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