summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRober Carr <carrr@rpi.edu>2009-02-10 23:34:04 +0000
committerColin Walters <walters@src.gnome.org>2009-02-10 23:34:04 +0000
commit049dc259e7f2c5f71eec63fb42a5cd5ec70d7be3 (patch)
treecc9141b7375d869497ad7e8e0e3c007d54ae8844
parent328524ab5212d0632a8b3405d6e4375db6aba086 (diff)
downloadgobject-introspection-049dc259e7f2c5f71eec63fb42a5cd5ec70d7be3.tar.gz
Bug 569633 – Typelib compiler fails with vararg callbacks
2009-02-10 Rober Carr <carrr@rpi.edu> Bug 569633 – Typelib compiler fails with vararg callbacks * girepository/girparser.c: Also filter out callback functions which take vararg arguments. svn path=/trunk/; revision=1095
-rw-r--r--ChangeLog7
-rw-r--r--girepository/girparser.c100
-rw-r--r--tests/scanner/foo-1.0-expected.gir53
-rw-r--r--tests/scanner/foo.h6
4 files changed, 155 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 380b6b09..d12f5e6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-02-10 Rober Carr <carrr@rpi.edu>
+
+ Bug 569633 – Typelib compiler fails with vararg callbacks
+
+ * girepository/girparser.c: Also filter out callback functions
+ which take vararg arguments.
+
2009-02-10 Xan Lopez <xan@gnome.org>
Bug 570903 - Add information about -I flag to scanner manpage
diff --git a/girepository/girparser.c b/girepository/girparser.c
index eb3c11d3..b376234d 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -3040,18 +3040,20 @@ cleanup (GMarkupParseContext *context,
}
static GList *
-post_filter_varargs_functions (GList *list)
+post_filter_toplevel_varargs_functions (GList *list,
+ GList **varargs_callbacks_out)
{
GList *iter;
-
+ GList *varargs_callbacks = *varargs_callbacks_out;
+
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)
@@ -3059,7 +3061,76 @@ post_filter_varargs_functions (GList *list)
list = g_list_delete_link (list, link);
}
}
+ if (node->type == G_IR_NODE_CALLBACK)
+ {
+ if (((GIrNodeFunction*)node)->is_varargs)
+ {
+ varargs_callbacks = g_list_append (varargs_callbacks,
+ node);
+ list = g_list_delete_link (list, link);
+ }
+ }
+ }
+
+ *varargs_callbacks_out = varargs_callbacks;
+
+ return list;
+}
+
+static GList *
+post_filter_varargs_functions (GList *list, GList ** varargs_callbacks_out)
+{
+ GList *iter;
+ GList *varargs_callbacks;
+
+ list = post_filter_toplevel_varargs_functions (list, varargs_callbacks_out);
+
+ varargs_callbacks = *varargs_callbacks_out;
+
+ iter = list;
+ while (iter)
+ {
+ GList *link = iter;
+ GIrNode *node = iter->data;
+
+ iter = iter->next;
+
+ if (node->type == G_IR_NODE_FUNCTION)
+ {
+ GList *param;
+ gboolean function_done = FALSE;
+
+ for (param = ((GIrNodeFunction *)node)->parameters;
+ param;
+ param = param->next)
+ {
+ GIrNodeParam *node = (GIrNodeParam *)param->data;
+
+ if (function_done)
+ break;
+
+ if (node->type->is_interface)
+ {
+ GList *callback;
+ for (callback = varargs_callbacks;
+ callback;
+ callback = callback->next)
+ {
+ if (!strcmp (node->type->interface,
+ ((GIrNode *)varargs_callbacks->data)->name))
+ {
+ list = g_list_delete_link (list, link);
+ function_done = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
}
+
+ *varargs_callbacks_out = varargs_callbacks;
+
return list;
}
@@ -3067,37 +3138,44 @@ static void
post_filter (GIrModule *module)
{
GList *iter;
-
- module->entries = post_filter_varargs_functions (module->entries);
+ GList *varargs_callbacks = NULL;
+
+ module->entries = post_filter_varargs_functions (module->entries,
+ &varargs_callbacks);
iter = module->entries;
while (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);
+ iface->members = post_filter_varargs_functions (iface->members,
+ &varargs_callbacks);
}
else if (node->type == G_IR_NODE_BOXED)
{
GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
- boxed->members = post_filter_varargs_functions (boxed->members);
+ boxed->members = post_filter_varargs_functions (boxed->members,
+ &varargs_callbacks);
}
else if (node->type == G_IR_NODE_STRUCT)
{
GIrNodeStruct *iface = (GIrNodeStruct*)node;
- iface->members = post_filter_varargs_functions (iface->members);
+ iface->members = post_filter_varargs_functions (iface->members,
+ &varargs_callbacks);
}
else if (node->type == G_IR_NODE_UNION)
{
GIrNodeUnion *iface = (GIrNodeUnion*)node;
- iface->members = post_filter_varargs_functions (iface->members);
+ iface->members = post_filter_varargs_functions (iface->members,
+ &varargs_callbacks);
}
}
+ g_list_free (varargs_callbacks);
}
/**
diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir
index 7bc20095..a76fa4ee 100644
--- a/tests/scanner/foo-1.0-expected.gir
+++ b/tests/scanner/foo-1.0-expected.gir
@@ -640,6 +640,59 @@ and/or use gtk-doc annotations. -->
</parameter>
</parameters>
</function>
+ <callback name="VarargsCallback" c:type="FooVarargsCallback">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="param" transfer-ownership="none">
+ <type name="utf8" c:type="char*"/>
+ </parameter>
+ <parameter transfer-ownership="none">
+ <varargs>
+ </varargs>
+ </parameter>
+ </parameters>
+ </callback>
+ <function name="test_varargs_callback"
+ c:identifier="foo_test_varargs_callback">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="i" transfer-ownership="none">
+ <type name="int" c:type="gint"/>
+ </parameter>
+ <parameter name="callback" transfer-ownership="none">
+ <type name="VarargsCallback" c:type="FooVarargsCallback"/>
+ </parameter>
+ </parameters>
+ </function>
+ <function name="test_varargs_callback2"
+ c:identifier="foo_test_varargs_callback2">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="callback" transfer-ownership="none">
+ <type name="VarargsCallback" c:type="FooVarargsCallback"/>
+ </parameter>
+ </parameters>
+ </function>
+ <function name="test_varargs_callback3"
+ c:identifier="foo_test_varargs_callback3">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="callback" transfer-ownership="none">
+ <type name="VarargsCallback" c:type="FooVarargsCallback"/>
+ </parameter>
+ <parameter name="callback2" transfer-ownership="none">
+ <type name="VarargsCallback" c:type="FooVarargsCallback"/>
+ </parameter>
+ </parameters>
+ </function>
<enumeration name="Error"
glib:type-name="FooError"
glib:get-type="foo_error_get_type"
diff --git a/tests/scanner/foo.h b/tests/scanner/foo.h
index e866bbea..060b5d55 100644
--- a/tests/scanner/foo.h
+++ b/tests/scanner/foo.h
@@ -303,6 +303,12 @@ const FooStruct * foo_test_const_struct_retval (void);
void foo_test_const_char_param (const char * param);
void foo_test_const_struct_param (const FooStruct * param);
+typedef void (*FooVarargsCallback) (const char * param, ...);
+void foo_test_varargs_callback (gint i, FooVarargsCallback callback);
+void foo_test_varargs_callback2 (FooVarargsCallback callback);
+void foo_test_varargs_callback3 (FooVarargsCallback callback,
+ FooVarargsCallback callback2);
+
typedef enum {
FOO_ERROR_GOOD,
FOO_ERROR_BAD,