]>
git.cameronkatri.com Git - mandoc.git/blob - mdoc.c
1 /* $Id: mdoc.c,v 1.46 2009/02/22 14:31:08 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
30 * Main caller in the libmdoc library. This begins the parsing routine,
31 * handles allocation of data, and so forth. Most of the "work" is done
32 * in macro.c, but this orchestrates who does what, when.
35 const char *const __mdoc_macronames
[MDOC_MAX
] = {
36 "\\\"", "Dd", "Dt", "Os",
37 "Sh", "Ss", "Pp", "D1",
38 "Dl", "Bd", "Ed", "Bl",
39 "El", "It", "Ad", "An",
40 "Ar", "Cd", "Cm", "Dv",
41 "Er", "Ev", "Ex", "Fa",
42 "Fd", "Fl", "Fn", "Ft",
43 "Ic", "In", "Li", "Nd",
44 "Nm", "Op", "Ot", "Pa",
45 "Rv", "St", "Va", "Vt",
47 "Xr", "\%A", "\%B", "\%D",
49 "\%I", "\%J", "\%N", "\%O",
51 "\%P", "\%R", "\%T", "\%V",
52 "Ac", "Ao", "Aq", "At",
53 "Bc", "Bf", "Bo", "Bq",
54 "Bsx", "Bx", "Db", "Dc",
55 "Do", "Dq", "Ec", "Ef",
56 "Em", "Eo", "Fx", "Ms",
57 "No", "Ns", "Nx", "Ox",
58 "Pc", "Pf", "Po", "Pq",
59 "Qc", "Ql", "Qo", "Qq",
60 "Re", "Rs", "Sc", "So",
61 "Sq", "Sm", "Sx", "Sy",
62 "Tn", "Ux", "Xc", "Xo",
63 "Fo", "Fc", "Oo", "Oc",
64 "Bk", "Ek", "Bt", "Hf",
68 const char *const __mdoc_argnames
[MDOC_ARG_MAX
] = {
69 "split", "nosplit", "ragged",
70 "unfilled", "literal", "file",
71 "offset", "bullet", "dash",
72 "hyphen", "item", "enum",
73 "tag", "diag", "hang",
74 "ohang", "inset", "column",
75 "width", "compact", "std",
76 "p1003.1-88", "p1003.1-90", "p1003.1-96",
77 "p1003.1-2001", "p1003.1-2004", "p1003.1",
78 "p1003.1b", "p1003.1b-93", "p1003.1c-95",
79 "p1003.1g-2000", "p1003.2-92", "p1387.2-95",
80 "p1003.2", "p1387.2", "isoC-90",
81 "isoC-amd1", "isoC-tcor1", "isoC-tcor2",
82 "isoC-99", "ansiC", "ansiC-89",
83 "ansiC-99", "ieee754", "iso8802-3",
84 "xpg3", "xpg4", "xpg4.2",
85 "xpg4.3", "xbd5", "xcu5",
86 "xsh5", "xns5", "xns5.2d2.0",
87 "xcurses4.2", "susv2", "susv3",
88 "svid4", "filled", "words",
89 "emphasis", "symbolic",
92 /* Central table of library: who gets parsed how. */
94 const struct mdoc_macro __mdoc_macros
[MDOC_MAX
] = {
96 { macro_constant
, MDOC_PROLOGUE
}, /* Dd */
97 { macro_constant
, MDOC_PROLOGUE
}, /* Dt */
98 { macro_constant
, MDOC_PROLOGUE
}, /* Os */
99 { macro_scoped
, 0 }, /* Sh */
100 { macro_scoped
, 0 }, /* Ss */
101 { macro_text
, 0 }, /* Pp */
102 { macro_scoped_line
, MDOC_PARSED
}, /* D1 */
103 { macro_scoped_line
, MDOC_PARSED
}, /* Dl */
104 { macro_scoped
, MDOC_EXPLICIT
}, /* Bd */
105 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Ed */
106 { macro_scoped
, MDOC_EXPLICIT
}, /* Bl */
107 { macro_scoped_close
, MDOC_EXPLICIT
}, /* El */
108 { macro_scoped
, MDOC_PARSED
}, /* It */
109 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ad */
110 { macro_text
, MDOC_PARSED
}, /* An */
111 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ar */
112 { macro_constant
, 0 }, /* Cd */
113 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Cm */
114 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dv */
115 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Er */
116 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ev */
117 { macro_constant
, 0 }, /* Ex */
118 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fa */
119 { macro_constant
, 0 }, /* Fd */
120 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fl */
121 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fn */
122 { macro_text
, MDOC_PARSED
}, /* Ft */
123 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ic */
124 { macro_constant
, 0 }, /* In */
125 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Li */
126 { macro_constant
, 0 }, /* Nd */
127 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nm */
128 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Op */
129 { macro_obsolete
, 0 }, /* Ot */
130 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pa */
131 { macro_constant
, 0 }, /* Rv */
132 /* XXX - .St supposed to be (but isn't) callable. */
133 { macro_constant_delimited
, MDOC_PARSED
}, /* St */
134 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Va */
135 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Vt */
136 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Xr */
137 { macro_constant
, 0 }, /* %A */
138 { macro_constant
, 0 }, /* %B */
139 { macro_constant
, 0 }, /* %D */
140 { macro_constant
, 0 }, /* %I */
141 { macro_constant
, 0 }, /* %J */
142 { macro_constant
, 0 }, /* %N */
143 { macro_constant
, 0 }, /* %O */
144 { macro_constant
, 0 }, /* %P */
145 { macro_constant
, 0 }, /* %R */
146 { macro_constant
, 0 }, /* %T */
147 { macro_constant
, 0 }, /* %V */
148 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ac */
149 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Ao */
150 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Aq */
151 { macro_constant_delimited
, 0 }, /* At */
152 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Bc */
153 { macro_scoped
, MDOC_EXPLICIT
}, /* Bf */
154 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bo */
155 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bq */
156 { macro_constant_delimited
, MDOC_PARSED
}, /* Bsx */
157 { macro_constant_delimited
, MDOC_PARSED
}, /* Bx */
158 { macro_constant
, 0 }, /* Db */
159 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Dc */
160 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Do */
161 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dq */
162 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ec */
163 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Ef */
164 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Em */
165 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Eo */
166 { macro_constant_delimited
, MDOC_PARSED
}, /* Fx */
167 { macro_text
, MDOC_PARSED
}, /* Ms */
168 { macro_constant_delimited
, MDOC_CALLABLE
| MDOC_PARSED
}, /* No */
169 { macro_constant_delimited
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ns */
170 { macro_constant_delimited
, MDOC_PARSED
}, /* Nx */
171 { macro_constant_delimited
, MDOC_PARSED
}, /* Ox */
172 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Pc */
173 { macro_constant_delimited
, MDOC_PARSED
}, /* Pf */
174 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Po */
175 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pq */
176 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Qc */
177 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ql */
178 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Qo */
179 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Qq */
180 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Re */
181 { macro_scoped
, MDOC_EXPLICIT
}, /* Rs */
182 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Sc */
183 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* So */
184 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sq */
185 { macro_constant
, 0 }, /* Sm */
186 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sx */
187 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sy */
188 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Tn */
189 { macro_constant_delimited
, MDOC_PARSED
}, /* Ux */
190 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Xc */
191 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Xo */
192 /* XXX - .Fo supposed to be (but isn't) callable. */
193 { macro_scoped
, MDOC_EXPLICIT
}, /* Fo */
194 /* XXX - .Fc supposed to be (but isn't) callable. */
195 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Fc */
196 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Oo */
197 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Oc */
198 { macro_scoped
, MDOC_EXPLICIT
}, /* Bk */
199 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Ek */
200 { macro_constant
, 0 }, /* Bt */
201 { macro_constant
, 0 }, /* Hf */
202 { macro_obsolete
, 0 }, /* Fr */
203 { macro_constant
, 0 }, /* Ud */
206 const char * const *mdoc_macronames
= __mdoc_macronames
;
207 const char * const *mdoc_argnames
= __mdoc_argnames
;
208 const struct mdoc_macro
* const mdoc_macros
= __mdoc_macros
;
210 static struct mdoc_arg
*argdup(size_t, const struct mdoc_arg
*);
211 static void argfree(size_t, struct mdoc_arg
*);
212 static void argcpy(struct mdoc_arg
*,
213 const struct mdoc_arg
*);
215 static struct mdoc_node
*mdoc_node_alloc(const struct mdoc
*);
216 static int mdoc_node_append(struct mdoc
*,
218 static void mdoc_elem_free(struct mdoc_elem
*);
219 static void mdoc_text_free(struct mdoc_text
*);
223 const struct mdoc_node
*
224 mdoc_node(struct mdoc
*mdoc
)
231 const struct mdoc_meta
*
232 mdoc_meta(struct mdoc
*mdoc
)
240 mdoc_free(struct mdoc
*mdoc
)
244 mdoc_node_freelist(mdoc
->first
);
246 mdoc_tokhash_free(mdoc
->htab
);
247 if (mdoc
->meta
.title
)
248 free(mdoc
->meta
.title
);
252 free(mdoc
->meta
.name
);
259 mdoc_alloc(void *data
, const struct mdoc_cb
*cb
)
263 p
= xcalloc(1, sizeof(struct mdoc
));
267 (void)memcpy(&p
->cb
, cb
, sizeof(struct mdoc_cb
));
269 p
->last
= xcalloc(1, sizeof(struct mdoc_node
));
270 p
->last
->type
= MDOC_ROOT
;
273 p
->next
= MDOC_NEXT_CHILD
;
274 p
->htab
= mdoc_tokhash_alloc();
281 mdoc_endparse(struct mdoc
*mdoc
)
284 if (MDOC_HALT
& mdoc
->flags
)
286 if (NULL
== mdoc
->first
)
290 if ( ! macro_end(mdoc
)) {
291 mdoc
->flags
|= MDOC_HALT
;
299 mdoc_parseln(struct mdoc
*mdoc
, int line
, char *buf
)
304 if (MDOC_HALT
& mdoc
->flags
)
310 if (SEC_PROLOGUE
== mdoc
->lastnamed
)
311 return(mdoc_perr(mdoc
, line
, 0, "text disallowed in document prologue"));
312 if ( ! mdoc_word_alloc(mdoc
, line
, 0, buf
))
314 mdoc
->next
= MDOC_NEXT_SIBLING
;
318 if (buf
[1] && '\\' == buf
[1])
319 if (buf
[2] && '\"' == buf
[2])
323 while (buf
[i
] && ! isspace((int)buf
[i
]) && i
< (int)sizeof(tmp
))
326 if (i
== (int)sizeof(tmp
)) {
327 mdoc
->flags
|= MDOC_HALT
;
328 return(mdoc_perr(mdoc
, line
, 1, "unknown macro"));
330 mdoc
->flags
|= MDOC_HALT
;
331 return(mdoc_perr(mdoc
, line
, 1, "unknown macro"));
336 (void)memcpy(tmp
, buf
+ 1, (size_t)i
);
339 if (MDOC_MAX
== (c
= mdoc_find(mdoc
, tmp
))) {
340 mdoc
->flags
|= MDOC_HALT
;
341 return(mdoc_perr(mdoc
, line
, 1, "unknown macro"));
344 while (buf
[i
] && isspace((int)buf
[i
]))
347 if ( ! mdoc_macro(mdoc
, c
, line
, 1, &i
, buf
)) {
348 mdoc
->flags
|= MDOC_HALT
;
356 mdoc_vmsg(struct mdoc
*mdoc
, int ln
, int pos
, const char *fmt
, ...)
361 if (NULL
== mdoc
->cb
.mdoc_msg
)
365 (void)vsnprintf(buf
, sizeof(buf
) - 1, fmt
, ap
);
367 (*mdoc
->cb
.mdoc_msg
)(mdoc
->data
, ln
, pos
, buf
);
372 mdoc_verr(struct mdoc
*mdoc
, int ln
, int pos
,
373 const char *fmt
, ...)
378 if (NULL
== mdoc
->cb
.mdoc_err
)
382 (void)vsnprintf(buf
, sizeof(buf
) - 1, fmt
, ap
);
384 return((*mdoc
->cb
.mdoc_err
)(mdoc
->data
, ln
, pos
, buf
));
389 mdoc_vwarn(struct mdoc
*mdoc
, int ln
, int pos
,
390 enum mdoc_warn type
, const char *fmt
, ...)
395 if (NULL
== mdoc
->cb
.mdoc_warn
)
399 (void)vsnprintf(buf
, sizeof(buf
) - 1, fmt
, ap
);
401 return((*mdoc
->cb
.mdoc_warn
)(mdoc
->data
, ln
, pos
, type
, buf
));
406 mdoc_macro(struct mdoc
*mdoc
, int tok
,
407 int ln
, int ppos
, int *pos
, char *buf
)
410 assert(mdoc_macros
[tok
].fp
);
412 if (MDOC_PROLOGUE
& mdoc_macros
[tok
].flags
&&
413 SEC_PROLOGUE
!= mdoc
->lastnamed
)
414 return(mdoc_perr(mdoc
, ln
, ppos
, "macro disallowed in document body"));
415 if ( ! (MDOC_PROLOGUE
& mdoc_macros
[tok
].flags
) &&
416 SEC_PROLOGUE
== mdoc
->lastnamed
)
417 return(mdoc_perr(mdoc
, ln
, ppos
, "macro disallowed in document prologue"));
418 if (1 != ppos
&& ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
))
419 return(mdoc_perr(mdoc
, ln
, ppos
, "macro not callable"));
420 return((*mdoc_macros
[tok
].fp
)(mdoc
, tok
, ln
, ppos
, pos
, buf
));
425 mdoc_node_append(struct mdoc
*mdoc
, struct mdoc_node
*p
)
427 const char *nn
, *nt
, *on
, *ot
, *act
;
431 assert(MDOC_ROOT
!= p
->type
);
433 /* See if we exceed the suggest line-max. */
447 /* This sort-of works (re-opening of text macros...). */
448 if (mdoc
->linetok
> MDOC_LINEARG_SOFTMAX
)
449 if ( ! mdoc_nwarn(mdoc
, p
, WARN_COMPAT
,
450 "suggested %d tokens per line exceeded (has %d)",
451 MDOC_LINEARG_SOFTMAX
, mdoc
->linetok
))
454 if (MDOC_TEXT
== mdoc
->last
->type
)
456 else if (MDOC_ROOT
== mdoc
->last
->type
)
459 on
= mdoc_macronames
[mdoc
->last
->tok
];
461 if (MDOC_TEXT
== p
->type
)
463 else if (MDOC_ROOT
== p
->type
)
466 nn
= mdoc_macronames
[p
->tok
];
468 ot
= mdoc_type2a(mdoc
->last
->type
);
469 nt
= mdoc_type2a(p
->type
);
471 switch (mdoc
->next
) {
472 case (MDOC_NEXT_SIBLING
):
473 mdoc
->last
->next
= p
;
474 p
->prev
= mdoc
->last
;
475 p
->parent
= mdoc
->last
->parent
;
478 case (MDOC_NEXT_CHILD
):
479 mdoc
->last
->child
= p
;
480 p
->parent
= mdoc
->last
;
488 if ( ! mdoc_valid_pre(mdoc
, p
))
493 assert(MDOC_BLOCK
== p
->parent
->type
);
494 p
->parent
->data
.block
.head
= p
;
497 assert(MDOC_BLOCK
== p
->parent
->type
);
498 p
->parent
->data
.block
.tail
= p
;
501 assert(MDOC_BLOCK
== p
->parent
->type
);
502 p
->parent
->data
.block
.body
= p
;
509 mdoc_msg(mdoc
, "parse: %s `%s' %s of %s `%s'",
510 nt
, nn
, act
, ot
, on
);
515 static struct mdoc_node
*
516 mdoc_node_alloc(const struct mdoc
*mdoc
)
520 p
= xcalloc(1, sizeof(struct mdoc_node
));
521 p
->sec
= mdoc
->lastsec
;
528 mdoc_tail_alloc(struct mdoc
*mdoc
, int line
, int pos
, int tok
)
535 p
= mdoc_node_alloc(mdoc
);
542 return(mdoc_node_append(mdoc
, p
));
547 mdoc_head_alloc(struct mdoc
*mdoc
, int line
, int pos
, int tok
)
554 p
= mdoc_node_alloc(mdoc
);
561 return(mdoc_node_append(mdoc
, p
));
566 mdoc_body_alloc(struct mdoc
*mdoc
, int line
, int pos
, int tok
)
573 p
= mdoc_node_alloc(mdoc
);
580 return(mdoc_node_append(mdoc
, p
));
585 mdoc_root_alloc(struct mdoc
*mdoc
)
589 p
= mdoc_node_alloc(mdoc
);
593 return(mdoc_node_append(mdoc
, p
));
598 mdoc_block_alloc(struct mdoc
*mdoc
, int line
, int pos
,
599 int tok
, size_t argsz
, const struct mdoc_arg
*args
)
603 p
= mdoc_node_alloc(mdoc
);
607 p
->type
= MDOC_BLOCK
;
609 p
->data
.block
.argc
= argsz
;
610 p
->data
.block
.argv
= argdup(argsz
, args
);
612 return(mdoc_node_append(mdoc
, p
));
617 mdoc_elem_alloc(struct mdoc
*mdoc
, int line
, int pos
,
618 int tok
, size_t argsz
, const struct mdoc_arg
*args
)
622 p
= mdoc_node_alloc(mdoc
);
628 p
->data
.elem
.argc
= argsz
;
629 p
->data
.elem
.argv
= argdup(argsz
, args
);
631 return(mdoc_node_append(mdoc
, p
));
636 mdoc_word_alloc(struct mdoc
*mdoc
,
637 int line
, int pos
, const char *word
)
641 p
= mdoc_node_alloc(mdoc
);
646 p
->data
.text
.string
= xstrdup(word
);
648 return(mdoc_node_append(mdoc
, p
));
653 argfree(size_t sz
, struct mdoc_arg
*p
)
662 for (i
= 0; i
< (int)sz
; i
++)
666 for (j
= 0; j
< (int)p
[i
].sz
; j
++)
675 mdoc_elem_free(struct mdoc_elem
*p
)
678 argfree(p
->argc
, p
->argv
);
683 mdoc_block_free(struct mdoc_block
*p
)
686 argfree(p
->argc
, p
->argv
);
691 mdoc_text_free(struct mdoc_text
*p
)
700 mdoc_node_free(struct mdoc_node
*p
)
705 mdoc_text_free(&p
->data
.text
);
708 mdoc_elem_free(&p
->data
.elem
);
711 mdoc_block_free(&p
->data
.block
);
722 mdoc_node_freelist(struct mdoc_node
*p
)
726 mdoc_node_freelist(p
->child
);
728 mdoc_node_freelist(p
->next
);
735 mdoc_find(const struct mdoc
*mdoc
, const char *key
)
738 return(mdoc_tokhash_find(mdoc
->htab
, key
));
743 argcpy(struct mdoc_arg
*dst
, const struct mdoc_arg
*src
)
747 dst
->line
= src
->line
;
750 if (0 == (dst
->sz
= src
->sz
))
752 dst
->value
= xcalloc(dst
->sz
, sizeof(char *));
753 for (i
= 0; i
< (int)dst
->sz
; i
++)
754 dst
->value
[i
] = xstrdup(src
->value
[i
]);
758 static struct mdoc_arg
*
759 argdup(size_t argsz
, const struct mdoc_arg
*args
)
767 pp
= xcalloc((size_t)argsz
, sizeof(struct mdoc_arg
));
768 for (i
= 0; i
< (int)argsz
; i
++)
769 argcpy(&pp
[i
], &args
[i
]);
775 /* FIXME: deprecate. */
777 mdoc_node2a(struct mdoc_node
*node
)
784 (void)xstrlcat(buf
, mdoc_type2a(node
->type
), 64);
785 if (MDOC_ROOT
== node
->type
)
787 (void)xstrlcat(buf
, " `", 64);
788 if (MDOC_TEXT
== node
->type
)
789 (void)xstrlcat(buf
, node
->data
.text
.string
, 64);
791 (void)xstrlcat(buf
, mdoc_macronames
[node
->tok
], 64);
792 (void)xstrlcat(buf
, "'", 64);