[GRASS-SVN] r65499 - grass/trunk/lib/gis

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jun 18 12:00:27 PDT 2015


Author: glynn
Date: 2015-06-18 12:00:26 -0700 (Thu, 18 Jun 2015)
New Revision: 65499

Modified:
   grass/trunk/lib/gis/token.c
Log:
Fix handling of quotes in G_tokenize() (issue #2692)


Modified: grass/trunk/lib/gis/token.c
===================================================================
--- grass/trunk/lib/gis/token.c	2015-06-18 15:55:51 UTC (rev 65498)
+++ grass/trunk/lib/gis/token.c	2015-06-18 19:00:26 UTC (rev 65499)
@@ -15,6 +15,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <grass/gis.h>
+#include <grass/glocale.h>
 
 static char **tokenize(const char *, const char *, const char *);
 
@@ -89,42 +90,88 @@
 {
     int i;
     char **tokens;
-    char *p;
+    const char *p;
+    char *q;
+    enum {
+	S_START,
+	S_IN_QUOTE,
+	S_AFTER_QUOTE,
+    };
+    enum {
+	A_NO_OP,
+	A_ADD_CHAR,
+	A_NEW_FIELD,
+	A_END_RECORD,
+	A_ERROR
+    };
+    int state;
+    int quo = inchar ? *inchar : -1;
 
     /* do not modify buf, make a copy */
-    p = G_store(buf);
+    p = q = G_store(buf);
 
     i = 0;
     tokens = (char **)G_malloc(2 * sizeof(char *));
 
     /* always one token */
-    tokens[i++] = p;
+    tokens[i++] = q;
 
-    while (TRUE) {
-	/* find next delimiter */
-	while (!strchr(delim, *p)) {
-	    /* opening border ? */
-	    if (inchar && *p == *inchar) {
-		p++;
-		/* find closing border */
-		while (*p != *inchar && *p != 0)
-		    p++;
-		if (*p == 0)
-		    break;
-	    }
-	    p++;
+    for (state = S_START; ; p++) {
+	int c = *p;
+	int action = A_NO_OP;
+	switch (state) {
+	case S_START:
+	    if (c == quo)
+		state = S_IN_QUOTE;
+	    else if (c == '\0')
+		action = A_END_RECORD;
+	    else if (strchr(delim, c))
+		action = A_NEW_FIELD;
+	    else
+		action = A_ADD_CHAR;
+	    break;
+	case S_IN_QUOTE:
+	    if (c == quo)
+		state = S_AFTER_QUOTE;
+	    else if (c == '\0')
+		action = A_ERROR;
+	    else
+		action = A_ADD_CHAR;
+	    break;
+	case S_AFTER_QUOTE:
+	    if (c == quo)
+		state = S_IN_QUOTE, action = A_ADD_CHAR;
+	    else if (c == '\0')
+		action = A_END_RECORD;
+	    else if (strchr(delim, c))
+		state = S_START, action = A_NEW_FIELD;
+	    else
+		action = A_ERROR;
+	    break;
 	}
-	if (*p == 0)
+
+	switch (action) {
+	case A_NO_OP:
 	    break;
-	/* replace delim with '\0' */
-	*p++ = 0;
-	/* set next token */
-	tokens[i++] = p;
-	tokens = (char **)G_realloc((char *)tokens, (i + 1) * sizeof(char *));
+	case A_ADD_CHAR:
+	    *q++ = *p;
+	    break;
+	case A_NEW_FIELD:
+	    *q++ = '\0';
+	    tokens[i++] = q;
+	    tokens = G_realloc(tokens, (i + 2) * sizeof(char *));
+	    break;
+	case A_END_RECORD:
+	    *q++ = '\0';
+	    tokens[i++] = NULL;
+	    return tokens;
+	case A_ERROR:
+	    G_warning(_("parse error"));
+	    *q++ = '\0';
+	    tokens[i++] = NULL;
+	    return tokens;
+	}
     }
-    tokens[i] = NULL;
-
-    return tokens;
 }
 
 /*!



More information about the grass-commit mailing list