+2008-08-23 Colin Walters <walters@verbum.org>
+
+ * girepository/girparser.c: Ignore <include>.
+ * giscanner/girparser.py: Parse them.
+ * giscanner/girwriter.py: Generate them.
+ * giscanner/transformer.py: Process <include>
+ recursively. Don't require full path for
+ includes, look in {$XDG_DATA_DIRS}/gir.
+ * tools/g-ir-scanner: Pass through includes.
+ * Makefile.am: Remove extra --include
+ args for scanner.
+ * *-expected.gir: Add expected includes.
+
2008-08-23 Johan Dahlin <johan@gnome.org>
* tests/scanner/Makefile.am:
--noclosure \
--output $@ \
--strip-prefix=g \
- --include=$(top_builddir)/gir/GLib.gir \
--include=$(top_builddir)/gir/GObject.gir \
--library=gio-2.0 \
-I$(GIO_INCLUDEDIR) \
STATE_START,
STATE_END,
STATE_REPOSITORY,
+ STATE_INCLUDE,
STATE_NAMESPACE,
- STATE_ENUM,
- STATE_BITFIELD, /* 5 */
+ STATE_ENUM, /* 5 */
+ STATE_BITFIELD,
STATE_FUNCTION,
STATE_FUNCTION_RETURN,
STATE_FUNCTION_PARAMETERS,
- STATE_FUNCTION_PARAMETER,
- STATE_CLASS, /* 10 */
+ STATE_FUNCTION_PARAMETER, /* 10 */
+ STATE_CLASS,
STATE_CLASS_FIELD,
STATE_CLASS_PROPERTY,
STATE_INTERFACE,
- STATE_INTERFACE_PROPERTY,
- STATE_INTERFACE_FIELD, /* 15 */
+ STATE_INTERFACE_PROPERTY, /* 15 */
+ STATE_INTERFACE_FIELD,
STATE_IMPLEMENTS,
STATE_REQUIRES,
STATE_BOXED,
- STATE_BOXED_FIELD,
- STATE_STRUCT, /* 20 */
+ STATE_BOXED_FIELD, /* 20 */
+ STATE_STRUCT,
STATE_STRUCT_FIELD,
STATE_ERRORDOMAIN,
STATE_UNION,
- STATE_UNION_FIELD,
- STATE_NAMESPACE_CONSTANT, /* 25 */
+ STATE_UNION_FIELD, /* 25 */
+ STATE_NAMESPACE_CONSTANT,
STATE_CLASS_CONSTANT,
STATE_INTERFACE_CONSTANT,
STATE_ALIAS,
break;
case 'i':
+ if (strcmp (element_name, "include") == 0 &&
+ ctx->state == STATE_REPOSITORY)
+ {
+ state_switch (ctx, STATE_INCLUDE);
+ goto out;
+ }
if (start_interface (context, element_name,
attribute_names, attribute_values,
ctx, error))
state_switch (ctx, STATE_END);
break;
+ case STATE_INCLUDE:
+ if (require_end_element (context, ctx, "include", element_name, error))
+ {
+ state_switch (ctx, STATE_REPOSITORY);
+ }
+ break;
+
case STATE_NAMESPACE:
if (require_end_element (context, ctx, "namespace", element_name, error))
{
def __init__(self, filename):
self._nodes = []
+ self._includes = set()
self._namespace_name = None
tree = parse(filename)
def get_namespace_name(self):
return self._namespace_name
+ def get_includes(self):
+ return self._includes
+
def get_nodes(self):
return self._nodes
def _parse_api(self, root):
assert root.tag == _corens('repository')
+ for node in root.getchildren():
+ if node.tag == _corens('include'):
+ self._includes.add(node.attrib['name'])
ns = root.find(_corens('namespace'))
assert ns is not None
self._namespace_name = ns.attrib['name']
class GIRWriter(XMLWriter):
- def __init__(self, namespace, shlib):
+ def __init__(self, namespace, shlib, includes):
super(GIRWriter, self).__init__()
- self._write_repository(namespace, shlib)
+ self._write_repository(namespace, shlib, includes)
- def _write_repository(self, namespace, shlib):
+ def _write_repository(self, namespace, shlib, includes=set()):
attrs = [
('version', '1.0'),
('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
]
with self.tagcontext('repository', attrs):
+ for include in includes:
+ self._write_include(include)
self._write_namespace(namespace, shlib)
+ def _write_include(self, include):
+ attrs = [('name', include)]
+ self.write_tag('include', attrs)
+
def _write_namespace(self, namespace, shlib):
attrs = [('name', namespace.name),
('shared-library', os.path.basename(shlib))]
# 02110-1301, USA.
#
+import os
+
from giscanner.ast import (Callback, Enum, Function, Namespace, Member,
Parameter, Return, Sequence, Struct, Field,
Type, Alias, Interface, Class, Node, Union,
from .odict import odict
from .utils import strip_common_prefix
+_xdg_data_dirs = [x for x in os.environ.get('XDG_DATA_DIRS', '').split(':') \
+ + ['/usr/share'] if x]
+
class SkipError(Exception):
pass
self._names = Names()
self._typedefs_ns = {}
self._strip_prefix = ''
+ self._includes = set()
+ self._includepaths = []
def get_names(self):
return self._names
+ def get_includes(self):
+ return self._includes
+
def set_strip_prefix(self, strip_prefix):
self._strip_prefix = strip_prefix
return self._namespace
def register_include(self, filename):
- if filename.endswith('.gir'):
+ (path, suffix) = os.path.splitext(filename)
+ name = os.path.basename(path)
+ if name in self._includes:
+ return
+ if suffix == '':
+ suffix = '.gir'
+ filename = path + suffix
+ if suffix == '.gir':
+ source = filename
+ if not os.path.exists(filename):
+ searchdirs = [os.path.join(d, 'gir') for d \
+ in _xdg_data_dirs]
+ searchdirs.extend(self._includepaths)
+ source = None
+ for d in searchdirs:
+ source = os.path.join(d, filename)
+ if os.path.exists(source):
+ break
+ source = None
+ if not source:
+ raise ValueError("Couldn't find include %r (search path: %r)"\
+ % (filename, searchdirs))
+ d = os.path.dirname(source)
+ if d not in self._includepaths:
+ self._includepaths.append(d)
+ self._includes.add(name)
from .girparser import GIRParser
- parser = GIRParser(filename)
- elif filename.endswith('.gidl'):
- from .gidlparser import GIDLParser
- parser = GIDLParser(filename)
+ parser = GIRParser(source)
else:
raise NotImplementedError(filename)
+ for include in parser.get_includes():
+ self.register_include(include)
nsname = parser.get_namespace_name()
for node in parser.get_nodes():
if isinstance(node, Alias):
%.gir: lib%.la %.c %.h utility.gir $(SCANNER) $(SCANNER_LIBS)
$(CHECK_DEBUG) $(SCANNER) -v \
- --include=$(top_srcdir)/gir/GLib.gir \
--include=$(top_srcdir)/gir/GObject.gir \
--include=$(top_builddir)/tests/scanner/utility.gir \
--library=$< \
utility.gir: libutility.la utility.h $(SCANNER) $(SCANNER_LIBS)
$(CHECK_DEBUG) $(SCANNER) -v \
- --include=$(top_srcdir)/gir/GLib.gir \
--include=$(top_srcdir)/gir/GObject.gir \
--library=$< \
--namespace=$* \
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+ <include name="GLib"/>
+ <include name="GObject"/>
<namespace name="annotation" shared-library="libannotation.la">
<record name="Object" c:type="AnnotationObject">
<field name="parent_instance">
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+ <include name="GLib"/>
+ <include name="GObject"/>
<namespace name="drawable" shared-library="libdrawable.la">
<class name="TestDrawable"
c:type="TestDrawable"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+ <include name="GLib"/>
+ <include name="GObject"/>
+ <include name="utility"/>
<namespace name="foo" shared-library="libfoo.la">
<alias name="List" target="GLib.SList" c:type="FooList"/>
<alias name="XEvent" target="none" c:type="FooXEvent"/>
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+ <include name="GLib"/>
+ <include name="GObject"/>
<namespace name="utility" shared-library="libutility.la">
<class name="Object"
c:type="UtilityObject"
namespace = glibtransformer.parse()
# Write out AST
- writer = Writer(namespace, primary_library)
+ writer = Writer(namespace, primary_library, transformer.get_includes())
data = writer.get_xml()
if options.output:
fd = open(options.output, "w")