aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-08-14 12:03:24 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-08-14 12:03:24 +0200
commitcad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8 (patch)
tree07a542ea9ee47b56f69122ed66dea7ed8e6c1925 /shell
parent4343ca9aa879cabc52ff82c0a46d3ba20d7fec5c (diff)
downloadbusybox-w32-cad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8.tar.gz
busybox-w32-cad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8.tar.bz2
busybox-w32-cad5a79bd4e8ceef4a68f1551fd2b25122bcb1c8.zip
hush: explain "empty quoted str marker" trick
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/shell/hush.c b/shell/hush.c
index d65da3b98..002140b1a 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -5656,15 +5656,20 @@ static struct pipe *parse_stream(char **pstring,
5656 nommu_addchr(&ctx.as_string, ch); 5656 nommu_addchr(&ctx.as_string, ch);
5657 if (ch == '\'') { 5657 if (ch == '\'') {
5658 ctx.word.has_quoted_part = 1; 5658 ctx.word.has_quoted_part = 1;
5659 next = i_getch(input); 5659 ch = i_getch(input);
5660 if (next == '\'' && !ctx.pending_redirect/*why?*/) { 5660 if (ch == '\'' && !ctx.pending_redirect/*why?*/) {
5661 insert_empty_quoted_str_marker: 5661 insert_empty_quoted_str_marker:
5662 nommu_addchr(&ctx.as_string, next); 5662 nommu_addchr(&ctx.as_string, ch);
5663//Just inserting nothing doesn't work: consider
5664// CMD $EMPTYVAR
5665// CMD ''
5666//At execution time both will expand argv[1] to empty string
5667//and thus the argument will "vanish".
5668//But for second CMD, it should not vanish!
5663 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); 5669 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5664 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); 5670 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5665 continue; /* get next char */ 5671 continue; /* get next char */
5666 } 5672 }
5667 ch = next;
5668 while (1) { 5673 while (1) {
5669 if (ch == EOF) { 5674 if (ch == EOF) {
5670 syntax_error_unterm_ch('\''); 5675 syntax_error_unterm_ch('\'');
@@ -5789,6 +5794,7 @@ static struct pipe *parse_stream(char **pstring,
5789 if ((ctx.is_assignment == MAYBE_ASSIGNMENT 5794 if ((ctx.is_assignment == MAYBE_ASSIGNMENT
5790 || ctx.is_assignment == WORD_IS_KEYWORD) 5795 || ctx.is_assignment == WORD_IS_KEYWORD)
5791 && ch == '=' 5796 && ch == '='
5797 // && !ctx.word.has_quoted_part // unnecessary, "empty quoted str marker" trick handles this too
5792 && endofname(ctx.word.data)[0] == '=' 5798 && endofname(ctx.word.data)[0] == '='
5793 ) { 5799 ) {
5794 ctx.is_assignment = DEFINITELY_ASSIGNMENT; 5800 ctx.is_assignment = DEFINITELY_ASSIGNMENT;
@@ -5983,7 +5989,7 @@ static struct pipe *parse_stream(char **pstring,
5983 case '"': 5989 case '"':
5984 ctx.word.has_quoted_part = 1; 5990 ctx.word.has_quoted_part = 1;
5985 if (next == '"' && !ctx.pending_redirect) { 5991 if (next == '"' && !ctx.pending_redirect) {
5986 i_getch(input); /* eat second " */ 5992 ch = i_getch(input); /* eat second " */
5987 goto insert_empty_quoted_str_marker; 5993 goto insert_empty_quoted_str_marker;
5988 } 5994 }
5989 if (ctx.is_assignment == NOT_ASSIGNMENT) 5995 if (ctx.is_assignment == NOT_ASSIGNMENT)