diff options
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 77 |
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 | ||
1173 | struct parsefile { | 1179 | struct 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 | ||
1185 | static struct parsefile basepf; /* top level input file */ | 1197 | static 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) |
9866 | static int pgetc(void); | ||
9849 | static int | 9867 | static int |
9850 | preadbuffer(void) | 9868 | preadbuffer(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 | |||
9958 | static int | 9964 | static int |
9959 | pgetc(void) | 9965 | pgetc(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 |
9975 | static int | 9988 | static 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 | */ |
10021 | static void | 10034 | static void |
10022 | pungetc(void) | 10035 | pungetc(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:) |