groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] new .cp register; was: Possible regression with `groff -C`


From: G. Branden Robinson
Subject: [PATCH] new .cp register; was: Possible regression with `groff -C`
Date: Tue, 14 Apr 2020 11:46:18 +1000
User-agent: NeoMutt/20180716

Hi, John!

First, let me address your lingering point.

At 2020-04-12T13:34:04+1000, John Gardner wrote:
> Wouldn't it be simpler to inline the contents of unicode.tmac? Only
> two other macro packages reference it, and the file is arguably short
> enough not to violate any DRY principles:
> 
> λ GNU-Groff (master): grep -rnw ./tmac -e unicode.tmac
> ./tmac/html.tmac:546:.mso unicode.tmac
> ./tmac/tmac.am:62:  tmac/unicode.tmac \
> ./tmac/tty.tmac:72:.  mso unicode.tmac
> ./tmac/unicode.tmac:1:.\" unicode.tmac
> 
> unicode.tmac has only 3 lines of (relevant) source code:
> 
> .char - \[hy]
> .char ` \[oq]
> .char ' \[cq]

We could do that.  I suspect the idea was that unicode.tmac might grow
in the future, causing increasing affront to the DRY principle.

However, I think doing so simply papers over a deeper and more insidious
issue, where groff file nesting, compatibility mode, and the historical
legacy of AT&T troff's two-character register namespace (because that's
all you'll ever need :-| ).

I've snipped my original plan because it did not survive contact with
the enemy.  What I ended up with was a small change to the parser to
support a new register.  I decided to document my justification in
groff_diff(7); here it is.

***

The register \n[.cp] is specialized and may require a statement of
rationale.  When writing your own macro packages or documents that use
groff features and will be sourced by others with the .so request, you
may desire correct operation regardless of compatibility mode in the
surrounding context.  It may occur to you to save the existing value of
\n(.C into a temporary register, say, _C, at the beginning of your
file, turn compatibility mode off with .cp 0, then restore it from that
register at the end with the .cp request.  At the same time, a modular
design may lead you to multiple layers of inclusion.  You cannot use
the same register name everywhere or you risk “clobbering” the value
from an outer scope.  The two‐character register namespace of AT&T
troff is confining and mnemonically difficult; you may wish to use
groff's more capacious namespace.  However, attempting
             .nr _my_saved_C \n(.C
will not work in compatibility mode; the register name is too long.
“This is exactly what .do is for,” you think.
             .do nr _my_saved_C \n(.C
The foregoing will always save zero to your register, because .do turns
compatibility mode off.  It will not serve to have .do report the saved
compatibility mode in \n(.C for this special case, because the request
can do anything (except change compatibility mode in its enclosing
scope), including call macros and source files, and the value of \n(.C
must be reliable there.  What you need is:
             .do nr _my_saved_C \n[.cp]
             .cp 0
at the beginning of your file, followed by
             .cp _my_saved_C
at the end.

***

What remains to be done for this changeset:

* Port the documentation over to an appropriate place in the Texinfo
  manual.

To be done in a subsequent changeset:

* Change all the man pages and macro files that manipulate compatibilty
  mode to use the technique described.

See attached patch for the details.

What do you think?

Thank you for writing that regression test!  This was quite the
adventure.

Regards,
Branden

Attachment: new_dot-cp_register.diff
Description: Text Data

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]