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