aboutsummaryrefslogblamecommitdiffstats
path: root/opts.c
blob: 7805897556480eeb3e4e8ccc8ddaccf27d39104b (plain) (tree)
























































                                                                                                                    
                        



                                                                                             
                        


                                                                                             





















                                                                                             





























































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