NAME
loadopt - parse options from command-line and (optionally) configuration file
SYNOPSIS
#include <limb/loadopt.h>
int loadopt(stralloc *sa, int argc, const char **argv, const struct option *options, int dirfd, const char *confdir, unsigned int poflags, struct loadopt *ctx) const char *LO_ARG(struct loadopt *ctx) size_t *LO_OFF*(struct loadopt *ctx) u16 *LO_CUR*(struct loadopt *ctx) int *LO_IDX*(struct loadopt *ctx) int *LO_FROMFILE*(struct loadopt *ctx)
DESCRIPTION
The loadopt
() function parses command-line arguments. Then, if confdir
is
not NULL, it will try to load any options that hasn't been set yet nor marked
OPT_SKIP from the configuration directory confdir
. If confdir
describes a
relative path, it is relative to the directory associated with the file
descriptor dirfd
, which may be AT_FDCWD to use the current working
directory.
After that it ensures any option marked as required (via OPT_REQ) has been set, then may check for non-options arguments.
The actual parsing of options is done through parseopt(3), as such many of the
arguments to loadopt
() are the same as to parseopt(3), namely argc
,
argv
, options
and flags
. Refer to parseopt(3) for more on those.
It is important to note, however, that the member flags
of struct option is
relevant here : it allows to define option-specific flags. Specifically, its
value is constructed as a bitwise-inclusive OR of the following :
OPT_SKIP
To indicate this option shall not be set from configuration directory, i.e. can only be used from command-line.
OPT_REQ
To indicate this option is required, i.e. error out if after having parsed all command-line options (and, optionally, options set in configuration directory), the option has not been set. Mostly useful with options that require an argument.
OPT_SA
The value of the option's argument will be appended into the stralloc sa
,
and available through the macro LO_OFF(), indicating the offset at which
it begins. When used, the macro LO_ARG() will always return NULL.
This can be useful if the argument's value must be kept after option parsing,
even when the option is set from configuration directory.
Additionally, in case some pre-processing is applied, see below.
OPT_ESC
Implies OPT_SA. If the option's argument is within double-quotes ("
) then
it will be un-escaped (as described in esc_scan(3)) before being placed
into sa
, thus ensuring the available value is always ready for use.
OPT_PATH
Implies OPT_ESC. Ensures that the (possibly unescaped) value does not contain any NUL byte, and is thusly a valid path name.
OPT_FILE
Implies OPT_PATH. Ensures that the (possibly unescaped) value does not
contain any slashes (/
), and is thusly a valid file name only.
OPT_RPT
Can only be used for the last-defined argument, not options. It indicates
that this argument can be "repeated", i.e. from this position (in argv
) on,
any and all further arguments are processed as this one.
The last argument ctx
is an opaque structure that should be initialized to
LOADOPT_ZERO.
The stralloc pointed by sa
is required when confdir
is not NULL, as it
will be used as temporary space to read files as needed. If at also required if
at least one element of options
has its OPT_SA flag set.
Accessing information is done through macros LO_ARG
(), LO_IDX
() and
LO_CUR
(), which are similar to their parseopt(3) counterparts PO_ARG(),
PO_IDX() and PO_CUR() respectively.
Additionally, macro LO_OFF
() must be used when OPT_SA was set, as described
above, and macro LO_FROMFILE
() will return 1 when the current option came
from configuration directory, zero otherwise (i.e. from command-line).
Configuration Directory
When called, loadopt
() will first defer to parseopt(3) to handle parsing of
command-line arguments. Once done, if confdir
was specified (i.e. is not
NULL) and the corresponding directory exists, it will be read and options
loaded from it.
That is, for every option that hasn't been set nor marked via OPT_SKIP it will
try and read the first line of a file whose name is that of the full long
option name (member longopt
). Anything after the first newline (\n
) is
ignored (can be thought of as comments).
The content of the first line, if any, is treated as is as the option's argument (no trimming is performed, though the actual newline byte is obviously not included), and process happens just as it would for an option specified on command-line.
You can use LO_FROMFILE
() to know whether an option was specified on
command-line or from configuration directory
Note that when an option was specified on configuration directory, its
argument, if any, will not be preserved/remain valid once parsing the option
is done. Thus, if its value is needed for later use it needs to be copied.
An easy way to achieve this is using the OPT_SA flag, to have it placed into
the stralloc sa
automatically (whether or not it comes from configuration
directory).
Command-line Arguments
Lastly, loadopt
() can perform some (minimal) checking for post-options
arguments on the command line once parsing of all options has been successful,
which includes making sure all options marked required were indeed found
(either from file or on command-line).
For this to happen, you need to specify a special element in the array options
by the macro LOADOPT_ARGUMENTS. Every element after it will be handled as
referring to an argument instead of an option.
Note that LOADOPT_ARGUMENTS can be the first element of the array, if there
are no options.
For elements referring to arguments, member shortopt
is ignored. The longopt
member is only used in warnings to the user, to refer to said argument.
The important member is arg
which is treated as defining whether the
argument is required (ARG_REQ) or optional (ARG_OPT). If required and no
argument was given on command-line, an error occurs. If optional and not
specified, loadopt
() successfully ends, returning 0.
To define them, you can use the following convenience macros :
ARGUMENT_OPT(name
, flags
, id
)
To define argument arg
as optional
ARGUMENT_REQ(name
, flags
, id
)
To define argument arg
as required
The actual parsing/handling of arguments is no different than of options,
loadopt
() will return the corresponding id
(which must be valid as described
above for options, with the exception that OPTID_SHORTOPT cannot be used), the
same macros are to be used.
Flags can also be used, so it is possible to have arguments' values be copied
into the stralloc sa
automatically, unescaped if needed and checked. Note
however that OPT_SKIP and OPT_REQ cannot be used here.
Finally, after all such argument definitions in the array options
, you must
terminate it with either one of the macros LOADOPT_DONE or LOADOPT_STOP.
If the later was specified, loadopt
() ends successfully regardless of whether
more arguments were specified on command-line or not. With the former however,
any more arguments will result in an error for "too many arguments".
LOADOPT_DONE is actually the same as OPTION_DONE as described from parseopt(3).
Note that either of those can be specified even without any actual arguments, i.e. as last element right after all the options, but must always be specified as last element.
Argument Repeating
It is possible, instead of using one of LOADOPT_DONE or LOADOPT_STOP, to set the flag OPT_RPT in the last argument. In which case any more argument specified on command-line will be processed as such an argument, over & over until all command-line has been parsed.
RETURN VALUE
If an option was successfully found, loadopt
() returns the option's id
if
non-zero, else its shortopt
. When all options, and, optionally, arguments,
have been successfully parsed it returns 0.
If an error occurs, loadopt
() returns -1 and sets errno
to indicate the
error.
Warnings may be emitted on error unless PARSEOPT_SILENT was set in flags
.
Refer to parseopt(3) for more.
ERRORS
The loadopt
() function may fail if :
ENOMEM
Not enough memory to read from configuration directory.
ENOKEY
A required option was missing/not specified.
ENODATA
A required argument was missing/not specified.
ETOOMANYREFS
Too many arguments were specified.
The loadopt
() function may also fail for any of the errors specified for
parseopt(3), readdir(3) and readopt(3), save for ENOBUFS.
SEE ALSO
autoopt(3), readopt(3)