From cb23f1f911523752db095781d0d5fa3e334f1aa5 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 29 Jul 2015 00:08:08 +0100 Subject: Add property generation and add it to prototype construction --- src/duk-libdom.c | 235 +++++++++++++++++++++----------- src/interface-map.c | 266 +++++++++++++++++++++++++++++++++---- src/interface-map.h | 23 +++- src/nsgenbind-ast.c | 63 +++++++++ src/nsgenbind-ast.h | 52 +++++++- src/webidl-ast.c | 14 +- src/webidl-ast.h | 5 +- src/webidl-parser.y | 2 +- test/data/bindings/browser-duk.bnd | 17 ++- 9 files changed, 556 insertions(+), 121 deletions(-) diff --git a/src/duk-libdom.c b/src/duk-libdom.c index d1af70c..f7a1a5f 100644 --- a/src/duk-libdom.c +++ b/src/duk-libdom.c @@ -97,68 +97,6 @@ static char *gen_class_name(struct interface_map_entry *interfacee) return name; } -/** - * find method by type on class - */ -static struct genbind_node * -find_class_method(struct genbind_node *node, - struct genbind_node *prev, - enum genbind_node_type nodetype) -{ - struct genbind_node *res_node; - - res_node = genbind_node_find_type( - genbind_node_getnode(node), - prev, GENBIND_NODE_TYPE_METHOD); - while (res_node != NULL) { - struct genbind_node *type_node; - enum genbind_node_type *type; - - type_node = genbind_node_find_type( - genbind_node_getnode(res_node), - NULL, GENBIND_NODE_TYPE_METHOD_TYPE); - - type = (enum genbind_node_type *)genbind_node_getint(type_node); - if (*type == nodetype) { - break; - } - - res_node = genbind_node_find_type( - genbind_node_getnode(node), - res_node, GENBIND_NODE_TYPE_METHOD); - } - - return res_node; -} - -/** - * find method by type on class with a specific ident - */ -static struct genbind_node * -find_class_method_ident(struct genbind_node *node, - struct genbind_node *prev, - enum genbind_node_type nodetype, - char *ident) -{ - struct genbind_node *res_node; - char *method_ident; - - res_node = find_class_method(node, prev, nodetype); - while (res_node != NULL) { - method_ident = genbind_node_gettext( - genbind_node_find_type( - genbind_node_getnode(res_node), - NULL, - GENBIND_NODE_TYPE_IDENT)); - if ((method_ident != NULL) && strcmp(ident, method_ident) == 0) { - break; - } - - res_node = find_class_method(node, res_node, nodetype); - } - return res_node; -} - /** * output character data of node of given type. * @@ -291,14 +229,14 @@ output_interface_inherit_init(FILE* outf, } /* find the initialisor method on the class (if any) */ - init_node = find_class_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_INIT); + init_node = genbind_node_find_method(interfacee->class, + NULL, + GENBIND_METHOD_TYPE_INIT); - inh_init_node = find_class_method(inherite->class, - NULL, - GENBIND_METHOD_TYPE_INIT); + inh_init_node = genbind_node_find_method(inherite->class, + NULL, + GENBIND_METHOD_TYPE_INIT); @@ -380,9 +318,9 @@ output_interface_init(FILE* outf, int res; /* find the initialisor method on the class (if any) */ - init_node = find_class_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_INIT); + init_node = genbind_node_find_method(interfacee->class, + NULL, + GENBIND_METHOD_TYPE_INIT); /* initialisor definition */ fprintf(outf, @@ -438,9 +376,9 @@ output_interface_fini(FILE* outf, struct genbind_node *fini_node; /* find the finaliser method on the class (if any) */ - fini_node = find_class_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_FINI); + fini_node = genbind_node_find_method(interfacee->class, + NULL, + GENBIND_METHOD_TYPE_FINI); /* finaliser definition */ fprintf(outf, @@ -530,7 +468,6 @@ output_set_constructor(FILE* outf, char *class_name, int idx, int argc) static int output_add_method(FILE* outf, char *class_name, char *method, int argc) { - //#define DUKKY_ADD_METHOD(klass,meth,nargs) fprintf(outf, "\t/* Add a method */\n"); fprintf(outf, "\tduk_dup(ctx, 0);\n"); fprintf(outf, "\tduk_push_string(ctx, %s);\n", method); @@ -653,6 +590,79 @@ output_prototype_methods(FILE *outf, struct interface_map_entry *interfacee) } +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); + fprintf(outf, "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\n"); + 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"); + + return 0; +} + +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); + fprintf(outf, + "\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"); + + return 0; +} + +static int +output_prototype_attribute(FILE *outf, + struct interface_map_entry *interfacee, + struct interface_map_attribute_entry *attributee) +{ + if (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) { + return output_populate_ro_property(outf, + interfacee->class_name, + attributee->name); + } else { + return output_populate_rw_property(outf, + interfacee->class_name, + attributee->name); + } +} + +/** + * generate prototype attribute definitions + */ +static int +output_prototype_attributes(FILE *outf, struct interface_map_entry *interfacee) +{ + int attrc; + + for (attrc = 0; attrc < interfacee->attributec; attrc++) { + output_prototype_attribute(outf, + interfacee, + interfacee->attributev + attrc); + } + + return 0; + +} + /** * generate the interface prototype creator */ @@ -678,6 +688,9 @@ output_interface_prototype(FILE* outf, /* generate setting of methods */ output_prototype_methods(outf, interfacee); + /* generate setting of attributes */ + output_prototype_attributes(outf, interfacee); + /* generate setting of destructor */ output_set_destructor(outf, interfacee->class_name, 0); @@ -727,10 +740,10 @@ output_interface_operation(FILE* outf, NULL, WEBIDL_NODE_TYPE_IDENT)); - method_node = find_class_method_ident(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_METHOD, - op_name); + method_node = genbind_node_find_method_ident(interfacee->class, + NULL, + GENBIND_METHOD_TYPE_METHOD, + op_name); /* method definition */ fprintf(outf, @@ -747,7 +760,6 @@ output_interface_operation(FILE* outf, fprintf(outf, "}\n\n"); return 0; - } /** @@ -795,6 +807,68 @@ output_interface_operations(FILE* outf, struct interface_map_entry *interfacee) return 0; } +/** + * Generate class property getter/setter for a single attribute + */ +static int +output_interface_attribute(FILE* outf, + struct interface_map_entry *interfacee, + struct interface_map_attribute_entry *atributee) +{ + /* 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); + + output_cdata(outf, atributee->getter, GENBIND_NODE_TYPE_CDATA); + + 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); + + output_cdata(outf, atributee->setter, GENBIND_NODE_TYPE_CDATA); + + 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 interface_map_entry *interfacee) +{ + int attrc; + + for (attrc = 0; attrc < interfacee->attributec; attrc++) { + output_interface_attribute(outf, + interfacee, + interfacee->attributev + attrc); + } + + return 0; +} + /** * generate a source file to implement an interface using duk and libdom. */ @@ -866,6 +940,7 @@ static int output_interface(struct genbind_node *genbind, output_interface_operations(ifacef, interfacee); /* attributes */ + output_interface_attributes(ifacef, interfacee); /* prototype */ output_interface_prototype(ifacef, interfacee, inherite); diff --git a/src/interface-map.c b/src/interface-map.c index 44ece42..6a77b6a 100644 --- a/src/interface-map.c +++ b/src/interface-map.c @@ -110,8 +110,10 @@ interface_topoligical_sort(struct interface_map_entry *srcinf, int infc) dstinf[idx].name = srcinf[inf].name; dstinf[idx].node = srcinf[inf].node; dstinf[idx].inherit_name = srcinf[inf].inherit_name; - dstinf[idx].operations = srcinf[inf].operations; - dstinf[idx].attributes = srcinf[inf].attributes; + dstinf[idx].operationc = srcinf[inf].operationc; + dstinf[idx].operationv = srcinf[inf].operationv; + dstinf[idx].attributec = srcinf[inf].attributec; + dstinf[idx].attributev = srcinf[inf].attributev; dstinf[idx].class = srcinf[inf].class; /* reduce refcount on inherit index if !=-1 */ @@ -126,6 +128,180 @@ interface_topoligical_sort(struct interface_map_entry *srcinf, int infc) return dstinf; } +static int +operation_map_new(struct webidl_node *interface, + struct genbind_node *class, + int *operationc_out, + struct interface_map_operation_entry **operationv_out) +{ + struct webidl_node *list_node; + struct webidl_node *op_node; /* attribute node */ + struct interface_map_operation_entry *cure; /* current entry */ + struct interface_map_operation_entry *operationv; + int operationc; + + /* 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 */ + return 0; + } + + operationv = calloc(operationc, + sizeof(struct interface_map_operation_entry)); + if (operationv == NULL) { + return -1; + }; + cure = operationv; + + /* iterate each list node within the interface */ + list_node = webidl_node_find_type( + webidl_node_getnode(interface), + NULL, + WEBIDL_NODE_TYPE_LIST); + + while (list_node != NULL) { + /* iterate through operations on list */ + op_node = webidl_node_find_type( + webidl_node_getnode(list_node), + NULL, + WEBIDL_NODE_TYPE_OPERATION); + + while (op_node != NULL) { + cure->node = op_node; + + cure->name = webidl_node_gettext( + webidl_node_find_type( + webidl_node_getnode(op_node), + NULL, + WEBIDL_NODE_TYPE_IDENT)); + + cure->method = genbind_node_find_method_ident( + class, + NULL, + GENBIND_METHOD_TYPE_METHOD, + cure->name); + + cure++; + + /* move to next operation */ + op_node = webidl_node_find_type( + webidl_node_getnode(list_node), + op_node, + WEBIDL_NODE_TYPE_OPERATION); + } + + list_node = webidl_node_find_type( + webidl_node_getnode(interface), + list_node, + WEBIDL_NODE_TYPE_LIST); + } + + *operationv_out = operationv; /* resulting operations map */ + + return 0; +} + +static int +attribute_map_new(struct webidl_node *interface, + struct genbind_node *class, + int *attributec_out, + struct interface_map_attribute_entry **attributev_out) +{ + struct webidl_node *list_node; + struct webidl_node *at_node; /* attribute node */ + struct interface_map_attribute_entry *cure; /* current entry */ + struct interface_map_attribute_entry *attributev; + int attributec; + + /* enumerate attributes */ + attributec = enumerate_interface_type(interface, + WEBIDL_NODE_TYPE_ATTRIBUTE); + *attributec_out = attributec; + + if (attributec < 1) { + *attributev_out = NULL; /* no attributes so empty map */ + return 0; + } + + attributev = calloc(attributec, + sizeof(struct interface_map_attribute_entry)); + if (attributev == NULL) { + return -1; + }; + cure = attributev; + + /* iterate each list node within the interface */ + list_node = webidl_node_find_type( + webidl_node_getnode(interface), + NULL, + WEBIDL_NODE_TYPE_LIST); + + while (list_node != NULL) { + /* iterate through attributes on list */ + at_node = webidl_node_find_type( + webidl_node_getnode(list_node), + NULL, + WEBIDL_NODE_TYPE_ATTRIBUTE); + + while (at_node != NULL) { + enum webidl_type_modifier *modifier; + + cure->node = at_node; + + cure->name = webidl_node_gettext( + webidl_node_find_type( + webidl_node_getnode(at_node), + NULL, + WEBIDL_NODE_TYPE_IDENT)); + + cure->getter = genbind_node_find_method_ident( + class, + NULL, + GENBIND_METHOD_TYPE_GETTER, + cure->name); + + /* check fo readonly attributes */ + modifier = (enum webidl_type_modifier *)webidl_node_getint( + webidl_node_find_type( + webidl_node_getnode(at_node), + NULL, + WEBIDL_NODE_TYPE_MODIFIER)); + if ((modifier != NULL) && + (*modifier == WEBIDL_TYPE_MODIFIER_READONLY)) { + cure->modifier = WEBIDL_TYPE_MODIFIER_READONLY; + } else { + cure->modifier = WEBIDL_TYPE_MODIFIER_NONE; + cure->setter = genbind_node_find_method_ident( + class, + NULL, + GENBIND_METHOD_TYPE_SETTER, + cure->name); + } + + cure++; + + /* move to next attribute */ + at_node = webidl_node_find_type( + webidl_node_getnode(list_node), + at_node, + WEBIDL_NODE_TYPE_ATTRIBUTE); + } + + list_node = webidl_node_find_type( + webidl_node_getnode(interface), + list_node, + WEBIDL_NODE_TYPE_LIST); + } + + *attributev_out = attributev; /* resulting attributes map */ + + return 0; +} + int interface_map_new(struct genbind_node *genbind, struct webidl_node *webidl, struct interface_map **index_out) @@ -162,7 +338,7 @@ int interface_map_new(struct genbind_node *genbind, webidl_node_find_type( webidl_node_getnode(node), NULL, - GENBIND_NODE_TYPE_IDENT)); + WEBIDL_NODE_TYPE_IDENT)); /* name of the inherited interface (if any) */ ecur->inherit_name = webidl_node_gettext( @@ -171,20 +347,22 @@ int interface_map_new(struct genbind_node *genbind, NULL, WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE)); - - /* enumerate the number of operations */ - ecur->operations = enumerate_interface_type(node, - WEBIDL_NODE_TYPE_OPERATION); - - /* enumerate the number of attributes */ - ecur->attributes = enumerate_interface_type(node, - WEBIDL_NODE_TYPE_ATTRIBUTE); - - /* matching class from binding */ ecur->class = genbind_node_find_type_ident(genbind, NULL, GENBIND_NODE_TYPE_CLASS, ecur->name); + /* enumerate and map the interface operations */ + operation_map_new(node, + ecur->class, + &ecur->operationc, + &ecur->operationv); + + /* enumerate and map the interface attributes */ + attribute_map_new(node, + ecur->class, + &ecur->attributec, + &ecur->attributev); + /* move to next interface */ node = webidl_node_find_type(webidl, node, WEBIDL_NODE_TYPE_INTERFACE); @@ -218,27 +396,68 @@ int interface_map_dump(struct interface_map *index) FILE *dumpf; int eidx; struct interface_map_entry *ecur; - const char *inherit_name; /* only dump AST to file if required */ if (!options->debug) { return 0; } - dumpf = genb_fopen("interface-index", "w"); + dumpf = genb_fopen("interface-map", "w"); if (dumpf == NULL) { return 2; } ecur = index->entries; for (eidx = 0; eidx < index->entryc; eidx++) { - inherit_name = ecur->inherit_name; - if (inherit_name == NULL) { - inherit_name = ""; - } - fprintf(dumpf, "%d %s %s i:%d a:%d %p\n", eidx, ecur->name, - inherit_name, ecur->operations, ecur->attributes, - ecur->class); + fprintf(dumpf, "%d %s\n", eidx, ecur->name); + if (ecur->inherit_name != NULL) { + fprintf(dumpf, " inherit:%s\n", ecur->inherit_name); + } + if (ecur->class != NULL) { + fprintf(dumpf, " class:%p\n", ecur->class); + } + if (ecur->operationc > 0) { + int opc = ecur->operationc; + struct interface_map_operation_entry *ope; + + fprintf(dumpf, " %d operations\n", + ecur->operationc); + + ope = ecur->operationv; + while (ope != NULL) { + fprintf(dumpf, " %s %p\n", + ope->name, ope->method); + ope++; + opc--; + if (opc == 0) { + break; + } + } + + } + if (ecur->attributec > 0) { + int attrc = ecur->attributec; + struct interface_map_attribute_entry *attre; + + fprintf(dumpf, " %d attributes\n", attrc); + + attre = ecur->attributev; + while (attre != NULL) { + fprintf(dumpf, " %s %p", + attre->name, + attre->getter); + if (attre->modifier == WEBIDL_TYPE_MODIFIER_NONE) { + fprintf(dumpf, " %p\n", attre->setter); + } else { + fprintf(dumpf, "\n"); + } + attre++; + attrc--; + if (attrc == 0) { + break; + } + } + } ecur++; } @@ -269,7 +488,8 @@ int interface_map_dumpdot(struct interface_map *index) for (eidx = 0; eidx < index->entryc; eidx++) { if (ecur->class != NULL) { /* interfaces bound to a class are shown in blue */ - fprintf(dumpf, "%04d [label=\"%s\" fontcolor=\"blue\"];\n", eidx, ecur->name); + fprintf(dumpf, "%04d [label=\"%s\" fontcolor=\"blue\"];\n", + eidx, ecur->name); } else { fprintf(dumpf, "%04d [label=\"%s\"];\n", eidx, ecur->name); } diff --git a/src/interface-map.h b/src/interface-map.h index 7373580..9d66dfb 100644 --- a/src/interface-map.h +++ b/src/interface-map.h @@ -12,12 +12,31 @@ struct genbind_node; struct webidl_node; +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) */ +}; + +struct interface_map_attribute_entry { + const char *name; /** attribute name */ + struct webidl_node *node; /**< AST attribute node */ + enum webidl_type_modifier modifier; + struct genbind_node *getter; /**< getter from binding (if any) */ + struct genbind_node *setter; /**< getter from binding (if any) */ +}; + struct interface_map_entry { const char *name; /** interface name */ struct webidl_node *node; /**< AST interface node */ const char *inherit_name; /**< Name of interface inhertited from */ - int operations; /**< number of operations on interface */ - int attributes; /**< number of attributes on interface */ + + int operationc; /**< number of operations on interface */ + struct interface_map_operation_entry *operationv; + + int attributec; /**< number of attributes on interface */ + struct interface_map_attribute_entry *attributev; + int inherit_idx; /**< index into map of inherited interface or -1 for * not in map */ diff --git a/src/nsgenbind-ast.c b/src/nsgenbind-ast.c index c1acee1..28326aa 100644 --- a/src/nsgenbind-ast.c +++ b/src/nsgenbind-ast.c @@ -288,6 +288,69 @@ genbind_node_find_type_type(struct genbind_node *node, return found_node; } + +/* exported interface documented in nsgenbind-ast.h */ +struct genbind_node * +genbind_node_find_method(struct genbind_node *node, + struct genbind_node *prev, + enum genbind_method_type methodtype) +{ + struct genbind_node *res_node; + + res_node = genbind_node_find_type( + genbind_node_getnode(node), + prev, GENBIND_NODE_TYPE_METHOD); + while (res_node != NULL) { + struct genbind_node *type_node; + enum genbind_method_type *type; + + type_node = genbind_node_find_type( + genbind_node_getnode(res_node), + NULL, GENBIND_NODE_TYPE_METHOD_TYPE); + + type = (enum genbind_method_type *)genbind_node_getint(type_node); + if (*type == methodtype) { + break; + } + + res_node = genbind_node_find_type( + genbind_node_getnode(node), + res_node, GENBIND_NODE_TYPE_METHOD); + } + + return res_node; +} + + +/* exported interface documented in nsgenbind-ast.h */ +struct genbind_node * +genbind_node_find_method_ident(struct genbind_node *node, + struct genbind_node *prev, + enum genbind_method_type nodetype, + const char *ident) +{ + struct genbind_node *res_node; + char *method_ident; + + res_node = genbind_node_find_method(node, prev, nodetype); + while (res_node != NULL) { + method_ident = genbind_node_gettext( + genbind_node_find_type( + genbind_node_getnode(res_node), + NULL, + GENBIND_NODE_TYPE_IDENT)); + if ((method_ident != NULL) && + strcmp(ident, method_ident) == 0) { + break; + } + + res_node = genbind_node_find_method(node, res_node, nodetype); + } + return res_node; +} + + +/* exported interface documented in nsgenbind-ast.h */ int genbind_cmp_node_type(struct genbind_node *node, void *ctx) { if (node->type == (enum genbind_node_type)ctx) diff --git a/src/nsgenbind-ast.h b/src/nsgenbind-ast.h index 9c564b9..0b0fcfd 100644 --- a/src/nsgenbind-ast.h +++ b/src/nsgenbind-ast.h @@ -101,7 +101,8 @@ genbind_node_find(struct genbind_node *node, genbind_callback_t *cb, void *ctx); -/** Depth first left hand search returning nodes of the specified type +/** + * Depth first left hand search returning nodes of the specified type * * @param node The node to start the search from * @param prev The node at which to stop the search, either NULL to @@ -115,7 +116,8 @@ genbind_node_find_type(struct genbind_node *node, struct genbind_node *prev, enum genbind_node_type nodetype); -/** count how many nodes of a specified type. +/** + * count how many nodes of a specified type. * * Enumerate how many nodes of the specified type there are by * performing a depth first search for nodes of the given type and @@ -129,7 +131,9 @@ int genbind_node_enumerate_type(struct genbind_node *node, enum genbind_node_type type); -/** Depth first left hand search returning nodes of the specified type + +/** + * Depth first left hand search returning nodes of the specified type * with an ident child node with matching text * * @param node The node to start the search from @@ -145,7 +149,9 @@ genbind_node_find_type_ident(struct genbind_node *node, enum genbind_node_type nodetype, const char *ident); -/** Returning node of the specified type with a GENBIND_NODE_TYPE_TYPE + +/** + * Returning node of the specified type with a GENBIND_NODE_TYPE_TYPE * subnode with matching text. * * This is a conveniance wrapper around nested calls to @@ -167,7 +173,43 @@ genbind_node_find_type_type(struct genbind_node *node, enum genbind_node_type nodetype, const char *type_text); -/** Iterate all nodes of a certian type from a node with a callback. + +/** + * Find a method node of a given method type + * + * \param node A node of type GENBIND_NODE_TYPE_CLASS to search for methods. + * \param prev The node at which to stop the search, either NULL to + * search the full tree depth (initial search) or the result + * of a previous search to continue. + * \param methodtype The type of method to find. + * \return A node of type GENBIND_NODE_TYPE_METHOD on success or NULL on faliure + */ +struct genbind_node * +genbind_node_find_method(struct genbind_node *node, + struct genbind_node *prev, + enum genbind_method_type methodtype); + + +/** + * Find a method node of a given method type and identifier + * + * \param node A node of type GENBIND_NODE_TYPE_CLASS to search for methods. + * \param prev The node at which to stop the search, either NULL to + * search the full tree depth (initial search) or the result + * of a previous search to continue. + * \param methodtype The type of method to find. + * \param ident The identifier to search for + * \return A node of type GENBIND_NODE_TYPE_METHOD on success or NULL on faliure + */ +struct genbind_node * +genbind_node_find_method_ident(struct genbind_node *node, + struct genbind_node *prev, + enum genbind_method_type methodtype, + const char *ident); + + +/** + * Iterate all nodes of a certian type from a node with a callback. * * Depth first search for nodes of the given type calling the callback * with context. diff --git a/src/webidl-ast.c b/src/webidl-ast.c index 6c24c41..75f969b 100644 --- a/src/webidl-ast.c +++ b/src/webidl-ast.c @@ -277,7 +277,7 @@ char *webidl_node_gettext(struct webidl_node *node) } /* exported interface defined in webidl-ast.h */ -int +int * webidl_node_getint(struct webidl_node *node) { if (node != NULL) { @@ -285,14 +285,13 @@ webidl_node_getint(struct webidl_node *node) case WEBIDL_NODE_TYPE_MODIFIER: case WEBIDL_NODE_TYPE_TYPE_BASE: case WEBIDL_NODE_TYPE_LITERAL_INT: - return node->r.number; + return &node->r.number; default: break; } } - return -1; - + return NULL; } /* exported interface defined in webidl-ast.h */ @@ -400,6 +399,7 @@ static int webidl_ast_dump(FILE *dumpf, struct webidl_node *node, int indent) { const char *SPACES=" "; char *txt; + int *value; while (node != NULL) { fprintf(dumpf, "%.*s%s", indent, SPACES, webidl_node_type_to_str(node->type)); @@ -415,8 +415,10 @@ static int webidl_ast_dump(FILE *dumpf, struct webidl_node *node, int indent) webidl_ast_dump(dumpf, next, indent + 2); } else { /* not txt or node has to be an int */ - fprintf(dumpf, ": %d\n", - webidl_node_getint(node)); + value = webidl_node_getint(node); + if (value != NULL) { + fprintf(dumpf, ": %d\n", *value); + } } } else { fprintf(dumpf, ": \"%s\"\n", txt); diff --git a/src/webidl-ast.h b/src/webidl-ast.h index 5d0cbc0..38968f3 100644 --- a/src/webidl-ast.h +++ b/src/webidl-ast.h @@ -62,9 +62,10 @@ enum webidl_type { }; enum webidl_type_modifier { + WEBIDL_TYPE_MODIFIER_NONE, WEBIDL_TYPE_MODIFIER_UNSIGNED, WEBIDL_TYPE_MODIFIER_UNRESTRICTED, - WEBIDL_TYPE_READONLY, + WEBIDL_TYPE_MODIFIER_READONLY, }; struct webidl_node; @@ -86,7 +87,7 @@ struct webidl_node *webidl_node_add(struct webidl_node *node, struct webidl_node /* node contents acessors */ char *webidl_node_gettext(struct webidl_node *node); struct webidl_node *webidl_node_getnode(struct webidl_node *node); -int webidl_node_getint(struct webidl_node *node); +int *webidl_node_getint(struct webidl_node *node); enum webidl_node_type webidl_node_gettype(struct webidl_node *node); /* node searches */ diff --git a/src/webidl-parser.y b/src/webidl-parser.y index 9717b8c..a48f3fd 100644 --- a/src/webidl-parser.y +++ b/src/webidl-parser.y @@ -689,7 +689,7 @@ Attribute: /* deal with readonly modifier */ if ($2) { - attribute = webidl_node_new(WEBIDL_NODE_TYPE_MODIFIER, attribute, (void *)WEBIDL_TYPE_READONLY); + attribute = webidl_node_new(WEBIDL_NODE_TYPE_MODIFIER, attribute, (void *)WEBIDL_TYPE_MODIFIER_READONLY); } $$ = webidl_node_new(WEBIDL_NODE_TYPE_ATTRIBUTE, NULL, attribute); diff --git a/test/data/bindings/browser-duk.bnd b/test/data/bindings/browser-duk.bnd index 0ddfa02..513ad99 100644 --- a/test/data/bindings/browser-duk.bnd +++ b/test/data/bindings/browser-duk.bnd @@ -161,10 +161,23 @@ method Node::appendChild() dom_node_unref(spare); %} -getter Node::aprop() +getter Node::textContent() %{ + dom_exception exc; + dom_string *content; + + exc = dom_node_get_text_content(priv->node, &content); + if (exc != DOM_NO_ERR) { + return 0; + } + + if (content != NULL) { + duk_push_lstring(ctx, dom_string_data(content), dom_string_length(content)); + dom_string_unref(content); + return 1; + } %} -setter Node::aprop() +setter Node::textContent() %{ %} -- cgit v1.2.3