diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index cf32481b68d..b49f90a7b96 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -252,10 +252,15 @@ echo %ErrorLevel% set WINE_FOO= echo ------------ Testing chains ------------ -rem brackets precede '&&', '||' and '&' -rem '&&' precedes '||' and '&' -rem '||' precedes '&' -rem 'a && b || c & d' is equivalent to '(((a && b) || c) & d)' +rem The chain operators have the following bottom-up precedence: +rem 'else' precedes nothing and matches the closest unmatched 'if' in the same bracket depth +rem '&' precedes 'else' +rem '||' precedes '&' and 'else' +rem '&&' precedes '||', '&' and 'else' +rem '|' precedes '&&', '||', '&' and 'else' +rem +rem Example: 'if 1==1 if 2==2 if 3==3 a | b && c || d & e else f else g' is interpreted as +rem 'if 1==1 (if 2==2 (if 3==3 ((((a | b) && c) || d) & e) else f) else g)' goto :cfailend :cfail echo %1 @@ -301,6 +306,8 @@ call :cfail k1||call :cfail k2&&call :cfail k3 echo --- call :cfail l1||call :cfail l2||call :cfail l3 echo --- chain brackets +rem Brackets are like regular commands, they support redirections +rem and have the same precedence as regular commands. echo a1&(echo a2&echo a3) echo b1&(echo b2&&echo b3) echo c1&(echo c2||echo c3) @@ -329,7 +336,108 @@ call :cfail p1||(call :cfail p2&call :cfail p3) call :cfail q1||(call :cfail q2&&call :cfail q3) echo --- call :cfail r1||(call :cfail r2||call :cfail r3) - +echo --- chain pipe +rem Piped commands run at the same time, so the print order varies. +rem Additionally, they don't run in the batch script context, as shown by +rem 'call :existing_label|echo read the error message'. +(echo a 1>&2|echo a 1>&2) 2>&1 +echo --- +echo b1|echo b2 +echo c1&&echo c2|echo c3 +echo d1||echo d2|echo d3 +echo --- +echo e1&echo e2|echo e3 +echo f1|echo f2&&echo f3 +echo g1|echo g2||echo g3 +echo --- +echo h1|echo h2&echo h3 +echo i1|echo i2|echo i3 +echo --- chain pipe input +rem The output data of the left side of a pipe can dissapear, probably +rem because it finished too fast and closed the pipe before it could be read, +rem which means we can get broken results for the tests of this section. +echo @echo off> tmp.cmd +echo set IN=X>> tmp.cmd +echo set /p IN=%%1:>> tmp.cmd +echo setlocal EnableDelayedExpansion>> tmp.cmd +echo echo [!IN!,%%1]>> tmp.cmd +echo endlocal>> tmp.cmd +echo set IN=>> tmp.cmd +echo a1|cmd /ctmp.cmd a2 +echo b1|cmd /ctmp.cmd b2|cmd /ctmp.cmd b3 +echo c1|cmd /ctmp.cmd c2|cmd /ctmp.cmd c3|cmd /ctmp.cmd c4 +echo d1|call tmp.cmd d2 +echo e1|call tmp.cmd e2|call tmp.cmd e3 +echo f1|call tmp.cmd f2|call tmp.cmd f3|call tmp.cmd f4 +rem FIXME these 3 tests cause "unexpected end of output" +rem test : echo g1|tmp.cmd g2 +rem result: g2:[g1,g2] +rem test : echo h1|tmp.cmd h2|tmp.cmd h3 +rem result: h3:[h2:[h1,h2],h3]@or_broken@h3:[h2:,h3] +rem test : echo i1|tmp.cmd i2|tmp.cmd i3|tmp.cmd i4 +rem result: i4:[i3:[i2:[i1,i2],i3],i4]@or_broken@i4:[i3:[i2:,i3],i4]@or_broken@i4:[i3:,i4] +del tmp.cmd +echo --- chain else +rem Command arguments are gready and eat up the 'else' unless terminated by +rem brackets, which means the 'else' can only be recognized when the +rem 'if true' command chain ends with brackets. +if 1==1 if 2==2 if 3==3 (echo a1) else (echo a2) else echo a3 +if 1==1 if 2==2 if 3==0 (echo b1) else (echo b2) else echo b3 +echo --- +if 1==1 if 2==0 if 3==3 (echo c1) else (echo c2) else echo c3 +echo --- +if 1==1 if 2==0 if 3==0 (echo d1) else (echo d2) else echo d3 +echo --- +if 1==0 if 2==2 if 3==3 (echo e1) else (echo e2) else echo e3 +echo --- +if 1==0 if 2==2 if 3==0 (echo f1) else (echo f2) else echo f3 +echo --- +if 1==0 if 2==0 if 3==3 (echo g1) else (echo g2) else echo g3 +echo --- +if 1==0 if 2==0 if 3==0 (echo h1) else (echo h2) else echo h3 +echo --- +echo --- chain else (if true) +if 1==1 echo a1 else echo a2 +if 1==1 echo b1|echo b2 else echo b3 +if 1==1 echo c1&&echo c2 else echo c3 +if 1==1 echo d1||echo d2 else echo d3 +echo --- +if 1==1 echo e1&echo e2 else echo e3 +if 1==1 echo f1 else echo f2|echo f3 +if 1==1 echo g1 else echo g2&&echo g3 +if 1==1 echo h1 else echo h2||echo h3 +echo --- +if 1==1 echo i1 else echo i2&echo i3 +if 1==1 echo j1|(echo j2) else echo j3 +echo --- +if 1==1 echo k1&&(echo k2) else echo k3 +if 1==1 echo l1||(echo l2) else echo l3 +echo --- +if 1==1 echo m1&(echo m2) else echo m3 +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 --- chain else (if false) +if 1==0 echo a1 else echo a2 +if 1==0 echo b1|echo b2 else echo b3 +if 1==0 echo c1&&echo c2 else echo c3 +if 1==0 echo d1||echo d2 else echo d3 +if 1==0 echo e1&echo e2 else echo e3 +if 1==0 echo f1 else echo f2|echo f3 +if 1==0 echo g1 else echo g2&&echo g3 +if 1==0 echo h1 else echo h2||echo h3 +if 1==0 echo i1 else echo i2&echo i3 +if 1==0 echo j1|(echo j2) else echo j3 +echo --- +if 1==0 echo k1&&(echo k2) else echo k3 +if 1==0 echo l1||(echo l2) else echo l3 +if 1==0 echo m1&(echo m2) else echo m3 +if 1==0 (echo n1) else echo n2|echo n3 +if 1==0 (echo o1) else echo o2&&echo o3 +if 1==0 (echo p1) else echo p2||echo p3 +echo --- +if 1==0 (echo q1) else echo q2&echo q3 echo ------------ Testing 'set' ------------ call :setError 0 rem Remove any WINE_FOO* WINE_BA* environment variables from shell before proceeding diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 58f6fae77f0..2df43115a89 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -363,6 +363,84 @@ q2 r1 r2 r3 +--- chain pipe +@todo_wine@a@space@ +@todo_wine@a@space@ +--- +b2 +c1 +c3 +d1 +@todo_wine@--- +e1 +e3 +f2 +f3 +g2 +@todo_wine@--- +h2 +h3 +i3 +--- chain pipe input +a2:[a1,a2] +b3:[b2:[b1,b2],b3]@or_broken@b3:[b2:,b3] +c4:[c3:[c2:[c1,c2],c3],c4]@or_broken@c4:[c3:[c2:,c3],c4]@or_broken@c4:[c3:,c4] +d2:[d1,d2] +e3:[e2:[e1,e2],e3]@or_broken@e3:[e2:,e3] +f4:[f3:[f2:[f1,f2],f3],f4]@or_broken@f4:[f3:[f2:,f3],f4]@or_broken@f4:[f3:,f4] +--- chain else +a1 +b2 +@todo_wine@--- +@todo_wine@c3 +@todo_wine@--- +@todo_wine@d3 +@todo_wine@--- +@todo_wine@--- +@todo_wine@--- +@todo_wine@--- +@todo_wine@--- +--- chain else (if true) +a1 else echo a2 +b2 else echo b3 +c1 +c2 else echo c3 +d1 +@todo_wine@--- +e1 +e2 else echo e3 +f3 +g1 else echo g2 +g3 +h1 else echo h2 +@todo_wine@--- +i1 else echo i2 +i3 +@todo_wine@j2@space@ +@todo_wine@--- +k1 +k2 +l1 +@todo_wine@--- +m1 +m2 +n1 +o1 +p1 +q1 +--- chain else (if false) +@todo_wine@j3 +--- +k3 +l3 +m3 +n3 +o2 +o3 +p2 +@todo_wine@--- +q2 +q3 ------------ Testing 'set' ------------ 1 0