aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2007-03-30 18:23:36 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2007-03-30 18:23:36 +0000
commitcc890264d9a0d3c2898c20d5d45cd43959339da4 (patch)
tree8385cdb209b12e65d76c1400242145fbff69cbc8
parenteceecea568a483a3acec2d4c03228b39ae2d6501 (diff)
downloadbusybox-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.c227
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)
89enum token_types { 95enum token_types {
90 UNOP, 96 UNOP,
91 BINOP, 97 BINOP,
@@ -95,8 +101,8 @@ enum token_types {
95}; 101};
96 102
97static const struct t_op { 103static 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
367static int filstat(char *nm, enum token mode) 373static 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; 424filetype:
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
446static enum token t_lex(char *s) 447static 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?
466static arith_t getn(const char *s) 468static 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()
559static int is_a_group_member(gid_t gid) 564static int is_a_group_member(gid_t gid)
560{ 565{
561 int i; 566 int i;