From 6cb520476a79fd7ff5a67c1a1064de9c267fdbc1 Mon Sep 17 00:00:00 2001 From: Jason Edmeades Date: Sun, 15 Jul 2018 23:15:29 +0100 Subject: [PATCH] cmd: Fix statements after 'else' inside for loops. When inside a for loop, an 'if' statement is processed and the true part taken. Once all the commands in the true are processed, the else part is parsed, and a flag set to skip all commands in the else part. Unfortunately this flag is left on even when the if statement ends, meaning subsequent commands are also skipped. Signed-off-by: Jason Edmeades Signed-off-by: Alexandre Julliard --- programs/cmd/builtins.c | 18 +++++++++++-- programs/cmd/tests/test_builtins.cmd | 34 ++++++++++++++++++++++++ programs/cmd/tests/test_builtins.cmd.exp | 14 ++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 1ee4fcccf3d..088632f214e 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -1571,10 +1571,12 @@ static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd, /* execute all appropriate commands */ curPosition = *cmdList; - WINE_TRACE("Processing cmdList(%p) - delim(%d) bd(%d / %d)\n", + WINE_TRACE("Processing cmdList(%p) - delim(%d) bd(%d / %d) processThese(%d)\n", *cmdList, (*cmdList)->prevDelim, - (*cmdList)->bracketDepth, myDepth); + (*cmdList)->bracketDepth, + myDepth, + processThese); /* Execute any statements appended to the line */ /* FIXME: Only if previous call worked for && or failed for || */ @@ -1613,6 +1615,18 @@ static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd, if (*cmd) { WCMD_execute (cmd, (*cmdList)->redirects, cmdList, FALSE); } + } else { + /* Loop skipping all commands until we get back to the current + depth, including skipping commands and their subsequent + pipes (eg cmd | prog) */ + do { + *cmdList = (*cmdList)->nextcommand; + } while (*cmdList && + ((*cmdList)->bracketDepth > myDepth || + (*cmdList)->prevDelim)); + + /* After the else is complete, we need to now process subsequent commands */ + processThese = TRUE; } if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand; } else if (!processThese) { diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index 5ca2427a8f8..b9e9b259a9c 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -418,6 +418,7 @@ if 1==1 (echo n1) else echo n2|echo n3 if 1==1 (echo o1) else echo o2&&echo o3 if 1==1 (echo p1) else echo p2||echo p3 if 1==1 (echo q1) else echo q2&echo q3 +echo --- echo --- chain else (if false) if 1==0 echo a1 else echo a2 if 1==0 echo b1|echo b2 else echo b3 @@ -1371,6 +1372,39 @@ for /L %%i in (2,2,1) do ( echo %%i echo FAILED ) +echo --- ifs inside for loops +for %%i in (test) do ( + echo a1 + if 1==1 ( + echo b1 + ) else ( + echo c1 + ) + echo d1 +) +for %%i in (test) do ( + echo a2 + if 1==1 ( + echo b2 + ) else echo c2 + echo d2 +) +for %%i in (test) do ( + echo a3 + if 1==0 ( + echo b3 + ) else echo c3 + echo d3 +) +for %%i in (test) do ( + echo a4 + if 1==0 ( + echo b4 + ) else ( + echo c4 + ) + echo d4 +) echo --- set /a goto :testseta diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 0a7c75a2a26..31183592654 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -428,6 +428,7 @@ n1 o1 p1 q1 +@todo_wine@--- --- chain else (if false) @todo_wine@j3 --- @@ -982,6 +983,19 @@ ErrorLevel 0 -1 1 3 +--- ifs inside for loops +a1 +b1 +d1 +a2 +b2 +d2 +a3 +c3 +d3 +a4 +c4 +d4 --- set /a ------ individual operations WINE_foo correctly 3