summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2010-03-26 01:22:05 +0000
committerschwarze <schwarze@openbsd.org>2010-03-26 01:22:05 +0000
commitac531cf149bb0c92daec85dbe45c2ebf82fae36f (patch)
treece0a8314675b2eb8304dccef3896bb6be3b8204c
parentReformat default value of PreferredAuthentications entry (current formatting (diff)
downloadwireguard-openbsd-ac531cf149bb0c92daec85dbe45c2ebf82fae36f.tar.xz
wireguard-openbsd-ac531cf149bb0c92daec85dbe45c2ebf82fae36f.zip
merge 1.9.17, keeping local patches
* much improved pod2man support and low-level roff robustness * have -Tlint imply -Wall and -fstrict * use fewer macros and more enum in libman * and various bug fixes
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/chars.c4
-rw-r--r--usr.bin/mandoc/chars.in31
-rw-r--r--usr.bin/mandoc/libman.h20
-rw-r--r--usr.bin/mandoc/main.c70
-rw-r--r--usr.bin/mandoc/man.7189
-rw-r--r--usr.bin/mandoc/man.c107
-rw-r--r--usr.bin/mandoc/man.h84
-rw-r--r--usr.bin/mandoc/man_action.c33
-rw-r--r--usr.bin/mandoc/man_hash.c57
-rw-r--r--usr.bin/mandoc/man_html.c26
-rw-r--r--usr.bin/mandoc/man_macro.c157
-rw-r--r--usr.bin/mandoc/man_term.c26
-rw-r--r--usr.bin/mandoc/man_validate.c30
-rw-r--r--usr.bin/mandoc/mandoc.121
-rw-r--r--usr.bin/mandoc/mdoc_term.c5
-rw-r--r--usr.bin/mandoc/term.c30
-rw-r--r--usr.bin/mandoc/term.h3
18 files changed, 591 insertions, 306 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index fa3c9fe1736..cbbf8c7e74f 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.28 2010/03/25 23:23:01 schwarze Exp $
+# $OpenBSD: Makefile,v 1.29 2010/03/26 01:22:05 schwarze Exp $
.include <bsd.own.mk>
-VERSION=1.9.16
+VERSION=1.9.17
CFLAGS+=-DVERSION=\"${VERSION}\"
CFLAGS+=-W -Wall -Wstrict-prototypes
.if ${USE_GCC3:L} != "no"
diff --git a/usr.bin/mandoc/chars.c b/usr.bin/mandoc/chars.c
index edeec1abb30..0e8348bc13a 100644
--- a/usr.bin/mandoc/chars.c
+++ b/usr.bin/mandoc/chars.c
@@ -1,4 +1,4 @@
-/* $Id: chars.c,v 1.5 2010/02/18 02:11:25 schwarze Exp $ */
+/* $Id: chars.c,v 1.6 2010/03/26 01:22:05 schwarze 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 },
diff --git a/usr.bin/mandoc/chars.in b/usr.bin/mandoc/chars.in
index 75b6601ee09..429d12ee9d9 100644
--- a/usr.bin/mandoc/chars.in
+++ b/usr.bin/mandoc/chars.in
@@ -1,4 +1,4 @@
-/* $Id: chars.in,v 1.5 2010/03/02 00:38:59 schwarze Exp $ */
+/* $Id: chars.in,v 1.6 2010/03/26 01:22:05 schwarze 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)
diff --git a/usr.bin/mandoc/libman.h b/usr.bin/mandoc/libman.h
index cc225c088ec..1bb92ebf14d 100644
--- a/usr.bin/mandoc/libman.h
+++ b/usr.bin/mandoc/libman.h
@@ -1,4 +1,4 @@
-/* $Id: libman.h,v 1.12 2010/03/25 23:23:01 schwarze Exp $ */
+/* $Id: libman.h,v 1.13 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -60,10 +60,11 @@ enum merr {
WNOSCOPE,
WOLITERAL,
WNLITERAL,
+ WROFFNEST,
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 {
@@ -73,6 +74,7 @@ struct man_macro {
#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;
@@ -89,15 +91,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 *);
-void man_node_unlink(struct man *, 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)
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 5688ec04728..0f2ab0b03b0 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.21 2010/02/18 02:11:26 schwarze Exp $ */
+/* $Id: main.c,v 1.22 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -60,11 +60,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;
@@ -78,8 +78,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 *);
@@ -132,7 +136,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'):
@@ -160,7 +164,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;
@@ -168,7 +172,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;
@@ -232,11 +236,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));
@@ -256,13 +260,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));
@@ -534,19 +538,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);
@@ -575,26 +582,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);
diff --git a/usr.bin/mandoc/man.7 b/usr.bin/mandoc/man.7
index b2d04bb2567..860013dc77a 100644
--- a/usr.bin/mandoc/man.7
+++ b/usr.bin/mandoc/man.7
@@ -1,4 +1,4 @@
-.\" $Id: man.7,v 1.17 2010/03/25 23:23:01 schwarze Exp $
+.\" $Id: man.7,v 1.18 2010/03/26 01:22:05 schwarze 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 $Mdocdate: March 25 2010 $
+.Dd $Mdocdate: March 26 2010 $
.Dt MAN 7
.Os
.
@@ -438,6 +438,7 @@ 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
@@ -448,54 +449,51 @@ The syntax is as follows:
.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 next-line stipulations for line macros apply here as
-well).
+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
@@ -523,33 +521,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
@@ -904,14 +903,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
@@ -979,31 +978,43 @@ 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.
-.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.
+macro does not accept negative values in mandoc. In GNU troff, this
+would result in strange behaviour.
.El
.
.
diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c
index 5d94334ea9b..ec14a091747 100644
--- a/usr.bin/mandoc/man.c
+++ b/usr.bin/mandoc/man.c
@@ -1,4 +1,4 @@
-/* $Id: man.c,v 1.21 2010/03/25 23:23:01 schwarze Exp $ */
+/* $Id: man.c,v 1.22 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -45,7 +45,8 @@ 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 */
};
const char *const __man_macronames[MAN_MAX] = {
@@ -57,15 +58,20 @@ const char *const __man_macronames[MAN_MAX] = {
"RI", "na", "i", "sp",
"nf", "fi", "r", "RE",
"RS", "DT", "UC", "PD",
- "Sp", "Vb", "Ve",
+ "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 *);
@@ -156,7 +162,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)
@@ -175,6 +181,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;
}
@@ -202,6 +209,7 @@ man_node_append(struct man *man, struct man_node *p)
/* NOTREACHED */
}
+ assert(p->parent);
p->parent->nchild++;
if ( ! man_valid_pre(man, p))
@@ -238,7 +246,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;
@@ -252,7 +260,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;
@@ -265,7 +273,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;
@@ -278,7 +286,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;
@@ -291,7 +299,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;
@@ -310,7 +318,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);
@@ -332,30 +340,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);
}
@@ -465,7 +472,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;
@@ -515,7 +523,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);
@@ -538,7 +546,7 @@ man_pmacro(struct man *m, int ln, char *buf)
* macros---they don't print text---so we let those slip by.
*/
- if ( ! (MAN_NSCOPED & man_macros[c].flags) &&
+ if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
m->flags & MAN_ELINE) {
assert(MAN_TEXT != m->last->type);
@@ -563,22 +571,24 @@ man_pmacro(struct man *m, int ln, char *buf)
if ( ! man_nwarn(m, n, WLNSCOPE))
return(0);
- man_node_unlink(m, n);
- 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:
/*
* 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)) {
@@ -667,26 +677,43 @@ man_err(struct man *m, int line, int pos, int iserr, enum merr type)
}
-void
+/*
+ * 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)
{
- if (n->prev) {
+ /* Adjust siblings. */
+
+ if (n->prev)
n->prev->next = n->next;
- if (m->last == n) {
- assert(NULL == 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 {
- n->parent->child = n->next;
- if (m->last == n) {
- assert(NULL == n->next);
+ } else {
m->last = n->parent;
m->next = MAN_NEXT_CHILD;
}
}
- if (n->next)
- n->next->prev = n->prev;
+ if (m && m->first == n)
+ m->first = NULL;
}
diff --git a/usr.bin/mandoc/man.h b/usr.bin/mandoc/man.h
index b99ffda6026..5fb1befdbcb 100644
--- a/usr.bin/mandoc/man.h
+++ b/usr.bin/mandoc/man.h
@@ -1,4 +1,4 @@
-/* $Id: man.h,v 1.13 2010/03/02 01:00:39 schwarze Exp $ */
+/* $Id: man.h,v 1.14 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -19,42 +19,50 @@
#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_Sp 32
-#define MAN_Vb 33
-#define MAN_Ve 34
-#define MAN_MAX 35
+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,
@@ -81,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)
diff --git a/usr.bin/mandoc/man_action.c b/usr.bin/mandoc/man_action.c
index ee9c20014a3..b9850dcbbf7 100644
--- a/usr.bin/mandoc/man_action.c
+++ b/usr.bin/mandoc/man_action.c
@@ -1,4 +1,4 @@
-/* $Id: man_action.c,v 1.13 2010/03/25 23:23:01 schwarze Exp $ */
+/* $Id: man_action.c,v 1.14 2010/03/26 01:22:05 schwarze 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 *);
@@ -67,6 +67,12 @@ const struct actions man_actions[MAN_MAX] = {
{ NULL }, /* Sp */
{ post_nf }, /* Vb */
{ post_fi }, /* Ve */
+ { post_de }, /* de */
+ { post_de }, /* dei */
+ { post_de }, /* am */
+ { post_de }, /* ami */
+ { post_de }, /* ig */
+ { NULL }, /* . */
};
@@ -106,6 +112,21 @@ 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)
{
@@ -177,8 +198,10 @@ post_TH(struct man *m)
if (n && (n = n->next))
m->meta.vol = mandoc_strdup(n->string);
- n = m->last;
- man_node_unlink(m, n);
- man_node_freelist(n);
+ /*
+ * Remove the `TH' node after we've processed it for our
+ * meta-data.
+ */
+ man_node_delete(m, m->last);
return(1);
}
diff --git a/usr.bin/mandoc/man_hash.c b/usr.bin/mandoc/man_hash.c
index 506f997b909..4d0a6a05d9a 100644
--- a/usr.bin/mandoc/man_hash.c
+++ b/usr.bin/mandoc/man_hash.c
@@ -1,4 +1,4 @@
-/* $Id: man_hash.c,v 1.7 2009/10/19 10:20:24 schwarze Exp $ */
+/* $Id: man_hash.c,v 1.8 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -17,13 +17,33 @@
#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,44 @@ man_hash_init(void)
memset(table, UCHAR_MAX, sizeof(table));
+ assert(/* CONSTCOND */ 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);
}
diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c
index 1d984a8833f..339bbf967e4 100644
--- a/usr.bin/mandoc/man_html.c
+++ b/usr.bin/mandoc/man_html.c
@@ -1,4 +1,4 @@
-/* $Id: man_html.c,v 1.7 2010/03/25 23:23:01 schwarze Exp $ */
+/* $Id: man_html.c,v 1.8 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -100,8 +100,14 @@ static const struct htmlman mans[MAN_MAX] = {
{ man_ign_pre, NULL }, /* UC */
{ man_ign_pre, NULL }, /* PD */
{ man_br_pre, NULL }, /* Sp */
- { NULL, NULL }, /* Vb */
- { NULL, NULL }, /* Vi */
+ { 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 }, /* . */
};
@@ -340,10 +346,18 @@ man_br_pre(MAN_ARGS)
SCALE_VS_INIT(&su, 1);
- if ((MAN_sp == n->tok || 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);
diff --git a/usr.bin/mandoc/man_macro.c b/usr.bin/mandoc/man_macro.c
index c282ea3db7a..8e62c005f22 100644
--- a/usr.bin/mandoc/man_macro.c
+++ b/usr.bin/mandoc/man_macro.c
@@ -1,4 +1,4 @@
-/* $Id: man_macro.c,v 1.11 2010/03/25 23:23:01 schwarze Exp $ */
+/* $Id: man_macro.c,v 1.12 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -21,18 +21,23 @@
#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 *);
const struct man_macro __man_macros[MAN_MAX] = {
@@ -64,13 +69,19 @@ const struct man_macro __man_macros[MAN_MAX] = {
{ 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, 0 }, /* Sp */
+ { 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;
@@ -81,7 +92,6 @@ man_unscope(struct man *m, const struct man_node *n)
{
assert(n);
- m->next = MAN_NEXT_SIBLING;
/* LINTED */
while (m->last != n) {
@@ -95,12 +105,18 @@ man_unscope(struct man *m, const struct man_node *n)
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 &&
@@ -115,10 +131,10 @@ 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;
if (MAN_ROOT == n->type)
return(REW_HALT);
@@ -171,10 +187,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) {
@@ -197,11 +213,50 @@ rew_scope(enum man_type type, struct man *m, int tok)
}
+/*
+ * 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;
+
+ 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);
+
+ 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) {
@@ -225,11 +280,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
@@ -289,7 +391,6 @@ blk_imp(MACRO_PROT_ARGS)
if ( ! rew_scope(MAN_HEAD, m, tok))
return(0);
-
return(man_body_alloc(m, line, ppos, tok));
}
@@ -314,11 +415,6 @@ in_line_eoln(MACRO_PROT_ARGS)
return(0);
if (0 == w)
break;
-
- /* XXX ignore Vb arguments for now */
- if (MAN_Vb == tok)
- continue;
-
if ( ! man_word_alloc(m, line, la, p))
return(0);
}
@@ -369,8 +465,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);
}
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c
index dcb24a50516..44dc484f2bb 100644
--- a/usr.bin/mandoc/man_term.c
+++ b/usr.bin/mandoc/man_term.c
@@ -1,4 +1,4 @@
-/* $Id: man_term.c,v 1.26 2010/03/25 23:23:01 schwarze Exp $ */
+/* $Id: man_term.c,v 1.27 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -135,9 +135,15 @@ static const struct termact termacts[MAN_MAX] = {
{ 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_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 }, /* . */
};
@@ -152,10 +158,12 @@ 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):
- p->maxrmargin = 65;
p->symtab = chars_init(CHARS_ASCII);
break;
default:
@@ -259,10 +267,11 @@ static int
pre_nf(DECL_ARGS)
{
- p->rmargin = p->maxrmargin = 160;
+ p->rmargin = p->maxrmargin = 78;
term_newln(p);
mt->fl |= MANT_LITERAL;
- return(1);
+
+ return(MAN_Vb != n->tok);
}
@@ -778,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;
@@ -878,6 +889,7 @@ print_man_head(struct termp *p, const struct man_meta *m)
size_t buflen, titlen;
p->rmargin = p->maxrmargin;
+
p->offset = 0;
buf[0] = title[0] = '\0';
diff --git a/usr.bin/mandoc/man_validate.c b/usr.bin/mandoc/man_validate.c
index 68d87fa3ef0..4630457a58a 100644
--- a/usr.bin/mandoc/man_validate.c
+++ b/usr.bin/mandoc/man_validate.c
@@ -1,4 +1,4 @@
-/* $Id: man_validate.c,v 1.13 2010/03/02 01:00:39 schwarze Exp $ */
+/* $Id: man_validate.c,v 1.14 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -42,6 +42,7 @@ 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);
@@ -53,10 +54,11 @@ static v_check posts_part[] = { check_part, NULL };
static v_check posts_sec[] = { check_sec, 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] = {
{ NULL, posts_eq0 }, /* br */
- { pres_bline, posts_ge2_le5 }, /* TH */
+ { pres_bline, posts_ge2_le5 }, /* TH */ /* FIXME: make sure capitalised. */
{ pres_bline, posts_sec }, /* SH */
{ pres_bline, posts_sec }, /* SS */
{ pres_bline, posts_par }, /* TP */
@@ -90,6 +92,12 @@ static const struct man_valid man_valids[MAN_MAX] = {
{ NULL, posts_le1 }, /* 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 }, /* . */
};
@@ -280,6 +288,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);
+}
diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1
index d34f39e56d3..4285e14d7c8 100644
--- a/usr.bin/mandoc/mandoc.1
+++ b/usr.bin/mandoc/mandoc.1
@@ -1,4 +1,4 @@
-.\" $Id: mandoc.1,v 1.22 2010/03/25 23:23:01 schwarze Exp $
+.\" $Id: mandoc.1,v 1.23 2010/03/26 01:22:05 schwarze 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 $Mdocdate: March 25 2010 $
+.Dd $Mdocdate: March 26 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
@@ -527,7 +533,7 @@ and
.Xr man 7 .
.Pp
Nesting elements within next-line element scopes of
-.Fl m Ar Ns an ,
+.Fl m Ns Ar an ,
such as
.Sq br
within an empty
@@ -536,4 +542,11 @@ will confuse
.Fl T Ns Ar html
and
.Fl T Ns Ar xhtml
-and cause it to forget the formatting.
+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.
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index dba0d2db54f..438853ecae4 100644
--- a/usr.bin/mandoc/mdoc_term.c
+++ b/usr.bin/mandoc/mdoc_term.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_term.c,v 1.70 2010/03/02 00:38:59 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.71 2010/03/26 01:22:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -268,6 +268,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):
diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c
index ea72b39410f..06d9efab18d 100644
--- a/usr.bin/mandoc/term.c
+++ b/usr.bin/mandoc/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.25 2010/03/22 23:16:21 schwarze Exp $ */
+/* $Id: term.c,v 1.26 2010/03/26 01:22:07 schwarze 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);
}
@@ -134,7 +133,6 @@ term_flushln(struct termp *p)
int jhy; /* last hyphen before line overflow */
size_t maxvis, mmax;
static int line_started = 0;
- static int overstep = 0;
/*
* First, establish the maximum columns of "visible" content.
@@ -145,12 +143,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;
@@ -224,10 +222,10 @@ term_flushln(struct termp *p)
for (j = 0; j < (int)p->offset; j++)
putchar(' ');
}
- /* 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(' ');
@@ -252,7 +250,7 @@ term_flushln(struct termp *p)
}
p->col = 0;
- overstep = 0;
+ p->overstep = 0;
if ( ! (TERMP_NOBREAK & p->flags)) {
if (line_started) {
@@ -264,7 +262,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;
/*
@@ -277,12 +275,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;
diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h
index ad29d165d77..83c9f017a2d 100644
--- a/usr.bin/mandoc/term.h
+++ b/usr.bin/mandoc/term.h
@@ -1,4 +1,4 @@
-/* $Id: term.h,v 1.13 2009/12/24 02:08:14 schwarze Exp $ */
+/* $Id: term.h,v 1.14 2010/03/26 01:22:07 schwarze 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(). */