Command line parsing differences between cmd.exe and TCC

Nov 6, 2014
26
0
When using TCC (v23.00.25 x64 on Win7 SP1) I find that the Subversion (svn) diff command doesn't get parsed the same way as cmd.exe does it.

In order for svn to integrate with a GUI diff utility, you write a script that parses a bunch of command line options then have the script turn around and pass the options in the order and with the switches appropriate for the GUI diff program (Beyond Compare in my case).

I found that the script that was working in cmd.exe broke when I tried it in TCC. Here's a version of the script that simply dumps the arguments passed to it:

=============
@echo off
echo all args: :%*:
echo arg1: :%1:
echo arg2: :%2:
echo arg3: :%3:
echo arg4: :%4:
echo arg5: :%5:
echo arg6: :%6:
echo arg7: :%7:
echo arg8: :%8:
=============

Here's what cmd.exe displays when svn passes the diff arguments to it:

=============
all args: :-u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0:
arg1: :-u:
arg2: :-L:
arg3: :"CalcsMgr/CalcsMgr.c (revision 38085)":
arg4: :-L:
arg5: :"CalcsMgr/CalcsMgr.c (working copy)":
arg6: :D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base:
arg7: :C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0:
arg8: ::
=============

And here's what I get when the script is run in TCC:

=============
all args: :*:
arg1: :-u:
arg2: :-L:
arg3: :"CalcsMgr/CalcsMgr.c:
arg4: :(revision:
arg5: :38085)":
arg6: :-L:
arg7: :"CalcsMgr/CalcsMgr.c:
arg8: :(working:
=============

So my questions are:

- is this a TCC bug?
- if not, is there a way I can have one batch file that parses the command line the same way in both cmd.exe and in TCC?
- why doesn't TCC expand the %* construct when it is immediately followed by a ':'? It only does this when it is immediately followed by a colon - and I often use a colon as a delimiter when debugging command line arguments because I find that using quotes makes it difficult to spot how quotes are actually being used.


Thanks
 
Nov 6, 2014
26
0
One more bit of information I just found: if I run the script from the TCC command line the parsting works:

============
[D:\devtrees\CPA_ExtRAM\trunk]bc4svn -u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_ExtRAM\trunk
\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0
all args: :*:
arg1: :-u:
arg2: :-L:
arg3: :"CalcsMgr/CalcsMgr.c (revision 38085)":
arg4: :-L:
arg5: :"CalcsMgr/CalcsMgr.c (working copy)":
arg6: :D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base:
arg7: :C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0:
arg8: ::
============

Update (again): I added a "pause" command to the end of the script so I could see exactly how svn.exe is invoking the batch file with the "Process Explorer" tool. It turns out that svn is wrapping the whole command line in double-quotes (and escaping parens and backslashes).

Invoked from cmd.exe:
===============
C:\Windows\system32\cmd.exe /C ""C:\util\bc4svn.bat" -u -L ^"CalcsMgr/CalcsMgr.c ^(revision 38085^)^" -L ^"CalcsMgr/CalcsMgr.c ^(working copy^)^" D:^\devtrees^\CPA_ExtRAM^\trunk^\.svn^\pristine^\19^\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:^\Users^\burrm^\AppData^\Local^\Temp^\svn-51900A6C"
===============


Invoked from TCC:
============
"C:\Program Files\JPSoft\TCMD23\TCC.EXE" /C ""C:\util\bc4svn.bat" -u -L ^"CalcsMgr/CalcsMgr.c ^(revision 38085^)^" -L ^"CalcsMgr/CalcsMgr.c ^(working copy^)^" D:^\devtrees^\CPA_ExtRAM^\trunk^\.svn^\pristine^\19^\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:^\Users^\burrm^\AppData^\Local^\Temp^\svn-48439300"
============



TCC does what I'd like it to do if the 'outer' double quotes are removed:

============
[D:\devtrees\CPA_ExtRAM\trunk]"C:\Program Files\JPSoft\TCMD23\TCC.EXE" /C "C:\util\bc4svn.bat" -u -L ^"CalcsMgr/CalcsMgr.c ^(revision 38085^)^" -L ^"CalcsMgr/CalcsMgr.c ^(working copy^)^" D:^\devtrees^\CPA_ExtRAM^\trunk^\.svn^\pristine^\19^\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:^\Users^\burrm^\AppData^\Local^\Temp^\svn-48439300
all args: :*:
arg1: :-u:
arg2: :-L:
arg3: :"CalcsMgr/CalcsMgr.c (revision 38085)":
arg4: :-L:
arg5: :"CalcsMgr/CalcsMgr.c (working copy)":
arg6: :D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base:
arg7: :C:\Users\burrm\AppData\Local\Temp\svn-48439300:
arg8: ::
============

I think that wrapping an entire command in double-quotes even when arguments are double-quoted is not an uncommon behavior, taking advantage of on of the hundreds of quirks/bugs in cmd.exe (but I don't really know that for sure - I don't know how rconn stays sane trying to keep TCC backwards compatible with cmd.exe).

Is there some reasonable way I can get TCC to handle this in a cmd.exe compatible way?
 
Last edited:
Nov 6, 2014
26
0
1. Use code blocks.

Are you talking about the Code::Blocks IDE? I'm not using an IDE at all, so I'm not sure what that would have to do with anything.

2. Finally explain, what you invoke and how.

I have posted the simple batch file that parses the command line. I have also posted information about how Subversion invokes the script which seems to be the root of the problem: the whole command line is enclosed in double-quotes while it contains items that are also quoted using double quotes.
 
May 20, 2008
11,437
99
Syracuse, NY, USA
the whole command line is enclosed in double-quotes while it contains items that are also quoted using double quotes.
That's not a good idea. Without :: TCC's %* works better. Besides that, I see that TCC and CMD work the same if there are or are not an outer set of quotes. (What appears next is a code block.)
Code:
v:\> type allargs.bat
@echo off
 echo all args: %*
 echo arg1: :%1:
 echo arg2: :%2:
 echo arg3: :%3:
 echo arg4: :%4:
 echo arg5: :%5:
 echo arg6: :%6:
 echo arg7: :%7:
 echo arg8: :%8:
v:\> allargs.bat -u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_Ex
tRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6
D8A0
all args: -u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0
arg1: :-u:
arg2: :-L:
arg3: :"CalcsMgr/CalcsMgr.c (revision 38085)":
arg4: :-L:
arg5: :"CalcsMgr/CalcsMgr.c (working copy)":
arg6: :D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base:
arg7: :C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0:
arg8: ::

v:\> cmd /c allargs.bat :-u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtree
s\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\
svn-4DC6D8A0
all args: :-u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0
arg1: ::-u:
arg2: :-L:
arg3: :"CalcsMgr/CalcsMgr.c (revision 38085)":
arg4: :-L:
arg5: :"CalcsMgr/CalcsMgr.c (working copy)":
arg6: :D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base:
arg7: :C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0:
arg8: ::

Here's another code block showing what happens when outer quotes are added.
Code:
v:\> allargs.bat "-u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_E
xtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC
6D8A0"
all args: "-u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0"
arg1: :"-u -L "CalcsMgr/CalcsMgr.c:
arg2: :(revision:
arg3: :38085)" -L "CalcsMgr/CalcsMgr.c:
arg4: :(working:
arg5: :copy)" D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0":
arg6: ::
arg7: ::
arg8: ::

v:\> cmd /c allargs.bat "-u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtree
s\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\
svn-4DC6D8A0"
all args: "-u -L "CalcsMgr/CalcsMgr.c (revision 38085)" -L "CalcsMgr/CalcsMgr.c (working copy)" D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0"
arg1: :"-u -L "CalcsMgr/CalcsMgr.c:
arg2: :(revision:
arg3: :38085)" -L "CalcsMgr/CalcsMgr.c:
arg4: :(working:
arg5: :copy)" D:\devtrees\CPA_ExtRAM\trunk\.svn\pristine\19\19ec3da79b2b6ceb9eced5aee49da6d1efe261cb.svn-base C:\Users\burrm\AppData\Local\Temp\svn-4DC6D8A0":
arg6: ::
arg7: ::
arg8: ::
 
Nov 6, 2014
26
0
The problem seems to boil down to the '^' quoting escaping of the double-quotes around arguments. The following examples use Vincent's "allargs.bat" script:

TCC:
Code:
[C:\temp]ver

TCC  23.00.25 x64   Windows 7 [Version 6.1.7601]

[C:\temp]allargs.bat ^"1 2^" 3
all args: "1 2" 3
arg1: :"1:
arg2: :2":
arg3: :3:
arg4: ::
arg5: ::
arg6: ::
arg7: ::
arg8: ::

cmd.exe:
Code:
C:\temp>ver

Microsoft Windows [Version 6.1.7601]

C:\temp>allargs.bat ^"1 2^" 3
all args: "1 2" 3
arg1: :"1 2":
arg2: :3:
arg3: ::
arg4: ::
arg5: ::
arg6: ::
arg7: ::
arg8: ::
 
Last edited:
Nov 6, 2014
26
0
I think I have a reasonable workaround:

Code:
@echo off
set ALLARGS=%*
call :doit %ALLARGS%
goto :eof
 
:doit
echo arg1: :%1:
echo arg2: :%2:
echo arg3: :%3:
echo arg4: :%4:
echo arg5: :%5:
echo arg6: :%6:
echo arg7: :%7:
echo arg8: :%8:
goto :eof



TCC (I get same results with cmd.exe):

Code:
[C:\temp]allargs.bat ^"1 2^" 3
arg1: :"1 2":
arg2: :3:
arg3: ::
arg4: ::
arg5: ::
arg6: ::
arg7: ::
arg8: ::


Note that if instead of passing %ALLARGS% to :doit I pass %*, TCC still parses the arguments to :doit in a way that splits the "1 and the 2" tokens. I don't know why that would be, but I'm not sure I care all that much.

To be clear, I think that TCC is behaving entirely reasonably - escaping the quotes should be an indication that the quotes be treated as normal characters not as quotes (that's what bash would do). However, cmd.exe doesn't do that and Subversion seems to rely on that cmd.exe bug. And that puts TCC in a bad position.

Anyway, I'm perfectly happy with the workaround. So rconn can do whatever he likes with this information (including ignoring it).

Thanks for helping!
 
Similar threads
Thread starter Title Forum Replies Date
J Python: TCC command line parsing removes '=' equal sign characters Support 4
H command line parsing question Support 5
cgunhouse One of the Focuses of V17 Beta Testing Should Be Command Line Parsing Support 1
T VIEW only works from command line Support 14
vefatica `Back quotes` - command line vs. batch file Support 5
Phileosophos Is there any way to open the Take Command options dialog from the command line? Support 8
Phileosophos Command-line Editing Shortkeys That Fail Support 6
D Open Windows 10 Photos app from command line Support 11
fpefpe How to? command echo in title line/bar Support 2
vefatica Command line DO with no closing parenthesis? Support 9
R Long commands retrieved from command history have blank line when wrapped Support 20
D Double Quote in TC Tool Bar Button Command line Support 3
Joe Caverly Expand all aliases on the command line Support 2
Jay Sage Cannot Postion Cursor in Command Line Using Mouse Support 7
vefatica IDE.EXE's command line? Support 19
D btm file command line augments comparing for string or math. Support 12
P Escape key no longer clears command line in v24 Support 21
J File explorer handling from command line? Support 2
M Ctrl-C when using command line history does nothing Support 2
C Replace 1st argument on command line Support 4
K Command Line Selection Not Working Support 12
J Error running Python at command line Support 9
rps How to? Alias/Command line use of *log on/off Support 2
x13 //directive ignored on TCC command-line Support 4
J How to? max. practical command line length? Support 3
mfarah WAD Odd behaviour with command-line arguments on TCMD. Support 7
thorntonpg F1 on command line The webpage cannot be found Support 5
L Fixed console line length in Take Command 19? Support 3
C LOG entry for TCMD/TCC command line Support 15
Joe Caverly How to? Date Range in command line for 7zip /= Support 1
cgunhouse Jabber Command Line Option Being Transmitted -- Fixed with Build 42 Support 2
M Hotkey-mechanism, for doing something with the current command-line Support 4
J Passing % character through command line to .btm Support 5
vefatica Command line SETLOCAL? Support 11
tmaynard How to? Control-U alias for Escape (command line editing) Support 5
BobK How to? Handling filenames with blanks at command line Support 3
CWBillow Send Command-line with prompt? Support 6
M Missing PERL command-line arguments Support 1
fpefpe WAD Python support does not process command line Support 14
vefatica SENDMAIL, command line override SMTP server? Support 2
vefatica (OT) Show desktop from command line? Support 20
M Starting Windows GUI programs from the command line... Support 10
A How to? Remove last argument on command line Support 4
nickles Reload tcmd.ini from the command line Support 11
A How to? Invoke View Clipboard from command line Support 8
ehab aboudaya How to? activate tab with same directory in command line Support 6
A minor documentation fix - command line editing Support 0
A Minor documentation fix ["-" on command line] Support 3
A WAD BOM printed on command line from BAT file Support 5
J command line cursor keeps reverting to overstrike Support 6

Similar threads