* This file provides a shell like 'expr' function to return.
*/
-#include <common.h>
#include <config.h>
#include <command.h>
+#include <ctype.h>
#include <env.h>
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
+#include <vsprintf.h>
+#include <linux/errno.h>
#include <linux/sizes.h>
+#include "printf.h"
+
+#define MAX_STR_LEN 128
/**
* struct expr_arg: Holds an argument to an expression
int len;
char *str;
- addr = simple_strtoul(&s[1], NULL, 16);
+ addr = hextoul(&s[1], NULL);
switch (w) {
case 1:
p = map_sysmem(addr, sizeof(uchar));
} else {
if (w == CMD_DATA_SIZE_STR)
return -EINVAL;
- arg.ival = simple_strtoul(s, NULL, 16);
+ arg.ival = hextoul(s, NULL);
}
*argp = arg;
* @olen: Length of @old excluding terminator
* @new: New string to replace @old with
* @nlen: Length of @new excluding terminator
- * @return pointer to immediately after the copied @new in @string, or NULL if
+ * Return: pointer to immediately after the copied @new in @string, or NULL if
* no replacement took place
*/
static char *substitute(char *string, int *slen, int ssize,
if (res == 0) {
if (loop == 0) {
- printf("%s: No match\n", data);
- return 1;
+ debug("%s: No match\n", data);
} else {
- break;
+ debug("## MATCH ## %s\n", data);
}
+ break;
}
- debug("## MATCH ## %s\n", data);
-
if (!s)
return 1;
if (ret)
return 1;
- printf("%s=%s\n", name, data);
+ debug("%s=%s\n", name, data);
return env_set(name, data);
}
int w;
/*
- * We take 3, 5, or 6 arguments:
+ * We take 3, 5, or 6 arguments, except fmt operation, which
+ * takes 4 to 8 arguments (limited by _maxargs):
* 3 : setexpr name value
* 5 : setexpr name val1 op val2
* setexpr name [g]sub r s
* 6 : setexpr name [g]sub r s t
+ * setexpr name fmt format [val1] [val2] [val3] [val4]
*/
- /* > 6 already tested by max command args */
- if ((argc < 3) || (argc == 4))
+ if (argc < 3)
return CMD_RET_USAGE;
w = cmd_get_data_size(argv[0], 4);
if (get_arg(argv[2], w, &aval))
return CMD_RET_FAILURE;
+ /* format string assignment: "setexpr name fmt %d value" */
+ if (strcmp(argv[2], "fmt") == 0 && IS_ENABLED(CONFIG_CMD_SETEXPR_FMT)) {
+ char str[MAX_STR_LEN];
+ int result;
+
+ if (argc == 3)
+ return CMD_RET_USAGE;
+
+ result = printf_setexpr(str, sizeof(str), argc - 3, &argv[3]);
+ if (result)
+ return result;
+
+ return env_set(argv[1], str);
+ }
+
+ if (argc == 4 || argc > 6)
+ return CMD_RET_USAGE;
+
/* plain assignment: "setexpr name value" */
if (argc == 3) {
if (w == CMD_DATA_SIZE_STR) {
}
U_BOOT_CMD(
- setexpr, 6, 0, do_setexpr,
+ setexpr, 8, 0, do_setexpr,
"set environment variable as the result of eval expression",
"[.b, .w, .l, .s] name [*]value1 <op> [*]value2\n"
" - set environment variable 'name' to the result of the evaluated\n"
" memory addresses (*)\n"
"setexpr[.b, .w, .l] name [*]value\n"
" - load a value into a variable"
+#ifdef CONFIG_CMD_SETEXPR_FMT
+ "\n"
+ "setexpr name fmt <format> [value1] [value2] [value3] [value4]\n"
+ " - set environment variable 'name' to the result of the bash like\n"
+ " format string evaluation of value."
+#endif
#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"
+ " value of <name>. If no substring matching <r> is found in <t>,\n"
+ " assign <t> to <name>.\n"
"setexpr name sub r s [t]\n"
" - Just like gsub(), but replace only the first matching substring"
#endif