1% tex.ch for C compilation with web2c, derived from various other change files. 2% By Tim Morgan, UC Irvine ICS Department, and many others. 3% 4% Be very careful when making changes to this file, as it is used to 5% generate TeX, e-TeX, and pdfTeX, and most changes require similar 6% changes to be made to the Aleph sources. 7% 8% (05/28/86) ETM Started with TeX 2.0 9% (06/03/87) ETM Brought up to TeX 2.2 10% (09/26/87) ETM Brought up to TeX 2.3 11% (10/01/87) ETM Brought up to TeX 2.5 12% (12/21/87) ETM Brought up to TeX 2.7 13% (01/14/88) ETM Brought up to TeX 2.9 14% (02/20/88) PAM Revised format and module numbers 15% (03/01/88) ETM Eliminated some unused variables and unnecesary tests 16% (05/09/88) ETM Added yet another casting bug fix 17% (06/21/88) ETM Brought up to TeX version 2.93 18% (12/11/88) ETM Brought up to TeX version 2.94 19% (01/12/89) PAM Brought up to TeX version 2.95 20% (02/14/89) ETM Brought up to TeX version 2.96 21% (03/10/89) ETM Brought up to TeX version 2.98 22% (07/06/89) ETM Brought up to TeX version 2.991 23% (11/30/89) KB To version 2.992 (8-bit). 24% (01/10/90) SR To version 2.993. 25% (03/27/90) KY To version 3.0. 26% (more recent changes in ChangeLog) 27% 28% The TeX program is copyright (C) 1982 by D. E. Knuth. 29% TeX is a trademark of the American Mathematical Society. 30% 31% Includes MLTEX.CH (Version 2.2) in text format, as of Dec 17, 1995. 32% MLTeX is copyright (C) 1990-92 by Michael J. Ferguson; all rights reserved. 33% MLTeX Version 2.2 is copyright (C) 1995 by B. Raichle; all rights reserved. 34% 35% The MLTeX changes are copyrighted so that we have some chance to 36% forbid unauthorized copies; we explicitly authorize copying of 37% correct MLTeX implementations, and not of incorrect ones! 38% 39% (This means that you can use the MLTeX changes as free as you can 40% use TeX and its algorithm.) 41% 42% Copying of this file is authorized only if either 43% (1) you make absolutely no changes to your copy, including name, or 44% (2) if you do make changes, you name it to something other than 45% "mltex.ch", "char_sub.ch", or "charsub.ch". 46% 47% Except for MLTeX, the new code in this file is in the public domain. 48% 49% The module numbers in this change file refer to TEX.WEB 3.14159 as 50% of March, 1995 (published as Donald E. Knuth, TeX: The Program, 51% Volume B of Computers & Typesetting). 52 53@x [0.0] l.83 - WEAVE: print changes only. 54 \def\?##1]{\hbox to 1in{\hfil##1.\ }} 55 } 56@y 83 57 \def\?##1]{\hbox{Changes to \hbox to 1em{\hfil##1}.\ }} 58 } 59\let\maybe=\iffalse 60@z 61 62@x [1.2] l.185 - MLTeX: add comment about banner line change 63November 1984]. 64@y 65November 1984]. 66 67ML\TeX{} will add new primitives changing the behaviour of \TeX. The 68|banner| string has to be changed. We do not change the |banner| 69string, but will output an additional line to make clear that this is 70a modified \TeX{} version. 71 72@z 73 74@x [1.2] l.188 75@d banner=='This is TeX, Version 3.14159265' {printed when \TeX\ starts} 76@y 77@d TeX_banner_k=='This is TeXk, Version 3.14159265' {printed when \TeX\ starts} 78@d TeX_banner=='This is TeX, Version 3.14159265' {printed when \TeX\ starts} 79@# 80@d banner==TeX_banner 81@d banner_k==TeX_banner_k 82@z 83 84@x [1.4] l.233 - program header 85Actually the heading shown here is not quite normal: The |program| line 86does not mention any |output| file, because \ph\ would ask the \TeX\ user 87to specify a file name if |output| were specified here. 88@:PASCAL H}{\ph@> 89@^system dependencies@> 90@y 91@z 92 93@x [1.4] l.243 - labels in outer block not needed 94program TEX; {all file names are defined dynamically} 95label @<Labels in the outer block@>@/ 96@y 97program TEX; {all file names are defined dynamically} 98@z 99 100@x [1.6] l.267 - labels in outer block not needed 101@ Three labels must be declared in the main program, so we give them 102symbolic names. 103 104@d start_of_TEX=1 {go here when \TeX's variables are initialized} 105@d end_of_TEX=9998 {go here to close files and terminate gracefully} 106@d final_end=9999 {this label marks the ending of the program} 107 108@<Labels in the out...@>= 109start_of_TEX@t\hskip-2pt@>, end_of_TEX@t\hskip-2pt@>,@,final_end; 110 {key control points} 111@y 112@ For Web2c, labels are not declared in the main program, but 113we still have to declare the symbolic names. 114 115@d start_of_TEX=1 {go here when \TeX's variables are initialized} 116@d final_end=9999 {this label marks the ending of the program} 117@z 118 119% Here we change these WEB symbols, which are used much as #ifdef's 120% are in C, into something which will get translated into actual #ifdef's. 121@x [1.7] l.292 - debug..gubed, stat..tats 122@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging} 123@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging} 124@y 125@d debug==ifdef('TEXMF_DEBUG') 126@d gubed==endif('TEXMF_DEBUG') 127@z 128@x [1.7] l.297 - debug..gubed, stat..tats 129@d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering 130 usage statistics} 131@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering 132 usage statistics} 133@y 134@d stat==ifdef('STAT') 135@d tats==endif('STAT') 136@z 137 138@x [1.8] Somewhat different for `init...tini'.. 310 m.8 139the codewords `$|init|\ldots|tini|$'. 140 141@d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version} 142@d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version} 143@y 314 144the codewords `$|init|\ldots|tini|$' for declarations and by the codewords 145`$|Init|\ldots|Tini|$' for executable code. This distinction is helpful for 146implementations where a run-time switch differentiates between the two 147versions of the program. 148 149@d init==ifdef('INITEX') 150@d tini==endif('INITEX') 151@d Init==init if ini_version then begin 152@d Tini==end;@+tini 153@f Init==begin 154@f Tini==end 155@z 156 157@x [1.8] l.319 - init...tini is dynamic 158@!init @<Initialize table entries (done by \.{INITEX} only)@>@;@+tini 159@y 318 160@!Init @<Initialize table entries (done by \.{INITEX} only)@>@;@+Tini 161@z 162 163@x [1.11] l.375 - Compile-time constants: most removed for dynamic allocation. 164@<Constants...@>= 165@!mem_max=30000; {greatest index in \TeX's internal |mem| array; 166 must be strictly less than |max_halfword|; 167 must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|} 168@!mem_min=0; {smallest index in \TeX's internal |mem| array; 169 must be |min_halfword| or more; 170 must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|} 171@!buf_size=500; {maximum number of characters simultaneously present in 172 current lines of open files and in control sequences between 173 \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|} 174@!error_line=72; {width of context lines on terminal error messages} 175@!half_error_line=42; {width of first lines of contexts in terminal 176 error messages; should be between 30 and |error_line-15|} 177@!max_print_line=79; {width of longest text lines output; should be at least 60} 178@!stack_size=200; {maximum number of simultaneous input sources} 179@!max_in_open=6; {maximum number of input files and error insertions that 180 can be going on simultaneously} 181@!font_max=75; {maximum internal font number; must not exceed |max_quarterword| 182 and must be at most |font_base+256|} 183@!font_mem_size=20000; {number of words of |font_info| for all fonts} 184@!param_size=60; {maximum number of simultaneous macro parameters} 185@!nest_size=40; {maximum number of semantic levels simultaneously active} 186@!max_strings=3000; {maximum number of strings; must not exceed |max_halfword|} 187@!string_vacancies=8000; {the minimum number of characters that should be 188 available for the user's control sequences and font names, 189 after \TeX's own error messages are stored} 190@!pool_size=32000; {maximum number of characters in strings, including all 191 error messages and help texts, and the names of all fonts and 192 control sequences; must exceed |string_vacancies| by the total 193 length of \TeX's own strings, which is currently about 23000} 194@!save_size=600; {space for saving values outside of current group; must be 195 at most |max_halfword|} 196@!trie_size=8000; {space for hyphenation patterns; should be larger for 197 \.{INITEX} than it is in production versions of \TeX} 198@!trie_op_size=500; {space for ``opcodes'' in the hyphenation patterns} 199@!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8} 200@!file_name_size=40; {file names shouldn't be longer than this} 201@!pool_name='TeXformats:TEX.POOL '; 202 {string of length |file_name_size|; tells where the string pool appears} 203@y 204@d file_name_size == maxint 205@d ssup_error_line = 255 206@d ssup_max_strings == 2097151 207{Larger values than 65536 cause the arrays to consume much more memory.} 208@d ssup_trie_opcode == 65535 209@d ssup_trie_size == @"3FFFFF 210 211@d ssup_hyph_size == 65535 {Changing this requires changing (un)dumping!} 212@d iinf_hyphen_size == 610 {Must be not less than |hyph_prime|!} 213 214@d max_font_max=9000 {maximum number of internal fonts; this can be 215 increased, but |hash_size+max_font_max| 216 should not exceed 29000.} 217@d font_base=0 {smallest internal font number; must be 218 |>= min_quarterword|; do not change this without 219 modifying the dynamic definition of the font arrays.} 220 221 222@<Constants...@>= 223@!hash_offset=514; {smallest index in hash array, i.e., |hash_base| } 224 {Use |hash_offset=0| for compilers which cannot decrement pointers.} 225@!trie_op_size=35111; {space for ``opcodes'' in the hyphenation patterns; 226 best if relatively prime to 313, 361, and 1009.} 227@!neg_trie_op_size=-35111; {for lower |trie_op_hash| array bound; 228 must be equal to |-trie_op_size|.} 229@!min_trie_op=0; {first possible trie op code for any language} 230@!max_trie_op=ssup_trie_opcode; {largest possible trie opcode for any language} 231@!pool_name=TEXMF_POOL_NAME; {this is configurable, for the sake of ML-\TeX} 232 {string of length |file_name_size|; tells where the string pool appears} 233@!engine_name=TEXMF_ENGINE_NAME; {the name of this engine} 234@# 235@!inf_mem_bot = 0; 236@!sup_mem_bot = 1; 237 238@!inf_main_memory = 3000; 239@!sup_main_memory = 256000000; 240 241@!inf_trie_size = 8000; 242@!sup_trie_size = ssup_trie_size; 243 244@!inf_max_strings = 3000; 245@!sup_max_strings = ssup_max_strings; 246@!inf_strings_free = 100; 247@!sup_strings_free = sup_max_strings; 248 249@!inf_buf_size = 500; 250@!sup_buf_size = 30000000; 251 252@!inf_nest_size = 40; 253@!sup_nest_size = 4000; 254 255@!inf_max_in_open = 6; 256@!sup_max_in_open = 127; 257 258@!inf_param_size = 60; 259@!sup_param_size = 32767; 260 261@!inf_save_size = 600; 262@!sup_save_size = 80000; 263 264@!inf_stack_size = 200; 265@!sup_stack_size = 30000; 266 267@!inf_dvi_buf_size = 800; 268@!sup_dvi_buf_size = 65536; 269 270@!inf_font_mem_size = 20000; 271@!sup_font_mem_size = 147483647; {|integer|-limited, so 2 could be prepended?} 272 273@!sup_font_max = max_font_max; 274@!inf_font_max = 50; {could be smaller, but why?} 275 276@!inf_pool_size = 32000; 277@!sup_pool_size = 40000000; 278@!inf_pool_free = 1000; 279@!sup_pool_free = sup_pool_size; 280@!inf_string_vacancies = 8000; 281@!sup_string_vacancies = sup_pool_size - 23000; 282 283@!sup_hash_extra = sup_max_strings; 284@!inf_hash_extra = 0; 285 286@!sup_hyph_size = ssup_hyph_size; 287@!inf_hyph_size = iinf_hyphen_size; {Must be not less than |hyph_prime|!} 288 289@!inf_expand_depth = 10; 290@!sup_expand_depth = 10000000; 291@z 292 293@x [1.12] l.427 - Constants that are WEB numeric macros. 294@d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX}; 295 must not be less than |mem_min|} 296@d mem_top==30000 {largest index in the |mem| array dumped by \.{INITEX}; 297 must be substantially larger than |mem_bot| 298 and not greater than |mem_max|} 299@d font_base=0 {smallest internal font number; must not be less 300 than |min_quarterword|} 301@d hash_size=2100 {maximum number of control sequences; it should be at most 302 about |(mem_max-mem_min)/10|} 303@d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|} 304@d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions} 305@y 306@d hash_size=15000 {maximum number of control sequences; it should be at most 307 about |(mem_max-mem_min)/10|; see also |font_max|} 308@d hash_prime=8501 {a prime number equal to about 85\pct! of |hash_size|} 309@d hyph_prime=607 {another prime for hashing \.{\\hyphenation} exceptions; 310 if you change this, you should also change |iinf_hyphen_size|.} 311@z 312 313@x [1.16] l.498 - Use C macros for `incr' and `decr'. 314@d incr(#) == #:=#+1 {increase a variable by unity} 315@d decr(#) == #:=#-1 {decrease a variable by unity} 316@y 317@z 318 319% The text_char type is used as an array index into xord. The 320% default type `char' produces signed integers, which are bad array 321% indices in C. 322@x [2.19] l.565 - data type text_char is 8-bit ASCII_code 323@d text_char == char {the data type of characters in text files} 324@y 325@d text_char == ASCII_code {the data type of characters in text files} 326@z 327 328@x [2.20] l.579 - printable characters 329@!xchr: array [ASCII_code] of text_char; 330 {specifies conversion of output characters} 331@y 332xchr: array [ASCII_code] of text_char; 333 { specifies conversion of output characters } 334xprn: array [ASCII_code] of ASCII_code; 335 { non zero iff character is printable } 336@z 337 338@x [2.23] l.723 - Translate characters if desired, otherwise allow them all. 339for i:=0 to @'37 do xchr[i]:=' '; 340for i:=@'177 to @'377 do xchr[i]:=' '; 341@y 342{Initialize |xchr| to the identity mapping.} 343for i:=0 to @'37 do xchr[i]:=i; 344for i:=@'177 to @'377 do xchr[i]:=i; 345@z 346 347@x [2.24] l.733 - Don't reinitialize xord. 348for i:=0 to @'176 do xord[xchr[i]]:=i; 349@y 350for i:=0 to @'176 do xord[xchr[i]]:=i; 351{Set |xprn| for printable ASCII, unless |eight_bit_p| is set.} 352for i:=0 to 255 do xprn[i]:=(eight_bit_p or ((i>=" ")and(i<="~"))); 353 354{The idea for this dynamic translation comes from the patch by 355 Libor Skarvada \.{<libor@@informatics.muni.cz>} 356 and Petr Sojka \.{<sojka@@informatics.muni.cz>}. I didn't use any of the 357 actual code, though, preferring a more general approach.} 358 359{This updates the |xchr|, |xord|, and |xprn| arrays from the provided 360 |translate_filename|. See the function definition in \.{texmfmp.c} for 361 more comments.} 362if translate_filename then read_tcx_file; 363@z 364 365% [3.26] name_of_file is no longer an array. And change the destination 366% type to text_char, which fixes: 367% 368% Date: 19 Sep 1994 10:38:24 +0200 369% From: thorinn@diku.dk (Lars Mathiesen) 370% When echoed to the screen and in the log, character codes 371% above '177 in file names are shown wrongly (typically as ^@). 372% 373@x [3.26] l.789 - name_of_file is no longer an array 374@!name_of_file:packed array[1..file_name_size] of char;@;@/ 375 {on some systems this may be a \&{record} variable} 376@y 377@!name_of_file:^text_char; 378@z 379 380@x [3.27] l.794 - Do file opening in C. 381@ The \ph\ compiler with which the present version of \TeX\ was prepared has 382extended the rules of \PASCAL\ in a very convenient way. To open file~|f|, 383we can write 384$$\vbox{\halign{#\hfil\qquad&#\hfil\cr 385|reset(f,@t\\{name}@>,'/O')|&for input;\cr 386|rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$ 387The `\\{name}' parameter, which is of type `{\bf packed array 388$[\langle\\{any}\rangle]$ of \\{char}}', stands for the name of 389the external file that is being opened for input or output. 390Blank spaces that might appear in \\{name} are ignored. 391 392The `\.{/O}' parameter tells the operating system not to issue its own 393error messages if something goes wrong. If a file of the specified name 394cannot be found, or if such a file cannot be opened for some other reason 395(e.g., someone may already be trying to write the same file), we will have 396|@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows 397\TeX\ to undertake appropriate corrective action. 398@:PASCAL H}{\ph@> 399@^system dependencies@> 400 401\TeX's file-opening procedures return |false| if no file identified by 402|name_of_file| could be opened. 403 404@d reset_OK(#)==erstat(#)=0 405@d rewrite_OK(#)==erstat(#)=0 406 407@p function a_open_in(var f:alpha_file):boolean; 408 {open a text file for input} 409begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); 410end; 411@# 412function a_open_out(var f:alpha_file):boolean; 413 {open a text file for output} 414begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); 415end; 416@# 417function b_open_in(var f:byte_file):boolean; 418 {open a binary file for input} 419begin reset(f,name_of_file,'/O'); b_open_in:=reset_OK(f); 420end; 421@# 422function b_open_out(var f:byte_file):boolean; 423 {open a binary file for output} 424begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f); 425end; 426@# 427function w_open_in(var f:word_file):boolean; 428 {open a word file for input} 429begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f); 430end; 431@# 432function w_open_out(var f:word_file):boolean; 433 {open a word file for output} 434begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f); 435end; 436@y 437@ All of the file opening functions are defined in C. 438@z 439 440@x [3.28] l.850 - Do file closing in C. 441@ Files can be closed with the \ph\ routine `|close(f)|', which 442@:PASCAL H}{\ph@> 443@^system dependencies@> 444should be used when all input or output with respect to |f| has been completed. 445This makes |f| available to be opened again, if desired; and if |f| was used for 446output, the |close| operation makes the corresponding external file appear 447on the user's area, ready to be read. 448 449These procedures should not generate error messages if a file is 450being closed before it has been successfully opened. 451 452@p procedure a_close(var f:alpha_file); {close a text file} 453begin close(f); 454end; 455@# 456procedure b_close(var f:byte_file); {close a binary file} 457begin close(f); 458end; 459@# 460procedure w_close(var f:word_file); {close a word file} 461begin close(f); 462end; 463@y 464@ And all the file closing routines as well. 465@z 466 467@x [3.30] l.888 - Array size of input buffer is determined at runtime. 468@!buffer:array[0..buf_size] of ASCII_code; {lines of characters being read} 469@y 470@!buffer:^ASCII_code; {lines of characters being read} 471@z 472 473@x [3.31] l.933 - Do `input_ln' in C. 474@p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean; 475 {inputs the next line or returns |false|} 476var last_nonblank:0..buf_size; {|last| with trailing blanks removed} 477begin if bypass_eoln then if not eof(f) then get(f); 478 {input the first character of the line into |f^|} 479last:=first; {cf.\ Matthew 19\thinspace:\thinspace30} 480if eof(f) then input_ln:=false 481else begin last_nonblank:=first; 482 while not eoln(f) do 483 begin if last>=max_buf_stack then 484 begin max_buf_stack:=last+1; 485 if max_buf_stack=buf_size then 486 @<Report overflow of the input buffer, and abort@>; 487 end; 488 buffer[last]:=xord[f^]; get(f); incr(last); 489 if buffer[last-1]<>" " then last_nonblank:=last; 490 end; 491 last:=last_nonblank; input_ln:=true; 492 end; 493end; 494@y 495We define |input_ln| in C, for efficiency. Nevertheless we quote the module 496`Report overflow of the input buffer, and abort' here in order to make 497\.{WEAVE} happy, since part of that module is needed by e-TeX. 498 499@p @{ @<Report overflow of the input buffer, and abort@> @} 500@z 501 502% [3.32] `term_in' and `term_out' are standard input and output. 503% Declare the variables that used to be constants. 504@x [3.32] l.961 - `term_in' and `term_out' are standard input and output. 505@<Glob...@>= 506@!term_in:alpha_file; {the terminal as an input file} 507@!term_out:alpha_file; {the terminal as an output file} 508@y 509@d term_in==stdin {the terminal as an input file} 510@d term_out==stdout {the terminal as an output file} 511 512@<Glob...@>= 513@!init 514@!ini_version:boolean; {are we \.{INITEX}?} 515@!dump_option:boolean; {was the dump name option used?} 516@!dump_line:boolean; {was a \.{\%\AM format} line seen?} 517tini@/ 518@# 519@!dump_name:const_cstring; {format name for terminal display} 520@# 521@!bound_default:integer; {temporary for setup} 522@!bound_name:const_cstring; {temporary for setup} 523@# 524@!mem_bot:integer;{smallest index in the |mem| array dumped by \.{INITEX}; 525 must not be less than |mem_min|} 526@!main_memory:integer; {total memory words allocated in initex} 527@!extra_mem_bot:integer; {|mem_min:=mem_bot-extra_mem_bot| except in \.{INITEX}} 528@!mem_min:integer; {smallest index in \TeX's internal |mem| array; 529 must be |min_halfword| or more; 530 must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|} 531@!mem_top:integer; {largest index in the |mem| array dumped by \.{INITEX}; 532 must be substantially larger than |mem_bot|, 533 equal to |mem_max| in \.{INITEX}, else not greater than |mem_max|} 534@!extra_mem_top:integer; {|mem_max:=mem_top+extra_mem_top| except in \.{INITEX}} 535@!mem_max:integer; {greatest index in \TeX's internal |mem| array; 536 must be strictly less than |max_halfword|; 537 must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|} 538@!error_line:integer; {width of context lines on terminal error messages} 539@!half_error_line:integer; {width of first lines of contexts in terminal 540 error messages; should be between 30 and |error_line-15|} 541@!max_print_line:integer; 542 {width of longest text lines output; should be at least 60} 543@!max_strings:integer; {maximum number of strings; must not exceed |max_halfword|} 544@!strings_free:integer; {strings available after format loaded} 545@!string_vacancies:integer; {the minimum number of characters that should be 546 available for the user's control sequences and font names, 547 after \TeX's own error messages are stored} 548@!pool_size:integer; {maximum number of characters in strings, including all 549 error messages and help texts, and the names of all fonts and 550 control sequences; must exceed |string_vacancies| by the total 551 length of \TeX's own strings, which is currently about 23000} 552@!pool_free:integer;{pool space free after format loaded} 553@!font_mem_size:integer; {number of words of |font_info| for all fonts} 554@!font_max:integer; {maximum internal font number; ok to exceed |max_quarterword| 555 and must be at most |font_base|+|max_font_max|} 556@!font_k:integer; {loop variable for initialization} 557@!hyph_size:integer; {maximun number of hyphen exceptions} 558@!trie_size:integer; {space for hyphenation patterns; should be larger for 559 \.{INITEX} than it is in production versions of \TeX. 50000 is 560 needed for English, German, and Portuguese.} 561@!buf_size:integer; {maximum number of characters simultaneously present in 562 current lines of open files and in control sequences between 563 \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|} 564@!stack_size:integer; {maximum number of simultaneous input sources} 565@!max_in_open:integer; {maximum number of input files and error insertions that 566 can be going on simultaneously} 567@!param_size:integer; {maximum number of simultaneous macro parameters} 568@!nest_size:integer; {maximum number of semantic levels simultaneously active} 569@!save_size:integer; {space for saving values outside of current group; must be 570 at most |max_halfword|} 571@!dvi_buf_size:integer; {size of the output buffer; must be a multiple of 8} 572@!expand_depth:integer; {limits recursive calls to the |expand| procedure} 573@!parse_first_line_p:cinttype; {parse the first line for options} 574@!file_line_error_style_p:cinttype; {format messages as file:line:error} 575@!eight_bit_p:cinttype; {make all characters printable by default} 576@!halt_on_error_p:cinttype; {stop at first error} 577@!quoted_filename:boolean; {current filename is quoted} 578{Variables for source specials} 579@!src_specials_p : boolean;{Whether |src_specials| are enabled at all} 580@!insert_src_special_auto : boolean; 581@!insert_src_special_every_par : boolean; 582@!insert_src_special_every_parend : boolean; 583@!insert_src_special_every_cr : boolean; 584@!insert_src_special_every_math : boolean; 585@!insert_src_special_every_hbox : boolean; 586@!insert_src_special_every_vbox : boolean; 587@!insert_src_special_every_display : boolean; 588@z 589 590@x [3.33] l.964 - We don't need to open terminal files. 591@ Here is how to open the terminal files 592in \ph. The `\.{/I}' switch suppresses the first |get|. 593@:PASCAL H}{\ph@> 594@^system dependencies@> 595 596@d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input} 597@d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output} 598@y 599@ Here is how to open the terminal files. |t_open_out| does nothing. 600|t_open_in|, on the other hand, does the work of ``rescanning,'' or getting 601any command line arguments the user has provided. It's defined in C. 602 603@d t_open_out == {output already open for text output} 604@z 605 606@x [3.34] l.982 - Flushing output to terminal files. 607these operations can be specified in \ph: 608@:PASCAL H}{\ph@> 609@^system dependencies@> 610 611@d update_terminal == break(term_out) {empty the terminal output buffer} 612@d clear_terminal == break_in(term_in,true) {clear the terminal input buffer} 613@y 614these operations can be specified with {\mc UNIX}. |update_terminal| 615does an |fflush|. |clear_terminal| is redefined 616to do nothing, since the user should control the terminal. 617@^system dependencies@> 618 619@d update_terminal == fflush (term_out) 620@d clear_terminal == do_nothing 621@z 622 623@x [3.35] l.1017 - needed for e-TeX, but differently 624@<Report overflow of the input buffer, and abort@>= 625if format_ident=0 then 626 begin write_ln(term_out,'Buffer size exceeded!'); goto final_end; 627@.Buffer size exceeded@> 628 end 629else begin cur_input.loc_field:=first; cur_input.limit_field:=last-1; 630@y 631Routine is implemented in C; part of module is, however, needed for e-TeX. 632 633@<Report overflow of the input buffer, and abort@>= 634 begin cur_input.loc_field:=first; cur_input.limit_field:=last-1; 635@z 636 637@x [3.37] l.1055 - |init_terminal|, reading the command line. 638@ The following program does the required initialization 639without retrieving a possible command line. 640It should be clear how to modify this routine to deal with command lines, 641if the system permits them. 642@^system dependencies@> 643 644@p function init_terminal:boolean; {gets the terminal input started} 645label exit; 646begin t_open_in; 647@y 648@ The following program does the required initialization. 649Iff anything has been specified on the command line, then |t_open_in| 650will return with |last > first|. 651@^system dependencies@> 652 653@p function init_terminal:boolean; {gets the terminal input started} 654label exit; 655begin t_open_in; 656if last > first then 657 begin loc := first; 658 while (loc < last) and (buffer[loc]=' ') do incr(loc); 659 if loc < last then 660 begin init_terminal := true; goto exit; 661 end; 662 end; 663@z 664 665@x [3.37] l.1068 - |init_terminal|, output missing newline. 666 write(term_out,'! End of file on the terminal... why?'); 667@y 668 write_ln(term_out,'! End of file on the terminal... why?'); 669@z 670 671@x [4.38] l.1126 - Array size for string pool is determined at runtime. 672@!pool_pointer = 0..pool_size; {for variables that point into |str_pool|} 673@!str_number = 0..max_strings; {for variables that point into |str_start|} 674@y 675@!pool_pointer = integer; {for variables that point into |str_pool|} 676@!str_number = 0..ssup_max_strings; {for variables that point into |str_start|} 677@z 678 679@x [4.39] l.1131 - Dynamically size pool arrays. 680@!str_pool:packed array[pool_pointer] of packed_ASCII_code; {the characters} 681@!str_start : array[str_number] of pool_pointer; {the starting pointers} 682@y 683@!str_pool: ^packed_ASCII_code; {the characters} 684@!str_start : ^pool_pointer; {the starting pointers} 685@z 686 687@x [4.47] l.1237 - string recycling 688@p @!init function get_strings_started:boolean; {initializes the string pool, 689@y 690@p @t\4@>@<Declare additional routines for string recycling@>@/ 691 692@!init function get_strings_started:boolean; {initializes the string pool, 693@z 694 695@x [4.49] l.1272 -- Change documentation (probably needed in more places) 696would like string @'32 to be the single character @'32 instead of the 697@y 698would like string @'32 to be printed as the single character @'32 699instead of the 700@z 701 702% [4.51] Open the pool file using a path, and can't do string 703% assignments directly. (`strcpy' and `strlen' work here because 704% `pool_name' is a constant string, and thus ends in a null and doesn't 705% start with a space.) 706@x [4.51] l.1314 - Open the pool file. 707name_of_file:=pool_name; {we needn't set |name_length|} 708if a_open_in(pool_file) then 709@y 710name_length := strlen (pool_name); 711name_of_file := xmalloc_array (ASCII_code, name_length + 1); 712strcpy (stringcast(name_of_file+1), pool_name); {copy the string} 713if a_open_in (pool_file, kpse_texpool_format) then 714@z 715 716@x [4.51] l.1322 - Make `TEX.POOL' lowercase, and change how it's read. 717else bad_pool('! I can''t read TEX.POOL.') 718@y 719else bad_pool('! I can''t read ', pool_name, '; bad path?') 720@z 721@x [4.52] l.1326 - Make `TEX.POOL' lowercase, and change how it's read. 722begin if eof(pool_file) then bad_pool('! TEX.POOL has no check sum.'); 723@.TEX.POOL has no check sum@> 724read(pool_file,m,n); {read two digits of string length} 725@y 726begin if eof(pool_file) then bad_pool('! ', pool_name, ' has no check sum.'); 727@.TEX.POOL has no check sum@> 728read(pool_file,m); read(pool_file,n); {read two digits of string length} 729@z 730@x [4.52] l.1332 - Make `TEX.POOL' lowercase, and change how it's read. 731 bad_pool('! TEX.POOL line doesn''t begin with two digits.'); 732@y 733 bad_pool('! ', pool_name, ' line doesn''t begin with two digits.'); 734@z 735@x [4.53] l.1354 - Make `TEX.POOL' lowercase, and change how it's read. 736 bad_pool('! TEX.POOL check sum doesn''t have nine digits.'); 737@y 738 bad_pool('! ', pool_name, ' check sum doesn''t have nine digits.'); 739@z 740@x [4.53] l.1360 - Make `TEX.POOL' lowercase, and change how it's read. 741done: if a<>@$ then bad_pool('! TEX.POOL doesn''t match; TANGLE me again.'); 742@y 743done: if a<>@$ then 744 bad_pool('! ', pool_name, ' doesn''t match; tangle me again (or fix the path).'); 745@z 746 747@x [5.54] l.1422 - error_line 748@!trick_buf:array[0..error_line] of ASCII_code; {circular buffer for 749@y 750@!trick_buf:array[0..ssup_error_line] of ASCII_code; {circular buffer for 751@z 752 753@x l.1536 -- If the ``src-specials'' feature is active, change the banner. 754wterm(banner); 755@y 756if src_specials_p or file_line_error_style_p or parse_first_line_p then 757 wterm(banner_k) 758else 759 wterm(banner); 760@z 761 762@x [5.61] l.1556 - Print rest of banner. 763if format_ident=0 then wterm_ln(' (no format preloaded)') 764else begin slow_print(format_ident); print_ln; 765 end; 766@y 767wterm(version_string); 768if format_ident=0 then wterm_ln(' (preloaded format=',dump_name,')') 769else begin slow_print(format_ident); print_ln; 770 end; 771if shellenabledp then begin 772 wterm(' '); 773 if restrictedshell then begin 774 wterm('restricted '); 775 end; 776 wterm_ln('\write18 enabled.'); 777end; 778if src_specials_p then begin 779 wterm_ln(' Source specials enabled.') 780end; 781if translate_filename then begin 782 wterm(' ('); 783 fputs(translate_filename, stdout); 784 wterm_ln(')'); 785end; 786@z 787 788@x [6.73] l.1732 - Add unspecified_mode. 789@d error_stop_mode=3 {stops at every opportunity to interact} 790@y 791@d error_stop_mode=3 {stops at every opportunity to interact} 792@d unspecified_mode=4 {extra value for command-line switch} 793@z 794 795@x [6.73] l.1734 - file:line:error style error messages. 796 print_nl("! "); print(#); 797@y 798 if file_line_error_style_p then print_file_line 799 else print_nl("! "); 800 print(#); 801@z 802 803 804@x [6.73] l.1738 - Add interaction_option. 805@!interaction:batch_mode..error_stop_mode; {current level of interaction} 806@y 807@!interaction:batch_mode..error_stop_mode; {current level of interaction} 808@!interaction_option:batch_mode..unspecified_mode; {set from command line} 809@z 810 811@x [6.74] l.1740 - Allow override by command line switch. 812@ @<Set init...@>=interaction:=error_stop_mode; 813@y 814@ @<Set init...@>=if interaction_option=unspecified_mode then 815 interaction:=error_stop_mode 816else 817 interaction:=interaction_option; 818@z 819 820% [6.81] Eliminate nonlocal goto, since C doesn't have them. 821% Plus, it's nicer just to do an exit with the appropriate status code 822% under Unix. We call it `uexit' because there's a WEB symbol called 823% `exit' already. We use a C macro to change `uexit' back to `exit'. 824@x [6.81] l.1852 - Eliminate nonlocal goto, since C doesn't have them. 825@<Error hand...@>= 826procedure jump_out; 827begin goto end_of_TEX; 828end; 829@y 830@d do_final_end==begin 831 update_terminal; 832 ready_already:=0; 833 if (history <> spotless) and (history <> warning_issued) then 834 uexit(1) 835 else 836 uexit(0); 837 end 838 839@<Error hand...@>= 840noreturn procedure jump_out; 841begin 842close_files_and_terminate; 843do_final_end; 844end; 845@z 846 847@x [6.82] l.1866 - halt on error? 848print_char("."); show_context; 849@y 850print_char("."); show_context; 851if (halt_on_error_p) then begin 852 history:=fatal_error_stop; jump_out; 853end; 854@z 855 856@x [6.84] l.1888 - Implement the switch-to-editor option. 857line ready to be edited. But such an extension requires some system 858wizardry, so the present implementation simply types out the name of the 859file that should be 860edited and the relevant line number. 861@^system dependencies@> 862 863There is a secret `\.D' option available when the debugging routines haven't 864been commented~out. 865@^debugging@> 866@y 867line ready to be edited. 868We do this by calling the external procedure |call_edit| with a pointer to 869the filename, its length, and the line number. 870However, here we just set up the variables that will be used as arguments, 871since we don't want to do the switch-to-editor until after TeX has closed 872its files. 873@^system dependencies@> 874 875There is a secret `\.D' option available when the debugging routines haven't 876been commented~out. 877@^debugging@> 878@d edit_file==input_stack[base_ptr] 879@z 880 881@x [6.84] l.1903 - Implement the switch-to-editor option. 882"E": if base_ptr>0 then 883 begin print_nl("You want to edit file "); 884@.You want to edit file x@> 885 slow_print(input_stack[base_ptr].name_field); 886 print(" at line "); print_int(line); 887 interaction:=scroll_mode; jump_out; 888@y 889"E": if base_ptr>0 then 890 begin edit_name_start:=str_start[edit_file.name_field]; 891 edit_name_length:=str_start[edit_file.name_field+1] - 892 str_start[edit_file.name_field]; 893 edit_line:=line; 894 jump_out; 895@z 896 897@x [6.93] l.2056 - Declare fatal_error as noreturn. 898procedure fatal_error(@!s:str_number); {prints |s|, and that's it} 899@y 900noreturn procedure fatal_error(@!s:str_number); {prints |s|, and that's it} 901@z 902 903@x [6.94] l.2065 - Declare overflow as noreturn. 904procedure overflow(@!s:str_number;@!n:integer); {stop due to finiteness} 905@y 906noreturn procedure overflow(@!s:str_number;@!n:integer); {stop due to finiteness} 907@z 908 909@x [6.95] l.2084 - Declare confusion as noreturn. 910procedure confusion(@!s:str_number); 911@y 912noreturn procedure confusion(@!s:str_number); 913@z 914 915% [7.104] `remainder' is a library routine on some systems, so change 916% its name to avoid conflicts. 917@x [7.104] l.2227 - avoid name conflicts with lib routine remainder() 918|remainder|, holds the remainder after a division. 919 920@<Glob...@>= 921@y 922|remainder|, holds the remainder after a division. 923 924@d remainder==tex_remainder 925 926@<Glob...@>= 927@z 928 929@x [7.109] l.2352 - Define glue_ratio in C. 930@!glue_ratio=real; {one-word representation of a glue expansion factor} 931@y 932@z 933 934% [8.110] Make it easy to change constants. Do not increase 935% max_quarterword without changing the memoryword structure in `texmfmem.h'. 936@x [8.110] l.2422 - increase |max_halfword| 937@d min_halfword==0 {smallest allowable value in a |halfword|} 938@d max_halfword==65535 {largest allowable value in a |halfword|} 939@y 2424 940@d min_halfword==-@"FFFFFFF {smallest allowable value in a |halfword|} 941@d max_halfword==@"FFFFFFF {largest allowable value in a |halfword|} 942@z 943 944@x [8.111] l.2435 - min_halfword and max_halfword 945if (mem_min<min_halfword)or(mem_max>=max_halfword)or@| 946 (mem_bot-mem_min>max_halfword+1) then bad:=14; 947@y 948if (mem_bot-sup_main_memory<min_halfword)or@| 949 (mem_top+sup_main_memory>=max_halfword) then bad:=14; 950@z 951 952@x [8.111] l.2437 - max_font_max 953if (font_base<min_quarterword)or(font_max>max_quarterword) then bad:=15; 954if font_max>font_base+256 then bad:=16; 955@y 956if (max_font_max<min_halfword)or(max_font_max>max_halfword) then bad:=15; 957if font_max>font_base+max_font_max then bad:=16; 958@z 959 960@x [8.112] l.2450 - Efficiency. 961macros are simplified in the obvious way when |min_quarterword=0|. 962@^inner loop@>@^system dependencies@> 963 964@d qi(#)==#+min_quarterword 965 {to put an |eight_bits| item into a quarterword} 966@d qo(#)==#-min_quarterword 967 {to take an |eight_bits| item out of a quarterword} 968@d hi(#)==#+min_halfword 969 {to put a sixteen-bit item into a halfword} 970@d ho(#)==#-min_halfword 971 {to take a sixteen-bit item from a halfword} 972@y 973macros are simplified in the obvious way when |min_quarterword=0|. 974So they have been simplified here in the obvious way. 975@^inner loop@>@^system dependencies@> 976 977The \.{WEB} source for \TeX\ defines |hi(#)==#+min_halfword| which can be 978simplified when |min_halfword=0|. The Web2C implemetation of \TeX\ can use 979|hi(#)==#| together with |min_halfword<0| as long as |max_halfword| is 980sufficiently large. 981 982@d qi(#)==# {to put an |eight_bits| item into a quarterword} 983@d qo(#)==# {to take an |eight_bits| item from a quarterword} 984@d hi(#)==# {to put a sixteen-bit item into a halfword} 985@d ho(#)==# {to take a sixteen-bit item from a halfword} 986@z 987 988% [8.113] We've put the memory structure into the include file 989% `texmf.h', since it's too hard to translate automatically. 990@x [8.113] l.2453 - data structures for main memory 991@!quarterword = min_quarterword..max_quarterword; {1/4 of a word} 992@!halfword=min_halfword..max_halfword; {1/2 of a word} 993@!two_choices = 1..2; {used when there are two variants in a record} 994@!four_choices = 1..4; {used when there are four variants in a record} 995@!two_halves = packed record@;@/ 996 @!rh:halfword; 997 case two_choices of 998 1: (@!lh:halfword); 999 2: (@!b0:quarterword; @!b1:quarterword); 1000 end; 1001@!four_quarters = packed record@;@/ 1002 @!b0:quarterword; 1003 @!b1:quarterword; 1004 @!b2:quarterword; 1005 @!b3:quarterword; 1006 end; 1007@!memory_word = record@;@/ 1008 case four_choices of 1009 1: (@!int:integer); 1010 2: (@!gr:glue_ratio); 1011 3: (@!hh:two_halves); 1012 4: (@!qqqq:four_quarters); 1013 end; 1014@y 1015@!quarterword = min_quarterword..max_quarterword; 1016@!halfword = min_halfword..max_halfword; 1017@!two_choices = 1..2; {used when there are two variants in a record} 1018@!four_choices = 1..4; {used when there are four variants in a record} 1019@=#include "texmfmem.h";@> 1020@z 1021 1022% [9.116] Change `mem' to `zmem', so we can define mem to be a register 1023% pointer to the memory array for speed. 1024@x [9.116] l.2545 - definition of main memory array 1025@!mem : array[mem_min..mem_max] of memory_word; {the big dynamic storage area} 1026@y 1027@!yzmem : ^memory_word; {the big dynamic storage area} 1028@!zmem : ^memory_word; {the big dynamic storage area} 1029@z 1030 1031@x [10.144] l.3006 - font numbers can be >255 now. 1032@p function new_ligature(@!f,@!c:quarterword; @!q:pointer):pointer; 1033@y 1034@p function new_ligature(@!f:internal_font_number; @!c:quarterword; 1035 @!q:pointer):pointer; 1036@z 1037 1038% [11.165] Fix the word `free' so that it doesn't conflict with the 1039% standard C library routine of the same name. 1040@x [11.165] l.3364 - avoid conflict with lib function free() 1041are debugging.) 1042@y 1043are debugging.) 1044 1045@d free==free_arr 1046@z 1047 1048@x [11.165] l.3367 - dummy |free| and |was_free| arrays 1049@!debug @!free: packed array [mem_min..mem_max] of boolean; {free cells} 1050@t\hskip10pt@>@!was_free: packed array [mem_min..mem_max] of boolean; 1051@y 1052 {The debug memory arrays have not been mallocated yet.} 1053@!debug @!free: packed array [0..9] of boolean; {free cells} 1054@t\hskip10pt@>@!was_free: packed array [0..9] of boolean; 1055@z 1056 1057@x [12.174] l.3526 - Eliminate unsigned comparisons to zero. 1058 begin if (font(p)<font_base)or(font(p)>font_max) then 1059@y 1060 begin if (font(p)>font_max) then 1061@z 1062 1063@x [12.176] l.3563 - Eliminate unsigned comparisons to zero. 1064@p procedure print_font_and_char(@!p:integer); {prints |char_node| data} 1065begin if p>mem_end then print_esc("CLOBBERED.") 1066else begin if (font(p)<font_base)or(font(p)>font_max) then print_char("*") 1067@y 1068@p procedure print_font_and_char(@!p:integer); {prints |char_node| data} 1069begin if p>mem_end then print_esc("CLOBBERED.") 1070else begin if (font(p)>font_max) then print_char("*") 1071@z 1072 1073@x [12.186] l.3747 - Don't worry about strange floating point values. 1074 if abs(mem[p+glue_offset].int)<@'4000000 then print("?.?") 1075 else if abs(g)>float_constant(20000) then 1076@y 3747 1077 { The Unix |pc| folks removed this restriction with a remark that 1078 invalid bit patterns were vanishingly improbable, so we follow 1079 their example without really understanding it. 1080 |if abs(mem[p+glue_offset].int)<@'4000000 then print('?.?')| 1081 |else| } 1082 if fabs(g)>float_constant(20000) then 1083@z 1084 1085 1086@x [15.209] l.4165 - MLTeX: \charsubdef primitive 1087@d shorthand_def=95 {code definition ( \.{\\chardef}, \.{\\countdef}, etc.~)} 1088@y 1089@d shorthand_def=95 {code definition ( \.{\\chardef}, \.{\\countdef}, etc.~)} 1090 {or \.{\\charsubdef}} 1091@z 1092 1093% i18n fix: messages printed by print_mode in [16.211] and [46.1049] 1094% can not be translated. For example, messages printed by |print_mode| 1095% from [16.211] use different word order and [46.1049] use different 1096% word order and words are declined. 1097@x [16.211] l.4256 1098begin if m>0 then 1099 case m div (max_command+1) of 1100 0:print("vertical"); 1101 1:print("horizontal"); 1102 2:print("display math"); 1103 end 1104else if m=0 then print("no") 1105else case (-m) div (max_command+1) of 1106 0:print("internal vertical"); 1107 1:print("restricted horizontal"); 1108 2:print("math"); 1109 end; 1110print(" mode"); 1111end; 1112@y 1113begin if m>0 then 1114 case m div (max_command+1) of 1115 0:print("vertical mode"); 1116 1:print("horizontal mode"); 1117 2:print("display math mode"); 1118 end 1119else if m=0 then print("no mode") 1120else case (-m) div (max_command+1) of 1121 0:print("internal vertical mode"); 1122 1:print("restricted horizontal mode"); 1123 2:print("math mode"); 1124 end; 1125end; 1126 1127procedure print_in_mode(@!m:integer); {prints the mode represented by |m|} 1128begin if m>0 then 1129 case m div (max_command+1) of 1130 0:print("' in vertical mode"); 1131 1:print("' in horizontal mode"); 1132 2:print("' in display math mode"); 1133 end 1134else if m=0 then print("' in no mode") 1135else case (-m) div (max_command+1) of 1136 0:print("' in internal vertical mode"); 1137 1:print("' in restricted horizontal mode"); 1138 2:print("' in math mode"); 1139 end; 1140end; 1141@z 1142 1143@x [16.213] l.4321 - texarray 1144@!nest:array[0..nest_size] of list_state_record; 1145@y 1146@!nest:^list_state_record; 1147@z 1148 1149@x [16.215] l.4344 - remove mem[] reference from initialize. 1150prev_graf:=0; shown_mode:=0; 1151@<Start a new current page@>; 1152@y 1153prev_graf:=0; shown_mode:=0; 1154@/{The following piece of code is a copy of module 991:} 1155page_contents:=empty; page_tail:=page_head; {|link(page_head):=null;|}@/ 1156last_glue:=max_halfword; last_penalty:=0; last_kern:=0; 1157page_depth:=0; page_max_depth:=0; 1158@z 1159 1160@x [16.219] l.4409 - i18n fix 1161 print_int(nest[p].pg_field); print(" line"); 1162 if nest[p].pg_field<>1 then print_char("s"); 1163@y 1164 print_int(nest[p].pg_field); 1165 if nest[p].pg_field<>1 then print(" lines") 1166 else print(" line"); 1167@z 1168 1169@x [17.220] l.4448 - MLTeX: char_sub_code_base 1170paragraph shape. 1171@y 1172paragraph shape. 1173Additionally region~4 contains the table with ML\TeX's character 1174substitution definitions. 1175@z 1176 1177@x [17.222] l.4523 - frozen_special, for source specials. 1178@d frozen_null_font=frozen_control_sequence+10 1179@y 1180@d frozen_special=frozen_control_sequence+10 1181 {permanent `\.{\\special}'} 1182@d frozen_null_font=frozen_control_sequence+11 1183@z 1184 1185@x [17.222] l.4526 - max_font_max 1186@d undefined_control_sequence=frozen_null_font+257 {dummy location} 1187@y 1188@d undefined_control_sequence=frozen_null_font+max_font_max+1 {dummy location} 1189@z 1190 1191@x [17.222] l.4533 - hash_extra 1192for k:=active_base to undefined_control_sequence-1 do 1193 eqtb[k]:=eqtb[undefined_control_sequence]; 1194@y 1195for k:=active_base to eqtb_top do 1196 eqtb[k]:=eqtb[undefined_control_sequence]; 1197@z 1198 1199@x [17.230] l.4731 - MLTeX: char_sub_code_base 1200@d int_base=math_code_base+256 {beginning of region 5} 1201@y 1202@d char_sub_code_base=math_code_base+256 {table of character substitutions} 1203@d int_base=char_sub_code_base+256 {beginning of region 5} 1204@z 1205 1206@x [17.230] l.4752 - MLTeX: char_sub_code_base 1207 {Note: |math_code(c)| is the true math code plus |min_halfword|} 1208@y 1209 {Note: |math_code(c)| is the true math code plus |min_halfword|} 1210@d char_sub_code(#)==equiv(char_sub_code_base+#) 1211 {Note: |char_sub_code(c)| is the true substitution info plus |min_halfword|} 1212@z 1213 1214% MLTeX: \charsubdefmax and \tracingcharsubdef 1215@x [17.236] l.4954 1216@d int_pars=55 {total number of integer parameters} 1217@y 1218@d tex_int_pars=55 {total number of \TeX's integer parameters} 1219@# 1220@d web2c_int_base=tex_int_pars {base for web2c's integer parameters} 1221@d char_sub_def_min_code=web2c_int_base {smallest value in the charsubdef list} 1222@d char_sub_def_max_code=web2c_int_base+1 {largest value in the charsubdef list} 1223@d tracing_char_sub_def_code=web2c_int_base+2 {traces changes to a charsubdef def} 1224@d web2c_int_pars=web2c_int_base+3 {total number of web2c's integer parameters} 1225@# 1226@d int_pars=web2c_int_pars {total number of integer parameters} 1227@z 1228 1229% MLTeX: \charsubdefmax and \tracingcharsubdef 1230@x [17.236] l.5016 1231@d error_context_lines==int_par(error_context_lines_code) 1232@y 1233@d error_context_lines==int_par(error_context_lines_code) 1234@# 1235@d char_sub_def_min==int_par(char_sub_def_min_code) 1236@d char_sub_def_max==int_par(char_sub_def_max_code) 1237@d tracing_char_sub_def==int_par(tracing_char_sub_def_code) 1238@z 1239 1240% MLTeX: \charsubdefmax and \tracingcharsubdef 1241@x [17.237] l.5080 1242error_context_lines_code:print_esc("errorcontextlines"); 1243@y 1244error_context_lines_code:print_esc("errorcontextlines"); 1245char_sub_def_min_code:print_esc("charsubdefmin"); 1246char_sub_def_max_code:print_esc("charsubdefmax"); 1247tracing_char_sub_def_code:print_esc("tracingcharsubdef"); 1248@z 1249 1250% MLTeX: \charsubdefmax and \tracingcharsubdef 1251@x [17.238] l.5200 1252@!@:error_context_lines_}{\.{\\errorcontextlines} primitive@> 1253@y 1254@!@:error_context_lines_}{\.{\\errorcontextlines} primitive@> 1255if mltex_p then 1256 begin mltex_enabled_p:=true; {enable character substitution} 1257 if false then {remove the if-clause to enable \.{\\charsubdefmin}} 1258 primitive("charsubdefmin",assign_int,int_base+char_sub_def_min_code);@/ 1259@!@:char_sub_def_min_}{\.{\\charsubdefmin} primitive@> 1260 primitive("charsubdefmax",assign_int,int_base+char_sub_def_max_code);@/ 1261@!@:char_sub_def_max_}{\.{\\charsubdefmax} primitive@> 1262 primitive("tracingcharsubdef",assign_int,int_base+tracing_char_sub_def_code);@/ 1263@!@:tracing_char_sub_def_}{\.{\\tracingcharsubdef} primitive@> 1264 end; 1265@z 1266 1267@x [17.240] l.5213 - MLTeX: \charsubdefmax and \tracingcharsubdef 1268for k:=int_base to del_code_base-1 do eqtb[k].int:=0; 1269@y 1270for k:=int_base to del_code_base-1 do eqtb[k].int:=0; 1271char_sub_def_min:=256; char_sub_def_max:=-1; 1272{allow \.{\\charsubdef} for char 0}@/ 1273{|tracing_char_sub_def:=0| is already done}@/ 1274@z 1275 1276@x [17.241] l.5219 - Do `fix_date_and_time' in C. 1277@ The following procedure, which is called just before \TeX\ initializes its 1278input and output, establishes the initial values of the date and time. 1279@^system dependencies@> 1280Since standard \PASCAL\ cannot provide such information, something special 1281is needed. The program here simply specifies July 4, 1776, at noon; but 1282users probably want a better approximation to the truth. 1283 1284@p procedure fix_date_and_time; 1285begin time:=12*60; {minutes since midnight} 1286day:=4; {fourth day of the month} 1287month:=7; {seventh month of the year} 1288year:=1776; {Anno Domini} 1289end; 1290@y 1291@ The following procedure, which is called just before \TeX\ initializes its 1292input and output, establishes the initial values of the date and time. 1293It calls a macro-defined |date_and_time| routine. |date_and_time| 1294in turn is a C macro, which calls |get_date_and_time|, passing 1295it the addresses of the day, month, etc., so they can be set by the 1296routine. |get_date_and_time| also sets up interrupt catching if that 1297is conditionally compiled in the C code. 1298@^system dependencies@> 1299 1300@d fix_date_and_time==date_and_time(time,day,month,year) 1301@z 1302 1303@x [17.252] l.5420 - hash_extra 1304else if n<glue_base then @<Show equivalent |n|, in region 1 or 2@> 1305@y 1306else if (n<glue_base) or ((n>eqtb_size)and(n<=eqtb_top)) then 1307 @<Show equivalent |n|, in region 1 or 2@> 1308@z 1309 1310@x [17.253] l.5435 - Change eqtb to zeqtb. 1311@!eqtb:array[active_base..eqtb_size] of memory_word; 1312@y 1313@!zeqtb:^memory_word; 1314@z 1315 1316@x [18.256] l.5483 - hash_extra 1317@!hash: array[hash_base..undefined_control_sequence-1] of two_halves; 1318 {the hash table} 1319@!hash_used:pointer; {allocation pointer for |hash|} 1320@y 1321@!hash: ^two_halves; {the hash table} 1322@!yhash: ^two_halves; {auxiliary pointer for freeing hash} 1323@!hash_used:pointer; {allocation pointer for |hash|} 1324@!hash_extra:pointer; {|hash_extra=hash| above |eqtb_size|} 1325@!hash_top:pointer; {maximum of the hash array} 1326@!eqtb_top:pointer; {maximum of the |eqtb|} 1327@!hash_high:pointer; {pointer to next high hash location} 1328@z 1329 1330@x [18.257] l.5491 - hash_extra 1331next(hash_base):=0; text(hash_base):=0; 1332for k:=hash_base+1 to undefined_control_sequence-1 do hash[k]:=hash[hash_base]; 1333@y 1334@z 1335 1336@x [18.258] l.5495 - hash_extra 1337hash_used:=frozen_control_sequence; {nothing is used} 1338@y 1339hash_used:=frozen_control_sequence; {nothing is used} 1340hash_high:=0; 1341@z 1342 1343@x [18.260] l.5531 - hash_extra 1344@ @<Insert a new control...@>= 1345begin if text(p)>0 then 1346 begin repeat if hash_is_full then overflow("hash size",hash_size); 1347@:TeX capacity exceeded hash size}{\quad hash size@> 1348 decr(hash_used); 1349 until text(hash_used)=0; {search for an empty location in |hash|} 1350 next(p):=hash_used; p:=hash_used; 1351 end; 1352@y 1353@ @<Insert a new control...@>= 1354begin if text(p)>0 then 1355 begin if hash_high<hash_extra then 1356 begin incr(hash_high); 1357 next(p):=hash_high+eqtb_size; p:=hash_high+eqtb_size; 1358 end 1359 else begin 1360 repeat if hash_is_full then overflow("hash size",hash_size+hash_extra); 1361@:TeX capacity exceeded hash size}{\quad hash size@> 1362 decr(hash_used); 1363 until text(hash_used)=0; {search for an empty location in |hash|} 1364 next(p):=hash_used; p:=hash_used; 1365 end; 1366 end; 1367@z 1368 1369@x [18.262] l.5583 - hash_extra 1370else if p>=undefined_control_sequence then print_esc("IMPOSSIBLE.") 1371@y 1372else if ((p>=undefined_control_sequence)and(p<=eqtb_size))or(p>eqtb_top) then 1373 print_esc("IMPOSSIBLE.") 1374@z 1375 1376@x [18.262] l.5584 - Remove more unsigned comparisons to zero. 1377else if (text(p)<0)or(text(p)>=str_ptr) then print_esc("NONEXISTENT.") 1378@y 1379else if (text(p)>=str_ptr) then print_esc("NONEXISTENT.") 1380@z 1381 1382@x [19.271] l.5872 - texarray 1383@!save_stack : array[0..save_size] of memory_word; 1384@y 1385@!save_stack : ^memory_word; 1386@z 1387 1388@x [19.283] l.6050 - hash_extra 1389if p<int_base then 1390@y 1391if (p<int_base)or(p>eqtb_size) then 1392@z 1393 1394@x [20.290] l.6158 - hash_extra 1395if cs_token_flag+undefined_control_sequence>max_halfword then bad:=21; 1396@y 1397if cs_token_flag+eqtb_size+hash_extra>max_halfword then bad:=21; 1398if (hash_offset<0)or(hash_offset>hash_base) then bad:=42; 1399@z 1400 1401@x [22.301] l.6432 - texarray 1402@!input_stack : array[0..stack_size] of in_state_record; 1403@y 1404@!input_stack : ^in_state_record; 1405@z 1406 1407@x [22.304] l.6536 - texarray; additions for file:line:error style. 1408@!input_file : array[1..max_in_open] of alpha_file; 1409@!line : integer; {current line number in the current source file} 1410@!line_stack : array[1..max_in_open] of integer; 1411@y 1412@!input_file : ^alpha_file; 1413@!line : integer; {current line number in the current source file} 1414@!line_stack : ^integer; 1415@!source_filename_stack : ^str_number; 1416@!full_source_filename_stack : ^str_number; 1417@z 1418 1419@x [22.306] l.6855 - i18n fix 1420 begin print_nl("Runaway "); 1421@.Runaway...@> 1422 case scanner_status of 1423 defining: begin print("definition"); p:=def_ref; 1424 end; 1425 matching: begin print("argument"); p:=temp_head; 1426 end; 1427 aligning: begin print("preamble"); p:=hold_head; 1428 end; 1429 absorbing: begin print("text"); p:=def_ref; 1430 end; 1431 end; {there are no other cases} 1432@y 1433 begin 1434@.Runaway...@> 1435 case scanner_status of 1436 defining: begin print_nl("Runaway definition"); p:=def_ref; 1437 end; 1438 matching: begin print_nl("Runaway argument"); p:=temp_head; 1439 end; 1440 aligning: begin print_nl("Runaway preamble"); p:=hold_head; 1441 end; 1442 absorbing: begin print_nl("Runaway text"); p:=def_ref; 1443 end; 1444 end; {there are no other cases} 1445@z 1446 1447@x [22.308] l.6701 - texarray 1448@!param_stack:array [0..param_size] of pointer; 1449 {token list pointers for parameters} 1450@y 1451@!param_stack: ^pointer; 1452 {token list pointers for parameters} 1453@z 1454 1455@x [23.328] l.7043 - keep top of source_filename_stack initialized 1456incr(in_open); push_input; index:=in_open; 1457@y 1458incr(in_open); push_input; index:=in_open; 1459source_filename_stack[index]:=0;full_source_filename_stack[index]:=0; 1460@z 1461 1462@x [23.331] l.7071 - init source file name stacks 1463begin input_ptr:=0; max_in_stack:=0; 1464@y 1465begin input_ptr:=0; max_in_stack:=0; 1466source_filename_stack[0]:=0;full_source_filename_stack[0]:=0; 1467@z 1468 1469@x [24.338] l.7164 - i18n fix 1470print(" while scanning "); 1471@y 1472@z 1473 1474@x [24.339] l.7185 - i18n fix 1475defining:begin print("definition"); info(p):=right_brace_token+"}"; 1476 end; 1477matching:begin print("use"); info(p):=par_token; long_state:=outer_call; 1478 end; 1479aligning:begin print("preamble"); info(p):=right_brace_token+"}"; q:=p; 1480 p:=get_avail; link(p):=q; info(p):=cs_token_flag+frozen_cr; 1481 align_state:=-1000000; 1482 end; 1483absorbing:begin print("text"); info(p):=right_brace_token+"}"; 1484@y 1485defining:begin print(" while scanning definition"); info(p):=right_brace_token+"}"; 1486 end; 1487matching:begin print(" while scanning use"); info(p):=par_token; long_state:=outer_call; 1488 end; 1489aligning:begin print(" while scanning preamble"); info(p):=right_brace_token+"}"; q:=p; 1490 p:=get_avail; link(p):=q; info(p):=cs_token_flag+frozen_cr; 1491 align_state:=-1000000; 1492 end; 1493absorbing:begin print(" while scanning text"); info(p):=right_brace_token+"}"; 1494@z 1495 1496@x [25.366] expansion depth check 1497The |expand| subroutine is used when |cur_cmd>max_command|. It removes a 1498@y 1499@ Sometimes, recursive calls to the following |expand| routine may 1500cause exhaustion of the run-time calling stack, resulting in 1501forced execution stops by the operating system. To diminish the chance 1502of this happening, a counter is used to keep track of the recursion 1503depth, in conjunction with a constant called |expand_depth|. 1504 1505This does not catch all possible infinite recursion loops, just the ones 1506that exhaust the application calling stack. The actual maximum value of 1507|expand_depth| is outside of our control, but the initial setting of 1508|10000| should be enough to prevent problems. 1509@^system dependencies@> 1510 1511@<Global...@>= 1512expand_depth_count:integer; 1513 1514@ @<Set init...@>= 1515expand_depth_count:=0; 1516 1517@ The |expand| subroutine is used when |cur_cmd>max_command|. It removes a 1518@z 1519 1520@x [25.366] 1521begin cv_backup:=cur_val; cvl_backup:=cur_val_level; radix_backup:=radix; 1522@y 1523begin 1524incr(expand_depth_count); 1525if expand_depth_count>=expand_depth then overflow("expansion depth",expand_depth); 1526cv_backup:=cur_val; cvl_backup:=cur_val_level; radix_backup:=radix; 1527@z 1528 1529@x [25.366] 1530cur_order:=co_backup; link(backup_head):=backup_backup; 1531@y 1532cur_order:=co_backup; link(backup_head):=backup_backup; 1533decr(expand_depth_count); 1534@z 1535 1536@x [28.501] l.9747 - \eof18 1537if_eof_code: begin scan_four_bit_int; b:=(read_open[cur_val]=closed); 1538 end; 1539@y 1540if_eof_code: begin scan_four_bit_int_or_18; 1541 if cur_val=18 then b:=not shellenabledp 1542 else b:=(read_open[cur_val]=closed); 1543 end; 1544@z 1545 1546@x [29.513] l.9951 - Area and extension rules for filenames. 1547@ The file names we shall deal with for illustrative purposes have the 1548following structure: If the name contains `\.>' or `\.:', the file area 1549consists of all characters up to and including the final such character; 1550otherwise the file area is null. If the remaining file name contains 1551`\..', the file extension consists of all such characters from the first 1552remaining `\..' to the end, otherwise the file extension is null. 1553@y 1554@ The file names we shall deal with have the 1555following structure: If the name contains `\./' or `\.:' 1556(for Amiga only), the file area 1557consists of all characters up to and including the final such character; 1558otherwise the file area is null. If the remaining file name contains 1559`\..', the file extension consists of all such characters from the last 1560`\..' to the end, otherwise the file extension is null. 1561@z 1562 1563@x [29.513] l.9963 - Area and extension rules for filenames. 1564@!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any} 1565@!ext_delimiter:pool_pointer; {the relevant `\..', if any} 1566@y 1567@!area_delimiter:pool_pointer; {the most recent `\./', if any} 1568@!ext_delimiter:pool_pointer; {the most recent `\..', if any} 1569@z 1570 1571@x [29.514] l.9973 - TeX area directories. 1572@d TEX_area=="TeXinputs:" 1573@.TeXinputs@> 1574@d TEX_font_area=="TeXfonts:" 1575@.TeXfonts@> 1576@y 1577In C, the default paths are specified separately. 1578@z 1579 1580@x [29.515] l.9995 - filenames: quoted 1581begin area_delimiter:=0; ext_delimiter:=0; 1582@y 1583begin area_delimiter:=0; ext_delimiter:=0; quoted_filename:=false; 1584@z 1585 1586@x [29.516] l.9992 - filenames: more_name 1587begin if c=" " then more_name:=false 1588@y 1589begin if (c=" ") and stop_at_space and (not quoted_filename) then 1590 more_name:=false 1591else if c="""" then begin 1592 quoted_filename:=not quoted_filename; 1593 more_name:=true; 1594 end 1595@z 1596 1597@x [29.516] l.9994 - filenames: more_name 1598 if (c=">")or(c=":") then 1599@y 1600 if IS_DIR_SEP(c) then 1601@z 1602 1603@x [29.516] l.9997 - filenames: more_name 1604 else if (c=".")and(ext_delimiter=0) then ext_delimiter:=cur_length; 1605@y 1606 else if c="." then ext_delimiter:=cur_length; 1607@z 1608 1609@x [29.517] l.10002 - end_name: string recycling 1610@ The third. 1611@^system dependencies@> 1612 1613@p procedure end_name; 1614@y 1615@ The third. 1616@^system dependencies@> 1617If a string is already in the string pool, the function 1618|slow_make_string| does not create a new string but returns this string 1619number, thus saving string space. Because of this new property of the 1620returned string number it is not possible to apply |flush_string| to 1621these strings. 1622 1623@p procedure end_name; 1624var temp_str: str_number; {result of file name cache lookups} 1625@!j,@!s,@!t: pool_pointer; {running indices} 1626@!must_quote:boolean; {whether we need to quote a string} 1627@z 1628 1629@x [29.517] l.10022 - end_name: spaces in filenames 1630@:TeX capacity exceeded number of strings}{\quad number of strings@> 1631@y 1632@:TeX capacity exceeded number of strings}{\quad number of strings@> 1633str_room(6); {Room for quotes, if needed.} 1634{add quotes if needed} 1635if area_delimiter<>0 then begin 1636 {maybe quote |cur_area|} 1637 must_quote:=false; 1638 s:=str_start[str_ptr]; 1639 t:=str_start[str_ptr]+area_delimiter; 1640 j:=s; 1641 while (not must_quote) and (j<t) do begin 1642 must_quote:=str_pool[j]=" "; incr(j); 1643 end; 1644 if must_quote then begin 1645 for j:=pool_ptr-1 downto t do str_pool[j+2]:=str_pool[j]; 1646 str_pool[t+1]:=""""; 1647 for j:=t-1 downto s do str_pool[j+1]:=str_pool[j]; 1648 str_pool[s]:=""""; 1649 if ext_delimiter<>0 then ext_delimiter:=ext_delimiter+2; 1650 area_delimiter:=area_delimiter+2; 1651 pool_ptr:=pool_ptr+2; 1652 end; 1653 end; 1654{maybe quote |cur_name|} 1655s:=str_start[str_ptr]+area_delimiter; 1656if ext_delimiter=0 then t:=pool_ptr else t:=str_start[str_ptr]+ext_delimiter-1; 1657must_quote:=false; 1658j:=s; 1659while (not must_quote) and (j<t) do begin 1660 must_quote:=str_pool[j]=" "; incr(j); 1661 end; 1662if must_quote then begin 1663 for j:=pool_ptr-1 downto t do str_pool[j+2]:=str_pool[j]; 1664 str_pool[t+1]:=""""; 1665 for j:=t-1 downto s do str_pool[j+1]:=str_pool[j]; 1666 str_pool[s]:=""""; 1667 if ext_delimiter<>0 then ext_delimiter:=ext_delimiter+2; 1668 pool_ptr:=pool_ptr+2; 1669 end; 1670if ext_delimiter<>0 then begin 1671 {maybe quote |cur_ext|} 1672 s:=str_start[str_ptr]+ext_delimiter-1; 1673 t:=pool_ptr; 1674 must_quote:=false; 1675 j:=s; 1676 while (not must_quote) and (j<t) do begin 1677 must_quote:=str_pool[j]=" "; incr(j); 1678 end; 1679 if must_quote then begin 1680 str_pool[t+1]:=""""; 1681 for j:=t-1 downto s do str_pool[j+1]:=str_pool[j]; 1682 str_pool[s]:=""""; 1683 pool_ptr:=pool_ptr+2; 1684 end; 1685 end; 1686@z 1687 1688@x [29.517] l.10011 - end_name: string recycling 1689 end; 1690if ext_delimiter=0 then 1691 begin cur_ext:=""; cur_name:=make_string; 1692@y 1693 temp_str:=search_string(cur_area); 1694 if temp_str>0 then 1695 begin cur_area:=temp_str; 1696 decr(str_ptr); {no |flush_string|, |pool_ptr| will be wrong!} 1697 for j:=str_start[str_ptr+1] to pool_ptr-1 do 1698 begin str_pool[j-area_delimiter]:=str_pool[j]; 1699 end; 1700 pool_ptr:=pool_ptr-area_delimiter; {update |pool_ptr|} 1701 end; 1702 end; 1703if ext_delimiter=0 then 1704 begin cur_ext:=""; cur_name:=slow_make_string; 1705@z 1706 1707@x [29.517] l.10016 - end_name: string recycling 1708 incr(str_ptr); cur_ext:=make_string; 1709@y 1710 incr(str_ptr); cur_ext:=make_string; 1711 decr(str_ptr); {undo extension string to look at name part} 1712 temp_str:=search_string(cur_name); 1713 if temp_str>0 then 1714 begin cur_name:=temp_str; 1715 decr(str_ptr); {no |flush_string|, |pool_ptr| will be wrong!} 1716 for j:=str_start[str_ptr+1] to pool_ptr-1 do 1717 begin str_pool[j-ext_delimiter+area_delimiter+1]:=str_pool[j]; 1718 end; 1719 pool_ptr:=pool_ptr-ext_delimiter+area_delimiter+1; {update |pool_ptr|} 1720 end; 1721 cur_ext:=slow_make_string; {remake extension string} 1722@z 1723 1724@x [29.518] l.10042 - print_file_name: quote if spaces in names. 1725some operating systems put the file area last instead of first.) 1726@^system dependencies@> 1727@y 1728some operating systems put the file area last instead of first.) 1729@^system dependencies@> 1730 1731@d check_quoted(#) == {check if string |#| needs quoting} 1732if #<>0 then begin 1733 j:=str_start[#]; 1734 while (not must_quote) and (j<str_start[#+1]) do begin 1735 must_quote:=str_pool[j]=" "; incr(j); 1736 end; 1737end 1738@# 1739@d print_quoted(#) == {print string |#|, omitting quotes} 1740if #<>0 then 1741 for j:=str_start[#] to str_start[#+1]-1 do 1742 if so(str_pool[j])<>"""" then 1743 print(so(str_pool[j])) 1744@z 1745 1746@x [29.518] l.10042 - print_file_name: quote if spaces in names. 1747begin slow_print(a); slow_print(n); slow_print(e); 1748@y 1749var must_quote: boolean; {whether to quote the filename} 1750@!j:pool_pointer; {index into |str_pool|} 1751begin 1752must_quote:=false; 1753check_quoted(a); check_quoted(n); check_quoted(e); 1754{FIXME: Alternative is to assume that any filename that has to be quoted has 1755 at least one quoted component...if we pick this, a number of insertions 1756 of |print_file_name| should go away. 1757|must_quote|:=((|a|<>0)and(|str_pool|[|str_start|[|a|]]=""""))or 1758 ((|n|<>0)and(|str_pool|[|str_start|[|n|]]=""""))or 1759 ((|e|<>0)and(|str_pool|[|str_start|[|e|]]=""""));} 1760if must_quote then print_char(""""); 1761print_quoted(a); print_quoted(n); print_quoted(e); 1762if must_quote then print_char(""""); 1763@z 1764 1765@x [29.519] l.10051 - have append_to_name skip quotes. 1766@d append_to_name(#)==begin c:=#; incr(k); 1767 if k<=file_name_size then name_of_file[k]:=xchr[c]; 1768 end 1769@y 1770@d append_to_name(#)==begin c:=#; if not (c="""") then begin incr(k); 1771 if k<=file_name_size then name_of_file[k]:=xchr[c]; 1772 end end 1773@z 1774 1775% [29.519] In pack_file_name, leave room for the extra null we append at 1776% the end of a filename. 1777@x [29.519] l.10047 - pack_file_name, leave room for the extra null 1778begin k:=0; 1779@y 1780begin k:=0; 1781if name_of_file then libc_free (name_of_file); 1782name_of_file:= xmalloc_array (ASCII_code, length(a)+length(n)+length(e)+1); 1783@z 1784 1785@x [29.519] l.10051 - pack_file_name, append the extra null 1786for k:=name_length+1 to file_name_size do name_of_file[k]:=' '; 1787@y 1788name_of_file[name_length+1]:=0; 1789@z 1790 1791@x [29.520] l.10060 - filenames: default format. 1792@d format_default_length=20 {length of the |TEX_format_default| string} 1793@d format_area_length=11 {length of its area part} 1794@d format_ext_length=4 {length of its `\.{.fmt}' part} 1795@y 1796Under {\mc UNIX} we don't give the area part, instead depending 1797on the path searching that will happen during file opening. Also, the 1798length will be set in the main program. 1799 1800@d format_area_length=0 {length of its area part} 1801@d format_ext_length=4 {length of its `\.{.fmt}' part} 1802@z 1803 1804@x [29.521] l.10066 - filenames: default format, where `plain.fmt' is. 1805@!TEX_format_default:packed array[1..format_default_length] of char; 1806 1807@ @<Set init...@>= 1808TEX_format_default:='TeXformats:plain.fmt'; 1809@y 1810@!format_default_length: integer; 1811@!TEX_format_default: cstring; 1812 1813@ We set the name of the default format file and the length of that name 1814in C, instead of Pascal, since we want them to depend on the name of the 1815program. 1816@z 1817 1818@x [29.523] l.10095 - Change to pack_buffered_name as with pack_file_name. 1819for j:=1 to n do append_to_name(xord[TEX_format_default[j]]); 1820for j:=a to b do append_to_name(buffer[j]); 1821for j:=format_default_length-format_ext_length+1 to format_default_length do 1822 append_to_name(xord[TEX_format_default[j]]); 1823if k<=file_name_size then name_length:=k@+else name_length:=file_name_size; 1824for k:=name_length+1 to file_name_size do name_of_file[k]:=' '; 1825@y 1826if name_of_file then libc_free (name_of_file); 1827name_of_file := xmalloc_array (ASCII_code, n+(b-a+1)+format_ext_length+1); 1828for j:=1 to n do append_to_name(xord[ucharcast(TEX_format_default[j])]); 1829for j:=a to b do append_to_name(buffer[j]); 1830for j:=format_default_length-format_ext_length+1 to format_default_length do 1831 append_to_name(xord[ucharcast(TEX_format_default[j])]); 1832if k<=file_name_size then name_length:=k@+else name_length:=file_name_size; 1833name_of_file[name_length+1]:=0; 1834@z 1835 1836@x [29.524] l.10118 - Format file opening: only try once, with path searching. 1837 pack_buffered_name(0,loc,j-1); {try first without the system file area} 1838 if w_open_in(fmt_file) then goto found; 1839 pack_buffered_name(format_area_length,loc,j-1); 1840 {now try the system format file area} 1841 if w_open_in(fmt_file) then goto found; 1842@y 1843 pack_buffered_name(0,loc,j-1); {Kpathsea does everything} 1844 if w_open_in(fmt_file) then goto found; 1845@z 1846 1847@x [29.524] l.10124 - replace `PLAIN' in error messages with `default'. 1848 wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.'); 1849@y 1850 wterm ('Sorry, I can''t find the format `'); 1851 fputs (stringcast(name_of_file + 1), stdout); 1852 wterm ('''; will try `'); 1853 fputs (TEX_format_default + 1, stdout); 1854 wterm_ln ('''.'); 1855@z 1856 1857@x [29.524] l.10132 - replace `PLAIN' in error messages with `default'. 1858 wterm_ln('I can''t find the PLAIN format file!'); 1859@.I can't find PLAIN...@> 1860@y 1861 wterm ('I can''t find the format file `'); 1862 fputs (TEX_format_default + 1, stdout); 1863 wterm_ln ('''!'); 1864@.I can't find the format...@> 1865@z 1866 1867@x [29.525] l.10170 - make_name_string 1868begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings)or 1869@y 1870save_area_delimiter, save_ext_delimiter: pool_pointer; 1871save_name_in_progress, save_stop_at_space: boolean; 1872begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings)or 1873@z 1874 1875@x [29.525] l.10174 - make_name_string 1876 make_name_string:=make_string; 1877@y 1878 make_name_string:=make_string; 1879 {At this point we also set |cur_name|, |cur_ext|, and |cur_area| to 1880 match the contents of |name_of_file|.} 1881 save_area_delimiter:=area_delimiter; save_ext_delimiter:=ext_delimiter; 1882 save_name_in_progress:=name_in_progress; save_stop_at_space:=stop_at_space; 1883 name_in_progress:=true; 1884 begin_name; 1885 stop_at_space:=false; 1886 k:=1; 1887 while (k<=name_length)and(more_name(name_of_file[k])) do 1888 incr(k); 1889 stop_at_space:=save_stop_at_space; 1890 end_name; 1891 name_in_progress:=save_name_in_progress; 1892 area_delimiter:=save_area_delimiter; ext_delimiter:=save_ext_delimiter; 1893@z 1894 1895@x [29.526] l.10194 - stop scanning file name if we're at end-of-line. 1896 if not more_name(cur_chr) then goto done; 1897@y 1898 {If |cur_chr| is a space and we're not scanning a token list, check 1899 whether we're at the end of the buffer. Otherwise we end up adding 1900 spurious spaces to file names in some cases.} 1901 if (cur_chr=" ") and (state<>token_list) and (loc>limit) then goto done; 1902 if not more_name(cur_chr) then goto done; 1903@z 1904 1905@x [29.530] l.10245 - prompt_file_name: prevent empty filenames. 1906var k:0..buf_size; {index into |buffer|} 1907@y 1908var k:0..buf_size; {index into |buffer|} 1909@!saved_cur_name:str_number; {to catch empty terminal input} 1910@!saved_cur_ext:str_number; {to catch empty terminal input} 1911@!saved_cur_area:str_number; {to catch empty terminal input} 1912@z 1913 1914@x [29.530] l.10252 - prompt_file_name: No default extension is TeX input file. 1915if e=".tex" then show_context; 1916@y 1917if (e=".tex") or (e="") then show_context; 1918print_ln; print_c_string(prompt_file_name_help_msg); 1919if (e<>"") then 1920 begin 1921 print("; default file extension is `"); print(e); print("'"); 1922 end; 1923print(")"); print_ln; 1924@z 1925 1926@x [29.530] l.10258 - prompt_file_name: prevent empty filenames. 1927clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>; 1928if cur_ext="" then cur_ext:=e; 1929@y 1930saved_cur_name:=cur_name; 1931saved_cur_ext:=cur_ext; 1932saved_cur_area:=cur_area; 1933clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>; 1934if (length(cur_name)=0) and (cur_ext="") and (cur_area="") then 1935 begin 1936 cur_name:=saved_cur_name; 1937 cur_ext:=saved_cur_ext; 1938 cur_area:=saved_cur_area; 1939 end 1940else 1941 if cur_ext="" then cur_ext:=e; 1942@z 1943 1944@x [29.532] l.10263 - avoid conflict, `logname' in <unistd.h> on some systems. 1945@d ensure_dvi_open==if output_file_name=0 then 1946@y 1947@d log_name == texmf_log_name 1948@d ensure_dvi_open==if output_file_name=0 then 1949@z 1950 1951@x [29.534] l.10285 - Adjust for C string conventions. 1952@!months:packed array [1..36] of char; {abbreviations of month names} 1953@y 1954@!months:const_cstring; 1955@z 1956 1957@x [29.534] l.10300 - Filename change for the recorder. 1958if job_name=0 then job_name:="texput"; 1959@.texput@> 1960@y 1961if job_name=0 then job_name:=get_job_name("texput"); 1962@.texput@> 1963pack_job_name(".fls"); 1964recorder_change_filename(stringcast(name_of_file+1)); 1965@z 1966 1967@x [29.534] l.10293 - MLTeX: add MLTeX banner after loading fmt file 1968@<Print the banner line, including the date and time@>; 1969@y 1970@<Print the banner line, including the date and time@>; 1971if mltex_enabled_p then 1972 begin wlog_cr; wlog('MLTeX v2.2 enabled'); 1973 end; 1974@z 1975 1976@x 1977begin wlog(banner); 1978@y 1979begin 1980if src_specials_p or file_line_error_style_p or parse_first_line_p 1981then 1982 wlog(banner_k) 1983else 1984 wlog(banner); 1985@z 1986 1987@x [29.536] l.10324 - Print rest of banner. 1988slow_print(format_ident); print(" "); 1989@y 1990wlog(version_string); 1991slow_print(format_ident); print(" "); 1992@z 1993 1994@x [29.536] l.10327 - Adjust for C string conventions. 1995months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'; 1996@y 1997months := ' JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'; 1998@z 1999 2000% Print whether we're using src-specials and other such features. 2001% Print TCX name if one's given. 2002@x [29.536] l.10331 2003end 2004@y 2005if shellenabledp then begin 2006 wlog_cr; 2007 wlog(' '); 2008 if restrictedshell then begin 2009 wlog('restricted '); 2010 end; 2011 wlog('\write18 enabled.') 2012 end; 2013if src_specials_p then begin 2014 wlog_cr; 2015 wlog(' Source specials enabled.') 2016 end; 2017if file_line_error_style_p then begin 2018 wlog_cr; 2019 wlog(' file:line:error style messages enabled.') 2020 end; 2021if parse_first_line_p then begin 2022 wlog_cr; 2023 wlog(' %&-line parsing enabled.'); 2024 end; 2025if translate_filename then begin 2026 wlog_cr; 2027 wlog(' ('); 2028 fputs(translate_filename, log_file); 2029 wlog(')'); 2030 end; 2031end 2032@z 2033 2034% [29.537] Use a path when calling a_open_in to do a \input; also, try 2035% to open the file with and without the `.tex' extension, regardless of 2036% whether the file already has an extension. This allows filenames like 2037% `foo' and `foo.bar.tex', as well as `foo.tex' and `foo.bar'. 2038@x [29.537] l.10338 - start_input 2039begin scan_file_name; {set |cur_name| to desired file name} 2040if cur_ext="" then cur_ext:=".tex"; 2041pack_cur_name; 2042loop@+ begin begin_file_reading; {set up |cur_file| and new level of input} 2043 if a_open_in(cur_file) then goto done; 2044 if cur_area="" then 2045 begin pack_file_name(cur_name,TEX_area,cur_ext); 2046 if a_open_in(cur_file) then goto done; 2047 end; 2048@y 2049var temp_str: str_number; 2050begin scan_file_name; {set |cur_name| to desired file name} 2051pack_cur_name; 2052loop@+begin 2053 begin_file_reading; {set up |cur_file| and new level of input} 2054 tex_input_type := 1; {Tell |open_input| we are \.{\\input}.} 2055 {Kpathsea tries all the various ways to get the file.} 2056 if kpse_in_name_ok(stringcast(name_of_file+1)) 2057 and a_open_in(cur_file, kpse_tex_format) then 2058 goto done; 2059@z 2060 2061@x [29.537] l.10348 - start_input: don't force ".tex" extension. 2062 prompt_file_name("input file name",".tex"); 2063@y 2064 prompt_file_name("input file name",""); 2065@z 2066 2067@x [29.537] l.10350 - start_input: string recycling 2068done: name:=a_make_name_string(cur_file); 2069@y 2070done: name:=a_make_name_string(cur_file); 2071source_filename_stack[in_open]:=name; 2072full_source_filename_stack[in_open]:=make_full_name_string; 2073if name=str_ptr-1 then {we can try to conserve string pool space now} 2074 begin temp_str:=search_string(name); 2075 if temp_str>0 then 2076 begin name:=temp_str; flush_string; 2077 end; 2078 end; 2079@z 2080 2081@x [29.537] l.10352 - start_input: was job_name given on the command line? 2082 begin job_name:=cur_name; open_log_file; 2083@y 2084 begin job_name:=get_job_name(cur_name); open_log_file; 2085@z 2086 2087@x [29.537] l.10356 - 2088if term_offset+length(name)>max_print_line-2 then print_ln 2089else if (term_offset>0)or(file_offset>0) then print_char(" "); 2090print_char("("); incr(open_parens); slow_print(name); update_terminal; 2091@y 2092if term_offset+length(full_source_filename_stack[in_open])>max_print_line-2 2093then print_ln 2094else if (term_offset>0)or(file_offset>0) then print_char(" "); 2095print_char("("); incr(open_parens); 2096slow_print(full_source_filename_stack[in_open]); update_terminal; 2097@z 2098 2099@x [29.537] l.10360 - start_input: don't return filename to string pool. 2100if name=str_ptr-1 then {we can conserve string pool space now} 2101 begin flush_string; name:=cur_name; 2102 end; 2103@y 2104@z 2105 2106@x [30.548] l.10673 - texarray 2107@!internal_font_number=font_base..font_max; {|font| in a |char_node|} 2108@!font_index=0..font_mem_size; {index into |font_info|} 2109@y 2110@!internal_font_number=integer; {|font| in a |char_node|} 2111@!font_index=integer; {index into |font_info|} 2112@!nine_bits=min_quarterword..non_char; 2113@z 2114 2115@x [30.549] l.10682 - texarray 2116@!font_info:array[font_index] of memory_word; 2117 {the big collection of font data} 2118@!fmem_ptr:font_index; {first unused word of |font_info|} 2119@!font_ptr:internal_font_number; {largest internal font number in use} 2120@!font_check:array[internal_font_number] of four_quarters; {check sum} 2121@!font_size:array[internal_font_number] of scaled; {``at'' size} 2122@!font_dsize:array[internal_font_number] of scaled; {``design'' size} 2123@!font_params:array[internal_font_number] of font_index; {how many font 2124 parameters are present} 2125@!font_name:array[internal_font_number] of str_number; {name of the font} 2126@!font_area:array[internal_font_number] of str_number; {area of the font} 2127@!font_bc:array[internal_font_number] of eight_bits; 2128 {beginning (smallest) character code} 2129@!font_ec:array[internal_font_number] of eight_bits; 2130 {ending (largest) character code} 2131@!font_glue:array[internal_font_number] of pointer; 2132 {glue specification for interword space, |null| if not allocated} 2133@!font_used:array[internal_font_number] of boolean; 2134 {has a character from this font actually appeared in the output?} 2135@!hyphen_char:array[internal_font_number] of integer; 2136 {current \.{\\hyphenchar} values} 2137@!skew_char:array[internal_font_number] of integer; 2138 {current \.{\\skewchar} values} 2139@!bchar_label:array[internal_font_number] of font_index; 2140 {start of |lig_kern| program for left boundary character, 2141 |non_address| if there is none} 2142@!font_bchar:array[internal_font_number] of min_quarterword..non_char; 2143 {right boundary character, |non_char| if there is none} 2144@!font_false_bchar:array[internal_font_number] of min_quarterword..non_char; 2145 {|font_bchar| if it doesn't exist in the font, otherwise |non_char|} 2146@y 2147@!font_info: ^fmemory_word; 2148 {the big collection of font data} 2149@!fmem_ptr:font_index; {first unused word of |font_info|} 2150@!font_ptr:internal_font_number; {largest internal font number in use} 2151@!font_check: ^four_quarters; {check sum} 2152@!font_size: ^scaled; {``at'' size} 2153@!font_dsize: ^scaled; {``design'' size} 2154@!font_params: ^font_index; {how many font 2155 parameters are present} 2156@!font_name: ^str_number; {name of the font} 2157@!font_area: ^str_number; {area of the font} 2158@!font_bc: ^eight_bits; 2159 {beginning (smallest) character code} 2160@!font_ec: ^eight_bits; 2161 {ending (largest) character code} 2162@!font_glue: ^pointer; 2163 {glue specification for interword space, |null| if not allocated} 2164@!font_used: ^boolean; 2165 {has a character from this font actually appeared in the output?} 2166@!hyphen_char: ^integer; 2167 {current \.{\\hyphenchar} values} 2168@!skew_char: ^integer; 2169 {current \.{\\skewchar} values} 2170@!bchar_label: ^font_index; 2171 {start of |lig_kern| program for left boundary character, 2172 |non_address| if there is none} 2173@!font_bchar: ^nine_bits; 2174 {right boundary character, |non_char| if there is none} 2175@!font_false_bchar: ^nine_bits; 2176 {|font_bchar| if it doesn't exist in the font, otherwise |non_char|} 2177@z 2178 2179@x [30.550] l.10723 - texarray 2180@!char_base:array[internal_font_number] of integer; 2181 {base addresses for |char_info|} 2182@!width_base:array[internal_font_number] of integer; 2183 {base addresses for widths} 2184@!height_base:array[internal_font_number] of integer; 2185 {base addresses for heights} 2186@!depth_base:array[internal_font_number] of integer; 2187 {base addresses for depths} 2188@!italic_base:array[internal_font_number] of integer; 2189 {base addresses for italic corrections} 2190@!lig_kern_base:array[internal_font_number] of integer; 2191 {base addresses for ligature/kerning programs} 2192@!kern_base:array[internal_font_number] of integer; 2193 {base addresses for kerns} 2194@!exten_base:array[internal_font_number] of integer; 2195 {base addresses for extensible recipes} 2196@!param_base:array[internal_font_number] of integer; 2197 {base addresses for font parameters} 2198@y 2199@!char_base: ^integer; 2200 {base addresses for |char_info|} 2201@!width_base: ^integer; 2202 {base addresses for widths} 2203@!height_base: ^integer; 2204 {base addresses for heights} 2205@!depth_base: ^integer; 2206 {base addresses for depths} 2207@!italic_base: ^integer; 2208 {base addresses for italic corrections} 2209@!lig_kern_base: ^integer; 2210 {base addresses for ligature/kerning programs} 2211@!kern_base: ^integer; 2212 {base addresses for kerns} 2213@!exten_base: ^integer; 2214 {base addresses for extensible recipes} 2215@!param_base: ^integer; 2216 {base addresses for font parameters} 2217@z 2218 2219@x [30.551] l.10743 - texarray 2220for k:=font_base to font_max do font_used[k]:=false; 2221@y 2222@z 2223 2224@x [30.552] l.10749 - texarray 2225font_ptr:=null_font; fmem_ptr:=7; 2226font_name[null_font]:="nullfont"; font_area[null_font]:=""; 2227hyphen_char[null_font]:="-"; skew_char[null_font]:=-1; 2228bchar_label[null_font]:=non_address; 2229font_bchar[null_font]:=non_char; font_false_bchar[null_font]:=non_char; 2230font_bc[null_font]:=1; font_ec[null_font]:=0; 2231font_size[null_font]:=0; font_dsize[null_font]:=0; 2232char_base[null_font]:=0; width_base[null_font]:=0; 2233height_base[null_font]:=0; depth_base[null_font]:=0; 2234italic_base[null_font]:=0; lig_kern_base[null_font]:=0; 2235kern_base[null_font]:=0; exten_base[null_font]:=0; 2236font_glue[null_font]:=null; font_params[null_font]:=7; 2237param_base[null_font]:=-1; 2238for k:=0 to 6 do font_info[k].sc:=0; 2239@y 2240@z 2241 2242@x [30.554] l.10795 - MLTeX: |effective_char| in |char_info| 2243as fast as possible under the circumstances. 2244@^inner loop@> 2245 2246@d char_info_end(#)==#].qqqq 2247@d char_info(#)==font_info[char_base[#]+char_info_end 2248@y 2249as fast as possible under the circumstances. 2250@^inner loop@> 2251 2252ML\TeX{} will assume that a character |c| exists iff either exists in 2253the current font or a character substitution definition for this 2254character was defined using \.{\\charsubdef}. To avoid the 2255distinction between these two cases, ML\TeX{} introduces the notion 2256``effective character'' of an input character |c|. If |c| exists in 2257the current font, the effective character of |c| is the character |c| 2258itself. If it doesn't exist but a character substitution is defined, 2259the effective character of |c| is the base character defined in the 2260character substitution. If there is an effective character for a 2261non-existing character |c|, the ``virtual character'' |c| will get 2262appended to the horizontal lists. 2263 2264The effective character is used within |char_info| to access 2265appropriate character descriptions in the font. For example, when 2266calculating the width of a box, ML\TeX{} will use the metrics of the 2267effective characters. For the case of a substitution, ML\TeX{} uses 2268the metrics of the base character, ignoring the metrics of the accent 2269character. 2270 2271If character substitutions are changed, it will be possible that a 2272character |c| neither exists in a font nor there is a valid character 2273substitution for |c|. To handle these cases |effective_char| should 2274be called with its first argument set to |true| to ensure that it 2275will still return an existing character in the font. If neither |c| 2276nor the substituted base character in the current character 2277substitution exists, |effective_char| will output a warning and 2278return the character |font_bc[f]| (which is incorrect, but can not be 2279changed within the current framework). 2280 2281Sometimes character substitutions are unwanted, therefore the 2282original definition of |char_info| can be used using the macro 2283|orig_char_info|. Operations in which character substitutions should 2284be avoided are, for example, loading a new font and checking the font 2285metric information in this font, and character accesses in math mode. 2286 2287@d char_list_exists(#)==(char_sub_code(#)>hi(0)) 2288@d char_list_accent(#)==(ho(char_sub_code(#)) div 256) 2289@d char_list_char(#)==(ho(char_sub_code(#)) mod 256) 2290@# 2291@d char_info_end(#)== #@=)@>].qqqq 2292@d char_info(#)== 2293 font_info[char_base[#]+effective_char@=(@>true,#,char_info_end 2294@# 2295@d orig_char_info_end(#)==#].qqqq 2296@d orig_char_info(#)==font_info[char_base[#]+orig_char_info_end 2297@# 2298@z 2299 2300@x [30] m.560 l.10876 - MLTeX: |effective_char| in |char_info| 2301@p function read_font_info(@!u:pointer;@!nom,@!aire:str_number; 2302@y 2303@p @t\4@>@<Declare additional functions for ML\TeX@>@/ 2304 2305function read_font_info(@!u:pointer;@!nom,@!aire:str_number; 2306@z 2307 2308@x [30.560] l.10898 - Check lengths 2309@!file_opened:boolean; {was |tfm_file| successfully opened?} 2310@y 2311@!name_too_long:boolean; {|nom| or |aire| exceeds 255 bytes?} 2312@!file_opened:boolean; {was |tfm_file| successfully opened?} 2313@z 2314 2315@x [30.561] l.10939 - Check lengths 2316else print(" not loadable: Metric (TFM) file not found"); 2317@y 2318else if name_too_long then print(" not loadable: Metric (TFM) file name too long") 2319else print(" not loadable: Metric (TFM) file not found"); 2320@z 2321 2322@x [30.563] l.10961 - Check lengths, don't use TEX_font_area. 2323if aire="" then pack_file_name(nom,TEX_font_area,".tfm") 2324else pack_file_name(nom,aire,".tfm"); 2325@y 2326name_too_long:=(length(nom)>255)or(length(aire)>255); 2327if name_too_long then abort; 2328{|kpse_find_file| will append the |".tfm"|, and avoid searching the disk 2329 before the font alias files as well.} 2330pack_file_name(nom,aire,""); 2331@z 2332 2333% [30.564] Reading the tfm file. As a special case, whenever we open a 2334% tfm file, we read its first byte into `tfm_temp' right away. TeX 2335% looks at `fbyte' before calling `fget', so it ends up seeing every 2336% byte. This is Pascal-like I/O. 2337@x [30.564] l.10956 - reading the tfm file, define fget & fbyte 2338@d fget==get(tfm_file) 2339@d fbyte==tfm_file^ 2340@y 2341@d fget==tfm_temp:=getc(tfm_file) 2342@d fbyte==tfm_temp 2343@z 2344 2345@x [30.570] l.11064 - MLTeX: fix for bug while loading font 2346 begin qw:=char_info(f)(d); 2347@y 2348 begin qw:=orig_char_info(f)(d); 2349@z 2350 2351@x [30.573] l.11116 - MLTeX: fix for bug while loading font 2352 qw:=char_info(f)(#); {N.B.: not |qi(#)|} 2353@y 2354 qw:=orig_char_info(f)(#); {N.B.: not |qi(#)|} 2355@z 2356 2357% [30.575] We only want `eof' on the TFM file to be true if we 2358% previously had EOF, not if we're at EOF now. This is like `feof', and 2359% unlike our implementation of `eof' elsewhere. 2360@x [30.575] l.11180 - Reading the tfm file, replace eof() by feof(). 2361if eof(tfm_file) then abort; 2362@y 2363if feof(tfm_file) then abort; 2364@z 2365 2366@x [30.576] l.11180 - MLTeX: fix for bug while loading font 2367 begin qw:=char_info(f)(bchar); {N.B.: not |qi(bchar)|} 2368@y 2369 begin qw:=orig_char_info(f)(bchar); {N.B.: not |qi(bchar)|} 2370@z 2371 2372@x [30.582] l.11276 - MLTeX: call |effective_char| in |new_character| 2373@p function new_character(@!f:internal_font_number;@!c:eight_bits):pointer; 2374label exit; 2375var p:pointer; {newly allocated node} 2376begin if font_bc[f]<=c then if font_ec[f]>=c then 2377 if char_exists(char_info(f)(qi(c))) then 2378@y 2379 2380This allows a character node to be used if there is an equivalent 2381in the |char_sub_code| list. 2382 2383@p function new_character(@!f:internal_font_number;@!c:eight_bits):pointer; 2384label exit; 2385var p:pointer; {newly allocated node} 2386@!ec:quarterword; {effective character of |c|} 2387begin ec:=effective_char(false,f,qi(c)); 2388if font_bc[f]<=qo(ec) then if font_ec[f]>=qo(ec) then 2389 if char_exists(orig_char_info(f)(ec)) then {N.B.: not |char_info|} 2390@z 2391 2392@x [32.592] l.11820 - font numbers can be >255 now. 2393@!c,@!f:quarterword; {character and font in current |char_node|} 2394@y 2395 {character and font in current |char_node|} 2396@!c:quarterword; 2397@!f:internal_font_number; 2398@z 2399 2400@x [32.595] l.11860 - texarray 2401@!dvi_buf:array[dvi_index] of eight_bits; {buffer for \.{DVI} output} 2402@!half_buf:dvi_index; {half of |dvi_buf_size|} 2403@!dvi_limit:dvi_index; {end of the current half buffer} 2404@!dvi_ptr:dvi_index; {the next available buffer address} 2405@y 2406@!dvi_buf:^eight_bits; {buffer for \.{DVI} output} 2407@!half_buf:integer; {half of |dvi_buf_size|} 2408@!dvi_limit:integer; {end of the current half buffer} 2409@!dvi_ptr:integer; {the next available buffer address} 2410@z 2411 2412@x [32.597] l.11886 - write_dvi done in C. 2413@p procedure write_dvi(@!a,@!b:dvi_index); 2414var k:dvi_index; 2415begin for k:=a to b do write(dvi_file,dvi_buf[k]); 2416end; 2417@y 2418In C, we use a macro to call |fwrite| or |write| directly, writing all 2419the bytes in one shot. Much better even than writing four 2420bytes at a time. 2421@z 2422 2423@x [32.601] l.11911 - check dvi file size 2424each time, we use the macro |dvi_out|. 2425@y 2426each time, we use the macro |dvi_out|. 2427 2428The length of |dvi_file| should not exceed |@"7FFFFFFF|; we set |cur_s:=-2| 2429to prevent further \.{DVI} output causing infinite recursion. 2430@z 2431 2432@x [32.601] l.11918 - dvi_swap: check dvi file size 2433begin if dvi_limit=dvi_buf_size then 2434@y 2435begin if dvi_ptr>(@"7FFFFFFF-dvi_offset) then 2436 begin cur_s:=-2; 2437 fatal_error("dvi length exceeds ""7FFFFFFF"); 2438@.dvi length exceeds...@> 2439 end; 2440if dvi_limit=dvi_buf_size then 2441@z 2442 2443@x [32.602] l.11932 - empty the last bytes: check dvi file size 2444if dvi_ptr>0 then write_dvi(0,dvi_ptr-1) 2445@y 2446if dvi_ptr>(@"7FFFFFFF-dvi_offset) then 2447 begin cur_s:=-2; 2448 fatal_error("dvi length exceeds ""7FFFFFFF"); 2449@.dvi length exceeds...@> 2450 end; 2451if dvi_ptr>0 then write_dvi(0,dvi_ptr-1) 2452@z 2453 2454@x [32.602] l.11944 - Allow for outputting more than 256 fonts. 2455begin dvi_out(fnt_def1); 2456dvi_out(f-font_base-1);@/ 2457@y 2458begin if f<=256+font_base then 2459 begin dvi_out(fnt_def1); 2460 dvi_out(f-font_base-1); 2461 end 2462else begin dvi_out(fnt_def1+1); 2463 dvi_out((f-font_base-1) div @'400); 2464 dvi_out((f-font_base-1) mod @'400); 2465 end; 2466@z 2467 2468@x [32.617] l.12280 - Use output_comment if the user set it. Assume it's short enough. 2469 old_setting:=selector; selector:=new_string; 2470@y 2471if output_comment then 2472 begin l:=strlen(output_comment); dvi_out(l); 2473 for s:=0 to l-1 do dvi_out(output_comment[s]); 2474 end 2475else begin {the default code is unchanged} 2476 old_setting:=selector; selector:=new_string; 2477@z 2478 2479@x [32.617] l.12288 - Use output_comment if the user set it. 2480 end 2481@y 2482end; 2483 end 2484@z 2485 2486@x [32.619] l.12294 - MLTeX: substitute character in |hlist_out| 2487procedure hlist_out; {output an |hlist_node| box} 2488label reswitch, move_past, fin_rule, next_p; 2489@y 2490procedure hlist_out; {output an |hlist_node| box} 2491label reswitch, move_past, fin_rule, next_p, continue, found; 2492@z 2493 2494@x [32.620] l.12326 - MLTeX: replace virtual character in |hlist_out| 2495reaching a non-|char_node|. The program uses the fact that |set_char_0=0|. 2496@^inner loop@> 2497@y 2498reaching a non-|char_node|. The program uses the fact that |set_char_0=0|. 2499 2500In ML\TeX{} this part looks for the existence of a substitution 2501definition for a character |c|, if |c| does not exist in the font, 2502and create appropriate \.{DVI} commands. Former versions of ML\TeX{} 2503have spliced appropriate character, kern, and box nodes into the 2504horizontal list. 2505% 2506% 91/05/08 \charsubdefmax bug detected by Bernd Raichle 2507Because the user can change character substitions or 2508\.{\\charsubdefmax} on the fly, we have to test a again 2509for valid substitutions. 2510% 2511% 93/10/29 \leaders bug detected by Eberhard Mattes 2512(Additional it is necessary to be careful---if leaders are used 2513the current hlist is normally traversed more than once!) 2514@^inner loop@> 2515@z 2516 2517@x [32.620] l.12334 - MLTeX: substitute character during |shipout| 2518 if c>=qi(128) then dvi_out(set1); 2519 dvi_out(qo(c));@/ 2520 cur_h:=cur_h+char_width(f)(char_info(f)(c)); 2521@y 2522 if font_ec[f]>=qo(c) then if font_bc[f]<=qo(c) then 2523 if char_exists(orig_char_info(f)(c)) then {N.B.: not |char_info|} 2524 begin if c>=qi(128) then dvi_out(set1); 2525 dvi_out(qo(c));@/ 2526 cur_h:=cur_h+char_width(f)(orig_char_info(f)(c)); 2527 goto continue; 2528 end; 2529 if mltex_enabled_p then 2530 @<Output a substitution, |goto continue| if not possible@>; 2531continue: 2532@z 2533 2534@x [32.622] l.12349 - more >256 font output stuff. 2535else begin dvi_out(fnt1); dvi_out(f-font_base-1); 2536 end; 2537@y 2538else if f<=256+font_base then 2539 begin dvi_out(fnt1); dvi_out(f-font_base-1); 2540 end 2541else begin dvi_out(fnt1+1); 2542 dvi_out((f-font_base-1) div @'400); 2543 dvi_out((f-font_base-1) mod @'400); 2544 end; 2545@z 2546 2547% We output each portion of the page as we get to it, if we are using 2548% IPC, so that the previewer (TeXView) can display it immediately. [SPM] 2549@x [32.640] l.12723 - IPC 2550done: 2551@y 2552ifdef ('IPC') 2553if ipc_on>0 then 2554 begin if dvi_limit=half_buf then 2555 begin write_dvi(half_buf, dvi_buf_size-1); 2556 flush_dvi; 2557 dvi_gone:=dvi_gone+half_buf; 2558 end; 2559 if dvi_ptr>(@"7FFFFFFF-dvi_offset) then 2560 begin cur_s:=-2; 2561 fatal_error("dvi length exceeds ""7FFFFFFF"); 2562@.dvi length exceeds...@> 2563 end; 2564 if dvi_ptr>0 then 2565 begin write_dvi(0, dvi_ptr-1); 2566 flush_dvi; 2567 dvi_offset:=dvi_offset+dvi_ptr; dvi_gone:=dvi_gone+dvi_ptr; 2568 end; 2569 dvi_ptr:=0; dvi_limit:=dvi_buf_size; 2570 ipc_page(dvi_gone); 2571 end; 2572endif ('IPC'); 2573done: 2574@z 2575 2576@x [32.645] l.12766 - check dvi file size 2577else begin dvi_out(post); {beginning of the postamble} 2578@y 2579else if cur_s<>-2 then 2580 begin dvi_out(post); {beginning of the postamble} 2581@z 2582 2583@x [32.645] l.12775 - Use dvi_offset instead of dvi_buf_size with IPC stuff. 2584 k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's} 2585@y 2586ifdef ('IPC') 2587 k:=7-((3+dvi_offset+dvi_ptr) mod 4); {the number of 223's} 2588endif ('IPC') 2589ifndef ('IPC') 2590 k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's} 2591endifn ('IPC') 2592@z 2593 2594@x [32.645] l.12780 - use print_file_name 2595 print_nl("Output written on "); slow_print(output_file_name); 2596@y 2597 print_nl("Output written on "); print_file_name(0, output_file_name, 0); 2598@z 2599 2600@x [32.645] l.12782 - i18n fix 2601 print(" ("); print_int(total_pages); print(" page"); 2602 if total_pages<>1 then print_char("s"); 2603@y 2604 print(" ("); print_int(total_pages); 2605 if total_pages<>1 then print(" pages") 2606 else print(" page"); 2607@z 2608 2609% The MLTeX changes never dealt with the problems of character 2610% substitutions in math mode. With the new additions in v2.2, 2611% non-existing characters between |font_bc[f]| and |font_ec[f]| 2612% can be substituted => we have to avoid this in math mode 2613% (for compatibility reasons and to avoid other problems). 2614% 2615@x [35.708] l.13903 - MLTeX: avoid substitution in |var_delimiter| 2616if (qo(y)>=font_bc[g])and(qo(y)<=font_ec[g]) then 2617 begin continue: q:=char_info(g)(y); 2618@y 2619if (qo(y)>=font_bc[g])and(qo(y)<=font_ec[g]) then 2620 begin continue: q:=orig_char_info(g)(y); 2621@z 2622 2623@x [36.722] l.14207 - MLTeX: avoid substitution in |fetch| 2624 cur_i:=char_info(cur_f)(cur_c) 2625@y 2626 cur_i:=orig_char_info(cur_f)(cur_c) 2627@z 2628 2629@x [36.740] l.14486 - MLTeX: avoid substitution in |make_math_accent| 2630 i:=char_info(f)(y); 2631@y 2632 i:=orig_char_info(f)(y); 2633@z 2634 2635@x [36.749] l.14638 - MLTeX: avoid substitution in |make_op| 2636 begin c:=rem_byte(cur_i); i:=char_info(cur_f)(c); 2637@y 2638 begin c:=rem_byte(cur_i); i:=orig_char_info(cur_f)(c); 2639@z 2640 2641% disabled in original tex-src-special.ch 2642 @x [37.774] l.15291 - source specials 2643if every_cr<>null then begin_token_list(every_cr,every_cr_text); 2644 @y 2645if (insert_src_special_every_cr and head<>tail) then insert_src_special; 2646if every_cr<>null then begin_token_list(every_cr,every_cr_text); 2647 @z 2648 2649% disabled in original tex-source-special.ch 2650 @x [37.799] l.15682 - source specials 2651if every_cr<>null then begin_token_list(every_cr,every_cr_text); 2652 @y 2653if (insert_src_special_every_cr) then insert_src_special; 2654if every_cr<>null then begin_token_list(every_cr,every_cr_text); 2655 @z 2656 2657@x [42.920] l.18056 - bigtrie: allow larger hyphenation tries. 2658Comparatively few different number sequences $n_0\ldots n_k$ actually occur, 2659since most of the |n|'s are generally zero. Therefore the number sequences 2660are encoded in such a way that |trie_op|$(z_k)$ is only one byte long. 2661If |trie_op(@t$z_k$@>)<>min_quarterword|, when $p_1\ldots p_k$ has matched 2662the letters in |hc[(l-k+1)..l@,]| of language |t|, 2663we perform all of the required operations 2664for this pattern by carrying out the following little program: Set 2665|v:=trie_op(@t$z_k$@>)|. Then set |v:=v+op_start[t]|, 2666|hyf[l-hyf_distance[v]]:=@tmax@>(hyf[l-hyf_distance[v]], hyf_num[v])|, 2667and |v:=hyf_next[v]|; repeat, if necessary, until |v=min_quarterword|. 2668@y 2669The theory that comparatively few different number sequences $n_0\ldots n_k$ 2670actually occur, since most of the |n|'s are generally zero, seems to fail 2671at least for the large German hyphenation patterns. 2672Therefore the number sequences cannot any longer be encoded in such a way 2673that |trie_op|$(z_k)$ is only one byte long. 2674We have introduced a new constant |max_trie_op| for the maximum allowable 2675hyphenation operation code value; |max_trie_op| might be different for 2676\TeX\ and \.{INITEX} and must not exceed |max_halfword|. 2677An opcode will occupy a halfword if |max_trie_op| exceeds |max_quarterword| 2678or a quarterword otherwise. 2679@^system dependencies@> 2680If |trie_op(@t$z_k$@>)<>min_trie_op|, when $p_1\ldots p_k$ has matched 2681the letters in |hc[(l-k+1)..l@,]| of language |t|, 2682we perform all of the required operations 2683for this pattern by carrying out the following little program: Set 2684|v:=trie_op(@t$z_k$@>)|. Then set |v:=v+op_start[t]|, 2685|hyf[l-hyf_distance[v]]:=@tmax@>(hyf[l-hyf_distance[v]], hyf_num[v])|, 2686and |v:=hyf_next[v]|; repeat, if necessary, until |v=min_trie_op|. 2687@z 2688 2689@x [42.920] l.18068 - bigtrie: allow larger hyphenation tries. 2690@!trie_pointer=0..trie_size; {an index into |trie|} 2691@y 2692@!trie_pointer=0..ssup_trie_size; {an index into |trie|} 2693@!trie_opcode=0..ssup_trie_opcode; {a trie opcode} 2694@z 2695 2696@x [42.921] l.18070 - bigtrie: allow larger hyphenation tries. 2697@ @d trie_link(#)==trie[#].rh {``downward'' link in a trie} 2698@d trie_char(#)==trie[#].b1 {character matched at this trie location} 2699@d trie_op(#)==trie[#].b0 {program for hyphenation at this trie location} 2700@y 2701@ For more than 255 trie op codes, the three fields |trie_link|, |trie_char|, 2702and |trie_op| will no longer fit into one memory word; thus using web2c 2703we define |trie| as three array instead of an array of records. 2704The variant will be implented by reusing the opcode field later on with 2705another macro. 2706 2707@d trie_link(#)==trie_trl[#] {``downward'' link in a trie} 2708@d trie_char(#)==trie_trc[#] {character matched at this trie location} 2709@d trie_op(#)==trie_tro[#] {program for hyphenation at this trie location} 2710@z 2711 2712@x [42.921] l.18075 - bigtrie: allow larger hyphenation tries. 2713@!trie:array[trie_pointer] of two_halves; {|trie_link|, |trie_char|, |trie_op|} 2714@y 2715{We will dynamically allocate these arrays.} 2716@!trie_trl:^trie_pointer; {|trie_link|} 2717@!trie_tro:^trie_pointer; {|trie_op|} 2718@!trie_trc:^quarterword; {|trie_char|} 2719@z 2720 2721@x [42.921] l.18078 - bigtrie: allow larger hyphenation tries. 2722@!hyf_next:array[1..trie_op_size] of quarterword; {continuation code} 2723@y 2724@!hyf_next:array[1..trie_op_size] of trie_opcode; {continuation code} 2725@z 2726 2727@x [42.923] l.18099 - bigtrie: allow larger hyphenation tries. 2728 begin if trie_op(z)<>min_quarterword then 2729@y 2730 begin if trie_op(z)<>min_trie_op then 2731@z 2732 2733@x [42.924] l.18112 - bigtrie: allow larger hyphenation tries. 2734until v=min_quarterword; 2735@y 2736until v=min_trie_op; 2737@z 2738 2739%%%%%%%% dynamic hyph_size 2740@x 18126 m.925 2741different from $\alpha$, we can conclude that $\alpha$ is not in the table. 2742@y 18126 2743different from $\alpha$, we can conclude that $\alpha$ is not in the table. 2744This is a clever scheme which saves the need for a hash link array. 2745However, it is difficult to increase the size of the hyphen exception 2746arrays. To make this easier, the ordered hash has been replaced by 2747a simple hash, using an additional array |hyph_link|. The value 2748|0| in |hyph_link[k]| means that there are no more entries corresponding 2749to the specific hash chain. When |hyph_link[k]>0|, the next entry in 2750the hash chain is |hyph_link[k]-1|. This value is used because the 2751arrays start at |0|. 2752@z 2753 2754%%%%%%%% dynamic hyph_size 2755@x 18134 m.925 2756@!hyph_pointer=0..hyph_size; {an index into the ordered hash table} 2757@y 18134 2758@!hyph_pointer=0..ssup_hyph_size; {index into hyphen exceptions hash table; 2759 enlarging this requires changing (un)dump code} 2760@z 2761 2762%%%%%%%% dynamic hyph_size 2763@x 18137 m.926 2764@!hyph_word:array[hyph_pointer] of str_number; {exception words} 2765@!hyph_list:array[hyph_pointer] of pointer; {lists of hyphen positions} 2766@!hyph_count:hyph_pointer; {the number of words in the exception dictionary} 2767@y 18139 2768@!hyph_word: ^str_number; {exception words} 2769@!hyph_list: ^pointer; {lists of hyphen positions} 2770@!hyph_link: ^hyph_pointer; {link array for hyphen exceptions hash table} 2771@!hyph_count:integer; {the number of words in the exception dictionary} 2772@!hyph_next:integer; {next free slot in hyphen exceptions hash table} 2773@z 2774 2775%%%%%%%% dynamic hyph_size 2776@x 18145 m.928 2777for z:=0 to hyph_size do 2778 begin hyph_word[z]:=0; hyph_list[z]:=null; 2779 end; 2780hyph_count:=0; 2781@y 18148 2782for z:=0 to hyph_size do 2783 begin hyph_word[z]:=0; hyph_list[z]:=null; hyph_link[z]:=0; 2784 end; 2785hyph_count:=0; 2786hyph_next:=hyph_prime+1; if hyph_next>hyph_size then hyph_next:=hyph_prime; 2787@z 2788 2789%%%%%%%% dynamic hyph_size 2790@x 18163 m.930 2791h:=hc[1]; incr(hn); hc[hn]:=cur_lang; 2792for j:=2 to hn do h:=(h+h+hc[j]) mod hyph_size; 2793loop@+ begin @<If the string |hyph_word[h]| is less than \(hc)|hc[1..hn]|, 2794 |goto not_found|; but if the two strings are equal, 2795 set |hyf| to the hyphen positions and |goto found|@>; 2796 if h>0 then decr(h)@+else h:=hyph_size; 2797 end; 2798not_found: decr(hn) 2799@y 18170 2800h:=hc[1]; incr(hn); hc[hn]:=cur_lang; 2801for j:=2 to hn do h:=(h+h+hc[j]) mod hyph_prime; 2802loop@+ begin @<If the string |hyph_word[h]| is less than \(hc)|hc[1..hn]|, 2803 |goto not_found|; but if the two strings are equal, 2804 set |hyf| to the hyphen positions and |goto found|@>; 2805 h:=hyph_link[h]; if h=0 then goto not_found; 2806 decr(h); 2807 end; 2808not_found: decr(hn) 2809@z 2810 2811@x [42.931] l.18206 - dynamic hyph_size 2812@ @<If the string |hyph_word[h]| is less than \(hc)...@>= 2813k:=hyph_word[h]; if k=0 then goto not_found; 2814if length(k)<hn then goto not_found; 2815@y 2816@ @<If the string |hyph_word[h]| is less than \(hc)...@>= 2817{This is now a simple hash list, not an ordered one, so 2818the module title is no longer descriptive.} 2819k:=hyph_word[h]; if k=0 then goto not_found; 2820@z 2821 2822@x [42.931] l.18211 - dynamic hyph_size 2823 repeat if so(str_pool[u])<hc[j] then goto not_found; 2824 if so(str_pool[u])>hc[j] then goto done; 2825@y 2826 repeat 2827 if so(str_pool[u])<>hc[j] then goto done; 2828@z 2829 2830%%%%%%%% dynamic hyph_size 2831@x 18245 m.934 2832@!s,@!t:str_number; {strings being compared or stored} 2833@y 2834@!s:str_number; {strings being compared or stored} 2835@z 2836 2837%%%%%%%% dynamic hyph_size 2838@x 18274 m.939 2839 begin h:=(h+h+hc[j]) mod hyph_size; 2840@y 18274 2841 begin h:=(h+h+hc[j]) mod hyph_prime; 2842@z 2843 2844%%%%%%%% dynamic hyph_size 2845@x 18281 m.940 2846@ @<Insert the \(p)pair |(s,p)|...@>= 2847if hyph_count=hyph_size then overflow("exception dictionary",hyph_size); 2848@:TeX capacity exceeded exception dictionary}{\quad exception dictionary@> 2849incr(hyph_count); 2850while hyph_word[h]<>0 do 2851 begin @<If the string |hyph_word[h]| is less than \(or)or equal to 2852 |s|, interchange |(hyph_word[h],hyph_list[h])| with |(s,p)|@>; 2853 if h>0 then decr(h)@+else h:=hyph_size; 2854 end; 2855hyph_word[h]:=s; hyph_list[h]:=p 2856@y 18290 2857@ @<Insert the \(p)pair |(s,p)|...@>= 2858 if hyph_next <= hyph_prime then 2859 while (hyph_next>0) and (hyph_word[hyph_next-1]>0) do decr(hyph_next); 2860if (hyph_count=hyph_size)or(hyph_next=0) then 2861 overflow("exception dictionary",hyph_size); 2862@:TeX capacity exceeded exception dictionary}{\quad exception dictionary@> 2863incr(hyph_count); 2864while hyph_word[h]<>0 do 2865 begin @<If the string |hyph_word[h]| is less than \(or)or equal to 2866 |s|, interchange |(hyph_word[h],hyph_list[h])| with |(s,p)|@>; 2867 if hyph_link[h]=0 then 2868 begin 2869 hyph_link[h]:=hyph_next; 2870 if hyph_next >= hyph_size then hyph_next:=hyph_prime; 2871 if hyph_next > hyph_prime then incr(hyph_next); 2872 end; 2873 h:=hyph_link[h]-1; 2874 end; 2875 2876found: hyph_word[h]:=s; hyph_list[h]:=p 2877@z 2878 2879@x [42.941] l.18326 - dynamic hyph_size 2880@ @<If the string |hyph_word[h]| is less than \(or)...@>= 2881k:=hyph_word[h]; 2882if length(k)<length(s) then goto found; 2883if length(k)>length(s) then goto not_found; 2884@y 2885@ @<If the string |hyph_word[h]| is less than \(or)...@>= 2886{This is now a simple hash list, not an ordered one, so 2887the module title is no longer descriptive.} 2888k:=hyph_word[h]; 2889if length(k)<>length(s) then goto not_found; 2890@z 2891 2892@x [42.941] l.18331 - dynamic hyph_size 2893repeat if str_pool[u]<str_pool[v] then goto found; 2894if str_pool[u]>str_pool[v] then goto not_found; 2895@y 2896repeat if str_pool[u]<>str_pool[v] then goto not_found; 2897@z 2898 2899@x [42.941] l.18335 - dynamic hyph_size 2900found:q:=hyph_list[h]; hyph_list[h]:=p; p:=q;@/ 2901t:=hyph_word[h]; hyph_word[h]:=s; s:=t; 2902not_found: 2903@y 2904{repeat hyphenation exception; flushing old data} 2905flush_string; s:=hyph_word[h]; {avoid |slow_make_string|!} 2906decr(hyph_count); 2907{ We could also |flush_list(hyph_list[h]);|, but it interferes 2908 with \.{trip.log}. } 2909goto found; 2910not_found: 2911@z 2912 2913@x [43.943] l.18332 - bigtrie: Larger tries, also in documentation parts. 2914|hyf_next[@t$v^\prime$@>]=min_quarterword|. 2915@y 2916|hyf_next[@t$v^\prime$@>]=min_trie_op|. 2917@z 2918 2919@x [43.943] l.18336 - bigtrie: Larger tries, also in documentation parts. 2920$$\hbox{|@t$v^\prime$@>:=new_trie_op(0,1,min_quarterword)|,\qquad 2921@y 2922$$\hbox{|@t$v^\prime$@>:=new_trie_op(0,1,min_trie_op)|,\qquad 2923@z 2924 2925@x [43.943] l.18346 - web2c can't parse negative lower bounds in arrays. Sorry. 2926@!init@! trie_op_hash:array[-trie_op_size..trie_op_size] of 0..trie_op_size; 2927@y 2928@!init@! trie_op_hash:array[neg_trie_op_size..trie_op_size] of 0..trie_op_size; 2929@z 2930 2931@x [43.943] l.18348 - bigtrie: Larger hyphenation tries. 2932@!trie_used:array[ASCII_code] of quarterword; 2933@y 2934@!trie_used:array[ASCII_code] of trie_opcode; 2935@z 2936 2937@x [43.943] l.18352 - bigtrie: Larger hyphenation tries. 2938@!trie_op_val:array[1..trie_op_size] of quarterword; 2939@y 2940@!trie_op_val:array[1..trie_op_size] of trie_opcode; 2941@z 2942 2943@x [43.943] l.18355 - Dynamic trie arrays 2944tini 2945@y 2946tini@; 2947@!max_op_used:trie_opcode; {largest opcode used for any language} 2948@!small_op:boolean; {flag used while dumping or undumping} 2949@z 2950 2951@x [43.944] l.18358 - bigtrie: Larger tries, also in documentation parts. 2952|new_trie_op| could return |min_quarterword| (thereby simply ignoring 2953@y 2954|new_trie_op| could return |min_trie_op| (thereby simply ignoring 2955@z 2956 2957@x [43.944] l.18365 - bigtrie: Larger hyphenation tries. 2958function new_trie_op(@!d,@!n:small_number;@!v:quarterword):quarterword; 2959label exit; 2960var h:-trie_op_size..trie_op_size; {trial hash location} 2961@!u:quarterword; {trial op code} 2962@y 2963function new_trie_op(@!d,@!n:small_number;@!v:trie_opcode):trie_opcode; 2964label exit; 2965var h:neg_trie_op_size..trie_op_size; {trial hash location} 2966@!u:trie_opcode; {trial op code} 2967@z 2968 2969@x [43.944] l.18370 - Another casting problem, and use |neg_trie_op_size|. 2970begin h:=abs(n+313*d+361*v+1009*cur_lang) mod (trie_op_size+trie_op_size) 2971 - trie_op_size; 2972@y 2973begin h:=abs(n+313*d+361*v+1009*cur_lang) mod (trie_op_size-neg_trie_op_size) 2974 + neg_trie_op_size; 2975@z 2976 2977@x [43.944] l.18377 - bigtrie: And larger tries again. 2978 if u=max_quarterword then 2979 overflow("pattern memory ops per language", 2980 max_quarterword-min_quarterword); 2981 incr(trie_op_ptr); incr(u); trie_used[cur_lang]:=u; 2982@y 2983 if u=max_trie_op then 2984 overflow("pattern memory ops per language", 2985 max_trie_op-min_trie_op); 2986 incr(trie_op_ptr); incr(u); trie_used[cur_lang]:=u; 2987 if u>max_op_used then max_op_used:=u; 2988@z 2989 2990@x [43.945] l.18399 - bigtrie: And larger tries again. 2991op_start[0]:=-min_quarterword; 2992@y 2993op_start[0]:=-min_trie_op; 2994@z 2995 2996@x [43.946] l.18416 - bigtrie: And larger tries again. 2997for k:=0 to 255 do trie_used[k]:=min_quarterword; 2998@y 2999for k:=0 to 255 do trie_used[k]:=min_trie_op; 3000@z 3001 3002@x [43.946] l.18417 - Dynamic trie arrays. 3003trie_op_ptr:=0; 3004@y 3005max_op_used:=min_trie_op; 3006trie_op_ptr:=0; 3007@z 3008 3009@x [43.947] l.18438 - Dynamically allocate arrays, and a casting problem. 3010@!init @!trie_c:packed array[trie_pointer] of packed_ASCII_code; 3011 {characters to match} 3012@t\hskip10pt@>@!trie_o:packed array[trie_pointer] of quarterword; 3013 {operations to perform} 3014@t\hskip10pt@>@!trie_l:packed array[trie_pointer] of trie_pointer; 3015 {left subtrie links} 3016@t\hskip10pt@>@!trie_r:packed array[trie_pointer] of trie_pointer; 3017 {right subtrie links} 3018@t\hskip10pt@>@!trie_ptr:trie_pointer; {the number of nodes in the trie} 3019@t\hskip10pt@>@!trie_hash:packed array[trie_pointer] of trie_pointer; 3020 {used to identify equivalent subtries} 3021tini 3022@y 3023@!init @!trie_c:^packed_ASCII_code; 3024 {characters to match} 3025@t\hskip10pt@>@!trie_o:^trie_opcode; 3026 {operations to perform} 3027@t\hskip10pt@>@!trie_l:^trie_pointer; 3028 {left subtrie links} 3029@t\hskip10pt@>@!trie_r:^trie_pointer; 3030 {right subtrie links} 3031@t\hskip10pt@>@!trie_ptr:trie_pointer; {the number of nodes in the trie} 3032@t\hskip10pt@>@!trie_hash:^trie_pointer; 3033 {used to identify equivalent subtries} 3034tini 3035@z 3036 3037@x [43.950] l.18521 - Dynamically allocate & larger tries. 3038@d trie_back(#)==trie[#].lh {backward links in |trie| holes} 3039@y 3040@d trie_back(#)==trie_tro[#] {use the opcode field now for backward links} 3041@z 3042 3043@x [43.590] l.18524 - Dynamically allocate & larger tries. 3044@!init@!trie_taken:packed array[1..trie_size] of boolean; 3045 {does a family start here?} 3046@t\hskip10pt@>@!trie_min:array[ASCII_code] of trie_pointer; 3047 {the first possible slot for each character} 3048@t\hskip10pt@>@!trie_max:trie_pointer; {largest location used in |trie|} 3049@t\hskip10pt@>@!trie_not_ready:boolean; {is the trie still in linked form?} 3050tini 3051@y 3052@!init@!trie_taken: ^boolean; 3053 {does a family start here?} 3054@t\hskip10pt@>@!trie_min:array[ASCII_code] of trie_pointer; 3055 {the first possible slot for each character} 3056@t\hskip10pt@>@!trie_max:trie_pointer; {largest location used in |trie|} 3057@t\hskip10pt@>@!trie_not_ready:boolean; {is the trie still in linked form?} 3058tini 3059@z 3060 3061@x [43.951] l.18539 - Dynamically allocate. 3062trie_not_ready:=true; trie_root:=0; trie_c[0]:=si(0); trie_ptr:=0; 3063@y 3064trie_not_ready:=true; 3065@z 3066 3067@x [43.958] l.18634 - bigtrie: Larger tries. 3068@<Move the data into |trie|@>= 3069h.rh:=0; h.b0:=min_quarterword; h.b1:=min_quarterword; {|trie_link:=0|, 3070 |trie_op:=min_quarterword|, |trie_char:=qi(0)|} 3071@y 3072@d clear_trie == {clear |trie[r]|} 3073 begin trie_link(r):=0; 3074 trie_op(r):=min_trie_op; 3075 trie_char(r):=min_quarterword; {|trie_char:=qi(0)|} 3076 end 3077 3078@<Move the data into |trie|@>= 3079@z 3080 3081@x [43.958] l.18638 - bigtrie: Larger tries. 3082 begin for r:=0 to 256 do trie[r]:=h; 3083@y 3084 begin for r:=0 to 256 do clear_trie; 3085@z 3086 3087@x [43.958] l.18643 - bigtrie: Larger tries. 3088 repeat s:=trie_link(r); trie[r]:=h; r:=s; 3089@y 3090 repeat s:=trie_link(r); clear_trie; r:=s; 3091@z 3092 3093@x [43.960] l.18677 - bigtrie: Larger tries. 3094@!v:quarterword; {trie op code} 3095@y 3096@!v:trie_opcode; {trie op code} 3097@z 3098 3099@x [43.963] l.18749 - bigtrie: Larger tries. 3100if trie_o[q]<>min_quarterword then 3101@y 3102if trie_o[q]<>min_trie_op then 3103@z 3104 3105@x [43.964] l.18762 - bigtrie: Larger tries. 3106trie_c[p]:=si(c); trie_o[p]:=min_quarterword; 3107@y 3108trie_c[p]:=si(c); trie_o[p]:=min_trie_op; 3109@z 3110 3111@x [43.965] l.18768 - bigtrie: Larger tries. 3112l:=k; v:=min_quarterword; 3113@y 3114l:=k; v:=min_trie_op; 3115@z 3116 3117@x [43.966] l.18786 - bigtrie: Larger tries. 3118@!h:two_halves; {template used to zero out |trie|'s holes} 3119@y 3120@z 3121 3122%% 3123%% We can rewrite the original code after "main_loop_move+2" upto the 3124%% "tail_append(lig_stack)" in module 1036 as 3125%% 3126% 3127% main_loop_move+2: 3128% if font_bc[main_f]<=cur_chr then 3129% if cur_chr<=font_ec[main_f] then 3130% begin main_i:=char_info(main_f)(cur_l); 3131% if char_exists(main_i) goto main_loop_move+3; 3132% end; 3133% char_warning(main_f,cur_chr); free_avail(lig_stack); goto big_switch; 3134% main_loop_move+3: 3135% tail_append(lig_stack) {|main_loop_lookahead| is next} 3136% 3137%% 3138%% We can use the rewritten code above to include additional MLTeX 3139%% specific parts in the future. Additionally it can be used when 3140%% optimizing |main_control| to minimize the call of the function 3141%% |effective_char|. 3142%% 3143% 3144%@x [46.1030] l.19977 - MLTeX: substitution in |main_control| 3145% main_loop_move,main_loop_move+1,main_loop_move+2,main_loop_move_lig, 3146%@y 3147% main_loop_move,main_loop_move+1,main_loop_move+2,main_loop_move+3, 3148% main_loop_move_lig, 3149%@z 3150 3151@x [46.1034] l.20074 - source specials 3152@<Append character |cur_chr|...@>= 3153@y 3154@<Append character |cur_chr|...@>= 3155if ((head=tail) and (mode>0)) then begin 3156 if (insert_src_special_auto) then append_src_special; 3157end; 3158@z 3159 3160@x [46.1036] l.20138 - MLTeX: substitution in |main_control| 3161main_loop_move+2:if(cur_chr<font_bc[main_f])or(cur_chr>font_ec[main_f]) then 3162@y 3163main_loop_move+2: 3164if(qo(effective_char(false,main_f,qi(cur_chr)))>font_ec[main_f])or 3165 (qo(effective_char(false,main_f,qi(cur_chr)))<font_bc[main_f]) then 3166@z 3167 3168@x [46.1036] l.20141 - MLTeX: substitution in |main_control| 3169main_i:=char_info(main_f)(cur_l); 3170@y 3171main_i:=effective_char_info(main_f,cur_l); 3172@z 3173 3174@x [46.1049] l.20407 - i18n fix, see change to [16.211] 3175print("' in "); print_mode(mode); 3176@y 3177print_in_mode(mode); 3178@z 3179 3180% disabled in original tex-src-special.ch 3181 @x [47.1083] l.20966 - source specials 3182 if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text); 3183 @y 3184 if (insert_src_special_every_vbox) then insert_src_special; 3185 if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text); 3186 @z 3187 3188% disabled in original tex-src-special.ch 3189 @x [47.1083] l.20969 - source specials 3190 if every_hbox<>null then begin_token_list(every_hbox,every_hbox_text); 3191 @y 3192 if (insert_src_special_every_hbox) then insert_src_special; 3193 if every_hbox<>null then begin_token_list(every_hbox,every_hbox_text); 3194 @z 3195 3196@x [47.1091] l.21064 - source specials 3197if indented then 3198 begin tail:=new_null_box; link(head):=tail; width(tail):=par_indent;@+ 3199 end; 3200@y 3201if indented then 3202 begin tail:=new_null_box; link(head):=tail; width(tail):=par_indent; 3203 if (insert_src_special_every_par) then insert_src_special;@+ 3204 end; 3205@z 3206 3207% disabled in original tex-src-special.ch, conflicts with etex. 3208 @x [47.1096] l.21121 - source specials 3209 else line_break(widow_penalty); 3210 @y 3211 else begin 3212 if (insert_src_special_every_parend) then insert_src_special; 3213 line_break(widow_penalty); 3214 end; 3215 @z 3216 3217@x [48.1142] l.21697 - source specials 3218if every_math<>null then begin_token_list(every_math,every_math_text); 3219@y 3220if (insert_src_special_every_math) then insert_src_special; 3221if every_math<>null then begin_token_list(every_math,every_math_text); 3222@z 3223 3224% disabled in original tex-src-special.ch 3225 @x [48.1145] l.21705 - source specials 3226if every_display<>null then begin_token_list(every_display,every_display_text); 3227 @y 3228if (insert_src_special_every_display) then append_src_special; 3229if every_display<>null then begin_token_list(every_display,every_display_text); 3230 @z 3231 3232@x [48.1167] l.22042 - source specials 3233 if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text); 3234@y 3235 if (insert_src_special_every_vbox) then insert_src_special; 3236 if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text); 3237@z 3238 3239@x [49.1215] l.22719 - hash_extra 3240if (cur_cs=0)or(cur_cs>frozen_control_sequence) then 3241@y 3242if (cur_cs=0)or(cur_cs>eqtb_top)or 3243 ((cur_cs>frozen_control_sequence)and(cur_cs<=eqtb_size)) then 3244@z 3245 3246@x [49.1222] l.22794 - MLTeX: \charsubdef primitive 3247@d toks_def_code=6 {|shorthand_def| for \.{\\toksdef}} 3248@y 3249@d toks_def_code=6 {|shorthand_def| for \.{\\toksdef}} 3250@d char_sub_def_code=7 {|shorthand_def| for \.{\\charsubdef}} 3251@z 3252 3253@x [49.1222] l.22810 - MLTeX: \charsubdef primitive 3254@!@:toks_def_}{\.{\\toksdef} primitive@> 3255@y 3256@!@:toks_def_}{\.{\\toksdef} primitive@> 3257if mltex_p then 3258 begin 3259 primitive("charsubdef",shorthand_def,char_sub_def_code);@/ 3260@!@:char_sub_def_}{\.{\\charsubdef} primitive@> 3261 end; 3262@z 3263 3264@x [49.1222] l.22820 - MLTeX: \charsubdef primitive 3265 othercases print_esc("toksdef") 3266@y 3267 char_sub_def_code: print_esc("charsubdef"); 3268 othercases print_esc("toksdef") 3269@z 3270 3271@x [49.1222] l.22833 - MLTeX: \charsubdef primitive 3272shorthand_def: begin n:=cur_chr; get_r_token; p:=cur_cs; define(p,relax,256); 3273@y 3274shorthand_def: if cur_chr=char_sub_def_code then 3275 begin scan_char_num; p:=char_sub_code_base+cur_val; scan_optional_equals; 3276 scan_char_num; n:=cur_val; {accent character in substitution} 3277 scan_char_num; 3278 if (tracing_char_sub_def>0) then 3279 begin begin_diagnostic; print_nl("New character substitution: "); 3280 print_ASCII(p-char_sub_code_base); print(" = "); 3281 print_ASCII(n); print_char(" "); 3282 print_ASCII(cur_val); end_diagnostic(false); 3283 end; 3284 n:=n*256+cur_val; 3285 define(p,data,hi(n)); 3286 if (p-char_sub_code_base)<char_sub_def_min then 3287 word_define(int_base+char_sub_def_min_code,p-char_sub_code_base); 3288 if (p-char_sub_code_base)>char_sub_def_max then 3289 word_define(int_base+char_sub_def_max_code,p-char_sub_code_base); 3290 end 3291else begin n:=cur_chr; get_r_token; p:=cur_cs; define(p,relax,256); 3292@z 3293 3294@x [49.1252] l.23230 - INI = VIR, so have to do runtime test. 3295 begin @!init new_patterns; goto done;@;@+tini@/ 3296@y 23215 3297 begin @!Init new_patterns; goto done;@;@+Tini@/ 3298@z 3299 3300% undo Knuth's change because 3301% a) the string is already replaced in |scan_file_name| and therefore 3302% b) the wrong string will get flushed!!! 3303% 3304@x [49.1257] l.23328 unused variable 3305@!flushable_string:str_number; {string not yet referenced} 3306@y 3307@z 3308@x [49.1260] l.23383 new_font: string recycling -- already done 3309flushable_string:=str_ptr-1; 3310@y 3311@z 3312 3313% If you don't want to remove code with the following two changes, 3314% please replace the former change by 3315% 3316% @x 3317% flushable_string:=str_ptr-1; 3318% @y 3319% if cur_name=str_ptr-1 then 3320% flushable_string:=str_ptr-1 3321% else 3322% flushable_string:=str_ptr; {number of a non-existing} 3323% @z 3324% 3325% otherwise the wrong string will get removed by |flush_string|!! 3326% 3327@x [49.1260] l.23386 new_font: string recycling -- already done 3328 begin if cur_name=flushable_string then 3329 begin flush_string; cur_name:=font_name[f]; 3330 end; 3331 if s>0 then 3332@y 3333 begin if s>0 then 3334@z 3335 3336@x [49.1265] if batchmode, mktex... scripts should be silent. 3337interaction:=cur_chr; 3338@y 3339interaction:=cur_chr; 3340if interaction = batch_mode 3341then kpse_make_tex_discard_errors := 1 3342else kpse_make_tex_discard_errors := 0; 3343@z 3344 3345@x [49.1275] l.23441 - Same stuff as for \input, this time for \openin. 3346 if cur_ext="" then cur_ext:=".tex"; 3347 pack_cur_name; 3348 if a_open_in(read_file[n]) then read_open[n]:=just_open; 3349@y 3350 pack_cur_name; 3351 tex_input_type:=0; {Tell |open_input| we are \.{\\openin}.} 3352 if kpse_in_name_ok(stringcast(name_of_file+1)) 3353 and a_open_in(read_file[n], kpse_tex_format) then 3354 read_open[n]:=just_open; 3355@z 3356 3357@x [50.1301] l.23679 - INI = VIR, so runtime test. 3358format_ident:=" (INITEX)"; 3359@y 3360if ini_version then format_ident:=" (INITEX)"; 3361@z 3362 3363% Eliminate now-unused variable `w' in `store_fmt_file'. 3364% Add format_engine. 3365@x [50.1302] l.23690 - store_fmt_file 3366@!w: four_quarters; {four ASCII codes} 3367@y 3368@!format_engine: ^text_char; 3369@z 3370 3371% MLTeX: dump |mltex_p| to fmt file 3372@x [50.1302] l.23694 3373@<Dump constants for consistency check@>; 3374@y 3375@<Dump constants for consistency check@>; 3376@<Dump ML\TeX-specific data@>; 3377@z 3378 3379% Eliminate now-unused variable `w' in `load_fmt_file'. 3380% Add format_engine. 3381% Add dummies for undumping |xord|, |xchr|, and |xprn| into the void. 3382@x [50.1303] l.23722 - load_fmt_file 3383@!w: four_quarters; {four ASCII codes} 3384@y 3385@!format_engine: ^text_char; 3386@!dummy_xord: ASCII_code; 3387@!dummy_xchr: text_char; 3388@!dummy_xprn: ASCII_code; 3389@z 3390 3391% MLTeX: undump |mltex_enabled_p| from fmt file 3392@x [50.1303] l.23694 3393begin @<Undump constants for consistency check@>; 3394@y 3395begin @<Undump constants for consistency check@>; 3396@<Undump ML\TeX-specific data@>; 3397@z 3398 3399@x [50.1305] l.23751 - Do dumping and undumping of fmt files in C. 3400@d dump_wd(#)==begin fmt_file^:=#; put(fmt_file);@+end 3401@d dump_int(#)==begin fmt_file^.int:=#; put(fmt_file);@+end 3402@d dump_hh(#)==begin fmt_file^.hh:=#; put(fmt_file);@+end 3403@d dump_qqqq(#)==begin fmt_file^.qqqq:=#; put(fmt_file);@+end 3404@y 3405@z 3406@x [1306] 3407@d undump_wd(#)==begin get(fmt_file); #:=fmt_file^;@+end 3408@d undump_int(#)==begin get(fmt_file); #:=fmt_file^.int;@+end 3409@d undump_hh(#)==begin get(fmt_file); #:=fmt_file^.hh;@+end 3410@d undump_qqqq(#)==begin get(fmt_file); #:=fmt_file^.qqqq;@+end 3411@y 3412@z 3413@x [still 1306] debug format file 3414@d undump_size_end_end(#)==too_small(#)@+else undump_end_end 3415@y 3416@d format_debug_end(#)== 3417 write_ln (stderr, ' = ', #); 3418 end; 3419@d format_debug(#)== 3420 if debug_format_file then begin 3421 write (stderr, 'fmtdebug:', #); 3422 format_debug_end 3423@d undump_size_end_end(#)== 3424 too_small(#)@+else format_debug (#)(x); undump_end_end 3425@z 3426 3427@x [50,1307] l.23779 - texarray 3428dump_int(@$);@/ 3429@y 3430dump_int(@"57325458); {Web2C \TeX's magic constant: "W2TX"} 3431{Align engine to 4 bytes with one or more trailing NUL} 3432x:=strlen(engine_name); 3433format_engine:=xmalloc_array(text_char,x+4); 3434strcpy(stringcast(format_engine), engine_name); 3435for k:=x to x+3 do format_engine[k]:=0; 3436x:=x+4-(x mod 4); 3437dump_int(x);dump_things(format_engine[0], x); 3438libc_free(format_engine);@/ 3439dump_int(@$);@/ 3440@<Dump |xord|, |xchr|, and |xprn|@>; 3441dump_int(max_halfword);@/ 3442dump_int(hash_high); 3443@z 3444 3445%%%%%%%% dynamic hyph_size 3446@x 23784 m.1307 3447dump_int(hyph_size) 3448@y 23784 3449dump_int(hyph_prime) 3450@z 3451 3452@x [50.1308] l.23793 - texarray 3453x:=fmt_file^.int; 3454if x<>@$ then goto bad_fmt; {check that strings are the same} 3455@y 3456@+Init 3457libc_free(font_info); libc_free(str_pool); libc_free(str_start); 3458libc_free(yhash); libc_free(zeqtb); libc_free(yzmem); 3459@+Tini 3460undump_int(x); 3461format_debug('format magic number')(x); 3462if x<>@"57325458 then goto bad_fmt; {not a format file} 3463undump_int(x); 3464format_debug('engine name size')(x); 3465if (x<0) or (x>256) then goto bad_fmt; {corrupted format file} 3466format_engine:=xmalloc_array(text_char, x); 3467undump_things(format_engine[0], x); 3468format_engine[x-1]:=0; {force string termination, just in case} 3469if strcmp(engine_name, stringcast(format_engine)) then 3470 begin wake_up_terminal; 3471 wterm_ln('---! ', stringcast(name_of_file+1), ' was written by ', format_engine); 3472 libc_free(format_engine); 3473 goto bad_fmt; 3474end; 3475libc_free(format_engine); 3476undump_int(x); 3477format_debug('string pool checksum')(x); 3478if x<>@$ then begin {check that strings are the same} 3479 wake_up_terminal; 3480 wterm_ln('---! ', stringcast(name_of_file+1), ' doesn''t match ', pool_name); 3481 goto bad_fmt; 3482end; 3483@<Undump |xord|, |xchr|, and |xprn|@>; 3484undump_int(x); 3485if x<>max_halfword then goto bad_fmt; {check |max_halfword|} 3486undump_int(hash_high); 3487 if (hash_high<0)or(hash_high>sup_hash_extra) then goto bad_fmt; 3488 if hash_extra<hash_high then hash_extra:=hash_high; 3489 eqtb_top:=eqtb_size+hash_extra; 3490 if hash_extra=0 then hash_top:=undefined_control_sequence else 3491 hash_top:=eqtb_top; 3492 yhash:=xmalloc_array(two_halves,1+hash_top-hash_offset); 3493 hash:=yhash - hash_offset; 3494 next(hash_base):=0; text(hash_base):=0; 3495 for x:=hash_base+1 to hash_top do hash[x]:=hash[hash_base]; 3496 zeqtb:=xmalloc_array (memory_word,eqtb_top+1); 3497 eqtb:=zeqtb; 3498 3499 eq_type(undefined_control_sequence):=undefined_cs; 3500 equiv(undefined_control_sequence):=null; 3501 eq_level(undefined_control_sequence):=level_zero; 3502 for x:=eqtb_size+1 to eqtb_top do 3503 eqtb[x]:=eqtb[undefined_control_sequence]; 3504@z 3505 3506@x [50.1308] l.23795 - texarray 3507undump_int(x); 3508if x<>mem_bot then goto bad_fmt; 3509undump_int(x); 3510if x<>mem_top then goto bad_fmt; 3511@y 3512undump_int(x); format_debug ('mem_bot')(x); 3513if x<>mem_bot then goto bad_fmt; 3514undump_int(mem_top); format_debug ('mem_top')(mem_top); 3515if mem_bot+1100>mem_top then goto bad_fmt; 3516 3517 3518head:=contrib_head; tail:=contrib_head; 3519 page_tail:=page_head; {page initialization} 3520 3521mem_min := mem_bot - extra_mem_bot; 3522mem_max := mem_top + extra_mem_top; 3523 3524yzmem:=xmalloc_array (memory_word, mem_max - mem_min + 1); 3525zmem := yzmem - mem_min; {this pointer arithmetic fails with some compilers} 3526mem := zmem; 3527@z 3528 3529%%%%%%%% dynamic hyph_size 3530@x 23804 m.1308 3531if x<>hyph_size then goto bad_fmt 3532@y 23804 3533if x<>hyph_prime then goto bad_fmt 3534@z 3535 3536% [1309] Make dumping/undumping more efficient by doing whole arrays at 3537% a time, via fread/fwrite in texmfmp.c. 3538@x [50.1309] l.23814 - Make dumping/undumping more efficient. 3539for k:=0 to str_ptr do dump_int(str_start[k]); 3540k:=0; 3541while k+4<pool_ptr do 3542 begin dump_four_ASCII; k:=k+4; 3543 end; 3544k:=pool_ptr-4; dump_four_ASCII; 3545@y 3546dump_things(str_start[0], str_ptr+1); 3547dump_things(str_pool[0], pool_ptr); 3548@z 3549 3550@x [50.1310] l.23829 - Make dumping/undumping more efficient. 3551undump_size(0)(pool_size)('string pool size')(pool_ptr); 3552undump_size(0)(max_strings)('max strings')(str_ptr); 3553for k:=0 to str_ptr do undump(0)(pool_ptr)(str_start[k]); 3554k:=0; 3555while k+4<pool_ptr do 3556 begin undump_four_ASCII; k:=k+4; 3557 end; 3558k:=pool_ptr-4; undump_four_ASCII; 3559@y 3560undump_size(0)(sup_pool_size-pool_free)('string pool size')(pool_ptr); 3561if pool_size<pool_ptr+pool_free then 3562 pool_size:=pool_ptr+pool_free; 3563undump_size(0)(sup_max_strings-strings_free)('sup strings')(str_ptr);@/ 3564if max_strings<str_ptr+strings_free then 3565 max_strings:=str_ptr+strings_free; 3566str_start:=xmalloc_array(pool_pointer, max_strings); 3567undump_checked_things(0, pool_ptr, str_start[0], str_ptr+1);@/ 3568str_pool:=xmalloc_array(packed_ASCII_code, pool_size); 3569undump_things(str_pool[0], pool_ptr); 3570@z 3571 3572@x [50.1311] l.23850 - Make dumping/undumping more efficient. 3573repeat for k:=p to q+1 do dump_wd(mem[k]); 3574@y 3575repeat dump_things(mem[p], q+2-p); 3576@z 3577 3578@x [50.1311] l.23855 - Make dumping/undumping more efficient. 3579for k:=p to lo_mem_max do dump_wd(mem[k]); 3580@y 3581dump_things(mem[p], lo_mem_max+1-p); 3582@z 3583 3584@x [50.1311] l.23858 - Make dumping/undumping more efficient. 3585for k:=hi_mem_min to mem_end do dump_wd(mem[k]); 3586@y 3587dump_things(mem[hi_mem_min], mem_end+1-hi_mem_min); 3588@z 3589 3590@x [50.1312] l.23873 - Make dumping/undumping more efficient. 3591repeat for k:=p to q+1 do undump_wd(mem[k]); 3592@y 3593repeat undump_things(mem[p], q+2-p); 3594@z 3595 3596@x [50.1312] l.23878 - Make dumping/undumping more efficient. 3597for k:=p to lo_mem_max do undump_wd(mem[k]); 3598@y 3599undump_things(mem[p], lo_mem_max+1-p); 3600@z 3601 3602@x [50.1312] l.23888 - Make dumping/undumping more efficient. 3603for k:=hi_mem_min to mem_end do undump_wd(mem[k]); 3604@y 3605undump_things (mem[hi_mem_min], mem_end+1-hi_mem_min); 3606@z 3607 3608@x [50.1314] l.23899 - hash_extra, source specials 3609undump(hash_base)(frozen_control_sequence)(par_loc); 3610par_token:=cs_token_flag+par_loc;@/ 3611undump(hash_base)(frozen_control_sequence)(write_loc);@/ 3612@y 3613undump(hash_base)(hash_top)(par_loc); 3614par_token:=cs_token_flag+par_loc;@/ 3615undump(hash_base)(hash_top)(write_loc);@/ 3616@z 3617 3618@x [50.1315] l.23925 - Make dumping/undumping more efficient - eqtb 3619while k<l do 3620 begin dump_wd(eqtb[k]); incr(k); 3621 end; 3622@y 3623dump_things(eqtb[k], l-k); 3624@z 3625 3626@x [50.1316] l.23944 - Make dumping/undumping more efficient - eqtb 3627while k<l do 3628 begin dump_wd(eqtb[k]); incr(k); 3629 end; 3630@y 3631dump_things(eqtb[k], l-k); 3632@z 3633 3634@x [50.1316] l.23947 - hash_extra 3635k:=j+1; dump_int(k-l); 3636until k>eqtb_size 3637@y 3638k:=j+1; dump_int(k-l); 3639until k>eqtb_size; 3640if hash_high>0 then dump_things(eqtb[eqtb_size+1],hash_high); 3641 {dump |hash_extra| part} 3642@z 3643 3644@x [50.1317] l.23958 - Make dumping/undumping more efficient - eqtb 3645for j:=k to k+x-1 do undump_wd(eqtb[j]); 3646@y 3647undump_things(eqtb[k], x); 3648@z 3649 3650@x [50.1317] l.23960 - hash_extra 3651until k>eqtb_size 3652@y 3653until k>eqtb_size; 3654if hash_high>0 then undump_things(eqtb[eqtb_size+1],hash_high); 3655 {undump |hash_extra| part} 3656@z 3657 3658@x [50.1318] l.23968 - hash_extra 3659dump_int(hash_used); cs_count:=frozen_control_sequence-1-hash_used; 3660@y 23968 3661dump_int(hash_used); cs_count:=frozen_control_sequence-1-hash_used+hash_high; 3662@z 3663 3664@x [50.1318] l.23972 - Make dumping/undumping more efficient, hash_extra 3665for p:=hash_used+1 to undefined_control_sequence-1 do dump_hh(hash[p]); 3666@y 3667dump_things(hash[hash_used+1], undefined_control_sequence-1-hash_used); 3668if hash_high>0 then dump_things(hash[eqtb_size+1], hash_high); 3669@z 3670 3671@x [50.1319] l.23980 - Make dumping/undumping more efficient, hash_extra 3672for p:=hash_used+1 to undefined_control_sequence-1 do undump_hh(hash[p]); 3673@y 3674undump_things (hash[hash_used+1], undefined_control_sequence-1-hash_used); 3675if debug_format_file then begin 3676 print_csnames (hash_base, undefined_control_sequence - 1); 3677end; 3678if hash_high > 0 then begin 3679 undump_things (hash[eqtb_size+1], hash_high); 3680 if debug_format_file then begin 3681 print_csnames (eqtb_size + 1, hash_high - (eqtb_size + 1)); 3682 end; 3683end; 3684@z 3685 3686@x [50.1320] l.23985 - Make dumping/undumping more efficient - tfm 3687for k:=0 to fmem_ptr-1 do dump_wd(font_info[k]); 3688dump_int(font_ptr); 3689for k:=null_font to font_ptr do 3690 @<Dump the array info for internal font number |k|@>; 3691@y 3692dump_things(font_info[0], fmem_ptr); 3693dump_int(font_ptr); 3694@<Dump the array info for internal font number |k|@>; 3695@z 3696 3697@x [50.1320] l.23991 - i18n fix 3698print_int(font_ptr-font_base); print(" preloaded font"); 3699if font_ptr<>font_base+1 then print_char("s") 3700@y 3701print_int(font_ptr-font_base); 3702if font_ptr<>font_base+1 then print(" preloaded fonts") 3703else print(" preloaded font") 3704@z 3705 3706@x [50.1321] l.23994 - texarray 3707undump_size(7)(font_mem_size)('font mem size')(fmem_ptr); 3708for k:=0 to fmem_ptr-1 do undump_wd(font_info[k]); 3709undump_size(font_base)(font_max)('font max')(font_ptr); 3710for k:=null_font to font_ptr do 3711 @<Undump the array info for internal font number |k|@> 3712@y 3713undump_size(7)(sup_font_mem_size)('font mem size')(fmem_ptr); 3714if fmem_ptr>font_mem_size then font_mem_size:=fmem_ptr; 3715font_info:=xmalloc_array(fmemory_word, font_mem_size); 3716undump_things(font_info[0], fmem_ptr);@/ 3717undump_size(font_base)(font_base+max_font_max)('font max')(font_ptr); 3718{This undumps all of the font info, despite the name.} 3719@<Undump the array info for internal font number |k|@>; 3720@z 3721 3722% [50.1322] Dumping font_info. 3723% Knuth's code writes all the information relevant to a single font 3724% in the same section of the fmt file. But it's a lot faster to 3725% write the arrays of information out, one whole array at a time. 3726% So that's the way we handle dumping and undumping font info. 3727@x [50.1322] l.24000 - Make dumping/undumping more efficient - tfm 3728@ @<Dump the array info for internal font number |k|@>= 3729begin dump_qqqq(font_check[k]); 3730dump_int(font_size[k]); 3731dump_int(font_dsize[k]); 3732dump_int(font_params[k]);@/ 3733dump_int(hyphen_char[k]); 3734dump_int(skew_char[k]);@/ 3735dump_int(font_name[k]); 3736dump_int(font_area[k]);@/ 3737dump_int(font_bc[k]); 3738dump_int(font_ec[k]);@/ 3739dump_int(char_base[k]); 3740dump_int(width_base[k]); 3741dump_int(height_base[k]);@/ 3742dump_int(depth_base[k]); 3743dump_int(italic_base[k]); 3744dump_int(lig_kern_base[k]);@/ 3745dump_int(kern_base[k]); 3746dump_int(exten_base[k]); 3747dump_int(param_base[k]);@/ 3748dump_int(font_glue[k]);@/ 3749dump_int(bchar_label[k]); 3750dump_int(font_bchar[k]); 3751dump_int(font_false_bchar[k]);@/ 3752print_nl("\font"); print_esc(font_id_text(k)); print_char("="); 3753print_file_name(font_name[k],font_area[k],""); 3754if font_size[k]<>font_dsize[k] then 3755 begin print(" at "); print_scaled(font_size[k]); print("pt"); 3756 end; 3757end 3758@y 3759@ @<Dump the array info for internal font number |k|@>= 3760begin 3761dump_things(font_check[null_font], font_ptr+1-null_font); 3762dump_things(font_size[null_font], font_ptr+1-null_font); 3763dump_things(font_dsize[null_font], font_ptr+1-null_font); 3764dump_things(font_params[null_font], font_ptr+1-null_font); 3765dump_things(hyphen_char[null_font], font_ptr+1-null_font); 3766dump_things(skew_char[null_font], font_ptr+1-null_font); 3767dump_things(font_name[null_font], font_ptr+1-null_font); 3768dump_things(font_area[null_font], font_ptr+1-null_font); 3769dump_things(font_bc[null_font], font_ptr+1-null_font); 3770dump_things(font_ec[null_font], font_ptr+1-null_font); 3771dump_things(char_base[null_font], font_ptr+1-null_font); 3772dump_things(width_base[null_font], font_ptr+1-null_font); 3773dump_things(height_base[null_font], font_ptr+1-null_font); 3774dump_things(depth_base[null_font], font_ptr+1-null_font); 3775dump_things(italic_base[null_font], font_ptr+1-null_font); 3776dump_things(lig_kern_base[null_font], font_ptr+1-null_font); 3777dump_things(kern_base[null_font], font_ptr+1-null_font); 3778dump_things(exten_base[null_font], font_ptr+1-null_font); 3779dump_things(param_base[null_font], font_ptr+1-null_font); 3780dump_things(font_glue[null_font], font_ptr+1-null_font); 3781dump_things(bchar_label[null_font], font_ptr+1-null_font); 3782dump_things(font_bchar[null_font], font_ptr+1-null_font); 3783dump_things(font_false_bchar[null_font], font_ptr+1-null_font); 3784for k:=null_font to font_ptr do 3785 begin print_nl("\font"); print_esc(font_id_text(k)); print_char("="); 3786 print_file_name(font_name[k],font_area[k],""); 3787 if font_size[k]<>font_dsize[k] then 3788 begin print(" at "); print_scaled(font_size[k]); print("pt"); 3789 end; 3790 end; 3791end 3792@z 3793 3794@x [50.1322] l.24031 - Make dumping/undumping more efficient - tfm 3795@ @<Undump the array info for internal font number |k|@>= 3796begin undump_qqqq(font_check[k]);@/ 3797undump_int(font_size[k]); 3798undump_int(font_dsize[k]); 3799undump(min_halfword)(max_halfword)(font_params[k]);@/ 3800undump_int(hyphen_char[k]); 3801undump_int(skew_char[k]);@/ 3802undump(0)(str_ptr)(font_name[k]); 3803undump(0)(str_ptr)(font_area[k]);@/ 3804undump(0)(255)(font_bc[k]); 3805undump(0)(255)(font_ec[k]);@/ 3806undump_int(char_base[k]); 3807undump_int(width_base[k]); 3808undump_int(height_base[k]);@/ 3809undump_int(depth_base[k]); 3810undump_int(italic_base[k]); 3811undump_int(lig_kern_base[k]);@/ 3812undump_int(kern_base[k]); 3813undump_int(exten_base[k]); 3814undump_int(param_base[k]);@/ 3815undump(min_halfword)(lo_mem_max)(font_glue[k]);@/ 3816undump(0)(fmem_ptr-1)(bchar_label[k]); 3817undump(min_quarterword)(non_char)(font_bchar[k]); 3818undump(min_quarterword)(non_char)(font_false_bchar[k]); 3819end 3820@y 3821@ This module should now be named `Undump all the font arrays'. 3822 3823@<Undump the array info for internal font number |k|@>= 3824begin {Allocate the font arrays} 3825font_check:=xmalloc_array(four_quarters, font_max); 3826font_size:=xmalloc_array(scaled, font_max); 3827font_dsize:=xmalloc_array(scaled, font_max); 3828font_params:=xmalloc_array(font_index, font_max); 3829font_name:=xmalloc_array(str_number, font_max); 3830font_area:=xmalloc_array(str_number, font_max); 3831font_bc:=xmalloc_array(eight_bits, font_max); 3832font_ec:=xmalloc_array(eight_bits, font_max); 3833font_glue:=xmalloc_array(halfword, font_max); 3834hyphen_char:=xmalloc_array(integer, font_max); 3835skew_char:=xmalloc_array(integer, font_max); 3836bchar_label:=xmalloc_array(font_index, font_max); 3837font_bchar:=xmalloc_array(nine_bits, font_max); 3838font_false_bchar:=xmalloc_array(nine_bits, font_max); 3839char_base:=xmalloc_array(integer, font_max); 3840width_base:=xmalloc_array(integer, font_max); 3841height_base:=xmalloc_array(integer, font_max); 3842depth_base:=xmalloc_array(integer, font_max); 3843italic_base:=xmalloc_array(integer, font_max); 3844lig_kern_base:=xmalloc_array(integer, font_max); 3845kern_base:=xmalloc_array(integer, font_max); 3846exten_base:=xmalloc_array(integer, font_max); 3847param_base:=xmalloc_array(integer, font_max); 3848 3849undump_things(font_check[null_font], font_ptr+1-null_font); 3850undump_things(font_size[null_font], font_ptr+1-null_font); 3851undump_things(font_dsize[null_font], font_ptr+1-null_font); 3852undump_checked_things(min_halfword, max_halfword, 3853 font_params[null_font], font_ptr+1-null_font); 3854undump_things(hyphen_char[null_font], font_ptr+1-null_font); 3855undump_things(skew_char[null_font], font_ptr+1-null_font); 3856undump_upper_check_things(str_ptr, font_name[null_font], font_ptr+1-null_font); 3857undump_upper_check_things(str_ptr, font_area[null_font], font_ptr+1-null_font); 3858{There's no point in checking these values against the range $[0,255]$, 3859 since the data type is |unsigned char|, and all values of that type are 3860 in that range by definition.} 3861undump_things(font_bc[null_font], font_ptr+1-null_font); 3862undump_things(font_ec[null_font], font_ptr+1-null_font); 3863undump_things(char_base[null_font], font_ptr+1-null_font); 3864undump_things(width_base[null_font], font_ptr+1-null_font); 3865undump_things(height_base[null_font], font_ptr+1-null_font); 3866undump_things(depth_base[null_font], font_ptr+1-null_font); 3867undump_things(italic_base[null_font], font_ptr+1-null_font); 3868undump_things(lig_kern_base[null_font], font_ptr+1-null_font); 3869undump_things(kern_base[null_font], font_ptr+1-null_font); 3870undump_things(exten_base[null_font], font_ptr+1-null_font); 3871undump_things(param_base[null_font], font_ptr+1-null_font); 3872undump_checked_things(min_halfword, lo_mem_max, 3873 font_glue[null_font], font_ptr+1-null_font); 3874undump_checked_things(0, fmem_ptr-1, 3875 bchar_label[null_font], font_ptr+1-null_font); 3876undump_checked_things(min_quarterword, non_char, 3877 font_bchar[null_font], font_ptr+1-null_font); 3878undump_checked_things(min_quarterword, non_char, 3879 font_false_bchar[null_font], font_ptr+1-null_font); 3880end 3881@z 3882 3883%%%%%%%% dynamic hyph_size 3884@x 24058 m.1324 3885dump_int(hyph_count); 3886for k:=0 to hyph_size do if hyph_word[k]<>0 then 3887 begin dump_int(k); dump_int(hyph_word[k]); dump_int(hyph_list[k]); 3888 end; 3889@y 24061 3890dump_int(hyph_count); 3891if hyph_next <= hyph_prime then hyph_next:=hyph_size; 3892dump_int(hyph_next);{minumum value of |hyphen_size| needed} 3893for k:=0 to hyph_size do if hyph_word[k]<>0 then 3894 begin dump_int(k+65536*hyph_link[k]); 3895 {assumes number of hyphen exceptions does not exceed 65535} 3896 dump_int(hyph_word[k]); dump_int(hyph_list[k]); 3897 end; 3898@z 3899 3900@x [50.1324] l.24063 - i18n fix 3901print_ln; print_int(hyph_count); print(" hyphenation exception"); 3902if hyph_count<>1 then print_char("s"); 3903@y 3904print_ln; print_int(hyph_count); 3905if hyph_count<>1 then print(" hyphenation exceptions") 3906else print(" hyphenation exception"); 3907@z 3908 3909@x [50.1324] l.24066 - Make dumping/undumping more efficient - trie 3910for k:=0 to trie_max do dump_hh(trie[k]); 3911@y 3912dump_things(trie_trl[0], trie_max+1); 3913dump_things(trie_tro[0], trie_max+1); 3914dump_things(trie_trc[0], trie_max+1); 3915@z 3916 3917@x [50.1324] l.24068 - Make dumping/undumping more efficient - trie 3918for k:=1 to trie_op_ptr do 3919 begin dump_int(hyf_distance[k]); 3920 dump_int(hyf_num[k]); 3921 dump_int(hyf_next[k]); 3922 end; 3923@y 3924dump_things(hyf_distance[1], trie_op_ptr); 3925dump_things(hyf_num[1], trie_op_ptr); 3926dump_things(hyf_next[1], trie_op_ptr); 3927@z 3928 3929@x [50.1324] l.24076 - i18n fix 3930print(" has "); print_int(trie_op_ptr); print(" op"); 3931if trie_op_ptr<>1 then print_char("s"); 3932@y 3933print(" has "); print_int(trie_op_ptr); 3934if trie_op_ptr<>1 then print(" ops") 3935else print(" op"); 3936@z 3937 3938%%%%%%%% dynamic hyph_size 3939@x 24087 m.1325 3940undump(0)(hyph_size)(hyph_count); 3941for k:=1 to hyph_count do 3942 begin undump(0)(hyph_size)(j); 3943 undump(0)(str_ptr)(hyph_word[j]); 3944 undump(min_halfword)(max_halfword)(hyph_list[j]); 3945 end; 3946@y 24092 3947undump_size(0)(hyph_size)('hyph_size')(hyph_count); 3948undump_size(hyph_prime)(hyph_size)('hyph_size')(hyph_next); 3949j:=0; 3950for k:=1 to hyph_count do 3951 begin undump_int(j); if j<0 then goto bad_fmt; 3952 if j>65535 then 3953 begin hyph_next:= j div 65536; j:=j - hyph_next * 65536; end 3954 else hyph_next:=0; 3955 if (j>=hyph_size)or(hyph_next>hyph_size) then goto bad_fmt; 3956 hyph_link[j]:=hyph_next; 3957 undump(0)(str_ptr)(hyph_word[j]); 3958 undump(min_halfword)(max_halfword)(hyph_list[j]); 3959 end; 3960 {|j| is now the largest occupied location in |hyph_word|} 3961 incr(j); 3962 if j<hyph_prime then j:=hyph_prime; 3963 hyph_next:=j; 3964 if hyph_next >= hyph_size then hyph_next:=hyph_prime else 3965 if hyph_next >= hyph_prime then incr(hyph_next); 3966@z 3967 3968@x [50.1325] l.24094 - Make dumping/undumping more efficient - trie 3969for k:=0 to j do undump_hh(trie[k]); 3970@y 3971{These first three haven't been allocated yet unless we're \.{INITEX}; 3972 we do that precisely so we don't allocate more space than necessary.} 3973if not trie_trl then trie_trl:=xmalloc_array(trie_pointer,j+1); 3974undump_things(trie_trl[0], j+1); 3975if not trie_tro then trie_tro:=xmalloc_array(trie_pointer,j+1); 3976undump_things(trie_tro[0], j+1); 3977if not trie_trc then trie_trc:=xmalloc_array(quarterword, j+1); 3978undump_things(trie_trc[0], j+1); 3979@z 3980 3981@x [50.1325] l.24096 - Make dumping/undumping more efficient - trie 3982for k:=1 to j do 3983 begin undump(0)(63)(hyf_distance[k]); {a |small_number|} 3984 undump(0)(63)(hyf_num[k]); 3985 undump(min_quarterword)(max_quarterword)(hyf_next[k]); 3986 end; 3987@y 3988{I'm not sure we have such a strict limitation (64) on these values, so 3989 let's leave them unchecked.} 3990undump_things(hyf_distance[1], j); 3991undump_things(hyf_num[1], j); 3992undump_upper_check_things(max_trie_op, hyf_next[1], j); 3993@z 3994 3995@x [50.1327] l.24117 - Allow command line to override dumped value. 3996undump(batch_mode)(error_stop_mode)(interaction); 3997@y 3998undump(batch_mode)(error_stop_mode)(interaction); 3999if interaction_option<>unspecified_mode then interaction:=interaction_option; 4000@z 4001 4002@x [50.1327] l.24172 - Test for end-of-file already done by undump. 4003if (x<>69069)or eof(fmt_file) then goto bad_fmt 4004@y 4005if x<>69069 then goto bad_fmt 4006@z 4007 4008@x [51.1332] l.24203 - make the main program a procedure, for eqtb hack. 4009@p begin @!{|start_here|} 4010@y 4011@d const_chk(#)==begin if # < inf@&# then # := inf@&# else 4012 if # > sup@&# then # := sup@&# end 4013 4014{|setup_bound_var| stuff duplicated in \.{mf.ch}.} 4015@d setup_bound_var(#)==bound_default:=#; setup_bound_var_end 4016@d setup_bound_var_end(#)==bound_name:=#; setup_bound_var_end_end 4017@d setup_bound_var_end_end(#)== 4018 setup_bound_variable(addressof(#), bound_name, bound_default) 4019 4020@p procedure main_body; 4021begin @!{|start_here|} 4022 4023{Bounds that may be set from the configuration file. We want the user to 4024 be able to specify the names with underscores, but \.{TANGLE} removes 4025 underscores, so we're stuck giving the names twice, once as a string, 4026 once as the identifier. How ugly.} 4027 setup_bound_var (0)('mem_bot')(mem_bot); 4028 setup_bound_var (250000)('main_memory')(main_memory); 4029 {|memory_word|s for |mem| in \.{INITEX}} 4030 setup_bound_var (0)('extra_mem_top')(extra_mem_top); 4031 {increase high mem in \.{VIRTEX}} 4032 setup_bound_var (0)('extra_mem_bot')(extra_mem_bot); 4033 {increase low mem in \.{VIRTEX}} 4034 setup_bound_var (200000)('pool_size')(pool_size); 4035 setup_bound_var (75000)('string_vacancies')(string_vacancies); 4036 setup_bound_var (5000)('pool_free')(pool_free); {min pool avail after fmt} 4037 setup_bound_var (15000)('max_strings')(max_strings); 4038 setup_bound_var (100)('strings_free')(strings_free); 4039 setup_bound_var (100000)('font_mem_size')(font_mem_size); 4040 setup_bound_var (500)('font_max')(font_max); 4041 setup_bound_var (20000)('trie_size')(trie_size); 4042 {if |ssup_trie_size| increases, recompile} 4043 setup_bound_var (659)('hyph_size')(hyph_size); 4044 setup_bound_var (3000)('buf_size')(buf_size); 4045 setup_bound_var (50)('nest_size')(nest_size); 4046 setup_bound_var (15)('max_in_open')(max_in_open); 4047 setup_bound_var (60)('param_size')(param_size); 4048 setup_bound_var (4000)('save_size')(save_size); 4049 setup_bound_var (300)('stack_size')(stack_size); 4050 setup_bound_var (16384)('dvi_buf_size')(dvi_buf_size); 4051 setup_bound_var (79)('error_line')(error_line); 4052 setup_bound_var (50)('half_error_line')(half_error_line); 4053 setup_bound_var (79)('max_print_line')(max_print_line); 4054 setup_bound_var (0)('hash_extra')(hash_extra); 4055 setup_bound_var (10000)('expand_depth')(expand_depth); 4056 4057 const_chk (mem_bot); 4058 const_chk (main_memory); 4059@+Init 4060 extra_mem_top := 0; 4061 extra_mem_bot := 0; 4062@+Tini 4063 if extra_mem_bot>sup_main_memory then extra_mem_bot:=sup_main_memory; 4064 if extra_mem_top>sup_main_memory then extra_mem_top:=sup_main_memory; 4065 {|mem_top| is an index, |main_memory| a size} 4066 mem_top := mem_bot + main_memory -1; 4067 mem_min := mem_bot; 4068 mem_max := mem_top; 4069 4070 {Check other constants against their sup and inf.} 4071 const_chk (trie_size); 4072 const_chk (hyph_size); 4073 const_chk (buf_size); 4074 const_chk (nest_size); 4075 const_chk (max_in_open); 4076 const_chk (param_size); 4077 const_chk (save_size); 4078 const_chk (stack_size); 4079 const_chk (dvi_buf_size); 4080 const_chk (pool_size); 4081 const_chk (string_vacancies); 4082 const_chk (pool_free); 4083 const_chk (max_strings); 4084 const_chk (strings_free); 4085 const_chk (font_mem_size); 4086 const_chk (font_max); 4087 const_chk (hash_extra); 4088 if error_line > ssup_error_line then error_line := ssup_error_line; 4089 4090 {array memory allocation} 4091 buffer:=xmalloc_array (ASCII_code, buf_size); 4092 nest:=xmalloc_array (list_state_record, nest_size); 4093 save_stack:=xmalloc_array (memory_word, save_size); 4094 input_stack:=xmalloc_array (in_state_record, stack_size); 4095 input_file:=xmalloc_array (alpha_file, max_in_open); 4096 line_stack:=xmalloc_array (integer, max_in_open); 4097 source_filename_stack:=xmalloc_array (str_number, max_in_open); 4098 full_source_filename_stack:=xmalloc_array (str_number, max_in_open); 4099 param_stack:=xmalloc_array (halfword, param_size); 4100 dvi_buf:=xmalloc_array (eight_bits, dvi_buf_size); 4101 hyph_word :=xmalloc_array (str_number, hyph_size); 4102 hyph_list :=xmalloc_array (halfword, hyph_size); 4103 hyph_link :=xmalloc_array (hyph_pointer, hyph_size); 4104@+Init 4105 yzmem:=xmalloc_array (memory_word, mem_top - mem_bot + 1); 4106 zmem := yzmem - mem_bot; {Some compilers require |mem_bot=0|} 4107 eqtb_top := eqtb_size+hash_extra; 4108 if hash_extra=0 then hash_top:=undefined_control_sequence else 4109 hash_top:=eqtb_top; 4110 yhash:=xmalloc_array (two_halves,1+hash_top-hash_offset); 4111 hash:=yhash - hash_offset; {Some compilers require |hash_offset=0|} 4112 next(hash_base):=0; text(hash_base):=0; 4113 for hash_used:=hash_base+1 to hash_top do hash[hash_used]:=hash[hash_base]; 4114 zeqtb:=xmalloc_array (memory_word, eqtb_top); 4115 eqtb:=zeqtb; 4116 4117 str_start:=xmalloc_array (pool_pointer, max_strings); 4118 str_pool:=xmalloc_array (packed_ASCII_code, pool_size); 4119 font_info:=xmalloc_array (fmemory_word, font_mem_size); 4120@+Tini 4121@z 4122 4123@x [51.1332] l.24215 - INI = VIR, so pool init needs runtime test 4124@!init if not get_strings_started then goto final_end; 4125init_prim; {call |primitive| for each primitive} 4126init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time; 4127tini@/ 4128@y 4129@!Init if not get_strings_started then goto final_end; 4130init_prim; {call |primitive| for each primitive} 4131init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time; 4132Tini@/ 4133@z 4134 4135@x [51.1332] l.24225 - main 4136end_of_TEX: close_files_and_terminate; 4137final_end: ready_already:=0; 4138end. 4139@y 4140close_files_and_terminate; 4141final_end: do_final_end; 4142end {|main_body|}; 4143@z 4144 4145@x [51.1333] l.24254 - Print new line before termination; switch to editor if necessary. 4146 slow_print(log_name); print_char("."); 4147 end; 4148 end; 4149@y 4150 print_file_name(0, log_name, 0); print_char("."); 4151 end; 4152 end; 4153print_ln; 4154if (edit_name_start<>0) and (interaction>batch_mode) then 4155 call_edit(str_pool,edit_name_start,edit_name_length,edit_line); 4156@z 4157 4158@x [51.1334] l.24275 - hash_extra 4159 wlog_ln(' ',cs_count:1,' multiletter control sequences out of ', 4160 hash_size:1);@/ 4161@y 24276 4162 wlog_ln(' ',cs_count:1,' multiletter control sequences out of ', 4163 hash_size:1, '+', hash_extra:1);@/ 4164@z 4165 4166@x [51.1335] l.24335 - Only do dump if ini. 4167 begin @!init for c:=top_mark_code to split_bot_mark_code do 4168@y 4169 begin @!Init for c:=top_mark_code to split_bot_mark_code do 4170@z 4171 4172@x [51.1335] l.24337 - Only do dump if ini. 4173 store_fmt_file; return;@+tini@/ 4174@y 4175 store_fmt_file; return;@+Tini@/ 4176@z 4177 4178@x [51.1337] l.24361 - Handle %&format in all cases. 4179if (format_ident=0)or(buffer[loc]="&") then 4180@y 4181if (format_ident=0)or(buffer[loc]="&")or dump_line then 4182@z 4183 4184@x [51.1337] l.24366 - Dynamic arrays size. 4185 w_close(fmt_file); 4186@y 4187 w_close(fmt_file); 4188 eqtb:=zeqtb; 4189@z 4190 4191%% [51] m.1337 l.24371 - MLTeX: add. MLTeX banner after loading fmt file 4192%% (MLTeX change: only "if mltex_enabled_p then ....;") 4193@x [51.1337] l.24371 - Allocate hyphenation tries, do char translation, MLTeX 4194fix_date_and_time;@/ 4195@y 4196if mltex_enabled_p then 4197 begin wterm_ln('MLTeX v2.2 enabled'); 4198 end; 4199fix_date_and_time;@/ 4200 4201@!init 4202if trie_not_ready then begin {initex without format loaded} 4203 trie_trl:=xmalloc_array (trie_pointer, trie_size); 4204 trie_tro:=xmalloc_array (trie_pointer, trie_size); 4205 trie_trc:=xmalloc_array (quarterword, trie_size); 4206 4207 trie_c:=xmalloc_array (packed_ASCII_code, trie_size); 4208 trie_o:=xmalloc_array (trie_opcode, trie_size); 4209 trie_l:=xmalloc_array (trie_pointer, trie_size); 4210 trie_r:=xmalloc_array (trie_pointer, trie_size); 4211 trie_hash:=xmalloc_array (trie_pointer, trie_size); 4212 trie_taken:=xmalloc_array (boolean, trie_size); 4213 4214 trie_root:=0; trie_c[0]:=si(0); trie_ptr:=0; 4215 4216 {Allocate and initialize font arrays} 4217 font_check:=xmalloc_array(four_quarters, font_max); 4218 font_size:=xmalloc_array(scaled, font_max); 4219 font_dsize:=xmalloc_array(scaled, font_max); 4220 font_params:=xmalloc_array(font_index, font_max); 4221 font_name:=xmalloc_array(str_number, font_max); 4222 font_area:=xmalloc_array(str_number, font_max); 4223 font_bc:=xmalloc_array(eight_bits, font_max); 4224 font_ec:=xmalloc_array(eight_bits, font_max); 4225 font_glue:=xmalloc_array(halfword, font_max); 4226 hyphen_char:=xmalloc_array(integer, font_max); 4227 skew_char:=xmalloc_array(integer, font_max); 4228 bchar_label:=xmalloc_array(font_index, font_max); 4229 font_bchar:=xmalloc_array(nine_bits, font_max); 4230 font_false_bchar:=xmalloc_array(nine_bits, font_max); 4231 char_base:=xmalloc_array(integer, font_max); 4232 width_base:=xmalloc_array(integer, font_max); 4233 height_base:=xmalloc_array(integer, font_max); 4234 depth_base:=xmalloc_array(integer, font_max); 4235 italic_base:=xmalloc_array(integer, font_max); 4236 lig_kern_base:=xmalloc_array(integer, font_max); 4237 kern_base:=xmalloc_array(integer, font_max); 4238 exten_base:=xmalloc_array(integer, font_max); 4239 param_base:=xmalloc_array(integer, font_max); 4240 4241 font_ptr:=null_font; fmem_ptr:=7; 4242 font_name[null_font]:="nullfont"; font_area[null_font]:=""; 4243 hyphen_char[null_font]:="-"; skew_char[null_font]:=-1; 4244 bchar_label[null_font]:=non_address; 4245 font_bchar[null_font]:=non_char; font_false_bchar[null_font]:=non_char; 4246 font_bc[null_font]:=1; font_ec[null_font]:=0; 4247 font_size[null_font]:=0; font_dsize[null_font]:=0; 4248 char_base[null_font]:=0; width_base[null_font]:=0; 4249 height_base[null_font]:=0; depth_base[null_font]:=0; 4250 italic_base[null_font]:=0; lig_kern_base[null_font]:=0; 4251 kern_base[null_font]:=0; exten_base[null_font]:=0; 4252 font_glue[null_font]:=null; font_params[null_font]:=7; 4253 param_base[null_font]:=-1; 4254 for font_k:=0 to 6 do font_info[font_k].sc:=0; 4255 end; 4256 tini@/ 4257 4258 font_used:=xmalloc_array (boolean, font_max); 4259 for font_k:=font_base to font_max do font_used[font_k]:=false; 4260@z 4261 4262% [52.1338] Core-dump in debugging mode on 0 input. Under Unix, it's 4263% not possible to portably switch into the debugger while a program is 4264% running. The best approximation is to do a core dump, then run the 4265% debugger on it later. 4266@x [52.1338] l.24411 - Core-dump in debugging mode on 0 input. 4267 begin goto breakpoint;@\ {go to every label at least once} 4268 breakpoint: m:=0; @{'BREAKPOINT'@}@\ 4269 end 4270@y 4271 dump_core {do something to cause a core dump} 4272@z 4273 4274@x [52.1339] l.24429 - debug - print tfm info 42755: print_word(font_info[n]); 4276@y 24397 42775: begin print_scaled(font_info[n].sc); print_char(" ");@/ 4278 print_int(font_info[n].qqqq.b0); print_char(":");@/ 4279 print_int(font_info[n].qqqq.b1); print_char(":");@/ 4280 print_int(font_info[n].qqqq.b2); print_char(":");@/ 4281 print_int(font_info[n].qqqq.b3); 4282 end; 4283@z 4284 4285@x [53.1344] l.24544 - source specials 4286primitive("special",extension,special_node);@/ 4287@y 4288primitive("special",extension,special_node);@/ 4289text(frozen_special):="special"; eqtb[frozen_special]:=eqtb[cur_val];@/ 4290@z 4291 4292@x [53.1348] (do_extension) Remove unused variables 4293var i,@!j,@!k:integer; {all-purpose integers} 4294@!p,@!q,@!r:pointer; {all-purpose pointers} 4295@y 4296var k:integer; {all-purpose integers} 4297@!p:pointer; {all-purpose pointers} 4298@z 4299 4300% [53.1350] (new_write_whatsit) Allow 18 as a \write stream. We never 4301% refer to an actual file, though, so we don't need to change the 4302% write_file or write_open arrays. We provide for disabling this at 4303% runtime, for paranoids. 4304@x [53.1350] l.24609 - system: Allow 18 as a \write stream. 4305 else if cur_val>15 then cur_val:=16; 4306@y 4307 else if (cur_val>15) and (cur_val <> 18) then cur_val:=16; 4308@z 4309 4310@x [53.1370] l.24770 - \write18{foo} 4311begin @<Expand macros in the token list 4312@y 4313@!d:integer; {number of characters in incomplete current string} 4314@!clobbered:boolean; {system string is ok?} 4315@!runsystem_ret:integer; {return value from |runsystem|} 4316begin @<Expand macros in the token list 4317@z 4318 4319@x [53.1370] l.24773 - system: (write_out) \write18{foo} => system(foo). 4320if write_open[j] then selector:=j 4321@y 4322if j=18 then selector := new_string 4323else if write_open[j] then selector:=j 4324@z 4325 4326% Then call system(3) on that string. 4327@x [53.1370] l.24779 - system: (write_out) \write18{foo} => system(foo). 4328flush_list(def_ref); selector:=old_setting; 4329@y 4330flush_list(def_ref); 4331if j=18 then 4332 begin if (tracing_online<=0) then 4333 selector:=log_only {Show what we're doing in the log file.} 4334 else selector:=term_and_log; {Show what we're doing.} 4335 {If the log file isn't open yet, we can only send output to the terminal. 4336 Calling |open_log_file| from here seems to result in bad data in the log.} 4337 if not log_opened then selector:=term_only; 4338 print_nl("runsystem("); 4339 for d:=0 to cur_length-1 do 4340 begin {|print| gives up if passed |str_ptr|, so do it by hand.} 4341 print(so(str_pool[str_start[str_ptr]+d])); {N.B.: not |print_char|} 4342 end; 4343 print(")..."); 4344 if shellenabledp then begin 4345 str_room(1); append_char(0); {Append a null byte to the expansion.} 4346 clobbered:=false; 4347 for d:=0 to cur_length-1 do {Convert to external character set.} 4348 begin 4349 str_pool[str_start[str_ptr]+d]:=xchr[str_pool[str_start[str_ptr]+d]]; 4350 if (str_pool[str_start[str_ptr]+d]=null_code) 4351 and (d<cur_length-1) then clobbered:=true; 4352 {minimal checking: NUL not allowed in argument string of |system|()} 4353 end; 4354 if clobbered then print("clobbered") 4355 else begin {We have the command. See if we're allowed to execute it, 4356 and report in the log. We don't check the actual exit status of 4357 the command, or do anything with the output.} 4358 runsystem_ret := runsystem(conststringcast(addressof( 4359 str_pool[str_start[str_ptr]]))); 4360 if runsystem_ret = -1 then print("quotation error in system command") 4361 else if runsystem_ret = 0 then print("disabled (restricted)") 4362 else if runsystem_ret = 1 then print("executed") 4363 else if runsystem_ret = 2 then print("executed safely (allowed)") 4364 end; 4365 end else begin 4366 print("disabled"); {|shellenabledp| false} 4367 end; 4368 print_char("."); print_nl(""); print_ln; 4369 pool_ptr:=str_start[str_ptr]; {erase the string} 4370end; 4371selector:=old_setting; 4372@z 4373 4374@x [53.1373] Need new local. 4375procedure out_what(@!p:pointer); 4376var j:small_number; {write stream number} 4377@y 4378procedure out_what(@!p:pointer); 4379var j:small_number; {write stream number} 4380 @!old_setting:0..max_selector; 4381@z 4382 4383@x [53.1374] Disallow certain \openout filenames, and log results. 4384 while not a_open_out(write_file[j]) do 4385 prompt_file_name("output file name",".tex"); 4386 write_open[j]:=true; 4387@y 4388 while not kpse_out_name_ok(stringcast(name_of_file+1)) 4389 or not a_open_out(write_file[j]) do 4390 prompt_file_name("output file name",".tex"); 4391 write_open[j]:=true; 4392 {If on first line of input, log file is not ready yet, so don't log.} 4393 if log_opened then begin 4394 old_setting:=selector; 4395 if (tracing_online<=0) then 4396 selector:=log_only {Show what we're doing in the log file.} 4397 else selector:=term_and_log; {Show what we're doing.} 4398 print_nl("\openout"); 4399 print_int(j); 4400 print(" = `"); 4401 print_file_name(cur_name,cur_area,cur_ext); 4402 print("'."); print_nl(""); print_ln; 4403 selector:=old_setting; 4404 end; 4405@z 4406 4407@x [54.1376] l.24903 - Add editor-switch variables to globals. 4408@* \[54] System-dependent changes. 4409@y 4410@* \[54/web2c] System-dependent changes for Web2c. 4411Here are extra variables for Web2c. (This numbering of the 4412system-dependent section allows easy integration of Web2c and e-\TeX, etc.) 4413@^<system dependencies@> 4414 4415@<Glob...@>= 4416@!edit_name_start: pool_pointer; {where the filename to switch to starts} 4417@!edit_name_length,@!edit_line: integer; {what line to start editing at} 4418@!ipc_on: cinttype; {level of IPC action, 0 for none [default]} 4419@!stop_at_space: boolean; {whether |more_name| returns false for space} 4420 4421@ The |edit_name_start| will be set to point into |str_pool| somewhere after 4422its beginning if \TeX\ is supposed to switch to an editor on exit. 4423 4424@<Set init...@>= 4425edit_name_start:=0; 4426stop_at_space:=true; 4427 4428@ These are used when we regenerate the representation of the first 256 4429strings. 4430 4431@<Global...@> = 4432@!save_str_ptr: str_number; 4433@!save_pool_ptr: pool_pointer; 4434@!shellenabledp: cinttype; 4435@!restrictedshell: cinttype; 4436@!output_comment: ^char; 4437@!k,l: 0..255; {used by `Make the first 256 strings', etc.} 4438 4439@ When debugging a macro package, it can be useful to see the exact 4440control sequence names in the format file. For example, if ten new 4441csnames appear, it's nice to know what they are, to help pinpoint where 4442they came from. (This isn't a truly ``basic'' printing procedure, but 4443that's a convenient module in which to put it.) 4444 4445@<Basic printing procedures@> = 4446procedure print_csnames (hstart:integer; hfinish:integer); 4447var c,h:integer; 4448begin 4449 write_ln(stderr, 'fmtdebug:csnames from ', hstart, ' to ', hfinish, ':'); 4450 for h := hstart to hfinish do begin 4451 if text(h) > 0 then begin {if have anything at this position} 4452 for c := str_start[text(h)] to str_start[text(h) + 1] - 1 4453 do begin 4454 put_byte(str_pool[c], stderr); {print the characters} 4455 end; 4456 write_ln(stderr, '|'); 4457 end; 4458 end; 4459end; 4460 4461@ Are we printing extra info as we read the format file? 4462 4463@<Glob...@> = 4464@!debug_format_file: boolean; 4465 4466 4467@ A helper for printing file:line:error style messages. Look for a 4468filename in |full_source_filename_stack|, and if we fail to find 4469one fall back on the non-file:line:error style. 4470 4471@<Basic print...@>= 4472procedure print_file_line; 4473var level: 0..max_in_open; 4474begin 4475 level:=in_open; 4476 while (level>0) and (full_source_filename_stack[level]=0) do 4477 decr(level); 4478 if level=0 then 4479 print_nl("! ") 4480 else begin 4481 print_nl (""); print (full_source_filename_stack[level]); print (":"); 4482 if level=in_open then print_int (line) 4483 else print_int (line_stack[level+1]); 4484 print (": "); 4485 end; 4486end; 4487 4488@ To be able to determine whether \.{\\write18} is enabled from within 4489\TeX\ we also implement \.{\\eof18}. We sort of cheat by having an 4490additional route |scan_four_bit_int_or_18| which is the same as 4491|scan_four_bit_int| except it also accepts the value 18. 4492 4493@<Declare procedures that scan restricted classes of integers@>= 4494procedure scan_four_bit_int_or_18; 4495begin scan_int; 4496if (cur_val<0)or((cur_val>15)and(cur_val<>18)) then 4497 begin print_err("Bad number"); 4498@.Bad number@> 4499 help2("Since I expected to read a number between 0 and 15,")@/ 4500 ("I changed this one to zero."); int_error(cur_val); cur_val:=0; 4501 end; 4502end; 4503 4504@ Dumping the |xord|, |xchr|, and |xprn| arrays. We dump these always 4505in the format, so a TCX file loaded during format creation can set a 4506default for users of the format. 4507 4508@<Dump |xord|, |xchr|, and |xprn|@>= 4509dump_things(xord[0], 256); 4510dump_things(xchr[0], 256); 4511dump_things(xprn[0], 256); 4512 4513@ Undumping the |xord|, |xchr|, and |xprn| arrays. This code is more 4514complicated, because we want to ensure that a TCX file specified on 4515the command line will override whatever is in the format. Since the 4516tcx file has already been loaded, that implies throwing away the data 4517in the format. Also, if no |translate_filename| is given, but 4518|eight_bit_p| is set we have to make all characters printable. 4519 4520@<Undump |xord|, |xchr|, and |xprn|@>= 4521if translate_filename then begin 4522 for k:=0 to 255 do undump_things(dummy_xord, 1); 4523 for k:=0 to 255 do undump_things(dummy_xchr, 1); 4524 for k:=0 to 255 do undump_things(dummy_xprn, 1); 4525 end 4526else begin 4527 undump_things(xord[0], 256); 4528 undump_things(xchr[0], 256); 4529 undump_things(xprn[0], 256); 4530 if eight_bit_p then 4531 for k:=0 to 255 do 4532 xprn[k]:=1; 4533end; 4534 4535 4536@* \[54/web2c-string] The string recycling routines. 4537\TeX{} uses 2 upto 4 {\it new\/} strings when scanning a filename in an 4538\.{\\input}, \.{\\openin}, or \.{\\openout} operation. These strings are 4539normally lost because the reference to them are not saved after finishing 4540the operation. |search_string| searches through the string pool for the 4541given string and returns either 0 or the found string number. 4542 4543@<Declare additional routines for string recycling@>= 4544function search_string(@!search:str_number):str_number; 4545label found; 4546var result: str_number; 4547@!s: str_number; {running index} 4548@!len: integer; {length of searched string} 4549begin result:=0; len:=length(search); 4550if len=0 then {trivial case} 4551 begin result:=""; goto found; 4552 end 4553else begin s:=search-1; {start search with newest string below |s|; |search>1|!} 4554 while s>255 do {first 256 strings depend on implementation!!} 4555 begin if length(s)=len then 4556 if str_eq_str(s,search) then 4557 begin result:=s; goto found; 4558 end; 4559 decr(s); 4560 end; 4561 end; 4562found:search_string:=result; 4563end; 4564 4565@ The following routine is a variant of |make_string|. It searches 4566the whole string pool for a string equal to the string currently built 4567and returns a found string. Otherwise a new string is created and 4568returned. Be cautious, you can not apply |flush_string| to a replaced 4569string! 4570 4571@<Declare additional routines for string recycling@>= 4572function slow_make_string : str_number; 4573label exit; 4574var s: str_number; {result of |search_string|} 4575@!t: str_number; {new string} 4576begin t:=make_string; s:=search_string(t); 4577if s>0 then 4578 begin flush_string; slow_make_string:=s; return; 4579 end; 4580slow_make_string:=t; 4581exit:end; 4582 4583 4584@* \[54/ML\TeX] System-dependent changes for ML\TeX. 4585 4586The boolean variable |mltex_p| is set by web2c according to the given 4587command line option (or an entry in the configuration file) before any 4588\TeX{} function is called. 4589 4590@<Global...@> = 4591@!mltex_p: boolean; 4592 4593@ The boolean variable |mltex_enabled_p| is used to enable ML\TeX's 4594character substitution. It is initialised to |false|. When loading 4595a \.{FMT} it is set to the value of the boolean |mltex_p| saved in 4596the \.{FMT} file. Additionally it is set to the value of |mltex_p| 4597in Ini\TeX. 4598 4599@<Glob...@>= 4600@!mltex_enabled_p:boolean; {enable character substitution} 4601 4602 4603@ @<Set init...@>= 4604mltex_enabled_p:=false; 4605 4606 4607@ The function |effective_char| computes the effective character with 4608respect to font information. The effective character is either the 4609base character part of a character substitution definition, if the 4610character does not exist in the font or the character itself. 4611 4612Inside |effective_char| we can not use |char_info| because the macro 4613|char_info| uses |effective_char| calling this function a second time 4614with the same arguments. 4615 4616If neither the character |c| exists in font |f| nor a character 4617substitution for |c| was defined, you can not use the function value 4618as a character offset in |char_info| because it will access an 4619undefined or invalid |font_info| entry! Therefore inside |char_info| 4620and in other places, |effective_char|'s boolean parameter |err_p| is 4621set to |true| to issue a warning and return the incorrect 4622replacement, but always existing character |font_bc[f]|. 4623@^inner loop@> 4624 4625@<Declare additional functions for ML\TeX@>= 4626function effective_char(@!err_p:boolean; 4627 @!f:internal_font_number;@!c:quarterword):integer; 4628label found; 4629var base_c: integer; {or |eightbits|: replacement base character} 4630@!result: integer; {or |quarterword|} 4631begin result:=c; {return |c| unless it does not exist in the font} 4632if not mltex_enabled_p then goto found; 4633if font_ec[f]>=qo(c) then if font_bc[f]<=qo(c) then 4634 if char_exists(orig_char_info(f)(c)) then {N.B.: not |char_info|(f)(c)} 4635 goto found; 4636if qo(c)>=char_sub_def_min then if qo(c)<=char_sub_def_max then 4637 if char_list_exists(qo(c)) then 4638 begin base_c:=char_list_char(qo(c)); 4639 result:=qi(base_c); {return |base_c|} 4640 if not err_p then goto found; 4641 if font_ec[f]>=base_c then if font_bc[f]<=base_c then 4642 if char_exists(orig_char_info(f)(qi(base_c))) then goto found; 4643 end; 4644if err_p then {print error and return existing character?} 4645 begin begin_diagnostic; 4646 print_nl("Missing character: There is no "); print("substitution for "); 4647@.Missing character@> 4648 print_ASCII(qo(c)); print(" in font "); 4649 slow_print(font_name[f]); print_char("!"); end_diagnostic(false); 4650 result:=qi(font_bc[f]); {N.B.: not non-existing character |c|!} 4651 end; 4652found: effective_char:=result; 4653end; 4654 4655 4656@ The function |effective_char_info| is equivalent to |char_info|, 4657except it will return |null_character| if neither the character |c| 4658exists in font |f| nor is there a substitution definition for |c|. 4659(For these cases |char_info| using |effective_char| will access an 4660undefined or invalid |font_info| entry. See the documentation of 4661|effective_char| for more information.) 4662@^inner loop@> 4663 4664@<Declare additional functions for ML\TeX@>= 4665function effective_char_info(@!f:internal_font_number; 4666 @!c:quarterword):four_quarters; 4667label exit; 4668var ci:four_quarters; {character information bytes for |c|} 4669@!base_c:integer; {or |eightbits|: replacement base character} 4670begin if not mltex_enabled_p then 4671 begin effective_char_info:=orig_char_info(f)(c); return; 4672 end; 4673if font_ec[f]>=qo(c) then if font_bc[f]<=qo(c) then 4674 begin ci:=orig_char_info(f)(c); {N.B.: not |char_info|(f)(c)} 4675 if char_exists(ci) then 4676 begin effective_char_info:=ci; return; 4677 end; 4678 end; 4679if qo(c)>=char_sub_def_min then if qo(c)<=char_sub_def_max then 4680 if char_list_exists(qo(c)) then 4681 begin {|effective_char_info:=char_info(f)(qi(char_list_char(qo(c))));|} 4682 base_c:=char_list_char(qo(c)); 4683 if font_ec[f]>=base_c then if font_bc[f]<=base_c then 4684 begin ci:=orig_char_info(f)(qi(base_c)); {N.B.: not |char_info|(f)(c)} 4685 if char_exists(ci) then 4686 begin effective_char_info:=ci; return; 4687 end; 4688 end; 4689 end; 4690effective_char_info:=null_character; 4691exit:end; 4692 4693 4694@ This code is called for a virtual character |c| in |hlist_out| 4695during |ship_out|. It tries to built a character substitution 4696construct for |c| generating appropriate \.{DVI} code using the 4697character substitution definition for this character. If a valid 4698character substitution exists \.{DVI} code is created as if 4699|make_accent| was used. In all other cases the status of the 4700substituion for this character has been changed between the creation 4701of the character node in the hlist and the output of the page---the 4702created \.{DVI} code will be correct but the visual result will be 4703undefined. 4704 4705Former ML\TeX\ versions have replaced the character node by a 4706sequence of character, box, and accent kern nodes splicing them into 4707the original horizontal list. This version does not do this to avoid 4708a)~a memory overflow at this processing stage, b)~additional code to 4709add a pointer to the previous node needed for the replacement, and 4710c)~to avoid wrong code resulting in anomalies because of the use 4711within a \.{\\leaders} box. 4712 4713@<Output a substitution, |goto continue| if not possible@>= 4714 begin 4715 @<Get substitution information, check it, goto |found| 4716 if all is ok, otherwise goto |continue|@>; 4717found: @<Print character substition tracing log@>; 4718 @<Rebuild character using substitution information@>; 4719 end 4720 4721 4722@ The global variables for the code to substitute a virtual character 4723can be declared as local. Nonetheless we declare them as global to 4724avoid stack overflows because |hlist_out| can be called recursivly. 4725 4726@<Glob...@>= 4727@!accent_c,@!base_c,@!replace_c:integer; 4728@!ia_c,@!ib_c:four_quarters; {accent and base character information} 4729@!base_slant,@!accent_slant:real; {amount of slant} 4730@!base_x_height:scaled; {accent is designed for characters of this height} 4731@!base_width,@!base_height:scaled; {height and width for base character} 4732@!accent_width,@!accent_height:scaled; {height and width for accent} 4733@!delta:scaled; {amount of right shift} 4734 4735 4736@ Get the character substitution information in |char_sub_code| for 4737the character |c|. The current code checks that the substition 4738exists and is valid and all substitution characters exist in the 4739font, so we can {\it not\/} substitute a character used in a 4740substitution. This simplifies the code because we have not to check 4741for cycles in all character substitution definitions. 4742 4743@<Get substitution information, check it...@>= 4744 if qo(c)>=char_sub_def_min then if qo(c)<=char_sub_def_max then 4745 if char_list_exists(qo(c)) then 4746 begin base_c:=char_list_char(qo(c)); 4747 accent_c:=char_list_accent(qo(c)); 4748 if (font_ec[f]>=base_c) then if (font_bc[f]<=base_c) then 4749 if (font_ec[f]>=accent_c) then if (font_bc[f]<=accent_c) then 4750 begin ia_c:=char_info(f)(qi(accent_c)); 4751 ib_c:=char_info(f)(qi(base_c)); 4752 if char_exists(ib_c) then 4753 if char_exists(ia_c) then goto found; 4754 end; 4755 begin_diagnostic; 4756 print_nl("Missing character: Incomplete substitution "); 4757@.Missing character@> 4758 print_ASCII(qo(c)); print(" = "); print_ASCII(accent_c); 4759 print(" "); print_ASCII(base_c); print(" in font "); 4760 slow_print(font_name[f]); print_char("!"); end_diagnostic(false); 4761 goto continue; 4762 end; 4763 begin_diagnostic; 4764 print_nl("Missing character: There is no "); print("substitution for "); 4765@.Missing character@> 4766 print_ASCII(qo(c)); print(" in font "); 4767 slow_print(font_name[f]); print_char("!"); end_diagnostic(false); 4768 goto continue 4769 4770 4771@ For |tracinglostchars>99| the substitution is shown in the log file. 4772 4773@<Print character substition tracing log@>= 4774 if tracing_lost_chars>99 then 4775 begin begin_diagnostic; 4776 print_nl("Using character substitution: "); 4777 print_ASCII(qo(c)); print(" = "); 4778 print_ASCII(accent_c); print(" "); print_ASCII(base_c); 4779 print(" in font "); slow_print(font_name[f]); print_char("."); 4780 end_diagnostic(false); 4781 end 4782 4783 4784@ This outputs the accent and the base character given in the 4785substitution. It uses code virtually identical to the |make_accent| 4786procedure, but without the node creation steps. 4787 4788Additionally if the accent character has to be shifted vertically it 4789does {\it not\/} create the same code. The original routine in 4790|make_accent| and former versions of ML\TeX{} creates a box node 4791resulting in |push| and |pop| operations, whereas this code simply 4792produces vertical positioning operations. This can influence the 4793pixel rounding algorithm in some \.{DVI} drivers---and therefore will 4794probably be changed in one of the next ML\TeX{} versions. 4795 4796@<Rebuild character using substitution information@>= 4797 base_x_height:=x_height(f); 4798 base_slant:=slant(f)/float_constant(65536); 4799@^real division@> 4800 accent_slant:=base_slant; {slant of accent character font} 4801 base_width:=char_width(f)(ib_c); 4802 base_height:=char_height(f)(height_depth(ib_c)); 4803 accent_width:=char_width(f)(ia_c); 4804 accent_height:=char_height(f)(height_depth(ia_c)); 4805 @/{compute necessary horizontal shift (don't forget slant)}@/ 4806 delta:=round((base_width-accent_width)/float_constant(2)+ 4807 base_height*base_slant-base_x_height*accent_slant); 4808@^real multiplication@> 4809@^real addition@> 4810 dvi_h:=cur_h; {update |dvi_h|, similar to the last statement in module 620} 4811 @/{1. For centering/horizontal shifting insert a kern node.}@/ 4812 cur_h:=cur_h+delta; synch_h; 4813 @/{2. Then insert the accent character possibly shifted up or down.}@/ 4814 if ((base_height<>base_x_height) and (accent_height>0)) then 4815 begin {the accent must be shifted up or down} 4816 cur_v:=base_line+(base_x_height-base_height); synch_v; 4817 if accent_c>=128 then dvi_out(set1); 4818 dvi_out(accent_c);@/ 4819 cur_v:=base_line; 4820 end 4821 else begin synch_v; 4822 if accent_c>=128 then dvi_out(set1); 4823 dvi_out(accent_c);@/ 4824 end; 4825 cur_h:=cur_h+accent_width; dvi_h:=cur_h; 4826 @/{3. For centering/horizontal shifting insert another kern node.}@/ 4827 cur_h:=cur_h+(-accent_width-delta); 4828 @/{4. Output the base character.}@/ 4829 synch_h; synch_v; 4830 if base_c>=128 then dvi_out(set1); 4831 dvi_out(base_c);@/ 4832 cur_h:=cur_h+base_width; 4833 dvi_h:=cur_h {update of |dvi_h| is unnecessary, will be set in module 620} 4834 4835@ Dumping ML\TeX-related material. This is just the flag in the 4836format that tells us whether ML\TeX{} is enabled. 4837 4838@<Dump ML\TeX-specific data@>= 4839dump_int(@"4D4C5458); {ML\TeX's magic constant: "MLTX"} 4840if mltex_p then dump_int(1) 4841else dump_int(0); 4842 4843@ Undump ML\TeX-related material, which is just a flag in the format 4844that tells us whether ML\TeX{} is enabled. 4845 4846@<Undump ML\TeX-specific data@>= 4847undump_int(x); {check magic constant of ML\TeX} 4848if x<>@"4D4C5458 then goto bad_fmt; 4849undump_int(x); {undump |mltex_p| flag into |mltex_enabled_p|} 4850if x=1 then mltex_enabled_p:=true 4851else if x<>0 then goto bad_fmt; 4852 4853 4854@* \[54] System-dependent changes. 4855@z 4856 4857@x [54.1379] l.24916 - extra routines 4858@* \[55] Index. 4859@y 4860 4861@ @<Declare action procedures for use by |main_control|@>= 4862 4863procedure insert_src_special; 4864var toklist, p, q : pointer; 4865begin 4866 if (source_filename_stack[in_open] > 0 and is_new_source (source_filename_stack[in_open] 4867, line)) then begin 4868 toklist := get_avail; 4869 p := toklist; 4870 info(p) := cs_token_flag+frozen_special; 4871 link(p) := get_avail; p := link(p); 4872 info(p) := left_brace_token+"{"; 4873 q := str_toks (make_src_special (source_filename_stack[in_open], line)); 4874 link(p) := link(temp_head); 4875 p := q; 4876 link(p) := get_avail; p := link(p); 4877 info(p) := right_brace_token+"}"; 4878 ins_list (toklist); 4879 remember_source_info (source_filename_stack[in_open], line); 4880 end; 4881end; 4882 4883procedure append_src_special; 4884var q : pointer; 4885begin 4886 if (source_filename_stack[in_open] > 0 and is_new_source (source_filename_stack[in_open] 4887, line)) then begin 4888 new_whatsit (special_node, write_node_size); 4889 write_stream(tail) := 0; 4890 def_ref := get_avail; 4891 token_ref_count(def_ref) := null; 4892 q := str_toks (make_src_special (source_filename_stack[in_open], line)); 4893 link(def_ref) := link(temp_head); 4894 write_tokens(tail) := def_ref; 4895 remember_source_info (source_filename_stack[in_open], line); 4896 end; 4897end; 4898 4899@ This function used to be in pdftex, but is useful in tex too. 4900 4901@p function get_nullstr: str_number; 4902begin 4903 get_nullstr := ""; 4904end; 4905 4906@* \[55] Index. 4907@z 4908