man_validate.c revision 1.1.1.13.2.1 1 1.1.1.13.2.1 yamt /* $Vendor-Id: man_validate.c,v 1.80 2012/01/03 15:16:24 kristaps 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.12 joerg * Copyright (c) 2010 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.8 joerg #define CHKARGS struct man *m, 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 joerg static int check_par(CHKARGS);
53 1.1 joerg static int check_part(CHKARGS);
54 1.1 joerg static int check_root(CHKARGS);
55 1.1.1.13 joerg static void check_text(CHKARGS);
56 1.1 joerg
57 1.1.1.11 joerg static int post_AT(CHKARGS);
58 1.1.1.13 joerg static int post_vs(CHKARGS);
59 1.1.1.11 joerg static int post_fi(CHKARGS);
60 1.1.1.13 joerg static int post_ft(CHKARGS);
61 1.1.1.11 joerg static int post_nf(CHKARGS);
62 1.1.1.13 joerg static int post_sec(CHKARGS);
63 1.1.1.11 joerg static int post_TH(CHKARGS);
64 1.1.1.11 joerg static int post_UC(CHKARGS);
65 1.1.1.13 joerg static int pre_sec(CHKARGS);
66 1.1.1.11 joerg
67 1.1.1.11 joerg static v_check posts_at[] = { post_AT, NULL };
68 1.1.1.13 joerg static v_check posts_br[] = { post_vs, check_eq0, NULL };
69 1.1 joerg static v_check posts_eq0[] = { check_eq0, NULL };
70 1.1.1.13.2.1 yamt static v_check posts_eq2[] = { check_eq2, NULL };
71 1.1.1.11 joerg static v_check posts_fi[] = { check_eq0, post_fi, NULL };
72 1.1.1.13 joerg static v_check posts_ft[] = { post_ft, NULL };
73 1.1.1.11 joerg static v_check posts_nf[] = { check_eq0, post_nf, NULL };
74 1.1 joerg static v_check posts_par[] = { check_par, NULL };
75 1.1 joerg static v_check posts_part[] = { check_part, NULL };
76 1.1.1.13 joerg static v_check posts_sec[] = { post_sec, NULL };
77 1.1.1.13 joerg static v_check posts_sp[] = { post_vs, check_le1, NULL };
78 1.1.1.12 joerg static v_check posts_th[] = { check_ge2, check_le5, post_TH, NULL };
79 1.1.1.11 joerg static v_check posts_uc[] = { post_UC, NULL };
80 1.1.1.13.2.1 yamt static v_check pres_sec[] = { pre_sec, NULL };
81 1.1.1.11 joerg
82 1.1 joerg static const struct man_valid man_valids[MAN_MAX] = {
83 1.1.1.13 joerg { NULL, posts_br }, /* br */
84 1.1.1.13.2.1 yamt { NULL, posts_th }, /* TH */
85 1.1.1.13 joerg { pres_sec, posts_sec }, /* SH */
86 1.1.1.13 joerg { pres_sec, posts_sec }, /* SS */
87 1.1.1.13.2.1 yamt { NULL, NULL }, /* TP */
88 1.1.1.13.2.1 yamt { NULL, posts_par }, /* LP */
89 1.1.1.13.2.1 yamt { NULL, posts_par }, /* PP */
90 1.1.1.13.2.1 yamt { NULL, posts_par }, /* P */
91 1.1.1.13.2.1 yamt { NULL, NULL }, /* IP */
92 1.1.1.13.2.1 yamt { NULL, NULL }, /* HP */
93 1.1 joerg { NULL, NULL }, /* SM */
94 1.1 joerg { NULL, NULL }, /* SB */
95 1.1 joerg { NULL, NULL }, /* BI */
96 1.1 joerg { NULL, NULL }, /* IB */
97 1.1 joerg { NULL, NULL }, /* BR */
98 1.1 joerg { NULL, NULL }, /* RB */
99 1.1 joerg { NULL, NULL }, /* R */
100 1.1 joerg { NULL, NULL }, /* B */
101 1.1 joerg { NULL, NULL }, /* I */
102 1.1 joerg { NULL, NULL }, /* IR */
103 1.1 joerg { NULL, NULL }, /* RI */
104 1.1.1.13.2.1 yamt { NULL, posts_eq0 }, /* na */
105 1.1.1.13.2.1 yamt { NULL, posts_sp }, /* sp */
106 1.1.1.13.2.1 yamt { NULL, posts_nf }, /* nf */
107 1.1.1.13.2.1 yamt { NULL, posts_fi }, /* fi */
108 1.1 joerg { NULL, NULL }, /* RE */
109 1.1 joerg { NULL, posts_part }, /* RS */
110 1.1 joerg { NULL, NULL }, /* DT */
111 1.1.1.11 joerg { NULL, posts_uc }, /* UC */
112 1.1.1.2 joerg { NULL, NULL }, /* PD */
113 1.1.1.11 joerg { NULL, posts_at }, /* AT */
114 1.1.1.10 joerg { NULL, NULL }, /* in */
115 1.1.1.11 joerg { NULL, posts_ft }, /* ft */
116 1.1.1.13.2.1 yamt { NULL, posts_eq2 }, /* OP */
117 1.1 joerg };
118 1.1 joerg
119 1.1 joerg
120 1.1 joerg int
121 1.1.1.8 joerg man_valid_pre(struct man *m, struct man_node *n)
122 1.1 joerg {
123 1.1 joerg v_check *cp;
124 1.1 joerg
125 1.1.1.11 joerg switch (n->type) {
126 1.1.1.11 joerg case (MAN_TEXT):
127 1.1.1.11 joerg /* FALLTHROUGH */
128 1.1.1.11 joerg case (MAN_ROOT):
129 1.1.1.11 joerg /* FALLTHROUGH */
130 1.1.1.12 joerg case (MAN_EQN):
131 1.1.1.12 joerg /* FALLTHROUGH */
132 1.1.1.11 joerg case (MAN_TBL):
133 1.1 joerg return(1);
134 1.1.1.11 joerg default:
135 1.1.1.11 joerg break;
136 1.1.1.11 joerg }
137 1.1 joerg
138 1.1 joerg if (NULL == (cp = man_valids[n->tok].pres))
139 1.1 joerg return(1);
140 1.1 joerg for ( ; *cp; cp++)
141 1.1 joerg if ( ! (*cp)(m, n))
142 1.1 joerg return(0);
143 1.1 joerg return(1);
144 1.1 joerg }
145 1.1 joerg
146 1.1 joerg
147 1.1 joerg int
148 1.1 joerg man_valid_post(struct man *m)
149 1.1 joerg {
150 1.1 joerg v_check *cp;
151 1.1 joerg
152 1.1 joerg if (MAN_VALID & m->last->flags)
153 1.1 joerg return(1);
154 1.1 joerg m->last->flags |= MAN_VALID;
155 1.1 joerg
156 1.1 joerg switch (m->last->type) {
157 1.1 joerg case (MAN_TEXT):
158 1.1.1.13 joerg check_text(m, m->last);
159 1.1.1.13 joerg return(1);
160 1.1 joerg case (MAN_ROOT):
161 1.1 joerg return(check_root(m, m->last));
162 1.1.1.12 joerg case (MAN_EQN):
163 1.1.1.12 joerg /* FALLTHROUGH */
164 1.1.1.11 joerg case (MAN_TBL):
165 1.1.1.11 joerg return(1);
166 1.1 joerg default:
167 1.1 joerg break;
168 1.1 joerg }
169 1.1 joerg
170 1.1 joerg if (NULL == (cp = man_valids[m->last->tok].posts))
171 1.1 joerg return(1);
172 1.1 joerg for ( ; *cp; cp++)
173 1.1 joerg if ( ! (*cp)(m, m->last))
174 1.1 joerg return(0);
175 1.1 joerg
176 1.1 joerg return(1);
177 1.1 joerg }
178 1.1 joerg
179 1.1 joerg
180 1.1 joerg static int
181 1.1 joerg check_root(CHKARGS)
182 1.1 joerg {
183 1.1 joerg
184 1.1 joerg if (MAN_BLINE & m->flags)
185 1.1.1.11 joerg man_nmsg(m, n, MANDOCERR_SCOPEEXIT);
186 1.1.1.11 joerg else if (MAN_ELINE & m->flags)
187 1.1.1.11 joerg man_nmsg(m, n, MANDOCERR_SCOPEEXIT);
188 1.1 joerg
189 1.1 joerg m->flags &= ~MAN_BLINE;
190 1.1 joerg m->flags &= ~MAN_ELINE;
191 1.1 joerg
192 1.1.1.7 joerg if (NULL == m->first->child) {
193 1.1.1.7 joerg man_nmsg(m, n, MANDOCERR_NODOCBODY);
194 1.1.1.7 joerg return(0);
195 1.1.1.7 joerg } else if (NULL == m->meta.title) {
196 1.1.1.11 joerg man_nmsg(m, n, MANDOCERR_NOTITLE);
197 1.1.1.11 joerg
198 1.1.1.6 joerg /*
199 1.1.1.6 joerg * If a title hasn't been set, do so now (by
200 1.1.1.6 joerg * implication, date and section also aren't set).
201 1.1.1.6 joerg */
202 1.1.1.11 joerg
203 1.1.1.6 joerg m->meta.title = mandoc_strdup("unknown");
204 1.1.1.7 joerg m->meta.msec = mandoc_strdup("1");
205 1.1.1.12 joerg m->meta.date = mandoc_normdate
206 1.1.1.12 joerg (m->parse, NULL, n->line, n->pos);
207 1.1.1.6 joerg }
208 1.1 joerg
209 1.1 joerg return(1);
210 1.1 joerg }
211 1.1 joerg
212 1.1.1.13 joerg static void
213 1.1.1.13 joerg check_text(CHKARGS)
214 1.1 joerg {
215 1.1.1.13 joerg char *cp, *p;
216 1.1 joerg
217 1.1.1.13.2.1 yamt if (MAN_LITERAL & m->flags)
218 1.1.1.13.2.1 yamt return;
219 1.1.1.13.2.1 yamt
220 1.1.1.13.2.1 yamt cp = n->string;
221 1.1.1.13.2.1 yamt for (p = cp; NULL != (p = strchr(p, '\t')); p++)
222 1.1.1.13 joerg man_pmsg(m, n->line, (int)(p - cp), MANDOCERR_BADTAB);
223 1.1 joerg }
224 1.1 joerg
225 1.1 joerg #define INEQ_DEFINE(x, ineq, name) \
226 1.1 joerg static int \
227 1.1 joerg check_##name(CHKARGS) \
228 1.1 joerg { \
229 1.1 joerg if (n->nchild ineq (x)) \
230 1.1 joerg return(1); \
231 1.1.1.12 joerg mandoc_vmsg(MANDOCERR_ARGCOUNT, m->parse, n->line, n->pos, \
232 1.1.1.7 joerg "line arguments %s %d (have %d)", \
233 1.1.1.7 joerg #ineq, (x), n->nchild); \
234 1.1.1.12 joerg return(1); \
235 1.1 joerg }
236 1.1 joerg
237 1.1 joerg INEQ_DEFINE(0, ==, eq0)
238 1.1.1.13.2.1 yamt INEQ_DEFINE(2, ==, eq2)
239 1.1 joerg INEQ_DEFINE(1, <=, le1)
240 1.1 joerg INEQ_DEFINE(2, >=, ge2)
241 1.1 joerg INEQ_DEFINE(5, <=, le5)
242 1.1 joerg
243 1.1.1.11 joerg static int
244 1.1.1.13 joerg post_ft(CHKARGS)
245 1.1.1.11 joerg {
246 1.1.1.11 joerg char *cp;
247 1.1.1.11 joerg int ok;
248 1.1.1.11 joerg
249 1.1.1.11 joerg if (0 == n->nchild)
250 1.1.1.11 joerg return(1);
251 1.1.1.11 joerg
252 1.1.1.11 joerg ok = 0;
253 1.1.1.11 joerg cp = n->child->string;
254 1.1.1.11 joerg switch (*cp) {
255 1.1.1.11 joerg case ('1'):
256 1.1.1.11 joerg /* FALLTHROUGH */
257 1.1.1.11 joerg case ('2'):
258 1.1.1.11 joerg /* FALLTHROUGH */
259 1.1.1.11 joerg case ('3'):
260 1.1.1.11 joerg /* FALLTHROUGH */
261 1.1.1.11 joerg case ('4'):
262 1.1.1.11 joerg /* FALLTHROUGH */
263 1.1.1.11 joerg case ('I'):
264 1.1.1.11 joerg /* FALLTHROUGH */
265 1.1.1.11 joerg case ('P'):
266 1.1.1.11 joerg /* FALLTHROUGH */
267 1.1.1.11 joerg case ('R'):
268 1.1.1.11 joerg if ('\0' == cp[1])
269 1.1.1.11 joerg ok = 1;
270 1.1.1.11 joerg break;
271 1.1.1.11 joerg case ('B'):
272 1.1.1.11 joerg if ('\0' == cp[1] || ('I' == cp[1] && '\0' == cp[2]))
273 1.1.1.11 joerg ok = 1;
274 1.1.1.11 joerg break;
275 1.1.1.11 joerg case ('C'):
276 1.1.1.11 joerg if ('W' == cp[1] && '\0' == cp[2])
277 1.1.1.11 joerg ok = 1;
278 1.1.1.11 joerg break;
279 1.1.1.11 joerg default:
280 1.1.1.11 joerg break;
281 1.1.1.11 joerg }
282 1.1.1.11 joerg
283 1.1.1.11 joerg if (0 == ok) {
284 1.1.1.12 joerg mandoc_vmsg
285 1.1.1.12 joerg (MANDOCERR_BADFONT, m->parse,
286 1.1.1.12 joerg n->line, n->pos, "%s", cp);
287 1.1.1.11 joerg *cp = '\0';
288 1.1.1.11 joerg }
289 1.1.1.11 joerg
290 1.1.1.11 joerg if (1 < n->nchild)
291 1.1.1.12 joerg mandoc_vmsg
292 1.1.1.12 joerg (MANDOCERR_ARGCOUNT, m->parse, n->line,
293 1.1.1.12 joerg n->pos, "want one child (have %d)",
294 1.1.1.12 joerg n->nchild);
295 1.1.1.11 joerg
296 1.1.1.11 joerg return(1);
297 1.1.1.11 joerg }
298 1.1 joerg
299 1.1 joerg static int
300 1.1.1.13 joerg pre_sec(CHKARGS)
301 1.1 joerg {
302 1.1 joerg
303 1.1.1.13 joerg if (MAN_BLOCK == n->type)
304 1.1.1.13 joerg m->flags &= ~MAN_LITERAL;
305 1.1 joerg return(1);
306 1.1 joerg }
307 1.1 joerg
308 1.1.1.13 joerg static int
309 1.1.1.13 joerg post_sec(CHKARGS)
310 1.1.1.13 joerg {
311 1.1.1.13 joerg
312 1.1.1.13 joerg if ( ! (MAN_HEAD == n->type && 0 == n->nchild))
313 1.1.1.13 joerg return(1);
314 1.1.1.13 joerg
315 1.1.1.13 joerg man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
316 1.1.1.13 joerg return(0);
317 1.1.1.13 joerg }
318 1.1 joerg
319 1.1 joerg static int
320 1.1 joerg check_part(CHKARGS)
321 1.1 joerg {
322 1.1 joerg
323 1.1 joerg if (MAN_BODY == n->type && 0 == n->nchild)
324 1.1.1.12 joerg mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line,
325 1.1.1.12 joerg n->pos, "want children (have none)");
326 1.1.1.11 joerg
327 1.1 joerg return(1);
328 1.1 joerg }
329 1.1 joerg
330 1.1 joerg
331 1.1 joerg static int
332 1.1 joerg check_par(CHKARGS)
333 1.1 joerg {
334 1.1 joerg
335 1.1.1.12 joerg switch (n->type) {
336 1.1.1.12 joerg case (MAN_BLOCK):
337 1.1.1.12 joerg if (0 == n->body->nchild)
338 1.1.1.12 joerg man_node_delete(m, n);
339 1.1.1.12 joerg break;
340 1.1.1.12 joerg case (MAN_BODY):
341 1.1.1.12 joerg if (0 == n->nchild)
342 1.1.1.12 joerg man_nmsg(m, n, MANDOCERR_IGNPAR);
343 1.1.1.12 joerg break;
344 1.1.1.12 joerg case (MAN_HEAD):
345 1.1.1.12 joerg if (n->nchild)
346 1.1.1.12 joerg man_nmsg(m, n, MANDOCERR_ARGSLOST);
347 1.1.1.12 joerg break;
348 1.1.1.12 joerg default:
349 1.1.1.12 joerg break;
350 1.1.1.12 joerg }
351 1.1 joerg
352 1.1 joerg return(1);
353 1.1 joerg }
354 1.1 joerg
355 1.1 joerg
356 1.1 joerg static int
357 1.1.1.11 joerg post_TH(CHKARGS)
358 1.1.1.11 joerg {
359 1.1.1.12 joerg const char *p;
360 1.1.1.12 joerg int line, pos;
361 1.1.1.11 joerg
362 1.1.1.11 joerg if (m->meta.title)
363 1.1.1.11 joerg free(m->meta.title);
364 1.1.1.11 joerg if (m->meta.vol)
365 1.1.1.11 joerg free(m->meta.vol);
366 1.1.1.11 joerg if (m->meta.source)
367 1.1.1.11 joerg free(m->meta.source);
368 1.1.1.11 joerg if (m->meta.msec)
369 1.1.1.11 joerg free(m->meta.msec);
370 1.1.1.12 joerg if (m->meta.date)
371 1.1.1.12 joerg free(m->meta.date);
372 1.1.1.11 joerg
373 1.1.1.12 joerg line = n->line;
374 1.1.1.12 joerg pos = n->pos;
375 1.1.1.12 joerg m->meta.title = m->meta.vol = m->meta.date =
376 1.1.1.11 joerg m->meta.msec = m->meta.source = NULL;
377 1.1.1.11 joerg
378 1.1.1.11 joerg /* ->TITLE<- MSEC DATE SOURCE VOL */
379 1.1.1.11 joerg
380 1.1.1.11 joerg n = n->child;
381 1.1.1.12 joerg if (n && n->string) {
382 1.1.1.12 joerg for (p = n->string; '\0' != *p; p++) {
383 1.1.1.12 joerg /* Only warn about this once... */
384 1.1.1.13 joerg if (isalpha((unsigned char)*p) &&
385 1.1.1.13 joerg ! isupper((unsigned char)*p)) {
386 1.1.1.12 joerg man_nmsg(m, n, MANDOCERR_UPPERCASE);
387 1.1.1.12 joerg break;
388 1.1.1.12 joerg }
389 1.1.1.12 joerg }
390 1.1.1.12 joerg m->meta.title = mandoc_strdup(n->string);
391 1.1.1.12 joerg } else
392 1.1.1.12 joerg m->meta.title = mandoc_strdup("");
393 1.1.1.11 joerg
394 1.1.1.11 joerg /* TITLE ->MSEC<- DATE SOURCE VOL */
395 1.1.1.11 joerg
396 1.1.1.12 joerg if (n)
397 1.1.1.12 joerg n = n->next;
398 1.1.1.12 joerg if (n && n->string)
399 1.1.1.12 joerg m->meta.msec = mandoc_strdup(n->string);
400 1.1.1.12 joerg else
401 1.1.1.12 joerg m->meta.msec = mandoc_strdup("");
402 1.1.1.11 joerg
403 1.1.1.11 joerg /* TITLE MSEC ->DATE<- SOURCE VOL */
404 1.1.1.11 joerg
405 1.1.1.12 joerg if (n)
406 1.1.1.12 joerg n = n->next;
407 1.1.1.13.2.1 yamt if (n && n->string && '\0' != n->string[0]) {
408 1.1.1.12 joerg pos = n->pos;
409 1.1.1.13.2.1 yamt m->meta.date = mandoc_normdate
410 1.1.1.13.2.1 yamt (m->parse, n->string, line, pos);
411 1.1.1.13.2.1 yamt } else
412 1.1.1.13.2.1 yamt m->meta.date = mandoc_strdup("");
413 1.1.1.11 joerg
414 1.1.1.11 joerg /* TITLE MSEC DATE ->SOURCE<- VOL */
415 1.1.1.11 joerg
416 1.1.1.11 joerg if (n && (n = n->next))
417 1.1.1.11 joerg m->meta.source = mandoc_strdup(n->string);
418 1.1.1.11 joerg
419 1.1.1.11 joerg /* TITLE MSEC DATE SOURCE ->VOL<- */
420 1.1.1.13.2.1 yamt /* If missing, use the default VOL name for MSEC. */
421 1.1.1.11 joerg
422 1.1.1.11 joerg if (n && (n = n->next))
423 1.1.1.11 joerg m->meta.vol = mandoc_strdup(n->string);
424 1.1.1.13.2.1 yamt else if ('\0' != m->meta.msec[0] &&
425 1.1.1.13.2.1 yamt (NULL != (p = mandoc_a2msec(m->meta.msec))))
426 1.1.1.13.2.1 yamt m->meta.vol = mandoc_strdup(p);
427 1.1.1.11 joerg
428 1.1.1.11 joerg /*
429 1.1.1.11 joerg * Remove the `TH' node after we've processed it for our
430 1.1.1.11 joerg * meta-data.
431 1.1.1.11 joerg */
432 1.1.1.11 joerg man_node_delete(m, m->last);
433 1.1.1.11 joerg return(1);
434 1.1.1.11 joerg }
435 1.1.1.11 joerg
436 1.1.1.11 joerg static int
437 1.1.1.11 joerg post_nf(CHKARGS)
438 1.1.1.11 joerg {
439 1.1.1.11 joerg
440 1.1.1.11 joerg if (MAN_LITERAL & m->flags)
441 1.1.1.11 joerg man_nmsg(m, n, MANDOCERR_SCOPEREP);
442 1.1.1.11 joerg
443 1.1.1.11 joerg m->flags |= MAN_LITERAL;
444 1.1.1.11 joerg return(1);
445 1.1.1.11 joerg }
446 1.1.1.11 joerg
447 1.1.1.11 joerg static int
448 1.1.1.11 joerg post_fi(CHKARGS)
449 1.1.1.11 joerg {
450 1.1.1.11 joerg
451 1.1.1.11 joerg if ( ! (MAN_LITERAL & m->flags))
452 1.1.1.12 joerg man_nmsg(m, n, MANDOCERR_WNOSCOPE);
453 1.1.1.11 joerg
454 1.1.1.11 joerg m->flags &= ~MAN_LITERAL;
455 1.1.1.11 joerg return(1);
456 1.1.1.11 joerg }
457 1.1.1.11 joerg
458 1.1.1.11 joerg static int
459 1.1.1.11 joerg post_UC(CHKARGS)
460 1.1.1.11 joerg {
461 1.1.1.11 joerg static const char * const bsd_versions[] = {
462 1.1.1.11 joerg "3rd Berkeley Distribution",
463 1.1.1.11 joerg "4th Berkeley Distribution",
464 1.1.1.11 joerg "4.2 Berkeley Distribution",
465 1.1.1.11 joerg "4.3 Berkeley Distribution",
466 1.1.1.11 joerg "4.4 Berkeley Distribution",
467 1.1.1.11 joerg };
468 1.1.1.11 joerg
469 1.1.1.11 joerg const char *p, *s;
470 1.1.1.11 joerg
471 1.1.1.11 joerg n = n->child;
472 1.1.1.11 joerg
473 1.1.1.11 joerg if (NULL == n || MAN_TEXT != n->type)
474 1.1.1.11 joerg p = bsd_versions[0];
475 1.1.1.11 joerg else {
476 1.1.1.11 joerg s = n->string;
477 1.1.1.11 joerg if (0 == strcmp(s, "3"))
478 1.1.1.11 joerg p = bsd_versions[0];
479 1.1.1.11 joerg else if (0 == strcmp(s, "4"))
480 1.1.1.11 joerg p = bsd_versions[1];
481 1.1.1.11 joerg else if (0 == strcmp(s, "5"))
482 1.1.1.11 joerg p = bsd_versions[2];
483 1.1.1.11 joerg else if (0 == strcmp(s, "6"))
484 1.1.1.11 joerg p = bsd_versions[3];
485 1.1.1.11 joerg else if (0 == strcmp(s, "7"))
486 1.1.1.11 joerg p = bsd_versions[4];
487 1.1.1.11 joerg else
488 1.1.1.11 joerg p = bsd_versions[0];
489 1.1.1.11 joerg }
490 1.1.1.11 joerg
491 1.1.1.11 joerg if (m->meta.source)
492 1.1.1.11 joerg free(m->meta.source);
493 1.1.1.11 joerg
494 1.1.1.11 joerg m->meta.source = mandoc_strdup(p);
495 1.1.1.11 joerg return(1);
496 1.1.1.11 joerg }
497 1.1.1.11 joerg
498 1.1.1.11 joerg static int
499 1.1.1.11 joerg post_AT(CHKARGS)
500 1.1.1.11 joerg {
501 1.1.1.11 joerg static const char * const unix_versions[] = {
502 1.1.1.11 joerg "7th Edition",
503 1.1.1.11 joerg "System III",
504 1.1.1.11 joerg "System V",
505 1.1.1.11 joerg "System V Release 2",
506 1.1.1.11 joerg };
507 1.1.1.11 joerg
508 1.1.1.11 joerg const char *p, *s;
509 1.1.1.11 joerg struct man_node *nn;
510 1.1.1.11 joerg
511 1.1.1.11 joerg n = n->child;
512 1.1.1.11 joerg
513 1.1.1.11 joerg if (NULL == n || MAN_TEXT != n->type)
514 1.1.1.11 joerg p = unix_versions[0];
515 1.1.1.11 joerg else {
516 1.1.1.11 joerg s = n->string;
517 1.1.1.11 joerg if (0 == strcmp(s, "3"))
518 1.1.1.11 joerg p = unix_versions[0];
519 1.1.1.11 joerg else if (0 == strcmp(s, "4"))
520 1.1.1.11 joerg p = unix_versions[1];
521 1.1.1.11 joerg else if (0 == strcmp(s, "5")) {
522 1.1.1.11 joerg nn = n->next;
523 1.1.1.11 joerg if (nn && MAN_TEXT == nn->type && nn->string[0])
524 1.1.1.11 joerg p = unix_versions[3];
525 1.1.1.11 joerg else
526 1.1.1.11 joerg p = unix_versions[2];
527 1.1.1.11 joerg } else
528 1.1.1.11 joerg p = unix_versions[0];
529 1.1.1.11 joerg }
530 1.1.1.11 joerg
531 1.1.1.11 joerg if (m->meta.source)
532 1.1.1.11 joerg free(m->meta.source);
533 1.1.1.11 joerg
534 1.1.1.11 joerg m->meta.source = mandoc_strdup(p);
535 1.1.1.11 joerg return(1);
536 1.1.1.11 joerg }
537 1.1.1.13 joerg
538 1.1.1.13 joerg static int
539 1.1.1.13 joerg post_vs(CHKARGS)
540 1.1.1.13 joerg {
541 1.1.1.13 joerg
542 1.1.1.13 joerg /*
543 1.1.1.13 joerg * Don't warn about this because it occurs in pod2man and would
544 1.1.1.13 joerg * cause considerable (unfixable) warnage.
545 1.1.1.13 joerg */
546 1.1.1.13 joerg if (NULL == n->prev && MAN_ROOT == n->parent->type)
547 1.1.1.13 joerg man_node_delete(m, n);
548 1.1.1.13 joerg
549 1.1.1.13 joerg return(1);
550 1.1.1.13 joerg }
551