xref: /freebsd/contrib/mandoc/mdoc_state.c (revision 6d38604fc532a3fc060788e3ce40464b46047eaf)
1*6d38604fSBaptiste Daroussin /* $Id: mdoc_state.c,v 1.17 2020/06/22 19:20:40 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
361d06d6bSBaptiste Daroussin  * Copyright (c) 2014, 2015, 2017 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  */
17*6d38604fSBaptiste Daroussin #include "config.h"
18*6d38604fSBaptiste 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 
2661d06d6bSBaptiste Daroussin #include "mandoc.h"
2761d06d6bSBaptiste Daroussin #include "roff.h"
2861d06d6bSBaptiste Daroussin #include "mdoc.h"
2961d06d6bSBaptiste Daroussin #include "libmandoc.h"
307295610fSBaptiste Daroussin #include "roff_int.h"
3161d06d6bSBaptiste Daroussin #include "libmdoc.h"
3261d06d6bSBaptiste Daroussin 
3361d06d6bSBaptiste Daroussin #define STATE_ARGS  struct roff_man *mdoc, struct roff_node *n
3461d06d6bSBaptiste Daroussin 
3561d06d6bSBaptiste Daroussin typedef	void	(*state_handler)(STATE_ARGS);
3661d06d6bSBaptiste Daroussin 
3761d06d6bSBaptiste Daroussin static	void	 state_bl(STATE_ARGS);
3861d06d6bSBaptiste Daroussin static	void	 state_sh(STATE_ARGS);
3961d06d6bSBaptiste Daroussin static	void	 state_sm(STATE_ARGS);
4061d06d6bSBaptiste Daroussin 
417295610fSBaptiste Daroussin static	const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = {
4261d06d6bSBaptiste Daroussin 	NULL,		/* Dd */
4361d06d6bSBaptiste Daroussin 	NULL,		/* Dt */
4461d06d6bSBaptiste Daroussin 	NULL,		/* Os */
4561d06d6bSBaptiste Daroussin 	state_sh,	/* Sh */
4661d06d6bSBaptiste Daroussin 	NULL,		/* Ss */
4761d06d6bSBaptiste Daroussin 	NULL,		/* Pp */
4861d06d6bSBaptiste Daroussin 	NULL,		/* D1 */
497295610fSBaptiste Daroussin 	NULL,		/* Dl */
507295610fSBaptiste Daroussin 	NULL,		/* Bd */
5161d06d6bSBaptiste Daroussin 	NULL,		/* Ed */
5261d06d6bSBaptiste Daroussin 	state_bl,	/* Bl */
5361d06d6bSBaptiste Daroussin 	NULL,		/* El */
5461d06d6bSBaptiste Daroussin 	NULL,		/* It */
5561d06d6bSBaptiste Daroussin 	NULL,		/* Ad */
5661d06d6bSBaptiste Daroussin 	NULL,		/* An */
5761d06d6bSBaptiste Daroussin 	NULL,		/* Ap */
5861d06d6bSBaptiste Daroussin 	NULL,		/* Ar */
5961d06d6bSBaptiste Daroussin 	NULL,		/* Cd */
6061d06d6bSBaptiste Daroussin 	NULL,		/* Cm */
6161d06d6bSBaptiste Daroussin 	NULL,		/* Dv */
6261d06d6bSBaptiste Daroussin 	NULL,		/* Er */
6361d06d6bSBaptiste Daroussin 	NULL,		/* Ev */
6461d06d6bSBaptiste Daroussin 	NULL,		/* Ex */
6561d06d6bSBaptiste Daroussin 	NULL,		/* Fa */
6661d06d6bSBaptiste Daroussin 	NULL,		/* Fd */
6761d06d6bSBaptiste Daroussin 	NULL,		/* Fl */
6861d06d6bSBaptiste Daroussin 	NULL,		/* Fn */
6961d06d6bSBaptiste Daroussin 	NULL,		/* Ft */
7061d06d6bSBaptiste Daroussin 	NULL,		/* Ic */
7161d06d6bSBaptiste Daroussin 	NULL,		/* In */
7261d06d6bSBaptiste Daroussin 	NULL,		/* Li */
7361d06d6bSBaptiste Daroussin 	NULL,		/* Nd */
7461d06d6bSBaptiste Daroussin 	NULL,		/* Nm */
7561d06d6bSBaptiste Daroussin 	NULL,		/* Op */
7661d06d6bSBaptiste Daroussin 	NULL,		/* Ot */
7761d06d6bSBaptiste Daroussin 	NULL,		/* Pa */
7861d06d6bSBaptiste Daroussin 	NULL,		/* Rv */
7961d06d6bSBaptiste Daroussin 	NULL,		/* St */
8061d06d6bSBaptiste Daroussin 	NULL,		/* Va */
8161d06d6bSBaptiste Daroussin 	NULL,		/* Vt */
8261d06d6bSBaptiste Daroussin 	NULL,		/* Xr */
8361d06d6bSBaptiste Daroussin 	NULL,		/* %A */
8461d06d6bSBaptiste Daroussin 	NULL,		/* %B */
8561d06d6bSBaptiste Daroussin 	NULL,		/* %D */
8661d06d6bSBaptiste Daroussin 	NULL,		/* %I */
8761d06d6bSBaptiste Daroussin 	NULL,		/* %J */
8861d06d6bSBaptiste Daroussin 	NULL,		/* %N */
8961d06d6bSBaptiste Daroussin 	NULL,		/* %O */
9061d06d6bSBaptiste Daroussin 	NULL,		/* %P */
9161d06d6bSBaptiste Daroussin 	NULL,		/* %R */
9261d06d6bSBaptiste Daroussin 	NULL,		/* %T */
9361d06d6bSBaptiste Daroussin 	NULL,		/* %V */
9461d06d6bSBaptiste Daroussin 	NULL,		/* Ac */
9561d06d6bSBaptiste Daroussin 	NULL,		/* Ao */
9661d06d6bSBaptiste Daroussin 	NULL,		/* Aq */
9761d06d6bSBaptiste Daroussin 	NULL,		/* At */
9861d06d6bSBaptiste Daroussin 	NULL,		/* Bc */
9961d06d6bSBaptiste Daroussin 	NULL,		/* Bf */
10061d06d6bSBaptiste Daroussin 	NULL,		/* Bo */
10161d06d6bSBaptiste Daroussin 	NULL,		/* Bq */
10261d06d6bSBaptiste Daroussin 	NULL,		/* Bsx */
10361d06d6bSBaptiste Daroussin 	NULL,		/* Bx */
10461d06d6bSBaptiste Daroussin 	NULL,		/* Db */
10561d06d6bSBaptiste Daroussin 	NULL,		/* Dc */
10661d06d6bSBaptiste Daroussin 	NULL,		/* Do */
10761d06d6bSBaptiste Daroussin 	NULL,		/* Dq */
10861d06d6bSBaptiste Daroussin 	NULL,		/* Ec */
10961d06d6bSBaptiste Daroussin 	NULL,		/* Ef */
11061d06d6bSBaptiste Daroussin 	NULL,		/* Em */
11161d06d6bSBaptiste Daroussin 	NULL,		/* Eo */
11261d06d6bSBaptiste Daroussin 	NULL,		/* Fx */
11361d06d6bSBaptiste Daroussin 	NULL,		/* Ms */
11461d06d6bSBaptiste Daroussin 	NULL,		/* No */
11561d06d6bSBaptiste Daroussin 	NULL,		/* Ns */
11661d06d6bSBaptiste Daroussin 	NULL,		/* Nx */
11761d06d6bSBaptiste Daroussin 	NULL,		/* Ox */
11861d06d6bSBaptiste Daroussin 	NULL,		/* Pc */
11961d06d6bSBaptiste Daroussin 	NULL,		/* Pf */
12061d06d6bSBaptiste Daroussin 	NULL,		/* Po */
12161d06d6bSBaptiste Daroussin 	NULL,		/* Pq */
12261d06d6bSBaptiste Daroussin 	NULL,		/* Qc */
12361d06d6bSBaptiste Daroussin 	NULL,		/* Ql */
12461d06d6bSBaptiste Daroussin 	NULL,		/* Qo */
12561d06d6bSBaptiste Daroussin 	NULL,		/* Qq */
12661d06d6bSBaptiste Daroussin 	NULL,		/* Re */
12761d06d6bSBaptiste Daroussin 	NULL,		/* Rs */
12861d06d6bSBaptiste Daroussin 	NULL,		/* Sc */
12961d06d6bSBaptiste Daroussin 	NULL,		/* So */
13061d06d6bSBaptiste Daroussin 	NULL,		/* Sq */
13161d06d6bSBaptiste Daroussin 	state_sm,	/* Sm */
13261d06d6bSBaptiste Daroussin 	NULL,		/* Sx */
13361d06d6bSBaptiste Daroussin 	NULL,		/* Sy */
13461d06d6bSBaptiste Daroussin 	NULL,		/* Tn */
13561d06d6bSBaptiste Daroussin 	NULL,		/* Ux */
13661d06d6bSBaptiste Daroussin 	NULL,		/* Xc */
13761d06d6bSBaptiste Daroussin 	NULL,		/* Xo */
13861d06d6bSBaptiste Daroussin 	NULL,		/* Fo */
13961d06d6bSBaptiste Daroussin 	NULL,		/* Fc */
14061d06d6bSBaptiste Daroussin 	NULL,		/* Oo */
14161d06d6bSBaptiste Daroussin 	NULL,		/* Oc */
14261d06d6bSBaptiste Daroussin 	NULL,		/* Bk */
14361d06d6bSBaptiste Daroussin 	NULL,		/* Ek */
14461d06d6bSBaptiste Daroussin 	NULL,		/* Bt */
14561d06d6bSBaptiste Daroussin 	NULL,		/* Hf */
14661d06d6bSBaptiste Daroussin 	NULL,		/* Fr */
14761d06d6bSBaptiste Daroussin 	NULL,		/* Ud */
14861d06d6bSBaptiste Daroussin 	NULL,		/* Lb */
14961d06d6bSBaptiste Daroussin 	NULL,		/* Lp */
15061d06d6bSBaptiste Daroussin 	NULL,		/* Lk */
15161d06d6bSBaptiste Daroussin 	NULL,		/* Mt */
15261d06d6bSBaptiste Daroussin 	NULL,		/* Brq */
15361d06d6bSBaptiste Daroussin 	NULL,		/* Bro */
15461d06d6bSBaptiste Daroussin 	NULL,		/* Brc */
15561d06d6bSBaptiste Daroussin 	NULL,		/* %C */
15661d06d6bSBaptiste Daroussin 	NULL,		/* Es */
15761d06d6bSBaptiste Daroussin 	NULL,		/* En */
15861d06d6bSBaptiste Daroussin 	NULL,		/* Dx */
15961d06d6bSBaptiste Daroussin 	NULL,		/* %Q */
16061d06d6bSBaptiste Daroussin 	NULL,		/* %U */
16161d06d6bSBaptiste Daroussin 	NULL,		/* Ta */
162*6d38604fSBaptiste Daroussin 	NULL,		/* Tg */
16361d06d6bSBaptiste Daroussin };
16461d06d6bSBaptiste Daroussin 
16561d06d6bSBaptiste Daroussin 
16661d06d6bSBaptiste Daroussin void
16761d06d6bSBaptiste Daroussin mdoc_state(struct roff_man *mdoc, struct roff_node *n)
16861d06d6bSBaptiste Daroussin {
16961d06d6bSBaptiste Daroussin 	state_handler handler;
17061d06d6bSBaptiste Daroussin 
17161d06d6bSBaptiste Daroussin 	if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
17261d06d6bSBaptiste Daroussin 		return;
17361d06d6bSBaptiste Daroussin 
17461d06d6bSBaptiste Daroussin 	assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
1757295610fSBaptiste Daroussin 	if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0)
17661d06d6bSBaptiste Daroussin 		mdoc->flags |= MDOC_PBODY;
17761d06d6bSBaptiste Daroussin 
1787295610fSBaptiste Daroussin 	handler = state_handlers[n->tok - MDOC_Dd];
17961d06d6bSBaptiste Daroussin 	if (*handler)
18061d06d6bSBaptiste Daroussin 		(*handler)(mdoc, n);
18161d06d6bSBaptiste Daroussin }
18261d06d6bSBaptiste Daroussin 
18361d06d6bSBaptiste Daroussin static void
18461d06d6bSBaptiste Daroussin state_bl(STATE_ARGS)
18561d06d6bSBaptiste Daroussin {
18661d06d6bSBaptiste Daroussin 	struct mdoc_arg	*args;
18761d06d6bSBaptiste Daroussin 	size_t		 i;
18861d06d6bSBaptiste Daroussin 
18961d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_HEAD || n->parent->args == NULL)
19061d06d6bSBaptiste Daroussin 		return;
19161d06d6bSBaptiste Daroussin 
19261d06d6bSBaptiste Daroussin 	args = n->parent->args;
19361d06d6bSBaptiste Daroussin 	for (i = 0; i < args->argc; i++) {
19461d06d6bSBaptiste Daroussin 		switch(args->argv[i].arg) {
19561d06d6bSBaptiste Daroussin 		case MDOC_Diag:
19661d06d6bSBaptiste Daroussin 			n->norm->Bl.type = LIST_diag;
19761d06d6bSBaptiste Daroussin 			return;
19861d06d6bSBaptiste Daroussin 		case MDOC_Column:
19961d06d6bSBaptiste Daroussin 			n->norm->Bl.type = LIST_column;
20061d06d6bSBaptiste Daroussin 			return;
20161d06d6bSBaptiste Daroussin 		default:
20261d06d6bSBaptiste Daroussin 			break;
20361d06d6bSBaptiste Daroussin 		}
20461d06d6bSBaptiste Daroussin 	}
20561d06d6bSBaptiste Daroussin }
20661d06d6bSBaptiste Daroussin 
20761d06d6bSBaptiste Daroussin static void
20861d06d6bSBaptiste Daroussin state_sh(STATE_ARGS)
20961d06d6bSBaptiste Daroussin {
21061d06d6bSBaptiste Daroussin 	struct roff_node *nch;
21161d06d6bSBaptiste Daroussin 	char		 *secname;
21261d06d6bSBaptiste Daroussin 
21361d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_HEAD)
21461d06d6bSBaptiste Daroussin 		return;
21561d06d6bSBaptiste Daroussin 
21661d06d6bSBaptiste Daroussin 	if ( ! (n->flags & NODE_VALID)) {
21761d06d6bSBaptiste Daroussin 		secname = NULL;
21861d06d6bSBaptiste Daroussin 		deroff(&secname, n);
21961d06d6bSBaptiste Daroussin 
22061d06d6bSBaptiste Daroussin 		/*
22161d06d6bSBaptiste Daroussin 		 * Set the section attribute for the BLOCK, HEAD,
22261d06d6bSBaptiste Daroussin 		 * and HEAD children; the latter can only be TEXT
22361d06d6bSBaptiste Daroussin 		 * nodes, so no recursion is needed.  For other
22461d06d6bSBaptiste Daroussin 		 * nodes, including the .Sh BODY, this is done
22561d06d6bSBaptiste Daroussin 		 * when allocating the node data structures, but
22661d06d6bSBaptiste Daroussin 		 * for .Sh BLOCK and HEAD, the section is still
22761d06d6bSBaptiste Daroussin 		 * unknown at that time.
22861d06d6bSBaptiste Daroussin 		 */
22961d06d6bSBaptiste Daroussin 
23061d06d6bSBaptiste Daroussin 		n->sec = n->parent->sec = secname == NULL ?
23161d06d6bSBaptiste Daroussin 		    SEC_CUSTOM : mdoc_a2sec(secname);
23261d06d6bSBaptiste Daroussin 		for (nch = n->child; nch != NULL; nch = nch->next)
23361d06d6bSBaptiste Daroussin 			nch->sec = n->sec;
23461d06d6bSBaptiste Daroussin 		free(secname);
23561d06d6bSBaptiste Daroussin 	}
23661d06d6bSBaptiste Daroussin 
23761d06d6bSBaptiste Daroussin 	if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
23861d06d6bSBaptiste Daroussin 		roff_setreg(mdoc->roff, "nS", 1, '=');
23961d06d6bSBaptiste Daroussin 		mdoc->flags |= MDOC_SYNOPSIS;
24061d06d6bSBaptiste Daroussin 	} else {
24161d06d6bSBaptiste Daroussin 		roff_setreg(mdoc->roff, "nS", 0, '=');
24261d06d6bSBaptiste Daroussin 		mdoc->flags &= ~MDOC_SYNOPSIS;
24361d06d6bSBaptiste Daroussin 	}
24461d06d6bSBaptiste Daroussin }
24561d06d6bSBaptiste Daroussin 
24661d06d6bSBaptiste Daroussin static void
24761d06d6bSBaptiste Daroussin state_sm(STATE_ARGS)
24861d06d6bSBaptiste Daroussin {
24961d06d6bSBaptiste Daroussin 
25061d06d6bSBaptiste Daroussin 	if (n->child == NULL)
25161d06d6bSBaptiste Daroussin 		mdoc->flags ^= MDOC_SMOFF;
25261d06d6bSBaptiste Daroussin 	else if ( ! strcmp(n->child->string, "on"))
25361d06d6bSBaptiste Daroussin 		mdoc->flags &= ~MDOC_SMOFF;
25461d06d6bSBaptiste Daroussin 	else if ( ! strcmp(n->child->string, "off"))
25561d06d6bSBaptiste Daroussin 		mdoc->flags |= MDOC_SMOFF;
25661d06d6bSBaptiste Daroussin }
257