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

Annotation of mandoc/mandoc.3, Revision 1.38

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

CVSweb