from cxxheaderparser.parser import CxxParser, ParserOptions from cxxheaderparser.visitor import CxxVisitor from cxxheaderparser.preprocessor import make_pcpp_preprocessor from cxxheaderparser.parserstate import NamespaceBlockState from cxxheaderparser.types import EnumDecl import textwrap import os class Visitor: def on_enum(self, state: NamespaceBlockState, cursor: EnumDecl) -> None: enum_name = cursor.typename.segments[0].format() if '<' in enum_name: raise Exception( "Enum '{}' is an anonymous enum, please name it\n".format(cursor.doxygen[3:] if cursor.doxygen else '') ) enum_constants = dict() for enum_const in cursor.values: name = enum_const.name.format() if enum_const.value is None: raise Exception(f"Enum constant '{name}' in '{enum_name}' does not have an explicit value assignment.") value = enum_const.value.format() if value in enum_constants: other_constant = enum_constants[value] error = f""" Enum '{enum_name}' contains a duplicate value: Value {value} is defined for both '{other_constant}' and '{name}' """ error = textwrap.dedent(error) raise Exception(error) enum_constants[value] = name print(f"Successfully verified the integrity of enum {enum_name} ({len(enum_constants)} entries)") def __getattr__(self, name): return lambda *args, **kwargs: True def parse_enum(file_path): # Create index parser = CxxParser( file_path, None, visitor=Visitor(), options=ParserOptions(preprocessor=make_pcpp_preprocessor()), ) parser.parse() if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description="Parse a C header file and check enum integrity.") parser.add_argument("file_path", type=str, help="Path to the C header file") args = parser.parse_args() file_path = args.file_path if not os.path.exists(file_path): raise Exception(f"Error: file '{file_path}' does not exist") enum_dict = parse_enum(file_path)