diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-23 01:52:30 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-23 01:52:30 +0000 |
commit | ef527f50e62ee8c0c9f34e8c1ab0489f6b0b1293 (patch) | |
tree | abbc6ba5df130e8ca3ff2cd927126e5729b463f3 | |
parent | a80d0e4bf708fa77852197d07a9de96a9d30295e (diff) | |
download | busybox-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.c | 117 | ||||
-rw-r--r-- | shell/ash_test/ash-quoting/dollar_squote_bash1.right | 9 | ||||
-rwxr-xr-x | shell/ash_test/ash-quoting/dollar_squote_bash1.tests | 7 |
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 | ||
10349 | static 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 | |||
10367 | static int | 10411 | static int |
10368 | readtoken1(int firstc, int syntax, char *eofmark, int striptabs) | 10412 | readtoken1(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)) |
10702 | parsesub: { | 10757 | parsesub: { |
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 @@ | |||
1 | a b | ||
2 | a | ||
3 | b c | ||
4 | def | ||
5 | a'b c"d e\f | ||
6 | a3b c3b e33f | ||
7 | a\80b c08b | ||
8 | a3b c30b | ||
9 | x 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 @@ | |||
1 | echo $'a\tb' | ||
2 | echo $'a\nb' $'c\nd''ef' | ||
3 | echo $'a\'b' $'c\"d' $'e\\f' | ||
4 | echo $'a\63b' $'c\063b' $'e\0633f' | ||
5 | echo $'a\80b' $'c\608b' | ||
6 | echo $'a\x33b' $'c\x330b' | ||
7 | echo $'x\x9y' | ||