ul — translate underlining and other Teletype Model 37 effects


ul [-i] [-t terminal] [file...]


The ul utility reads the named files (or standard input if none are given) and translates various control sequences as found on model 37 Teletypes (TTY-37) to control sequences for the terminal in use, writing the translated results to its standard output. Such input is generated, for examples, by the original nroff(1) utility, or by the GNU groff(1) utility (if instructed with its -P-c option to run grotty(1) in TTY-37 mode, rather than the normal ECMA-48 mode).

The terminal in use is specified by the environment variable TERM. If the TERM environment variable is unset and ul is invoked with the name "cul" and its standard output is not a terminal, it chooses the terminal type lpr.

Input control sequences

A subset of the model 37 Teletype control sequences is understood:

  • The CR (carriage return) control character resets the output position to the first column.

  • The LF (line feed) control character advances to a new line.

  • The TAB (horizontal tab) character advances to the next column that is a multiple of 8. It does not cease advancing at the right margin, and can cause a line wrap. TAB is non-destructive, in line with the effect on an actual TTY-37 of overstriking with a space; it does not change characters to blanks.

  • The BS (backspace) control character moves the output position back by one column, until it hits the left margin. It does not auto-wrap back onto previous lines, and it is non-destructive as on a real TTY-37.

  • Overstriking is performed by moving the current output position back over a previous character position and outputting another printable character. This can be done with the CR (carriage return) or BS (backspace) control characters. Multiple backspace characters can be used to move the current output position back more than one position.

    If an underscore character (_) overstrikes another character, or another character overstrikes an underscore, this signifies that the (non-underscore) character is to be underlined.

    If a character is overstruck with itself, this signifies that the character is to be boldfaced. An underscore overstruck with itself signifies underlining, not boldface.

    Any other overstriking ignores the second character and retains the character originally in the output position.

  • The SI (shift in) and SO (shift out) control characters denote switching to and from reverse video mode.

  • The ESC 7 sequence instructs a full reverse linefeed.

  • The ESC 8 sequence (half reverse linefeed) switches to superscript mode, or performs a full reverse linefeed if used twice.

  • The ESC 9 sequence (half forward linefeed) switches to subscript mode, or performs a full forward linefeed if used twice.

Unknown sequences beginning with ESC (escape) cause ul to abort with an error message. Other zero-width characters, including the C0 and C1 control characters, are ignored and have no effect. There is an automatic right margin at column 512.

Some of these effects are also understood by more(1) and less(1); although those two implement overstrike slightly differently, and in a more restricted way, to how ul does.

Output translation

The termcap(5) database is used to determine the appropriate control sequences to output. If there is no entry for the current terminal, a dumb terminal is assumed that has the os capability.

If the terminal has the os capability, ul uses overstriking for underline and boldface, using cursor motions to print characters on top of already printed characters. It also uses overstriking for underline if there is no capability for underline (or standout) mode at all nor any underline last character (uc) capability, and the terminal has the ul capability. If there is no capability for underline or standout mode, but there is the uc capability, it is used for underlining. Full reverse and forward linefeeds use up and down cursor motions.


  • Boldface uses the terminal's md capability, falling back if that is not present to the mr capability or then the so capability. (i.e. Boldface is rendered as boldface, or reverse video, or standout.)

  • Underline uses the terminal's us and ue capabilities, falling back to its so and se capabilities. (i.e. Underline is rendered as true underline, or standout.)

  • Reverse video uses the terminal's mr capability, falling back if that is not present to the so capability. (i.e. Reverse video is rendered as true reverse video, or standout.)

  • Superscript uses the terminal's mh and us capabilities, with the latter falling back if not present as per underline. (i.e. Superscript is rendered as dim underlined, or dim standout.)

  • Subscript uses the terminal's mh capability, falling back if that is not present to the so capability. (i.e. Subscript is rendered as dim or standout.)

Differences from a real Teletype Model 37

ul is geared towards the outputs of nroff(1), groff(1), and their ilk, which differ from strictly accurate TTY-37 semantics. It understands the multibyte encoding of the current locale and operates internally in terms of the C library's wide characters. It also has a carriage width of 512 columns.

A real Teletype Model 37 only understands 7-bit input and is only 80 columns wide. Similarly, a real TTY-37 has no reverse video and SI and SO (shift in and out) would denote switching between two trays of type. The half-line motions are true feed motions that cause overprinting of the top/bottom halves of other lines.


The following options are available:


Instead of using terminal control sequences, TTY-37 effects are indicated by a separate line containing marker characters for the various effects. This is useful when you want to look at the effects that are present in an nroff(1) output stream on a CRT-terminal. The marker characters are:










reverse video


combined modes (see BUGS)

-t terminal

Overrides the terminal type specified in the environment with terminal.


The LANG, LC_ALL, LC_CTYPE and TERM environment variables affect the execution of ul as described in environ(7).

Exit Status

The ul utility exits 0 on success, and >0 if an error occurs.

See also

  • colcrt(1)

  • man(1)

  • nroff(1)

  • ascii(7)


Bill Joy wrote a iul(6) (indicate underline) command in 1BSD, as a standalone version of the :indicateul command in ex(1). This behaved like ul -i except that it did not understand ESC control sequences, shift in/out, or overstriking for boldface. It had a 500-column carriage width, an automatic right-hand margin, and discarded the second character when overstriking as ul does.

The ul command appeared in 2.9BSD and was written by Mary Ann Horton (known as Mark Horton at the time). 2.9BSD also contained a related greek(8) command.


Attempts to combine multiple modes are not rendered properly. ul simply punts to using the terminal's standout mode if two or more TTY-37 effects are combined.

groff(1) in TTY-37 mode uses various overstriking effects that ul does not implement but that a real TTY-37 would. For example, groff generates the bullet points in this very manual page as a plus sign (+) overstruck by a lower case letter O (o) with the intention of producing a crossed circle. less(1) and more(1) do not handle this overstriking either, and display only the last character struck, in this case the o. ul displays only the first character struck, the +.

The g marker for reverse video has an obscure derivation as "graphics" or "greek", as those are what shift in and shift out generally mean with an actual TTY-37. The second tray of type usually contained greek letters or a set of graphics characters.

Double superscript is not output properly anywhere other than the beginning of a line.

-i does not work well with forward and reverse linefeeds.

The handling of FF (form feed) incorrectly assumes that it means form feed on the current terminal also. This is not the case for common DEC VT terminals and terminal emulators, where FF is a line index. FF should translate to the cl termcap capability.

The handling of width greater than 1 characters in the last column can cause buffer overflow.


Jonathan de Boyne Pollard