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