from pycparser import c_ast class FuncDefVisitor(c_ast.NodeVisitor): def __init__(self): self.func_table = {} def visit_FuncDef(self, node): self.func_table[node.decl.name] = node class StateAssignmentVisitor(c_ast.NodeVisitor): def __init__(self, state): super().__init__() self.state = state self.assignments = [] def visit(self, node, path = None): """ Visit a node. """ if path is None: path = [] if self._method_cache is None: self._method_cache = {} visitor = self._method_cache.get(node.__class__.__name__, None) if visitor is None: method = 'visit_' + node.__class__.__name__ visitor = getattr(self, method, self.generic_visit) self._method_cache[node.__class__.__name__] = visitor return visitor(node, path) def generic_visit(self, node, path): """ Called if no explicit visitor function exists for a node. Implements preorder visiting of the node. """ path = path.copy() path.append(node) for c in node: self.visit(c, path) def visit_Assignment(self, n, path): rval_str = n.rvalue.name if rval_str == self.state: self.assignments.append((n,path)) class EnumDefVisitor(c_ast.NodeVisitor): def __init__(self, name): super().__init__() self._name = name self.enums = {} def visit_Enum(self, node): self.enums[self._name] = node class EnumTypedefVisitor(c_ast.NodeVisitor): def __init__(self): self.enums = {} def visit_Typedef(self, node): ev = EnumDefVisitor(node.name) ev.visit(node) self.enums = {**self.enums, **ev.enums} class EnumVisitor(c_ast.NodeVisitor): def __init__(self): super().__init__() self.enum_names = [] def visit_Enumerator(self, node): self.enum_names.append(node.name) class SwitchCaseTermVisitor(c_ast.NodeVisitor): def __init__(self, asm_node): super().__init__() self._asm_node = asm_node self.hit = False def visit_Assignment(self, node): if node == self._asm_node: self.hit = True class SwitchCaseTranVisitor(c_ast.NodeVisitor): def __init__(self, asm_node): super().__init__() self._asm_node = asm_node self.tran_table = [] def visit_Case(self, node): sctv = SwitchCaseTermVisitor(self._asm_node) sctv.visit(node) if sctv.hit: self.tran_table.append((node.children()[0][1].name, self._asm_node.rvalue.name)) class SwitchCasePropertyVisitor(c_ast.NodeVisitor): def __init__(self, state_asmts): super().__init__() self._sas = state_asmts self.properties = [] def visit_Assignment(self, node): if not(node in self._sas): prop = None if isinstance(node.lvalue, c_ast.StructRef): prop = f"{node.lvalue.children()[0][1].name}->{node.lvalue.children()[1][1].name}<={node.rvalue.name}"; else: prop = f"{node.lvalue.name}<={node.rvalue.name}" self.properties.append(prop) class SwitchCaseCodePropertyVisitor(c_ast.NodeVisitor): def __init__(self, case, state_asmts): super().__init__() self._case = case self._sas = state_asmts self.properties = [] def visit_Case(self, node): label = node.children()[0][1] block = node if label.name == self._case: scpv = SwitchCasePropertyVisitor(self._sas) scpv.visit(block) self.properties += scpv.properties