]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_macro.c
Removed mdoc_nwarn (not being used anywhere).
[mandoc.git] / mdoc_macro.c
1 /* $Id: mdoc_macro.c,v 1.12 2009/06/12 09:18:00 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_CALLABLE | 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_CALLABLE | MDOC_PARSED }, /* Ft */
105 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
106 { in_line_eoln, 0 }, /* In */ /* FIXME: historic usage! */
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_CALLABLE | 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_CALLABLE | MDOC_PARSED }, /* Lk */
187 { in_line, MDOC_CALLABLE | 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_Lk):
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 if ( ! rew_last(mdoc, mdoc->last))
874 return(0);
875 } else if ( ! nc && 0 == cnt) {
876 mdoc_argv_free(arg);
877 if ( ! pwarn(mdoc, line, ppos, WIGNE))
878 return(0);
879 }
880 c = mdoc_macro(mdoc, c, line, la, pos, buf);
881 if (0 == c)
882 return(0);
883 if (ppos > 1)
884 return(1);
885 return(append_delims(mdoc, line, pos, buf));
886 } else if (-1 == c)
887 return(0);
888
889 /*
890 * Non-quote-enclosed punctuation. Set up our scope, if
891 * a word; rewind the scope, if a delimiter; then append
892 * the word.
893 */
894
895 d = mdoc_isdelim(p);
896
897 if (ARGS_QWORD != w && d) {
898 if (0 == lastpunct && ! rew_elem(mdoc, tok))
899 return(0);
900 lastpunct = 1;
901 } else if (lastpunct) {
902 c = mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
903 if (0 == c)
904 return(0);
905 mdoc->next = MDOC_NEXT_CHILD;
906 lastpunct = 0;
907 }
908
909 if ( ! d)
910 cnt++;
911 if ( ! mdoc_word_alloc(mdoc, line, la, p))
912 return(0);
913 mdoc->next = MDOC_NEXT_SIBLING;
914 }
915
916 if (0 == lastpunct && ! rew_elem(mdoc, tok))
917 return(0);
918
919 /*
920 * If no elements have been collected and we're allowed to have
921 * empties (nc), open a scope and close it out. Otherwise,
922 * raise a warning.
923 *
924 */
925 if (nc && 0 == cnt) {
926 c = mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
927 if (0 == c)
928 return(0);
929 if ( ! rew_last(mdoc, mdoc->last))
930 return(0);
931 } else if ( ! nc && 0 == cnt) {
932 mdoc_argv_free(arg);
933 if ( ! pwarn(mdoc, line, ppos, WIGNE))
934 return(0);
935 }
936
937 if (ppos > 1)
938 return(1);
939 return(append_delims(mdoc, line, pos, buf));
940 }
941
942
943 /*
944 * Block full-explicit and full-implicit.
945 */
946 static int
947 blk_full(MACRO_PROT_ARGS)
948 {
949 int c, lastarg, reopen;
950 struct mdoc_arg *arg;
951 char *p;
952
953 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
954 if ( ! rew_subblock(MDOC_BODY, mdoc,
955 tok, line, ppos))
956 return(0);
957 if ( ! rew_impblock(mdoc, tok, line, ppos))
958 return(0);
959 }
960
961 for (arg = NULL;; ) {
962 lastarg = *pos;
963 c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
964
965 if (ARGV_WORD == c) {
966 *pos = lastarg;
967 break;
968 }
969
970 if (ARGV_EOLN == c)
971 break;
972 if (ARGV_ARG == c)
973 continue;
974
975 mdoc_argv_free(arg);
976 return(0);
977 }
978
979 if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg))
980 return(0);
981 mdoc->next = MDOC_NEXT_CHILD;
982
983 if (0 == buf[*pos]) {
984 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
985 return(0);
986 if ( ! rew_subblock(MDOC_HEAD, mdoc,
987 tok, line, ppos))
988 return(0);
989 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
990 return(0);
991 mdoc->next = MDOC_NEXT_CHILD;
992 return(1);
993 }
994
995 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
996 return(0);
997 mdoc->next = MDOC_NEXT_CHILD;
998
999 for (reopen = 0;; ) {
1000 lastarg = *pos;
1001 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1002
1003 if (ARGS_ERROR == c)
1004 return(0);
1005 if (ARGS_EOLN == c)
1006 break;
1007 if (ARGS_PHRASE == c) {
1008 if (reopen && ! mdoc_head_alloc
1009 (mdoc, line, ppos, tok))
1010 return(0);
1011 mdoc->next = MDOC_NEXT_CHILD;
1012 /*
1013 * Phrases are self-contained macro phrases used
1014 * in the columnar output of a macro. They need
1015 * special handling.
1016 */
1017 if ( ! phrase(mdoc, line, lastarg, buf))
1018 return(0);
1019 if ( ! rew_subblock(MDOC_HEAD, mdoc,
1020 tok, line, ppos))
1021 return(0);
1022
1023 reopen = 1;
1024 continue;
1025 }
1026
1027 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1028 return(0);
1029
1030 if (MDOC_MAX == c) {
1031 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1032 return(0);
1033 mdoc->next = MDOC_NEXT_SIBLING;
1034 continue;
1035 }
1036
1037 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1038 return(0);
1039 break;
1040 }
1041
1042 if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
1043 return(0);
1044 if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1045 return(0);
1046
1047 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1048 return(0);
1049 mdoc->next = MDOC_NEXT_CHILD;
1050
1051 return(1);
1052 }
1053
1054
1055 /*
1056 * Block partial-imnplicit scope.
1057 */
1058 static int
1059 blk_part_imp(MACRO_PROT_ARGS)
1060 {
1061 int lastarg, c;
1062 char *p;
1063 struct mdoc_node *blk, *body, *n;
1064
1065 if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
1066 return(0);
1067 mdoc->next = MDOC_NEXT_CHILD;
1068 blk = mdoc->last;
1069
1070 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1071 return(0);
1072 mdoc->next = MDOC_NEXT_SIBLING;
1073
1074 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1075 return(0);
1076 mdoc->next = MDOC_NEXT_CHILD;
1077 body = mdoc->last;
1078
1079 /* XXX - no known argument macros. */
1080
1081 for (lastarg = ppos;; ) {
1082 lastarg = *pos;
1083 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1084 assert(ARGS_PHRASE != c);
1085
1086 if (ARGS_ERROR == c)
1087 return(0);
1088 if (ARGS_PUNCT == c)
1089 break;
1090 if (ARGS_EOLN == c)
1091 break;
1092
1093 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1094 return(0);
1095 else if (MDOC_MAX == c) {
1096 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1097 return(0);
1098 mdoc->next = MDOC_NEXT_SIBLING;
1099 continue;
1100 }
1101
1102 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1103 return(0);
1104 break;
1105 }
1106
1107 /*
1108 * Since we know what our context is, we can rewind directly to
1109 * it. This allows us to accomodate for our scope being
1110 * violated by another token.
1111 */
1112
1113 for (n = mdoc->last; n; n = n->parent)
1114 if (body == n)
1115 break;
1116
1117 if (NULL == n && ! pwarn(mdoc, body->line, body->pos, WIMPBRK))
1118 return(0);
1119
1120 if (n && ! rew_last(mdoc, body))
1121 return(0);
1122
1123 if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
1124 return(0);
1125
1126 if (n && ! rew_last(mdoc, blk))
1127 return(0);
1128
1129 return(1);
1130 }
1131
1132
1133 /*
1134 * Block partial-explicit macros.
1135 */
1136 static int
1137 blk_part_exp(MACRO_PROT_ARGS)
1138 {
1139 int lastarg, flushed, j, c, maxargs;
1140 char *p;
1141
1142 lastarg = ppos;
1143 flushed = 0;
1144
1145 /*
1146 * Number of arguments (head arguments). Only `Eo' has these,
1147 */
1148
1149 switch (tok) {
1150 case (MDOC_Eo):
1151 maxargs = 1;
1152 break;
1153 default:
1154 maxargs = 0;
1155 break;
1156 }
1157
1158 if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
1159 return(0);
1160 mdoc->next = MDOC_NEXT_CHILD;
1161
1162 if (0 == maxargs) {
1163 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1164 return(0);
1165 if ( ! rew_subblock(MDOC_HEAD, mdoc,
1166 tok, line, ppos))
1167 return(0);
1168 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1169 return(0);
1170 flushed = 1;
1171 } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1172 return(0);
1173
1174 mdoc->next = MDOC_NEXT_CHILD;
1175
1176 for (j = 0; ; j++) {
1177 lastarg = *pos;
1178 if (j == maxargs && ! flushed) {
1179 if ( ! rew_subblock(MDOC_HEAD, mdoc,
1180 tok, line, ppos))
1181 return(0);
1182 flushed = 1;
1183 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1184 return(0);
1185 mdoc->next = MDOC_NEXT_CHILD;
1186 }
1187
1188 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1189 assert(ARGS_PHRASE != c);
1190
1191 if (ARGS_ERROR == c)
1192 return(0);
1193 if (ARGS_PUNCT == c)
1194 break;
1195 if (ARGS_EOLN == c)
1196 break;
1197
1198 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1199 return(0);
1200 else if (MDOC_MAX != c) {
1201 if ( ! flushed) {
1202 if ( ! rew_subblock(MDOC_HEAD, mdoc,
1203 tok, line, ppos))
1204 return(0);
1205 flushed = 1;
1206 if ( ! mdoc_body_alloc(mdoc, line,
1207 ppos, tok))
1208 return(0);
1209 mdoc->next = MDOC_NEXT_CHILD;
1210 }
1211 if ( ! mdoc_macro(mdoc, c, line, lastarg,
1212 pos, buf))
1213 return(0);
1214 break;
1215 }
1216
1217 if ( ! flushed && mdoc_isdelim(p)) {
1218 if ( ! rew_subblock(MDOC_HEAD, mdoc,
1219 tok, line, ppos))
1220 return(0);
1221 flushed = 1;
1222 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1223 return(0);
1224 mdoc->next = MDOC_NEXT_CHILD;
1225 }
1226
1227 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1228 return(0);
1229 mdoc->next = MDOC_NEXT_SIBLING;
1230 }
1231
1232 if ( ! flushed) {
1233 if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1234 return(0);
1235 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1236 return(0);
1237 mdoc->next = MDOC_NEXT_CHILD;
1238 }
1239
1240 if (ppos > 1)
1241 return(1);
1242 return(append_delims(mdoc, line, pos, buf));
1243 }
1244
1245
1246 /*
1247 * In-line macros where reserved words signal closure of the macro.
1248 * Macros also have a fixed number of arguments.
1249 */
1250 static int
1251 in_line_argn(MACRO_PROT_ARGS)
1252 {
1253 int lastarg, flushed, j, c, maxargs;
1254 struct mdoc_arg *arg;
1255 char *p;
1256
1257
1258 /*
1259 * Fixed maximum arguments per macro. Some of these have none
1260 * and close as soon as the invocation is parsed.
1261 */
1262
1263 switch (tok) {
1264 case (MDOC_Ap):
1265 /* FALLTHROUGH */
1266 case (MDOC_No):
1267 /* FALLTHROUGH */
1268 case (MDOC_Ns):
1269 /* FALLTHROUGH */
1270 case (MDOC_Ux):
1271 maxargs = 0;
1272 break;
1273 default:
1274 maxargs = 1;
1275 break;
1276 }
1277
1278 for (lastarg = ppos, arg = NULL;; ) {
1279 lastarg = *pos;
1280 c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1281
1282 if (ARGV_WORD == c) {
1283 *pos = lastarg;
1284 break;
1285 }
1286
1287 if (ARGV_EOLN == c)
1288 break;
1289 if (ARGV_ARG == c)
1290 continue;
1291
1292 mdoc_argv_free(arg);
1293 return(0);
1294 }
1295
1296 if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
1297 return(0);
1298 mdoc->next = MDOC_NEXT_CHILD;
1299
1300 for (flushed = j = 0; ; j++) {
1301 lastarg = *pos;
1302
1303 if (j == maxargs && ! flushed) {
1304 if ( ! rew_elem(mdoc, tok))
1305 return(0);
1306 flushed = 1;
1307 }
1308
1309 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1310
1311 if (ARGS_ERROR == c)
1312 return(0);
1313 if (ARGS_PUNCT == c)
1314 break;
1315 if (ARGS_EOLN == c)
1316 break;
1317
1318 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1319 return(0);
1320 else if (MDOC_MAX != c) {
1321 if ( ! flushed && ! rew_elem(mdoc, tok))
1322 return(0);
1323 flushed = 1;
1324 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1325 return(0);
1326 break;
1327 }
1328
1329 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1330 ! flushed && mdoc_isdelim(p)) {
1331 if ( ! rew_elem(mdoc, tok))
1332 return(0);
1333 flushed = 1;
1334 }
1335
1336 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1337 return(0);
1338 mdoc->next = MDOC_NEXT_SIBLING;
1339 }
1340
1341 if ( ! flushed && ! rew_elem(mdoc, tok))
1342 return(0);
1343
1344 if (ppos > 1)
1345 return(1);
1346 return(append_delims(mdoc, line, pos, buf));
1347 }
1348
1349
1350 /*
1351 * In-line macro that spans an entire line. May be callable, but has no
1352 * subsequent parsed arguments.
1353 */
1354 static int
1355 in_line_eoln(MACRO_PROT_ARGS)
1356 {
1357 int c, w, la;
1358 struct mdoc_arg *arg;
1359 char *p;
1360
1361 assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1362
1363 arg = NULL;
1364
1365 for (;;) {
1366 la = *pos;
1367 c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1368
1369 if (ARGV_WORD == c) {
1370 *pos = la;
1371 break;
1372 }
1373 if (ARGV_EOLN == c)
1374 break;
1375 if (ARGV_ARG == c)
1376 continue;
1377
1378 mdoc_argv_free(arg);
1379 return(0);
1380 }
1381
1382 if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
1383 return(0);
1384
1385 mdoc->next = MDOC_NEXT_CHILD;
1386
1387 for (;;) {
1388 la = *pos;
1389 w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1390
1391 if (ARGS_ERROR == w)
1392 return(0);
1393 if (ARGS_EOLN == w)
1394 break;
1395
1396 c = ARGS_QWORD == w ? MDOC_MAX :
1397 lookup(mdoc, line, la, tok, p);
1398
1399 if (MDOC_MAX != c && -1 != c) {
1400 if ( ! rew_elem(mdoc, tok))
1401 return(0);
1402 return(mdoc_macro(mdoc, c, line, la, pos, buf));
1403 } else if (-1 == c)
1404 return(0);
1405
1406 if ( ! mdoc_word_alloc(mdoc, line, la, p))
1407 return(0);
1408 mdoc->next = MDOC_NEXT_SIBLING;
1409 }
1410
1411 return(rew_elem(mdoc, tok));
1412 }
1413
1414
1415 /* ARGSUSED */
1416 static int
1417 obsolete(MACRO_PROT_ARGS)
1418 {
1419
1420 return(pwarn(mdoc, line, ppos, WOBS));
1421 }
1422
1423
1424 static int
1425 phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
1426 {
1427 int i, la, c, quoted;
1428
1429 /*
1430 * Parse over words in a phrase. We have to handle this
1431 * specially because we assume no calling context -- in normal
1432 * circumstances, we switch argument parsing based on whether
1433 * the parent macro accepts quotes, tabs, etc. Here, anything
1434 * goes.
1435 */
1436
1437 for (i = ppos; buf[i]; ) {
1438 assert(' ' != buf[i]);
1439 la = i;
1440 quoted = 0;
1441
1442 /*
1443 * Read to next token. If quoted (check not escaped),
1444 * scan ahead to next unescaped quote. If not quoted or
1445 * escape-quoted, then scan ahead to next space.
1446 */
1447
1448 if ((i && '\"' == buf[i] && '\\' != buf[i - 1]) ||
1449 (0 == i && '\"' == buf[i])) {
1450 for (la = ++i; buf[i]; i++)
1451 if ('\"' != buf[i])
1452 continue;
1453 else if ('\\' != buf[i - 1])
1454 break;
1455 if (0 == buf[i])
1456 return(perr(mdoc, line, la, EQUOT));
1457 quoted = 1;
1458 } else
1459 for ( ; buf[i]; i++)
1460 if (i && ' ' == buf[i]) {
1461 if ('\\' != buf[i - 1])
1462 break;
1463 } else if (' ' == buf[i])
1464 break;
1465
1466 /* If not end-of-line, terminate argument. */
1467
1468 if (buf[i])
1469 buf[i++] = 0;
1470
1471 /* Read to next argument. */
1472
1473 for ( ; buf[i] && ' ' == buf[i]; i++)
1474 /* Spin. */ ;
1475
1476 /*
1477 * If we're a non-quoted string, try to look up the
1478 * value as a macro and execute it, if found.
1479 */
1480
1481 c = quoted ? MDOC_MAX :
1482 mdoc_hash_find(mdoc->htab, &buf[la]);
1483
1484 if (MDOC_MAX != c) {
1485 if ( ! mdoc_macro(mdoc, c, line, la, &i, buf))
1486 return(0);
1487 return(append_delims(mdoc, line, &i, buf));
1488 }
1489
1490 /* A regular word or quoted string. */
1491
1492 if ( ! mdoc_word_alloc(mdoc, line, la, &buf[la]))
1493 return(0);
1494 mdoc->next = MDOC_NEXT_SIBLING;
1495 }
1496
1497 return(1);
1498 }