-.\" $Id: mdoc.3,v 1.39 2010/05/25 21:46:48 kristaps Exp $
+.\" $Id: mdoc.3,v 1.45 2010/06/29 19:20:38 schwarze Exp $
.\"
.\" Copyright (c) 2009-2010 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: May 25 2010 $
+.Dd $Mdocdate: June 29 2010 $
.Dt MDOC 3
.Os
.Sh NAME
.Nd mdoc macro compiler library
.Sh SYNOPSIS
.In mandoc.h
+.In regs.h
.In mdoc.h
.Vt extern const char * const * mdoc_macronames;
.Vt extern const char * const * mdoc_argnames;
.Ft "struct mdoc *"
-.Fn mdoc_alloc "void *data" "int pflags" "mandocmsg msgs"
+.Fo mdoc_alloc
+.Fa "struct regset *regs"
+.Fa "void *data"
+.Fa "int pflags"
+.Fa "mandocmsg msgs"
+.Fc
.Ft int
.Fn mdoc_endparse "struct mdoc *mdoc"
.Ft void
.Ft "const struct mdoc_node *"
.Fn mdoc_node "const struct mdoc *mdoc"
.Ft int
-.Fn mdoc_parseln "struct mdoc *mdoc" "int line" "char *buf"
+.Fo mdoc_parseln
+.Fa "struct mdoc *mdoc"
+.Fa "int line"
+.Fa "char *buf"
+.Fc
.Ft int
.Fn mdoc_reset "struct mdoc *mdoc"
.Sh DESCRIPTION
Allocates a parsing structure.
The
.Fa data
-pointer is passed to callbacks in
-.Fa cb ,
-which are documented further in the header file.
+pointer is passed to
+.Fa msgs .
The
.Fa pflags
arguments are defined in
fields), its position in the tree (the
.Va parent ,
.Va child ,
+.Va nchild ,
.Va next
and
.Va prev
-fields) and some type-specific data.
+fields) and some type-specific data, in particular, for nodes generated
+from macros, the generating macro in the
+.Va tok
+field.
.Pp
The tree itself is arranged according to the following normal form,
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
-\(<- mnode+
+\(<- mnode*
.It BODY
-\(<- mnode+
+\(<- mnode* [ENDBODY mnode*]
.It TAIL
-\(<- mnode+
+\(<- mnode*
.It TEXT
\(<- [[:printable:],0x1e]*
.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.
+.Ss Badly nested blocks
+A special kind of node is available to end the formatting
+associated with a given block before the physical end of that block.
+Such an ENDBODY node has a non-null
+.Va end
+field, is of the BODY
+.Va type ,
+has the same
+.Va tok
+as the BLOCK it is ending, and has a
+.Va pending
+field pointing to that BLOCK's BODY node.
+It is an indirect child of that BODY node
+and has no children of its own.
+.Pp
+An ENDBODY node is generated when a block ends while one of its child
+blocks is still open, like in the following example:
+.Bd -literal -offset indent
+\&.Ao ao
+\&.Bo bo ac
+\&.Ac bc
+\&.Bc end
+.Ed
+.Pp
+This example results in the following block structure:
+.Bd -literal -offset indent
+BLOCK Ao
+ HEAD Ao
+ BODY Ao
+ TEXT ao
+ BLOCK Bo, pending -> Ao
+ HEAD Bo
+ BODY Bo
+ TEXT bo
+ TEXT ac
+ ENDBODY Ao, pending -> Ao
+ TEXT bc
+TEXT end
+.Ed
+.Pp
+Here, the formatting of the Ao block extends from TEXT ao to TEXT ac,
+while the formatting of the Bo block extends from TEXT bo to TEXT bc,
+rendering like this in
+.Fl T Ns Cm ascii
+mode:
+.Dl <ao [bo ac> bc] end
+Support for badly nested blocks is only provided for backward
+compatibility with some older
+.Xr mdoc 7
+implementations.
+Using them in new code is stronly discouraged:
+Some frontends, in particular
+.Fl T Ns Cm html ,
+are unable to render them in any meaningful way,
+many other
+.Xr mdoc 7
+implementations do not support them, and even for those that do,
+the behaviour is not well-defined, in particular when using multiple
+levels of badly nested blocks.
.Sh EXAMPLES
The following example reads lines from stdin and parses them, operating
on the finished parse tree with
.Fn parsed .
This example does not error-check nor free memory upon failure.
.Bd -literal -offset indent
+struct regset regs;
struct mdoc *mdoc;
const struct mdoc_node *node;
char *buf;
size_t len;
int line;
+bzero(®s, sizeof(struct regset));
line = 1;
-mdoc = mdoc_alloc(NULL, 0, NULL);
+mdoc = mdoc_alloc(®s, NULL, 0, NULL);
buf = NULL;
alloc_len = 0;