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