Author: jmorlan Date: Sun Feb 15 12:18:16 2009 New Revision: 39611
URL: http://svn.reactos.org/svn/reactos?rev=39611&view=rev Log: Don't expand FOR variables until execution time, so that special characters in them won't cause unwanted syntactic effects. For example, "for %a in (^>) do echo %a" should just echo the greater than sign.
Modified: trunk/reactos/base/shell/cmd/batch.c trunk/reactos/base/shell/cmd/batch.h trunk/reactos/base/shell/cmd/cmd.c trunk/reactos/base/shell/cmd/cmd.h trunk/reactos/base/shell/cmd/parser.c
Modified: trunk/reactos/base/shell/cmd/batch.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.c?rev=... ============================================================================== --- trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] Sun Feb 15 12:18:16 2009 @@ -405,19 +405,14 @@ }
/* At this point, fv points to parameter string */ + bc->forvalue = fv; + + /* Double up % signs so they will get through the parser intact */ while (*sp) { - if ((*sp == _T('%')) && (*(sp + 1) == bc->forvar)) - { - /* replace % var */ - dp = _stpcpy (dp, fv); - sp += 2; - } - else - { - /* Else just copy */ - *dp++ = *sp++; - } + if (*sp == _T('%')) + *dp++ = _T('%'); + *dp++ = *sp++; }
*dp++ = _T('\n');
Modified: trunk/reactos/base/shell/cmd/batch.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.h?rev=... ============================================================================== --- trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] Sun Feb 15 12:18:16 2009 @@ -21,6 +21,7 @@ HANDLE hFind; /* Preserve find handle when doing a for */ REDIRECTION *RedirList; TCHAR forvar; + LPTSTR forvalue; } BATCH_CONTEXT, *LPBATCH_CONTEXT;
Modified: trunk/reactos/base/shell/cmd/cmd.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=39... ============================================================================== --- trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] Sun Feb 15 12:18:16 2009 @@ -1261,19 +1261,56 @@ #undef APPEND1 }
+BOOL +SubstituteForVars(TCHAR *Src, TCHAR *Dest) +{ + TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1]; + while (*Src) + { + if (Src[0] == _T('%') && Src[1] != _T('\0')) + { + /* This might be a variable. Search the list of contexts for it */ + BATCH_CONTEXT *Ctx = bc; + while (Ctx && Ctx->forvar != Src[1]) + Ctx = Ctx->prev; + if (Ctx) + { + /* Found it */ + if (Dest + _tcslen(Ctx->forvalue) > DestEnd) + return FALSE; + Dest = _stpcpy(Dest, Ctx->forvalue); + Src += 2; + continue; + } + } + /* Not a variable; just copy the character */ + if (Dest >= DestEnd) + return FALSE; + *Dest++ = *Src++; + } + *Dest = _T('\0'); + return TRUE; +} + LPTSTR DoDelayedExpansion(LPTSTR Line) { - TCHAR Buf[CMDLINE_LENGTH]; - if (!_tcschr(Line, _T('!'))) - return cmd_dup(Line); + TCHAR Buf1[CMDLINE_LENGTH]; + TCHAR Buf2[CMDLINE_LENGTH]; + + /* First, substitute FOR variables */ + if (!SubstituteForVars(Line, Buf1)) + return NULL; + + if (!_tcschr(Buf1, _T('!'))) + return cmd_dup(Buf1);
/* FIXME: Delayed substitutions actually aren't quite the same as * immediate substitutions. In particular, it's possible to escape * the exclamation point using ^. */ - if (!SubstituteVars(Line, Buf, _T('!'))) + if (!SubstituteVars(Buf1, Buf2, _T('!'))) return NULL; - return cmd_dup(Buf); + return cmd_dup(Buf2); }
Modified: trunk/reactos/base/shell/cmd/cmd.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.h?rev=39... ============================================================================== --- trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] Sun Feb 15 12:18:16 2009 @@ -102,6 +102,7 @@ LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName ); VOID AddBreakHandler (VOID); VOID RemoveBreakHandler (VOID); +BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest); LPTSTR DoDelayedExpansion(LPTSTR Line); BOOL DoCommand (LPTSTR line); BOOL ReadLine(TCHAR *commandline, BOOL bMore);
Modified: 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 [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/parser.c [iso-8859-1] Sun Feb 15 12:18:16 2009 @@ -610,18 +610,21 @@ return Cmd; }
-/* Reconstruct a parse tree into text form; - * used for echoing batch file commands */ + +/* Reconstruct a parse tree into text form; used for echoing + * batch file commands and FOR instances. */ VOID EchoCommand(PARSED_COMMAND *Cmd) { + TCHAR Buf[CMDLINE_LENGTH]; PARSED_COMMAND *Sub; REDIRECTION *Redir;
switch (Cmd->Type) { case C_COMMAND: - ConOutPrintf(_T("%s"), Cmd->Command.CommandLine); + if (SubstituteForVars(Cmd->Command.CommandLine, Buf)) + ConOutPrintf(_T("%s"), Buf); break; case C_QUIET: return; @@ -649,9 +652,11 @@ ConOutPrintf(_T(" /I")); if (Cmd->If.Flags & IFFLAG_NEGATE) ConOutPrintf(_T(" not")); - if (Cmd->If.LeftArg) - ConOutPrintf(_T(" %s"), Cmd->If.LeftArg); - ConOutPrintf(_T(" %s %s "), IfOperatorString[Cmd->If.Operator], Cmd->If.RightArg); + if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, Buf)) + ConOutPrintf(_T(" %s"), Buf); + ConOutPrintf(_T(" %s"), IfOperatorString[Cmd->If.Operator]); + if (SubstituteForVars(Cmd->If.RightArg, Buf)) + ConOutPrintf(_T(" %s "), Buf); Sub = Cmd->Subcommands; EchoCommand(Sub); if (Sub->Next) @@ -664,8 +669,9 @@
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next) { - ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number, - RedirString[Redir->Type], Redir->Filename); + if (SubstituteForVars(Redir->Filename, Buf)) + ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number, + RedirString[Redir->Type], Buf); } }