diff --git a/analyze.py b/analyze.py index ddf7e5e..cc267a1 100644 --- a/analyze.py +++ b/analyze.py @@ -47,7 +47,9 @@ if __name__ == "__main__": func_table = {} enum_table = {} state_asmts = [] - + fsm_funcs = [] + proc_func = None + fdv = FuncDefVisitor() fdv.visit(ast) func_table = fdv.func_table @@ -58,14 +60,22 @@ if __name__ == "__main__": if not(args.func in func_table): raise Exception(f"Function name '{args.func}' not found!") + else: + proc_func = func_table[args.func] + fsm_funcs.append(proc_func) + func_table[args.func].show() + fcv = FuncCallVisitor() + fcv.visit(proc_func) + fsm_funcs += [ func_table[x] for x in fcv.func_calls ] if args.enum in enum_table: ev = EnumVisitor() ev.visit(enum_table[args.enum]) for ename in ev.enum_names: - sav = StateAssignmentVisitor(ename) - sav.visit(func_table[args.func]) - state_asmts += sav.assignments + for f in fsm_funcs: + sav = StateAssignmentVisitor(ename) + sav.visit(f) + state_asmts += sav.assignments else: print(f"Initial State Enum '{args.enum}' not found") @@ -73,14 +83,15 @@ if __name__ == "__main__": for asm in state_asmts: paths.append(asm[1]) - common = find_common_ancestor(paths) + #common = find_common_ancestor(paths) tran_table = [] - + for sa in state_asmts: - sctv = SwitchCaseTranVisitor(sa[0]) - sctv.visit(common) - tran_table += sctv.tran_table + for f in fsm_funcs: + sctv = SwitchCaseTranVisitor(sa[0]) + sctv.visit(f) + tran_table += sctv.tran_table comp_tt = {} print("Transitions") @@ -104,10 +115,11 @@ if __name__ == "__main__": print(f"{n}->{{{sstr}}}") # find properties - sccpv = SwitchCaseCodePropertyVisitor(n, pure_sa) - sccpv.visit(common) - if len(sccpv.properties) > 0: - props_by_state[n] = sccpv.properties + for f in fsm_funcs: + sccpv = SwitchCaseCodePropertyVisitor(n, pure_sa) + sccpv.visit(f) + if len(sccpv.properties) > 0: + props_by_state[n] = sccpv.properties print("") properties = {} diff --git a/astvisitors.py b/astvisitors.py index b66a3de..97d36a8 100644 --- a/astvisitors.py +++ b/astvisitors.py @@ -3,9 +3,17 @@ 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 FuncCallVisitor(c_ast.NodeVisitor): + def __init__(self): + self.func_calls = [] + + def visit_FuncCall(self, node): + self.func_calls.append(node.children()[0][1].name) + class StateAssignmentVisitor(c_ast.NodeVisitor): def __init__(self, state): super().__init__() @@ -38,7 +46,10 @@ class StateAssignmentVisitor(c_ast.NodeVisitor): self.visit(c, path) def visit_Assignment(self, n, path): - rval_str = n.rvalue.name + n.show() + rval_str = '' + if not isinstance(n.rvalue, c_ast.Constant): + rval_str = n.rvalue.name if rval_str == self.state: self.assignments.append((n,path)) @@ -99,11 +110,19 @@ class SwitchCasePropertyVisitor(c_ast.NodeVisitor): def visit_Assignment(self, node): if not(node in self._sas): - prop = None + lvalue = None + rvalue = 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}"; + lvalue = f"{node.lvalue.children()[0][1].name}->{node.lvalue.children()[1][1].name}"; else: - prop = f"{node.lvalue.name}<={node.rvalue.name}" + lvalue = f"{node.lvalue.name}<={node.rvalue.name}" + + if isinstance(node.rvalue, c_ast.Constant): + rvalue = f"{node.rvalue.type }({node.rvalue.value})" + else: + rvalue = node.rvalue.name + + prop = f"{lvalue}<={rvalue}" self.properties.append(prop)