Rules for label names vs GOTO and CALL

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Rules for label names vs GOTO and CALL

#16 Post by npocmaka_ » 13 Aug 2015 10:35

Just a continuation of this
for those who are (still) not on stack overflow.


It appears that most probably CALL uses GOTO to parse the labels (check jeb's answer) .
And for some reason this will print the GOTO help message:

Code: Select all

setlocal
set "label=/?"
call :%%label%%


More interesting it will execute the code bellow the CALL twice.
And will change its command line arguments :!:

try co call this this script with some arguments:

Code: Select all

setlocal
set "label=/?"
call :%%label%%  ##

echo -%1-


and without GOTO help message (EDIT on a second tought I dont see anyting special here)

Code: Select all

set l=l
call ::%%l%% ##
:l
echo -%1%-


On the second run it will be changed with ##



Also - it is possible to CALL :EOF with double expansion :


Code: Select all

@echo off
set e=EOF

call ::%%EOF%%
echo something



the thing is you can call any label with double semicolon (not possible with goto on the other hand goto can jump to labels without semicolon but call cant) which fits in the conclusion that CALL uses GOTO. And with double expansion it jumps to :EOF.


And one more side thing:

Code: Select all

set "h=/?"&call rem  %%h%%


:twisted:


EDIT

no need of double expansion to call eof - just

Code: Select all

call ::eof

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Rules for label names vs GOTO and CALL

#17 Post by npocmaka_ » 13 Aug 2015 13:33

I suppose this is not exactly related with the initial thread topic but why this appends to the file without new line and why works :?: (at least works the first time)


Code: Select all

@echo off

::
::rem the closing bracket should be the last symbol in the file
::
call ::eof && (
   echo echo something>>"%~f0"
)

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Rules for label names vs GOTO and CALL

#18 Post by dbenham » 13 Aug 2015 23:00

Great find npocmaka_, and great analysis by jeb.

Your last example "works" the first time because the entire block is parsed in its entirety, through the closing paren, before anything is executed.

The file pointer is now at the end of the file (after the paren).

The CALL ::EOF works as you have already discovered, and then the ECHO appends ECHO SOMETHING after the ) (on the same line).

But the file pointer currently resides after the paren, so when the parser resumes, it parses ECHO SOMETHING just fine.

On subsequent runs, the block fails entirely because the initial parse chokes on )ECHO SOMETHING.


Dave Benham

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Rules for label names vs GOTO and CALL

#19 Post by npocmaka_ » 14 Aug 2015 12:38

I've wondered if it is possible to strip the goto help message , so I'll be able to create anonymous function/subroutine . This is the only thing that came up to me:

Code: Select all

@echo off

setlocal


set "h=/?"
call :%%h%% anonymous a b c >nul

if not "%~1" == "anonymous" (
   echo(
   echo normal call
   echo %2 %3
)

if "%~1" == "anonymous" (
   echo(
   echo anonymous call
   echo %2 %3 %4
   exit /b 0
)>&3

echo end



Can this be useful?
I don't know .I think this could be a slight performance booster as the goto parsing is skipped.
The label will be not available for externalaccess so this also could be called a private function ...

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Rules for label names vs GOTO and CALL

#20 Post by dbenham » 14 Aug 2015 13:31

I was thinking of something similar, but was stumped until I saw your attempt :)

Here is an improvement. Instead of using %1 which could be spoofed, I rely on the %0 value, which I think is difficult (if not impossible) to fake. I also opted to name the variable "anonymous" instead of "h". I also explicitly redirect 3 to 1, just in case there has already been prior redirection.

I think it could be of marginal use for cases where you want to access variables set within a loop (or other block), don't want delayed expansion, and don't want a normal labeled routine that could be accidently called by some other code, and don't want to use the slow CALL ECHO %%var%% syntax.

Code: Select all

@echo off
setlocal
set "anonymous=/?"

echo Before anonymous call:
echo %%1=%1 %%2=%2 %%3=%3

for /l %%N in (1 1 5) do (
   set /a N=%%N*2
  call :%%anonymous%% a b c 3>&1 >nul
)
if "%0" == ":%anonymous%" (
  echo(
  echo Anonymous call:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
  exit /b 0
)>&3

echo(
echo After anonymous call:
echo %%1=%1 %%2=%2 %%3=%3

--OUTPUT--

Code: Select all

Before anonymous call:
%1= %2= %3=

Anonymous call:
%1=a %2=b %3=c  N=2

Anonymous call:
%1=a %2=b %3=c  N=4

Anonymous call:
%1=a %2=b %3=c  N=6

Anonymous call:
%1=a %2=b %3=c  N=8

Anonymous call:
%1=a %2=b %3=c  N=10

After anonymous call:
%1= %2= %3=


Dave Benham
Last edited by dbenham on 14 Aug 2015 13:38, edited 1 time in total.

OperatorGK
Posts: 66
Joined: 13 Jan 2015 06:55

Re: Rules for label names vs GOTO and CALL

#21 Post by OperatorGK » 14 Aug 2015 13:34

npocmaka_ wrote:external access

It is possible! I thought not :(. Someone, please dump all awesome stackoverflow things here or, at least, make a list.
Also, I made some nice syntax:

Code: Select all

set LF=^


set exports=^^^%LF%%LF%^%LF%%LF%

Use like this:

Code: Select all

:function %exports% library.bat %*

Sadly "%*" can't be removed.

OperatorGK
Posts: 66
Joined: 13 Jan 2015 06:55

Re: Rules for label names vs GOTO and CALL

#22 Post by OperatorGK » 14 Aug 2015 14:02

dbenham wrote:I was thinking of something similar, but was stumped until I saw your attempt :)

Here is an improvement. Instead of using %1 which could be spoofed, I rely on the %0 value, which I think is difficult (if not impossible) to fake. I also opted to name the variable "private" instead of "h". I also explicitly redirect 3 to 1, just in case there has already been prior redirection.

I think it could be of marginal use for cases where you want to access variables set within a loop (or other block), don't want delayed expansion, and don't want a normal labeled routine that could be accidently called by some other code, and don't want to use the slow CALL ECHO %%var%% syntax.

Code: Select all

@echo off
setlocal
set "private=/?"

echo Before private call:
echo %%1=%1 %%2=%2 %%3=%3

for /l %%N in (1 1 5) do (
   set /a N=%%N*2
  call :%%private%% a b c 3>&1 >nul
)
if "%0" == ":%private%" (
  echo(
  echo Private call:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
  exit /b 0
)>&3

echo(
echo After private call:
echo %%1=%1 %%2=%2 %%3=%3

--OUTPUT--

Code: Select all

Before private call:
%1= %2= %3=

Private call:
%1=a %2=b %3=c  N=2

Private call:
%1=a %2=b %3=c  N=4

Private call:
%1=a %2=b %3=c  N=6

Private call:
%1=a %2=b %3=c  N=8

Private call:
%1=a %2=b %3=c  N=10

After private call:
%1= %2= %3=


Dave Benham

Just to say, changing %0 is possible:

Code: Select all

@echo off
echo Non-faked: %0
set "impossibleLabel=:/?"
call:fake0 %%impossibleLabel%%
exit /b

:fake0
shift
echo Faked: %0
exit /b

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Rules for label names vs GOTO and CALL

#23 Post by npocmaka_ » 14 Aug 2015 16:56

dbenham wrote:I was thinking of something similar, but was stumped until I saw your attempt :)

Here is an improvement. Instead of using %1 which could be spoofed, I rely on the %0 value, which I think is difficult (if not impossible) to fake. I also opted to name the variable "anonymous" instead of "h". I also explicitly redirect 3 to 1, just in case there has already been prior redirection.

I think it could be of marginal use for cases where you want to access variables set within a loop (or other block), don't want delayed expansion, and don't want a normal labeled routine that could be accidently called by some other code, and don't want to use the slow CALL ECHO %%var%% syntax.


Dave Benham


Will admit that this is neater ..and with a far more better the redirection .But this will restrict the code to only one anonymous function?
Next step is a performance test.



please dump all awesome stackoverflow things here or, at least, make a list


I was thinking for a thread like this...

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Rules for label names vs GOTO and CALL

#24 Post by dbenham » 14 Aug 2015 21:17

npocmaka_ wrote:
dbenham wrote:I was thinking of something similar, but was stumped until I saw your attempt :)

Here is an improvement. Instead of using %1 which could be spoofed, I rely on the %0 value, which I think is difficult (if not impossible) to fake. I also opted to name the variable "anonymous" instead of "h". I also explicitly redirect 3 to 1, just in case there has already been prior redirection.

I think it could be of marginal use for cases where you want to access variables set within a loop (or other block), don't want delayed expansion, and don't want a normal labeled routine that could be accidently called by some other code, and don't want to use the slow CALL ECHO %%var%% syntax.


Dave Benham


Will admit that this is neater ..and with a far more better the redirection .But this will restrict the code to only one anonymous function?
Next step is a performance test.

Yes, one anonymous function per code block (immediately following the block). But it is a stretch in my mind to argue for one anonymous function, let alone multiple ones :wink:
Also, a named anonymous function would seem to be an oxymoron, but that is just semantics :roll:

In my quick tests, with a short script, an anonymous block that ECHOs a value is about 2/3 as fast as a normal labeled function call. I'm assuming the slowness is due to the time it takes to print out the HELP, even if it is directed to NUL. I suppose the difference will be less as the file gets bigger if there is a significant gap between the CALL and the :LABEL. But the anonymous CALL is twice as fast as a CALL to an ECHO with double expansion.


Dave Benham

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Rules for label names vs GOTO and CALL

#25 Post by npocmaka_ » 15 Aug 2015 02:36

yes.Unfortunately anonymous functions are even slower when executed in small scripts :( . Though they are a little bit faster when the script is bigger.

Here are my tests:

Code: Select all

anonymous
start 11:06:01.86 -end 11:06:19.51 - short script -                       17.65 sec
start 11:11:02.48 -end 11:11:19.92 - long script (126 additional lines) - 17.44 sec



Code: Select all

normal call
start 11:13:56.99 -end 11:14:20.13 - short script -                      13.14 sec
start 11:15:17.22 -end 11:15:40.45 - long script (126 additional lines)- 23.33 sec




The code I've used:

1.Normal function:

Code: Select all

@echo off

set time1=%time%
for /l %%N in (1 1 10000) do (
   set /a N=%%N*2
  call :anonymous a b c
)


set time2=%time%

echo %time1% %time2%


exit /b 0

:anonymous
  echo(
  echo Anonymous call:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
exit /b 0


2.Anonymous function

Code: Select all

@echo off
setlocal
set "anonymous=/?"

set time1=%time%

for /l %%N in (1 1 10000) do (
   set /a N=%%N*2
  call :%%anonymous%% a b c 3>&1 >nul
)
if "%0" == ":%anonymous%" (
  echo(
  echo Anonymous call:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
  exit /b 0
)>&3

set time2=%time%

echo %time1% %time2%

exit /b 0



the additional lines:

Code: Select all

Lorem ipsum dolor sit
Amet tempus at tortor
Volutpat nunc dui pede. Velit nonummy enim aliquam id proin leo a. Etiam donec pellentesque mauris orci.

Vestibulum elit vivamus imperdiet pellentesque nulla aliquam in. Pellentesque mauris rhoncus vitae. Nulla tellus potenti eget. Vivamus morbi nulla imperdiet. Auctor wisi arcu lorem mi.

Laoreet ligula orci condimentum
Diam vel etiam viverra. Class imperdiet hendrerit accumsan. A sed tempus gravida. Ultrices auctor per etiam ultrices donec magna vitae proin.

Nunc sit sit sit. Ac nulla elementum nulla fringilla quis ut tortor. Lacinia nisl varius eget. Condimentum senectus vehicula metus. Sed turpis aliquam rutrum tincidunt.

Et duis donec sint
Risus gravida vestibulum consequat. Dolorem magna proin fermentum. A vestibulum amet aut. Viverra quam pede urna consequat suscipit neque tincidunt nunc.

Proin odio nulla quisque. Integer sit nulla quis. Ut lorem eu est. Integer molestie purus eget con tellus ut aliquam. Eu suspendisse vitae at dolor.

Vulputate magna porttitor justo
Interdum commodo odio dolor congue dui metus duis. Sem imperdiet suspendisse sem. Elit aliquam rhoncus luctus. Nibh ante sit euismod id.

Dolor nulla dolor enim sagittis dui wisi elit. Enim maecenas quis elit. Scelerisque tristique ut maecenas. Felis mattis nunc turpis. Adipiscing eget orci eget eget.

Vitae laoreet a parturient
Nec at lacinia aut. Sagittis in euismod justo. Eleifend pharetra mollis erat fermentum nunc aliquet quam. Ac sed praesent turpis posuere.

Lorem tellus mauris vivamus quis phasellus sagittis adipiscing. Enim proin non sit. Fermentum metus in sem. Porttitor pulvinar fermentum pede. A wisi ligula posuere in.

Curabitur ligula ut in
Tortor purus id senectus. In malesuada wisi mattis. Mauris dictum gravida fusce elit eros amet elementum. Venenatis enim adipiscing nunc scelerisque.

Euismod placerat gravida vulputate sodales aliquam aenean diam. Et eu sed massa. Mollis tempor dui potenti. Purus nisl nam et. Mattis eu at et vivamus.

Lorem ipsum dolor sit
Amet tempus at tortor
Volutpat nunc dui pede. Velit nonummy enim aliquam id proin leo a. Etiam donec pellentesque mauris orci.

Vestibulum elit vivamus imperdiet pellentesque nulla aliquam in. Pellentesque mauris rhoncus vitae. Nulla tellus potenti eget. Vivamus morbi nulla imperdiet. Auctor wisi arcu lorem mi.

Laoreet ligula orci condimentum
Diam vel etiam viverra. Class imperdiet hendrerit accumsan. A sed tempus gravida. Ultrices auctor per etiam ultrices donec magna vitae proin.

Nunc sit sit sit. Ac nulla elementum nulla fringilla quis ut tortor. Lacinia nisl varius eget. Condimentum senectus vehicula metus. Sed turpis aliquam rutrum tincidunt.

Et duis donec sint
Risus gravida vestibulum consequat. Dolorem magna proin fermentum. A vestibulum amet aut. Viverra quam pede urna consequat suscipit neque tincidunt nunc.

Proin odio nulla quisque. Integer sit nulla quis. Ut lorem eu est. Integer molestie purus eget con tellus ut aliquam. Eu suspendisse vitae at dolor.

Vulputate magna porttitor justo
Interdum commodo odio dolor congue dui metus duis. Sem imperdiet suspendisse sem. Elit aliquam rhoncus luctus. Nibh ante sit euismod id.

Dolor nulla dolor enim sagittis dui wisi elit. Enim maecenas quis elit. Scelerisque tristique ut maecenas. Felis mattis nunc turpis. Adipiscing eget orci eget eget.

Vitae laoreet a parturient
Nec at lacinia aut. Sagittis in euismod justo. Eleifend pharetra mollis erat fermentum nunc aliquet quam. Ac sed praesent turpis posuere.

Lorem tellus mauris vivamus quis phasellus sagittis adipiscing. Enim proin non sit. Fermentum metus in sem. Porttitor pulvinar fermentum pede. A wisi ligula posuere in.

Curabitur ligula ut in
Tortor purus id senectus. In malesuada wisi mattis. Mauris dictum gravida fusce elit eros amet elementum. Venenatis enim adipiscing nunc scelerisque.

Euismod placerat gravida vulputate sodales aliquam aenean diam. Et eu sed massa. Mollis tempor dui potenti. Purus nisl nam et. Mattis eu at et vivamus.

Lorem ipsum dolor sit
Amet tempus at tortor
Volutpat nunc dui pede. Velit nonummy enim aliquam id proin leo a. Etiam donec pellentesque mauris orci.

Vestibulum elit vivamus imperdiet pellentesque nulla aliquam in. Pellentesque mauris rhoncus vitae. Nulla tellus potenti eget. Vivamus morbi nulla imperdiet. Auctor wisi arcu lorem mi.

Laoreet ligula orci condimentum
Diam vel etiam viverra. Class imperdiet hendrerit accumsan. A sed tempus gravida. Ultrices auctor per etiam ultrices donec magna vitae proin.

Nunc sit sit sit. Ac nulla elementum nulla fringilla quis ut tortor. Lacinia nisl varius eget. Condimentum senectus vehicula metus. Sed turpis aliquam rutrum tincidunt.

Et duis donec sint
Risus gravida vestibulum consequat. Dolorem magna proin fermentum. A vestibulum amet aut. Viverra quam pede urna consequat suscipit neque tincidunt nunc.

Proin odio nulla quisque. Integer sit nulla quis. Ut lorem eu est. Integer molestie purus eget con tellus ut aliquam. Eu suspendisse vitae at dolor.

Vulputate magna porttitor justo
Interdum commodo odio dolor congue dui metus duis. Sem imperdiet suspendisse sem. Elit aliquam rhoncus luctus. Nibh ante sit euismod id.

Dolor nulla dolor enim sagittis dui wisi elit. Enim maecenas quis elit. Scelerisque tristique ut maecenas. Felis mattis nunc turpis. Adipiscing eget orci eget eget.

Vitae laoreet a parturient
Nec at lacinia aut. Sagittis in euismod justo. Eleifend pharetra mollis erat fermentum nunc aliquet quam. Ac sed praesent turpis posuere.

Lorem tellus mauris vivamus quis phasellus sagittis adipiscing. Enim proin non sit. Fermentum metus in sem. Porttitor pulvinar fermentum pede. A wisi ligula posuere in.

Curabitur ligula ut in
Tortor purus id senectus. In malesuada wisi mattis. Mauris dictum gravida fusce elit eros amet elementum. Venenatis enim adipiscing nunc scelerisque.

Euismod placerat gravida vulputate sodales aliquam aenean diam. Et eu sed massa. Mollis tempor dui potenti. Purus nisl nam et. Mattis eu at et vivamus.
Lorem ipsum dolor sit
Amet tempus at tortor
Volutpat nunc dui pede. Velit nonummy enim aliquam id proin leo a. Etiam donec pellentesque mauris orci.

Vestibulum elit vivamus imperdiet pellentesque nulla aliquam in. Pellentesque mauris rhoncus vitae. Nulla tellus potenti eget. Vivamus morbi nulla imperdiet. Auctor wisi arcu lorem mi.

Laoreet ligula orci condimentum
Diam vel etiam viverra. Class imperdiet hendrerit accumsan. A sed tempus gravida. Ultrices auctor per etiam ultrices donec magna vitae proin.

Nunc sit sit sit. Ac nulla elementum nulla fringilla quis ut tortor. Lacinia nisl varius eget. Condimentum senectus vehicula metus. Sed turpis aliquam rutrum tincidunt.

Et duis donec sint
Risus gravida vestibulum consequat. Dolorem magna proin fermentum. A vestibulum amet aut. Viverra quam pede urna consequat suscipit neque tincidunt nunc.

Proin odio nulla quisque. Integer sit nulla quis. Ut lorem eu est. Integer molestie purus eget con tellus ut aliquam. Eu suspendisse vitae at dolor.

Vulputate magna porttitor justo
Interdum commodo odio dolor congue dui metus duis. Sem imperdiet suspendisse sem. Elit aliquam rhoncus luctus. Nibh ante sit euismod id.

Dolor nulla dolor enim sagittis dui wisi elit. Enim maecenas quis elit. Scelerisque tristique ut maecenas. Felis mattis nunc turpis. Adipiscing eget orci eget eget.

Vitae laoreet a parturient
Nec at lacinia aut. Sagittis in euismod justo. Eleifend pharetra mollis erat fermentum nunc aliquet quam. Ac sed praesent turpis posuere.

Lorem tellus mauris vivamus quis phasellus sagittis adipiscing. Enim proin non sit. Fermentum metus in sem. Porttitor pulvinar fermentum pede. A wisi ligula posuere in.

Curabitur ligula ut in
Tortor purus id senectus. In malesuada wisi mattis. Mauris dictum gravida fusce elit eros amet elementum. Venenatis enim adipiscing nunc scelerisque.

Euismod placerat gravida vulputate sodales aliquam aenean diam. Et eu sed massa. Mollis tempor dui potenti. Purus nisl nam et. Mattis eu at et vivamus.

OperatorGK
Posts: 66
Joined: 13 Jan 2015 06:55

Re: Rules for label names vs GOTO and CALL

#26 Post by OperatorGK » 15 Aug 2015 06:23

slower when used in small scripts

:shock: What developers of cmd.exe smoked? Cause I don't know HOW to code something that works slower when used in small script.
Also, it's speed decreases with memory usage - avg. 15 sec with 1MB used, but 90 sec with 4MB used on my computer.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Rules for label names vs GOTO and CALL

#27 Post by dbenham » 15 Aug 2015 08:12

I'm pretty sure the difference between 17.65 and 17.44 is nothing more than random variance. I believe you will find virtually no difference between the two if you run each 100 times and take the average.


Dave Benham

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Rules for label names vs GOTO and CALL

#28 Post by npocmaka_ » 15 Aug 2015 08:33

Ahm.What I've meant was that the anonymous functions are faster than normal call of functions with big scripts.Probably I've misled OperatorGK .

For sure these 200 milliseconds were between two anonymous calls were just a random noise.

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Rules for label names vs GOTO and CALL

#29 Post by npocmaka_ » 15 Aug 2015 09:49

Almost forgot how GOTO parses the arguments containing `/?` . It is possible to have a lot of anonymous functions:


Code: Select all

@echo off
setlocal
set "anonymous=/?#"

echo Before first anonymous call:
echo %%1=%1 %%2=%2 %%3=%3

for /l %%N in (1 1 5) do (
   set /a N=%%N*2
  call :%%anonymous%% a b c 3>&1 >nul
)
if "%0" == ":%anonymous%" (
  echo(
  echo Anonymous call:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
  exit /b 0
)>&3

echo(
echo After first anonymous call:
echo %%1=%1 %%2=%2 %%3=%3


echo ---------------------------

set "anonymous2=/?##"

echo Before second anonymous call:
echo %%1=%1 %%2=%2 %%3=%3

for /l %%N in (1 1 5) do (
   set /a N=%%N*2
  call :%%anonymous2%% e f g 3>&1 >nul
)
if "%0" == ":%anonymous2%" (
  echo(
  echo Anonymous call:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
  exit /b 0
)>&3

echo(
echo After the second anonymous call:
echo %%1=%1 %%2=%2 %%3=%3



And even `parts` of one anonymous function to placed on different places in the script

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Rules for label names vs GOTO and CALL

#30 Post by Aacini » 15 Aug 2015 10:23

The "anonymous subroutine" called by a certain "anonymous call" is the code placed below the "call :%%anonymous%%" line, so there is no need to distinguish one "anonymous subroutine" from another one:

Code: Select all

@echo off
setlocal
set "anonymous=/?"

echo Before first anonymous call:
echo %%1=%1 %%2=%2 %%3=%3

for /l %%N in (1 1 5) do (
   set /a N=%%N*2
  call :%%anonymous%% a b c 3>&1 >nul
)
if "%0" == ":%anonymous%" (
  echo(
  echo First anonymous subroutine:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
  exit /b 0
)>&3

echo(
echo After first anonymous call:
echo %%1=%1 %%2=%2 %%3=%3


echo ---------------------------

echo Before second anonymous call:
echo %%1=%1 %%2=%2 %%3=%3

for /l %%N in (1 1 5) do (
   set /a N=%%N*2
  call :%%anonymous%% e f g 3>&1 >nul
)
if "%0" == ":%anonymous%" (
  echo(
  echo Second anonymous subroutine:
  echo %%1=%1 %%2=%2 %%3=%3  N=%N%
  exit /b 0
)>&3

echo(
echo After the second anonymous call:
echo %%1=%1 %%2=%2 %%3=%3

Antonio

Post Reply