|
1 | | -from pycparser import c_parser, c_ast, parse_file |
2 | | -import os |
| 1 | +""" |
| 2 | +This script generates "checked" versions of functions from the specified header files. |
| 3 | +
|
| 4 | +Usage: |
| 5 | + python3 generate_checked_functions.py --headers <header1.h> <header2.h> ... |
| 6 | +
|
| 7 | +Arguments: |
| 8 | + --headers: A list of header file paths to process. Each header file will be parsed, and a corresponding |
| 9 | + "_checked.h" file will be generated with additional null pointer checks and error handling. |
| 10 | +
|
| 11 | +Example: |
| 12 | + python3 generate_checked_functions.py --headers core/iwasm/include/wasm_export.h |
| 13 | +
|
| 14 | +Description: |
| 15 | + The script parses the provided header files using `pycparser` to extract function declarations and typedefs. |
| 16 | + For each function, it generates a "checked" version that includes: |
| 17 | + - Null pointer checks for pointer parameters. |
| 18 | + - Error handling using a `Result` struct. |
| 19 | +
|
| 20 | + The generated "_checked.h" files include the original header file and define the `Result` struct, which |
| 21 | + encapsulates the return value and error codes. |
| 22 | +
|
| 23 | +Dependencies: |
| 24 | + - pycparser: Install it using `pip install pycparser`. |
| 25 | +
|
| 26 | +Output: |
| 27 | + For each input header file, a corresponding "_checked.h" file is created in the same directory. |
| 28 | +""" |
| 29 | + |
| 30 | +from pycparser import c_ast, parse_file |
3 | 31 | import argparse |
4 | 32 |
|
5 | 33 |
|
@@ -46,30 +74,22 @@ def resolve_base_type(ptr_decl): |
46 | 74 | if resolved_type is None: |
47 | 75 | return type_name |
48 | 76 |
|
49 | | - print(f"\n\nResolving typedef {type_name}:") |
50 | | - |
51 | 77 | if isinstance(resolved_type, c_ast.TypeDecl): |
52 | 78 | if isinstance(resolved_type.type, c_ast.Enum): |
53 | | - print(f"Resolved enum typedef {type_name}") |
54 | 79 | return type_name |
55 | 80 |
|
56 | 81 | if isinstance(resolved_type.type, c_ast.Struct): |
57 | | - print(f"Resolved struct typedef {type_name}") |
58 | 82 | return type_name |
59 | 83 |
|
60 | 84 | if isinstance(resolved_type.type, c_ast.Union): |
61 | | - print(f"Resolved union typedef {type_name}") |
62 | 85 | return type_name |
63 | 86 |
|
64 | 87 | if isinstance(resolved_type.type, c_ast.IdentifierType): |
65 | | - base_type_name = " ".join(resolved_type.type.names) |
66 | | - print(f"Resolved base typedef {type_name} to {base_type_name}") |
67 | 88 | return type_name |
68 | 89 |
|
69 | 90 | raise Exception(f"Unhandled TypeDecl typedef {type_name}") |
70 | 91 | elif isinstance(resolved_type, c_ast.PtrDecl): |
71 | 92 | pointer_type_name = resolve_base_type(resolved_type) |
72 | | - print(f"Resolved pointer typedef {type_name} to {pointer_type_name}") |
73 | 93 | return pointer_type_name |
74 | 94 | else: |
75 | 95 | resolved_type.show() |
@@ -215,35 +235,6 @@ def process_headers(header_paths): |
215 | 235 | "-D__asm(x)=", |
216 | 236 | "-D__builtin_va_list=int", |
217 | 237 | "-D__extension__=", |
218 | | - "-D__inline__=", |
219 | | - "-D__restrict=", |
220 | | - "-D__restrict__=", |
221 | | - "-D_Static_assert(x, y)=", |
222 | | - "-D__signed=", |
223 | | - "-D__volatile__(x)=", |
224 | | - "-Dstatic_assert(x, y)=", |
225 | | - ], |
226 | | - ) |
227 | | - |
228 | | - # Collect all typedefs |
229 | | - typedefs = collect_typedefs(ast) |
230 | | - |
231 | | - # Collect all function declarations |
232 | | - functions = [ |
233 | | - node |
234 | | - for node in ast.ext |
235 | | - if isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.FuncDecl) |
236 | | - ] |
237 | | - |
238 | | - # Scan all return types and update Result struct |
239 | | - return_types = set() |
240 | | - for func in functions: |
241 | | - if isinstance(func.type.type, c_ast.TypeDecl): |
242 | | - return_type = " ".join(func.type.type.type.names) |
243 | | - # resolved_type = resolve_typedef(typedefs, return_type) |
244 | | - return_types.add(return_type) |
245 | | - |
246 | | - # Update the Result struct with all return types |
247 | 238 | for return_type in return_types: |
248 | 239 | if return_type == "void": |
249 | 240 | continue # No need to add void type |
|
0 commit comments