%  Change file for TOPS-20 by Tomas Rokicki.  Send bug reports to
%  ROKICKI@SU-SCORE.

@x [1] Tell WEAVE to print only the changes:
\pageno=\contentspagenumber \advance\pageno by 1
@y
\pageno=\contentspagenumber \advance\pageno by 1
\let\maybe=\iffalse
\def\ttw{{\mc TOPS-20}}
\def\title{DVIIMP changes for \ttw}
@z

@x [2]
@d banner=='This is DVIIMP, Version 0.94' {printed when the program starts}
@y
@d banner=='This is DVIIMP, TOPS-20 Version 0.94'
   {printed when the program starts}
@z

@x [3]
@ The binary input comes from |dvi_file|, and the symbolic output is written
on \PASCAL's standard |output| file. The term |print| is used instead of
|write| when this program writes on |output|, so that all such output
could easily be redirected if desired.

@d print(#)==write(#)
@d print_ln(#)==write_ln(#)
@d print_nl==write_ln
@y
@ The binary input comes from |dvi_file|, and the symbolic output is written
on TOPS-20's standard |tty| file.  The term |print| is used instead of
|write| when this program writes on |tty|, so that all such output
could easily be redirected if desired.

@d print(#)==write(tty,#)
@d print_ln(#)==write_ln(tty,#)
@d print_nl==write_ln(tty)
@z

@x [4]
@p program DVI_IMP(@!dvi_file,@!im_file,@!output);
@y
@p program DVI_IMP ;
@z

@x [30]
@p function read_int:integer;
var i:integer;
@!neg_flag:boolean;
begin
neg_flag:=false; i:=0;
get(tty);
while tty^=' ' do get(tty);
if (tty^='-') then neg_flag:=true;
while (tty^='-') or (tty^='+') do get(tty);
while (tty^>='0') and (tty^<='9') do begin
    i:=i*10+xord[tty^]-"0"; get(tty);
    end;
if neg_flag then i:=-i;
read_int:=i;
end;
@y
@p function read_int:integer;
var i:integer;
@!neg_flag:boolean;
begin
neg_flag:=false; i:=0;
if rescan[rsp]='-' then neg_flag := true ;
if (rescan[rsp]='-') or (rescan[rsp]='+') then incr(rsp) ;
while (rescan[rsp]>='0') and (rescan[rsp]<='9') do begin
  i:=i*10+xord[rescan[rsp]]-"0"; incr(rsp);
end;
if neg_flag then i:=-i;
read_int:=i;
end;
@z

@x [31]
@p procedure open_dvi_file; {prepares to read packed bytes in |dvi_file|}
begin reset(dvi_file);
cur_loc:=0;
end;
@#
procedure open_gf_file; {prepares to read packed bytes in |gf_file|}
begin reset(gf_file,cur_name);
cur_gf_loc:=0;
end;
@#
procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|}
begin reset(tfm_file,cur_tfm_name);
end;
@y
@p procedure open_dvi_file; {prepares to read packed bytes in |dvi_file|}
begin reset(dvi_file,dvi_name,'/O/B:8');
cur_loc:=0;
end;
@#
procedure open_gf_file; {prepares to read packed bytes in |gf_file|}
begin reset(gf_file,cur_name,'/O/B:8');
cur_gf_loc:=0;
end;
@#
procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|}
begin reset(tfm_file,cur_tfm_name,'/O/B:8');
end;
@z

@x [32]
@p procedure open_im_file; {prepares to write packed bytes in |im_file|}
begin rewrite(im_file); im_byte_no:=0;
end;
@y
@p procedure open_im_file; {prepares to write packed bytes in |im_file|}
begin rewrite(im_file,im_name,'/O/B:8'); im_byte_no:=0;
end;
@z

@x [32]
it, we will also declare |cur_gf_loc|.
@y
it, we will also declare |cur_gf_loc|, |dvi_name|, and |im_name|.
@z

@x [32]
@!cur_name:packed array[1..name_length] of char; {external name,
  with no lower case letters}
@!cur_tfm_name:packed array[1..name_length] of char; {external name,
  with no lower case letters}
@y
@!cur_name:packed array[1..name_length] of char; {external name,
  with no lower case letters}
@!cur_tfm_name:packed array[1..name_length] of char; {external name,
  with no lower case letters}
@!dvi_name,@!im_name:packed array[1..name_length] of char;
  {external name, with no lower case letters}
@z

<><>@x [49]
@!font_m_val:array [0..max_fonts] of integer; {overall font magnification}
<><>@y
@!font_m_val:array [0..max_fonts] of integer; {overall font magnification}
@!font_d_val:array [0..max_fonts] of integer; {directory size of font}
<><>@z

@x [66]
and |term_out| for terminal output.
@^system dependencies@>

@<Glob...@>=
@!buffer:array[0..terminal_line_length] of ASCII_code;
@!term_in:text_file; {the terminal, considered as an input file}
@!term_out:text_file; {the terminal, considered as an output file}
@y
and |term_out| for terminal output.
@^system dependencies@>

@d term_in==tty {the terminal, considered as an input file}
@d term_out==tty {the terminal, considered as an output file}

@<Glob...@>=
@!buffer:array[0..terminal_line_length] of ASCII_code;
@z

@x [66]
begin update_terminal; reset(term_in);
@y
begin update_terminal;
@z

@x [67]
begin rewrite(term_out); {prepare the terminal for output}
write_ln(term_out,banner);
@y
begin
@<Determine the desired |dvi_name|@> ;
@z

@x [67]
  repeat if buffer[buf_ptr]="*" then
@y
  begin f_flag := true ;
  repeat if buffer[buf_ptr]="*" then
@z

@x [67]
  until start_vals=k
@y
  until start_vals=k ; start_page := start_count[0] ; end
@z

@x [68]
  begin max_pages:=get_integer;
@y
  begin n_flag := true ; max_pages := get_integer ; num_pages := max_pages ;
@z

<><>@x [72]
m:=round((0.3*mag*q)/d);
<><>@y
m:=round((0.3*mag*q)/d);font_d_val[nf]:=round((1.5*mag*q)/d);
<><>@z

@x [73]
@!k:0..name_size; {indices into |names|}
@y
@!i:integer; {general index}
@!k:0..name_size; {indices into |names|}
@z

@x [74]
    print(' not found');
@y
    print('gf not found');
@z

@x [75]
cur_name[r+1]:='.'; cur_name[r+2]:='G'; cur_name[r+3]:='F';
@y
  incr(r) ; cur_name[r] := '.' ;
  i := font_m_val[cur_font] ; incr(r) ;
  if i > 1000 then begin
    cur_name[r] := xchr["0"+i div 1000] ; incr(r) ; i := i mod 1000 ;
  end ;
  cur_name[r] := xchr["0"+i div 100] ; incr(r) ; i := i mod 100 ;
  cur_name[r] := xchr["0"+i div 10] ; incr(r) ;
  cur_name[r] := xchr["0"+i mod 10] ;
cur_name[r+1]:='G'; cur_name[r+2]:='F';
@z

@x [98]
@p begin initialize; {get all variables initialized}
@y
@p begin initialize; {get all variables initialized}
@<Get file name and options@> ;
@z

@x
final_end:end.
@y
if spoolit then @<Send the job to the printer@>;
final_end:end.
@z

@x [99]
This section should be replaced, if necessary, by changes to the program
that are necessary to make \.{DVIIMP} work at a particular installation.
It is usually best to design your change file so that all changes to
previous sections preserve the section numbering; then everybody's version
will be consistent with the printed program. More extensive changes,
which introduce new sections, can be inserted here; then only the index
itself will get a new section number.
@^system dependencies@>
@y
These are the changes that are necessary to make \.{DVIIMP} work on
TOPS-20.  This just means getting the file name from the command line
currently, but additional code to parse options needs to be added.
@^system dependencies@>

@ On TOPS-20, we can get the command line using the so-called rescan buffer.
Thus, the command line actually becomes the first part of input seen in the
file \.{TTY}.  We need to skip over to the file name, then parse the file
name and any options that may be specified.

@d RSCAN=@'500 {ReSCAN buffer JSYS}

@<Get file name and options...@>=
jsys(RSCAN,1,i;0;ac1); {put the command line into the |TTY| input buffer}
if (i<>2) or (ac1<=0) then
   abort('Couldn''t get a command line, somehow.'); {RSCAN failed, somehow}
if eoln(term_in) then read_ln(term_in); {for some TOPS-20's}
read(term_in,rescan:rescan_len); {read in rescan buffer}
if rescan_len>max_rescan then
   abort('command line too long!') ;
read_ln(term_in) ;
if rescan_len=ac1-2 then dialog
else begin
   i:=1; while rescan[i]>' ' do incr(i) ; { skip invocation name }
   while(i<=rescan_len) and (rescan[i]=' ') do incr(i) ; {skip spaces}
   if (i>rescan_len) then dialog
   else
      @<Parse file name and options@> ;
end ;

@ Now we define the routine in dialog which gets the file name from the
terminal.

@<Determine the desired |dvi_name|@>=
print('DVI file name:  ') ;
input_ln ;
@<Get the |dvi_name| and create the |im_name|@>

@ We had something on the command line.  Now we try to figure out what
it was.  For now we assume that the whole command line option is the name
of the file, so we copy it into |dvi_name|.  We then try to figure out
where the extension begins, so we can tack on the extension \.{IMP} and use
that as the file name.

@<Parse file name and options@>=
begin
spoolit:=true;
j := 0 ; last_ext := 0 ;
rescan[rescan_len+1] := '!' ;
while (i <= rescan_len) and (j < terminal_line_length) and
       (rescan[i] <> '/') do begin
   buffer[j] := xord[rescan[i]] ;
   incr(i) ; incr(j) ;
end ;
rsp := i ;
while (rescan[rsp]='/') do
   @<Parse option@> ;
if j >= terminal_line_length then abort('File name too long!') ;
buffer[j] := " " ;
@<Get the |dvi_name| and create the |im_name|@>;
end

@ Now we parse the desired option.  This can be any of C, F, or N, for
copies, starting page, and maximum pages, respectively.

@<Parse option@>=
begin
incr(rsp) ; {skip "/"}
i := rsp ; while (rescan[i] <> '/') and (rescan[i] <> '!') do incr(i) ;
	{now |i| points after option spec}
opt:=rescan[rsp]; incr(rsp);
if (opt>='A') and (opt<='Z') then opt:=chr(ord(opt)-ord('A')+ord('a'));
if (opt='c') then read_c
else if (opt='f') then read_f
else if (opt='n') then read_n
else if (opt='h') then read_h
else if (opt='v') then read_v
else if (opt='i') then spoolit:=false
else
  print_ln('Did not understand ',opt,' option.  Ignoring.') ;
rsp := i ;
end

@ Now we parse the name of the file, finding the extension (if any),
suffixing one if there wasn't, and creating the |im_name|.

@<Get the |dvi_name| and create the |im_name|@>=
i := 1 ; last_ext := 0 ;
while (buffer[i-1] <> " ") and (i <= terminal_line_length) and
         (i <= name_length) do begin
   if (buffer[i-1] <= "z") and (buffer[i-1] >= "a") then
      buffer[i-1] := buffer[i-1] - 32 ;
   dvi_name[i] := xchr[buffer[i-1]] ;
   im_name[i] := xchr[buffer[i-1]] ;
   if (buffer[i-1] = ".") and (last_ext = 0) then
      last_ext := i
   else if buffer[i-1] = ">" then
      last_ext := 0 ;
   incr(i) ;
end ;
if (i > name_length) then abort('File name too long!') ;
if last_ext = 0 then begin
   last_ext := i ;
   dvi_name[i] := '.' ; incr(i) ;
   dvi_name[i] := 'D' ; incr(i) ;
   dvi_name[i] := 'V' ; incr(i) ;
   dvi_name[i] := 'I' ; incr(i) ;
end ;
for j := i to name_length do
   dvi_name[j] := chr(0) ;
i := last_ext ;
im_name[i] := '.' ; incr(i) ;
im_name[i] := 'I' ; incr(i) ;
im_name[i] := 'M' ; incr(i) ;
im_name[i] := 'P' ; incr(i) ;
for j := i to name_length do
   im_name[j] := chr(0)

@ Magic.
@d STI=@'114 {Simulate Terminal Input JSYS}
@d PRIIN=@'100 {PRImary INput JFN JSYS}
@<Send the job to the printer@>=
begin
jsys(STI;PRIIN,ord('I'));
jsys(STI;PRIIN,ord('M'));
jsys(STI;PRIIN,ord('P'));
jsys(STI;PRIIN,ord('S'));
jsys(STI;PRIIN,ord('P'));
jsys(STI;PRIIN,ord('O'));
jsys(STI;PRIIN,ord('O'));
jsys(STI;PRIIN,ord('L'));
jsys(STI;PRIIN,ord(':'));
jsys(STI;PRIIN,ord(' '));
for i:=1 to name_length do
	if im_name[i]>chr(0) then jsys(STI;PRIIN,ord(im_name[i]));
jsys(STI;PRIIN,13);
end

@ Now we declare all of those variables we used.

@<Constants...@>=
@!max_rescan = 300 ; {maximum command line length}

@ @<Glob...@>=
i, j : integer ; {temporary indices}
@!rsp : integer ; {rescan line pointer}
@!option : 1..3 ; {what option was selected}
@!last_ext : integer ; {where we saw an extension}
@!ac1, @!rescan_len : integer ; {system call variables}
@!rescan : packed array [1..max_rescan] of char ; {rescan buffer}
@!spoolit: boolean;
@!opt: char;
@z