"""Process raw qstr file and output qstr data with length, hash and data bytes.This script works with Python 2.6, 2.7, 3.3 and 3.4."""from __future__ import print_functionimport reimport sys# Python 2/3 compatibility:# - iterating through bytes is different# - codepoint2name lives in a different moduleimport platformif platform.python_version_tuple()[0] == '2':bytes_cons = lambda val, enc=None: bytearray(val)from htmlentitydefs import codepoint2nameelif platform.python_version_tuple()[0] == '3':bytes_cons = bytesfrom html.entities import codepoint2name# end compatibility codecodepoint2name[ord('-')] = 'hyphen';# add some custom names to map characters that aren't in HTMLcodepoint2name[ord(' ')] = 'space'codepoint2name[ord('\'')] = 'squot'codepoint2name[ord(',')] = 'comma'codepoint2name[ord('.')] = 'dot'codepoint2name[ord(':')] = 'colon'codepoint2name[ord(';')] = 'semicolon'codepoint2name[ord('/')] = 'slash'codepoint2name[ord('%')] = 'percent'codepoint2name[ord('#')] = 'hash'codepoint2name[ord('(')] = 'paren_open'codepoint2name[ord(')')] = 'paren_close'codepoint2name[ord('[')] = 'bracket_open'codepoint2name[ord(']')] = 'bracket_close'codepoint2name[ord('{')] = 'brace_open'codepoint2name[ord('}')] = 'brace_close'codepoint2name[ord('*')] = 'star'codepoint2name[ord('!')] = 'bang'codepoint2name[ord('\\')] = 'backslash'codepoint2name[ord('+')] = 'plus'codepoint2name[ord('$')] = 'dollar'codepoint2name[ord('=')] = 'equals'codepoint2name[ord('?')] = 'question'codepoint2name[ord('@')] = 'at_sign'codepoint2name[ord('^')] = 'caret'codepoint2name[ord('|')] = 'pipe'codepoint2name[ord('~')] = 'tilde'# this must match the equivalent function in qstr.cdef compute_hash(qstr, bytes_hash):hash = 5381for b in qstr:hash = (hash * 33) ^ b# Make sure that valid hash is never zero, zero means "hash not computed"return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1def qstr_escape(qst):def esc_char(m):c = ord(m.group(0))try:name = codepoint2name[c]except KeyError:name = '0x%02x' % creturn "_" + name + '_'return re.sub(r'[^A-Za-z0-9_]', esc_char, qst)def parse_input_headers(infiles):# read the qstrs in from the input filesqcfgs = {}qstrs = {}for infile in infiles:with open(infile, 'rt') as f:for line in f:line = line.strip()# is this a config line?match = re.match(r'^QCFG\((.+), (.+)\)', line)if match:value = match.group(2)if value[0] == '(' and value[-1] == ')':# strip parenthesis from config valuevalue = value[1:-1]qcfgs[match.group(1)] = valuecontinue# is this a QSTR line?match = re.match(r'^Q\((.*)\)$', line)if not match:continue# get the qstr valueqstr = match.group(1)# special case to specify control charactersif qstr == '\\n':qstr = '\n'# work out the corresponding qstr nameident = qstr_escape(qstr)# don't add duplicatesif ident in qstrs:continue# add the qstr to the list, with order number to retain original order in fileorder = len(qstrs)# but put special method names like __add__ at the top of list, so# that their id's fit into a byteif ident == "":# Sort empty qstr above all stillorder = -200000elif ident == "__dir__":# Put __dir__ after empty qstr for builtin dir() to workorder = -190000elif ident.startswith("__"):order -= 100000qstrs[ident] = (order, ident, qstr)if not qcfgs:sys.stderr.write("ERROR: Empty preprocessor output - check for errors above\n")sys.exit(1)return qcfgs, qstrsdef make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr):qbytes = bytes_cons(qstr, 'utf8')qlen = len(qbytes)qhash = compute_hash(qbytes, cfg_bytes_hash)if all(32 <= ord(c) <= 126 and c != '\\' and c != '"' for c in qstr):# qstr is all printable ASCII so render it as-is (for easier debugging)qdata = qstrelse:# qstr contains non-printable codes so render entire thing as hex pairsqdata = ''.join(('\\x%02x' % b) for b in qbytes)if qlen >= (1 << (8 * cfg_bytes_len)):print('qstr is too long:', qstr)assert Falseqlen_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 variablescfg_bytes_len = int(qcfgs['BYTES_IN_LEN'])cfg_bytes_hash = int(qcfgs['BYTES_IN_HASH'])# print out the starter of the generated C header fileprint('// This file was automatically generated by makeqstrdata.py')print('')# add NULL qstr with no hash or dataprint('QDEF(MP_QSTR_NULL, (const byte*)"%s%s" "")' % ('\\x00' * cfg_bytes_hash, '\\x00' * cfg_bytes_len))# go through each qstr and print it outfor order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]):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:])
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。