Imported Upstream version 0.7.6
[platform/upstream/multipath-tools.git] / libmultipath / parser.c
index c47d891..2f9ab6e 100644 (file)
@@ -33,7 +33,8 @@ static int line_nr;
 int
 keyword_alloc(vector keywords, char *string,
              int (*handler) (struct config *, vector),
-             int (*print) (struct config *, char *, int, void *), int unique)
+             int (*print) (struct config *, char *, int, const void*),
+             int unique)
 {
        struct keyword *keyword;
 
@@ -71,7 +72,8 @@ install_sublevel_end(void)
 int
 _install_keyword(vector keywords, char *string,
                 int (*handler) (struct config *, vector),
-                int (*print) (struct config *, char *, int, void *), int unique)
+                int (*print) (struct config *, char *, int, const void*),
+                int unique)
 {
        int i = 0;
        struct keyword *keyword;
@@ -143,7 +145,8 @@ find_keyword(vector keywords, vector v, char * name)
 }
 
 int
-snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, void *data)
+snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
+               const void *data)
 {
        int r;
        int fwd = 0;
@@ -183,6 +186,12 @@ snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, void *data)
        return fwd;
 }
 
+static const char quote_marker[] = { '\0', '"', '\0' };
+bool is_quote(const char* token)
+{
+       return !memcmp(token, quote_marker, sizeof(quote_marker));
+}
+
 vector
 alloc_strvec(char *string)
 {
@@ -216,19 +225,20 @@ alloc_strvec(char *string)
 
        in_string = 0;
        while (1) {
+               int two_quotes = 0;
+
                if (!vector_alloc_slot(strvec))
                        goto out;
 
                start = cp;
-               if (*cp == '"') {
+               if (*cp == '"' && !(in_string && *(cp + 1) == '"')) {
                        cp++;
-                       token = MALLOC(2);
+                       token = MALLOC(sizeof(quote_marker));
 
                        if (!token)
                                goto out;
 
-                       *(token) = '"';
-                       *(token + 1) = '\0';
+                       memcpy(token, quote_marker, sizeof(quote_marker));
                        if (in_string)
                                in_string = 0;
                        else
@@ -243,11 +253,23 @@ alloc_strvec(char *string)
                        *(token + 1) = '\0';
                        cp++;
                } else {
+
+               move_on:
                        while ((in_string ||
                                (!isspace((int) *cp) && isascii((int) *cp) &&
                                 *cp != '!' && *cp != '#' && *cp != '{' &&
                                 *cp != '}')) && *cp != '\0' && *cp != '"')
                                cp++;
+
+                       /* Two consecutive double quotes - don't end string */
+                       if (in_string && *cp == '"') {
+                               if (*(cp + 1) == '"') {
+                                       two_quotes = 1;
+                                       cp += 2;
+                                       goto move_on;
+                               }
+                       }
+
                        strlen = cp - start;
                        token = MALLOC(strlen + 1);
 
@@ -256,10 +278,21 @@ alloc_strvec(char *string)
 
                        memcpy(token, start, strlen);
                        *(token + strlen) = '\0';
+
+                       /* Replace "" by " */
+                       if (two_quotes) {
+                               char *qq = strstr(token, "\"\"");
+                               while (qq != NULL) {
+                                       memmove(qq + 1, qq + 2,
+                                               strlen + 1 - (qq + 2 - token));
+                                       qq = strstr(qq + 1, "\"\"");
+                               }
+                       }
                }
                vector_set_slot(strvec, token);
 
-               while ((isspace((int) *cp) || !isascii((int) *cp))
+               while ((!in_string &&
+                       (isspace((int) *cp) || !isascii((int) *cp)))
                       && *cp != '\0')
                        cp++;
                if (*cp == '\0' || *cp == '!' || *cp == '#')
@@ -296,13 +329,13 @@ set_value(vector strvec)
                        (char *)VECTOR_SLOT(strvec, 0));
                return NULL;
        }
-       size = strlen(str);
-       if (size == 0) {
-               condlog(0, "option '%s' has empty value",
-                       (char *)VECTOR_SLOT(strvec, 0));
-               return NULL;
-       }
-       if (*str != '"') {
+       if (!is_quote(str)) {
+               size = strlen(str);
+               if (size == 0) {
+                       condlog(0, "option '%s' has empty value",
+                               (char *)VECTOR_SLOT(strvec, 0));
+                       return NULL;
+               }
                alloc = MALLOC(sizeof (char) * (size + 1));
                if (alloc)
                        memcpy(alloc, str, size);
@@ -326,7 +359,7 @@ set_value(vector strvec)
                                (char *)VECTOR_SLOT(strvec, 0));
                        return NULL;
                }
-               if (*str == '"')
+               if (is_quote(str))
                        break;
                tmp = alloc;
                /* The first +1 is for the NULL byte. The rest are for the
@@ -432,7 +465,7 @@ validate_config_strvec(vector strvec, char *file)
                        (char *)VECTOR_SLOT(strvec, 0), line_nr, file);
                return -1;
        }
-       if (*str != '"') {
+       if (!is_quote(str)) {
                if (VECTOR_SIZE(strvec) > 2)
                        condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file);
                return 0;
@@ -444,7 +477,7 @@ validate_config_strvec(vector strvec, char *file)
                                line_nr, file);
                        return -1;
                }
-               if (*str == '"') {
+               if (is_quote(str)) {
                        if (VECTOR_SIZE(strvec) > i + 1)
                                condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr, file);
                        return 0;
@@ -547,7 +580,7 @@ process_file(struct config *conf, char *file)
        FILE *stream;
 
        if (!conf->keywords) {
-               condlog(0, "No keywords alocated");
+               condlog(0, "No keywords allocated");
                return 1;
        }
        stream = fopen(file, "r");