cmd: Add full for /R support.
This commit is contained in:
parent
8fbd65358e
commit
9dde62cb96
|
@ -1079,10 +1079,13 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
|
|||
WCHAR variable[4];
|
||||
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;
|
||||
|
@ -1091,6 +1094,8 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
|
|||
|
||||
/* Handle optional qualifiers (multiple are allowed) */
|
||||
WCHAR *thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE);
|
||||
|
||||
optionsRoot[0] = 0;
|
||||
while (thisArg && *thisArg == '/') {
|
||||
WINE_TRACE("Processing qualifier at %s\n", wine_dbgstr_w(thisArg));
|
||||
thisArg++;
|
||||
|
@ -1103,20 +1108,23 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
|
|||
case 'R':
|
||||
case 'F':
|
||||
{
|
||||
BOOL isRecursive = (*thisArg == 'R');
|
||||
/* When recursing directories, use current directory as the starting point unless
|
||||
subsequently overridden */
|
||||
doRecurse = (toupperW(*thisArg) == 'R');
|
||||
if (doRecurse) GetCurrentDirectoryW(sizeof(optionsRoot)/sizeof(WCHAR), optionsRoot);
|
||||
|
||||
if (!isRecursive)
|
||||
doFileset = TRUE;
|
||||
doFileset = (toupperW(*thisArg) == 'F');
|
||||
|
||||
/* Retrieve next parameter to see if is path/options */
|
||||
thisArg = WCMD_parameter(p, parameterNo, NULL, NULL, !isRecursive);
|
||||
/* 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, NULL, doFileset);
|
||||
|
||||
/* Next parm is either qualifier, path/options or variable -
|
||||
only care about it if it is the path/options */
|
||||
if (thisArg && *thisArg != '/' && *thisArg != '%') {
|
||||
parameterNo++;
|
||||
if (isRecursive) WINE_FIXME("/R needs to handle supplied root\n");
|
||||
else {
|
||||
strcpyW(optionsRoot, thisArg);
|
||||
if (!doRecurse) {
|
||||
static unsigned int once;
|
||||
if (!once++) WINE_FIXME("/F needs to handle options\n");
|
||||
}
|
||||
|
@ -1137,6 +1145,17 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set up the list of directories to recurse if we are going to */
|
||||
if (doRecurse) {
|
||||
/* Allocate memory, add to list */
|
||||
dirsToWalk = HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY_STACK));
|
||||
dirsToWalk->next = NULL;
|
||||
dirsToWalk->dirName = HeapAlloc(GetProcessHeap(),0,
|
||||
(strlenW(optionsRoot) + 1) * sizeof(WCHAR));
|
||||
strcpyW(dirsToWalk->dirName, optionsRoot);
|
||||
WINE_TRACE("Starting with root directory %s\n", wine_dbgstr_w(dirsToWalk->dirName));
|
||||
}
|
||||
|
||||
/* Variable should follow */
|
||||
strcpyW(variable, thisArg);
|
||||
WINE_TRACE("Variable identified as %s\n", wine_dbgstr_w(variable));
|
||||
|
@ -1178,198 +1197,277 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Save away the starting position for the commands (and offset for the
|
||||
first one */
|
||||
cmdStart = *cmdList;
|
||||
cmdEnd = *cmdList;
|
||||
firstCmd = (*cmdList)->command + 3; /* Skip 'do ' */
|
||||
itemNum = 0;
|
||||
|
||||
thisSet = setStart;
|
||||
/* Loop through all set entries */
|
||||
while (thisSet &&
|
||||
thisSet->command != NULL &&
|
||||
thisSet->bracketDepth >= thisDepth) {
|
||||
/* Loop repeatedly per-directory we are potentially walking, when in for /r
|
||||
mode, or once for the rest of the time. */
|
||||
do {
|
||||
WCHAR fullitem[MAX_PATH];
|
||||
static const WCHAR slashstarW[] = {'\\','*','\0'};
|
||||
|
||||
/* Loop through all entries on the same line */
|
||||
WCHAR *item;
|
||||
WCHAR *itemStart;
|
||||
/* Save away the starting position for the commands (and offset for the
|
||||
first one) */
|
||||
cmdStart = *cmdList;
|
||||
firstCmd = (*cmdList)->command + 3; /* Skip 'do ' */
|
||||
itemNum = 0;
|
||||
|
||||
WINE_TRACE("Processing for set %p\n", thisSet);
|
||||
i = 0;
|
||||
while (*(item = WCMD_parameter (thisSet->command, i, &itemStart, NULL, TRUE))) {
|
||||
/* If we are recursing directories (ie /R), add all sub directories now, then
|
||||
prefix the root when searching for the item */
|
||||
if (dirsToWalk) {
|
||||
DIRECTORY_STACK *remainingDirs = dirsToWalk;
|
||||
|
||||
/*
|
||||
* If the parameter within the set has a wildcard then search for matching files
|
||||
* otherwise do a literal substitution.
|
||||
*/
|
||||
static const WCHAR wildcards[] = {'*','?','\0'};
|
||||
thisCmdStart = cmdStart;
|
||||
|
||||
itemNum++;
|
||||
WINE_TRACE("Processing for item %d '%s'\n", itemNum, wine_dbgstr_w(item));
|
||||
|
||||
if (!useNumbers && !doFileset) {
|
||||
if (strpbrkW (item, wildcards)) {
|
||||
hff = FindFirstFileW(item, &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 &&
|
||||
(strcmpW(fd.cFileName, dotdotW) != 0) &&
|
||||
(strcmpW(fd.cFileName, dotW) != 0))
|
||||
{
|
||||
thisCmdStart = cmdStart;
|
||||
WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName));
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, variable,
|
||||
fd.cFileName, FALSE, TRUE);
|
||||
}
|
||||
|
||||
} while (FindNextFileW(hff, &fd) != 0);
|
||||
FindClose (hff);
|
||||
}
|
||||
} else {
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, item, FALSE, TRUE);
|
||||
}
|
||||
|
||||
} else if (useNumbers) {
|
||||
/* Convert the first 3 numbers to signed longs and save */
|
||||
if (itemNum <=3) numbers[itemNum-1] = atolW(item);
|
||||
/* else ignore them! */
|
||||
|
||||
/* Filesets - either a list of files, or a command to run and parse the output */
|
||||
} else if (doFileset && *itemStart != '"') {
|
||||
|
||||
HANDLE input;
|
||||
WCHAR temp_file[MAX_PATH];
|
||||
|
||||
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 (*itemStart == '`' || *itemStart == '\'') {
|
||||
|
||||
WCHAR temp_path[MAX_PATH], temp_cmd[MAXSTRING];
|
||||
static const WCHAR redirOut[] = {'>','%','s','\0'};
|
||||
static const WCHAR cmdW[] = {'C','M','D','\0'};
|
||||
|
||||
/* Remove trailing character */
|
||||
itemStart[strlenW(itemStart)-1] = 0x00;
|
||||
|
||||
/* Get temp filename */
|
||||
GetTempPathW(sizeof(temp_path)/sizeof(WCHAR), temp_path);
|
||||
GetTempFileNameW(temp_path, cmdW, 0, temp_file);
|
||||
|
||||
/* Execute program and redirect output */
|
||||
wsprintfW(temp_cmd, redirOut, (itemStart+1), temp_file);
|
||||
WCMD_execute (itemStart, temp_cmd, NULL, NULL, NULL);
|
||||
|
||||
/* Open the file, read line by line and process */
|
||||
input = CreateFileW(temp_file, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
} else {
|
||||
|
||||
/* Open the file, read line by line and process */
|
||||
input = CreateFileW(item, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
|
||||
/* Process the input file */
|
||||
if (input == INVALID_HANDLE_VALUE) {
|
||||
WCMD_print_error ();
|
||||
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), item);
|
||||
errorlevel = 1;
|
||||
return; /* FOR loop aborts at first failure here */
|
||||
|
||||
} else {
|
||||
|
||||
WCHAR buffer[MAXSTRING] = {'\0'};
|
||||
WCHAR *where, *parm;
|
||||
|
||||
while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
|
||||
|
||||
/* Skip blank lines*/
|
||||
parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
|
||||
WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
|
||||
wine_dbgstr_w(buffer));
|
||||
|
||||
if (where) {
|
||||
/* FIXME: The following should be moved into its own routine and
|
||||
reused for the string literal parsing below */
|
||||
thisCmdStart = cmdStart;
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, parm, FALSE, TRUE);
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
buffer[0] = 0x00;
|
||||
|
||||
}
|
||||
CloseHandle (input);
|
||||
}
|
||||
|
||||
/* Delete the temporary file */
|
||||
if (*itemStart == '`' || *itemStart == '\'') {
|
||||
DeleteFileW(temp_file);
|
||||
}
|
||||
|
||||
/* Filesets - A string literal */
|
||||
} else if (doFileset && *itemStart == '"') {
|
||||
WCHAR buffer[MAXSTRING] = {'\0'};
|
||||
WCHAR *where, *parm;
|
||||
|
||||
/* Skip blank lines, and re-extract parameter now string has quotes removed */
|
||||
strcpyW(buffer, item);
|
||||
parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
|
||||
WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
|
||||
wine_dbgstr_w(buffer));
|
||||
|
||||
if (where) {
|
||||
/* FIXME: The following should be moved into its own routine and
|
||||
reused for the string literal parsing below */
|
||||
thisCmdStart = cmdStart;
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, parm, FALSE, TRUE);
|
||||
cmdEnd = thisCmdStart;
|
||||
/* Build a generic search and add all directories on the list of directories
|
||||
still to walk */
|
||||
strcpyW(fullitem, dirsToWalk->dirName);
|
||||
strcatW(fullitem, slashstarW);
|
||||
hff = FindFirstFileW(fullitem, &fd);
|
||||
if (hff != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
WINE_TRACE("Looking for subdirectories\n");
|
||||
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
(strcmpW(fd.cFileName, dotdotW) != 0) &&
|
||||
(strcmpW(fd.cFileName, dotW) != 0))
|
||||
{
|
||||
/* Allocate memory, add to list */
|
||||
DIRECTORY_STACK *toWalk = HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY_STACK));
|
||||
WINE_TRACE("(%p->%p)\n", remainingDirs, remainingDirs->next);
|
||||
toWalk->next = remainingDirs->next;
|
||||
remainingDirs->next = toWalk;
|
||||
remainingDirs = toWalk;
|
||||
toWalk->dirName = HeapAlloc(GetProcessHeap(), 0,
|
||||
sizeof(WCHAR) *
|
||||
(strlenW(dirsToWalk->dirName) + 2 + strlenW(fd.cFileName)));
|
||||
strcpyW(toWalk->dirName, dirsToWalk->dirName);
|
||||
strcatW(toWalk->dirName, slashW);
|
||||
strcatW(toWalk->dirName, fd.cFileName);
|
||||
WINE_TRACE("Added to stack %s (%p->%p)\n", wine_dbgstr_w(toWalk->dirName),
|
||||
toWalk, toWalk->next);
|
||||
}
|
||||
} while (FindNextFileW(hff, &fd) != 0);
|
||||
WINE_TRACE("Finished adding all subdirectories\n");
|
||||
FindClose (hff);
|
||||
}
|
||||
|
||||
WINE_TRACE("Post-command, cmdEnd = %p\n", cmdEnd);
|
||||
cmdEnd = thisCmdStart;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Move onto the next set line */
|
||||
thisSet = thisSet->nextcommand;
|
||||
}
|
||||
thisSet = setStart;
|
||||
/* Loop through all set entries */
|
||||
while (thisSet &&
|
||||
thisSet->command != NULL &&
|
||||
thisSet->bracketDepth >= thisDepth) {
|
||||
|
||||
/* If /L is provided, now run the for loop */
|
||||
if (useNumbers) {
|
||||
WCHAR thisNum[20];
|
||||
static const WCHAR fmt[] = {'%','d','\0'};
|
||||
/* Loop through all entries on the same line */
|
||||
WCHAR *item;
|
||||
WCHAR *itemStart;
|
||||
|
||||
WINE_TRACE("FOR /L provided range from %d to %d step %d\n",
|
||||
numbers[0], numbers[2], numbers[1]);
|
||||
for (i=numbers[0];
|
||||
(numbers[1]<0)? i>=numbers[2] : i<=numbers[2];
|
||||
i=i + numbers[1]) {
|
||||
WINE_TRACE("Processing for set %p\n", thisSet);
|
||||
i = 0;
|
||||
while (*(item = WCMD_parameter (thisSet->command, i, &itemStart, NULL, TRUE))) {
|
||||
|
||||
sprintfW(thisNum, fmt, i);
|
||||
WINE_TRACE("Processing FOR number %s\n", wine_dbgstr_w(thisNum));
|
||||
/*
|
||||
* If the parameter within the set has a wildcard then search for matching files
|
||||
* otherwise do a literal substitution.
|
||||
*/
|
||||
static const WCHAR wildcards[] = {'*','?','\0'};
|
||||
thisCmdStart = cmdStart;
|
||||
|
||||
thisCmdStart = cmdStart;
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, thisNum, FALSE, TRUE);
|
||||
itemNum++;
|
||||
WINE_TRACE("Processing for item %d '%s'\n", itemNum, wine_dbgstr_w(item));
|
||||
|
||||
if (!useNumbers && !doFileset) {
|
||||
WCHAR fullitem[MAX_PATH];
|
||||
|
||||
/* Now build the item to use / search for in the specified directory,
|
||||
as it is fully qualified in the /R case */
|
||||
if (dirsToWalk) {
|
||||
strcpyW(fullitem, dirsToWalk->dirName);
|
||||
strcatW(fullitem, slashW);
|
||||
strcatW(fullitem, item);
|
||||
} else {
|
||||
strcpyW(fullitem, item);
|
||||
}
|
||||
|
||||
if (strpbrkW (fullitem, wildcards)) {
|
||||
|
||||
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 &&
|
||||
(strcmpW(fd.cFileName, dotdotW) != 0) &&
|
||||
(strcmpW(fd.cFileName, dotW) != 0))
|
||||
{
|
||||
thisCmdStart = cmdStart;
|
||||
WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName));
|
||||
|
||||
if (doRecurse) {
|
||||
strcpyW(fullitem, dirsToWalk->dirName);
|
||||
strcatW(fullitem, slashW);
|
||||
strcatW(fullitem, fd.cFileName);
|
||||
} else {
|
||||
strcpyW(fullitem, fd.cFileName);
|
||||
}
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, variable,
|
||||
fullitem, FALSE, TRUE);
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
} while (FindNextFileW(hff, &fd) != 0);
|
||||
FindClose (hff);
|
||||
}
|
||||
} else {
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, fullitem, FALSE, TRUE);
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
} else if (useNumbers) {
|
||||
/* Convert the first 3 numbers to signed longs and save */
|
||||
if (itemNum <=3) numbers[itemNum-1] = atolW(item);
|
||||
/* else ignore them! */
|
||||
|
||||
/* Filesets - either a list of files, or a command to run and parse the output */
|
||||
} else if (doFileset && *itemStart != '"') {
|
||||
|
||||
HANDLE input;
|
||||
WCHAR temp_file[MAX_PATH];
|
||||
|
||||
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 (*itemStart == '`' || *itemStart == '\'') {
|
||||
|
||||
WCHAR temp_path[MAX_PATH], temp_cmd[MAXSTRING];
|
||||
static const WCHAR redirOut[] = {'>','%','s','\0'};
|
||||
static const WCHAR cmdW[] = {'C','M','D','\0'};
|
||||
|
||||
/* Remove trailing character */
|
||||
itemStart[strlenW(itemStart)-1] = 0x00;
|
||||
|
||||
/* Get temp filename */
|
||||
GetTempPathW(sizeof(temp_path)/sizeof(WCHAR), temp_path);
|
||||
GetTempFileNameW(temp_path, cmdW, 0, temp_file);
|
||||
|
||||
/* Execute program and redirect output */
|
||||
wsprintfW(temp_cmd, redirOut, (itemStart+1), temp_file);
|
||||
WCMD_execute (itemStart, temp_cmd, NULL, NULL, NULL);
|
||||
|
||||
/* Open the file, read line by line and process */
|
||||
input = CreateFileW(temp_file, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
} else {
|
||||
|
||||
/* Open the file, read line by line and process */
|
||||
input = CreateFileW(item, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
|
||||
/* Process the input file */
|
||||
if (input == INVALID_HANDLE_VALUE) {
|
||||
WCMD_print_error ();
|
||||
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), item);
|
||||
errorlevel = 1;
|
||||
return; /* FOR loop aborts at first failure here */
|
||||
|
||||
} else {
|
||||
|
||||
WCHAR buffer[MAXSTRING];
|
||||
WCHAR *where, *parm;
|
||||
|
||||
while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
|
||||
|
||||
/* Skip blank lines*/
|
||||
parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
|
||||
WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
|
||||
wine_dbgstr_w(buffer));
|
||||
|
||||
if (where) {
|
||||
/* FIXME: The following should be moved into its own routine and
|
||||
reused for the string literal parsing below */
|
||||
thisCmdStart = cmdStart;
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, parm, FALSE, TRUE);
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
buffer[0] = 0;
|
||||
|
||||
}
|
||||
CloseHandle (input);
|
||||
}
|
||||
|
||||
/* Delete the temporary file */
|
||||
if (*itemStart == '`' || *itemStart == '\'') {
|
||||
DeleteFileW(temp_file);
|
||||
}
|
||||
|
||||
/* Filesets - A string literal */
|
||||
} else if (doFileset && *itemStart == '"') {
|
||||
WCHAR buffer[MAXSTRING];
|
||||
WCHAR *where, *parm;
|
||||
|
||||
/* Skip blank lines, and re-extract parameter now string has quotes removed */
|
||||
strcpyW(buffer, item);
|
||||
parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
|
||||
WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
|
||||
wine_dbgstr_w(buffer));
|
||||
|
||||
if (where) {
|
||||
/* FIXME: The following should be moved into its own routine and
|
||||
reused for the string literal parsing below */
|
||||
thisCmdStart = cmdStart;
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, parm, FALSE, TRUE);
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
}
|
||||
|
||||
WINE_TRACE("Post-command, cmdEnd = %p\n", cmdEnd);
|
||||
i++;
|
||||
}
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
/* Move onto the next set line */
|
||||
thisSet = thisSet->nextcommand;
|
||||
}
|
||||
|
||||
/* If /L is provided, now run the for loop */
|
||||
if (useNumbers) {
|
||||
WCHAR thisNum[20];
|
||||
static const WCHAR fmt[] = {'%','d','\0'};
|
||||
|
||||
WINE_TRACE("FOR /L provided range from %d to %d step %d\n",
|
||||
numbers[0], numbers[2], numbers[1]);
|
||||
for (i=numbers[0];
|
||||
(numbers[1]<0)? i>=numbers[2] : i<=numbers[2];
|
||||
i=i + numbers[1]) {
|
||||
|
||||
sprintfW(thisNum, fmt, i);
|
||||
WINE_TRACE("Processing FOR number %s\n", wine_dbgstr_w(thisNum));
|
||||
|
||||
thisCmdStart = cmdStart;
|
||||
doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, thisNum, FALSE, TRUE);
|
||||
}
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
/* If we are walking directories, move on to any which remain */
|
||||
if (dirsToWalk != NULL) {
|
||||
DIRECTORY_STACK *nextDir = dirsToWalk->next;
|
||||
HeapFree(GetProcessHeap(), 0, dirsToWalk->dirName);
|
||||
HeapFree(GetProcessHeap(), 0, dirsToWalk);
|
||||
dirsToWalk = nextDir;
|
||||
if (dirsToWalk) WINE_TRACE("Moving to next directorty 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
|
||||
|
|
|
@ -726,6 +726,129 @@ rem del tmp
|
|||
rem for /d %%i in (*) do echo %%i>> tmp
|
||||
rem sort < tmp
|
||||
rem del tmp
|
||||
echo > baz\bazbaz
|
||||
goto :TestForR
|
||||
|
||||
:SetExpected
|
||||
del temp.bat 2>nul
|
||||
call :WriteLine set found=N
|
||||
for /l %%i in (1,1,%expectedresults%) do (
|
||||
call :WriteLine if "%%%%expectedresults.%%i%%%%"=="%%%%1" set found=Y
|
||||
call :WriteLine if "%%%%found%%%%"=="Y" set expectedresults.%%i=
|
||||
call :WriteLine if "%%%%found%%%%"=="Y" goto :eof
|
||||
)
|
||||
call :WriteLine echo Got unexpected result: "%%%%1"
|
||||
goto :eof
|
||||
|
||||
:WriteLine
|
||||
echo %*>> temp.bat
|
||||
goto :EOF
|
||||
|
||||
:ValidateExpected
|
||||
del temp.bat 2>nul
|
||||
for /l %%i in (1,1,%expectedresults%) do call :WriteLine if not "%%%%expectedresults.%%i%%%%"=="" echo Found missing result: "%%%%expectedresults.%%i%%%%"
|
||||
call temp.bat
|
||||
del temp.bat 2>nul
|
||||
goto :eof
|
||||
|
||||
:TestForR
|
||||
rem %CD% does not tork on NT4 so use the following workaround
|
||||
for /d %%i in (.) do set CURDIR=%%~dpnxi
|
||||
|
||||
echo --- for /R
|
||||
echo Plain directory enumeration
|
||||
set expectedresults=4
|
||||
set expectedresults.1=%CURDIR%\.
|
||||
set expectedresults.2=%CURDIR%\bar\.
|
||||
set expectedresults.3=%CURDIR%\baz\.
|
||||
set expectedresults.4=%CURDIR%\foo\.
|
||||
call :SetExpected
|
||||
for /R %%i in (.) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
|
||||
echo Plain directory enumeration from provided root
|
||||
set expectedresults=4
|
||||
set expectedresults.1=%CURDIR%\.
|
||||
set expectedresults.2=%CURDIR%\bar\.
|
||||
set expectedresults.3=%CURDIR%\baz\.
|
||||
set expectedresults.4=%CURDIR%\foo\.
|
||||
if "%CD%"=="" goto :SkipBrokenNT4
|
||||
call :SetExpected
|
||||
for /R "%CURDIR%" %%i in (.) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
:SkipBrokenNT4
|
||||
|
||||
echo File enumeration
|
||||
set expectedresults=2
|
||||
set expectedresults.1=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.2=%CURDIR%\bazbaz
|
||||
call :SetExpected
|
||||
for /R %%i in (baz*) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
|
||||
echo File enumeration from provided root
|
||||
set expectedresults=2
|
||||
set expectedresults.1=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.2=%CURDIR%\bazbaz
|
||||
call :SetExpected
|
||||
for /R %%i in (baz*) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
|
||||
echo Mixed enumeration
|
||||
set expectedresults=6
|
||||
set expectedresults.1=%CURDIR%\.
|
||||
set expectedresults.2=%CURDIR%\bar\.
|
||||
set expectedresults.3=%CURDIR%\baz\.
|
||||
set expectedresults.4=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.5=%CURDIR%\bazbaz
|
||||
set expectedresults.6=%CURDIR%\foo\.
|
||||
call :SetExpected
|
||||
for /R %%i in (. baz*) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
|
||||
echo Mixed enumeration from provided root
|
||||
set expectedresults=6
|
||||
set expectedresults.1=%CURDIR%\.
|
||||
set expectedresults.2=%CURDIR%\bar\.
|
||||
set expectedresults.3=%CURDIR%\baz\.
|
||||
set expectedresults.4=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.5=%CURDIR%\bazbaz
|
||||
set expectedresults.6=%CURDIR%\foo\.
|
||||
call :SetExpected
|
||||
for /R %%i in (. baz*) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
|
||||
echo With duplicates enumeration
|
||||
set expectedresults=12
|
||||
set expectedresults.1=%CURDIR%\bar\bazbaz
|
||||
set expectedresults.2=%CURDIR%\bar\fred
|
||||
set expectedresults.3=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.4=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.5=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.6=%CURDIR%\baz\fred
|
||||
set expectedresults.7=%CURDIR%\bazbaz
|
||||
set expectedresults.8=%CURDIR%\bazbaz
|
||||
set expectedresults.9=%CURDIR%\bazbaz
|
||||
set expectedresults.10=%CURDIR%\foo\bazbaz
|
||||
set expectedresults.11=%CURDIR%\foo\fred
|
||||
set expectedresults.12=%CURDIR%\fred
|
||||
call :SetExpected
|
||||
for /R %%i in (baz* bazbaz fred ba*) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
|
||||
echo Strip missing wildcards, keep unwildcarded names
|
||||
set expectedresults=6
|
||||
set expectedresults.1=%CURDIR%\bar\jim
|
||||
set expectedresults.2=%CURDIR%\baz\bazbaz
|
||||
set expectedresults.3=%CURDIR%\baz\jim
|
||||
set expectedresults.4=%CURDIR%\bazbaz
|
||||
set expectedresults.5=%CURDIR%\foo\jim
|
||||
set expectedresults.6=%CURDIR%\jim
|
||||
call :SetExpected
|
||||
for /R %%i in (baz* fred* jim) do call temp.bat %%i
|
||||
call :ValidateExpected
|
||||
|
||||
echo for /R passed
|
||||
cd .. & rd /s/Q foobar
|
||||
echo --- for /L
|
||||
rem Some cases loop forever writing 0s, like e.g. (1,0,1), (1,a,3) or (a,b,c); those can't be tested here
|
||||
|
|
|
@ -495,6 +495,16 @@ bar@space@
|
|||
PASSED
|
||||
xxx - Should be xxx
|
||||
Expected second line
|
||||
--- for /R
|
||||
Plain directory enumeration
|
||||
Plain directory enumeration from provided root
|
||||
File enumeration
|
||||
File enumeration from provided root
|
||||
Mixed enumeration
|
||||
Mixed enumeration from provided root
|
||||
With duplicates enumeration
|
||||
Strip missing wildcards, keep unwildcarded names
|
||||
for /R passed
|
||||
--- for /L
|
||||
1
|
||||
3
|
||||
|
|
Loading…
Reference in New Issue