1 //                  Roff for MULTICS
  2 //
  3 //  The first ROFF for Multics was written in March, 1969, by
  4 //  Doug McIlroy of Bell Labs.  Art Evans made extensive
  5 //  modifications to it in May and June, 1969, adding many
  6 //  comments and making various changes.
  7 //  Footnoting added by Dennis Capps in 1970.
  8 //  Maintained by Harwell Thrasher in 1971.
  9 //  Many new features added and bugs fixed by R Mabee in 1971-1972.
 10 //  RUNOFF and BCPL were brought over to the 6180 Multics (from 645) in May of 1973 by R F Mabee.
 11 
 12 //  Last modified on 05/30/74 at 18:43:28 by R F Mabee.
 13 
 14 //  The following files compose the RUNOFF command:
 15 //        runoff_driver       the command and driver.
 16 //        runoff_mr0          Miscellaneous utility subroutines.
 17 //        runoff_mr1          Roff - the main routine.
 18 //        runoff_mr2          Control line processors.
 19 //        runoff_mr3          Routines for text printing.
 20 //        runoff_mr4          Miscellaneous output subroutines.
 21 //        runoff_mr5          Routines for header and footer printing.
 22 //        runoff_mr6          Routines for footnote processing
 23 //        runoff_mr7          Routines for the "chars" option
 24 //        runoff_mr8          ReadExp - expression reading and evaluating subroutines.
 25 //        runoff_mr9          Reference symbol subroutines.
 26 //        runoff_dim          Routines for optional use of runoff as IOSIM.
 27 //        runoff_             Outer module transfer vector for ios_ to use above.
 28 //        runoff_head         Global and other declarations for RUNOFF.
 29 
 30 //  This last file includes a table-of-contents, listing for each
 31 //  routine which file it is declared in.
 32 //  In addition, of course, the usual BCPL library is used.
 33 
 34 //  This file contains the main program for RUNOFF on Multics.
 35 //  Roff is called by the driver, and sets things up before calling
 36 //  RoffProcess to do the work.  Its parameters are as follows:
 37 //        Streams   a vector of input streams to be processed.
 38 //        Sn        the number of streams in the vector Streams (1 to Sn).
 39 //        OutStream the main output stream.
 40 //  In addition, many global variables must be set (encoding options) before Roff is entered.
 41 
 42 
 43 //  Copyright (c) 1974 by Massachusetts Institute of Technology and Honeywell Information Systems, Inc.
 44 
 45 //  General permission is granted to copy and use this program, but not to sell it, provided that the above
 46 //  copyright statement is given.  Contact Information Processing Services, MIT, for further information.
 47 //  Please contact R F Mabee at MIT for information on this program and versions for other machines.
 48 
 49 get "runoff_head"   // Include declarations for ROFF.
 50 
 51 
 52 let Roff (Streams, Sn, OutStream) be
 53      $(
 54           Output := OutStream
 55 
 56 // Set up buffers for input and output lines.
 57 
 58           Char := vec Maxline * 2                 // Text buffer for output lines.
 59           Rawchar := vec Maxline + 20             // Buffer for input lines.
 60           Rawchar[0] := 0
 61 
 62 
 63 // Establish buffer to hold one footnote line.
 64           Footbuf := vec Maxline + 20
 65 
 66 // Establish a temporary storeroom for the unprocessed stuff in
 67 // Char while a footnote is being processed.
 68           Temp := vec Maxline * 2
 69 
 70 // Set up translation tables.
 71 
 72           TrTable, DeviceTable, Conv, CharsTable := vec 128, vec 128, vec 128, vec 128
 73           for i = 0 to 127 do CharsTable!i := '*s'
 74 
 75 // Establish buffers for headers' addresses.
 76 
 77           Eh, Oh := vec Maxheads, vec Maxheads              //  Headers.
 78           for i = 0 to Maxheads do Eh!i, Oh!i := 0, 0
 79           Ef, Of := vec Maxheads, vec Maxheads              //  Footers.
 80           for i = 0 to Maxheads do Ef!i, Of!i := 0, 0
 81 
 82 // Other initialization.
 83 
 84           InitializeSymbolTree ()
 85           InputStack := vec MaxDepth
 86 
 87                $(Pass                   //  Make requested number of passes. Output is produced only on last pass.
 88                                         //  This is a repeatwhile Passes > 0 loop.
 89           // Initialize various switches and things in global:
 90 
 91                     SetSwitches ()
 92 
 93                     if Passes > 1 do Fp, Lp, Print := 999999, 999999, false     //  Not final pass, suppress output.
 94 
 95 
 96           // Set up conversion table for output.
 97 
 98                     FillTrTable ()
 99 
100                     SetDevice (Device)
101                     SetCharsw (Charsw)
102                     SetPaging (NoPaging)
103 
104 
105           // Do all the work.
106 
107                     for i = 1 to Sn do RoffProcess (Streams!i)
108 
109 
110                     if Ft do Foot_end ()          //  Otherwise we die.
111                     Break ()
112                     Eject () repeatuntil Fl = 0
113 
114                     Freeheads (Oh)
115                     Freeheads (Eh)
116                     Freeheads (Of)
117                     Freeheads (Ef)
118 
119                     unless Fth = 0 do Freevec (Fth)
120                     Freevec (FootRef)
121                     Freevec (TextRef)
122 
123                     Passes := Passes - 1
124                $)Pass  repeatwhile Passes > 0
125      $)
126 
127 
128 and SetDevice (New) be
129      $(   Printersw, Selsw := false, false
130           Device := New
131           for i = 0 to 127 do DeviceTable!i := i
132           let T = valof switchon Device into
133                $(   case 1050: case 2741: case 963:
134                               resultis table 6, '{', '}', '[', ']', '`', '~'
135                     case 041: Selsw := true
136                               resultis table 2, '[', ']'
137                     case 015: case 012: case 088:
138                               Selsw := true
139                               resultis table 0
140                     case 202: case 300:
141                               Printersw := true
142                     default:  resultis table 0
143                $)
144 
145           if Selsw do
146                $(   let St = "-M;**:%m*"(>Bg.kh9y2384657#Ee b H*c
147                               *<P|XVUCAZO+WYJSQDFNR\TL!?I)='1 ^*c
148                               * p,xvucazo&wyjsqdfnr@tl$/i0    "
149                     if Device = 088 do St := "EMme:b*'*"(>Bg.kh912384657#**;<=%H*c
150                                               *-P|XVUCAZO+WYJSQDFNR\TL!?I) _ K^*c
151                                               * p,xvucazo&wyjsqdfnr@tl$/i0 G  "
152                     Unpackstring (St, DeviceTable + '*s')
153                     DeviceTable!'*s', DeviceTable!Skip := '*s', Skip  //  Limits of above string.
154                $)
155 
156           for i = 1 to T!0 do DeviceTable!(T!i) := '*s'
157           for i = 0 to 127 do Conv!i := DeviceTable!(TrTable!i)
158      $)
159 
160 and FillTrTable() be
161      $(   for i = 0 to $8037 do TrTable!i := Skip
162           for i = $8040 to $8176 do TrTable!i := i
163           TrTable!Skip := Skip
164           TrTable!'*t', TrTable!'*b', TrTable!'*n' := '*t', '*b', '*n'
165           TrTable!'*f', TrTable!'*d', TrTable!'*k' := '*f', '*d', '*k'
166      $)
167 and SetPaging (New) be
168      $(   NoPaging := New
169           test NoPaging
170           then Pl, Ma1, Ma2, Ma3, Ma4 := 1000000000, 0, 0, 0, 0
171           or   Pl, Ma1, Ma2, Ma3, Ma4 := PL_, MA1_, MA2_, MA3_, MA4_
172           SetLinesLeft ()
173      $)
174 
175 and SetSwitches () be
176      $(   Fp := From          //  First page to print.
177           Lp := To            //  Last page to print.
178           Np := Start         //  Number to be on first page.
179           NNp := Np + 1       //  Next page number.
180           Print := Fp le Np le Lp & Passes le 1   //  Are we now printing?
181           OddPage := Np rem 2 ne 0
182 
183           Ad := true          //  Adjust
184           Again := false      //  Control line to be reprocessed
185           Ce := 0             //  Do not center.
186           Eq := 0             //  Do not print line as equation.
187           Eqcnt := 1          //  Start equation counter at 1
188           Fc := 0             //  Number of characters in Footbuf
189           Fl := 0             //  Number of lines in FootList
190           Flp := false        //  Pagefull override off
191           Fi := not NoFill    //  Fill lines unless global override option.
192           Foot := 1           //  Start footnote counter at 1
193           FootList := 0       //  Top of list (growing end).
194           FootListBase := 0   //  Base of list.
195           Fr := true          //  Reset footnote counter at each page
196           Ft := false         //  Not processing a footnote
197           Fth := 0            //  Footnote demarcation.
198           In := 0             //  No indenting.
199           JumpLine := -1      //  Not performing goto.
200           LIno := NoControl -> 1000000000, 0  //  Process control lines normally.
201           Ll := LL_           //  Default line length.
202           Ma1 := MA1_         //  Space above header
203           Ma2 := MA2_         //  Space below header
204           Ma3 := MA3_         //  Space above footer
205           Ma4 := MA4_         //  Space below footer
206           MultiplePagecount := 1  //  Print every page.
207           Ms := 1             //  Multiple spacing
208           Nc := 0             //  No characters stored yet.
209           Nl := 0             //  Last used line number on page.
210           NoFtNo := false     //  Number footnotes normally.
211           Nr := 0             //  Count of characters in Rawchar.
212           PadLeft := false    //  Start adjusting with right end.
213           Pi := 0             //  Space needed for a picture.
214           Pl := PL_           //  Page length, in lines.
215           Roman := false      //  Print page numbers in Arabic.
216           SavedCc := 0        //  Initially no character in buffer cell.
217           Spec_char := '%'    //  Special character for symbol references.
218           Un := 0             //  No undenting.
219 
220           FootRef := StoreString ("(%Foot%) ")
221           TextRef := StoreString (" (%Foot%) ")
222      $)