Backport setexpr command, enable it by default, cleanup cmd_itest.c
authorPiotr Dymacz <pepe2k@gmail.com>
Wed, 31 Aug 2016 16:29:27 +0000 (18:29 +0200)
committerPiotr Dymacz <pepe2k@gmail.com>
Wed, 31 Aug 2016 16:29:27 +0000 (18:29 +0200)
u-boot/common/cmd_itest.c
u-boot/include/configs/qca9k_common.h

index 805cf125ba9eed851d830552a85b942b5da8d624..75148d4c456685690bb6b9e36cb4803a2680cc13 100644 (file)
 #include <config.h>
 #include <command.h>
 
+#if defined(CONFIG_CMD_ITEST) ||\
+    defined(CONFIG_CMD_SETEXPR)
+
+extern int cmd_get_data_size(char* arg, int default_size);
+
+static ulong evalexp(char *s, int w)
+{
+       ulong *p;
+       ulong l = 0;
+
+       /*
+        * If the parameter starts with a * then
+        * assume is a pointer to the value we want
+        */
+       if (s[0] == '*') {
+               p = (ulong *)simple_strtoul(&s[1], NULL, 16);
+               l = *p;
+       } else {
+               l = simple_strtoul(s, NULL, 16);
+       }
+
+       if (w < 4)
+               return l & ((1 << (w * 8)) - 1);
+       else
+               return l;
+}
+#endif /* CONFIG_CMD_ITEST || CONFIG_CMD_SETEXPR */
+
+#if defined(CONFIG_CMD_SETEXPR)
+int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       ulong a, b, value;
+       char buf[16];
+       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)) {
+               print_cmd_help(cmdtp);
+               return 1;
+       }
+
+       w = cmd_get_data_size(argv[0], 4);
+
+       a = evalexp(argv[2], w);
+
+       /* Plain assignment: "setexpr name value" */
+       if (argc == 3) {
+               sprintf(buf, "%X", a);
+               setenv(argv[1], buf);
+               return 0;
+       }
+
+       /* Standard operators: "setexpr name val1 op val2" */
+       if (argc != 5) {
+               print_cmd_help(cmdtp);
+               return 1;
+       }
+
+       if (strlen(argv[3]) != 1) {
+               print_cmd_help(cmdtp);
+               return 1;
+       }
+
+       b = evalexp(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("## Error: invalid op\n");
+               return 1;
+       }
+
+       sprintf(buf, "%X", value);
+       setenv(argv[1], buf);
+
+       return 0;
+}
+
+U_BOOT_CMD(setexpr, 6, 0, do_setexpr, "set env variable as the result of eval expr\n",
+       "[.b, .w, .l] name [*]val1 <op> [*]val2\n"
+       "\t- set env variable 'name' to the result of the evaluated\n"
+       "\t  expr specified by <op> (can be &, |, ^, +, -, *, /, %)\n"
+       "\t  size argument is only meaningful if val1 and/or val2 are memory addresses (*)\n"
+       "setexpr[.b, .w, .l] name [*]val\n"
+       "\t- load a 'val' into 'name' variable");
+#endif /* CONFIG_CMD_SETEXPR */
+
 #if defined(CONFIG_CMD_ITEST)
 
 #define EQ     0
 #define GE     5
 
 struct op_tbl_s {
-       char    *op;            /* operator string */
-       int     opcode;         /* internal representation of opcode */
+       char *op;       /* Operator string */
+       int opcode;     /* Internal representation of opcode */
 };
 
 typedef struct op_tbl_s op_tbl_t;
@@ -66,35 +184,17 @@ op_tbl_t op_table [] = {
 
 #define op_tbl_size (sizeof(op_table)/sizeof(op_table[0]))
 
-extern int cmd_get_data_size(char* arg, int default_size);
 
-static long evalexp(char *s, int w)
+static char *evalstr(char *s)
 {
-       long *p;
-       long l = 0;
-
-       /* if the parameter starts with a * then assume is a pointer to the value we want */
-       if (s[0] == '*') {
-               p = (long *)simple_strtoul(&s[1], NULL, 16);
-               l = *p;
-       } else {
-               l = simple_strtoul(s, NULL, 16);
-       }
-
-       if (w < 4)
-               return l & ((1 << (w * 8)) - 1);
-       else
-               return l;
-}
-
-static char * evalstr(char *s)
-{
-       /* if the parameter starts with a * then assume a string pointer else its a literal */
-       if (s[0] == '*') {
+       /*
+        * If the parameter starts with a * then
+        *assume a string pointer else its a literal
+        */
+       if (s[0] == '*')
                return (char *)simple_strtoul(&s[1], NULL, 16);
-       } else {
+       else
                return s;
-       }
 }
 
 static int stringcomp(char *s, char *t, int op)
@@ -105,40 +205,55 @@ static int stringcomp(char *s, char *t, int op)
        l = evalstr(s);
        r = evalstr(t);
 
-       /* we'll do a compare based on the length of the shortest string */
+       /* We'll do a compare based on the length of the shortest string */
        n = min(strlen(l), strlen(r));
 
        p = strncmp(l, r, n);
+
        switch (op) {
-       case EQ: return (p == 0);
-       case NE: return (p != 0);
-       case LT: return (p < 0);
-       case GT: return (p > 0);
-       case LE: return (p <= 0);
-       case GE: return (p >= 0);
+       case EQ:
+               return p == 0;
+       case NE:
+               return p != 0;
+       case LT:
+               return p < 0;
+       case GT:
+               return p > 0;
+       case LE:
+               return p <= 0;
+       case GE:
+               return p >= 0;
        }
-       return (0);
+
+       return 0;
 }
 
-static int arithcomp (char *s, char *t, int op, int w)
+static int arithcomp(char *s, char *t, int op, int w)
 {
-       long l, r;
+       ulong l, r;
 
-       l = evalexp (s, w);
-       r = evalexp (t, w);
+       l = evalexp(s, w);
+       r = evalexp(t, w);
 
        switch (op) {
-       case EQ: return (l == r);
-       case NE: return (l != r);
-       case LT: return (l < r);
-       case GT: return (l > r);
-       case LE: return (l <= r);
-       case GE: return (l >= r);
+       case EQ:
+               return l == r;
+       case NE:
+               return l != r;
+       case LT:
+               return l < r;
+       case GT:
+               return l > r;
+       case LE:
+               return l <= r;
+       case GE:
+               return l >= r;
        }
-       return (0);
+
+       return 0;
 }
 
-int binary_test (char *op, char *arg1, char *arg2, int w)
+static int binary_test(char *op, char *arg1, char *arg2, int w)
 {
        int len, i;
        op_tbl_t *optp;
@@ -146,34 +261,35 @@ int binary_test (char *op, char *arg1, char *arg2, int w)
        len = strlen(op);
 
        for (optp = (op_tbl_t *)&op_table, i = 0;
-            i < op_tbl_size;
-            optp++, i++) {
-
-               if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) {
-                       if (w == 0) {
-                               return (stringcomp(arg1, arg2, optp->opcode));
-                       } else {
-                               return (arithcomp (arg1, arg2, optp->opcode, w));
-                       }
+            i < op_tbl_size; optp++, i++) {
+               if ((strncmp(op, optp->op, len) == 0) &&
+                   (len == strlen(optp->op))) {
+                       if (w == 0)
+                               return stringcomp(arg1, arg2, optp->opcode);
+                       else
+                               return arithcomp(arg1, arg2, optp->opcode, w);
                }
        }
 
        printf("## Error: unknown operator '%s'\n", op);
-       return 0;       /* op code not found */
+
+       /* Op code not found */
+       return 0;
 }
 
-/* command line interface to the shell test */
-int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
+/* Command line interface to the shell test */
+int do_itest(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-       int     value, w;
+       int value, w;
 
        /* Validate arguments */
-       if ((argc != 4)){
+       if ((argc != 4)) {
                print_cmd_help(cmdtp);
                return 1;
        }
 
-       /* Check for a data width specification.
+       /*
+        * Check for a data width specification.
         * Defaults to long (4) if no specification.
         * Uses -2 as 'width' for .s (string) so as not to upset existing code
         */
@@ -181,10 +297,10 @@ int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
        case 1:
        case 2:
        case 4:
-               value = binary_test (argv[2], argv[1], argv[3], w);
+               value = binary_test(argv[2], argv[1], argv[3], w);
                break;
        case -2:
-               value = binary_test (argv[2], argv[1], argv[3], 0);
+               value = binary_test(argv[2], argv[1], argv[3], 0);
                break;
        case -1:
        default:
@@ -196,5 +312,6 @@ int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
        return !value;
 }
 
-U_BOOT_CMD(itest, 4, 0, do_itest, "return true/false on integer compare\n", "[.b, .w, .l, .s] [*]value1 <op> [*]value2\n");
+U_BOOT_CMD(itest, 4, 0, do_itest, "return true/false on int compare\n",
+       "[.b, .w, .l, .s] [*]val1 <op> [*]val2\n");
 #endif /* CONFIG_CMD_ITEST */
index d13c99e32640f1c50c29f4408fa0ea01eca958ee..9ff25c91516aeb6204b580dcce7cc9c99594c396 100644 (file)
 #define CONFIG_CMD_LOADB
 #define CONFIG_CMD_BUTTON
 #define CONFIG_CMD_SLEEP
+#define CONFIG_CMD_SETEXPR
 
 /* Simple upgrade scripts in environment */
 #define CONFIG_UPG_SCRIPTS_UBOOT