test: stop using lots of bss.

function                                             old     new   delta
test_main                                            425     456     +31
t_lex                                                 69      73      +4
syntax                                               100     104      +4
ptr_to_statics                                         8      12      +4
t_wp_op                                                4       -      -4
t_wp                                                   4       -      -4
ngroups                                                4       -      -4
group_array                                            4       -      -4
binop                                                590     585      -5
oexpr                                                104      97      -7
aexpr                                                101      94      -7
nexpr                                                831     820     -11
leaving                                              156       -    -156
------------------------------------------------------------------------------
(add/remove: 0/5 grow/shrink: 4/4 up/down: 43/-202)          Total: -159 bytes
   text    data     bss     dec     hex filename
 775098     929    9084  785111   bfad7 busybox_old
 775107     933    8908  784948   bfa34 busybox_unstripped
This commit is contained in:
Denis Vlasenko 2007-11-30 07:29:05 +00:00
parent b539c8452f
commit 6672c8e480
3 changed files with 67 additions and 29 deletions

View File

@ -23,7 +23,11 @@
#include "libbb.h"
#include <setjmp.h>
/* This is a NOEXEC applet. Be very careful! */
/* This is a NOFORK applet. Be very careful! */
/* test_main() is called from shells, and we need to be extra careful here.
* This is true regardless of PREFER_APPLETS and STANDALONE_SHELL
* state. */
/* test(1) accepts the following grammar:
@ -85,12 +89,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_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)
#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,
@ -153,13 +157,33 @@ typedef int64_t arith_t;
typedef int arith_t;
#endif
/* Cannot eliminate these static data (do the G trick)
* because of test_main usage from other applets */
static char **t_wp;
static const struct t_op *t_wp_op;
static gid_t *group_array;
static int ngroups;
static jmp_buf leaving;
/* We try to minimize both static and stack usage. */
struct statics {
char **t_wp;
const struct t_op *t_wp_op;
gid_t *group_array;
int ngroups;
jmp_buf leaving;
};
/* Make it reside in writable memory, yet make compiler understand
* that it is not going to change. */
static struct statics *const ptr_to_statics __attribute__ ((section (".data")));
#define S (*ptr_to_statics)
#define t_wp (S.t_wp )
#define t_wp_op (S.t_wp_op )
#define group_array (S.group_array )
#define ngroups (S.ngroups )
#define leaving (S.leaving )
#define INIT_S() do { \
(*(struct statics**)&ptr_to_statics) = xzalloc(sizeof(S)); \
} while (0)
#define DEINIT_S() do { \
free(ptr_to_statics); \
} while (0)
static arith_t primary(enum token n);
@ -550,9 +574,13 @@ int test_main(int argc, char **argv)
argv[argc] = NULL;
}
/* We must do DEINIT_S() prior to returning */
INIT_S();
res = setjmp(leaving);
if (res)
return res;
if (res) {
goto ret;
}
/* resetting ngroups is probably unnecessary. it will
* force a new call to getgroups(), which prevents using
@ -565,24 +593,30 @@ int test_main(int argc, char **argv)
ngroups = 0;
/* Implement special cases from POSIX.2, section 4.62.4 */
if (argc == 1)
return 1;
if (argc == 2)
return *argv[1] == '\0';
//assert(argc);
if (argc == 1) {
res = 1;
goto ret;
}
if (argc == 2) {
res = (*argv[1] == '\0');
goto ret;
}
/* remember if we saw argc==4 which wants *no* '!' test */
_off = argc - 4;
if (_off ?
(LONE_CHAR(argv[1], '!'))
: (argv[1][0] != '!' || argv[1][1] != '\0'))
{
if (argc == 3)
return *argv[2] != '\0';
if (_off ? (LONE_CHAR(argv[1], '!'))
: (argv[1][0] != '!' || argv[1][1] != '\0')
) {
if (argc == 3) {
res = (*argv[2] != '\0');
goto ret;
}
t_lex(argv[2 + _off]);
if (t_wp_op && t_wp_op->op_type == BINOP) {
t_wp = &argv[1 + _off];
return binop() == _off;
res = (binop() == _off);
goto ret;
}
}
t_wp = &argv[1];
@ -590,7 +624,9 @@ int test_main(int argc, char **argv)
if (*t_wp != NULL && *++t_wp != NULL) {
bb_error_msg("%s: unknown operand", *t_wp);
return 2;
res = 2;
}
ret:
DEINIT_S();
return res;
}

View File

@ -73,7 +73,7 @@ s - suid type:
#endif
USE_TEST(APPLET_NOEXEC([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
USE_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
USE_TEST(APPLET_NOUSAGE([[, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_ADDGROUP(APPLET(addgroup, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER))

View File

@ -121,6 +121,8 @@ struct statics {
#endif
};
/* Make it reside in writable memory, yet make compiler understand
* that it is not going to change. */
static struct statics *const ptr_to_statics __attribute__ ((section (".data")));
#define S (*ptr_to_statics)