]> git.cameronkatri.com Git - mandoc.git/blob - action.c
Initial block-display support.
[mandoc.git] / action.c
1 /* $Id: action.c,v 1.19 2009/02/22 14:31:08 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 <stdlib.h>
21 #include <time.h>
22
23 #include "private.h"
24
25 /*
26 * Actions are executed on macros after they've been post-validated: in
27 * other words, a macro will not be "acted upon" until all of its
28 * children have been filled in (post-fix order).
29 */
30
31 struct actions {
32 int (*post)(struct mdoc *);
33 };
34
35 /* Per-macro action routines. */
36
37 static int post_sh(struct mdoc *);
38 static int post_os(struct mdoc *);
39 static int post_dt(struct mdoc *);
40 static int post_dd(struct mdoc *);
41 static int post_nm(struct mdoc *);
42
43 static int post_prologue(struct mdoc *);
44
45 /* Array of macro action routines. */
46
47 const struct actions mdoc_actions[MDOC_MAX] = {
48 { NULL }, /* \" */
49 { post_dd }, /* Dd */
50 { post_dt }, /* Dt */
51 { post_os }, /* Os */
52 { post_sh }, /* Sh */
53 { NULL }, /* Ss */
54 { NULL }, /* Pp */
55 { NULL }, /* D1 */
56 { NULL }, /* Dl */
57 { NULL }, /* Bd */
58 { NULL }, /* Ed */
59 { NULL }, /* Bl */
60 { NULL }, /* El */
61 { NULL }, /* It */
62 { NULL }, /* Ad */
63 { NULL }, /* An */
64 { NULL }, /* Ar */
65 { NULL }, /* Cd */
66 { NULL }, /* Cm */
67 { NULL }, /* Dv */
68 { NULL }, /* Er */
69 { NULL }, /* Ev */
70 { NULL }, /* Ex */
71 { NULL }, /* Fa */
72 { NULL }, /* Fd */
73 { NULL }, /* Fl */
74 { NULL }, /* Fn */
75 { NULL }, /* Ft */
76 { NULL }, /* Ic */
77 { NULL }, /* In */
78 { NULL }, /* Li */
79 { NULL }, /* Nd */
80 { post_nm }, /* Nm */
81 { NULL }, /* Op */
82 { NULL }, /* Ot */
83 { NULL }, /* Pa */
84 { NULL }, /* Rv */
85 { NULL }, /* St */
86 { NULL }, /* Va */
87 { NULL }, /* Vt */
88 { NULL }, /* Xr */
89 { NULL }, /* %A */
90 { NULL }, /* %B */
91 { NULL }, /* %D */
92 { NULL }, /* %I */
93 { NULL }, /* %J */
94 { NULL }, /* %N */
95 { NULL }, /* %O */
96 { NULL }, /* %P */
97 { NULL }, /* %R */
98 { NULL }, /* %T */
99 { NULL }, /* %V */
100 { NULL }, /* Ac */
101 { NULL }, /* Ao */
102 { NULL }, /* Aq */
103 { NULL }, /* At */
104 { NULL }, /* Bc */
105 { NULL }, /* Bf */
106 { NULL }, /* Bo */
107 { NULL }, /* Bq */
108 { NULL }, /* Bsx */
109 { NULL }, /* Bx */
110 { NULL }, /* Db */
111 { NULL }, /* Dc */
112 { NULL }, /* Do */
113 { NULL }, /* Dq */
114 { NULL }, /* Ec */
115 { NULL }, /* Ef */
116 { NULL }, /* Em */
117 { NULL }, /* Eo */
118 { NULL }, /* Fx */
119 { NULL }, /* Ms */
120 { NULL }, /* No */
121 { NULL }, /* Ns */
122 { NULL }, /* Nx */
123 { NULL }, /* Ox */
124 { NULL }, /* Pc */
125 { NULL }, /* Pf */
126 { NULL }, /* Po */
127 { NULL }, /* Pq */
128 { NULL }, /* Qc */
129 { NULL }, /* Ql */
130 { NULL }, /* Qo */
131 { NULL }, /* Qq */
132 { NULL }, /* Re */
133 { NULL }, /* Rs */
134 { NULL }, /* Sc */
135 { NULL }, /* So */
136 { NULL }, /* Sq */
137 { NULL }, /* Sm */
138 { NULL }, /* Sx */
139 { NULL }, /* Sy */
140 { NULL }, /* Tn */
141 { NULL }, /* Ux */
142 { NULL }, /* Xc */
143 { NULL }, /* Xo */
144 { NULL }, /* Fo */
145 { NULL }, /* Fc */
146 { NULL }, /* Oo */
147 { NULL }, /* Oc */
148 { NULL }, /* Bk */
149 { NULL }, /* Ek */
150 { NULL }, /* Bt */
151 { NULL }, /* Hf */
152 { NULL }, /* Fr */
153 { NULL }, /* Ud */
154 };
155
156
157 /*
158 * The `Nm' macro sets the document's name when used the first time with
159 * an argument. Subsequent calls without a value will result in the
160 * name value being used.
161 */
162 static int
163 post_nm(struct mdoc *mdoc)
164 {
165 char buf[64];
166
167 assert(MDOC_ELEM == mdoc->last->type);
168 assert(MDOC_Nm == mdoc->last->tok);
169
170 if (mdoc->meta.name)
171 return(1);
172
173 if (xstrlcats(buf, mdoc->last->child, 64)) {
174 mdoc->meta.name = xstrdup(buf);
175 return(1);
176 }
177
178 return(mdoc_err(mdoc, "macro parameters too long"));
179 }
180
181
182 /*
183 * We keep track of the current section in order to provide warnings on
184 * section ordering, per-section macros, and so on.
185 */
186 static int
187 post_sh(struct mdoc *mdoc)
188 {
189 enum mdoc_sec sec;
190 char buf[64];
191
192 if (MDOC_HEAD != mdoc->last->type)
193 return(1);
194 if (xstrlcats(buf, mdoc->last->child, 64)) {
195 if (SEC_CUSTOM != (sec = mdoc_atosec(buf)))
196 mdoc->lastnamed = sec;
197 mdoc->lastsec = sec;
198 return(1);
199 }
200
201 return(mdoc_err(mdoc, "macro parameters too long"));
202 }
203
204
205 /*
206 * Prologue title must be parsed into document meta-data.
207 */
208 static int
209 post_dt(struct mdoc *mdoc)
210 {
211 int i;
212 char *p;
213 struct mdoc_node *n;
214
215 assert(MDOC_ELEM == mdoc->last->type);
216 assert(MDOC_Dt == mdoc->last->tok);
217
218 assert(NULL == mdoc->meta.title);
219
220 /* LINTED */
221 for (i = 0, n = mdoc->last->child; n; n = n->next, i++) {
222 assert(MDOC_TEXT == n->type);
223 p = n->data.text.string;
224
225 switch (i) {
226 case (0):
227 mdoc->meta.title = xstrdup(p);
228 break;
229 case (1):
230 mdoc->meta.msec = mdoc_atomsec(p);
231 if (MSEC_DEFAULT != mdoc->meta.msec)
232 break;
233 return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
234 case (2):
235 mdoc->meta.vol = mdoc_atovol(p);
236 if (VOL_DEFAULT != mdoc->meta.vol)
237 break;
238 mdoc->meta.arch = mdoc_atoarch(p);
239 if (ARCH_DEFAULT != mdoc->meta.arch)
240 break;
241 return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
242 default:
243 return(mdoc_nerr(mdoc, n, "too many parameters"));
244 }
245 }
246
247 if (NULL == mdoc->meta.title)
248 mdoc->meta.title = xstrdup("UNTITLED");
249
250 mdoc_msg(mdoc, "title: %s", mdoc->meta.title);
251
252 return(post_prologue(mdoc));
253 }
254
255
256 /*
257 * Prologue operating system must be parsed into document meta-data.
258 */
259 static int
260 post_os(struct mdoc *mdoc)
261 {
262 char buf[64];
263
264 assert(MDOC_ELEM == mdoc->last->type);
265 assert(MDOC_Os == mdoc->last->tok);
266 assert(NULL == mdoc->meta.os);
267
268 if ( ! xstrlcats(buf, mdoc->last->child, 64))
269 return(mdoc_err(mdoc, "macro parameters too long"));
270
271 mdoc->meta.os = xstrdup(buf[0] ? buf : "local");
272 mdoc->lastnamed = SEC_BODY;
273
274 return(post_prologue(mdoc));
275 }
276
277
278 /*
279 * Prologue date must be parsed into document meta-data.
280 */
281 static int
282 post_dd(struct mdoc *mdoc)
283 {
284 char buf[64];
285
286 assert(MDOC_ELEM == mdoc->last->type);
287 assert(MDOC_Dd == mdoc->last->tok);
288
289 assert(0 == mdoc->meta.date);
290
291 if ( ! xstrlcats(buf, mdoc->last->child, 64))
292 return(mdoc_err(mdoc, "macro parameters too long"));
293 if (0 == (mdoc->meta.date = mdoc_atotime(buf)))
294 return(mdoc_err(mdoc, "invalid parameter syntax"));
295
296 mdoc_msg(mdoc, "date: %u", mdoc->meta.date);
297
298 return(post_prologue(mdoc));
299 }
300
301
302 /*
303 * The end document shouldn't have the prologue macros as part of the
304 * syntax tree (they encompass only meta-data).
305 */
306 static int
307 post_prologue(struct mdoc *mdoc)
308 {
309 struct mdoc_node *n;
310
311 if (mdoc->last->parent->child == mdoc->last)
312 mdoc->last->parent->child = mdoc->last->prev;
313 if (mdoc->last->prev)
314 mdoc->last->prev->next = NULL;
315
316 n = mdoc->last;
317 assert(NULL == mdoc->last->next);
318
319 if (mdoc->last->prev) {
320 mdoc->last = mdoc->last->prev;
321 mdoc->next = MDOC_NEXT_SIBLING;
322 } else {
323 mdoc->last = mdoc->last->parent;
324 mdoc->next = MDOC_NEXT_CHILD;
325 }
326
327 mdoc_node_freelist(n);
328 return(1);
329 }
330
331
332 int
333 mdoc_action_post(struct mdoc *mdoc)
334 {
335
336 if (MDOC_ACTED & mdoc->last->flags)
337 return(1);
338 mdoc->last->flags |= MDOC_ACTED;
339
340 if (MDOC_TEXT == mdoc->last->type)
341 return(1);
342 if (MDOC_ROOT == mdoc->last->type)
343 return(1);
344 if (NULL == mdoc_actions[mdoc->last->tok].post)
345 return(1);
346 return((*mdoc_actions[mdoc->last->tok].post)(mdoc));
347 }