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