]> git.cameronkatri.com Git - mandoc.git/blob - action.c
df5b67695237f5a30f8b2b5076c2d5c04fd5a807
[mandoc.git] / action.c
1 /* $Id: action.c,v 1.22 2009/02/27 10:55:16 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
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
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include <assert.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24
25 #include "private.h"
26
27 /*
28 * Actions are executed on macros after they've been post-validated: in
29 * other words, a macro will not be "acted upon" until all of its
30 * children have been filled in (post-fix order).
31 */
32
33 struct actions {
34 int (*post)(struct mdoc *);
35 };
36
37 /* Per-macro action routines. */
38
39 static int post_bl(struct mdoc *);
40 static int post_sh(struct mdoc *);
41 static int post_os(struct mdoc *);
42 static int post_dt(struct mdoc *);
43 static int post_dd(struct mdoc *);
44 static int post_nm(struct mdoc *);
45
46 static int post_prologue(struct mdoc *);
47
48 /* Array of macro action routines. */
49
50 const struct actions mdoc_actions[MDOC_MAX] = {
51 { NULL }, /* \" */
52 { post_dd }, /* Dd */
53 { post_dt }, /* Dt */
54 { post_os }, /* Os */
55 { post_sh }, /* Sh */
56 { NULL }, /* Ss */
57 { NULL }, /* Pp */
58 { NULL }, /* D1 */
59 { NULL }, /* Dl */
60 { NULL }, /* Bd */
61 { NULL }, /* Ed */
62 { post_bl }, /* Bl */
63 { NULL }, /* El */
64 { NULL }, /* It */
65 { NULL }, /* Ad */
66 { NULL }, /* An */
67 { NULL }, /* Ar */
68 { NULL }, /* Cd */
69 { NULL }, /* Cm */
70 { NULL }, /* Dv */
71 { NULL }, /* Er */
72 { NULL }, /* Ev */
73 { NULL }, /* Ex */
74 { NULL }, /* Fa */
75 { NULL }, /* Fd */
76 { NULL }, /* Fl */
77 { NULL }, /* Fn */
78 { NULL }, /* Ft */
79 { NULL }, /* Ic */
80 { NULL }, /* In */
81 { NULL }, /* Li */
82 { NULL }, /* Nd */
83 { post_nm }, /* Nm */
84 { NULL }, /* Op */
85 { NULL }, /* Ot */
86 { NULL }, /* Pa */
87 { NULL }, /* Rv */
88 { NULL }, /* St */
89 { NULL }, /* Va */
90 { NULL }, /* Vt */
91 { NULL }, /* Xr */
92 { NULL }, /* %A */
93 { NULL }, /* %B */
94 { NULL }, /* %D */
95 { NULL }, /* %I */
96 { NULL }, /* %J */
97 { NULL }, /* %N */
98 { NULL }, /* %O */
99 { NULL }, /* %P */
100 { NULL }, /* %R */
101 { NULL }, /* %T */
102 { NULL }, /* %V */
103 { NULL }, /* Ac */
104 { NULL }, /* Ao */
105 { NULL }, /* Aq */
106 { NULL }, /* At */
107 { NULL }, /* Bc */
108 { NULL }, /* Bf */
109 { NULL }, /* Bo */
110 { NULL }, /* Bq */
111 { NULL }, /* Bsx */
112 { NULL }, /* Bx */
113 { NULL }, /* Db */
114 { NULL }, /* Dc */
115 { NULL }, /* Do */
116 { NULL }, /* Dq */
117 { NULL }, /* Ec */
118 { NULL }, /* Ef */
119 { NULL }, /* Em */
120 { NULL }, /* Eo */
121 { NULL }, /* Fx */
122 { NULL }, /* Ms */
123 { NULL }, /* No */
124 { NULL }, /* Ns */
125 { NULL }, /* Nx */
126 { NULL }, /* Ox */
127 { NULL }, /* Pc */
128 { NULL }, /* Pf */
129 { NULL }, /* Po */
130 { NULL }, /* Pq */
131 { NULL }, /* Qc */
132 { NULL }, /* Ql */
133 { NULL }, /* Qo */
134 { NULL }, /* Qq */
135 { NULL }, /* Re */
136 { NULL }, /* Rs */
137 { NULL }, /* Sc */
138 { NULL }, /* So */
139 { NULL }, /* Sq */
140 { NULL }, /* Sm */
141 { NULL }, /* Sx */
142 { NULL }, /* Sy */
143 { NULL }, /* Tn */
144 { NULL }, /* Ux */
145 { NULL }, /* Xc */
146 { NULL }, /* Xo */
147 { NULL }, /* Fo */
148 { NULL }, /* Fc */
149 { NULL }, /* Oo */
150 { NULL }, /* Oc */
151 { NULL }, /* Bk */
152 { NULL }, /* Ek */
153 { NULL }, /* Bt */
154 { NULL }, /* Hf */
155 { NULL }, /* Fr */
156 { NULL }, /* Ud */
157 };
158
159
160 /*
161 * The `Nm' macro sets the document's name when used the first time with
162 * an argument. Subsequent calls without a value will result in the
163 * name value being used.
164 */
165 static int
166 post_nm(struct mdoc *mdoc)
167 {
168 char buf[64];
169
170 assert(MDOC_ELEM == mdoc->last->type);
171 assert(MDOC_Nm == mdoc->last->tok);
172
173 if (mdoc->meta.name)
174 return(1);
175
176 if (xstrlcats(buf, mdoc->last->child, 64)) {
177 mdoc->meta.name = xstrdup(buf);
178 return(1);
179 }
180
181 return(mdoc_err(mdoc, "macro parameters too long"));
182 }
183
184
185 /*
186 * We keep track of the current section in order to provide warnings on
187 * section ordering, per-section macros, and so on.
188 */
189 static int
190 post_sh(struct mdoc *mdoc)
191 {
192 enum mdoc_sec sec;
193 char buf[64];
194
195 if (MDOC_HEAD != mdoc->last->type)
196 return(1);
197 if (xstrlcats(buf, mdoc->last->child, 64)) {
198 if (SEC_CUSTOM != (sec = mdoc_atosec(buf)))
199 mdoc->lastnamed = sec;
200 mdoc->lastsec = sec;
201 return(1);
202 }
203
204 return(mdoc_err(mdoc, "macro parameters too long"));
205 }
206
207
208 /*
209 * Prologue title must be parsed into document meta-data.
210 */
211 static int
212 post_dt(struct mdoc *mdoc)
213 {
214 int i;
215 char *p;
216 struct mdoc_node *n;
217
218 assert(MDOC_ELEM == mdoc->last->type);
219 assert(MDOC_Dt == mdoc->last->tok);
220
221 assert(NULL == mdoc->meta.title);
222
223 /* LINTED */
224 for (i = 0, n = mdoc->last->child; n; n = n->next, i++) {
225 assert(MDOC_TEXT == n->type);
226 p = n->data.text.string;
227
228 switch (i) {
229 case (0):
230 mdoc->meta.title = xstrdup(p);
231 break;
232 case (1):
233 mdoc->meta.msec = mdoc_atomsec(p);
234 if (MSEC_DEFAULT != mdoc->meta.msec)
235 break;
236 return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
237 case (2):
238 mdoc->meta.vol = mdoc_atovol(p);
239 if (VOL_DEFAULT != mdoc->meta.vol)
240 break;
241 mdoc->meta.arch = mdoc_atoarch(p);
242 if (ARCH_DEFAULT != mdoc->meta.arch)
243 break;
244 return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
245 default:
246 return(mdoc_nerr(mdoc, n, "too many parameters"));
247 }
248 }
249
250 if (NULL == mdoc->meta.title)
251 mdoc->meta.title = xstrdup("UNTITLED");
252
253 mdoc_msg(mdoc, "title: %s", mdoc->meta.title);
254
255 return(post_prologue(mdoc));
256 }
257
258
259 /*
260 * Prologue operating system must be parsed into document meta-data.
261 */
262 static int
263 post_os(struct mdoc *mdoc)
264 {
265 char buf[64];
266
267 assert(MDOC_ELEM == mdoc->last->type);
268 assert(MDOC_Os == mdoc->last->tok);
269 assert(NULL == mdoc->meta.os);
270
271 if ( ! xstrlcats(buf, mdoc->last->child, 64))
272 return(mdoc_err(mdoc, "macro parameters too long"));
273
274 mdoc->meta.os = xstrdup(buf[0] ? buf : "LOCAL");
275 mdoc->lastnamed = SEC_BODY;
276
277 return(post_prologue(mdoc));
278 }
279
280
281 /*
282 * Transform -width MACRO values into real widths.
283 */
284 static int
285 post_bl(struct mdoc *mdoc)
286 {
287 struct mdoc_block *bl;
288 size_t width;
289 int tok, i;
290 char buf[32];
291
292 if (MDOC_BLOCK != mdoc->last->type)
293 return(1);
294
295 bl = &mdoc->last->data.block;
296
297 for (i = 0; i < (int)bl->argc; i++)
298 if (MDOC_Width == bl->argv[i].arg)
299 break;
300
301 if (i == (int)bl->argc)
302 return(1);
303
304 assert(1 == bl->argv[i].sz);
305 if (MDOC_MAX == (tok = mdoc_find(mdoc, *bl->argv[i].value)))
306 return(1);
307
308 if (0 == (width = mdoc_macro2len(tok)))
309 return(mdoc_warn(mdoc, WARN_SYNTAX,
310 "-%s macro has no length",
311 mdoc_argnames[MDOC_Width]));
312
313 mdoc_msg(mdoc, "re-writing %s argument: %s -> %zun",
314 mdoc_argnames[MDOC_Width],
315 *bl->argv[i].value, width);
316
317 /* FIXME: silently truncates. */
318 (void)snprintf(buf, sizeof(buf), "%zun", width);
319
320 free(*bl->argv[i].value);
321 *bl->argv[i].value = strdup(buf);
322
323 return(1);
324 }
325
326
327 /*
328 * Prologue date must be parsed into document meta-data.
329 */
330 static int
331 post_dd(struct mdoc *mdoc)
332 {
333 char buf[64];
334
335 assert(MDOC_ELEM == mdoc->last->type);
336 assert(MDOC_Dd == mdoc->last->tok);
337
338 assert(0 == mdoc->meta.date);
339
340 if ( ! xstrlcats(buf, mdoc->last->child, 64))
341 return(mdoc_err(mdoc, "macro parameters too long"));
342 if (0 == (mdoc->meta.date = mdoc_atotime(buf)))
343 return(mdoc_err(mdoc, "invalid parameter syntax"));
344
345 mdoc_msg(mdoc, "date: %u", mdoc->meta.date);
346
347 return(post_prologue(mdoc));
348 }
349
350
351 /*
352 * The end document shouldn't have the prologue macros as part of the
353 * syntax tree (they encompass only meta-data).
354 */
355 static int
356 post_prologue(struct mdoc *mdoc)
357 {
358 struct mdoc_node *n;
359
360 if (mdoc->last->parent->child == mdoc->last)
361 mdoc->last->parent->child = mdoc->last->prev;
362 if (mdoc->last->prev)
363 mdoc->last->prev->next = NULL;
364
365 n = mdoc->last;
366 assert(NULL == mdoc->last->next);
367
368 if (mdoc->last->prev) {
369 mdoc->last = mdoc->last->prev;
370 mdoc->next = MDOC_NEXT_SIBLING;
371 } else {
372 mdoc->last = mdoc->last->parent;
373 mdoc->next = MDOC_NEXT_CHILD;
374 }
375
376 mdoc_node_freelist(n);
377 return(1);
378 }
379
380
381 int
382 mdoc_action_post(struct mdoc *mdoc)
383 {
384
385 if (MDOC_ACTED & mdoc->last->flags)
386 return(1);
387 mdoc->last->flags |= MDOC_ACTED;
388
389 if (MDOC_TEXT == mdoc->last->type)
390 return(1);
391 if (MDOC_ROOT == mdoc->last->type)
392 return(1);
393 if (NULL == mdoc_actions[mdoc->last->tok].post)
394 return(1);
395 return((*mdoc_actions[mdoc->last->tok].post)(mdoc));
396 }