Return to mdoc_man.c CVS log | Up to [cvsweb.bsd.lv] / mandoc |
version 1.4, 2011/10/06 22:29:12 | version 1.9, 2011/10/24 21:47:59 | ||
---|---|---|---|
|
|
||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | */ | ||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <stdio.h> | #include <stdio.h> | ||
#include <string.h> | #include <string.h> | ||
|
|
||
#include "mdoc.h" | #include "mdoc.h" | ||
#include "main.h" | #include "main.h" | ||
static int need_space = 0; | |||
static int need_nl = 0; | |||
#define DECL_ARGS const struct mdoc_meta *m, \ | #define DECL_ARGS const struct mdoc_meta *m, \ | ||
const struct mdoc_node *n | const struct mdoc_node *n, \ | ||
struct mman *mm | |||
struct mman { | |||
int need_space; /* next word needs prior ws */ | |||
int need_nl; /* next word needs prior nl */ | |||
}; | |||
struct manact { | struct manact { | ||
int (*cond)(DECL_ARGS); | int (*cond)(DECL_ARGS); /* DON'T run actions */ | ||
int (*pre)(DECL_ARGS); | int (*pre)(DECL_ARGS); /* pre-node action */ | ||
void (*post)(DECL_ARGS); | void (*post)(DECL_ARGS); /* post-node action */ | ||
const char *prefix; | const char *prefix; /* pre-node string constant */ | ||
const char *suffix; | const char *suffix; /* post-node string constant */ | ||
}; | }; | ||
static void print_word(const char *); | |||
static void print_node(DECL_ARGS); | |||
static int cond_head(DECL_ARGS); | |||
static int cond_body(DECL_ARGS); | static int cond_body(DECL_ARGS); | ||
static int pre_enc(DECL_ARGS); | static int cond_head(DECL_ARGS); | ||
static void post_bd(DECL_ARGS); | |||
static void post_dl(DECL_ARGS); | |||
static void post_enc(DECL_ARGS); | static void post_enc(DECL_ARGS); | ||
static void post_nm(DECL_ARGS); | |||
static void post_percent(DECL_ARGS); | static void post_percent(DECL_ARGS); | ||
static int pre_sect(DECL_ARGS); | static void post_pf(DECL_ARGS); | ||
static void post_sect(DECL_ARGS); | static void post_sect(DECL_ARGS); | ||
static void post_sp(DECL_ARGS); | |||
static int pre_ap(DECL_ARGS); | static int pre_ap(DECL_ARGS); | ||
static int pre_bd(DECL_ARGS); | static int pre_bd(DECL_ARGS); | ||
static void post_bd(DECL_ARGS); | |||
static int pre_br(DECL_ARGS); | static int pre_br(DECL_ARGS); | ||
static int pre_bx(DECL_ARGS); | |||
static int pre_dl(DECL_ARGS); | static int pre_dl(DECL_ARGS); | ||
static void post_dl(DECL_ARGS); | static int pre_enc(DECL_ARGS); | ||
static int pre_it(DECL_ARGS); | static int pre_it(DECL_ARGS); | ||
static int pre_nm(DECL_ARGS); | static int pre_nm(DECL_ARGS); | ||
static void post_nm(DECL_ARGS); | |||
static int pre_ns(DECL_ARGS); | static int pre_ns(DECL_ARGS); | ||
static void post_pf(DECL_ARGS); | |||
static int pre_pp(DECL_ARGS); | static int pre_pp(DECL_ARGS); | ||
static int pre_sp(DECL_ARGS); | static int pre_sp(DECL_ARGS); | ||
static void post_sp(DECL_ARGS); | static int pre_sect(DECL_ARGS); | ||
static int pre_ux(DECL_ARGS); | |||
static int pre_xr(DECL_ARGS); | static int pre_xr(DECL_ARGS); | ||
static void print_word(struct mman *, const char *); | |||
static void print_node(DECL_ARGS); | |||
static const struct manact manacts[MDOC_MAX + 1] = { | static const struct manact manacts[MDOC_MAX + 1] = { | ||
{ NULL, pre_ap, NULL, NULL, NULL }, /* Ap */ | { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* Dd */ | { NULL, NULL, NULL, NULL, NULL }, /* Dd */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* Dt */ | { NULL, NULL, NULL, NULL, NULL }, /* Dt */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Os */ | { NULL, NULL, NULL, NULL, NULL }, /* Os */ | ||
{ NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */ | { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */ | ||
{ NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */ | { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */ | ||
{ NULL, pre_pp, NULL, NULL, NULL }, /* Pp */ | { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */ | ||
|
|
||
{ NULL, NULL, NULL, NULL, NULL }, /* Bl */ | { NULL, NULL, NULL, NULL, NULL }, /* Bl */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* El */ | { NULL, NULL, NULL, NULL, NULL }, /* El */ | ||
{ NULL, pre_it, NULL, NULL, NULL }, /* _It */ | { NULL, pre_it, NULL, NULL, NULL }, /* _It */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ad */ | { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ad */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _An */ | { NULL, NULL, NULL, NULL, NULL }, /* _An */ | ||
{ NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */ | { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Cd */ | { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cd */ | ||
{ NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */ | { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Dv */ | { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Dv */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Er */ | { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Er */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ev */ | { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Ev */ | ||
{ NULL, pre_enc, post_enc, "The \\fB", | { NULL, pre_enc, post_enc, "The \\fB", | ||
"\\fP\nutility exits 0 on success, and >0 if an error occurs." | "\\fP\nutility exits 0 on success, and >0 if an error occurs." | ||
}, /* Ex */ | }, /* Ex */ | ||
|
|
||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ft */ | { NULL, NULL, NULL, NULL, NULL }, /* _Ft */ | ||
{ NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */ | { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _In */ | { NULL, NULL, NULL, NULL, NULL }, /* _In */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Li */ | { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Li */ | ||
{ cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */ | { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */ | ||
{ NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */ | { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */ | ||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Op */ | { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ot */ | { NULL, NULL, NULL, NULL, NULL }, /* Ot */ | ||
{ NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Pa */ | { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Pa */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Rv */ | { NULL, pre_enc, post_enc, "The \\fB", | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _St */ | "\\fP\nfunction returns the value 0 if successful;\n" | ||
"otherwise the value -1 is returned and the global\n" | |||
"variable \\fIerrno\\fP is set to indicate the error." | |||
}, /* Rv */ | |||
{ NULL, NULL, NULL, NULL, NULL }, /* St */ | |||
{ NULL, NULL, NULL, NULL, NULL }, /* _Va */ | { NULL, NULL, NULL, NULL, NULL }, /* _Va */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Vt */ | { NULL, NULL, NULL, NULL, NULL }, /* _Vt */ | ||
{ NULL, pre_xr, NULL, NULL, NULL }, /* _Xr */ | { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */ | ||
{ NULL, NULL, post_percent, NULL, NULL }, /* _%A */ | { NULL, NULL, post_percent, NULL, NULL }, /* _%A */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _%B */ | { NULL, NULL, NULL, NULL, NULL }, /* _%B */ | ||
{ NULL, NULL, post_percent, NULL, NULL }, /* _%D */ | { NULL, NULL, post_percent, NULL, NULL }, /* _%D */ | ||
|
|
||
{ NULL, NULL, NULL, NULL, NULL }, /* _%R */ | { NULL, NULL, NULL, NULL, NULL }, /* _%R */ | ||
{ NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */ | { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _%V */ | { NULL, NULL, NULL, NULL, NULL }, /* _%V */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ac */ | { NULL, NULL, NULL, NULL, NULL }, /* Ac */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ao */ | { cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */ | ||
{ cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */ | { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _At */ | { NULL, NULL, NULL, NULL, NULL }, /* At */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* Bc */ | { NULL, NULL, NULL, NULL, NULL }, /* Bc */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Bf */ | { NULL, NULL, NULL, NULL, NULL }, /* _Bf */ | ||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */ | { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */ | ||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */ | { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Bsx */ | { NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Bx */ | { NULL, pre_bx, NULL, NULL, NULL }, /* Bx */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Db */ | { NULL, NULL, NULL, NULL, NULL }, /* Db */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Dc */ | { NULL, NULL, NULL, NULL, NULL }, /* Dc */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Do */ | { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */ | ||
{ cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */ | { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ec */ | { NULL, NULL, NULL, NULL, NULL }, /* _Ec */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ef */ | { NULL, NULL, NULL, NULL, NULL }, /* _Ef */ | ||
{ NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */ | { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Eo */ | { NULL, NULL, NULL, NULL, NULL }, /* _Eo */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Fx */ | { NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ms */ | { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ms */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _No */ | { NULL, NULL, NULL, NULL, NULL }, /* No */ | ||
{ NULL, pre_ns, NULL, NULL, NULL }, /* Ns */ | { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Nx */ | { NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ox */ | { NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* Pc */ | { NULL, NULL, NULL, NULL, NULL }, /* Pc */ | ||
{ NULL, NULL, post_pf, NULL, NULL }, /* Pf */ | { NULL, NULL, post_pf, NULL, NULL }, /* Pf */ | ||
{ cond_body, pre_enc, post_enc, "(", ")" }, /* Po */ | { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */ | ||
{ cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */ | { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Qc */ | { NULL, NULL, NULL, NULL, NULL }, /* Qc */ | ||
{ cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */ | { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Qo */ | { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Qq */ | { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Re */ | { NULL, NULL, NULL, NULL, NULL }, /* Re */ | ||
{ cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */ | { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Sc */ | { NULL, NULL, NULL, NULL, NULL }, /* Sc */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _So */ | { cond_body, pre_enc, post_enc, "`", "'" }, /* So */ | ||
{ cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */ | { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Sm */ | { NULL, NULL, NULL, NULL, NULL }, /* _Sm */ | ||
{ NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */ | { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */ | ||
{ NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */ | { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Tn */ | { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Tn */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ux */ | { NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Xc */ | { NULL, NULL, NULL, NULL, NULL }, /* _Xc */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Xo */ | { NULL, NULL, NULL, NULL, NULL }, /* _Xo */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Fo */ | { NULL, NULL, NULL, NULL, NULL }, /* _Fo */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Fc */ | { NULL, NULL, NULL, NULL, NULL }, /* _Fc */ | ||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */ | { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Oc */ | { NULL, NULL, NULL, NULL, NULL }, /* Oc */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Bk */ | { NULL, NULL, NULL, NULL, NULL }, /* _Bk */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ek */ | { NULL, NULL, NULL, NULL, NULL }, /* _Ek */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Bt */ | { NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Hf */ | { NULL, NULL, NULL, NULL, NULL }, /* Hf */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Fr */ | { NULL, NULL, NULL, NULL, NULL }, /* Fr */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Ud */ | { NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Lb */ | { NULL, NULL, NULL, NULL, NULL }, /* _Lb */ | ||
{ NULL, pre_pp, NULL, NULL, NULL }, /* Lp */ | { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Lk */ | { NULL, NULL, NULL, NULL, NULL }, /* _Lk */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Mt */ | { NULL, NULL, NULL, NULL, NULL }, /* _Mt */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Brq */ | { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Bro */ | { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Brc */ | { NULL, NULL, NULL, NULL, NULL }, /* Brc */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _%C */ | { NULL, NULL, NULL, NULL, NULL }, /* _%C */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Es */ | { NULL, NULL, NULL, NULL, NULL }, /* _Es */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _En */ | { NULL, NULL, NULL, NULL, NULL }, /* _En */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _Dx */ | { NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */ | ||
{ NULL, NULL, NULL, NULL, NULL }, /* _%Q */ | { NULL, NULL, NULL, NULL, NULL }, /* _%Q */ | ||
{ NULL, pre_br, NULL, NULL, NULL }, /* br */ | { NULL, pre_br, NULL, NULL, NULL }, /* br */ | ||
{ NULL, pre_sp, post_sp, NULL, NULL }, /* sp */ | { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */ | ||
|
|
||
{ NULL, NULL, NULL, NULL, NULL }, /* ROOT */ | { NULL, NULL, NULL, NULL, NULL }, /* ROOT */ | ||
}; | }; | ||
static void | static void | ||
print_word(const char *s) | print_word(struct mman *mm, const char *s) | ||
{ | { | ||
if (need_nl) { | |||
if (mm->need_nl) { | |||
/* | |||
* If we need a newline, print it now and start afresh. | |||
*/ | |||
putchar('\n'); | putchar('\n'); | ||
need_space = 0; | mm->need_space = 0; | ||
need_nl = 0; | mm->need_nl = 0; | ||
} else if (need_space && | } else if (mm->need_space && '\0' != s[0]) | ||
(NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1])) | /* | ||
putchar(' '); | * If we need a space, only print it before | ||
need_space = ('(' != s[0] && '[' != s[0]) || '\0' != s[1]; | * (1) a nonzero length word; | ||
* (2) a word that is non-punctuation; and | |||
* (3) if punctuation, non-terminating puncutation. | |||
*/ | |||
if (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) | |||
putchar(' '); | |||
/* | |||
* Reassign needing space if we're not following opening | |||
* punctuation. | |||
*/ | |||
mm->need_space = | |||
('(' != s[0] && '[' != s[0]) || '\0' != s[1]; | |||
for ( ; *s; s++) { | for ( ; *s; s++) { | ||
switch (*s) { | switch (*s) { | ||
case (ASCII_NBRSP): | case (ASCII_NBRSP): | ||
|
|
||
putchar('-'); | putchar('-'); | ||
break; | break; | ||
default: | default: | ||
putchar(*s); | putchar((unsigned char)*s); | ||
break; | break; | ||
} | } | ||
} | } | ||
|
|
||
man_man(void *arg, const struct man *man) | man_man(void *arg, const struct man *man) | ||
{ | { | ||
/* | |||
* Dump the keep buffer. | |||
* We're guaranteed by now that this exists (is non-NULL). | |||
* Flush stdout afterward, just in case. | |||
*/ | |||
fputs(mparse_getkeep(man_mparse(man)), stdout); | fputs(mparse_getkeep(man_mparse(man)), stdout); | ||
fflush(stdout); | |||
} | } | ||
void | void | ||
|
|
||
{ | { | ||
const struct mdoc_meta *m; | const struct mdoc_meta *m; | ||
const struct mdoc_node *n; | const struct mdoc_node *n; | ||
struct mman mm; | |||
m = mdoc_meta(mdoc); | m = mdoc_meta(mdoc); | ||
n = mdoc_node(mdoc); | n = mdoc_node(mdoc); | ||
printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", | printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", | ||
m->title, m->msec, m->date, m->os, m->vol); | m->title, m->msec, m->date, m->os, m->vol); | ||
need_nl = 1; | |||
need_space = 0; | |||
print_node(m, n); | memset(&mm, 0, sizeof(struct mman)); | ||
mm.need_nl = 1; | |||
print_node(m, n, &mm); | |||
putchar('\n'); | putchar('\n'); | ||
} | } | ||
|
|
||
print_node(DECL_ARGS) | print_node(DECL_ARGS) | ||
{ | { | ||
const struct mdoc_node *prev, *sub; | const struct mdoc_node *prev, *sub; | ||
const struct manact *act = NULL; | const struct manact *act; | ||
int cond, do_sub; | int cond, do_sub; | ||
/* | |||
* Break the line if we were parsed subsequent the current node. | |||
* This makes the page structure be more consistent. | |||
*/ | |||
prev = n->prev ? n->prev : n->parent; | prev = n->prev ? n->prev : n->parent; | ||
if (prev && prev->line < n->line) | if (prev && prev->line < n->line) | ||
need_nl = 1; | mm->need_nl = 1; | ||
act = NULL; | |||
cond = 0; | cond = 0; | ||
do_sub = 1; | do_sub = 1; | ||
if (MDOC_TEXT == n->type) { | if (MDOC_TEXT == n->type) { | ||
if (need_nl && ('.' == *n->string || '\'' == *n->string)) { | /* | ||
print_word("\\&"); | * Make sure that we don't happen to start with a | ||
need_space = 0; | * control character at the start of a line. | ||
*/ | |||
if (mm->need_nl && ('.' == *n->string || | |||
'\'' == *n->string)) { | |||
print_word(mm, "\\&"); | |||
mm->need_space = 0; | |||
} | } | ||
print_word(n->string); | print_word(mm, n->string); | ||
} else { | } else { | ||
/* | |||
* Conditionally run the pre-node action handler for a | |||
* node. | |||
*/ | |||
act = manacts + n->tok; | act = manacts + n->tok; | ||
cond = NULL == act->cond || (*act->cond)(m, n); | cond = NULL == act->cond || (*act->cond)(m, n, mm); | ||
if (cond && act->pre) | if (cond && act->pre) | ||
do_sub = (*act->pre)(m, n); | do_sub = (*act->pre)(m, n, mm); | ||
} | } | ||
/* | |||
* Conditionally run all child nodes. | |||
* Note that this iterates over children instead of using | |||
* recursion. This prevents unnecessary depth in the stack. | |||
*/ | |||
if (do_sub) | if (do_sub) | ||
for (sub = n->child; sub; sub = sub->next) | for (sub = n->child; sub; sub = sub->next) | ||
print_node(m, sub); | print_node(m, sub, mm); | ||
/* | |||
* Lastly, conditionally run the post-node handler. | |||
*/ | |||
if (cond && act->post) | if (cond && act->post) | ||
(*act->post)(m, n); | (*act->post)(m, n, mm); | ||
} | } | ||
static int | static int | ||
cond_head(DECL_ARGS) | cond_head(DECL_ARGS) | ||
{ | { | ||
return(MDOC_HEAD == n->type); | return(MDOC_HEAD == n->type); | ||
} | } | ||
static int | static int | ||
cond_body(DECL_ARGS) | cond_body(DECL_ARGS) | ||
{ | { | ||
return(MDOC_BODY == n->type); | return(MDOC_BODY == n->type); | ||
} | } | ||
/* | |||
* Output a font encoding before a node, e.g., \fR. | |||
* This obviously has no trailing space. | |||
*/ | |||
static int | static int | ||
pre_enc(DECL_ARGS) | pre_enc(DECL_ARGS) | ||
{ | { | ||
const char *prefix; | const char *prefix; | ||
prefix = manacts[n->tok].prefix; | prefix = manacts[n->tok].prefix; | ||
if (NULL == prefix) | if (NULL == prefix) | ||
return(1); | return(1); | ||
print_word(prefix); | print_word(mm, prefix); | ||
need_space = 0; | mm->need_space = 0; | ||
return(1); | return(1); | ||
} | } | ||
/* | |||
* Output a font encoding subsequent a node, e.g., \fP. | |||
*/ | |||
static void | static void | ||
post_enc(DECL_ARGS) | post_enc(DECL_ARGS) | ||
{ | { | ||
|
|
||
suffix = manacts[n->tok].suffix; | suffix = manacts[n->tok].suffix; | ||
if (NULL == suffix) | if (NULL == suffix) | ||
return; | return; | ||
need_space = 0; | mm->need_space = 0; | ||
print_word(suffix); | print_word(mm, suffix); | ||
} | } | ||
/* | |||
* Used in listings (percent = %A, e.g.). | |||
* FIXME: this is incomplete. | |||
* It doesn't print a nice ", and" for lists. | |||
*/ | |||
static void | static void | ||
post_percent(DECL_ARGS) | post_percent(DECL_ARGS) | ||
{ | { | ||
post_enc(m, n); | post_enc(m, n, mm); | ||
if (n->next) | if (n->next) | ||
print_word(","); | print_word(mm, ","); | ||
else { | else { | ||
print_word("."); | print_word(mm, "."); | ||
need_nl = 1; | mm->need_nl = 1; | ||
} | } | ||
} | } | ||
/* | |||
* Print before a section header. | |||
*/ | |||
static int | static int | ||
pre_sect(DECL_ARGS) | pre_sect(DECL_ARGS) | ||
{ | { | ||
if (MDOC_HEAD != n->type) | if (MDOC_HEAD != n->type) | ||
return(1); | return(1); | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(manacts[n->tok].prefix); | print_word(mm, manacts[n->tok].prefix); | ||
print_word("\""); | print_word(mm, "\""); | ||
need_space = 0; | mm->need_space = 0; | ||
return(1); | return(1); | ||
} | } | ||
/* | |||
* Print subsequent a section header. | |||
*/ | |||
static void | static void | ||
post_sect(DECL_ARGS) | post_sect(DECL_ARGS) | ||
{ | { | ||
if (MDOC_HEAD != n->type) | if (MDOC_HEAD != n->type) | ||
return; | return; | ||
need_space = 0; | mm->need_space = 0; | ||
print_word("\""); | print_word(mm, "\""); | ||
need_nl = 1; | mm->need_nl = 1; | ||
} | } | ||
static int | static int | ||
pre_ap(DECL_ARGS) | pre_ap(DECL_ARGS) | ||
{ | { | ||
need_space = 0; | mm->need_space = 0; | ||
print_word("'"); | print_word(mm, "'"); | ||
need_space = 0; | mm->need_space = 0; | ||
return(0); | return(0); | ||
} | } | ||
|
|
||
if (DISP_unfilled == n->norm->Bd.type || | if (DISP_unfilled == n->norm->Bd.type || | ||
DISP_literal == n->norm->Bd.type) { | DISP_literal == n->norm->Bd.type) { | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(".nf"); | print_word(mm, ".nf"); | ||
} | } | ||
need_nl = 1; | mm->need_nl = 1; | ||
return(1); | return(1); | ||
} | } | ||
|
|
||
if (DISP_unfilled == n->norm->Bd.type || | if (DISP_unfilled == n->norm->Bd.type || | ||
DISP_literal == n->norm->Bd.type) { | DISP_literal == n->norm->Bd.type) { | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(".fi"); | print_word(mm, ".fi"); | ||
} | } | ||
need_nl = 1; | mm->need_nl = 1; | ||
} | } | ||
static int | static int | ||
pre_br(DECL_ARGS) | pre_br(DECL_ARGS) | ||
{ | { | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(".br"); | print_word(mm, ".br"); | ||
need_nl = 1; | mm->need_nl = 1; | ||
return(0); | return(0); | ||
} | } | ||
static int | static int | ||
pre_bx(DECL_ARGS) | |||
{ | |||
n = n->child; | |||
if (n) { | |||
print_word(mm, n->string); | |||
mm->need_space = 0; | |||
n = n->next; | |||
} | |||
print_word(mm, "BSD"); | |||
if (NULL == n) | |||
return(0); | |||
mm->need_space = 0; | |||
print_word(mm, "-"); | |||
mm->need_space = 0; | |||
print_word(mm, n->string); | |||
return(0); | |||
} | |||
static int | |||
pre_dl(DECL_ARGS) | pre_dl(DECL_ARGS) | ||
{ | { | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(".RS 6n"); | print_word(mm, ".RS 6n"); | ||
need_nl = 1; | mm->need_nl = 1; | ||
return(1); | return(1); | ||
} | } | ||
|
|
||
post_dl(DECL_ARGS) | post_dl(DECL_ARGS) | ||
{ | { | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(".RE"); | print_word(mm, ".RE"); | ||
need_nl = 1; | mm->need_nl = 1; | ||
} | } | ||
static int | static int | ||
|
|
||
const struct mdoc_node *bln; | const struct mdoc_node *bln; | ||
if (MDOC_HEAD == n->type) { | if (MDOC_HEAD == n->type) { | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(".TP"); | print_word(mm, ".TP"); | ||
bln = n->parent->parent->prev; | bln = n->parent->parent->prev; | ||
switch (bln->norm->Bl.type) { | switch (bln->norm->Bl.type) { | ||
case (LIST_bullet): | case (LIST_bullet): | ||
print_word("4n"); | print_word(mm, "4n"); | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word("\\fBo\\fP"); | print_word(mm, "\\fBo\\fP"); | ||
break; | break; | ||
default: | default: | ||
if (bln->norm->Bl.width) | if (bln->norm->Bl.width) | ||
print_word(bln->norm->Bl.width); | print_word(mm, bln->norm->Bl.width); | ||
break; | break; | ||
} | } | ||
need_nl = 1; | mm->need_nl = 1; | ||
} | } | ||
return(1); | return(1); | ||
} | } | ||
|
|
||
if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) | if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) | ||
return(1); | return(1); | ||
print_word("\\fB"); | print_word(mm, "\\fB"); | ||
need_space = 0; | mm->need_space = 0; | ||
if (NULL == n->child) | if (NULL == n->child) | ||
print_word(m->name); | print_word(mm, m->name); | ||
return(1); | return(1); | ||
} | } | ||
|
|
||
if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) | if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) | ||
return; | return; | ||
need_space = 0; | mm->need_space = 0; | ||
print_word("\\fP"); | print_word(mm, "\\fP"); | ||
} | } | ||
static int | static int | ||
pre_ns(DECL_ARGS) | pre_ns(DECL_ARGS) | ||
{ | { | ||
need_space = 0; | mm->need_space = 0; | ||
return(0); | return(0); | ||
} | } | ||
|
|
||
post_pf(DECL_ARGS) | post_pf(DECL_ARGS) | ||
{ | { | ||
need_space = 0; | mm->need_space = 0; | ||
} | } | ||
static int | static int | ||
pre_pp(DECL_ARGS) | pre_pp(DECL_ARGS) | ||
{ | { | ||
need_nl = 1; | mm->need_nl = 1; | ||
if (MDOC_It == n->parent->tok) | if (MDOC_It == n->parent->tok) | ||
print_word(".sp"); | print_word(mm, ".sp"); | ||
else | else | ||
print_word(".PP"); | print_word(mm, ".PP"); | ||
need_nl = 1; | mm->need_nl = 1; | ||
return(1); | return(1); | ||
} | } | ||
|
|
||
pre_sp(DECL_ARGS) | pre_sp(DECL_ARGS) | ||
{ | { | ||
need_nl = 1; | mm->need_nl = 1; | ||
print_word(".sp"); | print_word(mm, ".sp"); | ||
return(1); | return(1); | ||
} | } | ||
|
|
||
post_sp(DECL_ARGS) | post_sp(DECL_ARGS) | ||
{ | { | ||
need_nl = 1; | mm->need_nl = 1; | ||
} | } | ||
static int | static int | ||
|
|
||
n = n->child; | n = n->child; | ||
if (NULL == n) | if (NULL == n) | ||
return(0); | return(0); | ||
print_node(m, n); | print_node(m, n, mm); | ||
n = n->next; | n = n->next; | ||
if (NULL == n) | if (NULL == n) | ||
return(0); | return(0); | ||
need_space = 0; | mm->need_space = 0; | ||
print_word("("); | print_word(mm, "("); | ||
print_node(m, n); | print_node(m, n, mm); | ||
print_word(")"); | print_word(mm, ")"); | ||
return(0); | return(0); | ||
} | |||
static int | |||
pre_ux(DECL_ARGS) | |||
{ | |||
print_word(mm, manacts[n->tok].prefix); | |||
if (NULL == n->child) | |||
return(0); | |||
mm->need_space = 0; | |||
print_word(mm, "\\~"); | |||
mm->need_space = 0; | |||
return(1); | |||
} | } |