%%%  WEB Change File for TeX (Win32 version)
%%%  Time-stamp: "97/08/03 22:18:47 mik"
%%%
%%%  Copyright (C) 1991, 92, 93, 94, 95, 96, 97
%%%	Christian Schenk  <cschenk@berlin.snafu.de>
%%%
%%%  This file is part of MiKTeX.
%%%
%%%  MiKTeX is free software; you can redistribute it and/or
%%%  modify it under the terms of the GNU General Public License as
%%%  published by the Free Software Foundation; either version 2, or (at
%%%  your option) any later version.
%%%  
%%%  MiKTeX is distributed in the hope that it will be useful, but
%%%  WITHOUT ANY WARRANTY; without even the implied warranty of
%%%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
%%%  General Public License for more details.
%%%  
%%%  You should have received a copy of the GNU General Public License
%%%  along with MiKTeX; if not, write to the Free Software
%%%  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
%%%  USA.

@x
\def\title{\TeX82}
@y
\def\MiKTeX{MiK\TeX}
\def\title{\TeX82 for Win32 (\MiKTeX\ 1.08)}
@z

@x
  \def\?##1]{\hbox to 1in{\hfil##1.\ }}
  }
@y
  \def\?##1]{\hbox to 1in{\hfil##1.\ }}
  }
\let\maybe=\iffalse
@z

%% **     4  ******************************************************************

@x
procedure initialize; {this procedure gets things started properly}
  var @<Local variables for initialization@>@/
  begin @<Initialize whatever \TeX\ might access@>@;
  end;@#
@t\4@>@<Basic printing procedures@>@/
@t\4@>@<Error handling procedures@>@/
@y
@t\4@>@<External C routines@>@/
@#
procedure initialize; {this procedure gets things started properly}
  var @<Local variables for initialization@>@/
  begin @<Initialize whatever \TeX\ might access@>@;
  end;@#
@t\4@>@<Basic printing procedures@>@/
@t\4@>@<Error handling procedures@>@/
@z

%% **     6  ******************************************************************

@x
@d start_of_TEX=1 {go here when \TeX's variables are initialized}
@d end_of_TEX=9998 {go here to close files and terminate gracefully}
@d final_end=9999 {this label marks the ending of the program}
@y
@d start_of_TEX=1 {go here when \TeX's variables are initialized}
@d end_of_TEX=9998 {go here to close files and terminate gracefully}
@d final_end=9999 {this label marks the ending of the program}
@d goto_fin_end==c4p_longjmp(fin_buf,1)
@d goto_eof_TEX==c4p_longjmp(eo_TEX_buf,1)
@z

%% **     7  ******************************************************************

@x stat
@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 stat
@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}
@z stat

%% **     8  ******************************************************************

@x init
@d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
@d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
@y init
@d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
@d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
@z init

%% **    11  ******************************************************************

@x mem_max
@!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|}
@y mem_max
@!mem_max=1048576; {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|}
@z mem_max

@x mem_min
@!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|}
@y mem_min
@!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|}
@z mem_min

@x trip ignore buf_size
@!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|}
@y buf_size
@!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|}
@z buf_size

@x error_line
@!error_line=72; {width of context lines on terminal error messages}
@y error_line
@!error_line=72; {width of context lines on terminal error messages}
@z error_line

@x half_error_line
@!half_error_line=42; {width of first lines of contexts in terminal
  error messages; should be between 30 and |error_line-15|}
@y half_error_line
@!half_error_line=42; {width of first lines of contexts in terminal
  error messages; should be between 30 and |error_line-15|}
@z half_error_line

@x max_print_line
@!max_print_line=79; {width of longest text lines output; should be at least 60}
@y max_print_line
@!max_print_line=79; {width of longest text lines output; should be at least 60}
@z max_print_line

@x trip ignore stack_size
@!stack_size=200; {maximum number of simultaneous input sources}
@y stack_size
@!stack_size= 300; {maximum number of simultaneous input sources}
@z stack_size

@x trip ignore max_in_open
@!max_in_open=6; {maximum number of input files and error insertions that
  can be going on simultaneously}
@y max_in_open
@!max_in_open=20; {maximum number of input files and error insertions that
  can be going on simultaneously}
@z max_in_open

@x trip ignore font_max
@!font_max=75; {maximum internal font number; must not exceed |max_quarterword|
  and must be at most |font_base+256|}
@y font_max
@!font_max=256; {maximum internal font number; must not exceed |max_quarterword|
  and must be at most |font_base+256|}
@z font_max

@x trip ignore font_mem_size
@!font_mem_size=20000; {number of words of |font_info| for all fonts}
@y font_mem_size
@!font_mem_size=131068; {number of words of |font_info| for all fonts}
@z font_mem_size

@x trip ignore param_size
@!param_size=60; {maximum number of simultaneous macro parameters}
@y param_size
@!param_size=500; {maximum number of simultaneous macro parameters}
@z param_size

@x trip ignore max_strings
@!max_strings=3000; {maximum number of strings; must not exceed |max_halfword|}
@y max_strings
@!max_strings=20000; {maximum number of strings; must not exceed |max_halfword|}
@z max_strings

@x trip ignore string_vacancies
@!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}
@y string_vacancies
@!string_vacancies=96000; {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}
@z string_vacancies

@x trip ignore pool_size
@!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}
@y pool_size
@!pool_size=120000; {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}
@z pool_size

@x trip ignore save_size
@!save_size=600; {space for saving values outside of current group; must be
  at most |max_halfword|}
@y save_size
@!save_size= 32768; {space for saving values outside of current group; must be
  at most |max_halfword|}
@z save_size

@x trip ignore trie_size
@!trie_size=8000; {space for hyphenation patterns; should be larger for
  \.{INITEX} than it is in production versions of \TeX}
@y trie_size
@!trie_size=60000; {space for hyphenation patterns; should be larger for
  \.{INITEX} than it is in production versions of \TeX}
@z trie_size

@x trip ignore trie_op_size
@!trie_op_size=500; {space for ``opcodes'' in the hyphenation patterns}
@y trie_op_size
@!trie_op_size=2048; {space for ``opcodes'' in the hyphenation patterns}
@z trie_op_size

@x trip ignore dvi_buf_size
@!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8}
@y dvi_buf_size
@!dvi_buf_size=8192; {size of the output buffer; must be a multiple of 8}
@z dvi_buf_size

@x file_name_size
@!file_name_size=40; {file names shouldn't be longer than this}
@y file_name_size
@!file_name_size=260; {file names shouldn't be longer than this}
@!fil_name_size=261;
@z file_name_size

@x
@!pool_name='TeXformats:TEX.POOL                     ';
  {string of length |file_name_size|; tells where the string pool appears}
@.TeXformats@>
@y
@!pool_name='[TeX]Format Dirs:tex.pool';
  {name of the pool file; tells where the string pool appears}
@z

%% **    12  ******************************************************************

@x
@ Like the preceding parameters, the following quantities can be changed
at compile time to extend or reduce \TeX's capacity. But if they are changed,
it is necessary to rerun the initialization program \.{INITEX}
@.INITEX@>
to generate new tables for the production \TeX\ program.
One can't simply make helter-skelter changes to the following constants,
since certain rather complex initialization
numbers are computed from them. They are defined here using
\.{WEB} macros, instead of being put into \PASCAL's |const| list, in order to
emphasize this distinction.
@y
@ Like the preceding parameters, the following quantities can be changed
at compile time to extend or reduce \TeX's capacity. But if they are changed,
it is necessary to rerun the initialization program \.{INITEX}
@.INITEX@>
to generate new tables for the production \TeX\ program.
One can't simply make helter-skelter changes to the following constants,
since certain rather complex initialization
numbers are computed from them. They are defined here using
\.{WEB} macros, instead of being put into \PASCAL's |const| list, in order to
emphasize this distinction.
@z

@x mem_bot
@d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX};
  must not be less than |mem_min|}
@y mem_bot
@d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX};
  must not be less than |mem_min|}
@z mem_bot

@x mem_top
@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|}
@y mem_top
@d mem_top==1048576 {largest index in the |mem| array dumped by \.{INITEX};
  must be substantially larger than |mem_bot|
  and not greater than |mem_max|}
@z mem_top

@x
@d font_base=0 {smallest internal font number; must not be less
  than |min_quarterword|}
@y
@d font_base=0 {smallest internal font number; must not be less
  than |min_quarterword|}
@z

@x trip ignore hash_size
@d hash_size=2100 {maximum number of control sequences; it should be at most
  about |(mem_max-mem_min)/10|}
@y hash_size
@d hash_size=20000 {maximum number of control sequences; it should be at most
  about |(mem_max-mem_min)/10|}
@z hash_size

@x trip ignore hash_prime
@d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
@y hash_prime
@d hash_prime=16993 {a prime number equal to about 85\pct! of |hash_size|}
@z hash_prime

@x trip ignore hyph_size
@d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions}
@y hyph_size
@d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions}
@z hyph_size

%% **    16  ******************************************************************

%@x
%@d incr(#) == #:=#+1 {increase a variable by unity}
%@d decr(#) == #:=#-1 {decrease a variable by unity}
%@y
%@d incr(#) == c4p_incr (#) {increase a variable by unity}
%@d decr(#) == c4p_decr (#) {decrease a variable by unity}
%@z

%% **    19  ******************************************************************

@x
@d text_char == char {the data type of characters in text files}
@d first_text_char=0 {ordinal number of the smallest element of |text_char|}
@d last_text_char=255 {ordinal number of the largest element of |text_char|}
@y
@d text_char == char {the data type of characters in text files}
@d first_text_char=-128 {ordinal number of the smallest element of |text_char|}
@d last_text_char=127 {ordinal number of the largest element of |text_char|}
@^signed characters@>
@d tabulator=9
@d form_feed=12
@z

%% **    23  ******************************************************************

@x
To get the most ``permissive'' character set, change |' '| on the
right of these assignment statements to |chr(i)|.
@^character set dependencies@>
@^system dependencies@>

@<Set init...@>=
for i:=0 to @'37 do xchr[i]:=' ';
for i:=@'177 to @'377 do xchr[i]:=' ';
@y
@^character set dependencies@>
@^system dependencies@>

@<Set init...@>=
for i:=0 to @'37 do xchr[i]:=chr(i);
for i:=@'177 to @'377 do xchr[i]:=chr(i);
@z

%% **    26  ******************************************************************

@x
@!name_of_file:packed array[1..file_name_size] of char;@;@/
  {on some systems this may be a \&{record} variable}
@!name_length:0..file_name_size;@/{this many characters are actually
  relevant in |name_of_file| (the rest are blank)}
@y
@!name_of_file:packed array[1..fil_name_size] of char;@;@/
  {on some systems this may be a \&{record} variable}
@!name_length:0..file_name_size;@/{this many characters are actually
  relevant in |name_of_file|}
@z

%% **    27  ******************************************************************

@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;

@ 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
@ We can use the routine |@!c4p_try_fopen()| for file opening:
$$\vbox{\halign{#\hfil\qquad&#\hfil\cr
|c4p_try_fopen(f,@t\\{name}@>,@!c4p_r_mode);|&input;\cr
|c4p_try_fopen(f,@t\\{name}@>,@!c4p_w_mode);|&output;\cr
|c4p_try_fopen(f,@t\\{name}@>,@!c4p_rb_mode);|&binary input;\cr
|c4p_try_fopen(f,@t\\{name}@>,@!c4p_wb_mode);|&binary 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. It must
be zero terminated.
@^system dependencies@>

\TeX's file-opening procedures return |false| if no file identified by
|name_of_file| could be opened.

@d a_open_out(#)==c4p_try_fopen(#,name_of_file,c4p_w_mode)
  {open a text file for output}
@d b_open_out(#)==c4p_try_fopen(#,name_of_file,c4p_wb_mode)
  {open a byte file for output}
@d w_open_out(#)==c4p_try_fopen(#,name_of_file,c4p_wb_mode)
  {open a word file for output}

@p function a_open_in(var f:alpha_file):boolean;
  {open a text file for input}
begin if not mt_open_input_file(f) then a_open_in:=false
   else begin a_open_in:=true; end;
end;

@ Files can be closed with the routine `|@!c4p_fclose(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.

@d a_close(#)==c4p_fclose(#) {close a text file}
@d b_close(#)==c4p_fclose(#) {close a binary file}
@d w_close(#)==c4p_fclose(#) {close a word file}
@z

%% **    31  ******************************************************************

@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
@p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean;forward;
@z

%% **    33  ******************************************************************

@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 we open the terminal files.
@^system dependencies@>

@d t_open_in==term_in:=i@&nput
@d t_open_out==term_out:=output
@z

%% **    34  ******************************************************************

@x
some instruction to the operating system.  The following macros show how
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
some instruction to the operating system.
@^system dependencies@>

@d update_terminal == break(term_out) {empty the terminal output buffer}
@d clear_terminal == break(term_in) {clear the terminal input buffer}
@d wake_up_terminal == do_nothing {cancel the user's cancellation of output}
@z

%% **    35  ******************************************************************

@x
  begin write_ln(term_out,'Buffer size exceeded!'); goto final_end;
@y
  begin write_ln(term_out,'Buffer size exceeded!'); goto_fin_end;
@z

%% **    37  ******************************************************************

@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;
@y
@ The following program does the required initialization.

@p function init_terminal:boolean; {gets the terminal input started}
label exit;
begin t_open_in;
loop@+begin if (c4p_plen > 0) then
  begin
  cmdln_to_buf
  end else 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;
  end;
  loc:=first;
@z

%% **    49  ******************************************************************

@x
@<Character |k| cannot be printed@>=
  (k<" ")or(k>"~")
@y
@<Character |k| cannot be printed@>=
  not mt_is_print (k)
@z

%% **    51  ******************************************************************

@x
name_of_file:=pool_name; {we needn't set |name_length|}
if a_open_in(pool_file) then
@yi
c4p_strcpy(name_of_file, pool_name); {we needn't set |name_length|}
if mt_open_pool_file(pool_file) then
@z

%% **    61  ******************************************************************

@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);
miktex_banner(term_out);
if format_ident=0 then print_ln {|wterm_ln(' (no format preloaded)')|}
else  begin slow_print(format_ident); print_ln;
  end;
@z

%% **    81  ******************************************************************

@x
`|close_files_and_terminate|;\thinspace' followed by a call on some system
procedure that quietly terminates the program.

@<Error hand...@>=
procedure jump_out;
begin goto end_of_TEX;
end;
@y
`|close_files_and_terminate|;\thinspace' followed by a call on some system
procedure that quietly terminates the program.

@<Error hand...@>=
procedure jump_out;
begin goto_eof_TEX;
end;
@z

%% **   109  ******************************************************************

@x glue_ratio
@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|}
@y glue_ratio
@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|}
@z glue_ratio

@x
@<Types...@>=
@!glue_ratio=real; {one-word representation of a glue expansion factor}
@y
@<Types...@>=
@!glue_ratio=longreal; {one-word representation of a glue expansion factor}
@z

%% **   110  ******************************************************************

@x min_quarterword
@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 min_quarterword
@d min_quarterword=0 {smallest allowable value in a |quarterword|}
@d max_quarterword=1023 {largest allowable value in a |quarterword|}
@d min_halfword==0 {smallest allowable value in a |halfword|}
@d max_halfword==@"3FFFFFFF {largest allowable value in a |halfword|}
@z min_quarterword

%% **   126  ******************************************************************

@x
@ The lower part of |mem| grows by 1000 words at a time, unless
we are very close to going under. When it grows, we simply link
a new node into the available-space list. This method of controlled
growth helps to keep the |mem| usage consecutive when \TeX\ is
implemented on ``virtual memory'' systems.
@^virtual memory@>

@<Grow more variable-size memory and |goto restart|@>=
begin if hi_mem_min-lo_mem_max>=1998 then t:=lo_mem_max+1000
@y
@ The lower part of |mem| grows by 512 words at a time, unless
we are very close to going under. When it grows, we simply link
a new node into the available-space list. This method of controlled
growth helps to keep the |mem| usage consecutive when \TeX\ is
implemented on ``virtual memory'' systems.
@^virtual memory@>

@<Grow more variable-size memory and |goto restart|@>=
begin if hi_mem_min-lo_mem_max>=1022 then t:=lo_mem_max+512
@z

%% **   127  ******************************************************************

 @x
  llink(t):=llink(q); rlink(llink(q)):=t;@/
 @y
  r:=llink(q);
  llink(t):=r; rlink(r):=t;@/
 @z

%% **   186  ******************************************************************

@x
@<Display the value of |glue_set(p)|@>=
g:=float(glue_set(p));
if (g<>float_constant(0))and(glue_sign(p)<>normal) then
  begin print(", glue set ");
  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
@<Display the value of |glue_set(p)|@>=
g:=float(glue_set(p));
if (g<>float_constant(0))and(glue_sign(p)<>normal) then
  begin print(", glue set ");
  if glue_sign(p)=shrinking then print("- ");
  if abs(mem[p+glue_offset].int)<@'4000000 and false then print("?.?")
  else if abs(g)>float_constant(20000) then
@z

%% **   241  ******************************************************************

@x
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

@p procedure fix_date_and_time;
begin time:=c4p_hour*60+c4p_minute; {minutes since midnight}
day:=c4p_day; {day of month}
month:=c4p_month; {month of year}
year:=c4p_year; {Anno Domini}
end;
@z

%% **   513  ******************************************************************

@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}

@ Input files that can't be found in the user's area may appear in a standard
system area called |TEX_area|. Font metric files whose areas are not given
explicitly are assumed to appear in a standard system area called
|TEX_font_area|.  These system area names will, of course, vary from place
to place.
@^system dependencies@>

@d TEX_area=="TeXinputs:"
@.TeXinputs@>
@d TEX_font_area=="TeXfonts:"
@.TeXfonts@>
@y
@ File names have the
following structure:  If the name contains `\./', the file area
consists of all characters up to and including the final `\./';
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 `\./', if any}
@!ext_delimiter:pool_pointer; {the relevant `\..', if any}

@ Input files that can't be found in the user's area may appear in a standard
system area called |TEX_area|. Font metric files whose areas are not given
explicitly are assumed to appear in a standard system area called
|TEX_font_area|.  These system area names will, of course, vary from place
to place.
@^system dependencies@>

@d TEX_area=="[TeX]Input Dirs:"
@.[TeX]Input Dirs@>
@d TEX_font_area=="[TeX]Font Metric Dirs:"
@.[TeX]Font Metric Dirs@>
@z

%% **   516  ******************************************************************

@x
begin if c=" " then more_name:=false
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
begin if c=" " or c=tabulator then more_name:=false
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

%% **   519  ******************************************************************

@x
for k:=name_length+1 to file_name_size do name_of_file[k]:=' ';
@y
name_of_file[ name_length + 1 ]:= chr(0);
@z

%% **   520  ******************************************************************

@x
@ A messier routine is also needed, since format file names must be scanned
before \TeX's string mechanism has been initialized. We shall use the
global variable |TEX_format_default| to supply the text for default system areas
and extensions related to format files.
@^system dependencies@>

@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}
@d format_extension=".fmt" {the extension, as a \.{WEB} constant}

@<Glob...@>=
@!TEX_format_default:packed array[1..format_default_length] of char;

@ @<Set init...@>=
TEX_format_default:='TeXformats:plain.fmt';
@.TeXformats@>
@.plain@>
@^system dependencies@>
@y
@ We shall use the
global variable |TEX_format_default| to supply the text for default names
and extensions related to format files.
@^system dependencies@>

@d format_default_length=9 {length of the |TEX_format_default| string}
@d format_defaultz_length=format_default_length+1
@d format_ext_length=4 {length of its `\.{.fmt}' part}
@d format_extension=".fmt" {the extension, as a \.{WEB} constant}

@<Glob...@>=
@!TEX_format_default:packed array[1..format_defaultz_length] of char;

@ @<Set init...@>=
c4p_strcpy(TEX_format_default,'plain.fmt');
@.plain@>
@^system dependencies@>
@z

%% **   523  ******************************************************************

@x
@ Here is the messy routine that was just mentioned. It sets |name_of_file|
from the first |n| characters of |TEX_format_default|, followed by
|buffer[a..b]|, followed by the last |format_ext_length| characters of
|TEX_format_default|.

We dare not give error messages here, since \TeX\ calls this routine before
the |error| routine is ready to roll. Instead, we simply drop excess characters,
since the error will be detected in another way when a strange file name
isn't found.
@^system dependencies@>

@p procedure pack_buffered_name(@!n:small_number;@!a,@!b:integer);
var k:integer; {number of positions filled in |name_of_file|}
@!c: ASCII_code; {character being packed}
@!j:integer; {index into |buffer| or |TEX_format_default|}
begin if n+b-a+1+format_ext_length>file_name_size then
  b:=a+file_name_size-n-1-format_ext_length;
k:=0;
for j:=1 to n do append_to_name(xord[TEX_format_default[j]]);
for j:=a to b do append_to_name(buffer[j]);
for j:=format_default_length-format_ext_length+1 to format_default_length do
  append_to_name(xord[TEX_format_default[j]]);
if k<=file_name_size then name_length:=k@+else name_length:=file_name_size;
for k:=name_length+1 to file_name_size do name_of_file[k]:=' ';
end;

@ Here is the only place we use |pack_buffered_name|. This part of the program
becomes active when a ``virgin'' \TeX\ is trying to get going, just after
the preliminary initialization, or when the user is substituting another
format file by typing `\.\&' after the initial `\.{**}' prompt.  The buffer
contains the first line of input in |buffer[loc..(last-1)]|, where
|loc<last| and |buffer[loc]<>" "|.

@<Declare the function called |open_fmt_file|@>=
function open_fmt_file:boolean;
label found,exit;
var j:0..buf_size; {the first space after the format file name}
begin j:=loc;
if buffer[loc]="&" then
  begin incr(loc); j:=loc; buffer[last]:=" ";
  while buffer[j]<>" " do incr(j);
  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;
  wake_up_terminal;
  wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.');
@.Sorry, I can't find...@>
  update_terminal;
  end;
  {now pull out all the stops: try for the system \.{plain} file}
pack_buffered_name(format_default_length-format_ext_length,1,0);
if not w_open_in(fmt_file) then
  begin wake_up_terminal;
  wterm_ln('I can''t find the PLAIN format file!');
@.I can't find PLAIN...@>
@.plain@>
  open_fmt_file:=false; return;
  end;
found:loc:=j; open_fmt_file:=true;
exit:end;
@y
@

@ This part of the program
becomes active when a ``virgin'' \TeX\ is trying to get going, just after
the preliminary initialization, or when the user is substituting another
format file by typing `\.\&' after the initial `\.{**}' prompt.  The buffer
contains the first line of input in |buffer[loc..(last-1)]|, where
|loc<last| and |buffer[loc]<>" "|.

@<Declare the function called |open_fmt_file|@>=
function open_fmt_file:boolean;
label found,exit;
var j:0..buf_size; {the first space after the format file name}
begin j:=loc;
if buffer[loc]="&" then
  begin incr(loc); j:=loc; buffer[last]:=" ";
  while buffer[j]<>" " do incr(j);
  c4p_memcpy(name_of_file,c4p_ptr(buffer[loc]),j-loc);
  c4p_strcpy(c4p_ptr(name_of_file[j-loc+1]),
    c4p_ptr(TEX_format_default[format_default_length-format_ext_length+1]));
  if mt_open_format_file(fmt_file)
         then goto found;
  wake_up_terminal;
  wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.');
@.Sorry, I can't find...@>
  update_terminal;
  end;
  {now pull out all the stops: try for the system \.{plain} file}
c4p_strcpy(name_of_file,TEX_format_default);
if not mt_open_format_file(fmt_file) then
  begin wake_up_terminal;
  wterm_ln('I can''t find the PLAIN format file!');
@.I can't find PLAIN...@>
@.plain@>
  open_fmt_file:=false; return;
  end;
found:loc:=j; open_fmt_file:=true;
exit:end;
@z

%% **   525  ******************************************************************

@x
@p function make_name_string:str_number;
var k:1..file_name_size; {index into |name_of_file|}
begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings)or
 (cur_length>0) 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;
end;
function a_make_name_string(var f:alpha_file):str_number;
begin a_make_name_string:=make_name_string;
end;
function b_make_name_string(var f:byte_file):str_number;
begin b_make_name_string:=make_name_string;
end;
function w_make_name_string(var f:word_file):str_number;
begin w_make_name_string:=make_name_string;
end;
@y
@d a_make_name_string(#)==make_name_string
@d b_make_name_string(#)==make_name_string
@d w_make_name_string(#)==make_name_string

@p function make_name_string:str_number;
var k:1..file_name_size; {index into |name_of_file|}
begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings)or
 (cur_length>0) 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;
end;
@z

%% **   536  ******************************************************************

@x
begin wlog(banner);
slow_print(format_ident); print("  ");
print_int(day); print_char(" ");
months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
@y
begin wlog(banner);
miktex_banner(log_file);
slow_print(format_ident); print("  ");
print_int(day); print_char(" ");
c4p_arrcpy(months,'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC');
@z

%% **   537  ******************************************************************

%@x
    begin pack_file_name(cur_name,TEX_area,cur_ext);
    if a_open_in(cur_file) then goto done;
%@y
    begin pack_file_name(cur_name,TEX_area,cur_ext);
    if a_open_in(cur_file) then goto done;
%@z

%% **   563  ******************************************************************

@x
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;
@y
if aire="" then pack_file_name(nom,TEX_font_area,".tfm")
else pack_file_name(nom,aire,".tfm");
if not mt_open_tfm_file(tfm_file,name_of_file) then abort;
@z

%% **   597  ******************************************************************

@x
@ 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_dvi(a,b)|.
@^system dependencies@>
@^inner loop@>
@^defecation@>

@p procedure write_dvi(@!a,@!b:dvi_index);
begin c4p_buf_write(dvi_file,c4p_ptr(dvi_buf[a]),b-a+1);
end;
@z

%% **  1312  ******************************************************************

@x
undump(lo_mem_stat_max+1000)(hi_mem_stat_min-1)(lo_mem_max);
undump(lo_mem_stat_max+1)(lo_mem_max)(rover);
p:=mem_bot; q:=rover;
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]);
if mem_min<mem_bot-2 then {make more low memory available}
  begin p:=llink(rover); q:=mem_min+1;
  link(mem_min):=null; info(mem_min):=null; {we don't use the bottom word}
  rlink(p):=q; llink(rover):=q;@/
  rlink(q):=rover; llink(q):=p; link(q):=empty_flag;
  node_size(q):=mem_bot-q;
  end;
undump(lo_mem_max+1)(hi_mem_stat_min)(hi_mem_min);
undump(null)(mem_top)(avail); mem_end:=mem_top;
for k:=hi_mem_min to mem_end do undump_wd(mem[k]);
undump_int(var_used); undump_int(dyn_used)
@y
undump(lo_mem_stat_max+1000)(hi_mem_stat_min-1)(lo_mem_max);
undump(lo_mem_stat_max+1)(lo_mem_max)(rover);
p:=mem_bot; q:=rover;
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;
c4p_mget (fmt_file, c4p_ptr(mem[p]), lo_mem_max - p + 1);
if mem_min<mem_bot-2 then {make more low memory available}
  begin p:=llink(rover); q:=mem_min+1;
  link(mem_min):=null; info(mem_min):=null; {we don't use the bottom word}
  rlink(p):=q; llink(rover):=q;@/
  rlink(q):=rover; llink(q):=p; link(q):=empty_flag;
  node_size(q):=mem_bot-q;
  end;
undump(lo_mem_max+1)(hi_mem_stat_min)(hi_mem_min);
undump(null)(mem_top)(avail); mem_end:=mem_top;
c4p_mget (fmt_file, c4p_ptr(mem[hi_mem_min]), mem_end - hi_mem_min + 1);
undump_int(var_used); undump_int(dyn_used)
@z

%% **  1317  ******************************************************************

@x
for j:=k to k+x-1 do undump_wd(eqtb[j]);
@y
c4p_mget (fmt_file, c4p_ptr(eqtb[k]), x);
@z

%% **  1318  ******************************************************************

%@x
%for p:=hash_used+1 to undefined_control_sequence-1 do undump_hh(hash[p]);
%@y
%c4p_mget...
%@z

%% **  1332  ******************************************************************

@x
The initial test involving |ready_already| should be deleted if the
\PASCAL\ runtime system is smart enough to detect such a ``mistake.''
@^system dependencies@>

@p begin @!{|start_here|}
@y
The initial test involving |ready_already| should be deleted if the
\PASCAL\ runtime system is smart enough to detect such a ``mistake.''
@^system dependencies@>

@p begin @!{|start_here|}
if c4p_setjmp (eo_TEX_buf) <> 0 then goto end_of_TEX;
if c4p_setjmp (fin_buf) <> 0 then goto final_end;
mt_first_word;
mt_get_options;
@z

@x
ready_already:=314159;
@y
ready_already:=314159;
mt_after_init;
@z

@x
final_end: ready_already:=0;
@y
final_end: ready_already:=0;
mt_last_word;
if (history = error_message_issued) or (history = fatal_error_stop) then
begin
  c4p_exit (1);
end;
@z

%% **  1333  ******************************************************************

@x
@.Transcript written...@>
    slow_print(log_name); print_char(".");
    end;
  end;
@y
@.Transcript written...@>
    slow_print(log_name); print_char(".");
    end;
  end;
print_ln;
@z

%% **  1379  ******************************************************************

@x
itself will get a new section number.
@^system dependencies@>
@y
itself will get a new section number.
@^system dependencies@>

@ @<External C routines@>=

procedure mt_first_word; forward;
procedure mt_after_init; forward;
procedure mt_last_word; forward;
procedure mt_get_options; forward;
procedure cmdln_to_buf; forward;
function mt_open_format_file (var f:word_file) : boolean; forward;
function mt_open_pool_file (var f:alpha_file) : boolean; forward;
function mt_open_tfm_file (var f:byte_file; n:integer) : boolean; forward;
function mt_open_input_file (var f:alpha_file) : boolean; forward;
function mt_is_print (ch: ASCII_code) : boolean; forward;
procedure miktex_banner (var f:alpha_file); forward;

@ @<Global variables@>=
@!eo_TEX_buf, @!fin_buf : c4p_jmp_buf;
@z
