| example | ||
| include | ||
| src | ||
| tests | ||
| .gitignore | ||
| autogen.sh | ||
| configure.ac | ||
| LICENSE | ||
| Makefile.am | ||
| README.md | ||
libcli
A lightweight C library for parsing command-line arguments. Wraps getopt_long
with a descriptor-based API, typed parse utilities, duplicate detection, and
automatic help formatting.
Dependencies
- GCC (uses
__attribute__((unused))) - autoconf ≥ 2.69, automake, libtool
- Criterion — optional, required for
--enable-tests
Build
./autogen.sh
./configure
make
make install
To build and run the test suite:
./configure --enable-tests
make check
Quickstart
#include "cli.h"
#include "cli_parse_utils.h"
#include "compiler.h"
struct config { const char *name; };
static int handle_name(const char *arg, void *cfg) {
((struct config *)cfg)->name = arg;
return CLI_SUCCESS;
}
static int handle_help(const char *arg, void *cfg) {
printf("Usage: myprog [OPTIONS]\n\n");
cli_print_options(g_opts, NB_OPTS, cli_arg_type_to_str);
return CLI_EXIT_SUCCESS;
}
#define OPTIONS_LIST \
X('h', "help", no_argument, handle_help, OPT_ARG_NONE, "Display this help") \
X('n', "name", required_argument, handle_name, OPT_ARG_STRING, "Your name")
#define X(s, l, a, h, t, d) + 1
enum { NB_OPTS = 0 OPTIONS_LIST };
#undef X
#define X(s, l, a, h, t, d) + (1 + (a != no_argument ? 1 : 0))
enum { OPTSTR_LEN = 1 OPTIONS_LIST };
#undef X
#define X(s, l, a, h, t, d) { s, l, a, h, t, d },
static const struct option_descriptor g_opts[] = { OPTIONS_LIST };
#undef X
int main(int argc, char **argv) {
struct config cfg = { .name = "world" };
char opt_str[OPTSTR_LEN + 1];
struct option long_opts[NB_OPTS + 1];
cli_set_prog_name(argv[0]);
if (CLI_SUCCESS != cli_parse(argc, argv, &cfg, g_opts, NB_OPTS, opt_str, long_opts))
return 1;
printf("Hello, %s!\n", cfg.name);
return 0;
}
See example/ for a complete working example.
API
Parsing
enum cli_code cli_parse(int argc, char **argv, void *config,
const struct option_descriptor *opts, size_t nb_opts,
char *opt_str, struct option *long_opts);
Parses argv against the descriptor table opts. Calls each option's handler
with the raw argument string and config. Returns CLI_SUCCESS, CLI_ERROR,
or CLI_EXIT_SUCCESS (handler requested early exit, e.g. --help).
opt_str and long_opts are caller-allocated scratch buffers — size them with
the X-macro pattern shown above.
void cli_set_prog_name(const char *name);
Sets the program name used in error messages. Call with argv[0] before cli_parse.
Option descriptor
struct option_descriptor {
char short_opt; // e.g. 'h'
const char *long_opt; // e.g. "help"
int has_arg; // no_argument / required_argument / optional_argument
t_option_handler handler; // callback: int f(const char *arg, void *config)
int arg_type; // display hint for cli_print_options
const char *description; // displayed by cli_print_options
};
Help
void cli_print_options(const struct option_descriptor *opts, size_t nb_opts,
t_arg_type_to_str to_str);
Prints a formatted options table to stdout. to_str maps arg_type integers
to placeholder strings ("<NUM>", "<STR>", etc.).
const char *cli_arg_type_to_str(int type);
Default to_str implementation covering the built-in types. Pass directly to
cli_print_options if you don't need custom types.
Return codes
| Value | Meaning |
|---|---|
CLI_SUCCESS |
Continue — option handled successfully |
CLI_ERROR |
Abort — invalid option or argument |
CLI_EXIT_SUCCESS |
Abort — clean exit requested (e.g. after printing help) |
Parse utilities
int cli_parse_uint64(const char *s, uint64_t *out); // non-negative integers
int cli_parse_int64(const char *s, int64_t *out); // signed integers (use --opt=-N syntax)
int cli_parse_float(const char *s, float *out); // floats (use --opt=-1.5 syntax)
All return 0 on success, 1 on failure. They reject NULL, empty strings, trailing characters, and out-of-range values.
Custom arg types
The built-in CLI_OPT_ARG_TYPES X-macro covers OPT_ARG_NONE, OPT_ARG_INT,
OPT_ARG_UINT, OPT_ARG_FLOAT, OPT_ARG_STRING. To define custom types with
their own display strings, declare your own list and generate both the enum and
the to_str function from it:
#define MY_ARG_TYPES \
X(OPT_ARG_NONE, "") \
X(OPT_ARG_UINT, "<NUM>") \
X(OPT_ARG_SECONDS, "<SEC>") \
X(OPT_ARG_STRING, "<STR>")
#define X(name, str) name,
enum { MY_ARG_TYPES };
#undef X
static const char *my_arg_type_to_str(int type) {
static const char *strs[] = {
#define X(name, str) str,
MY_ARG_TYPES
#undef X
};
if ((size_t)type < COUNT_OF(strs))
return strs[type];
return "<ARG>";
}
Then pass my_arg_type_to_str to cli_print_options.
Limitations
- Maximum 64 options
License
GPLv3 — see LICENSE.