]> git.cameronkatri.com Git - mandoc.git/blob - man_macro.c
If no man.cgi `whatis' results are found, offer a quick link to the apropos
[mandoc.git] / man_macro.c
1 /* $Id: man_macro.c,v 1.70 2011/12/04 00:44:12 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
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 "man.h"
27 #include "mandoc.h"
28 #include "libmandoc.h"
29 #include "libman.h"
30
31 enum rew {
32 REW_REWIND,
33 REW_NOHALT,
34 REW_HALT
35 };
36
37 static int blk_close(MACRO_PROT_ARGS);
38 static int blk_exp(MACRO_PROT_ARGS);
39 static int blk_imp(MACRO_PROT_ARGS);
40 static int in_line_eoln(MACRO_PROT_ARGS);
41 static int man_args(struct man *, int,
42 int *, char *, char **);
43
44 static int rew_scope(enum man_type,
45 struct man *, enum mant);
46 static enum rew rew_dohalt(enum mant, enum man_type,
47 const struct man_node *);
48 static enum rew rew_block(enum mant, enum man_type,
49 const struct man_node *);
50 static void rew_warn(struct man *,
51 struct man_node *, enum mandocerr);
52
53 const struct man_macro __man_macros[MAN_MAX] = {
54 { in_line_eoln, MAN_NSCOPED }, /* br */
55 { in_line_eoln, MAN_BSCOPE }, /* TH */
56 { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */
57 { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */
58 { blk_imp, MAN_BSCOPE | MAN_SCOPED | MAN_FSCOPED }, /* TP */
59 { blk_imp, MAN_BSCOPE }, /* LP */
60 { blk_imp, MAN_BSCOPE }, /* PP */
61 { blk_imp, MAN_BSCOPE }, /* P */
62 { blk_imp, MAN_BSCOPE }, /* IP */
63 { blk_imp, MAN_BSCOPE }, /* HP */
64 { in_line_eoln, MAN_SCOPED }, /* SM */
65 { in_line_eoln, MAN_SCOPED }, /* SB */
66 { in_line_eoln, 0 }, /* BI */
67 { in_line_eoln, 0 }, /* IB */
68 { in_line_eoln, 0 }, /* BR */
69 { in_line_eoln, 0 }, /* RB */
70 { in_line_eoln, MAN_SCOPED }, /* R */
71 { in_line_eoln, MAN_SCOPED }, /* B */
72 { in_line_eoln, MAN_SCOPED }, /* I */
73 { in_line_eoln, 0 }, /* IR */
74 { in_line_eoln, 0 }, /* RI */
75 { in_line_eoln, MAN_NSCOPED }, /* na */
76 { in_line_eoln, MAN_NSCOPED }, /* sp */
77 { in_line_eoln, MAN_BSCOPE }, /* nf */
78 { in_line_eoln, MAN_BSCOPE }, /* fi */
79 { blk_close, 0 }, /* RE */
80 { blk_exp, MAN_EXPLICIT }, /* RS */
81 { in_line_eoln, 0 }, /* DT */
82 { in_line_eoln, 0 }, /* UC */
83 { in_line_eoln, 0 }, /* PD */
84 { in_line_eoln, 0 }, /* AT */
85 { in_line_eoln, 0 }, /* in */
86 { in_line_eoln, 0 }, /* ft */
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 void
96 rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
97 {
98
99 if (er == MANDOCERR_MAX || MAN_BLOCK != n->type)
100 return;
101 if (MAN_VALID & n->flags)
102 return;
103 if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
104 return;
105
106 assert(er < MANDOCERR_FATAL);
107 man_nmsg(m, n, er);
108 }
109
110
111 /*
112 * Rewind scope. If a code "er" != MANDOCERR_MAX has been provided, it
113 * will be used if an explicit block scope is being closed out.
114 */
115 int
116 man_unscope(struct man *m, const struct man_node *to,
117 enum mandocerr er)
118 {
119 struct man_node *n;
120
121 assert(to);
122
123 m->next = MAN_NEXT_SIBLING;
124
125 /* LINTED */
126 while (m->last != to) {
127 /*
128 * Save the parent here, because we may delete the
129 * m->last node in the post-validation phase and reset
130 * it to m->last->parent, causing a step in the closing
131 * out to be lost.
132 */
133 n = m->last->parent;
134 rew_warn(m, m->last, er);
135 if ( ! man_valid_post(m))
136 return(0);
137 m->last = n;
138 assert(m->last);
139 }
140
141 rew_warn(m, m->last, er);
142 if ( ! man_valid_post(m))
143 return(0);
144
145 return(1);
146 }
147
148
149 static enum rew
150 rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
151 {
152
153 if (MAN_BLOCK == type && ntok == n->parent->tok &&
154 MAN_BODY == n->parent->type)
155 return(REW_REWIND);
156 return(ntok == n->tok ? REW_HALT : REW_NOHALT);
157 }
158
159
160 /*
161 * There are three scope levels: scoped to the root (all), scoped to the
162 * section (all less sections), and scoped to subsections (all less
163 * sections and subsections).
164 */
165 static enum rew
166 rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
167 {
168 enum rew c;
169
170 /* We cannot progress beyond the root ever. */
171 if (MAN_ROOT == n->type)
172 return(REW_HALT);
173
174 assert(n->parent);
175
176 /* Normal nodes shouldn't go to the level of the root. */
177 if (MAN_ROOT == n->parent->type)
178 return(REW_REWIND);
179
180 /* Already-validated nodes should be closed out. */
181 if (MAN_VALID & n->flags)
182 return(REW_NOHALT);
183
184 /* First: rewind to ourselves. */
185 if (type == n->type && tok == n->tok)
186 return(REW_REWIND);
187
188 /*
189 * Next follow the implicit scope-smashings as defined by man.7:
190 * section, sub-section, etc.
191 */
192
193 switch (tok) {
194 case (MAN_SH):
195 break;
196 case (MAN_SS):
197 /* Rewind to a section, if a block. */
198 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
199 return(c);
200 break;
201 case (MAN_RS):
202 /* Rewind to a subsection, if a block. */
203 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
204 return(c);
205 /* Rewind to a section, if a block. */
206 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
207 return(c);
208 break;
209 default:
210 /* Rewind to an offsetter, if a block. */
211 if (REW_NOHALT != (c = rew_block(MAN_RS, type, n)))
212 return(c);
213 /* Rewind to a subsection, if a block. */
214 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
215 return(c);
216 /* Rewind to a section, if a block. */
217 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
218 return(c);
219 break;
220 }
221
222 return(REW_NOHALT);
223 }
224
225
226 /*
227 * Rewinding entails ascending the parse tree until a coherent point,
228 * for example, the `SH' macro will close out any intervening `SS'
229 * scopes. When a scope is closed, it must be validated and actioned.
230 */
231 static int
232 rew_scope(enum man_type type, struct man *m, enum mant tok)
233 {
234 struct man_node *n;
235 enum rew c;
236
237 /* LINTED */
238 for (n = m->last; n; n = n->parent) {
239 /*
240 * Whether we should stop immediately (REW_HALT), stop
241 * and rewind until this point (REW_REWIND), or keep
242 * rewinding (REW_NOHALT).
243 */
244 c = rew_dohalt(tok, type, n);
245 if (REW_HALT == c)
246 return(1);
247 if (REW_REWIND == c)
248 break;
249 }
250
251 /*
252 * Rewind until the current point. Warn if we're a roff
253 * instruction that's mowing over explicit scopes.
254 */
255 assert(n);
256
257 return(man_unscope(m, n, MANDOCERR_MAX));
258 }
259
260
261 /*
262 * Close out a generic explicit macro.
263 */
264 /* ARGSUSED */
265 int
266 blk_close(MACRO_PROT_ARGS)
267 {
268 enum mant ntok;
269 const struct man_node *nn;
270
271 switch (tok) {
272 case (MAN_RE):
273 ntok = MAN_RS;
274 break;
275 default:
276 abort();
277 /* NOTREACHED */
278 }
279
280 for (nn = m->last->parent; nn; nn = nn->parent)
281 if (ntok == nn->tok)
282 break;
283
284 if (NULL == nn)
285 man_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);
286
287 if ( ! rew_scope(MAN_BODY, m, ntok))
288 return(0);
289 if ( ! rew_scope(MAN_BLOCK, m, ntok))
290 return(0);
291
292 return(1);
293 }
294
295
296 /* ARGSUSED */
297 int
298 blk_exp(MACRO_PROT_ARGS)
299 {
300 int la;
301 char *p;
302
303 /*
304 * Close out prior scopes. "Regular" explicit macros cannot be
305 * nested, but we allow roff macros to be placed just about
306 * anywhere.
307 */
308
309 if ( ! man_block_alloc(m, line, ppos, tok))
310 return(0);
311 if ( ! man_head_alloc(m, line, ppos, tok))
312 return(0);
313
314 for (;;) {
315 la = *pos;
316 if ( ! man_args(m, line, pos, buf, &p))
317 break;
318 if ( ! man_word_alloc(m, line, la, p))
319 return(0);
320 }
321
322 assert(m);
323 assert(tok != MAN_MAX);
324
325 if ( ! rew_scope(MAN_HEAD, m, tok))
326 return(0);
327 return(man_body_alloc(m, line, ppos, tok));
328 }
329
330
331
332 /*
333 * Parse an implicit-block macro. These contain a MAN_HEAD and a
334 * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other
335 * scopes, such as `SH' closing out an `SS', are defined in the rew
336 * routines.
337 */
338 /* ARGSUSED */
339 int
340 blk_imp(MACRO_PROT_ARGS)
341 {
342 int la;
343 char *p;
344 struct man_node *n;
345
346 /* Close out prior scopes. */
347
348 if ( ! rew_scope(MAN_BODY, m, tok))
349 return(0);
350 if ( ! rew_scope(MAN_BLOCK, m, tok))
351 return(0);
352
353 /* Allocate new block & head scope. */
354
355 if ( ! man_block_alloc(m, line, ppos, tok))
356 return(0);
357 if ( ! man_head_alloc(m, line, ppos, tok))
358 return(0);
359
360 n = m->last;
361
362 /* Add line arguments. */
363
364 for (;;) {
365 la = *pos;
366 if ( ! man_args(m, line, pos, buf, &p))
367 break;
368 if ( ! man_word_alloc(m, line, la, p))
369 return(0);
370 }
371
372 /* Close out head and open body (unless MAN_SCOPE). */
373
374 if (MAN_SCOPED & man_macros[tok].flags) {
375 /* If we're forcing scope (`TP'), keep it open. */
376 if (MAN_FSCOPED & man_macros[tok].flags) {
377 m->flags |= MAN_BLINE;
378 return(1);
379 } else if (n == m->last) {
380 m->flags |= MAN_BLINE;
381 return(1);
382 }
383 }
384
385 if ( ! rew_scope(MAN_HEAD, m, tok))
386 return(0);
387 return(man_body_alloc(m, line, ppos, tok));
388 }
389
390
391 /* ARGSUSED */
392 int
393 in_line_eoln(MACRO_PROT_ARGS)
394 {
395 int la;
396 char *p;
397 struct man_node *n;
398
399 if ( ! man_elem_alloc(m, line, ppos, tok))
400 return(0);
401
402 n = m->last;
403
404 for (;;) {
405 la = *pos;
406 if ( ! man_args(m, line, pos, buf, &p))
407 break;
408 if ( ! man_word_alloc(m, line, la, p))
409 return(0);
410 }
411
412 /*
413 * If no arguments are specified and this is MAN_SCOPED (i.e.,
414 * next-line scoped), then set our mode to indicate that we're
415 * waiting for terms to load into our context.
416 */
417
418 if (n == m->last && MAN_SCOPED & man_macros[tok].flags) {
419 assert( ! (MAN_NSCOPED & man_macros[tok].flags));
420 m->flags |= MAN_ELINE;
421 return(1);
422 }
423
424 /* Set ignorable context, if applicable. */
425
426 if (MAN_NSCOPED & man_macros[tok].flags) {
427 assert( ! (MAN_SCOPED & man_macros[tok].flags));
428 m->flags |= MAN_ILINE;
429 }
430
431 assert(MAN_ROOT != m->last->type);
432 m->next = MAN_NEXT_SIBLING;
433
434 /*
435 * Rewind our element scope. Note that when TH is pruned, we'll
436 * be back at the root, so make sure that we don't clobber as
437 * its sibling.
438 */
439
440 for ( ; m->last; m->last = m->last->parent) {
441 if (m->last == n)
442 break;
443 if (m->last->type == MAN_ROOT)
444 break;
445 if ( ! man_valid_post(m))
446 return(0);
447 }
448
449 assert(m->last);
450
451 /*
452 * Same here regarding whether we're back at the root.
453 */
454
455 if (m->last->type != MAN_ROOT && ! man_valid_post(m))
456 return(0);
457
458 return(1);
459 }
460
461
462 int
463 man_macroend(struct man *m)
464 {
465
466 return(man_unscope(m, m->first, MANDOCERR_SCOPEEXIT));
467 }
468
469 static int
470 man_args(struct man *m, int line, int *pos, char *buf, char **v)
471 {
472 char *start;
473
474 assert(*pos);
475 *v = start = buf + *pos;
476 assert(' ' != *start);
477
478 if ('\0' == *start)
479 return(0);
480
481 *v = mandoc_getarg(m->parse, v, line, pos);
482 return(1);
483 }