diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index e8adb0cbb6..ea0ecd686f 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -45,7 +45,10 @@ def compute_hash(qstr, bytes_hash): # Make sure that valid hash is never zero, zero means "hash not computed" return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1 -def do_work(infiles): +def qstr_escape(qst): + return re.sub(r'[^A-Za-z0-9_]', lambda s: "_" + codepoint2name[ord(s.group(0))] + '_', qst) + +def parse_input_headers(infiles): # read the qstrs in from the input files qcfgs = {} qstrs = {} @@ -71,7 +74,7 @@ def do_work(infiles): # get the qstr value qstr = match.group(1) - ident = re.sub(r'[^A-Za-z0-9_]', lambda s: "_" + codepoint2name[ord(s.group(0))] + "_", qstr) + ident = qstr_escape(qstr) # don't add duplicates if ident in qstrs: @@ -84,10 +87,24 @@ def do_work(infiles): sys.stderr.write("ERROR: Empty preprocessor output - check for errors above\n") sys.exit(1) + return qcfgs, qstrs + +def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr): + qhash = compute_hash(qstr, cfg_bytes_hash) + # Calculate len of str, taking escapes into account + qlen = len(qstr.replace("\\\\", "-").replace("\\", "")) + qdata = qstr.replace('"', '\\"') + if qlen >= (1 << (8 * cfg_bytes_len)): + print('qstr is too long:', qstr) + assert False + qlen_str = ('\\x%02x' * cfg_bytes_len) % tuple(((qlen >> (8 * i)) & 0xff) for i in range(cfg_bytes_len)) + qhash_str = ('\\x%02x' * cfg_bytes_hash) % tuple(((qhash >> (8 * i)) & 0xff) for i in range(cfg_bytes_hash)) + return '(const byte*)"%s%s" "%s"' % (qhash_str, qlen_str, qdata) + +def print_qstr_data(qcfgs, qstrs): # get config variables cfg_bytes_len = int(qcfgs['BYTES_IN_LEN']) cfg_bytes_hash = int(qcfgs['BYTES_IN_HASH']) - cfg_max_len = 1 << (8 * cfg_bytes_len) # print out the starter of the generated C header file print('// This file was automatically generated by makeqstrdata.py') @@ -98,16 +115,12 @@ def do_work(infiles): # go through each qstr and print it out for order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]): - qhash = compute_hash(qstr, cfg_bytes_hash) - # Calculate len of str, taking escapes into account - qlen = len(qstr.replace("\\\\", "-").replace("\\", "")) - qdata = qstr.replace('"', '\\"') - if qlen >= cfg_max_len: - print('qstr is too long:', qstr) - assert False - qlen_str = ('\\x%02x' * cfg_bytes_len) % tuple(((qlen >> (8 * i)) & 0xff) for i in range(cfg_bytes_len)) - qhash_str = ('\\x%02x' * cfg_bytes_hash) % tuple(((qhash >> (8 * i)) & 0xff) for i in range(cfg_bytes_hash)) - print('QDEF(MP_QSTR_%s, (const byte*)"%s%s" "%s")' % (ident, qhash_str, qlen_str, qdata)) + qbytes = make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr) + print('QDEF(MP_QSTR_%s, %s)' % (ident, qbytes)) + +def do_work(infiles): + qcfgs, qstrs = parse_input_headers(infiles) + print_qstr_data(qcfgs, qstrs) if __name__ == "__main__": do_work(sys.argv[1:])