summaryrefslogtreecommitdiff
path: root/src/duk-libdom.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-07-26 17:52:27 +0100
committerVincent Sanders <vince@kyllikki.org>2015-07-26 17:52:27 +0100
commitef1eb5b59df798dc9a3e8df93fe46500aa4244e9 (patch)
treefcabafd8dca2e0983108b3b24ac03e8bd63728c4 /src/duk-libdom.c
parent13be4238314d1a9903b037ab749074575ef0d1eb (diff)
downloadnsgenbind-ef1eb5b59df798dc9a3e8df93fe46500aa4244e9.tar.gz
nsgenbind-ef1eb5b59df798dc9a3e8df93fe46500aa4244e9.tar.bz2
make the duktape libdom generator output initializers
Diffstat (limited to 'src/duk-libdom.c')
-rw-r--r--src/duk-libdom.c326
1 files changed, 299 insertions, 27 deletions
diff --git a/src/duk-libdom.c b/src/duk-libdom.c
index 4d8ecf5..ee45eaf 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom.c
@@ -22,6 +22,9 @@
#include "interface-map.h"
#include "duk-libdom.h"
+/** prefix for all generated functions */
+#define DLPFX "duckky"
+
#define NSGENBIND_PREAMBLE \
"/* Generated by nsgenbind\n" \
" *\n" \
@@ -95,6 +98,40 @@ 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
@@ -110,19 +147,258 @@ output_cdata(FILE* outf,
genbind_node_getnode(node),
NULL, nodetype));
if (cdata != NULL) {
- fprintf(outf, "%s\n", cdata);
+ fprintf(outf, "%s", cdata);
+ }
+ return 0;
+}
+
+/**
+ * Output code to create a private structure
+ *
+ */
+static int output_duckky_create_private(FILE* outf, char *class_name)
+{
+ fprintf(outf, "\t%s_private_t *priv = calloc(1, sizeof(*priv));\n",
+ class_name);
+ fprintf(outf, "\tif (priv == NULL) return 0;\n");
+ fprintf(outf, "\tduk_push_pointer(ctx, priv);\n");
+ fprintf(outf, "\tduk_put_prop_string(ctx, 0, PRIVATE_MAGIC)\n\n");
+
+ return 0;
+}
+
+/**
+ * generate code that gets a private pointer
+ */
+static int output_ducky_safe_get_private(FILE* outf, char *class_name, int idx)
+{
+ fprintf(outf,
+ "\t%s_private_t *priv = dukky_get_private(ctx, %d);\n",
+ class_name, idx);
+ fprintf(outf, "\tif (priv == NULL) return 0;\n\n");
+ return 0;
+}
+
+
+/**
+ * generate the interface constructor
+ */
+static int
+output_interface_constructor(FILE* outf, struct interface_map_entry *interfacee)
+{
+ /* constructor definition */
+ fprintf(outf,
+ "duk_ret_t %s_%s___constructor(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name);
+ fprintf(outf,"{\n");
+
+ output_duckky_create_private(outf, interfacee->class_name);
+
+ /* generate call to initialisor */
+ fprintf(outf,
+ "\t%s_%s___init(ctx, priv, duk_get_pointer(ctx, 1));\n",
+ DLPFX, interfacee->class_name);
+
+ fprintf(outf, "\tduk_set_top(ctx, 1);\n");
+ fprintf(outf, "\treturn 1;\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate the interface destructor
+ */
+static int
+output_interface_destructor(FILE* outf, struct interface_map_entry *interfacee)
+{
+ /* destructor definition */
+ fprintf(outf,
+ "duk_ret_t %s_%s___destructor(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name);
+ fprintf(outf,"{\n");
+
+ output_ducky_safe_get_private(outf, interfacee->class_name, 0);
+
+ /* generate call to finaliser */
+ fprintf(outf,
+ "\t%s_%s___fini(ctx, priv);\n",
+ DLPFX, interfacee->class_name);
+
+ fprintf(outf,"\tfree(priv);\n");
+ fprintf(outf,"\treturn 0;\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate an initialisor call to parent interface
+ */
+static int
+output_interface_inherit_init(FILE* outf,
+ struct interface_map_entry *interfacee,
+ struct interface_map_entry *inherite)
+{
+ struct genbind_node *init_node;
+ struct genbind_node *inh_init_node;
+ struct genbind_node *param_node;
+ struct genbind_node *inh_param_node;
+
+ /* only need to call parent initialisor if there is one */
+ if (inherite == NULL) {
+ return 0;
}
+
+ /* find the initialisor method on the class (if any) */
+ init_node = find_class_method(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+
+ inh_init_node = find_class_method(inherite->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+
+
+ fprintf(outf, "\t%s_%s___init(ctx, &priv->parent",
+ DLPFX, inherite->class_name);
+
+ /* for each parameter in the parent find a matching named
+ * parameter to pass and cast if necessary
+ */
+
+ inh_param_node = genbind_node_find_type(
+ genbind_node_getnode(inh_init_node),
+ NULL, GENBIND_NODE_TYPE_PARAMETER);
+ while (inh_param_node != NULL) {
+ char *param_name;
+ param_name = genbind_node_gettext(
+ genbind_node_find_type(
+ genbind_node_getnode(inh_param_node),
+ NULL,
+ GENBIND_NODE_TYPE_IDENT));
+
+ param_node = genbind_node_find_type_ident(
+ genbind_node_getnode(init_node),
+ NULL,
+ GENBIND_NODE_TYPE_PARAMETER,
+ param_name);
+ if (param_node == NULL) {
+ fprintf(stderr, "class \"%s\" (interface %s) parent class \"%s\" (interface %s) initialisor requires a parameter \"%s\" with compatible identifier\n",
+ interfacee->class_name,
+ interfacee->name,
+ inherite->class_name,
+ inherite->name,
+ param_name);
+ return -1;
+ } else {
+ char *param_type;
+ char *inh_param_type;
+
+ fprintf(outf, ", ");
+
+ /* cast the parameter if required */
+ param_type = genbind_node_gettext(
+ genbind_node_find_type(
+ genbind_node_getnode(param_node),
+ NULL,
+ GENBIND_NODE_TYPE_TYPE));
+
+ inh_param_type = genbind_node_gettext(
+ genbind_node_find_type(
+ genbind_node_getnode(inh_param_node),
+ NULL,
+ GENBIND_NODE_TYPE_TYPE));
+
+ if (strcmp(param_type, inh_param_type) != 0) {
+ fprintf(outf, "(%s)", inh_param_type);
+ }
+
+ /* output the parameter identifier */
+ output_cdata(outf, param_node, GENBIND_NODE_TYPE_IDENT);
+ }
+
+ inh_param_node = genbind_node_find_type(
+ genbind_node_getnode(inh_init_node),
+ inh_param_node, GENBIND_NODE_TYPE_METHOD);
+ }
+
+ fprintf(outf, ");\n");
+
return 0;
}
static int
+output_interface_init(FILE* outf,
+ struct interface_map_entry *interfacee,
+ struct interface_map_entry *inherite)
+{
+ struct genbind_node *init_node;
+ struct genbind_node *param_node;
+ int res;
+
+ /* find the initialisor method on the class (if any) */
+ init_node = find_class_method(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+ /* initialisor definition */
+ fprintf(outf,
+ "void %s_%s___init(duk_context *ctx, %s_private_t *priv",
+ DLPFX, interfacee->class_name, interfacee->class_name);
+
+ /* output the paramters on the method (if any) */
+ param_node = genbind_node_find_type(
+ genbind_node_getnode(init_node),
+ NULL, GENBIND_NODE_TYPE_PARAMETER);
+ while (param_node != NULL) {
+ fprintf(outf, ", ");
+ output_cdata(outf, param_node, GENBIND_NODE_TYPE_TYPE);
+ output_cdata(outf, param_node, GENBIND_NODE_TYPE_IDENT);
+
+ param_node = genbind_node_find_type(
+ genbind_node_getnode(init_node),
+ param_node, GENBIND_NODE_TYPE_METHOD);
+ }
+
+ fprintf(outf,")\n{\n");
+
+ /* if this interface inherits ensure we call its initialisor */
+ res = output_interface_inherit_init(outf, interfacee, inherite);
+ if (res != 0) {
+ return res;
+ }
+
+ /* generate log statement */
+ if (options->dbglog) {
+ fprintf(outf,
+ "\tLOG(\"Initialise %%p (priv=%%p)\", duk_get_heapptr(ctx, 0), priv);\n" );
+ }
+
+ /* output the initaliser code from the binding */
+ output_cdata(outf, init_node, GENBIND_NODE_TYPE_CDATA);
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+
+}
+
+static int
output_interface_fini(FILE* outf,
struct interface_map_entry *interfacee,
struct interface_map_entry *inherite)
{
struct genbind_node *fini_node;
- struct genbind_node *type_node;
- int *type;
+
+ /* find the finaliser method on the class (if any) */
+ fini_node = find_class_method(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_FINI);
/* finaliser definition */
fprintf(outf,
@@ -136,24 +412,7 @@ output_interface_fini(FILE* outf,
"\tLOG(\"Finalise %%p\", duk_get_heapptr(ctx, 0));\n" );
}
- /* find the finaliser method on the class (if any) */
- fini_node = genbind_node_find_type(
- genbind_node_getnode(interfacee->class),
- NULL, GENBIND_NODE_TYPE_METHOD);
- while (fini_node != NULL) {
- type_node = genbind_node_find_type(
- genbind_node_getnode(fini_node),
- NULL, GENBIND_NODE_TYPE_METHOD_TYPE);
-
- type = genbind_node_getint(type_node);
- if (*type == GENBIND_METHOD_TYPE_FINI) {
- break;
- }
-
- fini_node = genbind_node_find_type(
- genbind_node_getnode(interfacee->class),
- fini_node, GENBIND_NODE_TYPE_METHOD);
- }
+ /* output the finialisor code from the binding */
output_cdata(outf, fini_node, GENBIND_NODE_TYPE_CDATA);
/* if this interface inherits ensure we call its finaliser */
@@ -162,7 +421,7 @@ output_interface_fini(FILE* outf,
"\tdukky_%s___fini(ctx, &priv->parent);\n",
inherite->class_name);
}
- fprintf(outf, "}\n");
+ fprintf(outf, "}\n\n");
return 0;
}
@@ -180,7 +439,9 @@ static int output_interface(struct genbind_node *genbind,
int ifacenamelen;
struct genbind_node *binding_node;
struct interface_map_entry *inherite;
+ int res = 0;
+ /* compute clas name */
interfacee->class_name = gen_class_name(interfacee);
/* generate source filename */
@@ -198,15 +459,15 @@ static int output_interface(struct genbind_node *genbind,
/* find parent interface entry */
inherite = interface_map_inherit_entry(interface_map, interfacee);
- /* nsgenbind preamble */
- fprintf(ifacef, "%s\n", NSGENBIND_PREAMBLE);
-
binding_node = genbind_node_find_type(genbind, NULL,
GENBIND_NODE_TYPE_BINDING);
/* binding preface */
output_cdata(ifacef, binding_node, GENBIND_NODE_TYPE_PREFACE);
+ /* nsgenbind preamble */
+ fprintf(ifacef, "\n%s\n", NSGENBIND_PREAMBLE);
+
/* class preface */
output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PREFACE);
@@ -216,14 +477,24 @@ static int output_interface(struct genbind_node *genbind,
/* class prologue */
output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PROLOGUE);
+ fprintf(ifacef, "\n");
+
/* initialisor */
- //output_interface_init();
+ res = output_interface_init(ifacef, interfacee, inherite);
+ if (res != 0) {
+ goto op_error;
+ }
/* finaliser */
output_interface_fini(ifacef, interfacee, inherite);
/* constructor */
+ output_interface_constructor(ifacef, interfacee);
+
/* destructor */
+ output_interface_destructor(ifacef, interfacee);
+
+ fprintf(ifacef, "\n");
/* class epilogue */
output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_EPILOGUE);
@@ -237,9 +508,10 @@ static int output_interface(struct genbind_node *genbind,
/* binding postface */
output_cdata(ifacef, binding_node, GENBIND_NODE_TYPE_POSTFACE);
+op_error:
fclose(ifacef);
- return 0;
+ return res;
}
int duk_libdom_output(struct genbind_node *genbind,