summaryrefslogtreecommitdiff
path: root/dviware/beebe/utils
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/beebe/utils
Initial commit
Diffstat (limited to 'dviware/beebe/utils')
-rw-r--r--dviware/beebe/utils/hd.c100
-rw-r--r--dviware/beebe/utils/lpt.ps147
-rw-r--r--dviware/beebe/utils/lptops.1l213
-rw-r--r--dviware/beebe/utils/lptops.c1860
-rw-r--r--dviware/beebe/utils/lptops.hlp169
-rw-r--r--dviware/beebe/utils/lw78.c753
-rw-r--r--dviware/beebe/utils/texidx.c1766
-rw-r--r--dviware/beebe/utils/texidx.hlp183
-rw-r--r--dviware/beebe/utils/unhd.c55
-rw-r--r--dviware/beebe/utils/vms/streamlf.fdl13
-rw-r--r--dviware/beebe/utils/vms/variable.fdl13
-rw-r--r--dviware/beebe/utils/ws87.pas45
-rw-r--r--dviware/beebe/utils/wsltex.c948
-rw-r--r--dviware/beebe/utils/wsltex.let72
-rw-r--r--dviware/beebe/utils/wsltex.pas537
-rw-r--r--dviware/beebe/utils/xref25
-rw-r--r--dviware/beebe/utils/xref1.awk56
-rw-r--r--dviware/beebe/utils/xref2.awk74
-rw-r--r--dviware/beebe/utils/xref3.awk83
-rw-r--r--dviware/beebe/utils/xxu.c172
20 files changed, 7284 insertions, 0 deletions
diff --git a/dviware/beebe/utils/hd.c b/dviware/beebe/utils/hd.c
new file mode 100644
index 0000000000..a4bc2a4359
--- /dev/null
+++ b/dviware/beebe/utils/hd.c
@@ -0,0 +1,100 @@
+/***********************************************************************
+Dump one or more files to stdout, translating unprintable characters to
+\ooo octal sequences, and starting newlines at each ESC, or when line
+length would exceed 72 characters.
+
+Usage:
+ hd filelist
+
+Both 7-bit and 8-bit input files are supported, and the output contains
+the file name and its last-write date at the top of the page.
+
+Outside of TOPS-20, it will be necessary to provide (possibly dummy)
+definitions of fileof() and timeof(), which are intended to return
+character strings containing the file name and last read or write time,
+given the file pointer.
+
+[15-Aug-87]
+
+***********************************************************************/
+
+#define MAXLINE 72
+#define COMMENT '!' /* marks start of comment to end-of-line */
+
+#include <stdio.h>
+
+char* fileof();
+char* timeof();
+void hd();
+
+FILE* tty;
+
+
+main(argc,argv)
+int argc;
+char* argv[];
+{
+ int k;
+
+ tty = stdout;
+ for (k = 1; k < argc; ++k)
+ hd(argv[k]);
+}
+
+void
+hd(filename)
+char* filename;
+{
+ register int c;
+ register FILE* fp;
+ register int hpos;
+
+ if ((fp = fopen(filename,"rb")) == (FILE*)NULL)
+ exit(2);
+
+ (void)fprintf(tty,"%c%s [%s]\n",
+ COMMENT,fileof(fileno(fp)),timeof(fileno(fp),"w"));
+
+ hpos = 0;
+ while ((c = getc(fp)) != EOF)
+ {
+ if ((c < 040) || (c > 0176) || (c == '\\') || (c == COMMENT))
+ { /* use octal encoding */
+ if (c == 033)
+ {
+ putc('\n',tty);
+ hpos = 0;
+ }
+ else if (hpos > (MAXLINE-4))
+ {
+ putc('\n',tty);
+ putc('\t',tty);
+ hpos = 8;
+ }
+
+ (void)fprintf(tty,"\\%03o",c);
+ hpos += 4;
+ if (c == '\n')
+ {
+ putc('\n',tty);
+ hpos = 0;
+ }
+ }
+ else /* printable character */
+ {
+ if (hpos > (MAXLINE-1))
+ {
+ putc('\n',tty);
+ putc('\t',tty);
+ hpos = 8;
+ }
+ putc(c,tty);
+ hpos++;
+ }
+ }
+ putc('\n',tty);
+ putc('\f',tty);
+
+ (void)fflush(tty);
+ (void)fclose(fp);
+}
diff --git a/dviware/beebe/utils/lpt.ps b/dviware/beebe/utils/lpt.ps
new file mode 100644
index 0000000000..51d751863a
--- /dev/null
+++ b/dviware/beebe/utils/lpt.ps
@@ -0,0 +1,147 @@
+%!PS-Adobe-1.0
+%%Title: printfile.ps
+%%Creator: Glenn Reid, Adobe Systems Incorporated
+%%CreationDate: Tue Apr 22 15:35:53 1986
+%%Pages: 0
+%% Copyright (c) 1986 Glenn Reid and Adobe Systems Incorporated.
+%% Use it, distribute it (with this message), but don't sell it.
+%%
+%%======================================================================
+%% Updated [06-Feb-88] by Nelson H.F. Beebe (beebe@science.utah.edu)
+%% to recognize formfeeds (Ctl-L) and expand horizontal tabs (Ctl-I)
+%% to the next column which is a multiple of 8.
+%%======================================================================
+%%
+%% This program will take miscellaneous text concatenated at its
+%% end and print it in some default font. It is designed to be
+%% minimal in its functionality, but flexible enough to be easily
+%% adapted to other uses.
+
+/in. {72 mul} def
+/line 512 string def % for input line buffering
+/buff 10 string def % for page number conversion
+
+%% CHANGE THESE IF YOU LIKE
+
+%% If any of these parameters are defined ahead of this file, then
+%% those values will be used. A typical way to use this is to
+%% allow an application to redefine some of the parameters by
+%% inserting definitions ahead of this file in the print stream.
+%% Examples of redefinitions look like:
+%%
+%% /fontname /Palatino-Roman def
+%% /pointsize /13 def
+%% /header (document.ps) def
+%% /pagenumber false def
+%% /leftmargin 36 def
+%%
+%% Any number (including 0) of these parameters may be defined to
+%% be different from the defaults. The defaults are quite
+%% reasonable for general use, and will print in 11-point Courier
+%% with a 12-point Courier-Bold header (only prints a header of
+%% /header string is defined by the user). Margins top, left and
+%% bottom are: .75 in., .75 in., and .5 in.
+%%
+%% Otherwise, the following defaults will be used:
+
+/leftmargin where not
+ { /leftmargin .75 in. def } {pop} ifelse
+/bottom where not
+ { /bottom .5 in. def } {pop} ifelse
+/startX where not
+ { /startX leftmargin def } {pop} ifelse
+/startY where not
+ { /startY 10 in. def } {pop} ifelse
+/fontname where not
+ { /fontname /Courier def } {pop} ifelse
+/pointsize where not
+ { /pointsize 11 def } {pop} ifelse
+/leading where not
+ { /leading pointsize 2 add def } {pop} ifelse
+/headerfontname where not
+ { /headerfontname /Courier-Bold def } {pop} ifelse
+/headerpointsize where not
+ { /headerpointsize 12 def } {pop} ifelse
+/headerfont
+ headerfontname findfont headerpointsize scalefont
+def
+/page where not
+ { /page 1 def } {pop} ifelse
+/pagenumber where not
+ { /pagenumber true def } {pop} ifelse
+
+% This routine will print a header at the top of each page
+/printheader {
+ gsave
+ currentdict /header known {
+ 36 10.5 in. moveto
+ headerfont setfont
+ header show
+ } if
+ pagenumber {
+ 8 in. 10.5 in. moveto
+ headerfont setfont
+ page buff cvs show
+ /page page 1 add def
+ } if
+ grestore
+ startX startY moveto
+} bind def
+
+/crlf {
+ leftmargin currentpoint exch pop % replace X with leftmargin
+ leading sub
+ dup bottom le
+ { pop pop showpage printheader }
+ { moveto } ifelse
+} bind def
+
+/printfile {
+ line readline % read a line from the file
+ { % 'if' procedure body (+boolean)
+ { % 'while' procedure body
+
+% ======================================================================
+% Add code to check for FF (and later, HT)
+ dup (\f) search
+ { pop pop pop showpage printheader } { pop } ifelse
+ /col 0 def
+ {
+ (\t) search
+% col := col + length(pre)
+% tab expands to padding string of (8 - and(col,7)) blanks
+
+ { % then: STACK = (post) (match) (pre) true
+ dup % (pre) (pre)
+ show % (pre)
+ length col add % col + length(pre)
+ /col exch def % col := col + length(pre)
+ 8 col 7 and sub % (8 - and(col,7))
+ dup % save for updating col
+ {( ) show} repeat % print tab expansion
+ col add /col exch def
+ pop % discard (match) == (HT)
+ } % end then part
+ { % else: STACK = (string) false
+ show exit % display string and exit untab loop
+ } % end else part
+ ifelse
+ } loop % exits when string printed
+ crlf
+% ======================================================================
+% show crlf % show what's left by readline
+ currentfile cvlit % use as operand
+ line readline % and read the next line
+ not {exit} if % exit if no more input to be had
+ } loop % end of while-proc
+ } if
+ showpage % when input file is exhausted
+} bind def % /printfile
+
+fontname findfont pointsize scalefont setfont
+
+printheader % execute header
+currentfile cvlit % uses rest of this file as input
+
+% everything following 'PrintFile' is treated as data, through EOF
+printfile
diff --git a/dviware/beebe/utils/lptops.1l b/dviware/beebe/utils/lptops.1l
new file mode 100644
index 0000000000..4e8e508dcc
--- /dev/null
+++ b/dviware/beebe/utils/lptops.1l
@@ -0,0 +1,213 @@
+.\".VA
+.TH LPTOPS 1L "3 May 1988"
+.ds Ps P\s-2OST\s+2S\s-2CRIPT\s+2
+.ds Ts T\s-2RAN\s+2S\s-2CRIPT\s+2
+.SH NAME
+lptops \- convert an ascii text file into a printable
+P\s-2OST\s+2S\s-2CRIPT\s+2 file
+.SH SYNOPSIS
+.B lptops
+\fB[-a] [-b\fP\0\fI#\fP\fB] [-c\fP\0\fInum\fP\fB] [-f\fP\0\fIfont\fP\fB] [-h] [-i\fP \fI#\fP\fB] [-l\fP\0\fI#\fP\fB] [-m\fP\0\fInum\fP\fB] [-n\fP\0[\fItb\fP][\fIlcr\fP]\fInum\fP\fB] [-o\fP\0[\fI#\fP]\fB] [-p\fP\0\fI#\fP\fB] [-r\fP\0\fI#\fP\fB] [-s\fP\0\fI
+num\fP\fB] [-t\fP\0\fI#\fP\fB] [-u]\fP < \fIinfile\fP > \fIoutfile\fP
+.sp 0.5
+.B lptops
+\fB[-a] [-b\fP\0\fI#\fP\fB] [-c\fP\0\fInum\fP\fB] [-f\fP\0\fIfont\fP\fB] [-h] [-i\fP\0\fI#\fP\fB] [-l\fP\0\fI#\fP\fB] [-m\fP\0\fInum\fP\fB] [-n\fP\0[\fItb\fP][\fIlcr\fP]\fInum\fP\fB] [-o\fP\0[\fI#\fP]\fB] [-p\fP\0\fI#\fP\fB] [-r\fP\0\fI#\fP\fB] [-s\fP\0\f
+Inum\fP\fB] [-t\fP\0\fI#\fP\fB] [-u]\fP \fIfile1\fP \fIfile2\fP ... > \fIoutfile\fP
+.SH DESCRIPTION
+.I Lptops
+converts normal text files into \*(Ps
+for printing on the Apple LaserWriter, or any other
+\*(Ps compatible printing device.
+It supports selection of a variety of fonts at arbitrary point sizes,
+margin specification, portrait and landscape page orientation, automatic
+page numbering, page outlining, and multi-column printing. It can also
+overstrike text (used by many text formatters for underlining).
+.PP
+This program is distributed with the <PLOT79> system. The \*(Ts system
+provides a program of similar intent, known as \fIenscript\fP(1L).
+.SH OPTIONS
+Letter case is ignored (except in the case of font codes).
+.TP
+.B \-a
+Turn Scribe-like bold and italic requests (@b[...] and @i[...]) into
+bold or italic text.
+.TP
+.B \-b #
+Set bottom margin to # (default is 1.0in).
+.TP
+.BI \-c " num"
+Print \fInum\fP copies of each page (default 1).
+.TP
+.BI \-f " font"
+Set \*(Ps font. The full name or an abbreviation for the
+desired font type is given as \fIfont\fP. Default is
+Courier. The following 13 fonts are available on all \*(Ps
+printers. The second column provides font abbreviations
+used by this and earlier versions of \fIlptops\fP; the third
+column contains \fIditroff\fP(1L) font abbreviations, and
+the fourth column, Adobe \*(Ts font abbreviations. Any of
+these abbreviations may be used to specify \fIfont\fP.
+.ta 0.25i 3.25i 4.25i 5.25i
+.nf
+ Courier C C C
+ Courier-Bold CB CB CB
+ Courier-BoldOblique CBO CD CD
+ Courier-Oblique CO CO CO
+ Helvetica H he he
+ Helvetica-Bold HB He He
+ Helvetica-BoldOblique HBO HE HE
+ Helvetica-Oblique HO hE hE
+ Symbol S S S
+ Times-Bold TB R ti
+ Times-BoldItalic TBI BI TI
+ Times-Italic TI I tI
+ Times-Roman T R ti
+.fi
+
+The remaining fonts are available only on enhanced printers, such as the
+Apple LaserWriter Plus.
+
+.nf
+ AvantGarde-Book AGB ag ag
+ AvantGarde-BookOblique AGBO aG aG
+ AvantGarde-Demi AGD Ag Ag
+ AvantGarde-DemiOblique AGDO AG AG
+ Bookman-Demi BD Bo Bo
+ Bookman-DemiItalic BDI BO BO
+ Bookman-Light BL bo bo
+ Bookman-LightItalic BLI bO bO
+ Helvetica-Narrow HN hn hn
+ Helvetica-Narrow-Bold HNB Hn Hn
+ Helvetica-Narrow-BoldOblique HNBO HN HN
+ Helvetica-Narrow-Oblique HNO hN hN
+ NewCenturySchlbk-Bold NCSB Nc Nc
+ NewCenturySchlbk-BoldItalic NCSBI NC NC
+ NewCenturySchlbk-Italic NCSI nC nC
+ NewCenturySchlbk-Roman NCSR nc nc
+ Palatino-Bold PB Pa Pa
+ Palatino-BoldItalic PBI PA PA
+ Palatino-Italic PI pA pA
+ Palatino-Roman PR pa pa
+.fi
+.PP
+Note that the \fIditroff\fP(1L) and \*(Ts abbreviations are identical
+except for the Courier and Times fonts. The \*(Ts abbreviations are
+based on two-letter mnemonics, where upper-case in the first letter
+indicates bold, and upper-case in the second letter indicates italic.
+.PP
+Only the Courier fonts are fixed-width fonts. The others are
+proportionally spaced and tabular material will not line up properly.
+The Courier fonts have a width equal to 0.6 of their point size, so to
+fill a line W inches wide with up to N characters, one must have point
+size <= (W/(0.6 * N * 72)) = (W*120)/N pt. Equivalently, with a point
+size P pt, the output spacing is 120/P char/inch.
+.TP
+.B \-h
+Use horizontal page orientation (landscape mode) instead of vertical
+(portrait mode).
+.TP
+.BI \-i #
+Set top margin to # for initial page (for use with letterhead)
+If not specified, the value given for the top margin will be used
+(see the \fB\-t\fP command).
+.TP
+.BI \-l #
+Set left margin to # (default is 1.0in).
+.TP
+.BI \-m num
+Produce multiple column output (\fInum\fP columns). In multiple
+column mode, formfeeds cause column breaks instead of page breaks.
+Default value of \fInum\fP is 1.
+.TP
+.B \-n [\fItb\fP][\fIlcr\fP]\fInum\fP
+Number output pages. The margin in which the number is placed can be
+selected by \fIt\fP (top) or \fIb\fP (bottom), and the position of the
+number can be further specified by \fIl\fP (left), \fIc\fP (center),
+or \fIr\fP (right). The number is placed by default in the center of
+the top margin, If \fInum\fP is given, start numbering with that
+value, and otherwise with 1. If an initial top margin value is given
+with the \fB-i\fP option, numbering will be omitted on the first page
+if it is at the top. Pages are unnumbered if this option is not
+specified.
+.TP
+.B \-o [\fI#\fP]
+Outline pages (and columns) with a line which is # units wide. A
+narrow line of 0.4pt width is assumed if # is omitted; this particular
+width is what TeX uses in typesetting.
+.TP
+.BI \-p #
+Set font point size (default 10bp). The baseline skip (spacing
+between successive character baselines) is conventionally chosen to be
+6/5 of this value, so that with 10bp type, we have 12bp between lines,
+or 6 lines/inch, the same as standard printer output.
+.TP
+.BI \-r #
+Set right margin to # (default is 1.0in).
+.TP
+.BI \-s num
+Use manual feed tray (special handling) for the first \fInum\fP pages
+of the output. If \fIN\fP multiple copies are in effect (see option
+\fB-c\fP), then \fIN*num\fP sheets must be fed manually. If \fInum\fP
+is omitted, then all pages are to be fed manually. Default value of
+\fInum\fP is 0.
+.TP
+.BI \-t #
+Set top margin to # (default value is 1.0in).
+.TP
+.B \-u
+Produce pages in unsorted (first to last) order instead of in sorted
+(page reversed) order; some \*(Ps printers have
+page handlers that stack the paper in this order. The default is to
+sort because this is appropriate for the most common
+\*(Ps printer, the Apple LaserWriter.
+.SH SPECIFICATION OF DIMENSIONAL VALUES
+In the switch descriptions above, physical dimensions described as # may
+be specified as a single number with an optional fractional part, and a
+required two-letter unit designator. Possible forms are:
+.LP
+.ta 0.25i 1.0i 4.0i
+.nf
+#.##bp big point (1in = 72bp) [Courier: 120.000/Pbp cpi]
+#.##cc cicero (1cc = 12dd) [Courier: 9.381/Pcc cpi]
+#.##cm centimeter [Courier: 4.233/Pcm cpi]
+#.##dd didot point (1157dd = 1238pt) [Courier: 112.569/Pdd cpi]
+#.##in inch [Courier: 1.667/Pin cpi]
+#.##mm millimeter (10mm = 1cm) [Courier: 42.333/Pmm cpi]
+#.##pc pica (1pc = 12pt) [Courier: 10.038/Ppc cpi]
+#.##pt point (72.27pt = 1in) [Courier: 120.450/Ppt cpi]
+#.##sp scaled point (65536sp = 1pt) [Courier: 7.893/(Psp/1000000) cpi]
+.fi
+.LP
+The bracketed values give the number of characters per inch (cpi) for a
+point size of P units with the fixed-width Courier font. For example,
+with point size 8bp, there are 120/8 = 15 characters per inch. With
+point size 1000000sp, there are 7.893 characters/inch.
+.SH FILES
+.TP 2.2i
+/usr/local/plot79/tex/dvi/lptops.c
+source code
+.TP
+/usr/local/plot79/lptops
+executable
+.TP
+/usr/local/plot79/define
+various environment definitions, an appropriate subset of which should
+be placed in the user's \fI.cshrc\fP or \fI.profile\fP file
+.SH "SEE ALSO"
+document (1L), drawit(1L), grapht(1L), graph3t(1L), pfort(1L),
+piechtt(1L), plot79-intro(1L), plot79(1L), pluto(1L), pretty(1L),
+rdinfo(1L), sf3(1L), slides(1L), tekalw(1L), tkvecs(1L), tmacro(1L),
+world(1L)
+.SH AUTHOR
+Nelson H.F. Beebe, Ph.D.
+.br
+Center for Scientific Computing
+.br
+South Physics Building
+.br
+University of Utah
+.br
+Salt Lake City, Utah 84112
+.br
+(Manual page by R. P. C. Rodgers, Computer Applications in Laboratory
+Medicine Project, UCSF, San Francisco, CA 94143).
diff --git a/dviware/beebe/utils/lptops.c b/dviware/beebe/utils/lptops.c
new file mode 100644
index 0000000000..0ece9ff313
--- /dev/null
+++ b/dviware/beebe/utils/lptops.c
@@ -0,0 +1,1860 @@
+/* -*-C-*- LPTOPS.C */
+/*-->lptops*/
+/**********************************************************************/
+/******************************* lptops *******************************/
+/**********************************************************************/
+
+/***********************************************************************
+
+NB: In order to handle overprinting of input of the form
+
+...text...<CR>...overtext...<CR><LF>
+
+this must be loaded with a special version of the C library I/O routine
+(PCC:IOCR.REL on the DEC-20) which permits reading and writing of <CR>.
+No special action need be taken on Unix systems, since <CR> is not
+filtered out, and is normally absent. On PC-DOS, open options of "rb"
+will usually be necessary (this is the default on all systems but
+TOPS-20).
+***********************************************************************/
+
+/***********************************************************************
+ Line printer file to PostScript converter
+ [03-Jul-85]
+ [12-Nov-85]
+ [07-Apr-86]
+ [03-May-88]
+
+lptops converts normal text files into PostScript for printing on the
+Apple LaserWriter, or any other PostScript-compatible printing device.
+It supports selection of a variety of fonts at arbitrary point sizes,
+margin specification, portrait and landscape page orientation, automatic
+page numbering, page outlining, and multi-column printing. It can also
+handle overstruck text used by many document formatters for underlining.
+
+Usage:
+
+ lptops [switches] <infile >outfile
+ lptops [switches] filelist >outfile
+
+In the switch descriptions below, physical dimensions described as # may
+be specified as a single number with an optional fractional part, and a
+required two-letter unit designator. Letter case is ignored. Possible
+forms are:
+
+#.##bp big point (1in = 72bp) [Courier: 120.000/Pbp cpi]
+#.##cc cicero (1cc = 12dd) [Courier: 9.381/Pcc cpi]
+#.##cm centimeter [Courier: 4.233/Pcm cpi]
+#.##dd didot point (1157dd = 1238pt)[Courier: 112.569/Pdd cpi]
+#.##in inch [Courier: 1.667/Pin cpi]
+#.##mm millimeter (10mm = 1cm) [Courier: 42.333/Pmm cpi]
+#.##pc pica (1pc = 12pt) [Courier: 10.038/Ppc cpi]
+#.##pt point (72.27pt = 1in) [Courier: 120.450/Ppt cpi]
+#.##sp scaled point (65536sp = 1pt) [Courier: 7.893/(Psp/1000000) cpi]
+
+The bracketed values give the number of characters per inch (cpi) for a
+point size of P units with the fixed-width Courier font. For example,
+with point size 8bp, there are 120/8 = 15 characters per inch. With
+point size 1000000sp, there are 7.893 characters/inch.
+
+The optional switches are (letter case is ignored):
+
+ -A Turn Scribe-like bold and italic requests (@b[...] and
+ @i[...]) into bold or italic text.
+
+ -B# Bottom margin of #.
+
+ -Cn Print n copies of each page.
+
+ -Ffontname
+ PostScript fontname. Possible values with acceptable
+ short abbreviations formed from the upper-case letters
+ in the font names, and the ditroff and Adobe TranScript
+ abbreviations are as follows. The first 13 are
+ available on all PostScript printers; the remainder are
+ available only on enhanced printers, such as the Apple
+ LaserWriter Plus.
+
+ ==================== ===== ====== ==========
+ full name short ditroff TranScript
+ ==================== ===== ====== ==========
+ Courier C C C
+ Courier-Bold CB CB CB
+ Courier-BoldOblique CBO CD CD
+ Courier-Oblique CO CO CO
+ Helvetica H he he
+ Helvetica-Bold HB He He
+ Helvetica-BoldOblique HBO HE HE
+ Helvetica-Oblique HO hE hE
+ Symbol S S S
+ Times-Bold TB R ti
+ Times-BoldItalic TBI BI TI
+ Times-Italic TI I tI
+ Times-Roman T R ti
+
+ AvantGarde-Book AGB ag ag
+ AvantGarde-BookOblique AGBO aG aG
+ AvantGarde-Demi AGD Ag Ag
+ AvantGarde-DemiOblique AGDO AG AG
+ Bookman-Demi BD Bo Bo
+ Bookman-DemiItalic BDI BO BO
+ Bookman-Light BL bo bo
+ Bookman-LightItalic BLI bO bO
+ Helvetica-Narrow HN hn hn
+ Helvetica-Narrow-Bold HNB Hn Hn
+ Helvetica-Narrow-BoldOblique HNBO HN HN
+ Helvetica-Narrow-Oblique HNO hN hN
+ NewCenturySchlbk-Bold NCSB Nc Nc
+ NewCenturySchlbk-BoldItalic NCSBI NC NC
+ NewCenturySchlbk-Italic NCSI nC nC
+ NewCenturySchlbk-Roman NCSR nc nc
+ Palatino-Bold PB Pa Pa
+ Palatino-BoldItalic PBI PA PA
+ Palatino-Italic PI pA pA
+ Palatino-Roman PR pa pa
+ ZapfChancery-MediumItalic ZCMI ZC ZC
+ ZapfDingbats ZD ZD ZD
+ ==================== ===== ====== ==========
+
+ The ditroff and TranScript abbreviations are the same,
+ except for the Courier and Times fonts. They are based
+ on two-letter mnemonics, where upper-case in the first
+ letter means bold, and upper-case in the second letter
+ means italic.
+
+ Only the Courier fonts are fixed-width like typewriter
+ and line printer fonts are. The others are proportional
+ spaced for improved readability, and consequently,
+ tabular material will not line up properly with them.
+ The Courier fonts have a width equal to 0.6 of their
+ point size, so to fill a line W inches wide with up to N
+ characters, one must have point size <= (W/(0.6 * N *
+ 72)) = (W*120)/N pt. Equivalently, with a point size P
+ pt, the output spacing is 120/P char/inch.
+
+ -H Horizontal page orientation (landscape mode) instead of
+ vertical page (portrait mode).
+
+ -I# Top margin of # for initial page (for letterheads); if
+ not specified, it will default to the value given for
+ the top margin by default or by the -T# command.
+
+ -L# Left margin of #.
+
+ -Mn Multiple column output (n columns). In multiple column
+ mode, formfeeds cause column breaks instead of page
+ breaks.
+
+ -N[tb][lcr]n
+ Number output pages. The number is placed by default in
+ the center of the top margin, but the margin can be
+ selected explicitly by t (top) or b (bottom), and the
+ position of the page number can be further specified by
+ l (left), c (center), or r (right). If n is given,
+ start numbering with that value, and otherwise with 1.
+ If an initial top margin value is given with the -I#
+ option, numbering will be omitted on the first page if
+ it is at the top. Pages are unnumbered if this option
+ is not specified.
+
+ -O[#] Outline pages (and columns) with a # units wide. A
+ narrow line of 0.4pt width is assumed if # is omitted;
+ this particular width is what TeX uses in typesetting.
+
+ -P# Font point size (default 10bp). The baseline skip
+ (spacing between successive character baselines) is
+ conventionally chosen to be 6/5 of this value, so that
+ with 10bp type, we have 12bp between lines, or 6
+ lines/inch, the same as standard printer output.
+
+ -R# Right margin of #.
+
+ -S[n] special handling (i.e. manual paper feed) for the first
+ n pages of the output. If N multiple copies are in
+ effect, then N*n sheets must be fed manually. If n is
+ omitted, then all pages are to be fed manually. For
+ example, -S1 is convenient to get the first page of a
+ letter on letterhead paper fed manually, with remaining
+ pages from the paper cassette.
+
+ -T# Top margin of #.
+
+ -U Output pages in unsorted (first to last) order instead
+ of in sorted (page reversed) order; some PostScript
+ printers have page handlers that stack the paper in this
+ order. The default is sorted because this is
+ appropriate for the most common PostScript printer, the
+ Apple LaserWriter.
+
+Defaults are:
+
+ -B1.0in -C1 -FCourier -L1.0in -M1 -P10bp -R1.0in -S0 -T1.0in
+
+
+Revision history (reverse time order):
+
+[03-May-88] Add ditroff and Adobe TranScript font abbreviations.
+
+[19-Apr-86] Change page/line status report from output in End_Page()
+ only to output in Beg_Page() and End_Column().
+
+[07-Apr-86] Fix some incorrect font names, put font names into
+ table, add font abbreviations and new font names, change
+ default font to Courier (because most printing expects
+ fixed-width fonts). Add usage message if bad options,
+ and print fontnames if bad font switch given. Allow
+ multiple filenames on command line instead of just using
+ stdin -- this added new function Do_File() and changed
+ argument lists of inchar() and Copy_Plist(). Add
+ save/restore around each page image following new 1986
+ PostScript Language Reference Manual recommendation, and
+ change multiple copies sequence from repeat loop to
+ setting of standard variable #copies. Add -U option for
+ unsorted output.
+
+[03-Feb-86] Fix setting of final entry of page_table[]. It should
+ only be done when End_Page() is called, since otherwise
+ Beg_Page() has already set the final entry, and we just
+ have an empty page to be discarded. Without this fix,
+ this left a hole (0), so the entire file got copied in
+ its entirety to the last page of the sorted file.
+
+[18-Jan-86] Add (void) to fprintf()/printf(), test for disk storage
+ full at end of page, add OUTSTR() macro using fputs()
+ instead of fprintf() for efficiency.
+
+[20-Dec-85] Change getchar() to inchar(); the latter supplies a
+ trailing LF at EOF in the event it is missing.
+ Otherwise, the output PostScript has two tokens
+ jammed together (P 1 {copypage} --> P1 {copypage})
+
+[20-Dec-85] Following recommendation of Allan Hetzel on LASER-LOVERS
+ ARPA BBOARD, added "() pop" at top of every page. This
+ is selected by the switch FIX31OCT85:
+
+ --------------------------------------------------------
+ From: Allan Hetzel <SYSAL%UKCC.BITNET@WISCVM.ARPA>
+ Subject: Re: Apple Laserwriter XON/XOFF problem
+ To: <LASER-LOVERS@WASHINGTON.ARPA>
+
+ The note posted to Laser-Lovers on Oct 28 by Joseph
+ Goldstone of Symbolics Cambridge Research Center was
+ helpful but I didn't try his suggested fix correctly and
+ so I called Adobe. They were very helpful (much more so
+ than Apple) and explained the problem and how to bypass
+ it.
+
+ My apologies to Adobe if this not an accurate
+ description of the problem. The problem apparently is
+ due to the PostScript interpreter getting confused by
+ what it thinks is an excess of white space characters.
+
+ The bypass is to place a special character (parenthesis,
+ bracket, brace, slash, etc.) to the right of some token,
+ but without an intervening white space character. As the
+ PostScript scanner reads the token it also reads the
+ special character which acts as a delimiter. The scanner
+ then has to back up one character so that it can
+ reprocess the special character after it has processed
+ the preceding token. During this backing up process a
+ number of internal values are recalculated, including
+ some pointer into the input buffer. This causes the
+ XON/XOFF protocol to work properly. Doing this once per
+ page seems to keep everybody happy.
+
+ Each page in the PostScript file built by our word
+ processing program is surrounded by a "save restore"
+ sequence. We changed the beginning save sequence
+ "/saveobj save def" to read "/saveobj save def() pop".
+ The "() pop" is effectively a no-op and we are assured
+ that the necessary recalculations are done on each page.
+ This seems to have corrected the problem completely.
+
+ Allan Hetzel (sysal@ukcc.bitnet)
+ --------------------------------------------------------
+
+[11-Dec-85] Fix problem with extra () around overstruck text.
+
+[13-Nov-85] Insert FASTIO conditional compilation option to speed up
+ page reversal. Under VAX 4.2BSD, fread() and fwrite()
+ are already fast enough, and need not be replaced.
+
+[12-Nov-85] Add reversal of pages, storing output on intermediate
+ file which is deleted before exiting.
+
+[02-Nov-85] Add code to write output on temporary file, then
+ retrieve in reverse page order and output on stdout.
+
+[30-Oct-85] Add code to handle overstruck lines:
+ ...text...<CR>...overtext...<CR><LF>
+ will appear as
+ (...text...) O
+ (...overtext...) P
+
+ Macro definitions and font selection now repeated
+ on each page to allow selective reprinting.
+
+[07-Oct-85] Add code to discard input NUL's from word-padded files,
+ since the LaserWriter prints them as blanks.
+
+[27-Sep-85] Added missing 'N' switch, fixed Page_Switch() (it scanned
+ beyond last digit of page number)
+
+[11-Jul-85] Original version.
+
+
+***********************************************************************/
+
+
+#ifndef OS_TOPS20
+#define OS_TOPS20 0
+#endif
+
+#ifndef KCC_20
+#define KCC_20 0
+#endif
+
+#ifndef PCC_20
+#define PCC_20 0
+#endif
+
+#if (KCC_20 | PCC_20)
+#ifndef OS_TOPS20
+#define OS_TOPS20 1
+#endif
+#endif
+
+#ifndef OS_VAXVMS
+#define OS_VAXVMS 0
+#endif
+
+#ifndef OS_ATARI
+#define OS_ATARI 0
+#endif
+
+#ifndef OS_PCDOS
+#define OS_PCDOS 0
+#endif
+
+#ifndef IBM_PC_AZTEC
+#define IBM_PC_AZTEC 0
+#endif
+
+#ifndef IBM_PC_LATTICE
+#define IBM_PC_LATTICE 0
+#endif
+
+#ifndef IBM_PC_MICROSOFT
+#define IBM_PC_MICROSOFT 0
+#endif
+
+#ifndef IBM_PC_WIZARD
+#define IBM_PC_WIZARD 0
+#endif
+
+#if (IBM_PC_AZTEC | IBM_PC_LATTICE | IBM_PC_MICROSOFT | IBM_PC_WIZARD)
+#ifndef OS_PCDOS
+#define OS_PCDOS 1
+#endif
+#endif
+
+#if (OS_ATARI | OS_TOPS20 | OS_PCDOS | OS_VAXVMS)
+#define OS_UNIX 0
+#else
+#define OS_UNIX 1
+#endif
+
+#if (OS_ATARI | PCC_20)
+#define DISKFULL(fp) ferror(fp) /* PCC-20 does not always set errno */
+#else
+#define DISKFULL(fp) (ferror(fp) && (errno == ENOSPC))
+#endif
+
+#if OS_VAXVMS
+#define EXIT vms_exit
+#else
+#define EXIT exit
+#endif
+
+#if IBM_PC_LATTICE
+typedef int void; /* Lattice C does not have this */
+#endif
+
+#if IBM_PC_MICROSOFT
+#define ANSI_PROTOTYPES 1
+#endif
+
+#ifndef ANSI_PROTOTYPES
+#define ANSI_PROTOTYPES 0
+#endif
+
+#ifndef ANSI_LIBRARY
+#define ANSI_LIBRARY 0
+#endif
+
+/*
+************************************************************************
+On TOPS-20, fread()/fwrite() are implemented as loops around
+getc()/putc() calls, and these in turn also do CR/LF translation. Calls
+to _read() and _write() translate into direct calls to the Monitor for
+fast efficient block I/O. FASTIO selects this option. It is used in
+Copy_Block when the temporary file is output in reverse page order to
+stdout.
+************************************************************************
+*/
+
+#if OS_TOPS20
+#if PCC_20
+#define FASTIO 1 /* TOPS-20 use only */
+#undef DISKFULL
+#define DISKFULL(fp) ferror(fp) /* PCC-20 does not always set errno */
+extern int strcmp();
+#endif
+#endif
+
+#define FIX31OCT85 1 /* Allan Hetzel's XON/XOFF fix */
+
+typedef int BOOLEAN;
+
+#define FALSE 0
+#define TRUE 1
+
+#ifndef FASTIO
+#define FASTIO 0
+#endif
+
+#define PXLID 0 /* used in inch.h */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+
+#if IBM_PC_MICROSOFT
+/* int errno; */ /* not in errno.h */
+#include <stdlib.h>
+#include <time.h>
+#endif
+
+#if OS_TOPS20
+#include <time.h>
+#endif
+
+#if FASTIO
+#include <file.h>
+#include <jsys.h>
+#include <mon_s.h>
+#endif
+
+#if (OS_TOPS20 | OS_UNIX | OS_VAXVMS | IBM_PC_AZTEC)
+#define FOPEN_W "w"
+#define FOPEN_R "r"
+#else
+#define FOPEN_W "wb"
+#define FOPEN_R "rb"
+#endif
+
+/***********************************************************************
+PostScript's basic units are big points (72bp = 1in). Everything in
+this routine works in terms of "Quite Small Units": 1 inch = QSU qsu.
+***********************************************************************/
+
+
+#define NUL '\0'
+
+#define QSU 100000L /* quite small units per inch -- */
+ /* should be large to avoid */
+ /* truncation error accumulation */
+
+#define INCH_TO_QSU(x) ((COORDINATE)(x * (float)QSU))
+ /* inch to QSU conversion */
+
+#define LEFT_X (left_margin + col_margin)
+#define BOT_Y (bottom_margin + col_margin)
+#define TOP_Y(margin) (page_height - (margin) - baseline_skip - col_margin)
+
+#if OS_TOPS20 /* want <CR><LF> */
+#define NEWLINE(fp) {(void)putc((char)'\r',fp);(void)putc((char)'\n',fp);}
+#else
+#define NEWLINE(fp) (void)putc((char)'\n',fp) /* want bare <LF> */
+#endif
+
+#define OUTCHAR(c) (void)putc((char)(c),tf)
+#define OUTOCTAL(c) (void)fprintf(tf,"\\%03o",(c))
+#define OUTSTR(s) (void)fputs(s,tf)
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define HEIGHT (11L * QSU) /* page height in QSU */
+#define MAXBLOCK 4096L /* block size for file copy */
+#define MAXLEN 256 /* font name length */
+#define MAXPAGE 1024 /* size of page location table */
+#define WIDTH ((85L * QSU)/10L) /* page width in QSU */
+#define COL_TWIDDLE 40L /* 1/fraction of column width for */
+ /* column margin */
+
+#define PAGE_T 001 /* flag bits for page_flag */
+#define PAGE_B 002
+#define PAGE_L 010
+#define PAGE_R 020
+#define PAGE_C 040
+
+#define TEMPFILE "lptops.tmp" /* temporary output file */
+
+
+ /* global functions */
+#if ANSI_PROTOTYPES
+int main(int ,char *[]);
+void Beg_Column(void);
+void Beg_Line(void);
+void Beg_Page(void);
+void Beg_Text(char);
+void Copy_Block(long ,long);
+void Copy_Plist(char, FILE *);
+void Do_File(FILE *);
+void End_Column(void);
+void End_Page(void);
+void End_Line(void);
+void End_Text(char);
+float inch(char *);
+int inchar(FILE *);
+void Page_Switch(char *);
+
+#if ANSI_LIBRARY
+int atoi(const char *);
+char* ctime(const time_t *);
+#else /* NOT ANSI_LIBRARY */
+int atoi(char *);
+char* ctime(long *);
+#endif /* ANSI_LIBRARY */
+
+char *cuserid(char *);
+void EXIT(int);
+char *getlogin(void);
+
+#if ANSI_LIBRARY
+void perror(const char *);
+char *strcpy(char *,const char *);
+int strcm2(char *,char *);
+size_t strlen(const char *);
+char *strncpy(char *,const char *,size_t);
+time_t time(time_t *);
+int unlink(const char *);
+#else /* NOT ANSI_LIBRARY */
+void perror(char *);
+char *strcpy(char *,char *);
+int strcm2(char *,char *);
+int strlen(char *);
+char *strncpy(char *,char *,int);
+long time(long *);
+int unlink(char *);
+#endif /* ANSI_LIBRARY */
+
+#else
+void Beg_Column();
+void Beg_Line();
+void Beg_Page();
+void Beg_Text();
+void Copy_Block();
+void Copy_Plist();
+void Do_File();
+void End_Column();
+void End_Page();
+void End_Line();
+void End_Text();
+float inch();
+int inchar();
+int main();
+void Page_Switch();
+
+int atoi();
+char *ctime();
+char *cuserid();
+void EXIT();
+char *getlogin();
+void perror();
+char *strcpy();
+int strcm2();
+int strlen();
+char* strncpy();
+long time();
+int unline();
+#endif
+
+typedef long COORDINATE; /* variables in QSU need >=32 bits */
+
+
+ /* global variables */
+
+FILE *tf; /* temporary output file */
+BOOLEAN bad_option; /* bad option flag */
+COORDINATE baseline_skip; /* inter-line spacing */
+COORDINATE bottom_margin; /* bottom margin width in QSU */
+int column; /* current text column (1..numcol) */
+COORDINATE col_margin; /* column margin (extra space */
+ /* between column borders in */
+ /* multi-column mode) */
+COORDINATE col_width; /* column width in QSU */
+int copies; /* number of copies of each page */
+BOOLEAN do_page_number; /* page numbering flag */
+char font_name[MAXLEN+1]; /* font name -- normal */
+char font_bold[MAXLEN+1]; /* font name -- bold */
+char font_italic[MAXLEN+1]; /* font name -- italic */
+BOOLEAN found; /* search flag */
+int in_col; /* input line column */
+int init_page_number; /* initial page number */
+COORDINATE init_top_margin; /* initial page top margin in QSU */
+BOOLEAN landscape_mode; /* horizontal landscape mode output */
+COORDINATE left_margin; /* left margin in QSU */
+int level; /* parenthesis level */
+int line_number; /* current line number */
+int manual_feed; /* manual feed page count */
+int numcol; /* number of text columns */
+COORDINATE outline; /* page and column outline linewidth */
+int page_flag; /* page number location flag */
+COORDINATE page_height; /* page height in QSU */
+int page_number; /* current page number */
+long page_table[MAXPAGE+1]; /* page location table (with space */
+ /* for extra entry marking EOF) */
+COORDINATE page_width; /* page width in QSU */
+COORDINATE point_size; /* font point size in big points */
+BOOLEAN reverse; /* page reversal flag */
+COORDINATE right_margin; /* right margin in QSU */
+BOOLEAN scribe; /* recognize bold/italic sequences */
+COORDINATE top_margin; /* top margin in QSU */
+COORDINATE x; /* current horizontal coordinate */
+COORDINATE y; /* current vertical coordinate */
+
+/***********************************************************************
+Built-in PostScript font tables. The first column in each list contains
+the full (case sensitive) PostScript names, the second column contains
+convenient short abbreviations which can be used in the command line
+-ffontname option, the third and fourth columns contain ditroff and
+Adobe TranScript abbreviations.
+
+The first four lines of entries are available on the regular
+LaserWriter, and the remainder are available only on the LaserWriter
+Plus.
+***********************************************************************/
+
+char* ps_normal[] =
+{
+ /* fullname short ditroff TranScript */
+ "Courier", "C", "C", "C",
+ "Helvetica", "H", "he", "he",
+ "Times-Roman", "T", "R", "ti",
+ "Symbol", "S", "S", "S",
+ "AvantGarde-Book", "AGB", "ag", "ag",
+ "AvantGarde-Demi", "AGD", "Ag", "Ag",
+ "Bookman-Demi", "BD", "Bo", "Bo",
+ "Bookman-Light", "BL", "bo", "bo",
+ "Helvetica-Narrow", "HN", "hn", "hn",
+ "NewCenturySchlbk-Roman", "NCSR", "nc", "nc",
+ "Palatino-Roman", "PR", "pa", "pa",
+ "ZapfChancery-MediumItalic", "ZCMI", "ZC", "ZC",
+ "ZapfDingbats", "ZD", "ZD", "ZD"
+};
+
+char* ps_bold[] =
+{
+ /* fullname short ditroff TranScript */
+ "Courier-Bold", "CB", "CB", "CB",
+ "Helvetica-Bold", "HB", "He", "He",
+ "Times-Bold", "TB", "B", "Ti",
+ "Symbol", "S", "S", "S",
+ "AvantGarde-Book", "AGB", "ag", "ag",
+ "AvantGarde-Demi", "AGD", "Ag", "Ag",
+ "Bookman-Demi", "BD", "Bo", "Bo",
+ "Bookman-Light", "BL", "bo", "bo",
+ "Helvetica-Narrow-Bold", "HNB", "Hn", "Hn",
+ "NewCenturySchlbk-Bold", "NCSB", "Nc", "Nc",
+ "Palatino-Bold", "PB", "Pa", "Pa",
+ "ZapfChancery-MediumItalic", "ZCMI", "ZC", "ZC",
+ "ZapfDingbats", "ZD", "ZD", "ZD"
+};
+
+char* ps_italic[] =
+{
+ /* fullname short ditroff TranScript */
+ "Courier-Oblique", "CO", "CO", "CO",
+ "Helvetica-Oblique", "HO", "hE", "hE",
+ "Times-Italic", "TI", "I", "tI",
+ "Symbol", "S", "S", "S",
+ "AvantGarde-BookOblique", "AGBO", "aG", "aG",
+ "AvantGarde-DemiOblique", "AGDO", "AG", "AG",
+ "Bookman-DemiItalic", "BDI", "BO", "BO",
+ "Bookman-LightItalic", "BLI", "bO", "bO",
+ "Helvetica-Narrow-Oblique", "HNO", "hN", "hN",
+ "NewCenturySchlbk-Italic", "NCSI", "nC", "nC",
+ "Palatino-Italic", "PI", "pA", "pA",
+ "ZapfChancery-MediumItalic", "ZCMI", "ZC", "ZC",
+ "ZapfDingbats", "ZD", "ZD", "ZD"
+};
+
+char* ps_both[] =
+{
+ /* fullname short ditroff TranScript */
+ "Courier-BoldOblique", "CBO", "CD", "CD",
+ "Helvetica-BoldOblique", "HBO", "HE", "HE",
+ "Times-BoldItalic", "TBI", "BI", "TI",
+ "Symbol", "S", "S", "S",
+ "AvantGarde-BookOblique", "AGBO", "aG", "aG",
+ "AvantGarde-DemiOblique", "AGDO", "AG", "AG",
+ "Bookman-DemiItalic", "BDI", "BO", "BO",
+ "Bookman-LightItalic", "BLI", "bO", "bO",
+ "Helvetica-Narrow-BoldOblique", "HNBO", "HN", "HN",
+ "NewCenturySchlbk-BoldItalic", "NCSBI","NC", "NC",
+ "Palatino-BoldItalic", "PBI", "PA", "PA",
+ "ZapfChancery-MediumItalic", "ZCMI", "ZC", "ZC",
+ "ZapfDingbats", "ZD", "ZD", "ZD"
+};
+
+
+#define PS_DEFAULT 0 /* index of default font in ps_normal[] */
+#define MAXFONT (sizeof(ps_normal)/sizeof(char *)) /* size of font table */
+
+
+int
+main(argc,argv)
+int argc;
+char* argv[];
+{
+ register int k; /* loop index */
+ register char *p; /* temporary pointer */
+ register int m,n; /* loop indices */
+ FILE *fp; /* input file pointer */
+ char timestr[27]; /* result of ctime() */
+ long timeval; /* result of time() */
+ long last,next; /* result of fseek() for */
+ /* page_table[] construction */
+ int (*compare)();
+
+ /* establish defaults for all parameters */
+ bottom_margin = 1L * QSU;
+ column = 1;
+ col_margin = 0L;
+ copies = 1;
+ do_page_number = FALSE;
+ init_page_number = 1;
+ init_top_margin = -1; /* negative value flags unset state */
+ in_col = 0;
+ landscape_mode = FALSE;
+ left_margin = 1L * QSU;
+ manual_feed = 0;
+ numcol = 1;
+ outline = 0L;
+ page_height = HEIGHT;
+ page_number = init_page_number;
+ page_width = WIDTH;
+ point_size = INCH_TO_QSU(inch("10bp"));
+ reverse = TRUE;
+ right_margin = 1L * QSU;
+ scribe = FALSE;
+ top_margin = 1L * QSU;
+
+ strcpy(font_name,ps_normal[PS_DEFAULT]);
+ strcpy(font_bold,ps_bold[PS_DEFAULT]);
+ strcpy(font_italic,ps_italic[PS_DEFAULT]);
+
+ bad_option = FALSE;
+ for (k = 1; k < argc; ++k)
+ {
+ p = argv[k];
+ if (argv[k][0] == '-')
+ {
+ switch(argv[k][1])
+ {
+ case 'a':
+ case 'A':
+ scribe = TRUE;
+ break;
+
+ case 'b':
+ case 'B':
+ bottom_margin = INCH_TO_QSU(inch(&argv[k][2]));
+ break;
+
+ case 'c':
+ case 'C':
+ copies = atoi(&argv[k][2]);
+ break;
+
+ case 'f':
+ case 'F':
+ (void)strncpy(font_name,&argv[k][2],MAXLEN);
+ font_name[MAXLEN] = '\0';
+ found = FALSE;
+ for (n = 0; n < MAXFONT; n += 4)
+ {
+ for (m = 3; m >= 0; --m)
+ {
+ /* compare case-sensitive ditroff and TranScript
+ names before case-insensitive ones */
+ compare = (m > 1) ? strcmp : strcm2;
+ if ((*compare)(font_name,ps_normal[n+m]) == 0)
+ {
+ strcpy(font_name,ps_normal[n]);
+ strcpy(font_bold,ps_bold[n]);
+ strcpy(font_italic,ps_italic[n]);
+ found = TRUE;
+ break;
+ }
+ else if ((*compare)(font_name,ps_bold[n+m]) == 0)
+ {
+ strcpy(font_name,ps_bold[n]);
+ strcpy(font_bold,ps_bold[n]);
+ strcpy(font_italic,ps_italic[n]);
+ found = TRUE;
+ break;
+ }
+ else if ((*compare)(font_name,ps_italic[n+m]) == 0)
+ {
+ strcpy(font_name,ps_italic[n]);
+ strcpy(font_bold,ps_both[n]);
+ strcpy(font_italic,ps_normal[n]);
+ found = TRUE;
+ break;
+ }
+ else if ((*compare)(font_name,ps_both[n+m]) == 0)
+ {
+ strcpy(font_name,ps_both[n]);
+ strcpy(font_bold,ps_italic[n]);
+ strcpy(font_italic,ps_normal[n]);
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ if (!found)
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,
+ "?Illegal font name [%s]. Possible values are:",
+ font_name);
+ NEWLINE(stderr);
+
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"Normal fonts");
+ NEWLINE(stderr);
+ for (m = 0; m < MAXFONT; m += 4)
+ {
+ (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
+ ps_normal[m],ps_normal[m+1],ps_normal[m+2],
+ ps_normal[m+3]);
+ NEWLINE(stderr);
+ }
+
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"Bold fonts");
+ NEWLINE(stderr);
+ for (m = 0; m < MAXFONT; m += 4)
+ {
+ (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
+ ps_bold[m],ps_bold[m+1],ps_bold[m+2],
+ ps_bold[m+3]);
+ NEWLINE(stderr);
+ }
+
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"Oblique/Italic fonts");
+ NEWLINE(stderr);
+ for (m = 0; m < MAXFONT; m += 4)
+ {
+ (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
+ ps_italic[m],ps_italic[m+1],ps_italic[m+2],
+ ps_italic[m+3]);
+ NEWLINE(stderr);
+ }
+
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"BoldOblique/BoldItalic fonts");
+ NEWLINE(stderr);
+ for (m = 0; m < MAXFONT; m += 4)
+ {
+ (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
+ ps_both[m],ps_both[m+1],ps_both[m+2],
+ ps_both[m+3]);
+ NEWLINE(stderr);
+ }
+ NEWLINE(stderr);
+ bad_option = TRUE;
+ }
+ break;
+
+ case 'h':
+ case 'H':
+ landscape_mode = TRUE;
+ break;
+
+ case 'i':
+ case 'I':
+ init_top_margin = INCH_TO_QSU(inch(&argv[k][2]));
+ break;
+
+ case 'l':
+ case 'L':
+ left_margin = INCH_TO_QSU(inch(&argv[k][2]));
+ break;
+
+ case 'm':
+ case 'M':
+ numcol = atoi(&argv[k][2]);
+ break;
+
+ case 'n':
+ case 'N':
+ Page_Switch(&argv[k][1]);
+ break;
+
+ case 'o':
+ case 'O':
+ if (argv[k][2]) /* have -O# */
+ outline = INCH_TO_QSU(inch(&argv[k][2]));
+ else /* have -O, so give default */
+ outline = INCH_TO_QSU(inch("0.4pt")); /* from TeX */
+ break;
+
+ case 'p':
+ case 'P':
+ point_size = INCH_TO_QSU(inch(&argv[k][2]));
+ break;
+
+ case 'r':
+ case 'R':
+ right_margin = INCH_TO_QSU(inch(&argv[k][2]));
+ break;
+
+ case 's':
+ case 'S':
+ if (argv[k][2]) /* have count field */
+ manual_feed = atoi(&argv[k][2]);
+ else /* omitted count ==> large number */
+ manual_feed = 32767;
+ break;
+
+ case 't':
+ case 'T':
+ top_margin = INCH_TO_QSU(inch(&argv[k][2]));
+ break;
+
+ case 'u':
+ case 'U':
+ reverse = FALSE;
+ break;
+
+ default:
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Unrecognized option [%s]",p);
+ NEWLINE(stderr);
+ bad_option = TRUE;
+ }
+ }
+ }
+
+ if (bad_option)
+ {
+ (void)fprintf(stderr,
+ "Usage: %s -A -B# -Cn -Ffontname -H -I# -L# -Mn -N[tb][lcr]n \
+-O[#] -P# -R# -S[n] -T# -U filelist >outfile",argv[0]);
+ NEWLINE(stderr);
+
+ (void)fprintf(stderr,"Default options: -B1.0in -C1 -FCourier -L1.0in \
+-M1 -P10bp -R1.0in -S0 -T1.0in");
+ NEWLINE(stderr);
+
+ EXIT(1);
+ }
+
+
+ if (reverse)
+ {
+ if ((tf = fopen(TEMPFILE,FOPEN_W)) == (FILE *)NULL)
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Cannot open temporary file [%s]",TEMPFILE);
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+ }
+ else
+ tf = stdout;
+
+ /*******************************************************************
+ Make the PostScript File Structure header according to Version 1.0,
+ First Edition (January 1985) of the PostScript File Structuring
+ Conventions manual. We add one additional field at the end after
+ the %%Pages: n field:
+
+ %%PageTable: m1 n1 p1 ... mk nk pk
+
+ where the triples (mj nj pj) contain the page number pair (mj nj)
+ like the field
+
+ %%Page: mj nj
+
+ and pj is the byte position in the file of the beginning of that
+ "%%Page" command. A spooler can then easily position to arbitrary
+ pages in the file for reprinting.
+ *******************************************************************/
+
+ OUTSTR("%!PS-Adobe-1.0"); /* magical file header */
+ NEWLINE(tf);
+
+ OUTSTR("%%DocumentFonts: ");
+ OUTSTR(font_name); /* only use one font */
+ NEWLINE(tf);
+
+ OUTSTR("%%Dimensions: 0 0 612 792"); /* 8.5 x 11 inch page size */
+ NEWLINE(tf);
+
+ OUTSTR("%%Title:"); /* this contains our command line */
+ for (k = 0; k < argc; ++k)
+ {
+ OUTCHAR(' ');
+ OUTSTR(argv[k]);
+ }
+ NEWLINE(tf); /* end of %%Title line */
+
+ timeval = time((long *)NULL);
+ strcpy(timestr,ctime(&timeval));
+ k = strlen(timestr) - 1; /* ctime has its own \n */
+ timestr[k] = NUL; /* so kill it */
+ OUTSTR("%%CreationDate: ");
+ OUTSTR(timestr);
+ NEWLINE(tf);
+
+ /* Under TOPS-20, JSYS GFUST% cannot be used to obtain file owner string
+ of a terminal file, which stdout always is, so just use job login name */
+
+ OUTSTR("%%Creator: ");
+ if (cuserid((char*)NULL) != (char*)NULL)
+ OUTSTR(cuserid((char*)NULL));
+ NEWLINE(tf);
+
+ OUTSTR("%%Pages: (atend)");
+ NEWLINE(tf);
+ OUTSTR("%%EndComments");
+ NEWLINE(tf);
+ OUTSTR("save"); /* has matching "restore" at end */
+ NEWLINE(tf);
+ OUTSTR("%%EndProlog");
+ NEWLINE(tf);
+
+ /* validate input settings */
+ copies = MAX(1,copies);
+ numcol = MAX(1,numcol);
+ point_size = MAX(INCH_TO_QSU(inch("3bp")),point_size);
+ if (point_size > INCH_TO_QSU(0.25))
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,
+ "%warning -- font point size > 18pt is unusually large!");
+ NEWLINE(stderr);
+ }
+ outline = MAX(0L,outline);
+
+ if (landscape_mode) /* switch sizes for landscape mode */
+ {
+ page_height = WIDTH;
+ page_width = HEIGHT;
+ }
+ if (((left_margin + right_margin) >= page_width) ||
+ ((top_margin + bottom_margin) >= page_height) ||
+ ((init_top_margin + bottom_margin) >= page_height))
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Margin values too large for page");
+ NEWLINE(stderr);
+ EXIT(1);
+ }
+
+ col_width = (page_width - left_margin - right_margin)/numcol;
+ col_margin = ((numcol == 1) && (outline == 0)) ?
+ 0L : (col_width/COL_TWIDDLE);
+
+ /* TeX's baselineskip is 12pt for 10pt type; we preserve the same ratio */
+ baseline_skip = (point_size * 12L) / 10L;
+
+ m = 0; /* count of file names */
+ for (k = 1; k < argc; ++k)
+ {
+ if (*argv[k] != '-')
+ {
+ m++; /* count file name */
+ if ((fp = fopen(argv[k],FOPEN_R)) != (FILE *)NULL)
+ {
+ Do_File(fp);
+ (void)fclose(fp);
+ }
+ else
+ {
+ (void)fprintf(stderr,"?Open failure on [%s] -- file skipped",
+ argv[k]);
+ NEWLINE(stderr);
+ }
+ }
+ }
+ if (m == 0)
+ Do_File(stdin);
+
+ if (reverse)
+ {
+ /* Now close the temporary file and reopen for input, then transfer */
+ /* complete pages in reverse order to stdout using large blocks */
+
+ if (fclose(tf))
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Close failure on temporary file [%s]",
+ TEMPFILE);
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+
+ if ((tf = fopen(TEMPFILE,FOPEN_R)) == (FILE *)NULL)
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Cannot reopen temporary file [%s]",TEMPFILE);
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"[Reversing pages");
+ Copy_Block(0L,page_table[0]-1); /* first page is file header stuff */
+ last = page_table[MIN(MAXPAGE,page_number-init_page_number+1)];
+ for (k = MIN(MAXPAGE,page_number-init_page_number+1)-1; k >= 0; --k)
+ { /* copy remainder in reverse order */
+ (void)putc('.',stderr);
+ next = (long)ftell(stdout);
+ Copy_Block(page_table[k],last-1);
+ last = page_table[k];
+ page_table[k] = next;
+ }
+ (void)putc(']',stderr);
+ if (fclose(tf))
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Close failure on temporary file [%s]",
+ TEMPFILE);
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+
+ unlink(TEMPFILE); /* delete the temporary file */
+ }
+ /* add file trailer stuff */
+
+ tf = stdout; /* so OUTSTR() macro works */
+
+ OUTSTR("%%Trailer");
+ NEWLINE(stdout);
+ OUTSTR("restore"); /* matches "save" in prolog */
+ NEWLINE(stdout);
+ (void)printf("%%%%Pages: %d",page_number-init_page_number);
+ NEWLINE(stdout);
+ OUTSTR("%%PageTable: ");
+ for (k = 0; k < MIN(MAXPAGE,page_number-init_page_number+1); ++k)
+ (void)printf(" %d %d %ld",init_page_number+k,init_page_number+k,
+ page_table[k]);
+ NEWLINE(stdout);
+ if (putchar('\004') == EOF) /* CTL-D for EOF signal */
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Output error -- disk storage probably full");
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+ (void)fprintf(stderr," [ok]");
+ NEWLINE(stderr);
+ EXIT(0);
+ return (0); /* keep lint and compilers happy */
+}
+
+void
+Beg_Column()
+{
+ (void)fprintf(tf,"%ld %ld moveto",x,y);
+ NEWLINE(tf);
+}
+
+void
+Beg_Line()
+{
+ if (scribe)
+ {
+ OUTCHAR('S');
+ OUTCHAR(' ');
+ }
+}
+
+void
+Beg_Page()
+{
+ int k;
+
+ column = 1;
+ (void)fflush(tf);
+ k = page_number-init_page_number;
+ if (k < MAXPAGE)
+ page_table[k] = (long)ftell(tf);
+ (void)fprintf(tf,"%%%%Page: %d %d",k+1,page_number);
+ NEWLINE(tf);
+ OUTSTR("save"); /* will be matched by "restore" from End_Page() */
+ NEWLINE(tf);
+ if (scribe)
+ {
+ (void)fprintf(tf,"/B {/%s findfont %ld scalefont setfont} def",
+ font_bold,point_size);
+ NEWLINE(tf);
+
+ (void)fprintf(tf,"/E {grestore 0 %ld rmoveto} def",
+ -baseline_skip); /* End of line */
+ NEWLINE(tf);
+
+ (void)fprintf(tf,"/I {/%s findfont %ld scalefont setfont} def",
+ font_italic,point_size);
+ NEWLINE(tf);
+
+ (void)fprintf(tf,"/N {/%s findfont %ld scalefont setfont} def",
+ font_name,point_size);
+ NEWLINE(tf);
+
+ OUTSTR("/O {gsave show grestore} def"); /* OverPrint macro */
+ NEWLINE(tf);
+
+ OUTSTR("/S {gsave} def"); /* Start of line */
+ NEWLINE(tf);
+
+ OUTSTR("/W {show} def"); /* show text */
+ NEWLINE(tf);
+ }
+ else
+ {
+ OUTSTR("/O {gsave show grestore} def"); /* OverPrint macro */
+ NEWLINE(tf);
+
+ (void)fprintf(tf,"/P {gsave show grestore 0 %ld rmoveto} def",
+ -baseline_skip); /* Print macro */
+ NEWLINE(tf);
+
+ (void)fprintf(tf,"/N {/%s findfont %ld scalefont setfont} def",
+ font_name,point_size);
+ NEWLINE(tf);
+ }
+ (void)fprintf(tf,"72 %ld div 72 %ld div scale",QSU,QSU);
+ NEWLINE(tf);
+ OUTCHAR('N'); /* select normal font */
+
+#if FIX31OCT85
+ OUTSTR("()pop"); /* no-op for XON/XOFF bug workaround */
+#endif
+
+ NEWLINE(tf);
+
+ if (landscape_mode)
+ {
+ (void)fprintf(tf,"%ld %ld translate",0L,HEIGHT);
+ NEWLINE(tf);
+ OUTSTR("-90 rotate");
+ NEWLINE(tf);
+ }
+ (void)fprintf(stderr,
+ " [%d",page_number); /* begin [p.l.l...] status report */
+}
+
+void
+Beg_Text(c)
+char c;
+{
+ if (c)
+ {
+ OUTCHAR(' ');
+ OUTCHAR(c);
+ OUTCHAR(' ');
+ }
+ OUTCHAR('(');
+ level++;
+}
+
+void
+Copy_Block(b1,b2) /* copy bytes b1..b2 from tf to stdout */
+long b1,b2; /* start,end byte positions */
+{
+ static char block[MAXBLOCK]; /* static to save stack space */
+ long k; /* loop index */
+ long length; /* number of bytes to copy */
+
+#if FASTIO
+ (void)fflush(stdout); /* empty any buffered output */
+#endif
+ for (k = b1; k <= b2; k += MAXBLOCK)
+ {
+ length = MIN(MAXBLOCK,b2-k+1);
+
+ (void)fseek(tf,k,0); /* position to desired block */
+
+#if FASTIO
+ if (_read(jfnof(fileno(tf)),block,(int)length) != (int)length)
+#else
+ if (fread(block,1,(int)length,tf) != (int)length)
+#endif
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,
+ "?Input block length error on temporary file [%s]",TEMPFILE);
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+#if FASTIO
+ if (_write(jfnof(fileno(stdout)),block,(int)length) != (int)length)
+#else
+ if (fwrite(block,1,(int)length,stdout) != (int)length)
+#endif
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,
+ "?Output block length error on stdout");
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+ }
+ (void)fflush(stdout);
+}
+
+void
+Copy_Plist(fontc,fp) /* copy parenthesized list to tf */
+char fontc;
+FILE *fp;
+{
+ static char p_open[] = {'(','[','<','{',NUL};
+ static char p_close[] = {')',']','>','}',NUL};
+ register int match;
+ register int c;
+
+ c = inchar(fp);
+ match = 0;
+ while (p_open[match] && (p_open[match] != (char)c))
+ match++;
+
+ if (!p_open[match])
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?@b or @i not followed by open parenthesis!");
+ NEWLINE(stderr);
+ EXIT(1);
+ }
+
+ Beg_Text(fontc);
+ while (((c = inchar(fp)) != EOF) && ((char)c != p_close[match]))
+ {
+ if (c < ' ')
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,
+ "?@b[...] or @i[...] contains control character!");
+ NEWLINE(stderr);
+ EXIT(1);
+ }
+ in_col++;
+ switch(c)
+ {
+ case '(':
+ OUTCHAR('\\');
+ OUTCHAR(c);
+ break;
+
+ case ')':
+ OUTCHAR('\\');
+ OUTCHAR(c);
+ break;
+
+ case '\\':
+ OUTCHAR('\\');
+ OUTCHAR(c);
+ break;
+
+ default:
+ OUTCHAR(c);
+ break;
+ }
+ }
+ End_Text('N');
+ OUTCHAR(' ');
+}
+
+void
+Do_File(fp)
+FILE *fp;
+{
+ register int c; /* character */
+
+/**********************************************************************/
+/* PostScript Output Section */
+/**********************************************************************/
+
+ x = LEFT_X;
+ if (init_top_margin > 0)
+ y = TOP_Y(init_top_margin);
+ else
+ y = TOP_Y(top_margin);
+
+ Beg_Page();
+ Beg_Column();
+ level = 0;
+ in_col = 0;
+ line_number = 1;
+
+ if ((c = inchar(fp)) != '\f') /* discard any initial FF */
+ (void)ungetc(c,fp);
+
+ while ((c = inchar(fp)) != EOF)
+ {
+ switch (c)
+ {
+ case NUL:
+ break; /* discard NUL's from word-padded files */
+
+ case '\b':
+ if (in_col > 0)
+ {
+ in_col--;
+ OUTCHAR('\\');
+ OUTCHAR('b');
+ }
+ break;
+
+ case '\f':
+ in_col = 0;
+ End_Text(NUL);
+ NEWLINE(tf);
+ End_Column();
+ if (column > numcol)
+ Beg_Page();
+ Beg_Column();
+ line_number = 1;
+ break;
+
+ case '\n':
+ line_number++;
+ if (in_col == 0)
+ {
+ Beg_Line();
+ Beg_Text(NUL);
+ }
+ End_Text(NUL);
+ End_Line();
+ in_col = 0;
+ y -= baseline_skip;
+ if (y < BOT_Y)
+ {
+ End_Column();
+ if (column > numcol)
+ Beg_Page();
+ Beg_Column();
+ line_number = 1;
+ }
+ break;
+
+
+ case '\r': /* check for special case of overprinting */
+ if ((c = inchar(fp)) != '\n') /* peek ahead one character */
+ { /* and if not LF, have overstrike */
+ while (level > 0)
+ {
+ OUTCHAR(')');
+ level--;
+ }
+ in_col = 0;
+ OUTCHAR('O');
+ NEWLINE(tf); /* this lines up under previous line */
+ }
+ (void)ungetc(c,fp); /* put back the peeked-at character */
+ break;
+
+ case '\t':
+ if (in_col == 0)
+ {
+ Beg_Line();
+ Beg_Text(NUL);
+ }
+ do
+ {
+ in_col++;
+ OUTCHAR(' ');
+ }
+ while (in_col & 07); /* blank fill to multiple of 8 columns */
+ break;
+
+ case '(':
+ if (in_col == 0)
+ {
+ Beg_Line();
+ Beg_Text(NUL);
+ }
+ in_col++;
+ OUTCHAR('\\');
+ OUTCHAR('(');
+ break;
+
+ case ')':
+ if (in_col == 0)
+ {
+ Beg_Line();
+ Beg_Text(NUL);
+ }
+ in_col++;
+ OUTCHAR('\\');
+ OUTCHAR(')');
+ break;
+
+ case '\\':
+ if (in_col == 0)
+ {
+ Beg_Line();
+ Beg_Text(NUL);
+ }
+ in_col++;
+ OUTCHAR('\\');
+ OUTCHAR('\\');
+ break;
+
+ case '@':
+ if (scribe)
+ {
+ c = inchar(fp);
+ if ((c == 'b') || (c == 'B'))
+ {
+ if (in_col == 0)
+ Beg_Line();
+ else
+ End_Text(NUL);
+ Copy_Plist('B',fp);
+ Beg_Text(NUL);
+ break;
+ }
+ else if ((c == 'i') || (c == 'I'))
+ {
+ if (in_col == 0)
+ Beg_Line();
+ else
+ End_Text(NUL);
+ Copy_Plist('I',fp);
+ Beg_Text(NUL);
+ break;
+ }
+ (void)ungetc(c,fp); /* put back the peeked-at character */
+ c = (int)'@'; /* and restore original character */
+ }
+ /* ELSE fall through to default! */
+
+ default:
+ if (in_col == 0)
+ {
+ Beg_Line();
+ Beg_Text(NUL);
+ }
+ in_col++;
+ if ((c < 040) || (0176 < c))
+ OUTOCTAL(c);
+ else
+ OUTCHAR(c);
+ break;
+ }
+ }
+ if (in_col > 0)
+ End_Line();
+ End_Text(NUL);
+ column = numcol; /* to force End_Page() action */
+ End_Column();
+
+ /* Normally, Beg_Page() sets the page_table[] entry. Since this is
+ the last output for this file, we must set it here manually. If
+ more files are printed, this entry will be overwritten (with the
+ same value) at the next call to Beg_Page(). */
+ page_table[page_number-init_page_number] = (long)ftell(tf);
+}
+
+void
+End_Column()
+{
+ if (outline > 0)
+ {
+ NEWLINE(tf);
+ OUTSTR("gsave");
+ NEWLINE(tf);
+ (void)fprintf(tf,"%ld setlinewidth",outline);
+ NEWLINE(tf);
+ (void)fprintf(tf,"newpath %ld %ld moveto",x - col_margin,bottom_margin);
+ (void)fprintf(tf,
+ " %ld %ld rlineto %ld %ld rlineto %ld %ld rlineto closepath stroke",
+ col_width,0,
+ 0,page_height-bottom_margin-top_margin,
+ -col_width,0);
+ NEWLINE(tf);
+ OUTSTR("grestore");
+ NEWLINE(tf);
+ }
+ (void)fprintf(stderr,
+ ".%d",line_number); /* continue [p.l.l...] status report */
+ if (++column > numcol) /* columns filled, so start new page */
+ {
+ (void)putc(']',stderr); /* close [p.l.l...] report */
+ End_Page();
+ }
+ else /* just start new column */
+ {
+ x += col_width;
+ y = TOP_Y(top_margin);
+ }
+}
+
+void
+End_Page()
+{
+ register int k;
+
+ if (do_page_number)
+ {
+ if ((init_top_margin > 0) && (page_number == init_page_number)
+ && (page_flag | PAGE_T))
+ ; /* omit leading top pagenumber */
+ else
+ switch (page_flag)
+ {
+ case (PAGE_T | PAGE_L):
+ NEWLINE(tf);
+ (void)fprintf(tf,"%ld %ld moveto",left_margin,
+ page_height-top_margin/2-baseline_skip/2);
+ (void)fprintf(tf," (%d) show",page_number);
+ break;
+
+ case (PAGE_T | PAGE_C):
+ NEWLINE(tf);
+ (void)fprintf(tf,"%ld %ld moveto",page_width/2,
+ page_height-top_margin/2-baseline_skip/2);
+ (void)fprintf(tf,
+ " (- %d -) stringwidth pop 2 div neg 0 rmoveto",
+ page_number);
+ (void)fprintf(tf," (- %d -) show",page_number);
+ NEWLINE(tf);
+ break;
+
+ case (PAGE_T | PAGE_R):
+ NEWLINE(tf);
+ (void)fprintf(tf,"%ld %ld moveto",page_width-left_margin,
+ page_height-top_margin/2-baseline_skip/2);
+ (void)fprintf(tf," (%d) stringwidth pop neg 0 rmoveto",
+ page_number);
+ (void)fprintf(tf," (%d) show",page_number);
+ NEWLINE(tf);
+ break;
+
+ case (PAGE_B | PAGE_L):
+ NEWLINE(tf);
+ (void)fprintf(tf,"%ld %ld moveto",left_margin,
+ bottom_margin/2-baseline_skip/2);
+ (void)fprintf(tf," (%d) show",page_number);
+ break;
+
+ case (PAGE_B | PAGE_C):
+ NEWLINE(tf);
+ (void)fprintf(tf,"%ld %ld moveto",page_width/2,
+ bottom_margin/2-baseline_skip/2);
+ (void)fprintf(tf,
+ " (- %d -) stringwidth pop 2 div neg 0 rmoveto",
+ page_number);
+ (void)fprintf(tf," (- %d -) show",page_number);
+ NEWLINE(tf);
+ break;
+
+ case (PAGE_B | PAGE_R):
+ NEWLINE(tf);
+ (void)fprintf(tf,"%ld %ld moveto",page_width-left_margin,
+ bottom_margin/2-baseline_skip/2);
+ (void)fprintf(tf," (%d) stringwidth pop neg 0 rmoveto",
+ page_number);
+ (void)fprintf(tf," (%d) show",page_number);
+ NEWLINE(tf);
+ break;
+
+ default: /* else no numbering */
+ break;
+ }
+ }
+ page_number++;
+
+ if (manual_feed > 0)
+ {
+ OUTSTR("statusdict begin");
+ NEWLINE(tf);
+ OUTSTR("statusdict /manualfeed true put");
+ NEWLINE(tf);
+ }
+
+ if ((fprintf(tf,"/#copies %d def showpage",copies) == EOF) ||
+ DISKFULL(tf))
+ {
+ NEWLINE(stderr);
+ (void)fprintf(stderr,"?Output error -- disk storage probably full");
+ NEWLINE(stderr);
+ (void)perror("?perror() says");
+ EXIT(1);
+ }
+ NEWLINE(tf);
+
+ if (manual_feed > 0)
+ {
+ OUTSTR("end");
+ NEWLINE(tf);
+ }
+ manual_feed--;
+
+ OUTSTR("restore");
+ NEWLINE(tf);
+
+ for (k = 1; k <= copies; ++k)
+ OUTCHAR('\f'); /* output FF's for print spooler page accounting */
+
+ x = LEFT_X;
+ y = TOP_Y(top_margin);
+}
+
+void
+End_Line()
+{
+ if (scribe)
+ {
+ OUTCHAR(' ');
+ OUTCHAR('E');
+ }
+ NEWLINE(tf);
+}
+
+
+void
+End_Text(c)
+char c;
+{
+ register int k;
+
+ k = level;
+ while (level > 0)
+ {
+ OUTCHAR(')');
+ level--;
+ }
+ if (k > 0)
+ {
+ if (scribe)
+ OUTCHAR('W');
+ else
+ OUTCHAR('P');
+ }
+ if (c)
+ {
+ OUTCHAR(' ');
+ OUTCHAR(c);
+ }
+}
+
+#include "inch.h"
+
+int
+inchar(fp)
+FILE *fp;
+{
+ static int lastc = NUL; /* memory of previous input character */
+ register int c;
+
+ /* output is incorrect if the file does not end with a LF; this
+ routine supplies one at EOF if it is lacking */
+
+ c = getc(fp);
+ if ((c == EOF) && (lastc != '\n'))
+ c = '\n';
+ lastc = c;
+ return (c);
+}
+
+void
+Page_Switch(parg) /* parg -> "Nxxxnnn" */
+register char *parg;
+{
+ register char *porg;
+
+ porg = parg;
+ do_page_number = TRUE;
+ init_page_number = 1;
+ page_flag = (PAGE_T | PAGE_C); /* default location */
+ while (*++parg)
+ {
+ switch(*parg)
+ {
+ case 't':
+ case 'T':
+ page_flag &= ~(PAGE_B | PAGE_T);
+ page_flag |= PAGE_T;
+ break;
+
+ case 'b':
+ case 'B':
+ page_flag &= ~(PAGE_B | PAGE_T);
+ page_flag |= PAGE_B;
+ break;
+
+ case 'l':
+ case 'L':
+ page_flag &= ~(PAGE_L | PAGE_C | PAGE_R);
+ page_flag |= PAGE_L;
+ break;
+
+ case 'c':
+ case 'C':
+ page_flag &= ~(PAGE_L | PAGE_C | PAGE_R);
+ page_flag |= PAGE_C;
+ break;
+
+ case 'r':
+ case 'R':
+ page_flag &= ~(PAGE_L | PAGE_C | PAGE_R);
+ page_flag |= PAGE_R;
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ init_page_number = atoi(parg);
+ while (isdigit(*parg))
+ ++parg;
+ if (*parg == NUL)
+ break;
+ /* else fall through to error exit */
+ default:
+ NEWLINE(stderr);
+ (void)fprintf(stderr,
+ "?Unrecognized page number field [%s]",porg);
+ NEWLINE(stderr);
+ EXIT(1);
+ }
+ if (*parg == NUL)
+ break;
+ }
+}
+
+#include "strcm2.h"
diff --git a/dviware/beebe/utils/lptops.hlp b/dviware/beebe/utils/lptops.hlp
new file mode 100644
index 0000000000..5842ce24fc
--- /dev/null
+++ b/dviware/beebe/utils/lptops.hlp
@@ -0,0 +1,169 @@
+ Line printer file to PostScript converter
+ [03-Jul-85]
+ [12-Nov-85]
+ [07-Apr-86]
+ [03-May-88]
+
+lptops converts normal text files into PostScript for printing on the
+Apple LaserWriter, or any other PostScript-compatible printing device.
+It supports selection of a variety of fonts at arbitrary point sizes,
+margin specification, portrait and landscape page orientation, automatic
+page numbering, page outlining, and multi-column printing. It can also
+handle overstruck text used by many document formatters for underlining.
+
+Usage:
+
+ lptops [switches] <infile >outfile
+ lptops [switches] filelist >outfile
+
+In the switch descriptions below, physical dimensions described as # may
+be specified as a single number with an optional fractional part, and a
+required two-letter unit designator. Letter case is ignored. Possible
+forms are:
+
+#.##bp big point (1in = 72bp) [Courier: 120.000/Pbp cpi]
+#.##cc cicero (1cc = 12dd) [Courier: 9.381/Pcc cpi]
+#.##cm centimeter [Courier: 4.233/Pcm cpi]
+#.##dd didot point (1157dd = 1238pt)[Courier: 112.569/Pdd cpi]
+#.##in inch [Courier: 1.667/Pin cpi]
+#.##mm millimeter (10mm = 1cm) [Courier: 42.333/Pmm cpi]
+#.##pc pica (1pc = 12pt) [Courier: 10.038/Ppc cpi]
+#.##pt point (72.27pt = 1in) [Courier: 120.450/Ppt cpi]
+#.##sp scaled point (65536sp = 1pt) [Courier: 7.893/(Psp/1000000) cpi]
+
+The bracketed values give the number of characters per inch (cpi) for a
+point size of P units with the fixed-width Courier font. For example,
+with point size 8bp, there are 120/8 = 15 characters per inch. With
+point size 1000000sp, there are 7.893 characters/inch.
+
+The optional switches are (letter case is ignored):
+
+ -A Turn Scribe-like bold and italic requests (@b[...] and
+ @i[...]) into bold or italic text.
+
+ -B# Bottom margin of #.
+
+ -Cn Print n copies of each page.
+
+ -Ffontname
+ PostScript fontname. Possible values with acceptable
+ short abbreviations (formed from the upper-case letters
+ in the font names) are as follows. The first 13 are
+ available on all PostScript printers; the remainder are
+ available only on enhanced printers, such as the Apple
+ LaserWriter Plus.
+
+ ==================== ===== ====== ==========
+ full name short ditroff TranScript
+ ==================== ===== ====== ==========
+ Courier C C C
+ Courier-Bold CB CB CB
+ Courier-BoldOblique CBO CD CD
+ Courier-Oblique CO CO CO
+ Helvetica H he he
+ Helvetica-Bold HB He He
+ Helvetica-BoldOblique HBO HE HE
+ Helvetica-Oblique HO hE hE
+ Symbol S S S
+ Times-Bold TB R ti
+ Times-BoldItalic TBI BI TI
+ Times-Italic TI I tI
+ Times-Roman T R ti
+
+ AvantGarde-Book AGB ag ag
+ AvantGarde-BookOblique AGBO aG aG
+ AvantGarde-Demi AGD Ag Ag
+ AvantGarde-DemiOblique AGDO AG AG
+ Bookman-Demi BD Bo Bo
+ Bookman-DemiItalic BDI BO BO
+ Bookman-Light BL bo bo
+ Bookman-LightItalic BLI bO bO
+ Helvetica-Narrow HN hn hn
+ Helvetica-Narrow-Bold HNB Hn Hn
+ Helvetica-Narrow-BoldOblique HNBO HN HN
+ Helvetica-Narrow-Oblique HNO hN hN
+ NewCenturySchlbk-Bold NCSB Nc Nc
+ NewCenturySchlbk-BoldItalic NCSBI NC NC
+ NewCenturySchlbk-Italic NCSI nC nC
+ NewCenturySchlbk-Roman NCSR nc nc
+ Palatino-Bold PB Pa Pa
+ Palatino-BoldItalic PBI PA PA
+ Palatino-Italic PI pA pA
+ Palatino-Roman PR pa pa
+ ZapfChancery-MediumItalic ZCMI ZC ZC
+ ZapfDingbats ZD ZD ZD
+ ==================== ===== ====== ==========
+
+ The ditroff and TranScript abbreviations are the same,
+ except for the Courier and Times fonts. They are based
+ on two-letter mnemonics, where upper-case in the first
+ letter means bold, and upper-case in the second letter
+ means italic.
+
+ Only the Courier fonts are fixed-width like typewriter
+ and line printer fonts are. The others are proportional
+ spaced for improved readability, and consequently,
+ tabular material will not line up properly with them.
+ The Courier fonts have a width equal to 0.6 of their
+ point size, so to fill a line W inches wide with up to N
+ characters, one must have point size <= (W/(0.6 * N *
+ 72)) = (W*120)/N pt. Equivalently, with a point size P
+ pt, the output spacing is 120/P char/inch.
+
+ -H Horizontal page orientation (landscape mode) instead of
+ vertical page (portrait mode).
+
+ -I# Top margin of # for initial page (for letterheads); if
+ not specified, it will default to the value given for
+ the top margin by default or by the -T# command.
+
+ -L# Left margin of #.
+
+ -Mn Multiple column output (n columns). In multiple column
+ mode, formfeeds cause column breaks instead of page
+ breaks.
+
+ -N[tb][lcr]n
+ Number output pages. The number is placed by default in
+ the center of the top margin, but the margin can be
+ selected explicitly by t (top) or b (bottom), and the
+ position of the page number can be further specified by
+ l (left), c (center), or r (right). If n is given,
+ start numbering with that value, and otherwise with 1.
+ If an initial top margin value is given with the -I#
+ option, numbering will be omitted on the first page if
+ it is at the top. Pages are unnumbered if this option
+ is not specified.
+
+ -O[#] Outline pages (and columns) with a # units wide. A
+ narrow line of 0.4pt width is assumed if # is omitted;
+ this particular width is what TeX uses in typesetting.
+
+ -P# Font point size (default 10bp). The baseline skip
+ (spacing between successive character baselines) is
+ conventionally chosen to be 6/5 of this value, so that
+ with 10bp type, we have 12bp between lines, or 6
+ lines/inch, the same as standard printer output.
+
+ -R# Right margin of #.
+
+ -S[n] special handling (i.e. manual paper feed) for the first
+ n pages of the output. If N multiple copies are in
+ effect, then N*n sheets must be fed manually. If n is
+ omitted, then all pages are to be fed manually. For
+ example, -S1 is convenient to get the first page of a
+ letter on letterhead paper fed manually, with remaining
+ pages from the paper cassette.
+
+ -T# Top margin of #.
+
+ -U Output pages in unsorted (first to last) order instead
+ of in sorted (page reversed) order; some PostScript
+ printers have page handlers that stack the paper in this
+ order. The default is sorted because this is
+ appropriate for the most common PostScript printer, the
+ Apple LaserWriter.
+
+Defaults are:
+
+ -B1.0in -C1 -FCourier -L1.0in -M1 -P10bp -R1.0in -S0 -T1.0in
diff --git a/dviware/beebe/utils/lw78.c b/dviware/beebe/utils/lw78.c
new file mode 100644
index 0000000000..3f30e01f9b
--- /dev/null
+++ b/dviware/beebe/utils/lw78.c
@@ -0,0 +1,753 @@
+/* -*-C-*- lw78.c */
+/*-->lw78*/
+/**********************************************************************/
+/******************************** lw78 ********************************/
+/**********************************************************************/
+/* <BEEBE.TEX.DVI>LW78.C.27, 29-Oct-87 16:01:55, Edit by BEEBE */
+/* Added DOBE JSYS (dismiss process until output buffer empty) in */
+/* Put_Packet(); this seems to have completely eliminated the I/O error */
+/* conditions previously experienced; they were probably due to ALW+ */
+/* buffer overruns. A straight "COPY foo.ps ttynn:" got only 3 pages */
+/* out before the ALW+ said "I/O error", which is what led me to */
+/* suspect that overrun might be responsible for our ALW+ miserable */
+/* performance. */
+/* <BEEBE.TEX.DVI.NEW>LW78.C.9, 24-Sep-86 22:49:07, Edit by BEEBE */
+/* Add -n (notify user) option */
+/* <BEEBE.TEX.DVI.NEW>LW78.C.5, 19-Aug-86 14:13:53, Edit by BEEBE */
+/* Change check for PostScript header to "%!" and add PShdrfile (-h) */
+/* option support. */
+/* <BEEBE.TEX.DVI>LW78.C.15, 2-Dec-85 18:41:26, Edit by BEEBE */
+/* Add check for PostScript header in Copy_File */
+/* <BEEBE.TEX.DVI>LW78.C.11, 21-Nov-85 12:05:20, Edit by BEEBE */
+/* Add Time_Stamp() and calls thereto for each output line */
+/***********************************************************************
+Apple LaserWriter copy utility.
+
+Copy one or more 7-bit files in binary mode to an 8-bit file, halting on
+input from the output device after printing the contents of the input
+buffer.
+
+Usage:
+ lw78 [-aAcctFile] [-d] [-en] [-hPShdrfile] [-n] [-r] \
+ -oOutfile infile1 [infile2] ... [infilek]
+
+Letter case on the switch is ignored.
+
+The optional -a switch specifies a page accounting file to which a
+single entry will be made recording a time stampe, username, and page
+count for each file processed.
+
+The -d switch causes a delete and expunge of each file after processing
+it.
+
+The -en switch optionally sends ASCII character n after each file.
+
+The -h switch defines an optional header file which will be prefixed
+to non-PostScript files to allow them to be printed.
+
+The -n switch requests that each file owner be sent a message when the
+file has been printed.
+
+The -r switch causes the files to be processed in reverse order (useful
+because of the reversed stacking of the LaserWriter).
+
+[24-Sep-86]
+***********************************************************************/
+
+#include <stdio.h>
+
+#ifndef KCC_20
+#define KCC_20 0
+#endif
+
+#ifndef PCC_20
+#define PCC_20 0
+#endif
+
+#if (KCC_20 | PCC_20)
+#else
+#undef PCC_20
+#define PCC_20 1
+#endif
+
+#if KCC_20
+#include <jsys.h>
+
+/* KCC-20 and PCC-20 have similar enough JSYS interfaces that we just
+define values for KCC-20 using PCC-20 names, and copy in definitions of
+a few macros from PCC-20's tops20.h */
+#define JSbin BIN
+#define JSbkjfn BKJFN
+#define JSbout BOUT
+#define JSbout BOUT
+#define JSclosf CLOSF
+#define JSdisms DISMS
+#define JSdobe DOBE
+#define JSdvchr DVCHR
+#define JSgfust GFUST
+#define JSgfust GFUST
+#define JSjfns JFNS
+#define JSmtopr MTOPR
+#define JSmtopr MTOPR
+#define JSmtopr MTOPR
+#define JSopenf OPENF
+#define JSsfcoc SFCOC
+#define JSsfmod SFMOD
+#define JSsibe SIBE
+#define JSsout SOUT
+#define JSstpar STPAR
+
+#define DVtty 012 /* terminal */
+#define DV_typ 0777:35-17 /* device type field */
+
+#define GFlwr 01 /* get file last writer */
+
+#define GJ_fou 01:35-0 /* file is for output use */
+#define GJ_sht 01:35-17 /* short call format */
+
+#define MOslw 031 /* set width */
+#define MOsll 033 /* set length */
+#define MOsnt 034 /* set tty non-terminal status */
+#define MOsmn 01 /* no system messages(i.e. suppress) */
+
+#define OF_bsz 077:35-5 /* byte size */
+#define OF_rd 01:35-19 /* read */
+#define OF_wr 01:35-20 /* write */
+
+#define TT_mff 01:35-1 /* mechanical formfeed present */
+#define TT_tab 01:35-2 /* mechanical tab present */
+#define TT_lca 01:35-3 /* lower case capabilities present */
+#define TT_eco 01:35-24 /* echos on */
+#define TT_dam 03:35-29 /* data mode */
+#define TTbin 00 /* binary */
+#define TT_pgm 01:35-34 /* page mode */
+
+#define Absmask(name) ( (1?name) << (0?name) ) /* maybe use this one */
+#define Getmask(name) ( 1?name )
+#define Getshift(name) ( 0?name )
+
+#define getfield(var, name) ( (var) >> Getshift(name) & Getmask(name) )
+#define getright(b) ( (b) & 0777777 )
+#define makefield(name, value) ( ((value) & Getmask(name)) << Getshift(name) )
+#define makeword(l, r) ( ((l) << 18) | (r) )
+#define setfield(var, name, value) ( (var) = ((var) & ~Absmask(name)) |\
+ makefield(name, value) )
+#else /* must be PCC_20 */
+#include <file.h>
+#include <monsym.h>
+#endif /* KCC_20 */
+
+typedef int BOOLEAN;
+
+#define ACCOUNTING 1 /* define for accounting code */
+
+#define TRUE 1
+#define FALSE 0
+
+/* global constants */
+
+#define INTERVAL (5*512) /* how often to check input buffer */
+#define MAXERRMSG 512 /* error message size */
+#define MAXFILENAME 144 /* longest filename */
+#define MAXIDLE (10*1000) /* msec to wait for idle status */
+#define MAXLINE 128 /* maximum id line size */
+#define MAXPACKET (5*512) /* packet size to output */
+#define MAXPAUSE (500) /* msec to wait for new byte */
+#define MAXUSERNAME 256 /* longest username */
+#define MAXWAIT (5*1000) /* msec to wait after each file */
+
+#define PSHEADER "%!" /* what every PostScript file has */
+
+/* global variables */
+
+char author[MAXUSERNAME+1];
+BOOLEAN del_flag; /* file delete flag */
+int eof_char; /* end-of-file character */
+char errmsg[MAXERRMSG+1]; /* string from output device */
+int nbytes; /* global input byte count */
+BOOLEAN notify_owner; /* notify file owner when printed */
+int npacket; /* packet[] index */
+int packet[MAXPACKET+1]; /* want space for 1 extra eof_char */
+char timestr[27];
+long timeval;
+
+#if ACCOUNTING
+FILE *acctfile; /* accounting file */
+#endif
+
+FILE *PShdrfile = (FILE *)NULL; /* PostScript header file */
+
+/* Function macro definitions */
+
+#define BYTEPTR(x) (0004400000000 | (int)((x)-1)) /* x must be int*, not int */
+ /* PCC uses 36-bit bytes */
+#define CTL(c) ((char)(((int)(c)) & 037))
+#define GETBYTE(thejfn) (ac1 = thejfn, (void)jsys(JSbin, acs), ac2)
+#define HAVE_INPUT(thejfn) (ac1 = thejfn, (void)jsys(JSsibe, acs), (ac2 > 0))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+/* Procedure macro definitions */
+
+#define WAITMS(msec) {ac1 = msec; (void)jsys(JSdisms, acs);}
+
+/* Function/Procedure declarations */
+
+void Copy_File();
+char *ctime();
+char *fgetname();
+int Get_Byte();
+void Get_Msg();
+void Init_Terminal();
+BOOLEAN Input_Error();
+void Put_Packet();
+long time();
+void Time_Stamp();
+void Wait_For_Printer_Ready();
+
+/***********************************************************************
+It would be nice to have done this entirely with getc/putc, but alas,
+PCC will not open an 8-bit file to a terminal, because it attempts to
+issue an illegal SFBSZ% JSYS to set the file byte size, instead of
+checking to see if it is a terminal, and then just setting the byte size
+in the OPENF% JSYS. We therefore use the JSYS interface routines to do
+our own GTJFN%, OPENF%, and BOUT% calls.
+
+Sigh....
+
+***********************************************************************/
+
+main(argc,argv)
+int argc;
+char* argv[];
+{
+ BOOLEAN reverse_order;
+ register int c,k,len;
+ int fp,outjfn,nfile,kfile;
+ register FILE* infile; /* 7-bit file */
+
+ if (argc < 2)
+ {
+ (void)fprintf(stderr,
+ "%%Usage: %s [-aAcctFile] [-d] [-en] [-hPShdrfile] [-n] [-r] \
+-ooutfile infile1 [infile2] ... [infilek]\n",
+ argv[0]);
+ exit(1);
+ }
+
+ del_flag = FALSE;
+ eof_char = -1;
+ nfile = 0;
+ notify_owner = FALSE;
+ outjfn = -1;
+ reverse_order = FALSE;
+ PShdrfile = (FILE *)NULL;
+
+#if ACCOUNTING
+ acctfile = (FILE *)NULL;
+#endif
+
+ for (k = 1; k < argc; ++k)
+ {
+ if (*argv[k] != '-') /* not switch, must be file name */
+ nfile++;
+#if ACCOUNTING
+ else if ((strncmp("-a",argv[k],2) == 0) ||
+ (strncmp("-A",argv[k],2) == 0))
+ {
+ if ((acctfile = fopen(argv[k]+2,"a")) == (FILE *)NULL)
+ {
+ (void)fprintf(stderr,"?Cannot open accounting file [%s]\n",
+ argv[k]+2);
+ exit(1);
+ }
+ }
+#endif
+ else if ((strncmp("-d",argv[k],2) == 0) ||
+ (strncmp("-D",argv[k],2) == 0))
+ del_flag = TRUE;
+ else if ((strncmp("-e",argv[k],2) == 0) ||
+ (strncmp("-E",argv[k],2) == 0))
+ eof_char = atoi(argv[k]+2);
+ else if ((strncmp("-h",argv[k],2) == 0) ||
+ (strncmp("-H",argv[k],2) == 0))
+ {
+ if ((PShdrfile = fopen(argv[k]+2,"r")) == (FILE *)NULL)
+ {
+ (void)fprintf(stderr,"?Cannot open PShdrfile [%s]\n",
+ argv[k]+2);
+ exit(1);
+ }
+ }
+ else if ((strncmp("-n",argv[k],2) == 0) ||
+ (strncmp("-N",argv[k],2) == 0))
+ notify_owner = TRUE;
+ else if ((strncmp("-r",argv[k],2) == 0) ||
+ (strncmp("-R",argv[k],2) == 0))
+ reverse_order = TRUE;
+ else if ((strncmp("-o",argv[k],2) == 0) ||
+ (strncmp("-O",argv[k],2) == 0))
+ {
+ if ((outjfn = _gtjfn(argv[k]+2, makefield(GJ_fou,1) |
+ makefield(GJ_sht,1))) != -1) /* then got valid jfn */
+ {
+ ac1 = outjfn = getright(outjfn);
+ ac2 = makefield(OF_bsz, 8);
+ ac2 = setfield(ac2,OF_wr,1);
+ ac2 = setfield(ac2,OF_rd,1);
+ if (jsys(JSopenf, acs) != JSok)
+ outjfn = -1; /* open failed */
+ }
+ }
+ else
+ {
+ (void)fprintf(stderr,"?Unknown switch [%s]\n",argv[k]);
+ exit(1);
+ }
+ }
+ if (outjfn == -1)
+ {
+ (void)fprintf(stderr,"?Cannot open output file\n");
+ exit(1);
+ }
+ else /* open okay */
+ Init_Terminal(outjfn);
+
+ kfile = 0;
+ for (k = (reverse_order ? (argc-1) : 1);
+ (0 < k) && (k < argc);
+ (reverse_order ? --k : ++k))
+ {
+ if (*argv[k] == '-')
+ ; /* ignore switch field */
+
+#if KCC_20
+ else if ((infile = fopen(argv[k],"rb7")) != (FILE*)NULL)
+#endif
+#if PCC_20
+ else if ((fp = open(argv[k],
+ FATT_RDONLY | FATT_SETSIZE | FATT_BINARY,7)) >= 0)
+#endif
+ {
+#if PCC_20
+ infile = fdopen(fp,"rb");
+#endif
+ Wait_For_Printer_Ready(outjfn);
+
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"[%d of %d: %s]",++kfile,nfile,argv[k]);
+ Copy_File(infile,outjfn);
+ if (notify_owner)
+ {
+ ac1 = makeword(GFlwr,jfnof(fileno(infile)));
+ ac2 = POINT(author);
+ (void)jsys(JSgfust, acs);
+ timeval = time((long*)NULL);
+ strcpy(timestr,ctime(&timeval));
+ len = strlen(timestr) - 1; /* ctime has its own \n */
+ timestr[len] = '\0'; /* so kill it */
+ (void)sprintf(errmsg,
+ "send %s %s: %s printed on LaserWriter\n",
+ author,timestr,argv[k]);
+ (void)system(errmsg);
+ }
+ (void)fclose(infile);
+
+ if (del_flag)
+ {
+ (void)unlink(argv[k]); /* delete the file */
+ (void)fprintf(stderr," [OK - deleted]");
+ }
+ else
+ (void)fprintf(stderr," [OK]");
+
+ if (kfile < nfile) /* delay next output to try to */
+ WAITMS(MAXWAIT); /* avoid timeout bug! */
+ }
+ else
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"?Cannot open input file [%s]",argv[k]);
+ }
+ }
+
+ ac1 = outjfn;
+ (void)jsys(JSclosf, acs);
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"Spooler terminated\n\n\n\n");
+}
+
+void
+Copy_File(infile,outjfn)
+register FILE* infile;
+register int outjfn;
+{
+ register int c;
+ register int k;
+ char filename[MAXFILENAME+1];
+ char idline[MAXLINE+1];
+
+#if ACCOUNTING
+ int page_count;
+ int *pbyte;
+#endif
+
+ (void)
+ fgets(idline,MAXLINE,infile); /* peek at first line */
+ rewind(infile);
+
+ if (strncmp(idline,PSHEADER,strlen(PSHEADER)) != 0)
+ {
+ if (PShdrfile != (FILE *)NULL)
+ {
+ rewind(PShdrfile);
+ nbytes = 0;
+ while ((npacket = read(fileno(PShdrfile),packet,MAXPACKET)) > 0)
+ {
+ nbytes += npacket;
+ Put_Packet(outjfn,packet,npacket);
+ if (Input_Error(PShdrfile,outjfn))
+ return;
+ }
+ }
+ else /* reject non-PostScript file */
+ {
+ k = MAX(2,strlen(idline));
+ if (idline[k-1] == '\n')
+ idline[k-1] = '\0'; /* kill NL */
+ if (idline[k-2] == '\r')
+ idline[k-2] = '\0'; /* kill CR */
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,
+ "?File may not contain PostScript. First line has\n");
+ (void)fprintf(stderr,"\t[%s] instead of [%s] -- file discarded",
+ idline,PSHEADER);
+ return;
+ }
+ }
+
+#if ACCOUNTING
+ page_count = 0;
+#endif
+
+ nbytes = 0;
+#if (INTERVAL-MAXPACKET) /* copy one at a time */
+ npacket = 0;
+ while ((c = getc(infile)) != EOF)
+ {
+#if ACCOUNTING
+ if (c == '\f')
+ page_count++; /* each FF counts one page */
+#endif
+ if ((!((++nbytes) % INTERVAL)) && Input_Error(infile,outjfn))
+ return;
+ if (npacket >= MAXPACKET)
+ {
+ Put_Packet(outjfn,packet,npacket);
+ npacket = 0;
+ }
+ packet[npacket++] = c;
+ }
+#else /* copy in block mode */
+ while ((npacket = read(fileno(infile),packet,MAXPACKET)) > 0)
+ {
+ nbytes += npacket;
+ Put_Packet(outjfn,packet,npacket);
+
+#if ACCOUNTING
+ if (acctfile != (FILE*)NULL)
+ {
+ for ((pbyte = packet, k = npacket); k; (--k, ++pbyte))
+ if (*pbyte == '\f')
+ page_count++; /* each FF counts one page */
+ }
+#endif
+
+ if (Input_Error(infile,outjfn))
+ return;
+ }
+ if (npacket < 0)
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"?I/O error on input file");
+ }
+ npacket = 0;
+#endif
+
+ if (eof_char >= 0)
+ packet[npacket++] = eof_char;
+ if (npacket > 0)
+
+ Put_Packet(outjfn,packet,npacket);
+
+#if ACCOUNTING
+ if (acctfile != (FILE*)NULL)
+ {
+ ac1 = makeword(GFlwr,jfnof(fileno(infile)));
+ ac2 = POINT(author);
+ (void)jsys(JSgfust, acs);
+ Time_Stamp(acctfile);
+ (void)fprintf(acctfile,"%8d\t%s\t%s",
+ MAX(1,page_count),author,fgetname(infile,filename));
+ }
+#endif
+
+}
+
+int
+Get_Byte(thejfn) /* get byte (maybe waiting) */
+register int thejfn; /* returns EOF if no input */
+{
+ if (HAVE_INPUT(thejfn))
+ return(GETBYTE(thejfn));
+
+ WAITMS(MAXPAUSE);
+
+ if (HAVE_INPUT(thejfn))
+ return(GETBYTE(thejfn));
+ else /* still no input */
+ return(EOF);
+}
+
+void
+Get_Msg(thejfn)
+int thejfn;
+{
+ register int cm1,cm2,c,k;
+
+ Time_Stamp(stderr);
+ k = 0;
+ c = 0;
+ cm1 = 0;
+ cm2 = 0;
+ while (!((cm2 == ']') && (cm1 == '%') && (c == '%'))) /* until "]%%" */
+ { /* skip <garbage> and collect %%[ ... ]%% */
+ cm2 = cm1;
+ cm1 = c;
+ if ((c = Get_Byte(thejfn)) == EOF)
+ break; /* no input yet */
+ if ((cm2 == '%') && (cm1 == '%') && (c == '['))
+ { /* restart message collection */
+ k = 2;
+ errmsg[0] = '%';
+ errmsg[1] = '%';
+ }
+ if (k < MAXERRMSG)
+ errmsg[k++] = c;
+ putc(c,stderr);
+ }
+
+
+ errmsg[k] = '\0'; /* terminate string */
+
+ while (TRUE) /* "infinite" loop to discard any */
+ /* remaining input up to start of */
+ /* next message */
+ {
+
+ if ((c = Get_Byte(thejfn)) == EOF)
+ break; /* no input, so exit loop */
+
+ if (c == '%') /* if start of new message then */
+ { /* put character back and exit */
+ ac1 = thejfn;
+ (void)jsys(JSbkjfn,acs);
+ break;
+ }
+
+ if (!((c == '\r') || (c == '\n')))/* echo the character */
+ putc(c,stderr); /* but discard terminal CR LF */
+ } /* to avoid unwanted blank lines */
+}
+
+void
+Init_Terminal(thejfn)
+register int thejfn;
+{
+ ac1 = thejfn;
+ (void)jsys(JSdvchr, acs); /* get device characteristics */
+
+ if (getfield(ac2,DV_typ) == DVtty)
+ { /* have terminal, set its features */
+ ac1 = thejfn;
+ ac2 = MOsnt;
+ ac3 = MOsmn; /* no system messages */
+ (void)jsys(JSmtopr, acs);
+
+ ac1 = thejfn;
+ ac2 = makefield(TT_mff,1); /* has formfeed */
+ ac2 = setfield(ac2,TT_tab,1); /* has tab */
+ ac2 = setfield(ac2,TT_lca,1); /* has lowercase */
+ ac2 = setfield(ac2,TT_pgm,1); /* has X-on/X-off */
+ (void)jsys(JSstpar, acs);
+
+ ac1 = thejfn;
+ ac2 = makefield(TT_dam,TTbin); /* binary output */
+ ac2 = setfield(ac2,TT_eco,0); /* no echo */
+ (void)jsys(JSsfmod, acs);
+
+ ac1 = thejfn;
+ ac2 = 0525252525252;
+ ac3 = 0525252525252; /* no CTL-char translation */
+ (void)jsys(JSsfcoc, acs);
+
+ ac1 = thejfn;
+ ac2 = MOslw;
+ ac3 = 0; /* line width = 0 */
+ (void)jsys(JSmtopr, acs);
+
+ ac1 = thejfn;
+ ac2 = MOsll;
+ ac3 = 0; /* page length = 0 */
+ (void)jsys(JSmtopr, acs);
+ }
+}
+
+BOOLEAN
+Input_Error(infile,thejfn) /* return TRUE if error */
+register FILE* infile;
+register int thejfn;
+{
+ register int c;
+
+ if (HAVE_INPUT(thejfn))
+ {
+ Get_Msg(thejfn);
+ if (strncmp(errmsg,"%%[ Error: timeout;",19) == 0)
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"[Error occurred in input byte range %d..%d]",
+ MAX(0,nbytes-32),nbytes);
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,
+ "Attempting to recover from Apple LaserWriter BUG of \
+timeout error");
+ (void)fflush(stderr);
+ return(FALSE);
+ }
+ else if (strncmp(errmsg,"%%[ PrinterError: out of paper",30) == 0)
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"\t[Waiting 10 sec for paper]");
+ (void)fflush(stderr);
+ WAITMS(10000);
+ return(FALSE);
+ }
+ else if (strncmp(errmsg,"%%[ PrinterError: no paper tray",31) == 0)
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"\t[Waiting 10 sec for paper tray]");
+ (void)fflush(stderr);
+ WAITMS(10000);
+ return(FALSE);
+ }
+ else if (strncmp(errmsg,"%%[ Error: VMerror;",19) == 0)
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,
+ "Attempting to recover from Apple LaserWriter BUG of VMerror");
+ (void)fflush(stderr);
+ Wait_For_Printer_Ready(thejfn);
+ do /* skip to next page or end-of-job */
+ {
+ c = getc(infile);
+ }
+ while ((c != EOF) && (c != CTL('D')) && (c != CTL('L')));
+ npacket = 0; /* discard last packet */
+ return(FALSE);
+ }
+ else if (strcmp(errmsg,"%%[ status: idle ]%%") == 0)
+ return(FALSE);
+ else
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"[Error occurred in input byte range %d..%d]",
+ MAX(0,nbytes-32),nbytes);
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"[Job flushed]");
+ (void)fflush(stderr);
+ return(TRUE);
+ }
+ }
+ else /* no input yet */
+ return(FALSE);
+}
+
+void
+Put_Packet(thejfn,packet,n)
+int thejfn;
+int packet[];
+int n;
+{
+ ac1 = thejfn;
+ (void)jsys(JSdobe, acs); /* wait until output buffer empty */
+
+ ac1 = thejfn;
+ ac2 = BYTEPTR(packet);
+ ac3 = -n; /* exact byte count */
+ ac4 = 0;
+ if (n > 0)
+ {
+ if (jsys(JSsout, acs) != JSok)
+ {
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"?SOUT error");
+ exit(1);
+ }
+ }
+
+}
+
+void
+Time_Stamp(fp)
+FILE *fp;
+{
+ int k;
+
+ timeval = time((long*)NULL);
+ strcpy(timestr,ctime(&timeval));
+ k = strlen(timestr) - 1; /* ctime has its own \n */
+ timestr[k] = '\0'; /* so kill it */
+ (void)fprintf(fp,"\n%s\t",timestr);
+}
+
+void
+Wait_For_Printer_Ready(thejfn)
+register int thejfn;
+{
+ while (TRUE) /* "infinite" loop */
+ {
+ ac1 = thejfn;
+ ac2 = CTL('T'); /* CTL-T for status message */
+ (void)jsys(JSbout, acs);
+
+ ac1 = thejfn;
+ (void)jsys(JSdobe, acs); /* wait until output sent */
+
+ Get_Msg(thejfn);
+ if (strcmp(errmsg,"%%[ status: idle ]%%") == 0)
+ break; /* printer ready to go */
+
+ ac1 = thejfn;
+ ac2 = CTL('D'); /* CTL-D to terminate previous job */
+ (void)jsys(JSbout, acs);
+
+ Time_Stamp(stderr);
+ (void)fprintf(stderr,"\t[Waiting %d sec]",MAXIDLE/1000);
+
+ WAITMS(MAXIDLE);
+ }
+}
+
+char *
+fgetname(fp,buffer)
+FILE *fp;
+char buffer[];
+{
+ ac1 = POINT(buffer);
+ ac2 = jfnof(fileno(fp));
+ ac3 = 0;
+ ac4 = 0;
+ buffer[0] = '\0';
+ (void)jsys(JSjfns, acs);
+ return(buffer);
+}
diff --git a/dviware/beebe/utils/texidx.c b/dviware/beebe/utils/texidx.c
new file mode 100644
index 0000000000..7cbe6a4849
--- /dev/null
+++ b/dviware/beebe/utils/texidx.c
@@ -0,0 +1,1766 @@
+/* <BEEBE.GNU>TEXID3.C.18, 28-Nov-86 16:28:02, Edit by BEEBE */
+/* Fix incorrect isalnum() comparison in compare_prepared */
+/* <BEEBE.GNU>TEXID3.C.12, 5-Nov-86 12:12:51, Edit by BEEBE */
+/* (1) Modify indexify() to support pagenumber range output */
+/* (2) Complete forward function declarations */
+/* (3) Change type of xmalloc() and xrealloc() from int to char* */
+/* for portability (eventually, they will be void* with ANSI C) */
+/* <BEEBE.GNU>TEXIDX.C.11, 26-Sep-86 18:38:51, Edit by BEEBE */
+/* (1) Change num_keyfields-1 in comparisons to num_keyfields, so this */
+/* works for secondary entries too. */
+/* (2) Add initializations of 0 keyfield[] fields. */
+/* (3) Replace 5 instances of "if (keyfields->xxx)" with */
+/* "if (keyfields[0].xxx)" */
+/* <BEEBE.GNU>TEXIDX.C.3, 20-Aug-86 11:58:19, Edit by BEEBE */
+/* All local changes under control of "tops20" preprocessor symbol.*/
+/* Added #define's for 6-char unique externals. */
+/* Changed union text member to keytext in order to have unique */
+/* structure names (this required a careful global edit). */
+/* Changed struct keyfield to struct keyfld for uniqueness. */
+/* Changed open() call to old PCC form */
+
+/* Prepare Tex index dribble output into an actual index.
+ Copyright (C) Richard M. Stallman 1984
+
+ Permission is granted to anyone to make or distribute
+ verbatim copies of this program
+ provided that the copyright notice and this permission notice are preserved;
+ and provided that the recipient is not asked to waive or limit his right to
+ redistribute copies as permitted by this permission notice;
+ and provided that anyone possessing a machine-executable copy
+ is granted access to copy the source code, in machine-readable form,
+ in some reasonable manner.
+
+ Permission is granted to distribute derived works or enhanced versions of
+ this program under the above conditions with the additional condition
+ that the entire derivative or enhanced work
+ must be covered by a permission notice identical to this one.
+
+ Anything distributed as part of a package containing portions derived
+ from this program, which cannot in current practice perform its function
+ usefully in the absence of what was derived directly from this program,
+ is to be considered as forming, together with the latter,
+ a single work derived from this program,
+ which must be entirely covered by a permission notice identical to this one
+ in order for distribution of the package to be permitted.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define READ read
+#define EXIT exit
+
+#ifdef KCC_20
+#include <file.h>
+#define tops20
+#else
+#ifdef OS_VAXVMS
+#include <file.h>
+#undef READ
+#define READ vms_read
+#undef EXIT
+#define EXIT vms_exit
+#else
+#ifdef OS_ATARI
+#else
+#ifdef IBM_PC_MICROSOFT
+#include <fcntl.h>
+#include <io.h>
+#else
+#include <sys/file.h>
+#endif
+#endif
+#endif
+#endif
+
+#ifdef tops20
+
+/* variables */
+
+#define lastsecondarylength lstsln
+#define lengthptr lengp
+#define primarylength prilen
+#define compare_field cmpfld
+#define compare_general cmpgen
+#define compare_prepared cmppre
+#define keyfields keyfls
+#define lastinitial lstini
+#define lastinitial1 lstin1
+#define lastinitiallength lstiln
+#define lastprimary lstpri
+#define lastprimarylength lstpln
+#define lastsecondary lstsec
+#define length1 leng1
+#define length2 leng2
+#define secondarylength seclen
+#define start_tempcount strtmc
+#define tempcount tmpcnt
+
+/* functions */
+
+#define compare_full cmpful
+#define find_braced_end fndben
+#define find_braced_pos fndbpo
+#define find_field fndfld
+#define find_pos fndpos
+#define flush_tempfiles flstmp
+#define maketempname makete
+#define merge_direct mrgdir
+#define merge_files mrgfil
+#define parsefile prsfil
+#define pfatal_with_name pfawna
+#define readline rdline
+#define sort_in_core srtcor
+#define sort_offline srtoff
+#define writelines writln
+
+int sys_nerr = 0;
+char *sys_errlist[] = {"?"};
+
+void
+bzero (s,n)
+register char *s;
+register int n;
+{
+ while (n--)
+ *s++ = '\0';
+}
+
+#endif
+
+#ifdef VMS
+void
+bzero (s,n)
+register char *s;
+register int n;
+{
+ while (n--)
+ *s++ = '\0';
+}
+#endif
+
+#ifdef IBM_PC_MICROSOFT
+void
+bzero (s,n)
+register char *s;
+register int n;
+{
+ while (n--)
+ *s++ = '\0';
+}
+#endif
+
+#ifdef OS_ATARI
+void
+bzero (s,n)
+register char *s;
+register int n;
+{
+ while (n--)
+ *s++ = '\0';
+}
+#endif
+
+#ifndef L_XTND
+#define L_XTND 2
+#endif
+
+/* When sorting in core, this structure describes one line
+ and the position and length of its first keyfield. */
+
+struct lineinfo
+ {
+ char *text; /* The actual text of the line */
+ union
+ { /* The start of the key (for textual comparison) */
+ char *keytext;
+ long number; /* or the numeric value (for numeric comparison) */
+ } key;
+ long keylen; /* Length of key field */
+ };
+
+/* This structure describes a field to use as a sort key */
+
+struct keyfld
+ {
+ int startwords; /* # words to skip */
+ int startchars; /* and # additional chars to skip, to start */
+ /* of field */
+ int endwords; /* similar, from beg (or end) of line, to */
+ /* find end of field */
+ int endchars;
+ char ignore_blanks; /* Ignore spaces and tabs within the field */
+ char fold_case; /* Convert upper case to lower before */
+ /* comparing */
+ char reverse; /* Compare in reverse order */
+ char numeric; /* Parse text as an integer and compare the */
+ /* integers */
+ char positional; /* Sort according to position within the file */
+ char braced; /* Count balanced-braced groupings as fields */
+ };
+
+/* Vector of keyfields to use */
+
+struct keyfld keyfields[3];
+
+/* Number of keyfields stored in that vector. */
+
+int num_keyfields = 3;
+
+/* Vector of input file names, terminated with a zero (null pointer) */
+
+char **infiles;
+
+/* Vector of corresponding output file names, or zero meaning default it */
+
+char **outfiles;
+
+/* Length of `infiles' */
+
+int num_infiles;
+
+/* Pointer to the array of pointers to lines being sorted */
+
+char **linearray;
+
+/* The allocated length of `linearray'. */
+
+long lines;
+
+/* Directory to use for temporary files */
+
+char *tempdir;
+
+/* Start of filename to use for temporary files. It starts with a slash. */
+
+char *tempbase;
+
+/* Number of last temporary file. */
+
+int tempcount;
+
+/* Number of last temporary file already deleted.
+ Temporary files are deleted by `flush_tempfiles' in order of creation. */
+
+int last_deleted_tempcount;
+
+/* During in-core sort, this points to the base of the data block
+ which contains all the lines of data. */
+
+char *text_base;
+
+/* Additional command switches */
+
+int keep_tempfiles; /* Nonzero means do not delete tempfiles -- for */
+ /* debugging */
+
+/* Forward declarations of functions in this file (alphabetical by function */
+/* name) */
+
+int classify_arg();
+int compare_field();
+int compare_full();
+int compare_general();
+int compare_prepared();
+char* concat();
+void decode_command();
+void error();
+void fatal();
+char* find_braced_end();
+char* find_braced_pos();
+char* find_field();
+char* find_pos();
+long find_value();
+void finish_index();
+void flush_tempfiles();
+void indexify();
+void initbuffer();
+void init_index();
+int main();
+char* maketempname();
+int merge_direct();
+int merge_files();
+extern char* mktemp();
+char** parsefile();
+void pfatal_with_name();
+void put_range();
+long readline();
+void sort_in_core();
+void sort_offline();
+char* strchr();
+void writelines();
+char* xmalloc();
+char* xrealloc();
+
+#define MAX_IN_CORE_SORT 500000
+
+#ifdef KCC_20
+#undef MAX_IN_CORE_SORT
+#define MAX_IN_CORE_SORT 4*512*128
+#endif
+
+#ifdef IBM_PC_MICROSOFT
+#undef MAX_IN_CORE_SORT
+#define MAX_IN_CORE_SORT 64000
+#endif
+
+#ifdef PCC_20
+#undef MAX_IN_CORE_SORT
+#define MAX_IN_CORE_SORT 512*128
+#endif
+
+#ifdef OS_ATARI
+#undef MAX_IN_CORE_SORT
+#define MAX_IN_CORE_SORT 512*128
+long _stksize = 20000L;
+#endif
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+
+ tempcount = 0;
+ last_deleted_tempcount = 0;
+
+ /* Describe the kind of sorting to do. */
+ /* The first keyfield uses the first braced field and folds case */
+ keyfields[0].braced = 1;
+ keyfields[0].fold_case = 1;
+ keyfields[0].endwords = -1;
+ keyfields[0].endchars = -1;
+
+ keyfields[0].ignore_blanks = 0;
+ keyfields[0].numeric = 0;
+ keyfields[0].positional = 0;
+ keyfields[0].reverse = 0;
+ keyfields[0].startchars = 0;
+ keyfields[0].startwords = 0;
+
+ /* The second keyfield uses the second braced field, numerically */
+ keyfields[1].braced = 1;
+ keyfields[1].numeric = 1;
+ keyfields[1].startwords = 1;
+ keyfields[1].endwords = -1;
+ keyfields[1].endchars = -1;
+
+ keyfields[1].fold_case = 0;
+ keyfields[1].ignore_blanks = 0;
+ keyfields[1].positional = 0;
+ keyfields[1].reverse = 0;
+ keyfields[1].startchars = 0;
+
+ /* The third keyfield (which is ignored while discarding duplicates)
+ compares the whole line */
+ keyfields[2].endwords = -1;
+ keyfields[2].endchars = -1;
+
+ keyfields[2].braced = 0;
+ keyfields[2].fold_case = 0;
+ keyfields[2].ignore_blanks = 0;
+ keyfields[2].numeric = 0;
+ keyfields[2].positional = 0;
+ keyfields[2].reverse = 0;
+ keyfields[2].startchars = 0;
+ keyfields[2].startwords = 0;
+
+ decode_command (argc, argv);
+
+#ifdef OS_ATARI
+ tempbase = mktemp (concat ("\\TXIXXX\.", "", ""));
+#else
+ tempbase = mktemp (concat ("/txiXXXXXX", "", ""));
+#endif
+
+ /* Process input files completely, one by one. */
+
+ for (i = 0; i < num_infiles; i++)
+ {
+ int desc;
+ long ptr;
+ char *outfile;
+
+#ifdef VMS
+ FILE* fp;
+#endif
+ desc = open (infiles[i], 0, 0);
+ if (desc < 0) pfatal_with_name (infiles[i]);
+#ifdef VMS
+ fp = fdopen(desc,"r");
+#endif
+ lseek (desc, 0L, L_XTND);
+#ifdef VMS
+ ptr = ftell(fp);
+#else
+#ifdef OS_ATARI
+ ptr = ftell(desc);
+#else
+ ptr = tell (desc);
+#endif
+#endif
+ close (desc);
+
+ outfile = outfiles[i];
+ if (!outfile)
+ {
+ outfile = concat (infiles[i], "s", "");
+ }
+
+ if (ptr < MAX_IN_CORE_SORT)
+ /* Sort a small amount of data */
+ sort_in_core (infiles[i], ptr, outfile);
+ else
+ sort_offline (infiles[i], ptr, outfile);
+ }
+
+ flush_tempfiles (tempcount);
+ EXIT (0);
+}
+
+/* This page decodes the command line arguments to set the parameter variables
+ and set up the vector of keyfields and the vector of input files */
+
+void
+decode_command (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+ char **ip;
+ char **op;
+
+ /* Store default values into parameter variables */
+
+#ifdef OS_ATARI
+ tempdir = "\\TMP";
+#else
+ tempdir = "/tmp";
+#endif
+
+ keep_tempfiles = 0;
+
+ /* Allocate argc input files, which must be enough. */
+
+ infiles = (char **) xmalloc (argc * sizeof (char *));
+ outfiles = (char **) xmalloc (argc * sizeof (char *));
+ ip = infiles;
+ op = outfiles;
+
+ /* First find all switches that control the default kind-of-sort */
+
+ for (i = 1; i < argc; i++)
+ {
+ int tem = classify_arg (argv[i]);
+ char c;
+ char *p;
+
+ if (tem <= 0)
+ {
+ *ip++ = argv[i];
+ *op++ = 0;
+ continue;
+ }
+ if (tem > 1)
+ {
+ if (i + 1 == argc)
+ fatal ("switch %s given with no argument following it", argv[i]);
+ else if (!strcmp (argv[i], "-T"))
+ tempdir = argv[i + 1];
+ else if (!strcmp (argv[i], "-o"))
+ *(op - 1) = argv[i + 1];
+ i += tem - 1;
+ continue;
+ }
+
+ p = &argv[i][1];
+ while (c = *p++)
+ switch (c)
+ {
+ case 'k':
+ keep_tempfiles = 1;
+ break;
+
+ default:
+ fatal ("invalid command switch %c", c);
+ }
+ }
+
+ /* Record number of keyfields, terminate list of filenames */
+
+ num_infiles = ip - infiles;
+ *ip = 0;
+}
+
+/* Return 0 for an argument that is not a switch;
+ for a switch, return 1 plus the number of following arguments that the switch
+ swallows.
+*/
+
+int
+classify_arg (arg)
+ char *arg;
+{
+ if (!strcmp (arg, "-T") || !strcmp (arg, "-o"))
+ return 2;
+ if (arg[0] == '-')
+ return 1;
+ return 0;
+}
+
+/* Create a name for a temporary file */
+
+char *
+maketempname (count)
+ int count;
+{
+ char tempsuffix[10];
+ (void)sprintf (tempsuffix, "%d", count);
+ return concat (tempdir, tempbase, tempsuffix);
+}
+
+/* Delete all temporary files up to the specified count */
+
+void
+flush_tempfiles (to_count)
+ int to_count;
+{
+ if (keep_tempfiles) return;
+ while (last_deleted_tempcount < to_count)
+ unlink (maketempname (++last_deleted_tempcount));
+}
+
+
+/* Compare two lines, provided as pointers to pointers to text,
+ according to the specified set of keyfields */
+
+int
+compare_full (line1, line2)
+ char **line1, **line2;
+{
+ int i;
+
+ /* Compare using the first keyfield;
+ if that does not distinguish the lines, try the second keyfield; and so
+ on. */
+
+ for (i = 0; i < num_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], *line1, &length1);
+ char *start2 = find_field (&keyfields[i], *line2, &length2);
+ int tem = compare_field (&keyfields[i],
+ start1, length1, *line1 - text_base,
+ start2, length2, *line2 - text_base);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return - tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly */
+}
+
+/* Compare two lines described by structures
+ in which the first keyfield is identified in advance.
+ For positional sorting, assumes that the order of the lines in core
+ reflects their nominal order. */
+
+int
+compare_prepared (line1, line2)
+ struct lineinfo *line1, *line2;
+{
+ int i;
+ int tem;
+ char *text1, *text2;
+
+ /* Compare using the first keyfield, which has been found for us already */
+ if (keyfields[0].positional)
+ {
+ if (line1->text - text_base > line2->text - text_base)
+ tem = 1;
+ else
+ tem = -1;
+ }
+ else if (keyfields[0].numeric)
+ tem = line1->key.number - line2->key.number;
+ else
+ tem = compare_field (keyfields, line1->key.keytext, line1->keylen, 0,
+ line2->key, line2->keylen, 0);
+ if (tem)
+ {
+ if (keyfields[0].reverse)
+ return - tem;
+ return tem;
+ }
+
+ text1 = line1->text;
+ text2 = line2->text;
+
+ /* Compare using the second keyfield;
+ if that does not distinguish the lines, try the third keyfield; and so
+ on. */
+
+ for (i = 1; i < num_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], text1, &length1);
+ char *start2 = find_field (&keyfields[i], text2, &length2);
+ int tem = compare_field (&keyfields[i],
+ start1, length1, text1 - text_base,
+ start2, length2, text2 - text_base);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return - tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly */
+}
+
+/* Like compare_full but more general.
+ You can pass any strings, and you can say how many keyfields to use.
+ `pos1' and `pos2' should indicate the nominal positional ordering of
+ the two lines in the input. */
+
+int
+compare_general (str1, str2, pos1, pos2, use_keyfields)
+ char *str1, *str2;
+ long pos1, pos2;
+ int use_keyfields;
+{
+ int i;
+
+ /* Compare using the first keyfield;
+ if that does not distinguish the lines, try the second keyfield; and so
+ on. */
+
+ for (i = 0; i < use_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], str1, &length1);
+ char *start2 = find_field (&keyfields[i], str2, &length2);
+ int tem = compare_field (&keyfields[i], start1, length1, pos1, start2,
+ length2, pos2);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return - tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly */
+}
+
+/* Find the start and length of a field in `str' according to `keyfield'.
+ A pointer to the starting character is returned, and the length
+ is stored into the int that `lengthptr' points to. */
+
+char *
+find_field (keyfield, str, lengthptr)
+ struct keyfld *keyfield;
+ char *str;
+ long *lengthptr;
+{
+ char *start;
+ char *end;
+ char *(*fun) ();
+
+ if (keyfield->braced) fun = find_braced_pos;
+ else fun = find_pos;
+
+ start = ( *fun )(str, keyfield->startwords, keyfield->startchars,
+ keyfield->ignore_blanks);
+ if (keyfield->endwords < 0)
+ {
+ if (keyfield->braced)
+ end = find_braced_end (start);
+ else
+ {
+ end = start;
+ while (*end && *end != '\n') end++;
+ }
+ }
+ else
+ {
+ end = ( *fun )(str, keyfield->endwords, keyfield->endchars, 0);
+ if (end - str < start - str) end = start;
+ }
+ *lengthptr = end - start;
+ return start;
+}
+
+/* Find a pointer to a specified place within `str',
+ skipping (from the beginning) `words' words and then `chars' chars.
+ If `ignore_blanks' is nonzero, we skip all blanks
+ after finding the specified word. */
+
+char *
+find_pos (str, words, chars, ignore_blanks)
+ char *str;
+ int words, chars;
+ int ignore_blanks;
+{
+ int i;
+ char *p = str;
+
+ for (i = 0; i < words; i++)
+ {
+ char c;
+ /* Find next bunch of nonblanks and skip them. */
+ while ((c = *p) == ' ' || c == '\t') p++;
+ while ((c = *p) && c != '\n' && !(c == ' ' || c == '\t')) p++;
+ if (!*p || *p == '\n') return p;
+ }
+
+ while (*p == ' ' || *p == '\t') p++;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (!*p || *p == '\n') break;
+ p++;
+ }
+ return p;
+}
+
+/* Like find_pos but assumes that each field is surrounded by braces
+ and that braces within fields are balanced. */
+
+char *
+find_braced_pos (str, words, chars, ignore_blanks)
+ char *str;
+ int words, chars;
+ int ignore_blanks;
+{
+ int i;
+ int bracelevel;
+ char *p = str;
+ char c;
+
+ for (i = 0; i < words; i++)
+ {
+ bracelevel = 1;
+ while ((c = *p++) != '{' && c != '\n' && c);
+ if (c != '{')
+ return p - 1;
+ while (bracelevel)
+ {
+ c = *p++;
+ if (c == '{') bracelevel++;
+ if (c == '}') bracelevel--;
+ if (c == '\\') c = *p++; /* \ quotes braces and \ */
+ if (c == 0 || c == '\n') return p-1;
+ }
+ }
+
+ while ((c = *p++) != '{' && c != '\n' && c);
+
+ if (c != '{')
+ return p-1;
+
+ if (ignore_blanks)
+ while ((c = *p) == ' ' || c == '\t') p++;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (!*p || *p == '\n') break;
+ p++;
+ }
+ return p;
+}
+
+/* Find the end of the balanced-brace field which starts at `str'.
+ The position returned is just before the closing brace. */
+
+char *
+find_braced_end (str)
+ char *str;
+{
+ int bracelevel;
+ char *p = str;
+ char c;
+
+ bracelevel = 1;
+ while (bracelevel)
+ {
+ c = *p++;
+ if (c == '{') bracelevel++;
+ if (c == '}') bracelevel--;
+ if (c == '\\') c = *p++;
+ if (c == 0 || c == '\n') return p-1;
+ }
+ return p - 1;
+}
+
+long
+find_value (start, length)
+ char *start;
+ long length;
+{
+ while (length != 0L) {
+ if (isdigit(*start))
+ return atol(start);
+ length--;
+ start++;
+ }
+ return 0l;
+}
+
+/* Compare two fields (each specified as a start pointer and a character count)
+ according to `keyfield'. The sign of the value reports the relation between
+ the fields */
+
+int
+compare_field (keyfield, start1, length1, pos1, start2, length2, pos2)
+ struct keyfld *keyfield;
+ char *start1;
+ long length1;
+ long pos1;
+ char *start2;
+ long length2;
+ long pos2;
+{
+ if (keyfields[0].positional)
+ {
+ if (pos1 > pos2)
+ return 1;
+ else
+ return -1;
+ }
+ if (keyfield->numeric)
+ {
+ long value = find_value (start1, length1) - find_value (start2, length2);
+ if (value > 0) return 1;
+ if (value < 0) return -1;
+ return 0;
+ }
+ else
+ {
+ char *p1 = start1;
+ char *p2 = start2;
+ char *e1 = start1 + length1;
+ char *e2 = start2 + length2;
+
+ int fold_case = keyfield->fold_case;
+
+ while (1)
+ {
+ char c1, c2;
+
+ if (p1 == e1) c1 = 0;
+ else c1 = *p1++;
+ if (p2 == e2) c2 = 0;
+ else c2 = *p2++;
+
+ /* Ignore case of both if desired */
+
+ if (fold_case)
+ {
+ if (c1 >= 'A' && c1 <= 'Z') c1 = c1 + 040;
+ if (c2 >= 'A' && c2 <= 'Z') c2 = c2 + 040;
+ }
+
+ /* Actually compare */
+
+ /* Anything but a letter or digit is less than any letter or digit */
+ if ((isalnum (c1) == 0) != (isalnum (c2) == 0))
+ return (isalnum (c1)) ? 1 : -1;
+ if (c1 != c2) return c1 - c2;
+ if (!c1) break;
+ }
+ return 0;
+ }
+}
+
+/* A `struct linebuffer' is a structure which holds a line of text.
+ `readline' reads a line from a stream into a linebuffer
+ and works regardless of the length of the line. */
+
+struct linebuffer
+ {
+ long size;
+ char *buffer;
+ };
+
+/* Initialize a linebuffer for use */
+
+void
+initbuffer (linebuffer)
+ struct linebuffer *linebuffer;
+{
+ linebuffer->size = 200;
+ linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from `stream' into `linebuffer'.
+ Return the length of the line. */
+
+long
+readline (linebuffer, stream)
+ struct linebuffer *linebuffer;
+ FILE *stream;
+{
+ char *buffer = linebuffer->buffer;
+ char *p = linebuffer->buffer;
+ char *end = p + linebuffer->size;
+
+ while (1)
+ {
+ int c = getc (stream);
+ if (p == end)
+ {
+ buffer = (char *) xrealloc (buffer, linebuffer->size *= 2);
+ p += buffer - linebuffer->buffer;
+ end += buffer - linebuffer->buffer;
+ linebuffer->buffer = buffer;
+ }
+ if (c < 0 || c == '\n')
+ {
+ *p = 0;
+ break;
+ }
+ *p++ = c;
+ }
+
+ return p - buffer;
+}
+
+/* Sort the input files together when they are too big to sort in core */
+
+void
+sort_offline (infile, nfiles, total, outfile)
+ char *infile;
+ long total;
+ char *outfile;
+{
+ int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT; /* More
+ than enough */
+ char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+ FILE *istream = fopen (infile, "r");
+ int i;
+ struct linebuffer lb;
+ long linelength;
+
+ initbuffer (&lb);
+
+ /* Read in one line of input data. */
+
+ linelength = readline (&lb, istream);
+
+ /* Split up the input into `ntemps' temporary files, or maybe fewer,
+ and put the new files' names into `tempfiles' */
+
+ for (i = 0; i < ntemps; i++)
+ {
+ char *outname = maketempname (++tempcount);
+ FILE *ostream = fopen (outname, "w");
+ long tempsize = 0;
+
+ if (!ostream) pfatal_with_name (outname);
+ tempfiles[i] = outname;
+
+ /* Copy lines into this temp file as long as it does not make file "too
+ big" or until there are no more lines. */
+
+ while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT)
+ {
+ tempsize += linelength + 1;
+ fputs (lb.buffer, ostream);
+ putc ('\n', ostream);
+
+ /* Read another line of input data. */
+
+ linelength = readline (&lb, istream);
+ if (!linelength && feof (istream)) break;
+ }
+ fclose (ostream);
+ if (feof (istream)) break;
+ }
+
+ free (lb.buffer);
+
+ /* Record number of temp files we actually needed. */
+
+ ntemps = i;
+
+ /* Sort each tempfile into another tempfile.
+ Delete the first set of tempfiles and put the names of the second into
+ `tempfiles' */
+
+ for (i = 0; i < ntemps; i++)
+ {
+ char *newtemp = maketempname (++tempcount);
+ sort_in_core (&tempfiles[i], 1, MAX_IN_CORE_SORT, newtemp);
+ if (!keep_tempfiles)
+ unlink (tempfiles[i]);
+ tempfiles[i] = newtemp;
+ }
+
+ /* Merge the tempfiles together and indexify */
+
+ merge_files (tempfiles, ntemps, outfile);
+}
+
+/* Sort `infile', whose size is `total',
+ assuming that is small enough to be done in-core,
+ then indexify it and send the output to `outfile' (or to stdout). */
+
+void
+sort_in_core (infile, total, outfile)
+ char *infile;
+ long total;
+ char *outfile;
+{
+ char **nextline;
+ char *data = (char *) xmalloc (total + 1);
+ char *file_data;
+ long file_size;
+ FILE *ostream = stdout;
+ struct lineinfo *lineinfo;
+
+ /* Read the contents of the file into the moby array `data' */
+
+ int desc = open (infile, 0, 0);
+
+ if (desc < 0)
+ fatal ("failure reopening %s", infile);
+ file_size = READ (desc, data, total);
+ file_data = data;
+ data[file_size] = 0;
+
+ close (desc);
+
+ /* Sort routines want to know this address */
+
+ text_base = data;
+
+ /* Create the array of pointers to lines, with a default size frequently
+ enough. */
+
+ lines = total / 50;
+ if (!lines) lines = 2;
+ linearray = (char **) xmalloc (lines * sizeof (char *));
+
+ /* `nextline' points to the next free slot in this array.
+ `lines' is the allocated size. */
+
+ nextline = linearray;
+
+ /* Parse the input file's data, and make entries for the lines. */
+
+ nextline = parsefile (infile, nextline, file_data, file_size);
+
+ /* Sort the lines */
+
+ /* If we have enough space, find the first keyfield of each line in advance.
+ Make a `struct lineinfo' for each line, which records the keyfield
+ as well as the line, and sort them. */
+
+ lineinfo = (struct lineinfo *) malloc ((nextline - linearray) * sizeof
+ (struct lineinfo));
+
+ if (lineinfo)
+ {
+ struct lineinfo *lp;
+ char **p;
+
+ for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+ {
+ lp->text = *p;
+ lp->key.keytext = find_field (keyfields, *p, &lp->keylen);
+ if (keyfields[0].numeric)
+ lp->key.number = find_value (lp->key.keytext, lp->keylen);
+ }
+
+ qsort (lineinfo, nextline - linearray, sizeof (struct lineinfo),
+ compare_prepared);
+
+ for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+ *p = lp->text;
+
+ free (lineinfo);
+ }
+ else
+ qsort (linearray, nextline - linearray, sizeof (char *), compare_full);
+
+ /* Open the output file */
+
+ if (outfile)
+ {
+ ostream = fopen (outfile, "w");
+ if (!ostream)
+ pfatal_with_name (outfile);
+ }
+
+ writelines (linearray, nextline - linearray, ostream);
+ if (outfile) fclose (ostream);
+
+ free (linearray);
+ free (data);
+}
+
+/* Parse an input string in core into lines.
+ `data' is the input string, and `size' is its length.
+ Data goes in `linearray' starting at `nextline'.
+ The value returned is the first entry in `linearray' still unused. */
+
+char **
+parsefile (filename, nextline, data, size)
+ char *filename;
+ char **nextline;
+ char *data;
+ long size;
+{
+ char *p, *end;
+ char **line = nextline;
+
+ p = data;
+ end = p + size;
+ *end = 0;
+
+ while (p != end)
+ {
+ *line = p;
+ while (*p && *p != '\n') p++;
+ if (p != end) p++;
+
+ /* This feature will be installed later. */
+ /* if (discard_empty_lines && p == *line + 1) continue; */
+
+ line++;
+ if (line == linearray + lines)
+ {
+ char **old = linearray;
+ linearray = (char **) xrealloc (linearray, sizeof (char *) * (lines
+ *= 4));
+ line += linearray - old;
+ }
+ }
+
+ return line;
+}
+
+/* Indexification is a filter applied to the sorted lines
+ as they are being written to the output file.
+ Multiple entries for the same name, with different page numbers,
+ get combined into a single entry with multiple page numbers.
+ The first braced field, which is used for sorting, is discarded.
+ However, its first character is examined, folded to lower case,
+ and if it is different from that in the previous line fed to us
+ a \initial line is written with one argument, the new initial.
+
+ If an entry has four braced fields, then the second and third
+ constitute primary and secondary names.
+ In this case, each change of primary name
+ generates a \primary line which contains only the primary name,
+ and in between these are \secondary lines which contain
+ just a secondary name and page numbers.
+*/
+
+/* The last primary name we wrote a \primary entry for.
+ If only one level of indexing is being done, this is the last name seen */
+char *lastprimary;
+int lastprimarylength; /* Length of storage allocated for lastprimary */
+
+/* Similar, for the secondary name. */
+char *lastsecondary;
+int lastsecondarylength;
+
+/* Zero if we are not in the middle of writing an entry.
+ One if we have written the beginning of an entry but have not
+ yet written any page numbers into it.
+ Greater than one if we have written the beginning of an entry
+ plus at least one page number. */
+int pending;
+
+/* The initial (for sorting purposes) of the last primary entry written.
+ When this changes, a \initial {c} line is written */
+
+char * lastinitial;
+
+int lastinitiallength;
+
+/* When we need a string of length 1 for the value of lastinitial,
+ store it here. */
+
+char lastinitial1[2];
+
+/* Initialize static storage for writing an index */
+
+void
+init_index ()
+{
+ pending = 0;
+ lastinitial = lastinitial1;
+ lastinitial1[0] = 0;
+ lastinitial1[1] = 0;
+ lastinitiallength = 0;
+ lastprimarylength = 100;
+ lastprimary = (char *) xmalloc (lastprimarylength + 1);
+ bzero (lastprimary, lastprimarylength + 1);
+ lastsecondarylength = 100;
+ lastsecondary = (char *) xmalloc (lastsecondarylength + 1);
+ bzero (lastsecondary, lastsecondarylength + 1);
+}
+
+static int pnr_begin = -1; /* current page number range */
+static int pnr_end = -1;
+
+/* Indexify. Merge entries for the same name,
+ insert headers for each initial character, etc. */
+
+void
+indexify (line, ostream)
+ char *line;
+ FILE *ostream;
+{
+ char *primary, *secondary, *pagenumber;
+ int number;
+ int primarylength, secondarylength, pagelength;
+ int nosecondary;
+ int initiallength;
+ char *initial;
+ char initial1[2];
+ register char *p;
+
+ /* First, analyze the parts of the entry fed to us this time */
+
+ p = find_braced_pos (line, 0, 0, 0);
+ if (*p == '{')
+ {
+ initial = p;
+ /* Get length of inner pair of braces starting at p,
+ including that inner pair of braces. */
+ initiallength = find_braced_end (p + 1) + 1 - p;
+ }
+ else
+ {
+ initial = initial1;
+ initial1[0] = *p;
+ initial1[1] = 0;
+ initiallength = 1;
+
+ if (initial1[0] >= 'a' && initial1[0] <= 'z')
+ initial1[0] -= 040;
+ }
+
+ pagenumber = find_braced_pos (line, 1, 0, 0);
+ pagelength = find_braced_end (pagenumber) - pagenumber;
+ if (pagelength == 0)
+ abort ();
+
+ primary = find_braced_pos (line, 2, 0, 0);
+ primarylength = find_braced_end (primary) - primary;
+
+ secondary = find_braced_pos (line, 3, 0, 0);
+ nosecondary = !*secondary;
+ if (!nosecondary)
+ secondarylength = find_braced_end (secondary) - secondary;
+
+ /* If the primary is different from before, make a new primary entry */
+ if (strncmp (primary, lastprimary, primarylength))
+ {
+ /* Close off current secondary entry first, if one is open */
+ if (pending)
+ {
+ put_range(ostream);
+ fputs ("}\n", ostream);
+ pending = 0;
+ }
+
+ /* If this primary has a different initial, include an entry for the
+ initial */
+ if (initiallength != lastinitiallength || strcmp (initial, lastinitial))
+ {
+ (void)fprintf (ostream, "\n\n\\initial {");
+ if (strchr("^~\\",*initial) != (char*)NULL)
+ (void)fprintf(ostream,"\verb|%c|",*initial);
+ else
+ {
+ if (strchr("&$#%_{}",*initial) != (char*)NULL)
+ putc('\\',ostream); /* protect special characters */
+ fwrite (initial, 1, initiallength, ostream);
+ }
+ (void)fprintf (ostream, "}\n", initial);
+ if (initial == initial1)
+ {
+ lastinitial = lastinitial1;
+ *lastinitial1 = *initial1;
+ }
+ else
+ {
+ lastinitial = initial;
+ }
+ lastinitiallength = initiallength;
+ }
+
+ /* Make the entry for the primary. */
+ if (nosecondary)
+ fputs ("\\entry {", ostream);
+ else
+ fputs ("\\primary {", ostream);
+ fwrite (primary, primarylength, 1, ostream);
+ if (nosecondary)
+ {
+ fputs ("}{", ostream);
+ pending = 1;
+ }
+ else
+ fputs ("}\n", ostream);
+
+ /* Record name of most recent primary */
+ if (lastprimarylength < primarylength)
+ {
+ lastprimarylength = primarylength + 100;
+ lastprimary = (char *) xrealloc (lastprimary,
+ 1 + lastprimarylength);
+ }
+ strncpy (lastprimary, primary, primarylength);
+ lastprimary[primarylength] = 0;
+
+ /* There is no current secondary within this primary, now */
+ lastsecondary[0] = 0;
+ }
+
+ /* Should not have an entry with no subtopic following one with a subtopic */
+
+ if (nosecondary && *lastsecondary)
+ error ("entry %s follows an entry with a secondary name", line);
+
+ /* Start a new secondary entry if necessary */
+ if (!nosecondary && strncmp (secondary, lastsecondary, secondarylength))
+ {
+ if (pending)
+ {
+ put_range(ostream);
+ fputs ("}\n", ostream);
+ pending = 0;
+ }
+
+ /* Write the entry for the secondary. */
+ fputs ("\\secondary {", ostream);
+ fwrite (secondary, secondarylength, 1, ostream);
+ fputs ("}{", ostream);
+ pending = 1;
+
+ /* Record name of most recent secondary */
+ if (lastsecondarylength < secondarylength)
+ {
+ lastsecondarylength = secondarylength + 100;
+ lastsecondary = (char *) xrealloc (lastsecondary,
+ 1 + lastsecondarylength);
+ }
+ strncpy (lastsecondary, secondary, secondarylength);
+ lastsecondary[secondarylength] = 0;
+ }
+
+ /* Here to add one more page number to the current entry */
+ if (isdigit(*pagenumber)) /* then non-negative arabic page
+ number */
+ {
+ number = atoi(pagenumber);
+ if (pnr_begin < 0) /* start new range */
+ {
+ pnr_begin = number;
+ pnr_end = number;
+ }
+ else if (number == (pnr_end + 1)) /* extend range */
+ pnr_end = number;
+ else /* output current range and start new one */
+ {
+ put_range(ostream);
+ pnr_begin = number;
+ pnr_end = number;
+ pending++;
+ }
+ }
+ else /* non-arabic page number (probably roman numerals) */
+ {
+ if (pnr_begin >= 0) /* output current page range */
+ {
+ put_range(ostream);
+ pending++;
+ }
+ if (pending > 1)
+ fputs (", ", ostream); /* Punctuate first, if this is not the first */
+ pending++;
+ fwrite (pagenumber, pagelength, 1, ostream);
+ }
+}
+
+void
+put_range(ostream) /* output current page number range */
+ FILE *ostream;
+{
+ if (pnr_begin > 0) /* output pending range */
+ {
+ if (pending > 1)
+ fputs (", ", ostream); /* Punctuate first, this is not the first */
+ if (pnr_end > pnr_begin)
+ (void)fprintf(ostream,"%d--%d",pnr_begin,pnr_end);
+ else
+ (void)fprintf(ostream,"%d",pnr_begin);
+ pnr_begin = -1;
+ pnr_end = -1;
+ }
+}
+
+
+/* Close out any unfinished output entry */
+
+void
+finish_index (ostream)
+ FILE *ostream;
+{
+ put_range(ostream);
+ if (pending)
+ fputs ("}\n", ostream);
+ free (lastprimary);
+ free (lastsecondary);
+}
+
+/* Copy the lines in the sorted order.
+ Each line is copied out of the input file it was found in. */
+
+void
+writelines (linearray, nlines, ostream)
+ char **linearray;
+ int nlines;
+ FILE *ostream;
+{
+ char **stop_line = linearray + nlines;
+ char **next_line;
+
+ init_index ();
+
+ /* Output the text of the lines, and free the buffer space */
+
+ for (next_line = linearray; next_line != stop_line; next_line++)
+ {
+ /* If -u was specified, output the line only if distinct from previous
+ one. */
+ if (next_line == linearray
+ /* Compare previous line with this one, using only the explicitly
+ specd keyfields */
+ || compare_general (*(next_line - 1), *next_line, 0L, 0L,
+ num_keyfields))
+ {
+ char *p = *next_line;
+ char c;
+ while ((c = *p++) && c != '\n');
+ *(p-1) = 0;
+ indexify (*next_line, ostream);
+ }
+ }
+
+ finish_index (ostream);
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+ merge them and output the result.
+ Returns nonzero if any input file fails to be sorted.
+
+ This is the high-level interface that can handle an unlimited number of
+ files. */
+
+#define MAX_DIRECT_MERGE 10
+
+int
+merge_files (infiles, nfiles, outfile)
+ char **infiles;
+ int nfiles;
+ char *outfile;
+{
+ char **tempfiles;
+ int ntemps;
+ int i;
+ int value = 0;
+ int start_tempcount = tempcount;
+
+ if (nfiles <= MAX_DIRECT_MERGE)
+ return merge_direct (infiles, nfiles, outfile);
+
+ /* Merge groups of MAX_DIRECT_MERGE input files at a time,
+ making a temporary file to hold each group's result. */
+
+ ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE;
+ tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+ for (i = 0; i < ntemps; i++)
+ {
+ int nf = MAX_DIRECT_MERGE;
+ if (i + 1 == ntemps)
+ nf = nfiles - i * MAX_DIRECT_MERGE;
+ tempfiles[i] = maketempname (++tempcount);
+ value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]);
+ }
+
+ /* All temporary files that existed before are no longer needed
+ since their contents have been merged into our new tempfiles.
+ So delete them. */
+ flush_tempfiles (start_tempcount);
+
+ /* Now merge the temporary files we created. */
+
+ merge_files (tempfiles, ntemps, outfile);
+
+ free (tempfiles);
+
+ return value;
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+ merge them and output the result.
+ Returns nonzero if any input file fails to be sorted.
+
+ This version of merging will not work if the number of
+ input files gets too high. Higher level functions
+ use it only with a bounded number of input files. */
+
+int
+merge_direct (infiles, nfiles, outfile)
+ char **infiles;
+ int nfiles;
+ char *outfile;
+{
+ struct linebuffer *lb1, *lb2;
+ struct linebuffer **thisline, **prevline;
+ FILE **streams;
+ int i;
+ int nleft;
+ int lossage = 0;
+ int *file_lossage;
+ struct linebuffer *prev_out = 0;
+ FILE *ostream = stdout;
+
+ if (outfile)
+ ostream = fopen (outfile, "w");
+ if (!ostream) pfatal_with_name (outfile);
+
+ init_index ();
+
+ if (nfiles == 0)
+ {
+ if (outfile)
+ fclose (ostream);
+ return 0;
+ }
+
+ /* For each file, make two line buffers.
+ Also, for each file, there is an element of `thisline'
+ which points at any time to one of the file's two buffers,
+ and an element of `prevline' which points to the other buffer.
+ `thisline' is supposed to point to the next available line from the file,
+ while `prevline' holds the last file line used,
+ which is remembered so that we can verify that the file is properly
+ sorted. */
+
+ /* lb1 and lb2 contain one buffer each per file */
+ lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+ lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+
+ /* thisline[i] points to the linebuffer holding the next available line in
+ file i, or is zero if there are no lines left in that file. */
+ thisline = (struct linebuffer **) xmalloc (nfiles * sizeof (struct
+ linebuffer *));
+ /* prevline[i] points to the linebuffer holding the last used line from file
+ i. This is just for verifying that file i is properly sorted. */
+ prevline = (struct linebuffer **) xmalloc (nfiles * sizeof (struct
+ linebuffer *));
+ /* streams[i] holds the input stream for file i. */
+ streams = (FILE **) xmalloc (nfiles * sizeof (FILE *));
+ /* file_lossage[i] is nonzero if we already know file i is not properly
+ sorted. */
+ file_lossage = (int *) xmalloc (nfiles * sizeof (int));
+
+ /* Allocate and initialize all that storage */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ initbuffer (&lb1[i]);
+ initbuffer (&lb2[i]);
+ thisline[i] = &lb1[i];
+ prevline[i] = &lb2[i];
+ file_lossage[i] = 0;
+ streams[i] = fopen (infiles[i], "r");
+ if (!streams[i])
+ pfatal_with_name (infiles[i]);
+
+ (void)readline (thisline[i], streams[i]);
+ }
+
+ /* Keep count of number of files not at eof */
+ nleft = nfiles;
+
+ while (nleft)
+ {
+ struct linebuffer *best = 0;
+ struct linebuffer *exch;
+ int bestfile = -1;
+ int i;
+
+ /* Look at the next avail line of each file; choose the least one. */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ if (thisline[i] &&
+ (!best ||
+ 0 < compare_general (best->buffer, thisline[i]->buffer,
+ (long) bestfile, (long) i, num_keyfields)))
+ {
+ best = thisline[i];
+ bestfile = i;
+ }
+ }
+
+ /* Output that line, unless it matches the previous one and we don't
+ want duplicates */
+
+ if (!(prev_out &&
+ !compare_general (prev_out->buffer, best->buffer, 0L, 1L,
+ num_keyfields)))
+ indexify (best->buffer, ostream);
+ prev_out = best;
+
+ /* Now make the line the previous of its file, and fetch a new line from
+ that file */
+
+ exch = prevline[bestfile];
+ prevline[bestfile] = thisline[bestfile];
+ thisline[bestfile] = exch;
+
+ while (1)
+ {
+ /* If the file has no more, mark it empty */
+
+ if (feof (streams[bestfile]))
+ {
+ thisline[bestfile] = 0;
+ nleft--; /* Update the number of files still not empty */
+ break;
+ }
+ (void)readline (thisline[bestfile], streams[bestfile]);
+ if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile])) break;
+ }
+ }
+
+ finish_index (ostream);
+
+ /* Free all storage and close all input streams */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ fclose (streams[i]);
+ free (lb1[i].buffer);
+ free (lb2[i].buffer);
+ }
+ free (file_lossage);
+ free (lb1);
+ free (lb2);
+ free (thisline);
+ free (prevline);
+ free (streams);
+
+ if (outfile)
+ fclose (ostream);
+
+ return lossage;
+}
+
+/* Print error message and exit. */
+
+void
+fatal (s1, s2)
+ char *s1, *s2;
+{
+ error (s1, s2);
+
+ EXIT (1);
+}
+
+/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+
+void
+error (s1, s2)
+ char *s1, *s2;
+{
+ (void)printf ("texi: ");
+ (void)printf (s1, s2);
+ (void)printf ("\n");
+}
+
+void
+pfatal_with_name (name)
+ char *name;
+{
+
+#ifdef OS_VAXVMS
+ extern noshare int errno;
+ extern noshare int sys_nerr;
+ extern noshare char *sys_errlist[];
+#else
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+#endif
+
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat ("", sys_errlist[errno], " for %s");
+ else
+ s = "cannot open %s";
+ fatal (s, name);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of s1, s2,
+ s3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+char*
+xmalloc (size)
+ int size;
+{
+ char* result = (char *)malloc (size);
+ if (!result)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+
+char*
+xrealloc (ptr, size)
+ char *ptr;
+ int size;
+{
+ char* result = (char *)realloc (ptr, size);
+ if (!result)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+#include "strchr.h"
diff --git a/dviware/beebe/utils/texidx.hlp b/dviware/beebe/utils/texidx.hlp
new file mode 100644
index 0000000000..4d95933cc5
--- /dev/null
+++ b/dviware/beebe/utils/texidx.hlp
@@ -0,0 +1,183 @@
+ TeXIDX - TeX/LaTeX Index Filter
+ [07-Jan-88]
+
+TeXIDX (TeXINDEX on Unix systems) is a filter for converting the
+index file output of TeX and LaTeX to a form suitable for later
+input and generation of an index, with entries sorted by primary
+text entries, and within these, sorted by secondary text entries,
+and with duplicate page numbers eliminated. Elision of page
+ranges is not yet supported.
+
+TeXIDX expects one or more files of index entries output by TeX
+or LaTeX in the forms
+
+\entry{sort key}{page number}{primary entry}
+\entry{sort key}{page number}{primary entry}{secondary entry}
+
+Several examples are given below.
+
+TeXIDX is run by
+
+@TeXIDX file1 file2 ... filen
+
+and produces output files with the same name, but the letter `s'
+appended. Thus `foo.idx' is transformed to `foo.idxs'.
+
+The output of TeXIDX will contain lines like:
+
+\initial {c} % before the first topic whose
+ % initial is c
+\entry {topic}{pagelist} % for a topic that is used
+ % without subtopics
+\primary {topic} % for the beginning of a topic
+ % that is used with subtopics
+\secondary {subtopic}{pagelist} % for each subtopic.
+
+All sorting is by the sort key field ONLY, with letter case
+IGNORED. This means that if two primary/secondary fields have
+the same leading text, a sort key must be given which includes
+both the primary and secondary fields to preserve the correct
+order, and this key must be distinguishable from another which
+just happens to have a primary string equal to the concatenated
+primary and secondary strings of the first. For example,
+
+\entry{text editing}{18}{text editing}
+\entry{text}{20}{text}
+\entry{text<TAB>editing}{32}{text}{editing}
+\entry{text<TAB>buffering}{57}{text}{buffering}
+
+will produce correct index entries
+
+ text, 20
+ buffering, 57
+ editing, 32
+ text editing, 37
+
+whereas simple juxtaposition of the primary and secondary fields
+in the sort keys
+
+\entry{text editing}{18}{text editing}
+\entry{text}{20}{text}
+\entry{text editing}{32}{text}{editing}
+\entry{text buffering}{57}{text}{buffering}
+
+will produce INCORRECT ordering:
+
+ text, 20
+ buffering, 57
+ text editing, 18
+ editing, 32
+
+Any ASCII character which collates below space (dec. 32) will do
+as a separator between the primary and secondary fields in the
+sort key, but the only one that TeX will accept as input without
+modification of character \catcode's is <TAB> (dec. 9).
+Therefore, make sure that <TAB> characters are not used in the
+primary or secondary text values themselves.
+
+In order for TeXIDX to be used, you must first provide TeX/LaTeX
+with definitions of macros that create the output index file;
+neither the TeX manmac macros (p. 423ff of the TeXbook) or the
+LaTeX \index{} macros (p. 78, p. 189 of the LaTeX User's Guide
+and Reference Manual) are suitable. Once TeXIDX has been run,
+you must have definitions of \initial, \entry, \primary, and
+\secondary so that the index file can be processed.
+
+Since these definitions only have to be done once, they have been
+put in a LaTeX style file which can be automatically included in
+the documentstyle option list:
+
+\documentstyle[gnuindex]{...}
+
+This will cause the file texinputs:gnuindex.sty to be read by
+LaTeX at startup. This file defines \initial, \entry, \primary,
+and \secondary, so that LaTeX can format your index, and provides
+you with two macros to use to generate index entries.
+
+\INDEX{sortkey}{primary}
+\SUBINDEX{sortkey}{primary}{secondary}
+
+For \SUBINDEX{}, the {secondary} field is automatically appended
+to the sort key, but separated from it by an ASCII <TAB>
+character; in most cases, this makes it possible to use the just
+primary field as the sort key too, as long as the primary and
+secondary fields do not have special characters, font changes, or
+TeX control sequences embedded in them.
+
+To save some typing, and reduce the chances of error, you will
+probably want to produce your own macros which reference these.
+Here are two useful ones:
+
+\newcommand{\X}[1]{{#1}\INDEX{#1}{#1}}
+\newcommand{\XX}[2]{{#1}\SUBINDEX{#1}{#1}{#2}}
+
+You can then type
+
+ \X{gnats and gnus}
+
+to get the phrase `gnats and gnus' into the document text, as
+well as into the index both as a sort key, and as a primary
+field. Typing
+
+ This chapter will discuss the cooking of
+ \XX{gnats and gnus}{cooking directions} ...
+
+will put the same phrase `gnats and gnus' into the document text,
+but the index will get the sort key `gnats and gnus<TAB>cooking
+directions', a primary field `gnats and gnus', and a secondary
+field `cooking directions'. You would use \XX{} instead of \X{}
+when you wanted to make the index entry more precise, but only
+have the primary string in the running text.
+
+For those occasions when you need special fonts, or TeX control
+sequences, in your index, you can still use \INDEX{} and
+\SUBINDEX{} directly:
+
+ \INDEX{LaTeX's gnus}{\string\LaTeX{}'s gnus}
+ \INDEX{gnats}{\string\sc GNATS}
+
+Note the use of `\string' in front of each control sequence--it
+prevents the expansion of the following control sequence. That
+way, your index file will contain the words `\LaTeX' and `\sc',
+instead of the messy expansions of these.
+
+In summary, then, here is what your `foo.ltx' file might look like:
+
+ \documentstyle[gnuindex]{...}
+ \makeindex
+ \begin{document}
+ ...
+ \begin{theindex}
+ \input{foo.idxs} % Change this to whatever your file is called
+ \end{theindex}
+ \end{document}
+
+To process it, you need to run LaTeX twice and TeXIDX once:
+
+@LaTeX foo.ltx
+@TeXIDX foo.idx
+@LaTeX foo.ltx
+
+TeXIDX was written by Richard Stallman as part of the GNU Project
+at the Free Software Foundation in Cambridge, MA, and is in the
+public domain (though subject to a liberal copyright contained in
+the source file). It uses no proprietary software and should be
+implementable with most C compilers on micros, minis, and
+mainframes. In particular, all sorting is done with its own
+code, rather than relying on system or library sorting routines.
+The sorting is done in-core when possible, and otherwise,
+automatically spills to scratch files which are individually
+sorted, then merged.
+
+Nelson H.F. Beebe
+Center for Scientific Computing
+South Physics Building
+University of Utah
+Salt Lake City, UT 84112
+ Tel: (801) 581-5254
+
+Net mail:
+ BEEBE@SCIENCE.UTAH.EDU {preferred}
+ BEEBE@CS.UTAH.EDU
+ BEEBE@CTRSCI.UTAH.EDU
+ BEEBEN@RUAC.UTAH.EDU
diff --git a/dviware/beebe/utils/unhd.c b/dviware/beebe/utils/unhd.c
new file mode 100644
index 0000000000..456adec9f5
--- /dev/null
+++ b/dviware/beebe/utils/unhd.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+Process a file output by hd back into an 8-bit binary file. Characters
+out of the range 040..0176 are ignored.
+
+Usage:
+ unhd infile outfile
+
+The open mode flags passed to fopen() are likely to require modification
+outside of TOPS-20.
+
+[15-Aug-87]
+***********************************************************************/
+
+#include <stdio.h>
+#define COMMENT '!' /* marks start of comment to end-of-line */
+
+void
+main(argc,argv)
+int argc;
+char* argv[];
+{
+ FILE* in;
+ FILE* out;
+ register int c;
+
+ if (argc < 2)
+ {
+ (void)fprintf(stderr,"Usage: unhd infile outfile");
+ exit(0);
+ }
+ if ((in = fopen(argv[1],"rb")) == (FILE*)NULL)
+ exit(1);
+ if ((out = fopen(argv[2],"wb8")) == (FILE*)NULL)
+ exit(2);
+
+ while ((c = getc(in)) != EOF)
+ {
+ if (c == COMMENT)
+ {
+ while (((c = getc(in)) != EOF) && (c != '\n'))
+ /* flush comment */;
+ }
+ else if (c > 037)
+ {
+ if (c == '\\')
+ {
+ c = getc(in) - '0';
+ c = (c << 3) + (getc(in) - '0');
+ c = (c << 3) + (getc(in) - '0');
+ }
+ putc(c,out);
+ }
+ }
+ exit(0);
+}
diff --git a/dviware/beebe/utils/vms/streamlf.fdl b/dviware/beebe/utils/vms/streamlf.fdl
new file mode 100644
index 0000000000..be33609a40
--- /dev/null
+++ b/dviware/beebe/utils/vms/streamlf.fdl
@@ -0,0 +1,13 @@
+IDENT "17-APR-1987 15:13:54 VAX/VMS ANALYZE/RMS_FILE Utility"
+
+SYSTEM
+ SOURCE VAX/VMS
+
+FILE
+ ORGANIZATION sequential
+
+RECORD
+ BLOCK_SPAN yes
+ CARRIAGE_CONTROL carriage_return
+ FORMAT stream_lf
+
diff --git a/dviware/beebe/utils/vms/variable.fdl b/dviware/beebe/utils/vms/variable.fdl
new file mode 100644
index 0000000000..3527be3444
--- /dev/null
+++ b/dviware/beebe/utils/vms/variable.fdl
@@ -0,0 +1,13 @@
+IDENT "17-APR-1987 17:20:30 VAX/VMS ANALYZE/RMS_FILE Utility"
+
+SYSTEM
+ SOURCE VAX/VMS
+
+FILE
+ ORGANIZATION sequential
+
+RECORD
+ BLOCK_SPAN yes
+ CARRIAGE_CONTROL carriage_return
+ FORMAT variable
+
diff --git a/dviware/beebe/utils/ws87.pas b/dviware/beebe/utils/ws87.pas
new file mode 100644
index 0000000000..2bf88fa988
--- /dev/null
+++ b/dviware/beebe/utils/ws87.pas
@@ -0,0 +1,45 @@
+PROGRAM Ws87;
+ {
+ **********************************************************************
+ Copy an 8-bit file to a 7-bit file, turning characters with bit 8
+ set into 4-character octal escape sequences \nnn. This is useful in
+ analyzing WordStar microcomputer word processor files.
+
+ Usage:
+
+ @WS87
+ Old 8-bit file: filespec
+ New 7-bit file: filespec
+
+ [10-Oct-85]
+ **********************************************************************
+ }
+VAR
+ fp8,fp7 : PACKED FILE OF integer;
+BEGIN
+Rewrite(output,'tty:');
+Write('Old 8-bit file: ');
+Reset(fp8,'':@,'/e/b:8');
+Write('New 7-bit file: ');
+Rewrite(fp7,'':@,'/e/b:7');
+WHILE NOT Eof(fp8) DO
+ BEGIN
+ IF fp8^ > 127 THEN
+ BEGIN
+ fp7^ := ord('\');
+ Put(fp7);
+ fp7^ := (fp8^ DIV 64) + ord('0');
+ Put(fp7);
+ fp7^ := ((fp8^ DIV 8) MOD 8) + ord('0');
+ Put(fp7);
+ fp7^ := (fp8^ MOD 8) + ord('0');
+ Put(fp7)
+ END
+ ELSE
+ BEGIN
+ fp7^ := fp8^;
+ Put(fp7)
+ END;
+ Get(fp8)
+ END;
+END.
diff --git a/dviware/beebe/utils/wsltex.c b/dviware/beebe/utils/wsltex.c
new file mode 100644
index 0000000000..ddfc5442e6
--- /dev/null
+++ b/dviware/beebe/utils/wsltex.c
@@ -0,0 +1,948 @@
+/* program Wsltex */
+
+ /*
+ ********************************************************************
+ Copy an 8-bit file to a 7-bit file, turning characters with bit 8
+ set into 4-character octal escape sequences \nnn. This is useful in
+ analyzing WordStar microcomputer word processor files. Many
+ sequences which can be recognized as doing something useful are
+ turned into LaTeX command sequences. Comments below describe the
+ sequences which are recognized and translated.
+
+ Usage:
+
+ @WSLTEX WordStar_inputfile >LaTeX_outputfile
+
+ Remarks:
+ This program was converted automatically from Pascal to C by James
+ Peterson's Pascal-to-C translator from Carnegie-Mellon University.
+ Hand editing was required on all I/O references, which are not
+ converted satisfactorily (e.g. the Pascal file variable points to
+ the current input character returned by get(), while in C, one must
+ explicitly save the result of getc()). Comment and type declaration
+ formatting where also rearranged by hand. Defined constants were
+ changed to upper-case following the usual convenient C convention of
+ visible differences between variables and constants, and functions
+ and macros.
+
+ The conversion of a test 188K Ph.D. thesis file produced identical
+ results with both versions. Pascal compilation was much faster than
+ the PCC compiler. The conversion time with the Pascal version was
+ 15.5 sec. In the C version using putc(), it was 25.1 sec; changing
+ putc() to use of write() with large buffers further reduced the time
+ to 21.2 sec.
+
+ [21-Dec-85] conversion from Pascal
+ [11-Oct-85] original version
+ ********************************************************************
+ */
+
+
+#include <stdio.h>
+#include <file.h> /* for TOPS-20 open magic */
+
+/* One of OS_UNIX or OS_TOPS20 should be defined at compile time. */
+/* Default is OS_UNIX */
+
+#ifndef OS_TOPS20
+#define OS_TOPS20 0
+#define OS_UNIX 1
+#else
+#define OS_UNIX 0
+#endif
+
+#if OS_UNIX
+#define WRITELN(fp) putc('\n',fp)
+#else
+#define WRITELN(fp) {putc('\r',fp);putc('\n',fp);}
+#endif
+
+#if OS_TOPS20
+#define EMPTY_BUFFER {if (the_next > 0) \
+ _write(fileno(LaTeX_file),the_buffer,the_next);\
+ the_next = 0;}
+#else
+#define EMPTY_BUFFER {if (the_next > 0) \
+ write(fileno(LaTeX_file),the_buffer,the_next);\
+ the_next = 0;}
+#endif
+
+typedef int BOOLEAN;
+
+#define FALSE 0
+
+#define TRUE 1
+
+#define NUL '\0'
+
+#define BEL '\07'
+
+#define CR '\r'
+
+#define ESC '\033'
+
+#define FF '\f'
+
+#define HT '\t'
+
+#define LF '\n'
+
+#define MAXRING 256 /* limit for character ring */
+
+#define MAXSPECIAL 100 /* limit for warning when special
+ strings (underline, bold, etc) exceed
+ this length */
+
+#define MAXBUF 16384 /* large buffer for I/O efficiency */
+
+#define UNSET 0x8000 /* use most-negative 16-bit integer */
+
+FILE *WordStar_file; /* 8-bit input file */
+FILE *LaTeX_file; /* 7-bit or 8-bit output file */
+
+char *the_buffer; /* the output buffer (malloc()'ed) */
+int the_next; /* index of next empty slot in
+ the_buffer[]*/
+
+int ring_index; /* index into ring[] */
+char ring[MAXRING+1]; /* ring buffer for current output
+ context */
+
+BOOLEAN hyphen_break; /* hyphen break flag */
+BOOLEAN eol; /* end-of-line flag */
+BOOLEAN is_underline; /* underline et al flags */
+BOOLEAN is_subscript;
+BOOLEAN is_superscript;
+BOOLEAN is_bold;
+BOOLEAN is_alternate;
+
+int bi_eol; /* input byte offset at end-of-line */
+int bi_underline;
+int bi_subscript;
+int bi_superscript;
+int bi_bold;
+int bi_alternate;
+
+int bo_eol; /* output byte offset at end-of-line */
+int bo_underline;
+int bo_subscript;
+int bo_superscript;
+int bo_bold;
+int bo_alternate;
+
+int input_byte_offset;
+int output_byte_offset;
+int last_c; /* previous input character */
+
+/* global functions */
+
+#if OS_TOPS20
+#define Begin_alternate Beg_alternate /* unique to 6 characters */
+#define Begin_boldface Beg_boldface
+#endif
+
+void Begin_alternate ();
+void Begin_boldface ();
+void End_alternate ();
+void End_boldface ();
+void Line_feed ();
+void Superscript ();
+void Subscript ();
+void Underline ();
+void Warning ();
+void W_byte ();
+void W_char ();
+void W_octal ();
+void W_string ();
+
+char *strchr();
+
+
+/**********************************************************************/
+/*-->main */
+main(argc,argv) /* Main -- WSLTEX */
+int argc;
+char *argv[];
+{
+ int fp;
+ register int c; /* current input character */
+ register int c7; /* low-order 7 bits of c */
+
+ if (argc < 2)
+ {
+ (void)fprintf(stderr,
+ "%%Usage: %s WordStar_infile >LaTeX_outfile",argv[0]);
+ WRITELN(stderr);
+ exit(1);
+ }
+
+ /* only 7-bit bytes required, so stdout is okay to use provided
+ it does not do CRLF <--> LF translation. On TOPS-20, this is
+ suppressed by loading this program with a special version of the I/O
+ library. */
+
+ LaTeX_file = stdout;
+
+#if OS_TOPS20
+ /* Read file in bytesize 8 with binary flag set to prevent
+ CRLF <--> LF mapping; the "rb" or "wb" flag is not sufficient for
+ this because PCC-20 maintains two places internally
+ where the binary flag is set, and both are used! */
+
+ if ((fp =
+ open(argv[1], FATT_RDONLY | FATT_SETSIZE | FATT_BINARY,8)) >= 0)
+ WordStar_file = fdopen(fp,"rb");
+ else
+ WordStar_file = (FILE *)NULL;
+#else
+ WordStar_file = fopen(argv[1],"rb");
+#endif
+
+ if (WordStar_file == (FILE *)NULL)
+ {
+
+ (void)fprintf(stderr,
+ "?Open failure on WordStar input file [%s]",argv[1]);
+ WRITELN(stderr);
+ exit(1);
+ }
+
+ /* Initializations -- in alphabetical order */
+
+ bi_alternate = -1;
+ bi_bold = -1;
+ bi_subscript = -1;
+ bi_superscript = -1;
+ bi_underline = -1;
+ bo_alternate = -1;
+ bo_bold = -1;
+ bo_subscript = -1;
+ bo_superscript = -1;
+ bo_underline = -1;
+ eol = TRUE;
+ hyphen_break = FALSE;
+ input_byte_offset = -1;
+ is_bold = FALSE;
+ is_subscript = FALSE;
+ is_superscript = FALSE;
+ is_underline = FALSE;
+ last_c = -1;
+ output_byte_offset = -1;
+
+ for (ring_index=0; ring_index <= MAXRING; ring_index++)
+ ring[ring_index] = ' ';
+ ring_index = 0;
+
+ if ((the_buffer = (char *)malloc(MAXBUF)) == (char *)NULL)
+ {
+ (void)fprintf(stderr,
+ "?Unable to allocate output buffer of size %d",MAXBUF);
+ WRITELN(stderr);
+ exit(1);
+ }
+ the_next = 0;
+
+ /*
+ =====================================================================
+ WordStar makes heavy use of the 8-th (high-order) bit of 8-bit ASCII
+ characters. In general, it turns on that bit for
+ -- any character (0..127) at end-of-word
+ -- any character (0..127) at end-of-line
+ -- "hard" line break on CTL-M
+ -- "hard" page break on CTL-L
+
+ A discretionary hyphen (which can be removed on joining the lines) at
+ end-of-line is encoded as "-\215" (i.e. "-<\200|CTL-M>").
+
+ A required hyphen falling at end-of-line is encoded as "-\040\215"
+ (i.e. followed by a space).
+
+ Comment lines and WordStar command lines begin with a dot.
+
+ "Hard" line breaks are encoded as \215\015 (i.e.
+ "<\200|CTL-M><CTL-J>"); these occur between double-space lines.
+
+ "Soft" line breaks are encoded as <CTL-M><CTL-J>; these occur at
+ paragraph ends.
+
+ Centered text is stored centered without any special markings.
+
+ Underlined text is bracketed by CTL-S.
+
+ Boldface text is bracketed by CTL-E ..text.. CTL-R.
+
+ Superscripts are bracketed by CTL-T.
+
+ Subscripts are bracketed by CTL-V.
+
+ Alternate typewheel strings appear as CTL-Q ..text.. CTL-W. Some of
+ these at least are mnemonic (e = epsilon, m = mu, . = centered dot).
+
+ CTL-R also appears after all sub/superscript sequences, apparently
+ functioning as a "return to normal" state.
+ =====================================================================
+ */
+
+ while ((c = getc(WordStar_file)) != EOF)
+ {
+ if (c < 32) /* ordinary control character */
+ {
+ switch (c)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4: /* CTL-@ .. CTL-D */
+ W_octal(c);
+ break;
+
+ case 5: /* CTL-E */
+ Begin_boldface();
+ break;
+
+ case 6:
+ case 7:
+ case 8: /* CTL-F .. CTL-H */
+ W_octal(c);
+ break;
+
+ case 9: /* CTL-I */
+ W_byte(HT);
+ break;
+
+ case 10: /* CTL-J */
+ Line_feed();
+ break;
+
+ case 11: /* CTL-K */
+ W_octal(c);
+ break;
+
+ case 12: /* CTL-L */
+ W_byte(FF);
+ break;
+
+ case 13: /* CTL-M */
+ if (last_c == (int)('-'))
+ hyphen_break = TRUE;
+ else if (!hyphen_break)
+ W_byte(CR);
+ break;
+
+ case 14:
+ case 15:
+ case 16: /* CTL-N .. CTL-P */
+ W_octal(c);
+ break;
+
+ case 17: /* CTL-Q */
+ Begin_alternate();
+ break;
+
+ case 18: /* CTL-R */
+ if (is_bold)
+ End_boldface();
+ /* ELSE discard character */
+ break;
+
+ case 19: /* CTL-S */
+ Underline();
+ break;
+
+ case 20: /* CTL-T */
+ Superscript();
+ break;
+
+ case 21: /* CTL-U */
+ W_octal(c);
+ break;
+
+ case 22: /* CTL-V */
+ Subscript();
+ break;
+
+ case 23: /* CTL-W */
+ End_alternate();
+ break;
+
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31: /* CTL-X .. CTL-_ */
+ W_octal(c);
+ break;
+ }
+ /* case */
+ }
+ else if (strchr("#$%&~_^\\{}",c))
+ /* LaTeX special characters must be quoted by backslash */
+ {
+ W_char('\\');
+ W_byte(c);
+ }
+ else if (c == (int)('.')) /* check for WordStar comment */
+ {
+ if (eol)
+ W_string("%-WS-% ");
+ W_byte(c);
+ }
+ else if (c < 128) /* c in 32 .. 127 */
+ W_byte(c);
+ else /* c > 127 */
+ {
+ c7 = c & 0177; /* lop off 8-th bit */
+ switch (c7)
+ {
+ case 0: /* CTL-@ */
+ W_octal(c7);
+ break;
+
+ case 1: /* CTL-A */
+ W_octal(c7);
+ break;
+
+ case 2: /* CTL-B */
+ W_octal(c7);
+ break;
+
+ case 3: /* CTL-C */
+ W_octal(c7);
+ break;
+
+ case 4: /* CTL-D */
+ W_octal(c7);
+ break;
+
+ case 5: /* CTL-E */
+ Begin_boldface();
+ break;
+
+ case 6: /* CTL-F */
+ W_octal(c7);
+ break;
+
+ case 7: /* CTL-G */
+ W_octal(c7);
+ break;
+
+ case 8: /* CTL-H */
+ W_octal(c7);
+ break;
+
+ case 9: /* CTL-I */
+ W_byte(HT);
+ break;
+
+ case 10: /* CTL-J */
+ Line_feed();
+ break;
+
+ case 11: /* CTL-K */
+ W_octal(c7);
+ break;
+
+ case 12: /* CTL-L */
+ W_byte(FF);
+ break;
+
+ case 13: /* CTL-M */
+ if (last_c == (int)('-'))
+ hyphen_break = TRUE;
+ else if (!hyphen_break)
+ {
+ if (bo_eol < output_byte_offset)
+ W_byte(CR);
+ /* not double space */
+ }
+ break;
+
+ case 14: /* CTL-N */
+ W_octal(c7);
+ break;
+
+ case 15: /* CTL-O */
+ W_octal(c7);
+ break;
+
+ case 16: /* CTL-P */
+ W_octal(c7);
+ break;
+
+ case 17: /* CTL-Q */
+ Begin_alternate();
+ break;
+
+ case 18: /* CTL-R */
+ if (is_bold)
+ End_boldface();
+ /* ELSE discard character */
+ break;
+
+ case 19: /* CTL-S */
+ Underline();
+ break;
+
+ case 20: /* CTL-T */
+ Superscript();
+ break;
+
+ case 21: /* CTL-U */
+ W_octal(c7);
+ break;
+
+ case 22: /* CTL-V */
+ Subscript();
+ break;
+
+ case 23: /* CTL-W */
+ End_alternate();
+ break;
+
+ case 24: /* CTL-X */
+ W_octal(c7);
+ break;
+
+ case 25: /* CTL-Y */
+ W_octal(c7);
+ break;
+
+ case 26: /* CTL-Z */
+ W_octal(c7);
+ break;
+
+ case 27: /* CTL-[ */
+ W_octal(c7);
+ break;
+
+ case 28: /* CTL-\ */
+ W_octal(c7);
+ break;
+
+ case 29: /* CTL-] */
+ W_octal(c7);
+ break;
+
+ case 30: /* CTL-^ */
+ W_octal(c7);
+ break;
+
+ case 31: /* CTL-_ */
+ W_octal(c7);
+ break;
+
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ W_byte(c7);
+ break;
+
+ case 46: /* period */
+ if (eol)
+ W_string("%-WS-% ");
+ W_byte(c7);
+ break;
+
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ W_byte(c7);
+ break;
+
+ case 127:
+ W_octal(c7);
+ break;
+
+ default:
+ W_octal(c7);
+ break;
+ } /* CASE */
+ }
+ last_c = c;
+ input_byte_offset++;
+ }
+ EMPTY_BUFFER;
+}
+/* Main -- WSLTEX */
+
+
+/**********************************************************************/
+/*-->Begin_alternate */
+void
+Begin_alternate ()
+{
+ if (is_alternate)
+ Warning("BEGIN ALTERNATE CHARACTER SET command encounted inside\
+ alternate sequence",
+ bo_alternate,output_byte_offset);
+ bi_alternate = input_byte_offset;
+ bo_alternate = output_byte_offset;
+ is_alternate = TRUE;
+ W_string("{\\alt ");
+}
+/* Begin_alternate */
+
+
+/**********************************************************************/
+/*-->Begin_boldface */
+void
+Begin_boldface ()
+{
+ if (is_bold)
+ Warning("BEGIN BOLDFACE command encountered inside boldface",
+ bo_bold,output_byte_offset);
+ bi_bold = input_byte_offset;
+ bo_bold = output_byte_offset;
+ is_bold = TRUE;
+ W_string("{\\bf ");
+}
+/* Begin_boldface */
+
+/**********************************************************************/
+/*-->End_alternate */
+void
+End_alternate ()
+{
+ if (is_alternate)
+ {
+ if ((bo_alternate + MAXSPECIAL) < output_byte_offset)
+ Warning("Long ALTERNATE CHARACTER SET sequence",
+ bo_alternate,output_byte_offset);
+ }
+ else
+ Warning("END ALTERNATE CHARACTER SET command encountered\
+ outside alternate text",bo_alternate,output_byte_offset);
+ is_alternate = FALSE;
+ W_byte((int)('}'));
+}
+/* End_alternate */
+
+
+/**********************************************************************/
+/*-->End_boldface */
+void
+End_boldface ()
+{
+ if (is_bold)
+ {
+ if ((bo_bold + MAXSPECIAL) < output_byte_offset)
+ Warning("Long BOLDFACE sequence",
+ bo_bold,output_byte_offset);
+ }
+ else
+ Warning("END BOLDFACE command encountered outside boldface",
+ bo_bold,output_byte_offset);
+ is_bold = FALSE;
+ W_byte((int)('}'));
+}
+/* End_boldface */
+
+
+/**********************************************************************/
+/*-->Line_feed */
+void
+Line_feed ()
+{
+ if (hyphen_break) /* discard line break */
+ hyphen_break = FALSE;
+ else
+ {
+ if (bo_eol < output_byte_offset) /* text on line */
+ W_byte(LF);
+ else /* empty line */
+ {
+ if (last_c != (0200 | CR))
+ W_byte(LF);
+ }
+ }
+}
+/* Line_feed */
+
+
+/**********************************************************************/
+/*-->strchr() */
+char *
+strchr(s,c) /* return pointer to c in s[], or (char*)NULL */
+char *s;
+char c;
+{
+ while (*s && (*s != c))
+ ++s;
+ if (*s == c)
+ return (s);
+ else
+ return ((char *)NULL);
+}
+/* strchr */
+
+
+/**********************************************************************/
+/*-->Superscript */
+void
+Superscript ()
+{
+ if (is_superscript)
+ /* ending old superscript */
+ {
+ if ((bo_superscript + MAXSPECIAL) < output_byte_offset)
+ Warning("Long SUPERSCRIPT sequence",
+ bo_superscript,output_byte_offset);
+ W_byte((int)('}'));
+ }
+ else /* beginning new superscript */
+ {
+ bi_superscript = input_byte_offset;
+ bo_superscript = output_byte_offset;
+ W_string("^{");
+ }
+ is_superscript = !is_superscript;
+}
+/* Superscipt */
+
+
+/**********************************************************************/
+/*-->Subscript */
+void
+Subscript ()
+{
+ if (is_subscript)
+ /* ending old superscript */
+ {
+ if ((bo_subscript + MAXSPECIAL) < output_byte_offset)
+ Warning("Long SUBSCRIPT sequence",
+ bo_subscript,output_byte_offset);
+ W_byte((int)('}'));
+ }
+ else /* beginning new superscript */
+ {
+ bi_subscript = input_byte_offset;
+ bo_subscript = output_byte_offset;
+ W_string("_{");
+ }
+ is_subscript = !is_subscript;
+}
+/* Subscript */
+
+
+/**********************************************************************/
+/*-->Underline */
+void
+Underline ()
+{
+ if (is_underline)
+ /* ending old underline */
+ {
+ if ((bo_underline + MAXSPECIAL) < output_byte_offset)
+ Warning("Long UNDERLINE sequence",
+ bo_underline,output_byte_offset);
+ W_byte((int)('}'));
+ }
+ else /* beginning new underline */
+ {
+ bi_underline = input_byte_offset;
+ bo_underline = output_byte_offset;
+ W_string("{\\em ");
+ }
+ /* underlined text is \emphasized in LaTeX */
+ is_underline = !is_underline;
+}
+/* Underline */
+
+
+/**********************************************************************/
+/*-->Warning */
+void
+Warning (s,b1,b2)
+char s[];
+int b1, b2 /* output byte range, or UNSET,UNSET */;
+{
+ int k;
+ WRITELN(stderr); /* !!!! temporary for debugging !!!! */
+ WRITELN(stderr); /* !!!! temporary for debugging !!!! */
+ (void)fprintf(stderr,
+ "------------------------------------------------------------");
+ WRITELN(stderr);
+ (void)fprintf(stderr,"%s",s);
+ WRITELN(stderr);
+ if (b1 != UNSET)
+ {
+ (void)fprintf(stderr,"\toutput byte range = %d .. %d",b1,b2);
+ WRITELN(stderr);
+ }
+ (void)fprintf(stderr,"\tinput byte offset = %d",input_byte_offset);
+ WRITELN(stderr);
+ (void)fprintf(stderr,"\toutput byte offset = %d",output_byte_offset);
+ WRITELN(stderr);
+ (void)fprintf(stderr,"\tcurrent context = [");
+ WRITELN(stderr);
+ for (k=ring_index; k <= MAXRING; k++)
+ putc(ring[k],stderr);
+ for (k=0; k <= ((MAXRING + ring_index - 1) % MAXRING); k++)
+ putc(ring[k],stderr);
+ WRITELN(stderr);
+ (void)fprintf(stderr,"\t]");
+ WRITELN(stderr);
+ (void)fprintf(stderr,
+ "------------------------------------------------------------");
+ WRITELN(stderr);
+}
+/* Warning */
+
+
+/**********************************************************************/
+/*-->W_byte */
+void
+W_byte (c)
+int c;
+{
+ ring[ring_index] = (char)c;
+ ring_index = (ring_index++) % MAXRING;
+
+ /* All output bytes go through this single piece of code, so
+ we optimize output by buffering it in large blocks. The use
+ of write() instead of fwrite() avoids CR LF <--> LF translation
+ on most machines, and on some is significantly more efficient. */
+
+ if (the_next >= MAXBUF)
+ EMPTY_BUFFER;
+ the_buffer[the_next++] = c;
+
+ eol = (c == LF);
+ output_byte_offset++;
+ if (eol)
+ {
+ bi_eol = input_byte_offset;
+ bo_eol = output_byte_offset;
+ }
+}
+/* W_byte */
+
+
+/**********************************************************************/
+/*-->W_char */
+void
+W_char (c)
+char c;
+{
+ W_byte((int)(c));
+}
+/* W_char */
+
+
+/**********************************************************************/
+/*-->W_octal */
+void
+W_octal (c)
+int c;
+{
+ c = c & 0377;
+ W_byte((int)('\\'));
+ W_byte((c >> 6) + (int)('0'));
+ W_byte(((c >> 3) & 07) + (int)('0'));
+ W_byte((c & 07) + (int)('0'));
+}
+/* W_octal */
+
+
+/**********************************************************************/
+/*-->W_string */
+void
+W_string (s)
+char *s;
+{
+ while (*s)
+ W_byte((int)(*s++));
+}
+/* W_string */
diff --git a/dviware/beebe/utils/wsltex.let b/dviware/beebe/utils/wsltex.let
new file mode 100644
index 0000000000..189afc4d56
--- /dev/null
+++ b/dviware/beebe/utils/wsltex.let
@@ -0,0 +1,72 @@
+12-Oct-85 17:47:22-MDT,00000003019;000000000001
+Date: 12 Oct 1985 1747-MDT
+From: Beebe (Nelson H.F. Beebe)
+Subject: [Beebe (Nelson H.F. Beebe): WordStar to LaTeX translation]
+To: op.hendry, fh.harris
+cc: BEEBE
+
+2
+ ---------------
+
+Date: 11 Oct 1985 1804-MDT
+From: Beebe (Nelson H.F. Beebe)
+Subject: WordStar to LaTeX translation
+To: C-GRISS, CH.JM.DOWNING, FH.HARRIS, MA.PETERSEN, OP.BOWMAN, OP.DUNCAN,
+To: OP.HENDRY, OP.LICHTY, OP.WILLETT, VI.FULLERTON, GU.KILLIAN
+cc: BEEBE, MA.HOPPENSTEADT, CH.JM.KLING, BI.PARKINSON, bi.kofOID, CH.MAYNE,
+cc: vi.leaver, ma.othmer
+
+I completed today a pair of programs for assisting in the
+conversion of files from WordStar (a popular microcomputer
+word processor) to LaTeX. The subject manuscript was Pete
+Conwell's Ph.D. thesis, which Ed Leaver is going to massage
+further into a form that LaTeX will accept.
+
+WordStar file format makes extensive use of the high-order
+bit of 8-bit ASCII characters to flag "hard" and "soft" line
+breaks, underlining, subscripting, superscripting,
+boldfacing, etc. The exact sequences to do this are
+described in a document which the authors of WordStar market
+for $500; needless to say, I did not buy it, but just
+reverse engineered the job.
+
+The WordStar file was KERMITed to the DEC-20 from an IBM PC
+by issuing SET FILE 8-BIT then SERVER to KERMIT-20, followed
+by a normal KERMIT-PC SEND command.
+
+Both programs are in the directory APS:<BEEBE.UTILITY>.
+
+The first of them, WS87.PAS, can be used to copy any 8-bit
+file to a 7-bit file, turning all characters in the range
+128 .. 255 into printable \nnn octal escape sequences. This
+allows examination of the WordStar file on the DEC-20, and
+could be used for other 8-bit files as well.
+
+The second, WSLTEX, is a 535-line workhorse which identifies
+all the WordStar magic sequences used in Pete's thesis and
+turns them into appropriate LaTeX commands. It would be
+straightforward to modify WSLTEX now for any other document
+formatter, and if necessary, to recognize other WordStar
+sequences not used in the thesis.
+
+Conversion time was 19 sec on the DEC-20 for 6000 lines of
+WordStar input.
+
+WordStar is not a well-designed formatter, in that it does
+not consistently identify document features. In particular,
+double spacing actually appears verbatim (and is converted
+to single spacing by WSLTEX, except at paragraph
+boundaries), and centered text (as in chapter titles) is
+just centered without any identification. Consequently, an
+editing session is still necessary to take the output of
+WSLTEX and convert it into true LaTeX input. The important
+thing is that every special feature in the input WordStar
+document is preserved, something which is not possible if
+the 8-th bit is just lopped off.
+
+Help yourselves. Extensions, modifications, and bug reports
+are welcome. It's all public domain, so don't sell it!
+-------
+ ========
+-------
+ ========
diff --git a/dviware/beebe/utils/wsltex.pas b/dviware/beebe/utils/wsltex.pas
new file mode 100644
index 0000000000..cc2119fef9
--- /dev/null
+++ b/dviware/beebe/utils/wsltex.pas
@@ -0,0 +1,537 @@
+PROGRAM Wsltex;
+ {
+ **********************************************************************
+ Copy an 8-bit file to a 7-bit file, turning characters with bit 8
+ set into 4-character octal escape sequences \nnn. This is useful in
+ analyzing WordStar microcomputer word processor files. Many
+ sequences which can be recognized as doing something useful are
+ turned into LaTeX command sequences. Comments below describe the
+ sequences which are recognized and translated.
+
+ Usage:
+
+ @WSLTEX
+ Old 8-bit file: filespec
+ New 7-bit file: filespec
+
+ [11-Oct-85]
+ **********************************************************************
+ }
+{ ^L }
+CONST
+ nul = 0;
+
+ bel = 7;
+
+ ht = 9;
+ lf = 10;
+
+ ff = 12;
+ cr = 13;
+
+ esc = 27;
+
+ maxring = 256; { limit for character ring }
+
+ maxspecial = 100; { limit for warning when special strings (underline,
+ bold, etc) exceed this length }
+
+ unset = MAXINT;
+
+VAR
+ wordstar_file,latex_file : PACKED FILE OF integer;
+ ring_index : integer;
+ ring : PACKED ARRAY [0 .. maxring] OF integer;
+ hyphen_break : boolean;
+ eol,is_underline,is_subscript,is_superscript,is_bold,
+ is_alternate : boolean;
+ bi_eol,bi_underline,bi_subscript,bi_superscript,bi_bold,
+ bi_alternate : integer;
+ bo_eol,bo_underline,bo_subscript,bo_superscript,bo_bold,
+ bo_alternate : integer;
+ input_byte_offset,output_byte_offset : integer;
+ empty_count,last_c,c : integer;
+{ ^L }
+PROCEDURE Warning(s : PACKED ARRAY [k1 .. k2 : integer] OF char;
+ b1,b2 : integer { output byte range, or unset,unset }
+ );
+ VAR k : integer;
+BEGIN
+ Writeln(tty); { !!!! temporary for debugging !!!! }
+ Writeln(tty); { !!!! temporary for debugging !!!! }
+ Writeln(tty,'----------------------------------------------------------');
+ Write(tty,'%');
+
+ FOR k := k1 TO k2 DO
+ Write(tty,s[k]);
+ Writeln(tty);
+ if b1 <> unset then
+ Writeln(tty,' output byte range = ',b1:0,' .. ',b2:0);
+ Writeln(tty,' input byte offset = ',input_byte_offset);
+ Writeln(tty,' output byte offset = ',output_byte_offset);
+ Writeln(tty,' current context = [');
+ FOR k := ring_index TO maxring DO
+ Write(tty,Chr(ring[k]));
+ FOR k := 0 TO ((maxring + ring_index - 1) MOD maxring) DO
+ Write(tty,Chr(ring[k]));
+ Writeln(tty);
+ Writeln(tty,' ]');
+ Writeln(tty,'----------------------------------------------------------');
+ Writeln(tty)
+END; { Warning }
+
+{ ^L }
+PROCEDURE W_byte(c : integer);
+BEGIN
+ ring[ring_index] := c;
+ ring_index := (ring_index + 1) MOD maxring;
+ latex_file^ := c;
+ eol := (c = lf);
+ Put(latex_file);
+ output_byte_offset := output_byte_offset + 1;
+ IF eol THEN
+ BEGIN
+ bi_eol := input_byte_offset;
+ bo_eol := output_byte_offset
+ END
+END; { W_byte }
+
+PROCEDURE W_char(c : char);
+BEGIN
+ W_byte(Ord(c))
+END; { W_char }
+{ ^L }
+PROCEDURE W_octal;
+BEGIN
+ W_byte(Ord('\'));
+ W_byte((wordstar_file^ DIV 64) + Ord('0'));
+ W_byte(((wordstar_file^ DIV 8) MOD 8) + Ord('0'));
+ W_byte((wordstar_file^ MOD 8) + Ord('0'))
+END; { W_octal }
+{ ^L }
+PROCEDURE W_string(s : PACKED ARRAY [k1 .. k2 : integer] OF char);
+ VAR k : integer;
+BEGIN
+ FOR k := k1 TO k2 DO
+ W_byte(Ord(s[k]))
+END; { W_string }
+{ ^L }
+PROCEDURE Begin_alternate;
+BEGIN
+ IF is_alternate THEN
+ Warning(
+'BEGIN ALTERNATE CHARACTER SET command encounted inside alternate sequence',
+ bo_alternate,output_byte_offset);
+ bi_alternate := input_byte_offset;
+ bo_alternate := output_byte_offset;
+ is_alternate := true;
+ W_string('{\alt ')
+END; { Begin_alternate }
+{ ^L }
+PROCEDURE Begin_boldface;
+BEGIN
+ IF is_bold THEN
+ Warning('BEGIN BOLDFACE command encountered inside boldface',
+ bo_bold,output_byte_offset);
+ bi_bold := input_byte_offset;
+ bo_bold := output_byte_offset;
+ is_bold := true;
+ W_string('{\bf ')
+END; { Begin_boldface }
+{ ^L }
+PROCEDURE End_alternate;
+BEGIN
+ IF is_alternate THEN
+ BEGIN
+ IF (bo_alternate + maxspecial) < output_byte_offset THEN
+ Warning('Long ALTERNATE CHARACTER SET sequence',
+ bo_alternate,output_byte_offset)
+ END
+ ELSE
+ Warning(
+'END ALTERNATE CHARACTER SET command encountered outside alternate text',
+ bo_alternate,output_byte_offset);
+ is_alternate := false;
+ W_byte(Ord('}'))
+END; { End_alternate }
+{ ^L }
+PROCEDURE End_boldface;
+BEGIN
+ IF is_bold THEN
+ BEGIN
+ IF (bo_bold + maxspecial) < output_byte_offset THEN
+ Warning('Long BOLDFACE sequence',bo_bold,output_byte_offset)
+ END
+ ELSE
+ Warning('END BOLDFACE command encountered outside boldface',
+ bo_bold,output_byte_offset);
+ is_bold := false;
+ W_byte(Ord('}'))
+END; { End_boldface }
+{ ^L }
+PROCEDURE Line_feed;
+BEGIN { line_feed }
+ IF hyphen_break THEN { discard line break }
+ hyphen_break := false
+ ELSE
+ BEGIN
+ IF bo_eol < output_byte_offset THEN { text on line }
+ W_byte(lf)
+ ELSE { empty line }
+ BEGIN
+ IF last_c <> (128 + cr) THEN
+ W_byte(lf)
+ END
+ END
+END; { Line_feed }
+{ ^L }
+PROCEDURE Superscript;
+BEGIN
+ IF is_superscript THEN { ending old superscript }
+ BEGIN
+ IF (bo_superscript + maxspecial) < output_byte_offset THEN
+ Warning('Long SUPERSCRIPT sequence',
+ bo_superscript,output_byte_offset);
+ W_byte(Ord('}'))
+ END
+ ELSE { beginning new superscript }
+ BEGIN
+ bi_superscript := input_byte_offset;
+ bo_superscript := output_byte_offset;
+ W_string('^{')
+ END;
+ is_superscript := NOT is_superscript
+END; { Superscipt }
+{ ^L }
+PROCEDURE Subscript;
+BEGIN
+ IF is_subscript THEN { ending old superscript }
+ BEGIN
+ IF (bo_subscript + maxspecial) < output_byte_offset THEN
+ Warning('Long SUBSCRIPT sequence',
+ bo_subscript,output_byte_offset);
+ W_byte(Ord('}'))
+ END
+ ELSE { beginning new superscript }
+ BEGIN
+ bi_subscript := input_byte_offset;
+ bo_subscript := output_byte_offset;
+ W_string('_{');
+ END;
+ is_subscript := NOT is_subscript
+END; { Subscript }
+{ ^L }
+PROCEDURE Underline;
+BEGIN
+ IF is_underline THEN { ending old underline }
+ BEGIN
+ IF (bo_underline + maxspecial) < output_byte_offset THEN
+ Warning('Long UNDERLINE sequence',
+ bo_underline,output_byte_offset);
+ W_byte(Ord('}'))
+ END
+ ELSE { beginning new underline }
+ BEGIN
+ bi_underline := input_byte_offset;
+ bo_underline := output_byte_offset;
+ W_string('{\em ')
+ END;
+ { underlined text is \emphasized in LaTeX }
+ is_underline := NOT is_underline
+END; { Underline }
+{ ^L }
+BEGIN { Main -- WSLTEX }
+
+Rewrite(output,'tty:');
+Write('Input WordStar 8-bit file: ');
+Reset(wordstar_file,'':@,'/e/b:8');
+Write('Output LaTeX 7-bit file: ');
+Rewrite(latex_file,'':@,'/e/b:7');
+
+{ Initializations -- in alphabetical order }
+bi_alternate := -1;
+bi_bold := -1;
+bi_subscript := -1;
+bi_superscript := -1;
+bi_underline := -1;
+bo_alternate := -1;
+bo_bold := -1;
+bo_subscript := -1;
+bo_superscript := -1;
+bo_underline := -1;
+eol := true;
+hyphen_break := false;
+input_byte_offset := -1;
+is_bold := false;
+is_subscript := false;
+is_superscript := false;
+is_underline := false;
+last_c := -1;
+output_byte_offset := -1;
+
+for ring_index := 0 to maxring do
+ ring[ring_index] := ord(' ');
+ring_index := 0;
+{
+========================================================================
+WordStar makes heavy use of the 8-th (high-order) bit of 8-bit ASCII
+characters. In general, it turns on that bit for
+-- any character (0..127) at end-of-word
+-- any character (0..127) at end-of-line
+-- "hard" line break on CTL-M
+-- "hard" page break on CTL-L
+
+A discretionary hyphen (which can be removed on joining the lines) at
+end-of-line is encoded as "-\215" (i.e. "-<\200|CTL-M>").
+
+A required hyphen falling at end-of-line is encoded as "-\040\215" (i.e.
+followed by a space).
+
+Comment lines and WordStar command lines begin with a dot.
+
+"Hard" line breaks are encoded as \215\015 (i.e. "<\200|CTL-M><CTL-J>");
+these occur between double-space lines.
+
+"Soft" line breaks are encoded as <CTL-M><CTL-J>; these occur at
+paragraph ends.
+
+Centered text is stored centered without any special markings.
+
+Underlined text is bracketed by CTL-S.
+
+Boldface text is bracketed by CTL-E ..text.. CTL-R.
+
+Superscripts are bracketed by CTL-T.
+
+Subscripts are bracketed by CTL-V.
+
+Alternate typewheel strings appear as CTL-Q ..text.. CTL-W. Some of
+these at least are mnemonic (e = epsilon, m = mu, . = centered dot).
+
+CTL-R also appears after all sub/superscript sequences, apparently
+functioning as a "return to normal" state.
+========================================================================
+}
+
+c := wordstar_file^;
+WHILE NOT Eof(wordstar_file) DO
+BEGIN
+ IF c < 32 THEN { ordinary control character }
+ BEGIN
+ CASE c OF
+ 0,1,2,3,4 : { CTL-@ .. CTL-D }
+ W_octal;
+
+ 5 : { CTL-E }
+ Begin_boldface;
+
+ 6,7,8 : { CTL-F .. CTL-H }
+ W_octal;
+
+ 9 : { CTL-I }
+ W_byte(ht);
+
+ 10 : { CTL-J }
+ Line_feed;
+
+ 11 : { CTL-K }
+ W_octal;
+
+ 12 : { CTL-L }
+ W_byte(ff);
+
+ 13 : { CTL-M }
+ IF last_c = Ord('-') THEN
+ hyphen_break := true
+ ELSE IF NOT hyphen_break THEN
+ W_byte(cr);
+
+ 14,15,16 : { CTL-N .. CTL-P }
+ W_octal;
+
+ 17 : { CTL-Q }
+ Begin_alternate;
+
+ 18 : { CTL-R }
+ IF is_bold THEN
+ End_boldface;
+ { ELSE discard character }
+
+ 19 : { CTL-S }
+ Underline;
+
+ 20 : { CTL-T }
+ Superscript;
+
+ 21 : { CTL-U }
+ W_octal;
+
+ 22 : { CTL-V }
+ Subscript;
+
+ 23 : { CTL-W }
+ End_alternate;
+
+ 24,25,26,27,28,29,30,31 : { CTL-X .. CTL-_ }
+ W_octal
+ END { case }
+ END
+ ELSE IF chr(c) IN ['#','$','%','&','~','_','^','\','{','}']
+ THEN { LaTeX special characters must be quoted by backslash }
+ BEGIN
+ W_char('\');
+ W_byte(c)
+ END
+ ELSE IF c = Ord('.') THEN { check for WordStar comment }
+ BEGIN
+ IF eol THEN
+ W_string('%-WS-% ');
+ W_byte(c)
+ END
+ ELSE IF c < 128 THEN { c in 32 .. 127 }
+ W_byte(c)
+ ELSE { c > 127 }
+ BEGIN
+ c := c - 128; { lop off 8-th bit }
+ CASE c OF
+ 0 : { CTL-@ }
+ W_octal;
+
+ 1 : { CTL-A }
+ W_octal;
+
+ 2 : { CTL-B }
+ W_octal;
+
+ 3 : { CTL-C }
+ W_octal;
+
+ 4 : { CTL-D }
+ W_octal;
+
+ 5 : { CTL-E }
+ Begin_boldface;
+
+ 6 : { CTL-F }
+ W_octal;
+
+ 7 : { CTL-G }
+ W_octal;
+
+ 8 : { CTL-H }
+ W_octal;
+
+ 9 : { CTL-I }
+ W_byte(ht);
+
+
+ 10 : { CTL-J }
+ Line_feed;
+
+ 11 : { CTL-K }
+ W_octal;
+
+ 12 : { CTL-L }
+ W_byte(ff);
+
+
+ 13 : { CTL-M }
+ IF last_c = Ord('-') THEN
+ hyphen_break := true
+ ELSE IF NOT hyphen_break THEN
+ BEGIN
+ IF bo_eol < output_byte_offset THEN { not double space}
+ W_byte(cr);
+ END;
+
+ 14 : { CTL-N }
+ W_octal;
+
+ 15 : { CTL-O }
+ W_octal;
+
+ 16 : { CTL-P }
+ W_octal;
+
+ 17 : { CTL-Q }
+ Begin_alternate;
+
+ 18 : { CTL-R }
+ IF is_bold THEN
+ End_boldface;
+ { ELSE discard character }
+
+ 19 : { CTL-S }
+ Underline;
+
+ 20 : { CTL-T }
+ Superscript;
+
+ 21 : { CTL-U }
+ W_octal;
+
+ 22 : { CTL-V }
+ Subscript;
+
+ 23 : { CTL-W }
+ End_alternate;
+
+ 24 : { CTL-X }
+ W_octal;
+
+ 25 : { CTL-Y }
+ W_octal;
+
+ 26 : { CTL-Z }
+ W_octal;
+
+ 27 : { CTL-[ }
+ W_octal;
+
+ 28 : { CTL-\ }
+ W_octal;
+
+ 29 : { CTL-] }
+ W_octal;
+
+ 30 : { CTL-^ }
+ W_octal;
+
+ 31 : { CTL-_ }
+ W_octal;
+
+ 32,33,34,35,36,37,38,39,40,41,42,43,44,45 :
+ W_byte(c);
+
+ 46 : { period }
+ BEGIN
+ IF eol THEN
+ W_string('%-WS-% ');
+ W_byte(c)
+ END;
+
+ 47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 :
+ W_byte(c);
+
+ 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
+ 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95 :
+ W_byte(c);
+
+ 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,
+ 111,112,113,114,115,116,117,118,119,120,121,122,123,124,
+ 125,126 :
+ W_byte(c);
+
+ 127 :
+ W_octal;
+
+ OTHERS :
+ W_octal;
+ END { CASE }
+ END;
+ last_c := wordstar_file^;
+ input_byte_offset := input_byte_offset + 1;
+ Get(wordstar_file);
+ c := wordstar_file^
+END;
+END. { Main -- WSLTEX }
diff --git a/dviware/beebe/utils/xref b/dviware/beebe/utils/xref
new file mode 100644
index 0000000000..f45093cd3b
--- /dev/null
+++ b/dviware/beebe/utils/xref
@@ -0,0 +1,25 @@
+#!/bin/csh
+# Make a libref "references" and "referenced-by" pair of cross
+# reference tables on stdout from a list of C sources files.
+#
+# Usage:
+# xref filelist >foo.xref
+#
+# [09-Sep-87]
+
+set TEMPFILE = xref$$
+
+# Make "name<tab>file" list in $TEMPFILE
+cxref $* | awk -f xref1.awk | sort -u > $TEMPFILE
+
+# Make "references" libref-style map
+echo Created `date` on `hostname`
+echo xref $*
+sort $TEMPFILE | awk -f xref2.awk
+
+# Make "referenced-by" libref-style map
+echo " Created" `date` on `hostname`
+echo xref $*
+awk '{if ($2 != "") printf "%s\t%s\n",$2,$1;}' $TEMPFILE | sort | awk -f xref3.awk
+
+/bin/rm -f $TEMPFILE
diff --git a/dviware/beebe/utils/xref1.awk b/dviware/beebe/utils/xref1.awk
new file mode 100644
index 0000000000..556997b3b1
--- /dev/null
+++ b/dviware/beebe/utils/xref1.awk
@@ -0,0 +1,56 @@
+# Make a "nm"-style cross-reference table which can be later
+# converted into neat tabular form.
+#
+# Usage:
+# cxref filelist | awk -f xref1.awk | sort -u | >foo.nm
+#
+# Sun OS 3.3 cxref listings look like
+#
+#dvijep.c:
+#
+# SYMBOL FILE FUNCTION LINE
+#
+# #undef ./machdefs.h -- 382 404 406 413 427 432 436 441 446 466
+# ./main.h -- 17 45 67 78
+# ABS()
+# ./fixpos.h -- 24
+# ./gendefs.h -- *16
+# ./movedown.h -- 27
+# ./moveover.h -- 30
+# ./option.h -- 123
+# dvijep.c -- 554
+# etc..
+#
+# We want to extract from this a file with entries
+# name<tab>xref
+#
+# We ignore lines with only one field (eliminating the filename lines),
+# and reuse the previous name if the first field is empty. We
+# eliminate leading "./" in filenames, and discard lines for which
+# name == 'SYMBOL', or which have an absolute pathname in xref (we
+# don't want to cross-reference names defined in /usr/include/*.h),
+# or which have only digits or asterisks in xref (line numbers).
+# [18-Jul-87]
+BEGIN {name = "";}
+{
+ if (substr($0,1,1) != " ")
+ {
+ name = $1;
+ xref = $2;
+ }
+ else
+ xref = $1;
+ if ((name == "SYMBOL") && (xref == "FILE"))
+ next;
+ else if (substr(xref,1,1) == "/")
+ next;
+ else if (substr(name,1,1) == "#")
+ next;
+ else if (xref != "")
+ {
+ if (substr(xref,1,2) == "./")
+ xref = substr(xref,3)
+ if (xref !~ /[0-9*]/)
+ printf "%s\t%s\n",name,xref;
+ }
+}
diff --git a/dviware/beebe/utils/xref2.awk b/dviware/beebe/utils/xref2.awk
new file mode 100644
index 0000000000..93eb37a6a5
--- /dev/null
+++ b/dviware/beebe/utils/xref2.awk
@@ -0,0 +1,74 @@
+# Convert a sorted file with entries
+# name<tab>file
+# to a libref-style "references" map on stdout (4 entries per line)
+# [09-Sep-87]
+BEGIN {
+ FS = "\t";
+ nref = 0;
+ caller = "";
+ print "*********************************************************************";
+ print "* ..Name.. * ...Referenced in File... *";
+ print "*********************************************************************";
+ print "* * *";
+}
+
+{
+ if (($1 != caller) && (caller != ""))
+ {
+ if (length(caller) > 20)
+ the_caller = substr(caller,1,20);
+ else
+ the_caller = caller;
+ printf "* %-20s<-",the_caller;
+ nref4 = 4*int((nref + 3)/4);
+
+ for (k = nref; k < nref4; ++k)
+ refs[k] = " ";
+ nref = nref4;
+ for (k = 0; k < nref; )
+ {
+ printf " %-10s",refs[k];
+ ++k;
+ if ((k % 4) == 0)
+ {
+ printf "*\n";
+ if (k < nref)
+ {
+ printf "* *";
+ }
+ }
+ }
+ nref = 0;
+ print "* * *";
+ }
+ caller = $1;
+ if (length($2) > 10)
+ $2 = substr($2,1,10);
+ refs[nref] = $2;
+ nref++; # awk treats refs[nref++] as refs[++nref], sigh...
+
+}
+
+END {
+ printf "* %-20s<-",caller;
+ nref4 = 4*int((nref + 3)/4);
+ for (k = nref; k < nref4; ++k)
+ refs[k] = " ";
+ nref = nref4;
+ for (k = 0; k < nref; )
+ {
+ printf " %-10s",refs[k];
+ ++k;
+ if ((k % 4) == 0)
+ {
+ printf "*\n";
+ if (k < nref)
+ {
+ printf "* *";
+ }
+ }
+ }
+ nref = 0;
+ print "* * *";
+ print "*********************************************************************";
+}
diff --git a/dviware/beebe/utils/xref3.awk b/dviware/beebe/utils/xref3.awk
new file mode 100644
index 0000000000..935c310afa
--- /dev/null
+++ b/dviware/beebe/utils/xref3.awk
@@ -0,0 +1,83 @@
+# Convert a sorted file with entries
+# file<tab>name
+# to a libref-style "referenced-by" map on stdout (4 entries per line)
+# [09-Sep-87]
+BEGIN {
+ FS = "\t";
+ nref = 0;
+ callee = "";
+ print "*********************************************************************";
+ print "* ..File.. * ...Global Symbol... *";
+ print "*********************************************************************";
+ print "* * *";
+}
+
+{
+ if (($1 != "") && ($1 != callee) && (callee != ""))
+ {
+ if (length(callee) > 20)
+ the_callee = substr(callee,1,20);
+ else
+ the_callee = callee;
+ printf "* %-20s->",the_callee;
+ nref4 = 4*int((nref + 3)/4);
+
+ for (k = nref; k < nref4; ++k)
+ refby[k] = " ";
+ nref = nref4;
+ for (k = 0; k < nref; )
+ {
+ printf " %-10s",refby[k];
+ ++k;
+ if ((k % 4) == 0)
+ {
+ printf "*\n";
+ if (k < nref)
+ {
+ printf "* *";
+ }
+ }
+ }
+ nref = 0;
+ print "* * *";
+ }
+ if ($1 != "")
+ callee = $1; # first type--initial entry for new callee
+ if ($2 == "")
+ $2 = $4; # second type--same callee, different caller
+ if ($2 != "") # not third type
+ {
+ if (length($2) > 10)
+ $2 = substr($2,1,10);
+ refby[nref] = $2;
+ nref++; # awk treats refby[nref++] as refby[++nref], sigh...
+ }
+}
+
+END {
+ if (length(callee) > 20)
+ the_callee = substr(callee,1,20);
+ else
+ the_callee = callee;
+ printf "* %-20s->",the_callee;
+ nref4 = 4*int((nref + 3)/4);
+ for (k = nref; k < nref4; ++k)
+ refby[k] = " ";
+ nref = nref4;
+ for (k = 0; k < nref; )
+ {
+ printf " %-10s",refby[k];
+ ++k;
+ if ((k % 4) == 0)
+ {
+ printf "*\n";
+ if (k < nref)
+ {
+ printf "* *";
+ }
+ }
+ }
+ nref = 0;
+ print "* * *";
+ print "*********************************************************************";
+}
diff --git a/dviware/beebe/utils/xxu.c b/dviware/beebe/utils/xxu.c
new file mode 100644
index 0000000000..8bdeada1d2
--- /dev/null
+++ b/dviware/beebe/utils/xxu.c
@@ -0,0 +1,172 @@
+/* /usr.MC68020/csc-sun/u/local/src/C/xxu.c, Sat Jun 27 13:53:01 1987, */
+/* Add special[] processing, strip trailing dots from names */
+
+/* X X U -- 20-to-Unix filename converter */
+
+/*
+ Change DEC-20 or VAX/VMS style filenames into normal Unix names.
+ Handy for use after ftp MGETs, when you find your directory full of
+ files with names like LIB:<KERMIT>CKUFIO.C.2 or FRED::[ETHEL]A.B;37
+ when all you really wanted was ckufio.c and a.b.
+
+ Usage: xxu file(s)
+
+ Action: Renames argument files as follows:
+ strips Unix path name from front (up to rightmost '/') if present
+ strips DEC device:, node:: names from front (up to rightmost ':') if present
+ strips DEC-20 <directory> or VMS [directory] name if present
+ strips DEC-20 version number from end (everything after 2nd dot) if present
+ strips VMS generation number from end (everything after ';') if present
+ lowercases any uppercase letters
+ honors DEC-20 CTRL-V quote for special characters
+ discards unquoted unprintable characters
+ if result is null, file is renamed to xxfile-n, where n is a number.
+ if result would write over an existing file, file also renamed to xxfile-n.
+
+ Recommended procedure: make a new directory, cd to it, then FTP files
+ from DEC-20 or VMS system, then do "xxu *".
+
+ Author: F. da Cruz, CUCCA, July 85
+
+ Added directory handling: Brad Davis, UofU VCIS Group, Aug 85
+*/
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/file.h> /* For access() */
+#ifdef DODIRS
+#include <sys/types.h>
+#include <sys/dir.h>
+#endif
+#include <errno.h>
+
+/* A few names will be preserved in upper case or mixed case */
+char* special[] =
+ { /* "old name", "new name" */
+ "bugs", "BUGS",
+ "install", "INSTALL",
+ "makefile", "Makefile",
+ "note", "NOTE",
+ "readme", "README",
+ "todo", "TODO",
+ (char*)NULL, (char*)NULL
+ };
+
+char name[500]; /* File name buffer */
+char *pp, *cp, *xp; /* Character pointers */
+char delim; /* Directory Delimiter */
+int dc = 0, n = 0; /* Counters */
+int quote = 0, indir = 0; done = 0; /* Flags */
+#ifdef DODIRS
+DIR *dir;
+struct direct *entry;
+#endif
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ if (argc < 2) { /* Give message if no args */
+#ifdef DODIRS
+ (void)fprintf(stderr,"Usage: xxu directory(s)\n");
+#else
+ (void)fprintf(stderr,"Usage: xxu file(s)\n");
+#endif
+ exit(1);
+ }
+ n = 0; /* Unfixable filename counter */
+ while (--argc > 0) { /* For all files on command line... */
+ argv++;
+#ifdef DODIRS
+ dir = opendir(*argv);
+ while ((entry = readdir(dir)) != (struct direct *)NULL) {
+ xp = entry->d_name; /* Copy pointer for simplicity */
+ if (*xp == '.') continue; /* leave . and .. alone */
+#else
+ xp = *argv; /* Copy pointer for simplicity */
+#endif
+ (void)printf("%s ",xp); /* Echo name of this file */
+ pp = name; /* Point to translation buffer */
+ *name = '\0'; /* Initialize buffer */
+ dc = 0; /* Filename dot counter */
+ done = 0; /* Flag for early completion */
+ for (cp = xp; (*cp != '\0') && !done; cp++)
+ { /* Loop thru chars... */
+ if (quote) { /* If this char quoted, */
+ *pp++ = *cp; /* include it literally. */
+ quote = 0;
+ continue;
+ } /* */
+ if (indir) { /* If in directory name, */
+ if (*cp == delim) indir = 0; /* look for end delimiter. */
+ continue;
+ }
+ switch (*cp) {
+ case '<': /* Discard DEC-20 directory name */
+ indir = 1;
+ delim = '>';
+ break;
+ case '[': /* Discard VMS directory name */
+ indir = 1;
+ delim = ']';
+ break;
+ case '/': /* Discard Unix path name */
+ case ':': /* or DEC dev: or node:: name */
+ pp = name;
+ break;
+ case '.': /* DEC -20 generation number */
+ if (++dc == 1) /* Keep first dot */
+ *pp++ = *cp;
+ else /* Discard everything starting */
+ done = 1; /* with second dot. */
+ break;
+ case ';': /* VMS generation or DEC-20 attrib */
+ done = 1; /* Discard everything starting with */
+ break; /* semicolon */
+ case '\026': /* Control-V quote for special chars */
+ quote = 1; /* Set flag for next time. */
+ break;
+ default:
+ if (isupper(*cp)) /* Uppercase letter to lowercase */
+ *pp++ = tolower(*cp);
+ else if (isprint(*cp)) /* Other printable, just keep */
+ *pp++ = *cp;
+ }
+ }
+ *pp = '\0'; /* Done with name, terminate it */
+ if (strcmp(name,xp) == 0) { /* If no renaming necessary, */
+ (void)printf("(ok)\n"); /* just give message. */
+ continue;
+ }
+ /* Strip trailing dot (so makefile. becomes makefile)
+ and then check for special Unix files with
+ mixed case */
+ {
+ char **p;
+ if (*(pp-1) == '.')
+ *(pp-1) = '\0';
+ for (p = special; (*p != (char*)NULL); p += 2)
+ {
+ if (strcmp(name,*p) == 0)
+ {
+ strcpy(name,*(p+1));
+ break;
+ }
+ }
+ }
+ while (*name == '\0' ||
+ (access(name,0) == 0) && (errno != ENOENT))
+ { /* Find unique name */
+ (void)sprintf(name,"xxfile-%d",n++);
+ }
+ (void)printf("=> %s ",name); /* Tell what new name will be */
+ if ((strcmp(xp,name) == 0) ||
+ (rename(xp,name) == 0)) /* Try to rename it */
+ (void)printf("(ok)\n"); /* Say what happened */
+ else
+ perror("failed");
+ }
+#ifdef DODIRS
+ }
+#endif
+ exit(0); /* Done. */
+}