]>
git.cameronkatri.com Git - mandoc.git/blob - action.c
6203136855e4ab35445771d6b014fd497fe764b2
1 /* $Id: action.c,v 1.34 2009/03/08 12:40:27 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.
19 #include <sys/utsname.h>
31 * Actions are executed on macros after they've been post-validated: in
32 * other words, a macro will not be "acted upon" until all of its
33 * children have been filled in (post-fix order).
47 int (*post
)(struct mdoc
*);
50 static int nwarn(struct mdoc
*,
51 const struct mdoc_node
*, enum mwarn
);
52 static int nerr(struct mdoc
*,
53 const struct mdoc_node
*, enum merr
);
54 static int post_ar(struct mdoc
*);
55 static int post_bl(struct mdoc
*);
56 static int post_bl_width(struct mdoc
*);
57 static int post_bl_tagwidth(struct mdoc
*);
58 static int post_dd(struct mdoc
*);
59 static int post_dt(struct mdoc
*);
60 static int post_nm(struct mdoc
*);
61 static int post_os(struct mdoc
*);
62 static int post_sh(struct mdoc
*);
63 static int post_ex(struct mdoc
*);
64 static int post_prologue(struct mdoc
*);
66 const struct actions mdoc_actions
[MDOC_MAX
] = {
177 #define merr(m, t) nerr((m), (m)->last, (t))
179 nerr(struct mdoc
*m
, const struct mdoc_node
*n
, enum merr type
)
187 p
= "missing width argument";
192 return(mdoc_nerr(m
, n
, p
));
196 #define mwarn(m, t) nwarn((m), (m)->last, (t))
198 nwarn(struct mdoc
*m
, const struct mdoc_node
*n
, enum mwarn type
)
208 p
= "inappropriate document section in manual section";
212 p
= "cannot determine default width";
215 p
= "malformed date syntax";
220 return(mdoc_nwarn(m
, n
, c
, p
));
225 post_ex(struct mdoc
*mdoc
)
229 * If `.Ex -std' is invoked without an argument, fill it in with
230 * our name (if it's been set).
233 if (NULL
== mdoc
->last
->args
)
235 if (mdoc
->last
->args
->argv
[0].sz
)
238 assert(mdoc
->meta
.name
);
240 mdoc_msg(mdoc
, "writing %s argument: %s",
241 mdoc_argnames
[MDOC_Std
],
244 assert(1 == mdoc
->last
->args
->argv
[0].sz
);
246 mdoc
->last
->args
->argv
[0].sz
= 1;
247 mdoc
->last
->args
->argv
[0].value
= xcalloc(1, sizeof(char *));
248 mdoc
->last
->args
->argv
[0].value
[0] = xstrdup(mdoc
->meta
.name
);
254 post_nm(struct mdoc
*mdoc
)
261 (void)xstrlcpys(buf
, mdoc
->last
->child
, sizeof(buf
));
262 mdoc
->meta
.name
= xstrdup(buf
);
263 mdoc_msg(mdoc
, "name: %s", mdoc
->meta
.name
);
270 post_sh(struct mdoc
*mdoc
)
276 * We keep track of the current section /and/ the "named"
277 * section, which is one of the conventional ones, in order to
281 if (MDOC_HEAD
!= mdoc
->last
->type
)
284 (void)xstrlcpys(buf
, mdoc
->last
->child
, sizeof(buf
));
285 if (SEC_CUSTOM
!= (sec
= mdoc_atosec(buf
)))
286 mdoc
->lastnamed
= sec
;
290 switch (mdoc
->lastsec
) {
291 case (SEC_RETURN_VALUES
):
294 switch (mdoc
->meta
.msec
) {
302 return(mwarn(mdoc
, WBADSEC
));
313 post_dt(struct mdoc
*mdoc
)
320 if (mdoc
->meta
.title
)
321 free(mdoc
->meta
.title
);
323 free(mdoc
->meta
.vol
);
325 free(mdoc
->meta
.arch
);
327 mdoc
->meta
.title
= mdoc
->meta
.vol
= mdoc
->meta
.arch
= NULL
;
331 * --> title = unknown, volume = local, msec = 0, arch = NULL
334 if (NULL
== (n
= mdoc
->last
->child
)) {
335 mdoc
->meta
.title
= xstrdup("unknown");
336 mdoc
->meta
.vol
= xstrdup("local");
337 mdoc_msg(mdoc
, "title: %s", mdoc
->meta
.title
);
338 mdoc_msg(mdoc
, "volume: %s", mdoc
->meta
.vol
);
339 mdoc_msg(mdoc
, "arch: <unset>");
340 mdoc_msg(mdoc
, "msec: <unset>");
341 return(post_prologue(mdoc
));
344 /* Handles: `.Dt TITLE'
345 * --> title = TITLE, volume = local, msec = 0, arch = NULL
348 mdoc
->meta
.title
= xstrdup(n
->string
);
349 mdoc_msg(mdoc
, "title: %s", mdoc
->meta
.title
);
351 if (NULL
== (n
= n
->next
)) {
352 mdoc
->meta
.vol
= xstrdup("local");
353 mdoc_msg(mdoc
, "volume: %s", mdoc
->meta
.vol
);
354 mdoc_msg(mdoc
, "arch: <unset>");
355 mdoc_msg(mdoc
, "msec: %d", mdoc
->meta
.msec
);
356 return(post_prologue(mdoc
));
359 /* Handles: `.Dt TITLE SEC'
360 * --> title = TITLE, volume = SEC is msec ?
361 * format(msec) : SEC,
362 * msec = SEC is msec ? atoi(msec) : 0,
366 if ((cp
= mdoc_a2msec(n
->string
))) {
367 mdoc
->meta
.vol
= xstrdup(cp
);
369 lval
= strtol(n
->string
, &ep
, 10);
370 if (n
->string
[0] != '\0' && *ep
== '\0')
371 mdoc
->meta
.msec
= (int)lval
;
373 mdoc
->meta
.vol
= xstrdup(n
->string
);
375 if (NULL
== (n
= n
->next
)) {
376 mdoc_msg(mdoc
, "volume: %s", mdoc
->meta
.vol
);
377 mdoc_msg(mdoc
, "arch: <unset>");
378 mdoc_msg(mdoc
, "msec: %d", mdoc
->meta
.msec
);
379 return(post_prologue(mdoc
));
382 /* Handles: `.Dt TITLE SEC VOL'
383 * --> title = TITLE, volume = VOL is vol ?
385 * VOL is arch ? format(arch) :
389 if ((cp
= mdoc_a2vol(n
->string
))) {
390 free(mdoc
->meta
.vol
);
391 mdoc
->meta
.vol
= xstrdup(cp
);
394 cp
= mdoc_a2arch(n
->string
);
396 free(mdoc
->meta
.vol
);
397 mdoc
->meta
.vol
= xstrdup(n
->string
);
399 mdoc
->meta
.arch
= xstrdup(cp
);
402 mdoc_msg(mdoc
, "volume: %s", mdoc
->meta
.vol
);
403 mdoc_msg(mdoc
, "arch: %s", mdoc
->meta
.arch
?
404 mdoc
->meta
.arch
: "<unset>");
405 mdoc_msg(mdoc
, "msec: %d", mdoc
->meta
.msec
);
407 /* Ignore any subsequent parameters... */
409 return(post_prologue(mdoc
));
414 post_os(struct mdoc
*mdoc
)
417 struct utsname utsname
;
422 (void)xstrlcpys(buf
, mdoc
->last
->child
, sizeof(buf
));
425 if (-1 == uname(&utsname
))
426 return(mdoc_err(mdoc
, "utsname"));
427 (void)xstrlcpy(buf
, utsname
.sysname
, sizeof(buf
));
428 (void)xstrlcat(buf
, " ", sizeof(buf
));
429 (void)xstrlcat(buf
, utsname
.release
, sizeof(buf
));
432 mdoc
->meta
.os
= xstrdup(buf
);
433 mdoc_msg(mdoc
, "system: %s", mdoc
->meta
.os
);
435 mdoc
->lastnamed
= mdoc
->lastsec
= SEC_BODY
;
437 return(post_prologue(mdoc
));
442 post_bl_tagwidth(struct mdoc
*mdoc
)
449 * If -tag has been specified and -width has not been, then try
450 * to intuit our width from the first body element.
453 if (NULL
== (n
= mdoc
->last
->body
->child
))
457 * Use the text width, if a text node, or the default macro
461 if ((n
= n
->head
->child
)) {
462 if (MDOC_TEXT
!= n
->type
) {
463 if (0 == (sz
= (int)mdoc_macro2len(n
->tok
)))
466 sz
= (int)strlen(n
->string
) + 1;
471 if ( ! mwarn(mdoc
, WNOWIDTH
))
476 (void)snprintf(buf
, sizeof(buf
), "%dn", sz
);
479 * We have to dynamically add this to the macro's argument list.
480 * We're guaranteed that a MDOC_Width doesn't already exist.
483 if (NULL
== mdoc
->last
->args
) {
484 mdoc
->last
->args
= xcalloc
485 (1, sizeof(struct mdoc_arg
));
486 mdoc
->last
->args
->refcnt
= 1;
490 sz
= (int)n
->args
->argc
;
494 n
->args
->argv
= xrealloc(n
->args
->argv
,
495 n
->args
->argc
* sizeof(struct mdoc_arg
));
497 n
->args
->argv
[sz
- 1].arg
= MDOC_Width
;
498 n
->args
->argv
[sz
- 1].line
= mdoc
->last
->line
;
499 n
->args
->argv
[sz
- 1].pos
= mdoc
->last
->pos
;
500 n
->args
->argv
[sz
- 1].sz
= 1;
501 n
->args
->argv
[sz
- 1].value
= xcalloc(1, sizeof(char *));
502 n
->args
->argv
[sz
- 1].value
[0] = xstrdup(buf
);
504 mdoc_msg(mdoc
, "adding %s argument: %s",
505 mdoc_argnames
[MDOC_Width
], buf
);
512 post_bl_width(struct mdoc
*m
)
519 if (NULL
== m
->last
->args
)
520 return(merr(m
, ENOWIDTH
));
522 for (i
= 0; i
< (int)m
->last
->args
->argc
; i
++)
523 if (MDOC_Width
== m
->last
->args
->argv
[i
].arg
)
526 if (i
== (int)m
->last
->args
->argc
)
527 return(merr(m
, ENOWIDTH
));
529 p
= m
->last
->args
->argv
[i
].value
[0];
532 * If the value to -width is a macro, then we re-write it to be
533 * the macro's width as set in share/tmac/mdoc/doc-common.
536 if (xstrcmp(p
, "Ds"))
538 else if (MDOC_MAX
== (tok
= mdoc_tokhash_find(m
->htab
, p
)))
540 else if (0 == (width
= mdoc_macro2len(tok
)))
541 return(mwarn(m
, WNOWIDTH
));
543 mdoc_msg(m
, "re-writing %s argument: %s -> %zun",
544 mdoc_argnames
[MDOC_Width
], p
, width
);
546 /* The value already exists: free and reallocate it. */
548 (void)snprintf(buf
, sizeof(buf
), "%zun", width
);
550 free(m
->last
->args
->argv
[i
].value
[0]);
551 m
->last
->args
->argv
[i
].value
[0] = xstrdup(buf
);
558 post_bl(struct mdoc
*mdoc
)
562 if (MDOC_BLOCK
!= mdoc
->last
->type
)
566 * These are fairly complicated, so we've broken them into two
567 * functions. post_bl_tagwidth() is called when a -tag is
568 * specified, but no -width (it must be guessed). The second
569 * when a -width is specified (macro indicators must be
570 * rewritten into real lengths).
573 len
= (int)(mdoc
->last
->args
? mdoc
->last
->args
->argc
: 0);
575 for (r
= i
= 0; i
< len
; i
++) {
576 if (MDOC_Tag
== mdoc
->last
->args
->argv
[i
].arg
)
578 if (MDOC_Width
== mdoc
->last
->args
->argv
[i
].arg
)
582 if (r
& (1 << 0) && ! (r
& (1 << 1))) {
583 if ( ! post_bl_tagwidth(mdoc
))
585 } else if (r
& (1 << 1))
586 if ( ! post_bl_width(mdoc
))
594 post_ar(struct mdoc
*mdoc
)
598 if (mdoc
->last
->child
)
603 mdoc
->next
= MDOC_NEXT_CHILD
;
604 if ( ! mdoc_word_alloc(mdoc
, mdoc
->last
->line
,
605 mdoc
->last
->pos
, "file"))
607 mdoc
->next
= MDOC_NEXT_SIBLING
;
608 if ( ! mdoc_word_alloc(mdoc
, mdoc
->last
->line
,
609 mdoc
->last
->pos
, "..."))
613 mdoc
->next
= MDOC_NEXT_SIBLING
;
619 post_dd(struct mdoc
*mdoc
)
623 (void)xstrlcpys(buf
, mdoc
->last
->child
, sizeof(buf
));
625 if (0 == (mdoc
->meta
.date
= mdoc_atotime(buf
))) {
626 if ( ! mwarn(mdoc
, WBADDATE
))
628 mdoc
->meta
.date
= time(NULL
);
631 mdoc_msg(mdoc
, "date: %u", mdoc
->meta
.date
);
632 return(post_prologue(mdoc
));
637 post_prologue(struct mdoc
*mdoc
)
642 * The end document shouldn't have the prologue macros as part
643 * of the syntax tree (they encompass only meta-data).
646 if (mdoc
->last
->parent
->child
== mdoc
->last
)
647 mdoc
->last
->parent
->child
= mdoc
->last
->prev
;
648 if (mdoc
->last
->prev
)
649 mdoc
->last
->prev
->next
= NULL
;
652 assert(NULL
== mdoc
->last
->next
);
654 if (mdoc
->last
->prev
) {
655 mdoc
->last
= mdoc
->last
->prev
;
656 mdoc
->next
= MDOC_NEXT_SIBLING
;
658 mdoc
->last
= mdoc
->last
->parent
;
659 mdoc
->next
= MDOC_NEXT_CHILD
;
662 mdoc_node_freelist(n
);
668 mdoc_action_post(struct mdoc
*mdoc
)
671 if (MDOC_ACTED
& mdoc
->last
->flags
)
673 mdoc
->last
->flags
|= MDOC_ACTED
;
675 if (MDOC_TEXT
== mdoc
->last
->type
)
677 if (MDOC_ROOT
== mdoc
->last
->type
)
679 if (NULL
== mdoc_actions
[mdoc
->last
->tok
].post
)
681 return((*mdoc_actions
[mdoc
->last
->tok
].post
)(mdoc
));