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
|
#!/usr/bin/env python3
"""Generate ts_registry_generated.c with registry array and getter functions."""
import importlib.util
import os
import re
import sys
_spec = importlib.util.spec_from_file_location(
"ts_parser",
os.path.join(os.path.dirname(os.path.abspath(__file__)), "ts_parser.py"),
)
if _spec and _spec.loader:
ts_parser = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(ts_parser)
parse_all = ts_parser.parse_all
else:
print("Error: could not load ts_parser", file=sys.stderr)
sys.exit(1)
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
OUT = os.path.join(ROOT, "lib", "ts_registry_generated.c")
def _resolve_params_size(params_size, name):
"""Resolve params_size to a compile-time constant.
If params_size is '0', keep it. If it's sizeof(ts_X_params_t), check
if the struct is visible in ts.h. If not, compute size from definition.
"""
if params_size == "0":
return "0"
header_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "ts.h")
try:
with open(header_path, encoding="utf-8") as hf:
hcontent = hf.read()
if re.search(r"ts_" + re.escape(name) + r"_params_t", hcontent):
return params_size
except FileNotFoundError:
pass
# Struct not in header, compute size from definition
import glob
lib_dir = os.path.join(ROOT, "lib")
for cfile in glob.glob(os.path.join(lib_dir, "*.c")):
try:
with open(cfile, encoding="utf-8") as f:
content = f.read()
except OSError:
continue
struct_m = re.search(
r"typedef\s+struct\s*\{([^}]+)\}\s+ts_" + re.escape(name) + r"_params_t",
content,
)
if struct_m:
body = struct_m.group(1)
n_fp = len(re.findall(r"fp_t\s+", body))
n_uint = len(re.findall(r"uint_t\s+", body))
return str(n_fp * 8 + n_uint * 8)
return "0"
def main():
funcs = parse_all(detect_x_access=False)
if not funcs:
print("Warning: no ts_parameter declarations found.", file=sys.stderr)
sys.exit(1)
with open(OUT, "w", encoding="utf-8") as f:
f.write("/* Auto-generated function registry. Do not edit. */\n\n")
f.write('#include "ts.h"\n\n')
f.write(f"static const uint_t _ts_fn_count = {len(funcs)};\n\n")
f.write("static const ts_fn_info_t _ts_registry[] = {\n")
for fm in funcs:
ps = _resolve_params_size(fm.params_size, fm.name)
f.write(
f" {{ .n_inputs = {fm.x_n}, .n_outputs = {fm.y_n}, "
f".n_constants = {fm.c_n}, .params_size = {ps} }},\n"
)
f.write("};\n\n")
f.write("static const char * const _ts_fn_names[] = {\n")
for fm in funcs:
f.write(f' "{fm.name}",\n')
f.write("};\n\n")
# Getter functions
f.write("uint_t ts_fn_count( void ) { return _ts_fn_count; }\n\n")
f.write("const ts_fn_info_t* ts_registry_get( uint_t i )\n")
f.write("{\n")
f.write(" return i < _ts_fn_count ? &_ts_registry[i] : NULL;\n")
f.write("}\n\n")
f.write("const char* ts_fn_name_get( uint_t i )\n")
f.write("{\n")
f.write(" return i < _ts_fn_count ? _ts_fn_names[i] : NULL;\n")
f.write("}\n")
print(f"Generated {len(funcs)} entries -> {OUT}")
if __name__ == "__main__":
main()
|