+ def __getitem__(self, key):
+ return {
+ 'legal': self.legal,
+ 'doc' : self.doc,
+ 'code' : self.code
+ }[key]
+
+ def getDiff(self, other):
+ return self.asLinesList().getDiff(other.asLinesList())
+
+class Snippets:
+ """Collection of snippets, where snippets can be accessed
+ individually by name (like dictionary) or sequentionaly in the
+ order they were added."""
+ def __init__(self):
+ self._snippets = dict()
+ self._order = list()
+
+ def __iadd__(self, snippet):
+ assert isinstance(snippet, Snippet)
+ self._snippets[snippet.name] = snippet
+ self._order += [snippet]
+ return self
+
+ def __getitem__(self, key):
+ return self._snippets[key]
+
+ def __contains__(self, item):
+ return item in self._snippets
+
+ def __iter__(self):
+ return iter(self._order)
+
+ def __cmp__(self, other):
+ return cmp(self._snippets, other._snippets)
+
+ def loadFromFiles(self, fnames):
+ """Reads the snippets from several files and adds them to itself."""
+ for fn in fnames:
+ self += Snippet(fn)
+
+ def loadFromDict(self, snipDict):
+ """Adds snippets to itself from dictionary of LineLists."""
+ for s in snipDict:
+ snip = Snippet()
+ snip.name = s
+ snip.readLines(snipDict[s])
+ self += snip
+
+ def getDiff(self, other):
+ assert isinstance(other, Snippets)
+ s = ''
+ for snip in self:
+ if (snip.name[0:2] == '__'): continue
+ if (snip != other[snip.name]):
+ s += "Snippet %s:\n" % snip.name
+ 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 _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()
+
+ 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(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()
+ snipDict = self._getSnipDicts()
+ self.snippets.loadFromDict(snipDict)
+
+ def _getSnipDicts(self):
+ """Split self.rules to the original snippets, which are
+ returened as dictionary of LineLists."""
+ snipBegin = re.compile("^(.*)#OMK:([^@]*)(?:@(.*))?\n$")
+ snipDict = dict()
+ currentLinesList = None
+
+ for line in self.rules:
+ match = snipBegin.match(line)
+ 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]
+
+ if currentLinesList != None:
+ currentLinesList.append(line);
+
+ return snipDict
+
+