summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/chars.c4
-rw-r--r--usr.bin/mandoc/chars.in3
-rw-r--r--usr.bin/mandoc/libmdoc.h6
-rw-r--r--usr.bin/mandoc/main.c10
-rw-r--r--usr.bin/mandoc/mandoc.c4
-rw-r--r--usr.bin/mandoc/mandoc.h11
-rw-r--r--usr.bin/mandoc/manuals.7236
-rw-r--r--usr.bin/mandoc/mdoc.314
-rw-r--r--usr.bin/mandoc/mdoc.7385
-rw-r--r--usr.bin/mandoc/mdoc.c99
-rw-r--r--usr.bin/mandoc/mdoc.h3
-rw-r--r--usr.bin/mandoc/mdoc_action.c74
-rw-r--r--usr.bin/mandoc/mdoc_argv.c49
-rw-r--r--usr.bin/mandoc/mdoc_html.c137
-rw-r--r--usr.bin/mandoc/mdoc_macro.c159
-rw-r--r--usr.bin/mandoc/mdoc_term.c159
-rw-r--r--usr.bin/mandoc/mdoc_validate.c341
-rw-r--r--usr.bin/mandoc/roff.78
-rw-r--r--usr.bin/mandoc/roff.c6
20 files changed, 964 insertions, 748 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 6bf027e8d37..e9e566694d1 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.38 2010/06/06 18:08:41 schwarze Exp $
+# $OpenBSD: Makefile,v 1.39 2010/06/06 20:30:08 schwarze Exp $
.include <bsd.own.mk>
-VERSION=1.10.0
+VERSION=1.10.1
CFLAGS+=-DVERSION=\"${VERSION}\"
CFLAGS+=-W -Wall -Wstrict-prototypes
diff --git a/usr.bin/mandoc/chars.c b/usr.bin/mandoc/chars.c
index 3f839261af4..fb3c0b64ddc 100644
--- a/usr.bin/mandoc/chars.c
+++ b/usr.bin/mandoc/chars.c
@@ -1,4 +1,4 @@
-/* $Id: chars.c,v 1.7 2010/05/26 02:39:58 schwarze Exp $ */
+/* $Id: chars.c,v 1.8 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -39,7 +39,7 @@ struct ln {
#define CHARS_BOTH (CHARS_CHAR | CHARS_STRING)
};
-#define LINES_MAX 369
+#define LINES_MAX 370
#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 bd8b946934a..39e49923380 100644
--- a/usr.bin/mandoc/chars.in
+++ b/usr.bin/mandoc/chars.in
@@ -1,4 +1,4 @@
-/* $Id: chars.in,v 1.7 2010/04/02 12:39:47 schwarze Exp $ */
+/* $Id: chars.in,v 1.8 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -44,6 +44,7 @@ CHAR("%", 1, "", 0, "", 0)
CHAR("&", 1, "", 0, "", 0)
CHAR("^", 1, "", 0, "", 0)
CHAR("|", 1, "", 0, "", 0)
+CHAR("}", 1, "", 0, "", 0)
/* Accents. */
CHAR("a\"", 2, "\"", 1, "&#779;", 6)
diff --git a/usr.bin/mandoc/libmdoc.h b/usr.bin/mandoc/libmdoc.h
index 189cd25131d..ceeedfd3f0d 100644
--- a/usr.bin/mandoc/libmdoc.h
+++ b/usr.bin/mandoc/libmdoc.h
@@ -1,4 +1,4 @@
-/* $Id: libmdoc.h,v 1.36 2010/05/24 00:00:10 schwarze Exp $ */
+/* $Id: libmdoc.h,v 1.37 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -34,6 +34,7 @@ struct mdoc {
#define MDOC_NEWLINE (1 << 3) /* first macro/text in a line */
#define MDOC_PHRASELIT (1 << 4) /* literal within a partila phrase */
#define MDOC_PPHRASE (1 << 5) /* within a partial phrase */
+#define MDOC_FREECOL (1 << 6) /* `It' invocation should close */
int pflags;
enum mdoc_next next;
struct mdoc_node *last;
@@ -117,8 +118,7 @@ const char *mdoc_a2st(const char *);
const char *mdoc_a2arch(const char *);
const char *mdoc_a2vol(const char *);
const char *mdoc_a2msec(const char *);
-int mdoc_valid_pre(struct mdoc *,
- const struct mdoc_node *);
+int mdoc_valid_pre(struct mdoc *, struct mdoc_node *);
int mdoc_valid_post(struct mdoc *);
int mdoc_action_pre(struct mdoc *,
struct mdoc_node *);
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 0d9858ed90b..19ffe247f4a 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.33 2010/05/23 22:45:00 schwarze Exp $ */
+/* $Id: main.c,v 1.34 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -86,12 +86,11 @@ struct curparse {
static const char * const mandocerrs[MANDOCERR_MAX] = {
"ok",
"text should be uppercase",
- "sections out of conentional order",
+ "sections out of conventional order",
"section name repeats",
"out of order prologue",
"repeated prologue entry",
"list type must come first",
- "column syntax is inconsistent",
"bad standard",
"bad library",
"bad escape sequence",
@@ -100,7 +99,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"superfluous width argument",
"bad date argument",
"bad width argument",
- "unknown manual sction",
+ "unknown manual section",
"section not in conventional manual section",
"end of line whitespace",
"scope open on exit",
@@ -131,11 +130,12 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"macro requires body argument(s)",
"macro requires argument(s)",
"no title in document",
+ "missing list type",
"line argument(s) will be lost",
"body argument(s) will be lost",
+ "column syntax is inconsistent",
"missing font type",
"missing display type",
- "missing list type",
"displays may not be nested",
"no scope to rewind: syntax violated",
"scope broken, syntax violated",
diff --git a/usr.bin/mandoc/mandoc.c b/usr.bin/mandoc/mandoc.c
index 4f534f1589b..e83a98aa8ab 100644
--- a/usr.bin/mandoc/mandoc.c
+++ b/usr.bin/mandoc/mandoc.c
@@ -1,4 +1,4 @@
-/* $Id: mandoc.c,v 1.12 2010/05/26 02:39:58 schwarze Exp $ */
+/* $Id: mandoc.c,v 1.13 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -57,6 +57,8 @@ mandoc_special(const char *p)
/* FALLTHROUGH */
case (' '):
/* FALLTHROUGH */
+ case ('}'):
+ /* FALLTHROUGH */
case ('|'):
/* FALLTHROUGH */
case ('&'):
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h
index fb9911c46a7..6e1efa9e14e 100644
--- a/usr.bin/mandoc/mandoc.h
+++ b/usr.bin/mandoc/mandoc.h
@@ -1,4 +1,4 @@
-/* $Id: mandoc.h,v 1.5 2010/05/26 02:39:58 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.6 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -26,12 +26,11 @@ __BEGIN_DECLS
enum mandocerr {
MANDOCERR_OK,
MANDOCERR_UPPERCASE, /* text should be uppercase */
- MANDOCERR_SECOOO, /* sections out of conentional order */
+ MANDOCERR_SECOOO, /* sections out of conventional order */
MANDOCERR_SECREP, /* section name repeats */
MANDOCERR_PROLOGOOO, /* out of order prologue */
MANDOCERR_PROLOGREP, /* repeated prologue entry */
MANDOCERR_LISTFIRST, /* list type must come first */
- MANDOCERR_COLUMNS, /* column syntax is inconsistent */
MANDOCERR_BADSTANDARD, /* bad standard */
MANDOCERR_BADLIB, /* bad library */
MANDOCERR_BADESCAPE, /* bad escape sequence */
@@ -40,7 +39,7 @@ enum mandocerr {
MANDOCERR_WIDTHARG, /* superfluous width argument */
MANDOCERR_BADDATE, /* bad date argument */
MANDOCERR_BADWIDTH, /* bad width argument */
- MANDOCERR_BADMSEC, /* unknown manual sction */
+ MANDOCERR_BADMSEC, /* unknown manual section */
MANDOCERR_SECMSEC, /* section not in conventional manual section */
MANDOCERR_EOLNSPACE, /* end of line whitespace */
MANDOCERR_SCOPEEXIT, /* scope open on exit */
@@ -74,17 +73,17 @@ enum mandocerr {
MANDOCERR_NOBODY, /* macro requires body argument(s) */
MANDOCERR_NOARGV, /* macro requires argument(s) */
MANDOCERR_NOTITLE, /* no title in document */
+ MANDOCERR_LISTTYPE, /* missing list type */
MANDOCERR_ARGSLOST, /* line argument(s) will be lost */
MANDOCERR_BODYLOST, /* body argument(s) will be lost */
#define MANDOCERR_ERROR MANDOCERR_BODYLOST
+ MANDOCERR_COLUMNS, /* column syntax is inconsistent */
/* FIXME: this should be a MANDOCERR_ERROR */
MANDOCERR_FONTTYPE, /* missing font type */
/* FIXME: this should be a MANDOCERR_ERROR */
MANDOCERR_DISPTYPE, /* missing display type */
/* FIXME: this should be a MANDOCERR_ERROR */
- MANDOCERR_LISTTYPE, /* missing list type */
- /* FIXME: this should be a MANDOCERR_ERROR */
MANDOCERR_NESTEDDISP, /* displays may not be nested */
MANDOCERR_SYNTNOSCOPE, /* request scope close w/none open */
MANDOCERR_SYNTSCOPE, /* scope broken, syntax violated */
diff --git a/usr.bin/mandoc/manuals.7 b/usr.bin/mandoc/manuals.7
deleted file mode 100644
index 3fbb3c9486a..00000000000
--- a/usr.bin/mandoc/manuals.7
+++ /dev/null
@@ -1,236 +0,0 @@
-.\" $Id: manuals.7,v 1.6 2010/05/14 01:54:37 schwarze Exp $
-.\"
-.\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 14 2010 $
-.Dt MANUALS 7
-.Os
-.\" SECTION
-.Sh NAME
-.Nm Writing UNIX Documentation
-.Nd a guide to writing UNIX manuals
-.\" SECTION
-.Sh DESCRIPTION
-.Em A utility without good documentation is of no utility at all .
-.\" PARAGRAPH
-.Pp
-A system component's documentation describes the utility of that
-component, whether it's a device driver, an executable or, most
-importantly, a game.
-.Pp
-This document serves as a tutorial to writing
-.Ux
-documentation
-.Pq Dq manuals .
-.\" SECTION
-.Sh ENVIRONMENT
-First, copy over the manual template from
-.Pa /usr/share/misc/mdoc.template
-into your source directory.
-.Pp
-.Dl % cp /usr/share/misc/mdoc.template \.
-.Pp
-.Em \&Do not
-start afresh or by copying another manual unless you know exactly what
-you're doing! If the template doesn't exist, bug your administrator.
-.\" SUBSECTION
-.Ss Section Numbering
-Find an appropriate section for your manual. There may exist multiple
-manual names per section, so be specific:
-.Pp
-.\" LIST
-.Bl -tag -width "XXXXXXXXXXXX" -offset indent -compact
-.It Em Section
-.Em Description
-.It 1
-operator utilities
-.It 2
-system calls
-.It 3, 3p, 3f
-programming libraries (C, Perl, Fortran)
-.It 5
-file and wire protocol formats
-.It 6
-games
-.It 7
-tutorials, documents and papers
-.It 8
-administrator utilities
-.It 9
-in-kernel routines
-.El
-.Pp
-If your manual falls into multiple categories, choose the most
-widely-used or, better, re-consider the topic of your manual to be more
-specific. You can list all manuals per section by invoking
-.Xr apropos 1 ,
-then provide the
-.Fl s
-flag to
-.Xr man 1
-to see the specific section manual (section 1, in this example):
-.\" DISPLAY
-.Bd -literal -offset indent
-% apropos myname
-myname (1) - utility description
-myname (3) - library description
-% man \-s 1 myname
-.Ed
-.\" SUBSECTION
-.Ss Naming
-Name your component. Be terse, erring on the side of clarity. Look for
-other manuals by that same name before committing:
-.Pp
-.Dl % apropos myname
-.Pp
-Manual files are named
-.Pa myname.mysection ,
-such as
-.Pa manuals.7
-for this document. Rename the template file:
-.Pp
-.Dl % mv mdoc.template myname.mysection
-.\" SUBSECTION
-.Ss Development Tools
-While writing, make sure that your manual is correctly structured:
-.Pp
-.Dl % mandoc \-Tlint \-Wall \-fstrict name.1
-.Pp
-The quick-fix feature of
-.Xr vim 1
-is useful for checking over many manuals:
-.Bd -literal -offset indent
-% mandoc \-Wall \-fstrict \-Tlint \-fign-errors \e
- ./path/to/manuals/* 2>&1 > /tmp/mandoc.errs
-% vim -q /tmp/mandoc.errs
-.Ed
-.Pp
-You may spell-check your work as follows:
-.Pp
-.Dl % deroff name.1 | spell
-.Pp
-If
-.Xr ispell 1
-is installed, it has a special mode for manuals:
-.Pp
-.Dl % ispell \-n name.1
-.Pp
-Use
-.Xr cvs 1
-or
-.Xr rcs 1
-to version-control your work. If you wish the last check-in to effect
-your document's date, use the following RCS tag for the date macro:
-.Pp
-.Dl \&.Dd $Mdocdate: May 14 2010 $
-.\" SUBSECTION
-.Ss Viewing
-mdoc documents may be paged to your terminal with
-.Xr mandoc 1 .
-If you plan on distributing your work to systems without this tool,
-check it against
-.Xr groff 1 :
-.Bd -literal -offset indent
-% mandoc \-Wall name.1 2>&1 | less
-% groff -mandoc name.1 2>&1 | less
-.Ed
-.\" SUBSECTION
-.Ss Automation
-Consider adding your mdoc documents to
-.Xr make 1
-Makefiles in order to automatically check your input:
-.Bd -literal -offset indent
-\&.SUFFIXES: .1 .in
-
-\&.in.1:
- mandoc -Wall,error -Tlint $<
- cp -f $< $@
-.Ed
-.\" SUBSECTION
-.Ss Licensing
-Your manual must have a license. It should be listed at the start of
-your document, just as in source code.
-.\" SECTION
-.Sh COMPOSITION
-Manuals should
-.Em always
-be written in the
-.Xr mdoc 7
-formatting language.
-.\" PARAGRAPH
-.Pp
-Open the template you've copied into
-.Pa myname.mysection
-and begin editing.
-.\" SUBSECTION
-.Ss Language
-.Bl -enum
-.It
-Use clear, concise language. Favour simplicity.
-.It
-Write your manual in non-idiomatic English. Don't worry about
-Commonwealth or American spellings \(em just correct ones.
-.It
-Spell-check your manual, keeping in mind short-letter terms (
-.Xr iwi 4
-vs.
-.Xr iwn 4 ) .
-.It
-If you absolutely must use special characters (diacritics, mathematical
-symbols and so on), use the escapes dictated in
-.Xr mdoc 7 .
-.El
-.\" SUBSECTION
-.Ss Style
-The structure of the mdoc language makes it very hard to have any
-particular format style. Keep your lines under 72 characters in length.
-If you must have long option lines, use
-.Sq \&Oo/Oc .
-The same goes for function prototypes.
-.Em \&Do not
-use
-.Sq \&Xo/Xc .
-Find another way to structure your line.
-.\" SUBSECTION
-.Ss References
-Other components may be referenced with the
-.Sq \&Xr
-and
-.Sq \&Sx
-macros. Make sure that these exist. If you intend to distribute your
-manual, make sure
-.Sq \&Xr
-references are valid across systems (within reason). If you cross-link with
-.Sq \&Sx ,
-make sure that the section reference exists.
-.\" SUBSECTION
-.Ss Citations
-Cite your work. If your system references standards documents or other
-publications, please use the
-.Sq \&Rs/Re
-block macros.
-.\" SUBSECTION
-.Ss Formatting
-.Em Don't style your manual .
-Give it meaningful content. The front-end will worry about formatting
-and style.
-.\" SECTION
-.Sh MAINTENANCE
-As your component changes and bugs are fixed, your manual may become out
-of date. You may be tempted to use tools like Doxygen to automate the
-development of your manuals. Don't.
-.Pp
-.Em Manuals are part of a system component :
-if you modify your code or specifications, modify the documentation.
diff --git a/usr.bin/mandoc/mdoc.3 b/usr.bin/mandoc/mdoc.3
index eb382e31b9f..5eb59e962d1 100644
--- a/usr.bin/mandoc/mdoc.3
+++ b/usr.bin/mandoc/mdoc.3
@@ -1,4 +1,4 @@
-.\" $Id: mdoc.3,v 1.7 2010/05/26 02:55:16 schwarze Exp $
+.\" $Id: mdoc.3,v 1.8 2010/06/06 20:30:08 schwarze Exp $
.\"
.\" Copyright (c) 2009-2010 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -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: May 26 2010 $
+.Dd $Mdocdate: June 6 2010 $
.Dt MDOC 3
.Os
.Sh NAME
@@ -221,9 +221,7 @@ where capitalised non-terminals represent nodes.
.It mnode
\(<- BLOCK | ELEMENT | TEXT
.It BLOCK
-\(<- (HEAD [TEXT])+ [BODY [TEXT]] [TAIL [TEXT]]
-.It BLOCK
-\(<- BODY [TEXT] [TAIL [TEXT]]
+\(<- HEAD [TEXT] (BODY [TEXT])+ [TAIL [TEXT]]
.It ELEMENT
\(<- TEXT*
.It HEAD
@@ -237,12 +235,14 @@ where capitalised non-terminals represent nodes.
.El
.Pp
Of note are the TEXT nodes following the HEAD, BODY and TAIL nodes of
-the BLOCK production.
-These refer to punctuation marks.
+the BLOCK production: these refer to punctuation marks.
Furthermore, although a TEXT node will generally have a non-zero-length
string, in the specific case of
.Sq \&.Bd \-literal ,
an empty line will produce a zero-length string.
+Multiple body parts are only found in invocations of
+.Sq \&Bl \-column ,
+where a new body introduces a new phrase.
.Sh EXAMPLES
The following example reads lines from stdin and parses them, operating
on the finished parse tree with
diff --git a/usr.bin/mandoc/mdoc.7 b/usr.bin/mandoc/mdoc.7
index 32b7ab70401..6eeb96e9260 100644
--- a/usr.bin/mandoc/mdoc.7
+++ b/usr.bin/mandoc/mdoc.7
@@ -1,4 +1,4 @@
-.\" $Id: mdoc.7,v 1.33 2010/06/06 18:08:41 schwarze Exp $
+.\" $Id: mdoc.7,v 1.34 2010/06/06 20:30:08 schwarze Exp $
.\"
.\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -33,7 +33,7 @@ section describes compatibility with other troff \-mdoc implementations.
.Pp
An
.Nm
-document follows simple rules: lines beginning with the control
+document follows simple rules: lines beginning with the control
character
.Sq \.
are parsed for macros. Other lines are interpreted within the scope of
@@ -122,7 +122,7 @@ escape followed by an indicator: B (bold), I, (italic), R (Roman), or P
A numerical representation 3, 2, or 1 (bold, italic, and Roman,
respectively) may be used instead.
A text decoration is valid within
-the current font scope only: if a macro opens a font scope alongside
+the current font scope only: if a macro opens a font scope alongside
its own scope, such as
.Sx \&Bf
.Cm \&Sy ,
@@ -343,18 +343,15 @@ file:
\&.Dd $\&Mdocdate$
\&.Dt mdoc 7
\&.Os
-\&.
\&.Sh NAME
\&.Nm foo
\&.Nd a description goes here
\&.\e\*q The next is for sections 2, 3, & 9 only.
\&.\e\*q .Sh LIBRARY
-\&.
\&.Sh SYNOPSIS
\&.Nm foo
\&.Op Fl options
\&.Ar
-\&.
\&.Sh DESCRIPTION
The
\&.Nm
@@ -1139,22 +1136,18 @@ macro.
These dictate the width of columns either as
.Sx Scaling Widths
or literal text.
-List entry bodies must be left empty.
-Column bodies have the following syntax:
-.Pp
-.D1 .It col1 <TAB> ... coln
-.D1 .It col1 Ta ... coln
-.D1 .It col1 <TAB> col2 Ta coln
-.Pp
-where columns may be separated by tabs, the literal string
-.Qq Ta ,
-or a mixture of both.
-These are equivalent except that quoted sections propogate over tabs,
-for example,
-.Pp
-.D1 .It \(dqcol1 ; <TAB> col2 ;\(dq ;
-.Pp
-will preserve the semicolon whitespace except for the last.
+If the initial macro of a
+.Fl column
+list is not an
+.Sx \&It ,
+an
+.Sx \&It
+context spanning each line is implied until an
+.Sx \&It
+line macro is encountered, at which point list bodies are interpreted as
+described in the
+.Sx \&It
+documentation.
.It Fl dash
A list offset by a dash (hyphen).
The head of list entries must be empty.
@@ -1209,6 +1202,9 @@ after the head as specified by the
.Fl width
argument.
.El
+.Pp
+See also
+.Sx \&It .
.Ss \&Bo
Begins a block enclosed by square brackets.
Does not have any head arguments.
@@ -1336,6 +1332,11 @@ See also
and
.Sx \&Dl .
.Ss \&Db
+Start a debugging context.
+This macro is parsed, but generally ignored.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&Db Cm on | off
.Ss \&Dc
Closes a
.Sx \&Do
@@ -1345,9 +1346,9 @@ Document date.
This is the mandatory first macro of any
.Nm
manual.
-Its calling syntax is as follows:
+Its syntax is as follows:
.Pp
-.D1 \. Ns Sx \&Dd Cm date
+.D1 Pf \. Sx \&Dd Cm date
.Pp
The
.Cm date
@@ -1406,15 +1407,25 @@ Document title.
This is the mandatory second macro of any
.Nm
file.
-Its calling syntax is as follows:
-.Pp
-.D1 \. Ns Sx \&Dt Cm title section Op Cm volume | arch
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Dt
+.Oo
+.Cm title
+.Oo
+.Cm section
+.Op Cm volume | arch
+.Oc
+.Oc
+.Ed
.Pp
Its arguments are as follows:
.Bl -tag -width Ds -offset Ds
.It Cm title
-The document's title (name).
-This should be capitalised and is required.
+The document's title (name), defaulting to
+.Qq UNKNOWN
+if unspecified.
+It should be capitalised.
.It Cm section
The manual section.
This may be one of
@@ -1451,8 +1462,9 @@ This may be one of
or
.Ar paper
.Pq paper .
-It is also required and should correspond to the manual's filename
-suffix.
+It should correspond to the manual's filename suffix and defaults to
+.Qq 1
+if unspecified.
.It Cm volume
This overrides the volume inferred from
.Ar section .
@@ -1524,7 +1536,6 @@ Examples:
.D1 \&.Dt FOO 1
.D1 \&.Dt FOO 4 KM
.D1 \&.Dt FOO 9 i386
-.D1 \&.Dt FOO 9 KM i386
.Pp
See also
.Sx \&Dd
@@ -1561,6 +1572,13 @@ and
.Ss \&Ef
.Ss \&Ek
.Ss \&El
+Ends a list context started by
+.Sx \&Bl .
+.Pp
+See also
+.Sx \&Bl
+and
+.Sx \&It .
.Ss \&Em
Denotes text that should be emphasised.
Note that this is a presentation term and should not be used for
@@ -1600,8 +1618,45 @@ is not provided, the document's name as stipulated in
.Sx \&Nm
is provided.
.Ss \&Fa
+Function argument.
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Fa
+.Op Cm argtype
+.Cm argname
+.Ed
+.Pp
+This may be invoked for names with or without the corresponding type.
+It is also used to specify the field name of a structure.
+Most often, the
+.Sx \&Fa
+macro is used in the
+.Em SYNOPSIS
+within
+.Sx \&Fo
+section when documenting multi-line function prototypes.
+If invoked with multiple arguments, the arguments are separated by a
+comma.
+Furthermore, if the following macro is another
+.Sx \&Fa ,
+the last argument will also have a trailing comma.
+.Pp
+Examples:
+.D1 \&.Fa \(dqconst char *p\(dq
+.D1 \&.Fa \(dqint a\(dq \(dqint b\(dq \(dqint c\(dq
+.D1 \&.Fa foo
+.Pp
+See also
+.Sx \&Fo .
.Ss \&Fc
.Ss \&Fd
+Historically used to document include files.
+This usage has been deprecated in favour of
+.Sx \&In .
+Do not use this macro.
+.Pp
+See also
+.Sx \&In .
.Ss \&Fl
Command-line flag.
Used when listing arguments to command-line utilities.
@@ -1621,9 +1676,106 @@ Examples:
See also
.Sx \&Cm .
.Ss \&Fn
+A function name.
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Ns Sx \&Fn
+.Op Cm functype
+.Cm funcname
+.Op Oo Cm argtype Oc Cm argname
+.Ed
+.Pp
+If invoked in the
+.Em SYNOPSIS
+section, vertical space is asserted before and after the macro.
+In all cases, the function arguments are surrounded in parenthesis and
+are delimited by commas.
+If no arguments are specified, blank parenthesis are output.
+.Pp
+Examples:
+.D1 \&.Fn "int funcname" "int arg0" "int arg1"
+.D1 \&.Fn funcname "int arg0"
+.D1 \&.Fn funcname arg0
+.Bd -literal -offset indent -compact
+\&.Ft functype
+\&.Fn funcname
+.Ed
+.Pp
+See also
+.Sx \&Fa ,
+.Sx \&Fo ,
+.Sx \&Fc ,
+and
+.Sx \&Ft .
.Ss \&Fo
+Begin a function block.
+This is a multi-line version of
+.Sx \&Fn .
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&Fo Cm funcname
+.Pp
+Invocations usually occur in the following context:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Ft Cm functype
+.br
+.Pf \. Sx \&Fo Cm funcname
+.br
+.Pf \. Sx \&Fa Oo Cm argtype Oc Cm argname
+.br
+\.\.\.
+.br
+.Pf \. Sx \&Fc
+.Ed
+.Pp
+In the
+.Em SYNOPSIS
+section, a
+.Sx \&Fo
+block is surrounded by vertical space unless
+.Sx \&Ft
+is the prior macro, in which case it is preceded by only a newline.
+.Pp
+A
+.Sx \&Fo
+scope is closed by
+.Pp
+See also
+.Sx \&Fa ,
+.Sx \&Fc ,
+and
+.Sx \&Fn .
+.Sx \&Fc .
.Ss \&Fr
.Ss \&Ft
+A function type.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&Ft Cm functype
+.Pp
+If invoked before a
+.Sx \&Fo
+or
+.Sx \&Fn
+in the
+.Em SYNOPSIS
+section, a line-break will follow.
+Furthermore, if invoked in the
+.Em SYNOPSIS
+section, it will assert vertical space prior to its arguments.
+.Pp
+Examples:
+.D1 \&.Ft int
+.Bd -literal -offset indent -compact
+\&.Ft functype
+\&.Fn funcname
+.Ed
+.Pp
+See also
+.Sx \&Fo ,
+.Sx \&Fc ,
+and
+.Sx \&Fn .
.Ss \&Fx
Format the FreeBSD version provided as an argument, or a default value
if no argument is provided.
@@ -1644,12 +1796,106 @@ and
.Ss \&Hf
.Ss \&Ic
.Ss \&In
+An
+.Qq include
+file.
+In the
+.Em SYNOPSIS
+section (only if invoked as the line macro), the first argument is
+preceded by
+.Qq #include ,
+the arguments is enclosed in angled braces, and a newline is asserted.
+In all other invocations, only angled braces will enclose the argument.
+.Pp
+Examples
+.D1 \&.In sys/types
.Ss \&It
+A list item.
+The syntax of this macro depends on the list type.
+.Pp
+Lists
+of type
+.Fl hang ,
+.Fl ohang ,
+.Fl inset ,
+and
+.Fl diag
+have the following syntax:
+.Pp
+.D1 Pf \. Sx \&It Cm args
+.Pp
+Lists of type
+.Fl bullet ,
+.Fl dash ,
+.Fl enum ,
+.Fl hyphen
+and
+.Fl item
+have the following syntax:
+.Pp
+.D1 Pf \. Sx \&It
+.Pp
+with subsequent lines interpreted within the scope of the
+.Sx \&It
+until either a closing
+.Sx \&El
+or another
+.Sx \&It .
+.Pp
+The
+.Fl tag
+list has the following syntax:
+.Pp
+.D1 Pf \. Sx \&It Op Cm args
+.Pp
+Subsequent lines are interpreted as with
+.Fl bullet
+and family.
+The line arguments correspond to the list's left-hand side; body
+arguments correspond to the list's contents.
+.Pp
+The
+.Fl column
+list is the most complicated.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&It Op Cm args
+.Pp
+The
+.Cm args
+are phrases, a mix of macros and text corresponding to a line column,
+delimited by tabs or the special
+.Sq \&Ta
+pseudo-macro.
+Lines subsequent the
+.Sx \&It
+are interpreted within the scope of the last phrase.
+Calling the pseudo-macro
+.Sq \&Ta
+will open a new phrase scope (this must occur on a macro line to be
+interpreted as a macro). Note that the tab phrase delimiter may only be
+used within the
+.Sx \&It
+line itself.
+Subsequent this, only the
+.Sq \&Ta
+pseudo-macro may be used to delimit phrases.
+Furthermore, note that quoted sections propogate over tab-delimited
+phrases on an
+.Sx \&It ,
+for example,
+.Pp
+.D1 .It \(dqcol1 ; <TAB> col2 ;\(dq ;
+.Pp
+will preserve the semicolon whitespace except for the last.
+.Pp
+See also
+.Sx \&Bl .
.Ss \&Lb
Specify a library.
-The calling syntax is as follows:
+The syntax is as follows:
.Pp
-.D1 \. Ns Sx \&Lb Cm library
+.D1 Pf \. Sx \&Lb Cm library
.Pp
The
.Cm library
@@ -1671,9 +1917,9 @@ Examples:
.Ss \&Li
.Ss \&Lk
Format a hyperlink.
-The calling syntax is as follows:
+Its syntax is as follows:
.Pp
-.D1 \. Ns Sx \&Lk Cm uri Op Cm name
+.D1 Pf \. Sx \&Lk Cm uri Op Cm name
.Pp
Examples:
.D1 \&.Lk http://bsd.lv "The BSD.lv Project"
@@ -1684,6 +1930,15 @@ See also
.Ss \&Lp
.Ss \&Ms
.Ss \&Mt
+Format a
+.Qq mailto:
+hyperlink.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&Mt Cm address
+.Pp
+Examples:
+.D1 \&.Mt discuss@manpages.bsd.lv
.Ss \&Nd
.Ss \&Nm
.Ss \&No
@@ -1713,9 +1968,10 @@ Document operating system version.
This is the mandatory third macro of
any
.Nm
-file. Its calling syntax is as follows:
+file.
+Its syntax is as follows:
.Pp
-.D1 \. Ns Sx \&Os Op Cm system
+.D1 Pf \. Sx \&Os Op Cm system
.Pp
The optional
.Cm system
@@ -1787,6 +2043,7 @@ The block macro may only contain
.Sx \&%Q ,
.Sx \&%R ,
.Sx \&%T ,
+.Sx \&%U ,
and
.Sx \&%V
child macros (at least one must be specified).
@@ -1872,9 +2129,9 @@ since this limit has been lifted, the macro has been deprecated.
.Ss \&Xr
Link to another manual
.Pq Qq cross-reference .
-Its calling syntax is
+Its syntax is as follows:
.Pp
-.D1 \. Ns Sx \&Xr Cm name section
+.D1 Pf \. Sx \&Xr Cm name section
.Pp
The
.Cm name
@@ -1911,6 +2168,49 @@ Heirloom troff, the other significant troff implementation accepting
.Pp
.Bl -dash -compact
.It
+groff behaves inconsistently when encountering
+.Pf non- Sx \&Fa
+children of
+.Sx \&Fo
+regarding spacing between arguments.
+In mandoc, this is not the case: each argument is consistently followed
+by a single space and the trailing
+.Sq \&)
+suppresses prior spacing.
+.It
+groff behaves inconsistently when encountering
+.Sx \&Ft
+and
+.Sx \&Fn
+in the
+.Em SYNOPSIS :
+at times newline(s) are suppressed dependong on whether a prior
+.Sx \&Fn
+has been invoked.
+In mandoc, this is not the case.
+See
+.Sx \&Ft
+and
+.Sx \&Fn
+for the normalised behaviour.
+.It
+Historic groff does not break before an
+.Sx \&Fn
+when not invoked as the line macro in the
+.Em SYNOPSIS
+section.
+.It
+Historic groff formats the
+.Sx \&In
+badly: trailing arguments are trashed and
+.Em SYNOPSIS
+is not specially treated.
+.It
+groff does not accept the
+.Sq \&Ta
+pseudo-macro as a line macro.
+mandoc does.
+.It
The comment syntax
.Sq \e."
is no longer accepted.
@@ -1983,11 +2283,6 @@ delimiter to render.
This is not supported in mandoc.
.It
In groff, the
-.Sx \&Fo
-macro only produces the first parameter.
-This is not the case in mandoc.
-.It
-In groff, the
.Sx \&Cd ,
.Sx \&Er ,
.Sx \&Ex ,
diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c
index 2544ebb9113..aec75eae499 100644
--- a/usr.bin/mandoc/mdoc.c
+++ b/usr.bin/mandoc/mdoc.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc.c,v 1.55 2010/05/26 02:39:58 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.56 2010/06/06 20:30:08 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -65,7 +65,7 @@ const char *const __mdoc_macronames[MDOC_MAX] = {
/* LINTED */
"Dx", "%Q", "br", "sp",
/* LINTED */
- "%U"
+ "%U", "Ta"
};
const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
@@ -272,11 +272,11 @@ mdoc_macro(struct mdoc *m, enum mdoct tok,
if ( ! mdoc_pmsg(m, ln, pp, MANDOCERR_BADPROLOG))
return(0);
if (NULL == m->meta.title)
- m->meta.title = mandoc_strdup("unknown");
+ m->meta.title = mandoc_strdup("UNKNOWN");
if (NULL == m->meta.vol)
- m->meta.vol = mandoc_strdup("local");
+ m->meta.vol = mandoc_strdup("LOCAL");
if (NULL == m->meta.os)
- m->meta.os = mandoc_strdup("local");
+ m->meta.os = mandoc_strdup("LOCAL");
if (0 == m->meta.date)
m->meta.date = time(NULL);
m->flags |= MDOC_PBODY;
@@ -538,7 +538,8 @@ mdoc_node_delete(struct mdoc *m, struct mdoc_node *p)
static int
mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
{
- char *c, *ws, *end;
+ char *c, *ws, *end;
+ struct mdoc_node *n;
/* Ignore bogus comments. */
@@ -552,16 +553,45 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
if (SEC_NONE == m->lastnamed)
return(mdoc_pmsg(m, line, offs, MANDOCERR_NOTEXT));
+ assert(m->last);
+ n = m->last;
+
+ /*
+ * Divert directly to list processing if we're encountering a
+ * columnar MDOC_BLOCK with or without a prior MDOC_BLOCK entry
+ * (a MDOC_BODY means it's already open, in which case we should
+ * process within its context in the normal way).
+ */
+
+ if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
+ LIST_column == n->data.list) {
+ /* `Bl' is open without any children. */
+ m->flags |= MDOC_FREECOL;
+ return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
+ }
+
+ if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
+ NULL != n->parent &&
+ MDOC_Bl == n->parent->tok &&
+ LIST_column == n->parent->data.list) {
+ /* `Bl' has block-level `It' children. */
+ m->flags |= MDOC_FREECOL;
+ return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
+ }
+
/*
* Search for the beginning of unescaped trailing whitespace (ws)
* and for the first character not to be output (end).
*/
+
+ /* FIXME: replace with strcspn(). */
ws = NULL;
for (c = end = buf + offs; *c; c++) {
switch (*c) {
case '-':
if (mandoc_hyph(buf + offs, c))
*c = ASCII_HYPH;
+ ws = NULL;
break;
case ' ':
if (NULL == ws)
@@ -646,6 +676,7 @@ macrowarn(struct mdoc *m, int ln, const char *buf, int offs)
buf, strlen(buf) > 3 ? "..." : "");
/* FIXME: logic should be in driver. */
+ /* FIXME: broken, will error out and not omit a message. */
return(MDOC_IGN_MACRO & m->pflags ? rc : 0);
}
@@ -657,9 +688,10 @@ macrowarn(struct mdoc *m, int ln, const char *buf, int offs)
int
mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
{
- enum mdoct tok;
- int i, j, sv;
- char mac[5];
+ enum mdoct tok;
+ int i, j, sv;
+ char mac[5];
+ struct mdoc_node *n;
/* Empty lines are ignored. */
@@ -727,10 +759,51 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
if ( ! mdoc_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE))
goto err;
- /*
- * Begin recursive parse sequence. Since we're at the start of
- * the line, we don't need to do callable/parseable checks.
+ /*
+ * If an initial macro or a list invocation, divert directly
+ * into macro processing.
*/
+
+ if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) {
+ if ( ! mdoc_macro(m, tok, ln, sv, &i, buf))
+ goto err;
+ return(1);
+ }
+
+ n = m->last;
+ assert(m->last);
+
+ /*
+ * If the first macro of a `Bl -column', open an `It' block
+ * context around the parsed macro.
+ */
+
+ if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
+ LIST_column == n->data.list) {
+ m->flags |= MDOC_FREECOL;
+ if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
+ goto err;
+ return(1);
+ }
+
+ /*
+ * If we're following a block-level `It' within a `Bl -column'
+ * context (perhaps opened in the above block or in ptext()),
+ * then open an `It' block context around the parsed macro.
+ */
+
+ if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
+ NULL != n->parent &&
+ MDOC_Bl == n->parent->tok &&
+ LIST_column == n->parent->data.list) {
+ m->flags |= MDOC_FREECOL;
+ if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
+ goto err;
+ return(1);
+ }
+
+ /* Normal processing of a macro. */
+
if ( ! mdoc_macro(m, tok, ln, sv, &i, buf))
goto err;
diff --git a/usr.bin/mandoc/mdoc.h b/usr.bin/mandoc/mdoc.h
index 3b01a1854b9..80e04579da4 100644
--- a/usr.bin/mandoc/mdoc.h
+++ b/usr.bin/mandoc/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.26 2010/05/24 00:00:10 schwarze Exp $ */
+/* $Id: mdoc.h,v 1.27 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -149,6 +149,7 @@ enum mdoct {
MDOC_br,
MDOC_sp,
MDOC__U,
+ MDOC_Ta,
MDOC_MAX
};
diff --git a/usr.bin/mandoc/mdoc_action.c b/usr.bin/mandoc/mdoc_action.c
index 833ca34c497..dbb100c3123 100644
--- a/usr.bin/mandoc/mdoc_action.c
+++ b/usr.bin/mandoc/mdoc_action.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_action.c,v 1.39 2010/06/06 18:08:41 schwarze Exp $ */
+/* $Id: mdoc_action.c,v 1.40 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -190,6 +190,7 @@ static const struct actions mdoc_actions[MDOC_MAX] = {
{ NULL, NULL }, /* br */
{ NULL, NULL }, /* sp */
{ NULL, NULL }, /* %U */
+ { NULL, NULL }, /* Ta */
};
#define RSORD_MAX 14
@@ -495,8 +496,8 @@ post_dt(POST_ARGS)
if (NULL == (nn = n->child)) {
/* XXX: make these macro values. */
/* FIXME: warn about missing values. */
- m->meta.title = mandoc_strdup("unknown");
- m->meta.vol = mandoc_strdup("local");
+ m->meta.title = mandoc_strdup("UNKNOWN");
+ m->meta.vol = mandoc_strdup("LOCAL");
m->meta.msec = mandoc_strdup("1");
return(post_prol(m, n));
}
@@ -505,12 +506,13 @@ post_dt(POST_ARGS)
* --> title = TITLE, volume = local, msec = 0, arch = NULL
*/
- m->meta.title = mandoc_strdup(nn->string);
+ m->meta.title = mandoc_strdup
+ ('\0' == nn->string[0] ? "UNKNOWN" : nn->string);
if (NULL == (nn = nn->next)) {
/* FIXME: warn about missing msec. */
/* XXX: make this a macro value. */
- m->meta.vol = mandoc_strdup("local");
+ m->meta.vol = mandoc_strdup("LOCAL");
m->meta.msec = mandoc_strdup("1");
return(post_prol(m, n));
}
@@ -942,8 +944,7 @@ pre_offset(PRE_ARGS)
* stipulated by mdoc.samples.
*/
- assert(n->args);
- for (i = 0; i < (int)n->args->argc; i++) {
+ for (i = 0; n->args && i < (int)n->args->argc; i++) {
if (MDOC_Offset != n->args->argv[i].arg)
continue;
if (n->args->argv[i].sz)
@@ -963,63 +964,10 @@ pre_offset(PRE_ARGS)
static int
pre_bl(PRE_ARGS)
{
- int pos;
-
- if (MDOC_BLOCK != n->type) {
- assert(n->parent);
- assert(MDOC_BLOCK == n->parent->type);
- assert(MDOC_Bl == n->parent->tok);
- assert(LIST__NONE != n->parent->data.list);
- n->data.list = n->parent->data.list;
- return(1);
- }
-
- assert(LIST__NONE == n->data.list);
-
- for (pos = 0; pos < (int)n->args->argc; pos++) {
- switch (n->args->argv[pos].arg) {
- case (MDOC_Bullet):
- n->data.list = LIST_bullet;
- break;
- case (MDOC_Dash):
- n->data.list = LIST_dash;
- break;
- case (MDOC_Enum):
- n->data.list = LIST_enum;
- break;
- case (MDOC_Hyphen):
- n->data.list = LIST_hyphen;
- break;
- case (MDOC_Item):
- n->data.list = LIST_item;
- break;
- case (MDOC_Tag):
- n->data.list = LIST_tag;
- break;
- case (MDOC_Diag):
- n->data.list = LIST_diag;
- break;
- case (MDOC_Hang):
- n->data.list = LIST_hang;
- break;
- case (MDOC_Ohang):
- n->data.list = LIST_ohang;
- break;
- case (MDOC_Inset):
- n->data.list = LIST_inset;
- break;
- case (MDOC_Column):
- n->data.list = LIST_column;
- break;
- default:
- break;
- }
- if (LIST__NONE != n->data.list)
- break;
- }
- assert(LIST__NONE != n->data.list);
- return(pre_offset(m, n));
+ if (MDOC_BLOCK == n->type)
+ return(pre_offset(m, n));
+ return(1);
}
diff --git a/usr.bin/mandoc/mdoc_argv.c b/usr.bin/mandoc/mdoc_argv.c
index bdd8a115a9e..ef98643e148 100644
--- a/usr.bin/mandoc/mdoc_argv.c
+++ b/usr.bin/mandoc/mdoc_argv.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_argv.c,v 1.29 2010/05/23 22:45:00 schwarze Exp $ */
+/* $Id: mdoc_argv.c,v 1.30 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -206,6 +206,7 @@ static int mdoc_argflags[MDOC_MAX] = {
0, /* br */
0, /* sp */
0, /* %U */
+ 0, /* Ta */
};
@@ -222,7 +223,7 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
struct mdoc_argv tmp;
struct mdoc_arg *arg;
- if (0 == buf[*pos])
+ if ('\0' == buf[*pos])
return(ARGV_EOLN);
assert(' ' != buf[*pos]);
@@ -243,10 +244,10 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
/* XXX - save zeroed byte, if not an argument. */
- sv = 0;
+ sv = '\0';
if (buf[*pos]) {
sv = buf[*pos];
- buf[(*pos)++] = 0;
+ buf[(*pos)++] = '\0';
}
(void)memset(&tmp, 0, sizeof(struct mdoc_argv));
@@ -335,7 +336,7 @@ enum margserr
mdoc_args(struct mdoc *m, int line, int *pos,
char *buf, enum mdoct tok, char **v)
{
- int fl, c, i;
+ int fl;
struct mdoc_node *n;
fl = mdoc_argflags[tok];
@@ -343,26 +344,20 @@ mdoc_args(struct mdoc *m, int line, int *pos,
if (MDOC_It != tok)
return(args(m, line, pos, buf, fl, v));
- /*
- * The `It' macro is a special case, as it acquires parameters from its
- * parent `Bl' context, specifically, we're concerned with -column.
+ /*
+ * We know that we're in an `It', so it's reasonable to expect
+ * us to be sitting in a `Bl'. Someday this may not be the case
+ * (if we allow random `It's sitting out there), so provide a
+ * safe fall-back into the default behaviour.
*/
for (n = m->last; n; n = n->parent)
- if (MDOC_BLOCK == n->type && MDOC_Bl == n->tok)
+ if (MDOC_Bl == n->tok)
break;
- assert(n);
- c = (int)(n->args ? n->args->argc : 0);
- assert(c > 0);
-
- /* LINTED */
- for (i = 0; i < c; i++) {
- if (MDOC_Column != n->args->argv[i].arg)
- continue;
+ if (n && LIST_column == n->data.list) {
fl |= ARGS_TABSEP;
fl &= ~ARGS_DELIM;
- break;
}
return(args(m, line, pos, buf, fl, v));
@@ -373,9 +368,10 @@ static enum margserr
args(struct mdoc *m, int line, int *pos,
char *buf, int fl, char **v)
{
- int i;
- char *p, *pp;
- enum margserr rc;
+ int i;
+ char *p, *pp;
+ enum margserr rc;
+ enum mdelim d;
/*
* Parse out the terms (like `val' in `.Xx -arg val' or simply
@@ -392,7 +388,6 @@ args(struct mdoc *m, int line, int *pos,
* phrases like in `Bl -column'.
*/
- assert(*pos);
assert(' ' != buf[*pos]);
if ('\0' == buf[*pos]) {
@@ -420,7 +415,7 @@ args(struct mdoc *m, int line, int *pos,
if ((fl & ARGS_DELIM) && DELIM_CLOSE == mdoc_iscdelim(buf[*pos])) {
for (i = *pos; buf[i]; ) {
- enum mdelim d = mdoc_iscdelim(buf[i]);
+ d = mdoc_iscdelim(buf[i]);
if (DELIM_NONE == d || DELIM_OPEN == d)
break;
i++;
@@ -433,7 +428,7 @@ args(struct mdoc *m, int line, int *pos,
if ('\0' == buf[i]) {
*v = &buf[*pos];
- if (' ' != buf[i - 1])
+ if (i && ' ' != buf[i - 1])
return(ARGS_PUNCT);
if (ARGS_NOWARN & fl)
return(ARGS_PUNCT);
@@ -464,7 +459,7 @@ args(struct mdoc *m, int line, int *pos,
break;
if (pp > *v && ' ' != *(pp - 1))
continue;
- if (' ' == *(pp + 2) || 0 == *(pp + 2))
+ if (' ' == *(pp + 2) || '\0' == *(pp + 2))
break;
}
@@ -491,7 +486,7 @@ args(struct mdoc *m, int line, int *pos,
}
/* Whitespace check for eoln case... */
- if (0 == *p && ' ' == *(p - 1) && ! (ARGS_NOWARN & fl))
+ if ('\0' == *p && ' ' == *(p - 1) && ! (ARGS_NOWARN & fl))
if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
return(ARGS_ERROR);
@@ -564,7 +559,7 @@ args(struct mdoc *m, int line, int *pos,
*/
for ( ; buf[*pos]; (*pos)++)
- if (' ' == buf[*pos] && '\\' != buf[*pos - 1])
+ if (*pos && ' ' == buf[*pos] && '\\' != buf[*pos - 1])
break;
if ('\0' == buf[*pos])
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index 658dfbf2c96..be432204989 100644
--- a/usr.bin/mandoc/mdoc_html.c
+++ b/usr.bin/mandoc/mdoc_html.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_html.c,v 1.19 2010/05/24 12:33:06 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.20 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -80,6 +80,7 @@ static void mdoc_dq_post(MDOC_ARGS);
static int mdoc_dq_pre(MDOC_ARGS);
static int mdoc_dv_pre(MDOC_ARGS);
static int mdoc_fa_pre(MDOC_ARGS);
+static void mdoc_fd_post(MDOC_ARGS);
static int mdoc_fd_pre(MDOC_ARGS);
static int mdoc_fl_pre(MDOC_ARGS);
static int mdoc_fn_pre(MDOC_ARGS);
@@ -96,7 +97,8 @@ static int mdoc_it_block_pre(MDOC_ARGS, enum mdoc_list,
int, struct roffsu *, struct roffsu *);
static int mdoc_it_head_pre(MDOC_ARGS, enum mdoc_list,
struct roffsu *);
-static int mdoc_it_body_pre(MDOC_ARGS, enum mdoc_list);
+static int mdoc_it_body_pre(MDOC_ARGS, enum mdoc_list,
+ struct roffsu *);
static int mdoc_it_pre(MDOC_ARGS);
static int mdoc_lb_pre(MDOC_ARGS);
static int mdoc_li_pre(MDOC_ARGS);
@@ -153,7 +155,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
{mdoc_ev_pre, NULL}, /* Ev */
{mdoc_ex_pre, NULL}, /* Ex */
{mdoc_fa_pre, NULL}, /* Fa */
- {mdoc_fd_pre, NULL}, /* Fd */
+ {mdoc_fd_pre, mdoc_fd_post}, /* Fd */
{mdoc_fl_pre, NULL}, /* Fl */
{mdoc_fn_pre, NULL}, /* Fn */
{mdoc_ft_pre, NULL}, /* Ft */
@@ -250,6 +252,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
{mdoc_sp_pre, NULL}, /* br */
{mdoc_sp_pre, NULL}, /* sp */
{mdoc__x_pre, mdoc__x_post}, /* %U */
+ {NULL, NULL}, /* Ta */
};
@@ -826,7 +829,6 @@ mdoc_it_block_pre(MDOC_ARGS, enum mdoc_list type, int comp,
struct roffsu su;
nn = n->parent->parent;
- assert(nn->args);
/* XXX: see notes in mdoc_it_pre(). */
@@ -873,7 +875,7 @@ mdoc_it_block_pre(MDOC_ARGS, enum mdoc_list type, int comp,
/* ARGSUSED */
static int
-mdoc_it_body_pre(MDOC_ARGS, enum mdoc_list type)
+mdoc_it_body_pre(MDOC_ARGS, enum mdoc_list type, struct roffsu *width)
{
struct htmlpair tag;
struct roffsu su;
@@ -884,6 +886,12 @@ mdoc_it_body_pre(MDOC_ARGS, enum mdoc_list type)
case (LIST_ohang):
/* FALLTHROUGH */
case (LIST_column):
+ bufcat_su(h, "min-width", width);
+ bufcat_style(h, "clear", "none");
+ if (n->next)
+ bufcat_style(h, "float", "left");
+ PAIR_STYLE_INIT(&tag, h);
+ print_otag(h, TAG_DIV, 1, &tag);
break;
default:
/*
@@ -916,12 +924,6 @@ mdoc_it_head_pre(MDOC_ARGS, enum mdoc_list type, struct roffsu *width)
print_otag(h, TAG_DIV, 0, &tag);
return(1);
case (LIST_column):
- bufcat_su(h, "min-width", width);
- bufcat_style(h, "clear", "none");
- if (n->next && MDOC_HEAD == n->next->type)
- bufcat_style(h, "float", "left");
- PAIR_STYLE_INIT(&tag, h);
- print_otag(h, TAG_DIV, 1, &tag);
break;
default:
bufcat_su(h, "min-width", width);
@@ -1008,7 +1010,8 @@ mdoc_it_pre(MDOC_ARGS)
/* Get width, offset, and compact arguments. */
- for (wp = -1, comp = i = 0; i < (int)bl->args->argc; i++)
+ wp = -1;
+ for (comp = i = 0; bl->args && i < (int)bl->args->argc; i++)
switch (bl->args->argv[i].arg) {
case (MDOC_Column):
wp = i; /* Save for later. */
@@ -1044,25 +1047,21 @@ mdoc_it_pre(MDOC_ARGS)
break;
}
- /* Flip to body/block processing. */
-
- if (MDOC_BODY == n->type)
- return(mdoc_it_body_pre(m, n, h, type));
- if (MDOC_BLOCK == n->type)
- return(mdoc_it_block_pre(m, n, h, type, comp,
- &offs, &width));
-
- /* Override column widths. */
-
- if (LIST_column == type) {
+ if (LIST_column == type && MDOC_BODY == n->type) {
nn = n->parent->child;
- for (i = 0; nn && nn != n; nn = nn->next, i++)
- /* Counter... */ ;
+ for (i = 0; nn && nn != n; nn = nn->next)
+ if (MDOC_BODY == nn->type)
+ i++;
if (i < (int)bl->args->argv[wp].sz)
a2width(bl->args->argv[wp].value[i], &width);
}
- return(mdoc_it_head_pre(m, n, h, type, &width));
+ if (MDOC_HEAD == n->type)
+ return(mdoc_it_head_pre(m, n, h, type, &width));
+ else if (MDOC_BODY == n->type)
+ return(mdoc_it_body_pre(m, n, h, type, &width));
+
+ return(mdoc_it_block_pre(m, n, h, type, comp, &offs, &width));
}
@@ -1244,7 +1243,7 @@ mdoc_d1_pre(MDOC_ARGS)
/* FIXME: D1 shouldn't be literal. */
- SCALE_VS_INIT(&su, INDENT - 1);
+ SCALE_VS_INIT(&su, INDENT - 2);
bufcat_su(h, "margin-left", &su);
PAIR_CLASS_INIT(&tag[0], "lit");
PAIR_STYLE_INIT(&tag[1], h);
@@ -1320,7 +1319,7 @@ mdoc_bd_pre(MDOC_ARGS)
SCALE_VS_INIT(&su, 0);
type = comp = 0;
- for (i = 0; i < (int)bl->args->argc; i++)
+ for (i = 0; bl->args && i < (int)bl->args->argc; i++)
switch (bl->args->argv[i].arg) {
case (MDOC_Offset):
a2offs(bl->args->argv[i].value[0], &su);
@@ -1508,21 +1507,19 @@ mdoc_fa_pre(MDOC_ARGS)
/* ARGSUSED */
+static void
+mdoc_fd_post(MDOC_ARGS)
+{
+
+ print_otag(h, TAG_BR, 0, NULL);
+}
+
+
+/* ARGSUSED */
static int
mdoc_fd_pre(MDOC_ARGS)
{
struct htmlpair tag;
- struct roffsu su;
-
- if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags) {
- if (n->next && MDOC_Fd != n->next->tok) {
- SCALE_VS_INIT(&su, 1);
- bufcat_su(h, "margin-bottom", &su);
- PAIR_STYLE_INIT(&tag, h);
- print_otag(h, TAG_DIV, 1, &tag);
- } else
- print_otag(h, TAG_DIV, 0, NULL);
- }
PAIR_CLASS_INIT(&tag, "macro");
print_otag(h, TAG_SPAN, 1, &tag);
@@ -1562,8 +1559,8 @@ mdoc_ft_pre(MDOC_ARGS)
{
struct htmlpair tag;
- if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags)
- print_otag(h, TAG_DIV, 0, NULL);
+ if (SEC_SYNOPSIS == n->sec && n->prev)
+ print_otag(h, TAG_BR, 0, NULL);
PAIR_CLASS_INIT(&tag, "ftype");
print_otag(h, TAG_SPAN, 1, &tag);
@@ -1583,15 +1580,16 @@ mdoc_fn_pre(MDOC_ARGS)
int sz, i;
struct roffsu su;
- if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags) {
+ /* NB: MDOC_LINE has no effect on this macro! */
+ if (SEC_SYNOPSIS == n->sec) {
SCALE_HS_INIT(&su, INDENT);
bufcat_su(h, "margin-left", &su);
su.scale = -su.scale;
bufcat_su(h, "text-indent", &su);
- if (n->next) {
+ if (n->prev && MDOC_Ft != n->prev->tok) {
SCALE_VS_INIT(&su, 1);
- bufcat_su(h, "margin-bottom", &su);
- }
+ bufcat_su(h, "margin-top", &su);
+ }
PAIR_STYLE_INIT(&tag[0], h);
print_otag(h, TAG_DIV, 1, tag);
}
@@ -1779,25 +1777,39 @@ mdoc_mt_pre(MDOC_ARGS)
static int
mdoc_fo_pre(MDOC_ARGS)
{
- struct htmlpair tag;
- struct roffsu su;
+ struct htmlpair tag;
+ struct roffsu su;
+ struct tag *t;
if (MDOC_BODY == n->type) {
h->flags |= HTML_NOSPACE;
print_text(h, "(");
h->flags |= HTML_NOSPACE;
return(1);
- } else if (MDOC_BLOCK == n->type && n->next) {
+ } else if (MDOC_BLOCK == n->type) {
+ if (SEC_SYNOPSIS != n->sec)
+ return(1);
+ if (NULL == n->prev || MDOC_Ft == n->prev->tok) {
+ print_otag(h, TAG_DIV, 0, NULL);
+ return(1);
+ }
SCALE_VS_INIT(&su, 1);
- bufcat_su(h, "margin-bottom", &su);
+ bufcat_su(h, "margin-top", &su);
PAIR_STYLE_INIT(&tag, h);
print_otag(h, TAG_DIV, 1, &tag);
return(1);
}
+ /* XXX: we drop non-initial arguments as per groff. */
+
+ assert(n->child);
+ assert(n->child->string);
+
PAIR_CLASS_INIT(&tag, "fname");
- print_otag(h, TAG_SPAN, 1, &tag);
- return(1);
+ t = print_otag(h, TAG_SPAN, 1, &tag);
+ print_text(h, n->child->string);
+ print_tagq(h, t);
+ return(0);
}
@@ -1822,31 +1834,16 @@ mdoc_in_pre(MDOC_ARGS)
struct tag *t;
struct htmlpair tag[2];
int i;
- struct roffsu su;
-
- if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags) {
- if (n->next && MDOC_In != n->next->tok) {
- SCALE_VS_INIT(&su, 1);
- bufcat_su(h, "margin-bottom", &su);
- PAIR_STYLE_INIT(&tag[0], h);
- print_otag(h, TAG_DIV, 1, tag);
- } else
- print_otag(h, TAG_DIV, 0, NULL);
- }
-
- /* FIXME: there's a buffer bug in here somewhere. */
PAIR_CLASS_INIT(&tag[0], "includes");
print_otag(h, TAG_SPAN, 1, tag);
- if (SEC_SYNOPSIS == n->sec)
+ if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags)
print_text(h, "#include");
print_text(h, "<");
h->flags |= HTML_NOSPACE;
- /* XXX -- see warning in termp_in_post(). */
-
for (nn = n->child; nn; nn = nn->next) {
PAIR_CLASS_INIT(&tag[0], "link-includes");
i = 1;
@@ -1864,6 +1861,9 @@ mdoc_in_pre(MDOC_ARGS)
h->flags |= HTML_NOSPACE;
print_text(h, ">");
+ if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags)
+ print_otag(h, TAG_BR, 0, NULL);
+
return(0);
}
@@ -1995,8 +1995,7 @@ mdoc_bf_pre(MDOC_ARGS)
else if ( ! strcmp("Li", n->head->child->string))
PAIR_CLASS_INIT(&tag[0], "lit");
} else {
- assert(n->args);
- for (i = 0; i < (int)n->args->argc; i++)
+ for (i = 0; n->args && i < (int)n->args->argc; i++)
switch (n->args->argv[i].arg) {
case (MDOC_Symbolic):
PAIR_CLASS_INIT(&tag[0], "symb");
diff --git a/usr.bin/mandoc/mdoc_macro.c b/usr.bin/mandoc/mdoc_macro.c
index 230dbd2c8ef..bd0ea15fb34 100644
--- a/usr.bin/mandoc/mdoc_macro.c
+++ b/usr.bin/mandoc/mdoc_macro.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_macro.c,v 1.45 2010/06/06 18:08:41 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.46 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -40,13 +40,13 @@ static int in_line_eoln(MACRO_PROT_ARGS);
static int in_line_argn(MACRO_PROT_ARGS);
static int in_line(MACRO_PROT_ARGS);
static int obsolete(MACRO_PROT_ARGS);
+static int phrase_ta(MACRO_PROT_ARGS);
static int append_delims(struct mdoc *,
int, int *, char *);
static enum mdoct lookup(enum mdoct, const char *);
static enum mdoct lookup_raw(const char *);
-static int phrase(struct mdoc *, int, int,
- char *, enum margserr);
+static int phrase(struct mdoc *, int, int, char *);
static enum mdoct rew_alt(enum mdoct);
static int rew_dobreak(enum mdoct,
const struct mdoc_node *);
@@ -182,6 +182,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ in_line_eoln, 0 }, /* br */
{ in_line_eoln, 0 }, /* sp */
{ in_line_eoln, 0 }, /* %U */
+ { phrase_ta, MDOC_CALLABLE | MDOC_PARSED }, /* Ta */
};
const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
@@ -192,7 +193,7 @@ swarn(struct mdoc *mdoc, enum mdoc_type type,
int line, int pos, const struct mdoc_node *p)
{
const char *n, *t, *tt;
- int rc;
+ enum mandocerr ec;
n = t = "<root>";
tt = "block";
@@ -225,11 +226,12 @@ swarn(struct mdoc *mdoc, enum mdoc_type type,
break;
}
- rc = mdoc_vmsg(mdoc, MANDOCERR_SCOPE, line, pos,
- "%s scope breaks %s of %s", tt, t, n);
+ ec = (MDOC_IGN_SCOPE & mdoc->pflags) ?
+ MANDOCERR_SCOPE : MANDOCERR_SYNTSCOPE;
- /* FIXME: logic should be in driver. */
- return(MDOC_IGN_SCOPE & mdoc->pflags ? rc : 0);
+ return(mdoc_vmsg(mdoc, ec, line, pos,
+ "%s scope breaks %s of %s",
+ tt, t, n));
}
@@ -928,6 +930,7 @@ blk_full(MACRO_PROT_ARGS)
struct mdoc_node *head; /* save of head macro */
struct mdoc_node *body; /* save of body macro */
struct mdoc_node *n;
+ enum mdoc_type mtt;
enum mdoct ntok;
enum margserr ac, lac;
enum margverr av;
@@ -996,24 +999,38 @@ blk_full(MACRO_PROT_ARGS)
for ( ; ; ) {
la = *pos;
- lac = ac;
+ /* Initialise last-phrase-type with ARGS_PEND. */
+ lac = ARGS_ERROR == ac ? ARGS_PEND : ac;
ac = mdoc_args(m, line, pos, buf, tok, &p);
if (ARGS_ERROR == ac)
return(0);
- if (ARGS_EOLN == ac)
- break;
- if (ARGS_PEND == ac) {
- if (ARGS_PPHRASE == lac)
- ac = ARGS_PPHRASE;
- else
- ac = ARGS_PHRASE;
+ if (ARGS_EOLN == ac) {
+ if (ARGS_PPHRASE != lac && ARGS_PHRASE != lac)
+ break;
+ /*
+ * This is necessary: if the last token on a
+ * line is a `Ta' or tab, then we'll get
+ * ARGS_EOLN, so we must be smart enough to
+ * reopen our scope if the last parse was a
+ * phrase or partial phrase.
+ */
+ if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ return(0);
+ if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ return(0);
+ body = m->last;
+ break;
}
- /* Don't emit leading punct. for phrases. */
+ /*
+ * Emit leading punctuation (i.e., punctuation before
+ * the MDOC_HEAD) for non-phrase types.
+ */
if (NULL == head &&
+ ARGS_PEND != ac &&
ARGS_PHRASE != ac &&
ARGS_PPHRASE != ac &&
ARGS_QWORD != ac &&
@@ -1023,24 +1040,47 @@ blk_full(MACRO_PROT_ARGS)
continue;
}
- /* Always re-open head for phrases. */
+ /* Open a head if one hasn't been opened. */
- if (NULL == head ||
- ARGS_PHRASE == ac ||
- ARGS_PPHRASE == ac) {
+ if (NULL == head) {
if ( ! mdoc_head_alloc(m, line, ppos, tok))
return(0);
head = m->last;
}
- if (ARGS_PHRASE == ac || ARGS_PPHRASE == ac) {
+ if (ARGS_PHRASE == ac ||
+ ARGS_PEND == ac ||
+ ARGS_PPHRASE == ac) {
+ /*
+ * If we haven't opened a body yet, rewind the
+ * head; if we have, rewind that instead.
+ */
+
+ mtt = body ? MDOC_BODY : MDOC_HEAD;
+ if ( ! rew_sub(mtt, m, tok, line, ppos))
+ return(0);
+
+ /* Then allocate our body context. */
+
+ if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ return(0);
+ body = m->last;
+
+ /*
+ * Process phrases: set whether we're in a
+ * partial-phrase (this effects line handling)
+ * then call down into the phrase parser.
+ */
+
if (ARGS_PPHRASE == ac)
m->flags |= MDOC_PPHRASE;
- if ( ! phrase(m, line, la, buf, ac))
+ if (ARGS_PEND == ac && ARGS_PPHRASE == lac)
+ m->flags |= MDOC_PPHRASE;
+
+ if ( ! phrase(m, line, la, buf))
return(0);
+
m->flags &= ~MDOC_PPHRASE;
- if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
- return(0);
continue;
}
@@ -1069,7 +1109,7 @@ blk_full(MACRO_PROT_ARGS)
/* If we've already opened our body, exit now. */
if (NULL != body)
- return(1);
+ goto out;
/*
* If there is an open (i.e., unvalidated) sub-block requiring
@@ -1093,6 +1133,16 @@ blk_full(MACRO_PROT_ARGS)
if ( ! mdoc_body_alloc(m, line, ppos, tok))
return(0);
+out:
+ if ( ! (MDOC_FREECOL & m->flags))
+ return(1);
+
+ if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ return(0);
+ if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
+ return(0);
+
+ m->flags &= ~MDOC_FREECOL;
return(1);
}
@@ -1582,26 +1632,24 @@ obsolete(MACRO_PROT_ARGS)
* macro is encountered.
*/
static int
-phrase(struct mdoc *m, int line, int ppos, char *buf, enum margserr ac)
+phrase(struct mdoc *m, int line, int ppos, char *buf)
{
int la, pos;
- enum margserr aac;
+ enum margserr ac;
enum mdoct ntok;
char *p;
- assert(ARGS_PHRASE == ac || ARGS_PPHRASE == ac);
-
for (pos = ppos; ; ) {
la = pos;
- aac = mdoc_zargs(m, line, &pos, buf, 0, &p);
+ ac = mdoc_zargs(m, line, &pos, buf, 0, &p);
- if (ARGS_ERROR == aac)
+ if (ARGS_ERROR == ac)
return(0);
- if (ARGS_EOLN == aac)
+ if (ARGS_EOLN == ac)
break;
- ntok = ARGS_QWORD == aac ? MDOC_MAX : lookup_raw(p);
+ ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
if (MDOC_MAX == ntok) {
if ( ! mdoc_word_alloc(m, line, la, p))
@@ -1618,3 +1666,46 @@ phrase(struct mdoc *m, int line, int ppos, char *buf, enum margserr ac)
}
+/* ARGSUSED */
+static int
+phrase_ta(MACRO_PROT_ARGS)
+{
+ int la;
+ enum mdoct ntok;
+ enum margserr ac;
+ char *p;
+
+ /*
+ * FIXME: this is overly restrictive: if the `Ta' is unexpected,
+ * it should simply error out with ARGSLOST.
+ */
+
+ if ( ! rew_sub(MDOC_BODY, m, MDOC_It, line, ppos))
+ return(0);
+ if ( ! mdoc_body_alloc(m, line, ppos, MDOC_It))
+ return(0);
+
+ for (;;) {
+ la = *pos;
+ ac = mdoc_zargs(m, line, pos, buf, 0, &p);
+
+ if (ARGS_ERROR == ac)
+ return(0);
+ if (ARGS_EOLN == ac)
+ break;
+
+ ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
+
+ if (MDOC_MAX == ntok) {
+ if ( ! mdoc_word_alloc(m, line, la, p))
+ return(0);
+ continue;
+ }
+
+ if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
+ return(0);
+ return(append_delims(m, line, pos, buf));
+ }
+
+ return(1);
+}
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index 43d2a3d3593..733edc54b34 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.84 2010/06/06 18:08:41 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.85 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -78,7 +78,6 @@ static void termp_dq_post(DECL_ARGS);
static void termp_fd_post(DECL_ARGS);
static void termp_fn_post(DECL_ARGS);
static void termp_fo_post(DECL_ARGS);
-static void termp_ft_post(DECL_ARGS);
static void termp_in_post(DECL_ARGS);
static void termp_it_post(DECL_ARGS);
static void termp_lb_post(DECL_ARGS);
@@ -162,7 +161,7 @@ static const struct termact termacts[MDOC_MAX] = {
{ termp_bold_pre, termp_fd_post }, /* Fd */
{ termp_fl_pre, NULL }, /* Fl */
{ termp_fn_pre, termp_fn_post }, /* Fn */
- { termp_ft_pre, termp_ft_post }, /* Ft */
+ { termp_ft_pre, NULL }, /* Ft */
{ termp_bold_pre, NULL }, /* Ic */
{ termp_in_pre, termp_in_post }, /* In */
{ termp_li_pre, NULL }, /* Li */
@@ -256,6 +255,7 @@ static const struct termact termacts[MDOC_MAX] = {
{ termp_sp_pre, NULL }, /* br */
{ termp_sp_pre, NULL }, /* sp */
{ termp_under_pre, termp____post }, /* %U */
+ { NULL, NULL }, /* Ta */
};
@@ -696,7 +696,7 @@ termp_it_pre(DECL_ARGS)
switch (type) {
case (LIST_column):
- if (MDOC_BODY == n->type)
+ if (MDOC_HEAD == n->type)
break;
/*
* Imitate groff's column handling:
@@ -711,8 +711,13 @@ termp_it_pre(DECL_ARGS)
/* LINTED */
dcol = ncols < 5 ? 4 : ncols == 5 ? 3 : 1;
+ /*
+ * Calculate the offset by applying all prior MDOC_BODY,
+ * so we stop at the MDOC_HEAD (NULL == nn->prev).
+ */
+
for (i = 0, nn = n->prev;
- nn && i < (int)ncols;
+ nn->prev && i < (int)ncols;
nn = nn->prev, i++)
offset += dcol + a2width
(&bl->args->argv[vals[2]], i);
@@ -865,15 +870,18 @@ termp_it_pre(DECL_ARGS)
p->flags |= TERMP_DANGLE;
break;
case (LIST_column):
- if (MDOC_HEAD == n->type) {
- assert(n->next);
- if (MDOC_BODY == n->next->type)
- p->flags &= ~TERMP_NOBREAK;
- else
- p->flags |= TERMP_NOBREAK;
- if (n->prev)
- p->flags |= TERMP_NOLPAD;
- }
+ if (MDOC_HEAD == n->type)
+ break;
+
+ if (NULL == n->next)
+ p->flags &= ~TERMP_NOBREAK;
+ else
+ p->flags |= TERMP_NOBREAK;
+
+ assert(n->prev);
+ if (MDOC_BODY == n->prev->type)
+ p->flags |= TERMP_NOLPAD;
+
break;
case (LIST_diag):
if (MDOC_HEAD == n->type)
@@ -925,9 +933,9 @@ termp_it_pre(DECL_ARGS)
* XXX - this behaviour is not documented: the
* right-most column is filled to the right margin.
*/
- if (MDOC_HEAD == n->type &&
- MDOC_BODY == n->next->type &&
- p->rmargin < p->maxrmargin)
+ if (MDOC_HEAD == n->type)
+ break;
+ if (NULL == n->next && p->rmargin < p->maxrmargin)
p->rmargin = p->maxrmargin;
break;
default:
@@ -981,7 +989,7 @@ termp_it_pre(DECL_ARGS)
return(0);
break;
case (LIST_column):
- if (MDOC_BODY == n->type)
+ if (MDOC_HEAD == n->type)
return(0);
break;
default:
@@ -1013,7 +1021,7 @@ termp_it_post(DECL_ARGS)
term_newln(p);
break;
case (LIST_column):
- if (MDOC_HEAD == n->type)
+ if (MDOC_BODY == n->type)
term_flushln(p);
break;
default:
@@ -1345,12 +1353,7 @@ static void
termp_fd_post(DECL_ARGS)
{
- if (n->sec != SEC_SYNOPSIS || ! (MDOC_LINE & n->flags))
- return;
-
term_newln(p);
- if (n->next && MDOC_Fd != n->next->tok)
- term_vspace(p);
}
@@ -1503,9 +1506,9 @@ static int
termp_ft_pre(DECL_ARGS)
{
- if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags)
- if (n->prev && MDOC_Fo == n->prev->tok)
- term_vspace(p);
+ /* NB: MDOC_LINE does not effect this! */
+ if (SEC_SYNOPSIS == n->sec && n->prev)
+ term_vspace(p);
term_fontpush(p, TERMFONT_UNDER);
return(1);
@@ -1513,21 +1516,19 @@ termp_ft_pre(DECL_ARGS)
/* ARGSUSED */
-static void
-termp_ft_post(DECL_ARGS)
-{
-
- if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags)
- term_newln(p);
-}
-
-
-/* ARGSUSED */
static int
termp_fn_pre(DECL_ARGS)
{
const struct mdoc_node *nn;
+ /* NB: MDOC_LINE has no effect on this macro! */
+ if (SEC_SYNOPSIS == n->sec) {
+ if (n->prev && MDOC_Ft == n->prev->tok)
+ term_newln(p);
+ else if (n->prev)
+ term_vspace(p);
+ }
+
term_fontpush(p, TERMFONT_BOLD);
term_word(p, n->child->string);
term_fontpop(p);
@@ -1558,8 +1559,9 @@ static void
termp_fn_post(DECL_ARGS)
{
- if (n->sec == SEC_SYNOPSIS && n->next && MDOC_LINE & n->flags)
- term_vspace(p);
+ /* NB: MDOC_LINE has no effect on this macro! */
+ if (SEC_SYNOPSIS == n->sec)
+ term_newln(p);
}
@@ -1839,11 +1841,18 @@ static int
termp_in_pre(DECL_ARGS)
{
- term_fontpush(p, TERMFONT_BOLD);
- if (SEC_SYNOPSIS == n->sec)
+ if (SEC_SYNOPSIS == n->sec && n->prev && MDOC_In != n->prev->tok)
+ term_vspace(p);
+
+ if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags) {
+ term_fontpush(p, TERMFONT_BOLD);
term_word(p, "#include");
+ term_word(p, "<");
+ } else {
+ term_word(p, "<");
+ term_fontpush(p, TERMFONT_UNDER);
+ }
- term_word(p, "<");
p->flags |= TERMP_NOSPACE;
return(1);
}
@@ -1854,23 +1863,16 @@ static void
termp_in_post(DECL_ARGS)
{
- term_fontpush(p, TERMFONT_BOLD);
+ if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags)
+ term_fontpush(p, TERMFONT_BOLD);
+
p->flags |= TERMP_NOSPACE;
term_word(p, ">");
- term_fontpop(p);
-
- if (SEC_SYNOPSIS != n->sec && ! (MDOC_LINE & n->flags))
- return;
- term_newln(p);
- /*
- * XXX Not entirely correct. If `.In foo bar' is specified in
- * the SYNOPSIS section, then it produces a single break after
- * the <foo>; mandoc asserts a vertical space. Since this
- * construction is rarely used, I think it's fine.
- */
- if (n->next && MDOC_In != n->next->tok)
- term_vspace(p);
+ if (SEC_SYNOPSIS == n->sec && MDOC_LINE & n->flags) {
+ term_fontpop(p);
+ term_newln(p);
+ }
}
@@ -1979,23 +1981,29 @@ termp_pq_post(DECL_ARGS)
static int
termp_fo_pre(DECL_ARGS)
{
- const struct mdoc_node *nn;
- if (MDOC_BODY == n->type) {
+ if (MDOC_BLOCK == n->type) {
+ /* NB: MDOC_LINE has no effect on this macro! */
+ if (SEC_SYNOPSIS != n->sec)
+ return(1);
+ if (n->prev && MDOC_Ft == n->prev->tok)
+ term_newln(p);
+ else if (n->prev)
+ term_vspace(p);
+ return(1);
+ } else if (MDOC_BODY == n->type) {
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
p->flags |= TERMP_NOSPACE;
return(1);
- } else if (MDOC_HEAD != n->type)
- return(1);
+ }
- term_fontpush(p, TERMFONT_BOLD);
- for (nn = n->child; nn; nn = nn->next) {
- assert(MDOC_TEXT == nn->type);
- term_word(p, nn->string);
- }
- term_fontpop(p);
+ /* XXX: we drop non-initial arguments as per groff. */
+ assert(n->child);
+ assert(n->child->string);
+ term_fontpush(p, TERMFONT_BOLD);
+ term_word(p, n->child->string);
return(0);
}
@@ -2005,13 +2013,18 @@ static void
termp_fo_post(DECL_ARGS)
{
- if (MDOC_BODY != n->type)
- return;
- p->flags |= TERMP_NOSPACE;
- term_word(p, ")");
- p->flags |= TERMP_NOSPACE;
- term_word(p, ";");
- term_newln(p);
+ if (MDOC_BLOCK == n->type) {
+ /* NB: MDOC_LINE has no effect on this macro! */
+ if (SEC_SYNOPSIS == n->sec)
+ term_newln(p);
+ } else if (MDOC_BODY == n->type) {
+ p->flags |= TERMP_NOSPACE;
+ term_word(p, ")");
+ if (SEC_SYNOPSIS == n->sec) {
+ p->flags |= TERMP_NOSPACE;
+ term_word(p, ";");
+ }
+ }
}
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index 459da6d17cf..7d336d05567 100644
--- a/usr.bin/mandoc/mdoc_validate.c
+++ b/usr.bin/mandoc/mdoc_validate.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_validate.c,v 1.59 2010/06/06 18:08:41 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.60 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -30,7 +30,7 @@
/* FIXME: .Bl -diag can't have non-text children in HEAD. */
/* TODO: ignoring Pp (it's superfluous in some invocations). */
-#define PRE_ARGS struct mdoc *mdoc, const struct mdoc_node *n
+#define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n
#define POST_ARGS struct mdoc *mdoc
typedef int (*v_pre)(PRE_ARGS);
@@ -79,6 +79,7 @@ static int post_at(POST_ARGS);
static int post_bf(POST_ARGS);
static int post_bl(POST_ARGS);
static int post_bl_head(POST_ARGS);
+static int post_dt(POST_ARGS);
static int post_it(POST_ARGS);
static int post_lb(POST_ARGS);
static int post_nm(POST_ARGS);
@@ -109,6 +110,7 @@ static v_post posts_bf[] = { hwarn_le1, post_bf, NULL };
static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL };
static v_post posts_bool[] = { eerr_eq1, ebool, NULL };
static v_post posts_eoln[] = { post_eoln, NULL };
+static v_post posts_dt[] = { post_dt, NULL };
static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
static v_post posts_it[] = { post_it, NULL };
static v_post posts_lb[] = { eerr_eq1, post_lb, NULL };
@@ -143,7 +145,7 @@ static v_pre pres_ss[] = { pre_ss, NULL };
const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Ap */
{ pres_dd, posts_text }, /* Dd */
- { pres_dt, NULL }, /* Dt */
+ { pres_dt, posts_dt }, /* Dt */
{ pres_os, NULL }, /* Os */
{ pres_sh, posts_sh }, /* Sh */
{ pres_ss, posts_ss }, /* Ss */
@@ -262,11 +264,12 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, posts_notext }, /* br */
{ NULL, posts_sp }, /* sp */
{ NULL, posts_text1 }, /* %U */
+ { NULL, NULL }, /* Ta */
};
int
-mdoc_valid_pre(struct mdoc *mdoc, const struct mdoc_node *n)
+mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n)
{
v_pre *p;
int line, pos;
@@ -528,79 +531,117 @@ pre_display(PRE_ARGS)
static int
pre_bl(PRE_ARGS)
{
- int pos, type, width, offset;
-
- if (MDOC_BLOCK != n->type)
+ int i, width, offs, cmpt, dupl;
+ enum mdoc_list lt;
+
+ if (MDOC_BLOCK != n->type) {
+ assert(n->parent);
+ assert(MDOC_BLOCK == n->parent->type);
+ assert(MDOC_Bl == n->parent->tok);
+ assert(LIST__NONE != n->parent->data.list);
+ n->data.list = n->parent->data.list;
return(1);
- if (NULL == n->args) {
- mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE);
- return(0);
}
- /* Make sure that only one type of list is specified. */
+ /*
+ * First figure out which kind of list to use: bind ourselves to
+ * the first mentioned list type and warn about any remaining
+ * ones. If we find no list type, we default to LIST_item.
+ */
- type = offset = width = -1;
+ assert(LIST__NONE == n->data.list);
+ offs = width = cmpt = -1;
/* LINTED */
- for (pos = 0; pos < (int)n->args->argc; pos++)
- switch (n->args->argv[pos].arg) {
+ for (i = 0; n->args && i < (int)n->args->argc; i++) {
+ lt = LIST__NONE;
+ dupl = 0;
+ switch (n->args->argv[i].arg) {
+ /* Set list types. */
case (MDOC_Bullet):
- /* FALLTHROUGH */
+ lt = LIST_bullet;
+ break;
case (MDOC_Dash):
- /* FALLTHROUGH */
+ lt = LIST_dash;
+ break;
case (MDOC_Enum):
- /* FALLTHROUGH */
+ lt = LIST_enum;
+ break;
case (MDOC_Hyphen):
- /* FALLTHROUGH */
+ lt = LIST_hyphen;
+ break;
case (MDOC_Item):
- /* FALLTHROUGH */
+ lt = LIST_item;
+ break;
case (MDOC_Tag):
- /* FALLTHROUGH */
+ lt = LIST_tag;
+ break;
case (MDOC_Diag):
- /* FALLTHROUGH */
+ lt = LIST_diag;
+ break;
case (MDOC_Hang):
- /* FALLTHROUGH */
+ lt = LIST_hang;
+ break;
case (MDOC_Ohang):
- /* FALLTHROUGH */
+ lt = LIST_ohang;
+ break;
case (MDOC_Inset):
- /* FALLTHROUGH */
+ lt = LIST_inset;
+ break;
case (MDOC_Column):
- if (type < 0) {
- type = n->args->argv[pos].arg;
- break;
- }
- if (mdoc_nmsg(mdoc, n, MANDOCERR_LISTREP))
- break;
- return(0);
+ lt = LIST_column;
+ break;
+ /* Set list arguments. */
case (MDOC_Compact):
- if (type >= 0)
- break;
- if (mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST))
- break;
- return(0);
+ if (cmpt >= 0)
+ dupl++;
+ cmpt = i;
+ break;
case (MDOC_Width):
if (width >= 0)
- if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP))
- return(0);
- if (type < 0 && ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST))
- return(0);
- width = n->args->argv[pos].arg;
+ dupl++;
+ width = i;
break;
case (MDOC_Offset):
- if (offset >= 0)
- if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP))
- return(0);
- if (type < 0 && ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST))
- return(0);
- offset = n->args->argv[pos].arg;
- break;
- default:
+ if (offs >= 0)
+ dupl++;
+ offs = i;
break;
}
- if (type < 0) {
- mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE);
- return(0);
+ /* Check: duplicate auxiliary arguments. */
+
+ if (dupl)
+ if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP))
+ return(0);
+
+ /* Check: multiple list types. */
+
+ if (LIST__NONE != lt && n->data.list != LIST__NONE)
+ if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTREP))
+ return(0);
+
+ /* Assign list type. */
+
+ if (LIST__NONE != lt && n->data.list == LIST__NONE)
+ n->data.list = lt;
+
+ /* The list type should come first. */
+
+ if (n->data.list == LIST__NONE)
+ if (width >= 0 || offs >= 0 || cmpt >= 0)
+ if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST))
+ return(0);
+
+ continue;
+ }
+
+ /* Allow lists to default to LIST_item. */
+
+ if (LIST__NONE == n->data.list) {
+ if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE))
+ return(0);
+ n->data.list = LIST_item;
}
/*
@@ -609,23 +650,27 @@ pre_bl(PRE_ARGS)
* and must also be warned.
*/
- switch (type) {
- case (MDOC_Tag):
- if (width < 0 && ! mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG))
- return(0);
- break;
- case (MDOC_Column):
+ switch (n->data.list) {
+ case (LIST_tag):
+ if (width >= 0)
+ break;
+ if (mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG))
+ break;
+ return(0);
+ case (LIST_column):
/* FALLTHROUGH */
- case (MDOC_Diag):
+ case (LIST_diag):
/* FALLTHROUGH */
- case (MDOC_Ohang):
+ case (LIST_ohang):
/* FALLTHROUGH */
- case (MDOC_Inset):
+ case (LIST_inset):
/* FALLTHROUGH */
- case (MDOC_Item):
- if (width >= 0 && ! mdoc_nmsg(mdoc, n, MANDOCERR_WIDTHARG))
- return(0);
- break;
+ case (LIST_item):
+ if (width < 0)
+ break;
+ if (mdoc_nmsg(mdoc, n, MANDOCERR_WIDTHARG))
+ break;
+ return(0);
default:
break;
}
@@ -734,10 +779,27 @@ pre_rv(PRE_ARGS)
static int
-pre_dt(PRE_ARGS)
+post_dt(POST_ARGS)
{
+ const struct mdoc_node *nn;
+ const char *p;
+
+ if (NULL != (nn = mdoc->last->child))
+ for (p = nn->string; *p; p++) {
+ if (toupper((u_char)*p) == *p)
+ continue;
+ if ( ! mdoc_nmsg(mdoc, nn, MANDOCERR_UPPERCASE))
+ return(0);
+ break;
+ }
+
+ return(1);
+}
- /* FIXME: make sure is capitalised. */
+
+static int
+pre_dt(PRE_ARGS)
+{
if (0 == mdoc->meta.date || mdoc->meta.os)
if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO))
@@ -905,71 +967,37 @@ post_an(POST_ARGS)
static int
post_it(POST_ARGS)
{
- int type, i, cols;
+ int i, cols, rc;
+ enum mdoc_list lt;
struct mdoc_node *n, *c;
+ enum mandocerr er;
if (MDOC_BLOCK != mdoc->last->type)
return(1);
n = mdoc->last->parent->parent;
- if (NULL == n->args) {
- mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE);
- return(0);
- }
-
- /* Some types require block-head, some not. */
-
- /* LINTED */
- for (cols = type = -1, i = 0; -1 == type &&
- i < (int)n->args->argc; i++)
- switch (n->args->argv[i].arg) {
- case (MDOC_Tag):
- /* FALLTHROUGH */
- case (MDOC_Diag):
- /* FALLTHROUGH */
- case (MDOC_Hang):
- /* FALLTHROUGH */
- case (MDOC_Ohang):
- /* FALLTHROUGH */
- case (MDOC_Inset):
- /* FALLTHROUGH */
- case (MDOC_Bullet):
- /* FALLTHROUGH */
- case (MDOC_Dash):
- /* FALLTHROUGH */
- case (MDOC_Enum):
- /* FALLTHROUGH */
- case (MDOC_Hyphen):
- /* FALLTHROUGH */
- case (MDOC_Item):
- type = n->args->argv[i].arg;
- break;
- case (MDOC_Column):
- type = n->args->argv[i].arg;
- cols = (int)n->args->argv[i].sz;
- break;
- default:
- break;
- }
+ lt = n->data.list;
- if (-1 == type) {
+ if (LIST__NONE == lt) {
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE);
return(0);
}
- switch (type) {
- case (MDOC_Tag):
- if (NULL == mdoc->last->head->child)
- if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS))
- return(0);
+ switch (lt) {
+ case (LIST_tag):
+ if (mdoc->last->head->child)
+ break;
+ /* FIXME: give this a dummy value. */
+ if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS))
+ return(0);
break;
- case (MDOC_Hang):
+ case (LIST_hang):
/* FALLTHROUGH */
- case (MDOC_Ohang):
+ case (LIST_ohang):
/* FALLTHROUGH */
- case (MDOC_Inset):
+ case (LIST_inset):
/* FALLTHROUGH */
- case (MDOC_Diag):
+ case (LIST_diag):
if (NULL == mdoc->last->head->child)
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS))
return(0);
@@ -977,15 +1005,15 @@ post_it(POST_ARGS)
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY))
return(0);
break;
- case (MDOC_Bullet):
+ case (LIST_bullet):
/* FALLTHROUGH */
- case (MDOC_Dash):
+ case (LIST_dash):
/* FALLTHROUGH */
- case (MDOC_Enum):
+ case (LIST_enum):
/* FALLTHROUGH */
- case (MDOC_Hyphen):
+ case (LIST_hyphen):
/* FALLTHROUGH */
- case (MDOC_Item):
+ case (LIST_item):
if (mdoc->last->head->child)
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST))
return(0);
@@ -993,32 +1021,36 @@ post_it(POST_ARGS)
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY))
return(0);
break;
- case (MDOC_Column):
- if (NULL == mdoc->last->head->child)
- if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS))
- return(0);
- if (mdoc->last->body->child)
- if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BODYLOST))
- return(0);
- c = mdoc->last->child;
- for (i = 0; c && MDOC_HEAD == c->type; c = c->next)
- i++;
-
- if (i < cols) {
- if ( ! mdoc_vmsg(mdoc, MANDOCERR_ARGCOUNT,
- mdoc->last->line,
- mdoc->last->pos,
- "columns == %d (have %d)",
- cols, i))
+ case (LIST_column):
+ cols = -1;
+ for (i = 0; i < (int)n->args->argc; i++)
+ if (MDOC_Column == n->args->argv[i].arg) {
+ cols = (int)n->args->argv[i].sz;
+ break;
+ }
+
+ assert(-1 != cols);
+ assert(NULL == mdoc->last->head->child);
+
+ if (NULL == mdoc->last->body->child)
+ if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY))
return(0);
+
+ for (i = 0, c = mdoc->last->child; c; c = c->next)
+ if (MDOC_BODY == c->type)
+ i++;
+
+ if (i < cols)
+ er = MANDOCERR_ARGCOUNT;
+ else if (i == cols || i == cols + 1)
break;
- } else if (i == cols || i == cols + 1)
- break;
+ else
+ er = MANDOCERR_SYNTARGCOUNT;
- mdoc_vmsg(mdoc, MANDOCERR_SYNTARGCOUNT,
+ rc = mdoc_vmsg(mdoc, er,
mdoc->last->line, mdoc->last->pos,
"columns == %d (have %d)", cols, i);
- return(0);
+ return(rc);
default:
break;
}
@@ -1030,20 +1062,23 @@ post_it(POST_ARGS)
static int
post_bl_head(POST_ARGS)
{
- int i;
- const struct mdoc_node *n;
- const struct mdoc_argv *a;
+ int i;
+ struct mdoc_node *n;
+ assert(mdoc->last->parent);
n = mdoc->last->parent;
- assert(n->args);
- for (i = 0; i < (int)n->args->argc; i++) {
- a = &n->args->argv[i];
- if (a->arg == MDOC_Column) {
- if (a->sz && mdoc->last->nchild)
- return(mdoc_nmsg(mdoc, n, MANDOCERR_COLUMNS));
- return(1);
+ if (LIST_column == n->data.list) {
+ for (i = 0; i < (int)n->args->argc; i++)
+ if (MDOC_Column == n->args->argv[i].arg)
+ break;
+ assert(i < (int)n->args->argc);
+
+ if (n->args->argv[i].sz && mdoc->last->nchild) {
+ mdoc_nmsg(mdoc, n, MANDOCERR_COLUMNS);
+ return(0);
}
+ return(1);
}
if (0 == (i = mdoc->last->nchild))
diff --git a/usr.bin/mandoc/roff.7 b/usr.bin/mandoc/roff.7
index a284ac105b5..65fca6dbb95 100644
--- a/usr.bin/mandoc/roff.7
+++ b/usr.bin/mandoc/roff.7
@@ -1,4 +1,4 @@
-.\" $Id: roff.7,v 1.3 2010/05/25 00:02:34 schwarze Exp $
+.\" $Id: roff.7,v 1.4 2010/06/06 20:30:08 schwarze Exp $
.\"
.\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -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: May 25 2010 $
+.Dd $Mdocdate: June 6 2010 $
.Dt ROFF 7
.Os
.Sh NAME
@@ -207,7 +207,9 @@ macro is discarded.
Furthermore, if an explicit closing sequence
.Sq \e}
is specified in a free-form line, the entire line is accepted within the
-scope of the prior macro, not only the text preceding the close.
+scope of the prior macro, not only the text preceding the close, with the
+.Sq \e}
+collapsing into a zero-width space.
.Ss \&ig
Ignore input.
Accepts the following syntax:
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 62f17651a63..1169b559bad 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.3 2010/06/06 18:08:41 schwarze Exp $ */
+/* $Id: roff.c,v 1.4 2010/06/06 20:30:08 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -666,10 +666,8 @@ roff_cond_text(ROFF_ARGS)
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
}
- if (ep > st && '\\' != *(ep - 1)) {
- ep = '\0';
+ if (ep == st || (ep > st && '\\' != *(ep - 1)))
roffnode_pop(r);
- }
roffnode_cleanscope(r);
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);