mirror of
https://github.com/reactos/reactos.git
synced 2025-01-05 19:23:50 +08:00
[CMD] Make the command echoer Windows-CMD-compatible. CORE-14025
Add a MSCMD_ECHO_COMMAND_COMPAT define to be able to switch back to our older but less broken behaviour at compile-time. - Append a trailing space to commands when those have a parameter, as well as after a command-block closing parenthesis. - Space around redirection strings need to be switched around.
This commit is contained in:
parent
47ea3f1faa
commit
26cfadc352
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
|
/* Enable this define for "buggy" Windows' CMD command echoer compatibility */
|
||||||
|
#define MSCMD_ECHO_COMMAND_COMPAT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parser debugging support. These flags are global so that their values can be
|
* 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'
|
* modified at runtime from a debugger. They correspond to the public Windows'
|
||||||
@ -1127,48 +1130,85 @@ EchoCommand(PARSED_COMMAND *Cmd)
|
|||||||
switch (Cmd->Type)
|
switch (Cmd->Type)
|
||||||
{
|
{
|
||||||
case C_COMMAND:
|
case C_COMMAND:
|
||||||
|
{
|
||||||
if (SubstituteForVars(Cmd->Command.First, Buf))
|
if (SubstituteForVars(Cmd->Command.First, Buf))
|
||||||
ConOutPrintf(_T("%s"), Buf);
|
ConOutPrintf(_T("%s"), Buf);
|
||||||
if (SubstituteForVars(Cmd->Command.Rest, Buf))
|
if (SubstituteForVars(Cmd->Command.Rest, Buf))
|
||||||
|
{
|
||||||
ConOutPrintf(_T("%s"), Buf);
|
ConOutPrintf(_T("%s"), Buf);
|
||||||
|
#ifdef MSCMD_ECHO_COMMAND_COMPAT
|
||||||
|
/* NOTE: For Windows compatibility, add a trailing space after printing the command parameter, if present */
|
||||||
|
if (*Buf) ConOutChar(_T(' '));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case C_QUIET:
|
case C_QUIET:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case C_BLOCK:
|
case C_BLOCK:
|
||||||
|
{
|
||||||
|
BOOLEAN bIsFirstCmdCRLF;
|
||||||
|
|
||||||
ConOutChar(_T('('));
|
ConOutChar(_T('('));
|
||||||
|
|
||||||
Sub = Cmd->Subcommands;
|
Sub = Cmd->Subcommands;
|
||||||
if (Sub && !Sub->Next)
|
|
||||||
{
|
bIsFirstCmdCRLF = (Sub && Sub->Next);
|
||||||
/* Single-command block: display all on one line */
|
|
||||||
EchoCommand(Sub);
|
#if defined(MSCMD_ECHO_COMMAND_COMPAT) && defined(MSCMD_PARSER_BUGS)
|
||||||
}
|
/*
|
||||||
else if (Sub)
|
* We will emulate Windows' CMD handling of "CRLF" and "&" multi-command
|
||||||
{
|
* enumeration within parenthesized command blocks.
|
||||||
/* Multi-command block: display parenthesis on separate lines */
|
*/
|
||||||
|
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'));
|
ConOutChar(_T('\n'));
|
||||||
do
|
|
||||||
{
|
for (; Sub; Sub = Sub->Next)
|
||||||
EchoCommand(Sub);
|
{
|
||||||
|
EchoCommand(Sub);
|
||||||
|
if (Sub->Next)
|
||||||
|
#ifdef MSCMD_ECHO_COMMAND_COMPAT
|
||||||
|
ConOutPuts(_T(" \n "));
|
||||||
|
#else
|
||||||
ConOutChar(_T('\n'));
|
ConOutChar(_T('\n'));
|
||||||
Sub = Sub->Next;
|
#endif
|
||||||
} while (Sub);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(')'));
|
ConOutChar(_T(')'));
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case C_MULTI:
|
case C_MULTI:
|
||||||
case C_OR:
|
case C_OR:
|
||||||
case C_AND:
|
case C_AND:
|
||||||
case C_PIPE:
|
case C_PIPE:
|
||||||
|
{
|
||||||
Sub = Cmd->Subcommands;
|
Sub = Cmd->Subcommands;
|
||||||
EchoCommand(Sub);
|
EchoCommand(Sub);
|
||||||
ConOutPrintf(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
|
ConOutPrintf(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
|
||||||
EchoCommand(Sub->Next);
|
EchoCommand(Sub->Next);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case C_IF:
|
case C_IF:
|
||||||
|
{
|
||||||
ConOutPuts(_T("if"));
|
ConOutPuts(_T("if"));
|
||||||
if (Cmd->If.Flags & IFFLAG_IGNORECASE)
|
if (Cmd->If.Flags & IFFLAG_IGNORECASE)
|
||||||
ConOutPuts(_T(" /I"));
|
ConOutPuts(_T(" /I"));
|
||||||
@ -1187,8 +1227,10 @@ EchoCommand(PARSED_COMMAND *Cmd)
|
|||||||
EchoCommand(Sub->Next);
|
EchoCommand(Sub->Next);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case C_FOR:
|
case C_FOR:
|
||||||
|
{
|
||||||
ConOutPuts(_T("for"));
|
ConOutPuts(_T("for"));
|
||||||
if (Cmd->For.Switches & FOR_DIRS) ConOutPuts(_T(" /D"));
|
if (Cmd->For.Switches & FOR_DIRS) ConOutPuts(_T(" /D"));
|
||||||
if (Cmd->For.Switches & FOR_F) ConOutPuts(_T(" /F"));
|
if (Cmd->For.Switches & FOR_F) ConOutPuts(_T(" /F"));
|
||||||
@ -1204,12 +1246,24 @@ EchoCommand(PARSED_COMMAND *Cmd)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
|
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
|
||||||
{
|
{
|
||||||
if (SubstituteForVars(Redir->Filename, Buf))
|
if (SubstituteForVars(Redir->Filename, Buf))
|
||||||
{
|
{
|
||||||
ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
|
#ifdef MSCMD_ECHO_COMMAND_COMPAT
|
||||||
|
ConOutPrintf(_T("%c%s%s "),
|
||||||
|
_T('0') + Redir->Number,
|
||||||
RedirString[Redir->Mode], Buf);
|
RedirString[Redir->Mode], Buf);
|
||||||
|
#else
|
||||||
|
ConOutPrintf(_T(" %c%s%s"),
|
||||||
|
_T('0') + Redir->Number,
|
||||||
|
RedirString[Redir->Mode], Buf);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1325,6 +1379,10 @@ do { \
|
|||||||
PRINTF(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List);
|
PRINTF(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List);
|
||||||
RECURSE(Cmd->Subcommands);
|
RECURSE(Cmd->Subcommands);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSERT(FALSE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
|
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
|
||||||
@ -1335,6 +1393,11 @@ do { \
|
|||||||
RedirString[Redir->Mode], Buf);
|
RedirString[Redir->Mode], Buf);
|
||||||
}
|
}
|
||||||
return Out;
|
return Out;
|
||||||
|
|
||||||
|
#undef CHAR
|
||||||
|
#undef STRING
|
||||||
|
#undef PRINTF
|
||||||
|
#undef RECURSE
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
Loading…
Reference in New Issue
Block a user