wiley-logo-sm.gif
> wiley.com

UNIX SHELL PROGRAMMING, Fourth Edition

Appendix Y - Nroff and Troff

Documentation is one of the major features of UNIX. Major word-processing and desktop publishing packages such as Word Perfect, Interleaf, and Framemakers are now available on UNIX machines. Since these software tools are not part of UNIX, we'll focus on the documenation facilities that come with UNIX and how the Shell can aid their use.

In any bureaucracy, paperwork increases as you spend
more and more time reporting on the less and less you are doing.

In 1975, long before word processing and desktop publishing were performed by personal computers, there lived two commands, nroff and troff, that could do virtually everthing that modern packages could do. Nroff formats documentation for the existing ocean of dot-matrix and letter-quality printer; troff formats documents for PostScript laser printers and phototypesetters. Using nroff and troff can be made much easier by the use of Shell. The major documentation commands are shown in Table Y.1. Because of the number of commands and terminals that work with these two commands, it is often confusing to get all of the commands put together to generate the correct output. Shell helps eliminate those problems.
Otherwise, formatting documents with nroff would be as simple as
   nroff document_file
Usually, however, it takes many parameters and a few input and output filters to format a document correctly. The most frequently used paramenters invokes a macro package.


Table Y.1
Documentation Commands

Command
Description

checkeq
check a document's usage of equation macros

checkmm
check a document's usage of mm macros

col
processs reverse line feeds

cw
prepare constant-width text for troff

deroff
remove nroff/troff macros

diffmk
mark differences in two versions of a documents

eqn
equation preprocessor for troff

gath
gather files

greek
prepare output for special terminals

lp
spool output to printers (System V)

lpr
spool output to printers (Berkeley)

man
format UNIX manual pages

mm
format documents using memorandum macros

mmt
typeset documents, viewgraphs, and slides

negn
equation preprocessor for nroff

nroff
format documents for ASCII terminals

ptx
generate permuted index

spell
check spelling of documents

tbl
table preprocessor

troff
format documents for a phototypesetter

MACRO PACKAGES

There are a number of macro packages designed to handle most documentation problems. These packages are contained in /usr/lib/tmac and /usr/lib/macros. The most common ones are the memorandum macros (mm or csh:ms) and manual page macros (man). The available macro packages are shown in Table Y.2. Typically, a separate Shell command is necessary to invoke each different macro package:

        
  nroff -mm document     csh: nroff -ms document
  nroff -man manpage
To speed up loading of the macros and to improve efficiency, use the compacted macros - a "compliled" version of the macros:
  nroff -cm document     nroff -cs document
  nroff -can manpage
Documentation problems that couldn't be solved easily with these macro packages required special preprocessors to prepare the input files for nroff. Commands were developed to handle tables and equations.


Table Y.2
Documentation Macro Libraries

Macros
Description

man
manual page macros

mm
memorandum macros

mosd
operations systems deliverable documentation macros

mptx
permuted index macros

ms
manuscript macros (Berkeley)

mv
manuscript and slide macros

mv
viewgraph and slide macros

cm
complied memorandum macros

INPUT FILTERS

The commands that preprocess nroff files are equ, tbl, and gath. Equ processes equations for mathematical output. Tbl creates the nroff macros needed to format tables. And gath, which normally works with the remote job entry (RJE) facility, can be used to set keywords, include files, or execute commands and use their output as input to nroff or troff. Each of these commands expands the capability of nroff for text formatting.

Equ

Equ preprocesses mathematical equations for troff. Its twin, nequ, processes equation for nroff. They are useful for serious scientist, but hold little value for the average user. They are invoked as input filters to nroff or troff:
  equ files | troff
  nequ files | nroff
For the average documentation user, tbl and gath hold more interest.

Tbl

Tbl takes files of the form shown in Figure Y.1 and turns then into usable input for nroff. The resulting output from the following command is also shown in the figure.
  tbl document | nroff
To build a command to accurately format all documents regardless of content takes planning. On any system, tbl is a hog. It is more efficient to check the file for tables than it is to use tbl on all documents. We could use grep to check the file:

                       .TS
                       center tab(:)
                       lccc
                       lnnn
                       Sales.January:February:March
			
                       -   
                       Southwest:100:110:120
                       Northwest:230:150:170
                       .TE
Sales January   February March   April  
Southwest 100
110
  120
Northwest 230
150
  170

Cover

ISBN 0471168947

Wiley Computer Publishing
Timely. Practical. Reliable.

Figure Y.1 Documentation Example Using tbl Macros


  # get the names of any files that have tables
  if [ -z `grep -1"^.TS" $* | line` ]
  then 
   nroff -cm $*        # no tables in the file
  else 
   tbl $* | nroff -cm  # process tables and format files
  fi
The grep takes less time than running tbl on every file. It also keeps the user from forgetting to invoke the table preprocessor when required. Both of these advantages make the cost of searching each file for tables an inexpensive proposition.

Gath

Gath gathers information together just like the send command, but it doesn't send the information over the RJE. Instead, it puts the output on stdout. Gath can preprocess text to prompt for keywords, include files, and execute commands. Keywords are useful when the document doesn't change, but certain keys phrases do:

  ~=:FIRST
  ~=:LAST 
  ~=:ADDRESS 
  ~=:CITYSTZIP
  .nf
  FIRST LAST
  ADDRESS
  CITYSTZIP
  .sp
  Dear FIRST, 
  .sp
  .fi 
  . . . letter 

gath letter |nroff -cm
FIRST=Jay LAST=Arthur ADDRESS=123 Anystreet CITYSTZIP=Anytown, AZ 12345
Gath will prompt for each keyword, as previously shown, and then substitute them for all occurrences. The keywords can also be supplied on the command line:

  FIRST=Jay LAST=Arthur ADDRESS="123 Anystreet"\
  CITYSTZIP="Anytown, AZ 12345" gath letter | nroff -cm
Gath can also include files in the text:
  text. . .
  ~filename
  text. . .
Gath will include filename at that point in the text. But gath can also execute commands. In the following example, gath retrieves a file room from SCCS and runs it through tbl before inserting the text in the file:
  text
  ~!get -ps.tablefile | tbl
  text
Gath can even include the output from specific commands such as Is:
  text
  ~!cd;ls -1
  text
These are trivial examples, but they illustrate the potential for preprocessing nroff and troff input to allow for more robust documentation. The presence of gath commands can also be detected with grep:
  grep -n"^~"$*
In cases where both gath and tbl are required as input filters, execute gath before tbl to ensure that all tables are included with the text before invoking tbl.
  gath $* | tbl | nroff -cm   
Once the input has been processed correctly, nroff or troff must be brought into play to format the resulting text in a way that is suitable for the output device.

TERMINAL PREVIEWING OF DOCUMENTS

Because UNIX uses mainly asynchronous communications (except for rare implementations of synchronous support), there are innumerable types of terminals that can be used with UNIX. Video display terminals vary from so-called dumb terminals to workstations. Hardcopy output devices range from dot-matrix and letter-quality printers up through laser printers. These are all available to UNIX and connected as shown in Figure Y.2.

Figure Y.2 Printing Options

Because of the variety of output devices, nroff and troff use numerous parameters to control their output (see Table Y.3). Nroff and troff also extract a heavy toll from the system when they format a document. In most active UNIX systems, nroff and the screen editors will consume most of the



Table Y.3
Nroff and Troff Formatting Options

Option
Descriptions

Nroff and Troff

-i
read standard input

-nn
number first page as n

-o
print requested pages

-q
use input.output mode of .rd request

rAn
set register A to n

-sn
stop every n pages

-z
print messages generated by .tm requests

-cm
include compacted macro library m

-km
compact the macros and store in the current directory

-mn
include macro library m

Nroff Only

-e
invoke proportional spacing

-h
use tabs to speed output

-lname
format output for terminal type name

-un
set emboldening factor to n


systems's resources. All too often, when a user enters an nroff command, he or she will forget to enter all of the parameters needed. So they try again and again to get everything "right" for their terminal. In the process, they eat up huge chunks of system resources.

To circumvent this resources drain, it is usually wise to develop Shell commands to handle nroff or troff with each terminal type.

Video Display Terminals(VDTs)

VDT's come in two screen width - 80 and 132 characters. To have nroff format the output correctly for comfortable viewing, the width and offset options must be set as follows:

   nroff -r00 -rW79 document
   nroff -r00 -rW131 document
Why are the line widths one less than the maximum length? At the end of each line printed by nroff are a carriage return (CR) and a line feed (LF). Most VDTs have what is called a wraparound feature-when a long line is not truncated at the edge of the screen, a line feed is automatically generated and the remainder of the line prints on the next line on the screen. If a line is 80 characters long, a CR would generate a wraparound LF AND the LF following would leave a blank line on the screen. Line widths of 79 and 131 seem to work best. Since what people see on the screen should not differ from ultimately prints on a printer, these width options should be used for all printer output as well.

Emboldening - making text appear darker - possible with nroff and troff. Nroff emboldens text by overstriking each character as many as four times. There are several ways to embolden text:


  nroff    mm         nroff
  .bd      .B text    \fBtext\fR
  text
The result of using nroff on the following emboldened text is a series of characters and backspaces:
  \fBuser\fR
  u<u<u<us<s<s<se<e<e<er<r<r<r
Since most VDTs switch into enhanced print via a control character sequence, all of these backspaces and extra characters are unnecessary and require longer transmission times. Unless the administrators have developed an output filter to handle these special situations, suppress them by using the -u option to eliminate emboldening:
  nroff -cm -u -rW79 -rOO document
This helps speed up the transmission of the formatted document. Most other adjustment to the output are handled with output filters.

Printers

This type of printer can be specified with the -T parameter when printing directly on a given printer (i.e., when not using lp or lpr):

   nroff-cm-T630-rW79-rO8 document
This command specifies that the out is a Diablo printer (-T630) and states that the output is to offset eight spaces to the right (-rO8).
Local line printers can receive output by I/O redirection of the nroff output into a device name or a spooler:

  nroff -cm -rW79 -rO8 document>/dev/lp
  sh:  nroff -cm -rW79 -rO8 document | lp 
  csh:  nroff -cm -rW79 -rO8 document | lpr
  nroff -cm -rW79 -rO8 document | opr

OUTPUT FILTERS

The most common output filters for nroff are col,pr, sed,and uniq. All four are useful with VDTs. Col is also useful with some printers.
Col removes reverse line motions that are used to handle underlining, superscripts, and subscripts. VDTs and a few line printers cannot handle reverse line motions, so col is used to convert reverse line motions into single-line combinations of backspaces and characters. Col removes super- and subscripts from norff's output. The output of any nroff command for a VDT should be run through col:

 
  nroff -cm -rO8 rW79 document | col
The ouput of nroff can be further optimized for screens by use of filters. The most obvious one is uniq, which suppresses duplicate lines. Duplicates are most often blank lines at end of a page. At 1200 baud, a short last page can zip off the screen before the user can read it. To eliminate all but one occurrence of each blank line, use uniq:
 
  nroff -cm document | col | sed -e "s/\b.//: | uniq
Another way to handle the problem is to present only 24 lines at a time and then allow the user to request more information with pr, pg, or more:
  nroff -cm document | col | sed -e "s/\ b.//" | pr -124 -t -p
  nroff -cm document | col | sed -e "s/\b.//" | pg 
  nroff -cm document | col | sed -e "s/\ b.//" | more
Pr, pg, or more will sound the terminal bell and the user can hit return to view each new section of a formatted document.

PUTTING IT ALL TOGETHER

Customizing document output for a particular terminal can be handled with a variety of input and output filters. The command line for each terminal type looks like this:
 
input filters | nroff [macros] [parameters] | output filters
Putting all of these filters together requries changes to /etc/profile and the creation of a new command that we call output. First, /etc/profile should ask for the terminal type and assign it to the variable TERM:
 
  echo "Enter Terminal Type:"
  read TERM
  case $TERM in
     vt100|5420|tv970)
        tabs
        ;;
     lp|620|630|laser)
        ;;
     ti|700|745)
        tabs
        ;;
     *)
        echo "Setting up default terminal"
        ;;
  esac
Users will be prompted for this information when they log in. The output command can then use $TERM to make intelligent default choices for nroff. It should check for tables, equations, and commands for gath. Next, is should invoke output filters for the terminal type:

 

[ Home ] [ Appendix X - The Shell Filter Builder ] [ Appendix Y - Nroff and Troff ] [ Appendix Y - Nroff and Troff - continued ] [ Appendix Z - Regular Expressions ]