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