makeqstrdefs.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. """
  2. This script processes the output from the C preprocessor and extracts all
  3. qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'.
  4. This script works with Python 2.6, 2.7, 3.3 and 3.4.
  5. """
  6. from __future__ import print_function
  7. import re
  8. import sys
  9. import os
  10. # Blacklist of qstrings that are specially handled in further
  11. # processing and should be ignored
  12. QSTRING_BLACK_LIST = set(['NULL', 'number_of'])
  13. def write_out(fname, output):
  14. if output:
  15. for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]:
  16. fname = fname.replace(m, r)
  17. with open(args.output_dir + "/" + fname + ".qstr", "w") as f:
  18. f.write("\n".join(output) + "\n")
  19. def process_file(f):
  20. output = []
  21. last_fname = None
  22. for line in f:
  23. # match gcc-like output (# n "file") and msvc-like output (#line n "file")
  24. if line and (line[0:2] == "# " or line[0:5] == "#line"):
  25. m = re.match(r"#[line]*\s\d+\s\"([^\"]+)\"", line)
  26. assert m is not None
  27. fname = m.group(1)
  28. if not fname.endswith(".c"):
  29. continue
  30. if fname != last_fname:
  31. write_out(last_fname, output)
  32. output = []
  33. last_fname = fname
  34. continue
  35. for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line):
  36. name = match.replace('MP_QSTR_', '')
  37. if name not in QSTRING_BLACK_LIST:
  38. output.append('Q(' + name + ')')
  39. write_out(last_fname, output)
  40. return ""
  41. def cat_together():
  42. import glob
  43. import hashlib
  44. hasher = hashlib.md5()
  45. all_lines = []
  46. outf = open(args.output_dir + "/out", "wb")
  47. for fname in glob.glob(args.output_dir + "/*.qstr"):
  48. with open(fname, "rb") as f:
  49. lines = f.readlines()
  50. all_lines += lines
  51. all_lines.sort()
  52. all_lines = b"\n".join(all_lines)
  53. outf.write(all_lines)
  54. outf.close()
  55. hasher.update(all_lines)
  56. new_hash = hasher.hexdigest()
  57. #print(new_hash)
  58. old_hash = None
  59. try:
  60. with open(args.output_file + ".hash") as f:
  61. old_hash = f.read()
  62. except IOError:
  63. pass
  64. if old_hash != new_hash:
  65. print("QSTR updated")
  66. try:
  67. # rename below might fail if file exists
  68. os.remove(args.output_file)
  69. except:
  70. pass
  71. os.rename(args.output_dir + "/out", args.output_file)
  72. with open(args.output_file + ".hash", "w") as f:
  73. f.write(new_hash)
  74. else:
  75. print("QSTR not updated")
  76. if __name__ == "__main__":
  77. if len(sys.argv) != 5:
  78. print('usage: %s command input_filename output_dir output_file' % sys.argv[0])
  79. sys.exit(2)
  80. class Args:
  81. pass
  82. args = Args()
  83. args.command = sys.argv[1]
  84. args.input_filename = sys.argv[2]
  85. args.output_dir = sys.argv[3]
  86. args.output_file = sys.argv[4]
  87. try:
  88. os.makedirs(args.output_dir)
  89. except OSError:
  90. pass
  91. if args.command == "split":
  92. with open(args.input_filename) as infile:
  93. process_file(infile)
  94. if args.command == "cat":
  95. cat_together()