]>
git.cameronkatri.com Git - mandoc.git/blob - action.c
1 /* $Id: action.c,v 1.18 2009/02/21 21:00:06 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
);
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
;
226 mdoc
->meta
.title
= xstrdup(p
);
229 mdoc
->meta
.msec
= mdoc_atomsec(p
);
230 if (MSEC_DEFAULT
!= mdoc
->meta
.msec
)
232 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
234 mdoc
->meta
.vol
= mdoc_atovol(p
);
235 if (VOL_DEFAULT
!= mdoc
->meta
.vol
)
237 mdoc
->meta
.arch
= mdoc_atoarch(p
);
238 if (ARCH_DEFAULT
!= mdoc
->meta
.arch
)
240 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
242 return(mdoc_nerr(mdoc
, n
, "too many parameters"));
246 if (NULL
== mdoc
->meta
.title
)
247 mdoc
->meta
.title
= xstrdup("UNTITLED");
249 mdoc_msg(mdoc
, "title: %s", mdoc
->meta
.title
);
251 return(post_prologue(mdoc
));
256 * Prologue operating system must be parsed into document meta-data.
259 post_os(struct mdoc
*mdoc
)
263 assert(MDOC_ELEM
== mdoc
->last
->type
);
264 assert(MDOC_Os
== mdoc
->last
->tok
);
265 assert(NULL
== mdoc
->meta
.os
);
267 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
268 return(mdoc_err(mdoc
, "macro parameters too long"));
270 mdoc
->meta
.os
= xstrdup(buf
[0] ? buf
: "local");
271 mdoc
->lastnamed
= SEC_BODY
;
273 return(post_prologue(mdoc
));
278 * Prologue date must be parsed into document meta-data.
281 post_dd(struct mdoc
*mdoc
)
285 assert(MDOC_ELEM
== mdoc
->last
->type
);
286 assert(MDOC_Dd
== mdoc
->last
->tok
);
288 assert(0 == mdoc
->meta
.date
);
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"));
295 mdoc_msg(mdoc
, "date: %u", mdoc
->meta
.date
);
297 return(post_prologue(mdoc
));
302 * The end document shouldn't have the prologue macros as part of the
303 * syntax tree (they encompass only meta-data).
306 post_prologue(struct mdoc
*mdoc
)
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
;
316 assert(NULL
== mdoc
->last
->next
);
318 if (mdoc
->last
->prev
) {
319 mdoc
->last
= mdoc
->last
->prev
;
320 mdoc
->next
= MDOC_NEXT_SIBLING
;
322 mdoc
->last
= mdoc
->last
->parent
;
323 mdoc
->next
= MDOC_NEXT_CHILD
;
326 mdoc_node_freelist(n
);
332 mdoc_action_post(struct mdoc
*mdoc
)
335 if (MDOC_ACTED
& mdoc
->last
->flags
)
337 mdoc
->last
->flags
|= MDOC_ACTED
;
339 if (MDOC_TEXT
== mdoc
->last
->type
)
341 if (MDOC_ROOT
== mdoc
->last
->type
)
343 if (NULL
== mdoc_actions
[mdoc
->last
->tok
].post
)
345 return((*mdoc_actions
[mdoc
->last
->tok
].post
)(mdoc
));