]>
git.cameronkatri.com Git - mandoc.git/blob - mdoc.c
1 /* $Id: mdoc.c,v 1.2 2008/12/15 02:23:12 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.
29 extern int macro_text(struct mdoc
*, int, int, int *, char *);
30 extern int macro_scoped_implicit(struct mdoc
*,
31 int, int, int *, char *);
33 const char *const __mdoc_macronames
[MDOC_MAX
] = {
34 "\\\"", "Dd", "Dt", "Os",
35 "Sh", "Ss", "Pp", "D1",
36 "Dl", "Bd", "Ed", "Bl",
37 "El", "It", "Ad", "An",
38 "Ar", "Cd", "Cm", "Dv",
39 "Er", "Ev", "Ex", "Fa",
40 "Fd", "Fl", "Fn", "Ft",
41 "Ic", "In", "Li", "Nd",
42 "Nm", "Op", "Ot", "Pa",
43 "Rv", "St", "Va", "Vt",
45 "Xr", "\%A", "\%B", "\%D",
47 "\%I", "\%J", "\%N", "\%O",
49 "\%P", "\%R", "\%T", "\%V",
50 "Ac", "Ao", "Aq", "At",
51 "Bc", "Bf", "Bo", "Bq",
52 "Bsx", "Bx", "Db", "Dc",
53 "Do", "Dq", "Ec", "Ef",
54 "Em", "Eo", "Fx", "Ms",
55 "No", "Ns", "Nx", "Ox",
56 "Pc", "Pf", "Po", "Pq",
57 "Qc", "Ql", "Qo", "Qq",
58 "Re", "Rs", "Sc", "So",
59 "Sq", "Sm", "Sx", "Sy",
60 "Tn", "Ux", "Xc", "Xo",
61 "Fo", "Fc", "Oo", "Oc",
62 "Bk", "Ek", "Bt", "Hf",
66 const char *const __mdoc_argnames
[MDOC_ARG_MAX
] = {
67 "split", "nosplit", "ragged",
68 "unfilled", "literal", "file",
69 "offset", "bullet", "dash",
70 "hyphen", "item", "enum",
71 "tag", "diag", "hang",
72 "ohang", "inset", "column",
73 "width", "compact", "std",
74 "p1003.1-88", "p1003.1-90", "p1003.1-96",
75 "p1003.1-2001", "p1003.1-2004", "p1003.1",
76 "p1003.1b", "p1003.1b-93", "p1003.1c-95",
77 "p1003.1g-2000", "p1003.2-92", "p1387.2-95",
78 "p1003.2", "p1387.2", "isoC-90",
79 "isoC-amd1", "isoC-tcor1", "isoC-tcor2",
80 "isoC-99", "ansiC", "ansiC-89",
81 "ansiC-99", "ieee754", "iso8802-3",
82 "xpg3", "xpg4", "xpg4.2",
83 "xpg4.3", "xbd5", "xcu5",
84 "xsh5", "xns5", "xns5.2d2.0",
85 "xcurses4.2", "susv2", "susv3",
86 "svid4", "filled", "words",
89 const struct mdoc_macro __mdoc_macros
[MDOC_MAX
] = {
94 { macro_scoped_implicit
, 0 }, /* Sh */
95 { macro_scoped_implicit
, 0 }, /* Ss */
100 { NULL
, 0 }, /* Ed */
101 { NULL
, 0 }, /* Bl */
102 { NULL
, 0 }, /* El */
103 { NULL
, 0 }, /* It */
104 { macro_text
, MDOC_CALLABLE
}, /* Ad */
105 { NULL
, 0 }, /* An */
106 { macro_text
, MDOC_CALLABLE
}, /* Ar */
107 { NULL
, 0 }, /* Cd */
108 { macro_text
, MDOC_CALLABLE
}, /* Cm */
109 { macro_text
, MDOC_CALLABLE
}, /* Dv */
110 { macro_text
, MDOC_CALLABLE
}, /* Er */
111 { macro_text
, MDOC_CALLABLE
}, /* Ev */
112 { NULL
, 0 }, /* Ex */
113 { macro_text
, MDOC_CALLABLE
}, /* Fa */
114 { NULL
, 0 }, /* Fd */
115 { macro_text
, MDOC_CALLABLE
}, /* Fl */
116 { NULL
, 0 }, /* Fn */
117 { macro_text
, 0 }, /* Ft */
118 { macro_text
, MDOC_CALLABLE
}, /* Ic */
119 { NULL
, 0 }, /* In */
120 { macro_text
, MDOC_CALLABLE
}, /* Li */
121 { NULL
, 0 }, /* Nd */
122 { NULL
, 0 }, /* Nm */
123 { NULL
, 0 }, /* Op */
124 { NULL
, 0 }, /* Ot */
125 { macro_text
, MDOC_CALLABLE
}, /* Pa */
126 { NULL
, 0 }, /* Rv */
127 { NULL
, 0 }, /* St */
128 { macro_text
, MDOC_CALLABLE
}, /* Va */
129 { macro_text
, MDOC_CALLABLE
}, /* Vt */
130 { NULL
, 0 }, /* Xr */
131 { NULL
, 0 }, /* %A */
132 { NULL
, 0 }, /* %B */
133 { NULL
, 0 }, /* %D */
134 { NULL
, 0 }, /* %I */
135 { NULL
, 0 }, /* %J */
136 { NULL
, 0 }, /* %N */
137 { NULL
, 0 }, /* %O */
138 { NULL
, 0 }, /* %P */
139 { NULL
, 0 }, /* %R */
140 { NULL
, 0 }, /* %T */
141 { NULL
, 0 }, /* %V */
142 { NULL
, 0 }, /* Ac */
143 { NULL
, 0 }, /* Ao */
144 { NULL
, 0 }, /* Aq */
145 { NULL
, 0 }, /* At */
146 { NULL
, 0 }, /* Bc */
147 { NULL
, 0 }, /* Bf */
148 { NULL
, 0 }, /* Bo */
149 { NULL
, 0 }, /* Bq */
150 { NULL
, 0 }, /* Bsx */
151 { NULL
, 0 }, /* Bx */
152 { NULL
, 0 }, /* Db */
153 { NULL
, 0 }, /* Dc */
154 { NULL
, 0 }, /* Do */
155 { NULL
, 0 }, /* Dq */
156 { NULL
, 0 }, /* Ec */
157 { NULL
, 0 }, /* Ef */
158 { macro_text
, MDOC_CALLABLE
}, /* Em */
159 { NULL
, 0 }, /* Eo */
160 { NULL
, 0 }, /* Fx */
161 { macro_text
, 0 }, /* Ms */
162 { NULL
, 0 }, /* No */
163 { NULL
, 0 }, /* Ns */
164 { NULL
, 0 }, /* Nx */
165 { NULL
, 0 }, /* Ox */
166 { NULL
, 0 }, /* Pc */
167 { NULL
, 0 }, /* Pf */
168 { NULL
, 0 }, /* Po */
169 { NULL
, 0 }, /* Pq */
170 { NULL
, 0 }, /* Qc */
171 { NULL
, 0 }, /* Ql */
172 { NULL
, 0 }, /* Qo */
173 { NULL
, 0 }, /* Qq */
174 { NULL
, 0 }, /* Re */
175 { NULL
, 0 }, /* Rs */
176 { NULL
, 0 }, /* Sc */
177 { NULL
, 0 }, /* So */
178 { NULL
, 0 }, /* Sq */
179 { NULL
, 0 }, /* Sm */
180 { NULL
, 0 }, /* Sx */
181 { NULL
, 0 }, /* Sy */
182 { macro_text
, MDOC_CALLABLE
}, /* Tn */
183 { NULL
, 0 }, /* Ux */
184 { NULL
, 0 }, /* Xc */
185 { NULL
, 0 }, /* Xo */
186 { NULL
, 0 }, /* Fo */
187 { NULL
, 0 }, /* Fc */
188 { NULL
, 0 }, /* Oo */
189 { NULL
, 0 }, /* Oc */
190 { NULL
, 0 }, /* Bk */
191 { NULL
, 0 }, /* Ek */
192 { NULL
, 0 }, /* Bt */
193 { NULL
, 0 }, /* Hf */
194 { NULL
, 0 }, /* Fr */
195 { NULL
, 0 }, /* Ud */
198 const char * const *mdoc_macronames
= __mdoc_macronames
;
199 const char * const *mdoc_argnames
= __mdoc_argnames
;
200 const struct mdoc_macro
* const mdoc_macros
= __mdoc_macros
;
203 static void *xcalloc(size_t, size_t);
204 static char *xstrdup(const char *);
206 static struct mdoc_arg
*argdup(size_t, const struct mdoc_arg
*);
207 static void argfree(size_t, struct mdoc_arg
*);
208 static void argcpy(struct mdoc_arg
*,
209 const struct mdoc_arg
*);
210 static char **paramdup(size_t, const char **);
211 static void paramfree(size_t, char **);
213 static void mdoc_node_freelist(struct mdoc_node
*);
214 static void mdoc_node_append(struct mdoc
*, int,
216 static void mdoc_elem_free(struct mdoc_elem
*);
217 static void mdoc_text_free(struct mdoc_text
*);
220 const struct mdoc_node
*
221 mdoc_result(struct mdoc
*mdoc
)
229 mdoc_free(struct mdoc
*mdoc
)
233 mdoc_node_freelist(mdoc
->first
);
235 mdoc_hash_free(mdoc
->htab
);
242 mdoc_alloc(void *data
, const struct mdoc_cb
*cb
)
246 p
= xcalloc(1, sizeof(struct mdoc
));
249 (void)memcpy(&p
->cb
, cb
, sizeof(struct mdoc_cb
));
251 p
->htab
= mdoc_hash_alloc();
257 xcalloc(size_t num
, size_t sz
)
261 if (NULL
== (p
= calloc(num
, sz
)))
262 err(EXIT_FAILURE
, "calloc");
268 xstrdup(const char *p
)
272 if (NULL
== (pp
= strdup(p
)))
273 err(EXIT_FAILURE
, "strdup");
279 mdoc_parseln(struct mdoc
*mdoc
, char *buf
)
289 if (buf
[1] && '\\' == buf
[1])
290 if (buf
[2] && '\"' == buf
[2])
294 while (buf
[i
] && ! isspace(buf
[i
]) && i
< (int)sizeof(tmp
))
297 if (i
== (int)sizeof(tmp
))
298 return(mdoc_err(mdoc
, -1, 1, ERR_MACRO_NOTSUP
));
300 return(mdoc_err(mdoc
, -1, 1, ERR_MACRO_NOTSUP
));
304 (void)memcpy(tmp
, buf
+ 1, (size_t)i
);
307 if (MDOC_MAX
== (c
= mdoc_find(mdoc
, tmp
)))
308 return(mdoc_err(mdoc
, c
, 1, ERR_MACRO_NOTSUP
));
310 while (buf
[i
] && isspace(buf
[i
]))
313 if (NULL
== (mdoc_macros
[c
].fp
)) {
314 (void)mdoc_err(mdoc
, c
, 1, ERR_MACRO_NOTSUP
);
318 return((*mdoc_macros
[c
].fp
)(mdoc
, c
, 1, &i
, buf
));
323 mdoc_msg(struct mdoc
*mdoc
, int pos
, const char *fmt
, ...)
328 if (NULL
== mdoc
->cb
.mdoc_msg
)
332 (void)vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
335 (*mdoc
->cb
.mdoc_msg
)(mdoc
->data
, pos
, buf
);
340 mdoc_err(struct mdoc
*mdoc
, int tok
, int pos
, enum mdoc_err type
)
343 if (NULL
== mdoc
->cb
.mdoc_err
)
345 return((*mdoc
->cb
.mdoc_err
)(mdoc
->data
, tok
, pos
, type
));
350 mdoc_warn(struct mdoc
*mdoc
, int tok
, int pos
, enum mdoc_warn type
)
353 if (NULL
== mdoc
->cb
.mdoc_warn
)
355 return((*mdoc
->cb
.mdoc_warn
)(mdoc
->data
, tok
, pos
, type
));
360 mdoc_macro(struct mdoc
*mdoc
, int tok
, int ppos
, int *pos
, char *buf
)
363 if (NULL
== (mdoc_macros
[tok
].fp
)) {
364 (void)mdoc_err(mdoc
, tok
, ppos
, ERR_MACRO_NOTSUP
);
366 } else if ( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
)) {
367 (void)mdoc_err(mdoc
, tok
, ppos
, ERR_MACRO_NOTCALL
);
371 return((*mdoc_macros
[tok
].fp
)(mdoc
, tok
, ppos
, pos
, buf
));
376 mdoc_node_append(struct mdoc
*mdoc
, int pos
, struct mdoc_node
*p
)
378 const char *nn
, *on
, *nt
, *ot
, *act
;
386 nn
= mdoc_macronames
[p
->data
.body
.tok
];
390 nn
= mdoc_macronames
[p
->data
.elem
.tok
];
394 nn
= mdoc_macronames
[p
->data
.head
.tok
];
398 nn
= mdoc_macronames
[p
->data
.block
.tok
];
406 if (NULL
== mdoc
->first
) {
407 assert(NULL
== mdoc
->last
);
410 mdoc_msg(mdoc
, pos
, "parse: root %s `%s'", nt
, nn
);
414 switch (mdoc
->last
->type
) {
420 on
= mdoc_macronames
[mdoc
->last
->data
.body
.tok
];
424 on
= mdoc_macronames
[mdoc
->last
->data
.elem
.tok
];
428 on
= mdoc_macronames
[mdoc
->last
->data
.head
.tok
];
432 on
= mdoc_macronames
[mdoc
->last
->data
.block
.tok
];
442 switch (mdoc
->last
->type
) {
444 p
->parent
= mdoc
->last
;
445 mdoc
->last
->child
= p
;
449 p
->parent
= mdoc
->last
->parent
;
450 mdoc
->last
->next
= p
;
459 assert(mdoc
->last
->type
== MDOC_BLOCK
);
460 p
->parent
= mdoc
->last
;
461 mdoc
->last
->child
= p
;
465 switch (mdoc
->last
->type
) {
469 p
->parent
= mdoc
->last
->parent
;
470 mdoc
->last
->child
= p
;
474 p
->parent
= mdoc
->last
->parent
;
475 mdoc
->last
->next
= p
;
482 mdoc_msg(mdoc
, pos
, "parse: %s `%s' %s %s `%s'",
483 nt
, nn
, act
, ot
, on
);
489 mdoc_head_alloc(struct mdoc
*mdoc
, int pos
, int tok
,
490 size_t paramsz
, const char **params
)
496 assert(mdoc
->last
->type
== MDOC_BLOCK
);
497 assert(mdoc
->last
->data
.block
.tok
== tok
);
499 p
= xcalloc(1, sizeof(struct mdoc_node
));
501 p
->data
.head
.tok
= tok
;
502 p
->data
.head
.sz
= paramsz
;
503 p
->data
.head
.args
= paramdup(paramsz
, params
);
505 mdoc_node_append(mdoc
, pos
, p
);
510 mdoc_body_alloc(struct mdoc
*mdoc
, int pos
, int tok
)
516 assert((mdoc
->last
->type
== MDOC_BLOCK
) ||
517 (mdoc
->last
->type
== MDOC_HEAD
));
518 if (mdoc
->last
->type
== MDOC_BLOCK
)
519 assert(mdoc
->last
->data
.block
.tok
== tok
);
521 assert(mdoc
->last
->data
.head
.tok
== tok
);
523 p
= xcalloc(1, sizeof(struct mdoc_node
));
526 p
->data
.body
.tok
= tok
;
528 mdoc_node_append(mdoc
, pos
, p
);
533 mdoc_block_alloc(struct mdoc
*mdoc
, int pos
, int tok
,
534 size_t argsz
, const struct mdoc_arg
*args
)
538 p
= xcalloc(1, sizeof(struct mdoc_node
));
540 p
->type
= MDOC_BLOCK
;
541 p
->data
.block
.tok
= tok
;
542 p
->data
.block
.argc
= argsz
;
543 p
->data
.block
.argv
= argdup(argsz
, args
);
545 mdoc_node_append(mdoc
, pos
, p
);
550 mdoc_elem_alloc(struct mdoc
*mdoc
, int pos
, int tok
,
551 size_t argsz
, const struct mdoc_arg
*args
,
552 size_t paramsz
, const char **params
)
556 p
= xcalloc(1, sizeof(struct mdoc_node
));
558 p
->data
.elem
.tok
= tok
;
559 p
->data
.elem
.sz
= paramsz
;
560 p
->data
.elem
.args
= paramdup(paramsz
, params
);
561 p
->data
.elem
.argc
= argsz
;
562 p
->data
.elem
.argv
= argdup(argsz
, args
);
564 mdoc_node_append(mdoc
, pos
, p
);
569 mdoc_word_alloc(struct mdoc
*mdoc
, int pos
, const char *word
)
573 p
= xcalloc(1, sizeof(struct mdoc_node
));
575 p
->data
.text
.string
= xstrdup(word
);
577 mdoc_node_append(mdoc
, pos
, p
);
582 argfree(size_t sz
, struct mdoc_arg
*p
)
591 for (i
= 0; i
< (int)sz
; i
++)
595 for (j
= 0; j
< (int)p
[i
].sz
; j
++)
603 mdoc_elem_free(struct mdoc_elem
*p
)
606 paramfree(p
->sz
, p
->args
);
607 argfree(p
->argc
, p
->argv
);
612 mdoc_block_free(struct mdoc_block
*p
)
615 argfree(p
->argc
, p
->argv
);
620 mdoc_text_free(struct mdoc_text
*p
)
629 mdoc_head_free(struct mdoc_head
*p
)
632 paramfree(p
->sz
, p
->args
);
637 mdoc_node_free(struct mdoc_node
*p
)
642 mdoc_text_free(&p
->data
.text
);
645 mdoc_elem_free(&p
->data
.elem
);
648 mdoc_block_free(&p
->data
.block
);
651 mdoc_head_free(&p
->data
.head
);
662 mdoc_node_freelist(struct mdoc_node
*p
)
666 mdoc_node_freelist(p
->child
);
668 mdoc_node_freelist(p
->next
);
675 mdoc_find(const struct mdoc
*mdoc
, const char *key
)
678 return(mdoc_hash_find(mdoc
->htab
, key
));
683 argcpy(struct mdoc_arg
*dst
, const struct mdoc_arg
*src
)
688 if (0 == (dst
->sz
= src
->sz
))
690 dst
->value
= xcalloc(dst
->sz
, sizeof(char *));
691 for (i
= 0; i
< (int)dst
->sz
; i
++)
692 dst
->value
[i
] = xstrdup(src
->value
[i
]);
696 static struct mdoc_arg
*
697 argdup(size_t argsz
, const struct mdoc_arg
*args
)
705 pp
= xcalloc((size_t)argsz
, sizeof(struct mdoc_arg
));
706 for (i
= 0; i
< (int)argsz
; i
++)
707 argcpy(&pp
[i
], &args
[i
]);
714 paramfree(size_t sz
, char **p
)
723 for (i
= 0; i
< (int)sz
; i
++)
730 paramdup(size_t sz
, const char **p
)
738 pp
= xcalloc(sz
, sizeof(char *));
739 for (i
= 0; i
< (int)sz
; i
++)
740 pp
[i
] = xstrdup(p
[i
]);