summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--girepository/gdump.c83
-rw-r--r--girepository/gienuminfo.c17
-rw-r--r--girepository/gienuminfo.h1
-rw-r--r--girepository/girnode.c7
-rw-r--r--girepository/girnode.h1
-rw-r--r--girepository/girparser.c4
-rw-r--r--girepository/girwriter.c4
-rw-r--r--girepository/gitypelib-internal.h4
-rw-r--r--giscanner/ast.py11
-rw-r--r--giscanner/dumper.py26
-rw-r--r--giscanner/gdumpparser.py41
-rw-r--r--giscanner/girparser.py4
-rw-r--r--giscanner/girwriter.py4
-rw-r--r--giscanner/maintransformer.py6
-rwxr-xr-x[-rw-r--r--]giscanner/scannermain.py3
-rw-r--r--tests/scanner/Foo-1.0-expected.gir2
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"