diff options
author | Vincent Sanders <vince@kyllikki.org> | 2015-08-21 12:53:52 +0200 |
---|---|---|
committer | Vincent Sanders <vince@kyllikki.org> | 2015-08-21 12:53:52 +0200 |
commit | b0f64cff2c94d1a208528e2ed91c15ab037dbbb1 (patch) | |
tree | 85160c531ec6dd0a51c1aaa276e668cbac64298b /src/duk-libdom.c | |
parent | 56eee21ccb63cb7f040c5ce07bc226fbd229330d (diff) | |
download | nsgenbind-b0f64cff2c94d1a208528e2ed91c15ab037dbbb1.tar.gz nsgenbind-b0f64cff2c94d1a208528e2ed91c15ab037dbbb1.tar.bz2 |
split up duk-libdom generation source as it had grown unweildy
Diffstat (limited to 'src/duk-libdom.c')
-rw-r--r-- | src/duk-libdom.c | 1411 |
1 files changed, 1 insertions, 1410 deletions
diff --git a/src/duk-libdom.c b/src/duk-libdom.c index 3e20d13..45e7e79 100644 --- a/src/duk-libdom.c +++ b/src/duk-libdom.c @@ -3,7 +3,7 @@ * 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> + * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org> */ #include <stdio.h> @@ -27,53 +27,6 @@ #define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_" -#define NSGENBIND_PREAMBLE \ - "/* Generated by nsgenbind\n" \ - " *\n" \ - " * nsgenbind is published under the MIT Licence.\n" \ - " * nsgenbind is similar to a compiler is a purely transformative tool which\n" \ - " * explicitly makes no copyright claim on this generated output\n" \ - " */" - -/** - * Output code to create a private structure - * - */ -static int output_create_private(FILE* outf, char *class_name) -{ - fprintf(outf, "\t/* create private data and attach to instance */\n"); - fprintf(outf, "\t%s_private_t *priv = calloc(1, sizeof(*priv));\n", - class_name); - fprintf(outf, "\tif (priv == NULL) return 0;\n"); - fprintf(outf, "\tduk_push_pointer(ctx, priv);\n"); - fprintf(outf, - "\tduk_put_prop_string(ctx, 0, %s_magic_string_private);\n\n", - DLPFX); - - return 0; -} - -/** - * generate code that gets a private pointer - */ -static int output_safe_get_private(FILE* outf, char *class_name, int idx) -{ - fprintf(outf, - "\t%s_private_t *priv;\n", class_name); - fprintf(outf, - "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n", - idx, DLPFX); - fprintf(outf, - "\tpriv = duk_get_pointer(ctx, -1);\n"); - fprintf(outf, - "\tduk_pop(ctx);\n"); - fprintf(outf, - "\tif (priv == NULL) return 0;\n\n"); - - return 0; -} - - /** * generate a duktape prototype name */ @@ -95,190 +48,6 @@ static char *get_prototype_name(const char *interface_name) return proto_name; } -/** - * generate code that gets a prototype by name - */ -static int output_get_prototype(FILE* outf, const char *interface_name) -{ - char *proto_name; - - proto_name = get_prototype_name(interface_name); - - fprintf(outf, - "\t/* get prototype */\n"); - fprintf(outf, - "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n", - DLPFX); - fprintf(outf, - "\tduk_get_prop_string(ctx, -1, \"%s\");\n", - proto_name); - fprintf(outf, - "\tduk_replace(ctx, -2);\n"); - - free(proto_name); - - return 0; -} - -/** - * generate code that sets a destructor in a prototype - */ -static int output_set_destructor(FILE* outf, char *class_name, int idx) -{ - fprintf(outf, "\t/* Set the destructor */\n"); - fprintf(outf, "\tduk_dup(ctx, %d);\n", idx); - fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___destructor, 1);\n", - DLPFX, class_name); - fprintf(outf, "\tduk_set_finalizer(ctx, -2);\n"); - fprintf(outf, "\tduk_pop(ctx);\n\n"); - - return 0; -} - -/** - * generate code that sets a constructor in a prototype - */ -static int -output_set_constructor(FILE* outf, char *class_name, int idx, int argc) -{ - fprintf(outf, "\t/* Set the constructor */\n"); - fprintf(outf, "\tduk_dup(ctx, %d);\n", idx); - fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___constructor, %d);\n", - DLPFX, class_name, 1 + argc); - fprintf(outf, "\tduk_put_prop_string(ctx, -2, \"%sINIT\");\n", - MAGICPFX); - fprintf(outf, "\tduk_pop(ctx);\n\n"); - - return 0; -} - -static int -output_dump_stack(FILE* outf) -{ - if (options->dbglog) { - /* dump stack */ - fprintf(outf, "\tduk_push_context_dump(ctx);\n"); - fprintf(outf, "\tLOG(\"Stack: %%s\", duk_to_string(ctx, -1));\n"); - fprintf(outf, "\tduk_pop(ctx);\n"); - } - return 0; -} - -/** - * generate code that adds a method in a prototype - */ -static int -output_add_method(FILE* outf, - const char *class_name, - const char *method) -{ - fprintf(outf, "\t/* Add a method */\n"); - fprintf(outf, "\tduk_dup(ctx, 0);\n"); - fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n", method); - fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s, DUK_VARARGS);\n", - DLPFX, class_name, method); - output_dump_stack(outf); - fprintf(outf, "\tduk_def_prop(ctx, -3,\n"); - fprintf(outf, "\t DUK_DEFPROP_HAVE_VALUE |\n"); - fprintf(outf, "\t DUK_DEFPROP_HAVE_WRITABLE |\n"); - fprintf(outf, "\t DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE |\n"); - fprintf(outf, "\t DUK_DEFPROP_HAVE_CONFIGURABLE);\n"); - fprintf(outf, "\tduk_pop(ctx);\n\n"); - - return 0; -} - -/** - * Generate source to populate a read/write property on a prototype - */ -static int -output_populate_rw_property(FILE* outf, const char *class_name, const char *property) -{ - fprintf(outf, "\t/* Add read/write property */\n"); - fprintf(outf, "\tduk_dup(ctx, 0);\n"); - fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n", property); - fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s_getter, 0);\n", - DLPFX, class_name, property); - fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s_setter, 1);\n", - DLPFX, class_name, property); - output_dump_stack(outf); - fprintf(outf, "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\n"); - fprintf(outf, "\t\tDUK_DEFPROP_HAVE_SETTER |\n"); - fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE |\n"); - fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n"); - fprintf(outf, "\tduk_pop(ctx);\n\n"); - - return 0; -} - -/** - * Generate source to populate a readonly property on a prototype - */ -static int -output_populate_ro_property(FILE* outf, const char *class_name, const char *property) -{ - fprintf(outf, "\t/* Add readonly property */\n"); - fprintf(outf, "\tduk_dup(ctx, 0);\n"); - fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n", property); - fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s_getter, 0);\n", - DLPFX, class_name, property); - output_dump_stack(outf); - fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER |\n"); - fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE |\n"); - fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n"); - fprintf(outf, "\tduk_pop(ctx);\n\n"); - - return 0; -} - -/** - * Generate source to add a constant int value on a prototype - */ -static int -output_prototype_constant_int(FILE *outf, const char *constant_name, int value) -{ - fprintf(outf, "\tduk_dup(ctx, 0);\n"); - fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n", constant_name); - fprintf(outf, "\tduk_push_int(ctx, %d);\n", value); - fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |\n"); - fprintf(outf, "\t DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE |\n"); - fprintf(outf, "\t DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE);\n"); - fprintf(outf, "\tduk_pop(ctx);\n\n"); - return 0; -} - -/** - * generate code that gets a private pointer for a method - */ -static int -output_get_method_private(FILE* outf, char *class_name) -{ - fprintf(outf, "\t/* Get private data for method */\n"); - fprintf(outf, "\t%s_private_t *priv = NULL;\n", class_name); - fprintf(outf, "\tduk_push_this(ctx);\n"); - fprintf(outf, "\tduk_get_prop_string(ctx, -1, %s_magic_string_private);\n", - DLPFX); - fprintf(outf, "\tpriv = duk_get_pointer(ctx, -1);\n"); - fprintf(outf, "\tduk_pop_2(ctx);\n"); - fprintf(outf, "\tif (priv == NULL) {\n"); - if (options->dbglog) { - fprintf(outf, "\t\tLOG(\"priv failed\");\n"); - } - fprintf(outf, "\t\treturn 0; /* can do? No can do. */\n"); - fprintf(outf, "\t}\n\n"); - - return 0; -} - -/** - * generate preface block for nsgenbind - */ -static int output_tool_preface(FILE* outf) -{ - fprintf(outf, "%s\n", NSGENBIND_PREAMBLE); - - return 0; -} /** * Generate a C class name for the interface. @@ -345,34 +114,6 @@ static char *gen_class_name(struct ir_entry *interfacee) return name; } -/** - * output character data of node of given type. - * - * used for any cdata including pre/pro/epi/post sections - * - * \param outf The file handle to write output. - * \param node The node to search. - * \param nodetype the type of child node to search for. - * \return The number of nodes written or 0 for none. - */ -static int -output_cdata(FILE* outf, - struct genbind_node *node, - enum genbind_node_type nodetype) -{ - char *cdata; - int res = 0; - - cdata = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(node), - NULL, nodetype)); - if (cdata != NULL) { - fprintf(outf, "%s", cdata); - res = 1; - } - return res; -} static FILE *open_header(struct ir *ir, const char *name) { @@ -431,166 +172,7 @@ static int close_header(struct ir *ir, } -/** - * generate the interface constructor - */ -static int -output_interface_constructor(FILE* outf, struct ir_entry *interfacee) -{ - int init_argc; - - /* constructor definition */ - fprintf(outf, - "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n", - DLPFX, interfacee->class_name); - fprintf(outf,"{\n"); - - output_create_private(outf, interfacee->class_name); - - /* generate call to initialisor */ - fprintf(outf, - "\t%s_%s___init(ctx, priv", - DLPFX, interfacee->class_name); - for (init_argc = 1; - init_argc <= interfacee->class_init_argc; - init_argc++) { - fprintf(outf, ", duk_get_pointer(ctx, %d)", init_argc); - } - fprintf(outf, ");\n"); - - - fprintf(outf, "\tduk_set_top(ctx, 1);\n"); - fprintf(outf, "\treturn 1;\n"); - - fprintf(outf, "}\n\n"); - - return 0; -} - -/** - * generate the interface destructor - */ -static int -output_interface_destructor(FILE* outf, struct ir_entry *interfacee) -{ - /* destructor definition */ - fprintf(outf, - "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n", - DLPFX, interfacee->class_name); - fprintf(outf,"{\n"); - - output_safe_get_private(outf, interfacee->class_name, 0); - - /* generate call to finaliser */ - fprintf(outf, - "\t%s_%s___fini(ctx, priv);\n", - DLPFX, interfacee->class_name); - - fprintf(outf,"\tfree(priv);\n"); - fprintf(outf,"\treturn 0;\n"); - - fprintf(outf, "}\n\n"); - - return 0; -} - -/** - * generate an initialisor call to parent interface - */ -static int -output_interface_inherit_init(FILE* outf, - struct ir_entry *interfacee, - struct ir_entry *inherite) -{ - struct genbind_node *init_node; - struct genbind_node *inh_init_node; - struct genbind_node *param_node; - struct genbind_node *inh_param_node; - - /* only need to call parent initialisor if there is one */ - if (inherite == NULL) { - return 0; - } - - /* find the initialisor method on the class (if any) */ - init_node = genbind_node_find_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_INIT); - - - inh_init_node = genbind_node_find_method(inherite->class, - NULL, - GENBIND_METHOD_TYPE_INIT); - - - - fprintf(outf, "\t%s_%s___init(ctx, &priv->parent", - DLPFX, inherite->class_name); - - /* for each parameter in the parent find a matching named - * parameter to pass and cast if necessary - */ - - inh_param_node = genbind_node_find_type( - genbind_node_getnode(inh_init_node), - NULL, GENBIND_NODE_TYPE_PARAMETER); - while (inh_param_node != NULL) { - char *param_name; - param_name = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(inh_param_node), - NULL, - GENBIND_NODE_TYPE_IDENT)); - - param_node = genbind_node_find_type_ident( - genbind_node_getnode(init_node), - NULL, - GENBIND_NODE_TYPE_PARAMETER, - param_name); - if (param_node == NULL) { - fprintf(stderr, "class \"%s\" (interface %s) parent class \"%s\" (interface %s) initialisor requires a parameter \"%s\" with compatible identifier\n", - interfacee->class_name, - interfacee->name, - inherite->class_name, - inherite->name, - param_name); - return -1; - } else { - char *param_type; - char *inh_param_type; - - fprintf(outf, ", "); - - /* cast the parameter if required */ - param_type = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(param_node), - NULL, - GENBIND_NODE_TYPE_TYPE)); - - inh_param_type = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(inh_param_node), - NULL, - GENBIND_NODE_TYPE_TYPE)); - - if (strcmp(param_type, inh_param_type) != 0) { - fprintf(outf, "(%s)", inh_param_type); - } - - /* output the parameter identifier */ - output_cdata(outf, param_node, GENBIND_NODE_TYPE_IDENT); - } - - inh_param_node = genbind_node_find_type( - genbind_node_getnode(inh_init_node), - inh_param_node, GENBIND_NODE_TYPE_METHOD); - } - - fprintf(outf, ");\n"); - return 0; -} static int output_interface_init_declaration(FILE* outf, @@ -626,997 +208,6 @@ output_interface_init_declaration(FILE* outf, return 0; } -static int -output_interface_init(FILE* outf, - struct ir_entry *interfacee, - struct ir_entry *inherite) -{ - struct genbind_node *init_node; - int res; - - /* find the initialisor method on the class (if any) */ - init_node = genbind_node_find_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_INIT); - - /* initialisor definition */ - output_interface_init_declaration(outf, interfacee, init_node); - - fprintf(outf,"\n{\n"); - - /* if this interface inherits ensure we call its initialisor */ - res = output_interface_inherit_init(outf, interfacee, inherite); - if (res != 0) { - return res; - } - - /* generate log statement */ - if (options->dbglog) { - fprintf(outf, - "\tLOG(\"Initialise %%p (priv=%%p)\", duk_get_heapptr(ctx, 0), priv);\n" ); - } - - /* output the initaliser code from the binding */ - output_cdata(outf, init_node, GENBIND_NODE_TYPE_CDATA); - - fprintf(outf, "}\n\n"); - - return 0; - -} - -static int -output_interface_fini(FILE* outf, - struct ir_entry *interfacee, - struct ir_entry *inherite) -{ - struct genbind_node *fini_node; - - /* find the finaliser method on the class (if any) */ - fini_node = genbind_node_find_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_FINI); - - /* finaliser definition */ - fprintf(outf, - "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n", - DLPFX, interfacee->class_name, interfacee->class_name); - fprintf(outf,"{\n"); - - /* generate log statement */ - if (options->dbglog) { - fprintf(outf, - "\tLOG(\"Finalise %%p\", duk_get_heapptr(ctx, 0));\n" ); - } - - /* output the finialisor code from the binding */ - output_cdata(outf, fini_node, GENBIND_NODE_TYPE_CDATA); - - /* if this interface inherits ensure we call its finaliser */ - if (inherite != NULL) { - fprintf(outf, - "\t%s_%s___fini(ctx, &priv->parent);\n", - DLPFX, inherite->class_name); - } - fprintf(outf, "}\n\n"); - - return 0; -} - - -/** - * generate a prototype add for a single class method - */ -static int -output_prototype_method(FILE* outf, - struct ir_entry *interfacee, - struct ir_operation_entry *operatione) -{ - - if (operatione->name != NULL) { - /* normal method on prototype */ - output_add_method(outf, - interfacee->class_name, - operatione->name); - } else { - /* special method on prototype */ - fprintf(outf, - "\t/* Special method on prototype - UNIMPLEMENTED */\n\n"); - } - - return 0; -} - -/** - * generate prototype method definitions - */ -static int -output_prototype_methods(FILE *outf, struct ir_entry *entry) -{ - int opc; - int res = 0; - - for (opc = 0; opc < entry->u.interface.operationc; opc++) { - res = output_prototype_method( - outf, - entry, - entry->u.interface.operationv + opc); - if (res != 0) { - break; - } - } - - return res; -} - - -static int -output_prototype_attribute(FILE *outf, - struct ir_entry *interfacee, - struct ir_attribute_entry *attributee) -{ - if (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) { - return output_populate_ro_property(outf, - interfacee->class_name, - attributee->name); - } - return output_populate_rw_property(outf, - interfacee->class_name, - attributee->name); -} - -/** - * generate prototype attribute definitions - */ -static int -output_prototype_attributes(FILE *outf, struct ir_entry *entry) -{ - int attrc; - int res = 0; - - for (attrc = 0; attrc < entry->u.interface.attributec; attrc++) { - res = output_prototype_attribute( - outf, - entry, - entry->u.interface.attributev + attrc); - if (res != 0) { - break; - } - } - - return res; -} - -/** - * output constants on the prototype - * - * \todo This implementation assumes the constant is a literal int and should - * check the type node base value. - */ -static int -output_prototype_constant(FILE *outf, - struct ir_constant_entry *constante) -{ - int *value; - - value = webidl_node_getint( - webidl_node_find_type( - webidl_node_getnode(constante->node), - NULL, - WEBIDL_NODE_TYPE_LITERAL_INT)); - - output_prototype_constant_int(outf, constante->name, *value); - - return 0; -} - -/** - * generate prototype constant definitions - */ -static int -output_prototype_constants(FILE *outf, struct ir_entry *entry) -{ - int attrc; - int res = 0; - - for (attrc = 0; attrc < entry->u.interface.constantc; attrc++) { - res = output_prototype_constant( - outf, - entry->u.interface.constantv + attrc); - if (res != 0) { - break; - } - } - - return res; -} - -static int -output_global_create_prototype(FILE* outf, - struct ir *ir, - struct ir_entry *interfacee) -{ - int idx; - - fprintf(outf, "\t/* Create interface objects */\n"); - for (idx = 0; idx < ir->entryc; idx++) { - struct ir_entry *entry; - - entry = ir->entries + idx; - - if (entry->type == IR_ENTRY_TYPE_INTERFACE) { - - if (entry->u.interface.noobject) { - continue; - } - - if (entry == interfacee) { - fprintf(outf, "\tduk_dup(ctx, 0);\n"); - } else { - output_get_prototype(outf, entry->name); - } - - fprintf(outf, - "\tdukky_inject_not_ctr(ctx, 0, \"%s\");\n", - entry->name); - } - } - return 0; -} -/** - * generate the interface prototype creator - */ -static int -output_interface_prototype(FILE* outf, - struct ir *ir, - struct ir_entry *interfacee, - struct ir_entry *inherite) -{ - struct genbind_node *proto_node; - - /* find the prototype method on the class */ - proto_node = genbind_node_find_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_PROTOTYPE); - - /* prototype definition */ - fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx)\n", - DLPFX, interfacee->class_name); - fprintf(outf,"{\n"); - - /* Output any binding data first */ - if (output_cdata(outf, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) { - fprintf(outf,"\n"); - } - - /* generate prototype chaining if interface has a parent */ - if (inherite != NULL) { - fprintf(outf, - "\t/* Set this prototype's prototype (left-parent) */\n"); - output_get_prototype(outf, inherite->name); - fprintf(outf, "\tduk_set_prototype(ctx, 0);\n\n"); - } - - /* generate setting of methods */ - output_prototype_methods(outf, interfacee); - - /* generate setting of attributes */ - output_prototype_attributes(outf, interfacee); - - /* generate setting of constants */ - output_prototype_constants(outf, interfacee); - - /* if this is the global object, output all interfaces which do not - * prevent us from doing so - */ - if (interfacee->u.interface.primary_global) { - output_global_create_prototype(outf, ir, interfacee); - } - - /* generate setting of destructor */ - output_set_destructor(outf, interfacee->class_name, 0); - - /* generate setting of constructor */ - output_set_constructor(outf, - interfacee->class_name, - 0, - interfacee->class_init_argc); - - fprintf(outf,"\treturn 1; /* The prototype object */\n"); - - fprintf(outf, "}\n\n"); - - return 0; -} - -/** - * generate a single class method for an interface operation with elipsis - */ -static int -output_interface_elipsis_operation(FILE* outf, - struct ir_entry *interfacee, - struct ir_operation_entry *operatione) -{ - int cdatac; /* cdata blocks output */ - - /* overloaded method definition */ - fprintf(outf, - "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", - DLPFX, interfacee->class_name, operatione->name); - fprintf(outf,"{\n"); - - /** - * \todo This is where the checking of the parameters to the - * operation with elipsis should go - */ - WARN(WARNING_UNIMPLEMENTED, - "Elipsis parameetrs not checked: method %s::%s();", - interfacee->name, operatione->name); - - output_get_method_private(outf, interfacee->class_name); - - cdatac = output_cdata(outf, - operatione->method, - GENBIND_NODE_TYPE_CDATA); - - if (cdatac == 0) { - /* no implementation so generate default */ - WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: method %s::%s();", - interfacee->name, operatione->name); - fprintf(outf,"\treturn 0;\n"); - } - - fprintf(outf, "}\n\n"); - - return 0; -} - -/** - * generate a single class method for an interface overloaded operation - */ -static int -output_interface_overloaded_operation(FILE* outf, - struct ir_entry *interfacee, - struct ir_operation_entry *operatione) -{ - int cdatac; /* cdata blocks output */ - - /* overloaded method definition */ - fprintf(outf, - "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", - DLPFX, interfacee->class_name, operatione->name); - fprintf(outf,"{\n"); - - /** \todo This is where the checking of the parameters to the - * overloaded operation should go - */ - - output_get_method_private(outf, interfacee->class_name); - - cdatac = output_cdata(outf, - operatione->method, - GENBIND_NODE_TYPE_CDATA); - - if (cdatac == 0) { - /* no implementation so generate default */ - WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: method %s::%s();", - interfacee->name, operatione->name); - fprintf(outf,"\treturn 0;\n"); - } - - fprintf(outf, "}\n\n"); - - return 0; -} - -/** - * generate a single class method for an interface special operation - */ -static int -output_interface_special_operation(FILE* outf, - struct ir_entry *interfacee, - struct ir_operation_entry *operatione) -{ - /* special method definition */ - fprintf(outf, "/* Special method definition - UNIMPLEMENTED */\n\n"); - - WARN(WARNING_UNIMPLEMENTED, - "Special operation on interface %s (operation entry %p)", - interfacee->name, - operatione); - - return 0; -} - -/** - * generate default values on the duk stack - */ -static int -output_operation_optional_defaults(FILE* outf, - struct ir_operation_argument_entry *argumentv, - int argumentc) -{ - int argc; - for (argc = 0; argc < argumentc; argc++) { - struct ir_operation_argument_entry *cure; - struct webidl_node *lit_node; /* literal node */ - enum webidl_node_type lit_type; - int *lit_int; - char *lit_str; - - cure = argumentv + argc; - - lit_node = webidl_node_getnode( - webidl_node_find_type( - webidl_node_getnode(cure->node), - NULL, - WEBIDL_NODE_TYPE_OPTIONAL)); - - if (lit_node != NULL) { - - lit_type = webidl_node_gettype(lit_node); - - switch (lit_type) { - case WEBIDL_NODE_TYPE_LITERAL_NULL: - fprintf(outf, - "\t\tduk_push_null(ctx);\n"); - break; - - case WEBIDL_NODE_TYPE_LITERAL_INT: - lit_int = webidl_node_getint(lit_node); - fprintf(outf, - "\t\tduk_push_int(ctx, %d);\n", - *lit_int); - break; - - case WEBIDL_NODE_TYPE_LITERAL_BOOL: - lit_int = webidl_node_getint(lit_node); - fprintf(outf, - "\t\tduk_push_boolean(ctx, %d);\n", - *lit_int); - break; - - case WEBIDL_NODE_TYPE_LITERAL_STRING: - lit_str = webidl_node_gettext(lit_node); - fprintf(outf, - "\t\tduk_push_string(ctx, \"%s\");\n", - lit_str); - break; - - case WEBIDL_NODE_TYPE_LITERAL_FLOAT: - default: - fprintf(outf, - "\t\tduk_push_undefined(ctx);\n"); - break; - } - } else { - fprintf(outf, "\t\tduk_push_undefined(ctx);\n"); - } - } - return 0; -} - -static int -output_operation_argument_type_check( - FILE* outf, - struct ir_entry *interfacee, - struct ir_operation_entry *operatione, - struct ir_operation_overload_entry *overloade, - int argidx) -{ - struct ir_operation_argument_entry *argumente; - struct webidl_node *type_node; - enum webidl_type *argument_type; - - argumente = overloade->argumentv + argidx; - - type_node = webidl_node_find_type( - webidl_node_getnode(argumente->node), - NULL, - WEBIDL_NODE_TYPE_TYPE); - - if (type_node == NULL) { - fprintf(stderr, "%s:%s %dth argument %s has no type\n", - interfacee->name, - operatione->name, - argidx, - argumente->name); - return -1; - } - - argument_type = (enum webidl_type *)webidl_node_getint( - webidl_node_find_type( - webidl_node_getnode(type_node), - NULL, - WEBIDL_NODE_TYPE_TYPE_BASE)); - - if (argument_type == NULL) { - fprintf(stderr, - "%s:%s %dth argument %s has no type base\n", - interfacee->name, - operatione->name, - argidx, - argumente->name); - return -1; - } - - if (*argument_type == WEBIDL_TYPE_ANY) { - /* allowing any type needs no check */ - return 0; - } - - fprintf(outf, "\tif (%s_argc > %d) {\n", DLPFX, argidx); - - switch (*argument_type) { - case WEBIDL_TYPE_STRING: - fprintf(outf, - "\t\tif (!duk_is_string(ctx, %d)) {\n" - "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_string_type, %d, \"%s\");\n" - "\t\t}\n", argidx, DLPFX, argidx, argumente->name); - break; - - case WEBIDL_TYPE_BOOL: - fprintf(outf, - "\t\tif (!duk_is_boolean(ctx, %d)) {\n" - "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_bool_type, %d, \"%s\");\n" - "\t\t}\n", argidx, DLPFX, argidx, argumente->name); - break; - - case WEBIDL_TYPE_FLOAT: - case WEBIDL_TYPE_DOUBLE: - case WEBIDL_TYPE_SHORT: - case WEBIDL_TYPE_LONG: - case WEBIDL_TYPE_LONGLONG: - fprintf(outf, - "\t\tif (!duk_is_number(ctx, %d)) {\n" - "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_number_type, %d, \"%s\");\n" - "\t\t}\n", argidx, DLPFX, argidx, argumente->name); - break; - - - default: - fprintf(outf, - "\t\t/* unhandled type check */\n"); - } - - fprintf(outf, "\t}\n"); - - return 0; -} - - -/** - * generate a single class method for an interface operation - */ -static int -output_interface_operation(FILE* outf, - struct ir_entry *interfacee, - struct ir_operation_entry *operatione) -{ - int cdatac; /* cdata blocks output */ - struct ir_operation_overload_entry *overloade; - int fixedargc; /* number of non optional arguments */ - int argidx; /* loop counter for arguments */ - int optargc; /* loop counter for optional arguments */ - - if (operatione->name == NULL) { - return output_interface_special_operation(outf, - interfacee, - operatione); - } - - if (operatione->overloadc != 1) { - return output_interface_overloaded_operation(outf, - interfacee, - operatione); - } - - if (operatione->overloadv->elipsisc != 0) { - return output_interface_elipsis_operation(outf, - interfacee, - operatione); - } - - /* normal method definition */ - overloade = operatione->overloadv; - - fprintf(outf, - "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", - DLPFX, interfacee->class_name, operatione->name); - fprintf(outf,"{\n"); - - /* check arguments */ - - /* generate check for minimum number of parameters */ - - fixedargc = overloade->argumentc - overloade->optionalc; - - fprintf(outf, - "\t/* ensure the parameters are present */\n" - "\tduk_idx_t %s_argc = duk_get_top(ctx);\n\t", DLPFX); - - if (fixedargc > 0) { - fprintf(outf, - "if (%s_argc < %d) {\n" - "\t\t/* not enough arguments */\n" - "\t\tduk_error(ctx, DUK_RET_TYPE_ERROR, %s_error_fmt_argument, %d, %s_argc);\n" - "\t} else ", - DLPFX, - fixedargc, - DLPFX, - fixedargc, - DLPFX); - } - - for (optargc = fixedargc; - optargc < overloade->argumentc; - optargc++) { - fprintf(outf, - "if (%s_argc == %d) {\n" - "\t\t/* %d optional arguments need adding */\n", - DLPFX, - optargc, - overloade->argumentc - optargc); - output_operation_optional_defaults(outf, - overloade->argumentv + optargc, - overloade->argumentc - optargc); - fprintf(outf, - "\t} else "); - } - - fprintf(outf, - "if (%s_argc > %d) {\n" - "\t\t/* remove extraneous parameters */\n" - "\t\tduk_set_top(ctx, %d);\n" - "\t}\n", - DLPFX, - overloade->argumentc, - overloade->argumentc); - fprintf(outf, "\n"); - - /* generate argument type checks */ - - fprintf(outf, "\t/* check types of passed arguments are correct */\n"); - - for (argidx = 0; argidx < overloade->argumentc; argidx++) { - output_operation_argument_type_check(outf, - interfacee, - operatione, - overloade, - argidx); - } - - output_get_method_private(outf, interfacee->class_name); - - cdatac = output_cdata(outf, - operatione->method, - GENBIND_NODE_TYPE_CDATA); - - if (cdatac == 0) { - /* no implementation so generate default */ - WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: method %s::%s();", - interfacee->name, operatione->name); - fprintf(outf,"\treturn 0;\n"); - } - - fprintf(outf, "}\n\n"); - - return 0; -} - -/** - * generate class methods for each interface operation - */ -static int -output_interface_operations(FILE* outf, struct ir_entry *ife) -{ - int opc; - int res = 0; - - for (opc = 0; opc < ife->u.interface.operationc; opc++) { - res = output_interface_operation( - outf, - ife, - ife->u.interface.operationv + opc); - if (res != 0) { - break; - } - } - - return res; -} - -/** - * Generate class property getter/setter for a single attribute - */ -static int -output_interface_attribute(FILE* outf, - struct ir_entry *interfacee, - struct ir_attribute_entry *atributee) -{ - int cdatac; - - /* getter definition */ - fprintf(outf, - "static duk_ret_t %s_%s_%s_getter(duk_context *ctx)\n", - DLPFX, interfacee->class_name, atributee->name); - fprintf(outf,"{\n"); - - output_get_method_private(outf, interfacee->class_name); - - cdatac = output_cdata(outf, atributee->getter, GENBIND_NODE_TYPE_CDATA); - - if (cdatac == 0) { - WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: getter %s::%s();", - interfacee->name, atributee->name); - - /* no implementation so generate default */ - fprintf(outf,"\treturn 0;\n"); - } - - fprintf(outf, "}\n\n"); - - /* readonly attributes have no setter */ - if (atributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) { - return 0; - } - - /* setter definition */ - fprintf(outf, - "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n", - DLPFX, interfacee->class_name, atributee->name); - fprintf(outf,"{\n"); - - output_get_method_private(outf, interfacee->class_name); - - cdatac = output_cdata(outf, atributee->setter, GENBIND_NODE_TYPE_CDATA); - - if (cdatac == 0) { - WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: setter %s::%s();", - interfacee->name, atributee->name); - - /* no implementation so generate default */ - fprintf(outf,"\treturn 0;\n"); - } - - - fprintf(outf, "}\n\n"); - - return 0; -} - -/** - * generate class property getters and setters for each interface attribute - */ -static int -output_interface_attributes(FILE* outf, struct ir_entry *ife) -{ - int attrc; - - for (attrc = 0; attrc < ife->u.interface.attributec; attrc++) { - output_interface_attribute( - outf, - ife, - ife->u.interface.attributev + attrc); - } - - return 0; -} - - -/** - * generate preface block for nsgenbind - */ -static int output_tool_prologue(FILE* outf) -{ - char *fpath; - - fpath = genb_fpath("binding.h"); - fprintf(outf, "\n#include \"%s\"\n", fpath); - free(fpath); - - fpath = genb_fpath("private.h"); - fprintf(outf, "#include \"%s\"\n", fpath); - free(fpath); - - fpath = genb_fpath("prototype.h"); - fprintf(outf, "#include \"%s\"\n", fpath); - free(fpath); - - return 0; -} - -/** - * generate a source file to implement a dictionary using duk and libdom. - */ -static int output_dictionary(struct ir *ir, struct ir_entry *dictionarye) -{ - FILE *ifacef; - struct ir_entry *inherite; - int res = 0; - - /* open output file */ - ifacef = genb_fopen_tmp(dictionarye->filename); - if (ifacef == NULL) { - return -1; - } - - /* find parent interface entry */ - inherite = ir_inherit_entry(ir, dictionarye); - - /* tool preface */ - output_tool_preface(ifacef); - - /* binding preface */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_PREFACE); - - /* class preface */ - output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PREFACE); - - /* tool prologue */ - output_tool_prologue(ifacef); - - /* binding prologue */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_PROLOGUE); - - /* class prologue */ - output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PROLOGUE); - - fprintf(ifacef, "\n"); - - /* initialisor */ - res = output_interface_init(ifacef, dictionarye, inherite); - if (res != 0) { - goto op_error; - } - - /* finaliser */ - res = output_interface_fini(ifacef, dictionarye, inherite); - if (res != 0) { - goto op_error; - } - - /* constructor */ - res = output_interface_constructor(ifacef, dictionarye); - if (res != 0) { - goto op_error; - } - - /* destructor */ - res = output_interface_destructor(ifacef, dictionarye); - if (res != 0) { - goto op_error; - } - - /* prototype */ - res = output_interface_prototype(ifacef, ir, dictionarye, inherite); - if (res != 0) { - goto op_error; - } - - - fprintf(ifacef, "\n"); - - /* class epilogue */ - output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_EPILOGUE); - - /* binding epilogue */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_EPILOGUE); - - /* class postface */ - output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_POSTFACE); - - /* binding postface */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_POSTFACE); - -op_error: - genb_fclose_tmp(ifacef, dictionarye->filename); - - return res; -} - -/** - * generate a source file to implement an interface using duk and libdom. - */ -static int output_interface(struct ir *ir, struct ir_entry *interfacee) -{ - FILE *ifacef; - struct ir_entry *inherite; - int res = 0; - - /* open output file */ - ifacef = genb_fopen_tmp(interfacee->filename); - if (ifacef == NULL) { - return -1; - } - - /* find parent interface entry */ - inherite = ir_inherit_entry(ir, interfacee); - - /* tool preface */ - output_tool_preface(ifacef); - - /* binding preface */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_PREFACE); - - /* class preface */ - output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PREFACE); - - /* tool prologue */ - output_tool_prologue(ifacef); - - /* binding prologue */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_PROLOGUE); - - /* class prologue */ - output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PROLOGUE); - - fprintf(ifacef, "\n"); - - /* initialisor */ - res = output_interface_init(ifacef, interfacee, inherite); - if (res != 0) { - goto op_error; - } - - /* finaliser */ - output_interface_fini(ifacef, interfacee, inherite); - - /* constructor */ - output_interface_constructor(ifacef, interfacee); - - /* destructor */ - output_interface_destructor(ifacef, interfacee); - - /* operations */ - output_interface_operations(ifacef, interfacee); - - /* attributes */ - output_interface_attributes(ifacef, interfacee); - - /* prototype */ - output_interface_prototype(ifacef, ir, interfacee, inherite); - - fprintf(ifacef, "\n"); - - /* class epilogue */ - output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_EPILOGUE); - - /* binding epilogue */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_EPILOGUE); - - /* class postface */ - output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_POSTFACE); - - /* binding postface */ - output_cdata(ifacef, - ir->binding_node, - GENBIND_NODE_TYPE_POSTFACE); - -op_error: - genb_fclose_tmp(ifacef, interfacee->filename); - - return res; -} /** * generate private header |