The long option parser for subcommands

lopsub logo

About lopsub-suite(5) lopsubgen(1) API

API Reference

struct lls_suite Opaque structure which describes a lopsub suite.
struct lls_command Represents one command of a suite.
struct lls_option Represents one option of a command.
struct lls_parse_result An argument vector, fully parsed according to a lopsub command.
struct lls_opt_result The part of a parse result related to a specific option
lls_strerror A strerror-like function for lopsub error codes.
lls_parse Parse an argument vector according to a lopsub command.
lls_free_parse_result Deallocate a parse result.
lls_long_help Return the long help text of a command.
lls_short_help Return the short help text of a command.
lls_lookup_subcmd Tell whether the given string is the name of a subcommand.
lls_cmd Return a pointer to a command structure.
lls_command_name Obtain the name of the command, given a command pointer.
lls_user_data Obtain the application-specific data pointer.
lls_opt_result Extract information about one option from a parse result.
lls_opt Get a reference to an option, given a command and an option number.
lls_opt_given Return how many times an option was given.
lls_string_val Retrieve one argument to a string option.
lls_int32_val Retrieve one argument to an option that takes an int32 argument.
lls_uint32_val Retrieve one argument to an option that takes an uint32 argument.
lls_int64_val Retrieve one argument to an option that takes an int64 argument.
lls_uint64_val Retrieve one argument to an option that takes an uint64 argument.
lls_enum_string_val Get one possible argument value for an option.
lls_num_inputs Get the number of non-option arguments.
lls_input Get a reference to one non-option argument.
lls_version Get the version string of the lopsub library.
lls_purpose Get the line which describes the purpose of a command.
lls_convert_config Transform the contents of a config file into an argument vector.
lls_free_argv Deallocate an argument vector.
lls_check_arg_count Check the number of non-option arguments.
lls_serialize_parse_result Create a buffer from a parse result.
lls_deserialize_parse_result Initialize a parse result from a buffer.
lls_merge Combine two parse results, creating an effective configuration.
lls_dump_parse_result Create contents of a configuration file from a parse result.

struct lls_suite

Opaque structure which describes a lopsub suite.

This structure is defined in the .c file which is generated by lopsubgen(1). The corresponding header file exposes a const pointer to a this structure for use in the application.

Applications can not de-reference this pointer or access its content directly. They must call one of the accessor functions described below.


struct lls_command

Represents one command of a suite.

A command is identified by a suite and a command number. The symbolic names of all commands defined in a suite are exposed in the enumeration defined in the header file which is generated by lopsubgen(1),

Applications can obtain an opaque pointer to a command by calling lls_cmd(), providing the command number and the suite pointer as arguments.


struct lls_option

Represents one option of a command.

Similar to a command, an option is identified by a command and an option number. The header file created by the lopsubgen(1) utility provides an enumeration for all options of each command.

The lls_opt() function returns an opaque pointer to an option, given a command pointer and an option number.


struct lls_parse_result

An argument vector, fully parsed according to a lopsub command.

A pointer to an opaque structure of this type is returned by lls_parse() if the argument vector was found valid for the given command.

Several functions (described below) take a pointer to such a structure. This enables applications to obtain details about the options and arguments that were given in the argument vector, for example whether an option was specified and how many non-options (aka inputs) were given.


struct lls_opt_result

The part of a parse result related to a specific option

Given an option and a parse result, the lls_opt_result() function returns an opaque pointer to a structure of this type which contains information about the option in the argument vector that was used to create the parse result.

A pointer to a structure of this type can be passed to the various accessor functions described below. These functions return information about the option in the argument vector, for example how many times the option was given.


const char * lls_strerror(int lss_errno)

A strerror-like function for lopsub error codes.

This works just like strerror(3).

Return (const char *):


int lls_parse(int argc, char **argv, const struct lls_command *cmd, struct lls_parse_result **lprp, char **errctx)

Parse an argument vector according to a lopsub command.

This function turns a broken-up command line into a parse result, completely parsing all arguments according to the options defined in the given a lopsub command. As usual, options may be given in any order and the special argument "--" forces an end of option-scanning.

For each option defined in the suite, if the multiple flag is set for the option, the parse result contains an array of values, with one value for each time the option was given. Conversely, if the multiple flag is not set, only a single value is stored in the parse result. Those options may still be given multiple times, but only the last given argument is stored while all previous arguments are discarded.

For options which take an integer value, conversion is performed in a way that recognizes an optional base prefix like "0x". The empty string and strings with trailing non-digit characters result in a parse error. Range violations are detected and also cause the function to fail.

The parse_result pointer returned through lprp can be passed to several accessor functions described below in order to obtain information about the options and arguments in argv[].

Return (int):

On success lprp is initialized according to the options that have been parsed successfully. In this case either errctx or *errctx is NULL, so no cleanup needs to be performed in the caller. However, when the caller is no longer interested in the parse result, it should call lls_free_parse_result() to release the memory that was allocated during the call to lls_parse().

On errors, *lprp is set to NULL and the function returns a negative error code. This can happen for various reasons, for example if an invalid option or argument was given. Another possible reason is worth mentioning: when the non-opts-name directive was not specified in the suite, the subcommand is assumed to take no non-option arguments. In this case, lls_parse() fails if the argument vector does contain any non-option arguments.

In the error case, if errctx is not NULL, *errctx points to a zero-terminated string which describes the context of the error condition, for example the problematic element of argv[]. The only exception is when an out of memory condition occurs. In this case *errctx may be NULL because the function was unable to allocate the memory needed for the error context. If *errctx is not NULL, the memory it points to should be freed by the caller. However, lls_free_parse_result() need not be called in this case.


void lls_free_parse_result(struct lls_parse_result *lpr, const struct lls_command *cmd)

Deallocate a parse result.

This frees the memory space allocated by lls_parse().

The parse result pointer must have been returned by a previous call to lls_parse() or lls_serialize_parse_result(). Otherwise, or if lls_free_parse_result has already been called before, undefined behavior occurs. It's OK to pass a NULL pointer though. In this case no action is performed.


char * lls_long_help(const struct lls_command *cmd)

Return the long help text of a command.

The long help text contains the synopsis, the purpose and the help text of the command, followed by the option list including descriptions and help for each option.

Return (char *):


char * lls_short_help(const struct lls_command *cmd)

Return the short help text of a command.

This is similar to lls_long_help() but help texts are omitted from the output.

Return (char *):


int lls_lookup_subcmd(const char *string, const struct lls_suite *suite, char **errctx)

Tell whether the given string is the name of a subcommand.

This tries to match the given string against the subcommands of the suite. Exact matches and unique partial matches count as success.

Return (int):

The lookup fails if (a) the given string pointer is NULL, or (b) if the string is no prefix of any subcommand of the suite, or (c) if it is a proper prefix of more than one subcommand.

On success the error context pointer is set to NULL. In the error case, if errctx is not NULL, *errctx is pointed to a string that must be freed by the caller.


const struct lls_command * lls_cmd(unsigned cmd_num, const struct lls_suite *suite)

Return a pointer to a command structure.

Applications usually call this at the beginning of each function that implements a lopsub command (aka command handler). The returned pointer serves as an abstract reference to the command. This reference is needed to call other functions of the lopsub library, notably lls_parse().

The suite pointer and all valid command numbers are defined in the header file which is generated by lopsubgen(1). Hence this header file must be included from the application to get the name of the suite pointer variable and the command numbers.

Return (const struct lls_command *):

This function always succeeds if both arguments are valid. That is, the command number is a symbolic constant from the LSG_XXX_COMMANDS enumeration of the header file generated by lopsubgen(1), and the suite pointer equals the pointer that is declared in the same header file.

If at least one of the arguments are invalid, the behavior is undefined.


const char * lls_command_name(const struct lls_command *cmd)

Obtain the name of the command, given a command pointer.

Even in situations where the application knows the name of the command, it is less error-prone to call this function rather than to duplicate the command name in the application.

Return (const char *):

This function succeeds unless the given command pointer is invalid (was not obtained through an earlier call to lls_cmd() or is NULL), in which case the behavior is undefined. The return pointer refers to static storage that must not be freed by the caller.


const void * lls_user_data(const struct lls_command *cmd)

Obtain the application-specific data pointer.

Some applications need to store further information for each subcommand, for example a function pointer which refers to the implementation of the subcommand. The optional user data feature allows the application to define a pointer that can be retrieved by calling this function.

Of course storing one function pointer per command could simply be done by defining a suitable array in the application which contains one pointer per (sub)command. However, this approach has the disadvantage that it effectively creates two command lists (one in the suite file and one for the array) that need to be maintained and kept in sync. Moreover, functions can not be declared as static if they are defined in a different source file than the one that defines the array.

Therefore, lopsub offers an alternative: The .c file generated by lopsubgen(1) declares one const void * pointer per command. These pointers are marked with the "weak" attribute (a gcc extension, but also available for clang). This instructs the compiler to store the declaration as a weak symbol in the object file. Since the linker does not require weak symbols to be defined, linking succeeds even if the application chooses to not employ the user data feature.

To make use of the user data feature, the application needs to define one pointer for each command called lsg_xxx_com_yyy_user_data, where xxx is the name of the suite and yyy the name of the command. A suitable preprocessor macro can make this as simple as EXPORT_CMD(foo).

Return (const void *):

If the application did not define a user data pointer for the given command, the function returns NULL.


const struct lls_opt_result * lls_opt_result(unsigned opt_num, const struct lls_parse_result *lpr)

Extract information about one option from a parse result.

The returned pointer can be passed to the accessor functions described below. Those functions let the applications tell how many times the option was given and retrieve any argument(s) for the option.

The header file generated by lopsubgen(1) generates for each command an enumeration which declares one option number per option as a symbolic constant.

Return (const struct lls_opt_result *):

If the parse result pointer is invalid (was not returned by lls_parse(), or is NULL), or the option number does not correspond to the command that was used to create the parse result, the behaviour is undefined. Otherwise this function succeeds.


const struct lls_option * lls_opt(unsigned opt_num, const struct lls_command *cmd)

Get a reference to an option, given a command and an option number.

While an opt_result pointer described above is used to obtain information in an argument vector, the pointer returned by this function allows to obtain information about the option itself.

Applications rarely need to care about the option pointer. It is required to get the possible values of an enumeration option though. See lls_enum_string_val().

Return (const struct lls_option *):

This function always succeeds if both arguments are valid. Otherwise the behavior is undefined.


unsigned lls_opt_given(const struct lls_opt_result *r)

Return how many times an option was given.

This is employed as follows. Applications first call lls_parse() to initialize the parse result, followed by lls_opt_result() to obtain a reference to those parts of the parse result that are related to one specific option. The reference can then be passed to this function to find out how many times the option was given.

Return (unsigned):

Even if the multiple flag was not set for the option, the returned value may be greater than one because this flag only affects how many arguments are stored in the parse result.

This function succeeds unless the opt_result pointer is invalid (was not returned by lls_opt_result(), or is NULL), in which case the behaviour is undefined.


const char * lls_string_val(unsigned idx, const struct lls_opt_result *r)

Retrieve one argument to a string option.

This function may only be called for options which take an optional or required argument of string type. Enum options (which take as their argument one of a fixed, finite set of possible strings), however, are treated as if the option took an argument of uint32 type. Hence this function must not be called for these options.

The first argument must be zero if the multiple flag is not set for the option. Otherwise any number between zero and n - 1 (inclusively) may be passed, where n is the number of times the option was given, that is, the return value of lls_opt_given().

As as special case, if the option was not given at all (i.e., n == 0), it is still OK to call this function with an index value of zero. In this case, the default value for the option will be returned, or NULL if no default value was specified in the suite.

Return (const char *):

The memory referenced by the return pointer is part of the parse result and must not be freed by the caller. It will be freed when lls_free_parse_result() is called.

Undefined behaviour occurs in all of the following cases: (a) the index is out of range, (b) the opt_result pointer is NULL or was not obtained through a previous call to lls_opt_result(), (c) the opt_result pointer corresponds to an option which takes an argument of different type or no argument at all. If none of these conditions apply, the function is guaranteed to succeed.


int32_t lls_int32_val(unsigned idx, const struct lls_opt_result *r)

Retrieve one argument to an option that takes an int32 argument.

This is like lls_string_val(), but for options which take an optional or required argument of type int32.

As for lls_string_val(), a zero index value is considered a valid input even if the option was not given at all. In this case. the default value is returned, or zero if the option has no default value.

Return (int32_t):

Since conversion of the argument to int32_t takes place earlier during lls_parse(), no errors are possible unless the index parameter or the the opt result pointer (or both) are invalid. See above for details.


uint32_t lls_uint32_val(unsigned idx, const struct lls_opt_result *r)

Retrieve one argument to an option that takes an uint32 argument.

Identical to lls_int32_val(), except the argument type of the option and the return value are different.

For enum options, this is the correct function to call in order to obtain the index into the array of possible values, see lls_enum_string_val() below.

Return (uint32_t):


int64_t lls_int64_val(unsigned idx, const struct lls_opt_result *r)

Retrieve one argument to an option that takes an int64 argument.

Identical to lls_int32_val(), except that this function must be used for options which take a 64 bit signed integer argument.

Return (int64_t):


uint64_t lls_uint64_val(unsigned idx, const struct lls_opt_result *r)

Retrieve one argument to an option that takes an uint64 argument.

Identical to lls_int32_val(), except that this function must be used for options which take a 64 bit unsigned integer argument.

Return (uint64_t):


const char * lls_enum_string_val(unsigned idx, const struct lls_option *opt)

Get one possible argument value for an option.

This function must only be called for enum options. That is, options for which the set of possible arguments was defined through the values directive in the suite.

The possible values of an enum option are a property of the option itself and are thus independent of the command line. Therefore this function expects an option pointer rather than a pointer to an opt result.

The index parameter must be a value between zero and the number of possible values minus one, inclusively. This number is declared as the last member of the enumeration for the option, which is defined of the generated header file.

Return (const char *):

Behavior is undefined if the given option is not an enum option, a NULL pointer is passed, or if the index value is out of range.


unsigned lls_num_inputs(const struct lls_parse_result *lpr)

Get the number of non-option arguments.

In addition to options and their arguments, subcommands may accept any number of additional arguments which are not related to any particular option. For example, file names are frequently passed as such non-option arguments (aka inputs).

Passing a NULL pointer to this function results in undefined behaviour.

Return (unsigned):

This function never fails. See also lls_input(), lls_check_arg_count().


const char * lls_input(unsigned idx, const struct lls_parse_result *lpr)

Get a reference to one non-option argument.

If the argument vector passed to lls_parse() contained non-option arguments, the value of each of them can be obtained by calling this function.

The index must be between zero and n-1, inclusively, where n is the number returned by lls_num_inputs(). The parse_result pointer must have been obtained by an earlier call to lls_parse().

Return (const char *):

If the conditions described above are met, the function is guaranteed to succeed. It will never return a NULL pointer in this case.


const char * lls_version(void)

Get the version string of the lopsub library.

The version string is determined at build time from the sha1 of the HEAD git commit or from the name of the top level directory for compiling from a gitweb snapshot.

Return (const char *):

The returned string is of the form <tag>-<d>-g<sha1>, where <tag> is the name of the last tagged commit contained in the HEAD commit, <d> is the number of commits between <tag> and HEAD, and <sha1> is the first four hex digits of the hash of the HEAD commit. If the working tree was dirty at compile time, the string "-dirty" is appended to the version string.

This function always succeeds.


const char * lls_purpose(const struct lls_command *cmd)

Get the line which describes the purpose of a command.

This function is useful for applications which need to print their own command summary rather than employ lls_short_help() and lls_long_help(). One reason for this could be that the application has additional per-command informations which should be included in the command summary.

Return (const char *):

The returned string is the content of the corresponding directive of the suite file, with leading and trailing whitespace removed.


int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd, char ***result, char **errctx)

Transform the contents of a config file into an argument vector.

This function scans the given input buffer to compute an (argc, argv) pair which is suitable to be fed to lls_parse(). The function is config-agnostic. That is, it does not know anything about option names and their type.

Arguments are separated from the option by whitespace and an optional '=' character. Arguments to string options should be enclosed in double quotes and must not spawn multiple lines. Newline or tab characters may be embedded into the argument string with '\n' and '\t'. To embed a backslash, double it. To embed a quote, prefix it with a backslash.

If a subcommand is specified, only the part of the input buffer which is started by a [subcmd] marker is taken into account. Conversely, if a NULL pointer is passed, only the beginning part until the first section marker will be considered. This allows config files to contain options for the supercommand and subcommands.

Return (int):

On success, the number of elements in the computed argument vector is returned. Slot zero of the argument vector is initialized to a dummy value while the remaining values correspond to the options and arguments found in the input buffer. The argument vector should be freed with lls_free_argv() when it is no longer needed.

On failure a negative error code is returned and *result is set to NULL. Several types of failure are possible, including allocation failure, errors from the lexer and various syntax errors.


void lls_free_argv(char **argv)

Deallocate an argument vector.

lls_convert_config() dynamically allocates memory for the argument and for each of its elements. This function frees this memory.

It's OK to pass a NULL pointer, in which case the function does nothing.


int lls_check_arg_count(const struct lls_parse_result *lpr, int min_argc, int max_argc, char **errctx)

Check the number of non-option arguments.

This helper verifies that the number of non-option arguments lies within the specified range. Although this function is kind of trivial, it can help applications to provide nice and consistent error messages.

For the function to succeed, the number of non-option arguments (as returned by lls_num_inputs()) must be greater or equal to min_argc and less or equal to max_argc.

Both min_argc and max_argc may be zero (but not negative), and min_argc must be less or equal to max_argc. The value INT_MAX for max_argc indicates that the number of allowed non-option arguments is unbounded.

Return (int):

Examples:

min_argc = 0, max_argc = 0: no non-option argument may be given.

min_argc = 0, max_argc = INT_MAX: any number of non-option arguments OK.

min_argc = 1, max_argc = 2: either one or two non-option arguments OK.

Behaviour is undefined if min_argc or max_argc is negative, if min_argc is greater than max_argc, or if lpr is invalid.


int lls_serialize_parse_result(const struct lls_parse_result *lpr, const struct lls_command *cmd, char **result, size_t *nbytes)

Create a buffer from a parse result.

This function is handy for passing the result from lls_parse() to a different process.

Depending on the initial value of the result pointer, the function behaves as follows.

(a) If result is NULL, the size required to store the serialized buffer is computed and returned through the nbytes argument, but no serialization takes place.

(b) If result is not NULL, but *result is NULL, a suitable buffer is allocated with malloc() and *result is pointed at this buffer. The caller is responsible for freeing this buffer when it is no longer needed.

(c) If *result is not NULL, the buffer pointed at by *result is assumed be be large enough for the serialized parse result, and this buffer is used to store the result.

Return (int):

See also: lls_deserialize_parse_result().


int lls_deserialize_parse_result(const char *buf, const struct lls_command *cmd, struct lls_parse_result **lprp)

Initialize a parse result from a buffer.

This is the counterpart to lls_serialize_parse_result().

The input buffer should have been obtained through an earlier call to lls_serialize_parse_result().

Return (int):

On success all fields of lpr match the original values. After the call, no fields of *lprp contain references to buf, so buf may safely be freed.


int lls_merge(const struct lls_parse_result *primary, const struct lls_parse_result *secondary, const struct lls_command *cmd, struct lls_parse_result **lprp, char **errctx)

Combine two parse results, creating an effective configuration.

This is useful for applications which receive options from the command line and the configuration file.

Merging works on a per-option basis as follows. If the multiple flag is set for the option, the argument arrays of the primary and the secondary parse result are concatenated and the concatenation is the argument array for the merge result. It the multiple flag is not set, the value of the primary parse result becomes the argument for the merge result.

The two non-option argument arrays are concatenated in the same way as the arguments to options with the multiple flag set.

All arguments are copied from the two input parse results. It is safe to free them after the function returns. The merge result should be freed with lls_parse_result() when it is no longer needed.

Return (int):

The only possible error is an out of memory condition. However, behaviour is undefined if the primary or secondary parse result is NULL, or was not obtained from the given command.


char * lls_dump_parse_result(const struct lls_parse_result *lpr, const struct lls_command *cmd, bool non_default_only)

Create contents of a configuration file from a parse result.

The subcommand marker ([subcommand]) is not included in the output.

If non_default_only is false, options are included in the dump even if they are not given in the parse result. However, flag options are excluded in this case as well as options which take an argument for which no default value has been defined.

Return (char *):

If no options are given, or if every option argument of the parse result matches the default value of the option and non_default_only is true, the function returns the empty string.

The only possible error is an out of memory condition, in which case the NULL pointer is returned. Behaviour is undefined if any of the pointer arguments is NULL, or if the parse result does not match the given command.