From cf89528fc6668e6d07b6e99db0069c9fe1f6e05d Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 2 Aug 2015 18:30:18 +0100 Subject: Update the webidl parser to cope with specials and overloaded methods --- src/duk-libdom.c | 201 ++++++++++++++++++++++------------------------------ src/interface-map.c | 63 ++++++++++++++-- src/interface-map.h | 1 + src/webidl-ast.c | 9 ++- src/webidl-ast.h | 14 +++- src/webidl-parser.y | 82 +++++++++++++++------ 6 files changed, 227 insertions(+), 143 deletions(-) (limited to 'src') diff --git a/src/duk-libdom.c b/src/duk-libdom.c index 4dbc8e2..bc27dfc 100644 --- a/src/duk-libdom.c +++ b/src/duk-libdom.c @@ -23,7 +23,7 @@ #include "duk-libdom.h" /** prefix for all generated functions */ -#define DLPFX "duckky" +#define DLPFX "dukky" #define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_" @@ -46,7 +46,9 @@ static int output_create_private(FILE* outf, char *class_name) 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, PRIVATE_MAGIC)\n\n"); + fprintf(outf, + "\tduk_put_prop_string(ctx, 0, \"%sPRIVATE\");\n\n", + MAGICPFX); return 0; } @@ -57,7 +59,8 @@ static int output_create_private(FILE* outf, char *class_name) 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, PRIVATE_MAGIC);\n",idx); + fprintf(outf, "\tduk_get_prop_string(ctx, %d, \"%sPRIVATE\");\n", + idx, MAGICPFX); fprintf(outf, "\tpriv = duk_get_pointer(ctx, -1);\n"); fprintf(outf, "\tduk_pop(ctx);\n"); fprintf(outf, "\tif (priv == NULL) return 0;\n\n"); @@ -154,11 +157,14 @@ output_dump_stack(FILE* outf) * generate code that adds a method in a prototype */ static int -output_add_method(FILE* outf, char *class_name, char *method, int argc) +output_add_method(FILE* outf, + const char *class_name, + const char *method, + int argc) { 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_string(ctx, \"%s\");\n", method); fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s, ", DLPFX, class_name, method); if (argc == -1) { @@ -172,7 +178,7 @@ output_add_method(FILE* outf, char *class_name, char *method, int argc) 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"); + fprintf(outf, "\tduk_pop(ctx);\n\n"); return 0; } @@ -196,7 +202,7 @@ output_populate_rw_property(FILE* outf, const char *class_name, const char *prop fprintf(outf, "\t DUK_DEFPROP_HAVE_SETTER |\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"); + fprintf(outf, "\tduk_pop(ctx);\n\n"); return 0; } @@ -217,7 +223,7 @@ output_populate_ro_property(FILE* outf, const char *class_name, const char *prop "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\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"); + fprintf(outf, "\tduk_pop(ctx);\n\n"); return 0; } @@ -234,7 +240,7 @@ output_prototype_constant_int(FILE *outf, const char *constant_name, int 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"); + fprintf(outf, "\tduk_pop(ctx);\n\n"); return 0; } @@ -259,7 +265,7 @@ output_get_method_private(FILE* outf, char *class_name) */ static int output_tool_preface(FILE* outf) { - fprintf(outf, "\n%s\n", NSGENBIND_PREAMBLE); + fprintf(outf, "%s\n", NSGENBIND_PREAMBLE); return 0; } @@ -704,20 +710,30 @@ static int count_operation_arguments(struct webidl_node *node) static int output_prototype_method(FILE* outf, struct interface_map_entry *interfacee, - struct webidl_node *op_node) + struct interface_map_operation_entry *operatione) { - char *op_name; int op_argc; - op_name = webidl_node_gettext( - webidl_node_find_type( - webidl_node_getnode(op_node), - NULL, - WEBIDL_NODE_TYPE_IDENT)); + if (operatione->overloadc > 1) { + /* only generate a method for the first occourance of an + * overloaded method + */ + return 0; + } - op_argc = count_operation_arguments(op_node); + if (operatione->name != NULL) { + /* normal method of prototype */ + op_argc = count_operation_arguments(operatione->node); - output_add_method(outf, interfacee->class_name, op_name, op_argc); + output_add_method(outf, + interfacee->class_name, + operatione->name, + op_argc); + } else { + /* special method on prototype */ + fprintf(outf, + "\t/* Special method on prototype - UNIMPLEMENTED */\n\n"); + } return 0; } @@ -728,43 +744,19 @@ output_prototype_method(FILE* outf, static int output_prototype_methods(FILE *outf, struct interface_map_entry *interfacee) { - int res; - struct webidl_node *list_node; - struct webidl_node *op_node; /* operation on list node */ - - /* iterate each list node within the interface */ - list_node = webidl_node_find_type( - webidl_node_getnode(interfacee->node), - NULL, - WEBIDL_NODE_TYPE_LIST); - - while (list_node != NULL) { - /* iterate through operations in a list */ - op_node = webidl_node_find_type( - webidl_node_getnode(list_node), - NULL, - WEBIDL_NODE_TYPE_OPERATION); - - while (op_node != NULL) { - res = output_prototype_method(outf, interfacee, op_node); - if (res != 0) { - return res; - } + int opc; + int res = 0; - op_node = webidl_node_find_type( - webidl_node_getnode(list_node), - op_node, - WEBIDL_NODE_TYPE_OPERATION); + for (opc = 0; opc < interfacee->operationc; opc++) { + res = output_prototype_method(outf, + interfacee, + interfacee->operationv + opc); + if (res != 0) { + break; } - - - list_node = webidl_node_find_type( - webidl_node_getnode(interfacee->node), - list_node, - WEBIDL_NODE_TYPE_LIST); } - return 0; + return res; } @@ -900,35 +892,34 @@ output_interface_prototype(FILE* outf, static int output_interface_operation(FILE* outf, struct interface_map_entry *interfacee, - struct webidl_node *op_node) + struct interface_map_operation_entry *operatione) { - char *op_name; - struct genbind_node *method_node; - - op_name = webidl_node_gettext( - webidl_node_find_type( - webidl_node_getnode(op_node), - NULL, - WEBIDL_NODE_TYPE_IDENT)); - - method_node = genbind_node_find_method_ident(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_METHOD, - op_name); + if (operatione->overloadc > 1) { + /* only generate a method for the first occourance of an + * overloaded method + */ + return 0; + } - /* method definition */ - fprintf(outf, - "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", - DLPFX, interfacee->class_name, op_name); - fprintf(outf,"{\n"); + if (operatione->name != NULL) { + /* normal method definition */ + fprintf(outf, + "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", + DLPFX, interfacee->class_name, operatione->name); + fprintf(outf,"{\n"); - output_get_method_private(outf, interfacee->class_name); + output_get_method_private(outf, interfacee->class_name); - output_cdata(outf, method_node, GENBIND_NODE_TYPE_CDATA); + output_cdata(outf, operatione->method, GENBIND_NODE_TYPE_CDATA); - fprintf(outf,"\treturn 0;\n"); + fprintf(outf,"\treturn 0;\n"); - fprintf(outf, "}\n\n"); + fprintf(outf, "}\n\n"); + } else { + /* special method definition */ + fprintf(outf, + "/* Special method definition - UNIMPLEMENTED */\n\n"); + } return 0; } @@ -939,43 +930,19 @@ output_interface_operation(FILE* outf, static int output_interface_operations(FILE* outf, struct interface_map_entry *interfacee) { - int res; - struct webidl_node *list_node; - struct webidl_node *op_node; /* operation on list node */ - - /* iterate each list node within the interface */ - list_node = webidl_node_find_type( - webidl_node_getnode(interfacee->node), - NULL, - WEBIDL_NODE_TYPE_LIST); - - while (list_node != NULL) { - /* iterate through operations in a list */ - op_node = webidl_node_find_type( - webidl_node_getnode(list_node), - NULL, - WEBIDL_NODE_TYPE_OPERATION); - - while (op_node != NULL) { - res = output_interface_operation(outf, interfacee, op_node); - if (res != 0) { - return res; - } + int opc; + int res = 0; - op_node = webidl_node_find_type( - webidl_node_getnode(list_node), - op_node, - WEBIDL_NODE_TYPE_OPERATION); + for (opc = 0; opc < interfacee->operationc; opc++) { + res = output_interface_operation(outf, + interfacee, + interfacee->operationv + opc); + if (res != 0) { + break; } - - - list_node = webidl_node_find_type( - webidl_node_getnode(interfacee->node), - list_node, - WEBIDL_NODE_TYPE_LIST); } - return 0; + return res; } /** @@ -1097,24 +1064,25 @@ static int output_interface(struct interface_map *interface_map, /* find parent interface entry */ inherite = interface_map_inherit_entry(interface_map, interfacee); + /* tool preface */ + output_tool_preface(ifacef); + /* binding preface */ output_cdata(ifacef, interface_map->binding_node, GENBIND_NODE_TYPE_PREFACE); - /* tool preface */ - output_tool_preface(ifacef); - /* class preface */ output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PREFACE); + /* tool prologue */ + output_tool_prologue(ifacef); + /* binding prologue */ output_cdata(ifacef, interface_map->binding_node, GENBIND_NODE_TYPE_PROLOGUE); - output_tool_prologue(ifacef); - /* class prologue */ output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PROLOGUE); @@ -1389,20 +1357,21 @@ output_binding_src(struct interface_map *interface_map) return -1; } + /* tool preface */ + output_tool_preface(bindf); + /* binding preface */ output_cdata(bindf, interface_map->binding_node, GENBIND_NODE_TYPE_PREFACE); - /* tool preface */ - output_tool_preface(bindf); + output_tool_prologue(bindf); /* binding prologue */ output_cdata(bindf, interface_map->binding_node, GENBIND_NODE_TYPE_PROLOGUE); - output_tool_prologue(bindf); fprintf(bindf, "\n"); diff --git a/src/interface-map.c b/src/interface-map.c index 555156a..29e9ec0 100644 --- a/src/interface-map.c +++ b/src/interface-map.c @@ -132,6 +132,33 @@ interface_topoligical_sort(struct interface_map_entry *srcinf, int infc) return dstinf; } +static int +count_operation_name(struct interface_map_operation_entry *operationv, + int operationc, + const char *name) +{ + struct interface_map_operation_entry *cure; + int opc; + int res = 0; + + for (opc = 0; opc < operationc; opc++) { + cure = operationv + opc; + + if (cure->name == name) { + /* check pointers for equivalence */ + res++; + } else { + if ((cure->name != NULL) && + (name != NULL) && + (strcmp(cure->name, name) == 0)) { + res++; + } + } + } + + return res; +} + static int operation_map_new(struct webidl_node *interface, struct genbind_node *class, @@ -143,14 +170,16 @@ operation_map_new(struct webidl_node *interface, struct interface_map_operation_entry *cure; /* current entry */ struct interface_map_operation_entry *operationv; int operationc; + int opc; /* enumerate operationss */ operationc = enumerate_interface_type(interface, WEBIDL_NODE_TYPE_OPERATION); - *operationc_out = operationc; if (operationc < 1) { - *operationv_out = NULL; /* no operations so empty map */ + /* no operations so empty map */ + *operationc_out = 0; + *operationv_out = NULL; return 0; } @@ -189,6 +218,10 @@ operation_map_new(struct webidl_node *interface, GENBIND_METHOD_TYPE_METHOD, cure->name); + cure->overloadc = count_operation_name(operationv, + operationc, + cure->name); + cure++; /* move to next operation */ @@ -204,6 +237,21 @@ operation_map_new(struct webidl_node *interface, WEBIDL_NODE_TYPE_LIST); } + /* finally take a pass over the table to correct the overload count */ + for (opc = 0; opc < operationc; opc++) { + cure = operationv + opc; + if ((cure->overloadc == 1) && + (count_operation_name(operationv, + operationc, + cure->name) == 1)) { + /* if the "overloaded" member is itself it is not + * overloaded. + */ + cure->overloadc = 0; + } + } + + *operationc_out = operationc; *operationv_out = operationv; /* resulting operations map */ return 0; @@ -533,8 +581,15 @@ int interface_map_dump(struct interface_map *index) ope = ecur->operationv; while (ope != NULL) { - fprintf(dumpf, " %s %p\n", - ope->name, ope->method); + fprintf(dumpf, + " %s\n", + ope->name); + fprintf(dumpf, + " method:%p\n", + ope->method); + fprintf(dumpf, + " overload:%d\n", + ope->overloadc); ope++; opc--; if (opc == 0) { diff --git a/src/interface-map.h b/src/interface-map.h index c34eb4b..04d9df1 100644 --- a/src/interface-map.h +++ b/src/interface-map.h @@ -17,6 +17,7 @@ struct interface_map_operation_entry { const char *name; /** operation name */ struct webidl_node *node; /**< AST operation node */ struct genbind_node *method; /**< method from binding (if any) */ + int overloadc; /**< Number of previous overloads of this operation */ }; /** map entry for attributes on an interface */ diff --git a/src/webidl-ast.c b/src/webidl-ast.c index 75f969b..0e90767 100644 --- a/src/webidl-ast.c +++ b/src/webidl-ast.c @@ -285,6 +285,7 @@ webidl_node_getint(struct webidl_node *node) case WEBIDL_NODE_TYPE_MODIFIER: case WEBIDL_NODE_TYPE_TYPE_BASE: case WEBIDL_NODE_TYPE_LITERAL_INT: + case WEBIDL_NODE_TYPE_SPECIAL: return &node->r.number; default: @@ -386,6 +387,9 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type) case WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE: return "Extended Attribute"; + case WEBIDL_NODE_TYPE_SPECIAL: + return "Special"; + default: return "Unknown"; } @@ -414,10 +418,13 @@ static int webidl_ast_dump(FILE *dumpf, struct webidl_node *node, int indent) fprintf(dumpf, "\n"); webidl_ast_dump(dumpf, next, indent + 2); } else { - /* not txt or node has to be an int */ + /* not txt or node try an int */ value = webidl_node_getint(node); if (value != NULL) { fprintf(dumpf, ": %d\n", *value); + } else { + /* no value */ + fprintf(dumpf, "\n"); } } } else { diff --git a/src/webidl-ast.h b/src/webidl-ast.h index 38968f3..c17a54b 100644 --- a/src/webidl-ast.h +++ b/src/webidl-ast.h @@ -27,7 +27,8 @@ enum webidl_node_type { WEBIDL_NODE_TYPE_OPERATION, WEBIDL_NODE_TYPE_CONST, - WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT, + WEBIDL_NODE_TYPE_SPECIAL, + WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT, WEBIDL_NODE_TYPE_ARGUMENT, WEBIDL_NODE_TYPE_ELLIPSIS, WEBIDL_NODE_TYPE_TYPE, @@ -68,6 +69,15 @@ enum webidl_type_modifier { WEBIDL_TYPE_MODIFIER_READONLY, }; +/* the type of special node */ +enum webidl_type_special { + WEBIDL_TYPE_SPECIAL_GETTER, + WEBIDL_TYPE_SPECIAL_SETTER, + WEBIDL_TYPE_SPECIAL_CREATOR, + WEBIDL_TYPE_SPECIAL_DELETER, + WEBIDL_TYPE_SPECIAL_LEGACYCALLER, +}; + struct webidl_node; /** callback for search and iteration routines */ @@ -114,7 +124,7 @@ webidl_node_find(struct webidl_node *node, struct webidl_node * webidl_node_find_type(struct webidl_node *node, - struct webidl_node *prev, + struct webidl_node *prev, enum webidl_node_type type); struct webidl_node * diff --git a/src/webidl-parser.y b/src/webidl-parser.y index a48f3fd..953388e 100644 --- a/src/webidl-parser.y +++ b/src/webidl-parser.y @@ -155,6 +155,9 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %type Const %type Operation +%type SpecialOperation +%type Specials +%type Special %type OperationRest %type OptionalIdentifier @@ -723,55 +726,94 @@ ReadOnly: } ; - /* [35] */ + /* SE[47] */ Operation: - Qualifiers OperationRest + ReturnType OperationRest { - /* @todo fix qualifiers */ - $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, $2); + /* put return type on the operation */ + $2 = webidl_node_prepend($1, $2); + + $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, $2); + } + | + SpecialOperation + { + $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, $1); } ; - /* [36] */ -Qualifiers: - TOK_STATIC - | - Specials + /* SE[48] */ +SpecialOperation: + Special Specials ReturnType OperationRest + { + /* put return type on the operation */ + $$ = webidl_node_prepend($4, $3); + + /* specials */ + $$ = webidl_node_prepend($$, $2); + + /* special */ + $$ = webidl_node_prepend($$, $1); + } ; - /* [37] */ + /* SE[49] */ Specials: /* empty */ + { + $$ = NULL; + } | Special Specials + { + $$ = webidl_node_prepend($2, $1); + } ; - /* [38] */ + /* SE[50] */ Special: TOK_GETTER + { + $$ = webidl_node_new(WEBIDL_NODE_TYPE_SPECIAL, + NULL, (void *)WEBIDL_TYPE_SPECIAL_GETTER); + } | TOK_SETTER + { + $$ = webidl_node_new(WEBIDL_NODE_TYPE_SPECIAL, + NULL, (void *)WEBIDL_TYPE_SPECIAL_SETTER); + } | TOK_CREATOR + { + /* second edition removed this special but teh + specifications still use it! + */ + $$ = webidl_node_new(WEBIDL_NODE_TYPE_SPECIAL, + NULL, (void *)WEBIDL_TYPE_SPECIAL_CREATOR); + } | TOK_DELETER + { + $$ = webidl_node_new(WEBIDL_NODE_TYPE_SPECIAL, + NULL, (void *)WEBIDL_TYPE_SPECIAL_DELETER); + } | TOK_LEGACYCALLER + { + $$ = webidl_node_new(WEBIDL_NODE_TYPE_SPECIAL, + NULL, (void *)WEBIDL_TYPE_SPECIAL_LEGACYCALLER); + } ; - /* [39] */ + /* SE[51] */ OperationRest: - ReturnType OptionalIdentifier '(' ArgumentList ')' ';' + OptionalIdentifier '(' ArgumentList ')' ';' { - struct webidl_node *arglist; - - /* put return type in argument list */ - arglist = webidl_node_prepend($4, $1); - /* argument list */ - $$ = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, arglist); + $$ = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, $3); - $$ = webidl_node_prepend($$, $2); /* identifier */ + $$ = webidl_node_prepend($1, $$); /* identifier */ } ; -- cgit v1.2.3