From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.4 Received: from mandoc.bsd.lv (bsd.lv [66.111.2.12]) by inbox.vuxu.org (Postfix) with ESMTP id 492652D0F0 for ; Sun, 5 Jan 2025 19:14:43 +0100 (CET) Received: from fantadrom.bsd.lv (localhost [127.0.0.1]) by mandoc.bsd.lv (OpenSMTPD) with ESMTP id a9993b8d for ; Sun, 5 Jan 2025 18:14:42 +0000 (UTC) Received: from localhost (mandoc.bsd.lv [local]) by mandoc.bsd.lv (OpenSMTPD) with ESMTPA id 2eb4baf9 for ; Sun, 5 Jan 2025 18:14:42 +0000 (UTC) Date: Sun, 5 Jan 2025 18:14:42 +0000 (UTC) X-Mailinglist: mandoc-source Reply-To: source@mandoc.bsd.lv MIME-Version: 1.0 From: schwarze@mandoc.bsd.lv To: source@mandoc.bsd.lv Subject: mandoc: In the tbl(7) layout parser, use the roff(7) numerical X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 Message-ID: <95009ff764ce74f4@mandoc.bsd.lv> Log Message: ----------- In the tbl(7) layout parser, use the roff(7) numerical expression parser to support arithmetic operations in column width modifiers. Documentation authors ought to focus on semantic markup and avoid trying to manipulate presentational details. Consequently, using tbl(7) is discouraged in the first place, using column width modifiers even more so, and complicating them by performing arithmetics yet more so. However, the madhouse called DocBook relies on this feature. For example, DocBook XSL version 1.79.2 generates man(7)+tbl(7) code that abuses arithmetics in column width modifiers to format things as simple and mundane as numbered lists, resulting in atrocious layout that is very hard to read. Last year, tb@ reported git-reset(1) as an example of an affected manual page. Properly parsing the width in the tbl(7) parser allows removal of some incomplete ad-hoc parsing from the tbl(7) formatter, where it didn't really belong. Modified Files: -------------- mandoc: mandoc.1 mandoc.h mandoc_msg.c out.c tbl.c tbl.h tbl_layout.c mandoc/regress/tbl/mod: width.in width.out_ascii Revision Data ------------- Index: tbl_layout.c =================================================================== RCS file: /home/cvs/mandoc/mandoc/tbl_layout.c,v diff -Ltbl_layout.c -Ltbl_layout.c -u -p -r1.50 -r1.51 --- tbl_layout.c +++ tbl_layout.c @@ -1,8 +1,8 @@ /* $Id$ */ /* - * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2012, 2014, 2015, 2017, 2020, 2021 + * Copyright (c) 2012, 2014, 2015, 2017, 2020, 2021, 2025 * Ingo Schwarze + * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -67,7 +67,6 @@ mods(struct tbl_node *tbl, struct tbl_ce { char *endptr; unsigned long spacing; - size_t sz; int isz; enum mandoc_esc fontesc; @@ -138,20 +137,27 @@ mod: cp->flags |= TBL_CELL_UP; goto mod; case 'w': - sz = 0; if (p[*pos] == '(') { (*pos)++; - while (p[*pos + sz] != '\0' && p[*pos + sz] != ')') - sz++; - } else - while (isdigit((unsigned char)p[*pos + sz])) - sz++; - if (sz) { - free(cp->wstr); - cp->wstr = mandoc_strndup(p + *pos, sz); - *pos += sz; - if (p[*pos] == ')') + isz = 0; + if (roff_evalnum(ln, p, pos, &isz, 'n', 1) == 0 || + p[*pos] != ')') + mandoc_msg(MANDOCERR_TBLLAYOUT_WIDTH, + ln, *pos, "%s", p + *pos); + else { + /* Convert from BU to EN and round. */ + cp->width = (isz + 11) /24; (*pos)++; + } + } else { + cp->width = 0; + while (isdigit((unsigned char)p[*pos])) { + cp->width *= 10; + cp->width += p[(*pos)++] - '0'; + } + if (cp->width == 0) + mandoc_msg(MANDOCERR_TBLLAYOUT_WIDTH, + ln, *pos, "%s", p + *pos); } goto mod; case 'x': Index: tbl.c =================================================================== RCS file: /home/cvs/mandoc/mandoc/tbl.c,v diff -Ltbl.c -Ltbl.c -u -p -r1.46 -r1.47 --- tbl.c +++ tbl.c @@ -118,7 +118,6 @@ tbl_free(struct tbl_node *tbl) while (rp->first != NULL) { cp = rp->first; rp->first = cp->next; - free(cp->wstr); free(cp); } free(rp); Index: mandoc_msg.c =================================================================== RCS file: /home/cvs/mandoc/mandoc/mandoc_msg.c,v diff -Lmandoc_msg.c -Lmandoc_msg.c -u -p -r1.20 -r1.21 --- mandoc_msg.c +++ 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 + * Copyright (c) 2014-2022, 2025 Ingo Schwarze * Copyright (c) 2010, 2011 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any @@ -192,6 +192,7 @@ static const char *const type_message[MA "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", Index: mandoc.h =================================================================== RCS file: /home/cvs/mandoc/mandoc/mandoc.h,v diff -Lmandoc.h -Lmandoc.h -u -p -r1.282 -r1.283 --- mandoc.h +++ mandoc.h @@ -1,6 +1,6 @@ /* $Id$ */ /* - * Copyright (c) 2012-2022 Ingo Schwarze + * Copyright (c) 2012-2022, 2025 Ingo Schwarze * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons * * 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 */ Index: mandoc.1 =================================================================== RCS file: /home/cvs/mandoc/mandoc/mandoc.1,v diff -Lmandoc.1 -Lmandoc.1 -u -p -r1.267 -r1.268 --- mandoc.1 +++ mandoc.1 @@ -1,6 +1,6 @@ .\" $Id$ .\" -.\" Copyright (c) 2012, 2014-2023 Ingo Schwarze +.\" Copyright (c) 2012, 2014-2023, 2025 Ingo Schwarze .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -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 accomodate all its data cells. .It Sy "ignoring excessive spacing in tbl layout" .Pq tbl A spacing modifier in a table layout is unreasonably large. Index: tbl.h =================================================================== RCS file: /home/cvs/mandoc/mandoc/tbl.h,v diff -Ltbl.h -Ltbl.h -u -p -r1.2 -r1.3 --- tbl.h +++ tbl.h @@ -51,7 +51,6 @@ enum tbl_cellt { */ struct tbl_cell { struct tbl_cell *next; /* Layout cell to the right. */ - char *wstr; /* Min width represented as a string. */ size_t width; /* Minimum column width. */ size_t spacing; /* To the right of the column. */ int vert; /* Width of subsequent vertical line. */ Index: out.c =================================================================== RCS file: /home/cvs/mandoc/mandoc/out.c,v diff -Lout.c -Lout.c -u -p -r1.85 -r1.86 --- out.c +++ out.c @@ -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 struc 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 && Index: width.out_ascii =================================================================== RCS file: /home/cvs/mandoc/mandoc/regress/tbl/mod/width.out_ascii,v diff -Lregress/tbl/mod/width.out_ascii -Lregress/tbl/mod/width.out_ascii -u -p -r1.4 -r1.5 --- regress/tbl/mod/width.out_ascii +++ regress/tbl/mod/width.out_ascii @@ -4,9 +4,53 @@ NNAAMMEE tbl-mod-width - width modifier in table layout DDEESSCCRRIIPPTTIIOONN - normal text + Bare numbers without parentheses use EN units: + +---+------+ + |a | abcd | + +---+------+ + + Explicit scaling units and rounding - metric: + +-----+ + |1cm | + +-----+ + + Explicit scaling units and rounding - pica: + +---+ + |P | + +---+ + +----+ + |2P | + +----+ + + Explicit scaling units and rounding - points: + +----+ + |25p | + +----+ + +-----+ + |26p | + +-----+ + + Explicit scaling units and rounding - basic units: + +----+ + |84u | + +----+ + +-----+ + |85u | + +-----+ + + Multiplication: + +-------+--------+--------+--------+ + |3n*2u | 3u*2n | 3u*2 | 3*2u | + +-------+--------+--------+--------+ + + Division: + +--------+----------+--------+--------+ + |14n/2u | 384n/2n | 12/2u | 288/2 | + +--------+----------+--------+--------+ + + Data section containing text blocks: +---+------+----+------+ |a | abcd | a | abcd | +---+------+----+------+ -OpenBSD June 8, 2017 TBL-MOD-WIDTH(1) +OpenBSD January 4, 2025 TBL-MOD-WIDTH(1) Index: width.in =================================================================== RCS file: /home/cvs/mandoc/mandoc/regress/tbl/mod/width.in,v diff -Lregress/tbl/mod/width.in -Lregress/tbl/mod/width.in -u -p -r1.3 -r1.4 --- regress/tbl/mod/width.in +++ regress/tbl/mod/width.in @@ -1,12 +1,76 @@ -.\" $OpenBSD: width.in,v 1.3 2017/07/04 14:53:27 schwarze Exp $ -.TH TBL-MOD-WIDTH 1 "June 8, 2017" +.\" $OpenBSD: width.in,v 1.4 2025/01/05 18:03:51 schwarze Exp $ +.TH TBL-MOD-WIDTH 1 "January 4, 2025" .SH NAME tbl-mod-width \- width modifier in table layout .SH DESCRIPTION -normal text +Bare numbers without parentheses use EN units: .TS box tab(:); -lw2 | lw(2n) | lw(0.16i) | lw2 . +Lw2 | Lw3 . +a:abcd +.TE +.PP +Explicit scaling units and rounding \(en metric: +.TS +box tab(:); +Lw(1c). +1cm +.TE +.PP +Explicit scaling units and rounding \(en pica: +.TS +box tab(:); +Lw(1P). +P +.TE +.TS +box tab(:); +Lw(2P). +2P +.TE +.PP +Explicit scaling units and rounding \(en points: +.TS +box tab(:); +Lw(25p). +25p +.TE +.TS +box tab(:); +Lw(26p). +26p +.TE +.PP +Explicit scaling units and rounding \(en basic units: +.TS +box tab(:); +Lw(84u). +84u +.TE +.TS +box tab(:); +Lw(85u). +85u +.TE +.PP +Multiplication: +.TS +box tab(:); +Lw(3n*2u) | Lw(3u*2n) | Lw(3u*2) | Cw(3*2u). +3n*2u:3u*2n:3u*2:3*2u +.TE +.PP +Division: +.TS +box tab(:); +Lw(14n/2u) | Lw(384n/2n) | Lw(12/2u) | Lw(288/2). +14n/2u:384n/2n:12/2u:288/2 +.TE +.PP +Data section containing text blocks: +.TS +box tab(:); +lw2 | lw(2n) | lw(2m) | lw2 . a:abcd:T{ a T}:T{ -- To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv