- 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
This commit is contained in:
Bernhard Reutner-Fischer 2007-03-30 18:23:36 +00:00
parent eceecea568
commit cc890264d9
1 changed files with 124 additions and 119 deletions

View File

@ -12,6 +12,7 @@
* modified by Herbert Xu to be used as built-in in ash.
* modified by Erik Andersen <andersen@codepoet.org> to be used
* in busybox.
* modified by Bernhard Fischer to be useable (i.e. a bit less bloaty).
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
@ -85,7 +86,12 @@ enum token {
RPAREN,
OPERAND
};
#define __is_int_op(a) (((unsigned char)((a) - INTEQ)) <= 5)
#define __is_str_op(a) (((unsigned char)((a) - STREZ)) <= 5)
#define __is_file_op(a) (((unsigned char)((a) - FILNT)) <= 2)
#define __is_file_access(a) (((unsigned char)((a) - FILRD)) <= 2)
#define __is_file_type(a) (((unsigned char)((a) - FILREG)) <= 5)
#define __is_file_bit(a) (((unsigned char)((a) - FILSUID)) <= 2)
enum token_types {
UNOP,
BINOP,
@ -95,8 +101,8 @@ enum token_types {
};
static const struct t_op {
const char *op_text;
short op_num, op_type;
const char * const op_text;
unsigned char op_num, op_type;
} ops[] = {
{
"-r", FILRD, UNOP}, {
@ -206,34 +212,21 @@ int bb_test(int argc, char **argv)
ngroups = 0;
/* Implement special cases from POSIX.2, section 4.62.4 */
switch (argc) {
case 1:
if (argc == 1)
return 1;
case 2:
if (argc == 2)
return *argv[1] == '\0';
case 3:
if (argv[1][0] == '!' && argv[1][1] == '\0') {
//assert(argc);
if (LONE_CHAR(argv[1], '!')) {
bool _off;
if (argc == 3)
return *argv[2] != '\0';
_off = argc - 4;
if (t_lex(argv[2+_off]), t_wp_op && t_wp_op->op_type == BINOP) {
t_wp = &argv[1+_off];
return binop() == 0;
}
break;
case 4:
if (argv[1][0] != '!' || argv[1][1] != '\0') {
if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) {
t_wp = &argv[1];
return binop() == 0;
}
}
break;
case 5:
if (argv[1][0] == '!' && argv[1][1] == '\0') {
if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) {
t_wp = &argv[2];
return binop() != 0;
}
}
break;
}
t_wp = &argv[1];
res = !oexpr(t_lex(*t_wp));
@ -301,16 +294,14 @@ static arith_t primary(enum token n)
/* unary expression */
if (*++t_wp == NULL)
syntax(t_wp_op->op_text, "argument expected");
switch (n) {
case STREZ:
if (n == STREZ)
return strlen(*t_wp) == 0;
case STRNZ:
else if (n == STRNZ)
return strlen(*t_wp) != 0;
case FILTT:
else if (n == FILTT)
return isatty(getn(*t_wp));
default:
else
return filstat(*t_wp, n);
}
}
if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
@ -324,6 +315,7 @@ static int binop(void)
{
const char *opnd1, *opnd2;
struct t_op const *op;
smallint val1, val2;
opnd1 = *t_wp;
(void) t_lex(*++t_wp);
@ -332,42 +324,56 @@ static int binop(void)
if ((opnd2 = *++t_wp) == (char *) 0)
syntax(op->op_text, "argument expected");
switch (op->op_num) {
case STREQ:
return strcmp(opnd1, opnd2) == 0;
case STRNE:
return strcmp(opnd1, opnd2) != 0;
case STRLT:
return strcmp(opnd1, opnd2) < 0;
case STRGT:
return strcmp(opnd1, opnd2) > 0;
case INTEQ:
return getn(opnd1) == getn(opnd2);
case INTNE:
return getn(opnd1) != getn(opnd2);
case INTGE:
return getn(opnd1) >= getn(opnd2);
case INTGT:
return getn(opnd1) > getn(opnd2);
case INTLE:
return getn(opnd1) <= getn(opnd2);
case INTLT:
return getn(opnd1) < getn(opnd2);
case FILNT:
return newerf(opnd1, opnd2);
case FILOT:
return olderf(opnd1, opnd2);
case FILEQ:
return equalf(opnd1, opnd2);
if (__is_int_op(op->op_num)) {
val1 = getn(opnd1);
val2 = getn(opnd2);
if (op->op_num == INTEQ)
return val1 == val2;
if (op->op_num == INTNE)
return val1 != val2;
if (op->op_num == INTGE)
return val1 >= val2;
if (op->op_num == INTGT)
return val1 > val2;
if (op->op_num == INTLE)
return val1 <= val2;
if (op->op_num == INTLT)
return val1 < val2;
}
/* NOTREACHED */
return 1;
if (__is_str_op(op->op_num)) {
val1 = strcmp(opnd1, opnd2);
if (op->op_num == STREQ)
return val1 == 0;
if (op->op_num == STRNE)
return val1 != 0;
if (op->op_num == STRLT)
return val1 < 0;
if (op->op_num == STRGT)
return val1 > 0;
}
/* We are sure that these three are by now the only binops we didn't check
* yet, so we do not check if the class is correct:
*/
/* if (__is_file_op(op->op_num)) */
{
struct stat b1, b2;
if (!(!stat(opnd1, &b1) && !stat(opnd2, &b2)))
return 0; /* false, since stat failed */
if (op->op_num == FILNT)
return b1.st_mtime > b2.st_mtime;
if (op->op_num == FILOT)
return b1.st_mtime < b2.st_mtime;
if (op->op_num == FILEQ)
return b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino;
}
return 1; /* NOTREACHED */
}
static int filstat(char *nm, enum token mode)
{
struct stat s;
unsigned int i;
int i;
if (mode == FILSYM) {
#ifdef S_IFLNK
@ -381,66 +387,61 @@ static int filstat(char *nm, enum token mode)
if (stat(nm, &s) != 0)
return 0;
switch (mode) {
case FILRD:
return test_eaccess(nm, R_OK) == 0;
case FILWR:
return test_eaccess(nm, W_OK) == 0;
case FILEX:
return test_eaccess(nm, X_OK) == 0;
case FILEXIST:
return 1;
case FILREG:
i = S_IFREG;
goto filetype;
case FILDIR:
i = S_IFDIR;
goto filetype;
case FILCDEV:
i = S_IFCHR;
goto filetype;
case FILBDEV:
i = S_IFBLK;
goto filetype;
case FILFIFO:
#ifdef S_IFIFO
i = S_IFIFO;
goto filetype;
#else
return 0;
#endif
case FILSOCK:
#ifdef S_IFSOCK
i = S_IFSOCK;
goto filetype;
#else
return 0;
#endif
case FILSUID:
i = S_ISUID;
goto filebit;
case FILSGID:
i = S_ISGID;
goto filebit;
case FILSTCK:
i = S_ISVTX;
goto filebit;
case FILGZ:
return s.st_size > 0L;
case FILUID:
return s.st_uid == geteuid();
case FILGID:
return s.st_gid == getegid();
default:
if (mode == FILEXIST)
return 1;
else if (__is_file_access(mode)) {
if (mode == FILRD)
i = R_OK;
if (mode == FILWR)
i = W_OK;
if (mode == FILEX)
i = X_OK;
return test_eaccess(nm, i) == 0;
}
else if (__is_file_type(mode)) {
if (mode == FILREG)
i = S_IFREG;
if (mode == FILDIR)
i = S_IFDIR;
if (mode == FILCDEV)
i = S_IFCHR;
if (mode == FILBDEV)
i = S_IFBLK;
if (mode == FILFIFO) {
#ifdef S_IFIFO
i = S_IFIFO;
#else
return 0;
#endif
}
if (mode == FILSOCK) {
#ifdef S_IFSOCK
i = S_IFSOCK;
#else
return 0;
#endif
}
filetype:
return ((s.st_mode & S_IFMT) == i);
}
else if (__is_file_bit(mode)) {
if (mode == FILSUID)
i = S_ISUID;
if (mode == FILSGID)
i = S_ISGID;
if (mode == FILSTCK)
i = S_ISVTX;
return ((s.st_mode & i) != 0);
}
else if (mode == FILGZ)
return s.st_size > 0L;
else if (mode == FILUID)
return s.st_uid == geteuid();
else if (mode == FILGID)
return s.st_gid == getegid();
else
return 1; /* NOTREACHED */
filetype:
return ((s.st_mode & S_IFMT) == i);
filebit:
return ((s.st_mode & i) != 0);
}
static enum token t_lex(char *s)
@ -463,6 +464,7 @@ static enum token t_lex(char *s)
}
/* atoi with error detection */
//XXX: FIXME: duplicate of existing libbb function?
static arith_t getn(const char *s)
{
char *p;
@ -556,6 +558,9 @@ static void initialize_group_array(void)
}
/* Return non-zero if GID is one that we have in our groups list. */
//XXX: FIXME: duplicate of existing libbb function?
// see toplevel TODO file:
// possible code duplication ingroup() and is_a_group_member()
static int is_a_group_member(gid_t gid)
{
int i;