ash: undo "tokname hack"

dash has tokendlist[] array to decide which tokens end lists.
We store it as first byte of each tokname_array[i].

Switch to bit array, name it like dash (tokendlist), drop special
1st byte of tokname_array[i]. This brings us closer to dash, and
shrinks the binary, because many more string aliasing opportunities
are now open:

function                                             old     new   delta
pstrcmp1                                               -      16     +16
readtoken1                                          2852    2858      +6
list                                                 326     327      +1
pstrcmp                                               16      15      -1
tokname                                               45      42      -3
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/2 up/down: 23/-4)              Total: 19 bytes
   text	   data	    bss	    dec	    hex	filename
 943556	    916	  14292	 958764	  ea12c	busybox_old
 943463	    916	  14292	 958671	  ea0cf	busybox_unstripped
^^^^^^^ note this!

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2016-10-02 16:54:17 +02:00
parent bc1a00843f
commit 888527ccee

View File

@ -7881,49 +7881,86 @@ enum {
}; };
typedef smallint token_id_t; typedef smallint token_id_t;
/* first char is indicating which tokens mark the end of a list */ /* Nth bit indicates if token marks the end of a list */
enum {
tokendlist = 0
/* 0 */ | (1u << TEOF)
/* 1 */ | (0u << TNL)
/* 2 */ | (0u << TREDIR)
/* 3 */ | (0u << TWORD)
/* 4 */ | (0u << TSEMI)
/* 5 */ | (0u << TBACKGND)
/* 6 */ | (0u << TAND)
/* 7 */ | (0u << TOR)
/* 8 */ | (0u << TPIPE)
/* 9 */ | (0u << TLP)
/* 10 */ | (1u << TRP)
/* 11 */ | (1u << TENDCASE)
/* 12 */ | (1u << TENDBQUOTE)
/* 13 */ | (0u << TNOT)
/* 14 */ | (0u << TCASE)
/* 15 */ | (1u << TDO)
/* 16 */ | (1u << TDONE)
/* 17 */ | (1u << TELIF)
/* 18 */ | (1u << TELSE)
/* 19 */ | (1u << TESAC)
/* 20 */ | (1u << TFI)
/* 21 */ | (0u << TFOR)
#if ENABLE_ASH_BASH_COMPAT
/* 22 */ | (0u << TFUNCTION)
#endif
/* 23 */ | (0u << TIF)
/* 24 */ | (0u << TIN)
/* 25 */ | (1u << TTHEN)
/* 26 */ | (0u << TUNTIL)
/* 27 */ | (0u << TWHILE)
/* 28 */ | (0u << TBEGIN)
/* 29 */ | (1u << TEND)
, /* thus far 29 bits used */
};
static const char *const tokname_array[] = { static const char *const tokname_array[] = {
"\1end of file", "end of file",
"\0newline", "newline",
"\0redirection", "redirection",
"\0word", "word",
"\0;", ";",
"\0&", "&",
"\0&&", "&&",
"\0||", "||",
"\0|", "|",
"\0(", "(",
"\1)", ")",
"\1;;", ";;",
"\1`", "`",
#define KWDOFFSET 13 #define KWDOFFSET 13
/* the following are keywords */ /* the following are keywords */
"\0!", "!",
"\0case", "case",
"\1do", "do",
"\1done", "done",
"\1elif", "elif",
"\1else", "else",
"\1esac", "esac",
"\1fi", "fi",
"\0for", "for",
#if ENABLE_ASH_BASH_COMPAT #if ENABLE_ASH_BASH_COMPAT
"\0function", "function",
#endif #endif
"\0if", "if",
"\0in", "in",
"\1then", "then",
"\0until", "until",
"\0while", "while",
"\0{", "{",
"\1}", "}",
}; };
/* Wrapper around strcmp for qsort/bsearch/... */ /* Wrapper around strcmp for qsort/bsearch/... */
static int static int
pstrcmp(const void *a, const void *b) pstrcmp(const void *a, const void *b)
{ {
return strcmp((char*) a, (*(char**) b) + 1); return strcmp((char*)a, *(char**)b);
} }
static const char *const * static const char *const *
@ -9339,6 +9376,11 @@ static const struct builtincmd builtintab[] = {
/* /*
* Search the table of builtin commands. * Search the table of builtin commands.
*/ */
static int
pstrcmp1(const void *a, const void *b)
{
return strcmp((char*)a, *(char**)b + 1);
}
static struct builtincmd * static struct builtincmd *
find_builtin(const char *name) find_builtin(const char *name)
{ {
@ -9346,7 +9388,7 @@ find_builtin(const char *name)
bp = bsearch( bp = bsearch(
name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]), name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
pstrcmp pstrcmp1
); );
return bp; return bp;
} }
@ -10669,8 +10711,8 @@ static const char *
tokname(char *buf, int tok) tokname(char *buf, int tok)
{ {
if (tok < TSEMI) if (tok < TSEMI)
return tokname_array[tok] + 1; return tokname_array[tok];
sprintf(buf, "\"%s\"", tokname_array[tok] + 1); sprintf(buf, "\"%s\"", tokname_array[tok]);
return buf; return buf;
} }
@ -10727,7 +10769,7 @@ list(int nlflag)
} }
checkkwd = CHKNL | CHKKWD | CHKALIAS; checkkwd = CHKNL | CHKKWD | CHKALIAS;
if (nlflag == 2 && tokname_array[peektoken()][0]) if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
return n1; return n1;
nlflag |= 2; nlflag |= 2;
@ -11109,7 +11151,7 @@ parse_command(void)
n1->nbinary.ch1 = list(0); n1->nbinary.ch1 = list(0);
got = readtoken(); got = readtoken();
if (got != TDO) { if (got != TDO) {
TRACE(("expecting DO got '%s' %s\n", tokname_array[got] + 1, TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
got == TWORD ? wordtext : "")); got == TWORD ? wordtext : ""));
raise_error_unexpected_syntax(TDO); raise_error_unexpected_syntax(TDO);
} }
@ -12156,7 +12198,7 @@ readtoken(void)
pp = findkwd(wordtext); pp = findkwd(wordtext);
if (pp) { if (pp) {
lasttoken = t = pp - tokname_array; lasttoken = t = pp - tokname_array;
TRACE(("keyword '%s' recognized\n", tokname_array[t] + 1)); TRACE(("keyword '%s' recognized\n", tokname_array[t]));
goto out; goto out;
} }
} }
@ -12177,9 +12219,9 @@ readtoken(void)
checkkwd = 0; checkkwd = 0;
#if DEBUG #if DEBUG
if (!alreadyseen) if (!alreadyseen)
TRACE(("token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : "")); TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
else else
TRACE(("reread token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : "")); TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
#endif #endif
return t; return t;
} }