]>
git.cameronkatri.com Git - mandoc.git/blob - action.c
df5b67695237f5a30f8b2b5076c2d5c04fd5a807
1 /* $Id: action.c,v 1.22 2009/02/27 10:55:16 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.
28 * Actions are executed on macros after they've been post-validated: in
29 * other words, a macro will not be "acted upon" until all of its
30 * children have been filled in (post-fix order).
34 int (*post
)(struct mdoc
*);
37 /* Per-macro action routines. */
39 static int post_bl(struct mdoc
*);
40 static int post_sh(struct mdoc
*);
41 static int post_os(struct mdoc
*);
42 static int post_dt(struct mdoc
*);
43 static int post_dd(struct mdoc
*);
44 static int post_nm(struct mdoc
*);
46 static int post_prologue(struct mdoc
*);
48 /* Array of macro action routines. */
50 const struct actions mdoc_actions
[MDOC_MAX
] = {
161 * The `Nm' macro sets the document's name when used the first time with
162 * an argument. Subsequent calls without a value will result in the
163 * name value being used.
166 post_nm(struct mdoc
*mdoc
)
170 assert(MDOC_ELEM
== mdoc
->last
->type
);
171 assert(MDOC_Nm
== mdoc
->last
->tok
);
176 if (xstrlcats(buf
, mdoc
->last
->child
, 64)) {
177 mdoc
->meta
.name
= xstrdup(buf
);
181 return(mdoc_err(mdoc
, "macro parameters too long"));
186 * We keep track of the current section in order to provide warnings on
187 * section ordering, per-section macros, and so on.
190 post_sh(struct mdoc
*mdoc
)
195 if (MDOC_HEAD
!= mdoc
->last
->type
)
197 if (xstrlcats(buf
, mdoc
->last
->child
, 64)) {
198 if (SEC_CUSTOM
!= (sec
= mdoc_atosec(buf
)))
199 mdoc
->lastnamed
= sec
;
204 return(mdoc_err(mdoc
, "macro parameters too long"));
209 * Prologue title must be parsed into document meta-data.
212 post_dt(struct mdoc
*mdoc
)
218 assert(MDOC_ELEM
== mdoc
->last
->type
);
219 assert(MDOC_Dt
== mdoc
->last
->tok
);
221 assert(NULL
== mdoc
->meta
.title
);
224 for (i
= 0, n
= mdoc
->last
->child
; n
; n
= n
->next
, i
++) {
225 assert(MDOC_TEXT
== n
->type
);
226 p
= n
->data
.text
.string
;
230 mdoc
->meta
.title
= xstrdup(p
);
233 mdoc
->meta
.msec
= mdoc_atomsec(p
);
234 if (MSEC_DEFAULT
!= mdoc
->meta
.msec
)
236 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
238 mdoc
->meta
.vol
= mdoc_atovol(p
);
239 if (VOL_DEFAULT
!= mdoc
->meta
.vol
)
241 mdoc
->meta
.arch
= mdoc_atoarch(p
);
242 if (ARCH_DEFAULT
!= mdoc
->meta
.arch
)
244 return(mdoc_nerr(mdoc
, n
, "invalid parameter syntax"));
246 return(mdoc_nerr(mdoc
, n
, "too many parameters"));
250 if (NULL
== mdoc
->meta
.title
)
251 mdoc
->meta
.title
= xstrdup("UNTITLED");
253 mdoc_msg(mdoc
, "title: %s", mdoc
->meta
.title
);
255 return(post_prologue(mdoc
));
260 * Prologue operating system must be parsed into document meta-data.
263 post_os(struct mdoc
*mdoc
)
267 assert(MDOC_ELEM
== mdoc
->last
->type
);
268 assert(MDOC_Os
== mdoc
->last
->tok
);
269 assert(NULL
== mdoc
->meta
.os
);
271 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
272 return(mdoc_err(mdoc
, "macro parameters too long"));
274 mdoc
->meta
.os
= xstrdup(buf
[0] ? buf
: "LOCAL");
275 mdoc
->lastnamed
= SEC_BODY
;
277 return(post_prologue(mdoc
));
282 * Transform -width MACRO values into real widths.
285 post_bl(struct mdoc
*mdoc
)
287 struct mdoc_block
*bl
;
292 if (MDOC_BLOCK
!= mdoc
->last
->type
)
295 bl
= &mdoc
->last
->data
.block
;
297 for (i
= 0; i
< (int)bl
->argc
; i
++)
298 if (MDOC_Width
== bl
->argv
[i
].arg
)
301 if (i
== (int)bl
->argc
)
304 assert(1 == bl
->argv
[i
].sz
);
305 if (MDOC_MAX
== (tok
= mdoc_find(mdoc
, *bl
->argv
[i
].value
)))
308 if (0 == (width
= mdoc_macro2len(tok
)))
309 return(mdoc_warn(mdoc
, WARN_SYNTAX
,
310 "-%s macro has no length",
311 mdoc_argnames
[MDOC_Width
]));
313 mdoc_msg(mdoc
, "re-writing %s argument: %s -> %zun",
314 mdoc_argnames
[MDOC_Width
],
315 *bl
->argv
[i
].value
, width
);
317 /* FIXME: silently truncates. */
318 (void)snprintf(buf
, sizeof(buf
), "%zun", width
);
320 free(*bl
->argv
[i
].value
);
321 *bl
->argv
[i
].value
= strdup(buf
);
328 * Prologue date must be parsed into document meta-data.
331 post_dd(struct mdoc
*mdoc
)
335 assert(MDOC_ELEM
== mdoc
->last
->type
);
336 assert(MDOC_Dd
== mdoc
->last
->tok
);
338 assert(0 == mdoc
->meta
.date
);
340 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
341 return(mdoc_err(mdoc
, "macro parameters too long"));
342 if (0 == (mdoc
->meta
.date
= mdoc_atotime(buf
)))
343 return(mdoc_err(mdoc
, "invalid parameter syntax"));
345 mdoc_msg(mdoc
, "date: %u", mdoc
->meta
.date
);
347 return(post_prologue(mdoc
));
352 * The end document shouldn't have the prologue macros as part of the
353 * syntax tree (they encompass only meta-data).
356 post_prologue(struct mdoc
*mdoc
)
360 if (mdoc
->last
->parent
->child
== mdoc
->last
)
361 mdoc
->last
->parent
->child
= mdoc
->last
->prev
;
362 if (mdoc
->last
->prev
)
363 mdoc
->last
->prev
->next
= NULL
;
366 assert(NULL
== mdoc
->last
->next
);
368 if (mdoc
->last
->prev
) {
369 mdoc
->last
= mdoc
->last
->prev
;
370 mdoc
->next
= MDOC_NEXT_SIBLING
;
372 mdoc
->last
= mdoc
->last
->parent
;
373 mdoc
->next
= MDOC_NEXT_CHILD
;
376 mdoc_node_freelist(n
);
382 mdoc_action_post(struct mdoc
*mdoc
)
385 if (MDOC_ACTED
& mdoc
->last
->flags
)
387 mdoc
->last
->flags
|= MDOC_ACTED
;
389 if (MDOC_TEXT
== mdoc
->last
->type
)
391 if (MDOC_ROOT
== mdoc
->last
->type
)
393 if (NULL
== mdoc_actions
[mdoc
->last
->tok
].post
)
395 return((*mdoc_actions
[mdoc
->last
->tok
].post
)(mdoc
));