[gobject-introspection/wip/transformer] [major] process constants again



commit eb60ba427c79637bc328e8ea982332d0b1cf23f1
Author: Colin Walters <walters verbum org>
Date:   Mon Aug 16 16:00:45 2010 -0400

    [major] process constants again

 giscanner/transformer.py           |   63 +++++++++++++++++++++++-------------
 tests/scanner/Foo-1.0-expected.gir |    2 +-
 2 files changed, 41 insertions(+), 24 deletions(-)
---
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index e03ede2..bde2c0a 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -20,12 +20,13 @@
 
 import os
 import sys
+import re
 
 from .ast import (Bitfield, Callback, Enum, Function, Namespace, Member,
                   Parameter, Return, Record, Field,
                   Type, Array, List, Map, Alias, Interface, Class, Node, Union,
                   Varargs, Constant, type_names, basic_type_names,
-                  TYPE_STRING, TYPE_ANY)
+                  TYPE_STRING, TYPE_ANY, TYPE_INT, TYPE_DOUBLE)
 from .config import DATADIR, GIR_DIR, GIR_SUFFIX
 from .girparser import GIRParser
 from .odict import odict
@@ -48,6 +49,8 @@ _xdg_data_dirs = [x for x in os.environ.get('XDG_DATA_DIRS', '').split(':') \
 class Transformer(object):
     namespace = property(lambda self: self._namespace)
 
+    UCASE_CONSTANT_RE = re.compile(r'[_A-Z0-9]+')
+
     def __init__(self, cachestore, namespace_name, namespace_version,
                  strip_prefix=None):
         self._cwd = os.getcwd() + os.sep
@@ -79,21 +82,30 @@ class Transformer(object):
     def set_source_ast(self, src_ast):
         self.generator = src_ast
 
+    def _append_new_node(self, node):
+        original = self._namespace.get(node.name)
+        # Special case constants here; we allow duplication to sort-of
+        # handle #ifdef.  But this introduces an arch-dependency in the .gir
+        # file.  So far this has only come up scanning glib - in theory, other
+        # modules will just depend on that.
+        if isinstance(original, Constant) and isinstance(node, Constant):
+            pass
+        elif original:
+            positions = set()
+            positions.update(original.file_positions)
+            positions.update(node.file_positions)
+            self.log_warning("Namespace conflict for '%s'" % (node.name, ),
+                             positions)
+            sys.exit(1)
+        else:
+            self._namespace.append(node)
+
     def parse(self):
-        nodes = []
         for symbol in self.generator.get_symbols():
             node = self._traverse_one(symbol)
             if node:
-                try:
-                    self._namespace.append(node)
-                except ValueError, e:
-                    original = self._namespace.get(node.name)
-                    positions = set()
-                    positions.update(original.file_positions)
-                    positions.update(node.file_positions)
-                    self.log_warning("Namespace conflict for '%s'" % (node.name, ),
-                                     positions)
-                    sys.exit(1)
+                self._append_new_node(node)
+
         # Now look through the namespace for things like
         # typedef struct _Foo Foo;
         # where we've never seen the struct _Foo.  Just create
@@ -282,8 +294,11 @@ or raise ValueError."""
             return matches[0]
         raise ValueError("Unknown namespace for symbol %r" % (symbol, ))
 
-    def _strip_symbol_or_warn(self, symbol):
+    def _strip_symbol_or_warn(self, symbol, is_constant=False):
         ident = symbol.ident
+        if is_constant:
+            # Temporarily lowercase
+            ident = ident.lower()
         hidden = ident.startswith('_')
         if hidden:
             ident = ident[1:]
@@ -295,6 +310,8 @@ or raise ValueError."""
         if ns != self._namespace:
             self.log_symbol_warning(symbol, "Skipping foreign symbol from namespace %s" % (ns.name, ))
             return None
+        if is_constant:
+            name = name.upper()
         if hidden:
             return '_' + name
         return name
@@ -330,11 +347,8 @@ or raise ValueError."""
             return self._create_member(symbol)
         elif stype == CSYMBOL_TYPE_UNION:
             return self._create_union(symbol)
-        # FIXME - we need to require an annotation on
-        # #defines to have them be constants, otherwise
-        # namespace explosion can occur
         elif stype == CSYMBOL_TYPE_CONST:
-            pass
+            return self._create_const(symbol)
         # Ignore variable declarations in the header
         elif stype == CSYMBOL_TYPE_OBJECT:
             pass
@@ -595,22 +609,25 @@ or raise ValueError."""
         if (symbol.source_filename is None or
             not symbol.source_filename.endswith('.h')):
             return None
-        name = self._strip_symbol_or_warn(symbol)
+        # ignore non-uppercase defines
+        if not self.UCASE_CONSTANT_RE.match(symbol.ident):
+            return None
+        name = self._strip_symbol_or_warn(symbol, is_constant=True)
         if not name:
             return None
         if symbol.const_string is not None:
             typeval = TYPE_STRING
             value = symbol.const_string
         elif symbol.const_int is not None:
-            type_name = 'int'
-            value = symbol.const_int
+            typeval = TYPE_INT
+            value = '%d' % (symbol.const_int, )
         elif symbol.const_double is not None:
-            type_name = 'double'
-            value = symbol.const_double
+            typeval = TYPE_DOUBLE
+            value = '%f' % (symbol.const_double, )
         else:
             raise AssertionError()
 
-        const = Constant(name, type_name, value)
+        const = Constant(name, typeval, value)
         const.add_symbol_reference(symbol)
         return const
 
diff --git a/tests/scanner/Foo-1.0-expected.gir b/tests/scanner/Foo-1.0-expected.gir
index b9a957d..388f0be 100644
--- a/tests/scanner/Foo-1.0-expected.gir
+++ b/tests/scanner/Foo-1.0-expected.gir
@@ -156,7 +156,7 @@ and/or use gtk-doc annotations.  -->
       </method>
     </record>
     <constant name="DEFINE_SHOULD_BE_EXPOSED" value="should be exposed">
-      <type name="utf8"/>
+      <type name="utf8" c:type="gchar*"/>
     </constant>
     <enumeration name="EnumFullname" c:type="FooEnumFullname">
       <member name="one" value="1" c:identifier="FOO_ENUM_FULLNAME_ONE"/>



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