First stab at a script that mimicks Matthias Neerachers tool used to build GUSI.
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()