[PATCH 2/3] [programs/cmd] Handle "for" loop handling of tokens, where * does not follow a number
Jason Edmeades
us at edmeades.me.uk
Mon Sep 10 17:30:19 CDT 2018
Fixes bug#45722
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.
Signed-off-by: Jason Edmeades <us at edmeades.me.uk>
---
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 1e6181ddff..5fc00a423f 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 e74d4910ed..bed395091e 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -1840,11 +1840,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 021a5b0893..5cca037a30 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -1269,6 +1269,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@
--
2.17.1
More information about the wine-devel
mailing list