aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c239
1 files changed, 108 insertions, 131 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 5a001b004..ba116d83a 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -295,6 +295,10 @@ typedef long arith_t;
295# define PIPE_BUF 4096 /* amount of buffering in a pipe */ 295# define PIPE_BUF 4096 /* amount of buffering in a pipe */
296#endif 296#endif
297 297
298#ifndef unlikely
299# define unlikely(cond) (cond)
300#endif
301
298#if !BB_MMU 302#if !BB_MMU
299# error "Do not even bother, ash will not run on NOMMU machine" 303# error "Do not even bother, ash will not run on NOMMU machine"
300#endif 304#endif
@@ -583,6 +587,9 @@ struct strpush {
583#endif 587#endif
584 char *string; /* remember the string since it may change */ 588 char *string; /* remember the string since it may change */
585 589
590 /* Delay freeing so we can stop nested aliases. */
591 struct strpush *spfree;
592
586 /* Remember last two characters for pungetc. */ 593 /* Remember last two characters for pungetc. */
587 int lastc[2]; 594 int lastc[2];
588 595
@@ -605,6 +612,9 @@ struct parsefile {
605 struct strpush *strpush; /* for pushing strings at this level */ 612 struct strpush *strpush; /* for pushing strings at this level */
606 struct strpush basestrpush; /* so pushing one is fast */ 613 struct strpush basestrpush; /* so pushing one is fast */
607 614
615 /* Delay freeing so we can stop nested aliases. */
616 struct strpush *spfree;
617
608 /* Remember last two characters for pungetc. */ 618 /* Remember last two characters for pungetc. */
609 int lastc[2]; 619 int lastc[2];
610 620
@@ -3013,12 +3023,8 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3013#define CENDFILE 11 /* end of file */ 3023#define CENDFILE 11 /* end of file */
3014#define CCTL 12 /* like CWORD, except it must be escaped */ 3024#define CCTL 12 /* like CWORD, except it must be escaped */
3015#define CSPCL 13 /* these terminate a word */ 3025#define CSPCL 13 /* these terminate a word */
3016#define CIGN 14 /* character should be ignored */
3017 3026
3018#define PEOF 256 3027#define PEOF 256
3019#if ENABLE_ASH_ALIAS
3020# define PEOA 257
3021#endif
3022 3028
3023#define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE 3029#define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
3024 3030
@@ -3028,49 +3034,43 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3028# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8)) 3034# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
3029#endif 3035#endif
3030static const uint16_t S_I_T[] ALIGN2 = { 3036static const uint16_t S_I_T[] ALIGN2 = {
3031#if ENABLE_ASH_ALIAS 3037 SIT_ITEM(CSPCL , CWORD , CWORD, CWORD ), /* 0, ' ' */
3032 SIT_ITEM(CSPCL , CIGN , CIGN , CIGN ), /* 0, PEOA */ 3038 SIT_ITEM(CNL , CNL , CNL , CNL ), /* 1, \n */
3033#endif 3039 SIT_ITEM(CWORD , CCTL , CCTL , CWORD ), /* 2, !*-/:=?[]~ */
3034 SIT_ITEM(CSPCL , CWORD , CWORD, CWORD ), /* 1, ' ' */ 3040 SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD ), /* 3, '"' */
3035 SIT_ITEM(CNL , CNL , CNL , CNL ), /* 2, \n */ 3041 SIT_ITEM(CVAR , CVAR , CWORD, CVAR ), /* 4, $ */
3036 SIT_ITEM(CWORD , CCTL , CCTL , CWORD ), /* 3, !*-/:=?[]~ */ 3042 SIT_ITEM(CSQUOTE , CWORD , CENDQUOTE, CWORD), /* 5, "'" */
3037 SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD ), /* 4, '"' */ 3043 SIT_ITEM(CSPCL , CWORD , CWORD, CLP ), /* 6, ( */
3038 SIT_ITEM(CVAR , CVAR , CWORD, CVAR ), /* 5, $ */ 3044 SIT_ITEM(CSPCL , CWORD , CWORD, CRP ), /* 7, ) */
3039 SIT_ITEM(CSQUOTE , CWORD , CENDQUOTE, CWORD), /* 6, "'" */ 3045 SIT_ITEM(CBACK , CBACK , CCTL , CBACK ), /* 8, \ */
3040 SIT_ITEM(CSPCL , CWORD , CWORD, CLP ), /* 7, ( */ 3046 SIT_ITEM(CBQUOTE , CBQUOTE , CWORD, CBQUOTE), /* 9, ` */
3041 SIT_ITEM(CSPCL , CWORD , CWORD, CRP ), /* 8, ) */ 3047 SIT_ITEM(CENDVAR , CENDVAR , CWORD, CENDVAR), /* 10, } */
3042 SIT_ITEM(CBACK , CBACK , CCTL , CBACK ), /* 9, \ */
3043 SIT_ITEM(CBQUOTE , CBQUOTE , CWORD, CBQUOTE), /* 10, ` */
3044 SIT_ITEM(CENDVAR , CENDVAR , CWORD, CENDVAR), /* 11, } */
3045#if !USE_SIT_FUNCTION 3048#if !USE_SIT_FUNCTION
3046 SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */ 3049 SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 11, PEOF */
3047 SIT_ITEM(CWORD , CWORD , CWORD, CWORD ), /* 13, 0-9A-Za-z */ 3050 SIT_ITEM(CWORD , CWORD , CWORD, CWORD ), /* 12, 0-9A-Za-z */
3048 SIT_ITEM(CCTL , CCTL , CCTL , CCTL ) /* 14, CTLESC ... */ 3051 SIT_ITEM(CCTL , CCTL , CCTL , CCTL ) /* 13, CTLESC ... */
3049#endif 3052#endif
3050#undef SIT_ITEM 3053#undef SIT_ITEM
3051}; 3054};
3052/* Constants below must match table above */ 3055/* Constants below must match table above */
3053enum { 3056enum {
3054#if ENABLE_ASH_ALIAS 3057 CSPCL_CWORD_CWORD_CWORD , /* 0 */
3055 CSPCL_CIGN_CIGN_CIGN , /* 0 */ 3058 CNL_CNL_CNL_CNL , /* 1 */
3056#endif 3059 CWORD_CCTL_CCTL_CWORD , /* 2 */
3057 CSPCL_CWORD_CWORD_CWORD , /* 1 */ 3060 CDQUOTE_CENDQUOTE_CWORD_CWORD , /* 3 */
3058 CNL_CNL_CNL_CNL , /* 2 */ 3061 CVAR_CVAR_CWORD_CVAR , /* 4 */
3059 CWORD_CCTL_CCTL_CWORD , /* 3 */ 3062 CSQUOTE_CWORD_CENDQUOTE_CWORD , /* 5 */
3060 CDQUOTE_CENDQUOTE_CWORD_CWORD , /* 4 */ 3063 CSPCL_CWORD_CWORD_CLP , /* 6 */
3061 CVAR_CVAR_CWORD_CVAR , /* 5 */ 3064 CSPCL_CWORD_CWORD_CRP , /* 7 */
3062 CSQUOTE_CWORD_CENDQUOTE_CWORD , /* 6 */ 3065 CBACK_CBACK_CCTL_CBACK , /* 8 */
3063 CSPCL_CWORD_CWORD_CLP , /* 7 */ 3066 CBQUOTE_CBQUOTE_CWORD_CBQUOTE , /* 9 */
3064 CSPCL_CWORD_CWORD_CRP , /* 8 */ 3067 CENDVAR_CENDVAR_CWORD_CENDVAR , /* 10 */
3065 CBACK_CBACK_CCTL_CBACK , /* 9 */ 3068 CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 11 */
3066 CBQUOTE_CBQUOTE_CWORD_CBQUOTE , /* 10 */ 3069 CWORD_CWORD_CWORD_CWORD , /* 12 */
3067 CENDVAR_CENDVAR_CWORD_CENDVAR , /* 11 */ 3070 CCTL_CCTL_CCTL_CCTL , /* 13 */
3068 CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
3069 CWORD_CWORD_CWORD_CWORD , /* 13 */
3070 CCTL_CCTL_CCTL_CCTL , /* 14 */
3071}; 3071};
3072 3072
3073/* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF, 3073/* c in SIT(c, syntax) must be an *unsigned char* or PEOF,
3074 * caller must ensure proper cast on it if c is *char_ptr! 3074 * caller must ensure proper cast on it if c is *char_ptr!
3075 */ 3075 */
3076#if USE_SIT_FUNCTION 3076#if USE_SIT_FUNCTION
@@ -3088,44 +3088,28 @@ SIT(int c, int syntax)
3088 * but glibc one isn't. With '/' always treated as CWORD, 3088 * but glibc one isn't. With '/' always treated as CWORD,
3089 * both work fine. 3089 * both work fine.
3090 */ 3090 */
3091# if ENABLE_ASH_ALIAS
3092 static const uint8_t syntax_index_table[] ALIGN1 = {
3093 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
3094 7, 8, 3, 3,/*3,*/3, 1, 1, /* "()*-/:;<" */
3095 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
3096 11, 3 /* "}~" */
3097 };
3098# else
3099 static const uint8_t syntax_index_table[] ALIGN1 = { 3091 static const uint8_t syntax_index_table[] ALIGN1 = {
3100 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */ 3092 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
3101 6, 7, 2, 2,/*2,*/2, 0, 0, /* "()*-/:;<" */ 3093 6, 7, 2, 2,/*2,*/2, 0, 0, /* "()*-/:;<" */
3102 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */ 3094 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
3103 10, 2 /* "}~" */ 3095 10, 2 /* "}~" */
3104 }; 3096 };
3105# endif
3106 const char *s; 3097 const char *s;
3107 int indx; 3098 int indx;
3108 3099
3109 if (c == PEOF) 3100 if (c == PEOF)
3110 return CENDFILE; 3101 return CENDFILE;
3111# if ENABLE_ASH_ALIAS 3102 /* Cast is purely for paranoia here,
3112 if (c == PEOA) 3103 * just in case someone passed signed char to us */
3113 indx = 0; 3104 if ((unsigned char)c >= CTL_FIRST
3114 else 3105 && (unsigned char)c <= CTL_LAST
3115# endif 3106 ) {
3116 { 3107 return CCTL;
3117 /* Cast is purely for paranoia here,
3118 * just in case someone passed signed char to us */
3119 if ((unsigned char)c >= CTL_FIRST
3120 && (unsigned char)c <= CTL_LAST
3121 ) {
3122 return CCTL;
3123 }
3124 s = strchrnul(spec_symbls, c);
3125 if (*s == '\0')
3126 return CWORD;
3127 indx = syntax_index_table[s - spec_symbls];
3128 } 3108 }
3109 s = strchrnul(spec_symbls, c);
3110 if (*s == '\0')
3111 return CWORD;
3112 indx = syntax_index_table[s - spec_symbls];
3129 return (S_I_T[indx] >> (syntax*4)) & 0xf; 3113 return (S_I_T[indx] >> (syntax*4)) & 0xf;
3130} 3114}
3131 3115
@@ -3396,9 +3380,6 @@ static const uint8_t syntax_index_table[] ALIGN1 = {
3396 /* 254 */ CWORD_CWORD_CWORD_CWORD, 3380 /* 254 */ CWORD_CWORD_CWORD_CWORD,
3397 /* 255 */ CWORD_CWORD_CWORD_CWORD, 3381 /* 255 */ CWORD_CWORD_CWORD_CWORD,
3398 /* PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE, 3382 /* PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3399# if ENABLE_ASH_ALIAS
3400 /* PEOA */ CSPCL_CIGN_CIGN_CIGN,
3401# endif
3402}; 3383};
3403 3384
3404#if 1 3385#if 1
@@ -10712,7 +10693,7 @@ pushstring(char *s, struct alias *ap)
10712 10693
10713 len = strlen(s); 10694 len = strlen(s);
10714 INT_OFF; 10695 INT_OFF;
10715 if (g_parsefile->strpush) { 10696 if (g_parsefile->strpush || g_parsefile->spfree) {
10716 sp = ckzalloc(sizeof(*sp)); 10697 sp = ckzalloc(sizeof(*sp));
10717 sp->prev = g_parsefile->strpush; 10698 sp->prev = g_parsefile->strpush;
10718 } else { 10699 } else {
@@ -10722,6 +10703,7 @@ pushstring(char *s, struct alias *ap)
10722 sp->prev_string = g_parsefile->next_to_pgetc; 10703 sp->prev_string = g_parsefile->next_to_pgetc;
10723 sp->prev_left_in_line = g_parsefile->left_in_line; 10704 sp->prev_left_in_line = g_parsefile->left_in_line;
10724 sp->unget = g_parsefile->unget; 10705 sp->unget = g_parsefile->unget;
10706 sp->spfree = g_parsefile->spfree;
10725 memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc)); 10707 memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10726#if ENABLE_ASH_ALIAS 10708#if ENABLE_ASH_ALIAS
10727 sp->ap = ap; 10709 sp->ap = ap;
@@ -10733,11 +10715,11 @@ pushstring(char *s, struct alias *ap)
10733 g_parsefile->next_to_pgetc = s; 10715 g_parsefile->next_to_pgetc = s;
10734 g_parsefile->left_in_line = len; 10716 g_parsefile->left_in_line = len;
10735 g_parsefile->unget = 0; 10717 g_parsefile->unget = 0;
10718 g_parsefile->spfree = NULL;
10736 INT_ON; 10719 INT_ON;
10737} 10720}
10738 10721
10739static void 10722static void popstring(void)
10740popstring(void)
10741{ 10723{
10742 struct strpush *sp = g_parsefile->strpush; 10724 struct strpush *sp = g_parsefile->strpush;
10743 10725
@@ -10752,10 +10734,6 @@ popstring(void)
10752 if (sp->string != sp->ap->val) { 10734 if (sp->string != sp->ap->val) {
10753 free(sp->string); 10735 free(sp->string);
10754 } 10736 }
10755 sp->ap->flag &= ~ALIASINUSE;
10756 if (sp->ap->flag & ALIASDEAD) {
10757 unalias(sp->ap->name);
10758 }
10759 } 10737 }
10760#endif 10738#endif
10761 g_parsefile->next_to_pgetc = sp->prev_string; 10739 g_parsefile->next_to_pgetc = sp->prev_string;
@@ -10763,8 +10741,7 @@ popstring(void)
10763 g_parsefile->unget = sp->unget; 10741 g_parsefile->unget = sp->unget;
10764 memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc)); 10742 memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10765 g_parsefile->strpush = sp->prev; 10743 g_parsefile->strpush = sp->prev;
10766 if (sp != &(g_parsefile->basestrpush)) 10744 g_parsefile->spfree = sp;
10767 free(sp);
10768 INT_ON; 10745 INT_ON;
10769} 10746}
10770 10747
@@ -10853,26 +10830,16 @@ preadfd(void)
10853 */ 10830 */
10854//#define pgetc_debug(...) bb_error_msg(__VA_ARGS__) 10831//#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10855#define pgetc_debug(...) ((void)0) 10832#define pgetc_debug(...) ((void)0)
10856static int pgetc(void); 10833static int __pgetc(void);
10857static int 10834static int
10858preadbuffer(void) 10835preadbuffer(void)
10859{ 10836{
10860 char *q; 10837 char *q;
10861 int more; 10838 int more;
10862 10839
10863 if (g_parsefile->strpush) { 10840 if (unlikely(g_parsefile->strpush)) {
10864#if ENABLE_ASH_ALIAS
10865 if (g_parsefile->left_in_line == -1
10866 && g_parsefile->strpush->ap
10867 && g_parsefile->next_to_pgetc[-1] != ' '
10868 && g_parsefile->next_to_pgetc[-1] != '\t'
10869 ) {
10870 pgetc_debug("preadbuffer PEOA");
10871 return PEOA;
10872 }
10873#endif
10874 popstring(); 10841 popstring();
10875 return pgetc(); 10842 return __pgetc();
10876 } 10843 }
10877 /* on both branches above g_parsefile->left_in_line < 0. 10844 /* on both branches above g_parsefile->left_in_line < 0.
10878 * "pgetc" needs refilling. 10845 * "pgetc" needs refilling.
@@ -10966,8 +10933,31 @@ nlnoprompt(void)
10966 needprompt = doprompt; 10933 needprompt = doprompt;
10967} 10934}
10968 10935
10969static int 10936static void freestrings(struct strpush *sp)
10970pgetc(void) 10937{
10938 INT_OFF;
10939 do {
10940 struct strpush *psp;
10941
10942 if (sp->ap) {
10943 sp->ap->flag &= ~ALIASINUSE;
10944 if (sp->ap->flag & ALIASDEAD) {
10945 unalias(sp->ap->name);
10946 }
10947 }
10948
10949 psp = sp;
10950 sp = sp->spfree;
10951
10952 if (psp != &(g_parsefile->basestrpush))
10953 free(psp);
10954 } while (sp);
10955
10956 g_parsefile->spfree = NULL;
10957 INT_ON;
10958}
10959
10960static int __pgetc(void)
10971{ 10961{
10972 int c; 10962 int c;
10973 10963
@@ -10989,23 +10979,19 @@ pgetc(void)
10989 return c; 10979 return c;
10990} 10980}
10991 10981
10992#if ENABLE_ASH_ALIAS 10982/*
10993static int 10983 * Read a character from the script, returning PEOF on end of file.
10994pgetc_without_PEOA(void) 10984 * Nul characters in the input are silently discarded.
10985 */
10986static int pgetc(void)
10995{ 10987{
10996 int c; 10988 struct strpush *sp = g_parsefile->spfree;
10997 do { 10989
10998 pgetc_debug("pgetc at %d:%p'%s'", 10990 if (unlikely(sp))
10999 g_parsefile->left_in_line, 10991 freestrings(sp);
11000 g_parsefile->next_to_pgetc, 10992
11001 g_parsefile->next_to_pgetc); 10993 return __pgetc();
11002 c = pgetc();
11003 } while (c == PEOA);
11004 return c;
11005} 10994}
11006#else
11007# define pgetc_without_PEOA() pgetc()
11008#endif
11009 10995
11010/* 10996/*
11011 * Undo a call to pgetc. Only two characters may be pushed back. 10997 * Undo a call to pgetc. Only two characters may be pushed back.
@@ -11082,6 +11068,7 @@ pushfile(void)
11082 pf->prev = g_parsefile; 11068 pf->prev = g_parsefile;
11083 pf->pf_fd = -1; 11069 pf->pf_fd = -1;
11084 /*pf->strpush = NULL; - ckzalloc did it */ 11070 /*pf->strpush = NULL; - ckzalloc did it */
11071 /*pf->spfree = NULL;*/
11085 /*pf->basestrpush.prev = NULL;*/ 11072 /*pf->basestrpush.prev = NULL;*/
11086 /*pf->unget = 0;*/ 11073 /*pf->unget = 0;*/
11087 g_parsefile = pf; 11074 g_parsefile = pf;
@@ -11099,8 +11086,12 @@ popfile(void)
11099 if (pf->pf_fd >= 0) 11086 if (pf->pf_fd >= 0)
11100 close(pf->pf_fd); 11087 close(pf->pf_fd);
11101 free(pf->buf); 11088 free(pf->buf);
11102 while (pf->strpush) 11089 if (g_parsefile->spfree)
11090 freestrings(g_parsefile->spfree);
11091 while (pf->strpush) {
11103 popstring(); 11092 popstring();
11093 freestrings(g_parsefile->spfree);
11094 }
11104 g_parsefile = pf->prev; 11095 g_parsefile = pf->prev;
11105 free(pf); 11096 free(pf);
11106 INT_ON; 11097 INT_ON;
@@ -12390,7 +12381,7 @@ static int
12390readtoken1(int c, int syntax, char *eofmark, int striptabs) 12381readtoken1(int c, int syntax, char *eofmark, int striptabs)
12391{ 12382{
12392 /* NB: syntax parameter fits into smallint */ 12383 /* NB: syntax parameter fits into smallint */
12393 /* c parameter is an unsigned char or PEOF or PEOA */ 12384 /* c parameter is an unsigned char or PEOF */
12394 char *out; 12385 char *out;
12395 size_t len; 12386 size_t len;
12396 struct nodelist *bqlist; 12387 struct nodelist *bqlist;
@@ -12460,7 +12451,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12460 USTPUTC(c, out); 12451 USTPUTC(c, out);
12461 break; 12452 break;
12462 case CBACK: /* backslash */ 12453 case CBACK: /* backslash */
12463 c = pgetc_without_PEOA(); 12454 c = pgetc();
12464 if (c == PEOF) { 12455 if (c == PEOF) {
12465 USTPUTC(CTLESC, out); 12456 USTPUTC(CTLESC, out);
12466 USTPUTC('\\', out); 12457 USTPUTC('\\', out);
@@ -12567,8 +12558,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12567 break; 12558 break;
12568 case CENDFILE: 12559 case CENDFILE:
12569 goto endword; /* exit outer loop */ 12560 goto endword; /* exit outer loop */
12570 case CIGN:
12571 break;
12572 default: 12561 default:
12573 if (synstack->varnest == 0) { 12562 if (synstack->varnest == 0) {
12574#if BASH_REDIR_OUTPUT 12563#if BASH_REDIR_OUTPUT
@@ -12590,8 +12579,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12590#endif 12579#endif
12591 goto endword; /* exit outer loop */ 12580 goto endword; /* exit outer loop */
12592 } 12581 }
12593 IF_ASH_ALIAS(if (c != PEOA)) 12582 USTPUTC(c, out);
12594 USTPUTC(c, out);
12595 } 12583 }
12596 c = pgetc_top(synstack); 12584 c = pgetc_top(synstack);
12597 } /* for (;;) */ 12585 } /* for (;;) */
@@ -12642,14 +12630,9 @@ checkend: {
12642 int markloc; 12630 int markloc;
12643 char *p; 12631 char *p;
12644 12632
12645#if ENABLE_ASH_ALIAS
12646 if (c == PEOA)
12647 c = pgetc_without_PEOA();
12648#endif
12649 if (striptabs) { 12633 if (striptabs) {
12650 while (c == '\t') { 12634 while (c == '\t')
12651 c = pgetc_without_PEOA(); 12635 c = pgetc();
12652 }
12653 } 12636 }
12654 12637
12655 markloc = out - (char *)stackblock(); 12638 markloc = out - (char *)stackblock();
@@ -12663,7 +12646,7 @@ checkend: {
12663 * F 12646 * F
12664 * (see heredoc_bkslash_newline2.tests) 12647 * (see heredoc_bkslash_newline2.tests)
12665 */ 12648 */
12666 c = pgetc_without_PEOA(); 12649 c = pgetc();
12667 } 12650 }
12668 12651
12669 if (c == '\n' || c == PEOF) { 12652 if (c == '\n' || c == PEOF) {
@@ -12788,7 +12771,6 @@ parsesub: {
12788 12771
12789 c = pgetc_eatbnl(); 12772 c = pgetc_eatbnl();
12790 if ((checkkwd & CHKEOFMARK) 12773 if ((checkkwd & CHKEOFMARK)
12791 || c > 255 /* PEOA or PEOF */
12792 || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) 12774 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12793 ) { 12775 ) {
12794#if BASH_DOLLAR_SQUOTE 12776#if BASH_DOLLAR_SQUOTE
@@ -12811,7 +12793,7 @@ parsesub: {
12811 PARSEBACKQNEW(); 12793 PARSEBACKQNEW();
12812 } 12794 }
12813 } else { 12795 } else {
12814 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */ 12796 /* $VAR, $<specialchar>, ${...}, or PEOF */
12815 smalluint newsyn = synstack->syntax; 12797 smalluint newsyn = synstack->syntax;
12816 12798
12817 USTPUTC(CTLVAR, out); 12799 USTPUTC(CTLVAR, out);
@@ -13006,13 +12988,9 @@ parsebackq: {
13006 ) { 12988 ) {
13007 STPUTC('\\', pout); 12989 STPUTC('\\', pout);
13008 } 12990 }
13009 if (pc <= 255 /* not PEOA or PEOF */) { 12991 break;
13010 break;
13011 }
13012 /* fall through */
13013 12992
13014 case PEOF: 12993 case PEOF:
13015 IF_ASH_ALIAS(case PEOA:)
13016 raise_error_syntax("EOF in backquote substitution"); 12994 raise_error_syntax("EOF in backquote substitution");
13017 12995
13018 case '\n': 12996 case '\n':
@@ -13147,7 +13125,7 @@ xxreadtoken(void)
13147 setprompt_if(needprompt, 2); 13125 setprompt_if(needprompt, 2);
13148 for (;;) { /* until token or start of word found */ 13126 for (;;) { /* until token or start of word found */
13149 c = pgetc_eatbnl(); 13127 c = pgetc_eatbnl();
13150 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) 13128 if (c == ' ' || c == '\t')
13151 continue; 13129 continue;
13152 13130
13153 if (c == '#') { 13131 if (c == '#') {
@@ -13205,7 +13183,6 @@ xxreadtoken(void)
13205 c = pgetc_eatbnl(); 13183 c = pgetc_eatbnl();
13206 switch (c) { 13184 switch (c) {
13207 case ' ': case '\t': 13185 case ' ': case '\t':
13208 IF_ASH_ALIAS(case PEOA:)
13209 continue; 13186 continue;
13210 case '#': 13187 case '#':
13211 while ((c = pgetc()) != '\n' && c != PEOF) 13188 while ((c = pgetc()) != '\n' && c != PEOF)