blob: 92a19c39201caa6afc41286a214b9a69445e7c90 [file] [log] [blame]
Pavel Moravecdbbf0822016-03-11 16:12:59 +00001"""
2This script processes the output from the C preprocessor and extracts all
3qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'.
4
5This script works with Python 2.6, 2.7, 3.3 and 3.4.
6"""
7
Pavel Moravecdbbf0822016-03-11 16:12:59 +00008import re
9import argparse
10import os
11
12# Blacklist of qstrings that are specially handled in further
13# processing and should be ignored
Chris Packhama50b26e2016-09-08 20:34:34 +120014QSTRING_BLACK_LIST = set(['NULL', 'number_of'])
Pavel Moravecdbbf0822016-03-11 16:12:59 +000015
16
Paul Sokolovskyc618f912016-04-19 11:30:06 +030017def write_out(fname, output):
18 if output:
stijn9264d422016-04-23 18:36:07 +020019 for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]:
20 fname = fname.replace(m, r)
Paul Sokolovskyc618f912016-04-19 11:30:06 +030021 with open(args.output_dir + "/" + fname + ".qstr", "w") as f:
22 f.write("\n".join(output) + "\n")
23
Pavel Moravecdbbf0822016-03-11 16:12:59 +000024def process_file(f):
25 output = []
Paul Sokolovskyc618f912016-04-19 11:30:06 +030026 last_fname = None
Pavel Moravecdbbf0822016-03-11 16:12:59 +000027 for line in f:
stijn9264d422016-04-23 18:36:07 +020028 # match gcc-like output (# n "file") and msvc-like output (#line n "file")
29 if line and (line[0:2] == "# " or line[0:5] == "#line"):
30 m = re.match(r"#[line]*\s\d+\s\"([^\"]+)\"", line)
31 assert m is not None
32 fname = m.group(1)
Paul Sokolovskydcb90442016-06-16 01:04:42 +030033 if not fname.endswith(".c"):
Paul Sokolovskyc618f912016-04-19 11:30:06 +030034 continue
35 if fname != last_fname:
36 write_out(last_fname, output)
37 output = []
38 last_fname = fname
39 continue
Pavel Moravecdbbf0822016-03-11 16:12:59 +000040 for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line):
41 name = match.replace('MP_QSTR_', '')
42 if name not in QSTRING_BLACK_LIST:
43 output.append('Q(' + name + ')')
44
Paul Sokolovskyc618f912016-04-19 11:30:06 +030045 write_out(last_fname, output)
46 return ""
Pavel Moravecdbbf0822016-03-11 16:12:59 +000047
Paul Sokolovskyc618f912016-04-19 11:30:06 +030048
49def cat_together():
50 import glob
51 import hashlib
52 hasher = hashlib.md5()
53 all_lines = []
54 outf = open(args.output_dir + "/out", "wb")
55 for fname in glob.glob(args.output_dir + "/*.qstr"):
56 with open(fname, "rb") as f:
57 lines = f.readlines()
58 all_lines += lines
59 all_lines.sort()
60 all_lines = b"\n".join(all_lines)
61 outf.write(all_lines)
62 outf.close()
63 hasher.update(all_lines)
64 new_hash = hasher.hexdigest()
65 #print(new_hash)
66 old_hash = None
67 try:
68 with open(args.output_file + ".hash") as f:
69 old_hash = f.read()
70 except IOError:
71 pass
72 if old_hash != new_hash:
73 print("QSTR updated")
stijn9264d422016-04-23 18:36:07 +020074 try:
75 # rename below might fail if file exists
76 os.remove(args.output_file)
77 except:
78 pass
Paul Sokolovskyc618f912016-04-19 11:30:06 +030079 os.rename(args.output_dir + "/out", args.output_file)
80 with open(args.output_file + ".hash", "w") as f:
81 f.write(new_hash)
82 else:
83 print("QSTR not updated")
Pavel Moravecdbbf0822016-03-11 16:12:59 +000084
85
86if __name__ == "__main__":
87 parser = argparse.ArgumentParser(description='Generates qstr definitions from a specified source')
88
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +030089 parser.add_argument('command',
90 help='Command (split/cat)')
Paul Sokolovskyc618f912016-04-19 11:30:06 +030091 parser.add_argument('input_filename',
92 help='Name of the input file (when not specified, the script reads standard input)')
93 parser.add_argument('output_dir',
94 help='Output directory to store individual qstr files')
95 parser.add_argument('output_file',
96 help='Name of the output file with collected qstrs')
Pavel Moravecdbbf0822016-03-11 16:12:59 +000097
98 args = parser.parse_args()
Paul Sokolovskyc618f912016-04-19 11:30:06 +030099 try:
100 os.makedirs(args.output_dir)
101 except OSError:
102 pass
Pavel Moravecdbbf0822016-03-11 16:12:59 +0000103
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +0300104 if args.command == "split":
105 with open(args.input_filename) as infile:
106 process_file(infile)
Pavel Moravecdbbf0822016-03-11 16:12:59 +0000107
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +0300108 if args.command == "cat":
109 cat_together()