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