Modules |
Files |
Inheritance Tree |
Inheritance Graph |
Name Index |
Config
File: Synopsis/Linker/Stripper.py
1| # $Id: Stripper.py,v 1.4 2002/10/29 06:56:52 chalky Exp $
2| #
3| # This file is a part of Synopsis.
4| # Copyright (C) 2000, 2001 Stefan Seefeld
5| # Copyright (C) 2000, 2001 Stephen Davies
6| #
7| # Synopsis is free software; you can redistribute it and/or modify it
8| # under the terms of the GNU General Public License as published by
9| # the Free Software Foundation; either version 2 of the License, or
10| # (at your option) any later version.
11| #
12| # This program is distributed in the hope that it will be useful,
13| # but WITHOUT ANY WARRANTY; without even the implied warranty of
14| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15| # General Public License for more details.
16| #
17| # You should have received a copy of the GNU General Public License
18| # along with this program; if not, write to the Free Software
19| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20| # 02111-1307, USA.
21| #
22| # $Log: Stripper.py,v $
23| # Revision 1.4 2002/10/29 06:56:52 chalky
24| # Fixes to work on cygwin
25| #
26| # Revision 1.3 2002/10/28 16:30:05 chalky
27| # Trying to fix some bugs in the unduplication/stripping stages. Needs more work
28| #
29| # Revision 1.2 2002/10/11 05:57:17 chalky
30| # Support suspect comments
31| #
32| # Revision 1.1 2002/08/23 04:37:26 chalky
33| # Huge refactoring of Linker to make it modular, and use a config system similar
34| # to the HTML package
35| #
36|
37| import string
38|
39| from Synopsis.Core import AST, Type, Util
40|
41| from Linker import config, Operation
42|
43| def filterName(name, prefixes):
44| if not prefixes: return 1
45| for prefix in prefixes:
46| if Util.ccolonName(name)[:len(prefix)] == prefix:
47| return 1
48| return 0
49|
50| class Stripper(Operation, AST.Visitor):
51| """Strip common prefix from the declaration's name.
52| Keep a list of root nodes, such that children whos parent
53| scopes are not accepted but which themselfs are correct can
54| be maintained as new root nodes."""
55| def __init__(self):
56| self.__strip = config.strip
57| splitter = lambda x: tuple(string.split(x, "::"))
58| self.__scopes = map(splitter, self.__strip)
59| self.__root = []
60| self.__in = 0
61|
62| def execute(self, ast):
63| if not self.__strip: return
64|
65| # strip prefixes and remove non-matching declarations
66| self.stripDeclarations(ast.declarations())
67|
68| # Remove types not in strip
69| self.stripTypes(ast.types())
70|
71| def _stripName(self, name):
72| for scope in self.__scopes:
73| depth = len(scope)
74| if name[0:depth] == scope:
75| if len(name) == depth: return None
76| return name[depth:]
77| return None
78| def stripDeclarations(self, declarations):
79| for decl in declarations:
80| decl.accept(self)
81| declarations[:] = self.declarations()
82|
83| def stripTypes(self, types):
84| prefixes = self.__strip
85| # Remove the empty type (caused by C++ with extract_tails)
86| if types.has_key(()): del types[()]
87| if not prefixes: return
88| for name, type in types.items():
89| try:
90| del types[name]
91| name = self._stripName(name)
92| if name:
93| type.set_name(name)
94| types[name] = type
95| except:
96| print "ERROR Processing:",name,types[name]
97| raise
98|
99| def declarations(self): return self.__root
100|
101| def strip(self, declaration):
102| """test whether the declaration matches one of the prefixes, strip
103| it off, and return success. Success means that the declaration matches
104| the prefix set and thus should not be removed from the AST."""
105| passed = 0
106| if not self.__scopes: return 1
107| for scope in self.__scopes:
108| depth = len(scope)
109| name = declaration.name()
110| if name[0:depth] == scope:
111| if len(name) == depth: break
112| if config.verbose: print "symbol", string.join(name, "::"),
113| declaration.set_name(name[depth:])
114| if config.verbose: print "stripped to", string.join(name, "::")
115| passed = 1
116| else: break
117| if config.verbose and not passed: print "symbol", string.join(declaration.name(), "::"), "removed"
118| return passed
119|
120| def visitScope(self, scope):
121| root = self.strip(scope) and not self.__in
122| if root:
123| self.__in = 1
124| self.__root.append(scope)
125| for declaration in scope.declarations():
126| declaration.accept(self)
127| if root: self.__in = 0
128|
129| def visitClass(self, clas):
130| self.visitScope(clas)
131| templ = clas.template()
132| if templ:
133| name = self._stripName(templ.name())
134| if name: templ.set_name(name)
135|
136| def visitDeclaration(self, decl):
137| if self.strip(decl) and not self.__in:
138| self.__root.append(decl)
139|
140| def visitEnumerator(self, enumerator):
141| self.strip(enumerator)
142|
143| def visitEnum(self, enum):
144| self.visitDeclaration(enum)
145| for e in enum.enumerators():
146| e.accept(self)
147|
148| def visitFunction(self, function):
149| self.visitDeclaration(function)
150| for parameter in function.parameters():
151| parameter.accept(self)
152| templ = function.template()
153| if templ:
154| name = self._stripName(templ.name())
155| if name: templ.set_name(name)
156|
157| def visitOperation(self, operation):
158| self.visitFunction(operation)
159|
160| def visitMetaModule(self, module):
161| self.visitScope(module)
162| for decl in module.module_declarations():
163| name = self._stripName(decl.name())
164| if name: decl.set_name(name)
165|
166| linkerOperation = Stripper