+ return 0, val[2]
+
+ def _split_c_string_for_namespace_matches(self, name, is_identifier=False):
+ if not is_identifier and self._symbol_filter_cmd:
+ proc = subprocess.Popen(self._symbol_filter_cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ proc_name, err = proc.communicate(name.encode())
+ proc_name = proc_name.strip()
+ if proc.returncode:
+ raise ValueError('filter: %r exited: %d with error: %s' %
+ (self._symbol_filter_cmd, proc.returncode, err))
+ name = proc_name.decode('ascii')
+ name = name.strip()
+
+ matches = [] # Namespaces which might contain this name
+ unprefixed_namespaces = [] # Namespaces with no prefix, last resort
+ for ns in self._iter_namespaces():
+ if is_identifier:
+ prefixes = ns.identifier_prefixes
+ elif name[0].isupper():
+ prefixes = ns._ucase_symbol_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:
+ unprefixed_namespaces.append(ns)
+ if matches:
+ matches.sort(key=self._sort_matches)
+ return list(map(lambda x: (x[0], x[1]), matches))
+ elif self._accept_unprefixed:
+ 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)]
+ raise ValueError("Unknown namespace for %s '%s'"
+ % ('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_namespaces(self, symbol):
+ """Given a C symbol like foo_bar_do_baz, return a list of
+(namespace, stripped_symbol) sorted by namespace match probablity, or
+raise ValueError."""
+ return self._split_c_string_for_namespace_matches(symbol, is_identifier=False)
+
+ def split_csymbol(self, symbol):
+ """Given a C symbol like foo_bar_do_baz, return the most probable
+(namespace, stripped_symbol) match, or raise ValueError."""
+ matches = self._split_c_string_for_namespace_matches(symbol, is_identifier=False)
+ return matches[-1]
+
+ def strip_identifier(self, ident):
+ if self._identifier_filter_cmd:
+ proc = subprocess.Popen(self._identifier_filter_cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ proc_ident, err = proc.communicate(ident.encode())
+ if proc.returncode:
+ raise ValueError('filter: %r exited: %d with error: %s' %
+ (self._identifier_filter_cmd, proc.returncode, err))
+ ident = proc_ident.decode('ascii').strip()
+
+ hidden = ident.startswith('_')
+ if hidden:
+ ident = ident[1:]
+ try:
+ matches = self.split_ctype_namespaces(ident)
+ except ValueError as e:
+ raise TransformerException(str(e))
+ for ns, name in matches:
+ if ns is self._namespace:
+ if hidden:
+ return '_' + name
+ return name
+ (ns, name) = matches[-1]
+ raise TransformerException(
+ "Skipping foreign identifier '%s' from namespace %s" % (ident, ns.name, ))
+ return None
+
+ def _strip_symbol(self, symbol):
+ ident = symbol.ident
+ hidden = ident.startswith('_')
+ if hidden:
+ ident = ident[1:]
+ try:
+ (ns, name) = self.split_csymbol(ident)
+ except ValueError as e:
+ raise TransformerException(str(e))
+ if ns != self._namespace:
+ raise TransformerException(
+ "Skipping foreign symbol from namespace %s" % (ns.name, ))
+ if hidden:
+ return '_' + name