summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@src.gnome.org>2008-10-02 14:07:38 +0000
committerColin Walters <walters@src.gnome.org>2008-10-02 14:07:38 +0000
commitb8b1ab1162b492fcf5176678201ce191b740c3f8 (patch)
tree8ddaf13e9d4f1f41b1511f642b0b1c4e9cca3fce
parent9d03f102950cfb1235db5efe81e399e7c14a30af (diff)
downloadgobject-introspection-b8b1ab1162b492fcf5176678201ce191b740c3f8.tar.gz
Merge branch 'bug552393-varargs'
svn path=/trunk/; revision=643
-rw-r--r--girepository/girnode.h2
-rw-r--r--girepository/girparser.c182
-rw-r--r--giscanner/ast.py6
-rw-r--r--giscanner/girwriter.py6
-rw-r--r--giscanner/scannerparser.y16
-rw-r--r--giscanner/sourcescanner.h1
-rw-r--r--giscanner/sourcescanner.py4
-rw-r--r--giscanner/transformer.py13
-rw-r--r--tests/scanner/foo-expected.gir17
-rw-r--r--tests/scanner/foo.c6
-rw-r--r--tests/scanner/foo.h2
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;