xref: /illumos-gate/usr/src/cmd/mandoc/mdoc_state.c (revision e34d8872)
1 /*	$Id: mdoc_state.c,v 1.3 2015/10/30 18:53:54 schwarze Exp $ */
2 /*
3  * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
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 <sys/types.h>
18 
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "mandoc.h"
23 #include "roff.h"
24 #include "mdoc.h"
25 #include "libmandoc.h"
26 #include "libmdoc.h"
27 
28 #define STATE_ARGS  struct roff_man *mdoc, struct roff_node *n
29 
30 typedef	void	(*state_handler)(STATE_ARGS);
31 
32 static	void	 state_bd(STATE_ARGS);
33 static	void	 state_bl(STATE_ARGS);
34 static	void	 state_dl(STATE_ARGS);
35 static	void	 state_sh(STATE_ARGS);
36 static	void	 state_sm(STATE_ARGS);
37 
38 static	const state_handler state_handlers[MDOC_MAX] = {
39 	NULL,		/* Ap */
40 	NULL,		/* Dd */
41 	NULL,		/* Dt */
42 	NULL,		/* Os */
43 	state_sh,	/* Sh */
44 	NULL,		/* Ss */
45 	NULL,		/* Pp */
46 	NULL,		/* D1 */
47 	state_dl,	/* Dl */
48 	state_bd,	/* Bd */
49 	NULL,		/* Ed */
50 	state_bl,	/* Bl */
51 	NULL,		/* El */
52 	NULL,		/* It */
53 	NULL,		/* Ad */
54 	NULL,		/* An */
55 	NULL,		/* Ar */
56 	NULL,		/* Cd */
57 	NULL,		/* Cm */
58 	NULL,		/* Dv */
59 	NULL,		/* Er */
60 	NULL,		/* Ev */
61 	NULL,		/* Ex */
62 	NULL,		/* Fa */
63 	NULL,		/* Fd */
64 	NULL,		/* Fl */
65 	NULL,		/* Fn */
66 	NULL,		/* Ft */
67 	NULL,		/* Ic */
68 	NULL,		/* In */
69 	NULL,		/* Li */
70 	NULL,		/* Nd */
71 	NULL,		/* Nm */
72 	NULL,		/* Op */
73 	NULL,		/* Ot */
74 	NULL,		/* Pa */
75 	NULL,		/* Rv */
76 	NULL,		/* St */
77 	NULL,		/* Va */
78 	NULL,		/* Vt */
79 	NULL,		/* Xr */
80 	NULL,		/* %A */
81 	NULL,		/* %B */
82 	NULL,		/* %D */
83 	NULL,		/* %I */
84 	NULL,		/* %J */
85 	NULL,		/* %N */
86 	NULL,		/* %O */
87 	NULL,		/* %P */
88 	NULL,		/* %R */
89 	NULL,		/* %T */
90 	NULL,		/* %V */
91 	NULL,		/* Ac */
92 	NULL,		/* Ao */
93 	NULL,		/* Aq */
94 	NULL,		/* At */
95 	NULL,		/* Bc */
96 	NULL,		/* Bf */
97 	NULL,		/* Bo */
98 	NULL,		/* Bq */
99 	NULL,		/* Bsx */
100 	NULL,		/* Bx */
101 	NULL,		/* Db */
102 	NULL,		/* Dc */
103 	NULL,		/* Do */
104 	NULL,		/* Dq */
105 	NULL,		/* Ec */
106 	NULL,		/* Ef */
107 	NULL,		/* Em */
108 	NULL,		/* Eo */
109 	NULL,		/* Fx */
110 	NULL,		/* Ms */
111 	NULL,		/* No */
112 	NULL,		/* Ns */
113 	NULL,		/* Nx */
114 	NULL,		/* Ox */
115 	NULL,		/* Pc */
116 	NULL,		/* Pf */
117 	NULL,		/* Po */
118 	NULL,		/* Pq */
119 	NULL,		/* Qc */
120 	NULL,		/* Ql */
121 	NULL,		/* Qo */
122 	NULL,		/* Qq */
123 	NULL,		/* Re */
124 	NULL,		/* Rs */
125 	NULL,		/* Sc */
126 	NULL,		/* So */
127 	NULL,		/* Sq */
128 	state_sm,	/* Sm */
129 	NULL,		/* Sx */
130 	NULL,		/* Sy */
131 	NULL,		/* Tn */
132 	NULL,		/* Ux */
133 	NULL,		/* Xc */
134 	NULL,		/* Xo */
135 	NULL,		/* Fo */
136 	NULL,		/* Fc */
137 	NULL,		/* Oo */
138 	NULL,		/* Oc */
139 	NULL,		/* Bk */
140 	NULL,		/* Ek */
141 	NULL,		/* Bt */
142 	NULL,		/* Hf */
143 	NULL,		/* Fr */
144 	NULL,		/* Ud */
145 	NULL,		/* Lb */
146 	NULL,		/* Lp */
147 	NULL,		/* Lk */
148 	NULL,		/* Mt */
149 	NULL,		/* Brq */
150 	NULL,		/* Bro */
151 	NULL,		/* Brc */
152 	NULL,		/* %C */
153 	NULL,		/* Es */
154 	NULL,		/* En */
155 	NULL,		/* Dx */
156 	NULL,		/* %Q */
157 	NULL,		/* br */
158 	NULL,		/* sp */
159 	NULL,		/* %U */
160 	NULL,		/* Ta */
161 	NULL,		/* ll */
162 };
163 
164 
165 void
166 mdoc_state(struct roff_man *mdoc, struct roff_node *n)
167 {
168 	state_handler handler;
169 
170 	if (n->tok == TOKEN_NONE)
171 		return;
172 
173 	if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE))
174 		mdoc->flags |= MDOC_PBODY;
175 
176 	handler = state_handlers[n->tok];
177 	if (*handler)
178 		(*handler)(mdoc, n);
179 }
180 
181 void
182 mdoc_state_reset(struct roff_man *mdoc)
183 {
184 
185 	roff_setreg(mdoc->roff, "nS", 0, '=');
186 	mdoc->flags = 0;
187 }
188 
189 static void
190 state_bd(STATE_ARGS)
191 {
192 	enum mdocargt arg;
193 
194 	if (n->type != ROFFT_HEAD &&
195 	    (n->type != ROFFT_BODY || n->end != ENDBODY_NOT))
196 		return;
197 
198 	if (n->parent->args == NULL)
199 		return;
200 
201 	arg = n->parent->args->argv[0].arg;
202 	if (arg != MDOC_Literal && arg != MDOC_Unfilled)
203 		return;
204 
205 	state_dl(mdoc, n);
206 }
207 
208 static void
209 state_bl(STATE_ARGS)
210 {
211 
212 	if (n->type != ROFFT_HEAD || n->parent->args == NULL)
213 		return;
214 
215 	switch(n->parent->args->argv[0].arg) {
216 	case MDOC_Diag:
217 		n->norm->Bl.type = LIST_diag;
218 		break;
219 	case MDOC_Column:
220 		n->norm->Bl.type = LIST_column;
221 		break;
222 	default:
223 		break;
224 	}
225 }
226 
227 static void
228 state_dl(STATE_ARGS)
229 {
230 
231 	switch (n->type) {
232 	case ROFFT_HEAD:
233 		mdoc->flags |= MDOC_LITERAL;
234 		break;
235 	case ROFFT_BODY:
236 		mdoc->flags &= ~MDOC_LITERAL;
237 		break;
238 	default:
239 		break;
240 	}
241 }
242 
243 static void
244 state_sh(STATE_ARGS)
245 {
246 	struct roff_node *nch;
247 	char		 *secname;
248 
249 	if (n->type != ROFFT_HEAD)
250 		return;
251 
252 	if ( ! (n->flags & MDOC_VALID)) {
253 		secname = NULL;
254 		deroff(&secname, n);
255 
256 		/*
257 		 * Set the section attribute for the BLOCK, HEAD,
258 		 * and HEAD children; the latter can only be TEXT
259 		 * nodes, so no recursion is needed.  For other
260 		 * nodes, including the .Sh BODY, this is done
261 		 * when allocating the node data structures, but
262 		 * for .Sh BLOCK and HEAD, the section is still
263 		 * unknown at that time.
264 		 */
265 
266 		n->sec = n->parent->sec = secname == NULL ?
267 		    SEC_CUSTOM : mdoc_a2sec(secname);
268 		for (nch = n->child; nch != NULL; nch = nch->next)
269 			nch->sec = n->sec;
270 		free(secname);
271 	}
272 
273 	if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
274 		roff_setreg(mdoc->roff, "nS", 1, '=');
275 		mdoc->flags |= MDOC_SYNOPSIS;
276 	} else {
277 		roff_setreg(mdoc->roff, "nS", 0, '=');
278 		mdoc->flags &= ~MDOC_SYNOPSIS;
279 	}
280 }
281 
282 static void
283 state_sm(STATE_ARGS)
284 {
285 
286 	if (n->child == NULL)
287 		mdoc->flags ^= MDOC_SMOFF;
288 	else if ( ! strcmp(n->child->string, "on"))
289 		mdoc->flags &= ~MDOC_SMOFF;
290 	else if ( ! strcmp(n->child->string, "off"))
291 		mdoc->flags |= MDOC_SMOFF;
292 }
293