1% com16bit.ch: Aleph version of file tex.ch
2%
3% tex.ch for C compilation with web2c, derived from various other change files.
4% By Tim Morgan, UC Irvine ICS Department, and many others.
5%
6% (05/28/86) ETM Started with TeX 2.0
7% (06/03/87) ETM Brought up to TeX 2.2
8% (09/26/87) ETM Brought up to TeX 2.3
9% (10/01/87) ETM Brought up to TeX 2.5
10% (12/21/87) ETM Brought up to TeX 2.7
11% (01/14/88) ETM Brought up to TeX 2.9
12% (02/20/88) PAM Revised format and module numbers
13% (03/01/88) ETM Eliminated some unused variables and unnecesary tests
14% (05/09/88) ETM Added yet another casting bug fix
15% (06/21/88) ETM Brought up to TeX version 2.93
16% (12/11/88) ETM Brought up to TeX version 2.94
17% (01/12/89) PAM Brought up to TeX version 2.95
18% (02/14/89) ETM Brought up to TeX version 2.96
19% (03/10/89) ETM Brought up to TeX version 2.98
20% (07/06/89) ETM Brought up to TeX version 2.991
21% (11/30/89) KB  To version 2.992 (8-bit).
22% (01/10/90) SR  To version 2.993.
23% (03/27/90) KY  To version 3.0.
24% (more recent changes in ChangeLog)
25%
26% The TeX program is copyright (C) 1982 by D. E. Knuth.
27% TeX is a trademark of the American Mathematical Society.
28%
29% The module numbers in this change file refer to TEX.WEB 3.141592 as
30% of March, 1995 (published as Donald E. Knuth, TeX: The Program,
31% Volume B of Computers & Typesetting).
32
33@x [0.0] l.83 - WEAVE: print changes only.
34  \def\?##1]{\hbox to 1in{\hfil##1.\ }}
35  }
36@y 83
37  \def\?##1]{\hbox{Changes to \hbox to 1em{\hfil##1}.\ }}
38  }
39\let\maybe=\iffalse
40@z
41
42@x
43@d banner=='This is Aleph, Version 3.14159265-',Omega_version_banner,'-',eTeX_version_banner,'-',Aleph_version_banner {printed when \TeX\ starts}
44@y
45@d banner=='This is Aleph, Version 3.14159265-',Omega_version_banner,'-',eTeX_version_banner,'-',Aleph_version_banner {printed when \TeX\ starts}
46@d banner_k==banner {Web2C announces itself}
47@z
48
49@x [1.4] l.233 - program header
50Actually the heading shown here is not quite normal: The |program| line
51does not mention any |output| file, because \ph\ would ask the \TeX\ user
52to specify a file name if |output| were specified here.
53@:PASCAL H}{\ph@>
54@^system dependencies@>
55@y
56@z
57
58@x [1.4] l.243 - labels in outer block not needed
59program OMEGA; {all file names are defined dynamically}
60label @<Labels in the outer block@>@/
61@y
62program OMEGA; {all file names are defined dynamically}
63@z
64
65@x [1.6] l.267 - labels in outer block not needed
66@ Three labels must be declared in the main program, so we give them
67symbolic names.
68
69@d start_of_TEX=1 {go here when \TeX's variables are initialized}
70@d end_of_TEX=9998 {go here to close files and terminate gracefully}
71@d final_end=9999 {this label marks the ending of the program}
72
73@<Labels in the out...@>=
74start_of_TEX@t\hskip-2pt@>, end_of_TEX@t\hskip-2pt@>,@,final_end;
75  {key control points}
76@y
77@ For Web2c, labels are not declared in the main program, but
78we still have to declare the symbolic names.
79
80@d start_of_TEX=1 {go here when \TeX's variables are initialized}
81@d final_end=9999 {this label marks the ending of the program}
82@z
83
84% Here we change these WEB symbols, which are used much as #ifdef's
85% are in C, into something which will get translated into actual #ifdef's.
86@x [1.7] l.292 - debug..gubed, stat..tats
87@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
88@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
89@y
90@d debug==ifdef('TEXMF_DEBUG')
91@d gubed==endif('TEXMF_DEBUG')
92@z
93@x [1.7] l.297 - debug..gubed, stat..tats
94@d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering
95  usage statistics}
96@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering
97  usage statistics}
98@y
99@d stat==ifdef('STAT')
100@d tats==endif('STAT')
101@z
102
103@x [1.8] l.312 - Same, for `init...tini'.
104@d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
105@d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
106@y 312
107@d init==ifdef('INITEX')
108@d tini==endif('INITEX')
109@z
110
111@x [1.8] l.319 - init...tini is dynamic
112@!init @<Initialize table entries (done by \.{INITEX} only)@>@;@+tini
113@y  318
114@!init
115if ini_version then
116  begin @<Initialize table entries (done by \.{INITEX} only)@>@;
117  end;
118@+tini
119@z
120
121@x [1.11] l.375 - Compile-time constants: most removed for dynamic allocation.
122@<Constants...@>=
123@!mem_max=30000; {greatest index in \TeX's internal |mem| array;
124  must be strictly less than |max_halfword|;
125  must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|}
126@!mem_min=0; {smallest index in \TeX's internal |mem| array;
127  must be |min_halfword| or more;
128  must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|}
129@!buf_size=500; {maximum number of characters simultaneously present in
130  current lines of open files and in control sequences between
131  \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|}
132@!error_line=72; {width of context lines on terminal error messages}
133@!half_error_line=42; {width of first lines of contexts in terminal
134  error messages; should be between 30 and |error_line-15|}
135@!max_print_line=79; {width of longest text lines output; should be at least 60}
136@!stack_size=200; {maximum number of simultaneous input sources}
137@!max_in_open=6; {maximum number of input files and error insertions that
138  can be going on simultaneously}
139@y
140@d file_name_size == maxint
141@d ssup_error_line = 255
142@d ssup_max_strings == 2097151
143{Larger values may be used, but then the arrays consume much more memory.}
144@d ssup_trie_opcode == 65535
145@d ssup_trie_size == @"3FFFFF
146
147@d ssup_hyph_size == 65535 {Changing this requires changing (un)dumping!}
148@d iinf_hyphen_size == 610 {Must be not less than |hyph_prime|!}
149
150@<Constants...@>=
151@!mem_bot=0; {smallest index in the |mem| array dumped by \.{INITEX};
152  must not be less than |mem_min|}
153  {Use |mem_bot=0| for compilers which cannot decrement pointers.}
154@z
155
156@x
157@!font_max=65535; {maximum internal font number; must be at most |font_biggest|}
158@!param_size=60; {maximum number of simultaneous macro parameters}
159@!nest_size=40; {maximum number of semantic levels simultaneously active}
160@!max_strings=3000; {maximum number of strings; must not exceed |max_halfword|}
161@!string_vacancies=8000; {the minimum number of characters that should be
162  available for the user's control sequences and font names,
163  after \TeX's own error messages are stored}
164@!pool_size=32000; {maximum number of characters in strings, including all
165  error messages and help texts, and the names of all fonts and
166  control sequences; must exceed |string_vacancies| by the total
167  length of \TeX's own strings, which is currently about 23000}
168@!save_size=600; {space for saving values outside of current group; must be
169  at most |max_halfword|}
170@!trie_size=8000; {space for hyphenation patterns; should be larger for
171  \.{INITEX} than it is in production versions of \TeX}
172@!trie_op_size=500; {space for ``opcodes'' in the hyphenation patterns}
173@!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8}
174@!file_name_size=40; {file names shouldn't be longer than this}
175@!pool_name='TeXformats:ALEPH.POOL                  ';
176  {string of length |file_name_size|; tells where the string pool appears}
177@y
178@!font_max=65535; {maximum internal font number; must be at most |font_biggest|}
179@!hash_offset=514; {smallest index in hash array, i.e., |hash_base| }
180  {Use |hash_offset=0| for compilers which cannot decrement pointers.}
181@!trie_op_size=15011; {space for ``opcodes'' in the hyphenation patterns;
182  best if relatively prime to 313, 361, and 1009.}
183@!neg_trie_op_size=-35111; {for lower |trie_op_hash| array bound;
184  must be equal to |-trie_op_size|.}
185@!min_trie_op=0; {first possible trie op code for any language}
186@!max_trie_op=ssup_trie_opcode; {largest possible trie opcode for any language}
187@!pool_name=TEXMF_POOL_NAME; {this is configurable, for the sake of ML-\TeX}
188  {string of length |file_name_size|; tells where the string pool appears}
189@!engine_name=TEXMF_ENGINE_NAME; {the name of this engine}
190@#
191@!inf_main_memory = 2000000;
192@!sup_main_memory = 256000000;
193
194@!inf_trie_size = 80000;
195@!sup_trie_size = ssup_trie_size;
196
197@!inf_max_strings = 100000;
198@!sup_max_strings = ssup_max_strings;
199
200@!inf_strings_free = 100;
201@!sup_strings_free = sup_max_strings;
202
203@!inf_buf_size = 500;
204@!sup_buf_size = 30000000;
205
206@!inf_nest_size = 40;
207@!sup_nest_size = 4000;
208
209@!inf_max_in_open = 6;
210@!sup_max_in_open = 127;
211
212@!inf_param_size = 60;
213@!sup_param_size = 6000;
214
215@!inf_save_size = 600;
216@!sup_save_size = 80000;
217
218@!inf_stack_size = 200;
219@!sup_stack_size = 30000;
220
221@!inf_dvi_buf_size = 800;
222@!sup_dvi_buf_size = 65536;
223
224@!inf_pool_size = 32000;
225@!sup_pool_size = 40000000;
226@!inf_pool_free = 1000;
227@!sup_pool_free = sup_pool_size;
228@!inf_string_vacancies = 8000;
229@!sup_string_vacancies = sup_pool_size - 23000;
230
231@!sup_hyph_size = ssup_hyph_size;
232@!inf_hyph_size = iinf_hyphen_size; {Must be not less than |hyph_prime|!}
233@z
234
235@x [1.12] l.427 - Constants that are WEB numeric macros.
236@d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX};
237  must not be less than |mem_min|}
238@d mem_top==30000 {largest index in the |mem| array dumped by \.{INITEX};
239  must be substantially larger than |mem_bot|
240  and not greater than |mem_max|}
241@d font_base=0 {smallest internal font number; must not be less
242  than |min_quarterword|}
243@d hash_size=65536 {maximum number of control sequences; it should be at most
244  about |(mem_max-mem_min)/10|}
245@d hash_prime=55711 {a prime number equal to about 85\pct! of |hash_size|}
246@d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions}
247@y
248@d font_base=0 {smallest internal font number; must not be less
249  than |min_quarterword|}
250@d hash_size=65536 {maximum number of control sequences; it should be at most
251  about |(mem_max-mem_min)/10|}
252@d hash_prime=55711 {a prime number equal to about 85\pct! of |hash_size|}
253@d hyph_prime=607 {another prime for hashing \.{\\hyphenation} exceptions;
254                if you change this, you should also change |iinf_hyphen_size|.}
255@z
256
257@x [1.16] l.498 - Use C macros for `incr' and `decr'.
258@d incr(#) == #:=#+1 {increase a variable by unity}
259@d decr(#) == #:=#-1 {decrease a variable by unity}
260@y
261@z
262
263% The text_char type is used as an array index into xord.  The
264% default type `char' produces signed integers, which are bad array
265% indices in C.
266@x [2.19] l.565 - data type text_char is 8-bit ASCII_code
267@d text_char == char {the data type of characters in text files}
268@y
269@d text_char == ASCII_code {the data type of characters in text files}
270@z
271
272% [3.26] name_of_file is no longer an array.  And change the destination
273% type to text_char, which fixes:
274%
275% Date: 19 Sep 1994 10:38:24 +0200
276% From: thorinn@diku.dk (Lars Mathiesen)
277%	When echoed to the screen and in the log, character codes
278%	above '177 in file names are shown wrongly (typically as ^@).
279%
280@x [3.26] l.789 - name_of_file is no longer an array
281@!name_of_file:packed array[1..file_name_size] of char;@;@/
282  {on some systems this may be a \&{record} variable}
283@y
284@!name_of_file:^char;
285@z
286
287@x [3.27] l.794 - Do file opening in C.
288@ The \ph\ compiler with which the present version of \TeX\ was prepared has
289extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
290we can write
291$$\vbox{\halign{#\hfil\qquad&#\hfil\cr
292|reset(f,@t\\{name}@>,'/O')|&for input;\cr
293|rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
294The `\\{name}' parameter, which is of type `{\bf packed array
295$[\langle\\{any}\rangle]$ of \\{char}}', stands for the name of
296the external file that is being opened for input or output.
297Blank spaces that might appear in \\{name} are ignored.
298
299The `\.{/O}' parameter tells the operating system not to issue its own
300error messages if something goes wrong. If a file of the specified name
301cannot be found, or if such a file cannot be opened for some other reason
302(e.g., someone may already be trying to write the same file), we will have
303|@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|.  This allows
304\TeX\ to undertake appropriate corrective action.
305@:PASCAL H}{\ph@>
306@^system dependencies@>
307
308\TeX's file-opening procedures return |false| if no file identified by
309|name_of_file| could be opened.
310
311@d reset_OK(#)==erstat(#)=0
312@d rewrite_OK(#)==erstat(#)=0
313
314@p function a_open_in(var f:alpha_file):boolean;
315  {open a text file for input}
316begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f);
317end;
318@#
319function a_open_out(var f:alpha_file):boolean;
320  {open a text file for output}
321begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f);
322end;
323@#
324function b_open_in(var f:byte_file):boolean;
325  {open a binary file for input}
326begin reset(f,name_of_file,'/O'); b_open_in:=reset_OK(f);
327end;
328@#
329function b_open_out(var f:byte_file):boolean;
330  {open a binary file for output}
331begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f);
332end;
333@#
334function w_open_in(var f:word_file):boolean;
335  {open a word file for input}
336begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f);
337end;
338@#
339function w_open_out(var f:word_file):boolean;
340  {open a word file for output}
341begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f);
342end;
343@y
344@ All of the file opening functions are defined in C.
345@z
346
347@x [3.28] l.850 - Do file closing in C.
348@ Files can be closed with the \ph\ routine `|close(f)|', which
349@:PASCAL H}{\ph@>
350@^system dependencies@>
351should be used when all input or output with respect to |f| has been completed.
352This makes |f| available to be opened again, if desired; and if |f| was used for
353output, the |close| operation makes the corresponding external file appear
354on the user's area, ready to be read.
355
356These procedures should not generate error messages if a file is
357being closed before it has been successfully opened.
358
359@p procedure a_close(var f:alpha_file); {close a text file}
360begin close(f);
361end;
362@#
363procedure b_close(var f:byte_file); {close a binary file}
364begin close(f);
365end;
366@#
367procedure w_close(var f:word_file); {close a word file}
368begin close(f);
369end;
370@y
371@ And all the file closing routines as well.
372@z
373
374@x [3.30] l.888 - Array size of input buffer is determined at runtime.
375@!buffer:array[0..buf_size] of ASCII_code; {lines of characters being read}
376@y
377@!buffer:^ASCII_code; {lines of characters being read}
378@z
379
380@x [3.31] l.933 - Do `input_ln' in C.
381@p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean;
382  {inputs the next line or returns |false|}
383var last_nonblank:0..buf_size; {|last| with trailing blanks removed}
384begin if bypass_eoln then if not eof(f) then get(f);
385  {input the first character of the line into |f^|}
386last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
387if eof(f) then input_ln:=false
388else  begin last_nonblank:=first;
389  while not eoln(f) do
390    begin if last>=max_buf_stack then
391      begin max_buf_stack:=last+1;
392      if max_buf_stack=buf_size then
393        @<Report overflow of the input buffer, and abort@>;
394      end;
395    buffer[last]:=f^; get(f); incr(last);
396    if buffer[last-1]<>" " then last_nonblank:=last;
397    end;
398  last:=last_nonblank; input_ln:=true;
399  end;
400end;
401@y
402We define |input_ln| in C, for efficiency.
403@z
404
405% [3.32] `term_in' and `term_out' are standard input and output.
406% Declare the variables that used to be constants.
407@x [3.32] l.961 - `term_in' and `term_out' are standard input and output.
408@<Glob...@>=
409@!term_in:alpha_file; {the terminal as an input file}
410@!term_out:alpha_file; {the terminal as an output file}
411@y
412@d term_in==stdin {the terminal as an input file}
413@d term_out==stdout {the terminal as an output file}
414
415@<Glob...@>=
416@!init
417@!ini_version:boolean; {are we \.{INITEX}?}
418@!dump_option:boolean; {was the dump name option used?}
419@!dump_line:boolean; {was a \.{\%\AM format} line seen?}
420tini@/
421@#
422@!dump_name:const_cstring; {format name for terminal display}
423@#
424@!bound_default:integer; {temporary for setup}
425@!bound_name:const_cstring; {temporary for setup}
426@#
427@!main_memory:integer; {total memory words allocated in initex}
428@!extra_mem_bot:integer; {|mem_min:=mem_bot-extra_mem_bot| except in \.{INITEX}}
429@!mem_min:integer; {smallest index in \TeX's internal |mem| array;
430  must be |min_halfword| or more;
431  must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|}
432@!mem_top:integer; {largest index in the |mem| array dumped by \.{INITEX};
433  must be substantially larger than |mem_bot|,
434  equal to |mem_max| in \.{INITEX}, else not greater than |mem_max|}
435@!extra_mem_top:integer; {|mem_max:=mem_top+extra_mem_top| except in \.{INITEX}}
436@!mem_max:integer; {greatest index in \TeX's internal |mem| array;
437  must be strictly less than |max_halfword|;
438  must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|}
439@!error_line:integer; {width of context lines on terminal error messages}
440@!half_error_line:integer; {width of first lines of contexts in terminal
441  error messages; should be between 30 and |error_line-15|}
442@!max_print_line:integer;
443  {width of longest text lines output; should be at least 60}
444@!max_strings:integer; {maximum number of strings; must not exceed |max_halfword|}
445@!strings_free:integer; {strings available after format loaded}
446@!string_vacancies:integer; {the minimum number of characters that should be
447  available for the user's control sequences and font names,
448  after \TeX's own error messages are stored}
449@!pool_size:integer; {maximum number of characters in strings, including all
450  error messages and help texts, and the names of all fonts and
451  control sequences; must exceed |string_vacancies| by the total
452  length of \TeX's own strings, which is currently about 23000}
453@!pool_free:integer;{pool space free after format loaded}
454@!hyph_size:integer; {maximun number of hyphen exceptions}
455@!trie_size:integer; {space for hyphenation patterns; should be larger for
456  \.{INITEX} than it is in production versions of \TeX.  50000 is
457  needed for English, German, and Portuguese.}
458@!buf_size:integer; {maximum number of characters simultaneously present in
459  current lines of open files and in control sequences between
460  \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|}
461@!stack_size:integer; {maximum number of simultaneous input sources}
462@!max_in_open:integer; {maximum number of input files and error insertions that
463  can be going on simultaneously}
464@!param_size:integer; {maximum number of simultaneous macro parameters}
465@!nest_size:integer; {maximum number of semantic levels simultaneously active}
466@!save_size:integer; {space for saving values outside of current group; must be
467  at most |max_halfword|}
468@!dvi_buf_size:integer; {size of the output buffer; must be a multiple of 8}
469@!quoted_filename:boolean; {current filename is quoted}
470@z
471
472@x [3.33] l.964 - We don't need to open terminal files.
473@ Here is how to open the terminal files
474in \ph. The `\.{/I}' switch suppresses the first |get|.
475@:PASCAL H}{\ph@>
476@^system dependencies@>
477
478@d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
479@d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output}
480@y
481@ Here is how to open the terminal files.  |t_open_out| does nothing.
482|t_open_in|, on the other hand, does the work of ``rescanning,'' or getting
483any command line arguments the user has provided.  It's defined in C.
484
485@d t_open_out == {output already open for text output}
486@z
487
488@x [3.34] l.982 - Flushing output to terminal files.
489these operations can be specified in \ph:
490@:PASCAL H}{\ph@>
491@^system dependencies@>
492
493@d update_terminal == break(term_out) {empty the terminal output buffer}
494@d clear_terminal == break_in(term_in,true) {clear the terminal input buffer}
495@y
496these operations can be specified with {\mc UNIX}.  |update_terminal|
497does an |fflush|. |clear_terminal| is redefined
498to do nothing, since the user should control the terminal.
499@^system dependencies@>
500
501@d update_terminal == fflush (term_out)
502@d clear_terminal == do_nothing
503@z
504
505@x [3.35] l.1017 - Do `input_ln' in C => section not needed.
506@<Report overflow of the input buffer, and abort@>=
507if format_ident=0 then
508  begin write_ln(term_out,'Buffer size exceeded!'); goto final_end;
509@.Buffer size exceeded@>
510  end
511else begin cur_input.loc_field:=first; cur_input.limit_field:=last-1;
512  overflow("buffer size",buf_size);
513@:TeX capacity exceeded buffer size}{\quad buffer size@>
514  end
515@y
516Routine is implemented in C; part of module is, however, needed for e-TeX.
517
518@<Report overflow of the input buffer, and abort@>=
519  begin cur_input.loc_field:=first; cur_input.limit_field:=last-1;
520  overflow("buffer size",buf_size);
521@:TeX capacity exceeded buffer size}{\quad buffer size@>
522  end
523@z
524
525@x [3.37] l.1055 - |init_terminal|, reading the command line.
526@ The following program does the required initialization
527without retrieving a possible command line.
528It should be clear how to modify this routine to deal with command lines,
529if the system permits them.
530@^system dependencies@>
531
532@p function init_terminal:boolean; {gets the terminal input started}
533label exit;
534begin t_open_in;
535@y
536@ The following program does the required initialization.
537Iff anything has been specified on the command line, then |t_open_in|
538will return with |last > first|.
539@^system dependencies@>
540
541@p function init_terminal:boolean; {gets the terminal input started}
542label exit;
543begin t_open_in;
544if last > first then
545  begin loc := first;
546  while (loc < last) and (buffer[loc]=' ') do incr(loc);
547  if loc < last then
548    begin init_terminal := true; goto exit;
549    end;
550  end;
551@z
552
553@x [3.37] l.1068 - |init_terminal|, output missing newline.
554    write(term_out,'! End of file on the terminal... why?');
555@y
556    write_ln(term_out,'! End of file on the terminal... why?');
557@z
558
559@x [4.38] l.1126 - Array size for string pool is determined at runtime.
560@!pool_pointer = 0..pool_size; {for variables that point into |str_pool|}
561@!str_number = 0..max_strings; {for variables that point into |str_start|}
562@y
563@!pool_pointer = integer; {for variables that point into |str_pool|}
564@!str_number = 0..ssup_max_strings; {for variables that point into |str_start|}
565@z
566
567@x [4.39] l.1131 - Dynamically size pool arrays.
568@!str_pool:packed array[pool_pointer] of packed_ASCII_code; {the characters}
569@!str_start_ar : array[str_number] of pool_pointer; {the starting pointers}
570@y
571@!str_pool: ^packed_ASCII_code; {the characters}
572@!str_start_ar : ^pool_pointer; {the starting pointers}
573@z
574
575@x [4.47] l.1237 - string recycling
576@p @!init function get_strings_started:boolean; {initializes the string pool,
577@y
578@p @t\4@>@<Declare additional routines for string recycling@>@/
579
580@!init function get_strings_started:boolean; {initializes the string pool,
581@z
582
583@x - unused variables.
584var k,@!l:0..biggest_char; {small indices or counters}
585@!m,@!n:text_char; {characters input from |pool_file|}
586@!g:str_number; {garbage}
587@!a:integer; {accumulator for check sum}
588@!c:boolean; {check sum has been checked}
589@y
590var g:str_number; {garbage}
591@z
592
593@x
594@ @d bad_pool(#)==begin wake_up_terminal; write_ln(term_out,#);
595  a_close(pool_file); get_strings_started:=false; return;
596  end
597@<Read the other strings...@>=
598name_of_file:=pool_name; {we needn't set |name_length|}
599if a_open_in(pool_file) then
600  begin c:=false;
601  repeat @<Read one string, but return |false| if the
602    string memory space is getting too tight for comfort@>;
603  until c;
604  a_close(pool_file); get_strings_started:=true;
605  end
606else  bad_pool('! I can''t read ALEPH.POOL.')
607@.I can't read ALEPH.POOL@>
608
609@ @<Read one string...@>=
610begin if eof(pool_file) then bad_pool('! ALEPH.POOL has no check sum.');
611@.ALEPH.POOL has no check sum@>
612read(pool_file,m,n); {read two digits of string length}
613if m='*' then @<Check the pool check sum@>
614else  begin if (m<"0")or(m>"9")or@|
615      (n<"0")or(n>"9") then
616    bad_pool('! ALEPH.POOL line doesn''t begin with two digits.');
617@.ALEPH.POOL line doesn't...@>
618  l:=m*10+n-"0"*11; {compute the length}
619  if pool_ptr+l+string_vacancies>pool_size then
620    bad_pool('! You have to increase POOLSIZE.');
621@.You have to increase POOLSIZE@>
622  for k:=1 to l do
623    begin if eoln(pool_file) then m:=' '@+else read(pool_file,m);
624    append_char(m);
625    end;
626  read_ln(pool_file); g:=make_string;
627  end;
628end
629
630@ The \.{WEB} operation \.{@@\$} denotes the value that should be at the
631end of this \.{OMEGA.POOL} file; any other value means that the wrong pool
632file has been loaded.
633@^check sum@>
634
635@<Check the pool check sum@>=
636begin a:=0; k:=1;
637loop@+  begin if (n<"0")or(n>"9") then
638  bad_pool('! ALEPH.POOL check sum doesn''t have nine digits.');
639@.ALEPH.POOL check sum...@>
640  a:=10*a+n-"0";
641  if k=9 then goto done;
642  incr(k); read(pool_file,n);
643  end;
644done: if a<>@$ then bad_pool('! ALEPH.POOL doesn''t match; OTANGLE me again.');
645@.ALEPH.POOL doesn't match@>
646c:=true;
647end
648@y
649@ @<Read the other strings...@>=
650  g := loadpoolstrings((pool_size-string_vacancies));
651  if g=0 then begin
652     wake_up_terminal; write_ln(term_out,'! You have to increase POOLSIZE.');
653     get_strings_started:=false;
654     return;
655  end;
656  get_strings_started:=true;
657
658@ Empty module
659
660@ Empty module
661@z
662
663@x [5.54] l.1422 - error_line
664@!trick_buf:array[0..error_line] of ASCII_code; {circular buffer for
665@y
666@!trick_buf:array[0..ssup_error_line] of ASCII_code; {circular buffer for
667@z
668
669@x [5.61] l.1556 - Print rest of banner.
670wterm(eTeX_banner);
671if format_ident=0 then wterm_ln(' (no format preloaded)')
672else  begin slow_print(format_ident); print_ln;
673  end;
674@y
675wterm(eTeX_banner);
676wterm(version_string);
677if format_ident=0 then wterm_ln(' (preloaded format=',dump_name,')')
678else  begin slow_print(format_ident); print_ln;
679  end;
680@z
681
682@x [6.73] l.1732 - Add unspecified_mode.
683@d error_stop_mode=3 {stops at every opportunity to interact}
684@y
685@d error_stop_mode=3 {stops at every opportunity to interact}
686@d unspecified_mode=4 {extra value for command-line switch}
687@z
688
689@x [6.73] l.1738 - Add interaction_option.
690@!interaction:batch_mode..error_stop_mode; {current level of interaction}
691@y
692@!interaction:batch_mode..error_stop_mode; {current level of interaction}
693@!interaction_option:batch_mode..unspecified_mode; {set from command line}
694@z
695
696@x [6.74] l.1740 - Allow override by command line switch.
697@ @<Set init...@>=interaction:=error_stop_mode;
698@y
699@ @<Set init...@>=if interaction_option=unspecified_mode then
700  interaction:=error_stop_mode
701else
702  interaction:=interaction_option;
703@z
704
705% [6.81] Eliminate nonlocal goto, since C doesn't have them.
706% Plus, it's nicer just to do an exit with the appropriate status code
707% under Unix.  We call it `uexit' because there's a WEB symbol called
708% `exit' already.  We use a C macro to change `uexit' back to `exit'.
709@x [6.81] l.1852 - Eliminate nonlocal goto, since C doesn't have them.
710@<Error hand...@>=
711procedure jump_out;
712begin goto end_of_TEX;
713end;
714@y
715@d do_final_end==begin
716   update_terminal;
717   ready_already:=0;
718   if (history <> spotless) and (history <> warning_issued) then
719       uexit(1)
720   else
721       uexit(0);
722   end
723
724@<Error hand...@>=
725procedure jump_out;
726begin
727close_files_and_terminate;
728do_final_end;
729end;
730@z
731
732@x [6.84] l.1888 - Implement the switch-to-editor option.
733line ready to be edited. But such an extension requires some system
734wizardry, so the present implementation simply types out the name of the
735file that should be
736edited and the relevant line number.
737@^system dependencies@>
738
739There is a secret `\.D' option available when the debugging routines haven't
740been commented~out.
741@^debugging@>
742@y
743line ready to be edited.
744We do this by calling the external procedure |call_edit| with a pointer to
745the filename, its length, and the line number.
746However, here we just set up the variables that will be used as arguments,
747since we don't want to do the switch-to-editor until after TeX has closed
748its files.
749@^system dependencies@>
750
751There is a secret `\.D' option available when the debugging routines haven't
752been commented~out.
753@^debugging@>
754@d edit_file==input_stack[base_ptr]
755@z
756
757@x [6.84] l.1903 - Implement the switch-to-editor option.
758"E": if base_ptr>0 then
759  begin print_nl("You want to edit file ");
760@.You want to edit file x@>
761  slow_print(input_stack[base_ptr].name_field);
762  print(" at line "); print_int(line);
763  interaction:=scroll_mode; jump_out;
764@y
765"E": if base_ptr>0 then
766    begin edit_name_start:=str_start(edit_file.name_field);
767    edit_name_length:=str_start(edit_file.name_field+1) -
768    		      str_start(edit_file.name_field);
769    edit_line:=line;
770    jump_out;
771@z
772
773% [7.104] `remainder' is a library routine on some systems, so change
774% its name to avoid conflicts.
775@x [7.104] l.2227 - avoid name conflicts with lib routine remainder()
776|remainder|, holds the remainder after a division.
777
778@<Glob...@>=
779@y
780|remainder|, holds the remainder after a division.
781
782@d remainder==tex_remainder
783
784@<Glob...@>=
785@z
786
787@x [7.109] l.2352 - Define glue_ratio in C.
788@!glue_ratio=real; {one-word representation of a glue expansion factor}
789@y
790@z
791
792@x [8.112] l.2450 - Efficiency.
793macros are simplified in the obvious way when |min_quarterword=0|.
794@^inner loop@>@^system dependencies@>
795
796@d qi(#)==#+min_quarterword
797  {to put an |eight_bits| item into a quarterword}
798@d qo(#)==#-min_quarterword
799  {to take an |eight_bits| item out of a quarterword}
800@d hi(#)==#+min_halfword
801  {to put a sixteen-bit item into a halfword}
802@d ho(#)==#-min_halfword
803  {to take a sixteen-bit item from a halfword}
804@y
805macros are simplified in the obvious way when |min_quarterword=0|.
806So they have been simplified here in the obvious way.
807@^inner loop@>@^system dependencies@>
808
809The \.{WEB} source for \TeX\ defines |hi(#)==#+min_halfword| which can be
810simplified when |min_halfword=0|.  The Web2C implemetation of \Aleph\
811occasionally uses |null| as~0, and therefore requires |min_halfword=0|.
812
813@d qi(#)==# {to put an |eight_bits| item into a quarterword}
814@d qo(#)==# {to take an |eight_bits| item from a quarterword}
815@d hi(#)==# {to put a sixteen-bit item into a halfword}
816@d ho(#)==# {to take a sixteen-bit item from a halfword}
817@z
818
819% [8.113] We've put the memory structure into the include file
820% `texmf.h', since it's too hard to translate automatically.
821@x [8.113] l.2453 - data structures for main memory
822@!quarterword = min_quarterword..max_quarterword; {1/4 of a word}
823@!halfword=min_halfword..max_halfword; {1/2 of a word}
824@!two_choices = 1..2; {used when there are two variants in a record}
825@!four_choices = 1..4; {used when there are four variants in a record}
826@!two_halves = packed record@;@/
827  @!rh:halfword;
828  case two_choices of
829  1: (@!lh:halfword);
830  2: (@!b0:quarterword; @!b1:quarterword);
831  end;
832@!four_quarters = packed record@;@/
833  @!b0:quarterword;
834  @!b1:quarterword;
835  @!b2:quarterword;
836  @!b3:quarterword;
837  end;
838@!memory_word = record@;@/
839  case four_choices of
840  1: (@!int:integer);
841  2: (@!gr:glue_ratio);
842  3: (@!hh:two_halves);
843  4: (@!qqqq:four_quarters);
844  end;
845@y
846@!quarterword = min_quarterword..max_quarterword;
847@!halfword = min_halfword..max_halfword;
848@!two_choices = 1..2; {used when there are two variants in a record}
849@!four_choices = 1..4; {used when there are four variants in a record}
850@=#include "texmfmem.h";@>
851@=#include "alephmem.h";@>
852@z
853
854% [9.116] Change `mem' to `zmem', so we can define mem to be a register
855% pointer to the memory array for speed.
856@x [9.116] l.2545 - definition of main memory array
857@!mem : array[mem_min..mem_max] of memory_word; {the big dynamic storage area}
858@y
859@!yzmem : ^memory_word; {the big dynamic storage area}
860@!zmem : ^memory_word; {the big dynamic storage area}
861@z
862
863% [11.165] Fix the word `free' so that it doesn't conflict with the
864% standard C library routine of the same name.
865@x [11.165] l.3364 - avoid conflict with lib function free()
866are debugging.)
867@y
868are debugging.)
869
870@d free==free_arr
871@z
872
873@x [11.165] l.3367 - dummy |free| and |was_free| arrays
874@!debug @!free: packed array [mem_min..mem_max] of boolean; {free cells}
875@t\hskip10pt@>@!was_free: packed array [mem_min..mem_max] of boolean;
876@y
877 {The debug memory arrays have not been mallocated yet.}
878@!debug @!free: packed array [0..9] of boolean; {free cells}
879@t\hskip10pt@>@!was_free: packed array [0..9] of boolean;
880@z
881
882@x [12.174] l.3526 - Eliminate unsigned comparisons to zero.
883        begin if (font(p)<font_base)or(font(p)>font_max) then
884          print_char("*")
885@.*\relax@>
886        else @<Print the font identifier for |font(p)|@>;
887@y
888        begin @<Print the font identifier for |font(p)|@>;
889@z
890
891@x [12.176] l.3563 - Eliminate unsigned comparisons to zero.
892begin if p>mem_end then print_esc("CLOBBERED.")
893else  begin if (font(p)<font_base)or(font(p)>font_max) then print_char("*")
894@.*\relax@>
895  else @<Print the font identifier for |font(p)|@>;
896@y
897begin if p>mem_end then print_esc("CLOBBERED.")
898else  begin @<Print the font identifier for |font(p)|@>;
899@z
900
901@x [12.186] l.3747 - Don't worry about strange floating point values.
902  if abs(mem[p+glue_offset].int)<@'4000000 then print("?.?")
903  else if abs(g)>float_constant(20000) then
904@y 3747
905  { The Unix |pc| folks removed this restriction with a remark that
906    invalid bit patterns were vanishingly improbable, so we follow
907    their example without really understanding it.
908  |if abs(mem[p+glue_offset].int)<@'4000000 then print('?.?')|
909  |else| }
910  if fabs(g)>float_constant(20000) then
911@z
912
913
914@x [16.213] l.4321 - texarray
915@!nest:array[0..nest_size] of list_state_record;
916@y
917@!nest:^list_state_record;
918@z
919
920@x [16.215] l.4344 - remove mem[] reference from initialize.
921@<Start a new current page@>;
922@y
923@/{The following piece of code is a copy of module 991:}
924page_contents:=empty; page_tail:=page_head; {|link(page_head):=null;|}@/
925last_glue:=max_halfword; last_penalty:=0; last_kern:=0;
926page_depth:=0; page_max_depth:=0;
927@z
928
929@x [17.241] l.5219 - Do `fix_date_and_time' in C.
930@ The following procedure, which is called just before \TeX\ initializes its
931input and output, establishes the initial values of the date and time.
932@^system dependencies@>
933Since standard \PASCAL\ cannot provide such information, something special
934is needed. The program here simply specifies July 4, 1776, at noon; but
935users probably want a better approximation to the truth.
936
937@p procedure fix_date_and_time;
938begin time:=12*60; {minutes since midnight}
939day:=4; {fourth day of the month}
940month:=7; {seventh month of the year}
941year:=1776; {Anno Domini}
942end;
943@y
944@ The following procedure, which is called just before \TeX\ initializes its
945input and output, establishes the initial values of the date and time.
946It calls a macro-defined |date_and_time| routine.  |date_and_time|
947in turn is a C macro, which calls |get_date_and_time|, passing
948it the addresses of the day, month, etc., so they can be set by the
949routine.  |get_date_and_time| also sets up interrupt catching if that
950is conditionally compiled in the C code.
951@^system dependencies@>
952
953@d fix_date_and_time==o_date_and_time(int_base+time_code,
954                                      int_base+day_code,
955                                      int_base+month_code,
956                                      int_base+year_code)
957@z
958
959@x [18.262] l.5584 - Remove more unsigned comparisons to zero.
960else if (newtext(p)<0)or(newtext(p)>=str_ptr) then print_esc("NONEXISTENT.")
961@y
962else if (newtext(p)>=str_ptr) then print_esc("NONEXISTENT.")
963@z
964
965@x [19.271] l.5872 - texarray
966@!save_stack : array[0..save_size] of memory_word;
967@y
968@!save_stack : ^memory_word;
969@z
970
971@x [22.301] l.6432 - texarray
972@!input_stack : array[0..stack_size] of in_state_record;
973@y
974@!input_stack : ^in_state_record;
975@z
976
977@x [22.304] l.6536 - texarray
978@!input_file : array[1..max_in_open] of alpha_file;
979@!input_file_mode : array[1..max_in_open] of halfword;
980@!input_file_translation : array[1..max_in_open] of halfword;
981@!line : integer; {current line number in the current source file}
982@!line_stack : array[1..max_in_open] of integer;
983@y
984@!input_file : ^alpha_file;
985@!input_file_mode : ^halfword;
986@!input_file_translation : ^halfword;
987@!line : integer; {current line number in the current source file}
988@!line_stack : ^integer;
989@z
990
991@x [22.308] l.6701 - texarray
992@!param_stack:array [0..param_size] of pointer;
993  {token list pointers for parameters}
994@y
995@!param_stack: ^pointer;
996  {token list pointers for parameters}
997@z
998
999@x [23.328] l.7043 - keep top of source_filename_stack initialized
1000incr(in_open); push_input; index:=in_open;
1001@y
1002incr(in_open); push_input; index:=in_open;
1003source_filename_stack[index]:=0;full_source_filename_stack[index]:=0;
1004@z
1005
1006@x [23.331] l.7071 - init source file name stacks
1007begin input_ptr:=0; max_in_stack:=0;
1008@y
1009begin input_ptr:=0; max_in_stack:=0;
1010source_filename_stack[0]:=0;full_source_filename_stack[0]:=0;
1011@z
1012
1013@x [28.501] l.9747 - \eof18
1014if_eof_code: begin scan_four_bit_int; b:=(read_open[cur_val]=closed);
1015  end;
1016@y
1017if_eof_code: begin scan_four_bit_int_or_18;
1018  if cur_val=18 then b:=not shellenabledp
1019  else b:=(read_open[cur_val]=closed);
1020  end;
1021@z
1022
1023@x [29.513] l.9951 - Area and extension rules for filenames.
1024@ The file names we shall deal with for illustrative purposes have the
1025following structure:  If the name contains `\.>' or `\.:', the file area
1026consists of all characters up to and including the final such character;
1027otherwise the file area is null.  If the remaining file name contains
1028`\..', the file extension consists of all such characters from the first
1029remaining `\..' to the end, otherwise the file extension is null.
1030@y
1031@ The file names we shall deal with have the
1032following structure:  If the name contains `\./' or `\.:'
1033(for Amiga only), the file area
1034consists of all characters up to and including the final such character;
1035otherwise the file area is null.  If the remaining file name contains
1036`\..', the file extension consists of all such characters from the last
1037`\..' to the end, otherwise the file extension is null.
1038@z
1039
1040@x [29.513] l.9963 - Area and extension rules for filenames.
1041@!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any}
1042@!ext_delimiter:pool_pointer; {the relevant `\..', if any}
1043@y
1044@!area_delimiter:pool_pointer; {the most recent `\./', if any}
1045@!ext_delimiter:pool_pointer; {the most recent `\..', if any}
1046@z
1047
1048@x [29.514] l.9973 - TeX area directories.
1049@d TEX_area=="TeXinputs:"
1050@.TeXinputs@>
1051@d TEX_font_area=="TeXfonts:"
1052@.TeXfonts@>
1053@y
1054In C, the default paths are specified separately.
1055@z
1056
1057@x [29.515] l.9995 - filenames: quoted
1058begin area_delimiter:=0; ext_delimiter:=0;
1059@y
1060begin area_delimiter:=0; ext_delimiter:=0; quoted_filename:=false;
1061@z
1062
1063@x [29.516] l.9992 - filenames: more_name
1064begin if c=" " then more_name:=false
1065@y
1066begin if (c=" ") and stop_at_space and (not quoted_filename) then
1067  more_name:=false
1068else  if c="""" then begin
1069  quoted_filename:=not quoted_filename;
1070  more_name:=true;
1071  end
1072@z
1073
1074@x [29.516] l.9994 - filenames: more_name
1075  if (c=">")or(c=":") then
1076@y
1077  if IS_DIR_SEP(c) then
1078@z
1079
1080@x [29.516] l.9997 - filenames: more_name
1081  else if (c=".")and(ext_delimiter=0) then ext_delimiter:=cur_length;
1082@y
1083  else if c="." then ext_delimiter:=cur_length;
1084@z
1085
1086@x [29.517] l.10002 - end_name: string recycling
1087@ The third.
1088@^system dependencies@>
1089
1090@p procedure end_name;
1091@y
1092@ The third.
1093@^system dependencies@>
1094If a string is already in the string pool, the function
1095|slow_make_string| does not create a new string but returns this string
1096number, thus saving string space.  Because of this new property of the
1097returned string number it is not possible to apply |flush_string| to
1098these strings.
1099
1100@p procedure end_name;
1101var temp_str: str_number; {result of file name cache lookups}
1102@!j,@!s,@!t: pool_pointer; {running indices}
1103@!must_quote:boolean; {whether we need to quote a string}
1104@z
1105
1106@x [29.517] l.10022 - end_name: spaces in filenames
1107@:TeX capacity exceeded number of strings}{\quad number of strings@>
1108@y
1109@:TeX capacity exceeded number of strings}{\quad number of strings@>
1110str_room(6); {Room for quotes, if needed.}
1111{add quotes if needed}
1112if area_delimiter<>0 then begin
1113  {maybe quote |cur_area|}
1114  must_quote:=false;
1115  s:=str_start(str_ptr);
1116  t:=str_start(str_ptr)+area_delimiter;
1117  j:=s;
1118  while (not must_quote) and (j<t) do begin
1119    must_quote:=str_pool[j]=" "; incr(j);
1120    end;
1121  if must_quote then begin
1122    for j:=pool_ptr-1 downto t do str_pool[j+2]:=str_pool[j];
1123    str_pool[t+1]:="""";
1124    for j:=t-1 downto s do str_pool[j+1]:=str_pool[j];
1125    str_pool[s]:="""";
1126    if ext_delimiter<>0 then ext_delimiter:=ext_delimiter+2;
1127    area_delimiter:=area_delimiter+2;
1128    pool_ptr:=pool_ptr+2;
1129    end;
1130  end;
1131{maybe quote |cur_name|}
1132s:=str_start(str_ptr)+area_delimiter;
1133if ext_delimiter=0 then t:=pool_ptr else t:=str_start(str_ptr)+ext_delimiter-1;
1134must_quote:=false;
1135j:=s;
1136while (not must_quote) and (j<t) do begin
1137  must_quote:=str_pool[j]=" "; incr(j);
1138  end;
1139if must_quote then begin
1140  for j:=pool_ptr-1 downto t do str_pool[j+2]:=str_pool[j];
1141  str_pool[t+1]:="""";
1142  for j:=t-1 downto s do str_pool[j+1]:=str_pool[j];
1143  str_pool[s]:="""";
1144  if ext_delimiter<>0 then ext_delimiter:=ext_delimiter+2;
1145  pool_ptr:=pool_ptr+2;
1146  end;
1147if ext_delimiter<>0 then begin
1148  {maybe quote |cur_ext|}
1149  s:=str_start(str_ptr)+ext_delimiter-1;
1150  t:=pool_ptr;
1151  must_quote:=false;
1152  j:=s;
1153  while (not must_quote) and (j<t) do begin
1154    must_quote:=str_pool[j]=" "; incr(j);
1155    end;
1156  if must_quote then begin
1157    str_pool[t+1]:="""";
1158    for j:=t-1 downto s do str_pool[j+1]:=str_pool[j];
1159    str_pool[s]:="""";
1160    pool_ptr:=pool_ptr+2;
1161    end;
1162  end;
1163@z
1164
1165@x [29.517] l.10011 - end_name: string recycling
1166  str_start(str_ptr+1):=str_start(str_ptr)+area_delimiter; incr(str_ptr);
1167  end;
1168if ext_delimiter=0 then
1169  begin cur_ext:=""; cur_name:=make_string;
1170@y
1171  str_start(str_ptr+1):=str_start(str_ptr)+area_delimiter; incr(str_ptr);
1172  temp_str:=search_string(cur_area);
1173  if temp_str>0 then
1174    begin cur_area:=temp_str;
1175    decr(str_ptr);  {no |flush_string|, |pool_ptr| will be wrong!}
1176    for j:=str_start(str_ptr+1) to pool_ptr-1 do
1177      begin str_pool[j-area_delimiter]:=str_pool[j];
1178      end;
1179    pool_ptr:=pool_ptr-area_delimiter; {update |pool_ptr|}
1180    end;
1181  end;
1182if ext_delimiter=0 then
1183  begin cur_ext:=""; cur_name:=slow_make_string;
1184@z
1185
1186@x [29.517] l.10016 - end_name: string recycling
1187else  begin cur_name:=str_ptr;
1188  str_start(str_ptr+1):=str_start(str_ptr)+ext_delimiter-area_delimiter-1;
1189  incr(str_ptr); cur_ext:=make_string;
1190@y
1191else  begin cur_name:=str_ptr;
1192  str_start(str_ptr+1):=str_start(str_ptr)+ext_delimiter-area_delimiter-1;
1193  incr(str_ptr); cur_ext:=make_string;
1194  decr(str_ptr); {undo extension string to look at name part}
1195  temp_str:=search_string(cur_name);
1196  if temp_str>0 then
1197    begin cur_name:=temp_str;
1198    decr(str_ptr);  {no |flush_string|, |pool_ptr| will be wrong!}
1199    for j:=str_start(str_ptr+1) to pool_ptr-1 do
1200      begin str_pool[j-ext_delimiter+area_delimiter+1]:=str_pool[j];
1201      end;
1202    pool_ptr:=pool_ptr-ext_delimiter+area_delimiter+1;  {update |pool_ptr|}
1203    end;
1204  cur_ext:=slow_make_string;  {remake extension string}
1205@z
1206
1207@x [29.518] l.10042 - print_file_name: quote if spaces in names.
1208begin slow_print(a); slow_print(n); slow_print(e);
1209@y
1210var must_quote: boolean; {whether to quote the filename}
1211@!j:pool_pointer; {index into |str_pool|}
1212begin
1213must_quote:=false;
1214if a<>0 then begin
1215  j:=str_start(a);
1216  while (not must_quote) and (j<str_start(a+1)) do begin
1217    must_quote:=str_pool[j]=" "; incr(j);
1218  end;
1219end;
1220if n<>0 then begin
1221  j:=str_start(n);
1222  while (not must_quote) and (j<str_start(n+1)) do begin
1223    must_quote:=str_pool[j]=" "; incr(j);
1224  end;
1225end;
1226if e<>0 then begin
1227  j:=str_start(e);
1228  while (not must_quote) and (j<str_start(e+1)) do begin
1229    must_quote:=str_pool[j]=" "; incr(j);
1230  end;
1231end;
1232{FIXME: Alternative is to assume that any filename that has to be quoted has
1233 at least one quoted component...if we pick this, a number of insertions
1234 of |print_file_name| should go away.
1235|must_quote|:=((|a|<>0)and(|str_pool|[|str_start|(|a|)]=""""))or
1236              ((|n|<>0)and(|str_pool|[|str_start|(|n|)]=""""))or
1237              ((|e|<>0)and(|str_pool|[|str_start|(|e|)]=""""));}
1238if must_quote then print_char("""");
1239if a<>0 then
1240  for j:=str_start(a) to str_start(a+1)-1 do
1241    if so(str_pool[j])<>"""" then
1242      print_char(so(str_pool[j]));
1243if n<>0 then
1244  for j:=str_start(n) to str_start(n+1)-1 do
1245    if so(str_pool[j])<>"""" then
1246      print_char(so(str_pool[j]));
1247if e<>0 then
1248  for j:=str_start(e) to str_start(e+1)-1 do
1249    if so(str_pool[j])<>"""" then
1250      print_char(so(str_pool[j]));
1251if must_quote then print_char("""");
1252@z
1253
1254@x [29.519] l.10051 - have append_to_name skip quotes.
1255@d append_to_name(#)==begin c:=#; incr(k);
1256  if k<=file_name_size then name_of_file[k]:=xchr[c];
1257  end
1258@y
1259@d append_to_name(#)==begin c:=#; if not (c="""") then begin incr(k);
1260  if k<=file_name_size then name_of_file[k]:=xchr[c];
1261  end end
1262@z
1263
1264% [29.519] In pack_file_name, leave room for the extra null we append at
1265% the end of a filename.
1266@x [29.519] l.10047 - pack_file_name, leave room for the extra null
1267for j:=str_start(a) to str_start(a+1)-1 do append_to_name(so(str_pool[j]));
1268@y
1269if name_of_file then libc_free (name_of_file);
1270name_of_file:= xmalloc_array(char, 1 + length(a) + length(n) + length(e));
1271for j:=str_start(a) to str_start(a+1)-1 do append_to_name(so(str_pool[j]));
1272@z
1273
1274@x [29.519] l.10051 - pack_file_name, append the extra null
1275for k:=name_length+1 to file_name_size do name_of_file[k]:=' ';
1276@y
1277name_of_file[name_length+1]:=0;
1278@z
1279
1280@x [29.520] l.10060 - filenames: default format.
1281@d format_default_length=20 {length of the |TEX_format_default| string}
1282@d format_area_length=11 {length of its area part}
1283@d format_ext_length=4 {length of its `\.{.fmt}' part}
1284@d format_extension=".fmt" {the extension, as a \.{WEB} constant}
1285@y
1286Under {\mc UNIX} we don't give the area part, instead depending
1287on the path searching that will happen during file opening.  Also, the
1288length will be set in the main program.
1289
1290@d format_area_length=0 {length of its area part}
1291@d format_ext_length=4 {length of its `\.{.fmt}' part}
1292@d format_extension=".fmt" {the extension, as a \.{WEB} constant}
1293@z
1294
1295@x [29.521] l.10066 - filenames: default format, where `plain.fmt' is.
1296@!TEX_format_default:packed array[1..format_default_length] of char;
1297
1298@ @<Set init...@>=
1299TEX_format_default:='TeXformats:plain.fmt';
1300@y
1301@!format_default_length: integer;
1302@!TEX_format_default: ^char;
1303
1304@ We set the name of the default format file and the length of that name
1305in C, instead of Pascal, since we want them to depend on the name of the
1306program.
1307@z
1308
1309@x [29.523] l.10095 - Change to pack_buffered_name as with pack_file_name.
1310for j:=1 to n do append_to_name(TEX_format_default[j]);
1311@y
1312if name_of_file then libc_free (name_of_file);
1313name_of_file := xmalloc_array (char, 1 + n + (b - a + 1) + format_ext_length);
1314for j:=1 to n do append_to_name(TEX_format_default[j]);
1315@z
1316
1317@x [29.523] l.10100 - Change to pack_buffered_name as with pack_file_name.
1318for k:=name_length+1 to file_name_size do name_of_file[k]:=' ';
1319@y
1320name_of_file[name_length+1]:=0;
1321@z
1322
1323@x [29.524] l.10118 - Format file opening: only try once, with path searching.
1324  pack_buffered_name(0,loc,j-1); {try first without the system file area}
1325  if w_open_in(fmt_file) then goto found;
1326  pack_buffered_name(format_area_length,loc,j-1);
1327    {now try the system format file area}
1328  if w_open_in(fmt_file) then goto found;
1329@y
1330  pack_buffered_name(0,loc,j-1); {Kpathsea does everything}
1331  if w_open_in(fmt_file) then goto found;
1332@z
1333
1334@x [29.524] l.10124 - replace `PLAIN' in error messages with `default'.
1335  wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.');
1336@y
1337  wterm ('Sorry, I can''t find the format `');
1338  fputs (name_of_file + 1, stdout);
1339  wterm ('''; will try `');
1340  fputs (TEX_format_default + 1, stdout);
1341  wterm_ln ('''.');
1342@z
1343
1344@x [29.524] l.10132 - replace `PLAIN' in error messages with `default'.
1345  wterm_ln('I can''t find the PLAIN format file!');
1346@.I can't find PLAIN...@>
1347@y
1348  wterm ('I can''t find the format file `');
1349  fputs (TEX_format_default + 1, stdout);
1350  wterm_ln ('''!');
1351@.I can't find the format...@>
1352@z
1353
1354@x [29.525] l.10163 - make_name_string
1355@p function make_name_string:str_number;
1356var k:1..file_name_size; {index into |name_of_file|}
1357begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings)or
1358 (cur_length>0) then
1359  make_name_string:="?"
1360else  begin for k:=1 to name_length do append_char(name_of_file[k]);
1361  make_name_string:=make_string;
1362  end;
1363@y
1364@p function make_name_string:str_number;
1365var k:1..file_name_size; {index into |name_of_file|}
1366save_area_delimiter, save_ext_delimiter: pool_pointer;
1367save_name_in_progress, save_stop_at_space: boolean;
1368begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings)or
1369 (cur_length>0) then
1370  make_name_string:="?"
1371else  begin for k:=1 to name_length do append_char(name_of_file[k]);
1372  make_name_string:=make_string;
1373  {At this point we also set |cur_name|, |cur_ext|, and |cur_area| to
1374   match the contents of |name_of_file|.}
1375  save_area_delimiter:=area_delimiter; save_ext_delimiter:=ext_delimiter;
1376  save_name_in_progress:=name_in_progress; save_stop_at_space:=stop_at_space;
1377  name_in_progress:=true;
1378  begin_name;
1379  stop_at_space:=false;
1380  k:=1;
1381  while (k<=name_length)and(more_name(name_of_file[k])) do
1382    incr(k);
1383  stop_at_space:=save_stop_at_space;
1384  end_name;
1385  name_in_progress:=save_name_in_progress;
1386  area_delimiter:=save_area_delimiter; ext_delimiter:=save_ext_delimiter;
1387  end;
1388@z
1389
1390@x [29.526] l.10194 - stop scanning file name if we're at end-of-line.
1391  if not more_name(cur_chr) then goto done;
1392@y
1393  {If |cur_chr| is a space and we're not scanning a token list, check
1394   whether we're at the end of the buffer. Otherwise we end up adding
1395   spurious spaces to file names in some cases.}
1396  if (cur_chr=" ") and (state<>token_list) and (loc>limit) then goto done;
1397  if not more_name(cur_chr) then goto done;
1398@z
1399
1400@x [29.530] l.10245 - prompt_file_name: prevent empty filenames.
1401var k:0..buf_size; {index into |buffer|}
1402@y
1403var k:0..buf_size; {index into |buffer|}
1404@!saved_cur_name:str_number; {to catch empty terminal input}
1405@!saved_cur_ext:str_number; {to catch empty terminal input}
1406@!saved_cur_area:str_number; {to catch empty terminal input}
1407@z
1408
1409@x [29.530] l.10252 - prompt_file_name: No default extension is TeX input file.
1410if e=".tex" then show_context;
1411@y
1412if (e=".tex") or (e="") then show_context;
1413print_ln; print_c_string(prompt_file_name_help_msg);
1414if (e<>"") then
1415  begin
1416    print("; default file extension is `"); print(e); print("'");
1417  end;
1418print(")"); print_ln;
1419@z
1420
1421@x [29.530] l.10258 - prompt_file_name: prevent empty filenames.
1422clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>;
1423if cur_ext="" then cur_ext:=e;
1424@y
1425saved_cur_name:=cur_name;
1426saved_cur_ext:=cur_ext;
1427saved_cur_area:=cur_area;
1428clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>;
1429if (length(cur_name)=0) and (cur_ext="") and (cur_area="") then
1430  begin
1431    cur_name:=saved_cur_name;
1432    cur_ext:=saved_cur_ext;
1433    cur_area:=saved_cur_area;
1434  end
1435else
1436  if cur_ext="" then cur_ext:=e;
1437@z
1438
1439@x [29.532] l.10263 - avoid conflict, `logname' in <unistd.h> on some systems.
1440@ Here's an example of how these conventions are used. Whenever it is time to
1441ship out a box of stuff, we shall use the macro |ensure_dvi_open|.
1442
1443@y
1444@ Here's an example of how these conventions are used. Whenever it is time to
1445ship out a box of stuff, we shall use the macro |ensure_dvi_open|.
1446
1447@d log_name == texmf_log_name
1448@z
1449
1450@x [29.534] l.10285 - Adjust for C string conventions.
1451@!months:packed array [1..36] of char; {abbreviations of month names}
1452@y
1453@!months:const_cstring;
1454@z
1455
1456@x [29.534] l. - Send the job_name to the file recorder.
1457begin old_setting:=selector;
1458if job_name=0 then job_name:="texput";
1459@y
1460begin old_setting:=selector;
1461if job_name=0 then job_name:=get_job_name("texput");
1462pack_job_name(".ofl");
1463recorder_change_filename(stringcast(name_of_file+1));
1464@z
1465
1466@x [29.536] l.10324 - Print rest of banner.
1467begin wlog(eTeX_banner);
1468@y
1469begin wlog(eTeX_banner);
1470wlog(version_string);
1471@z
1472
1473@x [29.536] l.10327 - Adjust for C string conventions.
1474months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
1475@y
1476months := ' JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
1477@z
1478
1479% [29.537] Use a path when calling a_open_in to do a \input; also, try
1480% to open the file with and without the `.tex' extension, regardless of
1481% whether the file already has an extension.  This allows filenames like
1482% `foo' and `foo.bar.tex', as well as `foo.tex' and `foo.bar'.
1483@x [29.537] l.10338 - start_input
1484begin scan_file_name; {set |cur_name| to desired file name}
1485if cur_ext="" then cur_ext:=".tex";
1486pack_cur_name;
1487loop@+  begin begin_file_reading; {set up |cur_file| and new level of input}
1488  if a_open_in(cur_file) then goto done;
1489  if cur_area="" then
1490    begin pack_file_name(cur_name,TEX_area,cur_ext);
1491    if a_open_in(cur_file) then goto done;
1492    end;
1493@y
1494var temp_str: str_number;
1495begin scan_file_name; {set |cur_name| to desired file name}
1496pack_cur_name;
1497loop@+  begin begin_file_reading; {set up |cur_file| and new level of input}
1498  tex_input_type := 1; {Tell |open_input| we are \.{\\input}.}
1499  {Kpathsea tries all the various ways to get the file.}
1500  if kpse_in_name_ok(name_of_file+1)
1501     and a_open_in(cur_file, kpse_tex_format) then
1502    goto done;
1503@z
1504
1505@x [29.537] l.10348 - start_input: don't force ".tex" extension.
1506  prompt_file_name("input file name",".tex");
1507@y
1508  prompt_file_name("input file name","");
1509@z
1510
1511@x [29.537] l.10350 - start_input: string recycling
1512done: name:=a_make_name_string(cur_file);
1513@y
1514done: name:=a_make_name_string(cur_file);
1515if name=str_ptr-1 then {we can try to conserve string pool space now}
1516  begin temp_str:=search_string(name);
1517  if temp_str>0 then
1518    begin name:=temp_str; flush_string;
1519    end;
1520  end;
1521@z
1522
1523@x [29.537] l.10352 - start_input: use different heuristic for initex.
1524  begin job_name:=cur_name; open_log_file;
1525@y
1526  begin job_name:=get_job_name(cur_name); open_log_file;
1527@z
1528
1529@x [29.537] l.10359 - start_input: don't return filename to string pool.
1530if name=str_ptr-1 then {we can conserve string pool space now}
1531  begin flush_string; name:=cur_name;
1532  end;
1533@y
1534@z
1535
1536@x [30.560] l.10898 - Check lengths
1537@!file_opened:boolean; {was |tfm_file| successfully opened?}
1538@y
1539@!name_too_long:boolean; {|nom| or |aire| exceeds 255 bytes?}
1540@!file_opened:boolean; {was |tfm_file| successfully opened?}
1541@z
1542
1543@x [30.561] l.10939 - Check lengths
1544else print(" not loadable: Metric (TFM/OFM) file not found");
1545@y
1546else if name_too_long then print(" not loadable: Metric (TFM/OFM) file name too long")
1547else print(" not loadable: Metric (TFM/OFM) file not found");
1548@z
1549
1550@x [30.563] l.10960 - Check lengths
1551file_opened:=false;
1552@y
1553file_opened:=false;
1554name_too_long:=(length(nom)>255)or(length(aire)>255);
1555if name_too_long then abort;
1556@z
1557
1558@x [30.563] l.10961 - Don't use TEX_font_area.
1559if aire="" then pack_file_name(nom,TEX_font_area,".ofm")
1560else pack_file_name(nom,aire,".ofm");
1561if not b_open_in(tfm_file) then abort;
1562@y
1563{|kpse_find_file| will append the |".ofm"| or |".tfm"|,
1564 and avoid searching the disk before the font alias files as well.}
1565pack_file_name(nom,aire,"");
1566if not ofm_open_in(tfm_file) then abort;
1567@z
1568
1569% [30.564] Reading the tfm file.  As a special case, whenever we open a
1570% tfm file, we read its first byte into `tfm_temp' right away.  TeX
1571% looks at `fbyte' before calling `fget', so it ends up seeing every
1572% byte.  This is Pascal-like I/O.
1573@x [30.564] l.10956 - reading the tfm file, define fget & fbyte
1574@d fget==get(tfm_file)
1575@d fbyte==tfm_file^
1576@y
1577@d fget==tfm_temp:=getc(tfm_file)
1578@d fbyte==tfm_temp
1579@z
1580
1581% [32.575] We only want `eof' on the TFM file to be true if we
1582% previously had EOF, not if we're at EOF now.  This is like `feof', and
1583% unlike our implementation of `eof' elsewhere.
1584@x [32.575] l.11161 - Reading the tfm file, replace eof() by feof().
1585if eof(tfm_file) then abort;
1586@y
1587if feof(tfm_file) then abort;
1588@z
1589
1590@x [32.595] l.11860 - texarray
1591@!dvi_buf:array[dvi_index] of real_eight_bits; {buffer for \.{DVI} output}
1592@!half_buf:dvi_index; {half of |dvi_buf_size|}
1593@!dvi_limit:dvi_index; {end of the current half buffer}
1594@!dvi_ptr:dvi_index; {the next available buffer address}
1595@y
1596@!dvi_buf:^real_eight_bits; {buffer for \.{DVI} output}
1597@!half_buf:integer; {half of |dvi_buf_size|}
1598@!dvi_limit:integer; {end of the current half buffer}
1599@!dvi_ptr:integer; {the next available buffer address}
1600@z
1601
1602@x [32.597] l.11886 - write_dvi done in C.
1603@p procedure write_dvi(@!a,@!b:dvi_index);
1604var k:dvi_index;
1605begin for k:=a to b do write(dvi_file,dvi_buf[k]);
1606end;
1607@y
1608In C, we use a macro to call |fwrite| or |write| directly, writing all
1609the bytes in one shot.  Much better even than writing four
1610bytes at a time.
1611@z
1612
1613@x [32.601] l.11911 - check dvi file size
1614each time, we use the macro |dvi_out|.
1615@y
1616each time, we use the macro |dvi_out|.
1617
1618The length of |dvi_file| should not exceed |@"7FFFFFFF|; we set |cur_s:=-2|
1619to prevent further \.{DVI} output causing infinite recursion.
1620@z
1621
1622@x [32.601] l.11918 - dvi_swap: check dvi file size
1623begin if dvi_limit=dvi_buf_size then
1624@y
1625begin if dvi_ptr>(@"7FFFFFFF-dvi_offset) then
1626  begin cur_s:=-2;
1627  fatal_error("dvi length exceeds ""7FFFFFFF");
1628@.dvi length exceeds...@>
1629  end;
1630if dvi_limit=dvi_buf_size then
1631@z
1632
1633@x [32.602] l.11932 -  empty the last bytes: check dvi file size
1634if dvi_ptr>0 then write_dvi(0,dvi_ptr-1)
1635@y
1636if dvi_ptr>(@"7FFFFFFF-dvi_offset) then
1637  begin cur_s:=-2;
1638  fatal_error("dvi length exceeds ""7FFFFFFF");
1639@.dvi length exceeds...@>
1640  end;
1641if dvi_ptr>0 then write_dvi(0,dvi_ptr-1)
1642@z
1643
1644@x [32.617] l.12261 - Use output_comment if the user set it. Assume it's short enough.
1645  old_setting:=selector; selector:=new_string;
1646@y
1647if output_comment then
1648  begin l:=strlen(output_comment); dvi_out(l);
1649  for s:=0 to l-1 do dvi_out(output_comment[s]);
1650  end
1651else begin {the default code is unchanged}
1652  old_setting:=selector; selector:=new_string;
1653@z
1654
1655@x [32.617] l.12268 - Use output_comment if the user set it.
1656  pool_ptr:=str_start(str_ptr); {flush the current string}
1657@y
1658  pool_ptr:=str_start(str_ptr); {flush the current string}
1659end;
1660@z
1661
1662% We output each portion of the page as we get to it, if we are using
1663% IPC, so that the previewer (TeXView) can display it immediately. [SPM]
1664@x [32.640] l.12690 - IPC
1665dvi_out(eop); incr(total_pages); cur_s:=-1;
1666@y
1667dvi_out(eop); incr(total_pages); cur_s:=-1;
1668ifdef ('IPC')
1669if ipc_on>0 then
1670  begin if dvi_limit=half_buf then
1671    begin write_dvi(half_buf, dvi_buf_size-1);
1672    flush_dvi;
1673    dvi_gone:=dvi_gone+half_buf;
1674    end;
1675  if dvi_ptr>(@"7FFFFFFF-dvi_offset) then
1676    begin cur_s:=-2;
1677    fatal_error("dvi length exceeds ""7FFFFFFF");
1678@.dvi length exceeds...@>
1679    end;
1680  if dvi_ptr>0 then
1681    begin write_dvi(0, dvi_ptr-1);
1682    flush_dvi;
1683    dvi_offset:=dvi_offset+dvi_ptr; dvi_gone:=dvi_gone+dvi_ptr;
1684    end;
1685  dvi_ptr:=0; dvi_limit:=dvi_buf_size;
1686  ipc_page(dvi_gone);
1687  end;
1688endif ('IPC');
1689@z
1690
1691@x [32.645] l.12766 - check dvi file size
1692else  begin dvi_out(post); {beginning of the postamble}
1693@y
1694else if cur_s<>-2 then
1695  begin dvi_out(post); {beginning of the postamble}
1696@z
1697
1698@x [32.645] l.12775 - Use dvi_offset instead of dvi_buf_size with IPC stuff.
1699  k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's}
1700@y
1701ifdef ('IPC')
1702  k:=7-((3+dvi_offset+dvi_ptr) mod 4); {the number of 223's}
1703endif ('IPC')
1704ifndef ('IPC')
1705  k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's}
1706endifn ('IPC')
1707@z
1708
1709@x [32.642] l.12773 - use print_file_name
1710  print_nl("Output written on "); slow_print(output_file_name);
1711@y
1712  print_nl("Output written on "); print_file_name(0, output_file_name, 0);
1713@z
1714
1715@x [42.920] l.18068 - bigtrie: allow larger hyphenation tries.
1716@!trie_pointer=0..trie_size; {an index into |trie|}
1717@y
1718@!trie_pointer=0..ssup_trie_size; {an index into |trie|}
1719@z
1720
1721@x [42.921] l.18075 - bigtrie: allow larger hyphenation tries.
1722@!trie:array[trie_pointer] of two_halves; {|trie_link|, |trie_char|, |trie_op|}
1723@y
1724{We will dynamically allocate this arrays.}
1725@!trie:^two_halves; {|trie_link|}
1726@z
1727
1728%%%%%%%% dynamic hyph_size
1729@x 18126 m.925
1730different from $\alpha$, we can conclude that $\alpha$ is not in the table.
1731@y  18126
1732different from $\alpha$, we can conclude that $\alpha$ is not in the table.
1733This is a clever scheme which saves the need for a hash link array.
1734However, it is difficult to increase the size of the hyphen exception
1735arrays. To make this easier, the ordered hash has been replaced by
1736a simple hash, using an additional array |hyph_link|. The value
1737|0| in |hyph_link[k]| means that there are no more entries corresponding
1738to the specific hash chain. When |hyph_link[k]>0|, the next entry in
1739the hash chain is |hyph_link[k]-1|. This value is used because the
1740arrays start at |0|.
1741@z
1742
1743%%%%%%%% dynamic hyph_size
1744@x 18134 m.925
1745@!hyph_pointer=0..hyph_size; {an index into the ordered hash table}
1746@y  18134
1747@!hyph_pointer=0..ssup_hyph_size; {index into hyphen exceptions hash table;
1748                     enlarging this requires changing (un)dump code}
1749@z
1750
1751%%%%%%%% dynamic hyph_size
1752@x 18137 m.926
1753@!hyph_word:array[hyph_pointer] of str_number; {exception words}
1754@!hyph_list:array[hyph_pointer] of pointer; {lists of hyphen positions}
1755@!hyph_count:hyph_pointer; {the number of words in the exception dictionary}
1756@y  18139
1757@!hyph_word: ^str_number; {exception words}
1758@!hyph_list: ^pointer; {list of hyphen positions}
1759@!hyph_link: ^hyph_pointer; {link array for hyphen exceptions hash table}
1760@!hyph_count:integer; {the number of words in the exception dictionary}
1761@!hyph_next:integer; {next free slot in hyphen exceptions hash table}
1762@z
1763
1764%%%%%%%% dynamic hyph_size
1765@x 18145 m.928
1766for z:=0 to hyph_size do
1767  begin hyph_word[z]:=0; hyph_list[z]:=null;
1768  end;
1769hyph_count:=0;
1770@y  18148
1771for z:=0 to hyph_size do
1772  begin hyph_word[z]:=0; hyph_list[z]:=null; hyph_link[z]:=0;
1773  end;
1774hyph_count:=0;
1775hyph_next:=hyph_prime+1; if hyph_next>hyph_size then hyph_next:=hyph_prime;
1776@z
1777
1778%%%%%%%% dynamic hyph_size
1779@x 18163 m.930
1780h:=hc[1]; incr(hn); hc[hn]:=cur_lang;
1781for j:=2 to hn do h:=(h+h+hc[j]) mod hyph_size;
1782loop@+  begin @<If the string |hyph_word[h]| is less than \(hc)|hc[1..hn]|,
1783    |goto not_found|; but if the two strings are equal,
1784    set |hyf| to the hyphen positions and |goto found|@>;
1785  if h>0 then decr(h)@+else h:=hyph_size;
1786  end;
1787not_found: decr(hn)
1788@y  18170
1789h:=hc[1]; incr(hn); hc[hn]:=cur_lang;
1790for j:=2 to hn do h:=(h+h+hc[j]) mod hyph_prime;
1791loop@+  begin @<If the string |hyph_word[h]| is less than \(hc)|hc[1..hn]|,
1792    |goto not_found|; but if the two strings are equal,
1793    set |hyf| to the hyphen positions and |goto found|@>;
1794  h:=hyph_link[h]; if h=0 then goto not_found;
1795  decr(h);
1796  end;
1797not_found: decr(hn)
1798@z
1799
1800%%%%%%%% dynamic hyph_size
1801@x 18172 m.931
1802@ @<If the string |hyph_word[h]| is less than \(hc)...@>=
1803k:=hyph_word[h]; if k=0 then goto not_found;
1804if length(k)<hn then goto not_found;
1805if length(k)=hn then
1806  begin j:=1; u:=str_start(k);
1807  repeat if so(str_pool[u])<hc[j] then goto not_found;
1808  if so(str_pool[u])>hc[j] then goto done;
1809  incr(j); incr(u);
1810  until j>hn;
1811  @<Insert hyphens as specified in |hyph_list[h]|@>;
1812  decr(hn); goto found;
1813  end;
1814done:
1815@y  18184
1816@ @<If the string |hyph_word[h]| is less than \(hc)...@>=
1817{This is now a simple hash list, not an ordered one, so
1818the module title is no longer descriptive.}
1819k:=hyph_word[h]; if k=0 then goto not_found;
1820if length(k)=hn then
1821  begin j:=1; u:=str_start(k);
1822  repeat
1823  if so(str_pool[u])<>hc[j] then goto done;
1824  incr(j); incr(u);
1825  until j>hn;
1826  @<Insert hyphens as specified in |hyph_list[h]|@>;
1827  decr(hn); goto found;
1828  end;
1829done:
1830@z
1831
1832% The GNU C compiler complains of unused variables.
1833@x
1834@!s,@!t:str_number; {strings being compared or stored}
1835@y
1836@!s:str_number; {strings being compared or stored}
1837@z
1838
1839%%%%%%%% dynamic hyph_size
1840@x 18274 m.939
1841  begin h:=(h+h+hc[j]) mod hyph_size;
1842@y  18274
1843  begin h:=(h+h+hc[j]) mod hyph_prime;
1844@z
1845
1846%%%%%%%% dynamic hyph_size
1847@x 18281 m.940
1848@ @<Insert the \(p)pair |(s,p)|...@>=
1849if hyph_count=hyph_size then overflow("exception dictionary",hyph_size);
1850@:TeX capacity exceeded exception dictionary}{\quad exception dictionary@>
1851incr(hyph_count);
1852while hyph_word[h]<>0 do
1853  begin @<If the string |hyph_word[h]| is less than \(or)or equal to
1854  |s|, interchange |(hyph_word[h],hyph_list[h])| with |(s,p)|@>;
1855  if h>0 then decr(h)@+else h:=hyph_size;
1856  end;
1857hyph_word[h]:=s; hyph_list[h]:=p
1858@y  18290
1859@ @<Insert the \(p)pair |(s,p)|...@>=
1860  if hyph_next <= hyph_prime then
1861     while (hyph_next>0) and (hyph_word[hyph_next-1]>0) do decr(hyph_next);
1862if (hyph_count=hyph_size)or(hyph_next=0) then
1863   overflow("exception dictionary",hyph_size);
1864@:TeX capacity exceeded exception dictionary}{\quad exception dictionary@>
1865incr(hyph_count);
1866while hyph_word[h]<>0 do
1867  begin @<If the string |hyph_word[h]| is less than \(or)or equal to
1868  |s|, interchange |(hyph_word[h],hyph_list[h])| with |(s,p)|@>;
1869  if hyph_link[h]=0 then
1870  begin
1871    hyph_link[h]:=hyph_next;
1872    if hyph_next >= hyph_size then hyph_next:=hyph_prime;
1873    if hyph_next > hyph_prime then incr(hyph_next);
1874  end;
1875  h:=hyph_link[h]-1;
1876  end;
1877
1878found: hyph_word[h]:=s; hyph_list[h]:=p
1879@z
1880
1881%%%%%%%% dynamic hyph_size
1882@x 18292 m.941
1883@ @<If the string |hyph_word[h]| is less than \(or)...@>=
1884k:=hyph_word[h];
1885if length(k)<length(s) then goto found;
1886if length(k)>length(s) then goto not_found;
1887u:=str_start(k); v:=str_start(s);
1888repeat if str_pool[u]<str_pool[v] then goto found;
1889if str_pool[u]>str_pool[v] then goto not_found;
1890incr(u); incr(v);
1891until u=str_start(k+1);
1892found:q:=hyph_list[h]; hyph_list[h]:=p; p:=q;@/
1893t:=hyph_word[h]; hyph_word[h]:=s; s:=t;
1894not_found:
1895@y  18303
1896@ @<If the string |hyph_word[h]| is less than \(or)...@>=
1897{This is now a simple hash list, not an ordered one, so
1898the module title is no longer descriptive.}
1899k:=hyph_word[h];
1900if length(k)<>length(s) then goto not_found;
1901u:=str_start(k); v:=str_start(s);
1902repeat if str_pool[u]<>str_pool[v] then goto not_found;
1903incr(u); incr(v);
1904until u=str_start(k+1);
1905{repeat hyphenation exception; flushing old data}
1906flush_string; s:=hyph_word[h]; {avoid |slow_make_string|!}
1907decr(hyph_count);
1908{ We could also |flush_list(hyph_list[h]);|, but it interferes
1909  with \.{trip.log}. }
1910goto found;
1911not_found:
1912@z
1913
1914@x [43.943] l.18346 - web2c can't parse negative lower bounds in arrays.  Sorry.
1915@!init@! trie_op_hash:array[-trie_op_size..trie_op_size] of 0..trie_op_size;
1916@y
1917@!init@! trie_op_hash:array[neg_trie_op_size..trie_op_size] of 0..trie_op_size;
1918@z
1919
1920@x [43.944] l.18365 - web2c can't parse negative lower bounds in arrays.  Sorry
1921var h:-trie_op_size..trie_op_size; {trial hash location}
1922@y
1923var h:neg_trie_op_size..trie_op_size; {trial hash location}
1924@z
1925
1926@x [43.944] l.18370 - Another casting problem, and use |neg_trie_op_size|.
1927begin h:=abs(n+313*d+361*v+1009*cur_lang) mod (trie_op_size+trie_op_size)
1928  - trie_op_size;
1929@y
1930begin h:=abs(n+313*d+361*v+1009*cur_lang) mod (trie_op_size-neg_trie_op_size)
1931  + neg_trie_op_size;
1932@z
1933
1934@x [43.947] l.18438 - Dynamically allocate arrays, and a casting problem.
1935@!init @!trie_c:packed array[trie_pointer] of ASCII_code;
1936  {characters to match}
1937@t\hskip10pt@>@!trie_o:packed array[trie_pointer] of quarterword;
1938  {operations to perform}
1939@t\hskip10pt@>@!trie_l:packed array[trie_pointer] of trie_pointer;
1940  {left subtrie links}
1941@t\hskip10pt@>@!trie_r:packed array[trie_pointer] of trie_pointer;
1942  {right subtrie links}
1943@t\hskip10pt@>@!trie_ptr:trie_pointer; {the number of nodes in the trie}
1944@t\hskip10pt@>@!trie_hash:packed array[trie_pointer] of trie_pointer;
1945  {used to identify equivalent subtries}
1946tini
1947@y
1948@!init @!trie_c:^ASCII_code;
1949  {characters to match}
1950@t\hskip10pt@>@!trie_o:^quarterword;
1951  {operations to perform}
1952@t\hskip10pt@>@!trie_l:^trie_pointer;
1953  {left subtrie links}
1954@t\hskip10pt@>@!trie_r:^trie_pointer;
1955  {right subtrie links}
1956@t\hskip10pt@>@!trie_ptr:trie_pointer; {the number of nodes in the trie}
1957@t\hskip10pt@>@!trie_hash:^trie_pointer;
1958  {used to identify equivalent subtries}
1959tini
1960@z
1961
1962@x [43.590] l.18524 - Dynamically allocate & larger tries.
1963@!init@!trie_taken:packed array[1..trie_size] of boolean;
1964  {does a family start here?}
1965@t\hskip10pt@>@!trie_min:array[ASCII_code] of trie_pointer;
1966  {the first possible slot for each character}
1967@t\hskip10pt@>@!trie_max:trie_pointer; {largest location used in |trie|}
1968@t\hskip10pt@>@!trie_not_ready:boolean; {is the trie still in linked form?}
1969tini
1970@y
1971@!init@!trie_taken: ^boolean;
1972  {does a family start here?}
1973@t\hskip10pt@>@!trie_min:^trie_pointer;
1974  {the first possible slot for each character}
1975@t\hskip10pt@>@!trie_max:trie_pointer; {largest location used in |trie|}
1976@t\hskip10pt@>@!trie_not_ready:boolean; {is the trie still in linked form?}
1977tini
1978@z
1979
1980@x [43.951] l.18539 - Dynamically allocate.
1981trie_not_ready:=true; trie_root:=0; trie_c[0]:=si(0); trie_ptr:=0;
1982@y
1983trie_not_ready:=true;
1984@z
1985
1986%%
1987%% We can rewrite the original code after "main_loop_move+2" upto the
1988%% "tail_append(lig_stack)" in module 1036 as
1989%%
1990%
1991% main_loop_move+2:
1992% if font_bc[main_f]<=cur_chr then
1993%  if cur_chr<=font_ec[main_f] then
1994%    begin  main_i:=char_info(main_f)(cur_l);
1995%    if char_exists(main_i) goto main_loop_move+3;
1996%    end;
1997% char_warning(main_f,cur_chr); free_avail(lig_stack); goto big_switch;
1998% main_loop_move+3:
1999% tail_append(lig_stack) {|main_loop_lookahead| is next}
2000%
2001
2002@x [49.1252] l.23230 - INI = VIR, so have to do runtime test.
2003hyph_data: if cur_chr=1 then
2004    begin @!init new_patterns; goto done;@;@+tini@/
2005@y  23215
2006hyph_data: if cur_chr=1 then
2007    begin @!init if ini_version then
2008      begin new_patterns; goto done; end; @;@+tini@/
2009@z
2010
2011@x
2012@!flushable_string:str_number; {string not yet referenced}
2013@y
2014@z
2015
2016% undo Knuth's change because
2017%   a) the string is already replaced in |scan_file_name| and therefore
2018%   b) the wrong string will get flushed!!!
2019%
2020@x [49.1260] l.23331 new_font: string recycling -- already done
2021flushable_string:=str_ptr-1;
2022@y
2023@z
2024
2025% If you don't want to remove code with the following two changes,
2026% please replace the former change by
2027%
2028% @x
2029% flushable_string:=str_ptr-1;
2030% @y
2031% if cur_name=str_ptr-1 then
2032%   flushable_string:=str_ptr-1
2033% else
2034%   flushable_string:=str_ptr;  {number of a non-existing}
2035% @z
2036%
2037% otherwise the wrong string will get removed by |flush_string|!!
2038%
2039@x [49.1260] l.23334 new_font: string recycling -- already done
2040    begin if cur_name=flushable_string then
2041      begin flush_string; cur_name:=font_name(f);
2042      end;
2043    if s>0 then
2044@y
2045    begin if s>0 then
2046@z
2047
2048@x [49.1265] if batchmode, mktex... scripts should be silent.
2049interaction:=cur_chr;
2050@y
2051interaction:=cur_chr;
2052if interaction = batch_mode
2053then kpse_make_tex_discard_errors := 1
2054else kpse_make_tex_discard_errors := 0;
2055@z
2056
2057@x [49.1275] l.23441 - Same stuff as for \input, this time for \openin.
2058  if cur_ext="" then cur_ext:=".tex";
2059  pack_cur_name;
2060  if a_open_in(read_file[n]) then read_open[n]:=just_open;
2061@y
2062  pack_cur_name;
2063  tex_input_type:=0; {Tell |open_input| we are \.{\\openin}.}
2064  if kpse_in_name_ok(name_of_file+1)
2065      and a_open_in(read_file[n], kpse_tex_format) then
2066     read_open[n]:=just_open;
2067@z
2068
2069@x [50.1301] l.23679 - INI = VIR, so runtime test.
2070format_ident:=" (INIALEPH)";
2071@y
2072if ini_version then format_ident:=" (INIALEPH)";
2073@z
2074
2075% The GNU C compiler complains of unused variables.
2076% Add format_engine.
2077@x [50.1302] l.23690 - Eliminate now-unused variable `w' in `store_fmt_file'.
2078var j,@!k,@!l:integer; {all-purpose indices}
2079@!p,@!q: pointer; {all-purpose pointers}
2080@!x: integer; {something to dump}
2081@!w: four_quarters; {four ASCII codes}
2082@y
2083var j,@!k:integer; {all-purpose indices}
2084@!p,@!q: pointer; {all-purpose pointers}
2085@!x: integer; {something to dump}
2086@!format_engine: ^char;
2087@z
2088
2089@x [50.1303] l.23722 - Ditto, for `load_fmt_file'.
2090@!w: four_quarters; {four ASCII codes}
2091@y
2092@!format_engine: ^char;
2093@z
2094
2095@x [50.1305] l.23751 - Do dumping and undumping of fmt files in C.
2096@d dump_wd(#)==begin fmt_file^:=#; put(fmt_file);@+end
2097@d dump_int(#)==begin fmt_file^.int:=#; put(fmt_file);@+end
2098@d dump_hh(#)==begin fmt_file^.hh:=#; put(fmt_file);@+end
2099@d dump_qqqq(#)==begin fmt_file^.qqqq:=#; put(fmt_file);@+end
2100@y
2101@z
2102@x [1306]
2103@d undump_wd(#)==begin get(fmt_file); #:=fmt_file^;@+end
2104@d undump_int(#)==begin get(fmt_file); #:=fmt_file^.int;@+end
2105@d undump_hh(#)==begin get(fmt_file); #:=fmt_file^.hh;@+end
2106@d undump_qqqq(#)==begin get(fmt_file); #:=fmt_file^.qqqq;@+end
2107@y
2108@z
2109@x [still 1306] debug format file
2110@d undump_size_end_end(#)==too_small(#)@+else undump_end_end
2111@y
2112@d format_debug_end(#)==
2113    write_ln (stderr, ' = ', #);
2114  end;
2115@d format_debug(#)==
2116  if debug_format_file then begin
2117    write (stderr, 'fmtdebug:', #);
2118    format_debug_end
2119@d undump_size_end_end(#)==
2120  too_small(#)@+else format_debug (#)(x); undump_end_end
2121@z
2122
2123@x [50,1307] l.23779 - texarray
2124dump_int(@$);@/
2125@y
2126dump_int(@"57325458);  {Web2C \TeX's magic constant: "W2TX"}
2127{Align engine to 4 bytes with one or more trailing NUL}
2128x:=strlen(engine_name);
2129format_engine:=xmalloc_array(char,x+4);
2130strcpy(format_engine, engine_name);
2131for k:=x to x+3 do format_engine[k]:=0;
2132x:=x+4-(x mod 4);
2133dump_int(x);dump_things(format_engine[0], x);
2134libc_free(format_engine);@/
2135dump_int(@$);@/
2136dump_int(max_halfword);@/
2137@z
2138
2139%%%%%%%% dynamic hyph_size
2140@x 23784 m.1307
2141dump_int(hyph_size)
2142@y  23784
2143dump_int(hyph_prime)
2144@z
2145
2146@x [50.1308] l.23793 - texarray
2147x:=fmt_file^.int;
2148if x<>@$ then goto bad_fmt; {check that strings are the same}
2149@/@<Undump the \eTeX\ state@>@/
2150undump_int(x);
2151if x<>mem_bot then goto bad_fmt;
2152undump_int(x);
2153if x<>mem_top then goto bad_fmt;
2154@y
2155@+init
2156if ini_version then
2157  begin libc_free(str_pool); libc_free(str_start_ar); libc_free(yzmem);
2158  end;
2159@+tini
2160undump_int(x);
2161format_debug('format magic number')(x);
2162if x<>@"57325458 then goto bad_fmt; {not a format file}
2163undump_int(x);
2164format_debug('engine name size')(x);
2165if (x<0) or (x>256) then goto bad_fmt; {corrupted format file}
2166format_engine:=xmalloc_array(char, x);
2167undump_things(format_engine[0], x);
2168format_engine[x-1]:=0; {force string termination, just in case}
2169if strcmp(engine_name, format_engine) then
2170  begin wake_up_terminal;
2171  wterm_ln('---! ', stringcast(name_of_file+1), ' was written by ', format_engine);
2172  libc_free(format_engine);
2173  goto bad_fmt;
2174end;
2175libc_free(format_engine);
2176undump_int(x);
2177format_debug('string pool checksum')(x);
2178if x<>@$ then begin {check that strings are the same}
2179  wake_up_terminal;
2180  wterm_ln('---! ', stringcast(name_of_file+1), ' doesn''t match ', pool_name);
2181  goto bad_fmt;
2182end;
2183undump_int(x);
2184if x<>max_halfword then goto bad_fmt; {check |max_halfword|}
2185@/@<Undump the \eTeX\ state@>@/
2186
2187undump_int(x); format_debug ('mem_bot')(x);
2188if x<>mem_bot then goto bad_fmt;
2189undump_int(mem_top); format_debug ('mem_top')(mem_top);
2190if mem_bot+1100>mem_top then goto bad_fmt;
2191
2192
2193head:=contrib_head; tail:=contrib_head;
2194     page_tail:=page_head;  {page initialization}
2195
2196mem_min := mem_bot - extra_mem_bot;
2197mem_max := mem_top + extra_mem_top;
2198
2199yzmem:=xmalloc_array (memory_word, mem_max - mem_min + 1);
2200zmem := yzmem - mem_min;   {this pointer arithmetic fails with some compilers}
2201mem := zmem;
2202@z
2203
2204%%%%%%%% dynamic hyph_size
2205@x 23804 m.1308
2206if x<>hyph_size then goto bad_fmt
2207@y  23804
2208if x<>hyph_prime then goto bad_fmt
2209@z
2210
2211% [1309] Make dumping/undumping more efficient by doing whole arrays at
2212% a time, via fread/fwrite in texmfmp.c.
2213@x [50.1309] l.23814 - Make dumping/undumping more efficient.
2214for k:=too_big_char to str_ptr do dump_int(str_start(k));
2215k:=0;
2216while k+4<pool_ptr do
2217  begin dump_four_ASCII; k:=k+4;
2218  end;
2219k:=pool_ptr-4; dump_four_ASCII;
2220@y
2221dump_things(str_start(too_big_char), str_ptr-too_big_char+1);
2222dump_things(str_pool[0], pool_ptr);
2223@z
2224
2225@x [50.1310] l.23829 - Make dumping/undumping more efficient.
2226undump_size(0)(pool_size)('string pool size')(pool_ptr);
2227undump_size(0)(max_strings)('max strings')(str_ptr);
2228for k:=too_big_char to str_ptr do undump(0)(pool_ptr)(str_start(k));
2229k:=0;
2230while k+4<pool_ptr do
2231  begin undump_four_ASCII; k:=k+4;
2232  end;
2233k:=pool_ptr-4; undump_four_ASCII;
2234@y
2235undump_size(0)(sup_pool_size-pool_free)('string pool size')(pool_ptr);
2236if pool_size<pool_ptr+pool_free then
2237  pool_size:=pool_ptr+pool_free;
2238undump_size(0)(sup_max_strings-strings_free)('sup strings')(str_ptr);@/
2239if max_strings<str_ptr+strings_free then
2240  max_strings:=str_ptr+strings_free;
2241str_start_ar:=xmalloc_array(pool_pointer, max_strings-biggest_char);
2242undump_things(str_start(too_big_char), str_ptr-too_big_char+1);
2243str_pool:=xmalloc_array(packed_ASCII_code, pool_size);
2244undump_things(str_pool[0], pool_ptr);
2245@z
2246
2247@x [50.1311] l.23850 - Make dumping/undumping more efficient.
2248repeat for k:=p to q+1 do dump_wd(mem[k]);
2249@y
2250repeat dump_things(mem[p], q+2-p);
2251@z
2252
2253@x [50.1311] l.23855 - Make dumping/undumping more efficient.
2254for k:=p to lo_mem_max do dump_wd(mem[k]);
2255@y
2256dump_things(mem[p], lo_mem_max+1-p);
2257@z
2258
2259@x [50.1311] l.23858 - Make dumping/undumping more efficient.
2260for k:=hi_mem_min to mem_end do dump_wd(mem[k]);
2261@y
2262dump_things(mem[hi_mem_min], mem_end+1-hi_mem_min);
2263@z
2264
2265@x [50.1312] l.23873 - Make dumping/undumping more efficient.
2266repeat for k:=p to q+1 do undump_wd(mem[k]);
2267@y
2268repeat undump_things(mem[p], q+2-p);
2269@z
2270
2271@x [50.1312] l.23878 - Make dumping/undumping more efficient.
2272for k:=p to lo_mem_max do undump_wd(mem[k]);
2273@y
2274undump_things(mem[p], lo_mem_max+1-p);
2275@z
2276
2277@x [50.1312] l.23888 - Make dumping/undumping more efficient.
2278for k:=hi_mem_min to mem_end do undump_wd(mem[k]);
2279@y
2280undump_things (mem[hi_mem_min], mem_end+1-hi_mem_min);
2281@z
2282
2283%%%%%%%% dynamic hyph_size
2284@x 24058 m.1324
2285dump_int(hyph_count);
2286for k:=0 to hyph_size do if hyph_word[k]<>0 then
2287  begin dump_int(k); dump_int(hyph_word[k]); dump_int(hyph_list[k]);
2288  end;
2289@y  24061
2290dump_int(hyph_count);
2291if hyph_next <= hyph_prime then hyph_next:=hyph_size;
2292dump_int(hyph_next);{minumum value of |hyphen_size| needed}
2293for k:=0 to hyph_size do if hyph_word[k]<>0 then
2294  begin dump_int(k+65536*hyph_link[k]);
2295        {assumes number of hyphen exceptions does not exceed 65535}
2296   dump_int(hyph_word[k]); dump_int(hyph_list[k]);
2297  end;
2298@z
2299
2300@x [50.1324] l.24066 - Make dumping/undumping more efficient - trie
2301for k:=0 to trie_max do dump_hh(trie[k]);
2302dump_int(max_hyph_char);
2303dump_int(trie_op_ptr);
2304for k:=1 to trie_op_ptr do
2305  begin dump_int(hyf_distance[k]);
2306  dump_int(hyf_num[k]);
2307  dump_int(hyf_next[k]);
2308  end;
2309@y
2310dump_things(trie[0],trie_max+1);
2311dump_int(max_hyph_char);
2312dump_int(trie_op_ptr);
2313dump_things(hyf_distance[1], trie_op_ptr);
2314dump_things(hyf_num[1], trie_op_ptr);
2315dump_things(hyf_next[1], trie_op_ptr);
2316@z
2317
2318@x [50.1325] l.24086 - Make dumping/undumping more efficient - trie
2319@<Undump the hyphenation tables@>=
2320@y
2321{This is only used for the hyphenation tries below, and the size is
2322 always |j+1|.}
2323@d xmalloc_and_undump(#) ==
2324  if not # then #:=xmalloc_array(two_halves, j+1);
2325  undump_things(#[0], j+1);
2326
2327@<Undump the hyphenation tables@>=
2328@z
2329
2330%%%%%%%% dynamic hyph_size
2331@x 24087 m.1325
2332undump(0)(hyph_size)(hyph_count);
2333for k:=1 to hyph_count do
2334  begin undump(0)(hyph_size)(j);
2335  undump(0)(str_ptr)(hyph_word[j]);
2336  undump(min_halfword)(max_halfword)(hyph_list[j]);
2337  end;
2338@y  24092
2339undump_size(0)(hyph_size)('hyph_size')(hyph_count);
2340undump_size(hyph_prime)(hyph_size)('hyph_size')(hyph_next);
2341j:=0;
2342for k:=1 to hyph_count do
2343  begin undump_int(j); if j<0 then goto bad_fmt;
2344   if j>65535 then
2345   begin hyph_next:= j div 65536; j:=j - hyph_next * 65536; end
2346       else hyph_next:=0;
2347   if (j>=hyph_size)or(hyph_next>hyph_size) then goto bad_fmt;
2348   hyph_link[j]:=hyph_next;
2349  undump(0)(str_ptr)(hyph_word[j]);
2350  undump(min_halfword)(max_halfword)(hyph_list[j]);
2351  end;
2352  {|j| is now the largest occupied location in |hyph_word|}
2353  incr(j);
2354  if j<hyph_prime then j:=hyph_prime;
2355  hyph_next:=j;
2356  if hyph_next >= hyph_size then hyph_next:=hyph_prime else
2357  if hyph_next >= hyph_prime then incr(hyph_next);
2358@z
2359
2360
2361@x [50.1325] l.24094 - Make dumping/undumping more efficient - trie
2362for k:=0 to j do undump_hh(trie[k]);
2363undump_int(max_hyph_char);
2364undump_size(0)(trie_op_size)('trie op size')(j); @+init trie_op_ptr:=j;@+tini
2365for k:=1 to j do
2366  begin undump(0)(63)(hyf_distance[k]); {a |small_number|}
2367  undump(0)(63)(hyf_num[k]);
2368  undump(min_quarterword)(max_quarterword)(hyf_next[k]);
2369  end;
2370@y
2371{The first array has not been allocated yet unless we're \.{INITEX};
2372 we do that precisely so we don't allocate more space than necessary.}
2373xmalloc_and_undump(trie);
2374undump_int(max_hyph_char);
2375undump_size(0)(trie_op_size)('trie op size')(j); @+init trie_op_ptr:=j;@+tini
2376{I'm not sure we have such a strict limitation (64) on these values, so
2377 let's leave them unchecked.}
2378undump_things(hyf_distance[1], j);
2379undump_things(hyf_num[1], j);
2380undump_upper_check_things(max_quarterword, hyf_next[1], j);
2381@z
2382
2383@x [50.1327] l.24117 - Allow command line to override dumped value.
2384undump(batch_mode)(error_stop_mode)(interaction);
2385@y
2386undump(batch_mode)(error_stop_mode)(interaction);
2387if interaction_option<>unspecified_mode then interaction:=interaction_option;
2388@z
2389
2390@x [50.1327] l.24172 - Test for end-of-file already done by undump.
2391if (x<>69069)or eof(fmt_file) then goto bad_fmt
2392@y
2393if x<>69069 then goto bad_fmt
2394@z
2395
2396@x [51.1332] l.24203 - make the main program a procedure, for eqtb hack.
2397@p begin @!{|start_here|}
2398@y
2399@d const_chk(#)==begin if # < inf@&# then # := inf@&# else
2400                         if # > sup@&# then # := sup@&# end
2401
2402{|setup_bound_var| stuff duplicated in \.{mf.ch}.}
2403@d setup_bound_var(#)==bound_default:=#; setup_bound_var_end
2404@d setup_bound_var_end(#)==bound_name:=#; setup_bound_var_end_end
2405@d setup_bound_var_end_end(#)==
2406  setup_bound_variable(addressof(#), bound_name, bound_default);
2407
2408@p procedure main_body;
2409begin @!{|start_here|}
2410
2411{Always start the file recorder?}
2412  {|recorder_enabled:=true;|}
2413
2414{Bounds that may be set from the configuration file. We want the user to
2415 be able to specify the names with underscores, but \.{TANGLE} removes
2416 underscores, so we're stuck giving the names twice, once as a string,
2417 once as the identifier. How ugly.}
2418  setup_bound_var (1000000)('main_memory')(main_memory);
2419    {|memory_word|s for |mem| in \.{INITEX}}
2420  setup_bound_var (0)('extra_mem_top')(extra_mem_top);
2421    {increase high mem in \.{VIRTEX}}
2422  setup_bound_var (0)('extra_mem_bot')(extra_mem_bot);
2423    {increase low mem in \.{VIRTEX}}
2424  setup_bound_var (300000)('pool_size')(pool_size);
2425  setup_bound_var (200000)('string_vacancies')(string_vacancies);
2426  setup_bound_var (5000)('pool_free')(pool_free); {min pool avail after fmt}
2427  setup_bound_var (100000)('max_strings')(max_strings);
2428  setup_bound_var (100)('strings_free')(strings_free);
2429  setup_bound_var (20000)('trie_size')(trie_size);
2430    {if |ssup_trie_size| increases, recompile}
2431  setup_bound_var (659)('hyph_size')(hyph_size);
2432  setup_bound_var (20000)('buf_size')(buf_size);
2433  setup_bound_var (50)('nest_size')(nest_size);
2434  setup_bound_var (15)('max_in_open')(max_in_open);
2435  setup_bound_var (60)('param_size')(param_size);
2436  setup_bound_var (4000)('save_size')(save_size);
2437  setup_bound_var (300)('stack_size')(stack_size);
2438  setup_bound_var (16384)('dvi_buf_size')(dvi_buf_size);
2439  setup_bound_var (79)('error_line')(error_line);
2440  setup_bound_var (50)('half_error_line')(half_error_line);
2441  setup_bound_var (79)('max_print_line')(max_print_line);
2442  const_chk (main_memory);
2443@+init
2444  if ini_version then begin
2445    extra_mem_top := 0;
2446  end;
2447@+tini
2448  extra_mem_bot := 0;
2449  if extra_mem_top>sup_main_memory then extra_mem_top:=sup_main_memory;
2450  {|mem_top| is an index, |main_memory| a size}
2451  mem_top := mem_bot + main_memory -1;
2452  mem_min := mem_bot;
2453  mem_max := mem_top;
2454
2455  {Check other constants against their sup and inf.}
2456  const_chk (trie_size);
2457  const_chk (hyph_size);
2458  const_chk (buf_size);
2459  const_chk (nest_size);
2460  const_chk (max_in_open);
2461  const_chk (param_size);
2462  const_chk (save_size);
2463  const_chk (stack_size);
2464  const_chk (dvi_buf_size);
2465  const_chk (pool_size);
2466  const_chk (string_vacancies);
2467  const_chk (pool_free);
2468  const_chk (max_strings);
2469  const_chk (strings_free);
2470  if error_line > ssup_error_line then error_line := ssup_error_line;
2471
2472  {array memory allocation}
2473  buffer:=xmalloc_array (ASCII_code, buf_size);
2474  nest:=xmalloc_array (list_state_record, nest_size);
2475  save_stack:=xmalloc_array (memory_word, save_size);
2476  input_stack:=xmalloc_array (in_state_record, stack_size);
2477  input_file:=xmalloc_array (alpha_file, max_in_open);
2478  input_file_mode:=xmalloc_array (halfword, max_in_open);
2479  input_file_translation:=xmalloc_array (halfword, max_in_open);
2480  line_stack:=xmalloc_array (integer, max_in_open);
2481  param_stack:=xmalloc_array (halfword, param_size);
2482  dvi_buf:=xmalloc_array (real_eight_bits, dvi_buf_size);
2483  hyph_word:=xmalloc_array (str_number, hyph_size);
2484  hyph_list:=xmalloc_array (halfword, hyph_size);
2485  hyph_link:=xmalloc_array (hyph_pointer, hyph_size);
2486@+init
2487if ini_version then begin
2488  yzmem:=xmalloc_array (memory_word, mem_top - mem_bot + 1);
2489  zmem := yzmem - mem_bot;   {Some compilers require |mem_bot=0|}
2490
2491  str_start_ar:=xmalloc_array (pool_pointer, max_strings-biggest_char);
2492  str_pool:=xmalloc_array (packed_ASCII_code, pool_size);
2493end;
2494@+tini
2495@z
2496
2497@x [51.1332] l.24215 - INI = VIR, so pool init needs runtime test
2498@!init if not get_strings_started then goto final_end;
2499init_prim; {call |primitive| for each primitive}
2500init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time;
2501tini@/
2502@y
2503@+init if ini_version then
2504  begin if not get_strings_started then goto final_end;
2505  init_prim; {call |primitive| for each primitive}
2506  init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time;
2507  end;
2508@+tini@/
2509@z
2510
2511@x [51.1332] l.24225 - main
2512end_of_TEX: close_files_and_terminate;
2513final_end: ready_already:=0;
2514end.
2515@y
2516close_files_and_terminate;
2517final_end: do_final_end;
2518end {|main_body|};
2519@z
2520
2521@x [51.1333] l.24254 - Print new line before termination; switch to editor if necessary.
2522    slow_print(log_name); print_char(".");
2523    end;
2524  end;
2525@y
2526    print_file_name(0, log_name, 0); print_char(".");
2527    end;
2528  end;
2529print_ln;
2530if (edit_name_start<>0) and (interaction>batch_mode) then
2531  call_edit(str_pool,edit_name_start,edit_name_length,edit_line);
2532@z
2533
2534@x [51.1334] l. - Remove reference to fontmemsize
2535  wlog_ln(', out of ',font_mem_size:1,' for ',font_max-font_base:1);@/
2536@y
2537@z
2538
2539@x [51.1335] l.24335 - Only do dump if ini.
2540  begin @!init for c:=top_mark_code to split_bot_mark_code do
2541    if cur_mark[c]<>null then delete_token_ref(cur_mark[c]);
2542  if sa_mark<>null then
2543    if do_marks(destroy_marks,0,sa_mark) then sa_mark:=null;
2544  for c:=last_box_code to vsplit_code do flush_node_list(disc_ptr[c]);
2545  if last_glue<>max_halfword then delete_glue_ref(last_glue);
2546  store_fmt_file; return;@+tini@/
2547@y
2548  begin @!init if ini_version then
2549    begin for c:=top_mark_code to split_bot_mark_code do
2550      if cur_mark[c]<>null then delete_token_ref(cur_mark[c]);
2551    if sa_mark<>null then
2552      if do_marks(destroy_marks,0,sa_mark) then sa_mark:=null;
2553  for c:=last_box_code to vsplit_code do flush_node_list(disc_ptr[c]);
2554    store_fmt_file; return;
2555    end;@+tini@/
2556@z
2557
2558@x [51.1337] l.24361 - Handle %&format in all cases.
2559if (format_ident=0)or(buffer[loc]="&") then
2560@y
2561if (format_ident=0)or(buffer[loc]="&")or dump_line then
2562@z
2563
2564@x [51.1337] l.24371 - Allocate hyphenation tries.
2565fix_date_and_time;@/
2566@y
2567fix_date_and_time;@/
2568
2569@!init
2570if trie_not_ready then begin {initex without format loaded}
2571  trie:=xmalloc_array (two_halves, trie_size);
2572
2573  trie_c:=xmalloc_array (ASCII_code, trie_size);
2574  trie_o:=xmalloc_array (quarterword, trie_size);
2575  trie_l:=xmalloc_array (trie_pointer, trie_size);
2576  trie_r:=xmalloc_array (trie_pointer, trie_size);
2577  trie_hash:=xmalloc_array (trie_pointer, trie_size);
2578  trie_taken:=xmalloc_array (boolean, trie_size);
2579  trie_min:=xmalloc_array (trie_pointer, too_big_char);
2580
2581  trie_root:=0; trie_c[0]:=si(0); trie_ptr:=0;
2582  end;
2583  tini@/
2584
2585@z
2586
2587% [52.1338] Core-dump in debugging mode on 0 input.  Under Unix, it's
2588% not possible to portably switch into the debugger while a program is
2589% running.  The best approximation is to do a core dump, then run the
2590% debugger on it later.
2591@x [52.1338] l.24411 - Core-dump in debugging mode on 0 input.
2592    begin goto breakpoint;@\ {go to every label at least once}
2593    breakpoint: m:=0; @{'BREAKPOINT'@}@\
2594    end
2595@y
2596    dump_core {do something to cause a core dump}
2597@z
2598
2599% The GNU C compiler complains of unused variables.
2600@x
2601procedure do_extension;
2602var i,@!j,@!k:integer; {all-purpose integers}
2603@!p,@!q,@!r:pointer; {all-purpose pointers}
2604@y
2605procedure do_extension;
2606var @!k:integer; {all-purpose integers}
2607@!p:pointer; {all-purpose pointers}
2608@z
2609
2610% [53.1350] (new_write_whatsit) Allow 18 as a \write stream. We never
2611% refer to an actual file, though, so we don't need to change the
2612% write_file or write_open arrays. We provide for disabling this at
2613% runtime, for paranoids.
2614@x [53.1350] l.24609 - system: Allow 18 as a \write stream.
2615  else if cur_val>15 then cur_val:=16;
2616@y
2617  else if (cur_val>15) and (cur_val <> 18) then cur_val:=16;
2618@z
2619
2620@x [53.1370] l.24770 - system: (write_out) \write18{foo} => system(foo).
2621begin @<Expand macros in the token list
2622@y
2623@!d:integer; {number of characters in incomplete current string}
2624@!clobbered:boolean; {system string is ok?}
2625@!runsystem_ret:integer; {return value from |runsystem|}
2626begin @<Expand macros in the token list
2627@z
2628
2629@x [53.1370] l.24773 - system: (write_out) \write18{foo} => system(foo).
2630if write_open[j] then selector:=j
2631@y
2632if j=18 then selector := new_string
2633else if write_open[j] then selector:=j
2634@z
2635
2636% Then call system(3) on that string.
2637@x [53.1370] l.24779 - system: (write_out) \write18{foo} => system(foo).
2638flush_list(def_ref); selector:=old_setting;
2639@y
2640flush_list(def_ref);
2641if j=18 then
2642  begin if (tracing_online<=0) then
2643    selector:=log_only  {Show what we're doing in the log file.}
2644  else selector:=term_and_log;  {Show what we're doing.}
2645  {If the log file isn't open yet, we can only send output to the terminal.
2646   Calling |open_log_file| from here seems to result in bad data in the log.}
2647  if not log_opened then selector:=term_only;
2648  print_nl("runsystem(");
2649  for d:=0 to cur_length-1 do
2650    begin {|print| gives up if passed |str_ptr|, so do it by hand.}
2651    print(so(str_pool[str_start(str_ptr)+d])); {N.B.: not |print_char|}
2652    end;
2653  print(")...");
2654  if shellenabledp then begin
2655    str_room(1); append_char(0); {Append a null byte to the expansion.}
2656    clobbered:=false;
2657    for d:=0 to cur_length-1 do {Convert to external character set.}
2658      begin
2659        str_pool[str_start(str_ptr)+d]:=xchr[str_pool[str_start(str_ptr)+d]];
2660        if (str_pool[str_start(str_ptr)+d]=null_code)
2661           and (d<cur_length-1) then clobbered:=true;
2662        {minimal checking: NUL not allowed in argument string of |system|()}
2663      end;
2664    if clobbered then print("clobbered")
2665    else begin {We have the command.  See if we're allowed to execute it,
2666         and report in the log.  We don't check the actual exit status of
2667         the command, or do anything with the output.}
2668      for d:=0 to cur_length-1 do {Convert to external character set.}
2669        begin
2670        outside_string_array[d]:=xchr[str_pool[str_start(str_ptr)+d]];
2671        end;
2672      outside_string_array[cur_length]:=null_code;
2673      runsystem_ret := runsystem(stringcast(outside_string_array));
2674      if runsystem_ret = -1 then print("quotation error in system command")
2675      else if runsystem_ret = 0 then print("disabled (restricted)")
2676      else if runsystem_ret = 1 then print("executed")
2677      else if runsystem_ret = 2 then print("executed safely (allowed)")
2678    end;
2679  end else begin
2680    print("disabled"); {|shellenabledp| false}
2681  end;
2682  print_char("."); print_nl(""); print_ln;
2683  pool_ptr:=str_start(str_ptr);  {erase the string}
2684end;
2685selector:=old_setting;
2686@z
2687
2688@x [53.1373] Need new local.
2689procedure out_what(@!p:pointer);
2690var j:small_number; {write stream number}
2691@y
2692procedure out_what(@!p:pointer);
2693var j:small_number; {write stream number}
2694    @!old_setting:0..max_selector;
2695@z
2696
2697@x [53.1374] Disallow certain \openout filenames, and log results.
2698      while not a_open_out(write_file[j]) do
2699        prompt_file_name("output file name",".tex");
2700      write_open[j]:=true;
2701@y
2702      while not kpse_out_name_ok(name_of_file+1)
2703            or not a_open_out(write_file[j]) do
2704        prompt_file_name("output file name",".tex");
2705      write_open[j]:=true;
2706      {If on first line of input, log file is not ready yet, so don't log.}
2707      if log_opened then begin
2708        old_setting:=selector;
2709        if (tracing_online<=0) then
2710          selector:=log_only  {Show what we're doing in the log file.}
2711        else selector:=term_and_log;  {Show what we're doing.}
2712        print_nl("\openout");
2713        print_int(j);
2714        print(" = `");
2715        print_file_name(cur_name,cur_area,cur_ext);
2716        print("'."); print_nl(""); print_ln;
2717        selector:=old_setting;
2718      end;
2719@z
2720
2721@x [54.1376] l.24903 - Add editor-switch variables to globals.
2722@* \[54] System-dependent changes.
2723@y
2724@* \[54/web2c] System-dependent changes for Web2c.
2725Here are extra variables for Web2c.  (This numbering of the
2726system-dependent section allows easy integration of Web2c and e-\TeX, etc.)
2727@^<system dependencies@>
2728
2729@<Glob...@>=
2730@!edit_name_start: pool_pointer; {where the filename to switch to starts}
2731@!edit_name_length,@!edit_line: integer; {what line to start editing at}
2732@!ipc_on: cinttype; {level of IPC action, 0 for none [default]}
2733@!stop_at_space: boolean; {whether |more_name| returns false for space}
2734
2735@ The |edit_name_start| will be set to point into |str_pool| somewhere after
2736its beginning if \TeX\ is supposed to switch to an editor on exit.
2737
2738@<Set init...@>=
2739edit_name_start:=0;
2740stop_at_space:=true;
2741
2742@ These are used when we regenerate the representation of the first 256
2743strings.
2744
2745@<Global...@> =
2746@!save_str_ptr: str_number;
2747@!save_pool_ptr: pool_pointer;
2748@!shellenabledp: cinttype;
2749@!restrictedshell: cinttype;
2750@!output_comment: ^char;
2751@!k,l: 0..65535; {used by `Make the first 256 strings', etc.}
2752
2753@ When debugging a macro package, it can be useful to see the exact
2754control sequence names in the format file.  For example, if ten new
2755csnames appear, it's nice to know what they are, to help pinpoint where
2756they came from.  (This isn't a truly ``basic'' printing procedure, but
2757that's a convenient module in which to put it.)
2758
2759@<Basic printing procedures@> =
2760procedure print_csnames (hstart:integer; hfinish:integer);
2761var c,h:integer;
2762begin
2763  write_ln(stderr, 'fmtdebug:csnames from ', hstart, ' to ', hfinish, ':');
2764  for h := hstart to hfinish do begin
2765    if newtext(h) > 0 then begin {if have anything at this position}
2766      for c := str_start(newtext(h)) to str_start(newtext(h) + 1) - 1
2767      do begin
2768        put_byte(str_pool[c], stderr); {print the characters}
2769      end;
2770      write_ln(stderr, '|');
2771    end;
2772  end;
2773end;
2774
2775@ Are we printing extra info as we read the format file?
2776
2777@<Glob...@> =
2778@!debug_format_file: boolean;
2779
2780
2781@ A helper for printing file:line:error style messages.  Look for a
2782filename in |full_source_filename_stack|, and if we fail to find
2783one fall back on the non-file:line:error style.
2784
2785@<Basic print...@>=
2786procedure print_file_line;
2787var level: 0..max_in_open;
2788begin
2789  level:=in_open;
2790  while (level>0) and (full_source_filename_stack[level]=0) do
2791    decr(level);
2792  if level=0 then
2793    print_nl("! ")
2794  else begin
2795    print_nl (""); print (full_source_filename_stack[level]); print (":");
2796    if level=in_open then print_int (line)
2797    else print_int (line_stack[level+1]);
2798    print (": ");
2799  end;
2800end;
2801
2802@ To be able to determine whether \.{\\write18} is enabled from within
2803\TeX\ we also implement \.{\\eof18}.  We sort of cheat by having an
2804additional route |scan_four_bit_int_or_18| which is the same as
2805|scan_four_bit_int| except it also accepts the value 18.
2806
2807@<Declare procedures that scan restricted classes of integers@>=
2808procedure scan_four_bit_int_or_18;
2809begin scan_int;
2810if (cur_val<0)or((cur_val>15)and(cur_val<>18)) then
2811  begin print_err("Bad number");
2812@.Bad number@>
2813  help2("Since I expected to read a number between 0 and 15,")@/
2814    ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
2815  end;
2816end;
2817
2818@* \[54/web2c-string] The string recycling routines.
2819\TeX{} uses 2 upto 4 {\it new\/} strings when scanning a filename in an
2820\.{\\input}, \.{\\openin}, or \.{\\openout} operation.  These strings are
2821normally lost because the reference to them are not saved after finishing
2822the operation.  |search_string| searches through the string pool for the
2823given string and returns either 0 or the found string number.
2824
2825@<Declare additional routines for string recycling@>=
2826function search_string(@!search:str_number):str_number;
2827label found;
2828var result: str_number;
2829@!s: str_number; {running index}
2830@!len: integer; {length of searched string}
2831begin result:=0; len:=length(search);
2832if len=0 then  {trivial case}
2833  begin result:=""; goto found;
2834  end
2835else  begin s:=search-1;  {start search with newest string below |s|; |search>1|!}
2836  while s>65535 do  {first 65536 strings depend on implementation!!}
2837    begin if length(s)=len then
2838      if str_eq_str(s,search) then
2839        begin result:=s; goto found;
2840        end;
2841    decr(s);
2842    end;
2843  end;
2844found:search_string:=result;
2845end;
2846
2847@ The following routine is a variant of |make_string|.  It searches
2848the whole string pool for a string equal to the string currently built
2849and returns a found string.  Otherwise a new string is created and
2850returned.  Be cautious, you can not apply |flush_string| to a replaced
2851string!
2852
2853@<Declare additional routines for string recycling@>=
2854function slow_make_string : str_number;
2855label exit;
2856var s: str_number; {result of |search_string|}
2857@!t: str_number; {new string}
2858begin t:=make_string; s:=search_string(t);
2859if s>0 then
2860  begin flush_string; slow_make_string:=s; return;
2861  end;
2862slow_make_string:=t;
2863exit:end;
2864
2865@ This function used to be in pdftex, but is useful in aleph too.
2866
2867@p function get_nullstr: str_number;
2868begin
2869    get_nullstr := "";
2870end;
2871
2872@* \[54] System-dependent changes.
2873@z
2874