blob: 525dec1973438498a0fd781db140476b0a9d9503 [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
Damien Georgeb24ccfc2017-06-09 13:42:13 +10008from __future__ import print_function
9
Pavel Moravecdbbf0822016-03-11 16:12:59 +000010import re
Damien Georgeb24ccfc2017-06-09 13:42:13 +100011import sys
Pavel Moravecdbbf0822016-03-11 16:12:59 +000012import os
13
14# Blacklist of qstrings that are specially handled in further
15# processing and should be ignored
Chris Packhama50b26e2016-09-08 20:34:34 +120016QSTRING_BLACK_LIST = set(['NULL', 'number_of'])
Pavel Moravecdbbf0822016-03-11 16:12:59 +000017
18
Paul Sokolovskyc618f912016-04-19 11:30:06 +030019def write_out(fname, output):
20 if output:
stijn9264d422016-04-23 18:36:07 +020021 for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]:
22 fname = fname.replace(m, r)
Paul Sokolovskyc618f912016-04-19 11:30:06 +030023 with open(args.output_dir + "/" + fname + ".qstr", "w") as f:
24 f.write("\n".join(output) + "\n")
25
Pavel Moravecdbbf0822016-03-11 16:12:59 +000026def process_file(f):
27 output = []
Paul Sokolovskyc618f912016-04-19 11:30:06 +030028 last_fname = None
Pavel Moravecdbbf0822016-03-11 16:12:59 +000029 for line in f:
stijn9264d422016-04-23 18:36:07 +020030 # match gcc-like output (# n "file") and msvc-like output (#line n "file")
31 if line and (line[0:2] == "# " or line[0:5] == "#line"):
32 m = re.match(r"#[line]*\s\d+\s\"([^\"]+)\"", line)
33 assert m is not None
34 fname = m.group(1)
Paul Sokolovskydcb90442016-06-16 01:04:42 +030035 if not fname.endswith(".c"):
Paul Sokolovskyc618f912016-04-19 11:30:06 +030036 continue
37 if fname != last_fname:
38 write_out(last_fname, output)
39 output = []
40 last_fname = fname
41 continue
Pavel Moravecdbbf0822016-03-11 16:12:59 +000042 for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line):
43 name = match.replace('MP_QSTR_', '')
44 if name not in QSTRING_BLACK_LIST:
45 output.append('Q(' + name + ')')
46
Paul Sokolovskyc618f912016-04-19 11:30:06 +030047 write_out(last_fname, output)
48 return ""
Pavel Moravecdbbf0822016-03-11 16:12:59 +000049
Paul Sokolovskyc618f912016-04-19 11:30:06 +030050
51def cat_together():
52 import glob
53 import hashlib
54 hasher = hashlib.md5()
55 all_lines = []
56 outf = open(args.output_dir + "/out", "wb")
57 for fname in glob.glob(args.output_dir + "/*.qstr"):
58 with open(fname, "rb") as f:
59 lines = f.readlines()
60 all_lines += lines
61 all_lines.sort()
62 all_lines = b"\n".join(all_lines)
63 outf.write(all_lines)
64 outf.close()
65 hasher.update(all_lines)
66 new_hash = hasher.hexdigest()
67 #print(new_hash)
68 old_hash = None
69 try:
70 with open(args.output_file + ".hash") as f:
71 old_hash = f.read()
72 except IOError:
73 pass
74 if old_hash != new_hash:
75 print("QSTR updated")
stijn9264d422016-04-23 18:36:07 +020076 try:
77 # rename below might fail if file exists
78 os.remove(args.output_file)
79 except:
80 pass
Paul Sokolovskyc618f912016-04-19 11:30:06 +030081 os.rename(args.output_dir + "/out", args.output_file)
82 with open(args.output_file + ".hash", "w") as f:
83 f.write(new_hash)
84 else:
85 print("QSTR not updated")
Pavel Moravecdbbf0822016-03-11 16:12:59 +000086
87
88if __name__ == "__main__":
Damien Georgeb24ccfc2017-06-09 13:42:13 +100089 if len(sys.argv) != 5:
90 print('usage: %s command input_filename output_dir output_file' % sys.argv[0])
91 sys.exit(2)
Pavel Moravecdbbf0822016-03-11 16:12:59 +000092
Damien Georgeb24ccfc2017-06-09 13:42:13 +100093 class Args:
94 pass
95 args = Args()
96 args.command = sys.argv[1]
97 args.input_filename = sys.argv[2]
98 args.output_dir = sys.argv[3]
99 args.output_file = sys.argv[4]
Pavel Moravecdbbf0822016-03-11 16:12:59 +0000100
Paul Sokolovskyc618f912016-04-19 11:30:06 +0300101 try:
102 os.makedirs(args.output_dir)
103 except OSError:
104 pass
Pavel Moravecdbbf0822016-03-11 16:12:59 +0000105
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +0300106 if args.command == "split":
107 with open(args.input_filename) as infile:
108 process_file(infile)
Pavel Moravecdbbf0822016-03-11 16:12:59 +0000109
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +0300110 if args.command == "cat":
111 cat_together()