Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | #!/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) |