]> git.cameronkatri.com Git - mandoc.git/commitdiff
Added `Sm' functionality.
authorKristaps Dzonsons <kristaps@bsd.lv>
Tue, 2 Dec 2008 13:20:24 +0000 (13:20 +0000)
committerKristaps Dzonsons <kristaps@bsd.lv>
Tue, 2 Dec 2008 13:20:24 +0000 (13:20 +0000)
Makefile
mdocml.1
private.h
roff.c
xml.c

index e659dbc0d449b26655d8514c6cc2ffe577d90d93..d9d25126223c0621e0d95cc62ad6fa9f5a72dd56 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS += -W -Wall -Wno-unused-parameter -g
+CFLAGS += -W -Wall -Wno-unused-parameter -g 
 
 LINTFLAGS += -c -e -f -u
 
@@ -21,11 +21,13 @@ CLEAN       = mdocml mdocml.tgz $(LLNS) $(LNS) $(OBJS) $(LIBS)
 INSTALL        = Makefile $(HEADS) $(SRCS) $(MANS)
 
 FAIL   = test.0 test.1 test.2 test.3 test.4 test.5 test.6 \
-         test.15 test.20 test.22 test.24 test.26 test.27 test.30
+         test.15 test.20 test.22 test.24 test.26 test.27 test.30 \
+         test.36
 
 SUCCEED        = test.7 test.8 test.9 test.10 test.11 test.12 test.13 \
          test.14 test.16 test.17 test.18 test.19 test.21 test.23 \
-         test.25 test.28 test.29 test.31 test.32 test.33 test.34
+         test.25 test.28 test.29 test.31 test.32 test.33 test.34 \
+         test.35
 
 
 all: mdocml
index d04ce9717fa5203371619dfac5275595d8bbd7ce..2126243892bfbc5a9243f357e29f567e700ae153 100644 (file)
--- a/mdocml.1
+++ b/mdocml.1
@@ -86,7 +86,6 @@ The engine doesn't understand the
 .Sq \&Xc ,
 .Sq \&No ,
 .Sq \&Db ,
-.Sq \&Sm ,
 .Sq \&Xc ,
 and
 .Sq \&Xo
index ff6f7abf9b0ac86c51e077cf54a0de7ff41ba7a1..9995123461f93f206fa0dd67355dce17fc0dd3ae 100644 (file)
--- a/private.h
+++ b/private.h
@@ -1,4 +1,4 @@
-/* $Id: private.h,v 1.21 2008/12/01 15:32:36 kristaps Exp $ */
+/* $Id: private.h,v 1.22 2008/12/02 13:20:24 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -222,7 +222,7 @@ struct      roffcb {
        int     (*roffout)(void *, int);
        int     (*roffblkin)(void *, int, int *, char **);
        int     (*roffblkout)(void *, int);
-       int     (*roffspecial)(void *, int);
+       int     (*roffspecial)(void *, int, int *, char **, char **);
 };
 
 __BEGIN_DECLS
diff --git a/roff.c b/roff.c
index 46c1899e23525931e6db9fd3d5291a285a4ea886..aa3be033bb539287fb4357e6f6f7a446d88c216a 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.32 2008/12/02 00:15:41 kristaps Exp $ */
+/* $Id: roff.c,v 1.33 2008/12/02 13:20:24 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -17,6 +17,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 #include <sys/param.h>
+#include <sys/types.h>
 
 #include <assert.h>
 #include <ctype.h>
@@ -30,6 +31,8 @@
 #include "libmdocml.h"
 #include "private.h"
 
+/* FIXME: First letters of quoted-text interpreted in rofffindtok. */
+/* FIXME: `No' not implemented. */
 /* TODO: warn if Pp occurs before/after Sh etc. (see mdoc.samples). */
 /* TODO: warn about "X section only" macros. */
 /* TODO: warn about empty lists. */
@@ -104,6 +107,7 @@ static      int               roff_Dd(ROFFCALL_ARGS);
 static int               roff_Dt(ROFFCALL_ARGS);
 static int               roff_Os(ROFFCALL_ARGS);
 static int               roff_Ns(ROFFCALL_ARGS);
+static int               roff_Sm(ROFFCALL_ARGS);
 static int               roff_layout(ROFFCALL_ARGS);
 static int               roff_text(ROFFCALL_ARGS);
 static int               roff_noop(ROFFCALL_ARGS);
@@ -126,9 +130,19 @@ static     int               roffnextopt(const struct rofftree *,
                                int, char ***, char **);
 static int               roffparseopts(struct rofftree *, int, 
                                char ***, int *, char **);
+static int               roffcall(struct rofftree *, int, char **);
 static int               roffparse(struct rofftree *, char *);
 static int               textparse(const struct rofftree *, char *);
 
+#ifdef __linux__
+static size_t            strlcat(char *, const char *, size_t);
+static size_t            strlcpy(char *, const char *, size_t);
+extern int               vsnprintf(char *, size_t, 
+                               const char *, va_list);
+extern char             *strptime(const char *, const char *,
+                               struct tm *);
+#endif
+
 
 static const int roffarg_An[] = { ROFF_Split, ROFF_Nosplit, ROFF_ARGMAX };
 static const int roffarg_Bd[] = { ROFF_Ragged, ROFF_Unfilled, ROFF_Literal,
@@ -252,7 +266,7 @@ static      const struct rofftok tokens[ROFF_MAX] = {
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sc */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* So */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Sq */
-       {        NULL, NULL, NULL, NULL, 0, ROFF_SPECIAL, 0 }, /* Sm */
+       {     roff_Sm, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Sm */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sx */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */
@@ -817,6 +831,21 @@ roffnode_free(struct rofftree *tree)
 }
 
 
+static int
+roffcall(struct rofftree *tree, int tok, char **argv)
+{
+
+       if (NULL == tokens[tok].cb) {
+               roff_err(tree, *argv, "unsupported macro `%s'", 
+                               toknames[tok]);
+               return(0);
+       }
+       if ( ! (*tokens[tok].cb)(tok, tree, argv, ROFF_ENTER))
+               return(0);
+       return(1);
+}
+
+
 static int
 roffnextopt(const struct rofftree *tree, int tok, 
                char ***in, char **val)
@@ -835,7 +864,7 @@ roffnextopt(const struct rofftree *tree, int tok,
 
        if (ROFF_ARGMAX == (v = rofffindarg(arg + 1))) {
                roff_warn(tree, arg, "argument-like parameter `%s' to "
-                               "`%s'", &arg[1], toknames[tok]);
+                               "`%s'", arg, toknames[tok]);
                return(-1);
        } 
        
@@ -1053,73 +1082,86 @@ roff_Dt(ROFFCALL_ARGS)
 
 /* ARGSUSED */
 static int
-roff_Ns(ROFFCALL_ARGS)
+roff_Sm(ROFFCALL_ARGS)
 {
-       int              j, c, first;
+       int              argcp[1];
+       char            *argvp[1], *morep[1], *p;
 
-       first = (*argv == tree->cur);
+       p = *argv++;
 
-       argv++;
+       argcp[0] = ROFF_ARGMAX;
+       argvp[0] = NULL;
+       if (NULL == (morep[0] = *argv++)) {
+               roff_err(tree, p, "`Sm' expects an argument");
+               return(0);
+       } else if (0 != strcmp(morep[0], "on") && 
+                       0 != strcmp(morep[0], "off")) {
+               roff_err(tree, p, "`Sm' has invalid argument");
+               return(0);
+       }
 
-       if (ROFF_MAX != (c = rofffindcallable(*argv))) {
-               if (NULL == tokens[c].cb) {
-                       roff_err(tree, *argv, "unsupported macro `%s'",
-                                       toknames[c]);
-                       return(0);
-               }
-               if ( ! (*tree->cb.roffspecial)(tree->arg, tok))
-                       return(0);
-               if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
-                       return(0);
-               if ( ! first)
-                       return(1);
-               return(roffpurgepunct(tree, argv));
-       } 
+       if (*argv) 
+               roff_warn(tree, *argv, "`Sm' shouldn't have arguments");
 
-       if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++))
+       if ( ! (*tree->cb.roffspecial)(tree->arg, 
+                               tok, argcp, argvp, morep))
                return(0);
 
        while (*argv) {
-               if (ROFF_MAX == (c = rofffindcallable(*argv))) {
-                       if ( ! roffispunct(*argv)) {
-                               if ( ! (*tree->cb.roffdata)
-                                               (tree->arg, 1, *argv++))
-                                       return(0);
-                               continue;
-                       }
-                       
-                       /* FIXME: this is identical to that of
-                        * roff_text. */
+               if ((*tree->cb.roffdata)(tree->arg, 1, *argv++))
+                       continue;
+               return(0);
+       }
 
-                       /* See if only punctuation remains. */
+       return(1);
+}
 
-                       for (j = 0; argv[j]; j++)
-                               if ( ! roffispunct(argv[j]))
-                                       break;
 
-                       if (argv[j]) {
-                               if ( ! (*tree->cb.roffdata)
-                                               (tree->arg, 0, *argv++))
-                                       return(0);
-                               continue;
-                       }
+/* ARGSUSED */
+static int
+roff_Ns(ROFFCALL_ARGS)
+{
+       int              j, c, first;
+       int              argcp[1];
+       char            *argvp[1], *morep[1];
+
+       first = (*argv++ == tree->cur);
+
+       argcp[0] = ROFF_ARGMAX;
+       argvp[0] = morep[0] = NULL;
 
-                       /*  Only punctuation remains. */
+       if ( ! (*tree->cb.roffspecial)(tree->arg, 
+                               tok, argcp, argvp, morep))
+               return(0);
 
+       while (*argv) {
+               if (ROFF_MAX != (c = rofffindcallable(*argv))) {
+                       if ( ! roffcall(tree, c, argv))
+                               return(0);
                        break;
                }
-               if (NULL == tokens[c].cb) {
-                       roff_err(tree, *argv, "unsupported macro `%s'",
-                                       toknames[c]);
+
+               if ( ! roffispunct(*argv)) {
+                       if ((*tree->cb.roffdata)(tree->arg, 1, *argv++))
+                               continue;
                        return(0);
                }
-               if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
+               for (j = 0; argv[j]; j++)
+                       if ( ! roffispunct(argv[j]))
+                               break;
+
+               if (argv[j]) {
+                       if ((*tree->cb.roffdata)(tree->arg, 0, *argv++))
+                               continue;
                        return(0);
+               }
+
                break;
        }
 
        if ( ! first)
                return(1);
+
        return(roffpurgepunct(tree, argv));
 }
 
@@ -1240,16 +1282,8 @@ roff_layout(ROFFCALL_ARGS)
                        i = 1;
                        continue;
                }
-
-               if (NULL == tokens[c].cb) {
-                       roff_err(tree, *argv, "unsupported macro `%s'",
-                                       toknames[c]);
+               if ( ! roffcall(tree, c, argv))
                        return(0);
-               }
-
-               if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
-                       return(0);
-
                break;
        }
 
@@ -1316,60 +1350,41 @@ roff_text(ROFFCALL_ARGS)
 
        i = 0;
        while (*argv) {
-               if (ROFF_MAX == (c = rofffindcallable(*argv))) {
-                       if ( ! roffispunct(*argv)) {
-                               if ( ! (*tree->cb.roffdata)
-                                               (tree->arg, i, *argv++))
+               if (ROFF_MAX != (c = rofffindcallable(*argv))) {
+                       if ( ! (ROFF_LSCOPE & tokens[tok].flags))
+                               if ( ! (*tree->cb.roffout)(tree->arg, tok))
                                        return(0);
-                               i = 1;
-                               continue;
-                       }
-
-                       /* See if only punctuation remains. */
-
-                       i = 1;
-                       for (j = 0; argv[j]; j++)
-                               if ( ! roffispunct(argv[j]))
-                                       break;
-
-                       if (argv[j]) {
-                               if ( ! (*tree->cb.roffdata)
-                                               (tree->arg, 0, *argv++))
-                                       return(0);
-                               continue;
-                       }
-
-                       /*  Only punctuation remains. */
-
-                       if ( ! (*tree->cb.roffout)(tree->arg, tok))
+       
+                       if ( ! roffcall(tree, c, argv))
                                return(0);
+       
+                       if (ROFF_LSCOPE & tokens[tok].flags)
+                               if ( ! (*tree->cb.roffout)(tree->arg, tok))
+                                       return(0);
+       
                        break;
                }
 
-               /*
-                * A sub-command has been found.  Execute it and
-                * discontinue parsing for arguments.  If we're
-                * line-scoped, then close out after it returns; if we
-                * aren't, then close out before.
-                */
-
-               if (NULL == tokens[c].cb) {
-                       roff_err(tree, *argv, "unsupported macro `%s'",
-                                       toknames[c]);
-                       return(0);
-               } 
-               
-               if ( ! (ROFF_LSCOPE & tokens[tok].flags))
-                       if ( ! (*tree->cb.roffout)(tree->arg, tok))
+               if ( ! roffispunct(*argv)) {
+                       if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++))
                                return(0);
-               
-               if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
-                       return(0);
+                       i = 1;
+                       continue;
+               }
 
-               if (ROFF_LSCOPE & tokens[tok].flags)
-                       if ( ! (*tree->cb.roffout)(tree->arg, tok))
+               i = 1;
+               for (j = 0; argv[j]; j++)
+                       if ( ! roffispunct(argv[j]))
+                               break;
+
+               if (argv[j]) {
+                       if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++))
                                return(0);
+                       continue;
+               }
 
+               if ( ! (*tree->cb.roffout)(tree->arg, tok))
+                       return(0);
                break;
        }
 
@@ -1429,3 +1444,81 @@ roff_err(const struct rofftree *tree, const char *pos, char *fmt, ...)
        (*tree->cb.roffmsg)(tree->arg, 
                        ROFF_ERROR, tree->cur, pos, buf);
 }
+
+
+#ifdef __linux
+/*     $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $      */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+static size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+       char *d = dst;
+       const char *s = src;
+       size_t n = siz;
+       size_t dlen;
+
+       /* Find the end of dst and adjust bytes left but don't go past
+        * end */
+       while (n-- != 0 && *d != '\0')
+               d++;
+       dlen = d - dst;
+       n = siz - dlen;
+
+       if (n == 0)
+               return(dlen + strlen(s));
+       while (*s != '\0') {
+               if (n != 1) {
+                       *d++ = *s;
+                       n--;
+               }
+               s++;
+       }
+       *d = '\0';
+
+       return(dlen + (s - src));       /* count does not include NUL */
+}
+
+
+static size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+       char *d = dst;
+       const char *s = src;
+       size_t n = siz;
+
+       /* Copy as many bytes as will fit */
+       if (n != 0) {
+               while (--n != 0) {
+                       if ((*d++ = *s++) == '\0')
+                               break;
+               }
+       }
+
+       /* Not enough room in dst, add NUL and traverse rest of src */
+       if (n == 0) {
+               if (siz != 0)
+                       *d = '\0';              /* NUL-terminate dst */
+               while (*s++)
+                       ;
+       }
+
+       return(s - src - 1);    /* count does not include NUL */
+}
+#endif /*__linux__*/
diff --git a/xml.c b/xml.c
index 49dabb8c9c96a7b8d779ff50edeb7713bd85acd3..36f3295de6e762f87eb1ca38f4a68fa6bb351af9 100644 (file)
--- a/xml.c
+++ b/xml.c
@@ -1,4 +1,4 @@
-/* $Id: xml.c,v 1.7 2008/12/02 00:15:41 kristaps Exp $ */
+/* $Id: xml.c,v 1.8 2008/12/02 13:20:24 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 #define        MAXINDENT        8
 #define        COLUMNS          72
 
-#ifdef __linux__ /* FIXME */
-#define        strlcat          strncat
-#endif
-
 enum   md_ns {
        MD_NS_BLOCK,
        MD_NS_INLINE,
@@ -42,12 +38,11 @@ enum        md_ns {
 };
 
 enum   md_tok {
-       MD_BLKIN,
+       MD_BLKIN,               /* Controls spacing. */
        MD_BLKOUT,
        MD_IN,
        MD_OUT,
-       MD_TEXT,
-       MD_OVERRIDE
+       MD_TEXT
 };
 
 struct md_xml {
@@ -60,7 +55,9 @@ struct        md_xml {
        size_t           pos;
        enum md_tok      last;
        int              flags;
-#define        MD_LITERAL      (1 << 0) /* FIXME */
+#define        MD_LITERAL      (1 << 0) /* TODO */
+#define        MD_OVERRIDE_ONE (1 << 1)
+#define        MD_OVERRIDE_ALL (1 << 2)
 };
 
 static void             roffmsg(void *arg, enum roffmsg, 
@@ -72,8 +69,9 @@ static        int              roffdata(void *, int, char *);
 static int              roffout(void *, int);
 static int              roffblkin(void *, int, int *, char **);
 static int              roffblkout(void *, int);
-static int              roffspecial(void *, int);
+static int              roffspecial(void *, int, int *, char **, char **);
 
+static void             mbuf_mode(struct md_xml *, enum md_ns);
 static int              mbuf_newline(struct md_xml *);
 static int              mbuf_indent(struct md_xml *);
 static int              mbuf_data(struct md_xml *, int, char *);
@@ -90,6 +88,14 @@ static       int              mbuf_endtag(struct md_xml *,
                                const char *, enum md_ns);
 
 
+static void
+mbuf_mode(struct md_xml *p, enum md_ns ns)
+{
+       p->flags &= ~MD_OVERRIDE_ONE;
+       p->last = ns;
+}
+
+
 static int
 mbuf_begintag(struct md_xml *p, const char *name, enum md_ns ns, 
                int *argc, char **argv)
@@ -257,6 +263,9 @@ mbuf_data(struct md_xml *p, int space, char *buf)
        assert(p->mbuf);
        assert(0 != p->indent);
 
+       if (MD_OVERRIDE_ONE & p->flags || MD_OVERRIDE_ALL & p->flags)
+               space = 0;
+
        if (MD_LITERAL & p->flags)
                return(mbuf_putstring(p, buf));
 
@@ -281,11 +290,11 @@ mbuf_data(struct md_xml *p, int space, char *buf)
                                return(0);
                        if ( ! mbuf_nputstring(p, bufp, sz))
                                return(0);
-                       if (p->indent * MAXINDENT + sz >= COLUMNS) {
+                       if (p->indent * MAXINDENT + sz >= COLUMNS)
                                if ( ! mbuf_newline(p))
                                        return(0);
-                               continue;
-                       }
+                       if ( ! (MD_OVERRIDE_ALL & p->flags))
+                               space = 1;
                        continue;
                }
 
@@ -302,9 +311,8 @@ mbuf_data(struct md_xml *p, int space, char *buf)
                if ( ! mbuf_nputstring(p, bufp, sz))
                        return(0);
 
-               if ( ! space && p->pos >= COLUMNS)
-                       if ( ! mbuf_newline(p))
-                               return(0);
+               if ( ! (MD_OVERRIDE_ALL & p->flags))
+                       space = 1;
        }
 
        return(1);
@@ -388,7 +396,7 @@ roffhead(void *arg)
                return(0);
 
        p->indent++;
-       p->last = MD_BLKIN;
+       mbuf_mode(p, MD_BLKIN);
        return(mbuf_newline(p));
 }
 
@@ -404,16 +412,16 @@ rofftail(void *arg)
        if (0 != p->pos && ! mbuf_newline(p))
                return(0);
 
-       p->last = MD_BLKOUT;
+       mbuf_mode(p, MD_BLKOUT);
        if ( ! mbuf_endtag(p, "mdoc", MD_NS_DEFAULT))
                return(0);
-
        return(mbuf_newline(p));
 }
 
 
+/* ARGSUSED */
 static int
-roffspecial(void *arg, int tok)
+roffspecial(void *arg, int tok, int *argc, char **argv, char **more)
 {
        struct md_xml   *p;
 
@@ -424,7 +432,14 @@ roffspecial(void *arg, int tok)
 
        switch (tok) {
        case (ROFF_Ns):
-               p->last = MD_OVERRIDE;
+               p->flags |= MD_OVERRIDE_ONE;
+               break;
+       case (ROFF_Sm):
+               assert(*more);
+               if (0 == strcmp(*more, "on"))
+                       p->flags |= MD_OVERRIDE_ALL;
+               else
+                       p->flags &= ~MD_OVERRIDE_ALL;
                break;
        default:
                break;
@@ -452,8 +467,8 @@ roffblkin(void *arg, int tok, int *argc, char **argv)
 
        /* FIXME: xml won't like standards args (e.g., p1003.1-90). */
 
-       p->last = MD_BLKIN;
        p->indent++;
+       mbuf_mode(p, MD_BLKIN);
 
        if ( ! mbuf_begintag(p, toknames[tok], MD_NS_BLOCK,
                                argc, argv))
@@ -480,8 +495,7 @@ roffblkout(void *arg, int tok)
        } else if ( ! mbuf_indent(p))
                return(0);
 
-       p->last = MD_BLKOUT;
-
+       mbuf_mode(p, MD_BLKOUT);
        if ( ! mbuf_endtag(p, toknames[tok], MD_NS_BLOCK))
                return(0);
        return(mbuf_newline(p));
@@ -496,31 +510,22 @@ roffin(void *arg, int tok, int *argc, char **argv)
        assert(arg);
        p = (struct md_xml *)arg;
 
-       /* 
-        * FIXME: put all of this in a buffer, then check the buffer
-        * length versus the column width for nicer output.  This is a
-        * bit hacky.
-        */
-
-       if (p->pos + 11 > COLUMNS) 
+       if ( ! (MD_OVERRIDE_ONE & p->flags) && 
+                       ! (MD_OVERRIDE_ALL & p->flags) && 
+                       p->pos + 11 > COLUMNS) 
                if ( ! mbuf_newline(p))
                        return(0);
 
-       if (0 != p->pos) {
-               switch (p->last) {
-               case (MD_TEXT):
-                       /* FALLTHROUGH */
-               case (MD_OUT):
-                       if ( ! mbuf_nputs(p, " ", 1))
-                               return(0);
-                       break;
-               default:
-                       break;
-               }
-       } else if ( ! mbuf_indent(p))
+       if (0 != p->pos && (MD_TEXT == p->last || MD_OUT == p->last)
+                       && ! (MD_OVERRIDE_ONE & p->flags)
+                       && ! (MD_OVERRIDE_ALL & p->flags))
+               if ( ! mbuf_nputs(p, " ", 1))
+                       return(0);
+
+       if (0 == p->pos && ! mbuf_indent(p))
                return(0);
 
-       p->last = MD_IN;
+       mbuf_mode(p, MD_IN);
        return(mbuf_begintag(p, toknames[tok], 
                                MD_NS_INLINE, argc, argv));
 }
@@ -537,7 +542,7 @@ roffout(void *arg, int tok)
        if (0 == p->pos && ! mbuf_indent(p))
                return(0);
 
-       p->last = MD_OUT;
+       mbuf_mode(p, MD_OUT);
        return(mbuf_endtag(p, toknames[tok], MD_NS_INLINE));
 }
 
@@ -586,7 +591,7 @@ roffdata(void *arg, int space, char *buf)
        if ( ! mbuf_data(p, space, buf))
                return(0);
 
-       p->last = MD_TEXT;
+       mbuf_mode(p, MD_TEXT);
        return(1);
 }