The branch stable/14 has been updated by ziaee:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=a271d8fd33b5356a06b0d18b16a7a1eb9d5af980

commit a271d8fd33b5356a06b0d18b16a7a1eb9d5af980
Author:     Alexander Ziaee <zi...@freebsd.org>
AuthorDate: 2025-06-12 21:25:42 +0000
Commit:     Alexander Ziaee <zi...@freebsd.org>
CommitDate: 2025-07-14 16:44:45 +0000

    mandoc: Vendor import of upstream at 2025-04-08
    
    Interesting changes:
    + correct legacy mandoc date typo, reported on our very own bugzilla
    + improve libmandoc manual
    + strengthen recommendations to omit macros from title lines in mdoc(7)
    + improve html5 compliance in html output
    + improve RFC linking in markdown output
    + libmandoc and mdoc manuals have been improved
    + support arithmetic operations in tbl(7) column widths for DocBook
    + define the St -isoC-2023 macro for referencing the C23 spec
    
    Approved by:    mhorne (mentor, implicit)
    Reviewed by:    imp
    Discussed with: adrian, bapt, brooks
    Closes:         https://github.com/freebsd/freebsd-src/pull/1689
    
    (cherry picked from commit 80c12959679ab203459dc20eb9ece3a7328b7de5)
---
 contrib/mandoc/TODO            |  11 +++-
 contrib/mandoc/libmandoc.h     |   3 +-
 contrib/mandoc/man.1           |  38 ++++++++++-
 contrib/mandoc/mandoc.1        |  14 ++--
 contrib/mandoc/mandoc.3        |  37 ++++++++++-
 contrib/mandoc/mandoc.css      |   5 +-
 contrib/mandoc/mandoc.h        |   5 +-
 contrib/mandoc/mandoc_msg.c    |   3 +-
 contrib/mandoc/mdoc.7          |  36 +++++-----
 contrib/mandoc/mdoc_html.c     |  61 ++++++++++++-----
 contrib/mandoc/mdoc_man.c      |   7 +-
 contrib/mandoc/mdoc_markdown.c |  35 +++++++++-
 contrib/mandoc/out.c           |  10 +--
 contrib/mandoc/roff.c          | 146 +++++++++++++++++++++--------------------
 contrib/mandoc/st.c            |   2 +-
 contrib/mandoc/tbl.c           |   3 +-
 contrib/mandoc/tbl.h           |   3 +-
 contrib/mandoc/tbl_layout.c    |  36 +++++-----
 18 files changed, 304 insertions(+), 151 deletions(-)

diff --git a/contrib/mandoc/TODO b/contrib/mandoc/TODO
index 58d0d6937746..3f5a449af68f 100644
--- a/contrib/mandoc/TODO
+++ b/contrib/mandoc/TODO
@@ -1,6 +1,6 @@
 ************************************************************************
 * Official mandoc TODO.
-* $Id: TODO,v 1.335 2024/09/21 12:08:54 schwarze Exp $
+* $Id: TODO,v 1.337 2025/04/08 21:53:14 schwarze Exp $
 ************************************************************************
 
 Many issues are annotated for difficulty as follows:
@@ -234,6 +234,11 @@ are mere guesses, and some may be wrong.
 
 --- missing man features -----------------------------------------------
 
+- When calling less(1), specify -P to print "name(sec) lines ..."
+  in the bottom line instead of "/tmp/man..."
+  Jan Engelhardt (SuSE) via Matej Cepl 06 Apr 2025 14:42:52 +0200
+  loc *  exist *  algo *  size *  imp **
+
 - MANWIDTH
   Markus Waldeck <waldeck at gmx dot de> 9 Jun 2015 05:49:56 +0200
   Laura Morales <lauretas at mail dot com> 26 Apr 2018 08:15:55 +0200
@@ -483,6 +488,10 @@ are mere guesses, and some may be wrong.
   reveals lots of bugs both in groff and mandoc...
   reported by bentley@  Wed, 22 May 2013 23:49:30 -0600
 
+- Make an underlined blank an underscore rather than a blank in both
+  groff and mandoc terminal output (likely tricky, needs investigation)
+  job@  21 Jan 2025 18:03:52 +0000
+
 --- PostScript and PDF issues ------------------------------------------
 
 - PDF output doesn't use a monospaced font for .Bd -literal
diff --git a/contrib/mandoc/libmandoc.h b/contrib/mandoc/libmandoc.h
index ab7c29be510f..76183423603d 100644
--- a/contrib/mandoc/libmandoc.h
+++ b/contrib/mandoc/libmandoc.h
@@ -1,4 +1,4 @@
-/* $Id: libmandoc.h,v 1.80 2021/06/27 17:57:54 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.81 2025/01/05 16:58:22 schwarze Exp $ */
 /*
  * Copyright (c) 2013-2015,2017,2018,2020 Ingo Schwarze <schwa...@openbsd.org>
  * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <krist...@bsd.lv>
@@ -78,6 +78,7 @@ void           roff_userret(struct roff *);
 void            roff_endparse(struct roff *);
 void            roff_setreg(struct roff *, const char *, int, char);
 int             roff_getreg(struct roff *, const char *);
+int             roff_evalnum(int, const char *, int *, int *, char, int);
 char           *roff_strdup(const struct roff *, const char *);
 char           *roff_getarg(struct roff *, char **, int, int *);
 int             roff_getcontrol(const struct roff *,
diff --git a/contrib/mandoc/man.1 b/contrib/mandoc/man.1
index 888cabb4502b..b37d410e9130 100644
--- a/contrib/mandoc/man.1
+++ b/contrib/mandoc/man.1
@@ -1,4 +1,4 @@
-.\"    $Id: man.1,v 1.41 2022/08/04 11:32:23 schwarze Exp $
+.\" $Id: man.1,v 1.42 2025/01/26 14:43:25 schwarze Exp $
 .\"
 .\" Copyright (c) 1989, 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -31,7 +31,7 @@
 .\"
 .\"     @(#)man.1      8.2 (Berkeley) 1/2/94
 .\"
-.Dd $Mdocdate: August 4 2022 $
+.Dd $Mdocdate: January 26 2025 $
 .Dt MAN 1
 .Os
 .Sh NAME
@@ -58,7 +58,19 @@ a specific category
 .Pq Ar section
 or
 machine architecture
-.Pq Ar subsection .
+.Pq Ar subsection ,
+or searched for with
+.Fl k
+using
+.Xr apropos 1
+search expressions.
+The default pager,
+.Xr less 1 ,
+supports the command
+.Ic :t
+to jump to definitions of specific terms (see
+.Dv MANPAGER ,
+below).
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
@@ -345,6 +357,26 @@ See
 .Xr mandoc 1
 for details.
 .Sh EXAMPLES
+Show all manual pages that mention the
+.Ev PWD
+environment variable:
+.Pp
+.Dl $ man -ak Ev=PWD
+.Pp
+Show the
+.Xr ksh 1
+manual and jump to the place where the
+.Ic pwd
+builtin command is described:
+.Pp
+.Dl $ man -O tag=pwd ksh
+.Pp
+Equivalently, use the command
+.Ql man ksh ,
+then type
+.Ql :tpwd
+and press the return key.
+.Pp
 Format a page for pasting extracts into an email message \(em
 avoid printing any UTF-8 characters, reduce the width to ease
 quoting in replies, and remove markup:
diff --git a/contrib/mandoc/mandoc.1 b/contrib/mandoc/mandoc.1
index b1e0cf118336..32a3e2811513 100644
--- a/contrib/mandoc/mandoc.1
+++ b/contrib/mandoc/mandoc.1
@@ -1,6 +1,6 @@
-.\" $Id: mandoc.1,v 1.267 2023/11/13 19:13:01 schwarze Exp $
+.\" $Id: mandoc.1,v 1.270 2025/03/03 14:07:51 schwarze Exp $
 .\"
-.\" Copyright (c) 2012, 2014-2023 Ingo Schwarze <schwa...@openbsd.org>
+.\" Copyright (c) 2012, 2014-2023, 2025 Ingo Schwarze <schwa...@openbsd.org>
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <krist...@bsd.lv>
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: November 13 2023 $
+.Dd $Mdocdate: March 3 2025 $
 .Dt MANDOC 1
 .Os
 .Sh NAME
@@ -954,7 +954,7 @@ The
 macro uses the legacy
 .Xr man 7
 date format
-.Dq yyyy-dd-mm .
+.Dq yyyy-mm-dd .
 Consider using the conventional
 .Xr mdoc 7
 date format
@@ -1896,6 +1896,12 @@ The invalid character is discarded.
 A table layout specification contains an opening parenthesis,
 but no matching closing parenthesis.
 The rest of the input line, starting from the parenthesis, has no effect.
+.It Sy "ignoring invalid column width in tbl layout"
+.Pq tbl
+A column width specifier in a table layout is empty, zero, or not a valid
+numerical expression.
+The width specifier is ignored and the column is made wide enough
+to accommodate all its data cells.
 .It Sy "ignoring excessive spacing in tbl layout"
 .Pq tbl
 A spacing modifier in a table layout is unreasonably large.
diff --git a/contrib/mandoc/mandoc.3 b/contrib/mandoc/mandoc.3
index 4ecfbdebd8c2..6b759558e488 100644
--- a/contrib/mandoc/mandoc.3
+++ b/contrib/mandoc/mandoc.3
@@ -1,4 +1,4 @@
-.\"    $Id: mandoc.3,v 1.44 2018/12/30 00:49:55 schwarze Exp $
+.\" $Id: mandoc.3,v 1.46 2025/02/25 17:03:54 schwarze Exp $
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <krist...@bsd.lv>
 .\" Copyright (c) 2010-2017 Ingo Schwarze <schwa...@openbsd.org>
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: December 30 2018 $
+.Dd $Mdocdate: February 25 2025 $
 .Dt MANDOC 3
 .Os
 .Sh NAME
@@ -33,6 +33,8 @@
 .In sys/types.h
 .In stdio.h
 .In mandoc.h
+.In roff.h
+.In mandoc_parse.h
 .Pp
 .Fd "#define ASCII_NBRSP"
 .Fd "#define ASCII_HYPH"
@@ -141,6 +143,37 @@ or invoke
 .Fn mparse_reset
 and go back to step 2 to parse new files.
 .El
+.Pp
+The design goals of the
+.Nm mandoc
+library are limited to providing the functionality required by the
+.Xr mandoc 1
+program.
+Consequently, the functions documented in the present manual page
+do not aim for API stability.
+Any third-party program using them typically requires adjustments after every
+.Nm mandoc
+release.
+Linking such a program requires
+.Fl lz
+because
+.Fn mparse_readfd
+calls
+.Xr gzdopen 3 ,
+.Xr gzread 3 ,
+.Xr gzerror 3 ,
+and
+.Xr gzclose 3 .
+For
+.Xr mandoc 1
+itself, the
+.Pa ./configure
+script automatically adds
+.Fl lz
+to the
+.Ev LDADD
+.Xr make 1
+variable.
 .Sh REFERENCE
 This section documents the functions, types, and variables available
 via
diff --git a/contrib/mandoc/mandoc.css b/contrib/mandoc/mandoc.css
index 1dae127059d6..88432b9322b7 100644
--- a/contrib/mandoc/mandoc.css
+++ b/contrib/mandoc/mandoc.css
@@ -1,4 +1,4 @@
-/* $Id: mandoc.css,v 1.52 2022/07/06 14:34:59 schwarze Exp $ */
+/* $Id: mandoc.css,v 1.54 2025/01/25 03:18:55 schwarze Exp $ */
 /*
  * Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
  *
@@ -179,7 +179,8 @@ h3.Ss {             margin-top: 1.2em;
 .RsP { }
 .RsQ { }
 .RsR { }
-.RsT {         text-decoration: underline; }
+.RsT {         font-style: normal;
+               font-weight: normal; }
 .RsU { }
 .RsV { }
 
diff --git a/contrib/mandoc/mandoc.h b/contrib/mandoc/mandoc.h
index 9ab68327ecb4..ccbf90392f4c 100644
--- a/contrib/mandoc/mandoc.h
+++ b/contrib/mandoc/mandoc.h
@@ -1,6 +1,6 @@
-/* $Id: mandoc.h,v 1.282 2023/10/21 17:10:17 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.283 2025/01/05 18:14:39 schwarze Exp $ */
 /*
- * Copyright (c) 2012-2022 Ingo Schwarze <schwa...@openbsd.org>
+ * Copyright (c) 2012-2022, 2025 Ingo Schwarze <schwa...@openbsd.org>
  * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <krist...@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -193,6 +193,7 @@ enum        mandocerr {
        MANDOCERR_TBLLAYOUT_NONE, /* empty tbl layout */
        MANDOCERR_TBLLAYOUT_CHAR, /* invalid character in tbl layout: char */
        MANDOCERR_TBLLAYOUT_PAR, /* unmatched parenthesis in tbl layout */
+       MANDOCERR_TBLLAYOUT_WIDTH, /* invalid column width in tbl layout */
        MANDOCERR_TBLLAYOUT_SPC, /* ignoring excessive spacing in tbl layout */
        MANDOCERR_TBLDATA_NONE, /* tbl without any data cells */
        MANDOCERR_TBLDATA_SPAN, /* ignoring data in spanned tbl cell: data */
diff --git a/contrib/mandoc/mandoc_msg.c b/contrib/mandoc/mandoc_msg.c
index baa709c70c83..b4ba9cec9683 100644
--- a/contrib/mandoc/mandoc_msg.c
+++ b/contrib/mandoc/mandoc_msg.c
@@ -1,6 +1,6 @@
 /* $OpenBSD: mandoc_msg.c,v 1.8 2020/01/19 17:59:01 schwarze Exp $ */
 /*
- * Copyright (c) 2014-2022 Ingo Schwarze <schwa...@openbsd.org>
+ * Copyright (c) 2014-2022, 2025 Ingo Schwarze <schwa...@openbsd.org>
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <krist...@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -192,6 +192,7 @@ static      const char *const type_message[MANDOCERR_MAX] = 
{
        "empty tbl layout",
        "invalid character in tbl layout",
        "unmatched parenthesis in tbl layout",
+       "ignoring invalid column width in tbl layout",
        "ignoring excessive spacing in tbl layout",
        "tbl without any data cells",
        "ignoring data in spanned tbl cell",
diff --git a/contrib/mandoc/mdoc.7 b/contrib/mandoc/mdoc.7
index 9dbce2127361..edd74eafa328 100644
--- a/contrib/mandoc/mdoc.7
+++ b/contrib/mandoc/mdoc.7
@@ -1,4 +1,4 @@
-.\" $Id: mdoc.7,v 1.294 2024/09/22 10:34:58 schwarze Exp $
+.\" $Id: mdoc.7,v 1.296 2025/01/27 03:17:33 schwarze Exp $
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <krist...@bsd.lv>
 .\" Copyright (c) 2010, 2011, 2013-2020 Ingo Schwarze <schwa...@openbsd.org>
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: September 22 2024 $
+.Dd $Mdocdate: January 27 2025 $
 .Dt MDOC 7
 .Os
 .Sh NAME
@@ -2304,13 +2304,14 @@ Close single-quoted context opened by
 Begin a new section.
 For a list of conventional manual sections, see
 .Sx MANUAL STRUCTURE .
-These sections should be used unless it's absolutely necessary that
-custom sections be used.
-.Pp
-Section names should be unique so that they may be keyed by
-.Ic \&Sx .
-Although this macro is parsed, it should not consist of child node or it
-may not be linked with
+Use the conventional sections where applicable.
+For unusually long and complicated manual pages,
+adding custom sections is occasionally useful.
+.Pp
+Avoid using macros inside the
+.Ar TITLE LINE
+and keep that line unique within the manual page,
+such that it can be pointed to with
 .Ic \&Sx .
 .Pp
 See also
@@ -2360,10 +2361,10 @@ the conventional sections described in
 .Sx MANUAL STRUCTURE
 rarely have subsections.
 .Pp
-Sub-section names should be unique so that they may be keyed by
-.Ic \&Sx .
-Although this macro is parsed, it should not consist of child node or it
-may not be linked with
+Avoid using macros inside the
+.Ar Title line
+and keep that line unique within the manual page,
+such that it can be pointed to with
 .Ic \&Sx .
 .Pp
 See also
@@ -2405,12 +2406,17 @@ The original C standard.
 .It \-isoC-99
 .St -isoC-99
 .br
-The second major version of the C language standard.
+Edition 2 of the C language standard.
 .Pp
 .It \-isoC-2011
 .St -isoC-2011
 .br
-The third major version of the C language standard.
+Edition 3 of the C language standard.
+.Pp
+.It \-isoC-2023
+.St -isoC-2023
+.br
+Edition 5 of the C language standard.
 .El
 .It POSIX.1 before XPG4.2
 .Pp
diff --git a/contrib/mandoc/mdoc_html.c b/contrib/mandoc/mdoc_html.c
index 74d753a76bfb..b67eac4be233 100644
--- a/contrib/mandoc/mdoc_html.c
+++ b/contrib/mandoc/mdoc_html.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_html.c,v 1.350 2022/07/06 16:05:40 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.353 2025/01/25 00:22:28 schwarze Exp $ */
 /*
- * Copyright (c) 2014-2022 Ingo Schwarze <schwa...@openbsd.org>
+ * Copyright (c) 2014-2022, 2025 Ingo Schwarze <schwa...@openbsd.org>
  * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <krist...@bsd.lv>
  * Copyright (c) 2022 Anna Vyalkova <cy...@sysrq.in>
  *
@@ -1456,7 +1456,7 @@ mdoc_rs_pre(MDOC_ARGS)
        case ROFFT_BODY:
                if (n->sec == SEC_SEE_ALSO)
                        print_otag(h, TAG_P, "c", "Pp");
-               print_otag(h, TAG_CITE, "c", "Rs");
+               print_otag(h, TAG_SPAN, "c", "Rs");
                break;
        default:
                abort();
@@ -1494,10 +1494,13 @@ static int
 mdoc__x_pre(MDOC_ARGS)
 {
        struct roff_node        *nn;
-       const char              *cattr;
+       const unsigned char     *cp;
+       const char              *cattr, *arg;
+       char                    *url;
        enum htmltag             t;
 
        t = TAG_SPAN;
+       arg = n->child->string;
 
        switch (n->tok) {
        case MDOC__A:
@@ -1507,7 +1510,7 @@ mdoc__x_pre(MDOC_ARGS)
                        print_text(h, "and");
                break;
        case MDOC__B:
-               t = TAG_I;
+               t = TAG_CITE;
                cattr = "RsB";
                break;
        case MDOC__C:
@@ -1537,13 +1540,32 @@ mdoc__x_pre(MDOC_ARGS)
                cattr = "RsQ";
                break;
        case MDOC__R:
+               if (strncmp(arg, "RFC ", 4) == 0) {
+                       cp = arg += 4;
+                       while (isdigit(*cp))
+                               cp++;
+                       if (*cp == '\0') {
+                               mandoc_asprintf(&url, "https://www.rfc-";
+                                   "editor.org/rfc/rfc%s.html", arg);
+                               print_otag(h, TAG_A, "ch", "RsR", url);
+                               free(url);
+                               return 1;
+                       }
+               }
                cattr = "RsR";
                break;
        case MDOC__T:
-               cattr = "RsT";
+               t = TAG_CITE;
+               if (n->parent != NULL && n->parent->tok == MDOC_Rs &&
+                   n->parent->norm->Rs.quote_T) {
+                       print_text(h, "\\(lq");
+                       h->flags |= HTML_NOSPACE;
+                       cattr = "RsT";
+               } else
+                       cattr = "RsB";
                break;
        case MDOC__U:
-               print_otag(h, TAG_A, "ch", "RsU", n->child->string);
+               print_otag(h, TAG_A, "ch", "RsU", arg);
                return 1;
        case MDOC__V:
                cattr = "RsV";
@@ -1561,14 +1583,23 @@ mdoc__x_post(MDOC_ARGS)
 {
        struct roff_node *nn;
 
-       if (n->tok == MDOC__A &&
-           (nn = roff_node_next(n)) != NULL && nn->tok == MDOC__A &&
-           ((nn = roff_node_next(nn)) == NULL || nn->tok != MDOC__A) &&
-           ((nn = roff_node_prev(n)) == NULL || nn->tok != MDOC__A))
-               return;
-
-       /* TODO: %U */
-
+       switch (n->tok) {
+       case MDOC__A:
+               if ((nn = roff_node_next(n)) != NULL && nn->tok == MDOC__A &&
+                   ((nn = roff_node_next(nn)) == NULL || nn->tok != MDOC__A) &&
+                   ((nn = roff_node_prev(n)) == NULL || nn->tok != MDOC__A))
+                       return;
+               break;
+       case MDOC__T:
+               if (n->parent != NULL && n->parent->tok == MDOC_Rs &&
+                   n->parent->norm->Rs.quote_T) {
+                       h->flags |= HTML_NOSPACE;
+                       print_text(h, "\\(rq");
+               }
+               break;
+       default:
+               break;
+       }
        if (n->parent == NULL || n->parent->tok != MDOC_Rs)
                return;
 
diff --git a/contrib/mandoc/mdoc_man.c b/contrib/mandoc/mdoc_man.c
index d4fd88304fb0..5438b2ba5941 100644
--- a/contrib/mandoc/mdoc_man.c
+++ b/contrib/mandoc/mdoc_man.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_man.c,v 1.138 2023/04/28 19:11:04 schwarze Exp $ */
+/* $Id: mdoc_man.c,v 1.139 2025/01/24 22:37:24 schwarze Exp $ */
 /*
- * Copyright (c) 2011-2021 Ingo Schwarze <schwa...@openbsd.org>
+ * Copyright (c) 2011-2021, 2025 Ingo Schwarze <schwa...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -796,6 +796,9 @@ post_percent(DECL_ARGS)
        if (mdoc_man_act(n->tok)->pre == pre_em)
                font_pop();
 
+       if (n->parent == NULL || n->parent->tok != MDOC_Rs)
+               return;
+
        if ((nn = roff_node_next(n)) != NULL) {
                np = roff_node_prev(n);
                nnn = nn == NULL ? NULL : roff_node_next(nn);
diff --git a/contrib/mandoc/mdoc_markdown.c b/contrib/mandoc/mdoc_markdown.c
index ecad77e308e6..06ca839a58b8 100644
--- a/contrib/mandoc/mdoc_markdown.c
+++ b/contrib/mandoc/mdoc_markdown.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_markdown.c,v 1.38 2024/08/13 12:44:00 schwarze Exp $ */
+/* $Id: mdoc_markdown.c,v 1.39 2025/01/20 07:01:17 schwarze Exp $ */
 /*
- * Copyright (c) 2017, 2018, 2020 Ingo Schwarze <schwa...@openbsd.org>
+ * Copyright (c) 2017, 2018, 2020, 2025 Ingo Schwarze <schwa...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -85,6 +85,7 @@ static        int      md_pre_Sh(struct roff_node *);
 static int      md_pre_Sm(struct roff_node *);
 static int      md_pre_Vt(struct roff_node *);
 static int      md_pre_Xr(struct roff_node *);
+static int      md_pre__R(struct roff_node *);
 static int      md_pre__T(struct roff_node *);
 static int      md_pre_br(struct roff_node *);
 
@@ -159,7 +160,7 @@ static      const struct md_act md_acts[MDOC_MAX - MDOC_Dd] 
= {
        { NULL, NULL, md_post_pc, NULL, NULL }, /* %N */
        { NULL, NULL, md_post_pc, NULL, NULL }, /* %O */
        { NULL, NULL, md_post_pc, NULL, NULL }, /* %P */
-       { NULL, NULL, md_post_pc, NULL, NULL }, /* %R */
+       { NULL, md_pre__R, md_post_pc, NULL, NULL }, /* %R */
        { NULL, md_pre__T, md_post__T, NULL, NULL }, /* %T */
        { NULL, NULL, md_post_pc, NULL, NULL }, /* %V */
        { NULL, NULL, NULL, NULL, NULL }, /* Ac */
@@ -1580,6 +1581,34 @@ md_pre_Xr(struct roff_node *n)
        return 0;
 }
 
+static int
+md_pre__R(struct roff_node *n)
+{
+       const unsigned char     *cp;
+       const char              *arg;
+
+       arg = n->child->string;
+
+       if (strncmp(arg, "RFC ", 4) != 0)
+               return 1;
+       cp = arg += 4;
+       while (isdigit(*cp))
+               cp++;
+       if (*cp != '\0')
+               return 1;
+
+       md_rawword("[RFC ");
+       outflags &= ~MD_spc;
+       md_rawword(arg);
+       outflags &= ~MD_spc;
+       md_rawword("](http://www.rfc-editor.org/rfc/rfc";);
+       outflags &= ~MD_spc;
+       md_rawword(arg);
+       outflags &= ~MD_spc;
+       md_rawword(".html)");
+       return 0;
+}
+
 static int
 md_pre__T(struct roff_node *n)
 {
diff --git a/contrib/mandoc/out.c b/contrib/mandoc/out.c
index bb29f78c9701..f6f5859a1629 100644
--- a/contrib/mandoc/out.c
+++ b/contrib/mandoc/out.c
@@ -1,4 +1,4 @@
-/*     $Id: out.c,v 1.85 2021/10/17 21:05:54 schwarze Exp $ */
+/*     $Id: out.c,v 1.86 2025/01/05 18:14:39 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <krist...@bsd.lv>
  * Copyright (c) 2011, 2014, 2015, 2017, 2018, 2019, 2021
@@ -117,7 +117,6 @@ void
 tblcalc(struct rofftbl *tbl, const struct tbl_span *sp_first,
     size_t offset, size_t rmargin)
 {
-       struct roffsu            su;
        const struct tbl_opts   *opts;
        const struct tbl_span   *sp;
        const struct tbl_dat    *dp;
@@ -159,13 +158,6 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span 
*sp_first,
                                continue;
 
                        /* Handle explicit width specifications. */
-
-                       if (dp->layout->wstr != NULL &&
-                           dp->layout->width == 0 &&
-                           a2roffsu(dp->layout->wstr, &su, SCALE_EN)
-                           != NULL)
-                               dp->layout->width =
-                                   (*tbl->sulen)(&su, tbl->arg);
                        if (col->width < dp->layout->width)
                                col->width = dp->layout->width;
                        if (dp->layout->spacing != SIZE_MAX &&
diff --git a/contrib/mandoc/roff.c b/contrib/mandoc/roff.c
index bdb02101c053..7425b56873a0 100644
--- a/contrib/mandoc/roff.c
+++ b/contrib/mandoc/roff.c
@@ -1,6 +1,6 @@
-/* $Id: roff.c,v 1.400 2023/10/24 20:53:12 schwarze Exp $ */
+/* $Id: roff.c,v 1.405 2025/04/08 14:05:09 schwarze Exp $ */
 /*
- * Copyright (c) 2010-2015, 2017-2023 Ingo Schwarze <schwa...@openbsd.org>
+ * Copyright (c) 2010-2015, 2017-2025 Ingo Schwarze <schwa...@openbsd.org>
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <krist...@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -192,10 +192,8 @@ static     int              roff_ec(ROFF_ARGS);
 static int              roff_eo(ROFF_ARGS);
 static int              roff_eqndelim(struct roff *, struct buf *, int);
 static int              roff_evalcond(struct roff *, int, char *, int *);
-static int              roff_evalnum(struct roff *, int,
-                               const char *, int *, int *, int);
-static int              roff_evalpar(struct roff *, int,
-                               const char *, int *, int *, int);
+static int              roff_evalpar(int, const char *, int *, int *,
+                               char, int);
 static int              roff_evalstrcond(const char *, int *);
 static int              roff_expand(struct roff *, struct buf *,
                                int, int, char);
@@ -204,8 +202,8 @@ static      void             roff_expand_patch(struct buf 
*, int,
 static void             roff_free1(struct roff *);
 static void             roff_freereg(struct roffreg *);
 static void             roff_freestr(struct roffkv *);
-static size_t           roff_getname(struct roff *, char **, int, int);
-static int              roff_getnum(const char *, int *, int *, int);
+static size_t           roff_getname(char **, int, int);
+static int              roff_getnum(const char *, int *, int *, char, int);
 static int              roff_getop(const char *, int *, char *);
 static int              roff_getregn(struct roff *,
                                const char *, size_t, char);
@@ -258,9 +256,6 @@ static      int              roff_userdef(ROFF_ARGS);
 
 /* --- constant data ------------------------------------------------------ */
 
-#define        ROFFNUM_SCALE   (1 << 0)  /* Honour scaling in roff_getnum(). */
-#define        ROFFNUM_WHITE   (1 << 1)  /* Skip whitespace in roff_evalnum(). 
*/
-
 const char *__roff_name[MAN_MAX + 1] = {
        "br",           "ce",           "fi",           "ft",
        "ll",           "mc",           "nf",
@@ -1529,8 +1524,8 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int 
pos, char ec)
                case 'B':
                        npos = 0;
                        ubuf[0] = iendarg > iarg && iend > iendarg &&
-                           roff_evalnum(r, ln, buf->buf + iarg, &npos,
-                                        NULL, ROFFNUM_SCALE) &&
+                           roff_evalnum(ln, buf->buf + iarg, &npos,
+                                        NULL, 'u', 0) &&
                            npos == iendarg - iarg ? '1' : '0';
                        ubuf[1] = '\0';
                        res = ubuf;
@@ -2002,7 +1997,7 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, 
int ppos)
                return TOKEN_NONE;
 
        mac = cp;
-       maclen = roff_getname(r, &cp, ln, ppos);
+       maclen = roff_getname(&cp, ln, ppos);
 
        deftype = ROFFDEF_USER | ROFFDEF_REN;
        r->current_string = roff_getstrn(r, mac, maclen, &deftype);
@@ -2155,7 +2150,7 @@ roff_block(ROFF_ARGS)
                namesz = 0;
        } else {
                iname = cp;
-               namesz = roff_getname(r, &cp, ln, ppos);
+               namesz = roff_getname(&cp, ln, ppos);
                iname[namesz] = '\0';
        }
 
@@ -2226,7 +2221,7 @@ roff_block(ROFF_ARGS)
        /* Get the custom end marker. */
 
        iname = cp;
-       namesz = roff_getname(r, &cp, ln, ppos);
+       namesz = roff_getname(&cp, ln, ppos);
 
        /* Resolve the end marker if it is indirect. */
 
@@ -2427,74 +2422,81 @@ roff_cond_text(ROFF_ARGS)
 /* --- handling of numeric and conditional expressions -------------------- */
 
 /*
- * Parse a single signed integer number.  Stop at the first non-digit.
+ * Parse a single signed decimal number.  Stop at the first non-digit.
  * If there is at least one digit, return success and advance the
  * parse point, else return failure and let the parse point unchanged.
  * Ignore overflows, treat them just like the C language.
  */
 static int
-roff_getnum(const char *v, int *pos, int *res, int flags)
+roff_getnum(const char *v, int *pos, int *res, char unit, int skipspace)
 {
-       int      myres, scaled, n, p;
-
-       if (NULL == res)
-               res = &myres;
+       double   frac, myres;
+       int      n, p;
 
        p = *pos;
        n = v[p] == '-';
        if (n || v[p] == '+')
                p++;
 
-       if (flags & ROFFNUM_WHITE)
+       if (skipspace)
                while (isspace((unsigned char)v[p]))
                        p++;
 
-       for (*res = 0; isdigit((unsigned char)v[p]); p++)
-               *res = 10 * *res + v[p] - '0';
+       for (myres = 0.0; isdigit((unsigned char)v[p]); p++)
+               myres = myres * 10.0 + (v[p] - '0');
+       if (v[p] == '.')
+               for (frac = 0.1; isdigit((unsigned char)v[++p]); frac *= 0.1)
+                       myres += frac * (v[p] - '0');
+
        if (p == *pos + n)
                return 0;
 
        if (n)
-               *res = -*res;
+               myres *= -1.0;
 
        /* Each number may be followed by one optional scaling unit. */
 
-       switch (v[p]) {
+       if (v[p] != '\0' && strchr("ficvPmnpuM", v[p]) != NULL) {
+               if (unit != '\0')
+                       unit = v[p];
+               p++;
+       }
+
+       switch (unit) {
        case 'f':
-               scaled = *res * 65536;
+               myres *= 65536.0;
                break;
        case 'i':
-               scaled = *res * 240;
+               myres *= 240.0;
                break;
        case 'c':
-               scaled = *res * 240 / 2.54;
+               myres *= 24000.0;
+               myres /= 254.0;
                break;
        case 'v':
        case 'P':
-               scaled = *res * 40;
+               myres *= 40.0;
                break;
        case 'm':
        case 'n':
-               scaled = *res * 24;
+               myres *= 24.0;
                break;
        case 'p':
-               scaled = *res * 10 / 3;
+               myres *= 40.0;
+               myres /= 12.0;
                break;
        case 'u':
-               scaled = *res;
                break;
        case 'M':
-               scaled = *res * 6 / 25;
+               myres *= 24.0;
+               myres /= 100.0;
                break;
        default:
-               scaled = *res;
-               p--;
                break;
        }
-       if (flags & ROFFNUM_SCALE)
-               *res = scaled;
-
-       *pos = p + 1;
+       if (res != NULL)
+               *res = myres;
+       *pos = p;
        return 1;
 }
 
@@ -2616,7 +2618,7 @@ roff_evalcond(struct roff *r, int ln, char *v, int *pos)
                while (*cp == ' ')
                        cp++;
                name = cp;
-               sz = roff_getname(r, &cp, ln, cp - v);
+               sz = roff_getname(&cp, ln, cp - v);
                if (sz == 0)
                        istrue = 0;
                else if (v[*pos] == 'r')
@@ -2633,7 +2635,7 @@ roff_evalcond(struct roff *r, int ln, char *v, int *pos)
        }
 
        savepos = *pos;
-       if (roff_evalnum(r, ln, v, pos, &number, ROFFNUM_SCALE))
+       if (roff_evalnum(ln, v, pos, &number, 'u', 0))
                return (number > 0) == wanttrue;
        else if (*pos == savepos)
                return roff_evalstrcond(v, pos) == wanttrue;
@@ -2771,7 +2773,7 @@ roff_ds(ROFF_ARGS)
        if (*name == '\0')
                return ROFF_IGN;
 
-       namesz = roff_getname(r, &string, ln, pos);
+       namesz = roff_getname(&string, ln, pos);
        switch (name[namesz]) {
        case '\\':
                return ROFF_IGN;
@@ -2862,15 +2864,15 @@ roff_getop(const char *v, int *pos, char *res)
  * or a single signed integer number.
  */
 static int
-roff_evalpar(struct roff *r, int ln,
-       const char *v, int *pos, int *res, int flags)
+roff_evalpar(int ln, const char *v, int *pos, int *res, char unit,
+    int skipspace)
 {
 
        if ('(' != v[*pos])
-               return roff_getnum(v, pos, res, flags);
+               return roff_getnum(v, pos, res, unit, skipspace);
 
        (*pos)++;
-       if ( ! roff_evalnum(r, ln, v, pos, res, flags | ROFFNUM_WHITE))
+       if ( ! roff_evalnum(ln, v, pos, res, unit, 1))
                return 0;
 
        /*
@@ -2891,9 +2893,9 @@ roff_evalpar(struct roff *r, int ln,
  * Evaluate a complete numeric expression.
  * Proceed left to right, there is no concept of precedence.
  */
-static int
-roff_evalnum(struct roff *r, int ln, const char *v,
-       int *pos, int *res, int flags)
+int
+roff_evalnum(int ln, const char *v, int *pos, int *res, char unit,
+    int skipspace)
 {
        int              mypos, operand2;
        char             operator;
@@ -2903,29 +2905,29 @@ roff_evalnum(struct roff *r, int ln, const char *v,
                pos = &mypos;
        }
 
-       if (flags & ROFFNUM_WHITE)
+       if (skipspace)
                while (isspace((unsigned char)v[*pos]))
                        (*pos)++;
 
-       if ( ! roff_evalpar(r, ln, v, pos, res, flags))
+       if ( ! roff_evalpar(ln, v, pos, res, unit, skipspace))
                return 0;
 
        while (1) {
-               if (flags & ROFFNUM_WHITE)
+               if (skipspace)
                        while (isspace((unsigned char)v[*pos]))
                                (*pos)++;
 
                if ( ! roff_getop(v, pos, &operator))
                        break;
 
-               if (flags & ROFFNUM_WHITE)
+               if (skipspace)
                        while (isspace((unsigned char)v[*pos]))
                                (*pos)++;
 
-               if ( ! roff_evalpar(r, ln, v, pos, &operand2, flags))
+               if ( ! roff_evalpar(ln, v, pos, &operand2, unit, skipspace))
                        return 0;
 
-               if (flags & ROFFNUM_WHITE)
+               if (skipspace)
                        while (isspace((unsigned char)v[*pos]))
                                (*pos)++;
 
@@ -3062,6 +3064,8 @@ roff_getregro(const struct roff *r, const char *name)
                return 24;
        case 'j':  /* Always adjust left margin only. */
                return 0;
+       case 'l':  /* Fixed line width for DocBook. */
+               return 78 * 24;
        case 'T':  /* Some output device is always defined. */
                return 1;
        case 'V':  /* Fixed vertical resolution. */
@@ -3155,7 +3159,7 @@ roff_nr(ROFF_ARGS)
        if (*key == '\0')
                return ROFF_IGN;
 
-       keysz = roff_getname(r, &val, ln, pos);
+       keysz = roff_getname(&val, ln, pos);
        if (key[keysz] == '\\' || key[keysz] == '\t')
                return ROFF_IGN;
 
@@ -3164,13 +3168,13 @@ roff_nr(ROFF_ARGS)
                val++;
 
        len = 0;
-       if (roff_evalnum(r, ln, val, &len, &iv, ROFFNUM_SCALE) == 0)
+       if (roff_evalnum(ln, val, &len, &iv, 'u', 0) == 0)
                return ROFF_IGN;
 
        step = val + len;
        while (isspace((unsigned char)*step))
                step++;
-       if (roff_evalnum(r, ln, step, NULL, &is, 0) == 0)
+       if (roff_evalnum(ln, step, NULL, &is, '\0', 0) == 0)
                is = INT_MIN;
 
        roff_setregn(r, key, keysz, iv, sign, is);
@@ -3187,7 +3191,7 @@ roff_rr(ROFF_ARGS)
        name = cp = buf->buf + pos;
        if (*name == '\0')
                return ROFF_IGN;
-       namesz = roff_getname(r, &cp, ln, pos);
+       namesz = roff_getname(&cp, ln, pos);
        name[namesz] = '\0';
 
        prev = &r->regtab;
@@ -3217,7 +3221,7 @@ roff_rm(ROFF_ARGS)
        cp = buf->buf + pos;
        while (*cp != '\0') {
                name = cp;
-               namesz = roff_getname(r, &cp, ln, (int)(cp - buf->buf));
+               namesz = roff_getname(&cp, ln, (int)(cp - buf->buf));
*** 180 LINES SKIPPED ***

Reply via email to