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