]> granicus.if.org Git - python/commitdiff
First stab at a script that mimicks Matthias Neerachers tool used to build GUSI.
authorJack Jansen <jack.jansen@cwi.nl>
Thu, 14 Dec 2000 22:29:58 +0000 (22:29 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Thu, 14 Dec 2000 22:29:58 +0000 (22:29 +0000)
Mac/scripts/unweave.py [new file with mode: 0644]

diff --git a/Mac/scripts/unweave.py b/Mac/scripts/unweave.py
new file mode 100644 (file)
index 0000000..8a5e80f
--- /dev/null
@@ -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()