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*
16 comment ::= '#' text '\n'
17 empty-comment ::= '#' '\n'
18 text ::= [^#] ... '\n'
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 mark of the form #OMK@<snippet file name><EOL>. This mark
27 is used for splitting modified Makefile.rules back to the
28 original snippets. If <snippet file name> starts with __, it is
29 ignored during splitting.
32 from optparse import OptionParser
40 snippetsDir = "snippets"
43 """List of text lines"""
44 def getDiff(self, other):
46 for i in range(len(self)):
48 s += (" Line %d differs!\n" % i)
49 s += " -"+self[i].rstrip() + "\n"
52 if self[i] != other[i]:
53 s += (" Line %d differs!\n" % i)
54 s += " -"+self[i].rstrip() + "\n"
55 s += " +"+other[i].rstrip() + "\n"
64 def loadFromFile(self, fname):
65 """Loads itself from file."""
69 sys.stderr.write("Cannot open %s\n" % fname)
72 self.extend(f.readlines())
76 def __init__(self, fname = None, name = ""):
77 """Initializes the snippet and if fname is given, reads it
80 self.legal = LineList()
82 self.code = LineList()
83 if fname: self.loadFromFile(fname)
85 def loadFromFile(self, fname):
86 """Loads snippet from file."""
90 self.readLines(f.readlines())
94 def addCodeLine(self, line):
95 self.code.append(line)
97 def readLines(self, lines):
98 """Parses the snippet given as a list and stores it in itself."""
99 currentPart = self.legal
103 if currentPart == self.legal:
104 if line.strip() == "#": counter += 1
106 if counter == 2: currentPart = self.doc
107 if line[0] != "#": currentPart = self.code
109 currentPart.append(line)
112 self.doc = self.legal
113 self.legal = LineList()
115 def asLinesList(self):
117 for type in ['legal', 'doc', 'code']:
118 for line in self.__dict__[type]:
123 return str(self.asLinesList())
126 s = "<Snippet: %s>" % self.name
129 def __cmp__(self, other):
130 ret = cmp(self.name, other.name)
131 if ret != 0: return ret
132 ret = cmp(self.legal, other.legal)
133 if ret != 0: return ret
134 ret = cmp(self.doc, other.doc)
135 if ret != 0: return ret
136 ret = cmp(self.code, other.code)
139 def __getitem__(self, key):
146 def getDiff(self, other):
147 return self.asLinesList().getDiff(other.asLinesList())
150 """Collection of snippets, where snippets can be accessed
151 individually by name (like dictionary) or sequentionaly in the
152 order they were added."""
154 self._snippets = dict()
157 def __iadd__(self, snippet):
158 assert isinstance(snippet, Snippet)
159 self._snippets[snippet.name] = snippet
160 self._order += [snippet]
163 def __getitem__(self, key):
164 return self._snippets[key]
166 def __contains__(self, item):
167 return item in self._snippets
170 return iter(self._order)
172 def __cmp__(self, other):
173 return cmp(self._snippets, other._snippets)
175 def loadFromFiles(self, fnames):
176 """Reads the snippets from several files and adds them to itself."""
180 def loadFromDict(self, snipDict):
181 """Adds snippets to itself from dictionary of LineLists."""
185 snip.readLines(snipDict[s])
188 def getDiff(self, other):
189 assert isinstance(other, Snippets)
192 if (snip.name[0:2] == '__'): continue
193 if (snip != other[snip.name]):
194 s += "Snippet %s:\n" % snip.name
195 s += snip.getDiff(other[snip.name])
198 class MakefileRules(LineList):
200 self.snippets = Snippets()
201 self.rules = LineList()
204 """Combine self.snippets and produces self.rules"""
205 self.rules = LineList()
207 for type in ['legal', 'doc', 'code']:
208 for snip in self.snippets:
210 if len(lines) == 0: continue
211 firstLine = string.rstrip(lines[0])
212 self.rules += [firstLine.ljust(60)+" #OMK@%s\n"%snip.name]
213 self.rules += lines[1:]
214 #self.rules += ['a'] # test error
217 """Split self.rules to the original snippets in self.snippets."""
218 self.snippets = Snippets()
219 snipDict = self._getSnipDicts()
220 self.snippets.loadFromDict(snipDict)
222 def _getSnipDicts(self):
223 """Split self.rules to the original snippets, which are
224 returened as dictionary of LineLists."""
225 snipBegin = re.compile("^(.*)#OMK@(.*)$")
227 currentLinesList = None
229 for line in self.rules:
230 match = snipBegin.match(line)
232 line = match.group(1).rstrip() + "\n"
233 snipName = match.group(2)
234 if not snipName in snipDict:
235 snipDict[snipName] = LineList()
236 currentLinesList = snipDict[snipName]
238 if currentLinesList != None:
239 currentLinesList.append(line);
244 def parseCommandLine():
245 parser = OptionParser(usage = """
246 %prog [-o FILE] snippet1 snippet2 ... build Makefile.rules from snippets
247 %prog [-o - ] -s Makfile.rules
249 parser.add_option("-s", "--split",
250 action="store", dest="split", default=False, metavar="RULES",
251 help="Split given Makefile.rules to the original snippets")
252 parser.add_option("-o", "--output",
253 action="store", dest="output", default=False, metavar="RULES",
254 help="Write Makefile.rules to file RULES")
255 parser.add_option("-a", "--all",
256 action="store_true", dest="all",
257 help="Rebuild all rules acording to rulesdef.py")
258 (options, args) = parser.parse_args()
261 def buildRules(fnames, output, name):
262 rules = MakefileRules()
263 snip_rule_type = Snippet(name="__type")
264 snip_rule_type.addCodeLine("OMK_RULES_TYPE=%s\n" % name)
265 rules.snippets += snip_rule_type
266 rules.snippets.loadFromFiles(fnames)
269 rulesCheck = MakefileRules()
270 rulesCheck.rules = rules.rules
273 if rules.snippets != rulesCheck.snippets:
274 sys.stderr.write("Consistency error:\n")
275 diff = rules.snippets.getDiff(rulesCheck.snippets)
276 sys.stderr.write(diff)
279 if output: f = open(output,"w+")
281 f.writelines(rules.rules)
284 def splitRules(rulesFN, output):
285 rules = MakefileRules()
286 rules.rules.loadFromFile(rulesFN)
289 rulesCheck = MakefileRules()
290 rulesCheck.snippets = rules.snippets
293 # The comparsion is not that simple. The order of rules might be
295 # if rules.rules != rulesCheck.rules:
296 # sys.stderr.write("Consistency error:\n")
297 # diff = rules.rules.getDiff(rulesCheck.rules)
298 # sys.stderr.write(diff)
301 for snip in rules.snippets:
302 if snip.name[0:2] == "__":
306 if output == "-": f = sys.stdout
307 else: f = open(snip.name, "w+")
308 f.writelines(snip.asLinesList())
313 os.chdir(snippetsDir)
314 for rules in rulesdef.rules:
315 print 'Building rules: %s' % rules
316 outputDir = os.path.join(sys.path[0], rulesDir, rules)
317 if not os.path.isdir(outputDir): os.makedirs(outputDir)
318 buildRules(rulesdef.rules[rules], os.path.join(outputDir, 'Makefile.rules'), rules)
321 (options, args) = parseCommandLine()
325 splitRules(options.split, options.output)
327 buildRules(args, options.output)
330 if __name__ == "__main__": main()