#!/usr/bin/env python3 # Copyright (c) 2023 Baumer (www.baumer.com) # SPDX-License-Identifier: Apache-2.0 """This script converting the Zephyr coding guideline rst file to a output file, or print the output to the console. Which than can be used by a tool which needs to have that information in a specific format (e.g. for cppcheck). Or simply use the rule list to generate a filter to suppress all other rules used by default from such a tool. """ import sys import re import argparse from pathlib import Path class RuleFormatter: """ Base class for the different output formats """ def table_start_print(self, outputfile): pass def severity_print(self, outputfile, guideline_number, severity): pass def description_print(self, outputfile, guideline_number, description): pass def closing_print(self, outputfile): pass class CppCheckFormatter(RuleFormatter): """ Formatter class to print the rules in a format which can be used by cppcheck """ def table_start_print(self, outputfile): # Start search by cppcheck misra addon print('Appendix A Summary of guidelines', file=outputfile) def severity_print(self, outputfile, guideline_number, severity): print('Rule ' + guideline_number + ' ' + severity, file=outputfile) def description_print(self, outputfile, guideline_number, description): print(description + '(Misra rule ' + guideline_number + ')', file=outputfile) def closing_print(self, outputfile): # Make cppcheck happy by starting the appendix print('Appendix B', file=outputfile) print('', file=outputfile) def convert_guidelines(args): inputfile = args.input outputfile = sys.stdout formatter = None # If the output is not empty, open the given file for writing if args.output is not None: outputfile = open(args.output, "w") try: file_stream = open(inputfile, 'rt', errors='ignore') except Exception: print('Error opening ' + inputfile +'.') sys.exit() # Set formatter according to the used format if args.format == 'cppcheck': formatter = CppCheckFormatter() # Search for table named Main rules pattern_table_start = re.compile(r'.*list-table:: Main rules') # Each Rule is a new table column so start with '[tab]* - Rule' # Ignore directives here pattern_new_line = re.compile(r'^ \* - Rule ([0-9]+.[0-9]+).*$') # Each table column start with '[tab]- ' pattern_new_col = re.compile(r'^ - (.*)$') table_start = False guideline_number = '' guideline_state = 0 guideline_list = [] for line in file_stream: line = line.replace('\r', '').replace('\n', '') # Done if we find the Additional rules table start if line.find('Additional rules') >= 0: break if len(line) == 0: continue if not table_start: res = pattern_table_start.match(line) if res: table_start = True formatter.table_start_print(outputfile) continue res = pattern_new_line.match(line) if res: guideline_state = "severity" guideline_number = res.group(1) guideline_list.append(guideline_number) continue elif guideline_number == '': continue res = pattern_new_col.match(line) if res: if guideline_state == "severity": # Severity formatter.severity_print(outputfile, guideline_number, res.group(1)) guideline_state = "description" continue if guideline_state == "description": # Description formatter.description_print(outputfile, guideline_number, res.group(1)) guideline_state = "None" # We stop here for now, we do not handle the CERT C col guideline_number = '' continue formatter.closing_print(outputfile) if __name__ == "__main__": supported_formats = ['cppcheck'] parser = argparse.ArgumentParser(allow_abbrev=False) parser.add_argument( "-i", "--input", metavar="RST_FILE", type=Path, required=True, help="Path to rst input source file, where the guidelines are written down." ) parser.add_argument( "-f", "--format", metavar="FORMAT", choices=supported_formats, required=True, help="Format to convert guidlines to. Supported formats are: " + str(supported_formats) ) parser.add_argument( "-o", "--output", metavar="OUTPUT_FILE", type=Path, required=False, help="Path to output file, where the converted guidelines are written to. If outputfile is not specified, print to stdout." ) args = parser.parse_args() convert_guidelines(args)