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