Page 1 of 1

goto within block forces var re-evaluation

Posted: 04 Feb 2013 10:09
by Sponge Belly
Greetings!

I read an interesting Experts Exchange topic. Search for the Goto Issue section. The example given by Qlemo goes something like this:

Code: Select all

set fruit=apples
if 1==1 (
echo(%fruit%
set fruit=bananas
goto nextline
:nextline
echo(%fruit%
)


Pretty cool, huh? ;-) But wait, it gets better! I thought this trick would only work inside conditional or bare blocks, but FoxiDrive’s recent post on problem with a label in parentheses proves that you can use labels inside for loops so long as the label isn’t the last statement in the block. :shock:

This leaves the door open to commit such attrocities as:

Code: Select all

setlocal enabledelayedexpansion
set "string=!%~1!" & set "substr=!%~2!"

for %%v in (string substr) do (
set "var=!%%v!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~L!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~3!"
if not defined notdelayed set "var=!var:^=^^^^!"
goto nextline
:nextline
if not defined notdelayed set "var=%var:!=^^^!%" !
set "%%v=!var!"
)
endlocal


The above isn’t a standalone working example, but you get the idea. ;-) Apologies to Jeb for mangling his “safe string return” code.

Hope you find this useful.

- SB

Re: goto within block forces var re-evaluation

Posted: 04 Feb 2013 12:20
by jeb
Hi Sponge Belly,

Sponge Belly wrote:Code:
set fruit=apples
if 1==1 (
echo(%fruit%
set fruit=bananas
goto nextline
:nextline
echo(%fruit%
)


Pretty cool, huh? ;-)

It looks confusing, but the cause is simple:
A goto breaks a block, or better it leaves even the deepest nested blocks.

So effectively it's the same as:

Code: Select all

set fruit=apples
if 1==1 (
set fruit=bananas
echo(%fruit%
)
rem goto nextline
rem :nextline
echo(%fruit%
rem )


Sponge Belly wrote:But wait, it gets better! I thought this trick would only work inside conditional or bare blocks, but FoxiDrive's recent post on problem with a label in parentheses proved that you can use labels inside for loops so long as the label isn't the last statement in the block. :shock:


Yes, this is a bit more complicated, but even this follows some strange rules :)
Labels in blocks are two line oriented, a primary line (the label) and a secondary line.
A label in a block starts the two line logic, and requires a a secondary line.
In the simplest case the secondary line is a command, then all seems to be normal

Code: Select all

(
:myLabel
echo hello


But the secondary line must be a valid command line.
That's the cause why a simple closing brackt fails, and also a double colon will fail, but not a single colon.

And additionally in the secondary line labels are interpreted a bit different.

Code: Select all

(
:primaryLabel & echo this is a comment
:secondaryLabel & echo But this will be printed!
)


hope I could brought light into the darkness

jeb