Import mandoc-1.14.6.
[dragonfly.git] / contrib / mdocml / mdoc_state.c
1 /* $Id: mdoc_state.c,v 1.17 2020/06/22 19:20:40 schwarze Exp $ */
2 /*
3  * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include "config.h"
18
19 #include <sys/types.h>
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "mandoc.h"
27 #include "roff.h"
28 #include "mdoc.h"
29 #include "libmandoc.h"
30 #include "roff_int.h"
31 #include "libmdoc.h"
32
33 #define STATE_ARGS  struct roff_man *mdoc, struct roff_node *n
34
35 typedef void    (*state_handler)(STATE_ARGS);
36
37 static  void     state_bl(STATE_ARGS);
38 static  void     state_sh(STATE_ARGS);
39 static  void     state_sm(STATE_ARGS);
40
41 static  const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = {
42         NULL,           /* Dd */
43         NULL,           /* Dt */
44         NULL,           /* Os */
45         state_sh,       /* Sh */
46         NULL,           /* Ss */
47         NULL,           /* Pp */
48         NULL,           /* D1 */
49         NULL,           /* Dl */
50         NULL,           /* Bd */
51         NULL,           /* Ed */
52         state_bl,       /* Bl */
53         NULL,           /* El */
54         NULL,           /* It */
55         NULL,           /* Ad */
56         NULL,           /* An */
57         NULL,           /* Ap */
58         NULL,           /* Ar */
59         NULL,           /* Cd */
60         NULL,           /* Cm */
61         NULL,           /* Dv */
62         NULL,           /* Er */
63         NULL,           /* Ev */
64         NULL,           /* Ex */
65         NULL,           /* Fa */
66         NULL,           /* Fd */
67         NULL,           /* Fl */
68         NULL,           /* Fn */
69         NULL,           /* Ft */
70         NULL,           /* Ic */
71         NULL,           /* In */
72         NULL,           /* Li */
73         NULL,           /* Nd */
74         NULL,           /* Nm */
75         NULL,           /* Op */
76         NULL,           /* Ot */
77         NULL,           /* Pa */
78         NULL,           /* Rv */
79         NULL,           /* St */
80         NULL,           /* Va */
81         NULL,           /* Vt */
82         NULL,           /* Xr */
83         NULL,           /* %A */
84         NULL,           /* %B */
85         NULL,           /* %D */
86         NULL,           /* %I */
87         NULL,           /* %J */
88         NULL,           /* %N */
89         NULL,           /* %O */
90         NULL,           /* %P */
91         NULL,           /* %R */
92         NULL,           /* %T */
93         NULL,           /* %V */
94         NULL,           /* Ac */
95         NULL,           /* Ao */
96         NULL,           /* Aq */
97         NULL,           /* At */
98         NULL,           /* Bc */
99         NULL,           /* Bf */
100         NULL,           /* Bo */
101         NULL,           /* Bq */
102         NULL,           /* Bsx */
103         NULL,           /* Bx */
104         NULL,           /* Db */
105         NULL,           /* Dc */
106         NULL,           /* Do */
107         NULL,           /* Dq */
108         NULL,           /* Ec */
109         NULL,           /* Ef */
110         NULL,           /* Em */
111         NULL,           /* Eo */
112         NULL,           /* Fx */
113         NULL,           /* Ms */
114         NULL,           /* No */
115         NULL,           /* Ns */
116         NULL,           /* Nx */
117         NULL,           /* Ox */
118         NULL,           /* Pc */
119         NULL,           /* Pf */
120         NULL,           /* Po */
121         NULL,           /* Pq */
122         NULL,           /* Qc */
123         NULL,           /* Ql */
124         NULL,           /* Qo */
125         NULL,           /* Qq */
126         NULL,           /* Re */
127         NULL,           /* Rs */
128         NULL,           /* Sc */
129         NULL,           /* So */
130         NULL,           /* Sq */
131         state_sm,       /* Sm */
132         NULL,           /* Sx */
133         NULL,           /* Sy */
134         NULL,           /* Tn */
135         NULL,           /* Ux */
136         NULL,           /* Xc */
137         NULL,           /* Xo */
138         NULL,           /* Fo */
139         NULL,           /* Fc */
140         NULL,           /* Oo */
141         NULL,           /* Oc */
142         NULL,           /* Bk */
143         NULL,           /* Ek */
144         NULL,           /* Bt */
145         NULL,           /* Hf */
146         NULL,           /* Fr */
147         NULL,           /* Ud */
148         NULL,           /* Lb */
149         NULL,           /* Lp */
150         NULL,           /* Lk */
151         NULL,           /* Mt */
152         NULL,           /* Brq */
153         NULL,           /* Bro */
154         NULL,           /* Brc */
155         NULL,           /* %C */
156         NULL,           /* Es */
157         NULL,           /* En */
158         NULL,           /* Dx */
159         NULL,           /* %Q */
160         NULL,           /* %U */
161         NULL,           /* Ta */
162         NULL,           /* Tg */
163 };
164
165
166 void
167 mdoc_state(struct roff_man *mdoc, struct roff_node *n)
168 {
169         state_handler handler;
170
171         if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
172                 return;
173
174         assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
175         if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0)
176                 mdoc->flags |= MDOC_PBODY;
177
178         handler = state_handlers[n->tok - MDOC_Dd];
179         if (*handler)
180                 (*handler)(mdoc, n);
181 }
182
183 static void
184 state_bl(STATE_ARGS)
185 {
186         struct mdoc_arg *args;
187         size_t           i;
188
189         if (n->type != ROFFT_HEAD || n->parent->args == NULL)
190                 return;
191
192         args = n->parent->args;
193         for (i = 0; i < args->argc; i++) {
194                 switch(args->argv[i].arg) {
195                 case MDOC_Diag:
196                         n->norm->Bl.type = LIST_diag;
197                         return;
198                 case MDOC_Column:
199                         n->norm->Bl.type = LIST_column;
200                         return;
201                 default:
202                         break;
203                 }
204         }
205 }
206
207 static void
208 state_sh(STATE_ARGS)
209 {
210         struct roff_node *nch;
211         char             *secname;
212
213         if (n->type != ROFFT_HEAD)
214                 return;
215
216         if ( ! (n->flags & NODE_VALID)) {
217                 secname = NULL;
218                 deroff(&secname, n);
219
220                 /*
221                  * Set the section attribute for the BLOCK, HEAD,
222                  * and HEAD children; the latter can only be TEXT
223                  * nodes, so no recursion is needed.  For other
224                  * nodes, including the .Sh BODY, this is done
225                  * when allocating the node data structures, but
226                  * for .Sh BLOCK and HEAD, the section is still
227                  * unknown at that time.
228                  */
229
230                 n->sec = n->parent->sec = secname == NULL ?
231                     SEC_CUSTOM : mdoc_a2sec(secname);
232                 for (nch = n->child; nch != NULL; nch = nch->next)
233                         nch->sec = n->sec;
234                 free(secname);
235         }
236
237         if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
238                 roff_setreg(mdoc->roff, "nS", 1, '=');
239                 mdoc->flags |= MDOC_SYNOPSIS;
240         } else {
241                 roff_setreg(mdoc->roff, "nS", 0, '=');
242                 mdoc->flags &= ~MDOC_SYNOPSIS;
243         }
244 }
245
246 static void
247 state_sm(STATE_ARGS)
248 {
249
250         if (n->child == NULL)
251                 mdoc->flags ^= MDOC_SMOFF;
252         else if ( ! strcmp(n->child->string, "on"))
253                 mdoc->flags &= ~MDOC_SMOFF;
254         else if ( ! strcmp(n->child->string, "off"))
255                 mdoc->flags |= MDOC_SMOFF;
256 }