[PATCH 11/12] CMD.exe: Fix FOR so it works as 'well' as before
Jason Edmeades
jason.edmeades at googlemail.com
Thu Jun 14 17:06:47 CDT 2007
After this patch almost all my testcases (see 0th patch) work, except
one, which is certainly good enough to submit. This resolves a number
of issues, and makes the IF and FOR processing of the multipart/multiline
commands into a single function
---
programs/cmd/batch.c | 20 +---
programs/cmd/builtins.c | 339 ++++++++++++++++++++++++++++++-----------------
programs/cmd/wcmd.h | 9 +-
programs/cmd/wcmdmain.c | 61 ++++++---
4 files changed, 272 insertions(+), 157 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 0990b7e..8f0187c 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -109,7 +109,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, int called, WCHAR *startLabel, HAN
CMD_LIST *toExecute = NULL; /* Commands left to be executed */
if (WCMD_ReadAndParseLine(NULL, &toExecute, h) == NULL)
break;
- WCMD_process_commands(toExecute, FALSE);
+ WCMD_process_commands(toExecute, FALSE, NULL, NULL);
WCMD_free_commands(toExecute);
toExecute = NULL;
}
@@ -168,21 +168,9 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) {
i++;
p = param;
break;
- case '(':
- if (where != NULL && i==n) *where = s;
- s++;
- while ((*s != '\0') && (*s != ')')) {
- *p++ = *s++;
- }
- if (i == n) {
- *p = '\0';
- return param;
- }
- if (*s == ')') s++;
- param[0] = '\0';
- i++;
- p = param;
- break;
+ /* The code to handle bracketed parms is removed because it should no longer
+ be necessary after the multiline support has been added and the for loop
+ set of data is now parseable individually. */
case '\0':
return param;
default:
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 0f10d05..add4cce 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -40,7 +40,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
-void WCMD_execute (WCHAR *orig_command, WCHAR *parameter, WCHAR *substitution, CMD_LIST **cmdList);
+static void WCMD_part_execute(CMD_LIST **commands, WCHAR *firstcmd, WCHAR *variable,
+ WCHAR *value, BOOL isIF, BOOL conditionTRUE);
struct env_stack *saved_environment;
struct env_stack *pushd_directories;
@@ -571,6 +572,12 @@ void WCMD_echo (const WCHAR *command) {
* WCMD_for
*
* Batch file loop processing.
+ *
+ * On entry: cmdList contains the syntax up to the set
+ * next cmdList and all in that bracket contain the set data
+ * next cmdlist contains the DO cmd
+ * following that is either brackets or && entries (as per if)
+ *
* FIXME: We don't exhaustively check syntax. Any command which works in MessDOS
* will probably work here, but the reverse is not necessarily the case...
*/
@@ -579,45 +586,211 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
WIN32_FIND_DATA fd;
HANDLE hff;
- WCHAR *cmd, *item;
- WCHAR set[MAX_PATH], param[MAX_PATH];
int i;
const WCHAR inW[] = {'i', 'n', '\0'};
- const WCHAR doW[] = {'d', 'o', '\0'};
-
+ const WCHAR doW[] = {'d', 'o', ' ','\0'};
+ CMD_LIST *setStart, *thisSet, *cmdStart, *cmdEnd;
+ WCHAR variable[4];
+ WCHAR *firstCmd;
+ int thisDepth;
+
+ /* Check:
+ the first line includes the % variable name as first parm
+ we have been provided with more parts to the command
+ and there is at least some set data
+ and IN as the one after that */
if (lstrcmpiW (WCMD_parameter (p, 1, NULL), inW)
- || lstrcmpiW (WCMD_parameter (p, 3, NULL), doW)
- || (param1[0] != '%')) {
+ || (*cmdList) == NULL
+ || (*cmdList)->nextcommand == NULL
+ || (param1[0] != '%')
+ || (strlenW(param1) > 3)) {
WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
return;
}
- lstrcpynW (set, WCMD_parameter (p, 2, NULL), sizeof(set)/sizeof(WCHAR));
- WCMD_parameter (p, 4, &cmd);
- strcpyW (param, param1);
-/*
- * If the parameter within the set has a wildcard then search for matching files
- * otherwise do a literal substitution.
- */
+ /* Save away where the set of data starts and the variable */
+ strcpyW(variable, param1);
+ thisDepth = (*cmdList)->bracketDepth;
+ *cmdList = (*cmdList)->nextcommand;
+ setStart = (*cmdList);
- i = 0;
- while (*(item = WCMD_parameter (set, i, NULL))) {
- static const WCHAR wildcards[] = {'*','?','\0'};
- if (strpbrkW (item, wildcards)) {
- hff = FindFirstFile (item, &fd);
- if (hff == INVALID_HANDLE_VALUE) {
- return;
+ /* Skip until the close bracket */
+ WINE_TRACE("Searching %p as the set\n", *cmdList);
+ while (*cmdList &&
+ (*cmdList)->command != NULL &&
+ (*cmdList)->bracketDepth > thisDepth) {
+ WINE_TRACE("Skipping %p which is part of the set\n", *cmdList);
+ *cmdList = (*cmdList)->nextcommand;
+ }
+
+ /* Skip the close bracket, if there is one */
+ if (*cmdList) *cmdList = (*cmdList)->nextcommand;
+
+ /* 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) ||
+ (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+ (*cmdList)->command, 3, doW, -1) != 2)) {
+ WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
+ 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 ' */
+
+ thisSet = setStart;
+ /* Loop through all set entries */
+ while (thisSet &&
+ thisSet->command != NULL &&
+ thisSet->bracketDepth >= thisDepth) {
+
+ /* Loop through all entries on the same line */
+ WCHAR *item;
+
+ WINE_TRACE("Processing for set %p\n", thisSet);
+ i = 0;
+ while (*(item = WCMD_parameter (thisSet->command, i, NULL))) {
+
+ /*
+ * If the parameter within the set has a wildcard then search for matching files
+ * otherwise do a literal substitution.
+ */
+ static const WCHAR wildcards[] = {'*','?','\0'};
+ CMD_LIST *thisCmdStart = cmdStart;
+
+ WINE_TRACE("Processing for item '%s'\n", wine_dbgstr_w(item));
+ if (strpbrkW (item, wildcards)) {
+ hff = FindFirstFile (item, &fd);
+ if (hff != INVALID_HANDLE_VALUE) {
+ do {
+ thisCmdStart = cmdStart;
+ WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName));
+ WCMD_part_execute (&thisCmdStart, firstCmd, variable,
+ fd.cFileName, FALSE, TRUE);
+
+ } while (FindNextFile(hff, &fd) != 0);
+ FindClose (hff);
+ }
+ } else {
+ WCMD_part_execute(&thisCmdStart, firstCmd, variable, item, FALSE, TRUE);
}
- do {
- WCMD_execute (cmd, param, fd.cFileName, cmdList);
- } while (FindNextFile(hff, &fd) != 0);
- FindClose (hff);
+
+ WINE_TRACE("Post-command, cmdEnd = %p\n", cmdEnd);
+ cmdEnd = thisCmdStart;
+ i++;
}
- else {
- WCMD_execute (cmd, param, item, cmdList);
+
+ /* Move onto the next set line */
+ thisSet = thisSet->nextcommand;
+ }
+
+ /* 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 && cmdEnd->command == NULL) *cmdList = cmdEnd->nextcommand;
+}
+
+
+/*****************************************************************************
+ * WCMD_part_execute
+ *
+ * Execute a command, and any && or bracketed follow on to the command. The
+ * first command to be executed may not be at the front of the
+ * commands->thiscommand string (eg. it may point after a DO or ELSE
+ * Returns TRUE if something like exit or goto has aborted all processing
+ */
+void WCMD_part_execute(CMD_LIST **cmdList, WCHAR *firstcmd, WCHAR *variable,
+ WCHAR *value, BOOL isIF, BOOL conditionTRUE) {
+
+ CMD_LIST *curPosition = *cmdList;
+ int myDepth = (*cmdList)->bracketDepth;
+
+ WINE_TRACE("cmdList(%p), firstCmd(%p), with '%s'='%s', doIt(%d)\n",
+ cmdList, wine_dbgstr_w(firstcmd),
+ wine_dbgstr_w(variable), wine_dbgstr_w(value),
+ conditionTRUE);
+
+ /* Skip leading whitespace between condition and the command */
+ while (firstcmd && *firstcmd && (*firstcmd==' ' || *firstcmd=='\t')) firstcmd++;
+
+ /* Process the first command, if there is one */
+ if (conditionTRUE && firstcmd && *firstcmd) {
+ WCHAR *command = WCMD_strdupW(firstcmd);
+ WCMD_execute (firstcmd, variable, value, cmdList);
+ free (command);
+ }
+
+
+ /* If it didnt move the position, step to next command */
+ if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
+
+ /* Process any other parts of the command */
+ if (*cmdList) {
+ BOOL processThese = TRUE;
+
+ if (isIF) processThese = conditionTRUE;
+
+ while (*cmdList) {
+ const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
+
+ /* execute all appropriate commands */
+ curPosition = *cmdList;
+
+ WINE_TRACE("Processing cmdList(%p) - &(%d) bd(%d / %d)\n",
+ *cmdList,
+ (*cmdList)->isAmphersand,
+ (*cmdList)->bracketDepth, myDepth);
+
+ /* Execute any appended to the statement with &&'s */
+ if ((*cmdList)->isAmphersand) {
+ if (processThese) {
+ WCMD_execute ((*cmdList)->command, variable, value, cmdList);
+ }
+ if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
+
+ /* Execute any appended to the statement with (...) */
+ } else if ((*cmdList)->bracketDepth > myDepth) {
+ if (processThese) {
+ *cmdList = WCMD_process_commands(*cmdList, TRUE, variable, value);
+ WINE_TRACE("Back from processing commands, (next = %p)\n", *cmdList);
+ }
+ if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
+
+ /* End of the command - does 'ELSE ' follow as the next command? */
+ } else {
+ if (isIF && CompareString (LOCALE_USER_DEFAULT,
+ NORM_IGNORECASE | SORT_STRINGSORT,
+ (*cmdList)->command, 5, ifElse, -1) == 2) {
+
+ /* Swap between if and else processing */
+ processThese = !processThese;
+
+ /* Process the ELSE part */
+ if (processThese) {
+ WCHAR *cmd = ((*cmdList)->command) + strlenW(ifElse);
+
+ /* Skip leading whitespace between condition and the command */
+ while (*cmd && (*cmd==' ' || *cmd=='\t')) cmd++;
+ if (*cmd) {
+ WCMD_execute (cmd, variable, value, cmdList);
+ }
+ }
+ if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
+ } else {
+ WINE_TRACE("Found end of this IF statement (next = %p)\n", *cmdList);
+ break;
+ }
+ }
}
- i++;
}
+ return;
}
/*****************************************************************************
@@ -631,22 +804,26 @@ void WCMD_execute (WCHAR *orig_cmd, WCHAR *param, WCHAR *subst, CMD_LIST **cmdLi
WCHAR *new_cmd, *p, *s, *dup;
int size;
- size = strlenW (orig_cmd);
- new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
- dup = s = WCMD_strdupW(orig_cmd);
-
- while ((p = strstrW (s, param))) {
- *p = '\0';
- size += strlenW (subst);
- new_cmd = (WCHAR *) LocalReAlloc ((HANDLE)new_cmd, size, 0);
+ if (param) {
+ size = (strlenW (orig_cmd) + 1) * sizeof(WCHAR);
+ new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
+ dup = s = WCMD_strdupW(orig_cmd);
+
+ while ((p = strstrW (s, param))) {
+ *p = '\0';
+ size += strlenW (subst) * sizeof(WCHAR);
+ new_cmd = (WCHAR *) LocalReAlloc ((HANDLE)new_cmd, size, 0);
+ strcatW (new_cmd, s);
+ strcatW (new_cmd, subst);
+ s = p + strlenW (param);
+ }
strcatW (new_cmd, s);
- strcatW (new_cmd, subst);
- s = p + strlenW (param);
+ WCMD_process_command (new_cmd, cmdList);
+ free (dup);
+ LocalFree ((HANDLE)new_cmd);
+ } else {
+ WCMD_process_command (orig_cmd, cmdList);
}
- strcatW (new_cmd, s);
- WCMD_process_command (new_cmd, cmdList);
- free (dup);
- LocalFree ((HANDLE)new_cmd);
}
@@ -810,8 +987,6 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
static const WCHAR existW[] = {'e','x','i','s','t','\0'};
static const WCHAR defdW[] = {'d','e','f','i','n','e','d','\0'};
static const WCHAR eqeqW[] = {'=','=','\0'};
- CMD_LIST *curPosition;
- int myDepth;
if (!lstrcmpiW (param1, notW)) {
negate = 1;
@@ -848,81 +1023,7 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
/* Process rest of IF statement which is on the same line
Note: This may process all or some of the cmdList (eg a GOTO) */
- curPosition = *cmdList;
- myDepth = (*cmdList)->bracketDepth;
-
- if (test != negate) {
- WCHAR *cmd = command;
-
- /* Skip leading whitespace between condition and the command */
- while (cmd && *cmd && (*cmd==' ' || *cmd=='\t')) cmd++;
-
- if (cmd && *cmd) {
- command = WCMD_strdupW(cmd);
- WCMD_process_command (command, cmdList);
- free (command);
- }
- }
-
- /* If it didnt move the position, step to next command */
- if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
-
- /* Process any other parts of the IF */
- if (*cmdList) {
- BOOL processThese = (test != negate);
-
- while (*cmdList) {
- const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
-
- /* execute all appropriate commands */
- curPosition = *cmdList;
-
- WINE_TRACE("Processing cmdList(%p) - &(%d) bd(%d / %d)\n",
- *cmdList,
- (*cmdList)->isAmphersand,
- (*cmdList)->bracketDepth, myDepth);
-
- /* Execute any appended to the statement with &&'s */
- if ((*cmdList)->isAmphersand) {
- if (processThese) {
- WCMD_process_command((*cmdList)->command, cmdList);
- }
- if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
-
- /* Execute any appended to the statement with (...) */
- } else if ((*cmdList)->bracketDepth > myDepth) {
- if (processThese) {
- *cmdList = WCMD_process_commands(*cmdList, TRUE);
- WINE_TRACE("Back from processing commands, (next = %p)\n", *cmdList);
- }
- if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
-
- /* End of the command - does 'ELSE ' follow as the next command? */
- } else {
- if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
- (*cmdList)->command, 5, ifElse, -1) == 2) {
-
- /* Swap between if and else processing */
- processThese = !processThese;
-
- /* Process the ELSE part */
- if (processThese) {
- WCHAR *cmd = ((*cmdList)->command) + strlenW(ifElse);
-
- /* Skip leading whitespace between condition and the command */
- while (*cmd && (*cmd==' ' || *cmd=='\t')) cmd++;
- if (*cmd) {
- WCMD_process_command(cmd, cmdList);
- }
- }
- if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
- } else {
- WINE_TRACE("Found end of this IF statement (next = %p)\n", *cmdList);
- break;
- }
- }
- }
- }
+ WCMD_part_execute(cmdList, command, NULL, NULL, TRUE, (test != negate));
}
/****************************************************************************
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index 90f0179..0781fb6 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -62,7 +62,7 @@ void WCMD_output (const WCHAR *format, ...);
void WCMD_output_asis (const WCHAR *message);
void WCMD_parse (WCHAR *s, WCHAR *q, WCHAR *p1, WCHAR *p2);
void WCMD_pause (void);
-void WCMD_pipe (CMD_LIST **command);
+void WCMD_pipe (CMD_LIST **command, WCHAR *var, WCHAR *val);
void WCMD_popd (void);
void WCMD_print_error (void);
void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList);
@@ -101,9 +101,10 @@ WCHAR *WCMD_strdupW(WCHAR *input);
BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars,
LPDWORD charsRead, const LPOVERLAPPED unused);
-WCHAR *WCMD_ReadAndParseLine(WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom);
-CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket);
-void WCMD_free_commands(CMD_LIST *cmds);
+WCHAR *WCMD_ReadAndParseLine(WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom);
+CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket, WCHAR *var, WCHAR *val);
+void WCMD_free_commands(CMD_LIST *cmds);
+void WCMD_execute (WCHAR *orig_command, WCHAR *parameter, WCHAR *substitution, CMD_LIST **cmdList);
/* Data structure to hold context when executing batch files */
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index 0a9c4d2..36b8612 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -324,7 +324,7 @@ int wmain (int argc, WCHAR *argvW[])
/* Parse the command string, without reading any more input */
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
- WCMD_process_commands(toExecute, FALSE);
+ WCMD_process_commands(toExecute, FALSE, NULL, NULL);
WCMD_free_commands(toExecute);
toExecute = NULL;
@@ -417,7 +417,7 @@ int wmain (int argc, WCHAR *argvW[])
if (opt_k) {
/* Parse the command string, without reading any more input */
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
- WCMD_process_commands(toExecute, FALSE);
+ WCMD_process_commands(toExecute, FALSE, NULL, NULL);
WCMD_free_commands(toExecute);
toExecute = NULL;
HeapFree(GetProcessHeap(), 0, cmd);
@@ -449,7 +449,7 @@ int wmain (int argc, WCHAR *argvW[])
if (WCMD_ReadAndParseLine(NULL, &toExecute,
GetStdHandle(STD_INPUT_HANDLE)) == NULL)
break;
- WCMD_process_commands(toExecute, FALSE);
+ WCMD_process_commands(toExecute, FALSE, NULL, NULL);
WCMD_free_commands(toExecute);
toExecute = NULL;
}
@@ -497,8 +497,12 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList)
while ((p = strchrW(p, '%'))) {
i = *(p+1) - '0';
+ /* Dont touch %% */
+ if (*(p+1) == '%') {
+ p+=2;
+
/* Replace %~ modifications if in batch program */
- if (context && *(p+1) == '~') {
+ } else if (context && *(p+1) == '~') {
WCMD_HandleTildaModifiers(&p, NULL);
p++;
@@ -531,13 +535,17 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList)
if (context) {
p = cmd;
while ((p = strchrW(p, '%'))) {
- s = strchrW(p+1, '%');
- if (!s) {
- *p=0x00;
+ if (*(p+1) == '%') {
+ p+=2;
} else {
- t = WCMD_strdupW(s+1);
- strcpyW(p, t);
- free(t);
+ s = strchrW(p+1, '%');
+ if (!s) {
+ *p=0x00;
+ } else {
+ t = WCMD_strdupW(s+1);
+ strcpyW(p, t);
+ free(t);
+ }
}
}
@@ -1487,7 +1495,7 @@ void WCMD_opt_s_strip_quotes(WCHAR *cmd) {
* Handle pipes within a command - the DOS way using temporary files.
*/
-void WCMD_pipe (CMD_LIST **cmdEntry) {
+void WCMD_pipe (CMD_LIST **cmdEntry, WCHAR *var, WCHAR *val) {
WCHAR *p;
WCHAR *command = (*cmdEntry)->command;
@@ -1503,19 +1511,19 @@ void WCMD_pipe (CMD_LIST **cmdEntry) {
p = strchrW(command, '|');
*p++ = '\0';
wsprintf (temp_cmd, redirOut, command, temp_file);
- WCMD_process_command (temp_cmd, cmdEntry);
+ WCMD_execute (temp_cmd, var, val, cmdEntry);
command = p;
while ((p = strchrW(command, '|'))) {
*p++ = '\0';
GetTempFileName (temp_path, cmdW, 0, temp_file2);
wsprintf (temp_cmd, redirBoth, command, temp_file, temp_file2);
- WCMD_process_command (temp_cmd, cmdEntry);
+ WCMD_execute (temp_cmd, var, val, cmdEntry);
DeleteFile (temp_file);
strcpyW (temp_file, temp_file2);
command = p;
}
wsprintf (temp_cmd, redirIn, command, temp_file);
- WCMD_process_command (temp_cmd, cmdEntry);
+ WCMD_execute (temp_cmd, var, val, cmdEntry);
DeleteFile (temp_file);
}
@@ -1913,6 +1921,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
BOOL inRem = FALSE;
BOOL inFor = FALSE;
+ BOOL inIn = FALSE;
BOOL inIf = FALSE;
BOOL inElse= FALSE;
BOOL onlyWhiteSpace = FALSE;
@@ -2057,11 +2066,15 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
onlyWhiteSpace,
inFor, lastWasIn, lastWasDo,
inIf, inElse, lastWasElse);
- if (curLen == 0) {
+
+ /* Ignore open brackets inside the for set */
+ if (curLen == 0 && !inIn) {
+ WINE_TRACE("@@@4\n");
curDepth++;
/* If in quotes, ignore brackets */
} else if (inQuotes) {
+ WINE_TRACE("@@@3\n");
curString[curLen++] = *curPos;
/* In a FOR loop, an unquoted '(' may occur straight after
@@ -2075,6 +2088,13 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
(inElse && lastWasElse && onlyWhiteSpace) ||
(inFor && (lastWasIn || lastWasDo) && onlyWhiteSpace)) {
+ WINE_TRACE("@@@2\n");
+ /* If entering into an 'IN', set inIn */
+ if (inFor && lastWasIn && onlyWhiteSpace) {
+ WINE_TRACE("Inside an IN\n");
+ inIn = TRUE;
+ }
+
/* Add the current command */
thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST));
thisEntry->command = HeapAlloc(GetProcessHeap(), 0,
@@ -2094,6 +2114,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
curDepth++;
} else {
+ WINE_TRACE("@@@1\n");
curString[curLen++] = *curPos;
}
break;
@@ -2159,6 +2180,9 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
*output = thisEntry;
}
lastEntry = thisEntry;
+
+ /* Leave inIn if necessary */
+ if (inIn) inIn = FALSE;
} else {
curString[curLen++] = *curPos;
}
@@ -2227,7 +2251,8 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
*
* Process all the commands read in so far
*/
-CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket) {
+CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket,
+ WCHAR *var, WCHAR *val) {
int bdepth = -1;
@@ -2255,9 +2280,9 @@ CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket) {
WINE_TRACE("Executing command: '%s'\n", wine_dbgstr_w(thisCmd->command));
if (strchrW(thisCmd->command,'|') != NULL) {
- WCMD_pipe (&thisCmd);
+ WCMD_pipe (&thisCmd, var, val);
} else {
- WCMD_process_command (thisCmd->command, &thisCmd);
+ WCMD_execute (thisCmd->command, var, val, &thisCmd);
}
}
--
1.5.0
More information about the wine-patches
mailing list