diff options
author | Raghuram Subramani <raghus2247@gmail.com> | 2022-06-19 19:47:51 +0530 |
---|---|---|
committer | Raghuram Subramani <raghus2247@gmail.com> | 2022-06-19 19:47:51 +0530 |
commit | 4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch) | |
tree | 65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/py/makemoduledefs.py | |
parent | 0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff) |
add circuitpython code
Diffstat (limited to 'circuitpython/py/makemoduledefs.py')
-rw-r--r-- | circuitpython/py/makemoduledefs.py | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/circuitpython/py/makemoduledefs.py b/circuitpython/py/makemoduledefs.py new file mode 100644 index 0000000..aa2e507 --- /dev/null +++ b/circuitpython/py/makemoduledefs.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python + +# This pre-processor parses provided objects' c files for +# MP_REGISTER_MODULE(module_name, obj_module, enabled_define) +# These are used to generate a header with the required entries for +# "mp_rom_map_elem_t mp_builtin_module_table[]" in py/objmodule.c + +from __future__ import print_function + +import re +import io +import os +import argparse + + +pattern = re.compile(r"[\n;]\s*MP_REGISTER_MODULE\((.*?),\s*(.*?),\s*(.*?)\);", flags=re.DOTALL) + + +def find_c_file(obj_file, vpath): + """Search vpaths for the c file that matches the provided object_file. + + :param str obj_file: object file to find the matching c file for + :param List[str] vpath: List of base paths, similar to gcc vpath + :return: str path to c file or None + """ + c_file = None + relative_c_file = os.path.splitext(obj_file)[0] + ".c" + relative_c_file = relative_c_file.lstrip("/\\") + for p in vpath: + possible_c_file = os.path.join(p, relative_c_file) + if os.path.exists(possible_c_file): + c_file = possible_c_file + break + + return c_file + + +def find_module_registrations(c_file): + """Find any MP_REGISTER_MODULE definitions in the provided c file. + + :param str c_file: path to c file to check + :return: List[(module_name, obj_module, enabled_define)] + """ + global pattern + + if c_file is None: + # No c file to match the object file, skip + return set() + + with io.open(c_file, encoding="utf-8") as c_file_obj: + return set(re.findall(pattern, c_file_obj.read())) + + +def generate_module_table_header(modules): + """Generate header with module table entries for builtin modules. + + :param List[(module_name, obj_module, enabled_define)] modules: module defs + :return: None + """ + + # Print header file for all external modules. + mod_defs = [] + print("// Automatically generated by makemoduledefs.py.\n") + print('#include "py/mpconfig.h"') + for module_name, obj_module, enabled_define in modules: + mod_def = "MODULE_DEF_{}".format(module_name.upper()) + mod_defs.append(mod_def) + print( + ( + "#if ({enabled_define})\n" + " extern const struct _mp_obj_module_t {obj_module};\n" + " #define {mod_def} {{ MP_ROM_QSTR({module_name}), MP_ROM_PTR(&{obj_module}) }},\n" + "#else\n" + " #define {mod_def}\n" + "#endif\n" + ).format( + module_name=module_name, + obj_module=obj_module, + enabled_define=enabled_define, + mod_def=mod_def, + ) + ) + + print("\n#define MICROPY_REGISTERED_MODULES \\") + + for mod_def in mod_defs: + print(" {mod_def} \\".format(mod_def=mod_def)) + + print("// MICROPY_REGISTERED_MODULES") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--vpath", default=".", help="comma separated list of folders to search for c files in" + ) + parser.add_argument("files", nargs="*", help="list of c files to search") + args = parser.parse_args() + + vpath = [p.strip() for p in args.vpath.split(",")] + + modules = set() + for obj_file in args.files: + c_file = find_c_file(obj_file, vpath) + modules |= find_module_registrations(c_file) + + generate_module_table_header(sorted(modules)) + + +if __name__ == "__main__": + main() |