diff --git a/src/cpp.c b/src/cpp.c
index b3bc819b3d80e6927c3444438c6f9306ab08961d..581249b9b3aca3cb4b318d6870215f61879df5bd 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -1130,6 +1130,20 @@ static ptrdiff_t readstring( struct cpp *this, const PCHARP data, ptrdiff_t len,
   return pos;
 }
 
+static ptrdiff_t readstring_lit( struct cpp *this, const PCHARP data, ptrdiff_t len, ptrdiff_t pos,
+			     struct string_builder*nf, INT32 ec)
+{
+  INT32 ch;
+  while(1)
+    if(++pos>=len)
+      cpp_error(this,"End of file in string.");
+    else if((ch=INDEX_PCHARP(data,pos)) == '#' && INDEX_PCHARP(data,pos+1)==ec)
+        return pos + 2;
+    else
+        string_builder_putchar(nf, ch);
+  return pos;
+}
+
 static ptrdiff_t fixstring(struct cpp *this, const PCHARP data, ptrdiff_t len,
 			   ptrdiff_t pos, struct string_builder *nf, int outp)
 {
@@ -1989,6 +2003,7 @@ static void free_one_define(struct hash_entry *h)
  */
 #define READSTRING(nf) (pos=readstring(this,data,len,pos,&nf,0))
 #define READSTRING2(nf) (pos=readstring(this,data,len,pos,&nf,1))
+#define READSTRING3(nf,ec) (pos=readstring_lit(this,data,len,pos,&nf,ec))
 #define FIXSTRING(nf,outp) (pos=fixstring(this,data,len,pos,&nf,outp))
 
 /* Gobble an identifier at the current position. */
diff --git a/src/preprocessor.h b/src/preprocessor.h
index f713d22b9cb306d9b617502f372537e86409f862..2e9760978a927058d1c1b8cfc67212b2194b77b8 100644
--- a/src/preprocessor.h
+++ b/src/preprocessor.h
@@ -564,13 +564,19 @@ static ptrdiff_t low_cpp(struct cpp *this,
           case '"':
             {
               struct string_builder nf;
+              char end;
               init_string_builder(&nf, 0);
-
               READSTRING2(nf);
+              goto stringout;
+          case '(': end = ')'; goto litstring;
+          case '[': end = ']'; goto litstring;
+          case '{': end = '}';
+            litstring:
+              init_string_builder(&nf, 0);
+              READSTRING3(nf,end);
+            stringout:
               if(OUTP())
-              {
                 PUSH_STRING_SHIFT(nf.s->str, nf.s->len,nf.s->size_shift, &this->buf);
-              }
               free_string_builder(&nf);
               break;
             }