Bug 557786 - support fixed size arrays
authorColin Walters <walters@src.gnome.org>
Sat, 25 Oct 2008 15:20:54 +0000 (15:20 +0000)
committerColin Walters <walters@src.gnome.org>
Sat, 25 Oct 2008 15:20:54 +0000 (15:20 +0000)
svn path=/trunk/; revision=814

17 files changed:
ChangeLog
girepository/ginfo.c
girepository/girepository.h
girepository/girnode.c
girepository/girnode.h
girepository/girparser.c
girepository/gtypelib.h
giscanner/ast.py
giscanner/girwriter.py
giscanner/scannerparser.y
giscanner/sourcescanner.c
giscanner/sourcescanner.h
giscanner/transformer.py
tests/scanner/utility-1.0-expected.gir
tests/scanner/utility-1.0-expected.tgir
tests/scanner/utility.h
tools/generate.c

index 0143572..a097fe3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-10-25  Andreas Rottmann  <a.rottmann@gmx.at>
+
+       Bug 557786 - support fixed size arrays
+
+       * girepository/ginfo.c: Add g_type_info_get_array_fixed_size.
+       * giscanner/scannerparser.y: Retain fixed array size.
+       * giscanner/ast.py: Add to note.
+       * giscanner/girwriter.py: Write to gir.
+       * girepository/girnode.c: Write it to typelib.
+       * tools/generate.c: Generate.
+       * tests/*: Add tests.
+
 2008-10-25  Colin Walters  <walters@verbum.org>
 
        Bug 557076 - move typelibs to $libdir
index 0ad4759..3de0cf5 100644 (file)
@@ -830,6 +830,26 @@ g_type_info_get_array_length (GITypeInfo *info)
   return -1;
 }
 
+gint
+g_type_info_get_array_fixed_size (GITypeInfo *info)
+{
+  GIBaseInfo *base = (GIBaseInfo *)info;
+  SimpleTypeBlob *type = (SimpleTypeBlob *)&base->typelib->data[base->offset];
+  
+  if (!(type->reserved == 0 && type->reserved2 == 0))
+    {
+      ArrayTypeBlob *blob = (ArrayTypeBlob *)&base->typelib->data[base->offset];
+
+      if (blob->tag == GI_TYPE_TAG_ARRAY)
+       {
+         if (blob->has_size)
+           return blob->size;
+       }
+    }
+
+  return -1;
+}
+
 gboolean
 g_type_info_is_zero_terminated (GITypeInfo *info)
 {
index 1ab326b..103a099 100644 (file)
@@ -320,6 +320,7 @@ GITypeInfo *           g_type_info_get_param_type      (GITypeInfo *info,
                                                        gint       n);
 GIBaseInfo *           g_type_info_get_interface       (GITypeInfo *info);
 gint                   g_type_info_get_array_length    (GITypeInfo *info);
+gint                   g_type_info_get_array_fixed_size(GITypeInfo *info);
 gboolean               g_type_info_is_zero_terminated  (GITypeInfo *info);
 
 gint                   g_type_info_get_n_error_domains (GITypeInfo *info);
index fad4c28..632d5c3 100644 (file)
@@ -1114,6 +1114,8 @@ serialize_type (GIrModule    *module,
 
       if (node->has_length)
        g_string_append_printf (str, "length=%d", node->length);
+      else if (node->has_size)
+        g_string_append_printf (str, "fixed-size=%d", node->size);
       
       if (node->zero_terminated)
        g_string_append_printf (str, "%szero-terminated=1", 
@@ -1319,8 +1321,14 @@ g_ir_node_build_typelib (GIrNode    *node,
                      array->tag = type->tag;
                      array->zero_terminated = type->zero_terminated;
                      array->has_length = type->has_length;
+                      array->has_size = type->has_size;
                      array->reserved2 = 0;
-                     array->length = type->length;
+                      if (array->has_length)
+                        array->length = type->length;
+                      else if (array->has_size)
+                        array->size  = type->size;
+                      else
+                        array->length = -1;
                      
                      pos = *offset2 + 4;
                      *offset2 += 8;
index b816137..58b18c8 100644 (file)
@@ -119,6 +119,8 @@ struct _GIrNodeType
   gboolean zero_terminated;
   gboolean has_length;
   gint length;
+  gboolean has_size;
+  gint size;
   
   GIrNodeType *parameter_type1;
   GIrNodeType *parameter_type2;  
index b898db4..e355e61 100644 (file)
@@ -1514,6 +1514,7 @@ start_type (GMarkupParseContext *context,
     {
       const char *zero;
       const char *len;
+      const char *size;
 
       typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
 
@@ -1523,10 +1524,14 @@ start_type (GMarkupParseContext *context,
       
       zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
       len = find_attribute ("length", attribute_names, attribute_values);
-
+      size = find_attribute ("fixed-size", 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;
+      
+      typenode->has_size = size != NULL;
+      typenode->size = typenode->has_size ? atoi (size) : -1;
     }
   else
     {
index 3db620d..458d429 100644 (file)
@@ -206,9 +206,13 @@ typedef struct
 
   guint16 zero_terminated :1;
   guint16 has_length      :1;
-  guint16 reserved2       :6;
+  guint16 has_size        :1;
+  guint16 reserved2       :5;
 
-  guint16 length;
+  union {
+    guint16 length;
+    guint16 size;
+  };
 
   SimpleTypeBlob type;
 } ArrayTypeBlob;
index 6ee98c1..3d802df 100644 (file)
@@ -227,6 +227,7 @@ class Array(Type):
         self.zeroterminated = True
         self.length_param_index = -1
         self.length_param_name = None
+        self.size = None
 
     def __repr__(self):
         return 'Array(%r of %r)' % (self.name, self.element_type, )
index 5c8aa12..3de71bc 100644 (file)
@@ -176,6 +176,8 @@ class GIRWriter(XMLWriter):
             if ntype.length_param_index >= 0:
                 attrs.append(('length', '%d' % (ntype.length_param_index, )))
             attrs.append(('c:type', ntype.ctype))
+            if ntype.size is not None:
+                attrs.append(('fixed-size', ntype.size))
             with self.tagcontext('array', attrs):
                 self._write_type(ntype.element_type)
             return
index e3ca20e..64cf11b 100644 (file)
@@ -923,12 +923,12 @@ direct_declarator
        | direct_declarator '[' assignment_expression ']'
          {
                $$ = $1;
-               gi_source_symbol_merge_type ($$, gi_source_array_new ());
+               gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
          }
        | direct_declarator '[' ']'
          {
                $$ = $1;
-               gi_source_symbol_merge_type ($$, gi_source_array_new ());
+               gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
          }
        | direct_declarator '(' parameter_list ')'
          {
@@ -1059,22 +1059,22 @@ direct_abstract_declarator
        | '[' ']'
          {
                $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
-               gi_source_symbol_merge_type ($$, gi_source_array_new ());
+               gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
          }
        | '[' assignment_expression ']'
          {
                $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
-               gi_source_symbol_merge_type ($$, gi_source_array_new ());
+               gi_source_symbol_merge_type ($$, gi_source_array_new ($2));
          }
        | direct_abstract_declarator '[' ']'
          {
                $$ = $1;
-               gi_source_symbol_merge_type ($$, gi_source_array_new ());
+               gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
          }
        | direct_abstract_declarator '[' assignment_expression ']'
          {
                $$ = $1;
-               gi_source_symbol_merge_type ($$, gi_source_array_new ());
+               gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
          }
        | '(' ')'
          {
index ebdcf0d..c7bb57e 100644 (file)
@@ -163,9 +163,11 @@ gi_source_pointer_new (GISourceType * base_type)
 }
 
 GISourceType *
-gi_source_array_new (void)
+gi_source_array_new (GISourceSymbol *size)
 {
   GISourceType *array = gi_source_type_new (CTYPE_ARRAY);
+  if (size != NULL && size->type == CSYMBOL_TYPE_CONST && size->const_int_set)
+      array->child_list = g_list_append (array->child_list, size);
   return array;
 }
 
index 9ba8c52..02d2fac 100644 (file)
@@ -163,7 +163,6 @@ GISourceDirective * gi_source_directive_new            (const gchar            *name,
 void                gi_source_directive_free           (GISourceDirective  *directive);
 
 /* Private */
-GISourceType *      gi_source_array_new                (void);
 void                gi_source_scanner_add_symbol       (GISourceScanner  *scanner,
                                                        GISourceSymbol   *symbol);
 gboolean            gi_source_scanner_is_typedef       (GISourceScanner  *scanner,
@@ -178,7 +177,7 @@ GISourceType *          gi_source_struct_new               (const char       *name);
 GISourceType *             gi_source_union_new                (const char       *name);
 GISourceType *             gi_source_enum_new                 (const char       *name);
 GISourceType *             gi_source_pointer_new              (GISourceType     *base_type);
-GISourceType *             gi_source_array_new                (void);
+GISourceType *             gi_source_array_new                (GISourceSymbol   *size);
 GISourceType *             gi_source_function_new             (void);
 
 G_END_DECLS
index 925010a..c6c5bfa 100644 (file)
@@ -309,7 +309,14 @@ class Transformer(object):
             symbol.base_type.base_type.type == CTYPE_FUNCTION):
             node = self._create_callback(symbol)
         else:
-            ftype = self._create_type(symbol.base_type, {}, True)
+            opts = {}
+            if ctype == CTYPE_ARRAY:
+                opts['array'] = []
+                child_list = list(symbol.base_type.child_list)
+                if child_list:
+                    size_opt = 'fixed-size=%d' % (child_list[0].const_int, )
+                    opts['array'].append(size_opt)
+            ftype = self._create_type(symbol.base_type, opts, True)
             # Fields are assumed to be read-write
             # (except for Objects, see also glibtransformer.py)
             node = Field(symbol.ident, ftype, symbol.ident,
@@ -392,13 +399,16 @@ class Transformer(object):
                           ctype,
                           key_type, value_type)
         elif (ctype in default_array_types) or ('array' in options):
-            derefed_name = ctype[:-1] # strip the *
+            derefed_name = ctype[:-1] if ctype[-1] == '*' else ctype
             rettype = Array(ctype,
                             self._parse_ctype(derefed_name))
-            array_opts = options.get('array')
-            if array_opts:
-                (_, len_name) = array_opts[0].split('=')
-                rettype.length_param_name = len_name
+            array_opts = dict([opt.split('=')
+                               for opt in options.get('array', [])])
+            if 'length' in array_opts:
+                rettype.length_param_name = array_opts['length']
+            if 'fixed-size' in array_opts:
+                rettype.size = array_opts['fixed-size']
+                rettype.zeroterminated = False
         else:
             derefed_name = self._parse_ctype(ctype)
             rettype = Type(derefed_name, ctype)
index 05fb816..c01ec4c 100644 (file)
       <field name="bitfield2" writable="1" bits="2">
         <type name="uint" c:type="guint"/>
       </field>
+      <field name="data" writable="1">
+        <array zero-terminated="0" c:type="guint8" fixed-size="16">
+          <type name="uint8"/>
+        </array>
+      </field>
     </record>
     <union name="Union" c:type="UtilityUnion">
       <field name="pointer" writable="1">
index bb8cb44..924e0c0 100644 (file)
       <field name="bitfield2" writable="1" offset="0">
         <type name="uint"/>
       </field>
+      <field name="data" writable="1" offset="0">
+        <array fixed-size="16">
+          <type name="uint8"/>
+        </array>
+      </field>
     </record>
     <union name="Union">
       <field name="pointer" writable="1" offset="0">
index d1f581a..a592a96 100644 (file)
@@ -44,6 +44,7 @@ typedef struct
   int field;
   guint bitfield1 : 3;
   guint bitfield2 : 2;
+  guint8 data[16];
 } UtilityStruct;
 
 typedef union
index fad680f..c9b2f8a 100644 (file)
@@ -217,16 +217,19 @@ write_type_info (const gchar *namespace,
     }
   else if (tag == GI_TYPE_TAG_ARRAY)
     {
-      gint length;
-
+      gint length, size;
+      
       xml_start_element (file, "array");
 
       type = g_type_info_get_param_type (info, 0);
 
       length = g_type_info_get_array_length (info);
-      
       if (length >= 0)
-       xml_printf (file, " length=\"%d\"", length);
+        xml_printf (file, " length=\"%d\"", length);
+
+      size = g_type_info_get_array_fixed_size (info);
+      if (size >= 0)
+        xml_printf (file, " fixed-size=\"%d\"", size);
       
       if (g_type_info_is_zero_terminated (info))
        xml_printf (file, " zero-terminated=\"1\"");