From dfe0c6ee455f4a355885a711c81c5ae06ac20160 Mon Sep 17 00:00:00 2001 From: Kristaps Dzonsons Date: Sat, 12 Jun 2010 11:21:44 +0000 Subject: Cache all of `Bd's resolved arguments into mdoc_bd, which is stashed in the "data" union in mdoc_node. Allows me to remove some ugly loops in the front-end and duplicate tests in mdoc_action.c. Add a regression test to make sure we're not doing anything bad (more to come). --- mdoc.h | 8 +++++- mdoc_action.c | 6 ++--- mdoc_html.c | 30 +++++++-------------- mdoc_term.c | 33 +++++++++++------------ mdoc_validate.c | 71 +++++++++++++++++++++++++++++++++++++++++--------- regress/mdoc/Bd/bd0.in | 28 ++++++++++++++++++++ 6 files changed, 120 insertions(+), 56 deletions(-) create mode 100644 regress/mdoc/Bd/bd0.in diff --git a/mdoc.h b/mdoc.h index 07490544..def26d77 100644 --- a/mdoc.h +++ b/mdoc.h @@ -272,6 +272,12 @@ enum mdoc_disp { DISP_literal }; +struct mdoc_bd { + const char *offs; + enum mdoc_disp type; + int comp; +}; + /* Node in AST. */ struct mdoc_node { struct mdoc_node *parent; /* parent AST node */ @@ -300,7 +306,7 @@ struct mdoc_node { union { enum mdoc_list list; /* `Bl' nodes */ - enum mdoc_disp disp; /* `Bd' nodes */ + struct mdoc_bd Bd; } data; }; diff --git a/mdoc_action.c b/mdoc_action.c index 8aa7c92f..21cc2c1d 100644 --- a/mdoc_action.c +++ b/mdoc_action.c @@ -979,14 +979,12 @@ static int pre_bd(PRE_ARGS) { - if (MDOC_BLOCK == n->type) - return(pre_offset(m, n)); if (MDOC_BODY != n->type) return(1); - if (DISP_literal == n->data.disp) + if (DISP_literal == n->data.Bd.type) m->flags |= MDOC_LITERAL; - if (DISP_unfilled == n->data.disp) + if (DISP_unfilled == n->data.Bd.type) m->flags |= MDOC_LITERAL; return(1); diff --git a/mdoc_html.c b/mdoc_html.c index 66f005b1..04a313b1 100644 --- a/mdoc_html.c +++ b/mdoc_html.c @@ -1353,31 +1353,19 @@ static int mdoc_bd_pre(MDOC_ARGS) { struct htmlpair tag[2]; - int comp, i; - const struct mdoc_node *bl, *nn; + int comp; + const struct mdoc_node *nn; struct roffsu su; - if (MDOC_BLOCK == n->type) - bl = n; - else if (MDOC_HEAD == n->type) + if (MDOC_HEAD == n->type) return(0); - else - bl = n->parent; SCALE_VS_INIT(&su, 0); - comp = 0; - for (i = 0; bl->args && i < (int)bl->args->argc; i++) - switch (bl->args->argv[i].arg) { - case (MDOC_Offset): - a2offs(bl->args->argv[i].value[0], &su); - break; - case (MDOC_Compact): - comp = 1; - break; - default: - break; - } + if (n->data.Bd.offs) + a2offs(n->data.Bd.offs, &su); + + comp = n->data.Bd.comp; /* FIXME: -centered, etc. formatting. */ /* FIXME: does not respect -offset ??? */ @@ -1404,8 +1392,8 @@ mdoc_bd_pre(MDOC_ARGS) return(1); } - if (DISP_unfilled != n->data.disp && - DISP_literal != n->data.disp) + if (DISP_unfilled != n->data.Bd.type && + DISP_literal != n->data.Bd.type) return(1); PAIR_CLASS_INIT(&tag[0], "lit"); diff --git a/mdoc_term.c b/mdoc_term.c index 86fdc26f..b7a7f053 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -54,7 +54,7 @@ struct termact { static size_t a2width(const struct mdoc_argv *, int); static size_t a2height(const struct mdoc_node *); -static size_t a2offs(const struct mdoc_argv *); +static size_t a2offs(const char *); static int arg_hasattr(int, const struct mdoc_node *); static int arg_getattrs(const int *, int *, size_t, @@ -489,20 +489,20 @@ a2width(const struct mdoc_argv *arg, int pos) static size_t -a2offs(const struct mdoc_argv *arg) +a2offs(const char *v) { struct roffsu su; - if ('\0' == arg->value[0][0]) + if ('\0' == *v) return(0); - else if (0 == strcmp(arg->value[0], "left")) + else if (0 == strcmp(v, "left")) return(0); - else if (0 == strcmp(arg->value[0], "indent")) + else if (0 == strcmp(v, "indent")) return(INDENT + 1); - else if (0 == strcmp(arg->value[0], "indent-two")) + else if (0 == strcmp(v, "indent-two")) return((INDENT + 1) * 2); - else if ( ! a2roffsu(arg->value[0], &su, SCALE_MAX)) - SCALE_HS_INIT(&su, strlen(arg->value[0])); + else if ( ! a2roffsu(v, &su, SCALE_MAX)) + SCALE_HS_INIT(&su, strlen(v)); return(term_hspan(&su)); } @@ -672,7 +672,7 @@ termp_it_pre(DECL_ARGS) width = offset = 0; if (vals[1] >= 0) - offset = a2offs(&bl->args->argv[vals[1]]); + offset = a2offs(bl->args->argv[vals[1]].value[0]); switch (type) { case (LIST_column): @@ -1602,7 +1602,6 @@ static int termp_bd_pre(DECL_ARGS) { size_t tabwidth; - int i; size_t rm, rmax; const struct mdoc_node *nn; @@ -1612,10 +1611,8 @@ termp_bd_pre(DECL_ARGS) } else if (MDOC_HEAD == n->type) return(0); - nn = n->parent; - - if (-1 != (i = arg_getattr(MDOC_Offset, nn))) - p->offset += a2offs(&nn->args->argv[i]); + if (n->data.Bd.offs) + p->offset += a2offs(n->data.Bd.offs); /* * If -ragged or -filled are specified, the block does nothing @@ -1625,8 +1622,8 @@ termp_bd_pre(DECL_ARGS) * lines are allowed. */ - if (DISP_literal != n->data.disp && - DISP_unfilled != n->data.disp) + if (DISP_literal != n->data.Bd.type && + DISP_unfilled != n->data.Bd.type) return(1); tabwidth = p->tabwidth; @@ -1663,8 +1660,8 @@ termp_bd_post(DECL_ARGS) rm = p->rmargin; rmax = p->maxrmargin; - if (DISP_literal == n->data.disp || - DISP_unfilled == n->data.disp) + if (DISP_literal == n->data.Bd.type || + DISP_unfilled == n->data.Bd.type) p->rmargin = p->maxrmargin = TERM_MAXMARGIN; p->flags |= TERMP_NOSPACE; diff --git a/mdoc_validate.c b/mdoc_validate.c index 3c151fb3..10316fc4 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -683,23 +683,28 @@ pre_bl(PRE_ARGS) static int pre_bd(PRE_ARGS) { - int i; + int i, dup, comp; enum mdoc_disp dt; + const char *offs; if (MDOC_BLOCK != n->type) { assert(n->parent); assert(MDOC_BLOCK == n->parent->type); assert(MDOC_Bd == n->parent->tok); - assert(DISP__NONE != n->parent->data.disp); - n->data.disp = n->parent->data.disp; + assert(DISP__NONE != n->parent->data.Bd.type); + memcpy(&n->data.Bd, &n->parent->data.Bd, + sizeof(struct mdoc_bd)); return(1); } - assert(DISP__NONE == n->data.disp); + assert(DISP__NONE == n->data.Bd.type); /* LINTED */ for (i = 0; n->args && i < (int)n->args->argc; i++) { dt = DISP__NONE; + dup = comp = 0; + offs = NULL; + switch (n->args->argv[i].arg) { case (MDOC_Centred): dt = DISP_centred; @@ -720,25 +725,67 @@ pre_bd(PRE_ARGS) mdoc_nmsg(mdoc, n, MANDOCERR_BADDISP); return(0); case (MDOC_Offset): - /* FALLTHROUGH */ + /* NB: this can be empty! */ + if (n->args->argv[i].sz) { + offs = n->args->argv[i].value[0]; + dup = (NULL != n->data.Bd.offs); + break; + } + /* + * If empty, assign it to a sane default, which + * groff stipulates is about 8n. + */ + /* + * FIXME: remove this. + * + * Where the hell did I get the idea that this + * happens? + */ + assert(1 == n->args->refcnt); + n->args->argv[i].sz++; + n->args->argv[i].value = + mandoc_malloc(sizeof(char *)); + n->args->argv[i].value[0] = + mandoc_strdup("8n"); + offs = n->args->argv[i].value[0]; + break; case (MDOC_Compact): - /* FALLTHROUGH */ - default: + comp = 1; + dup = n->data.Bd.comp; break; + default: + abort(); + /* NOTREACHED */ } - if (DISP__NONE != dt && n->data.disp != DISP__NONE) + /* Check whether we have duplicates. */ + + if (dup && ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP)) + return(0); + + /* Make our auxiliary assignments. */ + + if (offs && ! dup) + n->data.Bd.offs = offs; + if (comp && ! dup) + n->data.Bd.comp = comp; + + /* Check whether a type has already been assigned. */ + + if (DISP__NONE != dt && n->data.Bd.type != DISP__NONE) if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_DISPREP)) return(0); - if (DISP__NONE != dt && n->data.disp == DISP__NONE) - n->data.disp = dt; + /* Make our type assignment. */ + + if (DISP__NONE != dt && n->data.Bd.type == DISP__NONE) + n->data.Bd.type = dt; } - if (DISP__NONE == n->data.disp) { + if (DISP__NONE == n->data.Bd.type) { if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE)) return(0); - n->data.disp = DISP_ragged; + n->data.Bd.type = DISP_ragged; } return(1); diff --git a/regress/mdoc/Bd/bd0.in b/regress/mdoc/Bd/bd0.in new file mode 100644 index 00000000..16921d3c --- /dev/null +++ b/regress/mdoc/Bd/bd0.in @@ -0,0 +1,28 @@ +.Dd $Mdocdate$ +.Dt FOO 1 +.Os +.Sh NAME +.Nm foo +.Nd bar +.Sh DESCRIPTION +1 +.Em who are you? +.Bd -ragged +a b +c d +.Ed +2 +.Bd -unfilled +a b +c d +.Ed +3 +.Bd -filled +a b +c d +.Ed +4 +.Bd -literal +a b +c d +.Ed -- cgit