diff options
Diffstat (limited to 'tools/getopt.c')
| -rw-r--r-- | tools/getopt.c | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/tools/getopt.c b/tools/getopt.c deleted file mode 100644 index 5277ed0..0000000 --- a/tools/getopt.c +++ /dev/null @@ -1,358 +0,0 @@ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "getopt.h" - -/* - * Standard getopt global variables. optreset starts as non-zero in order to - * trigger initialization behaviour. - */ -const char * optarg = NULL; -int optind = 1; -int opterr = 1; -int optreset = 1; - -/* - * Quasi-internal global variables -- these are used via GETOPT macros. - */ -const char * getopt_dummy = "(dummy)"; -int getopt_initialized = 0; - -/* - * Internal variables. - */ -static const char * cmdname = NULL; -static struct opt { - const char * os; - size_t olen; - int hasarg; -} * opts = NULL; -static size_t nopts; -static size_t opt_missing; -static size_t opt_default; -static size_t opt_found; -static const char * packedopts; -static char popt[3]; -static int atexit_registered = 0; - -/* Print a message. */ -#define PRINTMSG(...) do { \ - if (cmdname != NULL) \ - fprintf(stderr, "%s: ", cmdname); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ -} while (0) - -/* Print an error message and die. */ -#define DIE(...) do { \ - PRINTMSG(__VA_ARGS__); \ - abort(); \ -} while (0) - -/* Print a warning, if warnings are enabled. */ -#define WARN(...) do { \ - if (opterr == 0) \ - break; \ - if (opt_missing != opt_default) \ - break; \ - PRINTMSG(__VA_ARGS__); \ -} while (0) - -/* Free allocated options array. */ -static void -atexit_handler(void) -{ - - free(opts); - opts = NULL; -} - -/* Reset internal state. */ -static void -reset(int argc, char * const argv[]) -{ - const char * p; - - /* If we have arguments, stash argv[0] for error messages. */ - if (argc > 0) { - /* Find the basename, without leading directories. */ - for (p = cmdname = argv[0]; *p != '\0'; p++) { - if (*p == '/') - cmdname = p + 1; - } - } - - /* Discard any registered command-line options. */ - free(opts); - opts = NULL; - - /* Register atexit handler if we haven't done so already. */ - if (!atexit_registered) { - atexit(atexit_handler); - atexit_registered = 1; - } - - /* We will start scanning from the first option. */ - optind = 1; - - /* We're not in the middle of any packed options. */ - packedopts = NULL; - - /* We haven't found any option yet. */ - opt_found = (size_t)(-1); - - /* We're not initialized yet. */ - getopt_initialized = 0; - - /* Finished resetting state. */ - optreset = 0; -} - -/* Search for an option string. */ -static size_t -searchopt(const char * os) -{ - size_t i; - - /* Scan the array of options. */ - for (i = 0; i < nopts; i++) { - /* Is there an option in this slot? */ - if (opts[i].os == NULL) - continue; - - /* Does this match up to the length of the option string? */ - if (strncmp(opts[i].os, os, opts[i].olen)) - continue; - - /* Do we have <option>\0 or <option>= ? */ - if ((os[opts[i].olen] == '\0') || (os[opts[i].olen] == '=')) - return (i); - } - - /* Not found. */ - return (opt_default); -} - -const char * -getopt(int argc, char * const argv[]) -{ - const char * os = NULL; - const char * canonical_os = NULL; - - /* No argument yet. */ - optarg = NULL; - - /* Reset the getopt state if needed. */ - if (optreset) - reset(argc, argv); - - /* If not initialized, return dummy option. */ - if (!getopt_initialized) - return (GETOPT_DUMMY); - - /* If we've run out of arguments, we're done. */ - if (optind >= argc) - return (NULL); - - /* - * If we're not already in the middle of a packed single-character - * options, see if we should start. - */ - if ((packedopts == NULL) && (argv[optind][0] == '-') && - (argv[optind][1] != '-') && (argv[optind][1] != '\0')) { - /* We have one or more single-character options. */ - packedopts = &argv[optind][1]; - } - - /* If we're processing single-character options, fish one out. */ - if (packedopts != NULL) { - /* Construct the option string. */ - popt[0] = '-'; - popt[1] = *packedopts; - popt[2] = '\0'; - os = popt; - - /* We've done this character. */ - packedopts++; - - /* Are we done with this string? */ - if (*packedopts == '\0') { - packedopts = NULL; - optind++; - } - } - - /* If we don't have an option yet, do we have dash-dash? */ - if ((os == NULL) && (argv[optind][0] == '-') && - (argv[optind][1] == '-')) { - /* If this is not "--\0", it's an option. */ - if (argv[optind][2] != '\0') - os = argv[optind]; - - /* Either way, we want to eat the string. */ - optind++; - } - - /* If we have found nothing which looks like an option, we're done. */ - if (os == NULL) - return (NULL); - - /* Search for the potential option. */ - opt_found = searchopt(os); - - /* If the option is not registered, give up now. */ - if (opt_found == opt_default) { - WARN("unknown option: %s", os); - return (os); - } - - /* The canonical option string is the one registered. */ - canonical_os = opts[opt_found].os; - - /* Does the option take an argument? */ - if (opts[opt_found].hasarg) { - /* - * If we're processing packed single-character options, the - * rest of the string is the argument to this option. - */ - if (packedopts != NULL) { - optarg = packedopts; - packedopts = NULL; - optind++; - } - - /* - * If the option string is <option>=<value>, extract that - * value as the option argument. - */ - if (os[opts[opt_found].olen] == '=') - optarg = &os[opts[opt_found].olen + 1]; - - /* - * If we don't have an argument yet, take one from the - * remaining command line. - */ - if ((optarg == NULL) && (optind < argc)) - optarg = argv[optind++]; - - /* If we still have no option, declare it MIA. */ - if (optarg == NULL) { - WARN("option requires an argument: %s", - opts[opt_found].os); - opt_found = opt_missing; - } - } else { - /* If we have --foo=bar, something went wrong. */ - if (os[opts[opt_found].olen] == '=') { - WARN("option doesn't take an argument: %s", - opts[opt_found].os); - opt_found = opt_default; - } - } - - /* Return the canonical option string. */ - return (canonical_os); -} - -size_t -getopt_lookup(const char * os) -{ - - /* Can't reset here. */ - if (optreset) - DIE("Can't reset in the middle of getopt loop"); - - /* We should only be called after initialization is complete. */ - assert(getopt_initialized); - - /* GETOPT_DUMMY should never get passed back to us. */ - assert(os != GETOPT_DUMMY); - - /* - * Make sure the option passed back to us corresponds to the one we - * found earlier. - */ - assert((opt_found == opt_missing) || (opt_found == opt_default) || - ((opt_found < nopts) && (strcmp(os, opts[opt_found].os) == 0))); - - /* Return the option number we identified earlier. */ - return (opt_found); -} - -void -getopt_register_opt(const char * os, size_t ln, int hasarg) -{ - - /* Can't reset here. */ - if (optreset) - DIE("Can't reset in the middle of getopt loop"); - - /* We should only be called during initialization. */ - assert(!getopt_initialized); - - /* We should have space allocated for registering options. */ - assert(opts != NULL); - - /* We should not have registered an option here yet. */ - assert(opts[ln].os == NULL); - - /* Options should be "-X" or "--foo". */ - if ((os[0] != '-') || (os[1] == '\0') || - ((os[1] == '-') && (os[2] == '\0')) || - ((os[1] != '-') && (os[2] != '\0'))) - DIE("Not a valid command-line option: %s", os); - - /* Make sure we haven't already registered this option. */ - if (searchopt(os) != opt_default) - DIE("Command-line option registered twice: %s", os); - - /* Record option. */ - opts[ln].os = os; - opts[ln].olen = strlen(os); - opts[ln].hasarg = hasarg; -} - -void -getopt_register_missing(size_t ln) -{ - - /* Can't reset here. */ - if (optreset) - DIE("Can't reset in the middle of getopt loop"); - - /* We should only be called during initialization. */ - assert(!getopt_initialized); - - /* Record missing-argument value. */ - opt_missing = ln; -} - -void -getopt_setrange(size_t ln) -{ - size_t i; - - /* Can't reset here. */ - if (optreset) - DIE("Can't reset in the middle of getopt loop"); - - /* We should only be called during initialization. */ - assert(!getopt_initialized); - - /* Allocate space for options. */ - opts = malloc(ln * sizeof(struct opt)); - if ((ln > 0) && (opts == NULL)) - DIE("Failed to allocate memory in getopt"); - - /* Initialize options. */ - for (i = 0; i < ln; i++) - opts[i].os = NULL; - - /* Record the number of (potential) options. */ - nopts = ln; - - /* Record default missing-argument and no-such-option values. */ - opt_missing = opt_default = ln + 1; -} |
