forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 1
/
makemoduledefs.py
135 lines (105 loc) · 4.2 KB
/
makemoduledefs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""
This pre-processor parses a single file containing a list of
`MP_REGISTER_MODULE(MP_QSTR_module_name, obj_module)` or
`MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_module_name, obj_module)`
(i.e. the output of `py/makeqstrdefs.py cat module`).
The output is a header (typically moduledefs.h) which is included by
py/objmodule.c that contains entries to be included in the definition of
- mp_rom_map_elem_t mp_builtin_module_table[]
- mp_rom_map_elem_t mp_builtin_extensible_module_table[]
Extensible modules are modules that can be overridden from the filesystem, see
py/builtinimnport.c:process_import_at_level. Regular modules will always use
the built-in version.
"""
from __future__ import print_function
import sys
import re
import io
import argparse
register_pattern = re.compile(
r"\s*(MP_REGISTER_MODULE|MP_REGISTER_EXTENSIBLE_MODULE)\(MP_QSTR_(.*?),\s*(.*?)\);",
flags=re.DOTALL,
)
delegation_pattern = re.compile(
r"\s*(?:MP_REGISTER_MODULE_DELEGATION)\((.*?),\s*(.*?)\);",
flags=re.DOTALL,
)
def find_module_registrations(filename):
"""Find any MP_REGISTER_MODULE definitions in the provided file.
:param str filename: path to file to check
:return: List[(module_name, obj_module)]
"""
global pattern
with io.open(filename, encoding="utf-8") as c_file_obj:
c = c_file_obj.read()
return set(re.findall(register_pattern, c)), set(re.findall(delegation_pattern, c))
def generate_module_table_header(modules):
"""Generate header with module table entries for builtin modules.
:param List[(module_name, obj_module)] modules: module defs
:return: None
"""
# Print header file for all external modules.
mod_defs = set()
extensible_mod_defs = set()
for macro_name, module_name, obj_module in modules:
mod_def = "MODULE_DEF_{}".format(module_name.upper())
if macro_name == "MP_REGISTER_MODULE":
mod_defs.add(mod_def)
elif macro_name == "MP_REGISTER_EXTENSIBLE_MODULE":
extensible_mod_defs.add(mod_def)
if "," in obj_module:
print(
"ERROR: Call to {}({}, {}) should be {}({}, {})\n".format(
macro_name,
module_name,
obj_module,
macro_name,
module_name,
obj_module.split(",")[0],
),
file=sys.stderr,
)
sys.exit(1)
print(
(
"extern const struct _mp_obj_module_t {obj_module};\n"
"#undef {mod_def}\n"
"#define {mod_def} {{ MP_ROM_QSTR(MP_QSTR_{module_name}), MP_ROM_PTR(&{obj_module}) }},\n"
).format(
module_name=module_name,
obj_module=obj_module,
mod_def=mod_def,
)
)
print("\n#define MICROPY_REGISTERED_MODULES \\")
for mod_def in sorted(mod_defs):
print(" {mod_def} \\".format(mod_def=mod_def))
print("// MICROPY_REGISTERED_MODULES")
print("\n#define MICROPY_REGISTERED_EXTENSIBLE_MODULES \\")
for mod_def in sorted(extensible_mod_defs):
print(" {mod_def} \\".format(mod_def=mod_def))
print("// MICROPY_REGISTERED_EXTENSIBLE_MODULES")
def generate_module_delegations(delegations):
if not delegations:
return
print()
for obj_module, fun_name in delegations:
print("extern void {}(mp_obj_t self_in, qstr attr, mp_obj_t *dest);".format(fun_name))
print("#define MICROPY_MODULE_DELEGATIONS \\")
for obj_module, fun_name in delegations:
print(
" {{ MP_ROM_PTR(&{obj_module}), {fun_name} }}, \\".format(
obj_module=obj_module, fun_name=fun_name
)
)
print("// MICROPY_MODULE_DELEGATIONS")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("file", nargs=1, help="file with MP_REGISTER_MODULE definitions")
args = parser.parse_args()
print("// Automatically generated by makemoduledefs.py.\n")
modules, delegations = find_module_registrations(args.file[0])
generate_module_table_header(sorted(modules))
generate_module_delegations(sorted(delegations))
if __name__ == "__main__":
main()