Various fixes to the way cmd handles errorlevel and the "return values" of commands:

- Changed type of return values from BOOL to INT, with 0 indicating success and any other value indicating failure. If the left side of an || operator returns nonzero, errorlevel is set to that value.
- The return value of a batch file or FOR is the return value of the last command executed in it. An empty batch file returns 0, unless it was CALLed, in which case it returns errorlevel.
- CALL sets errorlevel to the return value of whatever was called.
- Running a GUI program doesn't change errorlevel, but always returns 0.
- CMD /C uses the command's return value, not errorlevel, as the process exit code.

svn path=/trunk/; revision=40474
This commit is contained in:
Jeffrey Morlan 2009-04-12 23:51:15 +00:00
parent 54f4f31dae
commit 8cf11060a9
7 changed files with 108 additions and 85 deletions

View file

@ -203,11 +203,12 @@ VOID ExitBatch()
* *
*/ */
BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd) INT Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd)
{ {
BATCH_CONTEXT new; BATCH_CONTEXT new;
LPFOR_CONTEXT saved_fc; LPFOR_CONTEXT saved_fc;
INT i; INT i;
INT ret = 0;
HANDLE hFile; HANDLE hFile;
SetLastError(0); SetLastError(0);
@ -221,7 +222,7 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
{ {
ConErrResPuts(STRING_BATCH_ERROR); ConErrResPuts(STRING_BATCH_ERROR);
return FALSE; return 1;
} }
if (bc != NULL && Cmd == bc->current) if (bc != NULL && Cmd == bc->current)
@ -238,10 +239,19 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd
else else
{ {
struct _SETLOCAL *setlocal = NULL; struct _SETLOCAL *setlocal = NULL;
/* If a batch file runs another batch file as part of a compound command
* (e.g. "x.bat & somethingelse") then the first file gets terminated. */ if (Cmd == NULL)
if (bc && Cmd != NULL)
{ {
/* This is a CALL. CALL will set errorlevel to our return value, so
* in order to keep the value of errorlevel unchanged in the case
* of calling an empty batch file, we must return that same value. */
ret = nErrorLevel;
}
else if (bc)
{
/* If a batch file runs another batch file as part of a compound command
* (e.g. "x.bat & somethingelse") then the first file gets terminated. */
/* Get its SETLOCAL stack so it can be migrated to the new context */ /* Get its SETLOCAL stack so it can be migrated to the new context */
setlocal = bc->setlocal; setlocal = bc->setlocal;
bc->setlocal = NULL; bc->setlocal = NULL;
@ -272,7 +282,7 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd
if (bc->raw_params == NULL) if (bc->raw_params == NULL)
{ {
error_out_of_memory(); error_out_of_memory();
return FALSE; return 1;
} }
/* Check if this is a "CALL :label" */ /* Check if this is a "CALL :label" */
@ -303,14 +313,14 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd
} }
bc->current = Cmd; bc->current = Cmd;
ExecuteCommand(Cmd); ret = ExecuteCommand(Cmd);
FreeCommand(Cmd); FreeCommand(Cmd);
} }
TRACE ("Batch: returns TRUE\n"); TRACE ("Batch: returns TRUE\n");
fc = saved_fc; fc = saved_fc;
return TRUE; return ret;
} }
VOID AddBatchRedirection(REDIRECTION **RedirList) VOID AddBatchRedirection(REDIRECTION **RedirList)

View file

@ -47,7 +47,7 @@ extern TCHAR textline[BATCH_BUFFSIZE]; /* Buffer for reading Batch file lines */
LPTSTR FindArg (TCHAR, BOOL *); LPTSTR FindArg (TCHAR, BOOL *);
LPTSTR BatchParams (LPTSTR, LPTSTR); LPTSTR BatchParams (LPTSTR, LPTSTR);
VOID ExitBatch (); VOID ExitBatch ();
BOOL Batch (LPTSTR, LPTSTR, LPTSTR, PARSED_COMMAND *); INT Batch (LPTSTR, LPTSTR, LPTSTR, PARSED_COMMAND *);
LPTSTR ReadBatchLine(); LPTSTR ReadBatchLine();
VOID AddBatchRedirection(REDIRECTION **); VOID AddBatchRedirection(REDIRECTION **);

View file

@ -73,10 +73,12 @@ INT cmd_call (LPTSTR param)
/* CALL :label - call a subroutine of the current batch file */ /* CALL :label - call a subroutine of the current batch file */
while (*param == _T(' ')) while (*param == _T(' '))
param++; param++;
return !Batch(bc->BatchFilePath, first, param, NULL); nErrorLevel = Batch(bc->BatchFilePath, first, param, NULL);
return nErrorLevel;
} }
return !DoCommand(first, param, NULL); nErrorLevel = DoCommand(first, param, NULL);
return nErrorLevel;
} }
/* EOF */ /* EOF */

View file

@ -308,7 +308,7 @@ HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
* Rest - rest of command line * Rest - rest of command line
*/ */
static BOOL static INT
Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd) Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
{ {
TCHAR szFullName[MAX_PATH]; TCHAR szFullName[MAX_PATH];
@ -363,7 +363,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
} }
if (!working) ConErrResPuts (STRING_FREE_ERROR1); if (!working) ConErrResPuts (STRING_FREE_ERROR1);
return working; return !working;
} }
/* get the PATH environment variable and parse it */ /* get the PATH environment variable and parse it */
@ -372,7 +372,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
if (!SearchForExecutable(First, szFullName)) if (!SearchForExecutable(First, szFullName))
{ {
error_bad_command(first); error_bad_command(first);
return FALSE; return 1;
} }
GetConsoleTitle (szWindowTitle, MAX_PATH); GetConsoleTitle (szWindowTitle, MAX_PATH);
@ -384,7 +384,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
while (*rest == _T(' ')) while (*rest == _T(' '))
rest++; rest++;
TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest)); TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
Batch (szFullName, first, rest, Cmd); dwExitCode = Batch(szFullName, first, rest, Cmd);
} }
else else
{ {
@ -448,17 +448,13 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
GetExitCodeProcess (prci.hProcess, &dwExitCode); GetExitCodeProcess (prci.hProcess, &dwExitCode);
nErrorLevel = (INT)dwExitCode; nErrorLevel = (INT)dwExitCode;
} }
else
{
nErrorLevel = 0;
}
CloseHandle (prci.hProcess); CloseHandle (prci.hProcess);
} }
else else
{ {
TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full)); TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
error_bad_command (first); error_bad_command (first);
nErrorLevel = 1; dwExitCode = 1;
} }
// restore console mode // restore console mode
@ -472,7 +468,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
OutputCodePage = GetConsoleOutputCP(); OutputCodePage = GetConsoleOutputCP();
SetConsoleTitle (szWindowTitle); SetConsoleTitle (szWindowTitle);
return nErrorLevel == 0; return dwExitCode;
} }
@ -485,7 +481,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
* rest - rest of command line * rest - rest of command line
*/ */
BOOL INT
DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd) DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
{ {
TCHAR com[_tcslen(first) + _tcslen(rest) + 2]; /* full command line */ TCHAR com[_tcslen(first) + _tcslen(rest) + 2]; /* full command line */
@ -530,7 +526,7 @@ DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
if (_tcsicmp(cmdptr->name, _T("echo")) != 0) if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
while (_istspace(*param)) while (_istspace(*param))
param++; param++;
return !cmdptr->func(param); return cmdptr->func(param);
} }
} }
@ -543,14 +539,16 @@ DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
* full input/output redirection and piping are supported * full input/output redirection and piping are supported
*/ */
VOID ParseCommandLine (LPTSTR cmd) INT ParseCommandLine (LPTSTR cmd)
{ {
INT Ret = 0;
PARSED_COMMAND *Cmd = ParseCommand(cmd); PARSED_COMMAND *Cmd = ParseCommand(cmd);
if (Cmd) if (Cmd)
{ {
ExecuteCommand(Cmd); Ret = ExecuteCommand(Cmd);
FreeCommand(Cmd); FreeCommand(Cmd);
} }
return Ret;
} }
/* Execute a command without waiting for it to finish. If it's an internal /* Execute a command without waiting for it to finish. If it's an internal
@ -679,27 +677,27 @@ failed:
#endif #endif
} }
BOOL INT
ExecuteCommand(PARSED_COMMAND *Cmd) ExecuteCommand(PARSED_COMMAND *Cmd)
{ {
PARSED_COMMAND *Sub; PARSED_COMMAND *Sub;
LPTSTR First, Rest; LPTSTR First, Rest;
BOOL Success = TRUE; INT Ret = 0;
if (!PerformRedirection(Cmd->Redirections)) if (!PerformRedirection(Cmd->Redirections))
return FALSE; return 1;
switch (Cmd->Type) switch (Cmd->Type)
{ {
case C_COMMAND: case C_COMMAND:
Success = FALSE; Ret = 1;
First = DoDelayedExpansion(Cmd->Command.First); First = DoDelayedExpansion(Cmd->Command.First);
if (First) if (First)
{ {
Rest = DoDelayedExpansion(Cmd->Command.Rest); Rest = DoDelayedExpansion(Cmd->Command.Rest);
if (Rest) if (Rest)
{ {
Success = DoCommand(First, Rest, Cmd); Ret = DoCommand(First, Rest, Cmd);
cmd_free(Rest); cmd_free(Rest);
} }
cmd_free(First); cmd_free(First);
@ -709,31 +707,36 @@ ExecuteCommand(PARSED_COMMAND *Cmd)
case C_BLOCK: case C_BLOCK:
case C_MULTI: case C_MULTI:
for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next) for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
Success = ExecuteCommand(Sub); Ret = ExecuteCommand(Sub);
break; break;
case C_IFFAILURE: case C_IFFAILURE:
Sub = Cmd->Subcommands;
Ret = ExecuteCommand(Sub);
if (Ret != 0)
{
nErrorLevel = Ret;
Ret = ExecuteCommand(Sub->Next);
}
break;
case C_IFSUCCESS: case C_IFSUCCESS:
Sub = Cmd->Subcommands; Sub = Cmd->Subcommands;
Success = ExecuteCommand(Sub); Ret = ExecuteCommand(Sub);
if (Success == (Cmd->Type - C_IFFAILURE)) if (Ret == 0)
{ Ret = ExecuteCommand(Sub->Next);
Sub = Sub->Next;
Success = ExecuteCommand(Sub);
}
break; break;
case C_PIPE: case C_PIPE:
ExecutePipeline(Cmd); ExecutePipeline(Cmd);
break; break;
case C_IF: case C_IF:
Success = ExecuteIf(Cmd); Ret = ExecuteIf(Cmd);
break; break;
case C_FOR: case C_FOR:
Success = ExecuteFor(Cmd); Ret = ExecuteFor(Cmd);
break; break;
} }
UndoRedirection(Cmd->Redirections, NULL); UndoRedirection(Cmd->Redirections, NULL);
return Success; return Ret;
} }
BOOL BOOL
@ -1402,7 +1405,7 @@ ReadLine (TCHAR *commandline, BOOL bMore)
return SubstituteVars(ip, commandline, _T('%')); return SubstituteVars(ip, commandline, _T('%'));
} }
static INT static VOID
ProcessInput() ProcessInput()
{ {
PARSED_COMMAND *Cmd; PARSED_COMMAND *Cmd;
@ -1416,8 +1419,6 @@ ProcessInput()
ExecuteCommand(Cmd); ExecuteCommand(Cmd);
FreeCommand(Cmd); FreeCommand(Cmd);
} }
return nErrorLevel;
} }
@ -1614,6 +1615,7 @@ Initialize()
TCHAR commandline[CMDLINE_LENGTH]; TCHAR commandline[CMDLINE_LENGTH];
TCHAR ModuleName[_MAX_PATH + 1]; TCHAR ModuleName[_MAX_PATH + 1];
TCHAR lpBuffer[2]; TCHAR lpBuffer[2];
INT nExitCode;
//INT len; //INT len;
TCHAR *ptr, *cmdLine, option = 0; TCHAR *ptr, *cmdLine, option = 0;
@ -1760,9 +1762,12 @@ Initialize()
{ {
/* Do the /C or /K command */ /* Do the /C or /K command */
GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip); GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
ParseCommandLine(commandline); nExitCode = ParseCommandLine(commandline);
if (option != _T('K')) if (option != _T('K'))
{
nErrorLevel = nExitCode;
bExit = TRUE; bExit = TRUE;
}
} }
} }
@ -1806,7 +1811,6 @@ int cmd_main (int argc, const TCHAR *argv[])
HANDLE hConsole; HANDLE hConsole;
TCHAR startPath[MAX_PATH]; TCHAR startPath[MAX_PATH];
CONSOLE_SCREEN_BUFFER_INFO Info; CONSOLE_SCREEN_BUFFER_INFO Info;
INT nExitCode;
lpOriginalEnvironment = DuplicateEnvironment(); lpOriginalEnvironment = DuplicateEnvironment();
@ -1839,15 +1843,15 @@ int cmd_main (int argc, const TCHAR *argv[])
Initialize(); Initialize();
/* call prompt routine */ /* call prompt routine */
nExitCode = ProcessInput(); ProcessInput();
/* do the cleanup */ /* do the cleanup */
Cleanup(); Cleanup();
cmd_free(lpOriginalEnvironment); cmd_free(lpOriginalEnvironment);
cmd_exit(nExitCode); cmd_exit(nErrorLevel);
return(nExitCode); return(nErrorLevel);
} }
/* EOF */ /* EOF */

View file

@ -102,16 +102,16 @@ INT cmd_cls (LPTSTR);
/* Prototypes for CMD.C */ /* Prototypes for CMD.C */
INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, INT len, BOOL bPutSeperator); INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, INT len, BOOL bPutSeperator);
HANDLE RunFile(DWORD, LPTSTR, LPTSTR, LPTSTR, INT); HANDLE RunFile(DWORD, LPTSTR, LPTSTR, LPTSTR, INT);
VOID ParseCommandLine (LPTSTR); INT ParseCommandLine(LPTSTR);
struct _PARSED_COMMAND; struct _PARSED_COMMAND;
BOOL ExecuteCommand(struct _PARSED_COMMAND *Cmd); INT ExecuteCommand(struct _PARSED_COMMAND *Cmd);
LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName ); LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName );
VOID AddBreakHandler (VOID); VOID AddBreakHandler (VOID);
VOID RemoveBreakHandler (VOID); VOID RemoveBreakHandler (VOID);
BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim); BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim);
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest); BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest);
LPTSTR DoDelayedExpansion(LPTSTR Line); LPTSTR DoDelayedExpansion(LPTSTR Line);
BOOL DoCommand(LPTSTR first, LPTSTR rest, struct _PARSED_COMMAND *Cmd); INT DoCommand(LPTSTR first, LPTSTR rest, struct _PARSED_COMMAND *Cmd);
BOOL ReadLine(TCHAR *commandline, BOOL bMore); BOOL ReadLine(TCHAR *commandline, BOOL bMore);
int cmd_main (int argc, const TCHAR *argv[]); int cmd_main (int argc, const TCHAR *argv[]);
@ -254,7 +254,7 @@ VOID CompleteFilename (LPTSTR, BOOL, LPTSTR, UINT);
#define FOR_LOOP 4 /* /L */ #define FOR_LOOP 4 /* /L */
#define FOR_RECURSIVE 8 /* /R */ #define FOR_RECURSIVE 8 /* /R */
INT cmd_for (LPTSTR); INT cmd_for (LPTSTR);
BOOL ExecuteFor(struct _PARSED_COMMAND *Cmd); INT ExecuteFor(struct _PARSED_COMMAND *Cmd);
/* Prototypes for FREE.C */ /* Prototypes for FREE.C */
@ -283,7 +283,7 @@ INT CommandHistory (LPTSTR param);
enum { IF_CMDEXTVERSION, IF_DEFINED, IF_ERRORLEVEL, IF_EXIST, enum { IF_CMDEXTVERSION, IF_DEFINED, IF_ERRORLEVEL, IF_EXIST,
IF_STRINGEQ, /* == */ IF_STRINGEQ, /* == */
IF_EQU, IF_GTR, IF_GEQ, IF_LSS, IF_LEQ, IF_NEQ }; IF_EQU, IF_GTR, IF_GEQ, IF_LSS, IF_LEQ, IF_NEQ };
BOOL ExecuteIf(struct _PARSED_COMMAND *Cmd); INT ExecuteIf(struct _PARSED_COMMAND *Cmd);
/* Prototypes for INTERNAL.C */ /* Prototypes for INTERNAL.C */

View file

@ -69,7 +69,7 @@ static BOOL GetNextElement(TCHAR **pStart, TCHAR **pEnd)
} }
/* Execute a single instance of a FOR command */ /* Execute a single instance of a FOR command */
static void RunInstance(PARSED_COMMAND *Cmd) static INT RunInstance(PARSED_COMMAND *Cmd)
{ {
if (bEcho && !bDisableBatchEcho && Cmd->Subcommands->Type != C_QUIET) if (bEcho && !bDisableBatchEcho && Cmd->Subcommands->Type != C_QUIET)
{ {
@ -80,7 +80,7 @@ static void RunInstance(PARSED_COMMAND *Cmd)
ConOutChar(_T('\n')); ConOutChar(_T('\n'));
} }
/* Just run the command (variable expansion is done in DoDelayedExpansion) */ /* Just run the command (variable expansion is done in DoDelayedExpansion) */
ExecuteCommand(Cmd->Subcommands); return ExecuteCommand(Cmd->Subcommands);
} }
/* Check if this FOR should be terminated early */ /* Check if this FOR should be terminated early */
@ -117,7 +117,7 @@ static LPTSTR ReadFileContents(FILE *InputFile, TCHAR *Buffer)
return Contents; return Contents;
} }
static BOOL ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer) static INT ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
{ {
LPTSTR Delims = _T(" \t"); LPTSTR Delims = _T(" \t");
TCHAR Eol = _T(';'); TCHAR Eol = _T(';');
@ -129,6 +129,7 @@ static BOOL ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
LPTSTR Variables[32]; LPTSTR Variables[32];
TCHAR *Start, *End; TCHAR *Start, *End;
INT i; INT i;
INT Ret = 0;
if (Cmd->For.Params) if (Cmd->For.Params)
{ {
@ -228,7 +229,7 @@ static BOOL ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
{ {
error: error:
error_syntax(Param); error_syntax(Param);
return FALSE; return 1;
} }
} }
} }
@ -270,7 +271,7 @@ static BOOL ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
if (!InputFile) if (!InputFile)
{ {
error_bad_command(Start + 1); error_bad_command(Start + 1);
return FALSE; return 1;
} }
FullInput = ReadFileContents(InputFile, Buffer); FullInput = ReadFileContents(InputFile, Buffer);
_pclose(InputFile); _pclose(InputFile);
@ -286,7 +287,7 @@ static BOOL ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
if (!InputFile) if (!InputFile)
{ {
error_sfile_not_found(Start); error_sfile_not_found(Start);
return FALSE; return 1;
} }
FullInput = ReadFileContents(InputFile, Buffer); FullInput = ReadFileContents(InputFile, Buffer);
fclose(InputFile); fclose(InputFile);
@ -295,7 +296,7 @@ static BOOL ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
if (!FullInput) if (!FullInput)
{ {
error_out_of_memory(); error_out_of_memory();
return FALSE; return 1;
} }
/* Loop over the input line by line */ /* Loop over the input line by line */
@ -337,20 +338,21 @@ static BOOL ForF(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
/* Don't run unless the line had enough tokens to fill at least one variable */ /* Don't run unless the line had enough tokens to fill at least one variable */
if (*Variables[0]) if (*Variables[0])
RunInstance(Cmd); Ret = RunInstance(Cmd);
} while (!Exiting(Cmd) && (In = NextLine) != NULL); } while (!Exiting(Cmd) && (In = NextLine) != NULL);
cmd_free(FullInput); cmd_free(FullInput);
} }
return TRUE; return Ret;
} }
/* FOR /L: Do a numeric loop */ /* FOR /L: Do a numeric loop */
static void ForLoop(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer) static INT ForLoop(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
{ {
enum { START, STEP, END }; enum { START, STEP, END };
INT params[3] = { 0, 0, 0 }; INT params[3] = { 0, 0, 0 };
INT i; INT i;
INT Ret = 0;
TCHAR *Start, *End = List; TCHAR *Start, *End = List;
for (i = 0; i < 3 && GetNextElement(&Start, &End); i++) for (i = 0; i < 3 && GetNextElement(&Start, &End); i++)
@ -361,17 +363,19 @@ static void ForLoop(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer)
(params[STEP] >= 0 ? (i <= params[END]) : (i >= params[END]))) (params[STEP] >= 0 ? (i <= params[END]) : (i >= params[END])))
{ {
_itot(i, Buffer, 10); _itot(i, Buffer, 10);
RunInstance(Cmd); Ret = RunInstance(Cmd);
i += params[STEP]; i += params[STEP];
} }
return Ret;
} }
/* Process a FOR in one directory. Stored in Buffer (up to BufPos) is a /* Process a FOR in one directory. Stored in Buffer (up to BufPos) is a
* string which is prefixed to each element of the list. In a normal FOR * string which is prefixed to each element of the list. In a normal FOR
* it will be empty, but in FOR /R it will be the directory name. */ * it will be empty, but in FOR /R it will be the directory name. */
static void ForDir(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer, TCHAR *BufPos) static INT ForDir(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer, TCHAR *BufPos)
{ {
TCHAR *Start, *End = List; TCHAR *Start, *End = List;
INT Ret = 0;
while (!Exiting(Cmd) && GetNextElement(&Start, &End)) while (!Exiting(Cmd) && GetNextElement(&Start, &End))
{ {
if (BufPos + (End - Start) > &Buffer[CMDLINE_LENGTH]) if (BufPos + (End - Start) > &Buffer[CMDLINE_LENGTH])
@ -402,22 +406,24 @@ static void ForDir(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer, TCHAR *BufPo
_tcscmp(w32fd.cFileName, _T("..")) == 0) _tcscmp(w32fd.cFileName, _T("..")) == 0)
continue; continue;
_tcscpy(FilePart, w32fd.cFileName); _tcscpy(FilePart, w32fd.cFileName);
RunInstance(Cmd); Ret = RunInstance(Cmd);
} while (!Exiting(Cmd) && FindNextFile(hFind, &w32fd)); } while (!Exiting(Cmd) && FindNextFile(hFind, &w32fd));
FindClose(hFind); FindClose(hFind);
} }
else else
{ {
RunInstance(Cmd); Ret = RunInstance(Cmd);
} }
} }
return Ret;
} }
/* FOR /R: Process a FOR in each directory of a tree, recursively. */ /* FOR /R: Process a FOR in each directory of a tree, recursively. */
static void ForRecursive(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer, TCHAR *BufPos) static INT ForRecursive(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer, TCHAR *BufPos)
{ {
HANDLE hFind; HANDLE hFind;
WIN32_FIND_DATA w32fd; WIN32_FIND_DATA w32fd;
INT Ret = 0;
if (BufPos[-1] != _T('\\')) if (BufPos[-1] != _T('\\'))
{ {
@ -425,12 +431,12 @@ static void ForRecursive(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer, TCHAR
*BufPos = _T('\0'); *BufPos = _T('\0');
} }
ForDir(Cmd, List, Buffer, BufPos); Ret = ForDir(Cmd, List, Buffer, BufPos);
_tcscpy(BufPos, _T("*")); _tcscpy(BufPos, _T("*"));
hFind = FindFirstFile(Buffer, &w32fd); hFind = FindFirstFile(Buffer, &w32fd);
if (hFind == INVALID_HANDLE_VALUE) if (hFind == INVALID_HANDLE_VALUE)
return; return Ret;
do do
{ {
if (!(w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) if (!(w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
@ -438,9 +444,10 @@ static void ForRecursive(PARSED_COMMAND *Cmd, LPTSTR List, TCHAR *Buffer, TCHAR
if (_tcscmp(w32fd.cFileName, _T(".")) == 0 || if (_tcscmp(w32fd.cFileName, _T(".")) == 0 ||
_tcscmp(w32fd.cFileName, _T("..")) == 0) _tcscmp(w32fd.cFileName, _T("..")) == 0)
continue; continue;
ForRecursive(Cmd, List, Buffer, _stpcpy(BufPos, w32fd.cFileName)); Ret = ForRecursive(Cmd, List, Buffer, _stpcpy(BufPos, w32fd.cFileName));
} while (!Exiting(Cmd) && FindNextFile(hFind, &w32fd)); } while (!Exiting(Cmd) && FindNextFile(hFind, &w32fd));
FindClose(hFind); FindClose(hFind);
return Ret;
} }
BOOL BOOL
@ -449,18 +456,18 @@ ExecuteFor(PARSED_COMMAND *Cmd)
TCHAR Buffer[CMDLINE_LENGTH]; /* Buffer to hold the variable value */ TCHAR Buffer[CMDLINE_LENGTH]; /* Buffer to hold the variable value */
LPTSTR BufferPtr = Buffer; LPTSTR BufferPtr = Buffer;
LPFOR_CONTEXT lpNew; LPFOR_CONTEXT lpNew;
BOOL Success = TRUE; INT Ret;
LPTSTR List = DoDelayedExpansion(Cmd->For.List); LPTSTR List = DoDelayedExpansion(Cmd->For.List);
if (!List) if (!List)
return FALSE; return 1;
/* Create our FOR context */ /* Create our FOR context */
lpNew = cmd_alloc(sizeof(FOR_CONTEXT)); lpNew = cmd_alloc(sizeof(FOR_CONTEXT));
if (!lpNew) if (!lpNew)
{ {
cmd_free(List); cmd_free(List);
return FALSE; return 1;
} }
lpNew->prev = fc; lpNew->prev = fc;
lpNew->firstvar = Cmd->For.Variable; lpNew->firstvar = Cmd->For.Variable;
@ -472,21 +479,21 @@ ExecuteFor(PARSED_COMMAND *Cmd)
if (Cmd->For.Switches & FOR_F) if (Cmd->For.Switches & FOR_F)
{ {
Success = ForF(Cmd, List, Buffer); Ret = ForF(Cmd, List, Buffer);
} }
else if (Cmd->For.Switches & FOR_LOOP) else if (Cmd->For.Switches & FOR_LOOP)
{ {
ForLoop(Cmd, List, Buffer); Ret = ForLoop(Cmd, List, Buffer);
} }
else if (Cmd->For.Switches & FOR_RECURSIVE) else if (Cmd->For.Switches & FOR_RECURSIVE)
{ {
DWORD Len = GetFullPathName(Cmd->For.Params ? Cmd->For.Params : _T("."), DWORD Len = GetFullPathName(Cmd->For.Params ? Cmd->For.Params : _T("."),
MAX_PATH, Buffer, NULL); MAX_PATH, Buffer, NULL);
ForRecursive(Cmd, List, Buffer, &Buffer[Len]); Ret = ForRecursive(Cmd, List, Buffer, &Buffer[Len]);
} }
else else
{ {
ForDir(Cmd, List, Buffer, Buffer); Ret = ForDir(Cmd, List, Buffer, Buffer);
} }
/* Remove our context, unless someone already did that */ /* Remove our context, unless someone already did that */
@ -495,7 +502,7 @@ ExecuteFor(PARSED_COMMAND *Cmd)
cmd_free(lpNew); cmd_free(lpNew);
cmd_free(List); cmd_free(List);
return Success; return Ret;
} }
/* EOF */ /* EOF */

View file

@ -63,7 +63,7 @@ INT cmd_if (LPTSTR param)
return 1; return 1;
} }
BOOL ExecuteIf(PARSED_COMMAND *Cmd) INT ExecuteIf(PARSED_COMMAND *Cmd)
{ {
INT result = FALSE; /* when set cause 'then' clause to be executed */ INT result = FALSE; /* when set cause 'then' clause to be executed */
LPTSTR param; LPTSTR param;
@ -73,13 +73,13 @@ BOOL ExecuteIf(PARSED_COMMAND *Cmd)
{ {
Left = DoDelayedExpansion(Cmd->If.LeftArg); Left = DoDelayedExpansion(Cmd->If.LeftArg);
if (!Left) if (!Left)
return FALSE; return 1;
} }
Right = DoDelayedExpansion(Cmd->If.RightArg); Right = DoDelayedExpansion(Cmd->If.RightArg);
if (!Right) if (!Right)
{ {
cmd_free(Left); cmd_free(Left);
return FALSE; return 1;
} }
if (Cmd->If.Operator == IF_CMDEXTVERSION) if (Cmd->If.Operator == IF_CMDEXTVERSION)
@ -91,7 +91,7 @@ BOOL ExecuteIf(PARSED_COMMAND *Cmd)
{ {
error_syntax(Right); error_syntax(Right);
cmd_free(Right); cmd_free(Right);
return FALSE; return 1;
} }
result = (2 >= n); result = (2 >= n);
} }
@ -108,7 +108,7 @@ BOOL ExecuteIf(PARSED_COMMAND *Cmd)
{ {
error_syntax(Right); error_syntax(Right);
cmd_free(Right); cmd_free(Right);
return FALSE; return 1;
} }
result = (nErrorLevel >= n); result = (nErrorLevel >= n);
} }
@ -166,7 +166,7 @@ BOOL ExecuteIf(PARSED_COMMAND *Cmd)
/* full condition was false, do the "else" command if there is one */ /* full condition was false, do the "else" command if there is one */
if (Cmd->Subcommands->Next) if (Cmd->Subcommands->Next)
return ExecuteCommand(Cmd->Subcommands->Next); return ExecuteCommand(Cmd->Subcommands->Next);
return TRUE; return 0;
} }
} }