162306a36Sopenharmony_ci#!/usr/bin/env python3 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ci# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org> 562306a36Sopenharmony_ci# 662306a36Sopenharmony_ci# dot2c: parse an automata in dot file digraph format into a C 762306a36Sopenharmony_ci# 862306a36Sopenharmony_ci# This program was written in the development of this paper: 962306a36Sopenharmony_ci# de Oliveira, D. B. and Cucinotta, T. and de Oliveira, R. S. 1062306a36Sopenharmony_ci# "Efficient Formal Verification for the Linux Kernel." International 1162306a36Sopenharmony_ci# Conference on Software Engineering and Formal Methods. Springer, Cham, 2019. 1262306a36Sopenharmony_ci# 1362306a36Sopenharmony_ci# For further information, see: 1462306a36Sopenharmony_ci# Documentation/trace/rv/deterministic_automata.rst 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cifrom dot2.automata import Automata 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciclass Dot2c(Automata): 1962306a36Sopenharmony_ci enum_suffix = "" 2062306a36Sopenharmony_ci enum_states_def = "states" 2162306a36Sopenharmony_ci enum_events_def = "events" 2262306a36Sopenharmony_ci struct_automaton_def = "automaton" 2362306a36Sopenharmony_ci var_automaton_def = "aut" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci def __init__(self, file_path): 2662306a36Sopenharmony_ci super().__init__(file_path) 2762306a36Sopenharmony_ci self.line_length = 100 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci def __buff_to_string(self, buff): 3062306a36Sopenharmony_ci string = "" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci for line in buff: 3362306a36Sopenharmony_ci string = string + line + "\n" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci # cut off the last \n 3662306a36Sopenharmony_ci return string[:-1] 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci def __get_enum_states_content(self): 3962306a36Sopenharmony_ci buff = [] 4062306a36Sopenharmony_ci buff.append("\t%s%s = 0," % (self.initial_state, self.enum_suffix)) 4162306a36Sopenharmony_ci for state in self.states: 4262306a36Sopenharmony_ci if state != self.initial_state: 4362306a36Sopenharmony_ci buff.append("\t%s%s," % (state, self.enum_suffix)) 4462306a36Sopenharmony_ci buff.append("\tstate_max%s" % (self.enum_suffix)) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return buff 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci def get_enum_states_string(self): 4962306a36Sopenharmony_ci buff = self.__get_enum_states_content() 5062306a36Sopenharmony_ci return self.__buff_to_string(buff) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci def format_states_enum(self): 5362306a36Sopenharmony_ci buff = [] 5462306a36Sopenharmony_ci buff.append("enum %s {" % self.enum_states_def) 5562306a36Sopenharmony_ci buff.append(self.get_enum_states_string()) 5662306a36Sopenharmony_ci buff.append("};\n") 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci return buff 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci def __get_enum_events_content(self): 6162306a36Sopenharmony_ci buff = [] 6262306a36Sopenharmony_ci first = True 6362306a36Sopenharmony_ci for event in self.events: 6462306a36Sopenharmony_ci if first: 6562306a36Sopenharmony_ci buff.append("\t%s%s = 0," % (event, self.enum_suffix)) 6662306a36Sopenharmony_ci first = False 6762306a36Sopenharmony_ci else: 6862306a36Sopenharmony_ci buff.append("\t%s%s," % (event, self.enum_suffix)) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci buff.append("\tevent_max%s" % self.enum_suffix) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci return buff 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci def get_enum_events_string(self): 7562306a36Sopenharmony_ci buff = self.__get_enum_events_content() 7662306a36Sopenharmony_ci return self.__buff_to_string(buff) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci def format_events_enum(self): 7962306a36Sopenharmony_ci buff = [] 8062306a36Sopenharmony_ci buff.append("enum %s {" % self.enum_events_def) 8162306a36Sopenharmony_ci buff.append(self.get_enum_events_string()) 8262306a36Sopenharmony_ci buff.append("};\n") 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return buff 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci def get_minimun_type(self): 8762306a36Sopenharmony_ci min_type = "unsigned char" 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if self.states.__len__() > 255: 9062306a36Sopenharmony_ci min_type = "unsigned short" 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if self.states.__len__() > 65535: 9362306a36Sopenharmony_ci min_type = "unsigned int" 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if self.states.__len__() > 1000000: 9662306a36Sopenharmony_ci raise Exception("Too many states: %d" % self.states.__len__()) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci return min_type 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci def format_automaton_definition(self): 10162306a36Sopenharmony_ci min_type = self.get_minimun_type() 10262306a36Sopenharmony_ci buff = [] 10362306a36Sopenharmony_ci buff.append("struct %s {" % self.struct_automaton_def) 10462306a36Sopenharmony_ci buff.append("\tchar *state_names[state_max%s];" % (self.enum_suffix)) 10562306a36Sopenharmony_ci buff.append("\tchar *event_names[event_max%s];" % (self.enum_suffix)) 10662306a36Sopenharmony_ci buff.append("\t%s function[state_max%s][event_max%s];" % (min_type, self.enum_suffix, self.enum_suffix)) 10762306a36Sopenharmony_ci buff.append("\t%s initial_state;" % min_type) 10862306a36Sopenharmony_ci buff.append("\tbool final_states[state_max%s];" % (self.enum_suffix)) 10962306a36Sopenharmony_ci buff.append("};\n") 11062306a36Sopenharmony_ci return buff 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci def format_aut_init_header(self): 11362306a36Sopenharmony_ci buff = [] 11462306a36Sopenharmony_ci buff.append("static const struct %s %s = {" % (self.struct_automaton_def, self.var_automaton_def)) 11562306a36Sopenharmony_ci return buff 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci def __get_string_vector_per_line_content(self, buff): 11862306a36Sopenharmony_ci first = True 11962306a36Sopenharmony_ci string = "" 12062306a36Sopenharmony_ci for entry in buff: 12162306a36Sopenharmony_ci if first: 12262306a36Sopenharmony_ci string = string + "\t\t\"" + entry 12362306a36Sopenharmony_ci first = False; 12462306a36Sopenharmony_ci else: 12562306a36Sopenharmony_ci string = string + "\",\n\t\t\"" + entry 12662306a36Sopenharmony_ci string = string + "\"" 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return string 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci def get_aut_init_events_string(self): 13162306a36Sopenharmony_ci return self.__get_string_vector_per_line_content(self.events) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci def get_aut_init_states_string(self): 13462306a36Sopenharmony_ci return self.__get_string_vector_per_line_content(self.states) 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci def format_aut_init_events_string(self): 13762306a36Sopenharmony_ci buff = [] 13862306a36Sopenharmony_ci buff.append("\t.event_names = {") 13962306a36Sopenharmony_ci buff.append(self.get_aut_init_events_string()) 14062306a36Sopenharmony_ci buff.append("\t},") 14162306a36Sopenharmony_ci return buff 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci def format_aut_init_states_string(self): 14462306a36Sopenharmony_ci buff = [] 14562306a36Sopenharmony_ci buff.append("\t.state_names = {") 14662306a36Sopenharmony_ci buff.append(self.get_aut_init_states_string()) 14762306a36Sopenharmony_ci buff.append("\t},") 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci return buff 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci def __get_max_strlen_of_states(self): 15262306a36Sopenharmony_ci max_state_name = max(self.states, key = len).__len__() 15362306a36Sopenharmony_ci return max(max_state_name, self.invalid_state_str.__len__()) 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci def __get_state_string_length(self): 15662306a36Sopenharmony_ci maxlen = self.__get_max_strlen_of_states() + self.enum_suffix.__len__() 15762306a36Sopenharmony_ci return "%" + str(maxlen) + "s" 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci def get_aut_init_function(self): 16062306a36Sopenharmony_ci nr_states = self.states.__len__() 16162306a36Sopenharmony_ci nr_events = self.events.__len__() 16262306a36Sopenharmony_ci buff = [] 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci strformat = self.__get_state_string_length() 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci for x in range(nr_states): 16762306a36Sopenharmony_ci line = "\t\t{ " 16862306a36Sopenharmony_ci for y in range(nr_events): 16962306a36Sopenharmony_ci next_state = self.function[x][y] 17062306a36Sopenharmony_ci if next_state != self.invalid_state_str: 17162306a36Sopenharmony_ci next_state = self.function[x][y] + self.enum_suffix 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if y != nr_events-1: 17462306a36Sopenharmony_ci line = line + strformat % next_state + ", " 17562306a36Sopenharmony_ci else: 17662306a36Sopenharmony_ci line = line + strformat % next_state + " }," 17762306a36Sopenharmony_ci buff.append(line) 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci return self.__buff_to_string(buff) 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci def format_aut_init_function(self): 18262306a36Sopenharmony_ci buff = [] 18362306a36Sopenharmony_ci buff.append("\t.function = {") 18462306a36Sopenharmony_ci buff.append(self.get_aut_init_function()) 18562306a36Sopenharmony_ci buff.append("\t},") 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci return buff 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci def get_aut_init_initial_state(self): 19062306a36Sopenharmony_ci return self.initial_state 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci def format_aut_init_initial_state(self): 19362306a36Sopenharmony_ci buff = [] 19462306a36Sopenharmony_ci initial_state = self.get_aut_init_initial_state() 19562306a36Sopenharmony_ci buff.append("\t.initial_state = " + initial_state + self.enum_suffix + ",") 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return buff 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci def get_aut_init_final_states(self): 20062306a36Sopenharmony_ci line = "" 20162306a36Sopenharmony_ci first = True 20262306a36Sopenharmony_ci for state in self.states: 20362306a36Sopenharmony_ci if first == False: 20462306a36Sopenharmony_ci line = line + ', ' 20562306a36Sopenharmony_ci else: 20662306a36Sopenharmony_ci first = False 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci if self.final_states.__contains__(state): 20962306a36Sopenharmony_ci line = line + '1' 21062306a36Sopenharmony_ci else: 21162306a36Sopenharmony_ci line = line + '0' 21262306a36Sopenharmony_ci return line 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci def format_aut_init_final_states(self): 21562306a36Sopenharmony_ci buff = [] 21662306a36Sopenharmony_ci buff.append("\t.final_states = { %s }," % self.get_aut_init_final_states()) 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci return buff 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci def __get_automaton_initialization_footer_string(self): 22162306a36Sopenharmony_ci footer = "};\n" 22262306a36Sopenharmony_ci return footer 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci def format_aut_init_footer(self): 22562306a36Sopenharmony_ci buff = [] 22662306a36Sopenharmony_ci buff.append(self.__get_automaton_initialization_footer_string()) 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return buff 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci def format_invalid_state(self): 23162306a36Sopenharmony_ci buff = [] 23262306a36Sopenharmony_ci buff.append("#define %s state_max%s\n" % (self.invalid_state_str, self.enum_suffix)) 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return buff 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci def format_model(self): 23762306a36Sopenharmony_ci buff = [] 23862306a36Sopenharmony_ci buff += self.format_states_enum() 23962306a36Sopenharmony_ci buff += self.format_invalid_state() 24062306a36Sopenharmony_ci buff += self.format_events_enum() 24162306a36Sopenharmony_ci buff += self.format_automaton_definition() 24262306a36Sopenharmony_ci buff += self.format_aut_init_header() 24362306a36Sopenharmony_ci buff += self.format_aut_init_states_string() 24462306a36Sopenharmony_ci buff += self.format_aut_init_events_string() 24562306a36Sopenharmony_ci buff += self.format_aut_init_function() 24662306a36Sopenharmony_ci buff += self.format_aut_init_initial_state() 24762306a36Sopenharmony_ci buff += self.format_aut_init_final_states() 24862306a36Sopenharmony_ci buff += self.format_aut_init_footer() 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci return buff 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci def print_model_classic(self): 25362306a36Sopenharmony_ci buff = self.format_model() 25462306a36Sopenharmony_ci print(self.__buff_to_string(buff)) 255