The double call is to break up parsing into 3 passes.
The first pass is carefully controlled and we precisely know the output:
Code: Select all
call(%%CMDCMDLINE:**=*%0%%_error_3
Otherwise, during this first pass, if %0 had already been expanded, inserted quotation marks, ampersands, etc. could blow everything up.
At the end of the first pass, one call is removed, and the second pass occurs following rules of expansion during a call (no delayed expansion, carets are doubled). The %0 is expanded, the %'s around CMDCMDLINE are halved and prepared for the next pass.
At the end of the second pass, the second call is removed, and the third pass occurs, also following rules of expansion during a call. The ( at the start of the call should be dummying out the call attempt (not actually tested) and this is when CMDCMDLINE gets modified and any control characters make stuff blow up. For whatever reason, things blowing up at this point doesn't make cmd.exe close, so that's nice.
I think I have all of that right. Maybe stuff blows up during the second pass and not the third; it's 3 AM and I kinda forget at the moment. Honestly, just change the double call to the reduced single call you suggest and observe the difference in errors.
double call:
Code: Select all
The following usage of the path operator in batch-parameter
substitution is invalid: %~.bat"%_error_3
For valid formats type CALL /? or FOR /?
CMDCMDLINE restored
["]
CMDCMDLINE restored
[]
Press any key to continue . . .
single call:
Code: Select all
The following usage of the path operator in batch-parameter
substitution is invalid: %~.bat"%_error_3
For valid formats type CALL /? or FOR /?
CMDCMDLINE restored
["]
'\..\test33' is not recognized as an internal or external command,
operable program or batch file.
'%%~.bat%_error_3' is not recognized as an internal or external command,
operable program or batch file.
CMDCMDLINE restored
[]
Press any key to continue . . .
Notice how the single call gives 2 "not recognized as an internal or external command" which indicate attempted file access. A parsing error is a much less serious error. The downside is calling a call has the same problem as calling any internal command where it searches %path% for a file named call. Since it's all wrapped in a setlocal anyway, I could just add
but I haven't gotten to that yet.
As to the weird REM's, I was attempting to trigger REM parsing rules during the second pass, but I think the results I was getting were a placebo. However, I was only able to get parsing errors (due to %~), and didn't see any bad command errors. Replacing
:^&rem; with
:^& serves the same purpose.
Edit - Here's a further iteration to play with. Unfortunately, it's getting more and more esoteric as it goes along. I'm not doing this to make it harder to read; just experimenting with different approaches to trigger variable expansion and avoid errors. At this point, changing to
call set might be viable, but I want to exhaust abuse of CMDCMDLINE first.
test34&%~.bat
Code: Select all
@setlocal
@echo off
:: @prompt;::$S$T$_
setlocal enabledelayedexpansion
path; & dpath; & set pathext=;
set ""=^" & set "{=!CMDCMDLINE!"
if not "!{:~10,1!"==":" goto:chk
if not "!{:~-2,1!"==" " goto:chk
(::
:;: !CMDCMDLINE:*:=*!!CMDCMDLINE:~0,1!)
2>nul call call(%%%%CMDCMDLINE:**=*%%0%%%%
set "}=!CMDCMDLINE:^^^^=^^!"
if "!}:~3,1!"==":" set ""=:^"
(::
:;: !CMDCMDLINE:~0,1!)
call(:^&%%CMDCMDLINE:**=!{:%%= !%%
(::
:;: !CMDCMDLINE:^^^^=^^!!CMDCMDLINE: =%%!)
if !CMDCMDLINE!==!{! echo CMDCMDLINE restored
:chk
endlocal & if not "%"%"=="" ( set ""="" ) else set ""=^"
echo [%"%]
if not defined ^" goto:jmp
"&"^&\..\test34^&%%~.bat test
:jmp
pause
cls
I trade out most of the calls for () label parsing rules. Only the two that are reliant on second+ passes still have calls. The placeholder characters for the %'s are TAB characters again. There must be a better placeholder I can use.
Queue