/* 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;
}