From ed92dd097848f4628abfa3a8cc8be802a996272d Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 1 Jan 2014 11:44:45 +0000 Subject: make binding constructor multiple interface capable --- src/Makefile | 2 +- src/jsapi-libdom-init.c | 3 +- src/jsapi-libdom-new.c | 395 ++++++++++++++++++++++++++++++++++++++++++++++++ src/jsapi-libdom.c | 186 ----------------------- src/jsapi-libdom.h | 3 + 5 files changed, 401 insertions(+), 188 deletions(-) create mode 100644 src/jsapi-libdom-new.c diff --git a/src/Makefile b/src/Makefile index 8bad59a..8233398 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-init.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 jsapi-libdom-new.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-init.c b/src/jsapi-libdom-init.c index 1f6b80d..6dfc66f 100644 --- a/src/jsapi-libdom-init.c +++ b/src/jsapi-libdom-init.c @@ -1,4 +1,5 @@ -/* const property generation +/* Javascript spidemonkey API to libdom binding generation for class + * initilisation * * This file is part of nsgenbind. * Licensed under the MIT License, diff --git a/src/jsapi-libdom-new.c b/src/jsapi-libdom-new.c new file mode 100644 index 0000000..b78c715 --- /dev/null +++ b/src/jsapi-libdom-new.c @@ -0,0 +1,395 @@ +/* Spidemonkey Javascript API to libdom binding generation for class + * construction. + * + * This file is part of nsgenbind. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2013 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 webidl_private_param_cb(struct genbind_node *node, void *ctx) +{ + struct binding *binding = ctx; + struct genbind_node *ident_node; + struct genbind_node *type_node; + + + ident_node = genbind_node_find_type(genbind_node_getnode(node), + NULL, + GENBIND_NODE_TYPE_IDENT); + if (ident_node == NULL) + return -1; /* bad AST */ + + type_node = genbind_node_find_type(genbind_node_getnode(node), + NULL, + GENBIND_NODE_TYPE_STRING); + if (type_node == NULL) + return -1; /* bad AST */ + + fprintf(binding->outfile, + ",\n\t\t%s%s", + genbind_node_gettext(type_node), + genbind_node_gettext(ident_node)); + + return 0; +} + +static int webidl_private_assign_cb(struct genbind_node *node, void *ctx) +{ + struct binding *binding = ctx; + struct genbind_node *ident_node; + const char *ident; + + ident_node = genbind_node_find_type(genbind_node_getnode(node), + NULL, + GENBIND_NODE_TYPE_IDENT); + if (ident_node == NULL) + return -1; /* bad AST */ + + ident = genbind_node_gettext(ident_node); + + fprintf(binding->outfile, "\tprivate->%s = %s;\n", ident, ident); + + return 0; +} + + + +static int +output_binding_constructor(struct binding *binding) +{ + fprintf(binding->outfile, + "JSObject *jsapi_new_%s(JSContext *cx, \n", + binding->name); + + fprintf(binding->outfile, "\t\tJSObject *prototype, \n"); + + if (binding->interfacec != 1) { + fprintf(binding->outfile, "\t\tconst char *interface_name, \n"); + } + + fprintf(binding->outfile, "\t\tJSObject *parent"); + + genbind_node_foreach_type(binding->binding_list, + GENBIND_NODE_TYPE_BINDING_PRIVATE, + webidl_private_param_cb, + binding); + + fprintf(binding->outfile, ")"); + + return 0; +} + +static int +output_class_wprivate_multi(struct binding *binding) +{ + int inf; + + /* create and initialise private data */ + 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_foreach_type(binding->binding_list, + GENBIND_NODE_TYPE_BINDING_PRIVATE, + webidl_private_assign_cb, + binding); + + + fprintf(binding->outfile, "\n\n\t"); + + /* for each interface in the map generate initialisor */ + for (inf = 0; inf < binding->interfacec; inf++) { + + fprintf(binding->outfile, + "if (strcmp(interface_name, JSClass_%s.name) == 0) {\n", + binding->interfaces[inf].name); + + fprintf(binding->outfile, + "\n" + "\t\tnewobject = JS_NewObject(cx, &JSClass_%s, prototype, parent);\n", + binding->interface); + + + fprintf(binding->outfile, + "\t\tif (newobject == NULL) {\n" + "\t\t\tfree(private);\n" + "\t\t\treturn NULL;\n" + "\t\t}\n\n"); + + /* root object to stop it being garbage collected */ + fprintf(binding->outfile, + "\t\tif (JSAPI_ADD_OBJECT_ROOT(cx, &newobject) != JS_TRUE) {\n" + "\t\t\tfree(private);\n" + "\t\t\treturn NULL;\n" + "\t\t}\n\n"); + + fprintf(binding->outfile, + "\n" + "\t\t/* attach private pointer */\n" + "\t\tif (JS_SetPrivate(cx, newobject, private) != JS_TRUE) {\n" + "\t\t\tfree(private);\n" + "\t\t\treturn NULL;\n" + "\t\t}\n\n"); + + + /* attach operations and attributes (functions and properties) */ + fprintf(binding->outfile, + "\t\tif (JS_DefineFunctions(cx, newobject, jsclass_functions) != JS_TRUE) {\n" + "\t\t\tfree(private);\n" + "\t\t\treturn NULL;\n" + "\t\t}\n\n"); + + fprintf(binding->outfile, + "\t\tif (JS_DefineProperties(cx, newobject, jsclass_properties) != JS_TRUE) {\n" + "\t\t\tfree(private);\n" + "\t\t\treturn NULL;\n" + "\t\t}\n\n"); + + /* unroot object */ + fprintf(binding->outfile, + "\t\tJSAPI_REMOVE_OBJECT_ROOT(cx, &newobject);\n\n" + "\t} else "); + } + fprintf(binding->outfile, + "{\n" + "\t\tfree(private);\n" + "\t\treturn NULL;\n" + "\t}\n"); + + return 0; +} + +static int +output_class_wprivate(struct binding *binding, struct genbind_node *api_node) +{ + /* create and initialise private data */ + 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_foreach_type(binding->binding_list, + GENBIND_NODE_TYPE_BINDING_PRIVATE, + webidl_private_assign_cb, + binding); + + if (api_node != NULL) { + output_code_block(binding, genbind_node_getnode(api_node)); + } else { + fprintf(binding->outfile, + "\n" + "\tnewobject = JS_NewObject(cx, &JSClass_%s, prototype, parent);\n", + binding->interface); + } + + fprintf(binding->outfile, + "\tif (newobject == NULL) {\n" + "\t\tfree(private);\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + /* root object to stop it being garbage collected */ + fprintf(binding->outfile, + "\tif (JSAPI_ADD_OBJECT_ROOT(cx, &newobject) != JS_TRUE) {\n" + "\t\tfree(private);\n" + "\t\treturn NULL;\n" + "\t}\n\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"); + + + /* attach operations and attributes (functions and properties) */ + fprintf(binding->outfile, + "\tif (JS_DefineFunctions(cx, newobject, jsclass_functions) != JS_TRUE) {\n" + "\t\tfree(private);\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + fprintf(binding->outfile, + "\tif (JS_DefineProperties(cx, newobject, jsclass_properties) != JS_TRUE) {\n" + "\t\tfree(private);\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + /* unroot object */ + fprintf(binding->outfile, + "\tJSAPI_REMOVE_OBJECT_ROOT(cx, &newobject);\n\n"); + + return 0; +} + +static int +output_class_woprivate_multi(struct binding *binding) +{ + int inf; + + fprintf(binding->outfile, "\n\t"); + + /* for each interface in the map generate initialisor */ + for (inf = 0; inf < binding->interfacec; inf++) { + fprintf(binding->outfile, + "if (strcmp(interface_name, JSClass_%s.name) == 0) {\n", + binding->interfaces[inf].name); + + fprintf(binding->outfile, + "\t\tnewobject = JS_NewObject(cx, &JSClass_%s, prototype, parent);\n", + binding->interface); + + + fprintf(binding->outfile, + "\tif (newobject == NULL) {\n" + "\t\treturn NULL;\n" + "\t}\n"); + + /* root object to stop it being garbage collected */ + fprintf(binding->outfile, + "\tif (JSAPI_ADD_OBJECT_ROOT(cx, &newobject) != JS_TRUE) {\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + /* attach operations and attributes (functions and properties) */ + fprintf(binding->outfile, + "\tif (JS_DefineFunctions(cx, newobject, jsclass_functions) != JS_TRUE) {\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + fprintf(binding->outfile, + "\tif (JS_DefineProperties(cx, newobject, jsclass_properties) != JS_TRUE) {\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + /* unroot object */ + fprintf(binding->outfile, + "\tJSAPI_REMOVE_OBJECT_ROOT(cx, &newobject);\n\n"); + + } + fprintf(binding->outfile, + "{\n" + "\t\tfree(private);\n" + "\t\treturn NULL;\n" + "\t}\n"); + + + return 0; +} + +static int +output_class_woprivate(struct binding *binding, struct genbind_node *api_node) +{ + + if (api_node != NULL) { + output_code_block(binding, genbind_node_getnode(api_node)); + } else { + fprintf(binding->outfile, + "\n" + "\tnewobject = JS_NewObject(cx, &JSClass_%s, prototype, parent);\n", + binding->interface); + + } + + fprintf(binding->outfile, + "\tif (newobject == NULL) {\n" + "\t\treturn NULL;\n" + "\t}\n"); + + /* root object to stop it being garbage collected */ + fprintf(binding->outfile, + "\tif (JSAPI_ADD_OBJECT_ROOT(cx, &newobject) != JS_TRUE) {\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + /* attach operations and attributes (functions and properties) */ + fprintf(binding->outfile, + "\tif (JS_DefineFunctions(cx, newobject, jsclass_functions) != JS_TRUE) {\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + fprintf(binding->outfile, + "\tif (JS_DefineProperties(cx, newobject, jsclass_properties) != JS_TRUE) {\n" + "\t\treturn NULL;\n" + "\t}\n\n"); + + /* unroot object */ + fprintf(binding->outfile, + "\tJSAPI_REMOVE_OBJECT_ROOT(cx, &newobject);\n\n"); + + return 0; +} + +int +output_class_new(struct binding *binding) +{ + int res = 0; + struct genbind_node *api_node; + + /* constructor declaration */ + if (binding->hdrfile) { + binding->outfile = binding->hdrfile; + + output_binding_constructor(binding); + + fprintf(binding->outfile, ";\n"); + + binding->outfile = binding->srcfile; + } + + /* constructor definition */ + output_binding_constructor(binding); + + fprintf(binding->outfile, + "\n{\n" + "\tJSObject *newobject;\n"); + + api_node = genbind_node_find_type_ident(binding->gb_ast, + NULL, + GENBIND_NODE_TYPE_API, + "new"); + + /* generate correct constructor body */ + if (binding->has_private) { + if ((binding->interfacec == 1) || (api_node != NULL)) { + res = output_class_wprivate(binding, api_node); + } else { + res = output_class_wprivate_multi(binding); + } + } else { + if ((binding->interfacec == 1) || (api_node != NULL)) { + res = output_class_woprivate(binding, api_node); + } else { + res = output_class_woprivate_multi(binding); + } + } + + /* return newly created object */ + fprintf(binding->outfile, + "\treturn newobject;\n" + "}\n"); + + return res; +} diff --git a/src/jsapi-libdom.c b/src/jsapi-libdom.c index de82678..895ccf4 100644 --- a/src/jsapi-libdom.c +++ b/src/jsapi-libdom.c @@ -135,51 +135,7 @@ static int webidl_private_cb(struct genbind_node *node, void *ctx) return 0; } -static int webidl_private_param_cb(struct genbind_node *node, void *ctx) -{ - struct binding *binding = ctx; - struct genbind_node *ident_node; - struct genbind_node *type_node; - - - ident_node = genbind_node_find_type(genbind_node_getnode(node), - NULL, - GENBIND_NODE_TYPE_IDENT); - if (ident_node == NULL) - return -1; /* bad AST */ - - type_node = genbind_node_find_type(genbind_node_getnode(node), - NULL, - GENBIND_NODE_TYPE_STRING); - if (type_node == NULL) - return -1; /* bad AST */ - - fprintf(binding->outfile, - ",\n\t\t%s%s", - genbind_node_gettext(type_node), - genbind_node_gettext(ident_node)); - return 0; -} - -static int webidl_private_assign_cb(struct genbind_node *node, void *ctx) -{ - struct binding *binding = ctx; - struct genbind_node *ident_node; - const char *ident; - - ident_node = genbind_node_find_type(genbind_node_getnode(node), - NULL, - GENBIND_NODE_TYPE_IDENT); - if (ident_node == NULL) - return -1; /* bad AST */ - - ident = genbind_node_gettext(ident_node); - - fprintf(binding->outfile, "\tprivate->%s = %s;\n", ident, ident); - - return 0; -} /* section output generators */ @@ -532,148 +488,6 @@ output_code_block(struct binding *binding, struct genbind_node *codelist) } -static int -output_class_new(struct binding *binding) -{ - int res = 0; - struct genbind_node *api_node; - - /* constructor declaration */ - if (binding->hdrfile) { - binding->outfile = binding->hdrfile; - - fprintf(binding->outfile, - "JSObject *jsapi_new_%s(JSContext *cx,\n" - "\t\tJSObject *prototype,\n" - "\t\tJSObject *parent", - binding->interface); - - genbind_node_foreach_type(binding->binding_list, - GENBIND_NODE_TYPE_BINDING_PRIVATE, - webidl_private_param_cb, - binding); - - fprintf(binding->outfile, ");"); - - binding->outfile = binding->srcfile; - } - - /* constructor definition */ - fprintf(binding->outfile, - "JSObject *jsapi_new_%s(JSContext *cx,\n" - "\t\tJSObject *prototype,\n" - "\t\tJSObject *parent", - binding->interface); - - genbind_node_foreach_type(binding->binding_list, - GENBIND_NODE_TYPE_BINDING_PRIVATE, - webidl_private_param_cb, - binding); - - fprintf(binding->outfile, - ")\n" - "{\n" - "\tJSObject *newobject;\n"); - - /* create private data */ - 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_foreach_type(binding->binding_list, - GENBIND_NODE_TYPE_BINDING_PRIVATE, - webidl_private_assign_cb, - binding); - } - - api_node = genbind_node_find_type_ident(binding->gb_ast, - NULL, - GENBIND_NODE_TYPE_API, - "new"); - - if (api_node != NULL) { - output_code_block(binding, genbind_node_getnode(api_node)); - } else { - fprintf(binding->outfile, - "\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\n"); - - /* root object to stop it being garbage collected */ - fprintf(binding->outfile, - "\tif (JSAPI_ADD_OBJECT_ROOT(cx, &newobject) != JS_TRUE) {\n" - "\t\tfree(private);\n" - "\t\treturn NULL;\n" - "\t}\n\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"); - - - /* attach operations and attributes (functions and properties) */ - fprintf(binding->outfile, - "\tif (JS_DefineFunctions(cx, newobject, jsclass_functions) != JS_TRUE) {\n" - "\t\tfree(private);\n" - "\t\treturn NULL;\n" - "\t}\n\n"); - - fprintf(binding->outfile, - "\tif (JS_DefineProperties(cx, newobject, jsclass_properties) != JS_TRUE) {\n" - "\t\tfree(private);\n" - "\t\treturn NULL;\n" - "\t}\n\n"); - } else { - fprintf(binding->outfile, - "\tif (newobject == NULL) {\n" - "\t\treturn NULL;\n" - "\t}\n"); - - /* root object to stop it being garbage collected */ - fprintf(binding->outfile, - "\tif (JSAPI_ADD_OBJECT_ROOT(cx, &newobject) != JS_TRUE) {\n" - "\t\treturn NULL;\n" - "\t}\n\n"); - - /* attach operations and attributes (functions and properties) */ - fprintf(binding->outfile, - "\tif (JS_DefineFunctions(cx, newobject, jsclass_functions) != JS_TRUE) {\n" - "\t\treturn NULL;\n" - "\t}\n\n"); - - fprintf(binding->outfile, - "\tif (JS_DefineProperties(cx, newobject, jsclass_properties) != JS_TRUE) {\n" - "\t\treturn NULL;\n" - "\t}\n\n"); - } - - /* unroot object and return it */ - fprintf(binding->outfile, - "\tJSAPI_REMOVE_OBJECT_ROOT(cx, &newobject);\n" - "\n" - "\treturn newobject;\n" - "}\n"); - - - return res; -} static int output_forward_declarations(struct binding *binding) diff --git a/src/jsapi-libdom.h b/src/jsapi-libdom.h index ee1b2f9..bdf4bec 100644 --- a/src/jsapi-libdom.h +++ b/src/jsapi-libdom.h @@ -90,5 +90,8 @@ int output_property_body(struct binding *binding); /** generate binding initialisation */ int output_class_init(struct binding *binding); +/** generate binding class constructors */ +int output_class_new(struct binding *binding); + #endif -- cgit v1.2.3