You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.8 KiB
144 lines
4.8 KiB
#!/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)
|
|
|