[ros-diffs] [jmorlan] 35530: - Extract the line-reading code in ProcessInput to a separate function (ReadLine) that the parser can call. Now line continuations (using ^ at the end of a line) and multi-line parenthesized blocks work. - ReadBatchLine: Don't strip the trailing \n, the parser needs it. Remove handling of :labels and @quiet commands, now done by the parser. - ReadCommand: Add a \n to the line. Move PrintPrompt call out, since the prompt shouldn't be printed for additional lines read in a command beyond the first.

jmorlan at svn.reactos.org jmorlan at svn.reactos.org
Fri Aug 22 16:37:12 CEST 2008


Author: jmorlan
Date: Fri Aug 22 09:37:11 2008
New Revision: 35530

URL: http://svn.reactos.org/svn/reactos?rev=35530&view=rev
Log:
- Extract the line-reading code in ProcessInput to a separate function (ReadLine) that the parser can call. Now line continuations (using ^ at the end of a line) and multi-line parenthesized blocks work.
- ReadBatchLine: Don't strip the trailing \n, the parser needs it. Remove handling of :labels and @quiet commands, now done by the parser.
- ReadCommand: Add a \n to the line. Move PrintPrompt call out, since the prompt shouldn't be printed for additional lines read in a command beyond the first.

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/cmdinput.c
    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=35530&r1=35529&r2=35530&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] Fri Aug 22 09:37:11 2008
@@ -332,10 +332,9 @@
  * Set eflag to 0 if line is not to be echoed else 1
  */
 
-LPTSTR ReadBatchLine (LPBOOL bLocalEcho)
+LPTSTR ReadBatchLine ()
 {
 	LPTSTR first;
-	LPTSTR ip;
 
 	/* No batch */
 	if (bc == NULL)
@@ -428,8 +427,6 @@
 
 			*dp = _T('\0');
 
-			*bLocalEcho = bEcho;
-
 			return textline;
 		}
 
@@ -446,14 +443,7 @@
 		}
 		TRACE ("ReadBatchLine(): textline: \'%s\'\n", debugstr_aw(textline));
 
-		/* Strip leading spaces and trailing space/control chars */
-		for (first = textline; _istspace (*first); first++)
-			;
-
-		for (ip = first + _tcslen (first) - 1; _istspace (*ip) || _istcntrl (*ip); ip--)
-			;
-
-		*++ip = _T('\0');
+		first = textline;
 
 		/* cmd block over multiple lines (..) */
 		if (bc->bCmdBlock >= 0)
@@ -488,22 +478,6 @@
 				}
 		}
 
-		/* ignore labels and empty lines */
-		if (*first == _T(':') || *first == 0)
-			continue;
-
-		if (*first == _T('@'))
-		{
-			/* don't echo this line */
-			do
-				first++;
-			while (_istspace (*first));
-
-			*bLocalEcho = 0;
-		}
-		else
-			*bLocalEcho = bEcho;
-
 		break;
 	}
 

Modified: trunk/reactos/base/shell/cmd/batch.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.h?rev=35530&r1=35529&r2=35530&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] Fri Aug 22 09:37:11 2008
@@ -44,7 +44,7 @@
 LPTSTR BatchParams (LPTSTR, LPTSTR);
 VOID   ExitBatch (LPTSTR);
 BOOL   Batch (LPTSTR, LPTSTR, LPTSTR);
-LPTSTR ReadBatchLine (LPBOOL);
+LPTSTR ReadBatchLine();
 VOID AddBatchRedirection(REDIRECTION **);
 
 #endif /* _BATCH_H_INCLUDED_ */

Modified: trunk/reactos/base/shell/cmd/cmd.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=35530&r1=35529&r2=35530&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] Fri Aug 22 09:37:11 2008
@@ -1239,60 +1239,86 @@
  *
  */
 
+BOOL bNoInteractive;
+BOOL bIsBatch;
+
+BOOL
+ReadLine (TCHAR *commandline, BOOL bMore)
+{
+	TCHAR readline[CMDLINE_LENGTH];
+	LPTSTR ip;
+
+	/* if no batch input then... */
+	if (!(ip = ReadBatchLine()))
+	{
+		if (bNoInteractive)
+		{
+			bExit = TRUE;
+			return FALSE;
+		}
+
+		if (bMore)
+		{
+			ConOutPrintf(_T("More? "));
+		}
+		else
+		{
+			/* JPP 19980807 - if echo off, don't print prompt */
+			if (bEcho)
+				PrintPrompt();
+		}
+
+		ReadCommand (readline, CMDLINE_LENGTH - 1);
+		if (CheckCtrlBreak(BREAK_INPUT))
+		{
+			ConOutPuts(_T("\n"));
+			return FALSE;
+		}
+		ip = readline;
+		bIsBatch = FALSE;
+	}
+	else
+	{
+		bIsBatch = TRUE;
+	}
+
+	if (!SubstituteVars(ip, commandline, _T('%'), bIsBatch))
+		return FALSE;
+
+	/* FIXME: !vars! should be substituted later, after parsing. */
+	if (!SubstituteVars(commandline, readline, _T('!'), bIsBatch))
+		return FALSE;
+	_tcscpy(commandline, readline);
+
+	return TRUE;
+}
+
 static INT
 ProcessInput (BOOL bFlag)
 {
-	TCHAR commandline[CMDLINE_LENGTH];
-	TCHAR readline[CMDLINE_LENGTH];
-	LPTSTR ip;
-	BOOL bEchoThisLine;
-    BOOL bIsBatch;
-
+	PARSED_COMMAND *Cmd;
+
+	bNoInteractive = bFlag;
 	do
 	{
-		/* if no batch input then... */
-		if (!(ip = ReadBatchLine (&bEchoThisLine)))
-		{
-			if (bFlag)
-				return nErrorLevel;
-
-			ReadCommand (readline, CMDLINE_LENGTH);
-			ip = readline;
-			bEchoThisLine = FALSE;
-            bIsBatch = FALSE;
-		}
-        else
-        {
-            bIsBatch = TRUE;
-        }
-
-		/* skip leading blanks */
-		while ( _istspace(*ip) )
-			++ip;
-
-		if (!SubstituteVars(ip, commandline, _T('%'), bIsBatch))
+		Cmd = ParseCommand(NULL);
+		if (!Cmd)
 			continue;
 
 		/* JPP 19980807 */
 		/* Echo batch file line */
-		if (bEchoThisLine)
+		if (bIsBatch && bEcho && Cmd->Type != C_QUIET)
 		{
 			PrintPrompt ();
-			ConOutPuts (commandline);
-		}
-
-		/* FIXME: !vars! should be substituted later, after parsing. */
-		if (!SubstituteVars(commandline, readline, _T('!'), bIsBatch))
-			continue;
-		_tcscpy(commandline, readline);
-
-		if (!CheckCtrlBreak(BREAK_INPUT) && *commandline)
-		{
-			ParseCommandLine (commandline);
-			if (bEcho && !bIgnoreEcho && (!bIsBatch || bEchoThisLine))
-				ConOutChar ('\n');
-			bIgnoreEcho = FALSE;
-		}
+			EchoCommand(Cmd);
+			ConOutChar(_T('\n'));
+		}
+
+		ExecuteCommand(Cmd);
+		if (bEcho && !bIgnoreEcho && (!bIsBatch || Cmd->Type != C_QUIET))
+			ConOutChar ('\n');
+		FreeCommand(Cmd);
+		bIgnoreEcho = FALSE;
 	}
 	while (!bCanExit || !bExit);
 

Modified: trunk/reactos/base/shell/cmd/cmd.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.h?rev=35530&r1=35529&r2=35530&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] Fri Aug 22 09:37:11 2008
@@ -103,6 +103,7 @@
 VOID AddBreakHandler (VOID);
 VOID RemoveBreakHandler (VOID);
 BOOL DoCommand (LPTSTR line);
+BOOL ReadLine(TCHAR *commandline, BOOL bMore);
 int cmd_main (int argc, const TCHAR *argv[]);
 
 extern HANDLE CMD_ModuleHandle;
@@ -340,6 +341,7 @@
 	TCHAR CommandLine[];
 } PARSED_COMMAND;
 PARSED_COMMAND *ParseCommand(LPTSTR Line);
+VOID EchoCommand(PARSED_COMMAND *Cmd);
 VOID FreeCommand(PARSED_COMMAND *Cmd);
 
 

Modified: trunk/reactos/base/shell/cmd/cmdinput.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmdinput.c?rev=35530&r1=35529&r2=35530&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/cmdinput.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmdinput.c [iso-8859-1] Fri Aug 22 09:37:11 2008
@@ -152,10 +152,6 @@
 	/* get screen size */
 	GetScreenSize (&maxx, &maxy);
 
-	/* JPP 19980807 - if echo off, don't print prompt */
-	if (bEcho)
-		PrintPrompt();
-
 	GetCursorXY (&orgx, &orgy);
 	GetCursorXY (&curx, &cury);
 
@@ -431,6 +427,8 @@
 				if (str[0])
 					History (0, str);
 #endif
+				str[charcount++] = _T('\n');
+				str[charcount] = _T('\0');
 				ConInDummy ();
 				ConOutChar (_T('\n'));
 			bReturn = TRUE;

Modified: trunk/reactos/base/shell/cmd/parser.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/parser.c?rev=35530&r1=35529&r2=35530&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/parser.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/parser.c [iso-8859-1] Fri Aug 22 09:37:11 2008
@@ -29,7 +29,10 @@
 {
 	TCHAR Char;
 
-//restart:
+	if (bParseError)
+		return CurChar = 0;
+
+restart:
 	/* Although CRs can be injected into a line via an environment
 	 * variable substitution, the parser ignores them - they won't
 	 * even separate tokens. */
@@ -39,9 +42,19 @@
 
 	if (!Char)
 	{
-		/*if (bLineContinuations)
-			if (ReadLine(ParseLine, TRUE) && *(ParsePos = ParseLine))
-				goto restart;*/
+		ParsePos--;
+		if (bLineContinuations)
+		{
+			if (!ReadLine(ParseLine, TRUE))
+			{
+				/* ^C pressed, or line was too long */
+				bParseError = TRUE;
+			}
+			else if (*(ParsePos = ParseLine))
+			{
+				goto restart;
+			}
+		}
 	}
 	return CurChar = Char;
 }
@@ -96,7 +109,8 @@
 				/* Next character is a forced literal */
 			}
 		}
-		/* FIXME: potential buffer overflow here */
+		if (Out == &CurrentToken[CMDLINE_LENGTH - 1])
+			break;
 		*Out++ = Char;
 		Char = ParseChar();
 	}
@@ -247,7 +261,7 @@
 	/* Read the block contents */
 	NextPtr = &Cmd->Subcommands;
 	InsideBlock++;
-	do
+	while (1)
 	{
 		Sub = ParseCommandOp(C_OP_LOWEST);
 		if (Sub)
@@ -261,7 +275,12 @@
 			FreeCommand(Cmd);
 			return NULL;
 		}
-	} while (CurrentTokenType != TOK_END_BLOCK);
+
+		if (CurrentTokenType == TOK_END_BLOCK)
+			break;
+		/* Skip past the \n */
+		ParseChar();
+	}
 	InsideBlock--;
 
 	/* Process any trailing redirections */
@@ -335,6 +354,10 @@
 		{
 			return ParseBlock(RedirList);
 		}
+		else if (Type == TOK_END_BLOCK && !RedirList)
+		{
+			return NULL;
+		}
 		else
 		{
 			ParseError();
@@ -352,7 +375,12 @@
 		Type = ParseToken(0, TRUE);
 		if (Type == TOK_NORMAL)
 		{
-			/* FIXME: potential buffer overflow here */
+			if (Pos + _tcslen(CurrentToken) >= &ParsedLine[CMDLINE_LENGTH])
+			{
+				ParseError();
+				FreeRedirection(RedirList);
+				return NULL;
+			}
 			Pos = _stpcpy(Pos, CurrentToken);
 		}
 		else if (Type == TOK_REDIRECTION)
@@ -426,7 +454,7 @@
 	}
 	else
 	{
-		/*if (!ReadLine(ParseLine, FALSE))*/
+		if (!ReadLine(ParseLine, FALSE))
 			return NULL;
 		bLineContinuations = TRUE;
 	}
@@ -435,13 +463,59 @@
 	CurChar = _T(' ');
 
 	Cmd = ParseCommandOp(C_OP_LOWEST);
-	if (Cmd && CurrentTokenType != TOK_END)
-	{
-		ParseError();
-		FreeCommand(Cmd);
-		Cmd = NULL;
+	if (Cmd)
+	{
+		if (CurrentTokenType != TOK_END)
+			ParseError();
+		if (bParseError)
+		{
+			FreeCommand(Cmd);
+			Cmd = NULL;
+		}
 	}
 	return Cmd;
+}
+
+/* Reconstruct a parse tree into text form;
+ * used for echoing batch file commands */
+VOID
+EchoCommand(PARSED_COMMAND *Cmd)
+{
+	PARSED_COMMAND *Sub;
+	REDIRECTION *Redir;
+
+	switch (Cmd->Type)
+	{
+	case C_COMMAND:
+		ConOutPrintf(_T("%s"), Cmd->CommandLine);
+		break;
+	case C_QUIET:
+		return;
+	case C_BLOCK:
+		ConOutChar(_T('('));
+		for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
+		{
+			EchoCommand(Sub);
+			ConOutChar(_T('\n'));
+		}
+		ConOutChar(_T(')'));
+		break;
+	case C_MULTI:
+	case C_IFFAILURE:
+	case C_IFSUCCESS:
+	case C_PIPE:
+		Sub = Cmd->Subcommands;
+		EchoCommand(Sub);
+		ConOutPrintf(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
+		EchoCommand(Sub->Next);
+		break;
+	}
+
+	for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
+	{
+		ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
+			RedirString[Redir->Type], Redir->Filename);
+	}
 }
 
 VOID



More information about the Ros-diffs mailing list