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