/* 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")) { 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 if (!strcmp(opt, "xdev")) { if (val) eprintf("-W option \"%s\" should not have an associated value", opt); config->recursive = 1; config->xdev = 1; } else if (!strcmp(opt, "no-xdev")) { if (val) eprintf("-W option \"%s\" should not have an associated value", opt); config->xdev = 0; } else if (!strcmp(opt, "xlink")) { if (val) eprintf("-W option \"%s\" should not have an associated value", opt); config->recursive = 1; config->xlink = 1; } else if (!strcmp(opt, "no-xlink")) { if (val) eprintf("-W option \"%s\" should not have an associated value", opt); config->xlink = 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; }