1 |
|
|
/* $OpenBSD: mdoc_state.c,v 1.8 2017/05/05 15:16:25 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 <stdlib.h> |
21 |
|
|
#include <string.h> |
22 |
|
|
|
23 |
|
|
#include "mandoc.h" |
24 |
|
|
#include "roff.h" |
25 |
|
|
#include "mdoc.h" |
26 |
|
|
#include "libmandoc.h" |
27 |
|
|
#include "libmdoc.h" |
28 |
|
|
|
29 |
|
|
#define STATE_ARGS struct roff_man *mdoc, struct roff_node *n |
30 |
|
|
|
31 |
|
|
typedef void (*state_handler)(STATE_ARGS); |
32 |
|
|
|
33 |
|
|
static void state_bd(STATE_ARGS); |
34 |
|
|
static void state_bl(STATE_ARGS); |
35 |
|
|
static void state_dl(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 |
|
|
state_dl, /* Dl */ |
48 |
|
|
state_bd, /* 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 |
|
|
static const state_handler *const state_handlers = __state_handlers - MDOC_Dd; |
162 |
|
|
|
163 |
|
|
|
164 |
|
|
void |
165 |
|
|
mdoc_state(struct roff_man *mdoc, struct roff_node *n) |
166 |
|
|
{ |
167 |
|
|
state_handler handler; |
168 |
|
|
|
169 |
✓✓✓✓
|
12906290 |
if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX) |
170 |
|
919264 |
return; |
171 |
|
|
|
172 |
✓✗✗✓
|
7378368 |
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX); |
173 |
✓✓ |
3689184 |
if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE)) |
174 |
|
3585342 |
mdoc->flags |= MDOC_PBODY; |
175 |
|
|
|
176 |
|
3689184 |
handler = state_handlers[n->tok]; |
177 |
✓✓ |
3689184 |
if (*handler) |
178 |
|
704042 |
(*handler)(mdoc, n); |
179 |
|
8297632 |
} |
180 |
|
|
|
181 |
|
|
void |
182 |
|
|
mdoc_state_reset(struct roff_man *mdoc) |
183 |
|
|
{ |
184 |
|
|
|
185 |
|
69000 |
roff_setreg(mdoc->roff, "nS", 0, '='); |
186 |
|
34500 |
mdoc->flags = 0; |
187 |
|
34500 |
} |
188 |
|
|
|
189 |
|
|
static void |
190 |
|
|
state_bd(STATE_ARGS) |
191 |
|
|
{ |
192 |
|
|
enum mdocargt arg; |
193 |
|
|
|
194 |
✓✓✓✓
|
153466 |
if (n->type != ROFFT_HEAD && |
195 |
✓✓ |
72217 |
(n->type != ROFFT_BODY || n->end != ENDBODY_NOT)) |
196 |
|
19861 |
return; |
197 |
|
|
|
198 |
✓✓ |
43774 |
if (n->parent->args == NULL) |
199 |
|
180 |
return; |
200 |
|
|
|
201 |
|
43594 |
arg = n->parent->args->argv[0].arg; |
202 |
✓✓ |
43594 |
if (arg != MDOC_Literal && arg != MDOC_Unfilled) |
203 |
|
6959 |
return; |
204 |
|
|
|
205 |
|
36635 |
state_dl(mdoc, n); |
206 |
|
100270 |
} |
207 |
|
|
|
208 |
|
|
static void |
209 |
|
|
state_bl(STATE_ARGS) |
210 |
|
|
{ |
211 |
|
|
|
212 |
✓✓✓✓
|
368310 |
if (n->type != ROFFT_HEAD || n->parent->args == NULL) |
213 |
|
|
return; |
214 |
|
|
|
215 |
✓✓✓ |
166093 |
switch(n->parent->args->argv[0].arg) { |
216 |
|
|
case MDOC_Diag: |
217 |
|
1266 |
n->norm->Bl.type = LIST_diag; |
218 |
|
1266 |
break; |
219 |
|
|
case MDOC_Column: |
220 |
|
2562 |
n->norm->Bl.type = LIST_column; |
221 |
|
2562 |
break; |
222 |
|
|
default: |
223 |
|
|
break; |
224 |
|
|
} |
225 |
|
162265 |
} |
226 |
|
|
|
227 |
|
|
static void |
228 |
|
|
state_dl(STATE_ARGS) |
229 |
|
|
{ |
230 |
|
|
|
231 |
✓✓✓ |
160083 |
switch (n->type) { |
232 |
|
|
case ROFFT_HEAD: |
233 |
|
19848 |
mdoc->flags |= MDOC_LITERAL; |
234 |
|
19848 |
break; |
235 |
|
|
case ROFFT_BODY: |
236 |
|
29763 |
mdoc->flags &= ~MDOC_LITERAL; |
237 |
|
29763 |
break; |
238 |
|
|
default: |
239 |
|
|
break; |
240 |
|
|
} |
241 |
|
55236 |
} |
242 |
|
|
|
243 |
|
|
static void |
244 |
|
|
state_sh(STATE_ARGS) |
245 |
|
|
{ |
246 |
|
|
struct roff_node *nch; |
247 |
|
907860 |
char *secname; |
248 |
|
|
|
249 |
✓✓ |
453930 |
if (n->type != ROFFT_HEAD) |
250 |
|
302620 |
return; |
251 |
|
|
|
252 |
✓✓ |
151310 |
if ( ! (n->flags & NODE_VALID)) { |
253 |
|
75655 |
secname = NULL; |
254 |
|
75655 |
deroff(&secname, n); |
255 |
|
|
|
256 |
|
|
/* |
257 |
|
|
* Set the section attribute for the BLOCK, HEAD, |
258 |
|
|
* and HEAD children; the latter can only be TEXT |
259 |
|
|
* nodes, so no recursion is needed. For other |
260 |
|
|
* nodes, including the .Sh BODY, this is done |
261 |
|
|
* when allocating the node data structures, but |
262 |
|
|
* for .Sh BLOCK and HEAD, the section is still |
263 |
|
|
* unknown at that time. |
264 |
|
|
*/ |
265 |
|
|
|
266 |
✓✗ |
226965 |
n->sec = n->parent->sec = secname == NULL ? |
267 |
|
75655 |
SEC_CUSTOM : mdoc_a2sec(secname); |
268 |
✓✓ |
302764 |
for (nch = n->child; nch != NULL; nch = nch->next) |
269 |
|
75727 |
nch->sec = n->sec; |
270 |
|
75655 |
free(secname); |
271 |
|
75655 |
} |
272 |
|
|
|
273 |
✓✓ |
151310 |
if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) { |
274 |
|
17556 |
roff_setreg(mdoc->roff, "nS", 1, '='); |
275 |
|
17556 |
mdoc->flags |= MDOC_SYNOPSIS; |
276 |
|
17556 |
} else { |
277 |
|
133754 |
roff_setreg(mdoc->roff, "nS", 0, '='); |
278 |
|
133754 |
mdoc->flags &= ~MDOC_SYNOPSIS; |
279 |
|
|
} |
280 |
|
605240 |
} |
281 |
|
|
|
282 |
|
|
static void |
283 |
|
|
state_sm(STATE_ARGS) |
284 |
|
|
{ |
285 |
|
|
|
286 |
✓✓ |
11222 |
if (n->child == NULL) |
287 |
|
108 |
mdoc->flags ^= MDOC_SMOFF; |
288 |
✓✓ |
5503 |
else if ( ! strcmp(n->child->string, "on")) |
289 |
|
2720 |
mdoc->flags &= ~MDOC_SMOFF; |
290 |
✓✓ |
2783 |
else if ( ! strcmp(n->child->string, "off")) |
291 |
|
2675 |
mdoc->flags |= MDOC_SMOFF; |
292 |
|
5611 |
} |