summaryrefslogtreecommitdiffstats
path: root/scripts/gen_all.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gen_all.py')
-rw-r--r--scripts/gen_all.py135
1 files changed, 135 insertions, 0 deletions
diff --git a/scripts/gen_all.py b/scripts/gen_all.py
new file mode 100644
index 0000000..dd9d395
--- /dev/null
+++ b/scripts/gen_all.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+"""Generate ts_generated.h with all indicator declarations and test registry.
+
+Parses lib/*.c for ts_parameter_t declarations and emits:
+- extern ts_parameter_t const ts_<name>_p
+- uint_t ts_<name>_offset(...)
+- int ts_<name>(...)
+- bool ts_test_<name>(void) [inside #ifdef TS_IMPLEMENTATION]
+"""
+
+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__)))
+TEST_DIR = os.path.join(ROOT, "test")
+OUT_H = os.path.join(ROOT, "ts_generated.h")
+OUT_TEST = os.path.join(TEST_DIR, "main_generated.c")
+
+
+def generate_header(funcs):
+ """Generate ts_generated.h."""
+ lines = []
+ lines.append("/* Auto-generated indicator declarations. Do not edit. */")
+ lines.append("")
+ lines.append("#ifndef TS_GENERATED_H")
+ lines.append("#define TS_GENERATED_H")
+ lines.append("")
+
+ for fm in funcs:
+ lines.append("extern ts_parameter_t const ts_" + fm.name + "_p;")
+ lines.append("uint_t ts_" + fm.name + "_offset( ts_constant_t const * );")
+ lines.append(
+ "int ts_"
+ + fm.name
+ + "( fp_t * const *y, uint_t y_n, fp_t const * const *x, "
+ "uint_t x_n, uint_t n, ts_constant_t const *c );"
+ )
+
+ lines.append("")
+ lines.append("#ifdef TS_IMPLEMENTATION")
+ lines.append("")
+ for fm in funcs:
+ lines.append("bool ts_test_" + fm.name + "( void );")
+ lines.append("")
+ lines.append("#endif /* TS_IMPLEMENTATION */")
+ lines.append("")
+ lines.append("#endif /* TS_GENERATED_H */")
+ lines.append("")
+
+ return "\n".join(lines)
+
+
+def generate_test_main(funcs):
+ """Generate test/main_generated.c with extern declarations and test array."""
+ lines = []
+ lines.append("/* Auto-generated test registry. Do not edit. */")
+ lines.append("")
+ lines.append("#define EXTERN_TEST(name) extern bool ts_test_##name(void)")
+ for fm in funcs:
+ lines.append("EXTERN_TEST(" + fm.name + ");")
+ lines.append("#undef EXTERN_TEST")
+ lines.append("")
+ lines.append("typedef struct {")
+ lines.append(" const char *name;")
+ lines.append(" bool (*func)(void);")
+ lines.append("} test_case_t;")
+ lines.append("")
+ lines.append("#define TEST_ENTRY(name) { #name, ts_test_##name }")
+ lines.append("")
+ lines.append("static test_case_t tests[] = {")
+ for fm in funcs:
+ lines.append(" TEST_ENTRY(" + fm.name + "),")
+ lines.append("};")
+ lines.append("")
+ lines.append("#define NUM_TESTS (sizeof(tests) / sizeof(tests[0]))")
+ lines.append("")
+ lines.append("#undef TEST_ENTRY")
+ lines.append("")
+
+ return "\n".join(lines)
+
+
+def _is_valid_c_identifier(name):
+ return bool(re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", name))
+
+
+def main():
+ funcs = parse_all(detect_x_access=False)
+
+ if not funcs:
+ print("Warning: no ts_parameter declarations found.", file=sys.stderr)
+ return 1
+
+ for fm in funcs:
+ if not _is_valid_c_identifier(fm.name):
+ print(f"Error: invalid C identifier '{fm.name}'", file=sys.stderr)
+ return 1
+
+ os.makedirs(TEST_DIR, exist_ok=True)
+
+ try:
+ with open(OUT_H, "w", encoding="utf-8") as f:
+ f.write(generate_header(funcs))
+ except OSError as e:
+ print(f"Error writing {OUT_H}: {e}", file=sys.stderr)
+ return 1
+
+ try:
+ with open(OUT_TEST, "w", encoding="utf-8") as f:
+ f.write(generate_test_main(funcs))
+ except OSError as e:
+ print(f"Error writing {OUT_TEST}: {e}", file=sys.stderr)
+ return 1
+
+ print(f"Generated {len(funcs)} declarations -> {OUT_H}")
+ print(f"Generated test registry -> {OUT_TEST}")
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())