blob: 226f74db8bc7d80be43b543533607eae8f5aa190 [file] [log] [blame]
/*
* Copyright (c), Edward Thomson <[email protected]>
* All rights reserved.
*
* This file is part of adopt, distributed under the MIT license.
* For full terms and conditions, see the included LICENSE file.
*
* THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT.
*
* This file was produced by using the `rename.pl` script included with
* adopt. The command-line specified was:
*
* ./rename.pl cli_opt --filename=opt --include=common.h --inline=GIT_INLINE --header-guard=CLI_opt_h__ --lowercase-status --without-usage
*/
#ifndef CLI_opt_h__
#define CLI_opt_h__
#include <stdio.h>
#include <stdint.h>
/**
* The type of argument to be parsed.
*/
typedef enum {
CLI_OPT_TYPE_NONE = 0,
/**
* An option that, when specified, sets a given value to true.
* This is useful for options like "--debug". A negation
* option (beginning with "no-") is implicitly specified; for
* example "--no-debug". The `value` pointer in the returned
* option will be set to `1` when this is specified, and set to
* `0` when the negation "no-" option is specified.
*/
CLI_OPT_TYPE_BOOL,
/**
* An option that, when specified, sets the given `value` pointer
* to the specified `switch_value`. This is useful for booleans
* where you do not want the implicit negation that comes with an
* `CLI_OPT_TYPE_BOOL`, or for switches that multiplex a value, like
* setting a mode. For example, `--read` may set the `value` to
* `MODE_READ` and `--write` may set the `value` to `MODE_WRITE`.
*/
CLI_OPT_TYPE_SWITCH,
/**
* An option that, when specified, increments the given
* `value` by the given `switch_value`. This can be specified
* multiple times to continue to increment the `value`.
* (For example, "-vvv" to set verbosity to 3.)
*/
CLI_OPT_TYPE_ACCUMULATOR,
/**
* An option that takes a value, for example `-n value`,
* `-nvalue`, `--name value` or `--name=value`.
*/
CLI_OPT_TYPE_VALUE,
/**
* A bare "--" that indicates that arguments following this are
* literal. This allows callers to specify things that might
* otherwise look like options, for example to operate on a file
* named "-rf" then you can invoke "program -- -rf" to treat
* "-rf" as an argument not an option.
*/
CLI_OPT_TYPE_LITERAL,
/**
* A single argument, not an option. When options are exhausted,
* arguments will be matches in the order that they're specified
* in the spec list. For example, if two `CLI_OPT_TYPE_ARGS` are
* specified, `input_file` and `output_file`, then the first bare
* argument on the command line will be `input_file` and the
* second will be `output_file`.
*/
CLI_OPT_TYPE_ARG,
/**
* A collection of arguments. This is useful when you want to take
* a list of arguments, for example, multiple paths. When specified,
* the value will be set to the first argument in the list.
*/
CLI_OPT_TYPE_ARGS,
} cli_opt_type_t;
/**
* Additional information about an option, including parsing
* restrictions and usage information to be displayed to the end-user.
*/
typedef enum {
/** Defaults for the argument. */
CLI_OPT_USAGE_DEFAULT = 0,
/** This argument is required. */
CLI_OPT_USAGE_REQUIRED = (1u << 0),
/**
* This is a multiple choice argument, combined with the previous
* argument. For example, when the previous argument is `-f` and
* this optional is applied to an argument of type `-b` then one
* of `-f` or `-b` may be specified.
*/
CLI_OPT_USAGE_CHOICE = (1u << 1),
/**
* This argument short-circuits the remainder of parsing.
* Useful for arguments like `--help`.
*/
CLI_OPT_USAGE_STOP_PARSING = (1u << 2),
/** The argument's value is optional ("-n" or "-n foo") */
CLI_OPT_USAGE_VALUE_OPTIONAL = (1u << 3),
/** This argument should not be displayed in usage. */
CLI_OPT_USAGE_HIDDEN = (1u << 4),
/** In usage, show the long format instead of the abbreviated format. */
CLI_OPT_USAGE_SHOW_LONG = (1u << 5),
} cli_opt_usage_t;
typedef enum {
/** Default parsing behavior. */
CLI_OPT_PARSE_DEFAULT = 0,
/**
* Parse with GNU `getopt_long` style behavior, where options can
* be intermixed with arguments at any position (for example,
* "file1 --help file2".) Like `getopt_long`, this can mutate the
* arguments given.
*/
CLI_OPT_PARSE_GNU = (1u << 0),
/**
* Force GNU `getopt_long` style behavior; the `POSIXLY_CORRECT`
* environment variable is ignored.
*/
CLI_OPT_PARSE_FORCE_GNU = (1u << 1),
} cli_opt_flag_t;
/** Specification for an available option. */
typedef struct cli_opt_spec {
/** Type of option expected. */
cli_opt_type_t type;
/** Name of the long option. */
const char *name;
/** The alias is the short (one-character) option alias. */
const char alias;
/**
* If this spec is of type `CLI_OPT_TYPE_BOOL`, this is a pointer
* to an `int` that will be set to `1` if the option is specified.
*
* If this spec is of type `CLI_OPT_TYPE_SWITCH`, this is a pointer
* to an `int` that will be set to the opt's `switch_value` (below)
* when this option is specified.
*
* If this spec is of type `CLI_OPT_TYPE_ACCUMULATOR`, this is a
* pointer to an `int` that will be incremented by the opt's
* `switch_value` (below). If no `switch_value` is provided then
* the value will be incremented by 1.
*
* If this spec is of type `CLI_OPT_TYPE_VALUE`,
* `CLI_OPT_TYPE_VALUE_OPTIONAL`, or `CLI_OPT_TYPE_ARG`, this is
* a pointer to a `char *` that will be set to the value
* specified on the command line.
*
* If this spec is of type `CLI_OPT_TYPE_ARGS`, this is a pointer
* to a `char **` that will be set to the remaining values
* specified on the command line.
*/
void *value;
/**
* If this spec is of type `CLI_OPT_TYPE_SWITCH`, this is the value
* to set in the option's `value` pointer when it is specified. If
* this spec is of type `CLI_OPT_TYPE_ACCUMULATOR`, this is the value
* to increment in the option's `value` pointer when it is
* specified. This is ignored for other opt types.
*/
int switch_value;
/**
* Optional usage flags that change parsing behavior and how
* usage information is shown to the end-user.
*/
uint32_t usage;
/**
* The name of the value, provided when creating usage information.
* This is required only for the functions that display usage
* information and only when a spec is of type `CLI_OPT_TYPE_VALUE,
* `CLI_OPT_TYPE_ARG` or `CLI_OPT_TYPE_ARGS``.
*/
const char *value_name;
/**
* Optional short description of the option to display to the
* end-user. This is only used when creating usage information.
*/
const char *help;
} cli_opt_spec;
/** Return value for `cli_opt_parser_next`. */
typedef enum {
/** Parsing is complete; there are no more arguments. */
CLI_OPT_STATUS_DONE = 0,
/**
* This argument was parsed correctly; the `opt` structure is
* populated and the value pointer has been set.
*/
CLI_OPT_STATUS_OK = 1,
/**
* The argument could not be parsed correctly, it does not match
* any of the specifications provided.
*/
CLI_OPT_STATUS_UNKNOWN_OPTION = 2,
/**
* The argument matched a spec of type `CLI_OPT_VALUE`, but no value
* was provided.
*/
CLI_OPT_STATUS_MISSING_VALUE = 3,
/** A required argument was not provided. */
CLI_OPT_STATUS_MISSING_ARGUMENT = 4,
} cli_opt_status_t;
/** An option provided on the command-line. */
typedef struct cli_opt {
/** The status of parsing the most recent argument. */
cli_opt_status_t status;
/**
* The specification that was provided on the command-line, or
* `NULL` if the argument did not match an `cli_opt_spec`.
*/
const cli_opt_spec *spec;
/**
* The argument as it was specified on the command-line, including
* dashes, eg, `-f` or `--foo`.
*/
char *arg;
/**
* If the spec is of type `CLI_OPT_VALUE` or `CLI_OPT_VALUE_OPTIONAL`,
* this is the value provided to the argument.
*/
char *value;
/**
* If the argument is of type `CLI_OPT_ARGS`, this is the number of
* arguments remaining. This value is persisted even when parsing
* is complete and `status` == `CLI_OPT_STATUS_DONE`.
*/
size_t args_len;
} cli_opt;
/* The internal parser state. Callers should not modify this structure. */
typedef struct cli_opt_parser {
const cli_opt_spec *specs;
char **args;
size_t args_len;
unsigned int flags;
/* Parser state */
size_t idx;
size_t arg_idx;
size_t in_args;
size_t in_short;
unsigned int needs_sort : 1,
in_literal : 1;
} cli_opt_parser;
/**
* Parses all the command-line arguments and updates all the options using
* the pointers provided. Parsing stops on any invalid argument and
* information about the failure will be provided in the opt argument.
*
* This is the simplest way to parse options; it handles the initialization
* (`parser_init`) and looping (`parser_next`).
*
* @param opt The The `cli_opt` information that failed parsing
* @param specs A NULL-terminated array of `cli_opt_spec`s that can be parsed
* @param args The arguments that will be parsed
* @param args_len The length of arguments to be parsed
* @param flags The `cli_opt_flag_t flags for parsing
*/
cli_opt_status_t cli_opt_parse(
cli_opt *opt,
const cli_opt_spec specs[],
char **args,
size_t args_len,
unsigned int flags);
/**
* Quickly executes the given callback for each argument.
*
* @param specs A NULL-terminated array of `cli_opt_spec`s that can be parsed
* @param args The arguments that will be parsed
* @param args_len The length of arguments to be parsed
* @param flags The `cli_opt_flag_t flags for parsing
* @param callback The callback to invoke for each specified option
* @param callback_data Data to be provided to the callback
*/
int cli_opt_foreach(
const cli_opt_spec specs[],
char **args,
size_t args_len,
unsigned int flags,
int (*callback)(cli_opt *, void *),
void *callback_data);
/**
* Initializes a parser that parses the given arguments according to the
* given specifications.
*
* @param parser The `cli_opt_parser` that will be initialized
* @param specs A NULL-terminated array of `cli_opt_spec`s that can be parsed
* @param args The arguments that will be parsed
* @param args_len The length of arguments to be parsed
* @param flags The `cli_opt_flag_t flags for parsing
*/
void cli_opt_parser_init(
cli_opt_parser *parser,
const cli_opt_spec specs[],
char **args,
size_t args_len,
unsigned int flags);
/**
* Parses the next command-line argument and places the information about
* the argument into the given `opt` data.
*
* @param opt The `cli_opt` information parsed from the argument
* @param parser An `cli_opt_parser` that has been initialized with
* `cli_opt_parser_init`
* @return true if the caller should continue iterating, or 0 if there are
* no arguments left to process.
*/
cli_opt_status_t cli_opt_parser_next(
cli_opt *opt,
cli_opt_parser *parser);
/**
* Prints the status after parsing the most recent argument. This is
* useful for printing an error message when an unknown argument was
* specified, or when an argument was specified without a value.
*
* @param file The file to print information to
* @param command The name of the command to use when printing (optional)
* @param opt The option that failed to parse
* @return 0 on success, -1 on failure
*/
int cli_opt_status_fprint(
FILE *file,
const char *command,
const cli_opt *opt);
#endif /* CLI_opt_h__ */