aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c77
1 files changed, 43 insertions, 34 deletions
diff --git a/shell/ash.c b/shell/ash.c
index a31cee259..a63d40d7e 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1168,6 +1168,12 @@ struct strpush {
1168 struct alias *ap; /* if push was associated with an alias */ 1168 struct alias *ap; /* if push was associated with an alias */
1169#endif 1169#endif
1170 char *string; /* remember the string since it may change */ 1170 char *string; /* remember the string since it may change */
1171
1172 /* Remember last two characters for pungetc. */
1173 int lastc[2];
1174
1175 /* Number of outstanding calls to pungetc. */
1176 int unget;
1171}; 1177};
1172 1178
1173struct parsefile { 1179struct parsefile {
@@ -1180,6 +1186,12 @@ struct parsefile {
1180 char *buf; /* input buffer */ 1186 char *buf; /* input buffer */
1181 struct strpush *strpush; /* for pushing strings at this level */ 1187 struct strpush *strpush; /* for pushing strings at this level */
1182 struct strpush basestrpush; /* so pushing one is fast */ 1188 struct strpush basestrpush; /* so pushing one is fast */
1189
1190 /* Remember last two characters for pungetc. */
1191 int lastc[2];
1192
1193 /* Number of outstanding calls to pungetc. */
1194 int unget;
1183}; 1195};
1184 1196
1185static struct parsefile basepf; /* top level input file */ 1197static struct parsefile basepf; /* top level input file */
@@ -9715,6 +9727,8 @@ pushstring(char *s, struct alias *ap)
9715 g_parsefile->strpush = sp; 9727 g_parsefile->strpush = sp;
9716 sp->prev_string = g_parsefile->next_to_pgetc; 9728 sp->prev_string = g_parsefile->next_to_pgetc;
9717 sp->prev_left_in_line = g_parsefile->left_in_line; 9729 sp->prev_left_in_line = g_parsefile->left_in_line;
9730 sp->unget = g_parsefile->unget;
9731 memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9718#if ENABLE_ASH_ALIAS 9732#if ENABLE_ASH_ALIAS
9719 sp->ap = ap; 9733 sp->ap = ap;
9720 if (ap) { 9734 if (ap) {
@@ -9724,6 +9738,7 @@ pushstring(char *s, struct alias *ap)
9724#endif 9738#endif
9725 g_parsefile->next_to_pgetc = s; 9739 g_parsefile->next_to_pgetc = s;
9726 g_parsefile->left_in_line = len; 9740 g_parsefile->left_in_line = len;
9741 g_parsefile->unget = 0;
9727 INT_ON; 9742 INT_ON;
9728} 9743}
9729 9744
@@ -9751,6 +9766,8 @@ popstring(void)
9751#endif 9766#endif
9752 g_parsefile->next_to_pgetc = sp->prev_string; 9767 g_parsefile->next_to_pgetc = sp->prev_string;
9753 g_parsefile->left_in_line = sp->prev_left_in_line; 9768 g_parsefile->left_in_line = sp->prev_left_in_line;
9769 g_parsefile->unget = sp->unget;
9770 memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
9754 g_parsefile->strpush = sp->prev; 9771 g_parsefile->strpush = sp->prev;
9755 if (sp != &(g_parsefile->basestrpush)) 9772 if (sp != &(g_parsefile->basestrpush))
9756 free(sp); 9773 free(sp);
@@ -9846,13 +9863,14 @@ preadfd(void)
9846 */ 9863 */
9847//#define pgetc_debug(...) bb_error_msg(__VA_ARGS__) 9864//#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9848#define pgetc_debug(...) ((void)0) 9865#define pgetc_debug(...) ((void)0)
9866static int pgetc(void);
9849static int 9867static int
9850preadbuffer(void) 9868preadbuffer(void)
9851{ 9869{
9852 char *q; 9870 char *q;
9853 int more; 9871 int more;
9854 9872
9855 while (g_parsefile->strpush) { 9873 if (g_parsefile->strpush) {
9856#if ENABLE_ASH_ALIAS 9874#if ENABLE_ASH_ALIAS
9857 if (g_parsefile->left_in_line == -1 9875 if (g_parsefile->left_in_line == -1
9858 && g_parsefile->strpush->ap 9876 && g_parsefile->strpush->ap
@@ -9864,13 +9882,7 @@ preadbuffer(void)
9864 } 9882 }
9865#endif 9883#endif
9866 popstring(); 9884 popstring();
9867 /* try "pgetc" now: */ 9885 return pgetc();
9868 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9869 g_parsefile->left_in_line,
9870 g_parsefile->next_to_pgetc,
9871 g_parsefile->next_to_pgetc);
9872 if (--g_parsefile->left_in_line >= 0)
9873 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9874 } 9886 }
9875 /* on both branches above g_parsefile->left_in_line < 0. 9887 /* on both branches above g_parsefile->left_in_line < 0.
9876 * "pgetc" needs refilling. 9888 * "pgetc" needs refilling.
@@ -9949,27 +9961,28 @@ preadbuffer(void)
9949 return (unsigned char)*g_parsefile->next_to_pgetc++; 9961 return (unsigned char)*g_parsefile->next_to_pgetc++;
9950} 9962}
9951 9963
9952#define pgetc_as_macro() \
9953 (--g_parsefile->left_in_line >= 0 \
9954 ? (unsigned char)*g_parsefile->next_to_pgetc++ \
9955 : preadbuffer() \
9956 )
9957
9958static int 9964static int
9959pgetc(void) 9965pgetc(void)
9960{ 9966{
9961 pgetc_debug("pgetc_fast at %d:%p'%s'", 9967 int c;
9968
9969 pgetc_debug("pgetc at %d:%p'%s'",
9962 g_parsefile->left_in_line, 9970 g_parsefile->left_in_line,
9963 g_parsefile->next_to_pgetc, 9971 g_parsefile->next_to_pgetc,
9964 g_parsefile->next_to_pgetc); 9972 g_parsefile->next_to_pgetc);
9965 return pgetc_as_macro(); 9973 if (g_parsefile->unget)
9966} 9974 return g_parsefile->lastc[--g_parsefile->unget];
9967 9975
9968#if ENABLE_ASH_OPTIMIZE_FOR_SIZE 9976 if (--g_parsefile->left_in_line >= 0)
9969# define pgetc_fast() pgetc() 9977 c = (signed char)*g_parsefile->next_to_pgetc++;
9970#else 9978 else
9971# define pgetc_fast() pgetc_as_macro() 9979 c = preadbuffer();
9972#endif 9980
9981 g_parsefile->lastc[1] = g_parsefile->lastc[0];
9982 g_parsefile->lastc[0] = c;
9983
9984 return c;
9985}
9973 9986
9974#if ENABLE_ASH_ALIAS 9987#if ENABLE_ASH_ALIAS
9975static int 9988static int
@@ -9977,11 +9990,11 @@ pgetc_without_PEOA(void)
9977{ 9990{
9978 int c; 9991 int c;
9979 do { 9992 do {
9980 pgetc_debug("pgetc_fast at %d:%p'%s'", 9993 pgetc_debug("pgetc at %d:%p'%s'",
9981 g_parsefile->left_in_line, 9994 g_parsefile->left_in_line,
9982 g_parsefile->next_to_pgetc, 9995 g_parsefile->next_to_pgetc,
9983 g_parsefile->next_to_pgetc); 9996 g_parsefile->next_to_pgetc);
9984 c = pgetc_fast(); 9997 c = pgetc();
9985 } while (c == PEOA); 9998 } while (c == PEOA);
9986 return c; 9999 return c;
9987} 10000}
@@ -10015,18 +10028,13 @@ pfgets(char *line, int len)
10015} 10028}
10016 10029
10017/* 10030/*
10018 * Undo the last call to pgetc. Only one character may be pushed back. 10031 * Undo a call to pgetc. Only two characters may be pushed back.
10019 * PEOF may be pushed back. 10032 * PEOF may be pushed back.
10020 */ 10033 */
10021static void 10034static void
10022pungetc(void) 10035pungetc(void)
10023{ 10036{
10024 g_parsefile->left_in_line++; 10037 g_parsefile->unget++;
10025 g_parsefile->next_to_pgetc--;
10026 pgetc_debug("pushed back to %d:%p'%s'",
10027 g_parsefile->left_in_line,
10028 g_parsefile->next_to_pgetc,
10029 g_parsefile->next_to_pgetc);
10030} 10038}
10031 10039
10032/* 10040/*
@@ -10043,6 +10051,7 @@ pushfile(void)
10043 pf->pf_fd = -1; 10051 pf->pf_fd = -1;
10044 /*pf->strpush = NULL; - ckzalloc did it */ 10052 /*pf->strpush = NULL; - ckzalloc did it */
10045 /*pf->basestrpush.prev = NULL;*/ 10053 /*pf->basestrpush.prev = NULL;*/
10054 /*pf->unget = 0;*/
10046 g_parsefile = pf; 10055 g_parsefile = pf;
10047} 10056}
10048 10057
@@ -11451,7 +11460,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11451 IF_ASH_ALIAS(if (c != PEOA)) 11460 IF_ASH_ALIAS(if (c != PEOA))
11452 USTPUTC(c, out); 11461 USTPUTC(c, out);
11453 } 11462 }
11454 c = pgetc_fast(); 11463 c = pgetc();
11455 } /* for (;;) */ 11464 } /* for (;;) */
11456 endword: 11465 endword:
11457 11466
@@ -11945,7 +11954,7 @@ xxreadtoken(void)
11945 setprompt_if(needprompt, 2); 11954 setprompt_if(needprompt, 2);
11946 startlinno = g_parsefile->linno; 11955 startlinno = g_parsefile->linno;
11947 for (;;) { /* until token or start of word found */ 11956 for (;;) { /* until token or start of word found */
11948 c = pgetc_fast(); 11957 c = pgetc();
11949 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) 11958 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
11950 continue; 11959 continue;
11951 11960
@@ -12008,7 +12017,7 @@ xxreadtoken(void)
12008 setprompt_if(needprompt, 2); 12017 setprompt_if(needprompt, 2);
12009 startlinno = g_parsefile->linno; 12018 startlinno = g_parsefile->linno;
12010 for (;;) { /* until token or start of word found */ 12019 for (;;) { /* until token or start of word found */
12011 c = pgetc_fast(); 12020 c = pgetc();
12012 switch (c) { 12021 switch (c) {
12013 case ' ': case '\t': 12022 case ' ': case '\t':
12014 IF_ASH_ALIAS(case PEOA:) 12023 IF_ASH_ALIAS(case PEOA:)