summaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-09-14 14:09:23 +1000
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-09-14 14:09:23 +1000
commitee7c9b2c212fc7db80cce945e094fc2601092283 (patch)
tree24e51b27dbc3e9ab0b00c5839a6822604c02187c /shell/ash.c
parentf28d4b20905b5b1f52ffa52060a0c6caf4b055ba (diff)
parent99862cbfad9c36b4f8f4378c3a7a9f077c239f20 (diff)
downloadbusybox-w32-ee7c9b2c212fc7db80cce945e094fc2601092283.tar.gz
busybox-w32-ee7c9b2c212fc7db80cce945e094fc2601092283.tar.bz2
busybox-w32-ee7c9b2c212fc7db80cce945e094fc2601092283.zip
Merge remote branch 'origin/master'
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c388
1 files changed, 189 insertions, 199 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 6d67a1f8a..0ff5adb04 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -88,7 +88,7 @@
88//applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, _BB_DIR_BIN, _BB_SUID_DROP, sh)) 88//applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, _BB_DIR_BIN, _BB_SUID_DROP, sh))
89//applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, _BB_DIR_BIN, _BB_SUID_DROP, bash)) 89//applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, _BB_DIR_BIN, _BB_SUID_DROP, bash))
90 90
91//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o 91//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
92//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o 92//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
93 93
94//config:config ASH 94//config:config ASH
@@ -1002,7 +1002,8 @@ sharg(union node *arg, FILE *fp)
1002 for (p = arg->narg.text; *p; p++) { 1002 for (p = arg->narg.text; *p; p++) {
1003 switch ((unsigned char)*p) { 1003 switch ((unsigned char)*p) {
1004 case CTLESC: 1004 case CTLESC:
1005 putc(*++p, fp); 1005 p++;
1006 putc(*p, fp);
1006 break; 1007 break;
1007 case CTLVAR: 1008 case CTLVAR:
1008 putc('$', fp); 1009 putc('$', fp);
@@ -1011,8 +1012,10 @@ sharg(union node *arg, FILE *fp)
1011 if (subtype == VSLENGTH) 1012 if (subtype == VSLENGTH)
1012 putc('#', fp); 1013 putc('#', fp);
1013 1014
1014 while (*p != '=') 1015 while (*p != '=') {
1015 putc(*p++, fp); 1016 putc(*p, fp);
1017 p++;
1018 }
1016 1019
1017 if (subtype & VSNUL) 1020 if (subtype & VSNUL)
1018 putc(':', fp); 1021 putc(':', fp);
@@ -2031,10 +2034,6 @@ extern struct globals_var *const ash_ptr_to_globals_var;
2031# define optindval() (voptind.var_text + 7) 2034# define optindval() (voptind.var_text + 7)
2032#endif 2035#endif
2033 2036
2034
2035#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
2036#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
2037
2038#if ENABLE_ASH_GETOPTS 2037#if ENABLE_ASH_GETOPTS
2039static void FAST_FUNC 2038static void FAST_FUNC
2040getoptsreset(const char *value) 2039getoptsreset(const char *value)
@@ -2044,24 +2043,26 @@ getoptsreset(const char *value)
2044} 2043}
2045#endif 2044#endif
2046 2045
2046/* math.h has these, otherwise define our private copies */
2047#if !ENABLE_SH_MATH_SUPPORT
2048#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
2049#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
2047/* 2050/*
2048 * Return of a legal variable name (a letter or underscore followed by zero or 2051 * Return the pointer to the first char which is not part of a legal variable name
2049 * more letters, underscores, and digits). 2052 * (a letter or underscore followed by letters, underscores, and digits).
2050 */ 2053 */
2051static char* FAST_FUNC 2054static const char*
2052endofname(const char *name) 2055endofname(const char *name)
2053{ 2056{
2054 char *p; 2057 if (!is_name(*name))
2055 2058 return name;
2056 p = (char *) name; 2059 while (*++name) {
2057 if (!is_name(*p)) 2060 if (!is_in_name(*name))
2058 return p;
2059 while (*++p) {
2060 if (!is_in_name(*p))
2061 break; 2061 break;
2062 } 2062 }
2063 return p; 2063 return name;
2064} 2064}
2065#endif
2065 2066
2066/* 2067/*
2067 * Compares two strings up to the first = or '\0'. The first 2068 * Compares two strings up to the first = or '\0'. The first
@@ -2244,9 +2245,10 @@ setvareq(char *s, int flags)
2244static void 2245static void
2245setvar(const char *name, const char *val, int flags) 2246setvar(const char *name, const char *val, int flags)
2246{ 2247{
2247 char *p, *q; 2248 const char *q;
2248 size_t namelen; 2249 char *p;
2249 char *nameeq; 2250 char *nameeq;
2251 size_t namelen;
2250 size_t vallen; 2252 size_t vallen;
2251 2253
2252 q = endofname(name); 2254 q = endofname(name);
@@ -2260,12 +2262,13 @@ setvar(const char *name, const char *val, int flags)
2260 } else { 2262 } else {
2261 vallen = strlen(val); 2263 vallen = strlen(val);
2262 } 2264 }
2265
2263 INT_OFF; 2266 INT_OFF;
2264 nameeq = ckmalloc(namelen + vallen + 2); 2267 nameeq = ckmalloc(namelen + vallen + 2);
2265 p = (char *)memcpy(nameeq, name, namelen) + namelen; 2268 p = memcpy(nameeq, name, namelen) + namelen;
2266 if (val) { 2269 if (val) {
2267 *p++ = '='; 2270 *p++ = '=';
2268 p = (char *)memcpy(p, val, vallen) + vallen; 2271 p = memcpy(p, val, vallen) + vallen;
2269 } 2272 }
2270 *p = '\0'; 2273 *p = '\0';
2271 setvareq(nameeq, flags | VNOSAVE); 2274 setvareq(nameeq, flags | VNOSAVE);
@@ -2491,12 +2494,13 @@ static const char *expandstr(const char *ps);
2491#endif 2494#endif
2492 2495
2493static void 2496static void
2494setprompt(int whichprompt) 2497setprompt_if(smallint do_set, int whichprompt)
2495{ 2498{
2496 const char *prompt; 2499 const char *prompt;
2497#if ENABLE_ASH_EXPAND_PRMT 2500 IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2498 struct stackmark smark; 2501
2499#endif 2502 if (!do_set)
2503 return;
2500 2504
2501 needprompt = 0; 2505 needprompt = 0;
2502 2506
@@ -5734,7 +5738,7 @@ ash_arith(const char *s)
5734 5738
5735 math_hooks.lookupvar = lookupvar; 5739 math_hooks.lookupvar = lookupvar;
5736 math_hooks.setvar = setvar2; 5740 math_hooks.setvar = setvar2;
5737 math_hooks.endofname = endofname; 5741 //math_hooks.endofname = endofname;
5738 5742
5739 INT_OFF; 5743 INT_OFF;
5740 result = arith(s, &errcode, &math_hooks); 5744 result = arith(s, &errcode, &math_hooks);
@@ -6326,7 +6330,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6326 flags &= ~EXP_TILDE; 6330 flags &= ~EXP_TILDE;
6327 tilde: 6331 tilde:
6328 q = p; 6332 q = p;
6329 if (*q == CTLESC && (flags & EXP_QWORD)) 6333 if ((unsigned char)*q == CTLESC && (flags & EXP_QWORD))
6330 q++; 6334 q++;
6331 if (*q == '~') 6335 if (*q == '~')
6332 p = exptilde(p, q, flags); 6336 p = exptilde(p, q, flags);
@@ -6340,9 +6344,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6340 c = p[length]; 6344 c = p[length];
6341 if (c) { 6345 if (c) {
6342 if (!(c & 0x80) 6346 if (!(c & 0x80)
6343#if ENABLE_SH_MATH_SUPPORT 6347 IF_SH_MATH_SUPPORT(|| c == CTLENDARI)
6344 || c == CTLENDARI
6345#endif
6346 ) { 6348 ) {
6347 /* c == '=' || c == ':' || c == CTLENDARI */ 6349 /* c == '=' || c == ':' || c == CTLENDARI */
6348 length++; 6350 length++;
@@ -6389,8 +6391,8 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6389 /* "$@" syntax adherence hack */ 6391 /* "$@" syntax adherence hack */
6390 if (!inquotes 6392 if (!inquotes
6391 && memcmp(p, dolatstr, 4) == 0 6393 && memcmp(p, dolatstr, 4) == 0
6392 && ( p[4] == CTLQUOTEMARK 6394 && ( p[4] == (char)CTLQUOTEMARK
6393 || (p[4] == CTLENDVAR && p[5] == CTLQUOTEMARK) 6395 || (p[4] == (char)CTLENDVAR && p[5] == (char)CTLQUOTEMARK)
6394 ) 6396 )
6395 ) { 6397 ) {
6396 p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1; 6398 p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1;
@@ -6425,8 +6427,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6425#endif 6427#endif
6426 } 6428 }
6427 } 6429 }
6428 breakloop: 6430 breakloop: ;
6429 ;
6430} 6431}
6431 6432
6432static char * 6433static char *
@@ -6611,8 +6612,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6611 int zero; 6612 int zero;
6612 char *(*scan)(char*, char*, char*, char*, int, int); 6613 char *(*scan)(char*, char*, char*, char*, int, int);
6613 6614
6614 //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d", 6615 //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6615 // p, varname, strloc, subtype, startloc, varflags, quotes); 6616 // p, varname, strloc, subtype, startloc, varflags, quotes);
6616 6617
6617 herefd = -1; 6618 herefd = -1;
6618 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0, 6619 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
@@ -7045,8 +7046,8 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
7045 vsplus: 7046 vsplus:
7046 if (varlen < 0) { 7047 if (varlen < 0) {
7047 argstr( 7048 argstr(
7048 p, flags | EXP_TILDE | 7049 p,
7049 (quoted ? EXP_QWORD : EXP_WORD), 7050 flags | (quoted ? EXP_TILDE|EXP_QWORD : EXP_TILDE|EXP_WORD),
7050 var_str_list 7051 var_str_list
7051 ); 7052 );
7052 goto end; 7053 goto end;
@@ -9870,7 +9871,7 @@ evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9870static int 9871static int
9871goodname(const char *p) 9872goodname(const char *p)
9872{ 9873{
9873 return !*endofname(p); 9874 return endofname(p)[0] == '\0';
9874} 9875}
9875 9876
9876 9877
@@ -11501,7 +11502,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11501 startlinno = g_parsefile->linno; 11502 startlinno = g_parsefile->linno;
11502 bqlist = NULL; 11503 bqlist = NULL;
11503 quotef = 0; 11504 quotef = 0;
11504 oldstyle = 0;
11505 prevsyntax = 0; 11505 prevsyntax = 0;
11506#if ENABLE_ASH_EXPAND_PRMT 11506#if ENABLE_ASH_EXPAND_PRMT
11507 pssyntax = (syntax == PSSYNTAX); 11507 pssyntax = (syntax == PSSYNTAX);
@@ -11517,159 +11517,156 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11517 STARTSTACKSTR(out); 11517 STARTSTACKSTR(out);
11518 loop: 11518 loop:
11519 /* For each line, until end of word */ 11519 /* For each line, until end of word */
11520 { 11520 CHECKEND(); /* set c to PEOF if at end of here document */
11521 CHECKEND(); /* set c to PEOF if at end of here document */ 11521 for (;;) { /* until end of line or end of word */
11522 for (;;) { /* until end of line or end of word */ 11522 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
11523 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ 11523 switch (SIT(c, syntax)) {
11524 switch (SIT(c, syntax)) { 11524 case CNL: /* '\n' */
11525 case CNL: /* '\n' */ 11525 if (syntax == BASESYNTAX)
11526 if (syntax == BASESYNTAX) 11526 goto endword; /* exit outer loop */
11527 goto endword; /* exit outer loop */ 11527 USTPUTC(c, out);
11528 USTPUTC(c, out); 11528 g_parsefile->linno++;
11529 g_parsefile->linno++; 11529 setprompt_if(doprompt, 2);
11530 if (doprompt) 11530 c = pgetc();
11531 setprompt(2); 11531 goto loop; /* continue outer loop */
11532 c = pgetc(); 11532 case CWORD:
11533 goto loop; /* continue outer loop */ 11533 USTPUTC(c, out);
11534 case CWORD: 11534 break;
11535 USTPUTC(c, out); 11535 case CCTL:
11536 break; 11536 if (eofmark == NULL || dblquote)
11537 case CCTL: 11537 USTPUTC(CTLESC, out);
11538 if (eofmark == NULL || dblquote)
11539 USTPUTC(CTLESC, out);
11540#if ENABLE_ASH_BASH_COMPAT 11538#if ENABLE_ASH_BASH_COMPAT
11541 if (c == '\\' && bash_dollar_squote) { 11539 if (c == '\\' && bash_dollar_squote) {
11542 c = decode_dollar_squote(); 11540 c = decode_dollar_squote();
11543 if (c & 0x100) { 11541 if (c & 0x100) {
11544 USTPUTC('\\', out); 11542 USTPUTC('\\', out);
11545 c = (unsigned char)c; 11543 c = (unsigned char)c;
11546 }
11547 } 11544 }
11545 }
11548#endif 11546#endif
11549 USTPUTC(c, out); 11547 USTPUTC(c, out);
11550 break; 11548 break;
11551 case CBACK: /* backslash */ 11549 case CBACK: /* backslash */
11552 c = pgetc_without_PEOA(); 11550 c = pgetc_without_PEOA();
11553 if (c == PEOF) { 11551 if (c == PEOF) {
11552 USTPUTC(CTLESC, out);
11553 USTPUTC('\\', out);
11554 pungetc();
11555 } else if (c == '\n') {
11556 setprompt_if(doprompt, 2);
11557 } else {
11558#if ENABLE_ASH_EXPAND_PRMT
11559 if (c == '$' && pssyntax) {
11554 USTPUTC(CTLESC, out); 11560 USTPUTC(CTLESC, out);
11555 USTPUTC('\\', out); 11561 USTPUTC('\\', out);
11556 pungetc(); 11562 }
11557 } else if (c == '\n') {
11558 if (doprompt)
11559 setprompt(2);
11560 } else {
11561#if ENABLE_ASH_EXPAND_PRMT
11562 if (c == '$' && pssyntax) {
11563 USTPUTC(CTLESC, out);
11564 USTPUTC('\\', out);
11565 }
11566#endif 11563#endif
11567 /* Backslash is retained if we are in "str" and next char isn't special */ 11564 /* Backslash is retained if we are in "str" and next char isn't special */
11568 if (dblquote 11565 if (dblquote
11569 && c != '\\' 11566 && c != '\\'
11570 && c != '`' 11567 && c != '`'
11571 && c != '$' 11568 && c != '$'
11572 && (c != '"' || eofmark != NULL) 11569 && (c != '"' || eofmark != NULL)
11573 ) { 11570 ) {
11574 USTPUTC(CTLESC, out); 11571 USTPUTC(CTLESC, out);
11575 USTPUTC('\\', out); 11572 USTPUTC('\\', out);
11576 }
11577 if (SIT(c, SQSYNTAX) == CCTL)
11578 USTPUTC(CTLESC, out);
11579 USTPUTC(c, out);
11580 quotef = 1;
11581 } 11573 }
11582 break; 11574 if (SIT(c, SQSYNTAX) == CCTL)
11583 case CSQUOTE: 11575 USTPUTC(CTLESC, out);
11584 syntax = SQSYNTAX; 11576 USTPUTC(c, out);
11577 quotef = 1;
11578 }
11579 break;
11580 case CSQUOTE:
11581 syntax = SQSYNTAX;
11585 quotemark: 11582 quotemark:
11586 if (eofmark == NULL) { 11583 if (eofmark == NULL) {
11587 USTPUTC(CTLQUOTEMARK, out); 11584 USTPUTC(CTLQUOTEMARK, out);
11585 }
11586 break;
11587 case CDQUOTE:
11588 syntax = DQSYNTAX;
11589 dblquote = 1;
11590 goto quotemark;
11591 case CENDQUOTE:
11592 IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
11593 if (eofmark != NULL && arinest == 0
11594 && varnest == 0
11595 ) {
11596 USTPUTC(c, out);
11597 } else {
11598 if (dqvarnest == 0) {
11599 syntax = BASESYNTAX;
11600 dblquote = 0;
11588 } 11601 }
11589 break; 11602 quotef = 1;
11590 case CDQUOTE:
11591 syntax = DQSYNTAX;
11592 dblquote = 1;
11593 goto quotemark; 11603 goto quotemark;
11594 case CENDQUOTE: 11604 }
11595 IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;) 11605 break;
11596 if (eofmark != NULL && arinest == 0 11606 case CVAR: /* '$' */
11597 && varnest == 0 11607 PARSESUB(); /* parse substitution */
11598 ) { 11608 break;
11599 USTPUTC(c, out); 11609 case CENDVAR: /* '}' */
11600 } else { 11610 if (varnest > 0) {
11601 if (dqvarnest == 0) { 11611 varnest--;
11602 syntax = BASESYNTAX; 11612 if (dqvarnest > 0) {
11603 dblquote = 0; 11613 dqvarnest--;
11604 }
11605 quotef = 1;
11606 goto quotemark;
11607 }
11608 break;
11609 case CVAR: /* '$' */
11610 PARSESUB(); /* parse substitution */
11611 break;
11612 case CENDVAR: /* '}' */
11613 if (varnest > 0) {
11614 varnest--;
11615 if (dqvarnest > 0) {
11616 dqvarnest--;
11617 }
11618 c = CTLENDVAR;
11619 } 11614 }
11620 USTPUTC(c, out); 11615 c = CTLENDVAR;
11621 break; 11616 }
11617 USTPUTC(c, out);
11618 break;
11622#if ENABLE_SH_MATH_SUPPORT 11619#if ENABLE_SH_MATH_SUPPORT
11623 case CLP: /* '(' in arithmetic */ 11620 case CLP: /* '(' in arithmetic */
11624 parenlevel++; 11621 parenlevel++;
11625 USTPUTC(c, out); 11622 USTPUTC(c, out);
11626 break; 11623 break;
11627 case CRP: /* ')' in arithmetic */ 11624 case CRP: /* ')' in arithmetic */
11628 if (parenlevel > 0) { 11625 if (parenlevel > 0) {
11629 parenlevel--; 11626 parenlevel--;
11630 } else { 11627 } else {
11631 if (pgetc() == ')') { 11628 if (pgetc() == ')') {
11632 if (--arinest == 0) { 11629 if (--arinest == 0) {
11633 syntax = prevsyntax; 11630 syntax = prevsyntax;
11634 dblquote = (syntax == DQSYNTAX); 11631 dblquote = (syntax == DQSYNTAX);
11635 c = CTLENDARI; 11632 c = CTLENDARI;
11636 }
11637 } else {
11638 /*
11639 * unbalanced parens
11640 * (don't 2nd guess - no error)
11641 */
11642 pungetc();
11643 } 11633 }
11634 } else {
11635 /*
11636 * unbalanced parens
11637 * (don't 2nd guess - no error)
11638 */
11639 pungetc();
11644 } 11640 }
11645 USTPUTC(c, out); 11641 }
11646 break; 11642 USTPUTC(c, out);
11643 break;
11647#endif 11644#endif
11648 case CBQUOTE: /* '`' */ 11645 case CBQUOTE: /* '`' */
11649 PARSEBACKQOLD(); 11646 PARSEBACKQOLD();
11650 break; 11647 break;
11651 case CENDFILE: 11648 case CENDFILE:
11652 goto endword; /* exit outer loop */ 11649 goto endword; /* exit outer loop */
11653 case CIGN: 11650 case CIGN:
11654 break; 11651 break;
11655 default: 11652 default:
11656 if (varnest == 0) { 11653 if (varnest == 0) {
11657#if ENABLE_ASH_BASH_COMPAT 11654#if ENABLE_ASH_BASH_COMPAT
11658 if (c == '&') { 11655 if (c == '&') {
11659 if (pgetc() == '>') 11656 if (pgetc() == '>')
11660 c = 0x100 + '>'; /* flag &> */ 11657 c = 0x100 + '>'; /* flag &> */
11661 pungetc(); 11658 pungetc();
11662 }
11663#endif
11664 goto endword; /* exit outer loop */
11665 } 11659 }
11666 IF_ASH_ALIAS(if (c != PEOA)) 11660#endif
11667 USTPUTC(c, out); 11661 goto endword; /* exit outer loop */
11668 } 11662 }
11669 c = pgetc_fast(); 11663 IF_ASH_ALIAS(if (c != PEOA))
11670 } /* for (;;) */ 11664 USTPUTC(c, out);
11671 } 11665 }
11666 c = pgetc_fast();
11667 } /* for (;;) */
11672 endword: 11668 endword:
11669
11673#if ENABLE_SH_MATH_SUPPORT 11670#if ENABLE_SH_MATH_SUPPORT
11674 if (syntax == ARISYNTAX) 11671 if (syntax == ARISYNTAX)
11675 raise_error_syntax("missing '))'"); 11672 raise_error_syntax("missing '))'");
@@ -11907,6 +11904,8 @@ parsesub: {
11907 c = pgetc(); 11904 c = pgetc();
11908#if ENABLE_ASH_BASH_COMPAT 11905#if ENABLE_ASH_BASH_COMPAT
11909 if (c == ':' || c == '$' || isdigit(c)) { 11906 if (c == ':' || c == '$' || isdigit(c)) {
11907//TODO: support more general format ${v:EXPR:EXPR},
11908// where EXPR follows $(()) rules
11910 subtype = VSSUBSTR; 11909 subtype = VSSUBSTR;
11911 pungetc(); 11910 pungetc();
11912 break; /* "goto do_pungetc" is bigger (!) */ 11911 break; /* "goto do_pungetc" is bigger (!) */
@@ -11934,6 +11933,9 @@ parsesub: {
11934 } 11933 }
11935#if ENABLE_ASH_BASH_COMPAT 11934#if ENABLE_ASH_BASH_COMPAT
11936 case '/': 11935 case '/':
11936 /* ${v/[/]pattern/repl} */
11937//TODO: encode pattern and repl separately.
11938// Currently ${v/$var_with_slash/repl} is horribly broken
11937 subtype = VSREPLACE; 11939 subtype = VSREPLACE;
11938 c = pgetc(); 11940 c = pgetc();
11939 if (c != '/') 11941 if (c != '/')
@@ -12000,16 +12002,14 @@ parsebackq: {
12000 treatment to some slashes, and then push the string and 12002 treatment to some slashes, and then push the string and
12001 reread it as input, interpreting it normally. */ 12003 reread it as input, interpreting it normally. */
12002 char *pout; 12004 char *pout;
12003 int pc;
12004 size_t psavelen; 12005 size_t psavelen;
12005 char *pstr; 12006 char *pstr;
12006 12007
12007
12008 STARTSTACKSTR(pout); 12008 STARTSTACKSTR(pout);
12009 for (;;) { 12009 for (;;) {
12010 if (needprompt) { 12010 int pc;
12011 setprompt(2); 12011
12012 } 12012 setprompt_if(needprompt, 2);
12013 pc = pgetc(); 12013 pc = pgetc();
12014 switch (pc) { 12014 switch (pc) {
12015 case '`': 12015 case '`':
@@ -12019,8 +12019,7 @@ parsebackq: {
12019 pc = pgetc(); 12019 pc = pgetc();
12020 if (pc == '\n') { 12020 if (pc == '\n') {
12021 g_parsefile->linno++; 12021 g_parsefile->linno++;
12022 if (doprompt) 12022 setprompt_if(doprompt, 2);
12023 setprompt(2);
12024 /* 12023 /*
12025 * If eating a newline, avoid putting 12024 * If eating a newline, avoid putting
12026 * the newline into the new character 12025 * the newline into the new character
@@ -12183,9 +12182,7 @@ xxreadtoken(void)
12183 tokpushback = 0; 12182 tokpushback = 0;
12184 return lasttoken; 12183 return lasttoken;
12185 } 12184 }
12186 if (needprompt) { 12185 setprompt_if(needprompt, 2);
12187 setprompt(2);
12188 }
12189 startlinno = g_parsefile->linno; 12186 startlinno = g_parsefile->linno;
12190 for (;;) { /* until token or start of word found */ 12187 for (;;) { /* until token or start of word found */
12191 c = pgetc_fast(); 12188 c = pgetc_fast();
@@ -12202,8 +12199,7 @@ xxreadtoken(void)
12202 break; /* return readtoken1(...) */ 12199 break; /* return readtoken1(...) */
12203 } 12200 }
12204 startlinno = ++g_parsefile->linno; 12201 startlinno = ++g_parsefile->linno;
12205 if (doprompt) 12202 setprompt_if(doprompt, 2);
12206 setprompt(2);
12207 } else { 12203 } else {
12208 const char *p; 12204 const char *p;
12209 12205
@@ -12249,9 +12245,7 @@ xxreadtoken(void)
12249 tokpushback = 0; 12245 tokpushback = 0;
12250 return lasttoken; 12246 return lasttoken;
12251 } 12247 }
12252 if (needprompt) { 12248 setprompt_if(needprompt, 2);
12253 setprompt(2);
12254 }
12255 startlinno = g_parsefile->linno; 12249 startlinno = g_parsefile->linno;
12256 for (;;) { /* until token or start of word found */ 12250 for (;;) { /* until token or start of word found */
12257 c = pgetc_fast(); 12251 c = pgetc_fast();
@@ -12267,8 +12261,7 @@ xxreadtoken(void)
12267 case '\\': 12261 case '\\':
12268 if (pgetc() == '\n') { 12262 if (pgetc() == '\n') {
12269 startlinno = ++g_parsefile->linno; 12263 startlinno = ++g_parsefile->linno;
12270 if (doprompt) 12264 setprompt_if(doprompt, 2);
12271 setprompt(2);
12272 continue; 12265 continue;
12273 } 12266 }
12274 pungetc(); 12267 pungetc();
@@ -12394,8 +12387,7 @@ parsecmd(int interact)
12394 12387
12395 tokpushback = 0; 12388 tokpushback = 0;
12396 doprompt = interact; 12389 doprompt = interact;
12397 if (doprompt) 12390 setprompt_if(doprompt, doprompt);
12398 setprompt(doprompt);
12399 needprompt = 0; 12391 needprompt = 0;
12400 t = readtoken(); 12392 t = readtoken();
12401 if (t == TEOF) 12393 if (t == TEOF)
@@ -12419,10 +12411,8 @@ parseheredoc(void)
12419 heredoclist = NULL; 12411 heredoclist = NULL;
12420 12412
12421 while (here) { 12413 while (here) {
12422 if (needprompt) { 12414 setprompt_if(needprompt, 2);
12423 setprompt(2); 12415 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12424 }
12425 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
12426 here->eofmark, here->striptabs); 12416 here->eofmark, here->striptabs);
12427 n = stzalloc(sizeof(struct narg)); 12417 n = stzalloc(sizeof(struct narg));
12428 n->narg.type = NARG; 12418 n->narg.type = NARG;