Jason Edmeades : cmd: Handle special case tokens=* in for /f.

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


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

Author: Jason Edmeades <us at edmeades.me.uk>
Date:   Sun Jul 15 23:15:27 2018 +0100

cmd: Handle special case tokens=* in for /f.

for /f allows a special syntax of tokens=* (rather than tokens=1* for example)
which just means put the whole line into the next variable). Note the handling of
the 'next variable' was wrong in the case of it being 'A' or 'a' as the wrap
calculation was wrong, but this only affected using this new syntax.

Signed-off-by: Jason Edmeades <us at edmeades.me.uk>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 4030a952095398e5a42f0a74213f6a1e9186c4bc)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 programs/cmd/builtins.c                  | 28 ++++++++++++++++++----------
 programs/cmd/tests/test_builtins.cmd     | 12 ++++++++++++
 programs/cmd/tests/test_builtins.cmd.exp |  5 +++++
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 752cf43..9cd86b3 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1845,6 +1845,14 @@ 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 */
+    if (*pos == '*') {
+      if (doall) *doall = TRUE;
+      if (totalfound) (*totalfound)++;
+      nexttoken = 0;
+      break;
+    }
+
     /* Get the next number */
     nextnumber1 = strtoulW(pos, &nextchar, 10);
 
@@ -1973,22 +1981,22 @@ static void WCMD_parse_line(CMD_LIST    *cmdStart,
    */
   lasttoken = -1;
   nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, &totalfound,
-                                 NULL, &thisduplicate);
+                                 &starfound, &thisduplicate);
   varidx = FOR_VAR_IDX(variable);
 
   /* Empty out variables */
   for (varoffset=0;
-       varidx >= 0 && varoffset<totalfound && ((varidx+varoffset)%26);
+       varidx >= 0 && varoffset<totalfound && (((varidx%26) + varoffset) < 26);
        varoffset++) {
     forloopcontext.variable[varidx + varoffset] = (WCHAR *)nullW;
-    /* Stop if we walk beyond z or Z */
-    if (((varidx+varoffset) % 26) == 0) break;
   }
 
-  /* Loop extracting the tokens */
+  /* Loop extracting the tokens
+     Note: nexttoken of 0 means there were no tokens requested, to handle
+           the special case of tokens=*                                   */
   varoffset = 0;
   WINE_TRACE("Parsing buffer into tokens: '%s'\n", wine_dbgstr_w(buffer));
-  while (varidx >= 0 && (nexttoken > lasttoken)) {
+  while (varidx >= 0 && (nexttoken > 0 && (nexttoken > lasttoken))) {
     anyduplicates |= thisduplicate;
 
     /* Extract the token number requested and set into the next variable context */
@@ -1996,9 +2004,9 @@ static void WCMD_parse_line(CMD_LIST    *cmdStart,
     WINE_TRACE("Parsed token %d(%d) as parameter %s\n", nexttoken,
                varidx + varoffset, wine_dbgstr_w(parm));
     if (varidx >=0) {
-      forloopcontext.variable[varidx + varoffset] = heap_strdupW(parm);
+      if (parm) forloopcontext.variable[varidx + varoffset] = heap_strdupW(parm);
       varoffset++;
-      if (((varidx + varoffset) %26) == 0) break;
+      if (((varidx%26)+varoffset) >= 26) break;
     }
 
     /* Find the next token */
@@ -2009,12 +2017,12 @@ static void WCMD_parse_line(CMD_LIST    *cmdStart,
 
   /* If all the rest of the tokens were requested, and there is still space in
      the variable range, write them now                                        */
-  if (!anyduplicates && starfound && varidx >= 0 && ((varidx+varoffset) % 26)) {
+  if (!anyduplicates && starfound && varidx >= 0 && (((varidx%26) + varoffset) < 26)) {
     nexttoken++;
     WCMD_parameter_with_delims(buffer, (nexttoken-1), &parm, FALSE, FALSE, forf_delims);
     WINE_TRACE("Parsed allremaining tokens (%d) as parameter %s\n",
                varidx + varoffset, wine_dbgstr_w(parm));
-    forloopcontext.variable[varidx + varoffset] = heap_strdupW(parm);
+    if (parm) forloopcontext.variable[varidx + varoffset] = heap_strdupW(parm);
   }
 
   /* Execute the body of the foor loop with these values */
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index cf9a986..08b9d9d 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -1774,6 +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=*
+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
+del testfile
 cd ..
 rd /s/q foobar
 echo ------ parameter splitting
@@ -1786,6 +1792,12 @@ goto :forFParameterSplittingEnd
 echo %~0 %~1 %~2 %~3 %~4 %~5
 goto :eof
 :forFParameterSplittingEnd
+echo 3.14>testfile
+FOR /F "delims=. tokens=*"  %%A IN (testfile) DO @echo 4:%%A,%%B
+FOR /F "delims=. tokens=1*" %%A IN (testfile) DO @echo 5:%%A,%%B
+FOR /F "delims=. tokens=2*" %%A IN (testfile) DO @echo 6:%%A,%%B
+FOR /F "delims=. tokens=3*" %%A IN (testfile) DO @echo 7:%%A,%%B
+del testfile
 
 echo ------------ Testing del ------------
 echo abc > file
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index dd8d1d4..e105576 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -1253,9 +1253,14 @@ h=%h i=a j=b k=c l=d e f g m=%m n=%n o=%o at or_broken@h=%h i=a j=b k=c l=d e f g m
 h=%h i=a j=c k= l= m=%m n=%n o=%o at or_broken@h=%h i=a 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
 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,
 ------ parameter splitting
 :forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest at space@@space@@space@
 :forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest at space@@space@@space@
+4:3.14,%B
+5:3,14
+6:14,
 ------------ Testing del ------------
 deleting 'file'
 errorlevel is 0, good




More information about the wine-cvs mailing list