makeqstrdefs.py 3.0 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 io
  10. import os
  11. def write_out(fname, output):
  12. if output:
  13. for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]:
  14. fname = fname.replace(m, r)
  15. with open(args.output_dir + "/" + fname + ".qstr", "w") as f:
  16. f.write("\n".join(output) + "\n")
  17. def process_file(f):
  18. re_line = re.compile(r"#[line]*\s\d+\s\"([^\"]+)\"")
  19. re_qstr = re.compile(r'MP_QSTR_[_a-zA-Z0-9]+')
  20. output = []
  21. last_fname = None
  22. for line in f:
  23. if line.isspace():
  24. continue
  25. # match gcc-like output (# n "file") and msvc-like output (#line n "file")
  26. if line.startswith(('# ', '#line')):
  27. m = re_line.match(line)
  28. assert m is not None
  29. fname = m.group(1)
  30. if not fname.endswith(".c"):
  31. continue
  32. if fname != last_fname:
  33. write_out(last_fname, output)
  34. output = []
  35. last_fname = fname
  36. continue
  37. for match in re_qstr.findall(line):
  38. name = match.replace('MP_QSTR_', '')
  39. output.append('Q(' + name + ')')
  40. write_out(last_fname, output)
  41. return ""
  42. def cat_together():
  43. import glob
  44. import hashlib
  45. hasher = hashlib.md5()
  46. all_lines = []
  47. outf = open(args.output_dir + "/out", "wb")
  48. for fname in glob.glob(args.output_dir + "/*.qstr"):
  49. with open(fname, "rb") as f:
  50. lines = f.readlines()
  51. all_lines += lines
  52. all_lines.sort()
  53. all_lines = b"\n".join(all_lines)
  54. outf.write(all_lines)
  55. outf.close()
  56. hasher.update(all_lines)
  57. new_hash = hasher.hexdigest()
  58. #print(new_hash)
  59. old_hash = None
  60. try:
  61. with open(args.output_file + ".hash") as f:
  62. old_hash = f.read()
  63. except IOError:
  64. pass
  65. if old_hash != new_hash:
  66. print("QSTR updated")
  67. try:
  68. # rename below might fail if file exists
  69. os.remove(args.output_file)
  70. except:
  71. pass
  72. os.rename(args.output_dir + "/out", args.output_file)
  73. with open(args.output_file + ".hash", "w") as f:
  74. f.write(new_hash)
  75. else:
  76. print("QSTR not updated")
  77. if __name__ == "__main__":
  78. if len(sys.argv) != 5:
  79. print('usage: %s command input_filename output_dir output_file' % sys.argv[0])
  80. sys.exit(2)
  81. class Args:
  82. pass
  83. args = Args()
  84. args.command = sys.argv[1]
  85. args.input_filename = sys.argv[2]
  86. args.output_dir = sys.argv[3]
  87. args.output_file = sys.argv[4]
  88. try:
  89. os.makedirs(args.output_dir)
  90. except OSError:
  91. pass
  92. if args.command == "split":
  93. with io.open(args.input_filename, encoding='utf-8') as infile:
  94. process_file(infile)
  95. if args.command == "cat":
  96. cat_together()