From 65e49e23019a97d51702077c82613c6c26e84033 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 31 Oct 2012 01:20:20 +0000 Subject: implement the "implements" webidl directive --- src/jsapi-libdom-operator.c | 163 +++++++++++++++++++++++---- src/jsapi-libdom-property.c | 97 ++++++++++------ src/jsapi-libdom.c | 265 ++++++++++++++++++++------------------------ src/jsapi-libdom.h | 5 + src/nsgenbind-ast.c | 18 +-- src/webidl-ast.c | 20 ++-- src/webidl-ast.h | 1 + src/webidl-parser.y | 55 ++++++--- 8 files changed, 378 insertions(+), 246 deletions(-) (limited to 'src') diff --git a/src/jsapi-libdom-operator.c b/src/jsapi-libdom-operator.c index 303c9da..4edf235 100644 --- a/src/jsapi-libdom-operator.c +++ b/src/jsapi-libdom-operator.c @@ -1,4 +1,4 @@ -/* operator body generation +/* function/operator generation * * This file is part of nsgenbind. * Licensed under the MIT License, @@ -17,6 +17,115 @@ #include "webidl-ast.h" #include "jsapi-libdom.h" +static int webidl_func_spec_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + struct webidl_node *ident_node; + + ident_node = webidl_node_find(webidl_node_getnode(node), + NULL, + webidl_cmp_node_type, + (void *)WEBIDL_NODE_TYPE_IDENT); + + if (ident_node == NULL) { + /* operation without identifier - must have special keyword + * http://www.w3.org/TR/WebIDL/#idl-operations + */ + } else { + fprintf(binding->outfile, + " JSAPI_FS(%s, 0, 0),\n", + webidl_node_gettext(ident_node)); + } + return 0; +} + + +static int generate_function_spec(struct binding *binding, const char *interface); + +/* callback to emit implements operator spec */ +static int webidl_function_spec_implements_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + + return generate_function_spec(binding, webidl_node_gettext(node)); +} + +static int +generate_function_spec(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; + } + + members_node = webidl_node_find(webidl_node_getnode(interface_node), + NULL, + webidl_cmp_node_type, + (void *)WEBIDL_NODE_TYPE_LIST); + while (members_node != NULL) { + + fprintf(binding->outfile," /**** %s ****/\n", interface); + + /* for each function emit a JSAPI_FS()*/ + webidl_node_for_each_type(webidl_node_getnode(members_node), + WEBIDL_NODE_TYPE_OPERATION, + webidl_func_spec_cb, + binding); + + members_node = webidl_node_find(webidl_node_getnode(interface_node), + members_node, + webidl_cmp_node_type, + (void *)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 = generate_function_spec(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_function_spec_implements_cb, + binding); + } + + return res; +} + +int output_function_spec(struct binding *binding) +{ + int res; + + fprintf(binding->outfile, + "static JSFunctionSpec jsclass_functions[] = {\n"); + + res = generate_function_spec(binding, binding->interface); + + fprintf(binding->outfile, " JSAPI_FS_END\n};\n\n"); + + return res; +} + + /** creates all the variable definitions * * generate functions variables (including return value) with default @@ -261,7 +370,7 @@ output_operation_input(struct binding *binding, case WEBIDL_TYPE_LONG: /* int32_t */ fprintf(binding->outfile, - "\tint32_t %s = 0;\n", + "\t%s = 0;\n", webidl_node_gettext(arg_ident)); break; @@ -332,24 +441,23 @@ static int webidl_operator_body_cb(struct webidl_node *node, void *ctx) fprintf(binding->outfile, "{\n"); - fprintf(binding->outfile, - "\tstruct jsclass_private *private;\n"); - fprintf(binding->outfile, "\tjsval *argv = JSAPI_ARGV(cx, vp);\n"); output_variable_definitions(binding, webidl_node_getnode(node)); - fprintf(binding->outfile, - "\n" - "\tprivate = JS_GetInstancePrivate(cx,\n" - "\t\t\tJSAPI_THIS_OBJECT(cx,vp),\n" - "\t\t\t&JSClass_%s,\n" - "\t\t\targv);\n" - "\tif (private == NULL)\n" - "\t\treturn JS_FALSE;\n\n", - binding->interface); - + if (binding->has_private) { + fprintf(binding->outfile, + "\tstruct jsclass_private *private;\n" + "\n" + "\tprivate = JS_GetInstancePrivate(cx,\n" + "\t\t\tJSAPI_THIS_OBJECT(cx,vp),\n" + "\t\t\t&JSClass_%s,\n" + "\t\t\targv);\n" + "\tif (private == NULL)\n" + "\t\treturn JS_FALSE;\n\n", + binding->interface); + } output_operation_input(binding, webidl_node_getnode(node)); @@ -378,7 +486,13 @@ static int webidl_operator_body_cb(struct webidl_node *node, void *ctx) return 0; } +/* callback to emit implements operator bodys */ +static int webidl_implements_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + return output_operator_body(binding, webidl_node_gettext(node)); +} /* exported interface documented in jsapi-libdom.h */ int @@ -387,6 +501,7 @@ output_operator_body(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, @@ -421,15 +536,21 @@ output_operator_body(struct binding *binding, const char *interface) } /* check for inherited nodes and insert them too */ - inherit_node = webidl_node_find(webidl_node_getnode(interface_node), + inherit_node = webidl_node_find_type(webidl_node_getnode(interface_node), NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); + WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); if (inherit_node != NULL) { - return output_operator_body(binding, - webidl_node_gettext(inherit_node)); + res = output_operator_body(binding, + webidl_node_gettext(inherit_node)); } - return 0; + if (res == 0) { + res = webidl_node_for_each_type(webidl_node_getnode(interface_node), + WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, + webidl_implements_cb, + binding); + } + + return res; } diff --git a/src/jsapi-libdom-property.c b/src/jsapi-libdom-property.c index c2c6c6a..6083bb9 100644 --- a/src/jsapi-libdom-property.c +++ b/src/jsapi-libdom-property.c @@ -52,13 +52,22 @@ static int webidl_property_spec_cb(struct webidl_node *node, void *ctx) return 0; } +static int generate_property_spec(struct binding *binding, const char *interface); +/* callback to emit implements property spec */ +static int webidl_property_spec_implements_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + + return generate_property_spec(binding, webidl_node_gettext(node)); +} + static int generate_property_spec(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, @@ -102,11 +111,18 @@ generate_property_spec(struct binding *binding, const char *interface) (void *)WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); if (inherit_node != NULL) { - return generate_property_spec(binding, + res = generate_property_spec(binding, webidl_node_gettext(inherit_node)); } - return 0; + if (res == 0) { + res = webidl_node_for_each_type(webidl_node_getnode(interface_node), + WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, + webidl_property_spec_implements_cb, + binding); + } + + return res; } int @@ -131,11 +147,9 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx) struct webidl_node *modifier_node; struct genbind_node *property_node; - ident_node = webidl_node_find(webidl_node_getnode(node), - NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_IDENT); - + ident_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_IDENT); if (ident_node == NULL) { /* properties must have an operator * http://www.w3.org/TR/WebIDL/#idl-attributes @@ -143,10 +157,9 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx) return 1; } - modifier_node = webidl_node_find(webidl_node_getnode(node), - NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_MODIFIER); + modifier_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_MODIFIER); if (webidl_node_getint(modifier_node) != WEBIDL_TYPE_READONLY) { @@ -170,17 +183,19 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx) /* return value */ fprintf(binding->outfile, "\tjsval jsretval = JSVAL_NULL;\n"); - /* get context */ - fprintf(binding->outfile, - "\tstruct jsclass_private *private;\n" - "\n" - "\tprivate = JS_GetInstancePrivate(cx,\n" - "\t\tobj,\n" - "\t\t&JSClass_%s,\n" - "\t\tNULL);\n" - "\tif (private == NULL)\n" - "\t\treturn JS_FALSE;\n\n", - binding->interface); + if (binding->has_private) { + /* get context */ + fprintf(binding->outfile, + "\tstruct jsclass_private *private;\n" + "\n" + "\tprivate = JS_GetInstancePrivate(cx,\n" + "\t\tobj,\n" + "\t\t&JSClass_%s,\n" + "\t\tNULL);\n" + "\tif (private == NULL)\n" + "\t\treturn JS_FALSE;\n\n", + binding->interface); + } property_node = genbind_node_find_type_ident(binding->gb_ast, NULL, @@ -232,6 +247,13 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx) return 0; } +/* callback to emit implements property bodys */ +static int webidl_implements_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + + return output_property_body(binding, webidl_node_gettext(node)); +} int output_property_body(struct binding *binding, const char *interface) @@ -239,7 +261,7 @@ output_property_body(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, @@ -253,11 +275,9 @@ output_property_body(struct binding *binding, const char *interface) return -1; } - members_node = webidl_node_find(webidl_node_getnode(interface_node), + members_node = webidl_node_find_type(webidl_node_getnode(interface_node), NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_LIST); - + WEBIDL_NODE_TYPE_LIST); while (members_node != NULL) { fprintf(binding->outfile,"/**** %s ****/\n", interface); @@ -269,22 +289,27 @@ output_property_body(struct binding *binding, const char *interface) binding); - members_node = webidl_node_find(webidl_node_getnode(interface_node), + members_node = webidl_node_find_type(webidl_node_getnode(interface_node), members_node, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_LIST); + WEBIDL_NODE_TYPE_LIST); } /* check for inherited nodes and insert them too */ - inherit_node = webidl_node_find(webidl_node_getnode(interface_node), + inherit_node = webidl_node_find_type(webidl_node_getnode(interface_node), NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); + WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); if (inherit_node != NULL) { - return output_property_body(binding, + res = output_property_body(binding, webidl_node_gettext(inherit_node)); } - return 0; + if (res == 0) { + res = webidl_node_for_each_type(webidl_node_getnode(interface_node), + WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, + webidl_implements_cb, + binding); + } + + return res; } diff --git a/src/jsapi-libdom.c b/src/jsapi-libdom.c index 36ed6b6..5a73f5e 100644 --- a/src/jsapi-libdom.c +++ b/src/jsapi-libdom.c @@ -17,7 +17,7 @@ #include "webidl-ast.h" #include "jsapi-libdom.h" -#define HDR_COMMENT_SEP "\n * " +#define HDR_COMMENT_SEP "\n * \n * " #define HDR_COMMENT_PREABLE "Generated by nsgenbind " @@ -80,85 +80,6 @@ static int webidl_hdrcomment_cb(struct genbind_node *node, void *ctx) return 0; } - - - -static int webidl_func_spec_cb(struct webidl_node *node, void *ctx) -{ - struct binding *binding = ctx; - struct webidl_node *ident_node; - - ident_node = webidl_node_find(webidl_node_getnode(node), - NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_IDENT); - - if (ident_node == NULL) { - /* operation without identifier - must have special keyword - * http://www.w3.org/TR/WebIDL/#idl-operations - */ - } else { - fprintf(binding->outfile, - " JSAPI_FS(%s, 0, 0),\n", - webidl_node_gettext(ident_node)); - } - return 0; -} - -static int -generate_function_spec(struct binding *binding, const char *interface) -{ - struct webidl_node *interface_node; - struct webidl_node *members_node; - struct webidl_node *inherit_node; - - /* 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; - } - - members_node = webidl_node_find(webidl_node_getnode(interface_node), - NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_LIST); - while (members_node != NULL) { - - fprintf(binding->outfile," /**** %s ****/\n", interface); - - /* for each function emit a JSAPI_FS()*/ - webidl_node_for_each_type(webidl_node_getnode(members_node), - WEBIDL_NODE_TYPE_OPERATION, - webidl_func_spec_cb, - binding); - - members_node = webidl_node_find(webidl_node_getnode(interface_node), - members_node, - webidl_cmp_node_type, - (void *)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) { - return generate_function_spec(binding, - webidl_node_gettext(inherit_node)); - } - - return 0; -} - - static int webidl_private_cb(struct genbind_node *node, void *ctx) { struct binding *binding = ctx; @@ -237,18 +158,20 @@ output_class_operations(struct binding *binding) { int res = 0; - /* finalize */ - fprintf(binding->outfile, - "static void jsclass_finalize(JSContext *cx, JSObject *obj)\n" - "{" - "\tstruct jsclass_private *private;\n" - "\n" - "\tprivate = JS_GetInstancePrivate(cx, obj, &JSClass_%s, NULL);\n" - "\tif (private != NULL) {\n" - "\t\tfree(private);\n" - "\t}\n" - "}\n\n", - binding->interface); + if (binding->has_private) { + /* finalizer only required if there is a private to free */ + fprintf(binding->outfile, + "static void jsclass_finalize(JSContext *cx, JSObject *obj)\n" + "{" + "\tstruct jsclass_private *private;\n" + "\n" + "\tprivate = JS_GetInstancePrivate(cx, obj, &JSClass_%s, NULL);\n" + "\tif (private != NULL) {\n" + "\t\tfree(private);\n" + "\t}\n" + "}\n\n", + binding->interface); + } /* resolve */ fprintf(binding->outfile, @@ -351,18 +274,22 @@ output_class_new(struct binding *binding) fprintf(binding->outfile, ")\n" "{\n" - "\tJSObject *newobject;\n" - "\tstruct jsclass_private *private;\n" - "\n" - "\tprivate = malloc(sizeof(struct jsclass_private));\n" - "\tif (private == NULL) {\n" - "\t\treturn NULL;\n" - "\t}\n"); + "\tJSObject *newobject;\n"); - genbind_node_for_each_type(genbind_node_getnode(binding_node), - GENBIND_NODE_TYPE_BINDING_PRIVATE, - webidl_private_assign_cb, - binding); + if (binding->has_private) { + fprintf(binding->outfile, + "\tstruct jsclass_private *private;\n" + "\n" + "\tprivate = malloc(sizeof(struct jsclass_private));\n" + "\tif (private == NULL) {\n" + "\t\treturn NULL;\n" + "\t}\n"); + + genbind_node_for_each_type(genbind_node_getnode(binding_node), + GENBIND_NODE_TYPE_BINDING_PRIVATE, + webidl_private_assign_cb, + binding); + } api_node = genbind_node_find_type_ident(binding->gb_ast, NULL, @@ -374,21 +301,25 @@ output_class_new(struct binding *binding) } else { fprintf(binding->outfile, "\n" - "\tnewobject = JS_NewObject(cx, &JSClass_%s, prototype, parent);\n" + "\tnewobject = JS_NewObject(cx, &JSClass_%s, prototype, parent);\n", + binding->interface); + } + + if (binding->has_private) { + fprintf(binding->outfile, "\tif (newobject == NULL) {\n" "\t\tfree(private);\n" "\t\treturn NULL;\n" - "\t}\n", - binding->interface); + "\t}\n" + "\n" + "\t/* attach private pointer */\n" + "\tif (JS_SetPrivate(cx, newobject, private) != JS_TRUE) {\n" + "\t\tfree(private);\n" + "\t\treturn NULL;\n" + "\t}\n"); } fprintf(binding->outfile, - "\n" - "\t/* attach private pointer */\n" - "\tif (JS_SetPrivate(cx, newobject, private) != JS_TRUE) {\n" - "\t\tfree(private);\n" - "\t\treturn NULL;\n" - "\t}\n" "\n" "\treturn newobject;\n" "}\n"); @@ -398,48 +329,62 @@ output_class_new(struct binding *binding) } -static int -output_function_spec(struct binding *binding) -{ - int res; - fprintf(binding->outfile, - "static JSFunctionSpec jsclass_functions[] = {\n"); - res = generate_function_spec(binding, binding->interface); - fprintf(binding->outfile, " JSAPI_FS_END\n};\n\n"); +static int +output_jsclass(struct binding *binding) +{ + if (binding->has_private) { - return res; -} + /* forward declare the resolver and finalizer */ + fprintf(binding->outfile, + "static void jsclass_finalize(JSContext *cx, JSObject *obj);\n"); + + fprintf(binding->outfile, + "static JSBool jsclass_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp);\n\n"); + /* output the class */ + fprintf(binding->outfile, + "JSClass JSClass_%1$s = {\n" + " \"%1$s\",\n" + " JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE,\n" + " JS_PropertyStub,\n" + " JS_PropertyStub,\n" + " JS_PropertyStub,\n" + " JS_StrictPropertyStub,\n" + " JS_EnumerateStub,\n" + " (JSResolveOp)jsclass_resolve,\n" + " JS_ConvertStub,\n" + " jsclass_finalize,\n" + " JSCLASS_NO_OPTIONAL_MEMBERS\n" + "};\n\n", + binding->interface); + } else { + /* forward declare the resolver */ + + fprintf(binding->outfile, + "static JSBool jsclass_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp);\n\n"); -static int -output_jsclass(struct binding *binding) -{ - /* forward declare the resolver and finalizer */ - fprintf(binding->outfile, - "static void jsclass_finalize(JSContext *cx, JSObject *obj);\n"); - fprintf(binding->outfile, - "static JSBool jsclass_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp);\n\n"); - /* output the class */ - fprintf(binding->outfile, - "JSClass JSClass_%1$s = {\n" - " \"%1$s\",\n" - " JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE,\n" - " JS_PropertyStub,\n" - " JS_PropertyStub,\n" - " JS_PropertyStub,\n" - " JS_StrictPropertyStub,\n" - " JS_EnumerateStub,\n" - " (JSResolveOp)jsclass_resolve,\n" - " JS_ConvertStub,\n" - " jsclass_finalize,\n" - " JSCLASS_NO_OPTIONAL_MEMBERS\n" - "};\n\n", - binding->interface); + /* output the class */ + fprintf(binding->outfile, + "JSClass JSClass_%1$s = {\n" + " \"%1$s\",\n" + " JSCLASS_NEW_RESOLVE,\n" + " JS_PropertyStub,\n" + " JS_PropertyStub,\n" + " JS_PropertyStub,\n" + " JS_StrictPropertyStub,\n" + " JS_EnumerateStub,\n" + " (JSResolveOp)jsclass_resolve,\n" + " JS_ConvertStub,\n" + " JS_FinalizeStub,\n" + " JSCLASS_NO_OPTIONAL_MEMBERS\n" + "};\n\n", + binding->interface); + } return 0; } @@ -449,6 +394,10 @@ output_private_declaration(struct binding *binding) struct genbind_node *binding_node; struct genbind_node *type_node; + if (!binding->has_private) { + return 0; + } + binding_node = genbind_node_find(binding->gb_ast, NULL, genbind_cmp_node_type, @@ -512,6 +461,28 @@ output_header_comments(struct binding *binding) return 0; } +static bool +binding_has_private(struct genbind_node *binding_node) +{ + struct genbind_node *node; + + node = genbind_node_find_type(genbind_node_getnode(binding_node), + NULL, + GENBIND_NODE_TYPE_BINDING_PRIVATE); + + if (node != NULL) { + return true; + } + + node = genbind_node_find_type(genbind_node_getnode(binding_node), + NULL, + GENBIND_NODE_TYPE_BINDING_INTERNAL); + if (node != NULL) { + return true; + } + return false; +} + static struct binding * binding_new(char *outfilename, struct genbind_node *genbind_ast) { @@ -571,7 +542,7 @@ binding_new(char *outfilename, struct genbind_node *genbind_ast) nb->name = genbind_node_gettext(ident_node); nb->interface = genbind_node_gettext(interface_node); nb->outfile = outfile; - + nb->has_private = binding_has_private(binding_node); return nb; } diff --git a/src/jsapi-libdom.h b/src/jsapi-libdom.h index f318b5d..a5db6ec 100644 --- a/src/jsapi-libdom.h +++ b/src/jsapi-libdom.h @@ -12,8 +12,12 @@ struct binding { struct genbind_node *gb_ast; struct webidl_node *wi_ast; + const char *name; /* name of the binding */ const char *interface; /* webidl interface binding is for */ + + bool has_private; /* true if the binding requires a private structure */ + FILE *outfile ; /* output file */ }; @@ -36,6 +40,7 @@ void output_code_block(struct binding *binding, struct genbind_node *codelist); * @param interface The interface to generate operator bodys for */ int output_operator_body(struct binding *binding, const char *interface); +int output_function_spec(struct binding *binding); int output_property_spec(struct binding *binding); int output_property_body(struct binding *binding, const char *interface); diff --git a/src/nsgenbind-ast.c b/src/nsgenbind-ast.c index e633439..c14f0df 100644 --- a/src/nsgenbind-ast.c +++ b/src/nsgenbind-ast.c @@ -100,7 +100,7 @@ genbind_node_find(struct genbind_node *node, { struct genbind_node *ret; - if (node == NULL) { + if ((node == NULL) || (node == prev)) { return NULL; } @@ -139,27 +139,21 @@ genbind_node_find_type_ident(struct genbind_node *node, struct genbind_node *found_node; struct genbind_node *ident_node; - found_node = genbind_node_find(node, - prev, - genbind_cmp_node_type, - (void *)type); + found_node = genbind_node_find_type(node, prev, type); + while (found_node != NULL) { - ident_node = genbind_node_find(genbind_node_getnode(found_node), + ident_node = genbind_node_find_type(genbind_node_getnode(found_node), NULL, - genbind_cmp_node_type, - (void *)GENBIND_NODE_TYPE_IDENT); + GENBIND_NODE_TYPE_IDENT); if (ident_node != NULL) { if (strcmp(ident_node->r.text, ident) == 0) break; } /* look for next matching node */ - found_node = genbind_node_find(node, - found_node, - genbind_cmp_node_type, - (void *)type); + found_node = genbind_node_find_type(node, found_node, type); } return found_node; diff --git a/src/webidl-ast.c b/src/webidl-ast.c index fef5f35..a1f2276 100644 --- a/src/webidl-ast.c +++ b/src/webidl-ast.c @@ -193,26 +193,19 @@ webidl_node_find_type_ident(struct webidl_node *root_node, struct webidl_node *node; struct webidl_node *ident_node; - node = webidl_node_find(root_node, - NULL, - webidl_cmp_node_type, - (void *)type); + node = webidl_node_find_type(root_node, NULL, type); while (node != NULL) { - ident_node = webidl_node_find(webidl_node_getnode(node), + ident_node = webidl_node_find_type(webidl_node_getnode(node), NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_IDENT); + WEBIDL_NODE_TYPE_IDENT); if (ident_node != NULL) { if (strcmp(ident_node->r.text, ident) == 0) break; } - node = webidl_node_find(root_node, - node, - webidl_cmp_node_type, - (void *)type); + node = webidl_node_find_type(root_node, node, type); } return node; @@ -224,7 +217,7 @@ char *webidl_node_gettext(struct webidl_node *node) switch(node->type) { case WEBIDL_NODE_TYPE_IDENT: case WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE: - + case WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS: return node->r.text; default: @@ -289,6 +282,9 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type) case WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE: return "Inherit"; + case WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS: + return "Implements"; + case WEBIDL_NODE_TYPE_INTERFACE: return "Interface"; diff --git a/src/webidl-ast.h b/src/webidl-ast.h index 2117cfa..d891dec 100644 --- a/src/webidl-ast.h +++ b/src/webidl-ast.h @@ -21,6 +21,7 @@ enum webidl_node_type { /* non structural node types */ WEBIDL_NODE_TYPE_INTERFACE, WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, + WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, WEBIDL_NODE_TYPE_ATTRIBUTE, WEBIDL_NODE_TYPE_OPERATION, WEBIDL_NODE_TYPE_CONST, diff --git a/src/webidl-parser.y b/src/webidl-parser.y index 3cf1b6c..53e21e1 100644 --- a/src/webidl-parser.y +++ b/src/webidl-parser.y @@ -167,22 +167,9 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %% - /* default rule to add built AST to passed in one */ -Input: - Definitions - { - *webidl_ast = webidl_node_prepend(*webidl_ast, $1); - } - | - error - { - fprintf(stderr, "%d: %s\n", yylloc.first_line, errtxt); - free(errtxt); - YYABORT ; - } - ; - - /* [1] altered from original grammar to be left recusive, */ + /* [1] default rule to add built AST to passed in one, altered from + * original grammar to be left recusive, + */ Definitions: /* empty */ { @@ -191,7 +178,14 @@ Definitions: | Definitions ExtendedAttributeList Definition { - $$ = webidl_node_prepend($1, $3); + $$ = *webidl_ast = webidl_node_prepend(*webidl_ast, $3); + } + | + error + { + fprintf(stderr, "%d: %s\n", yylloc.first_line, errtxt); + free(errtxt); + YYABORT ; } ; @@ -248,6 +242,7 @@ Interface: interface_node = webidl_node_find_type_ident(*webidl_ast, WEBIDL_NODE_TYPE_INTERFACE, $2); + if (interface_node == NULL) { /* no existing interface - create one with ident */ members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2); @@ -480,7 +475,31 @@ Typedef: ImplementsStatement: TOK_IDENTIFIER TOK_IMPLEMENTS TOK_IDENTIFIER ';' { - $$ = NULL; + /* extend interface with implements members */ + struct webidl_node *implements; + struct webidl_node *interface_node; + + + interface_node = webidl_node_find_type_ident(*webidl_ast, + WEBIDL_NODE_TYPE_INTERFACE, + $1); + + implements = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS, NULL, $3); + + if (interface_node == NULL) { + /* interface doesnt already exist so create it */ + + implements = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, implements, $1); + + $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, implements); + } else { + /* update the existing interface */ + + /* link implements node into interfaces_node */ + webidl_node_add(interface_node, implements); + + $$ = NULL; /* updating so no need to add a new node */ + } } ; -- cgit v1.2.3