230 lines
8.6 KiB
Python
230 lines
8.6 KiB
Python
|
#!/usr/bin/python3.8
|
||
|
"""
|
||
|
@file
|
||
|
mib_datapool_parser.py
|
||
|
@brief
|
||
|
Parses the global datapools and generates the corresponding source file optionally.
|
||
|
Python 3.8 required.
|
||
|
@details
|
||
|
Used by the MIB Exporter, inherits generic File Parser.
|
||
|
@author
|
||
|
R. Mueller
|
||
|
@date
|
||
|
03.01.2020
|
||
|
"""
|
||
|
import re
|
||
|
from enum import Enum
|
||
|
from datetime import date
|
||
|
|
||
|
from parserbase.mib_parser import FileParser
|
||
|
from utility.mib_csv_writer import CsvWriter
|
||
|
from utility.mib_printer import Printer
|
||
|
from utility.mib_file_management import copy_file
|
||
|
|
||
|
|
||
|
DATE_TODAY = date.today()
|
||
|
DATAPOOL_FILE = "../../config/dataPool/dataPoolInit.h"
|
||
|
DATAPOOL_CSV_NAME = "mib_datapool.csv"
|
||
|
CPP_FILE_NAME = "dataPoolInit.cpp"
|
||
|
|
||
|
WRITE_CSV_FILE = True
|
||
|
COPY_CSV_FILE = True
|
||
|
|
||
|
WRITE_CPP_FILE = True
|
||
|
COPY_CPP_FILE = False
|
||
|
|
||
|
CPP_COPY_DESTINATION = "../../config/dataPool/"
|
||
|
DATAPOOL_HEADER_COLUMNS = ["Pool ID", "Group", "Name", "Code Name", "Size", "Type", "Unit"]
|
||
|
|
||
|
|
||
|
class DatapoolColumns(Enum):
|
||
|
"""
|
||
|
Specifies order of MIB columns
|
||
|
"""
|
||
|
POOL_ID = 0
|
||
|
GROUP = 1
|
||
|
NAME = 2
|
||
|
CODE_NAME = 3
|
||
|
SIZE = 4
|
||
|
TYPE = 5
|
||
|
UNIT = 6
|
||
|
|
||
|
|
||
|
Clmns = DatapoolColumns
|
||
|
|
||
|
|
||
|
def main():
|
||
|
"""
|
||
|
This main is run if the datapool parser is to be run separately.
|
||
|
:return:
|
||
|
"""
|
||
|
file_list = [DATAPOOL_FILE]
|
||
|
print("DatapoolParser: Parsing datapool header file:")
|
||
|
print(file_list[0])
|
||
|
datapool_parser = DatapoolParser(file_list)
|
||
|
datapool_table = datapool_parser.parse_files()
|
||
|
Printer.print_content(datapool_table, "DatapoolParser: Printing datapool variable table:")
|
||
|
dh_command_writer = CsvWriter(DATAPOOL_CSV_NAME, datapool_table, DATAPOOL_HEADER_COLUMNS)
|
||
|
if WRITE_CSV_FILE:
|
||
|
dh_command_writer.write_to_csv()
|
||
|
if COPY_CSV_FILE:
|
||
|
dh_command_writer.move_csv("..")
|
||
|
if WRITE_CPP_FILE:
|
||
|
datapool_parser.write_data_pool_init_cpp()
|
||
|
print("DatapoolParser: C++ File was created.")
|
||
|
if COPY_CPP_FILE:
|
||
|
copy_file(CPP_FILE_NAME, CPP_COPY_DESTINATION)
|
||
|
print("DatapoolParser: Generated C++ file was copied to " + CPP_COPY_DESTINATION)
|
||
|
|
||
|
|
||
|
class DatapoolParser(FileParser):
|
||
|
"""
|
||
|
This parser reads the central datapool header file.
|
||
|
It can optionally generate the corresponding source file (C++11 needed).
|
||
|
|
||
|
Instantiate the class by supplying a number of files to parse and call the parse_files() method
|
||
|
:return:
|
||
|
"""
|
||
|
def __init__(self, file_list):
|
||
|
super().__init__(file_list)
|
||
|
|
||
|
# this table includes the current new table entry,
|
||
|
# which will be updated for target parameter
|
||
|
self.dict_entry_list = list(range(Clmns.__len__()))
|
||
|
|
||
|
self.cpp_file_information_list = []
|
||
|
self.parse_success = False
|
||
|
self.parse_for_datapool_entries = False
|
||
|
self.prev_group = ""
|
||
|
|
||
|
def _handle_file_parsing(self, file_name: str, *args, **kwargs):
|
||
|
file = open(file_name, "r")
|
||
|
print("Parsing " + file_name + " ...")
|
||
|
linecount = 1
|
||
|
for line in file.readlines():
|
||
|
self.__handle_line_reading(line)
|
||
|
linecount = linecount + 1
|
||
|
|
||
|
def _post_parsing_operation(self):
|
||
|
if len(self.mib_table) > 0:
|
||
|
self.parse_success = True
|
||
|
|
||
|
def write_data_pool_init_cpp(self):
|
||
|
"""
|
||
|
Writes the data pool CPP source file if the parsing was successfull
|
||
|
:param copy_cpp:
|
||
|
:param cpp_file_name:
|
||
|
:param cpp_copy_destination:
|
||
|
:return:
|
||
|
"""
|
||
|
if not self.parse_success:
|
||
|
print("Datapool Parser: MIB Table is empty, no data to write CPP file")
|
||
|
return
|
||
|
cpp_file = open(CPP_FILE_NAME, "w")
|
||
|
current_date = DATE_TODAY.strftime("%d.%m.%Y")
|
||
|
header = "/**\n * @file\tdataPoolInit.cpp\n *\n * @brief\tAuto-Generated datapool " \
|
||
|
"initialization\n * @date\t" + current_date +\
|
||
|
"\n */\n#include <config/dataPool/dataPoolInit.h> " \
|
||
|
"\n\nvoid datapool::dataPoolInit(poolMap * poolMap) {\n"
|
||
|
cpp_file.write(header)
|
||
|
entries_len = self.index + 1
|
||
|
for index in range(1, entries_len):
|
||
|
self.__handle_entry_write(cpp_file, index)
|
||
|
tail = "\n}\n"
|
||
|
cpp_file.write(tail)
|
||
|
cpp_file.close()
|
||
|
|
||
|
def __handle_line_reading(self, line):
|
||
|
if self.parse_for_datapool_entries:
|
||
|
if not self.__scan_for_pool_variable(line):
|
||
|
self.__scan_for_export_string(line)
|
||
|
if not self.parse_for_datapool_entries:
|
||
|
datapool_start = re.search(r'[\s]*enum[\w_ ]*[\s]*{', line)
|
||
|
if datapool_start:
|
||
|
self.parse_for_datapool_entries = True
|
||
|
else:
|
||
|
self.__scan_for_datapool_end(line)
|
||
|
|
||
|
def __scan_for_export_string(self, line):
|
||
|
export_string_match = re.search(r'[/*!>< ]*\[EXPORT\][ :]*([^\n]*)', line, re.IGNORECASE)
|
||
|
if export_string_match:
|
||
|
self.__handle_export_string_match(export_string_match.group(1))
|
||
|
return export_string_match
|
||
|
|
||
|
def __handle_export_string_match(self, string):
|
||
|
group_match = re.search(r'\[GROUP\][\s]*([^\n\*]*)', string, re.IGNORECASE)
|
||
|
if group_match:
|
||
|
self.dict_entry_list[Clmns.GROUP.value] = group_match.group(1).rstrip()
|
||
|
|
||
|
def __scan_for_pool_variable(self, line):
|
||
|
pool_var_match = re.search(r'[\s]*([\w]*)[ =]*([\w]*)(?:,)?[\s]*([^\n]*)', line)
|
||
|
if pool_var_match:
|
||
|
if pool_var_match.group(1) == "":
|
||
|
return False
|
||
|
self.__handle_pool_var_match(pool_var_match)
|
||
|
return pool_var_match
|
||
|
|
||
|
def __handle_pool_var_match(self, pool_var_match):
|
||
|
if re.search(r'NO_PARAMETER', pool_var_match.group(0)):
|
||
|
return
|
||
|
self.dict_entry_list[Clmns.CODE_NAME.value] = pool_var_match.group(1)
|
||
|
self.dict_entry_list[Clmns.POOL_ID.value] = pool_var_match.group(2)
|
||
|
export_string_match = re.search(r'[/!< ]*\[EXPORT\][: ]*([^\n]*)',
|
||
|
pool_var_match.group(3), re.IGNORECASE)
|
||
|
if export_string_match:
|
||
|
self.__handle_pool_var_export_string(export_string_match.group(1))
|
||
|
datapool_tuple = tuple(self.dict_entry_list)
|
||
|
self.index = self.index + 1
|
||
|
self.mib_table.update({self.index: datapool_tuple})
|
||
|
self.dict_entry_list[Clmns.SIZE.value] = ""
|
||
|
self.dict_entry_list[Clmns.TYPE.value] = ""
|
||
|
self.dict_entry_list[Clmns.NAME.value] = ""
|
||
|
self.dict_entry_list[Clmns.UNIT.value] = ""
|
||
|
|
||
|
def __handle_pool_var_export_string(self, string):
|
||
|
extracted_entries = re.findall(r'(?:\[([\w]*)\][\s]*([^\[]*))?', string)
|
||
|
if extracted_entries:
|
||
|
extraced_entries_len = len(extracted_entries) - 1
|
||
|
for group_index in range(extraced_entries_len):
|
||
|
(group_name, group_content) = extracted_entries[group_index]
|
||
|
group_content = group_content.rstrip()
|
||
|
if group_name.casefold() == "name":
|
||
|
self.dict_entry_list[Clmns.NAME.value] = group_content
|
||
|
elif group_name.casefold() == "size":
|
||
|
self.dict_entry_list[Clmns.SIZE.value] = group_content
|
||
|
elif group_name.casefold() == "type":
|
||
|
self.dict_entry_list[Clmns.TYPE.value] = group_content
|
||
|
elif group_name.casefold() == "unit":
|
||
|
self.dict_entry_list[Clmns.UNIT.value] = group_content
|
||
|
|
||
|
def __scan_for_datapool_end(self, line):
|
||
|
datapool_end = re.search(r'}[\s]*;', line)
|
||
|
if datapool_end:
|
||
|
self.parse_for_datapool_entries = False
|
||
|
|
||
|
def __handle_entry_write(self, cpp_file, index):
|
||
|
current_mib_entry = self.mib_table.get(index)
|
||
|
(_, current_group, _, current_code_name,
|
||
|
current_size, current_type, _) = current_mib_entry
|
||
|
if current_group != self.prev_group:
|
||
|
cpp_file.write("\n\t/* " + current_group + " */\n")
|
||
|
self.prev_group = current_group
|
||
|
current_pool_entry_init_value = "{"
|
||
|
if current_size == "":
|
||
|
print("Size is unknown for a pool entry. Please specify in header file !")
|
||
|
return
|
||
|
current_size = int(current_size)
|
||
|
for count in range(current_size):
|
||
|
current_pool_entry_init_value = current_pool_entry_init_value + "0"
|
||
|
if count != current_size - 1:
|
||
|
current_pool_entry_init_value = current_pool_entry_init_value + ", "
|
||
|
current_pool_entry_init_value = current_pool_entry_init_value + "}"
|
||
|
entry_string = "\tpoolMap->emplace(datapool::" + current_code_name + \
|
||
|
",\n\t\t\tnew PoolEntry<" + current_type + ">(" + \
|
||
|
current_pool_entry_init_value + "," + str(current_size) + "));\n"
|
||
|
cpp_file.write(entry_string)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|