Unable to pass batch file arguments unaltered

Aug 23, 2010
688
9
I have this script as a wrapper for Cygwin processes:

Code:
@SET PROMPT=@$S$P$_
@ECHO OFF
ON BREAK REM

CALL "%~dp0fix-path.btm"

SET ENV=%@PATH[%@FULL["%~0"]]env.exe
SET CMDNAME=%@EXECSTR[cygpath.exe -u "%~1"]
SHIFT

SET LANG=%@EXECSTR[locale -uU]
"%[ENV]" -- "%[CMDNAME]" "%$"
QUIT %?

Now, the problem is that it chokes when I pass it arguments enclosed in braces,
like your typical
Code:
git for-each-ref --format %(refname) %(objectname) --sort -committerdate
passage.

Is there a way to send arguments unaltered to the child process?
 

samintz

Scott Mintz
May 20, 2008
1,555
26
Solon, OH, USA
Is the problem the %(objectname) et. al.?
One option is to disable environment variable expansion using SETDOS /X. Another is to double up the %'s.
 
Aug 23, 2010
688
9
Yes, it is. Even with %@, the %(...) is executed before the program is called.
And the resulting command line contains
Code:
git for-each-ref --format 2 2 --sort -committerdate
where "2" looks like your usual "not found" return code. I appreciate the ability, but is it documented?
 
Aug 23, 2010
688
9
`SETDOS /X-4` doesn't work for the purpose.
TCC: Unknown command "refname"
TCC: Unknown command "objectname"
`SETDOS /X-3` breaks the script completely.
TCC: …\bin\cygwrap.btm [16] Unknown command "%[ENV]"

How to replace % with %% in an arbitrary string, if that string is evaluated long before I can make substitution?
 

samintz

Scott Mintz
May 20, 2008
1,555
26
Solon, OH, USA
I would think setdos /x-4 is what you want. However, I'm not clear on how what you posted gets called and when.

If your command is
Code:
git for-each-ref --format %(refname) %(objectname) --sort -committerdate
Then just double the %'s right there.
Code:
git for-each-ref --format %%(refname) %%(objectname) --sort -committerdate
 
Aug 23, 2010
688
9
My command is `git-wrapper.sh whatever arguments the caller decide to add`.
The association for ".sh" files is
Code:
$ assoc .sh
.sh=unixshell.script

$ ftype unixshell.script
unixshell.script="C:\Program Files\JPSoft\TCC-RT\TCC.EXE" /B /C "C:\Cygwin64\bin\cygwrap.btm" "%1" %*
 

samintz

Scott Mintz
May 20, 2008
1,555
26
Solon, OH, USA
I am not sure how you are invoking your scripts. I wrote a test framework:
Code:
assoc .foo=test.script
ftype test.script=c:\tc25\tcc.exe /b /c c:\tc25\echotest.btm %%*
I created echotest.btm:
Code:
@ECHO ON
setlocal
SET PROMPT=@$S$P$_
ON BREAK REM

rem CALL "%~dp0fix-path.btm"

SET ENV=%@PATH[%@FULL["%~0"]]env.exe
SET CMDNAME=%@EXECSTR[cygpath.exe -u "%~1"]
SHIFT

SET LANG=%@EXECSTR[locale -uU]
setdos /x-4
echo "%[ENV]" -- "%[CMDNAME]" "%$"
setdos /x0
QUIT %?
And then created test.foo which is basically empty. And invoked it:
Code:
test.foo git for-each-ref --format %%%%(refname) %%%%(objectname) --sort -committerdate
And got this output:
Code:
setlocal
SET PROMPT=@$S$P$_
ON BREAK REM
rem CALL "%~dp0fix-path.btm"
SET ENV=C:\tc25\env.exe
SET CMDNAME=test.foo
"C:\tc25\env.exe" -- "test.foo" "git for-each-ref --format %(refname) %(objectname) --sort -committerdate"
 

samintz

Scott Mintz
May 20, 2008
1,555
26
Solon, OH, USA
I think the arguments pass through the parser 2 or 3 times, and each time a % gets removed. Which is why I had to specify 4 %'s.

It might be easier to do a replace of some other symbol with %'s. e.g. #(refname) --> %(refname)
 
Aug 23, 2010
688
9
You had to write them 4 times because you passed the arguments from one command interpreter to another.
The fold before passing arguments to script was expected, the second, however, was not.
 
Aug 23, 2010
688
9
What quoting, can you please provide an example?
Just, before you do, I want to once again stress the fact I have no control over invocation of the script itself.
I can only work with what was passed to it.
 

rconn

Administrator
Staff member
May 14, 2008
12,556
167
What quoting, can you please provide an example?
Just, before you do, I want to once again stress the fact I have no control over invocation of the script itself.
I can only work with what was passed to it.

You didn't specify previously that you don't have control over invocation of the script.

SETDOS /X-4 won't help, as it only affects nested variables -- and you're not using nested variables.

To clarify, somebody else is passing a command (like "git for-each-ref --format %(refname) %(objectname) --sort -committerdate") to your script, and you need to pass the %(var) variables as-is?

If you have control over the command line, you'd just back quote the line to prevent all variable expansion.

If you don't, and you're trying to handle a command that's already been parsed *before* it's passed to the batch file -- that's more complicated. There are several issues:

1) The parentheses are not valid variable name characters;
2) So you need to turn off variable expansion, but if you do,
3) you'll disable the variable function expansion.

You could try turning on CMD-style variables (i.e., %var%) when you're parsing the input; then TCC won't think that "%(refname)" should be processed as a variable.
 

Similar threads