]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_macro.c
51c852a012421a80852e818e7cc6bcd006ea34ab
[mandoc.git] / mdoc_macro.c
1 /* $Id: mdoc_macro.c,v 1.82 2010/06/27 15:52:41 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
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 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <assert.h>
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <time.h>
27
28 #include "mandoc.h"
29 #include "libmdoc.h"
30 #include "libmandoc.h"
31
32 enum rew {
33 REWIND_REWIND,
34 REWIND_NOHALT,
35 REWIND_HALT
36 };
37
38 static int blk_full(MACRO_PROT_ARGS);
39 static int blk_exp_close(MACRO_PROT_ARGS);
40 static int blk_part_exp(MACRO_PROT_ARGS);
41 static int blk_part_imp(MACRO_PROT_ARGS);
42 static int ctx_synopsis(MACRO_PROT_ARGS);
43 static int in_line_eoln(MACRO_PROT_ARGS);
44 static int in_line_argn(MACRO_PROT_ARGS);
45 static int in_line(MACRO_PROT_ARGS);
46 static int obsolete(MACRO_PROT_ARGS);
47 static int phrase_ta(MACRO_PROT_ARGS);
48
49 static int append_delims(struct mdoc *,
50 int, int *, char *);
51 static enum mdoct lookup(enum mdoct, const char *);
52 static enum mdoct lookup_raw(const char *);
53 static int phrase(struct mdoc *, int, int, char *);
54 static enum mdoct rew_alt(enum mdoct);
55 static int rew_dobreak(enum mdoct,
56 const struct mdoc_node *);
57 static enum rew rew_dohalt(enum mdoct, enum mdoc_type,
58 const struct mdoc_node *);
59 static int rew_elem(struct mdoc *, enum mdoct);
60 static int rew_last(struct mdoc *,
61 const struct mdoc_node *);
62 static int rew_sub(enum mdoc_type, struct mdoc *,
63 enum mdoct, int, int);
64 static int swarn(struct mdoc *, enum mdoc_type, int,
65 int, const struct mdoc_node *);
66
67 const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
68 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
69 { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
70 { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
71 { in_line_eoln, MDOC_PROLOGUE }, /* Os */
72 { blk_full, 0 }, /* Sh */
73 { blk_full, 0 }, /* Ss */
74 { in_line_eoln, 0 }, /* Pp */
75 { blk_part_imp, MDOC_PARSED }, /* D1 */
76 { blk_part_imp, MDOC_PARSED }, /* Dl */
77 { blk_full, MDOC_EXPLICIT }, /* Bd */
78 { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
79 { blk_full, MDOC_EXPLICIT }, /* Bl */
80 { blk_exp_close, MDOC_EXPLICIT }, /* El */
81 { blk_full, MDOC_PARSED }, /* It */
82 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
83 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
84 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
85 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
86 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
87 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
88 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
89 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
90 { in_line_eoln, 0 }, /* Ex */
91 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
92 { in_line_eoln, 0 }, /* Fd */
93 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
94 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
95 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
96 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
97 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
98 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
99 { blk_full, 0 }, /* Nd */
100 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
101 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
102 { obsolete, 0 }, /* Ot */
103 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
104 { in_line_eoln, 0 }, /* Rv */
105 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
106 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
107 { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
108 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
109 { in_line_eoln, 0 }, /* %A */
110 { in_line_eoln, 0 }, /* %B */
111 { in_line_eoln, 0 }, /* %D */
112 { in_line_eoln, 0 }, /* %I */
113 { in_line_eoln, 0 }, /* %J */
114 { in_line_eoln, 0 }, /* %N */
115 { in_line_eoln, 0 }, /* %O */
116 { in_line_eoln, 0 }, /* %P */
117 { in_line_eoln, 0 }, /* %R */
118 { in_line_eoln, 0 }, /* %T */
119 { in_line_eoln, 0 }, /* %V */
120 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
121 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
122 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
123 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
124 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
125 { blk_full, MDOC_EXPLICIT }, /* Bf */
126 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
127 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
128 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
129 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
130 { in_line_eoln, 0 }, /* Db */
131 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
132 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
133 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
134 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
135 { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
136 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
137 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
138 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
139 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
140 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */
141 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
142 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
143 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
144 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
145 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
146 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
147 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
148 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
149 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
150 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
151 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
152 { blk_exp_close, MDOC_EXPLICIT }, /* Re */
153 { blk_full, MDOC_EXPLICIT }, /* Rs */
154 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
155 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
156 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
157 { in_line_eoln, 0 }, /* Sm */
158 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
159 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
160 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
161 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
162 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
163 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
164 { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
165 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
166 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
167 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
168 { blk_full, MDOC_EXPLICIT }, /* Bk */
169 { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
170 { in_line_eoln, 0 }, /* Bt */
171 { in_line_eoln, 0 }, /* Hf */
172 { obsolete, 0 }, /* Fr */
173 { in_line_eoln, 0 }, /* Ud */
174 { in_line, 0 }, /* Lb */
175 { in_line_eoln, 0 }, /* Lp */
176 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
177 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
178 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
179 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
180 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
181 { in_line_eoln, 0 }, /* %C */
182 { obsolete, 0 }, /* Es */
183 { obsolete, 0 }, /* En */
184 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
185 { in_line_eoln, 0 }, /* %Q */
186 { in_line_eoln, 0 }, /* br */
187 { in_line_eoln, 0 }, /* sp */
188 { in_line_eoln, 0 }, /* %U */
189 { phrase_ta, MDOC_CALLABLE | MDOC_PARSED }, /* Ta */
190 };
191
192 const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
193
194
195 static int
196 swarn(struct mdoc *mdoc, enum mdoc_type type,
197 int line, int pos, const struct mdoc_node *p)
198 {
199 const char *n, *t, *tt;
200 enum mandocerr ec;
201
202 n = t = "<root>";
203 tt = "block";
204
205 switch (type) {
206 case (MDOC_BODY):
207 tt = "multi-line";
208 break;
209 case (MDOC_HEAD):
210 tt = "line";
211 break;
212 default:
213 break;
214 }
215
216 switch (p->type) {
217 case (MDOC_BLOCK):
218 n = mdoc_macronames[p->tok];
219 t = "block";
220 break;
221 case (MDOC_BODY):
222 n = mdoc_macronames[p->tok];
223 t = "multi-line";
224 break;
225 case (MDOC_HEAD):
226 n = mdoc_macronames[p->tok];
227 t = "line";
228 break;
229 default:
230 break;
231 }
232
233 ec = (MDOC_IGN_SCOPE & mdoc->pflags) ?
234 MANDOCERR_SCOPE : MANDOCERR_SYNTSCOPE;
235
236 return(mdoc_vmsg(mdoc, ec, line, pos,
237 "%s scope breaks %s of %s",
238 tt, t, n));
239 }
240
241
242 /*
243 * This is called at the end of parsing. It must traverse up the tree,
244 * closing out open [implicit] scopes. Obviously, open explicit scopes
245 * are errors.
246 */
247 int
248 mdoc_macroend(struct mdoc *m)
249 {
250 struct mdoc_node *n;
251
252 /* Scan for open explicit scopes. */
253
254 n = MDOC_VALID & m->last->flags ? m->last->parent : m->last;
255
256 for ( ; n; n = n->parent) {
257 if (MDOC_BLOCK != n->type)
258 continue;
259 if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
260 continue;
261 mdoc_nmsg(m, n, MANDOCERR_SYNTSCOPE);
262 return(0);
263 }
264
265 /* Rewind to the first. */
266
267 return(rew_last(m, m->first));
268 }
269
270
271 /*
272 * Look up a macro from within a subsequent context.
273 */
274 static enum mdoct
275 lookup(enum mdoct from, const char *p)
276 {
277 /* FIXME: make -diag lists be un-PARSED. */
278
279 if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
280 return(MDOC_MAX);
281 return(lookup_raw(p));
282 }
283
284
285 /*
286 * Lookup a macro following the initial line macro.
287 */
288 static enum mdoct
289 lookup_raw(const char *p)
290 {
291 enum mdoct res;
292
293 if (MDOC_MAX == (res = mdoc_hash_find(p)))
294 return(MDOC_MAX);
295 if (MDOC_CALLABLE & mdoc_macros[res].flags)
296 return(res);
297 return(MDOC_MAX);
298 }
299
300
301 static int
302 rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
303 {
304
305 assert(to);
306 mdoc->next = MDOC_NEXT_SIBLING;
307
308 /* LINTED */
309 while (mdoc->last != to) {
310 if ( ! mdoc_valid_post(mdoc))
311 return(0);
312 if ( ! mdoc_action_post(mdoc))
313 return(0);
314 mdoc->last = mdoc->last->parent;
315 assert(mdoc->last);
316 }
317
318 if ( ! mdoc_valid_post(mdoc))
319 return(0);
320 return(mdoc_action_post(mdoc));
321 }
322
323
324 /*
325 * Return the opening macro of a closing one, e.g., `Ec' has `Eo' as its
326 * matching pair.
327 */
328 static enum mdoct
329 rew_alt(enum mdoct tok)
330 {
331 switch (tok) {
332 case (MDOC_Ac):
333 return(MDOC_Ao);
334 case (MDOC_Bc):
335 return(MDOC_Bo);
336 case (MDOC_Brc):
337 return(MDOC_Bro);
338 case (MDOC_Dc):
339 return(MDOC_Do);
340 case (MDOC_Ec):
341 return(MDOC_Eo);
342 case (MDOC_Ed):
343 return(MDOC_Bd);
344 case (MDOC_Ef):
345 return(MDOC_Bf);
346 case (MDOC_Ek):
347 return(MDOC_Bk);
348 case (MDOC_El):
349 return(MDOC_Bl);
350 case (MDOC_Fc):
351 return(MDOC_Fo);
352 case (MDOC_Oc):
353 return(MDOC_Oo);
354 case (MDOC_Pc):
355 return(MDOC_Po);
356 case (MDOC_Qc):
357 return(MDOC_Qo);
358 case (MDOC_Re):
359 return(MDOC_Rs);
360 case (MDOC_Sc):
361 return(MDOC_So);
362 case (MDOC_Xc):
363 return(MDOC_Xo);
364 default:
365 break;
366 }
367 abort();
368 /* NOTREACHED */
369 }
370
371
372 /*
373 * Rewind rules. This indicates whether to stop rewinding
374 * (REWIND_HALT) without touching our current scope, stop rewinding and
375 * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
376 * The scope-closing and so on occurs in the various rew_* routines.
377 */
378 static enum rew
379 rew_dohalt(enum mdoct tok, enum mdoc_type type,
380 const struct mdoc_node *p)
381 {
382
383 if (MDOC_ROOT == p->type)
384 return(REWIND_HALT);
385 if (MDOC_VALID & p->flags)
386 return(REWIND_NOHALT);
387
388 switch (tok) {
389 case (MDOC_Aq):
390 /* FALLTHROUGH */
391 case (MDOC_Bq):
392 /* FALLTHROUGH */
393 case (MDOC_Brq):
394 /* FALLTHROUGH */
395 case (MDOC_D1):
396 /* FALLTHROUGH */
397 case (MDOC_Dl):
398 /* FALLTHROUGH */
399 case (MDOC_Dq):
400 /* FALLTHROUGH */
401 case (MDOC_Op):
402 /* FALLTHROUGH */
403 case (MDOC_Pq):
404 /* FALLTHROUGH */
405 case (MDOC_Ql):
406 /* FALLTHROUGH */
407 case (MDOC_Qq):
408 /* FALLTHROUGH */
409 case (MDOC_Sq):
410 /* FALLTHROUGH */
411 case (MDOC_Vt):
412 assert(MDOC_TAIL != type);
413 if (type == p->type && tok == p->tok)
414 return(REWIND_REWIND);
415 break;
416 case (MDOC_It):
417 assert(MDOC_TAIL != type);
418 if (type == p->type && tok == p->tok)
419 return(REWIND_REWIND);
420 if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
421 return(REWIND_HALT);
422 break;
423 case (MDOC_Sh):
424 if (type == p->type && tok == p->tok)
425 return(REWIND_REWIND);
426 break;
427 case (MDOC_Nd):
428 /* FALLTHROUGH */
429 case (MDOC_Ss):
430 assert(MDOC_TAIL != type);
431 if (type == p->type && tok == p->tok)
432 return(REWIND_REWIND);
433 if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
434 return(REWIND_HALT);
435 break;
436 case (MDOC_Ao):
437 /* FALLTHROUGH */
438 case (MDOC_Bd):
439 /* FALLTHROUGH */
440 case (MDOC_Bf):
441 /* FALLTHROUGH */
442 case (MDOC_Bk):
443 /* FALLTHROUGH */
444 case (MDOC_Bl):
445 /* FALLTHROUGH */
446 case (MDOC_Bo):
447 /* FALLTHROUGH */
448 case (MDOC_Bro):
449 /* FALLTHROUGH */
450 case (MDOC_Do):
451 /* FALLTHROUGH */
452 case (MDOC_Eo):
453 /* FALLTHROUGH */
454 case (MDOC_Fo):
455 /* FALLTHROUGH */
456 case (MDOC_Oo):
457 /* FALLTHROUGH */
458 case (MDOC_Po):
459 /* FALLTHROUGH */
460 case (MDOC_Qo):
461 /* FALLTHROUGH */
462 case (MDOC_Rs):
463 /* FALLTHROUGH */
464 case (MDOC_So):
465 /* FALLTHROUGH */
466 case (MDOC_Xo):
467 if (type == p->type && tok == p->tok)
468 return(REWIND_REWIND);
469 break;
470 /* Multi-line explicit scope close. */
471 case (MDOC_Ac):
472 /* FALLTHROUGH */
473 case (MDOC_Bc):
474 /* FALLTHROUGH */
475 case (MDOC_Brc):
476 /* FALLTHROUGH */
477 case (MDOC_Dc):
478 /* FALLTHROUGH */
479 case (MDOC_Ec):
480 /* FALLTHROUGH */
481 case (MDOC_Ed):
482 /* FALLTHROUGH */
483 case (MDOC_Ek):
484 /* FALLTHROUGH */
485 case (MDOC_El):
486 /* FALLTHROUGH */
487 case (MDOC_Fc):
488 /* FALLTHROUGH */
489 case (MDOC_Ef):
490 /* FALLTHROUGH */
491 case (MDOC_Oc):
492 /* FALLTHROUGH */
493 case (MDOC_Pc):
494 /* FALLTHROUGH */
495 case (MDOC_Qc):
496 /* FALLTHROUGH */
497 case (MDOC_Re):
498 /* FALLTHROUGH */
499 case (MDOC_Sc):
500 /* FALLTHROUGH */
501 case (MDOC_Xc):
502 if (type == p->type && rew_alt(tok) == p->tok)
503 return(REWIND_REWIND);
504 break;
505 default:
506 abort();
507 /* NOTREACHED */
508 }
509
510 return(REWIND_NOHALT);
511 }
512
513
514 /*
515 * See if we can break an encountered scope (the rew_dohalt has returned
516 * REWIND_NOHALT).
517 */
518 static int
519 rew_dobreak(enum mdoct tok, const struct mdoc_node *p)
520 {
521
522 assert(MDOC_ROOT != p->type);
523 if (MDOC_ELEM == p->type)
524 return(1);
525 if (MDOC_TEXT == p->type)
526 return(1);
527 if (MDOC_VALID & p->flags)
528 return(1);
529
530 switch (tok) {
531 case (MDOC_It):
532 return(MDOC_It == p->tok);
533 case (MDOC_Nd):
534 return(MDOC_Nd == p->tok);
535 case (MDOC_Ss):
536 return(MDOC_Ss == p->tok);
537 case (MDOC_Sh):
538 if (MDOC_Nd == p->tok)
539 return(1);
540 if (MDOC_Ss == p->tok)
541 return(1);
542 return(MDOC_Sh == p->tok);
543 case (MDOC_El):
544 if (MDOC_It == p->tok)
545 return(1);
546 break;
547 case (MDOC_Oc):
548 if (MDOC_Op == p->tok)
549 return(1);
550 break;
551 default:
552 break;
553 }
554
555 if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
556 return(p->tok == rew_alt(tok));
557 else if (MDOC_BLOCK == p->type)
558 return(1);
559
560 return(tok == p->tok);
561 }
562
563
564 static int
565 rew_elem(struct mdoc *mdoc, enum mdoct tok)
566 {
567 struct mdoc_node *n;
568
569 n = mdoc->last;
570 if (MDOC_ELEM != n->type)
571 n = n->parent;
572 assert(MDOC_ELEM == n->type);
573 assert(tok == n->tok);
574
575 return(rew_last(mdoc, n));
576 }
577
578
579 static int
580 rew_sub(enum mdoc_type t, struct mdoc *m,
581 enum mdoct tok, int line, int ppos)
582 {
583 struct mdoc_node *n;
584 enum rew c;
585
586 /* LINTED */
587 for (n = m->last; n; n = n->parent) {
588 c = rew_dohalt(tok, t, n);
589 if (REWIND_HALT == c) {
590 if (MDOC_BLOCK != t)
591 return(1);
592 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))
593 return(1);
594 /* FIXME: shouldn't raise an error */
595 mdoc_pmsg(m, line, ppos, MANDOCERR_SYNTNOSCOPE);
596 return(0);
597 }
598 if (REWIND_REWIND == c)
599 break;
600 else if (rew_dobreak(tok, n))
601 continue;
602 if ( ! swarn(m, t, line, ppos, n))
603 return(0);
604 }
605
606 assert(n);
607 if ( ! rew_last(m, n))
608 return(0);
609
610 /*
611 * The current block extends an enclosing block beyond a line
612 * break. Now that the current block ends, close the enclosing
613 * block, too.
614 */
615 if (NULL != (n = n->pending)) {
616 assert(MDOC_HEAD == n->type);
617 if ( ! rew_last(m, n))
618 return(0);
619 if ( ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
620 return(0);
621 }
622
623 return(1);
624 }
625
626
627 static int
628 append_delims(struct mdoc *m, int line, int *pos, char *buf)
629 {
630 int la;
631 enum margserr ac;
632 char *p;
633
634 if ('\0' == buf[*pos])
635 return(1);
636
637 for (;;) {
638 la = *pos;
639 ac = mdoc_zargs(m, line, pos, buf, ARGS_NOWARN, &p);
640
641 if (ARGS_ERROR == ac)
642 return(0);
643 else if (ARGS_EOLN == ac)
644 break;
645
646 assert(DELIM_NONE != mdoc_isdelim(p));
647 if ( ! mdoc_word_alloc(m, line, la, p))
648 return(0);
649
650 /*
651 * If we encounter end-of-sentence symbols, then trigger
652 * the double-space.
653 *
654 * XXX: it's easy to allow this to propogate outward to
655 * the last symbol, such that `. )' will cause the
656 * correct double-spacing. However, (1) groff isn't
657 * smart enough to do this and (2) it would require
658 * knowing which symbols break this behaviour, for
659 * example, `. ;' shouldn't propogate the double-space.
660 */
661 if (mandoc_eos(p, strlen(p)))
662 m->last->flags |= MDOC_EOS;
663 }
664
665 return(1);
666 }
667
668
669 /*
670 * Close out block partial/full explicit.
671 */
672 static int
673 blk_exp_close(MACRO_PROT_ARGS)
674 {
675 int j, lastarg, maxargs, flushed, nl;
676 enum margserr ac;
677 enum mdoct ntok;
678 char *p;
679
680 nl = MDOC_NEWLINE & m->flags;
681
682 switch (tok) {
683 case (MDOC_Ec):
684 maxargs = 1;
685 break;
686 default:
687 maxargs = 0;
688 break;
689 }
690
691 if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
692 /* FIXME: do this in validate */
693 if (buf[*pos])
694 if ( ! mdoc_pmsg(m, line, ppos, MANDOCERR_ARGSLOST))
695 return(0);
696
697 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
698 return(0);
699 return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
700 }
701
702 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
703 return(0);
704
705 if (maxargs > 0)
706 if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
707 return(0);
708
709 for (flushed = j = 0; ; j++) {
710 lastarg = *pos;
711
712 if (j == maxargs && ! flushed) {
713 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
714 return(0);
715 flushed = 1;
716 }
717
718 ac = mdoc_args(m, line, pos, buf, tok, &p);
719
720 if (ARGS_ERROR == ac)
721 return(0);
722 if (ARGS_PUNCT == ac)
723 break;
724 if (ARGS_EOLN == ac)
725 break;
726
727 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
728
729 if (MDOC_MAX == ntok) {
730 if ( ! mdoc_word_alloc(m, line, lastarg, p))
731 return(0);
732 continue;
733 }
734
735 if ( ! flushed) {
736 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
737 return(0);
738 flushed = 1;
739 }
740 if ( ! mdoc_macro(m, ntok, line, lastarg, pos, buf))
741 return(0);
742 break;
743 }
744
745 if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
746 return(0);
747
748 if ( ! nl)
749 return(1);
750 return(append_delims(m, line, pos, buf));
751 }
752
753
754 static int
755 in_line(MACRO_PROT_ARGS)
756 {
757 int la, scope, cnt, nc, nl;
758 enum margverr av;
759 enum mdoct ntok;
760 enum margserr ac;
761 enum mdelim d;
762 struct mdoc_arg *arg;
763 char *p;
764
765 nl = MDOC_NEWLINE & m->flags;
766
767 /*
768 * Whether we allow ignored elements (those without content,
769 * usually because of reserved words) to squeak by.
770 */
771
772 switch (tok) {
773 case (MDOC_An):
774 /* FALLTHROUGH */
775 case (MDOC_Ar):
776 /* FALLTHROUGH */
777 case (MDOC_Fl):
778 /* FALLTHROUGH */
779 case (MDOC_Lk):
780 /* FALLTHROUGH */
781 case (MDOC_Nm):
782 /* FALLTHROUGH */
783 case (MDOC_Pa):
784 nc = 1;
785 break;
786 default:
787 nc = 0;
788 break;
789 }
790
791 for (arg = NULL;; ) {
792 la = *pos;
793 av = mdoc_argv(m, line, tok, &arg, pos, buf);
794
795 if (ARGV_WORD == av) {
796 *pos = la;
797 break;
798 }
799 if (ARGV_EOLN == av)
800 break;
801 if (ARGV_ARG == av)
802 continue;
803
804 mdoc_argv_free(arg);
805 return(0);
806 }
807
808 for (cnt = scope = 0;; ) {
809 la = *pos;
810 ac = mdoc_args(m, line, pos, buf, tok, &p);
811
812 if (ARGS_ERROR == ac)
813 return(0);
814 if (ARGS_EOLN == ac)
815 break;
816 if (ARGS_PUNCT == ac)
817 break;
818
819 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
820
821 /*
822 * In this case, we've located a submacro and must
823 * execute it. Close out scope, if open. If no
824 * elements have been generated, either create one (nc)
825 * or raise a warning.
826 */
827
828 if (MDOC_MAX != ntok) {
829 if (scope && ! rew_elem(m, tok))
830 return(0);
831 if (nc && 0 == cnt) {
832 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
833 return(0);
834 if ( ! rew_last(m, m->last))
835 return(0);
836 } else if ( ! nc && 0 == cnt) {
837 mdoc_argv_free(arg);
838 if ( ! mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY))
839 return(0);
840 }
841 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
842 return(0);
843 if ( ! nl)
844 return(1);
845 return(append_delims(m, line, pos, buf));
846 }
847
848 /*
849 * Non-quote-enclosed punctuation. Set up our scope, if
850 * a word; rewind the scope, if a delimiter; then append
851 * the word.
852 */
853
854 d = ARGS_QWORD == ac ? DELIM_NONE : mdoc_isdelim(p);
855
856 if (DELIM_NONE != d) {
857 /*
858 * If we encounter closing punctuation, no word
859 * has been omitted, no scope is open, and we're
860 * allowed to have an empty element, then start
861 * a new scope. `Ar', `Fl', and `Li', only do
862 * this once per invocation. There may be more
863 * of these (all of them?).
864 */
865 if (0 == cnt && (nc || MDOC_Li == tok) &&
866 DELIM_CLOSE == d && ! scope) {
867 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
868 return(0);
869 if (MDOC_Ar == tok || MDOC_Li == tok ||
870 MDOC_Fl == tok)
871 cnt++;
872 scope = 1;
873 }
874 /*
875 * Close out our scope, if one is open, before
876 * any punctuation.
877 */
878 if (scope && ! rew_elem(m, tok))
879 return(0);
880 scope = 0;
881 } else if ( ! scope) {
882 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
883 return(0);
884 scope = 1;
885 }
886
887 if (DELIM_NONE == d)
888 cnt++;
889 if ( ! mdoc_word_alloc(m, line, la, p))
890 return(0);
891
892 /*
893 * `Fl' macros have their scope re-opened with each new
894 * word so that the `-' can be added to each one without
895 * having to parse out spaces.
896 */
897 if (scope && MDOC_Fl == tok) {
898 if ( ! rew_elem(m, tok))
899 return(0);
900 scope = 0;
901 }
902 }
903
904 if (scope && ! rew_elem(m, tok))
905 return(0);
906
907 /*
908 * If no elements have been collected and we're allowed to have
909 * empties (nc), open a scope and close it out. Otherwise,
910 * raise a warning.
911 */
912
913 if (nc && 0 == cnt) {
914 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
915 return(0);
916 if ( ! rew_last(m, m->last))
917 return(0);
918 } else if ( ! nc && 0 == cnt) {
919 mdoc_argv_free(arg);
920 if ( ! mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY))
921 return(0);
922 }
923
924 if ( ! nl)
925 return(1);
926 return(append_delims(m, line, pos, buf));
927 }
928
929
930 static int
931 blk_full(MACRO_PROT_ARGS)
932 {
933 int la, nl;
934 struct mdoc_arg *arg;
935 struct mdoc_node *head; /* save of head macro */
936 struct mdoc_node *body; /* save of body macro */
937 struct mdoc_node *n;
938 enum mdoc_type mtt;
939 enum mdoct ntok;
940 enum margserr ac, lac;
941 enum margverr av;
942 char *p;
943
944 nl = MDOC_NEWLINE & m->flags;
945
946 /* Close out prior implicit scope. */
947
948 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
949 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
950 return(0);
951 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
952 return(0);
953 }
954
955 /*
956 * This routine accomodates implicitly- and explicitly-scoped
957 * macro openings. Implicit ones first close out prior scope
958 * (seen above). Delay opening the head until necessary to
959 * allow leading punctuation to print. Special consideration
960 * for `It -column', which has phrase-part syntax instead of
961 * regular child nodes.
962 */
963
964 for (arg = NULL;; ) {
965 la = *pos;
966 av = mdoc_argv(m, line, tok, &arg, pos, buf);
967
968 if (ARGV_WORD == av) {
969 *pos = la;
970 break;
971 }
972
973 if (ARGV_EOLN == av)
974 break;
975 if (ARGV_ARG == av)
976 continue;
977
978 mdoc_argv_free(arg);
979 return(0);
980 }
981
982 if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
983 return(0);
984
985 head = body = NULL;
986
987 /*
988 * The `Nd' macro has all arguments in its body: it's a hybrid
989 * of block partial-explicit and full-implicit. Stupid.
990 */
991
992 if (MDOC_Nd == tok) {
993 if ( ! mdoc_head_alloc(m, line, ppos, tok))
994 return(0);
995 head = m->last;
996 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
997 return(0);
998 if ( ! mdoc_body_alloc(m, line, ppos, tok))
999 return(0);
1000 body = m->last;
1001 }
1002
1003 ac = ARGS_ERROR;
1004
1005 for ( ; ; ) {
1006 la = *pos;
1007 /* Initialise last-phrase-type with ARGS_PEND. */
1008 lac = ARGS_ERROR == ac ? ARGS_PEND : ac;
1009 ac = mdoc_args(m, line, pos, buf, tok, &p);
1010
1011 if (ARGS_ERROR == ac)
1012 return(0);
1013
1014 if (ARGS_EOLN == ac) {
1015 if (ARGS_PPHRASE != lac && ARGS_PHRASE != lac)
1016 break;
1017 /*
1018 * This is necessary: if the last token on a
1019 * line is a `Ta' or tab, then we'll get
1020 * ARGS_EOLN, so we must be smart enough to
1021 * reopen our scope if the last parse was a
1022 * phrase or partial phrase.
1023 */
1024 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
1025 return(0);
1026 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1027 return(0);
1028 body = m->last;
1029 break;
1030 }
1031
1032 /*
1033 * Emit leading punctuation (i.e., punctuation before
1034 * the MDOC_HEAD) for non-phrase types.
1035 */
1036
1037 if (NULL == head &&
1038 ARGS_PEND != ac &&
1039 ARGS_PHRASE != ac &&
1040 ARGS_PPHRASE != ac &&
1041 ARGS_QWORD != ac &&
1042 DELIM_OPEN == mdoc_isdelim(p)) {
1043 if ( ! mdoc_word_alloc(m, line, la, p))
1044 return(0);
1045 continue;
1046 }
1047
1048 /* Open a head if one hasn't been opened. */
1049
1050 if (NULL == head) {
1051 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1052 return(0);
1053 head = m->last;
1054 }
1055
1056 if (ARGS_PHRASE == ac ||
1057 ARGS_PEND == ac ||
1058 ARGS_PPHRASE == ac) {
1059 /*
1060 * If we haven't opened a body yet, rewind the
1061 * head; if we have, rewind that instead.
1062 */
1063
1064 mtt = body ? MDOC_BODY : MDOC_HEAD;
1065 if ( ! rew_sub(mtt, m, tok, line, ppos))
1066 return(0);
1067
1068 /* Then allocate our body context. */
1069
1070 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1071 return(0);
1072 body = m->last;
1073
1074 /*
1075 * Process phrases: set whether we're in a
1076 * partial-phrase (this effects line handling)
1077 * then call down into the phrase parser.
1078 */
1079
1080 if (ARGS_PPHRASE == ac)
1081 m->flags |= MDOC_PPHRASE;
1082 if (ARGS_PEND == ac && ARGS_PPHRASE == lac)
1083 m->flags |= MDOC_PPHRASE;
1084
1085 if ( ! phrase(m, line, la, buf))
1086 return(0);
1087
1088 m->flags &= ~MDOC_PPHRASE;
1089 continue;
1090 }
1091
1092 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1093
1094 if (MDOC_MAX == ntok) {
1095 if ( ! mdoc_word_alloc(m, line, la, p))
1096 return(0);
1097 continue;
1098 }
1099
1100 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1101 return(0);
1102 break;
1103 }
1104
1105 if (NULL == head) {
1106 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1107 return(0);
1108 head = m->last;
1109 }
1110
1111 if (nl && ! append_delims(m, line, pos, buf))
1112 return(0);
1113
1114 /* If we've already opened our body, exit now. */
1115
1116 if (NULL != body)
1117 goto out;
1118
1119 /*
1120 * If there is an open (i.e., unvalidated) sub-block requiring
1121 * explicit close-out, postpone switching the current block from
1122 * head to body until the rew_sub() call closing out that
1123 * sub-block.
1124 */
1125 for (n = m->last; n && n != head; n = n->parent) {
1126 if (MDOC_BLOCK == n->type &&
1127 MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1128 ! (MDOC_VALID & n->flags)) {
1129 assert( ! (MDOC_ACTED & n->flags));
1130 n->pending = head;
1131 return(1);
1132 }
1133 }
1134
1135 /* Close out scopes to remain in a consistent state. */
1136
1137 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1138 return(0);
1139 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1140 return(0);
1141
1142 out:
1143 if ( ! (MDOC_FREECOL & m->flags))
1144 return(1);
1145
1146 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
1147 return(0);
1148 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
1149 return(0);
1150
1151 m->flags &= ~MDOC_FREECOL;
1152 return(1);
1153 }
1154
1155
1156 static int
1157 blk_part_imp(MACRO_PROT_ARGS)
1158 {
1159 int la, nl;
1160 enum mdoct ntok;
1161 enum margserr ac;
1162 char *p;
1163 struct mdoc_node *blk; /* saved block context */
1164 struct mdoc_node *body; /* saved body context */
1165 struct mdoc_node *n;
1166
1167 nl = MDOC_NEWLINE & m->flags;
1168
1169 /*
1170 * A macro that spans to the end of the line. This is generally
1171 * (but not necessarily) called as the first macro. The block
1172 * has a head as the immediate child, which is always empty,
1173 * followed by zero or more opening punctuation nodes, then the
1174 * body (which may be empty, depending on the macro), then zero
1175 * or more closing punctuation nodes.
1176 */
1177
1178 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1179 return(0);
1180
1181 blk = m->last;
1182
1183 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1184 return(0);
1185 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1186 return(0);
1187
1188 /*
1189 * Open the body scope "on-demand", that is, after we've
1190 * processed all our the leading delimiters (open parenthesis,
1191 * etc.).
1192 */
1193
1194 for (body = NULL; ; ) {
1195 la = *pos;
1196 ac = mdoc_args(m, line, pos, buf, tok, &p);
1197
1198 if (ARGS_ERROR == ac)
1199 return(0);
1200 if (ARGS_EOLN == ac)
1201 break;
1202 if (ARGS_PUNCT == ac)
1203 break;
1204
1205 if (NULL == body && ARGS_QWORD != ac &&
1206 DELIM_OPEN == mdoc_isdelim(p)) {
1207 if ( ! mdoc_word_alloc(m, line, la, p))
1208 return(0);
1209 continue;
1210 }
1211
1212 if (NULL == body) {
1213 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1214 return(0);
1215 body = m->last;
1216 }
1217
1218 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1219
1220 if (MDOC_MAX == ntok) {
1221 if ( ! mdoc_word_alloc(m, line, la, p))
1222 return(0);
1223 continue;
1224 }
1225
1226 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1227 return(0);
1228 break;
1229 }
1230
1231 /* Clean-ups to leave in a consistent state. */
1232
1233 if (NULL == body) {
1234 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1235 return(0);
1236 body = m->last;
1237 }
1238
1239 for (n = body->child; n && n->next; n = n->next)
1240 /* Do nothing. */ ;
1241
1242 /*
1243 * End of sentence spacing: if the last node is a text node and
1244 * has a trailing period, then mark it as being end-of-sentence.
1245 */
1246
1247 if (n && MDOC_TEXT == n->type && n->string)
1248 if (mandoc_eos(n->string, strlen(n->string)))
1249 n->flags |= MDOC_EOS;
1250
1251 /* Up-propogate the end-of-space flag. */
1252
1253 if (n && (MDOC_EOS & n->flags)) {
1254 body->flags |= MDOC_EOS;
1255 body->parent->flags |= MDOC_EOS;
1256 }
1257
1258 /*
1259 * If we can't rewind to our body, then our scope has already
1260 * been closed by another macro (like `Oc' closing `Op'). This
1261 * is ugly behaviour nodding its head to OpenBSD's overwhelming
1262 * crufty use of `Op' breakage.
1263 *
1264 * FIXME - this should be ifdef'd OpenBSD?
1265 */
1266 for (n = m->last; n; n = n->parent)
1267 if (body == n)
1268 break;
1269
1270 if (NULL == n && ! mdoc_nmsg(m, body, MANDOCERR_SCOPE))
1271 return(0);
1272
1273 if (n && ! rew_last(m, body))
1274 return(0);
1275
1276 /* Standard appending of delimiters. */
1277
1278 if (nl && ! append_delims(m, line, pos, buf))
1279 return(0);
1280
1281 /* Rewind scope, if applicable. */
1282
1283 if (n && ! rew_last(m, blk))
1284 return(0);
1285
1286 return(1);
1287 }
1288
1289
1290 static int
1291 blk_part_exp(MACRO_PROT_ARGS)
1292 {
1293 int la, nl;
1294 enum margserr ac;
1295 struct mdoc_node *head; /* keep track of head */
1296 struct mdoc_node *body; /* keep track of body */
1297 char *p;
1298 enum mdoct ntok;
1299
1300 nl = MDOC_NEWLINE & m->flags;
1301
1302 /*
1303 * The opening of an explicit macro having zero or more leading
1304 * punctuation nodes; a head with optional single element (the
1305 * case of `Eo'); and a body that may be empty.
1306 */
1307
1308 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1309 return(0);
1310
1311 for (head = body = NULL; ; ) {
1312 la = *pos;
1313 ac = mdoc_args(m, line, pos, buf, tok, &p);
1314
1315 if (ARGS_ERROR == ac)
1316 return(0);
1317 if (ARGS_PUNCT == ac)
1318 break;
1319 if (ARGS_EOLN == ac)
1320 break;
1321
1322 /* Flush out leading punctuation. */
1323
1324 if (NULL == head && ARGS_QWORD != ac &&
1325 DELIM_OPEN == mdoc_isdelim(p)) {
1326 assert(NULL == body);
1327 if ( ! mdoc_word_alloc(m, line, la, p))
1328 return(0);
1329 continue;
1330 }
1331
1332 if (NULL == head) {
1333 assert(NULL == body);
1334 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1335 return(0);
1336 head = m->last;
1337 }
1338
1339 /*
1340 * `Eo' gobbles any data into the head, but most other
1341 * macros just immediately close out and begin the body.
1342 */
1343
1344 if (NULL == body) {
1345 assert(head);
1346 /* No check whether it's a macro! */
1347 if (MDOC_Eo == tok)
1348 if ( ! mdoc_word_alloc(m, line, la, p))
1349 return(0);
1350
1351 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1352 return(0);
1353 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1354 return(0);
1355 body = m->last;
1356
1357 if (MDOC_Eo == tok)
1358 continue;
1359 }
1360
1361 assert(NULL != head && NULL != body);
1362
1363 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1364
1365 if (MDOC_MAX == ntok) {
1366 if ( ! mdoc_word_alloc(m, line, la, p))
1367 return(0);
1368 continue;
1369 }
1370
1371 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1372 return(0);
1373 break;
1374 }
1375
1376 /* Clean-up to leave in a consistent state. */
1377
1378 if (NULL == head) {
1379 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1380 return(0);
1381 head = m->last;
1382 }
1383
1384 if (NULL == body) {
1385 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1386 return(0);
1387 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1388 return(0);
1389 body = m->last;
1390 }
1391
1392 /* Standard appending of delimiters. */
1393
1394 if ( ! nl)
1395 return(1);
1396 return(append_delims(m, line, pos, buf));
1397 }
1398
1399
1400 /* ARGSUSED */
1401 static int
1402 in_line_argn(MACRO_PROT_ARGS)
1403 {
1404 int la, flushed, j, maxargs, nl;
1405 enum margserr ac;
1406 enum margverr av;
1407 struct mdoc_arg *arg;
1408 char *p;
1409 enum mdoct ntok;
1410
1411 nl = MDOC_NEWLINE & m->flags;
1412
1413 /*
1414 * A line macro that has a fixed number of arguments (maxargs).
1415 * Only open the scope once the first non-leading-punctuation is
1416 * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then
1417 * keep it open until the maximum number of arguments are
1418 * exhausted.
1419 */
1420
1421 switch (tok) {
1422 case (MDOC_Ap):
1423 /* FALLTHROUGH */
1424 case (MDOC_No):
1425 /* FALLTHROUGH */
1426 case (MDOC_Ns):
1427 /* FALLTHROUGH */
1428 case (MDOC_Ux):
1429 maxargs = 0;
1430 break;
1431 case (MDOC_Xr):
1432 maxargs = 2;
1433 break;
1434 default:
1435 maxargs = 1;
1436 break;
1437 }
1438
1439 for (arg = NULL; ; ) {
1440 la = *pos;
1441 av = mdoc_argv(m, line, tok, &arg, pos, buf);
1442
1443 if (ARGV_WORD == av) {
1444 *pos = la;
1445 break;
1446 }
1447
1448 if (ARGV_EOLN == av)
1449 break;
1450 if (ARGV_ARG == av)
1451 continue;
1452
1453 mdoc_argv_free(arg);
1454 return(0);
1455 }
1456
1457 for (flushed = j = 0; ; ) {
1458 la = *pos;
1459 ac = mdoc_args(m, line, pos, buf, tok, &p);
1460
1461 if (ARGS_ERROR == ac)
1462 return(0);
1463 if (ARGS_PUNCT == ac)
1464 break;
1465 if (ARGS_EOLN == ac)
1466 break;
1467
1468 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1469 ARGS_QWORD != ac &&
1470 0 == j && DELIM_OPEN == mdoc_isdelim(p)) {
1471 if ( ! mdoc_word_alloc(m, line, la, p))
1472 return(0);
1473 continue;
1474 } else if (0 == j)
1475 if ( ! mdoc_elem_alloc(m, line, la, tok, arg))
1476 return(0);
1477
1478 if (j == maxargs && ! flushed) {
1479 if ( ! rew_elem(m, tok))
1480 return(0);
1481 flushed = 1;
1482 }
1483
1484 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1485
1486 if (MDOC_MAX != ntok) {
1487 if ( ! flushed && ! rew_elem(m, tok))
1488 return(0);
1489 flushed = 1;
1490 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1491 return(0);
1492 j++;
1493 break;
1494 }
1495
1496 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1497 ARGS_QWORD != ac &&
1498 ! flushed &&
1499 DELIM_NONE != mdoc_isdelim(p)) {
1500 if ( ! rew_elem(m, tok))
1501 return(0);
1502 flushed = 1;
1503 }
1504
1505 /*
1506 * XXX: this is a hack to work around groff's ugliness
1507 * as regards `Xr' and extraneous arguments. It should
1508 * ideally be deprecated behaviour, but because this is
1509 * code is no here, it's unlikely to be removed.
1510 */
1511
1512 #ifdef __OpenBSD__
1513 if (MDOC_Xr == tok && j == maxargs) {
1514 if ( ! mdoc_elem_alloc(m, line, la, MDOC_Ns, NULL))
1515 return(0);
1516 if ( ! rew_elem(m, MDOC_Ns))
1517 return(0);
1518 }
1519 #endif
1520
1521 if ( ! mdoc_word_alloc(m, line, la, p))
1522 return(0);
1523 j++;
1524 }
1525
1526 if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg))
1527 return(0);
1528
1529 /* Close out in a consistent state. */
1530
1531 if ( ! flushed && ! rew_elem(m, tok))
1532 return(0);
1533 if ( ! nl)
1534 return(1);
1535 return(append_delims(m, line, pos, buf));
1536 }
1537
1538
1539 static int
1540 in_line_eoln(MACRO_PROT_ARGS)
1541 {
1542 int la;
1543 enum margserr ac;
1544 enum margverr av;
1545 struct mdoc_arg *arg;
1546 char *p;
1547 enum mdoct ntok;
1548
1549 assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1550
1551 /* Parse macro arguments. */
1552
1553 for (arg = NULL; ; ) {
1554 la = *pos;
1555 av = mdoc_argv(m, line, tok, &arg, pos, buf);
1556
1557 if (ARGV_WORD == av) {
1558 *pos = la;
1559 break;
1560 }
1561 if (ARGV_EOLN == av)
1562 break;
1563 if (ARGV_ARG == av)
1564 continue;
1565
1566 mdoc_argv_free(arg);
1567 return(0);
1568 }
1569
1570 /* Open element scope. */
1571
1572 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1573 return(0);
1574
1575 /* Parse argument terms. */
1576
1577 for (;;) {
1578 la = *pos;
1579 ac = mdoc_args(m, line, pos, buf, tok, &p);
1580
1581 if (ARGS_ERROR == ac)
1582 return(0);
1583 if (ARGS_EOLN == ac)
1584 break;
1585
1586 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1587
1588 if (MDOC_MAX == ntok) {
1589 if ( ! mdoc_word_alloc(m, line, la, p))
1590 return(0);
1591 continue;
1592 }
1593
1594 if ( ! rew_elem(m, tok))
1595 return(0);
1596 return(mdoc_macro(m, ntok, line, la, pos, buf));
1597 }
1598
1599 /* Close out (no delimiters). */
1600
1601 return(rew_elem(m, tok));
1602 }
1603
1604
1605 /* ARGSUSED */
1606 static int
1607 ctx_synopsis(MACRO_PROT_ARGS)
1608 {
1609 int nl;
1610
1611 nl = MDOC_NEWLINE & m->flags;
1612
1613 /* If we're not in the SYNOPSIS, go straight to in-line. */
1614 if (SEC_SYNOPSIS != m->lastsec)
1615 return(in_line(m, tok, line, ppos, pos, buf));
1616
1617 /* If we're a nested call, same place. */
1618 if ( ! nl)
1619 return(in_line(m, tok, line, ppos, pos, buf));
1620
1621 /*
1622 * XXX: this will open a block scope; however, if later we end
1623 * up formatting the block scope, then child nodes will inherit
1624 * the formatting. Be careful.
1625 */
1626
1627 return(blk_part_imp(m, tok, line, ppos, pos, buf));
1628 }
1629
1630
1631 /* ARGSUSED */
1632 static int
1633 obsolete(MACRO_PROT_ARGS)
1634 {
1635
1636 return(mdoc_pmsg(m, line, ppos, MANDOCERR_MACROOBS));
1637 }
1638
1639
1640 /*
1641 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1642 * They're unusual because they're basically free-form text until a
1643 * macro is encountered.
1644 */
1645 static int
1646 phrase(struct mdoc *m, int line, int ppos, char *buf)
1647 {
1648 int la, pos;
1649 enum margserr ac;
1650 enum mdoct ntok;
1651 char *p;
1652
1653 for (pos = ppos; ; ) {
1654 la = pos;
1655
1656 ac = mdoc_zargs(m, line, &pos, buf, 0, &p);
1657
1658 if (ARGS_ERROR == ac)
1659 return(0);
1660 if (ARGS_EOLN == ac)
1661 break;
1662
1663 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
1664
1665 if (MDOC_MAX == ntok) {
1666 if ( ! mdoc_word_alloc(m, line, la, p))
1667 return(0);
1668 continue;
1669 }
1670
1671 if ( ! mdoc_macro(m, ntok, line, la, &pos, buf))
1672 return(0);
1673 return(append_delims(m, line, &pos, buf));
1674 }
1675
1676 return(1);
1677 }
1678
1679
1680 /* ARGSUSED */
1681 static int
1682 phrase_ta(MACRO_PROT_ARGS)
1683 {
1684 int la;
1685 enum mdoct ntok;
1686 enum margserr ac;
1687 char *p;
1688
1689 /*
1690 * FIXME: this is overly restrictive: if the `Ta' is unexpected,
1691 * it should simply error out with ARGSLOST.
1692 */
1693
1694 if ( ! rew_sub(MDOC_BODY, m, MDOC_It, line, ppos))
1695 return(0);
1696 if ( ! mdoc_body_alloc(m, line, ppos, MDOC_It))
1697 return(0);
1698
1699 for (;;) {
1700 la = *pos;
1701 ac = mdoc_zargs(m, line, pos, buf, 0, &p);
1702
1703 if (ARGS_ERROR == ac)
1704 return(0);
1705 if (ARGS_EOLN == ac)
1706 break;
1707
1708 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
1709
1710 if (MDOC_MAX == ntok) {
1711 if ( ! mdoc_word_alloc(m, line, la, p))
1712 return(0);
1713 continue;
1714 }
1715
1716 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1717 return(0);
1718 return(append_delims(m, line, pos, buf));
1719 }
1720
1721 return(1);
1722 }