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