[gobject-introspection] scanner: Refactor name parsing



commit c8e227432c5072ab858f8acd93b24ffc26ed1c68
Author: Colin Walters <walters verbum org>
Date:   Wed Sep 1 12:39:52 2010 -0400

    scanner: Refactor name parsing
    
    First, merge the implementations of parsing both identifiers and
    symbols, since they had more in common than they had differences.
    
    Secondly, fix the logic for priority of --accept-unprefixed in
    the presence of unprefixed includes.  The current namespace should
    win.  An example of this is mutter which has unprefixed public
    symbols, but also includes xlib, which has no prefix.
    
    Third, for unprefixed namespaces, actually look at the contents
    rather than just blindly returning them.  This is a bit of a hack,
    but better than the alternatives.

 giscanner/scannermain.py |    3 +-
 giscanner/transformer.py |   58 ++++++++++++++++++++++++++-------------------
 2 files changed, 35 insertions(+), 26 deletions(-)
---
diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py
index 384727e..3b7cd53 100644
--- a/giscanner/scannermain.py
+++ b/giscanner/scannermain.py
@@ -102,7 +102,8 @@ the latter is not specified.""")
                       help="Remove this prefix from C symbols (function names)")
     parser.add_option("", "--accept-unprefixed",
                       action="store_true", dest="accept_unprefixed", default=False,
-                      help="If specified, accept symbols and identifiers that do not match the namespace prefix.")
+                      help="""If specified, accept symbols and identifiers that do not
+match the namespace prefix.""")
     parser.add_option("", "--add-init-section",
                       action="append", dest="init_sections", default=[],
             help="add extra initialization code in the introspection program")
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index aa1f4eb..5d4c299 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -275,44 +275,52 @@ currently-scanned namespace is first."""
             return -1
         return cmp(x[2], y[2])
 
-    def split_ctype_namespaces(self, ident):
-        """Given a StudlyCaps string identifier like FooBar, return a
-list of (namespace, stripped_identifier) sorted by namespace length,
-or raise ValueError.  As a special case, if the current namespace matches,
-it is always biggest (i.e. last)."""
-        matches = []
+    def _split_c_string_for_namespace_matches(self, name, is_identifier=False):
+        matches = []  # Namespaces which might contain this name
+        unprefixed_namespaces = [] # Namespaces with no prefix, last resort
         for ns in self._iter_namespaces():
-            if ns.identifier_prefixes:
-                for prefix in ns.identifier_prefixes:
-                    if ident.startswith(prefix):
-                        matches.append((ns, ident[len(prefix):], len(prefix)))
+            if is_identifier:
+                prefixes = ns.identifier_prefixes
+            else:
+                prefixes = ns.symbol_prefixes
+            if prefixes:
+                for prefix in prefixes:
+                    if (not is_identifier) and (not prefix.endswith('_')):
+                        prefix = prefix + '_'
+                    if name.startswith(prefix):
+                        matches.append((ns, name[len(prefix):], len(prefix)))
                         break
             else:
-                # A special case for namespaces without a prefix, such as X
-                matches.append((ns, ident, 0))
+                unprefixed_namespaces.append(ns)
         if matches:
             matches.sort(self._sort_matches)
             return map(lambda x: (x[0], x[1]), matches)
         elif self._accept_unprefixed:
-            return [(self._namespace, ident)]
-        raise ValueError("Unknown namespace for identifier %r" % (ident, ))
+            return [(self._namespace, name)]
+        elif unprefixed_namespaces:
+            # A bit of a hack; this function ideally shouldn't look through the
+            # contents of namespaces; but since we aren't scanning anything
+            # without a prefix, it's not too bad.
+            for ns in unprefixed_namespaces:
+                if name in ns:
+                    return [(ns, name)]
+        else:
+            raise ValueError("Unknown namespace for %s %r"
+                % ('identifier' if is_identifier else 'symbol', name, ))
+
+    def split_ctype_namespaces(self, ident):
+        """Given a StudlyCaps string identifier like FooBar, return a
+list of (namespace, stripped_identifier) sorted by namespace length,
+or raise ValueError.  As a special case, if the current namespace matches,
+it is always biggest (i.e. last)."""
+        return self._split_c_string_for_namespace_matches(ident, is_identifier=True)
 
     def split_csymbol(self, symbol):
         """Given a C symbol like foo_bar_do_baz, return a pair of
 (namespace, stripped_symbol) or raise ValueError."""
-        matches = []
-        for ns in self._iter_namespaces():
-            for prefix in ns.symbol_prefixes:
-                if not prefix.endswith('_'):
-                    prefix = prefix + '_'
-                if symbol.startswith(prefix):
-                    matches.append((ns, symbol[len(prefix):], len(prefix)))
-                    break
+        matches = self._split_c_string_for_namespace_matches(symbol, is_identifier=False)
         if matches:
-            matches.sort(self._sort_matches)
             return (matches[-1][0], matches[-1][1])
-        elif self._accept_unprefixed:
-            return (self._namespace, symbol)
         raise ValueError("Unknown namespace for symbol %r" % (symbol, ))
 
     def strip_identifier_or_warn(self, ident, fatal=False):



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