reactos/base/shell/cmd/parser.c

2108 lines
58 KiB
C
Raw Normal View History

/*
[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
* PARSER.C - Command-line Lexical Analyzer/Tokenizer and Parser.
*/
#include "precomp.h"
[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
/*
* Defines for enabling different Windows' CMD compatibility behaviours.
*/
/* Enable this define for command echoer compatibility */
#define MSCMD_ECHO_COMMAND_COMPAT
[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
/* Enable this define for parser quirks (see UnParseToken() for more details) */
#define MSCMD_PARSER_BUGS
/* Enable this define for parenthesized blocks parsing quirks */
// #define MSCMD_PARENS_PARSE_BUGS
/* Enable this define for redirection parsing quirks */
#define MSCMD_REDIR_PARSE_BUGS
/* Enable this define for allowing '&' commands with an empty RHS.
* The default behaviour is to just return the LHS instead.
* See ParseCommandBinaryOp() for details. */
// #define MSCMD_MULTI_EMPTY_RHS
/*
* Parser debugging support. These flags are global so that their values can be
* modified at runtime from a debugger. They correspond to the public Windows'
* cmd!fDumpTokens and cmd!fDumpParse booleans.
* (Same names are used for compatibility as they are documented online.)
*/
BOOLEAN fDumpTokens = FALSE;
BOOLEAN fDumpParse = FALSE;
#define C_OP_LOWEST C_MULTI
#define C_OP_HIGHEST C_PIPE
static const TCHAR OpString[][3] = { _T("&"), _T("||"), _T("&&"), _T("|") };
static const TCHAR RedirString[][3] = { _T("<"), _T(">"), _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
static const TCHAR* const IfOperatorString[] =
{
[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
/** Unary operators **/
/* Standard */
_T("errorlevel"),
_T("exist"),
/* Extended */
_T("cmdextversion"),
_T("defined"),
#define IF_MAX_UNARY IF_DEFINED
[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
/** Binary operators **/
/* Standard */
_T("=="),
/* Extended */
_T("equ"),
_T("neq"),
_T("lss"),
_T("leq"),
_T("gtr"),
_T("geq"),
#define IF_MAX_COMPARISON 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
static __inline BOOL IsSeparator(TCHAR Char)
{
[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
return _istspace(Char) || (Char && !!_tcschr(STANDARD_SEPS, Char));
}
[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 _TOK_TYPE
{
TOK_END,
TOK_NORMAL,
TOK_OPERATOR,
TOK_REDIRECTION,
TOK_BEGIN_BLOCK,
TOK_END_BLOCK
[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
} TOK_TYPE;
/* Scratch buffer for temporary command substitutions / expansions */
static TCHAR TempBuf[CMDLINE_LENGTH];
/*static*/ BOOL bParseError;
static BOOL bLineContinuations;
/*static*/ TCHAR ParseLine[CMDLINE_LENGTH];
[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
static PTCHAR ParsePos;
static PTCHAR OldParsePos;
[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
BOOL bIgnoreParserComments = TRUE;
BOOL bHandleContinuations = TRUE;
static TCHAR CurrentToken[CMDLINE_LENGTH];
[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
static TOK_TYPE CurrentTokenType = TOK_END;
#ifndef MSCMD_PARSER_BUGS
static BOOL bReparseToken = FALSE;
static PTCHAR LastCurTokPos;
#endif
static INT InsideBlock = 0;
static VOID ResetParser(IN PTCHAR Pos)
{
bParseError = FALSE;
ParsePos = Pos;
OldParsePos = ParsePos;
}
/*
* This function "refetches" the last parsed token back into the stream
* for later reparsing -- since the way of lexing it is context-dependent.
* This "feature" is at the root of many obscure CMD parsing quirks,
* due to the fact this feature is in opposition with line-continuation.
* Indeed, when a stream of characters has a line-continuation, the lexer-
* parser will parse the stream up to the end of the line, then will
* reset the parser state and position back to the beginning of the line
* before accepting the rest of the character stream and continuing
* parsing them. This means that all the non-parsed characters before the
* line-continuation have been lost. Of course, their parsed form is now
* within the current parsed token. However, suppose now we need to
* unparse this token for reparsing it a different way later on. If we
* somehow pushed the already-parsed current token back into the beginning
* of the character stream, besides the complications of moving up the
* characters in the stream buffer, we would basically have "new" data
* that has been already parsed one way, to be now parsed another way.
* If instead we had saved somehow the unparsed form of the token, and
* we push back that form into the stream buffer for reparsing, we would
* encounter again the line-continuation, that, depending on which
* context the token is reparsed, would cause problems:
* e.g. in the case of REM command parsing, the parser would stop at the
* first line-continuation.
*
* When MSCMD_PARSER_BUGS is undefined, the UnParseToken() / ParseToken()
* cycle keeps the current token in its buffer, but also saves the start
* position corresponding to the batch of characters that have been parsed
* during the last line-continuation. The next ParseToken() would then
* reparse these latest charcters and the result replaces the last part
* in the current token.
*
* For example, a first parsing of
* foo^\n
* bar^\n
* baz
* would result in the current token "foobarbaz", where the start position
* corresponding to the batch of characters parsed during the last line-continuation
* being pointing at "baz". The stream buffer only contains "baz" (and following data).
* Then UnParseToken() saves this info so that at the next ParseToken(), the "baz"
* part of the stream buffer gets reparsed (possibly differently) and the result
* would replace the "baz" part in the current token.
*
* If MSCMD_PARSER_BUGS is defined however, then the behaviour of the Windows' CMD
* parser applies: in the example above, the last ParseToken() call would completely
* replace the current token "foobarbaz" with the new result of the parsing of "baz".
*/
static VOID UnParseToken(VOID)
{
ParsePos = OldParsePos;
/* Debugging support */
if (fDumpTokens)
ConOutPrintf(_T("Ungetting: '%s'\n"), ParsePos);
#ifndef MSCMD_PARSER_BUGS
bReparseToken = TRUE;
#endif
}
static VOID InitParser(VOID)
{
*CurrentToken = 0;
CurrentTokenType = TOK_END;
InsideBlock = 0;
#ifndef MSCMD_PARSER_BUGS
bReparseToken = FALSE;
LastCurTokPos = NULL;
#endif
ResetParser(ParseLine);
}
[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
static TCHAR ParseChar(VOID)
{
TCHAR Char;
if (bParseError)
[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
return 0;
restart:
/*
* Although CRs can be injected into a line via an environment
* variable substitution, the parser ignores them - they won't
* even separate tokens.
*/
do
{
Char = *ParsePos++;
}
while (Char == _T('\r'));
[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 (!Char) --ParsePos;
if (!Char && bLineContinuations)
{
[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 (!ReadLine(ParseLine, TRUE))
{
[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
/* ^C pressed, or line was too long */
[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
//
// FIXME: Distinguish with respect to BATCH end of file !!
//
[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
bParseError = TRUE;
}
else
{
ResetParser(ParseLine);
if (*ParsePos)
goto restart;
}
}
[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
return Char;
}
VOID ParseErrorEx(IN PCTSTR s)
{
/* Only display the first error we encounter */
if (!bParseError)
error_syntax(s);
bParseError = TRUE;
}
static __inline VOID ParseError(VOID)
{
ParseErrorEx(CurrentTokenType != TOK_END ? CurrentToken : NULL);
}
[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
static TOK_TYPE
ParseTokenEx(
IN TCHAR PrefixOperator OPTIONAL,
IN TCHAR ExtraEnd OPTIONAL,
IN PCTSTR Separators OPTIONAL,
IN BOOL bHandleContinuations)
{
[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
TOK_TYPE Type;
PTCHAR CurrentTokStart = CurrentToken;
PTCHAR Out = CurrentTokStart;
TCHAR Char;
BOOL bInQuote = FALSE;
[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
#ifndef MSCMD_PARSER_BUGS
if (bReparseToken)
{
bReparseToken = FALSE;
/*
* We will append the part to be reparsed to the old one
* (still present in CurrentToken).
*/
CurrentTokStart = LastCurTokPos;
Out = CurrentTokStart;
}
else
{
LastCurTokPos = CurrentToken;
}
#endif
/* Start with what we have at current ParsePos */
OldParsePos = ParsePos;
for (Char = ParseChar(); Char && Char != _T('\n'); Char = ParseChar())
{
bInQuote ^= (Char == _T('"'));
if (!bInQuote)
{
if (Separators != NULL)
{
[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 (_istspace(Char) || !!_tcschr(Separators, Char))
{
/* Skip leading separators */
[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 (Out == CurrentTokStart)
continue;
break;
}
}
[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
/* Check for prefix operator */
if ((Out == CurrentTokStart) && (Char == PrefixOperator))
break;
/*
* Check for numbered redirection.
*
* For this purpose, we check whether this is a number, that is
* in first position in the current parsing buffer (remember that
* ParsePos points to the next character) or is preceded by a
* whitespace-like separator, including standard command operators
* (excepting '@' !) and double-quotes.
*/
if ( _istdigit(Char) &&
(ParsePos == &OldParsePos[1] ||
IsSeparator(ParsePos[-2]) ||
!!_tcschr(_T("()&|\""), ParsePos[-2])) &&
(*ParsePos == _T('<') || *ParsePos == _T('>')) )
{
break;
}
[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
/* Check for other delimiters / operators */
if (Char == ExtraEnd)
break;
if (InsideBlock && Char == _T(')'))
break;
if (_tcschr(_T("&|<>"), Char))
break;
[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 (bHandleContinuations && (Char == _T('^')))
{
Char = ParseChar();
/* Eat up a \n, allowing line continuation */
if (Char == _T('\n'))
[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
{
#ifndef MSCMD_PARSER_BUGS
LastCurTokPos = Out;
#endif
Char = ParseChar();
[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
}
/* Next character is a forced literal */
[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 (Out == CurrentTokStart)
{
/* Ignore any prefix operator if we don't start a new command block */
if (CurrentTokenType != TOK_BEGIN_BLOCK)
PrefixOperator = 0;
}
}
}
if (Out == &CurrentToken[CMDLINE_LENGTH - 1])
break;
*Out++ = Char;
[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
// PrefixOperator = 0;
}
[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
/*
* We exited the parsing loop. If the current character is the first one
* (Out == CurrentTokStart), interpret it as an operator. Otherwise,
* terminate the current token (type TOK_NORMAL) and keep the current
* character so that it can be refetched as an operator at the next call.
*/
if (Out != CurrentTokStart)
{
Type = TOK_NORMAL;
}
[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
/*
* Else we have an operator.
*/
else if (Char == _T('@'))
{
Type = TOK_OPERATOR; // TOK_QUIET / TOK_PREFIX_OPERATOR
*Out++ = Char;
Char = ParseChar();
}
else if (Char == _T('('))
{
Type = TOK_BEGIN_BLOCK;
*Out++ = Char;
[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
Char = ParseChar();
}
else if (Char == _T(')'))
{
Type = TOK_END_BLOCK;
*Out++ = Char;
[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
Char = ParseChar();
}
else if (Char == _T('&') || Char == _T('|'))
{
Type = TOK_OPERATOR;
*Out++ = Char;
Char = ParseChar();
[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
/* Check for '&&' or '||' */
if (Char == Out[-1])
{
*Out++ = Char;
[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
Char = ParseChar();
}
}
[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
else if ( _istdigit(Char) ||
(Char == _T('<') || Char == _T('>')) )
{
Type = TOK_REDIRECTION;
[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 (_istdigit(Char))
{
*Out++ = Char;
Char = ParseChar();
}
[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
/* By construction (see the while-loop above),
* the next character must be a redirection. */
ASSERT(Char == _T('<') || Char == _T('>'));
*Out++ = Char;
Char = ParseChar();
if (Char == Out[-1])
{
/* Strangely, the tokenizer allows << as well as >>... (it
* will cause an error when trying to parse it though) */
*Out++ = Char;
Char = ParseChar();
}
if (Char == _T('&'))
{
*Out++ = Char;
while (IsSeparator(Char = ParseChar()))
;
[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 (_istdigit(Char))
{
*Out++ = Char;
[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
Char = ParseChar();
}
}
}
else
{
Type = TOK_END;
[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
*Out++ = Char;
}
*Out = _T('\0');
[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
/*
* Rewind the parsing position, so that the current character can be
* refetched later on. However do this only if it is not NULL and if
* this is not TOK_END, since we do not want to reparse later the line
* termination (we could enter into infinite loops, or, in case of line
* continuation, get unwanted "More?" prompts).
*/
if (Char != 0 && Type != TOK_END)
--ParsePos;
/* Debugging support */
if (fDumpTokens)
ConOutPrintf(_T("ParseToken: (%d) '%s'\n"), Type, CurrentToken);
return (CurrentTokenType = Type);
}
[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
static __inline INT
ParseToken(
IN TCHAR ExtraEnd OPTIONAL,
IN PCTSTR Separators OPTIONAL)
{
[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
return ParseTokenEx(0, ExtraEnd, Separators, bHandleContinuations);
[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
}
static PARSED_COMMAND*
AllocCommand(
IN COMMAND_TYPE Type,
IN PCTSTR CmdHead OPTIONAL,
IN PCTSTR CmdTail OPTIONAL)
{
PARSED_COMMAND* Cmd;
switch (Type)
{
case C_COMMAND:
case C_REM:
{
SIZE_T CmdHeadLen = _tcslen(CmdHead) + 1;
SIZE_T CmdTailLen = _tcslen(CmdTail) + 1;
Cmd = cmd_alloc(FIELD_OFFSET(PARSED_COMMAND,
Command.First[CmdHeadLen + CmdTailLen]));
if (!Cmd)
return NULL;
Cmd->Type = Type;
Cmd->Next = NULL;
Cmd->Subcommands = NULL;
Cmd->Redirections = NULL; /* Is assigned by the calling function */
memcpy(Cmd->Command.First, CmdHead, CmdHeadLen * sizeof(TCHAR));
Cmd->Command.Rest = Cmd->Command.First + CmdHeadLen;
memcpy(Cmd->Command.Rest, CmdTail, CmdTailLen * sizeof(TCHAR));
return Cmd;
}
case C_QUIET:
case C_BLOCK:
case C_MULTI:
case C_OR:
case C_AND:
case C_PIPE:
{
Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
if (!Cmd)
return NULL;
Cmd->Type = Type;
Cmd->Next = NULL;
Cmd->Subcommands = NULL;
Cmd->Redirections = NULL; /* For C_BLOCK only: is assigned by the calling function */
return Cmd;
}
case C_FOR:
case C_IF:
{
Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
if (!Cmd)
return NULL;
memset(Cmd, 0, sizeof(PARSED_COMMAND));
Cmd->Type = Type;
return Cmd;
}
default:
ERR("Unknown command type 0x%x\n", Type);
ASSERT(FALSE);
return NULL;
}
}
VOID
FreeCommand(
IN OUT PARSED_COMMAND* Cmd)
{
if (Cmd->Subcommands)
FreeCommand(Cmd->Subcommands);
if (Cmd->Next)
FreeCommand(Cmd->Next);
FreeRedirection(Cmd->Redirections);
if (Cmd->Type == C_FOR)
{
cmd_free(Cmd->For.Params);
cmd_free(Cmd->For.List);
}
else if (Cmd->Type == C_IF)
{
cmd_free(Cmd->If.LeftArg);
cmd_free(Cmd->If.RightArg);
}
cmd_free(Cmd);
}
/* Parse redirections and append them to the list */
static BOOL
ParseRedirection(
IN OUT REDIRECTION** List)
{
PTSTR Tok = CurrentToken;
REDIRECTION* Redir;
REDIR_MODE RedirMode;
[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
BYTE Number;
if ( !(*Tok == _T('<') || *Tok == _T('>')) &&
!(_istdigit(*Tok) &&
(Tok[1] == _T('<') || Tok[1] == _T('>')) ) )
{
ASSERT(CurrentTokenType != TOK_REDIRECTION);
return FALSE;
}
ASSERT((CurrentTokenType == TOK_REDIRECTION) ||
(CurrentTokenType == TOK_NORMAL));
[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 (_istdigit(*Tok))
Number = *Tok++ - _T('0');
else
Number = *Tok == _T('<') ? 0 : 1;
if (*Tok++ == _T('<'))
{
RedirMode = REDIR_READ;
[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
/* Forbid '<<' */
if (*Tok == _T('<'))
goto fail;
}
else
{
RedirMode = REDIR_WRITE;
if (*Tok == _T('>'))
{
RedirMode = REDIR_APPEND;
Tok++;
}
}
[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 (*Tok == _T('&'))
{
/* This is a handle redirection: the next character must be one single digit */
if (!(_istdigit(Tok[1]) && !Tok[2]))
goto fail;
}
else
#ifndef MSCMD_REDIR_PARSE_BUGS
if (!*Tok)
[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
/* The file name was not part of this token, so it will be the next one */
#else
/* Get rid of what possibly remains in the token, and retrieve the next one */
#endif
{
if (ParseToken(0, STANDARD_SEPS) != TOK_NORMAL)
goto fail;
Tok = CurrentToken;
}
/* If a redirection for this handle number already exists, delete it */
while ((Redir = *List))
{
if (Redir->Number == Number)
{
*List = Redir->Next;
cmd_free(Redir);
continue;
}
List = &Redir->Next;
}
Redir = cmd_alloc(FIELD_OFFSET(REDIRECTION, Filename[_tcslen(Tok) + 1]));
if (!Redir)
{
WARN("Cannot allocate memory for Redir!\n");
goto fail;
}
Redir->Next = NULL;
Redir->OldHandle = INVALID_HANDLE_VALUE;
Redir->Number = Number;
Redir->Mode = RedirMode;
_tcscpy(Redir->Filename, Tok);
*List = Redir;
return TRUE;
fail:
ParseError();
FreeRedirection(*List);
*List = NULL;
return FALSE;
}
[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
static __inline PARSED_COMMAND*
ParseCommandOp(
IN COMMAND_TYPE OpType);
/* Parse a parenthesized block */
[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
static PARSED_COMMAND*
ParseBlock(
IN OUT REDIRECTION** RedirList)
{
PARSED_COMMAND *Cmd, *Sub, **NextPtr;
[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
Cmd = AllocCommand(C_BLOCK, NULL, NULL);
if (!Cmd)
{
WARN("Cannot allocate memory for Cmd!\n");
ParseError();
return NULL;
}
/* Read the block contents */
NextPtr = &Cmd->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
++InsideBlock;
while (TRUE)
{
[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
/*
* Windows' CMD compatibility: Strip leading newlines in the block.
*
* Note that this behaviour is buggy, especially when MSCMD_PARSER_BUGS is defined!
* For example:
* (foo^\n
* bar)
* would be parsed ultimately as: '(', 'bar', ')' because the "foo^"
* part would be discarded due to the UnParseToken() call, since this
* function doesn't work across line continuations.
*/
while (ParseToken(0, STANDARD_SEPS) == TOK_END && *CurrentToken == _T('\n'))
;
if (*CurrentToken && *CurrentToken != _T('\n'))
UnParseToken();
/* Break early if we have nothing else to read. We will also fail
* due to the fact we haven't encountered any closing parenthesis. */
if (!*CurrentToken /* || *CurrentToken == _T('\n') */)
{
ASSERT(CurrentTokenType == TOK_END);
break;
}
/*
* NOTE: Windows' CMD uses a "CRLF" operator when dealing with
* newlines in parenthesized blocks, as an alternative to the
* '&' command-separation operator.
*/
Sub = ParseCommandOp(C_OP_LOWEST);
if (Sub)
{
*NextPtr = Sub;
NextPtr = &Sub->Next;
}
else if (bParseError)
{
[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
--InsideBlock;
FreeCommand(Cmd);
return NULL;
}
if (CurrentTokenType == TOK_END_BLOCK)
break;
/* Skip past the \n */
}
[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
--InsideBlock;
/* Fail if the block was not terminated, or if we have
* an empty block, i.e. "( )", considered invalid. */
if ((CurrentTokenType != TOK_END_BLOCK) || (Cmd->Subcommands == NULL))
{
ParseError();
FreeCommand(Cmd);
return NULL;
}
[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
/* Process any trailing redirections and append them to the list */
#ifndef MSCMD_REDIR_PARSE_BUGS
while (ParseToken(0, STANDARD_SEPS) == TOK_REDIRECTION)
{
[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 (!ParseRedirection(RedirList))
{
FreeCommand(Cmd);
return NULL;
}
}
[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
#else
while (ParseToken(0, STANDARD_SEPS) != TOK_END)
{
if (!ParseRedirection(RedirList))
{
/* If an actual error happened in ParseRedirection(), bail out */
if (bParseError)
{
FreeCommand(Cmd);
return NULL;
}
/* Otherwise it just returned FALSE because the current token
* is not a redirection. Unparse the token and refetch it. */
break;
}
}
#endif
if (CurrentTokenType != TOK_END)
{
/*
* Windows' CMD compatibility: Unparse the current token.
*
* Note that this behaviour is buggy, especially when MSCMD_PARSER_BUGS is defined!
* For example:
* (foo^\n
* bar)
* would be parsed ultimately as: '(', 'bar', ')' because the "foo^"
* part would be discarded due to the UnParseToken() call, since this
* function doesn't work across line continuations.
*/
UnParseToken();
/*
* Since it is expected that when ParseBlock() returns, the next
* token is already fetched, call ParseToken() again to compensate.
*/
ParseToken(0, STANDARD_SEPS);
}
return Cmd;
}
/* Parse an IF statement */
[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
static PARSED_COMMAND*
ParseIf(VOID)
{
[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* Cmd;
[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
Cmd = AllocCommand(C_IF, NULL, NULL);
if (!Cmd)
{
WARN("Cannot allocate memory for Cmd!\n");
ParseError();
return NULL;
}
if (bEnableExtensions && (_tcsicmp(CurrentToken, _T("/I")) == 0))
{
Cmd->If.Flags |= IFFLAG_IGNORECASE;
ParseToken(0, STANDARD_SEPS);
}
if (_tcsicmp(CurrentToken, _T("not")) == 0)
{
Cmd->If.Flags |= IFFLAG_NEGATE;
ParseToken(0, STANDARD_SEPS);
}
if (CurrentTokenType != TOK_NORMAL)
goto error;
/* Check for unary operators */
for (; Cmd->If.Operator <= IF_MAX_UNARY; Cmd->If.Operator++)
{
/* Skip the extended operators if the extensions are disabled */
if (!bEnableExtensions && (Cmd->If.Operator >= IF_CMDEXTVERSION))
continue;
if (_tcsicmp(CurrentToken, IfOperatorString[Cmd->If.Operator]) == 0)
{
if (ParseToken(0, STANDARD_SEPS) != TOK_NORMAL)
goto error;
Cmd->If.RightArg = cmd_dup(CurrentToken);
goto condition_done;
}
}
/* It must be a two-argument (comparison) operator. It could be ==, so
* the equals sign can't be treated as whitespace here. */
Cmd->If.LeftArg = cmd_dup(CurrentToken);
ParseToken(0, _T(",;"));
/* The right argument can come immediately after == */
if (_tcsnicmp(CurrentToken, _T("=="), 2) == 0 && CurrentToken[2])
{
Cmd->If.RightArg = cmd_dup(&CurrentToken[2]);
goto condition_done;
}
// Cmd->If.Operator == IF_MAX_UNARY + 1;
for (; Cmd->If.Operator <= IF_MAX_COMPARISON; Cmd->If.Operator++)
{
/* Skip the extended operators if the extensions are disabled */
if (!bEnableExtensions && (Cmd->If.Operator >= IF_EQU)) // (Cmd->If.Operator > IF_STRINGEQ)
continue;
if (_tcsicmp(CurrentToken, IfOperatorString[Cmd->If.Operator]) == 0)
{
if (ParseToken(0, STANDARD_SEPS) != TOK_NORMAL)
goto error;
Cmd->If.RightArg = cmd_dup(CurrentToken);
goto condition_done;
}
}
goto error;
condition_done:
Cmd->Subcommands = ParseCommandOp(C_OP_LOWEST);
if (Cmd->Subcommands == NULL)
goto error;
if (_tcsicmp(CurrentToken, _T("else")) == 0)
{
Cmd->Subcommands->Next = ParseCommandOp(C_OP_LOWEST);
if (Cmd->Subcommands->Next == NULL)
goto error;
}
return Cmd;
error:
FreeCommand(Cmd);
ParseError();
return NULL;
}
/*
* Parse a FOR command.
* Syntax is: FOR [options] %var IN (list) DO 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
static PARSED_COMMAND*
ParseFor(VOID)
{
[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* Cmd;
[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
/* Use the scratch buffer */
PTSTR List = TempBuf;
PTCHAR Pos = List;
Cmd = AllocCommand(C_FOR, NULL, NULL);
if (!Cmd)
{
WARN("Cannot allocate memory for Cmd!\n");
ParseError();
return NULL;
}
/* Skip the extended FOR syntax if extensions are disabled */
if (!bEnableExtensions)
goto parseForBody;
[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
while (TRUE)
{
if (_tcsicmp(CurrentToken, _T("/D")) == 0)
{
Cmd->For.Switches |= FOR_DIRS;
}
else if (_tcsicmp(CurrentToken, _T("/F")) == 0)
{
Cmd->For.Switches |= FOR_F;
if (!Cmd->For.Params)
{
ParseToken(0, STANDARD_SEPS);
if (CurrentToken[0] == _T('/') || CurrentToken[0] == _T('%'))
break;
Cmd->For.Params = cmd_dup(CurrentToken);
}
}
else if (_tcsicmp(CurrentToken, _T("/L")) == 0)
{
Cmd->For.Switches |= FOR_LOOP;
}
else if (_tcsicmp(CurrentToken, _T("/R")) == 0)
{
Cmd->For.Switches |= FOR_RECURSIVE;
if (!Cmd->For.Params)
{
ParseToken(0, STANDARD_SEPS);
if (CurrentToken[0] == _T('/') || CurrentToken[0] == _T('%'))
break;
StripQuotes(CurrentToken);
Cmd->For.Params = cmd_dup(CurrentToken);
}
}
else
{
break;
}
ParseToken(0, STANDARD_SEPS);
}
/* Make sure there aren't two different switches specified
* at the same time, unless they're /D and /R */
if ((Cmd->For.Switches & (Cmd->For.Switches - 1)) != 0
&& Cmd->For.Switches != (FOR_DIRS | FOR_RECURSIVE))
{
goto error;
}
parseForBody:
/* Variable name should be % and just one other character */
if (CurrentToken[0] != _T('%') || _tcslen(CurrentToken) != 2)
goto error;
Cmd->For.Variable = CurrentToken[1];
ParseToken(0, STANDARD_SEPS);
if (_tcsicmp(CurrentToken, _T("in")) != 0)
goto error;
if (ParseToken(_T('('), STANDARD_SEPS) != TOK_BEGIN_BLOCK)
goto error;
[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
while (TRUE)
{
/* Pretend we're inside a block so the tokenizer will stop on ')' */
[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
++InsideBlock;
ParseToken(0, STANDARD_SEPS);
[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
--InsideBlock;
if (CurrentTokenType == TOK_END_BLOCK)
break;
[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
/* Skip past the \n */
if ((CurrentTokenType == TOK_END) && *CurrentToken == _T('\n'))
continue;
if (CurrentTokenType != TOK_NORMAL)
goto error;
if (Pos != List)
*Pos++ = _T(' ');
if (Pos + _tcslen(CurrentToken) >= &List[CMDLINE_LENGTH])
goto error;
Pos = _stpcpy(Pos, CurrentToken);
}
*Pos = _T('\0');
Cmd->For.List = cmd_dup(List);
ParseToken(0, STANDARD_SEPS);
if (_tcsicmp(CurrentToken, _T("do")) != 0)
goto error;
Cmd->Subcommands = ParseCommandOp(C_OP_LOWEST);
if (Cmd->Subcommands == NULL)
goto error;
return Cmd;
error:
FreeCommand(Cmd);
ParseError();
return NULL;
}
/* Parse a REM 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
static PARSED_COMMAND*
ParseRem(VOID)
{
[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* Cmd;
/* The common scratch buffer already contains the name of the command */
PTSTR ParsedLine = TempBuf;
PTCHAR Pos = ParsedLine + _tcslen(ParsedLine) + 1;
SIZE_T TailOffset = Pos - ParsedLine;
/* Build a minimal command for REM, so that it can still get through the batch echo unparsing */
/* Unparse the current token, so as to emulate the REM command parsing
* behaviour of Windows' CMD, that discards everything before the last
* line continuation. */
UnParseToken();
/*
* Ignore the rest of the line, without any line continuation (but eat the caret).
* We cannot simply set bLineContinuations to TRUE or FALSE, because we want (only
* for the REM command), even when bLineContinuations == FALSE, to get the caret,
* otherwise it would be ignored.
*/
while (ParseTokenEx(0, 0, NULL, FALSE) != TOK_END)
{
if (Pos + _tcslen(CurrentToken) >= &ParsedLine[CMDLINE_LENGTH])
{
ParseError();
return NULL;
}
Pos = _stpcpy(Pos, CurrentToken);
}
*Pos = _T('\0');
Cmd = AllocCommand(C_REM,
ParsedLine,
ParsedLine + TailOffset);
if (!Cmd)
{
WARN("Cannot allocate memory for Cmd!\n");
ParseError();
return NULL;
}
return Cmd;
}
[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
/* Parse a command */
static PARSED_COMMAND*
ParseCommandPart(
IN OUT REDIRECTION** RedirList)
{
[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* Cmd;
PARSED_COMMAND* (*Func)(VOID);
[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
/* Use the scratch buffer */
PTSTR ParsedLine = TempBuf;
/* We need to copy the current token because it's going to be changed below by the ParseToken() calls */
PTCHAR Pos = _stpcpy(ParsedLine, CurrentToken) + 1;
SIZE_T TailOffset = Pos - ParsedLine;
/* Check for special forms */
[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 ((Func = ParseFor, _tcsicmp(ParsedLine, _T("FOR")) == 0) ||
(Func = ParseIf, _tcsicmp(ParsedLine, _T("IF")) == 0) ||
(Func = ParseRem, _tcsicmp(ParsedLine, _T("REM")) == 0))
{
[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
PTCHAR pHelp;
ParseToken(0, STANDARD_SEPS);
[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 ((pHelp = _tcsstr(CurrentToken, _T("/?"))) &&
(Func == ParseIf ? (pHelp[2] == _T('/') || pHelp[2] == 0) : TRUE))
{
/* /? was found within the first token */
ParseToken(0, STANDARD_SEPS);
}
else
{
pHelp = NULL;
}
if (pHelp && (CurrentTokenType == TOK_NORMAL))
{
[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
/* We encountered /? first, but is followed
* by another token: that's an error. */
ParseError();
return NULL;
}
/* Do actual parsing only if no help is present */
if (!pHelp)
{
/* FOR and IF commands cannot have leading redirection, but REM can */
if (*RedirList && ((Func == ParseFor) || (Func == ParseIf)))
{
[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
/* Display the culprit command and fail */
ParseErrorEx(ParsedLine);
return NULL;
}
[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
return Func();
}
[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
/* Otherwise, run FOR,IF,REM as regular commands only for help support */
if (Pos + _tcslen(_T("/?")) >= &ParsedLine[CMDLINE_LENGTH])
{
ParseError();
return NULL;
}
Pos = _stpcpy(Pos, _T("/?"));
}
else
{
ParseToken(0, NULL);
}
/* Now get the tail */
[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
while (CurrentTokenType != TOK_END)
{
if (CurrentTokenType == TOK_NORMAL)
{
if (Pos + _tcslen(CurrentToken) >= &ParsedLine[CMDLINE_LENGTH])
{
ParseError();
return NULL;
}
Pos = _stpcpy(Pos, CurrentToken);
}
[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
#ifndef MSCMD_REDIR_PARSE_BUGS
else if (CurrentTokenType == TOK_REDIRECTION)
{
[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
/* Process any trailing redirections and append them to the list */
while (CurrentTokenType == TOK_REDIRECTION)
{
if (!ParseRedirection(RedirList))
return NULL;
ParseToken(0, STANDARD_SEPS);
}
if (CurrentTokenType == TOK_END)
break;
/* Unparse the current token, and reparse it below with no separators */
UnParseToken();
}
else
{
[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
/* There is no need to do a UnParseToken() / ParseToken() cycle */
break;
}
[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
#else
else
{
/* Process any trailing redirections and append them to the list */
BOOL bSuccess = FALSE;
ASSERT(CurrentTokenType != TOK_END);
while (CurrentTokenType != TOK_END)
{
if (!ParseRedirection(RedirList))
{
/* If an actual error happened in ParseRedirection(), bail out */
if (bParseError)
return NULL;
/* Otherwise it just returned FALSE because the current token
* is not a redirection. Unparse the token and refetch it. */
break;
}
bSuccess = TRUE;
ParseToken(0, STANDARD_SEPS);
}
if (CurrentTokenType == TOK_END)
break;
/* Unparse the current token, and reparse it below with no separators */
UnParseToken();
/* If bSuccess == FALSE, we know that it's still the old fetched token, but
* it has been unparsed, so we need to refetch it before quitting the loop. */
if (!bSuccess)
{
ParseToken(0, NULL);
break;
}
}
#endif
ParseToken(0, NULL);
}
[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
*Pos = _T('\0');
[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
Cmd = AllocCommand(C_COMMAND,
ParsedLine,
ParsedLine + TailOffset);
if (!Cmd)
{
WARN("Cannot allocate memory for Cmd!\n");
ParseError();
return NULL;
}
return Cmd;
}
[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
static PARSED_COMMAND*
ParsePrimary(VOID)
{
[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* Cmd = NULL;
REDIRECTION* RedirList = NULL;
[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
/* In this context, '@' is considered as a separate token */
if ((*CurrentToken == _T('@')) && (CurrentTokenType == TOK_OPERATOR))
{
[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
Cmd = AllocCommand(C_QUIET, NULL, NULL);
if (!Cmd)
{
WARN("Cannot allocate memory for Cmd!\n");
ParseError();
return NULL;
}
/* @ acts like a unary operator with low precedence,
* so call the top-level parser */
Cmd->Subcommands = ParseCommandOp(C_OP_LOWEST);
return Cmd;
}
/* Process leading redirections and get the head of the 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
#ifndef MSCMD_REDIR_PARSE_BUGS
while (CurrentTokenType == TOK_REDIRECTION)
{
if (!ParseRedirection(&RedirList))
return NULL;
[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
ParseToken(_T('('), STANDARD_SEPS);
}
#else
{
BOOL bSuccess = FALSE;
while (CurrentTokenType != TOK_END)
{
if (!ParseRedirection(&RedirList))
{
/* If an actual error happened in ParseRedirection(), bail out */
if (bParseError)
return NULL;
/* Otherwise it just returned FALSE because
* the current token is not a redirection. */
break;
}
bSuccess = TRUE;
ParseToken(0, STANDARD_SEPS);
}
if (bSuccess)
{
/* Unparse the current token, and reparse it with support for parenthesis */
if (CurrentTokenType != TOK_END)
UnParseToken();
ParseToken(_T('('), STANDARD_SEPS);
}
[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
}
#endif
[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 (CurrentTokenType == TOK_NORMAL)
Cmd = ParseCommandPart(&RedirList);
else if (CurrentTokenType == TOK_BEGIN_BLOCK)
Cmd = ParseBlock(&RedirList);
else if (CurrentTokenType == TOK_END_BLOCK && !RedirList)
return NULL;
[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 (Cmd)
{
/* FOR and IF commands cannot have leading redirection
* (checked by ParseCommandPart(), errors out if so). */
ASSERT(!RedirList || (Cmd->Type != C_FOR && Cmd->Type != C_IF));
/* Save the redirection list in the command */
Cmd->Redirections = RedirList;
/* Return the new command */
return Cmd;
}
ParseError();
FreeRedirection(RedirList);
return NULL;
}
[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
static PARSED_COMMAND*
ParseCommandBinaryOp(
IN COMMAND_TYPE OpType)
{
[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* Cmd;
if (OpType == C_OP_LOWEST) // i.e. CP_MULTI
{
/* Ignore any parser-level comments */
[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
if (bIgnoreParserComments && (*CurrentToken == _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
{
/* Ignore the rest of the line, including line continuations */
while (ParseToken(0, NULL) != TOK_END)
;
#ifdef MSCMD_PARENS_PARSE_BUGS
/*
* Return NULL in case we are NOT inside a parenthesized block,
* otherwise continue. The effects can be observed as follows:
* within a parenthesized block, every second ':'-prefixed command
* is not ignored, while the first of each "pair" is ignored.
* This first command **MUST NOT** be followed by an empty line,
* otherwise a syntax error is raised.
*/
if (InsideBlock == 0)
{
#endif
return NULL;
#ifdef MSCMD_PARENS_PARSE_BUGS
}
/* Get the next token */
ParseToken(0, NULL);
#endif
}
/*
* Ignore single closing parenthesis outside of command blocks,
* thus interpreted as a command. This very specific situation
* can happen e.g. while running in batch mode, when jumping to
* a label present inside a command block.
*
* NOTE: If necessary, this condition can be restricted to only
* when a batch context 'bc' is active.
*
* NOTE 2: For further security, Windows checks that we are NOT
* currently inside a parenthesized block, and also, ignores
* explicitly everything (ParseToken() loop) on the same line
* (including line continuations) after this closing parenthesis.
*
* Why doing so? Consider the following batch:
*
* IF 1==1 (
* :label
* echo A
* ) ^
* ELSE (
* echo B
* exit /b
* )
* GOTO :label
*
* First the IF block is executed. Since the condition is trivially
* true, only the first block "echo A" is executed, then execution
* goes after the IF block, that is, at the GOTO. Here, the GOTO
* jumps within the first IF-block, however, the running context now
* is NOT an IF. So parsing and execution will go through each command,
* starting with 'echo A'. But then one gets the ') ^\n ELSE (' part !!
* If we want to make sense of this without bailing out due to
* parsing error, we should ignore this line, **including** the line
* continuation. Hence we need to loop over all the tokens following
* the closing parenthesis, instead of just returning NULL straight ahead.
* Then execution continues with the other commands, 'echo B' and
* 'exit /b' (here to stop the code loop). Execution would also
* continue (if 'exit' was replaced by something else) and encounter
* the lone closing parenthesis ')', that should again be ignored.
*
* Note that this feature has been introduced in Win2k+.
*/
if (/** bc && **/ (_tcscmp(CurrentToken, _T(")")) == 0) &&
(CurrentTokenType != TOK_END_BLOCK))
{
ASSERT(InsideBlock == 0);
/* Ignore the rest of the line, including line continuations */
while (ParseToken(0, NULL) != TOK_END)
;
return NULL;
}
#ifdef MSCMD_PARENS_PARSE_BUGS
/* Check whether we have an empty line only if we are not inside
* a parenthesized block, and return NULL if so, otherwise do not
* do anything; a syntax error will be raised later. */
if (InsideBlock == 0)
#endif
if (!*CurrentToken || *CurrentToken == _T('\n'))
{
ASSERT(CurrentTokenType == TOK_END);
return NULL;
}
}
if (OpType == C_OP_HIGHEST)
Cmd = ParsePrimary();
else
[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
Cmd = ParseCommandBinaryOp(OpType + 1);
if (Cmd && !_tcscmp(CurrentToken, OpString[OpType - C_OP_LOWEST]))
{
[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* Left = Cmd;
PARSED_COMMAND* Right;
Right = ParseCommandOp(OpType);
if (!Right)
{
[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
/*
* The '&' operator is allowed to have an empty RHS.
* In this case, we directly return the LHS only.
* Note that Windows' CMD prefers building a '&'
* command with an empty RHS.
*/
if (!bParseError && (OpType != C_MULTI))
ParseError();
[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 (bParseError)
{
FreeCommand(Left);
return NULL;
}
[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
#ifndef MSCMD_MULTI_EMPTY_RHS
return Left;
#endif
}
[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
Cmd = AllocCommand(OpType, NULL, NULL);
if (!Cmd)
{
WARN("Cannot allocate memory for Cmd!\n");
ParseError();
FreeCommand(Left);
FreeCommand(Right);
return NULL;
}
Cmd->Subcommands = Left;
Left->Next = Right;
[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
#ifdef MSCMD_MULTI_EMPTY_RHS
if (Right)
#endif
Right->Next = NULL;
}
return Cmd;
}
[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
static __inline PARSED_COMMAND*
ParseCommandOp(
IN COMMAND_TYPE OpType)
{
/* Start parsing: initialize the first token */
[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
/* Parse the prefix "quiet" operator '@' as a separate command.
* Thus, @@foo@bar is parsed as: '@', '@', 'foo@bar'. */
[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
ParseTokenEx(_T('@'), _T('('), STANDARD_SEPS, bHandleContinuations);
[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
return ParseCommandBinaryOp(OpType);
}
[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)
{
[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* Cmd;
if (Line)
{
if (!SubstituteVars(Line, ParseLine, _T('%')))
return NULL;
bLineContinuations = FALSE;
}
else
{
if (!ReadLine(ParseLine, FALSE))
return NULL;
bLineContinuations = TRUE;
}
[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
InitParser();
Cmd = ParseCommandOp(C_OP_LOWEST);
if (Cmd)
{
bIgnoreEcho = FALSE;
[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 ((CurrentTokenType != TOK_END) &&
(_tcscmp(CurrentToken, _T("\n")) != 0))
{
ParseError();
[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 (bParseError)
{
FreeCommand(Cmd);
return NULL;
}
/* Debugging support */
if (fDumpParse)
DumpCommand(Cmd, 0);
}
else
{
bIgnoreEcho = TRUE;
}
return Cmd;
}
/*
* This function is similar to EchoCommand(), but is used
* for dumping the command tree for debugging purposes.
*/
static VOID
[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
DumpRedir(
IN REDIRECTION* Redirections)
{
REDIRECTION* Redir;
if (Redirections)
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutPuts(_T(" Redir: "));
#else
ConOutPuts(_T("Redir: "));
#endif
for (Redir = Redirections; Redir; Redir = Redir->Next)
{
ConOutPrintf(_T(" %x %s%s"), Redir->Number,
RedirString[Redir->Mode], Redir->Filename);
}
}
VOID
[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
DumpCommand(
IN PARSED_COMMAND* Cmd,
IN ULONG SpacePad)
{
/*
* This macro is like DumpCommand(Cmd, Pad);
* but avoids an extra recursive level.
* Note that it can be used ONLY for terminating commands!
*/
#define DUMP(Command, Pad) \
do { \
Cmd = (Command); \
SpacePad = (Pad); \
goto dump; \
} while (0)
[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* Sub;
dump:
[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 (!Cmd)
return;
/* Space padding */
ConOutPrintf(_T("%*s"), SpacePad, _T(""));
switch (Cmd->Type)
{
case C_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
case C_REM:
{
/* Generic command name, and Type */
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutPrintf(_T("Cmd: %s Type: %x"),
Cmd->Command.First, Cmd->Type);
#else
ConOutPrintf(_T("Cmd: %s Type: %x "),
Cmd->Command.First, Cmd->Type);
#endif
/* Arguments */
if (Cmd->Command.Rest && *(Cmd->Command.Rest))
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutPrintf(_T(" Args: `%s'"), Cmd->Command.Rest);
#else
ConOutPrintf(_T("Args: `%s' "), Cmd->Command.Rest);
#endif
/* Redirections */
DumpRedir(Cmd->Redirections);
ConOutChar(_T('\n'));
return;
}
case C_QUIET:
{
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutChar(_T('@'));
#else
ConOutPuts(_T("@ "));
#endif
DumpRedir(Cmd->Redirections); // FIXME: Can we have leading redirections??
ConOutChar(_T('\n'));
/*DumpCommand*/DUMP(Cmd->Subcommands, SpacePad + 2);
return;
}
case C_BLOCK:
{
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutChar(_T('('));
#else
ConOutPuts(_T("( "));
#endif
DumpRedir(Cmd->Redirections);
ConOutChar(_T('\n'));
SpacePad += 2;
for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
{
#if defined(MSCMD_ECHO_COMMAND_COMPAT) && defined(MSCMD_PARSER_BUGS)
/*
* We will emulate Windows' CMD handling of "CRLF" and "&" multi-command
* enumeration within parenthesized command blocks.
*/
if (!Sub->Next)
{
DumpCommand(Sub, SpacePad);
continue;
}
if (Sub->Type != C_MULTI)
{
ConOutPrintf(_T("%*s"), SpacePad, _T(""));
ConOutPuts(_T("CRLF \n"));
DumpCommand(Sub, SpacePad);
continue;
}
/* Now, Sub->Type == C_MULTI */
Cmd = Sub;
ConOutPrintf(_T("%*s"), SpacePad, _T(""));
ConOutPrintf(_T("%s \n"), OpString[Cmd->Type - C_OP_LOWEST]);
// FIXME: Can we have redirections on these operator-type commands?
SpacePad += 2;
Cmd = Cmd->Subcommands;
DumpCommand(Cmd, SpacePad);
ConOutPrintf(_T("%*s"), SpacePad, _T(""));
ConOutPuts(_T("CRLF \n"));
DumpCommand(Cmd->Next, SpacePad);
// NOTE: Next commands will remain indented.
#else
/*
* If this command is followed by another one, first display "CRLF".
* This also emulates the CRLF placement "bug" of Windows' CMD
* for the last two commands.
*/
if (Sub->Next)
{
ConOutPrintf(_T("%*s"), SpacePad, _T(""));
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutPuts(_T("CRLF\n"));
#else
ConOutPuts(_T("CRLF \n"));
#endif
}
DumpCommand(Sub, SpacePad);
#endif // defined(MSCMD_ECHO_COMMAND_COMPAT) && defined(MSCMD_PARSER_BUGS)
}
return;
}
case C_MULTI:
case C_OR:
case C_AND:
case C_PIPE:
{
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutPrintf(_T("%s\n"), OpString[Cmd->Type - C_OP_LOWEST]);
#else
ConOutPrintf(_T("%s \n"), OpString[Cmd->Type - C_OP_LOWEST]);
#endif
// FIXME: Can we have redirections on these operator-type commands?
SpacePad += 2;
Sub = Cmd->Subcommands;
DumpCommand(Sub, SpacePad);
/*DumpCommand*/DUMP(Sub->Next, SpacePad);
return;
}
[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
case C_FOR:
{
ConOutPuts(_T("for"));
/* NOTE: FOR cannot have leading redirections */
if (Cmd->For.Switches & FOR_DIRS) ConOutPuts(_T(" /D"));
if (Cmd->For.Switches & FOR_F) ConOutPuts(_T(" /F"));
if (Cmd->For.Switches & FOR_LOOP) ConOutPuts(_T(" /L"));
if (Cmd->For.Switches & FOR_RECURSIVE) ConOutPuts(_T(" /R"));
if (Cmd->For.Params)
ConOutPrintf(_T(" %s"), Cmd->For.Params);
ConOutPrintf(_T(" %%%c in (%s) do\n"), Cmd->For.Variable, Cmd->For.List);
/*DumpCommand*/DUMP(Cmd->Subcommands, SpacePad + 2);
return;
}
case C_IF:
{
ConOutPuts(_T("if"));
/* NOTE: IF cannot have leading redirections */
if (Cmd->If.Flags & IFFLAG_IGNORECASE)
ConOutPuts(_T(" /I"));
ConOutChar(_T('\n'));
SpacePad += 2;
/*
* Show the IF command condition as a command.
* If it is negated, indent the command more.
*/
if (Cmd->If.Flags & IFFLAG_NEGATE)
{
ConOutPrintf(_T("%*s"), SpacePad, _T(""));
ConOutPuts(_T("not\n"));
SpacePad += 2;
}
ConOutPrintf(_T("%*s"), SpacePad, _T(""));
/*
* Command name:
* - Unary operator: its name is the command name, and its argument is the command argument.
* - Binary operator: its LHS is the command name, its RHS is the command argument.
*
* Type:
* Windows' CMD (Win2k3 / Win7-10) values are as follows:
* CMDEXTVERSION Type: 0x32 / 0x34
* ERRORLEVEL Type: 0x33 / 0x35
* DEFINED Type: 0x34 / 0x36
* EXIST Type: 0x35 / 0x37
* == Type: 0x37 / 0x39 (String Comparison)
*
* For the following command:
* NOT Type: 0x36 / 0x38
* Windows only prints it without any type / redirection.
*
* For the following command:
* EQU, NEQ, etc. Type: 0x38 / 0x3a (Generic Comparison)
* Windows displays it as command of unknown type.
*/
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutPrintf(_T("Cmd: %s Type: %x"),
(Cmd->If.Operator <= IF_MAX_UNARY) ?
IfOperatorString[Cmd->If.Operator] :
Cmd->If.LeftArg,
Cmd->If.Operator);
#else
ConOutPrintf(_T("Cmd: %s Type: %x "),
(Cmd->If.Operator <= IF_MAX_UNARY) ?
IfOperatorString[Cmd->If.Operator] :
Cmd->If.LeftArg,
Cmd->If.Operator);
#endif
/* Arguments */
#ifndef MSCMD_ECHO_COMMAND_COMPAT
ConOutPrintf(_T(" Args: `%s'"), Cmd->If.RightArg);
#else
ConOutPrintf(_T("Args: `%s' "), Cmd->If.RightArg);
#endif
ConOutChar(_T('\n'));
if (Cmd->If.Flags & IFFLAG_NEGATE)
{
SpacePad -= 2;
}
Sub = Cmd->Subcommands;
DumpCommand(Sub, SpacePad);
if (Sub->Next)
{
ConOutPrintf(_T("%*s"), SpacePad - 2, _T(""));
ConOutPuts(_T("else\n"));
DumpCommand(Sub->Next, SpacePad);
}
return;
}
default:
ConOutPrintf(_T("*** Unknown type: %x\n"), Cmd->Type);
break;
}
#undef DUMP
}
/*
* Reconstruct a parse tree into text form; used for echoing
* batch file commands and FOR instances.
*/
VOID
[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
EchoCommand(
IN PARSED_COMMAND* Cmd)
{
[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* Sub;
REDIRECTION* Redir;
if (!Cmd)
return;
switch (Cmd->Type)
{
case C_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
case C_REM:
{
if (SubstituteForVars(Cmd->Command.First, TempBuf))
ConOutPrintf(_T("%s"), TempBuf);
if (SubstituteForVars(Cmd->Command.Rest, TempBuf))
{
ConOutPrintf(_T("%s"), TempBuf);
#ifdef MSCMD_ECHO_COMMAND_COMPAT
/* NOTE: For Windows compatibility, add a trailing space after printing the command parameter, if present */
if (*TempBuf) ConOutChar(_T(' '));
#endif
}
break;
}
case C_QUIET:
return;
case C_BLOCK:
{
BOOLEAN bIsFirstCmdCRLF;
ConOutChar(_T('('));
Sub = Cmd->Subcommands;
bIsFirstCmdCRLF = (Sub && Sub->Next);
#if defined(MSCMD_ECHO_COMMAND_COMPAT) && defined(MSCMD_PARSER_BUGS)
/*
* We will emulate Windows' CMD handling of "CRLF" and "&" multi-command
* enumeration within parenthesized command blocks.
*/
bIsFirstCmdCRLF = bIsFirstCmdCRLF && (Sub->Type != C_MULTI);
#endif
/*
* Single-command block: display all on one line.
* Multi-command block: display commands on separate lines.
*/
if (bIsFirstCmdCRLF)
ConOutChar(_T('\n'));
for (; Sub; Sub = Sub->Next)
{
EchoCommand(Sub);
if (Sub->Next)
#ifdef MSCMD_ECHO_COMMAND_COMPAT
ConOutPuts(_T(" \n "));
#else
ConOutChar(_T('\n'));
#endif
}
if (bIsFirstCmdCRLF)
ConOutChar(_T('\n'));
#ifdef MSCMD_ECHO_COMMAND_COMPAT
/* NOTE: For Windows compatibility, add a trailing space after printing the closing parenthesis */
ConOutPuts(_T(") "));
#else
ConOutChar(_T(')'));
#endif
break;
}
case C_MULTI:
case C_OR:
case C_AND:
case C_PIPE:
{
Sub = Cmd->Subcommands;
EchoCommand(Sub);
ConOutPrintf(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
EchoCommand(Sub->Next);
break;
}
[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
case C_FOR:
{
ConOutPuts(_T("for"));
if (Cmd->For.Switches & FOR_DIRS) ConOutPuts(_T(" /D"));
if (Cmd->For.Switches & FOR_F) ConOutPuts(_T(" /F"));
if (Cmd->For.Switches & FOR_LOOP) ConOutPuts(_T(" /L"));
if (Cmd->For.Switches & FOR_RECURSIVE) ConOutPuts(_T(" /R"));
if (Cmd->For.Params)
ConOutPrintf(_T(" %s"), Cmd->For.Params);
if (Cmd->For.List && SubstituteForVars(Cmd->For.List, TempBuf))
ConOutPrintf(_T(" %%%c in (%s) do "), Cmd->For.Variable, TempBuf);
else
ConOutPrintf(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List);
EchoCommand(Cmd->Subcommands);
break;
}
case C_IF:
{
ConOutPuts(_T("if"));
if (Cmd->If.Flags & IFFLAG_IGNORECASE)
ConOutPuts(_T(" /I"));
if (Cmd->If.Flags & IFFLAG_NEGATE)
ConOutPuts(_T(" not"));
if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, TempBuf))
ConOutPrintf(_T(" %s"), TempBuf);
ConOutPrintf(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
if (SubstituteForVars(Cmd->If.RightArg, TempBuf))
ConOutPrintf(_T(" %s "), TempBuf);
Sub = Cmd->Subcommands;
EchoCommand(Sub);
if (Sub->Next)
{
ConOutPuts(_T(" else "));
EchoCommand(Sub->Next);
}
break;
}
default:
ASSERT(FALSE);
break;
}
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
{
if (SubstituteForVars(Redir->Filename, TempBuf))
{
#ifdef MSCMD_ECHO_COMMAND_COMPAT
ConOutPrintf(_T("%c%s%s "),
_T('0') + Redir->Number,
RedirString[Redir->Mode], TempBuf);
#else
ConOutPrintf(_T(" %c%s%s"),
_T('0') + Redir->Number,
RedirString[Redir->Mode], TempBuf);
#endif
}
}
}
/*
* "Unparse" a command into a text form suitable for passing to CMD /C.
[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
* Used for pipes. This is basically the same thing as EchoCommand(),
* but writing into a string instead of to standard output.
*/
[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
PTCHAR
UnparseCommand(
IN PARSED_COMMAND* Cmd,
OUT PTCHAR Out,
IN PTCHAR OutEnd)
{
/*
* Since this function has the annoying requirement that it must avoid
* overflowing the supplied buffer, define some helper macros to make
* this less painful.
*/
#define CHAR(Char) \
do { \
if (Out == OutEnd) return NULL; \
*Out++ = Char; \
} while (0)
#define STRING(String) \
do { \
if (Out + _tcslen(String) > OutEnd) return NULL; \
Out = _stpcpy(Out, String); \
} while (0)
#define PRINTF(Format, ...) \
do { \
UINT Len = _sntprintf(Out, OutEnd - Out, Format, __VA_ARGS__); \
if (Len > (UINT)(OutEnd - Out)) return NULL; \
Out += Len; \
} while (0)
#define RECURSE(Subcommand) \
do { \
[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
Out = UnparseCommand(Subcommand, Out, OutEnd); \
if (!Out) return NULL; \
} while (0)
[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* Sub;
REDIRECTION* Redir;
if (!Cmd)
return Out;
switch (Cmd->Type)
{
case C_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
case C_REM:
{
/* This is fragile since there could be special characters, but
* Windows doesn't bother escaping them, so for compatibility
* we probably shouldn't do it either */
if (!SubstituteForVars(Cmd->Command.First, TempBuf)) return NULL;
STRING(TempBuf);
if (!SubstituteForVars(Cmd->Command.Rest, TempBuf)) return NULL;
STRING(TempBuf);
break;
[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
}
case C_QUIET:
[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
{
CHAR(_T('@'));
RECURSE(Cmd->Subcommands);
break;
[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
}
case C_BLOCK:
[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
{
CHAR(_T('('));
for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
{
RECURSE(Sub);
if (Sub->Next)
CHAR(_T('&'));
}
CHAR(_T(')'));
break;
[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
}
case C_MULTI:
case C_OR:
case C_AND:
case C_PIPE:
[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
{
Sub = Cmd->Subcommands;
RECURSE(Sub);
PRINTF(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
RECURSE(Sub->Next);
break;
[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
}
case C_FOR:
{
STRING(_T("for"));
if (Cmd->For.Switches & FOR_DIRS) STRING(_T(" /D"));
if (Cmd->For.Switches & FOR_F) STRING(_T(" /F"));
if (Cmd->For.Switches & FOR_LOOP) STRING(_T(" /L"));
if (Cmd->For.Switches & FOR_RECURSIVE) STRING(_T(" /R"));
if (Cmd->For.Params)
PRINTF(_T(" %s"), Cmd->For.Params);
if (Cmd->For.List && SubstituteForVars(Cmd->For.List, TempBuf))
PRINTF(_T(" %%%c in (%s) do "), Cmd->For.Variable, TempBuf);
else
PRINTF(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List);
RECURSE(Cmd->Subcommands);
break;
}
case C_IF:
[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
{
STRING(_T("if"));
if (Cmd->If.Flags & IFFLAG_IGNORECASE)
STRING(_T(" /I"));
if (Cmd->If.Flags & IFFLAG_NEGATE)
STRING(_T(" not"));
if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, TempBuf))
PRINTF(_T(" %s"), TempBuf);
PRINTF(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
if (!SubstituteForVars(Cmd->If.RightArg, TempBuf)) return NULL;
PRINTF(_T(" %s "), TempBuf);
Sub = Cmd->Subcommands;
RECURSE(Sub);
if (Sub->Next)
{
STRING(_T(" else "));
RECURSE(Sub->Next);
}
break;
[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
}
default:
ASSERT(FALSE);
break;
}
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
{
if (!SubstituteForVars(Redir->Filename, TempBuf))
return NULL;
PRINTF(_T(" %c%s%s"), _T('0') + Redir->Number,
RedirString[Redir->Mode], TempBuf);
}
return Out;
#undef CHAR
#undef STRING
#undef PRINTF
#undef RECURSE
}