--- doc.c.orig	2010-08-10 19:49:40.000000000 +0200
+++ doc.c	2010-08-17 12:01:43.451998318 +0200
@@ -187,6 +187,8 @@
 ESCAPES = /</&lt;/\n\
           />/&gt;/\n\
           /&/&amp;/\n\
+RPAREN = )\n\
+LPAREN = (\n\
 ";
 
 static char ddoc_decl_s[] = "$(DDOC_DECL ";
@@ -196,6 +198,61 @@
 static char ddoc_decl_dd_e[] = ")\n";
 
 
+void escapeStrayParenthesis(OutBuffer *buf, unsigned start, Loc loc)
+{
+    unsigned par_open = 0;
+    //max 1024. dynamic array?
+    unsigned open_pos[1024];
+    
+    for (unsigned u = start; u < buf->offset; u++)
+    {   
+        unsigned char c = buf->data[u];
+        switch(c)
+        {
+            case '(':
+                if(par_open < 1023)
+                    open_pos[par_open] = u;
+                par_open++;
+                break;
+            case ')':
+                if(par_open == 0)
+                {
+                    //stray ')'
+                    if(global.params.warnings)
+                        warning(loc, "Ddoc: Stray ')'. This may cause incorrect ddoc output."
+                        " Use $(RPAREN ) instead for unpaired parenthesis. See "
+                        "http://url-with-explanation.com for more information.");
+                    buf->remove(u, 1); //remove the )
+                    buf->insert(u, "$(RPAREN )", 10); //insert this instead
+                    u += 9; //skip over newly inserted macro
+                }
+                else
+                    par_open--;
+                break;
+            case '\n':
+            //For this to work, loc must be set to the beginning of the passed
+            //text which is currently not possible(loc is set to the Loc of the
+            //Dsymbol)
+                //loc.linnum++;
+                break;
+        }
+    }
+    if(par_open != 0)
+    {
+        //unclosed parenthesis
+        if(global.params.warnings)
+            warning(loc, "Ddoc: %d unclosed parenthesis. This may cause incorrect ddoc output."
+            " Use $(LPAREN ) instead for unpaired parenthesis. See "
+            "http://url-with-explanation.com for more information.", par_open);
+
+        for(int i = par_open > 1024 ? 1024 : par_open; i > 0; i--)
+        {
+            buf->remove(open_pos[i-1], 1); //remove the )
+            buf->insert(open_pos[i-1], "$(LPAREN )", 10); //insert this instead
+        }
+    }
+}
+
 /****************************************************
  */
 
@@ -1082,6 +1139,7 @@
                 buf->writestring("$(DDOC_SUMMARY ");
                     unsigned o = buf->offset;
                     buf->write(sec->body, sec->bodylen);
+                    escapeStrayParenthesis(buf, o, s->loc);
                     highlightText(sc, s, buf, o);
                 buf->writestring(")\n");
             }
@@ -1119,10 +1177,12 @@
         buf->writestring("$(DDOC_SECTION ");
             // Replace _ characters with spaces
             buf->writestring("$(DDOC_SECTION_H ");
+            unsigned o = buf->offset;
             for (unsigned u = 0; u < namelen; u++)
             {   unsigned char c = name[u];
                 buf->writeByte((c == '_') ? ' ' : c);
             }
+            escapeStrayParenthesis(buf, o, s->loc);
             buf->writestring(":)\n");
     }
     else
@@ -1132,6 +1192,7 @@
   L1:
     unsigned o = buf->offset;
     buf->write(body, bodylen);
+    escapeStrayParenthesis(buf, o, s->loc);
     highlightText(sc, s, buf, o);
     buf->writestring(")\n");
 }
@@ -1213,12 +1274,14 @@
                         arg->type->toCBuffer(buf, arg->ident, &hgs);
                     else
                         buf->write(namestart, namelen);
+                    escapeStrayParenthesis(buf, o, s->loc);
                     highlightCode(sc, s, buf, o);
                 buf->writestring(")\n");
 
                 buf->writestring("$(DDOC_PARAM_DESC ");
                     o = buf->offset;
                     buf->write(textstart, textlen);
+                    escapeStrayParenthesis(buf, o, s->loc);
                     highlightText(sc, s, buf, o);
                 buf->writestring(")");
             buf->writestring(")\n");
