package com.darwinsys.lang;
import com.darwinsys.util.Debug;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
/** A class to implement Unix-style (single-character) command-line argument
* parsing. Originally patterned after (but not using code from) the Unix
* getopt(3) program, this has been redesigned to be more Java-friendly.
* <p>
* This is <em>not</em> threadsafe; it is expected to be used only from main( ).
* <p>
* For another way of dealing with command lines, see the
* <a href="http://jakarta.apache.org/commons/cli/">Jakarta Commons
* Command Line Interface</a>.
* @author Ian F. Darwin, ian@darwinsys.com
* @version $Id: ch02,v 1.4 2004/05/04 20:11:12 ian Exp $
*/
public class GetOpt {
/** The list of file names found after args */
protected List fileNameArguments;
/** The set of characters to look for */
protected GetOptDesc[] options;
/** Where we are in the options */
protected int optind = 0;
/** Public constant for "no more options" */
public static final int DONE = 0;
/** Internal flag - whether we are done all the options */
protected boolean done = false;
/** The current option argument. */
protected String optarg;
/** Retrieve the current option argument */
public String optarg( ) {
return optarg;
}
/* Construct a GetOpt parser, given the option specifications
* in an array of GetOptDesc objects. This is the preferred constructor.
*/
public GetOpt(GetOptDesc[] options) {
this.options = options;
}
/* Construct a GetOpt parser, storing the set of option characters.
* This is a legacy constructor for backward compatibility.
*/
public GetOpt(String patt) {
// Pass One: just count the letters
int n = 0;
for (int i = 0; i<patt.length( ); i++) {
if (patt.charAt(i) != ':')
++n;
}
if (n == 0)
throw new IllegalArgumentException(
"No option letters found in " + patt);
// Pass Two: construct an array of GetOptDesc objects.
options = new GetOptDesc[n];
for (int i = 0, ix = 0; i<patt.length( ); i++) {
char c = patt.charAt(i);
boolean argTakesValue = false;
if (i < patt.length( ) - 1 && patt.charAt(i+1) == ':') {
argTakesValue = true;
++i;
}
options[ix++] = new GetOptDesc(c, null, argTakesValue);
Debug.println("getopt",
"CONSTR: options[" + ix + "] = " + c + ", " + argTakesValue);
}
}
/** Reset this GetOpt parser */
public void rewind( ) {
fileNameArguments = null;
done = false;
optind = 0;
}
/** Array used to convert a char to a String */
private static char[] strConvArray = { 0 };
/**
* Modern way of using GetOpt: call this once and get all options.
* <p>
* This parses the options and returns a Map whose keys are the found options.
* Normally followed by a call to getFilenameList( ).
* @return a Map whose keys are Strings of length 1 (containing the char
* from the option that was matched) and whose value is a String
* containing the value, or null for a non-option argument.
*/
public Map parseArguments(String[] argv) {
Map optionsAndValues = new HashMap( );
fileNameArguments = new ArrayList( );
for (int i = 0; i < argv.length; i++) {
Debug.println("getopt", "parseArg: i=" + i + ": arg " + argv[i]);
char c = getopt(argv);
if (c != DONE) {
strConvArray[0] = c;
optionsAndValues.put(new String(strConvArray), optarg);
// If this arg takes an option, we must skip it here.
if (optarg != null)
++i;
} else {
fileNameArguments.add(argv[i]);
}
}
return optionsAndValues;
}
/** Get the list of filename-like arguments after options */
public List getFilenameList( ) {
if (fileNameArguments == null) {
throw new IllegalArgumentException(
"Illegal call to getFilenameList( ) before parseOptions( )");
}
return fileNameArguments;
}
/** The true heart of getopt, whether used old way or new way:
* returns one argument; call repeatedly until it returns DONE.
*/
public char getopt(String argv[]) {
Debug.println("getopt",
"optind=" + optind + ", argv.length="+argv.length);
if (optind == (argv.length)-1) {
done = true;
}
// If we are (now) finished, bail.
if (done) {
return DONE;
}
// TODO - two-pass, 1st check long args, 2nd check for
// char, may be multi char as in "-no outfile" == "-n -o outfile".
// Pick off the next command-line argument; check if it starts "-".
// If so, look it up in the list.
String thisArg = argv[optind++];
if (thisArg.startsWith("-")) {
optarg = null;
for (int i=0; i<options.length; i++) {
if ( options[i].argLetter == thisArg.charAt(1) ||
(options[i].argName != null &&
options[i].argName == thisArg.substring(1))) { // found it
// If it needs an option argument, get it.
if (options[i].takesArgument) {
if (optind < argv.length) {
optarg = argv[optind];
++optind;
} else {
throw new IllegalArgumentException(
"Option " + options[i].argLetter +
" needs value but found end of arg list");
}
}
return options[i].argLetter;
}
}
// Began with "-" but not matched, so must be error.
return '?';
} else {
// Found non-argument non-option word in argv: end of options.
done = true;
return DONE;
}
}
/** Return optind, the index into args of the last option we looked at */
public int getOptInd( ) {
return optind;
}
}
A class to implement Unix-style (single-character) command-line argument parsing. Originally patterned after (but not using code from) the Unix getopt(3) program, this has been redesigned to be more Java-friendly.
Be the first to comment
You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.