Gitweb links:
...log
http://git.netsurf-browser.org/nsgenbind.git/shortlog/cb23f1f911523752db0...
...commit
http://git.netsurf-browser.org/nsgenbind.git/commit/cb23f1f911523752db095...
...tree
http://git.netsurf-browser.org/nsgenbind.git/tree/cb23f1f911523752db09578...
The branch, vince/interfacemap has been updated
via cb23f1f911523752db095781d0d5fa3e334f1aa5 (commit)
via 3f0d06f529fb5efaeb4edd89e61b3421951b8bf2 (commit)
from d67501b49bb147ac8784618906c024906ae25cbc (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/nsgenbind.git/commit/?id=cb23f1f911523752d...
commit cb23f1f911523752db095781d0d5fa3e334f1aa5
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
Add property generation and add it to prototype construction
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()
%{
%}
commitdiff
http://git.netsurf-browser.org/nsgenbind.git/commit/?id=3f0d06f529fb5efae...
commit 3f0d06f529fb5efaeb4edd89e61b3421951b8bf2
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
Generate class methods from interface operations
diff --git a/src/duk-libdom.c b/src/duk-libdom.c
index b372df7..d1af70c 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom.c
@@ -132,6 +132,34 @@ find_class_method(struct genbind_node *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
@@ -158,6 +186,7 @@ output_cdata(FILE* outf,
*/
static int output_duckky_create_private(FILE* outf, char *class_name)
{
+ fprintf(outf, "\t/* create private data and attach to instance */");
fprintf(outf, "\t%s_private_t *priv = calloc(1, sizeof(*priv));\n",
class_name);
fprintf(outf, "\tif (priv == NULL) return 0;\n");
@@ -453,11 +482,11 @@ static int output_get_prototype(FILE* outf, const char
*interface_name)
for ( ; pnamelen >= 0; pnamelen--) {
proto_name[pnamelen] = toupper(interface_name[pnamelen]);
}
-
- fprintf(outf,"\tduk_get_global_string(ctx, PROTO_MAGIC);\n");
- fprintf(outf,"\tduk_get_prop_string(ctx, -1, PROTO_NAME(%s));\n",
+ fprintf(outf, "\t/* get prototype */\n");
+ fprintf(outf, "\tduk_get_global_string(ctx, PROTO_MAGIC);\n");
+ fprintf(outf, "\tduk_get_prop_string(ctx, -1, PROTO_NAME(%s));\n",
proto_name);
- fprintf(outf,"\tduk_replace(ctx, -2);\n");
+ fprintf(outf, "\tduk_replace(ctx, -2);\n");
free(proto_name);
@@ -496,6 +525,135 @@ output_set_constructor(FILE* outf, char *class_name, int idx, int
argc)
}
/**
+ * generate code that adds a method in a prototype
+ */
+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);
+ fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s, ",
+ DLPFX, class_name, method);
+ if (argc == -1) {
+ fprintf(outf, "DUK_VARARGS);\n");
+
+ } else {
+ fprintf(outf, "%d);\n", argc);
+ }
+ fprintf(outf, "\tDUKKY_DUMP_STACK(ctx);\n");
+ 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;
+}
+
+/**
+ * count the number of arguments to an operation
+ *
+ * \todo this needs to consider multiple lists (overloaded calls?), varadic
+ * parameters.
+ *
+ * \retuen number of arguments or -1 if variable
+ */
+static int count_operation_arguments(struct webidl_node *node)
+{
+ int argc;
+ struct webidl_node *list_node;
+ list_node = webidl_node_find_type(
+ webidl_node_getnode(node),
+ NULL,
+ WEBIDL_NODE_TYPE_LIST);
+ if (list_node == NULL) {
+ /** \todo is having no argument list an error or a warning? */
+ return 0;
+ }
+ argc = webidl_node_enumerate_type(webidl_node_getnode(list_node),
+ WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT);
+ if (argc != 0) {
+ return -1;
+ }
+ return webidl_node_enumerate_type(webidl_node_getnode(list_node),
+ WEBIDL_NODE_TYPE_ARGUMENT);
+}
+
+/**
+ * generate a prototype add for a single class method
+ */
+static int
+output_prototype_method(FILE* outf,
+ struct interface_map_entry *interfacee,
+ struct webidl_node *op_node)
+{
+ 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));
+
+ op_argc = count_operation_arguments(op_node);
+
+ output_add_method(outf, interfacee->class_name, op_name, op_argc);
+
+ return 0;
+
+}
+
+/**
+ * generate prototype method definitions
+ */
+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;
+ }
+
+ 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(interfacee->node),
+ list_node,
+ WEBIDL_NODE_TYPE_LIST);
+ }
+
+ return 0;
+
+}
+
+/**
* generate the interface prototype creator
*/
static int
@@ -517,6 +675,9 @@ output_interface_prototype(FILE* outf,
fprintf(outf, "\tduk_set_prototype(ctx, 0);\n\n");
}
+ /* generate setting of methods */
+ output_prototype_methods(outf, interfacee);
+
/* generate setting of destructor */
output_set_destructor(outf, interfacee->class_name, 0);
@@ -534,6 +695,107 @@ output_interface_prototype(FILE* outf,
}
/**
+ * 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, PRIVATE_MAGIC);\n");
+ fprintf(outf, "\tpriv = duk_get_pointer(ctx, -1);\n");
+ fprintf(outf, "\tduk_pop_2(ctx);\n");
+ fprintf(outf, "\tif (priv == NULL) return 0; /* can do? No can do.
*/\n\n");
+ return 0;
+}
+
+/**
+ * generate a single class method for an interface operation
+ */
+static int
+output_interface_operation(FILE* outf,
+ struct interface_map_entry *interfacee,
+ struct webidl_node *op_node)
+{
+ 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 = find_class_method_ident(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_METHOD,
+ op_name);
+
+ /* method definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name, op_name);
+ fprintf(outf,"{\n");
+
+ output_get_method_private(outf, interfacee->class_name);
+
+ output_cdata(outf, method_node, GENBIND_NODE_TYPE_CDATA);
+
+ 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 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;
+ }
+
+ 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(interfacee->node),
+ list_node,
+ WEBIDL_NODE_TYPE_LIST);
+ }
+
+ return 0;
+}
+
+/**
* generate a source file to implement an interface using duk and libdom.
*/
static int output_interface(struct genbind_node *genbind,
@@ -600,6 +862,11 @@ static int output_interface(struct genbind_node *genbind,
/* destructor */
output_interface_destructor(ifacef, interfacee);
+ /* operations */
+ output_interface_operations(ifacef, interfacee);
+
+ /* attributes */
+
/* prototype */
output_interface_prototype(ifacef, interfacee, inherite);
diff --git a/test/data/bindings/browser-duk.bnd b/test/data/bindings/browser-duk.bnd
index 392f652..0ddfa02 100644
--- a/test/data/bindings/browser-duk.bnd
+++ b/test/data/bindings/browser-duk.bnd
@@ -147,8 +147,18 @@ fini Node()
dom_node_unref(priv->node);
%}
-method Node::AppendChild()
+method Node::appendChild()
%{
+ if (!dukky_instanceof(ctx, PROTO_NAME(NODE))) return 0;
+
+ DUKKY_SAFE_GET_ANOTHER(other,node,0);
+
+ dom_exception err;
+ dom_node *spare;
+
+ err = dom_node_append_child(priv->node, other->node, &spare);
+ if (err != DOM_NO_ERR) return 0;
+ dom_node_unref(spare);
%}
getter Node::aprop()
-----------------------------------------------------------------------
Summary of changes:
src/duk-libdom.c | 442 ++++++++++++++++++++++++++++++++----
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 | 29 ++-
9 files changed, 804 insertions(+), 92 deletions(-)
diff --git a/src/duk-libdom.c b/src/duk-libdom.c
index b372df7..f7a1a5f 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom.c
@@ -98,40 +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;
-}
-
-/**
* output character data of node of given type.
*
* used for pre/pro/epi/post sections
@@ -158,6 +124,7 @@ output_cdata(FILE* outf,
*/
static int output_duckky_create_private(FILE* outf, char *class_name)
{
+ fprintf(outf, "\t/* create private data and attach to instance */");
fprintf(outf, "\t%s_private_t *priv = calloc(1, sizeof(*priv));\n",
class_name);
fprintf(outf, "\tif (priv == NULL) return 0;\n");
@@ -262,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);
@@ -351,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,
@@ -409,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,
@@ -453,11 +420,11 @@ static int output_get_prototype(FILE* outf, const char
*interface_name)
for ( ; pnamelen >= 0; pnamelen--) {
proto_name[pnamelen] = toupper(interface_name[pnamelen]);
}
-
- fprintf(outf,"\tduk_get_global_string(ctx, PROTO_MAGIC);\n");
- fprintf(outf,"\tduk_get_prop_string(ctx, -1, PROTO_NAME(%s));\n",
+ fprintf(outf, "\t/* get prototype */\n");
+ fprintf(outf, "\tduk_get_global_string(ctx, PROTO_MAGIC);\n");
+ fprintf(outf, "\tduk_get_prop_string(ctx, -1, PROTO_NAME(%s));\n",
proto_name);
- fprintf(outf,"\tduk_replace(ctx, -2);\n");
+ fprintf(outf, "\tduk_replace(ctx, -2);\n");
free(proto_name);
@@ -496,6 +463,207 @@ output_set_constructor(FILE* outf, char *class_name, int idx, int
argc)
}
/**
+ * generate code that adds a method in a prototype
+ */
+static int
+output_add_method(FILE* outf, char *class_name, 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_c_function(ctx, %s_%s_%s, ",
+ DLPFX, class_name, method);
+ if (argc == -1) {
+ fprintf(outf, "DUK_VARARGS);\n");
+
+ } else {
+ fprintf(outf, "%d);\n", argc);
+ }
+ fprintf(outf, "\tDUKKY_DUMP_STACK(ctx);\n");
+ 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;
+}
+
+/**
+ * count the number of arguments to an operation
+ *
+ * \todo this needs to consider multiple lists (overloaded calls?), varadic
+ * parameters.
+ *
+ * \retuen number of arguments or -1 if variable
+ */
+static int count_operation_arguments(struct webidl_node *node)
+{
+ int argc;
+ struct webidl_node *list_node;
+ list_node = webidl_node_find_type(
+ webidl_node_getnode(node),
+ NULL,
+ WEBIDL_NODE_TYPE_LIST);
+ if (list_node == NULL) {
+ /** \todo is having no argument list an error or a warning? */
+ return 0;
+ }
+ argc = webidl_node_enumerate_type(webidl_node_getnode(list_node),
+ WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT);
+ if (argc != 0) {
+ return -1;
+ }
+ return webidl_node_enumerate_type(webidl_node_getnode(list_node),
+ WEBIDL_NODE_TYPE_ARGUMENT);
+}
+
+/**
+ * generate a prototype add for a single class method
+ */
+static int
+output_prototype_method(FILE* outf,
+ struct interface_map_entry *interfacee,
+ struct webidl_node *op_node)
+{
+ 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));
+
+ op_argc = count_operation_arguments(op_node);
+
+ output_add_method(outf, interfacee->class_name, op_name, op_argc);
+
+ return 0;
+
+}
+
+/**
+ * generate prototype method definitions
+ */
+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;
+ }
+
+ 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(interfacee->node),
+ list_node,
+ WEBIDL_NODE_TYPE_LIST);
+ }
+
+ return 0;
+
+}
+
+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
*/
static int
@@ -517,6 +685,12 @@ output_interface_prototype(FILE* outf,
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 destructor */
output_set_destructor(outf, interfacee->class_name, 0);
@@ -534,6 +708,168 @@ output_interface_prototype(FILE* outf,
}
/**
+ * 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, PRIVATE_MAGIC);\n");
+ fprintf(outf, "\tpriv = duk_get_pointer(ctx, -1);\n");
+ fprintf(outf, "\tduk_pop_2(ctx);\n");
+ fprintf(outf, "\tif (priv == NULL) return 0; /* can do? No can do.
*/\n\n");
+ return 0;
+}
+
+/**
+ * generate a single class method for an interface operation
+ */
+static int
+output_interface_operation(FILE* outf,
+ struct interface_map_entry *interfacee,
+ struct webidl_node *op_node)
+{
+ 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);
+
+ /* method definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name, op_name);
+ fprintf(outf,"{\n");
+
+ output_get_method_private(outf, interfacee->class_name);
+
+ output_cdata(outf, method_node, GENBIND_NODE_TYPE_CDATA);
+
+ 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 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;
+ }
+
+ 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(interfacee->node),
+ list_node,
+ WEBIDL_NODE_TYPE_LIST);
+ }
+
+ 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.
*/
static int output_interface(struct genbind_node *genbind,
@@ -600,6 +936,12 @@ static int output_interface(struct genbind_node *genbind,
/* destructor */
output_interface_destructor(ifacef, interfacee);
+ /* operations */
+ 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 392f652..513ad99 100644
--- a/test/data/bindings/browser-duk.bnd
+++ b/test/data/bindings/browser-duk.bnd
@@ -147,14 +147,37 @@ fini Node()
dom_node_unref(priv->node);
%}
-method Node::AppendChild()
+method Node::appendChild()
%{
+ if (!dukky_instanceof(ctx, PROTO_NAME(NODE))) return 0;
+
+ DUKKY_SAFE_GET_ANOTHER(other,node,0);
+
+ dom_exception err;
+ dom_node *spare;
+
+ err = dom_node_append_child(priv->node, other->node, &spare);
+ if (err != DOM_NO_ERR) return 0;
+ 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()
%{
%}
--
NetSurf Generator for JavaScript bindings