Up to now the setexpr command only supported concatenating string provided
by reference. Allow directly passing stings.

With this patch

    setexpr.s foo '1' + '3'

sets variable $foo to the value '13'.

Update the unit test for "setexpr.s fred 0".

Add a new unit test for "setexpr.s fred '1' + '3'".

Signed-off-by: Heinrich Schuchardt <heinrich.schucha...@canonical.com>
---
 cmd/setexpr.c      | 54 ++++++++++++++++++++++++++++++++--------------
 test/cmd/setexpr.c |  7 +++++-
 2 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index e111b8ba98a..c45fa85c887 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -35,9 +35,37 @@ struct expr_arg {
        };
 };
 
+/**
+ * arg_set_str() - copy string to expression argument
+ *
+ * The string is truncated to 64 KiB plus NUL terminator.
+ *
+ * @p:         pointer to string
+ * @argp:      pointer to expression argument
+ * Return:     0 on success, -ENOMEM if out of memory
+ */
+static int arg_set_str(void *p, struct expr_arg *argp)
+{
+       int len;
+       char *str;
+
+       /* Maximum string length of 64 KiB plus NUL terminator */
+       len = strnlen((char *)p, SZ_64K) + 1;
+       str = malloc(len);
+       if (!str) {
+               printf("Out of memory\n");
+               return -ENOMEM;
+       }
+       memcpy(str, p, len);
+       str[len - 1] = '\0';
+       argp->sval = str;
+       return 0;
+}
+
 static int get_arg(char *s, int w, struct expr_arg *argp)
 {
        struct expr_arg arg;
+       int ret;
 
        /*
         * If the parameter starts with a '*' then assume it is a pointer to
@@ -47,8 +75,6 @@ static int get_arg(char *s, int w, struct expr_arg *argp)
                ulong *p;
                ulong addr;
                ulong val;
-               int len;
-               char *str;
 
                addr = hextoul(&s[1], NULL);
                switch (w) {
@@ -66,18 +92,10 @@ static int get_arg(char *s, int w, struct expr_arg *argp)
                        break;
                case CMD_DATA_SIZE_STR:
                        p = map_sysmem(addr, SZ_64K);
-
-                       /* Maximum string length of 64KB plus terminator */
-                       len = strnlen((char *)p, SZ_64K) + 1;
-                       str = malloc(len);
-                       if (!str) {
-                               printf("Out of memory\n");
-                               return -ENOMEM;
-                       }
-                       memcpy(str, p, len);
-                       str[len - 1] = '\0';
+                       ret = arg_set_str(p, &arg);
                        unmap_sysmem(p);
-                       arg.sval = str;
+                       if (ret)
+                               return ret;
                        break;
                case 4:
                        p = map_sysmem(addr, sizeof(u32));
@@ -93,9 +111,13 @@ static int get_arg(char *s, int w, struct expr_arg *argp)
                        break;
                }
        } else {
-               if (w == CMD_DATA_SIZE_STR)
-                       return -EINVAL;
-               arg.ival = hextoul(s, NULL);
+               if (w == CMD_DATA_SIZE_STR) {
+                       ret = arg_set_str(s, &arg);
+                       if (ret)
+                               return ret;
+               } else {
+                       arg.ival = hextoul(s, NULL);
+               }
        }
        *argp = arg;
 
diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c
index 21a3268bd81..00d373f35ae 100644
--- a/test/cmd/setexpr.c
+++ b/test/cmd/setexpr.c
@@ -310,7 +310,8 @@ static int setexpr_test_str(struct unit_test_state *uts)
        ut_assertok(env_set("fred", "x"));
        start_mem = ut_check_free();
        strcpy(buf, "hello");
-       ut_asserteq(1, run_command("setexpr.s fred 0", 0));
+       ut_asserteq(0, run_command("setexpr.s fred 0", 0));
+       ut_asserteq_str("0", env_get("fred"));
        ut_assertok(ut_check_delta(start_mem));
 
        ut_assertok(env_set("fred", "12345"));
@@ -335,6 +336,10 @@ static int setexpr_test_str_oper(struct unit_test_state 
*uts)
        ulong start_mem;
        char *buf;
 
+       /* Test concatenation of strings */
+       ut_assertok(run_command("setexpr.s fred '1' + '3'", 0));
+       ut_asserteq_str("13", env_get("fred"));
+
        buf = map_sysmem(0, BUF_SIZE);
        memset(buf, '\xff', BUF_SIZE);
        strcpy(buf, "hello");
-- 
2.47.1

Reply via email to