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