slight refactor
This commit is contained in:
parent
aad9547029
commit
210a40e4fa
89
analyze.py
89
analyze.py
@ -1,16 +1,11 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import re
|
|
||||||
from pycparser import parse_file, c_ast, CParser
|
from pycparser import parse_file, c_ast, CParser
|
||||||
import graphviz as gv
|
import graphviz as gv
|
||||||
|
|
||||||
from modelbuilder import *
|
from modelbuilder import *
|
||||||
|
from utils import *
|
||||||
func_table = {}
|
|
||||||
enum_table = {}
|
|
||||||
assign_table = []
|
|
||||||
state_enums = []
|
|
||||||
|
|
||||||
class FuncDefVisitor(c_ast.NodeVisitor):
|
class FuncDefVisitor(c_ast.NodeVisitor):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -58,14 +53,19 @@ class EnumDefVisitor(c_ast.NodeVisitor):
|
|||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self.enums = {}
|
||||||
|
|
||||||
def visit_Enum(self, node):
|
def visit_Enum(self, node):
|
||||||
enum_table[self._name] = node
|
self.enums[self._name] = node
|
||||||
|
|
||||||
|
class EnumTypedefVisitor(c_ast.NodeVisitor):
|
||||||
|
def __init__(self):
|
||||||
|
self.enums = {}
|
||||||
|
|
||||||
class TypedefVisitor(c_ast.NodeVisitor):
|
|
||||||
def visit_Typedef(self, node):
|
def visit_Typedef(self, node):
|
||||||
ev = EnumDefVisitor(node.name)
|
ev = EnumDefVisitor(node.name)
|
||||||
ev.visit(node)
|
ev.visit(node)
|
||||||
|
self.enums = {**self.enums, **ev.enums}
|
||||||
|
|
||||||
|
|
||||||
class EnumVisitor(c_ast.NodeVisitor):
|
class EnumVisitor(c_ast.NodeVisitor):
|
||||||
@ -74,46 +74,7 @@ class EnumVisitor(c_ast.NodeVisitor):
|
|||||||
self.enum_names = []
|
self.enum_names = []
|
||||||
|
|
||||||
def visit_Enumerator(self, node):
|
def visit_Enumerator(self, node):
|
||||||
self.enum_names.append(node.name)
|
self.enum_names.append(node.name)
|
||||||
|
|
||||||
def find_longest_path(paths):
|
|
||||||
ms = 0
|
|
||||||
mp = None
|
|
||||||
for path in paths:
|
|
||||||
s = len(path)
|
|
||||||
if s > ms:
|
|
||||||
ms = s
|
|
||||||
mp = path
|
|
||||||
return mp
|
|
||||||
|
|
||||||
def find_shortest_path(paths):
|
|
||||||
ms = float('inf')
|
|
||||||
mp = None
|
|
||||||
for path in paths:
|
|
||||||
s = len(path)
|
|
||||||
if s < ms:
|
|
||||||
ms = s
|
|
||||||
mp = path
|
|
||||||
return mp
|
|
||||||
|
|
||||||
def find_common_ancestor(paths):
|
|
||||||
shortest_path = find_shortest_path(paths)
|
|
||||||
|
|
||||||
last_common = None
|
|
||||||
for gen_i,_ in enumerate(shortest_path):
|
|
||||||
common = True
|
|
||||||
last_node = paths[0][gen_i]
|
|
||||||
|
|
||||||
for path in paths:
|
|
||||||
if last_node == path[gen_i]:
|
|
||||||
common = True
|
|
||||||
last_node = path[gen_i]
|
|
||||||
else:
|
|
||||||
common = False
|
|
||||||
if common:
|
|
||||||
last_common = last_node
|
|
||||||
return last_common
|
|
||||||
|
|
||||||
|
|
||||||
class SwitchCaseTermVisitor(c_ast.NodeVisitor):
|
class SwitchCaseTermVisitor(c_ast.NodeVisitor):
|
||||||
def __init__(self, asm_node):
|
def __init__(self, asm_node):
|
||||||
@ -159,7 +120,6 @@ class SwitchCaseCodePropertyVisitor(c_ast.NodeVisitor):
|
|||||||
self._case = case
|
self._case = case
|
||||||
self._sas = state_asmts
|
self._sas = state_asmts
|
||||||
self.properties = []
|
self.properties = []
|
||||||
|
|
||||||
|
|
||||||
def visit_Case(self, node):
|
def visit_Case(self, node):
|
||||||
label = node.children()[0][1]
|
label = node.children()[0][1]
|
||||||
@ -169,27 +129,11 @@ class SwitchCaseCodePropertyVisitor(c_ast.NodeVisitor):
|
|||||||
scpv.visit(block)
|
scpv.visit(block)
|
||||||
self.properties += scpv.properties
|
self.properties += scpv.properties
|
||||||
|
|
||||||
def comment_remover(text):
|
|
||||||
def replacer(match):
|
|
||||||
s = match.group(0)
|
|
||||||
if s.startswith('/'):
|
|
||||||
return ""
|
|
||||||
else:
|
|
||||||
return s
|
|
||||||
pattern = re.compile(
|
|
||||||
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
|
|
||||||
re.DOTALL | re.MULTILINE
|
|
||||||
)
|
|
||||||
return re.sub(pattern, replacer, text)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
argparser = argparse.ArgumentParser('Create a Kripke Structure Model from C Code')
|
argparser = argparse.ArgumentParser('Create a Kripke Structure Model from C Code')
|
||||||
argparser.add_argument('filename',
|
argparser.add_argument('filename',
|
||||||
nargs='?',
|
nargs='?',
|
||||||
help='name of file to parse')
|
help='name of file to parse')
|
||||||
argparser.add_argument('--coord', help='show coordinates in the dump',
|
|
||||||
action='store_true')
|
|
||||||
|
|
||||||
argparser.add_argument('--func', help='process function')
|
argparser.add_argument('--func', help='process function')
|
||||||
argparser.add_argument('--enum', help='state enum')
|
argparser.add_argument('--enum', help='state enum')
|
||||||
argparser.add_argument('--initial', help='initial state')
|
argparser.add_argument('--initial', help='initial state')
|
||||||
@ -197,7 +141,7 @@ if __name__ == "__main__":
|
|||||||
argparser.add_argument('-o', '--output', dest='output', help='output NuSMV file')
|
argparser.add_argument('-o', '--output', dest='output', help='output NuSMV file')
|
||||||
argparser.add_argument('--dot', help='output dot file')
|
argparser.add_argument('--dot', help='output dot file')
|
||||||
args = argparser.parse_args()
|
args = argparser.parse_args()
|
||||||
|
|
||||||
source = ""
|
source = ""
|
||||||
with open(args.filename, "r") as f:
|
with open(args.filename, "r") as f:
|
||||||
#read whole file to a string
|
#read whole file to a string
|
||||||
@ -206,16 +150,22 @@ if __name__ == "__main__":
|
|||||||
parser = CParser()
|
parser = CParser()
|
||||||
ast = parser.parse(comment_remover(source))
|
ast = parser.parse(comment_remover(source))
|
||||||
#ast = parse_file(args.filename, use_cpp=False)
|
#ast = parse_file(args.filename, use_cpp=False)
|
||||||
|
|
||||||
|
assign_table = []
|
||||||
|
state_enums = []
|
||||||
|
func_table = {}
|
||||||
|
enum_table = {}
|
||||||
|
|
||||||
fdv = FuncDefVisitor()
|
fdv = FuncDefVisitor()
|
||||||
fdv.visit(ast)
|
fdv.visit(ast)
|
||||||
func_table = fdv.func_table
|
func_table = fdv.func_table
|
||||||
|
|
||||||
enumvis = TypedefVisitor()
|
etv = EnumTypedefVisitor()
|
||||||
enumvis.visit(ast)
|
etv.visit(ast)
|
||||||
|
enum_table = etv.enums
|
||||||
|
|
||||||
state_asmts = []
|
state_asmts = []
|
||||||
|
|
||||||
if args.enum in enum_table:
|
if args.enum in enum_table:
|
||||||
ev = EnumVisitor()
|
ev = EnumVisitor()
|
||||||
ev.visit(enum_table[args.enum])
|
ev.visit(enum_table[args.enum])
|
||||||
@ -297,7 +247,6 @@ if __name__ == "__main__":
|
|||||||
print("-------------------")
|
print("-------------------")
|
||||||
print(nusmv)
|
print(nusmv)
|
||||||
|
|
||||||
|
|
||||||
if args.dot is not None:
|
if args.dot is not None:
|
||||||
g = gv.Digraph('G')
|
g = gv.Digraph('G')
|
||||||
|
|
||||||
|
|||||||
11
test.c
11
test.c
@ -17,7 +17,14 @@ typedef struct
|
|||||||
bool m_b;
|
bool m_b;
|
||||||
} testfsm_t;
|
} testfsm_t;
|
||||||
|
|
||||||
void process(testfsm_t *p_fsm, const bool input)
|
typedef struct
|
||||||
|
{
|
||||||
|
bool m_i;
|
||||||
|
bool m_oa;
|
||||||
|
bool m_ob
|
||||||
|
} testfsm_pd_t;
|
||||||
|
|
||||||
|
void process_internal(testfsm_t *p_fsm, const bool input)
|
||||||
{
|
{
|
||||||
testfsm_state_t nextState = p_fsm->m_state;
|
testfsm_state_t nextState = p_fsm->m_state;
|
||||||
|
|
||||||
@ -56,6 +63,8 @@ void process(testfsm_t *p_fsm, const bool input)
|
|||||||
p_fsm->m_state = nextState;
|
p_fsm->m_state = nextState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void process_outputs(testfsm_t *p_fsm, const bool input
|
||||||
|
|
||||||
bool randbool(int throws)
|
bool randbool(int throws)
|
||||||
{
|
{
|
||||||
bool stillTrue = true;
|
bool stillTrue = true;
|
||||||
|
|||||||
55
utils.py
Normal file
55
utils.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
def find_longest_path(paths):
|
||||||
|
ms = 0
|
||||||
|
mp = None
|
||||||
|
for path in paths:
|
||||||
|
s = len(path)
|
||||||
|
if s > ms:
|
||||||
|
ms = s
|
||||||
|
mp = path
|
||||||
|
return mp
|
||||||
|
|
||||||
|
def find_shortest_path(paths):
|
||||||
|
ms = float('inf')
|
||||||
|
mp = None
|
||||||
|
for path in paths:
|
||||||
|
s = len(path)
|
||||||
|
if s < ms:
|
||||||
|
ms = s
|
||||||
|
mp = path
|
||||||
|
return mp
|
||||||
|
|
||||||
|
def find_common_ancestor(paths):
|
||||||
|
if len(paths) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
shortest_path = find_shortest_path(paths)
|
||||||
|
|
||||||
|
last_common = None
|
||||||
|
for gen_i,_ in enumerate(shortest_path):
|
||||||
|
common = True
|
||||||
|
last_node = paths[0][gen_i]
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
if last_node == path[gen_i]:
|
||||||
|
common = True
|
||||||
|
last_node = path[gen_i]
|
||||||
|
else:
|
||||||
|
common = False
|
||||||
|
if common:
|
||||||
|
last_common = last_node
|
||||||
|
return last_common
|
||||||
|
|
||||||
|
def comment_remover(text):
|
||||||
|
def replacer(match):
|
||||||
|
s = match.group(0)
|
||||||
|
if s.startswith('/'):
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return s
|
||||||
|
pattern = re.compile(
|
||||||
|
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
|
||||||
|
re.DOTALL | re.MULTILINE
|
||||||
|
)
|
||||||
|
return re.sub(pattern, replacer, text)
|
||||||
Loading…
x
Reference in New Issue
Block a user