gobject-introspection r355 - in trunk: . gir girepository giscanner tests/scanner



Author: walters
Date: Wed Aug 13 16:10:09 2008
New Revision: 355
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=355&view=rev

Log:
2008-08-12  Colin Walters  <walters verbum org>

	* giscanner/transformer.py: Record typedefs as <alias> elements.
	  Also attempt to look up types in external namespaces.
	* giscanner/girwriter.py: Write them.
	* giscanner/glibtransformer.py: Rework resolver using real instanceof
	checks.  Resolve interface methods and properties.
	* tests/scanner/foo-object.h: Add a method with typedef.
	* tests/scanner/Foo-expected.gir: Update.
	* girepository/girnode.c: Debug tweaks.
	* girepository/girparser.c: Make a first pass through the XML where we
	record all the aliases.  This lets us resolve them as we go through the
	second pass.
	* gir/Makefile.am: Don't install gobject-2.0.gir; we want that to come
	from gir-repository.




Modified:
   trunk/ChangeLog
   trunk/gir/Makefile.am
   trunk/girepository/girnode.c
   trunk/girepository/girparser.c
   trunk/giscanner/ast.py
   trunk/giscanner/girwriter.py
   trunk/giscanner/glibtransformer.py
   trunk/giscanner/transformer.py
   trunk/tests/scanner/Foo-expected.gir
   trunk/tests/scanner/foo-object.h

Modified: trunk/gir/Makefile.am
==============================================================================
--- trunk/gir/Makefile.am	(original)
+++ trunk/gir/Makefile.am	Wed Aug 13 16:10:09 2008
@@ -1,2 +1,2 @@
-girdir = $(datadir)/gir
-dist_gir_DATA = gobject-2.0.gir
+#girdir = $(datadir)/gir
+#dist_gir_DATA = gobject-2.0.gir

Modified: trunk/girepository/girnode.c
==============================================================================
--- trunk/girepository/girnode.c	(original)
+++ trunk/girepository/girnode.c	Wed Aug 13 16:10:09 2008
@@ -880,7 +880,7 @@
       size = 0;
     }
 
-  g_debug ("node %p type '%s' full size %d", node,
+  g_debug ("node '%s' %p type '%s' full size %d", node->name, node,
 	   g_ir_node_type_to_string (node->type), size);
 
   return size;
@@ -2173,8 +2173,8 @@
       g_assert_not_reached ();
     }
   
-  g_debug ("node %p type '%s', offset %d -> %d, offset2 %d -> %d",
-	   node, g_ir_node_type_to_string (node->type),
+  g_debug ("node '%s' %p type '%s', offset %d -> %d, offset2 %d -> %d",
+	   node->name, node, g_ir_node_type_to_string (node->type),
 	   old_offset, *offset, old_offset2, *offset2);
 
   if (*offset2 - old_offset2 + *offset - old_offset > g_ir_node_get_full_size (node))

Modified: trunk/girepository/girparser.c
==============================================================================
--- trunk/girepository/girparser.c	(original)
+++ trunk/girepository/girparser.c	Wed Aug 13 16:10:09 2008
@@ -53,7 +53,8 @@
   STATE_STRUCT_FIELD,
   STATE_ERRORDOMAIN, 
   STATE_UNION,
-  STATE_CONSTANT
+  STATE_CONSTANT,
+  STATE_ALIAS,  /* 25 */
 } ParseState;
 
 typedef struct _ParseContext ParseContext;
@@ -63,6 +64,7 @@
   ParseState prev_state;
 
   GList *modules;
+  GHashTable *aliases;
 
   GIrModule *current_module;
   GIrNode *current_node;
@@ -123,6 +125,18 @@
   ctx->state = newstate;
 }
 
+static GIrNodeType * parse_type_internal (gchar *str, gchar **rest);
+
+static GIrNodeType *
+create_pointer ()
+{
+  char *pointer = g_strdup ("any");
+  char *pointer_rest;
+  GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest);
+  g_free (pointer);
+  return ret;
+}
+
 static GIrNodeType *
 parse_type_internal (gchar *str, gchar **rest)
 {
@@ -258,6 +272,10 @@
 	    goto error;
 	  (*rest)++;
 	}
+      else
+	{
+	  type->parameter_type1 = create_pointer ();
+	}
     }
   else if (g_str_has_prefix (*rest, "GHashTable"))
     {
@@ -290,6 +308,12 @@
 	    goto error;
 	  (*rest)++;
 	}
+      else
+	{
+	  type->parameter_type1 = create_pointer ();
+	  type->parameter_type2 = create_pointer ();
+	}
+
     }
   else if (g_str_has_prefix (*rest, "GError"))
     {
@@ -396,13 +420,28 @@
   return NULL;
 }
 
+static const char *
+resolve_aliases (ParseContext *ctx, const gchar *type)
+{
+  gpointer orig;
+  gpointer value;
+
+  while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
+    {
+      g_debug ("Resolved: %s => %s", type, value);
+      type = value;
+    }
+  return type;
+}
+
 static GIrNodeType *
-parse_type (const gchar *type)
+parse_type (ParseContext *ctx, const gchar *type)
 {
   gchar *str;
   gchar *rest;
   GIrNodeType *node;
   
+  type = resolve_aliases (ctx, type);
   str = g_strdup (type);
   node = parse_type_internal (str, &rest);
   g_free (str);
@@ -849,6 +888,34 @@
 }
 
 static gboolean
+start_alias (GMarkupParseContext *context,
+	     const gchar         *element_name,
+	     const gchar        **attribute_names,
+	     const gchar        **attribute_values,
+	     ParseContext        *ctx,
+	     GError             **error)
+{
+  const gchar *name;
+  const gchar *target;
+  const gchar *type;
+
+  name = find_attribute ("name", attribute_names, attribute_values);
+  if (name == NULL) {
+    MISSING_ATTRIBUTE (context, error, element_name, "name");
+    return FALSE;
+  }
+
+  target = find_attribute ("target", attribute_names, attribute_values);
+  if (name == NULL) {
+    MISSING_ATTRIBUTE (context, error, element_name, "target");
+    return FALSE;
+  }
+
+  g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target));
+  return TRUE;
+}
+
+static gboolean
 start_enum (GMarkupParseContext *context,
 	     const gchar         *element_name,
 	     const gchar        **attribute_names,
@@ -1075,7 +1142,7 @@
 	  ((GIrNode *)constant)->name = g_strdup (name);
 	  constant->value = g_strdup (value);
 	  
-	  constant->type = parse_type (type);
+	  constant->type = parse_type (ctx, type);
 
 	  if (deprecated && strcmp (deprecated, "1") == 0)
 	    constant->deprecated = TRUE;
@@ -1310,19 +1377,19 @@
       {
 	GIrNodeParam *param;
 	param = (GIrNodeParam *)ctx->current_typed;
-	param->type = parse_type (name);
+	param->type = parse_type (ctx, name);
       }
       break;
     case G_IR_NODE_FIELD:
       {
 	GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
-	field->type = parse_type (name);
+	field->type = parse_type (ctx, name);
       }
       break;
     case G_IR_NODE_PROPERTY:
       {
 	GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
-	property->type = parse_type (name);
+	property->type = parse_type (ctx, name);
       }
       break;
     default:
@@ -1661,7 +1728,7 @@
 	MISSING_ATTRIBUTE (context, error, element_name, "offset");
 	{
 	  ((GIrNodeUnion *)ctx->current_node)->discriminator_type 
-	    = parse_type (type);
+	    = parse_type (ctx, type);
 	  ((GIrNodeUnion *)ctx->current_node)->discriminator_offset 
 	    = atoi (offset);
 	}
@@ -1705,6 +1772,13 @@
 
   switch (element_name[0]) 
     {
+    case 'a':
+      if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0) 
+	{
+	  state_switch (ctx, STATE_ALIAS);
+	  goto out;
+	}
+      break;
     case 'b':
       if (start_enum (context, element_name, 
 		      attribute_names, attribute_values,
@@ -2047,6 +2121,13 @@
         }
       break;
 
+    case STATE_ALIAS:
+      if (require_end_element (context, "alias", element_name, error))
+	{
+	  state_switch (ctx, STATE_NAMESPACE);
+	}
+      break;
+
     case STATE_FUNCTION_RETURN:
       if (strcmp ("type", element_name) == 0)
 	break;
@@ -2262,6 +2343,44 @@
   ctx->current_module = NULL;
 }
 
+static void
+firstpass_start_element_handler (GMarkupParseContext *context,
+				 const gchar         *element_name,
+				 const gchar        **attribute_names,
+				 const gchar        **attribute_values,
+				 gpointer             user_data,
+				 GError             **error)
+{
+  ParseContext *ctx = user_data;
+
+  if (strcmp (element_name, "alias") == 0) 
+    {
+      start_alias (context, element_name, attribute_names, attribute_values,
+		   ctx, error);
+    }
+}
+
+static void
+firstpass_end_element_handler (GMarkupParseContext *context,
+			       const gchar         *element_name,
+			       gpointer             user_data,
+			       GError             **error)
+{
+  ParseContext *ctx = user_data;
+
+}
+
+
+static GMarkupParser firstpass_parser = 
+{
+  firstpass_start_element_handler,
+  firstpass_end_element_handler,
+  NULL,
+  NULL,
+  NULL,
+};
+
+
 static GMarkupParser parser = 
 {
   start_element_handler,
@@ -2280,6 +2399,15 @@
   GMarkupParseContext *context;
 
   ctx.state = STATE_START;
+  ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+  context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
+
+  if (!g_markup_parse_context_parse (context, buffer, length, error))
+    goto out;
+
+  if (!g_markup_parse_context_end_parse (context, error))
+    goto out;
   
   context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
   if (!g_markup_parse_context_parse (context, buffer, length, error))
@@ -2289,6 +2417,8 @@
     goto out;
 
  out:
+
+  g_hash_table_destroy (ctx.aliases);
   
   g_markup_parse_context_free (context);
   

Modified: trunk/giscanner/ast.py
==============================================================================
--- trunk/giscanner/ast.py	(original)
+++ trunk/giscanner/ast.py	Wed Aug 13 16:10:09 2008
@@ -141,6 +141,17 @@
         self.ctype = ctype
 
 
+class Alias(Node):
+
+    def __init__(self, name, target,ctype=None):
+        Node.__init__(self, name)
+        self.target = target
+        self.ctype = ctype
+
+    def __repr__(self):
+        return 'Alias(%r, %r)' % (self.name, self.target)
+
+
 class Parameter(Node):
 
     def __init__(self, name, typenode):

Modified: trunk/giscanner/girwriter.py
==============================================================================
--- trunk/giscanner/girwriter.py	(original)
+++ trunk/giscanner/girwriter.py	Wed Aug 13 16:10:09 2008
@@ -21,7 +21,7 @@
 from __future__ import with_statement
 
 from .ast import (Callback, Class, Enum, Function, Interface, Member,
-                  Sequence, Struct)
+                  Sequence, Struct, Alias)
 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
                       GLibFlags, GLibObject, GLibInterface)
 from .xmlwriter import XMLWriter
@@ -65,9 +65,17 @@
         elif isinstance(node, Member):
             # FIXME: atk_misc_instance singleton
             pass
+        elif isinstance(node, Alias):
+            self._write_alias(node)
         else:
             print 'WRITER: Unhandled node', node
 
+    def _write_alias(self, alias):
+        attrs = [('name', alias.name), ('target', alias.target)]
+        if alias.ctype is not None:
+            attrs.append(('c:type', ntype.ctype))
+        self.write_tag('alias', attrs)
+
     def _write_function(self, func, tag_name='function'):
         attrs = [('name', func.name),
                  ('c:identifier', func.symbol)]

Modified: trunk/giscanner/glibtransformer.py
==============================================================================
--- trunk/giscanner/glibtransformer.py	(original)
+++ trunk/giscanner/glibtransformer.py	Wed Aug 13 16:10:09 2008
@@ -25,7 +25,7 @@
 from . import cgobject
 from .odict import odict
 from .ast import (Callback, Enum, Function, Member, Namespace, Parameter,
-                  Property, Return, Sequence, Struct, Field, Type,
+                  Property, Return, Sequence, Struct, Field, Type, Alias,
                   type_name_from_ctype)
 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
                       GLibInterface, GLibObject, GLibSignal)
@@ -95,6 +95,7 @@
 
     def _resolve_param_type(self, ptype):
         type_name = ptype.name.replace('*', '')
+        type_name = self._transformer.resolve_possible_typedef(type_name)
         ptype.name = self._resolve_type_name(type_name)
         return ptype
 
@@ -107,6 +108,8 @@
             self._parse_struct(node)
         elif isinstance(node, Callback):
             self._parse_callback(node)
+        elif isinstance(node, Alias):
+            self._parse_alias(node)
         elif isinstance(node, Member):
             # FIXME: atk_misc_instance singletons
             pass
@@ -114,21 +117,35 @@
             print 'GOBJECT BUILDER: Unhandled node:', node
 
     def _resolve_node(self, node):
-        ntype = type(node)
-        if ntype in (Callback, Function):
+
+        def isany(*klasses):
+            for klass in klasses:
+                if isinstance(node, klass):
+                    return True
+            return False
+
+        if isany(Callback, Function):
             self._resolve_function(node)
-        if ntype in (GLibObject, GLibBoxed):
+        if isany(GLibObject, GLibBoxed, GLibInterface):
             for meth in node.methods:
                 self._resolve_function(meth)
+        if isany(GLibObject, GLibBoxed):
             for ctor in node.constructors:
                 self._resolve_function(ctor)
-        if ntype in (Struct, ):
+        if isany(GLibObject, GLibInterface):
+            for prop in node.properties:
+                self._resolve_property(prop)
+            for sig in node.signals:
+                self._resolve_function(sig)
+        if isany(Struct, ):
             for field in node.fields:
                 if isinstance(field, Field):
                     self._resolve_field(field)
-        if ntype in (GLibObject, ):
-            for prop in node.properties:
-                self._resolve_property(prop)
+                elif isinstance(field, Callback):
+                    self._resolve_function(field)
+
+    def _parse_alias(self, alias):
+        self._add_attribute(alias)
 
     def _parse_enum(self, enum):
         self._add_attribute(enum)

Modified: trunk/giscanner/transformer.py
==============================================================================
--- trunk/giscanner/transformer.py	(original)
+++ trunk/giscanner/transformer.py	Wed Aug 13 16:10:09 2008
@@ -18,9 +18,12 @@
 # 02110-1301, USA.
 #
 
+import os
+import sys
+
 from giscanner.ast import (Callback, Enum, Function, Namespace, Member,
                            Parameter, Return, Sequence, Struct, Field,
-                           Type, type_name_from_ctype)
+                           Type, Alias, type_name_from_ctype)
 from giscanner.sourcescanner import (
     SourceSymbol, ctype_name, symbol_type_name, CTYPE_POINTER,
     CTYPE_BASIC_TYPE, CTYPE_UNION, CTYPE_ARRAY,
@@ -40,6 +43,7 @@
         self._type_names = {}
         self._typedefs_ns = {}
         self._strip_prefix = ''
+        self._typedefs = {}
 
     def get_type_names(self):
         return self._type_names
@@ -47,6 +51,9 @@
     def set_strip_prefix(self, strip_prefix):
         self._strip_prefix = strip_prefix
 
+    def resolve_possible_typedef(self, tname):
+        return self._typedefs.get(tname, tname)
+
     def parse(self):
         nodes = []
         for symbol in self.generator.get_symbols():
@@ -200,7 +207,7 @@
                        CTYPE_BASIC_TYPE,
                        CTYPE_UNION,
                        CTYPE_VOID):
-            return
+            return Alias(symbol.ident, symbol.base_type.name)
         else:
             raise NotImplementedError(
                 "symbol %r of type %s" % (symbol.ident, ctype_name(ctype)))
@@ -209,7 +216,8 @@
     def _create_type(self, source_type):
         ctype = self._create_source_type(source_type)
         type_name = type_name_from_ctype(ctype)
-        return Type(type_name, ctype)
+        resolved_type_name = self._resolve_type_name(type_name)
+        return Type(resolved_type_name, ctype)
 
     def _create_parameter(self, symbol, options):
         ptype = self._create_type(symbol.base_type)

Modified: trunk/tests/scanner/Foo-expected.gir
==============================================================================
--- trunk/tests/scanner/Foo-expected.gir	(original)
+++ trunk/tests/scanner/Foo-expected.gir	Wed Aug 13 16:10:09 2008
@@ -184,7 +184,7 @@
           </parameter>
         </parameters>
       </method>
-      <method name="with_voidp" c:identifier="foo_object_with_voidp">
+      <method name="various" c:identifier="foo_object_various">
         <return-value>
           <type name="none" c:type="void"/>
         </return-value>
@@ -195,6 +195,22 @@
           <parameter name="data">
             <type name="any" c:type="void*"/>
           </parameter>
+          <parameter name="some_type">
+            <type name="GType" c:type="GType"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="with_tdef" c:identifier="foo_object_with_tdef">
+        <return-value>
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <parameter name="object">
+            <type name="Object" c:type="FooObject*"/>
+          </parameter>
+          <parameter name="blah">
+            <type name="FooList" c:type="FooList*"/>
+          </parameter>
         </parameters>
       </method>
       <property name="string">
@@ -206,7 +222,7 @@
         </return-value>
         <parameters>
           <parameter name="object">
-            <type name="FooObject*" c:type="FooObject*"/>
+            <type name="Object" c:type="FooObject*"/>
           </parameter>
           <parameter name="first_param">
             <type name="int32" c:type="int"/>
@@ -219,7 +235,7 @@
         </return-value>
         <parameters>
           <parameter name="object">
-            <type name="GObject" c:type="GObject"/>
+            <type name="GLib.Object" c:type="GObject"/>
           </parameter>
           <parameter name="p0">
             <type name="any" c:type="gpointer"/>
@@ -227,6 +243,7 @@
         </parameters>
       </glib:signal>
     </class>
+    <alias name="FooList" target="GSList"/>
     <class name="Subobject"
            c:type="FooSubobject"
            parent="Object"

Modified: trunk/tests/scanner/foo-object.h
==============================================================================
--- trunk/tests/scanner/foo-object.h	(original)
+++ trunk/tests/scanner/foo-object.h	Wed Aug 13 16:10:09 2008
@@ -61,7 +61,13 @@
 GList*                foo_object_get_strings       (FooObject *object);
 GSList*               foo_object_get_objects       (FooObject *object);
 
-void                  foo_object_with_voidp        (FooObject *object, void *data);
+void                  foo_object_various           (FooObject *object, void *data, GType some_type);
+
+/* A random typedef */
+typedef GSList FooList;
+
+void                  foo_object_with_tdef         (FooObject *object, FooList *blah);
+
 
 struct _FooSubobject
 {



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