a50b26e4b0
py/makeqstrdefs.py declares that it works with python 2.6 however the syntax used to initialise of a set with values was only added in python 2.7. This leads to build failures when the host system doesn't have python 2.7 or newer. Instead of using the new syntax pass a list of initial values through set() to achieve the same result. This should work for python versions from at least 2.6 onwards. Helped-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Chris Packham <judge.packham@gmail.com>
110 lines
3.3 KiB
Python
110 lines
3.3 KiB
Python
"""
|
|
This script processes the output from the C preprocessor and extracts all
|
|
qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'.
|
|
|
|
This script works with Python 2.6, 2.7, 3.3 and 3.4.
|
|
"""
|
|
|
|
import re
|
|
import argparse
|
|
import os
|
|
|
|
# Blacklist of qstrings that are specially handled in further
|
|
# processing and should be ignored
|
|
QSTRING_BLACK_LIST = set(['NULL', 'number_of'])
|
|
|
|
|
|
def write_out(fname, output):
|
|
if output:
|
|
for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]:
|
|
fname = fname.replace(m, r)
|
|
with open(args.output_dir + "/" + fname + ".qstr", "w") as f:
|
|
f.write("\n".join(output) + "\n")
|
|
|
|
def process_file(f):
|
|
output = []
|
|
last_fname = None
|
|
for line in f:
|
|
# match gcc-like output (# n "file") and msvc-like output (#line n "file")
|
|
if line and (line[0:2] == "# " or line[0:5] == "#line"):
|
|
m = re.match(r"#[line]*\s\d+\s\"([^\"]+)\"", line)
|
|
assert m is not None
|
|
fname = m.group(1)
|
|
if not fname.endswith(".c"):
|
|
continue
|
|
if fname != last_fname:
|
|
write_out(last_fname, output)
|
|
output = []
|
|
last_fname = fname
|
|
continue
|
|
for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line):
|
|
name = match.replace('MP_QSTR_', '')
|
|
if name not in QSTRING_BLACK_LIST:
|
|
output.append('Q(' + name + ')')
|
|
|
|
write_out(last_fname, output)
|
|
return ""
|
|
|
|
|
|
def cat_together():
|
|
import glob
|
|
import hashlib
|
|
hasher = hashlib.md5()
|
|
all_lines = []
|
|
outf = open(args.output_dir + "/out", "wb")
|
|
for fname in glob.glob(args.output_dir + "/*.qstr"):
|
|
with open(fname, "rb") as f:
|
|
lines = f.readlines()
|
|
all_lines += lines
|
|
all_lines.sort()
|
|
all_lines = b"\n".join(all_lines)
|
|
outf.write(all_lines)
|
|
outf.close()
|
|
hasher.update(all_lines)
|
|
new_hash = hasher.hexdigest()
|
|
#print(new_hash)
|
|
old_hash = None
|
|
try:
|
|
with open(args.output_file + ".hash") as f:
|
|
old_hash = f.read()
|
|
except IOError:
|
|
pass
|
|
if old_hash != new_hash:
|
|
print("QSTR updated")
|
|
try:
|
|
# rename below might fail if file exists
|
|
os.remove(args.output_file)
|
|
except:
|
|
pass
|
|
os.rename(args.output_dir + "/out", args.output_file)
|
|
with open(args.output_file + ".hash", "w") as f:
|
|
f.write(new_hash)
|
|
else:
|
|
print("QSTR not updated")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description='Generates qstr definitions from a specified source')
|
|
|
|
parser.add_argument('command',
|
|
help='Command (split/cat)')
|
|
parser.add_argument('input_filename',
|
|
help='Name of the input file (when not specified, the script reads standard input)')
|
|
parser.add_argument('output_dir',
|
|
help='Output directory to store individual qstr files')
|
|
parser.add_argument('output_file',
|
|
help='Name of the output file with collected qstrs')
|
|
|
|
args = parser.parse_args()
|
|
try:
|
|
os.makedirs(args.output_dir)
|
|
except OSError:
|
|
pass
|
|
|
|
if args.command == "split":
|
|
with open(args.input_filename) as infile:
|
|
process_file(infile)
|
|
|
|
if args.command == "cat":
|
|
cat_together()
|