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

Nested IF syntax — TCC behaving differently to CMD

Discussion in 'Support' started by Christian Albaret, Jun 22, 2017.

  1. Christian Albaret

    Joined:
    Jul 1, 2008
    Messages:
    154
    Likes Received:
    1
    The following code comes from "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.Cmd", a Microsoft SDK batch file.
    Code:
    IF "x%TARGET_CPU%x"=="xx" (
    IF /I "%PROCESSOR_ARCHITECTURE%"=="x86" SET "TARGET_CPU=x86" & SET "CURRENT_CPU=x86"
    IF /I "%PROCESSOR_ARCHITEW6432%"=="x86" SET "TARGET_CPU=x86" & SET "CURRENT_CPU=x86"
    IF /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" SET "TARGET_CPU=x64" & SET "CURRENT_CPU=x64"
    IF /I "%PROCESSOR_ARCHITEW6432%"=="AMD64" SET "TARGET_CPU=x64" & SET "CURRENT_CPU=x64"
    IF /I "%PROCESSOR_ARCHITECTURE%"=="x64"   SET "TARGET_CPU=x64" & SET "CURRENT_CPU=x64"
    IF /I "%PROCESSOR_ARCHITECTURE%"=="IA64"  SET "TARGET_CPU=IA64" & SET "CURRENT_CPU=IA64"
    IF /I "%PROCESSOR_ARCHITEW6432%"=="IA64"  SET "TARGET_CPU=IA64" & SET "CURRENT_CPU=IA64"
    GOTO Parse_Args
    )
    
    (on my machine, it is the 3rd inner IF that triggers.)

    Under CMD, this code sets TARGET_CPU and CURRENT_CPU.
    Under TCC, this code sets none of the variables.

    The following code (only the 3rd inner IF, not nested)
    Code:
    IF /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" SET "TARGET_CPU=x64" & SET "CURRENT_CPU=x64"
    
    sets TARGET_CPU and CURRENT_CPU both under CMD and TCC.

    TCC 21.00.32 x64 Windows 7 [Version 6.1.7601]
     
    #1 Christian Albaret, Jun 22, 2017
    Last edited: Jun 22, 2017
  2. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,883
    Likes Received:
    29
    Here's a simplified version. It shows an apparent bug where v21 (in comparison to v20) seems to terminate the () grouping early. V20 acts more sanely, but still not like CMD.
    Code:
    v:\> type iffy.bat
    @echo off
    if "1"=="1" (
    echo 1
    if "%zz%"=="a" echo zz=a & echo zz=a
    echo 2
    if "%zz%"=="b" echo zz=b & echo zz=b
    )
    Here are the three, v21 ...
    Code:
    v:\> ver & set zz=a & iffy.bat
    
    TCC  21.00.32   Windows 7 [Version 6.1.7601]
    1
    zz=a
    zz=a
    2
    
    v:\> ver & set zz=b & iffy.bat
    
    TCC  21.00.32   Windows 7 [Version 6.1.7601]
    1
    v20 ...
    Code:
    v:\> ver & set zz=a & iffy.bat
    
    TCC  20.11.46   Windows 7 [Version 6.1.7601]
    1
    zz=a
    zz=a
    2
    zz=b
    
    v:\> ver & set zz=b & iffy.bat
    
    TCC  20.11.46   Windows 7 [Version 6.1.7601]
    1
    zz=a
    2
    zz=b
    zz=b
    CMD ...
    Code:
    V:\> ver
    
    Microsoft Windows [Version 6.1.7601]
    
    V:\> set zz=a
    
    V:\> iffy.bat
    1
    zz=a
    zz=a
    2
    
    V:\> set zz=b
    
    V:\> iffy.bat
    1
    2
    zz=b
    zz=b
     
  3. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,806
    Likes Received:
    82
  4. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,883
    Likes Received:
    29
    OK, that makes v21 act like v20. But (though it doesn't bother me) TCC and CMD still treat this differently.
    Code:
    if 1==2 echo foo & echo bar
    I recall this being discussed ib the past but I don't remember the bottom line.
     
  5. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,806
    Likes Received:
    82
    For that, you have to turn "Duplicate CMD.EXE bugs" back on. CMD will not process additional commands if the IF fails (which is undocumented, and obviously wrong behavior).
     
  6. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,883
    Likes Received:
    29
    A sensible (?) interpretation is that CMD's
    Code:
    if condition command1 & command 2
    is the same as TCC's
    Code:
    if condition (command1 & command2)
    That's how CMD behaves and it seems to be the intent in the BATfile from the original post in this thread.
     
  7. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,806
    Likes Received:
    82
    That would be sensible - except that (1) it's undocumented, and (2) CMD also supports command groups, so if you wanted it to ignore compound commands you could just use a command group. Having it act like that only for IF makes no sense.
     
    evensenm likes this.
  8. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,806
    Likes Received:
    82
    TCMD v21 and v20 behave exactly the same, provided you have the "Duplicate CMD.EXE bugs" set the same in both (apparently you didn't).
     
  9. evensenm

    Joined:
    Jul 29, 2016
    Messages:
    33
    Likes Received:
    1
    I haven't tried any of the above examples myself, but looking at what was posted above, it looks like TCC's behavior (with "Duplicate CMD Bugs" turned ON) is still different than CMD's behavior when it comes to *NESTED* IF statements (with the "outer" IF statement command(s) to execute being in a command group with ()'s ). Without nested IF statements and just a single IF statement with compound commands, it looks like TCC's behavior (with "Duplicate CMD Bugs" turned ON) and CMD's behavior are the same, as what I would expect with "Duplicate CMD Bugs" turned ON. It appears to be an issue with *NESTED* IF statements. Look at vefatica's first example again between TCC v21 and CMD (it's evident to me that his v21 is with "Duplicate CMD Bugs" turned ON). Again, I haven't personally tested, but am just making an observation on the output of the commands posted above.
     
    #9 evensenm, Jun 23, 2017
    Last edited: Jun 23, 2017
  10. evensenm

    Joined:
    Jul 29, 2016
    Messages:
    33
    Likes Received:
    1
    This is an issue in TCC that is inconsistent with what the documentation states.

    The documentation for the IF command states (excerpt):

    When an IF test fails, the remainder of the command is discarded. Whether TCC continues with the next command on the line, or discards the rest of the line and goes to the next line is dependent upon the Duplicate CMD Bugs configuration option. CMD will discard all remaining commands on the line when an IF test fails, including those after a command separator or pipe character. If you do not want to reproduce CMD.EXE's behavior of an IF affecting all commands on a line, set DuplicateBugs to No in the .INI file. The IF behavior is different when DuplicateBugs is YES in a command group in a batch file. If there are multiple command lines in the command group, a failed IF will only ignore the remainder of the commands on that line. The commands on the subsequent lines in the command group will still be executed.

    Note that it states that even with DuplicateBugs set to YES, a failed IF will only ignore the rest of the commands on that line (presumably separated with the command separator & ), and that the separate remaining lines in the command group will still be executed. TCC is clearly not doing that when "Duplicate CMD Bugs" is turned ON. All the remaining commands in the command group, even all the ones on separate lines, are discarded. Check this out:

    Code:
    C:\Users\Mark\Documents\test 4>type iffy.bat
    
    @echo off
    
    if "foo" == "foo" (
        echo Line 1
        if "%zz%" == "a" echo zz=a & echo zz=a
        echo Line 2
        if "%zz%" == "b" echo zz=b & echo zz=b
        echo Next to Last Line
    )
    
    echo Last Line
    
    Under TCC, this is shown when zz=a

    Code:
    C:\Users\Mark\Documents\test 4>iffy
    
    Line 1
    zz=a
    zz=a
    Line 2
    Last Line
    
    And when zz=b ....

    Code:
    C:\Users\Mark\Documents\test 4>iffy
    
    Line 1
    Last Line
    
    And under CMD.....
    zz=a
    Code:
    C:\Users\Mark\Documents\test 4>iffy
    
    Line 1
    zz=a
    zz=a
    Line 2
    Next to Last Line
    Last Line
    
    zz=b
    Code:
    C:\Users\Mark\Documents\test 4>iffy
    Line 1
    Line 2
    zz=b
    zz=b
    Next to Last Line
    Last Line
    
     
  11. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,883
    Likes Received:
    29
    Maybe this will shed some light on the problem. By mistake, I omitted a quote in the first of the nested IFs.
    Code:
    v:\> type iffy2.bat
    IF "1"=="2" (
    IF %zz"=="a" echo zz=a & echo zz=a
    IF "%zz"=="b" echo zz=b & echo zz=b
    IF "%zz"=="c" echo zz=c & echo zz=c
    )
    v:\>
    And, with DuplicateBuge=Yes, I get this.
    Code:
    v:\> iffy2.bat
    TCC: V:\iffy2.bat [6]  Unbalanced parentheses "IF "1"=="2" ( IF %zz"=="a" echo zz=a & echo zz=a &| IF "%zz"=="b"
    echo zz=b & echo zz=b &| IF "%zz"=="c" echo zz=c & echo zz=c ) "
    TCC: V:\iffy2.bat [7]  Unbalanced parentheses "( IF %zz"=="a" echo zz=a & echo zz=a &| IF "%zz"=="b" echo zz=b &
    echo zz=b &| IF "%zz"=="c" echo zz=c & echo zz=c ) "
    V:\iffy2.bat [7]  Usage : IF [/I] [NOT] condition [.AND. | .OR. | .XOR. [NOT] condition ...] command
    First, what's "&|"? Guessing that it's an internal construct for implementing DuplicateBugs and delineating the actual batch file lines, the intended (?) strategy seems sound ... when the condition is false, go to the next line. But it doesn't seem to be doing that.[/QUOTE]
     
  12. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,806
    Likes Received:
    82
    This issue isn't actually about nested IF statements (which TCC handles fine), it's about what to do when a (badly-written) CMD-compatible batch file inserts additional non-IF statements inside a command group in an IF. I have made a change to 21.0.33 to match CMD's highly-erratic (and undocumented, and flat out wrong) behavior if you have the "Duplicate CMD bugs" enabled.
     
  13. Christian Albaret

    Joined:
    Jul 1, 2008
    Messages:
    154
    Likes Received:
    1
    Thanks for the change.
    I agree the syntax is awful.
    I have "Duplicate CMD bugs" enabled — but I seldom bump into the category of problems this check addresses (my own scripts are obviously written in clear TCC syntax), and I didn't make the connection.
     

Share This Page