001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.options;
014    
015    import org.vmmagic.pragma.Uninterruptible;
016    import org.vmmagic.unboxed.Extent;
017    import org.vmmagic.unboxed.Word;
018    import org.vmutil.options.AddressOption;
019    import org.vmutil.options.BooleanOption;
020    import org.vmutil.options.EnumOption;
021    import org.vmutil.options.FloatOption;
022    import org.vmutil.options.IntOption;
023    import org.vmutil.options.MicrosecondsOption;
024    import org.vmutil.options.Option;
025    import org.vmutil.options.PagesOption;
026    import org.vmutil.options.StringOption;
027    
028    import org.jikesrvm.VM;
029    import org.jikesrvm.Constants;
030    import org.jikesrvm.CommandLineArgs;
031    
032    /**
033     * Class to handle command-line arguments and options for GC.
034     */
035    public final class OptionSet extends org.vmutil.options.OptionSet {
036    
037      private String prefix;
038    
039      public static final OptionSet gc = new OptionSet("-X:gc");
040    
041      private OptionSet(String prefix) {
042        this.prefix = prefix;
043      }
044    
045      /**
046       * Take a string (most likely a command-line argument) and try to proccess it
047       * as an option command.  Return true if the string was understood, false
048       * otherwise.
049       *
050       * @param arg a String to try to process as an option command
051       * @return {@code true} if successful, {@code false} otherwise
052       */
053      public boolean process(String arg) {
054    
055        // First handle the "option commands"
056        if (arg.equals("help")) {
057           printHelp();
058           return true;
059        }
060        if (arg.equals("printOptions")) {
061           printOptions();
062           return true;
063        }
064        if (arg.length() == 0) {
065          printHelp();
066          return true;
067        }
068    
069        // Required format of arg is 'name=value'
070        // Split into 'name' and 'value' strings
071        int split = arg.indexOf('=');
072        if (split == -1) {
073          VM.sysWriteln("  Illegal option specification!\n  \""+arg+
074                      "\" must be specified as a name-value pair in the form of option=value");
075          return false;
076        }
077    
078        String name = arg.substring(0,split);
079        String value = arg.substring(split+1);
080    
081        Option o = getOption(name);
082    
083        if (o == null) return false;
084    
085        switch (o.getType()) {
086          case Option.BOOLEAN_OPTION:
087            if (value.equals("true")) {
088              ((BooleanOption)o).setValue(true);
089              return true;
090            } else if (value.equals("false")) {
091              ((BooleanOption)o).setValue(false);
092              return true;
093            }
094            return false;
095          case Option.INT_OPTION:
096            int ival = CommandLineArgs.primitiveParseInt(value);
097            ((IntOption)o).setValue(ival);
098            return true;
099          case Option.ADDRESS_OPTION:
100            ival = CommandLineArgs.primitiveParseInt(value);
101            ((AddressOption)o).setValue(ival);
102            return true;
103          case Option.FLOAT_OPTION:
104            float fval = CommandLineArgs.primitiveParseFloat(value);
105            ((FloatOption)o).setValue(fval);
106            return true;
107          case Option.STRING_OPTION:
108            ((StringOption)o).setValue(value);
109            return true;
110          case Option.ENUM_OPTION:
111            ((EnumOption)o).setValue(value);
112            return true;
113          case Option.PAGES_OPTION:
114            long pval = CommandLineArgs.parseMemorySize(o.getName(), name, "b", 1, arg, value);
115            if (pval < 0) return false;
116            ((PagesOption)o).setBytes(Extent.fromIntSignExtend((int)pval));
117            return true;
118          case Option.MICROSECONDS_OPTION:
119            int mval = CommandLineArgs.primitiveParseInt(value);
120            ((MicrosecondsOption)o).setMicroseconds(mval);
121            return true;
122        }
123    
124        // None of the above tests matched, so this wasn't an option
125        return false;
126      }
127    
128      /**
129       * Print a short description of every option
130       */
131      public void printHelp() {
132    
133        VM.sysWriteln("Commands");
134        VM.sysWrite(prefix);VM.sysWriteln("[:help]\t\t\tPrint brief description of arguments");
135        VM.sysWrite(prefix);VM.sysWriteln(":printOptions\t\tPrint the current values of options");
136        VM.sysWriteln();
137    
138        //Begin generated help messages
139        VM.sysWrite("Boolean Options (");
140        VM.sysWrite(prefix);VM.sysWrite(":<option>=true or ");
141        VM.sysWrite(prefix);VM.sysWriteln(":<option>=false)");
142        VM.sysWriteln("Option                                 Description");
143    
144        Option o = getFirst();
145        while (o != null) {
146          if (o.getType() == Option.BOOLEAN_OPTION) {
147            String key = o.getKey();
148            VM.sysWrite(key);
149            for (int c = key.length(); c<39;c++) {
150              VM.sysWrite(" ");
151            }
152            VM.sysWriteln(o.getDescription());
153          }
154          o = o.getNext();
155        }
156    
157        VM.sysWrite("\nValue Options (");VM.sysWrite(prefix);VM.sysWriteln(":<option>=<value>)");
158        VM.sysWriteln("Option                         Type    Description");
159    
160        o = getFirst();
161        while (o != null) {
162          if (o.getType() != Option.BOOLEAN_OPTION &&
163              o.getType() != Option.ENUM_OPTION) {
164            String key = o.getKey();
165            VM.sysWrite(key);
166            for (int c = key.length(); c<31;c++) {
167              VM.sysWrite(" ");
168            }
169            switch (o.getType()) {
170              case Option.INT_OPTION:          VM.sysWrite("int     "); break;
171              case Option.ADDRESS_OPTION:      VM.sysWrite("address "); break;
172              case Option.FLOAT_OPTION:        VM.sysWrite("float   "); break;
173              case Option.MICROSECONDS_OPTION: VM.sysWrite("usec    "); break;
174              case Option.PAGES_OPTION:        VM.sysWrite("bytes   "); break;
175              case Option.STRING_OPTION:       VM.sysWrite("string  "); break;
176            }
177            VM.sysWriteln(o.getDescription());
178          }
179          o = o.getNext();
180        }
181    
182        VM.sysWriteln("\nSelection Options (set option to one of an enumeration of possible values)");
183    
184        o = getFirst();
185        while (o != null) {
186          if (o.getType() == Option.ENUM_OPTION) {
187            String key = o.getKey();
188            VM.sysWrite(key);
189            for (int c = key.length(); c<31;c++) {
190              VM.sysWrite(" ");
191            }
192            VM.sysWriteln(o.getDescription());
193            VM.sysWrite("    { ");
194            boolean first = true;
195            for (String val : ((EnumOption)o).getValues()) {
196              VM.sysWrite(first ? "" : ", ");
197              VM.sysWrite(val);
198              first = false;
199            }
200            VM.sysWriteln(" }");
201          }
202          o = o.getNext();
203        }
204    
205        VM.sysExit(VM.EXIT_STATUS_PRINTED_HELP_MESSAGE);
206      }
207    
208      /**
209       * Print out the option values
210       */
211      public void printOptions() {
212        VM.sysWriteln("Current value of GC options");
213    
214        Option o = getFirst();
215        while (o != null) {
216          if (o.getType() == Option.BOOLEAN_OPTION) {
217            String key = o.getKey();
218            VM.sysWrite("\t");
219            VM.sysWrite(key);
220            for (int c = key.length(); c<31;c++) {
221              VM.sysWrite(" ");
222            }
223            VM.sysWrite(" = ");
224            logValue(o, false);
225            VM.sysWriteln();
226          }
227          o = o.getNext();
228        }
229    
230        o = getFirst();
231        while (o != null) {
232          if (o.getType() != Option.BOOLEAN_OPTION &&
233              o.getType() != Option.ENUM_OPTION) {
234            String key = o.getKey();
235            VM.sysWrite("\t");
236            VM.sysWrite(key);
237            for (int c = key.length(); c<31;c++) {
238              VM.sysWrite(" ");
239            }
240            VM.sysWrite(" = ");
241            logValue(o, false);
242            VM.sysWriteln();
243          }
244          o = o.getNext();
245        }
246    
247        o = getFirst();
248        while (o != null) {
249          if (o.getType() == Option.ENUM_OPTION) {
250            String key = o.getKey();
251            VM.sysWrite("\t");
252            VM.sysWrite(key);
253            for (int c = key.length(); c<31;c++) {
254              VM.sysWrite(" ");
255            }
256            VM.sysWrite(" = ");
257            logValue(o, false);
258            VM.sysWriteln();
259          }
260          o = o.getNext();
261        }
262      }
263    
264      @Override
265      protected void logValue(Option o, boolean forXml) {
266        switch (o.getType()) {
267        case Option.BOOLEAN_OPTION:
268          VM.sysWrite(((BooleanOption) o).getValue() ? "true" : "false");
269          break;
270        case Option.INT_OPTION:
271          VM.sysWrite(((IntOption) o).getValue());
272          break;
273        case Option.ADDRESS_OPTION:
274          VM.sysWrite(((AddressOption) o).getValue());
275          break;
276        case Option.FLOAT_OPTION:
277          VM.sysWrite(((FloatOption) o).getValue());
278          break;
279        case Option.MICROSECONDS_OPTION:
280          VM.sysWrite(((MicrosecondsOption) o).getMicroseconds());
281          VM.sysWrite(" usec");
282          break;
283        case Option.PAGES_OPTION:
284          VM.sysWrite(((PagesOption) o).getBytes());
285          VM.sysWrite(" bytes");
286          break;
287        case Option.STRING_OPTION:
288          VM.sysWrite(((StringOption) o).getValue());
289          break;
290        case Option.ENUM_OPTION:
291          VM.sysWrite(((EnumOption) o).getValueString());
292          break;
293        }
294      }
295    
296      @Override
297      protected void logString(String s) {
298        VM.sysWrite(s);
299      }
300    
301      @Override
302      protected void logNewLine() {
303        VM.sysWriteln();
304      }
305    
306      @Override
307      protected String computeKey(String name) {
308        int space = name.indexOf(' ');
309        if (space < 0) return name.toLowerCase();
310    
311        String word = name.substring(0, space);
312        String key = word.toLowerCase();
313    
314        do {
315          int old = space+1;
316          space = name.indexOf(' ', old);
317          if (space < 0) {
318            key += name.substring(old);
319            return key;
320          }
321          key += name.substring(old, space);
322        } while (true);
323      }
324    
325      @Override
326      protected void warn(Option o, String message) {
327        VM.sysWriteln("WARNING: Option '" + o.getKey() + "' : " + message);
328      }
329    
330      @Override
331      protected void fail(Option o, String message) {
332        VM.sysFail("ERROR: Option '" + o.getKey() + "' : " + message);
333      }
334    
335      @Override
336      @Uninterruptible
337      protected int bytesToPages(Extent bytes) {
338        return bytes.plus(Constants.BYTES_IN_PAGE-1).toWord().rshl(Constants.LOG_BYTES_IN_PAGE).toInt();
339      }
340    
341      @Override
342      @Uninterruptible
343      protected Extent pagesToBytes(int pages) {
344        return Word.fromIntZeroExtend(pages).lsh(Constants.LOG_BYTES_IN_PAGE).toExtent();
345      }
346    }