]> git.cameronkatri.com Git - mandoc.git/blob - man_macro.c
Second test of log_accum.
[mandoc.git] / man_macro.c
1 /* $Id: man_macro.c,v 1.42 2010/03/29 10:10: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 <string.h>
25
26 #include "libman.h"
27
28 enum rew {
29 REW_REWIND,
30 REW_NOHALT,
31 REW_HALT
32 };
33
34 static int blk_close(MACRO_PROT_ARGS);
35 static int blk_dotted(MACRO_PROT_ARGS);
36 static int blk_exp(MACRO_PROT_ARGS);
37 static int blk_imp(MACRO_PROT_ARGS);
38 static int in_line_eoln(MACRO_PROT_ARGS);
39
40 static int rew_scope(enum man_type,
41 struct man *, enum mant);
42 static enum rew rew_dohalt(enum mant, enum man_type,
43 const struct man_node *);
44 static enum rew rew_block(enum mant, enum man_type,
45 const struct man_node *);
46 static int rew_warn(struct man *,
47 struct man_node *, enum merr);
48
49 const struct man_macro __man_macros[MAN_MAX] = {
50 { in_line_eoln, MAN_NSCOPED }, /* br */
51 { in_line_eoln, 0 }, /* TH */
52 { blk_imp, MAN_SCOPED }, /* SH */
53 { blk_imp, MAN_SCOPED }, /* SS */
54 { blk_imp, MAN_SCOPED | MAN_FSCOPED }, /* TP */
55 { blk_imp, 0 }, /* LP */
56 { blk_imp, 0 }, /* PP */
57 { blk_imp, 0 }, /* P */
58 { blk_imp, 0 }, /* IP */
59 { blk_imp, 0 }, /* HP */
60 { in_line_eoln, MAN_SCOPED }, /* SM */
61 { in_line_eoln, MAN_SCOPED }, /* SB */
62 { in_line_eoln, 0 }, /* BI */
63 { in_line_eoln, 0 }, /* IB */
64 { in_line_eoln, 0 }, /* BR */
65 { in_line_eoln, 0 }, /* RB */
66 { in_line_eoln, MAN_SCOPED }, /* R */
67 { in_line_eoln, MAN_SCOPED }, /* B */
68 { in_line_eoln, MAN_SCOPED }, /* I */
69 { in_line_eoln, 0 }, /* IR */
70 { in_line_eoln, 0 }, /* RI */
71 { in_line_eoln, MAN_NSCOPED }, /* na */
72 { in_line_eoln, 0 }, /* i */
73 { in_line_eoln, MAN_NSCOPED }, /* sp */
74 { in_line_eoln, 0 }, /* nf */
75 { in_line_eoln, 0 }, /* fi */
76 { in_line_eoln, 0 }, /* r */
77 { blk_close, 0 }, /* RE */
78 { blk_exp, MAN_EXPLICIT }, /* RS */
79 { in_line_eoln, 0 }, /* DT */
80 { in_line_eoln, 0 }, /* UC */
81 { in_line_eoln, 0 }, /* PD */
82 { in_line_eoln, MAN_NSCOPED }, /* Sp */
83 { in_line_eoln, 0 }, /* Vb */
84 { in_line_eoln, 0 }, /* Ve */
85 { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* de */
86 { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* dei */
87 { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* am */
88 { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* ami */
89 { blk_exp, MAN_EXPLICIT | MAN_NOCLOSE}, /* ig */
90 { blk_dotted, 0 }, /* . */
91 };
92
93 const struct man_macro * const man_macros = __man_macros;
94
95
96 /*
97 * Warn when "n" is an explicit non-roff macro.
98 */
99 static int
100 rew_warn(struct man *m, struct man_node *n, enum merr er)
101 {
102
103 if (er == WERRMAX || MAN_BLOCK != n->type)
104 return(1);
105 if (MAN_VALID & n->flags)
106 return(1);
107 if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
108 return(1);
109 if (MAN_NOCLOSE & man_macros[n->tok].flags)
110 return(1);
111 return(man_nwarn(m, n, er));
112 }
113
114
115 /*
116 * Rewind scope. If a code "er" != WERRMAX has been provided, it will
117 * be used if an explicit block scope is being closed out.
118 */
119 int
120 man_unscope(struct man *m, const struct man_node *n, enum merr er)
121 {
122
123 assert(n);
124
125 /* LINTED */
126 while (m->last != n) {
127 if ( ! rew_warn(m, m->last, er))
128 return(0);
129 if ( ! man_valid_post(m))
130 return(0);
131 if ( ! man_action_post(m))
132 return(0);
133 m->last = m->last->parent;
134 assert(m->last);
135 }
136
137 if ( ! rew_warn(m, m->last, er))
138 return(0);
139 if ( ! man_valid_post(m))
140 return(0);
141 if ( ! man_action_post(m))
142 return(0);
143
144 m->next = MAN_ROOT == m->last->type ?
145 MAN_NEXT_CHILD : MAN_NEXT_SIBLING;
146
147 return(1);
148 }
149
150
151 static enum rew
152 rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
153 {
154
155 if (MAN_BLOCK == type && ntok == n->parent->tok &&
156 MAN_BODY == n->parent->type)
157 return(REW_REWIND);
158 return(ntok == n->tok ? REW_HALT : REW_NOHALT);
159 }
160
161
162 /*
163 * There are three scope levels: scoped to the root (all), scoped to the
164 * section (all less sections), and scoped to subsections (all less
165 * sections and subsections).
166 */
167 static enum rew
168 rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
169 {
170 enum rew c;
171
172 /* We cannot progress beyond the root ever. */
173 if (MAN_ROOT == n->type)
174 return(REW_HALT);
175
176 assert(n->parent);
177
178 /* Normal nodes shouldn't go to the level of the root. */
179 if (MAN_ROOT == n->parent->type)
180 return(REW_REWIND);
181
182 /* Already-validated nodes should be closed out. */
183 if (MAN_VALID & n->flags)
184 return(REW_NOHALT);
185
186 /* First: rewind to ourselves. */
187 if (type == n->type && tok == n->tok)
188 return(REW_REWIND);
189
190 /*
191 * If we're a roff macro, then we can close out anything that
192 * stands between us and our parent context.
193 */
194 if (MAN_NOCLOSE & man_macros[tok].flags)
195 return(REW_NOHALT);
196
197 /*
198 * Don't clobber roff macros: this is a bit complicated. If the
199 * current macro is a roff macro, halt immediately and don't
200 * rewind. If it's not, and the parent is, then close out the
201 * current scope and halt at the parent.
202 */
203 if (MAN_NOCLOSE & man_macros[n->tok].flags)
204 return(REW_HALT);
205 if (MAN_NOCLOSE & man_macros[n->parent->tok].flags)
206 return(REW_REWIND);
207
208 /*
209 * Next follow the implicit scope-smashings as defined by man.7:
210 * section, sub-section, etc.
211 */
212
213 switch (tok) {
214 case (MAN_SH):
215 break;
216 case (MAN_SS):
217 /* Rewind to a section, if a block. */
218 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
219 return(c);
220 break;
221 case (MAN_RS):
222 /* Rewind to a subsection, if a block. */
223 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
224 return(c);
225 /* Rewind to a section, if a block. */
226 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
227 return(c);
228 break;
229 default:
230 /* Rewind to an offsetter, if a block. */
231 if (REW_NOHALT != (c = rew_block(MAN_RS, type, n)))
232 return(c);
233 /* Rewind to a subsection, if a block. */
234 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
235 return(c);
236 /* Rewind to a section, if a block. */
237 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
238 return(c);
239 break;
240 }
241
242 return(REW_NOHALT);
243 }
244
245
246 /*
247 * Rewinding entails ascending the parse tree until a coherent point,
248 * for example, the `SH' macro will close out any intervening `SS'
249 * scopes. When a scope is closed, it must be validated and actioned.
250 */
251 static int
252 rew_scope(enum man_type type, struct man *m, enum mant tok)
253 {
254 struct man_node *n;
255 enum rew c;
256
257 /* LINTED */
258 for (n = m->last; n; n = n->parent) {
259 /*
260 * Whether we should stop immediately (REW_HALT), stop
261 * and rewind until this point (REW_REWIND), or keep
262 * rewinding (REW_NOHALT).
263 */
264 c = rew_dohalt(tok, type, n);
265 if (REW_HALT == c)
266 return(1);
267 if (REW_REWIND == c)
268 break;
269 }
270
271 /*
272 * Rewind until the current point. Warn if we're a roff
273 * instruction that's mowing over explicit scopes.
274 */
275 assert(n);
276 if (MAN_NOCLOSE & man_macros[tok].flags)
277 return(man_unscope(m, n, WROFFSCOPE));
278
279 return(man_unscope(m, n, WERRMAX));
280 }
281
282
283 /*
284 * Closure for dotted macros (de, dei, am, ami, ign). This must handle
285 * any of these as the parent node, so it needs special handling.
286 * Beyond this, it's the same as blk_close().
287 */
288 /* ARGSUSED */
289 int
290 blk_dotted(MACRO_PROT_ARGS)
291 {
292 enum mant ntok;
293 struct man_node *nn;
294
295 /* Check for any of the following parents... */
296
297 for (nn = m->last->parent; nn; nn = nn->parent)
298 if (nn->tok == MAN_de || nn->tok == MAN_dei ||
299 nn->tok == MAN_am ||
300 nn->tok == MAN_ami ||
301 nn->tok == MAN_ig) {
302 ntok = nn->tok;
303 break;
304 }
305
306 if (NULL == nn) {
307 if ( ! man_pwarn(m, line, ppos, WNOSCOPE))
308 return(0);
309 return(1);
310 }
311
312 if ( ! rew_scope(MAN_BODY, m, ntok))
313 return(0);
314 if ( ! rew_scope(MAN_BLOCK, m, ntok))
315 return(0);
316
317 /*
318 * Restore flags set when we got here and also stipulate that we
319 * don't post-process the line when exiting the macro op
320 * function in man_pmacro(). See blk_exp().
321 */
322
323 m->flags = m->svflags | MAN_ILINE;
324 m->next = m->svnext;
325 return(1);
326 }
327
328
329 /*
330 * Close out a generic explicit macro.
331 */
332 /* ARGSUSED */
333 int
334 blk_close(MACRO_PROT_ARGS)
335 {
336 enum mant ntok;
337 const struct man_node *nn;
338
339 switch (tok) {
340 case (MAN_RE):
341 ntok = MAN_RS;
342 break;
343 default:
344 abort();
345 /* NOTREACHED */
346 }
347
348 for (nn = m->last->parent; nn; nn = nn->parent)
349 if (ntok == nn->tok)
350 break;
351
352 if (NULL == nn)
353 if ( ! man_pwarn(m, line, ppos, WNOSCOPE))
354 return(0);
355
356 if ( ! rew_scope(MAN_BODY, m, ntok))
357 return(0);
358 if ( ! rew_scope(MAN_BLOCK, m, ntok))
359 return(0);
360
361 return(1);
362 }
363
364
365 int
366 blk_exp(MACRO_PROT_ARGS)
367 {
368 int w, la;
369 char *p;
370
371 /*
372 * Close out prior scopes. "Regular" explicit macros cannot be
373 * nested, but we allow roff macros to be placed just about
374 * anywhere.
375 */
376
377 if ( ! (MAN_NOCLOSE & man_macros[tok].flags)) {
378 if ( ! rew_scope(MAN_BODY, m, tok))
379 return(0);
380 if ( ! rew_scope(MAN_BLOCK, m, tok))
381 return(0);
382 } else {
383 /*
384 * Save our state and next-scope indicator; we restore
385 * it when exiting from the roff instruction block. See
386 * blk_dotted().
387 */
388 m->svflags = m->flags;
389 m->svnext = m->next;
390
391 /* Make sure we drop any line modes. */
392 m->flags = 0;
393 }
394
395 if ( ! man_block_alloc(m, line, ppos, tok))
396 return(0);
397 if ( ! man_head_alloc(m, line, ppos, tok))
398 return(0);
399
400 for (;;) {
401 la = *pos;
402 w = man_args(m, line, pos, buf, &p);
403
404 if (-1 == w)
405 return(0);
406 if (0 == w)
407 break;
408
409 if ( ! man_word_alloc(m, line, la, p))
410 return(0);
411 }
412
413 assert(m);
414 assert(tok != MAN_MAX);
415
416 if ( ! rew_scope(MAN_HEAD, m, tok))
417 return(0);
418 return(man_body_alloc(m, line, ppos, tok));
419 }
420
421
422
423 /*
424 * Parse an implicit-block macro. These contain a MAN_HEAD and a
425 * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other
426 * scopes, such as `SH' closing out an `SS', are defined in the rew
427 * routines.
428 */
429 int
430 blk_imp(MACRO_PROT_ARGS)
431 {
432 int w, la;
433 char *p;
434 struct man_node *n;
435
436 /* Close out prior scopes. */
437
438 if ( ! rew_scope(MAN_BODY, m, tok))
439 return(0);
440 if ( ! rew_scope(MAN_BLOCK, m, tok))
441 return(0);
442
443 /* Allocate new block & head scope. */
444
445 if ( ! man_block_alloc(m, line, ppos, tok))
446 return(0);
447 if ( ! man_head_alloc(m, line, ppos, tok))
448 return(0);
449
450 n = m->last;
451
452 /* Add line arguments. */
453
454 for (;;) {
455 la = *pos;
456 w = man_args(m, line, pos, buf, &p);
457
458 if (-1 == w)
459 return(0);
460 if (0 == w)
461 break;
462
463 if ( ! man_word_alloc(m, line, la, p))
464 return(0);
465 }
466
467 /* Close out head and open body (unless MAN_SCOPE). */
468
469 if (MAN_SCOPED & man_macros[tok].flags) {
470 /* If we're forcing scope (`TP'), keep it open. */
471 if (MAN_FSCOPED & man_macros[tok].flags) {
472 m->flags |= MAN_BLINE;
473 return(1);
474 } else if (n == m->last) {
475 m->flags |= MAN_BLINE;
476 return(1);
477 }
478 }
479
480 if ( ! rew_scope(MAN_HEAD, m, tok))
481 return(0);
482 return(man_body_alloc(m, line, ppos, tok));
483 }
484
485
486 int
487 in_line_eoln(MACRO_PROT_ARGS)
488 {
489 int w, la;
490 char *p;
491 struct man_node *n;
492
493 if ( ! man_elem_alloc(m, line, ppos, tok))
494 return(0);
495
496 n = m->last;
497
498 for (;;) {
499 la = *pos;
500 w = man_args(m, line, pos, buf, &p);
501
502 if (-1 == w)
503 return(0);
504 if (0 == w)
505 break;
506 if ( ! man_word_alloc(m, line, la, p))
507 return(0);
508 }
509
510 /*
511 * If no arguments are specified and this is MAN_SCOPED (i.e.,
512 * next-line scoped), then set our mode to indicate that we're
513 * waiting for terms to load into our context.
514 */
515
516 if (n == m->last && MAN_SCOPED & man_macros[tok].flags) {
517 assert( ! (MAN_NSCOPED & man_macros[tok].flags));
518 m->flags |= MAN_ELINE;
519 return(1);
520 }
521
522 /* Set ignorable context, if applicable. */
523
524 if (MAN_NSCOPED & man_macros[tok].flags) {
525 assert( ! (MAN_SCOPED & man_macros[tok].flags));
526 m->flags |= MAN_ILINE;
527 }
528
529 /*
530 * Rewind our element scope. Note that when TH is pruned, we'll
531 * be back at the root, so make sure that we don't clobber as
532 * its sibling.
533 */
534
535 for ( ; m->last; m->last = m->last->parent) {
536 if (m->last == n)
537 break;
538 if (m->last->type == MAN_ROOT)
539 break;
540 if ( ! man_valid_post(m))
541 return(0);
542 if ( ! man_action_post(m))
543 return(0);
544 }
545
546 assert(m->last);
547
548 /*
549 * Same here regarding whether we're back at the root.
550 */
551
552 if (m->last->type != MAN_ROOT && ! man_valid_post(m))
553 return(0);
554 if (m->last->type != MAN_ROOT && ! man_action_post(m))
555 return(0);
556
557 m->next = MAN_ROOT == m->last->type ?
558 MAN_NEXT_CHILD : MAN_NEXT_SIBLING;
559
560 return(1);
561 }
562
563
564 int
565 man_macroend(struct man *m)
566 {
567
568 return(man_unscope(m, m->first, WEXITSCOPE));
569 }
570