]>
git.cameronkatri.com Git - mandoc.git/blob - action.c
1 /* $Id: action.c,v 1.19 2009/02/22 14:31:08 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
;
201 return(mdoc_err(mdoc
, "macro parameters too long"));
206 * Prologue title must be parsed into document meta-data.
209 post_dt(struct mdoc
*mdoc
)
215 assert(MDOC_ELEM
== mdoc
->last
->type
);
216 assert(MDOC_Dt
== mdoc
->last
->tok
);
218 assert(NULL
== mdoc
->meta
.title
);
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
;
227 mdoc
->meta
.title
= xstrdup(p
);
230 mdoc
->meta
.msec
= mdoc_atomsec(p
);
231 if (MSEC_DEFAULT
!= mdoc
->meta
.msec
)
233 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
235 mdoc
->meta
.vol
= mdoc_atovol(p
);
236 if (VOL_DEFAULT
!= mdoc
->meta
.vol
)
238 mdoc
->meta
.arch
= mdoc_atoarch(p
);
239 if (ARCH_DEFAULT
!= mdoc
->meta
.arch
)
241 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
243 return(mdoc_nerr(mdoc
, n
, "too many parameters"));
247 if (NULL
== mdoc
->meta
.title
)
248 mdoc
->meta
.title
= xstrdup("UNTITLED");
250 mdoc_msg(mdoc
, "title: %s", mdoc
->meta
.title
);
252 return(post_prologue(mdoc
));
257 * Prologue operating system must be parsed into document meta-data.
260 post_os(struct mdoc
*mdoc
)
264 assert(MDOC_ELEM
== mdoc
->last
->type
);
265 assert(MDOC_Os
== mdoc
->last
->tok
);
266 assert(NULL
== mdoc
->meta
.os
);
268 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
269 return(mdoc_err(mdoc
, "macro parameters too long"));
271 mdoc
->meta
.os
= xstrdup(buf
[0] ? buf
: "local");
272 mdoc
->lastnamed
= SEC_BODY
;
274 return(post_prologue(mdoc
));
279 * Prologue date must be parsed into document meta-data.
282 post_dd(struct mdoc
*mdoc
)
286 assert(MDOC_ELEM
== mdoc
->last
->type
);
287 assert(MDOC_Dd
== mdoc
->last
->tok
);
289 assert(0 == mdoc
->meta
.date
);
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"));
296 mdoc_msg(mdoc
, "date: %u", mdoc
->meta
.date
);
298 return(post_prologue(mdoc
));
303 * The end document shouldn't have the prologue macros as part of the
304 * syntax tree (they encompass only meta-data).
307 post_prologue(struct mdoc
*mdoc
)
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
;
317 assert(NULL
== mdoc
->last
->next
);
319 if (mdoc
->last
->prev
) {
320 mdoc
->last
= mdoc
->last
->prev
;
321 mdoc
->next
= MDOC_NEXT_SIBLING
;
323 mdoc
->last
= mdoc
->last
->parent
;
324 mdoc
->next
= MDOC_NEXT_CHILD
;
327 mdoc_node_freelist(n
);
333 mdoc_action_post(struct mdoc
*mdoc
)
336 if (MDOC_ACTED
& mdoc
->last
->flags
)
338 mdoc
->last
->flags
|= MDOC_ACTED
;
340 if (MDOC_TEXT
== mdoc
->last
->type
)
342 if (MDOC_ROOT
== mdoc
->last
->type
)
344 if (NULL
== mdoc_actions
[mdoc
->last
->tok
].post
)
346 return((*mdoc_actions
[mdoc
->last
->tok
].post
)(mdoc
));