diff options
Diffstat (limited to 'obsolete/systems/sisisi/unix/SiTeX3.141/tex.ch.other')
-rw-r--r-- | obsolete/systems/sisisi/unix/SiTeX3.141/tex.ch.other | 1964 |
1 files changed, 1964 insertions, 0 deletions
diff --git a/obsolete/systems/sisisi/unix/SiTeX3.141/tex.ch.other b/obsolete/systems/sisisi/unix/SiTeX3.141/tex.ch.other new file mode 100644 index 0000000000..ef710b8def --- /dev/null +++ b/obsolete/systems/sisisi/unix/SiTeX3.141/tex.ch.other @@ -0,0 +1,1964 @@ +% tex.ch for C compilation with web2c, derived from various other change files. +% By Tim Morgan, UC Irvine ICS Department, and many others. +% +% Modification history: +% (05/28/86) ETM Started with TeX 2.0 +% (06/03/87) ETM Brought up to TeX 2.2 +% (09/26/87) ETM Brought up to TeX 2.3 +% (10/01/87) ETM Brought up to TeX 2.5 +% (12/21/87) ETM Brought up to TeX 2.7 +% (01/14/88) ETM Brought up to TeX 2.9 +% (02/20/88) PAM Revised format and module numbers +% (03/01/88) ETM Eliminated some unused variables and unnecesary tests +% (05/09/88) ETM Added yet another casting bug fix +% (06/21/88) ETM Brought up to TeX version 2.93 +% (12/11/88) ETM Brought up to TeX version 2.94 +% (01/12/89) PAM Brought up to TeX version 2.95 +% (02/14/89) ETM Brought up to TeX version 2.96 +% (03/10/89) ETM Brought up to TeX version 2.98 +% (07/06/89) ETM Brought up to TeX version 2.991 +% (11/30/89) KB To version 2.992 (8-bit). +% (01/10/90) SR To version 2.993. +% (03/27/90) KY To version 3.0. +% (more recent changes in ChangeLog) +% +% The module numbers in this change file refer to the published text in +% TeX: The Program, Volume B of Computers&Typesetting. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [0] WEAVE: print changes only. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + \def\?##1]{\hbox to 1in{\hfil##1.\ }} + } +@y + \def\?##1]{\hbox{Changes to \hbox to 1em{\hfil##1}.\ }} + } +\let\maybe=\iffalse +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.2] banner +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d banner=='This is TeX, Version 3.141 (+SISISI 1.0)' +@y +@d banner=='This is TeX, Version 3.141 (+SISISI 1.0)' {more is printed later} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.4] program header +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +Actually the heading shown here is not quite normal: The |program| line +does not mention any |output| file, because \ph\ would ask the \TeX\ user +to specify a file name if |output| were specified here. +@^system dependencies@> + +@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:} +@f mtype==type {`\&{mtype}' will be equivalent to `\&{type}'} +@f type==true {but `|type|' will not be treated as a reserved word} + +@p @t\4@>@<Compiler directives@>@/ +program TEX; {all file names are defined dynamically} +label @<Labels in the outer block@>@/ +@y + +@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:} +@f mtype==type {`\&{mtype}' will be equivalent to `\&{type}'} +@f type==true {but `|type|' will not be treated as a reserved word} + +@p @t\4@>@<Compiler directives@>@/ +program TEX; {all file names are defined dynamically} +@z + +@x +@<Labels in the out...@>= +start_of_TEX@t\hskip-2pt@>, end_of_TEX@t\hskip-2pt@>,@,final_end; + {key control points} +@y +@<Labels in the outer block@>= +start_of_TEX@t\hskip-2pt@>, end_of_TEX@t\hskip-2pt@>,@,final_end; + {key control points} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.7] debug..gubed, stat..tats +% Here we change these WEB symbols, which are used much as #ifdef's +% are in C, into something which will get translated into actual #ifdef's. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@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==ifdef('DEBUG') +@d gubed==endif('DEBUG') +@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==ifdef('STAT') +@d tats==endif('STAT') +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.8] Same, for `init..tini'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@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==ifdef('INITEX') +@d tini==endif('INITEX') +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.9] Turn off all compiler directives. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead} +@!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging} +@y +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.11] Compile-time constants: some enlarged, dvi_buf_size 16K for +% BSD I/O, file_name_size is set from the system constant. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@<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} +@!trie_op_size=500; {space for ``opcodes'' in the hyphenation patterns} +@!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:SITEX3.POOL '; + {string of length |file_name_size|; tells where the string pool appears} +@y +@d file_name_size == PATH_MAX + +@<Constants...@>= +@!mem_max=262140; {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=3000; {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=300; {maximum number of simultaneous input sources} +@!max_in_open=15; {maximum number of input files and error insertions that + can be going on simultaneously} +@!font_max=255; {maximum internal font number; must not exceed |max_quarterword| + and must be at most |font_base+256|} +@!font_mem_size=100000; {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=15000; {maximum number of strings; must not exceed |max_halfword|} +@!string_vacancies=100000; {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=124000; {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=4000; {space for saving values outside of current group; must be + at most |max_halfword|} +@!trie_size=30000; {space for hyphenation patterns; should be larger for + \.{INITEX} than it is in production versions of \TeX. This much is + needed for English, German, and Portuguese.} +@!trie_op_size=751; {space for ``opcodes'' in the hyphenation patterns; + should be relatively prime to 313, 361, and 1009, and prime.} +@!neg_trie_op_size=-751; {for lower |trie_op_hash| array bound; + must be equal to |-trie_op_size|.} +@!min_trie_op=0; {first possible trie op code for any language} +@!max_trie_op=500; {largest possible trie op code for any language} +@!dvi_buf_size=16384; {size of the output buffer; must be a multiple of 8} +@!pool_name='sitex.pool'; + {string of length |file_name_size|; tells where the string pool appears} +@!mem_top=262140; {largest index in the |mem| array dumped by \.{INITEX}; + must be substantially larger than |mem_bot|, + equal to |mem_max| in \.{INITEX}, else not greater than |mem_max|} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.12] Sensitive compile-time constants. For C we change mem_base and +% hi_mem_base to reflect our use of 0-origin vs pc's use of +% negative-origin. Despite the fact that it is a ``sensitive'' +% constant, we're going to make mem_top a #define in the C code for +% readability and ease of modification (it's up above) -- it needs +% to be changed for the trip test. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@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|} +@d hash_prime=1777 {a prime number equal to about 85\pct! 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 font_base=0 {smallest internal font number; must not be less + than |min_quarterword|} +@d hash_size=9500 {maximum number of control sequences; it should be at most + about |(mem_max-mem_min)/10|} +@d hash_prime=7919 {a prime number equal to about 85\pct! of |hash_size|} +@d hyph_size=607 {another prime; the number of \.{\\hyphenation} exceptions} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [1.16] Use C macros for `incr' and `decr'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d incr(#) == #:=#+1 {increase a variable by unity} +@d decr(#) == #:=#-1 {decrease a variable by unity} +@y +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [??] The text_char type is used as an array index into xord. The +% default type `char' produces signed integers, which are bad array +% indices in C. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d text_char == char {the data type of characters in text files} +@y +@d text_char == ASCII_code {the data type of characters in text files} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [2.23] Allow any character as input. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +for i:=0 to @'37 do xchr[i]:=' '; +for i:=@'177 to @'377 do xchr[i]:=' '; +@y +for i:=0 to @'37 do xchr[i]:=chr(i); +for i:=@'177 to @'377 do xchr[i]:=chr(i); +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.25] Remove file types we don't need. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +The program actually makes use also of a third kind of file, called a +|word_file|, when dumping and reloading base information for its own +initialization. We shall define a word file later; but it will be possible +for us to specify simple operations on word files before they are defined. + +@y +I/O in C is done using standard I/O. We will define the path numbers +in an include file for C which are used in searching for files to be +read. We'll define all the file types in C also. +@z + +@x +@!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 +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.27] Do file opening in C. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ The \ph\ compiler with which the present version of \TeX\ was prepared has +extended the rules of \PASCAL\ in a very convenient way. To open file~|f|, +we can write +$$\vbox{\halign{#\hfil\qquad&#\hfil\cr +|reset(f,@t\\{name}@>,'/O')|&for input;\cr +|rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$ +The `\\{name}' parameter, which is of type `{\bf packed array +$[\langle\\{any}\rangle]$ of \\{char}}', stands for the name of +the external file that is being opened for input or output. +Blank spaces that might appear in \\{name} are ignored. + +The `\.{/O}' parameter tells the operating system not to issue its own +error messages if something goes wrong. If a file of the specified name +cannot be found, or if such a file cannot be opened for some other reason +(e.g., someone may already be trying to write the same file), we will have +|@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows +\TeX\ to undertake appropriate corrective action. +@:PASCAL H}{\ph@> +@^system dependencies@> + +\TeX's file-opening procedures return |false| if no file identified by +|name_of_file| could be opened. + +@d reset_OK(#)==erstat(#)=0 +@d rewrite_OK(#)==erstat(#)=0 + +@p function a_open_in(var f:alpha_file):boolean; + {open a text file for input} +begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); +end; +@# +function a_open_out(var f:alpha_file):boolean; + {open a text file for output} +begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); +end; +@# +function b_open_in(var f:byte_file):boolean; + {open a binary file for input} +begin reset(f,name_of_file,'/O'); b_open_in:=reset_OK(f); +end; +@# +function b_open_out(var f:byte_file):boolean; + {open a binary file for output} +begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f); +end; +@# +function w_open_in(var f:word_file):boolean; + {open a word file for input} +begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f); +end; +@# +function w_open_out(var f:word_file):boolean; + {open a word file for output} +begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f); +end; +@y +@ All of the file opening functions are defined in C. +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.28] Do file closing in C. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ Files can be closed with the \ph\ routine `|close(f)|', which +@^system dependencies@> +should be used when all input or output with respect to |f| has been completed. +This makes |f| available to be opened again, if desired; and if |f| was used for +output, the |close| operation makes the corresponding external file appear +on the user's area, ready to be read. + +These procedures should not generate error messages if a file is +being closed before it has been successfully opened. + +@p procedure a_close(var f:alpha_file); {close a text file} +begin close(f); +end; +@# +procedure b_close(var f:byte_file); {close a binary file} +begin close(f); +end; +@# +procedure w_close(var f:word_file); {close a word file} +begin close(f); +end; +@y +@ And all the file closing routines as well. +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.31] Do `input_ln' in C. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@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 + @<Report overflow of the input buffer, and abort@>; + 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 +We define |input_ln| in C, for efficiency. +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.32] `term_in' and `term_out' are standard input and output. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@<Glob...@>= +@!term_in:alpha_file; {the terminal as an input file} +@!term_out:alpha_file; {the terminal as an output file} +@y +@d term_in==stdin {the terminal as an input file} +@d term_out==stdout {the terminal as an output file} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.33] We don't need to open terminal files. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ 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. |t_open_out| does nothing. +|t_open_in|, on the other hand, does the work of ``rescanning,'' or getting +any command line arguments the user has provided. It's defined in C. + +@d t_open_out == {output already open for text output} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.34] Flushing output. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +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} +@y +these operations can be specified with {\mc UNIX}. |update_terminal| +does an |fflush| (via the macro |flush|). |clear_terminal| is redefined +to do nothing, since the user should control the terminal. +@^system dependencies@> + +@d update_terminal == flush (term_out) +@d clear_terminal == do_nothing +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [3.37] Reading the command line. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ 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. +Iff anything has been specified on the command line, then |t_open_in| +will return with |last > first|. +@^system dependencies@> + +@p +function init_terminal:boolean; {gets the terminal input started} +label exit; +begin + t_open_in; + if last > first then begin + loc := first; + while (loc < last) and (buffer[loc]=' ') do + incr(loc); + if loc < last then begin + init_terminal := true; + goto exit; + end; + end; + loop@+begin + wake_up_terminal; write(term_out, '**'); update_terminal; +@.**@> + if not input_ln(term_in,true) then begin {this shouldn't happen} + 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; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [4.51] Open the pool file using a path, and can't do string +% assignments directly. (`strcpy' and `strlen' work here because +% `pool_name' is a constant string, and thus ends in a null and doesn't +% start with a space.) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +name_of_file:=pool_name; {we needn't set |name_length|} +if a_open_in(pool_file) then +@y +vstrcpy (name_of_file+1, pool_name); {copy the string} +name_of_file[0] := ' '; +name_of_file[strlen (pool_name) +1 ] := ' '; +name_length := strlen (pool_name); +if a_open_in (pool_file, TEX_POOL_PATH) then +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [4.51,52,53] Make `TEX.POOL' lowercase in messages, and change how +% it's read. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +else bad_pool('! I can''t read SITEX3.POOL.') +@y +else begin + {Like |bad_pool|, but must not close file if we never opened it} + wake_up_terminal; write_ln(term_out, '! I can''t read sitex.pool.'); + get_strings_started:= false; return; +end +@z +@x +begin if eof(pool_file) then bad_pool('! TEX.POOL has no check sum.'); +@.TEX.POOL has no check sum@> +read(pool_file,m,n); {read two digits of string length} +@y +begin if eof(pool_file) then bad_pool('! sitex.pool has no check sum.'); +@.TEX.POOL has no check sum@> +read(pool_file,m); read(pool_file,n); {read two digits of string length} +@z +@x + bad_pool('! TEX.POOL line doesn''t begin with two digits.'); +@y + bad_pool('! sitex.pool line doesn''t begin with two digits.'); +@z +@x + bad_pool('! TEX.POOL check sum doesn''t have nine digits.'); +@y + bad_pool('! sitex.pool check sum doesn''t have nine digits.'); +@z +@x +done: if a<>@$ then bad_pool('! TEX.POOL doesn''t match; TANGLE me again.'); +@y +done: if a<>@$ then bad_pool('! sitex.pool doesn''t match; tangle me again.'); +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [5.61] Eliminate the misleading message ``(no format preloaded)''. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +wterm(banner); +if format_ident=0 then wterm_ln(' (no format preloaded)') +else begin slow_print(format_ident); print_ln; + end; +@y +wterm (banner); +wterm (version_string); +if format_ident>0 then slow_print(format_ident); +print_ln; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [6.81] Eliminate nonlocal goto, since C doesn't have them. +% Plus, it's nicer just to do an exit with the appropriate status code +% under Unix. We call it `uexit' because there's a WEB symbol called +% `exit' already. We use a C macro to change `uexit' back to `exit'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@<Error hand...@>= +procedure jump_out; +begin goto end_of_TEX; +end; +@y +@d do_final_end==begin + update_terminal; + ready_already:=0; + if (history <> spotless) and (history <> warning_issued) then + uexit(1) + else + uexit(0); + end +@<Error hand...@>= +procedure jump_out; +begin +close_files_and_terminate; +do_final_end; +end; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [6.84] Implement the switch-to-editor option. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +line ready to be edited. But such an extension requires some system +wizardry, so the present implementation simply types out the name of the +file that should be +edited and the relevant line number. +@^system dependencies@> + +There is a secret `\.D' option available when the debugging routines haven't +been commented~out. +@^debugging@> +@y +line ready to be edited. +We do this by calling the external procedure |call_edit| with a pointer to +the filename, its length, and the line number. +However, here we just set up the variables that will be used as arguments, +since we don't want to do the switch-to-editor until after TeX has closed +its files. +@^system dependencies@> + +There is a secret `\.D' option available when the debugging routines haven't +been commented~out. +@^debugging@> +@d edit_file==input_stack[base_ptr] +@z +@x +"E": if base_ptr>0 then + begin print_nl("You want to edit file "); +@.You want to edit file x@> + slow_print(input_stack[base_ptr].name_field); + print(" at line "); print_int(line); + interaction:=scroll_mode; jump_out; +@y +"E": if base_ptr>0 then + begin + edit_name_start:=str_start[edit_file.name_field]; + edit_name_length:=str_start[edit_file.name_field+1] - + str_start[edit_file.name_field]; + edit_line:=line; + jump_out; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [7.104] `remainder' is a library routine on some systems, so change +% its name to avoid conflicts. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@<Glob...@>= +@!arith_error:boolean; {has arithmetic overflow occurred recently?} +@!remainder:scaled; {amount subtracted to get an exact division} +@y +@d remainder == tex_remainder +@<Glob...@>= +@!arith_error:boolean; {has arithmetic overflow occurred recently?} +@!remainder:scaled; {amount subtracted to get an exact division} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [7.109] Define glue_ratio in C. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!glue_ratio=real; {one-word representation of a glue expansion factor} +@y +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [8.110] Make it easy to change constants. Do not increase +% max_quarterword without changing the memoryword structure in +% `texmfmem.h'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d min_quarterword=0 {smallest allowable value in a |quarterword|} +@d max_quarterword=255 {largest allowable value in a |quarterword|} +@d min_halfword==0 {smallest allowable value in a |halfword|} +@d max_halfword==65535 {largest allowable value in a |halfword|} +@y +@d min_quarterword=0 {smallest allowable value in a |quarterword|} +@d max_quarterword=255 {largest allowable value in a |quarterword|} +@d min_halfword==0 {smallest allowable value in a |halfword|} +@d max_halfword==262143 {largest allowable value in a |halfword|} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [8.112] Efficiency. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +The inner loop of \TeX\ will run faster with respect to compilers +that don't optimize expressions like `|x+0|' and `|x-0|', if these +macros are simplified in the obvious way when |min_quarterword=0|. +@^inner loop@>@^system dependencies@> + +@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 +The inner loop of \TeX\ will run faster with respect to compilers +that don't optimize expressions like `|x+0|' and `|x-0|', if these +macros are simplified in the obvious way when |min_quarterword=0|. +So they have been simplified here in the obvious way. +@^inner loop@>@^system dependencies@> + +@d qi(#)==# {to put an |eight_bits| item into a quarterword} +@d qo(#)==# {to take an |eight_bits| item from a quarterword} +@d hi(#)==# {to put a sixteen-bit item into a halfword} +@d ho(#)==# {to take a sixteen-bit item from a halfword} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [8.113] We've put the memory structure into the include file +% `texmf.h', since it's too hard to translate automatically. Also, +% remove the `word_file' type. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!quarterword = min_quarterword..max_quarterword; {1/4 of a word} +@!halfword=min_halfword..max_halfword; {1/2 of a word} +@!two_choices = 1..2; {used when there are two variants in a record} +@!four_choices = 1..4; {used when there are four variants in a record} +@!two_halves = packed record@;@/ + @!rh:halfword; + case two_choices of + 1: (@!lh:halfword); + 2: (@!b0:quarterword; @!b1:quarterword); + end; +@!four_quarters = packed record@;@/ + @!b0:quarterword; + @!b1:quarterword; + @!b2:quarterword; + @!b3:quarterword; + end; +@!memory_word = record@;@/ + case four_choices of + 1: (@!int:integer); + 2: (@!gr:glue_ratio); + 3: (@!hh:two_halves); + 4: (@!qqqq:four_quarters); + end; +@!word_file = file of memory_word; +@y +@!quarterword=min_quarterword..max_quarterword; +@!halfword=min_halfword..max_halfword; +@!two_choices = 1..2; {used when there are two variants in a record} +@!four_choices = 1..4; {used when there are four variants in a record} +@=#include "texmfmem.h";@> +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [9.116] Change `mem' to `zmem', so we can define mem to be a register +% pointer to the memory array for speed. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!mem : array[mem_min..mem_max] of memory_word; {the big dynamic storage area} +@y +@!zmem : array[mem_min..mem_max] of memory_word; {the big dynamic storage area} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [9.127] Fix casting problem in C. +% There are several of these. They come from the rules C uses for +% comparing signed and unsigned quantities. Just doing the comparison +% can result in incorrect evaluation wrt the way Pascal would do it. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if r>p+1 then @<Allocate from the top of node |p| and |goto found|@>; +@y +if r>toint(p+1) then @<Allocate from the top of node |p| and |goto found|@>; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [11.165] Fix the word `free' so that it doesn't conflict with the +% standard C library routine of the same name. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +been included. (You may want to decrease the size of |mem| while you +@^debugging@> +are debugging.) +@y +been included. (You may want to decrease the size of |mem| while you +@^debugging@> +are debugging.) + +@d free==free_arr +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [12.174,176] Eliminate some unsigned comparisons to zero. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + begin if (font(p)<font_base)or(font(p)>font_max) then + print_char("*") +@y + begin if (font(p)>font_max) then + print_char("*") +@z + +@x +@p procedure print_font_and_char(@!p:integer); {prints |char_node| data} +begin if p>mem_end then print_esc("CLOBBERED.") +else begin if (font(p)<font_base)or(font(p)>font_max) then print_char("*") +@y +@p procedure print_font_and_char(@!p:integer); {prints |char_node| data} +begin if p>mem_end then print_esc("CLOBBERED.") +else begin if (font(p)>font_max) then print_char("*") +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [12.186] Don't worry about strange floating point values. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + if glue_sign(p)=shrinking then print("- "); + if abs(mem[p+glue_offset].int)<@'4000000 then print("?.?") + else if abs(g)>float_constant(20000) then +@y + if glue_sign(p)=shrinking then print("- "); + { The Unix |pc| folks removed this restriction with a remark that + invalid bit patterns were vanishingly improbable, so we follow + their example without really understanding it. + |if abs(mem[p+glue_offset].int)<@'4000000 then print('?.?')| + |else| } + if fabs(g)>float_constant(20000) then +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [17.241] Do `fix_date_and_time' in C. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ The following procedure, which is called just before \TeX\ initializes its +input and output, establishes the initial values of the date and time. +@^system dependencies@> +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} +end; +@y +@ The following procedure, which is called just before \TeX\ initializes its +input and output, establishes the initial values of the date and time. +It calls a macro-defined |date_and_time| routine. |date_and_time| +in turn is a C macro, which calls |get_date_and_time|, passing +it the addresses of the day, month, etc., so they can be set by the +routine. |get_date_and_time| also sets up interrupt catching if that +is conditionally compiled in the C code. +@^system dependencies@> + +@d fix_date_and_time==date_and_time(time,day,month,year) +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [17.253] Change eqtb to zeqtb. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!eqtb:array[active_base..eqtb_size] of memory_word; +@y +@!zeqtb:array[active_base..eqtb_size] of memory_word; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [18.262] Remove more unsigned comparisons to zero. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +else if (text(p)<0)or(text(p)>=str_ptr) then print_esc("NONEXISTENT.") +@y +else if (text(p)>=str_ptr) then print_esc("NONEXISTENT.") +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.513] Area and extension rules for filenames. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ The file names we shall deal with for illustrative purposes have the +following structure: If the name contains `\.>' or `\.:', the file area +consists of all characters up to and including the final such character; +otherwise the file area is null. If the remaining file name contains +`\..', the file extension consists of all such characters from the first +remaining `\..' to the end, otherwise the file extension is null. +@^system dependencies@> + +We can scan such file names easily by using two global variables that keep track +of the occurrences of area and extension delimiters: + +@<Glob...@>= +@!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any} +@!ext_delimiter:pool_pointer; {the relevant `\..', if any} +@y +@ The file names we shall deal with for illustrative purposes have the +following structure: If the name contains `\./', the file area +consists of all characters up to and including the final such character; +otherwise the file area is null. If the remaining file name contains +`\..', the file extension consists of all such characters from the last +`\..' to the end, otherwise the file extension is null. +@^system dependencies@> + +We can scan such file names easily by using two global variables that keep +track of the occurrences of area and extension delimiters: + +@<Glob...@>= +@!area_delimiter:pool_pointer; {the most recent `\./', if any} +@!ext_delimiter:pool_pointer; {the most recent `\..', if any} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.514] TeX area directories. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d TEX_area=="TeXinputs:" +@.TeXinputs@> +@d TEX_font_area=="TeXfonts:" +@.TeXfonts@> +@y +In C, the default paths are specified in a separate +file, \.{site.h}. The file opening procedures do path searching +based either on those default paths, or on paths given by the user +in environment variables. +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.516] more_name +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +else begin str_room(1); append_char(c); {contribute |c| to the current string} + if (c=">")or(c=":") then + begin area_delimiter:=cur_length; ext_delimiter:=0; + end + else if (c=".")and(ext_delimiter=0) then ext_delimiter:=cur_length; +@y +else begin str_room(1); append_char(c); {contribute |c| to the current string} + if (c="/") then + begin area_delimiter:=cur_length; ext_delimiter:=0; + end + else if c="." then ext_delimiter:=cur_length; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.519] In pack_file_name, leave room for the extra null we append at +% the end of a filename in make_c_string. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if k<=file_name_size then name_length:=k@+else name_length:=file_name_size; +@y +if k<file_name_size then name_length:=k@+else name_length:=file_name_size-1; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.520] The default format. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d format_default_length=20 {length of the |TEX_format_default| string} +@d format_area_length=11 {length of its area part} +@d format_ext_length=4 {length of its `\.{.fmt}' part} +@y +Under {\mc UNIX} we don't give the area part, instead depending +on the path searching that will happen during file opening. Also, the +length will be set in the main program. + +@d format_area_length=0 {length of its area part} +@d format_ext_length=4 {length of its `\.{.fmt}' part} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.521] Where `plain.fmt' is. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!TEX_format_default:packed array[1..format_default_length] of char; + +@ @<Set init...@>= +TEX_format_default:='TeXformats:plain.fmt'; +@y +@!format_default_length: integer; +@!TEX_format_default: c_char_pointer; + +@ We set the name of the default format file and the length of that name +in C, instead of Pascal, since we want them to depend on the name of the +program. +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.523] Change to pack_buffered_name as with pack_file_name. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if k<=file_name_size then name_length:=k@+else name_length:=file_name_size; +@y +if k<file_name_size then name_length:=k@+else name_length:=file_name_size-1; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.524] Format file opening: only try once, with path searching. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + pack_buffered_name(0,loc,j-1); {try first without the system file area} + if w_open_in(fmt_file) then goto found; + pack_buffered_name(format_area_length,loc,j-1); + {now try the system format file area} + if w_open_in(fmt_file) then goto found; +@y + pack_buffered_name(0,loc,j-1); + if w_open_in(fmt_file) then goto found; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (still [29.524]) replace `PLAIN' in error messages with `default'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.'); +@y + wterm_ln('Sorry, I can''t find that format;',' will try the default.'); +@z +@x + wterm_ln('I can''t find the PLAIN format file!'); +@.I can't find PLAIN...@> +@y + wterm_ln('I can''t find the default format file!'); +@.I can't find default format...@> +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.532] `logname' is declared in <unistd.h> on some systems. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +ship out a box of stuff, we shall use the macro |ensure_dvi_open|. +@y +ship out a box of stuff, we shall use the macro |ensure_dvi_open|. + +@d log_name == texmf_log_name +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.536] Adjust for C string conventions. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!months:packed array [1..36] of char; {abbreviations of month names} +@y +@!months:c_char_pointer; +@z + +@x +begin wlog(banner); +slow_print(format_ident); print(" "); +print_int(day); print_char(" "); +months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'; +@y +begin wlog (banner); +wlog (version_string); +slow_print(format_ident); print(" "); +print_int(day); print_char(" "); +months := ' JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.537] Use a path when calling a_open_in to do a \input; also, try +% to open the file with and without the `.tex' extension, regardless of +% whether the file already has an extension. This allows filenames like +% `foo' and `foo.bar.tex', as well as `foo.tex' and `foo.bar'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if cur_ext="" then cur_ext:=".tex"; +pack_cur_name; +loop@+ begin begin_file_reading; {set up |cur_file| and new level of input} + if a_open_in(cur_file) then goto done; + if cur_area="" then + begin pack_file_name(cur_name,TEX_area,cur_ext); + if a_open_in(cur_file) then goto done; + end; +@y +pack_cur_name; {Try with |".tex"|.} +loop@+begin + begin_file_reading; {set up |cur_file| and new level of input} + {Don't add |".tex"| if it's already there, + if it would overflow |name_of_file|, + or if |"foo"| and |"foo.tex"| are really the same + file, because of operating-system filename length limitations (e.g., + |"afourteenlongf"| and |"afourteenlongf.tex"| under System V).} + if (cur_ext <> ".tex") and (name_length + 5 < file_name_size) + and (not extension_irrelevant_p (name_of_file, 'tex')) + then begin + name_of_file[name_length + 1] := "."; + name_of_file[name_length + 2] := "t"; + name_of_file[name_length + 3] := "e"; + name_of_file[name_length + 4] := "x"; + name_length := name_length + 4; + end; + if a_open_in (cur_file, TEX_INPUT_PATH) then goto done; + + {Try without |".tex"|.} + if cur_ext = ".tex" then cur_ext := ""; + pack_cur_name; + if a_open_in (cur_file, TEX_INPUT_PATH) then goto done; + + {Couldn't find the file. Put |".tex"| back into the filename if we + removed it, and then invoke an external program. If it succeeds, try + opening the file once more.} + if cur_ext = "" then begin + cur_ext := ".tex"; + pack_cur_name; + end; + if make_tex_tex then begin + if a_open_in (cur_file, TEX_INPUT_PATH) then goto done; + end; +@z + +% Knuth should fix this -- sometimes lines go over the |max_print_line|. +% I don't remember what caused this, so I'll comment this out until it +% happens again. +% @x +% if term_offset+length(name)>max_print_line-2 then print_ln +% @y +% if term_offset+length(name)>max_print_line-3 then print_ln +% @z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [29.537] Get rid of return of filename to string pool. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if name=str_ptr-1 then {we can conserve string pool space now} + begin flush_string; name:=cur_name; + end; +@y +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [30.563] Don't use font_area's in TFM opening, and invoke an external +% program if the first open fails. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +file_opened:=false; +if aire="" then pack_file_name(nom,TEX_font_area,".tfm") +else pack_file_name(nom,aire,".tfm"); +if not b_open_in(tfm_file) then abort; +file_opened:=true +@y +file_opened := false; +pack_file_name (nom, aire, ".tfm"); +if not b_open_in(tfm_file) then begin + if make_tex_tfm then begin + if not b_open_in(tfm_file) then abort; + end else + abort; +end; +file_opened:=true +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [30.564] Reading the tfm file. As a special case, whenever we open a +% tfm file, we read its first byte into `tfm_temp' right away. TeX +% looks at `fbyte' before calling `fget', so it ends up seeing every +% byte. This is Pascal-like I/O. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d fget==get(tfm_file) +@d fbyte==tfm_file^ +@y +@d fget==tfm_temp:=getc(tfm_file) +@d fbyte==tfm_temp +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [32.597] We only want `eof' on the TFM file to be true if we +% previously had EOF, not if we're at EOF now. This is like `feof', and +% unlike our implementation of `eof' elsewhere. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if eof(tfm_file) then abort; +@y +if feof(tfm_file) then abort; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [32.597] write_dvi +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@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 +In C, we use a macro to call |fwrite| or |write| directly, writing all +the bytes to be written in one shot. Much better even than writing four +bytes at a time. +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [38.859] Fix a casting/expression evaluation problem. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if abs(fit_class-fitness(r))>1 then d:=d+adj_demerits; +@y +if abs(toint(fit_class)-toint(fitness(r)))>1 then d:=d+adj_demerits; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [39.875] Another casting problem. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +repeat if type(r)<>delta_node then + begin line_diff:=line_number(r)-best_line; +@y +repeat if type(r)<>delta_node then + begin line_diff:=toint(line_number(r))-toint(best_line); +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [42.920,921,923,924] Allow larger hyphenation tries. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +Comparatively few different number sequences $n_0\ldots n_k$ actually occur, +since most of the |n|'s are generally zero. Therefore the number sequences +are encoded in such a way that |trie_op|$(z_k)$ is only one byte long. +If |trie_op(@t$z_k$@>)<>min_quarterword|, when $p_1\ldots p_k$ has matched +the letters in |hc[(l-k+1)..l@,]| of language |t|, +we perform all of the required operations +for this pattern by carrying out the following little program: Set +|v:=trie_op(@t$z_k$@>)|. Then set |v:=v+op_start[t]|, +|hyf[l-hyf_distance[v]]:=@tmax@>(hyf[l-hyf_distance[v]], hyf_num[v])|, +and |v:=hyf_next[v]|; repeat, if necessary, until |v=min_quarterword|. +@y +The theory that comparatively few different number sequences $n_0\ldots n_k$ +actually occur, since most of the |n|'s are generally zero, seems to fail +at least for the large German hyphenation patterns. +Therefore the number sequences cannot any longer be encoded in such a way +that |trie_op|$(z_k)$ is only one byte long. +We have introduced a new constant |max_trie_op| for the maximum allowable +hyphenation operation code value; |max_trie_op| might be different for +\TeX\ and \.{INITEX} and must not exceed |max_halfword|. +An opcode will occupy a halfword if |max_trie_op| exceeds |max_quarterword| +or a quarterword otherwise. +@^system dependencies@> +If |trie_op(@t$z_k$@>)<>min_trie_op|, when $p_1\ldots p_k$ has matched +the letters in |hc[(l-k+1)..l@,]| of language |t|, +we perform all of the required operations +for this pattern by carrying out the following little program: Set +|v:=trie_op(@t$z_k$@>)|. Then set |v:=v+op_start[t]|, +|hyf[l-hyf_distance[v]]:=@tmax@>(hyf[l-hyf_distance[v]], hyf_num[v])|, +and |v:=hyf_next[v]|; repeat, if necessary, until |v=min_trie_op|. +@z +@x +@!trie_pointer=0..trie_size; {an index into |trie|} +@y +@!trie_opcode=min_trie_op..max_trie_op; {a trie opcode} +@!trie_pointer=0..trie_size; {an index into |trie|} +@z +@x +@ @d trie_link(#)==trie[#].rh {``downward'' link in a trie} +@d trie_char(#)==trie[#].b1 {character matched at this trie location} +@d trie_op(#)==trie[#].b0 {program for hyphenation at this trie location} +@y +@ For more than 255 trie op codes, the three fields |trie_link|, |trie_char|, +and |trie_op| will no longer fit into one memory word; thus using web2c +we define |trie| as three array instead of an array of records. +The variant will be implented by reusing the opcode field later on with +another macro. +@d trie_link(#)==trie_trl[#] {``downward'' link in a trie} +@d trie_char(#)==trie_trc[#] {character matched at this trie location} +@d trie_op(#)==trie_tro[#] {program for hyphenation at this trie location} +@z +@x +@!trie:array[trie_pointer] of two_halves; {|trie_link|, |trie_char|, |trie_op|} +@y +@!trie_trl:array[trie_pointer] of halfword; {|trie_link|} +@!trie_tro:array[trie_pointer] of halfword; {|trie_op| and |trie_link|} +@!trie_trc:array[trie_pointer] of quarterword; {|trie_char|} +@z +@x +@!hyf_next:array[1..trie_op_size] of quarterword; {continuation code} +@y +@!hyf_next:array[1..trie_op_size] of trie_opcode; {continuation code} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [43.943] Larger tries, also in documentation parts. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +|hyf_next[@t$v^\prime$@>]=min_quarterword|. +@y +|hyf_next[@t$v^\prime$@>]=min_trie_op|. +@z +@x +$$\hbox{|@t$v^\prime$@>:=new_trie_op(0,1,min_quarterword)|,\qquad +@y +$$\hbox{|@t$v^\prime$@>:=new_trie_op(0,1,min_trie_op)|,\qquad +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [43.943] web2c can't parse negative lower bounds in arrays. Sorry. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!init@! trie_op_hash:array[-trie_op_size..trie_op_size] of 0..trie_op_size; +@y +@!init@! trie_op_hash:array[neg_trie_op_size..trie_op_size] of 0..trie_op_size; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [43.943,944] Larger hyphenation tries. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!trie_used:array[ASCII_code] of quarterword; +@y +@!trie_used:array[ASCII_code] of trie_opcode; +@z +@x +@!trie_op_val:array[1..trie_op_size] of quarterword; +@y +@!trie_op_val:array[1..trie_op_size] of trie_opcode; +@z +@x +tini +@y +tini@; +@!max_op_used:trie_opcode; {largest opcode used for any language} +@!small_op:boolean; {flag used while dumping or undumping} +@z +@x +|new_trie_op| could return |min_quarterword| (thereby simply ignoring +@y +|new_trie_op| could return |min_trie_op| (thereby simply ignoring +@z +@x +function new_trie_op(@!d,@!n:small_number;@!v:quarterword):quarterword; +label exit; +var h:-trie_op_size..trie_op_size; {trial hash location} +@!u:quarterword; {trial op code} +@y +function new_trie_op(@!d,@!n:small_number;@!v:trie_opcode):trie_opcode; +label exit; +var h:neg_trie_op_size..trie_op_size; {trial hash location} +@!u:trie_opcode; {trial op code} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [43.944] Another casting problem, and use |neg_trie_op_size|. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +begin h:=abs(n+313*d+361*v+1009*cur_lang) mod (trie_op_size+trie_op_size) + - trie_op_size; +@y +begin h:=abs(toint(n)+313*toint(d)+361*toint(v)+1009*toint(cur_lang)) + mod (trie_op_size - neg_trie_op_size) + + neg_trie_op_size; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [43.944,945,946] And larger tries again. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + if u=max_quarterword then + overflow("pattern memory ops per language", + max_quarterword-min_quarterword); + incr(trie_op_ptr); incr(u); trie_used[cur_lang]:=u; +@y + if u=max_trie_op then + overflow("pattern memory ops per language", + max_trie_op-min_trie_op); + incr(trie_op_ptr); incr(u); trie_used[cur_lang]:=u; + if u>max_op_used then max_op_used:=u; +@z +@x +op_start[0]:=-min_quarterword; +@y +op_start[0]:=-min_trie_op; +@z +@x +for k:=0 to 255 do trie_used[k]:=min_quarterword; +@y +for k:=0 to 255 do trie_used[k]:=min_trie_op; +@z +@x +trie_op_ptr:=0; +@y +max_op_used:=min_trie_op; +trie_op_ptr:=0; +@z +@x +@t\hskip10pt@>@!trie_o:packed array[trie_pointer] of quarterword; +@y +@t\hskip10pt@>@!trie_o:packed array[trie_pointer] of trie_opcode; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [43.947] A casting problem. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +begin h:=abs(trie_c[p]+1009*trie_o[p]+@| + 2718*trie_l[p]+3142*trie_r[p]) mod trie_size; +@y +begin h:=abs(toint(trie_c[p])+1009*toint(trie_o[p])+@| + 2718*toint(trie_l[p])+3142*toint(trie_r[p])) mod trie_size; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [43.950,958,960,963] Larger tries. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@d trie_back(#)==trie[#].lh {backward links in |trie| holes} +@y +@d trie_back(#)==trie_tro[#] {use the opcode field now for backward links} +@z +@x +@<Move the data into |trie|@>= +h.rh:=0; h.b0:=min_quarterword; h.b1:=min_quarterword; {|trie_link:=0|, + |trie_op:=min_quarterword|, |trie_char:=qi(0)|} +if trie_root=0 then {no patterns were given} + begin for r:=0 to 256 do trie[r]:=h; +@y +@d clear_trie == {clear |trie[r]|} + begin trie_link(r):=0; + trie_op(r):=min_trie_op; + trie_char(r):=min_quarterword; {|trie_char:=qi(0)|} + end +@<Move the data into |trie|@>= +if trie_root=0 then {no patterns were given} + begin for r:=0 to 256 do clear_trie; +@z +@x + repeat s:=trie_link(r); trie[r]:=h; r:=s; +@y + repeat s:=trie_link(r); clear_trie; r:=s; +@z +@x + @!h:two_halves; {template used to zero out |trie|'s holes} +@y +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [49.1275] Same stuff as for \input, this time for \openin. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + if cur_ext="" then cur_ext:=".tex"; + pack_cur_name; + if a_open_in(read_file[n]) then read_open[n]:=just_open; +@y + pack_cur_name; {Try with |".tex"|.} + if (cur_ext <> ".tex") and (name_length + 5 < file_name_size) + and (not extension_irrelevant_p (name_of_file, 'tex')) + then begin + name_of_file[name_length + 1] := "."; + name_of_file[name_length + 2] := "t"; + name_of_file[name_length + 3] := "e"; + name_of_file[name_length + 4] := "x"; + name_length := name_length + 4; + end; + if a_open_in (read_file[n], TEX_INPUT_PATH) + then read_open[n] := just_open + else begin + if cur_ext = ".tex" then cur_ext := ""; + pack_cur_name; {Try without |".tex"|.} + if a_open_in (read_file[n], TEX_INPUT_PATH) + then read_open[n] := just_open; + end; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [50.1302] Eliminate now-unused variable `w' in `store_fmt_file'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!x: integer; {something to dump} +@!w: four_quarters; {four ASCII codes} +@y +@!x: integer; {something to dump} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [50.1303] Ditto, for `load_fmt_file'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@!x: integer; {something undumped} +@!w: four_quarters; {four ASCII codes} +@y +@!x: integer; {something undumped} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [50.??] Do reading and writing of `fmt_file' in C. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@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 +@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 +@z + +@x +x:=fmt_file^.int; +@y +undump_int(x); {This reads the first word of the \.{.fmt} file} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [??] Make dumping/undumping more efficient. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +for k:=0 to str_ptr do dump_int(str_start[k]); +k:=0; +while k+4<pool_ptr do + begin dump_four_ASCII; k:=k+4; + end; +k:=pool_ptr-4; dump_four_ASCII; +@y +dump_things(str_start[0], str_ptr+1); +dump_things(str_pool[0], pool_ptr); +@z + +@x +for k:=0 to str_ptr do undump(0)(pool_ptr)(str_start[k]); +k:=0; +while k+4<pool_ptr do + begin undump_four_ASCII; k:=k+4; + end; +k:=pool_ptr-4; undump_four_ASCII; +@y +undump_things(str_start[0], str_ptr+1); +undump_things(str_pool[0], pool_ptr); +@z + +@x +repeat for k:=p to q+1 do dump_wd(mem[k]); +x:=x+q+2-p; var_used:=var_used+q-p; +p:=q+node_size(q); q:=rlink(q); +until q=rover; +var_used:=var_used+lo_mem_max-p; dyn_used:=mem_end+1-hi_mem_min;@/ +for k:=p to lo_mem_max do dump_wd(mem[k]); +x:=x+lo_mem_max+1-p; +dump_int(hi_mem_min); dump_int(avail); +for k:=hi_mem_min to mem_end do dump_wd(mem[k]); +@y +repeat + dump_things(mem[p], q+2-p); +x:=x+q+2-p; var_used:=var_used+q-p; +p:=q+node_size(q); q:=rlink(q); +until q=rover; +var_used:=var_used+lo_mem_max-p; dyn_used:=mem_end+1-hi_mem_min;@/ +dump_things(mem[p], lo_mem_max+1-p); +x:=x+lo_mem_max+1-p; +dump_int(hi_mem_min); dump_int(avail); +dump_things(mem[hi_mem_min], mem_end+1-hi_mem_min); +@z + +@x +repeat for k:=p to q+1 do undump_wd(mem[k]); +p:=q+node_size(q); +if (p>lo_mem_max)or((q>=rlink(q))and(rlink(q)<>rover)) then goto bad_fmt; +q:=rlink(q); +until q=rover; +for k:=p to lo_mem_max do undump_wd(mem[k]); +@y +repeat + undump_things(mem[p], q+2-p); +p:=q+node_size(q); +if (p>lo_mem_max)or((q>=rlink(q))and(rlink(q)<>rover)) then goto bad_fmt; +q:=rlink(q); +until q=rover; +undump_things(mem[p], lo_mem_max+1-p); +@z + +@x +for k:=hi_mem_min to mem_end do undump_wd(mem[k]); +@y +undump_things(mem[hi_mem_min], mem_end+1-hi_mem_min); +@z + +@x +while k<l do + begin dump_wd(eqtb[k]); incr(k); + end; +@y +dump_things(eqtb[k], l-k); +@z + +@x +while k<l do + begin dump_wd(eqtb[k]); incr(k); + end; +@y +dump_things(eqtb[k], l-k); +@z + +@x +for j:=k to k+x-1 do undump_wd(eqtb[j]); +@y +undump_things(eqtb[k], x); +@z + +@x +for p:=hash_used+1 to undefined_control_sequence-1 do dump_hh(hash[p]); +@y +dump_things(hash[hash_used+1], undefined_control_sequence-1-hash_used); +@z + +@x +for p:=hash_used+1 to undefined_control_sequence-1 do undump_hh(hash[p]); +@y +undump_things(hash[hash_used+1], undefined_control_sequence-1-hash_used); +@z + +@x +for k:=0 to fmem_ptr-1 do dump_wd(font_info[k]); +dump_int(font_ptr); +for k:=null_font to font_ptr do + @<Dump the array info for internal font number |k|@>; +@y +@<Dump the array info for internal font number |k|@>; +@z + +@x +for k:=0 to fmem_ptr-1 do undump_wd(font_info[k]); +undump_size(font_base)(font_max)('font max')(font_ptr); +for k:=null_font to font_ptr do + @<Undump the array info for internal font number |k|@> +@y +@<Undump the array info for internal font number |k|@>; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [50.1322] Writing font info (almost at end of dump stuff). +% Knuth's code writes all the information relevant to a single font +% in the same section of the fmt file. But it's a lot faster to +% write the arrays of information out, one whole array at a time. +% So that's the way we handle dumping and undumping font info. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ @<Dump the array info for internal font number |k|@>= +begin dump_qqqq(font_check[k]); +dump_int(font_size[k]); +dump_int(font_dsize[k]); +dump_int(font_params[k]);@/ +dump_int(hyphen_char[k]); +dump_int(skew_char[k]);@/ +dump_int(font_name[k]); +dump_int(font_area[k]);@/ +dump_int(font_bc[k]); +dump_int(font_ec[k]);@/ +dump_int(char_base[k]); +dump_int(width_base[k]); +dump_int(height_base[k]);@/ +dump_int(depth_base[k]); +dump_int(italic_base[k]); +dump_int(lig_kern_base[k]);@/ +dump_int(kern_base[k]); +dump_int(exten_base[k]); +dump_int(param_base[k]);@/ +dump_int(font_glue[k]);@/ +dump_int(bchar_label[k]); +dump_int(font_bchar[k]); +dump_int(font_false_bchar[k]);@/ +print_nl("\font"); print_esc(font_id_text(k)); print_char("="); +print_file_name(font_name[k],font_area[k],""); +if font_size[k]<>font_dsize[k] then + begin print(" at "); print_scaled(font_size[k]); print("pt"); + end; +end +@y +@ @<Dump the array info for internal font number |k|@>= +begin dump_things(font_info[0], fmem_ptr); +dump_int(font_ptr); +dump_things(font_check[null_font], font_ptr+1-null_font); +dump_things(font_size[null_font], font_ptr+1-null_font); +dump_things(font_dsize[null_font], font_ptr+1-null_font); +dump_things(font_params[null_font], font_ptr+1-null_font); +dump_things(hyphen_char[null_font], font_ptr+1-null_font); +dump_things(skew_char[null_font], font_ptr+1-null_font); +dump_things(font_name[null_font], font_ptr+1-null_font); +dump_things(font_area[null_font], font_ptr+1-null_font); +dump_things(font_bc[null_font], font_ptr+1-null_font); +dump_things(font_ec[null_font], font_ptr+1-null_font); +dump_things(char_base[null_font], font_ptr+1-null_font); +dump_things(width_base[null_font], font_ptr+1-null_font); +dump_things(height_base[null_font], font_ptr+1-null_font); +dump_things(depth_base[null_font], font_ptr+1-null_font); +dump_things(italic_base[null_font], font_ptr+1-null_font); +dump_things(lig_kern_base[null_font], font_ptr+1-null_font); +dump_things(kern_base[null_font], font_ptr+1-null_font); +dump_things(exten_base[null_font], font_ptr+1-null_font); +dump_things(param_base[null_font], font_ptr+1-null_font); +dump_things(font_glue[null_font], font_ptr+1-null_font); +dump_things(bchar_label[null_font], font_ptr+1-null_font); +dump_things(font_bchar[null_font], font_ptr+1-null_font); +dump_things(font_false_bchar[null_font], font_ptr+1-null_font); +for k:=null_font to font_ptr do begin + print_nl("\font"); print_esc(font_id_text(k)); print_char("="); + print_file_name(font_name[k],font_area[k],""); + if font_size[k]<>font_dsize[k] then begin + print(" at "); print_scaled(font_size[k]); print("pt"); + end; +end; +end +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [50.1322] Reading font info for C (nearly done with undump stuff). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@ @<Undump the array info for internal font number |k|@>= +begin undump_qqqq(font_check[k]);@/ +undump_int(font_size[k]); +undump_int(font_dsize[k]); +undump(min_halfword)(max_halfword)(font_params[k]);@/ +undump_int(hyphen_char[k]); +undump_int(skew_char[k]);@/ +undump(0)(str_ptr)(font_name[k]); +undump(0)(str_ptr)(font_area[k]);@/ +undump(0)(255)(font_bc[k]); +undump(0)(255)(font_ec[k]);@/ +undump_int(char_base[k]); +undump_int(width_base[k]); +undump_int(height_base[k]);@/ +undump_int(depth_base[k]); +undump_int(italic_base[k]); +undump_int(lig_kern_base[k]);@/ +undump_int(kern_base[k]); +undump_int(exten_base[k]); +undump_int(param_base[k]);@/ +undump(min_halfword)(lo_mem_max)(font_glue[k]);@/ +undump(0)(font_mem_size)(bchar_label[k]); +undump(min_quarterword)(non_char)(font_bchar[k]); +undump(min_quarterword)(non_char)(font_false_bchar[k]); +end +@y +@ The way this is done in C makes the reference to +the internal font number meaningless, but putting the code +here preserves the association with the WEB modules. + +@<Undump the array info for internal font number |k|@>= +begin undump_things(font_info[0], fmem_ptr); +undump_size(font_base)(font_max)('font max')(font_ptr); +undump_things(font_check[null_font], font_ptr+1-null_font); +undump_things(font_size[null_font], font_ptr+1-null_font); +undump_things(font_dsize[null_font], font_ptr+1-null_font); +undump_things(font_params[null_font], font_ptr+1-null_font); +undump_things(hyphen_char[null_font], font_ptr+1-null_font); +undump_things(skew_char[null_font], font_ptr+1-null_font); +undump_things(font_name[null_font], font_ptr+1-null_font); +undump_things(font_area[null_font], font_ptr+1-null_font); +undump_things(font_bc[null_font], font_ptr+1-null_font); +undump_things(font_ec[null_font], font_ptr+1-null_font); +undump_things(char_base[null_font], font_ptr+1-null_font); +undump_things(width_base[null_font], font_ptr+1-null_font); +undump_things(height_base[null_font], font_ptr+1-null_font); +undump_things(depth_base[null_font], font_ptr+1-null_font); +undump_things(italic_base[null_font], font_ptr+1-null_font); +undump_things(lig_kern_base[null_font], font_ptr+1-null_font); +undump_things(kern_base[null_font], font_ptr+1-null_font); +undump_things(exten_base[null_font], font_ptr+1-null_font); +undump_things(param_base[null_font], font_ptr+1-null_font); +undump_things(font_glue[null_font], font_ptr+1-null_font); +undump_things(bchar_label[null_font], font_ptr+1-null_font); +undump_things(font_bchar[null_font], font_ptr+1-null_font); +undump_things(font_false_bchar[null_font], font_ptr+1-null_font); +end +@z + +% The hyphenation patterns. +% +@x +for k:=0 to trie_max do dump_hh(trie[k]); +dump_int(trie_op_ptr); +for k:=1 to trie_op_ptr do + begin dump_int(hyf_distance[k]); + dump_int(hyf_num[k]); + dump_int(hyf_next[k]); + end; +@y +dump_things(trie_trl[0], trie_max+1); +dump_things(trie_tro[0], trie_max+1); +dump_things(trie_trc[0], trie_max+1); +dump_int(trie_op_ptr); +dump_things(hyf_distance[1], trie_op_ptr); +dump_things(hyf_num[1], trie_op_ptr); +dump_things(hyf_next[1], trie_op_ptr); +@z + +@x +for k:=0 to j do undump_hh(trie[k]); +undump_size(0)(trie_op_size)('trie op size')(j); @+init trie_op_ptr:=j;@+tini +for k:=1 to j do + begin undump(0)(63)(hyf_distance[k]); {a |small_number|} + undump(0)(63)(hyf_num[k]); + undump(min_quarterword)(max_quarterword)(hyf_next[k]); + end; +@y +undump_things(trie_trl[0], j+1); +undump_things(trie_tro[0], j+1); +undump_things(trie_trc[0], j+1); +undump_size(0)(trie_op_size)('trie op size')(j); @+init trie_op_ptr:=j;@+tini +undump_things(hyf_distance[1], j); +undump_things(hyf_num[1], j); +undump_things(hyf_next[1], j); +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [50.1327] As with TFM files, `eof' here means `have we previously +% encountered the end-of-file', not `are we at the end of the file'. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +if (x<>69069)or eof(fmt_file) then goto bad_fmt +@y +if (x<>69069)or feof(fmt_file) then goto bad_fmt +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [50.1328] Eliminate possibly wrong word `preloaded' from format_idents. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +print(" (preloaded format="); print(job_name); print_char(" "); +@y +print(" (format="); print(job_name); print_char(" "); +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [51.1332] `uexit' argument depends on `history'; add call to +% set_paths; make the main program a procedure, so that uses of `eqtb' +% will work. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +@p begin @!{|start_here|} +@y +@p procedure tex_body; +begin @!{|start_here|} +@z + +@x +t_open_out; {open the terminal for output} +@y +t_open_out; {open the terminal for output} +{get default file paths from the environment} +set_paths (TEX_FORMAT_PATH_BIT + TEX_INPUT_PATH_BIT + TEX_POOL_PATH_BIT + + TFM_FILE_PATH_BIT); +@z + +@x +end_of_TEX: close_files_and_terminate; +final_end: ready_already:=0; +end. +@y +close_files_and_terminate; +final_end: do_final_end; +end {|tex_body|}; +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [51.1333] Print new line before termination; switch to editor if +% necessary. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + slow_print(log_name); print_char("."); + end; + end; +@y + slow_print(log_name); print_char("."); + end; + end; +print_ln; +if (edit_name_start<>0) and (interaction>batch_mode) then + call_edit(str_pool,edit_name_start,edit_name_length,edit_line); +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [52.1338] Core-dump in debugging mode on 0 input. Under Unix, it's +% not possible to switch into the debugger while a program is running. +% The best approximation is to do a core dump, then run the debugger on +% it later. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x + begin goto breakpoint;@\ {go to every label at least once} + breakpoint: m:=0; @{'BREAKPOINT'@}@\ + end +@y + dump_core {Do something to cause a core dump} +@z + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% [54.1376] Add editor-switch variables to globals. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@x +This section should be replaced, if necessary, by any special +modifications of 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. +@^system dependencies@> +@y +Here is a temporary integer, used as a holder during reading and writing of +TFM files, and a temporary memory_word, used in reading/writing format +files. +Also, the variables used to hold ``switch-to-editor'' information. +@^<system dependencies@> + +@<Glob...@>= +@!edit_name_start: pool_pointer; +@!edit_name_length,@!edit_line,@!tfm_temp: integer; + +@ The |edit_name_start| will be set to point into |str_pool| somewhere after +its beginning if \TeX\ is supposed to switch to an editor on exit. + +@<Set init...@>= +edit_name_start:=0; +@z |