]>
git.cameronkatri.com Git - mandoc.git/blob - action.c
1 /* $Id: action.c,v 1.30 2009/03/05 13:12:12 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_ar(struct mdoc
*);
40 static int post_bl(struct mdoc
*);
41 static int post_bl_width(struct mdoc
*);
42 static int post_bl_tagwidth(struct mdoc
*);
43 static int post_dd(struct mdoc
*);
44 static int post_dt(struct mdoc
*);
45 static int post_nm(struct mdoc
*);
46 static int post_os(struct mdoc
*);
47 static int post_sh(struct mdoc
*);
48 static int post_ex(struct mdoc
*);
50 static int post_prologue(struct mdoc
*);
52 /* Array of macro action routines. */
54 const struct actions mdoc_actions
[MDOC_MAX
] = {
165 post_ex(struct mdoc
*mdoc
)
169 * If `.Ex -std' is invoked without an argument, fill it in with
170 * our name (if it's been set).
173 if (0 == mdoc
->last
->data
.elem
.argc
)
175 if (mdoc
->last
->data
.elem
.argv
[0].sz
)
178 assert(mdoc
->meta
.name
);
180 mdoc_msg(mdoc
, "writing %s argument: %s",
181 mdoc_argnames
[MDOC_Std
], mdoc
->meta
.name
);
183 mdoc
->last
->data
.elem
.argv
[0].sz
= 1;
184 mdoc
->last
->data
.elem
.argv
[0].value
= xcalloc(1, sizeof(char *));
185 mdoc
->last
->data
.elem
.argv
[0].value
[0] = xstrdup(mdoc
->meta
.name
);
191 post_nm(struct mdoc
*mdoc
)
195 assert(MDOC_ELEM
== mdoc
->last
->type
);
196 assert(MDOC_Nm
== mdoc
->last
->tok
);
199 * The `Nm' macro sets the document's name when used the first
200 * time with an argument. Subsequent calls without a value will
201 * result in the name value being used.
207 if (xstrlcats(buf
, mdoc
->last
->child
, 64)) {
208 mdoc
->meta
.name
= xstrdup(buf
);
212 return(mdoc_err(mdoc
, "macro parameters too long"));
217 post_sh(struct mdoc
*mdoc
)
223 * We keep track of the current section /and/ the "named"
224 * section, which is one of the conventional ones, in order to
228 if (MDOC_HEAD
!= mdoc
->last
->type
)
230 if (xstrlcats(buf
, mdoc
->last
->child
, 64)) {
231 if (SEC_CUSTOM
!= (sec
= mdoc_atosec(buf
)))
232 mdoc
->lastnamed
= sec
;
235 return(mdoc_err(mdoc
, "parameters too long"));
237 switch (mdoc
->lastsec
) {
238 case (SEC_RETURN_VALUES
):
241 switch (mdoc
->meta
.msec
) {
249 return(mdoc_warn(mdoc
, WARN_COMPAT
,
250 "inappropriate section for "
262 post_dt(struct mdoc
*mdoc
)
269 * Prologue title must be parsed into document meta-data.
272 assert(MDOC_ELEM
== mdoc
->last
->type
);
273 assert(MDOC_Dt
== mdoc
->last
->tok
);
275 assert(NULL
== mdoc
->meta
.title
);
278 for (i
= 0, n
= mdoc
->last
->child
; n
; n
= n
->next
, i
++) {
279 assert(MDOC_TEXT
== n
->type
);
280 p
= n
->data
.text
.string
;
284 mdoc
->meta
.title
= xstrdup(p
);
287 mdoc
->meta
.msec
= mdoc_atomsec(p
);
288 if (MSEC_DEFAULT
!= mdoc
->meta
.msec
)
290 return(mdoc_nerr(mdoc
, n
,
291 "invalid parameter syntax"));
293 mdoc
->meta
.vol
= mdoc_atovol(p
);
294 if (VOL_DEFAULT
!= mdoc
->meta
.vol
)
296 mdoc
->meta
.arch
= mdoc_atoarch(p
);
297 if (ARCH_DEFAULT
!= mdoc
->meta
.arch
)
299 return(mdoc_nerr(mdoc
, n
,
300 "invalid parameter syntax"));
302 return(mdoc_nerr(mdoc
, n
,
303 "too many parameters"));
307 if (NULL
== mdoc
->meta
.title
)
308 mdoc
->meta
.title
= xstrdup("UNTITLED");
310 mdoc_msg(mdoc
, "title: %s", mdoc
->meta
.title
);
312 return(post_prologue(mdoc
));
317 post_os(struct mdoc
*mdoc
)
322 * Prologue operating system must be parsed into document
326 assert(MDOC_ELEM
== mdoc
->last
->type
);
327 assert(MDOC_Os
== mdoc
->last
->tok
);
328 assert(NULL
== mdoc
->meta
.os
);
330 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
331 return(mdoc_err(mdoc
, "macro parameters too long"));
333 mdoc
->meta
.os
= xstrdup(buf
[0] ? buf
: "LOCAL");
334 mdoc
->lastnamed
= SEC_BODY
;
336 return(post_prologue(mdoc
));
341 post_bl_tagwidth(struct mdoc
*mdoc
)
344 struct mdoc_block
*b
;
349 * If -tag has been specified and -width has not been, then try
350 * to intuit our width from the first body element.
353 b
= &mdoc
->last
->data
.block
;
355 if (NULL
== (n
= b
->body
->child
))
357 assert(MDOC_It
== n
->tok
);
360 * Use the text width, if a text node, or the default macro
364 if ((n
= n
->data
.block
.head
->child
)) {
365 if (MDOC_TEXT
!= n
->type
) {
366 if (0 == (sz
= mdoc_macro2len(n
->tok
)))
369 sz
= (int)strlen(n
->data
.text
.string
) + 1;
374 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
,
375 "cannot determine default %s",
376 mdoc_argnames
[MDOC_Width
]))
381 (void)snprintf(buf
, sizeof(buf
), "%dn", sz
);
384 * We have to dynamically add this to the macro's argument list.
385 * We're guaranteed that a MDOC_Width doesn't already exist.
389 b
->argv
= xrealloc(b
->argv
, b
->argc
* sizeof(struct mdoc_arg
));
391 b
->argv
[b
->argc
- 1].arg
= MDOC_Width
;
392 b
->argv
[b
->argc
- 1].line
= mdoc
->last
->line
;
393 b
->argv
[b
->argc
- 1].pos
= mdoc
->last
->pos
;
394 b
->argv
[b
->argc
- 1].sz
= 1;
395 b
->argv
[b
->argc
- 1].value
= xcalloc(1, sizeof(char *));
396 b
->argv
[b
->argc
- 1].value
[0] = xstrdup(buf
);
398 mdoc_msg(mdoc
, "adding %s argument: %dn",
399 mdoc_argnames
[MDOC_Width
], sz
);
406 post_bl_width(struct mdoc
*mdoc
)
413 for (i
= 0; i
< (int)mdoc
->last
->data
.block
.argc
; i
++)
414 if (MDOC_Width
== mdoc
->last
->data
.block
.argv
[i
].arg
)
417 assert(i
< (int)mdoc
->last
->data
.block
.argc
);
418 assert(1 == mdoc
->last
->data
.block
.argv
[i
].sz
);
419 p
= &mdoc
->last
->data
.block
.argv
[i
].value
[0];
422 * If the value to -width is a macro, then we re-write it to be
423 * the macro's width as set in share/tmac/mdoc/doc-common.
426 if (xstrcmp(*p
, "Ds"))
428 else if (MDOC_MAX
== (tok
= mdoc_find(mdoc
, *p
)))
430 else if (0 == (width
= mdoc_macro2len(tok
)))
431 return(mdoc_warn(mdoc
, WARN_SYNTAX
,
432 "%s macro has no length",
433 mdoc_argnames
[MDOC_Width
]));
435 mdoc_msg(mdoc
, "re-writing %s argument: %s -> %zun",
436 mdoc_argnames
[MDOC_Width
], *p
, width
);
438 /* The value already exists: free and reallocate it. */
440 (void)snprintf(buf
, sizeof(buf
), "%zun", width
);
450 post_bl(struct mdoc
*mdoc
)
454 if (MDOC_BLOCK
!= mdoc
->last
->type
)
458 * These are fairly complicated, so we've broken them into two
459 * functions. post_bl_tagwidth() is called when a -tag is
460 * specified, but no -width (it must be guessed). The second
461 * when a -width is specified (macro indicators must be
462 * rewritten into real lengths).
465 for (r
= i
= 0; i
< (int)mdoc
->last
->data
.block
.argc
; i
++) {
466 if (MDOC_Tag
== mdoc
->last
->data
.block
.argv
[i
].arg
)
468 if (MDOC_Width
== mdoc
->last
->data
.block
.argv
[i
].arg
)
472 if (r
& (1 << 0) && ! (r
& (1 << 1))) {
473 if ( ! post_bl_tagwidth(mdoc
))
475 } else if (r
& (1 << 1))
476 if ( ! post_bl_width(mdoc
))
484 post_ar(struct mdoc
*mdoc
)
488 if (mdoc
->last
->child
)
493 mdoc
->next
= MDOC_NEXT_CHILD
;
494 mdoc_word_alloc(mdoc
, mdoc
->last
->line
,
495 mdoc
->last
->pos
, "file");
496 mdoc
->next
= MDOC_NEXT_SIBLING
;
497 mdoc_word_alloc(mdoc
, mdoc
->last
->line
,
498 mdoc
->last
->pos
, "...");
501 mdoc
->next
= MDOC_NEXT_SIBLING
;
507 post_dd(struct mdoc
*mdoc
)
512 * Prologue date must be parsed into document meta-data. We
513 * accept multiple kinds of dates, described mostly in
517 assert(MDOC_ELEM
== mdoc
->last
->type
);
518 assert(MDOC_Dd
== mdoc
->last
->tok
);
520 assert(0 == mdoc
->meta
.date
);
522 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
523 return(mdoc_err(mdoc
, "macro parameters too long"));
524 if (0 == (mdoc
->meta
.date
= mdoc_atotime(buf
)))
525 return(mdoc_err(mdoc
, "invalid parameter syntax"));
527 mdoc_msg(mdoc
, "date: %u", mdoc
->meta
.date
);
529 return(post_prologue(mdoc
));
534 post_prologue(struct mdoc
*mdoc
)
539 * The end document shouldn't have the prologue macros as part
540 * of the syntax tree (they encompass only meta-data).
543 if (mdoc
->last
->parent
->child
== mdoc
->last
)
544 mdoc
->last
->parent
->child
= mdoc
->last
->prev
;
545 if (mdoc
->last
->prev
)
546 mdoc
->last
->prev
->next
= NULL
;
549 assert(NULL
== mdoc
->last
->next
);
551 if (mdoc
->last
->prev
) {
552 mdoc
->last
= mdoc
->last
->prev
;
553 mdoc
->next
= MDOC_NEXT_SIBLING
;
555 mdoc
->last
= mdoc
->last
->parent
;
556 mdoc
->next
= MDOC_NEXT_CHILD
;
559 mdoc_node_freelist(n
);
565 mdoc_action_post(struct mdoc
*mdoc
)
568 if (MDOC_ACTED
& mdoc
->last
->flags
)
570 mdoc
->last
->flags
|= MDOC_ACTED
;
572 if (MDOC_TEXT
== mdoc
->last
->type
)
574 if (MDOC_ROOT
== mdoc
->last
->type
)
576 if (NULL
== mdoc_actions
[mdoc
->last
->tok
].post
)
578 return((*mdoc_actions
[mdoc
->last
->tok
].post
)(mdoc
));