This change file is for the Vax/VMS vesion of TeX. Copyright (C) 1983 by David Fuchs. All rights are reserved. 14May85 JLC .Increased string_vacancies and pool_size as in 1.1. ? VLJ .Modified to handle tabs and form-feeds in input. @x \pageno=3 @y \pageno=3 \let\maybe=\iffalse \def\title{\TeX82 changes for Vax/VMS} @z @x @d banner=='This is TeX, Version 2.9' {printed when \TeX\ starts} @y @d banner=='This is TeX, Vax/VMS Version 2.9' @z @x procedure initialize; {this procedure gets things started properly} @y @@/ procedure initialize; {this procedure gets things started properly} @z @x @d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging} @d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging} @y @d debug==@{ @d gubed==@} @z @x @d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering usage statistics} @d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering usage statistics} @y @d stat== @d tats== @z @x @d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version} @d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version} @y @d init==@{ @d tini==@} @z @x compiler directives== starlet and vax reserved words @= @{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead} @!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging} @y On Vax/VMS, there are no compiler directives that can be introduced in this way, but we take this opportunity to include a few sysetem dependent goodies. @d VAX_text==@= text @> @d VAX_new==@= new @> @d VAX_none==@= none @> @d VAX_word==@= word @> @d VAX_error==@= error @> @d VAX_length==@= length @> @d VAX_syi_sid==@= syi$_sid @> @d VAX_continue==@= continue @> @d VAX_external==@= external @> @d VAX_readonly==@= readonly @> @d VAX_volatile==@= volatile @> @d VAX_aligned==@= aligned @> @d VAX_static==@= static @> @d VAX_unsigned==@= unsigned @> @d VAX_carriage_control==@= carriage_control @> @d VAX_io_setmode==@= io$_setmode @> @d VAX_iom_ctrlcast==@= io$m_ctrlcast @> @d VAX_immed==@= %immed @> @d VAX_stdescr==@= %stdescr @> @d VAX_ref==@= %ref @> @d VAX_qiow==@= $qiow @> @d VAX_assign==@= $assign @> @d VAX_numtim==@= $numtim @> @d VAX_getsyi==@= $getsyi @> @d VAX_lib_get_foreign==@= lib$get_foreign @> @d VAX_disposition==@= disposition @> @d VAX_delete==@= delete @> @d VAX_save==@= save @> @d VAX_varying==@= varying @> @d VAX_substr==@= substr @> @d VAX_trnlog==@= $trnlog @> @d VAX_ss_normal==@= ss$_normal @> @d VAX_user_action==@=user_action@> @d VAX_create==@=$create@> @d VAX_connect==@=$connect@> @d VAX_open==@=$open@> @d VAX_FAB_type==@= FAB$type @> @d VAX_RAB_type==@= RAB$type @> @d VAX_NAM_type==@= NAM$type @> @d VAX_PAS_FAB==@= PAS$FAB @> @d VAX_PAS_RAB==@= PAS$RAB @> @d VAX_undefined==@= undefined@> @d VAX_FAB_L_NAM== @=FAB$L_NAM@> @d VAX_NAM_B_RSL== @=NAM$B_RSL@> @d VAX_NAM_L_RSA== @=NAM$L_RSA@> @= @\@=[inherit('sys$library:starlet')]@>@\ {allows us to use system symbols and routines} @z @x @d othercases == others: {default for cases not listed explicitly} @y @d othercases == otherwise {default for cases not listed explicitly} @z @x [1] compile-time constants @!mem_max=30000; {greatest index in \TeX's internal |mem| array; must be strictly less than |max_halfword|; must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|} @!mem_min=0; {smallest index in \TeX's internal |mem| array; must be |min_halfword| or more; must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|} @!buf_size=500; {maximum number of characters simultaneously present in current lines of open files and in control sequences between \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|} @!error_line=72; {width of context lines on terminal error messages} @!half_error_line=42; {width of first lines of contexts in terminal error messages; should be between 30 and |error_line-15|} @!max_print_line=79; {width of longest text lines output; should be at least 60} @!stack_size=200; {maximum number of simultaneous input sources} @!max_in_open=6; {maximum number of input files and error insertions that can be going on simultaneously} @!font_max=75; {maximum internal font number; must not exceed |max_quarterword| and must be at most |font_base+256|} @!font_mem_size=20000; {number of words of |font_info| for all fonts} @!param_size=60; {maximum number of simultaneous macro parameters} @!nest_size=40; {maximum number of semantic levels simultaneously active} @!max_strings=3000; {maximum number of strings; must not exceed |max_halfword|} @!string_vacancies=8000; {the minimum number of characters that should be available for the user's control sequences and font names, after \TeX's own error messages are stored} @!pool_size=32000; {maximum number of characters in strings, including all error messages and help texts, and the names of all fonts and control sequences; must exceed |string_vacancies| by the total length of \TeX's own strings, which is currently about 23000} @!save_size=600; {space for saving values outside of current group; must be at most |max_halfword|} @!trie_size=8000; {space for hyphenation patterns; should be larger for \.{INITEX} than it is in production versions of \TeX} @!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8} @!file_name_size=40; {file names shouldn't be longer than this} @!pool_name='TeXformats:TEX.POOL '; {string of length |file_name_size|; tells where the string pool appears} @y @!mem_max=65500; {greatest index in \TeX's internal |mem| array; must be strictly less than |max_halfword|; must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|} @!mem_min=0; {smallest index in \TeX's internal |mem| array; must be |min_halfword| or more; must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|} @!buf_size=500; {maximum number of characters simultaneously present in current lines of open files and in control sequences between \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|} @!error_line=79; {width of context lines on terminal error messages} @!half_error_line=50; {width of first lines of contexts in terminal error messages; should be between 30 and |error_line-15|} @!max_print_line=79; {width of longest text lines output; should be at least 60} @!stack_size=200; {maximum number of simultaneous input sources} @!max_in_open=6; {maximum number of input files and error insertions that can be going on simultaneously} @!font_max=100; {maximum internal font number; must not exceed |max_quarterword| and must be at most |font_base+256|} @!font_mem_size=35000; {number of words of |font_info| for all fonts} @!param_size=60; {maximum number of simultaneous macro parameters} @!nest_size=40; {maximum number of semantic levels simultaneously active} @!max_strings=5400; {maximum number of strings; must not exceed |max_halfword|} @!string_vacancies=26000; {the minimum number of characters that should be available for the user's control sequences and font names, after \TeX's own error messages are stored} @!pool_size=65500; {maximum number of characters in strings, including all error messages and help texts, and the names of all fonts and control sequences; must exceed |string_vacancies| by the total length of \TeX's own strings, which is currently about 22500} @!save_size=600; {space for saving values outside of current group; must be at most |max_halfword|} @!trie_size=8000; {space for hyphenation patterns; should be larger for \.{INITEX} than it is in production versions of \TeX} @!dvi_buf_size=1024; {size of the output buffer; must be a multiple of 8} @!VAX_block_length=512; {must be half |dvi_buf_size| on Vax/VMS} @!file_name_size=69; {file names shouldn't be longer than this} @!pool_name= 'TeX$formats:TEX.POO '; {string of length |file_name_size|; tells where the string pool appears} @.TeX{\$}formats@> @z @x [1] Tangle-time constants @d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX}; must not be less than |mem_min|} @d mem_top==30000 {largest index in the |mem| array dumped by \.{INITEX}; must be substantially larger than |mem_bot| and not greater than |mem_max|} @d font_base=0 {smallest internal font number; must not be less than |min_quarterword|} @d hash_size=2100 {maximum number of control sequences; it should be at most about |(mem_max-mem_min)/10|, but 2100 is already quite generous} @d hash_prime=1777 {a prime number equal to about 85\% of |hash_size|} @d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions} @y @d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX}; must not be less than |mem_min|} @d mem_top==65500 {largest index in the |mem| array dumped by \.{INITEX}; must be substantially larger than |mem_bot| and not greater than |mem_max|} @d font_base=0 {smallest internal font number; must not be less than |min_quarterword|} @d hash_size=2500 {maximum number of control sequences; it should be at most about |(mem_max-mem_min)/10|, but 2100 is already quite generous} @d hash_prime=2113 {a prime number equal to about 85\% of |hash_size|} @d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions} @z @x [2] System-dependent character set changes: @^character set dependencies@> @^system dependencies@> @= for i:=1 to @'37 do xchr[i]:=' '; @y @^character set dependencies@> @^system dependencies@> The code shown here is intended to be used on VAX/VMS systems, and at other installations where only the printable ASCII set, plus |carriage_return|, |tab|, and |form_feed| will show up in text files. All |line_feed| and |null| characters are skipped. @d form_feed=@'14 {ASCII code used at end of a page} @d tab=@'11 @= for i:=1 to @'37 do xchr[i]:=chr(i); xchr[form_feed]:=chr(form_feed); xchr[tab]:=chr(tab); @z @x [3] alpha files are text and byte files are blocks @!alpha_file=packed file of text_char; {files that contain textual data} @!byte_file=packed file of eight_bits; {files that contain binary data} @y @!alpha_file=VAX_text; {files that contain textual data} @!byte_block=packed array [0..VAX_block_length-1] of eight_bits; @!byte_file=packed file of byte_block; {files that contain binary data} @z @x @d reset_OK(#)==erstat(#)=0 @d rewrite_OK(#)==erstat(#)=0 @p function a_open_in(var f:alpha_file):boolean; @y @p function user_reset (var FAB:VAX_FAB_type; var RAB:VAX_RAB_type; var F:unsafe_file):integer; var status:integer; NAM:NAM_ptr; p:charptr; i:integer; begin last_length:=0; status:=VAX_open(FAB); if odd(status) then status:=VAX_connect(RAB); if odd(status) then begin NAM:=FAB.VAX_FAB_L_NAM::NAM_ptr; if NAM<>nil then last_length:=NAM^.VAX_NAM_B_RSL; for i:=1 to last_length do begin p:=(NAM^.VAX_NAM_L_RSA::integer+i-1)::charptr; last_name[i]:=p^; end; end; user_reset:=status; end; @# function user_rewrite (var FAB:VAX_FAB_type; var RAB:VAX_RAB_type; var F:unsafe_file):integer; var status:integer; NAM:NAM_ptr; p:charptr; i:integer; begin status:=VAX_create(FAB); if odd(status) then status:=VAX_connect(RAB); if odd(status) then begin NAM:=FAB.VAX_FAB_L_NAM::NAM_ptr; if NAM<>nil then last_length:=NAM^.VAX_NAM_B_RSL; for i:=1 to last_length do begin p:=(NAM^.VAX_NAM_L_RSA::integer+i-1)::charptr; last_name[i]:=p^; end; end; user_rewrite:=status; end; @# function a_open_in(var f:alpha_file):boolean; @z @x [3] file opening begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); @y begin open(f,name_of_file,VAX_readonly,VAX_user_action:=user_reset, VAX_error:=VAX_continue); if status(f)>0 then a_open_in:=false else begin reset(f,VAX_error:=VAX_continue); a_open_in:=status(f)<=0; end; @z @x begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); @y begin open(f,name_of_file,VAX_new,16383,VAX_disposition:=VAX_delete, VAX_user_action:=user_rewrite,VAX_error:=VAX_continue); if status(f)>0 then a_open_out:=false else begin linelimit(f,maxint); rewrite(f,VAX_error:=VAX_continue); a_open_out:=status(f)<=0; end; @z @x begin reset(f,name_of_file,'/O'); b_open_in:=reset_OK(f); @y begin open(f,name_of_file,VAX_readonly,VAX_user_action:=user_reset, VAX_error:=VAX_continue); if status(f)>0 then b_open_in:=false else begin reset(f,VAX_error:=VAX_continue); b_open_in:=status(f)<=0; end; @z @x begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f); @y begin open(f,name_of_file,VAX_new,VAX_disposition:=VAX_delete, VAX_user_action:=user_rewrite,VAX_error:=VAX_continue); if status(f)>0 then b_open_out:=false else begin rewrite(f,VAX_error:=VAX_continue); b_open_out:=status(f)<=0; end; @z @x begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f); @y begin open(f,name_of_file,VAX_readonly,VAX_user_action:=user_reset, VAX_error:=VAX_continue); if status(f)>0 then w_open_in:=false else begin reset(f,VAX_error:=VAX_continue); w_open_in:=status(f)<=0; end; fmt_count:=0; {hack} @z @x begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f); @y begin open(f,name_of_file,VAX_new,VAX_disposition:=VAX_delete, VAX_user_action:=user_rewrite,VAX_error:=VAX_continue); if status(f)>0 then w_open_out:=false else begin rewrite(f,VAX_error:=VAX_continue); w_open_out:=status(f)<=0; end; fmt_count:=0; {hack} @z @x [3] file closing begin close(f); @y begin close(f,VAX_disposition:=VAX_save,VAX_error:=VAX_continue); @z @x begin close(f); @y begin close(f,VAX_disposition:=VAX_save,VAX_error:=VAX_continue); @z @x begin close(f); @y begin close(f,VAX_disposition:=VAX_save,VAX_error:=VAX_continue); @z @x [3] read into auxiliary buffer first representing the beginning and ending of a line of text. @= @y representing the beginning and ending of a line of text. On Vax/VMS, we will read the lines first into an auxiliary buffer, in order to save the running time of procedure-call overhead. We have to be very carefull to handle lines longer than the arbitrarily chosen length of the |aux_buf|. @= @!aux_buf:VAX_varying [133] of char; {where the characters go first} @z @x [3] ditto @p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean; {inputs the next line or returns |false|} var last_nonblank:0..buf_size; {|last| with trailing blanks removed} begin if bypass_eoln then if not eof(f) then get(f); {input the first character of the line into |f^|} last:=first; {cf.\ Matthew 19\thinspace:\thinspace30} if eof(f) then input_ln:=false else begin last_nonblank:=first; while not eoln(f) do begin if last>=max_buf_stack then begin max_buf_stack:=last+1; if max_buf_stack=buf_size then overflow("buffer size",buf_size); @:TeX capacity exceeded buffer size}{\quad buffer size@> end; buffer[last]:=xord[f^]; get(f); incr(last); if buffer[last-1]<>" " then last_nonblank:=last; end; last:=last_nonblank; input_ln:=true; end; end; @y @p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean; {inputs the next line or returns |false|} label found; var @!len:integer; {length of line input} @!k:0..buf_size; {index into |buffer|} begin last:=first; {cf.\ Matthew 19\thinspace:\thinspace30} if status(f)<>0 then input_ln:=false else begin while not eoln(f) do begin read(f,aux_buf,VAX_error:=VAX_continue); len:=VAX_length(aux_buf); if last+len>=max_buf_stack then begin if last+lenfirst then if buffer[last-1]=" " then begin decr(last); goto found; end; input_ln:=true; read_ln(f,VAX_error:=VAX_continue); end; end; @z @x [3] terminal file opening @ Here is how to open the terminal files in \ph. The `\.{/I}' switch suppresses the first |get|. @^system dependencies@> @d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input} @d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output} @y @ Here is how to open the terminal files under Vax/VMS. @^system dependencies@> @d t_open_in==begin open(term_in,'SYS$INPUT'); reset(term_in); in_FAB:=VAX_PAS_FAB(term_in); in_RAB:=VAX_PAS_RAB(term_in); end {open the terminal for text input} @d t_open_out==begin open(term_out,'SYS$OUTPUT',VAX_carriage_control:=VAX_none); linelimit(term_out,maxint); rewrite(term_out); out_FAB:=VAX_PAS_FAB(term_out); out_RAB:=VAX_PAS_RAB(term_out); end {open the terminal for text output} @z @x [3] terminal hacks: clear and update these operations can be specified in \ph: @^system dependencies@> @d update_terminal == break(term_out) {empty the terminal output buffer} @d clear_terminal == break_in(term_in,true) {clear the terminal input buffer} @d wake_up_terminal == do_nothing {cancel the user's cancellation of output} @y these operations can be specified in Vax/VMS Pascal: @^system dependencies@> @d update_terminal == write_ln(term_out) {empty the terminal output buffer} @d clear_terminal == in_RAB^.@=RAB$V_PTA@>:=true {clear the terminal input buffer} @.PTA@> @d wake_up_terminal == begin out_RAB^.@=RAB$V_CCO@>:=true; write_ln(term_out); out_RAB^.@=RAB$V_CCO@>:=false; end {cancel the user's cancellation of output} @.CCO@> @d crlf == chr(13),chr(10) @z @x [3] terminal initialization @ The following program does the required initialization without retrieving a possible command line. It should be clear how to modify this routine to deal with command lines, if the system permits them. @^system dependencies@> @p function init_terminal:boolean; {gets the terminal input started} label exit; begin t_open_in; loop@+begin wake_up_terminal; write(term_out,'**'); update_terminal; @.**@> if not input_ln(term_in,true) then {this shouldn't happen} begin write_ln(term_out); write(term_out,'! End of file on the terminal... why?'); @.End of file on the terminal@> init_terminal:=false; return; end; loc:=first; while (loc @p [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; function init_terminal:boolean; {gets the terminal input started} label exit; var command_line: packed array[1..300] of char; @!len: sixteen_bits; @!i: integer; begin t_open_in; i:=0; VAX_lib_get_foreign(command_line,,len,i); i:=1; while (i<=len) and (command_line[i]=' ') do incr(i); if i<=len then begin loc:=first; last:=first; while i<=len do begin buffer[last]:=xord[command_line[i]]; if (buffer[last]>="A") and (buffer[last]<="Z") then buffer[last]:=buffer[last]+"a"-"A"; incr(last); incr(i); end; init_terminal:=true; return; end; loop@+begin wake_up_terminal; write(term_out,'**'); update_terminal; @.**@> if not input_ln(term_in,true) then {this shouldn't happen} begin write(term_out,crlf); write_ln(term_out,'! End of file on the terminal... why?',crlf); @.End of file on the terminal@> init_terminal:=false; return; end; loc:=first; while (loc} @y in_RAB^.@=RAB$V_PTA@>:=false; {turn off purging of typeahead} @.PTA@> term_offset:=0; {the user's line ended with \<\rm return>} @z @x [6] interrupts @d check_interrupt==begin if interrupt<>0 then pause_for_instructions; end @= @!interrupt:integer; {should \TeX\ pause for instructions?} @y @d check_interrupt==begin if interrupt<>0 then pause_for_instructions; end @d enable_control_C== VAX_qiow(,tt_chan,VAX_io_setmode+VAX_iom_ctrlcast,,,, VAX_immed ctrlc_rout,,VAX_immed 3,,,); @= @!interrupt:[VAX_volatile]integer; {should \TeX\ pause for instruction?} @z @x interrupt:=0; OK_to_interrupt:=true; @y interrupt:=0; OK_to_interrupt:=true; if VAX_assign('TT',tt_chan,,)=1 then enable_control_C; @z @x [7] double precision reals @d set_glue_ratio_zero(#) == #:=0.0 {store the representation of zero ratio} @d set_glue_ratio_one(#) == #:=1.0 {store the representation of unit ratio} @d float(#) == # {convert from |glue_ratio| to type |real|} @d unfloat(#) == # {convert from |real| to type |glue_ratio|} @d float_constant(#) == #.0 {convert |integer| constant to |real|} @= @!glue_ratio=real; {one-word representation of a glue expansion factor} @y On Vax/VMS, we use some hackery to cause floating point numbers stored in |mem| to be |single|, but other |real| variables and expressions are done as |double| length reals. @d set_glue_ratio_zero(#) == #:=0.0 {store the representation of zero ratio} @d set_glue_ratio_one(#) == #:=1.0 {store the representation of unit ratio} @d real == double {use double precision reals for computation} @d float(#) == dble(#) {convert from |glue_ratio| to type |real|} {FIX ME} @d unfloat(#) == sngl(1.0@&D0 * #) {convert from |real| to type |glue_ratio|} @d float_constant(#) == #.0@&D0 {convert |integer| constant to |real|} @= @!glue_ratio=r@&e@&a@&l; {one-word representation of a glue expansion factor} @z @x @d qi(#)==#+min_quarterword {to put an |eight_bits| item into a quarterword} @d qo(#)==#-min_quarterword {to take an |eight_bits| item out of a quarterword} @d hi(#)==#+min_halfword {to put a sixteen-bit item into a halfword} @d ho(#)==#-min_halfword {to take a sixteen-bit item from a halfword} @y @d qi(#)==# @d qo(#)==# @d hi(#)==# @d ho(#)==# @z @x [8] block up word files @!word_file = file of memory_word; @y @!word_block = packed array [0..VAX_block_length-1] of memory_word; @!word_file = packed file of word_block; @z @x [12] check glue ratio for REALness arbitrary random value. The following code assumes that a properly formed nonzero |real| number has absolute value $2^{20}$ or more when it is regarded as an integer; this precaution was adequate to prevent floating point underflow on the author's computer. @y arbitrary random value. The following code uses the Vax/VMS predeclared routine |undefined|. @z @x if abs(mem[p+glue_offset].int)<@'4000000 then print("?.?") @y if VAX_undefined(mem[p+glue_offset].gr) then print("?.?") @z @x [17] Special form_feed initialization: cat_code("\"):=escape; cat_code("%"):=comment; @y cat_code("\"):=escape; cat_code("%"):=comment; cat_code(form_feed):=car_ret; @z @x [17] date/time Since standard \PASCAL\ cannot provide such information, something special is needed. The program here simply specifies July 4, 1776, at noon; but users probably want a better approximation to the truth. @p procedure fix_date_and_time; begin time:=12*60; {minutes since midnight} day:=4; {fourth day of the month} month:=7; {seventh month of the year} year:=1776; {Anno Domini} @y @p procedure fix_date_and_time; var t:array[1..7] of signed_halfword; {raw year, month, day and time} begin VAX_numtim(t); year:=t[1]; month:=t[2]; day:=t[3]; time:=t[4]*60+t[5]; {minutes since midnight} @z @x [28] file names and default areas following structure: If the name contains `\.>' or `\.:', the file area @y following structure: If the name contains `\.]' or `\.:', the file area @z @x [28] system logical names @d TEX_area=="TeXinputs:" @.TeXinputs@> @d TEX_font_area=="TeXfonts:" @.TeXfonts@> @y @d TEX_area=="TeX$inputs:" @.TeXinputs@> @.TeX{\$}inputs@> @d TEX_font_area=="TeX$fonts:" @.TeXfonts@> @.TeX{\$}fonts@> @z @x [28] directories delimited with square brackets else begin if (c=">")or(c=":") then @y else begin if (c="]")or(c=":") then @z @x [29] Logical name translation: @ The third. @^system dependencies@> @p procedure end_name; begin if str_ptr+3>max_strings then overflow("number of strings",max_strings-init_str_ptr); @:TeX capacity exceeded number of strings}{\quad number of strings@> if area_delimiter=0 then cur_area:="" else begin cur_area:=str_ptr; incr(str_ptr); str_start[str_ptr]:=area_delimiter+1; end; if ext_delimiter=0 then begin cur_ext:=""; cur_name:=make_string; end else begin cur_name:=str_ptr; incr(str_ptr); str_start[str_ptr]:=ext_delimiter; cur_ext:=make_string; end; end; @y @ The third. We have to check to see if a logical name has been referred to, and if so, translate it. @^system dependencies@> @p procedure end_name; label restart,exit; var s,@!u:VAX_varying[file_name_size] of char; @!t:packed array[1..file_name_size] of char; @!TRNLOG_return: integer; {what did the TRNLOG return?} @!i:pool_pointer; @!len:signed_halfword; @!c:char; begin restart: if (str_pool[area_delimiter]=":") and (pool_ptr=area_delimiter+1) then begin cur_area:=make_string; len:=length(cur_area)-1; {don't include the colon} for i:=1 to len do begin c:=xchr[str_pool[str_start[cur_area]+i-1]]; if ('a'<=c) and (c<='z') then c:=chr(ord(c)+ord('A')-ord('a')); t[i]:=c; end; s:=VAX_substr(t,1,len); TRNLOG_return:=VAX_trnlog(s,len,t,,,); if TRNLOG_return<>VAX_ss_normal then begin cur_ext:=""; cur_name:=""; {silly case} return; end; flush_string; {needn't remember logical name in |cur_area|} begin_name; for i:=1 to len do if not more_name(xord[t[i]]) then goto restart; goto restart; {heavy!} end; if str_ptr+3>max_strings then overflow("number of strings",max_strings-init_str_ptr); @:TeX capacity exceeded number of strings}{\quad number of strings@> if area_delimiter=0 then cur_area:="" else begin cur_area:=str_ptr; incr(str_ptr); str_start[str_ptr]:=area_delimiter+1; end; if ext_delimiter=0 then begin cur_ext:=""; cur_name:=make_string; end else begin cur_name:=str_ptr; incr(str_ptr); str_start[str_ptr]:=ext_delimiter; cur_ext:=make_string; end; exit: end; @z @x [28] system logical names @d format_default_length=20 {length of the |TEX_format_default| string} @d format_area_length=11 {length of its area part} @y @d format_default_length=21 {length of the |TEX_format_default| string} @d format_area_length=12 {length of its area part} @z @x [28] system logical names TEX_format_default:='TeXformats:plain.fmt'; @y TEX_format_default:='TeX$formats:plain.fmt'; @.TeX{\$}formats@> @z @x [28] get file name from system begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings) then make_name_string:="?" else begin for k:=1 to name_length do append_char(xord[name_of_file[k]]); make_name_string:=make_string; end; @y begin if (pool_ptr+last_length>pool_size)or(str_ptr=max_strings) then make_name_string:="?" else begin for k:=1 to last_length do append_char(xord[last_name[k]]); make_name_string:=make_string; end; @z @x @p procedure pack_job_name(@!s:str_number); {|s = ".log"|, |".dvi"|, or @y @p procedure pack_job_name(@!s:str_number); {|s = ".lis"|, |".dvi"|, or @z @x pack_job_name(".log"); @y pack_job_name(".lis"); @z @x prompt_file_name("transcript file name",".log"); @y prompt_file_name("transcript file name",".lis"); @z @x [29] tfm blocking if not b_open_in(tfm_file) then abort; @y if not b_open_in(tfm_file) then abort; tfm_count:=0; @z @x [29] tfm blocked @d fget==get(tfm_file) @d fbyte==tfm_file^ @y @d fget==begin incr(tfm_count); if tfm_count=VAX_block_length then begin get(tfm_file,VAX_error:=VAX_continue); tfm_count:=0; end end @d fbyte==tfm_file^[tfm_count] @z @x [29] tfm blocked if eof(tfm_file) then abort; @y if status(tfm_file)<>0 then abort; if eof(tfm_file) then abort; @z @x [31] dvi blocked @ 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. @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 [31] dvi blocked @ The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling |write_dvi(a,b)|. For best results, this procedure should be optimized to run as fast as possible on each particular system, since it is part of \TeX's inner loop. 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@> @^inner loop@> @^defecation@> @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. Thus, we have to be sure that things line up properly. @^system dependencies@> @^inner loop@> @^defecation@> @= if dvi_buf_size<>2*VAX_block_length then bad:=223; @z % [31] dvi blocked @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 [31] dvi blocked 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 [50] block fmt files @d dump_wd(#)==begin fmt_file^:=#; put(fmt_file);@+end @d dump_int(#)==begin fmt_file^.int:=#; put(fmt_file);@+end @d dump_hh(#)==begin fmt_file^.hh:=#; put(fmt_file);@+end @d dump_qqqq(#)==begin fmt_file^.qqqq:=#; put(fmt_file);@+end @y @d fmt_put==begin incr(fmt_count); if fmt_count=VAX_block_length then begin put(fmt_file,VAX_error:=VAX_continue); fmt_count:=0; end end @d fmt_word==fmt_file^[fmt_count] @d dump_wd(#)==begin fmt_word:=#; fmt_put;@+end @d dump_int(#)==begin fmt_word.int:=#; fmt_put;@+end @d dump_hh(#)==begin fmt_word.hh:=#; fmt_put;@+end @d dump_qqqq(#)==begin fmt_word.qqqq:=#; fmt_put;@+end @z @x @d undump_wd(#)==begin get(fmt_file); #:=fmt_file^;@+end @d undump_int(#)==begin get(fmt_file); #:=fmt_file^.int;@+end @d undump_hh(#)==begin get(fmt_file); #:=fmt_file^.hh;@+end @d undump_qqqq(#)==begin get(fmt_file); #:=fmt_file^.qqqq;@+end @y @d fmt_get==begin incr(fmt_count); if fmt_count=VAX_block_length then begin get(fmt_file,VAX_error:=VAX_continue); fmt_count:=0; end end @d undump_wd(#)==begin fmt_get; #:=fmt_word;@+end @d undump_int(#)==begin fmt_get; #:=fmt_word.int;@+end @d undump_hh(#)==begin fmt_get; #:=fmt_word.hh;@+end @d undump_qqqq(#)==begin fmt_get; #:=fmt_word.qqqq;@+end @z @x x:=fmt_file^.int; @y x:=fmt_word.int; @z @x [50] fmt file blocked w_close(fmt_file) @y while fmt_count>0 do dump_int(0); {flush out the buffer} w_close(fmt_file) @z @x @!ready_already:integer; {a sacrifice of purity for economy} @y @!ready_already:[VAX_static]integer := 0; {a sacrifice of purity for economy} @z @x [54] left overs This section should be replaced, if necessary, by changes to the program that are necessary to make \TeX\ 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 published program. More extensive changes, which introduce new sections, can be inserted here; then only the index itself will get a new section number. @y Here are the remaining changes to the program that are necessary to make \.{TeX} work on Vax/VMS. @ Here are the things we need for |byte_file| and |word_file| files: @= @!tfm_count: 0..VAX_block_length; @!fmt_count: 0..VAX_block_length; @ Here's the interrupt stuff. @= @!signed_halfword=[VAX_word] -32768..32767; @!sixteen_bits=[VAX_word] 0..65535; @ @= @!itm: array [1..4] of VAX_unsigned; @!res:[VAX_volatile] integer; @!tt_chan: [VAX_volatile] signed_halfword; @ @= [asynchronous] procedure @!ctrlc_rout; begin interrupt:=1; enable_control_C; end; @ Here is the stuff for magic file operations. @= unsafe_file = [unsafe] file of char; FAB_ptr = ^VAX_FAB_type; RAB_ptr = ^VAX_RAB_type; NAM_ptr = ^VAX_NAM_type; charptr = ^char; @ @= function VAX_PAS_FAB(var foobar:unsafe_file):FAB_ptr; extern; function VAX_PAS_RAB(var foobar:unsafe_file):RAB_ptr; extern; @ @= in_FAB,out_FAB: FAB_ptr; in_RAB,out_RAB: RAB_ptr; last_length: integer; last_name:packed array [1..file_name_size] of char; @z