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 | |
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
-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; |