#!/bin/env python3.6 from sys import argv from collections import Counter """ Naive parser and pretty printer for the MISRA reports by cppcheck """ class Summarizer(object): def __init__(self, report_name): with open(report_name, 'r') as f: self.file_lines = f.readlines() f.close() self.red = "\033[91m" self.yellow = "\033[93m" self.green = "\033[92m" self.bold = "\033[1m" self.end = "\033[0m" def analyze(self): """ A really dumb parser for the pre-processed report generated by cppcheck """ errors_map = {} # dictionary containing filenames, rule violations and line where the violation occurred lines_seen = set() # contains the unique lines from the file if len(self.file_lines) == 0: print(bold + green + "Static analysis for MISRA compliance complete. No errors found." + end) return 0 for line in self.file_lines: # remove duplicate lines if line not in lines_seen: lines_seen.add(line) line_contents = line.split(':') file_name = line_contents[0] # first part is the filename (index 0) error = (line_contents[1], line_contents[2].strip('\n')) # index 1 is the line number, index 2 is the number of violated rule if file_name not in errors_map.keys(): errors_map[file_name] = list() # create a new list for the new filename and append the tuple in it errors_map[file_name].append(error) else: errors_map[file_name].append(error) # do not append if it already exists return errors_map # return the completed error dictionary def pretty_print(self, errors): """ Pretty-prints the contents of the error dictionary with colors and stuff """ print(self.bold + self.red + "=================================================\n" + self.end) print(self.bold + self.red + " Static analysis results: Error Summary \n" + self.end) for key in errors: for error in errors[key]: name_string = f"{self.bold}{self.red}File {self.yellow}{key}{self.red}" rule_violated_string = f"violates rule {self.yellow}#{error[1]}{self.red} of the MISRA C 2012 standard" line_number_string = f"at line {self.yellow}{error[0]}{self.end}" print(f"{name_string.ljust(75)} {rule_violated_string} {line_number_string}") print("") print("") print(self.bold + self.red +"=================================================" + self.end) if __name__ == "__main__": s = Summarizer(argv[1]) errors = s.analyze() if isinstance(errors, dict): s.pretty_print(errors) exit(127) elif isinstance(errors, int) and errors == 0: exit(0)