Jason Edmeades : cmd: Handle "for" loop handling of tokens, where * does not follow a number.

Alexandre Julliard julliard at winehq.org
Thu Nov 29 15:09:39 CST 2018


Module: wine
Branch: stable
Commit: 5d6c525dc4d4390f468ffafaf1e6cdeb29f410d6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=5d6c525dc4d4390f468ffafaf1e6cdeb29f410d6

Author: Jason Edmeades <us at edmeades.me.uk>
Date:   Mon Sep 10 23:30:19 2018 +0100

cmd: Handle "for" loop handling of tokens, where * does not follow a number.

With the 'for' loop /f syntax, if tokens are requested the the normal
syntax is something like tokens=1,2* but there is valid syntax like
1,2,* (which effectively means the same). Make this other syntax work.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45722
Signed-off-by: Jason Edmeades <us at edmeades.me.uk>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 1a7333bec627a31a43d380ecc63e5792e302373e)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 programs/cmd/builtins.c                  | 48 +++++++++++++++++++-------------
 programs/cmd/tests/test_builtins.cmd     |  3 +-
 programs/cmd/tests/test_builtins.cmd.exp |  1 +
 3 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 9cd86b3..48cfc13 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1836,8 +1836,8 @@ static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
   if (doall) *doall = FALSE;
   if (duplicates) *duplicates = FALSE;
 
-  WINE_TRACE("Find next token after %d in %s was %d\n", lasttoken,
-             wine_dbgstr_w(tokenstr), nexttoken);
+  WINE_TRACE("Find next token after %d in %s\n", lasttoken,
+             wine_dbgstr_w(tokenstr));
 
   /* Loop through the token string, parsing it. Valid syntax is:
      token=m or x-y with comma delimiter and optionally * to finish*/
@@ -1845,11 +1845,21 @@ static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
     int nextnumber1, nextnumber2 = -1;
     WCHAR *nextchar;
 
-    /* It is valid syntax tokens=* which just means get whole line */
+    /* Remember if the next character is a star, it indicates a need to
+       show all remaining tokens and should be the last character       */
     if (*pos == '*') {
       if (doall) *doall = TRUE;
       if (totalfound) (*totalfound)++;
-      nexttoken = 0;
+      /* If we have not found a next token to return, then indicate
+         time to process the star                                   */
+      if (nexttoken == -1) {
+         if (lasttoken == -1) {
+           /* Special case the syntax of tokens=* which just means get whole line */
+           nexttoken = 0;
+         } else {
+           nexttoken = lasttoken;
+         }
+      }
       break;
     }
 
@@ -1882,8 +1892,9 @@ static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
       if (nextnumber2 >= nextnumber1 && totalfound) {
         *totalfound = *totalfound + 1 + (nextnumber2 - nextnumber1);
       }
+      pos = nextchar;
 
-    } else {
+    } else if (pos != nextchar) {
       if (totalfound) (*totalfound)++;
 
       /* See if the number found is one we have already seen */
@@ -1894,26 +1905,25 @@ static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
          ((nexttoken == -1) || (nextnumber1 < nexttoken))) {
         nexttoken = nextnumber1;
       }
+      pos = nextchar;
 
+    } else {
+      /* Step on to the next character, usually over comma */
+      if (*pos) pos++;
     }
 
-    /* Remember if it is followed by a star, and if it is indicate a need to
-       show all tokens, unless a duplicate has been found                    */
-    if (*nextchar == '*') {
-      if (doall) *doall = TRUE;
-      if (totalfound) (*totalfound)++;
-    }
-
-    /* Step on to the next character */
-    pos = nextchar;
-    if (*pos) pos++;
   }
 
   /* Return result */
-  if (nexttoken == -1) nexttoken = lasttoken;
-  WINE_TRACE("Found next token after %d was %d\n", lasttoken, nexttoken);
-  if (totalfound) WINE_TRACE("Found total tokens in total %d\n", *totalfound);
-  if (doall && *doall) WINE_TRACE("Request for all tokens found\n");
+  if (nexttoken == -1) {
+    WINE_TRACE("No next token found, previous was %d\n", lasttoken);
+    nexttoken = lasttoken;
+  } else if (nexttoken==lasttoken && doall && *doall) {
+    WINE_TRACE("Request for all remaining tokens now\n");
+  } else {
+    WINE_TRACE("Found next token after %d was %d\n", lasttoken, nexttoken);
+  }
+  if (totalfound) WINE_TRACE("Found total tokens to be %d\n", *totalfound);
   if (duplicates && *duplicates) WINE_TRACE("Duplicate numbers found\n");
   return nexttoken;
 }
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 08b9d9d..1874b0c 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -1774,11 +1774,12 @@ for /f "tokens=1,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k
 for /f "tokens=1,1,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
 for /f "tokens=2,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
 for /f "tokens=3,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o
-rem Special case tokens=*
+rem Special case tokens=* or tokens=n,*
 echo 3.14>testfile
 FOR /F "tokens=*"  %%A IN (testfile) DO @echo 1:%%A,%%B
 FOR /F "tokens=1*" %%A IN (testfile) DO @echo 2:%%A,%%B
 FOR /F "tokens=2*" %%A IN (testfile) DO @echo 3:%%A,%%B
+FOR /F "tokens=1,* delims=." %%A IN (testfile) DO @echo 4:%%A,%%B
 del testfile
 cd ..
 rd /s/q foobar
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index e105576..ebb3161 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -1255,6 +1255,7 @@ h=%h i=b j=c k= l= m=%m n=%n o=%o at or_broken@h=%h i=b j=c k= l= m= n=%n o=%o
 h=%h i=b j=c k= l= m=%m n=%n o=%o at or_broken@h=%h i=b j=c k= l= m= n=%n o=%o
 1:3.14,%B
 2:3.14,
+4:3,14
 ------ parameter splitting
 :forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest at space@@space@@space@
 :forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest at space@@space@@space@




More information about the wine-cvs mailing list