mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
Rewrite complay.py to parse/minify layout XML
Doesn't make much difference to executable size, but it catches XML errors at build time rather than waiting for you to try the system (nw)
This commit is contained in:
parent
f7198793ee
commit
5eefcfdb68
@ -1,69 +1,152 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
##
|
##
|
||||||
## license:BSD-3-Clause
|
## license:BSD-3-Clause
|
||||||
## copyright-holders:Aaron Giles, Andrew Gardner
|
## copyright-holders:Vas Crabb
|
||||||
|
|
||||||
from __future__ import with_statement
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
import xml.sax
|
||||||
|
import xml.sax.saxutils
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
if len(sys.argv) < 4:
|
|
||||||
print('Usage:')
|
|
||||||
print(' complay <source.lay> <output.h> <varname>')
|
|
||||||
print('')
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
srcfile = sys.argv[1]
|
class ErrorHandler(object):
|
||||||
dstfile = sys.argv[2]
|
def __init__(self, **kwargs):
|
||||||
varname = sys.argv[3]
|
super(ErrorHandler, self).__init__(**kwargs)
|
||||||
type = 'uint8_t'
|
self.errors = 0
|
||||||
|
self.warnings = 0
|
||||||
|
|
||||||
try:
|
def error(self, exception):
|
||||||
myfile = open(srcfile, 'rb')
|
self.errors += 1
|
||||||
except IOError:
|
sys.stderr.write('error: %s' % (exception))
|
||||||
sys.stderr.write("Unable to open source file '%s'\n" % srcfile)
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
byteCount = os.path.getsize(srcfile)
|
def fatalError(self, exception):
|
||||||
compsize = 0
|
raise exception
|
||||||
compressiontype = 1
|
|
||||||
|
|
||||||
try:
|
def warning(self, exception):
|
||||||
dst = open(dstfile,'w')
|
self.warnings += 1
|
||||||
dst.write('const %s %s_data[] =\n{\n\t' % ( type, varname))
|
sys.stderr.write('warning: %s' % (exception))
|
||||||
offs = 0
|
|
||||||
with open(srcfile, "rb") as src:
|
|
||||||
while True:
|
class Minifyer(object):
|
||||||
chunk = src.read(byteCount)
|
def __init__(self, output, **kwargs):
|
||||||
if chunk:
|
super(Minifyer, self).__init__(**kwargs)
|
||||||
compchunk = bytearray(zlib.compress(chunk, 9))
|
|
||||||
compsize = len(compchunk)
|
self.output = output
|
||||||
for b in compchunk:
|
self.incomplete_tag = False
|
||||||
dst.write('%d' % b)
|
self.element_content = ''
|
||||||
offs += 1
|
|
||||||
if offs != compsize:
|
def setDocumentLocator(self, locator):
|
||||||
dst.write(',')
|
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:
|
else:
|
||||||
break
|
dst(', ')
|
||||||
dst.write('\n\t')
|
state[0] += 1
|
||||||
|
dst('%3u' % (ord(ch)))
|
||||||
|
|
||||||
dst.write('\n};\n')
|
def output(text):
|
||||||
|
block = text.encode('UTF-8')
|
||||||
|
state[1] += len(block)
|
||||||
|
write(comp.compress(block))
|
||||||
|
|
||||||
except IOError:
|
error_handler = ErrorHandler()
|
||||||
sys.stderr.write("Unable to open output file '%s'\n" % dstfile)
|
content_handler = Minifyer(output)
|
||||||
sys.exit(-1)
|
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')
|
||||||
|
|
||||||
try:
|
return state[1], state[0]
|
||||||
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')
|
|
||||||
|
|
||||||
|
|
||||||
dst.close()
|
if __name__ == '__main__':
|
||||||
except IOError:
|
if len(sys.argv) != 4:
|
||||||
sys.stderr.write("Unable to open output file '%s'\n" % dstfile)
|
print('Usage:')
|
||||||
sys.exit(-1)
|
print(' complay <source.lay> <output.h> <varname>')
|
||||||
|
sys.exit(0 if len(sys.argv) <= 1 else 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)
|
||||||
|
Loading…
Reference in New Issue
Block a user