cmd: Fix handling of redundant information on goto/labels.

This commit is contained in:
Jason Edmeades 2013-06-02 00:17:30 +01:00 committed by Alexandre Julliard
parent f3eb64ec73
commit dc4dd0cb97
4 changed files with 99 additions and 22 deletions

View file

@ -2501,7 +2501,8 @@ void WCMD_give_help (const WCHAR *args)
void WCMD_goto (CMD_LIST **cmdList) { void WCMD_goto (CMD_LIST **cmdList) {
WCHAR string[MAX_PATH]; WCHAR string[MAX_PATH];
WCHAR current[MAX_PATH]; WCHAR *labelend = NULL;
const WCHAR labelEndsW[] = {'>','<','|','&',' ',':','\t','\0'};
/* Do not process any more parts of a processed multipart or multilines command */ /* Do not process any more parts of a processed multipart or multilines command */
if (cmdList) *cmdList = NULL; if (cmdList) *cmdList = NULL;
@ -2521,25 +2522,38 @@ void WCMD_goto (CMD_LIST **cmdList) {
return; return;
} }
/* Support goto :label as well as goto label */ /* Support goto :label as well as goto label plus remove trailing chars */
if (*paramStart == ':') paramStart++; if (*paramStart == ':') paramStart++;
labelend = strpbrkW(paramStart, labelEndsW);
if (labelend) *labelend = 0x00;
WINE_TRACE("goto label: '%s'\n", wine_dbgstr_w(paramStart));
SetFilePointer (context -> h, 0, NULL, FILE_BEGIN); SetFilePointer (context -> h, 0, NULL, FILE_BEGIN);
while (WCMD_fgets (string, sizeof(string)/sizeof(WCHAR), context -> h)) { while (*paramStart &&
WCMD_fgets (string, sizeof(string)/sizeof(WCHAR), context -> h)) {
str = string; str = string;
while (isspaceW (*str)) str++;
if (*str == ':') {
DWORD index = 0;
str++;
while (((current[index] = str[index])) && (!isspaceW (current[index])))
index++;
/* ignore space at the end */ /* Ignore leading whitespace or no-echo character */
current[index] = 0; while (*str=='@' || isspaceW (*str)) str++;
if (lstrcmpiW (current, paramStart) == 0) return;
/* If the first real character is a : then this is a label */
if (*str == ':') {
str++;
/* Skip spaces between : and label */
while (isspaceW (*str)) str++;
WINE_TRACE("str before brk %s\n", wine_dbgstr_w(str));
/* Label ends at whitespace or redirection characters */
labelend = strpbrkW(str, labelEndsW);
if (labelend) *labelend = 0x00;
WINE_TRACE("comparing found label %s\n", wine_dbgstr_w(str));
if (lstrcmpiW (str, paramStart) == 0) return;
} }
} }
WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOTARGET)); WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOTARGET));
context -> skip_rest = TRUE;
} }
return; return;
} }

View file

@ -2538,17 +2538,72 @@ echo %ErrorLevel% should still be 7
echo ------------ Testing GOTO ------------ echo ------------ Testing GOTO ------------
if a==a goto dest1 if a==a goto dest1
echo FAILURE at dest 1
:dest1 :dest1
echo goto with no leading space worked echo goto with no leading space worked
if a==a goto :dest1b
echo FAILURE at dest 1b
:dest1b
echo goto with colon and no leading space worked
if b==b goto dest2 if b==b goto dest2
echo FAILURE at dest 2
:dest2 :dest2
echo goto with a leading space worked echo goto with a leading space worked
if c==c goto dest3 if c==c goto dest3
echo FAILURE at dest 3
:dest3 :dest3
echo goto with a leading tab worked echo goto with a leading tab worked
if d==d goto dest4 if d==d goto dest4
echo FAILURE at dest 4
:dest4@space@ :dest4@space@
echo goto with a following space worked echo goto with a following space worked
if e==e goto dest5
echo FAILURE at dest 5
:dest5&& echo FAILURE
echo goto with following amphersands worked
del failure.txt >nul 2>&1
if f==f goto dest6
echo FAILURE at dest 6
:dest6>FAILURE.TXT
if exist FAILURE.TXT echo FAILURE at dest 6 as file exists
echo goto with redirections worked
del FAILURE.TXT >nul 2>&1
:: some text that is ignored | dir >cmd_output | another test
if exist cmd_output echo FAILURE at dest 6 as file exists
echo Ignoring double colons worked
del cmd_output >nul 2>&1
rem goto a label which does not exist issues an error message and
rem acts the same as goto :EOF, and ensure ::label is never matched
del testgoto.bat >nul 2>&1
echo goto :dest7 ^>nul 2^>^&1 >> testgoto.bat
echo echo FAILURE at dest 7 - Should have not found label and issued an error plus ended the batch>> testgoto.bat
echo ::dest7>> testgoto.bat
echo echo FAILURE at dest 7 - Incorrectly went to label >> testgoto.bat
call testgoto.bat
del testgoto.bat >nul 2>&1
del testgoto.bat >nul 2>&1
echo goto ::dest8 ^>nul 2^>^&1 >> testgoto.bat
echo echo FAILURE at dest 8 - Should have not found label and issued an error plus ended the batch>> testgoto.bat
echo ::dest8>> testgoto.bat
echo echo FAILURE at dest 8 - Incorrectly went to label >> testgoto.bat
call testgoto.bat
del testgoto.bat >nul 2>&1
if g==g goto dest9
echo FAILURE at dest 9
:dest91
echo FAILURE at dest 91
@ : dest9>rubbish
echo label with mixed whitespace and no echo worked
if h==h goto :dest10:this is ignored
echo FAILURE at dest 10
:dest10:this is also ignored
echo Correctly ignored trailing information
echo ------------ Testing PATH ------------ echo ------------ Testing PATH ------------
set WINE_backup_path=%path% set WINE_backup_path=%path%

View file

@ -1294,9 +1294,15 @@ errorlevel zero, good@or_broken@errorlevel nonzero, bad
7 should still be 7 7 should still be 7
------------ Testing GOTO ------------ ------------ Testing GOTO ------------
goto with no leading space worked goto with no leading space worked
goto with colon and no leading space worked
goto with a leading space worked goto with a leading space worked
goto with a leading tab worked goto with a leading tab worked
goto with a following space worked goto with a following space worked
goto with following amphersands worked
goto with redirections worked
Ignoring double colons worked
label with mixed whitespace and no echo worked
Correctly ignored trailing information
------------ Testing PATH ------------ ------------ Testing PATH ------------
PATH=original PATH=original
PATH=try2 PATH=try2

View file

@ -1813,7 +1813,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
static const WCHAR forCmd[] = {'f','o','r'}; static const WCHAR forCmd[] = {'f','o','r'};
static const WCHAR ifCmd[] = {'i','f'}; static const WCHAR ifCmd[] = {'i','f'};
static const WCHAR ifElse[] = {'e','l','s','e'}; static const WCHAR ifElse[] = {'e','l','s','e'};
BOOL inRem = FALSE; BOOL inOneLine = FALSE;
BOOL inFor = FALSE; BOOL inFor = FALSE;
BOOL inIn = FALSE; BOOL inIn = FALSE;
BOOL inIf = FALSE; BOOL inIf = FALSE;
@ -1910,9 +1910,10 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
if (curStringLen == 0 && curCopyTo == curString) { if (curStringLen == 0 && curCopyTo == curString) {
static const WCHAR forDO[] = {'d','o'}; static const WCHAR forDO[] = {'d','o'};
/* If command starts with 'rem ', ignore any &&, ( etc. */ /* If command starts with 'rem ' or identifies a label, ignore any &&, ( etc. */
if (WCMD_keyword_ws_found(remCmd, sizeof(remCmd)/sizeof(remCmd[0]), curPos)) { if (WCMD_keyword_ws_found(remCmd, sizeof(remCmd)/sizeof(remCmd[0]), curPos) ||
inRem = TRUE; *curPos == ':') {
inOneLine = TRUE;
} else if (WCMD_keyword_ws_found(forCmd, sizeof(forCmd)/sizeof(forCmd[0]), curPos)) { } else if (WCMD_keyword_ws_found(forCmd, sizeof(forCmd)/sizeof(forCmd[0]), curPos)) {
inFor = TRUE; inFor = TRUE;
@ -1971,11 +1972,12 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
} }
} }
/* Nothing 'ends' a REM statement and &&, quotes etc are ineffective, /* Nothing 'ends' a one line statement (e.g. REM or :labels mean
so just use the default processing ie skip character specific the &&, quotes and redirection etc are ineffective, so just force
matching below */ the use of the default processing by skipping character specific
if (!inRem) thisChar = *curPos; matching below) */
else thisChar = 'X'; /* Character with no special processing */ if (!inOneLine) thisChar = *curPos;
else thisChar = 'X'; /* Character with no special processing */
lastWasWhiteSpace = FALSE; /* Will be reset below */ lastWasWhiteSpace = FALSE; /* Will be reset below */
lastWasCaret = FALSE; lastWasCaret = FALSE;
@ -2225,7 +2227,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
WCHAR *extraData; WCHAR *extraData;
WINE_TRACE("Need to read more data as outstanding brackets or carets\n"); WINE_TRACE("Need to read more data as outstanding brackets or carets\n");
inRem = FALSE; inOneLine = FALSE;
prevDelim = CMD_NONE; prevDelim = CMD_NONE;
inQuotes = 0; inQuotes = 0;
memset(extraSpace, 0x00, (MAXSTRING+1) * sizeof(WCHAR)); memset(extraSpace, 0x00, (MAXSTRING+1) * sizeof(WCHAR));