- Begin writing a real parser for cmd. &, &&, ||, and () are implemented. The parenthesized blocks aren't too useful yet as the parser can't read additional lines; doing this will require some restructuring in cmd.c.

- Remove ^-removing hacks in echo and set.

svn path=/trunk/; revision=35514
This commit is contained in:
Jeffrey Morlan 2008-08-21 20:18:35 +00:00
parent 07912f2b23
commit 4cdc27c1a2
7 changed files with 550 additions and 229 deletions

View file

@ -323,7 +323,7 @@ static BOOL RunFile(LPTSTR filename)
* Rest - rest of command line
*/
static VOID
static BOOL
Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
{
TCHAR *szFullName=NULL;
@ -345,7 +345,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
{
error_out_of_memory();
nErrorLevel = 1;
return ;
return FALSE;
}
rest = cmd_alloc ( (_tcslen(Rest) + 512) * sizeof(TCHAR));
@ -354,7 +354,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
cmd_free (first);
error_out_of_memory();
nErrorLevel = 1;
return ;
return FALSE;
}
full = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
@ -364,7 +364,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
cmd_free (rest);
error_out_of_memory();
nErrorLevel = 1;
return ;
return FALSE;
}
szFullName = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
@ -375,7 +375,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
cmd_free (full);
error_out_of_memory();
nErrorLevel = 1;
return ;
return FALSE;
}
@ -446,7 +446,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
cmd_free (full);
cmd_free (szFullName);
nErrorLevel = 1;
return;
return working;
}
/* get the PATH environment variable and parse it */
@ -459,7 +459,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
cmd_free (full);
cmd_free (szFullName);
nErrorLevel = 1;
return;
return FALSE;
}
@ -554,6 +554,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
cmd_free(rest);
cmd_free(full);
cmd_free (szFullName);
return nErrorLevel == 0;
}
@ -566,7 +567,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
*
*/
VOID
BOOL
DoCommand (LPTSTR line)
{
TCHAR *com = NULL; /* the first word in the command */
@ -575,6 +576,7 @@ DoCommand (LPTSTR line)
LPTSTR rest; /* pointer to the rest of the command line */
INT cl;
LPCOMMAND cmdptr;
BOOL ret = TRUE;
TRACE ("DoCommand: (\'%s\')\n", debugstr_aw(line));
@ -582,7 +584,7 @@ DoCommand (LPTSTR line)
if (com == NULL)
{
error_out_of_memory();
return;
return FALSE;
}
cp = com;
@ -640,7 +642,7 @@ DoCommand (LPTSTR line)
/* If end of table execute ext cmd */
if (cmdptr->name == NULL)
{
Execute (line, com, rest);
ret = Execute (line, com, rest);
break;
}
@ -677,6 +679,7 @@ DoCommand (LPTSTR line)
}
}
cmd_free(com);
return ret;
}
@ -687,25 +690,28 @@ DoCommand (LPTSTR line)
VOID ParseCommandLine (LPTSTR cmd)
{
TCHAR cmdline[CMDLINE_LENGTH];
LPTSTR s;
PARSED_COMMAND *Cmd = ParseCommand(cmd);
if (Cmd)
{
ExecuteCommand(Cmd);
FreeCommand(Cmd);
}
}
static VOID
ExecutePipeline(PARSED_COMMAND *Cmd)
{
#ifdef FEATURE_REDIRECTION
REDIRECTION *RedirList = NULL;
TCHAR szTempPath[MAX_PATH] = _T(".\\");
TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")};
HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
INT num = 0;
INT Length;
UINT Attributes;
BOOL bNewBatch = TRUE;
HANDLE hOldConIn;
HANDLE hOldConOut;
#endif /* FEATURE_REDIRECTION */
_tcscpy (cmdline, cmd);
s = &cmdline[0];
TRACE ("ParseCommandLine: (\'%s\')\n", debugstr_aw(s));
//TRACE ("ParseCommandLine: (\'%s\')\n", debugstr_aw(s));
#ifdef FEATURE_REDIRECTION
/* find the temp path to store temporary files */
@ -726,15 +732,6 @@ VOID ParseCommandLine (LPTSTR cmd)
if (szTempPath[_tcslen (szTempPath) - 1] != _T('\\'))
_tcscat (szTempPath, _T("\\"));
/* get the redirections from the command line */
num = GetRedirection (s, &RedirList);
if (!PerformRedirection(RedirList))
{
FreeRedirection(RedirList);
return;
}
/* Set up the initial conditions ... */
/* preserve STDIN and STDOUT handles */
hOldConIn = GetStdHandle (STD_INPUT_HANDLE);
@ -744,7 +741,7 @@ VOID ParseCommandLine (LPTSTR cmd)
*szFileName[0] = _T('\0');
hFile[0] = INVALID_HANDLE_VALUE;
while (num-- > 1)
while (Cmd->Type == C_PIPE)
{
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
@ -766,7 +763,7 @@ VOID ParseCommandLine (LPTSTR cmd)
SetStdHandle (STD_OUTPUT_HANDLE, hFile[1]);
DoCommand (s);
ExecuteCommand(Cmd->Subcommands);
/* close stdout file */
SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
@ -799,22 +796,18 @@ VOID ParseCommandLine (LPTSTR cmd)
OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
SetStdHandle (STD_INPUT_HANDLE, hFile[0]);
s = s + _tcslen (s) + 1;
Cmd = Cmd->Subcommands->Next;
}
/* Now set up the end conditions... */
SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
if(bc)
bNewBatch = FALSE;
#endif
/* process final command */
DoCommand (s);
ExecuteCommand(Cmd);
#ifdef FEATURE_REDIRECTION
if(bNewBatch && bc)
AddBatchRedirection(&RedirList);
/* close old stdin file */
#if 0 /* buggy implementation */
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
@ -870,12 +863,55 @@ VOID ParseCommandLine (LPTSTR cmd)
}
}
}
UndoRedirection(RedirList, NULL);
FreeRedirection(RedirList);
#endif /* FEATURE_REDIRECTION */
}
BOOL
ExecuteCommand(PARSED_COMMAND *Cmd)
{
BOOL bNewBatch = TRUE;
PARSED_COMMAND *Sub;
BOOL Success = TRUE;
if (!PerformRedirection(Cmd->Redirections))
return FALSE;
switch (Cmd->Type)
{
case C_COMMAND:
if(bc)
bNewBatch = FALSE;
Success = DoCommand(Cmd->CommandLine);
if(bNewBatch && bc)
AddBatchRedirection(&Cmd->Redirections);
break;
case C_QUIET:
case C_BLOCK:
case C_MULTI:
for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
Success = ExecuteCommand(Sub);
break;
case C_IFFAILURE:
case C_IFSUCCESS:
Sub = Cmd->Subcommands;
Success = ExecuteCommand(Sub);
if (Success == (Cmd->Type - C_IFFAILURE))
{
Sub = Sub->Next;
Success = ExecuteCommand(Sub);
}
break;
case C_PIPE:
ExecutePipeline(Cmd);
break;
}
UndoRedirection(Cmd->Redirections, NULL);
return Success;
}
BOOL
GrowIfNecessary_dbg ( UINT needed, LPTSTR* ret, UINT* retlen, const char *file, int line )
{

View file

@ -97,10 +97,12 @@ INT cmd_cls (LPTSTR, LPTSTR);
/* Prototypes for CMD.C */
INT ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len, BOOL bPutSeperator);
VOID ParseCommandLine (LPTSTR);
struct _PARSED_COMMAND;
BOOL ExecuteCommand(struct _PARSED_COMMAND *Cmd);
LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName );
VOID AddBreakHandler (VOID);
VOID RemoveBreakHandler (VOID);
VOID DoCommand (LPTSTR line);
BOOL DoCommand (LPTSTR line);
int cmd_main (int argc, const TCHAR *argv[]);
extern HANDLE CMD_ModuleHandle;
@ -326,6 +328,21 @@ INT cmd_move (LPTSTR, LPTSTR);
INT CommandMsgbox (LPTSTR, LPTSTR);
/* Prototypes from PARSER.C */
enum { C_COMMAND, C_QUIET, C_BLOCK, C_MULTI, C_IFFAILURE, C_IFSUCCESS, C_PIPE };
typedef struct _PARSED_COMMAND
{
struct _PARSED_COMMAND *Subcommands;
struct _PARSED_COMMAND *Next;
struct _REDIRECTION *Redirections;
TCHAR *Tail;
BYTE Type;
TCHAR CommandLine[];
} PARSED_COMMAND;
PARSED_COMMAND *ParseCommand(LPTSTR Line);
VOID FreeCommand(PARSED_COMMAND *Cmd);
/* Prototypes from PATH.C */
INT cmd_path (LPTSTR, LPTSTR);

View file

@ -44,6 +44,7 @@
<file>misc.c</file>
<file>move.c</file>
<file>msgbox.c</file>
<file>parser.c</file>
<file>path.c</file>
<file>pause.c</file>
<file>prompt.c</file>

View file

@ -83,16 +83,6 @@ INT CommandEcho (LPTSTR cmd, LPTSTR param)
}
if (*p1 != _T('\0'))
{
p1 = param;
while (NULL != (p1 = _tcschr(p1, _T('^'))))
{
memmove(p1, p1 + 1, (_tcslen(p1 + 1) + 1) * sizeof(TCHAR));
if (*p1)
{
//skip past the char being escaped
p1++;
}
}
ConOutPuts (param);
}
else

View file

@ -0,0 +1,456 @@
#include <precomp.h>
#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(">>") };
static BOOL IsSeparator(TCHAR Char)
{
/* These three characters act like spaces to the parser */
return _istspace(Char) || (Char && _tcschr(_T(",;="), Char));
}
enum { TOK_END, TOK_NORMAL, TOK_OPERATOR, TOK_REDIRECTION,
TOK_BEGIN_BLOCK, TOK_END_BLOCK };
static BOOL bParseError;
static BOOL bLineContinuations;
static TCHAR ParseLine[CMDLINE_LENGTH];
static TCHAR *ParsePos;
static TCHAR CurChar;
static TCHAR CurrentToken[CMDLINE_LENGTH];
static int CurrentTokenType;
static int InsideBlock;
static TCHAR ParseChar()
{
TCHAR Char;
//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'));
if (!Char)
{
/*if (bLineContinuations)
if (ReadLine(ParseLine, TRUE) && *(ParsePos = ParseLine))
goto restart;*/
}
return CurChar = Char;
}
static void ParseError()
{
if (CurrentTokenType == TOK_END)
ConOutResPuts(STRING_SYNTAX_COMMAND_INCORRECT);
else
ConOutPrintf(_T("%s was unexpected at this time.\n"), CurrentToken);
bParseError = TRUE;
}
/* Yes, cmd has a Lexical Analyzer. Whenever the parser gives an "xxx was
* unexpected at this time." message, it shows what the last token read was */
static int ParseToken(TCHAR ExtraEnd, BOOL PreserveSpace)
{
TCHAR *Out = CurrentToken;
TCHAR Char = CurChar;
int Type;
BOOL bInQuote = FALSE;
if (!PreserveSpace)
{
while (Char != _T('\n') && IsSeparator(Char))
Char = ParseChar();
}
while (Char && Char != _T('\n'))
{
bInQuote ^= (Char == _T('"'));
if (!bInQuote)
{
/* Check for all the myriad ways in which this token
* may be brought to an untimely end. */
if ((Char >= _T('0') && Char <= _T('9') &&
(ParsePos == &ParseLine[1] || IsSeparator(ParsePos[-2]))
&& (*ParsePos == _T('<') || *ParsePos == _T('>')))
|| _tcschr(_T(")&|<>") + (InsideBlock ? 0 : 1), Char)
|| (!PreserveSpace && IsSeparator(Char))
|| (Char == ExtraEnd))
{
break;
}
if (Char == _T('^'))
{
Char = ParseChar();
/* Eat up a \n, allowing line continuation */
if (Char == _T('\n'))
Char = ParseChar();
/* Next character is a forced literal */
}
}
/* FIXME: potential buffer overflow here */
*Out++ = Char;
Char = ParseChar();
}
/* Check if we got at least one character before reaching a special one.
* If so, return them and leave the special for the next call. */
if (Out != CurrentToken)
{
Type = TOK_NORMAL;
}
else if (Char == _T('('))
{
Type = TOK_BEGIN_BLOCK;
*Out++ = Char;
ParseChar();
}
else if (Char == _T(')'))
{
Type = TOK_END_BLOCK;
*Out++ = Char;
ParseChar();
}
else if (Char == _T('&') || Char == _T('|'))
{
Type = TOK_OPERATOR;
*Out++ = Char;
Char = ParseChar();
/* check for && or || */
if (Char == Out[-1])
{
*Out++ = Char;
ParseChar();
}
}
else if ((Char >= _T('0') && Char <= _T('9'))
|| (Char == _T('<') || Char == _T('>')))
{
Type = TOK_REDIRECTION;
if (Char >= _T('0') && Char <= _T('9'))
{
*Out++ = Char;
Char = ParseChar();
}
*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()))
;
if (Char >= _T('0') && Char <= _T('9'))
{
*Out++ = Char;
ParseChar();
}
}
}
else
{
Type = TOK_END;
}
*Out = _T('\0');
return CurrentTokenType = Type;
}
static BOOL ParseRedirection(REDIRECTION **List)
{
TCHAR *Tok = CurrentToken;
BYTE Number;
BYTE RedirType;
REDIRECTION *Redir;
if (*Tok >= _T('0') && *Tok <= _T('9'))
Number = *Tok++ - _T('0');
else
Number = *Tok == _T('<') ? 0 : 1;
if (*Tok++ == _T('<'))
{
RedirType = REDIR_READ;
if (*Tok == _T('<'))
goto fail;
}
else
{
RedirType = REDIR_WRITE;
if (*Tok == _T('>'))
{
RedirType = REDIR_APPEND;
Tok++;
}
}
if (!*Tok)
{
/* The file name was not part of this token, so it'll be the next one */
if (ParseToken(0, FALSE) != 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]));
Redir->Next = NULL;
Redir->OldHandle = INVALID_HANDLE_VALUE;
Redir->Number = Number;
Redir->Type = RedirType;
_tcscpy(Redir->Filename, Tok);
*List = Redir;
return TRUE;
fail:
ParseError();
FreeRedirection(*List);
*List = NULL;
return FALSE;
}
static PARSED_COMMAND *ParseCommandOp(int OpType);
/* Parse a parenthesized block */
static PARSED_COMMAND *ParseBlock(REDIRECTION *RedirList)
{
PARSED_COMMAND *Cmd, *Sub, **NextPtr;
Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
Cmd->Type = C_BLOCK;
Cmd->Next = NULL;
Cmd->Subcommands = NULL;
Cmd->Redirections = RedirList;
/* Read the block contents */
NextPtr = &Cmd->Subcommands;
InsideBlock++;
do
{
Sub = ParseCommandOp(C_OP_LOWEST);
if (Sub)
{
*NextPtr = Sub;
NextPtr = &Sub->Next;
}
else if (bParseError)
{
InsideBlock--;
FreeCommand(Cmd);
return NULL;
}
} while (CurrentTokenType != TOK_END_BLOCK);
InsideBlock--;
/* Process any trailing redirections */
while (ParseToken(0, FALSE) == TOK_REDIRECTION)
{
if (!ParseRedirection(&Cmd->Redirections))
{
FreeCommand(Cmd);
return NULL;
}
}
return Cmd;
}
static PARSED_COMMAND *ParseCommandPart(void)
{
TCHAR ParsedLine[CMDLINE_LENGTH];
TCHAR *Pos;
DWORD TailOffset;
PARSED_COMMAND *Cmd;
REDIRECTION *RedirList = NULL;
int Type;
while (IsSeparator(CurChar))
{
if (CurChar == _T('\n'))
return NULL;
ParseChar();
}
if (!CurChar)
return NULL;
if (CurChar == _T(':'))
{
/* "Ignore" the rest of the line.
* (Line continuations will still be parsed, though.) */
while (ParseToken(0, TRUE) != TOK_END)
;
return NULL;
}
if (CurChar == _T('@'))
{
ParseChar();
Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
Cmd->Type = C_QUIET;
Cmd->Next = NULL;
/* @ acts like a unary operator with low precedence,
* so call the top-level parser */
Cmd->Subcommands = ParseCommandOp(C_OP_LOWEST);
Cmd->Redirections = NULL;
return Cmd;
}
/* Get the head of the command */
while (1)
{
Type = ParseToken(_T('('), FALSE);
if (Type == TOK_NORMAL)
{
Pos = _stpcpy(ParsedLine, CurrentToken);
break;
}
else if (Type == TOK_REDIRECTION)
{
if (!ParseRedirection(&RedirList))
return NULL;
}
else if (Type == TOK_BEGIN_BLOCK)
{
return ParseBlock(RedirList);
}
else
{
ParseError();
FreeRedirection(RedirList);
return NULL;
}
}
TailOffset = Pos - ParsedLine;
/* FIXME: FOR, IF, and REM need special processing by the parser. */
/* Now get the tail */
while (1)
{
Type = ParseToken(0, TRUE);
if (Type == TOK_NORMAL)
{
/* FIXME: potential buffer overflow here */
Pos = _stpcpy(Pos, CurrentToken);
}
else if (Type == TOK_REDIRECTION)
{
if (!ParseRedirection(&RedirList))
return NULL;
}
else
{
break;
}
}
Cmd = cmd_alloc(FIELD_OFFSET(PARSED_COMMAND, CommandLine[Pos + 1 - ParsedLine]));
Cmd->Type = C_COMMAND;
Cmd->Next = NULL;
Cmd->Subcommands = NULL;
Cmd->Redirections = RedirList;
_tcscpy(Cmd->CommandLine, ParsedLine);
Cmd->Tail = Cmd->CommandLine + TailOffset;
return Cmd;
}
static PARSED_COMMAND *ParseCommandOp(int OpType)
{
PARSED_COMMAND *Cmd, *Left, *Right;
if (OpType == C_OP_HIGHEST)
Cmd = ParseCommandPart();
else
Cmd = ParseCommandOp(OpType + 1);
if (Cmd && !_tcscmp(CurrentToken, OpString[OpType - C_OP_LOWEST]))
{
Left = Cmd;
Right = ParseCommandOp(OpType);
if (!Right)
{
if (!bParseError)
{
/* & is allowed to have an empty RHS */
if (OpType == C_MULTI)
return Left;
ParseError();
}
FreeCommand(Left);
return NULL;
}
Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
Cmd->Type = OpType;
Cmd->Next = NULL;
Cmd->Redirections = NULL;
Cmd->Subcommands = Left;
Left->Next = Right;
Right->Next = NULL;
}
return Cmd;
}
PARSED_COMMAND *
ParseCommand(LPTSTR Line)
{
PARSED_COMMAND *Cmd;
if (Line)
{
_tcscpy(ParseLine, Line);
bLineContinuations = FALSE;
}
else
{
/*if (!ReadLine(ParseLine, FALSE))*/
return NULL;
bLineContinuations = TRUE;
}
bParseError = FALSE;
ParsePos = ParseLine;
CurChar = _T(' ');
Cmd = ParseCommandOp(C_OP_LOWEST);
if (Cmd && CurrentTokenType != TOK_END)
{
ParseError();
FreeCommand(Cmd);
Cmd = NULL;
}
return Cmd;
}
VOID
FreeCommand(PARSED_COMMAND *Cmd)
{
if (Cmd->Subcommands)
FreeCommand(Cmd->Subcommands);
if (Cmd->Next)
FreeCommand(Cmd->Next);
FreeRedirection(Cmd->Redirections);
cmd_free(Cmd);
}

View file

@ -30,175 +30,6 @@
#ifdef FEATURE_REDIRECTION
static BOOL
IsRedirection (TCHAR c)
{
return (c == _T('<')) || (c == _T('>')) || (c == _T('|'));
}
/*
* Gets the redirection info from the command line and copies the
* file names into ifn, ofn and efn removing them from the command
* line.
*
* Converts remaining command line into a series of null terminated
* strings defined by the pipe char '|'. Each string corresponds
* to a single executable command. A double null terminates the
* command strings.
*
* Return number of command strings found.
*
*/
INT GetRedirection (LPTSTR s, REDIRECTION **RedirList)
{
INT num = 1;
LPTSTR dp = s;
LPTSTR sp = s;
TCHAR Filename[MAX_PATH];
#ifdef INCLUDE_CMD_REM
TCHAR * line = s;
while (_istspace (*line))
line++;
/*first thing first. check to see if this is "rem" and hope out*/
if(!_tcsncmp (line, _T("rem "), 4))
{
return 1;
}
#endif
/* find and remove all the redirections first */
while (*sp)
{
if (*sp == _T('^'))
{
*dp++ = *sp++;
*dp++ = *sp++;
continue;
}
if ((*sp == _T('"')) || (*sp == _T('\'')))
{
/* No redirects inside quotes */
TCHAR qc = *sp;
do
*dp++ = *sp++;
while (*sp && *sp != qc);
*dp++ = *sp++;
continue;
}
int NumberGiven = (*sp >= _T('0') && *sp <= _T('9')) ? 1 : 0;
if (sp[NumberGiven] == _T('<') || sp[NumberGiven] == _T('>'))
{
BYTE HandleNumber;
BYTE Type;
BOOL bInQuote = FALSE;
TCHAR *fn = Filename;
REDIRECTION *Redir, **ListPtr;
if (NumberGiven)
HandleNumber = *sp++ - _T('0');
else
HandleNumber = *sp == _T('<') ? 0 : 1;
if (*sp == _T('<'))
{
/* input redirection */
Type = REDIR_READ;
sp++;
}
else
{
/* output redirection */
Type = REDIR_WRITE;
sp++;
/* append request ? */
if (*sp == _T('>'))
{
Type = REDIR_APPEND;
sp++;
}
}
while (_istspace(*sp))
sp++;
/* copy file name */
while (*sp && (bInQuote || (!IsRedirection (*sp) && !_istspace (*sp))))
{
bInQuote ^= (*sp == _T('"'));
*fn++ = *sp++;
}
*fn++ = _T('\0');
/* Delete any existing redirection for the same handle number */
ListPtr = RedirList;
while ((Redir = *ListPtr))
{
if (Redir->Number == HandleNumber)
{
*ListPtr = Redir->Next;
cmd_free(Redir);
continue;
}
ListPtr = &Redir->Next;
}
Redir = cmd_alloc(FIELD_OFFSET(REDIRECTION, Filename[fn - Filename]));
Redir->Next = NULL;
Redir->OldHandle = INVALID_HANDLE_VALUE;
Redir->Number = HandleNumber;
Redir->Type = Type;
_tcscpy(Redir->Filename, Filename);
*ListPtr = Redir;
}
else
*dp++ = *sp++;
}
*dp++ = _T('\0');
*dp = _T('\0');
/* now go for the pipes */
sp = s;
while (*sp)
{
if (*sp == _T('^'))
{
sp++;
sp++;
continue;
}
else if ((*sp == _T('"')) || (*sp == _T('\'')))
{
TCHAR qc = *sp;
do
sp++;
while (*sp && *sp != qc);
sp++;
}
else if (*sp == _T('|'))
{
*sp++ = _T('\0');
num++;
}
else
sp++;
}
return num;
}
/* cmd allows redirection of handles numbered 3-9 even though these don't
* correspond to any STD_ constant. */
static HANDLE ExtraHandles[10 - 3];

View file

@ -53,7 +53,6 @@ skip_ws ( LPCTSTR p )
INT cmd_set (LPTSTR cmd, LPTSTR param)
{
INT i;
LPTSTR p;
if ( !_tcsncmp (param, _T("/?"), 2) )
@ -62,15 +61,6 @@ INT cmd_set (LPTSTR cmd, LPTSTR param)
return 0;
}
/* remove escapes */
if ( param[0] ) for ( i = 0; param[i+1]; i++ )
{
if ( param[i] == _T('^') )
{
memmove ( &param[i], &param[i+1], _tcslen(&param[i]) * sizeof(TCHAR) );
}
}
/* if no parameters, show the environment */
if (param[0] == _T('\0'))
{