]>
git.cameronkatri.com Git - mandoc.git/blob - action.c
1 /* $Id: action.c,v 1.16 2009/01/21 11:35:26 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
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
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.
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).
32 int (*post
)(struct mdoc
*);
35 /* Per-macro action routines. */
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
*);
43 static int post_prologue(struct mdoc
*);
45 /* Array of macro action routines. */
47 const struct actions mdoc_actions
[MDOC_MAX
] = {
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.
163 post_nm(struct mdoc
*mdoc
)
167 assert(MDOC_ELEM
== mdoc
->last
->type
);
168 assert(MDOC_Nm
== mdoc
->last
->tok
);
173 if (xstrlcats(buf
, mdoc
->last
->child
, 64)) {
174 mdoc
->meta
.name
= xstrdup(buf
);
178 return(mdoc_err(mdoc
, "macro parameters too long"));
183 * We keep track of the current section in order to provide warnings on
184 * section ordering, per-section macros, and so on.
187 post_sh(struct mdoc
*mdoc
)
192 if (MDOC_HEAD
!= mdoc
->last
->type
)
194 if (xstrlcats(buf
, mdoc
->last
->child
, 64)) {
195 if (SEC_CUSTOM
!= (sec
= mdoc_atosec(buf
)))
196 mdoc
->lastnamed
= sec
;
200 return(mdoc_err(mdoc
, "macro parameters too long"));
205 * Prologue title must be parsed into document meta-data.
208 post_dt(struct mdoc
*mdoc
)
214 assert(MDOC_ELEM
== mdoc
->last
->type
);
215 assert(MDOC_Dt
== mdoc
->last
->tok
);
217 assert(NULL
== mdoc
->meta
.title
);
219 for (i
= 0, n
= mdoc
->last
->child
; n
; n
= n
->next
, i
++) {
220 assert(MDOC_TEXT
== n
->type
);
221 p
= n
->data
.text
.string
;
225 mdoc
->meta
.title
= xstrdup(p
);
228 mdoc
->meta
.msec
= mdoc_atomsec(p
);
229 if (MSEC_DEFAULT
!= mdoc
->meta
.msec
)
231 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
233 mdoc
->meta
.vol
= mdoc_atovol(p
);
234 if (VOL_DEFAULT
!= mdoc
->meta
.vol
)
236 mdoc
->meta
.arch
= mdoc_atoarch(p
);
237 if (ARCH_DEFAULT
!= mdoc
->meta
.arch
)
239 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
241 return(mdoc_nerr(mdoc
, n
, "too many parameters"));
245 if (NULL
== mdoc
->meta
.title
)
246 mdoc
->meta
.title
= xstrdup("untitled");
248 mdoc_msg(mdoc
, "title: %s", mdoc
->meta
.title
);
250 return(post_prologue(mdoc
));
255 * Prologue operating system must be parsed into document meta-data.
258 post_os(struct mdoc
*mdoc
)
262 assert(MDOC_ELEM
== mdoc
->last
->type
);
263 assert(MDOC_Os
== mdoc
->last
->tok
);
264 assert(NULL
== mdoc
->meta
.os
);
266 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
267 return(mdoc_err(mdoc
, "macro parameters too long"));
269 mdoc
->meta
.os
= xstrdup(buf
[0] ? buf
: "local");
270 mdoc
->lastnamed
= SEC_BODY
;
272 return(post_prologue(mdoc
));
277 * Prologue date must be parsed into document meta-data.
280 post_dd(struct mdoc
*mdoc
)
284 assert(MDOC_ELEM
== mdoc
->last
->type
);
285 assert(MDOC_Dd
== mdoc
->last
->tok
);
287 assert(0 == mdoc
->meta
.date
);
289 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
290 return(mdoc_err(mdoc
, "macro parameters too long"));
291 if (0 == (mdoc
->meta
.date
= mdoc_atotime(buf
)))
292 return(mdoc_err(mdoc
, "invalid parameter syntax"));
294 mdoc_msg(mdoc
, "date: %u", mdoc
->meta
.date
);
296 return(post_prologue(mdoc
));
301 * The end document shouldn't have the prologue macros as part of the
302 * syntax tree (they encompass only meta-data).
305 post_prologue(struct mdoc
*mdoc
)
309 if (mdoc
->last
->parent
->child
== mdoc
->last
)
310 mdoc
->last
->parent
->child
= mdoc
->last
->prev
;
311 if (mdoc
->last
->prev
)
312 mdoc
->last
->prev
->next
= NULL
;
315 assert(NULL
== mdoc
->last
->next
);
317 if (mdoc
->last
->prev
) {
318 mdoc
->last
= mdoc
->last
->prev
;
319 mdoc
->next
= MDOC_NEXT_SIBLING
;
321 mdoc
->last
= mdoc
->last
->parent
;
322 mdoc
->next
= MDOC_NEXT_CHILD
;
325 mdoc_node_freelist(n
);
331 mdoc_action_post(struct mdoc
*mdoc
)
334 if (MDOC_ACTED
& mdoc
->last
->flags
)
336 mdoc
->last
->flags
|= MDOC_ACTED
;
338 if (MDOC_TEXT
== mdoc
->last
->type
)
340 if (MDOC_ROOT
== mdoc
->last
->type
)
342 if (NULL
== mdoc_actions
[mdoc
->last
->tok
].post
)
344 return((*mdoc_actions
[mdoc
->last
->tok
].post
)(mdoc
));