/*
 * Copyright 2008 Freescale Semiconductor, Inc.
 * Copyright 2013 Wolfgang Denk <wd@denx.de>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*
 * This file provides a shell like 'expr' function to return.
 */

#include <common.h>
#include <config.h>
#include <command.h>

static ulong get_arg(char *s, int w)
{
	ulong *p;

	/*
	 * if the parameter starts with a '*' then assume
	 * it is a pointer to the value we want
	 */

	if (s[0] == '*') {
		p = (ulong *)simple_strtoul(&s[1], NULL, 16);
		switch (w) {
		case 1: return((ulong)(*(uchar *)p));
		case 2: return((ulong)(*(ushort *)p));
		case 4:
		default: return(*p);
		}
	} else {
		return simple_strtoul(s, NULL, 16);
	}
}

#ifdef CONFIG_REGEX

#include <slre.h>

#define SLRE_BUFSZ	16384
#define SLRE_PATSZ	4096

/*
 * memstr - Find the first substring in memory
 * @s1: The string to be searched
 * @s2: The string to search for
 *
 * Similar to and based on strstr(),
 * but strings do not need to be NUL terminated.
 */
static char *memstr(const char *s1, int l1, const char *s2, int l2)
{
	if (!l2)
		return (char *)s1;

	while (l1 >= l2) {
		l1--;
		if (!memcmp(s1, s2, l2))
			return (char *)s1;
		s1++;
	}
	return NULL;
}

static char *substitute(char *string,	/* string buffer */
			int *slen,	/* current string length */
			int ssize,	/* string bufer size */
			const char *old,/* old (replaced) string */
			int olen,	/* length of old string */
			const char *new,/* new (replacement) string */
			int nlen)	/* length of new string */
{
	char *p = memstr(string, *slen, old, olen);

	if (p == NULL)
		return NULL;

	debug("## Match at pos %ld: match len %d, subst len %d\n",
		(long)(p - string), olen, nlen);

	/* make sure replacement matches */
	if (*slen + nlen - olen > ssize) {
		printf("## error: substitution buffer overflow\n");
		return NULL;
	}

	/* move tail if needed */
	if (olen != nlen) {
		int tail, len;

		len = (olen > nlen) ? olen : nlen;

		tail = ssize - (p + len - string);

		debug("## tail len %d\n", tail);

		memmove(p + nlen, p + olen, tail);
	}

	/* insert substitue */
	memcpy(p, new, nlen);

	*slen += nlen - olen;

	return p + nlen;
}

/*
 * Perform regex operations on a environment variable
 *
 * Returns 0 if OK, 1 in case of errors.
 */
static int regex_sub(const char *name,
	const char *r, const char *s, const char *t,
	int global)
{
	struct slre slre;
	char data[SLRE_BUFSZ];
	char *datap = data;
	const char *value;
	int res, len, nlen, loop;

	if (name == NULL)
		return 1;

	if (slre_compile(&slre, r) == 0) {
		printf("Error compiling regex: %s\n", slre.err_str);
		return 1;
	}

	if (t == NULL) {
		value = getenv(name);

		if (value == NULL) {
			printf("## Error: variable \"%s\" not defined\n", name);
			return 1;
		}
		t = value;
	}

	debug("REGEX on %s=%s\n", name, t);
	debug("REGEX=\"%s\", SUBST=\"%s\", GLOBAL=%d\n",
		r, s ? s : "<NULL>", global);

	len = strlen(t);
	if (len + 1 > SLRE_BUFSZ) {
		printf("## error: subst buffer overflow: have %d, need %d\n",
			SLRE_BUFSZ, len + 1);
		return 1;
	}

	strcpy(data, t);

	if (s == NULL)
		nlen = 0;
	else
		nlen = strlen(s);

	for (loop = 0;; loop++) {
		struct cap caps[slre.num_caps + 2];
		char nbuf[SLRE_PATSZ];
		const char *old;
		char *np;
		int i, olen;

		(void) memset(caps, 0, sizeof(caps));

		res = slre_match(&slre, datap, len, caps);

		debug("Result: %d\n", res);

		for (i = 0; i < slre.num_caps; i++) {
			if (caps[i].len > 0) {
				debug("Substring %d: [%.*s]\n", i,
					caps[i].len, caps[i].ptr);
			}
		}

		if (res == 0) {
			if (loop == 0) {
				printf("%s: No match\n", t);
				return 1;
			} else {
				break;
			}
		}

		debug("## MATCH ## %s\n", data);

		if (s == NULL) {
			printf("%s=%s\n", name, t);
			return 1;
		}

		old = caps[0].ptr;
		olen = caps[0].len;

		if (nlen + 1 >= SLRE_PATSZ) {
			printf("## error: pattern buffer overflow: have %d, need %d\n",
				SLRE_BUFSZ, nlen + 1);
			return 1;
		}
		strcpy(nbuf, s);

		debug("## SUBST(1) ## %s\n", nbuf);

		/*
		 * Handle back references
		 *
		 * Support for \0 ... \9, where \0 is the
		 * whole matched pattern (similar to &).
		 *
		 * Implementation is a bit simpleminded as
		 * backrefs are substituted sequentially, one
		 * by one.  This will lead to somewhat
		 * unexpected results if the replacement
		 * strings contain any \N strings then then
		 * may get substitued, too.  We accept this
		 * restriction for the sake of simplicity.
		 */
		for (i = 0; i < 10; ++i) {
			char backref[2] = {
				'\\',
				'0',
			};

			if (caps[i].len == 0)
				break;

			backref[1] += i;

			debug("## BACKREF %d: replace \"%.*s\" by \"%.*s\" in \"%s\"\n",
				i,
				2, backref,
				caps[i].len, caps[i].ptr,
				nbuf);

			for (np = nbuf;;) {
				char *p = memstr(np, nlen, backref, 2);

				if (p == NULL)
					break;

				np = substitute(np, &nlen,
					SLRE_PATSZ,
					backref, 2,
					caps[i].ptr, caps[i].len);

				if (np == NULL)
					return 1;
			}
		}
		debug("## SUBST(2) ## %s\n", nbuf);

		datap = substitute(datap, &len, SLRE_BUFSZ,
				old, olen,
				nbuf, nlen);

		if (datap == NULL)
			return 1;

		debug("## REMAINDER: %s\n", datap);

		debug("## RESULT: %s\n", data);

		if (!global)
			break;
	}
	debug("## FINAL (now setenv()) :  %s\n", data);

	printf("%s=%s\n", name, data);

	return setenv(name, data);
}
#endif

static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	ulong a, b;
	ulong value;
	int w;

	/*
	 * We take 3, 5, or 6 arguments:
	 * 3 : setexpr name value
	 * 5 : setexpr name val1 op val2
	 *     setexpr name [g]sub r s
	 * 6 : setexpr name [g]sub r s t
	 */

	/* > 6 already tested by max command args */
	if ((argc < 3) || (argc == 4))
		return CMD_RET_USAGE;

	w = cmd_get_data_size(argv[0], 4);

	a = get_arg(argv[2], w);

	/* plain assignment: "setexpr name value" */
	if (argc == 3) {
		setenv_hex(argv[1], a);
		return 0;
	}

	/* 5 or 6 args (6 args only with [g]sub) */
#ifdef CONFIG_REGEX
	/*
	 * rexep handling: "setexpr name [g]sub r s [t]"
	 * with 5 args, "t" will be NULL
	 */
	if (strcmp(argv[2], "gsub") == 0)
		return regex_sub(argv[1], argv[3], argv[4], argv[5], 1);

	if (strcmp(argv[2], "sub") == 0)
		return regex_sub(argv[1], argv[3], argv[4], argv[5], 0);
#endif

	/* standard operators: "setexpr name val1 op val2" */
	if (argc != 5)
		return CMD_RET_USAGE;

	if (strlen(argv[3]) != 1)
		return CMD_RET_USAGE;

	b = get_arg(argv[4], w);

	switch (argv[3][0]) {
	case '|':
		value = a | b;
		break;
	case '&':
		value = a & b;
		break;
	case '+':
		value = a + b;
		break;
	case '^':
		value = a ^ b;
		break;
	case '-':
		value = a - b;
		break;
	case '*':
		value = a * b;
		break;
	case '/':
		value = a / b;
		break;
	case '%':
		value = a % b;
		break;
	default:
		printf("invalid op\n");
		return 1;
	}

	setenv_hex(argv[1], value);

	return 0;
}

U_BOOT_CMD(
	setexpr, 6, 0, do_setexpr,
	"set environment variable as the result of eval expression",
	"[.b, .w, .l] name [*]value1 <op> [*]value2\n"
	"    - set environment variable 'name' to the result of the evaluated\n"
	"      expression specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
	"      size argument is only meaningful if value1 and/or value2 are\n"
	"      memory addresses (*)\n"
	"setexpr[.b, .w, .l] name [*]value\n"
	"    - load a value into a variable"
#ifdef CONFIG_REGEX
	"\n"
	"setexpr name gsub r s [t]\n"
	"    - For each substring matching the regular expression <r> in the\n"
	"      string <t>, substitute the string <s>.  The result is\n"
	"      assigned to <name>.  If <t> is not supplied, use the old\n"
	"      value of <name>\n"
	"setexpr name sub r s [t]\n"
	"    - Just like gsub(), but replace only the first matching substring"
#endif
);
