xref: /openbsd-src/usr.bin/mandoc/mdoc_state.c (revision a0c8730ce5aaf571286843147f141a527c1df74a)
1*a0c8730cSschwarze /* $OpenBSD: mdoc_state.c,v 1.17 2022/08/19 12:49:36 schwarze Exp $ */
2396853b5Sschwarze /*
3*a0c8730cSschwarze  * Copyright (c) 2014,2015,2017,2018,2022 Ingo Schwarze <schwarze@openbsd.org>
4396853b5Sschwarze  *
5396853b5Sschwarze  * Permission to use, copy, modify, and distribute this software for any
6396853b5Sschwarze  * purpose with or without fee is hereby granted, provided that the above
7396853b5Sschwarze  * copyright notice and this permission notice appear in all copies.
8396853b5Sschwarze  *
9396853b5Sschwarze  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10396853b5Sschwarze  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11396853b5Sschwarze  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12396853b5Sschwarze  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13396853b5Sschwarze  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14396853b5Sschwarze  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15396853b5Sschwarze  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16396853b5Sschwarze  */
17396853b5Sschwarze #include <sys/types.h>
18396853b5Sschwarze 
1929478532Sschwarze #include <assert.h>
20e501e731Sschwarze #include <stdio.h>
21396853b5Sschwarze #include <stdlib.h>
22396853b5Sschwarze #include <string.h>
23396853b5Sschwarze 
24396853b5Sschwarze #include "mandoc.h"
25396853b5Sschwarze #include "roff.h"
26396853b5Sschwarze #include "mdoc.h"
27396853b5Sschwarze #include "libmandoc.h"
286b86842eSschwarze #include "roff_int.h"
29396853b5Sschwarze #include "libmdoc.h"
30396853b5Sschwarze 
31396853b5Sschwarze #define STATE_ARGS  struct roff_man *mdoc, struct roff_node *n
32396853b5Sschwarze 
33396853b5Sschwarze typedef	void	(*state_handler)(STATE_ARGS);
34396853b5Sschwarze 
35*a0c8730cSschwarze static	void	 setsec(struct roff_node *, enum roff_sec);
363e642ba0Sschwarze static	void	 state_bl(STATE_ARGS);
37396853b5Sschwarze static	void	 state_sh(STATE_ARGS);
38396853b5Sschwarze static	void	 state_sm(STATE_ARGS);
39396853b5Sschwarze 
4016fe0cfcSschwarze static	const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = {
41396853b5Sschwarze 	NULL,		/* Dd */
42396853b5Sschwarze 	NULL,		/* Dt */
43396853b5Sschwarze 	NULL,		/* Os */
44396853b5Sschwarze 	state_sh,	/* Sh */
45396853b5Sschwarze 	NULL,		/* Ss */
46396853b5Sschwarze 	NULL,		/* Pp */
47396853b5Sschwarze 	NULL,		/* D1 */
48c56b6dacSschwarze 	NULL,		/* Dl */
49c56b6dacSschwarze 	NULL,		/* Bd */
50396853b5Sschwarze 	NULL,		/* Ed */
513e642ba0Sschwarze 	state_bl,	/* Bl */
52396853b5Sschwarze 	NULL,		/* El */
53396853b5Sschwarze 	NULL,		/* It */
54396853b5Sschwarze 	NULL,		/* Ad */
55396853b5Sschwarze 	NULL,		/* An */
5614a309e3Sschwarze 	NULL,		/* Ap */
57396853b5Sschwarze 	NULL,		/* Ar */
58396853b5Sschwarze 	NULL,		/* Cd */
59396853b5Sschwarze 	NULL,		/* Cm */
60396853b5Sschwarze 	NULL,		/* Dv */
61396853b5Sschwarze 	NULL,		/* Er */
62396853b5Sschwarze 	NULL,		/* Ev */
63396853b5Sschwarze 	NULL,		/* Ex */
64396853b5Sschwarze 	NULL,		/* Fa */
65396853b5Sschwarze 	NULL,		/* Fd */
66396853b5Sschwarze 	NULL,		/* Fl */
67396853b5Sschwarze 	NULL,		/* Fn */
68396853b5Sschwarze 	NULL,		/* Ft */
69396853b5Sschwarze 	NULL,		/* Ic */
70396853b5Sschwarze 	NULL,		/* In */
71396853b5Sschwarze 	NULL,		/* Li */
72396853b5Sschwarze 	NULL,		/* Nd */
73396853b5Sschwarze 	NULL,		/* Nm */
74396853b5Sschwarze 	NULL,		/* Op */
75396853b5Sschwarze 	NULL,		/* Ot */
76396853b5Sschwarze 	NULL,		/* Pa */
77396853b5Sschwarze 	NULL,		/* Rv */
78396853b5Sschwarze 	NULL,		/* St */
79396853b5Sschwarze 	NULL,		/* Va */
80396853b5Sschwarze 	NULL,		/* Vt */
81396853b5Sschwarze 	NULL,		/* Xr */
82396853b5Sschwarze 	NULL,		/* %A */
83396853b5Sschwarze 	NULL,		/* %B */
84396853b5Sschwarze 	NULL,		/* %D */
85396853b5Sschwarze 	NULL,		/* %I */
86396853b5Sschwarze 	NULL,		/* %J */
87396853b5Sschwarze 	NULL,		/* %N */
88396853b5Sschwarze 	NULL,		/* %O */
89396853b5Sschwarze 	NULL,		/* %P */
90396853b5Sschwarze 	NULL,		/* %R */
91396853b5Sschwarze 	NULL,		/* %T */
92396853b5Sschwarze 	NULL,		/* %V */
93396853b5Sschwarze 	NULL,		/* Ac */
94396853b5Sschwarze 	NULL,		/* Ao */
95396853b5Sschwarze 	NULL,		/* Aq */
96396853b5Sschwarze 	NULL,		/* At */
97396853b5Sschwarze 	NULL,		/* Bc */
98396853b5Sschwarze 	NULL,		/* Bf */
99396853b5Sschwarze 	NULL,		/* Bo */
100396853b5Sschwarze 	NULL,		/* Bq */
101396853b5Sschwarze 	NULL,		/* Bsx */
102396853b5Sschwarze 	NULL,		/* Bx */
103396853b5Sschwarze 	NULL,		/* Db */
104396853b5Sschwarze 	NULL,		/* Dc */
105396853b5Sschwarze 	NULL,		/* Do */
106396853b5Sschwarze 	NULL,		/* Dq */
107396853b5Sschwarze 	NULL,		/* Ec */
108396853b5Sschwarze 	NULL,		/* Ef */
109396853b5Sschwarze 	NULL,		/* Em */
110396853b5Sschwarze 	NULL,		/* Eo */
111396853b5Sschwarze 	NULL,		/* Fx */
112396853b5Sschwarze 	NULL,		/* Ms */
113396853b5Sschwarze 	NULL,		/* No */
114396853b5Sschwarze 	NULL,		/* Ns */
115396853b5Sschwarze 	NULL,		/* Nx */
116396853b5Sschwarze 	NULL,		/* Ox */
117396853b5Sschwarze 	NULL,		/* Pc */
118396853b5Sschwarze 	NULL,		/* Pf */
119396853b5Sschwarze 	NULL,		/* Po */
120396853b5Sschwarze 	NULL,		/* Pq */
121396853b5Sschwarze 	NULL,		/* Qc */
122396853b5Sschwarze 	NULL,		/* Ql */
123396853b5Sschwarze 	NULL,		/* Qo */
124396853b5Sschwarze 	NULL,		/* Qq */
125396853b5Sschwarze 	NULL,		/* Re */
126396853b5Sschwarze 	NULL,		/* Rs */
127396853b5Sschwarze 	NULL,		/* Sc */
128396853b5Sschwarze 	NULL,		/* So */
129396853b5Sschwarze 	NULL,		/* Sq */
130396853b5Sschwarze 	state_sm,	/* Sm */
131396853b5Sschwarze 	NULL,		/* Sx */
132396853b5Sschwarze 	NULL,		/* Sy */
133396853b5Sschwarze 	NULL,		/* Tn */
134396853b5Sschwarze 	NULL,		/* Ux */
135396853b5Sschwarze 	NULL,		/* Xc */
136396853b5Sschwarze 	NULL,		/* Xo */
137396853b5Sschwarze 	NULL,		/* Fo */
138396853b5Sschwarze 	NULL,		/* Fc */
139396853b5Sschwarze 	NULL,		/* Oo */
140396853b5Sschwarze 	NULL,		/* Oc */
141396853b5Sschwarze 	NULL,		/* Bk */
142396853b5Sschwarze 	NULL,		/* Ek */
143396853b5Sschwarze 	NULL,		/* Bt */
144396853b5Sschwarze 	NULL,		/* Hf */
145396853b5Sschwarze 	NULL,		/* Fr */
146396853b5Sschwarze 	NULL,		/* Ud */
147396853b5Sschwarze 	NULL,		/* Lb */
148396853b5Sschwarze 	NULL,		/* Lp */
149396853b5Sschwarze 	NULL,		/* Lk */
150396853b5Sschwarze 	NULL,		/* Mt */
151396853b5Sschwarze 	NULL,		/* Brq */
152396853b5Sschwarze 	NULL,		/* Bro */
153396853b5Sschwarze 	NULL,		/* Brc */
154396853b5Sschwarze 	NULL,		/* %C */
155396853b5Sschwarze 	NULL,		/* Es */
156396853b5Sschwarze 	NULL,		/* En */
157396853b5Sschwarze 	NULL,		/* Dx */
158396853b5Sschwarze 	NULL,		/* %Q */
159396853b5Sschwarze 	NULL,		/* %U */
160396853b5Sschwarze 	NULL,		/* Ta */
16192929bf6Sschwarze 	NULL,		/* Tg */
162396853b5Sschwarze };
163396853b5Sschwarze 
164396853b5Sschwarze 
165396853b5Sschwarze void
mdoc_state(struct roff_man * mdoc,struct roff_node * n)166396853b5Sschwarze mdoc_state(struct roff_man *mdoc, struct roff_node *n)
167396853b5Sschwarze {
168396853b5Sschwarze 	state_handler handler;
169396853b5Sschwarze 
17029478532Sschwarze 	if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
171396853b5Sschwarze 		return;
172396853b5Sschwarze 
17329478532Sschwarze 	assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
17416fe0cfcSschwarze 	if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0)
175396853b5Sschwarze 		mdoc->flags |= MDOC_PBODY;
176396853b5Sschwarze 
17716fe0cfcSschwarze 	handler = state_handlers[n->tok - MDOC_Dd];
178396853b5Sschwarze 	if (*handler)
179396853b5Sschwarze 		(*handler)(mdoc, n);
180396853b5Sschwarze }
181396853b5Sschwarze 
182396853b5Sschwarze static void
state_bl(STATE_ARGS)1833e642ba0Sschwarze state_bl(STATE_ARGS)
1843e642ba0Sschwarze {
18508be5f13Sschwarze 	struct mdoc_arg	*args;
18608be5f13Sschwarze 	size_t		 i;
1873e642ba0Sschwarze 
1883e642ba0Sschwarze 	if (n->type != ROFFT_HEAD || n->parent->args == NULL)
1893e642ba0Sschwarze 		return;
1903e642ba0Sschwarze 
19108be5f13Sschwarze 	args = n->parent->args;
19208be5f13Sschwarze 	for (i = 0; i < args->argc; i++) {
19308be5f13Sschwarze 		switch(args->argv[i].arg) {
1943e642ba0Sschwarze 		case MDOC_Diag:
1953e642ba0Sschwarze 			n->norm->Bl.type = LIST_diag;
19608be5f13Sschwarze 			return;
1973e642ba0Sschwarze 		case MDOC_Column:
1983e642ba0Sschwarze 			n->norm->Bl.type = LIST_column;
19908be5f13Sschwarze 			return;
2003e642ba0Sschwarze 		default:
2013e642ba0Sschwarze 			break;
2023e642ba0Sschwarze 		}
2033e642ba0Sschwarze 	}
20408be5f13Sschwarze }
2053e642ba0Sschwarze 
2063e642ba0Sschwarze static void
setsec(struct roff_node * n,enum roff_sec sec)207*a0c8730cSschwarze setsec(struct roff_node *n, enum roff_sec sec)
208396853b5Sschwarze {
209396853b5Sschwarze 	struct roff_node *nch;
210*a0c8730cSschwarze 
211*a0c8730cSschwarze 	n->sec = sec;
212*a0c8730cSschwarze 	for (nch = n->child; nch != NULL; nch = nch->next)
213*a0c8730cSschwarze 		setsec(nch, sec);
214*a0c8730cSschwarze }
215*a0c8730cSschwarze 
216*a0c8730cSschwarze /*
217*a0c8730cSschwarze  * Set the section attribute for the BLOCK, HEAD, and HEAD children.
218*a0c8730cSschwarze  * For other nodes, including the .Sh BODY, this is done when allocating
219*a0c8730cSschwarze  * the node data structures, but for .Sh BLOCK and HEAD, the section is
220*a0c8730cSschwarze  * still unknown at that time.
221*a0c8730cSschwarze  */
222*a0c8730cSschwarze static void
state_sh(STATE_ARGS)223*a0c8730cSschwarze state_sh(STATE_ARGS)
224*a0c8730cSschwarze {
225*a0c8730cSschwarze 	enum roff_sec sec;
226396853b5Sschwarze 
227396853b5Sschwarze 	if (n->type != ROFFT_HEAD)
228396853b5Sschwarze 		return;
229396853b5Sschwarze 
230*a0c8730cSschwarze 	if ((n->flags & NODE_VALID) == 0) {
231*a0c8730cSschwarze 		sec = n->child != NULL && n->child->type == ROFFT_TEXT &&
232*a0c8730cSschwarze 		    n->child->next == NULL ? mdoc_a2sec(n->child->string) :
233*a0c8730cSschwarze 		    SEC_CUSTOM;
234*a0c8730cSschwarze 		n->parent->sec = sec;
235*a0c8730cSschwarze 		setsec(n, sec);
236396853b5Sschwarze 	}
237396853b5Sschwarze 	if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
238396853b5Sschwarze 		roff_setreg(mdoc->roff, "nS", 1, '=');
239396853b5Sschwarze 		mdoc->flags |= MDOC_SYNOPSIS;
240396853b5Sschwarze 	} else {
241396853b5Sschwarze 		roff_setreg(mdoc->roff, "nS", 0, '=');
242396853b5Sschwarze 		mdoc->flags &= ~MDOC_SYNOPSIS;
243396853b5Sschwarze 	}
244396853b5Sschwarze }
245396853b5Sschwarze 
246396853b5Sschwarze static void
state_sm(STATE_ARGS)247396853b5Sschwarze state_sm(STATE_ARGS)
248396853b5Sschwarze {
249396853b5Sschwarze 
250396853b5Sschwarze 	if (n->child == NULL)
251396853b5Sschwarze 		mdoc->flags ^= MDOC_SMOFF;
252396853b5Sschwarze 	else if ( ! strcmp(n->child->string, "on"))
253396853b5Sschwarze 		mdoc->flags &= ~MDOC_SMOFF;
254396853b5Sschwarze 	else if ( ! strcmp(n->child->string, "off"))
255396853b5Sschwarze 		mdoc->flags |= MDOC_SMOFF;
256396853b5Sschwarze }
257