def qstr_escape(qst): def esc_char(m): c = ord(m.group(0)) try: name = codepoint2name[c] except KeyError: name = "0x%02x" % c return "_" + name + "_" return re.sub(r"[^A-Za-z0-9_]", esc_char, qst)
def parse_input_headers(infiles): qcfgs = {} qstrs = {} # add static qstrs for qstr in static_qstr_list: # work out the corresponding qstr name ident = qstr_escape(qstr) # don't add duplicates assert ident not in qstrs # add the qstr to the list, with order number to retain original order in file order = len(qstrs) - 300000 qstrs[ident] = (order, ident, qstr) print(qstrs[ident])
执行结果
# 主要做两件事:提取QCFG配置的长度字节数和哈希字节数,提取Q描述的qstr字符串 # read the qstrs in from the input files 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 value value = value[1:-1] qcfgs[match.group(1)] = value continue # is this a QSTR line? match = re.match(r"^Q\((.*)\)$", line) if not match: continue # get the qstr value qstr = match.group(1) # special cases to specify control characters if qstr == "\\n": qstr = "\n" elif qstr == "\\r\\n": qstr = "\r\n" # work out the corresponding qstr name ident = qstr_escape(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 order = len(qstrs) # but put special method names like __add__ at the top of list, so # that their id's fit into a byte if ident == "": # Sort empty qstr above all still order = -200000 elif ident == "__dir__": # Put __dir__ after empty qstr for builtin dir() to work order = -190000 elif ident.startswith("__"): order -= 100000 qstrs[ident] = (order, ident, qstr)
上述问题解决:输入 bash
回车,然后再次执行生成
def 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 qlen >= (1 << (8 * cfg_bytes_len)): print("qstr is too long:", qstr) assert False qdata = escape_bytes(qstr, qbytes) # return '%d, %d, "%s"' % (qhash, qlen, qdata) return '"\\x%02x\\x%02x\\x%02x" "%s"' % (qhash >> 8, qhash & 0xFF, qlen, 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"]) # print out the starter of the generated C header file print("// This file was automatically generated by makeqstrdata.py") print("") # add NULL qstr with no hash or data # print('QDEF(MP_QSTRnull, 0, 0, "")') print('QDEF(MP_QSTRnull, "\\x00\\x00\\x00" "")') # go through each qstr and print it out # sorted(object, key=lambda 变量:变量[维数] ):对qstrs按第一维数据进行由小到大排序 for 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))