VMS changes file for the ASCII driver written by Warren Wolfe, Aug, 1988 Copyright 1987 CUBE Software, Victoria, B.C., Canada @x [2] @d banner=='This is ',clone,', Version 1.00' @y @d banner=='This is ',clone,', VAX/VMS Version 1.00' @z @x @d othercases == others: {default for cases not listed explicitly} @d endcases == @+end {follows the default case in an extended |case| statement} @f othercases == else @f endcases == end @y @d othercases == otherwise {default for cases not listed explicitly} @d endcases == @+end {follows the default case in an extended |case| statement} @f othercases == else @f endcases == end @z @x [4] add tfm_file,gen_input,and input to program header @p program vutex(dvi_file,bit_file,input,output); @y @p @\@=[inherit('sys$library:starlet')]@>@\ {allows us to use system symbols and routines} program vutex(dvi_file,bit_file,tfm_file,gen_input,input,output); @z @x procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin print_ln(banner);@/ @y @@/ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin @@/ print_ln(banner);@/ @z @x Some \PASCAL\ compilers use the original name |char| for the data type associated with the characters in text files, while other \PASCAL s consider |char| to be a 64-element subrange of a larger data type that has some other name. In order to accommodate this difference, we shall use the name |text_char| to stand for the data type of the characters in the output file. We shall also assume that |text_char| consists of the elements |chr(first_text_char)| through |chr(last_text_char)|, inclusive. The following definitions should be adjusted if necessary. @^system dependencies@> @d text_char == char {the data type of characters in text files} @d first_text_char=0 {ordinal number of the smallest element of |text_char|} @d last_text_char=127 {ordinal number of the largest element of |text_char|} @= @!text_file=packed file of text_char; @y Some \PASCAL\ compilers use the original name |char| for the data type associated with the characters in text files, while other \PASCAL s consider |char| to be a 64-element subrange of a larger data type that has some other name. In order to accommodate this difference, we shall use the name |text_char| to stand for the data type of the characters in the output file. We shall also assume that |text_char| consists of the elements |chr(first_text_char)| through |chr(last_text_char)|, inclusive. The following definitions should be adjusted if necessary. @^system dependencies@> @d text_char == char {the data type of characters in text files} @d first_text_char=0 {ordinal number of the smallest element of |text_char|} @d last_text_char=127 {ordinal number of the largest element of |text_char|} @= @!text_file=text; @z @x @!byte_file=packed file of eight_bits; {files that contain binary data} @y {later we'll define files that contain binary data} @z @x @!dvi_file:byte_file; {the stuff we are \.{DVI}typing} @!tfm_file:byte_file; {a font metric file} @y @!dvi_file:packed file of byte_block; {the stuff we are \.{DVI}typing} @!tfm_file:packed file of byte_block; {a font metric file} @!dvi_count:integer; {number of bytes read from current block of |dvi_file|} @!tfm_count:integer; {number of bytes read from current block of |tfm_file|} @!dvi_blocks:integer; {number of blocks in |dvi_file|} @z @x Initialize byte counter for block in open_dvi_file begin reset(dvi_file); @y begin reset(dvi_file); dvi_count:=0; @z @x And again in reopen_dvi_file begin reset(dvi_file); @y begin reset(dvi_file); dvi_count:=0; @z @x begin reset(tfm_file,cur_name); @y begin close(tfm_file,@=error@>:=@=continue@>); {stupid Vax/VMS run-times} open(tfm_file,cur_name,@=old@>,@=error@>:=@=continue@>); reset(tfm_file,@=error@>:=@=continue@>); tfm_count:=0; @z @x begin reset(gen_input, cur_name) ; @y begin close(gen_input,@=error@>:=@=continue@>); open(gen_input,cur_name,@=old@>,@=error@>:=@=message@>); reset(gen_input,@=error@>:=@=message@>); @z @x @p function get_byte:integer; {returns the next byte, unsigned} var b:eight_bits; begin if eof(dvi_file) then get_byte:=0 else begin read(dvi_file,b); incr(cur_loc); get_byte:=b; end; end; @# function signed_byte:integer; {returns the next byte, signed} var b:eight_bits; begin read(dvi_file,b); incr(cur_loc); if b<128 then signed_byte:=b @+ else signed_byte:=b-256; end; @# function get_two_bytes:integer; {returns the next two bytes, unsigned} var a,@!b:eight_bits; begin read(dvi_file,a); read(dvi_file,b); cur_loc:=cur_loc+2; get_two_bytes:=a*256+b; end; @# function signed_pair:integer; {returns the next two bytes, signed} var a,@!b:eight_bits; begin read(dvi_file,a); read(dvi_file,b); cur_loc:=cur_loc+2; if a<128 then signed_pair:=a*256+b else signed_pair:=(a-256)*256+b; end; @# function get_three_bytes:integer; {returns the next three bytes, unsigned} var a,@!b,@!c:eight_bits; begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c); cur_loc:=cur_loc+3; get_three_bytes:=(a*256+b)*256+c; end; @# function signed_trio:integer; {returns the next three bytes, signed} var a,@!b,@!c:eight_bits; begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c); cur_loc:=cur_loc+3; if a<128 then signed_trio:=(a*256+b)*256+c else signed_trio:=((a-256)*256+b)*256+c; end; @# function signed_quad:integer; {returns the next four bytes, signed} var a,@!b,@!c,@!d:eight_bits; begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c); read(dvi_file,d); cur_loc:=cur_loc+4; if a<128 then signed_quad:=((a*256+b)*256+c)*256+d else signed_quad:=(((a-256)*256+b)*256+c)*256+d; end; @y @d read_dvi_file(#)==begin if dvi_count=block_size then begin get(dvi_file,@=error:=continue@>); dvi_count:=0; end; #:=dvi_file^[dvi_count]; incr(dvi_count); end @p function get_byte:integer; {returns the next byte, unsigned} var b:eight_bits; begin if eof(dvi_file) then get_byte:=0 else begin read_dvi_file(b); incr(cur_loc); get_byte:=b; end; end; @# function signed_byte:integer; {returns the next byte, signed} var b:eight_bits; begin read_dvi_file(b); incr(cur_loc); if b<128 then signed_byte:=b @+ else signed_byte:=b-256; end; @# function get_two_bytes:integer; {returns the next two bytes, unsigned} var a,@!b:eight_bits; begin read_dvi_file(a); read_dvi_file(b); cur_loc:=cur_loc+2; get_two_bytes:=a*256+b; end; @# function signed_pair:integer; {returns the next two bytes, signed} var a,@!b:eight_bits; begin read_dvi_file(a); read_dvi_file(b); cur_loc:=cur_loc+2; if a<128 then signed_pair:=a*256+b else signed_pair:=(a-256)*256+b; end; @# function get_three_bytes:integer; {returns the next three bytes, unsigned} var a,@!b,@!c:eight_bits; begin read_dvi_file(a); read_dvi_file(b); read_dvi_file(c); cur_loc:=cur_loc+3; get_three_bytes:=(a*256+b)*256+c; end; @# function signed_trio:integer; {returns the next three bytes, signed} var a,@!b,@!c:eight_bits; begin read_dvi_file(a); read_dvi_file(b); read_dvi_file(c); cur_loc:=cur_loc+3; if a<128 then signed_trio:=(a*256+b)*256+c else signed_trio:=((a-256)*256+b)*256+c; end; @# function signed_quad:integer; {returns the next four bytes, signed} var a,@!b,@!c,@!d:eight_bits; begin read_dvi_file(a); read_dvi_file(b); read_dvi_file(c); read_dvi_file(d); cur_loc:=cur_loc+4; if a<128 then signed_quad:=((a*256+b)*256+c)*256+d else signed_quad:=(((a-256)*256+b)*256+c)*256+d; end; @z @x [37] @ We need a function that will read in a word from the \.{TFM} file. If the particular system @^system dependencies@> requires buffering, here is the place to do it. It also sets a global flag |eof_tfm| when it reaches the end of the file. If this flag is set on entrance to |load_tfm_file|, it is assumed that the file is bad. @p function tfm_integer : integer ; var i:integer; begin read(tfm_file, i); eof_tfm:=eof(tfm_file); tfm_integer:=i; end; @ There is nothing wrong with defining |eof_tfm| here. @= @!eof_tfm:boolean; {true when end of \.{TFM} file is reached.} @y @ We need a function that will read in a word from the \.{TFM} file. If the particular system @^system dependencies@> requires buffering, here is the place to do it. It also sets a global flag |eof_tfm| when it reaches the end of the file. If this flag is set on entrance to |load_tfm_file|, it is assumed that the file is bad. Since |tfm_file| is blocked, we need a function to read an integer from it. @d read_tfm_file(#)==begin if tfm_count=block_size then begin get(tfm_file); tfm_count:=0; end; #:=tfm_file^[tfm_count]; incr(tfm_count); end @# @p function tfm_integer : integer; var i,@!result,@!temp:integer; begin result := 0; for i:=1 to 4 do begin@/ read_tfm_file(temp); result := result*two_8+temp; end; eof_tfm := eof(tfm_file); tfm_integer := result ; end; @ There is nothing wrong with defining |eof_tfm| here. @= @!eof_tfm:boolean; {true when end of \.{TFM} file is reached.} @z @x and |term_out| for terminal output. @^system dependencies@> @= @!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==input {the terminal, considered as an input file} @d term_out==output {the terminal, considered as an output file} @= @!buffer:array[0..terminal_line_length] of ASCII_code; @!buf_length:integer; @z @x @ Since the terminal is being used for both input and output, some systems need a special routine to make sure that the user can see a prompt message before waiting for input based on that message. (Otherwise the message may just be sitting in a hidden buffer somewhere, and the user will have no idea what the program is waiting for.) We shall call a system-dependent subroutine |update_terminal| in order to avoid this problem. @^system dependencies@> @d update_terminal == break(term_out) {empty the terminal output buffer} @ During the dialog, \vutex\ will treat the first blank space in a line as the end of that line. Therefore |input_ln| makes sure that there is always at least one blank space in |buffer|. @^system dependencies@> @p procedure input_ln; {inputs a line from the terminal} var k:0..terminal_line_length; begin update_terminal; reset(term_in); if eoln(term_in) then read_ln(term_in); k:=0; while (k