xref: /freebsd/contrib/mandoc/mdoc_state.c (revision c1c95add8c80843ba15d784f95c361d795b1f593)
1*c1c95addSBrooks Davis /* $Id: mdoc_state.c,v 1.19 2022/08/19 12:59:26 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
3*c1c95addSBrooks Davis  * Copyright (c) 2014,2015,2017,2018,2022 Ingo Schwarze <schwarze@openbsd.org>
461d06d6bSBaptiste Daroussin  *
561d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
661d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
761d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
861d06d6bSBaptiste Daroussin  *
961d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1061d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1161d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1261d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1361d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1461d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1561d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1661d06d6bSBaptiste Daroussin  */
176d38604fSBaptiste Daroussin #include "config.h"
186d38604fSBaptiste Daroussin 
1961d06d6bSBaptiste Daroussin #include <sys/types.h>
2061d06d6bSBaptiste Daroussin 
2161d06d6bSBaptiste Daroussin #include <assert.h>
227295610fSBaptiste Daroussin #include <stdio.h>
2361d06d6bSBaptiste Daroussin #include <stdlib.h>
2461d06d6bSBaptiste Daroussin #include <string.h>
2561d06d6bSBaptiste Daroussin 
26*c1c95addSBrooks Davis #if DEBUG_MEMORY
27*c1c95addSBrooks Davis #include "mandoc_dbg.h"
28*c1c95addSBrooks Davis #endif
2961d06d6bSBaptiste Daroussin #include "mandoc.h"
3061d06d6bSBaptiste Daroussin #include "roff.h"
3161d06d6bSBaptiste Daroussin #include "mdoc.h"
3261d06d6bSBaptiste Daroussin #include "libmandoc.h"
337295610fSBaptiste Daroussin #include "roff_int.h"
3461d06d6bSBaptiste Daroussin #include "libmdoc.h"
3561d06d6bSBaptiste Daroussin 
3661d06d6bSBaptiste Daroussin #define STATE_ARGS  struct roff_man *mdoc, struct roff_node *n
3761d06d6bSBaptiste Daroussin 
3861d06d6bSBaptiste Daroussin typedef	void	(*state_handler)(STATE_ARGS);
3961d06d6bSBaptiste Daroussin 
40*c1c95addSBrooks Davis static	void	 setsec(struct roff_node *, enum roff_sec);
4161d06d6bSBaptiste Daroussin static	void	 state_bl(STATE_ARGS);
4261d06d6bSBaptiste Daroussin static	void	 state_sh(STATE_ARGS);
4361d06d6bSBaptiste Daroussin static	void	 state_sm(STATE_ARGS);
4461d06d6bSBaptiste Daroussin 
457295610fSBaptiste Daroussin static	const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = {
4661d06d6bSBaptiste Daroussin 	NULL,		/* Dd */
4761d06d6bSBaptiste Daroussin 	NULL,		/* Dt */
4861d06d6bSBaptiste Daroussin 	NULL,		/* Os */
4961d06d6bSBaptiste Daroussin 	state_sh,	/* Sh */
5061d06d6bSBaptiste Daroussin 	NULL,		/* Ss */
5161d06d6bSBaptiste Daroussin 	NULL,		/* Pp */
5261d06d6bSBaptiste Daroussin 	NULL,		/* D1 */
537295610fSBaptiste Daroussin 	NULL,		/* Dl */
547295610fSBaptiste Daroussin 	NULL,		/* Bd */
5561d06d6bSBaptiste Daroussin 	NULL,		/* Ed */
5661d06d6bSBaptiste Daroussin 	state_bl,	/* Bl */
5761d06d6bSBaptiste Daroussin 	NULL,		/* El */
5861d06d6bSBaptiste Daroussin 	NULL,		/* It */
5961d06d6bSBaptiste Daroussin 	NULL,		/* Ad */
6061d06d6bSBaptiste Daroussin 	NULL,		/* An */
6161d06d6bSBaptiste Daroussin 	NULL,		/* Ap */
6261d06d6bSBaptiste Daroussin 	NULL,		/* Ar */
6361d06d6bSBaptiste Daroussin 	NULL,		/* Cd */
6461d06d6bSBaptiste Daroussin 	NULL,		/* Cm */
6561d06d6bSBaptiste Daroussin 	NULL,		/* Dv */
6661d06d6bSBaptiste Daroussin 	NULL,		/* Er */
6761d06d6bSBaptiste Daroussin 	NULL,		/* Ev */
6861d06d6bSBaptiste Daroussin 	NULL,		/* Ex */
6961d06d6bSBaptiste Daroussin 	NULL,		/* Fa */
7061d06d6bSBaptiste Daroussin 	NULL,		/* Fd */
7161d06d6bSBaptiste Daroussin 	NULL,		/* Fl */
7261d06d6bSBaptiste Daroussin 	NULL,		/* Fn */
7361d06d6bSBaptiste Daroussin 	NULL,		/* Ft */
7461d06d6bSBaptiste Daroussin 	NULL,		/* Ic */
7561d06d6bSBaptiste Daroussin 	NULL,		/* In */
7661d06d6bSBaptiste Daroussin 	NULL,		/* Li */
7761d06d6bSBaptiste Daroussin 	NULL,		/* Nd */
7861d06d6bSBaptiste Daroussin 	NULL,		/* Nm */
7961d06d6bSBaptiste Daroussin 	NULL,		/* Op */
8061d06d6bSBaptiste Daroussin 	NULL,		/* Ot */
8161d06d6bSBaptiste Daroussin 	NULL,		/* Pa */
8261d06d6bSBaptiste Daroussin 	NULL,		/* Rv */
8361d06d6bSBaptiste Daroussin 	NULL,		/* St */
8461d06d6bSBaptiste Daroussin 	NULL,		/* Va */
8561d06d6bSBaptiste Daroussin 	NULL,		/* Vt */
8661d06d6bSBaptiste Daroussin 	NULL,		/* Xr */
8761d06d6bSBaptiste Daroussin 	NULL,		/* %A */
8861d06d6bSBaptiste Daroussin 	NULL,		/* %B */
8961d06d6bSBaptiste Daroussin 	NULL,		/* %D */
9061d06d6bSBaptiste Daroussin 	NULL,		/* %I */
9161d06d6bSBaptiste Daroussin 	NULL,		/* %J */
9261d06d6bSBaptiste Daroussin 	NULL,		/* %N */
9361d06d6bSBaptiste Daroussin 	NULL,		/* %O */
9461d06d6bSBaptiste Daroussin 	NULL,		/* %P */
9561d06d6bSBaptiste Daroussin 	NULL,		/* %R */
9661d06d6bSBaptiste Daroussin 	NULL,		/* %T */
9761d06d6bSBaptiste Daroussin 	NULL,		/* %V */
9861d06d6bSBaptiste Daroussin 	NULL,		/* Ac */
9961d06d6bSBaptiste Daroussin 	NULL,		/* Ao */
10061d06d6bSBaptiste Daroussin 	NULL,		/* Aq */
10161d06d6bSBaptiste Daroussin 	NULL,		/* At */
10261d06d6bSBaptiste Daroussin 	NULL,		/* Bc */
10361d06d6bSBaptiste Daroussin 	NULL,		/* Bf */
10461d06d6bSBaptiste Daroussin 	NULL,		/* Bo */
10561d06d6bSBaptiste Daroussin 	NULL,		/* Bq */
10661d06d6bSBaptiste Daroussin 	NULL,		/* Bsx */
10761d06d6bSBaptiste Daroussin 	NULL,		/* Bx */
10861d06d6bSBaptiste Daroussin 	NULL,		/* Db */
10961d06d6bSBaptiste Daroussin 	NULL,		/* Dc */
11061d06d6bSBaptiste Daroussin 	NULL,		/* Do */
11161d06d6bSBaptiste Daroussin 	NULL,		/* Dq */
11261d06d6bSBaptiste Daroussin 	NULL,		/* Ec */
11361d06d6bSBaptiste Daroussin 	NULL,		/* Ef */
11461d06d6bSBaptiste Daroussin 	NULL,		/* Em */
11561d06d6bSBaptiste Daroussin 	NULL,		/* Eo */
11661d06d6bSBaptiste Daroussin 	NULL,		/* Fx */
11761d06d6bSBaptiste Daroussin 	NULL,		/* Ms */
11861d06d6bSBaptiste Daroussin 	NULL,		/* No */
11961d06d6bSBaptiste Daroussin 	NULL,		/* Ns */
12061d06d6bSBaptiste Daroussin 	NULL,		/* Nx */
12161d06d6bSBaptiste Daroussin 	NULL,		/* Ox */
12261d06d6bSBaptiste Daroussin 	NULL,		/* Pc */
12361d06d6bSBaptiste Daroussin 	NULL,		/* Pf */
12461d06d6bSBaptiste Daroussin 	NULL,		/* Po */
12561d06d6bSBaptiste Daroussin 	NULL,		/* Pq */
12661d06d6bSBaptiste Daroussin 	NULL,		/* Qc */
12761d06d6bSBaptiste Daroussin 	NULL,		/* Ql */
12861d06d6bSBaptiste Daroussin 	NULL,		/* Qo */
12961d06d6bSBaptiste Daroussin 	NULL,		/* Qq */
13061d06d6bSBaptiste Daroussin 	NULL,		/* Re */
13161d06d6bSBaptiste Daroussin 	NULL,		/* Rs */
13261d06d6bSBaptiste Daroussin 	NULL,		/* Sc */
13361d06d6bSBaptiste Daroussin 	NULL,		/* So */
13461d06d6bSBaptiste Daroussin 	NULL,		/* Sq */
13561d06d6bSBaptiste Daroussin 	state_sm,	/* Sm */
13661d06d6bSBaptiste Daroussin 	NULL,		/* Sx */
13761d06d6bSBaptiste Daroussin 	NULL,		/* Sy */
13861d06d6bSBaptiste Daroussin 	NULL,		/* Tn */
13961d06d6bSBaptiste Daroussin 	NULL,		/* Ux */
14061d06d6bSBaptiste Daroussin 	NULL,		/* Xc */
14161d06d6bSBaptiste Daroussin 	NULL,		/* Xo */
14261d06d6bSBaptiste Daroussin 	NULL,		/* Fo */
14361d06d6bSBaptiste Daroussin 	NULL,		/* Fc */
14461d06d6bSBaptiste Daroussin 	NULL,		/* Oo */
14561d06d6bSBaptiste Daroussin 	NULL,		/* Oc */
14661d06d6bSBaptiste Daroussin 	NULL,		/* Bk */
14761d06d6bSBaptiste Daroussin 	NULL,		/* Ek */
14861d06d6bSBaptiste Daroussin 	NULL,		/* Bt */
14961d06d6bSBaptiste Daroussin 	NULL,		/* Hf */
15061d06d6bSBaptiste Daroussin 	NULL,		/* Fr */
15161d06d6bSBaptiste Daroussin 	NULL,		/* Ud */
15261d06d6bSBaptiste Daroussin 	NULL,		/* Lb */
15361d06d6bSBaptiste Daroussin 	NULL,		/* Lp */
15461d06d6bSBaptiste Daroussin 	NULL,		/* Lk */
15561d06d6bSBaptiste Daroussin 	NULL,		/* Mt */
15661d06d6bSBaptiste Daroussin 	NULL,		/* Brq */
15761d06d6bSBaptiste Daroussin 	NULL,		/* Bro */
15861d06d6bSBaptiste Daroussin 	NULL,		/* Brc */
15961d06d6bSBaptiste Daroussin 	NULL,		/* %C */
16061d06d6bSBaptiste Daroussin 	NULL,		/* Es */
16161d06d6bSBaptiste Daroussin 	NULL,		/* En */
16261d06d6bSBaptiste Daroussin 	NULL,		/* Dx */
16361d06d6bSBaptiste Daroussin 	NULL,		/* %Q */
16461d06d6bSBaptiste Daroussin 	NULL,		/* %U */
16561d06d6bSBaptiste Daroussin 	NULL,		/* Ta */
1666d38604fSBaptiste Daroussin 	NULL,		/* Tg */
16761d06d6bSBaptiste Daroussin };
16861d06d6bSBaptiste Daroussin 
16961d06d6bSBaptiste Daroussin 
17061d06d6bSBaptiste Daroussin void
mdoc_state(struct roff_man * mdoc,struct roff_node * n)17161d06d6bSBaptiste Daroussin mdoc_state(struct roff_man *mdoc, struct roff_node *n)
17261d06d6bSBaptiste Daroussin {
17361d06d6bSBaptiste Daroussin 	state_handler handler;
17461d06d6bSBaptiste Daroussin 
17561d06d6bSBaptiste Daroussin 	if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
17661d06d6bSBaptiste Daroussin 		return;
17761d06d6bSBaptiste Daroussin 
17861d06d6bSBaptiste Daroussin 	assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
1797295610fSBaptiste Daroussin 	if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0)
18061d06d6bSBaptiste Daroussin 		mdoc->flags |= MDOC_PBODY;
18161d06d6bSBaptiste Daroussin 
1827295610fSBaptiste Daroussin 	handler = state_handlers[n->tok - MDOC_Dd];
18361d06d6bSBaptiste Daroussin 	if (*handler)
18461d06d6bSBaptiste Daroussin 		(*handler)(mdoc, n);
18561d06d6bSBaptiste Daroussin }
18661d06d6bSBaptiste Daroussin 
18761d06d6bSBaptiste Daroussin static void
state_bl(STATE_ARGS)18861d06d6bSBaptiste Daroussin state_bl(STATE_ARGS)
18961d06d6bSBaptiste Daroussin {
19061d06d6bSBaptiste Daroussin 	struct mdoc_arg	*args;
19161d06d6bSBaptiste Daroussin 	size_t		 i;
19261d06d6bSBaptiste Daroussin 
19361d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_HEAD || n->parent->args == NULL)
19461d06d6bSBaptiste Daroussin 		return;
19561d06d6bSBaptiste Daroussin 
19661d06d6bSBaptiste Daroussin 	args = n->parent->args;
19761d06d6bSBaptiste Daroussin 	for (i = 0; i < args->argc; i++) {
19861d06d6bSBaptiste Daroussin 		switch(args->argv[i].arg) {
19961d06d6bSBaptiste Daroussin 		case MDOC_Diag:
20061d06d6bSBaptiste Daroussin 			n->norm->Bl.type = LIST_diag;
20161d06d6bSBaptiste Daroussin 			return;
20261d06d6bSBaptiste Daroussin 		case MDOC_Column:
20361d06d6bSBaptiste Daroussin 			n->norm->Bl.type = LIST_column;
20461d06d6bSBaptiste Daroussin 			return;
20561d06d6bSBaptiste Daroussin 		default:
20661d06d6bSBaptiste Daroussin 			break;
20761d06d6bSBaptiste Daroussin 		}
20861d06d6bSBaptiste Daroussin 	}
20961d06d6bSBaptiste Daroussin }
21061d06d6bSBaptiste Daroussin 
21161d06d6bSBaptiste Daroussin static void
setsec(struct roff_node * n,enum roff_sec sec)212*c1c95addSBrooks Davis setsec(struct roff_node *n, enum roff_sec sec)
21361d06d6bSBaptiste Daroussin {
21461d06d6bSBaptiste Daroussin 	struct roff_node *nch;
215*c1c95addSBrooks Davis 
216*c1c95addSBrooks Davis 	n->sec = sec;
217*c1c95addSBrooks Davis 	for (nch = n->child; nch != NULL; nch = nch->next)
218*c1c95addSBrooks Davis 		setsec(nch, sec);
219*c1c95addSBrooks Davis }
220*c1c95addSBrooks Davis 
221*c1c95addSBrooks Davis /*
222*c1c95addSBrooks Davis  * Set the section attribute for the BLOCK, HEAD, and HEAD children.
223*c1c95addSBrooks Davis  * For other nodes, including the .Sh BODY, this is done when allocating
224*c1c95addSBrooks Davis  * the node data structures, but for .Sh BLOCK and HEAD, the section is
225*c1c95addSBrooks Davis  * still unknown at that time.
226*c1c95addSBrooks Davis  */
227*c1c95addSBrooks Davis static void
state_sh(STATE_ARGS)228*c1c95addSBrooks Davis state_sh(STATE_ARGS)
229*c1c95addSBrooks Davis {
230*c1c95addSBrooks Davis 	enum roff_sec sec;
23161d06d6bSBaptiste Daroussin 
23261d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_HEAD)
23361d06d6bSBaptiste Daroussin 		return;
23461d06d6bSBaptiste Daroussin 
235*c1c95addSBrooks Davis 	if ((n->flags & NODE_VALID) == 0) {
236*c1c95addSBrooks Davis 		sec = n->child != NULL && n->child->type == ROFFT_TEXT &&
237*c1c95addSBrooks Davis 		    n->child->next == NULL ? mdoc_a2sec(n->child->string) :
238*c1c95addSBrooks Davis 		    SEC_CUSTOM;
239*c1c95addSBrooks Davis 		n->parent->sec = sec;
240*c1c95addSBrooks Davis 		setsec(n, sec);
24161d06d6bSBaptiste Daroussin 	}
24261d06d6bSBaptiste Daroussin 	if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
24361d06d6bSBaptiste Daroussin 		roff_setreg(mdoc->roff, "nS", 1, '=');
24461d06d6bSBaptiste Daroussin 		mdoc->flags |= MDOC_SYNOPSIS;
24561d06d6bSBaptiste Daroussin 	} else {
24661d06d6bSBaptiste Daroussin 		roff_setreg(mdoc->roff, "nS", 0, '=');
24761d06d6bSBaptiste Daroussin 		mdoc->flags &= ~MDOC_SYNOPSIS;
24861d06d6bSBaptiste Daroussin 	}
24961d06d6bSBaptiste Daroussin }
25061d06d6bSBaptiste Daroussin 
25161d06d6bSBaptiste Daroussin static void
state_sm(STATE_ARGS)25261d06d6bSBaptiste Daroussin state_sm(STATE_ARGS)
25361d06d6bSBaptiste Daroussin {
25461d06d6bSBaptiste Daroussin 
25561d06d6bSBaptiste Daroussin 	if (n->child == NULL)
25661d06d6bSBaptiste Daroussin 		mdoc->flags ^= MDOC_SMOFF;
25761d06d6bSBaptiste Daroussin 	else if ( ! strcmp(n->child->string, "on"))
25861d06d6bSBaptiste Daroussin 		mdoc->flags &= ~MDOC_SMOFF;
25961d06d6bSBaptiste Daroussin 	else if ( ! strcmp(n->child->string, "off"))
26061d06d6bSBaptiste Daroussin 		mdoc->flags |= MDOC_SMOFF;
26161d06d6bSBaptiste Daroussin }
262