FileDocCategorySizeDatePackage
GetOpt.javaAPI DocExample8416Mon May 31 22:51:36 BST 2004com.darwinsys.lang

GetOpt

public class GetOpt extends Object
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. As a result, there are two ways of using it.
  1. Original model:
    GetOpt go = new GetOpt("hno:");
    boolean numeric_option = false;
    String outFileName = "(standard output)";
    char c;
    while ((c = go.getopt(args)) != GetOpt.DONE) {
    switch(c) {
    case 'h':
    doHelp(0);
    break;
    case 'n':
    numeric_option = true;
    break;
    case 'o':
    outFileName = go.optarg();
    break;
    default:
    System.err.println("Unknown option character " + c);
    doHelp(1);
    }
    }
    System.out.print("Options: ");
    System.out.print("Numeric: " + numeric_option + ' ');
    System.out.print("Output: " + outFileName + "; ");
    System.out.print("Inputs: ");
    if (go.getOptInd() == args.length) {
    doFile("(standard input)");
    } else for (int i = go.getOptInd(); i < args.length; i++) {
    doFile(args[i]);
    }
    
  2. Newer model, which allows long-named options:
    boolean numeric_option = false;
    boolean errs = false;
    String outputFileName = null;
    
    GetOptDesc options[] = {
    new GetOptDesc('n', "numeric", false),
    new GetOptDesc('o', "output-file", true),
    };
    GetOpt parser = new GetOpt(options);
    Map optionsFound = parser.parseArguments(argv);
    Iterator it = optionsFound.keySet().iterator();
    while (it.hasNext()) {
    String key = (String)it.next();
    char c = key.charAt(0);
    switch (c) {
    case 'n':
    numeric_option = true;
    break;
    case 'o':
    outputFileName = (String)optionsFound.get(key);
    break;
    case '?':
    errs = true;
    break;
    default:
    throw new IllegalStateException(
    "Unexpected option character: " + c);
    }
    }
    if (errs) {
    System.err.println("Usage: GetOptDemo [-n][-o file][file...]");
    }
    System.out.print("Options: ");
    System.out.print("Numeric: " + numeric_option + ' ');
    System.out.print("Output: " + outputFileName + "; ");
    System.out.print("Input files: ");
    List files = parser.getFilenameList();
    while (files.hasNext()) {
    System.out.print(files.next());
    System.out.print(' ');
    }
    System.out.println();
    }
    

This is not threadsafe; it is expected to be used only from main().

For another way of dealing with command lines, see the Jakarta Commons Command Line Interface.

author
Ian F. Darwin, http://www.darwinsys.com/
version
$Id: GetOpt.java,v 1.23 2004/06/01 02:51:36 ian Exp $

Fields Summary
protected List
fileNameArguments
The List of File Names found after args
protected final GetOptDesc[]
options
The set of characters to look for
protected int
optind
Where we are in the options
public static final int
DONE
Public constant for "no more options"
protected boolean
done
Internal flag - whether we are done all the options
protected String
optarg
The current option argument.
private static char[]
strConvArray
Array used to convert a char to a String
Constructors Summary
public GetOpt(GetOptDesc[] opt)

		this.options = opt;
	
public GetOpt(String patt)

		if (patt == null) {
			throw new IllegalArgumentException("Pattern may not be null");
		}

		// 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 opjects.
		options = new GetOptDesc[n];
		for (int i = 0, ix = 0; i<patt.length(); i++) {
			final 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);
			++ix;
		}
	
Methods Summary
public java.util.ListgetFilenameList()
Get the list of filename-like arguments after options

		if (fileNameArguments == null) {
			throw new IllegalArgumentException(
				"Illegal call to getFilenameList() before parseOptions()");
		}
		return fileNameArguments;
	
public intgetOptInd()
Return optind, the index into args of the last option we looked at

		return optind;
	
public chargetopt(java.lang.String[] argv)
The true heart of getopt, whether used old way or new way: returns one argument; call repeatedly until it returns DONE.

		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;
		}

		// XXX 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;
		}
	
public java.lang.StringoptArg()
Retrieve the current option argument; Java variant spelling.

		return optarg;
	
public java.lang.Stringoptarg()
Retrieve the current option argument; UNIX variant spelling.


	         
	   
		return optarg;
	
public java.util.MapparseArguments(java.lang.String[] argv)
Modern way of using GetOpt: call this once and get all options.

This parses the options, 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.


	                                                                    	 
	    
		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;
	
public voidrewind()
Reset this GetOpt parser

		fileNameArguments = null;
		done = false;
		optind = 0;