Browse Source Download (without any required ccan dependencies)
autodata
stash pointers in your binary for automatic registration
This code allows declarations in your source which you can gather together at runtime to form tables. This is often used in place of having a central registration function or table.
Note that this technique does not work in general for shared libaries, only for code compiled into a binary.
// 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'
BSD-MIT