]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_macro.c
More in-code documentation and clarity re-arrangements.
[mandoc.git] / mdoc_macro.c
1 /* $Id: mdoc_macro.c,v 1.40 2010/01/01 17:14:29 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <assert.h>
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <time.h>
27
28 #include "libmdoc.h"
29
30 #define REWIND_REWIND (1 << 0)
31 #define REWIND_NOHALT (1 << 1)
32 #define REWIND_HALT (1 << 2)
33
34 static int obsolete(MACRO_PROT_ARGS);
35 static int blk_part_exp(MACRO_PROT_ARGS);
36 static int in_line_eoln(MACRO_PROT_ARGS);
37 static int in_line_argn(MACRO_PROT_ARGS);
38 static int in_line(MACRO_PROT_ARGS);
39 static int blk_full(MACRO_PROT_ARGS);
40 static int blk_exp_close(MACRO_PROT_ARGS);
41 static int blk_part_imp(MACRO_PROT_ARGS);
42
43 static int phrase(struct mdoc *, int, int, char *);
44 static int rew_dohalt(int, enum mdoc_type,
45 const struct mdoc_node *);
46 static int rew_alt(int);
47 static int rew_dobreak(int, const struct mdoc_node *);
48 static int rew_elem(struct mdoc *, int);
49 static int rew_sub(enum mdoc_type, struct mdoc *,
50 int, int, int);
51 static int rew_last(struct mdoc *,
52 const struct mdoc_node *);
53 static int append_delims(struct mdoc *, int, int *, char *);
54 static int lookup(int, const char *);
55 static int lookup_raw(const char *);
56 static int swarn(struct mdoc *, enum mdoc_type, int, int,
57 const struct mdoc_node *);
58
59 /* Central table of library: who gets parsed how. */
60
61 const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
62 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
63 { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
64 { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
65 { in_line_eoln, MDOC_PROLOGUE }, /* Os */
66 { blk_full, 0 }, /* Sh */
67 { blk_full, 0 }, /* Ss */
68 { in_line_eoln, 0 }, /* Pp */
69 { blk_part_imp, MDOC_PARSED }, /* D1 */
70 { blk_part_imp, MDOC_PARSED }, /* Dl */
71 { blk_full, MDOC_EXPLICIT }, /* Bd */
72 { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
73 { blk_full, MDOC_EXPLICIT }, /* Bl */
74 { blk_exp_close, MDOC_EXPLICIT }, /* El */
75 { blk_full, MDOC_PARSED }, /* It */
76 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
77 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
78 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
79 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
80 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
81 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
82 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
83 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
84 { in_line_eoln, 0 }, /* Ex */
85 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
86 { in_line_eoln, 0 }, /* Fd */
87 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
88 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
89 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
90 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
91 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
92 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
93 { blk_full, 0 }, /* Nd */
94 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
95 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
96 { obsolete, 0 }, /* Ot */
97 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
98 { in_line_eoln, 0 }, /* Rv */
99 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
100 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
101 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
102 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
103 { in_line_eoln, 0 }, /* %A */
104 { in_line_eoln, 0 }, /* %B */
105 { in_line_eoln, 0 }, /* %D */
106 { in_line_eoln, 0 }, /* %I */
107 { in_line_eoln, 0 }, /* %J */
108 { in_line_eoln, 0 }, /* %N */
109 { in_line_eoln, 0 }, /* %O */
110 { in_line_eoln, 0 }, /* %P */
111 { in_line_eoln, 0 }, /* %R */
112 { in_line_eoln, 0 }, /* %T */
113 { in_line_eoln, 0 }, /* %V */
114 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
115 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
116 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
117 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
118 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
119 { blk_full, MDOC_EXPLICIT }, /* Bf */
120 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
121 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
122 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
123 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
124 { in_line_eoln, 0 }, /* Db */
125 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
126 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
127 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
128 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
129 { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
130 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
131 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
132 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
133 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
134 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */
135 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
136 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
137 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
138 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
139 { in_line_argn, MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
140 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
141 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
142 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
143 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
144 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
145 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
146 { blk_exp_close, MDOC_EXPLICIT }, /* Re */
147 { blk_full, MDOC_EXPLICIT }, /* Rs */
148 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
149 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
150 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
151 { in_line_eoln, 0 }, /* Sm */
152 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
153 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
154 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
155 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
156 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
157 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
158 { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
159 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
160 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
161 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
162 { blk_full, MDOC_EXPLICIT }, /* Bk */
163 { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
164 { in_line_eoln, 0 }, /* Bt */
165 { in_line_eoln, 0 }, /* Hf */
166 { obsolete, 0 }, /* Fr */
167 { in_line_eoln, 0 }, /* Ud */
168 { in_line_eoln, 0 }, /* Lb */
169 { in_line_eoln, 0 }, /* Lp */
170 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
171 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
172 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
173 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
174 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
175 { in_line_eoln, 0 }, /* %C */
176 { obsolete, 0 }, /* Es */
177 { obsolete, 0 }, /* En */
178 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
179 { in_line_eoln, 0 }, /* %Q */
180 { in_line_eoln, 0 }, /* br */
181 { in_line_eoln, 0 }, /* sp */
182 { in_line_eoln, 0 }, /* %U */
183 };
184
185 const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
186
187
188 static int
189 swarn(struct mdoc *mdoc, enum mdoc_type type,
190 int line, int pos, const struct mdoc_node *p)
191 {
192 const char *n, *t, *tt;
193
194 n = t = "<root>";
195 tt = "block";
196
197 switch (type) {
198 case (MDOC_BODY):
199 tt = "multi-line";
200 break;
201 case (MDOC_HEAD):
202 tt = "line";
203 break;
204 default:
205 break;
206 }
207
208 switch (p->type) {
209 case (MDOC_BLOCK):
210 n = mdoc_macronames[p->tok];
211 t = "block";
212 break;
213 case (MDOC_BODY):
214 n = mdoc_macronames[p->tok];
215 t = "multi-line";
216 break;
217 case (MDOC_HEAD):
218 n = mdoc_macronames[p->tok];
219 t = "line";
220 break;
221 default:
222 break;
223 }
224
225 if ( ! (MDOC_IGN_SCOPE & mdoc->pflags))
226 return(mdoc_verr(mdoc, line, pos,
227 "%s scope breaks %s scope of %s",
228 tt, t, n));
229 return(mdoc_vwarn(mdoc, line, pos,
230 "%s scope breaks %s scope of %s",
231 tt, t, n));
232 }
233
234
235 /*
236 * This is called at the end of parsing. It must traverse up the tree,
237 * closing out open [implicit] scopes. Obviously, open explicit scopes
238 * are errors.
239 */
240 int
241 mdoc_macroend(struct mdoc *m)
242 {
243 struct mdoc_node *n;
244
245 /* Scan for open explicit scopes. */
246
247 n = MDOC_VALID & m->last->flags ? m->last->parent : m->last;
248
249 for ( ; n; n = n->parent) {
250 if (MDOC_BLOCK != n->type)
251 continue;
252 if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
253 continue;
254 return(mdoc_nerr(m, n, EOPEN));
255 }
256
257 /* Rewind to the first. */
258
259 return(rew_last(m, m->first));
260 }
261
262
263 /*
264 * Look up a macro from within a subsequent context.
265 */
266 static int
267 lookup(int from, const char *p)
268 {
269 /* FIXME: make -diag lists be un-PARSED. */
270
271 if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
272 return(MDOC_MAX);
273 return(lookup_raw(p));
274 }
275
276
277 /*
278 * Lookup a macro following the initial line macro.
279 */
280 static int
281 lookup_raw(const char *p)
282 {
283 int res;
284
285 if (MDOC_MAX == (res = mdoc_hash_find(p)))
286 return(MDOC_MAX);
287 if (MDOC_CALLABLE & mdoc_macros[res].flags)
288 return(res);
289 return(MDOC_MAX);
290 }
291
292
293 static int
294 rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
295 {
296
297 assert(to);
298 mdoc->next = MDOC_NEXT_SIBLING;
299
300 /* LINTED */
301 while (mdoc->last != to) {
302 if ( ! mdoc_valid_post(mdoc))
303 return(0);
304 if ( ! mdoc_action_post(mdoc))
305 return(0);
306 mdoc->last = mdoc->last->parent;
307 assert(mdoc->last);
308 }
309
310 if ( ! mdoc_valid_post(mdoc))
311 return(0);
312 return(mdoc_action_post(mdoc));
313 }
314
315
316 /*
317 * Return the opening macro of a closing one, e.g., `Ec' has `Eo' as its
318 * matching pair.
319 */
320 static int
321 rew_alt(int tok)
322 {
323 switch (tok) {
324 case (MDOC_Ac):
325 return(MDOC_Ao);
326 case (MDOC_Bc):
327 return(MDOC_Bo);
328 case (MDOC_Brc):
329 return(MDOC_Bro);
330 case (MDOC_Dc):
331 return(MDOC_Do);
332 case (MDOC_Ec):
333 return(MDOC_Eo);
334 case (MDOC_Ed):
335 return(MDOC_Bd);
336 case (MDOC_Ef):
337 return(MDOC_Bf);
338 case (MDOC_Ek):
339 return(MDOC_Bk);
340 case (MDOC_El):
341 return(MDOC_Bl);
342 case (MDOC_Fc):
343 return(MDOC_Fo);
344 case (MDOC_Oc):
345 return(MDOC_Oo);
346 case (MDOC_Pc):
347 return(MDOC_Po);
348 case (MDOC_Qc):
349 return(MDOC_Qo);
350 case (MDOC_Re):
351 return(MDOC_Rs);
352 case (MDOC_Sc):
353 return(MDOC_So);
354 case (MDOC_Xc):
355 return(MDOC_Xo);
356 default:
357 break;
358 }
359 abort();
360 /* NOTREACHED */
361 }
362
363
364 /*
365 * Rewind rules. This indicates whether to stop rewinding
366 * (REWIND_HALT) without touching our current scope, stop rewinding and
367 * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
368 * The scope-closing and so on occurs in the various rew_* routines.
369 */
370 static int
371 rew_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
372 {
373
374 if (MDOC_ROOT == p->type)
375 return(REWIND_HALT);
376 if (MDOC_VALID & p->flags)
377 return(REWIND_NOHALT);
378
379 switch (tok) {
380 case (MDOC_Aq):
381 /* FALLTHROUGH */
382 case (MDOC_Bq):
383 /* FALLTHROUGH */
384 case (MDOC_Brq):
385 /* FALLTHROUGH */
386 case (MDOC_D1):
387 /* FALLTHROUGH */
388 case (MDOC_Dl):
389 /* FALLTHROUGH */
390 case (MDOC_Dq):
391 /* FALLTHROUGH */
392 case (MDOC_Op):
393 /* FALLTHROUGH */
394 case (MDOC_Pq):
395 /* FALLTHROUGH */
396 case (MDOC_Ql):
397 /* FALLTHROUGH */
398 case (MDOC_Qq):
399 /* FALLTHROUGH */
400 case (MDOC_Sq):
401 assert(MDOC_TAIL != type);
402 if (type == p->type && tok == p->tok)
403 return(REWIND_REWIND);
404 break;
405 case (MDOC_It):
406 assert(MDOC_TAIL != type);
407 if (type == p->type && tok == p->tok)
408 return(REWIND_REWIND);
409 if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
410 return(REWIND_HALT);
411 break;
412 case (MDOC_Sh):
413 if (type == p->type && tok == p->tok)
414 return(REWIND_REWIND);
415 break;
416 case (MDOC_Nd):
417 /* FALLTHROUGH */
418 case (MDOC_Ss):
419 assert(MDOC_TAIL != type);
420 if (type == p->type && tok == p->tok)
421 return(REWIND_REWIND);
422 if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
423 return(REWIND_HALT);
424 break;
425 case (MDOC_Ao):
426 /* FALLTHROUGH */
427 case (MDOC_Bd):
428 /* FALLTHROUGH */
429 case (MDOC_Bf):
430 /* FALLTHROUGH */
431 case (MDOC_Bk):
432 /* FALLTHROUGH */
433 case (MDOC_Bl):
434 /* FALLTHROUGH */
435 case (MDOC_Bo):
436 /* FALLTHROUGH */
437 case (MDOC_Bro):
438 /* FALLTHROUGH */
439 case (MDOC_Do):
440 /* FALLTHROUGH */
441 case (MDOC_Eo):
442 /* FALLTHROUGH */
443 case (MDOC_Fo):
444 /* FALLTHROUGH */
445 case (MDOC_Oo):
446 /* FALLTHROUGH */
447 case (MDOC_Po):
448 /* FALLTHROUGH */
449 case (MDOC_Qo):
450 /* FALLTHROUGH */
451 case (MDOC_Rs):
452 /* FALLTHROUGH */
453 case (MDOC_So):
454 /* FALLTHROUGH */
455 case (MDOC_Xo):
456 if (type == p->type && tok == p->tok)
457 return(REWIND_REWIND);
458 break;
459 /* Multi-line explicit scope close. */
460 case (MDOC_Ac):
461 /* FALLTHROUGH */
462 case (MDOC_Bc):
463 /* FALLTHROUGH */
464 case (MDOC_Brc):
465 /* FALLTHROUGH */
466 case (MDOC_Dc):
467 /* FALLTHROUGH */
468 case (MDOC_Ec):
469 /* FALLTHROUGH */
470 case (MDOC_Ed):
471 /* FALLTHROUGH */
472 case (MDOC_Ek):
473 /* FALLTHROUGH */
474 case (MDOC_El):
475 /* FALLTHROUGH */
476 case (MDOC_Fc):
477 /* FALLTHROUGH */
478 case (MDOC_Ef):
479 /* FALLTHROUGH */
480 case (MDOC_Oc):
481 /* FALLTHROUGH */
482 case (MDOC_Pc):
483 /* FALLTHROUGH */
484 case (MDOC_Qc):
485 /* FALLTHROUGH */
486 case (MDOC_Re):
487 /* FALLTHROUGH */
488 case (MDOC_Sc):
489 /* FALLTHROUGH */
490 case (MDOC_Xc):
491 if (type == p->type && rew_alt(tok) == p->tok)
492 return(REWIND_REWIND);
493 break;
494 default:
495 abort();
496 /* NOTREACHED */
497 }
498
499 return(REWIND_NOHALT);
500 }
501
502
503 /*
504 * See if we can break an encountered scope (the rew_dohalt has returned
505 * REWIND_NOHALT).
506 */
507 static int
508 rew_dobreak(int tok, const struct mdoc_node *p)
509 {
510
511 assert(MDOC_ROOT != p->type);
512 if (MDOC_ELEM == p->type)
513 return(1);
514 if (MDOC_TEXT == p->type)
515 return(1);
516 if (MDOC_VALID & p->flags)
517 return(1);
518
519 switch (tok) {
520 case (MDOC_It):
521 return(MDOC_It == p->tok);
522 case (MDOC_Nd):
523 return(MDOC_Nd == p->tok);
524 case (MDOC_Ss):
525 return(MDOC_Ss == p->tok);
526 case (MDOC_Sh):
527 if (MDOC_Nd == p->tok)
528 return(1);
529 if (MDOC_Ss == p->tok)
530 return(1);
531 return(MDOC_Sh == p->tok);
532 case (MDOC_El):
533 if (MDOC_It == p->tok)
534 return(1);
535 break;
536 case (MDOC_Oc):
537 /* XXX - experimental! */
538 if (MDOC_Op == p->tok)
539 return(1);
540 break;
541 default:
542 break;
543 }
544
545 if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
546 return(p->tok == rew_alt(tok));
547 else if (MDOC_BLOCK == p->type)
548 return(1);
549
550 return(tok == p->tok);
551 }
552
553
554 static int
555 rew_elem(struct mdoc *mdoc, int tok)
556 {
557 struct mdoc_node *n;
558
559 n = mdoc->last;
560 if (MDOC_ELEM != n->type)
561 n = n->parent;
562 assert(MDOC_ELEM == n->type);
563 assert(tok == n->tok);
564
565 return(rew_last(mdoc, n));
566 }
567
568
569 static int
570 rew_sub(enum mdoc_type t, struct mdoc *m,
571 int tok, int line, int ppos)
572 {
573 struct mdoc_node *n;
574 int c;
575
576 /* LINTED */
577 for (n = m->last; n; n = n->parent) {
578 c = rew_dohalt(tok, t, n);
579 if (REWIND_HALT == c) {
580 if (MDOC_BLOCK != t)
581 return(1);
582 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))
583 return(1);
584 return(mdoc_perr(m, line, ppos, ENOCTX));
585 }
586 if (REWIND_REWIND == c)
587 break;
588 else if (rew_dobreak(tok, n))
589 continue;
590 if ( ! swarn(m, t, line, ppos, n))
591 return(0);
592 }
593
594 assert(n);
595 return(rew_last(m, n));
596 }
597
598
599 static int
600 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
601 {
602 int c, lastarg;
603 char *p;
604
605 if (0 == buf[*pos])
606 return(1);
607
608 for (;;) {
609 lastarg = *pos;
610 c = mdoc_zargs(mdoc, line, pos, buf, ARGS_NOWARN, &p);
611 assert(ARGS_PHRASE != c);
612
613 if (ARGS_ERROR == c)
614 return(0);
615 else if (ARGS_EOLN == c)
616 break;
617 assert(mdoc_isdelim(p));
618 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
619 return(0);
620 }
621
622 return(1);
623 }
624
625
626 /*
627 * Close out block partial/full explicit.
628 */
629 static int
630 blk_exp_close(MACRO_PROT_ARGS)
631 {
632 int j, c, lastarg, maxargs, flushed;
633 char *p;
634
635 switch (tok) {
636 case (MDOC_Ec):
637 maxargs = 1;
638 break;
639 default:
640 maxargs = 0;
641 break;
642 }
643
644 if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
645 if (buf[*pos])
646 if ( ! mdoc_pwarn(m, line, ppos, ENOLINE))
647 return(0);
648
649 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
650 return(0);
651 return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
652 }
653
654 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
655 return(0);
656
657 if (maxargs > 0)
658 if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
659 return(0);
660
661 for (flushed = j = 0; ; j++) {
662 lastarg = *pos;
663
664 if (j == maxargs && ! flushed) {
665 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
666 return(0);
667 flushed = 1;
668 }
669
670 c = mdoc_args(m, line, pos, buf, tok, &p);
671
672 if (ARGS_ERROR == c)
673 return(0);
674 if (ARGS_PUNCT == c)
675 break;
676 if (ARGS_EOLN == c)
677 break;
678
679 if (MDOC_MAX != (c = lookup(tok, p))) {
680 if ( ! flushed) {
681 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
682 return(0);
683 flushed = 1;
684 }
685 if ( ! mdoc_macro(m, c, line, lastarg, pos, buf))
686 return(0);
687 break;
688 }
689
690 if ( ! mdoc_word_alloc(m, line, lastarg, p))
691 return(0);
692 }
693
694 if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
695 return(0);
696
697 if (ppos > 1)
698 return(1);
699 return(append_delims(m, line, pos, buf));
700 }
701
702
703 static int
704 in_line(MACRO_PROT_ARGS)
705 {
706 int la, lastpunct, c, w, cnt, d, nc;
707 struct mdoc_arg *arg;
708 char *p;
709
710 /*
711 * Whether we allow ignored elements (those without content,
712 * usually because of reserved words) to squeak by.
713 */
714 switch (tok) {
715 case (MDOC_An):
716 /* FALLTHROUGH */
717 case (MDOC_Ar):
718 /* FALLTHROUGH */
719 case (MDOC_Fl):
720 /* FALLTHROUGH */
721 case (MDOC_Lk):
722 /* FALLTHROUGH */
723 case (MDOC_Nm):
724 /* FALLTHROUGH */
725 case (MDOC_Pa):
726 nc = 1;
727 break;
728 default:
729 nc = 0;
730 break;
731 }
732
733 for (arg = NULL;; ) {
734 la = *pos;
735 c = mdoc_argv(m, line, tok, &arg, pos, buf);
736
737 if (ARGV_WORD == c) {
738 *pos = la;
739 break;
740 }
741 if (ARGV_EOLN == c)
742 break;
743 if (ARGV_ARG == c)
744 continue;
745
746 mdoc_argv_free(arg);
747 return(0);
748 }
749
750 for (cnt = 0, lastpunct = 1;; ) {
751 la = *pos;
752 w = mdoc_args(m, line, pos, buf, tok, &p);
753
754 if (ARGS_ERROR == w)
755 return(0);
756 if (ARGS_EOLN == w)
757 break;
758 if (ARGS_PUNCT == w)
759 break;
760
761 /* Quoted words shouldn't be looked-up. */
762
763 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
764
765 /*
766 * In this case, we've located a submacro and must
767 * execute it. Close out scope, if open. If no
768 * elements have been generated, either create one (nc)
769 * or raise a warning.
770 */
771
772 if (MDOC_MAX != c) {
773 if (0 == lastpunct && ! rew_elem(m, tok))
774 return(0);
775 if (nc && 0 == cnt) {
776 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
777 return(0);
778 if ( ! rew_last(m, m->last))
779 return(0);
780 } else if ( ! nc && 0 == cnt) {
781 mdoc_argv_free(arg);
782 if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
783 return(0);
784 }
785 c = mdoc_macro(m, c, line, la, pos, buf);
786 if (0 == c)
787 return(0);
788 if (ppos > 1)
789 return(1);
790 return(append_delims(m, line, pos, buf));
791 }
792
793 /*
794 * Non-quote-enclosed punctuation. Set up our scope, if
795 * a word; rewind the scope, if a delimiter; then append
796 * the word.
797 */
798
799 d = mdoc_isdelim(p);
800
801 if (ARGS_QWORD != w && d) {
802 if (0 == lastpunct && ! rew_elem(m, tok))
803 return(0);
804 lastpunct = 1;
805 } else if (lastpunct) {
806 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
807 return(0);
808 lastpunct = 0;
809 }
810
811 if ( ! d)
812 cnt++;
813 if ( ! mdoc_word_alloc(m, line, la, p))
814 return(0);
815
816 /*
817 * `Fl' macros have their scope re-opened with each new
818 * word so that the `-' can be added to each one without
819 * having to parse out spaces.
820 */
821 if (0 == lastpunct && MDOC_Fl == tok) {
822 if ( ! rew_elem(m, tok))
823 return(0);
824 lastpunct = 1;
825 }
826 }
827
828 if (0 == lastpunct && ! rew_elem(m, tok))
829 return(0);
830
831 /*
832 * If no elements have been collected and we're allowed to have
833 * empties (nc), open a scope and close it out. Otherwise,
834 * raise a warning.
835 *
836 */
837 if (nc && 0 == cnt) {
838 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
839 return(0);
840 if ( ! rew_last(m, m->last))
841 return(0);
842 } else if ( ! nc && 0 == cnt) {
843 mdoc_argv_free(arg);
844 if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
845 return(0);
846 }
847
848 if (ppos > 1)
849 return(1);
850 return(append_delims(m, line, pos, buf));
851 }
852
853
854 static int
855 blk_full(MACRO_PROT_ARGS)
856 {
857 int c, lastarg, reopen, dohead;
858 struct mdoc_arg *arg;
859 char *p;
860
861 /*
862 * Whether to process a block-head section. If this is
863 * non-zero, then a head will be opened for all line arguments.
864 * If not, then the head will always be empty and only a body
865 * will be opened, which will stay open at the eoln.
866 */
867
868 switch (tok) {
869 case (MDOC_Nd):
870 dohead = 0;
871 break;
872 default:
873 dohead = 1;
874 break;
875 }
876
877 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
878 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
879 return(0);
880 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
881 return(0);
882 }
883
884 for (arg = NULL;; ) {
885 lastarg = *pos;
886 c = mdoc_argv(m, line, tok, &arg, pos, buf);
887
888 if (ARGV_WORD == c) {
889 *pos = lastarg;
890 break;
891 }
892
893 if (ARGV_EOLN == c)
894 break;
895 if (ARGV_ARG == c)
896 continue;
897
898 mdoc_argv_free(arg);
899 return(0);
900 }
901
902 if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
903 return(0);
904
905 if (0 == buf[*pos]) {
906 if ( ! mdoc_head_alloc(m, line, ppos, tok))
907 return(0);
908 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
909 return(0);
910 if ( ! mdoc_body_alloc(m, line, ppos, tok))
911 return(0);
912 return(1);
913 }
914
915 if ( ! mdoc_head_alloc(m, line, ppos, tok))
916 return(0);
917
918 /* Immediately close out head and enter body, if applicable. */
919
920 if (0 == dohead) {
921 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
922 return(0);
923 if ( ! mdoc_body_alloc(m, line, ppos, tok))
924 return(0);
925 }
926
927 for (reopen = 0;; ) {
928 lastarg = *pos;
929 c = mdoc_args(m, line, pos, buf, tok, &p);
930
931 if (ARGS_ERROR == c)
932 return(0);
933 if (ARGS_EOLN == c)
934 break;
935 if (ARGS_PHRASE == c) {
936 assert(dohead);
937 if (reopen && ! mdoc_head_alloc(m, line, ppos, tok))
938 return(0);
939 /*
940 * Phrases are self-contained macro phrases used
941 * in the columnar output of a macro. They need
942 * special handling.
943 */
944 if ( ! phrase(m, line, lastarg, buf))
945 return(0);
946 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
947 return(0);
948
949 reopen = 1;
950 continue;
951 }
952
953 if (MDOC_MAX == (c = lookup(tok, p))) {
954 if ( ! mdoc_word_alloc(m, line, lastarg, p))
955 return(0);
956 continue;
957 }
958
959 if ( ! mdoc_macro(m, c, line, lastarg, pos, buf))
960 return(0);
961 break;
962 }
963
964 if (1 == ppos && ! append_delims(m, line, pos, buf))
965 return(0);
966
967 /* If the body's already open, then just return. */
968 if (0 == dohead)
969 return(1);
970
971 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
972 return(0);
973 if ( ! mdoc_body_alloc(m, line, ppos, tok))
974 return(0);
975
976 return(1);
977 }
978
979
980 static int
981 blk_part_imp(MACRO_PROT_ARGS)
982 {
983 int la, c;
984 char *p;
985 struct mdoc_node *blk, *body, *n;
986
987 /* If applicable, close out prior scopes. */
988
989 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
990 return(0);
991 /* Saved for later close-out. */
992 blk = m->last;
993 if ( ! mdoc_head_alloc(m, line, ppos, tok))
994 return(0);
995 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
996 return(0);
997 if ( ! mdoc_body_alloc(m, line, ppos, tok))
998 return(0);
999 /* Saved for later close-out. */
1000 body = m->last;
1001
1002 /* Body argument processing. */
1003
1004 for (;;) {
1005 la = *pos;
1006 c = mdoc_args(m, line, pos, buf, tok, &p);
1007 assert(ARGS_PHRASE != c);
1008
1009 if (ARGS_ERROR == c)
1010 return(0);
1011 if (ARGS_PUNCT == c)
1012 break;
1013 if (ARGS_EOLN == c)
1014 break;
1015
1016 if (MDOC_MAX == (c = lookup(tok, p))) {
1017 if ( ! mdoc_word_alloc(m, line, la, p))
1018 return(0);
1019 continue;
1020 }
1021
1022 if ( ! mdoc_macro(m, c, line, la, pos, buf))
1023 return(0);
1024 break;
1025 }
1026
1027 /*
1028 * If we can't rewind to our body, then our scope has already
1029 * been closed by another macro (like `Oc' closing `Op'). This
1030 * is ugly behaviour nodding its head to OpenBSD's overwhelming
1031 * crufty use of `Op' breakage--XXX, deprecate in time.
1032 */
1033 for (n = m->last; n; n = n->parent)
1034 if (body == n)
1035 break;
1036 if (NULL == n && ! mdoc_nwarn(m, body, EIMPBRK))
1037 return(0);
1038 if (n && ! rew_last(m, body))
1039 return(0);
1040
1041 /* Standard appending of delimiters. */
1042
1043 if (1 == ppos && ! append_delims(m, line, pos, buf))
1044 return(0);
1045
1046 /* Rewind scope, if applicable. */
1047
1048 if (n && ! rew_last(m, blk))
1049 return(0);
1050
1051 return(1);
1052 }
1053
1054
1055 static int
1056 blk_part_exp(MACRO_PROT_ARGS)
1057 {
1058 int la, flushed, j, c, maxargs;
1059 char *p;
1060
1061 /* Number of head arguments. Only `Eo' has these, */
1062
1063 switch (tok) {
1064 case (MDOC_Eo):
1065 maxargs = 1;
1066 break;
1067 default:
1068 maxargs = 0;
1069 break;
1070 }
1071
1072 /* Begin the block scope. */
1073
1074 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1075 return(0);
1076
1077 /*
1078 * If no head arguments, open and then close out a head, noting
1079 * that we've flushed our terms. `flushed' means that we've
1080 * flushed out the head and the body is open.
1081 */
1082
1083 if (0 == maxargs) {
1084 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1085 return(0);
1086 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1087 return(0);
1088 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1089 return(0);
1090 flushed = 1;
1091 } else {
1092 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1093 return(0);
1094 flushed = 0;
1095 }
1096
1097 /* Process the head/head+body line arguments. */
1098
1099 for (j = 0; ; j++) {
1100 la = *pos;
1101 if (j == maxargs && ! flushed) {
1102 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1103 return(0);
1104 flushed = 1;
1105 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1106 return(0);
1107 }
1108
1109 c = mdoc_args(m, line, pos, buf, tok, &p);
1110 assert(ARGS_PHRASE != c);
1111
1112 if (ARGS_ERROR == c)
1113 return(0);
1114 if (ARGS_PUNCT == c)
1115 break;
1116 if (ARGS_EOLN == c)
1117 break;
1118
1119 if (MDOC_MAX != (c = lookup(tok, p))) {
1120 if ( ! flushed) {
1121 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1122 return(0);
1123 flushed = 1;
1124 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1125 return(0);
1126 }
1127 if ( ! mdoc_macro(m, c, line, la, pos, buf))
1128 return(0);
1129 break;
1130 }
1131
1132 if ( ! flushed && mdoc_isdelim(p)) {
1133 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1134 return(0);
1135 flushed = 1;
1136 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1137 return(0);
1138 }
1139
1140 if ( ! mdoc_word_alloc(m, line, la, p))
1141 return(0);
1142 }
1143
1144 /* Close the head and open the body, if applicable. */
1145
1146 if ( ! flushed) {
1147 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1148 return(0);
1149 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1150 return(0);
1151 }
1152
1153 /* Standard appending of delimiters. */
1154
1155 if (ppos > 1)
1156 return(1);
1157 return(append_delims(m, line, pos, buf));
1158 }
1159
1160
1161 static int
1162 in_line_argn(MACRO_PROT_ARGS)
1163 {
1164 int la, flushed, j, c, maxargs;
1165 struct mdoc_arg *arg;
1166 char *p;
1167
1168 /* Fixed maximum arguments per macro, if applicable. */
1169
1170 switch (tok) {
1171 case (MDOC_Ap):
1172 /* FALLTHROUGH */
1173 case (MDOC_No):
1174 /* FALLTHROUGH */
1175 case (MDOC_Ns):
1176 /* FALLTHROUGH */
1177 case (MDOC_Ux):
1178 maxargs = 0;
1179 break;
1180 default:
1181 maxargs = 1;
1182 break;
1183 }
1184
1185 /* Macro argument processing. */
1186
1187 for (arg = NULL;; ) {
1188 la = *pos;
1189 c = mdoc_argv(m, line, tok, &arg, pos, buf);
1190
1191 if (ARGV_WORD == c) {
1192 *pos = la;
1193 break;
1194 }
1195
1196 if (ARGV_EOLN == c)
1197 break;
1198 if (ARGV_ARG == c)
1199 continue;
1200
1201 mdoc_argv_free(arg);
1202 return(0);
1203 }
1204
1205 /* Open the element scope. */
1206
1207 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1208 return(0);
1209
1210 /* Process element arguments. */
1211
1212 for (flushed = j = 0; ; j++) {
1213 la = *pos;
1214
1215 if (j == maxargs && ! flushed) {
1216 if ( ! rew_elem(m, tok))
1217 return(0);
1218 flushed = 1;
1219 }
1220
1221 c = mdoc_args(m, line, pos, buf, tok, &p);
1222
1223 if (ARGS_ERROR == c)
1224 return(0);
1225 if (ARGS_PUNCT == c)
1226 break;
1227 if (ARGS_EOLN == c)
1228 break;
1229
1230 if (MDOC_MAX != (c = lookup(tok, p))) {
1231 if ( ! flushed && ! rew_elem(m, tok))
1232 return(0);
1233 flushed = 1;
1234 if ( ! mdoc_macro(m, c, line, la, pos, buf))
1235 return(0);
1236 break;
1237 }
1238
1239 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1240 ! flushed && mdoc_isdelim(p)) {
1241 if ( ! rew_elem(m, tok))
1242 return(0);
1243 flushed = 1;
1244 }
1245
1246 if ( ! mdoc_word_alloc(m, line, la, p))
1247 return(0);
1248 }
1249
1250 /* Close out and append delimiters. */
1251
1252 if ( ! flushed && ! rew_elem(m, tok))
1253 return(0);
1254
1255 if (ppos > 1)
1256 return(1);
1257 return(append_delims(m, line, pos, buf));
1258 }
1259
1260
1261 static int
1262 in_line_eoln(MACRO_PROT_ARGS)
1263 {
1264 int c, w, la;
1265 struct mdoc_arg *arg;
1266 char *p;
1267
1268 assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1269
1270 /* Parse macro arguments. */
1271
1272 for (arg = NULL; ; ) {
1273 la = *pos;
1274 c = mdoc_argv(m, line, tok, &arg, pos, buf);
1275
1276 if (ARGV_WORD == c) {
1277 *pos = la;
1278 break;
1279 }
1280 if (ARGV_EOLN == c)
1281 break;
1282 if (ARGV_ARG == c)
1283 continue;
1284
1285 mdoc_argv_free(arg);
1286 return(0);
1287 }
1288
1289 /* Open element scope. */
1290
1291 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1292 return(0);
1293
1294 /* Parse argument terms. */
1295
1296 for (;;) {
1297 la = *pos;
1298 w = mdoc_args(m, line, pos, buf, tok, &p);
1299
1300 if (ARGS_ERROR == w)
1301 return(0);
1302 if (ARGS_EOLN == w)
1303 break;
1304
1305 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
1306
1307 if (MDOC_MAX != c) {
1308 if ( ! rew_elem(m, tok))
1309 return(0);
1310 return(mdoc_macro(m, c, line, la, pos, buf));
1311 }
1312
1313 if ( ! mdoc_word_alloc(m, line, la, p))
1314 return(0);
1315 }
1316
1317 /* Close out (no delimiters). */
1318
1319 return(rew_elem(m, tok));
1320 }
1321
1322
1323 /* ARGSUSED */
1324 static int
1325 obsolete(MACRO_PROT_ARGS)
1326 {
1327
1328 return(mdoc_pwarn(m, line, ppos, EOBS));
1329 }
1330
1331
1332 /*
1333 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1334 * They're unusual because they're basically free-form text until a
1335 * macro is encountered.
1336 */
1337 static int
1338 phrase(struct mdoc *m, int line, int ppos, char *buf)
1339 {
1340 int c, w, la, pos;
1341 char *p;
1342
1343 for (pos = ppos; ; ) {
1344 la = pos;
1345
1346 /* Note: no calling context! */
1347 w = mdoc_zargs(m, line, &pos, buf, 0, &p);
1348
1349 if (ARGS_ERROR == w)
1350 return(0);
1351 if (ARGS_EOLN == w)
1352 break;
1353
1354 c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(p);
1355
1356 if (MDOC_MAX != c) {
1357 if ( ! mdoc_macro(m, c, line, la, &pos, buf))
1358 return(0);
1359 return(append_delims(m, line, &pos, buf));
1360 }
1361
1362 if ( ! mdoc_word_alloc(m, line, la, p))
1363 return(0);
1364 }
1365
1366 return(1);
1367 }
1368
1369