From mboxrd@z Thu Jan 1 00:00:00 1970 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=none autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 4884 invoked from network); 23 Oct 2023 21:24:02 -0000 Received: from bsd.lv (HELO mandoc.bsd.lv) (66.111.2.12) by inbox.vuxu.org with ESMTPUTF8; 23 Oct 2023 21:24:02 -0000 Received: from fantadrom.bsd.lv (localhost [127.0.0.1]) by mandoc.bsd.lv (OpenSMTPD) with ESMTP id aea83849 for ; Mon, 23 Oct 2023 21:24:00 +0000 (UTC) Received: from scc-mailout-kit-02.scc.kit.edu (scc-mailout-kit-02.scc.kit.edu [129.13.231.82]) by mandoc.bsd.lv (OpenSMTPD) with ESMTP id 5278ac3c for ; Mon, 23 Oct 2023 21:24:00 +0000 (UTC) Received: from hekate.asta.kit.edu ([2a00:1398:5:f401::77]) by scc-mailout-kit-02.scc.kit.edu with esmtps (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (envelope-from ) id 1qv2P0-009fsr-1r; Mon, 23 Oct 2023 23:23:59 +0200 Received: from login-1.asta.kit.edu ([2a00:1398:5:f400::72]) by hekate.asta.kit.edu with esmtp (Exim 4.94.2) (envelope-from ) id 1qv2Oy-000Xxk-Gz; Mon, 23 Oct 2023 23:23:56 +0200 Received: from schwarze by login-1.asta.kit.edu with local (Exim 4.94.2) (envelope-from ) id 1qv2Ox-001JLy-QZ; Mon, 23 Oct 2023 23:23:55 +0200 Date: Mon, 23 Oct 2023 23:23:55 +0200 From: Ingo Schwarze To: Paul Eggert Cc: tech@mandoc.bsd.lv, g.branden.robinson@gmail.com, Alejandro Colomar Subject: Re: mandoc mishandles tzfile(5)'s .IP \(bu "\w'\(bu 'u" Message-ID: References: <884cb5d0-27ce-a5ca-b449-972021e62e92@gmail.com> <7c3294cf-e3d0-c716-d1c0-5b6c5c757d7e@cs.ucla.edu> <7eb92df5-6c87-8384-c4a8-2a00eabf1c8e@gmail.com> <66ef5b92-6e19-8bea-2840-6c2f0240d225@cs.ucla.edu> <160e850e-c5eb-45a9-9011-b766ade9dd10@cs.ucla.edu> X-Mailinglist: mandoc-tech Reply-To: tech@mandoc.bsd.lv MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable In-Reply-To: <160e850e-c5eb-45a9-9011-b766ade9dd10@cs.ucla.edu> Hi Paul, Paul Eggert wrote on Sun, Oct 22, 2023 at 05:41:28PM -0700: > On 2023-10-22 14:06, Ingo Schwarze wrote: >> mandoc only supports ASCII strings as arguments to \w, not escape >> sequences or formatting instructions. =20 > For the TZDB man pages mandoc need not support all that, just \(bu. Thank you for identifying a subset of the functionality that is both useful and feasible. That's so much better than the TODO item for \w i have lying around - that one is much less important than what you suggested but horrifically difficult. > Just to make sure we're on the same page, I reproduced the problem by=20 > running the command "mandoc -man -Tascii t.5", where t.5 contains the=20 > following lines: >=20 > .TH tzfile 5 > .SH NAME > .IP \(bu "\w'\(bu 'u" > xxx > .PP > yyy >=20 > The output should contain two spaces between the bullet's "o" and the=20 > "x", but with current mandoc it contains five spaces. Yes, that matches my understanding. > Proposed mandoc patch attached. This isn't a perfect emulation of groff,= =20 In this case, that's a virtue, even though in many other cases, compatibility with groff is indeed among the main goals. > nor have I tested with fancy constructs, Not a major roadblock; such testing becomes significantly easier with the existing test suite, and by adding to it. > but it should be good enough for tzfile(5). And likely for some other pages, too. Regarding the implementation: I did not like that you did most of the work in roff_escape.c. That function is called each and every time any parser or formatter wants to deal with any escape sequence. Your patch did additional work for almost every kind of escape sequence, even though \w is the only escape sequence needing that kind of work. On top of that, while changing the internal API mandoc_escape(3) is not unheard of and can be done when it is really important, the need for an API break did not seem very urgent to me here. Consequently, i chose to do all the work at one local place in the internal function roff_expand(). Even though that requires iterating the argument of every \w escape sequence twice, it causes less work regarding the grand total because \w is a rare escape sequence, occurring much less frequently than other sequences, and even for \w relevant extra work is only done if the argument contains embedded escape sequences, which will occur still less frequently. Encountering long, complicated, deeply nested esacpe sequences inside \w would definitely be unusual. Doing extra work for every parsing and every formatting of each and every escape sequence sounds clearly worse. Besides, roff_expand() is really the place where the logic belongs. The function roff_escape() is a parser. Its job is to figure out where the various syntax elements (sequence, name, argument) begin and end and what the class of the sequence is. Doing calculations bases on the content of the argument is out of scope there, and considering that it's a parser, doing calculations related to formatting even more so. Calculating the information needed for interpolation really belongs into the string interpolation function roff_expand(), and given that \w in particular is related to formatting, the normal internal ESCAPE_* API that the formatters use for such purposes should be used here, too. Potentially, that might also make future refinements of the functionality easier: the more this code already resenmbles typical formatter code, the better. To summarize, i committed the following patch. Does that patch work for you as well as your own? Yours, Ingo Log Message: ----------- Support some escape sequences, in particular character escape sequences, inside \w arguments, and skip most other escape sequences when measuring the output length in this way because most escape sequences contribute little or nothing to text width: for example, consider font escapes in terminal output. This implementation is very rudimentary. In particular, it assumes that every character has the same width. No attempt is made to detect=20 double-width or zero-width Unicode characters or to take dependencies on output devices or fonts into account. These limitations are hard to avoid because mandoc has to interpolate \w at the parsing stage when the output device is not yet known. I really do not want the content of the syntax tree to depend on the output device. Feature requested by Paul , who also submitted a patch, but i chose to commit this very different patch with almost the same functionality. His input was still very valuable because complete support for \w is out of the question, and consequently, the main task is identifying subsets of the feature that are needed for real-world manual pages=20 and can be supported without uprooting the whole forest. Modified Files: -------------- mandoc: roff.7 roff.c mandoc/regress/roff/esc: w.in w.out_ascii w.out_lint Revision Data ------------- Index: roff.7 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/cvs/mandoc/mandoc/roff.7,v retrieving revision 1.120 retrieving revision 1.121 diff -Lroff.7 -Lroff.7 -u -p -r1.120 -r1.121 --- roff.7 +++ roff.7 @@ -1,6 +1,6 @@ .\" $Id$ .\" -.\" Copyright (c) 2010-2019, 2022 Ingo Schwarze +.\" Copyright (c) 2010-2019, 2022-2023 Ingo Schwarze .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -2224,7 +2224,8 @@ The .Xr mandoc 1 implementation assumes that after expansion of user-defined strings, the .Ar string -only contains normal characters, no escape sequences, and that each +only contains normal characters, characters expressed as escape sequences, +and zero-width escape sequences, and that each character has a width of 24 basic units. .It Ic \eX\(aq Ns Ar string Ns Ic \(aq Output Index: roff.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/cvs/mandoc/mandoc/roff.c,v retrieving revision 1.398 retrieving revision 1.399 diff -Lroff.c -Lroff.c -u -p -r1.398 -r1.399 --- roff.c +++ roff.c @@ -1,6 +1,6 @@ /* $Id$ */ /* - * Copyright (c) 2010-2015, 2017-2022 Ingo Schwarze + * Copyright (c) 2010-2015, 2017-2023 Ingo Schwarze * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any @@ -1362,6 +1362,7 @@ roff_expand(struct roff *r, struct buf * const char *res; /* the string to be pasted */ const char *src; /* source for copying */ char *dst; /* destination for copying */ + enum mandoc_esc subtype; /* return value from roff_escape */ int iesc; /* index of leading escape char */ int inam; /* index of the escape name */ int iarg; /* index beginning the argument */ @@ -1551,8 +1552,34 @@ roff_expand(struct roff *r, struct buf * res =3D ubuf; break; case 'w': - (void)snprintf(ubuf, sizeof(ubuf), - "%d", (iendarg - iarg) * 24); + rsz =3D 0; + subtype =3D ESCAPE_UNDEF; + while (iarg < iendarg) { + asz =3D subtype =3D=3D ESCAPE_SKIPCHAR ? 0 : 1; + if (buf->buf[iarg] !=3D '\\') { + rsz +=3D asz; + iarg++; + continue; + } + switch ((subtype =3D roff_escape(buf->buf, 0, + iarg, NULL, NULL, NULL, NULL, &iarg))) { + case ESCAPE_SPECIAL: + case ESCAPE_NUMBERED: + case ESCAPE_UNICODE: + case ESCAPE_OVERSTRIKE: + case ESCAPE_UNDEF: + break; + case ESCAPE_DEVICE: + asz *=3D 8; + break; + case ESCAPE_EXPAND: + abort(); + default: + continue; + } + rsz +=3D asz; + } + (void)snprintf(ubuf, sizeof(ubuf), "%d", rsz * 24); res =3D ubuf; break; default: Index: w.out_ascii =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/cvs/mandoc/mandoc/regress/roff/esc/w.out_ascii,v retrieving revision 1.3 retrieving revision 1.4 diff -Lregress/roff/esc/w.out_ascii -Lregress/roff/esc/w.out_ascii -u -p -r= 1.3 -r1.4 --- regress/roff/esc/w.out_ascii +++ regress/roff/esc/w.out_ascii @@ -8,6 +8,13 @@ D=08DE=08ES=08SC=08CR=08RI=08IP=08PT=08TI=08IO=08ON=08N character: 24 blank: 24 text: 96 + special: 24 + numbered: 24 + Unicode: 24 + overstrike: 24 + undefined: 24 + zero-width: 0 + skipchar: 48 =20 A=08Ar=08rg=08gu=08um=08me=08en=08nt=08t d=08de=08el=08li=08im=08mi=08i= t=08te=08er=08rs=08s unsupported \r: 24u @@ -27,4 +34,4 @@ D=08DE=08ES=08SC=08CR=08RI=08IP=08PT=08TI=08IO=08ON=08N overstrike: 24u unterminated: 72 =20 -OpenBSD June 8, 2022 Ope= nBSD +OpenBSD October 23, 2023 Ope= nBSD Index: w.out_lint =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/cvs/mandoc/mandoc/regress/roff/esc/w.out_lint,v retrieving revision 1.7 retrieving revision 1.8 diff -Lregress/roff/esc/w.out_lint -Lregress/roff/esc/w.out_lint -u -p -r1.= 7 -r1.8 --- regress/roff/esc/w.out_lint +++ regress/roff/esc/w.out_lint @@ -1,4 +1,5 @@ -mandoc: w.in:17:20: UNSUPP: unsupported escape sequence: \r -mandoc: w.in:17:23: UNSUPP: unsupported escape sequence: \r -mandoc: w.in:23:16: WARNING: undefined escape, printing literally: \G -mandoc: w.in:51:15: ERROR: incomplete escape sequence: \w'foo +mandoc: w.in:25:15: WARNING: undefined escape, printing literally: \G +mandoc: w.in:31:20: UNSUPP: unsupported escape sequence: \r +mandoc: w.in:31:23: UNSUPP: unsupported escape sequence: \r +mandoc: w.in:37:16: WARNING: undefined escape, printing literally: \G +mandoc: w.in:65:15: ERROR: incomplete escape sequence: \w'foo Index: w.in =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/cvs/mandoc/mandoc/regress/roff/esc/w.in,v retrieving revision 1.3 retrieving revision 1.4 diff -Lregress/roff/esc/w.in -Lregress/roff/esc/w.in -u -p -r1.3 -r1.4 --- regress/roff/esc/w.in +++ regress/roff/esc/w.in @@ -1,4 +1,4 @@ -.\" $OpenBSD: w.in,v 1.4 2022/06/08 13:08:00 schwarze Exp $ +.\" $OpenBSD: w.in,v 1.5 2023/10/23 20:07:19 schwarze Exp $ .Dd $Mdocdate$ .Dt ESC-W 1 .Os @@ -13,6 +13,20 @@ character: \w'n' blank: \w' ' .br text: \w'text' +.br +special: \w'\(bu' +.br +numbered: \w'\N'100'' +.br +Unicode: \w'\[u2013]' +.br +overstrike: \w'\o'ab'' +.br +undefined: \w'\G' +.br +zero-width: \w'\fB\&\fP' +.br +skipchar: \w'a\zb\z\(buc' .Ss Argument delimiters unsupported \er: \w\rM\ru .br -- To unsubscribe send an email to tech+unsubscribe@mandoc.bsd.lv