Print this page
Update to 1.12.3.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mandoc/mdoc_validate.c
+++ new/usr/src/cmd/mandoc/mdoc_validate.c
1 -/* $Id: mdoc_validate.c,v 1.182 2012/03/23 05:50:25 kristaps Exp $ */
1 +/* $Id: mdoc_validate.c,v 1.198 2013/12/15 21:23:52 schwarze Exp $ */
2 2 /*
3 - * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 - * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
3 + * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 + * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
5 5 *
6 6 * Permission to use, copy, modify, and distribute this software for any
7 7 * purpose with or without fee is hereby granted, provided that the above
8 8 * copyright notice and this permission notice appear in all copies.
9 9 *
10 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 17 */
18 18 #ifdef HAVE_CONFIG_H
19 19 #include "config.h"
20 20 #endif
21 21
22 -#ifndef OSNAME
22 +#ifndef OSNAME
23 23 #include <sys/utsname.h>
24 24 #endif
25 25
26 26 #include <sys/types.h>
27 27
28 28 #include <assert.h>
29 29 #include <ctype.h>
30 30 #include <limits.h>
31 31 #include <stdio.h>
32 32 #include <stdlib.h>
33 33 #include <string.h>
34 34 #include <time.h>
35 35
36 36 #include "mdoc.h"
37 37 #include "mandoc.h"
38 38 #include "libmdoc.h"
39 39 #include "libmandoc.h"
40 40
41 41 /* FIXME: .Bl -diag can't have non-text children in HEAD. */
42 42
43 43 #define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n
44 44 #define POST_ARGS struct mdoc *mdoc
45 45
46 46 #define NUMSIZ 32
47 47 #define DATESIZE 32
48 48
49 49 enum check_ineq {
50 50 CHECK_LT,
51 51 CHECK_GT,
52 52 CHECK_EQ
53 53 };
54 54
55 55 enum check_lvl {
56 56 CHECK_WARN,
57 57 CHECK_ERROR,
58 58 };
59 59
60 60 typedef int (*v_pre)(PRE_ARGS);
61 61 typedef int (*v_post)(POST_ARGS);
62 62
63 63 struct valids {
64 64 v_pre *pre;
65 65 v_post *post;
66 66 };
67 67
68 68 static int check_count(struct mdoc *, enum mdoc_type,
69 69 enum check_lvl, enum check_ineq, int);
70 70 static int check_parent(PRE_ARGS, enum mdoct, enum mdoc_type);
71 71 static void check_text(struct mdoc *, int, int, char *);
72 72 static void check_argv(struct mdoc *,
73 73 struct mdoc_node *, struct mdoc_argv *);
74 74 static void check_args(struct mdoc *, struct mdoc_node *);
75 75 static int concat(char *, const struct mdoc_node *, size_t);
76 76 static enum mdoc_sec a2sec(const char *);
77 77 static size_t macro2len(enum mdoct);
78 78
79 79 static int ebool(POST_ARGS);
80 80 static int berr_ge1(POST_ARGS);
81 81 static int bwarn_ge1(POST_ARGS);
82 82 static int ewarn_eq0(POST_ARGS);
83 83 static int ewarn_eq1(POST_ARGS);
84 84 static int ewarn_ge1(POST_ARGS);
85 85 static int ewarn_le1(POST_ARGS);
86 86 static int hwarn_eq0(POST_ARGS);
87 87 static int hwarn_eq1(POST_ARGS);
88 88 static int hwarn_ge1(POST_ARGS);
89 89 static int hwarn_le1(POST_ARGS);
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
90 90
91 91 static int post_an(POST_ARGS);
92 92 static int post_at(POST_ARGS);
93 93 static int post_bf(POST_ARGS);
94 94 static int post_bl(POST_ARGS);
95 95 static int post_bl_block(POST_ARGS);
96 96 static int post_bl_block_width(POST_ARGS);
97 97 static int post_bl_block_tag(POST_ARGS);
98 98 static int post_bl_head(POST_ARGS);
99 99 static int post_bx(POST_ARGS);
100 +static int post_defaults(POST_ARGS);
100 101 static int post_dd(POST_ARGS);
101 102 static int post_dt(POST_ARGS);
102 -static int post_defaults(POST_ARGS);
103 -static int post_literal(POST_ARGS);
104 103 static int post_eoln(POST_ARGS);
104 +static int post_hyph(POST_ARGS);
105 +static int post_ignpar(POST_ARGS);
105 106 static int post_it(POST_ARGS);
106 107 static int post_lb(POST_ARGS);
108 +static int post_literal(POST_ARGS);
107 109 static int post_nm(POST_ARGS);
108 110 static int post_ns(POST_ARGS);
109 111 static int post_os(POST_ARGS);
110 -static int post_ignpar(POST_ARGS);
112 +static int post_par(POST_ARGS);
111 113 static int post_prol(POST_ARGS);
112 114 static int post_root(POST_ARGS);
113 115 static int post_rs(POST_ARGS);
114 116 static int post_sh(POST_ARGS);
115 117 static int post_sh_body(POST_ARGS);
116 118 static int post_sh_head(POST_ARGS);
117 119 static int post_st(POST_ARGS);
118 120 static int post_std(POST_ARGS);
119 121 static int post_vt(POST_ARGS);
120 122 static int pre_an(PRE_ARGS);
121 123 static int pre_bd(PRE_ARGS);
122 124 static int pre_bl(PRE_ARGS);
123 125 static int pre_dd(PRE_ARGS);
124 126 static int pre_display(PRE_ARGS);
125 127 static int pre_dt(PRE_ARGS);
126 128 static int pre_it(PRE_ARGS);
127 129 static int pre_literal(PRE_ARGS);
128 130 static int pre_os(PRE_ARGS);
129 131 static int pre_par(PRE_ARGS);
130 132 static int pre_sh(PRE_ARGS);
131 133 static int pre_ss(PRE_ARGS);
132 134 static int pre_std(PRE_ARGS);
133 135
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
134 136 static v_post posts_an[] = { post_an, NULL };
135 137 static v_post posts_at[] = { post_at, post_defaults, NULL };
136 138 static v_post posts_bd[] = { post_literal, hwarn_eq0, bwarn_ge1, NULL };
137 139 static v_post posts_bf[] = { hwarn_le1, post_bf, NULL };
138 140 static v_post posts_bk[] = { hwarn_eq0, bwarn_ge1, NULL };
139 141 static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL };
140 142 static v_post posts_bx[] = { post_bx, NULL };
141 143 static v_post posts_bool[] = { ebool, NULL };
142 144 static v_post posts_eoln[] = { post_eoln, NULL };
143 145 static v_post posts_defaults[] = { post_defaults, NULL };
146 +static v_post posts_d1[] = { bwarn_ge1, post_hyph, NULL };
144 147 static v_post posts_dd[] = { post_dd, post_prol, NULL };
145 148 static v_post posts_dl[] = { post_literal, bwarn_ge1, NULL };
146 149 static v_post posts_dt[] = { post_dt, post_prol, NULL };
147 150 static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
151 +static v_post posts_hyph[] = { post_hyph, NULL };
152 +static v_post posts_hyphtext[] = { ewarn_ge1, post_hyph, NULL };
148 153 static v_post posts_it[] = { post_it, NULL };
149 154 static v_post posts_lb[] = { post_lb, NULL };
150 -static v_post posts_nd[] = { berr_ge1, NULL };
155 +static v_post posts_nd[] = { berr_ge1, post_hyph, NULL };
151 156 static v_post posts_nm[] = { post_nm, NULL };
152 157 static v_post posts_notext[] = { ewarn_eq0, NULL };
153 158 static v_post posts_ns[] = { post_ns, NULL };
154 159 static v_post posts_os[] = { post_os, post_prol, NULL };
160 +static v_post posts_pp[] = { post_par, ewarn_eq0, NULL };
155 161 static v_post posts_rs[] = { post_rs, NULL };
156 -static v_post posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL };
157 -static v_post posts_sp[] = { ewarn_le1, NULL };
158 -static v_post posts_ss[] = { post_ignpar, hwarn_ge1, NULL };
162 +static v_post posts_sh[] = { post_ignpar,hwarn_ge1,post_sh,post_hyph,NULL };
163 +static v_post posts_sp[] = { post_par, ewarn_le1, NULL };
164 +static v_post posts_ss[] = { post_ignpar, hwarn_ge1, post_hyph, NULL };
159 165 static v_post posts_st[] = { post_st, NULL };
160 166 static v_post posts_std[] = { post_std, NULL };
161 167 static v_post posts_text[] = { ewarn_ge1, NULL };
162 168 static v_post posts_text1[] = { ewarn_eq1, NULL };
163 169 static v_post posts_vt[] = { post_vt, NULL };
164 -static v_post posts_wline[] = { bwarn_ge1, NULL };
165 170 static v_pre pres_an[] = { pre_an, NULL };
166 171 static v_pre pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL };
167 172 static v_pre pres_bl[] = { pre_bl, pre_par, NULL };
168 173 static v_pre pres_d1[] = { pre_display, NULL };
169 174 static v_pre pres_dl[] = { pre_literal, pre_display, NULL };
170 175 static v_pre pres_dd[] = { pre_dd, NULL };
171 176 static v_pre pres_dt[] = { pre_dt, NULL };
172 -static v_pre pres_er[] = { NULL, NULL };
173 -static v_pre pres_fd[] = { NULL, NULL };
174 177 static v_pre pres_it[] = { pre_it, pre_par, NULL };
175 178 static v_pre pres_os[] = { pre_os, NULL };
176 179 static v_pre pres_pp[] = { pre_par, NULL };
177 180 static v_pre pres_sh[] = { pre_sh, NULL };
178 181 static v_pre pres_ss[] = { pre_ss, NULL };
179 182 static v_pre pres_std[] = { pre_std, NULL };
180 183
181 184 static const struct valids mdoc_valids[MDOC_MAX] = {
182 185 { NULL, NULL }, /* Ap */
183 186 { pres_dd, posts_dd }, /* Dd */
184 187 { pres_dt, posts_dt }, /* Dt */
185 188 { pres_os, posts_os }, /* Os */
186 189 { pres_sh, posts_sh }, /* Sh */
187 190 { pres_ss, posts_ss }, /* Ss */
188 - { pres_pp, posts_notext }, /* Pp */
189 - { pres_d1, posts_wline }, /* D1 */
191 + { pres_pp, posts_pp }, /* Pp */
192 + { pres_d1, posts_d1 }, /* D1 */
190 193 { pres_dl, posts_dl }, /* Dl */
191 194 { pres_bd, posts_bd }, /* Bd */
192 195 { NULL, NULL }, /* Ed */
193 196 { pres_bl, posts_bl }, /* Bl */
194 197 { NULL, NULL }, /* El */
195 198 { pres_it, posts_it }, /* It */
196 199 { NULL, NULL }, /* Ad */
197 200 { pres_an, posts_an }, /* An */
198 201 { NULL, posts_defaults }, /* Ar */
199 202 { NULL, NULL }, /* Cd */
200 203 { NULL, NULL }, /* Cm */
201 204 { NULL, NULL }, /* Dv */
202 - { pres_er, NULL }, /* Er */
205 + { NULL, NULL }, /* Er */
203 206 { NULL, NULL }, /* Ev */
204 207 { pres_std, posts_std }, /* Ex */
205 208 { NULL, NULL }, /* Fa */
206 - { pres_fd, posts_text }, /* Fd */
209 + { NULL, posts_text }, /* Fd */
207 210 { NULL, NULL }, /* Fl */
208 211 { NULL, NULL }, /* Fn */
209 212 { NULL, NULL }, /* Ft */
210 213 { NULL, NULL }, /* Ic */
211 214 { NULL, posts_text1 }, /* In */
212 215 { NULL, posts_defaults }, /* Li */
213 216 { NULL, posts_nd }, /* Nd */
214 217 { NULL, posts_nm }, /* Nm */
215 218 { NULL, NULL }, /* Op */
216 219 { NULL, NULL }, /* Ot */
217 220 { NULL, posts_defaults }, /* Pa */
218 221 { pres_std, posts_std }, /* Rv */
219 222 { NULL, posts_st }, /* St */
220 223 { NULL, NULL }, /* Va */
221 224 { NULL, posts_vt }, /* Vt */
222 225 { NULL, posts_text }, /* Xr */
223 226 { NULL, posts_text }, /* %A */
224 - { NULL, posts_text }, /* %B */ /* FIXME: can be used outside Rs/Re. */
227 + { NULL, posts_hyphtext }, /* %B */ /* FIXME: can be used outside Rs/Re. */
225 228 { NULL, posts_text }, /* %D */
226 229 { NULL, posts_text }, /* %I */
227 230 { NULL, posts_text }, /* %J */
228 - { NULL, posts_text }, /* %N */
229 - { NULL, posts_text }, /* %O */
231 + { NULL, posts_hyphtext }, /* %N */
232 + { NULL, posts_hyphtext }, /* %O */
230 233 { NULL, posts_text }, /* %P */
231 - { NULL, posts_text }, /* %R */
232 - { NULL, posts_text }, /* %T */ /* FIXME: can be used outside Rs/Re. */
234 + { NULL, posts_hyphtext }, /* %R */
235 + { NULL, posts_hyphtext }, /* %T */ /* FIXME: can be used outside Rs/Re. */
233 236 { NULL, posts_text }, /* %V */
234 237 { NULL, NULL }, /* Ac */
235 238 { NULL, NULL }, /* Ao */
236 239 { NULL, NULL }, /* Aq */
237 240 { NULL, posts_at }, /* At */
238 241 { NULL, NULL }, /* Bc */
239 242 { NULL, posts_bf }, /* Bf */
240 243 { NULL, NULL }, /* Bo */
241 244 { NULL, NULL }, /* Bq */
242 245 { NULL, NULL }, /* Bsx */
243 246 { NULL, posts_bx }, /* Bx */
244 247 { NULL, posts_bool }, /* Db */
245 248 { NULL, NULL }, /* Dc */
246 249 { NULL, NULL }, /* Do */
247 250 { NULL, NULL }, /* Dq */
248 251 { NULL, NULL }, /* Ec */
249 252 { NULL, NULL }, /* Ef */
250 253 { NULL, NULL }, /* Em */
251 254 { NULL, NULL }, /* Eo */
252 255 { NULL, NULL }, /* Fx */
253 256 { NULL, NULL }, /* Ms */
254 257 { NULL, posts_notext }, /* No */
255 258 { NULL, posts_ns }, /* Ns */
256 259 { NULL, NULL }, /* Nx */
257 260 { NULL, NULL }, /* Ox */
258 261 { NULL, NULL }, /* Pc */
259 262 { NULL, posts_text1 }, /* Pf */
260 263 { NULL, NULL }, /* Po */
261 264 { NULL, NULL }, /* Pq */
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
262 265 { NULL, NULL }, /* Qc */
263 266 { NULL, NULL }, /* Ql */
264 267 { NULL, NULL }, /* Qo */
265 268 { NULL, NULL }, /* Qq */
266 269 { NULL, NULL }, /* Re */
267 270 { NULL, posts_rs }, /* Rs */
268 271 { NULL, NULL }, /* Sc */
269 272 { NULL, NULL }, /* So */
270 273 { NULL, NULL }, /* Sq */
271 274 { NULL, posts_bool }, /* Sm */
272 - { NULL, NULL }, /* Sx */
275 + { NULL, posts_hyph }, /* Sx */
273 276 { NULL, NULL }, /* Sy */
274 277 { NULL, NULL }, /* Tn */
275 278 { NULL, NULL }, /* Ux */
276 279 { NULL, NULL }, /* Xc */
277 280 { NULL, NULL }, /* Xo */
278 281 { NULL, posts_fo }, /* Fo */
279 282 { NULL, NULL }, /* Fc */
280 283 { NULL, NULL }, /* Oo */
281 284 { NULL, NULL }, /* Oc */
282 285 { NULL, posts_bk }, /* Bk */
283 286 { NULL, NULL }, /* Ek */
284 287 { NULL, posts_eoln }, /* Bt */
285 288 { NULL, NULL }, /* Hf */
286 289 { NULL, NULL }, /* Fr */
287 290 { NULL, posts_eoln }, /* Ud */
288 291 { NULL, posts_lb }, /* Lb */
289 - { NULL, posts_notext }, /* Lp */
292 + { pres_pp, posts_pp }, /* Lp */
290 293 { NULL, NULL }, /* Lk */
291 294 { NULL, posts_defaults }, /* Mt */
292 295 { NULL, NULL }, /* Brq */
293 296 { NULL, NULL }, /* Bro */
294 297 { NULL, NULL }, /* Brc */
295 298 { NULL, posts_text }, /* %C */
296 299 { NULL, NULL }, /* Es */
297 300 { NULL, NULL }, /* En */
298 301 { NULL, NULL }, /* Dx */
299 302 { NULL, posts_text }, /* %Q */
300 - { NULL, posts_notext }, /* br */
301 - { pres_pp, posts_sp }, /* sp */
303 + { NULL, posts_pp }, /* br */
304 + { NULL, posts_sp }, /* sp */
302 305 { NULL, posts_text1 }, /* %U */
303 306 { NULL, NULL }, /* Ta */
304 307 };
305 308
306 309 #define RSORD_MAX 14 /* Number of `Rs' blocks. */
307 310
308 311 static const enum mdoct rsord[RSORD_MAX] = {
309 312 MDOC__A,
310 313 MDOC__T,
311 314 MDOC__B,
312 315 MDOC__I,
313 316 MDOC__J,
314 317 MDOC__R,
315 318 MDOC__N,
316 319 MDOC__V,
320 + MDOC__U,
317 321 MDOC__P,
318 322 MDOC__Q,
319 - MDOC__D,
320 - MDOC__O,
321 323 MDOC__C,
322 - MDOC__U
324 + MDOC__D,
325 + MDOC__O
323 326 };
324 327
325 328 static const char * const secnames[SEC__MAX] = {
326 329 NULL,
327 330 "NAME",
328 331 "LIBRARY",
329 332 "SYNOPSIS",
330 333 "DESCRIPTION",
331 334 "IMPLEMENTATION NOTES",
332 335 "RETURN VALUES",
333 336 "ENVIRONMENT",
334 337 "FILES",
335 338 "EXIT STATUS",
336 339 "EXAMPLES",
337 340 "DIAGNOSTICS",
338 341 "COMPATIBILITY",
339 342 "ERRORS",
340 343 "SEE ALSO",
341 344 "STANDARDS",
342 345 "HISTORY",
343 346 "AUTHORS",
344 347 "CAVEATS",
345 348 "BUGS",
346 349 "SECURITY CONSIDERATIONS",
347 350 NULL
348 351 };
349 352
350 353 int
351 354 mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n)
352 355 {
353 356 v_pre *p;
354 357 int line, pos;
355 358 char *tp;
356 359
357 360 switch (n->type) {
358 361 case (MDOC_TEXT):
359 362 tp = n->string;
360 363 line = n->line;
361 364 pos = n->pos;
362 365 check_text(mdoc, line, pos, tp);
363 366 /* FALLTHROUGH */
364 367 case (MDOC_TBL):
365 368 /* FALLTHROUGH */
366 369 case (MDOC_EQN):
367 370 /* FALLTHROUGH */
368 371 case (MDOC_ROOT):
369 372 return(1);
370 373 default:
371 374 break;
372 375 }
373 376
374 377 check_args(mdoc, n);
375 378
376 379 if (NULL == mdoc_valids[n->tok].pre)
377 380 return(1);
378 381 for (p = mdoc_valids[n->tok].pre; *p; p++)
379 382 if ( ! (*p)(mdoc, n))
380 383 return(0);
381 384 return(1);
382 385 }
383 386
384 387
385 388 int
386 389 mdoc_valid_post(struct mdoc *mdoc)
387 390 {
388 391 v_post *p;
389 392
390 393 if (MDOC_VALID & mdoc->last->flags)
391 394 return(1);
392 395 mdoc->last->flags |= MDOC_VALID;
393 396
394 397 switch (mdoc->last->type) {
395 398 case (MDOC_TEXT):
396 399 /* FALLTHROUGH */
397 400 case (MDOC_EQN):
398 401 /* FALLTHROUGH */
399 402 case (MDOC_TBL):
400 403 return(1);
401 404 case (MDOC_ROOT):
402 405 return(post_root(mdoc));
403 406 default:
404 407 break;
405 408 }
406 409
↓ open down ↓ |
74 lines elided |
↑ open up ↑ |
407 410 if (NULL == mdoc_valids[mdoc->last->tok].post)
408 411 return(1);
409 412 for (p = mdoc_valids[mdoc->last->tok].post; *p; p++)
410 413 if ( ! (*p)(mdoc))
411 414 return(0);
412 415
413 416 return(1);
414 417 }
415 418
416 419 static int
417 -check_count(struct mdoc *m, enum mdoc_type type,
420 +check_count(struct mdoc *mdoc, enum mdoc_type type,
418 421 enum check_lvl lvl, enum check_ineq ineq, int val)
419 422 {
420 423 const char *p;
421 424 enum mandocerr t;
422 425
423 - if (m->last->type != type)
426 + if (mdoc->last->type != type)
424 427 return(1);
425 428
426 429 switch (ineq) {
427 430 case (CHECK_LT):
428 431 p = "less than ";
429 - if (m->last->nchild < val)
432 + if (mdoc->last->nchild < val)
430 433 return(1);
431 434 break;
432 435 case (CHECK_GT):
433 436 p = "more than ";
434 - if (m->last->nchild > val)
437 + if (mdoc->last->nchild > val)
435 438 return(1);
436 439 break;
437 440 case (CHECK_EQ):
438 441 p = "";
439 - if (val == m->last->nchild)
442 + if (val == mdoc->last->nchild)
440 443 return(1);
441 444 break;
442 445 default:
443 446 abort();
444 447 /* NOTREACHED */
445 448 }
446 449
447 450 t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
448 - mandoc_vmsg(t, m->parse, m->last->line, m->last->pos,
451 + mandoc_vmsg(t, mdoc->parse, mdoc->last->line, mdoc->last->pos,
449 452 "want %s%d children (have %d)",
450 - p, val, m->last->nchild);
453 + p, val, mdoc->last->nchild);
451 454 return(1);
452 455 }
453 456
454 457 static int
455 458 berr_ge1(POST_ARGS)
456 459 {
457 460
458 461 return(check_count(mdoc, MDOC_BODY, CHECK_ERROR, CHECK_GT, 0));
459 462 }
460 463
461 464 static int
462 465 bwarn_ge1(POST_ARGS)
463 466 {
464 467 return(check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0));
465 468 }
466 469
467 470 static int
468 471 ewarn_eq0(POST_ARGS)
469 472 {
470 473 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0));
471 474 }
472 475
473 476 static int
474 477 ewarn_eq1(POST_ARGS)
475 478 {
476 479 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1));
477 480 }
478 481
479 482 static int
480 483 ewarn_ge1(POST_ARGS)
481 484 {
482 485 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0));
483 486 }
484 487
485 488 static int
486 489 ewarn_le1(POST_ARGS)
487 490 {
488 491 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2));
489 492 }
490 493
491 494 static int
492 495 hwarn_eq0(POST_ARGS)
493 496 {
494 497 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0));
495 498 }
496 499
497 500 static int
498 501 hwarn_eq1(POST_ARGS)
499 502 {
500 503 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 1));
501 504 }
502 505
503 506 static int
504 507 hwarn_ge1(POST_ARGS)
505 508 {
↓ open down ↓ |
45 lines elided |
↑ open up ↑ |
506 509 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_GT, 0));
507 510 }
508 511
509 512 static int
510 513 hwarn_le1(POST_ARGS)
511 514 {
512 515 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_LT, 2));
513 516 }
514 517
515 518 static void
516 -check_args(struct mdoc *m, struct mdoc_node *n)
519 +check_args(struct mdoc *mdoc, struct mdoc_node *n)
517 520 {
518 521 int i;
519 522
520 523 if (NULL == n->args)
521 524 return;
522 525
523 526 assert(n->args->argc);
524 527 for (i = 0; i < (int)n->args->argc; i++)
525 - check_argv(m, n, &n->args->argv[i]);
528 + check_argv(mdoc, n, &n->args->argv[i]);
526 529 }
527 530
528 531 static void
529 -check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v)
532 +check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v)
530 533 {
531 534 int i;
532 535
533 536 for (i = 0; i < (int)v->sz; i++)
534 - check_text(m, v->line, v->pos, v->value[i]);
537 + check_text(mdoc, v->line, v->pos, v->value[i]);
535 538
536 539 /* FIXME: move to post_std(). */
537 540
538 541 if (MDOC_Std == v->arg)
539 - if ( ! (v->sz || m->meta.name))
540 - mdoc_nmsg(m, n, MANDOCERR_NONAME);
542 + if ( ! (v->sz || mdoc->meta.name))
543 + mdoc_nmsg(mdoc, n, MANDOCERR_NONAME);
541 544 }
542 545
543 546 static void
544 -check_text(struct mdoc *m, int ln, int pos, char *p)
547 +check_text(struct mdoc *mdoc, int ln, int pos, char *p)
545 548 {
546 549 char *cp;
547 550
548 - if (MDOC_LITERAL & m->flags)
551 + if (MDOC_LITERAL & mdoc->flags)
549 552 return;
550 553
551 554 for (cp = p; NULL != (p = strchr(p, '\t')); p++)
552 - mdoc_pmsg(m, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
555 + mdoc_pmsg(mdoc, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
553 556 }
554 557
555 558 static int
556 559 check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t)
557 560 {
558 561
559 562 assert(n->parent);
560 563 if ((MDOC_ROOT == t || tok == n->parent->tok) &&
561 564 (t == n->parent->type))
562 565 return(1);
563 566
564 567 mandoc_vmsg(MANDOCERR_SYNTCHILD, mdoc->parse, n->line,
565 568 n->pos, "want parent %s", MDOC_ROOT == t ?
566 569 "<root>" : mdoc_macronames[tok]);
567 570 return(0);
568 571 }
569 572
570 573
571 574 static int
572 575 pre_display(PRE_ARGS)
573 576 {
574 577 struct mdoc_node *node;
575 578
576 579 if (MDOC_BLOCK != n->type)
577 580 return(1);
578 581
579 582 for (node = mdoc->last->parent; node; node = node->parent)
580 583 if (MDOC_BLOCK == node->type)
581 584 if (MDOC_Bd == node->tok)
582 585 break;
583 586
584 587 if (node)
585 588 mdoc_nmsg(mdoc, n, MANDOCERR_NESTEDDISP);
586 589
587 590 return(1);
588 591 }
589 592
590 593
591 594 static int
592 595 pre_bl(PRE_ARGS)
593 596 {
594 597 int i, comp, dup;
595 598 const char *offs, *width;
596 599 enum mdoc_list lt;
597 600 struct mdoc_node *np;
598 601
599 602 if (MDOC_BLOCK != n->type) {
600 603 if (ENDBODY_NOT != n->end) {
601 604 assert(n->pending);
602 605 np = n->pending->parent;
603 606 } else
604 607 np = n->parent;
605 608
606 609 assert(np);
607 610 assert(MDOC_BLOCK == np->type);
608 611 assert(MDOC_Bl == np->tok);
609 612 return(1);
610 613 }
611 614
612 615 /*
613 616 * First figure out which kind of list to use: bind ourselves to
614 617 * the first mentioned list type and warn about any remaining
615 618 * ones. If we find no list type, we default to LIST_item.
616 619 */
617 620
618 621 /* LINTED */
619 622 for (i = 0; n->args && i < (int)n->args->argc; i++) {
620 623 lt = LIST__NONE;
621 624 dup = comp = 0;
622 625 width = offs = NULL;
623 626 switch (n->args->argv[i].arg) {
624 627 /* Set list types. */
625 628 case (MDOC_Bullet):
626 629 lt = LIST_bullet;
627 630 break;
628 631 case (MDOC_Dash):
629 632 lt = LIST_dash;
630 633 break;
631 634 case (MDOC_Enum):
632 635 lt = LIST_enum;
633 636 break;
634 637 case (MDOC_Hyphen):
635 638 lt = LIST_hyphen;
636 639 break;
637 640 case (MDOC_Item):
638 641 lt = LIST_item;
639 642 break;
640 643 case (MDOC_Tag):
641 644 lt = LIST_tag;
642 645 break;
643 646 case (MDOC_Diag):
644 647 lt = LIST_diag;
645 648 break;
646 649 case (MDOC_Hang):
647 650 lt = LIST_hang;
648 651 break;
649 652 case (MDOC_Ohang):
650 653 lt = LIST_ohang;
651 654 break;
652 655 case (MDOC_Inset):
653 656 lt = LIST_inset;
654 657 break;
655 658 case (MDOC_Column):
656 659 lt = LIST_column;
657 660 break;
658 661 /* Set list arguments. */
659 662 case (MDOC_Compact):
660 663 dup = n->norm->Bl.comp;
661 664 comp = 1;
662 665 break;
663 666 case (MDOC_Width):
664 667 /* NB: this can be empty! */
665 668 if (n->args->argv[i].sz) {
666 669 width = n->args->argv[i].value[0];
667 670 dup = (NULL != n->norm->Bl.width);
668 671 break;
669 672 }
670 673 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV);
671 674 break;
672 675 case (MDOC_Offset):
673 676 /* NB: this can be empty! */
674 677 if (n->args->argv[i].sz) {
675 678 offs = n->args->argv[i].value[0];
676 679 dup = (NULL != n->norm->Bl.offs);
677 680 break;
678 681 }
679 682 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV);
680 683 break;
681 684 default:
682 685 continue;
683 686 }
684 687
685 688 /* Check: duplicate auxiliary arguments. */
686 689
687 690 if (dup)
688 691 mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP);
689 692
690 693 if (comp && ! dup)
691 694 n->norm->Bl.comp = comp;
692 695 if (offs && ! dup)
693 696 n->norm->Bl.offs = offs;
694 697 if (width && ! dup)
695 698 n->norm->Bl.width = width;
696 699
697 700 /* Check: multiple list types. */
698 701
699 702 if (LIST__NONE != lt && n->norm->Bl.type != LIST__NONE)
700 703 mdoc_nmsg(mdoc, n, MANDOCERR_LISTREP);
701 704
702 705 /* Assign list type. */
703 706
704 707 if (LIST__NONE != lt && n->norm->Bl.type == LIST__NONE) {
705 708 n->norm->Bl.type = lt;
706 709 /* Set column information, too. */
707 710 if (LIST_column == lt) {
708 711 n->norm->Bl.ncols =
709 712 n->args->argv[i].sz;
710 713 n->norm->Bl.cols = (void *)
711 714 n->args->argv[i].value;
712 715 }
713 716 }
714 717
715 718 /* The list type should come first. */
716 719
717 720 if (n->norm->Bl.type == LIST__NONE)
718 721 if (n->norm->Bl.width ||
719 722 n->norm->Bl.offs ||
720 723 n->norm->Bl.comp)
721 724 mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST);
722 725
723 726 continue;
724 727 }
725 728
↓ open down ↓ |
163 lines elided |
↑ open up ↑ |
726 729 /* Allow lists to default to LIST_item. */
727 730
728 731 if (LIST__NONE == n->norm->Bl.type) {
729 732 mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE);
730 733 n->norm->Bl.type = LIST_item;
731 734 }
732 735
733 736 /*
734 737 * Validate the width field. Some list types don't need width
735 738 * types and should be warned about them. Others should have it
736 - * and must also be warned.
739 + * and must also be warned. Yet others have a default and need
740 + * no warning.
737 741 */
738 742
739 743 switch (n->norm->Bl.type) {
740 744 case (LIST_tag):
741 - if (n->norm->Bl.width)
742 - break;
743 - mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
745 + if (NULL == n->norm->Bl.width)
746 + mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
744 747 break;
745 748 case (LIST_column):
746 749 /* FALLTHROUGH */
747 750 case (LIST_diag):
748 751 /* FALLTHROUGH */
749 752 case (LIST_ohang):
750 753 /* FALLTHROUGH */
751 754 case (LIST_inset):
752 755 /* FALLTHROUGH */
753 756 case (LIST_item):
754 757 if (n->norm->Bl.width)
755 758 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV);
756 759 break;
760 + case (LIST_bullet):
761 + /* FALLTHROUGH */
762 + case (LIST_dash):
763 + /* FALLTHROUGH */
764 + case (LIST_hyphen):
765 + if (NULL == n->norm->Bl.width)
766 + n->norm->Bl.width = "2n";
767 + break;
768 + case (LIST_enum):
769 + if (NULL == n->norm->Bl.width)
770 + n->norm->Bl.width = "3n";
771 + break;
757 772 default:
758 773 break;
759 774 }
760 775
761 776 return(1);
762 777 }
763 778
764 779
765 780 static int
766 781 pre_bd(PRE_ARGS)
767 782 {
768 783 int i, dup, comp;
769 784 enum mdoc_disp dt;
770 785 const char *offs;
771 786 struct mdoc_node *np;
772 787
773 788 if (MDOC_BLOCK != n->type) {
774 789 if (ENDBODY_NOT != n->end) {
775 790 assert(n->pending);
776 791 np = n->pending->parent;
777 792 } else
778 793 np = n->parent;
779 794
780 795 assert(np);
781 796 assert(MDOC_BLOCK == np->type);
782 797 assert(MDOC_Bd == np->tok);
783 798 return(1);
784 799 }
785 800
786 801 /* LINTED */
787 802 for (i = 0; n->args && i < (int)n->args->argc; i++) {
788 803 dt = DISP__NONE;
789 804 dup = comp = 0;
790 805 offs = NULL;
791 806
792 807 switch (n->args->argv[i].arg) {
793 808 case (MDOC_Centred):
794 809 dt = DISP_centred;
795 810 break;
796 811 case (MDOC_Ragged):
797 812 dt = DISP_ragged;
798 813 break;
799 814 case (MDOC_Unfilled):
800 815 dt = DISP_unfilled;
801 816 break;
802 817 case (MDOC_Filled):
803 818 dt = DISP_filled;
804 819 break;
805 820 case (MDOC_Literal):
806 821 dt = DISP_literal;
807 822 break;
808 823 case (MDOC_File):
809 824 mdoc_nmsg(mdoc, n, MANDOCERR_BADDISP);
810 825 return(0);
811 826 case (MDOC_Offset):
812 827 /* NB: this can be empty! */
813 828 if (n->args->argv[i].sz) {
814 829 offs = n->args->argv[i].value[0];
815 830 dup = (NULL != n->norm->Bd.offs);
816 831 break;
817 832 }
818 833 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV);
819 834 break;
820 835 case (MDOC_Compact):
821 836 comp = 1;
822 837 dup = n->norm->Bd.comp;
823 838 break;
824 839 default:
825 840 abort();
826 841 /* NOTREACHED */
827 842 }
828 843
829 844 /* Check whether we have duplicates. */
830 845
831 846 if (dup)
832 847 mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP);
833 848
834 849 /* Make our auxiliary assignments. */
835 850
836 851 if (offs && ! dup)
837 852 n->norm->Bd.offs = offs;
838 853 if (comp && ! dup)
839 854 n->norm->Bd.comp = comp;
840 855
841 856 /* Check whether a type has already been assigned. */
842 857
843 858 if (DISP__NONE != dt && n->norm->Bd.type != DISP__NONE)
844 859 mdoc_nmsg(mdoc, n, MANDOCERR_DISPREP);
845 860
846 861 /* Make our type assignment. */
847 862
848 863 if (DISP__NONE != dt && n->norm->Bd.type == DISP__NONE)
849 864 n->norm->Bd.type = dt;
850 865 }
851 866
852 867 if (DISP__NONE == n->norm->Bd.type) {
853 868 mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE);
854 869 n->norm->Bd.type = DISP_ragged;
855 870 }
856 871
857 872 return(1);
858 873 }
859 874
860 875
861 876 static int
862 877 pre_ss(PRE_ARGS)
863 878 {
864 879
865 880 if (MDOC_BLOCK != n->type)
866 881 return(1);
↓ open down ↓ |
100 lines elided |
↑ open up ↑ |
867 882 return(check_parent(mdoc, n, MDOC_Sh, MDOC_BODY));
868 883 }
869 884
870 885
871 886 static int
872 887 pre_sh(PRE_ARGS)
873 888 {
874 889
875 890 if (MDOC_BLOCK != n->type)
876 891 return(1);
877 -
878 - roff_regunset(mdoc->roff, REG_nS);
879 892 return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
880 893 }
881 894
882 895
883 896 static int
884 897 pre_it(PRE_ARGS)
885 898 {
886 899
887 900 if (MDOC_BLOCK != n->type)
888 901 return(1);
889 902
890 903 return(check_parent(mdoc, n, MDOC_Bl, MDOC_BODY));
891 904 }
892 905
893 906
894 907 static int
895 908 pre_an(PRE_ARGS)
896 909 {
897 910 int i;
898 911
899 912 if (NULL == n->args)
900 913 return(1);
901 914
902 915 for (i = 1; i < (int)n->args->argc; i++)
903 916 mdoc_pmsg(mdoc, n->args->argv[i].line,
904 917 n->args->argv[i].pos, MANDOCERR_IGNARGV);
905 918
906 919 if (MDOC_Split == n->args->argv[0].arg)
907 920 n->norm->An.auth = AUTH_split;
908 921 else if (MDOC_Nosplit == n->args->argv[0].arg)
909 922 n->norm->An.auth = AUTH_nosplit;
910 923 else
911 924 abort();
912 925
913 926 return(1);
914 927 }
915 928
916 929 static int
917 930 pre_std(PRE_ARGS)
918 931 {
919 932
920 933 if (n->args && 1 == n->args->argc)
921 934 if (MDOC_Std == n->args->argv[0].arg)
922 935 return(1);
923 936
924 937 mdoc_nmsg(mdoc, n, MANDOCERR_NOARGV);
925 938 return(1);
926 939 }
927 940
928 941 static int
929 942 pre_dt(PRE_ARGS)
930 943 {
931 944
932 945 if (NULL == mdoc->meta.date || mdoc->meta.os)
933 946 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO);
934 947
935 948 if (mdoc->meta.title)
936 949 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP);
937 950
938 951 return(1);
939 952 }
940 953
941 954 static int
942 955 pre_os(PRE_ARGS)
943 956 {
944 957
945 958 if (NULL == mdoc->meta.title || NULL == mdoc->meta.date)
946 959 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO);
947 960
948 961 if (mdoc->meta.os)
949 962 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP);
950 963
951 964 return(1);
952 965 }
953 966
954 967 static int
955 968 pre_dd(PRE_ARGS)
956 969 {
957 970
958 971 if (mdoc->meta.title || mdoc->meta.os)
959 972 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO);
960 973
961 974 if (mdoc->meta.date)
962 975 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP);
963 976
964 977 return(1);
965 978 }
966 979
967 980
968 981 static int
969 982 post_bf(POST_ARGS)
970 983 {
971 984 struct mdoc_node *np;
972 985 enum mdocargt arg;
973 986
974 987 /*
975 988 * Unlike other data pointers, these are "housed" by the HEAD
976 989 * element, which contains the goods.
977 990 */
978 991
979 992 if (MDOC_HEAD != mdoc->last->type) {
980 993 if (ENDBODY_NOT != mdoc->last->end) {
981 994 assert(mdoc->last->pending);
982 995 np = mdoc->last->pending->parent->head;
983 996 } else if (MDOC_BLOCK != mdoc->last->type) {
984 997 np = mdoc->last->parent->head;
985 998 } else
986 999 np = mdoc->last->head;
987 1000
988 1001 assert(np);
989 1002 assert(MDOC_HEAD == np->type);
990 1003 assert(MDOC_Bf == np->tok);
991 1004 return(1);
992 1005 }
993 1006
994 1007 np = mdoc->last;
995 1008 assert(MDOC_BLOCK == np->parent->type);
996 1009 assert(MDOC_Bf == np->parent->tok);
997 1010
998 1011 /*
999 1012 * Cannot have both argument and parameter.
1000 1013 * If neither is specified, let it through with a warning.
1001 1014 */
1002 1015
1003 1016 if (np->parent->args && np->child) {
1004 1017 mdoc_nmsg(mdoc, np, MANDOCERR_SYNTARGVCOUNT);
1005 1018 return(0);
1006 1019 } else if (NULL == np->parent->args && NULL == np->child) {
1007 1020 mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE);
1008 1021 return(1);
1009 1022 }
1010 1023
1011 1024 /* Extract argument into data. */
1012 1025
1013 1026 if (np->parent->args) {
1014 1027 arg = np->parent->args->argv[0].arg;
1015 1028 if (MDOC_Emphasis == arg)
1016 1029 np->norm->Bf.font = FONT_Em;
1017 1030 else if (MDOC_Literal == arg)
1018 1031 np->norm->Bf.font = FONT_Li;
1019 1032 else if (MDOC_Symbolic == arg)
1020 1033 np->norm->Bf.font = FONT_Sy;
1021 1034 else
1022 1035 abort();
1023 1036 return(1);
1024 1037 }
1025 1038
1026 1039 /* Extract parameter into data. */
1027 1040
1028 1041 if (0 == strcmp(np->child->string, "Em"))
1029 1042 np->norm->Bf.font = FONT_Em;
1030 1043 else if (0 == strcmp(np->child->string, "Li"))
1031 1044 np->norm->Bf.font = FONT_Li;
1032 1045 else if (0 == strcmp(np->child->string, "Sy"))
1033 1046 np->norm->Bf.font = FONT_Sy;
1034 1047 else
1035 1048 mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE);
1036 1049
1037 1050 return(1);
1038 1051 }
1039 1052
1040 1053 static int
1041 1054 post_lb(POST_ARGS)
1042 1055 {
1043 1056 const char *p;
1044 1057 char *buf;
1045 1058 size_t sz;
1046 1059
1047 1060 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
1048 1061
1049 1062 assert(mdoc->last->child);
1050 1063 assert(MDOC_TEXT == mdoc->last->child->type);
1051 1064
1052 1065 p = mdoc_a2lib(mdoc->last->child->string);
1053 1066
1054 1067 /* If lookup ok, replace with table value. */
1055 1068
1056 1069 if (p) {
1057 1070 free(mdoc->last->child->string);
1058 1071 mdoc->last->child->string = mandoc_strdup(p);
1059 1072 return(1);
1060 1073 }
1061 1074
1062 1075 /* If not, use "library ``xxxx''. */
1063 1076
1064 1077 sz = strlen(mdoc->last->child->string) +
1065 1078 2 + strlen("\\(lqlibrary\\(rq");
1066 1079 buf = mandoc_malloc(sz);
1067 1080 snprintf(buf, sz, "library \\(lq%s\\(rq",
1068 1081 mdoc->last->child->string);
1069 1082 free(mdoc->last->child->string);
1070 1083 mdoc->last->child->string = buf;
1071 1084 return(1);
1072 1085 }
1073 1086
1074 1087 static int
1075 1088 post_eoln(POST_ARGS)
1076 1089 {
1077 1090
1078 1091 if (mdoc->last->child)
1079 1092 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST);
1080 1093 return(1);
1081 1094 }
1082 1095
1083 1096
1084 1097 static int
1085 1098 post_vt(POST_ARGS)
1086 1099 {
1087 1100 const struct mdoc_node *n;
1088 1101
1089 1102 /*
1090 1103 * The Vt macro comes in both ELEM and BLOCK form, both of which
1091 1104 * have different syntaxes (yet more context-sensitive
1092 1105 * behaviour). ELEM types must have a child, which is already
1093 1106 * guaranteed by the in_line parsing routine; BLOCK types,
1094 1107 * specifically the BODY, should only have TEXT children.
1095 1108 */
1096 1109
1097 1110 if (MDOC_BODY != mdoc->last->type)
1098 1111 return(1);
1099 1112
1100 1113 for (n = mdoc->last->child; n; n = n->next)
1101 1114 if (MDOC_TEXT != n->type)
1102 1115 mdoc_nmsg(mdoc, n, MANDOCERR_CHILD);
1103 1116
↓ open down ↓ |
215 lines elided |
↑ open up ↑ |
1104 1117 return(1);
1105 1118 }
1106 1119
1107 1120
1108 1121 static int
1109 1122 post_nm(POST_ARGS)
1110 1123 {
1111 1124 char buf[BUFSIZ];
1112 1125 int c;
1113 1126
1114 - /* If no child specified, make sure we have the meta name. */
1115 -
1116 - if (NULL == mdoc->last->child && NULL == mdoc->meta.name) {
1117 - mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
1127 + if (NULL != mdoc->meta.name)
1118 1128 return(1);
1119 - } else if (mdoc->meta.name)
1120 - return(1);
1121 1129
1122 - /* If no meta name, set it from the child. */
1130 + /* Try to use our children for setting the meta name. */
1123 1131
1124 - buf[0] = '\0';
1125 - if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) {
1132 + if (NULL != mdoc->last->child) {
1133 + buf[0] = '\0';
1134 + c = concat(buf, mdoc->last->child, BUFSIZ);
1135 + } else
1136 + c = 0;
1137 +
1138 + switch (c) {
1139 + case (-1):
1126 1140 mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM);
1127 1141 return(0);
1142 + case (0):
1143 + mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
1144 + mdoc->meta.name = mandoc_strdup("UNKNOWN");
1145 + break;
1146 + default:
1147 + mdoc->meta.name = mandoc_strdup(buf);
1148 + break;
1128 1149 }
1129 -
1130 - assert(c);
1131 - mdoc->meta.name = mandoc_strdup(buf);
1132 1150 return(1);
1133 1151 }
1134 1152
1135 1153 static int
1136 1154 post_literal(POST_ARGS)
1137 1155 {
1138 1156
1139 1157 /*
1140 1158 * The `Dl' (note "el" not "one") and `Bd' macros unset the
1141 1159 * MDOC_LITERAL flag as they leave. Note that `Bd' only sets
1142 1160 * this in literal mode, but it doesn't hurt to just switch it
1143 1161 * off in general since displays can't be nested.
1144 1162 */
1145 1163
1146 1164 if (MDOC_BODY == mdoc->last->type)
1147 1165 mdoc->flags &= ~MDOC_LITERAL;
1148 1166
1149 1167 return(1);
1150 1168 }
1151 1169
1152 1170 static int
1153 1171 post_defaults(POST_ARGS)
1154 1172 {
1155 1173 struct mdoc_node *nn;
1156 1174
1157 1175 /*
1158 1176 * The `Ar' defaults to "file ..." if no value is provided as an
1159 1177 * argument; the `Mt' and `Pa' macros use "~"; the `Li' just
1160 1178 * gets an empty string.
1161 1179 */
1162 1180
1163 1181 if (mdoc->last->child)
1164 1182 return(1);
1165 1183
1166 1184 nn = mdoc->last;
1167 1185 mdoc->next = MDOC_NEXT_CHILD;
1168 1186
1169 1187 switch (nn->tok) {
1170 1188 case (MDOC_Ar):
1171 1189 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "file"))
1172 1190 return(0);
1173 1191 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "..."))
1174 1192 return(0);
1175 1193 break;
1176 1194 case (MDOC_At):
1177 1195 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "AT&T"))
1178 1196 return(0);
1179 1197 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "UNIX"))
1180 1198 return(0);
1181 1199 break;
1182 1200 case (MDOC_Li):
1183 1201 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, ""))
1184 1202 return(0);
1185 1203 break;
1186 1204 case (MDOC_Pa):
1187 1205 /* FALLTHROUGH */
1188 1206 case (MDOC_Mt):
1189 1207 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "~"))
1190 1208 return(0);
1191 1209 break;
1192 1210 default:
1193 1211 abort();
1194 1212 /* NOTREACHED */
1195 1213 }
1196 1214
1197 1215 mdoc->last = nn;
1198 1216 return(1);
1199 1217 }
1200 1218
1201 1219 static int
1202 1220 post_at(POST_ARGS)
1203 1221 {
1204 1222 const char *p, *q;
1205 1223 char *buf;
1206 1224 size_t sz;
1207 1225
1208 1226 /*
1209 1227 * If we have a child, look it up in the standard keys. If a
1210 1228 * key exist, use that instead of the child; if it doesn't,
1211 1229 * prefix "AT&T UNIX " to the existing data.
1212 1230 */
1213 1231
1214 1232 if (NULL == mdoc->last->child)
1215 1233 return(1);
1216 1234
1217 1235 assert(MDOC_TEXT == mdoc->last->child->type);
1218 1236 p = mdoc_a2att(mdoc->last->child->string);
1219 1237
1220 1238 if (p) {
1221 1239 free(mdoc->last->child->string);
1222 1240 mdoc->last->child->string = mandoc_strdup(p);
1223 1241 } else {
1224 1242 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADATT);
1225 1243 p = "AT&T UNIX ";
1226 1244 q = mdoc->last->child->string;
1227 1245 sz = strlen(p) + strlen(q) + 1;
1228 1246 buf = mandoc_malloc(sz);
1229 1247 strlcpy(buf, p, sz);
1230 1248 strlcat(buf, q, sz);
1231 1249 free(mdoc->last->child->string);
1232 1250 mdoc->last->child->string = buf;
1233 1251 }
1234 1252
1235 1253 return(1);
1236 1254 }
1237 1255
1238 1256 static int
1239 1257 post_an(POST_ARGS)
1240 1258 {
1241 1259 struct mdoc_node *np;
1242 1260
1243 1261 np = mdoc->last;
1244 1262 if (AUTH__NONE == np->norm->An.auth) {
1245 1263 if (0 == np->child)
1246 1264 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0);
1247 1265 } else if (np->child)
1248 1266 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0);
1249 1267
1250 1268 return(1);
1251 1269 }
1252 1270
1253 1271
1254 1272 static int
1255 1273 post_it(POST_ARGS)
1256 1274 {
1257 1275 int i, cols;
1258 1276 enum mdoc_list lt;
1259 1277 struct mdoc_node *n, *c;
1260 1278 enum mandocerr er;
1261 1279
1262 1280 if (MDOC_BLOCK != mdoc->last->type)
1263 1281 return(1);
1264 1282
1265 1283 n = mdoc->last->parent->parent;
1266 1284 lt = n->norm->Bl.type;
1267 1285
1268 1286 if (LIST__NONE == lt) {
1269 1287 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE);
1270 1288 return(1);
1271 1289 }
1272 1290
1273 1291 switch (lt) {
1274 1292 case (LIST_tag):
1275 1293 if (mdoc->last->head->child)
1276 1294 break;
1277 1295 /* FIXME: give this a dummy value. */
1278 1296 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS);
1279 1297 break;
1280 1298 case (LIST_hang):
1281 1299 /* FALLTHROUGH */
1282 1300 case (LIST_ohang):
1283 1301 /* FALLTHROUGH */
1284 1302 case (LIST_inset):
1285 1303 /* FALLTHROUGH */
1286 1304 case (LIST_diag):
1287 1305 if (NULL == mdoc->last->head->child)
1288 1306 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS);
1289 1307 break;
1290 1308 case (LIST_bullet):
1291 1309 /* FALLTHROUGH */
1292 1310 case (LIST_dash):
1293 1311 /* FALLTHROUGH */
1294 1312 case (LIST_enum):
1295 1313 /* FALLTHROUGH */
1296 1314 case (LIST_hyphen):
1297 1315 if (NULL == mdoc->last->body->child)
1298 1316 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY);
1299 1317 /* FALLTHROUGH */
1300 1318 case (LIST_item):
1301 1319 if (mdoc->last->head->child)
1302 1320 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST);
1303 1321 break;
1304 1322 case (LIST_column):
1305 1323 cols = (int)n->norm->Bl.ncols;
1306 1324
1307 1325 assert(NULL == mdoc->last->head->child);
1308 1326
1309 1327 if (NULL == mdoc->last->body->child)
1310 1328 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY);
1311 1329
1312 1330 for (i = 0, c = mdoc->last->child; c; c = c->next)
1313 1331 if (MDOC_BODY == c->type)
1314 1332 i++;
1315 1333
1316 1334 if (i < cols)
1317 1335 er = MANDOCERR_ARGCOUNT;
1318 1336 else if (i == cols || i == cols + 1)
1319 1337 break;
1320 1338 else
1321 1339 er = MANDOCERR_SYNTARGCOUNT;
1322 1340
1323 1341 mandoc_vmsg(er, mdoc->parse, mdoc->last->line,
1324 1342 mdoc->last->pos,
1325 1343 "columns == %d (have %d)", cols, i);
1326 1344 return(MANDOCERR_ARGCOUNT == er);
↓ open down ↓ |
185 lines elided |
↑ open up ↑ |
1327 1345 default:
1328 1346 break;
1329 1347 }
1330 1348
1331 1349 return(1);
1332 1350 }
1333 1351
1334 1352 static int
1335 1353 post_bl_block(POST_ARGS)
1336 1354 {
1337 - struct mdoc_node *n;
1355 + struct mdoc_node *n, *ni, *nc;
1338 1356
1339 1357 /*
1340 1358 * These are fairly complicated, so we've broken them into two
1341 1359 * functions. post_bl_block_tag() is called when a -tag is
1342 1360 * specified, but no -width (it must be guessed). The second
1343 1361 * when a -width is specified (macro indicators must be
1344 1362 * rewritten into real lengths).
1345 1363 */
1346 1364
1347 1365 n = mdoc->last;
1348 1366
1349 1367 if (LIST_tag == n->norm->Bl.type &&
1350 1368 NULL == n->norm->Bl.width) {
1351 1369 if ( ! post_bl_block_tag(mdoc))
1352 1370 return(0);
1371 + assert(n->norm->Bl.width);
1353 1372 } else if (NULL != n->norm->Bl.width) {
1354 1373 if ( ! post_bl_block_width(mdoc))
1355 1374 return(0);
1356 - } else
1357 - return(1);
1375 + assert(n->norm->Bl.width);
1376 + }
1358 1377
1359 - assert(n->norm->Bl.width);
1378 + for (ni = n->body->child; ni; ni = ni->next) {
1379 + if (NULL == ni->body)
1380 + continue;
1381 + nc = ni->body->last;
1382 + while (NULL != nc) {
1383 + switch (nc->tok) {
1384 + case (MDOC_Pp):
1385 + /* FALLTHROUGH */
1386 + case (MDOC_Lp):
1387 + /* FALLTHROUGH */
1388 + case (MDOC_br):
1389 + break;
1390 + default:
1391 + nc = NULL;
1392 + continue;
1393 + }
1394 + if (NULL == ni->next) {
1395 + mdoc_nmsg(mdoc, nc, MANDOCERR_MOVEPAR);
1396 + if ( ! mdoc_node_relink(mdoc, nc))
1397 + return(0);
1398 + } else if (0 == n->norm->Bl.comp &&
1399 + LIST_column != n->norm->Bl.type) {
1400 + mdoc_nmsg(mdoc, nc, MANDOCERR_IGNPAR);
1401 + mdoc_node_delete(mdoc, nc);
1402 + } else
1403 + break;
1404 + nc = ni->body->last;
1405 + }
1406 + }
1360 1407 return(1);
1361 1408 }
1362 1409
1363 1410 static int
1364 1411 post_bl_block_width(POST_ARGS)
1365 1412 {
1366 1413 size_t width;
1367 1414 int i;
1368 1415 enum mdoct tok;
1369 1416 struct mdoc_node *n;
1370 1417 char buf[NUMSIZ];
1371 1418
1372 1419 n = mdoc->last;
1373 1420
1374 1421 /*
1375 1422 * Calculate the real width of a list from the -width string,
1376 1423 * which may contain a macro (with a known default width), a
1377 1424 * literal string, or a scaling width.
1378 1425 *
1379 1426 * If the value to -width is a macro, then we re-write it to be
1380 1427 * the macro's width as set in share/tmac/mdoc/doc-common.
1381 1428 */
1382 1429
1383 1430 if (0 == strcmp(n->norm->Bl.width, "Ds"))
1384 1431 width = 6;
1385 1432 else if (MDOC_MAX == (tok = mdoc_hash_find(n->norm->Bl.width)))
1386 1433 return(1);
1387 1434 else if (0 == (width = macro2len(tok))) {
1388 1435 mdoc_nmsg(mdoc, n, MANDOCERR_BADWIDTH);
1389 1436 return(1);
1390 1437 }
1391 1438
1392 1439 /* The value already exists: free and reallocate it. */
1393 1440
1394 1441 assert(n->args);
1395 1442
1396 1443 for (i = 0; i < (int)n->args->argc; i++)
1397 1444 if (MDOC_Width == n->args->argv[i].arg)
1398 1445 break;
1399 1446
1400 1447 assert(i < (int)n->args->argc);
1401 1448
1402 1449 snprintf(buf, NUMSIZ, "%un", (unsigned int)width);
1403 1450 free(n->args->argv[i].value[0]);
1404 1451 n->args->argv[i].value[0] = mandoc_strdup(buf);
1405 1452
1406 1453 /* Set our width! */
1407 1454 n->norm->Bl.width = n->args->argv[i].value[0];
1408 1455 return(1);
1409 1456 }
1410 1457
1411 1458 static int
1412 1459 post_bl_block_tag(POST_ARGS)
1413 1460 {
1414 1461 struct mdoc_node *n, *nn;
1415 1462 size_t sz, ssz;
1416 1463 int i;
1417 1464 char buf[NUMSIZ];
1418 1465
1419 1466 /*
1420 1467 * Calculate the -width for a `Bl -tag' list if it hasn't been
1421 1468 * provided. Uses the first head macro. NOTE AGAIN: this is
1422 1469 * ONLY if the -width argument has NOT been provided. See
1423 1470 * post_bl_block_width() for converting the -width string.
1424 1471 */
1425 1472
1426 1473 sz = 10;
1427 1474 n = mdoc->last;
1428 1475
1429 1476 for (nn = n->body->child; nn; nn = nn->next) {
1430 1477 if (MDOC_It != nn->tok)
1431 1478 continue;
1432 1479
1433 1480 assert(MDOC_BLOCK == nn->type);
1434 1481 nn = nn->head->child;
1435 1482
1436 1483 if (nn == NULL)
1437 1484 break;
1438 1485
1439 1486 if (MDOC_TEXT == nn->type) {
1440 1487 sz = strlen(nn->string) + 1;
1441 1488 break;
1442 1489 }
1443 1490
1444 1491 if (0 != (ssz = macro2len(nn->tok)))
1445 1492 sz = ssz;
1446 1493
1447 1494 break;
1448 1495 }
1449 1496
1450 1497 /* Defaults to ten ens. */
1451 1498
1452 1499 snprintf(buf, NUMSIZ, "%un", (unsigned int)sz);
1453 1500
1454 1501 /*
1455 1502 * We have to dynamically add this to the macro's argument list.
1456 1503 * We're guaranteed that a MDOC_Width doesn't already exist.
1457 1504 */
1458 1505
1459 1506 assert(n->args);
1460 1507 i = (int)(n->args->argc)++;
1461 1508
1462 1509 n->args->argv = mandoc_realloc(n->args->argv,
1463 1510 n->args->argc * sizeof(struct mdoc_argv));
1464 1511
1465 1512 n->args->argv[i].arg = MDOC_Width;
1466 1513 n->args->argv[i].line = n->line;
1467 1514 n->args->argv[i].pos = n->pos;
1468 1515 n->args->argv[i].sz = 1;
1469 1516 n->args->argv[i].value = mandoc_malloc(sizeof(char *));
1470 1517 n->args->argv[i].value[0] = mandoc_strdup(buf);
1471 1518
1472 1519 /* Set our width! */
1473 1520 n->norm->Bl.width = n->args->argv[i].value[0];
1474 1521 return(1);
1475 1522 }
1476 1523
1477 1524
1478 1525 static int
1479 1526 post_bl_head(POST_ARGS)
1480 1527 {
1481 1528 struct mdoc_node *np, *nn, *nnp;
1482 1529 int i, j;
1483 1530
1484 1531 if (LIST_column != mdoc->last->norm->Bl.type)
1485 1532 /* FIXME: this should be ERROR class... */
1486 1533 return(hwarn_eq0(mdoc));
1487 1534
1488 1535 /*
1489 1536 * Convert old-style lists, where the column width specifiers
1490 1537 * trail as macro parameters, to the new-style ("normal-form")
1491 1538 * lists where they're argument values following -column.
1492 1539 */
1493 1540
1494 1541 /* First, disallow both types and allow normal-form. */
1495 1542
1496 1543 /*
1497 1544 * TODO: technically, we can accept both and just merge the two
1498 1545 * lists, but I'll leave that for another day.
1499 1546 */
1500 1547
1501 1548 if (mdoc->last->norm->Bl.ncols && mdoc->last->nchild) {
1502 1549 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_COLUMNS);
1503 1550 return(0);
1504 1551 } else if (NULL == mdoc->last->child)
1505 1552 return(1);
1506 1553
1507 1554 np = mdoc->last->parent;
1508 1555 assert(np->args);
1509 1556
1510 1557 for (j = 0; j < (int)np->args->argc; j++)
1511 1558 if (MDOC_Column == np->args->argv[j].arg)
1512 1559 break;
1513 1560
1514 1561 assert(j < (int)np->args->argc);
1515 1562 assert(0 == np->args->argv[j].sz);
1516 1563
1517 1564 /*
1518 1565 * Accommodate for new-style groff column syntax. Shuffle the
1519 1566 * child nodes, all of which must be TEXT, as arguments for the
1520 1567 * column field. Then, delete the head children.
1521 1568 */
1522 1569
1523 1570 np->args->argv[j].sz = (size_t)mdoc->last->nchild;
1524 1571 np->args->argv[j].value = mandoc_malloc
1525 1572 ((size_t)mdoc->last->nchild * sizeof(char *));
1526 1573
1527 1574 mdoc->last->norm->Bl.ncols = np->args->argv[j].sz;
1528 1575 mdoc->last->norm->Bl.cols = (void *)np->args->argv[j].value;
1529 1576
1530 1577 for (i = 0, nn = mdoc->last->child; nn; i++) {
1531 1578 np->args->argv[j].value[i] = nn->string;
1532 1579 nn->string = NULL;
1533 1580 nnp = nn;
1534 1581 nn = nn->next;
1535 1582 mdoc_node_delete(NULL, nnp);
1536 1583 }
↓ open down ↓ |
167 lines elided |
↑ open up ↑ |
1537 1584
1538 1585 mdoc->last->nchild = 0;
1539 1586 mdoc->last->child = NULL;
1540 1587
1541 1588 return(1);
1542 1589 }
1543 1590
1544 1591 static int
1545 1592 post_bl(POST_ARGS)
1546 1593 {
1547 - struct mdoc_node *n;
1594 + struct mdoc_node *nparent, *nprev; /* of the Bl block */
1595 + struct mdoc_node *nblock, *nbody; /* of the Bl */
1596 + struct mdoc_node *nchild, *nnext; /* of the Bl body */
1548 1597
1549 - if (MDOC_HEAD == mdoc->last->type)
1550 - return(post_bl_head(mdoc));
1551 - if (MDOC_BLOCK == mdoc->last->type)
1598 + nbody = mdoc->last;
1599 + switch (nbody->type) {
1600 + case (MDOC_BLOCK):
1552 1601 return(post_bl_block(mdoc));
1553 - if (MDOC_BODY != mdoc->last->type)
1602 + case (MDOC_HEAD):
1603 + return(post_bl_head(mdoc));
1604 + case (MDOC_BODY):
1605 + break;
1606 + default:
1554 1607 return(1);
1608 + }
1555 1609
1556 - for (n = mdoc->last->child; n; n = n->next) {
1557 - switch (n->tok) {
1558 - case (MDOC_Lp):
1559 - /* FALLTHROUGH */
1560 - case (MDOC_Pp):
1561 - mdoc_nmsg(mdoc, n, MANDOCERR_CHILD);
1562 - /* FALLTHROUGH */
1563 - case (MDOC_It):
1564 - /* FALLTHROUGH */
1565 - case (MDOC_Sm):
1610 + nchild = nbody->child;
1611 + while (NULL != nchild) {
1612 + if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
1613 + nchild = nchild->next;
1566 1614 continue;
1567 - default:
1568 - break;
1569 1615 }
1570 1616
1571 - mdoc_nmsg(mdoc, n, MANDOCERR_SYNTCHILD);
1572 - return(0);
1617 + mdoc_nmsg(mdoc, nchild, MANDOCERR_CHILD);
1618 +
1619 + /*
1620 + * Move the node out of the Bl block.
1621 + * First, collect all required node pointers.
1622 + */
1623 +
1624 + nblock = nbody->parent;
1625 + nprev = nblock->prev;
1626 + nparent = nblock->parent;
1627 + nnext = nchild->next;
1628 +
1629 + /*
1630 + * Unlink this child.
1631 + */
1632 +
1633 + assert(NULL == nchild->prev);
1634 + if (0 == --nbody->nchild) {
1635 + nbody->child = NULL;
1636 + nbody->last = NULL;
1637 + assert(NULL == nnext);
1638 + } else {
1639 + nbody->child = nnext;
1640 + nnext->prev = NULL;
1641 + }
1642 +
1643 + /*
1644 + * Relink this child.
1645 + */
1646 +
1647 + nchild->parent = nparent;
1648 + nchild->prev = nprev;
1649 + nchild->next = nblock;
1650 +
1651 + nblock->prev = nchild;
1652 + nparent->nchild++;
1653 + if (NULL == nprev)
1654 + nparent->child = nchild;
1655 + else
1656 + nprev->next = nchild;
1657 +
1658 + nchild = nnext;
1573 1659 }
1574 1660
1575 1661 return(1);
1576 1662 }
1577 1663
1578 1664 static int
1579 1665 ebool(struct mdoc *mdoc)
1580 1666 {
1581 1667
1582 1668 if (NULL == mdoc->last->child) {
1583 1669 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY);
1584 1670 mdoc_node_delete(mdoc, mdoc->last);
1585 1671 return(1);
1586 1672 }
1587 1673 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
1588 1674
1589 1675 assert(MDOC_TEXT == mdoc->last->child->type);
1590 1676
1591 - if (0 == strcmp(mdoc->last->child->string, "on"))
1677 + if (0 == strcmp(mdoc->last->child->string, "on")) {
1678 + if (MDOC_Sm == mdoc->last->tok)
1679 + mdoc->flags &= ~MDOC_SMOFF;
1592 1680 return(1);
1593 - if (0 == strcmp(mdoc->last->child->string, "off"))
1681 + }
1682 + if (0 == strcmp(mdoc->last->child->string, "off")) {
1683 + if (MDOC_Sm == mdoc->last->tok)
1684 + mdoc->flags |= MDOC_SMOFF;
1594 1685 return(1);
1686 + }
1595 1687
1596 1688 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL);
1597 1689 return(1);
1598 1690 }
1599 1691
1600 1692 static int
1601 1693 post_root(POST_ARGS)
1602 1694 {
1603 1695 int erc;
1604 1696 struct mdoc_node *n;
1605 1697
1606 1698 erc = 0;
1607 1699
1608 1700 /* Check that we have a finished prologue. */
1609 1701
1610 1702 if ( ! (MDOC_PBODY & mdoc->flags)) {
1611 1703 erc++;
1612 1704 mdoc_nmsg(mdoc, mdoc->first, MANDOCERR_NODOCPROLOG);
1613 1705 }
1614 1706
1615 1707 n = mdoc->first;
1616 1708 assert(n);
1617 1709
1618 1710 /* Check that we begin with a proper `Sh'. */
1619 1711
1620 1712 if (NULL == n->child) {
1621 1713 erc++;
1622 1714 mdoc_nmsg(mdoc, n, MANDOCERR_NODOCBODY);
1623 1715 } else if (MDOC_BLOCK != n->child->type ||
1624 1716 MDOC_Sh != n->child->tok) {
1625 1717 erc++;
1626 1718 /* Can this be lifted? See rxdebug.1 for example. */
1627 1719 mdoc_nmsg(mdoc, n, MANDOCERR_NODOCBODY);
1628 1720 }
1629 1721
1630 1722 return(erc ? 0 : 1);
1631 1723 }
1632 1724
1633 1725 static int
1634 1726 post_st(POST_ARGS)
1635 1727 {
1636 1728 struct mdoc_node *ch;
1637 1729 const char *p;
1638 1730
1639 1731 if (NULL == (ch = mdoc->last->child)) {
1640 1732 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY);
1641 1733 mdoc_node_delete(mdoc, mdoc->last);
1642 1734 return(1);
1643 1735 }
1644 1736
1645 1737 assert(MDOC_TEXT == ch->type);
1646 1738
1647 1739 if (NULL == (p = mdoc_a2st(ch->string))) {
1648 1740 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADSTANDARD);
1649 1741 mdoc_node_delete(mdoc, mdoc->last);
1650 1742 } else {
1651 1743 free(ch->string);
1652 1744 ch->string = mandoc_strdup(p);
1653 1745 }
1654 1746
1655 1747 return(1);
1656 1748 }
1657 1749
1658 1750 static int
1659 1751 post_rs(POST_ARGS)
1660 1752 {
1661 1753 struct mdoc_node *nn, *next, *prev;
1662 1754 int i, j;
1663 1755
1664 1756 switch (mdoc->last->type) {
1665 1757 case (MDOC_HEAD):
1666 1758 check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0);
1667 1759 return(1);
1668 1760 case (MDOC_BODY):
1669 1761 if (mdoc->last->child)
1670 1762 break;
1671 1763 check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0);
1672 1764 return(1);
1673 1765 default:
1674 1766 return(1);
1675 1767 }
1676 1768
1677 1769 /*
1678 1770 * Make sure only certain types of nodes are allowed within the
1679 1771 * the `Rs' body. Delete offending nodes and raise a warning.
1680 1772 * Do this before re-ordering for the sake of clarity.
1681 1773 */
1682 1774
1683 1775 next = NULL;
1684 1776 for (nn = mdoc->last->child; nn; nn = next) {
1685 1777 for (i = 0; i < RSORD_MAX; i++)
1686 1778 if (nn->tok == rsord[i])
1687 1779 break;
1688 1780
1689 1781 if (i < RSORD_MAX) {
1690 1782 if (MDOC__J == rsord[i] || MDOC__B == rsord[i])
1691 1783 mdoc->last->norm->Rs.quote_T++;
1692 1784 next = nn->next;
1693 1785 continue;
1694 1786 }
1695 1787
1696 1788 next = nn->next;
1697 1789 mdoc_nmsg(mdoc, nn, MANDOCERR_CHILD);
1698 1790 mdoc_node_delete(mdoc, nn);
1699 1791 }
1700 1792
1701 1793 /*
1702 1794 * Nothing to sort if only invalid nodes were found
1703 1795 * inside the `Rs' body.
1704 1796 */
1705 1797
1706 1798 if (NULL == mdoc->last->child)
1707 1799 return(1);
1708 1800
1709 1801 /*
1710 1802 * The full `Rs' block needs special handling to order the
1711 1803 * sub-elements according to `rsord'. Pick through each element
1712 1804 * and correctly order it. This is a insertion sort.
1713 1805 */
1714 1806
1715 1807 next = NULL;
1716 1808 for (nn = mdoc->last->child->next; nn; nn = next) {
1717 1809 /* Determine order of `nn'. */
1718 1810 for (i = 0; i < RSORD_MAX; i++)
1719 1811 if (rsord[i] == nn->tok)
1720 1812 break;
1721 1813
1722 1814 /*
1723 1815 * Remove `nn' from the chain. This somewhat
1724 1816 * repeats mdoc_node_unlink(), but since we're
1725 1817 * just re-ordering, there's no need for the
1726 1818 * full unlink process.
1727 1819 */
1728 1820
1729 1821 if (NULL != (next = nn->next))
1730 1822 next->prev = nn->prev;
1731 1823
1732 1824 if (NULL != (prev = nn->prev))
1733 1825 prev->next = nn->next;
1734 1826
1735 1827 nn->prev = nn->next = NULL;
1736 1828
1737 1829 /*
1738 1830 * Scan back until we reach a node that's
1739 1831 * ordered before `nn'.
1740 1832 */
1741 1833
1742 1834 for ( ; prev ; prev = prev->prev) {
1743 1835 /* Determine order of `prev'. */
1744 1836 for (j = 0; j < RSORD_MAX; j++)
1745 1837 if (rsord[j] == prev->tok)
1746 1838 break;
1747 1839
1748 1840 if (j <= i)
1749 1841 break;
1750 1842 }
1751 1843
1752 1844 /*
1753 1845 * Set `nn' back into its correct place in front
1754 1846 * of the `prev' node.
1755 1847 */
1756 1848
1757 1849 nn->prev = prev;
1758 1850
1759 1851 if (prev) {
1760 1852 if (prev->next)
1761 1853 prev->next->prev = nn;
1762 1854 nn->next = prev->next;
1763 1855 prev->next = nn;
↓ open down ↓ |
159 lines elided |
↑ open up ↑ |
1764 1856 } else {
1765 1857 mdoc->last->child->prev = nn;
1766 1858 nn->next = mdoc->last->child;
1767 1859 mdoc->last->child = nn;
1768 1860 }
1769 1861 }
1770 1862
1771 1863 return(1);
1772 1864 }
1773 1865
1866 +/*
1867 + * For some arguments of some macros,
1868 + * convert all breakable hyphens into ASCII_HYPH.
1869 + */
1774 1870 static int
1871 +post_hyph(POST_ARGS)
1872 +{
1873 + struct mdoc_node *n, *nch;
1874 + char *cp;
1875 +
1876 + n = mdoc->last;
1877 + switch (n->type) {
1878 + case (MDOC_HEAD):
1879 + if (MDOC_Sh == n->tok || MDOC_Ss == n->tok)
1880 + break;
1881 + return(1);
1882 + case (MDOC_BODY):
1883 + if (MDOC_D1 == n->tok || MDOC_Nd == n->tok)
1884 + break;
1885 + return(1);
1886 + case (MDOC_ELEM):
1887 + break;
1888 + default:
1889 + return(1);
1890 + }
1891 +
1892 + for (nch = n->child; nch; nch = nch->next) {
1893 + if (MDOC_TEXT != nch->type)
1894 + continue;
1895 + cp = nch->string;
1896 + if (3 > strnlen(cp, 3))
1897 + continue;
1898 + while ('\0' != *(++cp))
1899 + if ('-' == *cp &&
1900 + isalpha((unsigned char)cp[-1]) &&
1901 + isalpha((unsigned char)cp[1]))
1902 + *cp = ASCII_HYPH;
1903 + }
1904 + return(1);
1905 +}
1906 +
1907 +static int
1775 1908 post_ns(POST_ARGS)
1776 1909 {
1777 1910
1778 1911 if (MDOC_LINE & mdoc->last->flags)
1779 1912 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNNS);
1780 1913 return(1);
1781 1914 }
1782 1915
1783 1916 static int
1784 1917 post_sh(POST_ARGS)
1785 1918 {
1786 1919
1787 1920 if (MDOC_HEAD == mdoc->last->type)
1788 1921 return(post_sh_head(mdoc));
1789 1922 if (MDOC_BODY == mdoc->last->type)
1790 1923 return(post_sh_body(mdoc));
1791 1924
1792 1925 return(1);
1793 1926 }
1794 1927
1795 1928 static int
1796 1929 post_sh_body(POST_ARGS)
1797 1930 {
1798 1931 struct mdoc_node *n;
1799 1932
1800 1933 if (SEC_NAME != mdoc->lastsec)
1801 1934 return(1);
1802 1935
1803 1936 /*
1804 1937 * Warn if the NAME section doesn't contain the `Nm' and `Nd'
1805 1938 * macros (can have multiple `Nm' and one `Nd'). Note that the
1806 1939 * children of the BODY declaration can also be "text".
1807 1940 */
1808 1941
1809 1942 if (NULL == (n = mdoc->last->child)) {
1810 1943 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC);
1811 1944 return(1);
1812 1945 }
1813 1946
1814 1947 for ( ; n && n->next; n = n->next) {
1815 1948 if (MDOC_ELEM == n->type && MDOC_Nm == n->tok)
1816 1949 continue;
1817 1950 if (MDOC_TEXT == n->type)
1818 1951 continue;
1819 1952 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC);
1820 1953 }
1821 1954
1822 1955 assert(n);
1823 1956 if (MDOC_BLOCK == n->type && MDOC_Nd == n->tok)
1824 1957 return(1);
1825 1958
1826 1959 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC);
1827 1960 return(1);
1828 1961 }
1829 1962
1830 1963 static int
1831 1964 post_sh_head(POST_ARGS)
1832 1965 {
1833 1966 char buf[BUFSIZ];
1834 1967 struct mdoc_node *n;
1835 1968 enum mdoc_sec sec;
1836 1969 int c;
1837 1970
1838 1971 /*
1839 1972 * Process a new section. Sections are either "named" or
1840 1973 * "custom". Custom sections are user-defined, while named ones
1841 1974 * follow a conventional order and may only appear in certain
1842 1975 * manual sections.
1843 1976 */
1844 1977
1845 1978 sec = SEC_CUSTOM;
1846 1979 buf[0] = '\0';
1847 1980 if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) {
1848 1981 mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM);
1849 1982 return(0);
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
1850 1983 } else if (1 == c)
1851 1984 sec = a2sec(buf);
1852 1985
1853 1986 /* The NAME should be first. */
1854 1987
1855 1988 if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
1856 1989 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NAMESECFIRST);
1857 1990
1858 1991 /* The SYNOPSIS gets special attention in other areas. */
1859 1992
1860 - if (SEC_SYNOPSIS == sec)
1993 + if (SEC_SYNOPSIS == sec) {
1994 + roff_setreg(mdoc->roff, "nS", 1, '=');
1861 1995 mdoc->flags |= MDOC_SYNOPSIS;
1862 - else
1996 + } else {
1997 + roff_setreg(mdoc->roff, "nS", 0, '=');
1863 1998 mdoc->flags &= ~MDOC_SYNOPSIS;
1999 + }
1864 2000
1865 2001 /* Mark our last section. */
1866 2002
1867 2003 mdoc->lastsec = sec;
1868 2004
1869 2005 /*
1870 2006 * Set the section attribute for the current HEAD, for its
1871 2007 * parent BLOCK, and for the HEAD children; the latter can
1872 2008 * only be TEXT nodes, so no recursion is needed.
1873 2009 * For other blocks and elements, including .Sh BODY, this is
1874 2010 * done when allocating the node data structures, but for .Sh
1875 2011 * BLOCK and HEAD, the section is still unknown at that time.
1876 2012 */
1877 2013
1878 2014 mdoc->last->parent->sec = sec;
1879 2015 mdoc->last->sec = sec;
1880 2016 for (n = mdoc->last->child; n; n = n->next)
1881 2017 n->sec = sec;
1882 2018
1883 2019 /* We don't care about custom sections after this. */
1884 2020
1885 2021 if (SEC_CUSTOM == sec)
1886 2022 return(1);
1887 2023
1888 2024 /*
1889 2025 * Check whether our non-custom section is being repeated or is
1890 2026 * out of order.
1891 2027 */
1892 2028
1893 2029 if (sec == mdoc->lastnamed)
1894 2030 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECREP);
1895 2031
1896 2032 if (sec < mdoc->lastnamed)
1897 2033 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECOOO);
1898 2034
1899 2035 /* Mark the last named section. */
1900 2036
1901 2037 mdoc->lastnamed = sec;
1902 2038
1903 2039 /* Check particular section/manual conventions. */
1904 2040
1905 2041 assert(mdoc->meta.msec);
1906 2042
1907 2043 switch (sec) {
1908 2044 case (SEC_RETURN_VALUES):
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
1909 2045 /* FALLTHROUGH */
1910 2046 case (SEC_ERRORS):
1911 2047 /* FALLTHROUGH */
1912 2048 case (SEC_LIBRARY):
1913 2049 if (*mdoc->meta.msec == '2')
1914 2050 break;
1915 2051 if (*mdoc->meta.msec == '3')
1916 2052 break;
1917 2053 if (*mdoc->meta.msec == '9')
1918 2054 break;
1919 - mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECMSEC);
2055 + mandoc_msg(MANDOCERR_SECMSEC, mdoc->parse,
2056 + mdoc->last->line, mdoc->last->pos, buf);
1920 2057 break;
1921 2058 default:
1922 2059 break;
1923 2060 }
1924 2061
1925 2062 return(1);
1926 2063 }
1927 2064
1928 2065 static int
1929 2066 post_ignpar(POST_ARGS)
1930 2067 {
1931 2068 struct mdoc_node *np;
1932 2069
1933 2070 if (MDOC_BODY != mdoc->last->type)
1934 2071 return(1);
1935 2072
1936 2073 if (NULL != (np = mdoc->last->child))
1937 2074 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
1938 2075 mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR);
1939 2076 mdoc_node_delete(mdoc, np);
1940 2077 }
1941 2078
1942 2079 if (NULL != (np = mdoc->last->last))
1943 2080 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
1944 2081 mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR);
1945 2082 mdoc_node_delete(mdoc, np);
1946 2083 }
1947 2084
1948 2085 return(1);
1949 2086 }
1950 2087
1951 2088 static int
1952 2089 pre_par(PRE_ARGS)
1953 2090 {
1954 2091
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
1955 2092 if (NULL == mdoc->last)
1956 2093 return(1);
1957 2094 if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type)
1958 2095 return(1);
1959 2096
1960 2097 /*
1961 2098 * Don't allow prior `Lp' or `Pp' prior to a paragraph-type
1962 2099 * block: `Lp', `Pp', or non-compact `Bd' or `Bl'.
1963 2100 */
1964 2101
1965 - if (MDOC_Pp != mdoc->last->tok && MDOC_Lp != mdoc->last->tok)
2102 + if (MDOC_Pp != mdoc->last->tok &&
2103 + MDOC_Lp != mdoc->last->tok &&
2104 + MDOC_br != mdoc->last->tok)
1966 2105 return(1);
1967 2106 if (MDOC_Bl == n->tok && n->norm->Bl.comp)
1968 2107 return(1);
1969 2108 if (MDOC_Bd == n->tok && n->norm->Bd.comp)
1970 2109 return(1);
1971 2110 if (MDOC_It == n->tok && n->parent->norm->Bl.comp)
1972 2111 return(1);
1973 2112
1974 2113 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR);
1975 2114 mdoc_node_delete(mdoc, mdoc->last);
1976 2115 return(1);
1977 2116 }
1978 2117
1979 2118 static int
2119 +post_par(POST_ARGS)
2120 +{
2121 +
2122 + if (MDOC_ELEM != mdoc->last->type &&
2123 + MDOC_BLOCK != mdoc->last->type)
2124 + return(1);
2125 +
2126 + if (NULL == mdoc->last->prev) {
2127 + if (MDOC_Sh != mdoc->last->parent->tok &&
2128 + MDOC_Ss != mdoc->last->parent->tok)
2129 + return(1);
2130 + } else {
2131 + if (MDOC_Pp != mdoc->last->prev->tok &&
2132 + MDOC_Lp != mdoc->last->prev->tok &&
2133 + (MDOC_br != mdoc->last->tok ||
2134 + (MDOC_sp != mdoc->last->prev->tok &&
2135 + MDOC_br != mdoc->last->prev->tok)))
2136 + return(1);
2137 + }
2138 +
2139 + mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR);
2140 + mdoc_node_delete(mdoc, mdoc->last);
2141 + return(1);
2142 +}
2143 +
2144 +static int
1980 2145 pre_literal(PRE_ARGS)
1981 2146 {
1982 2147
1983 2148 if (MDOC_BODY != n->type)
1984 2149 return(1);
1985 2150
1986 2151 /*
1987 2152 * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd
1988 2153 * -unfilled' macros set MDOC_LITERAL on entrance to the body.
1989 2154 */
1990 2155
1991 2156 switch (n->tok) {
1992 2157 case (MDOC_Dl):
1993 2158 mdoc->flags |= MDOC_LITERAL;
1994 2159 break;
1995 2160 case (MDOC_Bd):
1996 2161 if (DISP_literal == n->norm->Bd.type)
1997 2162 mdoc->flags |= MDOC_LITERAL;
1998 2163 if (DISP_unfilled == n->norm->Bd.type)
1999 2164 mdoc->flags |= MDOC_LITERAL;
2000 2165 break;
2001 2166 default:
2002 2167 abort();
2003 2168 /* NOTREACHED */
2004 2169 }
2005 2170
2006 2171 return(1);
2007 2172 }
2008 2173
2009 2174 static int
2010 2175 post_dd(POST_ARGS)
2011 2176 {
2012 2177 char buf[DATESIZE];
2013 2178 struct mdoc_node *n;
2014 2179 int c;
2015 2180
2016 2181 if (mdoc->meta.date)
2017 2182 free(mdoc->meta.date);
2018 2183
2019 2184 n = mdoc->last;
2020 2185 if (NULL == n->child || '\0' == n->child->string[0]) {
2021 2186 mdoc->meta.date = mandoc_normdate
2022 2187 (mdoc->parse, NULL, n->line, n->pos);
2023 2188 return(1);
2024 2189 }
2025 2190
2026 2191 buf[0] = '\0';
2027 2192 if (-1 == (c = concat(buf, n->child, DATESIZE))) {
2028 2193 mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM);
2029 2194 return(0);
2030 2195 }
2031 2196
2032 2197 assert(c);
2033 2198 mdoc->meta.date = mandoc_normdate
2034 2199 (mdoc->parse, buf, n->line, n->pos);
2035 2200
2036 2201 return(1);
2037 2202 }
2038 2203
2039 2204 static int
2040 2205 post_dt(POST_ARGS)
2041 2206 {
2042 2207 struct mdoc_node *nn, *n;
2043 2208 const char *cp;
2044 2209 char *p;
2045 2210
2046 2211 n = mdoc->last;
2047 2212
2048 2213 if (mdoc->meta.title)
2049 2214 free(mdoc->meta.title);
2050 2215 if (mdoc->meta.vol)
2051 2216 free(mdoc->meta.vol);
2052 2217 if (mdoc->meta.arch)
2053 2218 free(mdoc->meta.arch);
2054 2219
2055 2220 mdoc->meta.title = mdoc->meta.vol = mdoc->meta.arch = NULL;
2056 2221
2057 2222 /* First make all characters uppercase. */
2058 2223
2059 2224 if (NULL != (nn = n->child))
2060 2225 for (p = nn->string; *p; p++) {
2061 2226 if (toupper((unsigned char)*p) == *p)
2062 2227 continue;
2063 2228
2064 2229 /*
2065 2230 * FIXME: don't be lazy: have this make all
2066 2231 * characters be uppercase and just warn once.
2067 2232 */
2068 2233 mdoc_nmsg(mdoc, nn, MANDOCERR_UPPERCASE);
2069 2234 break;
2070 2235 }
2071 2236
2072 2237 /* Handles: `.Dt'
2073 2238 * --> title = unknown, volume = local, msec = 0, arch = NULL
2074 2239 */
2075 2240
2076 2241 if (NULL == (nn = n->child)) {
2077 2242 /* XXX: make these macro values. */
2078 2243 /* FIXME: warn about missing values. */
2079 2244 mdoc->meta.title = mandoc_strdup("UNKNOWN");
2080 2245 mdoc->meta.vol = mandoc_strdup("LOCAL");
2081 2246 mdoc->meta.msec = mandoc_strdup("1");
2082 2247 return(1);
2083 2248 }
2084 2249
2085 2250 /* Handles: `.Dt TITLE'
2086 2251 * --> title = TITLE, volume = local, msec = 0, arch = NULL
2087 2252 */
2088 2253
2089 2254 mdoc->meta.title = mandoc_strdup
2090 2255 ('\0' == nn->string[0] ? "UNKNOWN" : nn->string);
2091 2256
2092 2257 if (NULL == (nn = nn->next)) {
2093 2258 /* FIXME: warn about missing msec. */
2094 2259 /* XXX: make this a macro value. */
2095 2260 mdoc->meta.vol = mandoc_strdup("LOCAL");
2096 2261 mdoc->meta.msec = mandoc_strdup("1");
2097 2262 return(1);
2098 2263 }
2099 2264
2100 2265 /* Handles: `.Dt TITLE SEC'
2101 2266 * --> title = TITLE, volume = SEC is msec ?
2102 2267 * format(msec) : SEC,
2103 2268 * msec = SEC is msec ? atoi(msec) : 0,
2104 2269 * arch = NULL
2105 2270 */
2106 2271
2107 2272 cp = mandoc_a2msec(nn->string);
2108 2273 if (cp) {
2109 2274 mdoc->meta.vol = mandoc_strdup(cp);
2110 2275 mdoc->meta.msec = mandoc_strdup(nn->string);
2111 2276 } else {
2112 2277 mdoc_nmsg(mdoc, n, MANDOCERR_BADMSEC);
2113 2278 mdoc->meta.vol = mandoc_strdup(nn->string);
2114 2279 mdoc->meta.msec = mandoc_strdup(nn->string);
2115 2280 }
2116 2281
2117 2282 if (NULL == (nn = nn->next))
2118 2283 return(1);
2119 2284
2120 2285 /* Handles: `.Dt TITLE SEC VOL'
2121 2286 * --> title = TITLE, volume = VOL is vol ?
↓ open down ↓ |
132 lines elided |
↑ open up ↑ |
2122 2287 * format(VOL) :
2123 2288 * VOL is arch ? format(arch) :
2124 2289 * VOL
2125 2290 */
2126 2291
2127 2292 cp = mdoc_a2vol(nn->string);
2128 2293 if (cp) {
2129 2294 free(mdoc->meta.vol);
2130 2295 mdoc->meta.vol = mandoc_strdup(cp);
2131 2296 } else {
2132 - /* FIXME: warn about bad arch. */
2133 2297 cp = mdoc_a2arch(nn->string);
2134 2298 if (NULL == cp) {
2299 + mdoc_nmsg(mdoc, nn, MANDOCERR_BADVOLARCH);
2135 2300 free(mdoc->meta.vol);
2136 2301 mdoc->meta.vol = mandoc_strdup(nn->string);
2137 2302 } else
2138 2303 mdoc->meta.arch = mandoc_strdup(cp);
2139 2304 }
2140 2305
2141 2306 /* Ignore any subsequent parameters... */
2142 2307 /* FIXME: warn about subsequent parameters. */
2143 2308
2144 2309 return(1);
2145 2310 }
2146 2311
2147 2312 static int
2148 2313 post_prol(POST_ARGS)
2149 2314 {
2150 2315 /*
2151 2316 * Remove prologue macros from the document after they're
2152 2317 * processed. The final document uses mdoc_meta for these
2153 2318 * values and discards the originals.
2154 2319 */
2155 2320
2156 2321 mdoc_node_delete(mdoc, mdoc->last);
2157 2322 if (mdoc->meta.title && mdoc->meta.date && mdoc->meta.os)
2158 2323 mdoc->flags |= MDOC_PBODY;
2159 2324
2160 2325 return(1);
2161 2326 }
2162 2327
2163 2328 static int
2164 2329 post_bx(POST_ARGS)
2165 2330 {
2166 2331 struct mdoc_node *n;
2167 2332
2168 2333 /*
2169 2334 * Make `Bx's second argument always start with an uppercase
2170 2335 * letter. Groff checks if it's an "accepted" term, but we just
2171 2336 * uppercase blindly.
2172 2337 */
2173 2338
2174 2339 n = mdoc->last->child;
2175 2340 if (n && NULL != (n = n->next))
2176 2341 *n->string = (char)toupper
2177 2342 ((unsigned char)*n->string);
2178 2343
2179 2344 return(1);
2180 2345 }
2181 2346
2182 2347 static int
2183 2348 post_os(POST_ARGS)
2184 2349 {
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
2185 2350 struct mdoc_node *n;
2186 2351 char buf[BUFSIZ];
2187 2352 int c;
2188 2353 #ifndef OSNAME
2189 2354 struct utsname utsname;
2190 2355 #endif
2191 2356
2192 2357 n = mdoc->last;
2193 2358
2194 2359 /*
2195 - * Set the operating system by way of the `Os' macro. Note that
2196 - * if an argument isn't provided and -DOSNAME="\"foo\"" is
2197 - * provided during compilation, this value will be used instead
2198 - * of filling in "sysname release" from uname().
2360 + * Set the operating system by way of the `Os' macro.
2361 + * The order of precedence is:
2362 + * 1. the argument of the `Os' macro, unless empty
2363 + * 2. the -Ios=foo command line argument, if provided
2364 + * 3. -DOSNAME="\"foo\"", if provided during compilation
2365 + * 4. "sysname release" from uname(3)
2199 2366 */
2200 2367
2201 - if (mdoc->meta.os)
2202 - free(mdoc->meta.os);
2368 + free(mdoc->meta.os);
2203 2369
2204 2370 buf[0] = '\0';
2205 2371 if (-1 == (c = concat(buf, n->child, BUFSIZ))) {
2206 2372 mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM);
2207 2373 return(0);
2208 2374 }
2209 2375
2210 2376 assert(c);
2211 2377
2212 - /* XXX: yes, these can all be dynamically-adjusted buffers, but
2213 - * it's really not worth the extra hackery.
2214 - */
2215 -
2216 2378 if ('\0' == buf[0]) {
2379 + if (mdoc->defos) {
2380 + mdoc->meta.os = mandoc_strdup(mdoc->defos);
2381 + return(1);
2382 + }
2217 2383 #ifdef OSNAME
2218 2384 if (strlcat(buf, OSNAME, BUFSIZ) >= BUFSIZ) {
2219 2385 mdoc_nmsg(mdoc, n, MANDOCERR_MEM);
2220 2386 return(0);
2221 2387 }
2222 2388 #else /*!OSNAME */
2223 2389 if (-1 == uname(&utsname)) {
2224 2390 mdoc_nmsg(mdoc, n, MANDOCERR_UNAME);
2225 2391 mdoc->meta.os = mandoc_strdup("UNKNOWN");
2226 2392 return(post_prol(mdoc));
2227 2393 }
2228 2394
2229 2395 if (strlcat(buf, utsname.sysname, BUFSIZ) >= BUFSIZ) {
2230 2396 mdoc_nmsg(mdoc, n, MANDOCERR_MEM);
2231 2397 return(0);
2232 2398 }
2233 2399 if (strlcat(buf, " ", BUFSIZ) >= BUFSIZ) {
2234 2400 mdoc_nmsg(mdoc, n, MANDOCERR_MEM);
2235 2401 return(0);
2236 2402 }
2237 2403 if (strlcat(buf, utsname.release, BUFSIZ) >= BUFSIZ) {
2238 2404 mdoc_nmsg(mdoc, n, MANDOCERR_MEM);
2239 2405 return(0);
2240 2406 }
2241 2407 #endif /*!OSNAME*/
2242 2408 }
2243 2409
2244 2410 mdoc->meta.os = mandoc_strdup(buf);
2245 2411 return(1);
2246 2412 }
2247 2413
2248 2414 static int
2249 2415 post_std(POST_ARGS)
2250 2416 {
2251 2417 struct mdoc_node *nn, *n;
2252 2418
2253 2419 n = mdoc->last;
2254 2420
2255 2421 /*
2256 2422 * Macros accepting `-std' as an argument have the name of the
2257 2423 * current document (`Nm') filled in as the argument if it's not
2258 2424 * provided.
2259 2425 */
2260 2426
2261 2427 if (n->child)
2262 2428 return(1);
2263 2429
2264 2430 if (NULL == mdoc->meta.name)
2265 2431 return(1);
2266 2432
2267 2433 nn = n;
2268 2434 mdoc->next = MDOC_NEXT_CHILD;
2269 2435
2270 2436 if ( ! mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name))
2271 2437 return(0);
2272 2438
2273 2439 mdoc->last = nn;
2274 2440 return(1);
2275 2441 }
2276 2442
2277 2443 /*
2278 2444 * Concatenate a node, stopping at the first non-text.
2279 2445 * Concatenation is separated by a single whitespace.
2280 2446 * Returns -1 on fatal (string overrun) error, 0 if child nodes were
2281 2447 * encountered, 1 otherwise.
2282 2448 */
2283 2449 static int
2284 2450 concat(char *p, const struct mdoc_node *n, size_t sz)
2285 2451 {
2286 2452
2287 2453 for ( ; NULL != n; n = n->next) {
2288 2454 if (MDOC_TEXT != n->type)
2289 2455 return(0);
2290 2456 if ('\0' != p[0] && strlcat(p, " ", sz) >= sz)
2291 2457 return(-1);
2292 2458 if (strlcat(p, n->string, sz) >= sz)
2293 2459 return(-1);
2294 2460 concat(p, n->child, sz);
2295 2461 }
2296 2462
2297 2463 return(1);
2298 2464 }
2299 2465
2300 2466 static enum mdoc_sec
2301 2467 a2sec(const char *p)
2302 2468 {
2303 2469 int i;
2304 2470
2305 2471 for (i = 0; i < (int)SEC__MAX; i++)
2306 2472 if (secnames[i] && 0 == strcmp(p, secnames[i]))
2307 2473 return((enum mdoc_sec)i);
2308 2474
2309 2475 return(SEC_CUSTOM);
2310 2476 }
2311 2477
2312 2478 static size_t
2313 2479 macro2len(enum mdoct macro)
2314 2480 {
2315 2481
2316 2482 switch (macro) {
2317 2483 case(MDOC_Ad):
2318 2484 return(12);
2319 2485 case(MDOC_Ao):
2320 2486 return(12);
2321 2487 case(MDOC_An):
2322 2488 return(12);
2323 2489 case(MDOC_Aq):
2324 2490 return(12);
2325 2491 case(MDOC_Ar):
2326 2492 return(12);
2327 2493 case(MDOC_Bo):
2328 2494 return(12);
2329 2495 case(MDOC_Bq):
2330 2496 return(12);
2331 2497 case(MDOC_Cd):
2332 2498 return(12);
2333 2499 case(MDOC_Cm):
2334 2500 return(10);
2335 2501 case(MDOC_Do):
2336 2502 return(10);
2337 2503 case(MDOC_Dq):
2338 2504 return(12);
2339 2505 case(MDOC_Dv):
2340 2506 return(12);
2341 2507 case(MDOC_Eo):
2342 2508 return(12);
2343 2509 case(MDOC_Em):
2344 2510 return(10);
2345 2511 case(MDOC_Er):
2346 2512 return(17);
2347 2513 case(MDOC_Ev):
2348 2514 return(15);
2349 2515 case(MDOC_Fa):
2350 2516 return(12);
2351 2517 case(MDOC_Fl):
2352 2518 return(10);
2353 2519 case(MDOC_Fo):
2354 2520 return(16);
2355 2521 case(MDOC_Fn):
2356 2522 return(16);
2357 2523 case(MDOC_Ic):
2358 2524 return(10);
2359 2525 case(MDOC_Li):
2360 2526 return(16);
2361 2527 case(MDOC_Ms):
2362 2528 return(6);
2363 2529 case(MDOC_Nm):
2364 2530 return(10);
2365 2531 case(MDOC_No):
2366 2532 return(12);
2367 2533 case(MDOC_Oo):
2368 2534 return(10);
2369 2535 case(MDOC_Op):
2370 2536 return(14);
2371 2537 case(MDOC_Pa):
2372 2538 return(32);
2373 2539 case(MDOC_Pf):
2374 2540 return(12);
2375 2541 case(MDOC_Po):
2376 2542 return(12);
2377 2543 case(MDOC_Pq):
2378 2544 return(12);
2379 2545 case(MDOC_Ql):
2380 2546 return(16);
2381 2547 case(MDOC_Qo):
2382 2548 return(12);
2383 2549 case(MDOC_So):
2384 2550 return(12);
2385 2551 case(MDOC_Sq):
2386 2552 return(12);
2387 2553 case(MDOC_Sy):
2388 2554 return(6);
2389 2555 case(MDOC_Sx):
2390 2556 return(16);
2391 2557 case(MDOC_Tn):
2392 2558 return(10);
2393 2559 case(MDOC_Va):
2394 2560 return(12);
2395 2561 case(MDOC_Vt):
2396 2562 return(12);
2397 2563 case(MDOC_Xr):
2398 2564 return(10);
2399 2565 default:
2400 2566 break;
2401 2567 };
2402 2568 return(0);
2403 2569 }
↓ open down ↓ |
177 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX