]> git.cameronkatri.com Git - mandoc.git/blob - action.c
Split mdocml -> mdocterm, mdoctree (new manuals, etc.).
[mandoc.git] / action.c
1 /* $Id: action.c,v 1.18 2009/02/21 21:00:06 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 return(1);
198 }
199
200 return(mdoc_err(mdoc, "macro parameters too long"));
201 }
202
203
204 /*
205 * Prologue title must be parsed into document meta-data.
206 */
207 static int
208 post_dt(struct mdoc *mdoc)
209 {
210 int i;
211 char *p;
212 struct mdoc_node *n;
213
214 assert(MDOC_ELEM == mdoc->last->type);
215 assert(MDOC_Dt == mdoc->last->tok);
216
217 assert(NULL == mdoc->meta.title);
218
219 /* LINTED */
220 for (i = 0, n = mdoc->last->child; n; n = n->next, i++) {
221 assert(MDOC_TEXT == n->type);
222 p = n->data.text.string;
223
224 switch (i) {
225 case (0):
226 mdoc->meta.title = xstrdup(p);
227 break;
228 case (1):
229 mdoc->meta.msec = mdoc_atomsec(p);
230 if (MSEC_DEFAULT != mdoc->meta.msec)
231 break;
232 return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
233 case (2):
234 mdoc->meta.vol = mdoc_atovol(p);
235 if (VOL_DEFAULT != mdoc->meta.vol)
236 break;
237 mdoc->meta.arch = mdoc_atoarch(p);
238 if (ARCH_DEFAULT != mdoc->meta.arch)
239 break;
240 return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
241 default:
242 return(mdoc_nerr(mdoc, n, "too many parameters"));
243 }
244 }
245
246 if (NULL == mdoc->meta.title)
247 mdoc->meta.title = xstrdup("UNTITLED");
248
249 mdoc_msg(mdoc, "title: %s", mdoc->meta.title);
250
251 return(post_prologue(mdoc));
252 }
253
254
255 /*
256 * Prologue operating system must be parsed into document meta-data.
257 */
258 static int
259 post_os(struct mdoc *mdoc)
260 {
261 char buf[64];
262
263 assert(MDOC_ELEM == mdoc->last->type);
264 assert(MDOC_Os == mdoc->last->tok);
265 assert(NULL == mdoc->meta.os);
266
267 if ( ! xstrlcats(buf, mdoc->last->child, 64))
268 return(mdoc_err(mdoc, "macro parameters too long"));
269
270 mdoc->meta.os = xstrdup(buf[0] ? buf : "local");
271 mdoc->lastnamed = SEC_BODY;
272
273 return(post_prologue(mdoc));
274 }
275
276
277 /*
278 * Prologue date must be parsed into document meta-data.
279 */
280 static int
281 post_dd(struct mdoc *mdoc)
282 {
283 char buf[64];
284
285 assert(MDOC_ELEM == mdoc->last->type);
286 assert(MDOC_Dd == mdoc->last->tok);
287
288 assert(0 == mdoc->meta.date);
289
290 if ( ! xstrlcats(buf, mdoc->last->child, 64))
291 return(mdoc_err(mdoc, "macro parameters too long"));
292 if (0 == (mdoc->meta.date = mdoc_atotime(buf)))
293 return(mdoc_err(mdoc, "invalid parameter syntax"));
294
295 mdoc_msg(mdoc, "date: %u", mdoc->meta.date);
296
297 return(post_prologue(mdoc));
298 }
299
300
301 /*
302 * The end document shouldn't have the prologue macros as part of the
303 * syntax tree (they encompass only meta-data).
304 */
305 static int
306 post_prologue(struct mdoc *mdoc)
307 {
308 struct mdoc_node *n;
309
310 if (mdoc->last->parent->child == mdoc->last)
311 mdoc->last->parent->child = mdoc->last->prev;
312 if (mdoc->last->prev)
313 mdoc->last->prev->next = NULL;
314
315 n = mdoc->last;
316 assert(NULL == mdoc->last->next);
317
318 if (mdoc->last->prev) {
319 mdoc->last = mdoc->last->prev;
320 mdoc->next = MDOC_NEXT_SIBLING;
321 } else {
322 mdoc->last = mdoc->last->parent;
323 mdoc->next = MDOC_NEXT_CHILD;
324 }
325
326 mdoc_node_freelist(n);
327 return(1);
328 }
329
330
331 int
332 mdoc_action_post(struct mdoc *mdoc)
333 {
334
335 if (MDOC_ACTED & mdoc->last->flags)
336 return(1);
337 mdoc->last->flags |= MDOC_ACTED;
338
339 if (MDOC_TEXT == mdoc->last->type)
340 return(1);
341 if (MDOC_ROOT == mdoc->last->type)
342 return(1);
343 if (NULL == mdoc_actions[mdoc->last->tok].post)
344 return(1);
345 return((*mdoc_actions[mdoc->last->tok].post)(mdoc));
346 }