hush: fix and_or_and_backgrounding.tests failure
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 15 Jul 2017 20:51:55 +0000 (22:51 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 15 Jul 2017 20:51:55 +0000 (22:51 +0200)
function                                             old     new   delta
done_pipe                                            133     218     +85

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash_test/ash-parsing/and_or_and_backgrounding.right [new file with mode: 0644]
shell/ash_test/ash-parsing/and_or_and_backgrounding.tests [new file with mode: 0755]
shell/hush.c
shell/hush_test/hush-bugs/and_or_and_backgrounding.right [deleted file]
shell/hush_test/hush-bugs/and_or_and_backgrounding.tests [deleted file]
shell/hush_test/hush-parsing/and_or_and_backgrounding.right [new file with mode: 0644]
shell/hush_test/hush-parsing/and_or_and_backgrounding.tests [new file with mode: 0755]

diff --git a/shell/ash_test/ash-parsing/and_or_and_backgrounding.right b/shell/ash_test/ash-parsing/and_or_and_backgrounding.right
new file mode 100644 (file)
index 0000000..90ce63e
--- /dev/null
@@ -0,0 +1,4 @@
+First
+Second
+Third
+Done
diff --git a/shell/ash_test/ash-parsing/and_or_and_backgrounding.tests b/shell/ash_test/ash-parsing/and_or_and_backgrounding.tests
new file mode 100755 (executable)
index 0000000..05acfb8
--- /dev/null
@@ -0,0 +1,31 @@
+# UNFIXED BUG: hush thinks that ; && || & have the same precedence.
+# According to this doc, && || have higher precedence than ; &.
+# See example below.
+# Precedence of ; is not a problem in practice. Precedence of & is.
+#
+#http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
+#
+#2.9.3 Lists
+#
+#An AND-OR list is a sequence of one or more pipelines separated by
+#the operators "&&" and "||" .
+#
+#A list is a sequence of one or more AND-OR lists separated by the operators
+#';' and '&' and optionally terminated by ';', '&', or <newline>.
+#
+#The operators "&&" and "||" shall have equal precedence and shall be
+#evaluated with left associativity. For example, both of the following
+#commands write solely bar to standard output:
+#
+#    false && echo foo || echo bar
+#    true || echo foo && echo bar
+#
+#A ';' or <newline> terminator shall cause the preceding AND-OR list
+#to be executed sequentially; an '&' shall cause asynchronous execution
+#of the preceding AND-OR list.
+
+echo First && sleep 0.2 && echo Third &
+sleep 0.1
+echo Second
+wait
+echo Done
index b76351fdef9be4ee444b99ddc578c1b2b8e4bf7a..2a734f3de8b31689a3e2eff473d5e6420ffd289a 100644 (file)
@@ -3373,12 +3373,47 @@ static void done_pipe(struct parse_context *ctx, pipe_style type)
        debug_printf_parse("done_pipe entered, followup %d\n", type);
        /* Close previous command */
        not_null = done_command(ctx);
-       ctx->pipe->followup = type;
 #if HAS_KEYWORDS
        ctx->pipe->pi_inverted = ctx->ctx_inverted;
        ctx->ctx_inverted = 0;
        ctx->pipe->res_word = ctx->ctx_res_w;
 #endif
+       if (type != PIPE_BG || ctx->list_head == ctx->pipe) {
+ no_conv:
+               ctx->pipe->followup = type;
+       } else {
+               /* Necessary since && and || have more precedence than &:
+                * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2,
+                * in a backgrounded subshell.
+                */
+               struct pipe *pi;
+               struct command *command;
+
+               /* Is this actually the case? */
+               pi = ctx->list_head;
+               while (pi != ctx->pipe) {
+                       if (pi->followup != PIPE_AND && pi->followup != PIPE_OR)
+                               goto no_conv;
+                       pi = pi->next;
+               }
+
+               debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n");
+               pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */
+               pi = xzalloc(sizeof(*pi));
+               pi->followup = PIPE_BG;
+               pi->num_cmds = 1;
+               pi->cmds = xzalloc(sizeof(pi->cmds[0]));
+               command = &pi->cmds[0];
+               if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */
+                       command->cmd_type = CMD_NORMAL;
+               command->group = ctx->list_head;
+#if !BB_MMU
+//TODO: is this correct?!
+               command->group_as_string = xstrdup(ctx->as_string.data);
+#endif
+               /* Replace all pipes in ctx with one newly created */
+               ctx->list_head = ctx->pipe = pi;
+       }
 
        /* Without this check, even just <enter> on command line generates
         * tree of three NOPs (!). Which is harmless but annoying.
diff --git a/shell/hush_test/hush-bugs/and_or_and_backgrounding.right b/shell/hush_test/hush-bugs/and_or_and_backgrounding.right
deleted file mode 100644 (file)
index 90ce63e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-First
-Second
-Third
-Done
diff --git a/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests b/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests
deleted file mode 100755 (executable)
index 05acfb8..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# UNFIXED BUG: hush thinks that ; && || & have the same precedence.
-# According to this doc, && || have higher precedence than ; &.
-# See example below.
-# Precedence of ; is not a problem in practice. Precedence of & is.
-#
-#http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
-#
-#2.9.3 Lists
-#
-#An AND-OR list is a sequence of one or more pipelines separated by
-#the operators "&&" and "||" .
-#
-#A list is a sequence of one or more AND-OR lists separated by the operators
-#';' and '&' and optionally terminated by ';', '&', or <newline>.
-#
-#The operators "&&" and "||" shall have equal precedence and shall be
-#evaluated with left associativity. For example, both of the following
-#commands write solely bar to standard output:
-#
-#    false && echo foo || echo bar
-#    true || echo foo && echo bar
-#
-#A ';' or <newline> terminator shall cause the preceding AND-OR list
-#to be executed sequentially; an '&' shall cause asynchronous execution
-#of the preceding AND-OR list.
-
-echo First && sleep 0.2 && echo Third &
-sleep 0.1
-echo Second
-wait
-echo Done
diff --git a/shell/hush_test/hush-parsing/and_or_and_backgrounding.right b/shell/hush_test/hush-parsing/and_or_and_backgrounding.right
new file mode 100644 (file)
index 0000000..90ce63e
--- /dev/null
@@ -0,0 +1,4 @@
+First
+Second
+Third
+Done
diff --git a/shell/hush_test/hush-parsing/and_or_and_backgrounding.tests b/shell/hush_test/hush-parsing/and_or_and_backgrounding.tests
new file mode 100755 (executable)
index 0000000..05acfb8
--- /dev/null
@@ -0,0 +1,31 @@
+# UNFIXED BUG: hush thinks that ; && || & have the same precedence.
+# According to this doc, && || have higher precedence than ; &.
+# See example below.
+# Precedence of ; is not a problem in practice. Precedence of & is.
+#
+#http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
+#
+#2.9.3 Lists
+#
+#An AND-OR list is a sequence of one or more pipelines separated by
+#the operators "&&" and "||" .
+#
+#A list is a sequence of one or more AND-OR lists separated by the operators
+#';' and '&' and optionally terminated by ';', '&', or <newline>.
+#
+#The operators "&&" and "||" shall have equal precedence and shall be
+#evaluated with left associativity. For example, both of the following
+#commands write solely bar to standard output:
+#
+#    false && echo foo || echo bar
+#    true || echo foo && echo bar
+#
+#A ';' or <newline> terminator shall cause the preceding AND-OR list
+#to be executed sequentially; an '&' shall cause asynchronous execution
+#of the preceding AND-OR list.
+
+echo First && sleep 0.2 && echo Third &
+sleep 0.1
+echo Second
+wait
+echo Done