URL: <https://savannah.gnu.org/bugs/?68133>
Summary: nail down semantics of character translations
involving non-characters
Group: GNU roff
Submitter: gbranden
Submitted: Mon 09 Mar 2026 12:05:07 AM UTC
Category: Core
Severity: 3 - Normal
Item Group: None
Status: None
Privacy: Public
Assigned to: None
Open/Closed: Open
Discussion Lock: Unlocked
Planned Release: None
_______________________________________________________
Follow-up Comments:
-------------------------------------------------------
Date: Mon 09 Mar 2026 12:05:07 AM UTC By: G. Branden Robinson <gbranden>
Item Group unknown at this time.
In 1991,
[https://cgit.git.savannah.gnu.org/cgit/groff.git/tree/troff/input.c?h=1.04#n4265
James Clark called character translations a "really bizarre troff feature",]
and I agree.
* Are translations to space escape sequences like \| and \^ permitted?
* The foregoing two are permitted to be defined as glyphs in a font in
Kernighan's device-independent _troff_ (though at the moment I cannot spot
this provision in CSTR #54 1992). But what about the other fixed-width space
escape sequences, \space and \0?
* What about _groff_'s "stretchable" space escape sequence, \~? (See bug
#65829.)
* Are translations to _parameterized_ space escape sequences (such as \h'1i')
permitted?
* Are translations _from_ any of the foregoing to ordinary, spacing, or
indexed characters permitted?
* Are translations from one kind of space escape sequence to another
permitted?
Existing implementations are inconsistent. (However, DWB 3.3 and Plan 9 from
User Space _troff_s appear to be consistent with each other.)
$ cat ATTIC/stupid-tr-tricks.roff
.nf
.tr !\|
abc!def
.tr #\^
ghi#jkl
.tr $\
mno$pqr
.tr %\0
stu%vwx
.if \n(.g \{\
.tr &\~
yz_&abc
.\}
.tr +\h'1i'
def+ghi
.tr !!##$$%%&&++
.tr \|!
def\|ghi
.tr \^#
jkl\^mno
.tr \ $
pqr\ stu
.tr \0%
vwx\0yz_
.if \n(.g \{\
.tr \~&
ABC\~DEF
.\}
.tr \h'1i'+
GHI\h'1i'JKL
$ dwb nroff ATTIC/stupid-tr-tricks.roff | cat -s
abc def
ghi jkl
mnopqr
stu%vwx
def+ghi
defghi
jklmno
pqr$stu
vwx yz_
GHI JKL
$ 9 nroff ATTIC/stupid-tr-tricks.roff | cat -s
abc def
ghi jkl
mnopqr
stu%vwx
def+ghi
defghi
jklmno
pqr$stu
vwx yz_
GHI JKL
$ heirloom nroff ATTIC/stupid-tr-tricks.roff | cat -s
abc\def
ghi\jkl
mnopqr
stu\vwx
def\g'i
defg'i
jklmno
pqr$stu
vwx yz_
GHI JKL
$ ~/groff-1.22.3/bin/nroff ATTIC/stupid-tr-tricks.roff | cat -s
ATTIC/stupid-tr-tricks.roff:2: normal or special character expected (got a
horizontal space)
ATTIC/stupid-tr-tricks.roff:4: normal or special character expected (got a
horizontal space)
ATTIC/stupid-tr-tricks.roff:6: normal or special character expected (got `\
')
ATTIC/stupid-tr-tricks.roff:8: normal or special character expected (got a
horizontal space)
ATTIC/stupid-tr-tricks.roff:14: normal or special character expected (got a
horizontal space)
ATTIC/stupid-tr-tricks.roff:17: normal or special character expected (got a
horizontal space)
ATTIC/stupid-tr-tricks.roff:19: normal or special character expected (got a
horizontal space)
ATTIC/stupid-tr-tricks.roff:21: normal or special character expected (got `\
')
ATTIC/stupid-tr-tricks.roff:23: normal or special character expected (got a
horizontal space)
ATTIC/stupid-tr-tricks.roff:26: normal or special character expected (got
`\~')
ATTIC/stupid-tr-tricks.roff:29: normal or special character expected (got a
horizontal space)
abc!def
ghi#jkl
mno$pqr
stu%vwx
yz_ abc
def+ghi
defghi
jklmno
pqr stu
vwx yz_
ABC DEF
GHI JKL
$ ~/groff-1.22.4/bin/nroff ATTIC/stupid-tr-tricks.roff | cat -s
troff: ATTIC/stupid-tr-tricks.roff:2: normal or special character expected
(got a horizontal space)
troff: ATTIC/stupid-tr-tricks.roff:4: normal or special character expected
(got a horizontal space)
troff: ATTIC/stupid-tr-tricks.roff:6: normal or special character expected
(got '\ ')
troff: ATTIC/stupid-tr-tricks.roff:8: normal or special character expected
(got a horizontal space)
troff: ATTIC/stupid-tr-tricks.roff:14: normal or special character expected
(got a horizontal space)
troff: ATTIC/stupid-tr-tricks.roff:17: normal or special character expected
(got a horizontal space)
troff: ATTIC/stupid-tr-tricks.roff:19: normal or special character expected
(got a horizontal space)
troff: ATTIC/stupid-tr-tricks.roff:21: normal or special character expected
(got '\ ')
troff: ATTIC/stupid-tr-tricks.roff:23: normal or special character expected
(got a horizontal space)
troff: ATTIC/stupid-tr-tricks.roff:26: normal or special character expected
(got '\~')
troff: ATTIC/stupid-tr-tricks.roff:29: normal or special character expected
(got a horizontal space)
abc!def
ghi#jkl
mno$pqr
stu%vwx
yz_ abc
def+ghi
defghi
jklmno
pqr stu
vwx yz_
ABC DEF
GHI JKL
$ ~/groff-1.23.0/bin/nroff ATTIC/stupid-tr-tricks.roff | cat -s
troff:ATTIC/stupid-tr-tricks.roff:2: error: expected ordinary or special
character, got a horizontal motion
troff:ATTIC/stupid-tr-tricks.roff:4: error: expected ordinary or special
character, got a horizontal motion
troff:ATTIC/stupid-tr-tricks.roff:6: error: expected ordinary or special
character, got an escaped ' '
troff:ATTIC/stupid-tr-tricks.roff:8: error: expected ordinary or special
character, got a horizontal motion
troff:ATTIC/stupid-tr-tricks.roff:14: error: expected ordinary or special
character, got a horizontal motion
troff:ATTIC/stupid-tr-tricks.roff:17: error: expected ordinary or special
character, got a horizontal motion
troff:ATTIC/stupid-tr-tricks.roff:19: error: expected ordinary or special
character, got a horizontal motion
troff:ATTIC/stupid-tr-tricks.roff:21: error: expected ordinary or special
character, got an escaped ' '
troff:ATTIC/stupid-tr-tricks.roff:23: error: expected ordinary or special
character, got a horizontal motion
troff:ATTIC/stupid-tr-tricks.roff:26: error: expected ordinary or special
character, got an escaped '~'
troff:ATTIC/stupid-tr-tricks.roff:29: error: expected ordinary or special
character, got a horizontal motion
abc!def
ghi#jkl
mno$pqr
stu%vwx
yz_ abc
def+ghi
defghi
jklmno
pqr stu
vwx yz_
ABC DEF
GHI JKL
_groff_ 1.24.0 aborts on this input with an assertion failure (bug #68132),
but once I've commented that out I expect it to behave as _groff_ 1.23.0.
At present, I propose to **BAN ALL THIS CRAP** by default (someone light the
John Gardner bat-signal), and exile to compatibility mode only that which is
required to support rendering of historical documents.
Character translations are for _translating_ *_characters_*.
If you want to _redefine_ characters, _groff_ has various `char` requests for
that.
(Also I want to make character translations a property of the environment; see
bug #62691.)
(And I didn't even cover the `.tr ~` "feature", a stupid trick along an
orthogonal axis...)
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?68133>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
signature.asc
Description: PGP signature
