commit 79f5264b6ea06b44a9435507c160f8ac515dbb55
Author: Colin Walters <walters@verbum.org>
Date:   Sun Nov 16 15:09:36 2008 -0500

    Initial code drop

diff --git a/girepository/ginfo.c b/girepository/ginfo.c
index 3de0cf5..668bfca 100644
--- a/girepository/ginfo.c
+++ b/girepository/ginfo.c
@@ -733,23 +733,14 @@ g_arg_info_get_type (GIArgInfo *info)
   return g_type_info_new (base, base->typelib, base->offset + 8);
 }
 
-/* GITypeInfo functions */
 gboolean
-g_type_info_is_pointer (GITypeInfo *info)
+g_type_tag_is_reference (GITypeTag   type)
 {
-  GIBaseInfo *base = (GIBaseInfo *)info;
-  SimpleTypeBlob *type = (SimpleTypeBlob *)&base->typelib->data[base->offset];
-  
-  if (type->reserved == 0 && type->reserved2 == 0)
-    return type->pointer;
-  else
-    {
-      InterfaceTypeBlob *iface = (InterfaceTypeBlob *)&base->typelib->data[base->offset];
-      
-      return iface->pointer;
-    }
+  return type < GI_TYPE_TAG_ANY;
 }
 
+/* GITypeInfo functions */
+
 GITypeTag
 g_type_info_get_tag (GITypeInfo *info)
 {
@@ -951,6 +942,9 @@ g_field_info_get_flags (GIFieldInfo *info)
   if (blob->writable)
     flags = flags | GI_FIELD_IS_WRITABLE;
 
+  if (!blob->reference)
+    flags = flags | GI_FIELD_IS_VALUE;
+
   return flags;
 }
 
@@ -1714,7 +1708,7 @@ g_constant_info_get_value (GIConstantInfo *info,
   /* FIXME non-basic types ? */
   if (blob->type.reserved == 0 && blob->type.reserved2 == 0)
     {
-      if (blob->type.pointer)
+      if (g_type_tag_is_reference (blob->type.tag))
 	value->v_pointer = g_memdup (&base->typelib->data[blob->offset], blob->size);
       else
 	{
@@ -1768,6 +1762,8 @@ g_constant_info_get_value (GIConstantInfo *info,
 	    case GI_TYPE_TAG_ULONG:
 	      value->v_ulong = *(gulong*)&base->typelib->data[blob->offset];
 	      break;
+	    default:
+	      g_assert_not_reached ();
 	    }
 	}
     }
diff --git a/girepository/ginvoke.c b/girepository/ginvoke.c
index 89419e5..8d98d88 100644
--- a/girepository/ginvoke.c
+++ b/girepository/ginvoke.c
@@ -42,10 +42,11 @@ g_invoke_error_quark (void)
 static ffi_type *
 get_ffi_type (GITypeInfo *info)
 {
-  if (g_type_info_is_pointer (info))
+  GITypeTag tag = g_type_info_get_tag (info);
+  if (g_type_tag_is_reference (tag))
     return &ffi_type_pointer;
   else
-    return g_ir_ffi_get_ffi_type (g_type_info_get_tag (info));
+    return g_ir_ffi_get_ffi_type (tag);
 }
 
 /**
diff --git a/girepository/girepository.c b/girepository/girepository.c
index e65910d..0404e12 100644
--- a/girepository/girepository.c
+++ b/girepository/girepository.c
@@ -1225,6 +1225,8 @@ g_type_tag_to_string (GITypeTag type)
       return "time_t";
     case GI_TYPE_TAG_GTYPE:
       return "GType";
+    case GI_TYPE_TAG_ANY:
+      return "any";
     case GI_TYPE_TAG_UTF8:
       return "utf8";
     case GI_TYPE_TAG_FILENAME:
diff --git a/girepository/girepository.h b/girepository/girepository.h
index 46082e0..709882f 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -281,13 +281,13 @@ GITypeInfo *           g_arg_info_get_type               (GIArgInfo *info);
 /* GITypeInfo */
 
 typedef enum {
-  /* Basic types */
+  /* Value types */
   GI_TYPE_TAG_VOID      =  0,
   GI_TYPE_TAG_BOOLEAN   =  1,
   GI_TYPE_TAG_INT8      =  2,
   GI_TYPE_TAG_UINT8     =  3,
   GI_TYPE_TAG_INT16     =  4,
-  GI_TYPE_TAG_UINT16    =  5,  
+  GI_TYPE_TAG_UINT16    =  5,
   GI_TYPE_TAG_INT32     =  6,
   GI_TYPE_TAG_UINT32    =  7,
   GI_TYPE_TAG_INT64     =  8,
@@ -302,24 +302,24 @@ typedef enum {
   GI_TYPE_TAG_DOUBLE    = 17,
   GI_TYPE_TAG_TIME_T    = 18,
   GI_TYPE_TAG_GTYPE     = 19,
-  GI_TYPE_TAG_UTF8      = 20,
-  GI_TYPE_TAG_FILENAME  = 21,
-  /* Non-basic types */
-  GI_TYPE_TAG_ARRAY     = 22,
-  GI_TYPE_TAG_INTERFACE = 23,
-  GI_TYPE_TAG_GLIST     = 24,
-  GI_TYPE_TAG_GSLIST    = 25,
-  GI_TYPE_TAG_GHASH     = 26,
-  GI_TYPE_TAG_ERROR     = 27
+  /* Default reference types, see g_type_tag_is_reference */
+  GI_TYPE_TAG_ANY       = 20,
+  GI_TYPE_TAG_UTF8      = 21,
+  GI_TYPE_TAG_FILENAME  = 22,
+  GI_TYPE_TAG_ARRAY     = 23,
+  GI_TYPE_TAG_INTERFACE = 24,
+  GI_TYPE_TAG_GLIST     = 25,
+  GI_TYPE_TAG_GSLIST    = 26,
+  GI_TYPE_TAG_GHASH     = 27,
+  GI_TYPE_TAG_ERROR     = 28
   /* Note - there is only room currently for 32 tags.
    * See docs/typelib-format.txt SimpleTypeBlob definition */
 } GITypeTag;
 
-#define G_TYPE_TAG_IS_BASIC(tag) (tag < GI_TYPE_TAG_ARRAY)
+gboolean               g_type_tag_is_reference         (GITypeTag   type);
 
 const gchar*           g_type_tag_to_string            (GITypeTag   type);
 
-gboolean               g_type_info_is_pointer          (GITypeInfo *info);
 GITypeTag              g_type_info_get_tag             (GITypeInfo *info);
 GITypeInfo *           g_type_info_get_param_type      (GITypeInfo *info,
 						        gint       n);
@@ -348,7 +348,8 @@ glong                  g_value_info_get_value      (GIValueInfo *info);
 typedef enum
 {
   GI_FIELD_IS_READABLE = 1 << 0,
-  GI_FIELD_IS_WRITABLE = 1 << 1
+  GI_FIELD_IS_WRITABLE = 1 << 1,
+  GI_FIELD_IS_VALUE    = 1 << 2
 } GIFieldInfoFlags;
 
 GIFieldInfoFlags       g_field_info_get_flags      (GIFieldInfo *info);
diff --git a/girepository/girffi.c b/girepository/girffi.c
index d6eefb2..f99820b 100644
--- a/girepository/girffi.c
+++ b/girepository/girffi.c
@@ -83,6 +83,7 @@ g_ir_ffi_get_ffi_type (GITypeTag tag)
       return &ffi_type_float;
     case GI_TYPE_TAG_DOUBLE:
       return &ffi_type_double;
+    case GI_TYPE_TAG_ANY:
     case GI_TYPE_TAG_UTF8:
     case GI_TYPE_TAG_FILENAME:
     case GI_TYPE_TAG_ARRAY:
diff --git a/girepository/girnode.c b/girepository/girnode.c
index 8851df0..5591ec5 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -1375,7 +1375,6 @@ g_ir_node_build_typelib (GIrNode    *node,
 	  { 
 	    blob->reserved = 0;
 	    blob->reserved2 = 0;
-	    blob->pointer = type->is_pointer;
 	    blob->reserved3 = 0;
 	    blob->tag = type->tag;
 	  }
@@ -1409,7 +1408,6 @@ g_ir_node_build_typelib (GIrNode    *node,
 		      ArrayTypeBlob *array = (ArrayTypeBlob *)&data[*offset2];
 		      guint32 pos;
 		      
-		      array->pointer = 1;
 		      array->reserved = 0;
 		      array->tag = type->tag;
 		      array->zero_terminated = type->zero_terminated;
@@ -1437,7 +1435,6 @@ g_ir_node_build_typelib (GIrNode    *node,
 		      InterfaceTypeBlob *iface = (InterfaceTypeBlob *)&data[*offset2];
 		      *offset2 += 4;
 
-		      iface->pointer = type->is_pointer;
 		      iface->reserved = 0;
 		      iface->tag = type->tag;
 		      iface->reserved2 = 0;
@@ -1452,7 +1449,6 @@ g_ir_node_build_typelib (GIrNode    *node,
 		      ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
 		      guint32 pos;
 		      
-		      param->pointer = 1;
 		      param->reserved = 0;
 		      param->tag = type->tag;
 		      param->reserved2 = 0;
@@ -1472,7 +1468,6 @@ g_ir_node_build_typelib (GIrNode    *node,
 		      ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
 		      guint32 pos;
 		      
-		      param->pointer = 1;
 		      param->reserved = 0;
 		      param->tag = type->tag;
 		      param->reserved2 = 0;
@@ -1495,7 +1490,6 @@ g_ir_node_build_typelib (GIrNode    *node,
 		      ErrorTypeBlob *blob = (ErrorTypeBlob *)&data[*offset2];
 		      gint i;
 		      
-		      blob->pointer = 1;
 		      blob->reserved = 0;
 		      blob->tag = type->tag;
 		      blob->reserved2 = 0;
diff --git a/girepository/girnode.h b/girepository/girnode.h
index 9829a93..ed5ec3c 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -106,7 +106,6 @@ struct _GIrNodeType
 {
   GIrNode node;
 
-  gboolean is_pointer;
   gboolean is_basic;
   gboolean is_array;
   gboolean is_glist;
@@ -205,6 +204,7 @@ struct _GIrNodeField
 {
   GIrNode node;
 
+  gboolean reference;
   gboolean readable;
   gboolean writable;
   gint bits;
diff --git a/girepository/giroffsets.c b/girepository/giroffsets.c
index 1844dd1..aaef025 100644
--- a/girepository/giroffsets.c
+++ b/girepository/giroffsets.c
@@ -202,7 +202,7 @@ get_field_size_alignment (GIrNodeField *field,
   GIrNodeType *type = field->type;
   ffi_type *type_ffi;
 
-  if (type->is_pointer)
+  if (field->reference)
     {
       type_ffi = &ffi_type_pointer;
     }
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 65ba282..0c1078f 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -316,12 +316,13 @@ static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboole
 typedef struct {
   const gchar *str;
   gint tag;
+  /* TODO remove this field, no longer needed */
   gboolean pointer;
 } BasicTypeInfo;
 
 static BasicTypeInfo basic_types[] = {
     { "none",     GI_TYPE_TAG_VOID,    0 },
-    { "any",      GI_TYPE_TAG_VOID,    1 },
+    { "any",      GI_TYPE_TAG_ANY,     0 },
 
     { "bool",     GI_TYPE_TAG_BOOLEAN, 0 },
     { "char",     GI_TYPE_TAG_INT8,    0 },
@@ -387,7 +388,6 @@ parse_type_internal (const gchar *str, char **next, gboolean in_glib,
     {
       type->is_basic = TRUE;
       type->tag = basic->tag;
-      type->is_pointer = basic->pointer;
 
       str += strlen(basic->str);
     }
@@ -433,14 +433,12 @@ parse_type_internal (const gchar *str, char **next, gboolean in_glib,
 	{
 	  type->tag = GI_TYPE_TAG_GLIST;
 	  type->is_glist = TRUE;
-	  type->is_pointer = TRUE;
 	  str += strlen ("List");
 	}
       else
 	{
 	  type->tag = GI_TYPE_TAG_GSLIST;
 	  type->is_gslist = TRUE;
-	  type->is_pointer = TRUE;
 	  str += strlen ("SList");
 	}
     }
@@ -450,7 +448,6 @@ parse_type_internal (const gchar *str, char **next, gboolean in_glib,
 
       type->tag = GI_TYPE_TAG_GHASH;
       type->is_ghashtable = TRUE;
-      type->is_pointer = TRUE;
       str += strlen ("HashTable");
     }
   else if (g_str_has_prefix (str, "GLib.Error"))
@@ -459,7 +456,6 @@ parse_type_internal (const gchar *str, char **next, gboolean in_glib,
 
       type->tag = GI_TYPE_TAG_ERROR;
       type->is_error = TRUE;
-      type->is_pointer = TRUE;
       str += strlen ("Error");
       
       if (*str == '<')
@@ -942,6 +938,7 @@ start_field (GMarkupParseContext *context,
 	     GError             **error)
 {
   const gchar *name;
+  const gchar *reference;
   const gchar *readable;
   const gchar *writable;
   const gchar *bits;
@@ -964,6 +961,7 @@ start_field (GMarkupParseContext *context,
     return FALSE;
   
   name = find_attribute ("name", attribute_names, attribute_values);
+  reference = find_attribute ("byreference", attribute_names, attribute_values);
   readable = find_attribute ("readable", attribute_names, attribute_values);
   writable = find_attribute ("writable", attribute_names, attribute_values);
   bits = find_attribute ("bits", attribute_names, attribute_values);
@@ -978,6 +976,8 @@ start_field (GMarkupParseContext *context,
   field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
   ctx->current_typed = (GIrNode*) field;
   ((GIrNode *)field)->name = g_strdup (name);
+  /* Struct members are assumed to be by reference */
+  field->reference = reference == NULL || strcmp (reference, "0") == 0;
   /* Fields are assumed to be read-only.
    * (see also girwriter.py and generate.c)
    */
@@ -1541,7 +1541,6 @@ start_type (GMarkupParseContext *context,
 	    GError             **error)
 {
   const gchar *name;
-  const gchar *ctype;
   gboolean is_array;
   gboolean is_varargs;
   GIrNodeType *typenode;
@@ -1640,7 +1639,6 @@ start_type (GMarkupParseContext *context,
       typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
 
       typenode->tag = GI_TYPE_TAG_ARRAY;
-      typenode->is_pointer = TRUE;
       typenode->is_array = TRUE;
       
       zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
@@ -1656,29 +1654,12 @@ start_type (GMarkupParseContext *context,
     }
   else
     {
-      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);
-
-      /* A 'disguised' structure is one where the c:type is a typedef that
-       * doesn't look like a pointer, but is internally.
-       */
-      if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
-	  is_disguised_structure (ctx, typenode->interface))
-	is_pointer = TRUE;
-
-      if (is_pointer)
-	typenode->is_pointer = is_pointer;
     }
 
   ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
diff --git a/girepository/gtypelib.c b/girepository/gtypelib.c
index be470a4..9201a62 100644
--- a/girepository/gtypelib.c
+++ b/girepository/gtypelib.c
@@ -382,15 +382,6 @@ validate_array_type_blob (GTypelib     *typelib,
 
   blob = (ArrayTypeBlob*)&typelib->data[offset];
 
-  if (!blob->pointer)
-    {
-      g_set_error (error,
-		   G_TYPELIB_ERROR,
-		   G_TYPELIB_ERROR_INVALID_BLOB,
-		   "Pointer type exected for tag %d", blob->tag);
-      return FALSE;	  
-    }
-
   /* FIXME validate length */
 
   if (!validate_type_blob (typelib,
@@ -436,15 +427,6 @@ validate_param_type_blob (GTypelib     *typelib,
 
   blob = (ParamTypeBlob*)&typelib->data[offset];
 
-  if (!blob->pointer)
-    {
-      g_set_error (error,
-		   G_TYPELIB_ERROR,
-		   G_TYPELIB_ERROR_INVALID_BLOB,
-		   "Pointer type exected for tag %d", blob->tag);
-      return FALSE;	  
-    }
-  
   if (blob->n_types != n_params)
     {
       g_set_error (error,
@@ -482,15 +464,6 @@ validate_error_type_blob (GTypelib     *typelib,
 
   header = (Header *)typelib->data;
 
-  if (!blob->pointer)
-    {
-      g_set_error (error,
-		   G_TYPELIB_ERROR,
-		   G_TYPELIB_ERROR_INVALID_BLOB,
-		   "Pointer type exected for tag %d", blob->tag);
-      return FALSE;	  
-    }
-  
   for (i = 0; i < blob->n_domains; i++)
     {
       if (blob->domains[i] == 0 || blob->domains[i] > header->n_entries)
@@ -542,16 +515,6 @@ validate_type_blob (GTypelib     *typelib,
 	  return FALSE;
 	}
       
-      if (simple->tag >= GI_TYPE_TAG_UTF8 &&
-	  !simple->pointer)
-	{
-	  g_set_error (error,
-		       G_TYPELIB_ERROR,
-		       G_TYPELIB_ERROR_INVALID_BLOB,
-		       "Pointer type exected for tag %d", simple->tag);
-	  return FALSE;	  
-	}
-
       return TRUE;
     }
 
diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h
index 458d429..f5a719e 100644
--- a/girepository/gtypelib.h
+++ b/girepository/gtypelib.h
@@ -112,8 +112,7 @@ typedef union
   {
     guint reserved   : 8;
     guint reserved2  :16;
-    guint pointer    : 1;
-    guint reserved3  : 2;
+    guint reserved3  : 3;
     guint tag        : 5;    
   };
   guint32    offset;
@@ -191,8 +190,7 @@ typedef struct
 
 typedef struct 
 {
-  guint8  pointer  :1;
-  guint8  reserved :2;
+  guint8  reserved :3;
   guint8  tag      :5;    
   guint8  reserved2;
   guint16 interface;  
@@ -200,8 +198,7 @@ typedef struct
 
 typedef struct
 {
-  guint16 pointer         :1;
-  guint16 reserved        :2;
+  guint16 reserved        :3;
   guint16 tag             :5;    
 
   guint16 zero_terminated :1;
@@ -219,8 +216,7 @@ typedef struct
 
 typedef struct
 {
-  guint8  	 pointer  :1;
-  guint8  	 reserved :2;
+  guint8  	 reserved :3;
   guint8  	 tag      :5;    
 
   guint8  	 reserved2;
@@ -231,8 +227,7 @@ typedef struct
 
 typedef struct
 {
-  guint8  pointer  :1;
-  guint8  reserved :2;
+  guint8  reserved :3;
   guint8  tag      :5;    
 
   guint8  reserved2;
@@ -267,9 +262,10 @@ typedef struct
 {
   guint32        name;
 
-  guint8         readable :1; 
+  guint8         reference :1;
+  guint8         readable :1;
   guint8         writable :1;
-  guint8         reserved :6;
+  guint8         reserved :5;
   guint8         bits;
 
   guint16        struct_offset;      
diff --git a/giscanner/ast.py b/giscanner/ast.py
index b4e8e9e..d6c3e06 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -334,13 +334,14 @@ class Struct(Node):
 
 class Field(Node):
 
-    def __init__(self, name, typenode, symbol, readable, writable, bits=None):
+    def __init__(self, name, typenode, symbol, readable, writable, bits, byreference):
         Node.__init__(self, name)
         self.type = typenode
         self.symbol = symbol
         self.readable = readable
         self.writable = writable
         self.bits = bits
+        self.byreference = byreference
 
     def __repr__(self):
         if self.bits:
diff --git a/giscanner/girparser.py b/giscanner/girparser.py
index 02c78b9..edbfcb8 100644
--- a/giscanner/girparser.py
+++ b/giscanner/girparser.py
@@ -300,7 +300,8 @@ class GIRParser(object):
                      type_node.ctype,
                      node.attrib.get('readable') != '0',
                      node.attrib.get('writable') == '1',
-                     node.attrib.get('bits'))
+                     node.attrib.get('bits'),
+                     node.attrib.get('byreference') == '1')
 
     def _parse_property(self, node):
         type_node = self._parse_type(node)
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 030ea82..50b6f63 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -352,6 +352,7 @@ class GIRWriter(XMLWriter):
             attrs.append(('writable', '1'))
         if field.bits:
             attrs.append(('bits', str(field.bits)))
+        attrs.append(('byreference', field.byreference and '1' or '0'))
         with self.tagcontext('field', attrs):
             self._write_type(field.type)
 
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 36b02f7..fac3f02 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -334,10 +334,13 @@ class Transformer(object):
                     opts['array'].append(size_opt)
             ftype = self._create_type(symbol.base_type, opts, True)
             ftype = self.resolve_param_type(ftype)
+            # Default to reference type for non-basic types
+            byreference = (ftype.name not in type_names) and (ctype == CTYPE_POINTER)
             # Fields are assumed to be read-write
             # (except for Objects, see also glibtransformer.py)
             node = Field(symbol.ident, ftype, symbol.ident,
-                       readable=True, writable=True, bits=symbol.const_int)
+                         readable=True, writable=True, bits=symbol.const_int,
+                         byreference=byreference)
         return node
 
     def _create_typedef(self, symbol):
diff --git a/tools/generate.c b/tools/generate.c
index 840de7c..8f26af7 100644
--- a/tools/generate.c
+++ b/tools/generate.c
@@ -194,22 +194,12 @@ write_type_info (const gchar *namespace,
   gint tag;
   gint i;
   GITypeInfo *type;
-  gboolean is_pointer;
   
   check_unresolved ((GIBaseInfo*)info);
 
   tag = g_type_info_get_tag (info);
-  is_pointer = g_type_info_is_pointer (info);
 
-  if (tag == GI_TYPE_TAG_VOID) 
-    {
-      xml_start_element (file, "type");
-
-      xml_printf (file, " name=\"%s\"", is_pointer ? "any" : "none");
-
-      xml_end_element (file, "type");
-    } 
-  else if (G_TYPE_TAG_IS_BASIC (tag))
+  if (!g_type_tag_is_reference (tag))
     {
       xml_start_element (file, "type");
       xml_printf (file, " name=\"%s\"", g_type_tag_to_string (tag));
