1@echo off 2setlocal enableextensions 3setlocal enabledelayedexpansion 4 5 6:: 7:: Tests for GOTO and CALL. 8:: 9 10 11:: GOTO/CALL jump to labels present forward to their call-point. Only when 12:: the label cannot be found forward, the search is then restarted from the 13:: beginning of the batch file onwards up to the original call-point. 14 15:: GOTO with a label parameter without ':' works. 16goto test_start 17 18:: Execution must never go there! 19:test_goto 20echo Unexpected GOTO jump^^! 21exit 22:test_call 23echo Unexpected CALL jump^^! 24goto :EOF 25 26 27:test_start 28 29:: Testing GOTO/CALL forwards. 30echo --------- Testing GOTO --------- 31goto :test_goto 32 33:do_test_call 34echo --------- Testing CALL within batch --------- 35call :test_call 36goto :continue 37 38:test_goto 39echo Test GOTO ok 40:: GOTO also understands '+' instead of ':' in its label parameter. 41goto +do_test_call 42 43:test_call 44echo Test CALL ok from %0 45:: We exit this CALL invocation 46goto :EOF 47 48 49:: 50:: Next suite of tests. 51:: 52 53:: GOTO label search algorithm ignores any whitespace between ':' 54:: and the label name, as well as leading and trailing whitespace. 55 :@tab@continue@space@@space@ 56 57 58:: Jumping to a label with escape carets. 59goto :la^^bel2 60 61:la^bel2 62echo Unexpected GOTO jump^^! 63:la^^bel2 64echo GOTO with escape caret worked 65 66 67:: Go to the next tests below. 68goto :continue 69 70 71:: 72:: Next suite of tests. 73:: 74:continue 75 76 77:: 78:: Extra GOTO syntax checks: separators in the label parameter 79:: 80 81:: Whitespace 82goto :testLbl1@tab@ignored 83:testLbl1 84echo Hi there^^! 85 86:: Colon 87goto :testLbl2:ignored 88:testLbl2 89echo Hi there^^! 90 91:: Plus sign 92goto :testLbl3+ignored 93:testLbl3 94echo Hi there^^! 95 96:: Comma 97goto :testLbl4,ignored 98:testLbl4 99echo Hi there^^! 100 101:: Semicolon 102goto :testLbl5;ignored 103:testLbl5 104echo Hi there^^! 105 106:: Equals 107goto :testLbl6;ignored 108:testLbl6 109echo Hi there^^! 110 111 112:: 113:: Testing :EOF support 114:: 115echo --------- Testing :EOF support --------- 116 117:: Use an auxiliary CMD file to test GOTO :EOF 118mkdir foobar && cd foobar 119 120:: GOTO :EOF is available only if commands extensions are enabled 121echo @echo off> tmp.cmd 122echo setlocal disableextensions>> tmp.cmd 123echo goto :eof>> tmp.cmd 124call :setError 0 125cmd /c tmp.cmd 126if %errorlevel% equ 0 (echo Unexpected: GOTO :EOF did not fail^^!) else echo OK 127 128:: GOTO :EOF is done only if the ":EOF" part is followed by whitespace or ends. 129:: The following two GOTO's fail because the labels cannot be found. 130echo @echo off> tmp.cmd 131echo setlocal enableextensions>> tmp.cmd 132echo goto :eof,lol>> tmp.cmd 133echo echo Batch continues^^!>> tmp.cmd 134call :setError 0 135cmd /c tmp.cmd 136if %errorlevel% equ 0 (echo Unexpected: GOTO :eof,lol did not fail^^!) else echo OK 137 138echo @echo off> tmp.cmd 139echo setlocal enableextensions>> tmp.cmd 140echo goto :eof:lol>> tmp.cmd 141echo echo Batch continues^^!>> tmp.cmd 142call :setError 0 143cmd /c tmp.cmd 144if %errorlevel% equ 0 (echo Unexpected: GOTO :eof:lol did not fail^^!) else echo OK 145 146:: GOTO :EOF expects at least one whitespace character before anything else. 147:: Not even '+',':' or other separators are allowed. 148echo @echo off> tmp.cmd 149echo setlocal enableextensions>> tmp.cmd 150echo goto :eof+lol>> tmp.cmd 151echo echo Batch continues^^!>> tmp.cmd 152call :setError 0 153cmd /c tmp.cmd 154if %errorlevel% equ 0 (echo Unexpected: GOTO :eof+lol did not fail^^!) else echo OK 155 156:: This GOTO :EOF works. 157echo @echo off> tmp.cmd 158echo setlocal enableextensions>> tmp.cmd 159echo goto :eof@tab@+lol>> tmp.cmd 160echo echo You should not see this^^!>> tmp.cmd 161call :setError 0 162cmd /c tmp.cmd 163if %errorlevel% neq 0 (echo Unexpected: GOTO :EOF did fail^^!) else echo OK 164 165 166:: Cleanup 167cd .. & rd /s/q foobar 168 169 170:: 171:: Testing GOTO/CALL from and to within parenthesized blocks. 172:: 173 174echo --------- Testing GOTO within block --------- 175(echo Block-test 1: Single-line& goto :block2 & echo Unexpected Block-test 1^^!) 176echo Unexpected echo 1^^! 177 178:block2 179( 180echo Block-test 2: Multi-line 181goto :block3 182echo Unexpected Block-test 2^^! 183) 184echo Unexpected echo 2-3^^! 185 186:test_call_block 187echo Test CALL in block OK from %0 188:: We exit this CALL invocation 189goto :EOF 190 191( 192:block3 193echo --------- Testing CALL within block --------- 194echo Block-test 3: CALL in block 195call :test_call_block 196echo CALL done 197) 198 199goto :block4 200echo Unexpected echo 4^^! 201( 202:block4 203echo Block-test 4 OK 204) 205 206 207:: 208:: Testing GOTO/CALL from within FOR and IF. 209:: This is a situation similar to the parenthesized blocks. 210:: See bug-report CORE-13713 211:: 212 213:: Testing CALL within FOR 214echo --------- Testing CALL within FOR --------- 215for /L %%A IN (0,1,3) DO ( 216 set Number=%%A 217 if %%A==2 call :out_of_loop_1 %%A 218 if %%A==2 (echo %%A IS equal to 2) else (echo %%A IS NOT equal to 2) 219) 220goto :continue_2 221:out_of_loop_1 222echo Out of FOR 1 CALL from %0, number is %1 223:: We exit this CALL invocation 224goto :EOF 225:continue_2 226 227 228:: Testing GOTO within FOR 229echo --------- Testing GOTO within FOR --------- 230for /L %%A IN (0,1,3) DO ( 231 set Number=%%A 232 if %%A==2 goto :out_of_loop_2 233 echo %%A IS NOT equal to 2 234) 235echo Unexpected FOR echo 2^^! 236:out_of_loop_2 237echo Out of FOR 2, number is %Number% 238 239 240 241:: 242:: Show how each different FOR-loop stops when a GOTO is encountered. 243:: 244echo --------- Testing FOR loop stopping with GOTO --------- 245 246:: FOR - Stops directly 247echo --- FOR 248@echo on 249for %%A in (1,2,3,4,5,6,7,8,9,10) do ( 250 set Number=%%A 251 if %%A==5 goto :out_of_loop_2a 252) 253echo Unexpected FOR echo 2a^^! 254:out_of_loop_2a 255echo Out of FOR 2a, number is %Number% 256@echo off 257 258 259:: FOR /R - Stops directly 260echo --- FOR /R 261 262:: Use auxiliary directoreis to test for /R 263mkdir foobar && cd foobar 264mkdir foo1 265mkdir foo2 266mkdir bar1 267 268@echo on 269for /r %%A in (1,2,3,4,5,6,7,8,9,10) do ( 270 set Number=%%~nA 271 if %%~nA==5 goto :out_of_loop_2b 272) 273echo Unexpected FOR echo 2b^^! 274:out_of_loop_2b 275echo Out of FOR 2b, number is %Number% 276@echo off 277 278:: Cleanup 279cd .. & rd /s/q foobar 280 281 282:: FOR /L - Does not stop directly. It continues looping until the end 283:: but does not execute its body code. This can cause problems e.g. for 284:: infinite loops "for /l %a in () do ( ... )" that are exited by EXIT /B, 285:: since the body code stops being executed, but the loop itself continues 286:: running forever. 287echo --- FOR /L 288@echo on 289for /l %%A in (1,1,10) do ( 290 set Number=%%A 291 if %%A==5 goto :out_of_loop_2c 292) 293echo Unexpected FOR echo 2c^^! 294:out_of_loop_2c 295echo Out of FOR 2c, number is %Number% 296@echo off 297 298 299:: FOR /F - Stops directly. 300echo --- FOR /F 301@echo on 302for %%T in ( "1:2:3" "4:5:6:7" "8:9:10" ) do ( 303 set "pc=%%~T" 304 for /f "delims=" %%A in (^"!pc::^=^ 305% New line % 306!^") do ( 307 308 set Number=%%A 309 if %%A==5 goto :out_of_loop_2d 310) 311) 312echo Unexpected FOR echo 2d^^! 313:out_of_loop_2d 314echo Out of FOR 2d, number is %Number% 315@echo off 316 317 318 319:: Testing CALL within IF 320echo --------- Testing CALL within IF --------- 321if 1==1 ( 322 call :out_of_if_1 123 323 echo Success IF echo 1 324) 325goto :continue_3 326:out_of_if_1 327echo Out of IF CALL from %0, number is %1 328:: We exit this CALL invocation 329goto :EOF 330:continue_3 331 332 333:: Testing GOTO within IF 334echo --------- Testing GOTO within IF --------- 335if 1==1 ( 336 goto :out_of_if_2 337 echo Unexpected IF echo 2a^^! 338) 339echo Unexpected IF echo 2b^^! 340:out_of_if_2 341echo Out of IF ok 342 343:: Same, but with line-continuation at the closing parenthesis of the IF block. 344if 1==1 ( 345:labelA 346 echo A 347) ^ 348else ( 349:labelB 350 echo B 351 goto :continue 352) 353:: We are jumping inside the IF, whose block will be interpreted as 354:: separate commands; thus we will also run the :labelB block as well. 355goto :labelA 356 357 358:: 359:: Next suite of tests. 360:: 361:continue 362 363:: Testing EXIT within IF 364echo --------- Testing EXIT within IF --------- 365 366:: Use a CALL context, and we will only check EXIT /B. 367call :doExitIfTest 1 368call :doExitIfTest 2 369goto :finished 370 371:doExitIfTest 372if %1==1 ( 373 echo First block 374 exit /b 375 echo Unexpected first block^^! 376) else ( 377 echo Second block 378 exit /b 379 echo Unexpected second block^^! 380) 381echo You won't see this^^! 382exit /b 383 384 385 386:: 387:: Finished! 388:: 389:finished 390echo --------- Finished -------------- 391goto :EOF 392 393:: Subroutine to set errorlevel and return 394:: in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported 395:setError 396exit /B %1 397:: This line runs under cmd in windows NT 4, but not in more modern versions. 398