4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * ident "%Z%%M% %I% %E% SMI"
29 /* Copyright (c) 1988 AT&T */
30 /* All Rights Reserved */
32 import java.io.StringWriter;
33 import java.io.PrintWriter;
36 * A Java port of Solaris {@code lib/libc/port/gen/getopt.c}, which is a
37 * port of System V UNIX getopt. See <b>getopt(3C)</b> and SUS/XPG
38 * getopt() for function definition and requirements. Unlike that
39 * definition, this implementation moves non-options to the end of the
40 * argv array rather than quitting at the first non-option.
43 static final int EOF = -1;
45 private String progname;
46 private String[] args;
48 private String optstring;
49 private int optind = 0; // args index
50 private int optopt = 0;
51 private String optarg = null;
52 private boolean opterr = true;
55 * _sp is required to keep state between successive calls to
56 * getopt() while extracting aggregated short-options (ie: -abcd).
61 * Creates a {Code Getopt} instance to parse the given command-line
62 * arguments. Modifies the given args array by swapping the
63 * positions of non-options and options so that non-options appear
64 * at the end of the array.
66 public Getopt(String programName, String[] args,
69 progname = programName;
70 // No defensive copy; Getopt is expected to modify the given
73 argc = this.args.length;
74 optstring = optionString;
81 if (progname == null) {
82 throw new NullPointerException("program name is null");
85 for (String s : args) {
87 throw new NullPointerException("null arg at index " + i);
91 if (optstring == null) {
92 throw new NullPointerException("option string is null");
96 private static class StringRef {
114 * Generalized error processing method. If the optstr parameter is
115 * null, the character c is converted to a string and displayed
119 err(String format, char c, String optstr)
121 if (opterr && optstring.charAt(0) != ':') {
122 StringWriter w = new StringWriter();
123 PrintWriter p = new PrintWriter(w);
124 p.printf(format, progname, (optstr == null ?
125 Character.toString(c) : optstr.substring(2)));
126 System.err.println(w.toString());
131 * Determine if the specified character (c) is present in the string
132 * (optstring) as a regular, single character option. If the option
133 * is found, return an index into optstring where the short-option
134 * character is found, otherwise return -1. The characters ':' and
135 * '(' are not allowed.
138 parseshort(String optstring, char c)
140 if (c == ':' || c == '(') {
145 int len = optstring.length();
146 for (int i = 0; i < len; ++i) {
147 ch = optstring.charAt(i);
152 while (i < len && ch == '(') {
153 for (++i; i < len && (ch = optstring.charAt(i)) != ')'; ++i);
161 * Determine if the specified string (opt) is present in the string
162 * (optstring) as a long-option contained within parenthesis. If the
163 * long-option specifies option-argument, return a reference to it
164 * in longoptarg. Otherwise set the longoptarg reference to null.
165 * If the option is found, return an index into optstring at the
166 * position of the short-option character associated with the
167 * long-option; otherwise return -1.
169 * @param optstring the entire optstring passed to the {@code
170 * Getopt} constructor
171 * @param opt the long option read from the command line
172 * @param longoptarg the value of the option is returned in this
173 * parameter, if an option exists. Possible return values in
176 * <li><b>NULL:</b> No argument was found</li>
177 * <li><b>empty string (""):</b> Argument was explicitly left empty
178 * by the user (e.g., --option= )</li>
179 * <li><b>valid string:</b> Argument found on the command line</li>
181 * @return index to equivalent short-option in optstring, or -1 if
182 * option not found in optstring.
185 parselong(String optstring, String opt, StringRef longoptarg)
187 int cp; // index into optstring, beginning of one option spec
188 int ip; // index into optstring, traverses every char
189 char ic; // optstring char
190 int il; // optstring length
191 int op; // index into opt
193 int ol; // opt length
194 boolean match; // true if opt is matching part of optstring
196 longoptarg.set(null);
198 il = optstring.length();
201 ic = optstring.charAt(ip);
202 if (ic != '(' && ++ip == il)
204 ic = optstring.charAt(ip);
205 if (ic == ':' && ++ip == il)
207 ic = optstring.charAt(ip);
213 while (ip < il && (ic = optstring.charAt(ip)) != ')' &&
215 oc = opt.charAt(op++);
216 match = (ic == oc && match);
220 if (match && ip < il && ic == ')' && (op >= ol ||
221 opt.charAt(op) == '=')) {
222 if (op < ol && opt.charAt(op) == '=') {
223 /* may be an empty string - OK */
224 longoptarg.set(opt.substring(op + 1));
226 longoptarg.set(null);
230 if (ip < il && ic == ')' && ++ip == il)
232 ic = optstring.charAt(ip);
236 * Handle double-colon in optstring ("a::(longa)") The old
237 * getopt() accepts it and treats it as a required argument.
239 while ((cp > 0) && (cp < il) && (optstring.charAt(cp) == ':')) {
247 * Get the current option value.
256 * Get the index of the next option to be parsed.
265 * Gets the command-line arguments.
270 // No defensive copy: Getopt is expected to modify the given
276 * Gets the aggregated short option that just failed. Since long
277 * options can't be aggregated, a failed long option can be obtained
278 * by {@code getArgv()[getOptind() - 1]}.
287 * Set to {@code false} to suppress diagnostic messages to stderr.
290 setOpterr(boolean err)
296 * Gets the next option character, or -1 if there are no more
297 * options. If getopt() encounters a short-option character or a
298 * long-option string not described in the {@code optionString}
299 * argument to the constructor, it returns the question-mark (?)
300 * character. If it detects a missing option-argument, it also
301 * returns the question-mark (?) character, unless the first
302 * character of the {@code optionString} argument was a colon (:),
303 * in which case getopt() returns the colon (:) character.
305 * This implementation swaps the positions of options and
306 * non-options in the given argv array.
314 StringRef longoptarg = new StringRef();
317 * Has the end of the options been encountered? The following
318 * implements the SUS requirements:
320 * If, when getopt() is called:
321 * - the first character of argv[optind] is not '-'
322 * - argv[optind] is the string "-"
323 * getopt() returns -1 without changing optind if
324 * - argv[optind] is the string "--"
325 * getopt() returns -1 after incrementing optind
331 if (optind >= argc || args[optind].equals("-")) {
333 } else if (args[optind].equals("--")) {
336 } else if (args[optind].charAt(0) != '-') {
337 // non-option: here we deviate from the SUS requirements
338 // by not quitting, and instead move non-options to the
339 // end of the args array
341 String tmp = args[optind];
342 if (optind + 1 < args.length) {
343 System.arraycopy(args, optind + 1, args, optind,
344 args.length - (optind + 1));
345 args[args.length - 1] = tmp;
353 * Getting this far indicates that an option has been encountered.
354 * Note that the syntax of optstring applies special meanings to
355 * the characters ':' and '(', so they are not permissible as
356 * option letters. A special meaning is also applied to the ')'
357 * character, but its meaning can be determined from context.
358 * Note that the specification only requires that the alnum
359 * characters be accepted.
361 * If the second character of the argument is a '-' this must be
362 * a long-option, otherwise it must be a short option. Scan for
363 * the option in optstring by the appropriate algorithm. Either
364 * scan will return an index to the short-option character in
365 * optstring if the option is found and -1 otherwise.
367 * For an unrecognized long-option, optopt will equal 0, but
368 * since long-options can't aggregate the failing option can be
369 * identified by argv[optind-1].
371 optopt = c = args[optind].charAt(_sp);
373 longopt = (_sp == 1 && c == '-');
375 ? ((cp = parselong(optstring, args[optind].substring(2),
377 : ((cp = parseshort(optstring, c)) != -1))) {
378 err("%s: illegal option -- %s", c,
379 (longopt ? args[optind] : null));
381 * Note: When the long option is unrecognized, optopt will
382 * be '-' here, which matches the specification.
384 if (args[optind].length() == ++_sp || longopt) {
390 optopt = c = optstring.charAt(cp);
393 * A valid option has been identified. If it should have an
394 * option-argument, process that now. SUS defines the setting
395 * of optarg as follows:
397 * 1. If the option was the last character in an element of
398 * argv, then optarg contains the next element of argv, and
399 * optind is incremented by 2. If the resulting value of
400 * optind is not less than argc, this indicates a missing
401 * option-argument, and getopt() returns an error indication.
403 * 2. Otherwise, optarg points to the string following the
404 * option character in that element of argv, and optind is
407 * The second clause allows -abcd (where b requires an
408 * option-argument) to be interpreted as "-a -b cd".
410 * Note that the option-argument can legally be an empty string,
412 * command --option= operand
413 * which explicitly sets the value of --option to nil
415 if (cp + 1 < optstring.length() && optstring.charAt(cp + 1) == ':') {
416 // The option takes an argument
417 if (!longopt && ((_sp + 1) < args[optind].length())) {
418 optarg = args[optind++].substring(_sp + 1);
419 } else if (longopt && (longoptarg.get() != null)) {
421 * The option argument was explicitly set to the empty
422 * string on the command line (--option=)
425 optarg = longoptarg.get();
426 } else if (++optind >= argc) {
427 err("%s: option requires an argument -- %s", c,
428 (longopt ? args[optind - 1] : null));
431 return (optstring.charAt(0) == ':' ? ':' : '?');
433 optarg = args[optind++];
436 // The option does NOT take an argument
437 if (longopt && (longoptarg.get() != null)) {
438 // User supplied an arg to an option that takes none
439 err("%s: option doesn't take an argument -- %s", (char)0,
440 (longopt ? args[optind] : null));
441 optarg = longoptarg.set(null).get();
445 if (longopt || args[optind].length() == ++_sp) {