Example: // Distributed commandline option registration (note: ccan/opt is better!)
#include <ccan/autodata/autodata.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <err.h>
static bool verbose = false;
// This would normally be in a header, so any C file can use it.
struct option {
char c;
bool takes_arg;
bool (*cb)(char *optarg);
};
AUTODATA_TYPE(options, struct option);
#define REGISTER_OPTION(optstruct) \
AUTODATA(options, (optstruct))
// Now a few examples (could be anywhere in source)
static bool verbose_cb(char *unused)
{
verbose = true;
return true;
}
static struct option dash_v = { 'v', false, verbose_cb };
REGISTER_OPTION(&dash_v);
static bool chdir_cb(char *dir)
{
if (verbose)
printf("chdir to %s. ", dir);
if (chdir(dir) != 0)
return false;
return true;
}
static struct option dash_C = { 'C', true, chdir_cb };
REGISTER_OPTION(&dash_C);
int main(int argc, char *argv[])
{
struct option **opts;
size_t i, num;
int o;
char *optstring, *p;
// Gather together all the registered options.
opts = autodata_get(options, &num);
// Make pretty string for getopt().
p = optstring = malloc(num * 2 + 1);
for (i = 0; i < num; i++) {
*(p++) = opts[i]->c;
if (opts[i]->takes_arg)
*(p++) = ':';
}
*p = '\0';
while ((o = getopt(argc, argv, optstring)) != -1) {
if (o == '?')
exit(1);
// Call callback in matching option.
for (i = 0; i < num; i++) {
if (opts[i]->c == o) {
if (!opts[i]->cb(optarg))
err(1, "parsing -%c", o);
break;
}
}
}
// free up gathered option table.
autodata_free(opts);
if (verbose)
printf("verbose mode on\n");
return 0;
}
// Given -v outputs 'verbose mode on'
// Given -v -C / outputs 'chdir to /. verbose mode on'
|