From bd22d0e47d0fb203286b088f048cf1aff1fa93a1 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Mon, 22 Jul 2024 23:14:43 +0200 Subject: Nieuw optieontleedsysteem, en migreer weerklank --- src/util/option.h | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/util/option.h (limited to 'src/util/option.h') diff --git a/src/util/option.h b/src/util/option.h new file mode 100644 index 0000000..780a6e9 --- /dev/null +++ b/src/util/option.h @@ -0,0 +1,76 @@ +#pragma once + +#include + + +enum option_spec_kind { + OPTSPECKIND_SETBOOL, + OPTSPECKIND_CALL, + OPTSPECKIND_CALLP, + + OPTSPECKIND_HELPUSAGE, + OPTSPECKIND_VERSION, + + OPTSPECKIND_END, // end of spec list (rest of spec entry ignored) +}; + +// For usage info, see option_parse() below. +struct option_spec { + char optc; // short option character + // TODO: long options? + + // From here, the fields should be filled in using the OPTION_* macros. + enum option_spec_kind kind; + union { + struct { bool *ptr; } setbool; + struct { void (*fun)(void); } call; + struct { void (*fun)(void*); void *data; } callp; + struct { const char *usagestr; } helpusage; + struct {} version; + } spec_sub; +}; + +// Takes a bool* and stores 'true' there if the flag is found. +#define OPTION_SETBOOL(boolptr) \ + OPTSPECKIND_SETBOOL, {.setbool={.ptr=(boolptr)}} + +// Takes a void(*)(void) and calls it every time the flag is found. +#define OPTION_CALL(funptr) \ + OPTSPECKIND_CALL, {.call={.fun=(funptr)}} + +// Takes a void(*)(void*) and a 'void *data', and calls the function with 'data' +// every time the flag is found. +#define OPTION_CALLP(funptr, dataptr) \ + OPTSPECKIND_CALLP, {.callp={.fun=(funptr), .data=(dataptr)}} + +// Takes a printf format string with a single %s, which is substituted (by +// printf) for argv[0]. Prints the formatted string and exits with code 0. +#define OPTION_HELPUSAGE(usagestring) \ + OPTSPECKIND_HELPUSAGE, {.helpusage={.usagestr=(usagestring)}} + +// Prints version of the tool and exits with code 0. +#define OPTION_VERSION() \ + OPTSPECKIND_VERSION, {.version={}} + +// This must be the final entry in the list of option specs; contrary to the +// other OPTION_* macros, it is an _entire_ 'struct option_spec'. +#define OPTION_SPEC_END {'\0', OPTSPECKIND_END, {}} + +// The spec must not contain duplicate entries for the same short option +// character. +// Reshuffles positional arguments to the end of the argument list; returns a +// pointer to the first positional argument after reshuffling. +// +// The specs array is most conveniently declared as a C array: +// +// const struct option_spec[] = { +// {'h', OPTION_HELPUSAGE("Gebruik: %s \n")}, +// {'V', OPTION_VERSION()}, +// OPTION_SPEC_END +// } +// +// The individual option specs should be initialised with a brace-initialiser +// containing the short option character followed by one of the OPTION_* macros, +// as shown in the example above. See the comments above the macros for their +// meaning. End the list with OPTION_SPEC_END. +char** option_parse(int argc, char **argv, const struct option_spec *specs); -- cgit v1.2.3-70-g09d2