hush: simplify \<newline> code, part 3

function                                             old     new   delta
parse_stream                                        2780    2762     -18

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-04-10 14:20:48 +02:00
parent e8b1bc0481
commit 92a930b4e8

View File

@ -5052,19 +5052,43 @@ static struct pipe *parse_stream(char **pstring,
} }
nommu_addchr(&ctx.as_string, ch); nommu_addchr(&ctx.as_string, ch);
next = '\0'; if (ch == '\'') {
if (ch != '\n') { ctx.word.has_quoted_part = 1;
/* Do not break this case: next = i_getch(input);
* echo '\ if (next == '\'' && !ctx.pending_redirect)
* ' goto insert_empty_quoted_str_marker;
* and
* echo z\\ ch = next;
*/ while (1) {
next = (ch == '\'' || ch == '\\') ? i_peek(input) : i_peek_and_eat_bkslash_nl(input); if (ch == EOF) {
/// syntax_error_unterm_ch('\'');
goto parse_error;
}
nommu_addchr(&ctx.as_string, ch);
if (ch == '\'')
break;
if (ch == SPECIAL_VAR_SYMBOL) {
/* Convert raw ^C to corresponding special variable reference */
o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
}
o_addqchr(&ctx.word, ch);
ch = i_getch(input);
}
continue; /* get next char */
} }
is_special = "{}<>;&|()#'" /* special outside of "str" */ next = '\0';
if (ch != '\n' && ch != '\\') {
/* Not on '\': do not break the case of "echo z\\":
* on 2nd '\', i_peek_and_eat_bkslash_nl()
* would stop and try to read next line,
* not letting the command to execute.
*/
next = i_peek_and_eat_bkslash_nl(input);
}
is_special = "{}<>;&|()#" /* special outside of "str" */
"\\$\"" IF_HUSH_TICK("`") /* always special */ "\\$\"" IF_HUSH_TICK("`") /* always special */
SPECIAL_VAR_SYMBOL_STR; SPECIAL_VAR_SYMBOL_STR;
/* Are { and } special here? */ /* Are { and } special here? */
@ -5252,7 +5276,7 @@ static struct pipe *parse_stream(char **pstring,
return ctx.list_head; return ctx.list_head;
} }
} }
skip_end_trigger:
if (is_blank) if (is_blank)
continue; continue;
@ -5278,7 +5302,7 @@ static struct pipe *parse_stream(char **pstring,
#endif #endif
if (parse_redirect(&ctx, redir_fd, redir_style, input)) if (parse_redirect(&ctx, redir_fd, redir_style, input))
goto parse_error; goto parse_error;
continue; /* back to top of while (1) */ continue; /* get next char */
case '<': case '<':
redir_fd = redirect_opt_num(&ctx.word); redir_fd = redirect_opt_num(&ctx.word);
if (done_word(&ctx)) { if (done_word(&ctx)) {
@ -5304,7 +5328,7 @@ static struct pipe *parse_stream(char **pstring,
#endif #endif
if (parse_redirect(&ctx, redir_fd, redir_style, input)) if (parse_redirect(&ctx, redir_fd, redir_style, input))
goto parse_error; goto parse_error;
continue; /* back to top of while (1) */ continue; /* get next char */
case '#': case '#':
if (ctx.word.length == 0 && !ctx.word.has_quoted_part) { if (ctx.word.length == 0 && !ctx.word.has_quoted_part) {
/* skip "#comment" */ /* skip "#comment" */
@ -5325,23 +5349,11 @@ static struct pipe *parse_stream(char **pstring,
if (ch == EOF) if (ch == EOF)
break; break;
} }
continue; /* back to top of while (1) */ continue; /* get next char */
} }
break; break;
#if 0 /* looks like we never reach this code */
case '\\':
if (next == '\n') {
/* It's "\<newline>" */
#if !BB_MMU
/* Remove trailing '\' from ctx.as_string */
ctx.as_string.data[--ctx.as_string.length] = '\0';
#endif
ch = i_getch(input); /* eat it */
continue; /* back to top of while (1) */
}
break;
#endif
} }
skip_end_trigger:
if (ctx.is_assignment == MAYBE_ASSIGNMENT if (ctx.is_assignment == MAYBE_ASSIGNMENT
/* check that we are not in word in "a=1 2>word b=1": */ /* check that we are not in word in "a=1 2>word b=1": */
@ -5366,20 +5378,19 @@ static struct pipe *parse_stream(char **pstring,
o_addchr(&ctx.word, ch); o_addchr(&ctx.word, ch);
continue; /* get next char */ continue; /* get next char */
case '\\': case '\\':
if (next == EOF) { /*nommu_addchr(&ctx.as_string, '\\'); - already done */
o_addchr(&ctx.word, '\\');
ch = i_getch(input);
if (ch == EOF) {
//TODO: in ". FILE" containing "cmd\" (no newline) bash ignores last "\" //TODO: in ". FILE" containing "cmd\" (no newline) bash ignores last "\"
syntax_error("\\<eof>"); syntax_error("\\<eof>");
xfunc_die(); xfunc_die();
} }
ch = i_getch(input);
/* note: ch != '\n' (that case does not reach this place) */
o_addchr(&ctx.word, '\\');
/*nommu_addchr(&ctx.as_string, '\\'); - already done */
o_addchr(&ctx.word, ch);
nommu_addchr(&ctx.as_string, ch);
/* Example: echo Hello \2>file /* Example: echo Hello \2>file
* we need to know that word 2 is quoted */ * we need to know that word 2 is quoted */
ctx.word.has_quoted_part = 1; ctx.word.has_quoted_part = 1;
nommu_addchr(&ctx.as_string, ch);
o_addchr(&ctx.word, ch);
continue; /* get next char */ continue; /* get next char */
case '$': case '$':
if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) {
@ -5388,33 +5399,12 @@ static struct pipe *parse_stream(char **pstring,
goto parse_error; goto parse_error;
} }
continue; /* get next char */ continue; /* get next char */
case '\'':
ctx.word.has_quoted_part = 1;
if (next == '\'' && !ctx.pending_redirect)
goto insert_empty_quoted_str_marker;
while (1) {
ch = i_getch(input);
if (ch == EOF) {
syntax_error_unterm_ch('\'');
goto parse_error;
}
nommu_addchr(&ctx.as_string, ch);
if (ch == '\'')
break;
if (ch == SPECIAL_VAR_SYMBOL) {
/* Convert raw ^C to corresponding special variable reference */
o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
}
o_addqchr(&ctx.word, ch);
}
continue; /* get next char */
case '"': case '"':
ctx.word.has_quoted_part = 1; ctx.word.has_quoted_part = 1;
if (next == '"' && !ctx.pending_redirect) { if (next == '"' && !ctx.pending_redirect) {
i_getch(input); /* eat second " */
insert_empty_quoted_str_marker: insert_empty_quoted_str_marker:
nommu_addchr(&ctx.as_string, next); nommu_addchr(&ctx.as_string, next);
i_getch(input); /* eat second ' */
o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL); o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
continue; /* get next char */ continue; /* get next char */