2006-02-16 23:23:37 +00:00
|
|
|
/*
|
|
|
|
* CMD.H - header file for the modules in CMD.EXE
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* History:
|
|
|
|
*
|
|
|
|
* 7-15-95 Tim Norman
|
|
|
|
* started
|
|
|
|
*
|
|
|
|
* 06/29/98 (Rob Lake)
|
|
|
|
* Moved error messages in here
|
|
|
|
*
|
|
|
|
* 07/12/98 (Rob Lake)
|
|
|
|
* Moved more error messages here.
|
|
|
|
*
|
|
|
|
* 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
|
|
|
|
* Added compile date to version.
|
|
|
|
*
|
2007-05-05 11:32:25 +00:00
|
|
|
* 26-Feb-1999 (Eric Kohl)
|
2006-02-16 23:23:37 +00:00
|
|
|
* Introduced a new version string.
|
|
|
|
* Thanks to Emanuele Aliberti!
|
|
|
|
*/
|
|
|
|
|
2010-02-26 11:43:19 +00:00
|
|
|
#pragma once
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2013-01-24 23:00:42 +00:00
|
|
|
#include <config.h>
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
#include "cmdver.h"
|
2007-08-01 10:17:13 +00:00
|
|
|
#include "cmddbg.h"
|
|
|
|
|
2020-07-12 19:41:07 +00:00
|
|
|
/* Version of the Command Extensions */
|
|
|
|
#define CMDEXTVERSION 2
|
|
|
|
|
[CMD] Fixes for Batch error execution control flow.
CORE-13713 CORE-13736
- In case execution of all batch contexts is stopped (by selecting "All"
at the Ctrl-C/Ctrl-Break prompt), notify as well the CheckCtrlBreak()
signal handler once there are no more batch contexts (this in effect
resets the internal 'bLeaveAll' static flag in CheckCtrlBreak).
This is an adaptation of the fix present in FreeCOM 1.5, first
described in https://gcfl.net/FreeDOS/command.com/bugs074g.html .
- Introduce a ParseErrorEx() helper that sets the 'bParseError' flag and
displays a customized syntax-error message, only for the first syntax
error encountered. Implement ParseError() around the *Ex function.
- In batch mode, echo the original pre-parsed batch file line if a parse
error has been encountered.
- When running a compound command - including IF, FOR, command blocks -,
and that control flow is modified by any CALL/GOTO/EXIT command,
detect this while running the compound command so as to stop it and go
back to the main batch execution loop, that will then set up the actual
new command to run.
- In GOTO, do not process any more parts of a compound command only when
we have found a valid label.
2020-05-18 00:05:53 +00:00
|
|
|
#define BREAK_BATCHFILE 1
|
|
|
|
#define BREAK_OUTOFBATCH 2 /* aka. BREAK_ENDOFBATCHFILES */
|
|
|
|
#define BREAK_INPUT 3
|
|
|
|
#define BREAK_IGNORE 4
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* define some error messages */
|
|
|
|
#define D_ON _T("on")
|
|
|
|
#define D_OFF _T("off")
|
|
|
|
|
|
|
|
/* command line buffer length */
|
|
|
|
#define CMDLINE_LENGTH 8192
|
|
|
|
|
2007-09-28 12:17:19 +00:00
|
|
|
/* 16k = max buffer size */
|
|
|
|
#define BUFF_SIZE 16384
|
|
|
|
|
2017-09-30 11:39:08 +00:00
|
|
|
/* Global variables */
|
2009-03-23 23:52:50 +00:00
|
|
|
extern LPTSTR lpOriginalEnvironment;
|
2006-02-16 23:23:37 +00:00
|
|
|
extern WORD wColor;
|
|
|
|
extern WORD wDefColor;
|
2018-04-28 22:53:49 +00:00
|
|
|
extern BOOL bCtrlBreak;
|
2006-02-16 23:23:37 +00:00
|
|
|
extern BOOL bIgnoreEcho;
|
|
|
|
extern BOOL bExit;
|
2009-03-26 01:14:25 +00:00
|
|
|
extern BOOL bDisableBatchEcho;
|
2017-09-30 11:39:08 +00:00
|
|
|
extern BOOL bEnableExtensions;
|
2009-03-06 18:05:45 +00:00
|
|
|
extern BOOL bDelayedExpansion;
|
2006-02-16 23:23:37 +00:00
|
|
|
extern INT nErrorLevel;
|
|
|
|
|
|
|
|
|
|
|
|
/* Prototypes for ALIAS.C */
|
|
|
|
VOID ExpandAlias (LPTSTR, INT);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandAlias (LPTSTR);
|
2009-03-16 18:18:26 +00:00
|
|
|
|
|
|
|
/* Prototypes for ASSOC.C */
|
|
|
|
INT CommandAssoc (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for BEEP.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_beep (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for CALL.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_call (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for CHOICE.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandChoice (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for CLS.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_cls (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for CMD.C */
|
2016-11-05 14:55:55 +00:00
|
|
|
INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, UINT len, BOOL bPutSeparator);
|
2009-03-22 01:51:29 +00:00
|
|
|
HANDLE RunFile(DWORD, LPTSTR, LPTSTR, LPTSTR, INT);
|
2009-04-12 23:51:15 +00:00
|
|
|
INT ParseCommandLine(LPTSTR);
|
2008-08-21 20:18:35 +00:00
|
|
|
struct _PARSED_COMMAND;
|
2020-05-18 00:03:15 +00:00
|
|
|
|
|
|
|
INT
|
|
|
|
ExecuteCommand(
|
|
|
|
IN struct _PARSED_COMMAND *Cmd);
|
|
|
|
|
|
|
|
INT
|
|
|
|
ExecuteCommandWithEcho(
|
|
|
|
IN struct _PARSED_COMMAND *Cmd);
|
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName );
|
|
|
|
VOID AddBreakHandler (VOID);
|
|
|
|
VOID RemoveBreakHandler (VOID);
|
2020-06-04 00:56:18 +00:00
|
|
|
|
|
|
|
BOOL
|
|
|
|
SubstituteVar(
|
|
|
|
IN PCTSTR Src,
|
|
|
|
OUT size_t* SrcIncLen, // VarNameLen
|
|
|
|
OUT PTCHAR Dest,
|
|
|
|
IN PTCHAR DestEnd,
|
|
|
|
OUT size_t* DestIncLen,
|
|
|
|
IN TCHAR Delim);
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
SubstituteVars(
|
|
|
|
IN PCTSTR Src,
|
|
|
|
OUT PTSTR Dest,
|
|
|
|
IN TCHAR Delim);
|
2020-07-04 15:40:58 +00:00
|
|
|
|
|
|
|
BOOL
|
|
|
|
SubstituteForVars(
|
|
|
|
IN PCTSTR Src,
|
|
|
|
OUT PTSTR Dest);
|
|
|
|
|
2020-06-04 00:56:18 +00:00
|
|
|
PTSTR
|
|
|
|
DoDelayedExpansion(
|
|
|
|
IN PCTSTR Line);
|
|
|
|
|
2009-04-12 23:51:15 +00:00
|
|
|
INT DoCommand(LPTSTR first, LPTSTR rest, struct _PARSED_COMMAND *Cmd);
|
2008-08-22 14:37:11 +00:00
|
|
|
BOOL ReadLine(TCHAR *commandline, BOOL bMore);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
extern HANDLE CMD_ModuleHandle;
|
|
|
|
|
|
|
|
|
|
|
|
/* Prototypes for CMDINPUT.C */
|
2009-03-29 19:17:45 +00:00
|
|
|
BOOL ReadCommand (LPTSTR, INT);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2017-09-30 11:39:08 +00:00
|
|
|
extern TCHAR AutoCompletionChar;
|
|
|
|
extern TCHAR PathCompletionChar;
|
|
|
|
|
|
|
|
#define IS_COMPLETION_DISABLED(CompletionCtrl) \
|
|
|
|
((CompletionCtrl) == 0x00 || (CompletionCtrl) == 0x0D || (CompletionCtrl) >= 0x20)
|
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for CMDTABLE.C */
|
|
|
|
#define CMD_SPECIAL 1
|
|
|
|
#define CMD_BATCHONLY 2
|
|
|
|
#define CMD_HIDE 4
|
|
|
|
|
|
|
|
typedef struct tagCOMMAND
|
|
|
|
{
|
2013-06-29 23:50:13 +00:00
|
|
|
LPTSTR name;
|
|
|
|
INT flags;
|
|
|
|
INT (*func)(LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
} COMMAND, *LPCOMMAND;
|
|
|
|
|
2013-06-29 23:50:13 +00:00
|
|
|
extern COMMAND cmds[]; /* The internal command table */
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
VOID PrintCommandList (VOID);
|
|
|
|
|
2008-02-02 21:06:53 +00:00
|
|
|
LPCTSTR GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA );
|
|
|
|
|
2017-10-02 17:03:01 +00:00
|
|
|
/* Prototypes for CTTY.C */
|
|
|
|
#ifdef INCLUDE_CMD_CTTY
|
|
|
|
INT cmd_ctty(LPTSTR);
|
|
|
|
#endif
|
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
/* Prototypes for COLOR.C */
|
2017-09-30 14:04:24 +00:00
|
|
|
INT CommandColor(LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2017-09-30 15:09:38 +00:00
|
|
|
/* Prototypes for CONSOLE.C */
|
|
|
|
#include "console.h"
|
2017-09-30 14:10:21 +00:00
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
/* Prototypes for COPY.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_copy (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for DATE.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_date (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for DEL.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandDelete (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for DELAY.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandDelay (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for DIR.C */
|
2009-03-16 00:44:08 +00:00
|
|
|
INT FormatDate (TCHAR *, LPSYSTEMTIME, BOOL);
|
|
|
|
INT FormatTime (TCHAR *, LPSYSTEMTIME);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandDir (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for DIRSTACK.C */
|
|
|
|
VOID InitDirectoryStack (VOID);
|
|
|
|
VOID DestroyDirectoryStack (VOID);
|
|
|
|
INT GetDirectoryStackDepth (VOID);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandPushd (LPTSTR);
|
|
|
|
INT CommandPopd (LPTSTR);
|
|
|
|
INT CommandDirs (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for ECHO.C */
|
2009-03-26 01:14:25 +00:00
|
|
|
BOOL OnOffCommand(LPTSTR param, LPBOOL flag, INT message);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandEcho (LPTSTR);
|
|
|
|
INT CommandEchos (LPTSTR);
|
|
|
|
INT CommandEchoerr (LPTSTR);
|
|
|
|
INT CommandEchoserr (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for ERROR.C */
|
2020-05-17 18:08:41 +00:00
|
|
|
VOID
|
|
|
|
ErrorMessage(
|
|
|
|
IN DWORD dwErrorCode,
|
2020-09-12 18:29:54 +00:00
|
|
|
IN PCTSTR szFormat OPTIONAL,
|
2020-05-17 18:08:41 +00:00
|
|
|
...);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2020-09-12 18:01:27 +00:00
|
|
|
VOID error_no_pipe(VOID);
|
2020-09-12 18:29:54 +00:00
|
|
|
VOID error_bad_command(PCTSTR s);
|
2020-09-12 18:01:27 +00:00
|
|
|
VOID error_invalid_drive(VOID);
|
|
|
|
VOID error_req_param_missing(VOID);
|
2020-09-12 18:29:54 +00:00
|
|
|
VOID error_sfile_not_found(PCTSTR s);
|
2020-09-12 18:01:27 +00:00
|
|
|
VOID error_file_not_found(VOID);
|
|
|
|
VOID error_path_not_found(VOID);
|
2020-09-12 18:29:54 +00:00
|
|
|
VOID error_too_many_parameters(PCTSTR s);
|
|
|
|
VOID error_parameter_format(TCHAR ch);
|
|
|
|
VOID error_invalid_switch(TCHAR ch);
|
|
|
|
VOID error_invalid_parameter_format(PCTSTR s);
|
2020-09-12 18:01:27 +00:00
|
|
|
VOID error_out_of_memory(VOID);
|
2020-09-12 18:29:54 +00:00
|
|
|
VOID error_syntax(PCTSTR s);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2020-09-12 18:01:27 +00:00
|
|
|
VOID msg_pause(VOID);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for FILECOMP.C */
|
|
|
|
#ifdef FEATURE_UNIX_FILENAME_COMPLETION
|
|
|
|
VOID CompleteFilename (LPTSTR, UINT);
|
|
|
|
INT ShowCompletionMatches (LPTSTR, INT);
|
|
|
|
#endif
|
|
|
|
#ifdef FEATURE_4NT_FILENAME_COMPLETION
|
|
|
|
VOID CompleteFilename (LPTSTR, BOOL, LPTSTR, UINT);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* Prototypes for FOR.C */
|
2009-02-24 20:29:18 +00:00
|
|
|
#define FOR_DIRS 1 /* /D */
|
|
|
|
#define FOR_F 2 /* /F */
|
|
|
|
#define FOR_LOOP 4 /* /L */
|
|
|
|
#define FOR_RECURSIVE 8 /* /R */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_for (LPTSTR);
|
2009-04-12 23:51:15 +00:00
|
|
|
INT ExecuteFor(struct _PARSED_COMMAND *Cmd);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Prototypes for FREE.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandFree (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for GOTO.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_goto (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for HISTORY.C */
|
|
|
|
#ifdef FEATURE_HISTORY
|
2007-09-28 08:51:04 +00:00
|
|
|
LPCTSTR PeekHistory(INT);
|
2017-12-03 17:49:41 +00:00
|
|
|
VOID History(INT, LPTSTR);/*add entries browse history*/
|
2006-02-16 23:23:37 +00:00
|
|
|
VOID History_move_to_bottom(VOID);/*F3*/
|
|
|
|
VOID InitHistory(VOID);
|
|
|
|
VOID CleanHistory(VOID);
|
|
|
|
VOID History_del_current_entry(LPTSTR str);/*CTRL-D*/
|
2017-12-03 17:49:41 +00:00
|
|
|
INT CommandHistory(LPTSTR param);
|
2006-02-16 23:23:37 +00:00
|
|
|
#endif
|
|
|
|
|
2008-12-22 22:34:51 +00:00
|
|
|
/* Prototypes for IF.C */
|
2020-07-12 19:41:07 +00:00
|
|
|
#define IFFLAG_NEGATE 1 /* NOT */
|
|
|
|
#define IFFLAG_IGNORECASE 2 /* /I - Extended */
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
typedef enum _IF_OPERATOR
|
|
|
|
{
|
2020-07-12 19:41:07 +00:00
|
|
|
/** Unary operators **/
|
|
|
|
/* Standard */
|
|
|
|
IF_ERRORLEVEL, IF_EXIST,
|
|
|
|
/* Extended */
|
|
|
|
IF_CMDEXTVERSION, IF_DEFINED,
|
|
|
|
|
|
|
|
/** Binary operators **/
|
|
|
|
/* Standard */
|
|
|
|
IF_STRINGEQ, /* == */
|
|
|
|
/* Extended */
|
|
|
|
IF_EQU, IF_NEQ, IF_LSS, IF_LEQ, IF_GTR, IF_GEQ
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
} IF_OPERATOR;
|
|
|
|
|
2009-04-12 23:51:15 +00:00
|
|
|
INT ExecuteIf(struct _PARSED_COMMAND *Cmd);
|
2008-12-22 22:34:51 +00:00
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
/* Prototypes for INTERNAL.C */
|
|
|
|
VOID InitLastPath (VOID);
|
|
|
|
VOID FreeLastPath (VOID);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_chdir (LPTSTR);
|
|
|
|
INT cmd_mkdir (LPTSTR);
|
|
|
|
INT cmd_rmdir (LPTSTR);
|
|
|
|
INT CommandExit (LPTSTR);
|
|
|
|
INT CommandRem (LPTSTR);
|
|
|
|
INT CommandShowCommands (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for LOCALE.C */
|
|
|
|
extern TCHAR cDateSeparator;
|
|
|
|
extern INT nDateFormat;
|
|
|
|
extern TCHAR cTimeSeparator;
|
|
|
|
extern INT nTimeFormat;
|
|
|
|
extern TCHAR cThousandSeparator;
|
|
|
|
extern TCHAR cDecimalSeparator;
|
|
|
|
extern INT nNumberGroups;
|
|
|
|
|
|
|
|
VOID InitLocale (VOID);
|
2009-03-16 00:44:08 +00:00
|
|
|
LPTSTR GetDateString (VOID);
|
|
|
|
LPTSTR GetTimeString (VOID);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for MEMORY.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandMemory (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2009-03-17 22:27:33 +00:00
|
|
|
/* Prototypes for MKLINK.C */
|
|
|
|
INT cmd_mklink(LPTSTR);
|
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
/* Prototypes for MISC.C */
|
2020-07-18 21:31:50 +00:00
|
|
|
INT
|
|
|
|
GetRootPath(
|
|
|
|
IN LPCTSTR InPath,
|
|
|
|
OUT LPTSTR OutPath,
|
|
|
|
IN INT size);
|
|
|
|
|
2009-04-05 01:50:24 +00:00
|
|
|
BOOL SetRootPath(TCHAR *oldpath,TCHAR *InPath);
|
2006-02-16 23:23:37 +00:00
|
|
|
TCHAR cgetchar (VOID);
|
|
|
|
BOOL CheckCtrlBreak (INT);
|
|
|
|
BOOL add_entry (LPINT ac, LPTSTR **arg, LPCTSTR entry);
|
2012-04-14 21:35:58 +00:00
|
|
|
LPTSTR *split (LPTSTR, LPINT, BOOL, BOOL);
|
2009-01-17 12:55:46 +00:00
|
|
|
LPTSTR *splitspace (LPTSTR, LPINT);
|
2006-02-16 23:23:37 +00:00
|
|
|
VOID freep (LPTSTR *);
|
|
|
|
LPTSTR _stpcpy (LPTSTR, LPCTSTR);
|
2008-08-21 15:33:59 +00:00
|
|
|
VOID StripQuotes(LPTSTR);
|
2020-09-03 22:17:15 +00:00
|
|
|
|
|
|
|
BOOL IsValidPathName(IN LPCTSTR pszPath);
|
|
|
|
BOOL IsExistingFile(IN LPCTSTR pszPath);
|
|
|
|
BOOL IsExistingDirectory(IN LPCTSTR pszPath);
|
2006-02-16 23:23:37 +00:00
|
|
|
VOID GetPathCase(TCHAR *, TCHAR *);
|
|
|
|
|
|
|
|
#define PROMPT_NO 0
|
|
|
|
#define PROMPT_YES 1
|
|
|
|
#define PROMPT_ALL 2
|
|
|
|
#define PROMPT_BREAK 3
|
|
|
|
|
2017-10-01 16:30:39 +00:00
|
|
|
BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total);
|
2008-07-26 22:49:49 +00:00
|
|
|
INT FilePromptYN (UINT);
|
|
|
|
INT FilePromptYNA (UINT);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for MOVE.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_move (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for MSGBOX.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandMsgbox (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2008-08-21 20:18:35 +00:00
|
|
|
/* Prototypes from PARSER.C */
|
2020-07-21 23:16:53 +00:00
|
|
|
|
|
|
|
/* These three characters act like spaces to the parser in most contexts */
|
|
|
|
#define STANDARD_SEPS _T(",;=")
|
|
|
|
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
typedef enum _COMMAND_TYPE
|
|
|
|
{
|
|
|
|
/* Standard command */
|
|
|
|
C_COMMAND,
|
|
|
|
/* Quiet operator */
|
|
|
|
C_QUIET,
|
|
|
|
/* Parenthesized block */
|
|
|
|
C_BLOCK,
|
|
|
|
/* Operators */
|
|
|
|
C_MULTI, C_OR, C_AND, C_PIPE,
|
|
|
|
/* Special parsed commands */
|
|
|
|
C_FOR, C_IF, C_REM
|
|
|
|
} COMMAND_TYPE;
|
|
|
|
|
2008-08-21 20:18:35 +00:00
|
|
|
typedef struct _PARSED_COMMAND
|
|
|
|
{
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
/*
|
|
|
|
* For IF : this is the 'main' case (the 'else' is obtained via SubCmd->Next).
|
|
|
|
* For FOR: this is the list of all the subcommands in the DO.
|
|
|
|
*/
|
2013-06-29 23:50:13 +00:00
|
|
|
struct _PARSED_COMMAND *Subcommands;
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
|
|
|
|
struct _PARSED_COMMAND *Next; // Next command(s) in the chain.
|
2013-06-29 23:50:13 +00:00
|
|
|
struct _REDIRECTION *Redirections;
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
COMMAND_TYPE Type;
|
2013-06-29 23:50:13 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
PTSTR Rest;
|
2013-06-29 23:50:13 +00:00
|
|
|
TCHAR First[];
|
|
|
|
} Command;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
BYTE Switches;
|
|
|
|
TCHAR Variable;
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
PTSTR Params;
|
|
|
|
PTSTR List;
|
2020-07-26 18:30:03 +00:00
|
|
|
struct _FOR_CONTEXT *Context;
|
2013-06-29 23:50:13 +00:00
|
|
|
} For;
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
BYTE Flags;
|
|
|
|
IF_OPERATOR Operator;
|
|
|
|
PTSTR LeftArg;
|
|
|
|
PTSTR RightArg;
|
|
|
|
} If;
|
2013-06-29 23:50:13 +00:00
|
|
|
};
|
2008-08-21 20:18:35 +00:00
|
|
|
} PARSED_COMMAND;
|
2020-07-26 18:30:03 +00:00
|
|
|
|
[CMD] Make the command-line parser more compatible with Windows' CMD one.
All these modifications have been verified with Windows' CMD, either
by using written cmd_rostests and the existing cmd_winetests, or
manually by enabling the flags cmd!fDumpTokens and cmd!fDumpParse
(available in the public symbols) and analyzing how the tokens are
being parsed, as well as the generated command tree.
See also the following links for more details (but remember that these
observations have to be double-checked in Windows' CMD!):
* Parser rules: https://stackoverflow.com/a/4095133/13530036
* Discussion: https://www.dostips.com/forum/viewtopic.php?f=3&t=8355
* Numbers parsing: https://www.dostips.com/forum/viewtopic.php?t=3758
* Label names vs. GOTO and CALL: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803
and: https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
- Fix REM command parsing. A C_COMMAND-like structure should still
be built, so that it can show up during batch command echo. However
some specific handling needs to be done, so use instead a new C_REM
command type.
Escape carets are parsed differently than usual: they are explicitly
kept in the command line and don't participate in line continuations.
Also, the Windows' CMD behaviour is to discards everything before the
last line continuation.
- Prefix operator '@' (the "silent" operator) is parsed as a separate
command. Thus, the command @@foo@bar is parsed as: '@', '@', 'foo@bar'.
- Improve the checks for numbered redirection.
For this purpose, we check whether this is a number, that is in first
position in the current parsing buffer or is preceded by a whitespace-
like separator, including standard command operators (excepting '@' !)
and double-quotes.
- Empty command blocks, i.e. "( )", standing by themselves, or present
in IF or FOR commands, are considered invalid. (The closing parenthesis
is considered "unexpected".)
- Ignore single closing parenthesis when being outside of command blocks,
thus interpreting it as a command, and ignore explicitly everything
following on the same line, including line continuations.
This very specific situation can happen e.g. while running in batch mode,
when jumping to a label present inside a command block.
See the code for a thorough explanation.
- Detect whether a parenthesized block is not terminated at the end
of a command stream (getting a NUL character instead of a newline),
and if so, bail out early instead of entering into an infinite loop.
- Perform a similar check for the parenthesized list in FOR commands.
- Initialize the static 'InsideBlock' value to a known value.
- The '&' operator (multi-commmand) is allowed to have an empty RHS.
When such situation occurs, turn the CurrentTokenType to TOK_END
so as to avoid a parse error later on.
- The main body of a IF statement, or its 'else' clause, as well as
the main body of a FOR statement, must not be empty, otherwise this
is considered a syntax error. If so, call ParseError() that sets
the 'bParseError' flag, and forcing all batch execution to stop.
2020-05-22 22:35:54 +00:00
|
|
|
PARSED_COMMAND*
|
|
|
|
ParseCommand(
|
|
|
|
IN PCTSTR Line);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
DumpCommand(
|
|
|
|
IN PARSED_COMMAND* Cmd,
|
|
|
|
IN ULONG SpacePad);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
EchoCommand(
|
|
|
|
IN PARSED_COMMAND* Cmd);
|
|
|
|
|
|
|
|
PTCHAR
|
|
|
|
UnparseCommand(
|
|
|
|
IN PARSED_COMMAND* Cmd,
|
|
|
|
OUT PTCHAR Out,
|
|
|
|
IN PTCHAR OutEnd);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FreeCommand(
|
|
|
|
IN OUT PARSED_COMMAND* Cmd);
|
2008-08-21 20:18:35 +00:00
|
|
|
|
2020-09-12 18:29:54 +00:00
|
|
|
VOID ParseErrorEx(IN PCTSTR s);
|
[CMD] Fixes for Batch error execution control flow.
CORE-13713 CORE-13736
- In case execution of all batch contexts is stopped (by selecting "All"
at the Ctrl-C/Ctrl-Break prompt), notify as well the CheckCtrlBreak()
signal handler once there are no more batch contexts (this in effect
resets the internal 'bLeaveAll' static flag in CheckCtrlBreak).
This is an adaptation of the fix present in FreeCOM 1.5, first
described in https://gcfl.net/FreeDOS/command.com/bugs074g.html .
- Introduce a ParseErrorEx() helper that sets the 'bParseError' flag and
displays a customized syntax-error message, only for the first syntax
error encountered. Implement ParseError() around the *Ex function.
- In batch mode, echo the original pre-parsed batch file line if a parse
error has been encountered.
- When running a compound command - including IF, FOR, command blocks -,
and that control flow is modified by any CALL/GOTO/EXIT command,
detect this while running the compound command so as to stop it and go
back to the main batch execution loop, that will then set up the actual
new command to run.
- In GOTO, do not process any more parts of a compound command only when
we have found a valid label.
2020-05-18 00:05:53 +00:00
|
|
|
extern BOOL bParseError;
|
|
|
|
extern TCHAR ParseLine[CMDLINE_LENGTH];
|
|
|
|
|
[CMD] CALL: Fix the implementation of the CALL command, make it more compatible with Windows' CMD.
- Fail if no parameter is provided.
- The "CALL :label args..." syntax is available only when command extensions
are enabled. Fail if this syntax is used outside of a batch context.
- Reparse the CALL command parameter with the command parser, in order
to accurately parse and interpret it as a possible command (including
escape carets, etc...) and not duplicate the logic.
** CURRENT Windows' CMD-compatibility LIMITATION ** (may be lifted in
a "ROS-specific" running mode of CMD): only allow standard commands to
be specified as parameter of the CALL command.
This reparsing behaviour can be observed in Windows' CMD, by dumping
the interpreted commands after enabling the cmd!fDumpParse flag from
a debugger (using public symbols).
- When reparsing, we should tell the parser to NOT ignore lines that
start with a colon, because in this situation these are to be
considered as valid "commands" (for parsing "CALL :label").
* For Windows' CMD-compatibility, the remaining escape carets need to
be doubled again so that, after the new parser step, they are escaped
back to their original form. But then we also need to do it the "buggy"
way à la Windows, where carets in quotes are doubled either! However
when being re-parsed, since they are in quotes they remain doubled!!
(see "Phase 6" in https://stackoverflow.com/a/4095133/13530036 ).
* A MSCMD_CALL_QUIRKS define allows to disable this buggy behaviour,
and instead tell the parser to not not interpret the escape carets.
- When initializing a new batch context when the "CALL :label" syntax is
used, ensure that we reuse the same batch file position pointer as its
parent, so as to have correct call label ordering behaviour.
That is,
:label
ECHO hi
CALL :label
:label
ECHO bye
should display:
hi
bye
bye
i.e., the CALL calls the second label instead of the first one (and
thus entering into an infinite loop).
Finally, the "CALL :label" syntax strips the first ':' away, so, as a
side-effect, the command "CALL :EOF" fails (otherwise it would perform
a "GOTO :EOF" and succeeds), while "CALL ::EOF" succeeds.
Fixes some cmd_winetests.
2020-07-26 18:30:21 +00:00
|
|
|
extern BOOL bIgnoreParserComments;
|
|
|
|
extern BOOL bHandleContinuations;
|
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
/* Prototypes from PATH.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_path (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes from PROMPT.C */
|
2013-07-04 01:05:14 +00:00
|
|
|
VOID InitPrompt (VOID);
|
2006-02-16 23:23:37 +00:00
|
|
|
VOID PrintPrompt (VOID);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_prompt (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for REDIR.C */
|
2017-10-02 17:03:01 +00:00
|
|
|
HANDLE GetHandle(UINT Number);
|
|
|
|
VOID SetHandle(UINT Number, HANDLE Handle);
|
|
|
|
|
2012-09-28 19:36:49 +00:00
|
|
|
typedef enum _REDIR_MODE
|
|
|
|
{
|
2013-06-29 23:50:13 +00:00
|
|
|
REDIR_READ = 0,
|
|
|
|
REDIR_WRITE = 1,
|
|
|
|
REDIR_APPEND = 2
|
2012-09-28 19:36:49 +00:00
|
|
|
} REDIR_MODE;
|
2008-08-21 15:33:59 +00:00
|
|
|
typedef struct _REDIRECTION
|
|
|
|
{
|
2013-06-29 23:50:13 +00:00
|
|
|
struct _REDIRECTION *Next;
|
|
|
|
HANDLE OldHandle;
|
|
|
|
BYTE Number;
|
|
|
|
REDIR_MODE Mode;
|
|
|
|
TCHAR Filename[];
|
2008-08-21 15:33:59 +00:00
|
|
|
} REDIRECTION;
|
|
|
|
BOOL PerformRedirection(REDIRECTION *);
|
|
|
|
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End);
|
|
|
|
INT GetRedirection(LPTSTR, REDIRECTION **);
|
|
|
|
VOID FreeRedirection(REDIRECTION *);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for REN.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_rename (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2007-09-27 08:35:08 +00:00
|
|
|
/* Prototypes for REN.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_replace (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for SCREEN.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandScreen (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for SET.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_set (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
2008-02-01 09:49:58 +00:00
|
|
|
/* Prototypes for SETLOCAL.C */
|
2009-03-23 23:52:50 +00:00
|
|
|
LPTSTR DuplicateEnvironment(VOID);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_setlocal (LPTSTR);
|
|
|
|
INT cmd_endlocal (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for START.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_start (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for STRTOCLR.C */
|
|
|
|
BOOL StringToColor (LPWORD, LPTSTR *);
|
|
|
|
|
|
|
|
/* Prototypes for TIME.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_time (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for TIMER.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandTimer (LPTSTR param);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for TITLE.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_title (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for TYPE.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_type (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for VER.C */
|
2014-12-31 21:22:49 +00:00
|
|
|
VOID InitOSVersion(VOID);
|
|
|
|
VOID PrintOSVersion(VOID);
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_ver (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for VERIFY.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_verify (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for VOL.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT cmd_vol (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* Prototypes for WHERE.C */
|
|
|
|
BOOL SearchForExecutable (LPCTSTR, LPTSTR);
|
|
|
|
|
|
|
|
/* Prototypes for WINDOW.C */
|
2008-08-25 23:22:03 +00:00
|
|
|
INT CommandActivate (LPTSTR);
|
|
|
|
INT CommandWindow (LPTSTR);
|
2006-02-16 23:23:37 +00:00
|
|
|
|
|
|
|
/* The MSDOS Batch Commands [MS-DOS 5.0 User's Guide and Reference p359] */
|
2008-08-25 23:22:03 +00:00
|
|
|
int cmd_if(TCHAR *);
|
|
|
|
int cmd_pause(TCHAR *);
|
|
|
|
int cmd_shift(TCHAR *);
|