% -*-LaTeX-*- % DVIDRIVER.LTX.314, 13-Apr-87 15:50:11, Edit by BEEBE % Reduce from 12pt Version 2.0 to 11pt Version 2.07 \documentstyle[titlepage,11pt,twoside,texindex,dvidriver]{article} % Bug report rewards ($0.64 each): % dispchar.h section -- ``previous'' --> ``later'' (John Wilkes, HP labs) % initglob.h section -- ``Allow'' --> ``although'' (John Wilkes, HP labs) % dvijet.c section -- no such ``enhanced'' LaserJet (John Wilkes, HP labs) \title{A \protect\TeX{} DVI Driver Family} \author{Nelson H.F. Beebe\\ Center for Scientific Computation\\ 220 South Physics Building\\ University of Utah\\ Salt Lake City, UT 84112\\ USA\\ \medskip Tel: (801) 581-5254\\ \medskip EMAIL: Beebe@Science.Utah.Edu (Internet) } % Previous editions: % 26 March 1986 --- Revision 2.0 \date{15 April 1987 --- Revision 2.07} \makeindex \begin{document} \sloppy % because of lots of file names here \pagenumbering{roman} \maketitle \tableofcontents % \listoftables % \listoffigures \newpage \pagenumbering{arabic} \pagestyle{headings} % !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \makeatletter % \renewcommand{\@oddfoot}{{\rm Draft \hfil Draft \hfil Draft}} % \renewcommand{\@evenfoot}{{\rm Draft \hfil Draft \hfil Draft}} \renewcommand{\@oddfoot}{{\rm 13 April 1987 \hfil Version 2.07}} \renewcommand{\@evenfoot}{{\rm Version 2.07 \hfil 13 April 1987}} \makeatother % !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \section{Introduction} This document describes a family of driver programs which translate the \TeX{} device-independent (DVI) output file to a device-specific file for a particular output device, such as a dot matrix printer, a laser printer, a CRT display, or a phototypesetter. These programs grew out of a DVI driver for the \BG{} terminal% \footnote{\INDEX{footnotes}{footnotes}% This fine terminal, which is almost unique in having support for variable sized downloaded fonts, is no longer made by BBN. It has been licensed by BBN to \X{EastMark, Inc.} (240 Smith Street, Lowell, MA 01851, Tel: (617)\-453-9150), who have improved the documentation and packaging and sell it as the \X{GTR01} model. Unit list price is about \$2950 (spring 1986). The screen resolution is $1024 \times 780$ in a portrait orientation nicely matching the printed page. } developed by Mark Senn \INDEX{senn, mark}{Senn, Mark} at Purdue University. This was further worked on at the University of Washington by Stephen Bechtolsheim,\INDEX{Bechtolsheim, Stephen}{Bechtolsheim, Stephen} Bob Brown,\INDEX{Brown, Bob}{Brown, Bob} Richard Furuta,\INDEX{Furuta, Richard}{Furuta, Richard} Jim Schaad,\INDEX{Schaad, Jim}{Schaad, Jim} and Robert Wells,\INDEX{Wells, Robert}{Wells, Robert} with contributions for \POSTSCRIPT{} devices by Neal Holtz \INDEX{Holtz, Neal}{Holtz, Neal} at Carleton University. Simon Barnes \INDEX{Barnes, Simon}{Barnes, Simon} of Schlumberger Cambridge Research Ltd., and Robin Rohlicek \INDEX{Rohlicek, Robin}{Rohlicek, Robin} at BBN provided useful additions to the \BG{} driver which have been generalized and incorporated in Version 2.07. In the winter of 1986/87, John Sauter \INDEX{Sauter, John}{Sauter, John} adapted one of the dot matrix drivers to produce \CN{dvil75} for the DEC LA75 printer. Lon Willett \INDEX{Willett, Lon}{Willett, Lon} at Utah adapted a laser printer driver to produce \CN{dviimp} for the \IMAGEN{} laser printer family. The transformation to about ten other device drivers, plus the massive code rearrangement for many new features as well as easy identification of host- and device-dependent sections, was carried out at the University of Utah by the present author. The code has undergone such extensive modification that there remains little in common with the original version, which no doubt has spawned other families of drivers at various institutions. What makes this driver family unique is the author's commitment to its support on a wide variety of host architectures and operating systems, and to {\em its remaining entirely in the public domain\/}. Recipients are encouraged to install it, use it, improve, and in the spirit of the \N{Emacs} community, return the improvements to this author for further distribution. Don Knuth,\INDEX{Knuth, Donald}{Knuth, Donald} Leslie Lamport,\INDEX{Lamport, Leslie}{Lamport, Leslie} and Mike Spivak\INDEX{Spivak, Michael}{Spivak, Michael} have given us \TeX{} and \MF, \LaTeX{}, and \AmSTeX{}, which are enormous contributions to the world of typesetting, and we should emulate them in giving away our own work. Many of us work at universities and to a large extent are supported by public educational funding; we owe them something back. Someone who commercializes \INDEX{commercialization policy}{commercialization policy} these DVI drivers is on his own; I shall continue to give the family away to anyone who asks for it. In January 1986 the availability of the family was announced on the \CN{TeXHaX} bulletin board, and repeated again in the March 1987 issue of the \TeX{} Users Group \INDEX{TeX Users Group}{\TeX{} Users Group} newsletter, \X{TUGBoat}. In the first two months after the announcement, about 60 copies were shipped by mail, and based on file \X{reference count}s, a roughly equal number of Internet \X{ANONYMOUS FTP}\INDEX{FTP}{FTP} retrievals were done from sites unknown. An electronic mailing \INDEX{electronic mail}{electronic mail} list is maintained to inform recipients of changes and updates. \section{The DVI Driver Software} \TeX{} is written in a subset of \X{ISO Standard \string\PASCAL{}} which was chosen both to enhance its portability, and to facilitate translations to other languages. For example, it avoids nested procedures, and use of enumeration variables. This author is aware of at least five% \footnote{\INDEX{footnotes}{footnotes}% (1) old \TeX{}78 port to 16-bit workstation; (2) D.R. Fuchs' Micro\TeX{} (available from Addison-Wesley); \INDEX{Fuchs, David}{Fuchs, David} (3) N. Naugle and T. Rokicki at Texas A\&M; \INDEX{Naugle, Norman}{Naugle, Norman} \INDEX{Rokicki, Tom}{Rokicki, Tom} (4) P. Monardo's Common \TeX{} at UC Berkeley; \INDEX{Monardo, Pat}{Monardo, Pat} (5) Per Bergsten at Chalmers Institute of Technology, G\"{o}teborg, Sweden. \INDEX{Bergsten, Per}{Bergsten, Per} } translations of \TeX{} to \C{}, and one of \MF{} to \N{Tal} and another to \N{Fortran}. The \TeX{} software system is actually written in the \WEB{} language, and translated into a \PASCAL{} program by \TANGLE{} and into a \TeX{} document by \WEAVE{}. \WEB{} supports change files which contain local modifications to the source code, so that all sites can work off a common master source file. Despite its many fine features which support the development of reliable and correct software, regrettably, \PASCAL{} is completely unsuited for the writing of DVI driver programs. The two serious omissions in this area are the lack of bit operations, and random-access I/O. The former are critical for efficient support of low-cost dot matrix printers, and the latter for efficient access to the many files which the driver requires. Niklaus Wirth's\INDEX{Wirth, Niklaus}{Wirth, Niklaus} second popular language, \N{Modula-2}, remedies both these problems, but is not yet widely-enough available, and lacks a standard I/O library. Because of its strong similarity to \PASCAL{}, it should not be difficult to prepare a version of the \WEB{} system to support it. \N{Ada} would also be a good possibility, but compilers again are either not available, or too expensive in many environments. Since \TeX{} now runs on many different computer systems, including the \IBMPC{} and the \MAC{}, there is a need for DVI driver programs which can be used on all of them. There is really only one language choice, and that is the \C{} language originally developed at Bell Laboratories for the support of the \UNIX{} operating system. It is even more widely available than \PASCAL{}, and it contains the necessary support for bit operations, random I/O, and hands-on access to files without having the operating system throwing in extra garbage which ruins them. Because \C{} is a ``low-level'' high-level language, it is close to common computer architectures, and in most implementations, compiles into reasonably efficient machine code, provided some care is taken at the source level. The major weaknesses of \C{} are its general lack of type and bounds checking, and its lax syntax which allows programming errors to be accepted as legal code. Two particularly noxious examples of the syntax problems are illustrated by the following program fragments: \begin{verbatim} for (k = 1; k <= n; ++k); foo(k); /* foo is called once */ for (k = 1; k <= n; ++k) foo(k); /* foo is called n times */ \end{verbatim} The indentation here implies to the reader that \CF{foo} is controlled by the \CN{for} loop. \begin{verbatim} if (avar = bvar); /* this sets avar */ foo(); /* foo is called once */ if (avar = bvar) /* this sets avar */ foo(); /* foo is called if bvar is non-zero */ if (avar == bvar); /* this leaves avar intact */ foo(); /* foo is called once */ if (avar == bvar) foo(); /* foo is called if avar equals bvar */ \end{verbatim} The indentation again implies that \CF{foo} is controlled by the \CN{if} statement. You must look closely to spot the tiny differences which give the very different effects noted in the comments. Although the coming ANSI \C{} Standard extends the language to support type checking of function arguments, arrays carry no bounds information unless the programmer arranges to create composite data types or pass dimension variables, and the majority of the standard library routines that have array or pointer arguments simply assume that adequate space is available when they are stored into. Two versions of \WEB{} in C have been reported in \X{TUGBoat}, % \footnote{\INDEX{footnotes}{footnotes}% Klaus Guntermann and Joachim Schrod, {\em WEB Adapted to C}, TUGBoat {\bf 7}, {No. 3}, 134--137 (1986). }% $^,$% \footnote{\INDEX{footnotes}{footnotes}% Silvio Levy, {\em WEB Adapted to C, Another Approach\/}, TUGBoat {\bf 8}, {No. 1}, 12--13 (1987). }% but I have not had an opportunity yet to obtain either of them. The extensive variable and code section cross-referencing provided automatically by \WEB{} are exceedingly useful features, and good grounds for Don Knuth's \INDEX{Knuth, Donald}{Knuth, Donald} calling \WEB{} programming {\em literate programming\/}.% \footnote{\INDEX{footnotes}{footnotes}% {\em Computer Journal\/}, {\bf 27}, 97-111 (1984) \INDEX{Computer Journal}{\string\em\space Computer Journal\/} } Without these cross-references, we have to make do with string search utilities like the \UNIX{} \CN{grep} program. Fortunately, the \C{} preprocessor provides most of the facilities that \WEB{} change files do. The fact that all versions exist inside the source code encapsulated by \CNNX{\#if}\INDEX{#if}{\CNNX{\#if}} \ldots \CNNX{\#endif}\INDEX{#endif}{\CNNX{\#endif}} sequences is both an advantage and a disadvantage. One source file has all implementations contained in it, but it is rarely possible for an implementor to completely test all versions when modifications are made to the version-specific sections. Nevertheless, the use of \C{} for this driver family has proved quite satisfactory, and development work on the \DEC{} \TOPS{} operating system is supported by the availability of Richard Stallman's\INDEX{Stallman, Richard}{Stallman, Richard} wonderful \N{Emacs} from MIT, and many of the most useful \UNIX{} utilities implemented with the portable \C{} compiler and library, \PCC{}, ported to \TOPS{} by Jay Lepreau,\INDEX{Lepreau, Jay}{Lepreau, Jay} at the University of Utah. In February, 1987, I installed the \KCC{} compiler which is under active maintenance and development at SRI-NIC, and the driver family has been implemented with it as well. It has proved to be a fine compiler, and is being updated to conform to the draft ANSI \C{} Standard. \section{Outline of the DVI Drivers} The DVI drivers follow to some extent David Fuch's \INDEX{Fuchs, David}{Fuchs, David} \CN{dvitype} program, which defines the standard DVI file format and how to process it. In simple terms, the DVI file is a sequential 8-bit byte command stream produced by \TeX{} as it processes a document, and consists mostly of compactly-encoded commands to move to a specific page position and typeset a character there. It is further embellished with version numbers, page pointers, checksums, font names, magic numbers to identify the file as a DVI file, and the like. The DVI driver must be able to read this file, processing all, or user-selected, pages, and produce an output file in a device-specific format which can produce typeset pages on some particular device. Although the output is device-specific, much of the processing done by the DVI driver is concerned with interpreting user run time command options, decoding the DVI commands, finding font files, and extracting character bitmaps from them. All of this part of the drivers is common across devices, and accounts for quite substantial code sharing. Each driver consists of a single \C{} source file, \FN{dvixxx.c}, where \FN{xxx} is a mnemonic abbreviation of the device, such as \FN{alw} for \ALW{}. This file contains \C{} preprocessor \CNNX{\#include}\INDEX{#include}{\CNNX{\#include}} directives to obtain a standard header file, \FN{dvihead.h}, which in turn \CNNX{\#include}'s\INDEX{#include}{\CNNX{\#include}} a header file, \FN{machdefs.h}, containing machine constants, and another, \FN{typedefs.h}, containing type definitions. Originally, \FN{dvihead.h} also contained the definitive revision history of the driver family in its extensive initial comments. This practice has been discontinued, and the \X{maintenance history} is now stored in a separate file, \FN{00revhst.txt}. This avoids unnecessary recompilations when the \UNIX{} \CN{make} utility is used to manage the software. \C{} has only a limited number of primitive data types, but it does have \CN{struct} and \CN{typedef} statements permitting the creation of new data types. These do not particularly enhance the type checking possibilities, at least not until the coming ANSI \C{} Standard has been widely implemented, but they do inform the compiler of storage requirements, which permits efficient code generation. This is of particular importance on the segmented memory architectures of the \N{Intel iAPX} microprocessor family used in the \IBMPC{} and clones, because there is an enormous execution-time penalty for processing objects bigger than the base architecture easily supports. Two examples of these are the need for subroutine calls to perform 32-bit integer arithmetic, and around 30 instructions to compute the address of an element in a vector larger than 64 Kbytes in extent, compared to one instruction when the vector is smaller than that size. Many compilers for these architectures have provided no support whatever for addressing objects larger than one segment. Objects in the DVI file consist of one-, two-, and four-byte integers, both signed and unsigned, and character strings. It is important to identify the exact space requirements of these to obtain an efficient implementation. Consequently, \FN{typedefs.h} defines new types called \CN{BOOLEAN}, \CN{BYTE}, \CN{COORDINATE}, \CN{INT8}, \CN{INT16}, \CN{INT32}, \CN{UNSIGN16}, \CN{UNSIGN32}, and \CN{void}. The \CN{void} type is available only in some \C{} implementations, although it will be in the ANSI \C{} Standard; it is used to signify the absence of a value, particularly for function values which are discarded. All \C{} procedures are in fact functions which may or may not return a value. A common programming error is to return inconsistent values from inside a function, or to return a value from one part, and none from another. One of the sloppy habits of many \C{} programmers is to ignore a returned function value, particularly with library procedures, most of which return error indicators of some sort when they cannot return a valid pointer or primitive value. The type cast \CNNX{(void)}\INDEX{void}{\CNNX{(void)}} in front of a function call then tells both the compiler and the reader that the function may in fact be returning something, but the result is intentionally being discarded. The \CN{COORDINATE} type is used for device coordinates (usually dots or pixels), and it is defined because the precision required may depend on the output device and on the size of the available integer types provided by the compiler. \C{} is quite permissive about type conversion by assignment; almost any object can be assigned to another and the compiler will accept it and generate code for it. One of the commonest misuses of this feature is the assignment of pointers to integers, and vice versa. While this may be reasonable on some architectures, there is no good reason to assume that both are interchangeable. Indeed, on \X{segmented memory} architectures, such as the widely-used \N{Intel iAPX} family mentioned earlier, this is definitely not the case. An integer may be a 16-bit quantity, while a pointer may be a composite 32-bit (or larger) value made up of segment number, memory offset in the segment, access rights, and type information. Another common error is the passing of integers of different sizes through the same argument of a function. On the \N{PDP-11} and \VAX{} architectures where \C{} was first implemented, this may work, but it definitely does not on the \N{Intel} and \N{Motorola} processors. Consequently, in the DVI driver family, extensive use is made of type casts in assignments, expressions, and function arguments. Null pointers are always cast as such; they are {\em never\/} assumed to be zero.% \footnote{\INDEX{footnotes}{footnotes}% If you find such an instance, it is a bug, so please inform me of it so it can be fixed. } After \FN{machdefs.h}, the next file included by \FN{dvixxx.c} is \FN{main.h}, which is the function \CF{main} required to prepare an executable \C{} program. It immediately includes all the standard system header files which are required for use of system library functions, plus four additional header files, \FN{commands.h}, \FN{gblprocs.h}, \FN{gblvars.h}, and \FN{gendefs.h}. For drivers for interactive displays, it will also include \FN{keydef.h}. \FN{commands.h} defines mnemonics for the commands in the DVI file, such as \CN{BOP} ({\em Beginning Of Page}), \CN{SET_RULE}, \CN{FNT_DEF1} ({\em Font Definition}), and so on. \FN{gendefs.h} is a catch-all for general \X{macro definitions} and assorted constants. \FN{gblprocs.h} defines all of the global functions. With the availability of a compiler anticipating the coming ANSI Standard, the \MICROSOFT{} Versions 3.0 and 4.0 compilers on the \IBMPC{}, this file has been revised so that the data types of arguments are defined; this was not previously possible in \C{}. The alternate declaration forms are selected under control of the preprocessor symbol \CN{ANSI}, which is set in \FN{machdefs.h}. \FN{gblvars.h} defines all the scalars, vectors, arrays, and structures which must be known globally. \INDEX{global data}{global data} These are analogous to \CN{EXTERNAL} variables in languages like \N{PL/1}. They represent one of the weakest areas in \C{}, in that no control exists over which functions reference or modify them; the packages of \N{Modula-2} and \N{Ada} were introduced specifically to deal with this problem. The names of these global variables reside in a single name space, so it is important that they be chosen carefully so as to be unlikely choices for local variables inside a function. Otherwise, an omitted type declaration in the function will use the global variable, producing a hard-to-find side effect (a fashionable word for {\em bug\/}). \FN{keydef.h} contains flag definitions and function declarations for the \X{keyboard input} package, \FN{keybrd.c}. There are presently about 70 files with extension \FN{.h}, and 9 have now been presented. The others are functions, most of which are required by all the drivers. By inclusion of all 5 of the standard top-level header files at the beginning of each of the remaining ones, they could be turned into separately-compiled functions. However, since several of them contain operating-system or device-dependent code sections delimited by preprocessor directives, extreme care would be required in building executable versions of the drivers to avoid inclusion of object files compiled with the wrong code segments selected. We have found it more reliable to use the \CNNX{\#include}\INDEX{#include}{\CNNX{\#include}} directive to insert each of these functions into the \FN{dvixxx.c} modules so that a only a single file need be presented to the compiler and linker. The recompilation time has so far not proved to be objectionable,% \footnote{\INDEX{footnotes}{footnotes}% 7 to 10 minutes on a standard \IBMPC{} \N{XT} (4.77MHz 8088 CPU) with the \MICROSOFT{} Version 3 \C{} compiler, and under two minutes on mainframes. } while the possibly more economic alternative of separate compilation would be exceedingly likely to cause problems. To summarize then, here is the general structure of the file nesting: \begin{verbatim} dvixxx.c --> dvihead.h --> machdefs.h --> typedefs.h --> main.h --> commands.h --> gendefs.h --> gblprocs.h --> gblvars.h --> keydef.h --> other function .h files \end{verbatim} \INDEX{nesting of files}{nesting of files} There is {\em no\/} further nesting of files than this. Each of the functions may call other ones, but the \FN{.h} files do not include any additional program text. In some of the function files, preprocessor directives select minor variations in code. When significant differences would be required, then \FN{dvixxx.c} does not use the \CNNX{\#include}\INDEX{#include}{\CNNX{\#include}} mechanism, but instead has a private version of the function embedded in itself. All functions following \CF{main} are in \X{alphabetical order}, and are readily identifiable on the terminal screen or in a program listing by a standard function header. \section{The Grubby Details} We shall now descend into subsections to discuss each of these header files separately. Like their invocations in \FN{dvixxx.c}, these too will be given in alphabetical order. Since \C{} permits letter case distinctions, many of the names were historically chosen to be in mixed case for readability (e.g. \CF{AbortRun} instead of \CF{abortrun} or \CF{abort_run}). This proved to be a nuisance as the code has been moved from machine to machine, so I have applied the \UNIX{} \CN{sed} utility to replace all mixed-case names with lower-case ones. For portability, function names must be unique in the first six characters, and file names in the first eight, so all function names have been shortened to eight or fewer characters. \INDEX{naming conventions}{naming conventions} \subsection{\protect\FN{abortrun.h}} \CF{abortrun} is called to terminate the DVI driver execution, both normally, and in the event of errors. It closes any open files, issues an error message if called with a non-zero completion code, and then returns to the operating system with the normal \CF{exit} call. \subsection{\protect\FN{actfact.h}} \CF{actfact} takes a font magnification factor and adjusts it to match the nearest one in an internal table of standard \TeX{} \X{font magnification}s. That way, a user request for, say, magnification 1094, will get adjusted to the expected value, 1095. Correct adjustments to an integer value are critical, because font files contain this value as part of their names or directory path. \subsection{\protect\FN{alldone.h}} \CF{alldone} is the routine called for normal termination. It closes any error \X{log file} and copies it to \CN{stderr}, tells the user if a log file was created, and then calls \CF{abortrun} to finish the job. \subsection{\protect\FN{bitmap.h}} This file is included by all the \FN{dvixxx.c} files which create page bitmaps in memory for dot-matrix printers. It defines macros and functions for accessing the bitmap; this is necessitated by the constraints of \X{segmented memory} on the \N{Intel iAPX} architecture. \subsection{\protect\FN{bopact.h}} \CF{bopact} is called from \CF{prtpage} to handle beginning-of-page action for interactive displays. For \CN{dvibit}, it writes the command and status window. \subsection{\protect\FN{chargf.h}} The functions \CF{chargf}, \CF{charpk}, and \CF{charpxl} are called from \CF{readfont}, as well as from \CF{setchar} in \FN{dvibit.c}, and \CF{loadchar} in \FN{dvialw.c}, \FN{dvican.c}, \FN{dviimp.c}, and \FN{dvijep.c}. They have the job of extracting the raster description, and possibly, character metrics, of a single character from the corresponding \FN{.gf}, \FN{.pk}, or \FN{.pxl} font file, and decoding it to produce a simple bitmap which can be easily painted into the page bitmap by \CF{dispchar}, or formatted for downloading to a more intelligent output device, such as the \BG{}, \POSTSCRIPT{} printers, and the \HPLJ{} \N{Plus}. For most devices, the character bitmap is quite small, and there would be no difficulty in storing the full bitmap. However, printers of much higher resolution are likely to become available over the next few years, while host computer memories will probably not increase substantially. For example, a 10pt character at 2400 dots/inch would require about 8 Kbytes for the entire image, but fewer than 25 bytes for a single row. A 72pt character, such as in the {\em aminch\/} font, would need about 430 Kbytes for the image, but only about 200 bytes for a row. Since all three font formats store character bitmaps in row order, it seemed expedient to have \CF{chargf}, \CF{charpk}, and \CF{charpxl} build up the character description a row at a time, calling another routine, \CF{outrow}, each time a row is completed. They then require no knowledge of what is to be done with the character bitmap, and no duplication of code for this is necessary, since it can be entirely hidden in \CF{outrow}. The \FN{.gf} font file format produced by the new \MF{} is reasonably complex, sharing much in design with \FN{.dvi} files. Instead of being stored as a full bitmap, with each row rounded up to a multiple of 32 bits to achieve word alignment on 32-bit hosts, as they are in a \FN{.pxl} file, character bitmaps in a \FN{.gf} file are stored in a run-length encoded \INDEX{run-length encoding}{run-length encoding} form with counts of white and black pixels in each row, and commands to skip repeated white rows. This gives a compression of only a few percent for normal size characters, but \FN{.gf} font files for very large characters may be up to 30\% smaller than the corresponding \FN{.pxl} files. The \FN{.pxl} file format has a 2K-byte directory at the end containing all necessary character metrics, plus pointers to their raster descriptions which are scattered throughout the file. This means that a relatively small block of data is all that is initially required from the file, and random access can be later used to retrieve needed character bitmaps. The \FN{.gf} file also has a directory at the end, but it contains only character escapements and widths, plus pointers to encoded character packets which are scattered throughout the file. The escapements and widths are required for updating coordinates when a character is set, but the offsets of the character bitmap from the character reference point, which are required in clipping decisions when a character is to be set, are stored in the character packets. Their availability is desirable, because off-page characters need never be set. This deficiency is unfortunate, because to retrieve them, it is necessary to read through the entire font file, causing unnecessary file page mapping. For many fonts used in a typical \TeX{} document, only a very few of the 128 possible characters in the file will ever be used, so this design flaw in the \FN{.gf} file format could in the worst case almost double the amount of font file input, compared to use of \FN{.pxl} files. Although it would be possible to carry a flag for each character indicating whether or not the offsets were available, I decided not to do so, because this would be needed only for one of the three font file formats. The code in \CF{chargf} follows that in \CN{GFtoPXL} fairly closely, although some duplication of code fragments was permitted to avoid the \CN{goto} statements present in the latter. Most of the approximately 340 lines of code in \CF{chargf} are part of a large \CN{switch} statement inside a loop, dispatching on the value of the next input byte. \subsection{\protect\FN{charpk.h}} As discussed in the preceding section, \CF{charpk} is called to handle the retrieval and decoding of the raster description of a single character from the \FN{.pk} form of a font file. The \FN{.pk} font file format was defined by Tom Rokicki, \INDEX{Rokicki, Tom}{Rokicki, Tom} formerly at Texas A\&M University, now at Stanford University. He has provided support programs \CN{GFtoPK}, \CN{PKtoPX}, and \CN{PXtoPK} for converting between the various font file formats. Combined with the Stanford \TeX{} Project's \CN{GFtoPXL}, only \CN{PXLtoGF} or \CN{PKtoGF} yet need to be written to allow going from any one of the three font file formats to the other. The \FN{.pk} format is even more complex than the \FN{.gf} format. Instead of \X{run-length encoding} character bitmaps by rows, it first recognizes repeated rows,% \footnote{\INDEX{footnotes}{footnotes}% About 37\% of the bitmap rows in the standard fonts required by \FN{plain.tex} are repeated! } then treats the remaining bitmap as a single bitstring to be run-length compressed. In addition, run-length counts are based on 4-bit nybbles, rather than 8-bit bytes. For the standard fonts, the \FN{.pk} files occupy slightly less than half the disk space of the \FN{.gf} files. This will clearly be of importance on small machines, particularly personal computers. The \FN{.pk} font file lacks a character directory, so to retrieve character metrics, the entire font file must be mapped in from disk. Each character is contained in a single packet, beginning with its number and metrics, and followed by its packed raster encoding. A stored packet length allows skipping over the rasters on the first pass by \CF{readpk} as the metrics are collected. The code in \CF{charpk} follows that in \CN{PKtoPX} fairly closely, although some duplication of code fragments was permitted to avoid the \CN{goto} statements present in the latter. There are approximately 350 lines of code in \CF{charpk}, but the processing is more complex than that required in \CF{chargf}. Consequently, the file \FN{charpk.h} departs from the convention of one function per file, and it contains three private functions, \CF{get_bit}, \CF{get_nybble}, and \CF{pk_packed_num}, plus several private globals known only within this file. For historical reasons, the \C{} data type \CN{static} \INDEX{private modules}{private modules} when used for objects declared outside a function body, really means {\em private to this file\/}, and we therefore have introduced a preprocessor symbol \CN{PRIVATE} for this purpose. A \CN{typedef} cannot be used, because \CN{static} is a type {\em modifier\/}, not a pure data type. \subsection{\protect\FN{charpxl.h}} \CF{charpxl} is quite short---about 55 lines. It retrieves a single character bitmap from a \FN{.pxl} file, and sends each row to \CF{outrow} for processing. Since there is no raster decoding necessary, once argument checking has been done and the font file successfully positioned to read the character bitmap, only eight lines of code are needed to do the whole job. Before the support for \FN{.pk} and \FN{.gf} font files was added, this operation was performed in a half-dozen different functions. Now, it is totally isolated in this one routine. \subsection{\protect\FN{clrbmap.h}} \CF{clrbmap} has the rather simple job of clearing a bitmap array to zero for those devices, such as dot matrix printers, which actually require one. Although it is a simple loop in \C{}, it has to be done for every page, and accounts for a surprisingly large portion of the run time when the driver execution is monitored with a program counter histogramming utility. For some machines, we have prepared a more efficient \INDEX{efficiency}{efficiency} assembly language version, \CF{zerom}, which it calls instead. This can take advantage of basic hardware facilities like \X{block move} to do it as fast as the machine is capable of. For \X{segmented memory} bitmaps, where the bitmap is allocated as a vector of pointers to raster lines, rather than as one large array, special code is required to clear individual raster lines. The preprocessor symbol \CN{SEGMEM} identifies these code sections. Details can be found later in the section on \CF{getbmap}. \subsection{\protect\FN{clrrow.h}} \CF{clrrow} is called from \CF{chargf}, \CF{charpk}, and \CF{charpxl} to clear the global array \CN{img_row[]} before collection of each character bitmap row begins. Although the code is a single loop, it is required frequently enough that it warranted encapsulation in a separate function. \subsection{\protect\FN{commands.h}} This file contains symbolic definitions of all of the DVI commands which are required in the driver program. These are fixed with the freezing of \TeX{}, but no program should ever contain magic constants where symbolic names would make the code more readable. \subsection{\protect\HCF{devinit}} \CF{devinit} has the job of carrying out any startup initializations required by the output device for the processing of a single DVI file. It is called from \CF{dvifile}. For most dot-matrix printers, there is little to do, but terminals and laser printers may require considerably more. \subsection{\protect\HCF{devterm}} \CF{devterm} is called from \CF{dvifile} to perform any device termination following the processing of a single DVI file. Comments made about \CF{devinit} apply to this function as well. \subsection{\protect\FN{dispchar.h}} \CF{dispchar} has the delicate job of painting \INDEX{character painting}{character painting} the current character onto the display surface. For downloaded font devices, this job may involve little more than output of a few command bytes, once the character rasters have been sent to the device. For bitmapped devices, it is fairly tricky, since the character bitmap will rarely be aligned on a word boundary in the output bitmap, and the code must be both efficient, \INDEX{efficiency}{efficiency} since it is done several thousand times per page, and independent of the host computer word size. It is further complicated by the fact that the right shift operator in \C{} may or may not propagate a sign bit; the \CN{unsigned} integer type attribute which should suppress this propagation is not available in all compiler implementations. The preprocessor symbol \CN{ARITHRSHIFT} is used to select the appropriate code section. Although the body of this function is less than 60 lines long, it is about the most complex function in the entire driver family, and also the one likely to require the most execution time. If code optimization is worthwhile, it surely will be here. For \X{segmented memory} machines, the bitmap is allocated as a vector of pointers to raster lines, rather than as one large array. Code which accesses the bitmap must take care to not step pointers across raster lines. The \CN{BITMAP(y,x)} macro otherwise hides the bitmap addressing. Since \CF{dispchar} fills in raster line order anyway, there is no penalty for this. Further details may be found in a later section on \CF{getbmap}. \subsection{\protect\FN{dumpchar.h}} This is a debugging routine used to dump character raster representations to the \CN{stderr} file. It is not normally required or included in the drivers. \subsection{\protect\FN{dvifile.h}} \CF{dvifile} is called from \CF{main} once for each DVI file to be processed. It calls \CF{dviinit} and \CF{devinit} for initializations, \CF{readpost} to read in the DVI postamble, then loops calling \CF{prtpage} for each page to be printed, and finally calls \CF{devterm} and \CF{dviterm} for termination chores. \subsection{\protect\FN{dvihead.h}} This file is the only non-function header file included directly by the \FN{dvixxx.c} files. It is the repository of old revision and development history of the family (current history is stored \INDEX{maintenance history}{maintenance history} in \FN{00revhst.txt} instead), and does nothing more than possibly define a debug symbol, and then include \FN{machdefs.h} and \FN{typedefs.h}, plus some system header files. The rest are included in \FN{machdefs.h} and \FN{main.h}. \subsection{\protect\FN{dviinit.h}} \CF{dviinit} is called from \CF{dvifile} for the initial DVI file processing. After defining some global variables, it does a simple parse on the DVI file name specified on the command line to identify the file's directory, if any, and its name and extension. The path and name are saved in global variables, and a name for the output file is constructed. The DVI file and output file are opened, and the magic identifying bytes in the DVI file are read to make sure this is really a proper DVI file. If it is not, \CF{fatal} is called to terminate the job. Otherwise, control returns to its caller. If opening of the output and \X{log file}s fails, then the file path of the DVI file is discarded, and these files are opened in the current directory. This allows processing of DVI files which reside in directories for which the user does not have write access. \subsection{\protect\FN{dviterm.h}} \CF{dviterm} is called from \CF{dvifile} to complete processing of the current DVI file. It closes all open files and frees all dynamically-allocated font memory. \subsection{\protect\FN{eopact.h}} \CF{eopact} is called from \CF{prtpage} to handle end-of-page action on interactive displays. It currently supports only the \BG{}, but should be straightforward to adapt to new displays. It consists of a single command loop which runs as long as keyboard input is available. All input commands are processed, but the display is not updated until there is no more input. The \X{keyboard input} support package in \FN{keybrd.c} supports this. \subsection{\protect\FN{f20open.h}} This section has a little story behind it, so in case you are interested, read the next four paragraphs; otherwise, skip to the last paragraph. Most modern computer architectures are based on memory built up of 8-bit chunks, called {\em bytes\/}, which are then assembled into larger units like {\em half words\/}, {\em words\/}, {\em long words\/}, and so on. The 8-bit byte size is convenient in that it is large enough to contain both the 7-bit ASCII and ISO character sets, and the 8-bit EBCDIC, and extended ASCII and ISO sets. The \TWENTY{} architecture dates from the 1960's when word-addressed memory was common, and like the original IBM 70x and 70xx machines, its word size is 36 bits. With early BCD, \N{CDC}, and Fieldata 6-bit character sets, this was not an unreasonable size, and the fact that six such characters fit exactly into a word is still with us in \N{Fortran}'s six-character name limits and the size of external names on many operating systems. On many of these machines, character access required awkward masking and shifting operations, one exception being the \N{Univac 1100} machines which have quarter-word instructions, and therefore use 9-bit ASCII. The \TWENTY{} is unusual in that it supports any byte size from 1 to 36 bits with equal ease.% \footnote{\INDEX{footnotes}{footnotes}% At DECUS meetings, you can see folks walking around with T-shirts reading ``I don't care what they say, 36 bits are here to stay''. } Conventionally, text files are stored in 7-bit ASCII, five per word, leaving one bit left over in the low-order position of the word.% \footnote{\INDEX{footnotes}{footnotes}% That bit is normally zero; when it is not, it signifies that the word contains a line number instead of text. } When 8-bit bytes are stored, they could be packed in groups of six bytes in a word pair, as \N{Univac} does, but on the \TWENTY{}, they are generally placed in four-byte groups in the high-order 32 bits of a word, with the four low-order bits zero, where they are amenable to efficient \INDEX{efficiency}{efficiency} access with the byte instructions. Unfortunately, the standard \CF{fopen} function does not know about byte sizes; it just assumes text bytes are wanted and opens the file in 7-bit mode. The DVI file, however, has 8-bit bytes, so on the \TWENTY{}, we have this special version, \CF{f20open}, which stoops to a lower level in the I/O library to twiddle the right flags to get the open done for 8-bit bytes. Nobody outside the \TWENTY{} has to care about this routine, because the preprocessor symbol \CN{BINARYOPEN} is set automatically in \FN{machdefs.h} to either \CF{f20open} for the \TWENTY{}, or \CF{fopen} for everyone else. \subsection{\protect\FN{fatal.h}} When necessary files cannot be found or read, or the disk storage fills up, execution must be terminated. This routine writes out an error message, resets the terminal characteristics if they were changed, tells the user if a \X{log file} was created, and then calls \CF{abortrun} to terminate the job. The name of the function issuing the call to \CF{fatal} is included as part of the message. \subsection{\protect\FN{fillrect.h}} When \TeX{} sets a horizontal or vertical rule, the output device probably simulates this by drawing a black solid-filled rectangle. For typesetters, this may be an available primitive, and so needs only the output of a few command bytes. For most others, we have to actually fill in bits in the bitmap. This job is only marginally easier than the one \CF{dispchar} has to do, and many of the same comments made in that section apply here. There usually are not a great many rules to typeset in a typical document, so efficiency in \CF{fillrect} is of little concern. However, the new \X{Bezier curve} option supported by \LaTeX{} draws lots of little rules (e.g. 2 dots by 2 dots on a laser printer), so you might want to give it some attention. \INDEX{efficiency}{efficiency} When many small rules are set like this, it might be valuable to have special case code for them, particular for the dot-matrix printer drivers. Only this function needs to know if you do. \CN{dvialw}, \CN{dvican}, \CN{dviimp}, and \CN{dvijep} arrange to avoid sending rule sizes to the device when they have not changed from the last use, and this has helped to reduce the output volume considerably. For \X{segmented memory} machines, the bitmap is allocated as a vector of pointers to raster lines, rather than as one large array. Code which accesses the bitmap must take care not to step pointers across raster lines. The \CN{BITMAP(y,x)} macro otherwise hides the bitmap addressing. Since \CF{fillrect} fills in raster line order anyway, there is no penalty for this. More details about this will be found in the later section on \CF{getbmap}. \subsection{\protect\FN{findpost.h}} When \TeX{} sets a document, it does not know until it gets done where all the pages are, and what fonts are needed. Consequently, the DVI file stores this information in a postamble section which the DVI driver probably wants to make use of. Because the postamble size is clearly variable, in its last eight bytes, the DVI file has a four-byte magic number that tells the driver that \TeX{} actually finished writing the file, and a four-byte pointer to the beginning of the postamble. \CF{findpost} has the job of reading this little trailer, validating it, exiting via \CF{fatal} if it is bad, and otherwise using the random I/O positioning standardly available in \C{} to set the file pointer at the beginning of the postamble. \subsection{\protect\FN{fixpos.h}} \TeX{} works in tiny units which do not match any output device, but still let it position characters accurately for even the most exacting photo\-type\-setters. The font designer works in device units (dots or pixels), because high quality demands attention to device resolution, particularly for the common low- and medium-resolution devices such as dot matrix printers and laser printers. The font designer specifies character widths in such a way as to provide for the most pleasing juxtaposition of characters into words, and \TeX{} follows this specification precisely. The problem is, \TeX{} does not know what the output device resolution will be (remember that DVI means {\em device independent\/}), so it may ask for a character to be positioned at what will probably not be an exact device coordinate. If the driver just rounds each precise \TeX{} coordinate to the device coordinate system, the chances are that characters in a word may not be positioned relative to one another as the font designer intended. The effect of incorrect rounding can be glaringly obvious---a line of 60 asterisks followed by a line of two asterisks separated by 58 spaces set in a fixed-width font may be off by as much as one character position on a 300-dot/inch laser printer. Considerable thought has gone into this problem, and it was not until Version 2.06 of \CN{dvitype} that the folks in the \TeX{} project got it right (at least until we see an example to the contrary). \CF{fixpos} implements the algorithm directly from \CN{dvitype}. \subsection{\protect\FN{fontfile.h}} Although most of the code in the DVI drivers is completely portable across \C{} implementations, operating system features like file names obviously are not. In particular, the drivers need to be able to take a \X{font name}, like {\em cmr10\/}, and a \X{font magnification}, say 1500 (normal 10pt type on a 300-dot/inch laser printer), and from them, construct a name of the file containing the character raster descriptions. On the \TWENTY{}, this file would usually be called \FN{texfonts:\-cmr10.1500pxl}. Under \UNIX{}, it might be \FN{/usr\-/lib\-/tex\-/fonts\-/1500\-/cmr10.\-pxl}. On the \IBMPC{}, it could be \FN{d:\bs{}tex\-\bs{}fonts\-\bs{}1500\-\bs{}cmr10.\-pxl}. Three different font file formats are now supported, and \CF{fontfile} has the job of figuring out just what the file names should be, and returning a list of them. For example, it might return for {\em Computer Modern 10pt\/} the names \FN{texfonts:\-cmr10.\-300pk}, \FN{texfonts:\-cmr10.\-300gf}, and \FN{texfonts:\-cmr10.\-1500pxl}. Note that the naming convention for \FN{.gf} and \FN{.pk} files has changed from that used for \FN{.pxl} files---standard magnification is \INDEX{font magnification}{font magnification} now 200 instead of 1000. The directory paths supplied are determined by the preprocessor symbol \CN{TEXFONTS} defined in \FN{machdefs.h}. In order not to permanently bind directory paths into the compiled programs, the default directory names for these files may be overridden at run time by \CF{initglob} with values of \X{environment variable}s. \subsection{\protect\FN{fontsub.c}} Sometimes, a DVI file references fonts which are not available in the requested magnification, \INDEX{font magnification}{font magnification} or perhaps even in the entire family. Calling \CF{fatal} if this happens is hardly user-friendly---it may be that only one character in a fifty-page document belongs to this missing font. The DVI drivers therefore offer the user the possibility of providing a file of font substitutions which can be tried in turn until one is found. If none can be, then the drivers consult a built-in table% \footnote{\INDEX{footnotes}{footnotes}% This table is defined by \FN{gblvars.h}. It contains values for devices of resolution 144, 200, and 300 dots/inch; if the family is extended to higher-resolution devices, this table should be extended. } of standard magnifications \INDEX{font magnification table}{font magnification table} to find the nearest one in the requested family; surely a character from {\em cmr10\/} at 1440 magnification instead of 1500 magnification is better than none at all! If even that fails, then execution continues with the missing character metrics all assumed to be zero; with luck, this will affect only a few lines in the output. Presumably, the \FN{.tfm} file was available to \TeX {} when it created the DVI file, so \CF{fontsub} could be extended to try to obtain the information from that file instead, and perhaps recover. A second possibility would be to supply some arbitrary, but reasonable, character width, and just set blank space for the missing characters. Neither of these has yet been implemented.% \SUBINDEX{to-do list}{to-do list}{handling missing fonts} A message is issued to the \X{log file} if a substitution is made according to the requests in the substitution file, or if a neighboring magnification \INDEX{font magnification}{font magnification} was chosen in the same family, so the user can still find out it happened. The format of the \X{font substitution file}, and the mechanism for finding it, has been chosen to simplify its use. First of all, an explicit font substitution file can be specified by a driver command-line option at run time. If this is not done, then the name of the DVI file is used to construct a default name with a different extension. For example, on \UNIX{}, the DVI file \FN{/usr\-/jones\-/book\-/hornets.\-dvi} would select a substitution file \FN{/usr\-/jones\-/book\-/hornets.\-sub}. This gives a document-specific choice of substitution files. If this one is not found, then a standard name, such as \FN{texfonts.sub}, is looked for in the same directory. In our example, this would be \FN{/usr\-/jones\-/book\-/texfonts.\-sub}. This second choice is therefore a directory-specific solution. If this file is not found either, then as a last resort, \CF{fontsub} looks for a system-wide file, usually stored in the same directory \TeX{} gets its input files from. The example file would therefore be something like \FN{/usr\-/lib\-/texinputs\-/texfonts.\-sub}. The format of the substitution file is simple to prepare, and can be parsed (almost) unambiguously by the standard \C{} input routine, \CF{sscanf}. It is also operating-system independent, so that substitution files can be moved from machine to machine if necessary. Font substitution lines have the forms: \begin{verbatim} % comment oldname.oldmag -> subname.submag % comment oldname oldmag -> subname submag % comment oldname -> subname % comment \end{verbatim} The first two forms request substitution of a particular font and magnification. \INDEX{font magnification}{font magnification} The third form substitutes an entire font family; the closest available magnification to the required one will be used. Any dots in the non-comment portion will be converted to spaces, and therefore, cannot be part of a name field. Examples are: \begin{verbatim} % These provide replacements for some LaTeX invisible fonts: iamr10 1500 -> amr10 1500 % comment iamr10.1500 -> amr10.1500 % comment iamssb8 -> amssb8 % comment \end{verbatim} The first matching substitution will be selected, so magnification-specific substitutions should be given first, before family substitutions. \hyphenation{white-space} Comments are introduced by percent and continue to end-of-line, just as for \TeX{}. One whitespace character is equivalent to any amount of whitespace. Whitespace and comments are optional. Anything which follows the substitution font will be ignored, so a line like \begin{verbatim} iamr10 1500 -> amr10 1500 long live TeX! % comment \end{verbatim} will be parsed successfully. It is not {\em de rigueur\/} in computer science to accept sloppy parsing, but in this case, a simple workable solution was provided by a standard library facility, \CF{sscanf}, with one line of code to call it; doing a better job would involve at least a few hundred lines of code. \subsection{\protect\FN{gblprocs.h}} This file contains definitions of all of the functions referenced by the DVI driver family. \CF{main} includes it. For compilers which support the additional function argument type syntax of the coming ANSI \C{} Standard, it has been updated to include these declarations. They are selected by a new preprocessor symbol, \CN{ANSI}, defined in \FN{machdefs.h}, in order to preserve compatibility with existing compilers. \subsection{\protect\FN{gblvars.h}} This file contains definitions of all the global scalars, vectors, arrays, and structures required by the drivers. This is also where the \X{font magnification} table used by \CF{fontsub} is defined. \subsection{\protect\FN{gendefs.h}} This file is included by \FN{main.h} and serves to collect assorted macro and constant definitions. It should normally not require modification on any new host computer. \subsection{\protect\FN{getbmap.h}} Some output devices require the construction of a bitmap containing the page image. Originally, the bitmap was simply statically allocated as a single global array. However, the \INDEX{segmented memory}{segmented memory} segmented memories of the \N{Intel iAPX} microprocessors pose a problem, because the bitmap is almost always larger than one memory segment. If all compilers supported accessing of objects larger than one segment, this problem could be ignored at the expense of efficiency \INDEX{efficiency}{efficiency} (recall that a large array indexing operation takes about 30 iAPX instructions). None of the four \C{} compilers I have tried permit compile-time allocation of objects larger than one segment. Three of them provide alternate memory allocation library functions which can be used at run time to create large objects, but unfortunately, \MICROSOFT{} Version 3.0 permits {\em no\/} addressing of large objects, even when the large memory model compile option is selected; Version 4.0 remedies this problem. After giving the matter some thought, I decided to implement the bitmap as a run-time allocated object, which on large machines is a single array, and on the \N{Intel} family, is a vector of large-memory pointers to raster lines. The allocation is performed by \CF{getbmap}. These two different representations pose a usage problem, because addressing of a particular word in a given raster line is different in the two cases. The bitmap is accessed frequently, so function call overhead to get at it cannot be tolerated. Fortunately, the \C{} preprocessor comes to the rescue, and the \CN{BITMAP(y,x)} macro has been defined to return the address of the requisite word with in-line code. This can be assigned to a scalar pointer variable, which is then incremented as the scan steps through the raster line. The only precaution necessary here is to avoid stepping the pointer from one raster line to another, since this is certain to fail with the vector-of-pointers representation. The only function which needed to be changed for this purpose is \CF{clrbmap}. Use of the scalar pointer variable reduces the bitmap addressing overhead to once per raster line, which is acceptable. The preprocessor symbol \CN{SEGMEM} is used to select appropriate code fragments in \CF{clrbmap}, \CF{getbmap}, \FN{machdefs.h}, \CF{main}, and several of the \FN{dvixxx.c} files. Changes were also necessary in \CF{makechar} and in some of the \CF{prtbmap} variants which appear in several of the \FN{dvixxx.c} files to handle vectors of raster pointers, rather than scalar pointers, but this again has been hidden from the code by appropriate preprocessor macro definitions. \subsection{\protect\FN{getbytes.h}} This function retrieves the next $n$ bytes from a file (usually the DVI file), returning them in a character array. It is short enough, and used often enough, that it could profitably be redefined as a macro for in-line expansion in some future version of the code. \SUBINDEX{to-do list}{to-do list}{functions into macros} \subsection{\protect\FN{getfntdf.h}} This function uses \CF{readfont} to collect all the font definitions stored in the DVI file postamble. It is called from \CF{readpost} when font preloading has been requested. \subsection{\protect\FN{getpgtab.h}} This function uses the {\em last page\/} pointer stored in the DVI file postamble to follow the chain of pointers to page beginnings right back to the first page set by \TeX{}. It uses the random I/O facilities of \C{} to accomplish this. The page table constructed contains byte position pointers to each of the pages for the output document; it is used in \CF{main} to find and process the pages requested by the user. \TeX{} stores ten counters \INDEX{page counters}{page counters} for each page; currently, only the first of these is collected and saved. This is conventionally the page number. \subsection{\protect\FN{inch.h}} In order to support run-time option values with attached units, the function \CF{inch} is provided. It converts a string containing a fractional number followed by a two-letter unit designator to a floating-point return value in inches. My apologies for the name of this function to the rest of the world which uses the metric system---our paper sizes are still in inches. The units recognized are given in the following table: \begin{center} \begin{tabular}{|l|l|} \hline value & units implied \\ \hline \#.\#\#bp & big point (1in = 72bp)\\ \#.\#\#cc & cicero (1cc = 12dd)\\ \#.\#\#cm & centimeter\\ \#.\#\#dd & didot point (1157dd = 1238pt)\\ \#.\#\#in & inch (1in = 2.54cm)\\ \#.\#\#mm & millimeter (10mm = 1cm)\\ \#.\#\#pc & pica (1pc = 12pt)\\ \#.\#\#pt & point (72.27pt = 1in)\\ \#.\#\#sp & scaled point (65536sp = 1pt)\\ \hline \end{tabular} \end{center} A leading plus or minus sign is optional, and the letter case of the dimension name is ignored. No space is permitted between the number and the dimension. \subsection{\protect\FN{initglob.h}} \CF{initglob} is called once at the beginning of \CF{main} to handle all initializations of global variables. Although \C{} permits declaration-time variable initializations by constants, this is not always convenient when machine-dependent actions, such as construction of word-size dependent bit masks, are required. \CF{initglob} uses the standard library function, \CF{getenv}, to obtain any run-time definitions of the \X{environment variable}s \CN{DVIHELP}, \CN{FONTLIST}, \CN{TEXINPUTS} and \CN{TEXFONTS} which are to override the internal defaults. See the sections on \CF{fontfile}, \CF{fontsub}, \FN{machdefs.h}, and \CF{usage} for further remarks. The driver family will accept \FN{.gf}, \FN{.pk}, and \FN{.pxl} font file variants, but not all sites may be expected to have all of these. A default font file type search path is therefore established internally, with font types in the order \FN{.pk}, \FN{.gf}, and \FN{.pxl}, which corresponds to increasing file size, and places new \MF{} fonts before old \MF{} fonts. This search path can be overridden at run time by definition of an alternate path in the \CN{FONTLIST} \X{environment variable} (\X{logical name} in \DEC{} operating systems). Because operating systems may impose a particular syntax on environment variables, \CF{initglob} will ignore letter case and any other characters except the three strings \CN{GF}, \CN{PK}, and \CN{PXL}; only the order, and presence or absence, of these in the definition is significant. Acceptable strings equivalent to the default search path could therefore be \CN{PKGFPXL}, \CN{pk/gf/pxl}, \CN{pk GF pxl}, \CN{pk-gf.pxl}, and so on. There is absolutely no harm in using the default value of \CN{FONTLIST}, even if some of the font file types are not available, since all that will happen is that a file open will fail and another will be tried. Redefinition of \CN{FONTLIST} to avoid open attempts on files which are known not to exist is only for efficiency. \INDEX{efficiency}{efficiency} It is of course also useful during debugging to be able to force the use of a particular font type. \subsection{\protect\FN{keydef.h}} \FN{keydef.h} contains flag definitions and function declarations for the \X{keyboard input} package, \FN{keybrd.c}. It is included by \FN{main.h} only for those devices which need it. \subsection{\protect\FN{keybrd.c}} In order to support better control of screen display for interactive DVI drivers, I developed a set of \X{keyboard input} primitives defined in \FN{keybrd.c}. These are analogous to \C{}'s standard input functions, but guarantee (if the host supports it) immediate access to keyboard characters without blocking in a wait for a carriage return, and also provide a function for testing if input is available. The code necessary to do this is ugly on all the operating systems supported for this DVI driver family, and is best hidden away in a separate module. Because it is likely to be useful in other applications, this package must be separately compiled and linked with each interactive DVI driver, instead of being included in the source with a preprocessor directive. The extensive initial comments in \FN{keybrd.c} describe the package in detail. The header file \FN{keydef.h} must be included in modules which use the package in order to obtain flag definitions and function declarations. \subsection{\protect\FN{loadchar.h}} As new characters are referenced by the DVI file, the driver must keep track of them, retrieving character metrics and bitmaps from the font files. With the exception of the main body font in a document, only a few characters from each font are likely to be used, so it would make no sense whatever to load an entire font in just because one character from it was used. Instead, space for character definitions is allocated dynamically, and a \X{reference count} for each character is maintained. When space is no longer available, which is discovered when \CF{malloc} begins to return null pointers, garbage collection is in order. This is a topic of continuing interest in computer science, particularly in the Lisp language family. David Fuchs and Don Knuth \INDEX{Fuchs, David}{Fuchs, David} \INDEX{Knuth, Donald}{Knuth, Donald} wrote an interesting Stanford report in 1981 entitled {\em Optimal Prepaging and Font Caching\/}% \footnote{\INDEX{footnotes}{footnotes}% Later published in {\em ACM Transactions on Programming Languages and Systems\/}, {\bf 7}, No. 1, 62-79 (1985). } which treats the problem from the point of view of a \TeX{} DVI driver. They point out that in this case, the job is somewhat easier, because it is possible for the driver to look ahead to see what characters are needed next, rather than using \X{reference count}s which reflect past history of character usage. One of the surprising results they found was that with proper implementation of their algorithm, relatively little storage is actually needed on the output device to keep it always supplied with the needed fonts. The scheme used in our DVI drivers is more modest. No lookahead is done, so the \X{reference count}s can be used to identify characters, and even entire fonts, which are candidates for storage reclamation. Actually, most implementations of the driver family so far have been on hosts with a large address space, and we have been able to get by without even having to do garbage collection. Nevertheless, the \X{reference count}s are there for use, or some ambitious implementor can go and study {\it Optimal Prepaging and Font Caching} to figure out how to do the job right. \SUBINDEX{to-do list}{to-do list}{optimal font handling} \FN{loadchar.h} is the version used for the bitmapped output devices; it retrieves character rasters and leaves them in a dynamically-allocated memory block located by a pointer in the \CN{char_entry} structure. Private versions of \CF{loadchar} for downloaded font devices send the rasters directly to the device, rather than preserving them in memory. In either case, \CF{loadchar} does not itself actually retrieve the rasters from the font file; it calls \CF{charxx} to do the job. \CF{charxx} is declared in the \CN{font_entry} structure as \begin{verbatim} void (*charxx)(); \end{verbatim} and was stored in the font structure by \CF{readfont} with a statement like \begin{verbatim} fontptr->charxx = (void(*)())charpk; \end{verbatim} which saves the address of the function required to read the character rasters. It is more convenient, and more efficient, to do it this way, than to use the font type to index a \CN{switch} statement every time one of these functions must be called. \CF{loadchar} should be able to call it by \begin{verbatim} (void)(*fontptr->charxx)(c,outrow); \end{verbatim} since the pointer operator, \verb|->|, has higher precedence than the indirection operator, \verb|*|. In fact, Kernighan \INDEX{Kernighan, Brian}{Kernighan, Brian} and Pike, \INDEX{Pike, Rob}{Pike, Rob} in their book {\em The Unix Programming Environment\/}, use precisely this construction on p. 250. They also use the more complex, but equivalent, variant \begin{verbatim} (void)(*(void (*)())(*fontptr->charxx))(c,outrow); \end{verbatim} on p. 264. These work as expected with the \LATTICE{}, \MICROSOFT{}, and \WIZARD{} \C{} compilers on the \IBMPC{}, but on both \PCC{} and \N{4.1BSD} \CN{cc}, these generate a jump to the word {\em containing\/} the address of the function, rather than to the function itself! % % Original formulation works fine with KCC [18-Apr-87] % It took some experimentation to find that a workaround was possible: \begin{verbatim} void (*charyy)(); ... charyy = fontptr->charxx; (void)(*charyy)(c,outrow); \end{verbatim} This results in correct code with all compilers used so far for the DVI driver family, so \CF{loadchar} adopts it as the standard way to do things, in the expectation that the bug is likely to be found in other \UNIX{} compilers derived from the \N{Portable} \C{} compiler. I have not had time to dig into the compiler sources to track down the source of the problem. \SUBINDEX{to-do list}{to-do list}{track down compiler error} \subsection{\protect\CF{loadbmap}} \CF{loadbmap} is used to download large characters as raster bitmaps, instead of as downloaded fonts. It is used in those drivers which have a limitation on downloaded font sizes. Private definitions exist in \FN{dvican.c} and \FN{dvijep.c}. \subsection{\protect\FN{machdefs.h}} This file is included by \FN{dvihead.h}, which in turn is included by \FN{dvixxx.c}. It contains almost all of the machine-specific definitions; the only other ones are already bracketed by preprocessor conditional directives using symbols defined in this module. Unless you are developing a new implementation, {\em it should not be necessary to change more than this single file\/} when you install any one of the dozen or so drivers in the family. Comments in this file describe each of the flags, and they will not be repeated here. The important things to change are \begin{itemize} \item the \X{operating system flag}, currently one of \CN{OS_PCDOS}, \CN{OS_TOPS20}, \CN{OS_UNIX}, or \CN{OS_VAXVMS}; \item the \X{implementation flag}, either none at all, or one of \CN{ATT}, \CN{BSD41}, \CN{BSD42}, \CN{HPUX}, \CN{PCC_20}, \CN{KCC_20}, \CN{IBM_PC_LATTICE}, \CN{IBM_PC_MICROSOFT}, or \CN{IBM_PC_WIZARD}; \item the default file pathnames, \CN{FONTPATH} and \CN{SUBPATH}; \item the default \X{environment variable}s, \CN{TEXFONTS} and \CN{TEXINPUTS}. \end{itemize} The last two of these are already encapsulated in code selected by the current \CN{OS_xxxx} flag, but they may differ from site to site, even with the same operating system and compilers. In order to minimize the dependence of the programs on specific file path names, in most implementations, the \X{environment variable}s (\X{logical name}s in \DEC{} operating systems) are tested at run time in \CF{initglob}, and any values they have replace the default file paths. Thus, even though a driver compiled on one \IBMPC{} might have been built with the assumption that the fonts are found in the directory \FN{d:\-\bs{}tex\-\bs{}fonts}, it still may be usable on another system where the fonts have been installed in the directory \FN{c:\-\bs{}usr\-\bs{}pctex\-\bs{}texfonts}. All the user need do is define the name \CN{TEXFONTS} before running \TeX{}: \begin{verbatim} SET TEXFONTS=C:\USR\PCTEX\TEXFONTS\ \end{verbatim} Note the final backslash---\CF{fontfile} will assume it can simply prefix the definition of \CN{TEXFONTS} to a file name. There are several other parameters defined in \FN{machdefs.h}; the best thing to do is examine each of them in turn, and change them to suit the local environment, before compiling any of the drivers. \subsection{\protect\FN{main.h}} This is the main program for all of the DVI drivers. It had become large enough to cause problems with some compilers, so most of the code has been split out into seven other functions. It contains \CNNX{\#include}'s\INDEX{#include}{\CNNX{\#include}} for \FN{commands.h}, \FN{gendefs.h}, \FN{gblprocs.h}, and \FN{gblvars.h}, as well as for several standard system header files. Following this, it defines the \CN{BITMAP(y,x)} macro for bitmap addressing The code body then checks the argument count, and calls \CF{usage} and \CF{exit} if none are given, and then goes on to call \CF{initglob} for initialization, \CF{option} to process run-time options, \CF{dvifile} once for each command-line argument which is not an option, and finally terminates with a call to \CF{alldone}. \subsection{\protect\HCF{makechar}} For those dot-matrix printers which require bitmap encodings of vertical bit columns, it has proved convenient to hide the messiness of this in a separate function, \CF{makechar}, which is defined in several of the \FN{dvixxx.c} files. Because it must deal with bits in several raster lines, this function is sensitive to the bitmap representation, as discussed in the section on \CF{getbmap}. \subsection{\protect\FN{movedown.h}} This function is called in response to a vertical movement command from the DVI file. It updates the current vertical page position, \CN{v}, in \TeX{} units, and computes a new rounded position, \CN{vv}, in device units, using \CF{fixpos} to get it right. Efficiency \INDEX{efficiency}{efficiency} buffs might want to turn this into a preprocessor macro, since it is used often. \SUBINDEX{to-do list}{to-do list}{functions into macros} \subsection{\protect\FN{moveover.h}} This function is called in response to a horizontal movement command from the DVI file. It updates the current horizontal page position, \CN{h}, in \TeX{} units, and computes a new rounded position, \CN{hh}, in device units, using \CF{fixpos} to get it right. Like \CF{movedown}, it is often used, and is a candidate for macro metamorphosis. \SUBINDEX{to-do list}{to-do list}{functions into macros} \subsection{\protect\FN{moveto.h}} This function should really be a macro; it just records the new current point (in device coordinates) in the global variables (\CN{xcp},\CN{ycp}). \SUBINDEX{to-do list}{to-do list}{functions into macros} \subsection{\protect\HCF{newfont}} When \CF{readgf}, \CF{readpk}, and \CF{readpxl} have retrieved necessary font information, they call \CF{newfont}, currently defined only in \FN{dvialw.c}, \FN{dvibit.c}, \FN{dvican.c}, \FN{dviimp.c}, and \FN{dvijep.c}. It has the job of outputting whatever is necessary to the device to define the use of a new font. \subsection{\protect\FN{nosignex.h}} In the interests of compactness of the DVI file, when \TeX{} writes an integer, it usually tries to use the fewest number of bytes possible. The integer may be a signed or an unsigned value. This function collects the next $n$ bytes from the file and returns them as a single $n$-byte {\em unsigned\/} integer value, where $n$ is in 1 \ldots 4. \CF{nosignex}, like its twin \CF{signex}, is heavily used, and is a good candidate for special loopless code and in-line expansion. \SUBINDEX{to-do list}{to-do list}{functions into macros} \subsection{\protect\FN{openfont.h}} Whenever a font switch is called for by the DVI file, it may be necessary to find and open a new font file; \CF{openfont} is called to handle the operation. It uses \CF{fontfile} to obtain lists of possible file names, and if none of these can be opened, it will first ask \CF{fontsub} for a possible font substitution, and if that too fails, it will try neighboring members in the magnification family. \INDEX{font magnification}{font magnification} In typical \TeX{} documents, font switching occurs {\em often\/} (three times in this very sentence). On all operating systems, file opening is a relatively expensive operation,% \footnote{\INDEX{footnotes}{footnotes}% On a large university \N{IBM} mainframe where I did my graduate work, each file opening cost us \$0.50, except at night, when it dropped to \$0.25. I'm glad those days are gone! I probably spent more money doing that, than I did for the \IBMPC{} on which I'm now writing this document. } and the drivers therefore take care to avoid unnecessary openings. The number of open files allowed is \INDEX{open file limit}{open file limit} usually dependent on fixed tables in the operating system, which in practice are much too small. You have to set special parameters in your \FN{config.sys} file to get more than the default of 8 open files with \PCDOS{}, and 5 of these are already used by the operating system; 20 is the absolute limit. \TOPS{} allows more than 70 open files per process, but \PCC{} follows the \UNIX{} practice of limiting the number to 20, at least 3 of which are in use when the process begins. Also, buffer space is required for each open file, and since \PCC{} does not support \TOPS{} extended addressing, one tends to run out of memory for buffers before one runs out of file handles for new file openings. \KCC{} permits 32 open files, and its support for extended addressing eliminates the buffer space problem. The number of open files that the drivers will use is determined by the constant \CN{MAXOPEN} set in \FN{machdefs.h}, and the ones currently open are maintained in a cache. Each open request for a file in the cache increments an open reference count. When the \CN{MAXOPEN} limit is reached, the font file which has the lowest open \X{reference count} is closed, but any characters cached from it are retained in memory for further use. The new file is then opened and a cache entry created for it. The \X{font cache search} is a simple sequential search; since \CN{MAXOPEN} in practice is quite small (5 to 15), there would likely be little benefit in implementing a more sophisticated associative cache table using hashing or binary search. However, it should be considered if an implementation is made which permits much larger numbers of open files; all that needs to be changed is the first \CN{for} loop in \CF{openfont}. \TeX{} is prepared to have up to 64 active fonts, so \CN{MAXOPEN} could potentially be as large as that. \SUBINDEX{to-do list}{to-do list}{fast font cache search} \subsection{\protect\FN{option.h}} All run-time command-line \X{option parsing} is handled by this function. After \CF{initglob} has done global initializations, \CF{option} is called once for each option found in the \CN{argv[]} array passed to \CF{main} by the \C{} run-time library startup routine. \CF{option} is just a big \CN{switch} statement with cases selected by the second character of its string argument. A bad argument results in a call to \CF{usage} followed by a termination call to \CF{fatal}. All of the variables which can be set by run-time options are global, so \CF{option} only has a single argument. New options can be easily added merely by introducing a new global variable in \FN{gblvars.h}, a new \CN{case} pair in the \CN{switch} statement in \CF{option}, and code selected by the option wherever else it is required. The available options will not be repeated here; they are completely described in \FN{dvihead.h}, and in the separate help file, \FN{dviman.ltx}. That help file also exists in a more useful format, \FN{dviman.texinfo}, which can be converted by \N{Gnu Emacs} to a \FN{.info} file. The option parsing is simple, involving little more than noting the presence of an argument, or collecting its string or integer value, or calling \CF{inch} to convert a number followed by a unit specifier. Similar code is present in almost all \C{} programs. The one difference here is that {\em option letter case is not significant\/}. In my view, one of the design flaws of \UNIX{} and \C{} was to make letter case significant in names. This means that every $n$-character identifier has $2^n$ different variants, all pronounced the same. The code therefore cannot pass the ``\X{telephone test}'' (dictate your favorite program over the telephone to a friend without excessive spelling of words).% \footnote{\INDEX{footnotes}{footnotes}% The situation is not unlike Japanese, for which the 600 or so commonest Kanji (Chinese) characters used in \INDEX{Kanji characters}{Kanji characters}% \INDEX{Japanese characters}{Japanese characters}% \INDEX{Chinese characters}{Chinese characters}% written Japanese share only about 25 different pronunciations, resulting in the necessity of speakers writing characters in the air or on their palms to distinguish which one is really meant when the choice is not clear from context. This homonymic situation also poses a problem for phonetic Roman character computer and word processor input schemes with \X{oriental languages}; see the January 1985 issue of {\em IEEE Computer\/} \INDEX{IEEE Computer}{\string\em\space IEEE Computer\/} for several interesting articles. } All user command-line input to the DVI drivers is letter-case {\em insensitive\/}, except possibly for file names, which must conform to the host operating system conventions. Internally, compiled-in file names are represented in lower case letters, since that works for both \UNIX{} and most case-insensitive operating systems. The \UNIX{} \X{environment variable}s are in upper-case, since that is conventional, though not required, in \UNIX{}, similar to the common practice of \C{} programmers of specifying variables with lower-case names, and preprocessor constants with upper-case names. This practice, incidentally, is {\em rigorously\/} adhered to in the DVI driver family. When you see a name entirely in upper-case \INDEX{letter case}{letter case} in the source code, you can be sure it is a preprocessor constant, and not a variable or function name. The reverse is also true. No names are spelled in mixed letter case.% \footnote{\INDEX{footnotes}{footnotes}% Except \TeX{}, when for lack of it, you have to write it {\tt TeX}! } \subsection{\protect\FN{outrow.h}} Once a single row of a character bitmap has been retrieved, decoded, and stored in the global array \CN{img_row[]}, \CF{outrow} is called from \CF{chargf}, \CF{charpk}, and \CF{charpxl}, to prepare it for output. The public version in \FN{outrow.h} is used by most of the family; it merely copies the row from its global storage location to the dynamically-allocated raster storage for that character. Private versions of \CF{outrow} in \FN{dvialw.c}, \FN{dvibit.c}, \FN{dvican.c}, \FN{dviimp.c}, and \FN{dvijep.c}, handle the formatting and output of the row for their particular device. \subsection{\protect\HCF{prtbmap}} This function is not stored in a separate include file, because it is sufficiently different from device to device to warrant inclusion inside the \FN{dvixxx.c} routines as a private function. Nevertheless, it is an important one, because it has the job of formatting a completed bitmap for output to the device. The bitmap cleared by \CF{clrbmap}, and written by \CF{dispchar}, is conceptually a simple rectangular array of bits, consecutive bits in memory corresponding to consecutive dots on the output rasters. For addressing \X{efficiency}, however, each scanline begins on a new word or byte boundary, depending on the host architecture, and if the host has \X{segmented memory}, it may be stored as a separately-allocated raster lines, as described in the earlier section on \CF{getbmap}. This format allows efficient operation by \CF{dispchar}, which can do its important job oblivious to the peculiarities of output device expectations. \CF{prtbmap} must take this rectangular array of bits and reformat it for the output device. For some devices, like the \HPLJ{}, this is straightforward ---only some escape sequences at the start and end of each raster line have to be attached, but otherwise, the raster bytes can be dumped directly to the output file. The \N{Printronix} printers are almost straightforward---they want horizontal raster lines encoded six bits per character; the peculiarity is that the bits must be reversed in the byte! It looks like some designer got his wires crossed. This unpleasantness is most easily handled by table lookup, and that is just what \CF{prtbmap} in \FN{dviprx.c} does. Other printers are more obnoxious---they want 6, 7, 8, or 24 bits in a {\em vertical\/} column to be reordered into consecutive bytes, because then the print head pins can be matched to the input bits and fired or not. For those that place fewer than 8 bits in a byte, most do so by biasing by 64 or 128, which can be done by a logical {\em or\/} operation. The \DEC{} \N{LA} family printers use a bias of 63, which requires a slower addition for each output byte. Printer designers have apparently not understood that input buffers of horizontal raster lines would be so much easier for the user, and also offer better possibilities for run-length compression of rasters. \INDEX{run-length encoding}{run-length encoding} This routine is probably the most tedious to code in the drivers, and it must be redone for each new bitmap format. It typically requires 50 to 100 lines of code (excluding translation tables). It is a fairly time-consuming operation, so the code goes to some length to be efficient, \INDEX{efficiency}{efficiency} using tricks like scanning over zero words in a raster line, trimming empty top and bottom raster lines before starting the encoding, and unrolling inner loops. The code is also likely to be dependent on host word size, and for a few lines in the inner loops, portability may well be sacrificed to efficiency. Some of the dot matrix printers support run-length compression \INDEX{run-length encoding}{run-length encoding} of rasters, wherein consecutive identical bytes are collapsed into a count field and a single data byte. This is a little tricky to get right, and is less effective with the vertical encodings than it would be with horizontal encodings, but it usually does reduce the output file size somewhat. The disappointing feature is that the printer is likely to run {\em slower\/}, rather than faster, because of inefficient decoding of the compression. If you have such a printer, try it both ways before you decide which method to use. \subsection{\protect\FN{prtpage.h}} \CF{prtpage} is one of the largest functions in the family. Its job is to typeset a single page selected by its caller. It has nearly 400 lines of code, but is really just a single loop containing a giant \CN{switch} statement which selects code fragments corresponding to each one of the 256 different byte codes which can be found in a DVI file. The loop exits when an end-of-page command is reached. For interactive displays (e.g. \CN{dvibit}), it also calls the end-of-page routine, \CF{eopact}, whenever \X{keyboard input} is available. This permits instant response of the screen display to user commands to reposition the display, go to a new page, or change the display magnification; \INDEX{font magnification}{font magnification} no time is wasted finishing the page display if it is just going to be changed anyway. Fortunately, the first 128 DVI codes are just ordinary character typesetting requests, and another 64 are font change commands, so $3/4$ of the cases can be handled by four lines of code. Almost all of the DVI driver run time is spent in \CF{prtpage} and the functions it calls, but because its structure is so simple, there is little one can do to improve it, short of in-line expansion of code for some of the more commonly-used command codes. Implementation of the {\em Optimal Prepaging and Font Caching\/} algorithm discussed earlier in the \FN{loadchar.h} section would probably involve converting this into a two-pass operation, one to collect commands and font requirements for a single page, caching the commands in memory to reduce I/O requirements, followed by a similar loop to process them, with font preloading happening at appropriate times as determined by the \X{Fuchs-Knuth algorithm}. \SUBINDEX{to-do list}{to-do list}{optimal font handling} \subsection{\protect\FN{readfont.h}} This function is called by \CF{getfntdf} to read in a single font definition sequence in the DVI file postamble, or the first time a font definition is encountered, if preloading has been suppressed. It initializes the \CN{font_entry} structure with parameters from the DVI file, then calls \CF{reldfont} to direct the loading of additional information from the font file. \subsection{\protect\FN{readgf.h}} \CF{readgf} is called from \CF{readfont} to initialize all font parameters for a \FN{.gf} font file, and retrieve the character metrics. As noted in the earlier section on \CF{chargf}, the entire file must be read to collect all of the metrics. For the several drivers currently supporting downloaded fonts, \CF{newfont} is called to do whatever is required to start a new font. \subsection{\protect\FN{readpk.h}} \CF{readpk} is called from \CF{readfont} to initialize all font parameters for a \FN{.pk} font file, and retrieve the character metrics. Just as for \CF{readgf}, the entire file must be read to collect all of the metrics, and for the drivers currently supporting downloaded fonts, \CF{newfont} must be called to do whatever is required to start a new font. \subsection{\protect\FN{readpost.h}} This function is called near the start of \CF{main} after command-line options have been processed. It coordinates the reading and checking of the DVI file postamble, using function \CF{findpost}, calls \CF{getfntdf} if font preloading has been requested, and finally calls \CF{getpgtab} to retrieve the document page table. \subsection{\protect\FN{readpxl.h}} \CF{readpxl} is called from \CF{readfont} to initialize all font parameters for a \FN{.pxl} font file, and retrieve the character metrics. Since these are all available in a 2-Kbyte directory at the end of the file, minimal file activity is needed to retrieve them. \CF{newfont} is then called to do whatever is required to start a new font. \subsection{\protect\FN{reldfont.h}} This function was split out of \FN{readfont.h} to separate the retrieval of font information from the DVI and font files, in order to support dynamic unloading of fonts required by the zoom option in \CN{dvibit}. It is called from \FN{readfont.h} and from the private function \INDEX{private modules}{private modules} \CF{unload_fonts} in \FN{eopact.h}. \CF{openfont} is used to find and open the font file, and then \CF{getfntdf} dynamically allocates a font entry containing basic character metrics for all characters in the font, but none of the potentially voluminous raster information. That portion is left in the font file for later retrieval and memory caching only when it is really needed. If font preloading has been suppressed (this is a run-time option), then \CF{getfntdf} will not be invoked at startup for all fonts found in the postamble, but only dynamically as each font is required. Preloading is forced if selected pages are printed, or pages are printed in reverse order (e.g. \CANON{} \N{LBP-CX} laser print engines without additional paper handling mechanisms). This is necessary because \TeX{} outputs a font definition command the first time a font is used, and then never again until the postamble is written. The code in \CF{newfont} ensures that the device receives the proper font definition sequences, and must be executed before any character in the font can be used. With the addition in late April, 1986, of support for the new \FN{.gf} and \FN{.pk} font file formats, a considerable revision of font handling became necessary, and resulted in the introduction of 11 new functions: \CF{chargf}, \CF{charpk}, \CF{charpxl}, \CF{clrrow}, \CF{outrow}, \CF{readgf}, \CF{readpk}, \CF{readpxl}, \CF{skgfspec}, \CF{skpkspec}, and \CF{strid2}. The goal in this was to make the source of font data known to only a small number of routines. After opening a font file successfully, \CF{reldfont} examines the bytes at the start of the file which uniquely identify which of the three font file types it is. It saves the font type and character retrieval function (\CF{chargf}, \CF{charpk}, or \CF{charpxl}) in the \CN{font_entry} structure, then calls \CF{readgf}, \CF{readpk}, or \CF{readpxl} to actually read the character metric data from the file. Should a new font file format be introduced, all that is necessary to support it is to add code to \CF{reldfont} to recognize it, and provide analogues of \CF{chargf} and \CF{readgf} to retrieve character rasters and metrics. \subsection{\protect\FN{rulepxl.h}} This short function converts a dimension of a horizontal or vertical rule measured in high-precision \TeX{} units to output device units. It is a good candidate for macro replacement. \SUBINDEX{to-do list}{to-do list}{functions into macros} \subsection{\protect\FN{setchar.h}} Apart from positioning commands, {\em Set Character\/} commands make up the bulk of the commands in the DVI file. \CF{setchar} is called for each of them.% \footnote{\INDEX{footnotes}{footnotes}% Except in some drivers; see \CF{setstr} in a later section. } First of all, it determines whether or not the character is visible on the current page. If it is, then it calls \CF{moveto} to update the current position, and then \CF{dispchar} to paint \INDEX{character painting}{character painting} the character. Then, depending on the particular DVI file command that invoked it, it may update the current horizontal position in both \TeX{} coordinates and device units. \CF{fixpos} again is used to do it right. \subsection{\protect\FN{setfntnm.h}} There are 64 DVI file commands which request font changes, and \CF{setfntnm} is called for each of them. It defines the font to be used for future printing until another {\em Set Font\/} command is encountered. Because actual font definitions are handled by another DVI command,% \footnote{\INDEX{footnotes}{footnotes}% See \CF{getfntdf}. } when this function is invoked, the font is already expected to have been loaded into the cache. A sequential search% \footnote{\INDEX{footnotes}{footnotes}% See the remarks in the subsection on \CF{openfont}. } of the cache is made to find the font pointer for the requested font; if it is not found, \CF{fatal} is called to terminate the job. \SUBINDEX{to-do list}{to-do list}{fast font cache search} \subsection{\protect\FN{setrule.h}} When \TeX{} sets a horizontal or vertical rule, it generates a DVI command which results in \CF{setrule} being called. It in turn calls \CF{fillrect}, then updates the horizontal positions, \CN{h} and \CN{hh}, relying again on \CF{fixpos} for help. \subsection{\protect\HCF{setstr}} \TeX{} does not insert glue between letters of a word, only between words. Consequently, words appear in a DVI file as consecutive {\em Set Character\/} requests, possibly interspersed by {\em Set Font\/} commands. For devices on which characters must be set by the DVI driver, such as dot matrix devices, there is no advantage to be taken of this. For devices with downloaded fonts but relatively low resolution, such as the \BG{}, not much can be done either, because character widths must be rounded to pixel boundaries, and within three or four characters, the cumulative string position would be incorrect. For downloaded characters in \N{Adobe} \POSTSCRIPT{}, it is possible to define precise widths which are not rounded to pixel boundaries. Several characters can be therefore be set by a single command, reducing the output volume considerably. \POSTSCRIPT{} has been licensed by several manufacturers, but the most widely available product using it at present is the \ALW{}, about which we shall later have more to say. \CF{setstr} is currently used in the \CN{dvialw}, \CN{dvican}, \CN{dviimp}, and \CN{dvijep} drivers. It functions similarly to \CF{setchar}, except that it loops collecting consecutive characters to be set, then outputs them all as a single string. The string is interrupted and a positioning command is issued if \CF{fixpos} produces a different horizontal position than the device would otherwise have from its character width information. Similarly, if a character is encountered which is too large to be definable as a single character on the device, the string is interrupted, and the large character is sent as a raster image. To conserve font memory on the \ALW{}, ``large'' characters% \footnote{\INDEX{footnotes}{footnotes}% The size limit can be set by a run-time option. } are downloaded each time they are required, bracketed by \POSTSCRIPT{} {\em save\/} and {\em restore\/} commands which cause them to be discarded after use. Because it is quite likely that a character encountered will not yet have been downloaded, the initial version just completed the current string, downloaded the new character definition by a call to \CF{loadchar}, and resumed the string collection. This entails some extra output overhead, so to reduce it, the latest version has two sets of loops. The first collects the characters into an internal array, and downloads any new ones. The second loop then processes the characters from the array, outputting them as a single string. There is a little extra run-time overhead because of the second loop, but it is minor compared to the reduction in the output volume. \subsection{\protect\FN{signex.h}} This is the twin to the function \CF{nosignex} discussed earlier. \CF{signex} collects the next $n$ bytes from the file and returns them as a single $n$-byte {\em signed\/} integer value, where $n$ is in 1 \ldots 4. Negative values are represented in {\em two's complement\/} form; implementors on one's-complement machines (\N{CDC}, \N{Univac}) must revise the code here. \subsection{\protect\FN{skgfspec.h}} \CF{skgfspec} is called by \CF{chargf} to skip over any \MF{} {\em numspecial\/} and {\em special\/} commands embedded in the font file. These are not currently used in the {\em Computer Modern\/} fonts. \subsection{\protect\FN{skipfont.h}} If fonts have been preloaded, then when \CF{prtpage} encounters a {\em Define Font\/} command, the font definition which immediately follows in the DVI file must be discarded. This function performs that task. If font preloading has not been selected, \CF{prtpage} calls \CF{readfont} instead. \subsection{\protect\FN{skpkspec.h}} \CF{skpkspec} is called by \CF{charpk} to skip over any \MF{} {\em numspecial\/} and {\em special\/} commands embedded in the font file. These are not currently used in the {\em Computer Modern\/} fonts, but \CN{GFtoPK} will copy any it finds in the input \FN{.gf} file to the output \FN{.pk} file. \subsection{\protect\FN{special.h}} The \TeX{} \verb|\special| command provides a means for inserting arbitrary text into the DVI file. The intention is to allow the DVI driver to provide support for features, like insertion of bitmap images, which \TeX{} cannot easily or efficiently offer. Such strings necessarily depend on the implementation, operating system, and output device, and therefore detract from document portability. Nevertheless, the feature can be exceedingly useful. The \TeX{} User's Group has twice had sessions on the subject of \verb|\special| commands with a view to coming to some consensus for what forms the command string should take, but no definite proposal has yet been put forward. When \CF{prtpage} meets a DVI file {\em XXXn\/} command, which is what \TeX{} produces in response to a \verb|\special|, it collects the following string and passes it to \CF{special}, which has the job of interpreting it. For most dot matrix printers, providing useful support for insertion of bitmap images is at best awkward, because the usually bizarre formatting required by the device would require reconstruction of a bitmap array from the encoding, then re-encoding it for output at the current position. However, it would not be difficult to add support for vector graphics files, such as the ubiquitous \TEKTRONIX{} format which is both compact and relatively easy to decode. The vectors could be suitably scaled and translated, then written directly into the bitmap which \CF{dispchar} has been updating. So far, for these devices, \CF{special} just raises a warning message containing its argument string, and then returns without further action. \SUBINDEX{to-do list}{to-do list}{\TEKTRONIX{} graphics file support} For the more intelligent laser printers, particularly those using the \POSTSCRIPT{} language, considerably more is possible, and the implementations of \CF{special} are still in their infancy. In \FN{dvialw.c} for the \ALW{}, I have brazenly copied the format used by David Kellerman\INDEX{Kellerman, David}{Kellerman, David} and Barry Smith\INDEX{Smith, Barry}{Smith, Barry} in their driver for the \IMAGEN{} laser printers. The \TeX{} \verb|\special| command is expected to look like one of the following: \begin{verbatim} \special{overlay filename} % absolute positioning \special{include filename} % relative positioning \special{insert filename} % relative positioning \end{verbatim} In the first case, the \POSTSCRIPT{} file to be included will be mapped onto the page at precisely the coordinates it specifies. In the other two cases, the upper-left corner of the bounding box will be placed at the current point. The \POSTSCRIPT{} file must then contain (usually near the start) a comment of the form \begin{verbatim} %%BoundingBox: llx lly urx ury \end{verbatim} specifying the bounding box lower-left and upper-right coordinates in standard \POSTSCRIPT{} units (big points, 1/72 inch). Alternatively, if the comment \begin{verbatim} %%BoundingBox: (atend) \end{verbatim} is found in the file, the last 1000 characters of the file will be searched to find a comment of the form: \begin{verbatim} %%BoundingBox: llx lly urx ury \end{verbatim} If the \POSTSCRIPT{} file cannot be opened, or the \verb|\special| command string cannot be recognized, or for relative positioning, the bounding box cannot be determined, a warning message is issued and the \verb|\special| command is ignored. Otherwise, the section of the \POSTSCRIPT{} file between the comment lines \begin{verbatim} %begin(plot) %end(plot) \end{verbatim} is copied to the output file surrounded by \begin{verbatim} save % revert to standard 1/72 inch units 300 72 div 300 72 div scale % if relative positioning (xcp(in 1/72in)-llx) (ycp(in 1/72in)-ury) translate ...PostScript file contents... restore \end{verbatim} This format nicely supports \POSTSCRIPT{} output from my \PLOT{} graphics system and has received considerable use locally. As we get more experience with \POSTSCRIPT{}, \CF{special} will no doubt be expanded to support fancier operations, like insertion of \N{MacPaint} and \N{MacDraw} images from the \MAC{}. \N{Adobe} Systems is aware of this problem of incorporating \POSTSCRIPT{} files in other \POSTSCRIPT{} documents, and in December, 1986, published a short document {\em Encapsulated PostScript File Format, EPSF Version 1.2\/} \INDEX{EPSF}{EPSF ({\em Encapsulated PostScript File Format\/})} describing conventions for doing this cleanly. Future changes to \CF{special} in \FN{dvialw.c} should adopt these. \subsection{\protect\FN{strchr.h}} \C{} is a sparse language, and contains no built-in functions or I/O facilities. The inventors of \C{} defined an extensive set of library functions, but implementors since have not always adhered to the original library conventions. Besides introducing new names for the same functions, implementors have sometimes committed the even worse sin of defining the same functions, but with changed function return types. This is certainly a detriment to portability. The string support functions are one area where significant differences exist. I have therefore chosen to implement some functions which are defined in the coming ANSI Standard \C{} library. \CF{strchr} searches a string for a single character, returning a pointer to the {\em first\/} matching character, or a null pointer if the character is not found. It is permissible to search for the \CN{NUL} character which terminates the string; the returned value minus the address of the string is the length of the string, excluding the \CN{NUL} terminator.% \footnote{\INDEX{footnotes}{footnotes}% Pointer subtraction in \C{} is defined to return the number of objects between the two addresses, not the number of memory units. } \subsection{\protect\FN{strcm2.h}} \CF{strcm2} compares two strings, ignoring case differences, and returns a negative number if the first is less than the second, zero if they match, and otherwise a positive number. It is analogous to the usual \CF{strcmp} function which does not ignore case differences. \MICROSOFT{} \C{} on the \IBMPC{} calls this function \CF{strcmpl}, but this violates our rule of uniqueness in the first six characters of a function name. The October 1986 draft of the proposed ANSI \C{} Standard has no equivalent function. \subsection{\protect\FN{strid2.h}} \CF{strid2} searches for the first occurrence of a substring in another string, returning -1 if it is not found, or else its index 0, 1, \ldots{} if it is found. Letter case is {\em ignored\/}. It is used by \CF{initglob} in the parsing of the \CN{FONTLIST} \X{environment variable}. The October 1986 draft of the proposed ANSI \C{} Standard has no equivalent function. \subsection{\protect\FN{strrchr.h}} \CF{strrchr} is the counterpart to \CF{strchr}. It searches a string for a single character, returning a pointer to the {\em last\/} matching character. It is permissible to search for the \CN{NUL} terminator. \subsection{\protect\FN{tctos.h}} \CF{tctos} converts a global list of \TeX{} page counters, \INDEX{page counters}{page counters} \CN{tex_counter[]}, to a character string, with counters separated by dots, and trailing zeroes dropped. It is used by the \FN{dvixxx.c} programs to format them for printing. \subsection{\protect\FN{typedefs.h}} This file is included by \FN{dvihead.h} after it includes \FN{machdefs.h}. As noted earlier, it contains \CN{typedef} declarations for \CN{BOOLEAN}, \CN{BYTE}, \CN{COORDINATE}, \CN{INT8}, \CN{INT16}, \CN{INT32}, \CN{UNSIGN16}, \CN{UNSIGN32}, and \CN{void}. If the implementation supports the \CN{void} type, then the \CN{typedef} for it is suppressed. The symbols \CN{TRUE} and \CN{FALSE} are also defined for use with objects of type \CN{BOOLEAN}. Dennis Ritchie's original definition of \C{} did not clearly indicate whether \CN{unsigned} is a {\em distinct\/} integer type, or a {\em modifier\/} of the integer types \CN{char}, \CN{short}, \CN{int}, and \CN{long}. Reasonable compilers implement it as a modifier, since one can quite reasonably require unsigned values in a variety of sizes, particularly in systems programming and graphics programming, where the integers being manipulated are really bit patterns, not numbers. Unfortunately, some compilers have chosen to make \CN{unsigned} a distinct type meaning \CN{unsigned int}; the \LATTICE{} \C{} compiler on the \IBMPC{} is one such example. This complicates programming, and special attention must be given to those parts of the code which use the \CN{UNSIGN16} and \CN{UNSIGN32} types. The most important example is the bitmap array used for the dot matrix printer drivers. \subsection{\protect\FN{usage.h}} \CN{usage} is called from \CF{main} whenever \CN{dvixxx} is invoked without arguments, and from \CF{option} in response to a bad argument. On the file defined by its single argument, it displays a short message illustrating the expected command line, followed by a suggestion of where to find detailed documentation (set by the preprocessor constant \CN{HELPCMD} defined in \FN{machdefs.h}, and possibly overridden at run time by the \X{environment variable} \CN{DVIHELP}), then returns to its caller. \subsection{\protect\FN{warning.h}} When situations arise which warrant the issuing of a warning message, such as a font substitution performed by \CF{fontsub}, \CF{warning} is called. If no \X{log file} is open, it tries to open one. If this succeeds, the message is written to the log file, possibly adorned by additional text. The name of the function issuing the call to \CF{warning} is included as part of the message. For example, the \TOPS{} operating system uses the convention that text written to the primary output file (terminal, or batch job log file) which begins with a percent sign is a warning, and text which begins with a query is an error message. The batch controller recognizes these and raises an error flag if a query is written first. These two characters are usually sufficiently rare in text files that they make convenient search targets when one is examining a \X{log file} with a text editor or string search utility. Consequently, when the symbols \CN{OS_TOPS20} or \CN{OS_VAXVMS} are defined, \CF{warning} and \CF{fatal} prefix these characters to the message. \section{DVI Driver Device Support} The preceding sections have given a comprehensive survey of the structure of the DVI drivers. In the following subsections, we shall briefly discuss each of the currently-supported devices, mostly in \X{alphabetical order} by filename. If you intend to implement a driver for a new device, you can profit by choosing the existing driver which most closely resembles your target device, then modifying it appropriately. Please send your implementation back to this author for inclusion in the collection. % Need italic correction after underscore to avoid it % running into the following punctuation You can quickly get an idea of just which functions are likely to require modification by using a string search utility to find processor conditionals ``\CNNX{\#if}''\INDEX{#if}{\CNNX{\#if}} in the source files. A listing will not be given here, because it would be difficult to keep up-to-date. You can similarly find operating system dependencies by searching for the string ``\CN{OS_}\/'', and implementation dependencies by searching for any of the flags discussed earlier in the section on \FN{machdefs.h}. \UNIX{} makes it easy to combine programs so that the output of one becomes the input of the other, with both running simultaneously. Consequently, many \UNIX{} programs are designed to read their input from \CN{stdin} and write their normal output to \CN{stdout}, and error messages to \CN{stderr}. These three files are automatically open when a process begins to execute. \PCC{} supports this model as well. I therefore had to make a design choice of whether the DVI drivers would adopt this model or not. In a pure \UNIX{} environment, this would be quite satisfactory, and conform well to the notion of a {\em filter\/} program. \UNIX{} users can quite reasonably expect to issue a command like \begin{verbatim} % tex myfile | dvixxx | xxxspool \end{verbatim} to have the file \FN{myfile.tex} processed by \TeX{}, translated by \CN{dvixxx}, and spooled to the output device by \CN{xxxspool}, all in one concurrent step. I chose not to use this model, because on the \TWENTY{}, where all my development work is done, the output of the \CN{dvixxx} program may not be a standard text file. Since \PCC{} supports only 7-bit I/O for \CN{stdin}, \CN{stdout}, and \CN{stderr}, while the output may require an 8-bit file, it is necessary to create an intermediate disk file. The convention adopted is that the suffix of the driver name becomes a suffix of the DVI file name. Thus, on the \TWENTY{} or under \UNIX{}, \FN{myfile.tex} is transformed by \TeX{} to \FN{myfile.dvi}, then by \CN{dvixxx} to \FN{myfile.dvi-xxx}. For operating systems which do not permit long file extensions, the driver may output it as \FN{myfile.xxx}. This has proved to be a wise choice even in the 8-bit world, where record-structured file systems like \VAX{} \VMS{} conflict with the byte-stream output of \CN{stdout}. \subsection{\protect\FN{dvialw.c}} This driver for the \ALW{} is the most recent addition to the family. It was developed starting from the \BG{} driver, \CN{dvibit}, since this was the only other driver with downloaded font support at the time. \N{Adobe} \POSTSCRIPT{} is a complete programming language designed for the support of intelligent printer drivers. Like the popular% \footnote{\INDEX{footnotes}{footnotes}% in some circles } \N{Forth} language, it is written in reverse Polish notation, which some claim is easier to parse because operands can be simply stacked until an operation is found, which then pops its operands off the stack, performs its job, and places the result, if any, back on the stack. Reverse Polish notation is certainly not easy to read without extensive practice. For example, to set a string at a particular page position, one writes \begin{verbatim} 250 300 moveto (Hello there) show \end{verbatim} This example shows the main problem with \POSTSCRIPT{} --- it is verbose. The compact \TEKTRONIX{} vector format would encode the first command in 5 or fewer characters, instead of 14. Perhaps someday there will be efficient \POSTSCRIPT{} compilers. In the meantime, one can only try to reduce the \POSTSCRIPT{} volume by definition of compact macros; \CN{dvialw} produces \begin{verbatim} (Hello there)250 300 S \end{verbatim} for the above. A space after the right parenthesis is discarded, and the two command words are collapsed into a single letter. This verbosity drastically reduces the potential performance of the \ALW{}. The \CANON{} print engine is capable of printing 8 pages per minute, and the \IMAGEN{} \N{8/300} which uses it too will output \TeX{} at 7 pages per minute. The best we have been able to do on the \ALW{} is about 2 per minute, and that represents an average serial transmission rate of about 750 characters per second, close to the limit of 960 at the 9600 baud limit. The printer may perhaps run faster with the 29 Kbaud \N{AppleTalk} connection. \POSTSCRIPT{} timing experiments showed that the \ALW{} performs about one arithmetic operation per millisecond, and further experiments revealed the fact that the arithmetic conforms to a single-precision subset of the \X{IEEE floating-point} format. This is not surprising, because Jerome Coonan,\INDEX{Coonan, Jerome}{Coonan, Jerome} one of the principal designers of the IEEE standard, works for \N{Apple} and did the software for the floating-point emulator for the \MAC{}. The printer and the computer both use the \N{Motorola 68000} microprocessor, and neither have floating-point hardware. Rumors of an advance to the faster \N{68020} CPU and \N{68881} hardware floating-point chip with the newly released \N{Enhanced} \ALW{} were wrong; it only has more internal fonts and more memory. I bought an \ALW{} in June, 1985, and although I was able to prepare a device driver for my \PLOT{} graphics systems and have it operational in under a day, the \TeX{} DVI driver has proved much more difficult. This is due to two reasons. First of all, the documentation and examples in the {\em PostScript User's Manual\/} (September 1984 printing) for downloaded fonts are incorrect; the examples simply do not work at all. Second, the \POSTSCRIPT{} Version 23.0 interpreter has two serious bugs. One of these is a flow-control bug which is documented in the \N{Apple} {\em Inside the LaserWriter\/} manual---the printer on occasion will send out an \CN{XOFF} character to stop host transmission, then never send the \CN{XON} character to resume it. Eventually, the printer times out and aborts the job after issuing an error message. Initially, this seemed to happen on almost every page, and it took several weeks of experimentation during the summer before I was able to write a transfer program which reduced the incidence. In December, 1985, I obtained a proposed fix for this bug from ARPANET correspondence, and it seems to have helped, although the problem still does arise. The second bug has to do with virtual memory management, which comes into play primarily with downloaded fonts, which neither the \MAC{} nor graphics applications make use of. At random intervals, the printer issues a {\em VM error\/} message and flushes the job. It is usually completely irreproducible; the same document will raise the error twice, and print on the third try. The longer the printer has been running, the slower it seems to get, until cycling the power reboots it. We have often found it necessary to do this several times a day, hardly a satisfactory situation for a printer which is expected to be a spooled output device. Because of the flow control bug, and because the printer sends back all kinds of messages, such as {\em \%\%[ PrinterError: out of paper ]\%\%\/}, it is necessary to have an intelligent file copy utility for it. Some people have gone to the trouble of handling \CN{XON} and \CN{XOFF} characters themselves, establishing a real-time interrupt when an \CN{XOFF} is received, and then resuming output either after receipt of an \CN{XON}, or when the timer interrupts. My copy utility, \FN{lw78.c}, lets the operating system handle flow control, but carries on a dialog with the printer before starting each job to make sure it is idle. It periodically monitors the printer input stream to see if any message is waiting, and if so, collects it, decodes it, and attempts to handle the commoner ones. Status messages do not always arrive complete, perhaps because of data loss at the serial interface on the host computer. Consequently, the copy utility cannot just collect two percents and an open bracket to start a message, then gobble characters until a close bracket and two more percents terminate it, because this might block the process completely. Instead, it alternates periods of sleep and tests for input data until about ten seconds have elapsed without receiving a complete message. At that point, the message is assumed to be garbled and a flag is set which causes later input attempts to flush data until a new start of message is recognized. This is clearly nothing but hackery; I am not proud of it, and it wasted weeks of work which could have been much more profitably spent. The \POSTSCRIPT{} font mechanism is complex and difficult to understand, and much better documentation and many examples are badly needed in the manuals. It centers around the idea that in the current font, for each character there is a collection of numbers defining the bounding box and displacement to the next character, plus a procedure which is invoked to draw the character whenever the character appears in a {\em Set String\/} command. This is a powerful mechanism which is also fundamental to the \N{Emacs} text editor. The character procedure is free to utilize the entire language to create a picture at the current point. The built-in fonts use proprietary outline encoding mechanisms which provide arbitrary scaling. For \TeX{}, we just send character bitmaps down encoded as hexadecimal strings. After all of the work on \CN{dvialw} had been completed, Addison-Wesley published the {\em PostScript Language Reference Manual\/} and the {\em PostScript Language Tutorial and Cookbook\/} in the spring of 1986. These offer much improved documentation, and remove my criticisms of that aspect. The font examples in the {\em Tutorial and Cookbook\/} now work as advertised, and the problems with the \ALW{} are discussed in Appendix D of the {\em Language Reference Manual\/}. These two books are essential for any \POSTSCRIPT{} programmer. To facilitate a certain amount of extensibility of the \TeX{} \POSTSCRIPT{} driver, macro references, rather than raw \POSTSCRIPT{}, are written to the output file. The macros are defined in a standard file named \FN{dvialw.ps} which is searched for in the current file directory, then in a standard system directory defined by the preprocessor symbol \CN{TEXINPUTS}. Like the font substitution file, the definition of this symbol may be overridden by the user at run time, allowing personal customizations. The standard \FN{dvialw.ps} file which goes with this driver is heavily commented to assist customization. The comments, and excess whitespace, are all stripped by function \CF{cppsfile} during the copy to the beginning of the output file, so they never have to be transferred to the printer. The driver is careful never to produce any unnecessary whitespace, in order to reduce the output volume. Even so, on large documents, the \POSTSCRIPT{} file is usually 4 to 6 times larger than the DVI file, and on short ones, up to 20 times longer. \FN{dvialw.c} supports the \TeX{} \verb|\special| command to a limited extent; see the section on function \CF{special} for details. While it is in principle possible for \FN{dvialw.ps} to support \POSTSCRIPT{} built-in fonts, this would require preparation of \TeX{} font metric (\FN{.tfm}) files for them. \TeX{} needs this information to use a font. At present, there is insufficient font metric information available for the built-in fonts, and the character repertoire is inadequate for mathematical typesetting. Some members of the Stanford \TeX{} project have been consulting with \N{Adobe}, so we may hope that this situation will improve. For non-\TeX{} printing on the \ALW{}, we have used a utility program I wrote, \FN{lptops.c}, to convert line printer files to \POSTSCRIPT{}. It has options to access all of the built-in fonts at arbitrary sizes, as well as support for multi-column printing, page numbering, overstriking, margin setting, multiple copies, page outlining, and manual paper feed selection. The help file, \FN{lptops.hlp}, describes these further. The \N{Enhanced} \ALW{} was announced in February 1986, at a list price of \$7995. Ordinary \N{LaserWriter}'s can be upgraded to it for about \$1000. This new model contains version 38.0 of the \POSTSCRIPT{} interpreter, and offers several new features: \begin{itemize} \item many internal performance improvements; \item expanded communications options, including baud rates to 57.6 Kbaud and hardware flow control; this is important for the IBM PC, which without additional software does not support software flow control; \item several new language features; \item correction of nearly all the known problems in the \ALW{}, including the flow-control bug; \item new resident fonts: Avant\-Garde, Bookman, Helvetica-Narrow, New\-Century\-School\-Book, Palatino, Zapf\-Chancery, and Zapf\-Dingbats; \item additional memory \end{itemize} One of the important performance improvements is the overlap of page output with input processing; previously, the \POSTSCRIPT{} interpreter waited up to 6 seconds per page before resuming input processing. Initial user experience with this printer is reported to be quite favorable; I personally have not yet had any. \N{Adobe} has recently made available accurate font metric and ligature information for the resident fonts. Kerning specifications are not yet available, but have been promised. Unfortunately, this information is not available in the new \POSTSCRIPT{} books, but font metric files are distributed with \N{Adobe}'s \N{TranScript} software for \UNIX{} systems, and probably also with \N{Pipeline Associates}' \N{devps} competing software. This should make it possible to augment \CN{dvialw} to support use of resident \POSTSCRIPT{} fonts with \TeX{}. This will be even more important for the \N{Mergenthaler Linotype Linotronic 300}, which is the first photo\-type\-setter to use \POSTSCRIPT{}. \subsection{\protect\FN{dvibit.c}} This driver is the first in the family, but has undergone the same extensive modifications as the rest of the members. It is the only one which provides a form of \TeX{} preview mechanism, but we unfortunately have only one \BG{} terminal on campus, so it has not received the use I would have liked to see. With laser printers increasingly available, the need has declined. Although the display speed is satisfactory, the resolution is coarse ($1024 \times 768$), and small characters are often indistinguishable. \TeX{} previewers on the \IBMPC{} have an even more severe limitation of half this resolution. In order to reduce the number of fonts required, the default size with Mark Senn's original version has been changed to 603 magnification. \INDEX{font magnification}{font magnification} This is in the standard magnification family for 300-dot/inch devices (magstep -5). Since we have \MF{} on the \TWENTY{}, production of arbitrary sizes for all of the \TeX{} fonts has been trivial; only disk space requirements limit our enthusiasm. In order to write commands to the BitGraph, it is necessary to be able to send ASCII \CN{ESC} characters, and to make the display easily controllable, character-at-a-time input without echo is desirable. Under \UNIX{} systems, this is straightforward---you just put the terminal in {\em half-cooked\/} or {\em raw\/} mode, and twiddle a couple of \CF{ioctl} flags. On the \TWENTY{}, it is quite possible, but somewhat convoluted, so there are large code sections under control of the \CN{OS_TOPS20} flag. When the driver exits, care has to be taken to reset the terminal characteristics properly. With Version 2.07 of the family, a major change was made in \CN{dvibit}. Keyboard input \INDEX{keyboard input}{keyboard input} with \CF{getc} has been replaced with a more powerful package, \FN{keybrd.c}, described earlier. This package supports immediate return of characters as they are typed, and also provides a primitive for checking if input is available, without blocking like \CF{getc} normally does. This makes it possible for the main command loop in \FN{prtpage.h} to check for \X{keyboard input} before processing each DVI command, which in turn avoids unnecessary screen redisplay, and facilitates rapid skimming through a document, as well as rapid page repositioning. In addition, the font handling mechanism was revised with the introduction of \FN{reldfont.h}, so that \CF{unload_fonts} in \FN{eopact.h} can dynamically change the \X{font magnification} to support a \X{zoom command}. Drawing of the command and status window is now done at page beginning by \FN{bopact.h}, and the display has been made larger and more informative. The size limit at which downloaded fonts are abandoned in favor of sending large character bitmaps each time they are needed has been substantially increased, so that any reasonable document and magnification \INDEX{font magnification}{font magnification} should be able to use downloaded fonts exclusively, giving much faster screen display. The display now works correctly with both black and white screen backgrounds (they are selectable in terminal setup mode); previously, large characters were displayed incorrectly on a black background. \subsection{\protect\FN{dvican.c}} This driver is for the \CANON{} \N{LBP-8 A2} laser printer, which uses \CANON{}'s own controller with their \N{LBP-CX} engine. The \N{LBP-8 A2} supports 300 dot/inch raster graphics, vector graphics, and, according to its documentation, downloaded fonts. After seeing this printer offered at under \$3000 from a local vendor, I obtained one on trial in late December, 1986, expecting to have a graphics interface and a DVI driver completed before the New Year. To make a long story short, in despair, it was returned to the dealer in March, 1987. The documentation for the printer is abysmal, and it was only through the help of a local laser printer development firm that I got sufficient detail on the printer to write any software at all for it. Eventually, I obtained a Subsystem Manual from \CANON{} headquarters in New York, but this seemed to only confirm that what \CN{dvican} is doing is correct according to the documentation. Downloaded fonts just do not work properly, and to get any \TeX{} output, it is necessary to send raster bitmaps for each character, which drastically increases the output file size, and slows the printer to about 1 page every 3 or 4 minutes. Correspondence with a site in Holland that had obtained another DVI driver for this printer from Japan resulted in their sending me a hexadecimal dump of the DVI output for the standard \TeX{} sample file, \FN{story.tex}. To my surprise, it too handles characters as bitmaps, instead of using downloaded fonts. This tends to confirm my experience. I have spent a great many frustrating hours with this printer; if anyone reading this has used the printer successfully with downloaded fonts, I would like to hear about it. Otherwise, I am inclined to blacklist it, and exclude it from further consideration. \subsection{\protect\FN{dvigd.c}} This driver was adapted for the {\em Golden Dawn Golden Laser 100\/} printer developed by a local Salt Lake City firm. This printer has not reached the commercial market, so the driver will not be of interest outside our local installation. \subsection{\protect\FN{dviimp.c}} This driver for the \IMAGEN{} laser printer family was produced by Lon Willett at Utah, starting from \FN{dvijep.c}, using the Stanford University \IMAGEN{} driver in \WEB{} as a guide. It has been working quite satisfactorily with both our \IMAGEN{} \N{8/300} and \N{3320} printers on \TWENTY{} and \VAX{} \VMS{}. The major work left to do is the addition of support for \verb|\special| commands. \subsection{\protect\FN{dvijet.c}} The \HPLJ{} printer has taken the low-cost page printer market by storm, and was claimed in one trade magazine survey to be the largest selling printer of all time. Like the \ALW{} and the \IMAGEN{} \N{8/300}, and several others on the market, it uses the 8 page/minute \CANON{} print engine. It appeared on the market in the late summer of 1984 at a list price of \$3495, and I got one in late November. There is a built-in Courier font, and additional fonts are provided by plug-in cartridges. There is no downloadable font capability, but fortunately, there is support for bitmap display, so it is treated very much like a dot matrix printer by the \FN{dvijet.c} \TeX{} driver. It has only about 55 Kbytes of raster memory, far less than the 900 Kbytes needed for the printable portion of a standard American page. Fortunately, it is possible to request the printing of a bitmap at 300, 150, 100, or 75 dots/inch, and the latter size is close to a full page. Each bit is imaged as a square 1 to 4 dots on edge for these resolutions. In the fall of 1985, the \N{LaserJet Plus} was announced at a list price of \$3995 and the regular \N{LaserJet} was reduced to \$3495. The latter can be upgraded to the \N{Plus}, which has quite decent support for downloaded fonts and larger bitmaps (but still limited---to 512 Kbytes). In late March, 1986, an \N{Enhanced LaserJet Plus}, the \N{HP 2686d}, was announced. It has a list price of \$4995 and offers two 250-sheet paper trays and in-order output stacking, but apparently still lacks sufficient memory for a full page bitmap. This printer has been aggressively marketed, and universities have seen discounts of 30\% or more. It could well become the most common \TeX{} output device. \subsection{\protect\FN{dvijep.c}} I was able to secure the loan of a \HPLJ{} \N{Plus} printer in late March, 1986, for the development of a DVI driver, and \CN{dvijep} is the result of that work. I lost about a day's work fiddling with trying to get downloaded characters to work, because of unclear documentation in the reference manual, but apart from that, conversion of \CN{dvialw} to \CN{dvijep} took less than a day. \CN{dvialw} was chosen as the starting point, rather than \CN{dvijet}, because it supports downloadable characters, and the translation of \POSTSCRIPT{} sequences required by \CN{dvialw} to \N{HP} printer sequences seemed straightforward. Some of the improvements made in \CN{dvijep} for output compression, including not outputting unchanged rule sizes, and remembering the current string {\em y\/} coordinate in a global variable for \CF{setstr}, have been carried back into \CN{dvialw}. The printer language used to control the \N{Hewlett-Packard} printers consists of escape sequences, most of which require a three-character prefix, and a single upper-case letter terminator, possibly separated by a digit string. For example, to move to a particular (x,y) coordinate position, one sends something like \begin{verbatim} p*1234X p*3214Y \end{verbatim} and to draw a solid-filled rule 200 dots wide by 50 dots high, with its upper-left corner at the current point, one sends \begin{verbatim} *c200A *c50B *c0P \end{verbatim} Characters outside of escape sequences are simply set in the current font, so in these examples, the sequences would be run together, for otherwise the newlines between them would generate blank lines in the output. Signed numbers can be specified for coordinates to get relative moves, instead of absolute moves. Consecutive control sequences with common three-character prefixes can be collapsed by omitting the prefix on all but the first, and changing all but the last terminator to lower-case. In addition, if a digit string is zero, it may be omitted entirely. Thus, the above examples can be reduced to \begin{verbatim} p*1234x3214Y \end{verbatim} and \begin{verbatim} *c200a50bP \end{verbatim} a savings of almost half. \CN{dvijep} takes great care to use these compact forms in order to decrease the output size, and the reduction has proved quite significant. To avoid scattering these control sequences throughout the various \FN{.h} files, they are entirely encapsulated in preprocessor macros defined at the beginning of \FN{dvijep.c}. This proved valuable in making optimizations of them. There is absolutely no error indication if a control sequence is bad---it is simply discarded by the printer. In the case of downloaded fonts, this means that characters whose downloaded description is incorrect, or garbled, will either be missing from the output, or will appear, but in a different font. This features makes debugging at times frustrating, since the printer cannot tell you what is wrong. It would be nice to have a mode wherein you could ask it to {\em print\/} error messages on the output page. Except for font downloading, most of the sequences are simple, and cause little difficulty. Communicating with the printer requires nothing more than obeying its \CN{XON}/\CN{XOFF} flow-control protocol, so standard operating system \CN{copy} commands usually suffice, and the pain and suffering I went through with \CN{lw78} for the \ALW{} did not have to be repeated. Character raster descriptions are sent as 8-bit binary data, and therefore require half the output volume that \POSTSCRIPT{} needs. With some large test DVI files, the \CN{dvijep} output is about 30\% shorter than the \CN{dvialw} output, and timing tests with 9600-baud communication show that the \N{LaserJet Plus} will output \TeX{} at 3 to 3.5 pages per minute. Once again, the serial communication seems to be the limiting factor, and it may be that with 19200 baud, or with the Centronix parallel interface, it may be able to produce 6 or 7 per minute. The \CANON{} \N{LBP-CX} engine is capable of 8 pages per minute. Only the dummy \CF{special} function is presently used in \CN{dvijep}. Support for insertion of raster images should not be difficult to add. As with the regular \N{LaserJet}, images can be displayed at 75, 100, 150, or 300 dots/inch, and the extra memory of the \N{Plus} permits a full page at 150 dots/inch, or a 5-inch square at 300 dots/inch. Besides having support for larger bitmaps and downloaded fonts, the \N{Plus} adds one useful extension over the regular {\sc laserjet}. All coordinates can be specified in dots, as well as the decipoints used by the latter. This makes it easy to position characters precisely, without worrying about conversions of units of 1/720 inch to ones of 1/300 inch. The printer permits origin resetting, but only to positions on the page, because positive coordinates are required. Experimenting with the output positioning showed that the upper-left page corner was actually at (0.1in, -0.07in) on the printer I have. Consequently, two new preprocessor symbols, \CN{XORIGIN} and \CN{YORIGIN}, have been introduced in \CN{dvijep} which are used in \CF{dviinit} to bias the left and top margin values specified by default, or by command-line options. Some remarks about the downloaded font capability are in order here. The \N{Plus} identifies fonts by numbers in 0 \ldots 32767, and fonts may be defined in any order and with any font numbers, provided that no more than 32 are resident in the printer at one time, and further, that no more than 16 are used on one page. It is not at all obvious why this page limitation should exist. Code has been inserted in \CF{readfont} to check for the possibility of more than 32 being defined; if this happens, it issues a warning indicating that the current page may be incomplete, and then deletes the last 16 and frees their font space. So far, this message has not been issued. No check is made to see if more than 16 fonts are in use on a single page, but this would not be hard to add. I am inclined to leave the changes until, and if, a problem arises from this limitation. So far, only one document has been encountered locally which reached this limit. The printer then imaged some characters as blanks, and used the wrong font for others. The author decided to accept the printer limitation, and revised his document to reduce the number of fonts per page. Fonts can be of two types---7-bit fonts, allowing characters 33 \ldots 127 to be downloaded, and 8-bit fonts, allowing characters 33 \ldots 127 and 160 \ldots 255 to be defined. The latter require double the internal storage. The size limitation on the characters is the same in both---255 dots high or wide; only the number of characters is different. \TeX{} fonts use all characters in 0 \ldots 127,% \footnote{\INDEX{footnotes}{footnotes}% The DVI file allows 0 \ldots 255. } so in order to keep the font mapping one-to-one, a macro \CN{MAPCHAR} is defined which remaps \TeX{} characters in 0 \ldots 32 onto 160 \ldots 192, so that this peculiarity is hidden from the code in \CF{loadchar}, \CF{setchar}, and \CF{setstr}. The descriptions of the {\em Create Font\/} command in the {\em Hewlett-Packard LaserJet Printer Technical Reference Manual\/} caused me considerably confusion and the loss of time noted earlier. The discussion and examples are oriented toward using the command to link cartridge-resident fonts with a user-defined numbered font, and the command has fields for {\em font type\/}, {\em symbol set\/}, {\em pitch\/}, {\em style\/}, {\em stroke weight\/}, and {\em typeface\/}, which are attributes settable with other printer commands which the \N{LaserJet} somehow (i.e. completely non-intuitively) relates to particular fonts. This is the only way fonts can be selected on the regular \N{LaserJet}, and it has previously cost me a good deal of frustration, since it is impossible to just tell it ``give me 10pt Courier bold''. When my tests at downloading a simple character failed, I assumed that the problem was with the values I had chosen for all of these attributes, and I spent several hours experimenting with them, each time getting blank output pages. The problem turned out to be none of these parameters, and their values are apparently arbitrary when one is downloading character descriptions. The {\em Create Font\/} command has four 16-bit fields called {\em cell width\/}, {\em cell height\/}, {\em baseline position\/}, and {\em font height\/}. Since the {\em Download Character\/} command defines its own character metrics, I had arbitrarily given these fields zero values. Later experiments with these revealed that {\em font height\/} is arbitrary, but the other three must be defined large enough to encompass the biggest enclosing box of any downloaded character. Downloaded characters with smaller metrics will print, but the larger ones are just discarded without error indication. The solution therefore was to have \CF{readfont} compute the requisite values for these from the metrics it retrieves from the font file, and output these in the {\em Create Font\/} command. I presume that the {\em cell height\/} and {\em cell width\/} parameters are used by the \N{Plus} for internal memory allocation, although there is no reason why it could not do this on receipt of the sizes specified in the {\em Download Character\/} commands. With sophisticated fonts used in typesetting, there is no reason whatever to assume any commonality of character sizes within a font, and neither is there any reason to store more than just the minimal bitmap for each character. The {\em Download Character\/} instruction contains some fixed magic bytes, followed by {\em left offset\/}, {\em top offset\/}, {\em character width\/}, {\em character height\/}, {\em delta x\/}, and finally the binary character bitmap as a byte stream, each raster line being rounded up to the next higher byte boundary. The {\em left offset\/} is the distance from the character reference point (the same one \TeX{} calls the character position) to the leftmost edge of the character bitmap; this is just the negative of the \CN{xoffp} parameter in the \TeX{} font file. The {\em top offset\/} is the distance from the reference point to the top of the character pattern, and is identical to the \CN{yoffp} parameter in the font file. Although both of these are specified as 16-bit numbers in the {\em Download Character\/} instruction, they are apparently stored internally as one-byte signed values, because they are restricted to the range -128 \ldots 127. \CF{loadchar} enforces these limits when it issues the download sequence, and \CF{readfont} prints a warning message when it finds any character which violates this restriction. Eventually, such characters should be sent as an ordinary raster image instead. The {\em delta x\/} value is four times the (possibly fractional) dot spacing to the next character reference point, and therefore is equivalent, except for scale and precision, to the \TeX{} \CN{tfm} character width. At present, no advantage is taken in \CF{setstr} of the higher precision of this spacing parameter; when \CF{fixpos} changes the horizontal position, a new string is started. The \N{LaserJet} supports landscape page orientation as well as portrait orientation, but unlike \POSTSCRIPT{} which requires only a very simple transformation matrix to get landscape mode, on the \N{Plus}, font definitions must be completely changed, and raster images (including character bitmaps) sent with vertical rasters, since these will be parallel to the engine scanning direction. This is a considerable inconvenience, with all the complications and host overhead noted earlier in the section on \CF{makechar}, so \CN{dvijet} does not yet offer this option. A final remark should be made here about the compactness of the output file. The {\em Create Font\/} and {\em Download Character\/} commands are encoded about as compactly as could be expected, although support for \X{run-length encoding} of raster images would be valuable. Once most of the required characters have been downloaded in the early pages of the document, the remainder of the file looks something like the following, taken from an actual test file: \begin{verbatim} *p323x1584Yplicit <--new line *p434Xexcitation *p631Xof *p683Xeac *p740Xh *p782Xquasi-normal *p1035Xmo *p1092Xde. *p1178XP *p1206Xo *p1226Xw *p1255Xer-la *p1335Xw *p1382Xtails *p1477Xpro *p1538Xduced *p1663Xb *p1686Xy *p1725Xthe *p1802Xv *p1823Xarious *p1949Xsources *p323x1634Yare <--new line *p394Xdiscussed. *p596XIn *p649Xparticular, \end{verbatim} Newlines have been inserted after each escape sequence to make them readable. Otherwise, the entire output file is one single stream of 8-bit bytes. Note that at the beginning of each new line, marked by the arrows in the example, there is a {\em y\/} coordinate specified, but for the remainder of the line, only {\em x\/} coordinates are given. When words are broken, it is usually an indication that \CF{fixpos} found a position discrepancy, so \CF{setstr} began a new output string. It is evident that in these cases, and between words, there is a typical overhead of eight extra characters. In fact, for this example, there are 314 total characters, of which 208 are in escape sequences, and the other 106 are to be displayed on the typeset page. This means that about $2/3$ of the file consists of overhead characters, and if this proportion could be reduced, the total savings, and speed-up in printing, would be substantial. Some repositioning is of course necessary at the start of each word, and using relative coordinates would reduce each sequence by one character, giving 16 fewer characters in this 16-word example, which is not a large saving. It would therefore appear valuable to define some of the currently unused font positions 193 \ldots 255 in each font as spaces of various sizes, then output the minimal number of these to obtain the required spacing. Since the interword spacing required is rarely more than 50 dots, or 200 quarter dots in the units defined for the {\em delta x\/} character parameter, if ten space characters of widths of 1, 2, 4, \ldots, 1024 quarter dots were defined, then by simple bit shifting of the required horizontal space value, we could output the required space with probably an average of three, instead of the eight characters in the above example. Care will of course have to be given to getting this precisely correct, because the danger of relative spacing is always that the small errors can accumulate to large ones, while using absolute coordinates for each word will repair small errors made in individual character positions. \SUBINDEX{to-do list}{to-do list}{fonts for small space characters} \subsection{\protect\FN{dvil75.c}} This driver is for the \N{DEC LA75} dot matrix printer in 144-dot/inch mode. It was contributed by John Sauter, and has not been tested locally. \subsection{\protect\FN{dvim72.c}} This driver is for the \N{Apple ImageWriter} dot matrix printer in 72-dot/inch mode. This printer has the same command set as the popular \N{Epson} printers, so the driver should work with both. Because these are low-cost printers, paper registration is poor, and high quality cannot be expected. Each pass of the print head may lay down 8 raster lines, but when the next group of 8 is printed after scrolling the paper, a thin white space is commonly seen. Expect times of 2 to 6 minutes per page. \subsection{\protect\FN{dvimac.c}} This driver is for the \N{Apple ImageWriter} dot matrix printer in 144-dot/inch mode. Except for code changes to double the printer bitmap size and to support the encoding of the higher resolution, it is identical to \CN{dvim72}. The higher resolution is achieved by encoding a 16-bit raster column into two 8-bit bytes, odd rows into the first byte, and even into the second. All odd bytes are then sent to the printer and printed, the carriage scrolls the paper up one dot, and then the even bytes are sent and printed. This suffers from even worse registration problems than the 72-dot/inch mode, and since it requires four times the data volume, it is hardly worthwhile. It may prove to be of better quality with the \N{ImageWriter Plus}, but I have not tried it. \subsection{\protect\FN{dvimpi.c}} \CN{dvimpi} is the DVI translator for the portable \N{MPI Sprinter} dot matrix printer, which was made here in Salt Lake City. Despite considerable popularity, low cost, and typewriter-like portability of the \N{Sprinter}, \N{MPI} went out of business in late 1985. The driver can be compiled for either 72- or 144-dot/inch printing, according to the preprocessor variable \CN{HIRES} in \FN{dvimpi.c}. The bitmap encoding is a 6-bit column per character, and in 144-dot/inch mode, printing takes four passes with intervening half-dot right and down motions. The \N{Sprinter} has no reset command, so it is not possible to restore it to a guaranteed state on completion. \subsection{\protect\FN{dvio72.c}} \CN{dvio72} is for the \N{Okidata Pacemark 2410} dot matrix printer at 72 dots/inch. Along with the more expensive \N{Printronix} printers, this is one of the sturdiest dot matrix printers on the market, and has been quite popular as a replacement for 200 to 600 line/minute band and drum printers. The bitmap encoding puts a 7-bit column into an 8-bit byte, but no bias is applied, so all 128 ASCII byte values are possible graphics data. This poses a problem discussed in the next paragraph, and necessitates a second pass by function \CF{outline} through the encoded bitmap data before it can be output. There is some problem in getting the print head to return to the same left margin position after each pass of the heads across the page, so the driver sends several carriage-return characters at the end of each line. The printer has a serious design flaw in that it lacks a command to reset to power-on state. This is serious, because it uses \CN{ETX} to enter graphics mode, \CN{ETX} \CN{STX} to exit graphics mode, and \CN{ETX} \CN{ETX} to mean \CN{ETX} as graphics data. This means that a single \CN{ETX} sent from the host may cause it to enter graphics mode, or generate an error if it is already in graphics mode. Similarly, an \CN{ETX} \CN{STX} will enter graphics mode if it is not already in it, instead of exiting graphics mode. We therefore turn on graphics mode for each line, then turn it off again. That way, there may be some remote hope of resynchronizing if we lose an \CN{ETX} due to line errors along the way. From an efficiency \INDEX{efficiency}{efficiency} standpoint, it is regrettable that it has no \X{run-length encoding} of graphics data. The output quality and speed are otherwise quite reasonable as medium-cost dot matrix printers go. \subsection{\protect\FN{dvioki.c}} \CN{dvioki} supports the \N{Okidata Pacemark 2410} in 144-dot/inch mode, but is otherwise very similar to \CN{dvio72}. This printer does not require awkward encoding of raster lines for high-resolution mode like the \N{Apple ImageWriter} and \N{MPI Sprinter} do, and printing is not done by half-line overlap, so the quality is higher. The printer takes care of whatever bit rearrangements are necessary; the bitmap is just four times as big. \subsection{\protect\FN{dviprx.c}} \CN{dviprx} is the second member of this family, and has formed the basis for all the other dot matrix printer development. The \N{Printronix} printer family is one of the sturdiest on the market. It has been emulated by \N{C-Itoh}, and remarketed by many computer manufacturers under their own names. It has been on the market for at least ten years, and one outside my door has been in regular use since 1978. List price, depending on speeds of 200 to 600 lines/minute, ranges from \$3000 to \$7000. Almost all the other dot matrix printers on the market have a moving head of vertically-aligned pins which impact the ribbon to print a dot. One firing of all the pins in the head prints one column of dots, and this operation must be repeated from 72 to 180 times per inch, depending on the printer resolution, with incremental head movement each time. Uniform print registration on successive passes is directly related to the cost of the printer, and most of the low-cost ones do a poor job. The \N{Printronix} mechanism has a shuttle of 44 horizontal hammer banks (in the 600 model; the number is model-dependent). Oscillation of the shuttle carries each hammer bank across only 3 character positions to obtain standard 132 character/line printing, with a resolution of 60 dots/inch. In graphics mode, one line of data bytes with 6 data bits per character, biased by 64, produces one raster line. The paper then moves up 1/72 inch, and the next raster line is printed. Since much less mechanical movement is involved, speed and print quality are much better than with the other types of printers. The primary complaint is that it results in a non-unit aspect ratio of $60/72 = 5/6$ which \TeX{} users must put up with. I have not felt it worthwhile to ask \MF{} to generate special fonts to compensate for this. As noted earlier in the section on \CF{prtbmap}, the bit encoding is backwards, so a table-lookup translation of each output byte is necessary. A modification of the \N{Printronix} mechanism for 100-dot/inch printing with unit aspect ratio was licensed by \N{Trilog} and marketed. One model could support color printing with a special multicolor ribbon, using three complete passes over the page. Unfortunately, the higher resolution came with a considerably higher price and speed of under 200 lines/minute, so I do not believe this was a great market success. \subsection{\protect\FN{dvitos.c}} Several Japanese printer companies, including Toshiba, NEC, Fujitsu, and Epson, and one American company, AMT, have developed 24-pin dot matrix printers capable of 180-dot/inch printing. The impetus for this came from the need to support the Japanese Kanji, Katakana, and Hierogana symbol \INDEX{Hierogana characters}{Hierogana characters} \INDEX{Japanese characters}{Japanese characters} \INDEX{Kanji characters}{Kanji characters} \INDEX{Katakana characters}{Katakana characters} sets. The JISCII (Japanese Industrial Standard Code for Information Interchange) \INDEX{JISCII character set}{JISCII character set} character set is based on a 128 by 128 character matrix, containing ISO/ASCII in the first row, \X{Greek} and \X{Cyrillic} in the next rows, and about 6000 characters divided into two levels according to frequency of use in the remaining rows. Two ASCII characters then can effectively represent one Japanese character. These characters can be quite complex, but the Japan Standards Institute has developed a collection of about 10000 characters which can all be represented in a 24 by 24 matrix. This size led to the pin configuration of these high-resolution dot matrix printers. As a side effect, 180 dots/inch is a great improvement over the resolution of most other dot matrix printers, and produces print quality which is not far from that of daisy-wheel printers, but at higher speed and with more versatility. These printers hit the market in late 1983, with the {\sc toshiba p-\small\sc1351} being one of the first. At that time, electrostatic printers were still expensive, and printed on unpleasant paper, and laser printers cost \$20,000 and up. Although the existence of a new low-cost print engine with a disposable drum cartridge from \CANON{} was rumored, there was nothing else on the market of comparable resolution, so I bought a \N{P-1351} about February 1984 for \$1950 (after academic discount). The \HPLJ{} was announced only three months later, and I was able to get one delivered in late November. It appeared then that the superior speed (8 pages/minute versus perhaps a half-page/minute), print quality, and quietness of the laser printer would be attractive, and despite a cost of at least \$1500 more, the business community at least might buy it. The enormous market success of low-cost laser printers has proven this view correct, and the 24-pin printers clearly have an extremely limited market life. Nevertheless, if you happen to own a \N{Toshiba P-1351}, \CN{dvitos} will produce \TeX{} output on it for you. The initial comments in \FN{dvitos.c} give some performance statistics. At 180 dots/inch, a reasonable size page requires over 200 Kbytes for the bitmap. The \N{P-1351} supports \X{run-length encoding} which can reduce the output volume somewhat, but in practice, it runs 2 to 3 times slower, and produces terrible print quality due to inaccurate positioning of the print head during horizontal skips. I do not know whether this is a mechanical problem with my particular printer, or symptomatic of all Toshiba printers in this class. The bitmap encoding puts a 24-bit column into 6 bits each of 4 successive bytes, biased by 64. About 120 lines of code are required in \CF{prtbmap} to handle this. The printer has the additional restriction that in any two adjacent bit columns, no two horizontally-adjacent bits can be set. Rather than deal with this complication during the encoding, \CF{prtbmap} ignores the rule and hands each byte stream representing 24 raster lines off to \CF{outline}, which makes a second pass through it, turning off adjacent bits, before sending it to the output file. Run-length encoding \INDEX{run-length encoding}{run-length encoding} is selectable by a run-time option, and is handled by \CF{outline} in a further 55 lines of code. The printer supports only encoding of successive whitespace, and since at least 12 consecutive 24-dot columns must be white for the encoding to save space, the chances of this happening are not large. Horizontal raster line encoding of both blank and white would do much better. The space reduction on two test files was less than 30\%, with print times of 1 to 6 minutes per page. At hardly double the cost, laser printers give much higher quality, silent printing, up to 40 times the speed, and twice the resolution, so these dot-matrix printers do not fare well as \TeX{} output devices. \section{Setting up the Environment} Someone setting up \TeX{} for the first time is likely to find it difficult to get an overview of just how things should be set up. A \TeX{} distribution tape is likely to fill about 30Mb of disk space with thousands of files in dozens of directories, and in order for the software to work properly and find its way around the file system, some naming conventions are necessary. To illustrate this, the layout we use on the \IBMPC{} , \TOPS{}, and \VAX{} \VMS{}, is sketched in the next three subsections. \subsection{\protect\IBMPC{} Setup} On my \IBMPC{}, I maintain \TeX{} and the DVI driver family on two dismountable 10Mb Bernouilli disk cartridges. For Personal \TeX{}'s PC{}\TeX{}, the directory layout looks as follows: \begin{verbatim} D:\PCTEX ! TeX.EXE, LaTeX.EXE, et al D:\PCTEX\TEXFMTS ! TeX .FMT files D:\PCTEX\TEXTFMS ! TeX .TFM files D:\PCTEX\TEXINPUT ! TeX input files \end{verbatim} For Micro{}\TeX{}, the structure is similar, and I chose to store the font files in its directory tree: \begin{verbatim} D:\TEX ! TeX.EXE, LaTeX.EXE, et al D:\TEX\INPUTS ! TeX input files D:\TEX\FONTS\180 ! *.pk font files D:\TEX\FONTS\240 ! *.pk font files ... D:\TEX\FONTS\1548 ! *.pk font files \end{verbatim} The DVI family files reside in the directories \begin{verbatim} D:\DVI D:\DVI\DOC \end{verbatim} The environment variables required by the DVI family are the ones chosen by default in \FN{machdefs.h}. They could be set in a startup file (typically \FN{AUTOEXEC.BAT}): \begin{verbatim} set FONTPATH d:\tex\fonts\ set PATH c:\bin;d:\dvi;d:\pctex set SUBPATH d:\tex\inputs\ set TEXFONTS d:\tex\fonts\ set TEXINPUTS d:\tex\inputs\ \end{verbatim} The \PCDOS{} \CN{PATH} variable should include all the directories that contain executable programs you require. Although you can copy programs into a common directory, I find it preferable to keep them in the directories where they originate, and just have a long \CN{PATH} search list. If you use \CN{dvialw}, its macro file, \FN{dvialw.ps}, should be copied into the directory defined by the \CN{TEXINPUTS} variable. \subsection{\protect\TOPS{} Setup} The main \TeX{} directory structure is identical to that maintained by the Stanford \TeX{} Project, but we have numerous additional local directories. In \FN{SYSTEM:n-m-CONFIG.CMD} (where system-wide \X{logical name}s are conventionally defined, and \FN{n} and \FN{m} are major and minor Monitor release numbers), we have \begin{footnotesize} \begin{verbatim} define DVISPOOL: tex:nospool.exe !Dummy .DVI file spooler define TEX: aps: ! *.EXE files for TeX, ! TeXware and DVI drivers define TEXFORMATS: aps: ! TeX and LaTeX *.FMT files define TEXFONTS: aps:,- ! CM fonts in .TFM and .PK form scrtch:,- ! AM fonts in .PXL form scrtch: ! AM*.TFM files define TEXINPUTS: aps:,- aps:,- aps: define TEXSPOOL: tex:nospool.exe !Dummy .DVI file spooler \end{verbatim} \end{footnotesize} Users can individually redefine \FN{TEXSPOOL:} to be \FN{TEX:\-DVIxxx.\-EXE} for their preferred DVI file translator, and \FN{DVISPOOL:} to be \FN{TEX:\-IMSPOOL.\-EXE} (\IMAGEN{}) or \FN{TEX:\-PSSPOOL.EXE} (\POSTSCRIPT{}). Both laser printers are driven by spooler jobs running under \CN{SYSJOB} (started by \CN{@DO OPR:--START-IM-SPOOL} and \CN{@DO OPR:--START-PS-SPOOL}); these use PCL command procedures to poll the spooler directory contents, print any files found there, and then sleep awhile. This approach is considerably simpler than modifying \CN{LPTSPL}, although is does have a certain amount of polling overhead which can be reduced by making the sleep time longer. We have not found it objectionable in many months of use. Here is what the main part of our \TeX{} directory structure looks like: \begin{verbatim} APS: APS: APS: APS: APS: APS: APS: APS: APS: APS: APS: APS: APS: APS: SCRTCH: SCRTCH: SCRTCH: SCRTCH: SCRTCH: SCRTCH: SCRTCH: \end{verbatim} \subsection{\protect\VMS{} Setup} Our \VAX{} \VMS{} directory structure follows the Kellerman and Smith distribution, again with additional directories. \INDEX{Kellerman, David}{Kellerman, David} \INDEX{Smith, Barry}{Smith, Barry} The DVI driver family needs to have foreign command symbols created for each \FN{.exe} file. For example, you might put lines like this \begin{verbatim} $ DVIALW :== $SYS$TEX:[TEX]DVIALW.EXE \end{verbatim} in a command file referenced in \FNNX{SYS\$MANAGER:SYLOGIN.COM}. \INDEX{SYS$MANAGER:SYLOGIN.COM}{\FNNX{SYS\$MANAGER:SYLOGIN.COM}} Here is a display of the important command files, a directory tree, and the contents of two of the font directories. \begin{footnotesize} \begin{verbatim} type lib:[tex]define.com $ ! SYS$LIBROOT:[TEX]DEFINE.COM, Thu Dec 18 11:03:33 1986, Edit by BEEBE (at VAX -VMS) $ ! Make define/system after installation complete $ defsys :== define/nolog/system $ $ ! New version on PS: $ defsys sys$tex sys$libroot: $ $ ! Put [.amstex] and [.latex] first to override old stuff in [.inputs] $ defsys tex_inputs sys$tex:[tex.latex], - sys$tex:[tex.amstex], - sys$tex:[tex.inputs] $ defsys tex_fonts sys$tex:[tex.cm] $ defsys tex_formats sys$tex:[tex.formats] $ defsys tex_output texput type lib:[imprint]*.com SYS$LIBROOT:[IMPRINT]INSTALL.COM;6 $ !===================================================================== $ ! Install IMPRINT spooler on system (do only once) $ !===================================================================== $ define imp sys$libroot:[imprint] $ set command /tables=sys$library:dcltables - /output=sys$library:dcltables - imp:imprint.cld $ set process/privilege=cmkrnl $ library/replace/help sys$help:helplib imp:imprint.hlp $ run sys$system:install sys$library:dcltables/replace /exit $ define/system imp_formats sys$libroot:[imprint] $ define/system imp_fonts sys$libroot:[imprint.fonts] SYS$LIBROOT:[IMPRINT]SHUTIMAGEN.COM;2 $ !===================================================================== $ ! Shutdown the Imagen 8/300 queue $ !===================================================================== $ set noon $ stop /next /queue sys$imagen $ delete/queue sys$imagen $ set device /nospooled sys$imagen SYS$LIBROOT:[IMPRINT]STARTIMAGEN.COM;6 $ !===================================================================== $ ! Start IMPRINT spooler $ !===================================================================== $ define/system sys$imagen txa0: $ define/system imp_formats sys$libroot:[imprint] $ define/system imp_fonts sys$libroot:[imprint.fonts] $ reply/enable=printer $ set term sys$imagen - /permanent - /nowrap - /speed=19200 $ set device/spooled sys$imagen $ initialize /queue - /term - /proc=imprint - /default=(feed,flag) - /start - sys$imagen $ cd lib:[imprint] $ @mgr:dirtree Output File: tt: Your Directory Structure. One moment please... IMPRINT ^-----FONTS ^-----1200 ^-----1440 $ cd lib:[tex] $ @mgr:dirtree Output File: tt: Your Directory Structure. One moment please... TEX ^-----AM ^-----1000 ^-----1095 ^-----1200 ^-----1315 ^-----1440 ^-----1500 ^-----1643 ^-----1728 ^-----1800 ^-----2074 ^-----2160 ^-----2400 ^-----2488 ^-----2592 ^-----2628 ^-----2880 ^-----2986 ^-----3110 ^-----3456 ^-----3732 ^-----4479 ^-----AMSTEX ^-----BIBTEX ^-----CM ^-----100 ^-----1075 ^-----121 ^-----1290 ^-----145 ^-----1548 ^-----174 ^-----208 ^-----240 ^-----250 ^-----274 ^-----300 ^-----329 ^-----360 ^-----432 ^-----518 ^-----622 ^-----746 ^-----896 ^-----DOC ^-----FORMATS ^-----HP ^-----INPUTS ^-----LATEX ^-----LTXGDE ^-----ROCHESTER ^-----SVI ^-----TEX ^-----TEXWARE ^-----TRIP ^-----WEB $ dir tex_fonts Directory SYS$LIBROOT:[TEX.CM] 00HEXBIN.COM;3 00HEXCHK.COM;2 00RENAME.COM;2 00TEST.COM;2 100.DIR;1 1075.DIR;1 121.DIR;1 1290.DIR;1 145.DIR;1 1548.DIR;1 174.DIR;1 208.DIR;1 240.DIR;1 250.DIR;1 274.DIR;1 300.DIR;1 329.DIR;1 360.DIR;1 432.DIR;1 518.DIR;1 622.DIR;1 746.DIR;1 896.DIR;1 AMR10.TFM;1 CIRCLE10.TFM;1 CIRCLEW10.TFM;1 CMB10.TFM;1 CMBSY10.TFM;1 CMBX10.TFM;1 CMBX12.TFM;1 CMBX5.TFM;1 CMBX6.TFM;1 CMBX7.TFM;1 CMBX8.TFM;1 CMBX9.TFM;1 CMBXSL10.TFM;1 CMBXTI10.TFM;1 CMCSC10.TFM;1 CMDUNH10.TFM;1 CMDUNH10.TFMHEX;1 CMEX10.TFM;1 CMFF10.TFM;1 CMFIB8.TFM;1 CMINCH.TFM;1 CMMI10.TFM;1 CMMI12.TFM;1 CMMI5.TFM;1 CMMI6.TFM;1 CMMI7.TFM;1 CMMI8.TFM;1 CMMI9.TFM;1 CMMIB10.TFM;1 CMR10.TFM;1 CMR12.TFM;1 CMR17.TFM;1 CMR5.TFM;1 CMR6.TFM;1 CMR7.TFM;1 CMR8.TFM;1 CMR9.TFM;1 CMSL10.TFM;1 CMSL12.TFM;1 CMSL8.TFM;1 CMSL9.TFM;1 CMSLTT10.TFM;1 CMSS10.TFM;1 CMSS12.TFM;1 CMSS17.TFM;1 CMSS8.TFM;1 CMSS9.TFM;1 CMSSBX10.TFM;1 CMSSDC10.TFM;1 CMSSI10.TFM;1 CMSSI12.TFM;1 CMSSI17.TFM;1 CMSSI8.TFM;1 CMSSI9.TFM;1 CMSSQ8.TFM;1 CMSSQI8.TFM;1 CMSY10.TFM;1 CMSY5.TFM;1 CMSY6.TFM;1 CMSY7.TFM;1 CMSY8.TFM;1 CMSY9.TFM;1 CMTCSC10.TFM;1 CMTEX10.TFM;1 CMTEX8.TFM;1 CMTEX9.TFM;1 CMTI10.TFM;1 CMTI12.TFM;1 CMTI7.TFM;1 CMTI8.TFM;1 CMTI9.TFM;1 CMTT10.TFM;1 CMTT12.TFM;1 CMTT8.TFM;1 CMTT9.TFM;1 CMU10.TFM;1 CMVTT10.TFM;1 DOC.TFM;1 DUMMY.TFM;1 FONTTEST.COM;2 FONTTEST.LOG;1 FONTTEST.TEX;1 ICMEX10.TFM;1 ICMMI8.TFM;1 ICMSY8.TFM;1 ICMTT8.TFM;1 ILASY8.TFM;1 ILCMSS8.TFM;1 ILCMSSB8.TFM;1 ILCMSSI8.TFM;1 LASY10.TFM;1 LASY5.TFM;1 LASY6.TFM;1 LASY7.TFM;1 LASY8.TFM;1 LASY9.TFM;1 LASYB10.TFM;1 LCMSS8.TFM;1 LCMSSB8.TFM;2 LCMSSI8.TFM;1 LINE10.TFM;1 LINEW10.TFM;1 LOGO10.TFM;1 LOGO8.TFM;1 LOGO9.TFM;1 LOGOBF10.TFM;1 LOGOSL10.TFM;1 MANFNT.TFM;1 TESTFONT.COM;11 TESTFONT.LIS;1 Total of 133 files. $ dir sys$tex:[tex.cm.300] Directory SYS$LIBROOT:[TEX.CM.300] CIRCLE10.PK;2 CIRCLEW10.PK;2 CMB10.PK;2 CMBSY10.PK;2 CMBX10.PK;4 CMBX12.PK;2 CMBX5.PK;2 CMBX6.PK;2 CMBX7.PK;2 CMBX8.PK;2 CMBX9.PK;2 CMBXSL10.PK;2 CMBXTI10.PK;2 CMCSC10.PK;2 CMDUNH10.PK;2 CMEX10.PK;2 CMFF10.PK;2 CMFIB8.PK;2 CMINCH.PK;2 CMMI10.PK;2 CMMI12.PK;2 CMMI5.PK;2 CMMI6.PK;2 CMMI7.PK;2 CMMI8.PK;2 CMMI9.PK;2 CMMIB10.PK;2 CMR10.300GFHEX;1 CMR10.GF;1 CMR10.PK;3 CMR12.PK;2 CMR17.PK;2 CMR5.PK;2 CMR6.PK;2 CMR7.PK;2 CMR8.PK;2 CMR9.PK;2 CMSL10.PK;3 CMSL12.PK;2 CMSL8.PK;2 CMSL9.PK;2 CMSLTT10.PK;2 CMSS10.PK;2 CMSS12.PK;2 CMSS17.PK;2 CMSS8.PK;2 CMSS9.PK;2 CMSSBX10.PK;2 CMSSDC10.PK;2 CMSSI10.PK;2 CMSSI12.PK;2 CMSSI17.PK;2 CMSSI8.PK;2 CMSSI9.PK;2 CMSSQ8.PK;2 CMSSQI8.PK;2 CMSY10.PK;2 CMSY5.PK;2 CMSY6.PK;2 CMSY7.PK;2 CMSY8.PK;2 CMSY9.PK;2 CMTCSC10.PK;2 CMTEX10.PK;2 CMTEX8.PK;2 CMTEX9.PK;2 CMTI10.PK;2 CMTI12.PK;2 CMTI7.PK;2 CMTI8.PK;2 CMTI9.PK;2 CMTT10.PK;2 CMTT12.PK;2 CMTT8.PK;2 CMTT9.PK;2 CMU10.PK;2 CMVTT10.PK;2 LASY10.PK;2 LASY5.PK;4 LASY6.PK;2 LASY7.PK;2 LASY8.PK;2 LASY9.PK;2 LASYB10.PK;2 LINE10.PK;1 LINEW10.PK;1 LOGO10.PK;1 LOGO8.PK;1 LOGO9.PK;1 LOGOBF10.PK;1 LOGOSL10.PK;1 MANFNT.PK;1 Total of 92 files. \end{verbatim} \end{footnotesize} \section{Building the Drivers} With Version 2.07 of the DVI drivers, a public-domain implementation of the \UNIX{} \CN{make} utility is included with the distribution. This version of \CN{make} runs on all the operating systems currently supported for the DVI driver family, plus some others. In my view, \CN{make} ranks right next to compilers in importance. \UNIX{} users should usually be introduced to it at an early stage, but people unfamiliar with \UNIX{} may be unaware of it. The essential idea behind \CN{make} is that a user should not have to issue routine compile and link commands to build software, but instead, should be able to describe in a \FN{makefile} dependencies of files on other files, and rules for producing one file from another file, or group of files. For example, an object files depends on its corresponding source file, since if the source file is changed, the object file must be replaced by one from a fresh source compilation. The object file also depends on all the header files included by the source file, since if these are changed, recompilation is also in general necessary. However, a source file does {\em not\/} depend on its included files, since if they are changed, no changes to the source file are required. Supplementing the file dependency lists in the \FN{makefile} are a set of rules for converting one file type to another. The commoner ones are built-in to \CN{make} itself, but additional ones (or replacements for built-in rules) can be provided in the \FN{makefile}, both as defaults, and as specific rules to be used for certain files. By default, \CN{make} finds the first target file in the \FN{makefile}, then executes all the necessary rules to bring it up to date. Thus, as Stu Feldman, \INDEX{Feldman, Stu}{Feldman, Stu} the author of the original \CN{make} says, \begin{quote} It is usually easier to type the make command than to issue even one of the needed operations, so the typical cycle of program development operations becomes \begin{quote} think - edit - make - test . . . \end{quote} \end{quote} \FN{makefile}'s in general contain multiple targets, and one or more of these can be selected by name when \CN{make} is run. This makes it possible to store the commands for making all of the files in a given directory in a single file. For software stored in a directory tree, the \FN{makefile} at the top level can run \CN{make} in each of its subdirectories, and these in turn can run \CN{make} in their subdirectories, so a single top-level \CN{make} command can build an entire software system, like the complete \UNIX{} operating system. \FN{makefile}'s have been prepared for each of the host computers supported in the DVI family, and they are given filenames \FN{makefile.xxx}, where \FN{xxx} is the host name. You can just copy the desired one into \FN{makefile}, and type \CN{make} to build all of the drivers. The leading comments in each \FN{makefile} list all the targets that can be made by executing \CN{make}, and should be consulted for details. Here is the \FN{makefile} which typesets this document: \begin{footnotesize} \begin{verbatim} #----------------------------------------------------------------------- # Usage: # # make dviman # or # make dvidriver # or # make clean # # [17-Apr-87] #----------------------------------------------------------------------- LATEX = LaTeX \batchmode \input CP = copy .SUFFIXES: .SUFFIXES: .dvi .ltx .ids .idx .idx.ids: $(CP) $*.idx $*.id texidx $*.id $(RM) $*.id.* dviman: dviman.ltx $(LATEX) dviman.ltx dvidriver: dvidriver.ltx dvidriver.sty $(LATEX) dvidriver.ltx $(RM) dvidriver.dvi.* make dvidriver.ids $(LATEX) dvidriver.ltx make dvidriver.ids dvidriver.ids: dvidriver.idx clean: $(RM) *.dvi*.* $(RM) *.lst.* $(RM) *.aux.* \end{verbatim} \end{footnotesize} The first \verb|.SUFFIXES| clears the default file suffix list, and the second installs four suffixes in it. The rule for converting the output \FN{.idx} file from \LaTeX{} into the sorted input \FN{.ids} file is given following the line beginning \verb|.idx.ids|. It tells \CN{make} to copy the \FN{.idx} file to one with extension \FN{.id}, run the indexing program, and then delete the temporary copy. This rule is used when the target \verb|dvidriver.ids| is needed, as happens when the rules for \verb|dvidriver| are executed. By default, \CN{make} will process the \FN{dviman.ltx} file, since that target occurs first. The string \verb|$(LATEX)| requests a macro substitution of the symbol \verb|LATEX| which is defined earlier to run \LaTeX{} in batch mode. The \verb|clean| target is conventional in \FN{makefile}'s; it contains commands to delete unnecessary files in the directory, and is usually executed when work is completed. \section{Programming Conventions} \INDEX{programming conventions}{programming conventions} I am quite particular about readability and appearance of computer programs, because I spend much of my time reading and writing them. The previous sections have mentioned certain programming conventions, but it is useful to summarize them here, in the hope that they may prove a guide to implementors. Some of these rules are designed to facilitate code portability across compiler implementations and operating systems. They are usually not written down in books, though {\em A C Reference Manual\/}, Prentice-Hall(1985), by Samuel Harbison and Guy Steele, Jr., is a valuable work which every serious \C{} programmer should study and use. A second edition incorporating much of the proposed draft ANSI \C{} Standard was published in early 1987, \begin{itemize} \item Compound statements begin and end on separate lines, with opening and closing braces in the same column, and on their own lines. This makes visual brace matching much easier than it is with the common practice of placing the opening brace at the end of a previous line. \item Indentation nesting increases 4 spaces for each level. Spaces and tabs may be used for indentation, and tabs fill up to the next column which is a multiple of 8. \item Only one statement appears per line, with preprocessor macro definitions exempted from the rule, since a definition is required to fit on one line, even if it expands into several \C{} statements. \item Lines must never exceed 80 characters in length, in order that the software can be distributed as 80-character line images on magnetic tape. It is expected that software transported in this manner will be blank-trimmed on reading from the tape. The standard \C{} backslash-newline sequence can be used to break a long line; continuation occurs in column 1 of the next line if a string constant has been broken, and otherwise 4 characters right of the leftmost character of the first line of the continued statement. \item Type declarations should declare only one variable per statement, and that statement should have a brief comment describing the variable. \item Single statements controlled by a \C{} conditional, looping, or switch statement appear on separate lines, and are indented 4 characters to the right of the controlling statement. Complicated statements in this context should be converted to brace-delimited compound statements to enhance readability. \item Preprocessor symbols are entirely in upper-case letters. Variables are entirely in lower-case letters. \item If definition of a macro for some code sequence simplifies it, do so. \item Labels and \CN{goto} statements are not to be used. \item Preprocessor \CNNX{\#if}\INDEX{#if}{\CNNX{\#if}} constant expressions should be avoided if possible. If you require expressions, do not use the operators \verb=!=, \verb=||=, and \verb=&&=. This rule is occasioned by a \LATTICE{} \C{} misfeature. \item The only \C{} preprocessor statements to be used are \CNNX{\#include}\INDEX{#include}{\CNNX{\#include}}, \CNNX{\#define}\INDEX{#define}{\CNNX{\#define}}, \CNNX{\#undef}\INDEX{#undef}{\CNNX{\#undef}}, \CNNX{\#if}\INDEX{#if}{\CNNX{\#if}}, \CNNX{\#else}\INDEX{#else}{\CNNX{\#else}}, and \CNNX{\#endif}\INDEX{#endif}{\CNNX{\#endif}}. In particular, the useful, but commonly absent, \CNNX{\#elif}\INDEX{#elif}{\CNNX{\#elif}} may not be used, nor may \CNNX{\#if defined(var)}. \INDEX{#if defined(var)}{\CNNX{\#if defined(var)}}% \CNNX{\#ifdef}\INDEX{#ifdef}{\CNNX{\#ifdef}}, \CNNX{\#ifndef}\INDEX{#ifndef}{\CNNX{\#ifndef}}, and \CNNX{\#undef}\INDEX{#undef}{\CNNX{\#undef}} are discouraged. In the driver family, they are restricted to \FN{machdefs.h} where they are used to eliminate compiler ``macro redefinition'' warning messages. When \CNNX{\#undef}\INDEX{#undef}{\CNNX{\#undef}} is used, the programmer must be aware that this may not make the symbol undefined; only its most recent definition may disappear, with a previous definition now visible. \LATTICE{} \C{} uses this scheme. Fortunately, the draft ANSI \C{} Standard forbids this interpretation. \item Preprocessor statements must begin in column 1, and have no whitespace between the \CNNX{\#} and the following keyword. \item Tricks, like empty comments, for preprocessor symbol concatenation are forbidden; until the ANSI \C{} Standard becomes a reality and is widely implemented, there is no way to do this on many implementations. \item Substitution of preprocessor \CNNX{\#define}\INDEX{#define}{\CNNX{\#define}} arguments in quoted strings is forbidden, and no \CNNX{\#define} argument name may appear as a character string inside a quoted string. \item Type casts must be used for all assignments where the data types of the left and right sides differ, and for function arguments which do not match formal parameters. \item Function values which are discarded must be cast as \CNNX{(void)},\INDEX{void}{\CNNX{void}} unless the function has already been declared that way. \item All functions should be declared before the \CF{main} function. \item All functions must be {\em explicitly\/} typed, with \CN{void} used for those which do not return a value. \item The \CF{main} function should be given first, followed by function definitions in \X{alphabetical order}. \item Alphabetical ordering, with letter case ignored, should be adhered to in macro, variable, and function declarations, and in long sequences of independent assignment statements. \item Equivalence of pointers and integers must not be assumed; type casts must be employed on assignment. \item The standard \CN{NULL} pointer declared in \FN{stdio.h} should be cast to the requisite type and compared against, rather than assuming null pointers are zero. That is, write \CN{while (s != (char *)NULL)}, rather than \CN{while (s)}. \item Use preprocessor symbols instead of magic constants. \CN{if (c == ESC)} is more readable than \CN{if (c == 27)}. \item If a function returns a yes/no or true/false value, declare it as \CN{BOOLEAN} and use the symbols \CN{TRUE} and \CN{FALSE} instead of constants 1 and 0. \item Avoid the generic \CN{int} type when a more restricted type could be used instead, or when the result might require more than 16-bit precision. \item Follow the conventions for visible function headers used in the DVI driver family. \item \C{} has at least 28 precedence levels in expressions, which is far too many for a programmer to remember accurately. Use parentheses instead to say what you mean, and don't be afraid to use whitespace to improve readability. \item Use long variable names freely, but keep external symbols unique in their first {\em six\/} characters. File names, variable names, and preprocessor variables should be unique in their first {\em eight\/} characters. \item Avoid features of \C{} which are not widely implemented. These include the \CN{enum} type (preprocessor constants can simulate this), and functions returning \CN{struct}'s (return pointers to \CN{struct}'s instead). \item Functions with variable numbers of arguments are {\em not\/} to be used. \item If you have to resort to machine-dependent coding, use the \C{} preprocessor to select it. \item When possible, use compiler options and tools like the \UNIX{} \CN{lint} program to help track down potential problems in code. \item Finally, use comments regularly to document what the code is doing. A recent letter to the editor of the {\em Communications of the ACM\/} reported that fewer than 5\% of the lines of code in the entire \UNIX{} system are commented! \C{} is most definitely not a self-documenting language; in fact, Philippe Kahn, the developer of the fine Turbo Pascal system on the \IBMPC{}, calls \C{} a {\em write only\/} language. \end{itemize} \section{Implementation Problems} We have in several earlier sections remarked on problems encountered with particular operating systems and compilers. These are summarized in the following subsections. After insertion of included files by the \C{} Preprocessor, these drivers each amount to between 6500 and 8000 lines of code. Since this is contained in a single file, it tends to tax the \IBMPC{} compilers severely. \subsection{\protect\TOPS{}} Text files on \TOPS{} are stored as simple byte streams as they are in \UNIX{}, except that \CN{CR} \CN{LF} terminates a line, instead of just \CN{LF}. The \C{} run-time library will take care of translation between these two, but in order to be able to suppress the translation to compress \POSTSCRIPT{} output, which does not require the \CN{CR}, text files are opened in binary mode, and the \CF{NEWLINE} preprocessor macro is used to output the desired end-of-line sequence. ASCII is a 7-bit character set, and \TOPS{} normally stores text files as five 7-bit characters in each 36-bit word, with the rightmost (low-order) bit set to zero. In order to obtain 8-bit I/O, it is necessary to use \CF{open} instead of \CF{fopen}, so this is encapsulated in the function \CF{f20open}. The code references this only through the preprocessor macro \CN{BINARYOPEN}. With a little more thought in the implementation of the I/O library, it should have been possible to extend the arguments to \CF{fopen} to achieve this, so that \CN{stdin} and \CN{stdout} could be chosen to be 8-bit streams if desired. \KCC{} accepts an extended mode argument to \CF{fopen} to obtain binary files of particular byte sizes, but it does not permit binary I/O on the files \CN{stderr}, \CN{stdin}, and \CN{stdout}. External names in \TOPS{} are normally limited to 6 upper-case characters. Although the linker supports long case-insensitive external names, and both the \PASCAL{} and \N{Algol} compilers use them, \PCC{} does not. Consequently, \C{} programmers must take care to avoid long external names which are not unique in the first 6 characters, ignoring case. Neither does \PCC{} provide support for extended addressing in a 23-bit address space, instead of an 18-bit address space, like \N{Fortran} and \PASCAL{} do. The compiler does not store function traceback information, or generate a symbol table for local variables, nor does it employ the linker argument type blocks which have proved enormously useful in catching argument type and count mismatches at link time with other languages. This makes debugging tedious, and I admit to having become fairly adapt at visually uncompiling assembly code back into \C{} inside the \N{DDT} debugger. By default, the compiler splits the 18-bit address space into two, half for code and half for data. With the large bitmaps required by some of the drivers, this provided insufficient space for data, so I created some alternate library routines which increase the data space to $3/4$ of the address space. \PCC{} does not permit members of different structures to be given the same names; this was a minor annoyance in the definition of the \CN{font_entry} and \CN{font_list} structures which both contain the same object, but are forced to name it differently. The ugliest piece of code occasioned by \PCC{}'s deficiencies is the saving and restoring of the terminal state in functions \CF{initterm} and \CF{rsetterm} in \FN{dvibit.c}. The \CN{void} data type is not recognized by \PCC{}, but is so useful that I simply inserted a statement \CN{typedef int void;} in \FN{stdio.h}, making it available to everyone. As noted in the section on \FN{loadchar.h}, the compiler did not correctly handle a function reference of the type \begin{verbatim} (void)(*fontptr->charxx)(c,outrow); \end{verbatim} It also generated incorrect code for functions returning a \CN{struct}, but I was able to fix that problem in the compiler. It does not apply to the DVI driver family, but the \UNIX{} {\sc awk} utility makes heavy use of this feature. The \C{} preprocessor had a symbol table for only 1000 symbols, which is much too low for a file the size of \FN{monsym.h}, which defines all the symbols for operating system calls. For the DVI driver family, I merely selected a subset of these and installed them in \FN{machdefs.h}. However, for convenience in other programs, I rebuilt the preprocessor with a table size of 20000 to eliminate this problem. The maximum \CN{switch} table size was increased from 250 to 513. This makes it possible to compile \CN{switch} statements indexed by 8-bit and 9-bit bytes. This was essential to avoid ugly workarounds in \FN{prtpage.h}. Availability of the compiler and library source code has been essential in overcoming some of these problems, and in tracking down questionable behavior in the run-time library. Adding support for \KCC{} was straightforward, and the compiler has proved to be reliable, and the library quite close to \UNIX{}. As of April, 1987, it does not implement the Berkeley terminal handling facility provided by \CF{ioctl} and \CF{sgtty}. The \TWENTY{} \X{JSYS interface} provided by \KCC{} is similar to \PCC{}'s, but the symbol names are closer to the assembly language definitions. To reduce code duplication, one set of symbols is defined explicitly in terms of the others. Like \PCC{}, a complete \FN{monsym.h} proved to have too many symbols for \KCC{}, so for the DVI driver family, the needed values are defined explicitly in \FN{machdefs.h}. The \KCC{} developers have since linked an extended addressing version of the compiler which happily handles \FN{monsym.h}, and we now use that version for systems programming. One caveat for \KCC{} must be issued here. It stores character data as 9-bit values, and short integers as 18-bit values, both accessed with \TWENTY{} byte instructions. This produces compact data, but the current hardware microcode implementation of these instructions is slower than the fullword integer instructions, so the drivers compiled with \KCC{} run considerably slower than when compiled with \PCC{}, despite the generally superior code generation of the former. The well-known \CN{sieve} benchmark is about 4 times slower with byte instructions than with fullword integer instructions. \subsection{\protect\UNIX{} \protect\N{4.1BSD}} Like \PCC{}, \CN{cc} under \N{4.1BSD} \UNIX{} does not correctly handle the case of function reference to a structure member. Filenames are restricted to 14 characters in length, so output file extensions are \FN{.xxx} instead of \FN{.dvi-xxx}. Otherwise, the drivers compile without problems. We found that after completion of execution, and production of correct output, they die with a stack error in \CF{exit}. Attempts to debug this with \CN{sdb} were unsuccessful, because the debugger would step right into the stack error and crash. When the drivers are run under control of the assembly-level debugger, \CN{adb}, they complete normally! In February, 1987, we traced this to a \N{4.1BSD} \UNIX{} system bug. \CF{fclose} is called in \CF{abortrun} to close all font files, and it turned out that whenever one of the files passed to \CF{fclose} was already closed, the library would install a time bomb which blew up the code at exit. According to the manual page for \CF{fclose}, no action should be taken if the file is not already open. \CF{abortrun} has been revised to avoid calls to \CF{fclose} for such files, and the problem was been solved. \subsection{\protect\HPUX{}} No problems were encountered with \HPUX{} which is based on \N{AT\&T System V} \UNIX{}, with \N{4.2BSD} extensions. The version I used ran on a \N{Hewlett-Packard 9000/350} workstation. File names up to 1024 characters in length are supported, and up to 60 open files are permitted, so the only change was the addition of a preprocessor symbol \CN{HPUX} in \FN{machdefs.h} to select code defining the larger limits. % Future section: % SUN-OS (V.3) 1024 byte names, 30 open files \subsection{\protect\IBMPC{} \protect\LATTICE{} C} I have both versions 2.15a and 3.0 of the \LATTICE{} \C{} compiler running under \PCDOS{}, and have used version 2.15a extensively for graphics work. The major problem with this version is the limited overlap with the standard \UNIX{} run-time library. This has been largely remedied with version 3.0. However, both versions have proved singularly incapable of producing working versions of any of the drivers---the executable programs die with errors. Version 2.15a implements \CN{unsigned} as a type, meaning a 16-bit unsigned integer, rather than a type modifier. The original Kernighan \INDEX{Kernighan, Brian}{Kernighan, Brian} and Ritchie \INDEX{Ritchie, Dennis}{Ritchie, Dennis} definition is unclear, but the ANSI \C{} standard committee has made it clear that it is a legal modifier on any integer data type. I expect that this would have posed a problem in the drivers, particularly those parts which twiddle bits in the character rasters and output bitmaps. Type \CN{void} is not recognized, either, but that can be solved with a simple \CN{typedef} in \FN{typedefs.h}. Version 3.0 raises a fatal error when \CNNX{(void)}\INDEX{void}{\CNNX{void}} is used as a typecast on a function previously declared to be of type \CN{void}; it does not do so if \CN{void} is replaced by any other data type. This particular use occurs extensively throughout the drivers, so I have shelved further work with this version until \LATTICE{} fixes it. One attractive feature of version 3.0 is the addition of support for argument type checking according to the prescription in the coming ANSI \C{} standard. The \LATTICE{} compilers correctly handle large arrays, but in the interests of \X{efficiency}, the driver code selects a bitmap implementation using a vector of raster pointers for all \IBMPC{} compilers. \subsection{\protect\IBMPC{} \protect\WIZARD{} C} The \WIZARD{} \C{} compiler was attractive because of its claim to a high degree of compatibility with the \UNIX{} run-time library. The \WIZARD{} compiler correctly handles large arrays, but in the interests of \X{efficiency}, the driver code selects a bitmap implementation using a vector of raster pointers for all \IBMPC{} compilers. Unfortunately, it has been unable to compile any of the drivers without getting internal table overflows. Its diagnostics about variables possibly used before definition, or declared but not used, and about suspicious statements, like \CN{if (a = b) foo();} have nevertheless been quite useful as an alternative to the \UNIX{} \CN{lint} utility. With Version 3.0 of the \WIZARD{} compiler, the drivers will compile, but they run incorrectly. For example, the trivial loop in \CF{cppsfile()} in \FN{dvialw.c} which copies the macro header file to the output file returns random characters with \CF{getc} (as determined by setting an assembly level breakpoint immediately after the call to that function). \subsection{\protect\IBMPC{} \protect\MICROSOFT{} C} Version 3.0 of the \MICROSOFT{} \C{} compiler is claimed to be a completely new release, sharing a very high degree of compatibility with the \MICROSOFT{} \N{Xenix} compiler, and the \UNIX{} run-time library. The compiler implements the ANSI argument type checking language extensions and will even generate a set of function type declarations from a source file. The 600 or so pages of documentation is thorough and, at least in the library reference volume, quite readable. The volume of the use of the compiler could be improved---it is quite difficult to track down precisely what compiler options to use, because they are spread across dozens of pages of the manual. There is an on-line one-page summary available if you invoke the compiler with the help option. Error diagnostics are about as good (or bad) as any other \C{} compiler---generally just the line number and a short message. Unfortunately, the error recovery techniques are abysmal, and a single error is likely to propagate dozens, or even hundreds, of other errors, even across function boundaries, so it is frequently quite difficult to find the sick tree in the forest of output. Version 4.0 of the compiler does not have this problem. Like most \C{} compilers for the \N{Intel} microprocessor family, this compiler supports several memory models. However, its large memory model support, which is essential for this driver family, is fatally flawed. Unlike the \LATTICE{} and \WIZARD{} compilers, which provide alternatives to \CF{malloc} for the case of large memory allocations,% \footnote{\INDEX{footnotes}{footnotes}% Recall that \CF{malloc} is defined to have the memory size argument be an \CN{int}, rather than a \CN{long}, introducing a 32-Kbyte limitation when an \CN{int} is only 16 bits. The draft ANSI \C{} Standard defines the argument to \CF{malloc} to be of a new type, \CN{size_t}, which is returned by the \CN{sizeof} operator; this should provide a clean work-around. } \MICROSOFT{} provides no such function. Even worse, 32-bit pointers consisting of a 16-bit segment and 16-bit offset, are {\em by design handled incorrectly\/}. Arithmetic on such pointers operates only on the offset portion. This makes it impossible to reliably use the \CN{++} or \CN{-{}-} operators on such a pointer, because it could result in segment wrap. Version 4.0 of the compiler introduced a {\em huge\/} memory model which does not have this limitation. For these reasons, the bitmap representation as a vector of raster pointers had to be introduced, and a special function \CF{normaddr} defined in \FN{bitmap.h} to allow arithmetic on pointers. This design flaw in the compiler, which is quite intentional because it is documented in the manuals, is frankly unforgivable. Perfectly decent code in \CF{openfont} generated a fatal compiler error, and a workaround under control of the preprocessor had to be installed. Getting around these flaws has occasioned considerable extra work, but the compiler does succeed in producing compiled code, and Version 4.0 has provided a reliable implementation of the DVI driver family which has received heavy use locally. The one library bug that we have noted with Version 4.0 is incorrect handling of formats to \CF{sscanf}; for the page number range switch parsed in \FN{option.h}, it is necessary to supply a trailing colon (i.e. use {\tt -o7:9:} instead of {\tt -o7:9}). \section{Implementation Efficiency} \INDEX{efficiency}{efficiency} As the driver family has undergone continued development, virtually all of the code has been reexamined with a view to its run-time efficiency. Where reasonable, in-line code is generated by macros, pointer arithmetic is used in preference to array indexing, and heavily used variables are declared with the \CN{register} attribute. Since not much computation is required in any of the processing, one might expect the drivers to be I/O bound, and this indeed proves to be the case. As a sample of what might be expected, the \FN{dvitype.web} file was selected for processing. This file will be available at every \TeX{} site. Application of \WEAVE{} generates a .TEX file which produces 53 printed pages, and the following run-time results for the \PCC{} implementation on our DEC-20/60 may be of interest. \begin{center} \begin{tabular}{|l|r|r|} \hline Operation & CPU & Output Filesize\\ & (sec) & (kbytes)\\ \hline weave dvitype.web & 22 & 149\\ tex dvitype.tex & 127 & 239\\ dvialw dvitype (PXL fonts) & 65 & 818\\ dvialw dvitype (GF fonts) & 79 & \\ dvialw dvitype (PK fonts) & 70 & 817\\ dviprx dvitype (PXL fonts) & 114 & 2608\\ dviprx dvitype (GF fonts) & & \\ dviprx dvitype (PK fonts) & 290 & 2379\\ \hline \end{tabular} \end{center} The \CN{dvialw} results are the average of 3 runs which had a variance of about 5 sec. Clearly, the penalty for the more complex \FN{.gf} and \FN{.pk} font formats is not large -- about 20\% for \FN{.gf} fonts, and 8\% for \FN{.pk} fonts. Since the \FN{.pk} fonts average about half the disk space of the \FN{.gf} fonts, and \CN{dvialw} runs faster with \FN{.pk} fonts than with \FN{.gf} fonts, there is no reason to keep \FN{.gf} fonts on-line once they have been generated by \MF{} and converted by \CN{GFtoPK}. To further investigate the CPU usage inside the driver, I ran \CN{dvialw} and \CN{dviprx} under control of the run-time PC-histogram utility, \CN{pclook}. This produces a histogram of where the program is spending its time, based on samples of the \X{program counter} taken every 25 msec. The total number of samples taken ranged from 1600 to 2000. In general, the time was distributed in small percentages throughout most of the functions in \CN{dvialw}, but the following results are of interest: \begin{center} \begin{tabular}{|l|r|r|r|} \hline dvialw test & \FN{.pxl} & \FN{.pk} & \FN{.gf}\\ \hline JSYS (TOPS-20 Monitor) & 52\% & 55\% & 47\%\\ C run-time library & 15\% & 16\% & 16\%\\ \CN{printf} & 11\% & 10\% & 11\%\\ \CN{dvialw} (all functions) & 27\% & 25\% & 31\%\\ \CN{chargf} & & & 3\%\\ \CN{charpk} & & 1\% & \\ \CN{charpxl} & 0.2\% & & \\ \CN{setstr} & 10\% & 8\% & 8\%\\ \hline \end{tabular} \end{center} \begin{center} \begin{tabular}{|l|r|r|r|} \hline dviprx test & \FN{.pxl} & \FN{.pk} & \FN{.gf}\\ \hline JSYS (TOPS-20 Monitor) & 48\% & 61\% & \\ C run-time library & 4\% & 21\% & \\ \CN{printf} & 0.1\% & 1\% & \\ \CN{dviprx} (all functions) & 46\% & 18\% & \\ \CN{chargf} & & &\\ \CN{charpk} & & 0.1\% &\\ \CN{charpxl} & 0.1\% & & \\ \CN{dispchar} & 17\% & 5\% & \\ \CN{fontsub} & & 2\% & \\ \CN{prtbmap} & 17\% & 4\% & \\ \CN{setchar} & 3\% & 1\% & \\ \hline \end{tabular} \end{center} The time for \CN{printf} is included in the run-time library total, but for \CN{dvialw} it represents the largest use of any library function. \CN{dviprx} uses \CF{putc} for the output of its bitmap, rather than \CF{printf}. The \CF{charxx} functions are the ones which actually read the font raster information and unpack it for output to the device. It is surprising that so little of the total time is spent doing this work. \CF{setstr} accounts for the largest fraction of time of any function in \CN{dvialw}; it loops reading characters from the DVI file, calling \CF{charxx} to output them. Similarly, \CF{dispchar} and \CF{setchar} in \CN{dviprx} together account for 20\% of the time, and an almost equal amount of time is spent by \CF{prtbmap} converting the page bitmap into a character stream for the printer. From 50\% to 70\% of the total time is spent inside the run-times and the \TOPS{} operating system, putting it beyond control of the ordinary programmer. Since the major reason for calling the operating system and run-time library is for I/O, it is evident that host I/O efficiency is the dominant factor in the DVI translator, and few source code changes in DVI driver family could be made that would have any significant effect on the overall efficiency. \section{Implementation Summary} You will no doubt encounter problems I have not documented here if you implement this driver family under a new operating system or with a new compiler. As you make changes, remember that the goal is to reduce all future changes to settings of preprocessor variables in {\em one\/} file, {\tt machdefs.h}. Look there first, and make sure that the operating system and implementation symbols are properly defined for your system. Find out whether your compiler generates sign-propagating arithmetic right shifts, \INDEX{shifts}{shifts} or uses logical right shifts, and set \CN{ARITHRSHIFT} accordingly. According to the proposed ANSI \C{} Standard, right shifts of signed integers should propagate the sign bit, and right shifts of unsigned integers should propagate leading zero bits. This was implementation dependent in the original \C{} definition. The file \FN{00ARIT.C} can be compiled and run to test the behavior of shifts. Check the file name, extension, and directory path specifications, and modify them if necessary, preferably under control of a preprocessor \CNNX{\#if}\INDEX{#if}{\CNNX{\#if}} statement. Finally, document all problems and send your comments back to me. You can complain all you like about something I have done, but if you do not tell me, I cannot fix it, or explain why I did it that way. \newpage \begin{theindex} \renewcommand{\INDEX}[2]{} \renewcommand{\SUBINDEX}[3]{} \input{dvidriver.ids} \end{theindex} \end{document}