summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--girepository/ginfo.c20
-rw-r--r--girepository/girepository.h1
-rw-r--r--girepository/girnode.c10
-rw-r--r--girepository/girnode.h2
-rw-r--r--girepository/girparser.c7
-rw-r--r--girepository/gtypelib.h8
-rw-r--r--giscanner/ast.py1
-rw-r--r--giscanner/girwriter.py2
-rw-r--r--giscanner/scannerparser.y12
-rw-r--r--giscanner/sourcescanner.c4
-rw-r--r--giscanner/sourcescanner.h3
-rw-r--r--giscanner/transformer.py22
-rw-r--r--tests/scanner/utility-1.0-expected.gir5
-rw-r--r--tests/scanner/utility-1.0-expected.tgir5
-rw-r--r--tests/scanner/utility.h1
-rw-r--r--tools/generate.c11
17 files changed, 103 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 01435727..a097fe3a 100644
--- 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
diff --git a/girepository/ginfo.c b/girepository/ginfo.c
index 0ad4759c..3de0cf59 100644
--- a/girepository/ginfo.c
+++ b/girepository/ginfo.c
@@ -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)
{
diff --git a/girepository/girepository.h b/girepository/girepository.h
index 1ab326b7..103a099d 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -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);
diff --git a/girepository/girnode.c b/girepository/girnode.c
index fad4c28c..632d5c34 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -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;
diff --git a/girepository/girnode.h b/girepository/girnode.h
index b8161375..58b18c8d 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -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;
diff --git a/girepository/girparser.c b/girepository/girparser.c
index b898db4f..e355e618 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -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
{
diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h
index 3db620d9..458d429d 100644
--- a/girepository/gtypelib.h
+++ b/girepository/gtypelib.h
@@ -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;
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 6ee98c1f..3d802df9 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -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, )
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 5c8aa12b..3de71bcd 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -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
diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y
index e3ca20e2..64cf11b3 100644
--- a/giscanner/scannerparser.y
+++ b/giscanner/scannerparser.y
@@ -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));
}
| '(' ')'
{
diff --git a/giscanner/sourcescanner.c b/giscanner/sourcescanner.c
index ebdcf0d5..c7bb57e0 100644
--- a/giscanner/sourcescanner.c
+++ b/giscanner/sourcescanner.c
@@ -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;
}
diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h
index 9ba8c520..02d2facd 100644
--- a/giscanner/sourcescanner.h
+++ b/giscanner/sourcescanner.h
@@ -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
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 925010a5..c6c5bfa7 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -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)
diff --git a/tests/scanner/utility-1.0-expected.gir b/tests/scanner/utility-1.0-expected.gir
index 05fb8161..c01ec4cb 100644
--- a/tests/scanner/utility-1.0-expected.gir
+++ b/tests/scanner/utility-1.0-expected.gir
@@ -41,6 +41,11 @@
<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">
diff --git a/tests/scanner/utility-1.0-expected.tgir b/tests/scanner/utility-1.0-expected.tgir
index bb8cb441..924e0c01 100644
--- a/tests/scanner/utility-1.0-expected.tgir
+++ b/tests/scanner/utility-1.0-expected.tgir
@@ -36,6 +36,11 @@
<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">
diff --git a/tests/scanner/utility.h b/tests/scanner/utility.h
index d1f581a0..a592a96d 100644
--- a/tests/scanner/utility.h
+++ b/tests/scanner/utility.h
@@ -44,6 +44,7 @@ typedef struct
int field;
guint bitfield1 : 3;
guint bitfield2 : 2;
+ guint8 data[16];
} UtilityStruct;
typedef union
diff --git a/tools/generate.c b/tools/generate.c
index fad680f5..c9b2f8a1 100644
--- a/tools/generate.c
+++ b/tools/generate.c
@@ -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\"");