Skip to content

Commit b7126c1

Browse files
committed
refactor: rename and break process_headers into small ones
1 parent 42ec04c commit b7126c1

File tree

1 file changed

+88
-63
lines changed

1 file changed

+88
-63
lines changed

ci/generate_checked_functions.py

Lines changed: 88 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,73 @@
2929

3030
from pycparser import c_ast, parse_file
3131
import argparse
32+
from pathlib import Path
33+
34+
# Constants for repeated strings
35+
CPP_ARGS = [
36+
"-E",
37+
"-D__attribute__(x)=",
38+
"-D__asm__(x)=",
39+
"-D__asm(x)=",
40+
"-D__builtin_va_list=int",
41+
"-D__extension__=",
42+
"-D__inline__=",
43+
"-D__restrict=",
44+
"-D__restrict__=",
45+
"-D_Static_assert(x, y)=",
46+
"-D__signed=",
47+
"-D__volatile__(x)=",
48+
"-Dstatic_assert(x, y)=",
49+
]
50+
51+
RESULT_STRUCT_TEMPLATE = """
52+
typedef struct {
53+
int error_code; // Error code (0 for success, non-zero for errors)
54+
union {
55+
// Add other types as needed
56+
} value;
57+
} Result;
58+
"""
3259

60+
INCLUDE_HEADERS = ["<stdbool.h>", "<stdint.h>", "<stdlib.h>"]
3361

34-
def collect_typedefs(ast):
35-
"""Collect all typedefs in the AST."""
36-
typedefs = {}
37-
for node in ast.ext:
38-
if not isinstance(node, c_ast.Typedef):
39-
continue
4062

41-
if node.name in typedefs:
42-
raise Exception(f"Duplicate typedef found: {node.name}")
63+
def extract_typedefs(ast):
64+
"""Extract all typedefs from the AST."""
65+
return {node.name: node.type for node in ast.ext if isinstance(node, c_ast.Typedef)}
66+
67+
68+
def generate_result_struct(return_types):
69+
"""Generate the Result struct based on return types."""
70+
result_struct = RESULT_STRUCT_TEMPLATE
71+
for return_type in return_types:
72+
if return_type != "void":
73+
result_struct = result_struct.replace(
74+
"// Add other types as needed",
75+
f" {return_type} {return_type}_value;\n // Add other types as needed",
76+
)
77+
return result_struct
78+
79+
80+
def write_checked_header(output_path, result_struct, functions, typedefs):
81+
"""Write the checked header file."""
82+
with open(output_path, "w") as f:
83+
f.write("#ifndef WASM_EXPORT_CHECKED_H\n#define WASM_EXPORT_CHECKED_H\n\n")
84+
85+
for header in INCLUDE_HEADERS:
86+
f.write(f"#include {header}\n")
87+
f.write("\n")
88+
f.write('#include "wasm_export.h"\n')
89+
f.write('#include "lib_export.h"\n')
90+
f.write("\n")
4391

44-
typedef_name = node.name
45-
typedef_type = node.type
46-
typedefs[typedef_name] = typedef_type
92+
f.write(result_struct + "\n")
4793

48-
return typedefs
94+
for func in functions:
95+
new_func = generate_checked_function(func, typedefs)
96+
f.write(new_func + "\n\n")
97+
98+
f.write("#endif // WASM_EXPORT_CHECKED_H\n")
4999

50100

51101
def resolve_typedef(typedefs, type_name):
@@ -97,6 +147,7 @@ def resolve_base_type(ptr_decl):
97147

98148

99149
def generate_checked_function(func, typedefs):
150+
"""Generate a checked version of the given function."""
100151
func_name = func.name # Access the name directly from Decl
101152
new_func_name = f"{func_name}_checked"
102153

@@ -194,6 +245,7 @@ def generate_checked_function(func, typedefs):
194245

195246

196247
def parse_arguments():
248+
"""Parse command-line arguments."""
197249
parser = argparse.ArgumentParser(
198250
description="Generate checked functions from header files."
199251
)
@@ -206,67 +258,40 @@ def parse_arguments():
206258
return parser.parse_args()
207259

208260

209-
# Updated process_header to scan all return types and create a proper Result type
210-
211-
212-
def process_headers(header_paths):
213-
# Define the Result struct as a string
214-
RESULT_STRUCT = """
215-
typedef struct {
216-
int error_code; // Error code (0 for success, non-zero for errors)
217-
union {
218-
// Add other types as needed
219-
} value;
220-
} Result;
221-
"""
222-
261+
def generate_checked_headers(header_paths):
262+
"""Process each header file and generate checked versions."""
223263
for input_header in header_paths:
224-
output_header = input_header.replace(".h", "_checked.h")
264+
input_path = Path(input_header)
265+
output_path = input_path.with_name(input_path.stem + "_checked.h")
225266

226-
# Parse the header file with preprocessing
227267
ast = parse_file(
228-
input_header,
268+
str(input_path),
229269
use_cpp=True,
230270
cpp_path="gcc",
231-
cpp_args=[
232-
"-E",
233-
"-D__attribute__(x)=",
234-
"-D__asm__(x)=",
235-
"-D__asm(x)=",
236-
"-D__builtin_va_list=int",
237-
"-D__extension__=",
238-
for return_type in return_types:
239-
if return_type == "void":
240-
continue # No need to add void type
241-
242-
RESULT_STRUCT = RESULT_STRUCT.replace(
243-
"// Add other types as needed",
244-
f" {return_type} {return_type}_value;\n // Add other types as needed",
245-
)
271+
cpp_args=CPP_ARGS,
272+
)
246273

247-
# Generate the new header file
248-
with open(output_header, "w") as f:
249-
f.write("#ifndef WASM_EXPORT_CHECKED_H\n#define WASM_EXPORT_CHECKED_H\n\n")
274+
typedefs = extract_typedefs(ast)
275+
functions = [
276+
node
277+
for node in ast.ext
278+
if isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.FuncDecl)
279+
]
250280

251-
# necessary headers
252-
f.write("#include <stdbool.h>\n")
253-
f.write("#include <stdint.h>\n")
254-
f.write("#include <stdlib.h>\n")
255-
f.write("\n")
256-
f.write('#include "wasm_export.h"\n')
257-
f.write('#include "lib_export.h"\n')
258-
f.write("\n")
281+
return_types = {
282+
" ".join(func.type.type.type.names)
283+
for func in functions
284+
if isinstance(func.type.type, c_ast.TypeDecl)
285+
}
259286

260-
# Write the updated Result struct
261-
f.write(RESULT_STRUCT + "\n")
287+
result_struct = generate_result_struct(return_types)
288+
write_checked_header(output_path, result_struct, functions, typedefs)
262289

263-
for func in functions:
264-
new_func = generate_checked_function(func, typedefs)
265-
f.write(new_func + "\n\n")
266290

267-
f.write("#endif // WASM_EXPORT_CHECKED_H\n")
291+
def main():
292+
args = parse_arguments()
293+
generate_checked_headers(args.headers)
268294

269295

270296
if __name__ == "__main__":
271-
args = parse_arguments()
272-
process_headers(args.headers)
297+
main()

0 commit comments

Comments
 (0)