Sometimes you may want to have an option which takes suboptions as
arguments. You can do this through the subopts
field of the
MU_OPT
structure. The subopts
field is a list of
MU_OPT
s, terminated by a suboption with all fields equal to
0
. Suboptions are in every way like regular options, except that
they may not have suboptions of their own and they must use the
subopt_name
field instead of short_opt
or
long_opt
. See Option Structure.
Suboptions may also specify the env_var
field for an equivalent
environment variables as well. Environment variables may also take
suboptions as a value. See Parsing the Environment.
Note: even though environment variables may be specified for
suboptions, you may not have a suboption which only specifies an
environment variable. I.e., you may not have a suboption which has no
subopt_name
field (such an option will be considered as a
terminator for the suboption list). If you want to do this, use a
regular option instead.
Options which take suboptions as arguments may use the
callback_subopt
field as a callback (see Option Callbacks). If a callback is used and the option is found on the
command line (or in the environment for an environment variable), the
callback for that option is guaranteed to be called before any
callbacks for the suboptions themselves. Note, however, that if a
suboption has an equivalent environment variable (using the
env_var
field), the callback for the option which takes that
suboption as an argument will not be called at all (though the
callback for the suboption will be called). Indeed, it is impossible to
call the callback for the option which takes the suboption as an
argument, because two different options with different callbacks may
take the same suboptions as arguments. Nor would it make any sense,
because the option never actually appeared on the command line (or
environment).
Suboptions are specified as a comma-separated list, with ‘=’ used to specify arguments. The commas must not contain spaces around them, and arguments cannot be specified any other way than with ‘=’.
Suboptions, like long options, may be abbreviated as long as they are
not ambiguous. Note that this is in contrast to getsubopt
, which
does not allow abbreviation (see (libc)Suboptions).
Like regular options, suboptions should use the help
field, which
will be used in the help message (see Formatting Help and
Option Structure). Suboptions may also use the arg_help
field if they take arguments (see Option Arguments).
Normally, suboptions are parsed by mu_parse_opts
from an argument
to a regular option, using the subopts
field. However, you may
also parse suboptions in a user-specified string as well. Doing so is
not too dissimilar from parsing regular options.
This is an opaque context for parsing suboptions. It is allocated using
mu_subopt_context_new
and freed using mu_opt_context_free
.
MU_SUBOPT_CONTEXT *
mu_subopt_context_new (const char *prog_name, const char *suboptstr,
¶const MU_OPT *subopts)
Allocate and return a new suboption parsing context. The name the
program was invoked as should be passed in prog_name (normally
argv[0]
), and is used for error reporting.
The suboptions will be parsed in suboptstr. A copy of
suboptstr will be made, so you need not worry about it going out
of scope or being modified (this copy will be freed by
mu_subopt_context_free
). The suboptions are specified in
subopts.
int
mu_subopt_context_free (MU_SUBOPT_CONTEXT *context)
¶Free the suboption context, context. Callback data is freed as for
mu_opt_context_free
(see Parsing Options and Environment). Like mu_opt_context_free
,
mu_subopt_context_free
will return nonzero if any of the
destructors returned nonzero, or zero if all destructors returned
zero. Also like mu_opt_context_free
, all destructors are called
even if one or more of them return nonzero.
int
mu_parse_subopts (MU_SUBOPT_CONTEXT *context)
¶Parse the suboptions given in context. Use
mu_subopt_context_new
(see above) to create the context. Zero is
returned on success, or an error code on error (see Option Parsing Errors).
Note that you may not call this function more than once. To do so is an error and will be diagnosed.
The following example illustrates the use of suboptions:
#include <stdio.h> #include <mu/options.h> #include <mu/safe.h> /* For mu_opt_context_x* */ int subopt_none(void *data, char *err) { puts("suboption found: none"); return 0; } int subopt_opt(int has_arg, const char *arg, void *data, char *err) { puts("suboption found: opt"); if (has_arg) printf("argument: %s\n", arg); return 0; } int subopt_req(int has_arg, const char *arg, void *data, char *err) { printf("suboption found: req\nargument: %s\n", arg); return 0; } int main(int argc, char **argv) { int ret; /* These are the suboptions that can be passed to the `-o' option. They are specified just like regular options, except that `subopt_name' is used instead of `long_opt' or `short_opt', and they may not have suboptions of their own. */ const MU_OPT suboptions[] = { { .subopt_name = "none", .has_arg = MU_OPT_NONE, .callback_none = subopt_none, .help = "a suboption taking no arguments" }, { .subopt_name = "opt", .has_arg = MU_OPT_OPTIONAL, .arg_type = MU_OPT_STRING, .callback_string = subopt_opt, .help = "a suboption taking an optional argument" }, { .subopt_name = "req", .has_arg = MU_OPT_REQUIRED, .arg_type = MU_OPT_STRING, .callback_string = subopt_req, .help = "a suboption taking a required argument" }, { 0 } }; const MU_OPT options[] = { { .short_opt = "o", .long_opt = "options", .has_arg = MU_OPT_REQUIRED, .arg_type = MU_OPT_SUBOPT, .subopts = suboptions, .help = "a regular option which takes suboptions" }, { 0 } }; MU_OPT_CONTEXT *context; context = mu_opt_context_xnew(argc, argv, options, MU_OPT_PERMUTE); /* Add the help option. */ mu_opt_context_add_help(context, NULL, NULL, "Parse suboptions.", NULL, "1", NULL, NULL, NULL); mu_opt_context_xadd_help_options(context, MU_HELP_BOTH); /* Parse the options. */ ret = mu_parse_opts(context); mu_opt_context_xfree(context); if (MU_OPT_ERR(ret)) return 1; return 0; }
And here is the output of the example program (note, the COLUMNS
environment variable is set to 65 so that the help message will look
good in this manual):
$ COLUMNS=65 $ export COLUMNS $ ./subopts -o none,opt=foo -| suboption found: none -| suboption found: opt -| argument: foo $ ./subopts -o req error→ ./subopts: 'req': suboption requires argument $ ./subopts --help -| Usage: ./subopts [OPTION]... -| Parse suboptions. -| -| Mandatory arguments to long options are mandatory for short options too. -| -o, --options=SUBOPTS a regular option which takes suboptions -| -h, --help[=plain|man] print this help in plain text format if 'plain', or as a man(1) page if -| 'man'; if the argument is omitted, it will default to 'plain'. -| -| Suboptions for -o, --options: -| none a suboption taking no arguments -| opt[=STRING] a suboption taking an optional argument -| req=STRING a suboption taking a required argument