Use m_tempfile and better errors msg
[apps/madmutt.git] / makedoc.c
index 92c3221..e2cfc67 100644 (file)
--- a/makedoc.c
+++ b/makedoc.c
@@ -1,19 +1,13 @@
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
- * 
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- * 
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *
+ * Parts were written/modified by:
+ * Rocco Rutte <pdmef@cs.tu-berlin.de>
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
  */
 
 /**
  **
  **/
 
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <errno.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
+#include <lib-lib/lib-lib.h>
 
 #ifdef HAVE_GETOPT_H
 # include <getopt.h>
@@ -82,16 +63,21 @@ enum output_formats_t {
 #define D_NL            (1 << 0)
 #define D_EM            (1 << 1)
 #define D_BF            (1 << 2)
-#define D_TAB           (1 << 3)
-#define D_NP            (1 << 4)
-#define D_INIT          (1 << 5)
-#define D_DL            (1 << 6)
-#define D_DT            (1 << 7)
+#define D_TT            (1 << 3)
+#define D_TAB           (1 << 4)
+#define D_NP            (1 << 5)
+#define D_INIT          (1 << 6)
+#define D_DL            (1 << 7)
+#define D_DT            (1 << 8)
+#define D_DD            (1 << 9)
+#define D_PA            (1 << 10)
 
 enum {
   SP_START_EM,
   SP_START_BF,
+  SP_START_TT,
   SP_END_FT,
+  SP_END_PAR,
   SP_NEWLINE,
   SP_NEWPAR,
   SP_STR,
@@ -100,13 +86,14 @@ enum {
   SP_START_DL,
   SP_DT,
   SP_DD,
+  SP_END_DD,
   SP_END_DL,
+  SP_END_SECT,
   SP_REFER
 };
 
 enum output_formats_t OutputFormat = F_NONE;
 char *Progname;
-short Debug = 0;
 
 static char *get_token (char *, size_t, char *);
 static char *skip_ws (char *);
@@ -118,9 +105,9 @@ static int print_it (int, char *, int);
 static void print_confline (const char *, int, const char *);
 static void handle_confline (char *);
 static void makedoc (FILE *, FILE *);
-static void pretty_default (char *, size_t, const char *, int);
 static int sgml_fputc (int);
 static int sgml_fputs (const char *);
+static int sgml_id_fputs (const char *);
 static void add_var (const char *);
 static int add_s (const char *);
 static int add_c (int);
@@ -146,9 +133,6 @@ int main (int argc, char *argv[])
     case 's':
       OutputFormat = F_SGML;
       break;
-    case 'd':
-      Debug++;
-      break;
     default:
       {
         fprintf (stderr, "%s: bad command line parameter.\n", Progname);
@@ -181,7 +165,7 @@ int main (int argc, char *argv[])
   }
 
   if (f != stdin)
-    fclose (f);
+    m_fclose(&f);
 
   exit (1);
 }
@@ -190,11 +174,11 @@ static void add_var (const char *name)
 {
   outbuf = realloc (outbuf, (++outcount) * sizeof (var_t));
   outbuf[outcount - 1].seen = 0;
-  outbuf[outcount - 1].name = strdup (name);
+  outbuf[outcount - 1].name = strdup(name);
   outbuf[outcount - 1].descr = NULL;
 }
 
-static int add (const char *s)
+static int add_s (const char *s)
 {
   size_t lnew = STRLEN (s), lold = STRLEN (outbuf[outcount - 1].descr);
 
@@ -206,7 +190,7 @@ static int add (const char *s)
   }
 
   if (lold == 0)
-    outbuf[outcount - 1].descr = strdup (s);
+    outbuf[outcount - 1].descr = strdup(s);
   else {
     outbuf[outcount - 1].descr =
       realloc (outbuf[outcount - 1].descr, lold + lnew + 1);
@@ -221,7 +205,7 @@ static int add_c (int c)
   char buf[2] = "\0\0";
 
   buf[0] = c;
-  return (add (buf));
+  return (add_s (buf));
 }
 
 static void makedoc (FILE * in, FILE * out)
@@ -246,11 +230,6 @@ static void makedoc (FILE * in, FILE * out)
     if (!(p = get_token (token, sizeof (token), buffer)))
       continue;
 
-    if (Debug) {
-      fprintf (stderr, "%s: line %d.  first token: \"%s\".\n",
-               Progname, line, token);
-    }
-
     if (!strcmp (token, "/*++*/"))
       active = 1;
     else if (!strcmp (token, "/*--*/")) {
@@ -297,35 +276,19 @@ static char *get_token (char *d, size_t l, char *s)
   short is_quoted = 0;
   char *dd = d;
 
-  if (Debug)
-    fprintf (stderr, "%s: get_token called for `%s'.\n", Progname, s);
-
   s = skip_ws (s);
 
-  if (Debug > 1)
-    fprintf (stderr, "%s: argumet after skip_ws():  `%s'.\n", Progname, s);
-
   if (!*s) {
-    if (Debug)
-      fprintf (stderr, "%s: no more tokens on this line.\n", Progname);
     return NULL;
   }
 
   if (strchr (single_char_tokens, *s)) {
-    if (Debug) {
-      fprintf (stderr, "%s: found single character token `%c'.\n",
-               Progname, *s);
-    }
     d[0] = *s++;
     d[1] = 0;
     return s;
   }
 
   if (*s == '"') {
-    if (Debug) {
-      fprintf (stderr, "%s: found quote character.\n", Progname);
-    }
-
     s++;
     is_quoted = 1;
   }
@@ -368,12 +331,6 @@ static char *get_token (char *d, size_t l, char *s)
 
   *d = '\0';
 
-  if (Debug) {
-    fprintf (stderr, "%s: Got %stoken: `%s'.\n",
-             Progname, is_quoted ? "quoted " : "", dd);
-    fprintf (stderr, "%s: Remainder: `%s'.\n", Progname, t);
-  }
-
   return t;
 }
 
@@ -401,7 +358,8 @@ enum {
   DT_RX,
   DT_MAGIC,
   DT_SYN,
-  DT_ADDR
+  DT_ADDR,
+  DT_SYS
 };
 
 struct {
@@ -420,6 +378,7 @@ struct {
   "DT_MAGIC", "folder magic"}, {
   "DT_SYN", NULL}, {
   "DT_ADDR", "e-mail address"}, {
+  "DT_SYS", "system property"}, {
   NULL, NULL}
 };
 
@@ -443,7 +402,6 @@ static void handle_confline (char *s)
 {
   char varname[BUFFSIZE];
   char buff[BUFFSIZE];
-  char tmp[BUFFSIZE];
   int type;
 
   char val[BUFFSIZE];
@@ -469,8 +427,6 @@ static void handle_confline (char *s)
     return;
 
   if (!strcmp (buff, "|")) {
-    if (Debug)
-      fprintf (stderr, "%s: Expecting <subtype> <comma>.\n", Progname);
     /* ignore subtype and comma */
     if (!(s = get_token (buff, sizeof (buff), s)))
       return;
@@ -498,93 +454,28 @@ static void handle_confline (char *s)
   if (!(s = get_token (buff, sizeof (buff), s)))
     return;
 
-  if (Debug)
-    fprintf (stderr, "%s: Expecting default value.\n", Progname);
-
   /* <default value> or UL <default value> */
   if (!(s = get_token (buff, sizeof (buff), s)))
     return;
   if (!strcmp (buff, "UL")) {
-    if (Debug)
-      fprintf (stderr, "%s: Skipping UL.\n", Progname);
     if (!(s = get_token (buff, sizeof (buff), s)))
       return;
   }
 
-  memset (tmp, 0, sizeof (tmp));
+  memset(val, 0, sizeof(val));
 
   do {
     if (!strcmp (buff, "}"))
       break;
 
-    strncpy (tmp + STRLEN (tmp), buff, sizeof (tmp) - STRLEN (tmp));
+    m_strcat(val, sizeof(val), buff);
   }
   while ((s = get_token (buff, sizeof (buff), s)));
 
-  pretty_default (val, sizeof (val), tmp, type);
   add_var (varname);
   print_confline (varname, type, val);
 }
 
-static void pretty_default (char *t, size_t l, const char *s, int type)
-{
-  memset (t, 0, l);
-  l--;
-
-  switch (type) {
-  case DT_QUAD:
-    {
-      if (!strcasecmp (s, "M_YES"))
-        strncpy (t, "yes", l);
-      else if (!strcasecmp (s, "M_NO"))
-        strncpy (t, "no", l);
-      else if (!strcasecmp (s, "M_ASKYES"))
-        strncpy (t, "ask-yes", l);
-      else if (!strcasecmp (s, "M_ASKNO"))
-        strncpy (t, "ask-no", l);
-      break;
-    }
-  case DT_BOOL:
-    {
-      if (atoi (s))
-        strncpy (t, "yes", l);
-      else
-        strncpy (t, "no", l);
-      break;
-    }
-  case DT_SORT:
-    {
-      /* heuristic! */
-      strncpy (t, s + 5, l);
-      for (; *t; t++)
-        *t = tolower ((unsigned char) *t);
-      break;
-    }
-  case DT_MAGIC:
-    {
-      /* heuristic! */
-      strncpy (t, s + 2, l);
-      for (; *t; t++)
-        *t = tolower ((unsigned char) *t);
-      break;
-    }
-  case DT_STR:
-  case DT_RX:
-  case DT_ADDR:
-  case DT_PATH:
-    {
-      if (!strcmp (s, "0"))
-        break;
-      /* fallthrough */
-    }
-  default:
-    {
-      strncpy (t, s, l);
-      break;
-    }
-  }
-}
-
 static void char_to_escape (char *dest, unsigned int c)
 {
   switch (c) {
@@ -610,7 +501,7 @@ static void conf_char_to_escape (unsigned int c)
   char buff[16];
 
   char_to_escape (buff, c);
-  add (buff);
+  add_s (buff);
 }
 
 static void conf_print_strval (const char *v)
@@ -637,9 +528,9 @@ static void man_print_strval (const char *v)
     }
 
     if (*v == '"')
-      add ("\\(rq");
+      add_s ("\\(rq");
     else if (*v == '\\')
-      add ("\\\\");
+      add_s ("\\\\");
     else
       add_c (*v);
   }
@@ -663,27 +554,31 @@ static int sgml_fputc (int c)
 {
   switch (c) {
   case '<':
-    return add ("&lt;");
+    return add_s ("&lt;");
   case '>':
-    return add ("&gt;");
+    return add_s ("&gt;");
+#if 0
   case '$':
-    return add ("&dollar;");
+    return add_s ("&dollar;");
   case '_':
-    return add ("&lowbar;");
+    return add_s ("&lowbar;");
   case '%':
-    return add ("&percnt;");
+    return add_s ("&percnt;");
+#endif
   case '&':
-    return add ("&amp;");
+    return add_s ("&amp;");
+#if 0
   case '\\':
-    return add ("&bsol;");
+    return add_s ("&bsol;");
   case '"':
-    return add ("&dquot;");
+    return add_s ("&quot;");
   case '[':
-    return add ("&lsqb;");
+    return add_s ("&lsqb;");
   case ']':
-    return add ("&rsqb;");
+    return add_s ("&rsqb;");
   case '~':
-    return add ("&tilde;");
+    return add_s ("&tilde;");
+#endif
   default:
     return add_c (c);
   }
@@ -698,6 +593,21 @@ static int sgml_fputs (const char *s)
   return 0;
 }
 
+/* reduce CDATA to ID */
+static int sgml_id_fputs (const char *s) {
+ char id;
+
+ for (; *s; s++) {
+   if (*s == '_')
+     id = '-';
+   else
+     id = *s;
+   if (sgml_fputc ((unsigned int) id) == EOF)
+     return EOF;
+ }
+ return 0;
+}
+
 static void print_confline (const char *varname, int type, const char *val)
 {
   if (type == DT_SYN)
@@ -707,61 +617,68 @@ static void print_confline (const char *varname, int type, const char *val)
     /* configuration file */
   case F_CONF:
     {
+      if (type == DT_SYS) {
+        add_s ("\n# set ?");
+        add_s (varname);
+        add_s (" prints ");
+        add_s (val);
+        break;
+      }
       if (type == DT_STR || type == DT_RX || type == DT_ADDR
           || type == DT_PATH) {
-        add ("\n# set ");
-        add (varname);
-        add ("\"");
+        add_s ("\n# set ");
+        add_s (varname);
+        add_s ("=\"");
         conf_print_strval (val);
-        add ("\"");
+        add_s ("\"");
       }
       else if (type != DT_SYN) {
-        add ("\n# set ");
-        add (varname);
-        add ("=");
-        add (val);
+        add_s ("\n# set ");
+        add_s (varname);
+        add_s ("=");
+        add_s (val);
       }
 
-      add ("\n#\n# Name: ");
-      add (varname);
-      add ("\n# Type: ");
-      add (type2human (type));
+      add_s ("\n#\n# Name: ");
+      add_s (varname);
+      add_s ("\n# Type: ");
+      add_s (type2human (type));
       if (type == DT_STR || type == DT_RX || type == DT_ADDR
           || type == DT_PATH) {
-        add ("\n# Default: \"");
+        add_s ("\n# Default: \"");
         conf_print_strval (val);
-        add ("\"");
+        add_s ("\"");
       }
       else {
-        add ("\n# Default: ");
-        add (val);
+        add_s ("\n# Default: ");
+        add_s (val);
       }
 
-      add ("\n# ");
+      add_s ("\n# ");
       break;
     }
 
     /* manual page */
   case F_MAN:
     {
-      add (".TP\n.B ");
-      add (varname);
-      add ("\n.nf\n");
-      add ("Type: ");
-      add (type2human (type));
+      add_s (".TP\n.B ");
+      add_s (varname);
+      add_s ("\n.nf\n");
+      add_s ("Type: ");
+      add_s (type2human (type));
       add_c ('\n');
       if (type == DT_STR || type == DT_RX || type == DT_ADDR
           || type == DT_PATH) {
-        add ("Default: \\(lq");
+        add_s ("Default: \\(lq");
         man_print_strval (val);
-        add ("\\(rq\n");
+        add_s ("\\(rq\n");
       }
       else {
-        add ("Default: ");
-        add (val);
+        add_s (type == DT_SYS ? "Value: " : "Default: ");
+        add_s (val);
         add_c ('\n');
       }
-      add (".fi");
+      add_s (".fi");
 
       break;
     }
@@ -769,26 +686,26 @@ static void print_confline (const char *varname, int type, const char *val)
     /* SGML based manual */
   case F_SGML:
     {
-      add ("\n<sect2>");
+      add_s ("\n<madmutt-doc:vardef name=\"");
       sgml_fputs (varname);
-      add ("<label id=\"");
-      add (varname);
-      add ("\">");
-      add ("\n<p>\nType: <tt>");
-      add (type2human (type));
-      add ("</tt>\n\n");
+      add_s ("\">\n<para>Type: <literal>");
+      add_s (type2human (type));
+      add_s ("</literal></para>\n");
 
       if (type == DT_STR || type == DT_RX || type == DT_ADDR
           || type == DT_PATH) {
-        add ("<p>\nDefault: <tt>&dquot;");
+        add_s ("<para>\nDefault: <literal>&quot;");
         sgml_print_strval (val);
-        add ("&dquot;</tt>");
+        add_s ("&quot;</literal>");
       }
       else {
-        add ("<p>\nDefault: <tt>");
-        add (val);
-        add ("</tt>");
+        add_s ("<para>\n"); 
+        add_s (type == DT_SYS ? "Value: " : "Default: ");
+        add_s ("<literal>");
+        add_s (val);
+        add_s ("</literal>");
       }
+      add_s ("</para>\n");
       break;
     }
     /* make gcc happy */
@@ -809,6 +726,7 @@ static void print_confline (const char *varname, int type, const char *val)
  **
  ** - \fI switches to italics
  ** - \fB switches to boldface
+ ** - \fT switches to typewriter for SGML
  ** - \fP switches to normal display
  ** - .dl on a line starts a definition list (name taken taken from HTML).
  ** - .dt starts a term in a definition list.
@@ -838,15 +756,20 @@ static int flush_doc (int docstat)
     exit (1);
   }
 
+  if (docstat & (D_PA))
+    docstat = print_it (SP_END_PAR, NULL, docstat);
+
   if (docstat & (D_TAB))
     docstat = print_it (SP_END_TAB, NULL, docstat);
 
   if (docstat & (D_DL))
     docstat = print_it (SP_END_DL, NULL, docstat);
 
-  if (docstat & (D_EM | D_BF))
+  if (docstat & (D_EM | D_BF | D_TT))
     docstat = print_it (SP_END_FT, NULL, docstat);
 
+  docstat = print_it (SP_END_SECT, NULL, docstat);
+
   docstat = print_it (SP_NEWLINE, NULL, 0);
 
   fd_recurse--;
@@ -869,7 +792,7 @@ static int print_it (int special, char *str, int docstat)
         static int Continuation = 0;
 
       case SP_END_FT:
-        docstat &= ~(D_EM | D_BF);
+        docstat &= ~(D_EM | D_BF | D_TT);
         break;
       case SP_START_BF:
         docstat |= D_BF;
@@ -877,12 +800,15 @@ static int print_it (int special, char *str, int docstat)
       case SP_START_EM:
         docstat |= D_EM;
         break;
+      case SP_START_TT:
+        docstat |= D_TT;
+        break;
       case SP_NEWLINE:
         {
           if (onl)
             docstat |= onl;
           else {
-            add ("\n# ");
+            add_s ("\n# ");
             docstat |= D_NL;
           }
           if (docstat & D_DL)
@@ -897,15 +823,15 @@ static int print_it (int special, char *str, int docstat)
           }
 
           if (!(onl & D_NL))
-            add ("\n# ");
-          add ("\n# ");
+            add_s ("\n# ");
+          add_s ("\n# ");
           docstat |= D_NP;
           break;
         }
       case SP_START_TAB:
         {
           if (!onl)
-            add ("\n# ");
+            add_s ("\n# ");
           docstat |= D_TAB;
           break;
         }
@@ -941,9 +867,9 @@ static int print_it (int special, char *str, int docstat)
         {
           if (Continuation) {
             Continuation = 0;
-            add ("        ");
+            add_s ("        ");
           }
-          add (str);
+          add_s (str);
           if (docstat & D_DT) {
             int i;
 
@@ -964,22 +890,28 @@ static int print_it (int special, char *str, int docstat)
       switch (special) {
       case SP_END_FT:
         {
-          add ("\\fP");
-          docstat &= ~(D_EM | D_BF);
+          add_s ("\\fP");
+          docstat &= ~(D_EM | D_BF | D_TT);
           break;
         }
       case SP_START_BF:
         {
-          add ("\\fB");
+          add_s ("\\fB");
           docstat |= D_BF;
-          docstat &= ~D_EM;
+          docstat &= ~(D_EM | D_TT);
           break;
         }
       case SP_START_EM:
         {
-          add ("\\fI");
+          add_s ("\\fI");
           docstat |= D_EM;
-          docstat &= ~D_BF;
+          docstat &= ~(D_BF | D_TT);
+          break;
+        }
+      case SP_START_TT:
+        {
+          docstat |= D_TT;
+          docstat &= ~(D_BF | D_EM);
           break;
         }
       case SP_NEWLINE:
@@ -1001,43 +933,43 @@ static int print_it (int special, char *str, int docstat)
 
           if (!(onl & D_NL))
             add_c ('\n');
-          add (".IP\n");
+          add_s (".IP\n");
 
           docstat |= D_NP;
           break;
         }
       case SP_START_TAB:
         {
-          add ("\n.IP\n.DS\n.sp\n.ft CR\n.nf\n");
+          add_s ("\n.IP\n.DS\n.sp\n.ft CR\n.nf\n");
           docstat |= D_TAB | D_NL;
           break;
         }
       case SP_END_TAB:
         {
-          add ("\n.fi\n.ec\n.ft P\n.sp\n");
+          add_s ("\n.fi\n.ec\n.ft P\n.sp\n");
           docstat &= ~D_TAB;
           docstat |= D_NL;
           break;
         }
       case SP_START_DL:
         {
-          add ("\n.RS");
+          add_s ("\n.RS");
           docstat |= D_DL;
           break;
         }
       case SP_DT:
         {
-          add ("\n.IP ");
+          add_s ("\n.IP ");
           break;
         }
       case SP_DD:
         {
-          add ("\n");
+          add_s ("\n");
           break;
         }
       case SP_END_DL:
         {
-          add ("\n.RE");
+          add_s ("\n.RE");
           docstat &= ~D_DL;
           break;
         }
@@ -1046,15 +978,15 @@ static int print_it (int special, char *str, int docstat)
           while (*str) {
             for (; *str; str++) {
               if (*str == '"')
-                add ("\\(rq");
+                add_s ("\\(rq");
               else if (*str == '\\')
-                add ("\\\\");
+                add_s ("\\\\");
               else if (!strncmp (str, "``", 2)) {
-                add ("\\(lq");
+                add_s ("\\(lq");
                 str++;
               }
               else if (!strncmp (str, "''", 2)) {
-                add ("\\(rq");
+                add_s ("\\(rq");
                 str++;
               }
               else
@@ -1074,24 +1006,33 @@ static int print_it (int special, char *str, int docstat)
       case SP_END_FT:
         {
           if (docstat & D_EM)
-            add ("</em>");
+            add_s ("</emphasis>");
           if (docstat & D_BF)
-            add ("</bf>");
-          docstat &= ~(D_EM | D_BF);
+            add_s ("</emphasis>");
+          if (docstat & D_TT)
+            add_s ("</literal>");
+          docstat &= ~(D_EM | D_BF | D_TT);
           break;
         }
       case SP_START_BF:
         {
-          add ("<bf>");
+          add_s ("<emphasis role=\"bold\">");
           docstat |= D_BF;
-          docstat &= ~D_EM;
+          docstat &= ~(D_EM | D_TT);
           break;
         }
       case SP_START_EM:
         {
-          add ("<em>");
+          add_s ("<emphasis>");
           docstat |= D_EM;
-          docstat &= ~D_BF;
+          docstat &= ~(D_BF | D_TT);
+          break;
+        }
+      case SP_START_TT:
+        {
+          add_s ("<literal>");
+          docstat |= D_TT;
+          docstat &= ~(D_EM | D_BF);
           break;
         }
       case SP_NEWLINE:
@@ -1099,7 +1040,7 @@ static int print_it (int special, char *str, int docstat)
           if (onl)
             docstat |= onl;
           else {
-            add ("\n");
+            add_s ("\n");
             docstat |= D_NL;
           }
           break;
@@ -1112,51 +1053,72 @@ static int print_it (int special, char *str, int docstat)
           }
 
           if (!(onl & D_NL))
-            add ("\n");
-          add ("\n<p>\n");
+            add_s ("\n");
+          if (docstat & D_PA)
+            add_s ("</para>\n");
+          add_s ("<para>\n");
 
           docstat |= D_NP;
+          docstat |= D_PA;
           break;
         }
       case SP_START_TAB:
         {
-          add ("\n<tscreen><verb>\n");
+          add_s ("\n<screen>\n");
           docstat |= D_TAB | D_NL;
           break;
         }
       case SP_END_TAB:
         {
-          add ("\n</verb></tscreen>");
+          add_s ("\n</screen>");
           docstat &= ~D_TAB;
           docstat |= D_NL;
           break;
         }
       case SP_START_DL:
         {
-          add ("\n<descrip>\n");
+          add_s ("\n<variablelist>\n");
           docstat |= D_DL;
           break;
         }
       case SP_DT:
         {
-          add ("<tag>");
+          add_s ("<varlistentry><term>");
           break;
         }
       case SP_DD:
         {
-          add ("</tag>");
+          add_s ("</term>\n<listitem><para>\n");
+          docstat |= D_DD;
           break;
         }
       case SP_END_DL:
         {
-          add ("</descrip>\n");
-          docstat &= ~D_DL;
+          add_s ("</para></listitem></varlistentry></variablelist>\n");
+          docstat &= ~(D_DL|D_DD);
+          break;
+        }
+      case SP_END_PAR:
+        {
+          add_s ("</para>\n");
+          docstat &= ~D_PA;
+          break;
+        }
+      case SP_END_DD:
+        {
+          add_s ("</para></listitem></varlistentry>\n");
+          docstat &= ~D_DD;
+          break;
+        }
+      case SP_END_SECT:
+        {
+          add_s ("</madmutt-doc:vardef>\n");
           break;
         }
       case SP_STR:
         {
           if (docstat & D_TAB)
-            add (str);
+            add_s (str);
           else
             sgml_fputs (str);
           break;
@@ -1179,17 +1141,17 @@ void print_ref (int output_dollar, const char *ref)
   case F_MAN:
     if (output_dollar)
       add_c ('$');
-    add (ref);
+    add_s (ref);
     break;
 
   case F_SGML:
-    add ("<ref id=\"");
-    add (ref);
-    add ("\" name=\"");
+    add_s ("<link linkend=\"");
+    sgml_id_fputs (ref);
+    add_s ("\">\n");
     if (output_dollar)
-      add ("&dollar;");
+      add_s ("$");
     sgml_fputs (ref);
-    add ("\">");
+    add_s ("</link>");
     break;
 
   default:
@@ -1215,9 +1177,6 @@ static int handle_docline (char *l, int docstat)
 
   l = skip_ws (l);
 
-  if (Debug)
-    fprintf (stderr, "%s: handle_docline `%s'\n", Progname, l);
-
   if (!strncmp (l, ".pp", 3))
     return print_it (SP_NEWPAR, NULL, docstat);
   else if (!strncmp (l, ".ts", 3))
@@ -1250,12 +1209,21 @@ static int handle_docline (char *l, int docstat)
       docstat = print_it (SP_START_BF, NULL, docstat);
       s += 2;
     }
+    else if (!strncmp (s, "\\fT", 3)) {
+      docstat = commit_buff (buff, &d, docstat);
+      docstat = print_it (SP_START_TT, NULL, docstat);
+      s += 2;
+    }
     else if (!strncmp (s, "\\fP", 3)) {
       docstat = commit_buff (buff, &d, docstat);
       docstat = print_it (SP_END_FT, NULL, docstat);
       s += 2;
     }
     else if (!strncmp (s, ".dt", 3)) {
+      if (docstat & D_DD) {
+        docstat = commit_buff (buff, &d, docstat);
+        docstat = print_it (SP_END_DD, NULL, docstat);
+      }
       docstat = commit_buff (buff, &d, docstat);
       docstat = print_it (SP_DT, NULL, docstat);
       s += 3;