aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/py/genlast.py
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
committerRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
commit4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch)
tree65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/py/genlast.py
parent0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff)
add circuitpython code
Diffstat (limited to 'circuitpython/py/genlast.py')
-rw-r--r--circuitpython/py/genlast.py90
1 files changed, 90 insertions, 0 deletions
diff --git a/circuitpython/py/genlast.py b/circuitpython/py/genlast.py
new file mode 100644
index 0000000..ad44745
--- /dev/null
+++ b/circuitpython/py/genlast.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+
+import sys
+import re
+import os
+import itertools
+from concurrent.futures import ProcessPoolExecutor
+import multiprocessing
+import threading
+import subprocess
+
+from makeqstrdefs import qstr_unescape, QSTRING_BLOCK_LIST
+
+re_line = re.compile(r"#[line]*\s(\d+)\s\"([^\"]+)\"", re.DOTALL)
+re_qstr = re.compile(r"MP_QSTR_[_a-zA-Z0-9]+", re.DOTALL)
+re_translate = re.compile(r"translate\(\"((?:(?=(\\?))\2.)*?)\"\)", re.DOTALL)
+
+
+def write_out(fname, output_dir, output):
+ if output:
+ for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]:
+ fname = fname.replace(m, r)
+ with open(output_dir + "/" + fname + ".qstr", "w") as f:
+ f.write("\n".join(output) + "\n")
+
+
+def process_file(fname, output_dir, content):
+ content = content.decode("utf-8", errors="ignore")
+ output = []
+ for match in re_qstr.findall(content):
+ name = match.replace("MP_QSTR_", "")
+ if name not in QSTRING_BLOCK_LIST:
+ output.append("Q(" + qstr_unescape(name) + ")")
+ for match in re_translate.findall(content):
+ output.append('TRANSLATE("' + match[0] + '")')
+
+ write_out(fname, output_dir, output)
+
+
+def checkoutput1(args):
+ info = subprocess.run(args, check=True, stdout=subprocess.PIPE, input="")
+ return info.stdout
+
+
+def preprocess(command, output_dir, fn):
+ try:
+ output = checkoutput1(command + [fn])
+ process_file(fn, output_dir, output)
+ except Exception as e:
+ print(e, file=sys.stderr)
+ raise
+
+
+def maybe_preprocess(command, output_dir, fn):
+ # Preprocess the source file if it contains "MP_QSTR", "translate",
+ # or if it uses enum.h (which generates "MP_QSTR" strings.
+ if subprocess.call(["grep", "-lqE", r"(MP_QSTR|translate|enum\.h)", fn]) == 0:
+ preprocess(command, output_dir, fn)
+
+
+if __name__ == "__main__":
+
+ idx1 = sys.argv.index("--")
+ idx2 = sys.argv.index("--", idx1 + 1)
+ output_dir = sys.argv[1]
+ check = sys.argv[2:idx1]
+ always = sys.argv[idx1 + 1 : idx2]
+ command = sys.argv[idx2 + 1 :]
+
+ if not os.path.isdir(output_dir):
+ os.makedirs(output_dir)
+
+ # Mac and Windows use 'spawn'. Uncomment this during testing to catch spawn-specific problems on Linux.
+ # multiprocessing.set_start_method("spawn")
+ executor = ProcessPoolExecutor(max_workers=multiprocessing.cpu_count() + 1)
+ results = []
+ try:
+ results.extend(
+ executor.map(
+ maybe_preprocess, itertools.repeat(command), itertools.repeat(output_dir), check
+ )
+ )
+ results.extend(
+ executor.map(
+ preprocess, itertools.repeat(command), itertools.repeat(output_dir), always
+ )
+ )
+ except subprocess.CalledProcessError:
+ raise SystemExit(1)
+ executor.shutdown()