RESEND [PATCH 08/11] CMD.exe: Correctly parse IF ELSE plus
multipart/multiline
Jason Edmeades
jason.edmeades at googlemail.com
Fri Jun 15 14:59:26 CDT 2007
Note the handling of the multipart/multiline is wrong, but the
parsed output is almost correct. It fails to handle one silly case,
if an '(' outside of double quotes as part of the expression, but
it did not seem a case worth worrying about for now
---
programs/cmd/wcmdmain.c | 49 +++++++++++++++++++++++++++++++++++++++-------
1 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index 5ccd6d8..a9beb61 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -1909,12 +1909,17 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
static WCHAR *extraSpace = NULL; /* Deliberately never freed */
const WCHAR remCmd[] = {'r','e','m',' ','\0'};
const WCHAR forCmd[] = {'f','o','r',' ','\0'};
+ const WCHAR ifCmd[] = {'i','f',' ','\0'};
+ const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
BOOL inRem = FALSE;
BOOL inFor = FALSE;
+ BOOL inIf = FALSE;
+ BOOL inElse= FALSE;
BOOL onlyWhiteSpace = FALSE;
BOOL lastWasWhiteSpace = FALSE;
- BOOL lastWasDo = FALSE;
- BOOL lastWasIn = FALSE;
+ BOOL lastWasDo = FALSE;
+ BOOL lastWasIn = FALSE;
+ BOOL lastWasElse = FALSE;
/* Allocate working space for a command read from keyboard, file etc */
if (!extraSpace)
@@ -1952,7 +1957,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
/* Certain commands need special handling */
if (curLen == 0) {
- const WCHAR forDO[] = {'d','o',' ','\0'};
+ const WCHAR forDO[] = {'d','o',' ','\0'};
/* If command starts with 'rem', ignore any &&, ( etc */
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
@@ -1964,6 +1969,26 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
curPos, 4, forCmd, -1) == 2) {
inFor = TRUE;
+ /* If command starts with 'if' or 'else', handle ('s mid line. We should ensure this
+ is only true in the command portion of the IF statement, but this
+ should suffice for now
+ FIXME: Silly syntax like "if 1(==1( (
+ echo they equal
+ )" will be parsed wrong */
+ } else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+ curPos, 3, ifCmd, -1) == 2) {
+ inIf = TRUE;
+
+ } else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+ curPos, 5, ifElse, -1) == 2) {
+ inElse = TRUE;
+ lastWasElse = TRUE;
+ onlyWhiteSpace = TRUE;
+ memcpy(&curString[curLen], curPos, 5*sizeof(WCHAR));
+ curLen+=5;
+ curPos+=5;
+ continue;
+
/* In a for loop, the DO command will follow a close bracket followed by
whitespace, followed by DO, ie closeBracket inserts a NULL entry, curLen
is then 0, and all whitespace is skipped */
@@ -2025,10 +2050,12 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
ie start of line or just after &&, then we read until an
unquoted ) is found */
WINE_TRACE("Found '(' conditions: curLen(%d), inQ(%d), onlyWS(%d)"
- ", for(%d, In:%d, Do:%d)\n",
+ ", for(%d, In:%d, Do:%d)"
+ ", if(%d, else:%d, lwe:%d)\n",
curLen, inQuotes,
onlyWhiteSpace,
- inFor, lastWasIn, lastWasDo);
+ inFor, lastWasIn, lastWasDo,
+ inIf, inElse, lastWasElse);
if (curLen == 0) {
curDepth++;
@@ -2037,8 +2064,15 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
curString[curLen++] = *curPos;
/* In a FOR loop, an unquoted '(' may occur straight after
- IN or DO */
- } else if (inFor && (lastWasIn || lastWasDo) && onlyWhiteSpace) {
+ IN or DO
+ In an IF statement just handle it regardless as we don't
+ parse the operands
+ In an ELSE statement, only allow it straight away after
+ the ELSE and whitespace
+ */
+ } else if (inIf ||
+ (inElse && lastWasElse && onlyWhiteSpace) ||
+ (inFor && (lastWasIn || lastWasDo) && onlyWhiteSpace)) {
/* Add the current command */
thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST));
@@ -2166,7 +2200,6 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
/* If we have reached the end of the string, see if bracketing outstanding */
if (*curPos == 0x00 && curDepth > 0 && readFrom != INVALID_HANDLE_VALUE) {
inRem = FALSE;
- inFor = FALSE;
isAmphersand = FALSE;
inQuotes = FALSE;
memset(extraSpace, 0x00, (MAXSTRING+1) * sizeof(WCHAR));
--
1.5.0
More information about the wine-patches
mailing list