summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/build/complay.py193
1 files changed, 138 insertions, 55 deletions
diff --git a/scripts/build/complay.py b/scripts/build/complay.py
index c8a61396dce..c44cc1e678f 100644
--- a/scripts/build/complay.py
+++ b/scripts/build/complay.py
@@ -1,69 +1,152 @@
#!/usr/bin/python
##
## license:BSD-3-Clause
-## copyright-holders:Aaron Giles, Andrew Gardner
+## copyright-holders:Vas Crabb
-from __future__ import with_statement
-
-import sys
import os
+import sys
+import xml.sax
+import xml.sax.saxutils
import zlib
-if len(sys.argv) < 4:
- print('Usage:')
- print(' complay <source.lay> <output.h> <varname>')
- print('')
- sys.exit(0)
-
-srcfile = sys.argv[1]
-dstfile = sys.argv[2]
-varname = sys.argv[3]
-type = 'uint8_t'
-
-try:
- myfile = open(srcfile, 'rb')
-except IOError:
- sys.stderr.write("Unable to open source file '%s'\n" % srcfile)
- sys.exit(-1)
-
-byteCount = os.path.getsize(srcfile)
-compsize = 0
-compressiontype = 1
-
-try:
- dst = open(dstfile,'w')
- dst.write('const %s %s_data[] =\n{\n\t' % ( type, varname))
- offs = 0
- with open(srcfile, "rb") as src:
- while True:
- chunk = src.read(byteCount)
- if chunk:
- compchunk = bytearray(zlib.compress(chunk, 9))
- compsize = len(compchunk)
- for b in compchunk:
- dst.write('%d' % b)
- offs += 1
- if offs != compsize:
- dst.write(',')
+
+class ErrorHandler(object):
+ def __init__(self, **kwargs):
+ super(ErrorHandler, self).__init__(**kwargs)
+ self.errors = 0
+ self.warnings = 0
+
+ def error(self, exception):
+ self.errors += 1
+ sys.stderr.write('error: %s' % (exception))
+
+ def fatalError(self, exception):
+ raise exception
+
+ def warning(self, exception):
+ self.warnings += 1
+ sys.stderr.write('warning: %s' % (exception))
+
+
+class Minifyer(object):
+ def __init__(self, output, **kwargs):
+ super(Minifyer, self).__init__(**kwargs)
+
+ self.output = output
+ self.incomplete_tag = False
+ self.element_content = ''
+
+ def setDocumentLocator(self, locator):
+ pass
+
+ def startDocument(self):
+ self.output('<?xml version="1.0"?>')
+
+ def endDocument(self):
+ self.output('\n')
+
+ def startElement(self, name, attrs):
+ self.flushElementContent()
+ if self.incomplete_tag:
+ self.output('>')
+ self.output('<%s' % (name))
+ for name in attrs.getNames():
+ self.output(' %s=%s' % (name, xml.sax.saxutils.quoteattr(attrs[name])))
+ self.incomplete_tag = True
+
+ def endElement(self, name):
+ self.flushElementContent()
+ if self.incomplete_tag:
+ self.output('/>')
+ else:
+ self.output('</%s>' % (name))
+ self.incomplete_tag = False
+
+ def characters(self, content):
+ self.element_content += content
+
+ def ignorableWhitespace(self, whitespace):
+ pass
+
+ def processingInstruction(self, target, data):
+ pass
+
+ def flushElementContent(self):
+ self.element_content = self.element_content.strip()
+ if self.element_content:
+ if self.incomplete_tag:
+ self.output('>')
+ self.incomplete_tag = False
+ self.output(xml.sax.saxutils.escape(self.element_content))
+ self.element_content = ''
+
+
+class XmlError(Exception):
+ pass
+
+
+def compressLayout(src, dst, comp):
+ state = [0, 0]
+ def write(block):
+ for ch in block:
+ if 0 == state[0]:
+ dst('\t')
+ elif 0 == (state[0] % 32):
+ dst(',\n\t')
else:
- break
- dst.write('\n\t')
+ dst(', ')
+ state[0] += 1
+ dst('%3u' % (ord(ch)))
+
+ def output(text):
+ block = text.encode('UTF-8')
+ state[1] += len(block)
+ write(comp.compress(block))
- dst.write('\n};\n')
+ error_handler = ErrorHandler()
+ content_handler = Minifyer(output)
+ parser = xml.sax.make_parser()
+ parser.setErrorHandler(error_handler)
+ parser.setContentHandler(content_handler)
+ try:
+ parser.parse(src)
+ write(comp.flush())
+ dst('\n')
+ except xml.sax.SAXException as exception:
+ print('fatal error: %s' % (exception))
+ raise XmlError('Fatal error parsing XML')
+ if (error_handler.errors > 0) or (error_handler.warnings > 0):
+ raise XmlError('Error(s) and/or warning(s) parsing XML')
-except IOError:
- sys.stderr.write("Unable to open output file '%s'\n" % dstfile)
- sys.exit(-1)
+ return state[1], state[0]
-try:
- dst.write('extern const internal_layout %s;\n' % ( varname ))
- dst.write('const internal_layout %s = { \n\t' % ( varname ))
- dst.write('%d,%d,%d,%s_data\n' % ( byteCount, compsize, compressiontype, varname ))
- dst.write('\n};\n')
+if __name__ == '__main__':
+ if len(sys.argv) != 4:
+ print('Usage:')
+ print(' complay <source.lay> <output.h> <varname>')
+ sys.exit(0 if len(sys.argv) <= 1 else 1)
- dst.close()
-except IOError:
- sys.stderr.write("Unable to open output file '%s'\n" % dstfile)
- sys.exit(-1)
+ srcfile = sys.argv[1]
+ dstfile = sys.argv[2]
+ varname = sys.argv[3]
+ comp_type = 1
+ try:
+ dst = open(dstfile,'w')
+ dst.write('static const unsigned char %s_data[] = {\n' % (varname))
+ byte_count, comp_size = compressLayout(srcfile, lambda x: dst.write(x), zlib.compressobj())
+ dst.write('};\n\n')
+ dst.write('const internal_layout %s = {\n' % (varname))
+ dst.write('\t%d, sizeof(%s_data), %d, %s_data\n' % (byte_count, varname, comp_type, varname))
+ dst.write('};\n')
+ dst.close()
+ except XmlError:
+ dst.close()
+ os.remove(dstfile)
+ sys.exit(2)
+ except IOError:
+ sys.stderr.write("Unable to open output file '%s'\n" % dstfile)
+ os.remove(dstfile)
+ dst.close()
+ sys.exit(3)