circuitpython/py/makeqstrdata.py
Damien George 1976baeeb7 Retain file order of qstr definitions.
Want common qstrs to be first in the list so they have the lowest ids,
so that in the byte code they take up the least room.
2014-01-24 22:22:00 +00:00

71 lines
2.4 KiB
Python

import argparse
import re
# codepoint2name is different in Python 2 to Python 3
import platform
if platform.python_version_tuple()[0] == '2':
from htmlentitydefs import codepoint2name
elif platform.python_version_tuple()[0] == '3':
from html.entities import codepoint2name
# this must match the equivalent function in qstr.c
def compute_hash(qstr):
hash = 0
for char in qstr:
hash += ord(char)
return hash & 0xffff
def do_work(infiles):
# read the qstrs in from the input files
qstrs = {}
for infile in infiles:
with open(infile, 'rt') as f:
line_number = 0
for line in f:
line_number += 1
line = line.strip()
# ignore blank lines and comments
if len(line) == 0 or line.startswith('//'):
continue
# verify line is of the correct form
match = re.match(r'Q\((.+)\)$', line)
if not match:
print('({}:{}) bad qstr format, got {}'.format(infile, line_number, line))
return False
# get the qstr value
qstr = match.group(1)
ident = re.sub(r'[^A-Za-z0-9_]', lambda s: "_" + codepoint2name[ord(s.group(0))] + "_", qstr)
# don't add duplicates
if ident in qstrs:
continue
# add the qstr to the list, with order number to retain original order in file
qstrs[ident] = (len(qstrs), ident, qstr)
# process the qstrs, printing out the generated C header file
print('// This file was automatically generated by makeqstrdata.py')
print('')
for order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]):
qhash = compute_hash(qstr)
qlen = len(qstr)
print('Q({}, (const byte*)"\\x{:02x}\\x{:02x}\\x{:02x}\\x{:02x}" "{}")'.format(ident, qhash & 0xff, (qhash >> 8) & 0xff, qlen & 0xff, (qlen >> 8) & 0xff, qstr))
return True
def main():
arg_parser = argparse.ArgumentParser(description='Process raw qstr file and output qstr data with length, hash and data bytes')
arg_parser.add_argument('files', nargs='+', help='input file(s)')
args = arg_parser.parse_args()
result = do_work(args.files)
if not result:
print('exiting with error code')
exit(1)
if __name__ == "__main__":
main()