From: Eric Pouech epouech@codeweavers.com
This should let the code be agnostic to the supported variables.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/batch.c | 4 ++-- programs/cmd/builtins.c | 18 +++++++++--------- programs/cmd/wcmd.h | 22 ++++++++++++++++++++-- programs/cmd/wcmdmain.c | 6 +++--- 4 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 455cc99083c..b67b14019f3 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -396,7 +396,7 @@ void WCMD_HandleTildeModifiers(WCHAR **start, BOOL atExecute) break;
} else { - int foridx = FOR_VAR_IDX(*lastModifier); + int foridx = for_var_char_to_index(*lastModifier); /* Its a valid parameter identifier - OK */ if ((foridx >= 0) && (forloopcontext.variable[foridx] != NULL)) break;
@@ -424,7 +424,7 @@ void WCMD_HandleTildeModifiers(WCHAR **start, BOOL atExecute) *lastModifier-'0' + context -> shift_count[*lastModifier-'0'], NULL, FALSE, TRUE)); } else { - int foridx = FOR_VAR_IDX(*lastModifier); + int foridx = for_var_char_to_index(*lastModifier); lstrcpyW(outputparam, forloopcontext.variable[foridx]); }
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 76f75bb2d96..f94230e6fae 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -1953,7 +1953,7 @@ static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr, static void WCMD_parse_line(CMD_NODE *cmdStart, const WCHAR *firstCmd, CMD_NODE **cmdEnd, - const WCHAR variable, + int varidx, WCHAR *buffer, BOOL *doExecuted, int *forf_skip, @@ -1963,7 +1963,7 @@ static void WCMD_parse_line(CMD_NODE *cmdStart,
WCHAR *parm; FOR_CONTEXT oldcontext; - int varidx, varoffset; + int varoffset; int nexttoken, lasttoken = -1; BOOL starfound = FALSE; BOOL thisduplicate = FALSE; @@ -1994,11 +1994,10 @@ static void WCMD_parse_line(CMD_NODE *cmdStart, lasttoken = -1; nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, &totalfound, &starfound, &thisduplicate); - varidx = FOR_VAR_IDX(variable);
/* Empty out variables */ for (varoffset=0; - varidx >= 0 && varoffset<totalfound && (((varidx%26) + varoffset) < 26); + varidx >= 0 && varoffset<totalfound && for_var_index_in_range(varidx, varoffset); varoffset++) { forloopcontext.variable[varidx + varoffset] = emptyW; } @@ -2011,6 +2010,8 @@ static void WCMD_parse_line(CMD_NODE *cmdStart, while (varidx >= 0 && (nexttoken > 0 && (nexttoken > lasttoken))) { anyduplicates |= thisduplicate;
+ if (!for_var_index_in_range(varidx, varoffset)) break; + /* Extract the token number requested and set into the next variable context */ parm = WCMD_parameter_with_delims(buffer, (nexttoken-1), NULL, TRUE, FALSE, forf_delims); WINE_TRACE("Parsed token %d(%d) as parameter %s\n", nexttoken, @@ -2018,7 +2019,6 @@ static void WCMD_parse_line(CMD_NODE *cmdStart, if (varidx >=0) { if (parm) forloopcontext.variable[varidx + varoffset] = xstrdupW(parm); varoffset++; - if (((varidx%26)+varoffset) >= 26) break; }
/* Find the next token */ @@ -2029,7 +2029,7 @@ static void WCMD_parse_line(CMD_NODE *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%26) + varoffset) < 26)) { + if (!anyduplicates && starfound && varidx >= 0 && for_var_index_in_range(varidx, varoffset)) { nexttoken++; WCMD_parameter_with_delims(buffer, (nexttoken-1), &parm, FALSE, FALSE, forf_delims); WINE_TRACE("Parsed allremaining tokens (%d) as parameter %s\n", @@ -2222,7 +2222,7 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) { /* Variable should follow */ lstrcpyW(variable, thisArg); WINE_TRACE("Variable identified as %s\n", wine_dbgstr_w(variable)); - varidx = FOR_VAR_IDX(variable[1]); + varidx = for_var_char_to_index(variable[1]);
/* Ensure line continues with IN */ thisArg = WCMD_parameter(p, parameterNo++, NULL, FALSE, FALSE); @@ -2429,7 +2429,7 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) { break; while (len && (buffer[len - 1] == '\n' || buffer[len - 1] == '\r')) buffer[--len] = L'\0'; - WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable[1], buffer, &doExecuted, + WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, for_var_char_to_index(variable[1]), buffer, &doExecuted, &forf_skip, forf_eol, forf_delims, forf_tokens); buffer[0] = 0; } @@ -2457,7 +2457,7 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
/* Copy the item away from the global buffer used by WCMD_parameter */ lstrcpyW(buffer, itemStart); - WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable[1], buffer, &doExecuted, + WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, for_var_char_to_index(variable[1]), buffer, &doExecuted, &forf_skip, forf_eol, forf_delims, forf_tokens);
/* Only one string can be supplied in the whole set, abort future set processing */ diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index def31d7e2d3..d556cd59fe8 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -267,8 +267,26 @@ typedef struct _DIRECTORY_STACK /* Data structure to for loop variables during for body execution, bearing in mind that for loops can be nested */ #define MAX_FOR_VARIABLES 52 -#define FOR_VAR_IDX(c) (((c)>='a'&&(c)<='z')?((c)-'a'):\ - ((c)>='A'&&(c)<='Z')?(26+(c)-'A'):-1) + +static inline int for_var_char_to_index(WCHAR c) +{ + if (c >= L'a' && c <= L'z') return c - L'a'; + if (c >= L'A' && c <= L'Z') return c - L'A' + 26; + return -1; +} + +static inline WCHAR for_var_index_to_char(int var_idx) +{ + if (var_idx < 0 || var_idx >= MAX_FOR_VARIABLES) return L'?'; + if (var_idx < 26) return L'a' + var_idx; + return L'A' + var_idx - 26; +} + +/* check that the range [var_idx, var_idx + var_offset] is a contiguous range */ +static inline BOOL for_var_index_in_range(int var_idx, int var_offset) +{ + return for_var_char_to_index(for_var_index_to_char(var_idx) + var_offset) == var_idx + var_offset; +}
typedef struct _FOR_CONTEXT { WCHAR *variable[MAX_FOR_VARIABLES]; /* a-z then A-Z */ diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 5f1a94b39b3..9e5f1eae241 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -807,10 +807,10 @@ static void handleExpansion(WCHAR *cmd, BOOL atExecute, BOOL delayed) { WCHAR *normalp;
/* Display the FOR variables in effect */ - for (i=0;i<52;i++) { + for (i=0;i<MAX_FOR_VARIABLES;i++) { if (forloopcontext.variable[i]) { WINE_TRACE("FOR variable context: %c = '%s'\n", - i<26?i+'a':(i-26)+'A', + for_var_index_to_char(i), wine_dbgstr_w(forloopcontext.variable[i])); } } @@ -859,7 +859,7 @@ static void handleExpansion(WCHAR *cmd, BOOL atExecute, BOOL delayed) { WCMD_strsubstW(p, p+2, NULL, 0);
} else { - int forvaridx = FOR_VAR_IDX(*(p+1)); + int forvaridx = for_var_char_to_index(*(p+1)); if (startchar == '%' && forvaridx != -1 && forloopcontext.variable[forvaridx]) { /* Replace the 2 characters, % and for variable character */ WCMD_strsubstW(p, p + 2, forloopcontext.variable[forvaridx], -1);