man_validate.c revision 1.1.1.13.2.2 1 1.1.1.13.2.2 yamt /* Id: man_validate.c,v 1.87 2013/12/31 18:07:42 schwarze Exp */
2 1.1 joerg /*
3 1.1.1.12 joerg * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps (at) bsd.lv>
4 1.1.1.13.2.2 yamt * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze (at) openbsd.org>
5 1.1 joerg *
6 1.1 joerg * Permission to use, copy, modify, and distribute this software for any
7 1.1 joerg * purpose with or without fee is hereby granted, provided that the above
8 1.1 joerg * copyright notice and this permission notice appear in all copies.
9 1.1 joerg *
10 1.1 joerg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 1.1 joerg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 1.1 joerg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 1.1 joerg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 1.1 joerg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 1.1 joerg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 1.1 joerg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 1.1 joerg */
18 1.1.1.4 joerg #ifdef HAVE_CONFIG_H
19 1.1.1.4 joerg #include "config.h"
20 1.1.1.4 joerg #endif
21 1.1.1.4 joerg
22 1.1 joerg #include <sys/types.h>
23 1.1 joerg
24 1.1 joerg #include <assert.h>
25 1.1 joerg #include <ctype.h>
26 1.1 joerg #include <errno.h>
27 1.1 joerg #include <limits.h>
28 1.1 joerg #include <stdarg.h>
29 1.1 joerg #include <stdlib.h>
30 1.1.1.10 joerg #include <string.h>
31 1.1.1.11 joerg #include <time.h>
32 1.1 joerg
33 1.1.1.12 joerg #include "man.h"
34 1.1.1.7 joerg #include "mandoc.h"
35 1.1 joerg #include "libman.h"
36 1.1 joerg #include "libmandoc.h"
37 1.1 joerg
38 1.1.1.13.2.2 yamt #define CHKARGS struct man *man, struct man_node *n
39 1.1 joerg
40 1.1 joerg typedef int (*v_check)(CHKARGS);
41 1.1 joerg
42 1.1 joerg struct man_valid {
43 1.1 joerg v_check *pres;
44 1.1 joerg v_check *posts;
45 1.1 joerg };
46 1.1 joerg
47 1.1 joerg static int check_eq0(CHKARGS);
48 1.1.1.13.2.1 yamt static int check_eq2(CHKARGS);
49 1.1 joerg static int check_le1(CHKARGS);
50 1.1 joerg static int check_ge2(CHKARGS);
51 1.1 joerg static int check_le5(CHKARGS);
52 1.1.1.13.2.2 yamt static int check_head1(CHKARGS);
53 1.1 joerg static int check_par(CHKARGS);
54 1.1 joerg static int check_part(CHKARGS);
55 1.1 joerg static int check_root(CHKARGS);
56 1.1.1.13 joerg static void check_text(CHKARGS);
57 1.1 joerg
58 1.1.1.11 joerg static int post_AT(CHKARGS);
59 1.1.1.13.2.2 yamt static int post_IP(CHKARGS);
60 1.1.1.13 joerg static int post_vs(CHKARGS);
61 1.1.1.11 joerg static int post_fi(CHKARGS);
62 1.1.1.13 joerg static int post_ft(CHKARGS);
63 1.1.1.11 joerg static int post_nf(CHKARGS);
64 1.1.1.13 joerg static int post_sec(CHKARGS);
65 1.1.1.11 joerg static int post_TH(CHKARGS);
66 1.1.1.11 joerg static int post_UC(CHKARGS);
67 1.1.1.13 joerg static int pre_sec(CHKARGS);
68 1.1.1.11 joerg
69 1.1.1.11 joerg static v_check posts_at[] = { post_AT, NULL };
70 1.1.1.13 joerg static v_check posts_br[] = { post_vs, check_eq0, NULL };
71 1.1 joerg static v_check posts_eq0[] = { check_eq0, NULL };
72 1.1.1.13.2.1 yamt static v_check posts_eq2[] = { check_eq2, NULL };
73 1.1.1.11 joerg static v_check posts_fi[] = { check_eq0, post_fi, NULL };
74 1.1.1.13 joerg static v_check posts_ft[] = { post_ft, NULL };
75 1.1.1.13.2.2 yamt static v_check posts_ip[] = { post_IP, NULL };
76 1.1.1.13.2.2 yamt static v_check posts_le1[] = { check_le1, NULL };
77 1.1.1.11 joerg static v_check posts_nf[] = { check_eq0, post_nf, NULL };
78 1.1 joerg static v_check posts_par[] = { check_par, NULL };
79 1.1 joerg static v_check posts_part[] = { check_part, NULL };
80 1.1.1.13 joerg static v_check posts_sec[] = { post_sec, NULL };
81 1.1.1.13 joerg static v_check posts_sp[] = { post_vs, check_le1, NULL };
82 1.1.1.12 joerg static v_check posts_th[] = { check_ge2, check_le5, post_TH, NULL };
83 1.1.1.11 joerg static v_check posts_uc[] = { post_UC, NULL };
84 1.1.1.13.2.2 yamt static v_check posts_ur[] = { check_head1, check_part, NULL };
85 1.1.1.13.2.1 yamt static v_check pres_sec[] = { pre_sec, NULL };
86 1.1.1.11 joerg
87 1.1 joerg static const struct man_valid man_valids[MAN_MAX] = {
88 1.1.1.13 joerg { NULL, posts_br }, /* br */
89 1.1.1.13.2.1 yamt { NULL, posts_th }, /* TH */
90 1.1.1.13 joerg { pres_sec, posts_sec }, /* SH */
91 1.1.1.13 joerg { pres_sec, posts_sec }, /* SS */
92 1.1.1.13.2.1 yamt { NULL, NULL }, /* TP */
93 1.1.1.13.2.1 yamt { NULL, posts_par }, /* LP */
94 1.1.1.13.2.1 yamt { NULL, posts_par }, /* PP */
95 1.1.1.13.2.1 yamt { NULL, posts_par }, /* P */
96 1.1.1.13.2.2 yamt { NULL, posts_ip }, /* IP */
97 1.1.1.13.2.1 yamt { NULL, NULL }, /* HP */
98 1.1 joerg { NULL, NULL }, /* SM */
99 1.1 joerg { NULL, NULL }, /* SB */
100 1.1 joerg { NULL, NULL }, /* BI */
101 1.1 joerg { NULL, NULL }, /* IB */
102 1.1 joerg { NULL, NULL }, /* BR */
103 1.1 joerg { NULL, NULL }, /* RB */
104 1.1 joerg { NULL, NULL }, /* R */
105 1.1 joerg { NULL, NULL }, /* B */
106 1.1 joerg { NULL, NULL }, /* I */
107 1.1 joerg { NULL, NULL }, /* IR */
108 1.1 joerg { NULL, NULL }, /* RI */
109 1.1.1.13.2.1 yamt { NULL, posts_eq0 }, /* na */
110 1.1.1.13.2.1 yamt { NULL, posts_sp }, /* sp */
111 1.1.1.13.2.1 yamt { NULL, posts_nf }, /* nf */
112 1.1.1.13.2.1 yamt { NULL, posts_fi }, /* fi */
113 1.1 joerg { NULL, NULL }, /* RE */
114 1.1 joerg { NULL, posts_part }, /* RS */
115 1.1 joerg { NULL, NULL }, /* DT */
116 1.1.1.11 joerg { NULL, posts_uc }, /* UC */
117 1.1.1.13.2.2 yamt { NULL, posts_le1 }, /* PD */
118 1.1.1.11 joerg { NULL, posts_at }, /* AT */
119 1.1.1.10 joerg { NULL, NULL }, /* in */
120 1.1.1.11 joerg { NULL, posts_ft }, /* ft */
121 1.1.1.13.2.1 yamt { NULL, posts_eq2 }, /* OP */
122 1.1.1.13.2.2 yamt { NULL, posts_nf }, /* EX */
123 1.1.1.13.2.2 yamt { NULL, posts_fi }, /* EE */
124 1.1.1.13.2.2 yamt { NULL, posts_ur }, /* UR */
125 1.1.1.13.2.2 yamt { NULL, NULL }, /* UE */
126 1.1 joerg };
127 1.1 joerg
128 1.1 joerg
129 1.1 joerg int
130 1.1.1.13.2.2 yamt man_valid_pre(struct man *man, struct man_node *n)
131 1.1 joerg {
132 1.1 joerg v_check *cp;
133 1.1 joerg
134 1.1.1.11 joerg switch (n->type) {
135 1.1.1.11 joerg case (MAN_TEXT):
136 1.1.1.11 joerg /* FALLTHROUGH */
137 1.1.1.11 joerg case (MAN_ROOT):
138 1.1.1.11 joerg /* FALLTHROUGH */
139 1.1.1.12 joerg case (MAN_EQN):
140 1.1.1.12 joerg /* FALLTHROUGH */
141 1.1.1.11 joerg case (MAN_TBL):
142 1.1 joerg return(1);
143 1.1.1.11 joerg default:
144 1.1.1.11 joerg break;
145 1.1.1.11 joerg }
146 1.1 joerg
147 1.1 joerg if (NULL == (cp = man_valids[n->tok].pres))
148 1.1 joerg return(1);
149 1.1 joerg for ( ; *cp; cp++)
150 1.1.1.13.2.2 yamt if ( ! (*cp)(man, n))
151 1.1 joerg return(0);
152 1.1 joerg return(1);
153 1.1 joerg }
154 1.1 joerg
155 1.1 joerg
156 1.1 joerg int
157 1.1.1.13.2.2 yamt man_valid_post(struct man *man)
158 1.1 joerg {
159 1.1 joerg v_check *cp;
160 1.1 joerg
161 1.1.1.13.2.2 yamt if (MAN_VALID & man->last->flags)
162 1.1 joerg return(1);
163 1.1.1.13.2.2 yamt man->last->flags |= MAN_VALID;
164 1.1 joerg
165 1.1.1.13.2.2 yamt switch (man->last->type) {
166 1.1 joerg case (MAN_TEXT):
167 1.1.1.13.2.2 yamt check_text(man, man->last);
168 1.1.1.13 joerg return(1);
169 1.1 joerg case (MAN_ROOT):
170 1.1.1.13.2.2 yamt return(check_root(man, man->last));
171 1.1.1.12 joerg case (MAN_EQN):
172 1.1.1.12 joerg /* FALLTHROUGH */
173 1.1.1.11 joerg case (MAN_TBL):
174 1.1.1.11 joerg return(1);
175 1.1 joerg default:
176 1.1 joerg break;
177 1.1 joerg }
178 1.1 joerg
179 1.1.1.13.2.2 yamt if (NULL == (cp = man_valids[man->last->tok].posts))
180 1.1 joerg return(1);
181 1.1 joerg for ( ; *cp; cp++)
182 1.1.1.13.2.2 yamt if ( ! (*cp)(man, man->last))
183 1.1 joerg return(0);
184 1.1 joerg
185 1.1 joerg return(1);
186 1.1 joerg }
187 1.1 joerg
188 1.1 joerg
189 1.1 joerg static int
190 1.1 joerg check_root(CHKARGS)
191 1.1 joerg {
192 1.1 joerg
193 1.1.1.13.2.2 yamt if (MAN_BLINE & man->flags)
194 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_SCOPEEXIT);
195 1.1.1.13.2.2 yamt else if (MAN_ELINE & man->flags)
196 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_SCOPEEXIT);
197 1.1 joerg
198 1.1.1.13.2.2 yamt man->flags &= ~MAN_BLINE;
199 1.1.1.13.2.2 yamt man->flags &= ~MAN_ELINE;
200 1.1 joerg
201 1.1.1.13.2.2 yamt if (NULL == man->first->child) {
202 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_NODOCBODY);
203 1.1.1.7 joerg return(0);
204 1.1.1.13.2.2 yamt } else if (NULL == man->meta.title) {
205 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_NOTITLE);
206 1.1.1.11 joerg
207 1.1.1.6 joerg /*
208 1.1.1.6 joerg * If a title hasn't been set, do so now (by
209 1.1.1.6 joerg * implication, date and section also aren't set).
210 1.1.1.6 joerg */
211 1.1.1.11 joerg
212 1.1.1.13.2.2 yamt man->meta.title = mandoc_strdup("unknown");
213 1.1.1.13.2.2 yamt man->meta.msec = mandoc_strdup("1");
214 1.1.1.13.2.2 yamt man->meta.date = mandoc_normdate
215 1.1.1.13.2.2 yamt (man->parse, NULL, n->line, n->pos);
216 1.1.1.6 joerg }
217 1.1 joerg
218 1.1 joerg return(1);
219 1.1 joerg }
220 1.1 joerg
221 1.1.1.13 joerg static void
222 1.1.1.13 joerg check_text(CHKARGS)
223 1.1 joerg {
224 1.1.1.13 joerg char *cp, *p;
225 1.1 joerg
226 1.1.1.13.2.2 yamt if (MAN_LITERAL & man->flags)
227 1.1.1.13.2.1 yamt return;
228 1.1.1.13.2.1 yamt
229 1.1.1.13.2.1 yamt cp = n->string;
230 1.1.1.13.2.1 yamt for (p = cp; NULL != (p = strchr(p, '\t')); p++)
231 1.1.1.13.2.2 yamt man_pmsg(man, n->line, (int)(p - cp), MANDOCERR_BADTAB);
232 1.1 joerg }
233 1.1 joerg
234 1.1 joerg #define INEQ_DEFINE(x, ineq, name) \
235 1.1 joerg static int \
236 1.1 joerg check_##name(CHKARGS) \
237 1.1 joerg { \
238 1.1 joerg if (n->nchild ineq (x)) \
239 1.1 joerg return(1); \
240 1.1.1.13.2.2 yamt mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line, n->pos, \
241 1.1.1.7 joerg "line arguments %s %d (have %d)", \
242 1.1.1.7 joerg #ineq, (x), n->nchild); \
243 1.1.1.12 joerg return(1); \
244 1.1 joerg }
245 1.1 joerg
246 1.1 joerg INEQ_DEFINE(0, ==, eq0)
247 1.1.1.13.2.1 yamt INEQ_DEFINE(2, ==, eq2)
248 1.1 joerg INEQ_DEFINE(1, <=, le1)
249 1.1 joerg INEQ_DEFINE(2, >=, ge2)
250 1.1 joerg INEQ_DEFINE(5, <=, le5)
251 1.1 joerg
252 1.1.1.11 joerg static int
253 1.1.1.13.2.2 yamt check_head1(CHKARGS)
254 1.1.1.13.2.2 yamt {
255 1.1.1.13.2.2 yamt
256 1.1.1.13.2.2 yamt if (MAN_HEAD == n->type && 1 != n->nchild)
257 1.1.1.13.2.2 yamt mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
258 1.1.1.13.2.2 yamt n->pos, "line arguments eq 1 (have %d)", n->nchild);
259 1.1.1.13.2.2 yamt
260 1.1.1.13.2.2 yamt return(1);
261 1.1.1.13.2.2 yamt }
262 1.1.1.13.2.2 yamt
263 1.1.1.13.2.2 yamt static int
264 1.1.1.13 joerg post_ft(CHKARGS)
265 1.1.1.11 joerg {
266 1.1.1.11 joerg char *cp;
267 1.1.1.11 joerg int ok;
268 1.1.1.11 joerg
269 1.1.1.11 joerg if (0 == n->nchild)
270 1.1.1.11 joerg return(1);
271 1.1.1.11 joerg
272 1.1.1.11 joerg ok = 0;
273 1.1.1.11 joerg cp = n->child->string;
274 1.1.1.11 joerg switch (*cp) {
275 1.1.1.11 joerg case ('1'):
276 1.1.1.11 joerg /* FALLTHROUGH */
277 1.1.1.11 joerg case ('2'):
278 1.1.1.11 joerg /* FALLTHROUGH */
279 1.1.1.11 joerg case ('3'):
280 1.1.1.11 joerg /* FALLTHROUGH */
281 1.1.1.11 joerg case ('4'):
282 1.1.1.11 joerg /* FALLTHROUGH */
283 1.1.1.11 joerg case ('I'):
284 1.1.1.11 joerg /* FALLTHROUGH */
285 1.1.1.11 joerg case ('P'):
286 1.1.1.11 joerg /* FALLTHROUGH */
287 1.1.1.11 joerg case ('R'):
288 1.1.1.11 joerg if ('\0' == cp[1])
289 1.1.1.11 joerg ok = 1;
290 1.1.1.11 joerg break;
291 1.1.1.11 joerg case ('B'):
292 1.1.1.11 joerg if ('\0' == cp[1] || ('I' == cp[1] && '\0' == cp[2]))
293 1.1.1.11 joerg ok = 1;
294 1.1.1.11 joerg break;
295 1.1.1.11 joerg case ('C'):
296 1.1.1.11 joerg if ('W' == cp[1] && '\0' == cp[2])
297 1.1.1.11 joerg ok = 1;
298 1.1.1.11 joerg break;
299 1.1.1.11 joerg default:
300 1.1.1.11 joerg break;
301 1.1.1.11 joerg }
302 1.1.1.11 joerg
303 1.1.1.11 joerg if (0 == ok) {
304 1.1.1.12 joerg mandoc_vmsg
305 1.1.1.13.2.2 yamt (MANDOCERR_BADFONT, man->parse,
306 1.1.1.12 joerg n->line, n->pos, "%s", cp);
307 1.1.1.11 joerg *cp = '\0';
308 1.1.1.11 joerg }
309 1.1.1.11 joerg
310 1.1.1.11 joerg if (1 < n->nchild)
311 1.1.1.12 joerg mandoc_vmsg
312 1.1.1.13.2.2 yamt (MANDOCERR_ARGCOUNT, man->parse, n->line,
313 1.1.1.12 joerg n->pos, "want one child (have %d)",
314 1.1.1.12 joerg n->nchild);
315 1.1.1.11 joerg
316 1.1.1.11 joerg return(1);
317 1.1.1.11 joerg }
318 1.1 joerg
319 1.1 joerg static int
320 1.1.1.13 joerg pre_sec(CHKARGS)
321 1.1 joerg {
322 1.1 joerg
323 1.1.1.13 joerg if (MAN_BLOCK == n->type)
324 1.1.1.13.2.2 yamt man->flags &= ~MAN_LITERAL;
325 1.1 joerg return(1);
326 1.1 joerg }
327 1.1 joerg
328 1.1.1.13 joerg static int
329 1.1.1.13 joerg post_sec(CHKARGS)
330 1.1.1.13 joerg {
331 1.1.1.13 joerg
332 1.1.1.13 joerg if ( ! (MAN_HEAD == n->type && 0 == n->nchild))
333 1.1.1.13 joerg return(1);
334 1.1.1.13 joerg
335 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_SYNTARGCOUNT);
336 1.1.1.13 joerg return(0);
337 1.1.1.13 joerg }
338 1.1 joerg
339 1.1 joerg static int
340 1.1 joerg check_part(CHKARGS)
341 1.1 joerg {
342 1.1 joerg
343 1.1 joerg if (MAN_BODY == n->type && 0 == n->nchild)
344 1.1.1.13.2.2 yamt mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line,
345 1.1.1.12 joerg n->pos, "want children (have none)");
346 1.1.1.11 joerg
347 1.1 joerg return(1);
348 1.1 joerg }
349 1.1 joerg
350 1.1 joerg
351 1.1 joerg static int
352 1.1 joerg check_par(CHKARGS)
353 1.1 joerg {
354 1.1 joerg
355 1.1.1.12 joerg switch (n->type) {
356 1.1.1.12 joerg case (MAN_BLOCK):
357 1.1.1.12 joerg if (0 == n->body->nchild)
358 1.1.1.13.2.2 yamt man_node_delete(man, n);
359 1.1.1.12 joerg break;
360 1.1.1.12 joerg case (MAN_BODY):
361 1.1.1.12 joerg if (0 == n->nchild)
362 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_IGNPAR);
363 1.1.1.12 joerg break;
364 1.1.1.12 joerg case (MAN_HEAD):
365 1.1.1.12 joerg if (n->nchild)
366 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_ARGSLOST);
367 1.1.1.12 joerg break;
368 1.1.1.12 joerg default:
369 1.1.1.12 joerg break;
370 1.1.1.12 joerg }
371 1.1 joerg
372 1.1 joerg return(1);
373 1.1 joerg }
374 1.1 joerg
375 1.1.1.13.2.2 yamt static int
376 1.1.1.13.2.2 yamt post_IP(CHKARGS)
377 1.1.1.13.2.2 yamt {
378 1.1.1.13.2.2 yamt
379 1.1.1.13.2.2 yamt switch (n->type) {
380 1.1.1.13.2.2 yamt case (MAN_BLOCK):
381 1.1.1.13.2.2 yamt if (0 == n->head->nchild && 0 == n->body->nchild)
382 1.1.1.13.2.2 yamt man_node_delete(man, n);
383 1.1.1.13.2.2 yamt break;
384 1.1.1.13.2.2 yamt case (MAN_BODY):
385 1.1.1.13.2.2 yamt if (0 == n->parent->head->nchild && 0 == n->nchild)
386 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_IGNPAR);
387 1.1.1.13.2.2 yamt break;
388 1.1.1.13.2.2 yamt default:
389 1.1.1.13.2.2 yamt break;
390 1.1.1.13.2.2 yamt }
391 1.1.1.13.2.2 yamt return(1);
392 1.1.1.13.2.2 yamt }
393 1.1 joerg
394 1.1 joerg static int
395 1.1.1.11 joerg post_TH(CHKARGS)
396 1.1.1.11 joerg {
397 1.1.1.12 joerg const char *p;
398 1.1.1.11 joerg
399 1.1.1.13.2.2 yamt free(man->meta.title);
400 1.1.1.13.2.2 yamt free(man->meta.vol);
401 1.1.1.13.2.2 yamt free(man->meta.source);
402 1.1.1.13.2.2 yamt free(man->meta.msec);
403 1.1.1.13.2.2 yamt free(man->meta.date);
404 1.1.1.13.2.2 yamt
405 1.1.1.13.2.2 yamt man->meta.title = man->meta.vol = man->meta.date =
406 1.1.1.13.2.2 yamt man->meta.msec = man->meta.source = NULL;
407 1.1.1.11 joerg
408 1.1.1.11 joerg /* ->TITLE<- MSEC DATE SOURCE VOL */
409 1.1.1.11 joerg
410 1.1.1.11 joerg n = n->child;
411 1.1.1.12 joerg if (n && n->string) {
412 1.1.1.12 joerg for (p = n->string; '\0' != *p; p++) {
413 1.1.1.12 joerg /* Only warn about this once... */
414 1.1.1.13 joerg if (isalpha((unsigned char)*p) &&
415 1.1.1.13 joerg ! isupper((unsigned char)*p)) {
416 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_UPPERCASE);
417 1.1.1.12 joerg break;
418 1.1.1.12 joerg }
419 1.1.1.12 joerg }
420 1.1.1.13.2.2 yamt man->meta.title = mandoc_strdup(n->string);
421 1.1.1.12 joerg } else
422 1.1.1.13.2.2 yamt man->meta.title = mandoc_strdup("");
423 1.1.1.11 joerg
424 1.1.1.11 joerg /* TITLE ->MSEC<- DATE SOURCE VOL */
425 1.1.1.11 joerg
426 1.1.1.12 joerg if (n)
427 1.1.1.12 joerg n = n->next;
428 1.1.1.12 joerg if (n && n->string)
429 1.1.1.13.2.2 yamt man->meta.msec = mandoc_strdup(n->string);
430 1.1.1.12 joerg else
431 1.1.1.13.2.2 yamt man->meta.msec = mandoc_strdup("");
432 1.1.1.11 joerg
433 1.1.1.11 joerg /* TITLE MSEC ->DATE<- SOURCE VOL */
434 1.1.1.11 joerg
435 1.1.1.12 joerg if (n)
436 1.1.1.12 joerg n = n->next;
437 1.1.1.13.2.1 yamt if (n && n->string && '\0' != n->string[0]) {
438 1.1.1.13.2.2 yamt man->meta.date = mandoc_normdate
439 1.1.1.13.2.2 yamt (man->parse, n->string, n->line, n->pos);
440 1.1.1.13.2.1 yamt } else
441 1.1.1.13.2.2 yamt man->meta.date = mandoc_strdup("");
442 1.1.1.11 joerg
443 1.1.1.11 joerg /* TITLE MSEC DATE ->SOURCE<- VOL */
444 1.1.1.11 joerg
445 1.1.1.11 joerg if (n && (n = n->next))
446 1.1.1.13.2.2 yamt man->meta.source = mandoc_strdup(n->string);
447 1.1.1.11 joerg
448 1.1.1.11 joerg /* TITLE MSEC DATE SOURCE ->VOL<- */
449 1.1.1.13.2.1 yamt /* If missing, use the default VOL name for MSEC. */
450 1.1.1.11 joerg
451 1.1.1.11 joerg if (n && (n = n->next))
452 1.1.1.13.2.2 yamt man->meta.vol = mandoc_strdup(n->string);
453 1.1.1.13.2.2 yamt else if ('\0' != man->meta.msec[0] &&
454 1.1.1.13.2.2 yamt (NULL != (p = mandoc_a2msec(man->meta.msec))))
455 1.1.1.13.2.2 yamt man->meta.vol = mandoc_strdup(p);
456 1.1.1.11 joerg
457 1.1.1.11 joerg /*
458 1.1.1.11 joerg * Remove the `TH' node after we've processed it for our
459 1.1.1.11 joerg * meta-data.
460 1.1.1.11 joerg */
461 1.1.1.13.2.2 yamt man_node_delete(man, man->last);
462 1.1.1.11 joerg return(1);
463 1.1.1.11 joerg }
464 1.1.1.11 joerg
465 1.1.1.11 joerg static int
466 1.1.1.11 joerg post_nf(CHKARGS)
467 1.1.1.11 joerg {
468 1.1.1.11 joerg
469 1.1.1.13.2.2 yamt if (MAN_LITERAL & man->flags)
470 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_SCOPEREP);
471 1.1.1.11 joerg
472 1.1.1.13.2.2 yamt man->flags |= MAN_LITERAL;
473 1.1.1.11 joerg return(1);
474 1.1.1.11 joerg }
475 1.1.1.11 joerg
476 1.1.1.11 joerg static int
477 1.1.1.11 joerg post_fi(CHKARGS)
478 1.1.1.11 joerg {
479 1.1.1.11 joerg
480 1.1.1.13.2.2 yamt if ( ! (MAN_LITERAL & man->flags))
481 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_WNOSCOPE);
482 1.1.1.11 joerg
483 1.1.1.13.2.2 yamt man->flags &= ~MAN_LITERAL;
484 1.1.1.11 joerg return(1);
485 1.1.1.11 joerg }
486 1.1.1.11 joerg
487 1.1.1.11 joerg static int
488 1.1.1.11 joerg post_UC(CHKARGS)
489 1.1.1.11 joerg {
490 1.1.1.11 joerg static const char * const bsd_versions[] = {
491 1.1.1.11 joerg "3rd Berkeley Distribution",
492 1.1.1.11 joerg "4th Berkeley Distribution",
493 1.1.1.11 joerg "4.2 Berkeley Distribution",
494 1.1.1.11 joerg "4.3 Berkeley Distribution",
495 1.1.1.11 joerg "4.4 Berkeley Distribution",
496 1.1.1.11 joerg };
497 1.1.1.11 joerg
498 1.1.1.11 joerg const char *p, *s;
499 1.1.1.11 joerg
500 1.1.1.11 joerg n = n->child;
501 1.1.1.11 joerg
502 1.1.1.11 joerg if (NULL == n || MAN_TEXT != n->type)
503 1.1.1.11 joerg p = bsd_versions[0];
504 1.1.1.11 joerg else {
505 1.1.1.11 joerg s = n->string;
506 1.1.1.11 joerg if (0 == strcmp(s, "3"))
507 1.1.1.11 joerg p = bsd_versions[0];
508 1.1.1.11 joerg else if (0 == strcmp(s, "4"))
509 1.1.1.11 joerg p = bsd_versions[1];
510 1.1.1.11 joerg else if (0 == strcmp(s, "5"))
511 1.1.1.11 joerg p = bsd_versions[2];
512 1.1.1.11 joerg else if (0 == strcmp(s, "6"))
513 1.1.1.11 joerg p = bsd_versions[3];
514 1.1.1.11 joerg else if (0 == strcmp(s, "7"))
515 1.1.1.11 joerg p = bsd_versions[4];
516 1.1.1.11 joerg else
517 1.1.1.11 joerg p = bsd_versions[0];
518 1.1.1.11 joerg }
519 1.1.1.11 joerg
520 1.1.1.13.2.2 yamt free(man->meta.source);
521 1.1.1.13.2.2 yamt man->meta.source = mandoc_strdup(p);
522 1.1.1.11 joerg return(1);
523 1.1.1.11 joerg }
524 1.1.1.11 joerg
525 1.1.1.11 joerg static int
526 1.1.1.11 joerg post_AT(CHKARGS)
527 1.1.1.11 joerg {
528 1.1.1.11 joerg static const char * const unix_versions[] = {
529 1.1.1.11 joerg "7th Edition",
530 1.1.1.11 joerg "System III",
531 1.1.1.11 joerg "System V",
532 1.1.1.11 joerg "System V Release 2",
533 1.1.1.11 joerg };
534 1.1.1.11 joerg
535 1.1.1.11 joerg const char *p, *s;
536 1.1.1.11 joerg struct man_node *nn;
537 1.1.1.11 joerg
538 1.1.1.11 joerg n = n->child;
539 1.1.1.11 joerg
540 1.1.1.11 joerg if (NULL == n || MAN_TEXT != n->type)
541 1.1.1.11 joerg p = unix_versions[0];
542 1.1.1.11 joerg else {
543 1.1.1.11 joerg s = n->string;
544 1.1.1.11 joerg if (0 == strcmp(s, "3"))
545 1.1.1.11 joerg p = unix_versions[0];
546 1.1.1.11 joerg else if (0 == strcmp(s, "4"))
547 1.1.1.11 joerg p = unix_versions[1];
548 1.1.1.11 joerg else if (0 == strcmp(s, "5")) {
549 1.1.1.11 joerg nn = n->next;
550 1.1.1.11 joerg if (nn && MAN_TEXT == nn->type && nn->string[0])
551 1.1.1.11 joerg p = unix_versions[3];
552 1.1.1.11 joerg else
553 1.1.1.11 joerg p = unix_versions[2];
554 1.1.1.11 joerg } else
555 1.1.1.11 joerg p = unix_versions[0];
556 1.1.1.11 joerg }
557 1.1.1.11 joerg
558 1.1.1.13.2.2 yamt free(man->meta.source);
559 1.1.1.13.2.2 yamt man->meta.source = mandoc_strdup(p);
560 1.1.1.11 joerg return(1);
561 1.1.1.11 joerg }
562 1.1.1.13 joerg
563 1.1.1.13 joerg static int
564 1.1.1.13 joerg post_vs(CHKARGS)
565 1.1.1.13 joerg {
566 1.1.1.13 joerg
567 1.1.1.13.2.2 yamt if (NULL != n->prev)
568 1.1.1.13.2.2 yamt return(1);
569 1.1.1.13.2.2 yamt
570 1.1.1.13.2.2 yamt switch (n->parent->tok) {
571 1.1.1.13.2.2 yamt case (MAN_SH):
572 1.1.1.13.2.2 yamt /* FALLTHROUGH */
573 1.1.1.13.2.2 yamt case (MAN_SS):
574 1.1.1.13.2.2 yamt man_nmsg(man, n, MANDOCERR_IGNPAR);
575 1.1.1.13.2.2 yamt /* FALLTHROUGH */
576 1.1.1.13.2.2 yamt case (MAN_MAX):
577 1.1.1.13.2.2 yamt /*
578 1.1.1.13.2.2 yamt * Don't warn about this because it occurs in pod2man
579 1.1.1.13.2.2 yamt * and would cause considerable (unfixable) warnage.
580 1.1.1.13.2.2 yamt */
581 1.1.1.13.2.2 yamt man_node_delete(man, n);
582 1.1.1.13.2.2 yamt break;
583 1.1.1.13.2.2 yamt default:
584 1.1.1.13.2.2 yamt break;
585 1.1.1.13.2.2 yamt }
586 1.1.1.13 joerg
587 1.1.1.13 joerg return(1);
588 1.1.1.13 joerg }
589