ash: undo "tokname hack"
authorDenys Vlasenko <vda.linux@googlemail.com>
Sun, 2 Oct 2016 14:54:17 +0000 (16:54 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 2 Oct 2016 14:54:17 +0000 (16:54 +0200)
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>
shell/ash.c

index 41ae5cbd2c585f4c1c0380de5d6f7b89b47d412e..421639e8b106f583e2c16be5757b49e0d78215fc 100644 (file)
@@ -7881,49 +7881,86 @@ enum {
 };
 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[] = {
-       "\1end of file",
-       "\0newline",
-       "\0redirection",
-       "\0word",
-       "\0;",
-       "\0&",
-       "\0&&",
-       "\0||",
-       "\0|",
-       "\0(",
-       "\1)",
-       "\1;;",
-       "\1`",
+       "end of file",
+       "newline",
+       "redirection",
+       "word",
+       ";",
+       "&",
+       "&&",
+       "||",
+       "|",
+       "(",
+       ")",
+       ";;",
+       "`",
 #define KWDOFFSET 13
        /* the following are keywords */
-       "\0!",
-       "\0case",
-       "\1do",
-       "\1done",
-       "\1elif",
-       "\1else",
-       "\1esac",
-       "\1fi",
-       "\0for",
+       "!",
+       "case",
+       "do",
+       "done",
+       "elif",
+       "else",
+       "esac",
+       "fi",
+       "for",
 #if ENABLE_ASH_BASH_COMPAT
-       "\0function",
-#endif
-       "\0if",
-       "\0in",
-       "\1then",
-       "\0until",
-       "\0while",
-       "\0{",
-       "\1}",
+       "function",
+#endif
+       "if",
+       "in",
+       "then",
+       "until",
+       "while",
+       "{",
+       "}",
 };
 
 /* Wrapper around strcmp for qsort/bsearch/... */
 static int
 pstrcmp(const void *a, const void *b)
 {
-       return strcmp((char*) a, (*(char**) b) + 1);
+       return strcmp((char*)a, *(char**)b);
 }
 
 static const char *const *
@@ -9339,6 +9376,11 @@ static const struct builtincmd builtintab[] = {
 /*
  * 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 *
 find_builtin(const char *name)
 {
@@ -9346,7 +9388,7 @@ find_builtin(const char *name)
 
        bp = bsearch(
                name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
-               pstrcmp
+               pstrcmp1
        );
        return bp;
 }
@@ -10669,8 +10711,8 @@ static const char *
 tokname(char *buf, int tok)
 {
        if (tok < TSEMI)
-               return tokname_array[tok] + 1;
-       sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
+               return tokname_array[tok];
+       sprintf(buf, "\"%s\"", tokname_array[tok]);
        return buf;
 }
 
@@ -10727,7 +10769,7 @@ list(int nlflag)
                }
 
                checkkwd = CHKNL | CHKKWD | CHKALIAS;
-               if (nlflag == 2 && tokname_array[peektoken()][0])
+               if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
                        return n1;
                nlflag |= 2;
 
@@ -11109,7 +11151,7 @@ parse_command(void)
                n1->nbinary.ch1 = list(0);
                got = readtoken();
                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 : ""));
                        raise_error_unexpected_syntax(TDO);
                }
@@ -12156,7 +12198,7 @@ readtoken(void)
                pp = findkwd(wordtext);
                if (pp) {
                        lasttoken = t = pp - tokname_array;
-                       TRACE(("keyword '%s' recognized\n", tokname_array[t] + 1));
+                       TRACE(("keyword '%s' recognized\n", tokname_array[t]));
                        goto out;
                }
        }
@@ -12177,9 +12219,9 @@ readtoken(void)
        checkkwd = 0;
 #if DEBUG
        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
-               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
        return t;
 }