From e031876dd52c9d789ec5a3e41156d99962126c2e Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 3 May 2019 17:29:45 +0100 Subject: Make file output use a common interface Signed-off-by: Vincent Sanders --- src/Makefile | 3 +- src/duk-libdom-common.c | 52 +-- src/duk-libdom-dictionary.c | 101 ++--- src/duk-libdom-generated.c | 100 ++--- src/duk-libdom-interface.c | 905 ++++++++++++++++++++++++++------------------ src/duk-libdom.c | 148 ++++---- src/duk-libdom.h | 29 +- src/nsgenbind.c | 1 + src/output.c | 106 ++++++ src/output.h | 42 ++ 10 files changed, 913 insertions(+), 574 deletions(-) create mode 100644 src/output.c create mode 100644 src/output.h diff --git a/src/Makefile b/src/Makefile index a525740..fa1ddc8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,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 \ +DIR_SOURCES := nsgenbind.c utils.c output.c \ + webidl-ast.c nsgenbind-ast.c ir.c \ duk-libdom.c duk-libdom-interface.c duk-libdom-dictionary.c \ duk-libdom-common.c duk-libdom-generated.c diff --git a/src/duk-libdom-common.c b/src/duk-libdom-common.c index c76f7a5..0cb1c0d 100644 --- a/src/duk-libdom-common.c +++ b/src/duk-libdom-common.c @@ -20,6 +20,7 @@ #include "nsgenbind-ast.h" #include "webidl-ast.h" #include "ir.h" +#include "output.h" #include "duk-libdom.h" #define NSGENBIND_PREFACE \ @@ -28,18 +29,18 @@ " * 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" \ - " */" + " */\n" /* exported interface documented in duk-libdom.h */ -int output_tool_preface(FILE* outf) +int output_tool_preface(struct opctx *outc) { - fprintf(outf, "%s\n", NSGENBIND_PREFACE); + outputf(outc, "%s", NSGENBIND_PREFACE); return 0; } /* exported interface documented in duk-libdom.h */ -int output_cdata(FILE* outf, +int output_cdata(struct opctx *outc, struct genbind_node *node, enum genbind_node_type nodetype) { @@ -51,15 +52,16 @@ int output_cdata(FILE* outf, genbind_node_getnode(node), NULL, nodetype)); if (cdata != NULL) { - fprintf(outf, "%s", cdata); + outputf(outc, "%s", cdata); res = 1; } return res; } /* exported interface documented in duk-libdom.h */ -int output_ccode(FILE* outf, struct genbind_node *node) +int output_ccode(struct opctx *outc, struct genbind_node *node) { + int res; int *line; char *filename; @@ -74,27 +76,31 @@ int output_ccode(FILE* outf, struct genbind_node *node) NULL, GENBIND_NODE_TYPE_FILE)); if ((line != NULL) && (filename != NULL)) { - fprintf(outf, "/* #line %d \"%s\" */\n", *line, filename); + outputf(outc, "#line %d \"%s\"\n", (*line) + 1, filename); + res = output_cdata(outc, node, GENBIND_NODE_TYPE_CDATA); + output_line(outc); + } else { + res = output_cdata(outc, node, GENBIND_NODE_TYPE_CDATA); } - return output_cdata(outf, node, GENBIND_NODE_TYPE_CDATA); + return res; } /* exported interface documented in duk-libdom.h */ -int output_tool_prologue(FILE* outf) +int output_tool_prologue(struct opctx *outc) { char *fpath; fpath = genb_fpath("binding.h"); - fprintf(outf, "\n#include \"%s\"\n", fpath); + outputf(outc, "\n#include \"%s\"\n", fpath); free(fpath); fpath = genb_fpath("private.h"); - fprintf(outf, "#include \"%s\"\n", fpath); + outputf(outc, "#include \"%s\"\n", fpath); free(fpath); fpath = genb_fpath("prototype.h"); - fprintf(outf, "#include \"%s\"\n", fpath); + outputf(outc, "#include \"%s\"\n", fpath); free(fpath); return 0; @@ -102,7 +108,7 @@ int output_tool_prologue(FILE* outf) /* exported interface documented in duk-libdom.h */ -int output_ctype(FILE *outf, struct genbind_node *node, bool identifier) +int output_ctype(struct opctx *outc, struct genbind_node *node, bool identifier) { const char *type_cdata = NULL; struct genbind_node *typename_node; @@ -113,7 +119,7 @@ int output_ctype(FILE *outf, struct genbind_node *node, bool identifier) while (typename_node != NULL) { type_cdata = genbind_node_gettext(typename_node); - fprintf(outf, "%s", type_cdata); + outputf(outc, "%s", type_cdata); typename_node = genbind_node_find_type( genbind_node_getnode(node), @@ -122,25 +128,25 @@ int output_ctype(FILE *outf, struct genbind_node *node, bool identifier) /* separate all but the last entry with spaces */ if (typename_node != NULL) { - fputc(' ', outf); + outputc(outc, ' '); } } if (identifier) { - if ((type_cdata != NULL) && - (type_cdata[0] != '*') && - (type_cdata[0] != ' ')) { - fputc(' ', outf); - } + if ((type_cdata != NULL) && + (type_cdata[0] != '*') && + (type_cdata[0] != ' ')) { + outputc(outc, ' '); + } - output_cdata(outf, node, GENBIND_NODE_TYPE_IDENT); + output_cdata(outc, node, GENBIND_NODE_TYPE_IDENT); } return 0; } /* exported interface documented in duk-libdom.h */ -int output_method_cdata(FILE* outf, +int output_method_cdata(struct opctx *outc, struct genbind_node *node, enum genbind_method_type sel_method_type) { @@ -160,7 +166,7 @@ int output_method_cdata(FILE* outf, GENBIND_NODE_TYPE_METHOD_TYPE)); if ((method_type != NULL) && (*method_type == sel_method_type)) { - output_cdata(outf, method, GENBIND_NODE_TYPE_CDATA); + output_cdata(outc, method, GENBIND_NODE_TYPE_CDATA); } method = genbind_node_find_type(genbind_node_getnode(node), diff --git a/src/duk-libdom-dictionary.c b/src/duk-libdom-dictionary.c index 8c80947..bc53147 100644 --- a/src/duk-libdom-dictionary.c +++ b/src/duk-libdom-dictionary.c @@ -20,6 +20,7 @@ #include "nsgenbind-ast.h" #include "webidl-ast.h" #include "ir.h" +#include "output.h" #include "duk-libdom.h" /** prefix for all generated functions */ @@ -100,11 +101,12 @@ get_member_default_str(struct ir_entry *dictionarye, return 0; } + /** * generate a single class method for an interface operation */ static int -output_member_acessor(FILE* outf, +output_member_acessor(struct opctx *outc, struct ir_entry *dictionarye, struct ir_operation_argument_entry *membere) { @@ -148,22 +150,22 @@ output_member_acessor(FILE* outf, switch (*argument_type) { case WEBIDL_TYPE_STRING: - fprintf(outf, + outputf(outc, "const char *\n" "%s_%s_get_%s(duk_context *ctx, duk_idx_t idx)\n" "{\n", DLPFX, dictionarye->class_name, membere->name); if (defl == NULL) { - fprintf(outf, + outputf(outc, "\tconst char *ret = NULL; /* No default */\n"); } else { - fprintf(outf, + outputf(outc, "\tconst char *ret = \"%s\"; /* Default value of %s */\n", defl, membere->name); } - fprintf(outf, + outputf(outc, "\t/* ... obj@idx ... */\n" "\tduk_get_prop_string(ctx, idx, \"%s\");\n" "\t/* ... obj@idx ... value/undefined */\n" @@ -179,22 +181,22 @@ output_member_acessor(FILE* outf, break; case WEBIDL_TYPE_BOOL: - fprintf(outf, + outputf(outc, "duk_bool_t\n" "%s_%s_get_%s(duk_context *ctx, duk_idx_t idx)\n" "{\n", DLPFX, dictionarye->class_name, membere->name); if (defl == NULL) { - fprintf(outf, + outputf(outc, "\tduk_bool_t ret = false; /* No default */\n"); } else { - fprintf(outf, + outputf(outc, "\tduk_bool_t ret = %s; /* Default value of %s */\n", defl, membere->name); } - fprintf(outf, + outputf(outc, "\t/* ... obj@idx ... */\n" "\tduk_get_prop_string(ctx, idx, \"%s\");\n" "\t/* ... obj@idx ... value/undefined */\n" @@ -212,21 +214,22 @@ output_member_acessor(FILE* outf, case WEBIDL_TYPE_SHORT: case WEBIDL_TYPE_LONG: case WEBIDL_TYPE_LONGLONG: - fprintf(outf, + outputf(outc, "duk_int_t\n" "%s_%s_get_%s(duk_context *ctx, duk_idx_t idx)\n" "{\n", DLPFX, dictionarye->class_name, membere->name); if (defl == NULL) { - fprintf(outf, "\tduk_int_t ret = 0; /* No default */\n"); + outputf(outc, + "\tduk_int_t ret = 0; /* No default */\n"); } else { - fprintf(outf, + outputf(outc, "\tduk_int_t ret = %s; /* Default value of %s */\n", defl, membere->name); } - fprintf(outf, + outputf(outc, "\t/* ... obj@idx ... */\n" "\tduk_get_prop_string(ctx, idx, \"%s\");\n" "\t/* ... obj@idx ... value/undefined */\n" @@ -242,19 +245,19 @@ output_member_acessor(FILE* outf, case WEBIDL_TYPE_FLOAT: case WEBIDL_TYPE_DOUBLE: - fprintf(outf, + outputf(outc, "duk_double_t\n" "%s_%s_get_%s(duk_context *ctx, duk_idx_t idx)\n", DLPFX, dictionarye->class_name, membere->name); - fprintf(outf, + outputf(outc, "{\n" "\tduk_double_t ret = %s; /* Default value of %s */\n" "\t/* ... obj@idx ... */\n" "\tduk_get_prop_string(ctx, idx, \"%s\");\n", defl, membere->name, membere->name); - fprintf(outf, + outputf(outc, "\t/* ... obj@idx ... value/undefined */\n" "\tif (!duk_is_undefined(ctx, -1)) {\n" "\t\t/* Note, this throws a duk_error if it's not a number */\n" @@ -271,7 +274,7 @@ output_member_acessor(FILE* outf, dictionarye->name, membere->name, *argument_type); - fprintf(outf, + outputf(outc, "/* Dictionary %s:%s unhandled type (%d) */\n\n", dictionarye->name, membere->name, @@ -286,7 +289,7 @@ output_member_acessor(FILE* outf, } static int -output_member_acessors(FILE* outf, struct ir_entry *dictionarye) +output_member_acessors(struct opctx *outc, struct ir_entry *dictionarye) { int memberc; int res = 0; @@ -295,7 +298,7 @@ output_member_acessors(FILE* outf, struct ir_entry *dictionarye) memberc < dictionarye->u.dictionary.memberc; memberc++) { res = output_member_acessor( - outf, + outc, dictionarye, dictionarye->u.dictionary.memberv + memberc); if (res != 0) { @@ -310,73 +313,72 @@ output_member_acessors(FILE* outf, struct ir_entry *dictionarye) /* exported function documented in duk-libdom.h */ int output_dictionary(struct ir *ir, struct ir_entry *dictionarye) { - FILE *ifacef; + struct opctx *dyop; int res = 0; - /* open output file */ - ifacef = genb_fopen_tmp(dictionarye->filename); - if (ifacef == NULL) { - return -1; + /* open the output */ + res = output_open(dictionarye->filename, &dyop); + if (res != 0) { + return res; } /* tool preface */ - output_tool_preface(ifacef); + output_tool_preface(dyop); /* binding preface */ - output_method_cdata(ifacef, + output_method_cdata(dyop, ir->binding_node, GENBIND_METHOD_TYPE_PREFACE); /* class preface */ - output_method_cdata(ifacef, + output_method_cdata(dyop, dictionarye->class, GENBIND_METHOD_TYPE_PREFACE); /* tool prologue */ - output_tool_prologue(ifacef); + output_tool_prologue(dyop); /* binding prologue */ - output_method_cdata(ifacef, + output_method_cdata(dyop, ir->binding_node, GENBIND_METHOD_TYPE_PROLOGUE); /* class prologue */ - output_method_cdata(ifacef, + output_method_cdata(dyop, dictionarye->class, GENBIND_METHOD_TYPE_PROLOGUE); - fprintf(ifacef, "\n"); + outputf(dyop, "\n"); - - res = output_member_acessors(ifacef, dictionarye); + res = output_member_acessors(dyop, dictionarye); if (res != 0) { goto op_error; } - fprintf(ifacef, "\n"); + outputf(dyop, "\n"); /* class epilogue */ - output_method_cdata(ifacef, + output_method_cdata(dyop, dictionarye->class, GENBIND_METHOD_TYPE_EPILOGUE); /* binding epilogue */ - output_method_cdata(ifacef, + output_method_cdata(dyop, ir->binding_node, GENBIND_METHOD_TYPE_EPILOGUE); /* class postface */ - output_method_cdata(ifacef, + output_method_cdata(dyop, dictionarye->class, GENBIND_METHOD_TYPE_POSTFACE); /* binding postface */ - output_method_cdata(ifacef, + output_method_cdata(dyop, ir->binding_node, GENBIND_METHOD_TYPE_POSTFACE); op_error: - genb_fclose_tmp(ifacef, dictionarye->filename); + output_close(dyop); return res; } @@ -385,9 +387,9 @@ op_error: * generate a single class method declaration for an interface operation */ static int -output_member_declaration(FILE* outf, - struct ir_entry *dictionarye, - struct ir_operation_argument_entry *membere) +output_member_declaration(struct opctx *outc, + struct ir_entry *dictionarye, + struct ir_operation_argument_entry *membere) { struct webidl_node *type_node; enum webidl_type *argument_type; @@ -422,13 +424,13 @@ output_member_declaration(FILE* outf, switch (*argument_type) { case WEBIDL_TYPE_STRING: - fprintf(outf, + outputf(outc, "const char *%s_%s_get_%s(duk_context *ctx, duk_idx_t idx);\n", DLPFX, dictionarye->class_name, membere->name); break; case WEBIDL_TYPE_BOOL: - fprintf(outf, + outputf(outc, "duk_bool_t %s_%s_get_%s(duk_context *ctx, duk_idx_t idx);\n", DLPFX, dictionarye->class_name, membere->name); break; @@ -436,20 +438,20 @@ output_member_declaration(FILE* outf, case WEBIDL_TYPE_SHORT: case WEBIDL_TYPE_LONG: case WEBIDL_TYPE_LONGLONG: - fprintf(outf, + outputf(outc, "duk_int_t %s_%s_get_%s(duk_context *ctx, duk_idx_t idx);\n", DLPFX, dictionarye->class_name, membere->name); break; case WEBIDL_TYPE_FLOAT: case WEBIDL_TYPE_DOUBLE: - fprintf(outf, + outputf(outc, "duk_double_t %s_%s_get_%s(duk_context *ctx, duk_idx_t idx);\n", DLPFX, dictionarye->class_name, membere->name); break; default: - fprintf(outf, + outputf(outc, "/* Dictionary %s:%s unhandled type (%d) */\n", dictionarye->name, membere->name, @@ -460,7 +462,8 @@ output_member_declaration(FILE* outf, } /* exported function documented in duk-libdom.h */ -int output_dictionary_declaration(FILE* outf, struct ir_entry *dictionarye) +int +output_dictionary_declaration(struct opctx *outc, struct ir_entry *dictionarye) { int memberc; int res = 0; @@ -469,7 +472,7 @@ int output_dictionary_declaration(FILE* outf, struct ir_entry *dictionarye) memberc < dictionarye->u.dictionary.memberc; memberc++) { res = output_member_declaration( - outf, + outc, dictionarye, dictionarye->u.dictionary.memberv + memberc); if (res != 0) { diff --git a/src/duk-libdom-generated.c b/src/duk-libdom-generated.c index 008f7dc..109b237 100644 --- a/src/duk-libdom-generated.c +++ b/src/duk-libdom-generated.c @@ -26,12 +26,13 @@ #include "nsgenbind-ast.h" #include "webidl-ast.h" #include "ir.h" +#include "output.h" #include "duk-libdom.h" static int -output_generated_attribute_user_getter(FILE* outf, - struct ir_entry *interfacee, - struct ir_attribute_entry *atributee) +output_generated_attribute_user_getter(struct opctx *outc, + struct ir_entry *interfacee, + struct ir_attribute_entry *atributee) { UNUSED(interfacee); @@ -45,7 +46,8 @@ output_generated_attribute_user_getter(FILE* outf, (atributee->name[1] != 'n')) { return -1; /* not onxxx */ } - fprintf(outf, + + outputf(outc, "\tdom_event_target *et = (dom_event_target *)(((node_private_t *)priv)->node);\n" "\tdom_string *name;\n" "\tdom_exception exc;\n\n" @@ -71,7 +73,7 @@ output_generated_attribute_user_getter(FILE* outf, /* exported function documented in duk-libdom.h */ int -output_generated_attribute_getter(FILE* outf, +output_generated_attribute_getter(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee) { @@ -84,16 +86,16 @@ output_generated_attribute_getter(FILE* outf, switch (atributee->typev[0].base) { case WEBIDL_TYPE_STRING: - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tdom_string *str;\n" "\n"); - fprintf(outf, + outputf(outc, "\texc = dom_%s_get_%s((struct dom_%s *)((node_private_t*)priv)->node, &str);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" @@ -105,11 +107,13 @@ output_generated_attribute_getter(FILE* outf, "\t\tdom_string_unref(str);\n" "\t} else {\n"); if (atributee->typev[0].nullable) { - fprintf(outf, "\t\tduk_push_null(ctx);\n"); + outputf(outc, + "\t\tduk_push_null(ctx);\n"); } else { - fprintf(outf, "\t\tduk_push_lstring(ctx, NULL, 0);\n"); + outputf(outc, + "\t\tduk_push_lstring(ctx, NULL, 0);\n"); } - fprintf(outf, + outputf(outc, "\t}\n" "\n" "\treturn 1;\n"); @@ -117,19 +121,21 @@ output_generated_attribute_getter(FILE* outf, case WEBIDL_TYPE_LONG: if (atributee->typev[0].modifier == WEBIDL_TYPE_MODIFIER_UNSIGNED) { - fprintf(outf, "\tdom_ulong l;\n"); + outputf(outc, + "\tdom_ulong l;\n"); } else { - fprintf(outf, "\tdom_long l;\n"); + outputf(outc, + "\tdom_long l;\n"); } - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\n"); - fprintf(outf, + outputf(outc, "\texc = dom_%s_get_%s((struct dom_%s *)((node_private_t*)priv)->node, &l);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" @@ -141,19 +147,21 @@ output_generated_attribute_getter(FILE* outf, case WEBIDL_TYPE_SHORT: if (atributee->typev[0].modifier == WEBIDL_TYPE_MODIFIER_UNSIGNED) { - fprintf(outf, "\tdom_ushort s;\n"); + outputf(outc, + "\tdom_ushort s;\n"); } else { - fprintf(outf, "\tdom_short s;\n"); + outputf(outc, + "\tdom_short s;\n"); } - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\n"); - fprintf(outf, + outputf(outc, "\texc = dom_%s_get_%s((struct dom_%s *)((node_private_t*)priv)->node, &s);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" @@ -164,16 +172,16 @@ output_generated_attribute_getter(FILE* outf, break; case WEBIDL_TYPE_BOOL: - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tbool b;\n" "\n"); - fprintf(outf, + outputf(outc, "\texc = dom_%s_get_%s((struct dom_%s *)((node_private_t*)priv)->node, &b);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" @@ -184,7 +192,7 @@ output_generated_attribute_getter(FILE* outf, break; case WEBIDL_TYPE_USER: - res = output_generated_attribute_user_getter(outf, + res = output_generated_attribute_user_getter(outc, interfacee, atributee); break; @@ -205,7 +213,7 @@ output_generated_attribute_getter(FILE* outf, } static int -output_generated_attribute_user_setter(FILE* outf, +output_generated_attribute_user_setter(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee) { @@ -222,7 +230,7 @@ output_generated_attribute_user_setter(FILE* outf, return -1; /* not onxxx */ } - fprintf(outf, + outputf(outc, "\t/* handlerfn */\n" "\tduk_push_this(ctx);\n" "\t/* handlerfn this */\n" @@ -251,7 +259,7 @@ output_generated_attribute_user_setter(FILE* outf, /* exported function documented in duk-libdom.h */ int -output_generated_attribute_setter(FILE* outf, +output_generated_attribute_setter(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee) { @@ -264,14 +272,14 @@ output_generated_attribute_setter(FILE* outf, switch (atributee->typev[0].base) { case WEBIDL_TYPE_STRING: - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tdom_string *str;\n" "\tduk_size_t slen;\n" "\tconst char *s;\n"); if ((atributee->treatnullas != NULL) && (strcmp(atributee->treatnullas, "EmptyString") == 0)) { - fprintf(outf, + outputf(outc, "\tif (duk_is_null(ctx, 0)) {\n" "\t\ts = \"\";\n" "\t\tslen = 0;\n" @@ -279,22 +287,22 @@ output_generated_attribute_setter(FILE* outf, "\t\ts = duk_safe_to_lstring(ctx, 0, &slen);\n" "\t}\n"); } else { - fprintf(outf, + outputf(outc, "\ts = duk_safe_to_lstring(ctx, 0, &slen);\n"); } - fprintf(outf, + outputf(outc, "\n" "\texc = dom_string_create((const uint8_t *)s, slen, &str);\n" "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" "\n"); - fprintf(outf, + outputf(outc, "\texc = dom_%s_set_%s((struct dom_%s *)((node_private_t*)priv)->node, str);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tdom_string_unref(str);\n" "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" @@ -305,26 +313,26 @@ output_generated_attribute_setter(FILE* outf, case WEBIDL_TYPE_LONG: if (atributee->typev[0].modifier == WEBIDL_TYPE_MODIFIER_UNSIGNED) { - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tdom_ulong l;\n" "\n" "\tl = duk_get_uint(ctx, 0);\n" "\n"); } else { - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tdom_long l;\n" "\n" "\tl = duk_get_int(ctx, 0);\n" "\n"); } - fprintf(outf, + outputf(outc, "\texc = dom_%s_set_%s((struct dom_%s *)((node_private_t*)priv)->node, l);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" @@ -334,26 +342,26 @@ output_generated_attribute_setter(FILE* outf, case WEBIDL_TYPE_SHORT: if (atributee->typev[0].modifier == WEBIDL_TYPE_MODIFIER_UNSIGNED) { - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tdom_ushort s;\n" "\n" "\ts = duk_get_uint(ctx, 0);\n" "\n"); } else { - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tdom_short s;\n" "\n" "\ts = duk_get_int(ctx, 0);\n" "\n"); } - fprintf(outf, + outputf(outc, "\texc = dom_%s_set_%s((struct dom_%s *)((node_private_t*)priv)->node, s);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" @@ -362,18 +370,18 @@ output_generated_attribute_setter(FILE* outf, break; case WEBIDL_TYPE_BOOL: - fprintf(outf, + outputf(outc, "\tdom_exception exc;\n" "\tbool b;\n" "\n" "\tb = duk_get_boolean(ctx, 0);\n" "\n"); - fprintf(outf, + outputf(outc, "\texc = dom_%s_set_%s((struct dom_%s *)((node_private_t*)priv)->node, b);\n", interfacee->class_name, atributee->property_name, interfacee->class_name); - fprintf(outf, + outputf(outc, "\tif (exc != DOM_NO_ERR) {\n" "\t\treturn 0;\n" "\t}\n" @@ -382,7 +390,7 @@ output_generated_attribute_setter(FILE* outf, break; case WEBIDL_TYPE_USER: - res = output_generated_attribute_user_setter(outf, + res = output_generated_attribute_user_setter(outc, interfacee, atributee); break; diff --git a/src/duk-libdom-interface.c b/src/duk-libdom-interface.c index 0e6697a..f6be419 100644 --- a/src/duk-libdom-interface.c +++ b/src/duk-libdom-interface.c @@ -20,6 +20,7 @@ #include "nsgenbind-ast.h" #include "webidl-ast.h" #include "ir.h" +#include "output.h" #include "duk-libdom.h" /** prefix for all generated functions */ @@ -27,85 +28,133 @@ #define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_" + /** - * Output code to create a private structure + * 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; +} + + +/** + * Compare two nodes to check their c types match. + */ +static bool compare_ctypes(struct genbind_node *a, struct genbind_node *b) +{ + struct genbind_node *ta; + struct genbind_node *tb; + + ta = genbind_node_find_type(genbind_node_getnode(a), + NULL, GENBIND_NODE_TYPE_NAME); + tb = genbind_node_find_type(genbind_node_getnode(b), + NULL, GENBIND_NODE_TYPE_NAME); + + while ((ta != NULL) && (tb != NULL)) { + char *txt_a; + char *txt_b; + + txt_a = genbind_node_gettext(ta); + txt_b = genbind_node_gettext(tb); + + if (strcmp(txt_a, txt_b) != 0) { + return false; /* missmatch */ + } + + ta = genbind_node_find_type(genbind_node_getnode(a), + ta, GENBIND_NODE_TYPE_NAME); + tb = genbind_node_find_type(genbind_node_getnode(b), + tb, GENBIND_NODE_TYPE_NAME); + } + if (ta != tb) { + return false; + } + + return true; +} + + +/** + * Generate code to create a private structure * + * \param outc Output context + * \param name of class private structure created for. */ -static int output_create_private(FILE* outf, char *class_name) +static int +output_create_private(struct opctx *outc, 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", + outputf(outc, + "\t/* create private data and attach to instance */\n"); + outputf(outc, + "\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, + outputf(outc, + "\tif (priv == NULL) return 0;\n"); + outputf(outc, + "\tduk_push_pointer(ctx, priv);\n"); + outputf(outc, "\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) +static int +output_safe_get_private(struct opctx *outc, char *class_name, int idx) { - fprintf(outf, + outputf(outc, "\t%s_private_t *priv;\n", class_name); - fprintf(outf, + outputf(outc, "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n", idx, DLPFX); - fprintf(outf, + outputf(outc, "\tpriv = duk_get_pointer(ctx, -1);\n"); - fprintf(outf, + outputf(outc, "\tduk_pop(ctx);\n"); - fprintf(outf, + outputf(outc, "\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) +static int output_get_prototype(struct opctx *outc, const char *interface_name) { char *proto_name; proto_name = get_prototype_name(interface_name); - fprintf(outf, + outputf(outc, "\t/* get prototype */\n"); - fprintf(outf, + outputf(outc, "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n", DLPFX); - fprintf(outf, + outputf(outc, "\tduk_get_prop_string(ctx, -1, \"%s\");\n", proto_name); - fprintf(outf, + outputf(outc, "\tduk_replace(ctx, -2);\n"); free(proto_name); @@ -116,14 +165,19 @@ static int output_get_prototype(FILE* outf, const char *interface_name) /** * generate code that sets a destructor in a prototype */ -static int output_set_destructor(FILE* outf, char *class_name, int idx) +static int output_set_destructor(struct opctx *outc, 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", + outputf(outc, + "\t/* Set the destructor */\n"); + outputf(outc, + "\tduk_dup(ctx, %d);\n", idx); + outputf(outc, + "\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"); + outputf(outc, + "\tduk_set_finalizer(ctx, -2);\n"); + outputf(outc, + "\tduk_pop(ctx);\n\n"); return 0; } @@ -132,51 +186,76 @@ static int output_set_destructor(FILE* outf, char *class_name, int idx) * generate code that sets a constructor in a prototype */ static int -output_set_constructor(FILE* outf, char *class_name, int idx, int argc) +output_set_constructor(struct opctx *outc, 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", + outputf(outc, + "\t/* Set the constructor */\n"); + outputf(outc, + "\tduk_dup(ctx, %d);\n", idx); + outputf(outc, + "\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", + outputf(outc, + "\tduk_put_prop_string(ctx, -2, \"%sINIT\");\n", MAGICPFX); - fprintf(outf, "\tduk_pop(ctx);\n\n"); + outputf(outc, + "\tduk_pop(ctx);\n\n"); return 0; } + +/** + * generate code to dump javascript stack + */ static int -output_dump_stack(FILE* outf) +output_dump_stack(struct opctx *outc) { if (options->dbglog) { /* dump stack */ - fprintf(outf, "\tduk_push_context_dump(ctx);\n"); - fprintf(outf, "\tNSLOG(dukky, INFO, \"Stack: %%s\", duk_to_string(ctx, -1));\n"); - fprintf(outf, "\tduk_pop(ctx);\n"); + outputf(outc, + "\tduk_push_context_dump(ctx);\n"); + outputf(outc, + "\tNSLOG(dukky, DEEPDEBUG, \"Stack: %%s\", duk_to_string(ctx, -1));\n"); + outputf(outc, + "\tduk_pop(ctx);\n"); } return 0; } + /** * generate code that adds a method in a prototype */ static int -output_add_method(FILE* outf, +output_add_method(struct opctx *outc, 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", + outputf(outc, + "\t/* Add a method */\n"); + outputf(outc, + "\tduk_dup(ctx, 0);\n"); + outputf(outc, + "\tduk_push_string(ctx, \"%s\");\n", method); + outputf(outc, + "\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"); + output_dump_stack(outc); + outputf(outc, + "\tduk_def_prop(ctx, -3,\n"); + outputf(outc, + "\t\t DUK_DEFPROP_HAVE_VALUE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_HAVE_WRITABLE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_HAVE_ENUMERABLE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_ENUMERABLE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_HAVE_CONFIGURABLE);\n"); + outputf(outc, + "\tduk_pop(ctx);\n\n"); return 0; } @@ -185,84 +264,133 @@ output_add_method(FILE* outf, * 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) +output_populate_rw_property(struct opctx *outc, + 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", + outputf(outc, + "\t/* Add read/write property */\n"); + outputf(outc, + "\tduk_dup(ctx, 0);\n"); + outputf(outc, + "\tduk_push_string(ctx, \"%s\");\n", property); + outputf(outc, + "\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", + outputf(outc, + "\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"); + output_dump_stack(outc); + outputf(outc, + "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\n"); + outputf(outc, + "\t\tDUK_DEFPROP_HAVE_SETTER |\n"); + outputf(outc, + "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE |\n"); + outputf(outc, + "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n"); + outputf(outc, + "\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) +output_populate_ro_property(struct opctx *outc, + 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", + outputf(outc, + "\t/* Add readonly property */\n"); + outputf(outc, + "\tduk_dup(ctx, 0);\n"); + outputf(outc, + "\tduk_push_string(ctx, \"%s\");\n", property); + outputf(outc, + "\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"); + output_dump_stack(outc); + outputf(outc, + "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER |\n"); + outputf(outc, + "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE |\n"); + outputf(outc, + "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n"); + outputf(outc, + "\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) +output_prototype_constant_int(struct opctx *outc, + 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"); + outputf(outc, + "\tduk_dup(ctx, 0);\n"); + outputf(outc, + "\tduk_push_string(ctx, \"%s\");\n", constant_name); + outputf(outc, + "\tduk_push_int(ctx, %d);\n", value); + outputf(outc, + "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_HAVE_WRITABLE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_HAVE_ENUMERABLE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_ENUMERABLE |\n"); + outputf(outc, + "\t\t DUK_DEFPROP_HAVE_CONFIGURABLE);\n"); + outputf(outc, + "\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, bool is_global) +output_get_method_private(struct opctx *outc, char *class_name, bool is_global) { - fprintf(outf, "\t/* Get private data for method */\n"); - fprintf(outf, "\t%s_private_t *priv = NULL;\n", class_name); + outputf(outc, + "\t/* Get private data for method */\n"); + outputf(outc, + "\t%s_private_t *priv = NULL;\n", class_name); if (is_global) { - fprintf(outf, "\tduk_push_global_object(ctx);\n"); + outputf(outc, + "\tduk_push_global_object(ctx);\n"); } else { - fprintf(outf, "\tduk_push_this(ctx);\n"); + outputf(outc, + "\tduk_push_this(ctx);\n"); } - fprintf(outf, "\tduk_get_prop_string(ctx, -1, %s_magic_string_private);\n", + outputf(outc, + "\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"); + outputf(outc, + "\tpriv = duk_get_pointer(ctx, -1);\n"); + outputf(outc, + "\tduk_pop_2(ctx);\n"); + outputf(outc, + "\tif (priv == NULL) {\n"); if (options->dbglog) { - fprintf(outf, "\t\tNSLOG(dukky, INFO, \"priv failed\");\n"); + outputf(outc, + "\t\tNSLOG(dukky, INFO, \"priv failed\");\n"); } - fprintf(outf, "\t\treturn 0; /* can do? No can do. */\n"); - fprintf(outf, "\t}\n\n"); + outputf(outc, + "\t\treturn 0; /* can do? No can do. */\n"); + outputf(outc, + "\t}\n\n"); return 0; } @@ -272,106 +400,81 @@ output_get_method_private(FILE* outf, char *class_name, bool is_global) * generate the interface constructor */ static int -output_interface_constructor(FILE* outf, struct ir_entry *interfacee) +output_interface_constructor(struct opctx *outc, struct ir_entry *interfacee) { int init_argc; /* constructor definition */ - fprintf(outf, + outputf(outc, "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n", DLPFX, interfacee->class_name); - fprintf(outf,"{\n"); + outputf(outc, + "{\n"); - output_create_private(outf, interfacee->class_name); + output_create_private(outc, interfacee->class_name); /* generate call to initialisor */ - fprintf(outf, + outputf(outc, "\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); + outputf(outc, + ", 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"); + outputf(outc, + ");\n"); + + outputf(outc, + "\tduk_set_top(ctx, 1);\n"); + outputf(outc, + "\treturn 1;\n"); + outputf(outc, + "}\n\n"); return 0; } + /** * generate the interface destructor */ static int -output_interface_destructor(FILE* outf, struct ir_entry *interfacee) +output_interface_destructor(struct opctx *outc, struct ir_entry *interfacee) { /* destructor definition */ - fprintf(outf, + outputf(outc, "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n", DLPFX, interfacee->class_name); - fprintf(outf,"{\n"); + outputf(outc, + "{\n"); - output_safe_get_private(outf, interfacee->class_name, 0); + output_safe_get_private(outc, interfacee->class_name, 0); /* generate call to finaliser */ - fprintf(outf, + outputf(outc, "\t%s_%s___fini(ctx, priv);\n", DLPFX, interfacee->class_name); - fprintf(outf,"\tfree(priv);\n"); - fprintf(outf,"\treturn 0;\n"); + outputf(outc, + "\tfree(priv);\n"); + outputf(outc, + "\treturn 0;\n"); - fprintf(outf, "}\n\n"); + outputf(outc, + "}\n\n"); return 0; } -/** - * Compare two nodes to check their c types match. - */ -static bool compare_ctypes(struct genbind_node *a, struct genbind_node *b) -{ - struct genbind_node *ta; - struct genbind_node *tb; - - ta = genbind_node_find_type(genbind_node_getnode(a), - NULL, GENBIND_NODE_TYPE_NAME); - tb = genbind_node_find_type(genbind_node_getnode(b), - NULL, GENBIND_NODE_TYPE_NAME); - - while ((ta != NULL) && (tb != NULL)) { - char *txt_a; - char *txt_b; - - txt_a = genbind_node_gettext(ta); - txt_b = genbind_node_gettext(tb); - - if (strcmp(txt_a, txt_b) != 0) { - return false; /* missmatch */ - } - - ta = genbind_node_find_type(genbind_node_getnode(a), - ta, GENBIND_NODE_TYPE_NAME); - tb = genbind_node_find_type(genbind_node_getnode(b), - tb, GENBIND_NODE_TYPE_NAME); - } - if (ta != tb) { - return false; - } - - return true; -} /** * generate an initialisor call to parent interface */ static int -output_interface_inherit_init(FILE* outf, +output_interface_inherit_init(struct opctx *outc, struct ir_entry *interfacee, struct ir_entry *inherite) { @@ -396,8 +499,8 @@ output_interface_inherit_init(FILE* outf, GENBIND_METHOD_TYPE_INIT); - - fprintf(outf, "\t%s_%s___init(ctx, &priv->parent", + outputf(outc, + "\t%s_%s___init(ctx, &priv->parent", DLPFX, inherite->class_name); /* for each parameter in the parent find a matching named @@ -421,7 +524,8 @@ output_interface_inherit_init(FILE* outf, 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", + 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, @@ -429,18 +533,18 @@ output_interface_inherit_init(FILE* outf, param_name); return -1; } else { - fprintf(outf, ", "); + outputf(outc, ", "); /* cast the parameter if required */ if (compare_ctypes(param_node, inh_param_node) == false) { - fputc('(', outf); - output_ctype(outf, inh_param_node, false); - fputc(')', outf); + outputc(outc, '('); + output_ctype(outc, inh_param_node, false); + outputc(outc, ')'); } /* output the parameter identifier */ - output_cdata(outf, param_node, GENBIND_NODE_TYPE_IDENT); + output_cdata(outc, param_node, GENBIND_NODE_TYPE_IDENT); } inh_param_node = genbind_node_find_type( @@ -448,22 +552,24 @@ output_interface_inherit_init(FILE* outf, inh_param_node, GENBIND_NODE_TYPE_METHOD); } - fprintf(outf, ");\n"); + outputf(outc, ");\n"); return 0; } + static int -output_interface_init_declaration(FILE* outf, +output_interface_init_declaration(struct opctx *outc, struct ir_entry *interfacee, struct genbind_node *init_node) { struct genbind_node *param_node; if (interfacee->refcount == 0) { - fprintf(outf, "static "); + outputf(outc, "static "); } - fprintf(outf, + + outputf(outc, "void %s_%s___init(duk_context *ctx, %s_private_t *priv", DLPFX, interfacee->class_name, interfacee->class_name); @@ -476,22 +582,26 @@ output_interface_init_declaration(FILE* outf, NULL, GENBIND_NODE_TYPE_PARAMETER); while (param_node != NULL) { interfacee->class_init_argc++; - fprintf(outf, ", "); + outputf(outc, ", "); - output_ctype(outf, param_node, true); + output_ctype(outc, param_node, true); param_node = genbind_node_find_type( genbind_node_getnode(init_node), param_node, GENBIND_NODE_TYPE_PARAMETER); } - fprintf(outf,")"); + outputc(outc, ')'); return 0; } + +/** + * generate code for interface (class) initialisor + */ static int -output_interface_init(FILE* outf, +output_interface_init(struct opctx *outc, struct ir_entry *interfacee, struct ir_entry *inherite) { @@ -504,33 +614,37 @@ output_interface_init(FILE* outf, GENBIND_METHOD_TYPE_INIT); /* initialisor definition */ - output_interface_init_declaration(outf, interfacee, init_node); + output_interface_init_declaration(outc, interfacee, init_node); - fprintf(outf,"\n{\n"); + outputf(outc, "\n{\n"); /* if this interface inherits ensure we call its initialisor */ - res = output_interface_inherit_init(outf, interfacee, inherite); + res = output_interface_inherit_init(outc, interfacee, inherite); if (res != 0) { return res; } /* generate log statement */ if (options->dbglog) { - fprintf(outf, + outputf(outc, "\tNSLOG(dukky, INFO, \"Initialise %%p (priv=%%p)\", duk_get_heapptr(ctx, 0), priv);\n" ); } /* output the initaliser code from the binding */ - output_ccode(outf, init_node); + output_ccode(outc, init_node); - fprintf(outf, "}\n\n"); + outputf(outc, "}\n\n"); return 0; } + +/** + * generate code for interface (class) finaliser + */ static int -output_interface_fini(FILE* outf, +output_interface_fini(struct opctx *outc, struct ir_entry *interfacee, struct ir_entry *inherite) { @@ -541,32 +655,31 @@ output_interface_fini(FILE* outf, NULL, GENBIND_METHOD_TYPE_FINI); - /* finaliser definition */ if (interfacee->refcount == 0) { - fprintf(outf, "static "); + outputf(outc, "static "); } - fprintf(outf, + outputf(outc, "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n", DLPFX, interfacee->class_name, interfacee->class_name); - fprintf(outf,"{\n"); + outputf(outc, "{\n"); /* generate log statement */ if (options->dbglog) { - fprintf(outf, + outputf(outc, "\tNSLOG(dukky, INFO, \"Finalise %%p\", duk_get_heapptr(ctx, 0));\n" ); } /* output the finialisor code from the binding */ - output_cdata(outf, fini_node, GENBIND_NODE_TYPE_CDATA); + output_cdata(outc, fini_node, GENBIND_NODE_TYPE_CDATA); /* if this interface inherits ensure we call its finaliser */ if (inherite != NULL) { - fprintf(outf, + outputf(outc, "\t%s_%s___fini(ctx, &priv->parent);\n", DLPFX, inherite->class_name); } - fprintf(outf, "}\n\n"); + outputf(outc, "}\n\n"); return 0; } @@ -576,37 +689,38 @@ output_interface_fini(FILE* outf, * generate a prototype add for a single class method */ static int -output_prototype_method(FILE* outf, +output_prototype_method(struct opctx *outc, struct ir_entry *interfacee, struct ir_operation_entry *operatione) { if (operatione->name != NULL) { /* normal method on prototype */ - output_add_method(outf, + output_add_method(outc, interfacee->class_name, operatione->name); } else { /* special method on prototype */ - fprintf(outf, + outputf(outc, "\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) +output_prototype_methods(struct opctx *outc, struct ir_entry *entry) { int opc; int res = 0; for (opc = 0; opc < entry->u.interface.operationc; opc++) { res = output_prototype_method( - outf, + outc, entry, entry->u.interface.operationv + opc); if (res != 0) { @@ -619,33 +733,34 @@ output_prototype_methods(FILE *outf, struct ir_entry *entry) static int -output_prototype_attribute(FILE *outf, +output_prototype_attribute(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *attributee) { if ((attributee->putforwards == NULL) && (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY)) { - return output_populate_ro_property(outf, + return output_populate_ro_property(outc, interfacee->class_name, attributee->name); } - return output_populate_rw_property(outf, + return output_populate_rw_property(outc, interfacee->class_name, attributee->name); } + /** * generate prototype attribute definitions */ static int -output_prototype_attributes(FILE *outf, struct ir_entry *entry) +output_prototype_attributes(struct opctx *outc, struct ir_entry *entry) { int attrc; int res = 0; for (attrc = 0; attrc < entry->u.interface.attributec; attrc++) { res = output_prototype_attribute( - outf, + outc, entry, entry->u.interface.attributev + attrc); if (res != 0) { @@ -656,6 +771,7 @@ output_prototype_attributes(FILE *outf, struct ir_entry *entry) return res; } + /** * output constants on the prototype * @@ -663,7 +779,7 @@ output_prototype_attributes(FILE *outf, struct ir_entry *entry) * check the type node base value. */ static int -output_prototype_constant(FILE *outf, +output_prototype_constant(struct opctx *outc, struct ir_constant_entry *constante) { int *value; @@ -674,23 +790,24 @@ output_prototype_constant(FILE *outf, NULL, WEBIDL_NODE_TYPE_LITERAL_INT)); - output_prototype_constant_int(outf, constante->name, *value); + output_prototype_constant_int(outc, constante->name, *value); return 0; } + /** * generate prototype constant definitions */ static int -output_prototype_constants(FILE *outf, struct ir_entry *entry) +output_prototype_constants(struct opctx *outc, struct ir_entry *entry) { int attrc; int res = 0; for (attrc = 0; attrc < entry->u.interface.constantc; attrc++) { res = output_prototype_constant( - outf, + outc, entry->u.interface.constantv + attrc); if (res != 0) { break; @@ -700,14 +817,16 @@ output_prototype_constants(FILE *outf, struct ir_entry *entry) return res; } + static int -output_global_create_prototype(FILE* outf, +output_global_create_prototype(struct opctx *outc, struct ir *ir, struct ir_entry *interfacee) { int idx; - fprintf(outf, "\t/* Create interface objects */\n"); + outputf(outc, + "\t/* Create interface objects */\n"); for (idx = 0; idx < ir->entryc; idx++) { struct ir_entry *entry; @@ -720,12 +839,13 @@ output_global_create_prototype(FILE* outf, } if (entry == interfacee) { - fprintf(outf, "\tduk_dup(ctx, 0);\n"); + outputf(outc, + "\tduk_dup(ctx, 0);\n"); } else { - output_get_prototype(outf, entry->name); + output_get_prototype(outc, entry->name); } - fprintf(outf, + outputf(outc, "\tdukky_inject_not_ctr(ctx, 0, \"%s\");\n", entry->name); } @@ -738,7 +858,7 @@ output_global_create_prototype(FILE* outf, * generate the interface prototype creator */ static int -output_interface_prototype(FILE* outf, +output_interface_prototype(struct opctx *outc, struct ir *ir, struct ir_entry *interfacee, struct ir_entry *inherite) @@ -747,74 +867,81 @@ output_interface_prototype(FILE* outf, /* find the prototype method on the class */ proto_node = genbind_node_find_method(interfacee->class, - NULL, - GENBIND_METHOD_TYPE_PROTOTYPE); + NULL, + GENBIND_METHOD_TYPE_PROTOTYPE); /* prototype definition */ - fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx, void *udata)\n", + outputf(outc, + "duk_ret_t %s_%s___proto(duk_context *ctx, void *udata)\n", DLPFX, interfacee->class_name); - fprintf(outf,"{\n"); + outputf(outc, "{\n"); /* Output any binding data first */ - if (output_cdata(outf, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) { - fprintf(outf,"\n"); + if (output_cdata(outc, proto_node, GENBIND_NODE_TYPE_CDATA) != 0) { + outputf(outc, + "\n"); } /* generate prototype chaining if interface has a parent */ if (inherite != NULL) { - fprintf(outf, + outputf(outc, "\t/* Set this prototype's prototype (left-parent) */\n"); - output_get_prototype(outf, inherite->name); - fprintf(outf, "\tduk_set_prototype(ctx, 0);\n\n"); + output_get_prototype(outc, inherite->name); + outputf(outc, + "\tduk_set_prototype(ctx, 0);\n\n"); } /* generate setting of methods */ - output_prototype_methods(outf, interfacee); + output_prototype_methods(outc, interfacee); /* generate setting of attributes */ - output_prototype_attributes(outf, interfacee); + output_prototype_attributes(outc, interfacee); /* generate setting of constants */ - output_prototype_constants(outf, interfacee); + output_prototype_constants(outc, 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); + output_global_create_prototype(outc, ir, interfacee); } /* generate setting of destructor */ - output_set_destructor(outf, interfacee->class_name, 0); + output_set_destructor(outc, interfacee->class_name, 0); /* generate setting of constructor */ - output_set_constructor(outf, + output_set_constructor(outc, interfacee->class_name, 0, interfacee->class_init_argc); - fprintf(outf,"\treturn 1; /* The prototype object */\n"); + outputf(outc, + "\treturn 1; /* The prototype object */\n"); - fprintf(outf, "}\n\n"); + outputf(outc, + "}\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) +output_interface_elipsis_operation(struct opctx *outc, + struct ir_entry *interfacee, + struct ir_operation_entry *operatione) { int cdatac; /* cdata blocks output */ /* overloaded method definition */ - fprintf(outf, + outputf(outc, "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", DLPFX, interfacee->class_name, operatione->name); - fprintf(outf,"{\n"); + outputf(outc, + "{\n"); /** * \todo This is where the checking of the parameters to the @@ -824,47 +951,51 @@ output_interface_elipsis_operation(FILE* outf, "Elipsis parameters not checked: method %s::%s();", interfacee->name, operatione->name); - output_get_method_private(outf, interfacee->class_name, + output_get_method_private(outc, interfacee->class_name, interfacee->u.interface.primary_global); - cdatac = output_ccode(outf, operatione->method); + cdatac = output_ccode(outc, operatione->method); if (cdatac == 0) { /* no implementation so generate default */ WARN(WARNING_UNIMPLEMENTED, "Unimplemented: method %s::%s();", interfacee->name, operatione->name); - fprintf(outf,"\treturn 0;\n"); + outputf(outc, + "\treturn 0;\n"); } - fprintf(outf, "}\n\n"); + outputf(outc, + "}\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) +output_interface_overloaded_operation(struct opctx *outc, + struct ir_entry *interfacee, + struct ir_operation_entry *operatione) { int cdatac; /* cdata blocks output */ /* overloaded method definition */ - fprintf(outf, + outputf(outc, "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", DLPFX, interfacee->class_name, operatione->name); - fprintf(outf,"{\n"); + outputf(outc, + "{\n"); /** \todo This is where the checking of the parameters to the * overloaded operation should go */ - output_get_method_private(outf, interfacee->class_name, + output_get_method_private(outc, interfacee->class_name, interfacee->u.interface.primary_global); - cdatac = output_cdata(outf, + cdatac = output_cdata(outc, operatione->method, GENBIND_NODE_TYPE_CDATA); @@ -873,24 +1004,28 @@ output_interface_overloaded_operation(FILE* outf, WARN(WARNING_UNIMPLEMENTED, "Unimplemented: method %s::%s();", interfacee->name, operatione->name); - fprintf(outf,"\treturn 0;\n"); + outputf(outc, + "\treturn 0;\n"); } - fprintf(outf, "}\n\n"); + outputf(outc, + "}\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) +output_interface_special_operation(struct opctx *outc, + struct ir_entry *interfacee, + struct ir_operation_entry *operatione) { /* special method definition */ - fprintf(outf, "/* Special method definition - UNIMPLEMENTED */\n\n"); + outputf(outc, + "/* Special method definition - UNIMPLEMENTED */\n\n"); WARN(WARNING_UNIMPLEMENTED, "Special operation on interface %s (operation entry %p)", @@ -900,11 +1035,13 @@ output_interface_special_operation(FILE* outf, return 0; } + /** * generate default values on the duk stack */ static int -output_operation_optional_defaults(FILE* outf, +output_operation_optional_defaults( + struct opctx *outc, struct ir_operation_argument_entry *argumentv, int argumentc) { @@ -930,47 +1067,49 @@ output_operation_optional_defaults(FILE* outf, switch (lit_type) { case WEBIDL_NODE_TYPE_LITERAL_NULL: - fprintf(outf, + outputf(outc, "\t\tduk_push_null(ctx);\n"); break; case WEBIDL_NODE_TYPE_LITERAL_INT: lit_int = webidl_node_getint(lit_node); - fprintf(outf, + outputf(outc, "\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, + outputf(outc, "\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, + outputf(outc, "\t\tduk_push_string(ctx, \"%s\");\n", lit_str); break; case WEBIDL_NODE_TYPE_LITERAL_FLOAT: default: - fprintf(outf, + outputf(outc, "\t\tduk_push_undefined(ctx);\n"); break; } } else { - fprintf(outf, "\t\tduk_push_undefined(ctx);\n"); + outputf(outc, + "\t\tduk_push_undefined(ctx);\n"); } } return 0; } + static int output_operation_argument_type_check( - FILE* outf, + struct opctx *outc, struct ir_entry *interfacee, struct ir_operation_entry *operatione, struct ir_operation_overload_entry *overloade, @@ -1017,19 +1156,20 @@ output_operation_argument_type_check( return 0; } - fprintf(outf, "\tif (%s_argc > %d) {\n", DLPFX, argidx); + outputf(outc, + "\tif (%s_argc > %d) {\n", DLPFX, argidx); switch (*argument_type) { case WEBIDL_TYPE_STRING: /* coerce values to string */ - fprintf(outf, + outputf(outc, "\t\tif (!duk_is_string(ctx, %d)) {\n" "\t\t\tduk_to_string(ctx, %d);\n" "\t\t}\n", argidx, argidx); break; case WEBIDL_TYPE_BOOL: - fprintf(outf, + outputf(outc, "\t\tif (!duk_is_boolean(ctx, %d)) {\n" "\t\t\treturn duk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_bool_type, %d, \"%s\");\n" "\t\t}\n", argidx, DLPFX, argidx, argumente->name); @@ -1040,19 +1180,21 @@ output_operation_argument_type_check( case WEBIDL_TYPE_SHORT: case WEBIDL_TYPE_LONG: case WEBIDL_TYPE_LONGLONG: - fprintf(outf, + outputf(outc, "\t\tif (!duk_is_number(ctx, %d)) {\n" "\t\t\treturn duk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_number_type, %d, \"%s\");\n" - "\t\t}\n", argidx, DLPFX, argidx, argumente->name); + "\t\t}\n", + argidx, DLPFX, argidx, argumente->name); break; default: - fprintf(outf, + outputf(outc, "\t\t/* unhandled type check */\n"); } - fprintf(outf, "\t}\n"); + outputf(outc, + "\t}\n"); return 0; } @@ -1062,7 +1204,7 @@ output_operation_argument_type_check( * generate a single class method for an interface operation */ static int -output_interface_operation(FILE* outf, +output_interface_operation(struct opctx *outc, struct ir_entry *interfacee, struct ir_operation_entry *operatione) { @@ -1073,19 +1215,19 @@ output_interface_operation(FILE* outf, int optargc; /* loop counter for optional arguments */ if (operatione->name == NULL) { - return output_interface_special_operation(outf, + return output_interface_special_operation(outc, interfacee, operatione); } if (operatione->overloadc != 1) { - return output_interface_overloaded_operation(outf, + return output_interface_overloaded_operation(outc, interfacee, operatione); } if (operatione->overloadv->elipsisc != 0) { - return output_interface_elipsis_operation(outf, + return output_interface_elipsis_operation(outc, interfacee, operatione); } @@ -1093,10 +1235,11 @@ output_interface_operation(FILE* outf, /* normal method definition */ overloade = operatione->overloadv; - fprintf(outf, + outputf(outc, "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", DLPFX, interfacee->class_name, operatione->name); - fprintf(outf,"{\n"); + outputf(outc, + "{\n"); /* check arguments */ @@ -1104,40 +1247,40 @@ output_interface_operation(FILE* outf, fixedargc = overloade->argumentc - overloade->optionalc; - fprintf(outf, + outputf(outc, "\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\treturn duk_error(ctx, DUK_RET_TYPE_ERROR, %s_error_fmt_argument, %d, %s_argc);\n" - "\t} else ", - DLPFX, - fixedargc, - DLPFX, - fixedargc, - DLPFX); + outputf(outc, + "if (%s_argc < %d) {\n", + DLPFX, fixedargc); + outputf(outc, + "\t\t/* not enough arguments */\n"); + outputf(outc, + "\t\treturn duk_error(ctx, DUK_RET_TYPE_ERROR, %s_error_fmt_argument, %d, %s_argc);\n", + DLPFX, fixedargc, DLPFX); + outputf(outc, + "\t} else "); } for (optargc = fixedargc; optargc < overloade->argumentc; optargc++) { - fprintf(outf, + outputf(outc, "if (%s_argc == %d) {\n" "\t\t/* %d optional arguments need adding */\n", DLPFX, optargc, overloade->argumentc - optargc); - output_operation_optional_defaults(outf, + output_operation_optional_defaults(outc, overloade->argumentv + optargc, overloade->argumentc - optargc); - fprintf(outf, + outputf(outc, "\t} else "); } - fprintf(outf, + outputf(outc, "if (%s_argc > %d) {\n" "\t\t/* remove extraneous parameters */\n" "\t\tduk_set_top(ctx, %d);\n" @@ -1145,24 +1288,26 @@ output_interface_operation(FILE* outf, DLPFX, overloade->argumentc, overloade->argumentc); - fprintf(outf, "\n"); + outputf(outc, + "\n"); /* generate argument type checks */ - fprintf(outf, "\t/* check types of passed arguments are correct */\n"); + outputf(outc, + "\t/* check types of passed arguments are correct */\n"); for (argidx = 0; argidx < overloade->argumentc; argidx++) { - output_operation_argument_type_check(outf, + output_operation_argument_type_check(outc, interfacee, operatione, overloade, argidx); } - output_get_method_private(outf, interfacee->class_name, + output_get_method_private(outc, interfacee->class_name, interfacee->u.interface.primary_global); - cdatac = output_ccode(outf, operatione->method); + cdatac = output_ccode(outc, operatione->method); if (cdatac == 0) { /* no implementation so generate default */ WARN(WARNING_UNIMPLEMENTED, @@ -1170,13 +1315,16 @@ output_interface_operation(FILE* outf, interfacee->name, operatione->name); if (options->dbglog) { - fprintf(outf, "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n" ); + outputf(outc, + "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n"); } - fprintf(outf,"\treturn 0;\n"); + outputf(outc, + "\treturn 0;\n"); } - fprintf(outf, "}\n\n"); + outputf(outc, + "}\n\n"); return 0; } @@ -1185,14 +1333,14 @@ output_interface_operation(FILE* outf, * generate class methods for each interface operation */ static int -output_interface_operations(FILE* outf, struct ir_entry *ife) +output_interface_operations(struct opctx *outc, struct ir_entry *ife) { int opc; int res = 0; for (opc = 0; opc < ife->u.interface.operationc; opc++) { res = output_interface_operation( - outf, + outc, ife, ife->u.interface.operationv + opc); if (res != 0) { @@ -1209,31 +1357,34 @@ output_interface_operations(FILE* outf, struct ir_entry *ife) * Output class property getter for a single attribute */ static int -output_attribute_getter(FILE* outf, +output_attribute_getter(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee) { /* getter definition */ - fprintf(outf, + outputf(outc, "static duk_ret_t %s_%s_%s_getter(duk_context *ctx)\n", DLPFX, interfacee->class_name, atributee->name); - fprintf(outf,"{\n"); + outputf(outc, + "{\n"); - output_get_method_private(outf, interfacee->class_name, + output_get_method_private(outc, + interfacee->class_name, interfacee->u.interface.primary_global); /* if binding available for this attribute getter process it */ if (atributee->getter != NULL) { int res; - res = output_ccode(outf, atributee->getter); + res = output_ccode(outc, atributee->getter); if (res == 0) { /* no code provided for this getter so generate */ - res = output_generated_attribute_getter(outf, + res = output_generated_attribute_getter(outc, interfacee, atributee); } if (res >= 0) { - fprintf(outf, "}\n\n"); + outputf(outc, + "}\n\n"); return res; } } @@ -1256,10 +1407,11 @@ output_attribute_getter(FILE* outf, type_str); if (options->dbglog) { - fprintf(outf, "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n" ); + outputf(outc, + "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n" ); } - fprintf(outf, + outputf(outc, "\treturn 0;\n" "}\n\n"); @@ -1271,19 +1423,20 @@ output_attribute_getter(FILE* outf, * Generate class property setter for a putforwards attribute */ static int -output_putforwards_setter(FILE* outf, - struct ir_entry *interfacee, - struct ir_attribute_entry *atributee) +output_putforwards_setter(struct opctx *outc, + struct ir_entry *interfacee, + struct ir_attribute_entry *atributee) { /* generate autogenerated putforwards */ - fprintf(outf,"\tduk_ret_t get_ret;\n\n"); + outputf(outc, + "\tduk_ret_t get_ret;\n\n"); - fprintf(outf, + outputf(outc, "\tget_ret = %s_%s_%s_getter(ctx);\n", DLPFX, interfacee->class_name, atributee->name); - fprintf(outf, + outputf(outc, "\tif (get_ret != 1) {\n" "\t\treturn 0;\n" "\t}\n\n" @@ -1292,46 +1445,49 @@ output_putforwards_setter(FILE* outf, "\t/* ... attribute parameter */\n\n" "\t/* call the putforward */\n"); - fprintf(outf, + outputf(outc, "\tduk_put_prop_string(ctx, -2, \"%s\");\n\n", atributee->putforwards); - fprintf(outf, + outputf(outc, "\treturn 0;\n"); return 0; } + /** * Generate class property setter for a single attribute */ static int -output_attribute_setter(FILE* outf, +output_attribute_setter(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee) { int res = -1; /* setter definition */ - fprintf(outf, + outputf(outc, "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n", DLPFX, interfacee->class_name, atributee->name); - fprintf(outf,"{\n"); + outputf(outc, + "{\n"); - output_get_method_private(outf, interfacee->class_name, + output_get_method_private(outc, + interfacee->class_name, interfacee->u.interface.primary_global); /* if binding available for this attribute getter process it */ if (atributee->setter != NULL) { - res = output_ccode(outf, atributee->setter); + res = output_ccode(outc, atributee->setter); if (res == 0) { /* no code provided for this setter so generate */ - res = output_generated_attribute_setter(outf, + res = output_generated_attribute_setter(outc, interfacee, atributee); } } else if (atributee->putforwards != NULL) { - res = output_putforwards_setter(outf, + res = output_putforwards_setter(outc, interfacee, atributee); } @@ -1354,14 +1510,17 @@ output_attribute_setter(FILE* outf, atributee->name, type_str); if (options->dbglog) { - fprintf(outf, "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n" ); + outputf(outc, + "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n"); } /* no implementation so generate default */ - fprintf(outf, "\treturn 0;\n"); + outputf(outc, + "\treturn 0;\n"); } - fprintf(outf, "}\n\n"); + outputf(outc, + "}\n\n"); return res; } @@ -1371,7 +1530,7 @@ output_attribute_setter(FILE* outf, * Generate class property getter/setter for a single attribute */ static int -output_interface_attribute(FILE* outf, +output_interface_attribute(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee) { @@ -1381,28 +1540,29 @@ output_interface_attribute(FILE* outf, atributee->property_name = gen_idl2c_name(atributee->name); } - res = output_attribute_getter(outf, interfacee, atributee); + res = output_attribute_getter(outc, interfacee, atributee); /* only read/write and putforward attributes have a setter */ if ((atributee->modifier != WEBIDL_TYPE_MODIFIER_READONLY) || (atributee->putforwards != NULL)) { - res = output_attribute_setter(outf, interfacee, atributee); + res = output_attribute_setter(outc, interfacee, atributee); } return res; } + /** * generate class property getters and setters for each interface attribute */ static int -output_interface_attributes(FILE* outf, struct ir_entry *ife) +output_interface_attributes(struct opctx *outc, struct ir_entry *ife) { int attrc; for (attrc = 0; attrc < ife->u.interface.attributec; attrc++) { output_interface_attribute( - outf, + outc, ife, ife->u.interface.attributev + attrc); } @@ -1411,104 +1571,111 @@ output_interface_attributes(FILE* outf, struct ir_entry *ife) } -/* exported interface documented in duk-libdom.h */ +/* + * generate a source file to implement an interface using duk and libdom. + * + * exported interface documented in duk-libdom.h + */ int output_interface(struct ir *ir, struct ir_entry *interfacee) { - FILE *ifacef; + struct opctx *ifop; struct ir_entry *inherite; int res = 0; - /* open output file */ - ifacef = genb_fopen_tmp(interfacee->filename); - if (ifacef == NULL) { - return -1; + /* open the output */ + res = output_open(interfacee->filename, &ifop); + if (res !=0 ) { + return res; } /* find parent interface entry */ inherite = ir_inherit_entry(ir, interfacee); /* tool preface */ - output_tool_preface(ifacef); + output_tool_preface(ifop); /* binding preface */ - output_method_cdata(ifacef, + output_method_cdata(ifop, ir->binding_node, GENBIND_METHOD_TYPE_PREFACE); /* class preface */ - output_method_cdata(ifacef, + output_method_cdata(ifop, interfacee->class, GENBIND_METHOD_TYPE_PREFACE); /* tool prologue */ - output_tool_prologue(ifacef); + output_tool_prologue(ifop); /* binding prologue */ - output_method_cdata(ifacef, + output_method_cdata(ifop, ir->binding_node, GENBIND_METHOD_TYPE_PROLOGUE); /* class prologue */ - output_method_cdata(ifacef, + output_method_cdata(ifop, interfacee->class, GENBIND_METHOD_TYPE_PROLOGUE); - fprintf(ifacef, "\n"); + outputf(ifop, + "\n"); /* initialisor */ - res = output_interface_init(ifacef, interfacee, inherite); + res = output_interface_init(ifop, interfacee, inherite); if (res != 0) { goto op_error; } /* finaliser */ - output_interface_fini(ifacef, interfacee, inherite); + output_interface_fini(ifop, interfacee, inherite); /* constructor */ - output_interface_constructor(ifacef, interfacee); + output_interface_constructor(ifop, interfacee); /* destructor */ - output_interface_destructor(ifacef, interfacee); + output_interface_destructor(ifop, interfacee); /* operations */ - output_interface_operations(ifacef, interfacee); + output_interface_operations(ifop, interfacee); /* attributes */ - output_interface_attributes(ifacef, interfacee); + output_interface_attributes(ifop, interfacee); /* prototype */ - output_interface_prototype(ifacef, ir, interfacee, inherite); + output_interface_prototype(ifop, ir, interfacee, inherite); - fprintf(ifacef, "\n"); + outputf(ifop, "\n"); /* class epilogue */ - output_method_cdata(ifacef, + output_method_cdata(ifop, interfacee->class, GENBIND_METHOD_TYPE_EPILOGUE); /* binding epilogue */ - output_method_cdata(ifacef, + output_method_cdata(ifop, ir->binding_node, GENBIND_METHOD_TYPE_EPILOGUE); /* class postface */ - output_method_cdata(ifacef, + output_method_cdata(ifop, interfacee->class, GENBIND_METHOD_TYPE_POSTFACE); /* binding postface */ - output_method_cdata(ifacef, + output_method_cdata(ifop, ir->binding_node, GENBIND_METHOD_TYPE_POSTFACE); op_error: - genb_fclose_tmp(ifacef, interfacee->filename); + output_close(ifop); return res; } + /* exported function documented in duk-libdom.h */ -int output_interface_declaration(FILE* outf, struct ir_entry *interfacee) +int +output_interface_declaration(struct opctx *outc, struct ir_entry *interfacee) { struct genbind_node *init_node; @@ -1520,7 +1687,8 @@ int output_interface_declaration(FILE* outf, struct ir_entry *interfacee) } /* prototype declaration */ - fprintf(outf, "duk_ret_t %s_%s___proto(duk_context *ctx, void *udata);\n", + outputf(outc, + "duk_ret_t %s_%s___proto(duk_context *ctx, void *udata);\n", DLPFX, interfacee->class_name); /* if the interface has no references (no other interface inherits from @@ -1528,13 +1696,13 @@ int output_interface_declaration(FILE* outf, struct ir_entry *interfacee) * other class constructor/destructor should call them. */ if (interfacee->refcount < 1) { - fprintf(outf, "\n"); - + outputf(outc, + "\n"); return 0; } /* finaliser declaration */ - fprintf(outf, + outputf(outc, "void %s_%s___fini(duk_context *ctx, %s_private_t *priv);\n", DLPFX, interfacee->class_name, interfacee->class_name); @@ -1544,9 +1712,10 @@ int output_interface_declaration(FILE* outf, struct ir_entry *interfacee) GENBIND_METHOD_TYPE_INIT); /* initialisor definition */ - output_interface_init_declaration(outf, interfacee, init_node); + output_interface_init_declaration(outc, interfacee, init_node); - fprintf(outf, ";\n\n"); + outputf(outc, + ";\n\n"); return 0; } diff --git a/src/duk-libdom.c b/src/duk-libdom.c index a04ee7d..6cb2815 100644 --- a/src/duk-libdom.c +++ b/src/duk-libdom.c @@ -20,6 +20,7 @@ #include "nsgenbind-ast.h" #include "webidl-ast.h" #include "ir.h" +#include "output.h" #include "duk-libdom.h" /** prefix for all generated functions */ @@ -52,58 +53,53 @@ static char *get_prototype_name(const char *interface_name) -static FILE *open_header(struct ir *ir, const char *name) +static struct opctx *open_header(struct ir *ir, const char *name) { - FILE *hdrf; char *fname; int fnamel; + struct opctx *hdrc; + int res; fnamel = strlen(name) + 4; fname = malloc(fnamel); snprintf(fname, fnamel, "%s.h", name); - /* open output file */ - hdrf = genb_fopen_tmp(fname); + /* open the output header file */ + res = output_open(fname, &hdrc); free(fname); - if (hdrf == NULL) { + if (res != 0 ) { return NULL; } /* tool preface */ - output_tool_preface(hdrf); + output_tool_preface(hdrc); /* binding preface */ - output_method_cdata(hdrf, + output_method_cdata(hdrc, ir->binding_node, GENBIND_METHOD_TYPE_PREFACE); /* header guard */ - fprintf(hdrf, "\n#ifndef %s_%s_h\n", DLPFX, name); - fprintf(hdrf, "#define %s_%s_h\n\n", DLPFX, name); + outputf(hdrc, + "\n#ifndef %s_%s_h\n", DLPFX, name); + outputf(hdrc, + "#define %s_%s_h\n\n", DLPFX, name); - return hdrf; + return hdrc; } -static int close_header(struct ir *ir, - FILE *hdrf, - const char *name) +static int close_header(struct ir *ir, struct opctx *hdrc) { - char *fname; - int fnamel; - - fnamel = strlen(name) + 4; - fname = malloc(fnamel); - snprintf(fname, fnamel, "%s.h", name); - - fprintf(hdrf, "\n#endif\n"); + /* close header guard */ + outputf(hdrc, + "\n#endif\n"); /* binding postface */ - output_method_cdata(hdrf, + output_method_cdata(hdrc, ir->binding_node, GENBIND_METHOD_TYPE_POSTFACE); - genb_fclose_tmp(hdrf, fname); - free(fname); + output_close(hdrc); return 0; } @@ -116,10 +112,10 @@ static int output_private_header(struct ir *ir) { int idx; - FILE *privf; + struct opctx *privc; /* open header */ - privf = open_header(ir, "private"); + privc = open_header(ir, "private"); for (idx = 0; idx < ir->entryc; idx++) { struct ir_entry *interfacee; @@ -138,24 +134,26 @@ output_private_header(struct ir *ir) switch (interfacee->type) { case IR_ENTRY_TYPE_INTERFACE: - fprintf(privf, + outputf(privc, "/* Private data for %s interface */\n", interfacee->name); break; case IR_ENTRY_TYPE_DICTIONARY: - fprintf(privf, + outputf(privc, "/* Private data for %s dictionary */\n", interfacee->name); break; } - fprintf(privf, "typedef struct {\n"); + outputf(privc, + "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", + outputf(privc, + "\t%s_private_t parent;\n", inherite->class_name); } @@ -165,11 +163,11 @@ output_private_header(struct ir *ir) NULL, GENBIND_NODE_TYPE_PRIVATE); while (priv_node != NULL) { - fprintf(privf, "\t"); + outputc(privc, '\t'); - output_ctype(privf, priv_node, true); + output_ctype(privc, priv_node, true); - fprintf(privf, ";\n"); + outputf(privc, ";\n"); priv_node = genbind_node_find_type( genbind_node_getnode(interfacee->class), @@ -177,11 +175,12 @@ output_private_header(struct ir *ir) GENBIND_NODE_TYPE_PRIVATE); } - fprintf(privf, "} __attribute__((aligned)) %s_private_t;\n\n", interfacee->class_name); - + outputf(privc, + "} __attribute__((aligned)) %s_private_t;\n\n", + interfacee->class_name); } - close_header(ir, privf, "private"); + close_header(ir, privc); return 0; } @@ -193,10 +192,10 @@ static int output_prototype_header(struct ir *ir) { int idx; - FILE *protof; + struct opctx *protoc; /* open header */ - protof = open_header(ir, "prototype"); + protoc = open_header(ir, "prototype"); for (idx = 0; idx < ir->entryc; idx++) { struct ir_entry *entry; @@ -205,16 +204,16 @@ output_prototype_header(struct ir *ir) switch (entry->type) { case IR_ENTRY_TYPE_INTERFACE: - output_interface_declaration(protof, entry); + output_interface_declaration(protoc, entry); break; case IR_ENTRY_TYPE_DICTIONARY: - output_dictionary_declaration(protof, entry); + output_dictionary_declaration(protoc, entry); break; } } - close_header(ir, protof, "prototype"); + close_header(ir, protoc); return 0; } @@ -271,12 +270,12 @@ output_makefile(struct ir *ir) static int output_binding_header(struct ir *ir) { - FILE *bindf; + struct opctx *bindc; /* open header */ - bindf = open_header(ir, "binding"); + bindc = open_header(ir, "binding"); - fprintf(bindf, + outputf(bindc, "#define _MAGIC(S) (\"%s\" S)\n" "#define MAGIC(S) _MAGIC(#S)\n" "#define PROTO_MAGIC MAGIC(PROTOTYPES)\n" @@ -291,7 +290,7 @@ output_binding_header(struct ir *ir) MAGICPFX); /* declaration of constant string values */ - fprintf(bindf, + outputf(bindc, "/* Constant strings */\n" "extern const char *%s_error_fmt_argument;\n" "extern const char *%s_error_fmt_bool_type;\n" @@ -301,14 +300,14 @@ output_binding_header(struct ir *ir) "\n", DLPFX, DLPFX, DLPFX, DLPFX, DLPFX); - fprintf(bindf, + outputf(bindc, "duk_bool_t %s_instanceof(duk_context *ctx, duk_idx_t index, const char *klass);\n", DLPFX); - fprintf(bindf, + outputf(bindc, "duk_ret_t %s_create_prototypes(duk_context *ctx);\n", DLPFX); - close_header(ir, bindf, "binding"); + close_header(ir, bindc); return 0; } @@ -324,54 +323,55 @@ static int output_binding_src(struct ir *ir) { int idx; - FILE *bindf; struct ir_entry *pglobale = NULL; char *proto_name; + struct opctx *bindc; + int res; - /* open output file */ - bindf = genb_fopen_tmp("binding.c"); - if (bindf == NULL) { + /* open the output binding file */ + res = output_open("binding.c", &bindc); + if (res != 0 ) { return -1; } /* tool preface */ - output_tool_preface(bindf); + output_tool_preface(bindc); /* binding preface */ - output_method_cdata(bindf, + output_method_cdata(bindc, ir->binding_node, GENBIND_METHOD_TYPE_PREFACE); /* tool prologue */ - output_tool_prologue(bindf); + output_tool_prologue(bindc); /* binding prologue */ - output_method_cdata(bindf, + output_method_cdata(bindc, ir->binding_node, GENBIND_METHOD_TYPE_PROLOGUE); - fprintf(bindf, "\n"); + outputc(bindc, '\n'); - fprintf(bindf, + outputf(bindc, "/* Error format strings */\n" "const char *%s_error_fmt_argument =\"%%d argument required, but ony %%d present.\";\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); - fprintf(bindf, "\n"); + outputf(bindc, "\n"); - fprintf(bindf, + outputf(bindc, "/* 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"); + outputf(bindc, "\n"); /* instanceof helper */ - fprintf(bindf, + outputf(bindc, "duk_bool_t\n" "%s_instanceof(duk_context *ctx, duk_idx_t _idx, const char *klass)\n" "{\n" @@ -406,7 +406,7 @@ output_binding_src(struct ir *ir) DLPFX, DLPFX); /* prototype creation helper function */ - fprintf(bindf, + outputf(bindc, "static duk_ret_t\n" "%s_to_string(duk_context *ctx)\n" "{\n" @@ -431,10 +431,10 @@ output_binding_src(struct ir *ir) DLPFX, MAGICPFX); - fprintf(bindf, + outputf(bindc, "static duk_ret_t %s_create_prototype(duk_context *ctx,\n", DLPFX); - fprintf(bindf, + outputf(bindc, "\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" @@ -460,10 +460,10 @@ output_binding_src(struct ir *ir) DLPFX); /* generate prototype creation */ - fprintf(bindf, + outputf(bindc, "duk_ret_t %s_create_prototypes(duk_context *ctx)\n", DLPFX); - fprintf(bindf, "{\n"); + outputf(bindc, "{\n"); for (idx = 0; idx < ir->entryc; idx++) { struct ir_entry *interfacee; @@ -489,7 +489,7 @@ output_binding_src(struct ir *ir) } proto_name = get_prototype_name(interfacee->name); - fprintf(bindf, + outputf(bindc, "\t%s_create_prototype(ctx, %s_%s___proto, \"%s\", \"%s\");\n", DLPFX, DLPFX, @@ -501,10 +501,10 @@ output_binding_src(struct ir *ir) } if (pglobale != NULL) { - fprintf(bindf, "\n\t/* Global object prototype is last */\n"); + outputf(bindc, "\n\t/* Global object prototype is last */\n"); proto_name = get_prototype_name(pglobale->name); - fprintf(bindf, + outputf(bindc, "\t%s_create_prototype(ctx, %s_%s___proto, \"%s\", \"%s\");\n", DLPFX, DLPFX, @@ -514,16 +514,16 @@ output_binding_src(struct ir *ir) free(proto_name); } - fprintf(bindf, "\n\treturn DUK_ERR_NONE;\n"); + outputf(bindc, "\n\treturn DUK_ERR_NONE;\n"); - fprintf(bindf, "}\n"); + outputf(bindc, "}\n"); /* binding postface */ - output_method_cdata(bindf, + output_method_cdata(bindc, ir->binding_node, GENBIND_METHOD_TYPE_POSTFACE); - genb_fclose_tmp(bindf, "binding.c"); + output_close(bindc); return 0; } diff --git a/src/duk-libdom.h b/src/duk-libdom.h index 51d4327..37a9825 100644 --- a/src/duk-libdom.h +++ b/src/duk-libdom.h @@ -16,33 +16,36 @@ int duk_libdom_output(struct ir *ir); /** * generate a source file to implement an interface using duk and libdom. + * + * \param ir The intermediate representation of the binding tree. + * \param interfacee The interface entry to output within the ir. */ int output_interface(struct ir *ir, struct ir_entry *interfacee); /** - * generate a declaration to implement a dictionary using duk and libdom. + * generate a source file to implement a dictionary using duk and libdom. */ -int output_interface_declaration(FILE* outf, struct ir_entry *interfacee); +int output_dictionary(struct ir *ir, struct ir_entry *dictionarye); /** - * generate a source file to implement a dictionary using duk and libdom. + * generate a declaration to implement a dictionary using duk and libdom. */ -int output_dictionary(struct ir *ir, struct ir_entry *dictionarye); +int output_interface_declaration(struct opctx *outc, struct ir_entry *interfacee); /** * generate a declaration to implement a dictionary using duk and libdom. */ -int output_dictionary_declaration(FILE* outf, struct ir_entry *dictionarye); +int output_dictionary_declaration(struct opctx *outc, struct ir_entry *dictionarye); /** * generate preface block for nsgenbind */ -int output_tool_preface(FILE* outf); +int output_tool_preface(struct opctx *outc); /** * generate preface block for nsgenbind */ -int output_tool_prologue(FILE* outf); +int output_tool_prologue(struct opctx *outc); /** * output character data of node of given type. @@ -54,7 +57,7 @@ int output_tool_prologue(FILE* outf); * \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); +int output_cdata(struct opctx *outc, struct genbind_node *node, enum genbind_node_type nodetype); /** @@ -67,7 +70,7 @@ int output_cdata(FILE* outf, struct genbind_node *node, enum genbind_node_type n * \param nodetype the type of child node to search for. * \return The number of nodes written or 0 for none. */ -int output_ccode(FILE* outf, struct genbind_node *node); +int output_ccode(struct opctx *outc, struct genbind_node *node); /** * output character data of method node of given type. @@ -79,7 +82,7 @@ int output_ccode(FILE* outf, struct genbind_node *node); * \param nodetype the type of child node to search for. * \return The number of nodes written or 0 for none. */ -int output_method_cdata(FILE* outf, struct genbind_node *node, enum genbind_method_type sel_method_type); +int output_method_cdata(struct opctx *outc, struct genbind_node *node, enum genbind_method_type sel_method_type); /** * output a C variable type @@ -94,7 +97,7 @@ int output_method_cdata(FILE* outf, struct genbind_node *node, enum genbind_meth * \param identifier If the indentifier should be output. * \return 0 on success. */ -int output_ctype(FILE *outf, struct genbind_node *node, bool identifier); +int output_ctype(struct opctx *outc, struct genbind_node *node, bool identifier); /** * Generate a C name from an IDL name. @@ -114,12 +117,12 @@ char *gen_idl2c_name(const char *idlname); /** * Generate class property setter for a single attribute. */ -int output_generated_attribute_setter(FILE* outf, struct ir_entry *interfacee, struct ir_attribute_entry *atributee); +int output_generated_attribute_setter(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee); /** * Generate class property getter for a single attribute. */ -int output_generated_attribute_getter(FILE* outf, struct ir_entry *interfacee, struct ir_attribute_entry *atributee); +int output_generated_attribute_getter(struct opctx *outc, struct ir_entry *interfacee, struct ir_attribute_entry *atributee); #endif diff --git a/src/nsgenbind.c b/src/nsgenbind.c index 58d62cb..73b9673 100644 --- a/src/nsgenbind.c +++ b/src/nsgenbind.c @@ -18,6 +18,7 @@ #include "nsgenbind-ast.h" #include "webidl-ast.h" #include "ir.h" +#include "output.h" #include "jsapi-libdom.h" #include "duk-libdom.h" diff --git a/src/output.c b/src/output.c new file mode 100644 index 0000000..84579f2 --- /dev/null +++ b/src/output.c @@ -0,0 +1,106 @@ +/* generated output implementation + * + * This file is part of nsgenbind. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2019 Vincent Sanders + */ + +#include +#include +#include +#include + +#include "utils.h" +#include "output.h" + +struct opctx { + char *filename; + FILE *outf; + unsigned int lineno; +}; + +int output_open(const char *filename, struct opctx **opctx_out) +{ + struct opctx *opctx; + + opctx = malloc(sizeof(struct opctx)); + if (opctx == NULL) { + return -1; + } + + opctx->filename = strdup(filename); + if (opctx->filename == NULL) { + free(opctx); + return -1; + } + + /* open output file */ + opctx->outf = genb_fopen_tmp(opctx->filename); + if (opctx->outf == NULL) { + free(opctx->filename); + free(opctx); + return -1; + } + + opctx->lineno = 2; + *opctx_out = opctx; + + return 0; +} + +int output_close(struct opctx *opctx) +{ + int res; + res = genb_fclose_tmp(opctx->outf, opctx->filename); + free(opctx->filename); + free(opctx); + return res; +} + +/** + * buffer to hold formatted output so newlines can be counted + */ +static char output_buffer[128*1024]; + +int outputf(struct opctx *opctx, const char *fmt, ...) +{ + va_list ap; + int res; + int idx; + + va_start(ap, fmt); + res = vsnprintf(output_buffer, sizeof(output_buffer), fmt, ap); + va_end(ap); + + /* account for newlines in output */ + for (idx = 0; idx < res; idx++) { + if (output_buffer[idx] == '\n') { + opctx->lineno++; + } + } + + fwrite(output_buffer, 1, res, opctx->outf); + + return res; +} + +int outputc(struct opctx *opctx, int c) +{ + if (c == '\n') { + opctx->lineno++; + } + fputc(c, opctx->outf); + + return 0; +} + +int output_line(struct opctx *opctx) +{ + int res; + res = fprintf(opctx->outf, + "#line %d \"%s\"\n", + opctx->lineno, opctx->filename); + opctx->lineno++; + return res; +} diff --git a/src/output.h b/src/output.h new file mode 100644 index 0000000..0423feb --- /dev/null +++ b/src/output.h @@ -0,0 +1,42 @@ +/* generated output handlers + * + * This file is part of nsgenbind. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2012 Vincent Sanders + */ + +#ifndef nsgenbind_output_h +#define nsgenbind_output_h + +struct opctx; + +/** + * open output file + * + * opens output file and creates output context + * + * \param filename The filename of the file to output + * \param opctx_out The resulting output context + * \return 0 on success and opctx_out updated else -1 + */ +int output_open(const char *filename, struct opctx **opctx_out); + +/** + * close output file and free context + */ +int output_close(struct opctx *opctx); + +/** + * output formatted data to file + */ +int outputf(struct opctx *opctx, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + +int outputc(struct opctx *opctx, int c); + +/** + * generate c comment with line directive for current outut context + */ +int output_line(struct opctx *opctx); + +#endif -- cgit v1.2.3