Fixed cristian bug
[repair.git] / Repair / RepairCompiler / MCC / CLI.java
1 package MCC;
2
3 import java.util.Vector;
4 import java.util.StringTokenizer;
5
6 /**
7  * A generic command-line interface for 6.035 compilers.  This class
8  * provides command-line parsing for student projects.  It recognizes
9  * the required <tt>-target</tt>, <tt>-debug</tt>, <tt>-opt</tt>, and
10  * <tt>-o</tt> switches, and generates a name for input and output
11  * files.
12  *
13  * @author  le01, 6.035 Staff (<tt>6.035-staff@mit.edu</tt>)
14  * @version <tt>$Id: CLI.java,v 1.2 2004/04/15 05:41:46 bdemsky Exp $</tt>
15  */
16 public class CLI {
17     /**
18      * Target value indicating that the compiler should produce its
19      * default output.
20      */
21     public static final int DEFAULT = 0;
22
23     /**
24      * Target value indicating that the compiler should scan the input
25      * and stop.
26      */
27     public static final int SCAN = 1;
28
29     /**
30      * Target value indicating that the compiler should scan and parse
31      * its input, and stop.
32      */
33     public static final int PARSE = 2;
34
35     /**
36      * Target value indicating that the compiler should produce a
37      * high-level intermediate representation from its input, and stop.
38      * This is not one of the segment targets for Fall 2000, but you
39      * may wish to use it for your own purposes.
40      */
41     public static final int INTER = 3;
42
43     /**
44      * Target value indicating that the compiler should produce a
45      * low-level intermediate representation from its input, and stop.
46      */
47     public static final int LOWIR = 4;
48
49     /**
50      * Target value indicating that the compiler should produce
51      * assembly from its input.
52      */
53     public static final int ASSEMBLY = 5;
54
55     /**
56      * Array indicating which optimizations should be performed.  If
57      * a particular element is true, it indicates that the optimization
58      * named in the optnames[] parameter to parse with the same index
59      * should be performed.
60      */
61     public boolean opts[];
62   
63     /**
64      * Vector of String containing the command-line arguments which could
65      * not otherwise be parsed.
66      */
67     public Vector extras;
68   
69     /**
70      * Vector of String containing the optimizations which could not be
71      * parsed.  It is okay to complain about anything in this list, even
72      * without the <tt>-debug</tt> flag.
73      */
74     public Vector extraopts;
75
76     /**
77      * Name of the file to put the output in.
78      */
79     public String outfile;
80   
81     /**
82      * Name of the file to get input from.  This is null if the user didn't
83      * provide a file name.
84      */
85     public String infile;
86
87     /**
88      * The target stage.  This should be one of the integer constants
89      * defined elsewhere in this package.
90      */
91     public int target;
92
93     /**
94      * The debug flag.  This is true if <tt>-debug</tt> was passed on
95      * the command line, requesting debugging output.
96      */
97     public boolean debug;
98
99     /**
100      * Native MIPS architecture is specified by "-native".  The default
101      * is SPIM.
102      */
103     public boolean fNative;
104
105     /**
106      * Runs IRVis on final node tree.
107      */
108     public boolean fVis;
109     public String visClass;
110     public String visMethod;
111
112     /**
113      * Dumps the before and after Node structure to two files that can be diffed.
114      */
115     public boolean fDiff;
116     public String diffFile;
117
118     /**
119      * Maximum optimization iterations.
120      */
121     public int numIterations = 5;
122
123     /**
124      * Verbose output
125      */
126     public int verbose;
127
128     /**
129      * Public constructor.  Sets up default values for all of the
130      * result fields.  Specifically, sets the input and output files
131      * to null, the target to DEFAULT, and the extras and extraopts
132      * arrays to new empty Vectors.
133      */
134     public CLI() {
135         outfile = null;
136         infile = null;
137         target = DEFAULT;
138         extras = new Vector();
139         extraopts = new Vector();
140         fNative = false;
141         fVis = false;
142         verbose = 0;
143         visClass = "";
144         visMethod = "";
145         fDiff = false;
146         diffFile = "";
147     }
148
149     /**
150      * Parse the command-line arguments.  Sets all of the result fields
151      * accordingly. <BR>
152      * <ul>
153      * <li><TT>-target <I>target</I></TT> sets the CLI.target field based
154      * on the <I>target</I> specified. </li>
155      * <li><TT>scan</TT> or <TT>scanner</TT> specifies CLI.SCAN</li>
156      * <li><TT>parse</TT> specifies CLI.PARSE</li>
157      * <li><TT>inter</TT> specifies CLI.INTER</li>
158      * <li><TT>lowir</TT> specifies CLI.LOWIR</li>
159      * <TT>assembly</TT> or <TT>codegen</TT> specifies CLI.ASSEMBLY</li>
160      * </ul>
161      * The boolean array opts[] indicates which, if any, of the
162      * optimizations in optnames[] should be performed; these arrays
163      * are in the same order.
164      *
165      * @param args Array of arguments passed in to the program's Main
166      *   function.
167      * @param optnames Ordered array of recognized optimization names.  */
168     public void parse(String args[]) {
169
170         String optnames[] = {};
171         int context = 0;
172         String ext = ".out";
173
174         opts = new boolean[optnames.length];
175
176         for (int i = 0; i < args.length; i++) {
177             if (args[i].equals("-debug")) {
178                 context = 0;
179                 debug = true;
180             } else if (args[i].equals("-native")) {
181                 context = 0;
182                 fNative = true;
183             } else if (args[i].equals("-checkonly")) {
184                 Compiler.REPAIR=false;
185             } else if (args[i].equals("-vis")) {
186                 context = 4;
187                 fVis = true;
188             } else if (args[i].equals("-diff")) {
189                 context = 5;
190                 fDiff = true;
191             } else if (args[i].equals("-i")) {
192                 context = 6;
193             } else if (args[i].equals("-verbose") || args[i].equals("-v")) {
194                 context = 0;
195                 verbose++;
196             } else if (args[i].equals("-opt"))
197                 context = 1;
198             else if (args[i].equals("-o"))
199                 context = 2;
200             else if (args[i].equals("-target"))
201                 context = 3;
202             else if (context == 1) {
203                 boolean hit = false;
204                 for (int j = 0; j < optnames.length; j++) {
205                     if (args[i].equals("all") ||
206                         (args[i].equals(optnames[j]))) {
207                         hit = true;
208                         opts[j] = true;
209                     }
210                     if (args[i].equals("-" + optnames[j])) {
211                         hit = true;
212                         opts[j] = false;
213                     }
214                 }
215                 if (!hit)
216                     extraopts.addElement(args[i]);
217             }
218             else if (context == 2) {
219                 outfile = args[i];
220                 context = 0;
221             }
222             else if (context == 3) {
223                 // Process case insensitive.
224                 String argSansCase = args[i].toLowerCase();
225                 // accept "scan" and "scanner" due to handout mistake
226                 if (argSansCase.equals("scan") || 
227                     argSansCase.equals("scanner"))
228                     target = SCAN;
229                 else if (argSansCase.equals("parse"))
230                     target = PARSE;
231                 else if (argSansCase.equals("inter"))
232                     target = INTER;
233                 else if (argSansCase.equals("lowir"))
234                     target = LOWIR;
235                 else if (argSansCase.equals("assembly") ||
236                          argSansCase.equals("codegen"))
237                     target = ASSEMBLY;
238                 else
239                     target = DEFAULT; // Anything else is just default
240                 context = 0;
241             } else if (context == 4) { // -vis
242                 StringTokenizer st = new StringTokenizer(args[i], ".");
243                 visClass = st.nextToken();
244                 visMethod = st.nextToken();
245                 context = 0;
246             } else if (context == 5) { // -diff
247                 diffFile = args[i]; // argument following is filename
248                 context = 0;
249             } else if (context == 6) { // -i <iterations>
250                 numIterations = Integer.parseInt(args[i]);
251                 context = 0;
252             } else {
253                 boolean hit = false;
254                 for (int j = 0; j < optnames.length; j++) {
255                     if (args[i].equals("-" + optnames[j])) {
256                         hit = true;
257                         opts[j] = true;
258                     }
259                 }
260                 if (!hit) {
261                     extras.addElement(args[i]);
262                 }
263             }
264         }
265
266         // grab infile and lose extra args
267         int i = 0;
268         while (infile == null && i < extras.size()) {
269             String fn = (String) extras.elementAt(i);
270           
271             if (fn.charAt(0) != '-')
272             {
273                 infile = fn;
274                 extras.removeElementAt(i);
275             }
276             i++;
277         }
278
279         // create outfile name
280         switch (target) {
281         case SCAN:
282             ext = ".scan";
283             break;
284         case PARSE:
285             ext = ".parse";
286             break;
287         case INTER:
288             ext = ".ir";
289             break;
290         case LOWIR:
291             ext = ".lowir";
292             break;
293         case ASSEMBLY:
294             ext = ".s";
295             break;
296         case DEFAULT:
297         default:
298             ext = ".out";
299             break;
300         }
301
302         if (outfile == null && infile != null) {
303             int dot = infile.lastIndexOf('.');
304             int slash = infile.lastIndexOf('/');
305             // Last dot comes after last slash means that the file
306             // has an extention.  Note that the base case where dot
307             // or slash are -1 also work.
308             if (dot <= slash)
309                 outfile = infile + ext;
310             else
311                 outfile = infile.substring(0, dot) + ext;
312         }
313     }
314 }