summaryrefslogtreecommitdiff
path: root/macro.py
diff options
context:
space:
mode:
authorPeter Simons <simons@cryp.to>2009-04-30 01:43:11 +0200
committerPeter Simons <simons@cryp.to>2009-05-05 01:43:35 +0200
commit3b300028e416c3a787e26157602c00eefa47b895 (patch)
tree8cd7ae0b589cf96a9c5872b948069b8f74820e10 /macro.py
parent04e8fe01cc30aa770fbee37f1c9814bf1c77a245 (diff)
downloadautoconf-archive-3b300028e416c3a787e26157602c00eefa47b895.tar.gz
maint: added initial version of the toolchain
The build process requires python, the python StringTemplate module, and preferably SCons. A make-based build exists, but it is really slow and awkward, compared to the SConstruct file.
Diffstat (limited to 'macro.py')
-rwxr-xr-xmacro.py136
1 files changed, 136 insertions, 0 deletions
diff --git a/macro.py b/macro.py
new file mode 100755
index 0000000..69f838c
--- /dev/null
+++ b/macro.py
@@ -0,0 +1,136 @@
+#! /usr/bin/env python
+
+from __future__ import with_statement
+from contextlib import closing
+import re
+import os.path as path
+import sys
+import textwrap
+import encodings
+
+def loadFile(path, encoding):
+ with closing( encodings.search_function(encoding).streamreader(open(path)) ) as fd:
+ return fd.read()
+
+def writeFile(path, encoding, buffer):
+ with closing( encodings.search_function(encoding).streamwriter(open(path, "w")) ) as fd:
+ fd.write(buffer)
+
+def splitSections(buffer):
+ while buffer:
+ assert len(buffer) >= 3
+ name = buffer.pop(0).lower()
+ assert buffer.pop(0) == ''
+ body = []
+ while buffer:
+ line = buffer.pop(0)
+ if line == '' or line[0].isspace():
+ body.append(line[2:])
+ else:
+ buffer.insert(0, line)
+ yield (name, body)
+ body = []
+ break
+ if body:
+ yield (name, body)
+
+def collapseText(lines, width = 72):
+ wrapper = textwrap.TextWrapper( width = width
+ , expand_tabs = False
+ , break_on_hyphens = False
+ , break_long_words = False
+ )
+ body = []
+ prev = None
+ for line in lines:
+ if line == '':
+ prev = None
+ elif line[0].isspace():
+ if prev == "quote":
+ body[-1].append(line)
+ else:
+ body.append([line])
+ prev = "quote"
+ else:
+ if prev == "text":
+ newtext = ' '.join(body[-1]) + ' ' + line
+ body[-1] = wrapper.wrap(newtext)
+ else:
+ body.append(wrapper.wrap(line))
+ prev = "text"
+ return body
+
+class Macro:
+ def __init__(self, filePath, encoding):
+ self.name = path.splitext(path.basename(filePath))[0]
+ # header and body are separated by an empty line.
+ (header,body) = loadFile(filePath, encoding).split("\n\n", 1)
+ self.body = body.split('\n')
+ # drop initial header (if present)
+ header = re.sub(r"^\n*# =+\n#[^\n]*\n# =+\n(#\n)+", '', header, 1)
+ # split buffer into lines and drop initial "# " prefix in the process
+ header = map(lambda l: l[2:], header.split('\n'))
+ # set defaults
+ self.authors = []
+ url = "http://www.nongnu.org/autoconf-archive/%s" % (self.name + ".html")
+ lineLen = max(75,len(url) + 2)
+ separator = '=' * lineLen
+ self.m4header = "# %s\n"*3 % (separator, url.center(lineLen), separator)
+ # parse each section in the remaining list
+ for (key, body) in splitSections(header):
+ # drop empty lines at beginning and end of body
+ while body[0] == '': body.pop(0)
+ while body[-1] == '': body.pop(-1)
+ # each section has its own parser
+ if key == "synopsis":
+ if '' in body:
+ raise Exception("%s: malformed synopsis section" % filePath)
+ elif key == "description":
+ body = collapseText(body)
+ elif key == "license":
+ while True:
+ match = re.match(r"Copyright \(c\) ([0-9]+) (.*)", body[0])
+ if not match: break
+ (year,name) = (match.group(1), match.group(2))
+ match = re.match(r"(.*) <(.*)>", name)
+ if match:
+ (name,email) = (match.group(1), match.group(2))
+ self.authors.append(dict(year = year, name = name, email = email))
+ else:
+ self.authors.append(dict(year = year, name = name))
+ body.pop(0)
+ assert self.authors
+ if body.pop(0) != '':
+ raise Exception("%s: malformed license section" % filePath)
+ body = collapseText(body)
+ else:
+ raise Exception("%s: unknown section %r in macro" % (filePath, key))
+ self.__dict__[key] = body
+
+ def __repr__(self):
+ return repr(self.__dict__)
+
+if __name__ == "__main__":
+ from stringtemplate3 import StringTemplateGroup, StringTemplate
+ from optparse import OptionParser
+
+ opts = OptionParser()
+ opts.add_option('', "--input-encoding", dest = "inEncode", default = "latin1")
+ opts.add_option('', "--output-encoding", dest = "outEncode", default = "latin1")
+ opts.add_option('', "--template-lexer", dest = "lexer", default = "angle-bracket")
+ opts.add_option('', "--output-dir", dest = "outDir", default = "stage")
+ opts.add_option('', "--output-suffix", dest = "suffix", default = ".m4")
+ (options, args) = opts.parse_args()
+ stFile = args.pop(0)
+ formatter = StringTemplateGroup(fileName = stFile, lexer = options.lexer)
+ for m4File in args:
+ (stem,suff) = path.splitext(path.basename(m4File))
+ assert suff == ".m4"
+ outFile = path.join(options.outDir, stem + options.suffix)
+ assert outFile != m4File
+ print m4File, "->", outFile
+ m = Macro(m4File, options.inEncode)
+ f = formatter.getInstanceOf("canon")
+ for (k,v) in m.__dict__.items():
+ f[k] = v
+ writeFile(outFile, options.outEncode, f.toString().strip() + '\n')