as they are in snippets i.e. copyrights, documentations and rules.
* On the first line of each part of the Makefile.rules, there is
- special mark of the form #OMK@<snippet file name><EOL>. This mark
- is used for splitting modified Makefile.rules back to the
- original snippets. If <snippet file name> starts with __, it is
- ignored during splitting.
+ special mark of the form:
+
+ #OMK:<snippet file name>[@<included from snippet>]<EOL>
+
+ This mark is used for splitting modified Makefile.rules back to
+ the original snippets. If <snippet file name> starts with __, it
+ is ignored during splitting.
+
+ * Toplevel snippet has name in the forb Makefile.rules.* and no
+ other (included) snippet has such name.
"""
from optparse import OptionParser
s += snip.getDiff(other[snip.name])
return s
+# Include directoves matching this r.e. will be replaced by this script
+reInclude = re.compile("^include ([^ ]*) #omkbuild")
+
class MakefileRules(LineList):
def __init__(self):
self.snippets = Snippets()
self.rules = LineList()
- def combine(self):
- """Combine self.snippets and produces self.rules"""
+ def _includeSnippets(self, filename, baseFileName="", onlyLoadSnippets=False):
+ """Recursively traverses snippets according to include
+ directives. If onlyLoadSnippets is True, self.rules is not
+ modified ..."""
+
+ if onlyLoadSnippets:
+ if filename in self.snippets:
+ sys.stderr.write("Error: Snippet included more than once\n")
+ # This is not allowed becouse it would cause problems
+ # during spliting
+ sys.exit(1)
+ self.snippets += Snippet(filename)
+
+ lines = self.snippets[filename]['code']
+
+ addMarker = 1 # The first line of the snippet should be marked
+ for line in lines:
+ match = reInclude.match(line)
+ if match:
+ # Include other snippet
+ self._includeSnippets(match.group(1).strip(),\
+ filename,
+ onlyLoadSnippets)
+ addMarker = 2 # The next line after include should be marked
+ else:
+ # Add this line to rules
+ if addMarker:
+ if addMarker==1:
+ line = string.rstrip(line).ljust(80)+" #OMK:%s@%s\n"%(filename,baseFileName)
+ elif addMarker==2:
+ line = string.rstrip(line).ljust(80)+" #OMK:%s\n"%(filename)
+ addMarker = 0
+ if not onlyLoadSnippets:
+ self.rules += [line]
+
+ def combineFrom(self, topLevelSnippet, onlyCheck=False):
+ """Produces self.rules from the topLevelSnippet and all
+ snippets included directly or indirectly from it."""
self.rules = LineList()
- for type in ['legal', 'doc', 'code']:
+ if not onlyCheck:
+ self._includeSnippets(topLevelSnippet, onlyLoadSnippets=True)
+
+ # Append legal and doc parts
+ for type in ['legal', 'doc']:
for snip in self.snippets:
lines = snip[type]
if len(lines) == 0: continue
firstLine = string.rstrip(lines[0])
- self.rules += [firstLine.ljust(60)+" #OMK@%s\n"%snip.name]
+ self.rules += [firstLine.ljust(80)+" #OMK:%s\n"%snip.name]
self.rules += lines[1:]
#self.rules += ['a'] # test error
+ # Append code parts
+ self._includeSnippets(topLevelSnippet)
+
+
def split(self):
"""Split self.rules to the original snippets in self.snippets."""
self.snippets = Snippets()
def _getSnipDicts(self):
"""Split self.rules to the original snippets, which are
returened as dictionary of LineLists."""
- snipBegin = re.compile("^(.*)#OMK@(.*)$")
+ snipBegin = re.compile("^(.*)#OMK:([^@]*)(?:@(.*))?\n$")
snipDict = dict()
currentLinesList = None
if match:
line = match.group(1).rstrip() + "\n"
snipName = match.group(2)
+ includedFrom = match.group(3)
+ if includedFrom:
+ if not includedFrom in snipDict: snipDict[includedFrom] = LineList()
+ snipDict[includedFrom].append("include %s #omkbuild\n" % snipName);
+
if not snipName in snipDict:
snipDict[snipName] = LineList()
currentLinesList = snipDict[snipName]
def parseCommandLine():
parser = OptionParser(usage = """
- %prog [-o FILE] snippet1 snippet2 ... build Makefile.rules from snippets
+ %prog [-o FILE] top-level-snippet build Makefile.rules from the top-level-snippet and included ones
%prog [-o - ] -s Makfile.rules
""")
parser.add_option("-s", "--split",
parser.add_option("-o", "--output",
action="store", dest="output", default=False, metavar="RULES",
help="Write Makefile.rules to file RULES")
- parser.add_option("-a", "--all",
- action="store_true", dest="all",
- help="Rebuild all rules acording to rulesdef.py")
(options, args) = parser.parse_args()
+ if len(args) > 1:
+ parser.print_help()
+ sys.exit(1)
return options, args
-def buildRules(fnames, output, name):
+def buildRules(topLevelSnippet, output):
rules = MakefileRules()
- snip_rule_type = Snippet(name="__type")
- snip_rule_type.addCodeLine("OMK_RULES_TYPE=%s\n" % name)
- rules.snippets += snip_rule_type
- rules.snippets.loadFromFiles(fnames)
- rules.combine()
+ rules.combineFrom(topLevelSnippet)
rulesCheck = MakefileRules()
rulesCheck.rules = rules.rules
sys.stderr.write(diff)
sys.exit(1)
- if output: f = open(output,"w+")
+ if output:
+ try: os.makedirs(os.path.dirname(output))
+ except: pass
+ f = open(output,"w+")
else: f = sys.stdout
f.writelines(rules.rules)
f.close()
rulesCheck = MakefileRules()
rulesCheck.snippets = rules.snippets
- rulesCheck.combine()
+
+ topLevelSnippet = None
+ for snip in rules.snippets:
+ if snip.name.startswith("Makefile.rules."):
+ topLevelSnippet = snip.name
+ if not topLevelSnippet:
+ sys.stderr.write("No toplevel snippet (Makefile.rules.*) found\n")
+ sys.exit(1)
+
+ rulesCheck.combineFrom(topLevelSnippet, onlyCheck=True)
# The comparsion is not that simple. The order of rules might be
- # different.
+ # different. FIXME: Is this still true?
# if rules.rules != rulesCheck.rules:
# sys.stderr.write("Consistency error:\n")
# diff = rules.rules.getDiff(rulesCheck.rules)
f.writelines(snip.asLinesList())
f.close()
-def buildAllRules():
- import rulesdef
- os.chdir(snippetsDir)
- for rules in rulesdef.rules:
- print 'Building rules: %s' % rules
- outputDir = os.path.join(sys.path[0], rulesDir, rules)
- if not os.path.isdir(outputDir): os.makedirs(outputDir)
- buildRules(rulesdef.rules[rules], os.path.join(outputDir, 'Makefile.rules'), rules)
-
def main():
(options, args) = parseCommandLine()
- if options.all:
- buildAllRules()
- elif options.split:
+ if options.split:
splitRules(options.split, options.output)
else:
- buildRules(args, options.output)
+ buildRules(args[0], options.output)
if __name__ == "__main__": main()