5.38.2 Compatibility Mode

Long identifier names may be GNU troff’s most obvious innovation. AT&T troff interprets ‘.dsabcd’ as defining a string ‘ab’ with contents ‘cd’. Normally, GNU troff interprets this as a call of a macro named dsabcd. AT&T troff also interprets ‘\*[’ and ‘\n[’ as an interpolation of a string or register, respectively, named ‘[’. In GNU troff, however, the ‘[’ is normally interpreted as delimiting a long name. In compatibility mode, GNU troff interprets names in the traditional way; they thus can be two characters long at most.

Request: .cp [n]
Register: \n[.C]

If n is missing or non-zero, turn on compatibility mode; otherwise, turn it off.

The read-only register .C is 1 if compatibility mode is on, 0 otherwise.

Compatibility mode can be also turned on with the -C command-line option.

Request: .do name
Register: \n[.cp]

The do request interprets the string, request, diversion, or macro name (along with any further arguments) with compatibility mode disabled. Compatibility mode is restored (only if it was active) when the expansion of name is interpreted; that is, the restored compatibility state applies to the contents of the macro, string, or diversion name as well as data read from files or pipes if name is any of the so, soquiet, mso, msoquiet, or pso requests.

The following example illustrates several aspects of do behavior.

.de mac1
FOO
..
.de1 mac2
groff
.mac1
..
.de mac3
compatibility
.mac1
..
.de ma
\\$1
..
.cp 1
.do mac1
.do mac2 \" mac2, defined with .de1, calls "mac1"
.do mac3 \" mac3 calls "ma" with argument "c1"
.do mac3 \[ti] \" groff syntax accepted in .do arguments
    ⇒ FOO groff FOO compatibility c1 ~

The read-only register .cp, meaningful only when dereferenced from a do request, is 1 if compatibility mode was on when the do request was encountered, and 0 if it was not. This register is specialized and may require a statement of rationale.

When writing macro packages or documents that use GNU troff features and which may be mixed with other packages or documents that do not—common scenarios include serial processing of man pages or use of the so or mso requests—you may desire correct operation regardless of compatibility mode enablement in the surrounding context. It may occur to you to save the existing value of ‘\n(.C’ into a 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 ‘.cp \n(_C’. At the same time, a modular design of a document or macro package may lead you to multiple layers of inclusion. You cannot use the same register name everywhere lest you “clobber” the value from a preceding or enclosing context. The two-character register name space of AT&T troff is confining and mnemonically challenging; you may wish to use the more capacious name space of GNU troff. 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 while it interprets its argument list.

To robustly save compatibility mode before switching it off, use

.do nr _my_saved_C \n[.cp]
.cp 0

at the beginning of your file, followed by

.cp \n[_my_saved_C]
.do rr _my_saved_C

at the end. As in the C language, we all have to share one big name space, so choose a register name that is unlikely to collide with other uses.

Normally, GNU troff preserves the interpolation depth in delimited arguments, but not in compatibility mode.

.ds xx '
\w'abc\*(xxdef'
    ⇒ 168 (normal mode on a terminal device)
    ⇒ 72def' (compatibility mode on a terminal device)

Furthermore, the escape sequences \f, \H, \m, \M, \R, \s, and \S are transparent for the purpose of recognizing a control character at the beginning of a line only in compatibility mode. For example, this code produces bold output in both cases, but the text differs.

.de xx
Hello!
..
\fB.xx\fP
    ⇒ .xx (normal mode)
    ⇒ Hello! (compatibility mode)

Normally, the syntax form \sn accepts only a single character (a digit) for n, consistently with other forms that originated in AT&T troff, like \*, \$, \f, \g, \k, \n, and \z. In compatibility mode only, a non-zero n must be in the range 4–39. Legacy documents relying upon this quirk of parsing120 should be migrated to another \s form.