addons: Reduce memory consumption (#2395)

* addons: Reduce memory consumption

Parse dump files incrementaly using ElementTree.iterparse. Clean unused
resources during parsing.  This method is explained in following
article: https://www.ibm.com/developerworks/xml/library/x-hiperfparse/

Memory consumption was reduced about 30% (measured with mprof),
execution time increased about 5% (measured with time utility).
More description available in PR.

* Switch to lxml and update iterparse routines

Use lxml module instead default xml.etree. Lxml provides convenient
wrappers around iterparse method that accepts `tag` argument. That
easer incremental parsing routines to select specific tags from roottree
like `dump` and `dumps`.

Element.clear() method was replaced by `lxml_clean` because lxml
keeps additional information to nodes that should be removed.

Added note about large consumption RAM on large dump files.
This commit doesn't solve this problem completely, but provides a way
to improve current parser to add incremental Configuration serialization
later.

* Working on iterative parser

* Added iterative Configurations parser

* fix

* Fix varlist iteration

* make sure that standards node was loaded
This commit is contained in:
Georgy Komarov 2019-12-27 10:50:56 +03:00 committed by Daniel Marjamäki
parent ec4668353d
commit d977761e76
9 changed files with 267 additions and 183 deletions

View File

@ -400,7 +400,7 @@ if __name__ == '__main__':
if not args.quiet: if not args.quiet:
print('Checking %s...' % dumpfile) print('Checking %s...' % dumpfile)
data = cppcheckdata.parsedump(dumpfile) data = cppcheckdata.CppcheckData(dumpfile)
if VERIFY: if VERIFY:
VERIFY_ACTUAL = [] VERIFY_ACTUAL = []
@ -411,8 +411,8 @@ if __name__ == '__main__':
if re.match(r'cert-[A-Z][A-Z][A-Z][0-9][0-9].*',word): if re.match(r'cert-[A-Z][A-Z][A-Z][0-9][0-9].*',word):
VERIFY_EXPECTED.append(str(tok.linenr) + ':' + word) VERIFY_EXPECTED.append(str(tok.linenr) + ':' + word)
for cfg in data.configurations: for cfg in data.iterconfigurations():
if (len(data.configurations) > 1) and (not args.quiet): if not args.quiet:
print('Checking %s, config %s...' % (dumpfile, cfg.name)) print('Checking %s, config %s...' % (dumpfile, cfg.name))
exp05(cfg) exp05(cfg)
exp42(cfg) exp42(cfg)

View File

@ -6,12 +6,12 @@ This is a Python module that helps you access Cppcheck dump data.
License: No restrictions, use this as you need. License: No restrictions, use this as you need.
""" """
from xml.etree import ElementTree
import argparse import argparse
from fnmatch import fnmatch
import json import json
import sys import sys
from xml.etree import ElementTree
from fnmatch import fnmatch
class Directive: class Directive:
""" """
@ -407,8 +407,6 @@ class Function:
self.argument = {} self.argument = {}
self.argumentId = {} self.argumentId = {}
for arg in element:
self.argumentId[int(arg.get('nr'))] = arg.get('variable')
def __repr__(self): def __repr__(self):
attrs = ["Id", "tokenDefId", "name", "type", "isVirtual", attrs = ["Id", "tokenDefId", "name", "type", "isVirtual",
@ -513,22 +511,7 @@ class Variable:
self.scope = IdMap[self.scopeId] self.scope = IdMap[self.scopeId]
class ValueFlow: class Value:
"""
ValueFlow::Value class
Each possible value has a ValueFlow::Value item.
Each ValueFlow::Value either has a intvalue or tokvalue
C++ class:
http://cppcheck.net/devinfo/doxyoutput/classValueFlow_1_1Value.html
Attributes:
values Possible values
"""
Id = None
values = None
class Value:
""" """
Value class Value class
@ -581,11 +564,25 @@ class ValueFlow:
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs))
) )
class ValueFlow:
"""
ValueFlow::Value class
Each possible value has a ValueFlow::Value item.
Each ValueFlow::Value either has a intvalue or tokvalue
C++ class:
http://cppcheck.net/devinfo/doxyoutput/classValueFlow_1_1Value.html
Attributes:
values Possible values
"""
Id = None
values = None
def __init__(self, element): def __init__(self, element):
self.Id = element.get('id') self.Id = element.get('id')
self.values = [] self.values = []
for value in element:
self.values.append(ValueFlow.Value(value))
def __repr__(self): def __repr__(self):
attrs = ["Id", "values"] attrs = ["Id", "values"]
@ -649,6 +646,7 @@ class Configuration:
functions List of Function items functions List of Function items
variables List of Variable items variables List of Variable items
valueflow List of ValueFlow values valueflow List of ValueFlow values
standards List of Standards values
""" """
name = '' name = ''
@ -658,54 +656,28 @@ class Configuration:
functions = [] functions = []
variables = [] variables = []
valueflow = [] valueflow = []
standards = []
def __init__(self, confignode): def __init__(self, name):
self.name = confignode.get('cfg') self.name = name
self.directives = [] self.directives = []
self.tokenlist = [] self.tokenlist = []
self.scopes = [] self.scopes = []
self.functions = [] self.functions = []
self.variables = [] self.variables = []
self.valueflow = [] self.valueflow = []
arguments = [] self.standards = []
for element in confignode: def set_tokens_links(self):
if element.tag == "standards": """Set next/previous links between tokens."""
self.standards = Standards(element)
if element.tag == 'directivelist':
for directive in element:
self.directives.append(Directive(directive))
if element.tag == 'tokenlist':
for token in element:
self.tokenlist.append(Token(token))
# set next/previous..
prev = None prev = None
for token in self.tokenlist: for token in self.tokenlist:
token.previous = prev token.previous = prev
if prev: if prev:
prev.next = token prev.next = token
prev = token prev = token
if element.tag == 'scopes':
for scope in element:
self.scopes.append(Scope(scope))
for functionList in scope:
if functionList.tag == 'functionList':
for function in functionList:
self.functions.append(Function(function))
if element.tag == 'variables':
for variable in element:
var = Variable(variable)
if var.nameTokenId:
self.variables.append(var)
else:
arguments.append(var)
if element.tag == 'valueflow':
for values in element:
self.valueflow.append(ValueFlow(values))
def set_id_map(self, arguments):
IdMap = {None: None, '0': None, '00000000': None, '0000000000000000': None} IdMap = {None: None, '0': None, '00000000': None, '0000000000000000': None}
for token in self.tokenlist: for token in self.tokenlist:
IdMap[token.Id] = token IdMap[token.Id] = token
@ -719,7 +691,6 @@ class Configuration:
IdMap[variable.Id] = variable IdMap[variable.Id] = variable
for values in self.valueflow: for values in self.valueflow:
IdMap[values.Id] = values.values IdMap[values.Id] = values.values
for token in self.tokenlist: for token in self.tokenlist:
token.setId(IdMap) token.setId(IdMap)
for scope in self.scopes: for scope in self.scopes:
@ -731,12 +702,12 @@ class Configuration:
for variable in arguments: for variable in arguments:
variable.setId(IdMap) variable.setId(IdMap)
def __repr__(self): def setIdMap(self, functions_arguments):
attrs = ["name"] """Set relationships between objects stored in this configuration.
return "{}({})".format( :param functions_arguments: List of Variable objects which are function arguments
"Configuration", """
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) self.set_tokens_links()
) self.set_id_map(functions_arguments)
class Platform: class Platform:
@ -810,7 +781,9 @@ class CppcheckData:
Contains a list of Configuration instances Contains a list of Configuration instances
Attributes: Attributes:
configurations List of Configurations filename Path to Cppcheck dump file
rawTokens List of rawToken elements
suppressions List of Suppressions
To iterate through all configurations use such code: To iterate through all configurations use such code:
@code @code
@ -842,42 +815,156 @@ class CppcheckData:
rawTokens = [] rawTokens = []
platform = None platform = None
configurations = []
suppressions = [] suppressions = []
def __init__(self, filename): def __init__(self, filename):
self.configurations = [] """
:param filename: Path to Cppcheck dump file
"""
self.filename = filename
data = ElementTree.parse(filename) files = [] # source files for elements occurred in this configuration
platform_done = False
rawtokens_done = False
suppressions_done = False
for platformNode in data.getroot(): # Parse general configuration options from <dumps> node
if platformNode.tag == 'platform': # We intentionally don't clean node resources here because we
self.platform = Platform(platformNode) # want to serialize in memory only small part of the XML tree.
for event, node in ElementTree.iterparse(self.filename, events=('start', 'end')):
for rawTokensNode in data.getroot(): if platform_done and rawtokens_done and suppressions_done:
if rawTokensNode.tag != 'rawtokens': break
continue if node.tag == 'platform' and event == 'start':
files = [] self.platform = Platform(node)
for node in rawTokensNode: platform_done = True
if node.tag == 'file': elif node.tag == 'rawtokens' and event == 'end':
files.append(node.get('name')) for rawtokens_node in node:
elif node.tag == 'tok': if rawtokens_node.tag == 'file':
tok = Token(node) files.append(rawtokens_node.get('name'))
tok.file = files[int(node.get('fileIndex'))] elif rawtokens_node.tag == 'tok':
tok = Token(rawtokens_node)
tok.file = files[int(rawtokens_node.get('fileIndex'))]
self.rawTokens.append(tok) self.rawTokens.append(tok)
for i in range(len(self.rawTokens) - 1): rawtokens_done = True
self.rawTokens[i + 1].previous = self.rawTokens[i] elif node.tag == 'suppressions' and event == 'end':
self.rawTokens[i].next = self.rawTokens[i + 1] for suppressions_node in node:
self.suppressions.append(Suppression(suppressions_node))
suppressions_done = True
for suppressionsNode in data.getroot(): # Set links between rawTokens.
if suppressionsNode.tag == "suppressions": for i in range(len(self.rawTokens)-1):
for suppression in suppressionsNode: self.rawTokens[i+1].previous = self.rawTokens[i]
self.suppressions.append(Suppression(suppression)) self.rawTokens[i].next = self.rawTokens[i+1]
# root is 'dumps' node, each config has its own 'dump' subnode. @property
for cfgnode in data.getroot(): def configurations(self):
if cfgnode.tag == 'dump': """
self.configurations.append(Configuration(cfgnode)) Return the list of all available Configuration objects.
"""
return list(self.iterconfigurations())
def iterconfigurations(self):
"""
Create and return iterator for the available Configuration objects.
The iterator loops over all Configurations in the dump file tree, in document order.
"""
cfg = None
cfg_arguments = [] # function arguments for Configuration node initialization
cfg_function = None
cfg_valueflow = None
# Scopes contains <varlist> with all occurred variables. Some of them
# appearaed in <variables> node for this configuration.
# Others are arguments of functions.
# They have similar tag <var> but doesn't contain any attributes. So we
# set set a special state when iterate <varlist> node to prevent
# overriding of cfg.variables list with empty values.
iter_varlist = False
# Use iterable objects to traverse XML tree for dump files incrementally.
# Iterative approach is required to avoid large memory consumption.
# Calling .clear() is necessary to let the element be garbage collected.
for event, node in ElementTree.iterparse(self.filename, events=('start', 'end')):
# Serialize new configuration node
if node.tag == 'dump':
if event == 'start':
cfg = Configuration(node.get('cfg'))
continue
elif event == 'end':
cfg.setIdMap(cfg_arguments)
yield cfg
cfg = None
cfg_arguments = []
# Parse nested elemenets of configuration node
elif node.tag == "standards" and event == 'start':
continue
elif node.tag == "standards" and event == 'end':
cfg.standards = Standards(node)
# Parse directives list
elif node.tag == 'directive' and event == 'start':
cfg.directives.append(Directive(node))
# Parse tokens
elif node.tag == 'tokenlist' and event == 'start':
continue
elif node.tag == 'token' and event == 'start':
cfg.tokenlist.append(Token(node))
# Parse scopes
elif node.tag == 'scopes' and event == 'start':
continue
elif node.tag == 'scope' and event == 'start':
cfg.scopes.append(Scope(node))
elif node.tag == 'varlist':
if event == 'start':
iter_varlist = True
elif event == 'end':
iter_varlist = False
# Parse functions
elif node.tag == 'functionList' and event == 'start':
continue
elif node.tag == 'function':
if event == 'start':
cfg_function = Function(node)
continue
elif event == 'end':
cfg.functions.append(cfg_function)
cfg_function = None
# Parse function arguments
elif node.tag == 'arg' and event == 'start':
arg_nr = int(node.get('nr'))
arg_variable_id = node.get('variable')
cfg_function.argumentId[arg_nr] = arg_variable_id
# Parse variables
elif node.tag == 'var' and event == 'start':
var = Variable(node)
if var.nameTokenId:
cfg.variables.append(var)
elif not iter_varlist:
cfg_arguments.append(var)
# Parse valueflows (list of values)
elif node.tag == 'valueflow' and event == 'start':
continue
elif node.tag == 'values':
if event == 'start':
cfg_valueflow = ValueFlow(node)
continue
elif event == 'end':
cfg.valueflow.append(cfg_valueflow)
cfg_valueflow = None
# Parse values
elif node.tag == 'value' and event == 'start':
cfg_valueflow.values.append(Value(node))
# Remove links to the sibling nodes
node.clear()
def __repr__(self): def __repr__(self):
attrs = ["configurations", "platform"] attrs = ["configurations", "platform"]

View File

@ -10,12 +10,11 @@ for arg in sys.argv[1:]:
if arg.startswith('-'): if arg.startswith('-'):
continue continue
print('Checking ' + arg + '...') print('Checking %s...' % arg)
data = cppcheckdata.parsedump(arg) data = cppcheckdata.CppcheckData(arg)
for cfg in data.configurations: for cfg in data.iterconfigurations():
if len(data.configurations) > 1: print('Checking %s, config %s...' % (arg, cfg.name))
print('Checking ' + arg + ', config "' + cfg.name + '"...')
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != '(' or not token.astOperand1 or token.astOperand2: if token.str != '(' or not token.astOperand1 or token.astOperand2:
continue continue

View File

@ -49,10 +49,10 @@ def isStringLiteral(tokenString):
return tokenString.startswith('"') return tokenString.startswith('"')
# check data # check data
def stringConcatInArrayInit(configurations, rawTokens): def stringConcatInArrayInit(data):
# Get all string macros # Get all string macros
stringMacros = [] stringMacros = []
for cfg in configurations: for cfg in data.iterconfigurations():
for directive in cfg.directives: for directive in cfg.directives:
res = re.match(r'#define[ ]+([A-Za-z0-9_]+)[ ]+".*', directive.str) res = re.match(r'#define[ ]+([A-Za-z0-9_]+)[ ]+".*', directive.str)
if res: if res:
@ -62,12 +62,12 @@ def stringConcatInArrayInit(configurations, rawTokens):
# Check code # Check code
arrayInit = False arrayInit = False
for i in range(len(rawTokens)): for i in range(len(data.rawTokens)):
if i < 2: if i < 2:
continue continue
tok1 = rawTokens[i-2].str tok1 = data.rawTokens[i-2].str
tok2 = rawTokens[i-1].str tok2 = data.rawTokens[i-1].str
tok3 = rawTokens[i-0].str tok3 = data.rawTokens[i-0].str
if tok3 == '}': if tok3 == '}':
arrayInit = False arrayInit = False
elif tok1 == ']' and tok2 == '=' and tok3 == '{': elif tok1 == ']' and tok2 == '=' and tok3 == '{':
@ -76,11 +76,11 @@ def stringConcatInArrayInit(configurations, rawTokens):
isString2 = (isStringLiteral(tok2) or (tok2 in stringMacros)) isString2 = (isStringLiteral(tok2) or (tok2 in stringMacros))
isString3 = (isStringLiteral(tok3) or (tok3 in stringMacros)) isString3 = (isStringLiteral(tok3) or (tok3 in stringMacros))
if isString2 and isString3: if isString2 and isString3:
reportError(rawTokens[i], 'style', 'String concatenation in array initialization, missing comma?', 'stringConcatInArrayInit') reportError(data.rawTokens[i], 'style', 'String concatenation in array initialization, missing comma?', 'stringConcatInArrayInit')
def implicitlyVirtual(data): def implicitlyVirtual(data):
for cfg in data.configurations: for cfg in data.iterconfigurations():
for function in cfg.functions: for function in cfg.functions:
if function.isImplicitlyVirtual is None: if function.isImplicitlyVirtual is None:
continue continue
@ -89,7 +89,7 @@ def implicitlyVirtual(data):
reportError(function.tokenDef, 'style', 'Function \'' + function.name + '\' overrides base class function but is not marked with \'virtual\' keyword.', 'implicitlyVirtual') reportError(function.tokenDef, 'style', 'Function \'' + function.name + '\' overrides base class function but is not marked with \'virtual\' keyword.', 'implicitlyVirtual')
def ellipsisStructArg(data): def ellipsisStructArg(data):
for cfg in data.configurations: for cfg in data.iterconfigurations():
for tok in cfg.tokenlist: for tok in cfg.tokenlist:
if tok.str != '(': if tok.str != '(':
continue continue
@ -137,8 +137,9 @@ def ellipsisStructArg(data):
for arg in sys.argv[1:]: for arg in sys.argv[1:]:
if arg in ['-debug', '-verify', '--cli']: if arg in ['-debug', '-verify', '--cli']:
continue continue
print('Checking ' + arg + '...')
data = cppcheckdata.parsedump(arg) print("Checking %s..." % arg)
data = cppcheckdata.CppcheckData(arg)
if VERIFY: if VERIFY:
VERIFY_ACTUAL = [] VERIFY_ACTUAL = []
@ -149,7 +150,7 @@ for arg in sys.argv[1:]:
if word in ['stringConcatInArrayInit', 'implicitlyVirtual', 'ellipsisStructArg']: if word in ['stringConcatInArrayInit', 'implicitlyVirtual', 'ellipsisStructArg']:
VERIFY_EXPECTED.append(str(tok.linenr) + ':' + word) VERIFY_EXPECTED.append(str(tok.linenr) + ':' + word)
stringConcatInArrayInit(data.configurations, data.rawTokens) stringConcatInArrayInit(data)
implicitlyVirtual(data) implicitlyVirtual(data)
ellipsisStructArg(data) ellipsisStructArg(data)

View File

@ -2593,15 +2593,13 @@ class MisraChecker:
else: else:
self.printStatus('Checking ' + dumpfile + '...') self.printStatus('Checking ' + dumpfile + '...')
cfgNumber = 0 for cfgNumber, cfg in enumerate(data.iterconfigurations()):
if not self.settings.quiet:
for cfg in data.configurations: self.printStatus('Checking %s, config %s...' % (dumpfile, cfg.name))
cfgNumber = cfgNumber + 1
if len(data.configurations) > 1:
self.printStatus('Checking ' + dumpfile + ', config "' + cfg.name + '"...')
self.executeCheck(207, self.misra_2_7, cfg) self.executeCheck(207, self.misra_2_7, cfg)
if cfgNumber == 1: # data.rawTokens is same for all configurations
if cfgNumber == 0:
self.executeCheck(301, self.misra_3_1, data.rawTokens) self.executeCheck(301, self.misra_3_1, data.rawTokens)
self.executeCheck(302, self.misra_3_2, data.rawTokens) self.executeCheck(302, self.misra_3_2, data.rawTokens)
self.executeCheck(401, self.misra_4_1, data.rawTokens) self.executeCheck(401, self.misra_4_1, data.rawTokens)
@ -2612,12 +2610,12 @@ class MisraChecker:
self.executeCheck(505, self.misra_5_5, cfg) self.executeCheck(505, self.misra_5_5, cfg)
# 6.1 require updates in Cppcheck (type info for bitfields are lost) # 6.1 require updates in Cppcheck (type info for bitfields are lost)
# 6.2 require updates in Cppcheck (type info for bitfields are lost) # 6.2 require updates in Cppcheck (type info for bitfields are lost)
if cfgNumber == 1: if cfgNumber == 0:
self.executeCheck(701, self.misra_7_1, data.rawTokens) self.executeCheck(701, self.misra_7_1, data.rawTokens)
self.executeCheck(703, self.misra_7_3, data.rawTokens) self.executeCheck(703, self.misra_7_3, data.rawTokens)
self.executeCheck(811, self.misra_8_11, cfg) self.executeCheck(811, self.misra_8_11, cfg)
self.executeCheck(812, self.misra_8_12, cfg) self.executeCheck(812, self.misra_8_12, cfg)
if cfgNumber == 1: if cfgNumber == 0:
self.executeCheck(814, self.misra_8_14, data.rawTokens) self.executeCheck(814, self.misra_8_14, data.rawTokens)
self.executeCheck(905, self.misra_9_5, data.rawTokens) self.executeCheck(905, self.misra_9_5, data.rawTokens)
self.executeCheck(1001, self.misra_10_1, cfg) self.executeCheck(1001, self.misra_10_1, cfg)
@ -2631,7 +2629,7 @@ class MisraChecker:
self.executeCheck(1107, self.misra_11_7, cfg) self.executeCheck(1107, self.misra_11_7, cfg)
self.executeCheck(1108, self.misra_11_8, cfg) self.executeCheck(1108, self.misra_11_8, cfg)
self.executeCheck(1109, self.misra_11_9, cfg) self.executeCheck(1109, self.misra_11_9, cfg)
if cfgNumber == 1: if cfgNumber == 0:
self.executeCheck(1201, self.misra_12_1_sizeof, data.rawTokens) self.executeCheck(1201, self.misra_12_1_sizeof, data.rawTokens)
self.executeCheck(1201, self.misra_12_1, cfg) self.executeCheck(1201, self.misra_12_1, cfg)
self.executeCheck(1202, self.misra_12_2, cfg) self.executeCheck(1202, self.misra_12_2, cfg)
@ -2649,11 +2647,11 @@ class MisraChecker:
self.executeCheck(1502, self.misra_15_2, cfg) self.executeCheck(1502, self.misra_15_2, cfg)
self.executeCheck(1503, self.misra_15_3, cfg) self.executeCheck(1503, self.misra_15_3, cfg)
self.executeCheck(1505, self.misra_15_5, cfg) self.executeCheck(1505, self.misra_15_5, cfg)
if cfgNumber == 1: if cfgNumber == 0:
self.executeCheck(1506, self.misra_15_6, data.rawTokens) self.executeCheck(1506, self.misra_15_6, data.rawTokens)
self.executeCheck(1507, self.misra_15_7, cfg) self.executeCheck(1507, self.misra_15_7, cfg)
self.executeCheck(1602, self.misra_16_2, cfg) self.executeCheck(1602, self.misra_16_2, cfg)
if cfgNumber == 1: if cfgNumber == 0:
self.executeCheck(1603, self.misra_16_3, data.rawTokens) self.executeCheck(1603, self.misra_16_3, data.rawTokens)
self.executeCheck(1604, self.misra_16_4, cfg) self.executeCheck(1604, self.misra_16_4, cfg)
self.executeCheck(1605, self.misra_16_5, cfg) self.executeCheck(1605, self.misra_16_5, cfg)
@ -2661,7 +2659,7 @@ class MisraChecker:
self.executeCheck(1607, self.misra_16_7, cfg) self.executeCheck(1607, self.misra_16_7, cfg)
self.executeCheck(1701, self.misra_17_1, cfg) self.executeCheck(1701, self.misra_17_1, cfg)
self.executeCheck(1702, self.misra_17_2, cfg) self.executeCheck(1702, self.misra_17_2, cfg)
if cfgNumber == 1: if cfgNumber == 0:
self.executeCheck(1706, self.misra_17_6, data.rawTokens) self.executeCheck(1706, self.misra_17_6, data.rawTokens)
self.executeCheck(1707, self.misra_17_7, cfg) self.executeCheck(1707, self.misra_17_7, cfg)
self.executeCheck(1708, self.misra_17_8, cfg) self.executeCheck(1708, self.misra_17_8, cfg)
@ -2672,7 +2670,7 @@ class MisraChecker:
self.executeCheck(1902, self.misra_19_2, cfg) self.executeCheck(1902, self.misra_19_2, cfg)
self.executeCheck(2001, self.misra_20_1, cfg) self.executeCheck(2001, self.misra_20_1, cfg)
self.executeCheck(2002, self.misra_20_2, cfg) self.executeCheck(2002, self.misra_20_2, cfg)
if cfgNumber == 1: if cfgNumber == 0:
self.executeCheck(2003, self.misra_20_3, data.rawTokens) self.executeCheck(2003, self.misra_20_3, data.rawTokens)
self.executeCheck(2004, self.misra_20_4, cfg) self.executeCheck(2004, self.misra_20_4, cfg)
self.executeCheck(2005, self.misra_20_5, cfg) self.executeCheck(2005, self.misra_20_5, cfg)

View File

@ -47,10 +47,10 @@ for arg in sys.argv[1:]:
if not arg.endswith('.dump'): if not arg.endswith('.dump'):
continue continue
print('Checking ' + arg + '...') print('Checking ' + arg + '...')
data = cppcheckdata.parsedump(arg) data = cppcheckdata.CppcheckData(arg)
for cfg in data.configurations:
if len(data.configurations) > 1: for cfg in data.iterconfigurations():
print('Checking ' + arg + ', config "' + cfg.name + '"...') print('Checking %s, config %s...' % (arg, cfg.name))
if RE_VARNAME: if RE_VARNAME:
for var in cfg.variables: for var in cfg.variables:
if var.access == 'Private': if var.access == 'Private':
@ -87,4 +87,3 @@ for arg in sys.argv[1:]:
if not res: if not res:
reportError( reportError(
scope.bodyStart, 'style', 'Function ' + scope.className + ' violates naming convention', 'functionName') scope.bodyStart, 'style', 'Function ' + scope.className + ' violates naming convention', 'functionName')

View File

@ -92,7 +92,7 @@ def process(dumpfiles, configfile, debugprint=False):
if not afile[-5:] == '.dump': if not afile[-5:] == '.dump':
continue continue
print('Checking ' + afile + '...') print('Checking ' + afile + '...')
data = cppcheckdata.parsedump(afile) data = cppcheckdata.CppcheckData(afile)
# Check File naming # Check File naming
if "RE_FILE" in conf and conf["RE_FILE"]: if "RE_FILE" in conf and conf["RE_FILE"]:
@ -111,8 +111,7 @@ def process(dumpfiles, configfile, debugprint=False):
evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors) evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors)
for cfg in data.configurations: for cfg in data.configurations:
if len(data.configurations) > 1: print('Checking %s, config %s...' % (afile, cfg.name))
print('Checking ' + afile + ', config "' + cfg.name + '"...')
if "RE_VARNAME" in conf and conf["RE_VARNAME"]: if "RE_VARNAME" in conf and conf["RE_VARNAME"]:
for var in cfg.variables: for var in cfg.variables:
if var.nameToken and var.access != 'Global' and var.access != 'Public' and var.access != 'Private': if var.nameToken and var.access != 'Global' and var.access != 'Public' and var.access != 'Private':

View File

@ -27,9 +27,10 @@ def checkstatic(data):
for arg in sys.argv[1:]: for arg in sys.argv[1:]:
if arg.startswith('-'): if arg.startswith('-'):
continue continue
print('Checking ' + arg + '...')
data = cppcheckdata.parsedump(arg) print('Checking %s...' % arg)
for cfg in data.configurations: data = cppcheckdata.CppcheckData(arg)
if len(data.configurations) > 1:
print('Checking ' + arg + ', config "' + cfg.name + '"...') for cfg in data.iterconfigurations():
print('Checking %s, config %s...' % (arg, cfg.name))
checkstatic(cfg) checkstatic(cfg)

View File

@ -154,7 +154,7 @@ def check_y2038_safe(dumpfile, quiet=False):
# Assume that the code is Y2038 safe until proven otherwise # Assume that the code is Y2038 safe until proven otherwise
y2038safe = True y2038safe = True
# load XML from .dump file # load XML from .dump file
data = cppcheckdata.parsedump(dumpfile) data = cppcheckdata.CppcheckData(dumpfile)
# Convert dump file path to source file in format generated by cppcheck. # Convert dump file path to source file in format generated by cppcheck.
# For example after the following call: # For example after the following call:
@ -165,9 +165,9 @@ def check_y2038_safe(dumpfile, quiet=False):
srcfile = os.path.normpath(srcfile) srcfile = os.path.normpath(srcfile)
# go through each configuration # go through each configuration
for cfg in data.configurations: for cfg in data.iterconfigurations():
if not quiet: if not quiet:
print('Checking ' + srcfile + ', config "' + cfg.name + '"...') print('Checking %s, config %s...' % (srcfile, cfg.name))
safe_ranges = [] safe_ranges = []
safe = -1 safe = -1
time_bits_defined = False time_bits_defined = False