diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | tests/winPipe.test | 78 | ||||
-rw-r--r-- | win/tclAppInit.c | 152 | ||||
-rw-r--r-- | win/tclWinPipe.c | 10 |
4 files changed, 92 insertions, 156 deletions
@@ -1,3 +1,11 @@ +2004-02-01 David Gravereaux <davygrvy@pobox.com> + + * tests/winPipe.test: more pass-thru commandline verifications. + * win/tclWinPipe.c (BuildCommandLine): Special case quoting for + '{' not required by the c-runtimes's _setargv(). + * win/tclAppInit.c: Removed our custom setargv() in favor of + the one provided by the c-runtime. [Bug 672938] + 2004-01-30 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: Use the -GZ compiler switch when building for diff --git a/tests/winPipe.test b/tests/winPipe.test index 26a7e33..51b26ef 100644 --- a/tests/winPipe.test +++ b/tests/winPipe.test @@ -12,7 +12,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: winPipe.test,v 1.22 2002/12/17 02:47:39 davygrvy Exp $ +# RCS: @(#) $Id: winPipe.test,v 1.23 2004/02/01 09:37:49 davygrvy Exp $ package require tcltest namespace import -force ::tcltest::* @@ -315,12 +315,80 @@ set path(echoArgs.tcl) [makeFile { puts "[list $argv0 $argv]" } echoArgs.tcl] + +### validate the raw output of BuildCommandLine(). +### test winpipe-7.1 {BuildCommandLine: null arguments} {pcOnly exec} { - exec [interpreter] $path(echoArgs.tcl) foo "" bar -} [list $path(echoArgs.tcl) {foo {} bar}] + exec $env(COMSPEC) /c echo foo "" bar +} {foo "" bar} test winpipe-7.2 {BuildCommandLine: null arguments} {pcOnly exec} { - exec [interpreter] $path(echoArgs.tcl) foo \" bar -} [list $path(echoArgs.tcl) {foo {"} bar}] + exec $env(COMSPEC) /c echo foo {} bar +} {foo "" bar} +test winpipe-7.3 {BuildCommandLine: dbl quote quoting #1} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo {"} bar +} {foo \" bar} +test winpipe-7.4 {BuildCommandLine: dbl quote quoting #2} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo {""} bar +} {foo \"\" bar} +test winpipe-7.5 {BuildCommandLine: dbl quote quoting #3} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo {" } bar +} {foo "\" " bar} +test winpipe-7.6 {BuildCommandLine: dbl quote quoting #4} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo {a="b"} bar +} {foo a=\"b\" bar} +test winpipe-7.7 {BuildCommandLine: dbl quote quoting #5} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo {a = "b"} bar +} {foo "a = \"b\"" bar} +test winpipe-7.8 {BuildCommandLine: dbl quote quoting #6} {pcOnly exec} { + exec $env(COMSPEC) /c echo {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} {he " llo} +} {\"hello\" \"\"hello\"\" \"\"\"hello\"\"\" \"\\\"hello\\\"\" "he llo" "he \" llo"} +test winpipe-7.9 {BuildCommandLine: special chars #1} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo \\ bar +} "foo \\ bar" +test winpipe-7.10 {BuildCommandLine: special chars #2} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo \{ bar +} "foo \{ bar" +test winpipe-7.11 {BuildCommandLine: special chars #3} {pcOnly exec} { + exec $env(COMSPEC) /c echo foo \} bar +} "foo \} bar" + +### validate the pass-thru from BuildCommandLine() to the crt's setargv(). +### +test winpipe-8.1 {BuildCommandLine/setargv pass-thru: null arguments} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo "" bar +} [list $path(echoArgs.tcl) [list foo {} bar]] +test winpipe-8.2 {BuildCommandLine/setargv pass-thru: null arguments} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo {} bar +} [list $path(echoArgs.tcl) [list foo {} bar]] +test winpipe-8.3 {BuildCommandLine/setargv pass-thru: dbl quote quoting #1} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo {"} bar +} [list $path(echoArgs.tcl) [list foo {"} bar]] +test winpipe-8.4 {BuildCommandLine/setargv pass-thru: dbl quote quoting #2} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo {""} bar +} [list $path(echoArgs.tcl) [list foo {""} bar]] +test winpipe-8.5 {BuildCommandLine/setargv pass-thru: dbl quote quoting #3} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo {" } bar +} [list $path(echoArgs.tcl) [list foo {" } bar]] +test winpipe-8.6 {BuildCommandLine/setargv pass-thru: dbl quote quoting #4} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo {a="b"} bar +} [list $path(echoArgs.tcl) [list foo {a="b"} bar]] +test winpipe-8.7 {BuildCommandLine/setargv pass-thru: dbl quote quoting #5} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo {a = "b"} bar +} [list $path(echoArgs.tcl) [list foo {a = "b"} bar]] +test winpipe-8.8 {BuildCommandLine/setargv pass-thru: dbl quote quoting #6} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} +} [list $path(echoArgs.tcl) [list {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo}]] +test winpipe-8.9 {BuildCommandLine/setargv pass-thru: special chars #1} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo \\ bar +} [list $path(echoArgs.tcl) [list foo \\ bar]] +test winpipe-8.10 {BuildCommandLine/setargv pass-thru: special chars #2} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo \{ bar +} [list $path(echoArgs.tcl) [list foo \{ bar]] +test winpipe-8.11 {BuildCommandLine/setargv pass-thru: special chars #3} {pcOnly exec} { + exec [interpreter] $path(echoArgs.tcl) foo \} bar +} [list $path(echoArgs.tcl) [list foo \} bar]] + + # restore old values for env(TMP) and env(TEMP) diff --git a/win/tclAppInit.c b/win/tclAppInit.c index 0b1d659..7f8f412 100644 --- a/win/tclAppInit.c +++ b/win/tclAppInit.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclAppInit.c,v 1.16 2004/01/16 02:46:10 davygrvy Exp $ + * RCS: @(#) $Id: tclAppInit.c,v 1.17 2004/02/01 09:37:49 davygrvy Exp $ */ #include "tcl.h" @@ -28,12 +28,10 @@ extern int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif #endif /* TCL_TEST */ -static void setargv _ANSI_ARGS_((int *argcPtr, char ***argvPtr)); -static BOOL __stdcall sigHandler (DWORD fdwCtrlType); +static BOOL WINAPI sigHandler (DWORD fdwCtrlType); static Tcl_AsyncProc asyncExit; static void AppInitExitHandler(ClientData clientData); -static char ** argvSave = NULL; static Tcl_AsyncHandler exitToken = NULL; static DWORD exitErrorCode = 0; @@ -56,9 +54,9 @@ static DWORD exitErrorCode = 0; */ int -main(argc, argv) - int argc; /* Number of command-line arguments. */ - char **argv; /* Values of command-line arguments. */ +main( + int argc, /* Number of command-line arguments. */ + char **argv) /* Values of command-line arguments. */ { /* * The following #if block allows you to change the AppInit @@ -82,29 +80,20 @@ main(argc, argv) extern int TCL_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv)); #endif - char buffer[MAX_PATH +1]; char *p; + /* * Set up the default locale to be standard "C" locale so parsing * is performed correctly. */ setlocale(LC_ALL, "C"); - setargv(&argc, &argv); /* - * Save this for later, so we can free it. + * Forward slash substitute argv[0] for backslashes. */ - argvSave = argv; - /* - * Replace argv[0] with full pathname of executable, and forward - * slashes substituted for backslashes. - */ - - GetModuleFileName(NULL, buffer, sizeof(buffer)); - argv[0] = buffer; - for (p = buffer; *p != '\0'; p++) { + for (p = argv[0]; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } @@ -118,7 +107,6 @@ main(argc, argv) return 0; /* Needed only to prevent compiler warning. */ } - /* *---------------------------------------------------------------------- @@ -245,11 +233,6 @@ static void AppInitExitHandler( ClientData clientData) { - if (argvSave != NULL) { - ckfree((char *)argvSave); - argvSave = NULL; - } - if (exitToken != NULL) { /* * This should be safe to do even if we @@ -261,123 +244,6 @@ AppInitExitHandler( } /* - *------------------------------------------------------------------------- - * - * setargv -- - * - * Parse the Windows command line string into argc/argv. Done here - * because we don't trust the builtin argument parser in crt0. - * Windows applications are responsible for breaking their command - * line into arguments. - * - * 2N backslashes + quote -> N backslashes + begin quoted string - * 2N + 1 backslashes + quote -> literal - * N backslashes + non-quote -> literal - * quote + quote in a quoted string -> single quote - * quote + quote not in quoted string -> empty string - * quote -> begin quoted string - * - * Results: - * Fills argcPtr with the number of arguments and argvPtr with the - * array of arguments. - * - * Side effects: - * Memory allocated. - * - *-------------------------------------------------------------------------- - */ - -static void -setargv(argcPtr, argvPtr) - int *argcPtr; /* Filled with number of argument strings. */ - char ***argvPtr; /* Filled with argument strings (malloc'd). */ -{ - char *cmdLine, *p, *arg, *argSpace; - char **argv; - int argc, size, inquote, copy, slashes; - - cmdLine = GetCommandLine(); /* INTL: BUG */ - - /* - * Precompute an overly pessimistic guess at the number of arguments - * in the command line by counting non-space spans. - */ - - size = 2; - for (p = cmdLine; *p != '\0'; p++) { - if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ - size++; - while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ - p++; - } - if (*p == '\0') { - break; - } - } - } - argSpace = (char *) ckalloc( - (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1)); - argv = (char **) argSpace; - argSpace += size * sizeof(char *); - size--; - - p = cmdLine; - for (argc = 0; argc < size; argc++) { - argv[argc] = arg = argSpace; - while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ - p++; - } - if (*p == '\0') { - break; - } - - inquote = 0; - slashes = 0; - while (1) { - copy = 1; - while (*p == '\\') { - slashes++; - p++; - } - if (*p == '"') { - if ((slashes & 1) == 0) { - copy = 0; - if ((inquote) && (p[1] == '"')) { - p++; - copy = 1; - } else { - inquote = !inquote; - } - } - slashes >>= 1; - } - - while (slashes) { - *arg = '\\'; - arg++; - slashes--; - } - - if ((*p == '\0') - || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */ - break; - } - if (copy != 0) { - *arg = *p; - arg++; - } - p++; - } - *arg = '\0'; - argSpace = arg + 1; - } - argv[argc] = NULL; - - *argcPtr = argc; - *argvPtr = argv; -} - -/* *---------------------------------------------------------------------- * * asyncExit -- @@ -422,7 +288,7 @@ asyncExit (ClientData clientData, Tcl_Interp *interp, int code) *---------------------------------------------------------------------- */ -BOOL __stdcall +BOOL WINAPI sigHandler(DWORD fdwCtrlType) { HANDLE hStdIn; diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c index 93d4a17..36ff112 100644 --- a/win/tclWinPipe.c +++ b/win/tclWinPipe.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinPipe.c,v 1.40 2004/01/20 05:18:22 davygrvy Exp $ + * RCS: @(#) $Id: tclWinPipe.c,v 1.41 2004/02/01 09:37:49 davygrvy Exp $ */ #include "tclWinInt.h" @@ -1581,10 +1581,9 @@ BuildCommandLine( arg = executable; } else { arg = argv[i]; + Tcl_DStringAppend(&ds, " ", 1); } - if(Tcl_DStringLength(&ds) > 0) Tcl_DStringAppend(&ds, " ", 1); - quote = 0; if (arg[0] == '\0') { quote = 1; @@ -1632,11 +1631,6 @@ BuildCommandLine( Tcl_DStringAppend(&ds, "\\\"", 2); start = special + 1; } - if (*special == '{') { - Tcl_DStringAppend(&ds, start, special - start); - Tcl_DStringAppend(&ds, "\\{", 2); - start = special + 1; - } if (*special == '\0') { break; } |