Skip to content

Instantly share code, notes, and snippets.

@Vbitz
Created March 6, 2024 01:23
Show Gist options
  • Save Vbitz/ed7488166d4df28f666cd836c5976ee6 to your computer and use it in GitHub Desktop.
Save Vbitz/ed7488166d4df28f666cd836c5976ee6 to your computer and use it in GitHub Desktop.
# structcompile.py
# Joshua Scarsbrook (@[email protected])
# Very horrible code.
# License: Apache-2.0
import argparse
import pycparser # Install with pip install pycparser
ast = pycparser.c_parser.c_ast
class BuiltinType:
def __init__(self, format):
self.format = format
def decl_to_python_struct(globals, decl) -> str:
if type(decl) == BuiltinType:
return decl.format
typ = decl.type
if type(typ) == ast.IdentifierType:
name = " ".join(typ.names)
return decl_to_python_struct(globals, globals[name])
else:
raise NotImplementedError(type(typ))
def struct_to_python_struct(globals, struct) -> str:
if type(struct) != ast.Struct:
raise Exception("struct is not a Struct")
ret = "@"
for decl in struct.decls:
typ = decl.type
if type(typ) == ast.ArrayDecl:
array_format = decl_to_python_struct(globals, typ.type)
dim = typ.dim
if type(dim) == ast.Constant:
if dim.type == "int":
ret += dim.value + array_format
else:
raise NotImplementedError(type(dim))
elif type(typ) == ast.TypeDecl:
ret += decl_to_python_struct(globals, typ)
else:
raise NotImplementedError(type(typ))
return ret
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="structcompile.py",
)
parser.add_argument(
"filename",
help="the file to include to find the structure. Unless --use-cpp is used this file must be preprocessed already.",
)
parser.add_argument("struct_name", help="the name of the struct to find")
parser.add_argument(
"--use-cpp",
action="store_true",
help="run the cpp preprocessor. filename will be looked up in the default include path.",
)
args = parser.parse_args()
parsed = None
if args.use_cpp:
with open("tmp.c", "w") as f:
f.write(f"#include <{args.filename}>")
parsed = pycparser.parse_file("tmp.c", use_cpp=True)
else:
parsed = pycparser.parse_file(args.filename)
decls = {}
decls["unsigned char"] = BuiltinType("B")
decls["unsigned short"] = BuiltinType("H")
decls["unsigned int"] = BuiltinType("I")
for node in parsed:
if type(node) == ast.Typedef:
decls[node.name] = node.type
if node.name == args.struct_name:
print(struct_to_python_struct(decls, node.type.type))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment