[2/8] cmd: Fix FOR tab handling

Frédéric Delanoy frederic.delanoy at gmail.com
Tue Aug 23 15:54:50 CDT 2011


---
 programs/cmd/builtins.c                  |   30 ++++++++++++++++++------------
 programs/cmd/tests/test_builtins.cmd     |    1 +
 programs/cmd/tests/test_builtins.cmd.exp |   11 +++++++----
 programs/cmd/wcmdmain.c                  |   24 +++++++++++++++++-------
 4 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index c4ad231..7aaa900 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -902,8 +902,10 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
   WIN32_FIND_DATAW fd;
   HANDLE hff;
   int i;
-  const WCHAR inW[] = {'i', 'n', ' ', '\0'};
-  const WCHAR doW[] = {'d', 'o', ' ', '\0'};
+  const WCHAR inW[]    = {'i', 'n', ' ',  '\0'};
+  const WCHAR inTabW[] = {'i', 'n', '\t', '\0'};
+  const WCHAR doW[]    = {'d', 'o', ' ',  '\0'};
+  const WCHAR doTabW[] = {'d', 'o', '\t', '\0'};
   CMD_LIST *setStart, *thisSet, *cmdStart, *cmdEnd;
   WCHAR variable[4];
   WCHAR *firstCmd;
@@ -938,7 +940,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
 
               /* Skip whitespace */
               curPos++;
-              while (*curPos && *curPos==' ') curPos++;
+              while (*curPos && (*curPos==' ' || *curPos=='\t')) curPos++;
 
               /* Next parm is either qualifier, path/options or variable -
                  only care about it if it is the path/options              */
@@ -954,11 +956,11 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
       }
 
       /* Skip whitespace between qualifiers */
-      while (*curPos && *curPos==' ') curPos++;
+      while (*curPos && (*curPos==' ' || *curPos=='\t')) curPos++;
   }
 
   /* Skip whitespace before variable */
-  while (*curPos && *curPos==' ') curPos++;
+  while (*curPos && (*curPos==' ' || *curPos=='\t')) curPos++;
 
   /* Ensure line continues with variable */
   if (!*curPos || *curPos != '%') {
@@ -968,19 +970,21 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
 
   /* Variable should follow */
   i = 0;
-  while (curPos[i] && curPos[i]!=' ') i++;
+  while (curPos[i] && curPos[i]!=' ' && curPos[i]!='\t') i++;
   memcpy(&variable[0], curPos, i*sizeof(WCHAR));
   variable[i] = 0x00;
   WINE_TRACE("Variable identified as %s\n", wine_dbgstr_w(variable));
   curPos = &curPos[i];
 
   /* Skip whitespace before IN */
-  while (*curPos && *curPos==' ') curPos++;
+  while (*curPos && (*curPos==' ' || *curPos=='\t')) curPos++;
 
   /* Ensure line continues with IN */
   if (!*curPos
-       || CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
-                         curPos, 3, inW, -1) != CSTR_EQUAL) {
+       || (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+                         curPos, 3, inW, -1) != CSTR_EQUAL
+           && CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+                         curPos, 3, inTabW, -1) != CSTR_EQUAL)) {
       WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
       return;
   }
@@ -1005,9 +1009,11 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
   /* Syntax error if missing close bracket, or nothing following it
      and once we have the complete set, we expect a DO              */
   WINE_TRACE("Looking for 'do' in %p\n", *cmdList);
-  if ((*cmdList == NULL) ||
-      (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
-                            (*cmdList)->command, 3, doW, -1) != CSTR_EQUAL)) {
+  if ((*cmdList == NULL)
+       || (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+                         (*cmdList)->command, 3, doW, -1) != CSTR_EQUAL
+           && CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+                         (*cmdList)->command, 3, doTabW, -1) != CSTR_EQUAL)) {
       WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
       return;
   }
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index b815e77..0d2f983 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -386,6 +386,7 @@ for %%i in at tab@(X3) do echo %%i
 for %%i in (@tab@ foo at tab@) do echo %%i
 for at tab@ %%i in at tab@(@tab at M) do echo %%i
 for %%i at tab@in (X)@tab at do@tab at echo %%i
+for at tab@ %%j in at tab@(@tab at M, N, O at tab@) do echo %%j
 goto :endForTestFun1
 :forTestFun1
 echo %1
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index b86c012..1138485 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -275,11 +275,14 @@ A
 B
 C
 X
- at todo_wine@X2
- at todo_wine@X3
+X2
+X3
 foo
- at todo_wine@M
- at todo_wine@X
+M
+X
+M
+N
+O
 ...imbricated FORs
 @todo_wine at X Y
 @todo_wine at X Y
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index d758857..67b6ef4 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -1742,7 +1742,8 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
     CMD_DELIMITERS prevDelim = CMD_NONE;
     static WCHAR    *extraSpace = NULL;  /* Deliberately never freed */
     const WCHAR remCmd[] = {'r','e','m',' ','\0'};
-    const WCHAR forCmd[] = {'f','o','r',' ','\0'};
+    const WCHAR forCmd[]    = {'f','o','r',' ' ,'\0'};
+    const WCHAR forTabCmd[] = {'f','o','r','\t','\0'};
     const WCHAR ifCmd[]  = {'i','f',' ','\0'};
     const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
     BOOL      inRem = FALSE;
@@ -1826,7 +1827,8 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
 
       /* Certain commands need special handling */
       if (curStringLen == 0 && curCopyTo == curString) {
-        const WCHAR forDO[]  = {'d','o',' ','\0'};
+        const WCHAR forDO[]     = {'d','o',' ' ,'\0'};
+        const WCHAR forDOTab[]  = {'d','o','\t','\0'};
 
         /* If command starts with 'rem', ignore any &&, ( etc */
         if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
@@ -1835,7 +1837,9 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
 
         /* If command starts with 'for', handle ('s mid line after IN or DO */
         } else if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
-          curPos, 4, forCmd, -1) == CSTR_EQUAL) {
+                                  curPos, 4, forCmd, -1) == CSTR_EQUAL
+                || CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+                                  curPos, 4, forTabCmd, -1) == CSTR_EQUAL) {
           inFor = TRUE;
 
         /* If command starts with 'if' or 'else', handle ('s mid line. We should ensure this
@@ -1863,7 +1867,9 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
            is then 0, and all whitespace is skipped                                */
         } else if (inFor &&
                    (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
-                    curPos, 3, forDO, -1) == CSTR_EQUAL)) {
+                                   curPos, 3, forDO, -1) == CSTR_EQUAL
+                 || CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+                                   curPos, 3, forDOTab, -1) == CSTR_EQUAL)) {
           WINE_TRACE("Found DO\n");
           lastWasDo = TRUE;
           onlyWhiteSpace = TRUE;
@@ -1876,12 +1882,15 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
 
         /* Special handling for the 'FOR' command */
         if (inFor && lastWasWhiteSpace) {
-          const WCHAR forIN[] = {'i','n',' ','\0'};
+          const WCHAR forIN[]    = {'i','n',' ' ,'\0'};
+          const WCHAR forINTab[] = {'i','n','\t','\0'};
 
           WINE_TRACE("Found 'FOR', comparing next parm: '%s'\n", wine_dbgstr_w(curPos));
 
           if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
-              curPos, 3, forIN, -1) == CSTR_EQUAL) {
+                             curPos, 3, forIN, -1) == CSTR_EQUAL
+           || CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+                             curPos, 3, forINTab, -1) == CSTR_EQUAL) {
             WINE_TRACE("Found IN\n");
             lastWasIn = TRUE;
             onlyWhiteSpace = TRUE;
@@ -2106,7 +2115,8 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
       /* At various times we need to know if we have only skipped whitespace,
          so reset this variable and then it will remain true until a non
          whitespace is found                                               */
-      if ((thisChar != ' ') && (thisChar != '\n')) onlyWhiteSpace = FALSE;
+      if ((thisChar != ' ') && (thisChar != '\t') && (thisChar != '\n'))
+        onlyWhiteSpace = FALSE;
 
       /* Flag end of interest in FOR DO and IN parms once something has been processed */
       if (!lastWasWhiteSpace) {
-- 
1.7.6




More information about the wine-patches mailing list