001: /*****************************************************************************
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025:
026: * The Original Software is the CVS Client Library.
027: * The Initial Developer of the Original Software is Robert Greig.
028: * Portions created by Robert Greig are Copyright (C) 2000.
029: * All Rights Reserved.
030: *
031: * If you wish your version of this file to be governed by only the CDDL
032: * or only the GPL Version 2, indicate your decision by adding
033: * "[Contributor] elects to include this software in this distribution
034: * under the [CDDL or GPL Version 2] license." If you do not indicate a
035: * single choice of license, a recipient has the option to distribute
036: * your version of this file under either the CDDL, the GPL Version 2 or
037: * to extend the choice of license to its licensees as provided above.
038: * However, if you add GPL Version 2 code and therefore, elected the GPL
039: * Version 2 license, then the option applies only if the new code is
040: * made subject to such option by the copyright holder.
041:
042: * Contributor(s): Robert Greig.
043: *****************************************************************************/package org.netbeans.lib.cvsclient.commandLine;
044:
045: /**
046: * <h1>Overview</h1>
047: *
048: * GetOpt provides a general means for a Java program to parse command
049: * line arguments in accordance with the standard Unix conventions;
050: * it is analogous to, and based on, getopt(3) for C programs.
051: * (The following documentation is based on the man page for getopt(3).)
052:
053: * <h1>Description</h1>
054: *
055: * GetOpt is a Java class that provides one method, getopt,
056: * and some variables that control behavior of or return additional
057: * information from getopt.
058: * <p>
059: * GetOpt interprets command arguments in accordance with the standard
060: * Unix conventions: option arguments of a command are introduced by "-"
061: * followed by a key character, and a non-option argument terminates
062: * the processing of options. GetOpt's option interpretation is controlled
063: * by its parameter optString, which specifies what characters designate
064: * legal options and which of them require associated values.
065: * <p>
066: * The getopt method returns the next, moving left to right, option letter
067: * in the command line arguments that matches a letter in optString.
068: * optString must contain the option letters the command using getopt
069: * will recognize. For example, getopt("ab") specifies that the command
070: * line should contain no options, only "-a", only "-b", or both "-a" and
071: * "-b" in either order. (The command line can also contain non-option
072: * arguments after any option arguments.) Multiple options per argument
073: * are allowed, e.g., "-ab" for the last case above.
074: * <p>
075: * If a letter in optString is followed by a colon, the option is expected
076: * to have an argument. The argument may or may not be separated by
077: * whitespace from the option letter. For example, getopt("w:") allows
078: * either "-w 80" or "-w80". The variable optArg is set to the option
079: * argument, e.g., "80" in either of the previous examples. Conversion
080: * functions such as Integer.parseInt(), etc., can then be applied to
081: * optArg.
082: * <p>
083: * getopt places in the variable optIndex the index of the next command
084: * line argument to be processed; optIndex is automatically initialized
085: * to 1 before the first call to getopt.
086: * <p>
087: * When all options have been processed (that is, up to the first
088: * non-option argument), getopt returns optEOF (-1). getopt recognizes the
089: * command line argument "--" (i.e., two dashes) to delimit the end of
090: * the options; getopt returns optEOF and skips "--". Subsequent,
091: * non-option arguments can be retrieved using the String array passed to
092: * main(), beginning with argument number optIndex.
093: *
094: * <h1>Diagnostics</h1>
095: *
096: * getopt prints an error message on System.stderr and returns a question
097: * mark ('?') when it encounters an option letter in a command line argument
098: * that is not included in optString. Setting the variable optErr to
099: * false disables this error message.
100:
101: * <h1>Notes</h1>
102: *
103: * The following notes describe GetOpt's behavior in a few interesting
104: * or special cases; these behaviors are consistent with getopt(3)'s
105: * behaviors.
106: * -- A '-' by itself is treated as a non-option argument.
107: * -- If optString is "a:" and the command line arguments are "-a -x",
108: * then "-x" is treated as the argument associated with the "-a".
109: * -- Duplicate command line options are allowed; it is up to user to
110: * deal with them as appropriate.
111: * -- A command line option like "-b-" is considered as the two options
112: * "b" and "-" (so "-" should appear in option string); this differs
113: * from "-b --".
114: * -- Sun and DEC getopt(3)'s differ w.r.t. how "---" is handled.
115: * Sun treats "---" (or anything starting with "--") the same as "--"
116: * DEC treats "---" as two separate "-" options
117: * (so "-" should appear in option string).
118: * Java GetOpt follows the DEC convention.
119: * -- An option `letter' can be a letter, number, or most special character.
120: * Like getopt(3), GetOpt disallows a colon as an option letter.
121: *
122: * @author Anonymous
123: *****************************************************************************/
124: public class GetOpt {
125:
126: private String[] theArgs = null;
127: private int argCount = 0;
128: private String optString = null;
129:
130: public GetOpt(String[] args, String opts) {
131: theArgs = args;
132: argCount = theArgs.length;
133: optString = opts;
134: }
135:
136: // user can toggle this to control printing of error messages
137: public boolean optErr = false;
138:
139: public int processArg(String arg, int n) {
140: int value;
141: try {
142: value = Integer.parseInt(arg);
143: } catch (NumberFormatException e) {
144: if (optErr)
145: System.err.println("processArg cannot process " + arg //NOI18N
146: + " as an integer"); //NOI18N
147: return n;
148: }
149: return value;
150: }
151:
152: public int tryArg(int k, int n) {
153: int value;
154: try {
155: value = processArg(theArgs[k], n);
156: } catch (ArrayIndexOutOfBoundsException e) {
157: if (optErr)
158: System.err.println("tryArg: no theArgs[" + k + "]"); //NOI18N
159: return n;
160: }
161: return value;
162: }
163:
164: public long processArg(String arg, long n) {
165: long value;
166: try {
167: value = Long.parseLong(arg);
168: } catch (NumberFormatException e) {
169: if (optErr)
170: System.err.println("processArg cannot process " + arg //NOI18N
171: + " as a long"); //NOI18N
172: return n;
173: }
174: return value;
175: }
176:
177: public long tryArg(int k, long n) {
178: long value;
179: try {
180: value = processArg(theArgs[k], n);
181: } catch (ArrayIndexOutOfBoundsException e) {
182: if (optErr)
183: System.err.println("tryArg: no theArgs[" + k + "]"); //NOI18N
184: return n;
185: }
186: return value;
187: }
188:
189: public double processArg(String arg, double d) {
190: double value;
191: try {
192: value = Double.valueOf(arg).doubleValue();
193: } catch (NumberFormatException e) {
194: if (optErr)
195: System.err.println("processArg cannot process " + arg //NOI18N
196: + " as a double"); //NOI18N
197: return d;
198: }
199: return value;
200: }
201:
202: public double tryArg(int k, double d) {
203: double value;
204: try {
205: value = processArg(theArgs[k], d);
206: } catch (ArrayIndexOutOfBoundsException e) {
207: if (optErr)
208: System.err.println("tryArg: no theArgs[" + k + "]"); //NOI18N
209: return d;
210: }
211: return value;
212: }
213:
214: public float processArg(String arg, float f) {
215: float value;
216: try {
217: value = Float.valueOf(arg).floatValue();
218: } catch (NumberFormatException e) {
219: if (optErr)
220: System.err.println("processArg cannot process " + arg //NOI18N
221: + " as a float"); //NOI18N
222: return f;
223: }
224: return value;
225: }
226:
227: public float tryArg(int k, float f) {
228: float value;
229: try {
230: value = processArg(theArgs[k], f);
231: } catch (ArrayIndexOutOfBoundsException e) {
232: if (optErr)
233: System.err.println("tryArg: no theArgs[" + k + "]"); //NOI18N
234: return f;
235: }
236: return value;
237: }
238:
239: public boolean processArg(String arg, boolean b) {
240: // `true' in any case mixture is true; anything else is false
241: return Boolean.valueOf(arg).booleanValue();
242: }
243:
244: public boolean tryArg(int k, boolean b) {
245: boolean value;
246: try {
247: value = processArg(theArgs[k], b);
248: } catch (ArrayIndexOutOfBoundsException e) {
249: if (optErr)
250: System.err.println("tryArg: no theArgs[" + k + "]"); //NOI18N
251: return b;
252: }
253: return value;
254: }
255:
256: public String tryArg(int k, String s) {
257: String value;
258: try {
259: value = theArgs[k];
260: } catch (ArrayIndexOutOfBoundsException e) {
261: if (optErr)
262: System.err.println("tryArg: no theArgs[" + k + "]"); //NOI18N
263: return s;
264: }
265: return value;
266: }
267:
268: private static void writeError(String msg, char ch) {
269: System.err.println("GetOpt: " + msg + " -- " + ch); //NOI18N
270: }
271:
272: public static final int optEOF = -1;
273:
274: private int optIndex = 0;
275:
276: public int optIndexGet() {
277: return optIndex;
278: }
279:
280: public void optIndexSet(int i) {
281: optIndex = i;
282: }
283:
284: private String optArg = null;
285:
286: public String optArgGet() {
287: return optArg;
288: }
289:
290: private int optPosition = 1;
291:
292: public int getopt() {
293: optArg = null;
294: if (theArgs == null || optString == null)
295: return optEOF;
296: if (optIndex < 0 || optIndex >= argCount)
297: return optEOF;
298: String this Arg = theArgs[optIndex];
299: int argLength = this Arg.length();
300: // handle special cases
301: if (argLength <= 1 || this Arg.charAt(0) != '-') {
302: // e.g., "", "a", "abc", or just "-"
303: return optEOF;
304: } else if (this Arg.equals("--")) {//NOI18N
305: // end of non-option args
306: optIndex++;
307: return optEOF;
308: }
309: // get next "letter" from option argument
310: char ch = this Arg.charAt(optPosition);
311: // find this option in optString
312: int pos = optString.indexOf(ch);
313: if (pos == -1 || ch == ':') {
314: if (optErr) {
315: writeError("illegal option", ch); //NOI18N
316: }
317: ch = '?';
318: } else { // handle colon, if present
319: if (pos < optString.length() - 1
320: && optString.charAt(pos + 1) == ':') {
321: if (optPosition != argLength - 1) {
322: // take rest of current arg as optArg
323: optArg = this Arg.substring(optPosition + 1);
324: optPosition = argLength - 1; // force advance to next arg below
325: } else { // take next arg as optArg
326: optIndex++;
327: if (optIndex < argCount
328: && (theArgs[optIndex].charAt(0) != '-' || theArgs[optIndex]
329: .length() >= 2
330: && (optString
331: .indexOf(theArgs[optIndex]
332: .charAt(1)) == -1 || theArgs[optIndex]
333: .charAt(1) == ':'))) {
334: optArg = theArgs[optIndex];
335: } else {
336: if (optErr) {
337: writeError("option requires an argument",
338: ch); //NOI18N
339: }
340: optArg = null;
341: ch = ':'; // Linux man page for getopt(3) says : not ?
342: }
343: }
344: }
345: }
346: // advance to next option argument,
347: // which might be in thisArg or next arg
348: optPosition++;
349: if (optPosition >= argLength) {
350: optIndex++;
351: optPosition = 1;
352: }
353: return ch;
354: }
355:
356: public static void main(String[] args) { // test the class
357: GetOpt go = new GetOpt(args, "Uab:f:h:w:");
358: go.optErr = true;
359: int ch = -1;
360: // process options in command line arguments
361: boolean usagePrint = false; // set
362: int aflg = 0; // default
363: boolean bflg = false; // values
364: String filename = "out"; // of
365: int width = 80; // options
366: double height = 1; // here
367: while ((ch = go.getopt()) != go.optEOF) {
368: if ((char) ch == 'U')
369: usagePrint = true;
370: else if ((char) ch == 'a')
371: aflg++;
372: else if ((char) ch == 'b')
373: bflg = go.processArg(go.optArgGet(), bflg);
374: else if ((char) ch == 'f')
375: filename = go.optArgGet();
376: else if ((char) ch == 'h')
377: height = go.processArg(go.optArgGet(), height);
378: else if ((char) ch == 'w')
379: width = go.processArg(go.optArgGet(), width);
380: else
381: System.exit(1); // undefined option
382: } // getopt() returns '?'
383: if (usagePrint) {
384: System.out
385: .println("Usage: -a -b bool -f file -h height -w width"); //NOI18N
386: System.exit(0);
387: }
388: System.out.println("These are all the command line arguments " + //NOI18N
389: "before processing with GetOpt:"); //NOI18N
390: for (int i = 0; i < args.length; i++) {
391: System.out.print(" " + args[i]); //NOI18N
392: }
393: System.out.println();
394: System.out.println("-U " + usagePrint); //NOI18N
395: System.out.println("-a " + aflg); //NOI18N
396: System.out.println("-b " + bflg); //NOI18N
397: System.out.println("-f " + filename); //NOI18N
398: System.out.println("-h " + height); //NOI18N
399: System.out.println("-w " + width); //NOI18N
400: // process non-option command line arguments
401: for (int k = go.optIndexGet(); k < args.length; k++) {
402: System.out.println("normal argument " + k + " is "
403: + args[k]); //NOI18N
404: }
405: }
406: }
407:
408: /* ............... Example compile and run(s)
409:
410: D:\>javac GetOpt.java
411:
412: D:\>java GetOpt -aaa -b true -f theFile -w -80 -h3.33 arg1 arg2
413:
414: These are all the command line arguments before processing with GetOpt:
415: -aaa -b true -f theFile -w -80 -h3.33 arg1 arg2
416: -U false
417: -a 3
418: -b true
419: -f theFile
420: -h 3.33
421: -w -80
422: normal argument 8 is arg1
423: normal argument 9 is arg2
424:
425: D:\>java GetOpt -aaa -x -w90
426:
427: GetOpt: illegal option -- x
428:
429: D:\>java GetOpt -af theFile -w -b true
430:
431: GetOpt: option requires an argument -- w
432: ... end of example run(s) */
|