Gitweb links:
...log
http://git.netsurf-browser.org/nsgenbind.git/shortlog/b0f64cff2c94d1a2085...
...commit
http://git.netsurf-browser.org/nsgenbind.git/commit/b0f64cff2c94d1a208528...
...tree
http://git.netsurf-browser.org/nsgenbind.git/tree/b0f64cff2c94d1a208528e2...
The branch, master has been updated
via b0f64cff2c94d1a208528e2ed91c15ab037dbbb1 (commit)
from 56eee21ccb63cb7f040c5ce07bc226fbd229330d (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=b0f64cff2c94d1a20...
commit b0f64cff2c94d1a208528e2ed91c15ab037dbbb1
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
split up duk-libdom generation source as it had grown unweildy
diff --git a/src/Makefile b/src/Makefile
index 9905baf..3ecfbe1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2,7 +2,8 @@ CFLAGS := $(CFLAGS) -I$(BUILDDIR) -Isrc/ -g -DYYENABLE_NLS=0
# Sources in this directory
DIR_SOURCES := nsgenbind.c utils.c webidl-ast.c nsgenbind-ast.c ir.c \
- duk-libdom.c
+ duk-libdom.c duk-libdom-interface.c duk-libdom-dictionary.c duk-libdom-common.c
+
# jsapi-libdom.c jsapi-libdom-function.c jsapi-libdom-property.c jsapi-libdom-init.c
jsapi-libdom-new.c jsapi-libdom-infmap.c jsapi-libdom-jsclass.c
SOURCES := $(SOURCES) $(BUILDDIR)/nsgenbind-parser.c $(BUILDDIR)/nsgenbind-lexer.c
$(BUILDDIR)/webidl-parser.c $(BUILDDIR)/webidl-lexer.c
diff --git a/src/duk-libdom-common.c b/src/duk-libdom-common.c
new file mode 100644
index 0000000..9a0f660
--- /dev/null
+++ b/src/duk-libdom-common.c
@@ -0,0 +1,78 @@
+/* duktape binding generation implementation
+ *
+ * This file is part of nsgenbind.
+ * Licensed under the MIT License,
+ *
http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2015 Vincent Sanders <vince(a)netsurf-browser.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "options.h"
+#include "utils.h"
+#include "nsgenbind-ast.h"
+#include "webidl-ast.h"
+#include "ir.h"
+#include "duk-libdom.h"
+
+#define NSGENBIND_PREFACE \
+ "/* Generated by nsgenbind\n" \
+ " *\n" \
+ " * nsgenbind is published under the MIT Licence.\n" \
+ " * nsgenbind is similar to a compiler is a purely transformative tool
which\n" \
+ " * explicitly makes no copyright claim on this generated output\n" \
+ " */"
+
+/* exported interface documented in duk-libdom.h */
+int output_tool_preface(FILE* outf)
+{
+ fprintf(outf, "%s\n", NSGENBIND_PREFACE);
+
+ return 0;
+}
+
+/* exported interface documented in duk-libdom.h */
+int output_cdata(FILE* outf,
+ struct genbind_node *node,
+ enum genbind_node_type nodetype)
+{
+ char *cdata;
+ int res = 0;
+
+ cdata = genbind_node_gettext(
+ genbind_node_find_type(
+ genbind_node_getnode(node),
+ NULL, nodetype));
+ if (cdata != NULL) {
+ fprintf(outf, "%s", cdata);
+ res = 1;
+ }
+ return res;
+}
+
+/* exported interface documented in duk-libdom.h */
+int output_tool_prologue(FILE* outf)
+{
+ char *fpath;
+
+ fpath = genb_fpath("binding.h");
+ fprintf(outf, "\n#include \"%s\"\n", fpath);
+ free(fpath);
+
+ fpath = genb_fpath("private.h");
+ fprintf(outf, "#include \"%s\"\n", fpath);
+ free(fpath);
+
+ fpath = genb_fpath("prototype.h");
+ fprintf(outf, "#include \"%s\"\n", fpath);
+ free(fpath);
+
+ return 0;
+}
diff --git a/src/duk-libdom-dictionary.c b/src/duk-libdom-dictionary.c
new file mode 100644
index 0000000..275855e
--- /dev/null
+++ b/src/duk-libdom-dictionary.c
@@ -0,0 +1,571 @@
+/* duktape binding generation implementation
+ *
+ * This file is part of nsgenbind.
+ * Licensed under the MIT License,
+ *
http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2012 Vincent Sanders <vince(a)netsurf-browser.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "options.h"
+#include "utils.h"
+#include "nsgenbind-ast.h"
+#include "webidl-ast.h"
+#include "ir.h"
+#include "duk-libdom.h"
+
+/** prefix for all generated functions */
+#define DLPFX "dukky"
+
+#define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_"
+
+/**
+ * Output code to create a private structure
+ *
+ */
+static int output_create_private(FILE* outf, char *class_name)
+{
+ fprintf(outf, "\t/* create private data and attach to instance */\n");
+ 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, %s_magic_string_private);\n\n",
+ DLPFX);
+
+ return 0;
+}
+
+/**
+ * generate code that gets a private pointer
+ */
+static int output_safe_get_private(FILE* outf, char *class_name, int idx)
+{
+ fprintf(outf,
+ "\t%s_private_t *priv;\n", class_name);
+ fprintf(outf,
+ "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n",
+ idx, DLPFX);
+ fprintf(outf,
+ "\tpriv = duk_get_pointer(ctx, -1);\n");
+ fprintf(outf,
+ "\tduk_pop(ctx);\n");
+ fprintf(outf,
+ "\tif (priv == NULL) return 0;\n\n");
+
+ return 0;
+}
+
+
+/**
+ * generate the dictionary constructor
+ */
+static int
+output_dictionary_constructor(FILE* outf, struct ir_entry *dictionarye)
+{
+ int init_argc;
+
+ /* constructor definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n",
+ DLPFX, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ output_create_private(outf, dictionarye->class_name);
+
+ /* generate call to initialisor */
+ fprintf(outf,
+ "\t%s_%s___init(ctx, priv",
+ DLPFX, dictionarye->class_name);
+ for (init_argc = 1;
+ init_argc <= dictionarye->class_init_argc;
+ init_argc++) {
+ fprintf(outf, ", duk_get_pointer(ctx, %d)", init_argc);
+ }
+ fprintf(outf, ");\n");
+
+
+ fprintf(outf, "\tduk_set_top(ctx, 1);\n");
+ fprintf(outf, "\treturn 1;\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate a duktape prototype name
+ */
+static char *get_prototype_name(const char *dictionary_name)
+{
+ char *proto_name;
+ int pnamelen;
+ int pfxlen;
+
+ /* duplicate the dictionary name in upper case */
+ pfxlen = SLEN(MAGICPFX) + SLEN("PROTOTYPE_");
+ pnamelen = strlen(dictionary_name) + 1;
+
+ proto_name = malloc(pnamelen + pfxlen);
+ snprintf(proto_name, pnamelen + pfxlen, "%sPROTOTYPE_%s", MAGICPFX,
dictionary_name);
+ for (pnamelen-- ; pnamelen >= 0; pnamelen--) {
+ proto_name[pnamelen + pfxlen] = toupper(dictionary_name[pnamelen]);
+ }
+ return proto_name;
+}
+
+
+/**
+ * generate code that gets a prototype by name
+ */
+static int output_get_prototype(FILE* outf, const char *dictionary_name)
+{
+ char *proto_name;
+
+ proto_name = get_prototype_name(dictionary_name);
+
+ fprintf(outf,
+ "\t/* get prototype */\n");
+ fprintf(outf,
+ "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n",
+ DLPFX);
+ fprintf(outf,
+ "\tduk_get_prop_string(ctx, -1, \"%s\");\n",
+ proto_name);
+ fprintf(outf,
+ "\tduk_replace(ctx, -2);\n");
+
+ free(proto_name);
+
+ return 0;
+}
+
+
+/**
+ * generate code that sets a destructor in a prototype
+ */
+static int output_set_destructor(FILE* outf, char *class_name, int idx)
+{
+ fprintf(outf, "\t/* Set the destructor */\n");
+ fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
+ fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___destructor, 1);\n",
+ DLPFX, class_name);
+ fprintf(outf, "\tduk_set_finalizer(ctx, -2);\n");
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+/**
+ * generate code that sets a constructor in a prototype
+ */
+static int
+output_set_constructor(FILE* outf, char *class_name, int idx, int argc)
+{
+ fprintf(outf, "\t/* Set the constructor */\n");
+ fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
+ fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___constructor,
%d);\n",
+ DLPFX, class_name, 1 + argc);
+ fprintf(outf, "\tduk_put_prop_string(ctx, -2,
\"%sINIT\");\n",
+ MAGICPFX);
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+/**
+ * generate the dictionary prototype creator
+ */
+static int
+output_dictionary_prototype(FILE* outf,
+ struct ir *ir,
+ struct ir_entry *dictionarye,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *proto_node;
+
+ /* find the prototype method on the class */
+ proto_node = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_PROTOTYPE);
+
+ /* prototype definition */
+ fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx)\n",
+ DLPFX, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ /* Output any binding data first */
+ if (output_cdata(outf, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) {
+ fprintf(outf,"\n");
+ }
+
+ /* generate prototype chaining if dictionary has a parent */
+ if (inherite != NULL) {
+ fprintf(outf,
+ "\t/* Set this prototype's prototype (left-parent)
*/\n");
+ output_get_prototype(outf, inherite->name);
+ fprintf(outf, "\tduk_set_prototype(ctx, 0);\n\n");
+ }
+
+ /* dictionary members*/
+
+
+ /* generate setting of destructor */
+ output_set_destructor(outf, dictionarye->class_name, 0);
+
+ /* generate setting of constructor */
+ output_set_constructor(outf,
+ dictionarye->class_name,
+ 0,
+ dictionarye->class_init_argc);
+
+ fprintf(outf,"\treturn 1; /* The prototype object */\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate the dictionary destructor
+ */
+static int
+output_dictionary_destructor(FILE* outf, struct ir_entry *dictionarye)
+{
+ /* destructor definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n",
+ DLPFX, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ output_safe_get_private(outf, dictionarye->class_name, 0);
+
+ /* generate call to finaliser */
+ fprintf(outf,
+ "\t%s_%s___fini(ctx, priv);\n",
+ DLPFX, dictionarye->class_name);
+
+ fprintf(outf,"\tfree(priv);\n");
+ fprintf(outf,"\treturn 0;\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate an initialisor call to parent dictionary
+ */
+static int
+output_dictionary_inherit_init(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct ir_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 = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+
+ inh_init_node = genbind_node_find_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\" (dictionary %s)
parent class \"%s\" (dictionary %s) initialisor requires a parameter
\"%s\" with compatible identifier\n",
+ dictionarye->class_name,
+ dictionarye->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_dictionary_init_declaration(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct genbind_node *init_node)
+{
+ struct genbind_node *param_node;
+
+ fprintf(outf,
+ "void %s_%s___init(duk_context *ctx, %s_private_t *priv",
+ DLPFX, dictionarye->class_name, dictionarye->class_name);
+
+ /* count the number of arguments on the initializer */
+ dictionarye->class_init_argc = 0;
+
+ /* 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) {
+ dictionarye->class_init_argc++;
+ 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_PARAMETER);
+ }
+
+ fprintf(outf,")");
+
+ return 0;
+}
+
+static int
+output_dictionary_init(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *init_node;
+ int res;
+
+ /* find the initialisor method on the class (if any) */
+ init_node = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+ /* initialisor definition */
+ output_dictionary_init_declaration(outf, dictionarye, init_node);
+
+ fprintf(outf,"\n{\n");
+
+ /* if this dictionary inherits ensure we call its initialisor */
+ res = output_dictionary_inherit_init(outf, dictionarye, 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_dictionary_fini(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *fini_node;
+
+ /* find the finaliser method on the class (if any) */
+ fini_node = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_FINI);
+
+ /* finaliser definition */
+ fprintf(outf,
+ "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n",
+ DLPFX, dictionarye->class_name, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ /* generate log statement */
+ if (options->dbglog) {
+ fprintf(outf,
+ "\tLOG(\"Finalise %%p\", duk_get_heapptr(ctx,
0));\n" );
+ }
+
+ /* output the finialisor code from the binding */
+ output_cdata(outf, fini_node, GENBIND_NODE_TYPE_CDATA);
+
+ /* if this dictionary inherits ensure we call its finaliser */
+ if (inherite != NULL) {
+ fprintf(outf,
+ "\t%s_%s___fini(ctx, &priv->parent);\n",
+ DLPFX, inherite->class_name);
+ }
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+
+/**
+ * generate a source file to implement a dictionary using duk and libdom.
+ */
+int output_dictionary(struct ir *ir, struct ir_entry *dictionarye)
+{
+ FILE *ifacef;
+ struct ir_entry *inherite;
+ int res = 0;
+
+ /* open output file */
+ ifacef = genb_fopen_tmp(dictionarye->filename);
+ if (ifacef == NULL) {
+ return -1;
+ }
+
+ /* find parent dictionary entry */
+ inherite = ir_inherit_entry(ir, dictionarye);
+
+ /* tool preface */
+ output_tool_preface(ifacef);
+
+ /* binding preface */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_PREFACE);
+
+ /* class preface */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PREFACE);
+
+ /* tool prologue */
+ output_tool_prologue(ifacef);
+
+ /* binding prologue */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_PROLOGUE);
+
+ /* class prologue */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PROLOGUE);
+
+ fprintf(ifacef, "\n");
+
+ /* initialisor */
+ res = output_dictionary_init(ifacef, dictionarye, inherite);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /* finaliser */
+ res = output_dictionary_fini(ifacef, dictionarye, inherite);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /* constructor */
+ res = output_dictionary_constructor(ifacef, dictionarye);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /* destructor */
+ res = output_dictionary_destructor(ifacef, dictionarye);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /** todo property handlers */
+
+ /* prototype */
+ res = output_dictionary_prototype(ifacef, ir, dictionarye, inherite);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ fprintf(ifacef, "\n");
+
+ /* class epilogue */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_EPILOGUE);
+
+ /* binding epilogue */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_EPILOGUE);
+
+ /* class postface */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_POSTFACE);
+
+ /* binding postface */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_POSTFACE);
+
+op_error:
+ genb_fclose_tmp(ifacef, dictionarye->filename);
+
+ return res;
+}
diff --git a/src/duk-libdom-interface.c b/src/duk-libdom-interface.c
new file mode 100644
index 0000000..7501bea
--- /dev/null
+++ b/src/duk-libdom-interface.c
@@ -0,0 +1,1334 @@
+/* duktape binding generation implementation
+ *
+ * This file is part of nsgenbind.
+ * Licensed under the MIT License,
+ *
http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2012 Vincent Sanders <vince(a)netsurf-browser.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "options.h"
+#include "utils.h"
+#include "nsgenbind-ast.h"
+#include "webidl-ast.h"
+#include "ir.h"
+#include "duk-libdom.h"
+
+/** prefix for all generated functions */
+#define DLPFX "dukky"
+
+#define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_"
+
+/**
+ * Output code to create a private structure
+ *
+ */
+static int output_create_private(FILE* outf, char *class_name)
+{
+ fprintf(outf, "\t/* create private data and attach to instance */\n");
+ 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, %s_magic_string_private);\n\n",
+ DLPFX);
+
+ return 0;
+}
+
+/**
+ * generate code that gets a private pointer
+ */
+static int output_safe_get_private(FILE* outf, char *class_name, int idx)
+{
+ fprintf(outf,
+ "\t%s_private_t *priv;\n", class_name);
+ fprintf(outf,
+ "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n",
+ idx, DLPFX);
+ fprintf(outf,
+ "\tpriv = duk_get_pointer(ctx, -1);\n");
+ fprintf(outf,
+ "\tduk_pop(ctx);\n");
+ fprintf(outf,
+ "\tif (priv == NULL) return 0;\n\n");
+
+ return 0;
+}
+
+
+/**
+ * generate a duktape prototype name
+ */
+static char *get_prototype_name(const char *interface_name)
+{
+ char *proto_name;
+ int pnamelen;
+ int pfxlen;
+
+ /* duplicate the interface name in upper case */
+ pfxlen = SLEN(MAGICPFX) + SLEN("PROTOTYPE_");
+ pnamelen = strlen(interface_name) + 1;
+
+ proto_name = malloc(pnamelen + pfxlen);
+ snprintf(proto_name, pnamelen + pfxlen, "%sPROTOTYPE_%s", MAGICPFX,
interface_name);
+ for (pnamelen-- ; pnamelen >= 0; pnamelen--) {
+ proto_name[pnamelen + pfxlen] = toupper(interface_name[pnamelen]);
+ }
+ return proto_name;
+}
+
+
+/**
+ * generate code that gets a prototype by name
+ */
+static int output_get_prototype(FILE* outf, const char *interface_name)
+{
+ char *proto_name;
+
+ proto_name = get_prototype_name(interface_name);
+
+ fprintf(outf,
+ "\t/* get prototype */\n");
+ fprintf(outf,
+ "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n",
+ DLPFX);
+ fprintf(outf,
+ "\tduk_get_prop_string(ctx, -1, \"%s\");\n",
+ proto_name);
+ fprintf(outf,
+ "\tduk_replace(ctx, -2);\n");
+
+ free(proto_name);
+
+ return 0;
+}
+
+/**
+ * generate code that sets a destructor in a prototype
+ */
+static int output_set_destructor(FILE* outf, char *class_name, int idx)
+{
+ fprintf(outf, "\t/* Set the destructor */\n");
+ fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
+ fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___destructor, 1);\n",
+ DLPFX, class_name);
+ fprintf(outf, "\tduk_set_finalizer(ctx, -2);\n");
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+/**
+ * generate code that sets a constructor in a prototype
+ */
+static int
+output_set_constructor(FILE* outf, char *class_name, int idx, int argc)
+{
+ fprintf(outf, "\t/* Set the constructor */\n");
+ fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
+ fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___constructor,
%d);\n",
+ DLPFX, class_name, 1 + argc);
+ fprintf(outf, "\tduk_put_prop_string(ctx, -2,
\"%sINIT\");\n",
+ MAGICPFX);
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+static int
+output_dump_stack(FILE* outf)
+{
+ if (options->dbglog) {
+ /* dump stack */
+ fprintf(outf, "\tduk_push_context_dump(ctx);\n");
+ fprintf(outf, "\tLOG(\"Stack: %%s\", duk_to_string(ctx,
-1));\n");
+ fprintf(outf, "\tduk_pop(ctx);\n");
+ }
+ return 0;
+}
+
+/**
+ * generate code that adds a method in a prototype
+ */
+static int
+output_add_method(FILE* outf,
+ const char *class_name,
+ const char *method)
+{
+ 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, DUK_VARARGS);\n",
+ DLPFX, class_name, method);
+ output_dump_stack(outf);
+ 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;
+}
+
+/**
+ * Generate source to populate a read/write property on a prototype
+ */
+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);
+ output_dump_stack(outf);
+ fprintf(outf, "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\n");
+ fprintf(outf, "\t\tDUK_DEFPROP_HAVE_SETTER |\n");
+ fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE
|\n");
+ fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+/**
+ * Generate source to populate a readonly property on a prototype
+ */
+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);
+ output_dump_stack(outf);
+ fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER |\n");
+ fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE
|\n");
+ fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+/**
+ * Generate source to add a constant int value on a prototype
+ */
+static int
+output_prototype_constant_int(FILE *outf, const char *constant_name, int value)
+{
+ fprintf(outf, "\tduk_dup(ctx, 0);\n");
+ fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n",
constant_name);
+ fprintf(outf, "\tduk_push_int(ctx, %d);\n", value);
+ fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |\n");
+ fprintf(outf, "\t DUK_DEFPROP_HAVE_WRITABLE |
DUK_DEFPROP_HAVE_ENUMERABLE |\n");
+ fprintf(outf, "\t DUK_DEFPROP_ENUMERABLE |
DUK_DEFPROP_HAVE_CONFIGURABLE);\n");
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+ return 0;
+}
+
+/**
+ * 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,
%s_magic_string_private);\n",
+ DLPFX);
+ fprintf(outf, "\tpriv = duk_get_pointer(ctx, -1);\n");
+ fprintf(outf, "\tduk_pop_2(ctx);\n");
+ fprintf(outf, "\tif (priv == NULL) {\n");
+ if (options->dbglog) {
+ fprintf(outf, "\t\tLOG(\"priv failed\");\n");
+ }
+ fprintf(outf, "\t\treturn 0; /* can do? No can do. */\n");
+ fprintf(outf, "\t}\n\n");
+
+ return 0;
+}
+
+
+/**
+ * generate the interface constructor
+ */
+static int
+output_interface_constructor(FILE* outf, struct ir_entry *interfacee)
+{
+ int init_argc;
+
+ /* constructor definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name);
+ fprintf(outf,"{\n");
+
+ output_create_private(outf, interfacee->class_name);
+
+ /* generate call to initialisor */
+ fprintf(outf,
+ "\t%s_%s___init(ctx, priv",
+ DLPFX, interfacee->class_name);
+ for (init_argc = 1;
+ init_argc <= interfacee->class_init_argc;
+ init_argc++) {
+ fprintf(outf, ", duk_get_pointer(ctx, %d)", init_argc);
+ }
+ fprintf(outf, ");\n");
+
+
+ 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 ir_entry *interfacee)
+{
+ /* destructor definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name);
+ fprintf(outf,"{\n");
+
+ output_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 ir_entry *interfacee,
+ struct ir_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 = genbind_node_find_method(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+
+ inh_init_node = genbind_node_find_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_declaration(FILE* outf,
+ struct ir_entry *interfacee,
+ struct genbind_node *init_node)
+{
+ struct genbind_node *param_node;
+
+ fprintf(outf,
+ "void %s_%s___init(duk_context *ctx, %s_private_t *priv",
+ DLPFX, interfacee->class_name, interfacee->class_name);
+
+ /* count the number of arguments on the initializer */
+ interfacee->class_init_argc = 0;
+
+ /* 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) {
+ interfacee->class_init_argc++;
+ 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_PARAMETER);
+ }
+
+ fprintf(outf,")");
+
+ return 0;
+}
+
+static int
+output_interface_init(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *init_node;
+ int res;
+
+ /* find the initialisor method on the class (if any) */
+ init_node = genbind_node_find_method(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+ /* initialisor definition */
+ output_interface_init_declaration(outf, interfacee, init_node);
+
+ 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 ir_entry *interfacee,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *fini_node;
+
+ /* find the finaliser method on the class (if any) */
+ fini_node = genbind_node_find_method(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_FINI);
+
+ /* finaliser definition */
+ fprintf(outf,
+ "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n",
+ DLPFX, interfacee->class_name, interfacee->class_name);
+ fprintf(outf,"{\n");
+
+ /* generate log statement */
+ if (options->dbglog) {
+ fprintf(outf,
+ "\tLOG(\"Finalise %%p\", duk_get_heapptr(ctx,
0));\n" );
+ }
+
+ /* 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 */
+ if (inherite != NULL) {
+ fprintf(outf,
+ "\t%s_%s___fini(ctx, &priv->parent);\n",
+ DLPFX, inherite->class_name);
+ }
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+
+/**
+ * generate a prototype add for a single class method
+ */
+static int
+output_prototype_method(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_operation_entry *operatione)
+{
+
+ if (operatione->name != NULL) {
+ /* normal method on prototype */
+ output_add_method(outf,
+ interfacee->class_name,
+ operatione->name);
+ } else {
+ /* special method on prototype */
+ fprintf(outf,
+ "\t/* Special method on prototype - UNIMPLEMENTED
*/\n\n");
+ }
+
+ return 0;
+}
+
+/**
+ * generate prototype method definitions
+ */
+static int
+output_prototype_methods(FILE *outf, struct ir_entry *entry)
+{
+ int opc;
+ int res = 0;
+
+ for (opc = 0; opc < entry->u.interface.operationc; opc++) {
+ res = output_prototype_method(
+ outf,
+ entry,
+ entry->u.interface.operationv + opc);
+ if (res != 0) {
+ break;
+ }
+ }
+
+ return res;
+}
+
+
+static int
+output_prototype_attribute(FILE *outf,
+ struct ir_entry *interfacee,
+ struct ir_attribute_entry *attributee)
+{
+ if (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) {
+ return output_populate_ro_property(outf,
+ interfacee->class_name,
+ attributee->name);
+ }
+ return output_populate_rw_property(outf,
+ interfacee->class_name,
+ attributee->name);
+}
+
+/**
+ * generate prototype attribute definitions
+ */
+static int
+output_prototype_attributes(FILE *outf, struct ir_entry *entry)
+{
+ int attrc;
+ int res = 0;
+
+ for (attrc = 0; attrc < entry->u.interface.attributec; attrc++) {
+ res = output_prototype_attribute(
+ outf,
+ entry,
+ entry->u.interface.attributev + attrc);
+ if (res != 0) {
+ break;
+ }
+ }
+
+ return res;
+}
+
+/**
+ * output constants on the prototype
+ *
+ * \todo This implementation assumes the constant is a literal int and should
+ * check the type node base value.
+ */
+static int
+output_prototype_constant(FILE *outf,
+ struct ir_constant_entry *constante)
+{
+ int *value;
+
+ value = webidl_node_getint(
+ webidl_node_find_type(
+ webidl_node_getnode(constante->node),
+ NULL,
+ WEBIDL_NODE_TYPE_LITERAL_INT));
+
+ output_prototype_constant_int(outf, constante->name, *value);
+
+ return 0;
+}
+
+/**
+ * generate prototype constant definitions
+ */
+static int
+output_prototype_constants(FILE *outf, struct ir_entry *entry)
+{
+ int attrc;
+ int res = 0;
+
+ for (attrc = 0; attrc < entry->u.interface.constantc; attrc++) {
+ res = output_prototype_constant(
+ outf,
+ entry->u.interface.constantv + attrc);
+ if (res != 0) {
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+output_global_create_prototype(FILE* outf,
+ struct ir *ir,
+ struct ir_entry *interfacee)
+{
+ int idx;
+
+ fprintf(outf, "\t/* Create interface objects */\n");
+ for (idx = 0; idx < ir->entryc; idx++) {
+ struct ir_entry *entry;
+
+ entry = ir->entries + idx;
+
+ if (entry->type == IR_ENTRY_TYPE_INTERFACE) {
+
+ if (entry->u.interface.noobject) {
+ continue;
+ }
+
+ if (entry == interfacee) {
+ fprintf(outf, "\tduk_dup(ctx, 0);\n");
+ } else {
+ output_get_prototype(outf, entry->name);
+ }
+
+ fprintf(outf,
+ "\tdukky_inject_not_ctr(ctx, 0,
\"%s\");\n",
+ entry->name);
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * generate the interface prototype creator
+ */
+static int
+output_interface_prototype(FILE* outf,
+ struct ir *ir,
+ struct ir_entry *interfacee,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *proto_node;
+
+ /* find the prototype method on the class */
+ proto_node = genbind_node_find_method(interfacee->class,
+ NULL,
+ GENBIND_METHOD_TYPE_PROTOTYPE);
+
+ /* prototype definition */
+ fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name);
+ fprintf(outf,"{\n");
+
+ /* Output any binding data first */
+ if (output_cdata(outf, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) {
+ fprintf(outf,"\n");
+ }
+
+ /* generate prototype chaining if interface has a parent */
+ if (inherite != NULL) {
+ fprintf(outf,
+ "\t/* Set this prototype's prototype (left-parent)
*/\n");
+ output_get_prototype(outf, inherite->name);
+ 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 constants */
+ output_prototype_constants(outf, interfacee);
+
+ /* if this is the global object, output all interfaces which do not
+ * prevent us from doing so
+ */
+ if (interfacee->u.interface.primary_global) {
+ output_global_create_prototype(outf, ir, interfacee);
+ }
+
+ /* generate setting of destructor */
+ output_set_destructor(outf, interfacee->class_name, 0);
+
+ /* generate setting of constructor */
+ output_set_constructor(outf,
+ interfacee->class_name,
+ 0,
+ interfacee->class_init_argc);
+
+ fprintf(outf,"\treturn 1; /* The prototype object */\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate a single class method for an interface operation with elipsis
+ */
+static int
+output_interface_elipsis_operation(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_operation_entry *operatione)
+{
+ int cdatac; /* cdata blocks output */
+
+ /* overloaded method definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name, operatione->name);
+ fprintf(outf,"{\n");
+
+ /**
+ * \todo This is where the checking of the parameters to the
+ * operation with elipsis should go
+ */
+ WARN(WARNING_UNIMPLEMENTED,
+ "Elipsis parameetrs not checked: method %s::%s();",
+ interfacee->name, operatione->name);
+
+ output_get_method_private(outf, interfacee->class_name);
+
+ cdatac = output_cdata(outf,
+ operatione->method,
+ GENBIND_NODE_TYPE_CDATA);
+
+ if (cdatac == 0) {
+ /* no implementation so generate default */
+ WARN(WARNING_UNIMPLEMENTED,
+ "Unimplemented: method %s::%s();",
+ interfacee->name, operatione->name);
+ fprintf(outf,"\treturn 0;\n");
+ }
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate a single class method for an interface overloaded operation
+ */
+static int
+output_interface_overloaded_operation(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_operation_entry *operatione)
+{
+ int cdatac; /* cdata blocks output */
+
+ /* overloaded method definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name, operatione->name);
+ fprintf(outf,"{\n");
+
+ /** \todo This is where the checking of the parameters to the
+ * overloaded operation should go
+ */
+
+ output_get_method_private(outf, interfacee->class_name);
+
+ cdatac = output_cdata(outf,
+ operatione->method,
+ GENBIND_NODE_TYPE_CDATA);
+
+ if (cdatac == 0) {
+ /* no implementation so generate default */
+ WARN(WARNING_UNIMPLEMENTED,
+ "Unimplemented: method %s::%s();",
+ interfacee->name, operatione->name);
+ fprintf(outf,"\treturn 0;\n");
+ }
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate a single class method for an interface special operation
+ */
+static int
+output_interface_special_operation(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_operation_entry *operatione)
+{
+ /* special method definition */
+ fprintf(outf, "/* Special method definition - UNIMPLEMENTED */\n\n");
+
+ WARN(WARNING_UNIMPLEMENTED,
+ "Special operation on interface %s (operation entry %p)",
+ interfacee->name,
+ operatione);
+
+ return 0;
+}
+
+/**
+ * generate default values on the duk stack
+ */
+static int
+output_operation_optional_defaults(FILE* outf,
+ struct ir_operation_argument_entry *argumentv,
+ int argumentc)
+{
+ int argc;
+ for (argc = 0; argc < argumentc; argc++) {
+ struct ir_operation_argument_entry *cure;
+ struct webidl_node *lit_node; /* literal node */
+ enum webidl_node_type lit_type;
+ int *lit_int;
+ char *lit_str;
+
+ cure = argumentv + argc;
+
+ lit_node = webidl_node_getnode(
+ webidl_node_find_type(
+ webidl_node_getnode(cure->node),
+ NULL,
+ WEBIDL_NODE_TYPE_OPTIONAL));
+
+ if (lit_node != NULL) {
+
+ lit_type = webidl_node_gettype(lit_node);
+
+ switch (lit_type) {
+ case WEBIDL_NODE_TYPE_LITERAL_NULL:
+ fprintf(outf,
+ "\t\tduk_push_null(ctx);\n");
+ break;
+
+ case WEBIDL_NODE_TYPE_LITERAL_INT:
+ lit_int = webidl_node_getint(lit_node);
+ fprintf(outf,
+ "\t\tduk_push_int(ctx, %d);\n",
+ *lit_int);
+ break;
+
+ case WEBIDL_NODE_TYPE_LITERAL_BOOL:
+ lit_int = webidl_node_getint(lit_node);
+ fprintf(outf,
+ "\t\tduk_push_boolean(ctx, %d);\n",
+ *lit_int);
+ break;
+
+ case WEBIDL_NODE_TYPE_LITERAL_STRING:
+ lit_str = webidl_node_gettext(lit_node);
+ fprintf(outf,
+ "\t\tduk_push_string(ctx,
\"%s\");\n",
+ lit_str);
+ break;
+
+ case WEBIDL_NODE_TYPE_LITERAL_FLOAT:
+ default:
+ fprintf(outf,
+ "\t\tduk_push_undefined(ctx);\n");
+ break;
+ }
+ } else {
+ fprintf(outf, "\t\tduk_push_undefined(ctx);\n");
+ }
+ }
+ return 0;
+}
+
+static int
+output_operation_argument_type_check(
+ FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_operation_entry *operatione,
+ struct ir_operation_overload_entry *overloade,
+ int argidx)
+{
+ struct ir_operation_argument_entry *argumente;
+ struct webidl_node *type_node;
+ enum webidl_type *argument_type;
+
+ argumente = overloade->argumentv + argidx;
+
+ type_node = webidl_node_find_type(
+ webidl_node_getnode(argumente->node),
+ NULL,
+ WEBIDL_NODE_TYPE_TYPE);
+
+ if (type_node == NULL) {
+ fprintf(stderr, "%s:%s %dth argument %s has no type\n",
+ interfacee->name,
+ operatione->name,
+ argidx,
+ argumente->name);
+ return -1;
+ }
+
+ argument_type = (enum webidl_type *)webidl_node_getint(
+ webidl_node_find_type(
+ webidl_node_getnode(type_node),
+ NULL,
+ WEBIDL_NODE_TYPE_TYPE_BASE));
+
+ if (argument_type == NULL) {
+ fprintf(stderr,
+ "%s:%s %dth argument %s has no type base\n",
+ interfacee->name,
+ operatione->name,
+ argidx,
+ argumente->name);
+ return -1;
+ }
+
+ if (*argument_type == WEBIDL_TYPE_ANY) {
+ /* allowing any type needs no check */
+ return 0;
+ }
+
+ fprintf(outf, "\tif (%s_argc > %d) {\n", DLPFX, argidx);
+
+ switch (*argument_type) {
+ case WEBIDL_TYPE_STRING:
+ fprintf(outf,
+ "\t\tif (!duk_is_string(ctx, %d)) {\n"
+ "\t\t\tduk_error(ctx, DUK_ERR_ERROR,
%s_error_fmt_string_type, %d, \"%s\");\n"
+ "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
+ break;
+
+ case WEBIDL_TYPE_BOOL:
+ fprintf(outf,
+ "\t\tif (!duk_is_boolean(ctx, %d)) {\n"
+ "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_bool_type,
%d, \"%s\");\n"
+ "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
+ break;
+
+ case WEBIDL_TYPE_FLOAT:
+ case WEBIDL_TYPE_DOUBLE:
+ case WEBIDL_TYPE_SHORT:
+ case WEBIDL_TYPE_LONG:
+ case WEBIDL_TYPE_LONGLONG:
+ fprintf(outf,
+ "\t\tif (!duk_is_number(ctx, %d)) {\n"
+ "\t\t\tduk_error(ctx, DUK_ERR_ERROR,
%s_error_fmt_number_type, %d, \"%s\");\n"
+ "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
+ break;
+
+
+ default:
+ fprintf(outf,
+ "\t\t/* unhandled type check */\n");
+ }
+
+ fprintf(outf, "\t}\n");
+
+ return 0;
+}
+
+
+/**
+ * generate a single class method for an interface operation
+ */
+static int
+output_interface_operation(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_operation_entry *operatione)
+{
+ int cdatac; /* cdata blocks output */
+ struct ir_operation_overload_entry *overloade;
+ int fixedargc; /* number of non optional arguments */
+ int argidx; /* loop counter for arguments */
+ int optargc; /* loop counter for optional arguments */
+
+ if (operatione->name == NULL) {
+ return output_interface_special_operation(outf,
+ interfacee,
+ operatione);
+ }
+
+ if (operatione->overloadc != 1) {
+ return output_interface_overloaded_operation(outf,
+ interfacee,
+ operatione);
+ }
+
+ if (operatione->overloadv->elipsisc != 0) {
+ return output_interface_elipsis_operation(outf,
+ interfacee,
+ operatione);
+ }
+
+ /* normal method definition */
+ overloade = operatione->overloadv;
+
+ fprintf(outf,
+ "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
+ DLPFX, interfacee->class_name, operatione->name);
+ fprintf(outf,"{\n");
+
+ /* check arguments */
+
+ /* generate check for minimum number of parameters */
+
+ fixedargc = overloade->argumentc - overloade->optionalc;
+
+ fprintf(outf,
+ "\t/* ensure the parameters are present */\n"
+ "\tduk_idx_t %s_argc = duk_get_top(ctx);\n\t", DLPFX);
+
+ if (fixedargc > 0) {
+ fprintf(outf,
+ "if (%s_argc < %d) {\n"
+ "\t\t/* not enough arguments */\n"
+ "\t\tduk_error(ctx, DUK_RET_TYPE_ERROR,
%s_error_fmt_argument, %d, %s_argc);\n"
+ "\t} else ",
+ DLPFX,
+ fixedargc,
+ DLPFX,
+ fixedargc,
+ DLPFX);
+ }
+
+ for (optargc = fixedargc;
+ optargc < overloade->argumentc;
+ optargc++) {
+ fprintf(outf,
+ "if (%s_argc == %d) {\n"
+ "\t\t/* %d optional arguments need adding */\n",
+ DLPFX,
+ optargc,
+ overloade->argumentc - optargc);
+ output_operation_optional_defaults(outf,
+ overloade->argumentv + optargc,
+ overloade->argumentc - optargc);
+ fprintf(outf,
+ "\t} else ");
+ }
+
+ fprintf(outf,
+ "if (%s_argc > %d) {\n"
+ "\t\t/* remove extraneous parameters */\n"
+ "\t\tduk_set_top(ctx, %d);\n"
+ "\t}\n",
+ DLPFX,
+ overloade->argumentc,
+ overloade->argumentc);
+ fprintf(outf, "\n");
+
+ /* generate argument type checks */
+
+ fprintf(outf, "\t/* check types of passed arguments are correct
*/\n");
+
+ for (argidx = 0; argidx < overloade->argumentc; argidx++) {
+ output_operation_argument_type_check(outf,
+ interfacee,
+ operatione,
+ overloade,
+ argidx);
+ }
+
+ output_get_method_private(outf, interfacee->class_name);
+
+ cdatac = output_cdata(outf,
+ operatione->method,
+ GENBIND_NODE_TYPE_CDATA);
+
+ if (cdatac == 0) {
+ /* no implementation so generate default */
+ WARN(WARNING_UNIMPLEMENTED,
+ "Unimplemented: method %s::%s();",
+ interfacee->name, operatione->name);
+ 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 ir_entry *ife)
+{
+ int opc;
+ int res = 0;
+
+ for (opc = 0; opc < ife->u.interface.operationc; opc++) {
+ res = output_interface_operation(
+ outf,
+ ife,
+ ife->u.interface.operationv + opc);
+ if (res != 0) {
+ break;
+ }
+ }
+
+ return res;
+}
+
+/**
+ * Generate class property getter/setter for a single attribute
+ */
+static int
+output_interface_attribute(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_attribute_entry *atributee)
+{
+ int cdatac;
+
+ /* 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);
+
+ cdatac = output_cdata(outf, atributee->getter, GENBIND_NODE_TYPE_CDATA);
+
+ if (cdatac == 0) {
+ WARN(WARNING_UNIMPLEMENTED,
+ "Unimplemented: getter %s::%s();",
+ interfacee->name, atributee->name);
+
+ /* no implementation so generate default */
+ 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);
+
+ cdatac = output_cdata(outf, atributee->setter, GENBIND_NODE_TYPE_CDATA);
+
+ if (cdatac == 0) {
+ WARN(WARNING_UNIMPLEMENTED,
+ "Unimplemented: setter %s::%s();",
+ interfacee->name, atributee->name);
+
+ /* no implementation so generate default */
+ 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 ir_entry *ife)
+{
+ int attrc;
+
+ for (attrc = 0; attrc < ife->u.interface.attributec; attrc++) {
+ output_interface_attribute(
+ outf,
+ ife,
+ ife->u.interface.attributev + attrc);
+ }
+
+ return 0;
+}
+
+
+/* exported interface documented in duk-libdom.h */
+int output_interface(struct ir *ir, struct ir_entry *interfacee)
+{
+ FILE *ifacef;
+ struct ir_entry *inherite;
+ int res = 0;
+
+ /* open output file */
+ ifacef = genb_fopen_tmp(interfacee->filename);
+ if (ifacef == NULL) {
+ return -1;
+ }
+
+ /* find parent interface entry */
+ inherite = ir_inherit_entry(ir, interfacee);
+
+ /* tool preface */
+ output_tool_preface(ifacef);
+
+ /* binding preface */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_PREFACE);
+
+ /* class preface */
+ output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PREFACE);
+
+ /* tool prologue */
+ output_tool_prologue(ifacef);
+
+ /* binding prologue */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_PROLOGUE);
+
+ /* class prologue */
+ output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PROLOGUE);
+
+ fprintf(ifacef, "\n");
+
+ /* initialisor */
+ 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);
+
+ /* operations */
+ output_interface_operations(ifacef, interfacee);
+
+ /* attributes */
+ output_interface_attributes(ifacef, interfacee);
+
+ /* prototype */
+ output_interface_prototype(ifacef, ir, interfacee, inherite);
+
+ fprintf(ifacef, "\n");
+
+ /* class epilogue */
+ output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_EPILOGUE);
+
+ /* binding epilogue */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_EPILOGUE);
+
+ /* class postface */
+ output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_POSTFACE);
+
+ /* binding postface */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_POSTFACE);
+
+op_error:
+ genb_fclose_tmp(ifacef, interfacee->filename);
+
+ return res;
+}
+
diff --git a/src/duk-libdom.c b/src/duk-libdom.c
index 3e20d13..45e7e79 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom.c
@@ -3,7 +3,7 @@
* This file is part of nsgenbind.
* Licensed under the MIT License,
*
http://www.opensource.org/licenses/mit-license.php
- * Copyright 2012 Vincent Sanders <vince(a)netsurf-browser.org>
+ * Copyright 2015 Vincent Sanders <vince(a)netsurf-browser.org>
*/
#include <stdio.h>
@@ -27,53 +27,6 @@
#define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_"
-#define NSGENBIND_PREAMBLE \
- "/* Generated by nsgenbind\n" \
- " *\n" \
- " * nsgenbind is published under the MIT Licence.\n" \
- " * nsgenbind is similar to a compiler is a purely transformative tool
which\n" \
- " * explicitly makes no copyright claim on this generated output\n" \
- " */"
-
-/**
- * Output code to create a private structure
- *
- */
-static int output_create_private(FILE* outf, char *class_name)
-{
- fprintf(outf, "\t/* create private data and attach to instance */\n");
- 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, %s_magic_string_private);\n\n",
- DLPFX);
-
- return 0;
-}
-
-/**
- * generate code that gets a private pointer
- */
-static int output_safe_get_private(FILE* outf, char *class_name, int idx)
-{
- fprintf(outf,
- "\t%s_private_t *priv;\n", class_name);
- fprintf(outf,
- "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n",
- idx, DLPFX);
- fprintf(outf,
- "\tpriv = duk_get_pointer(ctx, -1);\n");
- fprintf(outf,
- "\tduk_pop(ctx);\n");
- fprintf(outf,
- "\tif (priv == NULL) return 0;\n\n");
-
- return 0;
-}
-
-
/**
* generate a duktape prototype name
*/
@@ -95,190 +48,6 @@ static char *get_prototype_name(const char *interface_name)
return proto_name;
}
-/**
- * generate code that gets a prototype by name
- */
-static int output_get_prototype(FILE* outf, const char *interface_name)
-{
- char *proto_name;
-
- proto_name = get_prototype_name(interface_name);
-
- fprintf(outf,
- "\t/* get prototype */\n");
- fprintf(outf,
- "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n",
- DLPFX);
- fprintf(outf,
- "\tduk_get_prop_string(ctx, -1, \"%s\");\n",
- proto_name);
- fprintf(outf,
- "\tduk_replace(ctx, -2);\n");
-
- free(proto_name);
-
- return 0;
-}
-
-/**
- * generate code that sets a destructor in a prototype
- */
-static int output_set_destructor(FILE* outf, char *class_name, int idx)
-{
- fprintf(outf, "\t/* Set the destructor */\n");
- fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
- fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___destructor, 1);\n",
- DLPFX, class_name);
- fprintf(outf, "\tduk_set_finalizer(ctx, -2);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-/**
- * generate code that sets a constructor in a prototype
- */
-static int
-output_set_constructor(FILE* outf, char *class_name, int idx, int argc)
-{
- fprintf(outf, "\t/* Set the constructor */\n");
- fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
- fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___constructor,
%d);\n",
- DLPFX, class_name, 1 + argc);
- fprintf(outf, "\tduk_put_prop_string(ctx, -2,
\"%sINIT\");\n",
- MAGICPFX);
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-static int
-output_dump_stack(FILE* outf)
-{
- if (options->dbglog) {
- /* dump stack */
- fprintf(outf, "\tduk_push_context_dump(ctx);\n");
- fprintf(outf, "\tLOG(\"Stack: %%s\", duk_to_string(ctx,
-1));\n");
- fprintf(outf, "\tduk_pop(ctx);\n");
- }
- return 0;
-}
-
-/**
- * generate code that adds a method in a prototype
- */
-static int
-output_add_method(FILE* outf,
- const char *class_name,
- const char *method)
-{
- 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, DUK_VARARGS);\n",
- DLPFX, class_name, method);
- output_dump_stack(outf);
- 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;
-}
-
-/**
- * Generate source to populate a read/write property on a prototype
- */
-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);
- output_dump_stack(outf);
- fprintf(outf, "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_SETTER |\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE
|\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-/**
- * Generate source to populate a readonly property on a prototype
- */
-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);
- output_dump_stack(outf);
- fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER |\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE
|\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-/**
- * Generate source to add a constant int value on a prototype
- */
-static int
-output_prototype_constant_int(FILE *outf, const char *constant_name, int value)
-{
- fprintf(outf, "\tduk_dup(ctx, 0);\n");
- fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n",
constant_name);
- fprintf(outf, "\tduk_push_int(ctx, %d);\n", value);
- fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |\n");
- fprintf(outf, "\t DUK_DEFPROP_HAVE_WRITABLE |
DUK_DEFPROP_HAVE_ENUMERABLE |\n");
- fprintf(outf, "\t DUK_DEFPROP_ENUMERABLE |
DUK_DEFPROP_HAVE_CONFIGURABLE);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
- return 0;
-}
-
-/**
- * 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,
%s_magic_string_private);\n",
- DLPFX);
- fprintf(outf, "\tpriv = duk_get_pointer(ctx, -1);\n");
- fprintf(outf, "\tduk_pop_2(ctx);\n");
- fprintf(outf, "\tif (priv == NULL) {\n");
- if (options->dbglog) {
- fprintf(outf, "\t\tLOG(\"priv failed\");\n");
- }
- fprintf(outf, "\t\treturn 0; /* can do? No can do. */\n");
- fprintf(outf, "\t}\n\n");
-
- return 0;
-}
-
-/**
- * generate preface block for nsgenbind
- */
-static int output_tool_preface(FILE* outf)
-{
- fprintf(outf, "%s\n", NSGENBIND_PREAMBLE);
-
- return 0;
-}
/**
* Generate a C class name for the interface.
@@ -345,34 +114,6 @@ static char *gen_class_name(struct ir_entry *interfacee)
return name;
}
-/**
- * output character data of node of given type.
- *
- * used for any cdata including pre/pro/epi/post sections
- *
- * \param outf The file handle to write output.
- * \param node The node to search.
- * \param nodetype the type of child node to search for.
- * \return The number of nodes written or 0 for none.
- */
-static int
-output_cdata(FILE* outf,
- struct genbind_node *node,
- enum genbind_node_type nodetype)
-{
- char *cdata;
- int res = 0;
-
- cdata = genbind_node_gettext(
- genbind_node_find_type(
- genbind_node_getnode(node),
- NULL, nodetype));
- if (cdata != NULL) {
- fprintf(outf, "%s", cdata);
- res = 1;
- }
- return res;
-}
static FILE *open_header(struct ir *ir, const char *name)
{
@@ -431,166 +172,7 @@ static int close_header(struct ir *ir,
}
-/**
- * generate the interface constructor
- */
-static int
-output_interface_constructor(FILE* outf, struct ir_entry *interfacee)
-{
- int init_argc;
-
- /* constructor definition */
- fprintf(outf,
- "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n",
- DLPFX, interfacee->class_name);
- fprintf(outf,"{\n");
-
- output_create_private(outf, interfacee->class_name);
-
- /* generate call to initialisor */
- fprintf(outf,
- "\t%s_%s___init(ctx, priv",
- DLPFX, interfacee->class_name);
- for (init_argc = 1;
- init_argc <= interfacee->class_init_argc;
- init_argc++) {
- fprintf(outf, ", duk_get_pointer(ctx, %d)", init_argc);
- }
- fprintf(outf, ");\n");
-
-
- 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 ir_entry *interfacee)
-{
- /* destructor definition */
- fprintf(outf,
- "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n",
- DLPFX, interfacee->class_name);
- fprintf(outf,"{\n");
-
- output_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 ir_entry *interfacee,
- struct ir_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 = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_INIT);
-
- inh_init_node = genbind_node_find_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_declaration(FILE* outf,
@@ -626,997 +208,6 @@ output_interface_init_declaration(FILE* outf,
return 0;
}
-static int
-output_interface_init(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_entry *inherite)
-{
- struct genbind_node *init_node;
- int res;
-
- /* find the initialisor method on the class (if any) */
- init_node = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_INIT);
-
- /* initialisor definition */
- output_interface_init_declaration(outf, interfacee, init_node);
-
- 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 ir_entry *interfacee,
- struct ir_entry *inherite)
-{
- struct genbind_node *fini_node;
-
- /* find the finaliser method on the class (if any) */
- fini_node = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_FINI);
-
- /* finaliser definition */
- fprintf(outf,
- "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n",
- DLPFX, interfacee->class_name, interfacee->class_name);
- fprintf(outf,"{\n");
-
- /* generate log statement */
- if (options->dbglog) {
- fprintf(outf,
- "\tLOG(\"Finalise %%p\", duk_get_heapptr(ctx,
0));\n" );
- }
-
- /* 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 */
- if (inherite != NULL) {
- fprintf(outf,
- "\t%s_%s___fini(ctx, &priv->parent);\n",
- DLPFX, inherite->class_name);
- }
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-
-/**
- * generate a prototype add for a single class method
- */
-static int
-output_prototype_method(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
-
- if (operatione->name != NULL) {
- /* normal method on prototype */
- output_add_method(outf,
- interfacee->class_name,
- operatione->name);
- } else {
- /* special method on prototype */
- fprintf(outf,
- "\t/* Special method on prototype - UNIMPLEMENTED
*/\n\n");
- }
-
- return 0;
-}
-
-/**
- * generate prototype method definitions
- */
-static int
-output_prototype_methods(FILE *outf, struct ir_entry *entry)
-{
- int opc;
- int res = 0;
-
- for (opc = 0; opc < entry->u.interface.operationc; opc++) {
- res = output_prototype_method(
- outf,
- entry,
- entry->u.interface.operationv + opc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-
-static int
-output_prototype_attribute(FILE *outf,
- struct ir_entry *interfacee,
- struct ir_attribute_entry *attributee)
-{
- if (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) {
- return output_populate_ro_property(outf,
- interfacee->class_name,
- attributee->name);
- }
- return output_populate_rw_property(outf,
- interfacee->class_name,
- attributee->name);
-}
-
-/**
- * generate prototype attribute definitions
- */
-static int
-output_prototype_attributes(FILE *outf, struct ir_entry *entry)
-{
- int attrc;
- int res = 0;
-
- for (attrc = 0; attrc < entry->u.interface.attributec; attrc++) {
- res = output_prototype_attribute(
- outf,
- entry,
- entry->u.interface.attributev + attrc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-/**
- * output constants on the prototype
- *
- * \todo This implementation assumes the constant is a literal int and should
- * check the type node base value.
- */
-static int
-output_prototype_constant(FILE *outf,
- struct ir_constant_entry *constante)
-{
- int *value;
-
- value = webidl_node_getint(
- webidl_node_find_type(
- webidl_node_getnode(constante->node),
- NULL,
- WEBIDL_NODE_TYPE_LITERAL_INT));
-
- output_prototype_constant_int(outf, constante->name, *value);
-
- return 0;
-}
-
-/**
- * generate prototype constant definitions
- */
-static int
-output_prototype_constants(FILE *outf, struct ir_entry *entry)
-{
- int attrc;
- int res = 0;
-
- for (attrc = 0; attrc < entry->u.interface.constantc; attrc++) {
- res = output_prototype_constant(
- outf,
- entry->u.interface.constantv + attrc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-static int
-output_global_create_prototype(FILE* outf,
- struct ir *ir,
- struct ir_entry *interfacee)
-{
- int idx;
-
- fprintf(outf, "\t/* Create interface objects */\n");
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *entry;
-
- entry = ir->entries + idx;
-
- if (entry->type == IR_ENTRY_TYPE_INTERFACE) {
-
- if (entry->u.interface.noobject) {
- continue;
- }
-
- if (entry == interfacee) {
- fprintf(outf, "\tduk_dup(ctx, 0);\n");
- } else {
- output_get_prototype(outf, entry->name);
- }
-
- fprintf(outf,
- "\tdukky_inject_not_ctr(ctx, 0,
\"%s\");\n",
- entry->name);
- }
- }
- return 0;
-}
-/**
- * generate the interface prototype creator
- */
-static int
-output_interface_prototype(FILE* outf,
- struct ir *ir,
- struct ir_entry *interfacee,
- struct ir_entry *inherite)
-{
- struct genbind_node *proto_node;
-
- /* find the prototype method on the class */
- proto_node = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_PROTOTYPE);
-
- /* prototype definition */
- fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx)\n",
- DLPFX, interfacee->class_name);
- fprintf(outf,"{\n");
-
- /* Output any binding data first */
- if (output_cdata(outf, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) {
- fprintf(outf,"\n");
- }
-
- /* generate prototype chaining if interface has a parent */
- if (inherite != NULL) {
- fprintf(outf,
- "\t/* Set this prototype's prototype (left-parent)
*/\n");
- output_get_prototype(outf, inherite->name);
- 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 constants */
- output_prototype_constants(outf, interfacee);
-
- /* if this is the global object, output all interfaces which do not
- * prevent us from doing so
- */
- if (interfacee->u.interface.primary_global) {
- output_global_create_prototype(outf, ir, interfacee);
- }
-
- /* generate setting of destructor */
- output_set_destructor(outf, interfacee->class_name, 0);
-
- /* generate setting of constructor */
- output_set_constructor(outf,
- interfacee->class_name,
- 0,
- interfacee->class_init_argc);
-
- fprintf(outf,"\treturn 1; /* The prototype object */\n");
-
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-/**
- * generate a single class method for an interface operation with elipsis
- */
-static int
-output_interface_elipsis_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- int cdatac; /* cdata blocks output */
-
- /* overloaded method definition */
- fprintf(outf,
- "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
- DLPFX, interfacee->class_name, operatione->name);
- fprintf(outf,"{\n");
-
- /**
- * \todo This is where the checking of the parameters to the
- * operation with elipsis should go
- */
- WARN(WARNING_UNIMPLEMENTED,
- "Elipsis parameetrs not checked: method %s::%s();",
- interfacee->name, operatione->name);
-
- output_get_method_private(outf, interfacee->class_name);
-
- cdatac = output_cdata(outf,
- operatione->method,
- GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- /* no implementation so generate default */
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: method %s::%s();",
- interfacee->name, operatione->name);
- fprintf(outf,"\treturn 0;\n");
- }
-
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-/**
- * generate a single class method for an interface overloaded operation
- */
-static int
-output_interface_overloaded_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- int cdatac; /* cdata blocks output */
-
- /* overloaded method definition */
- fprintf(outf,
- "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
- DLPFX, interfacee->class_name, operatione->name);
- fprintf(outf,"{\n");
-
- /** \todo This is where the checking of the parameters to the
- * overloaded operation should go
- */
-
- output_get_method_private(outf, interfacee->class_name);
-
- cdatac = output_cdata(outf,
- operatione->method,
- GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- /* no implementation so generate default */
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: method %s::%s();",
- interfacee->name, operatione->name);
- fprintf(outf,"\treturn 0;\n");
- }
-
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-/**
- * generate a single class method for an interface special operation
- */
-static int
-output_interface_special_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- /* special method definition */
- fprintf(outf, "/* Special method definition - UNIMPLEMENTED */\n\n");
-
- WARN(WARNING_UNIMPLEMENTED,
- "Special operation on interface %s (operation entry %p)",
- interfacee->name,
- operatione);
-
- return 0;
-}
-
-/**
- * generate default values on the duk stack
- */
-static int
-output_operation_optional_defaults(FILE* outf,
- struct ir_operation_argument_entry *argumentv,
- int argumentc)
-{
- int argc;
- for (argc = 0; argc < argumentc; argc++) {
- struct ir_operation_argument_entry *cure;
- struct webidl_node *lit_node; /* literal node */
- enum webidl_node_type lit_type;
- int *lit_int;
- char *lit_str;
-
- cure = argumentv + argc;
-
- lit_node = webidl_node_getnode(
- webidl_node_find_type(
- webidl_node_getnode(cure->node),
- NULL,
- WEBIDL_NODE_TYPE_OPTIONAL));
-
- if (lit_node != NULL) {
-
- lit_type = webidl_node_gettype(lit_node);
-
- switch (lit_type) {
- case WEBIDL_NODE_TYPE_LITERAL_NULL:
- fprintf(outf,
- "\t\tduk_push_null(ctx);\n");
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_INT:
- lit_int = webidl_node_getint(lit_node);
- fprintf(outf,
- "\t\tduk_push_int(ctx, %d);\n",
- *lit_int);
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_BOOL:
- lit_int = webidl_node_getint(lit_node);
- fprintf(outf,
- "\t\tduk_push_boolean(ctx, %d);\n",
- *lit_int);
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_STRING:
- lit_str = webidl_node_gettext(lit_node);
- fprintf(outf,
- "\t\tduk_push_string(ctx,
\"%s\");\n",
- lit_str);
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_FLOAT:
- default:
- fprintf(outf,
- "\t\tduk_push_undefined(ctx);\n");
- break;
- }
- } else {
- fprintf(outf, "\t\tduk_push_undefined(ctx);\n");
- }
- }
- return 0;
-}
-
-static int
-output_operation_argument_type_check(
- FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione,
- struct ir_operation_overload_entry *overloade,
- int argidx)
-{
- struct ir_operation_argument_entry *argumente;
- struct webidl_node *type_node;
- enum webidl_type *argument_type;
-
- argumente = overloade->argumentv + argidx;
-
- type_node = webidl_node_find_type(
- webidl_node_getnode(argumente->node),
- NULL,
- WEBIDL_NODE_TYPE_TYPE);
-
- if (type_node == NULL) {
- fprintf(stderr, "%s:%s %dth argument %s has no type\n",
- interfacee->name,
- operatione->name,
- argidx,
- argumente->name);
- return -1;
- }
-
- argument_type = (enum webidl_type *)webidl_node_getint(
- webidl_node_find_type(
- webidl_node_getnode(type_node),
- NULL,
- WEBIDL_NODE_TYPE_TYPE_BASE));
-
- if (argument_type == NULL) {
- fprintf(stderr,
- "%s:%s %dth argument %s has no type base\n",
- interfacee->name,
- operatione->name,
- argidx,
- argumente->name);
- return -1;
- }
-
- if (*argument_type == WEBIDL_TYPE_ANY) {
- /* allowing any type needs no check */
- return 0;
- }
-
- fprintf(outf, "\tif (%s_argc > %d) {\n", DLPFX, argidx);
-
- switch (*argument_type) {
- case WEBIDL_TYPE_STRING:
- fprintf(outf,
- "\t\tif (!duk_is_string(ctx, %d)) {\n"
- "\t\t\tduk_error(ctx, DUK_ERR_ERROR,
%s_error_fmt_string_type, %d, \"%s\");\n"
- "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
- break;
-
- case WEBIDL_TYPE_BOOL:
- fprintf(outf,
- "\t\tif (!duk_is_boolean(ctx, %d)) {\n"
- "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_bool_type,
%d, \"%s\");\n"
- "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
- break;
-
- case WEBIDL_TYPE_FLOAT:
- case WEBIDL_TYPE_DOUBLE:
- case WEBIDL_TYPE_SHORT:
- case WEBIDL_TYPE_LONG:
- case WEBIDL_TYPE_LONGLONG:
- fprintf(outf,
- "\t\tif (!duk_is_number(ctx, %d)) {\n"
- "\t\t\tduk_error(ctx, DUK_ERR_ERROR,
%s_error_fmt_number_type, %d, \"%s\");\n"
- "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
- break;
-
-
- default:
- fprintf(outf,
- "\t\t/* unhandled type check */\n");
- }
-
- fprintf(outf, "\t}\n");
-
- return 0;
-}
-
-
-/**
- * generate a single class method for an interface operation
- */
-static int
-output_interface_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- int cdatac; /* cdata blocks output */
- struct ir_operation_overload_entry *overloade;
- int fixedargc; /* number of non optional arguments */
- int argidx; /* loop counter for arguments */
- int optargc; /* loop counter for optional arguments */
-
- if (operatione->name == NULL) {
- return output_interface_special_operation(outf,
- interfacee,
- operatione);
- }
-
- if (operatione->overloadc != 1) {
- return output_interface_overloaded_operation(outf,
- interfacee,
- operatione);
- }
-
- if (operatione->overloadv->elipsisc != 0) {
- return output_interface_elipsis_operation(outf,
- interfacee,
- operatione);
- }
-
- /* normal method definition */
- overloade = operatione->overloadv;
-
- fprintf(outf,
- "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
- DLPFX, interfacee->class_name, operatione->name);
- fprintf(outf,"{\n");
-
- /* check arguments */
-
- /* generate check for minimum number of parameters */
-
- fixedargc = overloade->argumentc - overloade->optionalc;
-
- fprintf(outf,
- "\t/* ensure the parameters are present */\n"
- "\tduk_idx_t %s_argc = duk_get_top(ctx);\n\t", DLPFX);
-
- if (fixedargc > 0) {
- fprintf(outf,
- "if (%s_argc < %d) {\n"
- "\t\t/* not enough arguments */\n"
- "\t\tduk_error(ctx, DUK_RET_TYPE_ERROR,
%s_error_fmt_argument, %d, %s_argc);\n"
- "\t} else ",
- DLPFX,
- fixedargc,
- DLPFX,
- fixedargc,
- DLPFX);
- }
-
- for (optargc = fixedargc;
- optargc < overloade->argumentc;
- optargc++) {
- fprintf(outf,
- "if (%s_argc == %d) {\n"
- "\t\t/* %d optional arguments need adding */\n",
- DLPFX,
- optargc,
- overloade->argumentc - optargc);
- output_operation_optional_defaults(outf,
- overloade->argumentv + optargc,
- overloade->argumentc - optargc);
- fprintf(outf,
- "\t} else ");
- }
-
- fprintf(outf,
- "if (%s_argc > %d) {\n"
- "\t\t/* remove extraneous parameters */\n"
- "\t\tduk_set_top(ctx, %d);\n"
- "\t}\n",
- DLPFX,
- overloade->argumentc,
- overloade->argumentc);
- fprintf(outf, "\n");
-
- /* generate argument type checks */
-
- fprintf(outf, "\t/* check types of passed arguments are correct
*/\n");
-
- for (argidx = 0; argidx < overloade->argumentc; argidx++) {
- output_operation_argument_type_check(outf,
- interfacee,
- operatione,
- overloade,
- argidx);
- }
-
- output_get_method_private(outf, interfacee->class_name);
-
- cdatac = output_cdata(outf,
- operatione->method,
- GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- /* no implementation so generate default */
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: method %s::%s();",
- interfacee->name, operatione->name);
- 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 ir_entry *ife)
-{
- int opc;
- int res = 0;
-
- for (opc = 0; opc < ife->u.interface.operationc; opc++) {
- res = output_interface_operation(
- outf,
- ife,
- ife->u.interface.operationv + opc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-/**
- * Generate class property getter/setter for a single attribute
- */
-static int
-output_interface_attribute(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_attribute_entry *atributee)
-{
- int cdatac;
-
- /* 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);
-
- cdatac = output_cdata(outf, atributee->getter, GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: getter %s::%s();",
- interfacee->name, atributee->name);
-
- /* no implementation so generate default */
- 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);
-
- cdatac = output_cdata(outf, atributee->setter, GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: setter %s::%s();",
- interfacee->name, atributee->name);
-
- /* no implementation so generate default */
- 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 ir_entry *ife)
-{
- int attrc;
-
- for (attrc = 0; attrc < ife->u.interface.attributec; attrc++) {
- output_interface_attribute(
- outf,
- ife,
- ife->u.interface.attributev + attrc);
- }
-
- return 0;
-}
-
-
-/**
- * generate preface block for nsgenbind
- */
-static int output_tool_prologue(FILE* outf)
-{
- char *fpath;
-
- fpath = genb_fpath("binding.h");
- fprintf(outf, "\n#include \"%s\"\n", fpath);
- free(fpath);
-
- fpath = genb_fpath("private.h");
- fprintf(outf, "#include \"%s\"\n", fpath);
- free(fpath);
-
- fpath = genb_fpath("prototype.h");
- fprintf(outf, "#include \"%s\"\n", fpath);
- free(fpath);
-
- return 0;
-}
-
-/**
- * generate a source file to implement a dictionary using duk and libdom.
- */
-static int output_dictionary(struct ir *ir, struct ir_entry *dictionarye)
-{
- FILE *ifacef;
- struct ir_entry *inherite;
- int res = 0;
-
- /* open output file */
- ifacef = genb_fopen_tmp(dictionarye->filename);
- if (ifacef == NULL) {
- return -1;
- }
-
- /* find parent interface entry */
- inherite = ir_inherit_entry(ir, dictionarye);
-
- /* tool preface */
- output_tool_preface(ifacef);
-
- /* binding preface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PREFACE);
-
- /* class preface */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PREFACE);
-
- /* tool prologue */
- output_tool_prologue(ifacef);
-
- /* binding prologue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PROLOGUE);
-
- /* class prologue */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PROLOGUE);
-
- fprintf(ifacef, "\n");
-
- /* initialisor */
- res = output_interface_init(ifacef, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
- /* finaliser */
- res = output_interface_fini(ifacef, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
- /* constructor */
- res = output_interface_constructor(ifacef, dictionarye);
- if (res != 0) {
- goto op_error;
- }
-
- /* destructor */
- res = output_interface_destructor(ifacef, dictionarye);
- if (res != 0) {
- goto op_error;
- }
-
- /* prototype */
- res = output_interface_prototype(ifacef, ir, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
-
- fprintf(ifacef, "\n");
-
- /* class epilogue */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_EPILOGUE);
-
- /* binding epilogue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_EPILOGUE);
-
- /* class postface */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_POSTFACE);
-
- /* binding postface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_POSTFACE);
-
-op_error:
- genb_fclose_tmp(ifacef, dictionarye->filename);
-
- return res;
-}
-
-/**
- * generate a source file to implement an interface using duk and libdom.
- */
-static int output_interface(struct ir *ir, struct ir_entry *interfacee)
-{
- FILE *ifacef;
- struct ir_entry *inherite;
- int res = 0;
-
- /* open output file */
- ifacef = genb_fopen_tmp(interfacee->filename);
- if (ifacef == NULL) {
- return -1;
- }
-
- /* find parent interface entry */
- inherite = ir_inherit_entry(ir, interfacee);
-
- /* tool preface */
- output_tool_preface(ifacef);
-
- /* binding preface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PREFACE);
-
- /* class preface */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PREFACE);
-
- /* tool prologue */
- output_tool_prologue(ifacef);
-
- /* binding prologue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PROLOGUE);
-
- /* class prologue */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PROLOGUE);
-
- fprintf(ifacef, "\n");
-
- /* initialisor */
- 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);
-
- /* operations */
- output_interface_operations(ifacef, interfacee);
-
- /* attributes */
- output_interface_attributes(ifacef, interfacee);
-
- /* prototype */
- output_interface_prototype(ifacef, ir, interfacee, inherite);
-
- fprintf(ifacef, "\n");
-
- /* class epilogue */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_EPILOGUE);
-
- /* binding epilogue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_EPILOGUE);
-
- /* class postface */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_POSTFACE);
-
- /* binding postface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_POSTFACE);
-
-op_error:
- genb_fclose_tmp(ifacef, interfacee->filename);
-
- return res;
-}
/**
* generate private header
diff --git a/src/duk-libdom.h b/src/duk-libdom.h
index 2ecd482..84fc497 100644
--- a/src/duk-libdom.h
+++ b/src/duk-libdom.h
@@ -9,6 +9,41 @@
#ifndef nsgenbind_duk_libdom_h
#define nsgenbind_duk_libdom_h
+/**
+ * Generate output for duktape and libdom bindings.
+ */
int duk_libdom_output(struct ir *ir);
+/**
+ * generate a source file to implement an interface using duk and libdom.
+ */
+int output_interface(struct ir *ir, struct ir_entry *interfacee);
+
+/**
+ * generate a source file to implement a dictionary using duk and libdom.
+ */
+int output_dictionary(struct ir *ir, struct ir_entry *dictionarye);
+
+/**
+ * generate preface block for nsgenbind
+ */
+int output_tool_preface(FILE* outf);
+
+/**
+ * generate preface block for nsgenbind
+ */
+int output_tool_prologue(FILE* outf);
+
+/**
+ * output character data of node of given type.
+ *
+ * used for any cdata including pre/pro/epi/post sections
+ *
+ * \param outf The file handle to write output.
+ * \param node The node to search.
+ * \param nodetype the type of child node to search for.
+ * \return The number of nodes written or 0 for none.
+ */
+int output_cdata(FILE* outf, struct genbind_node *node, enum genbind_node_type
nodetype);
+
#endif
-----------------------------------------------------------------------
Summary of changes:
src/Makefile | 3 +-
src/duk-libdom-common.c | 78 ++
src/duk-libdom-dictionary.c | 571 +++++++++++
src/{duk-libdom.c => duk-libdom-interface.c} | 853 +---------------
src/duk-libdom.c | 1411 +-------------------------
src/duk-libdom.h | 35 +
6 files changed, 692 insertions(+), 2259 deletions(-)
create mode 100644 src/duk-libdom-common.c
create mode 100644 src/duk-libdom-dictionary.c
copy src/{duk-libdom.c => duk-libdom-interface.c} (61%)
diff --git a/src/Makefile b/src/Makefile
index 9905baf..3ecfbe1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2,7 +2,8 @@ CFLAGS := $(CFLAGS) -I$(BUILDDIR) -Isrc/ -g -DYYENABLE_NLS=0
# Sources in this directory
DIR_SOURCES := nsgenbind.c utils.c webidl-ast.c nsgenbind-ast.c ir.c \
- duk-libdom.c
+ duk-libdom.c duk-libdom-interface.c duk-libdom-dictionary.c duk-libdom-common.c
+
# jsapi-libdom.c jsapi-libdom-function.c jsapi-libdom-property.c jsapi-libdom-init.c
jsapi-libdom-new.c jsapi-libdom-infmap.c jsapi-libdom-jsclass.c
SOURCES := $(SOURCES) $(BUILDDIR)/nsgenbind-parser.c $(BUILDDIR)/nsgenbind-lexer.c
$(BUILDDIR)/webidl-parser.c $(BUILDDIR)/webidl-lexer.c
diff --git a/src/duk-libdom-common.c b/src/duk-libdom-common.c
new file mode 100644
index 0000000..9a0f660
--- /dev/null
+++ b/src/duk-libdom-common.c
@@ -0,0 +1,78 @@
+/* duktape binding generation implementation
+ *
+ * This file is part of nsgenbind.
+ * Licensed under the MIT License,
+ *
http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2015 Vincent Sanders <vince(a)netsurf-browser.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "options.h"
+#include "utils.h"
+#include "nsgenbind-ast.h"
+#include "webidl-ast.h"
+#include "ir.h"
+#include "duk-libdom.h"
+
+#define NSGENBIND_PREFACE \
+ "/* Generated by nsgenbind\n" \
+ " *\n" \
+ " * nsgenbind is published under the MIT Licence.\n" \
+ " * nsgenbind is similar to a compiler is a purely transformative tool
which\n" \
+ " * explicitly makes no copyright claim on this generated output\n" \
+ " */"
+
+/* exported interface documented in duk-libdom.h */
+int output_tool_preface(FILE* outf)
+{
+ fprintf(outf, "%s\n", NSGENBIND_PREFACE);
+
+ return 0;
+}
+
+/* exported interface documented in duk-libdom.h */
+int output_cdata(FILE* outf,
+ struct genbind_node *node,
+ enum genbind_node_type nodetype)
+{
+ char *cdata;
+ int res = 0;
+
+ cdata = genbind_node_gettext(
+ genbind_node_find_type(
+ genbind_node_getnode(node),
+ NULL, nodetype));
+ if (cdata != NULL) {
+ fprintf(outf, "%s", cdata);
+ res = 1;
+ }
+ return res;
+}
+
+/* exported interface documented in duk-libdom.h */
+int output_tool_prologue(FILE* outf)
+{
+ char *fpath;
+
+ fpath = genb_fpath("binding.h");
+ fprintf(outf, "\n#include \"%s\"\n", fpath);
+ free(fpath);
+
+ fpath = genb_fpath("private.h");
+ fprintf(outf, "#include \"%s\"\n", fpath);
+ free(fpath);
+
+ fpath = genb_fpath("prototype.h");
+ fprintf(outf, "#include \"%s\"\n", fpath);
+ free(fpath);
+
+ return 0;
+}
diff --git a/src/duk-libdom-dictionary.c b/src/duk-libdom-dictionary.c
new file mode 100644
index 0000000..275855e
--- /dev/null
+++ b/src/duk-libdom-dictionary.c
@@ -0,0 +1,571 @@
+/* duktape binding generation implementation
+ *
+ * This file is part of nsgenbind.
+ * Licensed under the MIT License,
+ *
http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2012 Vincent Sanders <vince(a)netsurf-browser.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "options.h"
+#include "utils.h"
+#include "nsgenbind-ast.h"
+#include "webidl-ast.h"
+#include "ir.h"
+#include "duk-libdom.h"
+
+/** prefix for all generated functions */
+#define DLPFX "dukky"
+
+#define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_"
+
+/**
+ * Output code to create a private structure
+ *
+ */
+static int output_create_private(FILE* outf, char *class_name)
+{
+ fprintf(outf, "\t/* create private data and attach to instance */\n");
+ 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, %s_magic_string_private);\n\n",
+ DLPFX);
+
+ return 0;
+}
+
+/**
+ * generate code that gets a private pointer
+ */
+static int output_safe_get_private(FILE* outf, char *class_name, int idx)
+{
+ fprintf(outf,
+ "\t%s_private_t *priv;\n", class_name);
+ fprintf(outf,
+ "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n",
+ idx, DLPFX);
+ fprintf(outf,
+ "\tpriv = duk_get_pointer(ctx, -1);\n");
+ fprintf(outf,
+ "\tduk_pop(ctx);\n");
+ fprintf(outf,
+ "\tif (priv == NULL) return 0;\n\n");
+
+ return 0;
+}
+
+
+/**
+ * generate the dictionary constructor
+ */
+static int
+output_dictionary_constructor(FILE* outf, struct ir_entry *dictionarye)
+{
+ int init_argc;
+
+ /* constructor definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n",
+ DLPFX, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ output_create_private(outf, dictionarye->class_name);
+
+ /* generate call to initialisor */
+ fprintf(outf,
+ "\t%s_%s___init(ctx, priv",
+ DLPFX, dictionarye->class_name);
+ for (init_argc = 1;
+ init_argc <= dictionarye->class_init_argc;
+ init_argc++) {
+ fprintf(outf, ", duk_get_pointer(ctx, %d)", init_argc);
+ }
+ fprintf(outf, ");\n");
+
+
+ fprintf(outf, "\tduk_set_top(ctx, 1);\n");
+ fprintf(outf, "\treturn 1;\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate a duktape prototype name
+ */
+static char *get_prototype_name(const char *dictionary_name)
+{
+ char *proto_name;
+ int pnamelen;
+ int pfxlen;
+
+ /* duplicate the dictionary name in upper case */
+ pfxlen = SLEN(MAGICPFX) + SLEN("PROTOTYPE_");
+ pnamelen = strlen(dictionary_name) + 1;
+
+ proto_name = malloc(pnamelen + pfxlen);
+ snprintf(proto_name, pnamelen + pfxlen, "%sPROTOTYPE_%s", MAGICPFX,
dictionary_name);
+ for (pnamelen-- ; pnamelen >= 0; pnamelen--) {
+ proto_name[pnamelen + pfxlen] = toupper(dictionary_name[pnamelen]);
+ }
+ return proto_name;
+}
+
+
+/**
+ * generate code that gets a prototype by name
+ */
+static int output_get_prototype(FILE* outf, const char *dictionary_name)
+{
+ char *proto_name;
+
+ proto_name = get_prototype_name(dictionary_name);
+
+ fprintf(outf,
+ "\t/* get prototype */\n");
+ fprintf(outf,
+ "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n",
+ DLPFX);
+ fprintf(outf,
+ "\tduk_get_prop_string(ctx, -1, \"%s\");\n",
+ proto_name);
+ fprintf(outf,
+ "\tduk_replace(ctx, -2);\n");
+
+ free(proto_name);
+
+ return 0;
+}
+
+
+/**
+ * generate code that sets a destructor in a prototype
+ */
+static int output_set_destructor(FILE* outf, char *class_name, int idx)
+{
+ fprintf(outf, "\t/* Set the destructor */\n");
+ fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
+ fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___destructor, 1);\n",
+ DLPFX, class_name);
+ fprintf(outf, "\tduk_set_finalizer(ctx, -2);\n");
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+/**
+ * generate code that sets a constructor in a prototype
+ */
+static int
+output_set_constructor(FILE* outf, char *class_name, int idx, int argc)
+{
+ fprintf(outf, "\t/* Set the constructor */\n");
+ fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
+ fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___constructor,
%d);\n",
+ DLPFX, class_name, 1 + argc);
+ fprintf(outf, "\tduk_put_prop_string(ctx, -2,
\"%sINIT\");\n",
+ MAGICPFX);
+ fprintf(outf, "\tduk_pop(ctx);\n\n");
+
+ return 0;
+}
+
+/**
+ * generate the dictionary prototype creator
+ */
+static int
+output_dictionary_prototype(FILE* outf,
+ struct ir *ir,
+ struct ir_entry *dictionarye,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *proto_node;
+
+ /* find the prototype method on the class */
+ proto_node = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_PROTOTYPE);
+
+ /* prototype definition */
+ fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx)\n",
+ DLPFX, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ /* Output any binding data first */
+ if (output_cdata(outf, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) {
+ fprintf(outf,"\n");
+ }
+
+ /* generate prototype chaining if dictionary has a parent */
+ if (inherite != NULL) {
+ fprintf(outf,
+ "\t/* Set this prototype's prototype (left-parent)
*/\n");
+ output_get_prototype(outf, inherite->name);
+ fprintf(outf, "\tduk_set_prototype(ctx, 0);\n\n");
+ }
+
+ /* dictionary members*/
+
+
+ /* generate setting of destructor */
+ output_set_destructor(outf, dictionarye->class_name, 0);
+
+ /* generate setting of constructor */
+ output_set_constructor(outf,
+ dictionarye->class_name,
+ 0,
+ dictionarye->class_init_argc);
+
+ fprintf(outf,"\treturn 1; /* The prototype object */\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate the dictionary destructor
+ */
+static int
+output_dictionary_destructor(FILE* outf, struct ir_entry *dictionarye)
+{
+ /* destructor definition */
+ fprintf(outf,
+ "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n",
+ DLPFX, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ output_safe_get_private(outf, dictionarye->class_name, 0);
+
+ /* generate call to finaliser */
+ fprintf(outf,
+ "\t%s_%s___fini(ctx, priv);\n",
+ DLPFX, dictionarye->class_name);
+
+ fprintf(outf,"\tfree(priv);\n");
+ fprintf(outf,"\treturn 0;\n");
+
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+/**
+ * generate an initialisor call to parent dictionary
+ */
+static int
+output_dictionary_inherit_init(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct ir_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 = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+
+ inh_init_node = genbind_node_find_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\" (dictionary %s)
parent class \"%s\" (dictionary %s) initialisor requires a parameter
\"%s\" with compatible identifier\n",
+ dictionarye->class_name,
+ dictionarye->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_dictionary_init_declaration(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct genbind_node *init_node)
+{
+ struct genbind_node *param_node;
+
+ fprintf(outf,
+ "void %s_%s___init(duk_context *ctx, %s_private_t *priv",
+ DLPFX, dictionarye->class_name, dictionarye->class_name);
+
+ /* count the number of arguments on the initializer */
+ dictionarye->class_init_argc = 0;
+
+ /* 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) {
+ dictionarye->class_init_argc++;
+ 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_PARAMETER);
+ }
+
+ fprintf(outf,")");
+
+ return 0;
+}
+
+static int
+output_dictionary_init(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *init_node;
+ int res;
+
+ /* find the initialisor method on the class (if any) */
+ init_node = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_INIT);
+
+ /* initialisor definition */
+ output_dictionary_init_declaration(outf, dictionarye, init_node);
+
+ fprintf(outf,"\n{\n");
+
+ /* if this dictionary inherits ensure we call its initialisor */
+ res = output_dictionary_inherit_init(outf, dictionarye, 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_dictionary_fini(FILE* outf,
+ struct ir_entry *dictionarye,
+ struct ir_entry *inherite)
+{
+ struct genbind_node *fini_node;
+
+ /* find the finaliser method on the class (if any) */
+ fini_node = genbind_node_find_method(dictionarye->class,
+ NULL,
+ GENBIND_METHOD_TYPE_FINI);
+
+ /* finaliser definition */
+ fprintf(outf,
+ "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n",
+ DLPFX, dictionarye->class_name, dictionarye->class_name);
+ fprintf(outf,"{\n");
+
+ /* generate log statement */
+ if (options->dbglog) {
+ fprintf(outf,
+ "\tLOG(\"Finalise %%p\", duk_get_heapptr(ctx,
0));\n" );
+ }
+
+ /* output the finialisor code from the binding */
+ output_cdata(outf, fini_node, GENBIND_NODE_TYPE_CDATA);
+
+ /* if this dictionary inherits ensure we call its finaliser */
+ if (inherite != NULL) {
+ fprintf(outf,
+ "\t%s_%s___fini(ctx, &priv->parent);\n",
+ DLPFX, inherite->class_name);
+ }
+ fprintf(outf, "}\n\n");
+
+ return 0;
+}
+
+
+/**
+ * generate a source file to implement a dictionary using duk and libdom.
+ */
+int output_dictionary(struct ir *ir, struct ir_entry *dictionarye)
+{
+ FILE *ifacef;
+ struct ir_entry *inherite;
+ int res = 0;
+
+ /* open output file */
+ ifacef = genb_fopen_tmp(dictionarye->filename);
+ if (ifacef == NULL) {
+ return -1;
+ }
+
+ /* find parent dictionary entry */
+ inherite = ir_inherit_entry(ir, dictionarye);
+
+ /* tool preface */
+ output_tool_preface(ifacef);
+
+ /* binding preface */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_PREFACE);
+
+ /* class preface */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PREFACE);
+
+ /* tool prologue */
+ output_tool_prologue(ifacef);
+
+ /* binding prologue */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_PROLOGUE);
+
+ /* class prologue */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PROLOGUE);
+
+ fprintf(ifacef, "\n");
+
+ /* initialisor */
+ res = output_dictionary_init(ifacef, dictionarye, inherite);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /* finaliser */
+ res = output_dictionary_fini(ifacef, dictionarye, inherite);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /* constructor */
+ res = output_dictionary_constructor(ifacef, dictionarye);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /* destructor */
+ res = output_dictionary_destructor(ifacef, dictionarye);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ /** todo property handlers */
+
+ /* prototype */
+ res = output_dictionary_prototype(ifacef, ir, dictionarye, inherite);
+ if (res != 0) {
+ goto op_error;
+ }
+
+ fprintf(ifacef, "\n");
+
+ /* class epilogue */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_EPILOGUE);
+
+ /* binding epilogue */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_EPILOGUE);
+
+ /* class postface */
+ output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_POSTFACE);
+
+ /* binding postface */
+ output_cdata(ifacef,
+ ir->binding_node,
+ GENBIND_NODE_TYPE_POSTFACE);
+
+op_error:
+ genb_fclose_tmp(ifacef, dictionarye->filename);
+
+ return res;
+}
diff --git a/src/duk-libdom.c b/src/duk-libdom-interface.c
similarity index 61%
copy from src/duk-libdom.c
copy to src/duk-libdom-interface.c
index 3e20d13..7501bea 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom-interface.c
@@ -27,14 +27,6 @@
#define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_"
-#define NSGENBIND_PREAMBLE \
- "/* Generated by nsgenbind\n" \
- " *\n" \
- " * nsgenbind is published under the MIT Licence.\n" \
- " * nsgenbind is similar to a compiler is a purely transformative tool
which\n" \
- " * explicitly makes no copyright claim on this generated output\n" \
- " */"
-
/**
* Output code to create a private structure
*
@@ -95,6 +87,7 @@ static char *get_prototype_name(const char *interface_name)
return proto_name;
}
+
/**
* generate code that gets a prototype by name
*/
@@ -270,166 +263,6 @@ output_get_method_private(FILE* outf, char *class_name)
return 0;
}
-/**
- * generate preface block for nsgenbind
- */
-static int output_tool_preface(FILE* outf)
-{
- fprintf(outf, "%s\n", NSGENBIND_PREAMBLE);
-
- return 0;
-}
-
-/**
- * Generate a C class name for the interface.
- *
- * The IDL interface names are camelcase and not similar to libdom naming so it
- * is necessary to convert them to a libdom compatible class name. This
- * implementation is simple ASCII capable only and cannot cope with multibyte
- * codepoints.
- *
- * The algorithm is:
- * - copy characters to output lowering their case
- * - if the previous character in the input name was uppercase and the current
- * one is lowercase insert an underscore before the *previous* character.
- */
-static char *gen_class_name(struct ir_entry *interfacee)
-{
- const char *inc;
- char *outc;
- char *name;
- int wasupper;
-
- /* enpty strings are a bad idea */
- if ((interfacee->name == NULL) ||
- (interfacee->name[0] == 0)) {
- return NULL;
- }
-
- /* allocate result buffer as twice the input length as thats the
- * absolute worst case.
- */
- name = calloc(2, strlen(interfacee->name));
-
- outc = name;
- inc = interfacee->name;
- wasupper = 0;
-
- /* first character handled separately as inserting a leading underscore
- * is undesirable
- */
- *outc++ = tolower(*inc++);
- /* copy input to output */
- while (*inc != 0) {
- /* ugly hack as html IDL is always prefixed uppercase and needs
- * an underscore there
- */
- if ((inc == (interfacee->name + 4)) &&
- (interfacee->name[0] == 'H') &&
- (interfacee->name[1] == 'T') &&
- (interfacee->name[2] == 'M') &&
- (interfacee->name[3] == 'L') &&
- (islower(inc[1]) == 0)) {
- *outc++ = '_';
- }
- if ((islower(*inc) != 0) && (wasupper != 0)) {
- *outc = *(outc - 1);
- *(outc - 1) = '_';
- outc++;
- wasupper = 0;
- } else {
- wasupper = isupper(*inc);
- }
- *outc++ = tolower(*inc++);
- }
- return name;
-}
-
-/**
- * output character data of node of given type.
- *
- * used for any cdata including pre/pro/epi/post sections
- *
- * \param outf The file handle to write output.
- * \param node The node to search.
- * \param nodetype the type of child node to search for.
- * \return The number of nodes written or 0 for none.
- */
-static int
-output_cdata(FILE* outf,
- struct genbind_node *node,
- enum genbind_node_type nodetype)
-{
- char *cdata;
- int res = 0;
-
- cdata = genbind_node_gettext(
- genbind_node_find_type(
- genbind_node_getnode(node),
- NULL, nodetype));
- if (cdata != NULL) {
- fprintf(outf, "%s", cdata);
- res = 1;
- }
- return res;
-}
-
-static FILE *open_header(struct ir *ir, const char *name)
-{
- FILE *hdrf;
- char *fname;
- int fnamel;
-
- fnamel = strlen(name) + 4;
- fname = malloc(fnamel);
- snprintf(fname, fnamel, "%s.h", name);
-
- /* open output file */
- hdrf = genb_fopen_tmp(fname);
- free(fname);
- if (hdrf == NULL) {
- return NULL;
- }
-
- /* binding preface */
- output_cdata(hdrf,
- ir->binding_node,
- GENBIND_NODE_TYPE_PREFACE);
-
- /* tool preface */
- output_tool_preface(hdrf);
-
- /* header guard */
- fprintf(hdrf, "\n#ifndef %s_%s_h\n", DLPFX, name);
- fprintf(hdrf, "#define %s_%s_h\n\n", DLPFX, name);
-
- return hdrf;
-}
-
-static int close_header(struct ir *ir,
- FILE *hdrf,
- const char *name)
-{
- char *fname;
- int fnamel;
-
- fnamel = strlen(name) + 4;
- fname = malloc(fnamel);
- snprintf(fname, fnamel, "%s.h", name);
-
- fprintf(hdrf, "\n#endif\n");
-
- /* binding postface */
- output_cdata(hdrf,
- ir->binding_node,
- GENBIND_NODE_TYPE_POSTFACE);
-
- genb_fclose_tmp(hdrf, fname);
- free(fname);
-
- return 0;
-}
-
/**
* generate the interface constructor
@@ -863,6 +696,8 @@ output_global_create_prototype(FILE* outf,
}
return 0;
}
+
+
/**
* generate the interface prototype creator
*/
@@ -1409,129 +1244,8 @@ output_interface_attributes(FILE* outf, struct ir_entry *ife)
}
-/**
- * generate preface block for nsgenbind
- */
-static int output_tool_prologue(FILE* outf)
-{
- char *fpath;
-
- fpath = genb_fpath("binding.h");
- fprintf(outf, "\n#include \"%s\"\n", fpath);
- free(fpath);
-
- fpath = genb_fpath("private.h");
- fprintf(outf, "#include \"%s\"\n", fpath);
- free(fpath);
-
- fpath = genb_fpath("prototype.h");
- fprintf(outf, "#include \"%s\"\n", fpath);
- free(fpath);
-
- return 0;
-}
-
-/**
- * generate a source file to implement a dictionary using duk and libdom.
- */
-static int output_dictionary(struct ir *ir, struct ir_entry *dictionarye)
-{
- FILE *ifacef;
- struct ir_entry *inherite;
- int res = 0;
-
- /* open output file */
- ifacef = genb_fopen_tmp(dictionarye->filename);
- if (ifacef == NULL) {
- return -1;
- }
-
- /* find parent interface entry */
- inherite = ir_inherit_entry(ir, dictionarye);
-
- /* tool preface */
- output_tool_preface(ifacef);
-
- /* binding preface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PREFACE);
-
- /* class preface */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PREFACE);
-
- /* tool prologue */
- output_tool_prologue(ifacef);
-
- /* binding prologue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PROLOGUE);
-
- /* class prologue */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PROLOGUE);
-
- fprintf(ifacef, "\n");
-
- /* initialisor */
- res = output_interface_init(ifacef, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
- /* finaliser */
- res = output_interface_fini(ifacef, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
- /* constructor */
- res = output_interface_constructor(ifacef, dictionarye);
- if (res != 0) {
- goto op_error;
- }
-
- /* destructor */
- res = output_interface_destructor(ifacef, dictionarye);
- if (res != 0) {
- goto op_error;
- }
-
- /* prototype */
- res = output_interface_prototype(ifacef, ir, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
-
- fprintf(ifacef, "\n");
-
- /* class epilogue */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_EPILOGUE);
-
- /* binding epilogue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_EPILOGUE);
-
- /* class postface */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_POSTFACE);
-
- /* binding postface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_POSTFACE);
-
-op_error:
- genb_fclose_tmp(ifacef, dictionarye->filename);
-
- return res;
-}
-
-/**
- * generate a source file to implement an interface using duk and libdom.
- */
-static int output_interface(struct ir *ir, struct ir_entry *interfacee)
+/* exported interface documented in duk-libdom.h */
+int output_interface(struct ir *ir, struct ir_entry *interfacee)
{
FILE *ifacef;
struct ir_entry *inherite;
@@ -1618,560 +1332,3 @@ op_error:
return res;
}
-/**
- * generate private header
- */
-static int
-output_private_header(struct ir *ir)
-{
- int idx;
- FILE *privf;
-
- /* open header */
- privf = open_header(ir, "private");
-
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *interfacee;
- struct ir_entry *inherite;
- struct genbind_node *priv_node;
-
- interfacee = ir->entries + idx;
-
- /* do not generate private structs for interfaces marked no
- * output
- */
- if ((interfacee->type == IR_ENTRY_TYPE_INTERFACE) &&
- (interfacee->u.interface.noobject)) {
- continue;
- }
-
- switch (interfacee->type) {
- case IR_ENTRY_TYPE_INTERFACE:
- fprintf(privf,
- "/* Private data for %s interface */\n",
- interfacee->name);
- break;
-
- case IR_ENTRY_TYPE_DICTIONARY:
- fprintf(privf,
- "/* Private data for %s dictionary */\n",
- interfacee->name);
- break;
- }
-
- fprintf(privf, "typedef struct {\n");
-
- /* find parent entry and include in private */
- inherite = ir_inherit_entry(ir, interfacee);
- if (inherite != NULL) {
- fprintf(privf, "\t%s_private_t parent;\n",
- inherite->class_name);
- }
-
- /* for each private variable on the class output it here. */
- priv_node = genbind_node_find_type(
- genbind_node_getnode(interfacee->class),
- NULL,
- GENBIND_NODE_TYPE_PRIVATE);
- while (priv_node != NULL) {
- /* generate the private variable definition ensuring
- * the type is separated from the identifier with
- * either a * or space.
- */
- const char *type_cdata;
- char cdatae;
- type_cdata = genbind_node_gettext(
- genbind_node_find_type(
- genbind_node_getnode(priv_node),
- NULL,
- GENBIND_NODE_TYPE_TYPE));
-
- fprintf(privf, "\t%s", type_cdata);
- cdatae = type_cdata[strlen(type_cdata) - 1];
- if ((cdatae != '*') && (cdatae != ' '))
{
- fputc(' ', privf);
- }
-
- output_cdata(privf, priv_node, GENBIND_NODE_TYPE_IDENT);
- fprintf(privf, ";\n");
-
- priv_node = genbind_node_find_type(
- genbind_node_getnode(interfacee->class),
- priv_node,
- GENBIND_NODE_TYPE_PRIVATE);
- }
-
- fprintf(privf, "} %s_private_t;\n\n",
interfacee->class_name);
-
- }
-
- close_header(ir, privf, "private");
-
- return 0;
-}
-
-/**
- * generate prototype header
- */
-static int
-output_prototype_header(struct ir *ir)
-{
- int idx;
- FILE *protof;
-
- /* open header */
- protof = open_header(ir, "prototype");
-
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *interfacee;
- struct genbind_node *init_node;
-
- interfacee = ir->entries + idx;
-
- /* do not generate prototype declarations for interfaces marked
- * no output
- */
- if ((interfacee->type == IR_ENTRY_TYPE_INTERFACE) &&
- (interfacee->u.interface.noobject)) {
- continue;
- }
-
- /* prototype declaration */
- fprintf(protof, "duk_ret_t %s_%s___proto(duk_context
*ctx);\n",
- DLPFX, interfacee->class_name);
-
- /** \todo if the interface has no references (no other
- * interface inherits from it) there is no reason to export
- * the initalisor/finaliser as no other class
- * constructor/destructor should call them. Additionally the
- * init/fini definition should be made static.
- */
-
- /* finaliser declaration */
- fprintf(protof,
- "void %s_%s___fini(duk_context *ctx, %s_private_t
*priv);\n",
- DLPFX, interfacee->class_name, interfacee->class_name);
-
- /* find the initialisor method on the class (if any) */
- init_node = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_INIT);
-
- /* initialisor definition */
- output_interface_init_declaration(protof, interfacee, init_node);
- fprintf(protof, ";\n\n");
- }
-
- close_header(ir, protof, "prototype");
-
- return 0;
-}
-
-/**
- * generate makefile fragment
- */
-static int
-output_makefile(struct ir *ir)
-{
- int idx;
- FILE *makef;
-
- /* open output file */
- makef = genb_fopen_tmp("Makefile");
- if (makef == NULL) {
- return -1;
- }
-
- fprintf(makef, "# duk libdom makefile fragment\n\n");
-
- fprintf(makef, "NSGENBIND_SOURCES:=binding.c ");
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *interfacee;
-
- interfacee = ir->entries + idx;
-
- /* no source for interfaces marked no output */
- if ((interfacee->type == IR_ENTRY_TYPE_INTERFACE) &&
- (interfacee->u.interface.noobject)) {
- continue;
- }
-
- fprintf(makef, "%s ", interfacee->filename);
- }
- fprintf(makef, "\nNSGENBIND_PREFIX:=%s\n", options->outdirname);
-
- genb_fclose_tmp(makef, "Makefile");
-
- return 0;
-}
-
-
-/**
- * generate binding header
- *
- * The binding header contains all the duk-libdom specific binding interface
- * macros and definitions.
- *
- * the create prototypes interface is used to cause all the prototype creation
- * functions for all generated classes to be called in the correct order with
- * the primary global (if any) generated last.
- */
-static int
-output_binding_header(struct ir *ir)
-{
- FILE *bindf;
-
- /* open header */
- bindf = open_header(ir, "binding");
-
- fprintf(bindf,
- "#define _MAGIC(S) (\"%s\" S)\n"
- "#define MAGIC(S) _MAGIC(#S)\n"
- "#define PROTO_MAGIC MAGIC(PROTOTYPES)\n"
- "#define PRIVATE_MAGIC MAGIC(PRIVATE)\n"
- "#define INIT_MAGIC MAGIC(INIT)\n"
- "#define NODE_MAGIC MAGIC(NODE_MAP)\n"
- "#define _PROTO_NAME(K) _MAGIC(\"PROTOTYPE_\" K)\n"
- "#define PROTO_NAME(K) _PROTO_NAME(#K)\n"
- "#define _PROP_NAME(K,V) _MAGIC(K \"_PROPERTY_\"
V)\n"
- "#define PROP_NAME(K,V) _PROP_NAME(#K,#V)\n"
- "\n",
- MAGICPFX);
-
- /* declaration of constant string values */
- fprintf(bindf,
- "/* Constant strings */\n"
- "extern const char *%s_error_fmt_argument;\n"
- "extern const char *%s_error_fmt_string_type;\n"
- "extern const char *%s_error_fmt_bool_type;\n"
- "extern const char *%s_error_fmt_number_type;\n"
- "extern const char *%s_magic_string_private;\n"
- "extern const char *%s_magic_string_prototypes;\n"
- "\n",
- DLPFX, DLPFX, DLPFX, DLPFX, DLPFX, DLPFX);
-
- fprintf(bindf,
- "duk_bool_t %s_instanceof(duk_context *ctx, const char
*klass);\n",
- DLPFX);
-
- fprintf(bindf,
- "duk_ret_t %s_create_prototypes(duk_context *ctx);\n", DLPFX);
-
- close_header(ir, bindf, "binding");
-
- return 0;
-}
-
-
-/**
- * generate binding source
- *
- * The binding header contains all the duk-libdom specific binding
- * implementations.
- */
-static int
-output_binding_src(struct ir *ir)
-{
- int idx;
- FILE *bindf;
- struct ir_entry *pglobale = NULL;
- char *proto_name;
-
- /* open output file */
- bindf = genb_fopen_tmp("binding.c");
- if (bindf == NULL) {
- return -1;
- }
-
- /* tool preface */
- output_tool_preface(bindf);
-
- /* binding preface */
- output_cdata(bindf,
- ir->binding_node,
- GENBIND_NODE_TYPE_PREFACE);
-
- output_tool_prologue(bindf);
-
- /* binding prologue */
- output_cdata(bindf,
- ir->binding_node,
- GENBIND_NODE_TYPE_PROLOGUE);
-
-
- fprintf(bindf, "\n");
-
- fprintf(bindf,
- "/* Error format strings */\n"
- "const char *%s_error_fmt_argument =\"%%d argument required,
but ony %%d present.\";\n"
- "const char *%s_error_fmt_string_type =\"argument %%d (%%s)
requires a string\";\n"
- "const char *%s_error_fmt_bool_type =\"argument %%d (%%s)
requires a bool\";\n"
- "const char *%s_error_fmt_number_type =\"argument %%d (%%s)
requires a number\";\n",
- DLPFX, DLPFX, DLPFX, DLPFX);
-
- fprintf(bindf, "\n");
-
- fprintf(bindf,
- "/* Magic identifiers */\n"
- "const char *%s_magic_string_private
=\"%sPRIVATE\";\n"
- "const char *%s_magic_string_prototypes
=\"%sPROTOTYPES\";\n",
- DLPFX, MAGICPFX, DLPFX, MAGICPFX);
-
- fprintf(bindf, "\n");
-
-
- /* instance of helper */
- fprintf(bindf,
- "duk_bool_t\n"
- "%s_instanceof(duk_context *ctx, const char *klass)\n",
- DLPFX);
- fprintf(bindf,
- "{\n"
- "\t/* ... ??? */\n"
- "\tif (!duk_check_type(ctx, -1, DUK_TYPE_OBJECT)) {\n"
- "\t\treturn false;\n"
- "\t}\n"
- "\t/* ... obj */\n"
- "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n"
- "\t/* ... obj protos */\n"
- "\tduk_get_prop_string(ctx, -1, klass);\n"
- "\t/* ... obj protos goalproto */\n"
- "\tduk_get_prototype(ctx, -3);\n"
- "\t/* ... obj protos goalproto proto? */\n"
- "\twhile (!duk_is_undefined(ctx, -1)) {\n"
- "\t\tif (duk_strict_equals(ctx, -1, -2)) {\n"
- "\t\t\tduk_pop_3(ctx);\n"
- "\t\t\treturn true;\n"
- "\t\t}\n"
- "\t\tduk_get_prototype(ctx, -1);\n"
- "\t\t/* ... obj protos goalproto proto proto? */\n"
- "\t\tduk_replace(ctx, -2);\n"
- "\t\t/* ... obj protos goalproto proto? */\n"
- "\t}\n"
- "\tduk_pop_3(ctx);\n"
- "\t/* ... obj */\n"
- "\treturn false;\n"
- "}\n"
- "\n",
- DLPFX);
-
- /* prototype creation helper function */
- fprintf(bindf,
- "static duk_ret_t\n"
- "%s_to_string(duk_context *ctx)\n"
- "{\n"
- "\t/* */\n"
- "\tduk_push_this(ctx);\n"
- "\t/* this */\n"
- "\tduk_get_prototype(ctx, -1);\n"
- "\t/* this proto */\n"
- "\tduk_get_prop_string(ctx, -1,
\"%sklass_name\");\n"
- "\t/* this proto classname */\n"
- "\tduk_push_string(ctx, \"[object \");\n"
- "\t/* this proto classname str */\n"
- "\tduk_insert(ctx, -2);\n"
- "\t/* this proto str classname */\n"
- "\tduk_push_string(ctx, \"]\");\n"
- "\t/* this proto str classname str */\n"
- "\tduk_concat(ctx, 3);\n"
- "\t/* this proto str */\n"
- "\treturn 1;\n"
- "}\n"
- "\n",
- DLPFX,
- MAGICPFX);
-
- fprintf(bindf,
- "static duk_ret_t %s_create_prototype(duk_context *ctx,\n",
- DLPFX);
- fprintf(bindf,
- "\t\t\t\t\tduk_safe_call_function genproto,\n"
- "\t\t\t\t\tconst char *proto_name,\n"
- "\t\t\t\t\tconst char *klass_name)\n"
- "{\n"
- "\tduk_int_t ret;\n"
- "\tduk_push_object(ctx);\n"
- "\tif ((ret = duk_safe_call(ctx, genproto, 1, 1)) !=
DUK_EXEC_SUCCESS) {\n"
- "\t\tduk_pop(ctx);\n"
- "\t\tLOG(\"Failed to register prototype for %%s\",
proto_name + 2);\n"
- "\t\treturn ret;\n"
- "\t}\n"
- "\t/* top of stack is the ready prototype, inject it */\n"
- "\tduk_push_string(ctx, klass_name);\n"
- "\tduk_put_prop_string(ctx, -2,
\"%sklass_name\");\n"
- "\tduk_push_c_function(ctx, %s_to_string, 0);\n"
- "\tduk_put_prop_string(ctx, -2, \"toString\");\n"
- "\tduk_push_string(ctx, \"toString\");\n"
- "\tduk_def_prop(ctx, -2, DUK_DEFPROP_HAVE_ENUMERABLE);\n"
- "\tduk_put_global_string(ctx, proto_name);\n"
- "\treturn DUK_ERR_NONE;\n"
- "}\n\n",
- MAGICPFX,
- DLPFX);
-
- /* generate prototype creation */
- fprintf(bindf,
- "duk_ret_t %s_create_prototypes(duk_context *ctx)\n", DLPFX);
-
- fprintf(bindf, "{\n");
-
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *interfacee;
-
- interfacee = ir->entries + idx;
-
- /* do not generate prototype calls for interfaces marked
- * no output
- */
- if (interfacee->type == IR_ENTRY_TYPE_INTERFACE) {
- if (interfacee->u.interface.noobject) {
- continue;
- }
-
- if (interfacee->u.interface.primary_global) {
- pglobale = interfacee;
- continue;
- }
- }
- proto_name = get_prototype_name(interfacee->name);
-
- fprintf(bindf,
- "\t%s_create_prototype(ctx, %s_%s___proto, \"%s\",
\"%s\");\n",
- DLPFX,
- DLPFX,
- interfacee->class_name,
- proto_name,
- interfacee->name);
-
- free(proto_name);
- }
-
- if (pglobale != NULL) {
- fprintf(bindf, "\n\t/* Global object prototype is last */\n");
-
- proto_name = get_prototype_name(pglobale->name);
- fprintf(bindf,
- "\t%s_create_prototype(ctx, %s_%s___proto, \"%s\",
\"%s\");\n",
- DLPFX,
- DLPFX,
- pglobale->class_name,
- proto_name,
- pglobale->name);
- free(proto_name);
- }
-
- fprintf(bindf, "\n\treturn DUK_ERR_NONE;\n");
-
- fprintf(bindf, "}\n");
-
- /* binding postface */
- output_cdata(bindf,
- ir->binding_node,
- GENBIND_NODE_TYPE_POSTFACE);
-
- genb_fclose_tmp(bindf, "binding.c");
-
- return 0;
-}
-
-static int output_interfaces_dictionaries(struct ir *ir)
-{
- int res;
- int idx;
-
- /* generate interfaces */
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *irentry;
-
- irentry = ir->entries + idx;
-
- switch (irentry->type) {
- case IR_ENTRY_TYPE_INTERFACE:
- /* do not generate class for interfaces marked no
- * output
- */
- if (!irentry->u.interface.noobject) {
- res = output_interface(ir, irentry);
- if (res != 0) {
- return res;
- }
- }
- break;
-
- case IR_ENTRY_TYPE_DICTIONARY:
- res = output_dictionary(ir, irentry);
- if (res != 0) {
- return res;
- }
-
- default:
- break;
- }
- }
-
- return 0;
-}
-
-int duk_libdom_output(struct ir *ir)
-{
- int idx;
- int res = 0;
-
- /* process ir entries for output */
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *irentry;
-
- irentry = ir->entries + idx;
-
- /* compute class name */
- irentry->class_name = gen_class_name(irentry);
-
- if (irentry->class_name != NULL) {
- int ifacenamelen;
-
- /* generate source filename */
- ifacenamelen = strlen(irentry->class_name) + 4;
- irentry->filename = malloc(ifacenamelen);
- snprintf(irentry->filename,
- ifacenamelen,
- "%s.c",
- irentry->class_name);
- }
- }
-
- res = output_interfaces_dictionaries(ir);
- if (res != 0) {
- goto output_err;
- }
-
- /* generate private header */
- res = output_private_header(ir);
- if (res != 0) {
- goto output_err;
- }
-
- /* generate prototype header */
- res = output_prototype_header(ir);
- if (res != 0) {
- goto output_err;
- }
-
- /* generate binding header */
- res = output_binding_header(ir);
- if (res != 0) {
- goto output_err;
- }
-
- /* generate binding source */
- res = output_binding_src(ir);
- if (res != 0) {
- goto output_err;
- }
-
- /* generate makefile fragment */
- res = output_makefile(ir);
-
-output_err:
-
- return res;
-}
diff --git a/src/duk-libdom.c b/src/duk-libdom.c
index 3e20d13..45e7e79 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom.c
@@ -3,7 +3,7 @@
* This file is part of nsgenbind.
* Licensed under the MIT License,
*
http://www.opensource.org/licenses/mit-license.php
- * Copyright 2012 Vincent Sanders <vince(a)netsurf-browser.org>
+ * Copyright 2015 Vincent Sanders <vince(a)netsurf-browser.org>
*/
#include <stdio.h>
@@ -27,53 +27,6 @@
#define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_"
-#define NSGENBIND_PREAMBLE \
- "/* Generated by nsgenbind\n" \
- " *\n" \
- " * nsgenbind is published under the MIT Licence.\n" \
- " * nsgenbind is similar to a compiler is a purely transformative tool
which\n" \
- " * explicitly makes no copyright claim on this generated output\n" \
- " */"
-
-/**
- * Output code to create a private structure
- *
- */
-static int output_create_private(FILE* outf, char *class_name)
-{
- fprintf(outf, "\t/* create private data and attach to instance */\n");
- 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, %s_magic_string_private);\n\n",
- DLPFX);
-
- return 0;
-}
-
-/**
- * generate code that gets a private pointer
- */
-static int output_safe_get_private(FILE* outf, char *class_name, int idx)
-{
- fprintf(outf,
- "\t%s_private_t *priv;\n", class_name);
- fprintf(outf,
- "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n",
- idx, DLPFX);
- fprintf(outf,
- "\tpriv = duk_get_pointer(ctx, -1);\n");
- fprintf(outf,
- "\tduk_pop(ctx);\n");
- fprintf(outf,
- "\tif (priv == NULL) return 0;\n\n");
-
- return 0;
-}
-
-
/**
* generate a duktape prototype name
*/
@@ -95,190 +48,6 @@ static char *get_prototype_name(const char *interface_name)
return proto_name;
}
-/**
- * generate code that gets a prototype by name
- */
-static int output_get_prototype(FILE* outf, const char *interface_name)
-{
- char *proto_name;
-
- proto_name = get_prototype_name(interface_name);
-
- fprintf(outf,
- "\t/* get prototype */\n");
- fprintf(outf,
- "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n",
- DLPFX);
- fprintf(outf,
- "\tduk_get_prop_string(ctx, -1, \"%s\");\n",
- proto_name);
- fprintf(outf,
- "\tduk_replace(ctx, -2);\n");
-
- free(proto_name);
-
- return 0;
-}
-
-/**
- * generate code that sets a destructor in a prototype
- */
-static int output_set_destructor(FILE* outf, char *class_name, int idx)
-{
- fprintf(outf, "\t/* Set the destructor */\n");
- fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
- fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___destructor, 1);\n",
- DLPFX, class_name);
- fprintf(outf, "\tduk_set_finalizer(ctx, -2);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-/**
- * generate code that sets a constructor in a prototype
- */
-static int
-output_set_constructor(FILE* outf, char *class_name, int idx, int argc)
-{
- fprintf(outf, "\t/* Set the constructor */\n");
- fprintf(outf, "\tduk_dup(ctx, %d);\n", idx);
- fprintf(outf, "\tduk_push_c_function(ctx, %s_%s___constructor,
%d);\n",
- DLPFX, class_name, 1 + argc);
- fprintf(outf, "\tduk_put_prop_string(ctx, -2,
\"%sINIT\");\n",
- MAGICPFX);
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-static int
-output_dump_stack(FILE* outf)
-{
- if (options->dbglog) {
- /* dump stack */
- fprintf(outf, "\tduk_push_context_dump(ctx);\n");
- fprintf(outf, "\tLOG(\"Stack: %%s\", duk_to_string(ctx,
-1));\n");
- fprintf(outf, "\tduk_pop(ctx);\n");
- }
- return 0;
-}
-
-/**
- * generate code that adds a method in a prototype
- */
-static int
-output_add_method(FILE* outf,
- const char *class_name,
- const char *method)
-{
- 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, DUK_VARARGS);\n",
- DLPFX, class_name, method);
- output_dump_stack(outf);
- 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;
-}
-
-/**
- * Generate source to populate a read/write property on a prototype
- */
-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);
- output_dump_stack(outf);
- fprintf(outf, "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_SETTER |\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE
|\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-/**
- * Generate source to populate a readonly property on a prototype
- */
-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);
- output_dump_stack(outf);
- fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER |\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE
|\n");
- fprintf(outf, "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
-
- return 0;
-}
-
-/**
- * Generate source to add a constant int value on a prototype
- */
-static int
-output_prototype_constant_int(FILE *outf, const char *constant_name, int value)
-{
- fprintf(outf, "\tduk_dup(ctx, 0);\n");
- fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n",
constant_name);
- fprintf(outf, "\tduk_push_int(ctx, %d);\n", value);
- fprintf(outf, "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |\n");
- fprintf(outf, "\t DUK_DEFPROP_HAVE_WRITABLE |
DUK_DEFPROP_HAVE_ENUMERABLE |\n");
- fprintf(outf, "\t DUK_DEFPROP_ENUMERABLE |
DUK_DEFPROP_HAVE_CONFIGURABLE);\n");
- fprintf(outf, "\tduk_pop(ctx);\n\n");
- return 0;
-}
-
-/**
- * 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,
%s_magic_string_private);\n",
- DLPFX);
- fprintf(outf, "\tpriv = duk_get_pointer(ctx, -1);\n");
- fprintf(outf, "\tduk_pop_2(ctx);\n");
- fprintf(outf, "\tif (priv == NULL) {\n");
- if (options->dbglog) {
- fprintf(outf, "\t\tLOG(\"priv failed\");\n");
- }
- fprintf(outf, "\t\treturn 0; /* can do? No can do. */\n");
- fprintf(outf, "\t}\n\n");
-
- return 0;
-}
-
-/**
- * generate preface block for nsgenbind
- */
-static int output_tool_preface(FILE* outf)
-{
- fprintf(outf, "%s\n", NSGENBIND_PREAMBLE);
-
- return 0;
-}
/**
* Generate a C class name for the interface.
@@ -345,34 +114,6 @@ static char *gen_class_name(struct ir_entry *interfacee)
return name;
}
-/**
- * output character data of node of given type.
- *
- * used for any cdata including pre/pro/epi/post sections
- *
- * \param outf The file handle to write output.
- * \param node The node to search.
- * \param nodetype the type of child node to search for.
- * \return The number of nodes written or 0 for none.
- */
-static int
-output_cdata(FILE* outf,
- struct genbind_node *node,
- enum genbind_node_type nodetype)
-{
- char *cdata;
- int res = 0;
-
- cdata = genbind_node_gettext(
- genbind_node_find_type(
- genbind_node_getnode(node),
- NULL, nodetype));
- if (cdata != NULL) {
- fprintf(outf, "%s", cdata);
- res = 1;
- }
- return res;
-}
static FILE *open_header(struct ir *ir, const char *name)
{
@@ -431,166 +172,7 @@ static int close_header(struct ir *ir,
}
-/**
- * generate the interface constructor
- */
-static int
-output_interface_constructor(FILE* outf, struct ir_entry *interfacee)
-{
- int init_argc;
-
- /* constructor definition */
- fprintf(outf,
- "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n",
- DLPFX, interfacee->class_name);
- fprintf(outf,"{\n");
-
- output_create_private(outf, interfacee->class_name);
-
- /* generate call to initialisor */
- fprintf(outf,
- "\t%s_%s___init(ctx, priv",
- DLPFX, interfacee->class_name);
- for (init_argc = 1;
- init_argc <= interfacee->class_init_argc;
- init_argc++) {
- fprintf(outf, ", duk_get_pointer(ctx, %d)", init_argc);
- }
- fprintf(outf, ");\n");
-
-
- 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 ir_entry *interfacee)
-{
- /* destructor definition */
- fprintf(outf,
- "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n",
- DLPFX, interfacee->class_name);
- fprintf(outf,"{\n");
-
- output_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 ir_entry *interfacee,
- struct ir_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 = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_INIT);
-
- inh_init_node = genbind_node_find_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_declaration(FILE* outf,
@@ -626,997 +208,6 @@ output_interface_init_declaration(FILE* outf,
return 0;
}
-static int
-output_interface_init(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_entry *inherite)
-{
- struct genbind_node *init_node;
- int res;
-
- /* find the initialisor method on the class (if any) */
- init_node = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_INIT);
-
- /* initialisor definition */
- output_interface_init_declaration(outf, interfacee, init_node);
-
- 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 ir_entry *interfacee,
- struct ir_entry *inherite)
-{
- struct genbind_node *fini_node;
-
- /* find the finaliser method on the class (if any) */
- fini_node = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_FINI);
-
- /* finaliser definition */
- fprintf(outf,
- "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n",
- DLPFX, interfacee->class_name, interfacee->class_name);
- fprintf(outf,"{\n");
-
- /* generate log statement */
- if (options->dbglog) {
- fprintf(outf,
- "\tLOG(\"Finalise %%p\", duk_get_heapptr(ctx,
0));\n" );
- }
-
- /* 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 */
- if (inherite != NULL) {
- fprintf(outf,
- "\t%s_%s___fini(ctx, &priv->parent);\n",
- DLPFX, inherite->class_name);
- }
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-
-/**
- * generate a prototype add for a single class method
- */
-static int
-output_prototype_method(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
-
- if (operatione->name != NULL) {
- /* normal method on prototype */
- output_add_method(outf,
- interfacee->class_name,
- operatione->name);
- } else {
- /* special method on prototype */
- fprintf(outf,
- "\t/* Special method on prototype - UNIMPLEMENTED
*/\n\n");
- }
-
- return 0;
-}
-
-/**
- * generate prototype method definitions
- */
-static int
-output_prototype_methods(FILE *outf, struct ir_entry *entry)
-{
- int opc;
- int res = 0;
-
- for (opc = 0; opc < entry->u.interface.operationc; opc++) {
- res = output_prototype_method(
- outf,
- entry,
- entry->u.interface.operationv + opc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-
-static int
-output_prototype_attribute(FILE *outf,
- struct ir_entry *interfacee,
- struct ir_attribute_entry *attributee)
-{
- if (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) {
- return output_populate_ro_property(outf,
- interfacee->class_name,
- attributee->name);
- }
- return output_populate_rw_property(outf,
- interfacee->class_name,
- attributee->name);
-}
-
-/**
- * generate prototype attribute definitions
- */
-static int
-output_prototype_attributes(FILE *outf, struct ir_entry *entry)
-{
- int attrc;
- int res = 0;
-
- for (attrc = 0; attrc < entry->u.interface.attributec; attrc++) {
- res = output_prototype_attribute(
- outf,
- entry,
- entry->u.interface.attributev + attrc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-/**
- * output constants on the prototype
- *
- * \todo This implementation assumes the constant is a literal int and should
- * check the type node base value.
- */
-static int
-output_prototype_constant(FILE *outf,
- struct ir_constant_entry *constante)
-{
- int *value;
-
- value = webidl_node_getint(
- webidl_node_find_type(
- webidl_node_getnode(constante->node),
- NULL,
- WEBIDL_NODE_TYPE_LITERAL_INT));
-
- output_prototype_constant_int(outf, constante->name, *value);
-
- return 0;
-}
-
-/**
- * generate prototype constant definitions
- */
-static int
-output_prototype_constants(FILE *outf, struct ir_entry *entry)
-{
- int attrc;
- int res = 0;
-
- for (attrc = 0; attrc < entry->u.interface.constantc; attrc++) {
- res = output_prototype_constant(
- outf,
- entry->u.interface.constantv + attrc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-static int
-output_global_create_prototype(FILE* outf,
- struct ir *ir,
- struct ir_entry *interfacee)
-{
- int idx;
-
- fprintf(outf, "\t/* Create interface objects */\n");
- for (idx = 0; idx < ir->entryc; idx++) {
- struct ir_entry *entry;
-
- entry = ir->entries + idx;
-
- if (entry->type == IR_ENTRY_TYPE_INTERFACE) {
-
- if (entry->u.interface.noobject) {
- continue;
- }
-
- if (entry == interfacee) {
- fprintf(outf, "\tduk_dup(ctx, 0);\n");
- } else {
- output_get_prototype(outf, entry->name);
- }
-
- fprintf(outf,
- "\tdukky_inject_not_ctr(ctx, 0,
\"%s\");\n",
- entry->name);
- }
- }
- return 0;
-}
-/**
- * generate the interface prototype creator
- */
-static int
-output_interface_prototype(FILE* outf,
- struct ir *ir,
- struct ir_entry *interfacee,
- struct ir_entry *inherite)
-{
- struct genbind_node *proto_node;
-
- /* find the prototype method on the class */
- proto_node = genbind_node_find_method(interfacee->class,
- NULL,
- GENBIND_METHOD_TYPE_PROTOTYPE);
-
- /* prototype definition */
- fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx)\n",
- DLPFX, interfacee->class_name);
- fprintf(outf,"{\n");
-
- /* Output any binding data first */
- if (output_cdata(outf, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) {
- fprintf(outf,"\n");
- }
-
- /* generate prototype chaining if interface has a parent */
- if (inherite != NULL) {
- fprintf(outf,
- "\t/* Set this prototype's prototype (left-parent)
*/\n");
- output_get_prototype(outf, inherite->name);
- 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 constants */
- output_prototype_constants(outf, interfacee);
-
- /* if this is the global object, output all interfaces which do not
- * prevent us from doing so
- */
- if (interfacee->u.interface.primary_global) {
- output_global_create_prototype(outf, ir, interfacee);
- }
-
- /* generate setting of destructor */
- output_set_destructor(outf, interfacee->class_name, 0);
-
- /* generate setting of constructor */
- output_set_constructor(outf,
- interfacee->class_name,
- 0,
- interfacee->class_init_argc);
-
- fprintf(outf,"\treturn 1; /* The prototype object */\n");
-
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-/**
- * generate a single class method for an interface operation with elipsis
- */
-static int
-output_interface_elipsis_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- int cdatac; /* cdata blocks output */
-
- /* overloaded method definition */
- fprintf(outf,
- "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
- DLPFX, interfacee->class_name, operatione->name);
- fprintf(outf,"{\n");
-
- /**
- * \todo This is where the checking of the parameters to the
- * operation with elipsis should go
- */
- WARN(WARNING_UNIMPLEMENTED,
- "Elipsis parameetrs not checked: method %s::%s();",
- interfacee->name, operatione->name);
-
- output_get_method_private(outf, interfacee->class_name);
-
- cdatac = output_cdata(outf,
- operatione->method,
- GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- /* no implementation so generate default */
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: method %s::%s();",
- interfacee->name, operatione->name);
- fprintf(outf,"\treturn 0;\n");
- }
-
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-/**
- * generate a single class method for an interface overloaded operation
- */
-static int
-output_interface_overloaded_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- int cdatac; /* cdata blocks output */
-
- /* overloaded method definition */
- fprintf(outf,
- "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
- DLPFX, interfacee->class_name, operatione->name);
- fprintf(outf,"{\n");
-
- /** \todo This is where the checking of the parameters to the
- * overloaded operation should go
- */
-
- output_get_method_private(outf, interfacee->class_name);
-
- cdatac = output_cdata(outf,
- operatione->method,
- GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- /* no implementation so generate default */
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: method %s::%s();",
- interfacee->name, operatione->name);
- fprintf(outf,"\treturn 0;\n");
- }
-
- fprintf(outf, "}\n\n");
-
- return 0;
-}
-
-/**
- * generate a single class method for an interface special operation
- */
-static int
-output_interface_special_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- /* special method definition */
- fprintf(outf, "/* Special method definition - UNIMPLEMENTED */\n\n");
-
- WARN(WARNING_UNIMPLEMENTED,
- "Special operation on interface %s (operation entry %p)",
- interfacee->name,
- operatione);
-
- return 0;
-}
-
-/**
- * generate default values on the duk stack
- */
-static int
-output_operation_optional_defaults(FILE* outf,
- struct ir_operation_argument_entry *argumentv,
- int argumentc)
-{
- int argc;
- for (argc = 0; argc < argumentc; argc++) {
- struct ir_operation_argument_entry *cure;
- struct webidl_node *lit_node; /* literal node */
- enum webidl_node_type lit_type;
- int *lit_int;
- char *lit_str;
-
- cure = argumentv + argc;
-
- lit_node = webidl_node_getnode(
- webidl_node_find_type(
- webidl_node_getnode(cure->node),
- NULL,
- WEBIDL_NODE_TYPE_OPTIONAL));
-
- if (lit_node != NULL) {
-
- lit_type = webidl_node_gettype(lit_node);
-
- switch (lit_type) {
- case WEBIDL_NODE_TYPE_LITERAL_NULL:
- fprintf(outf,
- "\t\tduk_push_null(ctx);\n");
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_INT:
- lit_int = webidl_node_getint(lit_node);
- fprintf(outf,
- "\t\tduk_push_int(ctx, %d);\n",
- *lit_int);
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_BOOL:
- lit_int = webidl_node_getint(lit_node);
- fprintf(outf,
- "\t\tduk_push_boolean(ctx, %d);\n",
- *lit_int);
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_STRING:
- lit_str = webidl_node_gettext(lit_node);
- fprintf(outf,
- "\t\tduk_push_string(ctx,
\"%s\");\n",
- lit_str);
- break;
-
- case WEBIDL_NODE_TYPE_LITERAL_FLOAT:
- default:
- fprintf(outf,
- "\t\tduk_push_undefined(ctx);\n");
- break;
- }
- } else {
- fprintf(outf, "\t\tduk_push_undefined(ctx);\n");
- }
- }
- return 0;
-}
-
-static int
-output_operation_argument_type_check(
- FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione,
- struct ir_operation_overload_entry *overloade,
- int argidx)
-{
- struct ir_operation_argument_entry *argumente;
- struct webidl_node *type_node;
- enum webidl_type *argument_type;
-
- argumente = overloade->argumentv + argidx;
-
- type_node = webidl_node_find_type(
- webidl_node_getnode(argumente->node),
- NULL,
- WEBIDL_NODE_TYPE_TYPE);
-
- if (type_node == NULL) {
- fprintf(stderr, "%s:%s %dth argument %s has no type\n",
- interfacee->name,
- operatione->name,
- argidx,
- argumente->name);
- return -1;
- }
-
- argument_type = (enum webidl_type *)webidl_node_getint(
- webidl_node_find_type(
- webidl_node_getnode(type_node),
- NULL,
- WEBIDL_NODE_TYPE_TYPE_BASE));
-
- if (argument_type == NULL) {
- fprintf(stderr,
- "%s:%s %dth argument %s has no type base\n",
- interfacee->name,
- operatione->name,
- argidx,
- argumente->name);
- return -1;
- }
-
- if (*argument_type == WEBIDL_TYPE_ANY) {
- /* allowing any type needs no check */
- return 0;
- }
-
- fprintf(outf, "\tif (%s_argc > %d) {\n", DLPFX, argidx);
-
- switch (*argument_type) {
- case WEBIDL_TYPE_STRING:
- fprintf(outf,
- "\t\tif (!duk_is_string(ctx, %d)) {\n"
- "\t\t\tduk_error(ctx, DUK_ERR_ERROR,
%s_error_fmt_string_type, %d, \"%s\");\n"
- "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
- break;
-
- case WEBIDL_TYPE_BOOL:
- fprintf(outf,
- "\t\tif (!duk_is_boolean(ctx, %d)) {\n"
- "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_bool_type,
%d, \"%s\");\n"
- "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
- break;
-
- case WEBIDL_TYPE_FLOAT:
- case WEBIDL_TYPE_DOUBLE:
- case WEBIDL_TYPE_SHORT:
- case WEBIDL_TYPE_LONG:
- case WEBIDL_TYPE_LONGLONG:
- fprintf(outf,
- "\t\tif (!duk_is_number(ctx, %d)) {\n"
- "\t\t\tduk_error(ctx, DUK_ERR_ERROR,
%s_error_fmt_number_type, %d, \"%s\");\n"
- "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
- break;
-
-
- default:
- fprintf(outf,
- "\t\t/* unhandled type check */\n");
- }
-
- fprintf(outf, "\t}\n");
-
- return 0;
-}
-
-
-/**
- * generate a single class method for an interface operation
- */
-static int
-output_interface_operation(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_operation_entry *operatione)
-{
- int cdatac; /* cdata blocks output */
- struct ir_operation_overload_entry *overloade;
- int fixedargc; /* number of non optional arguments */
- int argidx; /* loop counter for arguments */
- int optargc; /* loop counter for optional arguments */
-
- if (operatione->name == NULL) {
- return output_interface_special_operation(outf,
- interfacee,
- operatione);
- }
-
- if (operatione->overloadc != 1) {
- return output_interface_overloaded_operation(outf,
- interfacee,
- operatione);
- }
-
- if (operatione->overloadv->elipsisc != 0) {
- return output_interface_elipsis_operation(outf,
- interfacee,
- operatione);
- }
-
- /* normal method definition */
- overloade = operatione->overloadv;
-
- fprintf(outf,
- "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
- DLPFX, interfacee->class_name, operatione->name);
- fprintf(outf,"{\n");
-
- /* check arguments */
-
- /* generate check for minimum number of parameters */
-
- fixedargc = overloade->argumentc - overloade->optionalc;
-
- fprintf(outf,
- "\t/* ensure the parameters are present */\n"
- "\tduk_idx_t %s_argc = duk_get_top(ctx);\n\t", DLPFX);
-
- if (fixedargc > 0) {
- fprintf(outf,
- "if (%s_argc < %d) {\n"
- "\t\t/* not enough arguments */\n"
- "\t\tduk_error(ctx, DUK_RET_TYPE_ERROR,
%s_error_fmt_argument, %d, %s_argc);\n"
- "\t} else ",
- DLPFX,
- fixedargc,
- DLPFX,
- fixedargc,
- DLPFX);
- }
-
- for (optargc = fixedargc;
- optargc < overloade->argumentc;
- optargc++) {
- fprintf(outf,
- "if (%s_argc == %d) {\n"
- "\t\t/* %d optional arguments need adding */\n",
- DLPFX,
- optargc,
- overloade->argumentc - optargc);
- output_operation_optional_defaults(outf,
- overloade->argumentv + optargc,
- overloade->argumentc - optargc);
- fprintf(outf,
- "\t} else ");
- }
-
- fprintf(outf,
- "if (%s_argc > %d) {\n"
- "\t\t/* remove extraneous parameters */\n"
- "\t\tduk_set_top(ctx, %d);\n"
- "\t}\n",
- DLPFX,
- overloade->argumentc,
- overloade->argumentc);
- fprintf(outf, "\n");
-
- /* generate argument type checks */
-
- fprintf(outf, "\t/* check types of passed arguments are correct
*/\n");
-
- for (argidx = 0; argidx < overloade->argumentc; argidx++) {
- output_operation_argument_type_check(outf,
- interfacee,
- operatione,
- overloade,
- argidx);
- }
-
- output_get_method_private(outf, interfacee->class_name);
-
- cdatac = output_cdata(outf,
- operatione->method,
- GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- /* no implementation so generate default */
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: method %s::%s();",
- interfacee->name, operatione->name);
- 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 ir_entry *ife)
-{
- int opc;
- int res = 0;
-
- for (opc = 0; opc < ife->u.interface.operationc; opc++) {
- res = output_interface_operation(
- outf,
- ife,
- ife->u.interface.operationv + opc);
- if (res != 0) {
- break;
- }
- }
-
- return res;
-}
-
-/**
- * Generate class property getter/setter for a single attribute
- */
-static int
-output_interface_attribute(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_attribute_entry *atributee)
-{
- int cdatac;
-
- /* 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);
-
- cdatac = output_cdata(outf, atributee->getter, GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: getter %s::%s();",
- interfacee->name, atributee->name);
-
- /* no implementation so generate default */
- 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);
-
- cdatac = output_cdata(outf, atributee->setter, GENBIND_NODE_TYPE_CDATA);
-
- if (cdatac == 0) {
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: setter %s::%s();",
- interfacee->name, atributee->name);
-
- /* no implementation so generate default */
- 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 ir_entry *ife)
-{
- int attrc;
-
- for (attrc = 0; attrc < ife->u.interface.attributec; attrc++) {
- output_interface_attribute(
- outf,
- ife,
- ife->u.interface.attributev + attrc);
- }
-
- return 0;
-}
-
-
-/**
- * generate preface block for nsgenbind
- */
-static int output_tool_prologue(FILE* outf)
-{
- char *fpath;
-
- fpath = genb_fpath("binding.h");
- fprintf(outf, "\n#include \"%s\"\n", fpath);
- free(fpath);
-
- fpath = genb_fpath("private.h");
- fprintf(outf, "#include \"%s\"\n", fpath);
- free(fpath);
-
- fpath = genb_fpath("prototype.h");
- fprintf(outf, "#include \"%s\"\n", fpath);
- free(fpath);
-
- return 0;
-}
-
-/**
- * generate a source file to implement a dictionary using duk and libdom.
- */
-static int output_dictionary(struct ir *ir, struct ir_entry *dictionarye)
-{
- FILE *ifacef;
- struct ir_entry *inherite;
- int res = 0;
-
- /* open output file */
- ifacef = genb_fopen_tmp(dictionarye->filename);
- if (ifacef == NULL) {
- return -1;
- }
-
- /* find parent interface entry */
- inherite = ir_inherit_entry(ir, dictionarye);
-
- /* tool preface */
- output_tool_preface(ifacef);
-
- /* binding preface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PREFACE);
-
- /* class preface */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PREFACE);
-
- /* tool prologue */
- output_tool_prologue(ifacef);
-
- /* binding prologue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PROLOGUE);
-
- /* class prologue */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_PROLOGUE);
-
- fprintf(ifacef, "\n");
-
- /* initialisor */
- res = output_interface_init(ifacef, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
- /* finaliser */
- res = output_interface_fini(ifacef, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
- /* constructor */
- res = output_interface_constructor(ifacef, dictionarye);
- if (res != 0) {
- goto op_error;
- }
-
- /* destructor */
- res = output_interface_destructor(ifacef, dictionarye);
- if (res != 0) {
- goto op_error;
- }
-
- /* prototype */
- res = output_interface_prototype(ifacef, ir, dictionarye, inherite);
- if (res != 0) {
- goto op_error;
- }
-
-
- fprintf(ifacef, "\n");
-
- /* class epilogue */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_EPILOGUE);
-
- /* binding epilogue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_EPILOGUE);
-
- /* class postface */
- output_cdata(ifacef, dictionarye->class, GENBIND_NODE_TYPE_POSTFACE);
-
- /* binding postface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_POSTFACE);
-
-op_error:
- genb_fclose_tmp(ifacef, dictionarye->filename);
-
- return res;
-}
-
-/**
- * generate a source file to implement an interface using duk and libdom.
- */
-static int output_interface(struct ir *ir, struct ir_entry *interfacee)
-{
- FILE *ifacef;
- struct ir_entry *inherite;
- int res = 0;
-
- /* open output file */
- ifacef = genb_fopen_tmp(interfacee->filename);
- if (ifacef == NULL) {
- return -1;
- }
-
- /* find parent interface entry */
- inherite = ir_inherit_entry(ir, interfacee);
-
- /* tool preface */
- output_tool_preface(ifacef);
-
- /* binding preface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PREFACE);
-
- /* class preface */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PREFACE);
-
- /* tool prologue */
- output_tool_prologue(ifacef);
-
- /* binding prologue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_PROLOGUE);
-
- /* class prologue */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_PROLOGUE);
-
- fprintf(ifacef, "\n");
-
- /* initialisor */
- 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);
-
- /* operations */
- output_interface_operations(ifacef, interfacee);
-
- /* attributes */
- output_interface_attributes(ifacef, interfacee);
-
- /* prototype */
- output_interface_prototype(ifacef, ir, interfacee, inherite);
-
- fprintf(ifacef, "\n");
-
- /* class epilogue */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_EPILOGUE);
-
- /* binding epilogue */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_EPILOGUE);
-
- /* class postface */
- output_cdata(ifacef, interfacee->class, GENBIND_NODE_TYPE_POSTFACE);
-
- /* binding postface */
- output_cdata(ifacef,
- ir->binding_node,
- GENBIND_NODE_TYPE_POSTFACE);
-
-op_error:
- genb_fclose_tmp(ifacef, interfacee->filename);
-
- return res;
-}
/**
* generate private header
diff --git a/src/duk-libdom.h b/src/duk-libdom.h
index 2ecd482..84fc497 100644
--- a/src/duk-libdom.h
+++ b/src/duk-libdom.h
@@ -9,6 +9,41 @@
#ifndef nsgenbind_duk_libdom_h
#define nsgenbind_duk_libdom_h
+/**
+ * Generate output for duktape and libdom bindings.
+ */
int duk_libdom_output(struct ir *ir);
+/**
+ * generate a source file to implement an interface using duk and libdom.
+ */
+int output_interface(struct ir *ir, struct ir_entry *interfacee);
+
+/**
+ * generate a source file to implement a dictionary using duk and libdom.
+ */
+int output_dictionary(struct ir *ir, struct ir_entry *dictionarye);
+
+/**
+ * generate preface block for nsgenbind
+ */
+int output_tool_preface(FILE* outf);
+
+/**
+ * generate preface block for nsgenbind
+ */
+int output_tool_prologue(FILE* outf);
+
+/**
+ * output character data of node of given type.
+ *
+ * used for any cdata including pre/pro/epi/post sections
+ *
+ * \param outf The file handle to write output.
+ * \param node The node to search.
+ * \param nodetype the type of child node to search for.
+ * \return The number of nodes written or 0 for none.
+ */
+int output_cdata(FILE* outf, struct genbind_node *node, enum genbind_node_type
nodetype);
+
#endif
--
NetSurf Generator for JavaScript bindings