[BACK]Return to mandoc.3 CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/mandoc.3, Revision 1.42

1.42    ! schwarze    1: .\"    $Id: mandoc.3,v 1.41 2017/07/04 23:40:01 schwarze Exp $
1.1       kristaps    2: .\"
                      3: .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.38      schwarze    4: .\" Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
1.1       kristaps    5: .\"
                      6: .\" Permission to use, copy, modify, and distribute this software for any
                      7: .\" purpose with or without fee is hereby granted, provided that the above
                      8: .\" copyright notice and this permission notice appear in all copies.
                      9: .\"
                     10: .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11: .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12: .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13: .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14: .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15: .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16: .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17: .\"
1.42    ! schwarze   18: .Dd $Mdocdate: July 4 2017 $
1.1       kristaps   19: .Dt MANDOC 3
                     20: .Os
                     21: .Sh NAME
                     22: .Nm mandoc ,
1.37      schwarze   23: .Nm deroff ,
                     24: .Nm mandocmsg ,
                     25: .Nm man_validate ,
                     26: .Nm mdoc_validate ,
1.1       kristaps   27: .Nm mparse_alloc ,
1.42    ! schwarze   28: .Nm mparse_copy ,
1.1       kristaps   29: .Nm mparse_free ,
1.26      schwarze   30: .Nm mparse_open ,
1.1       kristaps   31: .Nm mparse_readfd ,
                     32: .Nm mparse_reset ,
1.2       kristaps   33: .Nm mparse_result ,
                     34: .Nm mparse_strerror ,
1.38      schwarze   35: .Nm mparse_strlevel ,
1.41      schwarze   36: .Nm mparse_updaterc
1.1       kristaps   37: .Nd mandoc macro compiler library
                     38: .Sh SYNOPSIS
1.25      schwarze   39: .In sys/types.h
1.1       kristaps   40: .In mandoc.h
1.31      schwarze   41: .Pp
1.24      schwarze   42: .Fd "#define ASCII_NBRSP"
                     43: .Fd "#define ASCII_HYPH"
                     44: .Fd "#define ASCII_BREAK"
1.25      schwarze   45: .Ft struct mparse *
1.1       kristaps   46: .Fo mparse_alloc
1.25      schwarze   47: .Fa "int options"
1.40      schwarze   48: .Fa "enum mandocerr mmin"
1.23      schwarze   49: .Fa "mandocmsg mmsg"
1.40      schwarze   50: .Fa "enum mandoc_os oe_e"
                     51: .Fa "char *os_s"
1.1       kristaps   52: .Fc
                     53: .Ft void
1.24      schwarze   54: .Fo (*mandocmsg)
                     55: .Fa "enum mandocerr errtype"
                     56: .Fa "enum mandoclevel level"
                     57: .Fa "const char *file"
                     58: .Fa "int line"
                     59: .Fa "int col"
                     60: .Fa "const char *msg"
                     61: .Fc
                     62: .Ft void
1.1       kristaps   63: .Fo mparse_free
                     64: .Fa "struct mparse *parse"
                     65: .Fc
1.42    ! schwarze   66: .Ft void
        !            67: .Fo mparse_copy
1.14      kristaps   68: .Fa "const struct mparse *parse"
                     69: .Fc
1.35      schwarze   70: .Ft int
1.26      schwarze   71: .Fo mparse_open
                     72: .Fa "struct mparse *parse"
                     73: .Fa "const char *fname"
                     74: .Fc
                     75: .Ft "enum mandoclevel"
1.1       kristaps   76: .Fo mparse_readfd
                     77: .Fa "struct mparse *parse"
                     78: .Fa "int fd"
                     79: .Fa "const char *fname"
                     80: .Fc
                     81: .Ft void
                     82: .Fo mparse_reset
                     83: .Fa "struct mparse *parse"
                     84: .Fc
                     85: .Ft void
                     86: .Fo mparse_result
                     87: .Fa "struct mparse *parse"
1.37      schwarze   88: .Fa "struct roff_man **man"
1.25      schwarze   89: .Fa "char **sodest"
1.2       kristaps   90: .Fc
                     91: .Ft "const char *"
                     92: .Fo mparse_strerror
                     93: .Fa "enum mandocerr"
                     94: .Fc
                     95: .Ft "const char *"
                     96: .Fo mparse_strlevel
                     97: .Fa "enum mandoclevel"
1.1       kristaps   98: .Fc
1.38      schwarze   99: .Ft void
                    100: .Fo mparse_updaterc
                    101: .Fa "struct mparse *parse"
                    102: .Fa "enum mandoclevel *rc"
                    103: .Fc
1.37      schwarze  104: .In roff.h
                    105: .Ft void
                    106: .Fo deroff
                    107: .Fa "char **dest"
                    108: .Fa "const struct roff_node *node"
                    109: .Fc
1.25      schwarze  110: .In sys/types.h
1.24      schwarze  111: .In mandoc.h
                    112: .In mdoc.h
1.37      schwarze  113: .Vt extern const char * const * mdoc_argnames;
                    114: .Vt extern const char * const * mdoc_macronames;
1.25      schwarze  115: .Ft void
1.37      schwarze  116: .Fo mdoc_validate
                    117: .Fa "struct roff_man *mdoc"
1.24      schwarze  118: .Fc
1.25      schwarze  119: .In sys/types.h
1.24      schwarze  120: .In mandoc.h
                    121: .In man.h
1.37      schwarze  122: .Vt extern const char * const * man_macronames;
                    123: .Ft void
                    124: .Fo man_validate
                    125: .Fa "struct roff_man *man"
1.24      schwarze  126: .Fc
1.1       kristaps  127: .Sh DESCRIPTION
                    128: The
                    129: .Nm mandoc
                    130: library parses a
                    131: .Ux
                    132: manual into an abstract syntax tree (AST).
                    133: .Ux
                    134: manuals are composed of
                    135: .Xr mdoc 7
                    136: or
                    137: .Xr man 7 ,
                    138: and may be mixed with
                    139: .Xr roff 7 ,
                    140: .Xr tbl 7 ,
                    141: and
                    142: .Xr eqn 7
                    143: invocations.
                    144: .Pp
                    145: The following describes a general parse sequence:
                    146: .Bl -enum
                    147: .It
                    148: initiate a parsing sequence with
1.27      schwarze  149: .Xr mchars_alloc 3
                    150: and
1.1       kristaps  151: .Fn mparse_alloc ;
                    152: .It
1.31      schwarze  153: open a file with
                    154: .Xr open 2
                    155: or
                    156: .Fn mparse_open ;
                    157: .It
                    158: parse it with
1.1       kristaps  159: .Fn mparse_readfd ;
                    160: .It
1.34      schwarze  161: close it with
                    162: .Xr close 2 ;
                    163: .It
1.31      schwarze  164: retrieve the syntax tree with
1.1       kristaps  165: .Fn mparse_result ;
                    166: .It
1.37      schwarze  167: depending on whether the
                    168: .Fa macroset
                    169: member of the returned
                    170: .Vt struct roff_man
                    171: is
                    172: .Dv MACROSET_MDOC
                    173: or
                    174: .Dv MACROSET_MAN ,
                    175: validate it with
                    176: .Fn mdoc_validate
1.1       kristaps  177: or
1.37      schwarze  178: .Fn man_validate ,
                    179: respectively;
                    180: .It
1.38      schwarze  181: if information about the validity of the input is needed, fetch it with
                    182: .Fn mparse_updaterc ;
                    183: .It
1.37      schwarze  184: iterate over parse nodes with starting from the
                    185: .Fa first
                    186: member of the returned
                    187: .Vt struct roff_man ;
1.1       kristaps  188: .It
                    189: free all allocated memory with
1.27      schwarze  190: .Fn mparse_free
                    191: and
                    192: .Xr mchars_free 3 ,
1.1       kristaps  193: or invoke
                    194: .Fn mparse_reset
1.37      schwarze  195: and go back to step 2 to parse new files.
1.3       kristaps  196: .El
                    197: .Sh REFERENCE
                    198: This section documents the functions, types, and variables available
                    199: via
1.25      schwarze  200: .In mandoc.h ,
                    201: with the exception of those documented in
                    202: .Xr mandoc_escape 3
                    203: and
                    204: .Xr mchars_alloc 3 .
1.3       kristaps  205: .Ss Types
                    206: .Bl -ohang
                    207: .It Vt "enum mandocerr"
1.31      schwarze  208: An error or warning message during parsing.
1.3       kristaps  209: .It Vt "enum mandoclevel"
1.11      kristaps  210: A classification of an
1.23      schwarze  211: .Vt "enum mandocerr"
1.11      kristaps  212: as regards system operation.
1.37      schwarze  213: See the DIAGNOSTICS section in
                    214: .Xr mandoc 1
                    215: regarding the meanings of the levels.
1.3       kristaps  216: .It Vt "struct mparse"
1.11      kristaps  217: An opaque pointer to a running parse sequence.
                    218: Created with
                    219: .Fn mparse_alloc
                    220: and freed with
                    221: .Fn mparse_free .
                    222: This may be used across parsed input if
                    223: .Fn mparse_reset
                    224: is called between parses.
1.3       kristaps  225: .It Vt "mandocmsg"
1.31      schwarze  226: A prototype for a function to handle error and warning
1.11      kristaps  227: messages emitted by the parser.
1.3       kristaps  228: .El
                    229: .Ss Functions
                    230: .Bl -ohang
1.37      schwarze  231: .It Fn deroff
1.25      schwarze  232: Obtain a text-only representation of a
1.37      schwarze  233: .Vt struct roff_node ,
1.25      schwarze  234: including text contained in its child nodes.
1.37      schwarze  235: To be used on children of the
                    236: .Fa first
                    237: member of
                    238: .Vt struct roff_man .
1.25      schwarze  239: When it is no longer needed, the pointer returned from
1.37      schwarze  240: .Fn deroff
1.25      schwarze  241: can be passed to
                    242: .Xr free 3 .
1.37      schwarze  243: .It Fn man_validate
                    244: Validate the
                    245: .Dv MACROSET_MAN
                    246: parse tree obtained with
1.4       kristaps  247: .Fn mparse_result .
1.18      schwarze  248: Declared in
                    249: .In man.h ,
                    250: implemented in
                    251: .Pa man.c .
1.37      schwarze  252: .It Fn mdoc_validate
                    253: Validate the
                    254: .Dv MACROSET_MDOC
                    255: parse tree obtained with
1.4       kristaps  256: .Fn mparse_result .
1.18      schwarze  257: Declared in
                    258: .In mdoc.h ,
                    259: implemented in
                    260: .Pa mdoc.c .
1.3       kristaps  261: .It Fn mparse_alloc
1.4       kristaps  262: Allocate a parser.
1.23      schwarze  263: The arguments have the following effect:
                    264: .Bl -tag -offset 5n -width inttype
1.25      schwarze  265: .It Ar options
                    266: When the
1.23      schwarze  267: .Dv MPARSE_MDOC
                    268: or
1.25      schwarze  269: .Dv MPARSE_MAN
                    270: bit is set, only that parser is used.
                    271: Otherwise, the document type is automatically detected.
                    272: .Pp
                    273: When the
                    274: .Dv MPARSE_SO
                    275: bit is set,
                    276: .Xr roff 7
                    277: .Ic \&so
                    278: file inclusion requests are always honoured.
                    279: Otherwise, if the request is the only content in an input file,
                    280: only the file name is remembered, to be returned in the
                    281: .Fa sodest
                    282: argument of
                    283: .Fn mparse_result .
                    284: .Pp
                    285: When the
                    286: .Dv MPARSE_QUICK
                    287: bit is set, parsing is aborted after the NAME section.
                    288: This is for example useful in
                    289: .Xr makewhatis 8
                    290: .Fl Q
                    291: to quickly build minimal databases.
1.40      schwarze  292: .It Ar mmin
1.23      schwarze  293: Can be set to
1.40      schwarze  294: .Dv MANDOCERR_BASE ,
                    295: .Dv MANDOCERR_STYLE ,
                    296: .Dv MANDOCERR_WARNING ,
                    297: .Dv MANDOCERR_ERROR ,
                    298: .Dv MANDOCERR_UNSUPP ,
1.23      schwarze  299: or
1.40      schwarze  300: .Dv MANDOCERR_MAX .
1.23      schwarze  301: Messages below the selected level will be suppressed.
                    302: .It Ar mmsg
                    303: A callback function to handle errors and warnings.
                    304: See
                    305: .Pa main.c
                    306: for an example.
1.37      schwarze  307: If printing of error messages is not desired,
                    308: .Dv NULL
                    309: may be passed.
1.40      schwarze  310: .It Ar os_e
                    311: Operating system to check base system conventions for.
                    312: If
                    313: .Dv MANDOC_OS_OTHER ,
                    314: the system is automatically detected from
                    315: .Ic \&Os ,
                    316: .Fl Ios ,
                    317: or
                    318: .Xr uname 3 .
                    319: .It Ar os_s
1.23      schwarze  320: A default string for the
                    321: .Xr mdoc 7
1.40      schwarze  322: .Ic \&Os
1.23      schwarze  323: macro, overriding the
                    324: .Dv OSNAME
                    325: preprocessor definition and the results of
                    326: .Xr uname 3 .
1.37      schwarze  327: Passing
                    328: .Dv NULL
                    329: sets no default.
1.23      schwarze  330: .El
                    331: .Pp
1.4       kristaps  332: The same parser may be used for multiple files so long as
                    333: .Fn mparse_reset
                    334: is called between parses.
                    335: .Fn mparse_free
                    336: must be called to free the memory allocated by this function.
1.18      schwarze  337: Declared in
                    338: .In mandoc.h ,
                    339: implemented in
                    340: .Pa read.c .
1.3       kristaps  341: .It Fn mparse_free
1.4       kristaps  342: Free all memory allocated by
                    343: .Fn mparse_alloc .
1.18      schwarze  344: Declared in
                    345: .In mandoc.h ,
                    346: implemented in
                    347: .Pa read.c .
1.42    ! schwarze  348: .It Fn mparse_copy
        !           349: Dump a copy of the input to the standard output; used for
        !           350: .Fl man T Ns Cm man .
1.18      schwarze  351: Declared in
                    352: .In mandoc.h ,
                    353: implemented in
                    354: .Pa read.c .
1.26      schwarze  355: .It Fn mparse_open
1.32      schwarze  356: Open the file for reading.
                    357: If that fails and
1.26      schwarze  358: .Fa fname
1.32      schwarze  359: does not already end in
                    360: .Ql .gz ,
                    361: try again after appending
                    362: .Ql .gz .
                    363: Save the information whether the file is zipped or not.
1.35      schwarze  364: Return a file descriptor open for reading or -1 on failure.
1.26      schwarze  365: It can be passed to
                    366: .Fn mparse_readfd
                    367: or used directly.
                    368: Declared in
                    369: .In mandoc.h ,
                    370: implemented in
                    371: .Pa read.c .
1.3       kristaps  372: .It Fn mparse_readfd
1.30      schwarze  373: Parse a file descriptor opened with
                    374: .Xr open 2
                    375: or
1.29      schwarze  376: .Fn mparse_open .
1.30      schwarze  377: Pass the associated filename in
                    378: .Va fname .
1.29      schwarze  379: This function may be called multiple times with different parameters; however,
1.34      schwarze  380: .Xr close 2
                    381: and
1.4       kristaps  382: .Fn mparse_reset
                    383: should be invoked between parses.
1.18      schwarze  384: Declared in
                    385: .In mandoc.h ,
                    386: implemented in
                    387: .Pa read.c .
1.3       kristaps  388: .It Fn mparse_reset
1.4       kristaps  389: Reset a parser so that
                    390: .Fn mparse_readfd
                    391: may be used again.
1.18      schwarze  392: Declared in
                    393: .In mandoc.h ,
                    394: implemented in
                    395: .Pa read.c .
1.3       kristaps  396: .It Fn mparse_result
1.4       kristaps  397: Obtain the result of a parse.
1.37      schwarze  398: One of the two pointers will be filled in.
1.18      schwarze  399: Declared in
                    400: .In mandoc.h ,
                    401: implemented in
                    402: .Pa read.c .
1.3       kristaps  403: .It Fn mparse_strerror
1.4       kristaps  404: Return a statically-allocated string representation of an error code.
1.18      schwarze  405: Declared in
                    406: .In mandoc.h ,
                    407: implemented in
                    408: .Pa read.c .
1.3       kristaps  409: .It Fn mparse_strlevel
1.4       kristaps  410: Return a statically-allocated string representation of a level code.
1.38      schwarze  411: Declared in
                    412: .In mandoc.h ,
                    413: implemented in
                    414: .Pa read.c .
                    415: .It Fn mparse_updaterc
                    416: If the highest warning or error level that occurred during the current
                    417: .Fa parse
                    418: is higher than
                    419: .Pf * Fa rc ,
                    420: update
                    421: .Pf * Fa rc
                    422: accordingly.
                    423: This is useful after calling
                    424: .Fn mdoc_validate
                    425: or
                    426: .Fn man_validate .
1.18      schwarze  427: Declared in
                    428: .In mandoc.h ,
                    429: implemented in
                    430: .Pa read.c .
1.3       kristaps  431: .El
                    432: .Ss Variables
                    433: .Bl -ohang
                    434: .It Va man_macronames
1.37      schwarze  435: The string representation of a
                    436: .Xr man 7
                    437: macro as indexed by
1.4       kristaps  438: .Vt "enum mant" .
1.3       kristaps  439: .It Va mdoc_argnames
1.37      schwarze  440: The string representation of an
                    441: .Xr mdoc 7
                    442: macro argument as indexed by
1.4       kristaps  443: .Vt "enum mdocargt" .
1.3       kristaps  444: .It Va mdoc_macronames
1.37      schwarze  445: The string representation of an
                    446: .Xr mdoc 7
                    447: macro as indexed by
1.4       kristaps  448: .Vt "enum mdoct" .
1.1       kristaps  449: .El
                    450: .Sh IMPLEMENTATION NOTES
                    451: This section consists of structural documentation for
                    452: .Xr mdoc 7
                    453: and
                    454: .Xr man 7
1.11      kristaps  455: syntax trees and strings.
                    456: .Ss Man and Mdoc Strings
                    457: Strings may be extracted from mdoc and man meta-data, or from text
                    458: nodes (MDOC_TEXT and MAN_TEXT, respectively).
                    459: These strings have special non-printing formatting cues embedded in the
                    460: text itself, as well as
                    461: .Xr roff 7
                    462: escapes preserved from input.
                    463: Implementing systems will need to handle both situations to produce
                    464: human-readable text.
                    465: In general, strings may be assumed to consist of 7-bit ASCII characters.
                    466: .Pp
                    467: The following non-printing characters may be embedded in text strings:
                    468: .Bl -tag -width Ds
                    469: .It Dv ASCII_NBRSP
                    470: A non-breaking space character.
                    471: .It Dv ASCII_HYPH
                    472: A soft hyphen.
1.25      schwarze  473: .It Dv ASCII_BREAK
                    474: A breakable zero-width space.
1.11      kristaps  475: .El
                    476: .Pp
                    477: Escape characters are also passed verbatim into text strings.
                    478: An escape character is a sequence of characters beginning with the
                    479: backslash
                    480: .Pq Sq \e .
                    481: To construct human-readable text, these should be intercepted with
1.25      schwarze  482: .Xr mandoc_escape 3
                    483: and converted with one the functions described in
                    484: .Xr mchars_alloc 3 .
1.1       kristaps  485: .Ss Man Abstract Syntax Tree
                    486: This AST is governed by the ontological rules dictated in
                    487: .Xr man 7
                    488: and derives its terminology accordingly.
                    489: .Pp
                    490: The AST is composed of
1.37      schwarze  491: .Vt struct roff_node
1.1       kristaps  492: nodes with element, root and text types as declared by the
                    493: .Va type
                    494: field.
                    495: Each node also provides its parse point (the
                    496: .Va line ,
1.37      schwarze  497: .Va pos ,
1.1       kristaps  498: and
1.37      schwarze  499: .Va sec
1.1       kristaps  500: fields), its position in the tree (the
                    501: .Va parent ,
                    502: .Va child ,
                    503: .Va next
                    504: and
                    505: .Va prev
                    506: fields) and some type-specific data.
                    507: .Pp
                    508: The tree itself is arranged according to the following normal form,
                    509: where capitalised non-terminals represent nodes.
                    510: .Pp
                    511: .Bl -tag -width "ELEMENTXX" -compact
                    512: .It ROOT
                    513: \(<- mnode+
                    514: .It mnode
                    515: \(<- ELEMENT | TEXT | BLOCK
                    516: .It BLOCK
                    517: \(<- HEAD BODY
                    518: .It HEAD
                    519: \(<- mnode*
                    520: .It BODY
                    521: \(<- mnode*
                    522: .It ELEMENT
                    523: \(<- ELEMENT | TEXT*
                    524: .It TEXT
1.11      kristaps  525: \(<- [[:ascii:]]*
1.1       kristaps  526: .El
                    527: .Pp
                    528: The only elements capable of nesting other elements are those with
1.25      schwarze  529: next-line scope as documented in
1.1       kristaps  530: .Xr man 7 .
                    531: .Ss Mdoc Abstract Syntax Tree
                    532: This AST is governed by the ontological
                    533: rules dictated in
                    534: .Xr mdoc 7
                    535: and derives its terminology accordingly.
                    536: .Qq In-line
                    537: elements described in
                    538: .Xr mdoc 7
                    539: are described simply as
                    540: .Qq elements .
                    541: .Pp
                    542: The AST is composed of
1.37      schwarze  543: .Vt struct roff_node
1.1       kristaps  544: nodes with block, head, body, element, root and text types as declared
                    545: by the
                    546: .Va type
                    547: field.
                    548: Each node also provides its parse point (the
                    549: .Va line ,
1.37      schwarze  550: .Va pos ,
1.1       kristaps  551: and
1.37      schwarze  552: .Va sec
1.1       kristaps  553: fields), its position in the tree (the
                    554: .Va parent ,
                    555: .Va child ,
1.36      schwarze  556: .Va last ,
1.1       kristaps  557: .Va next
                    558: and
                    559: .Va prev
                    560: fields) and some type-specific data, in particular, for nodes generated
                    561: from macros, the generating macro in the
                    562: .Va tok
                    563: field.
                    564: .Pp
                    565: The tree itself is arranged according to the following normal form,
                    566: where capitalised non-terminals represent nodes.
                    567: .Pp
                    568: .Bl -tag -width "ELEMENTXX" -compact
                    569: .It ROOT
                    570: \(<- mnode+
                    571: .It mnode
                    572: \(<- BLOCK | ELEMENT | TEXT
                    573: .It BLOCK
                    574: \(<- HEAD [TEXT] (BODY [TEXT])+ [TAIL [TEXT]]
                    575: .It ELEMENT
                    576: \(<- TEXT*
                    577: .It HEAD
                    578: \(<- mnode*
                    579: .It BODY
                    580: \(<- mnode* [ENDBODY mnode*]
                    581: .It TAIL
                    582: \(<- mnode*
                    583: .It TEXT
1.11      kristaps  584: \(<- [[:ascii:]]*
1.1       kristaps  585: .El
                    586: .Pp
                    587: Of note are the TEXT nodes following the HEAD, BODY and TAIL nodes of
                    588: the BLOCK production: these refer to punctuation marks.
                    589: Furthermore, although a TEXT node will generally have a non-zero-length
                    590: string, in the specific case of
                    591: .Sq \&.Bd \-literal ,
                    592: an empty line will produce a zero-length string.
                    593: Multiple body parts are only found in invocations of
                    594: .Sq \&Bl \-column ,
                    595: where a new body introduces a new phrase.
                    596: .Pp
                    597: The
                    598: .Xr mdoc 7
1.5       kristaps  599: syntax tree accommodates for broken block structures as well.
1.1       kristaps  600: The ENDBODY node is available to end the formatting associated
                    601: with a given block before the physical end of that block.
                    602: It has a non-null
                    603: .Va end
                    604: field, is of the BODY
                    605: .Va type ,
                    606: has the same
                    607: .Va tok
                    608: as the BLOCK it is ending, and has a
                    609: .Va pending
                    610: field pointing to that BLOCK's BODY node.
                    611: It is an indirect child of that BODY node
                    612: and has no children of its own.
                    613: .Pp
                    614: An ENDBODY node is generated when a block ends while one of its child
                    615: blocks is still open, like in the following example:
                    616: .Bd -literal -offset indent
                    617: \&.Ao ao
                    618: \&.Bo bo ac
                    619: \&.Ac bc
                    620: \&.Bc end
                    621: .Ed
                    622: .Pp
                    623: This example results in the following block structure:
                    624: .Bd -literal -offset indent
                    625: BLOCK Ao
                    626:     HEAD Ao
                    627:     BODY Ao
                    628:         TEXT ao
                    629:         BLOCK Bo, pending -> Ao
                    630:             HEAD Bo
                    631:             BODY Bo
                    632:                 TEXT bo
                    633:                 TEXT ac
                    634:                 ENDBODY Ao, pending -> Ao
                    635:                 TEXT bc
                    636: TEXT end
                    637: .Ed
                    638: .Pp
                    639: Here, the formatting of the
1.40      schwarze  640: .Ic \&Ao
1.1       kristaps  641: block extends from TEXT ao to TEXT ac,
                    642: while the formatting of the
1.40      schwarze  643: .Ic \&Bo
1.1       kristaps  644: block extends from TEXT bo to TEXT bc.
                    645: It renders as follows in
                    646: .Fl T Ns Cm ascii
                    647: mode:
                    648: .Pp
                    649: .Dl <ao [bo ac> bc] end
                    650: .Pp
                    651: Support for badly-nested blocks is only provided for backward
                    652: compatibility with some older
                    653: .Xr mdoc 7
                    654: implementations.
                    655: Using badly-nested blocks is
                    656: .Em strongly discouraged ;
                    657: for example, the
                    658: .Fl T Ns Cm html
1.39      schwarze  659: front-end to
1.1       kristaps  660: .Xr mandoc 1
1.39      schwarze  661: is unable to render them in any meaningful way.
1.1       kristaps  662: Furthermore, behaviour when encountering badly-nested blocks is not
1.25      schwarze  663: consistent across troff implementations, especially when using multiple
1.1       kristaps  664: levels of badly-nested blocks.
                    665: .Sh SEE ALSO
                    666: .Xr mandoc 1 ,
1.37      schwarze  667: .Xr man.cgi 3 ,
1.25      schwarze  668: .Xr mandoc_escape 3 ,
1.37      schwarze  669: .Xr mandoc_headers 3 ,
1.25      schwarze  670: .Xr mandoc_malloc 3 ,
1.37      schwarze  671: .Xr mansearch 3 ,
1.25      schwarze  672: .Xr mchars_alloc 3 ,
1.37      schwarze  673: .Xr tbl 3 ,
1.1       kristaps  674: .Xr eqn 7 ,
                    675: .Xr man 7 ,
1.6       kristaps  676: .Xr mandoc_char 7 ,
1.1       kristaps  677: .Xr mdoc 7 ,
                    678: .Xr roff 7 ,
                    679: .Xr tbl 7
                    680: .Sh AUTHORS
1.37      schwarze  681: .An -nosplit
1.1       kristaps  682: The
                    683: .Nm
                    684: library was written by
1.37      schwarze  685: .An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
                    686: and is maintained by
                    687: .An Ingo Schwarze Aq Mt schwarze@openbsd.org .

CVSweb