63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
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)
|