Search code examples
batch-filemethod-call

How does CMD.exe execute Call on a given label inside a batch file?


Suppose I have a batch file.

This batch file has a 'subroutine' labeled :AppndLog and it's purpose is to append a log file.

This routine starts at line - let's say 540. Now - other 'subroutines' thereafter may call this same Label but ALL of these routines are AFTER the :AppndLog label. . . .

So the question goes - is it more efficient to place this :AppndLog (and any other widely accessed 'routines') at the END of the file instead of at the beginning? Suppose this batch file has 7k lines of actions. . .

Does CMD.Exe interpret this and start the search for the label at the line it is first called, going to the end of the file and looping around, or does it go to the beginning of the file first?

Bonus points - does the Goto :EOF command trudge through the lines in between an end of subroutine to the end of the file?

It is much faster for me to simply echo the data to log using >>%log% at the point where I Call this routine but I lose the ability to output the date on each line without making yet another call somewhere else. . . (A real "FUN" delay was making the :AppndLog routine call a :GetDate routine where the date info at the beginning was produced. . . .

REM ╔══════════════════════════════════════════════════════╗
REM ║  -AppndLog-                                          ║
REM ║Appends log file with provided data if Logging GEQ #  ║
REM ╚══════════════════════════════════════════════════════╝

REM <<<-_-_-_-_-_BEGIN :AppndLog_-_-_-_-_->>>
 
 :AppndLog [Logging Level Check] [Data to Append]
 REM If "!Logging!" GEQ "2" Echo Append Data to Log. >>%log%
 REM for /f "Tokens=1,2 Delims=." %%a in ('wmic os get localdatetime ^|Findstr /R ^^[0-9]') do (set UTCDate=%%a & set curMS=%%b)
 REM Call :GetDate
 set myDate=!date:/=!
 set myTime=!time::=!
 set myTime=!myTime:.=!
 set "fullDate=!myDate!!myTime!"

 If not "%~1"=="" (
   Echo !fullDate! :: %~1 >>%log%
   If "!Verbose!" GEQ "3" Echo %~2
 ) Else (
   Echo !fullDate! >>%log%
   If "!Verbose!" GEQ "3" Echo.
 )
 
 Goto :EOF
REM <<<-_-_-_-_-_END :AppndLog_-_-_-_-_->>>

Solution

  • Both goto label and call :label search the label from the line after the goto/call onwards. If not found, continue the search from the beginning of the file. This means that is more efficient to place the target labels and subroutines below the calling line (at the end of the file).

    The goto :EOF form does not search; it terminates the subroutine/file immediately. The exit /B command is equivalent to goto :EOF I used to use exit /B to end subroutines, and goto :EOF to end the main Batch file.

    Bonus information

    This behavior allows to repeat the same label so a goto repeatedLabel will always go to the next label placed after the goto. This is useful when there are multiple goto's to near forward labels. In order to make clear this purpose and not be confused with an error, you can use the same method that MASM32 use for the same purpose: call @F the repeated label:

    echo First goto near forward label
    goto @F
    
    echo This don't appears
    
    :@F
    echo Second goto near forward label
    goto @F
    
    echo Neither this appears...
    
    :@F
    echo OK