At present a ulong is used to hold operand values. This means that
strings cannot be used. While most operations are not useful for strings,
concatenation is. As a starting point to supporting strings, convert the
code to use a struct instead of a ulong for operands.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 cmd/setexpr.c | 111 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 67 insertions(+), 44 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index d364dbc2bc5..8a3654505da 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -15,8 +15,19 @@
 #include <log.h>
 #include <mapmem.h>
 
-static ulong get_arg(char *s, int w)
+/**
+ * struct expr_arg: Holds an argument to an expression
+ *
+ * @ival: Integer value (if width is not CMD_DATA_SIZE_STR)
+ */
+struct expr_arg {
+       ulong ival;
+};
+
+static int get_arg(char *s, int w, struct expr_arg *argp)
 {
+       struct expr_arg arg;
+
        /*
         * If the parameter starts with a '*' then assume it is a pointer to
         * the value we want.
@@ -32,26 +43,33 @@ static ulong get_arg(char *s, int w)
                        p = map_sysmem(addr, sizeof(uchar));
                        val = (ulong)*(uchar *)p;
                        unmap_sysmem(p);
-                       return val;
+                       arg.ival = val;
+                       break;
                case 2:
                        p = map_sysmem(addr, sizeof(ushort));
                        val = (ulong)*(ushort *)p;
                        unmap_sysmem(p);
-                       return val;
+                       arg.ival = val;
+                       break;
                case 4:
                        p = map_sysmem(addr, sizeof(u32));
                        val = *(u32 *)p;
                        unmap_sysmem(p);
-                       return val;
+                       arg.ival = val;
+                       break;
                default:
                        p = map_sysmem(addr, sizeof(ulong));
                        val = *p;
                        unmap_sysmem(p);
-                       return val;
+                       arg.ival = val;
+                       break;
                }
        } else {
-               return simple_strtoul(s, NULL, 16);
+               arg.ival = simple_strtoul(s, NULL, 16);
        }
+       *argp = arg;
+
+       return 0;
 }
 
 #ifdef CONFIG_REGEX
@@ -321,7 +339,7 @@ static int regex_sub_var(const char *name, const char *r, 
const char *s,
 static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
                      char *const argv[])
 {
-       ulong a, b;
+       struct expr_arg aval, bval;
        ulong value;
        int w;
 
@@ -339,13 +357,12 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, 
int argc,
 
        w = cmd_get_data_size(argv[0], 4);
 
-       a = get_arg(argv[2], w);
+       if (get_arg(argv[2], w, &aval))
+               return CMD_RET_FAILURE;
 
        /* plain assignment: "setexpr name value" */
-       if (argc == 3) {
-               env_set_hex(argv[1], a);
-               return 0;
-       }
+       if (argc == 3)
+               return env_set_hex(argv[1], aval.ival);
 
        /* 5 or 6 args (6 args only with [g]sub) */
 #ifdef CONFIG_REGEX
@@ -367,39 +384,45 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, 
int argc,
        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;
-       }
+       if (get_arg(argv[4], w, &bval))
+               return CMD_RET_FAILURE;
 
-       env_set_hex(argv[1], value);
+       if (w != CMD_DATA_SIZE_STR) {
+               ulong a = aval.ival;
+               ulong b = bval.ival;
+
+               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;
+               }
+
+               env_set_hex(argv[1], value);
+       }
 
        return 0;
 }
-- 
2.29.1.341.ge80a0c044ae-goog

Reply via email to