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=35... ============================================================================== --- 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=35... ============================================================================== --- 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?r... ============================================================================== --- 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=3... ============================================================================== --- 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?rev... ============================================================================== --- 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=35... ============================================================================== --- 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 */