]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/tools/misc/src/com/ibm/icu/dev/tool/UOption.java
Clean up imports.
[Dictionary.git] / jars / icu4j-52_1 / tools / misc / src / com / ibm / icu / dev / tool / UOption.java
1 /*
2 **********************************************************************
3 * Copyright (c) 2002-2004, International Business Machines
4 * Corporation and others.  All Rights Reserved.
5 **********************************************************************
6 * Author: Alan Liu
7 * Created: November 15 2002
8 * Since: ICU 2.4
9 **********************************************************************
10 */
11 package com.ibm.icu.dev.tool;
12
13 /**
14  * A command-line option.  A UOption specifies the name of an option
15  * and whether or not it takes an argument.  It is a mutable object
16  * that later contains the option argument, if any, and a boolean
17  * flag stating whether the option was seen or not.
18  *
19  * The static method parseArgs() takes an array of command-line
20  * arguments and an array of UOptions and parses the command-line
21  * arguments.
22  *
23  * This deliberately resembles the icu4c file uoption.[ch].
24  */
25 public class UOption {
26
27     // Deliberated public data members
28     public String  longName;
29     public String  value;
30     public Fn      optionFn;
31     public Object  context;
32     public char    shortName;
33     public int     hasArg;
34     public boolean doesOccur;
35
36     // Values of hasArg
37     public static final int NO_ARG       = 0;
38     public static final int REQUIRES_ARG = 1;
39     public static final int OPTIONAL_ARG = 2;
40
41     // Analog of UOptionFn.  We don't pass in the context because the
42     // functor can get it from the UOption.
43     public interface Fn {
44         int handle(UOption option);
45     }
46
47     /**
48      * Create a UOption with the given attributes.
49      */
50     public static UOption create(String aLongName,
51                                 char aShortName,
52                                 int hasArgument) {
53         return new UOption(aLongName, aShortName, hasArgument);
54     }
55
56     /**
57      * Create a UOption with the given attributes.
58      * Synonym for create(), for C compatibility.
59      */
60     public static UOption DEF(String aLongName,
61                               char aShortName,
62                               int hasArgument) {
63         return create(aLongName, aShortName, hasArgument);
64     }
65
66     // Standard canned options.  These create a new object when
67     // called.  Since the UOption object is mutable, we cannot use
68     // static final instances.
69     public static UOption HELP_H()             { return create("help", 'h', NO_ARG); }
70     public static UOption HELP_QUESTION_MARK() { return create("help", '?', NO_ARG); }
71     public static UOption VERBOSE()            { return create("verbose", 'v', NO_ARG); }
72     public static UOption QUIET()              { return create("quiet", 'q', NO_ARG); }
73     public static UOption VERSION()            { return create("version", 'V', NO_ARG); }
74     public static UOption COPYRIGHT()          { return create("copyright", 'c', NO_ARG); }
75
76     public static UOption DESTDIR()            { return create("destdir", 'd', REQUIRES_ARG); }
77     public static UOption SOURCEDIR()          { return create("sourcedir", 's', REQUIRES_ARG); }
78     public static UOption ENCODING()           { return create("encoding", 'e', REQUIRES_ARG); }
79     public static UOption ICUDATADIR()         { return create("icudatadir", 'i', REQUIRES_ARG); }
80     public static UOption PACKAGE_NAME()       { return create("package-name", 'p', REQUIRES_ARG); }
81     public static UOption BUNDLE_NAME()        { return create("bundle-name", 'b', REQUIRES_ARG); }
82
83     /**
84      * Java Command line argument parser.
85      *
86      * This function takes the argv[] command line and a description of
87      * the program's options in form of an array of UOption structures.
88      * Each UOption defines a long and a short name (a string and a character)
89      * for options like "--foo" and "-f".
90      *
91      * Each option is marked with whether it does not take an argument,
92      * requires one, or optionally takes one. The argument may follow in
93      * the same argv[] entry for short options, or it may always follow
94      * in the next argv[] entry.
95      *
96      * An argument is in the next argv[] entry for both long and short name
97      * options, except it is taken from directly behind the short name in
98      * its own argv[] entry if there are characters following the option letter.
99      * An argument in its own argv[] entry must not begin with a '-'
100      * unless it is only the '-' itself. There is no restriction of the
101      * argument format if it is part of the short name options's argv[] entry.
102      *
103      * The argument is stored in the value field of the corresponding
104      * UOption entry, and the doesOccur field is set to 1 if the option
105      * is found at all.
106      *
107      * Short name options without arguments can be collapsed into a single
108      * argv[] entry. After an option letter takes an argument, following
109      * letters will be taken as its argument.
110      *
111      * If the same option is found several times, then the last
112      * argument value will be stored in the value field.
113      *
114      * For each option, a function can be called. This could be used
115      * for options that occur multiple times and all arguments are to
116      * be collected.
117      *
118      * All options are removed from the argv[] array itself. If the parser
119      * is successful, then it returns the number of remaining non-option
120      * strings.  (Unlike C, the Java argv[] array does NOT contain
121      * the program name in argv[0].)
122      *
123      * An option "--" ends option processing; everything after this
124      * remains in the argv[] array.
125      *
126      * An option string "-" alone is treated as a non-option.
127      *
128      * If an option is not recognized or an argument missing, then
129      * the parser returns with the negative index of the argv[] entry
130      * where the error was detected.
131      *
132      * @param argv this parameter is modified
133      * @param start the first argument in argv[] to examine.  Must be
134      * 0..argv.length-1.  Arguments from 0..start-1 are ignored.
135      * @param options this parameter is modified
136      * @return the number of unprocessed arguments in argv[], including
137      * arguments 0..start-1.
138      */
139     public static int parseArgs(String argv[], int start, UOption options[]) {
140         String arg;
141         int i=start, remaining=start;
142         char c;
143         boolean stopOptions=false;
144
145         while(i<argv.length) {
146             arg=argv[i];
147             if(!stopOptions && arg.length()>1 && arg.charAt(0)=='-') {
148                 /* process an option */
149                 c=arg.charAt(1);
150                 UOption option=null;
151                 arg=arg.substring(2);
152                 if(c=='-') {
153                     /* process a long option */
154                     if(arg.length()==0) {
155                         /* stop processing options after "--" */
156                         stopOptions=true;
157                     } else {
158                         /* search for the option string */
159                         int j;
160                         for(j=0; j<options.length; ++j) {
161                             if(options[j].longName != null && arg.equals(options[j].longName)) {
162                                 option=options[j];
163                                 break;
164                             }
165                         }
166                         if(option==null) {
167                             /* no option matches */
168                             syntaxError("Unknown option " + argv[i]);
169                         }
170                         option.doesOccur=true;
171
172                         if(option.hasArg!=NO_ARG) {
173                             /* parse the argument for the option, if any */
174                             if(i+1<argv.length && !(argv[i+1].length()>1 && argv[i+1].charAt(0)=='-')) {
175                                 /* argument in the next argv[], and there is not an option in there */
176                                 option.value=argv[++i];
177                             } else if(option.hasArg==REQUIRES_ARG) {
178                                 /* there is no argument, but one is required: return with error */
179                                 syntaxError("Option " + argv[i] + " lacks required argument");
180                             }
181                         }
182                     }
183                 } else {
184                     /* process one or more short options */
185                     for (;;) {
186                         /* search for the option letter */
187                         int j;
188                         for(j=0; j<options.length; ++j) {
189                             if(c==options[j].shortName) {
190                                 option=options[j];
191                                 break;
192                             }
193                         }
194                         if(option==null) {
195                             /* no option matches */
196                             syntaxError("Unknown option '" + c + "' in " + argv[i]);
197                         }
198                         option.doesOccur=true;
199
200                         if(option.hasArg!=NO_ARG) {
201                             /* parse the argument for the option, if any */
202                             if(arg.length()!=0) {
203                                 /* argument following in the same argv[] */
204                                 option.value=arg;
205                                 /* do not process the rest of this arg as option letters */
206                                 break;
207                             } else if(i+1<argv.length && !(argv[i+1].length()>1 && argv[i+1].charAt(0)=='-')) {
208                                 /* argument in the next argv[], and there is not an option in there */
209                                 option.value=argv[++i];
210                                 /* this break is redundant because we know that *arg==0 */
211                                 break;
212                             } else if(option.hasArg==REQUIRES_ARG) {
213                                 /* there is no argument, but one is required: return with error */
214                                 syntaxError("Option -" + c + " lacks required argument");
215                             }
216                         }
217
218                         /* get the next option letter */
219                         option=null;
220                         if (arg.length()==0) break;
221                         c=arg.charAt(0);
222                         arg=arg.substring(1);
223                     }
224                 }
225
226                 if(option!=null && option.optionFn!=null && option.optionFn.handle(option)<0) {
227                     /* the option function was called and returned an error */
228                     syntaxError("Option handler failed for " + argv[i]);
229                 }
230
231                 /* go to next argv[] */
232                 ++i;
233             } else {
234                 /* move a non-option up in argv[] */
235                 argv[remaining++]=arg;
236                 ++i;
237             }
238         }
239         return remaining;
240     }
241
242     /**
243      * Allows the default to be set in an option list.
244      * @param s
245      * @return this
246      */public UOption setDefault(String s) {
247         value = s;
248         return this;
249     }
250
251     /**
252      * Convenient method.
253      */
254     public static int parseArgs(String argv[], UOption options[]) {
255         return parseArgs(argv, 0, options);
256     }
257
258     /**
259      * Constructor.
260      */
261     private UOption(String aLongName,
262                     char aShortName,
263                     int hasArgument) {
264         longName = aLongName;
265         shortName = aShortName;
266         hasArg = hasArgument;
267     }
268
269     /**
270      * Throw an exception indicating a syntax error.
271      */
272     private static void syntaxError(String message) {
273         throw new IllegalArgumentException("Error in argument list: " + message);
274     }
275 }