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