Ignore <include>. Parse them. Generate them. Process <include>
authorColin Walters <walters@verbum.org>
Sat, 23 Aug 2008 16:11:01 +0000 (16:11 +0000)
committerColin Walters <walters@src.gnome.org>
Sat, 23 Aug 2008 16:11:01 +0000 (16:11 +0000)
2008-08-22  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.

svn path=/trunk/; revision=467

12 files changed:
ChangeLog
gir/Makefile.am
girepository/girparser.c
giscanner/girparser.py
giscanner/girwriter.py
giscanner/transformer.py
tests/scanner/Makefile.am
tests/scanner/annotation-expected.gir
tests/scanner/drawable-expected.gir
tests/scanner/foo-expected.gir
tests/scanner/utility-expected.gir
tools/g-ir-scanner

index ad44575..4062c79 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+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:
index e5e9239..60b0190 100644 (file)
@@ -50,7 +50,6 @@ Gio.gir: GObject.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES)
            --noclosure \
            --output $@ \
            --strip-prefix=g \
-            --include=$(top_builddir)/gir/GLib.gir \
             --include=$(top_builddir)/gir/GObject.gir \
            --library=gio-2.0 \
            -I$(GIO_INCLUDEDIR) \
index 9a321d2..5b42856 100644 (file)
@@ -32,29 +32,30 @@ typedef enum
   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,
@@ -1922,6 +1923,12 @@ start_element_handler (GMarkupParseContext *context,
       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))
@@ -2174,6 +2181,13 @@ end_element_handler (GMarkupParseContext *context,
       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))
        {
index 5cf845f..5c2f121 100644 (file)
@@ -45,6 +45,7 @@ class GIRParser(object):
 
     def __init__(self, filename):
         self._nodes = []
+        self._includes = set()
         self._namespace_name = None
 
         tree = parse(filename)
@@ -55,6 +56,9 @@ class GIRParser(object):
     def get_namespace_name(self):
         return self._namespace_name
 
+    def get_includes(self):
+        return self._includes
+
     def get_nodes(self):
         return self._nodes
 
@@ -65,6 +69,9 @@ class GIRParser(object):
 
     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']
index c9b7f3d..18ba1b8 100644 (file)
@@ -31,11 +31,11 @@ from .xmlwriter import XMLWriter
 
 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'),
@@ -43,8 +43,14 @@ class GIRWriter(XMLWriter):
             ('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))]
index 475e728..2096000 100644 (file)
@@ -18,6 +18,8 @@
 # 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,
@@ -33,6 +35,9 @@ from giscanner.sourcescanner import (
 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
@@ -60,10 +65,15 @@ class Transformer(object):
         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
 
@@ -75,14 +85,38 @@ class Transformer(object):
         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):
index 56401d7..bf6a289 100644 (file)
@@ -30,7 +30,6 @@ BUILT_SOURCES = $(TYPELIBS) $(TXMLS) $(GIRS)
 
 %.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=$< \
@@ -44,7 +43,6 @@ GIRS += foo.gir
 
 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=$* \
index 1db97fb..d8f5349 100644 (file)
@@ -3,6 +3,8 @@
             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">
index 9ab8c80..55d2266 100644 (file)
@@ -3,6 +3,8 @@
             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"
index a7bc438..2bcfd4b 100644 (file)
@@ -3,6 +3,9 @@
             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"/>
index e682450..b0f0bb8 100644 (file)
@@ -3,6 +3,8 @@
             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"
index 8951aa1..af24598 100755 (executable)
@@ -179,7 +179,7 @@ def main(args):
     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")