[PATCH 5/5] cmd: fix parameter parsing of quotes and special chars

Martin Wilck mwilck at arcor.de
Mon Aug 29 17:34:34 CDT 2011


This patch applies the same logic of changes to WCMD_parameter()
that the previous two patches made to WCMD_parse(). In a perfect world
these two functions would be replaced by a single generic one.

This patch fixes all remaining TODOs in the added test code, and a few
TODOs in test_builtins.cmd.exp as well.
---
 programs/cmd/batch.c                     |   89 +++++++++++++++++++-----------
 programs/cmd/tests/test_builtins.cmd.exp |    8 +-
 programs/cmd/tests/test_parsing.cmd.exp  |   18 +++---
 3 files changed, 69 insertions(+), 46 deletions(-)

diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index f010f28..f90258e 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -50,6 +50,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, int called, WCHAR *startLabel, HAN
   HANDLE h = INVALID_HANDLE_VALUE;
   BATCH_CONTEXT *prev_context;
 
+  WINE_TRACE("command on entry:%s\n", wine_dbgstr_w(command));
   if (startLabel == NULL) {
     h = CreateFileW (file, GENERIC_READ, FILE_SHARE_READ,
                      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -127,52 +128,74 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) {
   static WCHAR param[MAX_PATH];
   WCHAR *p;
 
-  if (where != NULL) *where = NULL;
+  WINE_TRACE("param %d in %s\n", n, wine_dbgstr_w(s));
   p = param;
+  while ((*s == ' ') || (*s == '\t'))
+    s++;
+  if (where != NULL) {
+    if (i == 0)
+      *where = s;
+    else 
+      *where = NULL;
+  }
+  WINE_TRACE("start %d %s\n", i, wine_dbgstr_w(s));
   while (TRUE) {
     switch (*s) {
-      case ' ': /* Skip leading spaces */
-      case '\t': /* Treat tabs as spaces */
-	s++;
-	break;
+      case '\0':
+	*p = '\0';
+	if (where != NULL && param == p)
+	  *where = NULL;
+	WINE_TRACE("return1 %s at %s, i=%d, %s\n",  wine_dbgstr_w(param), wine_dbgstr_w(s),  
+		   i, where ? wine_dbgstr_w(*where) : NULL);
+        return param;
       case '"':
-        if (where != NULL && i==n) *where = s;
-	s++;
+	if (i == 0)
+	  s++;
+	else
+	  *p++ = *s++;
 	while ((*s != '\0') && (*s != '"')) {
 	  *p++ = *s++;
 	}
-        if (i == n) {
-          *p = '\0';
-          return param;
-        }
-	if (*s == '"') s++;
-          param[0] = '\0';
-          i++;
-        p = param;
-	break;
+        if (*s == '\0')
+	  break;
+	if (i == 0)
+	  s++;
+	else
+	  *p++ = *s++;
+	/* closing quote - parameter ends only if followed by whitespace */
+	/* fall through to default case */
       /* The code to handle bracketed parms is removed because it should no longer
          be necessary after the multiline support has been added and the for loop
          set of data is now parseable individually. */
-      case '\0':
-        return param;
       default:
-        /* Only return where if it is for the right parameter */
-        if (where != NULL && i==n) *where = s;
-	while ((*s != '\0') && (*s != ' ') && (*s != ',') && (*s != '=') && (*s != '\t')) {
+	while ((*s != '\0') && (*s != ' ') && (*s != ',') && (*s != '=') && (*s != '\t')
+	       && (*s != '"') && (*s != ';') && (*s != '(' || i > 0)) {
 	  *p++ = *s++;
 	}
-        if (i == n && (p!=param)) {
-          *p = '\0';
-          return param;
-        }
-        /* Skip double delimiters, eg. dir a.a,,,,,b.b */
-        if (p != param) {
-          param[0] = '\0';
-          i++;
-        } else {
-          s++; /* Skip delimiter */
-        }
-        p = param;
+	if (*s == '"')
+	    /* new opening quote - go back to '"' case */
+	    break;
+
+	/* Parameter end encountered */
+	if (i == n) {
+	  *p = '\0';
+	  WINE_TRACE("return %s at %s, %p\n",  wine_dbgstr_w(param), wine_dbgstr_w(s),
+		     where ? *where : NULL);
+	  return param;
+	}
+
+        /* Skip concurrent parms */
+	while ((*s == ' ') || (*s == '\t') || (*s == '=')  || (*s == ',') 
+	       || (*s == ';'))
+	  s++;
+
+	i++;
+	p = param;
+	*p = '\0';
+	if (where != NULL && i == n)
+	  *where = s;
+	WINE_TRACE("next %d %s\n", i, wine_dbgstr_w(s));
+	break;
     }
   }
 }
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 5c545ed..90c307f 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -659,15 +659,15 @@ foo at space@
 foo 8
 foo at space@@space@
 foo bar at space@
- at todo_wine@foo ""@space@
- at todo_wine@"" bar at space@
+foo ""@space@
+"" bar at space@
 foo ''@space@
 '' bar at space@
 bar :testRoutine
 foo at space@
 foo bar
- at todo_wine@foo ""
- at todo_wine@"" bar
+foo ""
+"" bar
 foo ''
 '' bar
 @todo_wine at 0
diff --git a/programs/cmd/tests/test_parsing.cmd.exp b/programs/cmd/tests/test_parsing.cmd.exp
index 9ecd793..d2325b1 100644
--- a/programs/cmd/tests/test_parsing.cmd.exp
+++ b/programs/cmd/tests/test_parsing.cmd.exp
@@ -66,12 +66,12 @@ good
 1:1,2:@space@
 1:(1),2:@space@
 1:1(2),2:@space@
- at todo_wine@1:(1),2:@space@
- at todo_wine@1:((1)),2:@space@
- at todo_wine@1:(1)(2),2:@space@
- at todo_wine@1:(1),2:(2)@space@
- at todo_wine@1:1,2:2 at space@
- at todo_wine@1:1,2:2 at space@
- at todo_wine@1:1,2:2 at space@
- at todo_wine@1:"p at space@"1,2:p"@space@"2 at space@
- at todo_wine@1:p"1 at space@p",2:2 at space@
+1:(1),2:@space@
+1:((1)),2:@space@
+1:(1)(2),2:@space@
+1:(1),2:(2)@space@
+1:1,2:2 at space@
+1:1,2:2 at space@
+1:1,2:2 at space@
+1:"p at space@"1,2:p"@space@"2 at space@
+1:p"1 at space@p",2:2 at space@
-- 
1.7.3.4



More information about the wine-patches mailing list