The same goes for OS/2 and its DOS box.
Combined with IF and by "nesting" GOTOs, one can easily create true "spaghetti code" which is a disaster to read and debug.

Compare this to "real" subroutines (or functions in Pascal, or procedures in Rexx), that can be used and called as independent functions within the program you are creating.
There is, of course, always a way to fake subroutines in batch files:

The real surprise here is (once more) Windows NT.
In NT, a call to a subroutine's label (CALL :label), combined with GOTO :EOF to terminate the subroutine, presents a way to create real subroutines, GOTO :EOF being the instruction to jump back to where the subroutine was called.

@ECHO OFF
•
•
:: First call of Sub5 subroutine
IF "X"=="%Y%" CALL :Sub5
•
•
:: Second call of Sub5 subroutine
IF "Z"=="%Y%" CALL :Sub5
•
•
:: End of main program
GOTO End
•
•
:: Sub5 subroutine starts here
:Sub5
• (some code to do whatever
• it is Sub5 should do)
:: End of Sub5 subroutine
GOTO :EOF
•
•
:: End of batch file
:End

The most difficult part of subroutines is usually deciding which part of the program's code goes into which subroutine.

Note:

A final note on labels in batch files:Always terminate a label with a line feed, or ("true") DOS won't be able to find it.
So if :End is the last line of your batch file, just append another empty line.