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