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