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