diff options
author | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2007-03-30 18:23:36 +0000 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2007-03-30 18:23:36 +0000 |
commit | cc890264d9a0d3c2898c20d5d45cd43959339da4 (patch) | |
tree | 8385cdb209b12e65d76c1400242145fbff69cbc8 /coreutils/test.c | |
parent | eceecea568a483a3acec2d4c03228b39ae2d6501 (diff) | |
download | busybox-w32-cc890264d9a0d3c2898c20d5d45cd43959339da4.tar.gz busybox-w32-cc890264d9a0d3c2898c20d5d45cd43959339da4.tar.bz2 busybox-w32-cc890264d9a0d3c2898c20d5d45cd43959339da4.zip |
- debloat test. untested.
text data bss dec hex filename
3154 0 172 3326 cfe test.o.oorig
2683 0 172 2855 b27 test.o
This applet should be rewritten not to use such odd lexer semantics.
It duplicates code from all over the place (see XXX).
brrr
Diffstat (limited to 'coreutils/test.c')
-rw-r--r-- | coreutils/test.c | 227 |
1 files changed, 116 insertions, 111 deletions
diff --git a/coreutils/test.c b/coreutils/test.c index 6e0d5d38e..813cde47c 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * modified by Herbert Xu to be used as built-in in ash. | 12 | * modified by Herbert Xu to be used as built-in in ash. |
13 | * modified by Erik Andersen <andersen@codepoet.org> to be used | 13 | * modified by Erik Andersen <andersen@codepoet.org> to be used |
14 | * in busybox. | 14 | * in busybox. |
15 | * modified by Bernhard Fischer to be useable (i.e. a bit less bloaty). | ||
15 | * | 16 | * |
16 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 17 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
17 | * | 18 | * |
@@ -85,7 +86,12 @@ enum token { | |||
85 | RPAREN, | 86 | RPAREN, |
86 | OPERAND | 87 | OPERAND |
87 | }; | 88 | }; |
88 | 89 | #define __is_int_op(a) (((unsigned char)((a) - INTEQ)) <= 5) | |
90 | #define __is_str_op(a) (((unsigned char)((a) - STREZ)) <= 5) | ||
91 | #define __is_file_op(a) (((unsigned char)((a) - FILNT)) <= 2) | ||
92 | #define __is_file_access(a) (((unsigned char)((a) - FILRD)) <= 2) | ||
93 | #define __is_file_type(a) (((unsigned char)((a) - FILREG)) <= 5) | ||
94 | #define __is_file_bit(a) (((unsigned char)((a) - FILSUID)) <= 2) | ||
89 | enum token_types { | 95 | enum token_types { |
90 | UNOP, | 96 | UNOP, |
91 | BINOP, | 97 | BINOP, |
@@ -95,8 +101,8 @@ enum token_types { | |||
95 | }; | 101 | }; |
96 | 102 | ||
97 | static const struct t_op { | 103 | static const struct t_op { |
98 | const char *op_text; | 104 | const char * const op_text; |
99 | short op_num, op_type; | 105 | unsigned char op_num, op_type; |
100 | } ops[] = { | 106 | } ops[] = { |
101 | { | 107 | { |
102 | "-r", FILRD, UNOP}, { | 108 | "-r", FILRD, UNOP}, { |
@@ -206,34 +212,21 @@ int bb_test(int argc, char **argv) | |||
206 | ngroups = 0; | 212 | ngroups = 0; |
207 | 213 | ||
208 | /* Implement special cases from POSIX.2, section 4.62.4 */ | 214 | /* Implement special cases from POSIX.2, section 4.62.4 */ |
209 | switch (argc) { | 215 | if (argc == 1) |
210 | case 1: | ||
211 | return 1; | 216 | return 1; |
212 | case 2: | 217 | if (argc == 2) |
213 | return *argv[1] == '\0'; | 218 | return *argv[1] == '\0'; |
214 | case 3: | 219 | //assert(argc); |
215 | if (argv[1][0] == '!' && argv[1][1] == '\0') { | 220 | if (LONE_CHAR(argv[1], '!')) { |
221 | bool _off; | ||
222 | if (argc == 3) | ||
216 | return *argv[2] != '\0'; | 223 | return *argv[2] != '\0'; |
224 | _off = argc - 4; | ||
225 | if (t_lex(argv[2+_off]), t_wp_op && t_wp_op->op_type == BINOP) { | ||
226 | t_wp = &argv[1+_off]; | ||
227 | return binop() == 0; | ||
217 | } | 228 | } |
218 | break; | ||
219 | case 4: | ||
220 | if (argv[1][0] != '!' || argv[1][1] != '\0') { | ||
221 | if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) { | ||
222 | t_wp = &argv[1]; | ||
223 | return binop() == 0; | ||
224 | } | ||
225 | } | ||
226 | break; | ||
227 | case 5: | ||
228 | if (argv[1][0] == '!' && argv[1][1] == '\0') { | ||
229 | if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) { | ||
230 | t_wp = &argv[2]; | ||
231 | return binop() != 0; | ||
232 | } | ||
233 | } | ||
234 | break; | ||
235 | } | 229 | } |
236 | |||
237 | t_wp = &argv[1]; | 230 | t_wp = &argv[1]; |
238 | res = !oexpr(t_lex(*t_wp)); | 231 | res = !oexpr(t_lex(*t_wp)); |
239 | 232 | ||
@@ -301,16 +294,14 @@ static arith_t primary(enum token n) | |||
301 | /* unary expression */ | 294 | /* unary expression */ |
302 | if (*++t_wp == NULL) | 295 | if (*++t_wp == NULL) |
303 | syntax(t_wp_op->op_text, "argument expected"); | 296 | syntax(t_wp_op->op_text, "argument expected"); |
304 | switch (n) { | 297 | if (n == STREZ) |
305 | case STREZ: | ||
306 | return strlen(*t_wp) == 0; | 298 | return strlen(*t_wp) == 0; |
307 | case STRNZ: | 299 | else if (n == STRNZ) |
308 | return strlen(*t_wp) != 0; | 300 | return strlen(*t_wp) != 0; |
309 | case FILTT: | 301 | else if (n == FILTT) |
310 | return isatty(getn(*t_wp)); | 302 | return isatty(getn(*t_wp)); |
311 | default: | 303 | else |
312 | return filstat(*t_wp, n); | 304 | return filstat(*t_wp, n); |
313 | } | ||
314 | } | 305 | } |
315 | 306 | ||
316 | if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { | 307 | if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { |
@@ -324,6 +315,7 @@ static int binop(void) | |||
324 | { | 315 | { |
325 | const char *opnd1, *opnd2; | 316 | const char *opnd1, *opnd2; |
326 | struct t_op const *op; | 317 | struct t_op const *op; |
318 | smallint val1, val2; | ||
327 | 319 | ||
328 | opnd1 = *t_wp; | 320 | opnd1 = *t_wp; |
329 | (void) t_lex(*++t_wp); | 321 | (void) t_lex(*++t_wp); |
@@ -332,42 +324,56 @@ static int binop(void) | |||
332 | if ((opnd2 = *++t_wp) == (char *) 0) | 324 | if ((opnd2 = *++t_wp) == (char *) 0) |
333 | syntax(op->op_text, "argument expected"); | 325 | syntax(op->op_text, "argument expected"); |
334 | 326 | ||
335 | switch (op->op_num) { | 327 | if (__is_int_op(op->op_num)) { |
336 | case STREQ: | 328 | val1 = getn(opnd1); |
337 | return strcmp(opnd1, opnd2) == 0; | 329 | val2 = getn(opnd2); |
338 | case STRNE: | 330 | if (op->op_num == INTEQ) |
339 | return strcmp(opnd1, opnd2) != 0; | 331 | return val1 == val2; |
340 | case STRLT: | 332 | if (op->op_num == INTNE) |
341 | return strcmp(opnd1, opnd2) < 0; | 333 | return val1 != val2; |
342 | case STRGT: | 334 | if (op->op_num == INTGE) |
343 | return strcmp(opnd1, opnd2) > 0; | 335 | return val1 >= val2; |
344 | case INTEQ: | 336 | if (op->op_num == INTGT) |
345 | return getn(opnd1) == getn(opnd2); | 337 | return val1 > val2; |
346 | case INTNE: | 338 | if (op->op_num == INTLE) |
347 | return getn(opnd1) != getn(opnd2); | 339 | return val1 <= val2; |
348 | case INTGE: | 340 | if (op->op_num == INTLT) |
349 | return getn(opnd1) >= getn(opnd2); | 341 | return val1 < val2; |
350 | case INTGT: | 342 | } |
351 | return getn(opnd1) > getn(opnd2); | 343 | if (__is_str_op(op->op_num)) { |
352 | case INTLE: | 344 | val1 = strcmp(opnd1, opnd2); |
353 | return getn(opnd1) <= getn(opnd2); | 345 | if (op->op_num == STREQ) |
354 | case INTLT: | 346 | return val1 == 0; |
355 | return getn(opnd1) < getn(opnd2); | 347 | if (op->op_num == STRNE) |
356 | case FILNT: | 348 | return val1 != 0; |
357 | return newerf(opnd1, opnd2); | 349 | if (op->op_num == STRLT) |
358 | case FILOT: | 350 | return val1 < 0; |
359 | return olderf(opnd1, opnd2); | 351 | if (op->op_num == STRGT) |
360 | case FILEQ: | 352 | return val1 > 0; |
361 | return equalf(opnd1, opnd2); | ||
362 | } | 353 | } |
363 | /* NOTREACHED */ | 354 | /* We are sure that these three are by now the only binops we didn't check |
364 | return 1; | 355 | * yet, so we do not check if the class is correct: |
356 | */ | ||
357 | /* if (__is_file_op(op->op_num)) */ | ||
358 | { | ||
359 | struct stat b1, b2; | ||
360 | |||
361 | if (!(!stat(opnd1, &b1) && !stat(opnd2, &b2))) | ||
362 | return 0; /* false, since stat failed */ | ||
363 | if (op->op_num == FILNT) | ||
364 | return b1.st_mtime > b2.st_mtime; | ||
365 | if (op->op_num == FILOT) | ||
366 | return b1.st_mtime < b2.st_mtime; | ||
367 | if (op->op_num == FILEQ) | ||
368 | return b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino; | ||
369 | } | ||
370 | return 1; /* NOTREACHED */ | ||
365 | } | 371 | } |
366 | 372 | ||
367 | static int filstat(char *nm, enum token mode) | 373 | static int filstat(char *nm, enum token mode) |
368 | { | 374 | { |
369 | struct stat s; | 375 | struct stat s; |
370 | unsigned int i; | 376 | int i; |
371 | 377 | ||
372 | if (mode == FILSYM) { | 378 | if (mode == FILSYM) { |
373 | #ifdef S_IFLNK | 379 | #ifdef S_IFLNK |
@@ -381,66 +387,61 @@ static int filstat(char *nm, enum token mode) | |||
381 | 387 | ||
382 | if (stat(nm, &s) != 0) | 388 | if (stat(nm, &s) != 0) |
383 | return 0; | 389 | return 0; |
384 | 390 | if (mode == FILEXIST) | |
385 | switch (mode) { | ||
386 | case FILRD: | ||
387 | return test_eaccess(nm, R_OK) == 0; | ||
388 | case FILWR: | ||
389 | return test_eaccess(nm, W_OK) == 0; | ||
390 | case FILEX: | ||
391 | return test_eaccess(nm, X_OK) == 0; | ||
392 | case FILEXIST: | ||
393 | return 1; | 391 | return 1; |
394 | case FILREG: | 392 | else if (__is_file_access(mode)) { |
395 | i = S_IFREG; | 393 | if (mode == FILRD) |
396 | goto filetype; | 394 | i = R_OK; |
397 | case FILDIR: | 395 | if (mode == FILWR) |
398 | i = S_IFDIR; | 396 | i = W_OK; |
399 | goto filetype; | 397 | if (mode == FILEX) |
400 | case FILCDEV: | 398 | i = X_OK; |
401 | i = S_IFCHR; | 399 | return test_eaccess(nm, i) == 0; |
402 | goto filetype; | 400 | } |
403 | case FILBDEV: | 401 | else if (__is_file_type(mode)) { |
404 | i = S_IFBLK; | 402 | if (mode == FILREG) |
405 | goto filetype; | 403 | i = S_IFREG; |
406 | case FILFIFO: | 404 | if (mode == FILDIR) |
405 | i = S_IFDIR; | ||
406 | if (mode == FILCDEV) | ||
407 | i = S_IFCHR; | ||
408 | if (mode == FILBDEV) | ||
409 | i = S_IFBLK; | ||
410 | if (mode == FILFIFO) { | ||
407 | #ifdef S_IFIFO | 411 | #ifdef S_IFIFO |
408 | i = S_IFIFO; | 412 | i = S_IFIFO; |
409 | goto filetype; | ||
410 | #else | 413 | #else |
411 | return 0; | 414 | return 0; |
412 | #endif | 415 | #endif |
413 | case FILSOCK: | 416 | } |
417 | if (mode == FILSOCK) { | ||
414 | #ifdef S_IFSOCK | 418 | #ifdef S_IFSOCK |
415 | i = S_IFSOCK; | 419 | i = S_IFSOCK; |
416 | goto filetype; | ||
417 | #else | 420 | #else |
418 | return 0; | 421 | return 0; |
419 | #endif | 422 | #endif |
420 | case FILSUID: | 423 | } |
421 | i = S_ISUID; | 424 | filetype: |
422 | goto filebit; | 425 | return ((s.st_mode & S_IFMT) == i); |
423 | case FILSGID: | 426 | } |
424 | i = S_ISGID; | 427 | else if (__is_file_bit(mode)) { |
425 | goto filebit; | 428 | if (mode == FILSUID) |
426 | case FILSTCK: | 429 | i = S_ISUID; |
427 | i = S_ISVTX; | 430 | if (mode == FILSGID) |
428 | goto filebit; | 431 | i = S_ISGID; |
429 | case FILGZ: | 432 | if (mode == FILSTCK) |
433 | i = S_ISVTX; | ||
434 | return ((s.st_mode & i) != 0); | ||
435 | } | ||
436 | else if (mode == FILGZ) | ||
430 | return s.st_size > 0L; | 437 | return s.st_size > 0L; |
431 | case FILUID: | 438 | else if (mode == FILUID) |
432 | return s.st_uid == geteuid(); | 439 | return s.st_uid == geteuid(); |
433 | case FILGID: | 440 | else if (mode == FILGID) |
434 | return s.st_gid == getegid(); | 441 | return s.st_gid == getegid(); |
435 | default: | 442 | else |
436 | return 1; | 443 | return 1; /* NOTREACHED */ |
437 | } | ||
438 | |||
439 | filetype: | ||
440 | return ((s.st_mode & S_IFMT) == i); | ||
441 | 444 | ||
442 | filebit: | ||
443 | return ((s.st_mode & i) != 0); | ||
444 | } | 445 | } |
445 | 446 | ||
446 | static enum token t_lex(char *s) | 447 | static enum token t_lex(char *s) |
@@ -463,6 +464,7 @@ static enum token t_lex(char *s) | |||
463 | } | 464 | } |
464 | 465 | ||
465 | /* atoi with error detection */ | 466 | /* atoi with error detection */ |
467 | //XXX: FIXME: duplicate of existing libbb function? | ||
466 | static arith_t getn(const char *s) | 468 | static arith_t getn(const char *s) |
467 | { | 469 | { |
468 | char *p; | 470 | char *p; |
@@ -556,6 +558,9 @@ static void initialize_group_array(void) | |||
556 | } | 558 | } |
557 | 559 | ||
558 | /* Return non-zero if GID is one that we have in our groups list. */ | 560 | /* Return non-zero if GID is one that we have in our groups list. */ |
561 | //XXX: FIXME: duplicate of existing libbb function? | ||
562 | // see toplevel TODO file: | ||
563 | // possible code duplication ingroup() and is_a_group_member() | ||
559 | static int is_a_group_member(gid_t gid) | 564 | static int is_a_group_member(gid_t gid) |
560 | { | 565 | { |
561 | int i; | 566 | int i; |