ash: shrink on top of previous change
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 28 Nov 2008 03:42:31 +0000 (03:42 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 28 Nov 2008 03:42:31 +0000 (03:42 -0000)
function                                             old     new   delta
readtoken1                                          3201    3221     +20
xxreadtoken                                          306     313      +7
pungetc                                               13      12      -1
ash_main                                            1380    1379      -1
setinputfile                                         196     192      -4
plinno                                                 4       -      -4
parsenleft                                             4       -      -4
parsenextc                                             4       -      -4
parselleft                                             4       -      -4
setinputstring                                        67      62      -5
pushstring                                           123     114      -9
pgetc                                                455     438     -17
pushfile                                              69      31     -38
popfile                                              114      76     -38
------------------------------------------------------------------------------
(add/remove: 0/4 grow/shrink: 2/8 up/down: 27/-129)          Total: -102 bytes
   text    data     bss     dec     hex filename
 798750     564    7756  807070   c509e busybox_old
 798664     560    7748  806972   c503c busybox_unstripped

shell/ash.c

index e1df89418872efdaab4cb2c5916c0b5cc754fb1e..05e2f630d310ab8cf13be1a8a1b02edd444f40d9 100644 (file)
@@ -1033,8 +1033,8 @@ struct alias;
 
 struct strpush {
        struct strpush *prev;   /* preceding string on stack */
-       char *prevstring;
-       int prevnleft;
+       char *prev_string;
+       int prev_left_in_line;
 #if ENABLE_ASH_ALIAS
        struct alias *ap;       /* if push was associated with an alias */
 #endif
@@ -1045,9 +1045,9 @@ struct parsefile {
        struct parsefile *prev; /* preceding file on stack */
        int linno;              /* current line */
        int fd;                 /* file descriptor (or -1 if string) */
-       int nleft;              /* number of chars left in this line */
-       int lleft;              /* number of chars left in this buffer */
-       char *nextc;            /* next char in buffer */
+       int left_in_line;       /* number of chars left in this line */
+       int left_in_buffer;     /* number of chars left in this buffer past the line */
+       char *next_to_pgetc;    /* next char in buffer */
        char *buf;              /* input buffer */
        struct strpush *strpush; /* for pushing strings at this level */
        struct strpush basestrpush; /* so pushing one is fast */
@@ -9084,19 +9084,48 @@ enum {
        INPUT_NOFILE_OK = 2,
 };
 
-static int plinno = 1;                  /* input line number */
-/* number of characters left in input buffer */
-static int parsenleft;                  /* copy of parsefile->nleft */
-static int parselleft;                  /* copy of parsefile->lleft */
-/* next character in input buffer */
-static char *parsenextc;                /* copy of parsefile->nextc */
-
 static smallint checkkwd;
 /* values of checkkwd variable */
 #define CHKALIAS        0x1
 #define CHKKWD          0x2
 #define CHKNL           0x4
 
+/*
+ * Push a string back onto the input at this current parsefile level.
+ * We handle aliases this way.
+ */
+#if !ENABLE_ASH_ALIAS
+#define pushstring(s, ap) pushstring(s)
+#endif
+static void
+pushstring(char *s, struct alias *ap)
+{
+       struct strpush *sp;
+       int len;
+
+       len = strlen(s);
+       INT_OFF;
+       if (g_parsefile->strpush) {
+               sp = ckzalloc(sizeof(*sp));
+               sp->prev = g_parsefile->strpush;
+       } else {
+               sp = &(g_parsefile->basestrpush);
+       }
+       g_parsefile->strpush = sp;
+       sp->prev_string = g_parsefile->next_to_pgetc;
+       sp->prev_left_in_line = g_parsefile->left_in_line;
+#if ENABLE_ASH_ALIAS
+       sp->ap = ap;
+       if (ap) {
+               ap->flag |= ALIASINUSE;
+               sp->string = s;
+       }
+#endif
+       g_parsefile->next_to_pgetc = s;
+       g_parsefile->left_in_line = len;
+       INT_ON;
+}
+
 static void
 popstring(void)
 {
@@ -9105,7 +9134,9 @@ popstring(void)
        INT_OFF;
 #if ENABLE_ASH_ALIAS
        if (sp->ap) {
-               if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
+               if (g_parsefile->next_to_pgetc[-1] == ' '
+                || g_parsefile->next_to_pgetc[-1] == '\t'
+               ) {
                        checkkwd |= CHKALIAS;
                }
                if (sp->string != sp->ap->val) {
@@ -9117,8 +9148,8 @@ popstring(void)
                }
        }
 #endif
-       parsenextc = sp->prevstring;
-       parsenleft = sp->prevnleft;
+       g_parsefile->next_to_pgetc = sp->prev_string;
+       g_parsefile->left_in_line = sp->prev_left_in_line;
        g_parsefile->strpush = sp->prev;
        if (sp != &(g_parsefile->basestrpush))
                free(sp);
@@ -9130,8 +9161,8 @@ preadfd(void)
 {
        int nr;
        char *buf = g_parsefile->buf;
-       parsenextc = buf;
 
+       g_parsefile->next_to_pgetc = buf;
 #if ENABLE_FEATURE_EDITING
  retry:
        if (!iflag || g_parsefile->fd != STDIN_FILENO)
@@ -9182,8 +9213,9 @@ preadfd(void)
  * Refill the input buffer and return the next input character:
  *
  * 1) If a string was pushed back on the input, pop it;
- * 2) If an EOF was pushed back (parsenleft < -BIGNUM) or we are reading
- *    from a string so we can't refill the buffer, return EOF.
+ * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
+ *    or we are reading from a string so we can't refill the buffer,
+ *    return EOF.
  * 3) If the is more stuff in this buffer, use it else call read to fill it.
  * 4) Process input up to the next newline, deleting nul characters.
  */
@@ -9197,8 +9229,10 @@ preadbuffer(void)
 
        while (g_parsefile->strpush) {
 #if ENABLE_ASH_ALIAS
-               if (parsenleft == -1 && g_parsefile->strpush->ap
-                && parsenextc[-1] != ' ' && parsenextc[-1] != '\t'
+               if (g_parsefile->left_in_line == -1
+                && g_parsefile->strpush->ap
+                && g_parsefile->next_to_pgetc[-1] != ' '
+                && g_parsefile->next_to_pgetc[-1] != '\t'
                ) {
                        pgetc_debug("preadbuffer PEOA");
                        return PEOA;
@@ -9206,43 +9240,51 @@ preadbuffer(void)
 #endif
                popstring();
                /* try "pgetc" now: */
-               pgetc_debug("internal pgetc at %d:%p'%s'", parsenleft, parsenextc, parsenextc);
-               if (--parsenleft >= 0)
-                       return signed_char2int(*parsenextc++);
-       }
-       /* on both branches above parsenleft < 0.
+               pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
+                               g_parsefile->left_in_line,
+                               g_parsefile->next_to_pgetc,
+                               g_parsefile->next_to_pgetc);
+               if (--g_parsefile->left_in_line >= 0)
+                       return (unsigned char)(*g_parsefile->next_to_pgetc++);
+       }
+       /* on both branches above g_parsefile->left_in_line < 0.
         * "pgetc" needs refilling.
         */
 
        /* -90 is -BIGNUM. Below we use -99 to mark "EOF on read",
-        * pungetc() may decrement it a few times. -90 is enough.
+        * pungetc() may increment it a few times.
+        * Assuming it won't increment it to 0.
         */
-       if (parsenleft < -90 || g_parsefile->buf == NULL) {
+       if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
                pgetc_debug("preadbuffer PEOF1");
-               /* even in failure keep them in lock step,
-                * for correct pungetc. */
-               parsenextc++;
+               /* even in failure keep left_in_line and next_to_pgetc
+                * in lock step, for correct multi-layer pungetc.
+                * left_in_line was decremented before preadbuffer(),
+                * must inc next_to_pgetc: */
+               g_parsefile->next_to_pgetc++;
                return PEOF;
        }
 
-       more = parselleft;
+       more = g_parsefile->left_in_buffer;
        if (more <= 0) {
                flush_stdout_stderr();
  again:
                more = preadfd();
                if (more <= 0) {
-                       parselleft = parsenleft = -99;
+                       /* don't try reading again */
+                       g_parsefile->left_in_line = -99;
                        pgetc_debug("preadbuffer PEOF2");
-                       parsenextc++;
+                       g_parsefile->next_to_pgetc++;
                        return PEOF;
                }
        }
 
        /* Find out where's the end of line.
-        * Set parsenleft/parselleft acordingly.
+        * Set g_parsefile->left_in_line
+        * and g_parsefile->left_in_buffer acordingly.
         * NUL chars are deleted.
         */
-       q = parsenextc;
+       q = g_parsefile->next_to_pgetc;
        for (;;) {
                char c;
 
@@ -9254,37 +9296,47 @@ preadbuffer(void)
                } else {
                        q++;
                        if (c == '\n') {
-                               parsenleft = q - parsenextc - 1;
+                               g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
                                break;
                        }
                }
 
                if (more <= 0) {
-                       parsenleft = q - parsenextc - 1;
-                       if (parsenleft < 0)
+                       g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
+                       if (g_parsefile->left_in_line < 0)
                                goto again;
                        break;
                }
        }
-       parselleft = more;
+       g_parsefile->left_in_buffer = more;
 
        if (vflag) {
                char save = *q;
                *q = '\0';
-               out2str(parsenextc);
+               out2str(g_parsefile->next_to_pgetc);
                *q = save;
        }
 
-       pgetc_debug("preadbuffer at %d:%p'%s'", parsenleft, parsenextc, parsenextc);
-       return signed_char2int(*parsenextc++);
+       pgetc_debug("preadbuffer at %d:%p'%s'",
+                       g_parsefile->left_in_line,
+                       g_parsefile->next_to_pgetc,
+                       g_parsefile->next_to_pgetc);
+       return (unsigned char)(*g_parsefile->next_to_pgetc++);
 }
 
-#define pgetc_as_macro() (--parsenleft >= 0 ? signed_char2int(*parsenextc++) : preadbuffer())
+#define pgetc_as_macro() \
+       (--g_parsefile->left_in_line >= 0 \
+       ? (unsigned char)(*g_parsefile->next_to_pgetc++) \
+       : preadbuffer() \
+       )
 
 static int
 pgetc(void)
 {
-       pgetc_debug("pgetc at %d:%p'%s'", parsenleft, parsenextc, parsenextc);
+       pgetc_debug("pgetc_fast at %d:%p'%s'",
+                       g_parsefile->left_in_line,
+                       g_parsefile->next_to_pgetc,
+                       g_parsefile->next_to_pgetc);
        return pgetc_as_macro();
 }
 
@@ -9303,6 +9355,10 @@ pgetc2(void)
 {
        int c;
        do {
+               pgetc_debug("pgetc_fast at %d:%p'%s'",
+                               g_parsefile->left_in_line,
+                               g_parsefile->next_to_pgetc,
+                               g_parsefile->next_to_pgetc);
                c = pgetc_fast();
        } while (c == PEOA);
        return c;
@@ -9343,45 +9399,12 @@ pfgets(char *line, int len)
 static void
 pungetc(void)
 {
-       parsenleft++;
-       parsenextc--;
-       pgetc_debug("pushed back to %d:%p'%s'", parsenleft, parsenextc, parsenextc);
-}
-
-/*
- * Push a string back onto the input at this current parsefile level.
- * We handle aliases this way.
- */
-#if !ENABLE_ASH_ALIAS
-#define pushstring(s, ap) pushstring(s)
-#endif
-static void
-pushstring(char *s, struct alias *ap)
-{
-       struct strpush *sp;
-       int len;
-
-       len = strlen(s);
-       INT_OFF;
-       if (g_parsefile->strpush) {
-               sp = ckzalloc(sizeof(*sp));
-               sp->prev = g_parsefile->strpush;
-       } else {
-               sp = &(g_parsefile->basestrpush);
-       }
-       g_parsefile->strpush = sp;
-       sp->prevstring = parsenextc;
-       sp->prevnleft = parsenleft;
-#if ENABLE_ASH_ALIAS
-       sp->ap = ap;
-       if (ap) {
-               ap->flag |= ALIASINUSE;
-               sp->string = s;
-       }
-#endif
-       parsenextc = s;
-       parsenleft = len;
-       INT_ON;
+       g_parsefile->left_in_line++;
+       g_parsefile->next_to_pgetc--;
+       pgetc_debug("pushed back to %d:%p'%s'",
+                       g_parsefile->left_in_line,
+                       g_parsefile->next_to_pgetc,
+                       g_parsefile->next_to_pgetc);
 }
 
 /*
@@ -9393,10 +9416,6 @@ pushfile(void)
 {
        struct parsefile *pf;
 
-       g_parsefile->nleft = parsenleft;
-       g_parsefile->lleft = parselleft;
-       g_parsefile->nextc = parsenextc;
-       g_parsefile->linno = plinno;
        pf = ckzalloc(sizeof(*pf));
        pf->prev = g_parsefile;
        pf->fd = -1;
@@ -9418,10 +9437,6 @@ popfile(void)
                popstring();
        g_parsefile = pf->prev;
        free(pf);
-       parsenleft = g_parsefile->nleft;
-       parselleft = g_parsefile->lleft;
-       parsenextc = g_parsefile->nextc;
-       plinno = g_parsefile->linno;
        INT_ON;
 }
 
@@ -9464,8 +9479,9 @@ setinputfd(int fd, int push)
        g_parsefile->fd = fd;
        if (g_parsefile->buf == NULL)
                g_parsefile->buf = ckmalloc(IBUFSIZ);
-       parselleft = parsenleft = 0;
-       plinno = 1;
+       g_parsefile->left_in_buffer = 0;
+       g_parsefile->left_in_line = 0;
+       g_parsefile->linno = 1;
 }
 
 /*
@@ -9506,10 +9522,10 @@ setinputstring(char *string)
 {
        INT_OFF;
        pushfile();
-       parsenextc = string;
-       parsenleft = strlen(string);
+       g_parsefile->next_to_pgetc = string;
+       g_parsefile->left_in_line = strlen(string);
        g_parsefile->buf = NULL;
-       plinno = 1;
+       g_parsefile->linno = 1;
        INT_ON;
 }
 
@@ -10653,7 +10669,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
        (void) &prevsyntax;
        (void) &syntax;
 #endif
-       startlinno = plinno;
+       startlinno = g_parsefile->linno;
        bqlist = NULL;
        quotef = 0;
        oldstyle = 0;
@@ -10681,7 +10697,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
                                if (syntax == BASESYNTAX)
                                        goto endword;   /* exit outer loop */
                                USTPUTC(c, out);
-                               plinno++;
+                               g_parsefile->linno++;
                                if (doprompt)
                                        setprompt(2);
                                c = pgetc();
@@ -10835,7 +10851,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
        if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
                raise_error_syntax("unterminated quoted string");
        if (varnest != 0) {
-               startlinno = plinno;
+               startlinno = g_parsefile->linno;
                /* { */
                raise_error_syntax("missing '}'");
        }
@@ -10890,7 +10906,7 @@ checkend: {
                                        continue;
                                if (*p == '\n' && *q == '\0') {
                                        c = PEOF;
-                                       plinno++;
+                                       g_parsefile->linno++;
                                        needprompt = doprompt;
                                } else {
                                        pushstring(line, NULL);
@@ -11166,7 +11182,7 @@ parsebackq: {
                        case '\\':
                                pc = pgetc();
                                if (pc == '\n') {
-                                       plinno++;
+                                       g_parsefile->linno++;
                                        if (doprompt)
                                                setprompt(2);
                                        /*
@@ -11189,11 +11205,11 @@ parsebackq: {
 #if ENABLE_ASH_ALIAS
                        case PEOA:
 #endif
-                               startlinno = plinno;
+                               startlinno = g_parsefile->linno;
                                raise_error_syntax("EOF in backquote substitution");
 
                        case '\n':
-                               plinno++;
+                               g_parsefile->linno++;
                                needprompt = doprompt;
                                break;
 
@@ -11334,7 +11350,7 @@ xxreadtoken(void)
        if (needprompt) {
                setprompt(2);
        }
-       startlinno = plinno;
+       startlinno = g_parsefile->linno;
        for (;;) {                      /* until token or start of word found */
                c = pgetc_fast();
                if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
@@ -11349,7 +11365,7 @@ xxreadtoken(void)
                                pungetc();
                                break; /* return readtoken1(...) */
                        }
-                       startlinno = ++plinno;
+                       startlinno = ++g_parsefile->linno;
                        if (doprompt)
                                setprompt(2);
                } else {
@@ -11358,7 +11374,7 @@ xxreadtoken(void)
                        p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
                        if (c != PEOF) {
                                if (c == '\n') {
-                                       plinno++;
+                                       g_parsefile->linno++;
                                        needprompt = doprompt;
                                }
 
@@ -11400,7 +11416,7 @@ xxreadtoken(void)
        if (needprompt) {
                setprompt(2);
        }
-       startlinno = plinno;
+       startlinno = g_parsefile->linno;
        for (;;) {      /* until token or start of word found */
                c = pgetc_fast();
                switch (c) {
@@ -11416,7 +11432,7 @@ xxreadtoken(void)
                        continue;
                case '\\':
                        if (pgetc() == '\n') {
-                               startlinno = ++plinno;
+                               startlinno = ++g_parsefile->linno;
                                if (doprompt)
                                        setprompt(2);
                                continue;
@@ -11424,7 +11440,7 @@ xxreadtoken(void)
                        pungetc();
                        goto breakloop;
                case '\n':
-                       plinno++;
+                       g_parsefile->linno++;
                        needprompt = doprompt;
                        RETURN(TNL);
                case PEOF:
@@ -13454,7 +13470,7 @@ static void
 init(void)
 {
        /* from input.c: */
-       basepf.nextc = basepf.buf = basebuf;
+       basepf.next_to_pgetc = basepf.buf = basebuf;
 
        /* from trap.c: */
        signal(SIGCHLD, SIG_DFL);
@@ -13575,7 +13591,8 @@ reset(void)
        evalskip = 0;
        loopnest = 0;
        /* from input.c: */
-       parselleft = parsenleft = 0;      /* clear input buffer */
+       g_parsefile->left_in_buffer = 0;
+       g_parsefile->left_in_line = 0;      /* clear input buffer */
        popallfiles();
        /* from parser.c: */
        tokpushback = 0;