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
|
#!/usr/bin/env python3
import os
from xml.etree import ElementTree
class CppcheckHTMLReportError(Exception):
pass
class CppcheckTXTReportError(Exception):
pass
def __elements_equal(el1, el2):
if type(el1) != type(el2): return False
if el1.find('location') is None: return False
if el2.find('location') is None: return False
el1_location = str(el1.find('location').attrib)
el2_location = str(el2.find('location').attrib)
if el1_location != el2_location: return False
return True
def __contain_element(new, lst):
for elem in lst:
if __elements_equal(new, elem):
return True
return False
def __get_xml_root_file(filename):
try:
result_xml_root = ElementTree.parse(filename).getroot()
except ElementTree.ParseError as e:
raise CppcheckHTMLReportError(
"XML parsing error in {}: {}".format(filename, e)
)
return result_xml_root
def __sanitize_cppcheck_xml_path(xml_tree, src_path, obj_path):
# Some path are relative to the source tree but some others are generated
# in the obj tree, for cppcheck when using cppcheck-htmlreport we can pass
# only one source tree where the files will be fetched if relative path are
# found. So for every path that does not exists in src tree, we guess it
# comes from obj tree and we put explicit absolute path to it
error_item_root = xml_tree.findall("errors")[0]
for error_item in error_item_root:
for location_item in error_item.findall("location"):
path = location_item.attrib["file"]
new_obj_path = obj_path + "/" + path
new_src_path = src_path + "/" + path
if (path[0] != "/") and (not os.path.isfile(new_src_path)) \
and os.path.isfile(new_obj_path):
location_item.attrib["file"] = new_obj_path
def cppcheck_merge_xml_fragments(fragments_list, out_xml_file, src_path,
obj_path):
result_xml = __get_xml_root_file(fragments_list[0])
insert_point = result_xml.findall("errors")[0]
for xml_file in fragments_list[1:]:
xml_root = __get_xml_root_file(xml_file)
curr_elem_list = list(insert_point)
new_elem_list = list(xml_root.findall("errors")[0])
for xml_error_elem in new_elem_list:
if not __contain_element(xml_error_elem, curr_elem_list):
insert_point.insert(1, xml_error_elem)
if result_xml is None:
return False
__sanitize_cppcheck_xml_path(result_xml, src_path, obj_path)
ElementTree.ElementTree(result_xml).write(out_xml_file)
return True
def cppcheck_merge_txt_fragments(fragments_list, out_txt_file, strip_paths):
try:
with open(out_txt_file, "wt") as outfile:
# Using a set will remove automatically the duplicate lines
text_report_content = set()
for file in fragments_list:
try:
with open(file, "rt") as infile:
frag_lines = infile.readlines()
except OSError as e:
raise CppcheckTXTReportError(
"Issue with reading file {}: {}"
.format(file, e)
)
text_report_content.update(frag_lines)
# Back to modifiable list
text_report_content = list(text_report_content)
# Strip path from report lines
for i in list(range(0, len(text_report_content))):
for path in strip_paths:
text_report_content[i] = text_report_content[i].replace(
path + "/", "")
# Split by : separator
text_report_content[i] = text_report_content[i].split(":")
# sort alphabetically for second field (misra rule) and as second
# criteria for the first field (file name)
text_report_content.sort(key = lambda x: (x[1], x[0]))
# merge back with : separator
text_report_content = [":".join(x) for x in text_report_content]
# Write the final text report
outfile.writelines(text_report_content)
except OSError as e:
raise CppcheckTXTReportError("Issue with writing file {}: {}"
.format(out_txt_file, e))
def cppcheck_strip_path_html(html_files, strip_paths):
for file in html_files:
try:
with open(file, "rt") as infile:
html_lines = infile.readlines()
except OSError as e:
raise CppcheckHTMLReportError("Issue with reading file {}: {}"
.format(file, e))
for i in list(range(0, len(html_lines))):
for path in strip_paths:
html_lines[i] = html_lines[i].replace(path + "/", "")
try:
with open(file, "wt") as outfile:
outfile.writelines(html_lines)
except OSError as e:
raise CppcheckHTMLReportError("Issue with writing file {}: {}"
.format(file, e))
|