From d15f8cde47100a77189d5febb8704c0e4d736594 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 25 Oct 2008 15:20:54 +0000 Subject: [PATCH] Bug 557786 - support fixed size arrays svn path=/trunk/; revision=814 --- ChangeLog | 12 ++++++++++++ girepository/ginfo.c | 20 ++++++++++++++++++++ girepository/girepository.h | 1 + girepository/girnode.c | 10 +++++++++- girepository/girnode.h | 2 ++ girepository/girparser.c | 7 ++++++- girepository/gtypelib.h | 8 ++++++-- giscanner/ast.py | 1 + giscanner/girwriter.py | 2 ++ giscanner/scannerparser.y | 12 ++++++------ giscanner/sourcescanner.c | 4 +++- giscanner/sourcescanner.h | 3 +-- giscanner/transformer.py | 22 ++++++++++++++++------ tests/scanner/utility-1.0-expected.gir | 5 +++++ tests/scanner/utility-1.0-expected.tgir | 5 +++++ tests/scanner/utility.h | 1 + tools/generate.c | 11 +++++++---- 17 files changed, 103 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0143572..a097fe3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-10-25 Andreas Rottmann + + 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 Bug 557076 - move typelibs to $libdir diff --git a/girepository/ginfo.c b/girepository/ginfo.c index 0ad4759..3de0cf5 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 1ab326b..103a099 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 fad4c28..632d5c3 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 b816137..58b18c8 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 b898db4..e355e61 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 3db620d..458d429 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 6ee98c1..3d802df 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 5c8aa12..3de71bc 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 e3ca20e..64cf11b 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 ebdcf0d..c7bb57e 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 9ba8c52..02d2fac 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 925010a..c6c5bfa 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 05fb816..c01ec4c 100644 --- a/tests/scanner/utility-1.0-expected.gir +++ b/tests/scanner/utility-1.0-expected.gir @@ -41,6 +41,11 @@ + + + + + diff --git a/tests/scanner/utility-1.0-expected.tgir b/tests/scanner/utility-1.0-expected.tgir index bb8cb44..924e0c0 100644 --- a/tests/scanner/utility-1.0-expected.tgir +++ b/tests/scanner/utility-1.0-expected.tgir @@ -36,6 +36,11 @@ + + + + + diff --git a/tests/scanner/utility.h b/tests/scanner/utility.h index d1f581a..a592a96 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 fad680f..c9b2f8a 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\""); -- 2.7.4