gobject-introspection r637 - in trunk: girepository giscanner tests/scanner



Author: walters
Date: Mon Sep 29 19:03:44 2008
New Revision: 637
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=637&view=rev

Log:
Rework to use recursive XML


Modified:
   trunk/girepository/girparser.c
   trunk/giscanner/ast.py
   trunk/giscanner/girparser.py
   trunk/giscanner/girwriter.py
   trunk/giscanner/transformer.py
   trunk/tests/scanner/annotation-expected.gir

Modified: trunk/girepository/girparser.c
==============================================================================
--- trunk/girepository/girparser.c	(original)
+++ trunk/girepository/girparser.c	Mon Sep 29 19:03:44 2008
@@ -59,7 +59,7 @@
   STATE_CLASS_CONSTANT, 
   STATE_INTERFACE_CONSTANT,
   STATE_ALIAS,
-  STATE_TYPE,
+  STATE_TYPE
 } ParseState;
 
 typedef struct _ParseContext ParseContext;
@@ -79,6 +79,8 @@
   GIrModule *current_module;
   GIrNode *current_node;
   GIrNode *current_typed;
+  GList *type_stack;
+  GList *type_parameters;
   int type_depth;
 };
 
@@ -347,25 +349,6 @@
 	  type->is_pointer = TRUE;
 	  str += strlen ("SList");
 	}
-      
-      if (*str == '<')
-	{
-	  (str)++;
-	  char *rest;
-
-	  type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
-	  if (type->parameter_type1 == NULL)
-	    goto error;
-	  str = rest;
-	  
-	  if (str[0] != '>')
-	    goto error;
-	  (str)++;
-	}
-      else
-	{
-	  type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
-	}
     }
   else if (g_str_has_prefix (str, "GLib.HashTable"))
     {
@@ -375,35 +358,6 @@
       type->is_ghashtable = TRUE;
       type->is_pointer = TRUE;
       str += strlen ("HashTable");
-      
-      if (*str == '<')
-	{
-	  char *rest;
-	  (str)++;
-      
-	  type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
-	  if (type->parameter_type1 == NULL)
-	    goto error;
-	  str = rest;
-      
-	  if (str[0] != ',')
-	    goto error;
-	  (str)++;
-	  
-	  type->parameter_type2 = parse_type_internal (str, &rest, in_glib);
-	  if (type->parameter_type2 == NULL)
-	    goto error;
-	  str = rest;
-      
-	  if ((str)[0] != '>')
-	    goto error;
-	  (str)++;
-	}
-      else
-	{
-	  type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
-	  type->parameter_type2 = parse_type_internal ("any", NULL, in_glib);
-	}
     }
   else if (g_str_has_prefix (str, "GLib.Error"))
     {
@@ -444,57 +398,6 @@
       type->interface = g_strndup (start, str - start);
     }
   
-  if (g_str_has_prefix (str, "["))
-    {
-      GIrNodeType *array;
-      int i;
-
-      array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
-
-      array->tag = GI_TYPE_TAG_ARRAY;
-      array->is_pointer = TRUE;
-      array->is_array = TRUE;
-      
-      array->parameter_type1 = type;
-
-      array->zero_terminated = FALSE;
-      array->has_length = FALSE;
-      array->length = 0;
-
-      if (!g_str_has_prefix (str, "[]"))
-	{
-	  gchar *end, *tmp, **opts;
-	  
-	  end = strchr (str, ']');
-	  tmp = g_strndup (str + 1, (end - str) - 1); 
-	  opts = g_strsplit (tmp, ",", 0);
-
-	  for (i = 0; opts[i]; i++)
-	    {
-	      gchar **vals;
-	      
-	      vals = g_strsplit (opts[i], "=", 0);
-
-	      if (strcmp (vals[0], "zero-terminated") == 0)
-		array->zero_terminated = (strcmp (vals[1], "1") == 0);
-	      else if (strcmp (vals[0], "length") == 0)
-		{
-		  array->has_length = TRUE;
-		  array->length = atoi (vals[1]);
-		}
-
-	      g_strfreev (vals);
-	    }
-
-	  g_free (tmp);
-	  g_strfreev (opts);
-
-	  str = end;
-	}
-	      
-      type = array;
-    }
-
   if (next)
     *next = (char*)str;
   g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
@@ -1506,14 +1409,20 @@
 {
   const gchar *name;
   const gchar *ctype;
-  gboolean is_pointer;
+  gboolean is_array;
   GIrNodeType *typenode;
 
-  if (strcmp (element_name, "type") != 0)
+  is_array = strcmp (element_name, "array") == 0;
+
+  if (!(is_array || (strcmp (element_name, "type") == 0)))
     return FALSE;
 
-  if (ctx->state == STATE_TYPE)
-    ctx->type_depth++;
+  if (ctx->state == STATE_TYPE) 
+    {
+      ctx->type_depth++;
+      ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
+      ctx->type_parameters = NULL;
+    } 
   else if (ctx->state == STATE_FUNCTION_PARAMETER ||
 	   ctx->state == STATE_FUNCTION_RETURN || 
 	   ctx->state == STATE_STRUCT_FIELD ||
@@ -1530,12 +1439,10 @@
     {
       state_switch (ctx, STATE_TYPE);
       ctx->type_depth = 1;
+      ctx->type_stack = NULL;
+      ctx->type_parameters = NULL;
     }
 
-  /* FIXME handle recursive types */
-  if (ctx->type_depth > 1)
-    return TRUE;
-
   if (!ctx->current_typed)
     {
       g_set_error (error,
@@ -1544,22 +1451,69 @@
 		   "The element <type> is invalid here");
       return FALSE;
     }
-  
-  name = find_attribute ("name", attribute_names, attribute_values);
 
-  if (name == NULL)
-    MISSING_ATTRIBUTE (context, error, element_name, "name");
+  if (is_array) 
+    {
+      const char *zero;
+      const char *len;
+      int i;
+
+      typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
 
-  ctype = find_attribute ("c:type", attribute_names, attribute_values);
-  if (ctype != NULL && strchr (ctype, '*'))
-    is_pointer = TRUE;
+      typenode->tag = GI_TYPE_TAG_ARRAY;
+      typenode->is_pointer = TRUE;
+      typenode->is_array = TRUE;
+      
+      zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
+      len = find_attribute ("length", attribute_names, attribute_values);
+
+      typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
+      typenode->has_length = len != NULL;
+      typenode->length = typenode->has_length ? atoi (len) : -1;
+    }
   else
-    is_pointer = FALSE;
+    {
+      gboolean is_pointer;
+      name = find_attribute ("name", attribute_names, attribute_values);
+
+      if (name == NULL)
+	MISSING_ATTRIBUTE (context, error, element_name, "name");
+      
+      ctype = find_attribute ("c:type", attribute_names, attribute_values);
+      if (ctype != NULL && strchr (ctype, '*'))
+	is_pointer = TRUE;
+      else
+	is_pointer = FALSE;
+
+      typenode = parse_type (ctx, name);
+
+      if (is_pointer)
+	typenode->is_pointer = is_pointer;
+    }
+
+  ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
+  
+  return TRUE;
+}
+
+static void
+end_type_top (ParseContext *ctx)
+{
+  GIrNodeType *typenode = (GIrNodeType*)ctx->type_parameters->data;
+
+  /* Default to pointer for unspecified containers */
+  if (typenode->tag == GI_TYPE_TAG_ARRAY ||
+      typenode->tag == GI_TYPE_TAG_GLIST ||
+      typenode->tag == GI_TYPE_TAG_GSLIST)
+    {
+      typenode->parameter_type1 = parse_type (ctx, "any");
+    }
+  else if (typenode->tag == GI_TYPE_TAG_GHASH)
+    {
+      typenode->parameter_type1 = parse_type (ctx, "any");
+      typenode->parameter_type2 = parse_type (ctx, "any");
+    }
 
-  typenode = parse_type (ctx, name);
-  if (is_pointer)
-    typenode->is_pointer = is_pointer;
-	
   switch (ctx->current_typed->type)
     {
     case G_IR_NODE_PARAM:
@@ -1590,10 +1544,61 @@
       g_printerr("current node is %d\n", ctx->current_node->type);
       g_assert_not_reached ();
     }
+  g_list_free (ctx->type_parameters);
+  
+  ctx->type_depth = 0;
+  ctx->type_parameters = NULL;
+  ctx->current_typed = NULL;
+}
+
+static void
+end_type_recurse (ParseContext *ctx)
+{
+  GList *types;
+  GIrNodeType *parent;
 
+  parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
 
-  ctx->current_typed = NULL;
-  return TRUE;
+  if (parent->tag == GI_TYPE_TAG_ARRAY ||
+      parent->tag == GI_TYPE_TAG_GLIST ||
+      parent->tag == GI_TYPE_TAG_GSLIST)
+    {
+      if (ctx->type_parameters == NULL)
+	parent->parameter_type1 = parse_type (ctx, "pointer");
+      else
+	parent->parameter_type1 = (GIrNodeType*)ctx->type_parameters->data;
+    }
+  else if (parent->tag == GI_TYPE_TAG_GHASH)
+    {
+      if (ctx->type_parameters == NULL)
+	{
+	  parent->parameter_type1 = parse_type (ctx, "pointer");
+	  parent->parameter_type2 = parse_type (ctx, "pointer");
+	}
+      else
+	{
+	  parent->parameter_type1 = (GIrNodeType*) ctx->type_parameters->data;
+	  parent->parameter_type2 = (GIrNodeType*) ctx->type_parameters->next->data;
+	}
+    }
+  g_list_free (ctx->type_parameters);
+  ctx->type_parameters = (GList *)ctx->type_stack->data;
+  ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
+}
+
+static void
+end_type (ParseContext *ctx)
+{
+  if (ctx->type_depth == 1)
+    {
+      end_type_top (ctx);
+      state_switch (ctx, ctx->prev_state);
+    }
+  else
+    {
+      end_type_recurse (ctx);
+      ctx->type_depth--;
+    }
 }
 
 static gboolean
@@ -2078,6 +2083,10 @@
 	  state_switch (ctx, STATE_ALIAS);
 	  goto out;
 	}
+      if (start_type (context, element_name,
+		      attribute_names, attribute_values,
+		      ctx, error))
+	goto out;
       break;
     case 'b':
       if (start_enum (context, element_name, 
@@ -2631,12 +2640,9 @@
 	}
       break;
     case STATE_TYPE:
-      if (strcmp ("type", element_name) == 0)
+      if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0))
 	{
-	  if (ctx->type_depth == 1)
-	    state_switch (ctx, ctx->prev_state);
-	  else
-	    ctx->type_depth -= 1;
+	  end_type (ctx);
 	  break;
 	}
     default:

Modified: trunk/giscanner/ast.py
==============================================================================
--- trunk/giscanner/ast.py	(original)
+++ trunk/giscanner/ast.py	Mon Sep 29 19:03:44 2008
@@ -170,8 +170,8 @@
 
 class Array(Type):
 
-    def __init__(self, name, ctype, element_type):
-        Type.__init__(self, name, ctype)
+    def __init__(self, ctype, element_type):
+        Type.__init__(self, '<carray>', ctype)
         self.element_type = element_type
         self.zeroterminated = True
         self.length_param_index = -1

Modified: trunk/giscanner/girparser.py
==============================================================================
--- trunk/giscanner/girparser.py	(original)
+++ trunk/giscanner/girparser.py	Mon Sep 29 19:03:44 2008
@@ -21,7 +21,7 @@
 from xml.etree.cElementTree import parse
 
 from .ast import (Alias, Callback, Function, Parameter, Return, Union,
-                  Struct, Type)
+                  Struct, Type, Array)
 from .glibast import (GLibEnum, GLibEnumMember, GLibFlags,
                       GLibInterface, GLibObject, GLibBoxedStruct,
                       GLibBoxedUnion, GLibBoxedOther)
@@ -128,7 +128,10 @@
 
     def _parse_function(self, node, klass):
         name = node.attrib['name']
-        retval = Return(self._parse_type(node.find(_corens('return-value'))))
+        returnnode = node.find(_corens('return-value'))
+        if not returnnode:
+            raise ValueError('node %r has no return-value' % (name, ))
+        retval = Return(self._parse_type(returnnode))
         parameters = []
         for paramnode in node.findall('parameter'):
             parameters.append(Parameter(paramnode.attrib['name'],
@@ -164,10 +167,15 @@
 
     def _parse_type(self, node):
         typenode = node.find(_corens('type'))
-        if node is None:
-            raise ValueError("failed to find type")
-        return Type(typenode.attrib['name'],
-                    typenode.attrib[_cns('type')])
+        if typenode is not None:
+            return Type(typenode.attrib['name'],
+                        typenode.attrib.get(_cns('type')))
+        typenode = node.find(_corens('array'))
+        if typenode is not None:
+            return Array(typenode.attrib[_cns('type')],
+                         self._parse_type(typenode))
+        raise ValueError("Couldn't parse type of node %r; children=%r",
+                         node, list(node))
 
     def _parse_boxed(self, node):
         obj = GLibBoxedOther(node.attrib[_glibns('name')],

Modified: trunk/giscanner/girwriter.py
==============================================================================
--- trunk/giscanner/girwriter.py	(original)
+++ trunk/giscanner/girwriter.py	Mon Sep 29 19:03:44 2008
@@ -143,21 +143,6 @@
     def _type_to_string(self, ntype):
         if isinstance(ntype, basestring):
             return ntype
-        if isinstance(ntype, List) and ntype.element_type:
-            return '%s<%s>' % (ntype.name,
-                               self._type_to_string(ntype.element_type))
-        if isinstance(ntype, Map) and ntype.key_type:
-            return '%s<%s,%s>' % (ntype.name,
-                                  self._type_to_string(ntype.key_type),
-                                  self._type_to_string(ntype.value_type))
-        if isinstance(ntype, Array):
-            options = []
-            if not ntype.zeroterminated:
-                options.append('zero-terminated=0')
-            if ntype.length_param_index >= 0:
-                options.append('length=%d' % (ntype.length_param_index, ))
-            return self._type_to_string(ntype.element_type) + \
-                '[%s]' % (','.join(options), )
         return ntype.name
 
     def _write_type(self, ntype, relation=None):
@@ -167,15 +152,33 @@
         else:
             typename = ntype.name
             type_cname = ntype.ctype
+        if isinstance(ntype, Array):
+            attrs = []
+            if not ntype.zeroterminated:
+                attrs.append(('zero-terminated', '0'))
+            if ntype.length_param_index >= 0:
+                attrs.append(('length', '%d' % (ntype.length_param_index, )))
+            attrs.append(('c:type', ntype.ctype))
+            with self.tagcontext('array', attrs):
+                self._write_type(ntype.element_type)
+            return
         attrs = [('name', self._type_to_string(ntype))]
-        if relation:
-            attrs.append(('relation', relation))
         # FIXME: figure out if type references a basic type
         #        or a boxed/class/interface etc. and skip
         #        writing the ctype if the latter.
         if type_cname is not None:
             attrs.append(('c:type', type_cname))
-            self.write_tag('type', attrs)
+        if isinstance(ntype, List) and ntype.element_type:
+            with self.tagcontext('type', attrs):
+                self._write_type(ntype.element_type)
+            return
+        if isinstance(ntype, Map) and ntype.key_type:
+            with self.tagcontext('type', attrs):
+                self._write_type(ntype.key_type)
+                self._write_type(ntype.value_type)
+            return
+        # Not a special type, just write it out
+        self.write_tag('type', attrs)
 
     def _write_enum(self, enum):
         attrs = [('name', enum.name),

Modified: trunk/giscanner/transformer.py
==============================================================================
--- trunk/giscanner/transformer.py	(original)
+++ trunk/giscanner/transformer.py	Mon Sep 29 19:03:44 2008
@@ -347,7 +347,7 @@
             if 'array' in options:
                 options.remove('array')
             derefed = ctype[:-1] # strip the *
-            return Array(None, ctype,
+            return Array(ctype,
                          self._parse_and_resolve_ctype(derefed))
         resolved_type_name = self._parse_and_resolve_ctype(ctype)
         return Type(resolved_type_name, ctype)

Modified: trunk/tests/scanner/annotation-expected.gir
==============================================================================
--- trunk/tests/scanner/annotation-expected.gir	(original)
+++ trunk/tests/scanner/annotation-expected.gir	Mon Sep 29 19:03:44 2008
@@ -151,7 +151,9 @@
     <function name="object_get_strings"
               c:identifier="annotation_object_get_strings">
       <return-value transfer-ownership="1">
-        <type name="GLib.List&lt;utf8&gt;" c:type="GList*"/>
+        <type name="GLib.List" c:type="GList*">
+          <type name="utf8"/>
+        </type>
       </return-value>
       <parameters>
         <parameter name="object">
@@ -162,7 +164,9 @@
     <function name="object_get_objects"
               c:identifier="annotation_object_get_objects">
       <return-value transfer-ownership="1">
-        <type name="GLib.SList&lt;Object&gt;" c:type="GSList*"/>
+        <type name="GLib.SList" c:type="GSList*">
+          <type name="Object"/>
+        </type>
       </return-value>
       <parameters>
         <parameter name="object">
@@ -180,7 +184,9 @@
           <type name="Object" c:type="AnnotationObject*"/>
         </parameter>
         <parameter name="bytes">
-          <type name="uint8[]" c:type="guchar*"/>
+          <array c:type="guchar*">
+            <type name="uint8"/>
+          </array>
         </parameter>
       </parameters>
     </function>
@@ -194,7 +200,9 @@
           <type name="Object" c:type="AnnotationObject*"/>
         </parameter>
         <parameter name="nums">
-          <type name="int[]" c:type="int*"/>
+          <array c:type="int*">
+            <type name="int"/>
+          </array>
         </parameter>
       </parameters>
     </function>
@@ -208,7 +216,9 @@
           <type name="Object" c:type="AnnotationObject*"/>
         </parameter>
         <parameter name="nums">
-          <type name="int[length=2]" c:type="int*"/>
+          <array length="2" c:type="int*">
+            <type name="int"/>
+          </array>
         </parameter>
         <parameter name="n_nums">
           <type name="int" c:type="int"/>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]