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