diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2003-08-29 07:29:30 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2003-08-29 07:29:30 +0000 |
commit | 7b8765c808641d74edd1f0a4f22c092ea21421fa (patch) | |
tree | f15b6c928209cc41ad172054caa8831e618066b4 /coreutils/expr.c | |
parent | 23365976f8e0265adc2f21d8e330ce58e270041a (diff) | |
download | busybox-w32-7b8765c808641d74edd1f0a4f22c092ea21421fa.tar.gz busybox-w32-7b8765c808641d74edd1f0a4f22c092ea21421fa.tar.bz2 busybox-w32-7b8765c808641d74edd1f0a4f22c092ea21421fa.zip |
vodz, last patch 103
Diffstat (limited to 'coreutils/expr.c')
-rw-r--r-- | coreutils/expr.c | 141 |
1 files changed, 69 insertions, 72 deletions
diff --git a/coreutils/expr.c b/coreutils/expr.c index ecba825d5..f58f4b062 100644 --- a/coreutils/expr.c +++ b/coreutils/expr.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Busybox modifications | 8 | * Busybox modifications |
9 | * Copyright (c) 2000 Edward Betts <edward@debian.org>. | 9 | * Copyright (c) 2000 Edward Betts <edward@debian.org>. |
10 | * Aug 2003 Vladimir Oleynik - reduced 464 bytes. | ||
10 | * | 11 | * |
11 | * this program is free software; you can redistribute it and/or modify | 12 | * this program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the gnu general public license as published by | 13 | * it under the terms of the gnu general public license as published by |
@@ -40,6 +41,7 @@ | |||
40 | #include <stdlib.h> | 41 | #include <stdlib.h> |
41 | #include <regex.h> | 42 | #include <regex.h> |
42 | #include <sys/types.h> | 43 | #include <sys/types.h> |
44 | #include <errno.h> | ||
43 | #include "busybox.h" | 45 | #include "busybox.h" |
44 | 46 | ||
45 | 47 | ||
@@ -135,10 +137,8 @@ static int null (VALUE *v) | |||
135 | switch (v->type) { | 137 | switch (v->type) { |
136 | case integer: | 138 | case integer: |
137 | return v->u.i == 0; | 139 | return v->u.i == 0; |
138 | case string: | 140 | default: /* string: */ |
139 | return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0; | 141 | return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0; |
140 | default: | ||
141 | abort (); | ||
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
@@ -156,13 +156,9 @@ static void tostring (VALUE *v) | |||
156 | 156 | ||
157 | static int toarith (VALUE *v) | 157 | static int toarith (VALUE *v) |
158 | { | 158 | { |
159 | if(v->type == string) { | ||
159 | int i; | 160 | int i; |
160 | 161 | ||
161 | switch (v->type) { | ||
162 | case integer: | ||
163 | return 1; | ||
164 | case string: | ||
165 | i = 0; | ||
166 | /* Don't interpret the empty string as an integer. */ | 162 | /* Don't interpret the empty string as an integer. */ |
167 | if (v->u.s == 0) | 163 | if (v->u.s == 0) |
168 | return 0; | 164 | return 0; |
@@ -170,10 +166,8 @@ static int toarith (VALUE *v) | |||
170 | free (v->u.s); | 166 | free (v->u.s); |
171 | v->u.i = i; | 167 | v->u.i = i; |
172 | v->type = integer; | 168 | v->type = integer; |
173 | return 1; | ||
174 | default: | ||
175 | abort (); | ||
176 | } | 169 | } |
170 | return 1; | ||
177 | } | 171 | } |
178 | 172 | ||
179 | /* Return nonzero if the next token matches STR exactly. | 173 | /* Return nonzero if the next token matches STR exactly. |
@@ -189,56 +183,59 @@ nextarg (char *str) | |||
189 | 183 | ||
190 | /* The comparison operator handling functions. */ | 184 | /* The comparison operator handling functions. */ |
191 | 185 | ||
192 | #define cmpf(name, rel) \ | 186 | static int cmp_common (VALUE *l, VALUE *r, int op) |
193 | static int name (VALUE *l, VALUE *r) \ | 187 | { |
194 | { \ | 188 | int cmpval; |
195 | if (l->type == string || r->type == string) { \ | ||
196 | tostring (l); \ | ||
197 | tostring (r); \ | ||
198 | return strcmp (l->u.s, r->u.s) rel 0; \ | ||
199 | } \ | ||
200 | else \ | ||
201 | return l->u.i rel r->u.i; \ | ||
202 | } | ||
203 | cmpf (less_than, <) | ||
204 | cmpf (less_equal, <=) | ||
205 | cmpf (equal, ==) | ||
206 | cmpf (not_equal, !=) | ||
207 | cmpf (greater_equal, >=) | ||
208 | cmpf (greater_than, >) | ||
209 | 189 | ||
210 | #undef cmpf | 190 | if (l->type == string || r->type == string) { |
191 | tostring (l); | ||
192 | tostring (r); | ||
193 | cmpval = strcmp (l->u.s, r->u.s); | ||
194 | } | ||
195 | else | ||
196 | cmpval = l->u.i - r->u.i; | ||
197 | switch(op) { | ||
198 | case '<': | ||
199 | return cmpval < 0; | ||
200 | case ('L'+'E'): | ||
201 | return cmpval <= 0; | ||
202 | case '=': | ||
203 | return cmpval == 0; | ||
204 | case '!': | ||
205 | return cmpval != 0; | ||
206 | case '>': | ||
207 | return cmpval > 0; | ||
208 | default: /* >= */ | ||
209 | return cmpval >= 0; | ||
210 | } | ||
211 | } | ||
211 | 212 | ||
212 | /* The arithmetic operator handling functions. */ | 213 | /* The arithmetic operator handling functions. */ |
213 | 214 | ||
214 | #define arithf(name, op) \ | 215 | static int arithmetic_common (VALUE *l, VALUE *r, int op) |
215 | static \ | 216 | { |
216 | int name (VALUE *l, VALUE *r) \ | 217 | int li, ri; |
217 | { \ | 218 | |
218 | if (!toarith (l) || !toarith (r)) \ | 219 | if (!toarith (l) || !toarith (r)) |
219 | bb_error_msg_and_die ("non-numeric argument"); \ | 220 | bb_error_msg_and_die ("non-numeric argument"); |
220 | return l->u.i op r->u.i; \ | 221 | li = l->u.i; |
221 | } | 222 | ri = r->u.i; |
222 | 223 | if((op == '/' || op == '%') && ri == 0) | |
223 | #define arithdivf(name, op) \ | 224 | bb_error_msg_and_die ( "division by zero"); |
224 | static int name (VALUE *l, VALUE *r) \ | 225 | switch(op) { |
225 | { \ | 226 | case '+': |
226 | if (!toarith (l) || !toarith (r)) \ | 227 | return li + ri; |
227 | bb_error_msg_and_die ( "non-numeric argument"); \ | 228 | case '-': |
228 | if (r->u.i == 0) \ | 229 | return li - ri; |
229 | bb_error_msg_and_die ( "division by zero"); \ | 230 | case '*': |
230 | return l->u.i op r->u.i; \ | 231 | return li * ri; |
232 | case '/': | ||
233 | return li / ri; | ||
234 | default: | ||
235 | return li % ri; | ||
236 | } | ||
231 | } | 237 | } |
232 | 238 | ||
233 | arithf (plus, +) | ||
234 | arithf (minus, -) | ||
235 | arithf (multiply, *) | ||
236 | arithdivf (divide, /) | ||
237 | arithdivf (mod, %) | ||
238 | |||
239 | #undef arithf | ||
240 | #undef arithdivf | ||
241 | |||
242 | /* Do the : operator. | 239 | /* Do the : operator. |
243 | SV is the VALUE for the lhs (the string), | 240 | SV is the VALUE for the lhs (the string), |
244 | PV is the VALUE for the rhs (the pattern). */ | 241 | PV is the VALUE for the rhs (the pattern). */ |
@@ -408,21 +405,21 @@ static VALUE *eval5 (void) | |||
408 | static VALUE *eval4 (void) | 405 | static VALUE *eval4 (void) |
409 | { | 406 | { |
410 | VALUE *l, *r; | 407 | VALUE *l, *r; |
411 | int (*fxn) (VALUE *, VALUE *), val; | 408 | int op, val; |
412 | 409 | ||
413 | l = eval5 (); | 410 | l = eval5 (); |
414 | while (1) { | 411 | while (1) { |
415 | if (nextarg ("*")) | 412 | if (nextarg ("*")) |
416 | fxn = multiply; | 413 | op = '*'; |
417 | else if (nextarg ("/")) | 414 | else if (nextarg ("/")) |
418 | fxn = divide; | 415 | op = '/'; |
419 | else if (nextarg ("%")) | 416 | else if (nextarg ("%")) |
420 | fxn = mod; | 417 | op = '%'; |
421 | else | 418 | else |
422 | return l; | 419 | return l; |
423 | args++; | 420 | args++; |
424 | r = eval5 (); | 421 | r = eval5 (); |
425 | val = (*fxn) (l, r); | 422 | val = arithmetic_common (l, r, op); |
426 | freev (l); | 423 | freev (l); |
427 | freev (r); | 424 | freev (r); |
428 | l = int_value (val); | 425 | l = int_value (val); |
@@ -434,19 +431,19 @@ static VALUE *eval4 (void) | |||
434 | static VALUE *eval3 (void) | 431 | static VALUE *eval3 (void) |
435 | { | 432 | { |
436 | VALUE *l, *r; | 433 | VALUE *l, *r; |
437 | int (*fxn) (VALUE *, VALUE *), val; | 434 | int op, val; |
438 | 435 | ||
439 | l = eval4 (); | 436 | l = eval4 (); |
440 | while (1) { | 437 | while (1) { |
441 | if (nextarg ("+")) | 438 | if (nextarg ("+")) |
442 | fxn = plus; | 439 | op = '+'; |
443 | else if (nextarg ("-")) | 440 | else if (nextarg ("-")) |
444 | fxn = minus; | 441 | op = '+'; |
445 | else | 442 | else |
446 | return l; | 443 | return l; |
447 | args++; | 444 | args++; |
448 | r = eval4 (); | 445 | r = eval4 (); |
449 | val = (*fxn) (l, r); | 446 | val = arithmetic_common (l, r, op); |
450 | freev (l); | 447 | freev (l); |
451 | freev (r); | 448 | freev (r); |
452 | l = int_value (val); | 449 | l = int_value (val); |
@@ -458,29 +455,29 @@ static VALUE *eval3 (void) | |||
458 | static VALUE *eval2 (void) | 455 | static VALUE *eval2 (void) |
459 | { | 456 | { |
460 | VALUE *l, *r; | 457 | VALUE *l, *r; |
461 | int (*fxn) (VALUE *, VALUE *), val; | 458 | int op, val; |
462 | 459 | ||
463 | l = eval3 (); | 460 | l = eval3 (); |
464 | while (1) { | 461 | while (1) { |
465 | if (nextarg ("<")) | 462 | if (nextarg ("<")) |
466 | fxn = less_than; | 463 | op = '<'; |
467 | else if (nextarg ("<=")) | 464 | else if (nextarg ("<=")) |
468 | fxn = less_equal; | 465 | op = 'L'+'E'; |
469 | else if (nextarg ("=") || nextarg ("==")) | 466 | else if (nextarg ("=") || nextarg ("==")) |
470 | fxn = equal; | 467 | op = '='; |
471 | else if (nextarg ("!=")) | 468 | else if (nextarg ("!=")) |
472 | fxn = not_equal; | 469 | op = '!'; |
473 | else if (nextarg (">=")) | 470 | else if (nextarg (">=")) |
474 | fxn = greater_equal; | 471 | op = 'G'+'E'; |
475 | else if (nextarg (">")) | 472 | else if (nextarg (">")) |
476 | fxn = greater_than; | 473 | op = '>'; |
477 | else | 474 | else |
478 | return l; | 475 | return l; |
479 | args++; | 476 | args++; |
480 | r = eval3 (); | 477 | r = eval3 (); |
481 | toarith (l); | 478 | toarith (l); |
482 | toarith (r); | 479 | toarith (r); |
483 | val = (*fxn) (l, r); | 480 | val = cmp_common (l, r, op); |
484 | freev (l); | 481 | freev (l); |
485 | freev (r); | 482 | freev (r); |
486 | l = int_value (val); | 483 | l = int_value (val); |