summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/interface-map.c292
-rw-r--r--src/interface-map.h43
-rw-r--r--src/jsapi-libdom-infmap.c348
-rw-r--r--src/nsgenbind-ast.h2
-rw-r--r--src/nsgenbind.c13
6 files changed, 349 insertions, 351 deletions
diff --git a/src/Makefile b/src/Makefile
index 3e5b8af..b7b142a 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,7 @@
CFLAGS := $(CFLAGS) -I$(BUILDDIR) -Isrc/ -g -DYYENABLE_NLS=0
# Sources in this directory
-DIR_SOURCES := nsgenbind.c utils.c webidl-ast.c nsgenbind-ast.c
+DIR_SOURCES := nsgenbind.c utils.c webidl-ast.c nsgenbind-ast.c interface-map.c
# jsapi-libdom.c jsapi-libdom-function.c jsapi-libdom-property.c jsapi-libdom-init.c jsapi-libdom-new.c jsapi-libdom-infmap.c jsapi-libdom-jsclass.c
SOURCES := $(SOURCES) $(BUILDDIR)/nsgenbind-parser.c $(BUILDDIR)/nsgenbind-lexer.c $(BUILDDIR)/webidl-parser.c $(BUILDDIR)/webidl-lexer.c
diff --git a/src/interface-map.c b/src/interface-map.c
new file mode 100644
index 0000000..aef697e
--- /dev/null
+++ b/src/interface-map.c
@@ -0,0 +1,292 @@
+/* interface mapping
+ *
+ * This file is part of nsgenbind.
+ * Published under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "options.h"
+#include "utils.h"
+#include "nsgenbind-ast.h"
+#include "webidl-ast.h"
+#include "interface-map.h"
+
+/** count the number of nodes of a given type on an interface */
+static int
+enumerate_interface_type(struct webidl_node *interface_node,
+ enum webidl_node_type node_type)
+{
+ int count = 0;
+ struct webidl_node *members_node;
+
+ members_node = webidl_node_find_type(
+ webidl_node_getnode(interface_node),
+ NULL,
+ WEBIDL_NODE_TYPE_LIST);
+ while (members_node != NULL) {
+ count += webidl_node_enumerate_type(
+ webidl_node_getnode(members_node),
+ node_type);
+
+ members_node = webidl_node_find_type(
+ webidl_node_getnode(interface_node),
+ members_node,
+ WEBIDL_NODE_TYPE_LIST);
+ }
+
+ return count;
+}
+
+/* find index of inherited node if it is one of those listed in the
+ * binding also maintain refcounts
+ */
+static void
+compute_inherit_refcount(struct interface_map_entry *entries, int entryc)
+{
+ int idx;
+ int inf;
+
+ for (idx = 0; idx < entryc; idx++ ) {
+ entries[idx].inherit_idx = -1;
+ for (inf = 0; inf < entryc; inf++ ) {
+ /* cannot inherit from self and name must match */
+ if ((inf != idx) &&
+ (entries[idx].inherit_name != NULL ) &&
+ (strcmp(entries[idx].inherit_name,
+ entries[inf].name) == 0)) {
+ entries[idx].inherit_idx = inf;
+ entries[inf].refcount++;
+ break;
+ }
+ }
+ }
+}
+
+/** Topoligical sort based on the refcount
+ *
+ * do not need to consider loops as constructed graph is a acyclic
+ *
+ * alloc a second copy of the map
+ * repeat until all entries copied:
+ * walk source mapping until first entry with zero refcount
+ * put the entry at the end of the output map
+ * reduce refcount on inherit index if !=-1
+ * remove entry from source map
+ */
+static struct interface_map_entry *
+interface_topoligical_sort(struct interface_map_entry *srcinf, int infc)
+{
+ struct interface_map_entry *dstinf;
+ int idx;
+ int inf;
+
+ dstinf = calloc(infc, sizeof(struct interface_map_entry));
+ if (dstinf == NULL) {
+ return NULL;
+ }
+
+ for (idx = infc - 1; idx >= 0; idx--) {
+ /* walk source map until first valid entry with zero refcount */
+ inf = 0;
+ while ((inf < infc) &&
+ ((srcinf[inf].name == NULL) ||
+ (srcinf[inf].refcount > 0))) {
+ inf++;
+ }
+ if (inf == infc) {
+ free(dstinf);
+ return NULL;
+ }
+
+ /* copy entry to the end of the output map */
+ dstinf[idx].name = srcinf[inf].name;
+ dstinf[idx].node = srcinf[inf].node;
+ dstinf[idx].inherit_name = srcinf[inf].inherit_name;
+ dstinf[idx].operations = srcinf[inf].operations;
+ dstinf[idx].attributes = srcinf[inf].attributes;
+ dstinf[idx].class = srcinf[inf].class;
+
+ /* reduce refcount on inherit index if !=-1 */
+ if (srcinf[inf].inherit_idx != -1) {
+ srcinf[srcinf[inf].inherit_idx].refcount--;
+ }
+
+ /* remove entry from source map */
+ srcinf[inf].name = NULL;
+ }
+
+ return dstinf;
+}
+
+int interface_map_new(struct genbind_node *genbind,
+ struct webidl_node *webidl,
+ struct interface_map **index_out)
+{
+ int interfacec;
+ struct interface_map_entry *entries;
+ struct interface_map_entry *sorted_entries;
+ struct interface_map_entry *ecur;
+ struct webidl_node *node;
+ struct interface_map *index;
+
+ interfacec = webidl_node_enumerate_type(webidl,
+ WEBIDL_NODE_TYPE_INTERFACE);
+
+ if (options->verbose) {
+ printf("Indexing %d interfaces\n", interfacec);
+ }
+
+ entries = calloc(interfacec, sizeof(struct interface_map_entry));
+ if (entries == NULL) {
+ return -1;
+ }
+
+ /* for each interface populate an entry in the index */
+ ecur = entries;
+ node = webidl_node_find_type(webidl, NULL, WEBIDL_NODE_TYPE_INTERFACE);
+ while (node != NULL) {
+
+ /* fill index entry */
+ ecur->node = node;
+
+ /* name of interface */
+ ecur->name = webidl_node_gettext(
+ webidl_node_find_type(
+ webidl_node_getnode(node),
+ NULL,
+ GENBIND_NODE_TYPE_IDENT));
+
+ /* name of the inherited interface (if any) */
+ ecur->inherit_name = webidl_node_gettext(
+ webidl_node_find_type(
+ webidl_node_getnode(node),
+ NULL,
+ WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE));
+
+
+ /* enumerate the number of operations */
+ ecur->operations = enumerate_interface_type(node,
+ WEBIDL_NODE_TYPE_OPERATION);
+
+ /* enumerate the number of attributes */
+ ecur->attributes = enumerate_interface_type(node,
+ WEBIDL_NODE_TYPE_ATTRIBUTE);
+
+
+ /* matching class from binding */
+ ecur->class = genbind_node_find_type_ident(genbind,
+ NULL, GENBIND_NODE_TYPE_CLASS, ecur->name);
+
+ /* move to next interface */
+ node = webidl_node_find_type(webidl, node,
+ WEBIDL_NODE_TYPE_INTERFACE);
+ ecur++;
+ }
+
+ /* compute inheritance and refcounts on map */
+ compute_inherit_refcount(entries, interfacec);
+
+ /* sort interfaces to ensure correct ordering */
+ sorted_entries = interface_topoligical_sort(entries, interfacec);
+ free(entries);
+ if (sorted_entries == NULL) {
+ return -1;
+ }
+
+ /* compute inheritance and refcounts on sorted map */
+ compute_inherit_refcount(sorted_entries, interfacec);
+
+ index = malloc(sizeof(struct interface_map));
+ index->entryc = interfacec;
+ index->entries = sorted_entries;
+
+ *index_out = index;
+
+ return 0;
+}
+
+int interface_map_dump(struct interface_map *index)
+{
+ FILE *dumpf;
+ int eidx;
+ struct interface_map_entry *ecur;
+ const char *inherit_name;
+
+ /* only dump AST to file if required */
+ if (!options->debug) {
+ return 0;
+ }
+
+ dumpf = genb_fopen("interface-index", "w");
+ if (dumpf == NULL) {
+ return 2;
+ }
+
+ ecur = index->entries;
+ for (eidx = 0; eidx < index->entryc; eidx++) {
+ inherit_name = ecur->inherit_name;
+ if (inherit_name == NULL) {
+ inherit_name = "";
+ }
+ fprintf(dumpf, "%d %s %s i:%d a:%d %p\n", eidx, ecur->name,
+ inherit_name, ecur->operations, ecur->attributes,
+ ecur->class);
+ ecur++;
+ }
+
+ fclose(dumpf);
+
+ return 0;
+}
+
+int interface_map_dumpdot(struct interface_map *index)
+{
+ FILE *dumpf;
+ int eidx;
+ struct interface_map_entry *ecur;
+
+ /* only dump AST to file if required */
+ if (!options->debug) {
+ return 0;
+ }
+
+ dumpf = genb_fopen("interface.dot", "w");
+ if (dumpf == NULL) {
+ return 2;
+ }
+
+ fprintf(dumpf, "digraph interfaces {\n");
+
+ ecur = index->entries;
+ for (eidx = 0; eidx < index->entryc; eidx++) {
+ if (ecur->class != NULL) {
+ /* interfaces bound to a class are shown in blue */
+ fprintf(dumpf, "%04d [label=\"%s\" fontcolor=\"blue\"];\n", eidx, ecur->name);
+ } else {
+ fprintf(dumpf, "%04d [label=\"%s\"];\n", eidx, ecur->name);
+ }
+ ecur++;
+ }
+
+ ecur = index->entries;
+ for (eidx = 0; eidx < index->entryc; eidx++) {
+ if (index->entries[eidx].inherit_idx != -1) {
+ fprintf(dumpf, "%04d -> %04d;\n",
+ eidx, index->entries[eidx].inherit_idx);
+ }
+ }
+
+ fprintf(dumpf, "}\n");
+
+ fclose(dumpf);
+
+ return 0;
+}
diff --git a/src/interface-map.h b/src/interface-map.h
new file mode 100644
index 0000000..c9dd654
--- /dev/null
+++ b/src/interface-map.h
@@ -0,0 +1,43 @@
+/* Interface mapping
+ *
+ * This file is part of nsgenbind.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ */
+
+#ifndef nsgenbind_interface_map_h
+#define nsgenbind_interface_map_h
+
+struct genbind_node;
+struct webidl_node;
+
+struct interface_map_entry {
+ const char *name; /** interface name */
+ struct webidl_node *node; /**< AST interface node */
+ const char *inherit_name; /**< Name of interface inhertited from */
+ int operations; /**< number of operations on interface */
+ int attributes; /**< number of attributes on interface */
+ int inherit_idx; /**< index into map of inherited interface or -1 for
+ * not in map
+ */
+ int refcount; /**< number of interfacess in map that refer to this
+ * interface
+ */
+ struct genbind_node *class; /**< class from binding (if any) */
+};
+
+struct interface_map {
+ int entryc; /**< count of interfaces */
+ struct interface_map_entry *entries;
+};
+
+int interface_map_new(struct genbind_node *genbind,
+ struct webidl_node *webidl,
+ struct interface_map **index_out);
+
+int interface_map_dump(struct interface_map *index);
+
+int interface_map_dumpdot(struct interface_map *index);
+
+#endif
diff --git a/src/jsapi-libdom-infmap.c b/src/jsapi-libdom-infmap.c
deleted file mode 100644
index 09fce1e..0000000
--- a/src/jsapi-libdom-infmap.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* interface map builder
- *
- * This file is part of nsgenbind.
- * Published under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
- * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
- */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#include "options.h"
-#include "nsgenbind-ast.h"
-#include "webidl-ast.h"
-#include "jsapi-libdom.h"
-
-/** count the number of methods or properties for an interface */
-static int
-enumerate_interface_own(struct webidl_node *interface_node,
- enum webidl_node_type node_type)
-{
- int count = 0;
- struct webidl_node *members_node;
-
- members_node = webidl_node_find_type(
- webidl_node_getnode(interface_node),
- NULL,
- WEBIDL_NODE_TYPE_LIST);
- while (members_node != NULL) {
- count += webidl_node_enumerate_type(
- webidl_node_getnode(members_node),
- node_type);
-
- members_node = webidl_node_find_type(
- webidl_node_getnode(interface_node),
- members_node,
- WEBIDL_NODE_TYPE_LIST);
- }
-
- return count;
-}
-
-static int
-fill_binding_interface(struct webidl_node *webidl_ast,
- struct binding_interface *interface)
-{
- /* get web IDL node for interface */
- interface->widl_node = webidl_node_find_type_ident(
- webidl_ast,
- WEBIDL_NODE_TYPE_INTERFACE,
- interface->name);
- if (interface->widl_node == NULL) {
- return -1;
- }
-
- /* enumerate the number of functions */
- interface->own_functions = enumerate_interface_own(
- interface->widl_node,
- WEBIDL_NODE_TYPE_OPERATION);
-
- /* enumerate the number of properties */
- interface->own_properties = enumerate_interface_own(
- interface->widl_node,
- WEBIDL_NODE_TYPE_ATTRIBUTE);
-
- /* extract the name of the inherited interface (if any) */
- interface->inherit_name = webidl_node_gettext(
- webidl_node_find_type(
- webidl_node_getnode(interface->widl_node),
- NULL,
- WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE));
-
- return 0;
-}
-
-/* find index of inherited node if it is one of those listed in the
- * binding also maintain refcounts
- */
-static void
-compute_inherit_refcount(struct binding_interface *interfaces,
- int interfacec)
-{
- int idx;
- int inf;
-
- for (idx = 0; idx < interfacec; idx++ ) {
- interfaces[idx].inherit_idx = -1;
- for (inf = 0; inf < interfacec; inf++ ) {
- /* cannot inherit from self and name must match */
- if ((inf != idx) &&
- (interfaces[idx].inherit_name != NULL ) &&
- (strcmp(interfaces[idx].inherit_name,
- interfaces[inf].name) == 0)) {
- interfaces[idx].inherit_idx = inf;
- interfaces[inf].refcount++;
- break;
- }
- }
- }
-}
-
-/** Topoligical sort based on the refcount
- *
- * do not need to consider loops as constructed graph is a acyclic
- *
- * alloc a second copy of the map
- * repeat until all entries copied:
- * walk source mapping until first entry with zero refcount
- * put the entry at the end of the output map
- * reduce refcount on inherit index if !=-1
- * remove entry from source map
- */
-static struct binding_interface *
-interface_topoligical_sort(struct binding_interface *srcinf, int infc)
-{
- struct binding_interface *dstinf;
- int idx;
- int inf;
-
- dstinf = calloc(infc, sizeof(struct binding_interface));
- if (dstinf == NULL) {
- return NULL;
- }
-
- for (idx = infc - 1; idx >= 0; idx--) {
- /* walk source map until first valid entry with zero refcount */
- inf = 0;
- while ((inf < infc) &&
- ((srcinf[inf].name == NULL) ||
- (srcinf[inf].refcount > 0))) {
- inf++;
- }
- if (inf == infc) {
- free(dstinf);
- return NULL;
- }
-
- /* copy entry to the end of the output map */
- dstinf[idx].name = srcinf[inf].name;
- dstinf[idx].node = srcinf[inf].node;
- dstinf[idx].widl_node = srcinf[inf].widl_node;
- dstinf[idx].inherit_name = srcinf[inf].inherit_name;
- dstinf[idx].own_properties = srcinf[inf].own_properties;
- dstinf[idx].own_functions = srcinf[inf].own_functions;
-
- /* reduce refcount on inherit index if !=-1 */
- if (srcinf[inf].inherit_idx != -1) {
- srcinf[srcinf[inf].inherit_idx].refcount--;
- }
-
- /* remove entry from source map */
- srcinf[inf].name = NULL;
- }
-
- return dstinf;
-}
-
-/* exported interface documented in jsapi-libdom.h */
-int build_interface_map(struct genbind_node *binding_node,
- struct webidl_node *webidl_ast,
- int *interfacec_out,
- struct binding_interface **interfaces_out)
-{
- int interfacec;
- int inf; /* interface loop counter */
- int idx; /* map index counter */
- struct binding_interface *interfaces;
- struct genbind_node *node = NULL;
- struct binding_interface *reinterfaces;
-
- /* count number of interfaces listed in binding */
- interfacec = genbind_node_enumerate_type(
- genbind_node_getnode(binding_node),
- GENBIND_NODE_TYPE_BINDING_INTERFACE);
-
- if (interfacec == 0) {
- return -1;
- }
- if (options->verbose) {
- printf("Binding has %d interfaces\n", interfacec);
- }
-
- interfaces = calloc(interfacec, sizeof(struct binding_interface));
- if (interfaces == NULL) {
- return -1;
- }
-
- /* fill in map with binding node data */
- idx = 0;
- node = genbind_node_find_type(genbind_node_getnode(binding_node),
- node,
- GENBIND_NODE_TYPE_BINDING_INTERFACE);
- while (node != NULL) {
-
- /* binding node */
- interfaces[idx].node = node;
-
- /* get interface name */
- interfaces[idx].name = genbind_node_gettext(
- genbind_node_find_type(genbind_node_getnode(node),
- NULL,
- GENBIND_NODE_TYPE_IDENT));
- if (interfaces[idx].name == NULL) {
- free(interfaces);
- return -1;
- }
-
- /* get interface info from webidl */
- if (fill_binding_interface(webidl_ast, interfaces + idx) == -1) {
- free(interfaces);
- return -1;
- }
-
- interfaces[idx].refcount = 0;
-
- /* ensure it is not a duplicate */
- for (inf = 0; inf < idx; inf++) {
- if (strcmp(interfaces[inf].name, interfaces[idx].name) == 0) {
- break;
- }
- }
- if (inf != idx) {
- WARN(WARNING_DUPLICATED,
- "interface %s duplicated in binding",
- interfaces[idx].name);
- } else {
- idx++;
- }
-
- /* next node */
- node = genbind_node_find_type(
- genbind_node_getnode(binding_node),
- node,
- GENBIND_NODE_TYPE_BINDING_INTERFACE);
- }
-
- /* update count which may have changed if there were duplicates */
- interfacec = idx;
-
- /* compute inheritance and refcounts on map */
- compute_inherit_refcount(interfaces, interfacec);
-
- /* the map must be augmented with all the interfaces not in
- * the binding but in the dependancy chain
- */
- for (idx = 0; idx < interfacec; idx++ ) {
- if ((interfaces[idx].inherit_idx == -1) &&
- (interfaces[idx].inherit_name != NULL)) {
- /* interface inherits but not currently in map */
-
- /* grow map */
- reinterfaces = realloc(interfaces,
- (interfacec + 1) * sizeof(struct binding_interface));
- if (reinterfaces == NULL) {
- fprintf(stderr,"Unable to grow interface map\n");
- free(interfaces);
- return -1;
- }
- interfaces = reinterfaces;
-
- /* setup all fields in new interface */
-
- /* this interface is not in the binding and
- * will not be exported
- */
- interfaces[interfacec].node = NULL;
-
- interfaces[interfacec].name = interfaces[idx].inherit_name;
-
- if (fill_binding_interface(webidl_ast,
- interfaces + interfacec) == -1) {
- fprintf(stderr,
- "Interface %s inherits from %s which is not in the WebIDL\n",
- interfaces[idx].name,
- interfaces[idx].inherit_name);
- free(interfaces);
- return -1;
- }
-
- interfaces[interfacec].inherit_idx = -1;
- interfaces[interfacec].refcount = 0;
-
- /* update dependancy info and refcount */
- for (inf = 0; inf < interfacec; inf++) {
- if (strcmp(interfaces[inf].inherit_name,
- interfaces[interfacec].name) == 0) {
- interfaces[inf].inherit_idx = interfacec;
- interfaces[interfacec].refcount++;
- }
- }
-
- /* update interface count in map */
- interfacec++;
-
- }
- }
-
- /* sort interfaces to ensure correct ordering */
- reinterfaces = interface_topoligical_sort(interfaces, interfacec);
- free(interfaces);
- if (reinterfaces == NULL) {
- return -1;
- }
- interfaces = reinterfaces;
-
- /* compute inheritance and refcounts on sorted map */
- compute_inherit_refcount(interfaces, interfacec);
-
- /* setup output index values */
- inf = 0;
- for (idx = 0; idx < interfacec; idx++ ) {
- if (interfaces[idx].node == NULL) {
- interfaces[idx].output_idx = -1;
- } else {
- interfaces[idx].output_idx = inf;
- inf++;
- }
- }
-
- /* show the interface map */
- if (options->verbose) {
- for (idx = 0; idx < interfacec; idx++ ) {
- printf("interface num:%d\n"
- " name:%s node:%p widl:%p\n"
- " inherit:%s inherit idx:%d refcount:%d\n"
- " own functions:%d own properties:%d output idx:%d\n",
- idx,
- interfaces[idx].name,
- interfaces[idx].node,
- interfaces[idx].widl_node,
- interfaces[idx].inherit_name,
- interfaces[idx].inherit_idx,
- interfaces[idx].refcount,
- interfaces[idx].own_functions,
- interfaces[idx].own_properties,
- interfaces[idx].output_idx);
- }
- }
-
- *interfacec_out = interfacec;
- *interfaces_out = interfaces;
-
- return 0;
-}
diff --git a/src/nsgenbind-ast.h b/src/nsgenbind-ast.h
index e7215b1..9c564b9 100644
--- a/src/nsgenbind-ast.h
+++ b/src/nsgenbind-ast.h
@@ -130,7 +130,7 @@ genbind_node_enumerate_type(struct genbind_node *node,
enum genbind_node_type type);
/** Depth first left hand search returning nodes of the specified type
- * and a ident child node with matching text
+ * with an ident child node with matching text
*
* @param node The node to start the search from
* @param prev The node at which to stop the search, either NULL to
diff --git a/src/nsgenbind.c b/src/nsgenbind.c
index 914f58e..18db196 100644
--- a/src/nsgenbind.c
+++ b/src/nsgenbind.c
@@ -14,10 +14,11 @@
#include <getopt.h>
#include <errno.h>
+#include "options.h"
#include "nsgenbind-ast.h"
#include "webidl-ast.h"
#include "jsapi-libdom.h"
-#include "options.h"
+#include "interface-map.h"
struct options *options;
@@ -194,6 +195,7 @@ int main(int argc, char **argv)
int res;
struct genbind_node *genbind_root = NULL;
struct webidl_node *webidl_root = NULL;
+ struct interface_map *interface_map = NULL;
enum bindingtype_e bindingtype;
options = process_cmdline(argc, argv);
@@ -226,6 +228,15 @@ int main(int argc, char **argv)
/* debug dump of web idl AST */
webidl_dump_ast(webidl_root);
+ /* generate index of interfaces in idl sorted by inheritance */
+ res = interface_map_new(genbind_root, webidl_root, &interface_map);
+ if (res != 0) {
+ return 5;
+ }
+
+ /* dump the interface mapping */
+ interface_map_dump(interface_map);
+ interface_map_dumpdot(interface_map);
#if 0
/* generate output for each binding */