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