1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

[14.02.36] leavefor in @execstr issue

Discussion in 'Support' started by Stefano Piccardi, Sep 4, 2012.

  1. Stefano Piccardi

    Joined:
    May 31, 2008
    Messages:
    376
    Likes Received:
    2
    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. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    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:\>
     
  3. Stefano Piccardi

    Joined:
    May 31, 2008
    Messages:
    376
    Likes Received:
    2
    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. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    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. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    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. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    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
     
  7. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    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. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    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
     
  9. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    I have no idea what you're trying to do here ...
     
  10. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,783
    Likes Received:
    29
    Earlier I had tried to get the "& leavefor" to be echoed (and failed). I was just pointing out that it can be done while (perhaps) pointing out the nuances of escaping ... just educational (for me too).
     
  11. Stefano Piccardi

    Joined:
    May 31, 2008
    Messages:
    376
    Likes Received:
    2
    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
     
  12. Charles Dye

    Charles Dye Super Moderator
    Staff Member

    Joined:
    May 20, 2008
    Messages:
    3,277
    Likes Received:
    38
    Wouldn't %@WORD[0,%CMD] be a simpler approach?
     
  13. Stefano Piccardi

    Joined:
    May 31, 2008
    Messages:
    376
    Likes Received:
    2

Share This Page