Merge branch 'bug552393-varargs'
authorColin Walters <walters@src.gnome.org>
Thu, 2 Oct 2008 14:07:38 +0000 (14:07 +0000)
committerColin Walters <walters@src.gnome.org>
Thu, 2 Oct 2008 14:07:38 +0000 (14:07 +0000)
svn path=/trunk/; revision=643

girepository/girnode.h
girepository/girparser.c
giscanner/ast.py
giscanner/girwriter.py
giscanner/scannerparser.y
giscanner/sourcescanner.h
giscanner/sourcescanner.py
giscanner/transformer.py
tests/scanner/foo-expected.gir
tests/scanner/foo.c
tests/scanner/foo.h

index 67027ae..eba8c6b 100644 (file)
@@ -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;
index 52f2294..1644f5d 100644 (file)
@@ -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);
index 7cd4fc6..6f2e9c2 100644 (file)
@@ -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):
index 996da87..fa7c0e5 100644 (file)
@@ -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:
index dbde322..53a30a3 100644 (file)
@@ -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
index 171a995..3e2aacd 100644 (file)
@@ -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,
index 1030f04..a4355ca 100644 (file)
@@ -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',
index d560474..f8e09d1 100644 (file)
@@ -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']:
index 8c6b8b5..d2fa4b3 100644 (file)
           </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"/>
index ef841a3..c65d728 100644 (file)
@@ -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)
 {
index 3183c88..2982f9d 100644 (file)
@@ -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;