diff options
author | Ron Yorston <rmy@pobox.com> | 2023-02-07 10:03:04 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-02-07 10:03:04 +0000 |
commit | 4b894b60ae377ee2a04ae209c14bb1e714ecf6f4 (patch) | |
tree | 8f42f36eb0a9dad2c712f7b0e07aff7dee059217 /shell | |
parent | c49b8b7052bb1df3ed5f9aeba61a7965d9c77f83 (diff) | |
download | busybox-w32-4b894b60ae377ee2a04ae209c14bb1e714ecf6f4.tar.gz busybox-w32-4b894b60ae377ee2a04ae209c14bb1e714ecf6f4.tar.bz2 busybox-w32-4b894b60ae377ee2a04ae209c14bb1e714ecf6f4.zip |
ash: change CRLF handling
As noted in commit 2d848eba5 (ash: fix CRLF handling) all CRs are
removed when scripts are read. Allow an alternative approach
(configurable at build-time, enabled by default):
- Do not strip CRs from input.
- Treat CR as similar to space or tab in base syntax mode.
- Adjust pgetc_eatbnl() to handle backslash-CRLF in the same way
as backslash-LF.
With these changes scripts containing CRLF line endings are more
likely to work.
Adds 48-56 bytes.
(GitHub issue #285)
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/shell/ash.c b/shell/ash.c index a24ed0ac8..63eb4947c 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -192,6 +192,14 @@ | |||
192 | //config: Enable support for the 'nocaseglob' option, which allows | 192 | //config: Enable support for the 'nocaseglob' option, which allows |
193 | //config: case-insensitive filename globbing. | 193 | //config: case-insensitive filename globbing. |
194 | //config: | 194 | //config: |
195 | //config:config ASH_IGNORE_CR | ||
196 | //config: bool "Ignore CR in scripts" | ||
197 | //config: default y | ||
198 | //config: depends on (ASH || SH_IS_ASH || BASH_IS_ASH) && PLATFORM_MINGW32 | ||
199 | //config: help | ||
200 | //config: Allow CRs to be ignored when shell scripts are parsed. This | ||
201 | //config: makes it possible to run scripts with CRLF line endings. | ||
202 | //config: | ||
195 | //config:endif # ash options | 203 | //config:endif # ash options |
196 | 204 | ||
197 | //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) | 205 | //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) |
@@ -762,7 +770,11 @@ struct strpush { | |||
762 | struct strpush *spfree; | 770 | struct strpush *spfree; |
763 | 771 | ||
764 | /* Remember last two characters for pungetc. */ | 772 | /* Remember last two characters for pungetc. */ |
773 | #if ENABLE_ASH_IGNORE_CR | ||
774 | int lastc[3]; /* Ignoring CRs needs more pungetc. */ | ||
775 | #else | ||
765 | int lastc[2]; | 776 | int lastc[2]; |
777 | #endif | ||
766 | 778 | ||
767 | /* Number of outstanding calls to pungetc. */ | 779 | /* Number of outstanding calls to pungetc. */ |
768 | int unget; | 780 | int unget; |
@@ -787,7 +799,11 @@ struct parsefile { | |||
787 | struct strpush *spfree; | 799 | struct strpush *spfree; |
788 | 800 | ||
789 | /* Remember last two characters for pungetc. */ | 801 | /* Remember last two characters for pungetc. */ |
802 | #if ENABLE_ASH_IGNORE_CR | ||
803 | int lastc[3]; /* Ignoring CRs needs more pungetc. */ | ||
804 | #else | ||
790 | int lastc[2]; | 805 | int lastc[2]; |
806 | #endif | ||
791 | 807 | ||
792 | /* Number of outstanding calls to pungetc. */ | 808 | /* Number of outstanding calls to pungetc. */ |
793 | int unget; | 809 | int unget; |
@@ -3596,7 +3612,11 @@ static const uint8_t syntax_index_table[] ALIGN1 = { | |||
3596 | /* 10 "\n" */ CNL_CNL_CNL_CNL, | 3612 | /* 10 "\n" */ CNL_CNL_CNL_CNL, |
3597 | /* 11 */ CWORD_CWORD_CWORD_CWORD, | 3613 | /* 11 */ CWORD_CWORD_CWORD_CWORD, |
3598 | /* 12 */ CWORD_CWORD_CWORD_CWORD, | 3614 | /* 12 */ CWORD_CWORD_CWORD_CWORD, |
3615 | #if ENABLE_ASH_IGNORE_CR | ||
3616 | /* 13 */ CSPCL_CWORD_CWORD_CWORD, | ||
3617 | #else | ||
3599 | /* 13 */ CWORD_CWORD_CWORD_CWORD, | 3618 | /* 13 */ CWORD_CWORD_CWORD_CWORD, |
3619 | #endif | ||
3600 | /* 14 */ CWORD_CWORD_CWORD_CWORD, | 3620 | /* 14 */ CWORD_CWORD_CWORD_CWORD, |
3601 | /* 15 */ CWORD_CWORD_CWORD_CWORD, | 3621 | /* 15 */ CWORD_CWORD_CWORD_CWORD, |
3602 | /* 16 */ CWORD_CWORD_CWORD_CWORD, | 3622 | /* 16 */ CWORD_CWORD_CWORD_CWORD, |
@@ -11846,7 +11866,9 @@ preadbuffer(void) | |||
11846 | more--; | 11866 | more--; |
11847 | 11867 | ||
11848 | c = *q; | 11868 | c = *q; |
11849 | if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) { | 11869 | /* Remove CR from input buffer as an alternative to ASH_IGNORE_CR. */ |
11870 | if (c == '\0' || (c == '\r' && | ||
11871 | ENABLE_PLATFORM_MINGW32 && !ENABLE_ASH_IGNORE_CR)) { | ||
11850 | memmove(q, q + 1, more); | 11872 | memmove(q, q + 1, more); |
11851 | } else { | 11873 | } else { |
11852 | q++; | 11874 | q++; |
@@ -11934,6 +11956,9 @@ static int __pgetc(void) | |||
11934 | else | 11956 | else |
11935 | c = preadbuffer(); | 11957 | c = preadbuffer(); |
11936 | 11958 | ||
11959 | #if ENABLE_ASH_IGNORE_CR | ||
11960 | g_parsefile->lastc[2] = g_parsefile->lastc[1]; | ||
11961 | #endif | ||
11937 | g_parsefile->lastc[1] = g_parsefile->lastc[0]; | 11962 | g_parsefile->lastc[1] = g_parsefile->lastc[0]; |
11938 | g_parsefile->lastc[0] = c; | 11963 | g_parsefile->lastc[0] = c; |
11939 | 11964 | ||
@@ -11971,11 +11996,24 @@ pgetc_eatbnl(void) | |||
11971 | int c; | 11996 | int c; |
11972 | 11997 | ||
11973 | while ((c = pgetc()) == '\\') { | 11998 | while ((c = pgetc()) == '\\') { |
11999 | #if !ENABLE_ASH_IGNORE_CR | ||
11974 | if (pgetc() != '\n') { | 12000 | if (pgetc() != '\n') { |
11975 | pungetc(); | 12001 | pungetc(); |
11976 | break; | 12002 | break; |
11977 | } | 12003 | } |
11978 | 12004 | #else | |
12005 | int c2 = pgetc(); | ||
12006 | if (c2 == '\r') { | ||
12007 | if (pgetc() == '\n') | ||
12008 | goto eatbnl; | ||
12009 | pungetc(); | ||
12010 | } | ||
12011 | if (c2 != '\n') { | ||
12012 | pungetc(); | ||
12013 | break; | ||
12014 | } | ||
12015 | eatbnl: | ||
12016 | #endif | ||
11979 | nlprompt(); | 12017 | nlprompt(); |
11980 | } | 12018 | } |
11981 | 12019 | ||
@@ -14114,7 +14152,7 @@ xxreadtoken(void) | |||
14114 | setprompt_if(needprompt, 2); | 14152 | setprompt_if(needprompt, 2); |
14115 | for (;;) { /* until token or start of word found */ | 14153 | for (;;) { /* until token or start of word found */ |
14116 | c = pgetc_eatbnl(); | 14154 | c = pgetc_eatbnl(); |
14117 | if (c == ' ' || c == '\t') | 14155 | if (c == ' ' || c == '\t' || (ENABLE_ASH_IGNORE_CR && c == '\r')) |
14118 | continue; | 14156 | continue; |
14119 | 14157 | ||
14120 | if (c == '#') { | 14158 | if (c == '#') { |