summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--giscanner/ast.py11
-rw-r--r--giscanner/girwriter.py14
-rw-r--r--giscanner/glibtransformer.py20
-rw-r--r--giscanner/transformer.py37
-rw-r--r--tests/scanner/Foo-expected.gir12
6 files changed, 96 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index b9cbf8f6..e630a525 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2008-08-19 Johan Dahlin <johan@gnome.org>
+ * giscanner/ast.py:
+ * giscanner/girwriter.py:
+ * giscanner/glibtransformer.py:
+ * giscanner/transformer.py:
+ * tests/scanner/Foo-expected.gir:
+ Add basic support for union, base the code much
+ on Struct. Add a testcase.
+
+2008-08-19 Johan Dahlin <johan@gnome.org>
+
* tests/scanner/Foo-expected.gir:
* tests/scanner/foo-object.h:
Add a union testcase which the compiler currently
diff --git a/giscanner/ast.py b/giscanner/ast.py
index bde22ad0..7d2e7667 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -306,3 +306,14 @@ class Sequence(Type):
def __repr__(self):
return 'Sequence(%r of %r)' % (self.name, self.element_type, )
+
+
+class Union(Node):
+
+ def __init__(self, name, symbol):
+ Node.__init__(self, name)
+ self.fields = []
+ self.symbol = symbol
+
+ def __repr__(self):
+ return 'Union(%r, %r)' % (self.name, self.fields, )
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 996893e3..a5e8ffc2 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -21,7 +21,7 @@
from __future__ import with_statement
from .ast import (Callback, Class, Enum, Function, Interface, Member,
- Sequence, Struct, Alias)
+ Sequence, Struct, Alias, Union)
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
GLibFlags, GLibObject, GLibInterface)
from .xmlwriter import XMLWriter
@@ -62,6 +62,8 @@ class GIRWriter(XMLWriter):
self._write_callback(node)
elif isinstance(node, Struct):
self._write_record(node)
+ elif isinstance(node, Union):
+ self._write_union(node)
elif isinstance(node, Member):
# FIXME: atk_misc_instance singleton
pass
@@ -227,6 +229,16 @@ class GIRWriter(XMLWriter):
else:
self.write_tag('record', attrs)
+ def _write_union(self, union):
+ attrs = [('name', union.name),
+ ('c:type', union.symbol)]
+ if union.fields:
+ with self.tagcontext('union', attrs):
+ for field in union.fields:
+ self._write_field(field)
+ else:
+ self.write_tag('union', attrs)
+
def _write_field(self, field):
# FIXME: Just function
if isinstance(field, (Callback, Function)):
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 52651564..266f5038 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -23,7 +23,7 @@ import ctypes
from . import cgobject
from .ast import (Callback, Enum, Function, Member, Namespace, Parameter,
Sequence, Property, Return, Struct, Type, Alias,
- type_name_from_ctype)
+ Union, type_name_from_ctype)
from .transformer import Names
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
GLibInterface, GLibObject, GLibSignal, type_names)
@@ -160,8 +160,10 @@ class GLibTransformer(object):
elif isinstance(node, Member):
# FIXME: atk_misc_instance singletons
pass
+ elif isinstance(node, Union):
+ self._parse_union(node)
else:
- print 'GOBJECT BUILDER: Unhandled node:', node
+ print 'GLIB Transformer: Unhandled node:', node
def _parse_alias(self, alias):
self._names.aliases[alias.name] = (None, alias)
@@ -277,6 +279,14 @@ class GLibTransformer(object):
(ns, node) = node
node.fields = struct.fields[:]
+ def _parse_union(self, union):
+ node = self._names.names.get(union.name)
+ if node is None:
+ self._add_attribute(union, replace=True)
+ return
+ (ns, node) = node
+ node.fields = union.fields[:]
+
def _parse_callback(self, callback):
self._add_attribute(callback)
@@ -489,6 +499,8 @@ class GLibTransformer(object):
self._resolve_glib_boxed(node)
elif isinstance(node, Struct):
self._resolve_struct(node)
+ elif isinstance(node, Union):
+ self._resolve_union(node)
elif isinstance(node, Alias):
self._resolve_alias(node)
@@ -496,6 +508,10 @@ class GLibTransformer(object):
for field in node.fields:
self._resolve_field(field)
+ def _resolve_union(self, node):
+ for field in node.fields:
+ self._resolve_field(field)
+
def _resolve_parent(self, node):
if not isinstance(node, (GLibInterface, GLibObject)):
raise AssertionError
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 3b117fff..89bdf28f 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -20,7 +20,7 @@
from giscanner.ast import (Callback, Enum, Function, Namespace, Member,
Parameter, Return, Sequence, Struct, Field,
- Type, Alias, Interface, Class, Node,
+ Type, Alias, Interface, Class, Node, Union,
type_name_from_ctype, type_names)
from .glibast import GLibBoxed
from giscanner.sourcescanner import (
@@ -149,8 +149,7 @@ class Transformer(object):
elif stype == CSYMBOL_TYPE_MEMBER:
return self._create_member(symbol)
elif stype == CSYMBOL_TYPE_UNION:
- # Unions are not supported
- pass
+ return self._create_union(symbol)
else:
raise NotImplementedError(
'Transformer: unhandled symbol: %r' % (symbol, ))
@@ -227,12 +226,13 @@ class Transformer(object):
node = self._create_callback(symbol)
elif ctype == CTYPE_STRUCT:
node = self._create_typedef_struct(symbol)
+ elif ctype == CTYPE_UNION:
+ node = self._create_typedef_union(symbol)
elif ctype == CTYPE_ENUM:
return self._create_enum(symbol)
elif ctype in (CTYPE_TYPEDEF,
CTYPE_POINTER,
CTYPE_BASIC_TYPE,
- CTYPE_UNION,
CTYPE_VOID):
if symbol.base_type.name:
name = self.strip_namespace_object(symbol.ident)
@@ -308,6 +308,13 @@ class Transformer(object):
self._typedefs_ns[symbol.ident] = struct
return struct
+ def _create_typedef_union(self, symbol):
+ name = self._remove_prefix(symbol.ident)
+ name = self.strip_namespace_object(name)
+ union = Union(name, symbol.ident)
+ self._typedefs_ns[symbol.ident] = union
+ return union
+
def _create_struct(self, symbol):
struct = self._typedefs_ns.get(symbol.ident, None)
if struct is None:
@@ -330,6 +337,28 @@ class Transformer(object):
return struct
+ def _create_union(self, symbol):
+ union = self._typedefs_ns.get(symbol.ident, None)
+ if union is None:
+ # This is a bit of a hack; really we should try
+ # to resolve through the typedefs to find the real
+ # name
+ if symbol.ident.startswith('_'):
+ name = symbol.ident[1:]
+ else:
+ name = symbol.ident
+ name = self._remove_prefix(name)
+ name = self.strip_namespace_object(name)
+ name = self.resolve_type_name(name)
+ union = Union(name, symbol.ident)
+
+ for child in symbol.base_type.child_list:
+ field = self._traverse_one(child)
+ if field:
+ union.fields.append(field)
+
+ return union
+
def _create_callback(self, symbol):
parameters = self._create_parameters(symbol.base_type.base_type)
retval = self._create_return(symbol.base_type.base_type.base_type)
diff --git a/tests/scanner/Foo-expected.gir b/tests/scanner/Foo-expected.gir
index 7ff7c5d8..ce0854be 100644
--- a/tests/scanner/Foo-expected.gir
+++ b/tests/scanner/Foo-expected.gir
@@ -4,7 +4,6 @@
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<namespace name="Foo">
<alias name="List" target="GSList" c:type="FooList"/>
- <alias name="Event" target="Event" c:type="FooEvent"/>
<interface name="Interface"
c:type="FooInterface"
glib:type-name="FooInterface"
@@ -420,5 +419,16 @@
<type name="int" c:type="gint"/>
</field>
</record>
+ <union name="Event" c:type="FooEvent">
+ <field name="type">
+ <type name="int" c:type="int"/>
+ </field>
+ <field name="any">
+ <type name="EventAny" c:type="FooEventAny"/>
+ </field>
+ <field name="expose">
+ <type name="EventExpose" c:type="FooEventExpose"/>
+ </field>
+ </union>
</namespace>
</repository>