Rob van der Woude's Scripting Pages

GOTO

How to Avoid "Spaghetti Code"

In "real DOS", the GOTO command is used to skip part of a batch file:

@ECHO OFF
   •
   •
CHOICE /C:123 /N Choose 1, 2 or 3
IF ERRORLEVEL 3 GOTO Label3
IF ERRORLEVEL 2 GOTO Label2
IF ERRORLEVEL 1 GOTO Label1
   •
   •
:Label1
ECHO You chose 1
GOTO End

:Label2
ECHO You chose 2
GOTO End

:Label3
ECHO You chose 3
GOTO End
   •
   •
:End

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:

@ECHO OFF
   •
   •
:: First call of Sub5 subroutine
SET RETURN=Label3
GOTO Sub5
:Label3
   •
   •
:: Second call of Sub5 subroutine
SET RETURN=Label4
GOTO Sub5
:Label4
   •
   •
:: End of main program
GOTO End
   •
   •
:: Sub5 subroutine starts here
:Sub5
   • (some code to do whateverit is Sub5 should do)
:: End of Sub5 subroutine
:: (emulated "Return")
GOTO %RETURN%
   •
   •
:: End of batch file
:End

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 whateverit 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.

page last modified: 2011-11-18; loaded in 0.0065 seconds