/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.netbeans.lib.cvsclient.commandLine; /** * <h1>Overview</h1> * * GetOpt provides a general means for a Java program to parse command line arguments in accordance with the standard Unix conventions; it * is analogous to, and based on, getopt(3) for C programs. (The following documentation is based on the man page for getopt(3).) * * <h1>Description</h1> * * GetOpt is a Java class that provides one method, getopt, and some variables that control behavior of or return additional information * from getopt. * <p> * GetOpt interprets command arguments in accordance with the standard Unix conventions: option arguments of a command are introduced by "-" * followed by a key character, and a non-option argument terminates the processing of options. GetOpt's option interpretation is controlled * by its parameter optString, which specifies what characters designate legal options and which of them require associated values. * <p> * The getopt method returns the next, moving left to right, option letter in the command line arguments that matches a letter in optString. * optString must contain the option letters the command using getopt will recognize. For example, getopt("ab") specifies that the command * line should contain no options, only "-a", only "-b", or both "-a" and "-b" in either order. (The command line can also contain * non-option arguments after any option arguments.) Multiple options per argument are allowed, e.g., "-ab" for the last case above. * <p> * If a letter in optString is followed by a colon, the option is expected to have an argument. The argument may or may not be separated by * whitespace from the option letter. For example, getopt("w:") allows either "-w 80" or "-w80". The variable optArg is set to the option * argument, e.g., "80" in either of the previous examples. Conversion functions such as Integer.parseInt(), etc., can then be applied to * optArg. * <p> * getopt places in the variable optIndex the index of the next command line argument to be processed; optIndex is automatically initialized * to 1 before the first call to getopt. * <p> * When all options have been processed (that is, up to the first non-option argument), getopt returns optEOF (-1). getopt recognizes the * command line argument "--" (i.e., two dashes) to delimit the end of the options; getopt returns optEOF and skips "--". Subsequent, * non-option arguments can be retrieved using the String array passed to main(), beginning with argument number optIndex. * * <h1>Diagnostics</h1> * * getopt prints an error message on System.stderr and returns a question mark ('?') when it encounters an option letter in a command line * argument that is not included in optString. Setting the variable optErr to false disables this error message. * * <h1>Notes</h1> * * The following notes describe GetOpt's behavior in a few interesting or special cases; these behaviors are consistent with getopt(3)'s * behaviors. -- A '-' by itself is treated as a non-option argument. -- If optString is "a:" and the command line arguments are "-a -x", * then "-x" is treated as the argument associated with the "-a". -- Duplicate command line options are allowed; it is up to user to deal * with them as appropriate. -- A command line option like "-b-" is considered as the two options "b" and "-" (so "-" should appear in * option string); this differs from "-b --". -- Sun and DEC getopt(3)'s differ w.r.t. how "---" is handled. Sun treats "---" (or anything * starting with "--") the same as "--" DEC treats "---" as two separate "-" options (so "-" should appear in option string). Java GetOpt * follows the DEC convention. -- An option `letter' can be a letter, number, or most special character. Like getopt(3), GetOpt disallows a * colon as an option letter. * * @author Anonymous *****************************************************************************/ public class GetOpt { private String[] theArgs = null; private int argCount = 0; private String optString = null; public GetOpt(String[] args, String opts) { theArgs = args; argCount = theArgs.length; optString = opts; } // user can toggle this to control printing of error messages public boolean optErr = false; public int processArg(String arg, int n) { int value; try { value = Integer.parseInt(arg); } catch (NumberFormatException e) { if (optErr) { System.err.println("processArg cannot process " + arg // NOI18N + " as an integer"); // NOI18N } return n; } return value; } public int tryArg(int k, int n) { int value; try { value = processArg(theArgs[k], n); } catch (ArrayIndexOutOfBoundsException e) { if (optErr) { System.err.println("tryArg: no theArgs[" + k + "]"); // NOI18N } return n; } return value; } public long processArg(String arg, long n) { long value; try { value = Long.parseLong(arg); } catch (NumberFormatException e) { if (optErr) { System.err.println("processArg cannot process " + arg // NOI18N + " as a long"); // NOI18N } return n; } return value; } public long tryArg(int k, long n) { long value; try { value = processArg(theArgs[k], n); } catch (ArrayIndexOutOfBoundsException e) { if (optErr) { System.err.println("tryArg: no theArgs[" + k + "]"); // NOI18N } return n; } return value; } public double processArg(String arg, double d) { double value; try { value = Double.valueOf(arg).doubleValue(); } catch (NumberFormatException e) { if (optErr) { System.err.println("processArg cannot process " + arg // NOI18N + " as a double"); // NOI18N } return d; } return value; } public double tryArg(int k, double d) { double value; try { value = processArg(theArgs[k], d); } catch (ArrayIndexOutOfBoundsException e) { if (optErr) { System.err.println("tryArg: no theArgs[" + k + "]"); // NOI18N } return d; } return value; } public float processArg(String arg, float f) { float value; try { value = Float.valueOf(arg).floatValue(); } catch (NumberFormatException e) { if (optErr) { System.err.println("processArg cannot process " + arg // NOI18N + " as a float"); // NOI18N } return f; } return value; } public float tryArg(int k, float f) { float value; try { value = processArg(theArgs[k], f); } catch (ArrayIndexOutOfBoundsException e) { if (optErr) { System.err.println("tryArg: no theArgs[" + k + "]"); // NOI18N } return f; } return value; } public boolean processArg(String arg, boolean b) { // `true' in any case mixture is true; anything else is false return Boolean.valueOf(arg).booleanValue(); } public boolean tryArg(int k, boolean b) { boolean value; try { value = processArg(theArgs[k], b); } catch (ArrayIndexOutOfBoundsException e) { if (optErr) { System.err.println("tryArg: no theArgs[" + k + "]"); // NOI18N } return b; } return value; } public String tryArg(int k, String s) { String value; try { value = theArgs[k]; } catch (ArrayIndexOutOfBoundsException e) { if (optErr) { System.err.println("tryArg: no theArgs[" + k + "]"); // NOI18N } return s; } return value; } private static void writeError(String msg, char ch) { System.err.println("GetOpt: " + msg + " -- " + ch); // NOI18N } public static final int optEOF = -1; private int optIndex = 0; public int optIndexGet() { return optIndex; } public void optIndexSet(int i) { optIndex = i; } private String optArg = null; public String optArgGet() { return optArg; } private int optPosition = 1; public int getopt() { optArg = null; if (theArgs == null || optString == null) { return optEOF; } if (optIndex < 0 || optIndex >= argCount) { return optEOF; } String thisArg = theArgs[optIndex]; int argLength = thisArg.length(); // handle special cases if (argLength <= 1 || thisArg.charAt(0) != '-') { // e.g., "", "a", "abc", or just "-" return optEOF; } else if (thisArg.equals("--")) {// NOI18N // end of non-option args optIndex++; return optEOF; } // get next "letter" from option argument char ch = thisArg.charAt(optPosition); // find this option in optString int pos = optString.indexOf(ch); if (pos == -1 || ch == ':') { if (optErr) { writeError("illegal option", ch); // NOI18N } ch = '?'; } else { // handle colon, if present if (pos < optString.length() - 1 && optString.charAt(pos + 1) == ':') { if (optPosition != argLength - 1) { // take rest of current arg as optArg optArg = thisArg.substring(optPosition + 1); optPosition = argLength - 1; // force advance to next arg below } else { // take next arg as optArg optIndex++; if (optIndex < argCount && (theArgs[optIndex].charAt(0) != '-' || theArgs[optIndex].length() >= 2 && (optString.indexOf(theArgs[optIndex].charAt(1)) == -1 || theArgs[optIndex].charAt(1) == ':'))) { optArg = theArgs[optIndex]; } else { if (optErr) { writeError("option requires an argument", ch); // NOI18N } optArg = null; ch = ':'; // Linux man page for getopt(3) says : not ? } } } } // advance to next option argument, // which might be in thisArg or next arg optPosition++; if (optPosition >= argLength) { optIndex++; optPosition = 1; } return ch; } public static void main(String[] args) { // test the class GetOpt go = new GetOpt(args, "Uab:f:h:w:"); go.optErr = true; int ch = -1; // process options in command line arguments boolean usagePrint = false; // set int aflg = 0; // default boolean bflg = false; // values String filename = "out"; // of int width = 80; // options double height = 1; // here while ((ch = go.getopt()) != GetOpt.optEOF) { if ((char) ch == 'U') { usagePrint = true; } else if ((char) ch == 'a') { aflg++; } else if ((char) ch == 'b') { bflg = go.processArg(go.optArgGet(), bflg); } else if ((char) ch == 'f') { filename = go.optArgGet(); } else if ((char) ch == 'h') { height = go.processArg(go.optArgGet(), height); } else if ((char) ch == 'w') { width = go.processArg(go.optArgGet(), width); } else { System.exit(1); // undefined option } } // getopt() returns '?' if (usagePrint) { System.out.println("Usage: -a -b bool -f file -h height -w width"); // NOI18N System.exit(0); } System.out.println("These are all the command line arguments " + // NOI18N "before processing with GetOpt:"); // NOI18N for (int i = 0; i < args.length; i++) { System.out.print(" " + args[i]); // NOI18N } System.out.println(); System.out.println("-U " + usagePrint); // NOI18N System.out.println("-a " + aflg); // NOI18N System.out.println("-b " + bflg); // NOI18N System.out.println("-f " + filename); // NOI18N System.out.println("-h " + height); // NOI18N System.out.println("-w " + width); // NOI18N // process non-option command line arguments for (int k = go.optIndexGet(); k < args.length; k++) { System.out.println("normal argument " + k + " is " + args[k]); // NOI18N } } } /* ............... Example compile and run(s) D:\>javac GetOpt.java D:\>java GetOpt -aaa -b true -f theFile -w -80 -h3.33 arg1 arg2 These are all the command line arguments before processing with GetOpt: -aaa -b true -f theFile -w -80 -h3.33 arg1 arg2 -U false -a 3 -b true -f theFile -h 3.33 -w -80 normal argument 8 is arg1 normal argument 9 is arg2 D:\>java GetOpt -aaa -x -w90 GetOpt: illegal option -- x D:\>java GetOpt -af theFile -w -b true GetOpt: option requires an argument -- w ... end of example run(s) */