---
name: "mandoc"
section: "3"
platform: "linux"
package: "libmandoc-dev"
version: "1.14.6-4"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/mandoc/3"
---

# mandoc(3)

mandoc macro compiler library

## NAME

**mandoc**, **deroff**, **mparse\_alloc**, **mparse\_copy**, **mparse\_free**, **mparse\_open**, **mparse\_readfd**, **mparse\_reset**, **mparse\_result** – mandoc macro compiler library

## SYNOPSIS

**#include \<sys/types.h\>**

**#include \<stdio.h\>**

**#include \<mandoc.h\>**

**#define ASCII\_NBRSP**

**#define ASCII\_HYPH**

**#define ASCII\_BREAK**

*struct* *mparse* *\**\

**mparse\_alloc**(*int options*, *enum mandoc\_os oe\_e*, *char \*os\_s*);

*void*\

**mparse\_free**(*struct mparse \*parse*);

*void*\

**mparse\_copy**(*const struct mparse \*parse*);

*int*\

**mparse\_open**(*struct mparse \*parse*, *const char \*fname*);

*void*\

**mparse\_readfd**(*struct mparse \*parse*, *int fd*, *const char \*fname*);

*void*\

**mparse\_reset**(*struct mparse \*parse*);

*struct* *roff\_meta* *\**\

**mparse\_result**(*struct mparse \*parse*);

**#include \<roff.h\>**

*void*\

**deroff**(*char \*\*dest*, *const struct roff\_node \*node*);

**#include \<sys/types.h\>**

**#include \<mandoc.h\>**

**#include \<mdoc.h\>**

*extern* *const* *char* *\** *const* *\** *mdoc\_argnames;* *extern* *const* *char* *\** *const* *\** *mdoc\_macronames;*

**#include \<sys/types.h\>**

**#include \<mandoc.h\>**

**#include \<man.h\>**

*extern* *const* *char* *\** *const* *\** *man\_macronames;*

## DESCRIPTION

The **mandoc** library parses a UNIX manual into an abstract syntax tree (AST). UNIX manuals are composed of [mdoc(7)](/mdoc/7.md) or [man(7)](/man/7.md), and may be mixed with [roff(7)](/roff/7.md), [tbl(7)](/tbl/7.md), and [eqn(7)](/eqn/7.md) invocations.

The following describes a general parse sequence:

1. initiate a parsing sequence with [mchars\_alloc(3)](/mchars_alloc/3.md) and **mparse\_alloc**();

2. open a file with [open(2)](/open/2.md) or **mparse\_open**();

3. parse it with **mparse\_readfd**();

4. close it with [close(2)](/close/2.md);

5. retrieve the syntax tree with **mparse\_result**();

6. if information about the validity of the input is needed, fetch it with **mparse\_updaterc**();

7. iterate over parse nodes with starting from the *first* member of the returned *struct* *roff\_meta*;

8. free all allocated memory with **mparse\_free**() and mchars\_free(3), or invoke **mparse\_reset**() and go back to step 2 to parse new files.

## REFERENCE

This section documents the functions, types, and variables available via ⟨mandoc.h⟩, with the exception of those documented in [mandoc\_escape(3)](/mandoc_escape/3.md) and [mchars\_alloc(3)](/mchars_alloc/3.md).

### Types

- *enum mandocerr*

  An error or warning message during parsing.

- *enum mandoclevel*

  A classification of an *enum mandocerr* as regards system operation. See the DIAGNOSTICS section in [mandoc(1)](/mandoc/1.md) regarding the meanings of the levels.

- *struct mparse*

  An opaque pointer to a running parse sequence. Created with **mparse\_alloc**() and freed with **mparse\_free**(). This may be used across parsed input if **mparse\_reset**() is called between parses.

### Functions

- **deroff**()

  Obtain a text-only representation of a *struct* *roff\_node*, including text contained in its child nodes. To be used on children of the *first* member of *struct* *roff\_meta*. When it is no longer needed, the pointer returned from **deroff**() can be passed to [free(3)](/free/3.md).

- **mparse\_alloc**()

  Allocate a parser. The arguments have the following effect:

  - *options*

    When the MPARSE\_MDOC or MPARSE\_MAN bit is set, only that parser is used. Otherwise, the document type is automatically detected.

    When the MPARSE\_SO bit is set, [roff(7)](/roff/7.md) **so** file inclusion requests are always honoured. Otherwise, if the request is the only content in an input file, only the file name is remembered, to be returned in the *sodest* field of *struct* *roff\_meta*.

    When the MPARSE\_QUICK bit is set, parsing is aborted after the NAME section. This is for example useful in [makewhatis(8)](/makewhatis/8.md) **-Q** to quickly build minimal databases.

    When the MARSE\_VALIDATE bit is set, **mparse\_result**() runs the validation functions before returning the syntax tree. This is almost always required, except in certain debugging scenarios, for example to dump unvalidated syntax trees.

  - *os\_e*

    Operating system to check base system conventions for. If MANDOC\_OS\_OTHER, the system is automatically detected from **Os**, **-Ios**, or [uname(3)](/uname/3.md).

  - *os\_s*

    A default string for the [mdoc(7)](/mdoc/7.md) **Os** macro, overriding the OSNAME preprocessor definition and the results of [uname(3)](/uname/3.md). Passing NULL sets no default.

    The same parser may be used for multiple files so long as **mparse\_reset**() is called between parses. **mparse\_free**() must be called to free the memory allocated by this function. Declared in ⟨mandoc.h⟩, implemented in *read.c*.

- **mparse\_free**()

  Free all memory allocated by **mparse\_alloc**(). Declared in ⟨mandoc.h⟩, implemented in *read.c*.

- **mparse\_copy**()

  Dump a copy of the input to the standard output; used for **-man** **-T****man**. Declared in ⟨mandoc.h⟩, implemented in *read.c*.

- **mparse\_open**()

  Open the file for reading. If that fails and *fname* does not already end in ‘.gz’, try again after appending ‘.gz’. Save the information whether the file is zipped or not. Return a file descriptor open for reading or -1 on failure. It can be passed to **mparse\_readfd**() or used directly. Declared in ⟨mandoc.h⟩, implemented in *read.c*.

- **mparse\_readfd**()

  Parse a file descriptor opened with [open(2)](/open/2.md) or **mparse\_open**(). Pass the associated filename in *fname*. This function may be called multiple times with different parameters; however, [close(2)](/close/2.md) and **mparse\_reset**() should be invoked between parses. Declared in ⟨mandoc.h⟩, implemented in *read.c*.

- **mparse\_reset**()

  Reset a parser so that **mparse\_readfd**() may be used again. Declared in ⟨mandoc.h⟩, implemented in *read.c*.

- **mparse\_result**()

  Obtain the result of a parse. Declared in ⟨mandoc.h⟩, implemented in *read.c*.

### Variables

- *man\_macronames*

  The string representation of a [man(7)](/man/7.md) macro as indexed by *enum mant*.

- *mdoc\_argnames*

  The string representation of an [mdoc(7)](/mdoc/7.md) macro argument as indexed by *enum mdocargt*.

- *mdoc\_macronames*

  The string representation of an [mdoc(7)](/mdoc/7.md) macro as indexed by *enum mdoct*.

## IMPLEMENTATION NOTES

This section consists of structural documentation for [mdoc(7)](/mdoc/7.md) and [man(7)](/man/7.md) syntax trees and strings.

### Man and Mdoc Strings

Strings may be extracted from mdoc and man meta-data, or from text nodes (MDOC\_TEXT and MAN\_TEXT, respectively). These strings have special non-printing formatting cues embedded in the text itself, as well as [roff(7)](/roff/7.md) escapes preserved from input. Implementing systems will need to handle both situations to produce human-readable text. In general, strings may be assumed to consist of 7-bit ASCII characters.

The following non-printing characters may be embedded in text strings:

- ASCII\_NBRSP

  A non-breaking space character.

- ASCII\_HYPH

  A soft hyphen.

- ASCII\_BREAK

  A breakable zero-width space.

Escape characters are also passed verbatim into text strings. An escape character is a sequence of characters beginning with the backslash (‘\\’). To construct human-readable text, these should be intercepted with [mandoc\_escape(3)](/mandoc_escape/3.md) and converted with one the functions described in [mchars\_alloc(3)](/mchars_alloc/3.md).

### Man Abstract Syntax Tree

This AST is governed by the ontological rules dictated in [man(7)](/man/7.md) and derives its terminology accordingly.

The AST is composed of *struct* *roff\_node* nodes with element, root and text types as declared by the *type* field. Each node also provides its parse point (the *line*, *pos*, and *sec* fields), its position in the tree (the *parent*, *child*, *next* and *prev* fields) and some type-specific data.

The tree itself is arranged according to the following normal form, where capitalised non-terminals represent nodes.

- ROOT

  ← mnode+

- mnode

  ← ELEMENT \| TEXT \| BLOCK

- BLOCK

  ← HEAD BODY

- HEAD

  ← mnode\*

- BODY

  ← mnode\*

- ELEMENT

  ← ELEMENT \| TEXT\*

- TEXT

  ← \[\[:ascii:\]\]\*

The only elements capable of nesting other elements are those with next-line scope as documented in [man(7)](/man/7.md).

### Mdoc Abstract Syntax Tree

This AST is governed by the ontological rules dictated in [mdoc(7)](/mdoc/7.md) and derives its terminology accordingly. "In-line" elements described in [mdoc(7)](/mdoc/7.md) are described simply as "elements".

The AST is composed of *struct* *roff\_node* nodes with block, head, body, element, root and text types as declared by the *type* field. Each node also provides its parse point (the *line*, *pos*, and *sec* fields), its position in the tree (the *parent*, *child*, *last*, *next* and *prev* fields) and some type-specific data, in particular, for nodes generated from macros, the generating macro in the *tok* field.

The tree itself is arranged according to the following normal form, where capitalised non-terminals represent nodes.

- ROOT

  ← mnode+

- mnode

  ← BLOCK \| ELEMENT \| TEXT

- BLOCK

  ← HEAD \[TEXT\] (BODY \[TEXT\])+ \[TAIL \[TEXT\]\]

- ELEMENT

  ← TEXT\*

- HEAD

  ← mnode\*

- BODY

  ← mnode\* \[ENDBODY mnode\*\]

- TAIL

  ← mnode\*

- TEXT

  ← \[\[:ascii:\]\]\*

Of note are the TEXT nodes following the HEAD, BODY and TAIL nodes of the BLOCK production: these refer to punctuation marks. Furthermore, although a TEXT node will generally have a non-zero-length string, in the specific case of ‘.Bd -literal’, an empty line will produce a zero-length string. Multiple body parts are only found in invocations of ‘Bl -column’, where a new body introduces a new phrase.

The [mdoc(7)](/mdoc/7.md) syntax tree accommodates for broken block structures as well. The ENDBODY node is available to end the formatting associated with a given block before the physical end of that block. It has a non-null *end* field, is of the BODY *type*, has the same *tok* as the BLOCK it is ending, and has a *pending* field pointing to that BLOCK's BODY node. It is an indirect child of that BODY node and has no children of its own.

An ENDBODY node is generated when a block ends while one of its child blocks is still open, like in the following example:

```
.Ao ao
.Bo bo ac
.Ac bc
.Bc end
```

This example results in the following block structure:

```
BLOCK Ao
    HEAD Ao
    BODY Ao
        TEXT ao
        BLOCK Bo, pending -> Ao
            HEAD Bo
            BODY Bo
                TEXT bo
                TEXT ac
                ENDBODY Ao, pending -> Ao
                TEXT bc
TEXT end
```

Here, the formatting of the **Ao** block extends from TEXT ao to TEXT ac, while the formatting of the **Bo** block extends from TEXT bo to TEXT bc. It renders as follows in **-T****ascii** mode:

```
<ao [bo ac> bc] end
```

Support for badly-nested blocks is only provided for backward compatibility with some older [mdoc(7)](/mdoc/7.md) implementations. Using badly-nested blocks is *strongly* *discouraged*; for example, the **-T****html** front-end to [mandoc(1)](/mandoc/1.md) is unable to render them in any meaningful way. Furthermore, behaviour when encountering badly-nested blocks is not consistent across troff implementations, especially when using multiple levels of badly-nested blocks.

## SEE ALSO

[mandoc(1)](/mandoc/1.md), man.cgi(3), [mandoc\_escape(3)](/mandoc_escape/3.md), mandoc\_headers(3), [mandoc\_malloc(3)](/mandoc_malloc/3.md), [mansearch(3)](/mansearch/3.md), [mchars\_alloc(3)](/mchars_alloc/3.md), [tbl(3)](/tbl/3.md), [eqn(7)](/eqn/7.md), [man(7)](/man/7.md), [mandoc\_char(7)](/mandoc_char/7.md), [mdoc(7)](/mdoc/7.md), [roff(7)](/roff/7.md), [tbl(7)](/tbl/7.md)

## AUTHORS

The **mandoc** library was written by Kristaps Dzonsons ⟨*kristaps@bsd.lv*⟩ and is maintained by Ingo Schwarze ⟨*schwarze@openbsd.org*⟩.
