aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-23 01:52:30 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-23 01:52:30 +0000
commitef527f50e62ee8c0c9f34e8c1ab0489f6b0b1293 (patch)
treeabbc6ba5df130e8ca3ff2cd927126e5729b463f3
parenta80d0e4bf708fa77852197d07a9de96a9d30295e (diff)
downloadbusybox-w32-ef527f50e62ee8c0c9f34e8c1ab0489f6b0b1293.tar.gz
busybox-w32-ef527f50e62ee8c0c9f34e8c1ab0489f6b0b1293.tar.bz2
busybox-w32-ef527f50e62ee8c0c9f34e8c1ab0489f6b0b1293.zip
ash: optional support for $'...\t...\n...' bashism
function old new delta readtoken1 2824 3172 +348 static.C_escapes - 18 +18 parse_command 1504 1500 -4 SIT 89 83 -6 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/2 up/down: 366/-10) Total: 356 bytes
-rw-r--r--shell/ash.c117
-rw-r--r--shell/ash_test/ash-quoting/dollar_squote_bash1.right9
-rwxr-xr-xshell/ash_test/ash-quoting/dollar_squote_bash1.tests7
3 files changed, 104 insertions, 29 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 7924c4dd9..8a731fd68 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1460,19 +1460,19 @@ _STPUTC(int c, char *p)
1460 if (l > m) \ 1460 if (l > m) \
1461 (p) = makestrspace(l, q); \ 1461 (p) = makestrspace(l, q); \
1462 } while (0) 1462 } while (0)
1463#define USTPUTC(c, p) (*p++ = (c)) 1463#define USTPUTC(c, p) (*(p)++ = (c))
1464#define STACKSTRNUL(p) \ 1464#define STACKSTRNUL(p) \
1465 do { \ 1465 do { \
1466 if ((p) == sstrend) \ 1466 if ((p) == sstrend) \
1467 p = growstackstr(); \ 1467 (p) = growstackstr(); \
1468 *p = '\0'; \ 1468 *(p) = '\0'; \
1469 } while (0) 1469 } while (0)
1470#define STUNPUTC(p) (--p) 1470#define STUNPUTC(p) (--(p))
1471#define STTOPC(p) (p[-1]) 1471#define STTOPC(p) ((p)[-1])
1472#define STADJUST(amount, p) (p += (amount)) 1472#define STADJUST(amount, p) ((p) += (amount))
1473 1473
1474#define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock()) 1474#define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1475#define ungrabstackstr(s, p) stunalloc((s)) 1475#define ungrabstackstr(s, p) stunalloc(s)
1476#define stackstrend() ((void *)sstrend) 1476#define stackstrend() ((void *)sstrend)
1477 1477
1478 1478
@@ -2687,10 +2687,10 @@ SIT(int c, int syntax)
2687 ) { 2687 ) {
2688 return CCTL; 2688 return CCTL;
2689 } else { 2689 } else {
2690 s = strchr(spec_symbls, c); 2690 s = strchrnul(spec_symbls, c);
2691 if (s == NULL || *s == '\0') 2691 if (*s == '\0')
2692 return CWORD; 2692 return CWORD;
2693 indx = syntax_index_table[(s - spec_symbls)]; 2693 indx = syntax_index_table[s - spec_symbls];
2694 } 2694 }
2695 return S_I_T[indx][syntax]; 2695 return S_I_T[indx][syntax];
2696} 2696}
@@ -4201,7 +4201,7 @@ cmdputs(const char *s)
4201 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc); 4201 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4202 p = s; 4202 p = s;
4203 while ((c = *p++) != 0) { 4203 while ((c = *p++) != 0) {
4204 str = 0; 4204 str = NULL;
4205 switch (c) { 4205 switch (c) {
4206 case CTLESC: 4206 case CTLESC:
4207 c = *p++; 4207 c = *p++;
@@ -10345,6 +10345,52 @@ parse_command(void)
10345 return n1; 10345 return n1;
10346} 10346}
10347 10347
10348#if ENABLE_ASH_BASH_COMPAT
10349static int decode_dollar_squote(void)
10350{
10351 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10352 int c, cnt;
10353 char *p;
10354 char buf[4];
10355
10356 c = pgetc();
10357 p = strchr(C_escapes, c);
10358 if (p) {
10359 buf[0] = c;
10360 p = buf;
10361 cnt = 3;
10362 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10363 do {
10364 c = pgetc();
10365 *++p = c;
10366 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10367 pungetc();
10368 } else if (c == 'x') { /* \xHH */
10369 do {
10370 c = pgetc();
10371 *++p = c;
10372 } while (isxdigit(c) && --cnt);
10373 pungetc();
10374 if (cnt == 3) { /* \x but next char is "bad" */
10375 c = 'x';
10376 goto unrecognized;
10377 }
10378 } else { /* simple seq like \\ or \t */
10379 p++;
10380 }
10381 *p = '\0';
10382 p = buf;
10383 c = bb_process_escape_sequence((void*)&p);
10384 } else { /* unrecognized "\z": print both chars unless ' or " */
10385 if (c != '\'' && c != '"') {
10386 unrecognized:
10387 c |= 0x100; /* "please encode \, then me" */
10388 }
10389 }
10390 return c;
10391}
10392#endif
10393
10348/* 10394/*
10349 * If eofmark is NULL, read a word or a redirection symbol. If eofmark 10395 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10350 * is not NULL, read a here document. In the latter case, eofmark is the 10396 * is not NULL, read a here document. In the latter case, eofmark is the
@@ -10356,14 +10402,12 @@ parse_command(void)
10356 * using goto's to implement the subroutine linkage. The following macros 10402 * using goto's to implement the subroutine linkage. The following macros
10357 * will run code that appears at the end of readtoken1. 10403 * will run code that appears at the end of readtoken1.
10358 */ 10404 */
10359
10360#define CHECKEND() {goto checkend; checkend_return:;} 10405#define CHECKEND() {goto checkend; checkend_return:;}
10361#define PARSEREDIR() {goto parseredir; parseredir_return:;} 10406#define PARSEREDIR() {goto parseredir; parseredir_return:;}
10362#define PARSESUB() {goto parsesub; parsesub_return:;} 10407#define PARSESUB() {goto parsesub; parsesub_return:;}
10363#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} 10408#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10364#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} 10409#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10365#define PARSEARITH() {goto parsearith; parsearith_return:;} 10410#define PARSEARITH() {goto parsearith; parsearith_return:;}
10366
10367static int 10411static int
10368readtoken1(int firstc, int syntax, char *eofmark, int striptabs) 10412readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10369{ 10413{
@@ -10385,6 +10429,8 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10385 int parenlevel; /* levels of parens in arithmetic */ 10429 int parenlevel; /* levels of parens in arithmetic */
10386 int dqvarnest; /* levels of variables expansion within double quotes */ 10430 int dqvarnest; /* levels of variables expansion within double quotes */
10387 10431
10432 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10433
10388#if __GNUC__ 10434#if __GNUC__
10389 /* Avoid longjmp clobbering */ 10435 /* Avoid longjmp clobbering */
10390 (void) &out; 10436 (void) &out;
@@ -10435,6 +10481,15 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10435 case CCTL: 10481 case CCTL:
10436 if (eofmark == NULL || dblquote) 10482 if (eofmark == NULL || dblquote)
10437 USTPUTC(CTLESC, out); 10483 USTPUTC(CTLESC, out);
10484#if ENABLE_ASH_BASH_COMPAT
10485 if (c == '\\' && bash_dollar_squote) {
10486 c = decode_dollar_squote();
10487 if (c & 0x100) {
10488 USTPUTC('\\', out);
10489 c = (unsigned char)c;
10490 }
10491 }
10492#endif
10438 USTPUTC(c, out); 10493 USTPUTC(c, out);
10439 break; 10494 break;
10440 case CBACK: /* backslash */ 10495 case CBACK: /* backslash */
@@ -10453,11 +10508,9 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10453 USTPUTC('\\', out); 10508 USTPUTC('\\', out);
10454 } 10509 }
10455#endif 10510#endif
10456 if (dblquote && 10511 if (dblquote && c != '\\'
10457 c != '\\' && c != '`' && 10512 && c != '`' && c != '$'
10458 c != '$' && ( 10513 && (c != '"' || eofmark != NULL)
10459 c != '"' ||
10460 eofmark != NULL)
10461 ) { 10514 ) {
10462 USTPUTC(CTLESC, out); 10515 USTPUTC(CTLESC, out);
10463 USTPUTC('\\', out); 10516 USTPUTC('\\', out);
@@ -10480,6 +10533,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10480 dblquote = 1; 10533 dblquote = 1;
10481 goto quotemark; 10534 goto quotemark;
10482 case CENDQUOTE: 10535 case CENDQUOTE:
10536 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10483 if (eofmark != NULL && arinest == 0 10537 if (eofmark != NULL && arinest == 0
10484 && varnest == 0 10538 && varnest == 0
10485 ) { 10539 ) {
@@ -10552,7 +10606,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10552 10606
10553 } 10607 }
10554 c = pgetc_macro(); 10608 c = pgetc_macro();
10555 } 10609 } /* for(;;) */
10556 } 10610 }
10557 endword: 10611 endword:
10558#if ENABLE_ASH_MATH_SUPPORT 10612#if ENABLE_ASH_MATH_SUPPORT
@@ -10573,12 +10627,13 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10573 if ((c == '>' || c == '<') 10627 if ((c == '>' || c == '<')
10574 && quotef == 0 10628 && quotef == 0
10575 && len <= 2 10629 && len <= 2
10576 && (*out == '\0' || isdigit(*out))) { 10630 && (*out == '\0' || isdigit(*out))
10631 ) {
10577 PARSEREDIR(); 10632 PARSEREDIR();
10578 return lasttoken = TREDIR; 10633 lasttoken = TREDIR;
10579 } else { 10634 return lasttoken;
10580 pungetc();
10581 } 10635 }
10636 pungetc();
10582 } 10637 }
10583 quoteflag = quotef; 10638 quoteflag = quotef;
10584 backquotelist = bqlist; 10639 backquotelist = bqlist;
@@ -10697,8 +10752,8 @@ parseredir: {
10697/* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise 10752/* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10698 * (assuming ascii char codes, as the original implementation did) */ 10753 * (assuming ascii char codes, as the original implementation did) */
10699#define is_special(c) \ 10754#define is_special(c) \
10700 ((((unsigned int)c) - 33 < 32) \ 10755 (((unsigned)(c) - 33 < 32) \
10701 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1)) 10756 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
10702parsesub: { 10757parsesub: {
10703 int subtype; 10758 int subtype;
10704 int typeloc; 10759 int typeloc;
@@ -10707,11 +10762,15 @@ parsesub: {
10707 static const char types[] ALIGN1 = "}-+?="; 10762 static const char types[] ALIGN1 = "}-+?=";
10708 10763
10709 c = pgetc(); 10764 c = pgetc();
10710 if ( 10765 if (c <= PEOA_OR_PEOF
10711 c <= PEOA_OR_PEOF || 10766 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10712 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10713 ) { 10767 ) {
10714 USTPUTC('$', out); 10768#if ENABLE_ASH_BASH_COMPAT
10769 if (c == '\'')
10770 bash_dollar_squote = 1;
10771 else
10772#endif
10773 USTPUTC('$', out);
10715 pungetc(); 10774 pungetc();
10716 } else if (c == '(') { /* $(command) or $((arith)) */ 10775 } else if (c == '(') { /* $(command) or $((arith)) */
10717 if (pgetc() == '(') { 10776 if (pgetc() == '(') {
diff --git a/shell/ash_test/ash-quoting/dollar_squote_bash1.right b/shell/ash_test/ash-quoting/dollar_squote_bash1.right
new file mode 100644
index 000000000..57536b1d9
--- /dev/null
+++ b/shell/ash_test/ash-quoting/dollar_squote_bash1.right
@@ -0,0 +1,9 @@
1a b
2a
3b c
4def
5a'b c"d e\f
6a3b c3b e33f
7a\80b c08b
8a3b c30b
9x y
diff --git a/shell/ash_test/ash-quoting/dollar_squote_bash1.tests b/shell/ash_test/ash-quoting/dollar_squote_bash1.tests
new file mode 100755
index 000000000..93a56cac3
--- /dev/null
+++ b/shell/ash_test/ash-quoting/dollar_squote_bash1.tests
@@ -0,0 +1,7 @@
1echo $'a\tb'
2echo $'a\nb' $'c\nd''ef'
3echo $'a\'b' $'c\"d' $'e\\f'
4echo $'a\63b' $'c\063b' $'e\0633f'
5echo $'a\80b' $'c\608b'
6echo $'a\x33b' $'c\x330b'
7echo $'x\x9y'