diff options
author | Jack Jansen <jack.jansen@cwi.nl> | 2000-12-14 22:29:58 (GMT) |
---|---|---|
committer | Jack Jansen <jack.jansen@cwi.nl> | 2000-12-14 22:29:58 (GMT) |
commit | 581fa783627b48f11cc2c4748574f9a895d00848 (patch) | |
tree | 80cccf2b575566b1356049c5ae0331fee8da1f12 /Mac | |
parent | 80716f0e618cc5689161cea55328e4c8bb1f4b3d (diff) | |
download | cpython-581fa783627b48f11cc2c4748574f9a895d00848.zip cpython-581fa783627b48f11cc2c4748574f9a895d00848.tar.gz cpython-581fa783627b48f11cc2c4748574f9a895d00848.tar.bz2 |
First stab at a script that mimicks Matthias Neerachers tool used to build GUSI.
Diffstat (limited to 'Mac')
-rw-r--r-- | Mac/scripts/unweave.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/Mac/scripts/unweave.py b/Mac/scripts/unweave.py new file mode 100644 index 0000000..8a5e80f --- /dev/null +++ b/Mac/scripts/unweave.py @@ -0,0 +1,164 @@ +"""An attempt at an unweave script. +Jack Jansen, jack@oratrix.com, 13-Dec-00 +""" +import re +import sys +import macfs +import os + +BEGINDEFINITION=re.compile("^<<(?P<name>.*)>>=\s*") +USEDEFINITION=re.compile("^(?P<pre>.*)<<(?P<name>.*)>>[^=]") +ENDDEFINITION=re.compile("^@") + +class Processor: + def __init__(self, filename): + self.items = {} + self.filename = filename + self.fp = open(filename) + self.lineno = 0 + self.resolving = {} + self.resolved = {} + self.pushback = None + + def _readline(self): + """Read a line. Allow for pushback""" + if self.pushback: + rv = self.pushback + self.pushback = None + return rv + self.lineno = self.lineno + 1 + return self.fp.readline() + + def _linedirective(self): + """Return a #line cpp directive for the current input file position""" + return '#line %d "%s"\n'%(self.lineno-2, os.path.split(self.filename)[1]) + + def _readitem(self): + """Read the definition of an item. Insert #line where needed. """ + rv = [self._linedirective()] + while 1: + line = self._readline() + if not line: + break + if ENDDEFINITION.search(line): + break + if BEGINDEFINITION.match(line): + self.pushback = line + break + mo = USEDEFINITION.match(line) + if mo: + pre = mo.group('pre') + if pre: + rv.append(pre+'\n') + rv.append(line) + # For simplicity we add #line directives now, if + # needed. + if mo: + rv.append(self._linedirective()) + return rv + + def _define(self, name, value): + """Define an item, or append to an existing definition""" + if self.items.has_key(name): + self.items[name] = self.items[name] + value + else: + self.items[name] = value + + def read(self): + """Read the source file and store all definitions""" + while 1: + line = self._readline() + if not line: break + mo = BEGINDEFINITION.search(line) + if mo: + name = mo.group('name') + value = self._readitem() + self._define(name, value) + else: + pass # We could output the TeX code but we don't bother. + + def resolve(self): + """Resolve all references""" + for name in self.items.keys(): + self._resolve_one(name) + + def _resolve_one(self, name): + """Resolve references in one definition, recursively""" + # First check for unknown macros and recursive calls + if not self.items.has_key(name): + print "Undefined macro:", name + return ['<<%s>>'%name] + if self.resolving.has_key(name): + print "Recursive macro:", name + return ['<<%s>>'%name] + # Then check that we haven't handled this one before + if self.resolved.has_key(name): + return self.items[name] + # No rest for the wicked: we have work to do. + self.resolving[name] = 1 + result = [] + for line in self.items[name]: + mo = USEDEFINITION.search(line) + if mo: + # We replace the complete line. Is this correct? + macro = mo.group('name') + replacement = self._resolve_one(macro) + result = result + replacement + else: + result.append(line) + self.items[name] = result + self.resolved[name] = 1 + del self.resolving[name] + return result + + def save(self, dir, pattern): + """Save macros that match pattern to folder dir""" + # Compile the pattern, if needed + if type(pattern) == type(''): + pattern = re.compile(pattern) + # If the directory is relative it is relative to the sourcefile + if not os.path.isabs(dir): + sourcedir = os.path.split(self.filename)[0] + dir = os.path.join(sourcedir, dir) + for name in self.items.keys(): + if pattern.search(name): + pathname = os.path.join(dir, name) + data = self._stripduplines(self.items[name]) + self._dosave(pathname, data) + + def _stripduplines(self, data): + for i in range(len(data)-1, 0, -1): + if data[i][:5] == '#line' and data[i-1][:5] == '#line': + del data[i-1] + if data[-1][:5] == '#line': + del data[-1] + return data + + def _dosave(self, pathname, data): + """Save data to pathname, unless it is identical to what is there""" + if os.path.exists(pathname): + olddata = open(pathname).readlines() + if olddata == data: + return + fp = open(pathname, "w").writelines(data) + +def process(file): + pr = Processor(file) + pr.read() + pr.resolve() + pr.save(":jacktest:src", "^.*\.cp$") + pr.save(":jacktest:include", "^.*\.h") + +def main(): + if len(sys.argv) > 1: + for file in sys.argv: + print "Processing", file + process(file) + else: + fss, ok = macfs.PromptGetFile("Select .nw source file", "TEXT") + if not ok: + sys.exit(0) + process(fss.as_pathname()) + +if __name__ == "__main__": + main() |