optparse

Summary

This module provides a generic way of describing and parsing command line arguments. Features:

  • Supports both short form (“-k”) and long form (“–key”) options.

  • Supports both mandatory and optional positional arguments.

  • Built-in parsers for most common options/argument types.

  • Automatically formats and prints a help string.

  • Supports custom parsers via callbacks.

  • The parser specification is designed to be read-only so it can be placed in the .text section of a binary (and in an MCU, into the FLASH).

Limitations

  • There is no way to tell that an option was not specified: options have default value and it is generally not possible to tell this value apart from a user supplied value.

  • When using custom actions, a character used as a short option key should NOT be used as a long option key in another rule or else the user callback will not be able to tell them apart (may or may not be an issue.)

Terminology

option

Optional value. Consists of a key an possibly a value. Each type of option has a predefined number of arguments it takes that may be either 0 or 1.

Example: -v --number 5 -k hello

Options (key, value): (v, none), (number, 5), (k, hello)

Options are identified by a string (or character) key.

switch

An option taking 0 values.

(positional) argument:

A value without a key. For example, in -c 3 abcd, abcd is an argument. Arguments can be either mandatory or optional and are identified by an integer index. Because of this, optional arguments must always come AFTER mandatory ones.

short-option

An option that starts with a single dash and consists of a single character. For example -k 78, -c, -f filename.

long-option

An option that starts with two dashes and consists of one or more characters (i.e. a string). For example --echo, --factor 1.5.

Usage

Initialize the required opt_conf and opt_rule structures and call optparse.h::optparse_cmd().

Tips for defining rules

  1. Make an enum with the name of the parameters (options and arguments) and with a last element marking its length:

    enum {HEIGHT, WIDTH, VERBOSE, ETC, .... , N_PARAMETERS
    
  2. Declare const struct opt_rule rules[N_PARAMETERS];

  3. Initialize it. If your compiler supports specifying sub-objects in array and struct/union initializers, they initializer macros can be used. These provide a fail-safe way to construct an array (i.e. they ensure that the correct tags and union elements are set:

    const struct opt_rule rules[N_PARAMETERS] = {
      [WIDTH] = OPTPARSE_O_INT('w', "width", 640, "Display height in px"),
      [HEIGHT] = OPTPARSE_O_INT('h', "height", 480, "Display height in px"),
      ... etc ...
    }
    
  4. Declare and initialize an opt_conf object.

Reference

optparse.h

Command-line argument parser.

OPTPARSE_NO_SHORT
1
'\0'

Used to indicate that an option has no short (i.e. single character) variant.

OPTPARSE_MAX_POSITIONAL
1
UCHAR_MAX

Maximum number of positional arguments supported.

OPTPARSE_IGNORE_ARGV0
1
(1 << OPTPARSE_IGNORE_ARGV0_b)

Indicates if argv[0] should be skipped

OPTPARSE_COLLECT_LAST_POS
1
(1 << OPTPARSE_COLLECT_LAST_POS_b)

If this flag is set, the last positional argument rule is applied to all extra positional arguments (i.e. it “collects” them all)

OPTPARSE_O( type, short_, long_, description, default_value_)
1
2
3
{.action=OPTPARSE_##type, .action_data.option.short_id=(short_), \
	 .action_data.option.long_id=(long_), .desc=(description), \
	 .default_value._OPTPARSE_##type##_INIT = (default_value_)}

Declare an option.

type must be a member of OPTPARSE_ACTIONS, with the “OPTPARSE_” prefix removed. For example:

OPTPARSE_O(SET_BOOL, ‘s’, “set”, “Set a flag ‘s’”, false)

OPTPARSE_P( type, name, description, default_value)
1
_OPTPARSE_P(OPTPARSE_POSITIONAL, type, name, description, default_value)

Declare a mandatory positional argument.

type must be a member of OPTPARSE_POS_ACTIONS, with the “OPTPARSE_POS” prefix removed. For example:

OPTPARSE_P(STR_NOCOPY, “filename”, “Output file”, “whatever.out”)

OPTPARSE_P_OPT( type, name, description, default_value)
1
_OPTPARSE_P(OPTPARSE_POSITIONAL_OPT, type, name, description, default_value)

Declare an optional positional argument.

Like OPTPARSE_P, but it is not an error if the argument is missing. Remember that optional arguments MUST come after mandatory ones on the optparse.h::opt_conf::rules array.

enum OPTPARSE_RESULT
OPTPARSE_OK

Parsing suceeded

OPTPARSE_NOMEM

Not enough memory. Only OPTPARSE_STR or a custom parser may cause this error.

OPTPARSE_BADSYNTAX

Command line is wrongly formed

OPTPARSE_BADCONFIG

The parser configuration is invalid.

OPTPARSE_REQHELP

The help option was requested.

enum OPTPARSE_ACTIONS
OPTPARSE_IGNORE

Ignore a key and its value. Takes 1 argument.

OPTPARSE_CUSTOM_ACTION

Delegate the action to a callback. int _thin_callback(union opt_key key, const char *value, union opt_data *data, const char **msg)

OPTPARSE_UINT

Parse the value as an unsigned int and store it in opt_data::d_uint

OPTPARSE_INT

Parse the value as an int and store it in opt_data::d_int

OPTPARSE_FLOAT

Parse the value as float and store it in opt_data::d_float

OPTPARSE_STR

Make a copy of the value string with strdup() and place it in data::d_str. The string must be deallocated with free().

OPTPARSE_STR_NOCOPY

Place a pointer to the value string in data::d_cstr.

In contrast with OPTPARSE_STR, this does NOT make a copy of the string. It should not be used if the strings will be modified.

OPTPARSE_IGNORE_SWITCH =_OPTPARSE_MAX_NEEDS_VALUE_END

Ignore a switch. Takes 0 arguments

OPTPARSE_SET_BOOL

Set opt_data::d_bool to true. Takes 0 arguments.

OPTPARSE_UNSET_BOOL

Set opt_data::d_bool to false. Takes 0 arguments.

OPTPARSE_COUNT

Count the number of occurences. Increments data::d_int each time the option is found.

OPTPARSE_DO_HELP

Print the following strings, except if they are NULL:

In addition it causes the parser to exit with code OPTPARSE_REQHELP.

OPTPARSE_POSITIONAL =_OPTPARSE_POSITIONAL_START

Indicates that the rule is a mandatory positional argument and not an option.

OPTPARSE_POSITIONAL_OPT

Indicates that the rule is an optional positional argument and not an option.

enum OPTPARSE_POSITIONAL_ACTIONS
OPTPARSE_POS_IGNORE = OPTPARSE_IGNORE
OPTPARSE_POS_COUNT = OPTPARSE_COUNT
OPTPARSE_POS_CUSTOM_ACTION = OPTPARSE_CUSTOM_ACTION
OPTPARSE_POS_UINT = OPTPARSE_UINT
OPTPARSE_POS_INT = OPTPARSE_INT
OPTPARSE_POS_FLOAT = OPTPARSE_FLOAT
OPTPARSE_POS_STR = OPTPARSE_STR
OPTPARSE_POS_STR_NOCOPY = OPTPARSE_STR_NOCOPY
enum OPTPARSE_TUNABLES
OPTPARSE_IGNORE_ARGV0_b
OPTPARSE_COLLECT_LAST_POS_b
uint16_t optparse_tune

Option bitfield

int optparse_cmd(const struct opt_conf * config, union opt_data * result, int argc, const char *const argv)

Main interface to the option parser.

Short options:

A short option that takes a value can be immediately followed by the value in the same argv string. For example “-upeter” would assign “peter” to the “u” option.

Short switches can be merged together like “-xj”.

Dash handling:

A double dash () indicates the parser that there are no more options/ switches and all the remaining command line arguments are to be interpreted as positional arguments

A single dash is interpreted as a positional argument argument.

Optional positional arguments:

Optional positional arguments MUST follow mandatory arguments. The n-th optional argument cannot be set if the (n-1)th optional argument is not set.

Return values

  • Number of positional arguments converted on success, or a negative error code from OPTPARSE_RESULT on error.

void optparse_free_strings(const struct opt_conf * config, union opt_data * result)

Free all strings allocated by OPTPARSE_STR and OPTPARSE_POS_STR.

Note that on a parsing error all strings are automatically deallocated.

This procedure will set all d_str fields to NULL, so it is safe to call it more than once.

struct opt_positionalkey

Identify a positional argument.

unsigned char position

Position (counting from zero) of this argument. Note that options do not contribute to this count. Whether argv[0] is counted depends on the status of OPTPARSE_IGNORE_ARGV0.

const char * name

User-supplied name of this arguments (from opt_rule_t::name) .

union opt_key

Structure to inform user callbacks of the argument or option being parsed.

union opt_data

Value type for options and arguments.

struct opt_rule

Configuration rules for a single command line option.

enum optparse.h::OPTPARSE_ACTIONS action

Parsing type/action. See OPTPARSE_ACTIONS.

enum optparse.h::OPTPARSE_POSITIONAL_ACTIONS pos_action
const char * name
struct opt_rule::@0::@1 argument

Positional handling specification.

If the action is OPTPARSE_POSITIONAL or OPTPARSE_POSITIONAL_OPT, this should hold the required action.

char short_id

Short option name (“-w”), can be OPTPARSE_NO_SHORT.

const char * long_id

Long option name (“–width”), Can be NULL

struct opt_rule::@0::opt_optionkey option
union opt_rule::@0 action_data

Keys for options or action type for positional arguments.

const char * desc

Help description. Can be NULL

union opt_data default_value

Value for when the option is not given.

struct opt_conf

Configuration for the command line parser.

const char * helpstr

Program’s description and general help string.

const struct opt_rule * rules

Array of options.

Optional positional arguments must always come after required ones in the rules array.

int n_rules

Number of elements in rules.

optparse.h::optparse_tune tune

Option bitfield.

Indices and tables