[PATCH 4/5] [cmd] Handle very odd delimiter support for command line

Ann and Jason Edmeades jason at edmeades.me.uk
Mon Oct 15 18:53:36 CDT 2012


The first argument on the command line is terminated when an
unquoted open bracket is found, but unlike all other delimiters
the bracket is then used as the first character for the next
argument. I cannot explain 100% why, as its different to
all other cases but it just 'seems to be the case' - this is
highlighted by the tests submitted last week.

Note: Also changed parameter name into builtin functions from
command to args, as that is what is being passed in and it is
confusing.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20121016/0879dabc/attachment-0001.html>
-------------- next part --------------
From 8dbddad9e4df3522755837b311d4a08080f020e0 Mon Sep 17 00:00:00 2001
From: Jason Edmeades <jason at edmeades.me.uk>
Date: Sat, 13 Oct 2012 23:07:20 +0100
Subject: [PATCH 4/5] [cmd] Handle very odd delimiter support for command line

The first argument on the command line is terminated when an
unquoted open bracket is found, but unlike all other delimiters
the bracket is then used as the first character for the next
argument. I cannot explain 100% why, as its different to
all other cases but it just 'seems to be the case' - this is
highlighted by the tests submitted last week.

Note: Also changed parameter name into builtin functions from
command to args, as that is what is being passed in and it is
confusing.
---
 programs/cmd/batch.c                    |   17 ++-
 programs/cmd/builtins.c                 |  175 ++++++++++++++++---------------
 programs/cmd/directory.c                |    8 +-
 programs/cmd/tests/test_cmdline.cmd.exp |   22 ++--
 programs/cmd/wcmd.h                     |   20 ++--
 programs/cmd/wcmdmain.c                 |   19 ++--
 6 files changed, 137 insertions(+), 124 deletions(-)

diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 6fc9970..7b17ea8 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -128,6 +128,9 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
  *  end   [O] Optional. Pointer to the last char of param n in s
  *  raw   [I] True to return the parameter in raw format (quotes maintained)
  *            False returns the parameter with quotes stripped
+ *  wholecmdline [I] True to indicate this routine is being used to parse the
+ *                   command line, and special logic for arg0->1 transition
+ *                   needs to be applied.
  *
  * RETURNS
  *  Success: The nth delimited parameter found in s
@@ -143,7 +146,8 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
  *  other API calls, e.g. c:\"a b"\c is returned as c:\a b\c. However, some commands
  *  need to preserve the exact syntax (echo, for, etc) hence the raw option.
  */
-WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw)
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
+                       BOOL wholecmdline)
 {
     static const WCHAR defaultDelims[] = { ' ', '\t', ',', '=', ';', '\0' };
     int curParamNb = 0;
@@ -173,6 +177,12 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw)
             /* Once we have found a delimiter, break */
             if (strchrW(defaultDelims, *p) != NULL) break;
 
+            /* Very odd special case - Seems as if a ( acts as a delimiter which is
+               not swallowed but is effective only when it comes between the program
+               name and the parameters. Need to avoid this triggering when used
+               to walk parameters generally.                                         */
+            if (wholecmdline && curParamNb == 0 && *p=='(') break;
+
             /* If we find a quote, copy until we get the end quote */
             if (*p == '"') {
                 p++;
@@ -418,8 +428,9 @@ void WCMD_HandleTildaModifiers(WCHAR **start, const WCHAR *forVariable,
     strcpyW(outputparam, context->batchfileW);
   } else if ((*lastModifier >= '1' && *lastModifier <= '9')) {
     strcpyW(outputparam,
-            WCMD_parameter (context -> command, *lastModifier-'0' + context -> shift_count[*lastModifier-'0'],
-                            NULL, NULL, FALSE));
+            WCMD_parameter (context -> command,
+                            *lastModifier-'0' + context -> shift_count[*lastModifier-'0'],
+                            NULL, NULL, FALSE, TRUE));
   } else {
     strcpyW(outputparam, forValue);
   }
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 1935c17..866281b 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -207,7 +207,7 @@ void WCMD_change_tty (void) {
  *
  */
 
-void WCMD_choice (const WCHAR * command) {
+void WCMD_choice (const WCHAR * args) {
 
     static const WCHAR bellW[] = {7,0};
     static const WCHAR commaW[] = {',',0};
@@ -229,7 +229,7 @@ void WCMD_choice (const WCHAR * command) {
     have_console = GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &oldmode);
     errorlevel = 0;
 
-    my_command = WCMD_strdupW(WCMD_skip_leading_spaces((WCHAR*) command));
+    my_command = WCMD_strdupW(WCMD_skip_leading_spaces((WCHAR*) args));
     if (!my_command)
         return;
 
@@ -494,7 +494,7 @@ static BOOL WCMD_ManualCopy(WCHAR *srcname, WCHAR *dstname, BOOL ascii, BOOL app
  *
  */
 
-void WCMD_copy(WCHAR * command) {
+void WCMD_copy(WCHAR * args) {
 
   BOOL    opt_d, opt_v, opt_n, opt_z, opt_y, opt_noty;
   WCHAR  *thisparam;
@@ -541,7 +541,7 @@ void WCMD_copy(WCHAR * command) {
   opt_d = opt_v = opt_n = opt_z = opt_y = opt_noty = FALSE;
 
   /* Walk through all args, building up a list of files to process */
-  thisparam = WCMD_parameter(command, argno++, &rawarg, NULL, TRUE);
+  thisparam = WCMD_parameter(args, argno++, &rawarg, NULL, TRUE, FALSE);
   while (*(thisparam)) {
     WCHAR *pos1, *pos2;
     BOOL inquotes;
@@ -599,7 +599,7 @@ void WCMD_copy(WCHAR * command) {
       }
 
       /* This parameter was purely switches, get the next one */
-      thisparam = WCMD_parameter(command, argno++, &rawarg, NULL, TRUE);
+      thisparam = WCMD_parameter(args, argno++, &rawarg, NULL, TRUE, FALSE);
       continue;
     }
 
@@ -623,7 +623,8 @@ void WCMD_copy(WCHAR * command) {
 
       /* Move to next thing to process */
       thisparam++;
-      if (*thisparam == 0x00) thisparam = WCMD_parameter(command, argno++, &rawarg, NULL, TRUE);
+      if (*thisparam == 0x00)
+        thisparam = WCMD_parameter(args, argno++, &rawarg, NULL, TRUE, FALSE);
       continue;
     }
 
@@ -680,7 +681,7 @@ void WCMD_copy(WCHAR * command) {
       thisparam = pos1;
       continue;
     } else {
-      thisparam = WCMD_parameter(command, argno++, &rawarg, NULL, TRUE);
+      thisparam = WCMD_parameter(args, argno++, &rawarg, NULL, TRUE, FALSE);
     }
   }
 
@@ -1008,9 +1009,9 @@ static BOOL create_full_path(WCHAR* path)
     return FALSE;
 }
 
-void WCMD_create_dir (WCHAR *command) {
+void WCMD_create_dir (WCHAR *args) {
     int   argno = 0;
-    WCHAR *argN = command;
+    WCHAR *argN = args;
 
     if (param1[0] == 0x00) {
         WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOARG));
@@ -1018,7 +1019,7 @@ void WCMD_create_dir (WCHAR *command) {
     }
     /* Loop through all args */
     while (TRUE) {
-        WCHAR *thisArg = WCMD_parameter(command, argno++, &argN, NULL, FALSE);
+        WCHAR *thisArg = WCMD_parameter(args, argno++, &argN, NULL, FALSE, FALSE);
         if (!argN) break;
         if (!create_full_path(thisArg)) {
             WCMD_print_error ();
@@ -1310,7 +1311,7 @@ static BOOL WCMD_delete_one (const WCHAR *thisArg) {
  *         non-hidden files
  */
 
-BOOL WCMD_delete (WCHAR *command) {
+BOOL WCMD_delete (WCHAR *args) {
     int   argno;
     WCHAR *argN;
     BOOL  argsProcessed = FALSE;
@@ -1323,7 +1324,7 @@ BOOL WCMD_delete (WCHAR *command) {
         WCHAR *thisArg;
 
         argN = NULL;
-        thisArg = WCMD_parameter (command, argno, &argN, NULL, FALSE);
+        thisArg = WCMD_parameter (args, argno, &argN, NULL, FALSE, FALSE);
         if (!argN)
             break;       /* no more parameters */
         if (argN[0] == '/')
@@ -1381,17 +1382,17 @@ static WCHAR *WCMD_strtrim(const WCHAR *s)
  * in DOS (try typing "ECHO ON AGAIN" for an example).
  */
 
-void WCMD_echo (const WCHAR *command)
+void WCMD_echo (const WCHAR *args)
 {
   int count;
-  const WCHAR *origcommand = command;
+  const WCHAR *origcommand = args;
   WCHAR *trimmed;
 
-  if (   command[0]==' ' || command[0]=='\t' || command[0]=='.'
-      || command[0]==':' || command[0]==';')
-    command++;
+  if (   args[0]==' ' || args[0]=='\t' || args[0]=='.'
+      || args[0]==':' || args[0]==';')
+    args++;
 
-  trimmed = WCMD_strtrim(command);
+  trimmed = WCMD_strtrim(args);
   if (!trimmed) return;
 
   count = strlenW(trimmed);
@@ -1407,7 +1408,7 @@ void WCMD_echo (const WCHAR *command)
   else if (lstrcmpiW(trimmed, offW) == 0)
     echo_mode = FALSE;
   else {
-    WCMD_output_asis (command);
+    WCMD_output_asis (args);
     WCMD_output_asis (newlineW);
   }
   HeapFree(GetProcessHeap(), 0, trimmed);
@@ -1547,7 +1548,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
   int    parameterNo = 0;
 
   /* Handle optional qualifiers (multiple are allowed) */
-  WCHAR *thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE);
+  WCHAR *thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE, FALSE);
 
   optionsRoot[0] = 0;
   while (thisArg && *thisArg == '/') {
@@ -1571,7 +1572,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
 
               /* Retrieve next parameter to see if is root/options (raw form required
                  with for /f, or unquoted in for /r)                                  */
-              thisArg = WCMD_parameter(p, parameterNo, NULL, NULL, doFileset);
+              thisArg = WCMD_parameter(p, parameterNo, NULL, NULL, doFileset, FALSE);
 
               /* Next parm is either qualifier, path/options or variable -
                  only care about it if it is the path/options              */
@@ -1590,7 +1591,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
       }
 
       /* Step to next token */
-      thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE);
+      thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE, FALSE);
   }
 
   /* Ensure line continues with variable */
@@ -1615,7 +1616,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
   WINE_TRACE("Variable identified as %s\n", wine_dbgstr_w(variable));
 
   /* Ensure line continues with IN */
-  thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE);
+  thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE, FALSE);
   if (!thisArg
        || !(CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
                            thisArg, sizeof(inW)/sizeof(inW[0]), inW,
@@ -1714,7 +1715,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
 
       WINE_TRACE("Processing for set %p\n", thisSet);
       i = 0;
-      while (*(item = WCMD_parameter (thisSet->command, i, &itemStart, NULL, TRUE))) {
+      while (*(item = WCMD_parameter (thisSet->command, i, &itemStart, NULL, TRUE, FALSE))) {
 
         /*
          * If the parameter within the set has a wildcard then search for matching files
@@ -1835,7 +1836,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
               while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
 
                 /* Skip blank lines*/
-                parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
+                parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE, FALSE);
                 WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
                            wine_dbgstr_w(buffer));
 
@@ -1866,7 +1867,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
 
             /* Skip blank lines, and re-extract parameter now string has quotes removed */
             strcpyW(buffer, item);
-            parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
+            parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE, FALSE);
             WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
                          wine_dbgstr_w(buffer));
 
@@ -1948,19 +1949,19 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
  *	Simple on-line help. Help text is stored in the resource file.
  */
 
-void WCMD_give_help (const WCHAR *command)
+void WCMD_give_help (const WCHAR *args)
 {
   size_t i;
 
-  command = WCMD_skip_leading_spaces((WCHAR*) command);
-  if (strlenW(command) == 0) {
+  args = WCMD_skip_leading_spaces((WCHAR*) args);
+  if (strlenW(args) == 0) {
     WCMD_output_asis (WCMD_LoadMessage(WCMD_ALLHELP));
   }
   else {
     /* Display help message for builtin commands */
     for (i=0; i<=WCMD_EXIT; i++) {
       if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
-	  command, -1, inbuilt[i], -1) == CSTR_EQUAL) {
+	  args, -1, inbuilt[i], -1) == CSTR_EQUAL) {
 	WCMD_output_asis (WCMD_LoadMessage(i));
 	return;
       }
@@ -1968,16 +1969,16 @@ void WCMD_give_help (const WCHAR *command)
     /* Launch the command with the /? option for external commands shipped with cmd.exe */
     for (i = 0; i <= (sizeof(externals)/sizeof(externals[0])); i++) {
       if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
-	  command, -1, externals[i], -1) == CSTR_EQUAL) {
+	  args, -1, externals[i], -1) == CSTR_EQUAL) {
         WCHAR cmd[128];
         static const WCHAR helpW[] = {' ', '/','?','\0'};
-        strcpyW(cmd, command);
+        strcpyW(cmd, args);
         strcatW(cmd, helpW);
         WCMD_run_program(cmd, FALSE);
         return;
       }
     }
-    WCMD_output (WCMD_LoadMessage(WCMD_NOCMDHELP), command);
+    WCMD_output (WCMD_LoadMessage(WCMD_NOCMDHELP), args);
   }
   return;
 }
@@ -2043,13 +2044,13 @@ void WCMD_goto (CMD_LIST **cmdList) {
  *	Push a directory onto the stack
  */
 
-void WCMD_pushd (const WCHAR *command)
+void WCMD_pushd (const WCHAR *args)
 {
     struct env_stack *curdir;
     WCHAR *thisdir;
     static const WCHAR parmD[] = {'/','D','\0'};
 
-    if (strchrW(command, '/') != NULL) {
+    if (strchrW(args, '/') != NULL) {
       SetLastError(ERROR_INVALID_PARAMETER);
       WCMD_print_error();
       return;
@@ -2068,7 +2069,7 @@ void WCMD_pushd (const WCHAR *command)
     strcpyW(quals, parmD);
     GetCurrentDirectoryW (1024, thisdir);
     errorlevel = 0;
-    WCMD_setshow_default(command);
+    WCMD_setshow_default(args);
     if (errorlevel) {
       LocalFree(curdir);
       LocalFree(thisdir);
@@ -2138,7 +2139,7 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
   WINE_TRACE("Condition: %s\n", wine_dbgstr_w(condition));
 
   if (!lstrcmpiW (condition, errlvlW)) {
-    WCHAR *param = WCMD_parameter(p, 1+negate, NULL, NULL, FALSE);
+    WCHAR *param = WCMD_parameter(p, 1+negate, NULL, NULL, FALSE, FALSE);
     WCHAR *endptr;
     long int param_int = strtolW(param, &endptr, 10);
     if (*endptr) {
@@ -2146,24 +2147,24 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
       return;
     }
     test = ((long int)errorlevel >= param_int);
-    WCMD_parameter(p, 2+negate, &command, NULL, FALSE);
+    WCMD_parameter(p, 2+negate, &command, NULL, FALSE, FALSE);
   }
   else if (!lstrcmpiW (condition, existW)) {
-    test = (GetFileAttributesW(WCMD_parameter(p, 1+negate, NULL, NULL, FALSE))
+    test = (GetFileAttributesW(WCMD_parameter(p, 1+negate, NULL, NULL, FALSE, FALSE))
              != INVALID_FILE_ATTRIBUTES);
-    WCMD_parameter(p, 2+negate, &command, NULL, FALSE);
+    WCMD_parameter(p, 2+negate, &command, NULL, FALSE, FALSE);
   }
   else if (!lstrcmpiW (condition, defdW)) {
-    test = (GetEnvironmentVariableW(WCMD_parameter(p, 1+negate, NULL, NULL, FALSE),
+    test = (GetEnvironmentVariableW(WCMD_parameter(p, 1+negate, NULL, NULL, FALSE, FALSE),
                                     NULL, 0) > 0);
-    WCMD_parameter(p, 2+negate, &command, NULL, FALSE);
+    WCMD_parameter(p, 2+negate, &command, NULL, FALSE, FALSE);
   }
   else if ((s = strstrW (p, eqeqW))) {
     /* We need to get potential surrounding double quotes, so param1/2 can't be used */
     WCHAR *leftPart, *leftPartEnd, *rightPart, *rightPartEnd;
     s += 2;
-    WCMD_parameter(p, 0+negate+caseInsensitive, &leftPart, &leftPartEnd, FALSE);
-    WCMD_parameter(p, 1+negate+caseInsensitive, &rightPart, &rightPartEnd, FALSE);
+    WCMD_parameter(p, 0+negate+caseInsensitive, &leftPart, &leftPartEnd, FALSE, FALSE);
+    WCMD_parameter(p, 1+negate+caseInsensitive, &rightPart, &rightPartEnd, FALSE, FALSE);
     test = caseInsensitive
             ? (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
                               leftPart, leftPartEnd-leftPart+1,
@@ -2171,7 +2172,7 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
             : (CompareStringW(LOCALE_SYSTEM_DEFAULT, 0,
                               leftPart, leftPartEnd-leftPart+1,
                               rightPart, rightPartEnd-rightPart+1) == CSTR_EQUAL);
-    WCMD_parameter(s, 1, &command, NULL, FALSE);
+    WCMD_parameter(s, 1, &command, NULL, FALSE, FALSE);
   }
   else {
     WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR));
@@ -2336,17 +2337,17 @@ void WCMD_pause (void)
  * Delete a directory.
  */
 
-void WCMD_remove_dir (WCHAR *command) {
+void WCMD_remove_dir (WCHAR *args) {
 
   int   argno         = 0;
   int   argsProcessed = 0;
-  WCHAR *argN          = command;
+  WCHAR *argN          = args;
   static const WCHAR parmS[] = {'/','S','\0'};
   static const WCHAR parmQ[] = {'/','Q','\0'};
 
   /* Loop through all args */
   while (argN) {
-    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL, FALSE);
+    WCHAR *thisArg = WCMD_parameter (args, argno++, &argN, NULL, FALSE, FALSE);
     if (argN && argN[0] != '/') {
       WINE_TRACE("rd: Processing arg %s (quals:%s)\n", wine_dbgstr_w(thisArg),
                  wine_dbgstr_w(quals));
@@ -2649,7 +2650,7 @@ void WCMD_endlocal (void) {
  *	Set/Show the current default directory
  */
 
-void WCMD_setshow_default (const WCHAR *command) {
+void WCMD_setshow_default (const WCHAR *args) {
 
   BOOL status;
   WCHAR string[1024];
@@ -2659,19 +2660,19 @@ void WCMD_setshow_default (const WCHAR *command) {
   HANDLE hff;
   static const WCHAR parmD[] = {'/','D','\0'};
 
-  WINE_TRACE("Request change to directory '%s'\n", wine_dbgstr_w(command));
+  WINE_TRACE("Request change to directory '%s'\n", wine_dbgstr_w(args));
 
   /* Skip /D and trailing whitespace if on the front of the command line */
   if (CompareStringW(LOCALE_USER_DEFAULT,
                      NORM_IGNORECASE | SORT_STRINGSORT,
-                     command, 2, parmD, -1) == CSTR_EQUAL) {
-    command += 2;
-    while (*command && (*command==' ' || *command=='\t'))
-      command++;
+                     args, 2, parmD, -1) == CSTR_EQUAL) {
+    args += 2;
+    while (*args && (*args==' ' || *args=='\t'))
+      args++;
   }
 
   GetCurrentDirectoryW(sizeof(cwd)/sizeof(WCHAR), cwd);
-  if (strlenW(command) == 0) {
+  if (strlenW(args) == 0) {
     strcatW (cwd, newlineW);
     WCMD_output_asis (cwd);
   }
@@ -2679,9 +2680,9 @@ void WCMD_setshow_default (const WCHAR *command) {
     /* Remove any double quotes, which may be in the
        middle, eg. cd "C:\Program Files"\Microsoft is ok */
     pos = string;
-    while (*command) {
-      if (*command != '"') *pos++ = *command;
-      command++;
+    while (*args) {
+      if (*args != '"') *pos++ = *args;
+      args++;
     }
     while (pos > string && (*(pos-1) == ' ' || *(pos-1) == '\t'))
       pos--;
@@ -2932,7 +2933,7 @@ void WCMD_setshow_env (WCHAR *s) {
  * Set/Show the path environment variable
  */
 
-void WCMD_setshow_path (const WCHAR *command) {
+void WCMD_setshow_path (const WCHAR *args) {
 
   WCHAR string[1024];
   DWORD status;
@@ -2951,8 +2952,8 @@ void WCMD_setshow_path (const WCHAR *command) {
     }
   }
   else {
-    if (*command == '=') command++; /* Skip leading '=' */
-    status = SetEnvironmentVariableW(pathW, command);
+    if (*args == '=') args++; /* Skip leading '=' */
+    status = SetEnvironmentVariableW(pathW, args);
     if (!status) WCMD_print_error();
   }
 }
@@ -3022,11 +3023,11 @@ void WCMD_setshow_time (void) {
  * Optional /n says where to start shifting (n=0-8)
  */
 
-void WCMD_shift (const WCHAR *command) {
+void WCMD_shift (const WCHAR *args) {
   int start;
 
   if (context != NULL) {
-    WCHAR *pos = strchrW(command, '/');
+    WCHAR *pos = strchrW(args, '/');
     int   i;
 
     if (pos == NULL) {
@@ -3051,7 +3052,7 @@ void WCMD_shift (const WCHAR *command) {
 /****************************************************************************
  * WCMD_start
  */
-void WCMD_start(const WCHAR *command)
+void WCMD_start(const WCHAR *args)
 {
     static const WCHAR exeW[] = {'\\','c','o','m','m','a','n','d',
                                  '\\','s','t','a','r','t','.','e','x','e',0};
@@ -3062,10 +3063,10 @@ void WCMD_start(const WCHAR *command)
 
     GetWindowsDirectoryW( file, MAX_PATH );
     strcatW( file, exeW );
-    cmdline = HeapAlloc( GetProcessHeap(), 0, (strlenW(file) + strlenW(command) + 2) * sizeof(WCHAR) );
+    cmdline = HeapAlloc( GetProcessHeap(), 0, (strlenW(file) + strlenW(args) + 2) * sizeof(WCHAR) );
     strcpyW( cmdline, file );
     strcatW( cmdline, spaceW );
-    strcatW( cmdline, command );
+    strcatW( cmdline, args );
 
     memset( &st, 0, sizeof(STARTUPINFOW) );
     st.cb = sizeof(STARTUPINFOW);
@@ -3092,8 +3093,8 @@ void WCMD_start(const WCHAR *command)
  *
  * Set the console title
  */
-void WCMD_title (const WCHAR *command) {
-  SetConsoleTitleW(command);
+void WCMD_title (const WCHAR *args) {
+  SetConsoleTitleW(args);
 }
 
 /****************************************************************************
@@ -3102,10 +3103,10 @@ void WCMD_title (const WCHAR *command) {
  * Copy a file to standard output.
  */
 
-void WCMD_type (WCHAR *command) {
+void WCMD_type (WCHAR *args) {
 
   int   argno         = 0;
-  WCHAR *argN          = command;
+  WCHAR *argN          = args;
   BOOL  writeHeaders  = FALSE;
 
   if (param1[0] == 0x00) {
@@ -3118,7 +3119,7 @@ void WCMD_type (WCHAR *command) {
   /* Loop through all args */
   errorlevel = 0;
   while (argN) {
-    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL, FALSE);
+    WCHAR *thisArg = WCMD_parameter (args, argno++, &argN, NULL, FALSE, FALSE);
 
     HANDLE h;
     WCHAR buffer[512];
@@ -3154,10 +3155,10 @@ void WCMD_type (WCHAR *command) {
  * Output either a file or stdin to screen in pages
  */
 
-void WCMD_more (WCHAR *command) {
+void WCMD_more (WCHAR *args) {
 
   int   argno         = 0;
-  WCHAR *argN          = command;
+  WCHAR *argN         = args;
   WCHAR  moreStr[100];
   WCHAR  moreStrPage[100];
   WCHAR  buffer[512];
@@ -3212,7 +3213,7 @@ void WCMD_more (WCHAR *command) {
     WCMD_enter_paged_mode(moreStrPage);
 
     while (argN) {
-      WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL, FALSE);
+      WCHAR *thisArg = WCMD_parameter (args, argno++, &argN, NULL, FALSE, FALSE);
       HANDLE h;
 
       if (!argN) break;
@@ -3271,21 +3272,21 @@ void WCMD_more (WCHAR *command) {
  * it...
  */
 
-void WCMD_verify (const WCHAR *command) {
+void WCMD_verify (const WCHAR *args) {
 
   int count;
 
-  count = strlenW(command);
+  count = strlenW(args);
   if (count == 0) {
     if (verify_mode) WCMD_output (WCMD_LoadMessage(WCMD_VERIFYPROMPT), onW);
     else WCMD_output (WCMD_LoadMessage(WCMD_VERIFYPROMPT), offW);
     return;
   }
-  if (lstrcmpiW(command, onW) == 0) {
+  if (lstrcmpiW(args, onW) == 0) {
     verify_mode = TRUE;
     return;
   }
-  else if (lstrcmpiW(command, offW) == 0) {
+  else if (lstrcmpiW(args, offW) == 0) {
     verify_mode = FALSE;
     return;
   }
@@ -3397,7 +3398,7 @@ void WCMD_exit (CMD_LIST **cmdList) {
  *	Lists or sets file associations  (assoc = TRUE)
  *      Lists or sets file types         (assoc = FALSE)
  */
-void WCMD_assoc (const WCHAR *command, BOOL assoc) {
+void WCMD_assoc (const WCHAR *args, BOOL assoc) {
 
     HKEY    key;
     DWORD   accessOptions = KEY_READ;
@@ -3411,7 +3412,7 @@ void WCMD_assoc (const WCHAR *command, BOOL assoc) {
 
     /* See if parameter includes '=' */
     errorlevel = 0;
-    newValue = strchrW(command, '=');
+    newValue = strchrW(args, '=');
     if (newValue) accessOptions |= KEY_WRITE;
 
     /* Open a key to HKEY_CLASSES_ROOT for enumerating */
@@ -3422,7 +3423,7 @@ void WCMD_assoc (const WCHAR *command, BOOL assoc) {
     }
 
     /* If no parameters then list all associations */
-    if (*command == 0x00) {
+    if (*args == 0x00) {
       int index = 0;
 
       /* Enumerate all the keys */
@@ -3470,7 +3471,7 @@ void WCMD_assoc (const WCHAR *command, BOOL assoc) {
         WCHAR subkey[MAXSTRING];
 
         /* Query terminates the parameter at the first space */
-        strcpyW(keyValue, command);
+        strcpyW(keyValue, args);
         space = strchrW(keyValue, ' ');
         if (space) *space=0x00;
 
@@ -3481,7 +3482,7 @@ void WCMD_assoc (const WCHAR *command, BOOL assoc) {
         if (RegOpenKeyExW(key, subkey, 0, accessOptions, &readKey) == ERROR_SUCCESS) {
 
           rc = RegQueryValueExW(readKey, NULL, NULL, NULL, (LPBYTE)keyValue, &valueLen);
-          WCMD_output_asis(command);
+          WCMD_output_asis(args);
           WCMD_output_asis(equalW);
           /* If no default value found, leave line empty after '=' */
           if (rc == ERROR_SUCCESS) WCMD_output_asis(keyValue);
@@ -3511,15 +3512,15 @@ void WCMD_assoc (const WCHAR *command, BOOL assoc) {
         newValue++;
 
         /* Set up key name */
-        strcpyW(subkey, command);
+        strcpyW(subkey, args);
         if (!assoc) strcatW(subkey, shOpCmdW);
 
         /* If nothing after '=' then clear value - only valid for ASSOC */
         if (*newValue == 0x00) {
 
-          if (assoc) rc = RegDeleteKeyW(key, command);
+          if (assoc) rc = RegDeleteKeyW(key, args);
           if (assoc && rc == ERROR_SUCCESS) {
-            WINE_TRACE("HKCR Key '%s' deleted\n", wine_dbgstr_w(command));
+            WINE_TRACE("HKCR Key '%s' deleted\n", wine_dbgstr_w(args));
 
           } else if (assoc && rc != ERROR_FILE_NOT_FOUND) {
             WCMD_print_error();
@@ -3555,7 +3556,7 @@ void WCMD_assoc (const WCHAR *command, BOOL assoc) {
             WCMD_print_error();
             errorlevel = 2;
           } else {
-            WCMD_output_asis(command);
+            WCMD_output_asis(args);
             WCMD_output_asis(equalW);
             WCMD_output_asis(newValue);
             WCMD_output_asis(newlineW);
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c
index 5f7746d..d9558ae 100644
--- a/programs/cmd/directory.c
+++ b/programs/cmd/directory.c
@@ -594,7 +594,7 @@ static void WCMD_dir_trailer(WCHAR drive) {
  *
  */
 
-void WCMD_directory (WCHAR *cmd)
+void WCMD_directory (WCHAR *args)
 {
   WCHAR path[MAX_PATH], cwd[MAX_PATH];
   DWORD status;
@@ -602,7 +602,7 @@ void WCMD_directory (WCHAR *cmd)
   WCHAR *p;
   WCHAR string[MAXSTRING];
   int   argno         = 0;
-  WCHAR *argN          = cmd;
+  WCHAR *argN          = args;
   WCHAR  lastDrive;
   BOOL  trailerReqd = FALSE;
   DIRECTORY_STACK *fullParms = NULL;
@@ -794,7 +794,7 @@ void WCMD_directory (WCHAR *cmd)
   }
 
   argno         = 0;
-  argN          = cmd;
+  argN          = args;
   GetCurrentDirectoryW(MAX_PATH, cwd);
   strcatW(cwd, slashW);
 
@@ -803,7 +803,7 @@ void WCMD_directory (WCHAR *cmd)
   prevEntry = NULL;
   while (argN) {
     WCHAR fullname[MAXSTRING];
-    WCHAR *thisArg = WCMD_parameter(cmd, argno++, &argN, NULL, FALSE);
+    WCHAR *thisArg = WCMD_parameter(args, argno++, &argN, NULL, FALSE, FALSE);
     if (argN && argN[0] != '/') {
 
       WINE_TRACE("Found parm '%s'\n", wine_dbgstr_w(thisArg));
diff --git a/programs/cmd/tests/test_cmdline.cmd.exp b/programs/cmd/tests/test_cmdline.cmd.exp
index 0317a99..99f8c45 100644
--- a/programs/cmd/tests/test_cmdline.cmd.exp
+++ b/programs/cmd/tests/test_cmdline.cmd.exp
@@ -57,7 +57,7 @@ var=33 at space@
 0 at space@
 3 at space@
 3 at space@
- at todo_wine@4 at space@
+4 at space@
 ------ Testing invocation with CMD /C -------------
 0 at space@
 1 at space@
@@ -69,7 +69,7 @@ var=33 at space@
 2 at space@
 0 at space@
 3 at space@
- at todo_wine@4 at space@
+4 at space@
 ---------- Testing CMD /C quoting -----------------
 "hi"
 1 at space@
@@ -93,7 +93,7 @@ THIS FAILS: cmd "/c"say one
 THIS FAILS: cmd ignoreme/c say one
 --------- Testing special characters --------------
 0 at space@
- at todo_wine@0 at space@
+0 at space@
 )@space@
 [@space@
 ]@space@
@@ -113,10 +113,10 @@ THIS FAILS: cmd ignoreme/c say one
 1:1,2:@space@
 1:(1),2:@space@
 1:1(2),2:@space@
- at todo_wine@1:(1),2:@space@
- at todo_wine@1:((1)),2:@space@
- at todo_wine@1:(1)(2),2:@space@
- at todo_wine@1:(1),2:(2)@space@
+1:(1),2:@space@
+1:((1)),2:@space@
+1:(1)(2),2:@space@
+1:(1),2:(2)@space@
 1:1,2:2 at space@
 1:1,2:2 at space@
 1:1,2:2 at space@
@@ -126,7 +126,7 @@ THIS FAILS: cmd ignoreme/c say one
 0:tell,1:1,2:2,All:'1 2'@or_broken at 0:tell,1:1,2:2,All:' 1 2'
 0:tell,1:1,2:2,All:'1 2'@or_broken at 0:tell,1:1,2:2,All:' 1 2'
 0:tell,1:1,2:2,All:'==1==2'
- at todo_wine@0:tell,1:(1234),2:,All:'(1234)'
- at todo_wine@0:tell,1:(12(34),2:,All:'(12(34)'
- at todo_wine@0:tell,1:(12,2:34),All:'(12;34)'
- at todo_wine@--------- Finished  --------------
+0:tell,1:(1234),2:,All:'(1234)'
+0:tell,1:(12(34),2:,All:'(12(34)'
+0:tell,1:(12,2:34),All:'(12;34)'
+--------- Finished  --------------
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index 529ca28..e303efe 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -69,7 +69,7 @@ void WCMD_endlocal (void);
 void WCMD_enter_paged_mode(const WCHAR *);
 void WCMD_exit (CMD_LIST **cmdList);
 void WCMD_for (WCHAR *, CMD_LIST **cmdList);
-void WCMD_give_help (const WCHAR *command);
+void WCMD_give_help (const WCHAR *args);
 void WCMD_goto (CMD_LIST **cmdList);
 void WCMD_if (WCHAR *, CMD_LIST **cmdList);
 void WCMD_leave_paged_mode(void);
@@ -83,31 +83,31 @@ void WCMD_output_asis_stderr (const WCHAR *message);
 void WCMD_pause (void);
 void WCMD_popd (void);
 void WCMD_print_error (void);
-void WCMD_pushd (const WCHAR *command);
+void WCMD_pushd (const WCHAR *args);
 void WCMD_remove_dir (WCHAR *command);
 void WCMD_rename (void);
 void WCMD_run_program (WCHAR *command, BOOL called);
-void WCMD_setlocal (const WCHAR *command);
+void WCMD_setlocal (const WCHAR *args);
 void WCMD_setshow_date (void);
-void WCMD_setshow_default (const WCHAR *command);
+void WCMD_setshow_default (const WCHAR *args);
 void WCMD_setshow_env (WCHAR *command);
-void WCMD_setshow_path (const WCHAR *command);
+void WCMD_setshow_path (const WCHAR *args);
 void WCMD_setshow_prompt (void);
 void WCMD_setshow_time (void);
-void WCMD_shift (const WCHAR *command);
-void WCMD_start (const WCHAR *command);
+void WCMD_shift (const WCHAR *args);
+void WCMD_start (const WCHAR *args);
 void WCMD_title (const WCHAR *);
 void WCMD_type (WCHAR *);
-void WCMD_verify (const WCHAR *command);
+void WCMD_verify (const WCHAR *args);
 void WCMD_version (void);
-int  WCMD_volume (BOOL set_label, const WCHAR *command);
+int  WCMD_volume (BOOL set_label, const WCHAR *args);
 
 static inline BOOL WCMD_is_console_handle(HANDLE h)
 {
     return (((DWORD_PTR)h) & 3) == 3;
 }
 WCHAR *WCMD_fgets (WCHAR *buf, DWORD n, HANDLE stream);
-WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw);
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw, BOOL wholecmdline);
 WCHAR *WCMD_skip_leading_spaces (WCHAR *string);
 BOOL WCMD_keyword_ws_found(const WCHAR *keyword, int len, const WCHAR *ptr);
 void WCMD_HandleTildaModifiers(WCHAR **start, const WCHAR *forVariable, const WCHAR *forValue, BOOL justFors);
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index f60ba84..07b8321 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -837,13 +837,14 @@ static void handleExpansion(WCHAR *cmd, BOOL justFors,
 
     /* Replace use of %0...%9 if in batch program*/
     } else if (!justFors && context && (i >= 0) && (i <= 9)) {
-      t = WCMD_parameter(context -> command, i + context -> shift_count[i], NULL, NULL, TRUE);
+      t = WCMD_parameter(context -> command, i + context -> shift_count[i],
+                         NULL, NULL, TRUE, TRUE);
       WCMD_strsubstW(p, p+2, t, -1);
 
     /* Replace use of %* if in batch program*/
     } else if (!justFors && context && *(p+1)=='*') {
       WCHAR *startOfParms = NULL;
-      WCMD_parameter(context -> command, 0, NULL, &startOfParms, TRUE);
+      WCMD_parameter(context -> command, 0, NULL, &startOfParms, TRUE, TRUE);
       if (startOfParms != NULL) {
         startOfParms++; /* Skip to first delimiter then skip whitespace */
         while (*startOfParms==' ' || *startOfParms == '\t') startOfParms++;
@@ -1021,7 +1022,7 @@ void WCMD_run_program (WCHAR *command, BOOL called)
 
   /* Quick way to get the filename is to extract the first argument. */
   WINE_TRACE("Running '%s' (%d)\n", wine_dbgstr_w(command), called);
-  firstParam = WCMD_parameter(command, 0, NULL, NULL, FALSE);
+  firstParam = WCMD_parameter(command, 0, NULL, NULL, FALSE, TRUE);
   if (!firstParam) return;
 
   /* Calculate the search path and stem to search for */
@@ -1359,7 +1360,7 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
 
     /* Otherwise STDIN could come from a '<' redirect */
     } else if ((p = strchrW(new_redir,'<')) != NULL) {
-      h = CreateFileW(WCMD_parameter(++p, 0, NULL, NULL, FALSE), GENERIC_READ, FILE_SHARE_READ,
+      h = CreateFileW(WCMD_parameter(++p, 0, NULL, NULL, FALSE, FALSE), GENERIC_READ, FILE_SHARE_READ,
                       &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
       if (h == INVALID_HANDLE_VALUE) {
 	WCMD_print_error ();
@@ -1404,7 +1405,7 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
         WINE_TRACE("Redirect %d (%p) to %d (%p)\n", handle, GetStdHandle(idx_stdhandles[idx]), idx, h);
 
       } else {
-        WCHAR *param = WCMD_parameter(p, 0, NULL, NULL, FALSE);
+        WCHAR *param = WCMD_parameter(p, 0, NULL, NULL, FALSE, FALSE);
         h = CreateFileW(param, GENERIC_WRITE, 0, &sa, creationDisposition,
                         FILE_ATTRIBUTE_NORMAL, NULL);
         if (h == INVALID_HANDLE_VALUE) {
@@ -2330,14 +2331,14 @@ int wmain (int argc, WCHAR *argvW[])
   args = 1;                /* start at first arg, skipping cmd.exe itself */
 
   opt_c = opt_k = opt_q = opt_s = FALSE;
-  WCMD_parameter(cmdLine, args, &argPos, NULL, TRUE);
+  WCMD_parameter(cmdLine, args, &argPos, NULL, TRUE, TRUE);
   while (argPos && argPos[0] != 0x00)
   {
       WCHAR c;
       WINE_TRACE("Command line parm: '%s'\n", wine_dbgstr_w(argPos));
       if (argPos[0]!='/' || argPos[1]=='\0') {
           args++;
-          WCMD_parameter(cmdLine, args, &argPos, NULL, TRUE);
+          WCMD_parameter(cmdLine, args, &argPos, NULL, TRUE, TRUE);
           continue;
       }
 
@@ -2362,7 +2363,7 @@ int wmain (int argc, WCHAR *argvW[])
 
       if (argPos[2]==0 || argPos[2]==' ' || argPos[2]=='\t') {
           args++;
-          WCMD_parameter(cmdLine, args, &argPos, NULL, TRUE);
+          WCMD_parameter(cmdLine, args, &argPos, NULL, TRUE, TRUE);
       }
       else /* handle `cmd /cnotepad.exe` and `cmd /x/c ...` */
       {
@@ -2443,7 +2444,7 @@ int wmain (int argc, WCHAR *argvW[])
       /* Finally, we only stay in new mode IF the first parameter is quoted and
          is a valid executable, ie must exist, otherwise drop back to old mode  */
       if (!opt_s) {
-        WCHAR *thisArg = WCMD_parameter(cmd, 0, NULL, NULL, FALSE);
+        WCHAR *thisArg = WCMD_parameter(cmd, 0, NULL, NULL, FALSE, TRUE);
         WCHAR  pathext[MAXSTRING];
         BOOL found = FALSE;
 
-- 
1.7.9.5


More information about the wine-patches mailing list