diff --git a/contrib/mandoc/TODO b/contrib/mandoc/TODO --- a/contrib/mandoc/TODO +++ b/contrib/mandoc/TODO @@ -563,9 +563,7 @@ reported again by Franco Fichtner Fri, 27 Sep 2013 21:02:28 +0200 reported again by Bruce Evans Fri, 17 Feb 2017 21:22:44 +0100 via bapt@ loc *** exist *** algo *** size ** imp *** - An easy partial fix would be to just skip the first word if it starts - with a dot, including any following white space, when measuring. - loc * exist * algo * size * imp *** + An easy partial fix has been implemented as skip_leading_dot_word(). - The \& zero-width character counts as output. That is, when it is alone on a line between two .Pp, diff --git a/contrib/mandoc/mdoc_validate.c b/contrib/mandoc/mdoc_validate.c --- a/contrib/mandoc/mdoc_validate.c +++ b/contrib/mandoc/mdoc_validate.c @@ -1818,6 +1818,45 @@ } } +/* + * If "in" begins with a dot, a word, and whitespace, return a dynamically + * allocated copy of "in" that skips all of those. Otherwise, return NULL. + * + * This is a partial workaround for the TODO list item beginning with: + * - When the -width string contains macros, the macros must be rendered + */ +static char * +skip_leading_dot_word(const char *in) +{ + const char *iter = in; + const char *space; + + if (*iter != '.') + return NULL; + iter++; + + while (*iter != '\0' && !isspace(*iter)) + iter++; + /* + * If the dot was followed by space or NUL, + * do not skip anything. + */ + if (iter == in + 1) + return NULL; + + space = iter; + while (isspace(*iter)) + iter++; + /* + * If the word was not followed by space, + * do not skip anything. + */ + if (iter == space) + return NULL; + + return strdup(iter); +} + /* * If the argument of -offset or -width is a macro, * replace it with the associated default width. @@ -1827,18 +1866,23 @@ { size_t width; enum roff_tok tok; + char *newarg; + newarg = NULL; if (*arg == NULL) return; else if ( ! strcmp(*arg, "Ds")) width = 6; - else if ((tok = roffhash_find(mdoc->mdocmac, *arg, 0)) == TOKEN_NONE) - return; - else + else if ((tok = roffhash_find(mdoc->mdocmac, *arg, 0)) != TOKEN_NONE) width = macro2len(tok); + else if ((newarg = skip_leading_dot_word(*arg)) == NULL) + return; free(*arg); - mandoc_asprintf(arg, "%zun", width); + if (newarg != NULL) + *arg = newarg; + else + mandoc_asprintf(arg, "%zun", width); } static void