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