At 2026-09-05T18:12:20+0200, Ingo Schwarze wrote:
> i'm reporting here instead of on Savannah because Savannah is so slow
> that i cannot use it.  Details at the very end of this posting.

LLM = DDoS  :(

> In groff-1.22.4, an empty tbl(7) table resulted in a blank output
> line in terminal output.  In groff-1.23.0, it no longer results
> in anything whatsoever, not even in an output line break.

I object, as I often must with respect to your reports, to your
characterization of this behavior as a "regression".  Show me where the
`TS` macro is _specified_, anywhere, even in mandoc(1)'s man pages, as
causing a break.

As I said in February,

"...if mandoc sampled groff in 2010 or so and resolved to pour
cement over every measurable aspect of groff behavior, whether specified
or not, whether documented or not, whether known to be a bug or not, and
proceeded to write all of its automated tests on such a presumption of
utter fixity in the software system being simulated, then the
mdocml/mandoc project set itself up for failure in this area.

...

What I will not do is abandon groff as a living software system or have
Hyrum's Law[...] imposed forcibly upon its developers by another
project.  To accept either would be betray my responsibilities as
_maintainer_ of the groff project.  An utterly stagnant system neither
has, nor requires, maintenance."[1]

That established, I think the balance of factors is likely in favor of
having _man_(7)'s (and _mdoc_(7)'s) `TS` macro unconditionally break,
but we must be quite cautious about undertaking any extrapolation
therefrom.  I'll return to this point.

> Here is what i mean by "empty table":
> 
>   .TH TBL-DATA-EMPTY 1 "January 28, 2015"
>   .SH NAME
>   tbl-data-empty \- empty table
>   .SH DESCRIPTION
>   normal text
>   .TS
>   box; l.
>   .TE
>   normal text

GNU tbl has complained about this sort of degenerate input since 1.22.4
at the latest.

$ printf '.TS\nL.\n.TE\n' | ~/groff-1.22.4/bin/tbl >/dev/null
/home/branden/groff-1.22.4/bin/tbl:<standard input>:3: no real data
/home/branden/groff-1.22.4/bin/tbl:<standard input>:3: giving up on this table

> With groff-1.22.4, the output was:
> 
>   DESCRIPTION
>        normal text
>   
>        normal text
> 
> With groff-1.23.0 and groff-1.25.0rc2, the output is:
> 
>   DESCRIPTION
>        normal text normal text
> 
> I think this is wrong and the output should be:
> 
>   DESCRIPTION
>        normal text
>        normal text
> 
> The blank line goes away because groff-1.23.0 changed the rules for
> vertical spacing around tables, but the line break should not go
> away: the beginning and the end of every table still implies a break,
> tables never appear on the same output line as preceding or following
> text.
> 
> As the root cause, based on this -W all output,
> 
>   tbl:"empty.in:9: error: no data in table
>   tbl:"empty.in:9: error: giving up on this table region
>   an.tmac:empty.in:9: warning: tbl preprocessor failed,
>     or it or soelim was not run; table(s) likely not rendered
>     (TE macro called with TW register undefined)
> 
> i suspect a parser regression.

Nothing of the sort.  The input promised a table that never showed up.

An empty table is an error condition.

> Probably a condition that would indeed warrant a warning was
> inadvertently turned into a fatal error.

There's no fatal error here in groff.  Since you hit a `.TE` token with
no preceding table, the fact that tbl "gives up" does no harm to the
document.  You can start up another table region, and it will render.

$ printf '.TS\nL.\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | ~/groff-1.22.4/bin/groff -at
tbl:<standard input>:3: no real data
tbl:<standard input>:3: giving up on this table
<beginning of page>
Hi, Ingo!

...and in more recent groffs, no "turning into a fatal error" has taken
place.

$ printf '.TS\nL.\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | ~/groff-1.24.1/bin/groff -at
tbl:<standard input>:3: error: no data in table
tbl:<standard input>:3: error: giving up on this table region
<beginning of page>
Hi, Ingo!

We can further elaborate the example, and illustrate text being
discarded due to GNU tbl giving up on the table region.

$ printf '.TS\nL.\n.T&\nL.fnord\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | ~/groff-1.24.1/bin/groff -at

$ printf '.TS\nL.\n.T&\nL.fnord\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | ~/groff-1.24.1/bin/groff -at
tbl:<standard input>:4: error: '.' is not the last character of the table format
tbl:<standard input>:4: error: giving up on this table region
<beginning of page>
Hi, Ingo!

Other tbl(1)s do likewise.

$ printf '.TS\nL.\n.T&\nL.fnord\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | solaris10 tbl | grep fnord

Input: line 4: dot not last character on format line
tbl quits

$ printf '.TS\nL.\n.T&\nL.fnord\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | dwb tbl | grep fnord
File -, line 4: Dot not last character on format line
tbl quits

$ printf '.TS\nL.\n.T&\nL.fnord\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | 9 tbl | grep fnord

Input:4: dot not last character on format line
tbl quits

$ printf '.TS\nL.\n.T&\nL.fnord\n.TE\n.TS\nL.\nHi, Ingo!\n.TE\n' \
  | heirloom tbl | grep fnord

Input: line 4: dot not last character on format line
tbl quits

Heirloom Doctools _tbl_, like GNU _tbl_, doesn't "quit", but stops
processing only the tbl region that has a problem, so with these two
_tbl_s, "Hi, Ingo!" gets formatted.

Mike Lesk apparently took the "fail fast, fail hard" principle even
farther than I do.  Unproductively far, IMO.

> Right now, mandoc is still compattible with groff-1.22.4 in this
> respect.  My preference would be to change it to do what i displayed
> below "should be" above, hoping that groff might eventually fix the
> regression.

Namely, that this:

>   normal text
>   .TS
>   box; l.
>   .TE
>   normal text

should render as:

>        normal text
>        normal text

...and I'm okay with that.

> Then again, if you feel very strongly that the behaviour in
> groff-1.25.0rc2 is correct and should not be changed, i'll just shrug
> and let mandoc follow groff in this respect.

I think it likely makes sense for the `TS` macro in man(7) and mdoc(7)
to unconditionally emit a `br` request (with the normal control
character), but my judgment proceeds from a radically different premise
than yours.

The primary reason we want the `TS` macro to cause a break is because a
basic presumption of the _tbl_ formatter is that it has an "entire
output line" to work with, even if it is formatting only one of those
(as with my examples above).

I can see some *roff users racing forward with a false symmetry,
asserting that _all_ preprocessor token macros should do the same.  As
some old EE prof at Purdue reportedly had a habit of roaring in the
lecture hall when illustrating solution methods that undergrads got
themselves into trouble with:  "ALWAYS wrong!  ALWAYS stupid!"

The reasoning fails for _all_ of the other Seventh Edition Unix
preprocessors.  Here's why.

* With eqn(1), you can have "eqn regions" _that produce no output_.  A
  widely seen example is:

    .EQ
    delim $$
    .EN

  Here, you _absolutely do not want to break the line_.

* Also with eqn(1), you can't just assume that an equation will be
  displayed.  It might be inline.  A common _idiom_ is to use
  delimiters, perhaps configured as shown above, for inline equations,
  and to use macros for displayed equations.  Some full-service macro
  packages like ms(7) and mm(7) apply that idiom.  But I don't think we
  can assume that it will be the case for man(7) and mdoc(7).  Again,
  this area is unspecified by anyone, TTBOMK.  That means we cannot
  assume that the idiom is binding on the man page macro packages.

* pic(1) _could_ be used inline just fine, when typesetting.

  But it appears that GNU _pic_ assumes that a picture will, like a
  _tbl_ table, have the whole output line to play around in.

  Exhibit:

    $ cat ATTIC/inline.roff
    .sp 1i
    We depict our node list as
    .PS
    circle rad 0.1i;
    arrow right;
    circle rad 0.1i;
    arrow right;
    polygon up 0.1i then right 0.1i then right 0.1i down 0.1i \
     then down 0.1i then left 0.2i filled 0.5;
    .PE
    at which point it terminates.

  Image attached.

  I expect one could get around this by formatting the picture in a
  diversion and then interpolating the diversion, but that seems
  tedious.  I wonder about a GNU _pic_ extension supporting inline
  pictures.  But if you overset the line, that's _your_ problem.

  Just an idea.  No idea of UI/syntax yet.  Maybe a third argument to
  the `PS` macro?  Another pic language keyword?  Both?  Maybe it's not
  worth the trouble; maybe masters of _pic_ are also masters of
  diversion usage.

* With refer(1), the whole point is to set the citations _inline_, until
  dumping out any "accumulated" references as a list in end notes or
  back matter.

> I originally found this regression on July 24, 2025, but never
> found the time to properly report it.
> 
> I'm reporting it now because i need to touch the code that deals
> with empty tables in mandoc anyway (in the context of adjacent
> bugfixes), so deciding now what the desired behaviour is would be
> welcome.

I've made my pitch above.

> P.S.
> I managed to build 1.25.0rc2 after fighting with the groff build
> system for a few hours.  The worst problem is this:
> 
> It appears that the dependency on soelim somehow causes the command
> list for each of the files listed in $(GROFF_MAN_PAGES_ALL) to become
> empty and the ".man:" inference rule to no longer take effect,
> thus killing the build because the *.1 files never get built
> and then the targets needing them fail.
> I did not yet manage to figure out what exactly goes wrong,
> mostly because the groff Makefile is so wordy and so full of
> indirections that it's very hard to debug.

Well, it's generated by Automake.  To see what we actually work on as
developers, consult "doc/doc.am".

...but that's pretty cold comfort, as it's the single most complicated
Automake script we have by a wide margin.

> In the end, i gave up for now and worked around the problem in an
> extremely hackish way without understanding the root cause.
> 
> I'm not planning to do systematic testing of 1.25 at this time -
> but i obviously had to check whether the 1.23 regression is
> still present in 1.25.0rc2 before reporting, which it is.
> 
> P.P.S.
> Regarding Savannah:
> At 12:57:42, trying to open a new ticket via the "Bugs >> Submit New"
> menu entry timed out after 80 seconds.
> I checked with tcpdump(8) that my browser sent several SYN packets to
> Savannah, never receiving any SYN packat back, before giving up.
> 
> I also tried searching for existing tickets using the query form.
> After several tries, that finally worked, but even then, getting
> responses to these request typically took around 20-40 seconds.

It might be faster to use the mailing list search feature applied to the
bug-groff list.

I have no more fruitful advice; sometimes Savannah gets so borked by the
bots that it kills my own work on groff for a day.  The problem is not
fundamentally technological, but economic and social.

We will not be freed of the effects of negative externalities until the
tech oligarchs are dragged through the streets of Seville in chains.

Regards,
Branden

[1] https://lists.gnu.org/archive/html/groff/2026-02/msg00067.html

Attachment: signature.asc
Description: PGP signature

Reply via email to