]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_macro.c
Fixed `Lb' to be in_line (reported by Ulrich Spoerlein).
[mandoc.git] / mdoc_macro.c
1 /* $Id: mdoc_macro.c,v 1.69 2010/05/26 09:35:35 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 #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
48 static int append_delims(struct mdoc *,
49 int, int *, char *);
50 static enum mdoct lookup(enum mdoct, const char *);
51 static enum mdoct lookup_raw(const char *);
52 static int phrase(struct mdoc *, int, int,
53 char *, enum margserr);
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 };
190
191 const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
192
193
194 static int
195 swarn(struct mdoc *mdoc, enum mdoc_type type,
196 int line, int pos, const struct mdoc_node *p)
197 {
198 const char *n, *t, *tt;
199 int rc;
200
201 n = t = "<root>";
202 tt = "block";
203
204 switch (type) {
205 case (MDOC_BODY):
206 tt = "multi-line";
207 break;
208 case (MDOC_HEAD):
209 tt = "line";
210 break;
211 default:
212 break;
213 }
214
215 switch (p->type) {
216 case (MDOC_BLOCK):
217 n = mdoc_macronames[p->tok];
218 t = "block";
219 break;
220 case (MDOC_BODY):
221 n = mdoc_macronames[p->tok];
222 t = "multi-line";
223 break;
224 case (MDOC_HEAD):
225 n = mdoc_macronames[p->tok];
226 t = "line";
227 break;
228 default:
229 break;
230 }
231
232 rc = mdoc_vmsg(mdoc, MANDOCERR_SCOPE, line, pos,
233 "%s scope breaks %s of %s", tt, t, n);
234
235 /* FIXME: logic should be in driver. */
236 return(MDOC_IGN_SCOPE & mdoc->pflags ? rc : 0);
237 }
238
239
240 /*
241 * This is called at the end of parsing. It must traverse up the tree,
242 * closing out open [implicit] scopes. Obviously, open explicit scopes
243 * are errors.
244 */
245 int
246 mdoc_macroend(struct mdoc *m)
247 {
248 struct mdoc_node *n;
249
250 /* Scan for open explicit scopes. */
251
252 n = MDOC_VALID & m->last->flags ? m->last->parent : m->last;
253
254 for ( ; n; n = n->parent) {
255 if (MDOC_BLOCK != n->type)
256 continue;
257 if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
258 continue;
259 mdoc_nmsg(m, n, MANDOCERR_SYNTSCOPE);
260 return(0);
261 }
262
263 /* Rewind to the first. */
264
265 return(rew_last(m, m->first));
266 }
267
268
269 /*
270 * Look up a macro from within a subsequent context.
271 */
272 static enum mdoct
273 lookup(enum mdoct from, const char *p)
274 {
275 /* FIXME: make -diag lists be un-PARSED. */
276
277 if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
278 return(MDOC_MAX);
279 return(lookup_raw(p));
280 }
281
282
283 /*
284 * Lookup a macro following the initial line macro.
285 */
286 static enum mdoct
287 lookup_raw(const char *p)
288 {
289 enum mdoct res;
290
291 if (MDOC_MAX == (res = mdoc_hash_find(p)))
292 return(MDOC_MAX);
293 if (MDOC_CALLABLE & mdoc_macros[res].flags)
294 return(res);
295 return(MDOC_MAX);
296 }
297
298
299 static int
300 rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
301 {
302
303 assert(to);
304 mdoc->next = MDOC_NEXT_SIBLING;
305
306 /* LINTED */
307 while (mdoc->last != to) {
308 if ( ! mdoc_valid_post(mdoc))
309 return(0);
310 if ( ! mdoc_action_post(mdoc))
311 return(0);
312 mdoc->last = mdoc->last->parent;
313 assert(mdoc->last);
314 }
315
316 if ( ! mdoc_valid_post(mdoc))
317 return(0);
318 return(mdoc_action_post(mdoc));
319 }
320
321
322 /*
323 * Return the opening macro of a closing one, e.g., `Ec' has `Eo' as its
324 * matching pair.
325 */
326 static enum mdoct
327 rew_alt(enum mdoct tok)
328 {
329 switch (tok) {
330 case (MDOC_Ac):
331 return(MDOC_Ao);
332 case (MDOC_Bc):
333 return(MDOC_Bo);
334 case (MDOC_Brc):
335 return(MDOC_Bro);
336 case (MDOC_Dc):
337 return(MDOC_Do);
338 case (MDOC_Ec):
339 return(MDOC_Eo);
340 case (MDOC_Ed):
341 return(MDOC_Bd);
342 case (MDOC_Ef):
343 return(MDOC_Bf);
344 case (MDOC_Ek):
345 return(MDOC_Bk);
346 case (MDOC_El):
347 return(MDOC_Bl);
348 case (MDOC_Fc):
349 return(MDOC_Fo);
350 case (MDOC_Oc):
351 return(MDOC_Oo);
352 case (MDOC_Pc):
353 return(MDOC_Po);
354 case (MDOC_Qc):
355 return(MDOC_Qo);
356 case (MDOC_Re):
357 return(MDOC_Rs);
358 case (MDOC_Sc):
359 return(MDOC_So);
360 case (MDOC_Xc):
361 return(MDOC_Xo);
362 default:
363 break;
364 }
365 abort();
366 /* NOTREACHED */
367 }
368
369
370 /*
371 * Rewind rules. This indicates whether to stop rewinding
372 * (REWIND_HALT) without touching our current scope, stop rewinding and
373 * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
374 * The scope-closing and so on occurs in the various rew_* routines.
375 */
376 static enum rew
377 rew_dohalt(enum mdoct tok, enum mdoc_type type,
378 const struct mdoc_node *p)
379 {
380
381 if (MDOC_ROOT == p->type)
382 return(REWIND_HALT);
383 if (MDOC_VALID & p->flags)
384 return(REWIND_NOHALT);
385
386 switch (tok) {
387 case (MDOC_Aq):
388 /* FALLTHROUGH */
389 case (MDOC_Bq):
390 /* FALLTHROUGH */
391 case (MDOC_Brq):
392 /* FALLTHROUGH */
393 case (MDOC_D1):
394 /* FALLTHROUGH */
395 case (MDOC_Dl):
396 /* FALLTHROUGH */
397 case (MDOC_Dq):
398 /* FALLTHROUGH */
399 case (MDOC_Op):
400 /* FALLTHROUGH */
401 case (MDOC_Pq):
402 /* FALLTHROUGH */
403 case (MDOC_Ql):
404 /* FALLTHROUGH */
405 case (MDOC_Qq):
406 /* FALLTHROUGH */
407 case (MDOC_Sq):
408 /* FALLTHROUGH */
409 case (MDOC_Vt):
410 assert(MDOC_TAIL != type);
411 if (type == p->type && tok == p->tok)
412 return(REWIND_REWIND);
413 break;
414 case (MDOC_It):
415 assert(MDOC_TAIL != type);
416 if (type == p->type && tok == p->tok)
417 return(REWIND_REWIND);
418 if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
419 return(REWIND_HALT);
420 break;
421 case (MDOC_Sh):
422 if (type == p->type && tok == p->tok)
423 return(REWIND_REWIND);
424 break;
425 case (MDOC_Nd):
426 /* FALLTHROUGH */
427 case (MDOC_Ss):
428 assert(MDOC_TAIL != type);
429 if (type == p->type && tok == p->tok)
430 return(REWIND_REWIND);
431 if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
432 return(REWIND_HALT);
433 break;
434 case (MDOC_Ao):
435 /* FALLTHROUGH */
436 case (MDOC_Bd):
437 /* FALLTHROUGH */
438 case (MDOC_Bf):
439 /* FALLTHROUGH */
440 case (MDOC_Bk):
441 /* FALLTHROUGH */
442 case (MDOC_Bl):
443 /* FALLTHROUGH */
444 case (MDOC_Bo):
445 /* FALLTHROUGH */
446 case (MDOC_Bro):
447 /* FALLTHROUGH */
448 case (MDOC_Do):
449 /* FALLTHROUGH */
450 case (MDOC_Eo):
451 /* FALLTHROUGH */
452 case (MDOC_Fo):
453 /* FALLTHROUGH */
454 case (MDOC_Oo):
455 /* FALLTHROUGH */
456 case (MDOC_Po):
457 /* FALLTHROUGH */
458 case (MDOC_Qo):
459 /* FALLTHROUGH */
460 case (MDOC_Rs):
461 /* FALLTHROUGH */
462 case (MDOC_So):
463 /* FALLTHROUGH */
464 case (MDOC_Xo):
465 if (type == p->type && tok == p->tok)
466 return(REWIND_REWIND);
467 break;
468 /* Multi-line explicit scope close. */
469 case (MDOC_Ac):
470 /* FALLTHROUGH */
471 case (MDOC_Bc):
472 /* FALLTHROUGH */
473 case (MDOC_Brc):
474 /* FALLTHROUGH */
475 case (MDOC_Dc):
476 /* FALLTHROUGH */
477 case (MDOC_Ec):
478 /* FALLTHROUGH */
479 case (MDOC_Ed):
480 /* FALLTHROUGH */
481 case (MDOC_Ek):
482 /* FALLTHROUGH */
483 case (MDOC_El):
484 /* FALLTHROUGH */
485 case (MDOC_Fc):
486 /* FALLTHROUGH */
487 case (MDOC_Ef):
488 /* FALLTHROUGH */
489 case (MDOC_Oc):
490 /* FALLTHROUGH */
491 case (MDOC_Pc):
492 /* FALLTHROUGH */
493 case (MDOC_Qc):
494 /* FALLTHROUGH */
495 case (MDOC_Re):
496 /* FALLTHROUGH */
497 case (MDOC_Sc):
498 /* FALLTHROUGH */
499 case (MDOC_Xc):
500 if (type == p->type && rew_alt(tok) == p->tok)
501 return(REWIND_REWIND);
502 break;
503 default:
504 abort();
505 /* NOTREACHED */
506 }
507
508 return(REWIND_NOHALT);
509 }
510
511
512 /*
513 * See if we can break an encountered scope (the rew_dohalt has returned
514 * REWIND_NOHALT).
515 */
516 static int
517 rew_dobreak(enum mdoct tok, const struct mdoc_node *p)
518 {
519
520 assert(MDOC_ROOT != p->type);
521 if (MDOC_ELEM == p->type)
522 return(1);
523 if (MDOC_TEXT == p->type)
524 return(1);
525 if (MDOC_VALID & p->flags)
526 return(1);
527
528 switch (tok) {
529 case (MDOC_It):
530 return(MDOC_It == p->tok);
531 case (MDOC_Nd):
532 return(MDOC_Nd == p->tok);
533 case (MDOC_Ss):
534 return(MDOC_Ss == p->tok);
535 case (MDOC_Sh):
536 if (MDOC_Nd == p->tok)
537 return(1);
538 if (MDOC_Ss == p->tok)
539 return(1);
540 return(MDOC_Sh == p->tok);
541 case (MDOC_El):
542 if (MDOC_It == p->tok)
543 return(1);
544 break;
545 case (MDOC_Oc):
546 if (MDOC_Op == p->tok)
547 return(1);
548 break;
549 default:
550 break;
551 }
552
553 if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
554 return(p->tok == rew_alt(tok));
555 else if (MDOC_BLOCK == p->type)
556 return(1);
557
558 return(tok == p->tok);
559 }
560
561
562 static int
563 rew_elem(struct mdoc *mdoc, enum mdoct tok)
564 {
565 struct mdoc_node *n;
566
567 n = mdoc->last;
568 if (MDOC_ELEM != n->type)
569 n = n->parent;
570 assert(MDOC_ELEM == n->type);
571 assert(tok == n->tok);
572
573 return(rew_last(mdoc, n));
574 }
575
576
577 static int
578 rew_sub(enum mdoc_type t, struct mdoc *m,
579 enum mdoct tok, int line, int ppos)
580 {
581 struct mdoc_node *n;
582 enum rew c;
583
584 /* LINTED */
585 for (n = m->last; n; n = n->parent) {
586 c = rew_dohalt(tok, t, n);
587 if (REWIND_HALT == c) {
588 if (MDOC_BLOCK != t)
589 return(1);
590 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))
591 return(1);
592 /* FIXME: shouldn't raise an error */
593 mdoc_pmsg(m, line, ppos, MANDOCERR_SYNTNOSCOPE);
594 return(0);
595 }
596 if (REWIND_REWIND == c)
597 break;
598 else if (rew_dobreak(tok, n))
599 continue;
600 if ( ! swarn(m, t, line, ppos, n))
601 return(0);
602 }
603
604 assert(n);
605 if ( ! rew_last(m, n))
606 return(0);
607
608 #ifdef UGLY
609 /*
610 * The current block extends an enclosing block beyond a line
611 * break. Now that the current block ends, close the enclosing
612 * block, too.
613 */
614 if (NULL != (n = n->pending)) {
615 assert(MDOC_HEAD == n->type);
616 if ( ! rew_last(m, n))
617 return(0);
618 if ( ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
619 return(0);
620 }
621 #endif
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, lastpunct, 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 = 0, lastpunct = 1;; ) {
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 (0 == lastpunct && ! 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 (ARGS_QWORD != ac && DELIM_NONE != d) {
857 if (0 == lastpunct && ! rew_elem(m, tok))
858 return(0);
859 lastpunct = 1;
860 } else if (lastpunct) {
861 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
862 return(0);
863 lastpunct = 0;
864 }
865
866 if (DELIM_NONE == d)
867 cnt++;
868 if ( ! mdoc_word_alloc(m, line, la, p))
869 return(0);
870
871 /*
872 * `Fl' macros have their scope re-opened with each new
873 * word so that the `-' can be added to each one without
874 * having to parse out spaces.
875 */
876 if (0 == lastpunct && MDOC_Fl == tok) {
877 if ( ! rew_elem(m, tok))
878 return(0);
879 lastpunct = 1;
880 }
881 }
882
883 if (0 == lastpunct && ! rew_elem(m, tok))
884 return(0);
885
886 /*
887 * If no elements have been collected and we're allowed to have
888 * empties (nc), open a scope and close it out. Otherwise,
889 * raise a warning.
890 */
891
892 if (nc && 0 == cnt) {
893 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
894 return(0);
895 if ( ! rew_last(m, m->last))
896 return(0);
897 } else if ( ! nc && 0 == cnt) {
898 mdoc_argv_free(arg);
899 if ( ! mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY))
900 return(0);
901 }
902
903 if ( ! nl)
904 return(1);
905 return(append_delims(m, line, pos, buf));
906 }
907
908
909 static int
910 blk_full(MACRO_PROT_ARGS)
911 {
912 int la, nl;
913 struct mdoc_arg *arg;
914 struct mdoc_node *head; /* save of head macro */
915 struct mdoc_node *body; /* save of body macro */
916 #ifdef UGLY
917 struct mdoc_node *n;
918 #endif
919 enum mdoct ntok;
920 enum margserr ac, lac;
921 enum margverr av;
922 char *p;
923
924 nl = MDOC_NEWLINE & m->flags;
925
926 /* Close out prior implicit scope. */
927
928 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
929 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
930 return(0);
931 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
932 return(0);
933 }
934
935 /*
936 * This routine accomodates implicitly- and explicitly-scoped
937 * macro openings. Implicit ones first close out prior scope
938 * (seen above). Delay opening the head until necessary to
939 * allow leading punctuation to print. Special consideration
940 * for `It -column', which has phrase-part syntax instead of
941 * regular child nodes.
942 */
943
944 for (arg = NULL;; ) {
945 la = *pos;
946 av = mdoc_argv(m, line, tok, &arg, pos, buf);
947
948 if (ARGV_WORD == av) {
949 *pos = la;
950 break;
951 }
952
953 if (ARGV_EOLN == av)
954 break;
955 if (ARGV_ARG == av)
956 continue;
957
958 mdoc_argv_free(arg);
959 return(0);
960 }
961
962 if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
963 return(0);
964
965 head = body = NULL;
966
967 /*
968 * The `Nd' macro has all arguments in its body: it's a hybrid
969 * of block partial-explicit and full-implicit. Stupid.
970 */
971
972 if (MDOC_Nd == tok) {
973 if ( ! mdoc_head_alloc(m, line, ppos, tok))
974 return(0);
975 head = m->last;
976 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
977 return(0);
978 if ( ! mdoc_body_alloc(m, line, ppos, tok))
979 return(0);
980 body = m->last;
981 }
982
983 ac = ARGS_ERROR;
984
985 for ( ; ; ) {
986 la = *pos;
987 lac = ac;
988 ac = mdoc_args(m, line, pos, buf, tok, &p);
989
990 if (ARGS_ERROR == ac)
991 return(0);
992 if (ARGS_EOLN == ac)
993 break;
994
995 if (ARGS_PEND == ac) {
996 if (ARGS_PPHRASE == lac)
997 ac = ARGS_PPHRASE;
998 else
999 ac = ARGS_PHRASE;
1000 }
1001
1002 /* Don't emit leading punct. for phrases. */
1003
1004 if (NULL == head &&
1005 ARGS_PHRASE != ac &&
1006 ARGS_PPHRASE != ac &&
1007 ARGS_QWORD != ac &&
1008 DELIM_OPEN == mdoc_isdelim(p)) {
1009 if ( ! mdoc_word_alloc(m, line, la, p))
1010 return(0);
1011 continue;
1012 }
1013
1014 /* Always re-open head for phrases. */
1015
1016 if (NULL == head ||
1017 ARGS_PHRASE == ac ||
1018 ARGS_PPHRASE == ac) {
1019 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1020 return(0);
1021 head = m->last;
1022 }
1023
1024 if (ARGS_PHRASE == ac || ARGS_PPHRASE == ac) {
1025 if (ARGS_PPHRASE == ac)
1026 m->flags |= MDOC_PPHRASE;
1027 if ( ! phrase(m, line, la, buf, ac))
1028 return(0);
1029 m->flags &= ~MDOC_PPHRASE;
1030 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1031 return(0);
1032 continue;
1033 }
1034
1035 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1036
1037 if (MDOC_MAX == ntok) {
1038 if ( ! mdoc_word_alloc(m, line, la, p))
1039 return(0);
1040 continue;
1041 }
1042
1043 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1044 return(0);
1045 break;
1046 }
1047
1048 if (NULL == head) {
1049 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1050 return(0);
1051 head = m->last;
1052 }
1053
1054 if (nl && ! append_delims(m, line, pos, buf))
1055 return(0);
1056
1057 /* If we've already opened our body, exit now. */
1058
1059 if (NULL != body)
1060 return(1);
1061
1062 #ifdef UGLY
1063 /*
1064 * If there is an open (i.e., unvalidated) sub-block requiring
1065 * explicit close-out, postpone switching the current block from
1066 * head to body until the rew_sub() call closing out that
1067 * sub-block.
1068 */
1069 for (n = m->last; n && n != head; n = n->parent) {
1070 if (MDOC_BLOCK == n->type &&
1071 MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1072 ! (MDOC_VALID & n->flags)) {
1073 assert( ! (MDOC_ACTED & n->flags));
1074 n->pending = head;
1075 return(1);
1076 }
1077 }
1078 #endif
1079
1080 /* Close out scopes to remain in a consistent state. */
1081
1082 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1083 return(0);
1084 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1085 return(0);
1086
1087 return(1);
1088 }
1089
1090
1091 static int
1092 blk_part_imp(MACRO_PROT_ARGS)
1093 {
1094 int la, nl;
1095 enum mdoct ntok;
1096 enum margserr ac;
1097 char *p;
1098 struct mdoc_node *blk; /* saved block context */
1099 struct mdoc_node *body; /* saved body context */
1100 struct mdoc_node *n;
1101
1102 nl = MDOC_NEWLINE & m->flags;
1103
1104 /*
1105 * A macro that spans to the end of the line. This is generally
1106 * (but not necessarily) called as the first macro. The block
1107 * has a head as the immediate child, which is always empty,
1108 * followed by zero or more opening punctuation nodes, then the
1109 * body (which may be empty, depending on the macro), then zero
1110 * or more closing punctuation nodes.
1111 */
1112
1113 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1114 return(0);
1115
1116 blk = m->last;
1117
1118 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1119 return(0);
1120 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1121 return(0);
1122
1123 /*
1124 * Open the body scope "on-demand", that is, after we've
1125 * processed all our the leading delimiters (open parenthesis,
1126 * etc.).
1127 */
1128
1129 for (body = NULL; ; ) {
1130 la = *pos;
1131 ac = mdoc_args(m, line, pos, buf, tok, &p);
1132
1133 if (ARGS_ERROR == ac)
1134 return(0);
1135 if (ARGS_EOLN == ac)
1136 break;
1137 if (ARGS_PUNCT == ac)
1138 break;
1139
1140 if (NULL == body && ARGS_QWORD != ac &&
1141 DELIM_OPEN == mdoc_isdelim(p)) {
1142 if ( ! mdoc_word_alloc(m, line, la, p))
1143 return(0);
1144 continue;
1145 }
1146
1147 if (NULL == body) {
1148 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1149 return(0);
1150 body = m->last;
1151 }
1152
1153 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1154
1155 if (MDOC_MAX == ntok) {
1156 if ( ! mdoc_word_alloc(m, line, la, p))
1157 return(0);
1158 continue;
1159 }
1160
1161 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1162 return(0);
1163 break;
1164 }
1165
1166 /* Clean-ups to leave in a consistent state. */
1167
1168 if (NULL == body) {
1169 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1170 return(0);
1171 body = m->last;
1172 }
1173
1174 for (n = body->child; n && n->next; n = n->next)
1175 /* Do nothing. */ ;
1176
1177 /*
1178 * End of sentence spacing: if the last node is a text node and
1179 * has a trailing period, then mark it as being end-of-sentence.
1180 */
1181
1182 if (n && MDOC_TEXT == n->type && n->string)
1183 if (mandoc_eos(n->string, strlen(n->string)))
1184 n->flags |= MDOC_EOS;
1185
1186 /* Up-propogate the end-of-space flag. */
1187
1188 if (n && (MDOC_EOS & n->flags)) {
1189 body->flags |= MDOC_EOS;
1190 body->parent->flags |= MDOC_EOS;
1191 }
1192
1193 /*
1194 * If we can't rewind to our body, then our scope has already
1195 * been closed by another macro (like `Oc' closing `Op'). This
1196 * is ugly behaviour nodding its head to OpenBSD's overwhelming
1197 * crufty use of `Op' breakage.
1198 *
1199 * FIXME - this should be ifdef'd OpenBSD?
1200 */
1201 for (n = m->last; n; n = n->parent)
1202 if (body == n)
1203 break;
1204
1205 if (NULL == n && ! mdoc_nmsg(m, body, MANDOCERR_SCOPE))
1206 return(0);
1207
1208 if (n && ! rew_last(m, body))
1209 return(0);
1210
1211 /* Standard appending of delimiters. */
1212
1213 if (nl && ! append_delims(m, line, pos, buf))
1214 return(0);
1215
1216 /* Rewind scope, if applicable. */
1217
1218 if (n && ! rew_last(m, blk))
1219 return(0);
1220
1221 return(1);
1222 }
1223
1224
1225 static int
1226 blk_part_exp(MACRO_PROT_ARGS)
1227 {
1228 int la, nl;
1229 enum margserr ac;
1230 struct mdoc_node *head; /* keep track of head */
1231 struct mdoc_node *body; /* keep track of body */
1232 char *p;
1233 enum mdoct ntok;
1234
1235 nl = MDOC_NEWLINE & m->flags;
1236
1237 /*
1238 * The opening of an explicit macro having zero or more leading
1239 * punctuation nodes; a head with optional single element (the
1240 * case of `Eo'); and a body that may be empty.
1241 */
1242
1243 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1244 return(0);
1245
1246 for (head = body = NULL; ; ) {
1247 la = *pos;
1248 ac = mdoc_args(m, line, pos, buf, tok, &p);
1249
1250 if (ARGS_ERROR == ac)
1251 return(0);
1252 if (ARGS_PUNCT == ac)
1253 break;
1254 if (ARGS_EOLN == ac)
1255 break;
1256
1257 /* Flush out leading punctuation. */
1258
1259 if (NULL == head && ARGS_QWORD != ac &&
1260 DELIM_OPEN == mdoc_isdelim(p)) {
1261 assert(NULL == body);
1262 if ( ! mdoc_word_alloc(m, line, la, p))
1263 return(0);
1264 continue;
1265 }
1266
1267 if (NULL == head) {
1268 assert(NULL == body);
1269 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1270 return(0);
1271 head = m->last;
1272 }
1273
1274 /*
1275 * `Eo' gobbles any data into the head, but most other
1276 * macros just immediately close out and begin the body.
1277 */
1278
1279 if (NULL == body) {
1280 assert(head);
1281 /* No check whether it's a macro! */
1282 if (MDOC_Eo == tok)
1283 if ( ! mdoc_word_alloc(m, line, la, p))
1284 return(0);
1285
1286 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1287 return(0);
1288 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1289 return(0);
1290 body = m->last;
1291
1292 if (MDOC_Eo == tok)
1293 continue;
1294 }
1295
1296 assert(NULL != head && NULL != body);
1297
1298 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1299
1300 if (MDOC_MAX == ntok) {
1301 if ( ! mdoc_word_alloc(m, line, la, p))
1302 return(0);
1303 continue;
1304 }
1305
1306 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1307 return(0);
1308 break;
1309 }
1310
1311 /* Clean-up to leave in a consistent state. */
1312
1313 if (NULL == head) {
1314 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1315 return(0);
1316 head = m->last;
1317 }
1318
1319 if (NULL == body) {
1320 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1321 return(0);
1322 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1323 return(0);
1324 body = m->last;
1325 }
1326
1327 /* Standard appending of delimiters. */
1328
1329 if ( ! nl)
1330 return(1);
1331 return(append_delims(m, line, pos, buf));
1332 }
1333
1334
1335 /* ARGSUSED */
1336 static int
1337 in_line_argn(MACRO_PROT_ARGS)
1338 {
1339 int la, flushed, j, maxargs, nl;
1340 enum margserr ac;
1341 enum margverr av;
1342 struct mdoc_arg *arg;
1343 char *p;
1344 enum mdoct ntok;
1345
1346 nl = MDOC_NEWLINE & m->flags;
1347
1348 /*
1349 * A line macro that has a fixed number of arguments (maxargs).
1350 * Only open the scope once the first non-leading-punctuation is
1351 * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then
1352 * keep it open until the maximum number of arguments are
1353 * exhausted.
1354 */
1355
1356 switch (tok) {
1357 case (MDOC_Ap):
1358 /* FALLTHROUGH */
1359 case (MDOC_No):
1360 /* FALLTHROUGH */
1361 case (MDOC_Ns):
1362 /* FALLTHROUGH */
1363 case (MDOC_Ux):
1364 maxargs = 0;
1365 break;
1366 case (MDOC_Xr):
1367 maxargs = 2;
1368 break;
1369 default:
1370 maxargs = 1;
1371 break;
1372 }
1373
1374 for (arg = NULL; ; ) {
1375 la = *pos;
1376 av = mdoc_argv(m, line, tok, &arg, pos, buf);
1377
1378 if (ARGV_WORD == av) {
1379 *pos = la;
1380 break;
1381 }
1382
1383 if (ARGV_EOLN == av)
1384 break;
1385 if (ARGV_ARG == av)
1386 continue;
1387
1388 mdoc_argv_free(arg);
1389 return(0);
1390 }
1391
1392 for (flushed = j = 0; ; ) {
1393 la = *pos;
1394 ac = mdoc_args(m, line, pos, buf, tok, &p);
1395
1396 if (ARGS_ERROR == ac)
1397 return(0);
1398 if (ARGS_PUNCT == ac)
1399 break;
1400 if (ARGS_EOLN == ac)
1401 break;
1402
1403 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1404 ARGS_QWORD != ac &&
1405 0 == j && DELIM_OPEN == mdoc_isdelim(p)) {
1406 if ( ! mdoc_word_alloc(m, line, la, p))
1407 return(0);
1408 continue;
1409 } else if (0 == j)
1410 if ( ! mdoc_elem_alloc(m, line, la, tok, arg))
1411 return(0);
1412
1413 if (j == maxargs && ! flushed) {
1414 if ( ! rew_elem(m, tok))
1415 return(0);
1416 flushed = 1;
1417 }
1418
1419 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1420
1421 if (MDOC_MAX != ntok) {
1422 if ( ! flushed && ! rew_elem(m, tok))
1423 return(0);
1424 flushed = 1;
1425 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1426 return(0);
1427 j++;
1428 break;
1429 }
1430
1431 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1432 ARGS_QWORD != ac &&
1433 ! flushed &&
1434 DELIM_NONE != mdoc_isdelim(p)) {
1435 if ( ! rew_elem(m, tok))
1436 return(0);
1437 flushed = 1;
1438 }
1439
1440 /*
1441 * XXX: this is a hack to work around groff's ugliness
1442 * as regards `Xr' and extraneous arguments. It should
1443 * ideally be deprecated behaviour, but because this is
1444 * code is no here, it's unlikely to be removed.
1445 */
1446
1447 #ifdef __OpenBSD__
1448 if (MDOC_Xr == tok && j == maxargs) {
1449 if ( ! mdoc_elem_alloc(m, line, la, MDOC_Ns, NULL))
1450 return(0);
1451 if ( ! rew_elem(m, MDOC_Ns))
1452 return(0);
1453 }
1454 #endif
1455
1456 if ( ! mdoc_word_alloc(m, line, la, p))
1457 return(0);
1458 j++;
1459 }
1460
1461 if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg))
1462 return(0);
1463
1464 /* Close out in a consistent state. */
1465
1466 if ( ! flushed && ! rew_elem(m, tok))
1467 return(0);
1468 if ( ! nl)
1469 return(1);
1470 return(append_delims(m, line, pos, buf));
1471 }
1472
1473
1474 static int
1475 in_line_eoln(MACRO_PROT_ARGS)
1476 {
1477 int la;
1478 enum margserr ac;
1479 enum margverr av;
1480 struct mdoc_arg *arg;
1481 char *p;
1482 enum mdoct ntok;
1483
1484 assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1485
1486 /* Parse macro arguments. */
1487
1488 for (arg = NULL; ; ) {
1489 la = *pos;
1490 av = mdoc_argv(m, line, tok, &arg, pos, buf);
1491
1492 if (ARGV_WORD == av) {
1493 *pos = la;
1494 break;
1495 }
1496 if (ARGV_EOLN == av)
1497 break;
1498 if (ARGV_ARG == av)
1499 continue;
1500
1501 mdoc_argv_free(arg);
1502 return(0);
1503 }
1504
1505 /* Open element scope. */
1506
1507 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1508 return(0);
1509
1510 /* Parse argument terms. */
1511
1512 for (;;) {
1513 la = *pos;
1514 ac = mdoc_args(m, line, pos, buf, tok, &p);
1515
1516 if (ARGS_ERROR == ac)
1517 return(0);
1518 if (ARGS_EOLN == ac)
1519 break;
1520
1521 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1522
1523 if (MDOC_MAX == ntok) {
1524 if ( ! mdoc_word_alloc(m, line, la, p))
1525 return(0);
1526 continue;
1527 }
1528
1529 if ( ! rew_elem(m, tok))
1530 return(0);
1531 return(mdoc_macro(m, ntok, line, la, pos, buf));
1532 }
1533
1534 /* Close out (no delimiters). */
1535
1536 return(rew_elem(m, tok));
1537 }
1538
1539
1540 /* ARGSUSED */
1541 static int
1542 ctx_synopsis(MACRO_PROT_ARGS)
1543 {
1544 int nl;
1545
1546 nl = MDOC_NEWLINE & m->flags;
1547
1548 /* If we're not in the SYNOPSIS, go straight to in-line. */
1549 if (SEC_SYNOPSIS != m->lastsec)
1550 return(in_line(m, tok, line, ppos, pos, buf));
1551
1552 /* If we're a nested call, same place. */
1553 if ( ! nl)
1554 return(in_line(m, tok, line, ppos, pos, buf));
1555
1556 /*
1557 * XXX: this will open a block scope; however, if later we end
1558 * up formatting the block scope, then child nodes will inherit
1559 * the formatting. Be careful.
1560 */
1561
1562 return(blk_part_imp(m, tok, line, ppos, pos, buf));
1563 }
1564
1565
1566 /* ARGSUSED */
1567 static int
1568 obsolete(MACRO_PROT_ARGS)
1569 {
1570
1571 return(mdoc_pmsg(m, line, ppos, MANDOCERR_MACROOBS));
1572 }
1573
1574
1575 /*
1576 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1577 * They're unusual because they're basically free-form text until a
1578 * macro is encountered.
1579 */
1580 static int
1581 phrase(struct mdoc *m, int line, int ppos, char *buf, enum margserr ac)
1582 {
1583 int la, pos;
1584 enum margserr aac;
1585 enum mdoct ntok;
1586 char *p;
1587
1588 assert(ARGS_PHRASE == ac || ARGS_PPHRASE == ac);
1589
1590 for (pos = ppos; ; ) {
1591 la = pos;
1592
1593 aac = mdoc_zargs(m, line, &pos, buf, 0, &p);
1594
1595 if (ARGS_ERROR == aac)
1596 return(0);
1597 if (ARGS_EOLN == aac)
1598 break;
1599
1600 ntok = ARGS_QWORD == aac ? MDOC_MAX : lookup_raw(p);
1601
1602 if (MDOC_MAX == ntok) {
1603 if ( ! mdoc_word_alloc(m, line, la, p))
1604 return(0);
1605 continue;
1606 }
1607
1608 if ( ! mdoc_macro(m, ntok, line, la, &pos, buf))
1609 return(0);
1610 return(append_delims(m, line, &pos, buf));
1611 }
1612
1613 return(1);
1614 }
1615
1616