several bugfixes and improvements
This commit is contained in:
parent
8e805d2408
commit
16280cc1df
@ -1,37 +1,37 @@
|
|||||||
"""
|
"""Generic File Parser class
|
||||||
@file file_list_parser.py
|
|
||||||
@brief Generic File Parser class
|
|
||||||
@details
|
|
||||||
Used by parse header files. Implemented as class in case header parser becomes more complex
|
Used by parse header files. Implemented as class in case header parser becomes more complex
|
||||||
@author R. Mueller
|
|
||||||
@date 22.11.2019
|
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
from fsfwgen.core import get_console_logger
|
||||||
|
|
||||||
|
LOGGER = get_console_logger()
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class FileListParser:
|
class FileListParser:
|
||||||
"""
|
"""Generic header parser which takes a directory name or directory name list
|
||||||
Generic header parser which takes a directory name or directory name list
|
|
||||||
and parses all included header files recursively.
|
and parses all included header files recursively.
|
||||||
|
TODO: Filter functionality for each directory to filter out files or folders
|
||||||
"""
|
"""
|
||||||
def __init__(self, directory_list_or_name: Union[str, list]):
|
def __init__(self, directory_list_or_name: Union[str, list]):
|
||||||
|
self.directory_list = []
|
||||||
if isinstance(directory_list_or_name, str):
|
if isinstance(directory_list_or_name, str):
|
||||||
self.directory_list = [directory_list_or_name]
|
self.directory_list.append(directory_list_or_name)
|
||||||
elif isinstance(directory_list_or_name, list):
|
elif isinstance(directory_list_or_name, list):
|
||||||
self.directory_list = directory_list_or_name
|
self.directory_list.extend(directory_list_or_name)
|
||||||
else:
|
else:
|
||||||
print("Header Parser: Passed directory list is not a header name or list of "
|
LOGGER.warning(
|
||||||
"header names")
|
"Header Parser: Passed directory list is not a header name or list of header names"
|
||||||
|
)
|
||||||
self.header_files = []
|
self.header_files = []
|
||||||
|
|
||||||
def parse_header_files(self, search_recursively: bool = False,
|
def parse_header_files(self, search_recursively: bool = False,
|
||||||
printout_string: str = "Parsing header files: ",
|
printout_string: str = "Parsing header files: ",
|
||||||
print_current_dir: bool = False):
|
print_current_dir: bool = False):
|
||||||
"""
|
"""This function is called to get a list of header files
|
||||||
This function is called to get a list of header files
|
|
||||||
:param search_recursively:
|
:param search_recursively:
|
||||||
:param printout_string:
|
:param printout_string:
|
||||||
:param print_current_dir:
|
:param print_current_dir:
|
||||||
|
@ -17,6 +17,12 @@ from abc import abstractmethod
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
|
|
||||||
|
class VerbosityLevels(enum.Enum):
|
||||||
|
REDUCED = 0,
|
||||||
|
REGULAR = 1,
|
||||||
|
DEBUG = 2
|
||||||
|
|
||||||
|
|
||||||
class FileParserModes(enum.Enum):
|
class FileParserModes(enum.Enum):
|
||||||
REGULAR = enum.auto(),
|
REGULAR = enum.auto(),
|
||||||
MOVING_WINDOW = enum.auto()
|
MOVING_WINDOW = enum.auto()
|
||||||
@ -72,6 +78,9 @@ class FileParser:
|
|||||||
def set_verbosity(self, verbose_level: int):
|
def set_verbosity(self, verbose_level: int):
|
||||||
self._verbose_level = verbose_level
|
self._verbose_level = verbose_level
|
||||||
|
|
||||||
|
def get_verbosity(self):
|
||||||
|
return self._verbose_level
|
||||||
|
|
||||||
def enable_moving_window_debugging(self, file_name: str):
|
def enable_moving_window_debugging(self, file_name: str):
|
||||||
self.__debug_moving_window = True
|
self.__debug_moving_window = True
|
||||||
self.__debug_moving_window_filename = file_name
|
self.__debug_moving_window_filename = file_name
|
||||||
@ -201,6 +210,8 @@ class FileParser:
|
|||||||
def _build_multi_line_string_generic(
|
def _build_multi_line_string_generic(
|
||||||
self, first_line: str, moving_window: List[str]
|
self, first_line: str, moving_window: List[str]
|
||||||
) -> str:
|
) -> str:
|
||||||
|
"""This function transforms a multi line match into a one line match by searching for the
|
||||||
|
semicolon at the string end"""
|
||||||
all_lines = first_line.rstrip()
|
all_lines = first_line.rstrip()
|
||||||
end_found = False
|
end_found = False
|
||||||
current_idx = self._moving_window_center_idx
|
current_idx = self._moving_window_center_idx
|
||||||
|
@ -2,19 +2,21 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
||||||
from fsfwgen.parserbase.parser import FileParser
|
from fsfwgen.parserbase.parser import FileParser, VerbosityLevels
|
||||||
from fsfwgen.utility.printer import PrettyPrinter
|
from fsfwgen.utility.printer import PrettyPrinter
|
||||||
|
from fsfwgen.core import get_console_logger
|
||||||
|
|
||||||
|
LOGGER = get_console_logger()
|
||||||
|
|
||||||
# Intermediate solution
|
# Intermediate solution
|
||||||
MAX_STRING_LEN = 80
|
MAX_STRING_LEN = 80
|
||||||
|
|
||||||
PRINT_TRUNCATED_ENTRIES = False
|
PRINT_TRUNCATED_ENTRIES = False
|
||||||
DEBUG_INTERFACE_ID_COMPARISON = False
|
|
||||||
DEBUG_FOR_FILE_NAME = False
|
DEBUG_FOR_FILE_NAME = False
|
||||||
|
|
||||||
DEBUG_FILE_NAME = "RingBufferAnalyzer"
|
|
||||||
CLASS_ID_NAMESPACE = "CLASS_ID"
|
CLASS_ID_NAMESPACE = "CLASS_ID"
|
||||||
DEFAULT_MOVING_WINDOWS_SIZE = 7
|
DEFAULT_MOVING_WINDOWS_SIZE = 7
|
||||||
|
INVALID_IF_ID = -1
|
||||||
|
|
||||||
|
|
||||||
class InterfaceParser(FileParser):
|
class InterfaceParser(FileParser):
|
||||||
@ -26,6 +28,10 @@ class InterfaceParser(FileParser):
|
|||||||
self.file_name_table = []
|
self.file_name_table = []
|
||||||
self.start_name_list = []
|
self.start_name_list = []
|
||||||
self.end_name_list = []
|
self.end_name_list = []
|
||||||
|
self._debug_mode = False
|
||||||
|
|
||||||
|
def enable_debug_mode(self, enable: bool):
|
||||||
|
self._debug_mode = enable
|
||||||
|
|
||||||
def _handle_file_parsing_moving_window(
|
def _handle_file_parsing_moving_window(
|
||||||
self, file_name: str, current_line: int, moving_window_size: int, moving_window: list,
|
self, file_name: str, current_line: int, moving_window_size: int, moving_window: list,
|
||||||
@ -182,7 +188,7 @@ class ReturnValueParser(FileParser):
|
|||||||
):
|
):
|
||||||
"""Parse for returnvalues using a moving window"""
|
"""Parse for returnvalues using a moving window"""
|
||||||
interface_id_match = re.search(
|
interface_id_match = re.search(
|
||||||
rf"{CLASS_ID_NAMESPACE}::([a-zA-Z_0-9]*)", moving_window[self._moving_window_center_idx]
|
rf'{CLASS_ID_NAMESPACE}::([a-zA-Z_0-9]*)', moving_window[self._moving_window_center_idx]
|
||||||
)
|
)
|
||||||
|
|
||||||
if interface_id_match:
|
if interface_id_match:
|
||||||
@ -202,22 +208,36 @@ class ReturnValueParser(FileParser):
|
|||||||
moving_window=moving_window,
|
moving_window=moving_window,
|
||||||
first_line=moving_window[self._moving_window_center_idx]
|
first_line=moving_window[self._moving_window_center_idx]
|
||||||
)
|
)
|
||||||
|
number_match = INVALID_IF_ID
|
||||||
|
# Try to match for a string using the new API first. Example:
|
||||||
|
# static const ReturnValue_t PACKET_TOO_LONG =
|
||||||
|
# HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0);
|
||||||
returnvalue_match = re.search(
|
returnvalue_match = re.search(
|
||||||
r"^[\s]*static const(?:expr)? ReturnValue_t[\s]*([\w] *)[\s]*"
|
r"^[\s]*static const(?:expr)? ReturnValue_t[\s]*([\w]*)[\s]*"
|
||||||
r"=[\s]*.*::[\w]*\(([\w]*),[\s]*([\d]*)\)",
|
r"=[\s]*.*::[\w]*\(([\w]*),[\s]*([\d]*)\)",
|
||||||
full_returnvalue_string
|
full_returnvalue_string
|
||||||
)
|
)
|
||||||
if not returnvalue_match:
|
if not returnvalue_match:
|
||||||
|
# Try to match for old API using MAE_RETURN_CODE macro
|
||||||
returnvalue_match = re.search(
|
returnvalue_match = re.search(
|
||||||
r'^[\s]*static const(?:expr)? ReturnValue_t[\s]*([a-zA-Z_0-9]*)[\s]*=[\s]*'
|
r'^[\s]*static const(?:expr)? ReturnValue_t[\s]*([a-zA-Z_0-9]*)[\s]*=[\s]*'
|
||||||
r'MAKE_RETURN_CODE[\s]*\([\s]*([\w]*)[\s]*\)',
|
r'MAKE_RETURN_CODE[\s]*\([\s]*([\w]*)[\s]*\)',
|
||||||
full_returnvalue_string
|
full_returnvalue_string
|
||||||
)
|
)
|
||||||
|
if returnvalue_match:
|
||||||
|
number_match = returnvalue_match.group(2)
|
||||||
|
else:
|
||||||
|
number_match = returnvalue_match.group(3)
|
||||||
if returnvalue_match:
|
if returnvalue_match:
|
||||||
description = self.__search_for_descrip_string(moving_window=moving_window)
|
description = self.__search_for_descrip_string(moving_window=moving_window)
|
||||||
|
if number_match == INVALID_IF_ID:
|
||||||
|
LOGGER.warning(f'Invalid number match detected for file {file_name}')
|
||||||
|
LOGGER.warning(f'Match groups:')
|
||||||
|
for group in returnvalue_match.groups():
|
||||||
|
LOGGER.info(group)
|
||||||
self.__handle_returnvalue_match(
|
self.__handle_returnvalue_match(
|
||||||
name_match=returnvalue_match.group(1), file_name=file_name,
|
name_match=returnvalue_match.group(1), file_name=file_name,
|
||||||
number_match=returnvalue_match.group(2), description=description
|
number_match=number_match, description=description
|
||||||
)
|
)
|
||||||
|
|
||||||
def __build_multi_line_returnvalue_string(
|
def __build_multi_line_returnvalue_string(
|
||||||
@ -256,17 +276,27 @@ class ReturnValueParser(FileParser):
|
|||||||
self.last_lines[1] = self.last_lines[0]
|
self.last_lines[1] = self.last_lines[0]
|
||||||
self.last_lines[0] = newline
|
self.last_lines[0] = newline
|
||||||
|
|
||||||
def __handle_interfaceid_match(self, interface_id_match, file_name: str):
|
def __handle_interfaceid_match(self, interface_id_match, file_name: str) -> bool:
|
||||||
if DEBUG_INTERFACE_ID_COMPARISON:
|
"""Handle a match of an interface ID definition in the code.
|
||||||
print(f"Interface ID {interface_id_match.group(1)} found in {file_name}")
|
Returns whether the interface ID was found successfully in the IF ID header files
|
||||||
self.current_interface_id_entries["ID"] = \
|
"""
|
||||||
self.interfaces[interface_id_match.group(1)][0]
|
if self.get_verbosity() == VerbosityLevels.DEBUG:
|
||||||
|
LOGGER.info(f'Interface ID {interface_id_match.group(1)} found in {file_name}')
|
||||||
|
if_id_entry = self.interfaces.get(interface_id_match.group(1))
|
||||||
|
if if_id_entry is not None:
|
||||||
|
self.current_interface_id_entries["ID"] = if_id_entry[0]
|
||||||
|
else:
|
||||||
|
LOGGER.warning(
|
||||||
|
f'Interface ID {interface_id_match.group(1)} not found in IF ID dictionary'
|
||||||
|
)
|
||||||
|
return False
|
||||||
self.current_interface_id_entries["Name"] = \
|
self.current_interface_id_entries["Name"] = \
|
||||||
self.interfaces[interface_id_match.group(1)][1]
|
self.interfaces[interface_id_match.group(1)][1]
|
||||||
self.current_interface_id_entries["FullName"] = interface_id_match.group(1)
|
self.current_interface_id_entries["FullName"] = interface_id_match.group(1)
|
||||||
if DEBUG_INTERFACE_ID_COMPARISON:
|
if self.get_verbosity() == VerbosityLevels.DEBUG:
|
||||||
current_id = self.current_interface_id_entries["ID"]
|
current_id = self.current_interface_id_entries["ID"]
|
||||||
print(f"Current ID: {current_id}")
|
LOGGER.info(f'Current ID: {current_id}')
|
||||||
|
return True
|
||||||
|
|
||||||
def __handle_returnvalue_match(
|
def __handle_returnvalue_match(
|
||||||
self, name_match: str, number_match: str, file_name: str, description: str
|
self, name_match: str, number_match: str, file_name: str, description: str
|
||||||
@ -312,7 +342,7 @@ class ReturnValueParser(FileParser):
|
|||||||
my_str = first_part + '_' + self.convert(second_part)
|
my_str = first_part + '_' + self.convert(second_part)
|
||||||
if len(my_str) > max_string_len:
|
if len(my_str) > max_string_len:
|
||||||
if print_truncated_entries:
|
if print_truncated_entries:
|
||||||
print("Warning: Entry " + my_str + " too long. Will truncate.")
|
LOGGER.warning(f'Entry {my_str} too long. Will truncate.')
|
||||||
my_str = my_str[0:max_string_len]
|
my_str = my_str[0:max_string_len]
|
||||||
else:
|
else:
|
||||||
# print("Entry: " + myStr + " is all right.")
|
# print("Entry: " + myStr + " is all right.")
|
||||||
@ -342,6 +372,6 @@ def return_number_from_string(a_string):
|
|||||||
return int(a_string, 16)
|
return int(a_string, 16)
|
||||||
if a_string.isdigit():
|
if a_string.isdigit():
|
||||||
return int(a_string)
|
return int(a_string)
|
||||||
print('Error: Illegal number representation: ' + a_string)
|
LOGGER.warning(f'Illegal number representation: {a_string}')
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user