1 |
|
|
/* $OpenBSD: mdoc_state.c,v 1.3 2015/10/30 18:53:37 schwarze Exp $ */ |
2 |
|
|
/* |
3 |
|
|
* Copyright (c) 2014, 2015 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 <stdlib.h> |
20 |
|
|
#include <string.h> |
21 |
|
|
|
22 |
|
|
#include "mandoc.h" |
23 |
|
|
#include "roff.h" |
24 |
|
|
#include "mdoc.h" |
25 |
|
|
#include "libmandoc.h" |
26 |
|
|
#include "libmdoc.h" |
27 |
|
|
|
28 |
|
|
#define STATE_ARGS struct roff_man *mdoc, struct roff_node *n |
29 |
|
|
|
30 |
|
|
typedef void (*state_handler)(STATE_ARGS); |
31 |
|
|
|
32 |
|
|
static void state_bd(STATE_ARGS); |
33 |
|
|
static void state_bl(STATE_ARGS); |
34 |
|
|
static void state_dl(STATE_ARGS); |
35 |
|
|
static void state_sh(STATE_ARGS); |
36 |
|
|
static void state_sm(STATE_ARGS); |
37 |
|
|
|
38 |
|
|
static const state_handler state_handlers[MDOC_MAX] = { |
39 |
|
|
NULL, /* Ap */ |
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, /* Ar */ |
56 |
|
|
NULL, /* Cd */ |
57 |
|
|
NULL, /* Cm */ |
58 |
|
|
NULL, /* Dv */ |
59 |
|
|
NULL, /* Er */ |
60 |
|
|
NULL, /* Ev */ |
61 |
|
|
NULL, /* Ex */ |
62 |
|
|
NULL, /* Fa */ |
63 |
|
|
NULL, /* Fd */ |
64 |
|
|
NULL, /* Fl */ |
65 |
|
|
NULL, /* Fn */ |
66 |
|
|
NULL, /* Ft */ |
67 |
|
|
NULL, /* Ic */ |
68 |
|
|
NULL, /* In */ |
69 |
|
|
NULL, /* Li */ |
70 |
|
|
NULL, /* Nd */ |
71 |
|
|
NULL, /* Nm */ |
72 |
|
|
NULL, /* Op */ |
73 |
|
|
NULL, /* Ot */ |
74 |
|
|
NULL, /* Pa */ |
75 |
|
|
NULL, /* Rv */ |
76 |
|
|
NULL, /* St */ |
77 |
|
|
NULL, /* Va */ |
78 |
|
|
NULL, /* Vt */ |
79 |
|
|
NULL, /* Xr */ |
80 |
|
|
NULL, /* %A */ |
81 |
|
|
NULL, /* %B */ |
82 |
|
|
NULL, /* %D */ |
83 |
|
|
NULL, /* %I */ |
84 |
|
|
NULL, /* %J */ |
85 |
|
|
NULL, /* %N */ |
86 |
|
|
NULL, /* %O */ |
87 |
|
|
NULL, /* %P */ |
88 |
|
|
NULL, /* %R */ |
89 |
|
|
NULL, /* %T */ |
90 |
|
|
NULL, /* %V */ |
91 |
|
|
NULL, /* Ac */ |
92 |
|
|
NULL, /* Ao */ |
93 |
|
|
NULL, /* Aq */ |
94 |
|
|
NULL, /* At */ |
95 |
|
|
NULL, /* Bc */ |
96 |
|
|
NULL, /* Bf */ |
97 |
|
|
NULL, /* Bo */ |
98 |
|
|
NULL, /* Bq */ |
99 |
|
|
NULL, /* Bsx */ |
100 |
|
|
NULL, /* Bx */ |
101 |
|
|
NULL, /* Db */ |
102 |
|
|
NULL, /* Dc */ |
103 |
|
|
NULL, /* Do */ |
104 |
|
|
NULL, /* Dq */ |
105 |
|
|
NULL, /* Ec */ |
106 |
|
|
NULL, /* Ef */ |
107 |
|
|
NULL, /* Em */ |
108 |
|
|
NULL, /* Eo */ |
109 |
|
|
NULL, /* Fx */ |
110 |
|
|
NULL, /* Ms */ |
111 |
|
|
NULL, /* No */ |
112 |
|
|
NULL, /* Ns */ |
113 |
|
|
NULL, /* Nx */ |
114 |
|
|
NULL, /* Ox */ |
115 |
|
|
NULL, /* Pc */ |
116 |
|
|
NULL, /* Pf */ |
117 |
|
|
NULL, /* Po */ |
118 |
|
|
NULL, /* Pq */ |
119 |
|
|
NULL, /* Qc */ |
120 |
|
|
NULL, /* Ql */ |
121 |
|
|
NULL, /* Qo */ |
122 |
|
|
NULL, /* Qq */ |
123 |
|
|
NULL, /* Re */ |
124 |
|
|
NULL, /* Rs */ |
125 |
|
|
NULL, /* Sc */ |
126 |
|
|
NULL, /* So */ |
127 |
|
|
NULL, /* Sq */ |
128 |
|
|
state_sm, /* Sm */ |
129 |
|
|
NULL, /* Sx */ |
130 |
|
|
NULL, /* Sy */ |
131 |
|
|
NULL, /* Tn */ |
132 |
|
|
NULL, /* Ux */ |
133 |
|
|
NULL, /* Xc */ |
134 |
|
|
NULL, /* Xo */ |
135 |
|
|
NULL, /* Fo */ |
136 |
|
|
NULL, /* Fc */ |
137 |
|
|
NULL, /* Oo */ |
138 |
|
|
NULL, /* Oc */ |
139 |
|
|
NULL, /* Bk */ |
140 |
|
|
NULL, /* Ek */ |
141 |
|
|
NULL, /* Bt */ |
142 |
|
|
NULL, /* Hf */ |
143 |
|
|
NULL, /* Fr */ |
144 |
|
|
NULL, /* Ud */ |
145 |
|
|
NULL, /* Lb */ |
146 |
|
|
NULL, /* Lp */ |
147 |
|
|
NULL, /* Lk */ |
148 |
|
|
NULL, /* Mt */ |
149 |
|
|
NULL, /* Brq */ |
150 |
|
|
NULL, /* Bro */ |
151 |
|
|
NULL, /* Brc */ |
152 |
|
|
NULL, /* %C */ |
153 |
|
|
NULL, /* Es */ |
154 |
|
|
NULL, /* En */ |
155 |
|
|
NULL, /* Dx */ |
156 |
|
|
NULL, /* %Q */ |
157 |
|
|
NULL, /* br */ |
158 |
|
|
NULL, /* sp */ |
159 |
|
|
NULL, /* %U */ |
160 |
|
|
NULL, /* Ta */ |
161 |
|
|
NULL, /* ll */ |
162 |
|
|
}; |
163 |
|
|
|
164 |
|
|
|
165 |
|
|
void |
166 |
|
|
mdoc_state(struct roff_man *mdoc, struct roff_node *n) |
167 |
|
|
{ |
168 |
|
|
state_handler handler; |
169 |
|
|
|
170 |
|
|
if (n->tok == TOKEN_NONE) |
171 |
|
|
return; |
172 |
|
|
|
173 |
|
|
if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE)) |
174 |
|
|
mdoc->flags |= MDOC_PBODY; |
175 |
|
|
|
176 |
|
|
handler = state_handlers[n->tok]; |
177 |
|
|
if (*handler) |
178 |
|
|
(*handler)(mdoc, n); |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
void |
182 |
|
|
mdoc_state_reset(struct roff_man *mdoc) |
183 |
|
|
{ |
184 |
|
|
|
185 |
|
|
roff_setreg(mdoc->roff, "nS", 0, '='); |
186 |
|
|
mdoc->flags = 0; |
187 |
|
|
} |
188 |
|
|
|
189 |
|
|
static void |
190 |
|
|
state_bd(STATE_ARGS) |
191 |
|
|
{ |
192 |
|
|
enum mdocargt arg; |
193 |
|
|
|
194 |
|
|
if (n->type != ROFFT_HEAD && |
195 |
|
|
(n->type != ROFFT_BODY || n->end != ENDBODY_NOT)) |
196 |
|
|
return; |
197 |
|
|
|
198 |
|
|
if (n->parent->args == NULL) |
199 |
|
|
return; |
200 |
|
|
|
201 |
|
|
arg = n->parent->args->argv[0].arg; |
202 |
|
|
if (arg != MDOC_Literal && arg != MDOC_Unfilled) |
203 |
|
|
return; |
204 |
|
|
|
205 |
|
|
state_dl(mdoc, n); |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
static void |
209 |
|
|
state_bl(STATE_ARGS) |
210 |
|
|
{ |
211 |
|
|
|
212 |
|
|
if (n->type != ROFFT_HEAD || n->parent->args == NULL) |
213 |
|
|
return; |
214 |
|
|
|
215 |
|
|
switch(n->parent->args->argv[0].arg) { |
216 |
|
|
case MDOC_Diag: |
217 |
|
|
n->norm->Bl.type = LIST_diag; |
218 |
|
|
break; |
219 |
|
|
case MDOC_Column: |
220 |
|
|
n->norm->Bl.type = LIST_column; |
221 |
|
|
break; |
222 |
|
|
default: |
223 |
|
|
break; |
224 |
|
|
} |
225 |
|
|
} |
226 |
|
|
|
227 |
|
|
static void |
228 |
|
|
state_dl(STATE_ARGS) |
229 |
|
|
{ |
230 |
|
|
|
231 |
|
|
switch (n->type) { |
232 |
|
|
case ROFFT_HEAD: |
233 |
|
|
mdoc->flags |= MDOC_LITERAL; |
234 |
|
|
break; |
235 |
|
|
case ROFFT_BODY: |
236 |
|
|
mdoc->flags &= ~MDOC_LITERAL; |
237 |
|
|
break; |
238 |
|
|
default: |
239 |
|
|
break; |
240 |
|
|
} |
241 |
|
|
} |
242 |
|
|
|
243 |
|
|
static void |
244 |
|
|
state_sh(STATE_ARGS) |
245 |
|
|
{ |
246 |
|
|
struct roff_node *nch; |
247 |
|
|
char *secname; |
248 |
|
|
|
249 |
|
|
if (n->type != ROFFT_HEAD) |
250 |
|
|
return; |
251 |
|
|
|
252 |
|
|
if ( ! (n->flags & MDOC_VALID)) { |
253 |
|
|
secname = NULL; |
254 |
|
|
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 |
|
|
n->sec = n->parent->sec = secname == NULL ? |
267 |
|
|
SEC_CUSTOM : mdoc_a2sec(secname); |
268 |
|
|
for (nch = n->child; nch != NULL; nch = nch->next) |
269 |
|
|
nch->sec = n->sec; |
270 |
|
|
free(secname); |
271 |
|
|
} |
272 |
|
|
|
273 |
|
|
if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) { |
274 |
|
|
roff_setreg(mdoc->roff, "nS", 1, '='); |
275 |
|
|
mdoc->flags |= MDOC_SYNOPSIS; |
276 |
|
|
} else { |
277 |
|
|
roff_setreg(mdoc->roff, "nS", 0, '='); |
278 |
|
|
mdoc->flags &= ~MDOC_SYNOPSIS; |
279 |
|
|
} |
280 |
|
|
} |
281 |
|
|
|
282 |
|
|
static void |
283 |
|
|
state_sm(STATE_ARGS) |
284 |
|
|
{ |
285 |
|
|
|
286 |
|
|
if (n->child == NULL) |
287 |
|
|
mdoc->flags ^= MDOC_SMOFF; |
288 |
|
|
else if ( ! strcmp(n->child->string, "on")) |
289 |
|
|
mdoc->flags &= ~MDOC_SMOFF; |
290 |
|
|
else if ( ! strcmp(n->child->string, "off")) |
291 |
|
|
mdoc->flags |= MDOC_SMOFF; |
292 |
|
|
} |