3 This script has two main functions:
5 1) Combine several snippets to form Makefile.rules file
6 2) Split Makefile.rules file to the originnal snippets
10 snippet ::= legal? documentation rules
12 legal ::= comment* empty-comment empty-comment
13 documentation := comment*
20 Makefile.rules policies:
22 * All the parts of the Makefile.rules are ordered in the same order
23 as they are in snippets i.e. copyrights, documentations and rules.
25 * On the first line of each part of the Makefile.rules, there is
26 special mart of the form #OMK@<snippet file name><EOL>. This mark
27 is used for splitting Makefile.rules back to the original
32 from optparse import OptionParser
39 """List of text lines"""
40 def getDiff(self, other):
42 for i in range(len(self)):
43 if self[i] != other[i]:
44 s += (" Line %d differs!\n" % i)
45 s += " -"+self[i].rstrip() + "\n"
46 s += " +"+other[i].rstrip() + "\n"
55 def loadFromFile(self, fname):
56 """Loads itself from file."""
58 self.expand(f.readlines())
62 def __init__(self, fname = None):
63 """Initializes the snippet and if fname is given, reads it
66 self.legal = LineList()
68 self.code = LineList()
69 if fname: self.loadFromFile(fname)
71 def loadFromFile(self, fname):
72 """Loads snippet from file."""
76 self.readLines(f.readlines())
80 def readLines(self, lines):
81 """Parses the snippet given as a list and stores it in itself."""
82 currentPart = self.legal
86 if currentPart == self.legal:
87 if line.strip() == "#": counter += 1
89 if counter == 2: currentPart = self.doc
90 if line[0] != "#": currentPart = self.code
92 currentPart.append(line)
96 self.legal = LineList()
98 def asLinesList(self):
100 for type in ['legal', 'doc', 'code']:
101 for line in self.__dict__[type]:
106 return str(self.asLinesList())
109 s = "<Snippet: %s>" % self.name
112 def __cmp__(self, other):
113 ret = cmp(self.name, other.name)
114 if ret != 0: return ret
115 ret = cmp(self.legal, other.legal)
116 if ret != 0: return ret
117 ret = cmp(self.doc, other.doc)
118 if ret != 0: return ret
119 ret = cmp(self.code, other.code)
122 def __getitem__(self, key):
129 def getDiff(self, other):
130 return self.asLinesList().getDiff(other.asLinesList())
133 """Collection of snippets, where snippets can be accessed
134 individually by name (like dictionary) or sequentionaly in the
135 order they were added."""
137 self._snippets = dict()
140 def __iadd__(self, snippet):
141 assert isinstance(snippet, Snippet)
142 self._snippets[snippet.name] = snippet
143 self._order += [snippet]
146 def __getitem__(self, key):
147 return self._snippets[key]
149 def __contains__(self, item):
150 return item in self._snippets
153 return iter(self._order)
155 def __cmp__(self, other):
156 return cmp(self._snippets, other._snippets)
158 def loadFromFiles(self, fnames):
159 """Reads the snippets from several files and adds them to itself."""
163 def loadFromDict(self, snipDict):
164 """Adds snippets to itself from dictionary of LineLists."""
168 snip.readLines(snipDict[s])
171 def getDiff(self, other):
172 assert isinstance(other, Snippets)
175 if (snip != other[snip.name]):
176 s += "Snippet %s:\n" % snip.name
177 s += snip.getDiff(other[snip.name])
180 class MakefileRules(LineList):
182 self.snippets = Snippets()
183 self.rules = LineList()
186 """Combine self.snippets and produces self.rules"""
187 self.rules = LineList()
189 for type in ['legal', 'doc', 'code']:
190 for snip in self.snippets:
192 if len(lines) == 0: continue
193 firstLine = string.rstrip(lines[0])
194 self.rules += [firstLine.ljust(60)+" #OMK@%s\n"%snip.name]
195 self.rules += lines[1:]
196 #self.rules += ['a'] # test error
199 """Split self.rules to the original snippets in self.snippets."""
200 self.snippets = Snippets()
201 snipDict = self._getSnipDicts()
202 self.snippets.loadFromDict(snipDict)
204 def _getSnipDicts(self):
205 """Split self.rules to the original snippets, which are
206 returened as dictionary of LineLists."""
207 snipBegin = re.compile("^(.*)#OMK@(.*)$")
209 currentLinesList = None
211 for line in self.rules:
212 match = snipBegin.match(line)
214 line = match.group(1).rstrip() + "\n"
215 snipName = match.group(2)
216 if not snipName in snipDict:
217 snipDict[snipName] = LineList()
218 currentLinesList = snipDict[snipName]
220 currentLinesList.append(line);
224 def parseCommandLine():
225 parser = OptionParser(usage = """
226 %prog [-o FILE] snippet1 snippet2 ... build Makefile.rules from snippets
227 %prog [-o - ] -s Makfile.rules
229 parser.add_option("-s", "--split",
230 action="store", dest="split", default=False, metavar="RULES",
231 help="Split given Makefile.rules to the original snippets")
232 parser.add_option("-o", "--output",
233 action="store", dest="output", default=False, metavar="RULES",
234 help="Output built Makefile.rules to file RULES")
235 (options, args) = parser.parse_args()
238 def buildRules(fnames, output):
239 rules = MakefileRules()
240 rules.snippets.loadFromFiles(fnames)
243 rulesCheck = MakefileRules()
244 rulesCheck.rules = rules.rules
247 if rules.snippets != rulesCheck.snippets:
248 sys.stderr.write("Consistency error:\n")
249 diff = rules.snippets.getDiff(rulesCheck.snippets)
250 sys.stderr.write(diff)
253 if output: f = open(output,"w+")
255 f.writelines(rules.rules)
258 def splitRules(rulesFN, output):
259 rules = MakefileRules()
260 rules.rules.loadFromFile(rulesFN)
263 rulesCheck = MakefileRules()
264 rulesCheck.snippets = rules.snippets
267 if rules.rules != rulesCheck.rules:
268 sys.stderr.write("Consistency error:\n")
269 diff = rules.rules.getDiff(rulesCheck.rules)
270 sys.stderr.write(diff)
273 #TODO: Store snippets to files
276 (options, args) = parseCommandLine()
278 splitRules(options.split, options.output)
280 buildRules(args, options.output)
283 if __name__ == "__main__": main()