from pycparser import c_ast, parse_file class Function: def __init__(self, name, return_type, args): self.name = name self.return_type = return_type self.args = args typemap = { "_Bool": "bool", "ExtismPlugin": "int32_t", "ExtismSize": "uint64_t", } class Type: def __init__(self, name, const=False, pointer=False): self.name = typemap.get(name) or name self.const = const self.pointer = pointer class Arg: def __init__(self, name, type): self.name = name self.type = type class Visitor(c_ast.NodeVisitor): def __init__(self, header): self.header = header def args(self, args): dest = [] for arg in args: name = arg.name if isinstance(arg.type, c_ast.PtrDecl): t = arg.type.type is_ptr = True else: t = arg.type is_ptr = False if hasattr(t.type, 'name'): type_name = t.type.name else: try: type_name = t.type.names[0] except: continue const = hasattr(t.type, 'quals') and 'const' in t.type.quals t = Type(type_name, const=const, pointer=is_ptr) dest.append(Arg(name, t)) return dest def visit_FuncDecl(self, node: c_ast.FuncDecl): if isinstance(node.type, c_ast.PtrDecl): t = node.type.type is_ptr = True else: t = node.type is_ptr = False name = t.declname args = self.args(node.args) if hasattr(t.type, 'name'): return_type_name = t.type.name else: return_type_name = t.type.names[0] const = hasattr(t.type, 'quals') and 'const' in t.type.quals return_type = Type(return_type_name, const=const, pointer=is_ptr) self.header.functions.append(Function(name, return_type, args)) class Header: def __init__(self, filename='runtime/extism.h'): self.functions = [] self.header = parse_file(filename, use_cpp=True, cpp_args='-w') self.visitor = Visitor(self) self.visitor.visit(self.header) def __iter__(self): return self.functions.__iter__() def __getitem__(self, func): for f in self.functions: if f.name == func: return f return None