1+ #!/usr/bin/python3
2+ import shutil
3+ import tempfile
4+ import argparse
5+ import os
6+ import re
7+ import subprocess
8+
9+ # Copyright © 2016 Edward Smith <tedks@cs.umass.edu>
10+ #
11+ # This program is free software: you can redistribute it and/or modify
12+ # it under the terms of the GNU General Public License as published by
13+ # the Free Software Foundation, either version 3 of the License, or
14+ # (at your option) any later version.
15+ #
16+ # This program is distributed in the hope that it will be useful,
17+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+ # GNU General Public License for more details.
20+ #
21+ # You should have received a copy of the GNU General Public License
22+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
23+
24+
25+ GP_PARAMS = {'sanity' : 'no' ,
26+ 'search' : 'oracle' ,
27+ 'fix-scheme' : 'uniform' ,
28+ 'fault-scheme' : 'uniform' ,
29+ 'pos-tests' : 0 ,
30+ 'neg-tests' : 0 ,
31+ 'oracle-genome' : None ,
32+ 'program' : None }
33+
34+ PROGRAMS = ['checksum' , 'digits' , 'grade' , 'median' , 'smallest' , 'syllables' ]
35+
36+ def args_of_dict (d ):
37+ args = []
38+ for (ck , cv ) in d .items ():
39+ if ck .startswith ('-' ):
40+ args .append (ck )
41+ else :
42+ args .append ("--{}" .format (ck ))
43+ if cv is not None :
44+ args .append (str (cv ))
45+ return args
46+
47+ def repatch (logfile , repair = 'repair' , output = 'repair.c' ):
48+ log = open (logfile )
49+ repair_line = None
50+ repair_regex = re .compile (r"Repair Found: ([adr\d\s,()]+\))" )
51+ args = GP_PARAMS
52+
53+ for line in log :
54+ if "Repair Found" in line : repair_line = line
55+
56+ if repair_line is None :
57+ raise ValueError ("Couldn't find repair in {}. " .format (logfile )
58+ + "Does this file contain a repair?" )
59+ match = repair_regex .search (repair_line )
60+ if match is None :
61+ raise ValueError ("Couldn't find repair string in {}" .format (logfile ))
62+ args ['oracle-genome' ] = match .group (1 )
63+
64+ program = None
65+ for p in PROGRAMS :
66+ if p in logfile : program = p
67+ args ['program' ] = os .path .dirname (logfile ) + os .path .sep + program + ".c"
68+
69+ args = args_of_dict (args )
70+
71+ # create a temp directory for GenProg. This is necessary because
72+ # otherwise GenProg will just write repair.c to CWD.
73+ with tempfile .TemporaryDirectory () as tmpdir :
74+ exit_code = subprocess .call ([repair ] + args ,
75+ stdout = subprocess .PIPE ,
76+ cwd = tmpdir )
77+ if exit_code != 0 : return exit_code
78+
79+ shutil .move (tmpdir + os .path .sep + "repair.c" , output )
80+ return exit_code
81+
82+
83+ def main ():
84+ parser = argparse .ArgumentParser ("A tool to regenerate GenProg repairs from the GenProg log." ,
85+ formatter_class = argparse .ArgumentDefaultsHelpFormatter )
86+ parser .add_argument ("repair" , help = "The path to the GenProg repair executable" )
87+ parser .add_argument ("log" , help = "The log to regenerate the patch from" )
88+ parser .add_argument ("--output_file" , '-o' , help = "Path to write the repaired program to." ,
89+ default = "repair.c" )
90+
91+ args = parser .parse_args ()
92+
93+ exit (repatch (os .path .abspath (args .log ),
94+ repair = os .path .abspath (args .repair ),
95+ output = args .output_file ))
96+
97+ if __name__ == "__main__" :
98+ main ()
0 commit comments