Author: jmorlan
Date: Thu Aug 21 15:18:35 2008
New Revision: 35514
URL:
http://svn.reactos.org/svn/reactos?rev=35514&view=rev
Log:
- 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.
Added:
trunk/reactos/base/shell/cmd/parser.c (with props)
Modified:
trunk/reactos/base/shell/cmd/cmd.c
trunk/reactos/base/shell/cmd/cmd.h
trunk/reactos/base/shell/cmd/cmd.rbuild
trunk/reactos/base/shell/cmd/echo.c
trunk/reactos/base/shell/cmd/redir.c
trunk/reactos/base/shell/cmd/set.c
Modified: trunk/reactos/base/shell/cmd/cmd.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=3…
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] Thu Aug 21 15:18:35 2008
@@ -323,7 +323,7 @@
* Rest - rest of command line
*/
-static VOID
+static BOOL
Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
{
TCHAR *szFullName=NULL;
@@ -345,7 +345,7 @@
{
error_out_of_memory();
nErrorLevel = 1;
- return ;
+ return FALSE;
}
rest = cmd_alloc ( (_tcslen(Rest) + 512) * sizeof(TCHAR));
@@ -354,7 +354,7 @@
cmd_free (first);
error_out_of_memory();
nErrorLevel = 1;
- return ;
+ return FALSE;
}
full = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
@@ -364,7 +364,7 @@
cmd_free (rest);
error_out_of_memory();
nErrorLevel = 1;
- return ;
+ return FALSE;
}
szFullName = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
@@ -375,7 +375,7 @@
cmd_free (full);
error_out_of_memory();
nErrorLevel = 1;
- return ;
+ return FALSE;
}
@@ -446,7 +446,7 @@
cmd_free (full);
cmd_free (szFullName);
nErrorLevel = 1;
- return;
+ return working;
}
/* get the PATH environment variable and parse it */
@@ -459,7 +459,7 @@
cmd_free (full);
cmd_free (szFullName);
nErrorLevel = 1;
- return;
+ return FALSE;
}
@@ -554,6 +554,7 @@
cmd_free(rest);
cmd_free(full);
cmd_free (szFullName);
+ return nErrorLevel == 0;
}
@@ -566,7 +567,7 @@
*
*/
-VOID
+BOOL
DoCommand (LPTSTR line)
{
TCHAR *com = NULL; /* the first word in the command */
@@ -575,6 +576,7 @@
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 @@
if (com == NULL)
{
error_out_of_memory();
- return;
+ return FALSE;
}
cp = com;
@@ -640,7 +642,7 @@
/* 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 @@
}
}
cmd_free(com);
+ return ret;
}
@@ -687,25 +690,28 @@
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 @@
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 @@
*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 @@
SetStdHandle (STD_OUTPUT_HANDLE, hFile[1]);
- DoCommand (s);
+ ExecuteCommand(Cmd->Subcommands);
/* close stdout file */
SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
@@ -799,22 +796,18 @@
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,10 +863,53 @@
}
}
}
-
- 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
Modified: trunk/reactos/base/shell/cmd/cmd.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.h?rev=3…
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] Thu Aug 21 15:18:35 2008
@@ -97,10 +97,12 @@
/* 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 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);
Modified: trunk/reactos/base/shell/cmd/cmd.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.rbuild?…
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.rbuild [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.rbuild [iso-8859-1] Thu Aug 21 15:18:35 2008
@@ -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>
Modified: trunk/reactos/base/shell/cmd/echo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/echo.c?rev=…
==============================================================================
--- trunk/reactos/base/shell/cmd/echo.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/echo.c [iso-8859-1] Thu Aug 21 15:18:35 2008
@@ -83,16 +83,6 @@
}
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
Added: trunk/reactos/base/shell/cmd/parser.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/parser.c?re…
==============================================================================
--- trunk/reactos/base/shell/cmd/parser.c (added)
+++ trunk/reactos/base/shell/cmd/parser.c [iso-8859-1] Thu Aug 21 15:18:35 2008
@@ -1,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);
+}
Propchange: trunk/reactos/base/shell/cmd/parser.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/base/shell/cmd/redir.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/redir.c?rev…
==============================================================================
--- trunk/reactos/base/shell/cmd/redir.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/redir.c [iso-8859-1] Thu Aug 21 15:18:35 2008
@@ -29,175 +29,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. */
Modified: trunk/reactos/base/shell/cmd/set.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/set.c?rev=3…
==============================================================================
--- trunk/reactos/base/shell/cmd/set.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/set.c [iso-8859-1] Thu Aug 21 15:18:35 2008
@@ -53,22 +53,12 @@
INT cmd_set (LPTSTR cmd, LPTSTR param)
{
- INT i;
LPTSTR p;
if ( !_tcsncmp (param, _T("/?"), 2) )
{
ConOutResPaging(TRUE,STRING_SET_HELP);
return 0;
- }
-
- /* remove escapes */
- if ( param[0] ) for ( i = 0; param[i+1]; i++ )
- {
- if ( param[i] == _T('^') )
- {
- memmove ( ¶m[i], ¶m[i+1], _tcslen(¶m[i]) * sizeof(TCHAR) );
- }
}
/* if no parameters, show the environment */