Follow-up Comment #17, bug #67372 (group groff):

You are saying there is no regression because only undefined
behaviour changed, and the mandoc(1) test suite is over-testing.

So, the first question is whether \w\*v is indeed undefined.
I believe the main place where to look for an answer is:

https://www.gnu.org/software/groff/manual/groff.html.node/Using-Escape-Sequenc
es.html

Citing selectively,

  Whereas requests must occur on control lines, escape sequences
  can occur intermixed with text and may appear in arguments
  to requests, macros, and other escape sequences.
  [...] Escape sequence interpolation is of higher precedence
  than escape sequence argument interpretation.  This rule affords
  flexibility in using escape sequences to construct parameters
  to other escape sequences.

Admittedly, this is not completely conclusive, so the judge must
interpret it resorting to legislative intent, or precedent,
or analogy, or common sense.  Legislative intent seems to
contrast requests, which can only be invoked in one very particular
place, to escape sequences, which can be invoked (almost?) anywhere.
Formally, it may be possible to interpret a long list that, on
first sight, seems all-encompassing, in particular when it does
not even allude to a single restriction, as "this is intended
as an exhaustive enumeration, nothing else is allowed" - but that
doesn't seem particularly compelling.  Precedent is unambigous
from the dawn of time to groff-1.22.4.

Several examples also support the idea that the first sentence is
not intended as exhaustive.

For example:

* .ds s B
   .\*s bold text
   invokes the B macro, printing bold text

* .\*sR bold text
   invokes the BR macro, printing only bold in bold

* .R\*s text bold
   invokes the RB macro, printing only bold in bold

* .ds t bold text
   .RB \*t
   passes *two* arguments, printing only bold in bold

* .ds t ld te
   .BR bo\*txt
   passes *two* arguments, printing only bold in bold

   Now arguably, the wording "may appear in arguments"
   might include escape sequences contributing to multiple
   arguments - though the more natural interpretation of
   that wording would be "may appear in all arguments"
   (i.e. any argument may invoke escape sequences.)

Even if you argue that the first sentence *is* exhaustive
and you are free to break all the above examples (and more),
the question remains open whether "argument interpretation"
includes argument delimiter interpretation - i would maybe
argue that it does.  At least, that is supported by examples
like the following:

* .ds s [B]
   \f\*stext

* .ds s (CB
   \f\*stext
   Both print the text in bold.

This section 5.6.4 mentions none of the terms "interpolation depth",
"nesting depth", or "input level", nor could i find any definition
of these terms anywhere (by grepping over all of groff git master).
Unless i'm missing something, they are only mentioned in passing
in obscure corners of the documentation (mostly about compatibility
with historic implementations) without ever properly defining them
and without ever specifying what their effect is, which leads me
to consider them implementation details that the user should not
have to worry about.

I admit that the original idea behind "interpolation depth"
looks interesting, i.e. getting \w'\*s' to work for arbitrary s,
including s containing single quotes, but it appears it was never
really thought through nor designed consistently, let alone
implemented consistently.

It *may* be possible to define and implement it in a consistent
manner as follows:

 1. If an escape sequence function character that (optionally or
    mandatorily) takes a delimited argument is immediately followed
    by a valid delimiter that does not result from interpolation,
    than any instances of the delimiter resulting from interpolation
    while parsing the argument do not end the argument.
 2. If an escape sequence function character that (optionally or
    mandatorily) takes a delimited argument is immediately
    followed by the beginning of another escape sequence,
    rule 1 does not apply.

That would possibly provide the intended benefit for \w'\*v'
without breaking \w\*v.  I'm not completely sure given how
complicated the logic is (and since how it is actually intended
to work is undocumented).  Also, i'm not convinced exposing the
user to such complicated logic is ideal, in particular since
this is only one (relatively minor) instance typical for
interpreted languages that support macros (notable and notorious
example, sh(1)) and certainly for roff(7).  The roff(7) language
contains more severe instances of the same class of problems.
For example, you can define a macro that starts are macro definition
without ending it, then call it and end the macro definition in the
surrounding code.  And given how much roff(7) revolves around
macro interpolation, i'm sure there is more.

For now, i'm *not* planning to commit my revert patch to groff,
mostly because a revert is adequate when there is consensus that
there is a regression, but there is no such consensus.
Besides, i don't currently have a working port of groff from git,
and i remember from the last time that i tried to build one, it
was extremely difficult to get it to build at all, and i neither
want to get distracted right now from working on 1.23 nor commit
anything without proper testing.  Repeatedly getting distracted
with git-master during the last two years was one contributing
factor to the intolerable delay dealing with 1.23, so not
getting near git-master is part of my (at this point, close to
desparate) strategy for finally getting 1.23 out of the door.

So i'll temporarily use my revert patch in the OpenBSD port -
not because i'm convinced that is the proper long-term solution,
but as an interim stopgap until we develop a consensus what
the intended behaviour actually is.  Once groff grows sane and
consistent behaviour, i'm not opposed to changing mandoc(1)
yet again.

One remark regarding over-testing.  You are right that over-testing
can be a real problem.  For example, that is the reason why the
mandoc(1) testsuite does not do any -T ps tests just yet:
i simply couldn't figure out any way so far how to avoid that
all PostScript tests would contain more over-testing than
intentional testing.

But testing only documented features is (sadly) not an option
for groff-mandoc compatibility testing, for multiple reasons.

 1. Even though groff documentation is significantly better than
    lots of other software documentation (that was already true
    during wl@ times), and has continued to improve over time, in
    particular during the last couple of years, it does still have
    its gaps and ambiguities, as this very ticket demonstrates.
    When documentation is less than perfect, testing for some
    undocumented features is unavoidable.

 2. Manual page authors are generally not known for diligently
    reading groff documentation before writing or maintaining
    manual pages.  Even the authors of the vast majority of
    man(7) code generators are not known for that - probably
    with the exception of the author(s) of pod2man(1), which
    quite reliably produces decent code.

    But even a generally exceptionally diligent and prolific manual
    page author as jmc@ has told me "if what i write doesn't work
    as i hoped, i simply tweak it until it does"; he only (partially)
    changed that stance and relied a bit more on mdoc(7) and roff(7)
    documentation some time after the advent of mandoc.

    Most authors of man(7) code generators clearly do the same.
    The end result is that not only documented behaviour
    matters, but it can easily happen that manual pages rely
    on undocumented behaviour.

 3. Mandoc(1) does not only aim for compatibilty with groff
    documentation, but for compatibility with groff output,
    aka bug-for-bug compatibility.  That requires some testing
    of undocumented features.

 4. While groff(1) documentation is good, it is not complete
    and detailed enough for guiding a reimplementation.
    When developing mandoc(1), i almost always have to run
    groff to test how it behaves before i can select algorithms
    for use in mandoc.  Once that is done, the test suite has
    to make sure mandoc(1) remains compatible.

 5. The test suite is primarily a mandoc(1) test suite, that is,
    its main purpose is to make sure that mandoc(1) output does
    not accidentally change, not even in cases where groff
    behaviour is undocumented.  Consequently, the test suite aims
    to exercise all code paths in mandoc(1) and all possible
    combinations of input tokens related to the feature being
    tested, with no regard to which combinations are documented.
    While test suite completeness is hard to define and hard to
    achieve, it is a worthy goal and should not be confused
    with overtesting.

When the test suite fails on the mandoc side, you generally
don't hear about it, i simply fix it myself.  When it fails on
the groff side, i try to classify it.  The reason may be:

 a) A groff regression that must be fixed in the groff port
    and reported upstream.
 b) A minor groff behaviour change that doesn't matter much
    either way and that mandoc(1) can simply follow.
 c) A bug fix in groff that mandoc(1) should follow.
 d) A feature improvement in groff that mandoc(1) should follow.

I don't think adding the following class would make much sense:

 e) Change in undefined behaviour, just delete the test.

In mandoc(1), i definitely don't want accidental output changes
even for invalid input.  Even for invalid input, i always want
to make sure that the new output makes more sense than the old
output.  I think aiming for that would make sense in groff, too.
I don't think the commit that caused this regression (or behaviour
change, if you want - but given that the behaviour change was
accidental rather than intentional, the term "regression" seems
fitting to me, no matter whether the behaviour is defined or not)
did not meet that standard.  I do not see how it made the output
or the diagnostics better.  Rather, both degraded - the output
lost text present in the input file, and the new warning message was
quite confusing and did not help the user in diagnosing the problem.

I find it quite surprising that the root cause for this fallout
turned out to be "a jjc@ feature that still isn't properly
documented nor unambiguously designed nor consistently implemented".
Had you asked me, i would hardly have thought that issues of
this kind still exist in groff.  Really surprising for groff
to still suffer from what can essentially be described as
a "paedriatic disease".  This regression now looks like the
runny nose and the rash that unavoidably comes with such a
childhood illness.



    _______________________________________________________

Reply to this item at:

  <https://savannah.gnu.org/bugs/?67372>

_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/

Attachment: signature.asc
Description: PGP signature

Reply via email to