1*2be1a816SJohn Birrell /* 2*2be1a816SJohn Birrell * CDDL HEADER START 3*2be1a816SJohn Birrell * 4*2be1a816SJohn Birrell * The contents of this file are subject to the terms of the 5*2be1a816SJohn Birrell * Common Development and Distribution License (the "License"). 6*2be1a816SJohn Birrell * You may not use this file except in compliance with the License. 7*2be1a816SJohn Birrell * 8*2be1a816SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2be1a816SJohn Birrell * or http://www.opensolaris.org/os/licensing. 10*2be1a816SJohn Birrell * See the License for the specific language governing permissions 11*2be1a816SJohn Birrell * and limitations under the License. 12*2be1a816SJohn Birrell * 13*2be1a816SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 14*2be1a816SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2be1a816SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 16*2be1a816SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 17*2be1a816SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 18*2be1a816SJohn Birrell * 19*2be1a816SJohn Birrell * CDDL HEADER END 20*2be1a816SJohn Birrell */ 21*2be1a816SJohn Birrell 22*2be1a816SJohn Birrell /* 23*2be1a816SJohn Birrell * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*2be1a816SJohn Birrell * Use is subject to license terms. 25*2be1a816SJohn Birrell * 26*2be1a816SJohn Birrell * ident "%Z%%M% %I% %E% SMI" 27*2be1a816SJohn Birrell */ 28*2be1a816SJohn Birrell 29*2be1a816SJohn Birrell /* Copyright (c) 1988 AT&T */ 30*2be1a816SJohn Birrell /* All Rights Reserved */ 31*2be1a816SJohn Birrell 32*2be1a816SJohn Birrell import java.io.StringWriter; 33*2be1a816SJohn Birrell import java.io.PrintWriter; 34*2be1a816SJohn Birrell 35*2be1a816SJohn Birrell /** 36*2be1a816SJohn Birrell * A Java port of Solaris {@code lib/libc/port/gen/getopt.c}, which is a 37*2be1a816SJohn Birrell * port of System V UNIX getopt. See <b>getopt(3C)</b> and SUS/XPG 38*2be1a816SJohn Birrell * getopt() for function definition and requirements. Unlike that 39*2be1a816SJohn Birrell * definition, this implementation moves non-options to the end of the 40*2be1a816SJohn Birrell * argv array rather than quitting at the first non-option. 41*2be1a816SJohn Birrell */ 42*2be1a816SJohn Birrell public class Getopt { 43*2be1a816SJohn Birrell static final int EOF = -1; 44*2be1a816SJohn Birrell 45*2be1a816SJohn Birrell private String progname; 46*2be1a816SJohn Birrell private String[] args; 47*2be1a816SJohn Birrell private int argc; 48*2be1a816SJohn Birrell private String optstring; 49*2be1a816SJohn Birrell private int optind = 0; // args index 50*2be1a816SJohn Birrell private int optopt = 0; 51*2be1a816SJohn Birrell private String optarg = null; 52*2be1a816SJohn Birrell private boolean opterr = true; 53*2be1a816SJohn Birrell 54*2be1a816SJohn Birrell /* 55*2be1a816SJohn Birrell * _sp is required to keep state between successive calls to 56*2be1a816SJohn Birrell * getopt() while extracting aggregated short-options (ie: -abcd). 57*2be1a816SJohn Birrell */ 58*2be1a816SJohn Birrell private int _sp = 1; 59*2be1a816SJohn Birrell 60*2be1a816SJohn Birrell /** 61*2be1a816SJohn Birrell * Creates a {Code Getopt} instance to parse the given command-line 62*2be1a816SJohn Birrell * arguments. Modifies the given args array by swapping the 63*2be1a816SJohn Birrell * positions of non-options and options so that non-options appear 64*2be1a816SJohn Birrell * at the end of the array. 65*2be1a816SJohn Birrell */ Getopt(String programName, String[] args, String optionString)66*2be1a816SJohn Birrell public Getopt(String programName, String[] args, 67*2be1a816SJohn Birrell String optionString) 68*2be1a816SJohn Birrell { 69*2be1a816SJohn Birrell progname = programName; 70*2be1a816SJohn Birrell // No defensive copy; Getopt is expected to modify the given 71*2be1a816SJohn Birrell // args array 72*2be1a816SJohn Birrell this.args = args; 73*2be1a816SJohn Birrell argc = this.args.length; 74*2be1a816SJohn Birrell optstring = optionString; 75*2be1a816SJohn Birrell validate(); 76*2be1a816SJohn Birrell } 77*2be1a816SJohn Birrell 78*2be1a816SJohn Birrell private void validate()79*2be1a816SJohn Birrell validate() 80*2be1a816SJohn Birrell { 81*2be1a816SJohn Birrell if (progname == null) { 82*2be1a816SJohn Birrell throw new NullPointerException("program name is null"); 83*2be1a816SJohn Birrell } 84*2be1a816SJohn Birrell int i = 0; 85*2be1a816SJohn Birrell for (String s : args) { 86*2be1a816SJohn Birrell if (s == null) { 87*2be1a816SJohn Birrell throw new NullPointerException("null arg at index " + i); 88*2be1a816SJohn Birrell } 89*2be1a816SJohn Birrell ++i; 90*2be1a816SJohn Birrell } 91*2be1a816SJohn Birrell if (optstring == null) { 92*2be1a816SJohn Birrell throw new NullPointerException("option string is null"); 93*2be1a816SJohn Birrell } 94*2be1a816SJohn Birrell } 95*2be1a816SJohn Birrell 96*2be1a816SJohn Birrell private static class StringRef { 97*2be1a816SJohn Birrell private String s; 98*2be1a816SJohn Birrell 99*2be1a816SJohn Birrell public String get()100*2be1a816SJohn Birrell get() 101*2be1a816SJohn Birrell { 102*2be1a816SJohn Birrell return s; 103*2be1a816SJohn Birrell } 104*2be1a816SJohn Birrell 105*2be1a816SJohn Birrell public StringRef set(String value)106*2be1a816SJohn Birrell set(String value) 107*2be1a816SJohn Birrell { 108*2be1a816SJohn Birrell s = value; 109*2be1a816SJohn Birrell return this; 110*2be1a816SJohn Birrell } 111*2be1a816SJohn Birrell } 112*2be1a816SJohn Birrell 113*2be1a816SJohn Birrell /* 114*2be1a816SJohn Birrell * Generalized error processing method. If the optstr parameter is 115*2be1a816SJohn Birrell * null, the character c is converted to a string and displayed 116*2be1a816SJohn Birrell * instead. 117*2be1a816SJohn Birrell */ 118*2be1a816SJohn Birrell void err(String format, char c, String optstr)119*2be1a816SJohn Birrell err(String format, char c, String optstr) 120*2be1a816SJohn Birrell { 121*2be1a816SJohn Birrell if (opterr && optstring.charAt(0) != ':') { 122*2be1a816SJohn Birrell StringWriter w = new StringWriter(); 123*2be1a816SJohn Birrell PrintWriter p = new PrintWriter(w); 124*2be1a816SJohn Birrell p.printf(format, progname, (optstr == null ? 125*2be1a816SJohn Birrell Character.toString(c) : optstr.substring(2))); 126*2be1a816SJohn Birrell System.err.println(w.toString()); 127*2be1a816SJohn Birrell } 128*2be1a816SJohn Birrell } 129*2be1a816SJohn Birrell 130*2be1a816SJohn Birrell /* 131*2be1a816SJohn Birrell * Determine if the specified character (c) is present in the string 132*2be1a816SJohn Birrell * (optstring) as a regular, single character option. If the option 133*2be1a816SJohn Birrell * is found, return an index into optstring where the short-option 134*2be1a816SJohn Birrell * character is found, otherwise return -1. The characters ':' and 135*2be1a816SJohn Birrell * '(' are not allowed. 136*2be1a816SJohn Birrell */ 137*2be1a816SJohn Birrell static int parseshort(String optstring, char c)138*2be1a816SJohn Birrell parseshort(String optstring, char c) 139*2be1a816SJohn Birrell { 140*2be1a816SJohn Birrell if (c == ':' || c == '(') { 141*2be1a816SJohn Birrell return -1; 142*2be1a816SJohn Birrell } 143*2be1a816SJohn Birrell 144*2be1a816SJohn Birrell int ch; 145*2be1a816SJohn Birrell int len = optstring.length(); 146*2be1a816SJohn Birrell for (int i = 0; i < len; ++i) { 147*2be1a816SJohn Birrell ch = optstring.charAt(i); 148*2be1a816SJohn Birrell if (ch == c) { 149*2be1a816SJohn Birrell return i; 150*2be1a816SJohn Birrell } 151*2be1a816SJohn Birrell 152*2be1a816SJohn Birrell while (i < len && ch == '(') { 153*2be1a816SJohn Birrell for (++i; i < len && (ch = optstring.charAt(i)) != ')'; ++i); 154*2be1a816SJohn Birrell } 155*2be1a816SJohn Birrell } 156*2be1a816SJohn Birrell 157*2be1a816SJohn Birrell return -1; 158*2be1a816SJohn Birrell } 159*2be1a816SJohn Birrell 160*2be1a816SJohn Birrell /** 161*2be1a816SJohn Birrell * Determine if the specified string (opt) is present in the string 162*2be1a816SJohn Birrell * (optstring) as a long-option contained within parenthesis. If the 163*2be1a816SJohn Birrell * long-option specifies option-argument, return a reference to it 164*2be1a816SJohn Birrell * in longoptarg. Otherwise set the longoptarg reference to null. 165*2be1a816SJohn Birrell * If the option is found, return an index into optstring at the 166*2be1a816SJohn Birrell * position of the short-option character associated with the 167*2be1a816SJohn Birrell * long-option; otherwise return -1. 168*2be1a816SJohn Birrell * 169*2be1a816SJohn Birrell * @param optstring the entire optstring passed to the {@code 170*2be1a816SJohn Birrell * Getopt} constructor 171*2be1a816SJohn Birrell * @param opt the long option read from the command line 172*2be1a816SJohn Birrell * @param longoptarg the value of the option is returned in this 173*2be1a816SJohn Birrell * parameter, if an option exists. Possible return values in 174*2be1a816SJohn Birrell * longoptarg are: 175*2be1a816SJohn Birrell * <ul> 176*2be1a816SJohn Birrell * <li><b>NULL:</b> No argument was found</li> 177*2be1a816SJohn Birrell * <li><b>empty string (""):</b> Argument was explicitly left empty 178*2be1a816SJohn Birrell * by the user (e.g., --option= )</li> 179*2be1a816SJohn Birrell * <li><b>valid string:</b> Argument found on the command line</li> 180*2be1a816SJohn Birrell * </ul> 181*2be1a816SJohn Birrell * @return index to equivalent short-option in optstring, or -1 if 182*2be1a816SJohn Birrell * option not found in optstring. 183*2be1a816SJohn Birrell */ 184*2be1a816SJohn Birrell static int parselong(String optstring, String opt, StringRef longoptarg)185*2be1a816SJohn Birrell parselong(String optstring, String opt, StringRef longoptarg) 186*2be1a816SJohn Birrell { 187*2be1a816SJohn Birrell int cp; // index into optstring, beginning of one option spec 188*2be1a816SJohn Birrell int ip; // index into optstring, traverses every char 189*2be1a816SJohn Birrell char ic; // optstring char 190*2be1a816SJohn Birrell int il; // optstring length 191*2be1a816SJohn Birrell int op; // index into opt 192*2be1a816SJohn Birrell char oc; // opt char 193*2be1a816SJohn Birrell int ol; // opt length 194*2be1a816SJohn Birrell boolean match; // true if opt is matching part of optstring 195*2be1a816SJohn Birrell 196*2be1a816SJohn Birrell longoptarg.set(null); 197*2be1a816SJohn Birrell cp = ip = 0; 198*2be1a816SJohn Birrell il = optstring.length(); 199*2be1a816SJohn Birrell ol = opt.length(); 200*2be1a816SJohn Birrell do { 201*2be1a816SJohn Birrell ic = optstring.charAt(ip); 202*2be1a816SJohn Birrell if (ic != '(' && ++ip == il) 203*2be1a816SJohn Birrell break; 204*2be1a816SJohn Birrell ic = optstring.charAt(ip); 205*2be1a816SJohn Birrell if (ic == ':' && ++ip == il) 206*2be1a816SJohn Birrell break; 207*2be1a816SJohn Birrell ic = optstring.charAt(ip); 208*2be1a816SJohn Birrell while (ic == '(') { 209*2be1a816SJohn Birrell if (++ip == il) 210*2be1a816SJohn Birrell break; 211*2be1a816SJohn Birrell op = 0; 212*2be1a816SJohn Birrell match = true; 213*2be1a816SJohn Birrell while (ip < il && (ic = optstring.charAt(ip)) != ')' && 214*2be1a816SJohn Birrell op < ol) { 215*2be1a816SJohn Birrell oc = opt.charAt(op++); 216*2be1a816SJohn Birrell match = (ic == oc && match); 217*2be1a816SJohn Birrell ++ip; 218*2be1a816SJohn Birrell } 219*2be1a816SJohn Birrell 220*2be1a816SJohn Birrell if (match && ip < il && ic == ')' && (op >= ol || 221*2be1a816SJohn Birrell opt.charAt(op) == '=')) { 222*2be1a816SJohn Birrell if (op < ol && opt.charAt(op) == '=') { 223*2be1a816SJohn Birrell /* may be an empty string - OK */ 224*2be1a816SJohn Birrell longoptarg.set(opt.substring(op + 1)); 225*2be1a816SJohn Birrell } else { 226*2be1a816SJohn Birrell longoptarg.set(null); 227*2be1a816SJohn Birrell } 228*2be1a816SJohn Birrell return cp; 229*2be1a816SJohn Birrell } 230*2be1a816SJohn Birrell if (ip < il && ic == ')' && ++ip == il) 231*2be1a816SJohn Birrell break; 232*2be1a816SJohn Birrell ic = optstring.charAt(ip); 233*2be1a816SJohn Birrell } 234*2be1a816SJohn Birrell cp = ip; 235*2be1a816SJohn Birrell /* 236*2be1a816SJohn Birrell * Handle double-colon in optstring ("a::(longa)") The old 237*2be1a816SJohn Birrell * getopt() accepts it and treats it as a required argument. 238*2be1a816SJohn Birrell */ 239*2be1a816SJohn Birrell while ((cp > 0) && (cp < il) && (optstring.charAt(cp) == ':')) { 240*2be1a816SJohn Birrell --cp; 241*2be1a816SJohn Birrell } 242*2be1a816SJohn Birrell } while (cp < il); 243*2be1a816SJohn Birrell return -1; 244*2be1a816SJohn Birrell } 245*2be1a816SJohn Birrell 246*2be1a816SJohn Birrell /** 247*2be1a816SJohn Birrell * Get the current option value. 248*2be1a816SJohn Birrell */ 249*2be1a816SJohn Birrell public String getOptarg()250*2be1a816SJohn Birrell getOptarg() 251*2be1a816SJohn Birrell { 252*2be1a816SJohn Birrell return optarg; 253*2be1a816SJohn Birrell } 254*2be1a816SJohn Birrell 255*2be1a816SJohn Birrell /** 256*2be1a816SJohn Birrell * Get the index of the next option to be parsed. 257*2be1a816SJohn Birrell */ 258*2be1a816SJohn Birrell public int getOptind()259*2be1a816SJohn Birrell getOptind() 260*2be1a816SJohn Birrell { 261*2be1a816SJohn Birrell return optind; 262*2be1a816SJohn Birrell } 263*2be1a816SJohn Birrell 264*2be1a816SJohn Birrell /** 265*2be1a816SJohn Birrell * Gets the command-line arguments. 266*2be1a816SJohn Birrell */ 267*2be1a816SJohn Birrell public String[] getArgv()268*2be1a816SJohn Birrell getArgv() 269*2be1a816SJohn Birrell { 270*2be1a816SJohn Birrell // No defensive copy: Getopt is expected to modify the given 271*2be1a816SJohn Birrell // args array. 272*2be1a816SJohn Birrell return args; 273*2be1a816SJohn Birrell } 274*2be1a816SJohn Birrell 275*2be1a816SJohn Birrell /** 276*2be1a816SJohn Birrell * Gets the aggregated short option that just failed. Since long 277*2be1a816SJohn Birrell * options can't be aggregated, a failed long option can be obtained 278*2be1a816SJohn Birrell * by {@code getArgv()[getOptind() - 1]}. 279*2be1a816SJohn Birrell */ 280*2be1a816SJohn Birrell public int getOptopt()281*2be1a816SJohn Birrell getOptopt() 282*2be1a816SJohn Birrell { 283*2be1a816SJohn Birrell return optopt; 284*2be1a816SJohn Birrell } 285*2be1a816SJohn Birrell 286*2be1a816SJohn Birrell /** 287*2be1a816SJohn Birrell * Set to {@code false} to suppress diagnostic messages to stderr. 288*2be1a816SJohn Birrell */ 289*2be1a816SJohn Birrell public void setOpterr(boolean err)290*2be1a816SJohn Birrell setOpterr(boolean err) 291*2be1a816SJohn Birrell { 292*2be1a816SJohn Birrell opterr = err; 293*2be1a816SJohn Birrell } 294*2be1a816SJohn Birrell 295*2be1a816SJohn Birrell /** 296*2be1a816SJohn Birrell * Gets the next option character, or -1 if there are no more 297*2be1a816SJohn Birrell * options. If getopt() encounters a short-option character or a 298*2be1a816SJohn Birrell * long-option string not described in the {@code optionString} 299*2be1a816SJohn Birrell * argument to the constructor, it returns the question-mark (?) 300*2be1a816SJohn Birrell * character. If it detects a missing option-argument, it also 301*2be1a816SJohn Birrell * returns the question-mark (?) character, unless the first 302*2be1a816SJohn Birrell * character of the {@code optionString} argument was a colon (:), 303*2be1a816SJohn Birrell * in which case getopt() returns the colon (:) character. 304*2be1a816SJohn Birrell * <p> 305*2be1a816SJohn Birrell * This implementation swaps the positions of options and 306*2be1a816SJohn Birrell * non-options in the given argv array. 307*2be1a816SJohn Birrell */ 308*2be1a816SJohn Birrell public int getopt()309*2be1a816SJohn Birrell getopt() 310*2be1a816SJohn Birrell { 311*2be1a816SJohn Birrell char c; 312*2be1a816SJohn Birrell int cp; 313*2be1a816SJohn Birrell boolean longopt; 314*2be1a816SJohn Birrell StringRef longoptarg = new StringRef(); 315*2be1a816SJohn Birrell 316*2be1a816SJohn Birrell /* 317*2be1a816SJohn Birrell * Has the end of the options been encountered? The following 318*2be1a816SJohn Birrell * implements the SUS requirements: 319*2be1a816SJohn Birrell * 320*2be1a816SJohn Birrell * If, when getopt() is called: 321*2be1a816SJohn Birrell * - the first character of argv[optind] is not '-' 322*2be1a816SJohn Birrell * - argv[optind] is the string "-" 323*2be1a816SJohn Birrell * getopt() returns -1 without changing optind if 324*2be1a816SJohn Birrell * - argv[optind] is the string "--" 325*2be1a816SJohn Birrell * getopt() returns -1 after incrementing optind 326*2be1a816SJohn Birrell */ 327*2be1a816SJohn Birrell if (_sp == 1) { 328*2be1a816SJohn Birrell boolean nonOption; 329*2be1a816SJohn Birrell do { 330*2be1a816SJohn Birrell nonOption = false; 331*2be1a816SJohn Birrell if (optind >= argc || args[optind].equals("-")) { 332*2be1a816SJohn Birrell return EOF; 333*2be1a816SJohn Birrell } else if (args[optind].equals("--")) { 334*2be1a816SJohn Birrell ++optind; 335*2be1a816SJohn Birrell return EOF; 336*2be1a816SJohn Birrell } else if (args[optind].charAt(0) != '-') { 337*2be1a816SJohn Birrell // non-option: here we deviate from the SUS requirements 338*2be1a816SJohn Birrell // by not quitting, and instead move non-options to the 339*2be1a816SJohn Birrell // end of the args array 340*2be1a816SJohn Birrell nonOption = true; 341*2be1a816SJohn Birrell String tmp = args[optind]; 342*2be1a816SJohn Birrell if (optind + 1 < args.length) { 343*2be1a816SJohn Birrell System.arraycopy(args, optind + 1, args, optind, 344*2be1a816SJohn Birrell args.length - (optind + 1)); 345*2be1a816SJohn Birrell args[args.length - 1] = tmp; 346*2be1a816SJohn Birrell } 347*2be1a816SJohn Birrell --argc; 348*2be1a816SJohn Birrell } 349*2be1a816SJohn Birrell } while (nonOption); 350*2be1a816SJohn Birrell } 351*2be1a816SJohn Birrell 352*2be1a816SJohn Birrell /* 353*2be1a816SJohn Birrell * Getting this far indicates that an option has been encountered. 354*2be1a816SJohn Birrell * Note that the syntax of optstring applies special meanings to 355*2be1a816SJohn Birrell * the characters ':' and '(', so they are not permissible as 356*2be1a816SJohn Birrell * option letters. A special meaning is also applied to the ')' 357*2be1a816SJohn Birrell * character, but its meaning can be determined from context. 358*2be1a816SJohn Birrell * Note that the specification only requires that the alnum 359*2be1a816SJohn Birrell * characters be accepted. 360*2be1a816SJohn Birrell * 361*2be1a816SJohn Birrell * If the second character of the argument is a '-' this must be 362*2be1a816SJohn Birrell * a long-option, otherwise it must be a short option. Scan for 363*2be1a816SJohn Birrell * the option in optstring by the appropriate algorithm. Either 364*2be1a816SJohn Birrell * scan will return an index to the short-option character in 365*2be1a816SJohn Birrell * optstring if the option is found and -1 otherwise. 366*2be1a816SJohn Birrell * 367*2be1a816SJohn Birrell * For an unrecognized long-option, optopt will equal 0, but 368*2be1a816SJohn Birrell * since long-options can't aggregate the failing option can be 369*2be1a816SJohn Birrell * identified by argv[optind-1]. 370*2be1a816SJohn Birrell */ 371*2be1a816SJohn Birrell optopt = c = args[optind].charAt(_sp); 372*2be1a816SJohn Birrell optarg = null; 373*2be1a816SJohn Birrell longopt = (_sp == 1 && c == '-'); 374*2be1a816SJohn Birrell if (!(longopt 375*2be1a816SJohn Birrell ? ((cp = parselong(optstring, args[optind].substring(2), 376*2be1a816SJohn Birrell longoptarg)) != -1) 377*2be1a816SJohn Birrell : ((cp = parseshort(optstring, c)) != -1))) { 378*2be1a816SJohn Birrell err("%s: illegal option -- %s", c, 379*2be1a816SJohn Birrell (longopt ? args[optind] : null)); 380*2be1a816SJohn Birrell /* 381*2be1a816SJohn Birrell * Note: When the long option is unrecognized, optopt will 382*2be1a816SJohn Birrell * be '-' here, which matches the specification. 383*2be1a816SJohn Birrell */ 384*2be1a816SJohn Birrell if (args[optind].length() == ++_sp || longopt) { 385*2be1a816SJohn Birrell ++optind; 386*2be1a816SJohn Birrell _sp = 1; 387*2be1a816SJohn Birrell } 388*2be1a816SJohn Birrell return '?'; 389*2be1a816SJohn Birrell } 390*2be1a816SJohn Birrell optopt = c = optstring.charAt(cp); 391*2be1a816SJohn Birrell 392*2be1a816SJohn Birrell /* 393*2be1a816SJohn Birrell * A valid option has been identified. If it should have an 394*2be1a816SJohn Birrell * option-argument, process that now. SUS defines the setting 395*2be1a816SJohn Birrell * of optarg as follows: 396*2be1a816SJohn Birrell * 397*2be1a816SJohn Birrell * 1. If the option was the last character in an element of 398*2be1a816SJohn Birrell * argv, then optarg contains the next element of argv, and 399*2be1a816SJohn Birrell * optind is incremented by 2. If the resulting value of 400*2be1a816SJohn Birrell * optind is not less than argc, this indicates a missing 401*2be1a816SJohn Birrell * option-argument, and getopt() returns an error indication. 402*2be1a816SJohn Birrell * 403*2be1a816SJohn Birrell * 2. Otherwise, optarg points to the string following the 404*2be1a816SJohn Birrell * option character in that element of argv, and optind is 405*2be1a816SJohn Birrell * incremented by 1. 406*2be1a816SJohn Birrell * 407*2be1a816SJohn Birrell * The second clause allows -abcd (where b requires an 408*2be1a816SJohn Birrell * option-argument) to be interpreted as "-a -b cd". 409*2be1a816SJohn Birrell * 410*2be1a816SJohn Birrell * Note that the option-argument can legally be an empty string, 411*2be1a816SJohn Birrell * such as: 412*2be1a816SJohn Birrell * command --option= operand 413*2be1a816SJohn Birrell * which explicitly sets the value of --option to nil 414*2be1a816SJohn Birrell */ 415*2be1a816SJohn Birrell if (cp + 1 < optstring.length() && optstring.charAt(cp + 1) == ':') { 416*2be1a816SJohn Birrell // The option takes an argument 417*2be1a816SJohn Birrell if (!longopt && ((_sp + 1) < args[optind].length())) { 418*2be1a816SJohn Birrell optarg = args[optind++].substring(_sp + 1); 419*2be1a816SJohn Birrell } else if (longopt && (longoptarg.get() != null)) { 420*2be1a816SJohn Birrell /* 421*2be1a816SJohn Birrell * The option argument was explicitly set to the empty 422*2be1a816SJohn Birrell * string on the command line (--option=) 423*2be1a816SJohn Birrell */ 424*2be1a816SJohn Birrell optind++; 425*2be1a816SJohn Birrell optarg = longoptarg.get(); 426*2be1a816SJohn Birrell } else if (++optind >= argc) { 427*2be1a816SJohn Birrell err("%s: option requires an argument -- %s", c, 428*2be1a816SJohn Birrell (longopt ? args[optind - 1] : null)); 429*2be1a816SJohn Birrell _sp = 1; 430*2be1a816SJohn Birrell optarg = null; 431*2be1a816SJohn Birrell return (optstring.charAt(0) == ':' ? ':' : '?'); 432*2be1a816SJohn Birrell } else 433*2be1a816SJohn Birrell optarg = args[optind++]; 434*2be1a816SJohn Birrell _sp = 1; 435*2be1a816SJohn Birrell } else { 436*2be1a816SJohn Birrell // The option does NOT take an argument 437*2be1a816SJohn Birrell if (longopt && (longoptarg.get() != null)) { 438*2be1a816SJohn Birrell // User supplied an arg to an option that takes none 439*2be1a816SJohn Birrell err("%s: option doesn't take an argument -- %s", (char)0, 440*2be1a816SJohn Birrell (longopt ? args[optind] : null)); 441*2be1a816SJohn Birrell optarg = longoptarg.set(null).get(); 442*2be1a816SJohn Birrell c = '?'; 443*2be1a816SJohn Birrell } 444*2be1a816SJohn Birrell 445*2be1a816SJohn Birrell if (longopt || args[optind].length() == ++_sp) { 446*2be1a816SJohn Birrell _sp = 1; 447*2be1a816SJohn Birrell ++optind; 448*2be1a816SJohn Birrell } 449*2be1a816SJohn Birrell optarg = null; 450*2be1a816SJohn Birrell } 451*2be1a816SJohn Birrell return (c); 452*2be1a816SJohn Birrell } 453*2be1a816SJohn Birrell } 454