A negatable option is an option which can be specified later on the command line in a different form, to negate the effect of a previous specification. Short options are negated using ‘+’ rather than ‘-’ to specify the option. Long options and suboptions must be prefixed with ‘no-’ or the specified negation prefixes (see Negation Prefixes). For example,
$ prog --foo --no-foo
should act as though --foo were never specified. Only negatable
options can be negated. For an option to be negatable, its
negatable
field must be set to a nonzero value (see Option Structure). Options that take arguments (i.e., options for which the
has_arg
field is not MU_OPT_NONE
) may not be
negated. Indeed, setting the negatable
field to any value
for an option which takes an argument results in undefined behavior.
Environment variables may not be negated. The reason for this is because
it is not easy to control the order in which environment variables
appear. Thus, if environment variable negation were allowed and
FOO
were a negatable environment variable,
$ FOO= NO_FOO= prog
may or may not act as though FOO
were specified. So if an option
for which the negatable
field is nonzero also has a
non-NULL
env_var
field, NO_FOO
will be
ignored. Note, however, that the callback_negatable
callback
should still be used (but it may be better not to use callbacks at all;
see below). Rather than having an env_var
field for a negatable
option, it is instead better to make a separate environment variable
that has a boolean value (see Option Argument Types).
Since environment variables may not be negated, specifying the
negatable
field for an environment variable which has no
equivalent options is useless. Because of this, it is not allowed and
will be diagnosed.
When option parsing is finished, the value that the found_opt
field points to (if any) will be nonzero if the last instance of the
option found on the command line was not negated, or zero if it was
negated.
Negatable options should use the callback_negatable
field if they
are using a callback (see Option Callbacks), although it is usually
preferable not to use a callback. Suppose you have a certain negatable
option, and you want to, say, open a file when it is found. If you used
a callback, you would need to open the file whenever value was
nonzero, and then close it again when it is zero. Although in this case
this would be fairly easy to implement (although far from ideal), it is
still much better to simply wait until option parsing is finished, and
then check the value that the found_opt
field points to.
Here is an example illustrating how to parse negatable options:
#include <stdio.h> #include <mu/options.h> #include <mu/safe.h> /* For mu_opt_context_x{new,free} */ /* Print a message when we find the negatable option. Usually, we shouldn't use a callback for negatable options, but we are just using it to print a message. */ static int print_negatable(int value, void *data, char *err) { printf(" Found the negatable option, and it was%s negated.\n", value ? " not" : ""); return 0; } int main(int argc, char **argv) { int found_negatable; int ret; const MU_OPT options[] = { { .short_opt = "n", .long_opt = "negatable", .has_arg = MU_OPT_NONE, .negatable = 1, .found_opt = &found_negatable, .callback_negatable = print_negatable }, { 0 } }; MU_OPT_CONTEXT *context; /* Parse the options. */ context = mu_opt_context_xnew(argc, argv, options, MU_OPT_PERMUTE); ret = mu_parse_opts(context); mu_opt_context_xfree(context); if (MU_OPT_ERR(ret)) return 1; printf("It appears that the negatable option was%s given.\n", found_negatable ? "" : " not"); return 0; }
Here is the output of the above program:
$ ./option-negatable -| It appears that the negatable option was not given. $ ./option-negatable --negatable -n --no-negatable +n -| Found the negatable option, and it was not negated. -| Found the negatable option, and it was not negated. -| Found the negatable option, and it was negated. -| Found the negatable option, and it was negated. -| It appears that the negatable option was not given. $ ./option-negatable -n +n --negatable -| Found the negatable option, and it was not negated. -| Found the negatable option, and it was negated. -| Found the negatable option, and it was not negated. -| It appears that the negatable option was given.