#include #include "config.h" /** * 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. * * License: BSD-MIT * * Example: * // Distributed commandline option registration (note: ccan/opt is better!) * #include * #include * #include * #include * #include * * 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' */ int main(int argc, char *argv[]) { /* Expect exactly one argument */ if (argc != 2) return 1; if (strcmp(argv[1], "depends") == 0) { printf("ccan/compiler\n"); printf("ccan/ptr_valid\n"); return 0; } return 1; }