From 0c9803cf78453a19ec37fbc2b3fdba3c106cfd84 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 29 Dec 2013 15:25:39 +0000 Subject: construct topoligicaly consitant (dependancy correct) interface map use dependancy map to generate javascript prototype for all interfaces in the binding. --- src/Makefile | 2 +- src/jsapi-libdom-const.c | 195 --------------------------- src/jsapi-libdom-init.c | 342 +++++++++++++++++++++++++++++++++++++++++++++++ src/jsapi-libdom.c | 240 +++++++++++++++++++++------------ src/jsapi-libdom.h | 26 ++-- src/nsgenbind-ast.c | 21 +++ src/nsgenbind-ast.h | 15 +++ 7 files changed, 553 insertions(+), 288 deletions(-) delete mode 100644 src/jsapi-libdom-const.c create mode 100644 src/jsapi-libdom-init.c diff --git a/src/Makefile b/src/Makefile index 972beb9..8bad59a 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 webidl-ast.c nsgenbind-ast.c jsapi-libdom.c jsapi-libdom-operator.c jsapi-libdom-property.c jsapi-libdom-const.c +DIR_SOURCES := nsgenbind.c webidl-ast.c nsgenbind-ast.c jsapi-libdom.c jsapi-libdom-operator.c jsapi-libdom-property.c jsapi-libdom-init.c SOURCES := $(SOURCES) $(BUILDDIR)/nsgenbind-parser.c $(BUILDDIR)/nsgenbind-lexer.c $(BUILDDIR)/webidl-parser.c $(BUILDDIR)/webidl-lexer.c diff --git a/src/jsapi-libdom-const.c b/src/jsapi-libdom-const.c deleted file mode 100644 index ac728c7..0000000 --- a/src/jsapi-libdom-const.c +++ /dev/null @@ -1,195 +0,0 @@ -/* const property generation - * - * This file is part of nsgenbind. - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - * Copyright 2012 Vincent Sanders - */ - -#include -#include -#include -#include -#include - -#include "options.h" -#include "nsgenbind-ast.h" -#include "webidl-ast.h" -#include "jsapi-libdom.h" - -static int output_cast_literal(struct binding *binding, - struct webidl_node *node) -{ - struct webidl_node *type_node = NULL; - struct webidl_node *literal_node = NULL; - struct webidl_node *type_base = NULL; - enum webidl_type webidl_arg_type; - - type_node = webidl_node_find_type(webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_TYPE); - - type_base = webidl_node_find_type(webidl_node_getnode(type_node), - NULL, - WEBIDL_NODE_TYPE_TYPE_BASE); - - webidl_arg_type = webidl_node_getint(type_base); - - switch (webidl_arg_type) { - - case WEBIDL_TYPE_BOOL: - /* JSBool */ - literal_node = webidl_node_find_type(webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_LITERAL_BOOL); - fprintf(binding->outfile, "BOOLEAN_TO_JSVAL(JS_FALSE)"); - break; - - case WEBIDL_TYPE_FLOAT: - case WEBIDL_TYPE_DOUBLE: - /* double */ - literal_node = webidl_node_find_type(webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_LITERAL_FLOAT); - fprintf(binding->outfile, "DOUBLE_TO_JSVAL(0.0)"); - break; - - case WEBIDL_TYPE_LONG: - /* int32_t */ - literal_node = webidl_node_find_type(webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_LITERAL_INT); - fprintf(binding->outfile, - "INT_TO_JSVAL(%d)", - webidl_node_getint(literal_node)); - break; - - case WEBIDL_TYPE_SHORT: - /* int16_t */ - literal_node = webidl_node_find_type(webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_LITERAL_INT); - fprintf(binding->outfile, - "INT_TO_JSVAL(%d)", - webidl_node_getint(literal_node)); - break; - - - case WEBIDL_TYPE_STRING: - case WEBIDL_TYPE_BYTE: - case WEBIDL_TYPE_OCTET: - case WEBIDL_TYPE_LONGLONG: - case WEBIDL_TYPE_SEQUENCE: - case WEBIDL_TYPE_OBJECT: - case WEBIDL_TYPE_DATE: - case WEBIDL_TYPE_VOID: - case WEBIDL_TYPE_USER: - default: - WARN(WARNING_UNIMPLEMENTED, "types not allowed as literal"); - break; /* @todo these types are not allowed here */ - } - - return 0; -} - -static int webidl_const_define_cb(struct webidl_node *node, void *ctx) -{ - struct binding *binding = ctx; - struct webidl_node *ident_node; - - ident_node = webidl_node_find_type(webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_IDENT); - if (ident_node == NULL) { - /* Broken AST - must have ident */ - return 1; - } - - fprintf(binding->outfile, - "\tJS_DefineProperty(cx,\n" - "\t\tprototype,\n" - "\t\t\"%s\",\n" - "\t\t", - webidl_node_gettext(ident_node)); - - output_cast_literal(binding, node); - - fprintf(binding->outfile, - ",\n" - "\t\tJS_PropertyStub,\n" - "\t\tJS_StrictPropertyStub,\n" - "\t\tJSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT);\n\n"); - - return 0; - -} - - -/* callback to emit implements property spec */ -static int webidl_const_spec_implements_cb(struct webidl_node *node, void *ctx) -{ - struct binding *binding = ctx; - - return output_const_defines(binding, webidl_node_gettext(node)); -} - -int -output_const_defines(struct binding *binding, const char *interface) -{ - struct webidl_node *interface_node; - struct webidl_node *members_node; - struct webidl_node *inherit_node; - int res = 0; - - /* find interface in webidl with correct ident attached */ - interface_node = webidl_node_find_type_ident(binding->wi_ast, - WEBIDL_NODE_TYPE_INTERFACE, - interface); - - if (interface_node == NULL) { - fprintf(stderr, - "Unable to find interface %s in loaded WebIDL\n", - interface); - return -1; - } - - /* generate property entries for each list (partial interfaces) */ - members_node = webidl_node_find_type(webidl_node_getnode(interface_node), - NULL, - WEBIDL_NODE_TYPE_LIST); - - while (members_node != NULL) { - fprintf(binding->outfile,"\t/**** %s ****/\n", interface); - - /* for each const emit a property define */ - webidl_node_for_each_type(webidl_node_getnode(members_node), - WEBIDL_NODE_TYPE_CONST, - webidl_const_define_cb, - binding); - - - members_node = webidl_node_find_type(webidl_node_getnode(interface_node), - members_node, - WEBIDL_NODE_TYPE_LIST); - } - - /* check for inherited nodes and insert them too */ - inherit_node = webidl_node_find(webidl_node_getnode(interface_node), - NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); - - if (inherit_node != NULL) { - res = output_const_defines(binding, - webidl_node_gettext(inherit_node)); - } - - if (res == 0) { - res = webidl_node_for_each_type(webidl_node_getnode(interface_node), - WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, - webidl_const_spec_implements_cb, - binding); - } - - return res; -} diff --git a/src/jsapi-libdom-init.c b/src/jsapi-libdom-init.c new file mode 100644 index 0000000..1f6b80d --- /dev/null +++ b/src/jsapi-libdom-init.c @@ -0,0 +1,342 @@ +/* const property generation + * + * This file is part of nsgenbind. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2012 Vincent Sanders + */ + +#include +#include +#include +#include +#include +#include + +#include "options.h" +#include "nsgenbind-ast.h" +#include "webidl-ast.h" +#include "jsapi-libdom.h" + +static int output_const_defines(struct binding *binding, const char *interface); + +static int output_cast_literal(struct binding *binding, + struct webidl_node *node) +{ + struct webidl_node *type_node = NULL; + struct webidl_node *literal_node = NULL; + struct webidl_node *type_base = NULL; + enum webidl_type webidl_arg_type; + + type_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_TYPE); + + type_base = webidl_node_find_type(webidl_node_getnode(type_node), + NULL, + WEBIDL_NODE_TYPE_TYPE_BASE); + + webidl_arg_type = webidl_node_getint(type_base); + + switch (webidl_arg_type) { + + case WEBIDL_TYPE_BOOL: + /* JSBool */ + literal_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_LITERAL_BOOL); + fprintf(binding->outfile, "BOOLEAN_TO_JSVAL(JS_FALSE)"); + break; + + case WEBIDL_TYPE_FLOAT: + case WEBIDL_TYPE_DOUBLE: + /* double */ + literal_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_LITERAL_FLOAT); + fprintf(binding->outfile, "DOUBLE_TO_JSVAL(0.0)"); + break; + + case WEBIDL_TYPE_LONG: + /* int32_t */ + literal_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_LITERAL_INT); + fprintf(binding->outfile, + "INT_TO_JSVAL(%d)", + webidl_node_getint(literal_node)); + break; + + case WEBIDL_TYPE_SHORT: + /* int16_t */ + literal_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_LITERAL_INT); + fprintf(binding->outfile, + "INT_TO_JSVAL(%d)", + webidl_node_getint(literal_node)); + break; + + + case WEBIDL_TYPE_STRING: + case WEBIDL_TYPE_BYTE: + case WEBIDL_TYPE_OCTET: + case WEBIDL_TYPE_LONGLONG: + case WEBIDL_TYPE_SEQUENCE: + case WEBIDL_TYPE_OBJECT: + case WEBIDL_TYPE_DATE: + case WEBIDL_TYPE_VOID: + case WEBIDL_TYPE_USER: + default: + WARN(WARNING_UNIMPLEMENTED, "types not allowed as literal"); + break; /* @todo these types are not allowed here */ + } + + return 0; +} + +static int webidl_const_define_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + struct webidl_node *ident_node; + + ident_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_IDENT); + if (ident_node == NULL) { + /* Broken AST - must have ident */ + return 1; + } + + fprintf(binding->outfile, + "\tJS_DefineProperty(cx, " + "prototype, " + "\"%s\", ", + webidl_node_gettext(ident_node)); + + output_cast_literal(binding, node); + + fprintf(binding->outfile, + ", " + "JS_PropertyStub, " + "JS_StrictPropertyStub, " + "JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT);\n\n"); + + return 0; + +} + + +/** output all the constant property defines for an interface */ +static int +output_interface_consts(struct binding *binding, + struct webidl_node *interface_node) +{ + struct webidl_node *members_node; + + /* generate property entries for each list (partial interfaces) */ + members_node = webidl_node_find_type( + webidl_node_getnode(interface_node), + NULL, + WEBIDL_NODE_TYPE_LIST); + + while (members_node != NULL) { + + /* for each const emit a property define */ + webidl_node_for_each_type(webidl_node_getnode(members_node), + WEBIDL_NODE_TYPE_CONST, + webidl_const_define_cb, + binding); + + + members_node = webidl_node_find_type( + webidl_node_getnode(interface_node), + members_node, + WEBIDL_NODE_TYPE_LIST); + } + + return 0; +} + +/* callback to emit implements property spec */ +static int webidl_const_spec_implements_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + + return output_const_defines(binding, webidl_node_gettext(node)); +} + +/** generate property definitions for constants */ +static int +output_const_defines(struct binding *binding, const char *interface) +{ + struct webidl_node *interface_node; + struct webidl_node *inherit_node; + int res = 0; + + /* find interface in webidl with correct ident attached */ + interface_node = webidl_node_find_type_ident(binding->wi_ast, + WEBIDL_NODE_TYPE_INTERFACE, + interface); + + if (interface_node == NULL) { + fprintf(stderr, + "Unable to find interface %s in loaded WebIDL\n", + interface); + return -1; + } + + fprintf(binding->outfile, "\t/**** %s ****/\n", interface); + + /* write the property defines for this interface */ + res = output_interface_consts(binding, interface_node); + + + /* check for inherited nodes and insert them too */ + inherit_node = webidl_node_find_type( + webidl_node_getnode(interface_node), + NULL, + WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); + + if (inherit_node != NULL) { + res = output_const_defines(binding, + webidl_node_gettext(inherit_node)); + } + + if (res == 0) { + res = webidl_node_for_each_type( + webidl_node_getnode(interface_node), + WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, + webidl_const_spec_implements_cb, + binding); + } + + return res; +} + +/** generate class initialisers + * + * Generates function to create the javascript class prototypes for + * each interface in the binding. + * + */ +int output_class_init(struct binding *binding) +{ + int res = 0; + struct genbind_node *api_node; + int inf; + + /* class Initialisor declaration */ + if (binding->hdrfile) { + + if (binding->interfacec > 1) { + fprintf(binding->hdrfile, + "\n#define %s_INTERFACE_COUNT %d", + binding->name, + binding->interfacec); + } + + fprintf(binding->hdrfile, + "\nint jsapi_InitClass_%s(JSContext *cx, JSObject *parent, JSObject **prototypes);\n\n", + binding->name); + + + } + + /* class Initialisor definition */ + fprintf(binding->outfile, + "int\n" + "jsapi_InitClass_%s(JSContext *cx, " + "JSObject *parent, " + "JSObject **prototypes)\n" + "{\n" + "\tJSObject *prototype;\n", + binding->name); + + /* check for the binding having an init override */ + api_node = genbind_node_find_type_ident(binding->gb_ast, + NULL, + GENBIND_NODE_TYPE_API, + "init"); + + if (api_node != NULL) { + output_code_block(binding, genbind_node_getnode(api_node)); + } else { + for (inf = 0; inf < binding->interfacec; inf++) { + + fprintf(binding->outfile, + "\n" + "\tprototype = JS_InitClass(cx, " + "parent, "); + + if (binding->interfaces[inf].inherit_idx == -1) { + /* interface does not get its + * prototypes from another interface + * we are generating + */ + fprintf(binding->outfile, + "NULL, " + "&JSClass_%s, " + "NULL, " + "0, " + "NULL, " + "NULL, " + "NULL, " + "NULL);\n", + binding->interfaces[inf].name); + + fprintf(binding->outfile, + "\tif (prototype == NULL) {\n" + "\t\treturn %d;\n" + "\t}\n\n", + inf); + + fprintf(binding->outfile, + "\tprototypes[%d] = prototype;\n", + inf); + + output_const_defines(binding, + binding->interfaces[inf].name); + + } else { + /* interface prototype is based on one + * we already generated (interface map + * is topologicaly sorted */ + assert(binding->interfaces[inf].inherit_idx < inf); + + fprintf(binding->outfile, + "prototypes[%d], " + "&JSClass_%s, " + "NULL, " + "0, " + "NULL, " + "NULL, " + "NULL, " + "NULL);\n", + binding->interfaces[inf].inherit_idx, + binding->interfaces[inf].name); + + fprintf(binding->outfile, + "\tif (prototype == NULL) {\n" + "\t\treturn %d;\n" + "\t}\n\n", + inf); + + fprintf(binding->outfile, + "\tprototypes[%d] = prototype;\n", + inf); + + output_interface_consts(binding, + binding->interfaces[inf].widl_node); + + } + } + fprintf(binding->outfile, + "\n\treturn %d;\n", + inf); + } + + fprintf(binding->outfile, "}\n\n"); + + return res; +} diff --git a/src/jsapi-libdom.c b/src/jsapi-libdom.c index f0dc5a3..de82678 100644 --- a/src/jsapi-libdom.c +++ b/src/jsapi-libdom.c @@ -531,62 +531,6 @@ output_code_block(struct binding *binding, struct genbind_node *codelist) } } -/** generate class initialiser which create the javascript class prototype */ -static int -output_class_init(struct binding *binding) -{ - int res = 0; - struct genbind_node *api_node; - - /* class Initialisor declaration */ - if (binding->hdrfile) { - binding->outfile = binding->hdrfile; - - fprintf(binding->outfile, - "JSObject *jsapi_InitClass_%s(JSContext *cx, JSObject *parent);\n", - binding->interface); - - binding->outfile = binding->srcfile; - } - - /* class Initialisor definition */ - fprintf(binding->outfile, - "JSObject *jsapi_InitClass_%s(JSContext *cx, JSObject *parent)\n" - "{\n" - "\tJSObject *prototype;\n", - binding->interface); - - api_node = genbind_node_find_type_ident(binding->gb_ast, - NULL, - GENBIND_NODE_TYPE_API, - "init"); - - if (api_node != NULL) { - output_code_block(binding, genbind_node_getnode(api_node)); - } else { - fprintf(binding->outfile, - "\n" - "\tprototype = JS_InitClass(cx,\n" - "\t\tparent,\n" - "\t\tNULL,\n" - "\t\t&JSClass_%s,\n" - "\t\tNULL,\n" - "\t\t0,\n" - "\t\tNULL,\n" - "\t\tNULL, \n" - "\t\tNULL, \n" - "\t\tNULL);\n", - binding->interface); - } - - output_const_defines(binding, binding->interface); - - fprintf(binding->outfile, - "\treturn prototype;\n" - "}\n\n"); - - return res; -} static int output_class_new(struct binding *binding) @@ -1061,47 +1005,158 @@ binding_has_private(struct genbind_node *binding_list) return false; } +/* build interface map and return the first interface */ +static struct genbind_node * +build_interface_map(struct genbind_node *binding_node, + struct webidl_node *webidl_ast, + int *interfacec_out, + struct binding_interface **interfaces_out) +{ + int interfacec; + int idx; + struct binding_interface *interfaces; + struct genbind_node *node = NULL; + + /* 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 NULL; + } + if (options->verbose) { + printf("Binding has %d interfaces\n", interfacec); + } + + interfaces = malloc(interfacec * sizeof(struct binding_interface)); + if (interfaces == NULL) { + return NULL; + } + + /* fill in map with node data */ + for (idx = 0; idx < interfacec; idx++ ) { + node = genbind_node_find_type( + genbind_node_getnode(binding_node), + node, + GENBIND_NODE_TYPE_BINDING_INTERFACE); + if (node == NULL) { + free(interfaces); + return NULL; + } + + 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 NULL; + } + + /* get web IDL node for interface */ + interfaces[idx].widl_node = webidl_node_find_type_ident( + webidl_ast, + WEBIDL_NODE_TYPE_INTERFACE, + interfaces[idx].name); + if (interfaces[idx].widl_node == NULL) { + free(interfaces); + return NULL; + } + + interfaces[idx].inherit_name = webidl_node_gettext( + webidl_node_find_type( + webidl_node_getnode(interfaces[idx].widl_node), + NULL, + WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE)); + + interfaces[idx].refcount = 0; + } + + /* find index of inherited node if it is one of those listed + * in the binding also maintain refcounts + */ + for (idx = 0; idx < interfacec; idx++ ) { + int inf; + interfaces[idx].inherit_idx = -1; + for (inf = 0; inf < interfacec; inf++ ) { + /* cannot inherit from self. and name must match */ + if ((inf != idx) && + (strcmp(interfaces[idx].inherit_name, + interfaces[inf].name) == 0)) { + interfaces[idx].inherit_idx = inf; + interfaces[inf].refcount++; + break; + } + } + } + + /** @todo There should be a 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 + */ + + /* show the interface map */ + if (options->verbose) { + for (idx = 0; idx < interfacec; idx++ ) { + printf("interface num:%d name:%s node:%p widl:%p inherit:%s inherit idx:%d refcount:%d\n", + idx, + interfaces[idx].name, + interfaces[idx].node, + interfaces[idx].widl_node, + interfaces[idx].inherit_name, + interfaces[idx].inherit_idx, + interfaces[idx].refcount); + } + } + + *interfacec_out = interfacec; + *interfaces_out = interfaces; + + return interfaces[0].node; +} + static struct binding * binding_new(struct options *options, struct genbind_node *genbind_ast, struct genbind_node *binding_node) { struct binding *nb; + + int interfacec; /* numer of interfaces in the interface map */ + struct binding_interface *interfaces; /* binding interface map */ + struct genbind_node *interface_node; struct genbind_node *binding_list; - struct genbind_node *binding_ident; char *hdrguard = NULL; struct webidl_node *webidl_ast = NULL; int res; - binding_list = genbind_node_getnode(binding_node); - if (binding_list == NULL) { + /* walk AST and load any web IDL files required */ + res = read_webidl(genbind_ast, &webidl_ast); + if (res != 0) { + fprintf(stderr, "Error: failed reading Web IDL\n"); return NULL; } - /* find the first interface node - there must be at least one */ - interface_node = genbind_node_find_type(binding_list, - NULL, - GENBIND_NODE_TYPE_BINDING_INTERFACE); + /* build the bindings interface (class) name map */ + interface_node = build_interface_map(binding_node, + webidl_ast, + &interfacec, + &interfaces); if (interface_node == NULL) { - return NULL; - } - - /* get the binding identifier */ - /* @todo it should be possible to specify this as part of the - * binding instead of just using the first interface - */ - binding_ident = genbind_node_find_type(genbind_node_getnode(interface_node), - NULL, - GENBIND_NODE_TYPE_IDENT); - if (binding_ident == NULL) { - return NULL; - } - - /* walk AST and load any web IDL files required */ - res = read_webidl(genbind_ast, &webidl_ast); - if (res != 0) { - fprintf(stderr, "Error reading Web IDL files\n"); + /* the binding must have at least one interface */ + fprintf(stderr, "Error: Binding must have a valid interface\n"); return NULL; } @@ -1121,18 +1176,35 @@ binding_new(struct options *options, } } + binding_list = genbind_node_getnode(binding_node); + if (binding_list == NULL) { + return NULL; + } + nb = calloc(1, sizeof(struct binding)); nb->gb_ast = genbind_ast; nb->wi_ast = webidl_ast; - /* @todo binding name should not be called interface */ - nb->interface = genbind_node_gettext(binding_ident); + + /* keep the binding list node */ + nb->binding_list = binding_list; + + /* store the interface mapping */ + nb->interfaces = interfaces; + nb->interfacec = interfacec; + + /* @todo it should be possible to specify the binding name + * instead of just using the name of the first interface. + * + * @todo get rid of the interface element out of the binding + * struct and use the interface map instead. + */ + nb->name = nb->interface = interfaces[0].name; nb->outfile = options->outfilehandle; nb->srcfile = options->outfilehandle; nb->hdrfile = options->hdrfilehandle; nb->hdrguard = hdrguard; nb->has_private = binding_has_private(binding_list); - nb->binding_list = binding_list; /* class API */ nb->addproperty = genbind_node_find_type_ident(genbind_ast, diff --git a/src/jsapi-libdom.h b/src/jsapi-libdom.h index b83eeb0..ee1b2f9 100644 --- a/src/jsapi-libdom.h +++ b/src/jsapi-libdom.h @@ -11,10 +11,23 @@ struct options; +struct binding_interface { + const char *name; /* name of interface */ + struct genbind_node *node; /* node of interface in binding */ + struct webidl_node *widl_node; /* node of interface in webidl */ + const char *inherit_name; /* name of interface this inherits from */ + int inherit_idx; /* index into binding map of inherited interface or -1 for not in map */ + int refcount; /* number of entries in map that refer to this interface */ +}; + struct binding { struct genbind_node *gb_ast; /* root node of binding AST */ struct webidl_node *wi_ast; /* root node of webidl AST */ + const char *name; /* Name of binding (first interface name by default) */ + int interfacec; /* numer of interfaces in the interface map */ + struct binding_interface *interfaces; /* binding interface map */ + const char *interface; /* webidl interface binding is for */ bool has_private; /* true if the binding requires a private structure */ @@ -33,7 +46,7 @@ struct binding { FILE *outfile ; /* file handle output should be written to, * allows reuse of callback routines to output - * to headers and source files + * to headers and source files */ FILE *srcfile ; /* output source file */ FILE *hdrfile ; /* output header file */ @@ -55,17 +68,16 @@ int output_function_spec(struct binding *binding); * * This walks the web IDL AST to find all operator interface members * and construct appropriate jsapi native function body to implement - * them. + * them. * * Function body contents can be overriden with an operator code * block in the binding definition. * - * @param binding The binding information + * @param binding The binding information * @param interface The interface to generate operator bodys for */ int output_operator_body(struct binding *binding, const char *interface); - /** generate property tinyid enum */ int output_property_tinyid(struct binding *binding); @@ -75,10 +87,8 @@ int output_property_spec(struct binding *binding); /** generate property function bodies */ int output_property_body(struct binding *binding); -/** generate property definitions for constants */ -int output_const_defines(struct binding *binding, const char *interface); - - +/** generate binding initialisation */ +int output_class_init(struct binding *binding); #endif diff --git a/src/nsgenbind-ast.c b/src/nsgenbind-ast.c index fc1e196..2f630b7 100644 --- a/src/nsgenbind-ast.c +++ b/src/nsgenbind-ast.c @@ -68,6 +68,8 @@ genbind_new_node(enum genbind_node_type type, struct genbind_node *l, void *r) return nn; } + +/* exported interface defined in nsgenbind-ast.h */ int genbind_node_foreach_type(struct genbind_node *node, enum genbind_node_type type, @@ -92,6 +94,25 @@ genbind_node_foreach_type(struct genbind_node *node, return 0; } +static int genbind_enumerate_node(struct genbind_node *node, void *ctx) +{ + node = node; + (*((int *)ctx))++; + return 0; +} + +/* exported interface defined in nsgenbind-ast.h */ +int +genbind_node_enumerate_type(struct genbind_node *node, + enum genbind_node_type type) +{ + int count = 0; + genbind_node_foreach_type(node, + type, + genbind_enumerate_node, + &count); + return count; +} /* exported interface defined in nsgenbind-ast.h */ struct genbind_node * diff --git a/src/nsgenbind-ast.h b/src/nsgenbind-ast.h index 128dce7..4911f5a 100644 --- a/src/nsgenbind-ast.h +++ b/src/nsgenbind-ast.h @@ -82,12 +82,27 @@ genbind_node_find(struct genbind_node *node, * search the full tree depth (initial search) or the result * of a previous search to continue. * @param nodetype The type of node to seach for + * @return The found node or NULL for no nodes. */ struct genbind_node * genbind_node_find_type(struct genbind_node *node, struct genbind_node *prev, enum genbind_node_type nodetype); +/** count how many nodes of a specified type. + * + * Enumerate how many nodes of the specified type there are by + * performing a depth first search for nodes of the given type and + * counting the number of results. + * + * @param node The node to start the search from + * @param nodetype The type of node to count + * @return The number of nodes found. + */ +int +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 * -- cgit v1.2.3