Blame view

common/cmd_itest.c 4.17 KB
2d1a537d8   wdenk   * Patch by Thomas...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * (C) Copyright 2003
   * Tait Electronics Limited, Christchurch, New Zealand
   *
   * See file CREDITS for list of people who contributed to this
   * project.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation; either version 2 of
   * the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
cd0a9de68   wdenk   * Patch by Lauren...
15
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
2d1a537d8   wdenk   * Patch by Thomas...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
   * MA 02111-1307 USA
   */
  
  /*
   * This file provides a shell like 'test' function to return
   * true/false from an integer or string compare of two memory
   * locations or a location and a scalar/literal.
   * A few parts were lifted from bash 'test' command
   */
  
  #include <common.h>
  #include <config.h>
  #include <command.h>
  
  #define EQ	0
  #define NE	1
  #define LT	2
  #define GT	3
  #define LE	4
  #define GE	5
  
  struct op_tbl_s {
  	char	*op;		/* operator string */
  	int	opcode;		/* internal representation of opcode */
  };
  
  typedef struct op_tbl_s op_tbl_t;
fc9903f38   Mike Frysinger   cmd_itest: consti...
48
  static const op_tbl_t op_table [] = {
2d1a537d8   wdenk   * Patch by Thomas...
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  	{ "-lt", LT },
  	{ "<"  , LT },
  	{ "-gt", GT },
  	{ ">"  , GT },
  	{ "-eq", EQ },
  	{ "==" , EQ },
  	{ "-ne", NE },
  	{ "!=" , NE },
  	{ "<>" , NE },
  	{ "-ge", GE },
  	{ ">=" , GE },
  	{ "-le", LE },
  	{ "<=" , LE },
  };
2d1a537d8   wdenk   * Patch by Thomas...
63
64
  static long evalexp(char *s, int w)
  {
f3651764e   Frans Meulenbroeks   cmd_itest.c: fix ...
65
66
  	long l = 0;
  	long *p;
2d1a537d8   wdenk   * Patch by Thomas...
67
68
69
70
  
  	/* 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);
f3651764e   Frans Meulenbroeks   cmd_itest.c: fix ...
71
72
73
74
75
  		switch (w) {
  		case 1: return((long)(*(unsigned char *)p));
  		case 2: return((long)(*(unsigned short *)p));
  		case 4: return(*p);
  		}
2d1a537d8   wdenk   * Patch by Thomas...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  	} else {
  		l = simple_strtoul(s, NULL, 16);
  	}
  
  	return (l & ((1 << (w * 8)) - 1));
  }
  
  static char * evalstr(char *s)
  {
  	/* 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 {
  		return s;
  	}
  }
  
  static int stringcomp(char *s, char *t, int op)
  {
cc22b795f   Wolfgang Denk   itest: fix result...
95
  	int p;
2d1a537d8   wdenk   * Patch by Thomas...
96
97
98
99
  	char *l, *r;
  
  	l = evalstr(s);
  	r = evalstr(t);
cc22b795f   Wolfgang Denk   itest: fix result...
100
  	p = strcmp(l, r);
2d1a537d8   wdenk   * Patch by Thomas...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  	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);
  	}
  	return (0);
  }
  
  static int arithcomp (char *s, char *t, int op, int w)
  {
  	long l, r;
  
  	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);
  	}
  	return (0);
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
129
  static int binary_test(char *op, char *arg1, char *arg2, int w)
2d1a537d8   wdenk   * Patch by Thomas...
130
131
  {
  	int len, i;
fc9903f38   Mike Frysinger   cmd_itest: consti...
132
  	const op_tbl_t *optp;
2d1a537d8   wdenk   * Patch by Thomas...
133
134
135
136
  
  	len = strlen(op);
  
  	for (optp = (op_tbl_t *)&op_table, i = 0;
fc9903f38   Mike Frysinger   cmd_itest: consti...
137
  	     i < ARRAY_SIZE(op_table);
2d1a537d8   wdenk   * Patch by Thomas...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  	     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("Unknown operator '%s'
  ", op);
  	return 0;	/* op code not found */
  }
  
  /* command line interface to the shell test */
088f1b199   Kim Phillips   common/cmd_*.c: s...
155
  static int do_itest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2d1a537d8   wdenk   * Patch by Thomas...
156
  {
cd0a9de68   wdenk   * Patch by Lauren...
157
  	int	value, w;
2d1a537d8   wdenk   * Patch by Thomas...
158

cd0a9de68   wdenk   * Patch by Lauren...
159
  	/* Validate arguments */
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
160
  	if ((argc != 4))
4c12eeb8b   Simon Glass   Convert cmd_usage...
161
  		return CMD_RET_USAGE;
2d1a537d8   wdenk   * Patch by Thomas...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  
  	/* 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
  	 */
  	switch (w = cmd_get_data_size(argv[0], 4)) {
  	case 1:
  	case 2:
  	case 4:
  		value = binary_test (argv[2], argv[1], argv[3], w);
  		break;
  	case -2:
  		value = binary_test (argv[2], argv[1], argv[3], 0);
  		break;
  	case -1:
  	default:
  		puts("Invalid data width specifier
  ");
  		value = 0;
  		break;
  	}
  
  	return !value;
  }
  
  U_BOOT_CMD(
  	itest, 4, 0, do_itest,
2fb2604d5   Peter Tyser   Command usage cle...
189
  	"return true/false on integer compare",
a89c33db9   Wolfgang Denk   General help mess...
190
  	"[.b, .w, .l, .s] [*]value1 <op> [*]value2"
2d1a537d8   wdenk   * Patch by Thomas...
191
  );