OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [gnu/] [classpath/] [tools/] [getopt/] [Parser.java] - Blame information for rev 779

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 779 jeremybenn
/* Parser.java - parse command line options
2
 Copyright (C) 2006, 2008 Free Software Foundation, Inc.
3
 
4
 This file is part of GNU Classpath.
5
 
6
 GNU Classpath is free software; you can redistribute it and/or modify
7
 it under the terms of the GNU General Public License as published by
8
 the Free Software Foundation; either version 2, or (at your option)
9
 any later version.
10
 
11
 GNU Classpath is distributed in the hope that it will be useful, but
12
 WITHOUT ANY WARRANTY; without even the implied warranty of
13
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 General Public License for more details.
15
 
16
 You should have received a copy of the GNU General Public License
17
 along with GNU Classpath; see the file COPYING.  If not, write to the
18
 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
 02110-1301 USA.
20
 
21
 Linking this library statically or dynamically with other modules is
22
 making a combined work based on this library.  Thus, the terms and
23
 conditions of the GNU General Public License cover the whole
24
 combination.
25
 
26
 As a special exception, the copyright holders of this library give you
27
 permission to link this library with independent modules to produce an
28
 executable, regardless of the license terms of these independent
29
 modules, and to copy and distribute the resulting executable under
30
 terms of your choice, provided that you also meet, for each linked
31
 independent module, the terms and conditions of the license of that
32
 module.  An independent module is a module which is not derived from
33
 or based on this library.  If you modify this library, you may extend
34
 this exception to your version of the library, but you are not
35
 obligated to do so.  If you do not wish to do so, delete this
36
 exception statement from your version. */
37
 
38
 
39
package gnu.classpath.tools.getopt;
40
 
41
import java.io.PrintStream;
42
import java.text.BreakIterator;
43
import java.text.MessageFormat;
44
import java.util.ArrayList;
45
import java.util.Iterator;
46
import java.util.Locale;
47
 
48
/**
49
 * An instance of this class is used to parse command-line options. It does "GNU
50
 * style" argument recognition and also automatically handles "--help" and
51
 * "--version" processing. It can also be put in "long option only" mode. In
52
 * this mode long options are recognized with a single dash (as well as a double
53
 * dash) and strings of options like "-abc" are never parsed as a collection of
54
 * short options.
55
 */
56
public class Parser
57
{
58
  /** The maximum right column position. */
59
  public static final int MAX_LINE_LENGTH = 80;
60
 
61
  private String programName;
62
 
63
  private String headerText;
64
 
65
  private String footerText;
66
 
67
  private boolean longOnly;
68
 
69
  // All of the options.  This is null initially; users must call
70
  // requireOptions before access.
71
  private ArrayList options;
72
 
73
  private ArrayList optionGroups = new ArrayList();
74
 
75
  private OptionGroup defaultGroup = new OptionGroup();
76
 
77
  private OptionGroup finalGroup;
78
 
79
  // These are used while parsing.
80
  private int currentIndex;
81
 
82
  private String[] args;
83
 
84
  /**
85
   * Create a new parser. The program name is used when printing error messages.
86
   * The version string is printed verbatim in response to "--version".
87
   *
88
   * @param programName the name of the program
89
   * @param versionString the program's version information
90
   */
91
  public Parser(String programName, String versionString)
92
  {
93
    this(programName, versionString, false);
94
  }
95
 
96
  /**
97
   * Print a designated text to a {@link PrintStream}, eventually wrapping the
98
   * lines of text so as to ensure that the width of each line does not overflow
99
   * {@link #MAX_LINE_LENGTH} columns. The line-wrapping is done with a
100
   * {@link BreakIterator} using the default {@link Locale}.
101
   * <p>
102
   * The text to print may contain <code>\n</code> characters. This method will
103
   * force a line-break for each such character.
104
   *
105
   * @param out the {@link PrintStream} destination of the formatted text.
106
   * @param text the text to print.
107
   * @see Parser#MAX_LINE_LENGTH
108
   */
109
  protected static void formatText(PrintStream out, String text)
110
  {
111
    formatText(out, text, Locale.getDefault());
112
  }
113
 
114
  /**
115
   * Similar to the method with the same name and two arguments, except that the
116
   * caller MUST specify a non-null {@link Locale} instance.
117
   * <p>
118
   * Print a designated text to a {@link PrintStream}, eventually wrapping the
119
   * lines of text so as to ensure that the width of each line does not overflow
120
   * {@link #MAX_LINE_LENGTH} columns. The line-wrapping is done with a
121
   * {@link BreakIterator} using the designated {@link Locale}.
122
   * <p>
123
   * The text to print may contain <code>\n</code> characters. This method will
124
   * force a line-break for each such character.
125
   *
126
   * @param out the {@link PrintStream} destination of the formatted text.
127
   * @param text the text to print.
128
   * @param aLocale the {@link Locale} instance to use when constructing the
129
   *          {@link BreakIterator}.
130
   * @see Parser#MAX_LINE_LENGTH
131
   */
132
  protected static void formatText(PrintStream out, String text, Locale aLocale)
133
  {
134
    BreakIterator bit = BreakIterator.getLineInstance(aLocale);
135
    String[] lines = text.split("\n"); //$NON-NLS-1$
136
    for (int i = 0; i < lines.length; i++)
137
      {
138
        text = lines[i];
139
        bit.setText(text);
140
        int length = 0;
141
        int finish;
142
        int start = bit.first();
143
        while ((finish = bit.next()) != BreakIterator.DONE)
144
          {
145
            String word = text.substring(start, finish);
146
            length += word.length();
147
            if (length >= MAX_LINE_LENGTH)
148
              {
149
                out.println();
150
                length = word.length();
151
              }
152
            out.print(word);
153
            start = finish;
154
          }
155
        out.println();
156
      }
157
  }
158
 
159
  /**
160
   * Create a new parser. The program name is used when printing error messages.
161
   * The version string is printed verbatim in response to "--version".
162
   *
163
   * @param programName the name of the program
164
   * @param versionString the program's version information
165
   * @param longOnly true if the parser should work in long-option-only mode
166
   */
167
  public Parser(String programName, final String versionString, boolean longOnly)
168
  {
169
    this.programName = programName;
170
    this.longOnly = longOnly;
171
 
172
    // Put standard options in their own section near the end.
173
    finalGroup = new OptionGroup(Messages.getString("Parser.StdOptions")); //$NON-NLS-1$
174
    finalGroup.add(new Option("help", Messages.getString("Parser.PrintHelp")) //$NON-NLS-1$ //$NON-NLS-2$
175
    {
176
      public void parsed(String argument) throws OptionException
177
      {
178
        printHelp(System.out);
179
        System.exit(0);
180
      }
181
    });
182
    finalGroup.add(new Option("version", Messages.getString("Parser.PrintVersion")) //$NON-NLS-1$ //$NON-NLS-2$
183
    {
184
      public void parsed(String argument) throws OptionException
185
      {
186
        System.out.println(versionString);
187
        System.exit(0);
188
      }
189
    });
190
    add(finalGroup);
191
 
192
    add(defaultGroup);
193
  }
194
 
195
  /**
196
   * Set the header text that is printed by --help.
197
   *
198
   * @param headerText the header text
199
   */
200
  public synchronized void setHeader(String headerText)
201
  {
202
    this.headerText = headerText;
203
  }
204
 
205
  /**
206
   * Set the footer text that is printed by --help.
207
   *
208
   * @param footerText the footer text
209
   */
210
  public synchronized void setFooter(String footerText)
211
  {
212
    this.footerText = footerText;
213
  }
214
 
215
  /**
216
   * Add an option to this parser. The option is added to the default option
217
   * group; this affects where it is placed in the help output.
218
   *
219
   * @param opt the option
220
   */
221
  public synchronized void add(Option opt)
222
  {
223
    defaultGroup.add(opt);
224
  }
225
 
226
  /**
227
   * This is like {@link #add(Option)}, but adds the option to the "final"
228
   * group.  This should be used sparingly, if at all; it is intended for
229
   * other very generic options like --help or --version.
230
   * @param opt the option to add
231
   */
232
  protected synchronized void addFinal(Option opt)
233
  {
234
    finalGroup.add(opt);
235
  }
236
 
237
  /**
238
   * Add an option group to this parser. All the options in this group will be
239
   * recognized by the parser.
240
   *
241
   * @param group the option group
242
   */
243
  public synchronized void add(OptionGroup group)
244
  {
245
    // This ensures that the final group always appears at the end
246
    // of the options.
247
    if (optionGroups.isEmpty())
248
      optionGroups.add(group);
249
    else
250
      optionGroups.add(optionGroups.size() - 1, group);
251
  }
252
 
253
  // Make sure the 'options' field is properly initialized.
254
  private void requireOptions()
255
  {
256
    if (options != null)
257
      return;
258
    options = new ArrayList();
259
    Iterator it = optionGroups.iterator();
260
    while (it.hasNext())
261
      {
262
        OptionGroup group = (OptionGroup) it.next();
263
        options.addAll(group.options);
264
      }
265
  }
266
 
267
  public void printHelp()
268
  {
269
    this.printHelp(System.out);
270
  }
271
 
272
  synchronized void printHelp(PrintStream out)
273
  {
274
    requireOptions();
275
 
276
    if (headerText != null)
277
      {
278
        formatText(out, headerText);
279
        out.println();
280
      }
281
 
282
    Iterator it = optionGroups.iterator();
283
    while (it.hasNext())
284
      {
285
        OptionGroup group = (OptionGroup) it.next();
286
        // An option group might be empty, in which case we don't
287
        // want to print it..
288
        if (! group.options.isEmpty())
289
          {
290
            group.printHelp(out, longOnly);
291
            out.println();
292
          }
293
      }
294
 
295
    if (footerText != null)
296
      formatText(out, footerText);
297
  }
298
 
299
  /**
300
   * This method can be overridden by subclassses to provide some option
301
   * validation.  It is called by the parser after all options have been
302
   * parsed.  If an option validation problem is encountered, this should
303
   * throw an {@link OptionException} whose message should be shown to
304
   * the user.
305
   * <p>
306
   * It is better to do validation here than after {@link #parse(String[])}
307
   * returns, because the parser will print a message referring the
308
   * user to the <code>--help</code> option.
309
   * <p>
310
   * The base implementation does nothing.
311
   *
312
   * @throws OptionException the error encountered
313
   */
314
  protected void validate() throws OptionException
315
  {
316
    // Base implementation does nothing.
317
  }
318
 
319
  private String getArgument(String request) throws OptionException
320
  {
321
    ++currentIndex;
322
    if (currentIndex >= args.length)
323
      {
324
        String message
325
          = MessageFormat.format(Messages.getString("Parser.ArgReqd"), //$NON-NLS-1$
326
                                 new Object[] { request });
327
        throw new OptionException(request);
328
      }
329
    return args[currentIndex];
330
  }
331
 
332
  private void handleLongOption(String real, int index) throws OptionException
333
  {
334
    String option = real.substring(index);
335
    String justName = option;
336
    int eq = option.indexOf('=');
337
    if (eq != -1)
338
      justName = option.substring(0, eq);
339
    boolean isPlainShort = justName.length() == 1;
340
    char shortName = justName.charAt(0);
341
    Option found = null;
342
    for (int i = options.size() - 1; i >= 0; --i)
343
      {
344
        Option opt = (Option) options.get(i);
345
        if (justName.equals(opt.getLongName()))
346
          {
347
            found = opt;
348
            break;
349
          }
350
        if ((isPlainShort || opt.isJoined())
351
            && opt.getShortName() == shortName)
352
          {
353
            if (! isPlainShort)
354
              {
355
                // The rest of the option string is the argument.
356
                eq = 0;
357
              }
358
            found = opt;
359
            break;
360
          }
361
      }
362
    if (found == null)
363
      {
364
        String msg = MessageFormat.format(Messages.getString("Parser.Unrecognized"), //$NON-NLS-1$
365
                                          new Object[] { real });
366
        throw new OptionException(msg);
367
      }
368
    String argument = null;
369
    if (found.getTakesArgument())
370
      {
371
        if (eq == -1)
372
          argument = getArgument(real);
373
        else
374
          argument = option.substring(eq + 1);
375
      }
376
    else if (eq != - 1)
377
      {
378
        String msg
379
          = MessageFormat.format(Messages.getString("Parser.NoArg"), //$NON-NLS-1$
380
                                 new Object[] { real.substring(0, eq + index) });
381
        throw new OptionException(msg);
382
      }
383
    found.parsed(argument);
384
  }
385
 
386
  private void handleShortOptions(String option) throws OptionException
387
  {
388
    for (int charIndex = 1; charIndex < option.length(); ++charIndex)
389
      {
390
        char optChar = option.charAt(charIndex);
391
        Option found = null;
392
        for (int i = options.size() - 1; i >= 0; --i)
393
          {
394
            Option opt = (Option) options.get(i);
395
            if (optChar == opt.getShortName())
396
              {
397
                found = opt;
398
                break;
399
              }
400
          }
401
        if (found == null)
402
          {
403
            String msg = MessageFormat.format(Messages.getString("Parser.UnrecDash"), //$NON-NLS-1$
404
                                              new Object[] { "" + optChar }); //$NON-NLS-1$
405
            throw new OptionException(msg);
406
          }
407
        String argument = null;
408
        if (found.getTakesArgument())
409
          {
410
            // If this is a joined short option, and there are more
411
            // characters left in this argument, use those as the
412
            // argument.
413
            if (found.isJoined() && charIndex + 1 < option.length())
414
              {
415
                argument = option.substring(charIndex + 1);
416
                charIndex = option.length();
417
              }
418
            else
419
              argument = getArgument("-" + optChar); //$NON-NLS-1$
420
          }
421
        found.parsed(argument);
422
      }
423
  }
424
 
425
  /**
426
   * Parse a command line. Any files which are found will be passed to the file
427
   * argument callback. This method will exit on error or when --help or
428
   * --version is specified.
429
   *
430
   * @param inArgs the command-line arguments
431
   * @param files the file argument callback
432
   */
433
  public synchronized void parse(String[] inArgs, FileArgumentCallback files)
434
  {
435
    requireOptions();
436
    try
437
      {
438
        args = inArgs;
439
        for (currentIndex = 0; currentIndex < args.length; ++currentIndex)
440
          {
441
            if (args[currentIndex].length() == 0
442
                || args[currentIndex].charAt(0) != '-'
443
                || "-".equals(args[currentIndex])) //$NON-NLS-1$
444
              {
445
                files.notifyFile(args[currentIndex]);
446
                continue;
447
              }
448
            if ("--".equals(args[currentIndex])) //$NON-NLS-1$
449
              break;
450
            if (args[currentIndex].charAt(1) == '-')
451
              handleLongOption(args[currentIndex], 2);
452
            else if (longOnly)
453
              handleLongOption(args[currentIndex], 1);
454
            else
455
              handleShortOptions(args[currentIndex]);
456
          }
457
        // Add remaining arguments to leftovers.
458
        for (++currentIndex; currentIndex < args.length; ++currentIndex)
459
          files.notifyFile(args[currentIndex]);
460
        // See if something went wrong.
461
        validate();
462
      }
463
    catch (OptionException err)
464
      {
465
        System.err.println(programName + ": " + err.getMessage()); //$NON-NLS-1$
466
        String fmt;
467
        if (longOnly)
468
          fmt = Messages.getString("Parser.TryHelpShort"); //$NON-NLS-1$
469
        else
470
          fmt = Messages.getString("Parser.TryHelpLong"); //$NON-NLS-1$
471
        String msg = MessageFormat.format(fmt, new Object[] { programName });
472
        System.err.println(programName + ": " + msg); //$NON-NLS-1$
473
        System.exit(1);
474
      }
475
  }
476
 
477
  /**
478
   * Parse a command line. Any files which are found will be returned. This
479
   * method will exit on error or when --help or --version is specified.
480
   *
481
   * @param inArgs the command-line arguments
482
   */
483
  public String[] parse(String[] inArgs)
484
  {
485
    final ArrayList fileResult = new ArrayList();
486
    parse(inArgs, new FileArgumentCallback()
487
    {
488
      public void notifyFile(String fileArgument)
489
      {
490
        fileResult.add(fileArgument);
491
      }
492
    });
493
    return (String[]) fileResult.toArray(new String[0]);
494
  }
495
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.