Module: wine Branch: master Commit: 345cb891752d6f594c488a371f702b013a6e7aca URL: http://source.winehq.org/git/wine.git/?a=commit;h=345cb891752d6f594c488a371f...
Author: Jason Edmeades jason.edmeades@googlemail.com Date: Fri Jun 15 20:59:26 2007 +0100
cmd.exe: Correctly parse IF ELSE plus multipart/multiline.
---
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));