about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--lr.c22
2 files changed, 20 insertions, 4 deletions
diff --git a/README.md b/README.md
index 9d0ae0b..2fc52c3 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ Default: `n`.
 	             | =~                -- POSIX Extended Regular Expressions
 	             | =~~               -- case insensitive POSIX Extended Regular Expressions
 	
-	<str>      ::= " [^"]+ "
+	<str>      ::= " ([^"] | "")+ "  -- use "" for a single " inside "
 
 	<typetest> ::= type == ( b | c | d | p | f | l )
 
diff --git a/lr.c b/lr.c
index 82832de..16d7661 100644
--- a/lr.c
+++ b/lr.c
@@ -322,12 +322,28 @@ parse_type()
 static int
 parse_string(char **s)
 {
+	char *buf = 0;
+	size_t bufsiz = 0;
+	size_t len = 0;
+
 	if (*pos == '"') {
 		pos++;
-		char *e = strchr(pos, '"');
-		*s = strndup(pos, e - pos);
-		pos += e - pos + 1;
+		while (*pos != '"' || (*pos == '"' && *(pos+1) == '"')) {
+			if (len >= bufsiz) {
+				bufsiz = 2*bufsiz + 16;
+				buf = realloc(buf, bufsiz);
+				if (!buf)
+					parse_error("string too long");
+			}
+			if (*pos == '"')
+				pos++;
+			buf[len++] = *pos++;
+		}
+		if (buf)
+			buf[len] = 0;
+		pos++;
 		ws();
+		*s = buf ? buf : (char *) "";
 		return 1;
 	}