summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-07-29 00:08:08 +0100
committerVincent Sanders <vince@kyllikki.org>2015-07-29 00:08:08 +0100
commitcb23f1f911523752db095781d0d5fa3e334f1aa5 (patch)
tree4c9044542443243067f9e57d4710573b49122f74
parent3f0d06f529fb5efaeb4edd89e61b3421951b8bf2 (diff)
downloadnsgenbind-cb23f1f911523752db095781d0d5fa3e334f1aa5.tar.gz
nsgenbind-cb23f1f911523752db095781d0d5fa3e334f1aa5.tar.bz2
Add property generation and add it to prototype construction
-rw-r--r--src/duk-libdom.c235
-rw-r--r--src/interface-map.c266
-rw-r--r--src/interface-map.h23
-rw-r--r--src/nsgenbind-ast.c63
-rw-r--r--src/nsgenbind-ast.h52
-rw-r--r--src/webidl-ast.c14
-rw-r--r--src/webidl-ast.h5
-rw-r--r--src/webidl-parser.y2
-rw-r--r--test/data/bindings/browser-duk.bnd17
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
@@ -98,68 +98,6 @@ static char *gen_class_name(struct interface_map_entry *interfacee)
}
/**
- * 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.
*
* used for pre/pro/epi/post sections
@@ -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;
-
}
/**
@@ -796,6 +808,68 @@ output_interface_operations(FILE* outf, struct interface_map_entry *interfacee)
}
/**
+ * 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.
*/
static int output_interface(struct genbind_node *genbind,
@@ -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()
%{
%}