Jason Edmeades : cmd: Support for ^ character at end of line.

Alexandre Julliard julliard at winehq.org
Wed Sep 26 14:06:51 CDT 2012


Module: wine
Branch: master
Commit: 2ff533c1f2c6b6054260d7a448126a0d32015a0c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2ff533c1f2c6b6054260d7a448126a0d32015a0c

Author: Jason Edmeades <jason at edmeades.me.uk>
Date:   Tue Sep 25 21:02:09 2012 +0100

cmd: Support for ^ character at end of line.

Based on a patch by John Chow.

---

 programs/cmd/tests/test_builtins.cmd     |    9 +++++
 programs/cmd/tests/test_builtins.cmd.exp |    6 +++
 programs/cmd/wcmdmain.c                  |   52 +++++++++++++++++++++++++----
 3 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index e8ffe53..7c4b37f 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -197,6 +197,15 @@ echo ^hell^o, world
 echo hell^o, world
 echo hell^^o, world
 echo hell^^^o, world
+echo hello^
+world
+echo hello^
+
+world
+echo hello^
+
+
+echo finished
 mkdir foobar
 echo baz> foobar\baz
 type foobar\baz
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index b019280..2888ffc 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -201,6 +201,12 @@ hello, world
 hello, world
 hell^o, world
 hell^o, world
+helloworld
+hello
+world
+hello
+
+finished
 baz
 baz
 foo | echo bar
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index a328f83..b095deb 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -1788,6 +1788,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
     BOOL      lastWasIn   = FALSE;
     BOOL      lastWasElse = FALSE;
     BOOL      lastWasRedirect = TRUE;
+    BOOL      lastWasCaret = FALSE;
 
     /* Allocate working space for a command read from keyboard, file etc */
     if (!extraSpace)
@@ -1856,6 +1857,12 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
                  lastWasWhiteSpace, onlyWhiteSpace);
       */
 
+      /* Prevent overflow caused by the caret escape char*/
+      if (*curLen >= MAXSTRING) {
+        WINE_ERR("Overflow detected in command\n");
+        return NULL;
+      }
+
       /* Certain commands need special handling */
       if (curStringLen == 0 && curCopyTo == curString) {
         static const WCHAR forDO[] = {'d','o'};
@@ -1928,6 +1935,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
       else        thisChar = 'X';  /* Character with no special processing */
 
       lastWasWhiteSpace = FALSE; /* Will be reset below */
+      lastWasCaret = FALSE;
 
       switch (thisChar) {
 
@@ -2070,7 +2078,15 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
                 }
                 break;
 
-      case '^': if (!inQuotes) curPos++;
+      case '^': if (!inQuotes) {
+                  /* If we reach the end of the input, we need to wait for more */
+                  if (*(curPos+1) == 0x00) {
+                    lastWasCaret = TRUE;
+                    WINE_TRACE("Caret found at end of line\n");
+                    break;
+                  }
+                  curPos++;
+                }
                 curCopyTo[(*curLen)++] = *curPos;
                 break;
 
@@ -2147,8 +2163,9 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
         lastWasIn = lastWasDo = FALSE;
       }
 
-      /* If we have reached the end, add this command into the list */
-      if (*curPos == 0x00 && *curLen > 0) {
+      /* If we have reached the end, add this command into the list
+         Do not add command to list if escape char ^ was last */
+      if (*curPos == 0x00 && !lastWasCaret && *curLen > 0) {
 
           /* Add an entry to the command list */
           WCMD_addCommand(curString, &curStringLen,
@@ -2158,19 +2175,38 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
                 &lastEntry, output);
       }
 
-      /* If we have reached the end of the string, see if bracketing outstanding */
-      if (*curPos == 0x00 && curDepth > 0 && readFrom != INVALID_HANDLE_VALUE) {
+      /* If we have reached the end of the string, see if bracketing or
+         final caret is outstanding */
+      if (*curPos == 0x00 && (curDepth > 0 || lastWasCaret) &&
+          readFrom != INVALID_HANDLE_VALUE) {
+        WCHAR *extraData;
+
+        WINE_TRACE("Need to read more data as outstanding brackets or carets\n");
         inRem = FALSE;
         prevDelim = CMD_NONE;
         inQuotes = 0;
         memset(extraSpace, 0x00, (MAXSTRING+1) * sizeof(WCHAR));
+        extraData = extraSpace;
 
         /* Read more, skipping any blank lines */
-        while (*extraSpace == 0x00) {
+        do {
+          WINE_TRACE("Read more input\n");
           if (!context) WCMD_output_asis( WCMD_LoadMessage(WCMD_MOREPROMPT));
-          if (!WCMD_fgets(extraSpace, MAXSTRING, readFrom))
+          if (!WCMD_fgets(extraData, MAXSTRING, readFrom))
             break;
-        }
+
+          /* Edge case for carets - a completely blank line (ie was just
+             CRLF) is oddly added as an LF but then more data is received (but
+             only once more!) */
+          if (lastWasCaret) {
+            if (*extraSpace == 0x00) {
+              WINE_TRACE("Read nothing, so appending LF char and will try again\n");
+              *extraData++ = '\r';
+              *extraData = 0x00;
+            } else break;
+          }
+
+        } while (*extraData == 0x00);
         curPos = extraSpace;
         if (context) handleExpansion(extraSpace, FALSE, NULL, NULL);
         /* Continue to echo commands IF echo is on and in batch program */




More information about the wine-cvs mailing list