Hi Ingo,

At 2026-01-19T11:55:49+0100, Ingo Schwarze wrote:
> I had to look up what \n[.y] even is, and now i find it weird that
> this register exists at all.

I think you mean `\n[.Y]`--uppercase.

To refresh readers:
$ nroff -t -man -P -cbou $(man -w 'groff(7)') | grep '\n\[\.[XxYy]]'
       \n[.x]         Major version number of the running troff formatter.
       \n[.y]         Minor version number of the running troff formatter.
       \n[.Y]         Revision number of the running troff formatter.

(Why not `.z`?  Ossanna troff already used that for another purpose.
But this may be fortunate, since as you note, people should likely not
employ `.Y` for the same sorts of purposes as `.x` and `.y` anyway.)

> That's not something documents should access or depend on.

I think you're taking a sound principle and carrying it a little too
far.  I'll explain.

I don't think a _visible interface change_, meaning something one can
write *roff document (or macro file) logic depending on, should be
accompanied by anything less than a minor version bump.  (I'll qualify
this claim below.)

However, I have actually used the feature myself not to manage flow of
control, but simply to annotate a reconstructed document with the
identity of its formatter.[2]  After all, the date isn't part of the
formatter interface either, so why do we have the crap below?

$ nroff -t -man -P -cbou $(man -w 'groff(7)') \
  | grep -E '\n\[(year|yr|mo|dy|dw|hours|minutes|seconds)]'
       \n[dw]         Day of the week (1–7; 1 is Sunday).
       \n[dy]         Day of the month (1–31).
       \n[hours]      Count of hours elapsed since midnight (0–23).
       \n[minutes]    Count of minutes elapsed in the hour (0–59).
       \n[mo]         Month of the year (1–12).
       \n[seconds]    Count of seconds elapsed in the minute (0–60).
       \n[year]       Gregorian year.
       \n[yr]         Gregorian year minus 1900.

For the limited purpose of disclosing information about the formatter
itself or its operating environment[3], it seems fine to me, and if we
hold to the contract of semantic versioning[4] applied to the formatter
itself, users will seldom have reason to write logic predicated on it.

The combination of groff's non-glacial development pace and limited
quantity of personnel means we don't do "micro" (or "revision") version
releases to a "stable branch" anymore, but it's conceivable that we
might in the future--if, for example, a painful security vulnerability
arises or a behavioral bug comes to our attention that is too grievous
not to be backported.

In that circumstance, a user might want to write `\n[.Y]`-based logic to
work around the bug (or simply abort the formatter) because they have
out-of-band knowledge of the bug fix.

This sharp line gets fuzzy if the bug fix in question can alter
formatting outcomes, in which case it might be observable after all--for
example, if with a particular document I know that groff 1.22.2 records
one vertical drawing position after typesetting the phrase "landowner's
oscillation" and groff 1.22.3 records another.  In that scenario, one
might either test the micro/revision number register `.Y` or, I think
more advisedly, test the vertical drawing position `\n[nl]` itself.

So, unlike you, I don't need smelling salts to cope with `\n[.Y]`.  But
it should be used only advisedly.

> Whatever, we have the usual problem of feature creep here:

Regarding register `.Y`, possibly.  Regarding `.y`, that feature crept
in in the mid-1970s with Ossanna troff.[1]  You'll need a spirit medium
to take your objection up with him.

> once a useless or detrimental feature has been added, it's hard to
> remove again because somebody is likely to have started depending on
> it, however unwisely.
> 
> However, i regard .Y as totally unrelated to the naming of the
> release tarball.  Isn't the obvious right thing to do to set
> the file and directory name to groff-1.24.0rc1 and set .Y to 0?

I think it was Bertrand who put in some machinery tying Git, Autoconf,
and Automake together to construct the name of the directory (and
therefore the tar archive).  I failed to exercise that machinery for
rc1, and simply renamed the archive (which "make dist" had made for me)
for upload to alpha.gnu.org.  That was a mistake, which you and Colin
pointed out.

https://savannah.gnu.org/bugs/?67933

I have a change in my working copy that intends to resolve that
ticket.[5]

Also, `.Y` _does_ report `0`, even with a build from the weirdly-named-
when-unpacked rc1 archive.  If you're seeing something else, I want to
hear about it.

> > I'm having trouble tracking down citations, but it [happened] back
> > around 2017-2018.  I think a release candidate was put out and it
> > broke weirdly for some people because the interpolated contents of
> > the `.Y` register were not a simple integer.
> 
> Right, obviously setting .Y to "0rc1" would be wrong because
> .Y is documented as the "Minor version number" and "0rc1" is not
> the minor version number...

I think you got your lettercase scrambled...

       \n[.Y]         Revision number of the running troff formatter.

> Duh.

But if you mean "a number is a decimal integer", then yes.

> So, here is the second problem report.  For now, i'm lazily quoting
> my preliminary commit message in the WIP port:

I'll reply separately to this issue because it's a totally different
subject.

Regards,
Branden

[1] https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/doc/troff
[2] https://lists.gnu.org/archive/html/groff/2024-10/msg00096.html

[3]

$ info ./build/doc/groff.info
...
5.8.5 Built-in Registers
------------------------

Predefined registers whose identifiers start with a dot are read-only.
Many are Boolean-valued, interpolating a true or false value testable
with the 'if', 'ie', or 'while' requests.

   *Caution:* Built-in registers are subject to removal like others;
once removed, they can be recreated only as normal writable registers
and will not otherwise reflect the configuration of the formatter.

   A register name is often associated with a request of the same name
(without the dot).  A complete listing of all built-in registers can be
found in *note Register Index::.

   We present here a few built-in registers that are not described
elsewhere in this manual; they have to do with invariant properties of
GNU 'troff', or obtain information about the formatter's command-line
options or processing progress.

...

5.34 Host System Service Access
===============================

Occasionally a document wants to access the system clock, file storage,
or other services provided by the operating environment.

[4] https://semver.org/

    People have, predictably, turned semantic versioning into a
    religion.  Naturally enough, an effort to deprogram its cultists has
    risen in response.

    https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e
    
https://reprog.wordpress.com/2023/12/27/semantic-versioning-is-a-terrible-mistake/

[5] In fact, here's everything in my working copy relative to rc1.

commit c1dee79ef67fbc1c718fe6c7f6331263e751cc87 (HEAD -> master)
Author: G. Branden Robinson <[email protected]>
Date:   Sun Jan 18 19:12:10 2026 -0600

    HACKING: Add guidance re: a failure scenario.

commit 9119a112c382b3316dd0b216c86b2b55f3d4cdad
Author: G. Branden Robinson <[email protected]>
Date:   Sun Jan 18 18:46:27 2026 -0600

    FOR-RELEASE: Add item; thanks to Ingo Schwarze.

commit 860cc8f67b468312ffcc4f4de6c14190d6eb2602 (origin/master, origin/HEAD)
Author: G. Branden Robinson <[email protected]>
Date:   Sun Jan 18 15:26:21 2026 -0600

    NEWS: Fix fractured grammar in item.

I'll need to update the middle item to add a bug-closer.

Attachment: signature.asc
Description: PGP signature

Reply via email to