Precisely, this library:
(Suppose that a program supports three long-named options "--html", "--html-false" and "--html-true". For various incomple options given, the library behaves as intuitively as possible, for example, "--html-f" is considered "--html-false", "--html" is recognized as it is and "--html-" results in a warning for its ambiguity. This feature is called "abbreviated names for long-named options.")
The Option Parsing Library reserves identifiers starting with opt_
and OPT_
, and imports no other libraries except for the standard library.
"Program arguments" or "arguments" for brevity refer to anything given to a program being executed.
"Operands" refer to arguments not starting with a hyphen character or to "-" that denotes the standard input stream. These are sometimes referred to as "non-option arguments."
"Options" refer to arguments starting with a hyphen character but excluding "-". "Short-named options" are options that start with a single hyphen and have a single character following as in "-x"; several short-named options can be grouped after a hyphen as in "-xyz" which is equivalent to "-x -y -z". "Long-named options" are options that start with two hyphens and have a non-empty character sequence following; for example, "--long-option".
If an option takes an additional argument which may immediately follow (possibly with an intervening equal sign) or appear as a separate argument, the argument is called an "option-argument." For long-named options, option-arguments must follow an equal sign unless they appear as separate ones. (See IEEE Std 1003.1, 2004 Edition, 12. Utility Conventions.)
The storage used to parse program arguments is managed by the library.
util -a -b inputfile outputfile util inputfile -a outputfile -b
This behavior canned "argument permutation," in most cases, helps users to flexibly place options among operands. Some programs, however, require options always proceed operands; for example, given the following line,
util -a util2 -b
it might be wanted to interpret this as giving "-a" to "util" but "-b" to "util2" which cannot be achieved with argument permutation. For such a case, this library provdes two modes to keep the order in which options and operands are given: the POSIX-compliant mode and the "return-in-order" mode which are denoted by REQUIRE_ORDER
and RETURN_IN_ORDER
in a typical implementation of getopt().
In the POSIX-compliant mode, parsing options stops immediately whenever an operand is encountered. This behavior is what POSIX requires, as its name implies.
In the "return-in-order" mode, encountering operands makes the character valued 1 returned as if the operand is an option-argument for the option whose short name has the value 1.
This ordering mode can be controlled by marking a desired ordering mode in an option description table or setting an environment variable (see opt_t
).
opt_t
for more detailed explanation.After the library initialized, opt_parse() insepcts each program argument and performs what specified by the option description table for it. In most cases, this process is made up of a loop containing jumps based on the return value of opt_parse().
As opt_prase() reports that all options have been inspected, a program is granted an access to remaining non-option arguments. These operands are inspected as if they were only arguments to the program.
Since opt_init() allocates storages for duplicating pointers to program arguments, opt_free() should be invoked in order to avoid memory leakage after handling operands has finished.
opt_abort() is a function that stops recognization of options being performed by conf_parse(). All remaining options are regarded as operands. It is useful when a program introduces an option stopper like "--" for its own purposes.
opt.c contains an example designed to use as many facilities of the library as possible in a disabled part and a bolierplate code that is a simplified version of the example is given here:
static struct { const char *prgname; int verbose; ... } option; int main(int argc, char *argv[]) { opt_t tab[] = { "verbose", 0, &(option.verbose), 1, "add", 'a', OPT_ARG_NO, OPT_TYPE_NO, "create", 'c', OPT_ARG_REQ, OPT_TYPE_STR, "number", 'n', OPT_ARG_OPT, OPT_TYPE_REAL, "help", UCHAR_MAX+1, OPT_ARG_NO, OPT_TYPE_NO, NULL, } option.prgname = opt_init(tab, &argc, &argv, &argptr, PRGNAME, '/'); if (!option.prgname) { fprintf(stderr, "%s: failed to parse options\n", PRGNAME); return EXIT_FAILURE; } while ((c = opt_parse()) != -1) { switch(c) { case 'a': ... --add or -a given ... break; case 'c': printf("%s: option -c given with value '%s'\n, option.prgname, (const char *)argptr); break; case 'n': printf("%s: option -n given", option.prgname); if (argptr) printf(" with value '%f'\n", *(const double *)argptr); else putchar('\n'); break; case UCHAR_MAX+1: printf("%s: option --help given\n", option.prgname); opt_free(); return 0; case 0: break; case '?': case '-': case '+': case '*': fprintf(stderr, "%s: ", option.prgname); fprintf(stderr, opt_errmsg(c), (const char *)argptr); opt_free(); return EXIT_FAILURE; default: assert(!"not all options covered -- should never reach here"); break; } } if (option.verbose) puts("verbose flag is set"); if (argc > 1) { printf("non-option ARGV-arguments:"); for (i = 1; i < argc; i++) printf(" %s", argv[i]); putchar('\n'); } opt_free(); return 0; }
The struct object option
manages all objects set by program arguments. Note that it has the static storage duration; since its member is used as an initializer for the option description table that is an array, it has to have the static storage duration; C99 has removed this restriction.
Each row in the option description table specifies options to recognize:
Because the failure of opt_init() means that memory allocation failed, you do not have to call opt_free() before terminating the program.
The case labes above one handling 0 are for options given in tab
. Those labels below them are for exceptional cases and opt_errmsg() helps to construct appropriate messages for them. In addtion, there are other ways to handle those cases; see opt_errmsg() for details. Remember that, if invoked, opt_free() should be invoked after all program arguments including non-option arguments have been processed. Since opt_init() makes copies of pointers in argv
and opt_free() releases storages for them, any access to them gets invalidated by opt_free().
Any comments about the library are welcomed. If you have a proposal or question on the library just email me, and then I will reply as soon as possible.
This package is an option parser implementation by Jun Woong. The implementation was written so as to conform with the Standard C published by ISO 9899:1990 and ISO 9899:1999.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.