]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_test.c
cmd_test: check for binary operators before unary
[karo-tx-uboot.git] / common / cmd_test.c
1 /*
2  * Copyright 2000-2009
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * Define _STDBOOL_H here to avoid macro expansion of true and false.
10  * If the future code requires macro true or false, remove this define
11  * and undef true and false before U_BOOT_CMD. This define and comment
12  * shall be removed if change to U_BOOT_CMD is made to take string
13  * instead of stringifying it.
14  */
15 #define _STDBOOL_H
16
17 #include <common.h>
18 #include <command.h>
19
20 #define OP_INVALID      0
21 #define OP_OR           2
22 #define OP_AND          3
23 #define OP_STR_EMPTY    4
24 #define OP_STR_NEMPTY   5
25 #define OP_STR_EQ       6
26 #define OP_STR_NEQ      7
27 #define OP_STR_LT       8
28 #define OP_STR_GT       9
29 #define OP_INT_EQ       10
30 #define OP_INT_NEQ      11
31 #define OP_INT_LT       12
32 #define OP_INT_LE       13
33 #define OP_INT_GT       14
34 #define OP_INT_GE       15
35
36 const struct {
37         int arg;
38         const char *str;
39         int op;
40         int adv;
41 } op_adv[] = {
42         {1, "=", OP_STR_EQ, 3},
43         {1, "!=", OP_STR_NEQ, 3},
44         {1, "<", OP_STR_LT, 3},
45         {1, ">", OP_STR_GT, 3},
46         {1, "-eq", OP_INT_EQ, 3},
47         {1, "-ne", OP_INT_NEQ, 3},
48         {1, "-lt", OP_INT_LT, 3},
49         {1, "-le", OP_INT_LE, 3},
50         {1, "-gt", OP_INT_GT, 3},
51         {1, "-ge", OP_INT_GE, 3},
52         {0, "-o", OP_OR, 1},
53         {0, "-a", OP_AND, 1},
54         {0, "-z", OP_STR_EMPTY, 2},
55         {0, "-n", OP_STR_NEMPTY, 2},
56 };
57
58 static int do_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
59 {
60         char * const *ap;
61         int i, op, left, adv, expr, last_expr, neg, last_cmp;
62
63         /* args? */
64         if (argc < 3)
65                 return 1;
66
67 #ifdef DEBUG
68         {
69                 debug("test(%d):", argc);
70                 left = 1;
71                 while (argv[left])
72                         debug(" '%s'", argv[left++]);
73         }
74 #endif
75
76         last_expr = 0;
77         left = argc - 1; ap = argv + 1;
78         if (left > 0 && strcmp(ap[0], "!") == 0) {
79                 neg = 1;
80                 ap++;
81                 left--;
82         } else
83                 neg = 0;
84
85         expr = -1;
86         last_cmp = OP_INVALID;
87         last_expr = -1;
88         while (left > 0) {
89                 for (i = 0; i < ARRAY_SIZE(op_adv); i++) {
90                         if (left <= op_adv[i].arg)
91                                 continue;
92                         if (!strcmp(ap[op_adv[i].arg], op_adv[i].str)) {
93                                 op = op_adv[i].op;
94                                 adv = op_adv[i].adv;
95                                 break;
96                         }
97                 }
98                 if (i == ARRAY_SIZE(op_adv)) {
99                         expr = 1;
100                         break;
101                 }
102                 if (left < adv) {
103                         expr = 1;
104                         break;
105                 }
106
107                 switch (op) {
108                 case OP_STR_EMPTY:
109                         expr = strlen(ap[1]) == 0 ? 1 : 0;
110                         break;
111                 case OP_STR_NEMPTY:
112                         expr = strlen(ap[1]) == 0 ? 0 : 1;
113                         break;
114                 case OP_STR_EQ:
115                         expr = strcmp(ap[0], ap[2]) == 0;
116                         break;
117                 case OP_STR_NEQ:
118                         expr = strcmp(ap[0], ap[2]) != 0;
119                         break;
120                 case OP_STR_LT:
121                         expr = strcmp(ap[0], ap[2]) < 0;
122                         break;
123                 case OP_STR_GT:
124                         expr = strcmp(ap[0], ap[2]) > 0;
125                         break;
126                 case OP_INT_EQ:
127                         expr = simple_strtol(ap[0], NULL, 10) ==
128                                         simple_strtol(ap[2], NULL, 10);
129                         break;
130                 case OP_INT_NEQ:
131                         expr = simple_strtol(ap[0], NULL, 10) !=
132                                         simple_strtol(ap[2], NULL, 10);
133                         break;
134                 case OP_INT_LT:
135                         expr = simple_strtol(ap[0], NULL, 10) <
136                                         simple_strtol(ap[2], NULL, 10);
137                         break;
138                 case OP_INT_LE:
139                         expr = simple_strtol(ap[0], NULL, 10) <=
140                                         simple_strtol(ap[2], NULL, 10);
141                         break;
142                 case OP_INT_GT:
143                         expr = simple_strtol(ap[0], NULL, 10) >
144                                         simple_strtol(ap[2], NULL, 10);
145                         break;
146                 case OP_INT_GE:
147                         expr = simple_strtol(ap[0], NULL, 10) >=
148                                         simple_strtol(ap[2], NULL, 10);
149                         break;
150                 }
151
152                 switch (op) {
153                 case OP_OR:
154                         last_expr = expr;
155                         last_cmp = OP_OR;
156                         break;
157                 case OP_AND:
158                         last_expr = expr;
159                         last_cmp = OP_AND;
160                         break;
161                 default:
162                         if (last_cmp == OP_OR)
163                                 expr = last_expr || expr;
164                         else if (last_cmp == OP_AND)
165                                 expr = last_expr && expr;
166                         last_cmp = OP_INVALID;
167                         break;
168                 }
169
170                 ap += adv; left -= adv;
171         }
172
173         if (neg)
174                 expr = !expr;
175
176         expr = !expr;
177
178         debug (": returns %d\n", expr);
179
180         return expr;
181 }
182
183 U_BOOT_CMD(
184         test,   CONFIG_SYS_MAXARGS,     1,      do_test,
185         "minimal test like /bin/sh",
186         "[args..]"
187 );
188
189 static int do_false(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
190 {
191         return 1;
192 }
193
194 U_BOOT_CMD(
195         false,  CONFIG_SYS_MAXARGS,     1,      do_false,
196         "do nothing, unsuccessfully",
197         NULL
198 );
199
200 static int do_true(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
201 {
202         return 0;
203 }
204
205 U_BOOT_CMD(
206         true,   CONFIG_SYS_MAXARGS,     1,      do_true,
207         "do nothing, successfully",
208         NULL
209 );