[PATCH 1/3] cmd: setexpr: add fmt format string operation
Roland Gaudig
roland.gaudig-oss at weidmueller.com
Mon Jun 28 17:17:48 CEST 2021
From: Roland Gaudig <roland.gaudig at weidmueller.com>
Add format string "fmt" operation to the setexpr command
which converts the input value according the format string
specification and stores the result into the variable named name.
Signed-off-by: Roland Gaudig <roland.gaudig at weidmueller.com>
---
cmd/setexpr.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 101 insertions(+), 1 deletion(-)
diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index e828be3970..b69cbab3dd 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -11,12 +11,15 @@
#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 <linux/sizes.h>
+#define MAX_STR_LEN 128
+
/**
* struct expr_arg: Holds an argument to an expression
*
@@ -361,6 +364,95 @@ static int regex_sub_var(const char *name, const char *r, const char *s,
}
#endif
+/**
+ * setexpr_fmt_spec_search() - Search for format specifier
+ *
+ * This function searches the intput string for the first occurrence of a
+ * format specifier which starts with a %. Double % are ignored.
+ *
+ * @format: C like format string to search
+ * @return: Pointer to found format specifier, NULL in case none is found
+ */
+static char *setexpr_fmt_spec_search(char *format)
+{
+ while (*format != '\0') {
+ if (*format == '%') {
+ switch (*(format + 1)) {
+ case '%':
+ /* found '%%', not a format specifier, skip. */
+ format++;
+ break;
+ case '\0':
+ /* found '%' at end of string,
+ * incomplete format specifier.
+ */
+ return NULL;
+ default:
+ /* looks like a format specifier */
+ return format;
+ }
+ }
+ format++;
+ }
+
+ return NULL;
+}
+
+/**
+ * setexpr_fmt() - Implements the setexpr <name> fmt command
+ *
+ * This function implements the setexpr <name> fmt <format> <value> command.
+ *
+ * @name: Name of the environment variable to save the evaluated expression in
+ * @format: C like format string
+ * @value: Input value to be converted
+ * @return: 0 if OK, 1 on error
+ */
+static int setexpr_fmt(char *name, char *format, char *value)
+{
+ struct expr_arg aval;
+ int data_size;
+ char str[MAX_STR_LEN];
+ int fmt_len = strlen(format);
+
+ if (fmt_len < 2) {
+ printf("Error: missing format string");
+ return CMD_RET_FAILURE;
+ }
+
+ /* Search format specifier */
+ char *first = setexpr_fmt_spec_search(format);
+
+ /* Exactly one format specifier is required */
+ if (!first || setexpr_fmt_spec_search(first + 1)) {
+ printf("Error: exactly one format specifier is required\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /* Search type field of format specifier */
+ while (*first && !isalpha(*first))
+ first++;
+
+ /* Test if type is supported */
+ if (!strchr("diouxX", *first)) {
+ printf("Error: format type not supported\n");
+ return CMD_RET_FAILURE;
+ }
+
+ data_size = cmd_get_data_size(value, 4);
+
+ if (data_size == CMD_DATA_SIZE_STR) {
+ free(aval.sval);
+ return CMD_RET_FAILURE;
+ }
+
+ if (get_arg(value, data_size, &aval))
+ return CMD_RET_FAILURE;
+
+ snprintf(str, sizeof(str), format, aval.ival);
+ return env_set(name, str);
+}
+
static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
@@ -374,6 +466,7 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
* 3 : setexpr name value
* 5 : setexpr name val1 op val2
* setexpr name [g]sub r s
+ * setexpr name fmt format value
* 6 : setexpr name [g]sub r s t
*/
@@ -398,6 +491,10 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
return ret;
}
+ /* format string assignment: "setexpr name fmt %d value" */
+ if (strcmp(argv[2], "fmt") == 0)
+ return setexpr_fmt(argv[1], argv[3], argv[4]);
+
/* 5 or 6 args (6 args only with [g]sub) */
#ifdef CONFIG_REGEX
/*
@@ -504,7 +601,10 @@ U_BOOT_CMD(
" 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"
+ " - load a value into a variable\n"
+ "setexpr name fmt <format> [*]value\n"
+ " - set environment variable 'name' to the result of the C like\n"
+ " format string evaluation of [*]value.\n"
#ifdef CONFIG_REGEX
"\n"
"setexpr name gsub r s [t]\n"
--
2.25.1
More information about the U-Boot
mailing list