"Functions" in cmd.exe batch files

This (test.cmd) works in cmd.exe
Code:
@echo off
ver
where cmd.exe
set "TwoParams(x,y)= x=x,y , y=(x,y)"
set /A "test=%TwoParams(x,y):x,y=123,456%"
echo x=%x%, y=%y%
...returns...
Code:
c:\utils>test.cmd

Microsoft Windows [Version 6.1.7601]
C:\Windows\System32\cmd.exe
x=123, y=456
When I run it under CMDebug using CMD Syntax, it returns;
Code:
TCC-RT  23.00.17 x64   Windows 7 [Version 6.1.7601]
x=123456, y=456
...which is not what I get with cmd.exe

When I run it under CMDebug using TCC Syntax, it returns;
Code:
TCC-RT  23.00.17 x64   Windows 7 [Version 6.1.7601]
C:\Windows\System32\cmd.exe
x=123456, y=456
When I run test.cmd from TCC, it returns;
Code:
c:\users\jlc\utils>test.cmd

TCC  23.00.23 x64   Windows 7 [Version 6.1.7601]
C:\Windows\System32\cmd.exe
TCC: C:\Users\jlc\utils\test.cmd [5]  Unbalanced parentheses "(x"
x=, y=
Joe
 
May 20, 2008
10,624
81
Syracuse, NY, USA
Joe, can you explain what CMD is doing.

At the CMD command line, I get this.
Code:
V:\> set "TwoParams(x,y)= x=x,y , y=(x,y)"

V:\> set /A "test=%TwoParams(x,y):x,y=123,456%"
456
V:\> echo %test%
123
If the "final value of the expression" were 456 (as auto-echoed by SET /A) why was 123 assigned to the variable "test"?
 
A better example;
Code:
@echo off
setlocal EnableDelayedExpansion
ver
where cmd.exe
set "Max(x,y)=( x=x,y, y=(x,y), c=(x-y>>31)+1, c*x+^^^!c*y )"
set "Min(x,y)=!Max(x,y):x-y=y-x!"

echo/
set numbers=123 456
set /A "n1=%numbers: =,n2=%, max=%Max(x,y):x,y=n1,n2%, min=%Min(x,y):x,y=n1,n2%"
echo Max = %max%,  Min = %min%
echo x=%x%, y=%y%
Joe
 

samintz

Scott Mintz
May 20, 2008
1,422
13
Solon, OH, USA
I can sort of grasp the string substitution when invoking a function. But the way the function itself works is voodoo. Can you explain what exactly the MAX function is doing?
Code:
it looks like when the set /A is executed, you get:
set /A "n1=123,n2=456, max=( x=123,456, y=(123,456), c=(123-456>>31)+1, 0*123+^^^!0*456 )"
It looks like SET /A var=x,y sets var to x. And SET /A var=(x,y), sets var to y. And it looks like the expression is evaluated from left to right.
But what do the 3 ^^^'s do?
 

rconn

Administrator
Staff member
May 14, 2008
11,926
133
That syntax is simply bizarre. You're combining two undocumented CMD behaviors to derive a third that I doubt even the CMD authors intended.

I would be very interested in where you found this documented or used, and exactly (as in step by step) what you think it's doing.
 

rconn

Administrator
Staff member
May 14, 2008
11,926
133
The first issue here is that due to the use of invalid characters in the variable name, you have to set CMDVariables=Yes in your TCMD.INI for TCC to accept the variable name in "test=%TwoParams(x,y):x,y=123,456%". TCC then, like CMD, simply accepts anything between the two %'s.

The second issue is that TCC sees "x=123,456" and interprets the comma as a thousands separator, not an argument delimiter. (TCC works fine with the equally silly undocumented CMD syntax "set /a x=1,y=2,z=3" because the comma isn't embedded in a numeric string.)

The third issue is the undocumented CMD behavior when you give it multiple arguments. For example:

set /a test=123,456

echos "456" (at the command prompt, but not in a batch file), and sets test to 123. That's a little odd, but not as odd as issue four:

set /a test=(123,456)

which sets test to 456.

Now, I can support issue #2 by disallowing thousands separators (not a big issue, because only CMD batch files would be using this grotesque syntax anyway).

Regarding #3 and #4 -- I'm unconvinced that the CMD authors intended this behavior (and if they did, someone should slap them upside the head). But if someone wants to post it in the Suggestions Forum (with a convincing explanation of why this is a good idea), I'll consider it for a future version.