1
+ """
2
+ usage: reduce.py [-h] -exe EXE -exe_args EXE_ARGS -expected EXPECTED -file FILE [-segfault]
3
+
4
+ options:
5
+ -h, --help show this help message and exit
6
+ -exe EXE, --exe EXE cppcheck executable
7
+ -exe_args EXE_ARGS, --exe_args EXE_ARGS
8
+ cppcheck executable commands
9
+ -expected EXPECTED, --expected EXPECTED
10
+ expected text output
11
+ -file FILE, --file FILE
12
+ source file
13
+ -segfault, --segfault
14
+ """
15
+
1
16
#!/usr/bin/env python3
2
17
import subprocess
3
18
import sys
4
19
import time
20
+ import argparse
5
21
6
22
7
23
class Reduce :
8
24
def __init__ (self , cmd , expected , file , segfault = None ):
9
- if cmd is None :
25
+ if not "" . join ( cmd ) :
10
26
raise RuntimeError ('Abort: No --cmd' )
11
27
12
- if not segfault and expected is None :
28
+ if not segfault and not expected :
13
29
raise RuntimeError ('Abort: No --expected' )
14
30
15
- if file is None :
31
+ if not file :
16
32
raise RuntimeError ('Abort: No --file' )
17
33
18
34
# need to add '--error-exitcode=0' so detected issues will not be interpreted as a crash
19
35
if segfault and '--error-exitcode=0' not in cmd :
20
36
print ("Adding '--error-exitcode=0' to --cmd" )
21
- self .__cmd = cmd + ' --error-exitcode=0'
37
+ self .__cmd = cmd + [ ' --error-exitcode=0']
22
38
else :
23
39
self .__cmd = cmd
24
40
self .__expected = expected
@@ -30,7 +46,7 @@ def __init__(self, cmd, expected, file, segfault=None):
30
46
self .__elapsed_time = None
31
47
32
48
def print_info (self ):
33
- print ('CMD=' + self .__cmd )
49
+ print ('CMD=' , " " . join ( self .__cmd ) )
34
50
if self .__segfault :
35
51
print ('EXPECTED=SEGFAULT' )
36
52
else :
@@ -46,7 +62,7 @@ def runtool(self, filedata=None):
46
62
timeout = None
47
63
if self .__elapsed_time :
48
64
timeout = self .__elapsed_time * 2
49
- p = subprocess .Popen (self .__cmd . split () , stdout = subprocess .PIPE , stderr = subprocess .PIPE , universal_newlines = True )
65
+ p = subprocess .Popen (self .__cmd , stdout = subprocess .PIPE , stderr = subprocess .PIPE , universal_newlines = True )
50
66
try :
51
67
comm = self .__communicate (p , timeout = timeout )
52
68
except TimeoutExpired :
@@ -268,31 +284,27 @@ def main():
268
284
# TODO: add --hang option to detect code which impacts the analysis time
269
285
def show_syntax ():
270
286
print ('Syntax:' )
271
- print (' reduce.py --cmd=< full command> --expected= <expected text output> --file= <source file> [--segfault]' )
287
+ print (' reduce.py --exe <cppcheck executable> --exe_args < full command> --expected <expected text output> --file <source file> [--segfault]' )
272
288
print ('' )
273
289
print ("Example. source file = foo/bar.c" )
274
290
print (
275
- " reduce.py --cmd=' ./cppcheck --enable=style foo/bar.c' --expected= \ " Variable 'x ' is reassigned\ " --file= foo/bar.c" )
291
+ ' reduce.py --exe ./cppcheck --exe_args " -- enable=style" --expected "Variable \' x \ ' is reassigned" --file foo/bar.c' )
276
292
sys .exit (1 )
277
293
278
294
if len (sys .argv ) == 1 :
279
295
show_syntax ()
280
-
281
- arg_cmd = None
282
- arg_expected = None
283
- arg_file = None
284
- arg_segfault = False
285
-
286
- for arg in sys .argv [1 :]:
287
- if arg .startswith ('--cmd=' ):
288
- arg_cmd = arg [arg .find ('=' ) + 1 :]
289
- elif arg .startswith ('--expected=' ):
290
- arg_expected = arg [arg .find ('=' ) + 1 :]
291
- elif arg .startswith ('--file=' ):
292
- arg_file = arg [arg .find ('=' ) + 1 :]
293
- elif arg == '--segfault' :
294
- arg_segfault = True
295
-
296
+ parser = argparse .ArgumentParser ()
297
+ parser .add_argument ('-exe' , '--exe' , required = True , help = "cppcheck executable" )
298
+ parser .add_argument ('-exe_args' , '--exe_args' , required = False , default = "" , help = "cppcheck executable commands" )
299
+ parser .add_argument ('-expected' , '--expected' , required = True , help = "expected text output" )
300
+ parser .add_argument ('-file' , '--file' , required = True , help = "source file" )
301
+ parser .add_argument ('-segfault' , '--segfault' , required = False , action = 'store_true' )
302
+ args = parser .parse_args ()
303
+
304
+ arg_file = args .file
305
+ arg_cmd = [args .exe ] + args .exe_args .split () + [arg_file ]
306
+ arg_expected = args .expected
307
+ arg_segfault = args .segfault
296
308
try :
297
309
reduce = Reduce (arg_cmd , arg_expected , arg_file , arg_segfault )
298
310
except RuntimeError as e :
0 commit comments