[14.02.36] leavefor in @execstr issue

May 31, 2008
382
2
#1
The following batch file never goes past the @execstr line.
Code:
setlocal
set cmd=TODO. "a b"
set x=%@execstr[for %%i in (%[cmd]) (echo %%i ^&leavefor)]
echo x=%x
endlocal
quit
output
Code:
setlocal
set cmd=TODO. "a b"
set x=TODO.
Changing the code to using gosub reveals that execution does continue past @execst but there seems to be one extra pop of the return stack, I guess.
Code:
setlocal
gosub test
echo here!
endlocal
quit
:test
set cmd=TODO. "a b"
set x=%@execstr[for %%i in (%[cmd]) (echo %%i ^&leavefor)]
echo x=%x
return
output
Code:
setlocal
gosub test
set cmd=TODO. "a b"
set x=TODO.
echo here!
here!
endlocal
quit
TCC 14.02.36 Windows XP [Version 5.1.2600]
TCC Build 36 Windows XP Build 2600 Service Pack 3
 
#2
It works as expected if you don't escape the '&' (why did you escape it?). When it's escaped, I'd expect it to be echoed but it's not and execution doesn't continue.
Code:
v:\> type forleave.btm
setlocal
set str=a b c
set z=%@execstr[for %%x in ( %[str] ) (echo x = %%x & leavefor)]
echo %z
echo foo
echo bar
 
v:\> forleave.btm
x = a
foo
bar
 
v:\> type forleave.btm
setlocal
set str=a b c
set z=%@execstr[for %%x in ( %[str] ) (echo x = %%x ^& leavefor)]
echo %z
echo foo
echo bar
 
v:\> forleave.btm
 
v:\>
 
May 31, 2008
382
2
#3
Doesn't & inside @execstr need to be escaped in general? I'm confused; what do you think is happening in the second example below?
Code:
[C:\]echo %@execstr[echo a & echo b]
a

[C:\]echo %@execstr[echo a ^& echo b]
a
 b
 
#4
Doesn't & inside @execstr need to be escaped in general? I'm confused; what do you think is happening in the second example below?
Code:
[C:\]echo %@execstr[echo a & echo b]
a
 
[C:\]echo %@execstr[echo a ^& echo b]
a
b
I think the parens are protecting it ... perhaps too well ... it can't be escaped to be made a literal '&'.
Code:
v:\> echo %@execstr[for %%x in ( a b c ) (echo x = %%x & leavefor)]
x = a
 
v:\> echo %@execstr[for %%x in ( a b c ) (echo x = %%x ^& leavefor)]
x = a
 
v:\> echo %@execstr[for %%x in ( a b c ) (echo x = %%x ^^& leavefor)]
x = a ^
 
#5
I didn't try hard enough.
Code:
v:\> echo %@execstr[for %%x in ( a b c ) (echo x = %%x ^^^& leavefor)]
x = a & leavefor
 
v:\>
But that doesn't work in a batch file. Regardless of how many times the '&' is escaped, you get the screwy behavior.
 
#6
This is the penultimate paragraph of the documentation:
@EXECSTR involves several extensive internal processing stages. You might be able to use more complex command sequences (pipes, command groups, etc.) as its parameter, but always test carefully first as the results may not always be what you expect. We recommend that you only use a single command (internal, external, batch file, etc.) parameter.
IMHO there is no problem.

Here are some points about the reason for the observed behavior.
- escaped command separator (e.s.c.)
in first pass it is not interpreted as a command separator, thus the characters behind it are considered part of the command preceding the e.s.c. Once the WHOLE command containing the @EXECSTR is executed, it is found by the parser, and executed as a command outside of the @EXECSTR context. This behavior may be considered "screwy", but well within the warnings quoted above.
- multiple ECHO commands separated by command separator
the first line written to STDOUT is returned as the value of @EXECSTR; all subsequent lines discarded
 

rconn

Administrator
Staff member
May 14, 2008
10,326
94
#7
The following batch file never goes past the @execstr line.
I don't understand what you're trying to do, but your syntax almost certainly won't result in what you're expecting.

Don't escape &'s (or |'s) inside command groups. What's happening is that the "& LEAVEFOR" is getting put into the output of @EXECSTR, so your SET statement expands to

set x=TODO. & leavefor

and the LEAVEFOR with no matching FOR is causing your batch file to close. (This is WAD.)
 
#8
I didn't go far enough earlier (again). Though I doubt it was Stefano's intention, you can get the '&' echoed if you escape it enough. And (below) I don't see "x = b & leavefor" because that's the second line of output.

Code:
v:\> type forleave.btm
echos 1^t
echo %@execstr[(echo x = x ^^^& leavefor)]
set z=%@execstr[for %%x in ( a b ) (echo x = %%x ^^^^^^^& leavefor)]
echos 2^t
set z
echos 3^t
echo %z

v:\> forleave.btm
1       x = x & leavefor
2       x = a ^& leavefor
3       x = a & leavefor
 
May 31, 2008
382
2
#11
I don't understand what you're trying to do...
Separating the first, possibly quoted multiword, argument from the tail of %cmd
Code:
E:\>set cmd="a b c" x y z
 
E:\>echo %@execstr[for %%i in (%[cmd]) (echo %%i &leavefor)]
"a b c"
 
E:\>set cmd=a "x y z"
 
E:\>echo %@execstr[for %%i in (%[cmd]) (echo %%i &leavefor)]
a