1*99db7d0eSSascha Wildner /* $Id: mdoc_state.c,v 1.17 2020/06/22 19:20:40 schwarze Exp $ */
254ba9607SSascha Wildner /*
354ba9607SSascha Wildner * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
454ba9607SSascha Wildner *
554ba9607SSascha Wildner * Permission to use, copy, modify, and distribute this software for any
654ba9607SSascha Wildner * purpose with or without fee is hereby granted, provided that the above
754ba9607SSascha Wildner * copyright notice and this permission notice appear in all copies.
854ba9607SSascha Wildner *
954ba9607SSascha Wildner * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1054ba9607SSascha Wildner * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1154ba9607SSascha Wildner * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1254ba9607SSascha Wildner * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1354ba9607SSascha Wildner * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1454ba9607SSascha Wildner * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1554ba9607SSascha Wildner * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1654ba9607SSascha Wildner */
17*99db7d0eSSascha Wildner #include "config.h"
18*99db7d0eSSascha Wildner
1954ba9607SSascha Wildner #include <sys/types.h>
2054ba9607SSascha Wildner
2154ba9607SSascha Wildner #include <assert.h>
2254ba9607SSascha Wildner #include <stdio.h>
2354ba9607SSascha Wildner #include <stdlib.h>
2454ba9607SSascha Wildner #include <string.h>
2554ba9607SSascha Wildner
2654ba9607SSascha Wildner #include "mandoc.h"
2754ba9607SSascha Wildner #include "roff.h"
2854ba9607SSascha Wildner #include "mdoc.h"
2954ba9607SSascha Wildner #include "libmandoc.h"
3054ba9607SSascha Wildner #include "roff_int.h"
3154ba9607SSascha Wildner #include "libmdoc.h"
3254ba9607SSascha Wildner
3354ba9607SSascha Wildner #define STATE_ARGS struct roff_man *mdoc, struct roff_node *n
3454ba9607SSascha Wildner
3554ba9607SSascha Wildner typedef void (*state_handler)(STATE_ARGS);
3654ba9607SSascha Wildner
3754ba9607SSascha Wildner static void state_bl(STATE_ARGS);
3854ba9607SSascha Wildner static void state_sh(STATE_ARGS);
3954ba9607SSascha Wildner static void state_sm(STATE_ARGS);
4054ba9607SSascha Wildner
4154ba9607SSascha Wildner static const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = {
4254ba9607SSascha Wildner NULL, /* Dd */
4354ba9607SSascha Wildner NULL, /* Dt */
4454ba9607SSascha Wildner NULL, /* Os */
4554ba9607SSascha Wildner state_sh, /* Sh */
4654ba9607SSascha Wildner NULL, /* Ss */
4754ba9607SSascha Wildner NULL, /* Pp */
4854ba9607SSascha Wildner NULL, /* D1 */
4954ba9607SSascha Wildner NULL, /* Dl */
5054ba9607SSascha Wildner NULL, /* Bd */
5154ba9607SSascha Wildner NULL, /* Ed */
5254ba9607SSascha Wildner state_bl, /* Bl */
5354ba9607SSascha Wildner NULL, /* El */
5454ba9607SSascha Wildner NULL, /* It */
5554ba9607SSascha Wildner NULL, /* Ad */
5654ba9607SSascha Wildner NULL, /* An */
5754ba9607SSascha Wildner NULL, /* Ap */
5854ba9607SSascha Wildner NULL, /* Ar */
5954ba9607SSascha Wildner NULL, /* Cd */
6054ba9607SSascha Wildner NULL, /* Cm */
6154ba9607SSascha Wildner NULL, /* Dv */
6254ba9607SSascha Wildner NULL, /* Er */
6354ba9607SSascha Wildner NULL, /* Ev */
6454ba9607SSascha Wildner NULL, /* Ex */
6554ba9607SSascha Wildner NULL, /* Fa */
6654ba9607SSascha Wildner NULL, /* Fd */
6754ba9607SSascha Wildner NULL, /* Fl */
6854ba9607SSascha Wildner NULL, /* Fn */
6954ba9607SSascha Wildner NULL, /* Ft */
7054ba9607SSascha Wildner NULL, /* Ic */
7154ba9607SSascha Wildner NULL, /* In */
7254ba9607SSascha Wildner NULL, /* Li */
7354ba9607SSascha Wildner NULL, /* Nd */
7454ba9607SSascha Wildner NULL, /* Nm */
7554ba9607SSascha Wildner NULL, /* Op */
7654ba9607SSascha Wildner NULL, /* Ot */
7754ba9607SSascha Wildner NULL, /* Pa */
7854ba9607SSascha Wildner NULL, /* Rv */
7954ba9607SSascha Wildner NULL, /* St */
8054ba9607SSascha Wildner NULL, /* Va */
8154ba9607SSascha Wildner NULL, /* Vt */
8254ba9607SSascha Wildner NULL, /* Xr */
8354ba9607SSascha Wildner NULL, /* %A */
8454ba9607SSascha Wildner NULL, /* %B */
8554ba9607SSascha Wildner NULL, /* %D */
8654ba9607SSascha Wildner NULL, /* %I */
8754ba9607SSascha Wildner NULL, /* %J */
8854ba9607SSascha Wildner NULL, /* %N */
8954ba9607SSascha Wildner NULL, /* %O */
9054ba9607SSascha Wildner NULL, /* %P */
9154ba9607SSascha Wildner NULL, /* %R */
9254ba9607SSascha Wildner NULL, /* %T */
9354ba9607SSascha Wildner NULL, /* %V */
9454ba9607SSascha Wildner NULL, /* Ac */
9554ba9607SSascha Wildner NULL, /* Ao */
9654ba9607SSascha Wildner NULL, /* Aq */
9754ba9607SSascha Wildner NULL, /* At */
9854ba9607SSascha Wildner NULL, /* Bc */
9954ba9607SSascha Wildner NULL, /* Bf */
10054ba9607SSascha Wildner NULL, /* Bo */
10154ba9607SSascha Wildner NULL, /* Bq */
10254ba9607SSascha Wildner NULL, /* Bsx */
10354ba9607SSascha Wildner NULL, /* Bx */
10454ba9607SSascha Wildner NULL, /* Db */
10554ba9607SSascha Wildner NULL, /* Dc */
10654ba9607SSascha Wildner NULL, /* Do */
10754ba9607SSascha Wildner NULL, /* Dq */
10854ba9607SSascha Wildner NULL, /* Ec */
10954ba9607SSascha Wildner NULL, /* Ef */
11054ba9607SSascha Wildner NULL, /* Em */
11154ba9607SSascha Wildner NULL, /* Eo */
11254ba9607SSascha Wildner NULL, /* Fx */
11354ba9607SSascha Wildner NULL, /* Ms */
11454ba9607SSascha Wildner NULL, /* No */
11554ba9607SSascha Wildner NULL, /* Ns */
11654ba9607SSascha Wildner NULL, /* Nx */
11754ba9607SSascha Wildner NULL, /* Ox */
11854ba9607SSascha Wildner NULL, /* Pc */
11954ba9607SSascha Wildner NULL, /* Pf */
12054ba9607SSascha Wildner NULL, /* Po */
12154ba9607SSascha Wildner NULL, /* Pq */
12254ba9607SSascha Wildner NULL, /* Qc */
12354ba9607SSascha Wildner NULL, /* Ql */
12454ba9607SSascha Wildner NULL, /* Qo */
12554ba9607SSascha Wildner NULL, /* Qq */
12654ba9607SSascha Wildner NULL, /* Re */
12754ba9607SSascha Wildner NULL, /* Rs */
12854ba9607SSascha Wildner NULL, /* Sc */
12954ba9607SSascha Wildner NULL, /* So */
13054ba9607SSascha Wildner NULL, /* Sq */
13154ba9607SSascha Wildner state_sm, /* Sm */
13254ba9607SSascha Wildner NULL, /* Sx */
13354ba9607SSascha Wildner NULL, /* Sy */
13454ba9607SSascha Wildner NULL, /* Tn */
13554ba9607SSascha Wildner NULL, /* Ux */
13654ba9607SSascha Wildner NULL, /* Xc */
13754ba9607SSascha Wildner NULL, /* Xo */
13854ba9607SSascha Wildner NULL, /* Fo */
13954ba9607SSascha Wildner NULL, /* Fc */
14054ba9607SSascha Wildner NULL, /* Oo */
14154ba9607SSascha Wildner NULL, /* Oc */
14254ba9607SSascha Wildner NULL, /* Bk */
14354ba9607SSascha Wildner NULL, /* Ek */
14454ba9607SSascha Wildner NULL, /* Bt */
14554ba9607SSascha Wildner NULL, /* Hf */
14654ba9607SSascha Wildner NULL, /* Fr */
14754ba9607SSascha Wildner NULL, /* Ud */
14854ba9607SSascha Wildner NULL, /* Lb */
14954ba9607SSascha Wildner NULL, /* Lp */
15054ba9607SSascha Wildner NULL, /* Lk */
15154ba9607SSascha Wildner NULL, /* Mt */
15254ba9607SSascha Wildner NULL, /* Brq */
15354ba9607SSascha Wildner NULL, /* Bro */
15454ba9607SSascha Wildner NULL, /* Brc */
15554ba9607SSascha Wildner NULL, /* %C */
15654ba9607SSascha Wildner NULL, /* Es */
15754ba9607SSascha Wildner NULL, /* En */
15854ba9607SSascha Wildner NULL, /* Dx */
15954ba9607SSascha Wildner NULL, /* %Q */
16054ba9607SSascha Wildner NULL, /* %U */
16154ba9607SSascha Wildner NULL, /* Ta */
162*99db7d0eSSascha Wildner NULL, /* Tg */
16354ba9607SSascha Wildner };
16454ba9607SSascha Wildner
16554ba9607SSascha Wildner
16654ba9607SSascha Wildner void
mdoc_state(struct roff_man * mdoc,struct roff_node * n)16754ba9607SSascha Wildner mdoc_state(struct roff_man *mdoc, struct roff_node *n)
16854ba9607SSascha Wildner {
16954ba9607SSascha Wildner state_handler handler;
17054ba9607SSascha Wildner
17154ba9607SSascha Wildner if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
17254ba9607SSascha Wildner return;
17354ba9607SSascha Wildner
17454ba9607SSascha Wildner assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
17554ba9607SSascha Wildner if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0)
17654ba9607SSascha Wildner mdoc->flags |= MDOC_PBODY;
17754ba9607SSascha Wildner
17854ba9607SSascha Wildner handler = state_handlers[n->tok - MDOC_Dd];
17954ba9607SSascha Wildner if (*handler)
18054ba9607SSascha Wildner (*handler)(mdoc, n);
18154ba9607SSascha Wildner }
18254ba9607SSascha Wildner
18354ba9607SSascha Wildner static void
state_bl(STATE_ARGS)18454ba9607SSascha Wildner state_bl(STATE_ARGS)
18554ba9607SSascha Wildner {
18654ba9607SSascha Wildner struct mdoc_arg *args;
18754ba9607SSascha Wildner size_t i;
18854ba9607SSascha Wildner
18954ba9607SSascha Wildner if (n->type != ROFFT_HEAD || n->parent->args == NULL)
19054ba9607SSascha Wildner return;
19154ba9607SSascha Wildner
19254ba9607SSascha Wildner args = n->parent->args;
19354ba9607SSascha Wildner for (i = 0; i < args->argc; i++) {
19454ba9607SSascha Wildner switch(args->argv[i].arg) {
19554ba9607SSascha Wildner case MDOC_Diag:
19654ba9607SSascha Wildner n->norm->Bl.type = LIST_diag;
19754ba9607SSascha Wildner return;
19854ba9607SSascha Wildner case MDOC_Column:
19954ba9607SSascha Wildner n->norm->Bl.type = LIST_column;
20054ba9607SSascha Wildner return;
20154ba9607SSascha Wildner default:
20254ba9607SSascha Wildner break;
20354ba9607SSascha Wildner }
20454ba9607SSascha Wildner }
20554ba9607SSascha Wildner }
20654ba9607SSascha Wildner
20754ba9607SSascha Wildner static void
state_sh(STATE_ARGS)20854ba9607SSascha Wildner state_sh(STATE_ARGS)
20954ba9607SSascha Wildner {
21054ba9607SSascha Wildner struct roff_node *nch;
21154ba9607SSascha Wildner char *secname;
21254ba9607SSascha Wildner
21354ba9607SSascha Wildner if (n->type != ROFFT_HEAD)
21454ba9607SSascha Wildner return;
21554ba9607SSascha Wildner
21654ba9607SSascha Wildner if ( ! (n->flags & NODE_VALID)) {
21754ba9607SSascha Wildner secname = NULL;
21854ba9607SSascha Wildner deroff(&secname, n);
21954ba9607SSascha Wildner
22054ba9607SSascha Wildner /*
22154ba9607SSascha Wildner * Set the section attribute for the BLOCK, HEAD,
22254ba9607SSascha Wildner * and HEAD children; the latter can only be TEXT
22354ba9607SSascha Wildner * nodes, so no recursion is needed. For other
22454ba9607SSascha Wildner * nodes, including the .Sh BODY, this is done
22554ba9607SSascha Wildner * when allocating the node data structures, but
22654ba9607SSascha Wildner * for .Sh BLOCK and HEAD, the section is still
22754ba9607SSascha Wildner * unknown at that time.
22854ba9607SSascha Wildner */
22954ba9607SSascha Wildner
23054ba9607SSascha Wildner n->sec = n->parent->sec = secname == NULL ?
23154ba9607SSascha Wildner SEC_CUSTOM : mdoc_a2sec(secname);
23254ba9607SSascha Wildner for (nch = n->child; nch != NULL; nch = nch->next)
23354ba9607SSascha Wildner nch->sec = n->sec;
23454ba9607SSascha Wildner free(secname);
23554ba9607SSascha Wildner }
23654ba9607SSascha Wildner
23754ba9607SSascha Wildner if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
23854ba9607SSascha Wildner roff_setreg(mdoc->roff, "nS", 1, '=');
23954ba9607SSascha Wildner mdoc->flags |= MDOC_SYNOPSIS;
24054ba9607SSascha Wildner } else {
24154ba9607SSascha Wildner roff_setreg(mdoc->roff, "nS", 0, '=');
24254ba9607SSascha Wildner mdoc->flags &= ~MDOC_SYNOPSIS;
24354ba9607SSascha Wildner }
24454ba9607SSascha Wildner }
24554ba9607SSascha Wildner
24654ba9607SSascha Wildner static void
state_sm(STATE_ARGS)24754ba9607SSascha Wildner state_sm(STATE_ARGS)
24854ba9607SSascha Wildner {
24954ba9607SSascha Wildner
25054ba9607SSascha Wildner if (n->child == NULL)
25154ba9607SSascha Wildner mdoc->flags ^= MDOC_SMOFF;
25254ba9607SSascha Wildner else if ( ! strcmp(n->child->string, "on"))
25354ba9607SSascha Wildner mdoc->flags &= ~MDOC_SMOFF;
25454ba9607SSascha Wildner else if ( ! strcmp(n->child->string, "off"))
25554ba9607SSascha Wildner mdoc->flags |= MDOC_SMOFF;
25654ba9607SSascha Wildner }
257