diff options
-rw-r--r-- | shell/ash.c | 239 |
1 files changed, 128 insertions, 111 deletions
diff --git a/shell/ash.c b/shell/ash.c index e1df89418..05e2f630d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -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; |