cmd: Remove old FOR loop related code.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
Eric Pouech 2024-06-14 18:02:24 +02:00 committed by Alexandre Julliard
parent f98077591f
commit 96762f12e7
2 changed files with 2 additions and 682 deletions

View file

@ -1673,110 +1673,6 @@ void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
}
}
static BOOL option_equals(WCHAR **haystack, const WCHAR *needle)
{
int len = wcslen(needle);
if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
*haystack, len, needle, len) == CSTR_EQUAL) {
*haystack += len;
return TRUE;
}
return FALSE;
}
/*****************************************************************************
* WCMD_parse_forf_options
*
* Parses the for /f 'options', extracting the values and validating the
* keywords. Note all keywords are optional.
* Parameters:
* options [I] The unparsed parameter string
* eol [O] Set to the comment character (eol=x)
* skip [O] Set to the number of lines to skip (skip=xx)
* delims [O] Set to the token delimiters (delims=)
* tokens [O] Set to the requested tokens, as provided (tokens=)
* usebackq [O] Set to TRUE if usebackq found
*
* Returns TRUE on success, FALSE on syntax error
*
*/
static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
WCHAR *delims, WCHAR *tokens, BOOL *usebackq)
{
WCHAR *pos = options;
int len = lstrlenW(pos);
/* Initialize to defaults */
lstrcpyW(delims, L" \t");
lstrcpyW(tokens, L"1");
*eol = 0;
*skip = 0;
*usebackq = FALSE;
/* Strip (optional) leading and trailing quotes */
if ((*pos == '"') && (pos[len-1] == '"')) {
pos[len-1] = 0;
pos++;
}
/* Process each keyword */
while (pos && *pos) {
if (*pos == ' ' || *pos == '\t') {
pos++;
/* Save End of line character (Ignore line if first token (based on delims) starts with it) */
} else if (option_equals(&pos, L"eol=")) {
*eol = *pos++;
WINE_TRACE("Found eol as %c(%x)\n", *eol, *eol);
/* Save number of lines to skip (Can be in base 10, hex (0x...) or octal (0xx) */
} else if (option_equals(&pos, L"skip=")) {
WCHAR *nextchar = NULL;
*skip = wcstoul(pos, &nextchar, 0);
WINE_TRACE("Found skip as %d lines\n", *skip);
pos = nextchar;
/* Save if usebackq semantics are in effect */
} else if (option_equals(&pos, L"usebackq")) {
*usebackq = TRUE;
WINE_TRACE("Found usebackq\n");
/* Save the supplied delims. Slightly odd as space can be a delimiter but only
if you finish the optionsroot string with delims= otherwise the space is
just a token delimiter! */
} else if (option_equals(&pos, L"delims=")) {
int i=0;
while (*pos && *pos != ' ') {
delims[i++] = *pos;
pos++;
}
if (*pos==' ' && *(pos+1)==0) delims[i++] = *pos;
delims[i++] = 0; /* Null terminate the delims */
WINE_TRACE("Found delims as '%s'\n", wine_dbgstr_w(delims));
/* Save the tokens being requested */
} else if (option_equals(&pos, L"tokens=")) {
int i=0;
while (*pos && *pos != ' ') {
tokens[i++] = *pos;
pos++;
}
tokens[i++] = 0; /* Null terminate the tokens */
WINE_TRACE("Found tokens as '%s'\n", wine_dbgstr_w(tokens));
} else {
WINE_WARN("Unexpected data in optionsroot: '%s'\n", wine_dbgstr_w(pos));
return FALSE;
}
}
return TRUE;
}
/*****************************************************************************
* WCMD_add_dirstowalk
*
@ -1953,177 +1849,6 @@ int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
return nexttoken;
}
/**************************************************************************
* WCMD_parse_line
*
* When parsing file or string contents (for /f), once the string to parse
* has been identified, handle the various options and call the do part
* if appropriate.
*
* Parameters:
* cmdStart [I] - Identifies the list of commands making up the
* for loop body (especially if brackets in use)
* firstCmd [I] - The textual start of the command after the DO
* which is within the first item of cmdStart
* cmdEnd [O] - Identifies where to continue after the DO
* variable [I] - The variable identified on the for line
* buffer [I] - The string to parse
* doExecuted [O] - Set to TRUE if the DO is ever executed once
* forf_skip [I/O] - How many lines to skip first
* forf_eol [I] - The 'end of line' (comment) character
* forf_delims [I] - The delimiters to use when breaking the string apart
* forf_tokens [I] - The tokens to use when breaking the string apart
*/
static void WCMD_parse_line(CMD_NODE *cmdStart,
const WCHAR *firstCmd,
CMD_NODE **cmdEnd,
int varidx,
WCHAR *buffer,
BOOL *doExecuted,
int *forf_skip,
WCHAR forf_eol,
WCHAR *forf_delims,
WCHAR *forf_tokens) {
WCHAR *parm;
int varoffset;
int nexttoken, lasttoken = -1;
BOOL starfound = FALSE;
BOOL thisduplicate = FALSE;
BOOL anyduplicates = FALSE;
int totalfound;
static WCHAR emptyW[] = L"";
/* Skip lines if requested */
if (*forf_skip) {
(*forf_skip)--;
return;
}
/* Save away any existing for variable context (e.g. nested for loops) */
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).
Rough logic:
Count how many tokens are named in the line, identify the lowest
Empty (set to null terminated string) that number of named variables
While lasttoken != nextlowest
%letter = parameter number 'nextlowest'
letter++ (if >26 or >52 abort)
Go through token= string finding next lowest number
If token ends in * set %letter = raw position of token(nextnumber+1)
*/
lasttoken = -1;
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, &totalfound,
&starfound, &thisduplicate);
/* Empty out variables */
for (varoffset=0;
varidx >= 0 && varoffset<totalfound && for_var_index_in_range(varidx, varoffset);
varoffset++) {
WCMD_set_for_loop_variable(varidx + varoffset, emptyW);
}
/* 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 > 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,
varidx + varoffset, wine_dbgstr_w(parm));
if (varidx >=0) {
if (parm)
WCMD_set_for_loop_variable(varidx + varoffset, parm);
varoffset++;
}
/* Find the next token */
lasttoken = nexttoken;
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, NULL,
&starfound, &thisduplicate);
}
/* 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 && 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",
varidx + varoffset, wine_dbgstr_w(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) {
CMD_NODE *thisCmdStart = cmdStart;
*doExecuted = TRUE;
WCMD_part_execute(&thisCmdStart, firstCmd, FALSE, TRUE);
*cmdEnd = thisCmdStart;
}
WCMD_restore_for_loop_context();
}
/**************************************************************************
* WCMD_forf_getinput
*
* Return a FILE* which can be used for reading the input lines,
* either to a specific file (which may be quote delimited as we have to
* read the parameters in raw mode) or to a command which we need to
* execute. The command being executed runs in its own shell and stores
* its data in a temporary file.
*
* Parameters:
* usebackq [I] - Indicates whether usebackq is in effect or not
* itemStr [I] - The item to be handled, either a filename or
* whole command string to execute
* iscmd [I] - Identifies whether this is a command or not
*
* 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)
{
WCHAR *trimmed = NULL;
FILE* ret;
/* Remove leading and trailing character (but there may be trailing whitespace too) */
if ((iscmd && (itemstr[0] == '`' && usebackq)) ||
(iscmd && (itemstr[0] == '\'' && !usebackq)) ||
(!iscmd && (itemstr[0] == '"' && usebackq)))
{
trimmed = WCMD_strtrim(itemstr);
if (trimmed)
itemstr = trimmed;
itemstr[lstrlenW(itemstr)-1] = 0x00;
itemstr++;
}
if (iscmd)
{
WCHAR temp_cmd[MAXSTRING];
wsprintfW(temp_cmd, L"CMD.EXE /C %s", itemstr);
WINE_TRACE("Reading output of '%s'\n", wine_dbgstr_w(temp_cmd));
ret = _wpopen(temp_cmd, L"rt,ccs=unicode");
}
else
{
/* Open the file, read line by line and process */
WINE_TRACE("Reading input to parse from '%s'\n", wine_dbgstr_w(itemstr));
ret = _wfopen(itemstr, L"rt,ccs=unicode");
}
free(trimmed);
return ret;
}
/**************************************************************************
* WCMD_for
*
@ -2136,411 +1861,6 @@ static FILE *WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
*
*/
static void WCMD_for_OLD (WCHAR *p, CMD_NODE **cmdList) {
WIN32_FIND_DATAW fd;
HANDLE hff;
int i;
const int in_len = lstrlenW(L"in");
CMD_NODE *setStart, *thisSet, *cmdStart, *cmdEnd;
WCHAR variable[4];
int varidx = -1;
WCHAR *firstCmd;
int thisDepth;
WCHAR optionsRoot[MAX_PATH];
DIRECTORY_STACK *dirsToWalk = NULL;
BOOL expandDirs = FALSE;
BOOL useNumbers = FALSE;
BOOL doFileset = FALSE;
BOOL doRecurse = FALSE;
BOOL doExecuted = FALSE; /* Has the 'do' part been executed */
LONG numbers[3] = {0,0,0}; /* Defaults to 0 in native */
int itemNum;
CMD_NODE *thisCmdStart;
int parameterNo = 0;
WCHAR forf_eol = 0;
int forf_skip = 0;
WCHAR forf_delims[256];
WCHAR forf_tokens[MAXSTRING];
BOOL forf_usebackq = FALSE;
/* Handle optional qualifiers (multiple are allowed) */
WCHAR *thisArg = WCMD_parameter(p, parameterNo++, NULL, FALSE, FALSE);
optionsRoot[0] = 0;
while (thisArg && *thisArg == '/') {
WINE_TRACE("Processing qualifier at %s\n", wine_dbgstr_w(thisArg));
thisArg++;
switch (towupper(*thisArg)) {
case 'D': expandDirs = TRUE; break;
case 'L': useNumbers = TRUE; break;
/* Recursive is special case - /R can have an optional path following it */
/* filenamesets are another special case - /F can have an optional options following it */
case 'R':
case 'F':
{
/* When recursing directories, use current directory as the starting point unless
subsequently overridden */
doRecurse = (towupper(*thisArg) == 'R');
if (doRecurse) GetCurrentDirectoryW(ARRAY_SIZE(optionsRoot), optionsRoot);
doFileset = (towupper(*thisArg) == 'F');
/* Retrieve next parameter to see if is root/options (raw form required
with for /f, or unquoted in for /r) */
thisArg = WCMD_parameter(p, parameterNo, NULL, doFileset, FALSE);
/* Next parm is either qualifier, path/options or variable -
only care about it if it is the path/options */
if (thisArg && *thisArg != '/' && *thisArg != '%') {
parameterNo++;
lstrcpyW(optionsRoot, thisArg);
}
break;
}
default:
WINE_FIXME("for qualifier '%c' unhandled\n", *thisArg);
}
/* Step to next token */
thisArg = WCMD_parameter(p, parameterNo++, NULL, FALSE, FALSE);
}
/* Ensure line continues with variable */
if (*thisArg != '%') {
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
return;
}
/* With for /f parse the options if provided */
if (doFileset) {
if (!WCMD_parse_forf_options(optionsRoot, &forf_eol, &forf_skip,
forf_delims, forf_tokens, &forf_usebackq))
{
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
return;
}
/* Set up the list of directories to recurse if we are going to */
} else if (doRecurse) {
/* Allocate memory, add to list */
dirsToWalk = WCMD_dir_stack_create(optionsRoot, NULL);
TRACE("Starting with root directory %s\n", wine_dbgstr_w(dirsToWalk->dirName));
}
/* Variable should follow */
lstrcpyW(variable, thisArg);
WINE_TRACE("Variable identified as %s\n", wine_dbgstr_w(variable));
varidx = for_var_char_to_index(variable[1]);
/* Ensure line continues with IN */
thisArg = WCMD_parameter(p, parameterNo++, NULL, FALSE, FALSE);
if (!thisArg
|| !(CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
thisArg, in_len, L"in", in_len) == CSTR_EQUAL)) {
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
return;
}
/* Save away where the set of data starts and the variable */
thisDepth = CMD_node_get_depth(*cmdList);
*cmdList = CMD_node_next(*cmdList);
setStart = (*cmdList);
/* Skip until the close bracket */
WINE_TRACE("Searching %p as the set\n", *cmdList);
while (*cmdList &&
CMD_node_get_command(*cmdList)->command != NULL &&
CMD_node_get_depth(*cmdList) > thisDepth) {
WINE_TRACE("Skipping %p which is part of the set\n", *cmdList);
*cmdList = CMD_node_next(*cmdList);
}
/* Skip the close bracket, if there is one */
if (*cmdList) *cmdList = CMD_node_next(*cmdList);
/* Syntax error if missing close bracket, or nothing following it
and once we have the complete set, we expect a DO */
WINE_TRACE("Looking for 'do ' in %p\n", *cmdList);
if ((*cmdList == NULL) || !WCMD_keyword_ws_found(L"do", CMD_node_get_command(*cmdList)->command)) {
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
return;
}
cmdEnd = *cmdList;
/* Loop repeatedly per-directory we are potentially walking, when in for /r
mode, or once for the rest of the time. */
do {
/* Save away the starting position for the commands (and offset for the
first one) */
cmdStart = *cmdList;
firstCmd = CMD_node_get_command(*cmdList)->command + 3; /* Skip 'do ' */
itemNum = 0;
/* If we are recursing directories (ie /R), add all sub directories now, then
prefix the root when searching for the item */
if (dirsToWalk) WCMD_add_dirstowalk(dirsToWalk);
thisSet = setStart;
/* Loop through all set entries */
while (thisSet &&
CMD_node_get_command(thisSet)->command != NULL &&
CMD_node_get_depth(thisSet) >= thisDepth) {
/* Loop through all entries on the same line */
WCHAR *staticitem;
WCHAR *itemStart;
WCHAR buffer[MAXSTRING];
WINE_TRACE("Processing for set %p\n", thisSet);
i = 0;
while (*(staticitem = WCMD_parameter (CMD_node_get_command(thisSet)->command, i, &itemStart, TRUE, FALSE))) {
/*
* If the parameter within the set has a wildcard then search for matching files
* otherwise do a literal substitution.
*/
/* Take a copy of the item returned from WCMD_parameter as it is held in a
static buffer which can be overwritten during parsing of the for body */
WCHAR item[MAXSTRING];
lstrcpyW(item, staticitem);
thisCmdStart = cmdStart;
itemNum++;
WINE_TRACE("Processing for item %d '%s'\n", itemNum, wine_dbgstr_w(item));
if (!useNumbers && !doFileset) {
WCHAR fullitem[MAX_PATH];
int prefixlen = 0;
/* Now build the item to use / search for in the specified directory,
as it is fully qualified in the /R case */
if (dirsToWalk) {
lstrcpyW(fullitem, dirsToWalk->dirName);
lstrcatW(fullitem, L"\\");
lstrcatW(fullitem, item);
} else {
WCHAR *prefix = wcsrchr(item, '\\');
if (prefix) prefixlen = (prefix - item) + 1;
lstrcpyW(fullitem, item);
}
if (wcspbrk(fullitem, L"*?")) {
hff = FindFirstFileW(fullitem, &fd);
if (hff != INVALID_HANDLE_VALUE) {
do {
BOOL isDirectory = FALSE;
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) isDirectory = TRUE;
/* Handle as files or dirs appropriately, but ignore . and .. */
if (isDirectory == expandDirs &&
(lstrcmpW(fd.cFileName, L"..") != 0) && (lstrcmpW(fd.cFileName, L".") != 0))
{
thisCmdStart = cmdStart;
WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName));
if (doRecurse) {
if (wcslen(dirsToWalk->dirName) + 1 + wcslen(fd.cFileName) >= MAX_PATH)
{
WINE_TRACE("Skipping too long path %s\\%s\n",
debugstr_w(dirsToWalk->dirName), debugstr_w(fd.cFileName));
continue;
}
lstrcpyW(fullitem, dirsToWalk->dirName);
lstrcatW(fullitem, L"\\");
lstrcatW(fullitem, fd.cFileName);
} else {
if (prefixlen) lstrcpynW(fullitem, item, prefixlen + 1);
fullitem[prefixlen] = 0x00;
lstrcatW(fullitem, fd.cFileName);
}
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)
WCMD_set_for_loop_variable(varidx, fullitem);
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
WCMD_restore_for_loop_context();
cmdEnd = thisCmdStart;
}
} while (FindNextFileW(hff, &fd) != 0);
FindClose (hff);
}
} 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)
WCMD_set_for_loop_variable(varidx, fullitem);
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
WCMD_restore_for_loop_context();
cmdEnd = thisCmdStart;
}
} else if (useNumbers) {
/* Convert the first 3 numbers to signed longs and save */
if (itemNum <=3) numbers[itemNum-1] = wcstol(item, NULL, 10);
/* else ignore them! */
/* Filesets - either a list of files, or a command to run and parse the output */
} else if (doFileset && ((!forf_usebackq && *itemStart != '"') ||
(forf_usebackq && *itemStart != '\''))) {
FILE *input;
WCHAR *itemparm;
WINE_TRACE("Processing for filespec from item %d '%s'\n", itemNum,
wine_dbgstr_w(item));
/* If backquote or single quote, we need to launch that command
and parse the results - use a temporary file */
if ((forf_usebackq && *itemStart == '`') ||
(!forf_usebackq && *itemStart == '\'')) {
/* Use itemstart because the command is the whole set, not just the first token */
itemparm = itemStart;
} else {
/* Use item because the file to process is just the first item in the set */
itemparm = item;
}
input = WCMD_forf_getinput(forf_usebackq, itemparm, (itemparm==itemStart));
/* Process the input file */
if (!input) {
WCMD_print_error ();
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), item);
errorlevel = 1;
return; /* FOR loop aborts at first failure here */
} else {
/* Read line by line until end of file */
while (fgetws(buffer, ARRAY_SIZE(buffer), input)) {
size_t len = wcslen(buffer);
/* Either our buffer isn't large enough to fit a full line, or there's a stray
* '\0' in the buffer.
*/
if (!feof(input) && (len == 0 || (buffer[len - 1] != '\n' && buffer[len - 1] != '\r')))
break;
while (len && (buffer[len - 1] == '\n' || buffer[len - 1] == '\r'))
buffer[--len] = L'\0';
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;
}
fclose (input);
}
/* When we have processed the item as a whole command, abort future set processing */
if (itemparm==itemStart) {
thisSet = NULL;
break;
}
/* Filesets - A string literal */
} else if (doFileset && ((!forf_usebackq && *itemStart == '"') ||
(forf_usebackq && *itemStart == '\''))) {
/* Remove leading and trailing character, ready to parse with delims= delimiters
Note that the last quote is removed from the set and the string terminates
there to mimic windows */
WCHAR *strend = wcsrchr(itemStart, forf_usebackq?'\'':'"');
if (strend) {
*strend = 0x00;
itemStart++;
}
/* Copy the item away from the global buffer used by WCMD_parameter */
lstrcpyW(buffer, itemStart);
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 */
thisSet = NULL;
break;
}
WINE_TRACE("Post-command, cmdEnd = %p\n", cmdEnd);
i++;
}
/* Move onto the next set line */
if (thisSet) thisSet = CMD_node_next(thisSet);
}
/* If /L is provided, now run the for loop */
if (useNumbers) {
WCHAR thisNum[20];
WINE_TRACE("FOR /L provided range from %ld to %ld step %ld\n",
numbers[0], numbers[2], numbers[1]);
for (i=numbers[0];
(numbers[1]<0)? i>=numbers[2] : i<=numbers[2];
i=i + numbers[1]) {
swprintf(thisNum, ARRAY_SIZE(thisNum), L"%d", i);
WINE_TRACE("Processing FOR number %s\n", wine_dbgstr_w(thisNum));
thisCmdStart = cmdStart;
doExecuted = TRUE;
/* 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)
{
WCMD_save_for_loop_context(FALSE);
WCMD_set_for_loop_variable(varidx, thisNum);
}
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
if (varidx >= 0)
WCMD_restore_for_loop_context();
}
cmdEnd = thisCmdStart;
}
/* If we are walking directories, move on to any which remain */
if (dirsToWalk != NULL) {
dirsToWalk = WCMD_dir_stack_free(dirsToWalk);
if (dirsToWalk) WINE_TRACE("Moving to next directory to iterate: %s\n",
wine_dbgstr_w(dirsToWalk->dirName));
else WINE_TRACE("Finished all directories.\n");
}
} while (dirsToWalk != NULL);
/* Now skip over the do part if we did not perform the for loop so far.
We store in cmdEnd the next command after the do block, but we only
know this if something was run. If it has not been, we need to calculate
it. */
if (!doExecuted) {
thisCmdStart = cmdStart;
WINE_TRACE("Skipping for loop commands due to no valid iterations\n");
WCMD_part_execute(&thisCmdStart, firstCmd, FALSE, FALSE);
cmdEnd = thisCmdStart;
}
/* When the loop ends, either something like a GOTO or EXIT /b has terminated
all processing, OR it should be pointing to the end of && processing OR
it should be pointing at the NULL end of bracket for the DO. The return
value needs to be the NEXT command to execute, which it either is, or
we need to step over the closing bracket */
*cmdList = cmdEnd;
if (cmdEnd && CMD_node_get_command(cmdEnd)->command == NULL) *cmdList = CMD_node_next(cmdEnd);
}
void WCMD_for(WCHAR *p, CMD_NODE **cmdList)
{
CMD_FOR_CONTROL *for_ctrl;
@ -2548,8 +1868,7 @@ void WCMD_for(WCHAR *p, CMD_NODE **cmdList)
for_ctrl = for_control_parse(p);
if (!for_ctrl)
{
/* temporary code: use OLD code for non migrated FOR constructs */
WCMD_for_OLD(p, cmdList);
*cmdList = NULL;
return;
}

View file

@ -2277,6 +2277,7 @@ CMD_FOR_CONTROL *for_control_parse(WCHAR *opts_var)
for_op = CMD_FOR_FILE_SET;
break;
default:
FIXME("Unexpected situation\n");
return NULL;
}