gobject-introspection r912 - in trunk: . docs gir giscanner tests/everything tests/offsets tests/scanner tools



Author: walters
Date: Thu Nov 13 19:57:12 2008
New Revision: 912
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=912&view=rev

Log:
Bug 558436 - avoid having scanner load app code

Removed:
   trunk/giscanner/cgobject.py
Modified:
   trunk/ChangeLog
   trunk/docs/g-ir-scanner.1
   trunk/gir/Makefile.am
   trunk/giscanner/Makefile.am
   trunk/giscanner/glibtransformer.py
   trunk/giscanner/transformer.py
   trunk/tests/everything/Makefile.am
   trunk/tests/offsets/Makefile.am
   trunk/tests/scanner/Makefile.am
   trunk/tests/scanner/annotation-1.0-expected.gir
   trunk/tests/scanner/annotation-1.0-expected.tgir
   trunk/tests/scanner/annotation.c
   trunk/tests/scanner/annotation.h
   trunk/tests/scanner/foo-1.0-expected.gir
   trunk/tests/scanner/foo-1.0-expected.tgir
   trunk/tools/g-ir-scanner

Modified: trunk/docs/g-ir-scanner.1
==============================================================================
--- trunk/docs/g-ir-scanner.1	(original)
+++ trunk/docs/g-ir-scanner.1	Thu Nov 13 19:57:12 2008
@@ -43,14 +43,27 @@
 This option can be specified multiple times to include more than one
 directory to look for libraries in.
 .TP
-.B \-n, ---namspace=NAME
+.B \-n, ---namespace=NAME
 The namespace name. This name should be capitalized, eg the first letter
 should be upper case. Examples: Gtk, Clutter, WebKit.
 .TP
+.B \---no-libtool
+Disable usage of libtool for compiling stub introspection binary.  Use this
+if your build system does not require libtool.
+.TP
 .B ---nsversion=VERSION
 The namespace version. For instance 1.0. This is usually the platform version,
 eg 2.0 for Gtk+, not 2.12.7.
 .TP
+.B \-p, ---program=PROGRAM
+Specifies a binary that will be introspected. This means that the
+*_get_type() functions in it will be called for GObject data types.
+The binary must be modified to take a --introspect= option, and
+to pass the argument to this function to g_irepository_dump.
+.TP
+.B \---program-arg=ARG
+Additional argument to pass to program for introspection.
+.TP
 .B \, ---strip-prefix=PREFIX
 If this option is specified a prefix will be stripped from all functions.
 If not specified, the lower case version of the namespace will be used.

Modified: trunk/gir/Makefile.am
==============================================================================
--- trunk/gir/Makefile.am	(original)
+++ trunk/gir/Makefile.am	Thu Nov 13 19:57:12 2008
@@ -1,11 +1,8 @@
+include $(top_srcdir)/common.mk
+
 BUILT_SOURCES =
 EXTRA_DIST = 
 
-G_IR_SCANNER = $(top_srcdir)/tools/g-ir-scanner
-G_IR_SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-G_IR_SCANNER_FILES = $(top_srcdir)/giscanner/*.py \
-	$(top_builddir)/giscanner/libgiscanner.la
-
 # glib
 GLIB_INCLUDEDIR=`pkg-config --variable=includedir glib-2.0`/glib-2.0
 GLIB_LIBDIR=`pkg-config --variable=libdir glib-2.0`
@@ -16,10 +13,9 @@
 GLIB_LIBRARY=glib-2.0
 endif
 
-GLib-2.0.gir: $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) glib-2.0.c
-	PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-	    -v --namespace GLib --nsversion=2.0 \
-	    --add-include-path=. \
+GLib-2.0.gir: $(SCANNER_BIN) $(SCANNER_LIBS) Makefile glib-2.0.c
+	$(SCANNER) \
+	    --namespace GLib --nsversion=2.0 \
 	    --noclosure \
 	    --output $@ \
 	    --strip-prefix=g \
@@ -32,7 +28,7 @@
 	    $(GLIB_LIBDIR)/glib-2.0/include/glibconfig.h \
 	    $(srcdir)/glib-2.0.c \
 	    $(GLIB_INCLUDEDIR)/glib/*.h
-	PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
+	$(SCANNER) $(SCANNER_ARGS) \
 	    --xpath-assertions=$(srcdir)/GLib-2.0.xpath GLib-2.0.gir
 BUILT_SOURCES += GLib-2.0.gir
 EXTRA_DIST += glib-2.0.c GLib-2.0.xpath
@@ -47,10 +43,9 @@
 GOBJECT_LIBRARY=gobject-2.0
 endif
 
-GObject-2.0.gir: GLib-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES)
-	PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-	    -v --namespace GObject --nsversion=2.0 \
-	    --add-include-path=. \
+GObject-2.0.gir: GLib-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(SCANNER) \
+	    --namespace GObject --nsversion=2.0 \
 	    --noclosure \
 	    --output $@ \
 	    --strip-prefix=g \
@@ -73,9 +68,9 @@
 GMODULE_LIBRARY=gmodule-2.0
 endif
 
-GModule-2.0.gir: GLib-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES)
-	PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-	    -v --namespace GModule --nsversion=2.0 \
+GModule-2.0.gir: GLib-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS)
+	$(SCANNER) \
+	    --namespace GModule --nsversion=2.0 \
 	    --add-include-path=. \
 	    --noclosure \
 	    --output $@ \
@@ -98,9 +93,9 @@
 GIO_LIBRARY=gio-2.0
 endif
 
-Gio-2.0.gir: GObject-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) $(srcdir)/gio-2.0.c
-	PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-	    -v --namespace Gio --nsversion=2.0 \
+Gio-2.0.gir: GObject-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile $(srcdir)/gio-2.0.c
+	$(SCANNER) \
+	    --namespace Gio --nsversion=2.0 \
 	    --add-include-path=. \
 	    --noclosure \
 	    --output $@ \
@@ -122,15 +117,14 @@
 	$(top_srcdir)/girepository/girepository.c \
 	$(top_srcdir)/girepository/girepository.h
 
-GIRepository-2.0.gir: GObject-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) $(GIREPOSITORY_FILES)
-	PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-	    -v --namespace GIRepository --nsversion=1.0\
-	    --add-include-path=. \
+GIRepository-2.0.gir: GObject-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) $(GIREPOSITORY_FILES)
+	$(SCANNER) \
+	    --namespace GIRepository --nsversion=1.0\
 	    --noclosure \
 	    --output $@ \
 	    --strip-prefix=g \
             --include=GObject-2.0 \
-	    --library=$(top_builddir)/girepository/libgirepository.la \
+	    --library=girepository \
 	    -I$(srcdir)/girepository \
             --pkg glib-2.0 \
             --pkg gobject-2.0 \

Modified: trunk/giscanner/Makefile.am
==============================================================================
--- trunk/giscanner/Makefile.am	(original)
+++ trunk/giscanner/Makefile.am	Thu Nov 13 19:57:12 2008
@@ -37,8 +37,8 @@
 	__init__.py		\
 	ast.py			\
 	cachestore.py		\
-	cgobject.py		\
 	config.py		\
+	dumper.py		\
 	girparser.py		\
 	girwriter.py		\
 	glibast.py		\

Modified: trunk/giscanner/glibtransformer.py
==============================================================================
--- trunk/giscanner/glibtransformer.py	(original)
+++ trunk/giscanner/glibtransformer.py	Thu Nov 13 19:57:12 2008
@@ -19,11 +19,12 @@
 #
 
 import os
+import sys
 import re
-import ctypes
-from ctypes.util import find_library
+import tempfile
+import shutil
+import subprocess
 
-from . import cgobject
 from .ast import (Callback, Constant, Enum, Function, Member, Namespace,
                   Parameter, Property, Return, Struct, Type, Alias,
                   Union, Field, type_name_from_ctype,
@@ -32,10 +33,20 @@
 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
                       GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
                       GLibBoxedUnion, GLibBoxedOther, type_names)
-from .utils import extract_libtool, to_underscores, to_underscores_noprefix
+from .utils import to_underscores, to_underscores_noprefix
 
 default_array_types['guchar*'] = TYPE_UINT8
 
+# GParamFlags
+G_PARAM_READABLE = 1 << 0
+G_PARAM_WRITABLE = 1 << 1
+G_PARAM_CONSTRUCT = 1 << 2
+G_PARAM_CONSTRUCT_ONLY = 1 << 3
+G_PARAM_LAX_VALIDATION = 1 << 4
+G_PARAM_STATIC_NAME = 1 << 5
+G_PARAM_STATIC_NICK = 1 << 6
+G_PARAM_STATIC_BLURB = 1 << 7
+
 SYMBOL_BLACKLIST = [
     # These ones break GError conventions
     'g_simple_async_result_new_from_error',
@@ -49,6 +60,16 @@
                            [r'\w+_marshal_[A-Z]+__', ]]
 
 
+class IntrospectionBinary(object):
+
+    def __init__(self, args, tmpdir=None):
+        self.args = args
+        if tmpdir is None:
+            self.tmpdir = tempfile.mkdtemp('', 'tmp-introspect')
+        else:
+            self.tmpdir = tmpdir
+
+
 class Unresolved(object):
 
     def __init__(self, target):
@@ -68,7 +89,9 @@
         self._namespace_name = None
         self._names = Names()
         self._uscore_type_names = {}
-        self._libraries = []
+        self._binary = None
+        self._get_type_functions = []
+        self._gtype_data = {}
         self._failed_types = {}
         self._boxed_types = {}
         self._private_internal_types = {}
@@ -77,23 +100,8 @@
 
     # Public API
 
-    def add_library(self, libname):
-        # For testing mainly.
-        libtool_libname = 'lib' + libname + '.la'
-        if os.path.exists(libname):
-            found_libname = os.path.abspath(libname)
-        elif os.path.exists(libtool_libname):
-            found_libname = extract_libtool(libtool_libname)
-        else:
-            found_libname = find_library(libname)
-
-        if libname.endswith('.la'):
-            found_libname = extract_libtool(libname)
-            libname = os.path.basename(found_libname)
-        if not found_libname:
-            raise ValueError("Failed to find library: %r" % (libname, ))
-        self._libraries.append(ctypes.cdll.LoadLibrary(found_libname))
-        return libname
+    def set_introspection_binary(self, binary):
+        self._binary = binary
 
     def _print_statistics(self):
         nodes = list(self._names.names.itervalues())
@@ -120,6 +128,11 @@
         if namespace.name == 'GObject':
             del self._names.aliases['Type']
 
+        # Get all the GObject data by passing our list of get_type
+        # functions to the compiled binary
+
+        self._execute_binary()
+
         # Introspection is done from within parsing
 
         # Second pass: pair boxed structures
@@ -169,6 +182,16 @@
             return node[1]
         return None
 
+    def _lookup_node(self, name):
+        if name in type_names:
+            return None
+        node = self._get_attribute(name)
+        if node is None:
+            node = self._transformer.get_names().names.get(name)
+            if node:
+                return node[1]
+        return node
+
     def _register_internal_type(self, type_name, node):
         self._names.type_names[type_name] = (None, node)
         uscored = to_underscores(type_name).lower()
@@ -183,16 +206,6 @@
 
     # Helper functions
 
-    def _type_from_gtype(self, type_id):
-        ctype = cgobject.type_name(type_id)
-        type_name = type_name_from_ctype(ctype)
-        type_name = type_name.replace('*', '')
-        type_name = self._resolve_type_name(type_name)
-
-        type = Type(type_name, ctype)
-        type._gtype = type_id
-        return type
-
     def _resolve_gtypename(self, gtype_name):
         try:
             return self._transformer.gtypename_to_giname(gtype_name,
@@ -200,21 +213,45 @@
         except KeyError, e:
             return Unresolved(gtype_name)
 
+    def _execute_binary(self):
+        in_path = os.path.join(self._binary.tmpdir, 'types.txt')
+        f = open(in_path, 'w')
+        for func in self._get_type_functions:
+            f.write(func)
+            f.write('\n')
+        f.close()
+        out_path = os.path.join(self._binary.tmpdir, 'dump.xml')
+
+        introspect_arg = '--introspect-dump=%s,%s' % (in_path, out_path)
+        args = self._binary.args
+        args.append(introspect_arg)
+        # Invoke the binary, having written our get_type functions to types.txt
+        print args
+        subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
+        self._read_introspect_dump(out_path)
+
+        # Clean up temporaries
+        shutil.rmtree(self._binary.tmpdir)
+
+    def _read_introspect_dump(self, xmlpath):
+        from xml.etree.cElementTree import parse
+        tree = parse(xmlpath)
+        root = tree.getroot()
+        for child in root:
+            self._gtype_data[child.attrib['name']] = child
+        for child in root:
+            self._introspect_type(child)
+
     def _create_gobject(self, node):
         type_name = 'G' + node.name
         if type_name == 'GObject':
             parent_gitype = None
             symbol = 'intern'
-        else:
-            type_id = cgobject.type_from_name(type_name)
-            parent_type_name = cgobject.type_name(
-                cgobject.type_parent(type_id))
+        elif type_name == 'GInitiallyUnowned':
+            parent_type_name = 'GObject'
             parent_gitype = self._resolve_gtypename(parent_type_name)
-            symbol = to_underscores(type_name).lower() + '_get_type'
+            symbol = 'g_initially_unowned_get_type'
         node = GLibObject(node.name, parent_gitype, type_name, symbol, True)
-        type_id = cgobject.TYPE_OBJECT
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
         self._add_attribute(node)
         self._register_internal_type(type_name, node)
 
@@ -281,26 +318,7 @@
                    ", not GObject.Type") % (func.retval.type.name, )
             return False
 
-        if not self._libraries:
-            print "Warning: No libraries loaded, cannot call %s" % (symbol, )
-            return False
-
-        for library in self._libraries:
-            try:
-                func = getattr(library, symbol)
-                break
-            except AttributeError:
-                continue
-        else:
-            print 'Warning: could not find symbol: %s' % symbol
-            name = symbol.replace('_get_type', '')
-            self._failed_types[name] = True
-            return False
-
-        func.restype = cgobject.GType
-        func.argtypes = []
-        type_id = func()
-        self._introspect_type(type_id, symbol)
+        self._get_type_functions.append(symbol)
         return True
 
     def _name_is_internal_gtype(self, giname):
@@ -491,65 +509,51 @@
 
     # Introspection
 
-    def _introspect_type(self, type_id, symbol):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if (fundamental_type_id == cgobject.TYPE_ENUM or
-            fundamental_type_id == cgobject.TYPE_FLAGS):
-            self._introspect_enum(fundamental_type_id, type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_OBJECT:
-            self._introspect_object(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_INTERFACE:
-            self._introspect_interface(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_BOXED:
-            self._introspect_boxed(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_BOXED:
-            self._introspect_boxed(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_POINTER:
-            # FIXME: Should we do something about these?
-            #        GHashTable, GValue and a few other fundamentals are
-            #        covered here
-            return
-        else:
-            print 'unhandled GType: %s(%d)' % (cgobject.type_name(type_id),
-                                               type_id)
-
-    def _introspect_enum(self, ftype_id, type_id, symbol):
-        type_class = cgobject.type_class_ref(type_id)
-        if type_class is None:
-            return
+    def _introspect_type(self, xmlnode):
+        if xmlnode.tag in ('enum', 'flags'):
+            self._introspect_enum(xmlnode)
+        elif xmlnode.tag == 'class':
+            self._introspect_object(xmlnode)
+        elif xmlnode.tag == 'interface':
+            self._introspect_interface(xmlnode)
+        elif xmlnode.tag == 'boxed':
+            self._introspect_boxed(xmlnode)
+        else:
+            raise ValueError("Unhandled introspection XML tag %s", xmlnode.tag)
 
+    def _introspect_enum(self, node):
         members = []
-        for enum_value in type_class.get_values():
-            members.append(GLibEnumMember(enum_value.value_nick,
-                                          enum_value.value,
-                                          enum_value.value_name,
-                                          enum_value.value_nick))
+        for member in node.findall('member'):
+            members.append(GLibEnumMember(member.attrib['nick'],
+                                          member.attrib['value'],
+                                          member.attrib['name'],
+                                          member.attrib['nick']))
 
-        klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
-        type_name = cgobject.type_name(type_id)
+        klass = (GLibFlags if node.tag == 'flags' else GLibEnum)
+        type_name = node.attrib['name']
         enum_name = self._transformer.remove_prefix(type_name)
-        node = klass(enum_name, type_name, members, symbol)
+        node = klass(enum_name, type_name, members, node.attrib['get-type'])
         self._add_attribute(node, replace=True)
         self._register_internal_type(type_name, node)
 
-    def _introspect_object(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
+    def _introspect_object(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         # We handle this specially above; in 2.16 and below there
         # was no g_object_get_type, for later versions we need
         # to skip it
         if type_name == 'GObject':
             return
-        parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
+        parent_type_name = xmlnode.attrib['parent']
         parent_gitype = self._resolve_gtypename(parent_type_name)
-        is_abstract = cgobject.type_is_abstract(type_id)
+        is_abstract = not not xmlnode.attrib.get('abstract', False)
         node = GLibObject(
             self._transformer.remove_prefix(type_name),
             parent_gitype,
             type_name,
-            symbol, is_abstract)
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
-        self._introspect_implemented_interfaces(node, type_id)
+            xmlnode.attrib['get-type'], is_abstract)
+        self._introspect_properties(node, xmlnode)
+        self._introspect_signals(node, xmlnode)
+        self._introspect_implemented_interfaces(node, xmlnode)
 
         # add struct fields
         struct = self._get_attribute(node.name)
@@ -564,84 +568,69 @@
         self._add_attribute(node, replace=True)
         self._register_internal_type(type_name, node)
 
-    def _introspect_interface(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
-        parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
-        if parent_type_name == 'GInterface':
-            parent_gitype = None
-        else:
-            parent_gitype = self._resolve_gtypename(parent_type_name)
+    def _introspect_interface(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         node = GLibInterface(
             self._transformer.remove_prefix(type_name),
-            parent_gitype,
-            type_name, symbol)
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
+            None,
+            type_name, xmlnode.attrib['get-type'])
+        self._introspect_properties(node, xmlnode)
+        self._introspect_signals(node, xmlnode)
         # GtkFileChooserEmbed is an example of a private interface, we
         # just filter them out
-        if symbol.startswith('_'):
+        if xmlnode.attrib['get-type'].startswith('_'):
             print "NOTICE: Marking %s as internal type" % (type_name, )
             self._private_internal_types[type_name] = node
         else:
             self._add_attribute(node, replace=True)
             self._register_internal_type(type_name, node)
 
-    def _introspect_boxed(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
+    def _introspect_boxed(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         # This one doesn't go in the main namespace; we associate it with
         # the struct or union
-        node = GLibBoxed(type_name, symbol)
+        node = GLibBoxed(type_name, xmlnode.attrib['get-type'])
         self._boxed_types[node.type_name] = node
         self._register_internal_type(type_name, node)
 
-    def _introspect_implemented_interfaces(self, node, type_id):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if fundamental_type_id != cgobject.TYPE_OBJECT:
-            raise AssertionError
-        interfaces = cgobject.type_interfaces(type_id)
+    def _introspect_implemented_interfaces(self, node, xmlnode):
         gt_interfaces = []
-        for interface_typeid in interfaces:
-            iname = cgobject.type_name(interface_typeid)
-            gitype = self._resolve_gtypename(iname)
+        for interface in xmlnode.findall('implements'):
+            gitype = self._resolve_gtypename(interface.attrib['name'])
             gt_interfaces.append(gitype)
         node.interfaces = gt_interfaces
 
-    def _introspect_properties(self, node, type_id):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if fundamental_type_id == cgobject.TYPE_OBJECT:
-            pspecs = cgobject.object_class_list_properties(type_id)
-        elif fundamental_type_id == cgobject.TYPE_INTERFACE:
-            pspecs = cgobject.object_interface_list_properties(type_id)
-        else:
-            raise AssertionError
-
-        for pspec in pspecs:
-            if pspec.owner_type != type_id:
-                continue
-            ctype = cgobject.type_name(pspec.value_type)
-            readable = (pspec.flags & 1) != 0
-            writable = (pspec.flags & 2) != 0
-            construct = (pspec.flags & 4) != 0
-            construct_only = (pspec.flags & 8) != 0
+    def _introspect_properties(self, node, xmlnode):
+        for pspec in xmlnode.findall('property'):
+            ctype = pspec.attrib['type']
+            flags = int(pspec.attrib['flags'])
+            readable = (flags & G_PARAM_READABLE) != 0
+            writable = (flags & G_PARAM_WRITABLE) != 0
+            construct = (flags & G_PARAM_CONSTRUCT) != 0
+            construct_only = (flags & G_PARAM_CONSTRUCT_ONLY) != 0
             node.properties.append(Property(
-                pspec.name,
+                pspec.attrib['name'],
                 type_name_from_ctype(ctype),
                 readable, writable, construct, construct_only,
                 ctype,
                 ))
 
-    def _introspect_signals(self, node, type_id):
-        for signal_info in cgobject.signal_list(type_id):
-            rtype = self._type_from_gtype(signal_info.return_type)
-            return_ = Return(rtype)
-            signal = GLibSignal(signal_info.signal_name, return_)
-            for i, parameter in enumerate(signal_info.get_params()):
+    def _introspect_signals(self, node, xmlnode):
+        for signal_info in xmlnode.findall('signal'):
+            rctype = signal_info.attrib['return']
+            rtype = Type(self._transformer.parse_ctype(rctype), rctype)
+            return_ = Return(rtype, signal_info.attrib['return'])
+            return_.transfer = 'full'
+            signal = GLibSignal(signal_info.attrib['name'], return_)
+            for i, parameter in enumerate(signal_info.findall('param')):
                 if i == 0:
                     name = 'object'
                 else:
                     name = 'p%s' % (i-1, )
-                ptype = self._type_from_gtype(parameter)
+                pctype = parameter.attrib['type']
+                ptype = Type(self._transformer.parse_ctype(pctype), pctype)
                 param = Parameter(name, ptype)
+                param.transfer = 'none'
                 signal.parameters.append(param)
             node.signals.append(signal)
 
@@ -651,7 +640,6 @@
         # Workaround glib bug #548689, to be included in 2.18.0
         if type_name == "GParam":
             type_name = "GObject.ParamSpec"
-
         res = self._transformer.resolve_type_name_full
         try:
             return res(type_name, ctype, self._names)
@@ -659,6 +647,9 @@
             return self._transformer.resolve_type_name(type_name, ctype)
 
     def _resolve_param_type(self, ptype, **kwargs):
+        # Workaround glib bug #548689, to be included in 2.18.0
+        if ptype.name == "GParam":
+            ptype.name = "GObject.ParamSpec"
         return self._transformer.resolve_param_type_full(ptype,
                                                          self._names,
                                                          **kwargs)
@@ -783,43 +774,23 @@
         prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
 
     def _adjust_transfer(self, param):
+        if not (param.transfer is None or param.transfer_inferred):
+            return
+
         # Do GLib/GObject-specific type transformations here
+        node = self._lookup_node(param.type.name)
+        if node is None:
+            return
 
-        transfer = None
-        is_object = None
-        if hasattr(param.type, '_gtype'):
-            ftype = cgobject.type_fundamental(param.type._gtype)
-            assert ftype != cgobject.TYPE_INVALID, param.type._gtype
-
-            is_object = ftype in [cgobject.TYPE_OBJECT,
-                                  cgobject.TYPE_INTERFACE]
-
-            if ftype in [cgobject.TYPE_OBJECT,
-                         cgobject.TYPE_INTERFACE,
-                         cgobject.TYPE_STRING,
-                         cgobject.TYPE_BOXED,
-                         cgobject.TYPE_PARAM]:
+        if isinstance(param, Parameter):
+            if param.direction != PARAM_DIRECTION_IN:
                 transfer = 'full'
             else:
-                # if type is a cgobject.TYPE_POINTER we could require direction
-                # and transfer-ownership annotations
                 transfer = 'none'
-
-        if is_object is None:
-            is_object = (param.type.name == 'GObject.Object' or
-                         (self._namespace_name == 'GObject' and
-                          param.type.name == 'Object'))
-
-        # Default to full transfer for GObjects
-        if isinstance(param, Parameter):
-            is_out = (param.direction != PARAM_DIRECTION_IN)
         else:
-            is_out = True
-        if param.transfer is None or param.transfer_inferred:
-            if is_out and is_object:
-                param.transfer = 'full'
-            elif transfer is not None:
-                param.transfer = transfer
+            transfer = 'full'
+
+        param.transfer = transfer
 
     def _adjust_throws(self, func):
         if func.parameters == []:

Modified: trunk/giscanner/transformer.py
==============================================================================
--- trunk/giscanner/transformer.py	(original)
+++ trunk/giscanner/transformer.py	Thu Nov 13 19:57:12 2008
@@ -142,7 +142,8 @@
                 self._names.aliases[node.name] = (nsname, node)
             elif isinstance(node, (GLibBoxed, Interface, Class)):
                 self._names.type_names[node.type_name] = (nsname, node)
-            self._names.names[node.name] = (nsname, node)
+            giname = '%s.%s' % (nsname, node.name)
+            self._names.names[giname] = (nsname, node)
             if hasattr(node, 'ctype'):
                 self._names.ctypes[node.ctype] = (nsname, node)
             elif hasattr(node, 'symbol'):
@@ -370,7 +371,7 @@
                 "symbol %r of type %s" % (symbol.ident, ctype_name(ctype)))
         return node
 
-    def _parse_ctype(self, ctype):
+    def parse_ctype(self, ctype):
         # First look up the ctype including any pointers;
         # a few type names like 'char*' have their own aliases
         # and we need pointer information for those.
@@ -398,29 +399,29 @@
         if ctype in self._list_ctypes:
             param = options.get('element-type')
             if param:
-                contained_type = self._parse_ctype(param[0])
+                contained_type = self.parse_ctype(param[0])
             else:
                 contained_type = None
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = List(derefed_name,
                            ctype,
                            contained_type)
         elif ctype in self._map_ctypes:
             param = options.get('element-type')
             if param:
-                key_type = self._parse_ctype(param[0])
-                value_type = self._parse_ctype(param[1])
+                key_type = self.parse_ctype(param[0])
+                value_type = self.parse_ctype(param[1])
             else:
                 key_type = None
                 value_type = None
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = Map(derefed_name,
                           ctype,
                           key_type, value_type)
         elif (ctype in default_array_types) or ('array' in options):
             derefed_name = ctype[:-1] if ctype[-1] == '*' else ctype
             rettype = Array(ctype,
-                            self._parse_ctype(derefed_name))
+                            self.parse_ctype(derefed_name))
             array_opts = dict([opt.split('=')
                                for opt in options.get('array', [])])
             if 'length' in array_opts:
@@ -429,7 +430,7 @@
                 rettype.size = array_opts['fixed-size']
                 rettype.zeroterminated = False
         else:
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = Type(derefed_name, ctype)
 
         # Deduce direction for some types passed by reference that

Modified: trunk/tests/everything/Makefile.am
==============================================================================
--- trunk/tests/everything/Makefile.am	(original)
+++ trunk/tests/everything/Makefile.am	Thu Nov 13 19:57:12 2008
@@ -1,3 +1,5 @@
+include $(top_srcdir)/common.mk
+
 LT_CURRENT = 1
 LT_REVISION = 0
 LT_AGE = 0
@@ -23,18 +25,13 @@
 endif
 
 GIRS =
-SCANNER = $(top_srcdir)/tools/g-ir-scanner
-SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-SCANNER_LIBS = $(top_srcdir)/giscanner/*.py \
-	       $(top_builddir)/giscanner/libgiscanner.la
 TYPELIBS = $(GIRS:.gir=.typelib)
 TXMLS = $(GIRS:.gir=.gir.txml)
 CLEANFILES = $(TYPELIBS) $(TXMLS) $(GIRS)
 BUILT_SOURCES = $(TYPELIBS) $(TXMLS) $(GIRS)
 
-Everything-$(TYPELIB_VERSION).gir: libgirepository-everything.la gitesttypes.c gitesttypes.h $(SCANNER) $(SCANNER_LIBS)
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-	--add-include-path=$(top_builddir)/gir \
+Everything-$(TYPELIB_VERSION).gir: libgirepository-everything.la gitesttypes.c gitesttypes.h $(SCANNER_BIN) $(SCANNER_LIBS)
+	$(CHECK_DEBUG) $(SCANNER) \
 	--include=GObject-2.0 \
 	--library=girepository-everything \
 	--namespace=Everything --nsversion=$(TYPELIB_VERSION) \

Modified: trunk/tests/offsets/Makefile.am
==============================================================================
--- trunk/tests/offsets/Makefile.am	(original)
+++ trunk/tests/offsets/Makefile.am	Thu Nov 13 19:57:12 2008
@@ -1,3 +1,5 @@
+include $(top_srcdir)/common.mk
+
 BUILT_SOURCES =
 CLEANFILES =
 EXTRA_DIST =
@@ -5,12 +7,6 @@
 check_LTLIBRARIES =
 check_PROGRAMS =
 
-SCANNER = $(top_srcdir)/tools/g-ir-scanner
-SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-SCANNER_LIBS = \
-	$(top_srcdir)/giscanner/*.py \
-	$(top_builddir)/giscanner/libgiscanner.la
-
 ############################################################
 
 check_LTLIBRARIES += liboffsets.la
@@ -20,11 +16,10 @@
 	offsets.c
 liboffsets_la_CPPFLAGS = $(GIREPO_CFLAGS)
 # dummy rpath to get built dynamically (huh?)
-liboffsets_la_LDFLAGS = -module -avoid-version -rpath $(libdir)
+liboffsets_la_LDFLAGS = -avoid-version -rpath $(libdir)
 
-offsets-1.0.gir: liboffsets.la offsets.h $(SCANNER) $(SCANNER_LIBS) Makefile
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+offsets-1.0.gir: liboffsets.la offsets.h $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(CHECK_DEBUG) $(SCANNER) \
 	--library=offsets \
 	--namespace=offsets \
 	--nsversion=1.0 \

Modified: trunk/tests/scanner/Makefile.am
==============================================================================
--- trunk/tests/scanner/Makefile.am	(original)
+++ trunk/tests/scanner/Makefile.am	Thu Nov 13 19:57:12 2008
@@ -1,3 +1,5 @@
+include $(top_srcdir)/common.mk
+
 # We need to build a shared library, which can be dlopened
 # it does not work with noinst_LTLIBRARIES
 testlib_LTLIBRARIES = \
@@ -9,9 +11,10 @@
 testlibdir = $(prefix)/unused
 install-testlibLTLIBRARIES: # prevent it from being installed
 
-AM_CFLAGS = $(GOBJECT_CFLAGS)
-AM_LDFLAGS = -module -avoid-version
-LIBS = $(GOBJECT_LIBS)
+AM_CPPFLAGS = -I$(top_srcdir)/girepository
+AM_CFLAGS = $(GOBJECT_CFLAGS) $(GTHREAD_CFLAGS)
+AM_LDFLAGS = -avoid-version
+LIBS = $(GOBJECT_LIBS) $(GTHREAD_LIBS)
 
 libannotation_la_SOURCES = $(srcdir)/annotation.c $(srcdir)/annotation.h
 libdrawable_la_SOURCES = $(srcdir)/drawable.c $(srcdir)/drawable.h
@@ -25,11 +28,6 @@
 
 # .gir --[scanner]-> .typelib --[generate]-> .tgir
 GIRS =
-SCANNER = $(top_srcdir)/tools/g-ir-scanner
-SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-SCANNER_LIBS = \
-	$(top_srcdir)/giscanner/*.py \
-	$(top_builddir)/giscanner/libgiscanner.la
 TYPELIBS = $(GIRS:.gir=.typelib)
 CHECKGIRS = $(GIRS:.gir=.gir.check)
 EXPECTEDGIRS = $(GIRS:.gir=-expected.gir)
@@ -40,9 +38,8 @@
 BUILT_SOURCES = $(TYPELIBS) $(GIRS)
 EXTRA_DIST = $(EXPECTEDGIRS) $(EXPECTEDTGIRS)
 
-annotation-1.0.gir: libannotation.la annotation.c annotation.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+annotation-1.0.gir: libannotation.la annotation.c annotation.h utility-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	 $(CHECK_DEBUG) $(SCANNER) \
 	--include=GObject-2.0 \
 	--include=utility-1.0 \
 	--library=annotation \
@@ -53,9 +50,8 @@
 	 --output $@
 GIRS += annotation-1.0.gir
 
-drawable-1.0.gir: libdrawable.la drawable.c drawable.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+drawable-1.0.gir: libdrawable.la drawable.c drawable.h utility-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(CHECK_DEBUG) $(SCANNER) \
 	--include=GObject-2.0 \
 	--include=utility-1.0 \
 	--library=drawable \
@@ -66,15 +62,14 @@
 	 --output $@
 GIRS += drawable-1.0.gir
 
-drawable-injected-1.0.gir: drawable-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
+drawable-injected-1.0.gir: drawable-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(CHECK_DEBUG) $(SCANNER) -v \
 	 --inject drawable-1.0.gir $(srcdir)/DrawableAdditions.xml $@
 GIRS += drawable-injected-1.0.gir
 EXTRA_DIST += DrawableAdditions.xml
 
-foo-1.0.gir: libfoo.la foo.c foo.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+foo-1.0.gir: libfoo.la foo.c foo.h utility-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(CHECK_DEBUG) $(SCANNER) \
 	--include=GObject-2.0 \
 	--include=utility-1.0 \
 	--library=foo \
@@ -85,9 +80,8 @@
 	 --output $@
 GIRS += foo-1.0.gir
 
-utility-1.0.gir: libutility.la utility.h $(SCANNER) $(SCANNER_LIBS) Makefile
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+utility-1.0.gir: libutility.la utility.h $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(CHECK_DEBUG) $(SCANNER) \
 	--include=GObject-2.0 \
 	--library=utility \
 	--namespace=utility \
@@ -98,9 +92,8 @@
 GIRS += utility-1.0.gir
 
 # This one tests different --namespace and --strip-prefix
-GtkFrob-1.0.gir: libgtkfrob.la gtkfrob.h $(SCANNER) $(SCANNER_LIBS) Makefile
-	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+GtkFrob-1.0.gir: libgtkfrob.la gtkfrob.h $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(CHECK_DEBUG) $(SCANNER) \
 	--include=GObject-2.0 \
 	--library=gtkfrob \
 	--namespace=GtkFrob \
@@ -111,6 +104,23 @@
 	--output $@
 GIRS += GtkFrob-1.0.gir
 
+bin_PROGRAMS = barapp
+
+barapp_SOURCES = barapp.c barapp.h
+barapp_LDADD = $(top_builddir)/girepository/libgirepository.la
+barapp_LDFLAGS = -export-dynamic
+BarApp-1.0.gir: barapp $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+	$(SCANNER) \
+	--include=GObject-2.0 \
+	--program=./barapp \
+	--namespace=BarApp \
+	--strip-prefix=Bar \
+	--nsversion=1.0 \
+	--pkg gobject-2.0 \
+	$(barapp_SOURCES) \
+	--output $@
+GIRS += BarApp-1.0.gir
+
 pre-check:
 	@if test "$(top_builddir)" != "$(top_srcdir)"; then \
 	   cp -f $(top_srcdir)/giscanner/*.py $(top_builddir)/giscanner; \

Modified: trunk/tests/scanner/annotation-1.0-expected.gir
==============================================================================
--- trunk/tests/scanner/annotation-1.0-expected.gir	(original)
+++ trunk/tests/scanner/annotation-1.0-expected.gir	Thu Nov 13 19:57:12 2008
@@ -62,7 +62,7 @@
           <type name="GObject.Object" c:type="GObject*"/>
         </return-value>
         <parameters>
-          <parameter name="somearg" transfer-ownership="full" allow-none="1">
+          <parameter name="somearg" transfer-ownership="none" allow-none="1">
             <type name="utf8" c:type="gchar*"/>
           </parameter>
         </parameters>

Modified: trunk/tests/scanner/annotation-1.0-expected.tgir
==============================================================================
--- trunk/tests/scanner/annotation-1.0-expected.tgir	(original)
+++ trunk/tests/scanner/annotation-1.0-expected.tgir	Thu Nov 13 19:57:12 2008
@@ -60,7 +60,7 @@
           <type name="GObject.Object"/>
         </return-value>
         <parameters>
-          <parameter name="somearg" transfer-ownership="full" allow-none="1">
+          <parameter name="somearg" transfer-ownership="none" allow-none="1">
             <type name="utf8"/>
           </parameter>
         </parameters>

Modified: trunk/tests/scanner/annotation.c
==============================================================================
--- trunk/tests/scanner/annotation.c	(original)
+++ trunk/tests/scanner/annotation.c	Thu Nov 13 19:57:12 2008
@@ -247,7 +247,7 @@
  * @somearg: (allow-none):
  **/
 GObject*
-annotation_object_allow_none (AnnotationObject *object, gchar *somearg)
+annotation_object_allow_none (AnnotationObject *object, const gchar *somearg)
 {
   return NULL;
 }

Modified: trunk/tests/scanner/annotation.h
==============================================================================
--- trunk/tests/scanner/annotation.h	(original)
+++ trunk/tests/scanner/annotation.h	Thu Nov 13 19:57:12 2008
@@ -39,7 +39,7 @@
 					 int              *outarg);
 GObject* annotation_object_create_object(AnnotationObject *object);
 GObject* annotation_object_allow_none   (AnnotationObject *object,
-					 gchar            *somearg);
+					 const gchar      *somearg);
 GObject* annotation_object_notrans      (AnnotationObject *object);
 gint     annotation_object_inout        (AnnotationObject *object,
 					 int              *inoutarg);

Modified: trunk/tests/scanner/foo-1.0-expected.gir
==============================================================================
--- trunk/tests/scanner/foo-1.0-expected.gir	(original)
+++ trunk/tests/scanner/foo-1.0-expected.gir	Thu Nov 13 19:57:12 2008
@@ -157,7 +157,7 @@
           <type name="utf8" c:type="gchararray"/>
         </return-value>
         <parameters>
-          <parameter name="object" transfer-ownership="full">
+          <parameter name="object" transfer-ownership="none">
             <type name="GObject.Object" c:type="GObject"/>
           </parameter>
           <parameter name="p0" transfer-ownership="none">

Modified: trunk/tests/scanner/foo-1.0-expected.tgir
==============================================================================
--- trunk/tests/scanner/foo-1.0-expected.tgir	(original)
+++ trunk/tests/scanner/foo-1.0-expected.tgir	Thu Nov 13 19:57:12 2008
@@ -101,7 +101,7 @@
           <type name="utf8"/>
         </return-value>
         <parameters>
-          <parameter name="object" transfer-ownership="full">
+          <parameter name="object" transfer-ownership="none">
             <type name="GObject.Object"/>
           </parameter>
           <parameter name="p0" transfer-ownership="none">

Modified: trunk/tools/g-ir-scanner
==============================================================================
--- trunk/tools/g-ir-scanner	(original)
+++ trunk/tools/g-ir-scanner	Thu Nov 13 19:57:12 2008
@@ -43,12 +43,12 @@
 
 from giscanner.ast import Include
 from giscanner.cachestore import CacheStore
-from giscanner.glibtransformer import GLibTransformer
+from giscanner.dumper import compile_introspection_binary
+from giscanner.glibtransformer import GLibTransformer, IntrospectionBinary
 from giscanner.minixpath import myxpath, xpath_assert
 from giscanner.sourcescanner import SourceScanner
 from giscanner.transformer import Transformer
 
-
 def _get_option_parser():
     parser = optparse.OptionParser('%prog [options] sources')
     parser.add_option("", "--format",
@@ -58,9 +58,18 @@
     parser.add_option("-i", "--include",
                       action="append", dest="includes", default=[],
                       help="include types for other gidls")
-    parser.add_option("--add-include-path",
+    parser.add_option("", "--add-include-path",
                       action="append", dest="include_paths", default=[],
                       help="include paths for other GIR files")
+    parser.add_option("", "--program",
+                      action="store", dest="program", default=None,
+                      help="program to execute")
+    parser.add_option("", "--program-arg",
+                      action="append", dest="program_args", default=[],
+                      help="extra arguments to program")
+    parser.add_option("", "--no-libtool",
+                      action="store_true", dest="nolibtool", default=False,
+                      help="use libtool")
     parser.add_option("-l", "--library",
                       action="append", dest="libraries", default=[],
                       help="libraries of this unit")
@@ -209,8 +218,9 @@
     else:
         _error("Unknown format: %s" % (options.format, ))
 
-    if not options.libraries:
-        _error("Must specify --library at least one primary library")
+    if not (options.libraries or options.program):
+        _error("Must specify --program or --library")
+    libraries = options.libraries
 
     for package in options.packages:
         output = subprocess.Popen(['pkg-config', '--cflags', package],
@@ -285,13 +295,17 @@
         include_obj = Include.from_string(include)
         transformer.register_include(include_obj)
 
+    if options.program:
+        args=[options.program]
+        args.extend(options.program_args)
+        binary = IntrospectionBinary(args)
+    else:
+        binary = compile_introspection_binary(options)
+
     # Transform the C AST nodes into higher level
     # GLib/GObject nodes
     glibtransformer = GLibTransformer(transformer, noclosure=options.noclosure)
-    libraries = []
-    if options.libraries:
-        for library in options.libraries:
-            libraries.append(glibtransformer.add_library(library))
+    glibtransformer.set_introspection_binary(binary)
 
     namespace = glibtransformer.parse()
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]