1echo Tests for cmd's builtin commands
2
3@echo on
4echo ------------ Testing 'echo' [ON] ------------
5echo word
6echo 'singlequotedword'
7echo "doublequotedword"
8@echo at-echoed-word
9echo "/?"
10echo.
11echo .
12echo.word
13echo .word
14echo:
15echo :
16echo:word
17echo :word
18echo/
19echo /
20echo/word
21echo /word
22echo off now
23echo word@space@
24echo word@space@@space@
25 echo word
26echo@tab@word
27echo@tab@word @tab@
28echo@tab@word@tab@@space@
29@tab@echo word
30echo @tab@word
31echo  @tab@word
32echo@tab@@tab@word
33echo @tab@ on @space@
34@echo --- @ with chains and brackets
35(echo the @ character chains until&&@echo we leave the current depth||(
36echo hidden
37@echo hidden
38))&&echo and can hide brackets||(@echo command hidden)||@(echo brackets hidden)
39@echo ---
40
41@echo off
42echo off@tab@@space@
43@echo noecho1
44 @echo noecho2
45@@@@@echo echo3
46echo ------------ Testing 'echo' [OFF] ------------
47echo word
48echo 'singlequotedword'
49echo "doublequotedword"
50@echo at-echoed-word
51echo "/?"
52echo.
53echo .
54echo.word
55echo .word
56echo:
57echo :
58echo:word
59echo :word
60echo/
61echo /
62echo/word
63echo /word
64echo on again
65echo word@space@
66echo word@space@@space@
67 echo word
68echo@tab@word
69echo@tab@word @tab@
70echo@tab@word@tab@@space@
71@tab@echo word
72echo @tab@word
73echo  @tab@word
74echo@tab@@tab@word
75
76echo ------------ Testing mixed echo modes ------------
77echo @echo on> mixedEchoModes.cmd
78echo if 1==1 echo foo>> mixedEchoModes.cmd
79echo if 1==1 @echo bar>> mixedEchoModes.cmd
80echo @echo off>> mixedEchoModes.cmd
81echo if 1==1 echo foo2>> mixedEchoModes.cmd
82echo if 1==1 @echo bar2>> mixedEchoModes.cmd
83type mixedEchoModes.cmd
84cmd /c mixedEchoModes.cmd
85del mixedEchoModes.cmd
86
87echo ------------ Testing parameterization ------------
88call :TestParm a b c
89call :TestParm "a b c"
90call :TestParm "a b"\c
91call :TestParm a=~`+,.{}!+b
92call :TestParm a;b
93call :TestParm "a;b"
94call :TestParm a^;b
95call :TestParm a[b]{c}(d)e
96call :TestParm a&echo second line
97call :TestParm a   b,,,c
98call :TestParm a==b;;c
99call :TestParm       a,,,  b
100goto :TestRem
101
102:TestParm
103echo '%1', '%2', '%3'
104goto :eof
105
106:TestRem
107echo ------------ Testing rem ------------
108rem Hello
109rem  Hello
110rem   Hello || foo
111rem echo lol
112rem echo foo & echo bar
113rem @tab@  Hello
114rem@tab@  Hello
115rem@tab@echo foo & echo bar
116@echo on
117rem Hello
118rem  Hello
119rem   Hello || foo
120rem echo lol
121rem echo foo & echo bar
122rem @tab@  Hello
123rem@tab@  Hello
124rem@tab@echo foo & echo bar
125@echo off
126
127echo ------------ Testing redirection operators ------------
128mkdir foobar & cd foobar
129echo --- stdout redirection
130echo foo>foo
131type foo
132echo foo 1> foo
133type foo
134echo foo@tab@1> foo
135type foo
136echo foo 1>@tab@foo
137type foo
138echo foo@tab@1>@tab@foo
139type foo
140echo foo7 7> foo
141type foo
142echo foo9 9> foo
143type foo
144echo foo1> foo
145type foo
146echo foo11> foo
147type foo
148echo foo12> foo
149type foo
150echo foo13>"foo"
151type foo
152echo foo14>."\foo"
153type foo
154echo foo15>."\f"oo
155type foo
156del foo
157echo1>foo
158type foo
159echo --- stdout appending
160echo foo>foo
161echo foo >>foo
162type foo
163del foo
164echo foob >> foo
165type foo
166echo fooc 1>>foo
167type foo
168echo food1>>foo
169type foo
170echo food2>>"foo"
171type foo
172del foo
173echo food21>>foo
174type foo
175del foo
176echo foo> foo
177echo foo7 7>> foo || (echo not supported & del foo)
178if exist foo (type foo) else echo not supported
179echo --- redirections within IF statements
180if 1==1 echo foo1>bar
181type bar & del bar
182if 1==1 echo foo2>>bar
183type bar & del bar
184echo -----
185if 1==1 (echo foo2>bar) else echo baz2>bar
186type bar & del bar
187if 1==1 (echo foo3) else echo baz3>bar
188type bar || echo file does not exist, ok
189if 1==1 (echo foo4>bar) else echo baz4>bar
190type bar & del bar
191if 1==0 (echo foo5>bar) else echo baz5>bar
192type bar & del bar
193if 1==0 (echo foo6) else echo baz6 1>bar
194type bar & del bar
195if 1==0 (echo foo7 1>bar) else echo baz7>bar
196type bar & del bar
197if 1==0 (echo foo8 1>bar) else echo baz8>bak
198type bak
199if 1==1 (echo foo>bar & echo baz)
200type bar
201if 1==1 (
202   echo foo>bar
203   echo baz
204)
205type bar
206(if 1==1 (echo A) else echo B) > C
207type C
208(if 1==0 (echo A) else echo B) > C
209type C
210(if 1==0 (echo A > B) else echo C)
211cd .. & rd /s/q foobar
212
213echo ------------ Testing circumflex escape character ------------
214rem Using something like "echo foo^" asks for an additional char after a "More?" prompt on the following line; it's not possible to currently test that non-interactively
215echo ^hell^o, world
216echo hell^o, world
217echo hell^^o, world
218echo hell^^^o, world
219echo hello^
220world
221echo hello^
222
223world
224echo hello^
225
226
227echo finished
228mkdir foobar
229echo baz> foobar\baz
230type foobar\baz
231type foobar^\baz
232rd /s/q foobar
233echo foo ^| echo bar
234echo foo ^& echo bar
235call :setError 0
236echo bak ^&& echo baz 2> nul
237echo %ErrorLevel%
238echo foo ^> foo
239echo ^<> foo
240type foo
241del foo
242set WINE_FOO=oof
243echo ff^%WINE_FOO%
244set WINE_FOO=bar ^| baz
245set WINE_FOO
246rem FIXME: echoing %WINE_FOO% gives an error (baz not recognized) but prematurely
247rem exits the script on windows; redirecting stdout and/or stderr doesn't help
248echo %ErrorLevel%
249call :setError 0
250set WINE_FOO=bar ^^^| baz
251set WINE_FOO
252echo %WINE_FOO%
253echo %ErrorLevel%
254set WINE_FOO=
255
256echo ------------ Testing chains ------------
257rem The chain operators have the following bottom-up precedence:
258rem 'else' precedes nothing and matches the closest unmatched 'if' in the same bracket depth
259rem '&' precedes 'else'
260rem '||' precedes '&' and 'else'
261rem '&&' precedes '||', '&' and 'else'
262rem '|' precedes '&&', '||', '&' and 'else'
263rem
264rem Example: 'if 1==1 if 2==2 if 3==3 a | b && c || d & e else f else g' is interpreted as
265rem          'if 1==1 (if 2==2 (if 3==3 ((((a | b) && c) || d) & e) else f) else g)'
266goto :cfailend
267:cfail
268echo %1
269call :setError 1
270goto :eof
271:cfailend
272echo --- chain success
273echo a1&echo a2
274echo b1&&echo b2
275echo c1||echo c2
276echo ---
277echo d1&echo d2&echo d3
278echo e1&echo e2&&echo e3
279echo f1&echo f2||echo f3
280echo ---
281echo g1&&echo g2&echo g3
282echo h1&&echo h2&&echo h3
283echo i1&&echo i2||echo i3
284echo ---
285echo j1||echo j2&echo j3
286echo ---
287echo k1||echo k2&&echo k3
288echo ---
289echo l1||echo l2||echo l3
290echo ---
291echo --- chain failure
292call :cfail a1&call :cfail a2
293call :cfail b1&&call :cfail b2
294echo ---
295call :cfail c1||call :cfail c2
296call :cfail d1&call :cfail d2&call :cfail d3
297call :cfail e1&call :cfail e2&&call :cfail e3
298echo ---
299call :cfail f1&call :cfail f2||call :cfail f3
300call :cfail g1&&call :cfail g2&call :cfail g3
301echo ---
302call :cfail h1&&call :cfail h2&&call :cfail h3
303echo ---
304call :cfail i1&&call :cfail i2||call :cfail i3
305echo ---
306call :cfail j1||call :cfail j2&call :cfail j3
307call :cfail k1||call :cfail k2&&call :cfail k3
308echo ---
309call :cfail l1||call :cfail l2||call :cfail l3
310echo --- chain brackets
311rem Brackets are like regular commands, they support redirections
312rem and have the same precedence as regular commands.
313echo a1&(echo a2&echo a3)
314echo b1&(echo b2&&echo b3)
315echo c1&(echo c2||echo c3)
316echo ---
317echo d1&&(echo d2&echo d3)
318echo e1&&(echo e2&&echo e3)
319echo f1&&(echo f2||echo f3)
320echo ---
321echo g1||(echo g2&echo g3)
322echo ---
323echo h1||(echo h2&&echo h3)
324echo ---
325echo i1||(echo i2||echo i3)
326echo ---
327call :cfail j1&(call :cfail j2&call :cfail j3)
328call :cfail k1&(call :cfail k2&&call :cfail k3)
329echo ---
330call :cfail l1&(call :cfail l2||call :cfail l3)
331call :cfail m1&&(call :cfail m2&call :cfail m3)
332echo ---
333call :cfail n1&&(call :cfail n2&&call :cfail n3)
334echo ---
335call :cfail o1&&(call :cfail o2||call :cfail o3)
336echo ---
337call :cfail p1||(call :cfail p2&call :cfail p3)
338call :cfail q1||(call :cfail q2&&call :cfail q3)
339echo ---
340call :cfail r1||(call :cfail r2||call :cfail r3)
341echo --- chain pipe
342rem Piped commands run at the same time, so the print order varies.
343rem Additionally, they don't run in the batch script context, as shown by
344rem 'call :existing_label|echo read the error message'.
345(echo a 1>&2|echo a 1>&2) 2>&1
346echo ---
347echo b1|echo b2
348echo c1&&echo c2|echo c3
349echo d1||echo d2|echo d3
350echo ---
351echo e1&echo e2|echo e3
352echo f1|echo f2&&echo f3
353echo g1|echo g2||echo g3
354echo ---
355echo h1|echo h2&echo h3
356echo i1|echo i2|echo i3
357echo --- chain pipe input
358rem The output data of the left side of a pipe can disappear, probably
359rem because it finished too fast and closed the pipe before it could be read,
360rem which means we can get broken results for the tests of this section.
361echo @echo off> tmp.cmd
362echo set IN=X>> tmp.cmd
363echo set /p IN=%%1:>> tmp.cmd
364echo setlocal EnableDelayedExpansion>> tmp.cmd
365echo echo [!IN!,%%1]>> tmp.cmd
366echo endlocal>> tmp.cmd
367echo set IN=>> tmp.cmd
368echo a1|cmd /ctmp.cmd a2
369echo b1|cmd /ctmp.cmd b2|cmd /ctmp.cmd b3
370echo c1|cmd /ctmp.cmd c2|cmd /ctmp.cmd c3|cmd /ctmp.cmd c4
371echo d1|call tmp.cmd d2
372echo e1|call tmp.cmd e2|call tmp.cmd e3
373echo f1|call tmp.cmd f2|call tmp.cmd f3|call tmp.cmd f4
374rem FIXME these 3 tests cause "unexpected end of output"
375rem test  : echo g1|tmp.cmd g2
376rem result: g2:[g1,g2]
377rem test  : echo h1|tmp.cmd h2|tmp.cmd h3
378rem result: h3:[h2:[h1,h2],h3]@or_broken@h3:[h2:,h3]
379rem test  : echo i1|tmp.cmd i2|tmp.cmd i3|tmp.cmd i4
380rem result: i4:[i3:[i2:[i1,i2],i3],i4]@or_broken@i4:[i3:[i2:,i3],i4]@or_broken@i4:[i3:,i4]
381del tmp.cmd
382echo --- chain else
383rem Command arguments are gready and eat up the 'else' unless terminated by
384rem brackets, which means the 'else' can only be recognized when the
385rem 'if true' command chain ends with brackets.
386if 1==1 if 2==2 if 3==3 (echo a1) else (echo a2) else echo a3
387if 1==1 if 2==2 if 3==0 (echo b1) else (echo b2) else echo b3
388echo ---
389if 1==1 if 2==0 if 3==3 (echo c1) else (echo c2) else echo c3
390echo ---
391if 1==1 if 2==0 if 3==0 (echo d1) else (echo d2) else echo d3
392echo ---
393if 1==0 if 2==2 if 3==3 (echo e1) else (echo e2) else echo e3
394echo ---
395if 1==0 if 2==2 if 3==0 (echo f1) else (echo f2) else echo f3
396echo ---
397if 1==0 if 2==0 if 3==3 (echo g1) else (echo g2) else echo g3
398echo ---
399if 1==0 if 2==0 if 3==0 (echo h1) else (echo h2) else echo h3
400echo ---
401echo --- chain else (if true)
402if 1==1 echo a1 else echo a2
403if 1==1 echo b1|echo b2 else echo b3
404if 1==1 echo c1&&echo c2 else echo c3
405if 1==1 echo d1||echo d2 else echo d3
406echo ---
407if 1==1 echo e1&echo e2 else echo e3
408if 1==1 echo f1 else echo f2|echo f3
409if 1==1 echo g1 else echo g2&&echo g3
410if 1==1 echo h1 else echo h2||echo h3
411echo ---
412if 1==1 echo i1 else echo i2&echo i3
413if 1==1 echo j1|(echo j2) else echo j3
414echo ---
415if 1==1 echo k1&&(echo k2) else echo k3
416if 1==1 echo l1||(echo l2) else echo l3
417echo ---
418if 1==1 echo m1&(echo m2) else echo m3
419if 1==1 (echo n1) else echo n2|echo n3
420if 1==1 (echo o1) else echo o2&&echo o3
421if 1==1 (echo p1) else echo p2||echo p3
422if 1==1 (echo q1) else echo q2&echo q3
423echo ---
424echo --- chain else (if false)
425if 1==0 echo a1 else echo a2
426if 1==0 echo b1|echo b2 else echo b3
427if 1==0 echo c1&&echo c2 else echo c3
428if 1==0 echo d1||echo d2 else echo d3
429if 1==0 echo e1&echo e2 else echo e3
430if 1==0 echo f1 else echo f2|echo f3
431if 1==0 echo g1 else echo g2&&echo g3
432if 1==0 echo h1 else echo h2||echo h3
433if 1==0 echo i1 else echo i2&echo i3
434if 1==0 echo j1|(echo j2) else echo j3
435echo ---
436if 1==0 echo k1&&(echo k2) else echo k3
437if 1==0 echo l1||(echo l2) else echo l3
438if 1==0 echo m1&(echo m2) else echo m3
439if 1==0 (echo n1) else echo n2|echo n3
440if 1==0 (echo o1) else echo o2&&echo o3
441if 1==0 (echo p1) else echo p2||echo p3
442echo ---
443if 1==0 (echo q1) else echo q2&echo q3
444echo ------------ Testing 'set' ------------
445call :setError 0
446rem Remove any WINE_FOO* WINE_BA* environment variables from shell before proceeding
447for /f "delims==" %%i in ('set WINE_ba') do set %%i=
448for /f "delims==" %%i in ('set WINE_foo') do set %%i=
449set WINE_FOOBAR 2> nul > nul
450echo %ErrorLevel%
451set WINE_FOOBAR =  baz
452echo %ErrorLevel%
453echo %WINE_FOOBAR%WINE_FOOBAR not defined
454echo %WINE_FOOBAR %
455set WINE_FOOBAR 2> nul
456set WINE_FOOBAR =  baz2
457echo %ErrorLevel%
458echo %WINE_fOObAr %
459set WINE_FOOBAR= bar
460echo %ErrorLevel%
461echo %WINE_FOOBAR%
462set WINE_FOO
463set WINE_FOOBAR=
464set WINE_FOOB
465echo %WINE_FOOBAR%WINE_FOOBAR not defined
466set WINE_FOOBAR =
467set WINE_FOOBA 2> nul > nul
468echo %ErrorLevel%
469set WINE_FOO=bar
470echo %WINE_FOO%
471set WINE_FOO=foo
472set WINE_BAR=bar
473echo %WINE_FOO%%WINE_BAR%
474set WINE_BAR=
475set WINE_FOO=
476set WINE_FOO=%WINE_FOO%
477echo %WINE_FOO%WINE_FOO not defined
478set WINE_BAZ%=bazbaz
479set WINE_BA
480echo %WINE_BAZ%%
481set WINE_BAZ%=
482echo set "WINE_FOO=bar" should not include the quotes in the variable value
483set "WINE_FOO=bar"
484echo %WINE_FOO%
485set@tab@WINE_FOO=foo
486echo %WINE_FOO%
487set@tab@WINE_FOO=
488echo '%WINE_FOO%'
489set WINE_FOO=foo@space@
490echo '%WINE_FOO%'
491set WINE_FOO=foo@tab@
492echo '%WINE_FOO%'
493rem Space symbol must appear in `var`
494set WINE_FOO=value@space@
495echo '%WINE_FOO%'
496rem Space symbol must NOT appear in `var`
497set "WINE_FOO=value"@space@
498echo '%WINE_FOO%'
499rem Mixed examples:
500set WINE_FOO=jim fred
501echo '%WINE_FOO%'
502set WINE_FOO="jim" fred
503echo '%WINE_FOO%'
504set "WINE_FOO=jim fred"
505echo '%WINE_FOO%'
506set "WINE_FOO=jim" fred
507echo '%WINE_FOO%'
508rem Only the final quote ends the string
509set "WINE_FOO=apple"banana"grape"orange
510echo '%WINE_FOO%'
511set WINE_FOO=
512rem set PATH must work with quotes
513set PATH_BACKUP=%PATH%
514mkdir folder
515mkdir "fol;der"
516echo echo I'm here! > "fol;der\sub1.bat"
517echo echo I'm here! > folder\sub1.bat
518set PATH=nothing;"fol;der"
519call sub1
520set PATH="folder
521call sub1
522set PATH=folder"
523call sub1
524del "fol;der\sub1.bat"
525del folder\sub1.bat
526rmdir "fol;der"
527rmdir folder
528PATH=%PATH_BACKUP%
529
530echo ------------ Testing 'choice' ------------
531
532rem Windows XP and Windows 2000 do not come with choice
533rem echo is used for @or_broken@ formatting
534choice /C:ABC /M "Example message" /D A /T:0
535if %ERRORLEVEL% EQU 9009 (
536  echo choice unavailable
537)
538echo %ERRORLEVEL%
539choice /C ABC "/M:Example message" /D:B /T 0
540if %ERRORLEVEL% EQU 9009 (
541  echo choice unavailable
542)
543echo %ERRORLEVEL%
544choice /C def /D:f /T:0
545if %ERRORLEVEL% EQU 9009 (
546  echo choice unavailable
547)
548echo %ERRORLEVEL%
549REM If a pipe fails due to a nonexistent command
550REM it will stop the whole program's execution
551if %ERRORLEVEL% NEQ 9009 (
552  echo Y | choice /C ABCXYZ /D A /T 2
553)
554if %ERRORLEVEL% EQU 9009 (
555  echo choice unavailable
556)
557echo %ERRORLEVEL%
558choice /C ABC /N /D A /T 0
559if %ERRORLEVEL% EQU 9009 (
560  echo choice unavailable
561)
562echo %ERRORLEVEL%
563choice /C abcABC /CS /D:A /T:0
564if %ERRORLEVEL% EQU 9009 (
565  echo choice unavailable
566)
567echo %ERRORLEVEL%
568rem intentional error
569choice /C abcABC /D:A /T:0 >NUL 2>NUL
570echo %ERRORLEVEL%
571
572echo ------------ Testing variable expansion ------------
573call :setError 0
574echo ~p0 should be path containing batch file
575echo %~p0
576mkdir dummydir
577cd dummydir
578echo %~p0
579cd ..
580rmdir dummydir
581echo ~dp0 should be directory containing batch file
582echo %~dp0
583mkdir dummydir
584cd dummydir
585echo %~dp0
586cd ..
587rmdir dummydir
588echo CD value %CD%
589echo %%
590echo P%
591echo %P
592echo %WINE_UNKNOWN%S
593echo P%WINE_UNKNOWN%
594echo P%WINE_UNKNOWN%S
595echo %ERRORLEVEL
596echo %ERRORLEVEL%
597echo %ERRORLEVEL%%ERRORLEVEL%
598echo %ERRORLEVEL%ERRORLEVEL%
599echo %ERRORLEVEL%%
600echo %ERRORLEVEL%%%
601echo P%ERRORLEVEL%
602echo %ERRORLEVEL%S
603echo P%ERRORLEVEL%S
604
605echo ------------ Testing variable substrings ------------
606set WINE_VAR=qwerty
607echo %WINE_VAR:~0,1%
608echo %WINE_VAR:~0,3%
609echo %WINE_VAR:~2,2%
610echo '%WINE_VAR:~-2,3%'
611echo '%WINE_VAR:~-2,1%'
612echo %WINE_VAR:~2,-1%
613echo %WINE_VAR:~2,-3%
614echo '%WINE_VAR:~-2,-4%'
615echo %WINE_VAR:~-3,-2%
616set WINE_VAR=
617
618echo ------------ Testing variable substitution ------------
619echo --- in FOR variables
620for %%i in ("A B" C) do echo %%i
621rem check works when prefix with @
622@for %%i in ("A B" C) do echo %%i
623rem quotes removal
624for %%i in ("A B" C) do echo '%%~i'
625rem fully qualified path
626for %%f in ("C D" E) do echo %%~ff
627rem drive letter
628for %%i in ("F G" H) do echo %%~di
629rem path
630for %%d in ("I J" K) do echo %%~pd
631rem filename
632for %%i in ("L M" N) do echo %%~ni
633rem file extension
634for %%i in ("O. P.OOL" Q.TABC hello) do echo '%%~xi'
635rem path with short path names
636for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do echo '%%~sI'
637rem file attribute
638for %%i in ("U V" W) do echo '%%~ai'
639echo foo> foo
640for %%i in (foo) do echo '%%~ai'
641for %%i in (foo) do echo '%%~zi'
642del foo
643rem file date/time
644rem Not fully testable, until we can grep dir's output to get foo's creation time in an envvar...
645for %%i in ("a b" c) do echo '%%~ti'
646rem file size
647rem Similar issues as above
648for %%i in ("a b" c) do echo '%%~zi'
649rem combined options
650for %%i in ("d e" f) do echo %%~dpi
651for %%i in ("g h" i) do echo %%~sdi
652for %%i in ("g h" i) do echo %%~dsi
653for %%i in ("j k" l.eh) do echo '%%~xsi'
654for %%i in ("") do echo '%%~i,%%~fi,%%~di,%%~pi,%%~ni,%%~xi,%%~si,%%~ai,%%~ti,%%~zi'
655
656echo --- in parameters
657for %%i in ("A B" C) do call :echoFun %%i
658rem quotes removal
659for %%i in ("A B" C) do call :echoFunQ %%i
660rem fully qualified path
661for %%f in ("C D" E) do call :echoFunF %%f
662rem drive letter
663for %%i in ("F G" H) do call :echoFunD %%i
664rem path
665for %%d in ("I J" K) do call :echoFunP %%d
666rem filename
667for %%i in ("L M" N) do call :echoFunN %%i
668rem file extension
669for %%i in ("O. P.OOL" Q.TABC hello) do call :echoFunX %%i
670rem path with short path names
671for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do call :echoFunS %%I
672rem NT4 aborts whole script execution when encountering ~a, ~t and ~z substitutions, preventing full testing
673rem combined options
674for %%i in ("d e" f) do call :echoFunDP %%i
675for %%i in ("g h" i) do call :echoFunSD %%i
676for %%i in ("g h" i) do call :echoFunDS %%i
677for %%i in ("j k" l.eh) do call :echoFunXS %%i
678
679goto :endEchoFuns
680:echoFun
681echo %1
682goto :eof
683
684:echoFunQ
685echo '%~1'
686goto :eof
687
688:echoFunF
689echo %~f1
690goto :eof
691
692:echoFunD
693echo %~d1
694goto :eof
695
696:echoFunP
697echo %~p1
698goto :eof
699
700:echoFunN
701echo %~n1
702goto :eof
703
704:echoFunX
705echo '%~x1'
706goto :eof
707
708:echoFunS
709rem some NT4 workaround
710set WINE_VAR='%~s1'
711echo %WINE_VAR%
712set WINE_VAR=
713goto :eof
714
715:echoFunDP
716echo %~dp1
717goto :eof
718
719:echoFunSD
720echo %~sd1
721goto :eof
722
723:echoFunDS
724echo %~ds1
725goto :eof
726
727:echoFunXS
728echo '%~xs1'
729goto :eof
730:endEchoFuns
731
732echo ------------ Testing parameter zero ------------
733call :func parm1 parm2
734goto :endParm0
735:func
736echo %~0 %~1
737echo [%0] [%~d0] [%~p0] [%~n0] [%~x0] [%~s0]
738goto :EOF
739:endParm0
740
741echo ------------ Testing variable delayed expansion ------------
742rem NT4 doesn't support this
743echo --- default mode (load-time expansion)
744set WINE_FOO=foo
745echo %WINE_FOO%
746echo !WINE_FOO!
747if %WINE_FOO% == foo (
748    set WINE_FOO=bar
749    if %WINE_FOO% == bar (echo bar) else echo foo
750)
751
752set WINE_FOO=foo
753if %WINE_FOO% == foo (
754    set WINE_FOO=bar
755    if !WINE_FOO! == bar (echo bar) else echo foo
756)
757
758echo --- runtime (delayed) expansion mode
759setlocal EnableDelayedExpansion
760set WINE_FOO=foo
761echo %WINE_FOO%
762echo !WINE_FOO!
763if %WINE_FOO% == foo (
764    set WINE_FOO=bar
765    if %WINE_FOO% == bar (echo bar) else echo foo
766)
767
768set WINE_FOO=foo
769if %WINE_FOO% == foo (
770    set WINE_FOO=bar
771    if !WINE_FOO! == bar (echo bar) else echo foo
772)
773echo %ErrorLevel%
774setlocal DisableDelayedExpansion
775echo %ErrorLevel%
776set WINE_FOO=foo
777echo %WINE_FOO%
778echo !WINE_FOO!
779set WINE_FOO=
780echo --- using /V cmd flag
781echo @echo off> tmp.cmd
782echo set WINE_FOO=foo>> tmp.cmd
783echo echo %%WINE_FOO%%>> tmp.cmd
784echo echo !WINE_FOO!>> tmp.cmd
785echo set WINE_FOO=>> tmp.cmd
786cmd /V:ON /C tmp.cmd
787cmd /V:OfF /C tmp.cmd
788del tmp.cmd
789
790echo ------------ Testing conditional execution ------------
791echo --- unconditional ampersand
792call :setError 123 & echo foo1
793echo bar2 & echo foo2
794mkdir foobar & cd foobar
795echo > foobazbar
796cd .. & rd /s/q foobar
797if exist foobazbar (
798    echo foobar not deleted!
799    cd ..
800    rd /s/q foobar
801) else echo foobar deleted
802echo --- on success conditional and
803call :setError 456 && echo foo3 > foo3
804if exist foo3 (
805    echo foo3 created
806    del foo3
807) else echo foo3 not created
808echo bar4 && echo foo4
809echo --- on failure conditional or
810call :setError 789 || echo foo5
811echo foo6 || echo bar6 > bar6
812if exist bar6 (
813    echo bar6 created
814    del bar6
815)
816
817echo ------------ Testing cd ------------
818mkdir foobar
819cd foobar
820echo blabla > singleFile
821dir /b
822echo Current dir: %CD%
823cd
824cd ..
825cd
826cd foobar@space@
827cd
828cd ..
829cd
830cd @space@foobar
831cd
832cd..
833cd
834cd foobar
835cd..@space@
836cd
837if not exist foobar (cd ..)
838cd foobar
839cd@tab@..@tab@@space@@tab@
840cd
841if not exist foobar (cd ..)
842cd foobar
843mkdir "bar bak"
844cd "bar bak"
845cd
846cd ..
847cd ".\bar bak"
848cd
849cd ..
850cd .\"bar bak"
851cd
852cd ..
853cd bar bak
854cd
855cd "bar bak@space@"@tab@@space@
856cd
857cd ..\..
858cd
859rd /Q/s foobar
860mkdir foobar
861cd /d@tab@foobar
862cd
863cd ..
864rd /q/s foobar
865
866echo ------------ Testing type ------------
867echo bar> foobaz
868@echo on
869type foobaz
870echo ---
871@echo off
872type foobaz@tab@
873echo ---1
874type ."\foobaz"
875echo ---2
876type ".\foobaz"
877echo ---3
878echo foo> foobay
879echo ---4
880type foobaz foobay > foobax 2> foobaw
881echo ---5
882type foobax
883echo ---6
884type foobaw
885echo ---7
886del foobaz foobay foobax foobaw
887
888echo ------------ Testing NUL ------------
889md foobar & cd foobar
890rem NUL file (non) creation + case insensitivity
891rem Note: "if exist" does not work with NUL, so to check for file existence we use a kludgy workaround
892echo > bar
893echo foo > NUL
894dir /b /a-d
895echo foo > nul
896dir /b /a-d
897echo foo > NuL
898@tab@dir /b@tab@/a-d
899del bar
900rem NUL not special everywhere
901call :setError 123
902echo NUL> foo
903if not exist foo (echo foo should have been created) else (
904    type foo
905    del foo
906)
907rem Empty file creation
908copy nul foo > nul
909if exist foo (
910    echo foo created
911    del foo
912    type foo
913) else (
914    echo ***
915)
916echo 1234 >a.a
917copy a.a+NUL b.b >nul
918call :CheckFileSize a.a 7 b.b 8
919copy NUL+a.a b.b >nul
920call :CheckFileSize a.a 7 b.b 8
921mkdir subdir
922copy a.a+NUL subdir\ >nul
923call :CheckFileSize a.a 7 subdir\a.a 8
924del subdir\a.a
925cd subdir
926copy ..\a.a NUL >nul
927if exist a.a echo Failed
928cd ..
929rd subdir /s /q
930del a.a b.b
931cd .. & rd foobar /s /q
932
933echo ------------ Testing if/else ------------
934echo --- if/else should work with blocks
935if 0 == 0 (
936  echo if seems to work
937) else (
938  echo if seems to be broken
939)
940if 1 == 0 (
941  echo else seems to be broken
942) else (
943  echo else seems to work
944)
945if /c==/c (
946  echo if seems not to detect /c as parameter
947) else (
948  echo parameter detection seems to be broken
949)
950SET elseIF=0
951if 1 == 1 (
952  SET /a elseIF=%elseIF%+1
953) else if 1 == 1 (
954  SET /a elseIF=%elseIF%+2
955) else (
956  SET /a elseIF=%elseIF%+2
957)
958if %elseIF% == 1 (
959  echo else if seems to work
960) else (
961  echo else if seems to be broken
962)
963SET elseIF=0
964if 1 == 2 (
965  SET /a elseIF=%elseIF%+2
966) else if 1 == 1 (
967  SET /a elseIF=%elseIF%+1
968) else (
969  SET /a elseIF=%elseIF%+2
970)
971if %elseIF% == 1 (
972  echo else if seems to work
973) else (
974  echo else if seems to be broken
975)
976SET elseIF=0
977if 1 == 2 (
978  SET /a elseIF=%elseIF%+2
979) else if 1 == 2 (
980  SET /a elseIF=%elseIF%+2
981) else (
982  SET /a elseIF=%elseIF%+1
983)
984if %elseIF% == 1 (
985  echo else if seems to work
986) else (
987  echo else if seems to be broken
988)
989if "x" == "a" (
990  echo broken1
991) else (
992  echo expected1
993  if "y" == "b" echo broken2
994  echo expected post-embedded if
995)
996if ()==() (
997  echo comparison operators surrounded by brackets seem to work
998) else (
999  echo comparison operators surrounded by brackets seem to be broken
1000)
1001if 1(==1( (
1002  echo comparison operators surrounded by brackets seem to work
1003) else (
1004  echo comparison operators surrounded by brackets seem to be broken
1005)
1006if )==) (
1007  echo comparison operators surrounded by brackets seem to work
1008) else (
1009  echo comparison operators surrounded by brackets seem to be broken
1010)
1011if /i not (a)==(b) (
1012  echo comparison operators surrounded by brackets seem to work
1013) else (
1014  echo comparison operators surrounded by brackets seem to be broken
1015)
1016if defined windir echo windir is defined
1017if not defined windir echo windir is defined
1018if not exist %windir% (
1019  echo windir does not exist
1020) else (
1021  echo windir does exist
1022)
1023echo --- case sensitivity with and without /i option
1024if bar==BAR echo if does not default to case sensitivity
1025if not bar==BAR echo if seems to default to case sensitivity
1026if /i foo==FOO echo if /i seems to work
1027if /i not foo==FOO echo if /i seems to be broken
1028if /I foo==FOO echo if /I seems to work
1029if /I not foo==FOO echo if /I seems to be broken
1030
1031echo --- string comparisons
1032if abc == abc  (echo equal) else echo non equal
1033if abc =="abc" (echo equal) else echo non equal
1034if "abc"== abc (echo equal) else echo non equal
1035if "abc"== "abc" (echo equal) else echo non equal
1036
1037echo --- tabs handling
1038if@tab@1==1 echo doom
1039if @tab@1==1 echo doom
1040if 1==1 (echo doom) else@tab@echo quake
1041if@tab@not @tab@1==@tab@0 @tab@echo lol
1042if 1==0@tab@(echo doom) else echo quake
1043if 1==0 (echo doom)@tab@else echo quake
1044if 1==0 (echo doom) else@tab@echo quake
1045
1046echo --- comparison operators
1047rem NT4 misevaluates conditionals in for loops so we have to use subroutines as workarounds
1048echo ------ for strings
1049rem NT4 stops processing of the whole batch file as soon as it finds a
1050rem comparison operator non fully uppercased, such as lss instead of LSS, so we
1051rem can't test those here.
1052if LSS LSS LSSfoo (echo LSS string can be used as operand for LSS comparison)
1053if LSS LSS LSS (echo bar)
1054if 1.1 LSS 1.10 (echo floats are handled as strings)
1055if "9" LSS "10" (echo numbers in quotes recognized!) else echo numbers in quotes are handled as strings
1056if not "-1" LSS "1" (echo negative numbers as well) else echo NT4
1057if /i foo LSS FoOc echo if /i seems to work for LSS
1058if /I not foo LSS FOOb echo if /I seems to be broken for LSS
1059set WINE_STR_PARMS=A B AB BA AA
1060for %%i in (%WINE_STR_PARMS%) do (
1061    for %%j in (%WINE_STR_PARMS%) do (
1062        call :LSStest %%i %%j))
1063if b LSS B (echo b LSS B) else echo NT4
1064if /I b LSS B echo b LSS B insensitive
1065if b LSS A echo b LSS A
1066if /I b LSS A echo b LSS A insensitive
1067if a LSS B (echo a LSS B) else echo NT4
1068if /I a LSS B echo a LSS B insensitive
1069if A LSS b echo A LSS b
1070if /I A LSS b echo A LSS b insensitive
1071for %%i in (%WINE_STR_PARMS%) do (
1072    for %%j in (%WINE_STR_PARMS%) do (
1073        call :LEQtest %%i %%j))
1074if b LEQ B (echo b LEQ B) else echo NT4
1075if /I b LEQ B echo b LEQ B insensitive
1076if b LEQ A echo b LEQ A
1077if /I b LEQ A echo b LEQ A insensitive
1078if a LEQ B (echo a LEQ B) else echo NT4
1079if /I a LEQ B echo a LEQ B insensitive
1080if A LEQ b echo A LEQ b
1081if /I A LEQ b echo A LEQ b insensitive
1082for %%i in (%WINE_STR_PARMS%) do (
1083    for %%j in (%WINE_STR_PARMS%) do (
1084        call :EQUtest %%i %%j))
1085if /I A EQU a echo A EQU a insensitive
1086for %%i in (%WINE_STR_PARMS%) do (
1087    for %%j in (%WINE_STR_PARMS%) do (
1088        call :NEQtest %%i %%j))
1089for %%i in (%WINE_STR_PARMS%) do (
1090    for %%j in (%WINE_STR_PARMS%) do (
1091        call :GEQtest %%i %%j))
1092for %%i in (%WINE_STR_PARMS%) do (
1093    for %%j in (%WINE_STR_PARMS%) do (
1094        call :GTRtest %%i %%j))
1095
1096echo ------------ Testing if/exist ------------
1097mkdir subdir
1098echo something>subdir\bar
1099echo something else>foo
1100if exist foo (
1101   echo exist explicit works
1102) else (
1103   echo ERROR exist explicit broken
1104)
1105if exist bar (
1106   echo ERROR exist explicit unknown file broken
1107) else (
1108   echo exist explicit unknown file works
1109)
1110if exist subdir\bar (
1111   echo exist explicit in subdir works
1112) else (
1113   echo ERROR exist explicit in subdir broken
1114)
1115if exist fo* (
1116   echo exist simple wildcard works
1117) else (
1118   echo ERROR exist simple wildcard broken
1119)
1120if exist subdir\ba* (
1121   echo exist wildcard works
1122) else (
1123   echo ERROR exist wildcard broken
1124)
1125if not exist subdir\ba* (
1126   echo ERROR negate exist wildcard broken
1127) else (
1128   echo negate exist wildcard works
1129)
1130if exist idontexist\ba* (
1131   echo ERROR exist wildcard bad subdir broken
1132) else (
1133   echo exist wildcard bad subdir broken works
1134)
1135if exist subdir (
1136   echo exist subdir ok
1137) else (
1138   echo ERROR exist subdir not working
1139)
1140if exist subdir\. (
1141   echo exist subdir with . ok
1142) else (
1143   echo ERROR exist subdir with . not working
1144)
1145if exist subdir\ (
1146   echo exist subdir with \ ok
1147) else (
1148   echo ERROR exist subdir with \ not working
1149)
1150if exist "subdir\" (
1151   echo exist subdir with \ and quotes ok
1152) else (
1153   echo ERROR exist subdir with \ and quotes not working
1154)
1155del foo subdir\bar
1156rd subdir
1157
1158echo ------ for numbers
1159if -1 LSS 1 (echo negative numbers handled)
1160if not -1 LSS -10 (echo negative numbers handled)
1161if not 9 LSS 010 (echo octal handled)
1162if not -010 LSS -8 (echo also in negative form)
1163if 4 LSS 0x5 (echo hexa handled)
1164if not -1 LSS -0x1A (echo also in negative form)
1165if 11 LSS 101 (echo 11 LSS 101)
1166set WINE_INT_PARMS=0 1 10 9
1167for %%i in (%WINE_INT_PARMS%) do (
1168    for %%j in (%WINE_INT_PARMS%) do (
1169        call :LSStest %%i %%j))
1170for %%i in (%WINE_INT_PARMS%) do (
1171    for %%j in (%WINE_INT_PARMS%) do (
1172        call :LEQtest %%i %%j))
1173for %%i in (%WINE_INT_PARMS%) do (
1174    for %%j in (%WINE_INT_PARMS%) do (
1175        call :EQUtest %%i %%j))
1176if 011 EQU 9 (echo octal ok)
1177if 0xA1 EQU 161 (echo hexa ok)
1178if 0xA1 EQU "161" (echo hexa should be recognized) else (echo string/hexa compare ok)
1179if "0xA1" EQU 161 (echo hexa should be recognized) else (echo string/hexa compare ok)
1180for %%i in (%WINE_INT_PARMS%) do (
1181    for %%j in (%WINE_INT_PARMS%) do (
1182        call :NEQtest %%i %%j))
1183for %%i in (%WINE_INT_PARMS%) do (
1184    for %%j in (%WINE_INT_PARMS%) do (
1185        call :GEQtest %%i %%j))
1186for %%i in (%WINE_INT_PARMS%) do (
1187    for %%j in (%WINE_INT_PARMS%) do (
1188        call :GTRtest %%i %%j))
1189echo ------ for numbers and stringified numbers
1190if not "1" EQU 1 (echo strings and integers not equal) else echo foo
1191if not 1 EQU "1" (echo strings and integers not equal) else echo foo
1192if '1' EQU 1 echo '1' EQU 1
1193if 1 EQU '1' echo 1 EQU '1'
1194if not "1" GEQ 1 (echo foo) else echo bar
1195if "10" GEQ "1" echo "10" GEQ "1"
1196if '1' GEQ 1 (echo '1' GEQ 1) else echo NT4
1197if 1 GEQ "1" echo 1 GEQ "1"
1198if "1" GEQ "1" echo "1" GEQ "1"
1199if '1' GEQ "1" echo '1' GEQ "1"
1200if "10" GEQ "1" echo "10" GEQ "1"
1201if not 1 GEQ '1' (echo non NT4) else echo 1 GEQ '1'
1202for %%i in ("1" '1') do call :GEQtest %%i '1'
1203if "10" GEQ '1' (echo "10" GEQ '1') else echo foo
1204if 1 GEQ "10" (echo 1 GEQ "10") else echo foo
1205if "1" GEQ "10" (echo 1 GEQ "10") else echo foo
1206if '1' GEQ "10" (echo '1' GEQ "10") else echo foo
1207if "10" GEQ "10" (echo "10" GEQ "10")
1208echo --- unconditional ampersand after if one line
1209if "0"=="0" echo 1 & echo 2 & echo 3 else echo 4
1210echo ---
1211echo x & if "0"=="1" echo 1 & echo 2
1212echo ---
1213echo x & if "0"=="1" echo 1 & echo 2 & echo 3
1214echo ---
1215echo x & if "0"=="1" (echo 1 & echo 2 & echo 3)
1216echo ---
1217echo x & if "0"=="1" echo 1 & echo 2 & echo 3 else echo 4
1218echo ---
1219goto :endIfCompOpsSubroutines
1220
1221rem IF subroutines helpers
1222:LSStest
1223if %1 LSS %2 echo %1 LSS %2
1224goto :eof
1225:LEQtest
1226if %1 LEQ %2 echo %1 LEQ %2
1227goto :eof
1228:EQUtest
1229if %1 EQU %2 echo %1 EQU %2
1230goto :eof
1231:NEQtest
1232if %1 NEQ %2 echo %1 NEQ %2
1233goto :eof
1234:GEQtest
1235if %1 GEQ %2 echo %1 GEQ %2
1236goto :eof
1237:GTRtest
1238if %1 GTR %2 echo %1 GTR %2
1239goto :eof
1240
1241:endIfCompOpsSubroutines
1242set WINE_STR_PARMS=
1243set WINE_INT_PARMS=
1244
1245echo ------------ Testing for ------------
1246echo --- plain FOR
1247for %%i in (A B C) do echo %%i
1248for %%i in (A B C) do echo %%I
1249for %%i in (A B C) do echo %%j
1250for %%i in (A B C) do call :forTestFun1 %%i
1251for %%i in (1,4,1) do echo %%i
1252for %%i in (A, B,C) do echo %%i
1253for %%i in  (X) do echo %%i
1254for@tab@%%i in  (X2) do echo %%i
1255for %%i in@tab@(X3) do echo %%i
1256for %%i in (@tab@ foo@tab@) do echo %%i
1257for@tab@ %%i in@tab@(@tab@M) do echo %%i
1258for %%i@tab@in (X)@tab@do@tab@echo %%i
1259for@tab@ %%j in@tab@(@tab@M, N, O@tab@) do echo %%j
1260for %%i in (`echo A B`) do echo %%i
1261for %%i in ('echo A B') do echo %%i
1262for %%i in ("echo A B") do echo %%i
1263for %%i in ("A B" C) do echo %%i
1264goto :endForTestFun1
1265:forTestFun1
1266echo %1
1267goto :eof
1268:endForTestFun1
1269echo --- imbricated FORs
1270for %%i in (X) do (
1271    for %%j in (Y) do (
1272        echo %%i %%j))
1273for %%i in (X) do (
1274    for %%I in (Y) do (
1275        echo %%i %%I))
1276for %%i in (A B) do (
1277    for %%j in (C D) do (
1278        echo %%i %%j))
1279for %%i in (A B) do (
1280    for %%j in (C D) do (
1281        call :forTestFun2 %%i %%j ))
1282goto :endForTestFun2
1283:forTestFun2
1284echo %1 %2
1285goto :eof
1286:endForTestFun2
1287mkdir foobar & cd foobar
1288mkdir foo
1289mkdir bar
1290mkdir baz
1291mkdir pop
1292echo > bazbaz
1293echo --- basic wildcards
1294for %%i in (ba*) do echo %%i
1295echo --- wildcards in subdirs
1296echo something>pop\bar1
1297echo something>pop\bar2.txt
1298echo something>pop\bar3
1299for %%f in (pop\ba*) do ( call echo %%f )
1300rmdir /s/q pop
1301echo --- for /d
1302for /d %%i in (baz foo bar) do echo %%i 2>&1
1303rem Confirm we don't match files:
1304for /d %%i in (bazb*) do echo %%i 2>&1
1305for /d %%i in (bazb2*) do echo %%i 2>&1
1306rem Show we pass through non wildcards
1307for /d %%i in (PASSED) do echo %%i
1308for /d %%i in (xxx) do (
1309  echo %%i - Should be xxx
1310  echo Expected second line
1311)
1312rem Show we issue no messages on failures
1313for /d %%i in (FAILED?) do echo %%i 2>&1
1314for /d %%i in (FAILED?) do (
1315  echo %%i - Unexpected!
1316  echo FAILED Unexpected second line
1317)
1318for /d %%i in (FAILED*) do echo %%i 2>&1
1319for /d %%i in (FAILED*) do (
1320  echo %%i - Unexpected!
1321  echo FAILED Unexpected second line
1322)
1323rem FIXME can't test wildcard expansion here since it's listed in directory
1324rem order, and not in alphabetic order.
1325rem Proper testing would need a currently missing "sort" program implementation.
1326rem for /d %%i in (ba*) do echo %%i>> tmp
1327rem sort < tmp
1328rem del tmp
1329rem for /d %%i in (?a*) do echo %%i>> tmp
1330rem sort < tmp
1331rem del tmp
1332rem for /d %%i in (*) do echo %%i>> tmp
1333rem sort < tmp
1334rem del tmp
1335echo > baz\bazbaz
1336goto :TestForR
1337
1338:SetExpected
1339del temp.bat 2>nul
1340call :WriteLine set WINE_found=N
1341for /l %%i in (1,1,%WINE_expectedresults%) do (
1342  call :WriteLine if "%%%%WINE_expectedresults.%%i%%%%"=="%%%%~1" set WINE_found=Y
1343  call :WriteLine if "%%%%WINE_found%%%%"=="Y" set WINE_expectedresults.%%i=
1344  call :WriteLine if "%%%%WINE_found%%%%"=="Y" goto :eof
1345)
1346call :WriteLine echo Got unexpected result: "%%%%~1"
1347goto :eof
1348
1349:WriteLine
1350echo %*>> temp.bat
1351goto :EOF
1352
1353:ValidateExpected
1354del temp.bat 2>nul
1355for /l %%i in (1,1,%WINE_expectedresults%) do (
1356  call :WriteLine if not "%%%%WINE_expectedresults.%%i%%%%"=="" echo Found missing result: "%%%%WINE_expectedresults.%%i%%%%"
1357)
1358call temp.bat
1359del temp.bat 2>nul
1360goto :eof
1361
1362:TestForR
1363rem %CD% does not work on NT4 so use the following workaround
1364for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi
1365
1366echo --- for /R
1367echo Plain directory enumeration
1368set WINE_expectedresults=4
1369set WINE_expectedresults.1=%WINE_CURDIR%\.
1370set WINE_expectedresults.2=%WINE_CURDIR%\bar\.
1371set WINE_expectedresults.3=%WINE_CURDIR%\baz\.
1372set WINE_expectedresults.4=%WINE_CURDIR%\foo\.
1373call :SetExpected
1374for /R %%i in (.) do call temp.bat "%%i"
1375call :ValidateExpected
1376
1377echo Plain directory enumeration from provided root
1378set WINE_expectedresults=4
1379set WINE_expectedresults.1=%WINE_CURDIR%\.
1380set WINE_expectedresults.2=%WINE_CURDIR%\bar\.
1381set WINE_expectedresults.3=%WINE_CURDIR%\baz\.
1382set WINE_expectedresults.4=%WINE_CURDIR%\foo\.
1383if "%CD%"=="" goto :SkipBrokenNT4
1384call :SetExpected
1385for /R "%WINE_CURDIR%" %%i in (.) do call temp.bat "%%i"
1386call :ValidateExpected
1387:SkipBrokenNT4
1388
1389echo File enumeration
1390set WINE_expectedresults=2
1391set WINE_expectedresults.1=%WINE_CURDIR%\baz\bazbaz
1392set WINE_expectedresults.2=%WINE_CURDIR%\bazbaz
1393call :SetExpected
1394for /R %%i in (baz*) do call temp.bat "%%i"
1395call :ValidateExpected
1396
1397echo File enumeration from provided root
1398set WINE_expectedresults=2
1399set WINE_expectedresults.1=%WINE_CURDIR%\baz\bazbaz
1400set WINE_expectedresults.2=%WINE_CURDIR%\bazbaz
1401call :SetExpected
1402for /R %%i in (baz*) do call temp.bat "%%i"
1403call :ValidateExpected
1404
1405echo Mixed enumeration
1406set WINE_expectedresults=6
1407set WINE_expectedresults.1=%WINE_CURDIR%\.
1408set WINE_expectedresults.2=%WINE_CURDIR%\bar\.
1409set WINE_expectedresults.3=%WINE_CURDIR%\baz\.
1410set WINE_expectedresults.4=%WINE_CURDIR%\baz\bazbaz
1411set WINE_expectedresults.5=%WINE_CURDIR%\bazbaz
1412set WINE_expectedresults.6=%WINE_CURDIR%\foo\.
1413call :SetExpected
1414for /R %%i in (. baz*) do call temp.bat "%%i"
1415call :ValidateExpected
1416
1417echo Mixed enumeration from provided root
1418set WINE_expectedresults=6
1419set WINE_expectedresults.1=%WINE_CURDIR%\.
1420set WINE_expectedresults.2=%WINE_CURDIR%\bar\.
1421set WINE_expectedresults.3=%WINE_CURDIR%\baz\.
1422set WINE_expectedresults.4=%WINE_CURDIR%\baz\bazbaz
1423set WINE_expectedresults.5=%WINE_CURDIR%\bazbaz
1424set WINE_expectedresults.6=%WINE_CURDIR%\foo\.
1425call :SetExpected
1426for /R %%i in (. baz*) do call temp.bat "%%i"
1427call :ValidateExpected
1428
1429echo With duplicates enumeration
1430set WINE_expectedresults=12
1431set WINE_expectedresults.1=%WINE_CURDIR%\bar\bazbaz
1432set WINE_expectedresults.2=%WINE_CURDIR%\bar\fred
1433set WINE_expectedresults.3=%WINE_CURDIR%\baz\bazbaz
1434set WINE_expectedresults.4=%WINE_CURDIR%\baz\bazbaz
1435set WINE_expectedresults.5=%WINE_CURDIR%\baz\bazbaz
1436set WINE_expectedresults.6=%WINE_CURDIR%\baz\fred
1437set WINE_expectedresults.7=%WINE_CURDIR%\bazbaz
1438set WINE_expectedresults.8=%WINE_CURDIR%\bazbaz
1439set WINE_expectedresults.9=%WINE_CURDIR%\bazbaz
1440set WINE_expectedresults.10=%WINE_CURDIR%\foo\bazbaz
1441set WINE_expectedresults.11=%WINE_CURDIR%\foo\fred
1442set WINE_expectedresults.12=%WINE_CURDIR%\fred
1443call :SetExpected
1444for /R %%i in (baz* bazbaz fred ba*) do call temp.bat "%%i"
1445call :ValidateExpected
1446
1447echo Strip missing wildcards, keep unwildcarded names
1448set WINE_expectedresults=6
1449set WINE_expectedresults.1=%WINE_CURDIR%\bar\jim
1450set WINE_expectedresults.2=%WINE_CURDIR%\baz\bazbaz
1451set WINE_expectedresults.3=%WINE_CURDIR%\baz\jim
1452set WINE_expectedresults.4=%WINE_CURDIR%\bazbaz
1453set WINE_expectedresults.5=%WINE_CURDIR%\foo\jim
1454set WINE_expectedresults.6=%WINE_CURDIR%\jim
1455call :SetExpected
1456for /R %%i in (baz* fred* jim) do call temp.bat "%%i"
1457call :ValidateExpected
1458
1459echo for /R passed
1460echo --- Complex wildcards unix and windows slash
1461cd ..
1462echo Windows slashes, valid path
1463for %%f in (foobar\baz\bazbaz) do echo ASIS: %%f
1464for %%f in (foobar\baz\*) do echo WC  : %%f
1465echo Windows slashes, invalid path
1466for %%f in (foobar\jim\bazbaz) do echo ASIS: %%f
1467for %%f in (foobar\jim\*) do echo WC  : %%f
1468echo Unix slashes, valid path
1469for %%f in (foobar/baz/bazbaz) do echo ASIS: %%f
1470for %%f in (foobar/baz/*) do echo WC  : %%f
1471echo Unix slashes, invalid path
1472for %%f in (foobar/jim/bazbaz) do echo ASIS: %%f
1473for %%f in (foobar/jim/*) do echo WC  : %%f
1474echo Done
1475rd /s/Q foobar
1476echo --- for /L
1477rem Some cases loop forever writing 0s, like e.g. (1,0,1), (1,a,3) or (a,b,c); those can't be tested here
1478for /L %%i in (1,2,0) do echo %%i
1479for@tab@/L %%i in (1,2,0) do echo %%i
1480for /L %%i in (1,2,6) do echo %%i
1481for /l %%i in (1 ,2,6) do echo %%i
1482for /L %%i in (a,2,3) do echo %%i
1483for /L %%i in (1,2,-1) do echo %%i
1484for /L %%i in (-4,-1,-1) do echo %%i
1485for /L %%i in (1,-2,-2) do echo %%i
1486for /L %%i in (1,2,a) do echo %%i
1487echo ErrorLevel %ErrorLevel%
1488for /L %%i in (1,a,b) do echo %%i
1489echo ErrorLevel %ErrorLevel%
1490rem Test boundaries
1491for /l %%i in (1,1,4) do echo %%i
1492for /l %%i in (1,2,4) do echo %%i
1493for /l %%i in (4,-1,1) do echo %%i
1494for /l %%i in (4,-2,1) do echo %%i
1495for /l %%i in (1,-1,4) do echo %%i
1496for /l %%i in (4,1,1) do echo %%i
1497for /L %%i in (a,2,b) do echo %%i
1498for /L %%i in (1,1,1) do echo %%i
1499for /L %%i in (1,-2,-1) do echo %%i
1500for /L %%i in (-1,-1,-1) do echo %%i
1501for /L %%i in (1,2, 3) do echo %%i
1502rem Test zero iteration skips the body of the for
1503for /L %%i in (2,2,1) do (
1504  echo %%i
1505  echo FAILED
1506)
1507echo --- rems inside for loops
1508for /f %%i IN ("hello") DO (
1509   REM foo|echo ERROR unexpected execution 1
1510   @REM foo|echo ERROR unexpected execution 2
1511   @     REM foo|echo ERROR unexpected execution 3
1512)
1513echo --- ifs inside for loops
1514for %%i in (test) do (
1515    echo a1
1516    if 1==1 (
1517        echo b1
1518    ) else (
1519        echo c1
1520    )
1521    echo d1
1522)
1523for %%i in (test) do (
1524    echo a2
1525    if 1==1 (
1526        echo b2
1527    ) else echo c2
1528    echo d2
1529)
1530for %%i in (test) do (
1531    echo a3
1532    if 1==0 (
1533        echo b3
1534    ) else echo c3
1535    echo d3
1536)
1537for %%i in (test) do (
1538    echo a4
1539    if 1==0 (
1540        echo b4
1541    ) else (
1542        echo c4
1543    )
1544    echo d4
1545)
1546echo --- set /a
1547goto :testseta
1548
1549Rem Ideally for /f can be used rather than building a command to execute
1550rem but that does not work on NT4
1551:checkenvvars
1552if "%1"=="" goto :eof
1553call :executecmd set wine_result=%%%1%%
1554if "%wine_result%"=="%2" (
1555  echo %1 correctly %2
1556) else echo ERROR: %1 incorrectly %wine_result% [%2]
1557set %1=
1558shift
1559shift
1560rem shift
1561goto :checkenvvars
1562:executecmd
1563%*
1564goto :eof
1565
1566:testseta
1567rem No output when using "set expr" syntax, unless in interactive mode
1568rem Need to use "set envvar=expr" to use in a batch script
1569echo ------ individual operations
1570set WINE_foo=0
1571set /a WINE_foo=1 +2 & call :checkenvvars WINE_foo 3
1572set /a WINE_foo=1 +-2 & call :checkenvvars WINE_foo -1
1573set /a WINE_foo=1 --2 & call :checkenvvars WINE_foo 3
1574set /a WINE_foo=2* 3 & call :checkenvvars WINE_foo 6
1575set /a WINE_foo=-2* -5 & call :checkenvvars WINE_foo 10
1576set /a WINE_foo=12/3 & call :checkenvvars WINE_foo 4
1577set /a WINE_foo=13/3 & call :checkenvvars WINE_foo 4
1578set /a WINE_foo=-13/3 & call :checkenvvars WINE_foo -4
1579rem FIXME Divide by zero should return an error, but error messages cannot be tested with current infrastructure
1580set /a WINE_foo=5 %% 5 & call :checkenvvars WINE_foo 0
1581set /a WINE_foo=5 %% 3 & call :checkenvvars WINE_foo 2
1582set /a WINE_foo=5 %% -3 & call :checkenvvars WINE_foo 2
1583set /a WINE_foo=-5 %% -3 & call :checkenvvars WINE_foo -2
1584set /a WINE_foo=1 ^<^< 0 & call :checkenvvars WINE_foo 1
1585set /a WINE_foo=1 ^<^< 2 & call :checkenvvars WINE_foo 4
1586set /a WINE_foo=1 ^<^< -2 & call :checkenvvars WINE_foo 0
1587set /a WINE_foo=-1 ^<^< -2 & call :checkenvvars WINE_foo 0
1588set /a WINE_foo=-1 ^<^< 2 & call :checkenvvars WINE_foo -4
1589set /a WINE_foo=9 ^>^> 0 & call :checkenvvars WINE_foo 9
1590set /a WINE_foo=9 ^>^> 2 & call :checkenvvars WINE_foo 2
1591set /a WINE_foo=9 ^>^> -2 & call :checkenvvars WINE_foo 0
1592set /a WINE_foo=-9 ^>^> -2 & call :checkenvvars WINE_foo -1
1593set /a WINE_foo=-9 ^>^> 2 & call :checkenvvars WINE_foo -3
1594set /a WINE_foo=5 ^& 0 & call :checkenvvars WINE_foo 0
1595set /a WINE_foo=5 ^& 1 & call :checkenvvars WINE_foo 1
1596set /a WINE_foo=5 ^& 3 & call :checkenvvars WINE_foo 1
1597set /a WINE_foo=5 ^& 4 & call :checkenvvars WINE_foo 4
1598set /a WINE_foo=5 ^& 1 & call :checkenvvars WINE_foo 1
1599set /a WINE_foo=5 ^| 0 & call :checkenvvars WINE_foo 5
1600set /a WINE_foo=5 ^| 1 & call :checkenvvars WINE_foo 5
1601set /a WINE_foo=5 ^| 3 & call :checkenvvars WINE_foo 7
1602set /a WINE_foo=5 ^| 4 & call :checkenvvars WINE_foo 5
1603set /a WINE_foo=5 ^| 1 & call :checkenvvars WINE_foo 5
1604set /a WINE_foo=5 ^^ 0 & call :checkenvvars WINE_foo 5
1605set /a WINE_foo=5 ^^ 1 & call :checkenvvars WINE_foo 4
1606set /a WINE_foo=5 ^^ 3 & call :checkenvvars WINE_foo 6
1607set /a WINE_foo=5 ^^ 4 & call :checkenvvars WINE_foo 1
1608set /a WINE_foo=5 ^^ 1 & call :checkenvvars WINE_foo 4
1609echo ------ precedence and grouping
1610set /a WINE_foo=4 + 2*3 & call :checkenvvars WINE_foo 10
1611set /a WINE_foo=(4+2)*3 & call :checkenvvars WINE_foo 18
1612set /a WINE_foo=4 * 3/5 & call :checkenvvars WINE_foo 2
1613set /a WINE_foo=(4 * 3)/5 & call :checkenvvars WINE_foo 2
1614set /a WINE_foo=4 * 5 %% 4 & call :checkenvvars WINE_foo 0
1615set /a WINE_foo=4 * (5 %% 4) & call :checkenvvars WINE_foo 4
1616set /a WINE_foo=3 %% (5 + 8 %% 3 ^^ 2) & call :checkenvvars WINE_foo 3
1617set /a WINE_foo=3 %% (5 + 8 %% 3 ^^ -2) & call :checkenvvars WINE_foo 3
1618echo ------ octal and hexadecimal
1619set /a WINE_foo=0xf + 3 & call :checkenvvars WINE_foo 18
1620set /a WINE_foo=0xF + 3 & call :checkenvvars WINE_foo 18
1621set /a WINE_foo=015 + 2 & call :checkenvvars WINE_foo 15
1622set /a WINE_foo=3, 8+3,0 & call :checkenvvars WINE_foo 3
1623echo ------ variables
1624set /a WINE_foo=WINE_bar=3, WINE_bar+1 & call :checkenvvars WINE_foo 3 WINE_bar 3
1625set /a WINE_foo=WINE_bar=3, WINE_bar+=1 & call :checkenvvars WINE_foo 3 WINE_bar 4
1626set /a WINE_foo=WINE_bar=3, WINE_baz=1, WINE_baz+=WINE_bar, WINE_baz & call :checkenvvars WINE_foo 3 WINE_bar 3 WINE_baz 4
1627set WINE_bar=3
1628set /a WINE_foo=WINE_bar*= WINE_bar & call :checkenvvars WINE_foo 9 WINE_bar 9
1629set /a WINE_foo=WINE_whateverNonExistingVar & call :checkenvvars WINE_foo 0
1630set WINE_bar=4
1631set /a WINE_foo=WINE_whateverNonExistingVar + WINE_bar & call :checkenvvars WINE_foo 4 WINE_bar 4
1632set WINE_bar=4
1633set /a WINE_foo=WINE_bar -= WINE_bar + 7 & call :checkenvvars WINE_foo -7 WINE_bar -7
1634set WINE_bar=-7
1635set /a WINE_foo=WINE_bar /= 3 + 2 & call :checkenvvars WINE_foo -1 WINE_bar -1
1636set /a WINE_foo=WINE_bar=5, WINE_bar %%=2 & call :checkenvvars WINE_foo 5 WINE_bar 1
1637set WINE_bar=1
1638set /a WINE_foo=WINE_bar ^<^<= 2 & call :checkenvvars WINE_foo 4 WINE_bar 4
1639set WINE_bar=4
1640set /a WINE_foo=WINE_bar ^>^>= 2 & call :checkenvvars WINE_foo 1 WINE_bar 1
1641set WINE_bar=1
1642set /a WINE_foo=WINE_bar ^&= 2 & call :checkenvvars WINE_foo 0 WINE_bar 0
1643set /a WINE_foo=WINE_bar=5, WINE_bar ^|= 2 & call :checkenvvars WINE_foo 5 WINE_bar 7
1644set /a WINE_foo=WINE_bar=5, WINE_bar ^^= 2 & call :checkenvvars WINE_foo 5 WINE_bar 7
1645set WINE_baz=4
1646set /a WINE_foo=WINE_bar=19, WINE_bar %%= 4 + (WINE_baz %%= 7) & call :checkenvvars WINE_foo 19 WINE_bar 3 WINE_baz 4
1647echo --- quotes
1648set /a WINE_foo=1
1649call :checkenvvars WINE_foo 1
1650set /a "WINE_foo=1"
1651call :checkenvvars WINE_foo 1
1652set /a WINE_foo=1,WINE_bar=2
1653call :checkenvvars WINE_foo 1 WINE_bar 2
1654set /a "WINE_foo=1,WINE_bar=2"
1655call :checkenvvars WINE_foo 1 WINE_bar 2
1656set /a "WINE_foo=1","WINE_bar=2"
1657call :checkenvvars WINE_foo 1 WINE_bar 2
1658set /a ""WINE_foo=1","WINE_bar=2""
1659call :checkenvvars WINE_foo 1 WINE_bar 2
1660set /a WINE_foo=1,WINE_bar=2,WINE_baz=3
1661call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3
1662set /a "WINE_foo=1,WINE_bar=2,WINE_baz=3"
1663call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3
1664set /a "WINE_foo=1","WINE_bar=2","WINE_baz=3"
1665call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3
1666set /a ""WINE_foo=1","WINE_bar=2","WINE_baz=3""
1667call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3
1668set /a ""WINE_foo=1","WINE_bar=2"","WINE_baz=3"
1669call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3
1670set /a """"""WINE_foo=1""""""
1671call :checkenvvars WINE_foo 1
1672set /a """"""WINE_foo=1","WINE_bar=5""","WINE_baz=2""
1673call :checkenvvars WINE_foo 1 WINE_bar 5 WINE_baz 2
1674set /a WINE_foo="3"+"4"+"5+6"
1675call :checkenvvars WINE_foo 18
1676set WINE_foo=3
1677set /a WINE_bar="WINE_""foo"+4
1678call :checkenvvars WINE_foo 3 WINE_bar 7
1679echo --- whitespace are ignored between double char operators
1680set WINE_foo=4
1681set WINE_bar=5
1682set /a     WINE_foo   +    = 6
1683set /a     WINE_bar     *    = WINE_foo
1684call :checkenvvars WINE_foo 10 WINE_bar 50
1685set WINE_foo=4
1686set WINE_bar=5
1687set /a     WINE_foo   +    = "6  < < 7"
1688set /a     WINE_bar     *    = WINE_foo  +  WINE_foo
1689call :checkenvvars WINE_foo 772 WINE_bar 7720
1690set /a     WINE_foo=6 7
1691set /a     WINE_ var1=8
1692set WINE_foo=
1693echo --- invalid operator sequence
1694set WINE_foo=4
1695set /a =4
1696set /a *=4
1697set /a ^>=4"
1698set /a ^<=4"
1699set /a WINE_foo^>^<=4
1700echo %WINE_foo%
1701set /a WINE_foo^>^>^>=4
1702echo %WINE_foo%
1703echo ----- negative prefix
1704set /a WINE_foo=-1
1705call :checkenvvars WINE_foo -1
1706set /a WINE_foo=--1
1707call :checkenvvars WINE_foo 1
1708set /a WINE_foo=3--3
1709call :checkenvvars WINE_foo 6
1710set /a WINE_foo=3---3
1711call :checkenvvars WINE_foo 0
1712set /a WINE_foo=3----3
1713call :checkenvvars WINE_foo 6
1714set /a WINE_foo=-~1
1715call :checkenvvars WINE_foo 2
1716set /a WINE_foo=~-1
1717call :checkenvvars WINE_foo 0
1718set /a WINE_foo=3+-~1
1719call :checkenvvars WINE_foo 5
1720set /a WINE_foo=3+~-1
1721call :checkenvvars WINE_foo 3
1722echo ----- assignment tests involving the end destination
1723set WINE_foo=3
1724set /a WINE_foo+=3+(WINE_foo=4)
1725call :checkenvvars WINE_foo 11
1726set WINE_foo=2
1727set /a WINE_bar=3+(WINE_foo=6)
1728call :checkenvvars WINE_foo 6 WINE_bar 9
1729set WINE_foo=2
1730set /a WINE_bar=3+(WINE_foo=6,WINE_baz=7)
1731call :checkenvvars WINE_foo 6 WINE_bar 10 WINE_baz 7
1732set WINE_foo=2
1733set /a WINE_bar=WINE_foo=7
1734call :checkenvvars WINE_foo 7 WINE_bar 7
1735echo ----- equal precedence on stack
1736rem Unary - don't reduce if precedence is equal
1737set /a WINE_foo=!!1
1738call :checkenvvars WINE_foo 1
1739set /a WINE_foo=!!0
1740call :checkenvvars WINE_foo 0
1741set /a WINE_foo=~~1
1742call :checkenvvars WINE_foo 1
1743set /a WINE_foo=~~0
1744call :checkenvvars WINE_foo 0
1745set /a WINE_foo=--1
1746call :checkenvvars WINE_foo 1
1747set /a WINE_foo=+-1
1748call :checkenvvars WINE_foo -1
1749set /a WINE_foo=-+1
1750call :checkenvvars WINE_foo -1
1751set /a WINE_foo=++1
1752call :checkenvvars WINE_foo 1
1753set /a WINE_foo=!~1
1754call :checkenvvars WINE_foo 0
1755set /a WINE_foo=~!1
1756call :checkenvvars WINE_foo -1
1757set /a WINE_foo=!-1
1758call :checkenvvars WINE_foo 0
1759set /a WINE_foo=-!1
1760call :checkenvvars WINE_foo 0
1761set /a WINE_foo=!-0
1762call :checkenvvars WINE_foo 1
1763set /a WINE_foo=-!0
1764call :checkenvvars WINE_foo -1
1765rem Aritmatic - Reduce if precedence is equal
1766set /a WINE_foo=10*5/2
1767call :checkenvvars WINE_foo 25
1768set /a WINE_foo=5/2*10
1769call :checkenvvars WINE_foo 20
1770set /a WINE_foo=10/5/2
1771call :checkenvvars WINE_foo 1
1772set /a WINE_foo=5%%2*4
1773call :checkenvvars WINE_foo 4
1774set /a WINE_foo=10-5+2
1775call :checkenvvars WINE_foo 7
1776set /a WINE_foo=1^<^<4^>^>1
1777call :checkenvvars WINE_foo 8
1778rem Assignment - don't reduce if precedence is equal
1779set /a WINE_foo=5
1780set /a WINE_bar=WINE_foo=6
1781call :checkenvvars WINE_foo 6 WINE_bar 6
1782
1783echo --- for /F
1784mkdir foobar & cd foobar
1785echo ------ string argument
1786rem NT4 does not support usebackq
1787for /F %%i in ("a b c") do echo %%i
1788for /F %%i in (  "a b c"    ) do echo X%%iX
1789for /f usebackq %%i in ('a b c') do echo %%i>output_file
1790if not exist output_file (echo no output) else (type output_file & del output_file)
1791for /f usebackq %%i in (   'a b c'   ) do echo X%%iX>output_file
1792if not exist output_file (echo no output) else (type output_file & del output_file)
1793for /f %%i in ("a ") do echo %%i
1794for /f usebackq %%i in ('a ') do echo %%i>output_file
1795if not exist output_file (echo no output) else (type output_file & del output_file)
1796for /f %%i in ("a") do echo %%i
1797for /f usebackq %%i in ('a') do echo %%i>output_file
1798if not exist output_file (echo no output) else (type output_file & del output_file)
1799fOr /f %%i in (" a") do echo %%i
1800for /f usebackq %%i in (' a') do echo %%i>output_file
1801if not exist output_file (echo no output) else (type output_file & del output_file)
1802for /f %%i in (" a ") do echo %%i
1803for /f usebackq %%i in (' a ') do echo %%i>output_file
1804if not exist output_file (echo no output) else (type output_file & del output_file)
1805echo ------ fileset argument
1806echo --------- basic blank handling
1807echo a b c>foo
1808for /f %%i in (foo) do echo %%i
1809echo a >foo
1810for /f %%i in (foo) do echo %%i
1811echo a>foo
1812for /f %%i in (foo) do echo %%i
1813echo  a>foo
1814for /f %%i in (foo) do echo %%i
1815echo  a >foo
1816for /f %%i in (foo) do echo %%i
1817echo. > foo
1818for /f %%i in (foo) do echo %%i
1819echo. >> foo
1820echo b > foo
1821for /f %%i in (foo) do echo %%i
1822echo --------- multi-line with empty lines
1823echo a Z f> foo
1824echo. >> foo
1825echo.>> foo
1826echo b bC>> foo
1827echo c>> foo
1828echo. >> foo
1829for /f %%b in (foo) do echo %%b
1830echo --------- multiple files
1831echo q w > bar
1832echo.>> bar
1833echo kkk>>bar
1834for /f %%k in (foo bar) do echo %%k
1835for /f %%k in (bar foo) do echo %%k
1836echo ------ command argument
1837rem Not implemented on NT4, need to skip it as no way to get output otherwise
1838if "%CD%"=="" goto :SkipFORFcmdNT4
1839for /f %%i in ('echo.Passed1') do echo %%i
1840for /f "usebackq" %%i in (`echo.Passed2`) do echo %%i
1841for /f usebackq %%i in (`echo.Passed3`) do echo %%i
1842for /f "usebackq" %%i in (`"c:\windows\system32\cmd.exe" /C echo Passed4`) do echo %%i
1843for /f "usebackq" %%i in (`""c:\windows\system32\cmd.exe" /C echo Passed5"`) do echo %%i
1844for /f %%i in (  'echo.Passed6'  ) do echo %%i
1845for /f "usebackq" %%i in (   `echo.Passed7` ) do echo %%i
1846goto :ContinueFORF
1847:SkipFORFcmdNT4
1848for /l %%i in (1,1,7) do echo Missing functionality - Broken%%i
1849:ContinueFORF
1850rem FIXME: Rest not testable right now in wine: not implemented and would need
1851rem preliminary grep-like program implementation (e.g. like findstr or fc) even
1852rem for a simple todo_wine test
1853rem (for /f "usebackq" %%i in (`echo z a b`) do echo %%i) || echo not supported
1854rem (for /f usebackq %%i in (`echo z a b`) do echo %%i) || echo not supported
1855echo ------ eol option
1856if "%CD%"=="" goto :SkipFORFeolNT4
1857echo Line one>foo
1858echo and Line two>>foo
1859echo Line three>>foo
1860for /f "eol=L" %%i in (foo) do echo %%i
1861for /f "eol=a" %%i in (foo) do echo %%i
1862del foo
1863goto :ContinueFORFeol
1864:SkipFORFeolNT4
1865for /l %%i in (1,1,3) do echo Broken NT4 functionality%%i
1866:ContinueFORFeol
1867for /f "eol=@" %%i in ("    ad") do echo %%i
1868for /f "eol=@" %%i in (" z@y") do echo %%i
1869for /f "eol=|" %%i in ("a|d") do echo %%i
1870for /f "eol=@" %%i in ("@y") do echo %%i > output_file
1871if not exist output_file (echo no output) else (del output_file)
1872for /f "eol==" %%i in ("=y") do echo %%i > output_file
1873if not exist output_file (echo no output) else (del output_file)
1874echo ------ delims option
1875for /f "delims=|" %%i in ("a|d") do echo %%i
1876for /f "delims=|" %%i in ("a |d") do echo %%i
1877for /f "delims=|" %%i in ("a d|") do echo %%i
1878for /f "delims=| " %%i in ("a d|") do echo %%i
1879for /f "delims==" %%i in ("C r=d|") do echo %%i
1880for /f "delims=" %%i in ("foo bar baz") do echo %%i
1881for /f "delims=" %%i in ("c:\foo bar baz\..") do echo %%~fi
1882echo ------ skip option
1883echo a > foo
1884echo b >> foo
1885echo c >> foo
1886for /f "skip=2" %%i in (foo) do echo %%i
1887for /f "skip=3" %%i in (foo) do echo %%i > output_file
1888if not exist output_file (echo no output) else (del output_file)
1889for /f "skip=4" %%i in (foo) do echo %%i > output_file
1890if not exist output_file (echo no output) else (del output_file)
1891for /f "skip=02" %%i in (foo) do echo %%i
1892for /f "skip=0x2" %%i in (foo) do echo %%i
1893for /f "skip=1" %%i in ("skipme") do echo %%i > output_file
1894if not exist output_file (echo no output) else (del output_file)
1895echo ------ tokens= option
1896rem Basic
1897for /f %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1898for /f "tokens=2" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1899for /f "tokens=1,3,5-7" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1900rem Show * means the rest
1901for /f "tokens=1,5*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1902for /f "tokens=6,9*" %%i in ("a b c d e f g h i j k l m n o p q r s t u v w x y z") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1903rem Show * means the rest (not tokenized and rebuilt)
1904for /f "tokens=6,9*" %%i in ("a b c d e f g h i j k l m  n;;==  o p q r s t u v w x y z") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1905rem Order is irrelevant
1906for /f "tokens=1,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1907for /f "tokens=3,2,1*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1908rem Duplicates are ignored
1909for /f "tokens=1,2,1*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1910rem Large tokens are allowed
1911for /f "tokens=25,1,5*" %%i in ("a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1912rem Show tokens blanked in advance regardless of uniqueness of requested tokens
1913for /f "tokens=1,1,1,2*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1914for /f "tokens=1-2,1-2,1-2" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1915rem Show No wrapping from z to A BUT wrapping sort of occurs Z to a occurs
1916for /f "tokens=1-20" %%u in ("a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z") do echo u=%%u v=%%v w=%%w x=%%x y=%%y z=%%z A=%%A a=%%a
1917for /f "tokens=1-20" %%U in ("a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z") do echo U=%%U V=%%V W=%%W X=%%X Y=%%Y Z=%%Z A=%%A a=%%a
1918rem Show negative ranges have no effect
1919for /f "tokens=1-3,5" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1920for /f "tokens=3-1,5" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o
1921rem Show duplicates stop * from working
1922for /f "tokens=1,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1923for /f "tokens=1,1,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1924for /f "tokens=2,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1925for /f "tokens=3,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
1926rem Special case tokens=* or tokens=n,*
1927echo 3.14>testfile
1928FOR /F "tokens=*"  %%A IN (testfile) DO @echo 1:%%A,%%B
1929FOR /F "tokens=1*" %%A IN (testfile) DO @echo 2:%%A,%%B
1930FOR /F "tokens=2*" %%A IN (testfile) DO @echo 3:%%A,%%B
1931FOR /F "tokens=1,* delims=." %%A IN (testfile) DO @echo 4:%%A,%%B
1932del testfile
1933cd ..
1934rd /s/q foobar
1935echo ------ parameter splitting
1936echo forFParameterSplittingFunc "myparam1=myvalue1 myparam2=myparam2" mytest> foo
1937for /f "tokens=1 delims=;" %%i in (foo) do (call :%%i)
1938del foo
1939for /f "tokens=1 delims=;" %%i in ("forFParameterSplittingFunc "myparam1^=myvalue1 myparam2^=myparam2" mytest") do (call :%%i)
1940goto :forFParameterSplittingEnd
1941:forFParameterSplittingFunc
1942echo %~0 %~1 %~2 %~3 %~4 %~5
1943goto :eof
1944:forFParameterSplittingEnd
1945echo 3.14>testfile
1946FOR /F "delims=. tokens=*"  %%A IN (testfile) DO @echo 4:%%A,%%B
1947FOR /F "delims=. tokens=1*" %%A IN (testfile) DO @echo 5:%%A,%%B
1948FOR /F "delims=. tokens=2*" %%A IN (testfile) DO @echo 6:%%A,%%B
1949FOR /F "delims=. tokens=3*" %%A IN (testfile) DO @echo 7:%%A,%%B
1950del testfile
1951
1952echo ------------ Testing del ------------
1953echo abc > file
1954echo deleting 'file'
1955del file
1956if errorlevel 0 (
1957    echo errorlevel is 0, good
1958) else (
1959    echo unexpected errorlevel, got %errorlevel%
1960)
1961if not exist file (
1962    echo successfully deleted 'file'
1963) else (
1964    echo error deleting 'file'
1965)
1966echo attempting to delete 'file', even though it is not present
1967del file
1968if errorlevel 0 (
1969    echo errorlevel is 0, good
1970) else (
1971    echo unexpected errorlevel, got %errorlevel%
1972)
1973
1974echo ------------ Testing del /a ------------
1975del /f/q *.test > nul
1976echo r > r.test
1977attrib +r r.test
1978echo not-r > not-r.test
1979
1980if not exist not-r.test echo not-r.test not found before delete, bad
1981del /a:-r *.test
1982if not exist not-r.test echo not-r.test not found after delete, good
1983
1984if not exist r.test echo r.test not found before delete, bad
1985if exist r.test echo r.test found before delete, good
1986del /a:r *.test
1987if not exist r.test echo r.test not found after delete, good
1988if exist r.test echo r.test found after delete, bad
1989
1990echo ------------ Testing del /q ------------
1991mkdir del_q_dir
1992cd del_q_dir
1993echo abc > file1
1994echo abc > file2.dat
1995rem If /q doesn't work, cmd will prompt and the test case should hang
1996del /q * > nul
1997for %%a in (1 2.dat) do if exist file%%a echo del /q * failed on file%%a
1998for %%a in (1 2.dat) do if not exist file%%a echo del /q * succeeded on file%%a
1999cd ..
2000rmdir del_q_dir
2001
2002echo ------------ Testing del /s ------------
2003mkdir "foo bar"
2004cd "foo bar"
2005mkdir "foo:"
2006echo hi > file1.dat
2007echo there > file2.dat
2008echo bub > file3.dat
2009echo bye > "file with spaces.dat"
2010cd ..
2011del /s file1.dat > nul
2012del file2.dat /s > nul
2013del "file3.dat" /s > nul
2014del "file with spaces.dat" /s > nul
2015cd "foo bar"
2016for %%f in (1 2 3) do if exist file%%f.dat echo Del /s failed on file%%f
2017for %%f in (1 2 3) do if exist file%%f.dat del file%%f.dat
2018if exist "file with spaces.dat" echo Del /s failed on "file with spaces.dat"
2019if exist "file with spaces.dat" del "file with spaces.dat"
2020rmdir "foo:"
2021cd ..
2022rmdir "foo bar"
2023
2024echo ------------ Testing rename ------------
2025mkdir foobar & cd foobar
2026echo --- ren and rename are synonymous
2027echo > foo
2028rename foo bar
2029if exist foo echo foo should be renamed!
2030if exist bar echo foo renamed to bar
2031ren bar foo
2032if exist bar echo bar should be renamed!
2033if exist foo echo bar renamed to foo
2034echo --- name collision
2035echo foo>foo
2036echo bar>bar
2037ren foo bar 2> nul
2038type foo
2039type bar
2040rem no-op
2041ren foo foo
2042mkdir baz
2043ren foo baz\abc
2044echo --- rename read-only files
2045echo > file1
2046attrib +r file1
2047ren file1 file2
2048if not exist file1 (
2049    if exist file2 (
2050        echo read-only file renamed
2051    )
2052) else (
2053    echo read-only file not renamed!
2054)
2055echo --- rename directories
2056mkdir rep1
2057ren rep1 rep2
2058if not exist rep1 (
2059    if exist rep2 (
2060        echo dir renamed
2061    )
2062)
2063attrib +r rep2
2064ren rep2 rep1
2065if not exist rep2 (
2066    if exist rep1 (
2067        echo read-only dir renamed
2068    )
2069)
2070echo --- rename in other directory
2071if not exist baz\abc (
2072    echo rename impossible in other directory
2073    if exist foo echo original file still present
2074) else (
2075    echo shouldn't rename in other directory!
2076    if not exist foo echo original file not present anymore
2077)
2078cd .. & rd /s/q foobar
2079
2080echo ------------ Testing move ------------
2081mkdir foobar & cd foobar
2082echo --- file move
2083echo >foo
2084move foo bar > nul 2>&1
2085if not exist foo (
2086    if exist bar (
2087        echo file move succeeded
2088    )
2089)
2090echo bar>bar
2091echo baz> baz
2092move /Y bar baz > nul 2>&1
2093if not exist bar (
2094    if exist baz (
2095        echo file move with overwrite succeeded
2096    )
2097) else (
2098    echo file overwrite impossible!
2099    del bar
2100)
2101type baz
2102
2103attrib +r baz
2104move baz bazro > nul 2>&1
2105if not exist baz (
2106    if exist bazro (
2107        echo read-only files are moveable
2108        move bazro baz > nul 2>&1
2109    )
2110) else (
2111    echo read-only file not moved!
2112)
2113attrib -r baz
2114mkdir rep
2115move baz rep > nul 2>&1
2116if not exist baz (
2117    if exist rep\baz (
2118        echo file moved in subdirectory
2119    )
2120)
2121call :setError 0
2122move rep\baz . > nul 2>&1
2123move /Y baz baz > nul 2>&1
2124if errorlevel 1 (
2125    echo moving a file to itself should be a no-op!
2126) else (
2127    echo moving a file to itself is a no-op
2128)
2129echo ErrorLevel: %ErrorLevel%
2130call :setError 0
2131del baz
2132echo --- directory move
2133mkdir foo\bar
2134mkdir baz
2135echo baz2>baz\baz2
2136move baz foo\bar > nul 2>&1
2137if not exist baz (
2138    if exist foo\bar\baz\baz2 (
2139        echo simple directory move succeeded
2140    )
2141)
2142call :setError 0
2143mkdir baz
2144move baz baz > nul 2>&1
2145echo moving a directory to itself gives error; errlevel %ErrorLevel%
2146echo ------ dir in dir move
2147rd /s/q foo
2148mkdir foo bar
2149echo foo2>foo\foo2
2150echo bar2>bar\bar2
2151move foo bar > nul 2>&1
2152if not exist foo (
2153    if exist bar (
2154        dir /b /ad bar
2155        dir /b /a-d bar
2156        dir /b bar\foo
2157    )
2158)
2159cd .. & rd /s/q foobar
2160
2161echo ------------ Testing mkdir ------------
2162call :setError 0
2163echo --- md and mkdir are synonymous
2164mkdir foobar
2165echo %ErrorLevel%
2166rmdir foobar
2167md foobar
2168echo %ErrorLevel%
2169rmdir foobar
2170echo --- creating an already existing directory/file must fail
2171mkdir foobar
2172md foobar
2173echo %ErrorLevel%
2174rmdir foobar
2175echo > foobar
2176mkdir foobar
2177echo %ErrorLevel%
2178del foobar
2179echo --- multilevel path creation
2180mkdir foo
2181echo %ErrorLevel%
2182mkdir foo\bar\baz
2183echo %ErrorLevel%
2184cd foo
2185echo %ErrorLevel%
2186cd bar
2187echo %ErrorLevel%
2188cd baz
2189echo %ErrorLevel%
2190echo > ..\..\bar2
2191mkdir ..\..\..\foo\bar2
2192echo %ErrorLevel%
2193del ..\..\bar2
2194mkdir ..\..\..\foo\bar2
2195echo %ErrorLevel%
2196rmdir ..\..\..\foo\bar2
2197cd ..
2198rmdir baz
2199cd ..
2200rmdir bar
2201cd ..
2202rmdir foo
2203echo %ErrorLevel%
2204echo --- trailing backslashes
2205mkdir foo\\\\
2206echo %ErrorLevel%
2207if exist foo (rmdir foo & echo dir created
2208) else ( echo dir not created )
2209echo %ErrorLevel%
2210echo --- invalid chars
2211mkdir ?
2212echo mkdir ? gives errorlevel %ErrorLevel%
2213call :setError 0
2214mkdir ?\foo
2215echo mkdir ?\foo gives errorlevel %ErrorLevel%
2216call :setError 0
2217mkdir foo\?
2218echo mkdir foo\? gives errorlevel %ErrorLevel%
2219if exist foo (rmdir foo & echo ok, foo created
2220) else ( echo foo not created )
2221call :setError 0
2222mkdir foo\bar\?
2223echo mkdir foo\bar\? gives errorlevel %ErrorLevel%
2224call :setError 0
2225if not exist foo (
2226    echo bad, foo not created
2227) else (
2228    cd foo
2229    if exist bar (
2230        echo ok, foo\bar created
2231        rmdir bar
2232    )
2233    cd ..
2234    rmdir foo
2235)
2236echo --- multiple directories at once
2237mkdir foobaz & cd foobaz
2238mkdir foo bar\baz foobar "bazbaz" .\"zabzab"
2239if exist foo (echo foo created) else echo foo not created!
2240if exist bar (echo bar created) else echo bar not created!
2241if exist foobar (echo foobar created) else echo foobar not created!
2242if exist bar\baz (echo bar\baz created) else echo bar\baz not created!
2243if exist bazbaz (echo bazbaz created) else echo bazbaz not created!
2244if exist zabzab (echo zabzab created) else echo zabzab not created!
2245cd .. & rd /s/q foobaz
2246call :setError 0
2247mkdir foo\*
2248echo mkdir foo\* errorlevel %ErrorLevel%
2249if exist foo (rmdir foo & echo ok, foo created
2250) else ( echo bad, foo not created )
2251
2252echo ------------ Testing rmdir ------------
2253call :setError 0
2254rem rd and rmdir are synonymous
2255mkdir foobar
2256rmdir foobar
2257echo %ErrorLevel%
2258if not exist foobar echo dir removed
2259mkdir foobar
2260rd foobar
2261echo %ErrorLevel%
2262if not exist foobar echo dir removed
2263rem Removing nonexistent directory
2264rmdir foobar
2265echo %ErrorLevel%
2266rem Removing single-level directories
2267echo > foo
2268rmdir foo
2269echo %ErrorLevel%
2270if exist foo echo file not removed
2271del foo
2272mkdir foo
2273echo > foo\bar
2274rmdir foo
2275echo %ErrorLevel%
2276if exist foo echo non-empty dir not removed
2277del foo\bar
2278mkdir foo\bar
2279rmdir foo
2280echo %ErrorLevel%
2281if exist foo echo non-empty dir not removed
2282rmdir foo\bar
2283rmdir foo
2284rem Recursive rmdir
2285mkdir foo\bar\baz
2286rmdir /s /Q foo
2287if not exist foo (
2288    echo recursive rmdir succeeded
2289) else (
2290    rd foo\bar\baz
2291    rd foo\bar
2292    rd foo
2293)
2294mkdir foo\bar\baz
2295echo foo > foo\bar\brol
2296rmdir /s /Q foo 2>&1
2297if not exist foo (
2298    echo recursive rmdir succeeded
2299) else (
2300    rd foo\bar\baz
2301    del foo\bar\brol
2302    rd foo\bar
2303    rd foo
2304)
2305rem multiples directories at once
2306mkdir foobaz & cd foobaz
2307mkdir foo
2308mkdir bar\baz
2309mkdir foobar
2310rd /s/q foo bar foobar
2311if not exist foo (echo foo removed) else echo foo not removed!
2312if not exist bar (echo bar removed) else echo bar not removed!
2313if not exist foobar (echo foobar removed) else echo foobar not removed!
2314if not exist bar\baz (echo bar\baz removed) else echo bar\baz not removed!
2315cd .. & rd /s/q foobaz
2316
2317echo ------------ Testing pushd/popd ------------
2318cd
2319echo --- popd is no-op when dir stack is empty
2320popd
2321cd
2322echo --- pushing non-existing dir
2323pushd foobar
2324cd
2325echo --- basic behaviour
2326mkdir foobar\baz
2327pushd foobar
2328cd
2329popd
2330cd
2331pushd foobar
2332pushd baz
2333cd
2334popd
2335cd
2336pushd baz
2337popd
2338cd
2339popd
2340cd
2341pushd .
2342cd foobar\baz
2343pushd ..
2344cd
2345popd
2346popd
2347cd
2348rd /s/q foobar
2349
2350echo ------------ Testing attrib ------------
2351rem FIXME Add tests for archive, hidden and system attributes + mixed attributes modifications
2352mkdir foobar & cd foobar
2353echo foo original contents> foo
2354attrib foo
2355echo > bar
2356echo --- read-only attribute
2357rem Read-only files cannot be altered or deleted, unless forced
2358attrib +R foo
2359attrib foo
2360dir /Ar /B
2361echo bar>> foo
2362type foo
2363del foo > NUL 2>&1
2364if exist foo (
2365    echo Read-only file not deleted
2366) else (
2367    echo Should not delete read-only file!
2368)
2369del /F foo
2370if not exist foo (
2371    echo Read-only file forcibly deleted
2372) else (
2373    echo Should delete read-only file with del /F!
2374    attrib -r foo
2375    del foo
2376)
2377cd .. & rd /s/q foobar
2378echo --- recursive behaviour
2379mkdir foobar\baz & cd foobar
2380echo > level1
2381echo > whatever
2382echo > baz\level2
2383attrib baz\level2
2384cd ..
2385attrib +R l*vel? /S > nul 2>&1
2386cd foobar
2387attrib level1
2388attrib baz\level2
2389echo > bar
2390attrib bar
2391cd .. & rd /s/q foobar
2392echo --- folders processing
2393mkdir foobar
2394attrib foobar
2395cd foobar
2396mkdir baz
2397echo toto> baz\toto
2398attrib +r baz /s /d > nul 2>&1
2399attrib baz
2400attrib baz\toto
2401echo lulu>>baz\toto
2402type baz\toto
2403echo > baz\lala
2404rem Oddly windows allows file creation in a read-only directory...
2405if exist baz\lala (echo file created in read-only dir) else echo file not created
2406cd .. & rd /s/q foobar
2407
2408echo ------------ Testing assoc ------------
2409rem Modifying associations requires some privileges...
2410net session >nul 2>&1
2411if errorlevel 1 goto :SkipAssoc
2412
2413rem FIXME Can't test error messages in the current test system, so we have to use some kludges
2414rem FIXME Revise once || conditional execution is fixed
2415mkdir foobar & cd foobar
2416echo --- setting association
2417assoc .foo > baz
2418type baz
2419echo ---
2420
2421assoc .foo=bar
2422assoc .foo
2423
2424rem association set system-wide
2425echo @echo off> tmp.cmd
2426echo echo +++>> tmp.cmd
2427echo assoc .foo>> tmp.cmd
2428cmd /c tmp.cmd
2429
2430echo --- resetting association
2431assoc .foo=
2432assoc .foo > baz
2433type baz
2434echo ---
2435
2436rem association removal set system-wide
2437cmd /c tmp.cmd > baz
2438type baz
2439echo ---
2440cd .. & rd /s/q foobar
2441goto ContinueFType
2442:SkipAssoc
2443echo --- setting association
2444echo ---
2445echo .foo=bar
2446echo .foo=bar
2447echo +++
2448echo .foo=bar
2449echo --- resetting association
2450echo ---
2451echo +++
2452echo ---
2453
2454
2455:ContinueFType
2456echo ------------ Testing ftype ------------
2457rem Modifying associations requires some privileges...
2458net session >nul 2>&1
2459if errorlevel 1 goto :SkipFType
2460rem FIXME Can't test error messages in the current test system, so we have to use some kludges
2461rem FIXME Revise once || conditional execution is fixed
2462mkdir foobar & cd foobar
2463echo --- setting association
2464ftype footype> baz
2465type baz
2466echo ---
2467
2468ftype footype=foo_opencmd
2469assoc .foo=footype
2470ftype footype
2471
2472rem association set system-wide
2473echo @echo off> tmp.cmd
2474echo echo +++>> tmp.cmd
2475echo ftype footype>> tmp.cmd
2476cmd /c tmp.cmd
2477
2478echo --- resetting association
2479assoc .foo=
2480
2481rem Removing a file type association doesn't work on XP due to a bug, so a workaround is needed
2482setlocal EnableDelayedExpansion
2483set WINE_FOO=original value
2484ftype footype=
2485ftype footype > baz
2486for /F %%i in ('type baz') do (set WINE_FOO=buggyXP)
2487rem Resetting actually works on wine/NT4, but is reported as failing due to the peculiar test (and non-support for EnabledDelayedExpansion)
2488rem FIXME Revisit once a grep-like program like ftype is implemented
2489rem (e.g. to check baz's size using dir /b instead)
2490echo !WINE_FOO!
2491
2492rem cleanup registry
2493echo REGEDIT4> regCleanup.reg
2494echo.>> regCleanup.reg
2495echo [-HKEY_CLASSES_ROOT\footype]>> regCleanup.reg
2496regedit /s regCleanup.reg
2497set WINE_FOO=
2498endlocal
2499cd .. & rd /s/q foobar
2500goto ContinueCall
2501:SkipFType
2502echo --- setting association
2503echo ---
2504echo footype=foo_opencmd
2505echo .foo=footype
2506echo footype=foo_opencmd
2507echo +++
2508echo footype=foo_opencmd
2509echo --- resetting association
2510echo original value
2511
2512:ContinueCall
2513echo ------------ Testing CALL ------------
2514mkdir foobar & cd foobar
2515echo --- external script
2516echo echo foo %%1> foo.cmd
2517call foo
2518call foo.cmd 8
2519echo echo %%1 %%2 > foo.cmd
2520call foo.cmd foo
2521call foo.cmd foo bar
2522call foo.cmd foo ""
2523call foo.cmd "" bar
2524call foo.cmd foo ''
2525call foo.cmd '' bar
2526del foo.cmd
2527
2528echo --- internal routines
2529call :testRoutine :testRoutine
2530goto :endTestRoutine
2531:testRoutine
2532echo bar %1
2533goto :eof
2534:endTestRoutine
2535
2536call :testRoutineArgs foo
2537call :testRoutineArgs foo bar
2538call :testRoutineArgs foo ""
2539call :testRoutineArgs ""  bar
2540call :testRoutineArgs foo ''
2541call :testRoutineArgs ''  bar
2542goto :endTestRoutineArgs
2543:testRoutineArgs
2544echo %1 %2
2545goto :eof
2546:endTestRoutineArgs
2547
2548echo --- with builtins
2549call mkdir foo
2550echo %ErrorLevel%
2551if exist foo (echo foo created) else echo foo should exist!
2552rmdir foo
2553set WINE_FOOBAZ_VAR=foobaz
2554call echo Should expand %WINE_FOOBAZ_VAR%
2555set WINE_FOOBAZ_VAR=
2556echo>batfile
2557call dir /b
2558echo>robinfile
2559if 1==1 call del batfile
2560dir /b
2561if exist batfile echo batfile shouldn't exist
2562rem ... but not for 'if' or 'for'
2563call if 1==1 echo bar 2> nul
2564echo %ErrorLevel%
2565call :setError 0
2566call for %%i in (foo bar baz) do echo %%i 2> nul
2567echo %ErrorLevel%
2568rem First look for programs in the path before trying a builtin
2569echo echo non-builtin dir> dir.cmd
2570call dir /b
2571del dir.cmd
2572rem The below line equates to call (, which does nothing, then the
2573rem subsequent lines are executed.
2574call (
2575  echo Line one
2576  echo Line two
2577)
2578rem The below line equates to call if, which always fails, then the
2579rem subsequent lines are executed. Note cmd.exe swallows all lines
2580rem starting with )
2581call if 1==1 (
2582  echo Get if
2583) else (
2584  echo ... and else!
2585)
2586call call call echo passed
2587cd .. & rd /s/q foobar
2588
2589echo ------------ Testing SHIFT ------------
2590
2591call :shiftFun p1 p2 p3 p4 p5
2592goto :endShiftFun
2593
2594:shiftFun
2595echo '%1' '%2' '%3' '%4' '%5'
2596shift
2597echo '%1' '%2' '%3' '%4' '%5'
2598shift@tab@ /1
2599echo '%1' '%2' '%3' '%4' '%5'
2600shift /2
2601echo '%1' '%2' '%3' '%4' '%5'
2602shift /-1
2603echo '%1' '%2' '%3' '%4' '%5'
2604shift /0
2605echo '%1' '%2' '%3' '%4' '%5'
2606goto :eof
2607:endShiftFun
2608
2609echo ------------ Testing cmd invocation ------------
2610rem FIXME: only a stub ATM
2611echo --- a batch file can delete itself
2612echo del foo.cmd>foo.cmd
2613cmd /q /c foo.cmd
2614if not exist foo.cmd (
2615    echo file correctly deleted
2616) else (
2617    echo file should be deleted!
2618    del foo.cmd
2619)
2620echo --- a batch file can alter itself
2621echo echo bar^>foo.cmd>foo.cmd
2622cmd /q /c foo.cmd > NUL 2>&1
2623if exist foo.cmd (
2624    type foo.cmd
2625    del foo.cmd
2626) else (
2627    echo file not created!
2628)
2629
2630echo ---------- Testing copy
2631md foobar2
2632cd foobar2
2633rem Note echo adds 0x0d 0x0a on the end of the line in the file
2634echo AAA> file1
2635echo BBBBBB> file2
2636echo CCCCCCCCC> file3
2637md dir1
2638goto :testcopy
2639
2640:CheckExist
2641if exist "%1" (
2642  echo Passed: Found expected %1
2643) else (
2644  echo Failed: Did not find expected %1
2645)
2646del /q "%1" >nul 2>&1
2647shift
2648if not "%1"=="" goto :CheckExist
2649goto :eof
2650
2651:CheckNotExist
2652if not exist "%1" (
2653  echo Passed: Did not find %1
2654) else (
2655  echo Failed: Unexpectedly found %1
2656  del /q "%1" >nul 2>&1
2657)
2658shift
2659if not "%1"=="" goto :CheckNotExist
2660goto :eof
2661
2662rem Note: No way to check file size on NT4 so skip the test
2663:CheckFileSize
2664if not exist "%1" (
2665  echo Failed: File missing when requested filesize check [%2]
2666  goto :ContinueFileSizeChecks
2667)
2668for %%i in (%1) do set WINE_filesize=%%~zi
2669if "%WINE_filesize%"=="%2" (
2670    echo Passed: file size check on %1 [%WINE_filesize%]
2671) else (
2672  if "%WINE_filesize%"=="%%~zi" (
2673    echo Skipping file size check on NT4
2674  ) else (
2675    echo Failed: file size check on %1 [%WINE_filesize% != %2]
2676  )
2677)
2678:ContinueFileSizeChecks
2679shift
2680shift
2681if not "%1"=="" goto :CheckFileSize
2682goto :eof
2683
2684:testcopy
2685
2686rem -----------------------
2687rem Simple single file copy
2688rem -----------------------
2689rem Simple single file copy, normally used syntax
2690copy file1 dummy.file >nul 2>&1
2691if errorlevel 1 echo Incorrect errorlevel
2692call :CheckExist dummy.file
2693
2694rem Simple single file copy, destination supplied as two forms of directory
2695copy file1 dir1 >nul 2>&1
2696if errorlevel 1 echo Incorrect errorlevel
2697call :CheckExist dir1\file1
2698
2699copy file1 dir1\ >nul 2>&1
2700if errorlevel 1 echo Incorrect errorlevel
2701call :CheckExist dir1\file1
2702
2703rem Simple single file copy, destination supplied as fully qualified destination
2704copy file1 dir1\file99 >nul 2>&1
2705if errorlevel 1 echo Incorrect errorlevel
2706call :CheckExist dir1\file99
2707
2708rem Simple single file copy, destination not supplied
2709cd dir1
2710copy ..\file1 >nul 2>&1
2711if errorlevel 1 echo Incorrect errorlevel
2712call :CheckExist file1
2713cd ..
2714
2715rem Simple single file copy, destination supplied as nonexistent directory
2716copy file1 dir2\ >nul 2>&1
2717if not errorlevel 1 echo Incorrect errorlevel
2718call :CheckNotExist dir2 dir2\file1
2719
2720rem -----------------------
2721rem Wildcarded copy
2722rem -----------------------
2723rem Simple single file copy, destination supplied as two forms of directory
2724copy file? dir1 >nul 2>&1
2725if errorlevel 1 echo Incorrect errorlevel
2726call :CheckExist dir1\file1 dir1\file2 dir1\file3
2727
2728copy file* dir1\ >nul 2>&1
2729if errorlevel 1 echo Incorrect errorlevel
2730call :CheckExist dir1\file1 dir1\file2 dir1\file3
2731
2732rem Simple single file copy, destination not supplied
2733cd dir1
2734copy ..\file*.* >nul 2>&1
2735if errorlevel 1 echo Incorrect errorlevel
2736call :CheckExist file1 file2 file3
2737cd ..
2738
2739rem Simple wildcarded file copy, destination supplied as nonexistent directory
2740copy file? dir2\ >nul 2>&1
2741if not errorlevel 1 echo Incorrect errorlevel
2742call :CheckNotExist dir2 dir2\file1 dir2\file2 dir2\file3
2743
2744rem ------------------------------------------------
2745rem Confirm overwrite works (cannot test prompting!)
2746rem ------------------------------------------------
2747copy file1 testfile >nul 2>&1
2748copy /y file2 testfile >nul 2>&1
2749call :CheckExist testfile
2750
2751rem ------------------------------------------------
2752rem Test concatenation
2753rem ------------------------------------------------
2754rem simple case, no wildcards
2755copy file1+file2 testfile >nul 2>&1
2756if errorlevel 1 echo Incorrect errorlevel
2757call :CheckExist testfile
2758
2759rem simple case, wildcards, no concatenation
2760copy file* testfile >nul 2>&1
2761if errorlevel 1 echo Incorrect errorlevel
2762call :CheckExist testfile
2763
2764rem simple case, wildcards, and concatenation
2765echo ddddd > fred
2766copy file*+fred testfile >nul 2>&1
2767if errorlevel 1 echo Incorrect errorlevel
2768call :CheckExist testfile
2769
2770rem simple case, wildcards, and concatenation
2771copy fred+file* testfile >nul 2>&1
2772if errorlevel 1 echo Incorrect errorlevel
2773call :CheckExist testfile
2774
2775rem Calculate destination name
2776copy fred+file* dir1 >nul 2>&1
2777if errorlevel 1 echo Incorrect errorlevel
2778call :CheckExist dir1\fred
2779
2780rem Calculate destination name
2781copy fred+file* dir1\ >nul 2>&1
2782if errorlevel 1 echo Incorrect errorlevel
2783call :CheckExist dir1\fred
2784
2785rem Calculate destination name (none supplied)
2786cd dir1
2787copy ..\fred+..\file* >nul 2>&1
2788if errorlevel 1 echo Incorrect errorlevel
2789call :CheckExist fred
2790
2791copy ..\fr*+..\file1  >nul 2>&1
2792if errorlevel 1 echo Incorrect errorlevel
2793call :CheckExist fred
2794cd ..
2795
2796rem ******************************************************************
2797rem ASCII and BINARY tests
2798rem Note: hard coded numbers deliberate because need to ensure whether
2799rem an additional EOF has been added or not. There is no way to handle
2800rem EOFs in batch, so assume if a single byte appears, it's an EOF!
2801rem ******************************************************************
2802
2803rem Confirm original sizes of file1,2,3
2804call :CheckFileSize file1 5 file2 8 file3 11
2805
2806cd dir1
2807
2808rem ----------------------------------------------
2809rem Show concatenation defaults copy to ascii mode
2810rem ----------------------------------------------
2811rem Simple default copy source to destination (should not append EOF 5)
2812copy ..\file1 file1_default >nul 2>&1
2813call :CheckFileSize file1_default 5
2814
2815rem Simple binary copy source to destination (should not append EOF 5)
2816copy /b ..\file1 file1_default2 >nul 2>&1
2817call :CheckFileSize file1_default2 5
2818
2819rem Simple ascii copy source to destination (should append EOF 5+1, 8+1, 11+1)
2820copy /a ..\file1 file1_plus_eof >nul 2>&1
2821call :CheckFileSize file1_plus_eof 6
2822copy /a ..\file2 file2_plus_eof >nul 2>&1
2823call :CheckFileSize file2_plus_eof 9
2824copy /a ..\file3 file3_plus_eof >nul 2>&1
2825call :CheckFileSize file3_plus_eof 12
2826
2827rem Concat 2 files, ascii mode - (only one EOF on the end 5+8+1)
2828copy /a ..\file1+..\file2 file12_plus_eof >nul 2>&1
2829call :CheckFileSize file12_plus_eof 14
2830
2831rem Concat 2 files, binary mode - (no EOF on the end 5+8)
2832copy /b ..\file1+..\file2 file12_no_eof >nul 2>&1
2833call :CheckFileSize file12_no_eof 13
2834
2835rem Concat 2 files, default mode - (one EOF on the end 5+8+1)
2836copy ..\file1+..\file2 file12_eof2 >nul 2>&1
2837call :CheckFileSize file12_eof2 14
2838
2839rem Test copying when destination is one of the sources.
2840rem Concat file1+file2+file3 into file1, should produce file1+file2+file3 = 24
2841copy /y ..\file? .\ >nul 2>&1
2842copy /y /b file1+file2+file3 file1 >nul 2>&1
2843call :CheckFileSize file1 24
2844
2845rem Concat file1+file2+file3 into file2, should produce file1+file3 = 16
2846copy /y ..\file? .\ >nul 2>&1
2847copy /y /b file1+file2+file3 file2 >nul 2>&1
2848call :CheckFileSize file2 16
2849
2850rem Concat file1+file2+file3 into file3, should produce file1+file2 = 13
2851copy /y ..\file? .\ >nul 2>&1
2852copy /y /b file1+file2+file3 file3 >nul 2>&1
2853call :CheckFileSize file3 13
2854
2855rem --------------------------------------------------------------
2856rem Show ascii source copy stops at first EOF, binary does the lot
2857rem --------------------------------------------------------------
2858copy file1_plus_eof /b file1_binary_srccopy /b >nul 2>&1
2859call :CheckFileSize file1_binary_srccopy 6
2860
2861copy file1_plus_eof /a file1_ascii_srccopy /b >nul 2>&1
2862call :CheckFileSize file1_ascii_srccopy 5
2863
2864rem --------------------------------------------------------------
2865rem Show results of concatenating files (ending in EOFs) and /a /b
2866rem --------------------------------------------------------------
2867
2868rem Default and ascii copy reads as ascii, stripping EOFs, so 6-1 + 9-1 + 12-1 + 1
2869copy file1_plus_eof+file2_plus_eof+file3_plus_eof file123_default_copy >nul 2>&1
2870call :CheckFileSize file123_default_copy 25
2871copy /a file1_plus_eof+file2_plus_eof+file3_plus_eof file123_ascii_copy >nul 2>&1
2872call :CheckFileSize file123_ascii_copy 25
2873
2874rem In binary mode, we get 3 eofs, so 6 + 9 + 12 = 27
2875copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_binary_copy >nul 2>&1
2876call :CheckFileSize file123_binary_copy 27
2877
2878rem We can select which we want the eofs from by postfixing it with /a or /b
2879rem so here have first and third with eof, second as ascii 6 + 9-1 + 12
2880copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy1 >nul 2>&1
2881call :CheckFileSize file123_mixed_copy1 26
2882
2883rem By postfixing the destination with /a, we ask for an ascii destination which appends EOF
2884rem so here have first and third with eof, second as ascii 6 + 9-1 + 12 + extra EOF
2885rem Note the delta between this and the previous one also shows that the destination
2886rem ascii/binary is inherited from the last /a or /b on the line
2887copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy2 /a >nul 2>&1
2888call :CheckFileSize file123_mixed_copy2 27
2889
2890rem so here have second with eof, first and third as ascii 6-1 + 9 + 12-1
2891rem Note the delta between the next two also shows that the destination ascii/binary is
2892rem inherited from the last /a or /b on the line, so the first has an extra EOF
2893copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy3 >nul 2>&1
2894call :CheckFileSize file123_mixed_copy3 26
2895copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy4 /b >nul 2>&1
2896call :CheckFileSize file123_mixed_copy4 25
2897
2898rem -------------------------------------------------------------------------------------------
2899rem This shows when concatenating, an ascii destination always adds on an EOF but when we
2900rem are not concatenating, it's a direct copy regardless of destination if being read as binary
2901rem -------------------------------------------------------------------------------------------
2902
2903rem All 3 have eof's, plus an extra = 6 + 9 + 12 + eof
2904copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_mixed_copy5 /a >nul 2>&1
2905call :CheckFileSize file123_mixed_copy5 28
2906
2907rem All 2 have eof's, plus an extra = 6 + 12 + eof
2908copy /b file1_plus_eof + file3_plus_eof file123_mixed_copy6 /a >nul 2>&1
2909call :CheckFileSize file123_mixed_copy6 19
2910
2911rem One file has EOF, but doesn't get an extra one, i.e. 6
2912copy /b file1_plus_eof file123_mixed_copy7 /a >nul 2>&1
2913call :CheckFileSize file123_mixed_copy7 6
2914
2915rem Syntax means concatenate so ascii destination kicks in
2916copy /b file1_plus_eof* file123_mixed_copy8 /a >nul 2>&1
2917call :CheckFileSize file123_mixed_copy8 7
2918
2919del *.* /q
2920cd ..
2921
2922rem ---------------------------------------
2923rem Error combinations
2924rem ---------------------------------------
2925rem Specify source directory but name is a file
2926call :setError 0
2927copy file1\ dir1\ >NUL 2>&1
2928if errorlevel 1 echo Passed: errorlevel invalid check 1
2929if not errorlevel 1 echo Failed: errorlevel invalid check 1
2930call :CheckNotExist dir1\file1
2931
2932rem Overwrite same file
2933call :setError 0
2934copy file1 file1 >NUL 2>&1
2935if errorlevel 1 echo Passed: errorlevel invalid check 2
2936if not errorlevel 1 echo Failed: errorlevel invalid check 2
2937
2938rem Supply same file identified as a directory
2939call :setError 0
2940copy file1 file1\ >NUL 2>&1
2941if errorlevel 1 echo Passed: errorlevel invalid check 3
2942if not errorlevel 1 echo Failed: errorlevel invalid check 3
2943
2944cd ..
2945rd foobar2 /s /q
2946
2947echo ------------ Testing setlocal/endlocal ------------
2948call :setError 0
2949rem Note: setlocal EnableDelayedExpansion already tested in the variable delayed expansion test section
2950mkdir foobar & cd foobar
2951echo --- enable/disable extensions
2952setlocal DisableEXTensions
2953echo ErrLev: %ErrorLevel%
2954endlocal
2955echo ErrLev: %ErrorLevel%
2956echo @echo off> tmp.cmd
2957echo echo ErrLev: %%ErrorLevel%%>> tmp.cmd
2958rem Enabled by default
2959cmd /C tmp.cmd
2960cmd /E:OfF /C tmp.cmd
2961cmd /e:oN /C tmp.cmd
2962
2963rem FIXME: creating file before setting envvar value to prevent parsing-time evaluation (due to EnableDelayedExpansion not being implemented/available yet)
2964echo --- setlocal with corresponding endlocal
2965rem %CD% does not work on NT4 so use the following workaround
2966for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi
2967echo @echo off> test.cmd
2968echo echo %%WINE_VAR%%>> test.cmd
2969echo setlocal>> test.cmd
2970echo set WINE_VAR=localval>> test.cmd
2971echo md foobar2>> test.cmd
2972echo cd foobar2>> test.cmd
2973echo echo %%WINE_VAR%%>> test.cmd
2974echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2975echo endlocal>> test.cmd
2976echo echo %%WINE_VAR%%>> test.cmd
2977echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2978set WINE_VAR=globalval
2979call test.cmd
2980echo %WINE_VAR%
2981for /d %%i in (.) do echo %%~dpnxi
2982cd /d %WINE_CURDIR%
2983rd foobar2
2984set WINE_VAR=
2985echo --- setlocal with no corresponding endlocal
2986echo @echo off> test.cmd
2987echo echo %%WINE_VAR%%>> test.cmd
2988echo setlocal>> test.cmd
2989echo set WINE_VAR=localval>> test.cmd
2990echo md foobar2>> test.cmd
2991echo cd foobar2>> test.cmd
2992echo echo %%WINE_VAR%%>> test.cmd
2993echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2994set WINE_VAR=globalval
2995rem %CD% does not work on NT4 so use the following workaround
2996for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi
2997call test.cmd
2998echo %WINE_VAR%
2999for /d %%i in (.) do echo %%~dpnxi
3000cd /d %WINE_CURDIR%
3001rd foobar2
3002set WINE_VAR=
3003echo --- setlocal within same batch program
3004set WINE_var1=one
3005set WINE_var2=
3006set WINE_var3=
3007rem %CD% does not work on NT4 so use the following workaround
3008for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi
3009setlocal
3010set WINE_var2=two
3011mkdir foobar2
3012cd foobar2
3013setlocal
3014set WINE_var3=three
3015if "%WINE_var1%"=="one" echo Var1 ok 1
3016if "%WINE_var2%"=="two" echo Var2 ok 2
3017if "%WINE_var3%"=="three" echo Var3 ok 3
3018for /d %%i in (.) do set WINE_curdir2=%%~dpnxi
3019if "%WINE_curdir2%"=="%WINE_CURDIR%\foobar2" echo Directory is ok 1
3020endlocal
3021if "%WINE_var1%"=="one" echo Var1 ok 1
3022if "%WINE_var2%"=="two" echo Var2 ok 2
3023if "%WINE_var3%"=="" echo Var3 ok 3
3024for /d %%i in (.) do set WINE_curdir2=%%~dpnxi
3025if "%WINE_curdir2%"=="%WINE_CURDIR%\foobar2" echo Directory is ok 2
3026endlocal
3027if "%WINE_var1%"=="one" echo Var1 ok 1
3028if "%WINE_var2%"=="" echo Var2 ok 2
3029if "%WINE_var3%"=="" echo Var3 ok 3
3030for /d %%i in (.) do set WINE_curdir2=%%~dpnxi
3031if "%WINE_curdir2%"=="%WINE_CURDIR%" echo Directory is ok 3
3032rd foobar2 /s /q
3033set WINE_var1=
3034
3035echo --- Mismatched set and end locals
3036mkdir foodir2 2>nul
3037mkdir foodir3 2>nul
3038mkdir foodir4 2>nul
3039rem %CD% does not work on NT4 so use the following workaround
3040for /d %%i in (.) do set WINE_curdir=%%~dpnxi
3041
3042echo @echo off> 2set1end.cmd
3043echo echo %%WINE_var%%>> 2set1end.cmd
3044echo setlocal>> 2set1end.cmd
3045echo set WINE_VAR=2set1endvalue1>> 2set1end.cmd
3046echo cd ..\foodir3>> 2set1end.cmd
3047echo setlocal>> 2set1end.cmd
3048echo set WINE_VAR=2set1endvalue2>> 2set1end.cmd
3049echo cd ..\foodir4>> 2set1end.cmd
3050echo endlocal>> 2set1end.cmd
3051echo echo %%WINE_var%%>> 2set1end.cmd
3052echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 2set1end.cmd
3053
3054echo @echo off> 1set2end.cmd
3055echo echo %%WINE_var%%>> 1set2end.cmd
3056echo setlocal>> 1set2end.cmd
3057echo set WINE_VAR=1set2endvalue1>> 1set2end.cmd
3058echo cd ..\foodir3>> 1set2end.cmd
3059echo endlocal>> 1set2end.cmd
3060echo echo %%WINE_var%%>> 1set2end.cmd
3061echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd
3062echo endlocal>> 1set2end.cmd
3063echo echo %%WINE_var%%>> 1set2end.cmd
3064echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd
3065
3066echo --- Extra setlocal in called batch
3067set WINE_VAR=value1
3068rem -- setlocal1 == this batch, should never be used inside a called routine
3069setlocal
3070set WINE_var=value2
3071cd foodir2
3072call "%WINE_CURDIR%\2set1end.cmd"
3073echo Finished:
3074echo %WINE_VAR%
3075for /d %%i in (.) do echo %%~dpnxi
3076endlocal
3077echo %WINE_VAR%
3078for /d %%i in (.) do echo %%~dpnxi
3079cd /d %WINE_CURDIR%
3080
3081echo --- Extra endlocal in called batch
3082set WINE_VAR=value1
3083rem -- setlocal1 == this batch, should never be used inside a called routine
3084setlocal
3085set WINE_var=value2
3086cd foodir2
3087call "%WINE_CURDIR%\1set2end.cmd"
3088echo Finished:
3089echo %WINE_VAR%
3090for /d %%i in (.) do echo %%~dpnxi
3091endlocal
3092echo %WINE_VAR%
3093for /d %%i in (.) do echo %%~dpnxi
3094cd /d %WINE_CURDIR%
3095
3096echo --- endlocal in called function rather than batch pgm is ineffective
3097@echo off
3098set WINE_var=1
3099set WINE_var2=1
3100setlocal
3101set WINE_var=2
3102call :endlocalroutine
3103echo %WINE_var%
3104endlocal
3105echo %WINE_var%
3106goto :endlocalfinished
3107:endlocalroutine
3108echo %WINE_var%
3109endlocal
3110echo %WINE_var%
3111setlocal
3112set WINE_var2=2
3113endlocal
3114echo %WINE_var2%
3115endlocal
3116echo %WINE_var%
3117echo %WINE_var2%
3118goto :eof
3119:endlocalfinished
3120echo %WINE_var%
3121
3122set WINE_var=
3123set WINE_var2=
3124cd .. & rd /q/s foobar
3125
3126echo ------------ Testing Errorlevel ------------
3127rem WARNING: Do *not* add tests using ErrorLevel after this section
3128should_not_exist 2> nul > nul
3129echo %ErrorLevel%
3130rem nt 4.0 doesn't really support a way of setting errorlevel, so this is weak
3131rem See http://www.robvanderwoude.com/exit.php
3132call :setError 1
3133echo %ErrorLevel%
3134if errorlevel 2 echo errorlevel too high, bad
3135if errorlevel 1 echo errorlevel just right, good
3136if errorlevel 01 echo errorlevel with leading zero just right, good
3137if errorlevel -1 echo errorlevel with negative number OK
3138if errorlevel 0x1 echo hexa should not be recognized!
3139if errorlevel 1a echo invalid error level recognized!
3140call :setError 0
3141echo abc%ErrorLevel%def
3142if errorlevel 1 echo errorlevel nonzero, bad
3143if not errorlevel 1 echo errorlevel zero, good
3144if not errorlevel 0x1 echo hexa should not be recognized!
3145if not errorlevel 1a echo invalid error level recognized!
3146rem Now verify that setting a real variable hides its magic variable
3147set errorlevel=7
3148echo %ErrorLevel% should be 7
3149if errorlevel 7 echo setting var worked too well, bad
3150call :setError 3
3151echo %ErrorLevel% should still be 7
3152
3153echo ------------ Testing GOTO ------------
3154if a==a goto dest1
3155echo FAILURE at dest 1
3156:dest1
3157echo goto with no leading space worked
3158if a==a goto :dest1b
3159echo FAILURE at dest 1b
3160:dest1b
3161echo goto with colon and no leading space worked
3162if b==b goto dest2
3163echo FAILURE at dest 2
3164 :dest2
3165echo goto with a leading space worked
3166if c==c goto dest3
3167echo FAILURE at dest 3
3168	:dest3
3169echo goto with a leading tab worked
3170if d==d goto dest4
3171echo FAILURE at dest 4
3172:dest4@space@
3173echo goto with a following space worked
3174if e==e goto dest5
3175echo FAILURE at dest 5
3176:dest5&& echo FAILURE
3177echo goto with following amphersands worked
3178
3179del failure.txt >nul 2>&1
3180if f==f goto dest6
3181echo FAILURE at dest 6
3182:dest6>FAILURE.TXT
3183if exist FAILURE.TXT echo FAILURE at dest 6 as file exists
3184echo goto with redirections worked
3185del FAILURE.TXT >nul 2>&1
3186
3187:: some text that is ignored | dir >cmd_output | another test
3188if exist cmd_output echo FAILURE at dest 6 as file exists
3189echo Ignoring double colons worked
3190del cmd_output >nul 2>&1
3191
3192rem goto a label which does not exist issues an error message and
3193rem acts the same as goto :EOF, and ensure ::label is never matched
3194del testgoto.bat >nul 2>&1
3195echo goto :dest7 ^>nul 2^>^&1 >> testgoto.bat
3196echo echo FAILURE at dest 7 - Should have not found label and issued an error plus ended the batch>> testgoto.bat
3197echo ::dest7>> testgoto.bat
3198echo echo FAILURE at dest 7 - Incorrectly went to label >> testgoto.bat
3199call testgoto.bat
3200del testgoto.bat >nul 2>&1
3201
3202del testgoto.bat >nul 2>&1
3203echo goto ::dest8 ^>nul 2^>^&1 >> testgoto.bat
3204echo echo FAILURE at dest 8 - Should have not found label and issued an error plus ended the batch>> testgoto.bat
3205echo ::dest8>> testgoto.bat
3206echo echo FAILURE at dest 8 - Incorrectly went to label >> testgoto.bat
3207call testgoto.bat
3208del testgoto.bat >nul 2>&1
3209
3210if g==g goto dest9
3211echo FAILURE at dest 9
3212:dest91
3213echo FAILURE at dest 91
3214@   :     dest9>rubbish
3215echo label with mixed whitespace and no echo worked
3216
3217if h==h goto :dest10:this is ignored
3218echo FAILURE at dest 10
3219:dest10:this is also ignored
3220echo Correctly ignored trailing information
3221
3222rem Testing which label is reached when there are many options
3223echo Begin:
3224set nextlabel=
3225call :sub
3226set nextlabel=middle
3227goto :sub
3228
3229:sub
3230echo ..First sub
3231if not "%nextlabel%"=="" goto :%nextlabel%
3232goto :EOF
3233
3234:sub
3235echo ..Second sub
3236if not "%nextlabel%"=="" goto :%nextlabel%
3237goto :EOF
3238
3239:middle
3240echo Middle:
3241set nextlabel=
3242call :sub
3243set nextlabel=nearend
3244goto :sub
3245
3246:sub
3247echo ..Third sub
3248if not "%nextlabel%"=="" goto :%nextlabel%
3249goto :EOF
3250
3251:nearend
3252echo Near end:
3253set nextlabel=
3254call :sub
3255set nextlabel=end
3256goto :sub
3257
3258:sub
3259echo ..Fourth sub
3260if not "%nextlabel%"=="" goto :%nextlabel%
3261goto :EOF
3262
3263:end
3264echo At end:
3265set nextlabel=
3266call :sub
3267set nextlabel=done
3268goto :sub
3269
3270:done
3271echo Finished
3272
3273echo ------------ Testing PATH ------------
3274set WINE_backup_path=%path%
3275set path=original
3276path
3277path try2
3278path
3279path=try3
3280path
3281set path=%WINE_backup_path%
3282set WINE_backup_path=
3283
3284echo ------------ Testing start /W ------------
3285echo start /W failed to wait>foobar.txt
3286start /W "" cmd /C "ping -n1 & echo start /W seems to really wait>foobar.txt"& type foobar.txt& del foobar.txt
3287
3288echo ------------ Testing changing the drive letter ----------
3289pushd C:\
3290
3291echo Normal:
3292call :setError 0
3293C:
3294if errorlevel 1 echo Normal drive change failed
3295
3296echo Normal+space
3297call :setError 0
3298C:@space@
3299if errorlevel 1 echo Normal+space drive change failed
3300
3301echo Normal+space+garbage
3302call :setError 0
3303C: garbage
3304if errorlevel 1 echo Normal+space+garbage drive change failed
3305
3306call :setError 0
3307echo Quoted should fail
3308"C:"
3309if not errorlevel 1 echo quoted drive change unexpectedly worked
3310
3311echo Normal+tab
3312call :setError 0
3313C:@tab@
3314if errorlevel 1 echo Normal+tab drive change failed
3315
3316echo Normal+tab+garbage
3317call :setError 0
3318C:@tab@garbagetab
3319if errorlevel 1 echo Normal+tab+garbage drive change failed
3320
3321popd
3322
3323echo ------------ Testing combined CALLs/GOTOs ------------
3324echo @echo off>foo.cmd
3325echo goto :eof>>foot.cmd
3326echo :eof>>foot.cmd
3327echo echo world>>foo.cmd
3328
3329echo @echo off>foot.cmd
3330echo echo cheball>>foot.cmd
3331echo.>>foot.cmd
3332echo call :bar>>foot.cmd
3333echo if "%%1"=="deleteMe" (del foot.cmd)>>foot.cmd
3334echo goto :eof>>foot.cmd
3335echo.>>foot.cmd
3336echo :bar>>foot.cmd
3337echo echo barbare>>foot.cmd
3338echo goto :eof>>foot.cmd
3339
3340call foo.cmd
3341call foot
3342call :bar
3343del foo.cmd
3344rem Script execution stops after the following line
3345foot deleteMe
3346call :foo
3347call :foot
3348goto :endFuns
3349
3350:foot
3351echo foot
3352
3353:foo
3354echo foo
3355goto :eof
3356
3357:endFuns
3358
3359:bar
3360echo bar
3361call :foo
3362
3363:baz
3364echo baz
3365goto :eof
3366
3367echo Final message is not output since earlier 'foot' processing stops script execution
3368echo Do NOT add any tests below this line
3369
3370echo ------------ Done, jumping to EOF -----------
3371goto :eof
3372rem Subroutine to set errorlevel and return
3373rem in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported
3374:setError
3375exit /B %1
3376rem This line runs under cmd in windows NT 4, but not in more modern versions.
3377