mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
cmd: Introduce helpers to save and restore FOR loop contexts.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
parent
abcc2a1bc6
commit
dc7e8da528
4 changed files with 84 additions and 49 deletions
|
@ -398,7 +398,7 @@ void WCMD_HandleTildeModifiers(WCHAR **start, BOOL atExecute)
|
|||
} else {
|
||||
int foridx = for_var_char_to_index(*lastModifier);
|
||||
/* Its a valid parameter identifier - OK */
|
||||
if ((foridx >= 0) && (forloopcontext.variable[foridx] != NULL)) break;
|
||||
if ((foridx >= 0) && (forloopcontext->variable[foridx] != NULL)) break;
|
||||
|
||||
/* Its not a valid parameter identifier - step backwards */
|
||||
lastModifier--;
|
||||
|
@ -425,7 +425,8 @@ void WCMD_HandleTildeModifiers(WCHAR **start, BOOL atExecute)
|
|||
NULL, FALSE, TRUE));
|
||||
} else {
|
||||
int foridx = for_var_char_to_index(*lastModifier);
|
||||
lstrcpyW(outputparam, forloopcontext.variable[foridx]);
|
||||
if (foridx != -1)
|
||||
lstrcpyW(outputparam, forloopcontext->variable[foridx]);
|
||||
}
|
||||
|
||||
/* 1. Handle '~' : Strip surrounding quotes */
|
||||
|
@ -663,12 +664,10 @@ void WCMD_call (WCHAR *command) {
|
|||
if (context) {
|
||||
|
||||
LARGE_INTEGER li;
|
||||
FOR_CONTEXT oldcontext;
|
||||
|
||||
/* Save the for variable context, then start with an empty context
|
||||
as for loop variables do not survive a call */
|
||||
oldcontext = forloopcontext;
|
||||
memset(&forloopcontext, 0, sizeof(forloopcontext));
|
||||
WCMD_save_for_loop_context(TRUE);
|
||||
|
||||
/* Save the current file position, call the same file,
|
||||
restore position */
|
||||
|
@ -680,7 +679,7 @@ void WCMD_call (WCHAR *command) {
|
|||
&li.u.HighPart, FILE_BEGIN);
|
||||
|
||||
/* Restore the for loop context */
|
||||
forloopcontext = oldcontext;
|
||||
WCMD_restore_for_loop_context();
|
||||
} else {
|
||||
WCMD_output_asis_stderr(WCMD_LoadMessage(WCMD_CALLINSCRIPT));
|
||||
}
|
||||
|
|
|
@ -1962,7 +1962,6 @@ static void WCMD_parse_line(CMD_NODE *cmdStart,
|
|||
WCHAR *forf_tokens) {
|
||||
|
||||
WCHAR *parm;
|
||||
FOR_CONTEXT oldcontext;
|
||||
int varoffset;
|
||||
int nexttoken, lasttoken = -1;
|
||||
BOOL starfound = FALSE;
|
||||
|
@ -1978,7 +1977,7 @@ static void WCMD_parse_line(CMD_NODE *cmdStart,
|
|||
}
|
||||
|
||||
/* Save away any existing for variable context (e.g. nested for loops) */
|
||||
oldcontext = forloopcontext;
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
|
||||
/* Extract the parameters based on the tokens= value (There will always
|
||||
be some value, as if it is not supplied, it defaults to tokens=1).
|
||||
|
@ -1999,7 +1998,7 @@ static void WCMD_parse_line(CMD_NODE *cmdStart,
|
|||
for (varoffset=0;
|
||||
varidx >= 0 && varoffset<totalfound && for_var_index_in_range(varidx, varoffset);
|
||||
varoffset++) {
|
||||
forloopcontext.variable[varidx + varoffset] = emptyW;
|
||||
WCMD_set_for_loop_variable(varidx + varoffset, emptyW);
|
||||
}
|
||||
|
||||
/* Loop extracting the tokens
|
||||
|
@ -2017,7 +2016,8 @@ static void WCMD_parse_line(CMD_NODE *cmdStart,
|
|||
WINE_TRACE("Parsed token %d(%d) as parameter %s\n", nexttoken,
|
||||
varidx + varoffset, wine_dbgstr_w(parm));
|
||||
if (varidx >=0) {
|
||||
if (parm) forloopcontext.variable[varidx + varoffset] = xstrdupW(parm);
|
||||
if (parm)
|
||||
WCMD_set_for_loop_variable(varidx + varoffset, parm);
|
||||
varoffset++;
|
||||
}
|
||||
|
||||
|
@ -2034,30 +2034,19 @@ static void WCMD_parse_line(CMD_NODE *cmdStart,
|
|||
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));
|
||||
if (parm) forloopcontext.variable[varidx + varoffset] = xstrdupW(parm);
|
||||
if (parm)
|
||||
WCMD_set_for_loop_variable(varidx + varoffset, parm);
|
||||
}
|
||||
|
||||
/* Execute the body of the foor loop with these values */
|
||||
if (varidx >= 0 && forloopcontext.variable[varidx] && forloopcontext.variable[varidx][0] != forf_eol) {
|
||||
if (varidx >= 0 && forloopcontext->variable[varidx] && forloopcontext->variable[varidx][0] != forf_eol) {
|
||||
CMD_NODE *thisCmdStart = cmdStart;
|
||||
*doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
*cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
/* Free the duplicated strings, and restore the context */
|
||||
if (varidx >=0) {
|
||||
int i;
|
||||
for (i=varidx; i<MAX_FOR_VARIABLES; i++) {
|
||||
if ((forloopcontext.variable[i] != oldcontext.variable[i]) &&
|
||||
(forloopcontext.variable[i] != emptyW)) {
|
||||
free(forloopcontext.variable[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore the original for variable contextx */
|
||||
forloopcontext = oldcontext;
|
||||
WCMD_restore_for_loop_context();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -2077,7 +2066,7 @@ static void WCMD_parse_line(CMD_NODE *cmdStart,
|
|||
*
|
||||
* Returns a file handle which can be used to read the input lines from.
|
||||
*/
|
||||
static FILE* WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
|
||||
static FILE *WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
|
||||
{
|
||||
WCHAR *trimmed = NULL;
|
||||
FILE* ret;
|
||||
|
@ -2132,7 +2121,6 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
|
|||
CMD_NODE *setStart, *thisSet, *cmdStart, *cmdEnd;
|
||||
WCHAR variable[4];
|
||||
int varidx = -1;
|
||||
WCHAR *oldvariablevalue;
|
||||
WCHAR *firstCmd;
|
||||
int thisDepth;
|
||||
WCHAR optionsRoot[MAX_PATH];
|
||||
|
@ -2352,14 +2340,13 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
|
|||
}
|
||||
doExecuted = TRUE;
|
||||
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
/* Save away any existing for variable context (e.g. nested for loops)
|
||||
and restore it after executing the body of this for loop */
|
||||
if (varidx >= 0) {
|
||||
oldvariablevalue = forloopcontext.variable[varidx];
|
||||
forloopcontext.variable[varidx] = fullitem;
|
||||
}
|
||||
if (varidx >= 0)
|
||||
WCMD_set_for_loop_variable(varidx, fullitem);
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
if (varidx >= 0) forloopcontext.variable[varidx] = oldvariablevalue;
|
||||
WCMD_restore_for_loop_context();
|
||||
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
@ -2369,14 +2356,13 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
|
|||
} else {
|
||||
doExecuted = TRUE;
|
||||
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
/* Save away any existing for variable context (e.g. nested for loops)
|
||||
and restore it after executing the body of this for loop */
|
||||
if (varidx >= 0) {
|
||||
oldvariablevalue = forloopcontext.variable[varidx];
|
||||
forloopcontext.variable[varidx] = fullitem;
|
||||
}
|
||||
if (varidx >= 0)
|
||||
WCMD_set_for_loop_variable(varidx, fullitem);
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
if (varidx >= 0) forloopcontext.variable[varidx] = oldvariablevalue;
|
||||
WCMD_restore_for_loop_context();
|
||||
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
@ -2491,12 +2477,14 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
|
|||
|
||||
/* Save away any existing for variable context (e.g. nested for loops)
|
||||
and restore it after executing the body of this for loop */
|
||||
if (varidx >= 0) {
|
||||
oldvariablevalue = forloopcontext.variable[varidx];
|
||||
forloopcontext.variable[varidx] = thisNum;
|
||||
if (varidx >= 0)
|
||||
{
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
WCMD_set_for_loop_variable(varidx, thisNum);
|
||||
}
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
if (varidx >= 0) forloopcontext.variable[varidx] = oldvariablevalue;
|
||||
if (varidx >= 0)
|
||||
WCMD_restore_for_loop_context();
|
||||
}
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
|
|
@ -288,10 +288,16 @@ 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 */
|
||||
typedef struct _FOR_CONTEXT
|
||||
{
|
||||
struct _FOR_CONTEXT *previous;
|
||||
WCHAR *variable[MAX_FOR_VARIABLES]; /* a-z then A-Z */
|
||||
} FOR_CONTEXT;
|
||||
|
||||
void WCMD_save_for_loop_context(BOOL reset);
|
||||
void WCMD_restore_for_loop_context(void);
|
||||
void WCMD_set_for_loop_variable(int var_idx, const WCHAR *value);
|
||||
|
||||
/*
|
||||
* Global variables quals, param1, param2 contain the current qualifiers
|
||||
* (uppercased and concatenated) and parameters entered, with environment
|
||||
|
@ -300,7 +306,7 @@ typedef struct _FOR_CONTEXT {
|
|||
extern WCHAR quals[MAXSTRING], param1[MAXSTRING], param2[MAXSTRING];
|
||||
extern int errorlevel;
|
||||
extern BATCH_CONTEXT *context;
|
||||
extern FOR_CONTEXT forloopcontext;
|
||||
extern FOR_CONTEXT *forloopcontext;
|
||||
extern BOOL delayedsubst;
|
||||
|
||||
#endif /* !RC_INVOKED */
|
||||
|
|
|
@ -39,7 +39,7 @@ BATCH_CONTEXT *context = NULL;
|
|||
int errorlevel;
|
||||
WCHAR quals[MAXSTRING], param1[MAXSTRING], param2[MAXSTRING];
|
||||
BOOL interactive;
|
||||
FOR_CONTEXT forloopcontext; /* The 'for' loop context */
|
||||
FOR_CONTEXT *forloopcontext; /* The 'for' loop context */
|
||||
BOOL delayedsubst = FALSE; /* The current delayed substitution setting */
|
||||
|
||||
int defaultColor = 7;
|
||||
|
@ -808,10 +808,10 @@ static void handleExpansion(WCHAR *cmd, BOOL atExecute, BOOL delayed) {
|
|||
|
||||
/* Display the FOR variables in effect */
|
||||
for (i=0;i<MAX_FOR_VARIABLES;i++) {
|
||||
if (forloopcontext.variable[i]) {
|
||||
if (forloopcontext->variable[i]) {
|
||||
WINE_TRACE("FOR variable context: %c = '%s'\n",
|
||||
for_var_index_to_char(i),
|
||||
wine_dbgstr_w(forloopcontext.variable[i]));
|
||||
wine_dbgstr_w(forloopcontext->variable[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -860,9 +860,9 @@ static void handleExpansion(WCHAR *cmd, BOOL atExecute, BOOL delayed) {
|
|||
|
||||
} else {
|
||||
int forvaridx = for_var_char_to_index(*(p+1));
|
||||
if (startchar == '%' && forvaridx != -1 && forloopcontext.variable[forvaridx]) {
|
||||
if (startchar == '%' && forvaridx != -1 && forloopcontext->variable[forvaridx]) {
|
||||
/* Replace the 2 characters, % and for variable character */
|
||||
WCMD_strsubstW(p, p + 2, forloopcontext.variable[forvaridx], -1);
|
||||
WCMD_strsubstW(p, p + 2, forloopcontext->variable[forvaridx], -1);
|
||||
} else if (!atExecute || startchar == '!') {
|
||||
p = WCMD_expand_envvar(p, startchar);
|
||||
|
||||
|
@ -2710,6 +2710,44 @@ BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void WCMD_save_for_loop_context(BOOL reset)
|
||||
{
|
||||
FOR_CONTEXT *new = xalloc(sizeof(*new));
|
||||
if (reset)
|
||||
memset(new, 0, sizeof(*new));
|
||||
else /* clone existing */
|
||||
*new = *forloopcontext;
|
||||
new->previous = forloopcontext;
|
||||
forloopcontext = new;
|
||||
}
|
||||
|
||||
void WCMD_restore_for_loop_context(void)
|
||||
{
|
||||
FOR_CONTEXT *old = forloopcontext->previous;
|
||||
int varidx;
|
||||
if (!old)
|
||||
{
|
||||
FIXME("Unexpected situation\n");
|
||||
return;
|
||||
}
|
||||
for (varidx = 0; varidx < MAX_FOR_VARIABLES; varidx++)
|
||||
{
|
||||
if (forloopcontext->variable[varidx] != old->variable[varidx])
|
||||
free(forloopcontext->variable[varidx]);
|
||||
}
|
||||
free(forloopcontext);
|
||||
forloopcontext = old;
|
||||
}
|
||||
|
||||
void WCMD_set_for_loop_variable(int var_idx, const WCHAR *value)
|
||||
{
|
||||
if (var_idx < 0 || var_idx >= MAX_FOR_VARIABLES) return;
|
||||
if (forloopcontext->previous &&
|
||||
forloopcontext->previous->variable[var_idx] != forloopcontext->variable[var_idx])
|
||||
free(forloopcontext->variable[var_idx]);
|
||||
forloopcontext->variable[var_idx] = xstrdupW(value);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* WCMD_process_commands
|
||||
*
|
||||
|
@ -2799,6 +2837,10 @@ int __cdecl wmain (int argc, WCHAR *argvW[])
|
|||
LocalFree(cmd);
|
||||
cmd = NULL;
|
||||
|
||||
/* init for loop context */
|
||||
forloopcontext = NULL;
|
||||
WCMD_save_for_loop_context(TRUE);
|
||||
|
||||
/* Can't use argc/argv as it will have stripped quotes from parameters
|
||||
* meaning cmd.exe /C echo "quoted string" is impossible
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue