Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/coreutils/expr.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/coreutils/expr.c
r1765 r2725 12 12 * - 64 math support 13 13 * 14 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.14 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 15 15 */ 16 16 … … 29 29 #include "xregex.h" 30 30 31 /* The kinds of value we can have. */32 enum valtype {33 integer,34 string35 };36 typedef enum valtype TYPE;37 38 31 #if ENABLE_EXPR_MATH_SUPPORT_64 39 32 typedef int64_t arith_t; … … 52 45 /* TODO: use bb_strtol[l]? It's easier to check for errors... */ 53 46 47 /* The kinds of value we can have. */ 48 enum { 49 INTEGER, 50 STRING 51 }; 52 54 53 /* A value is.... */ 55 54 struct valinfo { 56 TYPE type;/* Which kind. */57 union { 55 smallint type; /* Which kind. */ 56 union { /* The value itself. */ 58 57 arith_t i; 59 58 char *s; … … 65 64 struct globals { 66 65 char **args; 67 } ;66 } FIX_ALIASING; 68 67 #define G (*(struct globals*)&bb_common_bufsiz1) 69 68 … … 78 77 VALUE *v; 79 78 80 v = xmalloc(sizeof(VALUE)); 81 v->type = integer; 79 v = xzalloc(sizeof(VALUE)); 80 if (INTEGER) /* otherwise xzaaloc did it already */ 81 v->type = INTEGER; 82 82 v->u.i = i; 83 83 return v; … … 90 90 VALUE *v; 91 91 92 v = xmalloc(sizeof(VALUE)); 93 v->type = string; 92 v = xzalloc(sizeof(VALUE)); 93 if (STRING) /* otherwise xzaaloc did it already */ 94 v->type = STRING; 94 95 v->u.s = xstrdup(s); 95 96 return v; … … 98 99 /* Free VALUE V, including structure components. */ 99 100 100 static void freev(VALUE * 101 { 102 if (v->type == string)101 static void freev(VALUE *v) 102 { 103 if (v->type == STRING) 103 104 free(v->u.s); 104 105 free(v); … … 107 108 /* Return nonzero if V is a null-string or zero-number. */ 108 109 109 static int null(VALUE * 110 { 111 if (v->type == integer)110 static int null(VALUE *v) 111 { 112 if (v->type == INTEGER) 112 113 return v->u.i == 0; 113 /* string: */114 /* STRING: */ 114 115 return v->u.s[0] == '\0' || LONE_CHAR(v->u.s, '0'); 115 116 } 116 117 117 /* Coerce V to a stringvalue (can't fail). */118 119 static void tostring(VALUE * 120 { 121 if (v->type == integer) {118 /* Coerce V to a STRING value (can't fail). */ 119 120 static void tostring(VALUE *v) 121 { 122 if (v->type == INTEGER) { 122 123 v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i); 123 v->type = string;124 } 125 } 126 127 /* Coerce V to an integervalue. Return 1 on success, 0 on failure. */128 129 static bool toarith(VALUE * 130 { 131 if (v->type == string) {124 v->type = STRING; 125 } 126 } 127 128 /* Coerce V to an INTEGER value. Return 1 on success, 0 on failure. */ 129 130 static bool toarith(VALUE *v) 131 { 132 if (v->type == STRING) { 132 133 arith_t i; 133 134 char *e; … … 140 141 free(v->u.s); 141 142 v->u.i = i; 142 v->type = integer;143 v->type = INTEGER; 143 144 } 144 145 return 1; 145 146 } 146 147 147 /* Return nonzeroif the next token matches STR exactly.148 /* Return str[0]+str[1] if the next token matches STR exactly. 148 149 STR must not be NULL. */ 149 150 150 static boolnextarg(const char *str)151 { 152 if (*G.args == NULL )151 static int nextarg(const char *str) 152 { 153 if (*G.args == NULL || strcmp(*G.args, str) != 0) 153 154 return 0; 154 return strcmp(*G.args, str) == 0;155 return (unsigned char)str[0] + (unsigned char)str[1]; 155 156 } 156 157 157 158 /* The comparison operator handling functions. */ 158 159 159 static int cmp_common(VALUE * l, VALUE * r, int op) 160 { 161 int cmpval; 162 163 if (l->type == string || r->type == string) { 160 static int cmp_common(VALUE *l, VALUE *r, int op) 161 { 162 arith_t ll, rr; 163 164 ll = l->u.i; 165 rr = r->u.i; 166 if (l->type == STRING || r->type == STRING) { 164 167 tostring(l); 165 168 tostring(r); 166 cmpval = strcmp(l->u.s, r->u.s); 167 } else 168 cmpval = l->u.i - r->u.i; 169 ll = strcmp(l->u.s, r->u.s); 170 rr = 0; 171 } 172 /* calculating ll - rr and checking the result is prone to overflows. 173 * We'll do it differently: */ 169 174 if (op == '<') 170 return cmpval < 0;171 if (op == (' L' + 'E'))172 return cmpval <= 0;173 if (op == '=' )174 return cmpval == 0;175 if (op == '!' )176 return cmpval != 0;175 return ll < rr; 176 if (op == ('<' + '=')) 177 return ll <= rr; 178 if (op == '=' || (op == '=' + '=')) 179 return ll == rr; 180 if (op == '!' + '=') 181 return ll != rr; 177 182 if (op == '>') 178 return cmpval > 0;183 return ll > rr; 179 184 /* >= */ 180 return cmpval >= 0;185 return ll >= rr; 181 186 } 182 187 183 188 /* The arithmetic operator handling functions. */ 184 189 185 static arith_t arithmetic_common(VALUE * l, VALUE *r, int op)190 static arith_t arithmetic_common(VALUE *l, VALUE *r, int op) 186 191 { 187 192 arith_t li, ri; … … 191 196 li = l->u.i; 192 197 ri = r->u.i; 193 if ((op == '/' || op == '%') && ri == 0)194 bb_error_msg_and_die("division by zero");195 198 if (op == '+') 196 199 return li + ri; 197 elseif (op == '-')200 if (op == '-') 198 201 return li - ri; 199 elseif (op == '*')202 if (op == '*') 200 203 return li * ri; 201 else if (op == '/') 204 if (ri == 0) 205 bb_error_msg_and_die("division by zero"); 206 if (op == '/') 202 207 return li / ri; 203 else 204 return li % ri; 208 return li % ri; 205 209 } 206 210 … … 209 213 PV is the VALUE for the rhs (the pattern). */ 210 214 211 static VALUE *docolon(VALUE * sv, VALUE * pv) 212 { 215 static VALUE *docolon(VALUE *sv, VALUE *pv) 216 { 217 enum { NMATCH = 2 }; 213 218 VALUE *v; 214 219 regex_t re_buffer; 215 const int NMATCH = 2;216 220 regmatch_t re_regs[NMATCH]; 217 221 … … 220 224 221 225 if (pv->u.s[0] == '^') { 222 bb_error_msg( "\223 warning: unportable BRE: `%s': using `^' as the first character\n\ 224 of a basic regular expression is not portable; it is beingignored", pv->u.s);226 bb_error_msg( 227 "warning: '%s': using '^' as the first character\n" 228 "of a basic regular expression is not portable; it is ignored", pv->u.s); 225 229 } 226 230 227 231 memset(&re_buffer, 0, sizeof(re_buffer)); 228 memset(re_regs, 0, sizeof( *re_regs));232 memset(re_regs, 0, sizeof(re_regs)); 229 233 xregcomp(&re_buffer, pv->u.s, 0); 230 234 231 235 /* expr uses an anchored pattern match, so check that there was a 232 236 * match and that the match starts at offset 0. */ 233 if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && 234 re_regs[0].rm_so == 0) { 237 if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH 238 && re_regs[0].rm_so == 0 239 ) { 235 240 /* Were \(...\) used? */ 236 if (re_buffer.re_nsub > 0 ) {241 if (re_buffer.re_nsub > 0 && re_regs[1].rm_so >= 0) { 237 242 sv->u.s[re_regs[1].rm_eo] = '\0'; 238 243 v = str_value(sv->u.s + re_regs[1].rm_so); 239 } else 244 } else { 240 245 v = int_value(re_regs[0].rm_eo); 246 } 241 247 } else { 242 248 /* Match failed -- return the right kind of null. */ … … 246 252 v = int_value(0); 247 253 } 248 //FIXME: sounds like here is a bit missing:regfree(&re_buffer);254 regfree(&re_buffer); 249 255 return v; 250 256 } … … 328 334 else { 329 335 v = xmalloc(sizeof(VALUE)); 330 v->type = string;336 v->type = STRING; 331 337 v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); 332 338 } … … 336 342 } 337 343 return v; 338 339 344 } 340 345 … … 368 373 l = eval5(); 369 374 while (1) { 370 if (nextarg("*")) 371 op = '*'; 372 else if (nextarg("/")) 373 op = '/'; 374 else if (nextarg("%")) 375 op = '%'; 376 else 377 return l; 375 op = nextarg("*"); 376 if (!op) { op = nextarg("/"); 377 if (!op) { op = nextarg("%"); 378 if (!op) return l; 379 }} 378 380 G.args++; 379 381 r = eval5(); … … 395 397 l = eval4(); 396 398 while (1) { 397 if (nextarg("+")) 398 op = '+'; 399 else if (nextarg("-")) 400 op = '-'; 401 else 402 return l; 399 op = nextarg("+"); 400 if (!op) { 401 op = nextarg("-"); 402 if (!op) return l; 403 } 403 404 G.args++; 404 405 r = eval4(); … … 420 421 l = eval3(); 421 422 while (1) { 422 if (nextarg("<")) 423 op = '<'; 424 else if (nextarg("<=")) 425 op = 'L' + 'E'; 426 else if (nextarg("=") || nextarg("==")) 427 op = '='; 428 else if (nextarg("!=")) 429 op = '!'; 430 else if (nextarg(">=")) 431 op = 'G' + 'E'; 432 else if (nextarg(">")) 433 op = '>'; 434 else 435 return l; 423 op = nextarg("<"); 424 if (!op) { op = nextarg("<="); 425 if (!op) { op = nextarg("="); 426 if (!op) { op = nextarg("=="); 427 if (!op) { op = nextarg("!="); 428 if (!op) { op = nextarg(">="); 429 if (!op) { op = nextarg(">"); 430 if (!op) return l; 431 }}}}}} 436 432 G.args++; 437 433 r = eval3(); … … 484 480 } 485 481 486 int expr_main(int argc, char **argv) ;487 int expr_main(int argc , char **argv)482 int expr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 483 int expr_main(int argc UNUSED_PARAM, char **argv) 488 484 { 489 485 VALUE *v; 490 486 491 if (argc == 1) { 487 xfunc_error_retval = 2; /* coreutils compat */ 488 G.args = argv + 1; 489 if (*G.args == NULL) { 492 490 bb_error_msg_and_die("too few arguments"); 493 491 } 494 495 G.args = argv + 1;496 497 492 v = eval(); 498 493 if (*G.args) 499 494 bb_error_msg_and_die("syntax error"); 500 501 if (v->type == integer) 495 if (v->type == INTEGER) 502 496 printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); 503 497 else 504 498 puts(v->u.s); 505 506 499 fflush_stdout_and_exit(null(v)); 507 500 }
Note:
See TracChangeset
for help on using the changeset viewer.