diff options
author | Colin Walters <walters@src.gnome.org> | 2008-10-02 14:07:38 +0000 |
---|---|---|
committer | Colin Walters <walters@src.gnome.org> | 2008-10-02 14:07:38 +0000 |
commit | b8b1ab1162b492fcf5176678201ce191b740c3f8 (patch) | |
tree | 8ddaf13e9d4f1f41b1511f642b0b1c4e9cca3fce | |
parent | 9d03f102950cfb1235db5efe81e399e7c14a30af (diff) | |
download | gobject-introspection-b8b1ab1162b492fcf5176678201ce191b740c3f8.tar.gz |
Merge branch 'bug552393-varargs'
svn path=/trunk/; revision=643
-rw-r--r-- | girepository/girnode.h | 2 | ||||
-rw-r--r-- | girepository/girparser.c | 182 | ||||
-rw-r--r-- | giscanner/ast.py | 6 | ||||
-rw-r--r-- | giscanner/girwriter.py | 6 | ||||
-rw-r--r-- | giscanner/scannerparser.y | 16 | ||||
-rw-r--r-- | giscanner/sourcescanner.h | 1 | ||||
-rw-r--r-- | giscanner/sourcescanner.py | 4 | ||||
-rw-r--r-- | giscanner/transformer.py | 13 | ||||
-rw-r--r-- | tests/scanner/foo-expected.gir | 17 | ||||
-rw-r--r-- | tests/scanner/foo.c | 6 | ||||
-rw-r--r-- | tests/scanner/foo.h | 2 |
11 files changed, 204 insertions, 51 deletions
diff --git a/girepository/girnode.h b/girepository/girnode.h index 67027aec..eba8c6b9 100644 --- a/girepository/girnode.h +++ b/girepository/girnode.h @@ -85,6 +85,7 @@ struct _GIrNodeFunction GIrNode node; gboolean deprecated; + gboolean is_varargs; /* Not in typelib yet */ gboolean is_method; gboolean is_setter; @@ -183,6 +184,7 @@ struct _GIrNodeVFunc { GIrNode node; + gboolean is_varargs; /* Not in typelib yet */ gboolean must_chain_up; gboolean must_be_implemented; gboolean must_not_be_implemented; diff --git a/girepository/girparser.c b/girepository/girparser.c index 52f2294c..1644f5d6 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -79,6 +79,7 @@ struct _ParseContext GIrModule *current_module; GIrNode *current_node; GIrNode *current_typed; + gboolean is_varargs; GList *type_stack; GList *type_parameters; int type_depth; @@ -1420,11 +1421,13 @@ start_type (GMarkupParseContext *context, const gchar *name; const gchar *ctype; gboolean is_array; + gboolean is_varargs; GIrNodeType *typenode; is_array = strcmp (element_name, "array") == 0; + is_varargs = strcmp (element_name, "varargs") == 0; - if (!(is_array || (strcmp (element_name, "type") == 0))) + if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0))) return FALSE; if (ctx->state == STATE_TYPE) @@ -1449,6 +1452,25 @@ start_type (GMarkupParseContext *context, { state_switch (ctx, STATE_TYPE); ctx->type_depth = 1; + if (is_varargs) + { + switch (ctx->current_node->type) + { + case G_IR_NODE_FUNCTION: + case G_IR_NODE_CALLBACK: + { + GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node; + func->is_varargs = TRUE; + } + break; + case G_IR_NODE_VFUNC: + { + GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node; + vfunc->is_varargs = TRUE; + } + break; + } + } ctx->type_stack = NULL; ctx->type_parameters = NULL; } @@ -1462,6 +1484,9 @@ start_type (GMarkupParseContext *context, return FALSE; } + if (is_varargs) + return TRUE; + if (is_array) { const char *zero; @@ -1509,7 +1534,12 @@ start_type (GMarkupParseContext *context, static void end_type_top (ParseContext *ctx) { - GIrNodeType *typenode = (GIrNodeType*)ctx->type_parameters->data; + GIrNodeType *typenode; + + if (!ctx->type_parameters) + goto out; + + typenode = (GIrNodeType*)ctx->type_parameters->data; /* Default to pointer for unspecified containers */ if (typenode->tag == GI_TYPE_TAG_ARRAY || @@ -1559,7 +1589,8 @@ end_type_top (ParseContext *ctx) g_assert_not_reached (); } g_list_free (ctx->type_parameters); - + + out: ctx->type_depth = 0; ctx->type_parameters = NULL; ctx->current_typed = NULL; @@ -2322,7 +2353,11 @@ start_element_handler (GMarkupParseContext *context, if (start_vfunc (context, element_name, attribute_names, attribute_values, ctx, error)) - goto out; + goto out; + if (start_type (context, element_name, + attribute_names, attribute_values, + ctx, error)) + goto out; break; } @@ -2464,36 +2499,43 @@ end_element_handler (GMarkupParseContext *context, break; case STATE_FUNCTION: - if (ctx->current_node == g_list_last (ctx->current_module->entries)->data) - { - ctx->current_node = NULL; - state_switch (ctx, STATE_NAMESPACE); - } - else - { - ctx->current_node = g_list_last (ctx->current_module->entries)->data; - if (ctx->current_node->type == G_IR_NODE_INTERFACE) - state_switch (ctx, STATE_INTERFACE); - else if (ctx->current_node->type == G_IR_NODE_OBJECT) - state_switch (ctx, STATE_CLASS); - else if (ctx->current_node->type == G_IR_NODE_BOXED) - state_switch (ctx, STATE_BOXED); - else if (ctx->current_node->type == G_IR_NODE_STRUCT) - state_switch (ctx, STATE_STRUCT); - else if (ctx->current_node->type == G_IR_NODE_UNION) - state_switch (ctx, STATE_UNION); - else - { - int line_number, char_number; - g_markup_parse_context_get_position (context, &line_number, &char_number); - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_INVALID_CONTENT, - "Unexpected end tag '%s' on line %d char %d", - element_name, - line_number, char_number); - } - } + { + gboolean current_is_toplevel; + GList *last = g_list_last (ctx->current_module->entries); + + current_is_toplevel = ctx->current_node == last->data; + + if (current_is_toplevel) + { + ctx->current_node = NULL; + state_switch (ctx, STATE_NAMESPACE); + } + else + { + ctx->current_node = g_list_last (ctx->current_module->entries)->data; + if (ctx->current_node->type == G_IR_NODE_INTERFACE) + state_switch (ctx, STATE_INTERFACE); + else if (ctx->current_node->type == G_IR_NODE_OBJECT) + state_switch (ctx, STATE_CLASS); + else if (ctx->current_node->type == G_IR_NODE_BOXED) + state_switch (ctx, STATE_BOXED); + else if (ctx->current_node->type == G_IR_NODE_STRUCT) + state_switch (ctx, STATE_STRUCT); + else if (ctx->current_node->type == G_IR_NODE_UNION) + state_switch (ctx, STATE_UNION); + else + { + int line_number, char_number; + g_markup_parse_context_get_position (context, &line_number, &char_number); + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Unexpected end tag '%s' on line %d char %d", + element_name, + line_number, char_number); + } + } + } break; case STATE_CLASS_FIELD: @@ -2654,7 +2696,8 @@ end_element_handler (GMarkupParseContext *context, } break; case STATE_TYPE: - if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0)) + if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) || + (strcmp ("varargs", element_name) == 0)) { end_type (ctx); break; @@ -2700,6 +2743,69 @@ static GMarkupParser parser = cleanup }; +static GList * +post_filter_varargs_functions (GList *list) +{ + GList *iter; + + iter = list; + while (iter) + { + GList *link = iter; + GIrNode *node = iter->data; + + iter = iter->next; + + if (node->type == G_IR_NODE_FUNCTION) + { + if (((GIrNodeFunction*)node)->is_varargs) + { + g_printerr ("deleting varargs function\n"); + list = g_list_delete_link (list, link); + } + } + } + return list; +} + +static void +post_filter (GIrModule *module) +{ + GList *iter; + + module->entries = post_filter_varargs_functions (module->entries); + iter = module->entries; + while (iter) + { + GList *link = iter; + GIrNode *node = iter->data; + + iter = iter->next; + + if (node->type == G_IR_NODE_OBJECT || + node->type == G_IR_NODE_INTERFACE) + { + GIrNodeInterface *iface = (GIrNodeInterface*)node; + iface->members = post_filter_varargs_functions (iface->members); + } + else if (node->type == G_IR_NODE_BOXED) + { + GIrNodeBoxed *boxed = (GIrNodeBoxed*)node; + boxed->members = post_filter_varargs_functions (boxed->members); + } + else if (node->type == G_IR_NODE_STRUCT) + { + GIrNodeStruct *iface = (GIrNodeStruct*)node; + iface->members = post_filter_varargs_functions (iface->members); + } + else if (node->type == G_IR_NODE_UNION) + { + GIrNodeUnion *iface = (GIrNodeUnion*)node; + iface->members = post_filter_varargs_functions (iface->members); + } + } +} + GList * g_ir_parse_string (const gchar *namespace, const gchar *const *includes, @@ -2753,6 +2859,7 @@ g_ir_parse_file (const gchar *filename, gchar *buffer; gsize length; GList *modules; + GList *iter; const char *slash; char *namespace; @@ -2779,6 +2886,11 @@ g_ir_parse_file (const gchar *filename, modules = g_ir_parse_string (namespace, includes, buffer, length, error); + for (iter = modules; iter; iter = iter->next) + { + post_filter ((GIrModule*)iter->data); + } + g_free (namespace); g_free (buffer); diff --git a/giscanner/ast.py b/giscanner/ast.py index 7cd4fc6c..6f2e9c2e 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -169,6 +169,12 @@ class Type(Node): self.resolved = False +class Varargs(Type): + + def __init__(self): + Type.__init__(self, '<varargs>') + + class Array(Type): def __init__(self, ctype, element_type): diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index 996da873..fa7c0e57 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -23,7 +23,7 @@ from __future__ import with_statement import os from .ast import (Callback, Class, Enum, Function, Interface, Member, - Array, Struct, Alias, Union, List, Map) + Array, Struct, Alias, Union, List, Map, Varargs) from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags, GLibObject, GLibInterface) from .xmlwriter import XMLWriter @@ -152,6 +152,10 @@ class GIRWriter(XMLWriter): else: typename = ntype.name type_cname = ntype.ctype + if isinstance(ntype, Varargs): + with self.tagcontext('varargs', []): + pass + return if isinstance(ntype, Array): attrs = [] if not ntype.zeroterminated: diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y index dbde3223..53a30a31 100644 --- a/giscanner/scannerparser.y +++ b/giscanner/scannerparser.y @@ -100,7 +100,6 @@ static GHashTable *const_table = NULL; %type <list> enumerator_list %type <list> identifier_list %type <list> init_declarator_list -%type <list> parameter_type_list %type <list> parameter_list %type <list> struct_declaration %type <list> struct_declaration_list @@ -904,7 +903,7 @@ direct_declarator $$ = $1; gi_source_symbol_merge_type ($$, gi_source_array_new ()); } - | direct_declarator '(' parameter_type_list ')' + | direct_declarator '(' parameter_list ')' { GISourceType *func = gi_source_function_new (); // ignore (void) parameter list @@ -958,11 +957,6 @@ type_qualifier_list } ; -parameter_type_list - : parameter_list - | parameter_list ',' ELLIPSIS - ; - parameter_list : parameter_declaration { @@ -990,6 +984,10 @@ parameter_declaration $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID); $$->base_type = $1; } + | ELLIPSIS + { + $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS); + } ; identifier_list @@ -1057,7 +1055,7 @@ direct_abstract_declarator $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID); gi_source_symbol_merge_type ($$, func); } - | '(' parameter_type_list ')' + | '(' parameter_list ')' { GISourceType *func = gi_source_function_new (); // ignore (void) parameter list @@ -1073,7 +1071,7 @@ direct_abstract_declarator $$ = $1; gi_source_symbol_merge_type ($$, func); } - | direct_abstract_declarator '(' parameter_type_list ')' + | direct_abstract_declarator '(' parameter_list ')' { GISourceType *func = gi_source_function_new (); // ignore (void) parameter list diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h index 171a995a..3e2aacda 100644 --- a/giscanner/sourcescanner.h +++ b/giscanner/sourcescanner.h @@ -36,6 +36,7 @@ typedef struct _GISourceDirective GISourceDirective; typedef enum { CSYMBOL_TYPE_INVALID, + CSYMBOL_TYPE_ELLIPSIS, CSYMBOL_TYPE_CONST, CSYMBOL_TYPE_OBJECT, CSYMBOL_TYPE_FUNCTION, diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py index 1030f04b..a4355ca5 100644 --- a/giscanner/sourcescanner.py +++ b/giscanner/sourcescanner.py @@ -25,6 +25,7 @@ import tempfile from . import _giscanner (CSYMBOL_TYPE_INVALID, + CSYMBOL_TYPE_ELLIPSIS, CSYMBOL_TYPE_CONST, CSYMBOL_TYPE_OBJECT, CSYMBOL_TYPE_FUNCTION, @@ -32,7 +33,7 @@ from . import _giscanner CSYMBOL_TYPE_UNION, CSYMBOL_TYPE_ENUM, CSYMBOL_TYPE_TYPEDEF, - CSYMBOL_TYPE_MEMBER) = range(9) + CSYMBOL_TYPE_MEMBER) = range(10) (CTYPE_INVALID, CTYPE_VOID, @@ -72,6 +73,7 @@ FUNCTION_INLINE = 1 << 1 def symbol_type_name(symbol_type): return { CSYMBOL_TYPE_INVALID: 'invalid', + CSYMBOL_TYPE_ELLIPSIS: 'ellipsis', CSYMBOL_TYPE_CONST: 'const', CSYMBOL_TYPE_OBJECT: 'object', CSYMBOL_TYPE_FUNCTION: 'function', diff --git a/giscanner/transformer.py b/giscanner/transformer.py index d560474d..f8e09d13 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -23,8 +23,8 @@ import os from giscanner.ast import (Callback, Enum, Function, Namespace, Member, Parameter, Return, Array, Struct, Field, Type, Alias, Interface, Class, Node, Union, - List, Map, type_name_from_ctype, type_names, - default_array_types) + List, Map, Varargs, type_name_from_ctype, + type_names, default_array_types) from giscanner.config import DATADIR from .glibast import GLibBoxed from giscanner.sourcescanner import ( @@ -33,7 +33,7 @@ from giscanner.sourcescanner import ( CTYPE_VOID, CTYPE_ENUM, CTYPE_FUNCTION, CTYPE_STRUCT, CSYMBOL_TYPE_FUNCTION, CSYMBOL_TYPE_TYPEDEF, CSYMBOL_TYPE_STRUCT, CSYMBOL_TYPE_ENUM, CSYMBOL_TYPE_UNION, CSYMBOL_TYPE_OBJECT, - CSYMBOL_TYPE_MEMBER) + CSYMBOL_TYPE_MEMBER, CSYMBOL_TYPE_ELLIPSIS) from .odict import odict from .utils import strip_common_prefix, to_underscores @@ -318,7 +318,7 @@ class Transformer(object): def _create_type(self, source_type, options=[]): ctype = self._create_source_type(source_type) if ctype == 'va_list': - raise SkipError + raise SkipError() # FIXME: FILE* should not be skipped, it should be handled # properly instead elif ctype == 'FILE*': @@ -353,7 +353,10 @@ class Transformer(object): return Type(resolved_type_name, ctype) def _create_parameter(self, symbol, options): - ptype = self._create_type(symbol.base_type, options) + if symbol.type == CSYMBOL_TYPE_ELLIPSIS: + ptype = Varargs() + else: + ptype = self._create_type(symbol.base_type, options) param = Parameter(symbol.ident, ptype) for option in options: if option in ['in-out', 'inout']: diff --git a/tests/scanner/foo-expected.gir b/tests/scanner/foo-expected.gir index 8c6b8b5e..d2fa4b31 100644 --- a/tests/scanner/foo-expected.gir +++ b/tests/scanner/foo-expected.gir @@ -77,6 +77,23 @@ </parameter> </parameters> </method> + <method name="take_all" c:identifier="foo_object_take_all"> + <return-value> + <type name="none" c:type="void"/> + </return-value> + <parameters> + <parameter name="object"> + <type name="Object" c:type="FooObject*"/> + </parameter> + <parameter name="x"> + <type name="int" c:type="int"/> + </parameter> + <parameter> + <varargs> + </varargs> + </parameter> + </parameters> + </method> <method name="with_tdef" c:identifier="foo_object_with_tdef"> <return-value> <type name="none" c:type="void"/> diff --git a/tests/scanner/foo.c b/tests/scanner/foo.c index ef841a33..c65d7289 100644 --- a/tests/scanner/foo.c +++ b/tests/scanner/foo.c @@ -137,6 +137,12 @@ foo_object_external_type (FooObject *object) } +void +foo_object_take_all (FooObject *object, int x, ...) +{ + +} + void foo_do_foo (FooInterface *self) { diff --git a/tests/scanner/foo.h b/tests/scanner/foo.h index 3183c883..2982f9d5 100644 --- a/tests/scanner/foo.h +++ b/tests/scanner/foo.h @@ -53,6 +53,8 @@ UtilityObject* foo_object_external_type (FooObject *object); void foo_object_various (FooObject *object, void *data, GType some_type); +void foo_object_take_all (FooObject *object, int x, ...); + /* A random typedef */ typedef GSList FooList; |