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