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