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=3…
==============================================================================
--- 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=3…
==============================================================================
--- 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?re…
==============================================================================
--- 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);
}
}