summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c125
1 files changed, 58 insertions, 67 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 2155dda8e..6a6c1c5a0 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -5601,7 +5601,6 @@ static struct pipe *parse_stream(char **pstring,
heredoc_cnt = 0;
while (1) {
- int is_blank;
int ch;
int next;
int redir_fd;
@@ -5680,16 +5679,7 @@ static struct pipe *parse_stream(char **pstring,
continue; /* get next char */
}
- next = '\0';
- is_blank = 1;
- /* If '\n', must not peek (peeking past '\n' provokes line editing) */
- if (ch == '\n')
- /* had to test for '\n' anyway, can also jump directly to newline handling */
- goto ch_is_newline;
- next = i_peek_and_eat_bkslash_nl(input);
-
- is_blank = (ch == ' ' || ch == '\t');
- if (is_blank) {
+ if (ch == ' ' || ch == '\t') {
#if ENABLE_HUSH_LINENO_VAR
/* "while ...; do<whitespace><newline>
* CMD"
@@ -5698,67 +5688,73 @@ static struct pipe *parse_stream(char **pstring,
* Need to skip whitespace up to next newline (and eat it)
* or not-whitespace (and do not eat it).
*/
- do {
+ for (;;) {
next = i_peek(input);
if (next != ' ' && next != '\t' && next != '\n')
break; /* next char is not ws */
ch = i_getch(input);
- } while (ch != '\n');
+ if (ch == '\n')
+ goto ch_is_newline;
+ }
#endif
- ch_is_newline:
if (done_word(&ctx))
goto parse_error_exitcode1;
- if (ch == '\n') {
- /* Is this a case when newline is simply ignored?
- * Some examples:
- * "CMD | <newline> CMD ..."
- * "case ... in <newline> PATTERN) ..."
+ continue; /* get next char */
+ }
+
+ if (ch == '\n') {
+ IF_HUSH_LINENO_VAR(ch_is_newline:)
+ if (done_word(&ctx))
+ goto parse_error_exitcode1;
+ /* Is this a case when newline is simply ignored?
+ * Some examples:
+ * "CMD | <newline> CMD ..."
+ * "case ... in <newline> PATTERN) ..."
+ */
+ if (IS_NULL_CMD(ctx.command)
+ && IS_NULL_WORD(ctx.word)
+ && heredoc_cnt == 0
+ ) {
+ /* This newline can be ignored. But...
+ * Without check #1, interactive shell
+ * ignores even bare <newline>,
+ * and shows the continuation prompt:
+ * ps1$ <enter>
+ * ps2> _ <=== wrong, should be ps1
+ * Without check #2, "CMD & <newline>"
+ * is similarly mistreated.
+ * (BTW, this makes "CMD & CMD"
+ * and "CMD && CMD" non-orthogonal.
+ * Really, ask yourself, why
+ * "CMD && <newline>" doesn't start
+ * CMD but waits for more input?
+ * The only reason is that it might be
+ * a "CMD1 && <nl> CMD2 &" construct:
+ * CMD1 may need to run in BG).
*/
- if (IS_NULL_CMD(ctx.command)
- && IS_NULL_WORD(ctx.word)
- && heredoc_cnt == 0
+ pi = ctx.list_head;
+ if (pi->num_cmds != 0 /* check #1 */
+ && pi->followup != PIPE_BG /* check #2 */
) {
- /* This newline can be ignored. But...
- * Without check #1, interactive shell
- * ignores even bare <newline>,
- * and shows the continuation prompt:
- * ps1$ <enter>
- * ps2> _ <=== wrong, should be ps1
- * Without check #2, "CMD & <newline>"
- * is similarly mistreated.
- * (BTW, this makes "CMD & CMD"
- * and "CMD && CMD" non-orthogonal.
- * Really, ask yourself, why
- * "CMD && <newline>" doesn't start
- * CMD but waits for more input?
- * The only reason is that it might be
- * a "CMD1 && <nl> CMD2 &" construct:
- * CMD1 may need to run in BG).
- */
- pi = ctx.list_head;
- if (pi->num_cmds != 0 /* check #1 */
- && pi->followup != PIPE_BG /* check #2 */
- ) {
- continue; /* ignore newline */
- }
+ continue; /* ignore newline */
}
- /* Treat newline as a command separator */
- done_pipe(&ctx, PIPE_SEQ);
- debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt);
- if (heredoc_cnt) {
- heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input);
- if (heredoc_cnt != 0)
- goto parse_error_exitcode1;
- }
- ctx.is_assignment = MAYBE_ASSIGNMENT;
- debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
- ch = ';';
- /* note: if (is_blank) continue;
- * will still trigger for us */
- } /* if ch == '\n */
+ }
+ /* Treat newline as a command separator */
+ done_pipe(&ctx, PIPE_SEQ);
+ debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt);
+ if (heredoc_cnt) {
+ heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input);
+ if (heredoc_cnt != 0)
+ goto parse_error_exitcode1;
+ }
+ ctx.is_assignment = MAYBE_ASSIGNMENT;
+ debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
+ next = '\0';
+ ch = ';';
} else {
const char *is_special;
+ next = i_peek_and_eat_bkslash_nl(input);
is_special = "{}<>&|();#" /* special outside of "str" */
"$\"" IF_HUSH_TICK("`") /* always special */
SPECIAL_VAR_SYMBOL_STR;
@@ -5782,8 +5778,7 @@ static struct pipe *parse_stream(char **pstring,
/* They are not special, skip "{}" */
is_special += 2;
}
- is_special = strchr(is_special, ch);
- if (!is_special) { /* ordinary char */
+ if (!strchr(is_special, ch)) { /* ordinary char? */
ordinary_char:
o_addQchr(&ctx.word, ch);
if ((ctx.is_assignment == MAYBE_ASSIGNMENT
@@ -5794,7 +5789,7 @@ static struct pipe *parse_stream(char **pstring,
ctx.is_assignment = DEFINITELY_ASSIGNMENT;
debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
}
- continue;
+ continue; /* get next char */
}
}
@@ -5874,9 +5869,6 @@ static struct pipe *parse_stream(char **pstring,
}
}
- if (is_blank) /* space, tab or newline? */
- continue;
-
/* Catch <, > before deciding whether this word is
* an assignment. a=1 2>z b=2: b=2 is still assignment */
switch (ch) {
@@ -6022,8 +6014,7 @@ static struct pipe *parse_stream(char **pstring,
done_pipe(&ctx, PIPE_SEQ);
#if ENABLE_HUSH_CASE
if (ctx.ctx_res_w == RES_CASE_BODY
- && !is_blank /* is it really actual semicolon? */
- && i_peek_and_eat_bkslash_nl(input) == ';' /* and next char is ';' too? */
+ && next == ';' /* and next char is ';' too? */
) {
ch = i_getch(input);
nommu_addchr(&ctx.as_string, ch);