29#define MAGICPFX "\\xFF\\xFFNETSURF_DUKTAPE_"
35static char *get_prototype_name(
const char *interface_name)
43 pnamelen = strlen(interface_name) + 1;
45 proto_name =
malloc(pnamelen + pfxlen);
46 snprintf(proto_name, pnamelen + pfxlen,
47 "%sPROTOTYPE_%s",
MAGICPFX, interface_name);
48 for (pnamelen-- ; pnamelen >= 0; pnamelen--) {
49 proto_name[pnamelen + pfxlen] = toupper(interface_name[pnamelen]);
68 while ((ta != NULL) && (tb != NULL)) {
75 if (strcmp(txt_a, txt_b) != 0) {
99output_create_private(
struct opctx *outc,
char *class_name)
102 "\t/* create private data and attach to instance */\n");
104 "\t%s_private_t *priv = calloc(1, sizeof(*priv));\n",
107 "\tif (priv == NULL) return 0;\n");
109 "\tduk_push_pointer(ctx, priv);\n");
111 "\tduk_put_prop_string(ctx, 0, %s_magic_string_private);\n\n",
122output_safe_get_private(
struct opctx *outc,
char *class_name,
int idx)
125 "\t%s_private_t *priv;\n", class_name);
127 "\tduk_get_prop_string(ctx, %d, %s_magic_string_private);\n",
130 "\tpriv = duk_get_pointer(ctx, -1);\n");
132 "\tduk_pop(ctx);\n");
134 "\tif (priv == NULL) return 0;\n\n");
143static int output_get_prototype(
struct opctx *outc,
const char *interface_name)
147 proto_name = get_prototype_name(interface_name);
150 "\t/* get prototype */\n");
152 "\tduk_get_global_string(ctx, %s_magic_string_prototypes);\n",
155 "\tduk_get_prop_string(ctx, -1, \"%s\");\n",
158 "\tduk_replace(ctx, -2);\n");
168static int output_set_destructor(
struct opctx *outc,
char *class_name,
int idx)
171 "\t/* Set the destructor */\n");
173 "\tduk_dup(ctx, %d);\n", idx);
175 "\tduk_push_c_function(ctx, %s_%s___destructor, 1);\n",
178 "\tduk_set_finalizer(ctx, -2);\n");
180 "\tduk_pop(ctx);\n\n");
189output_set_constructor(
struct opctx *outc,
char *class_name,
int idx,
int argc)
192 "\t/* Set the constructor */\n");
194 "\tduk_dup(ctx, %d);\n", idx);
196 "\tduk_push_c_function(ctx, %s_%s___constructor, %d);\n",
197 DLPFX, class_name, 1 + argc);
199 "\tduk_put_prop_string(ctx, -2, \"%sINIT\");\n",
202 "\tduk_pop(ctx);\n\n");
212output_dump_stack(
struct opctx *outc)
217 "\tduk_push_context_dump(ctx);\n");
219 "\tNSLOG(dukky, DEEPDEBUG, \"Stack: %%s\", duk_to_string(ctx, -1));\n");
221 "\tduk_pop(ctx);\n");
231output_add_method(
struct opctx *outc,
232 const char *class_name,
236 "\t/* Add a method */\n");
238 "\tduk_dup(ctx, 0);\n");
240 "\tduk_push_string(ctx, \"%s\");\n", method);
242 "\tduk_push_c_function(ctx, %s_%s_%s, DUK_VARARGS);\n",
243 DLPFX, class_name, method);
244 output_dump_stack(outc);
246 "\tduk_def_prop(ctx, -3,\n");
248 "\t\t DUK_DEFPROP_HAVE_VALUE |\n");
250 "\t\t DUK_DEFPROP_HAVE_WRITABLE |\n");
252 "\t\t DUK_DEFPROP_HAVE_ENUMERABLE |\n");
254 "\t\t DUK_DEFPROP_ENUMERABLE |\n");
256 "\t\t DUK_DEFPROP_HAVE_CONFIGURABLE);\n");
258 "\tduk_pop(ctx);\n\n");
267output_populate_rw_property(
struct opctx *outc,
268 const char *class_name,
269 const char *property)
272 "\t/* Add read/write property */\n");
274 "\tduk_dup(ctx, 0);\n");
276 "\tduk_push_string(ctx, \"%s\");\n", property);
278 "\tduk_push_c_function(ctx, %s_%s_%s_getter, 0);\n",
279 DLPFX, class_name, property);
281 "\tduk_push_c_function(ctx, %s_%s_%s_setter, 1);\n",
282 DLPFX, class_name, property);
283 output_dump_stack(outc);
285 "\tduk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |\n");
287 "\t\tDUK_DEFPROP_HAVE_SETTER |\n");
289 "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE |\n");
291 "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
293 "\tduk_pop(ctx);\n\n");
303output_populate_ro_property(
struct opctx *outc,
304 const char *class_name,
305 const char *property)
308 "\t/* Add readonly property */\n");
310 "\tduk_dup(ctx, 0);\n");
312 "\tduk_push_string(ctx, \"%s\");\n", property);
314 "\tduk_push_c_function(ctx, %s_%s_%s_getter, 0);\n",
315 DLPFX, class_name, property);
316 output_dump_stack(outc);
318 "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER |\n");
320 "\t\tDUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE |\n");
322 "\t\tDUK_DEFPROP_HAVE_CONFIGURABLE);\n");
324 "\tduk_pop(ctx);\n\n");
334output_prototype_constant_int(
struct opctx *outc,
335 const char *constant_name,
339 "\tduk_dup(ctx, 0);\n");
341 "\tduk_push_string(ctx, \"%s\");\n", constant_name);
343 "\tduk_push_int(ctx, %d);\n",
value);
345 "\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |\n");
347 "\t\t DUK_DEFPROP_HAVE_WRITABLE |\n");
349 "\t\t DUK_DEFPROP_HAVE_ENUMERABLE |\n");
351 "\t\t DUK_DEFPROP_ENUMERABLE |\n");
353 "\t\t DUK_DEFPROP_HAVE_CONFIGURABLE);\n");
355 "\tduk_pop(ctx);\n\n");
364output_get_method_private(
struct opctx *outc,
char *class_name,
bool is_global)
367 "\t/* Get private data for method */\n");
369 "\t%s_private_t *priv = NULL;\n", class_name);
372 "\tduk_push_global_object(ctx);\n");
375 "\tduk_push_this(ctx);\n");
378 "\tduk_get_prop_string(ctx, -1, %s_magic_string_private);\n",
381 "\tpriv = duk_get_pointer(ctx, -1);\n");
383 "\tduk_pop_2(ctx);\n");
385 "\tif (priv == NULL) {\n");
388 "\t\tNSLOG(dukky, INFO, \"priv failed\");\n");
391 "\t\treturn 0; /* can do? No can do. */\n");
403output_interface_constructor(
struct opctx *outc,
struct ir_entry *interfacee)
409 "static duk_ret_t %s_%s___constructor(duk_context *ctx)\n",
414 output_create_private(outc, interfacee->
class_name);
418 "\t%s_%s___init(ctx, priv",
427 ", duk_get_bool(ctx, %d)",
433 ", duk_get_int(ctx, %d)",
438 ", duk_get_pointer(ctx, %d)",
447 "\tduk_set_top(ctx, 1);\n");
461output_interface_destructor(
struct opctx *outc,
struct ir_entry *interfacee)
465 "static duk_ret_t %s_%s___destructor(duk_context *ctx)\n",
470 output_safe_get_private(outc, interfacee->
class_name, 0);
474 "\t%s_%s___fini(ctx, priv);\n",
493output_interface_inherit_init(
struct opctx *outc,
503 if (inherite == NULL) {
519 "\t%s_%s___init(ctx, &priv->parent",
529 while (inh_param_node != NULL) {
542 if (param_node == NULL) {
544 "class \"%s\" (interface %s) parent class \"%s\" (interface %s) initialisor requires a parameter \"%s\" with compatible identifier\n",
555 if (compare_ctypes(param_node,
556 inh_param_node) ==
false) {
579 const char *type_cdata = NULL;
581 bool unsigned_ =
false;
588 while (typename_node != NULL) {
590 if (strcmp(type_cdata,
"unsigned") == 0) {
592 }
else if (strcmp(type_cdata,
"int") == 0) {
594 }
else if (strcmp(type_cdata,
"bool") == 0) {
603 if (type_cdata[0] ==
'*') {
605 }
else if (unsigned_) {
618output_interface_init_declaration(
struct opctx *outc,
629 "void %s_%s___init(duk_context *ctx, %s_private_t *priv",
640 while (param_node != NULL) {
645 guess_argtype_from(param_node);
665output_interface_init(
struct opctx *outc,
678 output_interface_init_declaration(outc, interfacee, init_node);
683 res = output_interface_inherit_init(outc, interfacee, inherite);
691 "\tNSLOG(dukky, INFO, \"Initialise %%p (priv=%%p)\", duk_get_heapptr(ctx, 0), priv);\n" );
708output_interface_fini(
struct opctx *outc,
724 "void %s_%s___fini(duk_context *ctx, %s_private_t *priv)\n",
731 "\tNSLOG(dukky, INFO, \"Finalise %%p\", duk_get_heapptr(ctx, 0));\n" );
738 if (inherite != NULL) {
740 "\t%s_%s___fini(ctx, &priv->parent);\n",
753output_prototype_method(
struct opctx *outc,
758 if (operatione->
name != NULL) {
760 output_add_method(outc,
766 "\t/* Special method on prototype - UNIMPLEMENTED */\n\n");
777output_prototype_methods(
struct opctx *outc,
struct ir_entry *entry)
783 res = output_prototype_method(
797output_prototype_attribute(
struct opctx *outc,
803 return output_populate_ro_property(outc,
807 return output_populate_rw_property(outc,
817output_prototype_attributes(
struct opctx *outc,
struct ir_entry *entry)
823 res = output_prototype_attribute(
843output_prototype_constant(
struct opctx *outc,
854 output_prototype_constant_int(outc, constante->
name, *
value);
864output_prototype_constants(
struct opctx *outc,
struct ir_entry *entry)
870 res = output_prototype_constant(
883output_global_create_prototype(
struct opctx *outc,
890 "\t/* Create interface objects */\n");
891 for (idx = 0; idx <
ir->
entryc; idx++) {
902 if (entry == interfacee) {
904 "\tduk_dup(ctx, 0);\n");
906 output_get_prototype(outc, entry->
name);
910 "\tdukky_inject_not_ctr(ctx, 0, \"%s\");\n",
922output_interface_prototype(
struct opctx *outc,
936 "duk_ret_t %s_%s___proto(duk_context *ctx, void *udata)\n",
947 if (inherite != NULL) {
949 "\t/* Set this prototype's prototype (left-parent) */\n");
950 output_get_prototype(outc, inherite->
name);
952 "\tduk_set_prototype(ctx, 0);\n\n");
956 output_prototype_methods(outc, interfacee);
959 output_prototype_attributes(outc, interfacee);
962 output_prototype_constants(outc, interfacee);
968 output_global_create_prototype(outc,
ir, interfacee);
972 output_set_destructor(outc, interfacee->
class_name, 0);
975 output_set_constructor(outc,
981 "\treturn 1; /* The prototype object */\n");
994output_interface_elipsis_operation(
struct opctx *outc,
1002 "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
1012 "Elipsis parameters not checked: method %s::%s();",
1013 interfacee->
name, operatione->
name);
1015 output_get_method_private(outc, interfacee->
class_name,
1022 "Unimplemented: method %s::%s();",
1023 interfacee->
name, operatione->
name);
1039output_interface_overloaded_operation(
struct opctx *outc,
1047 "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
1056 output_get_method_private(outc, interfacee->
class_name,
1065 "Unimplemented: method %s::%s();",
1066 interfacee->
name, operatione->
name);
1082output_interface_special_operation(
struct opctx *outc,
1088 "/* Special method definition - UNIMPLEMENTED */\n\n");
1091 "Special operation on interface %s (operation entry %p)",
1103output_operation_optional_defaults(
1109 for (argc = 0; argc < argumentc; argc++) {
1116 cure = argumentv + argc;
1124 if (lit_node != NULL) {
1131 "\t\tduk_push_null(ctx);\n");
1137 "\t\tduk_push_int(ctx, %d);\n",
1144 "\t\tduk_push_boolean(ctx, %d);\n",
1151 "\t\tduk_push_string(ctx, \"%s\");\n",
1158 "\t\tduk_push_undefined(ctx);\n");
1163 "\t\tduk_push_undefined(ctx);\n");
1171output_operation_argument_type_check(
1182 argumente = overloade->
argumentv + argidx;
1189 if (type_node == NULL) {
1190 fprintf(stderr,
"%s:%s %dth argument %s has no type\n",
1204 if (argument_type == NULL) {
1206 "%s:%s %dth argument %s has no type base\n",
1220 "\tif (%s_argc > %d) {\n",
DLPFX, argidx);
1222 switch (*argument_type) {
1226 "\t\tif (!duk_is_string(ctx, %d)) {\n"
1227 "\t\t\tduk_to_string(ctx, %d);\n"
1228 "\t\t}\n", argidx, argidx);
1233 "\t\tif (!duk_is_boolean(ctx, %d)) {\n"
1234 "\t\t\tif (duk_is_number(ctx, %d)) {\n"
1235 "\t\t\t\tduk_to_boolean(ctx, %d);\n"
1237 "\t\t\t\treturn duk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_bool_type, %d, \"%s\");\n"
1239 "\t\t}\n", argidx, argidx, argidx,
DLPFX, argidx, argumente->
name);
1248 "\t\tif (!duk_is_number(ctx, %d)) {\n"
1249 "\t\t\treturn duk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_number_type, %d, \"%s\");\n"
1251 argidx,
DLPFX, argidx, argumente->
name);
1257 "\t\t/* unhandled type check */\n");
1271output_interface_operation(
struct opctx *outc,
1281 if (operatione->
name == NULL) {
1282 return output_interface_special_operation(outc,
1288 return output_interface_overloaded_operation(outc,
1294 return output_interface_elipsis_operation(outc,
1303 "static duk_ret_t %s_%s_%s(duk_context *ctx)\n",
1315 "\t/* ensure the parameters are present */\n"
1316 "\tduk_idx_t %s_argc = duk_get_top(ctx);\n\t",
DLPFX);
1318 if (fixedargc > 0) {
1320 "if (%s_argc < %d) {\n",
1323 "\t\t/* not enough arguments */\n");
1325 "\t\treturn duk_error(ctx, DUK_RET_TYPE_ERROR, %s_error_fmt_argument, %d, %s_argc);\n",
1331 for (optargc = fixedargc;
1335 "if (%s_argc == %d) {\n"
1336 "\t\t/* %d optional arguments need adding */\n",
1340 output_operation_optional_defaults(outc,
1348 "if (%s_argc > %d) {\n"
1349 "\t\t/* remove extraneous parameters */\n"
1350 "\t\tduk_set_top(ctx, %d);\n"
1361 "\t/* check types of passed arguments are correct */\n");
1363 for (argidx = 0; argidx < overloade->
argumentc; argidx++) {
1364 output_operation_argument_type_check(outc,
1371 output_get_method_private(outc, interfacee->
class_name,
1378 "Unimplemented: method %s::%s();",
1379 interfacee->
name, operatione->
name);
1383 "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n");
1400output_interface_operations(
struct opctx *outc,
struct ir_entry *ife)
1406 res = output_interface_operation(
1424output_attribute_getter(
struct opctx *outc,
1430 "static duk_ret_t %s_%s_%s_getter(duk_context *ctx)\n",
1435 output_get_method_private(outc,
1440 if (atributee->
getter != NULL) {
1457 const char *type_str;
1458 if (atributee->
typec == 0) {
1460 }
else if (atributee->
typec == 1) {
1464 type_str =
"multiple";
1468 "Unimplemented: getter %s::%s(%s);",
1475 "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n" );
1490output_putforwards_setter(
struct opctx *outc,
1497 "\tduk_ret_t get_ret;\n\n");
1500 "\tget_ret = %s_%s_%s_getter(ctx);\n",
1504 "\tif (get_ret != 1) {\n"
1507 "\t/* parameter ... attribute */\n\n"
1508 "\tduk_dup(ctx, 0);\n"
1509 "\t/* ... attribute parameter */\n\n"
1510 "\t/* call the putforward */\n");
1513 "\tduk_put_prop_string(ctx, -2, \"%s\");\n\n",
1527output_attribute_setter(
struct opctx *outc,
1535 "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n",
1540 output_get_method_private(outc,
1545 if (atributee->
setter != NULL) {
1554 res = output_putforwards_setter(outc,
1561 const char *type_str;
1562 if (atributee->
typec == 0) {
1564 }
else if (atributee->
typec == 1) {
1569 type_str =
"multiple";
1572 "Unimplemented: setter %s::%s(%s);",
1578 "\tNSLOG(dukky, WARNING, \"Unimplemented\");\n");
1597output_interface_attribute(
struct opctx *outc,
1607 res = output_attribute_getter(outc, interfacee, atributee);
1612 res = output_attribute_setter(outc, interfacee, atributee);
1623output_interface_attributes(
struct opctx *outc,
struct ir_entry *ife)
1628 output_interface_attribute(
1688 res = output_interface_init(ifop, interfacee, inherite);
1694 output_interface_fini(ifop, interfacee, inherite);
1697 output_interface_constructor(ifop, interfacee);
1700 output_interface_destructor(ifop, interfacee);
1703 output_interface_operations(ifop, interfacee);
1706 output_interface_attributes(ifop, interfacee);
1709 output_interface_prototype(ifop,
ir, interfacee, inherite);
1755 "duk_ret_t %s_%s___proto(duk_context *ctx, void *udata);\n",
1770 "void %s_%s___fini(duk_context *ctx, %s_private_t *priv);\n",
1779 output_interface_init_declaration(outc, interfacee, init_node);
int output_method_cdata(struct opctx *outc, struct genbind_node *node, enum genbind_method_type sel_method_type)
int output_cdata(struct opctx *outc, struct genbind_node *node, enum genbind_node_type nodetype)
int output_tool_prologue(struct opctx *outc)
int output_ccode(struct opctx *outc, struct genbind_node *node)
int output_tool_preface(struct opctx *outc)
int output_ctype(struct opctx *outc, struct genbind_node *node, bool identifier)
char * gen_idl2c_name(const char *idlname)
int output_generated_attribute_setter(struct opctx *outc, 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)
int output_interface_declaration(struct opctx *outc, struct ir_entry *interfacee)
int output_interface(struct ir *ir, struct ir_entry *interfacee)
struct ir_entry * ir_inherit_entry(struct ir *map, struct ir_entry *entry)
@ IR_ENTRY_TYPE_INTERFACE
struct genbind_node * genbind_node_find_type(struct genbind_node *node, struct genbind_node *prev, enum genbind_node_type type)
struct genbind_node * genbind_node_find_type_ident(struct genbind_node *node, struct genbind_node *prev, enum genbind_node_type type, const char *ident)
struct genbind_node * genbind_node_find_method(struct genbind_node *node, struct genbind_node *prev, enum genbind_method_type methodtype)
struct genbind_node * genbind_node_getnode(struct genbind_node *node)
char * genbind_node_gettext(struct genbind_node *node)
@ GENBIND_METHOD_TYPE_INIT
@ GENBIND_METHOD_TYPE_PREFACE
@ GENBIND_METHOD_TYPE_PROLOGUE
@ GENBIND_METHOD_TYPE_POSTFACE
@ GENBIND_METHOD_TYPE_PROTOTYPE
@ GENBIND_METHOD_TYPE_EPILOGUE
@ GENBIND_METHOD_TYPE_FINI
@ GENBIND_NODE_TYPE_PARAMETER
@ GENBIND_NODE_TYPE_METHOD
@ GENBIND_NODE_TYPE_IDENT
@ GENBIND_NODE_TYPE_CDATA
#define WARN(flags, msg, args...)
int outputc(struct opctx *opctx, int c)
int outputf(struct opctx *opctx, const char *fmt,...)
int output_close(struct opctx *opctx)
int output_open(const char *filename, struct opctx **opctx_out)
enum webidl_type_modifier modifier
struct ir_type_entry * typev
struct genbind_node * setter
struct genbind_node * getter
struct webidl_node * node
enum ir_init_argtype * class_init_argt
struct genbind_node * class
struct ir_interface_entry interface
struct ir_attribute_entry * attributev
struct ir_operation_entry * operationv
struct ir_constant_entry * constantv
struct webidl_node * node
struct ir_operation_overload_entry * overloadv
struct genbind_node * method
struct ir_operation_argument_entry * argumentv
enum webidl_type_modifier modifier
struct genbind_node * binding_node
struct ir_entry * entries
struct webidl_node * webidl_node_getnode(struct webidl_node *node)
char * webidl_node_gettext(struct webidl_node *node)
const char * webidl_type_to_str(enum webidl_type_modifier m, enum webidl_type t)
int * webidl_node_getint(struct webidl_node *node)
enum webidl_node_type webidl_node_gettype(struct webidl_node *node)
struct webidl_node * webidl_node_find_type(struct webidl_node *node, struct webidl_node *prev, enum webidl_node_type type)
@ WEBIDL_NODE_TYPE_LITERAL_STRING
@ WEBIDL_NODE_TYPE_TYPE_BASE
@ WEBIDL_NODE_TYPE_LITERAL_NULL
@ WEBIDL_NODE_TYPE_OPTIONAL
@ WEBIDL_NODE_TYPE_LITERAL_BOOL
@ WEBIDL_NODE_TYPE_LITERAL_INT
@ WEBIDL_NODE_TYPE_LITERAL_FLOAT
@ WEBIDL_TYPE_MODIFIER_READONLY