Page 1 of 1

IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 17 May 2024 17:58
by CJM
In my debugging of IF statements, I've noticed that the evaluation equation is ECHO-suppressed sometimes so that the echoed IF statement doesn't reveal the values being compared, obviously impeding the intended debugging. So far, I've localized this phenomenon to equations where the resulting equation begins with a colon (:) character. I haven't identified if this happens with any other character.

Note: I'm not referring to values being suppressed using the ECHO command. I'm referring to the echoed IF statements when command ECHO is ON: they're missing only the resulting equation when that equation begins with a colon (:) character, either hard-coded or as a variable (not shown since it's irrelevant).

Here's the example batch file I used (name it anything.bat or .cmd):

Code: Select all

@FOR %%$ in ($)do IF :0==:0	ECHO/[Evaluation SUPPRESSED, true]
@FOR %%$ in ($)do IF :0==10	ECHO/[Evaluation SUPPRESSED, false] 
@FOR %%$ in ($)do IF 0==:10	ECHO/[Evaluation printed, false] 
@FOR %%$ in ($)do IF 0==0	ECHO/[Evaluation printed, true]
@FOR %%$ in ($)do IF(0)==(0)	ECHO/[Evaluation printed, true]
@FOR %%$ in ($)do IF (0==(0	ECHO/[Evaluation printed, true]
@FOR %%$ in ($)do IF :0:==:0:	ECHO/[Evaluation SUPPRESSED, true]
@FOR %%$ in ($)do IF:0:==:0:	ECHO/[Evaluation printed, error] The filename, directory name, or volume label syntax is incorrect. 
@FOR %%$ in ($)do IF 0:==0:	ECHO/[Evaluation printed, true]
I'm using "@FOR %%$ in ($)do " to see the resulting IF evaluation ECHOed in batch. One can omit that part when testing the IF commands directly at the command prompt.

Output:

Code: Select all

C:\Test>IF ECHO/[Evaluation SUPPRESSED, true]
[Evaluation SUPPRESSED, true]

C:\Test>IF ECHO/[Evaluation SUPPRESSED, false]

C:\Test>IF 0 == :10 ECHO/[Evaluation printed, false]

C:\Test>IF 0 == 0 ECHO/[Evaluation printed, true]
[Evaluation printed, true]

C:\Test>IF (0) == (0) ECHO/[Evaluation printed, true]
[Evaluation printed, true]

C:\Test>IF (0 == (0 ECHO/[Evaluation printed, true]
[Evaluation printed, true]

C:\Test>IF ECHO/[Evaluation SUPPRESSED, true]
[Evaluation SUPPRESSED, true]

C:\Test>IF:0:==:0:       ECHO/[Evaluation printed, error] The filename, directory name, or volume label syntax is incorrect.
The filename, directory name, or volume label syntax is incorrect.

C:\Test>IF 0: == 0: ECHO/[Evaluation printed, true]
[Evaluation printed, true]
In my examples, I did intentionally include a few with no token delimiter after the "IF" command, having noticed that "IF(" is acceptable syntax but "IF:" is not, instead resulting in a filename ... syntax error. I'm minorly curious about this error too--why it's being interpreted as some invalid filename, but the main issue...

My question: Why would this be a thing? It just seems so random that leading the equation with a colon suppresses the equation itself from being ECHOed, but I'm wondering if I'm missing some hidden purpose to this behavior, and (even better) if there's a way to stop it and always display the equation when ECHO is ON.

Re: IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 18 May 2024 04:45
by jeb
Hi CJM,

interessting finding :D
But, I don't understand why you used the prefix of: "@FOR %%$ in ($)do"
This only seems to complicate things without bringing any benefit.

Some of my thoughts and findings:
- The echo cancellation only appears to be for ":"
- The echo cancellation can be fixed by a simple prefix with any other character like IF _:bla== or IF ":bla"==...
- The echo cancellation can be fixed by a delayed expansion variable

Code: Select all

set "VAR=:bla"
IF !VAR! == :bla ECHO/[Evaluation printed, true] 
- My best guess: The label handling suppresses the echo, for just this token, that could explain why the "IF" itself is still visible

Code: Select all

IF :label == something MY-COMMAND
results to the output of:
C:\Users\jeb\bat>IF MY-COMMAND
- Currently I can't see how this behavior could be misused in any good way :(

Re: IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 18 May 2024 06:39
by T3RRY
Nothing to add on the why, but another finding to add

Using CMD /c to conduct the If operation will show the full command

for testing from the command line:

Code: Select all

@For %G in (":0" "0" "0:")Do cmd /c if %~G==%~G echo [%~G==%~G true]
@For %G in (":0" "0" "0:")Do if %~G==%~G echo [%~G==%~G true]

Re: IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 19 May 2024 16:37
by CJM
jeb wrote:
18 May 2024 04:45
...
But, I don't understand why you used the prefix of: "@FOR %%$ in ($)do"
This only seems to complicate things without bringing any benefit.
...
Good point! I can't remember why I had to do that my first time through, and it might only be needed inside a parenthetical block, but you're right: with ECHO ON, it's not necessary in my example, and this works just as well:

Code: Select all

IF :0==:0	ECHO/[Evaluation SUPPRESSED, true]
IF :0==10	ECHO/[Evaluation SUPPRESSED, false] 
IF 0==:10	ECHO/[Evaluation printed, false] 
IF 0==0	ECHO/[Evaluation printed, true]
IF(0)==(0)	ECHO/[Evaluation printed, true]
IF (0==(0	ECHO/[Evaluation printed, true]
IF :0:==:0:	ECHO/[Evaluation SUPPRESSED, true]
IF:0:==:0:	ECHO/[Evaluation printed, error] The filename, directory name, or volume label syntax is incorrect. 
IF 0:==0:	ECHO/[Evaluation printed, true]
jeb wrote:
18 May 2024 04:45
- The echo cancellation only appears to be for ":"
I'm curious: did you validate this by testing other characters, or is this based on the idea that it's related to label handling? I plan to test a selection of other characters when I have time.
jeb wrote:
18 May 2024 04:45
- The echo cancellation can be fixed by a simple prefix with any other character like IF _:bla== or IF ":bla"==...
This is a decent work-around! I think prefacing with double quotes is the safest universal for both arguments and FOR variables, e.g.: IF ""%1=="":0 ...
jeb wrote:
18 May 2024 04:45
- The echo cancellation can be fixed by a delayed expansion variable

Code: Select all

set "VAR=:bla"
IF !VAR! == :bla ECHO/[Evaluation printed, true] 
Interesting, except that the variable name is then echoed and doesn't achieve my original purpose: that of being able to see the resulting variable values being evaluated.
jeb wrote:
18 May 2024 04:45
- My best guess: The label handling suppresses the echo, for just this token, that could explain why the "IF" itself is still visible

Code: Select all

IF :label == something MY-COMMAND
results to the output of:
C:\Users\jeb\bat>IF MY-COMMAND
It makes sense that label handling is involved somehow, and it makes me wonder if there is any other case where a single token's visibility is suppressed.
jeb wrote:
18 May 2024 04:45
- Currently I can't see how this behavior could be misused in any good way :(
I actually wasn't looking for a way to misuse the behavior, but that'd be interesting too!

Re: IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 19 May 2024 16:53
by CJM
T3RRY wrote:
18 May 2024 06:39
Using CMD /c to conduct the If operation will show the full command
This makes sense since the original command processor is doing the echoing at that point. :D This could work for debugging a one-line statement. However, for the more complex debugging scenarios I originally intended, such as nested IF statements, I think adding a secondary command processor in the mix introduces too much complexity to the situation given that variables can have multiple variables depending on which command processor is doing the interpreting.

Re: IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 20 May 2024 11:54
by CJM
Trying a bunch of other leading characters, only the colon (:) exhibits the equation-suppression behavior:

Code: Select all

C:\Test>IF ?0 == false ECHO

C:\Test>IF *0 == false ECHO

C:\Test>FOR %# in (: "%" "^" "&" "|" ";" "," "=" ` ~ ! @ # $ - _ + \ / [ ] { } .)do IF %~#0 == false ECHO

C:\Test>IF ECHO

C:\Test>IF %0 == false ECHO

C:\Test>IF ^0 == false ECHO

C:\Test>IF &0 == false ECHO

C:\Test>IF |0 == false ECHO

C:\Test>IF ;0 == false ECHO

C:\Test>IF ,0 == false ECHO

C:\Test>IF =0 == false ECHO

C:\Test>IF `0 == false ECHO

C:\Test>IF ~0 == false ECHO

C:\Test>IF !0 == false ECHO

C:\Test>IF @0 == false ECHO

C:\Test>IF #0 == false ECHO

C:\Test>IF $0 == false ECHO

C:\Test>IF -0 == false ECHO

C:\Test>IF _0 == false ECHO

C:\Test>IF +0 == false ECHO

C:\Test>IF \0 == false ECHO

C:\Test>IF /0 == false ECHO

C:\Test>IF [0 == false ECHO

C:\Test>IF ]0 == false ECHO

C:\Test>IF {0 == false ECHO

C:\Test>IF }0 == false ECHO

C:\Test>IF .0 == false ECHO

Re: IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 20 May 2024 12:12
by CJM
Each leading-colon-equation token is echo-suppressed in a nested IF too:

Code: Select all

C:\Test>FOR %$ in ($)do IF :0 == :0 IF :0 == false ECHO

C:\Test>IF IF ECHO

Re: IF Evaluation Values Are ECHO-Suppressed When Beginning With Colon ":". Why?

Posted: 21 May 2024 11:35
by T3RRY
CJM wrote:
20 May 2024 12:12
Each leading-colon-equation token is echo-suppressed in a nested IF too:

Code: Select all

C:\Test>FOR %$ in ($)do IF :0 == :0 IF :0 == false ECHO

C:\Test>IF IF ECHO
Reviewing the command parsing behaviour as described on this forum and Stackoverflow, I believe Jeb is bang on the money with regards to the behaviour being the result of label parsing in phase 2.

The following are relevant in describing the behaviour which occurs during phase 2:
IF is split into two or three distinct parts that are processed independently. A syntax error in the IF construction will result in a fatal syntax error.
The comparison operation is the actual command that flows all the way through to phase 7
All IF options are fully parsed in phase 2.

Executed Label - A label that is not fully detected until phase 7
All prior phases are applied to the label, but then during execution, the label is ignored (not really executed), or else results in an error, or in rare cases, changes the current volume.
There are two basic classes of executed labels
Delayed label - The command token did not begin with a colon in phase 2. The leading colon only appears after FOR expansion in phase 4 or delayed expansion in phase 5
The following occurs when an executed label is discovered in phase 2
The label, its arguments, and its redirection are all excluded from any echo output in phase 3
Any subsequent concatenated commands on the line are fully parsed and executed
While not explicitly described as a known case resulting in an executed label, the described behaviour is precisely what is occuring.