tech@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: Ingo Schwarze <schwarze@usta.de>
To: "Anthony J. Bentley" <anthony@cathet.us>
Cc: tech@mdocml.bsd.lv
Subject: Re: Description of Bl ... -width
Date: Thu, 30 Oct 2014 21:15:56 +0100	[thread overview]
Message-ID: <20141030201556.GI6607@iris.usta.de> (raw)
In-Reply-To: <13567.1414554036@cathet.us>

Hi Anthony,

Anthony J. Bentley wrote on Tue, Oct 28, 2014 at 09:40:36PM -0600:

> I've spent a long time blindly typing ".Bl -tag -width Ds" without
> understanding what it meant. In the back of my mind I just assumed Ds
> triggered an indent of two characters, never noticing that the indent
> in the result is obviously not two characters.
> 
> This is what mdoc(7) says about the -width argument to Bl:
> 
>      The -width and -offset arguments accept scaling widths as
>      described in roff(7) or use the length of the given string.

You are right, that is incomplete.

> In reality:
> 
>	/*
>	 * Calculate the real width of a list from the -width string,
>	 * which may contain a macro (with a known default width), a
>	 * literal string, or a scaling width.
>	 *
>	 * If the value to -width is a macro, then we re-write it to be
>	 * the macro's width as set in share/tmac/mdoc/doc-common.
>	 */
> 
> The macro part is documented in mdoc(7), but only under Bd's -offset:
> 
>   -offset width  Indent the display by the width, which may
>		   be one of the following:
>		   ...
>		   A macro invocation, which selects a predefined width
>		   associated with that macro.  The most popular is the
>		   imaginary macro Ds, which resolves to 6n.
>		   ...
> 
> It looks like Bl's -offset matches the manual and doesn't support
> determining macro widths.

Which, actually, was a bug.

By the way, there was another bug.  Bl -offset treated "left",
"indent", and "indent-two" specially just like Bd -offset,
which it should not do.

> So that leaves just Bl's -width that is documented wrong.

It's true that Bl -width is documented incompletely,
but so is Bl -offset.

> Here is an attempt to fix it--does this make sense?
> But I'm not sure the paragraph flows very well now.

The fact that both -width and -offset were documented wrongly
allowed an easier fix that i committed together with the
required code changes and regression tests.

Thanks for the report!
  Ingo


Log Message:
-----------
Major bugsquashing with respect to -offset and -width:
1. Support specifying the .Bd and .Bl -offset as a macro default width;
while here, simplify the code handling the same for .Bl -width.
2. Correct handling of .Bl -offset arguments:  unlike .Bd -offset, the
arguments "left", "indent", and "indent-two" have no special meaning.
3. Fix the scaling of string length -offset and -width arguments in -Thtml.
Triggered by an incomplete documentation patch from bentley@.

Modified Files:
--------------
    mdocml:
        mdoc.7
        mdoc_html.c
        mdoc_man.c
        mdoc_term.c
        mdoc_validate.c

Revision Data
-------------
Index: mdoc_man.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_man.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -Lmdoc_man.c -Lmdoc_man.c -u -p -r1.70 -r1.71
--- mdoc_man.c
+++ mdoc_man.c
@@ -112,7 +112,7 @@ static	int	  pre_xr(DECL_ARGS);
 static	void	  print_word(const char *);
 static	void	  print_line(const char *, int);
 static	void	  print_block(const char *, int);
-static	void	  print_offs(const char *);
+static	void	  print_offs(const char *, int);
 static	void	  print_width(const char *,
 				const struct mdoc_node *, size_t);
 static	void	  print_count(int *);
@@ -416,7 +416,7 @@ print_block(const char *s, int newflags)
 }
 
 static void
-print_offs(const char *v)
+print_offs(const char *v, int keywords)
 {
 	char		  buf[24];
 	struct roffsu	  su;
@@ -425,11 +425,11 @@ print_offs(const char *v)
 	print_line(".RS", MMAN_Bk_susp);
 
 	/* Convert v into a number (of characters). */
-	if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
+	if (NULL == v || '\0' == *v || (keywords && !strcmp(v, "left")))
 		sz = 0;
-	else if (0 == strcmp(v, "indent"))
+	else if (keywords && !strcmp(v, "indent"))
 		sz = 6;
-	else if (0 == strcmp(v, "indent-two"))
+	else if (keywords && !strcmp(v, "indent-two"))
 		sz = 12;
 	else if (a2roffsu(v, &su, SCALE_MAX)) {
 		if (SCALE_EN == su.unit)
@@ -876,7 +876,7 @@ pre_bd(DECL_ARGS)
 		print_line(".nf", 0);
 	if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
 		outflags |= MMAN_sp;
-	print_offs(n->norm->Bd.offs);
+	print_offs(n->norm->Bd.offs, 1);
 	return(1);
 }
 
@@ -963,7 +963,7 @@ pre_bl(DECL_ARGS)
 	 * just nest and do not add up their indentation.
 	 */
 	if (n->norm->Bl.offs) {
-		print_offs(n->norm->Bl.offs);
+		print_offs(n->norm->Bl.offs, 0);
 		Bl_stack[Bl_stack_len++] = 0;
 	}
 
@@ -1048,7 +1048,7 @@ static int
 pre_dl(DECL_ARGS)
 {
 
-	print_offs("6n");
+	print_offs("6n", 0);
 	return(1);
 }
 
Index: mdoc_validate.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_validate.c,v
retrieving revision 1.253
retrieving revision 1.254
diff -Lmdoc_validate.c -Lmdoc_validate.c -u -p -r1.253 -r1.254
--- mdoc_validate.c
+++ mdoc_validate.c
@@ -70,6 +70,7 @@ static	void	 check_args(struct mdoc *, s
 static	int	 child_an(const struct mdoc_node *);
 static	enum mdoc_sec	a2sec(const char *);
 static	size_t		macro2len(enum mdoct);
+static	void	 rewrite_macro2len(char **);
 
 static	int	 ebool(POST_ARGS);
 static	int	 berr_ge1(POST_ARGS);
@@ -88,7 +89,6 @@ static	int	 post_bf(POST_ARGS);
 static	int	 post_bk(POST_ARGS);
 static	int	 post_bl(POST_ARGS);
 static	int	 post_bl_block(POST_ARGS);
-static	int	 post_bl_block_width(POST_ARGS);
 static	int	 post_bl_block_tag(POST_ARGS);
 static	int	 post_bl_head(POST_ARGS);
 static	int	 post_bx(POST_ARGS);
@@ -597,6 +597,7 @@ pre_bl(PRE_ARGS)
 				    mdoc->parse, argv->line,
 				    argv->pos, "Bl -width %s",
 				    argv->value[0]);
+			rewrite_macro2len(argv->value);
 			n->norm->Bl.width = argv->value[0];
 			break;
 		case MDOC_Offset:
@@ -611,6 +612,7 @@ pre_bl(PRE_ARGS)
 				    mdoc->parse, argv->line,
 				    argv->pos, "Bl -offset %s",
 				    argv->value[0]);
+			rewrite_macro2len(argv->value);
 			n->norm->Bl.offs = argv->value[0];
 			break;
 		default:
@@ -758,6 +760,7 @@ pre_bd(PRE_ARGS)
 				    mdoc->parse, argv->line,
 				    argv->pos, "Bd -offset %s",
 				    argv->value[0]);
+			rewrite_macro2len(argv->value);
 			n->norm->Bd.offs = argv->value[0];
 			break;
 		case MDOC_Compact:
@@ -1336,10 +1339,6 @@ post_bl_block(POST_ARGS)
 		if ( ! post_bl_block_tag(mdoc))
 			return(0);
 		assert(n->norm->Bl.width);
-	} else if (NULL != n->norm->Bl.width) {
-		if ( ! post_bl_block_width(mdoc))
-			return(0);
-		assert(n->norm->Bl.width);
 	}
 
 	for (ni = n->body->child; ni; ni = ni->next) {
@@ -1379,50 +1378,27 @@ post_bl_block(POST_ARGS)
 	return(1);
 }
 
-static int
-post_bl_block_width(POST_ARGS)
+/*
+ * If the argument of -offset or -width is a macro,
+ * replace it with the associated default width.
+ */
+void
+rewrite_macro2len(char **arg)
 {
 	size_t		  width;
-	int		  i;
 	enum mdoct	  tok;
-	struct mdoc_node *n;
-	char		  buf[24];
-
-	n = mdoc->last;
-
-	/*
-	 * Calculate the real width of a list from the -width string,
-	 * which may contain a macro (with a known default width), a
-	 * literal string, or a scaling width.
-	 *
-	 * If the value to -width is a macro, then we re-write it to be
-	 * the macro's width as set in share/tmac/mdoc/doc-common.
-	 */
 
-	if (0 == strcmp(n->norm->Bl.width, "Ds"))
+	if (*arg == NULL)
+		return;
+	else if ( ! strcmp(*arg, "Ds"))
 		width = 6;
-	else if (MDOC_MAX == (tok = mdoc_hash_find(n->norm->Bl.width)))
-		return(1);
+	else if ((tok = mdoc_hash_find(*arg)) == MDOC_MAX)
+		return;
 	else
 		width = macro2len(tok);
 
-	/* The value already exists: free and reallocate it. */
-
-	assert(n->args);
-
-	for (i = 0; i < (int)n->args->argc; i++)
-		if (MDOC_Width == n->args->argv[i].arg)
-			break;
-
-	assert(i < (int)n->args->argc);
-
-	(void)snprintf(buf, sizeof(buf), "%un", (unsigned int)width);
-	free(n->args->argv[i].value[0]);
-	n->args->argv[i].value[0] = mandoc_strdup(buf);
-
-	/* Set our width! */
-	n->norm->Bl.width = n->args->argv[i].value[0];
-	return(1);
+	free(*arg);
+	mandoc_asprintf(arg, "%zun", width);
 }
 
 static int
@@ -1437,7 +1413,7 @@ post_bl_block_tag(POST_ARGS)
 	 * Calculate the -width for a `Bl -tag' list if it hasn't been
 	 * provided.  Uses the first head macro.  NOTE AGAIN: this is
 	 * ONLY if the -width argument has NOT been provided.  See
-	 * post_bl_block_width() for converting the -width string.
+	 * rewrite_macro2len() for converting the -width string.
 	 */
 
 	sz = 10;
Index: mdoc_html.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_html.c,v
retrieving revision 1.208
retrieving revision 1.209
diff -Lmdoc_html.c -Lmdoc_html.c -u -p -r1.208 -r1.209
--- mdoc_html.c
+++ mdoc_html.c
@@ -56,7 +56,6 @@ static	void		  synopsis_pre(struct html 
 				const struct mdoc_node *);
 
 static	void		  a2width(const char *, struct roffsu *);
-static	void		  a2offs(const char *, struct roffsu *);
 
 static	void		  mdoc_root_post(MDOC_ARGS);
 static	int		  mdoc_root_pre(MDOC_ARGS);
@@ -281,7 +280,7 @@ a2width(const char *p, struct roffsu *su
 {
 
 	if ( ! a2roffsu(p, su, SCALE_MAX)) {
-		su->unit = SCALE_BU;
+		su->unit = SCALE_EN;
 		su->scale = html_strlen(p);
 	}
 }
@@ -328,27 +327,6 @@ synopsis_pre(struct html *h, const struc
 	}
 }
 
-/*
- * Calculate the scaling unit passed in an `-offset' argument.  This
- * uses either a native scaling unit (e.g., 1i, 2m), one of a set of
- * predefined strings (indent, etc.), or the string length of the value.
- */
-static void
-a2offs(const char *p, struct roffsu *su)
-{
-
-	/* FIXME: "right"? */
-
-	if (0 == strcmp(p, "left"))
-		SCALE_HS_INIT(su, 0);
-	else if (0 == strcmp(p, "indent"))
-		SCALE_HS_INIT(su, INDENT);
-	else if (0 == strcmp(p, "indent-two"))
-		SCALE_HS_INIT(su, INDENT * 2);
-	else if ( ! a2roffsu(p, su, SCALE_MAX))
-		SCALE_HS_INIT(su, html_strlen(p));
-}
-
 static void
 print_mdoc(MDOC_ARGS)
 {
@@ -994,7 +972,7 @@ mdoc_bl_pre(MDOC_ARGS)
 	/* Set the block's left-hand margin. */
 
 	if (n->norm->Bl.offs) {
-		a2offs(n->norm->Bl.offs, &su);
+		a2width(n->norm->Bl.offs, &su);
 		bufcat_su(h, "margin-left", &su);
 	}
 
@@ -1160,9 +1138,17 @@ mdoc_bd_pre(MDOC_ARGS)
 		return(1);
 	}
 
-	SCALE_HS_INIT(&su, 0);
-	if (n->norm->Bd.offs)
-		a2offs(n->norm->Bd.offs, &su);
+	/* Handle the -offset argument. */
+
+	if (n->norm->Bd.offs == NULL ||
+	    ! strcmp(n->norm->Bd.offs, "left"))
+		SCALE_HS_INIT(&su, 0);
+	else if ( ! strcmp(n->norm->Bd.offs, "indent"))
+		SCALE_HS_INIT(&su, INDENT);
+	else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
+		SCALE_HS_INIT(&su, INDENT * 2);
+	else
+		a2width(n->norm->Bd.offs, &su);
 
 	bufinit(h);
 	bufcat_su(h, "margin-left", &su);
Index: mdoc_term.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_term.c,v
retrieving revision 1.287
retrieving revision 1.288
diff -Lmdoc_term.c -Lmdoc_term.c -u -p -r1.287 -r1.288
--- mdoc_term.c
+++ mdoc_term.c
@@ -51,7 +51,6 @@ struct	termact {
 
 static	size_t	  a2width(const struct termp *, const char *);
 static	size_t	  a2height(const struct termp *, const char *);
-static	size_t	  a2offs(const struct termp *, const char *);
 
 static	void	  print_bvspace(struct termp *,
 			const struct mdoc_node *,
@@ -550,27 +549,6 @@ a2width(const struct termp *p, const cha
 	return(term_hspan(p, &su));
 }
 
-static size_t
-a2offs(const struct termp *p, const char *v)
-{
-	struct roffsu	 su;
-
-	if ('\0' == *v)
-		return(0);
-	else if (0 == strcmp(v, "left"))
-		return(0);
-	else if (0 == strcmp(v, "indent"))
-		return(term_len(p, p->defindent + 1));
-	else if (0 == strcmp(v, "indent-two"))
-		return(term_len(p, (p->defindent + 1) * 2));
-	else if ( ! a2roffsu(v, &su, SCALE_MAX)) {
-		SCALE_HS_INIT(&su, term_strlen(p, v));
-		su.scale /= term_strlen(p, "0");
-	}
-
-	return(term_hspan(p, &su));
-}
-
 /*
  * Determine how much space to print out before block elements of `It'
  * (and thus `Bl') and `Bd'.  And then go ahead and print that space,
@@ -659,7 +637,7 @@ termp_it_pre(DECL_ARGS)
 	width = offset = 0;
 
 	if (bl->norm->Bl.offs)
-		offset = a2offs(p, bl->norm->Bl.offs);
+		offset = a2width(p, bl->norm->Bl.offs);
 
 	switch (type) {
 	case LIST_column:
@@ -1581,8 +1559,17 @@ termp_bd_pre(DECL_ARGS)
 	} else if (MDOC_HEAD == n->type)
 		return(0);
 
-	if (n->norm->Bd.offs)
-		p->offset += a2offs(p, n->norm->Bd.offs);
+	/* Handle the -offset argument. */
+
+	if (n->norm->Bd.offs == NULL ||
+	    ! strcmp(n->norm->Bd.offs, "left"))
+		/* nothing */;
+	else if ( ! strcmp(n->norm->Bd.offs, "indent"))
+		p->offset += term_len(p, p->defindent + 1);
+	else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
+		p->offset += term_len(p, (p->defindent + 1) * 2);
+	else
+		p->offset += a2width(p, n->norm->Bd.offs);
 
 	/*
 	 * If -ragged or -filled are specified, the block does nothing
Index: mdoc.7
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc.7,v
retrieving revision 1.239
retrieving revision 1.240
diff -Lmdoc.7 -Lmdoc.7 -u -p -r1.239 -r1.240
--- mdoc.7
+++ mdoc.7
@@ -937,8 +937,11 @@ The
 .Fl width
 and
 .Fl offset
-arguments accept scaling widths as described in
-.Xr roff 7
+arguments accept macro names as described for
+.Sx \&Bd
+.Fl offset ,
+scaling widths as described in
+.Xr roff 7 ,
 or use the length of the given string.
 The
 .Fl offset
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

      reply	other threads:[~2014-10-30 20:16 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-29  3:40 Anthony J. Bentley
2014-10-30 20:15 ` Ingo Schwarze [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141030201556.GI6607@iris.usta.de \
    --to=schwarze@usta.de \
    --cc=anthony@cathet.us \
    --cc=tech@mdocml.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).