diff options
-rw-r--r-- | girepository/gdump.c | 83 | ||||
-rw-r--r-- | girepository/gienuminfo.c | 17 | ||||
-rw-r--r-- | girepository/gienuminfo.h | 1 | ||||
-rw-r--r-- | girepository/girnode.c | 7 | ||||
-rw-r--r-- | girepository/girnode.h | 1 | ||||
-rw-r--r-- | girepository/girparser.c | 4 | ||||
-rw-r--r-- | girepository/girwriter.c | 4 | ||||
-rw-r--r-- | girepository/gitypelib-internal.h | 4 | ||||
-rw-r--r-- | giscanner/ast.py | 11 | ||||
-rw-r--r-- | giscanner/dumper.py | 26 | ||||
-rw-r--r-- | giscanner/gdumpparser.py | 41 | ||||
-rw-r--r-- | giscanner/girparser.py | 4 | ||||
-rw-r--r-- | giscanner/girwriter.py | 4 | ||||
-rw-r--r-- | giscanner/maintransformer.py | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | giscanner/scannermain.py | 3 | ||||
-rw-r--r-- | tests/scanner/Foo-1.0-expected.gir | 2 |
16 files changed, 177 insertions, 41 deletions
diff --git a/girepository/gdump.c b/girepository/gdump.c index cb6e7419..e607f323 100644 --- a/girepository/gdump.c +++ b/girepository/gdump.c @@ -70,6 +70,7 @@ goutput_write (GOutputStream *out, const char *str) } typedef GType (*GetTypeFunc)(void); +typedef GQuark (*ErrorQuarkFunc)(void); static GType invoke_get_type (GModule *self, const char *symbol, GError **error) @@ -97,6 +98,23 @@ invoke_get_type (GModule *self, const char *symbol, GError **error) return ret; } +static GQuark +invoke_error_quark (GModule *self, const char *symbol, GError **error) +{ + ErrorQuarkFunc sym; + + if (!g_module_symbol (self, symbol, (void**)&sym)) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Failed to find symbol '%s'", symbol); + return G_TYPE_INVALID; + } + + return sym (); +} + static void dump_properties (GType type, GOutputStream *out) { @@ -365,6 +383,13 @@ dump_type (GType type, const char *symbol, GOutputStream *out) } } +static void +dump_error_quark (GQuark quark, const char *symbol, GOutputStream *out) +{ + escaped_printf (out, " <error-quark function=\"%s\" domain=\"%s\"/>\n", + symbol, g_quark_to_string (quark)); +} + /** * g_irepository_dump: * @arg: Comma-separated pair of input and output filenames @@ -437,29 +462,55 @@ g_irepository_dump (const char *arg, GError **error) { gsize len; char *line = g_data_input_stream_read_line (in, &len, NULL, NULL); - GType type; + const char *function; if (line == NULL || *line == '\0') - { - g_free (line); - break; - } + { + g_free (line); + break; + } g_strchomp (line); - type = invoke_get_type (self, line, error); - if (type == G_TYPE_INVALID) - { - caught_error = TRUE; - g_free (line); - break; - } + if (strncmp (line, "get-type:", strlen ("get-type:")) == 0) + { + GType type; - if (g_hash_table_lookup (output_types, (gpointer) type)) - goto next; - g_hash_table_insert (output_types, (gpointer) type, (gpointer) type); + function = line + strlen ("get-type:"); + + type = invoke_get_type (self, function, error); + + if (type == G_TYPE_INVALID) + { + g_printerr ("Invalid GType function: '%s'\n", function); + caught_error = TRUE; + g_free (line); + break; + } + + if (g_hash_table_lookup (output_types, (gpointer) type)) + goto next; + g_hash_table_insert (output_types, (gpointer) type, (gpointer) type); + + dump_type (type, function, G_OUTPUT_STREAM (output)); + } + else if (strncmp (line, "error-quark:", strlen ("error-quark:")) == 0) + { + GQuark quark; + function = line + strlen ("error-quark:"); + quark = invoke_error_quark (self, function, error); + + if (quark == 0) + { + g_printerr ("Invalid error quark function: '%s'\n", function); + caught_error = TRUE; + g_free (line); + break; + } + + dump_error_quark (quark, function, G_OUTPUT_STREAM (output)); + } - dump_type (type, line, G_OUTPUT_STREAM (output)); next: g_free (line); diff --git a/girepository/gienuminfo.c b/girepository/gienuminfo.c index 062f3abf..338a46ee 100644 --- a/girepository/gienuminfo.c +++ b/girepository/gienuminfo.c @@ -66,6 +66,23 @@ g_enum_info_get_n_values (GIEnumInfo *info) return blob->n_values; } +const gchar * +g_enum_info_get_error_domain (GIEnumInfo *info) +{ + GIRealInfo *rinfo = (GIRealInfo *)info; + EnumBlob *blob; + + g_return_val_if_fail (info != NULL, 0); + g_return_val_if_fail (GI_IS_ENUM_INFO (info), 0); + + blob = (EnumBlob *)&rinfo->typelib->data[rinfo->offset]; + + if (blob->error_domain) + return g_typelib_get_string (rinfo->typelib, blob->error_domain); + else + return NULL; +} + /** * g_enum_info_get_value: * @info: a #GIEnumInfo diff --git a/girepository/gienuminfo.h b/girepository/gienuminfo.h index 6b24fe7e..fc0f3c84 100644 --- a/girepository/gienuminfo.h +++ b/girepository/gienuminfo.h @@ -41,6 +41,7 @@ gint g_enum_info_get_n_values (GIEnumInfo *info); GIValueInfo * g_enum_info_get_value (GIEnumInfo *info, gint n); GITypeTag g_enum_info_get_storage_type (GIEnumInfo *info); +const gchar * g_enum_info_get_error_domain (GIEnumInfo *info); gint64 g_value_info_get_value (GIValueInfo *info); diff --git a/girepository/girnode.c b/girepository/girnode.c index 1c51bfd4..166ca30a 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -328,6 +328,7 @@ _g_ir_node_free (GIrNode *node) g_free (node->name); g_free (enum_->gtype_name); g_free (enum_->gtype_init); + g_free (enum_->error_domain); for (l = enum_->values; l; l = l->next) _g_ir_node_free ((GIrNode *)l->data); @@ -712,6 +713,8 @@ _g_ir_node_get_full_size_internal (GIrNode *parent, size += ALIGN_VALUE (strlen (enum_->gtype_name) + 1, 4); size += ALIGN_VALUE (strlen (enum_->gtype_init) + 1, 4); } + if (enum_->error_domain) + size += ALIGN_VALUE (strlen (enum_->error_domain) + 1, 4); for (l = enum_->values; l; l = l->next) size += _g_ir_node_get_full_size_internal (node, (GIrNode *)l->data); @@ -2021,6 +2024,10 @@ _g_ir_node_build_typelib (GIrNode *node, blob->gtype_name = 0; blob->gtype_init = 0; } + if (enum_->error_domain) + blob->error_domain = _g_ir_write_string (enum_->error_domain, strings, data, offset2); + else + blob->error_domain = 0; blob->n_values = 0; blob->reserved2 = 0; diff --git a/girepository/girnode.h b/girepository/girnode.h index fb2616b1..6e03821b 100644 --- a/girepository/girnode.h +++ b/girepository/girnode.h @@ -285,6 +285,7 @@ struct _GIrNodeEnum gchar *gtype_name; gchar *gtype_init; + gchar *error_domain; GList *values; }; diff --git a/girepository/girparser.c b/girepository/girparser.c index 4e552725..c9b7d629 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -1332,6 +1332,7 @@ start_enum (GMarkupParseContext *context, const gchar *typename; const gchar *typeinit; const gchar *deprecated; + const gchar *error_domain; GIrNodeEnum *enum_; if (!((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) || @@ -1344,6 +1345,7 @@ start_enum (GMarkupParseContext *context, name = find_attribute ("name", attribute_names, attribute_values); typename = find_attribute ("glib:type-name", attribute_names, attribute_values); typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values); + error_domain = find_attribute ("glib:error-domain", attribute_names, attribute_values); deprecated = find_attribute ("deprecated", attribute_names, attribute_values); if (name == NULL) @@ -1361,6 +1363,8 @@ start_enum (GMarkupParseContext *context, ((GIrNode *)enum_)->name = g_strdup (name); enum_->gtype_name = g_strdup (typename); enum_->gtype_init = g_strdup (typeinit); + enum_->error_domain = g_strdup (error_domain); + if (deprecated) enum_->deprecated = TRUE; else diff --git a/girepository/girwriter.c b/girepository/girwriter.c index 2cdc9a11..d9f916c5 100644 --- a/girepository/girwriter.c +++ b/girepository/girwriter.c @@ -805,6 +805,7 @@ write_enum_info (const gchar *namespace, const gchar *name; const gchar *type_name; const gchar *type_init; + const gchar *error_domain; gboolean deprecated; gint i; @@ -813,6 +814,7 @@ write_enum_info (const gchar *namespace, type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info); type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info); + error_domain = g_enum_info_get_error_domain (info); if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM) xml_start_element (file, "enumeration"); @@ -822,6 +824,8 @@ write_enum_info (const gchar *namespace, if (type_init) xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init); + if (error_domain) + xml_printf (file, " glib:error-domain=\"%s\"", error_domain); if (deprecated) xml_printf (file, " deprecated=\"1\""); diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h index 2bda8d9d..49fbe4e3 100644 --- a/girepository/gitypelib-internal.h +++ b/girepository/gitypelib-internal.h @@ -798,6 +798,8 @@ typedef struct { * (will be a signed or unsigned integral type) * @gtype_name: String name of the associated #GType * @gtype_init: String naming the symbol which gets the runtime #GType + * @error_domain: String naming the #GError domain this enum is + * associated with * @n_values: The lengths of the values arrays. * @values: Describes the enum values. */ @@ -817,7 +819,7 @@ typedef struct { guint16 n_values; guint16 reserved2; - guint32 reserved3; + guint32 error_domain; ValueBlob values[]; } EnumBlob; diff --git a/giscanner/ast.py b/giscanner/ast.py index d4780f9e..bd56aef3 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -569,6 +569,13 @@ class Function(Callable): self.shadows = None # C symbol string +class ErrorQuarkFunction(Function): + + def __init__(self, name, retval, parameters, throws, symbol, error_domain): + Function.__init__(self, name, retval, parameters, throws, symbol) + self.error_domain = error_domain + + class VFunction(Callable): def __init__(self, name, retval, parameters, throws): @@ -704,8 +711,8 @@ class Enum(Node, Registered): self.c_symbol_prefix = c_symbol_prefix self.ctype = ctype self.members = members - # Associated error quark - self.error_quark = None + # Associated error domain name + self.error_domain = None class Bitfield(Node, Registered): diff --git a/giscanner/dumper.py b/giscanner/dumper.py index 615b3fc5..61cba257 100644 --- a/giscanner/dumper.py +++ b/giscanner/dumper.py @@ -76,9 +76,10 @@ class LinkerError(Exception): class DumpCompiler(object): - def __init__(self, options, get_type_functions): + def __init__(self, options, get_type_functions, error_quark_functions): self._options = options self._get_type_functions = get_type_functions + self._error_quark_functions = error_quark_functions self._compiler_cmd = os.environ.get('CC', 'gcc') self._linker_cmd = os.environ.get('CC', self._compiler_cmd) @@ -114,9 +115,9 @@ class DumpCompiler(object): f = open(c_path, 'w') f.write(_PROGRAM_TEMPLATE % tpl_args) - # We need to reference our get_type functions to make sure they are - # pulled in at the linking stage if the library is a static library - # rather than a shared library. + # We need to reference our get_type and error_quark functions + # to make sure they are pulled in at the linking stage if the + # library is a static library rather than a shared library. if len(self._get_type_functions) > 0: for func in self._get_type_functions: f.write("extern GType " + func + "(void);\n") @@ -129,6 +130,18 @@ class DumpCompiler(object): f.write(",\n") f.write(" " + func) f.write("\n};\n") + if len(self._error_quark_functions) > 0: + for func in self._error_quark_functions: + f.write("extern GQuark " + func + "(void);\n") + f.write("GQuark (*GI_ERROR_QUARK_FUNCS_[])(void) = {\n") + first = True + for func in self._error_quark_functions: + if first: + first = False + else: + f.write(",\n") + f.write(" " + func) + f.write("\n};\n") f.close() o_path = self._generate_tempfile(tmpdir, '.o') @@ -271,6 +284,7 @@ class DumpCompiler(object): else: args.append('-l' + library) -def compile_introspection_binary(options, get_type_functions): - dc = DumpCompiler(options, get_type_functions) +def compile_introspection_binary(options, get_type_functions, + error_quark_functions): + dc = DumpCompiler(options, get_type_functions, error_quark_functions) return dc.run() diff --git a/giscanner/gdumpparser.py b/giscanner/gdumpparser.py index 87621bc9..35fea72b 100644 --- a/giscanner/gdumpparser.py +++ b/giscanner/gdumpparser.py @@ -68,7 +68,8 @@ class GDumpParser(object): self._namespace = transformer.namespace self._binary = None self._get_type_functions = [] - self._gtype_data = {} + self._error_quark_functions = [] + self._error_domains = {} self._boxed_types = {} self._private_internal_types = {} @@ -94,6 +95,9 @@ class GDumpParser(object): def get_get_type_functions(self): return self._get_type_functions + def get_error_quark_functions(self): + return self._error_quark_functions + def set_introspection_binary(self, binary): self._binary = binary @@ -105,9 +109,10 @@ class GDumpParser(object): tree = self._execute_binary_get_tree() root = tree.getroot() for child in root: - self._gtype_data[child.attrib['name']] = child - for child in root: - self._introspect_type(child) + if child.tag == 'error-quark': + self._introspect_error_quark(child) + else: + self._introspect_type(child) # Pair up boxed types and class records for name, boxed in self._boxed_types.iteritems(): @@ -138,10 +143,14 @@ class GDumpParser(object): def _execute_binary_get_tree(self): """Load the library (or executable), returning an XML blob containing data gleaned from GObject's primitive introspection.""" - in_path = os.path.join(self._binary.tmpdir, 'types.txt') + in_path = os.path.join(self._binary.tmpdir, 'functions.txt') f = open(in_path, 'w') - # TODO: Introspect GQuark functions for func in self._get_type_functions: + f.write('get-type:') + f.write(func) + f.write('\n') + for func in self._error_quark_functions: + f.write('error-quark:') f.write(func) f.write('\n') f.close() @@ -209,6 +218,8 @@ blob containing data gleaned from GObject's primitive introspection.""" return elif (symbol.endswith('_get_type') or symbol.endswith('_get_gtype')): self._initparse_get_type_function(func) + elif symbol.endswith('_error_quark'): + self._initparse_error_quark_function(func) def _initparse_get_type_function(self, func): if func.symbol in ('g_object_get_type', @@ -229,6 +240,12 @@ blob containing data gleaned from GObject's primitive introspection.""" self._get_type_functions.append(func.symbol) return True + def _initparse_error_quark_function(self, func): + if (func.retval.type.ctype != 'GQuark'): + return False + self._error_quark_functions.append(func.symbol) + return True + def _initparse_gobject_record(self, record): # Special handling for when we're parsing GObject / GLib if record.name in ('Object', 'InitiallyUnowned', 'ParamSpec'): @@ -495,6 +512,18 @@ different --identifier-prefix.""" % (xmlnode.attrib['name'], self._namespace.ide # (see also _find_class_record and transformer.py) field.writable = False + def _introspect_error_quark(self, xmlnode): + symbol = xmlnode.attrib['function'] + error_domain = xmlnode.attrib['domain'] + function = self._namespace.get_by_symbol(symbol) + if function is None: + return + + node = ast.ErrorQuarkFunction(function.name, function.retval, + function.parameters, function.throws, + function.symbol, error_domain) + self._namespace.append(node, replace=True) + def _pair_boxed_type(self, boxed): try: name = self._transformer.strip_identifier(boxed.gtype_name) diff --git a/giscanner/girparser.py b/giscanner/girparser.py index bcf68bfd..45a93ed6 100644 --- a/giscanner/girparser.py +++ b/giscanner/girparser.py @@ -536,7 +536,7 @@ class GIRParser(object): ctype = node.attrib.get(_cns('type')) get_type = node.attrib.get(_glibns('get-type')) type_name = node.attrib.get(_glibns('type-name')) - glib_error_quark = node.attrib.get(_glibns('error-quark')) + glib_error_domain = node.attrib.get(_glibns('error-domain')) if node.tag == _corens('bitfield'): klass = ast.Bitfield else: @@ -546,7 +546,7 @@ class GIRParser(object): members=members, gtype_name=type_name, get_type=get_type) - obj.error_quark = glib_error_quark + obj.error_domain = glib_error_domain obj.ctype = ctype self._parse_generic_attribs(node, obj) self._namespace.append(obj) diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index 4a6c47e0..1da2417d 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -328,8 +328,8 @@ and/or use gtk-doc annotations. ''') self._append_node_generic(enum, attrs) self._append_registered(enum, attrs) attrs.append(('c:type', enum.ctype)) - if enum.error_quark: - attrs.append(('glib:error-quark', enum.error_quark)) + if enum.error_domain: + attrs.append(('glib:error-domain', enum.error_domain)) with self.tagcontext('enumeration', attrs): self._write_generic(enum) diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py index 34d17b44..d2d1f2d8 100644 --- a/giscanner/maintransformer.py +++ b/giscanner/maintransformer.py @@ -858,9 +858,7 @@ the ones that failed to resolve removed.""" uscore_enums[no_uscore_prefixed] = enum for node in self._namespace.itervalues(): - if not isinstance(node, ast.Function): - continue - if node.retval.type.target_giname != 'GLib.Quark': + if not isinstance(node, ast.ErrorQuarkFunction): continue short = node.symbol[:-len('_quark')] if short == "g_io_error": @@ -872,7 +870,7 @@ the ones that failed to resolve removed.""" if enum is None: enum = uscore_enums.get(short) if enum is not None: - enum.error_quark = node.symbol + enum.error_domain = node.error_domain else: message.warn_node(node, """%s: Couldn't find corresponding enumeration""" % (node.symbol, )) diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py index 52ee4cc0..3c1386a9 100644..100755 --- a/giscanner/scannermain.py +++ b/giscanner/scannermain.py @@ -300,7 +300,8 @@ def create_binary(transformer, options, args): binary = IntrospectionBinary(args) else: binary = compile_introspection_binary(options, - gdump_parser.get_get_type_functions()) + gdump_parser.get_get_type_functions(), + gdump_parser.get_error_quark_functions()) shlibs = resolve_shlibs(options, binary, options.libraries) gdump_parser.set_introspection_binary(binary) diff --git a/tests/scanner/Foo-1.0-expected.gir b/tests/scanner/Foo-1.0-expected.gir index 8b9dc387..cc4c8d7a 100644 --- a/tests/scanner/Foo-1.0-expected.gir +++ b/tests/scanner/Foo-1.0-expected.gir @@ -191,7 +191,7 @@ and/or use gtk-doc annotations. --> glib:type-name="FooError" glib:get-type="foo_error_get_type" c:type="FooError" - glib:error-quark="foo_error_quark"> + glib:error-domain="foo-error-quark"> <member name="good" value="0" c:identifier="FOO_ERROR_GOOD" |