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