diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /obsolete/systems/knuth/unsupported/tex/tex.vms-changes |
Initial commit
Diffstat (limited to 'obsolete/systems/knuth/unsupported/tex/tex.vms-changes')
-rw-r--r-- | obsolete/systems/knuth/unsupported/tex/tex.vms-changes | 1092 |
1 files changed, 1092 insertions, 0 deletions
diff --git a/obsolete/systems/knuth/unsupported/tex/tex.vms-changes b/obsolete/systems/knuth/unsupported/tex/tex.vms-changes new file mode 100644 index 0000000000..35e203cc2e --- /dev/null +++ b/obsolete/systems/knuth/unsupported/tex/tex.vms-changes @@ -0,0 +1,1092 @@ +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 +@<Vax/VMS procedures@>@/ +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 +@<Compiler directives@>= +@{@&$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@> + +@<Compiler directives@>= +@\@=[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@> + +@<Set init...@>= +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 + +@<Set initial values...@>= +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. + +@<Glob...@>= +@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|. + +@<Glob...@>= +@!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+len<buf_size then max_buf_stack:=last+len + else overflow("buffer size",buf_size); + end; + for k:=last to last+len-1 do buffer[k]:=xord[aux_buf[k-last+1]]; + last:=last+len; + end; + found: if last>first 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<last)and(buffer[loc]=" ") do incr(loc); + if loc<last then + begin init_terminal:=true; + return; {return unless the line was all blank} + end; + write_ln(term_out,'Please type the name of your input file.'); + end; +exit:end; +@y +@ The following program does the required initialization +by retrieving a possible command line, and if none exists, +prompting the user for the first line of input. +@^system dependencies@> + +@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<last)and(buffer[loc]=" ") do incr(loc); + if loc<last then + begin init_terminal:=true; + return; {return unless the line was all blank} + end; + write_ln(term_out,'Please type the name of your input file.',crlf); + end; +exit:end; +@z + +@x [4] bad_pool needs real crlf +@ @d bad_pool(#)==begin wake_up_terminal; write_ln(term_out,#); +@y +@ @d bad_pool(#)==begin wake_up_terminal; write_ln(term_out,#,crlf); +@z + +@x [5] real crlf for terminal +@d wterm(#)==write(term_out,#) +@d wterm_ln(#)==write_ln(term_out,#) +@d wterm_cr==write_ln(term_out) +@y +@d wterm(#)==write(term_out,#) +@d wterm_ln(#)==write_ln(term_out,#,crlf) +@d wterm_cr==write_ln(term_out,crlf) +@z + +@x [5] Turn off clearing typeahead after terminal input +term_offset:=0; {the user's line ended with \<\rm return>} +@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 + +@<Global...@>= +@!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,,,); + +@<Global...@>= +@!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|} + +@<Types...@>= +@!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|} + +@<Types...@>= +@!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@> + +@<Glob...@>= +@!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} + +@<Glob...@>= +@!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@> + +@<Check the ``co...@>= +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: + +@<Glob...@>= +@!tfm_count: 0..VAX_block_length; +@!fmt_count: 0..VAX_block_length; + +@ Here's the interrupt stuff. + +@<Types...@>= +@!signed_halfword=[VAX_word] -32768..32767; +@!sixteen_bits=[VAX_word] 0..65535; + +@ @<Glob...@>= +@!itm: array [1..4] of VAX_unsigned; +@!res:[VAX_volatile] integer; +@!tt_chan: [VAX_volatile] signed_halfword; + +@ @<Vax/VMS procedures@>= +[asynchronous] procedure @!ctrlc_rout; +begin +interrupt:=1; +enable_control_C; +end; + +@ Here is the stuff for magic file operations. +@<Types...@>= +unsafe_file = [unsafe] file of char; +FAB_ptr = ^VAX_FAB_type; +RAB_ptr = ^VAX_RAB_type; +NAM_ptr = ^VAX_NAM_type; +charptr = ^char; + +@ @<Vax/VMS procedures@>= +function VAX_PAS_FAB(var foobar:unsafe_file):FAB_ptr; extern; +function VAX_PAS_RAB(var foobar:unsafe_file):RAB_ptr; extern; + +@ @<Glob...@>= +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 |