1
votes

I unfortunately own a batch program that has duplicate label names. Can anyone explain why the GOTO goes to the label in the second block, not the first? The code:

@ECHO OFF
SET FLAG=1
IF [%FLAG%]==[1] (
    ECHO IN THE FIRST IF...
    GOTO TD_NEXT
:TD_NEXT
    ECHO HERE AT TD_NEXT IN THE FIRST BLOCK
)

IF [%FLAG%]==[1] (
    ECHO IN THE SECOND IF...
    GOTO TD_NEXT
:TD_NEXT
     ECHO HERE AT TD_NEXT IN THE SECOND BLOCK
)

The output:

IN THE FIRST IF...
HERE AT TD_NEXT IN THE SECOND BLOCK

I can add a third block, and see that it jumps to the one after the next, each time.

IN THE FIRST IF...
HERE AT TD_NEXT IN THE SECOND BLOCK
IN THE THIRD IF...
HERE AT TD_NEXT IN THE FIRST BLOCK
IN THE SECOND IF...
HERE AT TD_NEXT IN THE THIRD BLOCK
2

2 Answers

2
votes

Interesting problem! The answer is comprised of two parts:

1- A goto command always seek for the label from the next instruction to the end of the file. If the label is not found, the seek is restarted from the beginning of the file up to the same line of the original goto command. If not found, an error is issued.

2- In previous description, the next instruction usually refers to the line following the goto. However, if the goto is placed inside a code block (that should never be done, but that is another story), then the "current instruction" is the whole code block where the goto is placed. This means that the label is seek from the end of the if command on...

This is just another reason to not place labels inside code blocks; this also cause several other problems.

EDIT: See this funny example:

@echo off

set var=1
if %var% equ 1 (

:NEXT
   if %var% neq 1 goto NEXT
   echo This appear first time:  var=%var%
   set var=2
   goto NEXT

:NEXT
   echo This appear second time: var=%var%

)

Output:

This appear first time:  var=1
This appear second time: var=2

SECOND EDIT: The example below proves that the labels are seek in the way described at point 1 above:

@echo off

goto PATCH

:LABEL
echo :LABEL >> "%~F0"
echo echo At end of file >> "%~F0"

:PATCH
echo In an infinite loop:
goto LABEL

Output:

In an infinite loop:
In an infinite loop:
At end of file
0
votes

I believe the reason is that the last label by that name is the one that the interpreter remembers. The interpreter stores labels and locations in a table in memory. If it comes across another label with the same name, this simply overwrites the previous label with the same name.

Cheers