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