Tweak to use UINT instead of INT. Not likely to matter. Add to
authorColin Walters <walters@verbum.org>
Thu, 21 Aug 2008 16:15:55 +0000 (16:15 +0000)
committerColin Walters <walters@src.gnome.org>
Thu, 21 Aug 2008 16:15:55 +0000 (16:15 +0000)
2008-08-21  Colin Walters  <walters@verbum.org>

* girepository/girnode.c (write_string): Tweak to
use UINT instead of INT.  Not likely to matter.
* girepository/girmodule.c (g_ir_module_build_typelib):
Add to header_offset as well for header strings
to match what write_string does.
* girepository/gtypelib.c: Replace is_name with
validate_name, which more strongly validates and
handles errors in a better way.  Update all callers.
* giscanner/glibtransformer.py: Handle constructors
better.

svn path=/trunk/; revision=439

ChangeLog
girepository/girmodule.c
girepository/girnode.c
girepository/gtypelib.c
giscanner/glibtransformer.py

index 1bfd07c..2ffb657 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-08-21  Colin Walters  <walters@verbum.org>
+
+       * girepository/girnode.c (write_string): Tweak to
+       use UINT instead of INT.  Not likely to matter.
+       * girepository/girmodule.c (g_ir_module_build_typelib):
+       Add to header_offset as well for header strings
+       to match what write_string does.
+       * girepository/gtypelib.c: Replace is_name with
+       validate_name, which more strongly validates and
+       handles errors in a better way.  Update all callers.
+       * giscanner/glibtransformer.py: Handle constructors
+       better.
+
 2008-08-21  Johan Dahlin  <johan@gnome.org>
 
        * gir/Makefile.am (typelibs_DATA): Build and 
index 1ffbf9b..1fcdadb 100644 (file)
@@ -104,8 +104,12 @@ g_ir_module_build_typelib (GIrModule  *module,
 
   /* Adjust size for strings allocated in header below specially */
   size += strlen (module->name);
-  if (module->shared_library)
-    size += strlen (module->shared_library);
+  header_size = ALIGN_VALUE (header_size + strlen (module->name) + 1, 4);
+  if (module->shared_library) 
+    {
+      size += strlen (module->shared_library);
+      header_size = ALIGN_VALUE (header_size + strlen (module->shared_library) + 1, 4);
+    }
 
   g_message ("allocating %d bytes (%d header, %d directory, %d entries)\n", 
          size, header_size, dir_size, size - header_size - dir_size);
index 6fb32aa..06e1b8e 100644 (file)
@@ -2144,12 +2144,12 @@ write_string (const gchar *str,
   value = g_hash_table_lookup (strings, str);
   
   if (value)
-    return GPOINTER_TO_INT (value);
+    return GPOINTER_TO_UINT (value);
 
   unique_string_count += 1;
   unique_string_size += strlen (str);
 
-  g_hash_table_insert (strings, (gpointer)str, GINT_TO_POINTER (*offset));
+  g_hash_table_insert (strings, (gpointer)str, GUINT_TO_POINTER (*offset));
 
   start = *offset;
   *offset = ALIGN_VALUE (start + strlen (str) + 1, 4);
index 6e04f65..53684fd 100644 (file)
@@ -81,17 +81,44 @@ is_aligned (guint32 offset)
 #define MAX_NAME_LEN 200
 
 static gboolean
-is_name (const guchar *data, guint32 offset)
+validate_name (GTypelib *typelib,
+              const char *msg,
+              const guchar *data, guint32 offset,
+              GError **error)
 {
   gchar *name;
 
+  if (typelib->len < offset)
+    {
+      g_set_error (error,
+                  G_TYPELIB_ERROR,
+                  G_TYPELIB_ERROR_INVALID,
+                  "The buffer is too short for type %s",
+                  msg);
+      return FALSE;
+    }
+
   name = (gchar*)&data[offset];
   
-  if (!memchr (name, '\0', MAX_NAME_LEN))
-    return FALSE;
+  if (!memchr (name, '\0', MAX_NAME_LEN)) 
+    {
+      g_set_error (error,
+                  G_TYPELIB_ERROR,
+                  G_TYPELIB_ERROR_INVALID,
+                  "The %s is too long: %s",
+                  msg, name);
+      return FALSE;
+    }
   
-  if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
-    return FALSE;
+  if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name)) 
+    {
+      g_set_error (error,
+                  G_TYPELIB_ERROR,
+                  G_TYPELIB_ERROR_INVALID,
+                  "The %s is contains invalid characters: %s",
+                  msg, name);
+      return FALSE;
+    }
   
   return TRUE;
 }
@@ -204,14 +231,8 @@ validate_header (GTypelib  *typelib,
       return FALSE; 
     }
 
-  if (!is_name (typelib->data, header->namespace))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_HEADER,
-                  "Invalid namespace name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error))
+    return FALSE; 
 
   return TRUE;
 }
@@ -470,14 +491,8 @@ validate_arg_blob (GTypelib     *typelib,
 
   blob = (ArgBlob*) &typelib->data[offset];
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid argument name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "argument", typelib->data, blob->name, error))
+    return FALSE; 
  
   if (!validate_type_blob (typelib, 
                           offset + G_STRUCT_OFFSET (ArgBlob, arg_type), 
@@ -557,23 +572,11 @@ validate_function_blob (GTypelib     *typelib,
       return FALSE;
     }
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid function name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "function", typelib->data, blob->name, error))
+    return FALSE; 
   
-  if (!is_name (typelib->data, blob->symbol))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid function symbol");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
+    return FALSE; 
   
   if (blob->constructor)
     {
@@ -657,14 +660,8 @@ validate_callback_blob (GTypelib     *typelib,
       return FALSE;
     }
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid callback name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "callback", typelib->data, blob->name, error))
+    return FALSE; 
   
   if (!validate_signature_blob (typelib, blob->signature, error))
     return FALSE;
@@ -708,14 +705,8 @@ validate_constant_blob (GTypelib     *typelib,
       return FALSE;
     }
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid constant name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
+    return FALSE; 
   
   if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type), 
                           0, FALSE, error))
@@ -775,14 +766,8 @@ validate_value_blob (GTypelib     *typelib,
 
   blob = (ValueBlob*) &typelib->data[offset];
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid value name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "value", typelib->data, blob->name, error))
+    return FALSE; 
   
   return TRUE;
 }
@@ -805,15 +790,9 @@ validate_field_blob (GTypelib     *typelib,
 
   blob = (FieldBlob*) &typelib->data[offset];
   
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid field name");
-      return FALSE; 
-    }
-    
+  if (!validate_name (typelib, "field", typelib->data, blob->name, error))
+    return FALSE; 
+  
   if (!validate_type_blob (typelib,
                           offset + G_STRUCT_OFFSET (FieldBlob, type), 
                           0, FALSE, error))
@@ -840,14 +819,8 @@ validate_property_blob (GTypelib     *typelib,
 
   blob = (PropertyBlob*) &typelib->data[offset];
   
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid property name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "property", typelib->data, blob->name, error))
+    return FALSE; 
     
   if (!validate_type_blob (typelib,
                           offset + G_STRUCT_OFFSET (PropertyBlob, type), 
@@ -877,14 +850,8 @@ validate_signal_blob (GTypelib     *typelib,
 
   blob = (SignalBlob*) &typelib->data[offset];
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid signal name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
+    return FALSE; 
   
   if ((blob->run_first != 0) + 
       (blob->run_last != 0) + 
@@ -952,14 +919,8 @@ validate_vfunc_blob (GTypelib     *typelib,
 
   blob = (VFuncBlob*) &typelib->data[offset];
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid vfunc name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
+    return FALSE; 
   
   if (blob->class_closure)
     {
@@ -1035,34 +996,16 @@ validate_struct_blob (GTypelib     *typelib,
       return FALSE;
     }
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid struct name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
+    return FALSE; 
   
   if (blob_type == BLOB_TYPE_BOXED)
     {
-      if (!is_name (typelib->data, blob->gtype_name))
-       {
-         g_set_error (error,
-                      G_TYPELIB_ERROR,
-                      G_TYPELIB_ERROR_INVALID_BLOB,
-                      "Invalid boxed type name");
-         return FALSE; 
-       }
+      if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
+       return FALSE; 
 
-      if (!is_name (typelib->data, blob->gtype_init))
-       {
-         g_set_error (error,
-                      G_TYPELIB_ERROR,
-                      G_TYPELIB_ERROR_INVALID_BLOB,
-                      "Invalid boxed type init");
-         return FALSE; 
-       }
+      if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
+       return FALSE; 
     }
   else
     {
@@ -1142,23 +1085,11 @@ validate_enum_blob (GTypelib     *typelib,
   
   if (!blob->unregistered)
     {
-      if (!is_name (typelib->data, blob->gtype_name))
-       {
-         g_set_error (error,
-                      G_TYPELIB_ERROR,
-                      G_TYPELIB_ERROR_INVALID_BLOB,
-                      "Invalid enum type name");
-         return FALSE; 
-       }
+      if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
+       return FALSE; 
 
-      if (!is_name (typelib->data, blob->gtype_init))
-       {
-         g_set_error (error,
-                      G_TYPELIB_ERROR,
-                      G_TYPELIB_ERROR_INVALID_BLOB,
-                      "Invalid enum type init");
-         return FALSE; 
-       }
+      if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
+       return FALSE; 
     }
   else
     {
@@ -1172,14 +1103,8 @@ validate_enum_blob (GTypelib     *typelib,
        }
     }
 
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid enum name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
+    return FALSE; 
   
   if (typelib->len < offset + sizeof (EnumBlob) + 
       blob->n_values * sizeof (ValueBlob))
@@ -1256,32 +1181,14 @@ validate_object_blob (GTypelib     *typelib,
       return FALSE;
     }
   
-  if (!is_name (typelib->data, blob->gtype_name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid object type name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
+    return FALSE; 
   
-  if (!is_name (typelib->data, blob->gtype_init))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid object type init");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
+    return FALSE; 
   
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid object name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "object", typelib->data, blob->name, error))
+    return FALSE; 
   
   if (blob->parent > header->n_entries)
     {
@@ -1428,32 +1335,14 @@ validate_interface_blob (GTypelib     *typelib,
       return FALSE;
     }
   
-  if (!is_name (typelib->data, blob->gtype_name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid interface type name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
+    return FALSE; 
   
-  if (!is_name (typelib->data, blob->gtype_init))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid interface type init");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
+    return FALSE; 
   
-  if (!is_name (typelib->data, blob->name))
-    {
-      g_set_error (error,
-                  G_TYPELIB_ERROR,
-                  G_TYPELIB_ERROR_INVALID_BLOB,
-                  "Invalid interface name");
-      return FALSE; 
-    }
+  if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
+    return FALSE; 
   
   if (typelib->len < offset + sizeof (InterfaceBlob) + 
             (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
@@ -1642,14 +1531,8 @@ validate_directory (GTypelib     *typelib,
     {
       entry = g_typelib_get_dir_entry (typelib, i + 1);
 
-      if (!is_name (typelib->data, entry->name))
-       {
-         g_set_error (error,
-                      G_TYPELIB_ERROR,
-                      G_TYPELIB_ERROR_INVALID_DIRECTORY,
-                      "Invalid entry name");
-         return FALSE; 
-       }
+      if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
+       return FALSE; 
       
       if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
          entry->blob_type > BLOB_TYPE_UNION)
@@ -1695,14 +1578,8 @@ validate_directory (GTypelib     *typelib,
              return FALSE;
            }
 
-         if (!is_name (typelib->data, entry->offset))
-           {
-             g_set_error (error,
-                          G_TYPELIB_ERROR,
-                          G_TYPELIB_ERROR_INVALID_DIRECTORY,
-                          "Invalid namespace name");
-             return FALSE; 
-           }
+         if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
+           return FALSE; 
        }
     }
 
index 6e3e7cc..007b005 100644 (file)
@@ -178,10 +178,6 @@ class GLibTransformer(object):
     def _parse_function(self, func):
         if self._parse_get_type_function(func):
             return
-        elif self._parse_constructor(func):
-            return
-        elif self._parse_method(func):
-            return
 
         self._add_attribute(func)
 
@@ -245,25 +241,41 @@ class GLibTransformer(object):
             target_arg = func.retval
         else:
             target_arg = func.parameters[0]
+        target_arg.type = self._resolve_param_type(target_arg.type)
+
         klass = self._get_attribute(target_arg.type.name)
-        if klass is None or not isinstance(klass, (GLibObject, GLibBoxed)):
-            return False
+        if klass is None or not isinstance(klass, (GLibObject, GLibBoxed,
+                                                   GLibInterface)):
+            return None
 
-        # Look at the original C type (before namespace stripping), without
-        # pointers: GtkButton -> gtk_button_, so we can figure out the
-        # method name
         orig_type = target_arg.type.ctype.replace('*', '')
         prefix = to_underscores(orig_type).lower() + '_'
-        if not func.symbol.startswith(prefix):
-            return False
+        if not is_method:
+            # Interfaces can't have constructors, punt to global scope
+            # Constructors must have _new
+            new_idx = func.symbol.find('_new')
+            if (isinstance(klass, GLibInterface) or
+                new_idx < 0):
+                return None
+            # Just strip everything before _new
+            prefix = func.symbol[:new_idx+1]
+            # TODO - check that the return type is a subclass of the
+            # class from the prefix
+        else:
+            # Look at the original C type (before namespace stripping), without
+            # pointers: GtkButton -> gtk_button_, so we can figure out the
+            # method name
+            if not func.symbol.startswith(prefix):
+                return None
 
+        self._remove_attribute(func.name)
         # Strip namespace and object prefix: gtk_window_new -> new
         func.name = func.symbol[len(prefix):]
         if is_method:
             klass.methods.append(func)
         else:
             klass.constructors.append(func)
-        return True
+        return func
 
     def _parse_struct(self, struct):
         # This is a hack, but GObject is a rather fundamental piece so.
@@ -496,7 +508,10 @@ class GLibTransformer(object):
         return ptype
 
     def _resolve_node(self, node):
-        if isinstance(node, (Callback, Function)):
+        if isinstance(node, Function):
+            self._resolve_function_toplevel(node)
+
+        elif isinstance(node, Callback):
             self._resolve_function(node)
         elif isinstance(node, GLibObject):
             self._resolve_glib_object(node)
@@ -511,6 +526,15 @@ class GLibTransformer(object):
         elif isinstance(node, Alias):
             self._resolve_alias(node)
 
+    def _resolve_function_toplevel(self, func):
+        newfunc = self._parse_constructor(func)
+        if not newfunc:
+            newfunc = self._parse_method(func)
+            if not newfunc:
+                self._resolve_function(func)
+                return
+        self._resolve_function(newfunc)
+
     def _resolve_struct(self, node):
         for field in node.fields:
             self._resolve_field(field)