GFtoDVI change file for Vax/VMS Jane Colman, Lawrence Berkeley Laboratory 19 Nov 84 @x \pageno=\contentspagenumber \advance\pageno by 1 @y \pageno=\contentspagenumber \advance\pageno by 1 \let\maybe=\iftrue \def\title{GFtoDVI changes for Vax/VMS} @z @x @d banner=='This is GFtoDVI, Version 1.7' {printed when the program starts} @y @d banner=='This is GFtoDVI, Vax/VMS Version 1.7' @z @x @d othercases == others: {default for cases not listed explicitly} @y @d othercases == otherwise {default for cases not listed explicitly} @z @x @d print(#)==write(#) @d print_ln(#)==write_ln(#) @d print_nl(#)==begin write_ln; write(#); end @p program GF_to_DVI(@!output); @y @d crlf==chr(13),chr(10) @d print(#)==write(#) @d print_ln(#)==write_ln(#,crlf) @d print_nl(#)==begin write_ln(crlf); write(#); end @d VAX_carriage_control==@= carriage_control @> @d VAX_none==@= none @> @d real==double @p @=[inherit('sys$library:starlet')]@>@\ {allows us to use system symbols and routines} program GF_to_DVI(@!input,@!output,@!gf_file,@!tfm_file,@!dvi_file); @z @x procedure initialize; {this procedure gets things started properly} var @!i,@!j,@!m,@!n:integer; {loop indices for initializations} begin print_ln(banner);@/ @y @@/ procedure initialize; {this procedure gets things started properly} var @!i,@!j,@!m,@!n:integer; {loop indices for initializations} begin open(output,'SYS$OUTPUT',VAX_carriage_control:=VAX_none); rewrite(output); out_FAB:=@=PAS$FAB@>(output); out_RAB:=@=PAS$RAB@>(output); print_ln(banner);@/ @z @x @= @!max_labels=2000; {maximum number of labels and dots per character} @!pool_size=10000; {maximum total length of labels and other strings} @!max_strings=1100; {maximum number of labels and other strings} @!terminal_line_length=150; {maximum number of characters input in a single line of input from the terminal} @!file_name_size=50; {a file name shouldn't be longer than this} @!font_mem_size=1000; {space for font metric data} @!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8} @!widest_row=8192; {maximum number of pixels per row} @y @= @!max_labels=2000; {maximum number of labels and dots per character} @!pool_size=10000; {maximum total length of labels and other strings} @!max_strings=1100; {maximum number of labels and other strings} @!terminal_line_length=150; {maximum number of characters input in a single line of input from the terminal} @!file_name_size=50; {a file name shouldn't be longer than this} @!font_mem_size=1000; {space for font metric data} @!dvi_buf_size=1024; {size of the output buffer; must be twice |VAX_block_length|} @!widest_row=8192; {maximum number of pixels per row} @z @x @d update_terminal == break(output) {empty the terminal output buffer} @= @!buffer:array[0..terminal_line_length] of 0..255; @!term_in:text_file; {the terminal, considered as an input file} @y @d update_terminal == write_ln(output) {empty the terminal output buffer} @d term_in == input {the terminal, considered as an input file} @= @!buffer:array[0..terminal_line_length] of 0..255; @z @x begin update_terminal; reset(term_in); if eoln(term_in) then read_ln(term_in); line_length:=0; while (line_length); reset(gf_file,@=error:=continue@>); gf_count:=0; @z @x begin reset(tfm_file,name_of_file); @y begin close(tfm_file,@=error:=continue@>); open(tfm_file,name_of_file,@=old,error:=continue@>); reset(tfm_file,@=error:=continue@>); tfm_count:=0; @z @x begin rewrite(dvi_file,name_of_file); @y begin open(dvi_file,name_of_file,@=new,error:=continue@>); rewrite(dvi_file); dvi_count:=0; @z @x @p procedure read_tfm_word; begin read(tfm_file,b0); read(tfm_file,b1); read(tfm_file,b2); read(tfm_file,b3); end; @y @d read_tfm_file(#) == begin if tfm_count=VAX_block_length then begin get(tfm_file,@=error:=continue@>); tfm_count:=0; end; #:=tfm_file^[tfm_count]; incr (tfm_count); end @p procedure read_tfm_word; begin read_tfm_file(b0); read_tfm_file(b1); read_tfm_file(b2); read_tfm_file(b3); end; @z @x @p function get_byte:integer; {returns the next byte, unsigned} var b:eight_bits; begin if eof(gf_file) then get_byte:=0 else begin read(gf_file,b); incr(cur_loc); get_byte:=b; end; end; @# function get_two_bytes:integer; {returns the next two bytes, unsigned} var a,@!b:eight_bits; begin read(gf_file,a); read(gf_file,b); cur_loc:=cur_loc+2; get_two_bytes:=a*256+b; end; @# function get_three_bytes:integer; {returns the next three bytes, unsigned} var a,@!b,@!c:eight_bits; begin read(gf_file,a); read(gf_file,b); read(gf_file,c); cur_loc:=cur_loc+3; get_three_bytes:=(a*256+b)*256+c; end; @# function signed_quad:integer; {returns the next four bytes, signed} var a,@!b,@!c,@!d:eight_bits; begin read(gf_file,a); read(gf_file,b); read(gf_file,c); read(gf_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_gf_file(#) == begin if gf_count=VAX_block_length then begin get(gf_file,@=error:=continue@>); gf_count:=0; end; #:=gf_file^[gf_count]; incr(gf_count); end @p function get_byte:integer; {returns the next byte, unsigned} var b:eight_bits; begin if eof(gf_file) then get_byte:=0 else begin read_gf_file(b); incr(cur_loc); get_byte:=b; end; end; @# function get_two_bytes:integer; {returns the next two bytes, unsigned} var a,@!b:eight_bits; begin read_gf_file(a); read_gf_file(b); cur_loc:=cur_loc+2; get_two_bytes:=a*256+b; end; @# function get_three_bytes:integer; {returns the next three bytes, unsigned} var a,@!b,@!c:eight_bits; begin read_gf_file(a); read_gf_file(b); read_gf_file(c); cur_loc:=cur_loc+3; get_three_bytes:=(a*256+b)*256+c; end; @# function signed_quad:integer; {returns the next four bytes, signed} var a,@!b,@!c,@!d:eight_bits; begin read_gf_file(a); read_gf_file(b); read_gf_file(c); read_gf_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 @d qi(#)==#+min_quarterword {to put an |eight_bits| item into a quarterword} @d qo(#)==#-min_quarterword @y @d qi(#)==# {to put an |eight_bits| item into a quarterword} @d qo(#)==# @z @x following structure: If the name contains `\.>' or `\.:', the file area @y following structure: If the name contains `\.]' or `\.:', the file area @z @x @!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any} @y @!area_delimiter:pool_pointer; {the most recent `\.]' or `\.:', if any} @z @x to place. The program here sets it to `\.{TeXfonts:}'. @^system dependencies@> @.TeXfonts@> @= l:=9; init_str9("T")("e")("X")("f")("o")("n")("t")("s")(":")(home_font_area);@/ @y to place. The program here sets it to `\.{TeX$fonts:}'. @^system dependencies@> @.TeX$fonts@> @= l:=10; init_str10("T")("e")("X")("$")("f")("o")("n")("t")("s")(":") (home_font_area);@/ @z @x else begin if (c=">")or(c=":") then @y else begin if (c="]")or(c=":") then @z @x Although this routine is system-independent, it should probably be modified to take the file name from the command line (without an initial prompt), on systems that permit such things. @p procedure start_gf; label found,done; begin loop@+begin print_nl('GF file name: '); input_ln; @.GF file name@> buf_ptr:=0; buffer[line_length]:="?"; while buffer[buf_ptr]=" " do incr(buf_ptr); if buf_ptr; if cur_ext=null_string then cur_ext:=gf_ext; pack_file_name(cur_name,cur_area,cur_ext); open_gf_file; if not eof(gf_file) then goto found; print_nl('Oops... I can''t find file '); print(name_of_file); @.Oops...@> @.I can't find...@> end; end; @y On Vax/VMS this routine has been modified to take the file name from the command line (without an initial prompt). @d VAX_volatile==@=volatile@> @d VAX_aligned==@=aligned@> @d VAX_immed==@=%immed @> @d VAX_external==@=external@> @d VAX_stdescr==@=%stdescr @> @d VAX_lib_get_foreign==@= lib$get_foreign@> @p procedure start_gf; label found,done; var @!i,j:integer; begin i:=0; j:=VAX_lib_get_foreign(command_line,,cmd_len,i); i:=1; buf_ptr:=0; while i<=cmd_len do begin buffer[buf_ptr]:=xord[command_line[i]]; incr(buf_ptr); incr(i); end; line_length:=buf_ptr; loop@+begin buf_ptr:=0; buffer[line_length]:="?"; while buffer[buf_ptr]=" " do incr(buf_ptr); if buf_ptr; if cur_ext=null_string then cur_ext:=gf_ext; pack_file_name(cur_name,cur_area,cur_ext); open_gf_file; if not eof(gf_file) then goto found; print_nl('Oops... I can''t find file '); print_ln(name_of_file); @.Oops...@> @.I can't find...@> end; print('GF file name: '); input_ln; @.GF file name@> end; @z @x @ Some systems may find it more efficient to make |dvi_buf| a |packed| array, since output of four bytes at once may be facilitated. @^system dependencies@> @= @!dvi_buf:array[dvi_index] of eight_bits; {buffer for \.{DVI} output} @y @ Some systems may find it more efficient to make |dvi_buf| a |packed| array, since output of four bytes at once may be facilitated. On Vax/VMS, we get even more complicated than that, for efficiency. @^system dependencies@> @d dvi_buf==d_buffer.b {buffer for \.{DVI} output} @= @!d_buffer: [VAX_volatile,VAX_aligned(9)] packed record case boolean of false: (b:packed array[dvi_index] of eight_bits); true: (l:byte_block; r:byte_block; j:eight_bits); end; @z @x @ The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling |write_dvi(a,b)|. It is safe to assume that |a| and |b+1| will both be multiples of 4 when |write_dvi(a,b)| is called; therefore it is possible on many machines to use efficient methods to pack four bytes per word and to output an array of words with one system call. @^system dependencies@> @p procedure write_dvi(@!a,@!b:dvi_index); var k:dvi_index; begin for k:=a to b do write(dvi_file,dvi_buf[k]); end; @y @ The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling |write| on the other variant of the |dvi_buf| record. @^system dependencies@> @z @x begin write_dvi(0,half_buf-1); dvi_limit:=half_buf; @y begin write(dvi_file,d_buffer.l); dvi_limit:=half_buf; @z @x else begin write_dvi(half_buf,dvi_buf_size-1); dvi_limit:=dvi_buf_size; @y else begin write(dvi_file,d_buffer.r); dvi_limit:=dvi_buf_size; @z @x if dvi_limit=half_buf then write_dvi(half_buf,dvi_buf_size-1); if dvi_ptr>0 then write_dvi(0,dvi_ptr-1) @y if dvi_limit=half_buf then write(dvi_file,d_buffer.r); for k:=dvi_ptr to dvi_buf_size do dvi_buf[k]:=223; if dvi_ptr>0 then write(dvi_file,d_buffer.l); if dvi_ptr>half_buf then write(dvi_file,d_buffer.r); @z @x This section should be replaced, if necessary, by changes to the program that are necessary to make \.{GFtoDVI} 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 Here are the remaining changes to the program that are necessary to make \.{GFtoDVI} work on Vax/VMS. @^system dependencies@> @= VAX_block_length=512; @ @= byte_block=packed array[0..VAX_block_length-1] of 0..255; sixteen_bits=0..65535; @ @= @!command_line: packed array[1..terminal_line_length] of char; @!cmd_len:sixteen_bits; @ Here is the library procedure that gets the user's command line. @= [VAX_external] function VAX_lib_get_foreign(VAX_stdescr cmdlin:[VAX_volatile] packed array[$l1..$u1:integer]of char:=VAX_immed 0; VAX_stdescr prompt:[VAX_volatile]packed array[$l2..$u2:integer] of char:=VAX_immed 0; var len:[VAX_volatile]sixteen_bits:=VAX_immed 0; var flag:[VAX_volatile]integer:=VAX_immed 0):integer;extern; @ Here is the stuff for magic file operations. @= unsafe_file = [unsafe] file of char; FAB_ptr = ^@=FAB$TYPE@>; RAB_ptr = ^@=RAB$TYPE@>; @ @= function@= PAS$FAB@>(var foobar:unsafe_file):FAB_ptr; extern; function@= PAS$RAB@>(var foobar:unsafe_file):RAB_ptr; extern; @ @= out_FAB: FAB_ptr; out_RAB: RAB_ptr; @z