From 345cb891752d6f594c488a371f702b013a6e7aca Mon Sep 17 00:00:00 2001 From: Jason Edmeades Date: Fri, 15 Jun 2007 20:59:26 +0100 Subject: [PATCH] cmd.exe: Correctly parse IF ELSE plus multipart/multiline. --- programs/cmd/wcmdmain.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 5ccd6d81c9f..a9beb61a95a 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)); -- 2.11.4.GIT