mandoc(1): Update to 1.9.19.
authorSascha Wildner <saw@online.de>
Sat, 27 Mar 2010 19:25:34 +0000 (20:25 +0100)
committerSascha Wildner <saw@online.de>
Sat, 27 Mar 2010 19:25:34 +0000 (20:25 +0100)
For a full list of changes, see <http://mdocml.bsd.lv/ChangeLog.html>.

Thanks-to: Kristaps Dzonsons

22 files changed:
share/man/man7/mandoc_char.7
usr.bin/mandoc/Makefile
usr.bin/mandoc/arch.in
usr.bin/mandoc/chars.c
usr.bin/mandoc/chars.in
usr.bin/mandoc/libman.h
usr.bin/mandoc/main.c
usr.bin/mandoc/man.3
usr.bin/mandoc/man.7
usr.bin/mandoc/man.c
usr.bin/mandoc/man.h
usr.bin/mandoc/man_action.c
usr.bin/mandoc/man_hash.c
usr.bin/mandoc/man_html.c
usr.bin/mandoc/man_macro.c
usr.bin/mandoc/man_term.c
usr.bin/mandoc/man_validate.c
usr.bin/mandoc/mandoc.1
usr.bin/mandoc/mdoc.7
usr.bin/mandoc/mdoc_term.c
usr.bin/mandoc/term.c
usr.bin/mandoc/term.h

index 25d99ce..209345f 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mandoc_char.7,v 1.31 2010/01/07 09:16:19 kristaps Exp $
+.\"    $Id: mandoc_char.7,v 1.33 2010/03/23 13:25:01 kristaps Exp $
 .\"
 .\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd February 20, 2010
+.Dd March 27, 2010
 .Dt MANDOC_CHAR 7
 .Os
 .
@@ -540,6 +540,25 @@ implementations:
 .It \e*(>=   Ta \*(>=       Ta greater-than-equal
 .It \e*(aa   Ta \*(aa       Ta acute
 .It \e*(ga   Ta \*(ga       Ta grave
+.It \e*(--   Ta \*(--       Ta dash
+.It \e*(PI   Ta \*(PI       Ta pi
+.It \e*(L"   Ta \*(L"       Ta left double-quote
+.It \e*(R"   Ta \*(R"       Ta right double-quote
+.It \e*(C+   Ta \*(C+       Ta C++
+.It \e*(C`   Ta \*(C`       Ta left single-quote
+.It \e*(C'   Ta \*(C'       Ta right single-quote
+.It \e*(Aq   Ta \*(Aq       Ta apostrophe quote
+.It \e*^     Ta \*^         Ta up-arrow
+.It \e*,     Ta \*,         Ta comma
+.It \e*~     Ta \*~         Ta tilde
+.It \e*/     Ta \*/         Ta forward slash
+.It \e*:     Ta \*:         Ta umlaut
+.It \e*8     Ta \*8         Ta beta
+.It \e*o     Ta \*o         Ta degree symbol
+.It \e*(D-   Ta \*(D-       Ta Eth
+.It \e*(d-   Ta \*(d-       Ta eth
+.It \e*(TH   Ta \*(TH       Ta Thorn
+.It \e*(th   Ta \*(th       Ta thorn
 .El
 .
 .
@@ -578,19 +597,6 @@ having no known representation:
 .Xr mandoc 1
 .
 .
-.Sh STANDARDS
-.Rs
-.%A The Unicode Consortium
-.%T The Unicode Standard: Worldwide Character Encoding, Version 5.2
-.%D 1991
-.Re
-.Rs
-.%A W3C
-.%T HTML 4.01 Specification
-.%D December, 1999
-.Re
-.
-.
 .Sh AUTHORS
 The
 .Nm
index 306442b..2b22f52 100644 (file)
@@ -1,6 +1,6 @@
 #      $OpenBSD: Makefile,v 1.21 2009/10/27 21:40:07 schwarze Exp $
 
-VERSION=1.9.15
+VERSION=1.9.19
 CFLAGS+=-DVERSION=\"${VERSION}\"
 WARNS?=        3
 
index 97bd2f6..fc0db57 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: arch.in,v 1.5 2009/06/10 20:18:43 kristaps Exp $ */
+/*     $Id: arch.in,v 1.7 2010/03/26 07:07:58 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -25,6 +25,7 @@
  */
 
 LINE("alpha",          "Alpha")
+LINE("amd64",          "AMD64")
 LINE("amiga",          "Amiga")
 LINE("arc",            "ARC")
 LINE("arm",            "ARM")
@@ -35,6 +36,7 @@ LINE("hppa",          "HPPA")
 LINE("hppa64",         "HPPA64")
 LINE("i386",           "i386")
 LINE("landisk",                "LANDISK")
+LINE("loongson",       "Loongson")
 LINE("luna88k",                "Luna88k")
 LINE("mac68k",         "Mac68k")
 LINE("macppc",         "MacPPC")
index aece6b4..746535b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: chars.c,v 1.16 2010/01/28 06:04:59 kristaps Exp $ */
+/*     $Id: chars.c,v 1.17 2010/03/23 13:25:01 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -38,7 +38,7 @@ struct        ln {
 #define CHARS_BOTH      (CHARS_CHAR | CHARS_STRING)
 };
 
-#define        LINES_MAX         350
+#define        LINES_MAX         369
 
 #define CHAR(w, x, y, z, a, b) \
        { NULL, (w), (y), (a), (x), (z), (b), CHARS_CHAR },
index 15157c1..68ad956 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: chars.in,v 1.20 2010/01/05 19:51:10 kristaps Exp $ */
+/*     $Id: chars.in,v 1.21 2010/03/23 13:25:01 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -50,10 +50,10 @@ CHAR("a\"",                 2,      "\"",           1,      "&#779;",       6)
 CHAR("a-",                     2,      "-",            1,      "&#175;",       6)
 CHAR("a.",                     2,      ".",            1,      "&#729;",       6)
 CHAR("a^",                     2,      "^",            1,      "&#770;",       6)
-CHAR("\'",                     1,      "\'",           1,      "&#769;",       6)
+BOTH("\'",                     1,      "\'",           1,      "&#769;",       6)
 BOTH("aa",                     2,      "\'",           1,      "&#769;",       6)
 BOTH("ga",                     2,      "`",            1,      "&#768;",       6)
-CHAR("`",                      1,      "`",            1,      "&#768;",       6)
+BOTH("`",                      1,      "`",            1,      "&#768;",       6)
 CHAR("ab",                     2,      "`",            1,      "&#774;",       6)
 CHAR("ac",                     2,      ",",            1,      "&#807;",       6)
 CHAR("ad",                     2,      "\"",           1,      "&#776;",       6)
@@ -321,8 +321,8 @@ CHAR("fi",                  2,      "fi",           2,      "&#64257;",     8)
 CHAR("fl",                     2,      "fl",           2,      "&#64258;",     8)
 CHAR("Fi",                     2,      "ffi",          3,      "&#64259;",     8)
 CHAR("Fl",                     2,      "ffl",          3,      "&#64260;",     8)
-CHAR("AE",                     2,      "AE",           2,      "&#198;",       6)
-CHAR("ae",                     2,      "ae",           2,      "&#230;",       6)
+BOTH("AE",                     2,      "AE",           2,      "&#198;",       6)
+BOTH("ae",                     2,      "ae",           2,      "&#230;",       6)
 CHAR("OE",                     2,      "OE",           2,      "&#338;",       6)
 CHAR("oe",                     2,      "oe",           2,      "&#339;",       6)
 CHAR("ss",                     2,      "ss",           2,      "&#223;",       6)
@@ -347,6 +347,27 @@ CHAR("Po",                 2,      "L",            1,      "&#163;",       6)
 CHAR("Cs",                     2,      "x",            1,      "&#164;",       6)
 CHAR("Fn",                     2,      "f",            1,      "&#402;",       6)
 
+/* pod2man holdovers. */
+STRING("--",                   2,      "--",           2,      "&#8212;",      7)
+STRING("PI",                   2,      "pi",           2,      "&#960;",       6)
+STRING("L\"",                  2,      "``",           2,      "&#8220;",      7)
+STRING("R\"",                  2,      "\'\'",         2,      "&#8221;",      7)
+STRING("C+",                   2,      "C++",          3,      "C++",          3)
+STRING("C`",                   2,      "`",            1,      "&#8216;",      7)
+STRING("C\'",                  2,      "\'",           1,      "&#8217;",      7)
+STRING("Aq",                   2,      "\'",           1,      "\'",           1)
+STRING("^",                    1,      "^",            1,      "^",            1)
+STRING(",",                    1,      ",",            1,      ",",            1)
+STRING("~",                    1,      "~",            1,      "~",            1)
+STRING("/",                    1,      "/",            1,      "/",            1)
+STRING(":",                    1,      "\"",           1,      "&#776;",       6)
+STRING("8",                    1,      "B",            1,      "&#946;",       6)
+STRING("o",                    1,      "o",            1,      "&#176;",       6)
+STRING("D-",                   2,      "D",            1,      "&#208;",       6)
+STRING("d-",                   2,      "o",            1,      "&#240;",       6)
+STRING("TH",                   2,      "b",            1,      "&#222;",       6)
+STRING("th",                   2,      "b",            1,      "&#254;",       6)
+
 /* Old style. */
 STRING("Am",                   2,      "&",            1,      "&amp;",        5)
 STRING("Ba",                   2,      "|",            1,      "|",            1)
index c0b5cb4..ecd7da6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: libman.h,v 1.23 2009/10/30 05:58:36 kristaps Exp $ */
+/*     $Id: libman.h,v 1.28 2010/03/27 10:04:56 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -32,7 +32,8 @@ struct        man {
 #define        MAN_HALT        (1 << 0)
 #define        MAN_ELINE       (1 << 1)        /* Next-line element scope. */
 #define        MAN_BLINE       (1 << 2)        /* Next-line block scope. */
-#define        MAN_LITERAL     (1 << 3)        /* Literal input. */
+#define        MAN_ILINE       (1 << 3) /* Ignored in next-line scope. */
+#define        MAN_LITERAL     (1 << 4) /* Literal input. */
        enum man_next    next;
        struct man_node *last;
        struct man_node *first;
@@ -44,6 +45,7 @@ enum  merr {
        WMSEC,
        WDATE,
        WLNSCOPE,
+       WLNSCOPE2,
        WTSPACE,
        WTQUOTE,
        WNODATA,
@@ -58,10 +60,13 @@ enum        merr {
        WNOSCOPE,
        WOLITERAL,
        WNLITERAL,
+       WROFFNEST,
+       WROFFSCOPE,
+       WTITLECASE,
        WERRMAX
 };
 
-#define        MACRO_PROT_ARGS   struct man *m, int tok, int line, \
+#define        MACRO_PROT_ARGS   struct man *m, enum mant tok, int line, \
                          int ppos, int *pos, char *buf
 
 struct man_macro {
@@ -70,6 +75,8 @@ struct        man_macro {
 #define        MAN_SCOPED       (1 << 0)
 #define        MAN_EXPLICIT     (1 << 1)       /* See blk_imp(). */
 #define        MAN_FSCOPED      (1 << 2)       /* See blk_imp(). */
+#define        MAN_NSCOPED      (1 << 3)       /* See in_line_eoln(). */
+#define        MAN_NOCLOSE      (1 << 4)       /* See blk_exp(). */
 };
 
 extern const struct man_macro *const man_macros;
@@ -86,14 +93,13 @@ __BEGIN_DECLS
                  man_err((m), (n)->line, (n)->pos, 0, (t))
 
 int              man_word_alloc(struct man *, int, int, const char *);
-int              man_block_alloc(struct man *, int, int, int);
-int              man_head_alloc(struct man *, int, int, int);
-int              man_body_alloc(struct man *, int, int, int);
-int              man_elem_alloc(struct man *, int, int, int);
-void             man_node_free(struct man_node *);
-void             man_node_freelist(struct man_node *);
+int              man_block_alloc(struct man *, int, int, enum mant);
+int              man_head_alloc(struct man *, int, int, enum mant);
+int              man_body_alloc(struct man *, int, int, enum mant);
+int              man_elem_alloc(struct man *, int, int, enum mant);
+void             man_node_delete(struct man *, struct man_node *);
 void             man_hash_init(void);
-int              man_hash_find(const char *);
+enum   mant      man_hash_find(const char *);
 int              man_macroend(struct man *);
 int              man_args(struct man *, int, int *, char *, char **);
 #define        ARGS_ERROR      (-1)
@@ -107,7 +113,8 @@ int           man_valid_post(struct man *);
 int              man_valid_pre(struct man *, const struct man_node *);
 int              man_action_post(struct man *);
 int              man_action_pre(struct man *, struct man_node *);
-int              man_unscope(struct man *, const struct man_node *);
+int              man_unscope(struct man *,
+                       const struct man_node *, enum merr);
 
 __END_DECLS
 
index a4a4ce8..361cead 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: main.c,v 1.59 2010/01/29 14:39:38 kristaps Exp $ */
+/*     $Id: main.c,v 1.60 2010/03/22 20:43:00 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -68,11 +68,11 @@ struct      curparse {
 #define        WARN_WALL        (1 << 0)       /* All-warnings mask. */
 #define        WARN_WERR        (1 << 2)       /* Warnings->errors. */
        int               fflags;
-#define        IGN_SCOPE        (1 << 0)       /* Ignore scope errors. */
-#define        NO_IGN_ESCAPE    (1 << 1)       /* Don't ignore bad escapes. */
-#define        NO_IGN_MACRO     (1 << 2)       /* Don't ignore bad macros. */
-#define        NO_IGN_CHARS     (1 << 3)       /* Don't ignore bad chars. */
-#define        IGN_ERRORS       (1 << 4)       /* Ignore failed parse. */
+#define        FL_IGN_SCOPE     (1 << 0)       /* Ignore scope errors. */
+#define        FL_NIGN_ESCAPE   (1 << 1)       /* Don't ignore bad escapes. */
+#define        FL_NIGN_MACRO    (1 << 2)       /* Don't ignore bad macros. */
+#define        FL_NIGN_CHARS    (1 << 3)       /* Don't ignore bad chars. */
+#define        FL_IGN_ERRORS    (1 << 4)       /* Ignore failed parse. */
        enum intt         inttype;      /* Input parsers... */
        struct man       *man;
        struct man       *lastman;
@@ -86,8 +86,12 @@ struct       curparse {
        char              outopts[BUFSIZ];
 };
 
+#define        FL_STRICT         FL_NIGN_ESCAPE | \
+                         FL_NIGN_MACRO | \
+                         FL_NIGN_CHARS
+
 static int               foptions(int *, char *);
-static int               toptions(enum outt *, char *);
+static int               toptions(struct curparse *, char *);
 static int               moptions(enum intt *, char *);
 static int               woptions(int *, char *);
 static int               merr(void *, int, int, const char *);
@@ -140,7 +144,7 @@ main(int argc, char *argv[])
                        (void)strlcat(curp.outopts, ",", BUFSIZ);
                        break;
                case ('T'):
-                       if ( ! toptions(&curp.outtype, optarg))
+                       if ( ! toptions(&curp, optarg))
                                return(EXIT_FAILURE);
                        break;
                case ('W'):
@@ -168,7 +172,7 @@ main(int argc, char *argv[])
                curp.fd = STDIN_FILENO;
 
                c = fdesc(&blk, &ln, &curp);
-               if ( ! (IGN_ERRORS & curp.fflags))
+               if ( ! (FL_IGN_ERRORS & curp.fflags))
                        rc = 1 == c ? 1 : 0;
                else
                        rc = -1 == c ? 0 : 1;
@@ -176,7 +180,7 @@ main(int argc, char *argv[])
 
        while (rc && *argv) {
                c = ffile(&blk, &ln, *argv, &curp);
-               if ( ! (IGN_ERRORS & curp.fflags))
+               if ( ! (FL_IGN_ERRORS & curp.fflags))
                        rc = 1 == c ? 1 : 0;
                else
                        rc = -1 == c ? 0 : 1;
@@ -240,11 +244,11 @@ man_init(struct curparse *curp)
 
        pflags = MAN_IGN_MACRO | MAN_IGN_ESCAPE | MAN_IGN_CHARS;
 
-       if (curp->fflags & NO_IGN_MACRO)
+       if (curp->fflags & FL_NIGN_MACRO)
                pflags &= ~MAN_IGN_MACRO;
-       if (curp->fflags & NO_IGN_CHARS)
+       if (curp->fflags & FL_NIGN_CHARS)
                pflags &= ~MAN_IGN_CHARS;
-       if (curp->fflags & NO_IGN_ESCAPE)
+       if (curp->fflags & FL_NIGN_ESCAPE)
                pflags &= ~MAN_IGN_ESCAPE;
 
        return(man_alloc(curp, pflags, &mancb));
@@ -264,13 +268,13 @@ mdoc_init(struct curparse *curp)
 
        pflags = MDOC_IGN_MACRO | MDOC_IGN_ESCAPE | MDOC_IGN_CHARS;
 
-       if (curp->fflags & IGN_SCOPE)
+       if (curp->fflags & FL_IGN_SCOPE)
                pflags |= MDOC_IGN_SCOPE;
-       if (curp->fflags & NO_IGN_ESCAPE)
+       if (curp->fflags & FL_NIGN_ESCAPE)
                pflags &= ~MDOC_IGN_ESCAPE;
-       if (curp->fflags & NO_IGN_MACRO)
+       if (curp->fflags & FL_NIGN_MACRO)
                pflags &= ~MDOC_IGN_MACRO;
-       if (curp->fflags & NO_IGN_CHARS)
+       if (curp->fflags & FL_NIGN_CHARS)
                pflags &= ~MDOC_IGN_CHARS;
 
        return(mdoc_alloc(curp, pflags, &mdoccb));
@@ -542,19 +546,22 @@ moptions(enum intt *tflags, char *arg)
 
 
 static int
-toptions(enum outt *tflags, char *arg)
+toptions(struct curparse *curp, char *arg)
 {
 
        if (0 == strcmp(arg, "ascii"))
-               *tflags = OUTT_ASCII;
-       else if (0 == strcmp(arg, "lint"))
-               *tflags = OUTT_LINT;
+               curp->outtype = OUTT_ASCII;
+       else if (0 == strcmp(arg, "lint")) {
+               curp->outtype = OUTT_LINT;
+               curp->wflags |= WARN_WALL;
+               curp->fflags |= FL_STRICT;
+       }
        else if (0 == strcmp(arg, "tree"))
-               *tflags = OUTT_TREE;
+               curp->outtype = OUTT_TREE;
        else if (0 == strcmp(arg, "html"))
-               *tflags = OUTT_HTML;
+               curp->outtype = OUTT_HTML;
        else if (0 == strcmp(arg, "xhtml"))
-               *tflags = OUTT_XHTML;
+               curp->outtype = OUTT_XHTML;
        else {
                fprintf(stderr, "%s: Bad argument\n", arg);
                return(0);
@@ -583,26 +590,25 @@ foptions(int *fflags, char *arg)
                o = arg;
                switch (getsubopt(&arg, UNCONST(toks), &v)) {
                case (0):
-                       *fflags |= IGN_SCOPE;
+                       *fflags |= FL_IGN_SCOPE;
                        break;
                case (1):
-                       *fflags |= NO_IGN_ESCAPE;
+                       *fflags |= FL_NIGN_ESCAPE;
                        break;
                case (2):
-                       *fflags |= NO_IGN_MACRO;
+                       *fflags |= FL_NIGN_MACRO;
                        break;
                case (3):
-                       *fflags |= NO_IGN_CHARS;
+                       *fflags |= FL_NIGN_CHARS;
                        break;
                case (4):
-                       *fflags |= IGN_ERRORS;
+                       *fflags |= FL_IGN_ERRORS;
                        break;
                case (5):
-                       *fflags |= NO_IGN_ESCAPE |
-                                  NO_IGN_MACRO | NO_IGN_CHARS;
+                       *fflags |= FL_STRICT;
                        break;
                case (6):
-                       *fflags &= ~NO_IGN_ESCAPE;
+                       *fflags &= ~FL_NIGN_ESCAPE;
                        break;
                default:
                        fprintf(stderr, "%s: Bad argument\n", o);
index 6a03afa..c139142 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: man.3,v 1.12 2010/02/17 19:22:01 kristaps Exp $
+.\"    $Id: man.3,v 1.13 2010/03/27 10:04:56 kristaps Exp $
 .\"
 .\" Copyright (c) 2009-2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd February 20, 2010
+.Dd March 27, 2010
 .Dt MAN 3
 .Os
-.\" SECTION
+.
+.
 .Sh NAME
+.Nm man ,
 .Nm man_alloc ,
 .Nm man_parseln ,
 .Nm man_endparse ,
@@ -27,7 +29,8 @@
 .Nm man_free ,
 .Nm man_reset
 .Nd man macro compiler library
-.\" SECTION
+.
+.
 .Sh SYNOPSIS
 .In man.h
 .Vt extern const char * const * man_macronames;
 .Fn man_meta "const struct man *man"
 .Ft int
 .Fn man_endparse "struct man *man"
-.\" SECTION
+.
+.
 .Sh DESCRIPTION
 The
-.Nm man
+.Nm
 library parses lines of
 .Xr man 7
 input (and
 .Em only
 man) into an abstract syntax tree (AST).
-.\" PARAGRAPH
+.
 .Pp
 In general, applications initiate a parsing sequence with
 .Fn man_alloc ,
@@ -74,8 +78,58 @@ function may be used in order to reset the parser for another input
 sequence.  See the
 .Sx EXAMPLES
 section for a full example.
-.\" PARAGRAPH
+.
+.Pp
+Beyond the full set of macros defined in
+.Xr man 7 ,
+the
+.Nm
+library also accepts the following macros:
+.
 .Pp
+.Bl -tag -width Ds -compact
+.It am
+.It ami
+.It de
+.It dei
+.It ig
+Instructional macros in the original roff language.  Blocks begun by
+these macros end with
+.Sq ..
+and may begin anywhere, although they may not break the next-line
+scoping rules specified in
+.Xr man 7 .
+These blocks are discarded.
+.
+.It PD
+Has no effect.  Handled as a current-scope line macro.
+.
+.It Sp
+A synonym for
+.Sq sp 0.5v
+.Pq part of the standard preamble for Perl documentation .
+Handled as a line macro.
+.
+.It UC
+Has no effect.  Handled as a current-scope line macro.
+.
+.It Vb
+A synonym for
+.Sq nf
+.Pq part of the standard preamble for Perl documentation .
+Handled as a current-scope line macro.
+.
+.It Ve
+A synonym for
+.Sq fi ,
+closing
+.Sq Vb
+.Pq part of the standard preamble for Perl documentation .
+Handled as a current-scope line macro.
+.El
+.
+.
+.Sh REFERENCE
 This section further defines the
 .Sx Types ,
 .Sx Functions
@@ -84,7 +138,8 @@ and
 available to programmers.  Following that, the
 .Sx Abstract Syntax Tree
 section documents the output tree.
-.\" SUBSECTION
+.
+.
 .Ss Types
 Both functions (see
 .Sx Functions )
@@ -92,16 +147,16 @@ and variables (see
 .Sx Variables )
 may use the following types:
 .Bl -ohang
-.\" LIST-ITEM
+.
 .It Vt struct man
 An opaque type defined in
 .Pa man.c .
 Its values are only used privately within the library.
-.\" LIST-ITEM
+.
 .It Vt struct man_cb
 A set of message callbacks defined in
 .Pa man.h .
-.\" LIST-ITEM
+.
 .It Vt struct man_node
 A parsed node.  Defined in
 .Pa man.h .
@@ -109,11 +164,12 @@ See
 .Sx Abstract Syntax Tree
 for details.
 .El
-.\" SUBSECTION
+.
+.
 .Ss Functions
 Function descriptions follow:
 .Bl -ohang
-.\" LIST-ITEM
+.
 .It Fn man_alloc
 Allocates a parsing structure.  The
 .Fa data
@@ -126,29 +182,29 @@ arguments are defined in
 .Pa man.h .
 Returns NULL on failure.  If non-NULL, the pointer must be freed with
 .Fn man_free .
-.\" LIST-ITEM
+.
 .It Fn man_reset
 Reset the parser for another parse routine.  After its use,
 .Fn man_parseln
 behaves as if invoked for the first time.
-.\" LIST-ITEM
+.
 .It Fn man_free
 Free all resources of a parser.  The pointer is no longer valid after
 invocation.
-.\" LIST-ITEM
+.
 .It Fn man_parseln
 Parse a nil-terminated line of input.  This line should not contain the
 trailing newline.  Returns 0 on failure, 1 on success.  The input buffer
 .Fa buf
 is modified by this function.
-.\" LIST-ITEM
+.
 .It Fn man_endparse
 Signals that the parse is complete.  Note that if
 .Fn man_endparse
 is called subsequent to
 .Fn man_node ,
 the resulting tree is incomplete.  Returns 0 on failure, 1 on success.
-.\" LIST-ITEM
+.
 .It Fn man_node
 Returns the first node of the parse.  Note that if
 .Fn man_parseln
@@ -163,15 +219,17 @@ or
 .Fn man_endparse
 return 0, the data will be incomplete.
 .El
-.\" SUBSECTION
+.
+.
 .Ss Variables
 The following variables are also defined:
 .Bl -ohang
-.\" LIST-ITEM
+.
 .It Va man_macronames
 An array of string-ified token names.
 .El
-.\" SUBSECTION
+.
+.
 .Ss Abstract Syntax Tree
 The
 .Nm
@@ -185,13 +243,13 @@ or after
 or
 .Fn man_parseln
 fail, it may be incomplete.
-.\" PARAGRAPH
+.
 .Pp
 This AST is governed by the ontological
 rules dictated in
 .Xr man 7
 and derives its terminology accordingly.
-.\" PARAGRAPH
+.
 .Pp
 The AST is composed of
 .Vt struct man_node
@@ -210,13 +268,12 @@ fields), its position in the tree (the
 and
 .Va prev
 fields) and some type-specific data.
-.\" PARAGRAPH
+.
 .Pp
 The tree itself is arranged according to the following normal form,
 where capitalised non-terminals represent nodes.
 .Pp
 .Bl -tag -width "ELEMENTXX" -compact
-.\" LIST-ITEM
 .It ROOT
 \(<- mnode+
 .It mnode
@@ -232,12 +289,13 @@ where capitalised non-terminals represent nodes.
 .It TEXT
 \(<- [[:alpha:]]*
 .El
-.\" PARAGRAPH
+.
 .Pp
 The only elements capable of nesting other elements are those with
 next-lint scope as documented in
 .Xr man 7 .
-.\" SECTION
+.
+.
 .Sh EXAMPLES
 The following example reads lines from stdin and parses them, operating
 on the finished parse tree with
@@ -273,11 +331,13 @@ if (NULL == (node = man_node(man)))
 parsed(man, node);
 man_free(man);
 .Ed
-.\" SECTION
+.
+.
 .Sh SEE ALSO
 .Xr mandoc 1 ,
 .Xr man 7
-.\" SECTION
+.
+.
 .Sh AUTHORS
 The
 .Nm
index 8e09c6b..6aa434c 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: man.7,v 1.55 2010/01/07 19:10:09 kristaps Exp $
+.\"    $Id: man.7,v 1.60 2010/03/27 10:22:28 kristaps Exp $
 .\"
 .\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd February 20, 2010
+.Dd March 27, 2010
 .Dt MAN 7
 .Os
 .
@@ -403,9 +403,11 @@ Documents any security precautions that operators should consider.
 Macros are one to three three characters in length and begin with a
 control character ,
 .Sq \&. ,
-at the beginning of the line.  An arbitrary amount of whitespace may
-sit between the control character and the macro name.  Thus, the
-following are equivalent:
+at the beginning of the line.  The
+.Sq \(aq
+macro control character is also accepted.  An arbitrary amount of
+whitespace (spaces or tabs) may sit between the control character and
+the macro name.  Thus, the following are equivalent:
 .Bd -literal -offset indent
 \&.PP
 \&.\ \ \ PP
@@ -423,8 +425,8 @@ subsequent lines until closed by another block macro.
 .Ss Line Macros
 Line macros are generally scoped to the current line, with the body
 consisting of zero or more arguments.  If a macro is scoped to the next
-line and the line arguments are empty, the next line is used instead,
-else the general syntax is used.  Thus:
+line and the line arguments are empty, the next line, which must be
+text, is used instead.  Thus:
 .Bd -literal -offset indent
 \&.I
 foo
@@ -433,63 +435,69 @@ foo
 .Pp
 is equivalent to
 .Sq \&.I foo .
-If next-line macros are invoked consecutively, only the last is used; in
-other words, if a next-line macro is preceded by a block macro, it is
-ignored.
+If next-line macros are invoked consecutively, only the last is used.
+If a next-line macro is followed by a non-next-line macro, an error is
+raised (unless in the case of
+.Sx \&br ,
+.Sx \&sp ,
+.Sx \&Sp ,
+or
+.Sx \&na ) .
+.Pp
+The syntax is as follows:
 .Bd -literal -offset indent
 \&.YO \(lBbody...\(rB
 \(lBbody...\(rB
 .Ed
 .
 .Pp
-.Bl -column -compact -offset indent "MacroX" "ArgumentsX" "ScopeXXXXX"
-.It Em Macro Ta Em Arguments Ta Em Scope
-.It Sx \&B   Ta    n         Ta    next-line
-.It Sx \&BI  Ta    n         Ta    current
-.It Sx \&BR  Ta    n         Ta    current
-.It Sx \&DT  Ta    0         Ta    current
-.It Sx \&I   Ta    n         Ta    next-line
-.It Sx \&IB  Ta    n         Ta    current
-.It Sx \&IR  Ta    n         Ta    current
-.It Sx \&PD  Ta    n         Ta    current
-.It Sx \&R   Ta    n         Ta    next-line
-.It Sx \&RB  Ta    n         Ta    current
-.It Sx \&RI  Ta    n         Ta    current
-.It Sx \&SB  Ta    n         Ta    next-line
-.It Sx \&SM  Ta    n         Ta    next-line
-.It Sx \&TH  Ta    >1, <6    Ta    current
-.It Sx \&UC  Ta    n         Ta    current
-.It Sx \&br  Ta    0         Ta    current
-.It Sx \&fi  Ta    0         Ta    current
-.It Sx \&i   Ta    n         Ta    current
-.It Sx \&na  Ta    0         Ta    current
-.It Sx \&nf  Ta    0         Ta    current
-.It Sx \&r   Ta    0         Ta    current
-.It Sx \&sp  Ta    1         Ta    current
+.Bl -column -compact -offset indent "MacroX" "ArgumentsX" "ScopeXXXXX" "CompatX"
+.It Em Macro Ta Em Arguments Ta Em Scope     Ta Em Notes
+.It Sx \&B   Ta    n         Ta    next-line Ta    \&
+.It Sx \&BI  Ta    n         Ta    current   Ta    \&
+.It Sx \&BR  Ta    n         Ta    current   Ta    \&
+.It Sx \&DT  Ta    0         Ta    current   Ta    \&
+.It Sx \&I   Ta    n         Ta    next-line Ta    \&
+.It Sx \&IB  Ta    n         Ta    current   Ta    \&
+.It Sx \&IR  Ta    n         Ta    current   Ta    \&
+.\" .It Sx \&PD  Ta    n         Ta    current   Ta    compat
+.It Sx \&R   Ta    n         Ta    next-line Ta    \&
+.It Sx \&RB  Ta    n         Ta    current   Ta    \&
+.It Sx \&RI  Ta    n         Ta    current   Ta    \&
+.It Sx \&SB  Ta    n         Ta    next-line Ta    \&
+.It Sx \&SM  Ta    n         Ta    next-line Ta    \&
+.It Sx \&TH  Ta    >1, <6    Ta    current   Ta    \&
+.\" .It Sx \&UC  Ta    n         Ta    current   Ta    compat
+.It Sx \&br  Ta    0         Ta    current   Ta    compat
+.It Sx \&fi  Ta    0         Ta    current   Ta    compat
+.It Sx \&i   Ta    n         Ta    current   Ta    compat
+.It Sx \&na  Ta    0         Ta    current   Ta    compat
+.It Sx \&nf  Ta    0         Ta    current   Ta    compat
+.It Sx \&r   Ta    0         Ta    current   Ta    compat
+.It Sx \&sp  Ta    1         Ta    current   Ta    compat
+.\" .It Sx \&Sp  Ta    0         Ta    current   Ta    compat
+.\" .It Sx \&Vb  Ta    <1        Ta    current   Ta    compat
+.\" .It Sx \&Ve  Ta    0         Ta    current   Ta    compat
 .El
 .
 .Pp
-The
-.Sx \&PD ,
-.Sx \&RS ,
-.Sx \&RE ,
-.Sx \&UC ,
-.Sx \&br ,
-.Sx \&fi ,
-.Sx \&i ,
-.Sx \&na ,
-.Sx \&nf ,
-.Sx \&r ,
-and
-.Sx \&sp
-macros should not be used.  They're included for compatibility.
+Macros marked as
+.Qq compat
+are included for compatibility with the significant corpus of existing
+manuals that mix dialects of roff.  These macros should not be used for
+portable
+.Nm
+manuals.
 .
 .
 .Ss Block Macros
 Block macros are comprised of a head and body.  Like for in-line macros,
 the head is scoped to the current line and, in one circumstance, the
-next line; the body is scoped to subsequent lines and is closed out by a
-subsequent block macro invocation.
+next line (the next-line stipulations as in
+.Sx Line Macros
+apply here as well).
+.Pp
+The syntax is as follows:
 .Bd -literal -offset indent
 \&.YO \(lBhead...\(rB
 \(lBhead...\(rB
@@ -515,33 +523,34 @@ or
 No closure refers to an explicit block closing macro.
 .
 .Pp
-.Bl -column "MacroX" "ArgumentsX" "Head ScopeX" "sub-sectionX" -compact -offset indent
-.It Em Macro Ta Em Arguments Ta Em Head Scope Ta Em Body Scope
-.It Sx \&HP  Ta    <2        Ta    current    Ta    paragraph
-.It Sx \&IP  Ta    <3        Ta    current    Ta    paragraph
-.It Sx \&LP  Ta    0         Ta    current    Ta    paragraph
-.It Sx \&P   Ta    0         Ta    current    Ta    paragraph
-.It Sx \&PP  Ta    0         Ta    current    Ta    paragraph
-.It Sx \&RE  Ta    0         Ta    current    Ta    none
-.It Sx \&RS  Ta    1         Ta    current    Ta    part
-.It Sx \&SH  Ta    >0        Ta    next-line  Ta    section
-.It Sx \&SS  Ta    >0        Ta    next-line  Ta    sub-section
-.It Sx \&TP  Ta    n         Ta    next-line  Ta    paragraph
+As a rule, block macros may not be nested; thus, calling a block macro
+while another block macro scope is open, and the open scope is not
+implicitly closed, is syntactically incorrect.
+.
+.Pp
+.Bl -column -compact -offset indent "MacroX" "ArgumentsX" "Head ScopeX" "sub-sectionX" "compatX"
+.It Em Macro Ta Em Arguments Ta Em Head Scope Ta Em Body Scope  Ta Em Notes
+.It Sx \&HP  Ta    <2        Ta    current    Ta    paragraph   Ta    \&
+.It Sx \&IP  Ta    <3        Ta    current    Ta    paragraph   Ta    \&
+.It Sx \&LP  Ta    0         Ta    current    Ta    paragraph   Ta    \&
+.It Sx \&P   Ta    0         Ta    current    Ta    paragraph   Ta    \&
+.It Sx \&PP  Ta    0         Ta    current    Ta    paragraph   Ta    \&
+.It Sx \&RE  Ta    0         Ta    current    Ta    none        Ta    compat
+.It Sx \&RS  Ta    1         Ta    current    Ta    part        Ta    compat
+.It Sx \&SH  Ta    >0        Ta    next-line  Ta    section     Ta    \&
+.It Sx \&SS  Ta    >0        Ta    next-line  Ta    sub-section Ta    \&
+.It Sx \&TP  Ta    n         Ta    next-line  Ta    paragraph   Ta    \&
 .El
+.Pp
+.
+Macros marked
+.Qq compat
+are as mentioned in
+.Sx Line Macros .
 .
 .Pp
 If a block macro is next-line scoped, it may only be followed by in-line
-macros (excluding
-.Sx \&DT ,
-.Sx \&PD ,
-.Sx \&TH ,
-.Sx \&UC ,
-.Sx \&br ,
-.Sx \&na ,
-.Sx \&sp ,
-.Sx \&nf ,
-and
-.Sx \&fi ) .
+macros for decorating text.
 .
 .
 .Sh REFERENCE
@@ -896,14 +905,14 @@ See also
 .Sx \&P ,
 and
 .Sx \&PP .
-.
-.
-.Ss \&PD
-Has no effect.  Included for compatibility.
-.
-.
-.Ss \&UC
-Has no effect.  Included for compatibility.
+.\" .
+.\" .
+.\" .Ss \&PD
+.\" Has no effect.  Included for compatibility.
+.\" .
+.\" .
+.\" .Ss \&UC
+.\" Has no effect.  Included for compatibility.
 .
 .
 .Ss \&br
@@ -971,31 +980,54 @@ macro.  Defaults to 1, if unspecified.
 See also
 .Sx \&br .
 .
+.\" .Ss \&Sp
+.\" A synonym for
+.\" .Sx \&sp
+.\" .Cm 0.5v .
+.\" .
+.\" .Ss \&Vb
+.\" A synonym for
+.\" .Sx \&nf .
+.\" Accepts an argument (the height of the formatted space) which is
+.\" disregarded.
+.\" .
+.\" .Ss \&Ve
+.\" A synonym for
+.\" .Sx \&fi .
+.\" .
 .
 .Sh COMPATIBILITY
-This section documents compatibility with other roff implementations, at
-this time limited to
-.Xr groff 1 .
+This section documents areas of questionable portability between
+implementations of the
+.Nm
+language.
+.
 .Pp
 .Bl -dash -compact
 .It
-The
-.Xr groff 1
-.Sx \&i
-macro will italicise all subsequent text if a line argument is not
-provided.  This behaviour is not implemented.
+In quoted literals, GNU troff allowed pair-wise double-quotes to produce
+a standalone double-quote in formatted output.  It is not known whether
+this behaviour is exhibited by other formatters.
+.
 .It
-In quoted literals, groff allowed pair-wise double-quotes to produce a
-standalone double-quote in formatted output.  This idiosyncratic
-behaviour is no longer applicable.
+Blocks of whitespace are stripped from macro and free-form text lines
+(except when in literal mode) in mandoc.  This is not the case for GNU
+troff: for maximum portability, whitespace sensitive blocks should be
+enclosed in literal contexts.
+.
 .It
 The
 .Sx \&sp
-macro does not accept negative numbers.
+macro does not accept negative values in mandoc.  In GNU troff, this
+would result in strange behaviour.
+.
 .It
-Blocks of whitespace are stripped from both macro and free-form text
-lines (except when in literal mode), while groff would retain whitespace
-in free-form text lines.
+The
+.Sq \(aq
+macro control character, in GNU troff (and prior troffs) suppresses a
+newline before macro output; in mandoc, it is an alias for the standard
+.Sq \&.
+control character.
 .El
 .
 .
index 721fcff..7b84ee5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man.c,v 1.49 2010/01/07 10:24:43 kristaps Exp $ */
+/*     $Id: man.c,v 1.57 2010/03/27 10:26:39 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -31,6 +31,7 @@ const char *const __man_merrnames[WERRMAX] = {
        "invalid manual section", /* WMSEC */
        "invalid date format", /* WDATE */
        "scope of prior line violated", /* WLNSCOPE */
+       "over-zealous prior line scope violation", /* WLNSCOPE2 */
        "trailing whitespace", /* WTSPACE */
        "unterminated quoted parameter", /* WTQUOTE */
        "document has no body", /* WNODATA */
@@ -44,7 +45,10 @@ const        char *const __man_merrnames[WERRMAX] = {
        "scope open on exit", /* WEXITSCOPE */
        "no scope context", /* WNOSCOPE */
        "literal context already open", /* WOLITERAL */
-       "no literal context open" /* WNLITERAL */
+       "no literal context open", /* WNLITERAL */
+       "invalid nesting of roff declarations", /* WROFFNEST */
+       "scope in roff instructions broken", /* WROFFSCOPE */
+       "document title should be uppercase", /* WTITLECASE */
 };
 
 const  char *const __man_macronames[MAN_MAX] = {
@@ -55,15 +59,21 @@ const       char *const __man_macronames[MAN_MAX] = {
        "R",            "B",            "I",            "IR",
        "RI",           "na",           "i",            "sp",
        "nf",           "fi",           "r",            "RE",
-       "RS",           "DT",           "UC",           "PD"
+       "RS",           "DT",           "UC",           "PD",
+       "Sp",           "Vb",           "Ve",           "de",
+       "dei",          "am",           "ami",          "ig",
+       ".",
        };
 
 const  char * const *man_macronames = __man_macronames;
 
 static struct man_node *man_node_alloc(int, int,
-                               enum man_type, int);
+                               enum man_type, enum mant);
 static int              man_node_append(struct man *,
                                struct man_node *);
+static void             man_node_free(struct man_node *);
+static void             man_node_unlink(struct man *,
+                               struct man_node *);
 static int              man_ptext(struct man *, int, char *);
 static int              man_pmacro(struct man *, int, char *);
 static void             man_free1(struct man *);
@@ -143,7 +153,7 @@ int
 man_parseln(struct man *m, int ln, char *buf)
 {
 
-       return('.' == *buf ?
+       return('.' == *buf || '\'' == *buf ?
                        man_pmacro(m, ln, buf) :
                        man_ptext(m, ln, buf));
 }
@@ -154,7 +164,7 @@ man_free1(struct man *man)
 {
 
        if (man->first)
-               man_node_freelist(man->first);
+               man_node_delete(man, man->first);
        if (man->meta.title)
                free(man->meta.title);
        if (man->meta.source)
@@ -173,6 +183,7 @@ man_alloc1(struct man *m)
        m->last = mandoc_calloc(1, sizeof(struct man_node));
        m->first = m->last;
        m->last->type = MAN_ROOT;
+       m->last->tok = MAN_MAX;
        m->next = MAN_NEXT_CHILD;
 }
 
@@ -200,6 +211,7 @@ man_node_append(struct man *man, struct man_node *p)
                /* NOTREACHED */
        }
 
+       assert(p->parent);
        p->parent->nchild++;
 
        if ( ! man_valid_pre(man, p))
@@ -236,7 +248,7 @@ man_node_append(struct man *man, struct man_node *p)
 
 
 static struct man_node *
-man_node_alloc(int line, int pos, enum man_type type, int tok)
+man_node_alloc(int line, int pos, enum man_type type, enum mant tok)
 {
        struct man_node *p;
 
@@ -250,7 +262,7 @@ man_node_alloc(int line, int pos, enum man_type type, int tok)
 
 
 int
-man_elem_alloc(struct man *m, int line, int pos, int tok)
+man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
@@ -263,7 +275,7 @@ man_elem_alloc(struct man *m, int line, int pos, int tok)
 
 
 int
-man_head_alloc(struct man *m, int line, int pos, int tok)
+man_head_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
@@ -276,7 +288,7 @@ man_head_alloc(struct man *m, int line, int pos, int tok)
 
 
 int
-man_body_alloc(struct man *m, int line, int pos, int tok)
+man_body_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
@@ -289,7 +301,7 @@ man_body_alloc(struct man *m, int line, int pos, int tok)
 
 
 int
-man_block_alloc(struct man *m, int line, int pos, int tok)
+man_block_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
@@ -308,7 +320,7 @@ pstring(struct man *m, int line, int pos,
        struct man_node *n;
        size_t           sv;
 
-       n = man_node_alloc(line, pos, MAN_TEXT, -1);
+       n = man_node_alloc(line, pos, MAN_TEXT, MAN_MAX);
        n->string = mandoc_malloc(len + 1);
        sv = strlcpy(n->string, p, len + 1);
 
@@ -330,30 +342,29 @@ man_word_alloc(struct man *m, int line, int pos, const char *word)
 }
 
 
-void
+/*
+ * Free all of the resources held by a node.  This does NOT unlink a
+ * node from its context; for that, see man_node_unlink().
+ */
+static void
 man_node_free(struct man_node *p)
 {
 
        if (p->string)
                free(p->string);
-       if (p->parent)
-               p->parent->nchild--;
        free(p);
 }
 
 
 void
-man_node_freelist(struct man_node *p)
+man_node_delete(struct man *m, struct man_node *p)
 {
-       struct man_node *n;
 
-       if (p->child)
-               man_node_freelist(p->child);
-       assert(0 == p->nchild);
-       n = p->next;
+       while (p->child)
+               man_node_delete(m, p->child);
+
+       man_node_unlink(m, p);
        man_node_free(p);
-       if (n)
-               man_node_freelist(n);
 }
 
 
@@ -434,7 +445,7 @@ descope:
 
        if (MAN_ELINE & m->flags) {
                m->flags &= ~MAN_ELINE;
-               if ( ! man_unscope(m, m->last->parent))
+               if ( ! man_unscope(m, m->last->parent, WERRMAX))
                        return(0);
        }
 
@@ -442,7 +453,7 @@ descope:
                return(1);
        m->flags &= ~MAN_BLINE;
 
-       if ( ! man_unscope(m, m->last->parent))
+       if ( ! man_unscope(m, m->last->parent, WERRMAX))
                return(0);
        return(man_body_alloc(m, line, 0, m->last->tok));
 }
@@ -463,7 +474,8 @@ macrowarn(struct man *m, int ln, const char *buf)
 int
 man_pmacro(struct man *m, int ln, char *buf)
 {
-       int              i, j, c, ppos, fl;
+       int              i, j, ppos, fl;
+       enum mant        tok;
        char             mac[5];
        struct man_node *n;
 
@@ -476,9 +488,13 @@ man_pmacro(struct man *m, int ln, char *buf)
 
        i = 1;
 
-       if (' ' == buf[i]) {
+       /*
+        * Skip whitespace between the control character and initial
+        * text.  "Whitespace" is both spaces and tabs.
+        */
+       if (' ' == buf[i] || '\t' == buf[i]) {
                i++;
-               while (buf[i] && ' ' == buf[i])
+               while (buf[i] && (' ' == buf[i] || '\t' == buf[i]))
                        i++;
                if ('\0' == buf[i])
                        goto out;
@@ -513,7 +529,7 @@ man_pmacro(struct man *m, int ln, char *buf)
                return(1);
        }
 
-       if (MAN_MAX == (c = man_hash_find(mac))) {
+       if (MAN_MAX == (tok = man_hash_find(mac))) {
                if ( ! macrowarn(m, ln, mac))
                        goto err;
                return(1);
@@ -530,42 +546,71 @@ man_pmacro(struct man *m, int ln, char *buf)
                if ( ! man_pwarn(m, ln, i - 1, WTSPACE))
                        goto err;
 
-       /* Remove prior ELINE macro, if applicable. */
+       /*
+        * Remove prior ELINE macro, as it's being clobbering by a new
+        * macro.  Note that NSCOPED macros do not close out ELINE
+        * macros---they don't print text---so we let those slip by.
+        */
+
+       if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
+                       m->flags & MAN_ELINE) {
+               assert(MAN_TEXT != m->last->type);
+
+               /*
+                * This occurs in the following construction:
+                *   .B
+                *   .br
+                *   .B
+                *   .br
+                *   I hate man macros.
+                * Flat-out disallow this madness.
+                */
+               if (MAN_NSCOPED & man_macros[m->last->tok].flags)
+                       return(man_perr(m, ln, ppos, WLNSCOPE));
 
-       if (m->flags & MAN_ELINE) {
                n = m->last;
+
+               assert(n);
                assert(NULL == n->child);
                assert(0 == n->nchild);
+
                if ( ! man_nwarn(m, n, WLNSCOPE))
                        return(0);
 
-               if (n->prev) {
-                       assert(n != n->parent->child);
-                       assert(n == n->prev->next);
-                       n->prev->next = NULL;
-                       m->last = n->prev;
-                       m->next = MAN_NEXT_SIBLING;
-               } else {
-                       assert(n == n->parent->child);
-                       n->parent->child = NULL;
-                       m->last = n->parent;
-                       m->next = MAN_NEXT_CHILD;
-               }
-
-               man_node_free(n);
+               man_node_delete(m, n);
                m->flags &= ~MAN_ELINE;
        }
 
        /* Begin recursive parse sequence. */
 
-       assert(man_macros[c].fp);
+       assert(man_macros[tok].fp);
 
-       if ( ! (*man_macros[c].fp)(m, c, ln, ppos, &i, buf))
+       if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &i, buf))
                goto err;
 
 out:
-       if ( ! (MAN_BLINE & fl))
+       /*
+        * We weren't in a block-line scope when entering the
+        * above-parsed macro, so return.
+        *
+        * FIXME: this prohibits the nesting of blocks (e.g., `de' and
+        * family) within BLINE or ELINE systems.  This is annoying.
+        */
+
+       if ( ! (MAN_BLINE & fl)) {
+               m->flags &= ~MAN_ILINE;
                return(1);
+       }
+
+       /*
+        * If we're in a block scope, then allow this macro to slip by
+        * without closing scope around it.
+        */
+
+       if (MAN_ILINE & m->flags) {
+               m->flags &= ~MAN_ILINE;
+               return(1);
+       }
 
        /*
         * If we've opened a new next-line element scope, then return
@@ -580,7 +625,7 @@ out:
        assert(MAN_BLINE & m->flags);
        m->flags &= ~MAN_BLINE;
 
-       if ( ! man_unscope(m, m->last->parent))
+       if ( ! man_unscope(m, m->last->parent, WERRMAX))
                return(0);
        return(man_body_alloc(m, ln, 0, m->last->tok));
 
@@ -636,3 +681,45 @@ man_err(struct man *m, int line, int pos, int iserr, enum merr type)
 
        return(man_vwarn(m, line, pos, p));
 }
+
+
+/*
+ * Unlink a node from its context.  If "m" is provided, the last parse
+ * point will also be adjusted accordingly.
+ */
+static void
+man_node_unlink(struct man *m, struct man_node *n)
+{
+
+       /* Adjust siblings. */
+
+       if (n->prev)
+               n->prev->next = n->next;
+       if (n->next)
+               n->next->prev = n->prev;
+
+       /* Adjust parent. */
+
+       if (n->parent) {
+               n->parent->nchild--;
+               if (n->parent->child == n)
+                       n->parent->child = n->prev ? n->prev : n->next;
+       }
+
+       /* Adjust parse point, if applicable. */
+
+       if (m && m->last == n) {
+               /*XXX: this can occur when bailing from validation. */
+               /*assert(NULL == n->next);*/
+               if (n->prev) {
+                       m->last = n->prev;
+                       m->next = MAN_NEXT_SIBLING;
+               } else {
+                       m->last = n->parent;
+                       m->next = MAN_NEXT_CHILD;
+               }
+       }
+
+       if (m && m->first == n)
+               m->first = NULL;
+}
index efb8568..cbcbaea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man.h,v 1.23 2009/10/30 05:58:37 kristaps Exp $ */
+/*     $Id: man.h,v 1.27 2010/03/27 10:13:16 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
 
 #include <time.h>
 
-#define        MAN_br           0
-#define        MAN_TH           1
-#define        MAN_SH           2
-#define        MAN_SS           3
-#define        MAN_TP           4
-#define        MAN_LP           5
-#define        MAN_PP           6
-#define        MAN_P            7
-#define        MAN_IP           8
-#define        MAN_HP           9
-#define        MAN_SM           10
-#define        MAN_SB           11
-#define        MAN_BI           12
-#define        MAN_IB           13
-#define        MAN_BR           14
-#define        MAN_RB           15
-#define        MAN_R            16
-#define        MAN_B            17
-#define        MAN_I            18
-#define        MAN_IR           19
-#define        MAN_RI           20
-#define        MAN_na           21
-#define        MAN_i            22
-#define        MAN_sp           23
-#define        MAN_nf           24
-#define        MAN_fi           25
-#define        MAN_r            26
-#define        MAN_RE           27
-#define        MAN_RS           28
-#define        MAN_DT           29
-#define        MAN_UC           30
-#define        MAN_PD           31
-#define        MAN_MAX          32
+enum   mant {
+       MAN_br = 0,
+       MAN_TH,
+       MAN_SH,
+       MAN_SS,
+       MAN_TP,
+       MAN_LP,
+       MAN_PP,
+       MAN_P,
+       MAN_IP,
+       MAN_HP,
+       MAN_SM,
+       MAN_SB,
+       MAN_BI,
+       MAN_IB,
+       MAN_BR,
+       MAN_RB,
+       MAN_R,
+       MAN_B,
+       MAN_I,
+       MAN_IR,
+       MAN_RI,
+       MAN_na,
+       MAN_i,
+       MAN_sp,
+       MAN_nf,
+       MAN_fi,
+       MAN_r,
+       MAN_RE,
+       MAN_RS,
+       MAN_DT,
+       MAN_UC,
+       MAN_PD,
+       MAN_Sp,
+       MAN_Vb,
+       MAN_Ve,
+       MAN_de,
+       MAN_dei,
+       MAN_am,
+       MAN_ami,
+       MAN_ig,
+       MAN_dot,
+       MAN_MAX
+};
 
 enum   man_type {
        MAN_TEXT,
@@ -78,7 +89,7 @@ struct        man_node {
        int              nchild;
        int              line;
        int              pos;
-       int              tok;
+       enum mant        tok;
        int              flags;
 #define        MAN_VALID       (1 << 0)
 #define        MAN_ACTED       (1 << 1)
index e0e801a..de7fa42 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_action.c,v 1.25 2010/01/01 17:14:27 kristaps Exp $ */
+/*     $Id: man_action.c,v 1.30 2010/03/27 10:04:56 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -14,7 +14,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-#include <sys/utsname.h>
 
 #include <assert.h>
 #include <stdlib.h>
@@ -28,6 +27,7 @@ struct        actions {
 };
 
 static int       post_TH(struct man *);
+static int       post_de(struct man *);
 static int       post_fi(struct man *);
 static int       post_nf(struct man *);
 
@@ -64,6 +64,15 @@ const        struct actions man_actions[MAN_MAX] = {
        { NULL }, /* DT */
        { NULL }, /* UC */
        { NULL }, /* PD */
+       { NULL }, /* Sp */
+       { post_nf }, /* Vb */
+       { post_fi }, /* Ve */
+       { post_de }, /* de */
+       { post_de }, /* dei */
+       { post_de }, /* am */
+       { post_de }, /* ami */
+       { post_de }, /* ig */
+       { NULL }, /* . */
 };
 
 
@@ -102,6 +111,20 @@ post_fi(struct man *m)
 }
 
 
+static int
+post_de(struct man *m)
+{
+
+       /*
+        * XXX: for the time being, we indiscriminately remove roff
+        * instructions from the parse stream.
+        */
+       if (MAN_BLOCK == m->last->type)
+               man_node_delete(m, m->last);
+       return(1);
+}
+
+
 static int
 post_nf(struct man *m)
 {
@@ -175,23 +198,9 @@ post_TH(struct man *m)
                m->meta.vol = mandoc_strdup(n->string);
 
        /*
-        * The end document shouldn't have the prologue macros as part
-        * of the syntax tree (they encompass only meta-data).
+        * Remove the `TH' node after we've processed it for our
+        * meta-data.
         */
-
-       if (m->last->parent->child == m->last) {
-               m->last->parent->child = NULL;
-               n = m->last;
-               m->last = m->last->parent;
-               m->next = MAN_NEXT_CHILD;
-       } else {
-               assert(m->last->prev);
-               m->last->prev->next = NULL;
-               n = m->last;
-               m->last = m->last->prev;
-               m->next = MAN_NEXT_SIBLING;
-       }
-
-       man_node_freelist(n);
+       man_node_delete(m, m->last);
        return(1);
 }
index b19d63a..a68c1a5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_hash.c,v 1.16 2010/01/01 17:14:28 kristaps Exp $ */
+/*     $Id: man_hash.c,v 1.18 2010/03/27 10:14:32 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
 #include <sys/types.h>
 
 #include <assert.h>
+#include <ctype.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "libman.h"
 
-static u_char          table[26 * 6];
+#define        HASH_DEPTH       6
+
+#define        HASH_ROW(x) do { \
+               if ('.' == (x)) \
+                       (x) = 26; \
+               else if (isupper((u_char)(x))) \
+                       (x) -= 65; \
+               else \
+                       (x) -= 97; \
+               (x) *= HASH_DEPTH; \
+       } while (/* CONSTCOND */ 0)
+
+/*
+ * Lookup table is indexed first by lower-case first letter (plus one
+ * for the period, which is stored in the last row), then by lower or
+ * uppercase second letter.  Buckets correspond to the index of the
+ * macro (the integer value of the enum stored as a char to save a bit
+ * of space).
+ */
+static u_char           table[27 * HASH_DEPTH];
 
 /*
  * XXX - this hash has global scope, so if intended for use as a library
@@ -36,39 +56,45 @@ man_hash_init(void)
 
        memset(table, UCHAR_MAX, sizeof(table));
 
+       assert(/* LINTED */
+                       MAN_MAX < UCHAR_MAX);
+
        for (i = 0; i < MAN_MAX; i++) {
                x = man_macronames[i][0];
-               assert((x >= 65 && x <= 90) ||
-                               (x >= 97 && x <= 122));
 
-               x -= (x <= 90) ? 65 : 97;
-               x *= 6;
+               assert(isalpha((u_char)x) || '.' == x);
 
-               for (j = 0; j < 6; j++)
+               HASH_ROW(x);
+
+               for (j = 0; j < HASH_DEPTH; j++)
                        if (UCHAR_MAX == table[x + j]) {
                                table[x + j] = (u_char)i;
                                break;
                        }
-               assert(j < 6);
+
+               assert(j < HASH_DEPTH);
        }
 }
 
-int
+
+enum mant
 man_hash_find(const char *tmp)
 {
-       int              x, i, tok;
+       int              x, y, i;
+       enum mant        tok;
 
-       if (0 == (x = tmp[0]))
+       if ('\0' == (x = tmp[0]))
                return(MAN_MAX);
-       if ( ! ((x >= 65 && x <= 90) || (x >= 97 && x <= 122)))
+       if ( ! (isalpha((u_char)x) || '.' == x))
                return(MAN_MAX);
 
-       x -= (x <= 90) ? 65 : 97;
-       x *= 6;
+       HASH_ROW(x);
 
-       for (i = 0; i < 6; i++) {
-               if (UCHAR_MAX == (tok = table[x + i]))
+       for (i = 0; i < HASH_DEPTH; i++) {
+               if (UCHAR_MAX == (y = table[x + i]))
                        return(MAN_MAX);
+
+               tok = (enum mant)y;
                if (0 == strcmp(tmp, man_macronames[tok]))
                        return(tok);
        }
index 4e34937..3b1560d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_html.c,v 1.26 2010/01/29 14:39:38 kristaps Exp $ */
+/*     $Id: man_html.c,v 1.30 2010/03/24 20:10:53 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -99,6 +99,15 @@ static       const struct htmlman mans[MAN_MAX] = {
        { man_ign_pre, NULL }, /* DT */
        { man_ign_pre, NULL }, /* UC */
        { man_ign_pre, NULL }, /* PD */
+       { man_br_pre, NULL }, /* Sp */
+       { man_ign_pre, NULL }, /* Vb */
+       { NULL, NULL }, /* Ve */
+       { man_ign_pre, NULL }, /* de */
+       { man_ign_pre, NULL }, /* dei */
+       { man_ign_pre, NULL }, /* am */
+       { man_ign_pre, NULL }, /* ami */
+       { man_ign_pre, NULL }, /* ig */
+       { NULL, NULL }, /* . */
 };
 
 
@@ -177,6 +186,12 @@ print_man_node(MAN_ARGS)
 
        bufinit(h);
 
+       /*
+        * FIXME: embedded elements within next-line scopes (e.g., `br'
+        * within an empty `B') will cause formatting to be forgotten
+        * due to scope closing out.
+        */
+
        switch (n->type) {
        case (MAN_ROOT):
                child = man_root_pre(m, n, h);
@@ -331,10 +346,18 @@ man_br_pre(MAN_ARGS)
 
        SCALE_VS_INIT(&su, 1);
 
-       if (MAN_sp == n->tok && n->child)
-               a2roffsu(n->child->string, &su, SCALE_VS);
-       else if (MAN_br == n->tok)
+       switch (n->tok) {
+       case (MAN_Sp):
+               SCALE_VS_INIT(&su, 0.5);
+               break;
+       case (MAN_sp):
+               if (n->child)
+                       a2roffsu(n->child->string, &su, SCALE_VS);
+               break;
+       default:
                su.scale = 0;
+               break;
+       }
 
        bufcat_su(h, "height", &su);
        PAIR_STYLE_INIT(&tag, h);
@@ -563,6 +586,8 @@ man_IP_pre(MAN_ARGS)
        SCALE_HS_INIT(&su, INDENT);
        width = 0;
 
+       /* Width is the last token. */
+
        if (MAN_IP == n->tok && NULL != nn)
                if (NULL != (nn = nn->next)) {
                        for ( ; nn->next; nn = nn->next)
@@ -570,8 +595,15 @@ man_IP_pre(MAN_ARGS)
                        width = a2width(nn, &su);
                }
 
-       if (MAN_TP == n->tok && NULL != nn)
-               width = a2width(nn, &su);
+       /* Width is the first token. */
+
+       if (MAN_TP == n->tok && NULL != nn) {
+               /* Skip past non-text children. */
+               while (nn && MAN_TEXT != nn->type)
+                       nn = nn->next;
+               if (nn)
+                       width = a2width(nn, &su);
+       }
 
        if (MAN_BLOCK == n->type) {
                bufcat_su(h, "margin-left", &su);
@@ -596,11 +628,20 @@ man_IP_pre(MAN_ARGS)
        PAIR_STYLE_INIT(&tag, h);
        print_otag(h, TAG_DIV, 1, &tag);
 
-       /* With a length string, manually omit the last child. */
+       /*
+        * Without a length string, we can print all of our children.
+        */
 
        if ( ! width)
                return(1);
 
+       /*
+        * When a length has been specified, we need to carefully print
+        * our child context:  IP gets all children printed but the last
+        * (the width), while TP gets all children printed but the first
+        * (the width).
+        */
+
        if (MAN_IP == n->tok)
                for (nn = n->child; nn->next; nn = nn->next)
                        print_man_node(m, nn, h);
index 408fc8d..f8f892b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_macro.c,v 1.30 2010/01/01 17:14:28 kristaps Exp $ */
+/*     $Id: man_macro.c,v 1.40 2010/03/27 10:14:32 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
 
 #include "libman.h"
 
-#define        REW_REWIND      (0)             /* See rew_scope(). */
-#define        REW_NOHALT      (1)             /* See rew_scope(). */
-#define        REW_HALT        (2)             /* See rew_scope(). */
+enum   rew {
+       REW_REWIND,
+       REW_NOHALT,
+       REW_HALT
+};
 
-static int              in_line_eoln(MACRO_PROT_ARGS);
-static int              blk_imp(MACRO_PROT_ARGS);
 static int              blk_close(MACRO_PROT_ARGS);
+static int              blk_dotted(MACRO_PROT_ARGS);
+static int              blk_exp(MACRO_PROT_ARGS);
+static int              blk_imp(MACRO_PROT_ARGS);
+static int              in_line_eoln(MACRO_PROT_ARGS);
 
-static int              rew_scope(enum man_type, struct man *, int);
-static int              rew_dohalt(int, enum man_type,
+static int              rew_scope(enum man_type,
+                               struct man *, enum mant);
+static enum rew         rew_dohalt(enum mant, enum man_type,
                                const struct man_node *);
-static int              rew_block(int, enum man_type,
+static enum rew         rew_block(enum mant, enum man_type,
                                const struct man_node *);
+static int              rew_warn(struct man *,
+                               struct man_node *, enum merr);
 
 const  struct man_macro __man_macros[MAN_MAX] = {
-       { in_line_eoln, 0 }, /* br */
+       { in_line_eoln, MAN_NSCOPED }, /* br */
        { in_line_eoln, 0 }, /* TH */
        { blk_imp, MAN_SCOPED }, /* SH */
        { blk_imp, MAN_SCOPED }, /* SS */
@@ -57,31 +64,64 @@ const       struct man_macro __man_macros[MAN_MAX] = {
        { in_line_eoln, MAN_SCOPED }, /* I */
        { in_line_eoln, 0 }, /* IR */
        { in_line_eoln, 0 }, /* RI */
-       { in_line_eoln, 0 }, /* na */
+       { in_line_eoln, MAN_NSCOPED }, /* na */
        { in_line_eoln, 0 }, /* i */
-       { in_line_eoln, 0 }, /* sp */
+       { in_line_eoln, MAN_NSCOPED }, /* sp */
        { in_line_eoln, 0 }, /* nf */
        { in_line_eoln, 0 }, /* fi */
        { in_line_eoln, 0 }, /* r */
        { blk_close, 0 }, /* RE */
-       { blk_imp, MAN_EXPLICIT }, /* RS */
+       { blk_exp, MAN_EXPLICIT }, /* RS */
        { in_line_eoln, 0 }, /* DT */
        { in_line_eoln, 0 }, /* UC */
        { in_line_eoln, 0 }, /* PD */
+       { in_line_eoln, MAN_NSCOPED }, /* Sp */
+       { in_line_eoln, 0 }, /* Vb */
+       { in_line_eoln, 0 }, /* Ve */
+       { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* de */
+       { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* dei */
+       { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* am */
+       { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* ami */
+       { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* ig */
+       { blk_dotted, 0 }, /* . */
 };
 
 const  struct man_macro * const man_macros = __man_macros;
 
 
+/*
+ * Warn when "n" is an explicit non-roff macro.
+ */
+static int
+rew_warn(struct man *m, struct man_node *n, enum merr er)
+{
+
+       if (er == WERRMAX || MAN_BLOCK != n->type)
+               return(1);
+       if (MAN_VALID & n->flags)
+               return(1);
+       if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
+               return(1);
+       if (MAN_NOCLOSE & man_macros[n->tok].flags)
+               return(1);
+       return(man_nwarn(m, n, er));
+}
+
+
+/*
+ * Rewind scope.  If a code "er" != WERRMAX has been provided, it will
+ * be used if an explicit block scope is being closed out.
+ */
 int
-man_unscope(struct man *m, const struct man_node *n)
+man_unscope(struct man *m, const struct man_node *n, enum merr er)
 {
 
        assert(n);
-       m->next = MAN_NEXT_SIBLING;
 
        /* LINTED */
        while (m->last != n) {
+               if ( ! rew_warn(m, m->last, er))
+                       return(0);
                if ( ! man_valid_post(m))
                        return(0);
                if ( ! man_action_post(m))
@@ -90,14 +130,22 @@ man_unscope(struct man *m, const struct man_node *n)
                assert(m->last);
        }
 
+       if ( ! rew_warn(m, m->last, er))
+               return(0);
        if ( ! man_valid_post(m))
                return(0);
-       return(man_action_post(m));
+       if ( ! man_action_post(m))
+               return(0);
+
+       m->next = MAN_ROOT == m->last->type ?
+               MAN_NEXT_CHILD : MAN_NEXT_SIBLING;
+
+       return(1);
 }
 
 
-static int
-rew_block(int ntok, enum man_type type, const struct man_node *n)
+static enum rew
+rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
 {
 
        if (MAN_BLOCK == type && ntok == n->parent->tok &&
@@ -112,23 +160,52 @@ rew_block(int ntok, enum man_type type, const struct man_node *n)
  * section (all less sections), and scoped to subsections (all less
  * sections and subsections).
  */
-static int
-rew_dohalt(int tok, enum man_type type, const struct man_node *n)
+static enum rew
+rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
 {
-       int              c;
+       enum rew         c;
 
+       /* We cannot progress beyond the root ever. */
        if (MAN_ROOT == n->type)
                return(REW_HALT);
+
        assert(n->parent);
+
+       /* Normal nodes shouldn't go to the level of the root. */
        if (MAN_ROOT == n->parent->type)
                return(REW_REWIND);
+
+       /* Already-validated nodes should be closed out. */
        if (MAN_VALID & n->flags)
                return(REW_NOHALT);
 
-       /* Rewind to ourselves, first. */
+       /* First: rewind to ourselves. */
        if (type == n->type && tok == n->tok)
                return(REW_REWIND);
 
+       /*
+        * If we're a roff macro, then we can close out anything that
+        * stands between us and our parent context.
+        */
+       if (MAN_NOCLOSE & man_macros[tok].flags)
+               return(REW_NOHALT);
+
+       /*
+        * Don't clobber roff macros: this is a bit complicated.  If the
+        * current macro is a roff macro, halt immediately and don't
+        * rewind.  If it's not, and the parent is, then close out the
+        * current scope and halt at the parent.
+        */
+       if (MAN_NOCLOSE & man_macros[n->tok].flags)
+               return(REW_HALT);
+       if (MAN_NOCLOSE & man_macros[n->parent->tok].flags)
+               return(REW_REWIND);
+
+       /*
+        * Next follow the implicit scope-smashings as defined by man.7:
+        * section, sub-section, etc.
+        */
+
        switch (tok) {
        case (MAN_SH):
                break;
@@ -168,10 +245,10 @@ rew_dohalt(int tok, enum man_type type, const struct man_node *n)
  * scopes.  When a scope is closed, it must be validated and actioned.
  */
 static int
-rew_scope(enum man_type type, struct man *m, int tok)
+rew_scope(enum man_type type, struct man *m, enum mant tok)
 {
        struct man_node *n;
-       int              c;
+       enum rew         c;
 
        /* LINTED */
        for (n = m->last; n; n = n->parent) {
@@ -187,18 +264,78 @@ rew_scope(enum man_type type, struct man *m, int tok)
                        break;
        }
 
-       /* Rewind until the current point. */
-
+       /*
+        * Rewind until the current point.  Warn if we're a roff
+        * instruction that's mowing over explicit scopes.
+        */
        assert(n);
-       return(man_unscope(m, n));
+       if (MAN_NOCLOSE & man_macros[tok].flags)
+               return(man_unscope(m, n, WROFFSCOPE));
+
+       return(man_unscope(m, n, WERRMAX));
 }
 
 
+/*
+ * Closure for dotted macros (de, dei, am, ami, ign).  This must handle
+ * any of these as the parent node, so it needs special handling.
+ * Beyond this, it's the same as blk_close().
+ */
+/* ARGSUSED */
+int
+blk_dotted(MACRO_PROT_ARGS)
+{
+       enum mant        ntok;
+       struct man_node *nn;
+
+       /* Check for any of the following parents... */
+
+       for (nn = m->last->parent; nn; nn = nn->parent)
+               if (nn->tok == MAN_de || nn->tok == MAN_dei ||
+                               nn->tok == MAN_am ||
+                               nn->tok == MAN_ami ||
+                               nn->tok == MAN_ig) {
+                       ntok = nn->tok;
+                       break;
+               }
+
+       if (NULL == nn) {
+               if ( ! man_pwarn(m, line, ppos, WNOSCOPE))
+                       return(0);
+               return(1);
+       }
+
+       if ( ! rew_scope(MAN_BODY, m, ntok))
+               return(0);
+       if ( ! rew_scope(MAN_BLOCK, m, ntok))
+               return(0);
+
+       /*
+        * XXX: manually adjust our next-line status.  roff macros are,
+        * for the moment, ignored, so we don't want to close out bodies
+        * and so on.
+        */
+
+       switch (m->last->type) {
+       case (MAN_BODY):
+               m->next = MAN_NEXT_CHILD;
+               break;
+       default:
+               break;
+       }
+
+       return(1);
+}
+
+
+/*
+ * Close out a generic explicit macro.
+ */
 /* ARGSUSED */
 int
 blk_close(MACRO_PROT_ARGS)
 {
-       int                      ntok;
+       enum mant                ntok;
        const struct man_node   *nn;
 
        switch (tok) {
@@ -222,11 +359,58 @@ blk_close(MACRO_PROT_ARGS)
                return(0);
        if ( ! rew_scope(MAN_BLOCK, m, ntok))
                return(0);
-       m->next = MAN_NEXT_SIBLING;
+
        return(1);
 }
 
 
+int
+blk_exp(MACRO_PROT_ARGS)
+{
+       int              w, la;
+       char            *p;
+
+       /*
+        * Close out prior scopes.  "Regular" explicit macros cannot be
+        * nested, but we allow roff macros to be placed just about
+        * anywhere.
+        */
+
+       if ( ! (MAN_NOCLOSE & man_macros[tok].flags)) {
+               if ( ! rew_scope(MAN_BODY, m, tok))
+                       return(0);
+               if ( ! rew_scope(MAN_BLOCK, m, tok))
+                       return(0);
+       }
+
+       if ( ! man_block_alloc(m, line, ppos, tok))
+               return(0);
+       if ( ! man_head_alloc(m, line, ppos, tok))
+               return(0);
+
+       for (;;) {
+               la = *pos;
+               w = man_args(m, line, pos, buf, &p);
+
+               if (-1 == w)
+                       return(0);
+               if (0 == w)
+                       break;
+
+               if ( ! man_word_alloc(m, line, la, p))
+                       return(0);
+       }
+
+       assert(m);
+       assert(tok != MAN_MAX);
+
+       if ( ! rew_scope(MAN_HEAD, m, tok))
+               return(0);
+       return(man_body_alloc(m, line, ppos, tok));
+}
+
+
+
 /*
  * Parse an implicit-block macro.  These contain a MAN_HEAD and a
  * MAN_BODY contained within a MAN_BLOCK.  Rules for closing out other
@@ -286,7 +470,6 @@ blk_imp(MACRO_PROT_ARGS)
 
        if ( ! rew_scope(MAN_HEAD, m, tok))
                return(0);
-
        return(man_body_alloc(m, line, ppos, tok));
 }
 
@@ -311,19 +494,33 @@ in_line_eoln(MACRO_PROT_ARGS)
                        return(0);
                if (0 == w)
                        break;
-
                if ( ! man_word_alloc(m, line, la, p))
                        return(0);
        }
 
+       /*
+        * If no arguments are specified and this is MAN_SCOPED (i.e.,
+        * next-line scoped), then set our mode to indicate that we're
+        * waiting for terms to load into our context.
+        */
+
        if (n == m->last && MAN_SCOPED & man_macros[tok].flags) {
+               assert( ! (MAN_NSCOPED & man_macros[tok].flags));
                m->flags |= MAN_ELINE;
                return(1);
        }
 
+       /* Set ignorable context, if applicable. */
+
+       if (MAN_NSCOPED & man_macros[tok].flags) {
+               assert( ! (MAN_SCOPED & man_macros[tok].flags));
+               m->flags |= MAN_ILINE;
+       }
+
        /*
-        * Note that when TH is pruned, we'll be back at the root, so
-        * make sure that we don't clobber as its sibling.
+        * Rewind our element scope.  Note that when TH is pruned, we'll
+        * be back at the root, so make sure that we don't clobber as
+        * its sibling.
         */
 
        for ( ; m->last; m->last = m->last->parent) {
@@ -347,8 +544,9 @@ in_line_eoln(MACRO_PROT_ARGS)
                return(0);
        if (m->last->type != MAN_ROOT && ! man_action_post(m))
                return(0);
-       if (m->last->type != MAN_ROOT)
-               m->next = MAN_NEXT_SIBLING;
+
+       m->next = MAN_ROOT == m->last->type ?
+               MAN_NEXT_CHILD : MAN_NEXT_SIBLING;
 
        return(1);
 }
@@ -357,19 +555,6 @@ in_line_eoln(MACRO_PROT_ARGS)
 int
 man_macroend(struct man *m)
 {
-       struct man_node *n;
-
-       n = MAN_VALID & m->last->flags ?
-               m->last->parent : m->last;
-
-       for ( ; n; n = n->parent) {
-               if (MAN_BLOCK != n->type)
-                       continue;
-               if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
-                       continue;
-               if ( ! man_nwarn(m, n, WEXITSCOPE))
-                       return(0);
-       }
 
-       return(man_unscope(m, m->first));
+       return(man_unscope(m, m->first, WEXITSCOPE));
 }
index 4da50c5..b1e6d9f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_term.c,v 1.55 2010/01/01 17:14:28 kristaps Exp $ */
+/*     $Id: man_term.c,v 1.59 2010/03/24 20:10:53 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -61,6 +61,8 @@ struct        mtermp {
 struct termact {
        int             (*pre)(DECL_ARGS);
        void            (*post)(DECL_ARGS);
+       int               flags;
+#define        MAN_NOTEXT       (1 << 0) /* Never has text children. */
 };
 
 static int               a2width(const struct man_node *);
@@ -101,38 +103,47 @@ static    void              post_SS(DECL_ARGS);
 static void              post_TP(DECL_ARGS);
 
 static const struct termact termacts[MAN_MAX] = {
-       { pre_br, NULL }, /* br */
-       { NULL, NULL }, /* TH */
-       { pre_SH, post_SH }, /* SH */
-       { pre_SS, post_SS }, /* SS */
-       { pre_TP, post_TP }, /* TP */
-       { pre_PP, NULL }, /* LP */
-       { pre_PP, NULL }, /* PP */
-       { pre_PP, NULL }, /* P */
-       { pre_IP, post_IP }, /* IP */
-       { pre_HP, post_HP }, /* HP */
-       { NULL, NULL }, /* SM */
-       { pre_B, NULL }, /* SB */
-       { pre_BI, NULL }, /* BI */
-       { pre_BI, NULL }, /* IB */
-       { pre_RB, NULL }, /* BR */
-       { pre_RB, NULL }, /* RB */
-       { NULL, NULL }, /* R */
-       { pre_B, NULL }, /* B */
-       { pre_I, NULL }, /* I */
-       { pre_RI, NULL }, /* IR */
-       { pre_RI, NULL }, /* RI */
-       { NULL, NULL }, /* na */
-       { pre_I, NULL }, /* i */
-       { pre_sp, NULL }, /* sp */
-       { pre_nf, NULL }, /* nf */
-       { pre_fi, NULL }, /* fi */
-       { NULL, NULL }, /* r */
-       { NULL, NULL }, /* RE */
-       { pre_RS, post_RS }, /* RS */
-       { pre_ign, NULL }, /* DT */
-       { pre_ign, NULL }, /* UC */
-       { pre_ign, NULL }, /* PD */
+       { pre_br, NULL, MAN_NOTEXT }, /* br */
+       { NULL, NULL, 0 }, /* TH */
+       { pre_SH, post_SH, 0 }, /* SH */
+       { pre_SS, post_SS, 0 }, /* SS */
+       { pre_TP, post_TP, 0 }, /* TP */
+       { pre_PP, NULL, 0 }, /* LP */
+       { pre_PP, NULL, 0 }, /* PP */
+       { pre_PP, NULL, 0 }, /* P */
+       { pre_IP, post_IP, 0 }, /* IP */
+       { pre_HP, post_HP, 0 }, /* HP */
+       { NULL, NULL, 0 }, /* SM */
+       { pre_B, NULL, 0 }, /* SB */
+       { pre_BI, NULL, 0 }, /* BI */
+       { pre_BI, NULL, 0 }, /* IB */
+       { pre_RB, NULL, 0 }, /* BR */
+       { pre_RB, NULL, 0 }, /* RB */
+       { NULL, NULL, 0 }, /* R */
+       { pre_B, NULL, 0 }, /* B */
+       { pre_I, NULL, 0 }, /* I */
+       { pre_RI, NULL, 0 }, /* IR */
+       { pre_RI, NULL, 0 }, /* RI */
+       { NULL, NULL, MAN_NOTEXT }, /* na */
+       { pre_I, NULL, 0 }, /* i */
+       { pre_sp, NULL, MAN_NOTEXT }, /* sp */
+       { pre_nf, NULL, 0 }, /* nf */
+       { pre_fi, NULL, 0 }, /* fi */
+       { NULL, NULL, 0 }, /* r */
+       { NULL, NULL, 0 }, /* RE */
+       { pre_RS, post_RS, 0 }, /* RS */
+       { pre_ign, NULL, 0 }, /* DT */
+       { pre_ign, NULL, 0 }, /* UC */
+       { pre_ign, NULL, 0 }, /* PD */
+       { pre_sp, NULL, MAN_NOTEXT }, /* Sp */
+       { pre_nf, NULL, 0 }, /* Vb */
+       { pre_fi, NULL, 0 }, /* Ve */
+       { pre_ign, NULL, MAN_NOTEXT }, /* de */
+       { pre_ign, NULL, MAN_NOTEXT }, /* dei */
+       { pre_ign, NULL, MAN_NOTEXT }, /* am */
+       { pre_ign, NULL, MAN_NOTEXT }, /* ami */
+       { pre_ign, NULL, MAN_NOTEXT }, /* ig */
+       { NULL, NULL, 0 }, /* . */
 };
 
 
@@ -147,6 +158,9 @@ terminal_man(void *arg, const struct man *man)
 
        p = (struct termp *)arg;
 
+       p->overstep = 0;
+       p->maxrmargin = 65;
+
        if (NULL == p->symtab)
                switch (p->enc) {
                case (TERMENC_ASCII):
@@ -242,6 +256,7 @@ static int
 pre_fi(DECL_ARGS)
 {
 
+       p->rmargin = p->maxrmargin = 65;
        mt->fl &= ~MANT_LITERAL;
        return(1);
 }
@@ -252,9 +267,11 @@ static int
 pre_nf(DECL_ARGS)
 {
 
+       p->rmargin = p->maxrmargin = 78;
        term_newln(p);
        mt->fl |= MANT_LITERAL;
-       return(1);
+
+       return(MAN_Vb != n->tok);
 }
 
 
@@ -570,10 +587,13 @@ pre_TP(DECL_ARGS)
 
        /* Calculate offset. */
 
-       if (NULL != (nn = n->parent->head->child))
-               if (NULL != nn->next)
+       if (NULL != (nn = n->parent->head->child)) {
+               while (nn && MAN_TEXT != nn->type)
+                       nn = nn->next;
+               if (nn && nn->next)
                        if ((ival = a2width(nn)) >= 0)
                                len = (size_t)ival;
+       }
 
        switch (n->type) {
        case (MAN_HEAD):
@@ -767,6 +787,8 @@ post_RS(DECL_ARGS)
        case (MAN_BLOCK):
                mt->offset = mt->lmargin = INDENT;
                break;
+       case (MAN_HEAD):
+               break;
        default:
                term_newln(p);
                p->offset = INDENT;
@@ -799,7 +821,8 @@ print_man_node(DECL_ARGS)
                }
                break;
        default:
-               term_fontrepl(p, TERMFONT_NONE);
+               if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
+                       term_fontrepl(p, TERMFONT_NONE);
                if (termacts[n->tok].pre)
                        c = (*termacts[n->tok].pre)(p, mt, n, m);
                break;
@@ -811,7 +834,8 @@ print_man_node(DECL_ARGS)
        if (MAN_TEXT != n->type) {
                if (termacts[n->tok].post)
                        (*termacts[n->tok].post)(p, mt, n, m);
-               term_fontrepl(p, TERMFONT_NONE);
+               if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
+                       term_fontrepl(p, TERMFONT_NONE);
        }
 }
 
@@ -862,18 +886,24 @@ static void
 print_man_head(struct termp *p, const struct man_meta *m)
 {
        char            buf[BUFSIZ], title[BUFSIZ];
+       size_t          buflen, titlen;
 
        p->rmargin = p->maxrmargin;
+
        p->offset = 0;
        buf[0] = title[0] = '\0';
 
        if (m->vol)
                strlcpy(buf, m->vol, BUFSIZ);
+       buflen = strlen(buf);
 
        snprintf(title, BUFSIZ, "%s(%d)", m->title, m->msec);
+       titlen = strlen(title);
 
        p->offset = 0;
-       p->rmargin = (p->maxrmargin - strlen(buf) + 1) / 2;
+       p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
+           (p->maxrmargin - strlen(buf) + 1) / 2 :
+           p->maxrmargin - buflen;
        p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
 
        term_word(p, title);
@@ -881,18 +911,20 @@ print_man_head(struct termp *p, const struct man_meta *m)
 
        p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
        p->offset = p->rmargin;
-       p->rmargin = p->maxrmargin - strlen(title);
+       p->rmargin = p->offset + buflen + titlen < p->maxrmargin ?
+           p->maxrmargin - titlen : p->maxrmargin;
 
        term_word(p, buf);
        term_flushln(p);
 
-       p->offset = p->rmargin;
-       p->rmargin = p->maxrmargin;
        p->flags &= ~TERMP_NOBREAK;
-       p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
-
-       term_word(p, title);
-       term_flushln(p);
+       if (p->rmargin + titlen <= p->maxrmargin) {
+               p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+               p->offset = p->rmargin;
+               p->rmargin = p->maxrmargin;
+               term_word(p, title);
+               term_flushln(p);
+       }
 
        p->rmargin = p->maxrmargin;
        p->offset = 0;
index 00112d3..416a73e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_validate.c,v 1.28 2010/01/01 17:14:28 kristaps Exp $ */
+/*     $Id: man_validate.c,v 1.32 2010/03/27 10:04:56 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -42,21 +42,24 @@ static      int       check_ge2(CHKARGS);
 static int       check_le5(CHKARGS);
 static int       check_par(CHKARGS);
 static int       check_part(CHKARGS);
+static int       check_roff(CHKARGS);
 static int       check_root(CHKARGS);
 static int       check_sec(CHKARGS);
 static int       check_text(CHKARGS);
+static int       check_title(CHKARGS);
 
 static v_check   posts_eq0[] = { check_eq0, NULL };
-static v_check   posts_ge2_le5[] = { check_ge2, check_le5, NULL };
+static v_check   posts_th[] = { check_ge2, check_le5, check_title, NULL };
 static v_check   posts_par[] = { check_par, NULL };
 static v_check   posts_part[] = { check_part, NULL };
 static v_check   posts_sec[] = { check_sec, NULL };
-static v_check   posts_sp[] = { check_le1, NULL };
+static v_check   posts_le1[] = { check_le1, NULL };
 static v_check   pres_bline[] = { check_bline, NULL };
+static v_check   pres_roff[] = { check_bline, check_roff, NULL };
 
 static const struct man_valid man_valids[MAN_MAX] = {
-       { pres_bline, posts_eq0 }, /* br */
-       { pres_bline, posts_ge2_le5 }, /* TH */ /* FIXME: make sure capitalised. */
+       { NULL, posts_eq0 }, /* br */
+       { pres_bline, posts_th }, /* TH */
        { pres_bline, posts_sec }, /* SH */
        { pres_bline, posts_sec }, /* SS */
        { pres_bline, posts_par }, /* TP */
@@ -76,9 +79,9 @@ static        const struct man_valid man_valids[MAN_MAX] = {
        { NULL, NULL }, /* I */
        { NULL, NULL }, /* IR */
        { NULL, NULL }, /* RI */
-       { pres_bline, posts_eq0 }, /* na */
+       { NULL, posts_eq0 }, /* na */
        { NULL, NULL }, /* i */
-       { pres_bline, posts_sp }, /* sp */
+       { NULL, posts_le1 }, /* sp */
        { pres_bline, posts_eq0 }, /* nf */
        { pres_bline, posts_eq0 }, /* fi */
        { NULL, NULL }, /* r */
@@ -87,6 +90,15 @@ static       const struct man_valid man_valids[MAN_MAX] = {
        { NULL, NULL }, /* DT */
        { NULL, NULL }, /* UC */
        { NULL, NULL }, /* PD */
+       { NULL, posts_eq0 }, /* Sp */
+       { pres_bline, posts_le1 }, /* Vb */
+       { pres_bline, posts_eq0 }, /* Ve */
+       { pres_roff, NULL }, /* de */
+       { pres_roff, NULL }, /* dei */
+       { pres_roff, NULL }, /* am */
+       { pres_roff, NULL }, /* ami */
+       { pres_roff, NULL }, /* ig */
+       { NULL, NULL }, /* . */
 };
 
 
@@ -158,6 +170,24 @@ check_root(CHKARGS)
 }
 
 
+static int
+check_title(CHKARGS)
+{
+       const char      *p;
+
+       assert(n->child);
+       if ('\0' == *n->child->string)
+               return(man_nerr(m, n, WNOTITLE));
+
+       for (p = n->child->string; '\0' != *p; p++)
+               if (isalpha((u_char)*p) && ! isupper((u_char)*p))
+                       if ( ! man_nwarn(m, n, WTITLECASE))
+                               return(0);
+
+       return(1);
+}
+
+
 static int
 check_text(CHKARGS)
 {
@@ -277,5 +307,24 @@ check_bline(CHKARGS)
        assert( ! (MAN_ELINE & m->flags));
        if (MAN_BLINE & m->flags)
                return(man_nerr(m, n, WLNSCOPE));
+
+       return(1);
+}
+
+
+static int
+check_roff(CHKARGS)
+{
+
+       if (MAN_BLOCK != n->type)
+               return(1);
+
+       for (n = n->parent; n; n = n->parent)
+               if (MAN_de == n->tok || MAN_dei == n->tok ||
+                               MAN_am == n->tok ||
+                               MAN_ami == n->tok ||
+                               MAN_ig == n->tok)
+                       return(man_nerr(m, n, WROFFNEST));
+
        return(1);
 }
index 3a78d8e..eff7132 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mandoc.1,v 1.50 2010/01/29 14:39:38 kristaps Exp $
+.\"    $Id: mandoc.1,v 1.54 2010/03/27 10:10:10 kristaps Exp $
 .\"
 .\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd February 20, 2010
+.Dd March 27, 2010
 .Dt MANDOC 1
 .Os
 .
@@ -176,6 +176,10 @@ Produce an indented parse tree.
 .
 .It Fl T Ns Ar lint
 Parse only: produce no output.
+Implies
+.Fl W Ns Ar all
+and
+.Fl f Ns Ar strict .
 .El
 .
 .Pp
@@ -225,6 +229,8 @@ over a large set of manuals passed on the command line.
 .Ss Output Options
 For the time being, only
 .Fl T Ns Ar html
+and
+.Fl T Ns Ar xhtml
 accepts output options:
 .Bl -tag -width Ds
 .It Fl O Ns Ar style=style.css
@@ -502,8 +508,9 @@ and
 .Fl T Ns Ar xhtml
 CSS2 styling used for
 .Fl m Ns Ar doc
-input lists does not render properly in brain-dead browsers, such as
-Internet Explorer 6 and earlier.
+input lists does not render properly in older browsers, such as Internet
+Explorer 6 and earlier.
+.
 .Pp
 In
 .Fl T Ns Ar html
@@ -514,6 +521,7 @@ the maximum size of an element attribute is determined by
 which is usually 1024 bytes.  Be aware of this when setting long link
 formats, e.g.,
 .Fl O Ns Ar style=really/long/link .
+.
 .Pp
 The
 .Fl T Ns Ar html
@@ -525,3 +533,29 @@ font size escape documented in
 .Xr mdoc 7
 and
 .Xr man 7 .
+.
+.Pp
+Nesting elements within next-line element scopes of
+.Fl m Ns Ar an ,
+such as
+.Sq br
+within an empty
+.Sq B ,
+will confuse
+.Fl T Ns Ar html
+and
+.Fl T Ns Ar xhtml
+and cause them to forget the formatting of the prior next-line scope.
+.
+.Pp
+The
+.Sq i
+macro in
+.Fl m Ns Ar an
+should italicise all subsequent text if a line argument is not provided.
+This behaviour is not implemented.
+.
+The
+.Sq \(aq
+control character is an alias for the standard macro control character
+and does not emit a line-break as stipulated in GNU troff.
index e5374ff..fb01885 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mdoc.7,v 1.84 2010/02/17 19:22:50 kristaps Exp $
+.\"    $Id: mdoc.7,v 1.86 2010/03/26 07:07:58 kristaps Exp $
 .\"
 .\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd February 20, 2010
+.Dd March 27, 2010
 .Dt MDOC 7
 .Os
 .
@@ -1553,6 +1553,7 @@ subsequent that.  It, too, is optional.  It must be one of
 .Ar hppa64 ,
 .Ar i386 ,
 .Ar landisk ,
+.Ar loongson ,
 .Ar luna88k ,
 .Ar mac68k ,
 .Ar macppc ,
index 2023d5b..4835fcd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_term.c,v 1.110 2010/01/30 08:42:21 kristaps Exp $ */
+/*     $Id: mdoc_term.c,v 1.111 2010/03/23 12:42:22 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -266,6 +266,9 @@ terminal_mdoc(void *arg, const struct mdoc *mdoc)
 
        p = (struct termp *)arg;
 
+       p->overstep = 0;
+       p->maxrmargin = 78;
+
        if (NULL == p->symtab)
                switch (p->enc) {
                case (TERMENC_ASCII):
index 7a70916..4779745 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: term.c,v 1.128 2010/01/01 17:14:30 kristaps Exp $ */
+/*     $Id: term.c,v 1.129 2010/03/23 12:42:22 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -79,7 +79,6 @@ term_alloc(enum termenc enc)
                perror(NULL);
                exit(EXIT_FAILURE);
        }
-       p->maxrmargin = 78;
        p->enc = enc;
        return(p);
 }
@@ -132,7 +131,6 @@ term_flushln(struct termp *p)
        size_t           bp;    /* visual right border position */
        int              j;     /* temporary loop index */
        size_t           maxvis, mmax;
-       static int       overstep = 0;
 
        /*
         * First, establish the maximum columns of "visible" content.
@@ -143,12 +141,12 @@ term_flushln(struct termp *p)
 
        assert(p->offset < p->rmargin);
 
-       maxvis = (int)(p->rmargin - p->offset) - overstep < 0 ?
+       maxvis = (int)(p->rmargin - p->offset) - p->overstep < 0 ?
                /* LINTED */
-               0 : p->rmargin - p->offset - overstep;
-       mmax = (int)(p->maxrmargin - p->offset) - overstep < 0 ?
+               0 : p->rmargin - p->offset - p->overstep;
+       mmax = (int)(p->maxrmargin - p->offset) - p->overstep < 0 ?
                /* LINTED */
-               0 : p->maxrmargin - p->offset - overstep;
+               0 : p->maxrmargin - p->offset - p->overstep;
 
        bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;
 
@@ -211,10 +209,10 @@ term_flushln(struct termp *p)
                                        putchar(' ');
                                vis = 0;
                        }
-                       /* Remove the overstep width. */
+                       /* Remove the p->overstep width. */
                        bp += (int)/* LINTED */
-                               overstep;
-                       overstep = 0;
+                               p->overstep;
+                       p->overstep = 0;
                } else {
                        for (j = 0; j < (int)vbl; j++)
                                putchar(' ');
@@ -238,7 +236,7 @@ term_flushln(struct termp *p)
        }
 
        p->col = 0;
-       overstep = 0;
+       p->overstep = 0;
 
        if ( ! (TERMP_NOBREAK & p->flags)) {
                putchar('\n');
@@ -247,7 +245,7 @@ term_flushln(struct termp *p)
 
        if (TERMP_HANG & p->flags) {
                /* We need one blank after the tag. */
-               overstep = /* LINTED */
+               p->overstep = /* LINTED */
                        vis - maxvis + 1;
 
                /*
@@ -260,12 +258,12 @@ term_flushln(struct termp *p)
                 * move it one step LEFT and flag the rest of the line
                 * to be longer.
                 */
-               if (overstep >= -1) {
-                       assert((int)maxvis + overstep >= 0);
+               if (p->overstep >= -1) {
+                       assert((int)maxvis + p->overstep >= 0);
                        /* LINTED */
-                       maxvis += overstep;
+                       maxvis += p->overstep;
                } else
-                       overstep = 0;
+                       p->overstep = 0;
 
        } else if (TERMP_DANGLE & p->flags)
                return;
index 134c83d..4a1ed90 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: term.h,v 1.51 2009/11/12 05:50:13 kristaps Exp $ */
+/*     $Id: term.h,v 1.52 2010/03/23 12:42:22 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -35,6 +35,7 @@ struct        termp {
        size_t            maxcols;      /* Max size of buf. */
        size_t            offset;       /* Margin offest. */
        size_t            col;          /* Bytes in buf. */
+       int               overstep;     /* See termp_flushln(). */
        int               flags;
 #define        TERMP_NOSPACE    (1 << 2)       /* No space before words. */
 #define        TERMP_NOLPAD     (1 << 3)       /* See term_flushln(). */