]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_macro.c
Get rid of all calls to rew_sub() in blk_exp_close(); only ten calls
[mandoc.git] / mdoc_macro.c
1 /* $Id: mdoc_macro.c,v 1.166 2015/02/02 04:26:44 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #include "config.h"
19
20 #include <sys/types.h>
21
22 #include <assert.h>
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <time.h>
28
29 #include "mdoc.h"
30 #include "mandoc.h"
31 #include "libmdoc.h"
32 #include "libmandoc.h"
33
34 enum rew { /* see rew_dohalt() */
35 REWIND_NONE,
36 REWIND_THIS,
37 REWIND_MORE,
38 REWIND_FORCE,
39 REWIND_LATER,
40 REWIND_ERROR
41 };
42
43 static void blk_full(MACRO_PROT_ARGS);
44 static void blk_exp_close(MACRO_PROT_ARGS);
45 static void blk_part_exp(MACRO_PROT_ARGS);
46 static void blk_part_imp(MACRO_PROT_ARGS);
47 static void ctx_synopsis(MACRO_PROT_ARGS);
48 static void in_line_eoln(MACRO_PROT_ARGS);
49 static void in_line_argn(MACRO_PROT_ARGS);
50 static void in_line(MACRO_PROT_ARGS);
51 static void phrase_ta(MACRO_PROT_ARGS);
52
53 static void dword(struct mdoc *, int, int, const char *,
54 enum mdelim, int);
55 static void append_delims(struct mdoc *, int, int *, char *);
56 static enum mdoct lookup(struct mdoc *, enum mdoct,
57 int, int, const char *);
58 static int macro_or_word(MACRO_PROT_ARGS, int);
59 static int make_pending(struct mdoc_node *, enum mdoct,
60 struct mdoc *, int, int);
61 static int parse_rest(struct mdoc *, enum mdoct,
62 int, int *, char *);
63 static enum mdoct rew_alt(enum mdoct);
64 static enum rew rew_dohalt(enum mdoct, enum mdoc_type,
65 const struct mdoc_node *);
66 static void rew_elem(struct mdoc *, enum mdoct);
67 static void rew_last(struct mdoc *, const struct mdoc_node *);
68 static void rew_pending(struct mdoc *, const struct mdoc_node *);
69 static void rew_sub(enum mdoc_type, struct mdoc *,
70 enum mdoct, int, int);
71
72 const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
73 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
74 { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
75 { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
76 { in_line_eoln, MDOC_PROLOGUE }, /* Os */
77 { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */
78 { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Ss */
79 { in_line_eoln, 0 }, /* Pp */
80 { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* D1 */
81 { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* Dl */
82 { blk_full, MDOC_EXPLICIT }, /* Bd */
83 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */
84 { blk_full, MDOC_EXPLICIT }, /* Bl */
85 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* El */
86 { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */
87 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
88 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */
89 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
90 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */
91 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
92 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
93 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
94 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
95 { in_line_eoln, 0 }, /* Ex */
96 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
97 { in_line_eoln, 0 }, /* Fd */
98 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
99 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
100 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
101 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ic */
102 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
103 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Li */
104 { blk_full, MDOC_JOIN }, /* Nd */
105 { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
106 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
107 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ot */
108 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
109 { in_line_eoln, 0 }, /* Rv */
110 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
111 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
112 { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
113 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
114 { in_line_eoln, MDOC_JOIN }, /* %A */
115 { in_line_eoln, MDOC_JOIN }, /* %B */
116 { in_line_eoln, MDOC_JOIN }, /* %D */
117 { in_line_eoln, MDOC_JOIN }, /* %I */
118 { in_line_eoln, MDOC_JOIN }, /* %J */
119 { in_line_eoln, 0 }, /* %N */
120 { in_line_eoln, MDOC_JOIN }, /* %O */
121 { in_line_eoln, 0 }, /* %P */
122 { in_line_eoln, MDOC_JOIN }, /* %R */
123 { in_line_eoln, MDOC_JOIN }, /* %T */
124 { in_line_eoln, 0 }, /* %V */
125 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
126 MDOC_EXPLICIT | MDOC_JOIN }, /* Ac */
127 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
128 MDOC_EXPLICIT | MDOC_JOIN }, /* Ao */
129 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Aq */
130 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
131 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
132 MDOC_EXPLICIT | MDOC_JOIN }, /* Bc */
133 { blk_full, MDOC_EXPLICIT }, /* Bf */
134 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
135 MDOC_EXPLICIT | MDOC_JOIN }, /* Bo */
136 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* 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_CALLABLE | MDOC_PARSED |
141 MDOC_EXPLICIT | MDOC_JOIN }, /* Dc */
142 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
143 MDOC_EXPLICIT | MDOC_JOIN }, /* Do */
144 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Dq */
145 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ec */
146 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ef */
147 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Em */
148 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
149 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
150 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
151 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* No */
152 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
153 MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */
154 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
155 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
156 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
157 MDOC_EXPLICIT | MDOC_JOIN }, /* Pc */
158 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
159 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
160 MDOC_EXPLICIT | MDOC_JOIN }, /* Po */
161 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Pq */
162 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
163 MDOC_EXPLICIT | MDOC_JOIN }, /* Qc */
164 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ql */
165 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
166 MDOC_EXPLICIT | MDOC_JOIN }, /* Qo */
167 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Qq */
168 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Re */
169 { blk_full, MDOC_EXPLICIT }, /* Rs */
170 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
171 MDOC_EXPLICIT | MDOC_JOIN }, /* Sc */
172 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
173 MDOC_EXPLICIT | MDOC_JOIN }, /* So */
174 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */
175 { in_line_argn, 0 }, /* Sm */
176 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */
177 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */
178 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
179 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ux */
180 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
181 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
182 { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
183 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
184 MDOC_EXPLICIT | MDOC_JOIN }, /* Fc */
185 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
186 MDOC_EXPLICIT | MDOC_JOIN }, /* Oo */
187 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
188 MDOC_EXPLICIT | MDOC_JOIN }, /* Oc */
189 { blk_full, MDOC_EXPLICIT }, /* Bk */
190 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ek */
191 { in_line_eoln, 0 }, /* Bt */
192 { in_line_eoln, 0 }, /* Hf */
193 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fr */
194 { in_line_eoln, 0 }, /* Ud */
195 { in_line, 0 }, /* Lb */
196 { in_line_eoln, 0 }, /* Lp */
197 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
198 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
199 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */
200 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
201 MDOC_EXPLICIT | MDOC_JOIN }, /* Bro */
202 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
203 MDOC_EXPLICIT | MDOC_JOIN }, /* Brc */
204 { in_line_eoln, MDOC_JOIN }, /* %C */
205 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Es */
206 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* En */
207 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
208 { in_line_eoln, MDOC_JOIN }, /* %Q */
209 { in_line_eoln, 0 }, /* br */
210 { in_line_eoln, 0 }, /* sp */
211 { in_line_eoln, 0 }, /* %U */
212 { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
213 { in_line_eoln, MDOC_PROLOGUE }, /* ll */
214 };
215
216 const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
217
218
219 /*
220 * This is called at the end of parsing. It must traverse up the tree,
221 * closing out open [implicit] scopes. Obviously, open explicit scopes
222 * are errors.
223 */
224 void
225 mdoc_macroend(struct mdoc *mdoc)
226 {
227 struct mdoc_node *n;
228
229 /* Scan for open explicit scopes. */
230
231 n = mdoc->last->flags & MDOC_VALID ?
232 mdoc->last->parent : mdoc->last;
233
234 for ( ; n; n = n->parent)
235 if (n->type == MDOC_BLOCK &&
236 mdoc_macros[n->tok].flags & MDOC_EXPLICIT)
237 mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,
238 n->line, n->pos, mdoc_macronames[n->tok]);
239
240 /* Rewind to the first. */
241
242 rew_last(mdoc, mdoc->first);
243 }
244
245 /*
246 * Look up the macro at *p called by "from",
247 * or as a line macro if from == MDOC_MAX.
248 */
249 static enum mdoct
250 lookup(struct mdoc *mdoc, enum mdoct from, int line, int ppos, const char *p)
251 {
252 enum mdoct res;
253
254 if (from == MDOC_MAX || mdoc_macros[from].flags & MDOC_PARSED) {
255 res = mdoc_hash_find(p);
256 if (res != MDOC_MAX) {
257 if (mdoc_macros[res].flags & MDOC_CALLABLE)
258 return(res);
259 if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll)
260 mandoc_msg(MANDOCERR_MACRO_CALL,
261 mdoc->parse, line, ppos, p);
262 }
263 }
264 return(MDOC_MAX);
265 }
266
267 /*
268 * Rewind up to and including a specific node.
269 */
270 static void
271 rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
272 {
273 struct mdoc_node *n, *np;
274
275 assert(to);
276 mdoc->next = MDOC_NEXT_SIBLING;
277 while (mdoc->last != to) {
278 if ( ! (mdoc->last->flags & MDOC_VALID))
279 mdoc->last->lastline = to->lastline -
280 (mdoc->flags & MDOC_NEWLINE ? 1 : 0);
281 /*
282 * Save the parent here, because we may delete the
283 * mdoc->last node in the post-validation phase and reset
284 * it to mdoc->last->parent, causing a step in the closing
285 * out to be lost.
286 */
287 np = mdoc->last->parent;
288 mdoc_valid_post(mdoc);
289 n = mdoc->last;
290 mdoc->last = np;
291 assert(mdoc->last);
292 mdoc->last->last = n;
293 }
294 mdoc_valid_post(mdoc);
295 }
296
297 /*
298 * Rewind up to a specific block, including all blocks that broke it.
299 */
300 static void
301 rew_pending(struct mdoc *mdoc, const struct mdoc_node *n)
302 {
303
304 rew_last(mdoc, n);
305
306 if (n->type != MDOC_BLOCK)
307 return;
308
309 while ((n = n->pending) != NULL) {
310 rew_last(mdoc, n);
311 if (n->type == MDOC_HEAD)
312 mdoc_body_alloc(mdoc, n->line, n->pos, n->tok);
313 }
314 }
315
316 /*
317 * For a block closing macro, return the corresponding opening one.
318 * Otherwise, return the macro itself.
319 */
320 static enum mdoct
321 rew_alt(enum mdoct tok)
322 {
323 switch (tok) {
324 case MDOC_Ac:
325 return(MDOC_Ao);
326 case MDOC_Bc:
327 return(MDOC_Bo);
328 case MDOC_Brc:
329 return(MDOC_Bro);
330 case MDOC_Dc:
331 return(MDOC_Do);
332 case MDOC_Ec:
333 return(MDOC_Eo);
334 case MDOC_Ed:
335 return(MDOC_Bd);
336 case MDOC_Ef:
337 return(MDOC_Bf);
338 case MDOC_Ek:
339 return(MDOC_Bk);
340 case MDOC_El:
341 return(MDOC_Bl);
342 case MDOC_Fc:
343 return(MDOC_Fo);
344 case MDOC_Oc:
345 return(MDOC_Oo);
346 case MDOC_Pc:
347 return(MDOC_Po);
348 case MDOC_Qc:
349 return(MDOC_Qo);
350 case MDOC_Re:
351 return(MDOC_Rs);
352 case MDOC_Sc:
353 return(MDOC_So);
354 case MDOC_Xc:
355 return(MDOC_Xo);
356 default:
357 return(tok);
358 }
359 /* NOTREACHED */
360 }
361
362 /*
363 * Rewinding to tok, how do we have to handle *p?
364 * REWIND_NONE: *p would delimit tok, but no tok scope is open
365 * inside *p, so there is no need to rewind anything at all.
366 * REWIND_THIS: *p matches tok, so rewind *p and nothing else.
367 * REWIND_MORE: *p is implicit, rewind it and keep searching for tok.
368 * REWIND_FORCE: *p is explicit, but tok is full, force rewinding *p.
369 * REWIND_LATER: *p is explicit and still open, postpone rewinding.
370 * REWIND_ERROR: No tok block is open at all.
371 */
372 static enum rew
373 rew_dohalt(enum mdoct tok, enum mdoc_type type,
374 const struct mdoc_node *p)
375 {
376
377 /*
378 * No matching token, no delimiting block, no broken block.
379 * This can happen when full implicit macros are called for
380 * the first time but try to rewind their previous
381 * instance anyway.
382 */
383 if (MDOC_ROOT == p->type)
384 return(MDOC_BLOCK == type &&
385 MDOC_EXPLICIT & mdoc_macros[tok].flags ?
386 REWIND_ERROR : REWIND_NONE);
387
388 /*
389 * When starting to rewind, skip plain text
390 * and nodes that have already been rewound.
391 */
392 if (p->type == MDOC_TEXT || p->flags & (MDOC_VALID | MDOC_BREAK))
393 return(REWIND_MORE);
394
395 /*
396 * The easiest case: Found a matching token.
397 * This applies to both blocks and elements.
398 */
399 tok = rew_alt(tok);
400 if (tok == p->tok)
401 return(p->end ? REWIND_NONE :
402 type == p->type ? REWIND_THIS : REWIND_MORE);
403
404 /*
405 * While elements do require rewinding for themselves,
406 * they never affect rewinding of other nodes.
407 */
408 if (MDOC_ELEM == p->type)
409 return(REWIND_MORE);
410
411 /*
412 * Blocks delimited by our target token get REWIND_MORE.
413 * Blocks delimiting our target token get REWIND_NONE.
414 */
415 switch (tok) {
416 case MDOC_Bl:
417 if (MDOC_It == p->tok)
418 return(REWIND_MORE);
419 break;
420 case MDOC_It:
421 if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
422 return(REWIND_NONE);
423 break;
424 /*
425 * XXX Badly nested block handling still fails badly
426 * when one block is breaking two blocks of the same type.
427 * This is an incomplete and extremely ugly workaround,
428 * required to let the OpenBSD tree build.
429 */
430 case MDOC_Oo:
431 if (MDOC_Op == p->tok)
432 return(REWIND_MORE);
433 break;
434 case MDOC_Nm:
435 return(REWIND_NONE);
436 case MDOC_Nd:
437 /* FALLTHROUGH */
438 case MDOC_Ss:
439 if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
440 return(REWIND_NONE);
441 /* FALLTHROUGH */
442 case MDOC_Sh:
443 if (MDOC_ROOT == p->parent->type)
444 return(REWIND_THIS);
445 if (MDOC_Nd == p->tok || MDOC_Ss == p->tok ||
446 MDOC_Sh == p->tok)
447 return(REWIND_MORE);
448 break;
449 default:
450 break;
451 }
452
453 /*
454 * Default block rewinding rules.
455 * In particular, always skip block end markers,
456 * and let all blocks rewind Nm children.
457 * Do not warn again when closing a block,
458 * since closing the body already warned.
459 */
460 if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok ||
461 MDOC_BLOCK == type || (MDOC_BLOCK == p->type &&
462 ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)))
463 return(REWIND_MORE);
464
465 /*
466 * By default, closing out full blocks
467 * forces closing of broken explicit blocks,
468 * while closing out partial blocks
469 * allows delayed rewinding by default.
470 */
471 return (&blk_full == mdoc_macros[tok].fp ?
472 REWIND_FORCE : REWIND_LATER);
473 }
474
475 static void
476 rew_elem(struct mdoc *mdoc, enum mdoct tok)
477 {
478 struct mdoc_node *n;
479
480 n = mdoc->last;
481 if (MDOC_ELEM != n->type)
482 n = n->parent;
483 assert(MDOC_ELEM == n->type);
484 assert(tok == n->tok);
485 rew_last(mdoc, n);
486 }
487
488 /*
489 * We are trying to close a block identified by tok,
490 * but the child block *broken is still open.
491 * Thus, postpone closing the tok block
492 * until the rew_sub call closing *broken.
493 */
494 static int
495 make_pending(struct mdoc_node *broken, enum mdoct tok,
496 struct mdoc *mdoc, int line, int ppos)
497 {
498 struct mdoc_node *breaker;
499
500 /*
501 * Iterate backwards, searching for the block matching tok,
502 * that is, the block breaking the *broken block.
503 */
504 for (breaker = broken->parent; breaker; breaker = breaker->parent) {
505
506 /*
507 * If the *broken block (Z) is already broken and we
508 * encounter its breaker (B), make the tok block (A)
509 * pending on that inner breaker (B).
510 * Graphically, [A breaker=[B! broken=[Z->B B] tok=A] Z]
511 * becomes breaker=[A broken=[B! [Z->B B] tok=A] Z]
512 * and finally [A! [B!->A [Z->B B] A] Z].
513 * In these graphics, "->" indicates the "pending"
514 * pointer and "!" indicates the MDOC_BREAK flag.
515 * Each of the cases gets one additional pointer (B->A)
516 * and one additional flag (A!).
517 */
518 if (breaker == broken->pending) {
519 broken = breaker;
520 continue;
521 }
522
523 if (REWIND_THIS != rew_dohalt(tok, MDOC_BLOCK, breaker))
524 continue;
525 if (MDOC_BODY == broken->type)
526 broken = broken->parent;
527
528 /*
529 * Found the breaker.
530 * If another, outer breaker (X) is already pending on
531 * the *broken block (B), we must not clobber the link
532 * to the outer breaker, but make it pending on the
533 * new, now inner breaker (A).
534 * Graphically, [X! breaker=[A broken=[B->X X] tok=A] B]
535 * becomes [X! breaker=[A->X broken=[B X] tok=A] B]
536 * and finally [X! [A!->X [B->A X] A] B].
537 */
538 if (broken->pending) {
539 struct mdoc_node *taker;
540
541 /*
542 * If the inner breaker (A) is already broken,
543 * too, it cannot take on the outer breaker (X)
544 * but must hand it on to its own breakers (Y):
545 * [X! [Y! breaker=[A->Y Y] broken=[B->X X] tok=A] B]
546 * [X! take=[Y!->X brea=[A->Y Y] brok=[B X] tok=A] B]
547 * and finally [X! [Y!->X [A!->Y Y] [B->A X] A] B].
548 */
549 taker = breaker;
550 while (taker->pending)
551 taker = taker->pending;
552 taker->pending = broken->pending;
553 }
554
555 /*
556 * Now we have reduced the situation to the simplest
557 * case, which is just breaker=[A broken=[B tok=A] B]
558 * and becomes [A! [B->A A] B].
559 */
560 broken->pending = breaker;
561 breaker->flags |= MDOC_BREAK;
562 if (breaker->body != NULL)
563 breaker->body->flags |= MDOC_BREAK;
564 mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos,
565 "%s breaks %s", mdoc_macronames[tok],
566 mdoc_macronames[broken->tok]);
567 return(1);
568 }
569
570 /*
571 * Found no matching block for tok.
572 * Are you trying to close a block that is not open?
573 */
574 return(0);
575 }
576
577 static void
578 rew_sub(enum mdoc_type t, struct mdoc *mdoc,
579 enum mdoct tok, int line, int ppos)
580 {
581 struct mdoc_node *n, *to;
582
583 to = NULL;
584 n = mdoc->last;
585 while (n) {
586 switch (rew_dohalt(tok, t, n)) {
587 case REWIND_NONE:
588 if (to == NULL)
589 return;
590 n = to;
591 break;
592 case REWIND_THIS:
593 n->lastline = line -
594 (mdoc->flags & MDOC_NEWLINE &&
595 ! (mdoc_macros[tok].flags & MDOC_EXPLICIT));
596 break;
597 case REWIND_FORCE:
598 mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse,
599 line, ppos, "%s breaks %s",
600 mdoc_macronames[tok],
601 mdoc_macronames[n->tok]);
602 /* FALLTHROUGH */
603 case REWIND_MORE:
604 n->lastline = line -
605 (mdoc->flags & MDOC_NEWLINE ? 1 : 0);
606 to = n;
607 n = n->parent;
608 continue;
609 case REWIND_LATER:
610 if (make_pending(n, tok, mdoc, line, ppos) ||
611 t != MDOC_BLOCK)
612 return;
613 /* FALLTHROUGH */
614 case REWIND_ERROR:
615 mandoc_msg(MANDOCERR_BLK_NOTOPEN,
616 mdoc->parse, line, ppos,
617 mdoc_macronames[tok]);
618 return;
619 }
620 break;
621 }
622 assert(n);
623 rew_pending(mdoc, n);
624 }
625
626 /*
627 * Allocate a word and check whether it's punctuation or not.
628 * Punctuation consists of those tokens found in mdoc_isdelim().
629 */
630 static void
631 dword(struct mdoc *mdoc, int line, int col, const char *p,
632 enum mdelim d, int may_append)
633 {
634
635 if (d == DELIM_MAX)
636 d = mdoc_isdelim(p);
637
638 if (may_append &&
639 ! (mdoc->flags & (MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF)) &&
640 d == DELIM_NONE && mdoc->last->type == MDOC_TEXT &&
641 mdoc_isdelim(mdoc->last->string) == DELIM_NONE) {
642 mdoc_word_append(mdoc, p);
643 return;
644 }
645
646 mdoc_word_alloc(mdoc, line, col, p);
647
648 /*
649 * If the word consists of a bare delimiter,
650 * flag the new node accordingly,
651 * unless doing so was vetoed by the invoking macro.
652 * Always clear the veto, it is only valid for one word.
653 */
654
655 if (d == DELIM_OPEN)
656 mdoc->last->flags |= MDOC_DELIMO;
657 else if (d == DELIM_CLOSE &&
658 ! (mdoc->flags & MDOC_NODELIMC) &&
659 mdoc->last->parent->tok != MDOC_Fd)
660 mdoc->last->flags |= MDOC_DELIMC;
661 mdoc->flags &= ~MDOC_NODELIMC;
662 }
663
664 static void
665 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
666 {
667 char *p;
668 int la;
669
670 if (buf[*pos] == '\0')
671 return;
672
673 for (;;) {
674 la = *pos;
675 if (mdoc_args(mdoc, line, pos, buf, MDOC_MAX, &p) == ARGS_EOLN)
676 break;
677 dword(mdoc, line, la, p, DELIM_MAX, 1);
678
679 /*
680 * If we encounter end-of-sentence symbols, then trigger
681 * the double-space.
682 *
683 * XXX: it's easy to allow this to propagate outward to
684 * the last symbol, such that `. )' will cause the
685 * correct double-spacing. However, (1) groff isn't
686 * smart enough to do this and (2) it would require
687 * knowing which symbols break this behaviour, for
688 * example, `. ;' shouldn't propagate the double-space.
689 */
690
691 if (mandoc_eos(p, strlen(p)))
692 mdoc->last->flags |= MDOC_EOS;
693 }
694 }
695
696 /*
697 * Parse one word.
698 * If it is a macro, call it and return 1.
699 * Otherwise, allocate it and return 0.
700 */
701 static int
702 macro_or_word(MACRO_PROT_ARGS, int parsed)
703 {
704 char *p;
705 enum mdoct ntok;
706
707 p = buf + ppos;
708 ntok = MDOC_MAX;
709 if (*p == '"')
710 p++;
711 else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT))
712 ntok = lookup(mdoc, tok, line, ppos, p);
713
714 if (ntok == MDOC_MAX) {
715 dword(mdoc, line, ppos, p, DELIM_MAX, tok == MDOC_MAX ||
716 mdoc_macros[tok].flags & MDOC_JOIN);
717 return(0);
718 } else {
719 if (mdoc_macros[tok].fp == in_line_eoln)
720 rew_elem(mdoc, tok);
721 mdoc_macro(mdoc, ntok, line, ppos, pos, buf);
722 if (tok == MDOC_MAX)
723 append_delims(mdoc, line, pos, buf);
724 return(1);
725 }
726 }
727
728 /*
729 * Close out block partial/full explicit.
730 */
731 static void
732 blk_exp_close(MACRO_PROT_ARGS)
733 {
734 struct mdoc_node *body; /* Our own body. */
735 struct mdoc_node *endbody; /* Our own end marker. */
736 struct mdoc_node *later; /* A sub-block starting later. */
737 struct mdoc_node *n; /* Search back to our block. */
738
739 int have_it, j, lastarg, maxargs, nl;
740 enum margserr ac;
741 enum mdoct atok, ntok;
742 char *p;
743
744 nl = MDOC_NEWLINE & mdoc->flags;
745
746 switch (tok) {
747 case MDOC_Ec:
748 maxargs = 1;
749 break;
750 case MDOC_Ek:
751 mdoc->flags &= ~MDOC_KEEP;
752 /* FALLTHROUGH */
753 default:
754 maxargs = 0;
755 break;
756 }
757
758 /*
759 * Search backwards for beginnings of blocks,
760 * both of our own and of pending sub-blocks.
761 */
762
763 have_it = 0;
764 atok = rew_alt(tok);
765 body = endbody = later = NULL;
766 for (n = mdoc->last; n; n = n->parent) {
767 if (n->flags & (MDOC_VALID | MDOC_BREAK))
768 continue;
769
770 /* Remember the start of our own body. */
771
772 if (n->type == MDOC_BODY && atok == n->tok) {
773 if (n->end == ENDBODY_NOT) {
774 body = n;
775 n->lastline = line;
776 }
777 continue;
778 }
779
780 if (n->type != MDOC_BLOCK || n->tok == MDOC_Nm)
781 continue;
782
783 if (n->tok == MDOC_It) {
784 have_it = 1;
785 continue;
786 }
787
788 if (atok == n->tok) {
789 n->lastline = line;
790 assert(body);
791
792 /*
793 * Found the start of our own block.
794 * When there is no pending sub block,
795 * just proceed to closing out.
796 */
797
798 if (later == NULL ||
799 (tok == MDOC_El && !have_it))
800 break;
801
802 /*
803 * When there is a pending sub block,
804 * postpone closing out the current block
805 * until the rew_sub() closing out the sub-block.
806 */
807
808 make_pending(later, tok, mdoc, line, ppos);
809
810 /*
811 * Mark the place where the formatting - but not
812 * the scope - of the current block ends.
813 */
814
815 endbody = mdoc_endbody_alloc(mdoc, line, ppos,
816 atok, body, ENDBODY_SPACE);
817
818 /*
819 * If a block closing macro taking arguments
820 * breaks another block, put the arguments
821 * into the end marker.
822 */
823
824 if (maxargs)
825 mdoc->next = MDOC_NEXT_CHILD;
826 break;
827 }
828
829 /*
830 * When finding an open sub block, remember the last
831 * open explicit block, or, in case there are only
832 * implicit ones, the first open implicit block.
833 */
834
835 if (later == NULL ||
836 ! (mdoc_macros[later->tok].flags & MDOC_EXPLICIT))
837 later = n;
838 }
839
840 if (body == NULL) {
841 mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,
842 line, ppos, mdoc_macronames[tok]);
843 if (maxargs && endbody == NULL) {
844 /*
845 * Stray .Ec without previous .Eo:
846 * Break the output line, keep the arguments.
847 */
848 mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL);
849 rew_elem(mdoc, MDOC_br);
850 }
851 } else if (endbody == NULL) {
852 rew_last(mdoc, body);
853 if (maxargs)
854 mdoc_tail_alloc(mdoc, line, ppos, atok);
855 }
856
857 if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) {
858 if (buf[*pos] != '\0')
859 mandoc_vmsg(MANDOCERR_ARG_SKIP,
860 mdoc->parse, line, ppos,
861 "%s %s", mdoc_macronames[tok],
862 buf + *pos);
863 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
864 return;
865 }
866
867 if (endbody != NULL)
868 n = endbody;
869 for (j = 0; ; j++) {
870 lastarg = *pos;
871
872 if (j == maxargs && n != NULL) {
873 rew_pending(mdoc, n);
874 n = NULL;
875 }
876
877 ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
878 if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
879 break;
880
881 ntok = ac == ARGS_QWORD ? MDOC_MAX :
882 lookup(mdoc, tok, line, lastarg, p);
883
884 if (ntok == MDOC_MAX) {
885 dword(mdoc, line, lastarg, p, DELIM_MAX,
886 MDOC_JOIN & mdoc_macros[tok].flags);
887 continue;
888 }
889
890 if (n != NULL) {
891 rew_pending(mdoc, n);
892 n = NULL;
893 }
894 mdoc->flags &= ~MDOC_NEWLINE;
895 mdoc_macro(mdoc, ntok, line, lastarg, pos, buf);
896 break;
897 }
898
899 if (n != NULL)
900 rew_pending(mdoc, n);
901 if (nl)
902 append_delims(mdoc, line, pos, buf);
903 }
904
905 static void
906 in_line(MACRO_PROT_ARGS)
907 {
908 int la, scope, cnt, firstarg, mayopen, nc, nl;
909 enum mdoct ntok;
910 enum margserr ac;
911 enum mdelim d;
912 struct mdoc_arg *arg;
913 char *p;
914
915 nl = MDOC_NEWLINE & mdoc->flags;
916
917 /*
918 * Whether we allow ignored elements (those without content,
919 * usually because of reserved words) to squeak by.
920 */
921
922 switch (tok) {
923 case MDOC_An:
924 /* FALLTHROUGH */
925 case MDOC_Ar:
926 /* FALLTHROUGH */
927 case MDOC_Fl:
928 /* FALLTHROUGH */
929 case MDOC_Mt:
930 /* FALLTHROUGH */
931 case MDOC_Nm:
932 /* FALLTHROUGH */
933 case MDOC_Pa:
934 nc = 1;
935 break;
936 default:
937 nc = 0;
938 break;
939 }
940
941 mdoc_argv(mdoc, line, tok, &arg, pos, buf);
942
943 d = DELIM_NONE;
944 firstarg = 1;
945 mayopen = 1;
946 for (cnt = scope = 0;; ) {
947 la = *pos;
948 ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
949
950 /*
951 * At the end of a macro line,
952 * opening delimiters do not suppress spacing.
953 */
954
955 if (ac == ARGS_EOLN) {
956 if (d == DELIM_OPEN)
957 mdoc->last->flags &= ~MDOC_DELIMO;
958 break;
959 }
960
961 /*
962 * The rest of the macro line is only punctuation,
963 * to be handled by append_delims().
964 * If there were no other arguments,
965 * do not allow the first one to suppress spacing,
966 * even if it turns out to be a closing one.
967 */
968
969 if (ac == ARGS_PUNCT) {
970 if (cnt == 0 && nc == 0)
971 mdoc->flags |= MDOC_NODELIMC;
972 break;
973 }
974
975 ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ?
976 MDOC_MAX : lookup(mdoc, tok, line, la, p);
977
978 /*
979 * In this case, we've located a submacro and must
980 * execute it. Close out scope, if open. If no
981 * elements have been generated, either create one (nc)
982 * or raise a warning.
983 */
984
985 if (ntok != MDOC_MAX) {
986 if (scope)
987 rew_elem(mdoc, tok);
988 if (nc && ! cnt) {
989 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
990 rew_last(mdoc, mdoc->last);
991 } else if ( ! nc && ! cnt) {
992 mdoc_argv_free(arg);
993 mandoc_msg(MANDOCERR_MACRO_EMPTY,
994 mdoc->parse, line, ppos,
995 mdoc_macronames[tok]);
996 }
997 mdoc_macro(mdoc, ntok, line, la, pos, buf);
998 if (nl)
999 append_delims(mdoc, line, pos, buf);
1000 return;
1001 }
1002
1003 /*
1004 * Non-quote-enclosed punctuation. Set up our scope, if
1005 * a word; rewind the scope, if a delimiter; then append
1006 * the word.
1007 */
1008
1009 d = ac == ARGS_QWORD ? DELIM_NONE : mdoc_isdelim(p);
1010
1011 if (DELIM_NONE != d) {
1012 /*
1013 * If we encounter closing punctuation, no word
1014 * has been emitted, no scope is open, and we're
1015 * allowed to have an empty element, then start
1016 * a new scope.
1017 */
1018 if ((d == DELIM_CLOSE ||
1019 (d == DELIM_MIDDLE && tok == MDOC_Fl)) &&
1020 !cnt && !scope && nc && mayopen) {
1021 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1022 scope = 1;
1023 cnt++;
1024 if (tok == MDOC_Nm)
1025 mayopen = 0;
1026 }
1027 /*
1028 * Close out our scope, if one is open, before
1029 * any punctuation.
1030 */
1031 if (scope)
1032 rew_elem(mdoc, tok);
1033 scope = 0;
1034 if (tok == MDOC_Fn)
1035 mayopen = 0;
1036 } else if (mayopen && !scope) {
1037 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1038 scope = 1;
1039 cnt++;
1040 }
1041
1042 dword(mdoc, line, la, p, d,
1043 MDOC_JOIN & mdoc_macros[tok].flags);
1044
1045 /*
1046 * If the first argument is a closing delimiter,
1047 * do not suppress spacing before it.
1048 */
1049
1050 if (firstarg && d == DELIM_CLOSE && !nc)
1051 mdoc->last->flags &= ~MDOC_DELIMC;
1052 firstarg = 0;
1053
1054 /*
1055 * `Fl' macros have their scope re-opened with each new
1056 * word so that the `-' can be added to each one without
1057 * having to parse out spaces.
1058 */
1059 if (scope && tok == MDOC_Fl) {
1060 rew_elem(mdoc, tok);
1061 scope = 0;
1062 }
1063 }
1064
1065 if (scope)
1066 rew_elem(mdoc, tok);
1067
1068 /*
1069 * If no elements have been collected and we're allowed to have
1070 * empties (nc), open a scope and close it out. Otherwise,
1071 * raise a warning.
1072 */
1073
1074 if ( ! cnt) {
1075 if (nc) {
1076 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1077 rew_last(mdoc, mdoc->last);
1078 } else {
1079 mdoc_argv_free(arg);
1080 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
1081 line, ppos, mdoc_macronames[tok]);
1082 }
1083 }
1084 if (nl)
1085 append_delims(mdoc, line, pos, buf);
1086 }
1087
1088 static void
1089 blk_full(MACRO_PROT_ARGS)
1090 {
1091 int la, nl, parsed;
1092 struct mdoc_arg *arg;
1093 struct mdoc_node *blk; /* Our own block. */
1094 struct mdoc_node *head; /* Our own head. */
1095 struct mdoc_node *body; /* Our own body. */
1096 struct mdoc_node *n;
1097 enum margserr ac, lac;
1098 char *p;
1099
1100 nl = MDOC_NEWLINE & mdoc->flags;
1101
1102 /* Skip items outside lists. */
1103
1104 if (tok == MDOC_It) {
1105 for (n = mdoc->last; n; n = n->parent)
1106 if (n->tok == MDOC_Bl && n->type == MDOC_BLOCK &&
1107 ! (n->flags & (MDOC_VALID | MDOC_BREAK)))
1108 break;
1109 if (n == NULL) {
1110 mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,
1111 line, ppos, "It %s", buf + *pos);
1112 mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL);
1113 rew_elem(mdoc, MDOC_br);
1114 return;
1115 }
1116 }
1117
1118 /* Close out prior implicit scope. */
1119
1120 if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) {
1121 rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
1122 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
1123 }
1124
1125 /*
1126 * This routine accommodates implicitly- and explicitly-scoped
1127 * macro openings. Implicit ones first close out prior scope
1128 * (seen above). Delay opening the head until necessary to
1129 * allow leading punctuation to print. Special consideration
1130 * for `It -column', which has phrase-part syntax instead of
1131 * regular child nodes.
1132 */
1133
1134 mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1135 blk = mdoc_block_alloc(mdoc, line, ppos, tok, arg);
1136 head = body = NULL;
1137
1138 /*
1139 * Exception: Heads of `It' macros in `-diag' lists are not
1140 * parsed, even though `It' macros in general are parsed.
1141 */
1142
1143 parsed = tok != MDOC_It ||
1144 mdoc->last->parent->tok != MDOC_Bl ||
1145 mdoc->last->parent->norm->Bl.type != LIST_diag;
1146
1147 /*
1148 * The `Nd' macro has all arguments in its body: it's a hybrid
1149 * of block partial-explicit and full-implicit. Stupid.
1150 */
1151
1152 if (tok == MDOC_Nd) {
1153 head = mdoc_head_alloc(mdoc, line, ppos, tok);
1154 rew_last(mdoc, head);
1155 body = mdoc_body_alloc(mdoc, line, ppos, tok);
1156 }
1157
1158 if (tok == MDOC_Bk)
1159 mdoc->flags |= MDOC_KEEP;
1160
1161 ac = ARGS_PEND;
1162 for (;;) {
1163 la = *pos;
1164 lac = ac;
1165 ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1166 if (ac == ARGS_PUNCT)
1167 break;
1168 if (ac == ARGS_EOLN) {
1169 if (lac != ARGS_PPHRASE && lac != ARGS_PHRASE)
1170 break;
1171 /*
1172 * This is necessary: if the last token on a
1173 * line is a `Ta' or tab, then we'll get
1174 * ARGS_EOLN, so we must be smart enough to
1175 * reopen our scope if the last parse was a
1176 * phrase or partial phrase.
1177 */
1178 rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
1179 body = mdoc_body_alloc(mdoc, line, ppos, tok);
1180 break;
1181 }
1182
1183 /*
1184 * Emit leading punctuation (i.e., punctuation before
1185 * the MDOC_HEAD) for non-phrase types.
1186 */
1187
1188 if (head == NULL &&
1189 ac != ARGS_PEND &&
1190 ac != ARGS_PHRASE &&
1191 ac != ARGS_PPHRASE &&
1192 ac != ARGS_QWORD &&
1193 mdoc_isdelim(p) == DELIM_OPEN) {
1194 dword(mdoc, line, la, p, DELIM_OPEN, 0);
1195 continue;
1196 }
1197
1198 /* Open a head if one hasn't been opened. */
1199
1200 if (head == NULL)
1201 head = mdoc_head_alloc(mdoc, line, ppos, tok);
1202
1203 if (ac == ARGS_PHRASE ||
1204 ac == ARGS_PEND ||
1205 ac == ARGS_PPHRASE) {
1206
1207 /*
1208 * If we haven't opened a body yet, rewind the
1209 * head; if we have, rewind that instead.
1210 */
1211
1212 rew_sub(body ? MDOC_BODY : MDOC_HEAD,
1213 mdoc, tok, line, ppos);
1214 body = mdoc_body_alloc(mdoc, line, ppos, tok);
1215
1216 /*
1217 * Process phrases: set whether we're in a
1218 * partial-phrase (this effects line handling)
1219 * then call down into the phrase parser.
1220 */
1221
1222 if (ac == ARGS_PPHRASE)
1223 mdoc->flags |= MDOC_PPHRASE;
1224 if (ac == ARGS_PEND && lac == ARGS_PPHRASE)
1225 mdoc->flags |= MDOC_PPHRASE;
1226 parse_rest(mdoc, MDOC_MAX, line, &la, buf);
1227 mdoc->flags &= ~MDOC_PPHRASE;
1228 continue;
1229 }
1230
1231 if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed))
1232 break;
1233 }
1234
1235 if (blk->flags & MDOC_VALID)
1236 return;
1237 if (head == NULL)
1238 head = mdoc_head_alloc(mdoc, line, ppos, tok);
1239 if (nl)
1240 append_delims(mdoc, line, pos, buf);
1241 if (body != NULL)
1242 goto out;
1243
1244 /*
1245 * If there is an open (i.e., unvalidated) sub-block requiring
1246 * explicit close-out, postpone switching the current block from
1247 * head to body until the rew_sub() call closing out that
1248 * sub-block.
1249 */
1250 for (n = mdoc->last; n && n != head; n = n->parent) {
1251 if (n->type == MDOC_BLOCK &&
1252 mdoc_macros[n->tok].flags & MDOC_EXPLICIT &&
1253 ! (n->flags & MDOC_VALID)) {
1254 n->pending = head;
1255 return;
1256 }
1257 }
1258
1259 /* Close out scopes to remain in a consistent state. */
1260
1261 rew_sub(MDOC_HEAD, mdoc, tok, line, ppos);
1262 mdoc_body_alloc(mdoc, line, ppos, tok);
1263 out:
1264 if (mdoc->flags & MDOC_FREECOL) {
1265 rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
1266 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
1267 mdoc->flags &= ~MDOC_FREECOL;
1268 }
1269 }
1270
1271 static void
1272 blk_part_imp(MACRO_PROT_ARGS)
1273 {
1274 int la, nl;
1275 enum margserr ac;
1276 char *p;
1277 struct mdoc_node *blk; /* saved block context */
1278 struct mdoc_node *body; /* saved body context */
1279 struct mdoc_node *n;
1280
1281 nl = MDOC_NEWLINE & mdoc->flags;
1282
1283 /*
1284 * A macro that spans to the end of the line. This is generally
1285 * (but not necessarily) called as the first macro. The block
1286 * has a head as the immediate child, which is always empty,
1287 * followed by zero or more opening punctuation nodes, then the
1288 * body (which may be empty, depending on the macro), then zero
1289 * or more closing punctuation nodes.
1290 */
1291
1292 blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL);
1293 rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok));
1294
1295 /*
1296 * Open the body scope "on-demand", that is, after we've
1297 * processed all our the leading delimiters (open parenthesis,
1298 * etc.).
1299 */
1300
1301 for (body = NULL; ; ) {
1302 la = *pos;
1303 ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1304 if (ac == ARGS_EOLN || ac == ARGS_PUNCT)
1305 break;
1306
1307 if (body == NULL && ac != ARGS_QWORD &&
1308 mdoc_isdelim(p) == DELIM_OPEN) {
1309 dword(mdoc, line, la, p, DELIM_OPEN, 0);
1310 continue;
1311 }
1312
1313 if (body == NULL)
1314 body = mdoc_body_alloc(mdoc, line, ppos, tok);
1315
1316 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
1317 break;
1318 }
1319 if (body == NULL)
1320 body = mdoc_body_alloc(mdoc, line, ppos, tok);
1321
1322 /*
1323 * If there is an open sub-block requiring explicit close-out,
1324 * postpone closing out the current block
1325 * until the rew_sub() call closing out the sub-block.
1326 */
1327
1328 for (n = mdoc->last; n && n != body && n != blk->parent;
1329 n = n->parent) {
1330 if (n->type == MDOC_BLOCK &&
1331 mdoc_macros[n->tok].flags & MDOC_EXPLICIT &&
1332 ! (n->flags & MDOC_VALID)) {
1333 make_pending(n, tok, mdoc, line, ppos);
1334 mdoc_endbody_alloc(mdoc, line, ppos,
1335 tok, body, ENDBODY_NOSPACE);
1336 return;
1337 }
1338 }
1339 assert(n == body);
1340 rew_last(mdoc, body);
1341 if (nl)
1342 append_delims(mdoc, line, pos, buf);
1343 rew_pending(mdoc, blk);
1344
1345 /* Move trailing .Ns out of scope. */
1346
1347 for (n = body->child; n && n->next; n = n->next)
1348 /* Do nothing. */ ;
1349 if (n && n->tok == MDOC_Ns)
1350 mdoc_node_relink(mdoc, n);
1351 }
1352
1353 static void
1354 blk_part_exp(MACRO_PROT_ARGS)
1355 {
1356 int la, nl;
1357 enum margserr ac;
1358 struct mdoc_node *head; /* keep track of head */
1359 char *p;
1360
1361 nl = MDOC_NEWLINE & mdoc->flags;
1362
1363 /*
1364 * The opening of an explicit macro having zero or more leading
1365 * punctuation nodes; a head with optional single element (the
1366 * case of `Eo'); and a body that may be empty.
1367 */
1368
1369 mdoc_block_alloc(mdoc, line, ppos, tok, NULL);
1370 head = NULL;
1371 for (;;) {
1372 la = *pos;
1373 ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1374 if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
1375 break;
1376
1377 /* Flush out leading punctuation. */
1378
1379 if (head == NULL && ac != ARGS_QWORD &&
1380 mdoc_isdelim(p) == DELIM_OPEN) {
1381 dword(mdoc, line, la, p, DELIM_OPEN, 0);
1382 continue;
1383 }
1384
1385 if (head == NULL) {
1386 head = mdoc_head_alloc(mdoc, line, ppos, tok);
1387 if (tok == MDOC_Eo) /* Not parsed. */
1388 dword(mdoc, line, la, p, DELIM_MAX, 0);
1389 rew_last(mdoc, head);
1390 mdoc_body_alloc(mdoc, line, ppos, tok);
1391 if (tok == MDOC_Eo)
1392 continue;
1393 }
1394
1395 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
1396 break;
1397 }
1398
1399 /* Clean-up to leave in a consistent state. */
1400
1401 if (head == NULL) {
1402 rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok));
1403 mdoc_body_alloc(mdoc, line, ppos, tok);
1404 }
1405 if (nl)
1406 append_delims(mdoc, line, pos, buf);
1407 }
1408
1409 static void
1410 in_line_argn(MACRO_PROT_ARGS)
1411 {
1412 int la, flushed, j, maxargs, nl;
1413 enum margserr ac;
1414 struct mdoc_arg *arg;
1415 char *p;
1416 enum mdoct ntok;
1417
1418 nl = mdoc->flags & MDOC_NEWLINE;
1419
1420 /*
1421 * A line macro that has a fixed number of arguments (maxargs).
1422 * Only open the scope once the first non-leading-punctuation is
1423 * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then
1424 * keep it open until the maximum number of arguments are
1425 * exhausted.
1426 */
1427
1428 switch (tok) {
1429 case MDOC_Ap:
1430 /* FALLTHROUGH */
1431 case MDOC_Ns:
1432 /* FALLTHROUGH */
1433 case MDOC_Ux:
1434 maxargs = 0;
1435 break;
1436 case MDOC_Bx:
1437 /* FALLTHROUGH */
1438 case MDOC_Es:
1439 /* FALLTHROUGH */
1440 case MDOC_Xr:
1441 maxargs = 2;
1442 break;
1443 default:
1444 maxargs = 1;
1445 break;
1446 }
1447
1448 mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1449
1450 p = NULL;
1451 flushed = j = 0;
1452 for (;;) {
1453 la = *pos;
1454 ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1455 if (ac == ARGS_PUNCT || ac == ARGS_EOLN) {
1456 if (j < 2 && tok == MDOC_Pf)
1457 mandoc_vmsg(MANDOCERR_PF_SKIP,
1458 mdoc->parse, line, ppos, "Pf %s",
1459 p == NULL ? "at eol" : p);
1460 break;
1461 }
1462
1463 if ( ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) &&
1464 ac != ARGS_QWORD && j == 0 &&
1465 mdoc_isdelim(p) == DELIM_OPEN) {
1466 dword(mdoc, line, la, p, DELIM_OPEN, 0);
1467 continue;
1468 } else if (j == 0)
1469 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1470
1471 if (j == maxargs && ! flushed) {
1472 rew_elem(mdoc, tok);
1473 flushed = 1;
1474 }
1475
1476 ntok = (ac == ARGS_QWORD || (tok == MDOC_Pf && j == 0)) ?
1477 MDOC_MAX : lookup(mdoc, tok, line, la, p);
1478
1479 if (ntok != MDOC_MAX) {
1480 if ( ! flushed)
1481 rew_elem(mdoc, tok);
1482 flushed = 1;
1483 mdoc_macro(mdoc, ntok, line, la, pos, buf);
1484 j++;
1485 break;
1486 }
1487
1488 if ( ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) &&
1489 ac != ARGS_QWORD && ! flushed &&
1490 mdoc_isdelim(p) != DELIM_NONE) {
1491 rew_elem(mdoc, tok);
1492 flushed = 1;
1493 }
1494
1495 dword(mdoc, line, la, p, DELIM_MAX,
1496 MDOC_JOIN & mdoc_macros[tok].flags);
1497 j++;
1498 }
1499
1500 if (j == 0) {
1501 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1502 if (ac == ARGS_PUNCT && tok == MDOC_Pf)
1503 append_delims(mdoc, line, pos, buf);
1504 }
1505 if ( ! flushed)
1506 rew_elem(mdoc, tok);
1507 if (nl)
1508 append_delims(mdoc, line, pos, buf);
1509 }
1510
1511 static void
1512 in_line_eoln(MACRO_PROT_ARGS)
1513 {
1514 struct mdoc_arg *arg;
1515
1516 if (tok == MDOC_Pp)
1517 rew_sub(MDOC_BLOCK, mdoc, MDOC_Nm, line, ppos);
1518
1519 mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1520 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1521 if (parse_rest(mdoc, tok, line, pos, buf))
1522 return;
1523 rew_elem(mdoc, tok);
1524 }
1525
1526 /*
1527 * The simplest argument parser available: Parse the remaining
1528 * words until the end of the phrase or line and return 0
1529 * or until the next macro, call that macro, and return 1.
1530 */
1531 static int
1532 parse_rest(struct mdoc *mdoc, enum mdoct tok, int line, int *pos, char *buf)
1533 {
1534 int la;
1535
1536 for (;;) {
1537 la = *pos;
1538 if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN)
1539 return(0);
1540 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
1541 return(1);
1542 }
1543 }
1544
1545 static void
1546 ctx_synopsis(MACRO_PROT_ARGS)
1547 {
1548
1549 if (~mdoc->flags & (MDOC_SYNOPSIS | MDOC_NEWLINE))
1550 in_line(mdoc, tok, line, ppos, pos, buf);
1551 else if (tok == MDOC_Nm)
1552 blk_full(mdoc, tok, line, ppos, pos, buf);
1553 else {
1554 assert(tok == MDOC_Vt);
1555 blk_part_imp(mdoc, tok, line, ppos, pos, buf);
1556 }
1557 }
1558
1559 /*
1560 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1561 * They're unusual because they're basically free-form text until a
1562 * macro is encountered.
1563 */
1564 static void
1565 phrase_ta(MACRO_PROT_ARGS)
1566 {
1567 struct mdoc_node *n;
1568
1569 /* Make sure we are in a column list or ignore this macro. */
1570
1571 n = mdoc->last;
1572 while (n != NULL &&
1573 (n->tok != MDOC_Bl || n->flags & (MDOC_VALID | MDOC_BREAK)))
1574 n = n->parent;
1575 if (n == NULL || n->norm->Bl.type != LIST_column) {
1576 mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse,
1577 line, ppos, "Ta");
1578 return;
1579 }
1580
1581 /* Advance to the next column. */
1582
1583 rew_sub(MDOC_BODY, mdoc, MDOC_It, line, ppos);
1584 mdoc_body_alloc(mdoc, line, ppos, MDOC_It);
1585 parse_rest(mdoc, MDOC_MAX, line, pos, buf);
1586 }