Nested IF syntax — TCC behaving differently to CMD

#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]
 
Last edited:
#2
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
 

rconn

Administrator
Staff member
May 14, 2008
10,644
97
#5
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.
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
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.
 

rconn

Administrator
Staff member
May 14, 2008
10,644
97
#7
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.
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.
 
Likes: evensenm

rconn

Administrator
Staff member
May 14, 2008
10,644
97
#8
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.
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).
 
Jul 29, 2016
36
1
#9
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.
 
Last edited:
Jul 29, 2016
36
1
#10
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
This is an issue in TCC that is inconsistent with what the documentation states.
The documentation for the IF command states (excerpt):
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]
 

rconn

Administrator
Staff member
May 14, 2008
10,644
97
#12
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
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.