]> git.cameronkatri.com Git - mandoc.git/blobdiff - roff.c
Fixed spacing (almost there).
[mandoc.git] / roff.c
diff --git a/roff.c b/roff.c
index 90b2f11638a0cd2bd8ba33efa00802ede8270402..b05bb173785a50620a6a33841ae4e922ba0a5834 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.19 2008/11/29 16:23:22 kristaps Exp $ */
+/* $Id: roff.c,v 1.21 2008/11/30 18:50:44 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 
 /* FIXME: warn about empty lists. */
 
-/* FIXME: ; : } ) (etc.) after text macros? */
+/* FIXME: roff_layout and roff_text have identical-ish lower bodies. */
 
 /* FIXME: NAME section needs specific elements. */
 
-/* FIXME: don't print Os, just do roffbegin. */
-
 #define        ROFF_MAXARG       32
 
 enum   roffd { 
@@ -70,9 +68,7 @@ struct        rofftok {
        int               flags;
 #define        ROFF_PARSED      (1 << 0)               /* "Parsed". */
 #define        ROFF_CALLABLE    (1 << 1)               /* "Callable". */
-#define        ROFF_QUOTES      (1 << 2)               /* Quoted args. */
-#define        ROFF_SHALLOW     (1 << 3)               /* Nesting block. */
-#define        ROFF_PUNCT       (1 << 4)
+#define        ROFF_SHALLOW     (1 << 2)               /* Nesting block. */
 };
 
 struct roffarg {
@@ -180,9 +176,9 @@ static      const struct rofftok tokens[ROFF_MAX] = {
        {roff_comment, NULL, NULL, NULL, 0, ROFF_COMMENT, 0 }, /* \" */
        {     roff_Dd, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dd */
        {     roff_Dt, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dt */
-       {     roff_Os, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_QUOTES }, /* Os */
-       { roff_layout, NULL, NULL, NULL, ROFF_Sh, ROFF_LAYOUT, ROFF_PARSED }, /* Sh */
-       { roff_layout, NULL, NULL, NULL, ROFF_Ss, ROFF_LAYOUT, ROFF_PARSED }, /* Ss */ 
+       {     roff_Os, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Os */
+       { roff_layout, NULL, NULL, NULL, ROFF_Sh, ROFF_LAYOUT, 0 }, /* Sh */
+       { roff_layout, NULL, NULL, NULL, ROFF_Ss, ROFF_LAYOUT, 0 }, /* Ss */ 
        {   roff_text, NULL, NULL, NULL, ROFF_Pp, ROFF_TEXT, 0 }, /* Pp */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* D1 */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Dl */
@@ -190,34 +186,34 @@ static    const struct rofftok tokens[ROFF_MAX] = {
        {  roff_close, NULL, NULL, NULL, ROFF_Bd, ROFF_LAYOUT, 0 }, /* Ed */
        { roff_layout, roffarg_Bl, NULL, roffchild_Bl, 0, ROFF_LAYOUT, 0 }, /* Bl */
        {  roff_close, NULL, roffparent_El, NULL, ROFF_Bl, ROFF_LAYOUT, 0 }, /* El */
-       { roff_layout, NULL, roffparent_It, NULL, ROFF_It, ROFF_LAYOUT, ROFF_SHALLOW }, /* It */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Ad */
-       {   roff_text, roffarg_An, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* An */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Ar */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_QUOTES }, /* Cd */ /* XXX man.4 only */
+       { roff_layout, NULL, roffparent_It, NULL, ROFF_It, ROFF_LAYOUT, ROFF_PARSED | ROFF_SHALLOW }, /* It */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ad */ /* FIXME */
+       {   roff_text, roffarg_An, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* An */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ar */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Cd */ /* XXX man.4 only */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Cm */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Dv */ /* XXX needs arg */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Er */ /* XXX needs arg */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Ev */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Dv */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Er */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ev */ /* XXX needs arg */
        {   roff_text, roffarg_Ex, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Ex */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Fa */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fa */ /* XXX needs arg */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Fd */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Fl */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Fn */ /* XXX needs arg */ /* FIXME */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Ft */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Ic */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fl */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fn */ /* XXX needs arg */ /* FIXME */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ft */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ic */ /* XXX needs arg */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* In */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Li */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_QUOTES }, /* Nd */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Nm */ /* FIXME */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Op */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Li */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Nd */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Nm */ /* FIXME */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Op */
        {   NULL, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Ot */ /* XXX deprecated */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Pa */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Pa */
        {   roff_text, roffarg_Rv, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Rv */
        {   roff_text, roffarg_St, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* St */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Va */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Vt */ /* XXX needs arg */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Xr */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Va */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Vt */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xr */ /* XXX needs arg */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* %A */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE}, /* %B */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* %D */
@@ -237,22 +233,22 @@ static    const struct rofftok tokens[ROFF_MAX] = {
        {   NULL, NULL, NULL, NULL, 0, ROFF_TEXT, 0 },  /* Bf */ /* FIXME */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Bo */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Bq */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Bsx */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Bx */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Bsx */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Bx */
        {roff_special, NULL, NULL, NULL, 0, ROFF_SPECIAL, 0 },  /* Db */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Dc */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Do */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Dq */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ec */
        {   NULL, NULL, NULL, NULL, 0, ROFF_TEXT, 0 },  /* Ef */ /* FIXME */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Em */ /* XXX needs arg */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Em */ /* XXX needs arg */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Eo */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Fx */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Ms */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Fx */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ms */
        {   NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* No */
        {   NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ns */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Nx */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Ox */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Nx */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ox */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Pc */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Pf */
        {   roff_text, NULL, NULL, NULL, 0, ROFF_LAYOUT, ROFF_PARSED | ROFF_CALLABLE }, /* Po */
@@ -268,9 +264,9 @@ static      const struct rofftok tokens[ROFF_MAX] = {
        {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sq */
        {roff_special, NULL, NULL, NULL, 0, ROFF_SPECIAL, 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 | ROFF_PUNCT }, /* Sy */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_PUNCT }, /* Tn */
-       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_PUNCT }, /* Ux */
+       {   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 */
+       {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ux */
        {   NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xc */
        {   NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */
        { roff_layout, NULL, NULL, roffchild_Fo, 0, ROFF_LAYOUT, 0 }, /* Fo */
@@ -442,7 +438,7 @@ static int
 textparse(const struct rofftree *tree, char *buf)
 {
 
-       return((*tree->cb.roffdata)(tree->arg, buf));
+       return((*tree->cb.roffdata)(tree->arg, 1, buf));
 }
 
 
@@ -697,6 +693,48 @@ rofffindtok(const char *buf)
 }
 
 
+static int
+roffispunct(const char *p)
+{
+
+       if (0 == *p)
+               return(0);
+       if (0 != *(p + 1))
+               return(0);
+
+       switch (*p) {
+       case('{'):
+               /* FALLTHROUGH */
+       case('.'):
+               /* FALLTHROUGH */
+       case(','):
+               /* FALLTHROUGH */
+       case(';'):
+               /* FALLTHROUGH */
+       case(':'):
+               /* FALLTHROUGH */
+       case('?'):
+               /* FALLTHROUGH */
+       case('!'):
+               /* FALLTHROUGH */
+       case('('):
+               /* FALLTHROUGH */
+       case(')'):
+               /* FALLTHROUGH */
+       case('['):
+               /* FALLTHROUGH */
+       case(']'):
+               /* FALLTHROUGH */
+       case('}'):
+               return(1);
+       default:
+               break;
+       }
+
+       return(0);
+}
+
+
 static int
 rofffindcallable(const char *name)
 {
@@ -942,13 +980,16 @@ roff_layout(ROFFCALL_ARGS)
                return(0);
 
        if ( ! (ROFF_PARSED & tokens[tok].flags)) {
+               i = 0;
                while (*argv) {
-                       if ( ! (*tree->cb.roffdata)(tree->arg, *argv++))
+                       if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++))
                                return(0);
+                       i = 1;
                }
                return((*tree->cb.roffout)(tree->arg, tok));
        }
 
+       i = 0;
        while (*argv) {
                if (ROFF_MAX != (c = rofffindcallable(*argv))) {
                        if (NULL == tokens[c].cb) {
@@ -963,8 +1004,35 @@ roff_layout(ROFFCALL_ARGS)
                }
 
                assert(tree->arg);
-               if ( ! (*tree->cb.roffdata)(tree->arg, *argv++))
+               if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++))
                        return(0);
+               i = 1;
+       }
+
+       /* 
+        * If we're the first parser (*argv == tree->cur) then purge out
+        * any additional punctuation, should there be any remaining at
+        * the end of line. 
+        */
+
+       if (ROFF_PARSED & tokens[tok].flags && *argv) {
+               i = 0;
+               while (argv[i])
+                       i++;
+
+               assert(i > 0);
+               if ( ! roffispunct(argv[--i]))
+                       return(1);
+
+               while (i >= 0 && roffispunct(argv[i]))
+                       i--;
+
+               assert(0 != i);
+               i++;
+
+               while (argv[i])
+                       if ( ! (*tree->cb.roffdata)(tree->arg, 0, argv[i++]))
+                               return(0);
        }
 
        return((*tree->cb.roffout)(tree->arg, tok));
@@ -975,7 +1043,7 @@ roff_layout(ROFFCALL_ARGS)
 static int
 roff_text(ROFFCALL_ARGS) 
 {
-       int              i, c, argcp[ROFF_MAXARG];
+       int              i, j, first, c, argcp[ROFF_MAXARG];
        char            *v, *argvp[ROFF_MAXARG];
 
        if (ROFF_PRELUDE & tree->state) {
@@ -984,6 +1052,9 @@ roff_text(ROFFCALL_ARGS)
                return(0);
        }
 
+       /* FIXME: breaks if passed from roff_layout. */
+       first = *argv == tree->cur;
+
        i = 0;
        argv++;
 
@@ -1004,31 +1075,85 @@ roff_text(ROFFCALL_ARGS)
                return(0);
 
        if ( ! (ROFF_PARSED & tokens[tok].flags)) {
+               i = 0;
                while (*argv) {
-                       if ( ! (*tree->cb.roffdata)(tree->arg, *argv++))
+                       if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++))
                                return(0);
+                       i = 1;
                }
                return((*tree->cb.roffout)(tree->arg, tok));
        }
 
+       i = 0;
        while (*argv) {
-               if (ROFF_MAX != (c = rofffindcallable(*argv))) {
-                       if (NULL == tokens[c].cb) {
-                               roff_err(tree, *argv, "unsupported "
-                                               "macro `%s'",
-                                               toknames[c]);
-                               return(0);
+               if (ROFF_MAX == (c = rofffindcallable(*argv))) {
+                       /* 
+                        * If all that remains is roff punctuation, then
+                        * close out our scope and return.
+                        */
+                       if (roffispunct(*argv)) {
+                               for (j = 0; argv[j]; j++)
+                                       if ( ! roffispunct(argv[j]))
+                                               break;
+                               if (NULL == argv[j])
+                                       break;
+                               i = 1;
                        }
-                       if ( ! (*tokens[c].cb)(c, tree, 
-                                               argv, ROFF_ENTER))
+                       
+                       if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++))
                                return(0);
-                       break;
+
+                       i = 1;
+                       continue;
                }
-               if ( ! (*tree->cb.roffdata)(tree->arg, *argv++))
+
+               /*
+                * A sub-command has been found.  Execute it and
+                * discontinue parsing for arguments.
+                */
+
+               if (NULL == tokens[c].cb) {
+                       roff_err(tree, *argv, "unsupported macro `%s'",
+                                       toknames[c]);
                        return(0);
+               } 
+               
+               if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
+                       return(0);
+
+               break;
        }
 
-       return((*tree->cb.roffout)(tree->arg, tok));
+       if ( ! (*tree->cb.roffout)(tree->arg, tok))
+               return(0);
+
+       /* 
+        * If we're the first parser (*argv == tree->cur) then purge out
+        * any additional punctuation, should there be any remaining at
+        * the end of line. 
+        */
+
+       if (first && *argv) {
+               i = 0;
+               while (argv[i])
+                       i++;
+
+               assert(i > 0);
+               if ( ! roffispunct(argv[--i]))
+                       return(1);
+
+               while (i >= 0 && roffispunct(argv[i]))
+                       i--;
+
+               assert(0 != i);
+               i++;
+
+               while (argv[i])
+                       if ( ! (*tree->cb.roffdata)(tree->arg, 0, argv[i++]))
+                               return(0);
+       }
+
+       return(1);
 }