From 8779ca25c44286b956ac604549d55c7d1661619e Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 1 Nov 2012 21:10:37 +0000 Subject: improve return variable handling --- src/jsapi-libdom-operator.c | 231 ++++++++++++++++++++++++++++++++++-- src/jsapi-libdom-property.c | 282 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 467 insertions(+), 46 deletions(-) diff --git a/src/jsapi-libdom-operator.c b/src/jsapi-libdom-operator.c index 748ea4c..a20f377 100644 --- a/src/jsapi-libdom-operator.c +++ b/src/jsapi-libdom-operator.c @@ -17,6 +17,9 @@ #include "webidl-ast.h" #include "jsapi-libdom.h" +#define WARN(msg, args...) fprintf(stderr, "%s: warning:"msg"\n", __func__, ## args); + + static int webidl_func_spec_cb(struct webidl_node *node, void *ctx) { struct binding *binding = ctx; @@ -125,6 +128,219 @@ int output_function_spec(struct binding *binding) return res; } +static int output_return(struct binding *binding, + const char *ident, + struct webidl_node *node) +{ + struct webidl_node *arglist_node = NULL; + struct webidl_node *type_node = NULL; + struct webidl_node *type_base = NULL; + enum webidl_type webidl_arg_type; + + arglist_node = webidl_node_find_type(node, + NULL, + WEBIDL_NODE_TYPE_LIST); + + if (arglist_node == NULL) { + return -1; /* @todo check if this is broken AST */ + } + + type_node = webidl_node_find_type(webidl_node_getnode(arglist_node), + NULL, + WEBIDL_NODE_TYPE_TYPE); + + type_base = webidl_node_find_type(webidl_node_getnode(type_node), + NULL, + WEBIDL_NODE_TYPE_TYPE_BASE); + + webidl_arg_type = webidl_node_getint(type_base); + + switch (webidl_arg_type) { + case WEBIDL_TYPE_USER: + /* User type are represented with jsobject */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(%s));\n", + ident); + + break; + + case WEBIDL_TYPE_BOOL: + /* JSBool */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(%s));\n", + ident); + + break; + + case WEBIDL_TYPE_BYTE: + WARN("Unhandled type WEBIDL_TYPE_BYTE"); + break; + + case WEBIDL_TYPE_OCTET: + WARN("Unhandled type WEBIDL_TYPE_OCTET"); + break; + + case WEBIDL_TYPE_FLOAT: + case WEBIDL_TYPE_DOUBLE: + /* double */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_SHORT: + WARN("Unhandled type WEBIDL_TYPE_SHORT"); + break; + + case WEBIDL_TYPE_LONGLONG: + WARN("Unhandled type WEBIDL_TYPE_LONGLONG"); + break; + + case WEBIDL_TYPE_LONG: + /* int32_t */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, INT_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_STRING: + /* JSString * */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, STRING_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_SEQUENCE: + WARN("Unhandled type WEBIDL_TYPE_SEQUENCE"); + break; + + case WEBIDL_TYPE_OBJECT: + /* JSObject * */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_DATE: + WARN("Unhandled type WEBIDL_TYPE_DATE"); + break; + + case WEBIDL_TYPE_VOID: + /* specifically requires no value */ + break; + + default: + break; + } + + return 0; +} + + +/* generate variable declaration of the correct type with appropriate default */ +static int output_return_declaration(struct binding *binding, + const char *ident, + struct webidl_node *node) +{ + struct webidl_node *arglist_node = NULL; + struct webidl_node *type_node = NULL; + struct webidl_node *type_base = NULL; + struct webidl_node *type_name = NULL; + enum webidl_type webidl_arg_type; + + arglist_node = webidl_node_find_type(node, + NULL, + WEBIDL_NODE_TYPE_LIST); + + if (arglist_node == NULL) { + return -1; /* @todo check if this is broken AST */ + } + + type_node = webidl_node_find_type(webidl_node_getnode(arglist_node), + NULL, + WEBIDL_NODE_TYPE_TYPE); + + type_base = webidl_node_find_type(webidl_node_getnode(type_node), + NULL, + WEBIDL_NODE_TYPE_TYPE_BASE); + + webidl_arg_type = webidl_node_getint(type_base); + + switch (webidl_arg_type) { + case WEBIDL_TYPE_USER: + /* User type are represented with jsobject */ + type_name = webidl_node_find_type(webidl_node_getnode(type_node), + NULL, + WEBIDL_NODE_TYPE_IDENT); + fprintf(binding->outfile, + "\tJSObject *%s = NULL; /* %s */\n", + ident, + webidl_node_gettext(type_name)); + + break; + + case WEBIDL_TYPE_BOOL: + /* JSBool */ + fprintf(binding->outfile, "\tJSBool %s = JS_FALSE;\n",ident); + + break; + + case WEBIDL_TYPE_BYTE: + WARN("Unhandled type WEBIDL_TYPE_BYTE"); + break; + + case WEBIDL_TYPE_OCTET: + WARN("Unhandled type WEBIDL_TYPE_OCTET"); + break; + + case WEBIDL_TYPE_FLOAT: + case WEBIDL_TYPE_DOUBLE: + /* double */ + fprintf(binding->outfile, "\tdouble %s = 0;\n", ident); + break; + + case WEBIDL_TYPE_SHORT: + WARN("Unhandled type WEBIDL_TYPE_SHORT"); + break; + + case WEBIDL_TYPE_LONGLONG: + WARN("Unhandled type WEBIDL_TYPE_LONGLONG"); + break; + + case WEBIDL_TYPE_LONG: + /* int32_t */ + fprintf(binding->outfile, "\tint32_t %s = 0;\n", ident); + break; + + case WEBIDL_TYPE_STRING: + /* JSString * */ + fprintf(binding->outfile, + "\tJSString *%s = NULL;\n", + ident); + break; + + case WEBIDL_TYPE_SEQUENCE: + WARN("Unhandled type WEBIDL_TYPE_SEQUENCE"); + break; + + case WEBIDL_TYPE_OBJECT: + /* JSObject * */ + fprintf(binding->outfile, "\tJSObject *%s = NULL;\n", ident); + break; + + case WEBIDL_TYPE_DATE: + WARN("Unhandled type WEBIDL_TYPE_DATE"); + break; + + case WEBIDL_TYPE_VOID: + /* specifically requires no value */ + break; + + default: + break; + } + return 0; +} /** creates all the variable definitions * @@ -145,9 +361,6 @@ output_variable_definitions(struct binding *binding, struct webidl_node *arg_type_ident = NULL; enum webidl_type webidl_arg_type; - /* return value */ - fprintf(binding->outfile, "\tjsval jsretval = JSVAL_VOID;\n"); - /* input variables */ arglist_node = webidl_node_find_type(operation_list, NULL, @@ -197,7 +410,7 @@ output_variable_definitions(struct binding *binding, NULL, WEBIDL_NODE_TYPE_IDENT); - fprintf(stderr, + fprintf(stderr, "User type: %s:%s %s\n", webidl_node_gettext(operation_ident), webidl_node_gettext(arg_type_ident), @@ -448,6 +661,9 @@ static int webidl_operator_body_cb(struct webidl_node *node, void *ctx) fprintf(binding->outfile, "{\n"); + /* return value declaration */ + output_return_declaration(binding, "jsret", webidl_node_getnode(node)); + output_variable_definitions(binding, webidl_node_getnode(node)); if (binding->has_private) { @@ -475,15 +691,16 @@ static int webidl_operator_body_cb(struct webidl_node *node, void *ctx) genbind_node_getnode(operation_node)); } else { - fprintf(stderr, - "Warning: function/operation %s.%s has no implementation\n", + fprintf(stderr, + "warning: operation %s.%s has no implementation\n", binding->interface, webidl_node_gettext(ident_node)); } + output_return(binding, "jsret", webidl_node_getnode(node)); + /* set return value an return true */ fprintf(binding->outfile, - "\tJSAPI_SET_RVAL(cx, vp, jsretval);\n" "\treturn JS_TRUE;\n" "}\n\n"); } diff --git a/src/jsapi-libdom-property.c b/src/jsapi-libdom-property.c index 6083bb9..b5f30b9 100644 --- a/src/jsapi-libdom-property.c +++ b/src/jsapi-libdom-property.c @@ -140,48 +140,217 @@ output_property_spec(struct binding *binding) return res; } -static int webidl_property_body_cb(struct webidl_node *node, void *ctx) +#define WARN(msg, args...) fprintf(stderr, "%s: warning:"msg"\n", __func__, ## args); + +static int output_return(struct binding *binding, + const char *ident, + struct webidl_node *node) { - struct binding *binding = ctx; - struct webidl_node *ident_node; - struct webidl_node *modifier_node; - struct genbind_node *property_node; + struct webidl_node *type_node = NULL; + struct webidl_node *type_base = NULL; + enum webidl_type webidl_arg_type; - ident_node = webidl_node_find_type(webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_IDENT); - if (ident_node == NULL) { - /* properties must have an operator - * http://www.w3.org/TR/WebIDL/#idl-attributes - */ - return 1; - } + type_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_TYPE); - modifier_node = webidl_node_find_type(webidl_node_getnode(node), + type_base = webidl_node_find_type(webidl_node_getnode(type_node), NULL, - WEBIDL_NODE_TYPE_MODIFIER); + WEBIDL_NODE_TYPE_TYPE_BASE); + webidl_arg_type = webidl_node_getint(type_base); - if (webidl_node_getint(modifier_node) != WEBIDL_TYPE_READONLY) { - /* no readonly so a set function is required */ + switch (webidl_arg_type) { + case WEBIDL_TYPE_USER: + /* User type are represented with jsobject */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_BOOL: + /* JSBool */ fprintf(binding->outfile, - "static JSBool JSAPI_PROPERTYSET(%s, JSContext *cx, JSObject *obj, jsval *vp)\n", - webidl_node_gettext(ident_node)); + "\tJS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(%s));\n", + ident); + + break; + + case WEBIDL_TYPE_BYTE: + WARN("Unhandled type WEBIDL_TYPE_BYTE"); + break; + + case WEBIDL_TYPE_OCTET: + WARN("Unhandled type WEBIDL_TYPE_OCTET"); + break; + + case WEBIDL_TYPE_FLOAT: + case WEBIDL_TYPE_DOUBLE: + /* double */ fprintf(binding->outfile, - "{\n" - " return JS_FALSE;\n" - "}\n\n"); + "\tJS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_SHORT: + WARN("Unhandled type WEBIDL_TYPE_SHORT"); + break; + + case WEBIDL_TYPE_LONGLONG: + WARN("Unhandled type WEBIDL_TYPE_LONGLONG"); + break; + + case WEBIDL_TYPE_LONG: + /* int32_t */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, INT_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_STRING: + /* JSString * */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, STRING_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_SEQUENCE: + WARN("Unhandled type WEBIDL_TYPE_SEQUENCE"); + break; + + case WEBIDL_TYPE_OBJECT: + /* JSObject * */ + fprintf(binding->outfile, + "\tJS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(%s));\n", + ident); + break; + + case WEBIDL_TYPE_DATE: + WARN("Unhandled type WEBIDL_TYPE_DATE"); + break; + + case WEBIDL_TYPE_VOID: + /* specifically requires no value */ + break; + + default: + break; } - /* property getter */ + return 0; +} + + +/* generate variable declaration of the correct type with appropriate default */ +static int output_return_declaration(struct binding *binding, + const char *ident, + struct webidl_node *node) +{ + struct webidl_node *type_node = NULL; + struct webidl_node *type_base = NULL; + struct webidl_node *type_name = NULL; + enum webidl_type webidl_arg_type; + + type_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_TYPE); + + type_base = webidl_node_find_type(webidl_node_getnode(type_node), + NULL, + WEBIDL_NODE_TYPE_TYPE_BASE); + + webidl_arg_type = webidl_node_getint(type_base); + + switch (webidl_arg_type) { + case WEBIDL_TYPE_USER: + /* User type are represented with jsobject */ + type_name = webidl_node_find_type(webidl_node_getnode(type_node), + NULL, + WEBIDL_NODE_TYPE_IDENT); + fprintf(binding->outfile, + "\tJSObject *%s = NULL; /* %s */\n", + ident, + webidl_node_gettext(type_name)); + + break; + + case WEBIDL_TYPE_BOOL: + /* JSBool */ + fprintf(binding->outfile, "\tJSBool %s = JS_FALSE;\n",ident); + + break; + + case WEBIDL_TYPE_BYTE: + WARN("Unhandled type WEBIDL_TYPE_BYTE"); + break; + + case WEBIDL_TYPE_OCTET: + WARN("Unhandled type WEBIDL_TYPE_OCTET"); + break; + + case WEBIDL_TYPE_FLOAT: + case WEBIDL_TYPE_DOUBLE: + /* double */ + fprintf(binding->outfile, "\tdouble %s = 0;\n", ident); + break; + + case WEBIDL_TYPE_SHORT: + WARN("Unhandled type WEBIDL_TYPE_SHORT"); + break; + + case WEBIDL_TYPE_LONGLONG: + WARN("Unhandled type WEBIDL_TYPE_LONGLONG"); + break; + + case WEBIDL_TYPE_LONG: + /* int32_t */ + fprintf(binding->outfile, "\tint32_t %s = 0;\n", ident); + break; + + case WEBIDL_TYPE_STRING: + /* JSString * */ + fprintf(binding->outfile, + "\tJSString *%s = NULL;\n", + ident); + break; + + case WEBIDL_TYPE_SEQUENCE: + WARN("Unhandled type WEBIDL_TYPE_SEQUENCE"); + break; + + case WEBIDL_TYPE_OBJECT: + /* JSObject * */ + fprintf(binding->outfile, "\tJSObject *%s = NULL;\n", ident); + break; + + case WEBIDL_TYPE_DATE: + WARN("Unhandled type WEBIDL_TYPE_DATE"); + break; + + case WEBIDL_TYPE_VOID: + /* specifically requires no value */ + break; + + default: + break; + } + return 0; +} + +static int output_property_getter(struct binding *binding, + struct webidl_node *node, + const char *ident) +{ + struct genbind_node *property_node; + fprintf(binding->outfile, "static JSBool JSAPI_PROPERTYGET(%s, JSContext *cx, JSObject *obj, jsval *vp)\n" "{\n", - webidl_node_gettext(ident_node)); + ident); - /* return value */ - fprintf(binding->outfile, "\tjsval jsretval = JSVAL_NULL;\n"); + /* return value declaration */ + output_return_declaration(binding, "jsret", node); if (binding->has_private) { /* get context */ @@ -193,14 +362,14 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx) "\t\t&JSClass_%s,\n" "\t\tNULL);\n" "\tif (private == NULL)\n" - "\t\treturn JS_FALSE;\n\n", + "\t\treturn JS_FALSE;\n\n", binding->interface); } property_node = genbind_node_find_type_ident(binding->gb_ast, NULL, GENBIND_NODE_TYPE_GETTER, - webidl_node_gettext(ident_node)); + ident); if (property_node != NULL) { /* binding source block */ @@ -218,33 +387,68 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx) internal_node = genbind_node_find_type_ident(genbind_node_getnode(binding_node), NULL, GENBIND_NODE_TYPE_BINDING_INTERNAL, - webidl_node_gettext(ident_node)); + ident); } if (internal_node != NULL) { /** @todo fetching from internal entries ought to be type sensitive */ fprintf(binding->outfile, - "\tjsretval = OBJECT_TO_JSVAL(private->%s);\n", - webidl_node_gettext(ident_node)); + "\tjsret = private->%s;\n", + ident); } else { - fprintf(stderr, - "Warning: property/attribute getter %s.%s has no implementation\n", + fprintf(stderr, + "warning: attribute getter %s.%s has no implementation\n", binding->interface, - webidl_node_gettext(ident_node)); + ident); } } + output_return(binding, "jsret", node); fprintf(binding->outfile, - "\tJS_SET_RVAL(cx, vp, jsretval);\n" - "\treturn JS_TRUE;\n"); + "\treturn JS_TRUE;\n" + "}\n\n"); + + return 0; +} + +static int webidl_property_body_cb(struct webidl_node *node, void *ctx) +{ + struct binding *binding = ctx; + struct webidl_node *ident_node; + struct webidl_node *modifier_node; - fprintf(binding->outfile, "}\n\n"); + ident_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_IDENT); + if (ident_node == NULL) { + /* properties must have an operator + * http://www.w3.org/TR/WebIDL/#idl-attributes + */ + return 1; + } + modifier_node = webidl_node_find_type(webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_MODIFIER); - return 0; + + if (webidl_node_getint(modifier_node) != WEBIDL_TYPE_READONLY) { + /* no readonly so a set function is required */ + + fprintf(binding->outfile, + "static JSBool JSAPI_PROPERTYSET(%s, JSContext *cx, JSObject *obj, jsval *vp)\n", + webidl_node_gettext(ident_node)); + fprintf(binding->outfile, + "{\n" + " return JS_FALSE;\n" + "}\n\n"); + } + + /* property getter */ + return output_property_getter(binding, node, webidl_node_gettext(ident_node)); } /* callback to emit implements property bodys */ -- cgit v1.2.3