From: Dmitry Sokolov mr.dmitry.sokolov@gmail.com
Visual Studio's native tool command prompt uses rare FOR loop variables: %%1, %%2. This fix allows to use %%1 var in FOR loops.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55401 --- programs/cmd/builtins.c | 28 ++----------------- programs/cmd/tests/test_builtins.cmd | 35 +----------------------- programs/cmd/tests/test_builtins.cmd.exp | 10 ++----- programs/cmd/wcmd.h | 8 ++++++ 4 files changed, 14 insertions(+), 67 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index d8a74a6249f..d2cb7745a3a 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -1915,28 +1915,6 @@ static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr, return nexttoken; }
-/************************************************************************** - * WCMD_check_varidx - * - * Checks if the given varidx and varidx+varoffset are in suitable range, - * i.e. (0 <= X <= 25) || (26 <= X <= 51) || (52 <= X <= 61) - * a z A Z 0 9 - * - * Parameters: - * varidx [I] - Var index to check - * varoffset [I] - Var offset to check - * - * Returns TRUE on success, FALSE otherwise - */ -inline BOOL WCMD_check_varidx(int varidx, int varoffset) { - int X = varidx + varoffset; - return (varoffset >= 0) && ( - (0 <= varidx && varidx <= 25 && 0 <= X && X <= 25) || - (26 <= varidx && varidx <= 51 && 26 <= X && X <= 51) || - (52 <= varidx && varidx <= 61 && 52 <= X && X <= 61) - ); -} - /************************************************************************** * WCMD_parse_line * @@ -2006,7 +1984,7 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
/* Empty out variables */ for (varoffset=0; - varidx >= 0 && varoffset<totalfound && WCMD_check_varidx(varidx, varoffset); + varidx >= 0 && varoffset < totalfound && varidx+varoffset <= get_FOR_var_index_upper_boundary(varidx); varoffset++) { forloopcontext.variable[varidx + varoffset] = emptyW; } @@ -2029,7 +2007,7 @@ static void WCMD_parse_line(CMD_LIST *cmdStart, if (varidx >=0) { if (parm) forloopcontext.variable[varidx + varoffset] = xstrdupW(parm); varoffset++; - if (!WCMD_check_varidx(varidx, varoffset)) break; + if (varidx+varoffset > get_FOR_var_index_upper_boundary(varidx)) break; }
/* Find the next token */ @@ -2040,7 +2018,7 @@ 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 && WCMD_check_varidx(varidx, varoffset)) { + if (!anyduplicates && starfound && varidx >= 0 && varidx+varoffset <= get_FOR_var_index_upper_boundary(varidx)) { nexttoken++; WCMD_parameter_with_delims(buffer, (nexttoken-1), &parm, FALSE, FALSE, forf_delims); WINE_TRACE("Parsed allremaining tokens (%d) as parameter %s\n", diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index 13d58acf567..6081b945a7e 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -1606,49 +1606,16 @@ for %%i in (test) do ( )
echo --- for loop with rare var names -set "WINE_LOG_LEVEL=" -:test_for_loop_params set "WINE_ARGS= -foo=bar -x=y" :test_for_loop_params_parse for /F "tokens=1,* delims= " %%a in ("%WINE_ARGS%") do ( for /F "tokens=1,2 delims==" %%1 in ("%%a") do ( - if "%WINE_LOG_LEVEL%" GEQ "2" ( - echo [DEBUG] inner argument {%%1, %%2} - ) - call :test_for_loop_params_inner %%1 %%2 + echo inner argument {%%1, %%2} ) set "WINE_ARGS=%%b" goto :test_for_loop_params_parse ) -if not defined WINE_LOG_LEVEL set "WINE_LOG_LEVEL=1" & goto :test_for_loop_params -if "%WINE_LOG_LEVEL%" LSS "2" set "WINE_LOG_LEVEL=2" & goto :test_for_loop_params -goto :test_for_loop_params_end - -:test_for_loop_params_inner -set "__arg_found=" -if /I "%1"=="-foo" ( - echo foo=%2 - set "__arg_found=1" -) -if /I "%1"=="-x" ( - echo x=%2 - set "__arg_found=1" -) -if "%__arg_found%" NEQ "1" ( - if "%2"=="" ( - echo [ERROR] Invalid command line argument: '%1' - ) else ( - echo [ERROR] Invalid command line argument: '%1=%2' - ) - set "__arg_found=" - goto :eof -) -set "__arg_found=" -goto :eof - -:test_for_loop_params_end set "WINE_ARGS=" -set "WINE_LOG_LEVEL="
echo --- set /a diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index e106a0d2f9a..5a207686ff6 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -1066,14 +1066,8 @@ a4 c4 d4 --- for loop with rare var names -foo=bar -x=y -foo=bar -x=y -[DEBUG] inner argument {-foo, bar} -foo=bar -[DEBUG] inner argument {-x, y} -x=y +inner argument {-foo, bar} +inner argument {-x, y} --- set /a ------ individual operations WINE_foo correctly 3 diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 829c46100e5..24a317878e0 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -203,6 +203,14 @@ static inline WCHAR get_FOR_var_name(int index) return 'a'; }
+static inline int get_FOR_var_index_upper_boundary(int index) +{ + if (index >= 52) { return 61; } + if (index >= 26) { return 51; } + if (index >= 0) { return 25; } + return 0; +} + typedef struct _FOR_CONTEXT { WCHAR *variable[MAX_FOR_VARIABLES]; /* a-z then A-Z then 0-9 */ } FOR_CONTEXT;