From 544544185bcee3b5efb8ee4ccd6c444ea8fef690 Mon Sep 17 00:00:00 2001 From: Kristaps Dzonsons Date: Sat, 30 Jan 2010 08:42:20 +0000 Subject: Fix in handling Vt in SYNOPSIS with trailing punctuation. Spotted by Joerg Sonnenberger. --- html.c | 1 - mdoc_html.c | 7 +++++-- mdoc_macro.c | 28 +++++++++++++++++++++++++++- mdoc_term.c | 20 ++++++++++++++++++-- mdoc_validate.c | 30 +++++++++++++++++++++++++++++- 5 files changed, 79 insertions(+), 7 deletions(-) diff --git a/html.c b/html.c index a9190e8f..694b48dd 100644 --- a/html.c +++ b/html.c @@ -312,7 +312,6 @@ print_encode(struct html *h, const char *p, int norecurse) } else if ('>' == *p) { printf(">"); continue; - /* FIXME: already escaped? */ } else if ('&' == *p) { printf("&"); continue; diff --git a/mdoc_html.c b/mdoc_html.c index 86e8b800..9305b508 100644 --- a/mdoc_html.c +++ b/mdoc_html.c @@ -1583,7 +1583,7 @@ mdoc_vt_pre(MDOC_ARGS) struct htmlpair tag; struct roffsu su; - if (SEC_SYNOPSIS == n->sec) { + if (MDOC_BLOCK == n->type) { if (n->prev && MDOC_Vt != n->prev->tok) { SCALE_VS_INIT(&su, 1); bufcat_su(h, "margin-top", &su); @@ -1591,7 +1591,10 @@ mdoc_vt_pre(MDOC_ARGS) print_otag(h, TAG_DIV, 1, &tag); } else print_otag(h, TAG_DIV, 0, NULL); - } + + return(1); + } else if (MDOC_HEAD == n->type) + return(0); PAIR_CLASS_INIT(&tag, "type"); print_otag(h, TAG_SPAN, 1, &tag); diff --git a/mdoc_macro.c b/mdoc_macro.c index 106a05db..65464c7d 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -31,6 +31,7 @@ #define REWIND_NOHALT (1 << 1) #define REWIND_HALT (1 << 2) +static int ctx_synopsis(MACRO_PROT_ARGS); static int obsolete(MACRO_PROT_ARGS); static int blk_part_exp(MACRO_PROT_ARGS); static int in_line_eoln(MACRO_PROT_ARGS); @@ -98,7 +99,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { in_line_eoln, 0 }, /* Rv */ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ - { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ + { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ { in_line_eoln, 0 }, /* %A */ { in_line_eoln, 0 }, /* %B */ @@ -398,6 +399,8 @@ rew_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p) case (MDOC_Qq): /* FALLTHROUGH */ case (MDOC_Sq): + /* FALLTHROUGH */ + case (MDOC_Vt): assert(MDOC_TAIL != type); if (type == p->type && tok == p->tok) return(REWIND_REWIND); @@ -1320,6 +1323,29 @@ in_line_eoln(MACRO_PROT_ARGS) } +/* ARGSUSED */ +static int +ctx_synopsis(MACRO_PROT_ARGS) +{ + + /* If we're not in the SYNOPSIS, go straight to in-line. */ + if (SEC_SYNOPSIS != m->lastsec) + return(in_line(m, tok, line, ppos, pos, buf)); + + /* If we're a nested call, same place. */ + if (ppos > 1) + return(in_line(m, tok, line, ppos, pos, buf)); + + /* + * XXX: this will open a block scope; however, if later we end + * up formatting the block scope, then child nodes will inherit + * the formatting. Be careful. + */ + + return(blk_part_imp(m, tok, line, ppos, pos, buf)); +} + + /* ARGSUSED */ static int obsolete(MACRO_PROT_ARGS) diff --git a/mdoc_term.c b/mdoc_term.c index b850b8e1..ee1967bc 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -132,6 +132,7 @@ static int termp_sq_pre(DECL_ARGS); static int termp_ss_pre(DECL_ARGS); static int termp_under_pre(DECL_ARGS); static int termp_ud_pre(DECL_ARGS); +static int termp_vt_pre(DECL_ARGS); static int termp_xr_pre(DECL_ARGS); static int termp_xx_pre(DECL_ARGS); @@ -175,7 +176,7 @@ static const struct termact termacts[MDOC_MAX] = { { termp_rv_pre, NULL }, /* Rv */ { NULL, NULL }, /* St */ { termp_under_pre, NULL }, /* Va */ - { termp_under_pre, termp_vt_post }, /* Vt */ + { termp_vt_pre, termp_vt_post }, /* Vt */ { termp_xr_pre, NULL }, /* Xr */ { NULL, termp____post }, /* %A */ { termp_under_pre, termp____post }, /* %B */ @@ -1290,12 +1291,27 @@ termp_xr_pre(DECL_ARGS) } +static int +termp_vt_pre(DECL_ARGS) +{ + + if (MDOC_ELEM == n->type) + return(termp_under_pre(p, pair, m, n)); + else if (MDOC_HEAD == n->type) + return(0); + else if (MDOC_BLOCK == n->type) + return(1); + + return(termp_under_pre(p, pair, m, n)); +} + + /* ARGSUSED */ static void termp_vt_post(DECL_ARGS) { - if (n->sec != SEC_SYNOPSIS) + if (MDOC_BLOCK != n->type) return; if (n->next && MDOC_Vt == n->next->tok) term_newln(p); diff --git a/mdoc_validate.c b/mdoc_validate.c index 22376c13..906fe1f5 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -94,6 +94,7 @@ static int post_sh(POST_ARGS); static int post_sh_body(POST_ARGS); static int post_sh_head(POST_ARGS); static int post_st(POST_ARGS); +static int post_vt(POST_ARGS); static int pre_an(PRE_ARGS); static int pre_bd(PRE_ARGS); static int pre_bl(PRE_ARGS); @@ -130,6 +131,7 @@ static v_post posts_ss[] = { herr_ge1, NULL }; static v_post posts_st[] = { eerr_eq1, post_st, NULL }; static v_post posts_text[] = { eerr_ge1, NULL }; static v_post posts_text1[] = { eerr_eq1, NULL }; +static v_post posts_vt[] = { post_vt, NULL }; static v_post posts_wline[] = { bwarn_ge1, herr_eq0, NULL }; static v_post posts_wtext[] = { ewarn_ge1, NULL }; static v_post posts_xr[] = { eerr_ge1, eerr_le2, NULL }; @@ -190,7 +192,7 @@ const struct valids mdoc_valids[MDOC_MAX] = { { pres_rv, NULL }, /* Rv */ { NULL, posts_st }, /* St */ { NULL, NULL }, /* Va */ - { NULL, posts_text }, /* Vt */ + { NULL, posts_vt }, /* Vt */ { NULL, posts_xr }, /* Xr */ { NULL, posts_text }, /* %A */ { NULL, posts_text }, /* %B */ /* FIXME: can be used outside Rs/Re. */ @@ -890,6 +892,32 @@ post_lb(POST_ARGS) } +static int +post_vt(POST_ARGS) +{ + const struct mdoc_node *n; + + /* + * The Vt macro comes in both ELEM and BLOCK form, both of which + * have different syntaxes (yet more context-sensitive + * behaviour). ELEM types must have a child; BLOCK types, + * specifically the BODY, should only have TEXT children. + */ + + if (MDOC_ELEM == mdoc->last->type) + return(eerr_ge1(mdoc)); + if (MDOC_BODY != mdoc->last->type) + return(1); + + for (n = mdoc->last->child; n; n = n->next) + if (MDOC_TEXT != n->type) + if ( ! mdoc_nwarn(mdoc, n, EBADCHILD)) + return(0); + + return(1); +} + + static int post_nm(POST_ARGS) { -- cgit