Module: wine
Branch: master
Commit: 51b0d941d0b9c9dc60ecbcc99ed0eacae4329e85
URL: http://source.winehq.org/git/wine.git/?a=commit;h=51b0d941d0b9c9dc60ecbcc99…
Author: Jason Edmeades <jason(a)edmeades.me.uk>
Date: Tue Oct 23 22:05:06 2012 +0100
cmd: Add for /f delims= support.
---
programs/cmd/batch.c | 29 ++++++++++++++++++++++-------
programs/cmd/builtins.c | 13 +++++++------
programs/cmd/tests/test_builtins.cmd.exp | 12 ++++++------
programs/cmd/wcmd.h | 2 ++
4 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 1c0bc24..7b037d7 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -121,9 +121,10 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
}
/*******************************************************************
- * WCMD_parameter
+ * WCMD_parameter_with_delims
*
- * Extracts a delimited parameter from an input string
+ * Extracts a delimited parameter from an input string, providing
+ * the delimiters characters to use
*
* PARAMS
* s [I] input string, non NULL
@@ -135,6 +136,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
* wholecmdline [I] True to indicate this routine is being used to parse the
* command line, and special logic for arg0->1 transition
* needs to be applied.
+ * delims[I] The delimiter characters to use
*
* RETURNS
* Success: The nth delimited parameter found in s
@@ -150,10 +152,9 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
* other API calls, e.g. c:\"a b"\c is returned as c:\a b\c. However, some commands
* need to preserve the exact syntax (echo, for, etc) hence the raw option.
*/
-WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
- BOOL wholecmdline)
+WCHAR *WCMD_parameter_with_delims (WCHAR *s, int n, WCHAR **start, WCHAR **end,
+ BOOL raw, BOOL wholecmdline, const WCHAR *delims)
{
- static const WCHAR defaultDelims[] = { ' ', '\t', ',', '=', ';', '\0' };
int curParamNb = 0;
static WCHAR param[MAX_PATH];
WCHAR *p = s, *begin;
@@ -165,7 +166,7 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
while (TRUE) {
/* Absorb repeated word delimiters until we get to the next token (or the end!) */
- while (*p && (strchrW(defaultDelims, *p) != NULL))
+ while (*p && (strchrW(delims, *p) != NULL))
p++;
if (*p == '\0') return param;
@@ -179,7 +180,7 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
/* Loop character by character, but just need to special case quotes */
while (*p) {
/* Once we have found a delimiter, break */
- if (strchrW(defaultDelims, *p) != NULL) break;
+ if (strchrW(delims, *p) != NULL) break;
/* Very odd special case - Seems as if a ( acts as a delimiter which is
not swallowed but is effective only when it comes between the program
@@ -218,6 +219,20 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
}
}
+/*******************************************************************
+ * WCMD_parameter
+ *
+ * Extracts a delimited parameter from an input string, using a
+ * default set of delimiter characters. For parameters, see the main
+ * function above.
+ */
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
+ BOOL wholecmdline)
+{
+ static const WCHAR defaultDelims[] = { ' ', '\t', ',', '=', ';', '\0' };
+ return WCMD_parameter_with_delims (s, n, start, end, raw, wholecmdline, defaultDelims);
+}
+
/****************************************************************************
* WCMD_fgets
*
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 4bb4702..8eaa9e7 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1600,7 +1600,7 @@ static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
}
if (*pos==' ' && *(pos+1)==0) delims[i++] = *pos;
delims[i++] = 0; /* Null terminate the delims */
- WINE_FIXME("Found delims as '%s'\n", wine_dbgstr_w(delims));
+ WINE_TRACE("Found delims as '%s'\n", wine_dbgstr_w(delims));
/* Save the tokens being requested */
} else if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
@@ -1694,6 +1694,7 @@ static void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk) {
* 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
*/
static void WCMD_parse_line(CMD_LIST *cmdStart,
const WCHAR *firstCmd,
@@ -1702,7 +1703,8 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
WCHAR *buffer,
BOOL *doExecuted,
int *forf_skip,
- WCHAR forf_eol) {
+ WCHAR forf_eol,
+ WCHAR *forf_delims) {
WCHAR *parm, *where;
@@ -1713,7 +1715,7 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
}
/* Extract the parameter */
- parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE, FALSE);
+ parm = WCMD_parameter_with_delims(buffer, 0, &where, NULL, FALSE, FALSE, forf_delims);
WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
wine_dbgstr_w(buffer));
@@ -2070,7 +2072,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* Read line by line until end of file */
while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted,
- &forf_skip, forf_eol);
+ &forf_skip, forf_eol, forf_delims);
buffer[0] = 0;
}
CloseHandle (input);
@@ -2090,7 +2092,6 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
Note that the last quote is removed from the set and the string terminates
there to mimic windows */
WCHAR *strend = strrchrW(itemStart, forf_usebackq?'\'':'"');
-
if (strend) {
*strend = 0x00;
itemStart++;
@@ -2099,7 +2100,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* Copy the item away from the global buffer used by WCMD_parameter */
strcpyW(buffer, itemStart);
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted,
- &forf_skip, forf_eol);
+ &forf_skip, forf_eol, forf_delims);
/* Only one string can be supplied in the whole set, abort future set processing */
thisSet = NULL;
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index c15a58d..9b5eb3b 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -826,14 +826,14 @@ ad
z@y
a|d
no output
-@todo_wine@no output
+no output
------ delims option
-@todo_wine@a
-@todo_wine@a@space@
-@todo_wine@a d
a
-@todo_wine@C r
-@todo_wine@foo bar baz
+a@space@
+a d
+a
+C r
+foo bar baz
@todo_wine@c:\
------ skip option
c
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index d4d148f..26b89c6 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -108,6 +108,8 @@ static inline BOOL WCMD_is_console_handle(HANDLE h)
}
WCHAR *WCMD_fgets (WCHAR *buf, DWORD n, HANDLE stream);
WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw, BOOL wholecmdline);
+WCHAR *WCMD_parameter_with_delims (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
+ BOOL wholecmdline, const WCHAR *delims);
WCHAR *WCMD_skip_leading_spaces (WCHAR *string);
BOOL WCMD_keyword_ws_found(const WCHAR *keyword, int len, const WCHAR *ptr);
void WCMD_HandleTildaModifiers(WCHAR **start, const WCHAR *forVariable, const WCHAR *forValue, BOOL justFors);
Module: wine
Branch: master
Commit: 9171fd145438072d60effda0709b17ddb89437a4
URL: http://source.winehq.org/git/wine.git/?a=commit;h=9171fd145438072d60effda07…
Author: Jason Edmeades <jason(a)edmeades.me.uk>
Date: Mon Oct 22 22:22:28 2012 +0100
cmd: Add support for usebackq (for /f).
---
programs/cmd/batch.c | 1 +
programs/cmd/builtins.c | 108 ++++++++++++++++++++---------
programs/cmd/tests/test_builtins.cmd | 14 +++-
programs/cmd/tests/test_builtins.cmd.exp | 4 +
4 files changed, 90 insertions(+), 37 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 02d1fcf..1c0bc24 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -113,6 +113,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
HeapFree(GetProcessHeap(), 0, context->batchfileW);
LocalFree (context);
if ((prev_context != NULL) && (!called)) {
+ WINE_TRACE("Batch completed, but was not 'called' so skipping outer batch too\n");
prev_context -> skip_rest = TRUE;
context = prev_context;
}
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 6ecadac..6e252fe 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1583,7 +1583,7 @@ static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
usebackqW, sizeof(usebackqW)/sizeof(WCHAR)) == CSTR_EQUAL) {
*usebackq = TRUE;
pos = pos + sizeof(usebackqW)/sizeof(WCHAR);
- WINE_FIXME("Found usebackq\n");
+ 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
@@ -1727,6 +1727,67 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
}
/**************************************************************************
+ * WCMD_forf_getinputhandle
+ *
+ * Return a file handle 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.
+ */
+HANDLE WCMD_forf_getinputhandle(BOOL usebackq, WCHAR *itemstr, BOOL iscmd) {
+ WCHAR temp_str[MAX_PATH];
+ WCHAR temp_file[MAX_PATH];
+ WCHAR temp_cmd[MAXSTRING];
+ HANDLE hinput = INVALID_HANDLE_VALUE;
+ static const WCHAR redirOutW[] = {'>','%','s','\0'};
+ static const WCHAR cmdW[] = {'C','M','D','\0'};
+ static const WCHAR cmdslashcW[] = {'C','M','D','.','E','X','E',' ',
+ '/','C',' ','"','%','s','"','\0'};
+
+ /* Remove leading and trailing character */
+ if ((iscmd && (itemstr[0] == '`' && usebackq)) ||
+ (iscmd && (itemstr[0] == '\'' && !usebackq)) ||
+ (!iscmd && (itemstr[0] == '"' && usebackq)))
+ {
+ itemstr[strlenW(itemstr)-1] = 0x00;
+ itemstr++;
+ }
+
+ if (iscmd) {
+ /* Get temp filename */
+ GetTempPathW(sizeof(temp_str)/sizeof(WCHAR), temp_str);
+ GetTempFileNameW(temp_str, cmdW, 0, temp_file);
+
+ /* Redirect output to the temporary file */
+ wsprintfW(temp_str, redirOutW, temp_file);
+ wsprintfW(temp_cmd, cmdslashcW, itemstr);
+ WINE_TRACE("Issuing '%s' with redirs '%s'\n",
+ wine_dbgstr_w(temp_cmd), wine_dbgstr_w(temp_str));
+ WCMD_execute (temp_cmd, temp_str, NULL, NULL, NULL, FALSE);
+
+ /* Open the file, read line by line and process */
+ hinput = CreateFileW(temp_file, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+
+ } else {
+ /* Open the file, read line by line and process */
+ WINE_TRACE("Reading input to parse from '%s'\n", wine_dbgstr_w(itemstr));
+ hinput = CreateFileW(itemstr, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ }
+ return hinput;
+}
+
+/**************************************************************************
* WCMD_for
*
* Batch file loop processing.
@@ -1764,7 +1825,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
int forf_skip = 0;
WCHAR forf_delims[256];
WCHAR forf_tokens[MAXSTRING];
- BOOL forf_usebackq;
+ BOOL forf_usebackq = FALSE;
/* Handle optional qualifiers (multiple are allowed) */
WCHAR *thisArg = WCMD_parameter(p, parameterNo++, NULL, NULL, FALSE, FALSE);
@@ -1974,41 +2035,25 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* else ignore them! */
/* Filesets - either a list of files, or a command to run and parse the output */
- } else if (doFileset && *itemStart != '"') {
+ } else if (doFileset && ((!forf_usebackq && *itemStart != '"') ||
+ (forf_usebackq && *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;
+ if ((forf_usebackq && *itemStart == '`') ||
+ (!forf_usebackq && *itemStart == '\'')) {
- /* 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, FALSE);
-
- /* 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);
+ /* Use itemstart because the command is the whole set, not just the first token */
+ input = WCMD_forf_getinputhandle(forf_usebackq, itemStart, TRUE);
} 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);
+ /* Use item because the file to process is just the first item in the set */
+ input = WCMD_forf_getinputhandle(forf_usebackq, item, FALSE);
}
/* Process the input file */
@@ -2020,8 +2065,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
} else {
- WCHAR buffer[MAXSTRING];
-
+ /* Read line by line until end of file */
while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted,
&forf_skip, forf_eol);
@@ -2030,13 +2074,9 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
CloseHandle (input);
}
- /* Delete the temporary file */
- if (*itemStart == '`' || *itemStart == '\'') {
- DeleteFileW(temp_file);
- }
-
/* Filesets - A string literal */
- } else if (doFileset && *itemStart == '"') {
+ } else if (doFileset && ((!forf_usebackq && *itemStart == '"') ||
+ (forf_usebackq && *itemStart == '\''))) {
/* Copy the item away from the global buffer used by WCMD_parameter */
strcpyW(buffer, item);
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 11b5dbd..acd5a44 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -1147,9 +1147,17 @@ echo.>> bar
echo kkk>>bar
for /f %%k in (foo bar) do echo %%k
for /f %%k in (bar foo) do echo %%k
-rem echo ------ command argument
-rem Not implemented on NT4
-rem FIXME: Not testable right now in wine: not implemented and would need
+echo ------ command argument
+rem Not implemented on NT4, need to skip it as no way to get output otherwise
+if "%CD%"=="" goto :SkipFORFcmdNT4
+for /f %%i in ('echo.Passed1') do echo %%i
+for /f "usebackq" %%i in (`echo.Passed2`) do echo %%i
+for /f usebackq %%i in (`echo.Passed3`) do echo %%i
+goto :ContinueFORF
+:SkipFORFcmdNT4
+for /l %%i in (1,1,3) do echo Missing functionality - Broken%%i
+:ContinueFORF
+rem FIXME: Rest not testable right now in wine: not implemented and would need
rem preliminary grep-like program implementation (e.g. like findstr or fc) even
rem for a simple todo_wine test
rem (for /f "usebackq" %%i in (`echo z a b`) do echo %%i) || echo not supported
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 8980c1b..66820be 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -809,6 +809,10 @@ kkk
a
b
c
+------ command argument
+Passed1@or_broken@Missing functionality - Broken1
+Passed2@or_broken@Missing functionality - Broken2
+Passed3@or_broken@Missing functionality - Broken3
------ eol option
and@or_broken@Broken NT4 functionality1
Line@or_broken@Broken NT4 functionality2
Module: wine
Branch: master
Commit: 84ecf34c2c74dfff302dc198040629d74a29367d
URL: http://source.winehq.org/git/wine.git/?a=commit;h=84ecf34c2c74dfff302dc1980…
Author: Jason Edmeades <jason(a)edmeades.me.uk>
Date: Mon Oct 22 00:10:10 2012 +0100
cmd: Refactor building a list of directories out of WCMD_for.
---
programs/cmd/builtins.c | 89 ++++++++++++++++++++++++++++-------------------
1 files changed, 53 insertions(+), 36 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 7bafd9e..f706dff 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1624,6 +1624,58 @@ static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
return TRUE;
}
+/*****************************************************************************
+ * WCMD_add_dirstowalk
+ *
+ * When recursing through directories (for /r), we need to add to the list of
+ * directories still to walk, any subdirectories of the one we are processing.
+ *
+ * Parameters
+ * options [I] The remaining list of directories still to process
+ *
+ * Note this routine inserts the subdirectories found between the entry being
+ * processed, and any other directory still to be processed, mimicing what
+ * Windows does
+ */
+static void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk) {
+ DIRECTORY_STACK *remainingDirs = dirsToWalk;
+ WCHAR fullitem[MAX_PATH];
+ WIN32_FIND_DATAW fd;
+ HANDLE hff;
+
+ /* 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);
+ }
+}
+
/**************************************************************************
* WCMD_for
*
@@ -1779,7 +1831,6 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* 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];
/* Save away the starting position for the commands (and offset for the
first one) */
@@ -1789,41 +1840,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* 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;
-
- /* 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);
- }
- }
+ if (dirsToWalk) WCMD_add_dirstowalk(dirsToWalk);
thisSet = setStart;
/* Loop through all set entries */