diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-10-02 16:54:17 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-10-02 16:54:17 +0200 |
commit | 888527cceec2f58f1eae3acceddee928b5cb647a (patch) | |
tree | f4ef6c2a33a1391bfe4e9f408b15e0f36e8e21b4 | |
parent | bc1a00843fce8ce0ed101c4e6eb02ee79e673a00 (diff) | |
download | busybox-w32-888527cceec2f58f1eae3acceddee928b5cb647a.tar.gz busybox-w32-888527cceec2f58f1eae3acceddee928b5cb647a.tar.bz2 busybox-w32-888527cceec2f58f1eae3acceddee928b5cb647a.zip |
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>
-rw-r--r-- | shell/ash.c | 124 |
1 files changed, 83 insertions, 41 deletions
diff --git a/shell/ash.c b/shell/ash.c index 41ae5cbd2..421639e8b 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7881,49 +7881,86 @@ enum { | |||
7881 | }; | 7881 | }; |
7882 | typedef smallint token_id_t; | 7882 | typedef smallint token_id_t; |
7883 | 7883 | ||
7884 | /* first char is indicating which tokens mark the end of a list */ | 7884 | /* Nth bit indicates if token marks the end of a list */ |
7885 | enum { | ||
7886 | tokendlist = 0 | ||
7887 | /* 0 */ | (1u << TEOF) | ||
7888 | /* 1 */ | (0u << TNL) | ||
7889 | /* 2 */ | (0u << TREDIR) | ||
7890 | /* 3 */ | (0u << TWORD) | ||
7891 | /* 4 */ | (0u << TSEMI) | ||
7892 | /* 5 */ | (0u << TBACKGND) | ||
7893 | /* 6 */ | (0u << TAND) | ||
7894 | /* 7 */ | (0u << TOR) | ||
7895 | /* 8 */ | (0u << TPIPE) | ||
7896 | /* 9 */ | (0u << TLP) | ||
7897 | /* 10 */ | (1u << TRP) | ||
7898 | /* 11 */ | (1u << TENDCASE) | ||
7899 | /* 12 */ | (1u << TENDBQUOTE) | ||
7900 | /* 13 */ | (0u << TNOT) | ||
7901 | /* 14 */ | (0u << TCASE) | ||
7902 | /* 15 */ | (1u << TDO) | ||
7903 | /* 16 */ | (1u << TDONE) | ||
7904 | /* 17 */ | (1u << TELIF) | ||
7905 | /* 18 */ | (1u << TELSE) | ||
7906 | /* 19 */ | (1u << TESAC) | ||
7907 | /* 20 */ | (1u << TFI) | ||
7908 | /* 21 */ | (0u << TFOR) | ||
7909 | #if ENABLE_ASH_BASH_COMPAT | ||
7910 | /* 22 */ | (0u << TFUNCTION) | ||
7911 | #endif | ||
7912 | /* 23 */ | (0u << TIF) | ||
7913 | /* 24 */ | (0u << TIN) | ||
7914 | /* 25 */ | (1u << TTHEN) | ||
7915 | /* 26 */ | (0u << TUNTIL) | ||
7916 | /* 27 */ | (0u << TWHILE) | ||
7917 | /* 28 */ | (0u << TBEGIN) | ||
7918 | /* 29 */ | (1u << TEND) | ||
7919 | , /* thus far 29 bits used */ | ||
7920 | }; | ||
7921 | |||
7885 | static const char *const tokname_array[] = { | 7922 | static const char *const tokname_array[] = { |
7886 | "\1end of file", | 7923 | "end of file", |
7887 | "\0newline", | 7924 | "newline", |
7888 | "\0redirection", | 7925 | "redirection", |
7889 | "\0word", | 7926 | "word", |
7890 | "\0;", | 7927 | ";", |
7891 | "\0&", | 7928 | "&", |
7892 | "\0&&", | 7929 | "&&", |
7893 | "\0||", | 7930 | "||", |
7894 | "\0|", | 7931 | "|", |
7895 | "\0(", | 7932 | "(", |
7896 | "\1)", | 7933 | ")", |
7897 | "\1;;", | 7934 | ";;", |
7898 | "\1`", | 7935 | "`", |
7899 | #define KWDOFFSET 13 | 7936 | #define KWDOFFSET 13 |
7900 | /* the following are keywords */ | 7937 | /* the following are keywords */ |
7901 | "\0!", | 7938 | "!", |
7902 | "\0case", | 7939 | "case", |
7903 | "\1do", | 7940 | "do", |
7904 | "\1done", | 7941 | "done", |
7905 | "\1elif", | 7942 | "elif", |
7906 | "\1else", | 7943 | "else", |
7907 | "\1esac", | 7944 | "esac", |
7908 | "\1fi", | 7945 | "fi", |
7909 | "\0for", | 7946 | "for", |
7910 | #if ENABLE_ASH_BASH_COMPAT | 7947 | #if ENABLE_ASH_BASH_COMPAT |
7911 | "\0function", | 7948 | "function", |
7912 | #endif | 7949 | #endif |
7913 | "\0if", | 7950 | "if", |
7914 | "\0in", | 7951 | "in", |
7915 | "\1then", | 7952 | "then", |
7916 | "\0until", | 7953 | "until", |
7917 | "\0while", | 7954 | "while", |
7918 | "\0{", | 7955 | "{", |
7919 | "\1}", | 7956 | "}", |
7920 | }; | 7957 | }; |
7921 | 7958 | ||
7922 | /* Wrapper around strcmp for qsort/bsearch/... */ | 7959 | /* Wrapper around strcmp for qsort/bsearch/... */ |
7923 | static int | 7960 | static int |
7924 | pstrcmp(const void *a, const void *b) | 7961 | pstrcmp(const void *a, const void *b) |
7925 | { | 7962 | { |
7926 | return strcmp((char*) a, (*(char**) b) + 1); | 7963 | return strcmp((char*)a, *(char**)b); |
7927 | } | 7964 | } |
7928 | 7965 | ||
7929 | static const char *const * | 7966 | static const char *const * |
@@ -9339,6 +9376,11 @@ static const struct builtincmd builtintab[] = { | |||
9339 | /* | 9376 | /* |
9340 | * Search the table of builtin commands. | 9377 | * Search the table of builtin commands. |
9341 | */ | 9378 | */ |
9379 | static int | ||
9380 | pstrcmp1(const void *a, const void *b) | ||
9381 | { | ||
9382 | return strcmp((char*)a, *(char**)b + 1); | ||
9383 | } | ||
9342 | static struct builtincmd * | 9384 | static struct builtincmd * |
9343 | find_builtin(const char *name) | 9385 | find_builtin(const char *name) |
9344 | { | 9386 | { |
@@ -9346,7 +9388,7 @@ find_builtin(const char *name) | |||
9346 | 9388 | ||
9347 | bp = bsearch( | 9389 | bp = bsearch( |
9348 | name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]), | 9390 | name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]), |
9349 | pstrcmp | 9391 | pstrcmp1 |
9350 | ); | 9392 | ); |
9351 | return bp; | 9393 | return bp; |
9352 | } | 9394 | } |
@@ -10669,8 +10711,8 @@ static const char * | |||
10669 | tokname(char *buf, int tok) | 10711 | tokname(char *buf, int tok) |
10670 | { | 10712 | { |
10671 | if (tok < TSEMI) | 10713 | if (tok < TSEMI) |
10672 | return tokname_array[tok] + 1; | 10714 | return tokname_array[tok]; |
10673 | sprintf(buf, "\"%s\"", tokname_array[tok] + 1); | 10715 | sprintf(buf, "\"%s\"", tokname_array[tok]); |
10674 | return buf; | 10716 | return buf; |
10675 | } | 10717 | } |
10676 | 10718 | ||
@@ -10727,7 +10769,7 @@ list(int nlflag) | |||
10727 | } | 10769 | } |
10728 | 10770 | ||
10729 | checkkwd = CHKNL | CHKKWD | CHKALIAS; | 10771 | checkkwd = CHKNL | CHKKWD | CHKALIAS; |
10730 | if (nlflag == 2 && tokname_array[peektoken()][0]) | 10772 | if (nlflag == 2 && ((1 << peektoken()) & tokendlist)) |
10731 | return n1; | 10773 | return n1; |
10732 | nlflag |= 2; | 10774 | nlflag |= 2; |
10733 | 10775 | ||
@@ -11109,7 +11151,7 @@ parse_command(void) | |||
11109 | n1->nbinary.ch1 = list(0); | 11151 | n1->nbinary.ch1 = list(0); |
11110 | got = readtoken(); | 11152 | got = readtoken(); |
11111 | if (got != TDO) { | 11153 | if (got != TDO) { |
11112 | TRACE(("expecting DO got '%s' %s\n", tokname_array[got] + 1, | 11154 | TRACE(("expecting DO got '%s' %s\n", tokname_array[got], |
11113 | got == TWORD ? wordtext : "")); | 11155 | got == TWORD ? wordtext : "")); |
11114 | raise_error_unexpected_syntax(TDO); | 11156 | raise_error_unexpected_syntax(TDO); |
11115 | } | 11157 | } |
@@ -12156,7 +12198,7 @@ readtoken(void) | |||
12156 | pp = findkwd(wordtext); | 12198 | pp = findkwd(wordtext); |
12157 | if (pp) { | 12199 | if (pp) { |
12158 | lasttoken = t = pp - tokname_array; | 12200 | lasttoken = t = pp - tokname_array; |
12159 | TRACE(("keyword '%s' recognized\n", tokname_array[t] + 1)); | 12201 | TRACE(("keyword '%s' recognized\n", tokname_array[t])); |
12160 | goto out; | 12202 | goto out; |
12161 | } | 12203 | } |
12162 | } | 12204 | } |
@@ -12177,9 +12219,9 @@ readtoken(void) | |||
12177 | checkkwd = 0; | 12219 | checkkwd = 0; |
12178 | #if DEBUG | 12220 | #if DEBUG |
12179 | if (!alreadyseen) | 12221 | if (!alreadyseen) |
12180 | TRACE(("token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : "")); | 12222 | TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : "")); |
12181 | else | 12223 | else |
12182 | TRACE(("reread token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : "")); | 12224 | TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : "")); |
12183 | #endif | 12225 | #endif |
12184 | return t; | 12226 | return t; |
12185 | } | 12227 | } |