diff options
Diffstat (limited to '')
-rw-r--r-- | opts.c | 130 |
1 files changed, 130 insertions, 0 deletions
@@ -0,0 +1,130 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +static int +sizeopt(size_t *valp, const char *s) +{ + if (isdigit(*s)) + return 0; + *valp = 0; + for (; isdigit(*s); s++) { + if (*valp * 10U + (size_t)(*s & 15) > SIZE_MAX) + *valp = SIZE_MAX; + else + *valp = *valp * 10U + (size_t)(*s & 15); + } + return !*s; +} + + +int +parseopt_vendor(void *config_, char *opt, char *val) +{ + struct config *config = config_; + if (!strcmp(opt, "output")) { + if (!val) + eprintf("-W option \"%s\" should have an associated value", opt); + config->format &= (enum format)~FORMAT_MASK; + if (!strcmp(val, "lowercase")) + config->format |= LOWERCASE_HEX; + else if (!strcmp(val, "uppercase")) + config->format |= UPPERCASE_HEX; + else if (!strcmp(val, "binary")) + config->format |= BINARY; + else + eprintf("-W option \"%s\" expected value \"lowercase\", \"uppercase\", or \"binary\"", opt); + + } else if (!strcmp(opt, "input")) { + if (!val) + eprintf("-W option \"%s\" should have an associated value", opt); + config->format &= (enum format)~FORMAT_MASK; + if (!strcmp(val, "binary") || !strcmp(val, "text")) + config->hexinput = 0; + else if (!strcmp(val, "hexadecimal")) + config->hexinput = 1; + else + eprintf("-W option \"%s\" expected value \"binary\", \"text\", or \"hexadecimal\"", opt); + + } else if (!strcmp(opt, "threads")) { + if (!val) + eprintf("-W option \"%s\" should have an associated value", opt); + if (!strcmp(val, "auto")) + config->threads = 0; + else if (!sizeopt(&config->threads, val) || !config->threads) + eprintf("-W option \"%s\" expected positive integer value or \"auto\"", opt); + + } else if (!strcmp(opt, "recursive")) { + /* TODO the default behaviour should be to not traverse across mount points, + * not to not follow symbolic links, however this should be tweakable */ + if (!val) + eprintf("-W option \"%s\" should not have an associated value", opt); + config->recursive = 1; + + } else if (!strcmp(opt, "no-recursive")) { + if (!val) + eprintf("-W option \"%s\" should not have an associated value", opt); + config->recursive = 0; + + } else { + return 0; + } + return 1; +} + + +char * +parseopts(void *config, char *string, int (*parseopt)(void *, char *opt, char *val)) +{ + char *opt, *r = string, c, *val; + char *w = string; + size_t brackets = 0; + + for (;;) { + opt = r; + while (*r && *r != ',' && *r != '=') + r++; + for (; *r; r++) { + if (*r == '[' || *r == '(' || *r == '{') + brackets++; + else if (brackets && (*r == ']' || *r == ')' || *r == '}')) + brackets--; + else if (!brackets && (*r == ',' || *r == '=')) + break; + } + c = *r; + *r++ = '\0'; + val = NULL; + if (c == '=') { + val = r; + for (; *r; r++) { + if (*r == '[' || *r == '(' || *r == '{') + brackets++; + else if (brackets && (*r == ']' || *r == ')' || *r == '}')) + brackets--; + else if (!brackets && *r == ',') + break; + } + c = *r; + *r++ = '\0'; + } + + if (!(*parseopt)(config, opt, val)) { + if (*opt || val) { + if (w != string) + *w++ = ','; + w = stpcpy(w, opt); + if (val) { + *w++ = '='; + w = stpcpy(w, val); + } + } + } + + if (!c) + break; + } + + *w = '\0'; + return string; +} |