blob: 95e7c80a44063c6273c9b1d419a202dccc75a5bd [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
14QSTRING_BLACK_LIST = {'NULL', 'number_of', }
15
16
Paul Sokolovskyc618f912016-04-19 11:30:06 +030017def write_out(fname, output):
18 if output:
19 fname = fname.replace("/", "__").replace("..", "@@")
20 with open(args.output_dir + "/" + fname + ".qstr", "w") as f:
21 f.write("\n".join(output) + "\n")
22
Pavel Moravecdbbf0822016-03-11 16:12:59 +000023def process_file(f):
24 output = []
Paul Sokolovskyc618f912016-04-19 11:30:06 +030025 last_fname = None
Pavel Moravecdbbf0822016-03-11 16:12:59 +000026 for line in f:
Paul Sokolovsky8dd704b2016-04-19 12:52:57 +030027 if line and line[0:2] == "# ":
Paul Sokolovskyc618f912016-04-19 11:30:06 +030028 comp = line.split()
29 fname = comp[2]
30 assert fname[0] == '"' and fname[-1] == '"'
31 fname = fname[1:-1]
32 if fname[0] == "/" or not fname.endswith(".c"):
33 continue
34 if fname != last_fname:
35 write_out(last_fname, output)
36 output = []
37 last_fname = fname
38 continue
Pavel Moravecdbbf0822016-03-11 16:12:59 +000039 for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line):
40 name = match.replace('MP_QSTR_', '')
41 if name not in QSTRING_BLACK_LIST:
42 output.append('Q(' + name + ')')
43
Paul Sokolovskyc618f912016-04-19 11:30:06 +030044 write_out(last_fname, output)
45 return ""
Pavel Moravecdbbf0822016-03-11 16:12:59 +000046
Paul Sokolovskyc618f912016-04-19 11:30:06 +030047
48def cat_together():
49 import glob
50 import hashlib
51 hasher = hashlib.md5()
52 all_lines = []
53 outf = open(args.output_dir + "/out", "wb")
54 for fname in glob.glob(args.output_dir + "/*.qstr"):
55 with open(fname, "rb") as f:
56 lines = f.readlines()
57 all_lines += lines
58 all_lines.sort()
59 all_lines = b"\n".join(all_lines)
60 outf.write(all_lines)
61 outf.close()
62 hasher.update(all_lines)
63 new_hash = hasher.hexdigest()
64 #print(new_hash)
65 old_hash = None
66 try:
67 with open(args.output_file + ".hash") as f:
68 old_hash = f.read()
69 except IOError:
70 pass
71 if old_hash != new_hash:
72 print("QSTR updated")
73 os.rename(args.output_dir + "/out", args.output_file)
74 with open(args.output_file + ".hash", "w") as f:
75 f.write(new_hash)
76 else:
77 print("QSTR not updated")
Pavel Moravecdbbf0822016-03-11 16:12:59 +000078
79
80if __name__ == "__main__":
81 parser = argparse.ArgumentParser(description='Generates qstr definitions from a specified source')
82
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +030083 parser.add_argument('command',
84 help='Command (split/cat)')
Paul Sokolovskyc618f912016-04-19 11:30:06 +030085 parser.add_argument('input_filename',
86 help='Name of the input file (when not specified, the script reads standard input)')
87 parser.add_argument('output_dir',
88 help='Output directory to store individual qstr files')
89 parser.add_argument('output_file',
90 help='Name of the output file with collected qstrs')
Pavel Moravecdbbf0822016-03-11 16:12:59 +000091
92 args = parser.parse_args()
Paul Sokolovskyc618f912016-04-19 11:30:06 +030093 try:
94 os.makedirs(args.output_dir)
95 except OSError:
96 pass
Pavel Moravecdbbf0822016-03-11 16:12:59 +000097
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +030098 if args.command == "split":
99 with open(args.input_filename) as infile:
100 process_file(infile)
Pavel Moravecdbbf0822016-03-11 16:12:59 +0000101
Paul Sokolovsky1b60a6d2016-04-19 14:39:08 +0300102 if args.command == "cat":
103 cat_together()