summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/generic/knuth/errata/tex82.bug
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/doc/generic/knuth/errata/tex82.bug')
-rw-r--r--Master/texmf-dist/doc/generic/knuth/errata/tex82.bug9094
1 files changed, 0 insertions, 9094 deletions
diff --git a/Master/texmf-dist/doc/generic/knuth/errata/tex82.bug b/Master/texmf-dist/doc/generic/knuth/errata/tex82.bug
deleted file mode 100644
index 607ffff358d..00000000000
--- a/Master/texmf-dist/doc/generic/knuth/errata/tex82.bug
+++ /dev/null
@@ -1,9094 +0,0 @@
-This file has been updated periodically ever since TeX82 was born;
-it has been summarized in "The errors of TeX," Software Practice &
-Experience, July 1989. Entries are in chronological order;
-thus the most recent news (including all bugfixes made since
-that article was published) appears at the bottom of the file.
-
-[Add 519 to these entry numbers to get the corresponding number in
-the published article. The article also translates all module
-numbers to their final form; what you are about to read is
-"authentic source material" from the early days before TeX converged.]
-
--------------------------------------------------------------------------------
-
-First updates to the TeX82 listing published in September, 1982.
-(These changes were included in the original Version 0 of TeX, but they
-were discovered after the listing went to press.)
-
-1. Module 943, line 6 (bug discovered 9/28)
-change "if cur_cmd=char_num then" to
- if (cur_cmd=letter) or (cur_cmd=other_char) then r:=qi(cur_chr)
- else if cur_cmd=char_num then
-
-2. "pause" changed to "pausing" and "pause_code" to "pausing code", throughout.
-
-3. Module 719, lines 8 and 11 (bug discovered 9/28)
-insert "rule_save:=overfull_rule; overfull_rule:=0;" after "save_ptr-2;"
-insert "overfull_rule:=rule_save;" before "q:=p+list_offset;"
-and insert a declaration of "overfull_rule: scaled" in module 716.
-
-4. Module 1128, lines 6 and following (bug discovered 9/28)
-change "while n<>0 do" to "loop"
-change "goto done" to
- begin scan_left_brace; new_save_level(false_group);
- goto done;
- end
-change "... return 1130>;" to
- ... return 1130>
- else if n=0 then
- begin new_save_level(case_group); goto done;
- end;
-and change "done: ... (false_group);" to "done:".
-
-5. Module 182, line 10 (suggestion by DRF on 9/30)
-change "0.0" to "?.?"
-
-6. Module 682, new definition of math_spacing (decision of 10/2)
-"0234000122*4000133**3**344*0400400*000000234000111*4111112341011"
-
-7. Module 684, new code for case "4" (decision of 10/2)
-"4": if cur_style<script_style then x:=thick_mu_skip_code else x:=0;
-[Also in module 682 line 7, say "...a conditional thick space (\nonscript..."]
-
-8. Module 11, trie_size changed from 7000 to 8000 because of new
-improved (but longer) hyphenation patterns (10/4)
-
-9. Module 453, forgot to change this when 454 changed (noted by DRF 10/6)
-format_default_length=20 (not 22)
-format_area_length=11 (not 13)
-
- Changes to TEX.WEB made after Version 0 was released in October, 1982.
-
-Since copies of TEX.WEB are not supposed to be edited, there are
-two ways to make your version of TeX bug-free:
- 1. Get a new copy of TEX.WEB.
- 2. Put the corrections into your change file(s).
-Some people will find (1) easier than (2), except the main TeX sources at
-SCORE won't be updated quite as fast as the sources at SAIL (which have to
-be translated into ascii before they are sent to the outside world).
-Actually (2) will be quite easy, unless the list of changes becomes quite
-long, so it is the recommended procedure. In case (2) it would be useful
-to include a comment like "this is fix number xx" (using the numbering
-scheme in this file), so that the change could readily be deleted at some
-future time.
-
-10. Module 857 line -5 (bug discovered 10/8/82 by HWT)
-change it to: if h>0 then decr(h) else h:=trie_op_hash_size;
-
-11. Module 457 line 3 (typo discovered 10/9/82)
-change `\.!' to `\.\&'
-
-12. Module 1245 line 8 (bug fixed 10/9/82, discovered by MMD)
-insert the following between "begin" and "if":
-if format_ident<>0 then initialize; {erase preloaded format}
-
-** Version 0.1 incorporates the above changes.
-
-13. This is an extension to the language, put in to satisfy people who
-objected to the fact that \write (and \openout and \closeout) only
-caused action after being deferred to the next \shipout. Some applications
-call for immediate output, hence a new feature: \immediate followed by
-\openout or \write or \closeout causes the output action to take place
-without delay. For example, \immediate\write{x} is equivalent to
-\shipout\vbox{\write{x}} except that the latter also puts an empty
-page into the DVI file.
-
-The extension requires the following new code:
-13a. Insert `\immediate' after `\closeout' in module 1248.
-13b. Define immediate_code=4 and include the following in module 1252:
- primitive("immediate",extension,immediate_code);
-13c. Include the following in module 1254:
- immediate_code:print_esc("immediate");
-13d. And, in module 1256:
- immediate_code:@<Implement \.{\\immediate}@>;
-13e. Finally, there's a new module inserted after old module 1280.
-Here is the WEB coding for this module:
-
-@ The presence of `\.{\\immediate}' causes the |do_extension| procedure
-to descend to one level of recursion. Nothing happens unless \.{\\immediate}
-is followed by `\.{\\openout}', `\.{\\write}', or `\.{\\closeout}'.
-@^recursion@>
-
-@<Implement \.{\\immediate}@>=
-begin get_nc_token;
-if (cur_cmd=extension)and(cur_chr<=close_node) then
- begin p:=tail; do_extension; {append a whatsit node}
- out_what(tail); {do the action immediately}
- flush_node_list(tail); tail:=p; link(p):=null;
- end
-else back_input;
-end;
-
-** Version 0.2 incorporates the above changes.
-
-14. Like change 11, this one doesn't affect the program, it just improves
-the documentation: Insert the following definitions in module 106:
-define set_glue_ratio_zero(#) == #:=0.0 {assign representation of zero ratio}
-define set_glue_ratio_one(#) == #:=1.0 {assign representation of unit ratio}
-
-These macros are now introduced in a dozen or so future modules, thereby
-eliminating most of the system-dependent changes needed elsewhere for ratios.
-(Note: I also changed 0 to 0.0 in two places of module 182, where a glue_ratio
-comparision was being made.)
-
-15. Change of module 576 (discovered by HWT, 10/14/82)
-"hd:quarterword" should be "hd:eight_bits".
-(The same error occurs in module 522, but in that module the remedy is
-simply to delete the declaration of hd, since this variable is no longer used.)
-
-16. A most embarrassing bug (discovered by DRF, 10/14/82)
-Replace module 531 by:
-
-@ A mild optimization of the output is performed by the |dvi_pop|
-routine, which issues a |pop| unless it is possible to cancel a
-`|push| |pop|' pair. The parameter to |dvi_pop| is the byte address
-following the old |push| that matches the new |pop|.
-
-@p procedure dvi_pop(@!l:integer);
-begin if (l=dvi_offset+dvi_ptr)and(dvi_ptr>0) then decr(dvi_ptr)
-else dvi_out(pop);
-end;
-
-Now we need to make a few changes to subsequent modules:
-16a. In 549, after "incr(cur_s)", insert
- if cur_s>0 then dvi_out(push);
-and before "decr(cur_s)", insert
- if cur_s>0 then dvi_pop(save_loc);
-
-16b. Delete "dvi_out(push);" and "dvi_pop;" from modules 553, 558, 562, 567.
-
-16c. Change module 559 just as in 16a.
-
-17. Module 605, line 6 (discovered 10/15/82)
-The test should be "prev_depth>ignore_depth"
-
-** Version 0.3 incorporates the above changes.
-
-18. Module 11 (noticed by WLS, 10/16/82)
-Delete the definition of align_size (it's harmless but never used)
-
-19. (This change and the next cause major changes to the TRIP output;
-file TRIP.LOG and its relatives are being kept up to date on area [tug,dek].)
-The change avoids error messages when vpackage is called during output.
-Such messages can occur when there was no error, because the page is being
-boxed without the \skip glue from its insertions; so they should be omitted.
-The user who really wants such messages can still get them by saying
-"\setbox255=\vbox to 1ht255{\unbox255}".
-In module 903, insert the followng before the declaration of "wait":
- save_vbadness:integer; {saved value of |vbadness|}
- save_vfuzz: scaled; {saved value of |vfuzz|}
-Then in module 924, insert
- save_vbadness:=vbadness; vbadness:=inf_bad;
- save_vfuzz:=vfuzz; vfuzz:=max_dimen; {inhibit error messages}
-before the call on vpackage, and
- vbadness:=save_vbadness; vfuzz:=save_vfuzz;
-after.
-
-20. Module 917 computes |page_size| improperly. (Noticed 10/21/82)
-Delete the statement "page_so_far[1]:=page_so_far[1]+width(q);"
-and change the preceding statement to:
- page_size:=page_size-h-width(q);
-(The comment about page_so_far in the first paragraph of module 895 is
-correct; I mistakenly introduced a bug in module 917 some months after
-writing the first draft of the code, believing that I was making the
-algorithm more elegant or something.)
-
-** Version 0.4 incorporates the above changes.
-
-21. Since TeX82 applied to (the "woven" documentation) TEX.TEX uses
-about 11500 words of variable-size memory, I'm increasing hi_mem_size
-(in module 12) from 12000 to 13000. Actually, I recommend using considerably
-larger values for mem_max and hi_mem_size, whenever possible.
-
-22. Addition of the \boxmaxdepth parameter (10/22/82):
-This involves renumbering hfuzz_code through dimen_pars, in module 234,
-to numbers 9 through 18; inserting the lines
- @d box_max_depth_code=8 {maximum depth of explicit vboxes}
- @d box_max_depth==dimen_par(box_max_depth_code)
- box_max_depth_code:print_esc("boxmaxdepth");
-to module 234 and
- primitive("boxmaxdepth",assign_dimen,box_max_depth_code);
-to module 235; and changing the call on vpack in module 996 to
- vpackage(link(head),saved(2),saved(1),box_max_depth);
-
-** Version 0.5 incorporates the above changes.
-
-23. Module 1224, line 4 (bug found by GMK/HWT on 10/26/82)
-change "(k+x>eqtb_size)" to "(k+x>eqtb_size+1)"
-
-24. Module 247, line 13 (bug found 10/26/82)
-(bug was reflected in TRIP.LOG but not noticed)
-change "ch_code(p)" to "ch_code(p-single_base)"
-
-25. Module 670, line 18 (bug found 10/27/82)
-interchange the statements "fetch(...)" and "math_type(...):=..."
-(since the fetch routine sometimes has a side-effect of changing math_type)
- A major change (Version 0.6) made on October 28:
-The following list of changes counts as "number 26" on the list.
-Fonts now have identifiers instead of code numbers; the "\:" primitive
-has disappeared; and there are associated new features for "\the".
-
-a. In module 11, delete bad_font_code.
-b. In modules 170 and 172, delete print_esc(":"), and change
- `print_int(font_code' to `sprint_cs(font_ident'.
-c. In module 205, the comment for set_font is revised.
-d. In module 217, there are now five locations for control sequences
- that are perpetually defined; undefined_control_sequence
- is therefore defined to be frozen_control_sequence+5.
-e. In module 248, sprint_cs is now included among <Basic printing procedures>.
-f. Delete the primitive ":" in modules 250 and 251.
-g. Add to module 376: <Declare procedures that scan font-related stuff>
-h. In module 377, seven levels are now distinguished; we define
- font_val=4, ident_val=5, tok_val=6.
-i. In module 380, delete the previous cases for def_family and set_font,
- and the following takes the place of case assign_toks:
- assign_toks,def_family,set_font,def_font: <Fetch a token list or
- font number or font identifier, provided that level=tok_val>;
-j. Module 382 (which now has a new name) has this new ending:
- else if cur_cmd=assign_toks then scanned_result(equiv(m))(tok_val)
- else <Fetch a font number or a font identifier>
-k. Module 389 becomes
- <Fetch a font number or a font identifier>=
- if cur_cmd=set_font then scanned_result(cur_chr)(font_val)
- else if cur_cmd=def_font then
- scanned_result(font_ident[cur_font])(ident_val)
- else begin scan_four_bit_int;
- scanned_result(font_ident[equiv(m+cur_val)])(ident_val);
- end
-l. In module 393, the relation `<>tok_val' becomes `<=mu_val'.
-m. In module 426, the relation `=tok_val' becomes '>=ident_val'.
- Also add a new case to the case statement:
- font_val: begin print(font_name[cur_val]);
- if font_size[cur_val]<>font_dsize[cur_val] then
- begin print(" at "); print_scaled(font_size[cur_val]);
- print("pt");
- end;
- end;
-n. The body of module 427 becomes:
- begin p:=temp_head; link(p):=null;
- if cur_val_level=ident_val then store_new_token(cs_token_flag+cur_val)
- else if cur_val<>null then
- begin r:=link(cur_val); {do not copy the reference count}
- while r<>null do
- begin store_new_token(info(r)); r:=link(r);
- end;
- end;
- the_toks:=p;
- end
-o. In module 480, delete user_font_code; there's a new comment:
- When the user defines \font\f, say, TeX assigns an internal number
- to the user's font \f. For example, if this internal number is 13,
- we will have font_ident[13]=p and equiv(p)=13, where p is the eqtb
- location of the control sequence \f.
-p. In module 481, delete the declaration of font_number, and
- replace the declaration of font_code by
- font_ident:array[internal_font_number] of pointer;
-q. New stuff in module 483 (also delete references to font_number, font_code):
- define bad_font_ident=frozen_control_sequence+4 {denotes a null font}
- font_name[undefined_font]:="nullfont";
- font_ident[undefined_font]:=bad_font_ident;
- text(bad_font_ident):="nullfont"; eq_level(bad_font_ident):=level_one;
- eq_type(bad_font_ident):=set_font;
- equiv(bad_font_ident):=undefined_font;
-r. In module 490, parameter u is new of type pointer, and the
- read_font_info subroutine is changed to a function that
- returns an internal_font_number. There's a new local variable
- g:internal_font_namber; {the number to return}
- and we set g:=undefined_font immediately upon entering read_font_info.
- Also set read_font_info:=g just before exiting.
-s. In module 491, print_int(u) becomes sprint_cs(u).
-t. Delete the statements involving font_code and font_number in module 506,
- and set g:=f at the end of that module.
-u. The body of module 507 becomes:
- <Declare procedures that scan font-related stuff>=
- procedure scan_font_ident;
- var f:internal_font_number;
- begin <Get the next non-blank non-call...>;
- if cur_cmd=set_font then f:=cur_chr
- else begin print_nl("! Missing font identifier");
- help2("I was looking for a control sequence whose")
- ("current meaning has been defined by \font.");
- back_error; f:=undefined_font;
- end;
- end;
-v. New beginning of module 508:
- The following routine is used to implement `\texinfo f n'.
- The boolean parameter writing is set true if the calling program
- intends to change the parameter value.
- <Declare procedures that scan font-related stuff>=
-and "scan_font_number" is changed to "scan_font_ident".
-w. In module 509, "print_int(font_code" becomes "sprint_cs(font_ident".
- Also "font code is defined" becomes "\font is loaded" in the help.
-x. In module 940, the first line of help is changed to
- "You have to specify a font identifier,"
-y. The set_font case in module 1138 reduces to
- set_font: define(cur_font_loc,data,cur_chr);
-z. In module 1153, delete all the complicated stuff starting with "scan_int"
- and substitute simply this:
- scan_font_ident; define(p,data,cur_val);
- end;
-aa. Change new_font to new_font(a) in module 1169, and add parameter
- (a:small_number)
- in module 1170. Also add the label common_ending, and declare
- variable u to have type pointer. The code beginning with "scan_int"
- is changed to the following:
- get_token;
- if cs_ptr=0 then
- <Complain about the missing control sequence and return>;
- u:=cs_ptr; scan_optional_equals; scan_file_name;
- <Scan the ``at'' size specification>;
- <If this font has already been loaded, set f to the internal
- font number and goto common_ending>;
- f:=read_font_info(u,cur_name,cur_area,s);
- common_ending: define(u,set_font,f); font_ident[f]:=u;
- exit:end;
-bb. New module 1172:
- When the user gives a new identifier to a font that was previously
- loaded, the new value becomes the font_ident of record.
- Font names `xyz' and `XYZ' are considered to be different.
- <If this font has already been loaded...>=
- for f:=font_base+1 to font_ptr do
- if [the test previously in module 1174] then goto common_ending
-cc. New module 1173:
- <Complain about the missing control sequence and return>=
- begin print_nl("! A font identifier must be a control sequence");
- help2("You should say, e.g., `\font\f=fontfilename'.")
- ("(I'm going to ignore the \font command you just gave.)");
- back_error; return;
- end
-dd. New module 1174:
- <Cases of print_cmd_chr...>=
- set_font:begin print("select font "); print(font_name[chr_code]);
- if font_size[chr_code]<>font_dsize[chr_code] then
- begin print(" at "); print_scaled(font_size[chr_code]);
- print("pt");
- end;
- end;
-ee. Delete the comment at the beginning of module 1227, and delete the
- loop for k:=0 to bad_font_code-1, and delete dump_int(undefined_font).
-ff. Delete the repeat loop in module 1228.
-gg. Change font_code to font_ident in module 1229, and change
- print_int(font_code to sprint_int(font_ident.
-hh. In module 1230,
- begin undump(single_base)(undefined_control_sequence)(font_ident[k]);
- undump_qqqq(font_check[k]); [and continue as before]
-
-The changes above have been incorporated into Version 0.6.
- The ill-fated Version 0.7
-
-27. (Here's a change that I retracted shortly after making it, since I
-discovered that the source was flaky after all; and I also found a reliable
-source [NBS Circular 570] confirming my original information. I include
-the note here only for historical purposes...)
-
-"After years of searching, I've finally found a definitive definition of
-the printer's point; and (unfortunately) my previous conjecture was wrong.
-The truth is that 83pc=35cm, exactly; so I am changing TeX to conform.
-This means some changes in the comments of modules 101 and 517, and the
-following changes to the program:
-
-"27a. In modules 547 and 571, the appropriate DVI numbers are now:
- dvi_four(109375); dvi_four(2039808); {conversion ratio for sp}
-"27b. The guts of module 418 become:
- if scan_keyword("in") then set_conversion(63246)(875)
- else if scan_keyword("pc") then set_conversion(12)(1)
- else if scan_keyword("cm") then set_conversion(996)(35)
- else if scan_keyword("mm") then set_conversion(498)(175)
- else if scan_keyword("bp") then set_conversion(10541)(10500)
- else if scan_keyword("dd") then set_conversion(996)(931)
- else if scan_keyword("cc") then set_conversion(11952)(931)
- else..."
-
-*** Version 0.7 of TeX incorporated the changes above (82/10/30);
-this version was withdrawn on 82/11/2.
- Changes subsequent to Version 0.6
-
-28. The experience with #27 did lead me to one improvement, thanks
-to Chuck Bigelow, with respect to Didot points. (11/4/82)
-Add the following comment to module 418:
- According to the definitions here, $\rm2660\,dd\approx1000.33297\,mm$;
- this agrees well with the value $\rm1000.333/,mm$ cited by Bosshard
- in {\sl Technische Grundlagen zur Satzherstellung\/} (Bern, 1980).
-And change two lines of the code there as follows:
- else if scan_keyword("dd") then set_conversion(1238)(1157)
- else if scan_keyword("cc") then set_conversion(14856)(1157)
-
-29. The new font material is made more robust by ensuring that \the\font
-always returns a pointer to a control sequence whose command code is
-set_font. (Change 11/4/82)
-
-29a. The code changed in 26aa is changed again, to the following:
- <If the next token isn't a control sequence, issue a complaint and
- return; otherwise set u:=cs_ptr, and set hash_used to the
- location of a ``frozen'' copy of the new font identifier>;
- define(u,set_font,undefined_font);
- scan_optional_equals; scan_file_name;
- <Scan the ``at'' size specification>;
- <If this font has already been loaded, set f to the internal
- font number and goto common_ending>;
- f:=read_font_info(u,cur_name,cur_area,s);
- common_ending: equiv(u):=f; geq_define(hash_used,set_font,f);
- font_ident[f]:=hash_used;
- exit:end;
-29b. Instead of 26cc, here's the new module 1173:
- We reserve a special control sequence for the font identifier;
- this one cannot be redefined by the user, so it is safe to
- return it as a value of \the\font.
- <If the next token isn't a control sequence...>=
- get_token;
- if cs_ptr<hash_base then
- begin print_nl(
- "! A font identifier must be a multiletter control sequence");
- help2("You should say, e.g., `\font\ffn=fontfilename'.")
- ("(I'm going to ignore the \font command you just gave.)");
- back_error; return;
- end;
- repeat if hash_is_full then overflow("hash size",hash_size);
- decr(hash_used);
- until text(hash_used)=0; {search for an empty location in hash}
- u:=cs_ptr; text(hash_used):=text(u); {copy the name}
- stat incr(cs_count); tats
-
-30. Module 993, replace lines 5 to 7 (11/5/82):
-else begin if k=vmode then new_save_level(vbox_group)
- else begin new_save_level(vtop_group); k:=vmode;
- end;
- if looseness<>0 then eq_word_define(int_base+looseness_code,0);
- if hanging_indent<>0 then
- eq_word_define(dimen_base+hanging_indent_code,0);
- if par_shape_ptr<>null then eq_define(par_shape_loc,shape_ref,null);
- end;
-
-31. Module 403, replace line 5 (11/6/82):
-if cur_tok<cs_token_flag then
- begin cur_val:=cur_chr;
- if cur_cmd<=right_brace then
- if cur_cmd=right_brace then incr(align_state)
- else decr(align_state);
- end
-
-32. Improvements to error recovery for bad alignments (11/6/82):
-In module 1039, replace "begin align_error; goto reswitch; end" by "align_error"
-In module 1040, delete "cur_cmd:=left_brace;" and "cur_cmd:=right_brace;"
- and change "error" to "back_error"
-In module 1041, delete "cur_cmd:=relax;"
-
-33. More power to \let (11/8/82):
-33a. Module 1141 becomes:
- <Assignments>+=
- let: begin get_token;
- if cs_ptr<>0 then <Carry out the \let operation>
- else begin print_nl
- ("! You can use \let only with control sequences");
- help2("I'm not \let-ting anything change here,")
- ("since I can only do things like `\let\a=b'.");
- back_error;
- end;
- end;
-33b. Module 1142 becomes:
- <Carry out the \let...>=
- begin p:=cs_ptr;
- repeat get_token;
- until cur_cmd<>spacer;
- if cur_tok=other_token+"=" then
- begin get_token;
- if cur_cmd=spacer then get_token;
- end;
- if cur_cmd>=call then add_token_ref(cur_chr);
- define(p,cur_cmd,cur_chr);
- end
-
-34. This change helps you see an undefined control sequence
-in certain unusual cases (discovered by JDH, 11/8/82):
-Add the clause "(base_ptr=input_ptr) or" to module 294, line 2.
-
-35. Here's an improvement in the formula for demerits; previously
-more weight was given to minimizing bad spacing on lines with penalties,
-so that (slightly loose hyphenated line)(OK line) was considered worse
-than (OK hyphenated line)(quite loose line). (fixed 11/8/82)
-Change lines 2--7 of module 772 to the following:
- d:=line_penalty+b; d:=d*d;
- if pi<>0 then
- if pi>0 then d:=d+pi*pi
- else if pi>eject_penalty then d:=d-pi*pi;
-
-36. Minor change to save buffer space in non-INITEX (11/10/82):
-Enclose the declaration of pool_file in module 50 by init...tini.
-
-37. Minor improvement in format for the context of error messages (11/13/82):
-37a. Module 289, type "inserted" split into "backed_up=3", "inserted=4"
-and the other type numbers increase: "macro=5", etc.
-37b. In module 296, backed_up: if loc=null then print_nl("<recently read>")
- else print_nl("<to be read again> ");
- inserted: print_nl("<inserted text> ");
-37c. Minor changes to comments in modules 289 and 293.
-37d. Change "inserted" to "backed_up" in module 294.
-37e. Add definition "back_list(#)==begin_token_list(#,backed_up)" in module 305.
-37f. In module 306, first test should be ">=backed_up", second "<=inserted".
-37g. Change ins_list to back_list in modules 307, 318, 375, 1195.
-37h. Add definition to module 308:
- ins_error==begin back_error; token_type:=inserted; end
-37i. Change back_error to ins_error in modules 362, 1040, 1046.
-37j. Change "<to be read again>" to "<inserted text>" in module 973 help.
-
-38. Module 407, the error message is changed (11/11/82) to:
-"! Missing number, treated as zero".
-
-39. Fix anomaly when hbadness or vbadness is small (11/11/82):
-Module 593, line 2, "if (-x-total_shrink[normal]>hfuzz) or (hbadness<100)"
-Module 603, line 2, "if (-x-total_shrink[normal]>vfuzz) or (vbadness<100)"
-
-40. Added the \tokens primitive (11/13/82):
-In module 223, defined tokens_loc and tokens (analogous to every_par).
-In module 225, defined the primitive.
-In module 1146, changed the comment to include tokens_loc as a possibility.
-
-41. Change get_nc_token to get_token in module 374 (11/13/82).
-(In particular \def\foo{...}\foo won't say "undefined c.s." now!)
-(This change later retracted during debugging; it was found that
-"endv" aborts the job, so this cure was worse than the disease. Then
-it was re-established as part of the major change to conditionals,
-because endv needed to be more robust anyway.)
-
-42. In module 699, we make \span expand in a preamble (11/13/82).
-Change lines -7 through -3 to:
- begin get_nc_token; goto reswitch;
- end;
-
-43. Modules 321 and 322 have been altered for better efficiency (11/12/82)
-and better exposition; the three conditions of module 322 are now
-in separate if tests.
-
-44. Frozen control sequences are now unredefinable. (11/16/82)
-A new procedure get_r_token has been introduced to give uniform error
-messages for \def, \let, \read, \font, \mathchardef, and to make them
-incapable of changing the frozen equivalents.
-
-Incidentally, get_nc_token is changed to get_x_token; and ch_code
-becomes cat_code.
- A major change (Version 0.8) made on November 14--16:
-Conditional statements are taken from semantics to syntax.
-
-This change, which counts as number 45 on the list, made it necessary
-to renumber the modules. And it was such a drastic change, the
-differences can only be sketched here, using the old module numbers
-for reference. A variety of other things were cleaned up because this
-change made it more natural for them to be handled differently.
-
-45a. Module 158, inserted a permanently empty token list called null_list.
-45b. Module 204, deleted if_test, case_branch, else_code, convert;
- inserted end_cs_name.
-45c. Module 206, inserted if_test, fi_or_else, cs_name, convert, and
- end_template (the latter comes after long_outer_call).
-45d. Module 217, there are now nine frozen control sequences; also null_cs.
-45e. Modules 247 and 248, must be able to print a null control sequence.
-45f. Module 268 (leave_transparent_group) disappears; comments in the
- previous modules also are appropriately simplified.
-45g. Module 273, delete endv_token.
-45h. Modules 277 and 278, delete references to endv (it no longer appears).
-45i. After module 281, a procedure show_cur_cmd_chr takes the
- code for tracing commands from module 937.
-45j. Module 317 now forbids \outer control sequences when skipping,
- and inserts \fi in front of them, for error recovery.
-45k. Module 334 now uses null_cs if carriage-return is an escape.
-45l. Module 343 no longer has endv test.
-45m. Module 344, major extensions to expand_calls make it several modules
- longer. It saves global variables like cur_val. It changes
- end_template to endv. It processes cs_name and convert.
- It processes if_test by calling the "conditional" procedure.
- It processes fi_or_else by checking their legality, and (if legal)
- updating the if stack.
-45n. Module 373 (pass_block) disappears.
-45o. After module 400, radix and cur_val and cur_val_level are initialized.
-45p. Module 428 changes so that conv_toks is a procedure rather than a
- function; this procedure is invoked by expand_calls.
-45q. Modules 436 and 1032, delete reference to conv_toks.
-45r. After module 443, the entire part 48 moves to this part of the program,
- and the parts are renumbered accordingly. \case is changed to
- \ifcase, and it resides under the if_test command.
- New routines are inserted to maintain a linked stack that records
- the current state of conditionals. There's a procedure
- pass_text that skips text while looking for \fi or \else or \or
- on level zero with respect to \if...\fi nesting. The previous
- routines for skip control via handle_right_brace are eliminated,
- and the new ones are somewhat simpler. The new \ifcat is mostly
- combined with the old \if; they no longer ignore spaces.
- The scanner_status is set to normal while processing \ifx.
- \ifx will consider \a to equal 0 after \let\a=0.
-45s. Modules 701, 707: endv_token is replaced by a token for a frozen
- control sequence whose command code end_template makes it behave
- like an outer_call. After expand_calls, it is converted to another
- frozen control sequence, whose command code is endv. This two-step
- facilitates error recovery, instead of giving a fatal error stop.
-45t. Module 874, remove "pass_block(1); goto done".
-45u. After module 1047, routine for end_cs_name prints an error message.
-45v. Module 1049, get_nc_token becomes get_token. (else $\ifmmode fails)
-45w. Module 1202 gets another case (end_template).
-45x. Module 1243, new warning is printed if the if stack isn't empty.
- Changes after version 0.8
-
-46. Declare c : ascii_code in module 825 (noted by DRF, 11/21/82)
-
-47. Module 776 lines 4-6 (suggested by DRF, 11/21/82)
-threshold:=pretolerance;
-if threshold>=0 then
- begin stat if tracing_stats>2 then
- begin begin_diagnostic; print_nl("@@firstpass");
- end; tats
- second_pass:=false;
- end
-else begin threshold:=tolerance; second_pass:=true;
- end;
-
-48. Protection for DVI files (added 11/16/82)
-Replace lines 2 and 3 of module 570 by:
- <Update the values of max_h and max_v; but if the page is too large,
- goto done>;
-Move the statement "dead_cycles:=0" from module 570 to module 568.
-Declare "label done;" in module 568.
-And add the following new module after 570:
-
-@ Sometimes the user will generate a huge page because other error messages
-are being ignored. Such pages are not output to the \.{dvi} file, since they
-may confuse the printing software.
-
-@<Update the values of |max_h| and |max_v|; but if the page is too large...@>=
-if (height(p)>max_dimen)or(depth(p)>max_dimen)or(width(p)>max_dimen) then
- begin print_nl("! Huge page cannot be shipped out");
- help2("The page just created is more than 18 feet tall or")@/
- ("more than 18 feet wide, so I suspect something went wrong.");
- error;
- if tracing_output=0 then
- begin begin_diagnostic;
- print_nl("The following box has been deleted:");
- show_box(p);
- end_diagnostic(true);
- end;
- goto done;
- end;
-if height(p)+depth(p)>max_v then max_v:=height(p)+depth(p);
-if width(p)>max_h then max_h:=width(p)
-
-49. New features \everymath and \everydisplay (12/2/82).
-Make changes analogous to those for "\tokens" (see change 40).
-Put the following just before the end of module 1050:
- if every_math<>null then begin_token_list(every_math,every_math_text);
-And put the following just before the end of module 1056:
- if every_display<>null then
- begin_token_list(every_display,every_display_text);
-
-50. New feature \futurelet (12/2/82):
-Module 1141 changes again. (Also, "let" and "futurelet" share cmd code "let".)
-let: begin n:=cur_chr;
- get_r_token; p:=cs_ptr;
- if n=normal then
- begin repeat get_token;
- until cur_cmd<>spacer;
- if cur_tok=other_token+"=" then
- begin get_token;
- if cur_cmd=spacer then get_token;
- end;
- end
- else begin get_token; q:=cur_tok; get_token; back_input;
- cur_tok:=q; back_input; {look ahead, then back up}
- end; {|back_input| doesn't affect |cur_cmd|, |cur_chr|}
-and continue with "if cur_cmd>=call", as before.
-
-*** The changes above have been incorporated into version 0.9 of TeX.
- Changes after version 0.9
-
-51. new \endinput primitive (suggested by FY, 12/7/82):
-\input and \endinput both use the same command code. The cases in module
-955 are deleted and replaced by those in module 965 (which disappears),
-because \input is now allowed in any mode. The code for any_mode(input)
-is "if cur_chr=0 then start_input else force_eof:=true", and it moves from
-module 952 to just before module 1197. The global variable force_eof
-is initially false, and module 340 becomes (after first:=start;)
- if not force_eof then
- begin if input_ln.... else force_eof:=true;
- end;
- if force_eof then begin print_char(")"); force_eof:=false;...
-
-52. Module 1005, line 4 (12/8/82)
-change "if align_state<0" to "if (mode<0)or(align_state<0)"
-(This avoids embarrassing case where TeX says "type a command or say \end"
-but when you type \end it says "You can't use \end in restricted horiz mode".)
-
-53. Patch to the new code for \csname (12/21/82)
-After eq_type(cs_ptr):=relax, also say equiv(cs_ptr):=256.
-(This corrects a bug that would appear only if \csname occurs right
-after a file name.)
-
-54. Change 47 introduced a bug when tracingonline=0 (12/20/82)
-when omitting firstpass, also do "if tracing_stats>2 then begin_diagnostic;"
-
-55. \hskip -1pt plus 2pt was parsed as \hskip -(1pt plus 2pt)! (12/20/82)
-In module 421, before line -4, insert the following:
- if negative then
- begin cur_val:=-cur_val; negative:=false;
- end;
-But then realize that "negative" is always false on line -2; simplify.
-
-56. Cosmetic change to paragraph statistics (12/23/82)
-tight_fit..very_loose_fit codes have been renumbered very_loose_fit..tight_fit.
-
-57. Module 729 changes to make TeX language more consistent (12/23/82):
-else if type(tail)<>glue_node then tail_append(new_penalty(inf_penalty))
-else begin type(tail):=penalty_node; delete_glue_ref(glue_ptr(tail));
- flush_node_list(leader_ptr(tail)); penalty(tail):=inf_penalty;
-
-58. Commas are allowed as alternates to radix points. (12/23/82)
-define continental_point_token=other_token+"," {decimal point, Eurostyle}
-in module 400, and insert the following twice in 409:
- if cur_tok=continental_point_token then cur_tok:=point_token;
-
-59. \hangindent becomes a normal parameter. (12/23/82)
-This simplifies the code in obvious ways; for example, module 1148 disappears.
-The command code hang_indent goes away too; what was previously called
-hanging_indent is then renamed hang_indent.
-
-60. \prevgraf becomes accessible. (12/23/82)
-This involves renaming the "after" field "pg_field" in the nest array;
-making a new command code set_prev_graf;
-including the following loop into scan_the:
- nest[nest_ptr]:=cur_list; p:=nest_ptr;
- while abs(nest[p].mode_field)<>vmode do decr(p);
- scanned_result(nest[p].pg_field)(int_val);
-and including the following active procedure for any_mode(set_prev_graf):
- procedure change_prev_graf;
- var p:0..nest_size; {index into |nest|}
- begin nest[nest_ptr]:=cur_list; p:=nest_ptr;
- while abs(nest[p].mode_field)<>vmode do decr(p);
- scan_optional_equals; scan_int;
- if cur_val<0 then
- begin print_nl("! Bad \prevgraf");
- help1("I allow only nonnegative values here.");
- int_error(cur_val);
- end
- else begin nest[p].pg_field:=cur_val; cur_list:=nest[nest_ptr];
- end;
- end;
-
-61. \clubpenalty is split off from \widowpenalty. (12/23/82)
-
-62. Bad bug in module 1005 (12/24/82)
-(must not go to reswitch if \par is a macro!)
-Instead of setting cur_cmd and cur_chr and goto reswitch, just back_input
-and set token_type:=inserted.
-
-63. \openin not to prompt if file not present (12/25/82)
-Change lines -4 and -3 of module 1183 to:
- if a_open_in(read_file[n]) then read_open[n]:=just_open
- else read_open[n]:=closed;
-
-64. New \jobname primitive (12/25/82)
-It is added to the "convert" command in the obvious way.
-In conv_toks, the relevant code is
- if job_name=0 then open_log_file
-before "selector" is changed and
- print(job_name)
-after.
-
-65. Better error recovery for math-only things (12/25/82):
-In module 952, don't goto reswitch after insert_dollar_sign.
-In module 954, first back_input, then set cur_tok, and
-don't bother to set cur_chr or cur_cmd; ins_error instead of back_error.
-
-66. Module 1163, line 3, insert "scan_optional_equals" (12/25/82).
-Also make \the\parshape allowed.
-
-67. The location where an \if begins is stacked (12/26/82)
-so that a better error message can be given for \end while \if is incomplete.
-This means two-word nodes instead of one-word nodes in the if stack.
-
-68. Change 30 is extended to \insert, \vadjust, \valign, \output (12/26/82)
-The one-time-only paragraph parameters are now cleared by a
-subroutine called normal_paragraph; hang_after is also set to 1.
-The essential change being made now is to call normal_paragraph in modules
-704, 932, 1009, and 1076.
-
-69. \pagetotal and \pagegoal are added (12/27/82)
-The changes are analogous to, but simpler than, those for \prevgraf.
-
-70. Tracing of page-optimization calculations (12/27/82)
-A bunch of print commands are added to modules 897, 914, and 918,
-activated if tracing_pages>0. Also, \tracingparagraphs is separated
-from \tracingstats.
-
-**** The changes above have been incorporated into version 0.91 of TeX
-
-71. The build_page procedure is broken in two parts (Dec 31, 1982)
-by making module 919 into a procedure called fire_up.
-
-72. \ifeven1\else is made legal by introducing if_code (Dec 31, 1982)
-This improves part of the code in change 45; if_limit has a specific
-value that recovers automatically from a former syntax error.
-
-73. Improvement to alignments when columns don't occur (Dec 31, 1982)
-Delete module 711; and where it was used in module 708, say this:
- begin fin_col:=true; return;
- end;
-Also, in module 717, replace the statement "width(q):=0" by
-"<Nullify width(q) and the tabskip glue following the current column>"
-where that new module has the following code:
- begin width(q):=0; r:=link(q); s:=glue_ptr(r);
- if s<>zero_glue then
- begin add_glue_rel(zero_glue); delete_glue_ref(s);
- glue_ptr(r):=zero_glue;
- end;
- end
-
-74. Better error message in overfull alignment (Dec 31, 1982)
-In module 717, don't set both height and width; set the height zero.
-Then in module 719, switch width to height if necessary. (People didn't
-understand the previous error messages, and I couldn't blame them.)
-
-*** The changes above have been incorporated into version 0.92 of TeX82
-*** (which was the last version of 1982, completed 11:59pm on December 31)
- The first changes after 1982
-
-75. Modules 961 and 962 should be one module. (Jan 3, 1983)
-Also, the absolute constant 100 is replaced, and the test becomes
- if ((page_head=page_tail)and(head=tail)and(dead_cycles=0))or
- (dead_cycles>max_dead_cycles) then
-
-76. Surprise bug: module 1010. (Jan 3, 1983)
-The case "if head<>tail" needs an else clause: else pop_nest.
-Also remove the "<Scan an optional space>" in that module.
-
-77. Improvement to change 22 (Jan 4, 1983)
-In module 996, use box_max_depth from inside the \vbox:
- @!d:scaled; {maximum depth}
- begin d:=box_max_depth; unsave;... vpackage(...,d);
-
-78. \groupbegin and \groupend changed to \begingroup and \endgroup (Jan 4, 83)
-
-79. \deadcycles made accessible (Jan 4, 83)
-
-80. New calculations for split insertions (Jan 4, 83)
-In module 918, we now work with natural width, and add in the page depth too:
-The line "else w:=x_over_n..." is changed to
- else begin w:=page_goal-page_total-page_depth;
- if count(n)<>1000 then w:=x_over_n(w,count(n))*1000;
- end;
-(Note that cur_page_height and cur_page_depth and page_size have been
-renamed page_total, page_depth, and page_goal, in accordance with new syntax.)
-
-*** The changes above have been incorporated into Version 0.93
-
-81. Old bug finally unearthed by PHY (Jan 6, 1983)
-insert "incompleat_node:=null;" after "push_nest;" in module 1097.
-
-82. Extension of change 69: \pageshrink, etc. added (Jan 6, 1983)
-
-83. \floatingpenalty and \insertpenalties added (Jan 6, 1983)
-Also, the insertion nodes now have a new format, so that the values of
-\floatingpenalty, \splittopskip, and \splitmaxdepth can be stored with
-each insertion; this requires the obvious changes in several places:
-a) Module 136, ins_node has fields float,depth,height,ins_ptr,split_top_ptr
-b) Module 184, these fields are displayed
-c) Module 198, ins_node case, also delete_glue_ref(split_top_ptr(p))
-d) Module 202, ins_node case, also add_glue_ref(split_top_ptr(p))
-e) Modules 226-228, new integer parameter \floatingpenalty
-f) Module 883, add parameter d to vert_break subroutine
-g) Module 885, use d instead of split_max_depth
-h) Module 890, argument split_max_depth to call of vert_break
-i) Module 894, change width to height (better name)
-j) Module 900, initialize insert_penalties here, not in 901
-k) Module 914, cost to be awful_bad if insert_penalties>=10000
-l) Module 916, add float(p) to insert_penalties if type(r)<>inserting
-m) Module 916, subtract page_depth from delta
-n) Module 918, subtract page_shrink from delta
-o) Module 918, argument depth(p) to call of vert_break
-p) Module 921, insert_penalties:=0, save split_top_skip before calling 925
-q) Module 921, restore split_top_skip before calling 924
-r) Module 928, set split_top_skip:=split_top_ptr(p) before prune_page_top
-s) Module 929, after q:=p, incr(insert_penalties)
-t) Module 929, before free_node, delete_glue_ref(split_top_ptr(p))
-u) Module 933, clear insert_penalties before calling 934
-v) Module 978, more local variables needed
-w) Module 1010, build the newfangled ins_node
-
-84. Scanner goes to new_line when <return> is category 13 (Jan 7, 1983)
-Insert state:=new_line in module 323 just before the reference to module 339;
-and delete "state:=new_line;" from modules 328 and 330 (and their names).
-
-85. Distinguish between user \kern and font \kern (Jan 9, 1983)
-The nontrivial parts of this are to change "type(s)<>kern_node" to
-"(type(s)<>kern_node)or(subtype(s)<>normal)" in modules 809 and 810;
-and to say "kern_node: if subtype(s)=explicit then goto done4" in module 812.
-The \kern primitive now has "explicit" instead of "normal" in 967.
-
-86. "ignorespace" becomes "ignorespaces" (Jan 9, 1983)
-
-87. Don't omit a blank space after \def, \message, \mark, etc. (Jan 9, 1983)
-<Scan an optional space> is removed from modules 431, 848, 874.
-"info(r):=space_token;" and "link(r):=get_avail; r:=link(r);" removed from 1278.
-
-*** The above changes appear in Version 0.94.
- Version 0.95
-
-88. New active characters in math mode (Jan 12, 1983)
-In module 1062, add a label "restart" and change lines -3 and -2 as follows:
-fam(p):=(c div 256) mod 16;
-if c>=var_code then
- if fam(p)<8 then fam(p):=cur_fam
- else begin <Convert c to an active character whose equivalent is
- ready to be scanned next>; goto restart;
- end;
-In module 1064, the body of the procedure becomes
-begin if c>='4000 then <Convert c ...> else <the former body>; end
-And there's a new module:
-<Convert c...>=
-begin cs_ptr:=(c mod 128)+active_base;
-cur_cmd:=eq_type(cs_ptr); cur_chr:=equiv(cs_ptr); x_token; back_input;
-end
-
-89. Surprise bug: $1-$ treated the - as binary (Jan 15, 1983)
-New module <Convert a final bin_noad to an ord_noad>=
- if r_type=bin_noad then type(r):=ord_noad
-is called in module 649 before the call of 678, and in module 651
-in the place where that code already appears.
-
-90. Another oversight (Jan 15, 1983)
-Add "space_factor:=1000;" after "push_nest" in modules 1027, 1029
-
-91. And a more embarrassing one (Jan 16, 1983)
-I forgot "spotless:=false;" at the beginning of the procedure in module 80.
-But while fixing this, I decided to make it more general since IBMers want
-a return code at the end of the job. So there's a history variable that has
-four values: spotless, warning_issued, error_message_issued, fatal_error_stop.
-a) module 75: declare history, define spotless etc.
-b) module 76: initialize history:=spotless
-c) module 80: if history<error_mess... then history:=error_mess...
-d) 80 and 90: history:=fatal_error_stop before jump_out
-e) 92: if history<error_message_issued then
-f) 232: if history=spotless then history:=warning_issued
-g) 1243: if history=warning_issued then print_nl("(see the log...)")
-
-92. "This can't happen" could happen, so there's new error recovery (Jan 16, 83)
-In module 933, replace the call on confusion by a call of the following module:
- @ @<Recover from an unbalanced output routine@>=
- begin print_nl("! Unbalanced \output routine");
- help2("Your sneaky output routine has fewer real {'s than }'s.")@/
- ("I can't handle that very well; good luck."); error;
- repeat get_token;
- until loc=null;
- end
-In module 1278, replace the call on confusion by a call of:
- @ @<Recover from an unbalanced write command@>=
- begin print_nl("! Unbalanced \write command");
- help2("On this page there's a \write with fewer real {'s than }'s.")@/
- ("I can't handle that very well; good luck."); error;
- repeat get_token;
- until cur_tok=end_write_token;
- end
-
-93. String overflow clobbered the log file (Jan 18, 1983)
-Also, "confusion" before log file open would cause problems. Also start_input
-calling open_log_file calling prompt_file_name calling fatal_error!
-To fix these anomalies, open_log_file no longer calls prompt_file_name,
-if interaction<scrollmode; instead, it terminates after printing what went
-wrong. Also, the fatal_error and overflow and confusion procedures call
-the following new subroutine:
-procedure normalize_selector;
-begin if job_name>0 then selector:=term_and_log else selector:=term_only;
-if interaction=batch_mode then decr(selector);
-if job_name=0 then open_log_file;
-end;
-
-94. \ifeof\fi loops infinitely (Jan 18, discovered by Lamport)
-Change 72 converted such a \fi to <space>\fi. Now it is converted to \relax\fi.
-
-95. \limitswitch changed to \displaylimits et al. (Jan 18, 1983)
-[Incidentally, this fixes a bug in the former positioning of \int\limitswitch]
-a) module 608: subtype of Op can be normal, limits, or no_limits.
-b) 620: display the subtype if not normal
-c) 667: new logic decides limits before looking at the operand (and the operand
- is now called the nucleus); the italic correction is removed only if
- it should not be put back
-d) 1069: subtype(tail):=cur_chr
-
-96. Minor changes to math in unusual cases (Jan 19, 1983)
-a:delete "if height(y)<=0 then height(y):=default_rule_thickness" in module 658
-b:move "if thickness(q)=default..." from module 664 to module 661
-c:delete module 1081, that error message isn't worth the bother
-d:in module 1062, char_num case, c:=math_code(cur_val) (if cur_val<128)
-e:in module 1064, a similar change
-
-97. Bad spacing from change 6 is corrected (Jan 19, 1983)
-underline, overline, radical, vcenter, and accent noads now revert to type
-Ord instead of type Inner.
-{...} produces type Ord also.
-There's a new primitive \mathinner.
-The new_noad function now produces an ord_noad (change its calls accordingly).
-And the default is changed in module 679 to t:=ord_noad; the fraction_noad
-case sets t:=inner_noad, and the (inner_noad,ord_noad) cases swap places.
-
-98. New \mathchoice primitive (Jan 19, 1983)
-a) module 204: new command
-b) 254: math_choice_group
-c) 614: style node three words long, so a choice node can be converted to it
-d) 614a: choice node has four subfields: display_mlist, text_mlits, etc.
-e) 1081a: routines to build a choice_node like 1027-1029 build discretionaries
-
-99. \input moves to syntax from semantics (Jan 19, 1983)
-a) 204, 206: renumber commands
-b) When input is to be expanded, if name_in_progress then insert_relax
-c) 459,464: name_in_pr:=true; begin_name;...end_name; name_in_pr:=false;
-d) 406,461: declare name_in_progress, a global boolean initially false
-
-100. \chardef joins \mathchardef (Jan 19, 1983)
-a) 204: math_only becomes math_given; add new command char_given
-b) 205: new command char_def
-c) 250,251: new primitive char_def
-d) 380: char_given,math_given yield integer after \the
-e) 401: char_given,math_given yield integer in context of integer
-f) 936,943: char_given treated like other_char
-g) 1062,1064: same, if cur_chr<128, else assume math_code(x)=x
-h) 1143,1144: char_def is analogous to math_char_def
-
-101. \unbox becomes \unhbox,\unvbox; also add \unhcopy (Jan 19, 1983)
-Module 1020 changes in the obvious way.
-
-102. \spacefactor, \pagetotal, etc. move to prefixed_command (Jan 20, 1983)
-
-103. \hrule in horizontal mode, \vrule in vertical mode: switch modes (Jan 20)
-
-104. \globaldefs parameter, affects prefixed_command (Jan 20, 1983)
-
-105. After looking at frequency counts, some optimizations made (Jan 21, 1983)
-a) "fast_get_avail" and "fast_store_new_token" introduced to speed up the loops
-in modules 360 and 431.
-b) some procedure call overhead eliminated in begin_token_list, end_token_list,
-back_input, and flush_node_list.
-c) a few if tests changed from "if a and b then" to "if a then if b then".
-
-106. Changes for space efficiency in math constructions (Jan 22, 1983)
-a) In module 1102, mlist_penalties:=(mode>0)
-b) The following code is inserted before "free_node" in module 639 (rebox):
- if (is_char_node(p))and(link(p)=null) then
- begin f:=font(p); v:=char_width(f)(char_info(f)(character(p)));
- if v<>width(b) then link(p):=new_kern(width(b)-v);
- end;
-c) A new module is called just before clean_box exits:
-<Simplify a trivial box>=
-q:=list_ptr(x);
-if is_char_node(q) then
- begin r:=link(q);
- if r<>null then if link(r)=null then if type(r)=kern_node then
- begin free_node(r,small_node_size); link(q):=null;
- end;
- end
-
-107. Oversight in rebox routine (module 639) corrected (Jan 22, 1983)
-if type(b)=vlist_node then b:=hpack(b,natural);
-
-108. Module 217 clobbers eqtb[bad_font_ident] set in change 26q (Jan 22, 1983)
-Decided to fix this by making \nullfont a primitive.
-This means the procedure missing_font can be deleted, and the test for
-undefined font can be removed from the inner loop.
-(This reflects a rather dramatic change from TeX80, where
-a missing font was a fatal "Whoa" error!)
-Note: I thought I could delete module 646, but realized that it still provides
-a useful error message. The dump/undump routines (cf. change 26ee) now
-dump the null_font information too, as its parameters can be changed.
-
-109. End of program now lists all incomplete \ifs (Jan 24, 1983)
-
-110. Alignment preamble setup to allow \halign\lb (Jan 29, 1983)
-The statement "align_state:=-1000000;" is inserted near the beginning
-of module 695 (and the comment about align_state=-999999 is deleted).
-The constant -999999 is changed to -1000000 in modules 700 and 701.
-
-111. Forgot to test is_char_node(r) (Jan 30, 1983)
-in the <Simplify a trivial box> code of change 106c.
-By coincidence, this was caught since somebody used font number 11
-in the second character of a list of length 2!
-
-112. Improved format for stats at end of run (suggested by DRF, Jan 30, 1983)
-Module 1242 changes; nothing subtle.
-
-**** The changes above have been incorporated into version 0.95
- Version 0.96
-
-113. space after one-symbol control sequences NOT to be ignored unless
-the catcode of that symbol is letter or spacer. (Jan 30, 1983)
-The name of module 334 changes slightly; the state is set based
-on cat_code(cur_chr), shortly after label start_cs.
-A new variable cat is introduced and set to cat_code(cur_chr) in modules
-334 and 336.
-
-114. trailing spaces removed on all lines of input (Jan 30, 1983)
-last_nonblank is added to input_ln routine (module 31)
-
-115. mmode+accent gives error but assumes math_accent (Feb 3, 1983)
-This goes into math_ac procedure (module 1075); module 1035 is eliminated.
-
-116. \iftrue and \iffalse (Feb 5, 1983)
-Simple addition of two new conditions.
-
-117. Bad calculation of size for \left and \right (Feb 6, 1983)
-In module 680, the first assignment to delta should be
- delta:=(delta1 div 500)*delimiter_factor.
-
-118. \delimitershortfall (new name) replaces \delimiterlimit. (Feb 12)
-
-119. \abovewithdelims.. to be equivalent to \above (Feb 12)
-Module 1089 revised so that the delimiters are scanned before the dimension.
-
-120. Remove the kludgy math codes introduced in change 88 (Feb 12)
-\fam becomes a normal integer parameter
-and \mathcode stored with min_halfword added
-and \mathcode allowed to be 32768
-and current family is substituted only when it's in range.
-Also the initialization of mathcode for letters now specifies family 1.
-(This implies a dozen or so obvious revisions.)
-
-121. Bug in module 1152: max spacefactor is 32767 (Feb 12)
-also module 1013 gets a restricted range
-
-122. Octal output to be replaced by hexadecimal. (Feb 14)
-
-123. Forgot to include char_given in module 1037, re change 100 (Feb 14)
-
-124. vmode+valign,hmode+halign made legal transitions (Feb 17)
-
-125. \tracingrestores (Feb 18)
-This involves a lot of new, rather tedious code that's interspersed with the
-eqtb definitions (the body of a procedure called show_eqtb).
-
-126. New error message for hmode+hrule in -hmode. (Feb 25)
-head_for_vmode now suggests \leaders in this case. [improves change 103]
-
-127. under/overfull boxes in alignment: Better message. (Feb 27)
-par_begin_line becomes pack_begin_line, and it is set (negative) in
-module 719, read in modules 590 and 601.
-
-128. New \xcr feature. (suggested by Lamport comments, Mar 4)
-align_peek (module 702) ignores it, otherwise it acts like ordinary \cr.
-
-129. In stats, subtract out TeX's own string requirements (Mar 4)
-(cf. change 112)
-init_pool_ptr and init_str_ptr variables added in obvious way
-(declared in module 39, set in module 1240, used in module 1242)
-
-130. \everyhbox and \everyvbox. (Mar 6)
-The modifications are obvious; for example, module 1076 gets the statement
- if every_vbox<>null then begin_token_list(every_vbox,every_vbox_text);
-and a similar pair of statements goes into module 993.
-
-131. Precaution in module 1105 error recovery (March 9, 1983)
-Change the first test to "if (a=null)or danger", in order to
-avoid accessing math_quad when the symbol fonts aren't known to be present.
-
-132. Installed float and unfloat to aid portability (suggested by HWT, 3/7/83)
-
-133. \dispskip becomes \abovedisplayskip and \belowdisplayskip (3/9/83)
-Also \dispaskip becomes \abovedisplayshortskip; \dispbskip similar.
-
-134. \romannumeral separated from \number (suggested by FY, March 10)
-Obvious changes; print_roman_int now accepts negative input but gives
-no output in such cases (the test in module 68 becomes "if n<=0 then return").
-
-135. scan_keyword to ignore leading spaces (Mar 12)
-In module 375, change "else begin" to
-"else if (cur_cmd<>spacer)or(p<>backup_head) then begin".
-
-136. Update to change 112 (Mar 14)
-Module 1242 now uses write and write_ln directly (saves space and time).
-
-137. Another change to page-break cost (suggested by Lamport, March 16)
-Cf. change 83k above; the relevant lines of module 914 now read
- if b<awful_bad then
- if pi<=eject_penalty then c:=pi
- else if b<inf_bad then c:=b+pi+insert_penalties
- else c:=deplorable
- else c:=b;
- if insert_penalties>=10000 then c:=awful_bad;
-and a similar change (but without insert_penalties) occurs in module 887.
-
-**** The changes above have been incorporated into version 0.96 (March 16, 1983)
- Version 0.97
-
-138. \everyjob (suggested by FY, March 18)
-Module 936: main_control inserts every_job as its first action.
-
-139. Improved printout of macro definitions (March 19)
-In module 278, simply treat left_brace like right_brace.
-(This corresponds to the way the manual describes parameter matching.)
-
-140. Omit blanks as non-delimited parameters (March 19)
-In module 360, replace
- else store_new_token(cur_tok);
-by
- else @<Store the current token, but |goto continue| if it is
- a blank space that would become an undelimited parameter@>;
-Then define @<Store the current token...@> to be:
-begin if cur_tok=space_token then
- if info(r)<=end_match_token then
- if info(r)>=match_token then goto continue;
-store_new_token(cur_tok);
-end
-
-141. Minor patch in module 386, catches mu_glue (March 21)
-begin cur_val:=zero_glue; cur_val_level:=glue_val;
-if not is_char_node(tail)and(mode<>0) then
- begin if type(tail)=glue_node then
- begin cur_val:=glue_ptr(tail);
- if subtype(tail)=mu_glue then cur_val_level:=mu_val;
- end;
- end
-else if (mode=vmode)and(tail=head)and(last_page_glue<>max_halfword) then
- cur_val:=last_page_glue;
-end
-
-142. Patch in module 699, \span expands only one level (March 21)
-(See previous change #42.) The "get_x_token" in the code
-while (cur_chr=span_code)and(cur_cmd=tab_mark) do get_x_token;
-should be replaced by:
- begin get_token;
- if cur_cmd>max_command then
- begin expand_calls; get_token;
- end;
- end
-
-143. Single # in \tokens, \message, etc. (March 22)
-(The previous rule was really bad in connection with \uppercase,
-or with \write when #'s had to be given four times!)
-Module 437 should be prefaced with "if macro_def then".
-And get_token should become get_x_token there, if xpand is true.
-
-144. Keyword "to" required in \read. (March 22)
-This will avoid the common error of a missing space before the \cs.
-Also the stream number can be out of range, for terminal input.
-The stream number in a \write can be out of range too, for terminal output.
-Modules 1145 and 1258 and 1280, etc., change in the obvious ways.
-
-145. \ifeven<countnumber> replaced by \ifodd<number> (March 26)
-This makes the language more consistent.
-
-146. Big surprise bug relating to \if\if aabc\fi (March 26)
-(related to change 45; the possibility that cur_if might not be the
-correct one when the conditional is evaluated was discovered today)
-The main change is to add the change_if_limit procedure, and to add
-the variable save_cond_ptr and the code that now depends on it.
-
-147. \if and \ifcat should tolerate primitives (March 28)
-
-148. "absent" becomes "void", a better word (March 28)
-
-149. Module 990: \lastbox to clear the shift_amount (March 28)
-since I don't want to figure out what it means in all cases (\vsplit, etc)
-
-150. print_err("...") takes the place of print_nl("! ...") (DRF, March 29)
-And wake_up_terminal is introduced in module 34, and used in modules
-37, 70, 341, 441, 457, 463, 1210, 1240, 1246.
-
-151. \halign extended to periodic preambles (April 1)
-Modules 688--690: cur_loop introduced, stacked/unstacked
-Module 695: cur_loop initialized
-Module 700: cur_loop set up
-Module 708--709: cur_loop used and advanced
-
-152. \leaders to align by the smallest enclosing box. (April 1)
-Module 549: new local variable left_edge, initialized to cur_h
-Module 557: cur_h:=left_edge+leader_wd*((cur_h-left_edge) div leader_wd)
-Module 559: new local variable top_edge, initialized to cur_v-height(this_box)
-Module 566: analogous to 557
-
-153. hyphenation after whatsits is OK (April 1)
-In module 809, skip past whatsits
-
-154. \par in vertical mode should build_page (April 2)
-vmode+par_end moves from 952 to 1005
-
-155. Clear aux to zero in module 703 (April 2)
-
-156. Digits will switch families (April 4)
-(initialize their math codes differently in module 225)
-
-157. Refinement to correction 83m (April 7)
-the test for not splitting should be
- if ((h<=0)or(h<=delta))and(height(p)+height(r)<=dimen(n)) then
-
-158. (re 128) \xcr renamed to \crcr, at Lamport's request. (April 8)
-
-159. Better error recovery in runaway preamble (April 11)
-Module 319, aligning: set align_state:=-1000000
-
-160. \read to get balanced braces (April 12)
-Module 440 changed to look more like 431.
-Module 443 gives error message if the \read goes off end of file.
-Module 319 removes \outer from forbidden control sequence that is \read.
-
-161. Bug found by Jim Sterken (April 14)
-Module 798 can make q a char_node, so module 794 needs this patch:
- if not is_char_node(q) then
-to be inserted just before "if (type(q)=math_node)..."
-
-162. \uppercase and \lowercase to apply to all characters (April 15)
-module 1196 changes; also I put active_base before single_base in eqtb
-
-**** The changes above have been incorporated into version 0.97 (April 16, 1983)
-**** except the part of 144 about \read-1 was forgotten and put in 0.98 later
- Version 0.98
-
-163. change small_number to 0..65 in module 814 (found by DRF, April 17)
-
-164. improved error recovery in module 1166 (suggested by DRF, April 17)
-after error: repeat get_token; until cur_cmd=right_brace; {flush the patterns}
-
-165. improved \read from terminal (suggested by Todd Allen at Yale, May 1)
-I had forgotten to implement the extended stream numbers in change 144.
-Also, the prompt is now omitted if n<0.
-
-166. \write n writes only to the log file, if n<0. (May 18)
-
-167. Unified syntax for parameters and registers. (May 18)
-a) Command code changes: def_font moved to before prefix;
- register eliminated; set_register renamed register and
- moved (with adv_register...div_register) to before prefix;
- min_internal and max_internal defined.
-b) scan_the renamed scan_something_internal, and it acts on cur_tok.
-c) scan_int, scan_dimen, scan_glue simplified accordingly; instead of
- testing for cur_cmd=the or cur_cmd=register, they now test
- cur_cmd versus min_internal and max_internal.
-d) ins_the is removed.
-e) \minusthe is removed. Consequently "the_toks" needs no parameter.
-
-168. new parameters \hoffset, \voffset (May 18)
-
-169. \everycr (suggested by Spivak, installed May 24)
-
-170. \countdef, \dimendef, etc. (suggested by DRF long ago, installed May 25)
-Straightforward change to internal representation of assign_int and similar
-commands, so that the chr part is now a pointer to the eqtb location.
-
-171. \advance, \multiply, \divide (suggested by FY, installed May 25)
-
-172. \hyphenchar (May 25)
-A new command assign_font_int is introduced, and incorporated into
-scan_something_internal and prefixed_command in the usual way.
-The hyphen_char array entries are initialized in modules 483 and 506,
-allocated in 482, used in modules 809 [is hyphenation to be suppressed?],
-828 [insert the hyphen character], 946 [insert discretionary node
-following hyphen], 1027 [implementation of \-].
-hyphen_char[k] is dumped and undumped in modules 1229 and 1230.
-
-173. \skewchar (May 25)
-Loaded and fetched with the same command code as \hyphenchar.
-Module 659 gets a dozen more lines of program, to compute the skew.
-
-174. \noexpand (May 25)
-This involves: introduction of no_expand and dont_expand command codes;
-frozen_dont_expand as an internal marker; small change to get_next
-when that marker is sensed; change to processing of \if and \ifcat;
-implementation of no_expand in the expand_calls subroutine.
-I also changed the name of expand_calls to "expand".
-
-175. \meaning (May 25)
-This adds one case to the "convert" command.
-print_meaning is a new subroutine, using code that was in show_whatever.
-
-176. "dm" and "vu" are out, ".5\hsize" is in (May 25)
-Straightforward changes to module 416.
-
-177. \texinfo f n becomes \fontdimen n f (May 25)
-
-178. \afterassignment (suggested by ARK, May 27)
-
-179. \chardef\xx=5\xx shouldn't say that \xx is undefined (May 27)
-
-180. \relax to be ignored like spaces in math mode (May 28)
-and in a few other places: <Get next non-blank non-relax non-call token>
-is now used in modules 379, 988, 994, 1062, 1070, 1134, 1179
-(i.e., scan_left_brace, scan_box, scan_math, scan_delimiter, prefixed_command,
-do_assignments, and just after \leaders).
-
-181. improve \mathaccent wrt sub/superscripts (sugg by HWT, May 30)
-
-182. its_all_over: remove dead_cycles>max_dead_cycles (May 30)
-Modules 961 and 962 are combined and simplified.
-
-*** The changes above were installed into version 0.98 on May 31, 1983 ***
- Version 0.99
-
-183. \mark and \insert and \vadjust allowed in restricted hmode (Jun 3)
-also in math; this is a comparatively big change
-[at present, \mark in a display causes TeX to crash with "can't happen"!]
-modules 652 and 679: mark_node,ins_node,adjust_node now permitted
-modules 576 and 578: t becomes a global variable adjust_tail
-modules 802 and 1110: new calling sequence to get the adjustments
-modules 254, 986, 993, 995, 996: adjusted_hbox_group for the new kind of hbox
-modules 698--690: cur_head and cur_tail added to alignment stack
-modules 703, 712, 715: adjustments gathered and appended during \halign
-
-184. \ht, \wd, and \dp (Jun 6)
-
-185. When displaying noads, use ^ and _ instead of ( and [ (Jun 6)
-
-186. A..F in hex constants could be otherchar as well as letter (Jun 6)
-
-187. Remove <scan optional space> from module 417 (Jun 7)
-(it was redundant code)
-
-188. \mkern .5\thinmuskip and \mkern\thinmuskip should be legal (Jun 7)
-
-189. 2.5\space\space\dimen0 should work (Jun 7)
-previously it worked after "plus" or "minus" only!
-
-190. <font identifier> to allow also \font for current font (Jun 7)
-"if cur_cmd=def_font then f:=cur_font else" added to module 507
-
-191. \gdef not to be global when \globaldefs<0 (Jun 7)
-"and (global_defs>=0)" added to module 1139
-
-192. \advance\spaceskip by-\spaceskip should yield zero_glue (Jun 7)
-the procedure trap_zero_glue is culled from module 1147
-
-193. \show should work with any token (Jun 7)
-
-194. \tokens to become 256 registers (Jun 8)
-\toks and \toksdef added in the straightforward way
-(this affects mainly eqtb, scan_something_internal, prefixed_command)
-
-195. allow \indent in math mode (Jun 8)
-also, \valign in math mode to give missing $ error
-modules 1001 and 1043 disappear; 1004 is generalized slightly.
-
-196. remove redundant code (Jun 8)
-In module 1044, there's no need to check cur_group and call off_save.
-Similarly in module 1053.
-
-197. new_write_whatsit shouldn't allow \openout-1, \closeout-1 (Jun 8)
-(simple change to module 1258)
-
-198. \lastbox should give error in math mode (Jun 8)
-(simple change to module 990)
-
-199. \leaders not followed by proper glue should be back_error (Jun 9)
-[I made the change; TRIP should test this error message!]
-
-200. Module 702, correction to beginning of \noalign (Jun 9)
-if mode=-vmode then normal_paragraph;
-
-201. After alphabetic constant, expand the optional space (Jun 10)
-
-202. Set space_factor:=1000 after rule or constructing an accent (Jun 12)
-That's in modules 964 and 1036.
-
-203. blunder in module 783 (caught by Jim Sterken, fixed Jun 14)
-disc_width:=0 needs to be set before testing if s=null
-(A real bug that existed since the beginning! It showed up on page 37
- of the September 1982 TRIP manual; my hand-checking was incomplete...)
-
-204. Change to optional spaces after <dimen> (Jun 14)
-The optional space will now be analogous to that after <number>.
-
-205. Fix conflict between \output and \everydisplay (Jun 14)
-In change 49, I should have inserted every_display before calling build_page.
-
-206. Overflow errors to be consistent with statistics reporting (Jun 17)
-(See change 129.)
-
-207. \tracing switches to be all positive vs nonpositive (Jun 17)
-
-*** The changes above were installed into version 0.99 on June 19, 1983 ***
- Version 0.999
-
-208. \catcode`\%=14 to be done by INITEX (Jun 20)
-
-209. \par in vmode to clear parshape etc. (Jun 21)
-Module 1005, which contains vmode+par_end, now calls normal_paragraph.
-
-210. Improvement to change 39 (Jun 21)
-Module 593, overfull_rule not appended if solely due to hbadness
-
-211. Alignment bug allows glue_set to be less than -1! (Jun 21)
-Modules 723 and 724 need to be patched.
-
-212. Correction to change 134 (found by Debby Clark, Jun 22)
-Module 68: n to be declared integer, not nonnegative_integer.
-
-213. "by" to be optional (suggested by Lamport, Jun 22)
-Module 1158 disappears
-
-214. Module 1235, slight change in format_ident message (Jun 24)
-
-215. New measures needed to thwart trickery (Jun 25)
-Glue set values computed by \span could have been brought into
-TeX's registers via, e.g., \valign and \vsplit; so the
-"kern" idea of module 722 is insufficient and should be abandoned.
-Extra boxes and glue are added; this has additional virtue
-of perfect accuracy in alignment of vertical rules.
-The main change is to introduce a new module after 722, in which s and t
-are updated for spans, and to eliminate the "equivalent kern" code from 719
-(the corresponding glue calculations are now done in the new module).
-
-216. leaders to affect height/width of their boxes (Jun 25)
-Module 583 splits into two parts (one for hpack, one for vpack).
-
-217. \unskip permitted a little more often (Jun 28)
-Module 1018 reports error only if last_page_glue<max_halfword.
-
-218. {\bf A} in math: not to make a box (Jul 1)
-Module 1093 changes as follows: info(saved(0)):=fin_mlist(null) becomes
-p:=fin_mlist(null); info(saved(0)):=p; if <simple case> then <simplify>.
-
-219. "scaled" feature added to \font input.
-
-220. \mathaccent still not working right? (Jul 2)
-Change 181, I forgot to correct delta when box x changed.
-
-221. Remove confusion possible on file of length 1 (found by Lamport)
-Correction suggested by DRF, July 2: introduce bypass_eoln
-
-222. Allow things like ^^b. (July 4)
-This simplifies modules 332 and 335; also affects 48 and 49.
-And (surprise) 58.
-
-223. \escapechar \defaulthyphenchar \defaultskewchar \endlinechar (July 4)
-to make TeX less dependent on the character set
-A lot of error messages are now broken up so that they use print_esc
-
-224. erstat added for file opening/closing (by DRF, July 7)
-That's module 27.
-
-225. \tracingpages output to show total glue too (July 11)
-Added a procedure called print_page_totals, used also by show_activities.
-Broke modules 214 and 896 into two modules each.
-
-226. Guard against insertion into an hbox (July 11)
-A new procedure ensure_vbox is called in modules 917 and 925.
-
-227. <tokenvar>=<tokenvar> allowed (July 11)
-
-228. \errhelp parameter added (July 11)
-
-229. get_preamble_token should look at global_defs (July 11)
-Module 699 is patched.
-
-*** The above changes installed in preliminary version 0.999 on July 12, 1983,
-but I decided later in the day to do a few more things:
-
-230. \string, \noexpand, \meaning to allow \outer (Todd Allen, July 12)
-
-231. \the to be an expandable control sequence (July 12)
-Several things in the language are cleaned up:
-a) \the\tenrm replaced by \fontname\tenrm [\fontname<font>]
-b) when expanding edef, etc., result of \the still expanded only only level
-c) expansion after \def not inhibited, since \noexpand is now present
-d) \the\the disallowed.
-
-232. \unhbox and \unhcopy allowed in math mode if the box is void (July 12)
-Module 1020 is extended to handle this case.
-
-233. Value of default_rule was incorrectly rounded (July 16)
-Module 424: default_rule=26214 {.39999 pt}
-
-234. \mathaccent still not right! (July 16)
-I need to make the final height the max of (height of accented letter w/o
-superscript, height of unaccented letter w superscript).
-
-235. \newlinechar parameter (July 16)
-simple change to print subroutine
-
-236. boxes and rules to be allowed in discretionaries (sugg by HP man, July 16)
-in fact this simply requires omitting of the prohibition (in module 1031)
-and a few more cases equivalent to kern_node in modules 754, 755, 784.
-
-237. \tracingcommands to show all expandable tokens (July 16)
-
-238. \char to be allowed in \hyphenation list (July 16)
-Module 848 changes in the obvious way.
-
-239. \aftergroup (July 16)
-A new save_type.
-
-240. Curtail running dimensions inside alignments (sugg by ARK, July 16)
-Module 720.
-
-241. Strange pattern data could cause PASCAL error (found July 17)
-Put "if hc[1]=127 then hyf[0]:=0;" at beginning of module 878.
-
-242. hc codes for hyphenation are one lower (July 17)
-e.g., hc[...]:=lc_code(...)-1. This makes code 127 impossible to match.
-
-243. whatsits also allowed after hyphenatable words (July 17)
-Module 812.
-
-244. \/ makes an explicit kern (July 17)
-"subtype(tail):=explicit" in module 1023.
-
-*** Version 0.999 installed July 17, 1983.
-But later in the day I decided to do a few more things:
-
-245. Lowercase letters allowed in file names (July 18)
-In module 452, omit the conversion to uppercase.
-
-246. "No output file" becomes "No pages of output." (July 18)
-Module 571.
-
-247. QRS on error leads to confirmation message (sugg by ARK, July 18)
-Module 84.
-
-*** The real version 0.999 finally installed July 18.
- * Version 1.0
-
-(Changes made after the Version 0.999 listing of TeX82)
-(Henceforth the "final" module numbers are used)
-
-248. Module 1215, allow space in \read n to \cs (by FY, July 25, 1983)
-@x patch in get_r_token routine
-begin restart: get_token;
-@y
-begin restart: repeat get_token;
-until cur_tok<>space_token;
-@z
-
-249. Module 498, we must stack the current if type (FY, July 27)
-@x patch in conditional routine
-begin @<Push the condition stack@>;@+save_cond_ptr:=cond_ptr;@/
-@y
-@!this_if:small_number; {type of this conditional}
-begin @<Push the condition stack@>;@+save_cond_ptr:=cond_ptr;this_if:=cur_chr;@/
-@z
-Also replace cur_if by this_if in modules 501, 503, 506. The following
-patches do only what is necessary to make things work:
-@x
- print_cmd_chr(if_test,cur_if);
-@y
- print_cmd_chr(if_test,this_if);
-@z
-@x
-if cur_if=if_int_code then scan_int@+else scan_normal_dimen;
-@y
-if this_if=if_int_code then scan_int@+else scan_normal_dimen;
-@z
-@x
-if cur_if=if_char_code then b:=(n=cur_chr)@+else b:=(m=cur_cmd);
-@y
-if this_if=if_char_code then b:=(n=cur_chr)@+else b:=(m=cur_cmd);
-@z
-
-250. Module 507, \ifx need not put a control sequence in hash table (July 29)
-@x
-get_token; n:=cs_ptr; p:=cur_cmd; q:=cur_chr;
-get_token; if cur_cmd<>p then b:=false
-@y
-get_next; n:=cs_ptr; p:=cur_cmd; q:=cur_chr;
-get_next; if cur_cmd<>p then b:=false
-@z
-
-251. Module 86, message is lost (noticed by HWT, July 31)
-@x
-print("..."); print_ln; return;
-@y
-print("..."); print_ln; update_terminal; return;
-@z
-
-252. Don't put empty at end of \input file! (Aug 1)
-[This simplifies the rules and the program, and also gets around a bug
-that occurred at the end of files with \endlinechar<0.]
-@x Module 362:
-@ An empty line is inserted at the end of the file, if the last line
-wasn't already empty, because |input_ln| sets |last:=first| when
-it discovers an |eof|.
-@^empty line at end of file@>
-
-@<Read next line of file into |buffer|, or
- |goto restart| if the file has ended@>=
-begin incr(line); first:=start;
-if not force_eof then
- begin if input_ln(cur_file,true) then {not end of file}
- firm_up_the_line {this sets |limit|}
- else if limit<>start then firm_up_the_line
- {if |pausing|, the user can add more lines}
- else force_eof:=true;
-@y
-@ @<Read next line of file into |buffer|, or
- |goto restart| if the file has ended@>=
-begin incr(line); first:=start;
-if not force_eof then
- begin if input_ln(cur_file,true) then {not end of file}
- firm_up_the_line {this sets |limit|}
- else force_eof:=true;
-@z
-
-*** The changes above went into Version 0.9999, which was widely distributed
-
-253. Ridiculous blunder made in change 146 (found by FY, August 16)
-@x Correction to module 497
-else loop@+begin q:=cond_ptr;
- if link(q)=p then
- begin type(p):=l; return;
- end;
- if q=null then confusion("if");
-@:this can't happen if}{\quad if@>
- q:=link(q);
-@y
-else begin q:=cond_ptr;
- loop@+ begin if q=null then confusion("if");
-@:this can't happen if}{\quad if@>
- if link(q)=p then
- begin type(q):=l; return;
- end;
- q:=link(q);
- end;
-@z
-
-254. Minor amendment to stat(s) printing (cf. change 129) (August 16)
-@x in module 1334
- wlog_ln(' ',str_ptr-init_str_ptr:1,' strings out of ',
- max_strings-init_str_ptr:1);@/
-@y
- wlog(' ',str_ptr-init_str_ptr:1,' string');
- if str_ptr<>init_str_ptr+1 then wlog('s');
- wlog_ln(' out of ',
-@z
-
-255. Bug in \xleader computations (found by FY, August 18)
-@x in module 592
-@!lq,@!lr:integer; {quantities used in calculations for leaders}
-@y
-@!lq,@!lr,@!lx:integer; {quantities used in calculations for leaders}
-@z
-@x in module 626
- begin edge:=cur_h+rule_wd;
- @<Let |cur_h| be the position of the first box, and set |leader_wd|
- to the spacing between corresponding parts of boxes@>;
- while cur_h+leader_wd<=edge do
- @<Output a leader box at |cur_h|,
- then advance |cur_h| by |leader_wd|@>;
-@y
- begin edge:=cur_h+rule_wd; lx:=0;
- @<Let |cur_h| be the position of the first box, and set |leader_wd+lx|
- to the spacing between corresponding parts of boxes@>;
- while cur_h+leader_wd<=edge do
- @<Output a leader box at |cur_h|,
- then advance |cur_h| by |leader_wd+lx|@>;
-@z
-@x in module 627
- leader_wd:=leader_wd+lx;
-@y
-@z
-@x in module 628
-cur_h:=save_h+leader_wd;
-@y
-cur_h:=save_h+leader_wd+lx;
-@z
-@x in module 635
- begin edge:=cur_v+rule_ht;
- @<Let |cur_v| be the position of the first box, and set |leader_ht|
- to the spacing between corresponding parts of boxes@>;
- while cur_v+leader_ht<=edge do
- @<Output a leader box at |cur_v|,
- then advance |cur_v| by |leader_ht|@>;
-@y
- begin edge:=cur_v+rule_ht; lx:=0;
- @<Let |cur_v| be the position of the first box, and set |leader_ht+lx|
- to the spacing between corresponding parts of boxes@>;
- while cur_v+leader_ht<=edge do
- @<Output a leader box at |cur_v|,
- then advance |cur_v| by |leader_ht+lx|@>;
-@z
-@x in module 636
- leader_ht:=leader_ht+lx;
-@y
-@z
-@x in module 637
-cur_v:=save_v-height(leader_box)+leader_ht;
-@y
-cur_v:=save_v-height(leader_box)+leader_ht+lx;
-@z
-Also insert the following in modules 619 and 629:
-@!lx:scaled; {extra space between leader boxes}
-
-256. \/ should apply to ligatures! (August 20)
-@x in module 1113
-var f:internal_font_number; {the font in the |char_node|}
-begin if is_char_node(tail)and(tail<>head) then
- begin f:=font(tail);
- tail_append(new_kern(char_italic(f)(char_info(f)(character(tail)))));
-@y
-label exit;
-var p:pointer; {|char_node| at the tail of the current list}
-@!f:internal_font_number; {the font in the |char_node|}
-begin if tail<>head then
- begin if is_char_node(tail) then p:=tail
- else if type(tail)=ligature_node then p:=lig_char(tail)
- else return;
- f:=font(p);
- tail_append(new_kern(char_italic(f)(char_info(f)(character(p)))));
-@z
-@x later in that same module
-end;
-@y
-exit: end;
-@z
-
-257. Another debugging hack. (August 27)
-@x module 1339
-15: begin font_in_short_display:=null_font; short_display(n);
- end;
-@y
-15: begin font_in_short_display:=null_font; short_display(n);
- end;
-16: panicking:=not panicking;
-@z
-
-258. Redundant code eliminated (August 27)
-Module 531 needn't set and reset name_in_progress [but it's harmless].
-
-259. Bug: \input shouldn't occur during font size spec (Spivak; fixed August 27)
-@x module 1258
-@ @<Scan the font size specification@>=
-@y
-@ @<Scan the font size specification@>=
-name_in_progress:=true; {this keeps |cur_name| from being changed}
-@z
-@x module 1258
-else s:=-1000
-@y
-else s:=-1000;
-name_in_progress:=false
-@z
-
-260. \ifhbox and \ifvbox introduced. (August 27)
-@x module 487
-@d ifx_code=10 { `\.{\\ifx}' }
-@d if_eof_code=11 { `\.{\\ifeof}' }
-@d if_true_code=12 { `\.{\\iftrue}' }
-@d if_false_code=13 { `\.{\\iffalse}' }
-@d if_case_code=14 { `\.{\\ifcase}' }
-@y
-@d if_hbox_code=10 { `\.{\\ifhbox}' }
-@d if_vbox_code=11 { `\.{\\ifvbox}' }
-@d ifx_code=12 { `\.{\\ifx}' }
-@d if_eof_code=13 { `\.{\\ifeof}' }
-@d if_true_code=14 { `\.{\\iftrue}' }
-@d if_false_code=15 { `\.{\\iffalse}' }
-@d if_case_code=16 { `\.{\\ifcase}' }
-@z
-@x
-primitive("ifx",if_test,ifx_code);
-@y
-primitive("ifhbox",if_test,if_hbox_code);
-@!@:if_hbox_}{\.{\\ifhbox} primitive@>
-primitive("ifvbox",if_test,if_vbox_code);
-@!@:if_vbox_}{\.{\\ifvbox} primitive@>
-primitive("ifx",if_test,ifx_code);
-@z
-@x module 488
- ifx_code:print_esc("ifx");
-@y
- if_hbox_code:print_esc("ifhbox");
- if_vbox_code:print_esc("ifvbox");
- ifx_code:print_esc("ifx");
-@z
-@x module 501
-if_void_code: @<Test if a box is void@>;
-@y
-if_void_code, if_hbox_code, if_vbox_code: @<Test box register status@>;
-@z
-@x module 505
-@ @<Test if a box is void@>=
-begin scan_eight_bit_int; b:=(box(cur_val)=null);
-end
-@y
-@ @<Test box register status@>=
-begin scan_eight_bit_int; p:=box(cur_val);
-if this_if=if_void_code then b:=(p=null)
-else if p=null then b:=false
-else if this_if=if_hbox_code then b:=(type(p)=hlist_node)
-else b:=(type(p)=vlist_node);
-end
-
-261. Serious data structure error (found by Todd Allen, August 29)
-@x module 478 (an error introduced in change 231)
- q:=the_toks; link(p):=link(temp_head); p:=q;
-@y
- q:=the_toks;
- if link(temp_head)<>null then
- begin link(p):=link(temp_head); p:=q;
- end;
-@z
-
-262. Minor patch for efficiency (August 29)
-@x module 466
- begin store_new_token(info(r)); r:=link(r);
-@y
- begin fast_store_new_token(info(r)); r:=link(r);
-@z
-
-263. Minor patch to error message (August 29)
-@module 579
- print(" has "); print_int(font_params[f]);
- print(" fontdimen parameters");
-@.Font x has n fontdimen...@>
-@y
- print(" has only "); print_int(font_params[f]);
- print(" fontdimen parameters");
-@.Font x has only...@>
-@z
-
-*** The changes above comprise version 0.99999, used only at SAIL (August 29)
-
-264. funny blank spaces are showable (August 30)
-@x module 298
-spacer: print("blank space");
-@y
-spacer: chr_cmd("blank space ");
-@z
-
-265. \newlinechar [change 235] should affect print_char too (August 31)
-@x module 58
-procedure print_char(@!c:ascii_code); {prints a single character}
-begin case selector of
-term_and_log: begin wterm(xchr[c]); write(log_file,xchr[c]);
- incr(term_offset); incr(file_offset);
- if term_offset=max_print_line then
- begin wterm_cr; term_offset:=0;
- end;
- if file_offset=max_print_line then
- begin wlog_cr; file_offset:=0;
- end;
- end;
-log_only: begin write(log_file,xchr[c]); incr(file_offset);
- if file_offset=max_print_line then print_ln;
- end;
-term_only: begin wterm(xchr[c]); incr(term_offset);
- if term_offset=max_print_line then print_ln;
- end;
-no_print: do_nothing;
-pseudo: if tally<trick_count then trick_buf[tally mod error_line]:=c;
-new_string: begin if pool_ptr<pool_size then append_char(c);
- end; {drop characters if the string space is full}
-othercases write(write_file[selector],xchr[c])
-endcases;@/
-incr(tally);
-end;
-@y
-procedure print_char(@!s:ascii_code); {prints a single character}
-label exit;
-begin if @<Character |s| is the current new-line character@> then
- if selector<pseudo then
- begin print_ln; return;
- end;
-case selector of
-term_and_log: begin wterm(xchr[s]); wlog(xchr[s]);
- incr(term_offset); incr(file_offset);
- if term_offset=max_print_line then
- begin wterm_cr; term_offset:=0;
- end;
- if file_offset=max_print_line then
- begin wlog_cr; file_offset:=0;
- end;
- end;
-log_only: begin wlog(xchr[s]); incr(file_offset);
- if file_offset=max_print_line then print_ln;
- end;
-term_only: begin wterm(xchr[s]); incr(term_offset);
- if term_offset=max_print_line then print_ln;
- end;
-no_print: do_nothing;
-pseudo: if tally<trick_count then trick_buf[tally mod error_line]:=s;
-new_string: begin if pool_ptr<pool_size then append_char(s);
- end; {drop characters if the string space is full}
-othercases write(write_file[selector],xchr[s])
-endcases;@/
-incr(tally);
-exit:end;
-
-266. \lastkern,\lastpenalty,\unkern,\unpenalty (September 4)
-@x module 208
-@d unskip=25 {nullify glue ( \.{\\unskip} )}
-@y
-@d remove_item=25 {nullify last item ( \.{\\unpenalty},
- \.{\\unkern}, \.{\\unskip} )}
-@z
-@x module 208
-@d last_skip=69 {most recent glue ( \.{\\lastskip} )}
-@y
-@d last_item=69 {most recent item ( \.{\\lastpenalty},
- \.{\\lastkern}, \.{\\lastskip} )}
-@z
-@x module 265
-primitive("lastskip",last_skip,0);@/
-@!@:last_skip_}{\.{\\lastskip} primitive@>
-@y
-@z
-@x module 265
-primitive("the",the,0);
-@!@:the_}{\.{\\the} primitive@>
-primitive("toks",toks_register,0);
-@!@:toks_}{\.{\\toks} primitive@>
-primitive("unskip",unskip,0);@/
-@!@:unskip_}{\.{\\unskip} primitive@>
-@y
-primitive("the",the,0);@/
-@!@:the_}{\.{\\the} primitive@>
-primitive("toks",toks_register,0);@/
-@!@:toks_}{\.{\\toks} primitive@>
-@z
-@x module 266
-last_skip: print_esc("lastskip");
-@y
-@z
-@x module 266
-unskip: print_esc("unskip");
-@y
-@z
-@x module 413
-last_skip: @<Fetch the glue in the current node, if any@>;
-@y
-last_item: @<Fetch an item in the current node, if appropriate@>;
-@z
-@x module 416 [I also changed the comment]
-primitive("dp",set_box_dimen,depth_offset);
-@!@:dp_}{\.{\\dp} primitive@>
-@y
-primitive("dp",set_box_dimen,depth_offset);
-@!@:dp_}{\.{\\dp} primitive@>
-primitive("lastpenalty",last_item,int_val);
-@!@:last_penalty_}{\.{\\lastpenalty} primitive@>
-primitive("lastkern",last_item,dimen_val);
-@!@:last_kern_}{\.{\\lastkern} primitive@>
-primitive("lastskip",last_item,glue_val);
-@!@:last_skip_}{\.{\\lastskip} primitive@>
-@z
-@x module 417
-else print_esc("dp");
-@y
-else print_esc("dp");
-last_item: if chr_code=int_val then print_esc("lastpenalty")
-else if chr_code=dimen_val then print_esc("lastkern")
-else print_esc("lastskip");
-@z
-@x module 424
-@ Here is where \.{\\lastskip} is implemented. The reference count will be
-updated later.
-@:last_skip_}{\.{\\lastskip} primitive@>
-
-@<Fetch the glue in the current node, if any@>=
-begin cur_val:=zero_glue; cur_val_level:=glue_val;
-if not is_char_node(tail)and(mode<>0) then
- begin if type(tail)=glue_node then
- begin cur_val:=glue_ptr(tail);
- if subtype(tail)=mu_glue then cur_val_level:=mu_val;
- end;
- end
-else if (mode=vmode)and(tail=head)and(last_page_glue<>max_halfword) then
- cur_val:=last_page_glue;
-end
-@y
-@ Here is where \.{\\lastpenalty}, \.{\\lastkern}, and \.{\\lastskip} are
-implemented. The reference count for \.{\\lastskip} will be updated later.
-
-@<Fetch an item in the current node...@>=
-begin if cur_chr=glue_val then cur_val:=zero_glue@+else cur_val:=0;
-cur_val_level:=cur_chr;
-if not is_char_node(tail)and(mode<>0) then
- case cur_chr of
- int_val: if type(tail)=penalty_node then cur_val:=penalty(tail);
- dimen_val: if type(tail)=kern_node then cur_val:=width(tail);
- glue_val: if type(tail)=glue_node then
- begin cur_val:=glue_ptr(tail);
- if subtype(tail)=mu_glue then cur_val_level:=mu_val;
- end;
- end {there are no other cases}
-else if (mode=vmode)and(tail=head) then
- case cur_chr of
- int_val: cur_val:=last_penalty;
- dimen_val: cur_val:=last_kern;
- glue_val: if last_glue<>max_halfword then cur_val:=last_glue;
- end; {there are no other cases}
-end
-@z
-@x module 982 [also the comment changes]
-@!last_page_glue:pointer; {used to implement \.{\\lastskip}}
-@y
-@!last_glue:pointer; {used to implement \.{\\lastskip}}
-@!last_penalty:integer; {used to implement \.{\\lastpenalty}}
-@!last_kern:scaled; {used to implement \.{\\lastkern}}
-@z
-@x module 991
-last_page_glue:=max_halfword;
-@y
-last_glue:=max_halfword; last_penalty:=0; last_kern:=0;
-@z
-@x module 994
-@<Update the value of |last_page_glue|@>;
-@y
-@<Update the values of |last_glue|, |last_penalty|, and |last_kern|@>;
-@z
-@x module 996
-@ @<Update the value of |last_page_glue|@>=
-if last_page_glue<>max_halfword then delete_glue_ref(last_page_glue);
-if type(p)=glue_node then
- begin last_page_glue:=glue_ptr(p); add_glue_ref(last_page_glue);
- end
-else last_page_glue:=max_halfword
-@y
-@ @<Update the values of |last_glue|...@>=
-if last_glue<>max_halfword then delete_glue_ref(last_glue);
-last_penalty:=0; last_kern:=0;
-if type(p)=glue_node then
- begin last_glue:=glue_ptr(p); add_glue_ref(last_glue);
- end
-else begin last_glue:=max_halfword;
- if type(p)=penalty_node then last_penalty:=penalty(p)
- else if type(p)=kern_node then last_kern:=width(p);
- end
-@z
-@x module 1017
-if last_page_glue<>max_halfword then delete_glue_ref(last_page_glue);
-@<Start a new current page@>; {this sets |last_page_glue:=max_halfword|}
-@y
-if last_glue<>max_halfword then delete_glue_ref(last_glue);
-@<Start a new current page@>; {this sets |last_glue:=max_halfword|}
-@z
-@x module 1048
-vmode+vmove,hmode+hmove,mmode+hmove,any_mode(last_skip),
-@y
-vmode+vmove,hmode+hmove,mmode+hmove,any_mode(last_item),
-@z
-@x module 1104
-any_mode(unskip): delete_skip;
-@y
-any_mode(remove_item): delete_last;
-@z
-@x module 1105
-procedure delete_skip;
-var p:pointer; {runs through the current list}
-begin if (mode=vmode)and(tail=head) then
- @<Apologize for inability to do \.{\\unskip} now,
- unless the previous node was not glue@>
-else begin if not is_char_node(tail) then if type(tail)=glue_node then
-@y
-procedure delete_last;
-var p:pointer; {runs through the current list}
-begin if (mode=vmode)and(tail=head) then
- @<Apologize for inability to do the operation now,
- unless \.{\\unskip} follows non-glue@>
-else begin if not is_char_node(tail) then if type(tail)=cur_chr then
-@z
-@x module 1106
-@ @<Apologize for inability to do \.{\\unskip}...@>=
-begin if last_page_glue<>max_halfword then
- begin you_cant;
- help2("Sorry...I'm usually unable to take things from the current")@/
- ("page. Try `I\vskip-\lastskip' instead."); error;
-@y
-@ @<Apologize for inability to do the operation...@>=
-begin if (cur_chr<>glue_node)or(last_glue<>max_halfword) then
- begin you_cant;
- help2("Sorry...I'm usually unable to take things from the current")@/
- ("page. Try `I\vskip-\lastskip' instead.");
- if cur_chr=kern_node then help_line[0]:=
- ("page. Try `I\kern-\lastkern' instead.")
- else if cur_chr<>glue_node then help_line[0]:=@|
- ("page. Perhaps you can make the output routine do it.");
- error;
-@z
-@x module 1107
-primitive("unhbox",un_hbox,box_code);@/
-@y
-primitive("unpenalty",remove_item,penalty_node);@/
-@!@:un_penalty_}{\.{\\unpenalty} primitive@>
-primitive("unkern",remove_item,kern_node);@/
-@!@:un_kern_}{\.{\\unkern} primitive@>
-primitive("unskip",remove_item,glue_node);@/
-@!@:un_skip_}{\.{\\unskip} primitive@>
-primitive("unhbox",un_hbox,box_code);@/
-@z
-@x module 1108
-un_hbox: if chr_code=copy_code then print_esc("unhcopy")
-@y
-remove_item: if chr_code=glue_node then print_esc("unskip")
- else if chr_code=kern_node then print_esc("unkern")
- else print_esc("unpenalty");
-un_hbox: if chr_code=copy_code then print_esc("unhcopy")
-@z
-
-*** The above changes installed in version 0.999999 (September 5, 1983)
-
-267. Undo change 29: it was overkill and not needed (Sep 17)
-@x module 1257
-label exit, common_ending;
-var u:pointer; {user's font identifier}
-@!s:scaled; {stated ``at'' size, or negative of scaled magnification}
-@!f:internal_font_number; {runs through existing fonts}
-begin if job_name=0 then open_log_file;
- {avoid confusing \.{texput} with the font name}
-@<If the next token isn't a suitable control sequence, issue a complaint
- and |return|; otherwise set |u:=cs_ptr|, and set |hash_used| to the
- location of a ``frozen'' copy of the new font identifier@>;
-define(u,set_font,null_font); scan_optional_equals; scan_file_name;
-@<Scan the font size specification@>;
-@<If this font has already been loaded, set |f| to the internal
- font number and |goto common_ending|@>;
-f:=read_font_info(u,cur_name,cur_area,s);
-common_ending: equiv(u):=f; geq_define(hash_used,set_font,f);
-font_ident[f]:=hash_used;
-exit:end;
-@y
-label common_ending;
-var u:pointer; {user's font identifier}
-@!s:scaled; {stated ``at'' size, or negative of scaled magnification}
-@!f:internal_font_number; {runs through existing fonts}
-begin if job_name=0 then open_log_file;
- {avoid confusing \.{texput} with the font name}
-get_r_token; u:=cs_ptr;
-define(u,set_font,null_font); scan_optional_equals; scan_file_name;
-@<Scan the font size specification@>;
-@<If this font has already been loaded, set |f| to the internal
- font number and |goto common_ending|@>;
-f:=read_font_info(u,cur_name,cur_area,s);
-common_ending: equiv(u):=f; font_ident[f]:=u;
-end;
-@z
-@x module 1260
-@ We reserve a special control sequence for the font identifier; this one
-cannot be redefined by the user, so it is safe to return it as a value of
-\.{\\the\\font}.
-
-@<If the next token isn't a suitable control sequence...@>=
-get_r_token;
-if cs_ptr<hash_base then
- begin print_err("A font identifier must be a multiletter control sequence");
-@.A font identifier...@>
- help2("You should say, e.g., `\font\ffn=fontfilename'.")@/
- ("(I'm going to ignore the \font command you just gave.)");
- back_error; return;
- end;
-repeat if hash_is_full then overflow("hash size",hash_size);
-@:TeX capacity exceeded hash size}{\quad hash size@>
-decr(hash_used);
-until text(hash_used)=0; {search for an empty location in |hash|}
-u:=cs_ptr; text(hash_used):=text(u); {copy the name}
-@!stat incr(cs_count);@+tats@;@/
-@y
-@z
-Note: Since module 1260 has disappeared, module 1258 has been split into two.
-
-268. Minor change to diagnostic output format (September 18)
-@x module 211 [print_mode]
- 2:print("displayed math");
-@y
- 2:print("display math");
-@z
-
-269. Kerns inserted for accents must be explicit (September 20)
-@x module 1123
-@!p,@!q: pointer; {character and box nodes}
-@y
-@!p,@!q,@!r:pointer; {character, box, and kern nodes}
-@z
-@x module 1125
-link(tail):=new_kern(delta); link(link(tail)):=p;
-link(p):=new_kern(-a-delta); tail:=link(p); p:=q;
-@y
-r:=new_kern(delta); subtype(r):=explicit; link(tail):=r; link(r):=p;
-tail:=new_kern(-a-delta); subtype(tail):=explicit; link(p):=tail; p:=q;
-@z
-
-270. "log" changed to "transcript" in a few output messages (Sep 26)
-@x module 535
-prompt_file_name("log file name",".log");
-@y
-prompt_file_name("transcript file name",".log");
-@z
-@x module 1293
- ("lists on your terminal as well as on the log file.");
-@y
- ("lists on your terminal as well as in the transcript file.");
-@z
-@x module 1335
- print_nl("(see the log file for additional information)");
-@.see the log file...@>
-@y
- print_nl("(see the transcript file for additional information)");
-@.see the transcript file...@>
-@z
-
-271. Uninitialized variable bug (found by Bernd Schulze, 1 Oct 83)
-@x module 944
- begin if trie_op_ptr>=max_quarterword-1 then {overflow}
- begin trie_op_ptr:=max_quarterword;
- new_trie_op:=min_quarterword; return;
-@y we allow one more trie op (OK since trie_op_hash_size is big enough)
- begin if trie_op_ptr=max_quarterword then {overflow}
- begin new_trie_op:=min_quarterword; return;
-@z
-
-272. Spaces at end of lines ignored also in TEX.POOL (by DRF, 14 Oct 83)
-@x module 52
- begin if eoln(pool_file) then bad_pool('! TEX.POOL line too short.');
-@.TEX.POOL line too short@>
- read(pool_file,m); append_char(xord[m]);
-@y
- begin if eoln(pool_file) then m:=' '@+else read(pool_file,m);
- append_char(xord[m]);
-@z
-
-273. |history| updates (by DRF, 14 Oct 83)
-@x module 77
-deletions_allowed:=true; history:=spotless; error_count:=0;
-@y
-deletions_allowed:=true; error_count:=0; {|history| is initialized elsewhere}
-@z
-@x module 1332
-@p begin {@!|start_here|}
-@y
-@p begin {@!|start_here|}
-history:=fatal_error_stop; {in case we quit during initialization}
-@z
-@x ibid.
-main_control; {come to life}
-@y
-history:=spotless; {ready to go!}
-main_control; {come to life}
-@z
-
-274. improved "runaway" messages (suggested by FY, October 18)
-@x module 305 (the introductory comment is changed too)
-@d aligning=4 {|scanner_status| when reading an alignment preamble}
-
-@<Glob...@>=
-@!scanner_status : normal..aligning; {can a subfile end now?}
-@y
-@d aligning=4 {|scanner_status| when reading an alignment preamble}
-@d absorbing=5 {|scanner_status| when reading a balanced text}
-
-@<Glob...@>=
-@!scanner_status : normal..absorbing; {can a subfile end now?}
-@z
-@x module 306 (string space is also now conserved slightly)
- defining: begin print("definition?"); p:=def_ref;
- end;
- matching: begin print("argument?"); p:=temp_head;
- end;
- aligning: begin print("preamble?"); p:=hold_head;
- end;
- end; {there are no other cases}
- print_ln; show_token_list(link(p),null,error_line-10);
-@y
- defining: begin print("definition"); p:=def_ref;
- end;
- matching: begin print("argument"); p:=temp_head;
- end;
- aligning: begin print("preamble"); p:=hold_head;
- end;
- absorbing: begin print("text"); p:=def_ref;
- end;
- end; {there are no other cases}
- print_char("?");print_ln; show_token_list(link(p),null,error_line-10);
-@x module 339 (I also changed the module name)
-end; {there are no other cases}
-@y
-absorbing:begin print("text"); info(p):=right_brace_token+"}";
- end;
-end; {there are no other cases}
-@z
-@x module 473
-begin scanner_status:=defining; warning_index:=cs_ptr;
-def_ref:=get_avail; info(def_ref):=null;
-@y
-begin if macro_def then scanner_status:=defining
-@+else scanner_status:=absorbing;
-warning_index:=cs_ptr; def_ref:=get_avail; info(def_ref):=null;
-@z
-
-275. similar, but this corrects a real bug (found by FY, October 18)
-@x module 1226
- cs_ptr:=q;
- @<Get the next non-blank non-relax non-call token@>;
- if cur_cmd<>left_brace then @<If the righthand side is a token parameter
- or token register, finish the assignment and |goto done|@>;
- back_input; q:=scan_toks(false,false);
-@y
- @<Get the next non-blank non-relax non-call token@>;
- if cur_cmd<>left_brace then @<If the righthand side is a token parameter
- or token register, finish the assignment and |goto done|@>;
- back_input; cs_ptr:=q; q:=scan_toks(false,false);
-@z
-
-276. Change #119 should have changed module 1090 too (by Barry Smith, Oct 24)
-@x module 1183 [which was module 1090 at the time of change 119]
-begin if c mod delimited_code=above_code then scan_normal_dimen;
-if c>=delimited_code then
- begin scan_delimiter(garbage,false); scan_delimiter(garbage,false);
- end;
-@y
-begin if c>=delimited_code then
- begin scan_delimiter(garbage,false); scan_delimiter(garbage,false);
- end;
-if c mod delimited_code=above_code then scan_normal_dimen;
-@z
-
-277. Changes for efficiency, based on empirical frequency data (Nov 9)
-@x module 45 [since the result is true almost always]
-begin j:=str_start[s]; result:=false;
-while j<str_start[s+1] do
- begin if str_pool[j]<>buffer[k] then goto not_found;
-@y
-begin j:=str_start[s];
-while j<str_start[s+1] do
- begin if str_pool[j]<>buffer[k] then
- begin result:=false; goto not_found;
- end;
-@z
-@x module 380 [many compilers don't handle "while true do" very well]
-label done;
-begin loop begin get_next;
-@^inner loop@>
- if cur_cmd<=max_command then goto done;
- if cur_cmd>=call then
- if cur_cmd<end_template then macro_call
- else begin cs_ptr:=frozen_endv; cur_cmd:=endv;
- goto done; {|cur_chr=null_list|}
- end
- else expand;
- end;
-@y
-label restart,done;
-begin restart: get_next;
-@^inner loop@>
-if cur_cmd<=max_command then goto done;
-if cur_cmd>=call then
- if cur_cmd<end_template then macro_call
- else begin cs_ptr:=frozen_endv; cur_cmd:=endv;
- goto done; {|cur_chr=null_list|}
- end
-else expand;
-goto restart;
-@z
-@x module 829 [preparation for change to module 852]
-label exit,done,continue,deactivate;
-@y
-label exit,done,done1,continue,deactivate;
-@z
-@x module 830 [ditto]
-@!save_link:pointer; {temporarily holds value of |link(cur_p)|}
-@y
-@!save_link:pointer; {temporarily holds value of |link(cur_p)|}
-@!shortfall:scaled; {used in badness calculations}
-@z
-@x modue 851 [ditto]
-if cur_active_width[1]<line_width then
-@y
-shortfall:=line_width-cur_active_width[1]; {we're this much too short}
-if shortfall>0 then
-@z
-@x module 852 [avoid calling |badness| in most common case]
-else begin b:=badness(line_width-cur_active_width[1],cur_active_width[2]);
-@y
-else begin if shortfall>7230584 then if cur_active_width[2]<1663497 then
- begin b:=inf_bad; fit_class:=very_loose_fit; goto done1;
- end;
- b:=badness(shortfall,cur_active_width[2]);
-@z
-@x module 852, continued
- else fit_class:=decent_fit;
-@y
- else fit_class:=decent_fit;
- done1:
-@z
-@x module 853 [using |shortfall|, since we now have it]
-begin if cur_active_width[1]-line_width>cur_active_width[6] then
- b:=inf_bad+1
-else b:=badness(cur_active_width[1]-line_width,cur_active_width[6]);
-@y
-begin if -shortfall>cur_active_width[6] then b:=inf_bad+1
-else b:=badness(-shortfall,cur_active_width[6]);
-@z
-
-278. Forgotten |error| call (noticed by Gabi Kuper, December 3, 1983)
-@x module 500
- help1("I'm ignoring this; it doesn't match any \if.");
-@y
- help1("I'm ignoring this; it doesn't match any \if.");
- error;
-@z
-
-*** Version 1.0 released on December 3, 1983 incorporates all of the above.
- Version 1.1
-
-279. Problem with change 267 (found by Mike Urban, received 2 Feb 84)
-(I had overlooked many problems, e.g. `{\font\a=x \global\a}\the\font'
-and `\font\a=x \font\b=x \let\b=\undefined \the\a', etc.
-The remedy involves removal of the font_ident array, so there's a
-sprinkling of corrections in lots of modules. But basically the change
-is quite conservative, so it shouldn't spawn any new bugs (it says here).)
-
-@x module 174 (removing a reference to |font_ident|)
- else sprint_cs(font_ident[font(p)]);
-@y
- else @<Print the font identifier for |font(p)|@>;
-@z
-@x module 176 (removing a reference to |font_ident|)
- else sprint_cs(font_ident[font(p)]);
-@y
- else @<Print the font identifier for |font(p)|@>;
-@z
-@x module 222 (redefining and expanding the `frozen' area)
-@d frozen_null_font=frozen_control_sequence+9 {permanent `\.{\\nullfont}'}
-@d frozen_dont_expand=frozen_control_sequence+10
- {permanent `\.{\\notexpanded:}'}
-@d undefined_control_sequence=frozen_control_sequence+11 {dummy location}
-@y
-@d frozen_dont_expand=frozen_control_sequence+9
- {permanent `\.{\\notexpanded:}'}
-@d frozen_null_font=frozen_control_sequence+10
- {permanent `\.{\\nullfont}'}
-@d font_id_base=frozen_null_font-font_base
- {begins table of 257 permanent font identifiers}
-@d undefined_control_sequence=frozen_null_font+257 {dummy location}
-@z
-@x module 234 (removing a reference to |font_ident|, awkwardly)
-print_char("="); sprint_cs(font_ident[equiv(n)]);
-@y
-print_char("=");@/
-print_esc(hash[font_id_base+equiv(n)].rh);
- {that's |text(font_id_base+equiv(n))|}
-@z
-@x module 256 (adding a new macro, font_id_text)
-@d hash_is_full == (hash_used=hash_base) {test if all positions are occupied}
-@y
-@d hash_is_full == (hash_used=hash_base) {test if all positions are occupied}
-@d font_id_text(#) == text(font_id_base+#) {a frozen font identifier's name}
-@z
-@x module 262 (relaxing a former restriction)
-else if (text(p)<128)or(text(p)>=str_ptr) then print_esc("NONEXISTENT.")
-@y
-else if (text(p)<0)or(text(p)>=str_ptr) then print_esc("NONEXISTENT.")
-@z
-@x module 267 (pick up the changes from 174 and 176)
-@!@^Single-character primitives@>
-@y
-@!@^Single-character primitives@>
-
-Meanwhile, this is a convenient place to catch up on something we were unable
-to do before the hash table was defined:
-
-@<Print the font identifier for |font(p)|@>=
-print_esc(font_id_text(font(p)))
-@z
-@x module 415 (removing another reference to font_ident)
- scanned_result(font_ident[cur_val])(ident_val);
-@y
- scanned_result(font_id_base+cur_val)(ident_val);
-@z
-@x module 548 (change to the comment only)
-to the user's font~\.{\\f}. For example, if this internal number is 13,
-we will have |font_ident[13]=p| and |equiv(p)=13|, where |p| is the |eqtb|
-location of the control sequence~\.{\\f}.
-@y
-to the user's font~\.{\\f}. Adding this number to |font_id_base| gives the
-|eqtb| location of a ``frozen'' control sequence that will always select
-the font.
-@z
-@x module 549 (deleting the declaration of font_ident)
-@!font_ident:array[internal_font_number] of pointer; {the most recent user
- font identifier corresponding to an internal font number}
-@y
-@z
-@x module 552 (deleting an unnecessary initialization of font_ident)
-font_ident[null_font]:=frozen_null_font;
-@y
-@z
-@x module 579 (removing another reference to font_ident)
- begin print_err("Font "); sprint_cs(font_ident[f]);
-@y
- begin print_err("Font "); print_esc(font_id_text(f));
-@z
-@x module 1257 (this is the real change!)
-begin if job_name=0 then open_log_file;
- {avoid confusing \.{texput} with the font name}
-get_r_token; u:=cs_ptr;
-define(u,set_font,null_font); scan_optional_equals; scan_file_name;
-@<Scan the font size specification@>;
-@<If this font has already been loaded, set |f| to the internal
- font number and |goto common_ending|@>;
-f:=read_font_info(u,cur_name,cur_area,s);
-common_ending: equiv(u):=f; font_ident[f]:=u;
-@y
-@!t:str_number; {name for the frozen font identifier}
-@!old_setting:0..max_selector; {holds |selector| setting}
-begin if job_name=0 then open_log_file;
- {avoid confusing \.{texput} with the font name}
-get_r_token; u:=cs_ptr;
-if u>=hash_base then t:=text(u)
-else if u>=single_base then
- if u=null_cs then t:="FONT"@+else t:=u-single_base
-else begin old_setting:=selector; selector:=new_string;
- print("FONT"); print(u-active_base); selector:=old_setting;
-@.FONTx@>
- str_room(1); t:=make_string;
- end;
-define(u,set_font,null_font); scan_optional_equals; scan_file_name;
-@<Scan the font size specification@>;
-@<If this font has already been loaded, set |f| to the internal
- font number and |goto common_ending|@>;
-f:=read_font_info(u,cur_name,cur_area,s);
-common_ending: equiv(u):=f; eqtb[font_id_base+f]:=eqtb[u]; font_id_text(f):=t;
-@z
-@x module 1260 (change to the comment only)
-the new value becomes the |font_ident| of record. Font names `\.{xyz}' and
-@y
-the new name becomes the font identifier of record. Font names `\.{xyz}' and
-@z
-@x module 1322 (no need to dump font_ident)
-begin dump_int(font_ident[k]);
-dump_qqqq(font_check[k]);
-@y
-begin dump_qqqq(font_check[k]);
-@z
-@x module 1322 (or to print from it)
-print_nl("\font"); sprint_cs(font_ident[k]); print_char("=");
-@y
-print_nl("\font"); print_esc(font_id_text(k)); print_char("=");
-@z
-@x module 1323 (or to undump it)
-begin undump(active_base)(undefined_control_sequence)(font_ident[k]);
-undump_qqqq(font_check[k]);@/
-@y
-begin undump_qqqq(font_check[k]);@/
-@z
-
-280. Double interrupt possibility (found by Clint Cuzzo, received 9 Feb 84)
-@x module 1031
-if interrupt>0 then if OK_to_interrupt then
- begin back_input; pause_for_instructions; goto big_switch;
-@y
-if interrupt<>0 then if OK_to_interrupt then
- begin back_input; check_interrupt; goto big_switch;
-@z
-
-281. Improve spacing in $(A,<)$. (12 Feb 84)
-@x module 764
-"0234000122*4000133**3**344*0400400*000000234000111*4111112341011"
-@y
-"0234000122*4000133**3**344*0400400*000000234000111*1111112341011"
-@z
-
-282. Bad goto! (diagnosis by Clint Cuzzo and George O'Connor, recd 13 Feb 84)
-@x module 344 (here we simply change the name of module 346)
-any_state_plus(invalid_char): @<Decry the invalid character and
- |goto switch|@>;
-@y
-any_state_plus(invalid_char): @<Decry the invalid character and
- |goto restart|@>;
-@z
-@x module 346 (because clear_for_error_prompt might make state=token_list)
-goto switch;
-@y
-goto restart;
-@z
-
-283. String pool economy (suggested by DRF, 13 Feb 84)
-@x module 537
-@<Read the first line of the new file@>;
-@y
-if name=str_ptr-1 then {we can conserve string pool space now}
- begin flush_string; name:=cur_name;
- end;
-@<Read the first line of the new file@>;
-@z
-
-284. Nicer scaled output (suggested by METAFONT development, 26 Feb 84)
-@x module 103
-be reproduced exactly. [{\sl Proof:\/} If round$(x)=\lfloor
-x+{1\over2}\rfloor$ and if $\alpha<1$, it is not difficult to verify that
-round$(\alpha\,\hbox{round}( \alpha^{-1}n))=n$ for all integers |n|. In
-our case $\alpha=2^{16}/10^5$.]
-
-@p procedure print_scaled(@!s:scaled); {prints scaled real, rounded to five
- digits}
-begin if s<0 then
- begin print_char("-"); negate(s); {print the sign, if negative}
- end;
-print_int(s div unity); {print the integer part}
-s:=((s mod unity) * 3125 + 1024) div 2048;
- {now |0<=s<100000| is the fraction part}
-print_char(".");
-repeat print_char("0"+(s div 10000)); s:=10*(s mod 10000);
-until s=0;
-end;
-@y
-be reproduced exactly; the ``simplest'' such decimal number is output,
-but there is always at least one digit following the decimal point.
-
-The invariant relation in the \&{repeat} loop is that a sequence of
-decimal digits yet to be printed will yield the original number if and only if
-they form a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$.
-We can stop if and only if $f=0$ satisfies this condition; the loop will
-terminate before $s$ can possibly become zero.
-
-@p procedure print_scaled(@!s:scaled); {prints scaled real, rounded to five
- digits}
-var delta:scaled; {amount of allowable inaccuracy}
-begin if s<0 then
- begin print_char("-"); negate(s); {print the sign, if negative}
- end;
-print_int(s div unity); {print the integer part}
-print_char(".");
-s:=10*(s mod unity)+5; delta:=10;
-repeat if delta>unity then s:=s+@'100000-(delta div 2); {round the last digit}
-print_char("0"+(s div unity)); s:=10*(s mod unity); delta:=delta*10;
-until s<=delta;
-end;
-@z
-
-*** Those six changes account for version 1.1 (February 29, 1984).
-*** And we put the following change in too, at the last minute:
-
-285. ".00000762939453126pt" didn't round correctly! (March 2, 1984)
-@x module 452
- if k<16 then {digits for |k>=16| cannot affect the result}
-@y (Note, I also changed the comment in module 102: 16 -> 17)
- if k<17 then {digits for |k>=17| cannot affect the result}
-@z
-
-*** Note: I changed "cs_ptr" to "cur_cs", since the name change is more
-indicative of the fact that this variable makes a trio with cur_cmd
-and cur_chr. The TEX.WEB source changed 78 times, as a result, but
-none of the author's change files were affected.
-(But note: "save_cs_ptr" was not changed to "save_cur_cs", because
-of a name conflict.)
-
-*** And the following two were slipped in at the last second:
-
-286. loophole permitted get_next recursion (March 16, 1984)
-@x module 336
- begin @<Back up an outer control sequence so that it can be reread@>;
-@y
- begin deletions_allowed:=false;
- @<Back up an outer control sequence so that it can be reread@>;
-@z
-@x ibid
- end;
-@y
- deletions_allowed:=true;
- end;
-@z [the changes to deletions_allowed in module 338 can now be removed]
-
-287. terminal not open when the program starts bad (March 24, 1984)
-@x module 1332
-initialize; {set global variables to their starting values}
-@<Check the ``constant'' values...@>@;
-if bad>0 then
- begin wake_up_terminal;
- wterm('Ouch---my internal constants have been',
- ' clobbered!---case ',bad:1);
-@.Ouch...clobbered@>
- goto final_end;
- end;
-@y
-@<Check the ``constant'' values...@>@;
-if bad>0 then
- begin t_open_out;
- wterm('Ouch---my internal constants have been',
- ' clobbered!---case ',bad:1);
-@.Ouch...clobbered@>
- goto final_end;
- end;
-initialize; {set global variables to their starting values}
-@z
-
-*** Note: "Cosmetic" changes were also made in module 363 ("print_ln"
-moved to after "wake_up_terminal") and in some commentary.
-
-*** Another last-minute correction:
-288. \patterns{xxx...xxxdxxxdxxx} anomaly found by JRD (Mar 27, 1984)
-@x module 962
-else begin hyf[k]:=cur_chr-"0"; digit_sensed:=true;
-@y
-else begin hyf[k]:=cur_chr-"0";
- if k<63 then digit_sensed:=true;
-@z
-
-*** Yoicks, yet ANOTHER:
-289. a whole case of copy_node_list forgotten (Apr 11, 1984)
-@x module 206
-othercases confusion("copying")
-@y
-adjust_node: begin r:=get_node(small_node_size);
- adjust_ptr(r):=copy_node_list(adjust_ptr(p));
- end; {|words=1=small_node_size-1|}
-othercases confusion("copying")
-@z
-
-*** And "finally"...
-290. uninitialized variables could be accessed (found by Nick Briggs, June 11)
-@x module 552
-font_size[null_font]:=0; font_dsize[null_font]:=0;
-@y
-font_size[null_font]:=0; font_dsize[null_font]:=0;
-char_base[null_font]:=0; width_base[null_font]:=0;
-height_base[null_font]:=0; depth_base[null_font]:=0;
-italic_base[null_font]:=0; lig_kern_base[null_font]:=0;
-kern_base[null_font]:=0; exten_base[null_font]:=0;
-@z (actual values are immaterial except for debugging safeguards)
-
-291. same, cf. modules 355 and 389 (Nick Briggs, June 11)
-@x module 331
-scanner_status:=normal; first:=1;
-@y
-for first:=0 to buf_size do buffer[first]:=0;
-scanner_status:=normal; warning_index:=null; first:=1;
-@z (error was harmless except that it might trigger debugging checks)
-
-292. missing ligature/kern (found by JRD, June 21)
-@x module 1036
- if (cur_cmd=letter)or(cur_cmd=other_char) then r:=qi(cur_chr)
-@y
- if (cur_cmd=letter)or(cur_cmd=other_char)or(cur_cmd=char_given) then
- r:=qi(cur_chr)
-@z
-
-293. quarterword constraint is made explicit (July 4)
-@x module 111
-if (buf_size>max_halfword) then bad:=18;
-@y
-if buf_size>max_halfword then bad:=18;
-if max_quarterword-min_quarterword<255 then bad:=19;
-@z
-
-294. trivial optimization made for consistency with MF (July 7)
-@x module 363
-if (pausing>0)and(interaction>nonstop_mode) then
-@y
-if pausing>0 then if interaction>nonstop_mode then
-@z
-
-295. \tracingmacros>1 for more diagnostics (July 8)
-@x module 323
- if t=macro then param_start:=param_ptr@+else loc:=link(p);
-@y
- if t=macro then param_start:=param_ptr
- else begin loc:=link(p);
- if tracing_macros>1 then
- begin begin_diagnostic; print_nl("");
- case t of
- mark_text:print_esc("mark");
- write_text:print_esc("write");
- othercases print_cmd_chr(assign_toks,t-output_text+output_routine_loc)
- endcases;@/
- print("->"); token_show(p); end_diagnostic(false);
- end;
- end;
-@z
-
-*** The changes above were incorporated in Version 1.1, released July 9, 1984.
- Version 1.2
-
-296. "see the transcript file" on offline show commands. (July 27, 1984)
-@x module 1293
-@ @d show_error==@;@/
- if interaction<error_stop_mode then
- begin help0; decr(error_count);
- end
- else if tracing_online>0 then
- begin@t@>@;@/
- help3("This isn't an error message; I'm just \showing something.")
- @t\4\4@>@/
- ("Type `I\show...' to show more (e.g., \show\cs,")@/
- ("\showthe\count10, \showbox255, \showlists).");
- end
- else begin@t@>@;@/
- help5("This isn't an error message; I'm just \showing something.")
- @t\4\4@>@/
- ("Type `I\show...' to show more (e.g., \show\cs,")@/
- ("\showthe\count10, \showbox255, \showlists).")@/
- ("And type `I\tracingonline=1\show...' to show boxes and")@/
- ("lists on your terminal as well as in the transcript file.");
- end;
- error
-
-@<Declare act...@>=
-procedure show_whatever;
-var p:pointer; {tail of a token list to show}
-begin case cur_chr of
-show_code: @<Show the current meaning of a token@>;
-show_box_code: @<Show the current contents of a box@>;
-show_the_code: @<Show the current value of some parameter or register@>;
-othercases @<Show the current semantic nest@>
-endcases;
-end;
-@y
-@ @<Declare act...@>=
-procedure show_whatever;
-label common_ending;
-var p:pointer; {tail of a token list to show}
-begin case cur_chr of
-show_lists: begin begin_diagnostic; show_activities;
- end;
-show_box_code: @<Show the current contents of a box@>;
-show_code: @<Show the current meaning of a token, then |goto common_ending|@>;
-othercases @<Show the current value of some parameter or register,
- then |goto common_ending|@>
-endcases;@/
-@<Complete a potentially long \.{\\show} command@>;
-common_ending: if interaction<error_stop_mode then
- begin help0; decr(error_count);
- end
-else if tracing_online>0 then
- begin@t@>@;@/
- help3("This isn't an error message; I'm just \showing something.")@/
- ("Type `I\show...' to show more (e.g., \show\cs,")@/
- ("\showthe\count10, \showbox255, \showlists).");
- end
-else begin@t@>@;@/
- help5("This isn't an error message; I'm just \showing something.")
- ("Type `I\show...' to show more (e.g., \show\cs,")@/
- ("\showthe\count10, \showbox255, \showlists).")@/
- ("And type `I\tracingonline=1\show...' to show boxes and")@/
- ("lists on your terminal as well as in the transcript file.");
- end;
-error;
-end;
-@z
-@x module 1294
-@ @<Show the current meaning of a token@>=
-begin get_token; print_nl("> ");
-if cur_cs<>0 then
- begin sprint_cs(cur_cs); print_char("=");
- end;
-print_meaning; show_error;
-@y
-@ @<Show the current meaning of a token...@>=
-begin get_token; print_nl("> ");
-if cur_cs<>0 then
- begin sprint_cs(cur_cs); print_char("=");
- end;
-print_meaning; goto common_ending;
-@z
-@x module 1296
-end_diagnostic(true);
-print_err("OK");
-@.OK@>
-show_error;
-@y
-@z
-@x module 1297
-flush_list(link(temp_head)); show_error;
-@y
-flush_list(link(temp_head)); goto common_ending;
-@z
-@x module 1298
-@ @<Show the current semantic nest@>=
-begin begin_diagnostic; show_activities; end_diagnostic(true);
-print_err("OK");
-show_error;
-@.OK@>
-end
-@y
-@ @<Complete a potentially long \.{\\show} command@>=
-end_diagnostic(true); print_err("OK");
-@.OK@>
-if selector=term_and_log then if tracing_online<=0 then
- begin selector:=term_only; print(" (see the transcript file)");
- selector:=term_and_log;
- end
-@z
-
-297. allow `0' in response to error prompts (October 20, 1984)
-@x module 84
-"1","2","3","4","5","6","7","8","9": if deletions_allowed then
-@y
-"0","1","2","3","4","5","6","7","8","9": if deletions_allowed then
-@z
- Versions 1.3 and 1.4
-
-298. Dirty PASCAL (two quarterword 0's were read as a halfword) (25 Nov 84)
-@x module 846
-print(" -> @@@@"); print_int(serial(prev_break(passive)));
-@y
-print(" -> @@@@");
-if prev_break(passive)=null then print_char("0")
-else print_int(serial(prev_break(passive)));
-@z
-
-299. Ditto! (25 Nov 84)
-@x module 934
-label reswitch, exit, found, not_found;
-@y
-label reswitch, exit, found, not_found, done;
-@z
-@x module 939
-while info(p)>n-3 do {eliminate hyphens \TeX\ doesn't like}
- begin q:=link(p); free_avail(p); p:=q;
- end;
-@<Insert the \(p)pair |(s,p)| into the exception table@>;
-@y
-loop@+ begin if p=null then goto done;
- if info(p)<n-2 then goto done;
- q:=link(p); free_avail(p); p:=q; {eliminate hyphens that \TeX\ doesn't like}
- end;
-done: @<Insert the \(p)pair |(s,p)| into the exception table@>;
-@z
-
-300. Major change to memory management (25 Nov 84)
-[The following changes have two main merits: (1) TeX should run faster on
-virtual-memory systems when the jobs are small; (2) it should be possible
-to use the same production version of TeX both for jobs with lots of macros
-and few boxes as well as for jobs with lots of boxes and few macros, because
-the boundary line between the two types of storage is now chosen dynamically.]
-[The user is unaffected, except that there's only one "memory size" overflow
-error now instead of two.]
-[The TRIP test is now changed slightly: The correct settings of memory
-size parameters are now mem_min=mem_bot=1, mem_top=mem_max=3000.]
-
-@x module 11
-@!mem_max=30000; {greatest index in \TeX's internal |mem| array;
- must be strictly less than |max_halfword|}
-@y
-@!mem_max=30000; {greatest index in \TeX's internal |mem| array;
- must be strictly less than |max_halfword|;
- must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|}
-@!mem_min=0; {smallest index in \TeX's internal |mem| array;
- must be |min_halfword| or more;
- must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|}
-@z
-@x module 12
-@d mem_base=0 {smallest index in the |mem| array; must not be less
- than |min_halfword|}
-@d hi_mem_base=13000 {smallest index in the single-word area of |mem|;
- must be substantially larger than |mem_base| and smaller than |mem_max|}
-@y
-@d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX};
- must not be less than |mem_min|}
-@d mem_top==30000 {largest index in the |mem| array dumped by \.{INITEX};
- must be substantially larger than |mem_bot|
- and not greater than |mem_max|}
-@z
-@x module 12
- about |(mem_max-hi_mem_base)/6|, but 2100 is already quite generous}
-@y
- about |(mem_max-mem_min)/10|, but 2100 is already quite generous}
-@z
-@x module 14
-if (hi_mem_base<mem_base+100)or(hi_mem_base+100>mem_max) then bad:=4;
-@y
-if mem_bot+1100>mem_top then bad:=4;
-@z
-@x module 111
-if (min_quarterword>0)or(max_quarterword<127) then bad:=11;
-@y
-init if (mem_min<>mem_bot)or(mem_max<>mem_top) then bad:=10;@+tini@;@/
-if (mem_min>mem_bot)or(mem_max<mem_top) then bad:=10;
-if (min_quarterword>0)or(max_quarterword<127) then bad:=11;
-@z
-@x module 111
-if (mem_base<min_halfword)or(mem_max>=max_halfword) then bad:=14;
-@y
-if (mem_min<min_halfword)or(mem_max>=max_halfword) then bad:=14;
-@z
-@x module 115
-value represents a null pointer.
-
-@d pointer==halfword {a flag or a location in |mem| or |eqtb|}
-@d null==mem_base {the null pointer}
-@y
-value represents a null pointer. \TeX\ does not assume that |mem[null]| exists.
-
-@d pointer==halfword {a flag or a location in |mem| or |eqtb|}
-@d null==min_halfword {the null pointer}
-@z
-@x module 116
-@ The |mem| array is divided once and for all into two regions that are
-allocated separately. Locations less than |hi_mem_base| are used for storing
-@y
-@ The |mem| array is divided into two regions that are allocated separately,
-but the dividing line between these two regions is not fixed; they grow
-together until finding their ``natural'' size in a particular job.
-Locations less than or equal to |lo_mem_max| are used for storing
-@z
-@x module 116
-relevant size when a node is freed. The remaining region of |mem| is
-allocated in single words using a conventional \.{AVAIL} stack.
-
-Incidentally, it would be feasible to construct implementations of \TeX\ that
-are based on 16-bit words instead of 32-bit words, for machines having
-comparatively small memories. In such cases it might be desirable to have
-two parallel arrays for the upper part of memory, called say \\{mem\_link}|[p]|
-and \\{mem\_info}|[p]|,
-since the single-word region in the present implementation
-consists entirely of |memory_word| items of type |two_halves|.
-@^small computers@>
-@y
-relevant size when a node is freed. Locations greater than or equal to
-|hi_mem_min| are used for storing one-word records; a conventional
-\.{AVAIL} stack is used for allocation in this region.
-
-Locations of |mem| between |mem_bot| and |mem_top| may be dumped as part
-of preloaded format files, by the \.{INITEX} preprocessor.
-@.INITEX@>
-Production versions of \TeX\ may extend the memory at both ends in order to
-provide more space; locations between |mem_min| and |mem_bot| are always
-used for variable-size nodes, and locations between |mem_top| and |mem_max|
-are always used for single-word nodes.
-
-The key pointers that govern |mem| allocation have a prescribed order:
-$$\hbox{|null<=mem_min<=mem_bot<lo_mem_max<
- hi_mem_min<mem_top<=mem_end<=mem_max|.}$$
-@z
-@x module 116
-@!mem : array[mem_base..mem_max] of memory_word; {the big dynamic storage area}
-@y
-@!mem : array[mem_min..mem_max] of memory_word; {the big dynamic storage area}
-@!lo_mem_max : pointer; {the largest location of variable-size memory in use}
-@!hi_mem_min : pointer; {the smallest location of one-word memory in use}
-@z
-@x module 117
-@!max_var_used : integer; {how much memory was in use}
-@y
-@z
-@x module 118
-occur between |hi_mem_base| and |mem_end|, inclusive, are of type
-@y
-occur between |hi_mem_min| and |mem_end|, inclusive, are of type
-@z
-@x module 120
-else begin runaway; {if memory is exhausted, display possible runaway text}
- overflow("macro memory size",mem_max+1-hi_mem_base);
- {quit; all one-word nodes are busy}
-@:TeX capacity exceeded macro memory size}{\quad macro memory size@>
- end;
-@y
-else begin decr(hi_mem_min); p:=hi_mem_min;
- if hi_mem_min<=lo_mem_max then
- begin runaway; {if memory is exhausted, display possible runaway text}
- overflow("main memory size",mem_max+1-mem_min);
- {quit; all one-word nodes are busy}
-@:TeX capacity exceeded main memory size}{\quad main memory size@>
- end;
- end;
-@z
-@x module 125
-label found,exit;
-@y
-label found,exit,restart;
-@z
-@x module 125
-begin p:=rover; {start at some free node in the ring}
-@y
-begin restart: p:=rover; {start at some free node in the ring}
-@z
-@x module 125
-overflow("box memory size",hi_mem_base-mem_base);
- {sorry, nothing satisfactory is left}
-@:TeX capacity exceeded box memory size}{\quad box memory size@>
-found: link(r):=null; {this node is now nonempty}
-@!stat var_used:=var_used+s; {maintain usage statistics}
-if var_used>max_var_used then max_var_used:=var_used;
-@y
-if lo_mem_max+2<hi_mem_min then
- @<Grow more variable-size memory and |goto restart|@>;
-overflow("main memory size",mem_max+1-mem_min);
- {sorry, nothing satisfactory is left}
-@:TeX capacity exceeded main memory size}{\quad main memory size@>
-found: link(r):=null; {this node is now nonempty}
-@!stat var_used:=var_used+s; {maintain usage statistics}
-@z
-@x modules 126--127
-@ Empirical tests show that the routine in this section performs a
-|remove_node| operation about 0.75 times per allocation, on the average,
-after which it finds that |r>p+1| about 95\% of the time.
-
-@<Try to allocate...@>=
-q:=p+node_size(p); {find the physical successor}
-@^inner loop@>
-while is_empty(q) do @<Merge node |p| with node |q|@>;
-r:=q-s;
-if r>p+1 then @<Allocate from the top of node |p| and |goto found|@>;
-if r=p then if ((rlink(p)<>rover) or (llink(p)<>rover)) then
- @<Allocate entire node |p| and |goto found|@>;
-node_size(p):=q-p {reset the size in case it grew}
-
-@ @<Merge node |p| with node |q|@>=
-begin t:=rlink(q);
-@^inner loop@>
-if q=rover then rover:=t;
-llink(t):=llink(q); rlink(llink(q)):=t;@/
-q:=q+node_size(q);
-end
-@y
-@ The lower part of |mem| grows by 1000 words at a time, unless
-we are very close to going under. When it grows, we simply link
-a new node into the available-space list. This method of controlled
-growth helps to keep the |mem| usage consecutive when \TeX\ is
-implemented on ``virtual memory'' systems.
-@^virtual memory@>
-
-@<Grow more variable-size memory and |goto restart|@>=
-begin if lo_mem_max+1000<hi_mem_min then t:=lo_mem_max+1000
-else t:=(lo_mem_max+hi_mem_min+2) div 2; {|lo_mem_max+2<=t<hi_mem_min|}
-p:=llink(rover); q:=lo_mem_max; rlink(p):=q; llink(rover):=q;@/
-rlink(q):=rover; llink(q):=p; link(q):=empty_flag; node_size(q):=t-lo_mem_max;@/
-lo_mem_max:=t; link(lo_mem_max):=null; info(lo_mem_max):=null;
-rover:=q; goto restart;
-end
-
-@ Empirical tests show that the routine in this section performs a
-node-merging operation about 0.75 times per allocation, on the average,
-after which it finds that |r>p+1| about 95\% of the time.
-
-@<Try to allocate...@>=
-q:=p+node_size(p); {find the physical successor}
-@^inner loop@>
-while is_empty(q) do {merge node |p| with node |q|}
- begin t:=rlink(q);
- if q=rover then rover:=t;
- llink(t):=llink(q); rlink(llink(q)):=t;@/
- q:=q+node_size(q);
- end;
-r:=q-s;
-if r>p+1 then @<Allocate from the top of node |p| and |goto found|@>;
-if r=p then if ((rlink(p)<>rover) or (llink(p)<>rover)) then
- @<Allocate entire node |p| and |goto found|@>;
-node_size(p):=q-p {reset the size in case it grew}
-@z
-% module 129 no longer refers to remove_node; I don't recall when it changed!
-@x module 134
-@d is_char_node(#) == (#>hi_mem_base)
-@y
-@d is_char_node(#) == (#>=hi_mem_min)
-@z
-@x module 162
-example, locations |mem_base| to |mem_base+3| are always used to store the
-specification for glue that is `\.{0pt plus 0pt minus 0pt}'. The
-following macro definitions accomplish the static allocation by giving
-symbolic names to the fixed positions. Dynamic allocation of variable-size
-nodes is restricted to locations |first_mem| through |(hi_mem_base-1)|,
-and single-word nodes are dynamically allocated in locations |second_mem|
-through |mem_max|, inclusive. It is harmless to let |lig_trick|, |garbage|,
-and |backup_head| share the same location of |mem|.
-
-@d zero_glue==mem_base {specification for \.{0pt plus 0pt minus 0pt}}
-@y
-example, locations |mem_bot| to |mem_bot+3| are always used to store the
-specification for glue that is `\.{0pt plus 0pt minus 0pt}'. The
-following macro definitions accomplish the static allocation by giving
-symbolic names to the fixed positions. Static variable-size nodes appear
-in locations |mem_bot| through |lo_mem_stat_max|, and static single-word nodes
-appear in locations |hi_mem_stat_min| through |mem_top|, inclusive. It is
-harmless to let |lig_trick|, |garbage|, and |backup_head| share the same
-location of |mem|.
-
-@d zero_glue==mem_bot {specification for \.{0pt plus 0pt minus 0pt}}
-@z
-@x module 162
-@d first_mem==fil_neg_glue+glue_spec_size {first dynamically allocatable word
- in the variable-size |mem|}
-@#
-@d page_ins_head==hi_mem_base {list of insertion data for current page}
-@d contrib_head==hi_mem_base+1 {vlist of items not yet on current page}
-@d page_head==hi_mem_base+2 {vlist for current page}
-@d temp_head==hi_mem_base+3 {head of a temporary list of some kind}
-@d hold_head==hi_mem_base+4 {head of a temporary list of another kind}
-@d adjust_head==hi_mem_base+5 {head of adjustment list returned by |hpack|}
-@d active==hi_mem_base+6 {head of active list in |line_break|, needs two words}
-@d align_head==hi_mem_base+8 {head of preamble list for alignments}
-@d end_span==hi_mem_base+9 {tail of spanned-width lists}
-@d omit_template==hi_mem_base+10 {a constant token list}
-@d null_list==hi_mem_base+11 {permanently empty list}
-@d lig_trick==hi_mem_base+12 {a ligature masquerading as a |char_node|}
-@d garbage==hi_mem_base+12 {used for scrap information}
-@d backup_head==hi_mem_base+13 {head of token list built by |scan_keyword|}
-@d second_mem==hi_mem_base+14 {first dynamically allocatable word in
- the one-word |mem|}
-@y
-@d lo_mem_stat_max==fil_neg_glue+glue_spec_size-1 {largest statically
- allocated word in the variable-size |mem|}
-@#
-@d page_ins_head==mem_top {list of insertion data for current page}
-@d contrib_head==mem_top-1 {vlist of items not yet on current page}
-@d page_head==mem_top-2 {vlist for current page}
-@d temp_head==mem_top-3 {head of a temporary list of some kind}
-@d hold_head==mem_top-4 {head of a temporary list of another kind}
-@d adjust_head==mem_top-5 {head of adjustment list returned by |hpack|}
-@d active==mem_top-6 {head of active list in |line_break|, needs two words}
-@d align_head==mem_top-8 {head of preamble list for alignments}
-@d end_span==mem_top-9 {tail of spanned-width lists}
-@d omit_template==mem_top-10 {a constant token list}
-@d null_list==mem_top-11 {permanently empty list}
-@d lig_trick==mem_top-12 {a ligature masquerading as a |char_node|}
-@d garbage==mem_top-12 {used for scrap information}
-@d backup_head==mem_top-13 {head of token list built by |scan_keyword|}
-@d hi_mem_stat_min==mem_top-13 {smallest statically allocated word in
- the one-word |mem|}
-@z
-@x module 164
-for k:=mem_base+1 to first_mem-1 do mem[k].sc:=0;
- {all glue dimensions are zeroed}
-@^data structure assumptions@>
-k:=mem_base;@+while k<first_mem do {set first words of glue specifications}
-@y
-for k:=mem_bot+1 to lo_mem_stat_max do mem[k].sc:=0;
- {all glue dimensions are zeroed}
-@^data structure assumptions@>
-k:=mem_bot;@+while k<=lo_mem_stat_max do
- {set first words of glue specifications}
-@z
-@x module 164
-rover:=first_mem; link(rover):=empty_flag; {now initialize the dynamic memory}
-node_size(rover):=hi_mem_base-rover; {which is one big available node}
-llink(rover):=rover; rlink(rover):=rover;@/
-link(hi_mem_base):=null; info(hi_mem_base):=null;
-for k:=hi_mem_base+1 to second_mem-1 do
- mem[k]:=mem[hi_mem_base];{clear list heads}
-@<Initialize the special list heads and constant nodes@>;
-avail:=null; mem_end:=second_mem-1; {initialize the one-word memory}
-var_used:=first_mem-mem_base; dyn_used:=second_mem-hi_mem_base;
-max_var_used:=var_used; {initialize statistics}
-@y
-rover:=lo_mem_stat_max+1;
-link(rover):=empty_flag; {now initialize the dynamic memory}
-node_size(rover):=1000; {which is a 1000-word available node}
-llink(rover):=rover; rlink(rover):=rover;@/
-lo_mem_max:=rover+1000; link(lo_mem_max):=null; info(lo_mem_max):=null;@/
-for k:=hi_mem_stat_min to mem_top do
- mem[k]:=mem[lo_mem_max]; {clear list heads}
-@<Initialize the special list heads and constant nodes@>;
-avail:=null; mem_end:=mem_top;
-hi_mem_min:=hi_mem_stat_min; {initialize the one-word memory}
-var_used:=lo_mem_stat_max+1-mem_bot; dyn_used:=mem_top+1-hi_mem_stat_min;
- {initialize statistics}
-@z
-@x module 165
-@t\hskip1em@>@!was_mem_end: pointer; {previous |mem_end|}
-@y
-@t\hskip1em@>@!was_mem_end,@!was_lo_max,@!was_hi_min: pointer;
- {previous |mem_end|, |lo_mem_max|,and |hi_mem_min|}
-@z
-@x module 166
-@!debug was_mem_end:=mem_base; {indicate that everything was previously free}
-@y
-@!debug was_mem_end:=mem_min; {indicate that everything was previously free}
-was_lo_max:=mem_min; was_hi_min:=mem_max;
-@z
-@x module 167
-begin for p:=mem_base to mem_end do free[p]:=false; {you can probably
- do this faster}
-@y
-begin for p:=mem_min to lo_mem_max do free[p]:=false; {you can probably
- do this faster}
-for p:=hi_mem_min to mem_end do free[p]:=false; {ditto}
-@z
-@x module 167
-for p:=0 to mem_end do was_free[p]:=free[p]; {|was_free:=free| might be faster}
-was_mem_end:=mem_end;
-@y
-for p:=mem_min to lo_mem_max do was_free[p]:=free[p];
-for p:=hi_mem_min to mem_end do was_free[p]:=free[p];
- {|was_free:=free| might be faster}
-was_mem_end:=mem_end; was_lo_max:=lo_mem_max; was_hi_min:=hi_mem_min;
-@z
-@x module 168
- begin if (p>mem_end)or(p<second_mem) then clobbered:=true
-@y
- begin if (p>mem_end)or(p<hi_mem_min) then clobbered:=true
-@z
-@x module 169
-repeat if (p>=hi_mem_base)or(p<first_mem) then clobbered:=true
- else if (rlink(p)>=hi_mem_base)or(rlink(p)<first_mem) then clobbered:=true
- else if not(is_empty(p))or(node_size(p)<2)or@|
- (p+node_size(p)>hi_mem_base)or@| (llink(rlink(p))<>p) then clobbered:=true;
-@y
-repeat if (p>=lo_mem_max)or(p<mem_min) then clobbered:=true
- else if (rlink(p)>=lo_mem_max)or(rlink(p)<mem_min) then clobbered:=true
- else if not(is_empty(p))or(node_size(p)<2)or@|
- (p+node_size(p)>lo_mem_max)or@| (llink(rlink(p))<>p) then clobbered:=true;
-@z
-@x module 170
-p:=mem_base;
-while p<=hi_mem_base do {node |p| should not be empty}
-@y
-p:=mem_min;
-while p<=lo_mem_max do {node |p| should not be empty}
-@z
-@x module 170
- while (p<=hi_mem_base) and not free[p] do incr(p);
- while (p<=hi_mem_base) and free[p] do incr(p);
-@y
- while (p<=lo_mem_max) and not free[p] do incr(p);
- while (p<=lo_mem_max) and free[p] do incr(p);
-@z
-@x module 171
-for p:=mem_base to mem_end do
- if not free[p] and ((p>was_mem_end) or was_free[p]) then
-@y
-for p:=mem_min to lo_mem_max do
- if not free[p] and ((p>was_lo_max) or was_free[p]) then
- begin print_char(" "); print_int(p);
- end;
-for p:=hi_mem_min to mem_end do
- if not free[p] and
- ((p<was_hi_min) or (p>was_mem_end) or was_free[p]) then
-@z
-@x module 172
-begin for q:=mem_base to mem_end do
-@y
-begin for q:=mem_min to lo_mem_max do
-@z
-@x module 172
-@<Search |eqtb| for equivalents equal to |p|@>;
-@y
-for q:=hi_mem_min to mem_end do
- begin if link(q)=p then
- begin print_nl("LINK("); print_int(q); print_char(")");
- end;
- if info(q)=p then
- begin print_nl("INFO("); print_int(q); print_char(")");
- end;
- end;
-@<Search |eqtb| for equivalents equal to |p|@>;
-@z
-@x module 176
-if (p<hi_mem_base)or(p>mem_end) then print_esc("CLOBBERED.")
-@y
-if (p<hi_mem_min)or(p>mem_end) then print_esc("CLOBBERED.")
-@z
-@x module 178
-begin if (p<mem_base)or(p>=hi_mem_base) then print_char("*")
-@y
-begin if (p<mem_min)or(p>=lo_mem_max) then print_char("*")
-@z
-@x module 293
-if (p<hi_mem_base) or (p>mem_end) then
-@y
-if (p<hi_mem_min) or (p>mem_end) then
-@z
-@x module 639
- print_int(dyn_used); print("; max so far: ");
- print_int(max_var_used); print_char("&");
- print_int(mem_end+1-hi_mem_base); print_ln;
-@y
- print_int(dyn_used); print("; still untouched: ");
- print_int(hi_mem_min-lo_mem_max-1); print_ln;
-@z
-@x module 857
-begin save_link:=link(cur_p); {this is OK even if |cur_p=null|}
-link(cur_p):=null; print_nl(""); short_display(link(printed_node));
-link(cur_p):=save_link; printed_node:=cur_p;
-@y
-begin print_nl("");
-if cur_p=null then short_display(link(printed_node))
-else begin save_link:=link(cur_p);
- link(cur_p):=null; print_nl(""); short_display(link(printed_node));
- link(cur_p):=save_link;
- end;
-printed_node:=cur_p;
-@z
-@x module 1249
-if 2*max_halfword<hi_mem_base-mem_base then bad:=41;
-@y
-if 2*max_halfword<mem_top-mem_min then bad:=41;
-@z
-@x module 1307
-dump_int(hi_mem_base);@/
-@y
-dump_int(mem_bot);@/
-dump_int(mem_top);@/
-@z
-@x module 1308
-if x<>hi_mem_base then goto bad_fmt;
-@y
-if x<>mem_bot then goto bad_fmt;
-undump_int(x);
-if x<>mem_top then goto bad_fmt;
-@z
-@x module 1311
-dump_int(rover);
-p:=mem_base; q:=rover; x:=0;
-@y
-dump_int(lo_mem_max); dump_int(rover);
-p:=mem_bot; q:=rover; x:=0;
-@z
-@x module 1311
-var_used:=var_used+hi_mem_base-p; dyn_used:=mem_end+1-hi_mem_base;@/
-dump_int(mem_end); dump_int(avail);
-for k:=p to mem_end do dump_wd(mem[k]);
-x:=x+mem_end+1-p;
-@y
-var_used:=var_used+lo_mem_max-p; dyn_used:=mem_end+1-hi_mem_min;@/
-for k:=p to lo_mem_max do dump_wd(mem[k]);
-x:=x+lo_mem_max+1-p;
-dump_int(hi_mem_min); dump_int(avail);
-for k:=hi_mem_min to mem_end do dump_wd(mem[k]);
-x:=x+mem_end+1-hi_mem_min;
-@z
-@x module 1312
-undump(min_halfword)(hi_mem_base)(rover);
-p:=mem_base; q:=rover; x:=0;
-repeat for k:=p to q+1 do undump_wd(mem[k]);
-p:=q+node_size(q);
-if (p>hi_mem_base)or((q>=rlink(q))and(rlink(q)<>rover)) then goto bad_fmt;
-q:=rlink(q);
-until q=rover;
-undump_size(hi_mem_base)(mem_max)('mem max')(mem_end);
-undump(null)(mem_end)(avail);
-for k:=p to mem_end do undump_wd(mem[k]);
-undump_int(var_used); undump_int(dyn_used);
-max_var_used:=var_used
-@y
-undump(lo_mem_stat_max+1000)(hi_mem_stat_min-1)(lo_mem_max);
-undump(lo_mem_stat_max+1)(lo_mem_max)(rover);
-p:=mem_bot; q:=rover; x:=0;
-repeat for k:=p to q+1 do undump_wd(mem[k]);
-p:=q+node_size(q);
-if (p>lo_mem_max)or((q>=rlink(q))and(rlink(q)<>rover)) then goto bad_fmt;
-q:=rlink(q);
-until q=rover;
-for k:=p to lo_mem_max do undump_wd(mem[k]);
-if mem_min<mem_bot-2 then {make more low memory available}
- begin p:=llink(rover); q:=mem_min+1;
- link(mem_min):=null; info(mem_min):=null; {we don't use the bottom word}
- rlink(p):=q; llink(rover):=q;@/
- rlink(q):=rover; llink(q):=p; link(q):=empty_flag;
- node_size(q):=mem_bot-q;
- end;
-undump(lo_mem_max+1)(hi_mem_stat_min)(hi_mem_min);
-undump(null)(mem_top)(avail); mem_end:=mem_top;
-for k:=hi_mem_min to mem_end do undump_wd(mem[k]);
-undump_int(var_used); undump_int(dyn_used)
-@z
-@x module 1323
-undump(min_halfword)(hi_mem_base)(font_glue[k]);
-@y
-undump(min_halfword)(lo_mem_max)(font_glue[k]);
-@z
-@x module 1334
- wlog_ln(' ',max_var_used:1,'&',mem_end+1-hi_mem_base:1,@|
- ' words of memory out of ',
- hi_mem_base-mem_base:1,'&',mem_max+1-hi_mem_base:1);@/
-@y
- wlog_ln(' ',lo_mem_max-mem_min+mem_end-hi_mem_min+2:1,@|
- ' words of memory out of ',mem_end+1-mem_min:1);@/
-@z that's the end of change number 300!
-
-301. node_size field could overflow if low mem was too large (Dec 20, 1984)
-[This bug existed from the beginning, if hi_mem_base-first_mem>max_halfword!]
-@x module 111
-if (mem_min<min_halfword)or(mem_max>=max_halfword) then bad:=14;
-@y
-if (mem_min<min_halfword)or(mem_max>=max_halfword)or@|
- (mem_bot-mem_min>max_halfword+1) then bad:=14;
-@z
-@x module 125
-@!t:pointer; {temporary register}
-@y
-@!t:integer; {temporary register}
-@z
-@x module 125
-if lo_mem_max+2<hi_mem_min then
-@y
-if lo_mem_max+2<hi_mem_min then if lo_mem_max+2<=mem_bot+max_halfword then
-@z
-@x module 126
-rlink(q):=rover; llink(q):=p; link(q):=empty_flag; node_size(q):=t-lo_mem_max;@/
-@y
-if t>mem_bot+max_halfword then t:=mem_bot+max_halfword;
-rlink(q):=rover; llink(q):=p; link(q):=empty_flag; node_size(q):=t-lo_mem_max;@/
-@z
-
-302. Improvement to missing-format-file error (DRF, 5 Jan 85)
-@x module 524
-var j:0..buf_size; {the first space after the file name}
-begin if buffer[loc]="&" then
- begin incr(loc); j:=loc; buffer[last]:=" ";
- while buffer[j]<>" " do incr(j);
- pack_buffered_name(0,loc,j-1); {try first without the system file area}
- if w_open_in(fmt_file) then
- begin loc:=j; goto found;
- end;@/
- pack_buffered_name(format_area_length,loc,j-1);
- {now try the system format file area}
- if w_open_in(fmt_file) then
- begin loc:=j; goto found;
- end;
- wake_up_terminal;
- wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.');
-@.Sorry, I can't find...@>
- end;
- {now pull out all the stops: try for the system \.{PLAIN} file}
-pack_buffered_name(format_default_length-format_ext_length,1,0);
-if not w_open_in(fmt_file) then
- begin wake_up_terminal;
- wterm_ln('I can''t find the PLAIN format file!');
-@.I can't find PLAIN...@>
-@.PLAIN@>
- open_fmt_file:=false; return;
- end;
-found:open_fmt_file:=true;
-@y
-var j:0..buf_size; {the first space after the format file name}
-begin j:=loc;
-if buffer[loc]="&" then
- begin incr(loc); j:=loc; buffer[last]:=" ";
- while buffer[j]<>" " do incr(j);
- pack_buffered_name(0,loc,j-1); {try first without the system file area}
- if w_open_in(fmt_file) then goto found;
- pack_buffered_name(format_area_length,loc,j-1);
- {now try the system format file area}
- if w_open_in(fmt_file) then goto found;
- wake_up_terminal;
- wterm_ln('Sorry, I can''t find that format;',' will try PLAIN.');
-@.Sorry, I can't find...@>
- update_terminal;
- end;
- {now pull out all the stops: try for the system \.{PLAIN} file}
-pack_buffered_name(format_default_length-format_ext_length,1,0);
-if not w_open_in(fmt_file) then
- begin wake_up_terminal;
- wterm_ln('I can''t find the PLAIN format file!');
-@.I can't find PLAIN...@>
-@.PLAIN@>
- open_fmt_file:=false; return;
- end;
-found:loc:=j; open_fmt_file:=true;
-@z
-
-303. Welcoming message appears sooner (DRF, Jan 7)
-@x module 61
-else begin print(format_ident); print_ln;
- end;
-@y
-else begin print(format_ident); print_ln;
- end;
-update_terminal;
-@z
-
-304. Minor change to help message in "confusion" (Jan 23)
-@x module 95
- help2("One of your earlier faux pas has wounded me deeply,")@/
- ("so I'm barely conscious. Please fix it and try again.");
-@y
- help2("One of your faux pas seems to have wounded me deeply...")@/
- ("in fact, I'm barely conscious. Please fix it and try again.");
-@z
-
-305. Improved logic for `(see the transcript file...)' (Jan 23)
-@x module 245
-if history=spotless then history:=warning_issued;
-if (tracing_online<=0)and(selector=term_and_log) then decr(selector);
-@y
-if (tracing_online<=0)and(selector=term_and_log) then
- begin decr(selector);
- if history=spotless then history:=warning_issued;
- end;
-@z
-
-306. Change 291 violated standard PASCAL (CET1, Feb 18)
-@x module 331
-for first:=0 to buf_size do buffer[first]:=0;
-@y since some procedures `threaten' |first| globally [BS/6192 sec 6.8.3.9]
-first:=buf_size; repeat buffer[first]:=0; decr(first); until first=0;
-@z
-
-307. Nonexistent character could be output via ligature hyphenation (April 11)
-@x module 582 (slight inefficiency removed while correcting this)
-begin if (font_bc[f]<=c)and(font_ec[f]>=c) then
-@y
-begin if font_bc[f]<=c then if font_ec[f]>=c then
-@z
-@x module 892 (likewise)
-@!hu:array[1..63] of ASCII_code; {like |hc|, before conversion to lowercase}
-@y
-@!hu:array[1..63] of ASCII_code; {like |hc|, before conversion to lowercase}
-@!hyf_char:integer; {hyphen character of the relevant font}
-@z
-@x module 896 (likewise)
-done2: if hyphen_char[hf]<0 then goto done1;
-if hyphen_char[hf]>255 then goto done1;
-@y
-done2: hyf_char:=hyphen_char[hf];
-if hyf_char<0 then goto done1;
-if hyf_char>255 then goto done1;
-@z
-@x module 912 and another local variable
-@!c:ASCII_code; {character temporarily replaced by a hyphen}
-@y
-@!c:ASCII_code; {character temporarily replaced by a hyphen}
-@!hyf_node:pointer; {the hyphen, if it exists}
-@z
-@x module 915 (this is the real bugfix)
-minor_tail:=null; c:=hu[i+1]; hu[i+1]:=hyphen_char[hf];
-repeat l:=reconstitute(l+1,i+1);
-if minor_tail=null then pre_break(r):=link(hold_head)
-else link(minor_tail):=link(hold_head);
-minor_tail:=link(hold_head);
-if link(minor_tail)<>null then minor_tail:=link(minor_tail);
-until l>i;
-hu[i+1]:=c; {restore the character in the hyphen position}
-decr(l); hyf[l]:=0
-@y
-minor_tail:=null; hyf_node:=new_character(hf,hyf_char);
-if hyf_node<>null then
- begin incr(i); c:=hu[i]; hu[i]:=hyf_char;
- end;
-repeat l:=reconstitute(l+1,i);
-if minor_tail=null then pre_break(r):=link(hold_head)
-else link(minor_tail):=link(hold_head);
-minor_tail:=link(hold_head);
-if link(minor_tail)<>null then minor_tail:=link(minor_tail);
-until l=i;
-if hyf_node<>null then
- begin hu[i]:=c; {restore the character in the hyphen position}
- free_avail(hyf_node); decr(i); l:=i;
- end;
-hyf[i]:=0
-@z
-@x module 918
-begin r:=new_disc; pre_break(r):=new_character(hf,hyphen_char[hf]);
-@y
-begin r:=new_disc; pre_break(r):=new_character(hf,hyf_char);
-@z
-
-308. Improper memory usage computed by INITEX in change 300. (DRF, April 15)
-@x module 162
-@d hi_mem_stat_min==mem_top-13 {smallest statically allocated word in
- the one-word |mem|}
-@y
-@d hi_mem_stat_min==mem_top-13 {smallest statically allocated word in
- the one-word |mem|}
-@d hi_mem_stat_usage=14 {the number of one-word nodes always present}
-@z
-@x module 164 (text macro without parentheses strikes again!)
-var_used:=lo_mem_stat_max+1-mem_bot; dyn_used:=mem_top+1-hi_mem_stat_min;
-@y
-var_used:=lo_mem_stat_max+1-mem_bot; dyn_used:=hi_mem_stat_usage;
-@z
-
-309. A faster |flush_list| routine for the inner loop. (DRF, April 16)
-@x module 123
-var q:pointer; {the successor of node |p|}
-begin while p<>null do
- begin q:=link(p); free_avail(p); p:=q;
- end;
-@y
-var @!q,@!r:pointer; {list traversers}
-begin if p<>null then
- begin r:=p;
- repeat q:=r; r:=link(r); @!stat decr(dyn_used);@+tats@/
- until r=null; {now |q| is the last node on the list}
- link(q):=avail; avail:=p;
- end;
-@z
-
-310. Kern for accent positioning could disappear after a line break (April 17)
-(Change 269 fixed only part of the problem!)
-@x module 155
-@d explicit=1 {|subtype| of kern nodes from \.{\\kern} and \.{\\/} and accents}
-@y
-@d explicit=1 {|subtype| of kern nodes from \.{\\kern} and \.{\\/}}
-@d acc_kern=2 {|subtype| of kern nodes from accents}
-@z
-@x module 191
-if subtype(p)<=explicit then
- begin print_esc("kern");
- if subtype(p)=explicit then print_char(" ");
- print_scaled(width(p));
-@y
-if subtype(p)<>mu_glue then
- begin print_esc("kern");
- if subtype(p)<>normal then print_char(" ");
- print_scaled(width(p));
- if subtype(p)=acc_kern then print(" (for accent)");
-@.for accent@>
-@z
-@x module 837
- math_node,kern_node: break_width[1]:=break_width[1]-width(s);
-@y
- math_node,kern_node: if subtype(s)=acc_kern then goto done
- else break_width[1]:=break_width[1]-width(s);
-@z
-@x module 879
- if non_discardable(q) then goto done1;
-@y
- if non_discardable(q) then goto done1;
- if subtype(q)=acc_kern then if type(q)=kern_node then goto done1;
-@z
-@x module 1125
-r:=new_kern(delta); subtype(r):=explicit; link(tail):=r; link(r):=p;
-tail:=new_kern(-a-delta); subtype(tail):=explicit; link(p):=tail; p:=q;
-@y
-r:=new_kern(delta); subtype(r):=acc_kern; link(tail):=r; link(r):=p;
-tail:=new_kern(-a-delta); subtype(tail):=acc_kern; link(p):=tail; p:=q;
-@z
-
-311. \lastbox and \unkern must not remove discretionary replacements (April 18)
-(Change 236 introduced this bug!)
-@x module 1079
-label exit;
-var p:pointer; {runs through the current list}
-@y
-label exit, done;
-var @!p,@!q:pointer; {run through the current list}
-@!m:quarterword; {the length of a replacement list}
-@z
-@x modules 1080 and 1081
- @<Apologize for inability to do \.{\\lastbox} now@>
-else begin if not is_char_node(tail) then
- if (type(tail)=hlist_node)or(type(tail)=vlist_node) then
- begin p:=head; cur_box:=tail; shift_amount(cur_box):=0;
- while link(p)<>tail do p:=link(p);
- tail:=p; link(p):=null;
- end;
- end;
-end
-
-@ @<Apologize for inability to do \.{\\lastbox} now@>=
-begin you_cant;
-help2("Sorry...I'm usually unable to take things from the current")@/
- ("page. This \lastbox will therefore be void."); error;
-end
-@y
- begin you_cant;
- help2("Sorry...I usually can't take things from the current page.")@/
- ("This \lastbox will therefore be void."); error;
- end
-else begin if not is_char_node(tail) then
- if (type(tail)=hlist_node)or(type(tail)=vlist_node) then
- @<Remove the last box, unless it's part of a discretionary@>;
- end;
-end
-
-@ @<Remove the last box...@>=
-begin q:=head;
-repeat p:=q;
-if not is_char_node(q) then if type(q)=disc_node then
- begin for m:=1 to replace_count(q) do p:=link(p);
- if p=tail then goto done;
- end;
-q:=link(p);
-until q=tail;
-cur_box:=tail; shift_amount(cur_box):=0;
-tail:=p; link(p):=null;
-done: end
-@z
-@x module 1105
-var p:pointer; {runs through the current list}
-@y
-label exit;
-var @!p,@!q:pointer; {run through the current list}
-@!m:quarterword; {the length of a replacement list}
-@z
-@x module 1105
- begin p:=head;
- while link(p)<>tail do p:=link(p);
- link(p):=null; flush_node_list(tail); tail:=p;
- end;
- end;
-end;
-@y
- begin q:=head;
- repeat p:=q;
- if not is_char_node(q) then if type(q)=disc_node then
- begin for m:=1 to replace_count(q) do p:=link(p);
- if p=tail then return;
- end;
- q:=link(p);
- until q=tail;
- link(p):=null; flush_node_list(tail); tail:=p;
- end;
- end;
-exit:end;
-@z
-@x module 1106
- help2("Sorry...I'm usually unable to take things from the current")@/
- ("page. Try `I\vskip-\lastskip' instead.");
- if cur_chr=kern_node then help_line[0]:=
- ("page. Try `I\kern-\lastkern' instead.")
- else if cur_chr<>glue_node then help_line[0]:=@|
- ("page. Perhaps you can make the output routine do it.");
-@y
- help2("Sorry...I usually can't take things from the current page.")@/
- ("Try `I\vskip-\lastskip' instead.");
- if cur_chr=kern_node then help_line[0]:=
- ("Try `I\kern-\lastkern' instead.")
- else if cur_chr<>glue_node then help_line[0]:=@|
- ("Perhaps you can make the output routine do it.");
-@z
-@x module 1120
-if n<128 then replace_count(tail):=n
-@y
-if n<=max_quarterword then replace_count(tail):=n
-@z
-
-
-*** Note by DEK, 18 Apr 1985
-(The code for version 1.3 has been published by Addison-Wesley under the
-title "TeX: The Program". It was phototypeset on our APS, but does not
-contain changes > 300. Some of those changes have been made in versions
-of TeX called 1.3; but the exact definition of version 1.3 is somewhat
-vague. Version 1.4 was released on April 18, 1985, after
-making change 311. At present I believe Version 1.4 will be identical
-to Version 2.0 except perhaps for things like index entries in the
-documentation and slightly revised help messages. Version 2.0 will
-coincide with the publication of Volume 1 of Computers and Typesetting,
-which will come out when METAFONT and Computer Modern are both finished.)
- Version 1.5
-312. if nonstandard area specified, don't try TEX_area too. (DRF, 26 Apr 85)
-@x module 537
- pack_file_name(cur_name,TEX_area,cur_ext);
- if a_open_in(cur_file) then goto done;
-@y
- if cur_area="" then
- begin pack_file_name(cur_name,TEX_area,cur_ext);
- if a_open_in(cur_file) then goto done;
- end;
-@z
-
-313. length of \write need no longer be limited (cf 235). (NBT, 30 Apr 85)
-@x module 1370
-show_token_list(link(def_ref),null,buf_size-10); print_ln;
-@y
-show_token_list(link(def_ref),null,10000000); print_ln;
-@z
-
-314. bug introduced in #300, just lucky it didn't cause trouble (CET1, 8 May 85)
-@x module 162
-@d active==mem_top-6 {head of active list in |line_break|, needs two words}
-@y
-@d active==mem_top-7 {head of active list in |line_break|, needs two words}
-@z
-
-315. Missing eoln after last typeout (Gropp, 11 May 85)
-@x module 1332
- wterm('Ouch---my internal constants have been',
-@y
- wterm_ln('Ouch---my internal constants have been',
-@z
-
-316. Redundancy (CET1, 17 May 85)
-[Change 287 was apparently introduced because of a faulty assumption,
-although its change to the calling of "initialize" was valid.]
-@x module 1332
- begin t_open_out;
- wterm_ln('Ouch---my internal constants have been',
- ' clobbered!---case ',bad:1);
-@y
- begin wterm_ln('Ouch---my internal constants have been clobbered!',
- '---case ',bad:1);
-@z
-
-317. batchmode to see if log file couldn't be opened (DRF, 22 May 85)
-@x module 92
-if interaction=batch_mode then decr(selector);
-if job_name=0 then open_log_file;
-@y
-if job_name=0 then open_log_file;
-if interaction=batch_mode then decr(selector);
-@z
-
-318. If the string pool overflows while reading the command line... (22 May 85)
-[This bug was first found in METAFONT, when it could occur more easily]
-@x module 525
-begin str_room(name_length);
-for k:=1 to name_length do append_char(xord[name_of_file[k]]);
-make_name_string:=make_string;
-@y
-begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings) then
- make_name_string:="?"
-else begin for k:=1 to name_length do append_char(xord[name_of_file[k]]);
- make_name_string:=make_string;
- end;
-@z
-
-319. Bug in \edef\foo{\iffalse\fi\the\toks0} (found by Dan Brotsky, 7 Aug 85)
-@x module 478
- if cur_cmd<>the then goto done2;
- q:=the_toks;
- if link(temp_head)<>null then
- begin link(p):=link(temp_head); p:=q;
- end;
-@y
- if cur_cmd<=max_command then goto done2;
- if cur_cmd<>the then expand
- else begin q:=the_toks;
- if link(temp_head)<>null then
- begin link(p):=link(temp_head); p:=q;
- end;
- end;
-@z
-
-*** Version 1.5 was released on August 7, 1985.
-
-320. Lowercase `plain' for consistency with the manual
-@x module 521
-TEX_format_default:='TeXformats:PLAIN.fmt';
-@.TeXformats@>
-@.PLAIN@>
-@y
-TEX_format_default:='TeXformats:plain.fmt';
-@.TeXformats@>
-@.plain@>
-@z (index entries also changed to lowercase in modules 524, 1331)
-
-321. Terminal woken up by \show and \showthe (November 27, 1985)
-@x module 1294
-begin get_token; print_nl("> ");
-@y
-begin get_token;
-if interaction=error_stop_mode then wake_up_terminal;
-print_nl("> ");
-@z
-@x module 1297
-begin p:=the_toks; print_nl("> "); token_show(temp_head);
-@y
-begin p:=the_toks;
-if interaction=error_stop_mode then wake_up_terminal;
-print_nl("> "); token_show(temp_head);
-@z
- Changes subsequent to `Version 2.0' as published in C&T, Volume B:
-
-322. Trivial change to a help message.
-@x module 1283
- ("Pretend that you're Hercule Poirot, examine all clues,")@/
-@y
- ("Pretend that you're Hercule Poirot: Examine all clues,")@/
-@z
-
-323. Precaution since |index| can be as high as |max_in_open|. (DRF)
-@x module 14
-if hash_prime>hash_size then bad:=5;
-@y
-if hash_prime>hash_size then bad:=5;
-if max_in_open>=128 then bad:=6;
-@z
-
-324. \kern clobbered at end of pre-break list in discretionary break.
-@x module 881
- |disc_break:=true|@>;
- if not is_char_node(q) then
- if (type(q)=math_node)or(type(q)=kern_node) then width(q):=0;
-@y
- |disc_break:=true|@>
- else if (type(q)=math_node)or(type(q)=kern_node) then width(q):=0;
-@z
-
-325. width after discretionary didn't take account of discarded nodes.
-@x module 830 (slight redefinition)
-@!t:quarterword; {replacement count, if |cur_p| is a discretionary node}
-@y
-@!t:integer; {node count, if |cur_p| is a discretionary node}
-@z
-@x module 837 (slight rearrangement)
-if (break_type=unhyphenated)or(cur_p=null) then
- begin s:=cur_p;
- while s<>null do
- begin if is_char_node(s) then goto done;
- case type(s) of
- glue_node:@<Subtract glue from |break_width|@>;
- penalty_node: do_nothing;
- math_node,kern_node: if subtype(s)=acc_kern then goto done
- else break_width[1]:=break_width[1]-width(s);
- othercases goto done
- endcases;@/
- s:=link(s);
- end;
- end
-else @<Compute the discretionary |break_width| values@>;
-@y
-s:=cur_p;
-if break_type>unhyphenated then if cur_p<>null then
- @<Compute the discretionary |break_width| values@>;
-while s<>null do
- begin if is_char_node(s) then goto done;
- case type(s) of
- glue_node:@<Subtract glue from |break_width|@>;
- penalty_node: do_nothing;
- math_node,kern_node: if subtype(s)=acc_kern then goto done
- else break_width[1]:=break_width[1]-width(s);
- othercases goto done
- endcases;@/
- s:=link(s);
- end;
-@z
-@x module 840 (this is the main change to fix the bug)
-begin t:=replace_count(cur_p); s:=cur_p;
-while t>0 do
- begin decr(t); s:=link(s);
- @<Subtract the width of node |s| from |break_width|@>;
- end;
-s:=post_break(cur_p);
-while s<>null do
- begin @<Add the width of node |s| to |break_width|@>;
-@y
-begin t:=replace_count(cur_p); v:=cur_p; s:=post_break(cur_p);
-while t>0 do
- begin decr(t); v:=link(v);
- @<Subtract the width of node |v| from |break_width|@>;
- end;
-while s<>null do
- begin @<Add the width of node |s| to |break_width| and increase |t|,
- unless it's discardable@>;
-@z
-@x module 840, continued
-break_width[1]:=break_width[1]+disc_width;
-@y
-break_width[1]:=break_width[1]+disc_width;
-if t=0 then s:=link(v); {more nodes may also be discardable after the break}
-@z
-@x module 841 (here we just change |s| to |v|)
-@<Subtract the width of node |s|...@>=
-if is_char_node(s) then
- begin f:=font(s);
- break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(s)));
- end
-else case type(s) of
- ligature_node: begin f:=font(lig_char(s));@/
- break_width[1]:=@|break_width[1]-
- char_width(f)(char_info(f)(character(lig_char(s))));
- end;
- hlist_node,vlist_node,rule_node,kern_node:
- break_width[1]:=break_width[1]-width(s);
-@y
-@<Subtract the width of node |v|...@>=
-if is_char_node(v) then
- begin f:=font(v);
- break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v)));
- end
-else case type(v) of
- ligature_node: begin f:=font(lig_char(v));@/
- break_width[1]:=@|break_width[1]-
- char_width(f)(char_info(f)(character(lig_char(v))));
- end;
- hlist_node,vlist_node,rule_node,kern_node:
- break_width[1]:=break_width[1]-width(v);
-@z
-@x module 842
- hlist_node,vlist_node,rule_node,kern_node:
- break_width[1]:=break_width[1]+width(s);
- othercases confusion("disc2")
-@:this can't happen disc2}{\quad disc2@>
- endcases
-@y
- hlist_node,vlist_node,rule_node:break_width[1]:=break_width[1]+width(s);
- kern_node: if (t=0)and(subtype(s)<>acc_kern) then t:=-1 {discardable}
- else break_width[1]:=break_width[1]+width(s);
- othercases confusion("disc2")
-@:this can't happen disc2}{\quad disc2@>
- endcases;
-incr(t)
-@z
-
-*** Version 2.1 was released on January 26, 1987.
-
-326. Removal of redundant code (found by Pat Monardo, 5 Feb 87)
-@x module 1224 [this change need not be made, since it has no effect]
- char_def_code: define(p,char_given,cur_val);
- math_char_def_code: define(p,math_given,cur_val);
-@y the cases cannot occur, so we simply don't list them
-@z
-
-327. More robustness is needed when debugging (Ronaldo Am\'a, 14 Apr 87)
-@x module 174
-begin while p>null do
-@y maybe mem_min>null (but nodes shouldn't be put in location mem_min exactly)
-begin while p>mem_min do
-@z
-@x module 182
-@p procedure show_node_list(@!p:pointer); {prints a node list symbolically}
-@y
-@p procedure show_node_list(@!p:integer); {prints a node list symbolically}
-@z
-@x module 182, continued
-while p>null do
-@y
-while p>mem_min do
-@z
-
-328. Storage allocation can be more elegant and efficient (4/21/87)
-@x module 127
-if r=p then if ((rlink(p)<>rover) or (llink(p)<>rover)) then
-@y
-if r=p then if rlink(p)<>p then
-@z
-
-329. Miscalculation of empty-line condition (April 22, 1987)
-@x module 360
- begin if limit=start then {previous line was empty}
-@y
- begin if (end_line_char<0)or(end_line_char>127) then incr(limit);
- if limit=start then {previous line was empty}
-@z
-
-330. A case where we don't have to assume system bookkeeping (April 28, 1987)
-@x module 560
-done: b_close(tfm_file); read_font_info:=g;
-@y [suggested by Jim Sterken]
-done: if file_opened then b_close(tfm_file);
-read_font_info:=g;
-@z [this was not a bug, according to the comment in module 28]
-
-331. jump_out must fix unfinished output (Found by Klaus Gunterman, 3 Aug 87)
-@x module 593
-doing_leaders:=false; dead_cycles:=0;
-@y
-doing_leaders:=false; dead_cycles:=0; cur_s:=-1;
-@z
-@x module 617
-cur_s:=-1; ensure_dvi_open;
-@y
-ensure_dvi_open;
-@z
-@x module 640
-dvi_out(eop); incr(total_pages);
-@y
-dvi_out(eop); incr(total_pages); cur_s:=-1;
-@z
-@x module 642
-if total_pages=0 then print_nl("No pages of output.")
-@y
-while cur_s>-1 do
- begin if cur_s>0 then dvi_out(pop)
- else begin dvi_out(eop); incr(total_pages);
- end;
- decr(cur_s);
- end;
-if total_pages=0 then print_nl("No pages of output.")
-@z
-
-332. \hangindent=1pt$$\halign{...\cr\noalign{\hrule}}$$ problem (19 Aug 87)
-@x module 805
-q:=link(head);
-@y
-q:=link(head); s:=head;
-@z
-@x module 805, continued
- q:=link(q);
-@y
- s:=q; q:=link(q);
-@z
-@x module 806
-if is_running(depth(q)) then depth(q):=depth(p);
-@y
-if is_running(depth(q)) then depth(q):=depth(p);
-if o<>0 then
- begin r:=link(q); link(q):=null; q:=hpack(q,natural);
- shift_amount(q):=o; link(q):=r; link(s):=q;
- end;
-@z
-
-333. \hskip 0pt plus 1fil\ifdim problem (found by Alan Guth, 20 Aug 87)
-@x module 366
-@!cvl_backup,@!radix_backup:small_number; {to save |cur_val_level| and |radix|}
-@y
-@!cvl_backup,@!radix_backup,@!co_backup:small_number;
- {to save |cur_val_level|, etc.}
-@z
-@x
-backup_backup:=link(backup_head);
-@y
-co_backup:=cur_order; backup_backup:=link(backup_head);
-@z
-@x
-link(backup_head):=backup_backup;
-@y
-cur_order:=co_backup; link(backup_head):=backup_backup;
-@z
-
-334. leaders too sensitive near exact multiples (M. F. Bridgland, 9 Nov 87)
-@x module 626
- begin edge:=cur_h+rule_wd; lx:=0;
-@y
- begin rule_wd:=rule_wd+10; {compensate for floating-point rounding}
- edge:=cur_h+rule_wd; lx:=0;
-@z
-@x ibid
- cur_h:=edge; goto next_p;
-@y
- cur_h:=edge-10; goto next_p;
-@z
-@x module 635
- begin edge:=cur_v+rule_ht; lx:=0;
-@y
- begin rule_ht:=rule_ht+10; {compensate for floating-point rounding}
- edge:=cur_v+rule_ht; lx:=0;
-@z
-@x ibid
- cur_v:=edge; goto next_p;
-@y
- cur_v:=edge-10; goto next_p;
-@z
-
-335. Glitch in fixed-point multiplication of negatives (W.G. Sullivan, 17Nov87)
-@x module 572
-begin alpha:=16*z; beta:=16;
-while z>=@'40000000 do
- begin z:=z div 2; beta:=beta div 2;
- end;
-@y
-begin alpha:=16;
-while z>=@'40000000 do
- begin z:=z div 2; alpha:=alpha+alpha;
- end;
-beta:=256 div alpha; alpha:=alpha*z;
-@z
-
-336. If there are no \patterns and some \lccode is 1 (Breitenlohner, 12Dec87)
-@x module 952
-trie_link(0):=0; trie_char(0):=0; trie_op(0):=0;
-@y
-trie_link(0):=0; trie_char(0):=0; trie_op(0):=min_quarterword;
-@z
-
-337. \csname might encounter undefined_cs in a group (Chris Thompson, 23Dec87)
-@x module 372
- begin eqtb[cur_cs]:=eqtb[frozen_relax];
-@y
- begin eq_define(cur_cs,relax,256);
-@z
-
-338. \outer\def\a0{}\a\a shows temp_head list garbage (Silvio Levy, 20Apr88)
-@x module 391
-repeat if (info(r)>match_token+127)or(info(r)<match_token) then s:=null
-else begin match_chr:=info(r)-match_token; s:=link(r); r:=s;
- p:=temp_head; link(p):=null; m:=0;
-@y
-repeat link(temp_head):=null;
-if (info(r)>match_token+127)or(info(r)<match_token) then s:=null
-else begin match_chr:=info(r)-match_token; s:=link(r); r:=s;
- p:=temp_head; m:=0;
-@z
-
-339. \def\\#1{}\input a\\\z failed (Robert Messer, 24Apr88)
-@x module 259
-var h:integer; {hash code}
-@y
-var h:integer; {hash code}
-@!d:integer; {number of characters in incomplete current string}
-@z
-@x module 260
-str_room(l);
-for k:=j to j+l-1 do append_char(buffer[k]);
-text(p):=make_string;
-@y
-str_room(l); d:=cur_length;
-while pool_ptr>str_start[str_ptr] do
- begin decr(pool_ptr); str_pool[pool_ptr+l]:=str_pool[pool_ptr];
- end; {move current string up to make room for another}
-for k:=j to j+l-1 do append_char(buffer[k]);
-text(p):=make_string; pool_ptr:=pool_ptr+d;
-@z
-
-340. Make patterns work when trie_min=0 (Peter Breitenlohner, 10May88)
-@x module 951
-trie_max:=128; trie_min:=128; trie_link(0):=1; trie_taken[0]:=false;
-@y
-trie_max:=128; trie_min:=128; trie_link(0):=1; trie_taken[0]:=false;
-trie_link(trie_size):=0; trie_back(0):=trie_size; {wrap around}
-@z
-@x module 953
-begin c:=trie_c[p]; {we have |c>0|}
-if c<trie_min then trie_min:=c;
-z:=trie_link(trie_min-1); {get the first conceivably good hole}
-@y
-begin c:=trie_c[p];
-if c<trie_min then trie_min:=c;
-if trie_min=0 then z:=trie_link(trie_size)
-else z:=trie_link(trie_min-1); {get the first conceivably good hole}
-@z
-@x module 966
-r:=0; {finally, we will zero out the holes}
-@y
-r:=trie_size; {finally, we will zero out the holes}
-@z
-
-341. Avoid possible trie_pointer out of range (24May88)
-@x module 923
-hc[0]:=127; hc[hn+1]:=127; hc[hn+2]:=256; {insert delimiters}
-@y
-hc[0]:=127; hc[hn+1]:=127; hc[hn+2]:=128; {insert delimiters}
-@z
-
-342. \input a\romannumeral1 etc.; similar to bug 339. (25May88)
-@x module 464
-@p function str_toks:pointer; {changes the current string to a token list}
-@y
-@p function str_toks(@!b:pool_pointer):pointer;
- {changes the string |str_pool[b..pool_ptr]| to a token list}
-@z
-@x module 464, continued
-p:=temp_head; link(p):=null; k:=str_start[str_ptr];
-@y
-p:=temp_head; link(p):=null; k:=b;
-@z
-@x module 464, concluded
-pool_ptr:=str_start[str_ptr]; str_toks:=p;
-@y
-pool_ptr:=b; str_toks:=p;
-@z
-@x module 465
-begin get_x_token; scan_something_internal(tok_val,false);
-if cur_val_level>=ident_val then @<Copy the token list@>
-else begin old_setting:=selector; selector:=new_string;
-@y
-@!b:pool_pointer; {base of temporary string}
-begin get_x_token; scan_something_internal(tok_val,false);
-if cur_val_level>=ident_val then @<Copy the token list@>
-else begin old_setting:=selector; selector:=new_string; b:=pool_ptr;
-@z
-@x module 465, continued
- selector:=old_setting; the_toks:=str_toks;
-@y
- selector:=old_setting; the_toks:=str_toks(b);
-@z
-@x module 470
-begin c:=cur_chr; @<Scan the argument for command |c|@>;
-old_setting:=selector; selector:=new_string;
-@<Print the result of command |c|@>;
-selector:=old_setting; link(garbage):=str_toks; ins_list(link(temp_head));
-@y
-@!b:pool_pointer; {base of temporary string}
-begin c:=cur_chr; @<Scan the argument for command |c|@>;
-old_setting:=selector; selector:=new_string; b:=pool_ptr;
-@<Print the result of command |c|@>;
-selector:=old_setting; link(garbage):=str_toks(b); ins_list(link(temp_head));
-@z
-
-343. **\input\romannumeral6 confusion bypassed (25May88)
-@x module 525
-begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings) then
-@y
-begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings)or
- (cur_length>0) then
-@z
-
-344. Avoid negative dividend rounding upward (Chris Thompson, fixed 19Jun88)
-@x module 126
-else t:=(lo_mem_max+hi_mem_min+2) div 2; {|lo_mem_max+2<=t<hi_mem_min|}
-@y
-else t:=lo_mem_max+1+(hi_mem_min-lo_mem_max)div 2; {|lo_mem_max+2<=t<hi_mem_min|}
-@z
-
-345. Better strategy when near memory overflow (Chris Thompson)
-@x module 126
-begin if lo_mem_max+1000<hi_mem_min then t:=lo_mem_max+1000
-@y
-begin if hi_mem_min-lo_mem_max>=1998 then t:=lo_mem_max+1000
-@z
-
-346. An omission from change 333 (Tsunetoshi Hayashi, reported 20June88)
-@x module 439
-cur_val:=0; cur_val_level:=int_val; radix:=0;
-@y
-cur_val:=0; cur_val_level:=int_val; radix:=0; cur_order:=0;
-@z
-
-347. Avoid fatal_error after terminal eof (Tim Morgan, reported 25Oct88)
-@x module 71 [serious problem occurred if this was called in open_log_file]
-if not input_ln(term_in,true) then fatal_error("End of file on the terminal!");
-@y
-if not input_ln(term_in,true) then t_open_in;
-@z
-
-348. Force terminal output when open_log_file aborts (6Nov88)
-@x module 535
- begin print_err("I can't write on file `");
-@y
- begin selector:=term_only; print_err("I can't write on file `");
-@z
-
-349. By popular request, undo #347 and fix the bug a more complex way.
-@x module 71 [this undoes change #347]
-if not input_ln(term_in,true) then t_open_in;
-@y
-if not input_ln(term_in,true) then fatal_error("End of file on the terminal!");
-@z
-@x module 92 [now we get to the new stuff]
-begin if job_name>0 then selector:=term_and_log
-@y
-begin if log_opened then selector:=term_and_log
-@z
-@x module 93
- error;
-@y
- if log_opened then error;
-@z
-@x module 527
-@!job_name:str_number; {principal file name}
-@y
-@!job_name:str_number; {principal file name}
-@!log_opened:boolean; {has the transcript file been opened?}
-@z
-@x module 528
-@<Initialize the output...@>=job_name:=0; name_in_progress:=false;
-@y
-@<Initialize the output...@>=
-job_name:=0; name_in_progress:=false; log_opened:=false;
-@z
-@x module 534
-selector:=log_only;
-@y
-selector:=log_only; log_opened:=true;
-@z
-@x module 535
-begin if interaction<scroll_mode then {bypass |fatal_error|}
- begin selector:=term_only; print_err("I can't write on file `");
-@.I can't write on file x@>
- print_file_name(cur_name,cur_area,cur_ext); print("'.");@/
- job_name:=0; history:=fatal_error_stop; jump_out;
- end; {abort the program without a log file}
-@y
-begin selector:=term_only;
-@z
-@x module 1265 [this change is optional, but it's a slight improvement]
-if job_name<>0 then selector:=selector+2;
-@y
-if log_opened then selector:=selector+2;
-@z
-@x module 1333
-if job_name>0 then
-@y
-if log_opened then
-@z
-@x module 1334
-if job_name>0 then {the log file is open}
-@y
-if log_opened then
-@z
-
-350. Forgotten update in error recovery (Breitenlohner, 20 Jan 89)
-@x module 976
- glue_ptr(p):=r;
-@y
- glue_ptr(p):=r; q:=r;
-@z
-@x module 1004
- glue_ptr(p):=r;
-@y
- glue_ptr(p):=r; q:=r;
-@z
-
-351. Avoid error \aftergroup\relax\dump (Mittelbach&Schoepf, 17 Feb 89)
-@x module 280
-begin check_full_save_stack;
-save_type(save_ptr):=insert_token; save_level(save_ptr):=level_zero;
-save_index(save_ptr):=t; incr(save_ptr);
-@y
-begin if cur_level>level_one then
- begin check_full_save_stack;
- save_type(save_ptr):=insert_token; save_level(save_ptr):=level_zero;
- save_index(save_ptr):=t; incr(save_ptr);
- end;
-@z
-
-352. Cosmetic change to validate comment in 115 (Breitenlohner, 20 Mar 89)
-@x module 791
-begin q:=link(cur_align);
-if (cur_align=null)or(q=null) then confusion("endv");
-@y
-begin if cur_align=null then confusion("endv");
-q:=link(cur_align);@+if q=null then confusion("endv");
-@z
-
-353. $$\begingroup\halign{#\cr}$$ caused confusion (Mittelbach, 7 Jun 89)
-@x module 1130
-mmode+halign: if privileged then init_align;
-@y
-mmode+halign: if privileged then
- if cur_group=math_shift_group then init_align
- else off_save;
-@z
-
-354. Conflict in global array dig with .5\ifdim.6 (Mittelbach, 20 Jun 89)
-@x module 450
-@!k:small_number; {number of digits in a decimal fraction}
-@y
-@!k,@!kk:small_number; {number of digits in a decimal fraction}
-@!p,@!q:pointer; {top of decimal digit stack}
-@z
-@x module 452
-begin k:=0; get_token; {|point_token| is being re-scanned}
-loop@+ begin get_x_token;
- if (cur_tok>zero_token+9)or(cur_tok<zero_token) then goto done1;
- if k<17 then {digits for |k>=17| cannot affect the result}
- begin dig[k]:=cur_tok-zero_token; incr(k);
- end;
- end;
-done1: f:=round_decimals(k);
-@y
-begin k:=0; p:=null; get_token; {|point_token| is being re-scanned}
-loop@+ begin get_x_token;
- if (cur_tok>zero_token+9)or(cur_tok<zero_token) then goto done1;
- if k<17 then {digits for |k>=17| cannot affect the result}
- begin q:=get_avail; link(q):=p; info(q):=cur_tok-zero_token;
- p:=q; incr(k);
- end;
- end;
-done1: for kk:=k downto 1 do
- begin dig[kk-1]:=info(p); q:=p; p:=link(p); free_avail(q);
- end;
-f:=round_decimals(k);
-@z
-
-355. String startup problems (Wayne Sullivan, 17 Jul 89)
-@x module 31 (Warning: This affects most change files!)
- overflow("buffer size",buf_size);
-@:TeX capacity exceeded buffer size}{\quad buffer size@>
-@y
- @<Report overflow of the input buffer, and abort@>;
-@z
-@x module 35
-consist of the remainder of the command line, after the part that invoked
-\TeX.
-@y
-consist of the remainder of the command line, after the part that invoked
-\TeX.
-
-The first line is special also because it may be read before \TeX\ has
-input a format file. In such cases, normal error messages cannot yet
-be given. The following code uses concepts that will be explained later.
-
-@<Report overflow of the input buffer, and abort@>=
-if format_ident=0 then
- begin write_ln(term_out,'Buffer size exceeded!'); goto final_end;
-@.Buffer size exceeded@>
- end
-else begin cur_input.loc_field:=first; cur_input.limit_field:=last-1;
- overflow("buffer size",buf_size);
-@:TeX capacity exceeded buffer size}{\quad buffer size@>
- end
-@z
-@x module 1310
-k:=pool_ptr-4; undump_four_ASCII
-@y
-k:=pool_ptr-4; undump_four_ASCII;
-init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr
-@z
-@x module 1332
-tini@/
-@y
-init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr; fix_date_and_time;
-tini@/
-@z
-@x module 1332
-init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr;@/
-@y
-@z
-
-356. Allow integer products to be 31 bits long (Mittelbach, 16 Aug 89)
-@x module 105
-@p function nx_plus_y(@!n:integer;@!x,@!y:scaled):scaled;
-begin if n<0 then
- begin negate(x); negate(n);
- end;
-if n=0 then nx_plus_y:=y
-else if ((x<=(@'7777777777-y) div n)and(-x<=(@'7777777777+y) div n)) then
- nx_plus_y:=n*x+y
-else begin arith_error:=true; nx_plus_y:=0;
- end;
-end;
-@y
-@d nx_plus_y(#)==mult_and_add(#,@'7777777777)
-@d mult_integers(#)==mult_and_add(#,0,@'17777777777)
-
-@p function mult_and_add(@!n:integer;@!x,@!y,@!max_answer:scaled):scaled;
-begin if n<0 then
- begin negate(x); negate(n);
- end;
-if n=0 then mult_and_add:=y
-else if ((x<=(max_answer-y) div n)and(-x<=(max_answer+y) div n)) then
- mult_and_add:=n*x+y
-else begin arith_error:=true; mult_and_add:=0;
- end;
-end;
-@z
-@x module 1240
- if q=multiply then cur_val:=nx_plus_y(eqtb[l].int,cur_val,0)
-@y
- if q=multiply then
- if p=int_val then cur_val:=mult_integers(eqtb[l].int,cur_val)
- else cur_val:=nx_plus_y(eqtb[l].int,cur_val,0)
-@z
-
-357. Raise the maximum number of tokens normally shown (pointed out by
-John Lavagnino in TeXhax on 19 May 89; corrected on 31 Aug 89).
-@x module 295
-begin if p<>null then show_token_list(link(p),null,1000);
-@y
-begin if p<>null then show_token_list(link(p),null,10000000);
-@z
-@x module 1370 (this part of the change is cosmetic only)
-show_token_list(link(def_ref),null,10000000); print_ln;
-@y
-token_show(def_ref); print_ln;
-@z
-
-358. Like 353, but with $$\begingroup\eqno$$ (Mittelbach, 25 Jul 89)
-@x module 1140
-mmode+eq_no: if privileged then start_eq_no;
-@y
-mmode+eq_no: if privileged then
- if cur_group=math_shift_group then start_eq_no
- else off_save;
-@z
-
-359. Major extension to 8-bit character input. (These changes, and a few that
-follow, were discussed during the 10th TUG meeting and installed during
-the week of 10 Sep 1989. They bring the implementation of TeX82 up to date with
-international developments and experience, and I believe they mark the
-final development of this program into a completely stable system.)
-Several changes to the documentation (not the program) are omitted here.
-@x module 18
-@!ASCII_code=0..127; {seven-bit numbers}
-@y
-@!ASCII_code=0..255; {eight-bit numbers}
-@z
-@x module 19
-@d last_text_char=127 {ordinal number of the largest element of |text_char|}
-
-@<Local variables for init...@>=
-@!i:0..last_text_char;
-@y
-@d last_text_char=255 {ordinal number of the largest element of |text_char|}
-
-@<Local variables for init...@>=
-@!i:integer;
-@z
-@x module 21
-xchr[0]:=' '; xchr[@'177]:=' ';
- {ASCII codes 0 and |@'177| do not appear in text}
-@y
-@z
-@x module 23
-for i:=1 to @'37 do xchr[i]:=' ';
-@y changing ' ' to chr(i) here will allow all 8-bit characters to get in
-for i:=0 to @'37 do xchr[i]:=' ';
-for i:=@'177 to @'377 do xchr[i]:=' ';
-@z
-@x module 24
-for i:=1 to @'176 do xord[xchr[i]]:=i;
-@y
-for i:=@'200 to @'377 do xord[xchr[i]]:=i;
-for i:=0 to @'176 do xord[xchr[i]]:=i;
-@z
-@x module 38
-@<Types...@>=
-@!pool_pointer = 0..pool_size; {for variables that point into |str_pool|}
-@!str_number = 0..max_strings; {for variables that point into |str_start|}
-
-@ @<Glob...@>=
-@!str_pool:packed array[pool_pointer] of ASCII_code; {the characters}
-@y [OK to make si(#)==#-128 and so(#)==#+128 (without parens) in change files]
-Some \PASCAL\ compilers won't pack integers into a single byte unless the
-integers lie in the range |-128..127|. To accommodate such systems
-we access the string pool only via macros that can easily be redefined.
-
-@d si(#) == # {convert from |ASCII_code| to |packed_ASCII_code|}
-@d so(#) == # {convert from |packed_ASCII_code| to |ASCII_code|}
-
-@<Types...@>=
-@!pool_pointer = 0..pool_size; {for variables that point into |str_pool|}
-@!str_number = 0..max_strings; {for variables that point into |str_start|}
-@!packed_ASCII_code = 0..255; {elements of |str_pool| array}
-
-@ @<Glob...@>=
-@!str_pool:packed array[pool_pointer] of packed_ASCII_code; {the characters}
-@z
-@x module 42
-begin str_pool[pool_ptr]:=#; incr(pool_ptr);
-@y
-begin str_pool[pool_ptr]:=si(#); incr(pool_ptr);
-@z
-@x module 45
- begin if str_pool[j]<>buffer[k] then
-@y
- begin if so(str_pool[j])<>buffer[k] then
-@z
-@x module 47
-var k,@!l:0..127; {small indices or counters}
-@y
-var k,@!l:0..255; {small indices or counters}
-@z
-@x module 47
-@<Make the first 128 strings@>;
-@y
-@<Make the first 256 strings@>;
-@z
-@x module 48
-@ @<Make the first 128...@>=
-for k:=0 to 127 do
- begin if (@<Character |k| cannot be printed@>) then
- begin append_char("^"); append_char("^");
- if k<@'100 then append_char(k+@'100)
- else append_char(k-@'100);
-@y
-@ @d app_lc_hex(#)==l:=#;
- if l<10 then append_char(l+"0)@+else append_char(l-10+"a")
-
-@<Make the first 256...@>=
-for k:=0 to 255 do
- begin if (@<Character |k| cannot be printed@>) then
- begin append_char("^"); append_char("^");
- if k<@'100 then append_char(k+@'100)
- else if k<@'200 then append_char(k-@'100)
- else begin app_lc_hex(k div 16); app_lc_hex(k mod 16);
- end;
-@z
-@x module 59
- begin print_char(str_pool[j]); incr(j);
-@y
- begin print_char(so(str_pool[j])); incr(j);
-@z
-@x modules 59 and 60
-else if s<128 then
-@y
-else if s<256 then
-@z
-@x module 60
- begin print(str_pool[j]); incr(j);
-@y
- begin print(so(str_pool[j])); incr(j);
-@z
-@x module 63
-if c>=0 then if c<128 then print(c);
-@y
-if c>=0 then if c<256 then print(c);
-@z
-@x module 68
-@ In certain situations, \TeX\ prints either a standard visible ASCII
-character or its hexadecimal ASCII code.
-
-@p procedure print_ASCII(@!c:integer); {prints a character or its code}
-begin if (c>=0) and (c<=127) then print(c)
-else begin print_char("[");
- if c<0 then print_int(c)@+else print_hex(c);
- print_char("]");
- end;
-end;
-@y
-@ Old versions of \TeX\ needed a procedure called |print_ASCII| whose function
-is now subsumed by |print|. We retain the old name here as a possible aid to
-future software arch\ae ologists.
-
-@d print_ASCII == print
-@z
-@x module 69
- begin print_char(str_pool[j]); n:=n-v;
- end;
- if n<=0 then return; {nonpositive input produces no output}
- k:=j+2; u:=v div (str_pool[k-1]-"0");
- if str_pool[k-1]="2" then
- begin k:=k+2; u:=u div (str_pool[k-1]-"0");
- end;
- if n+u>=v then
- begin print_char(str_pool[k]); n:=n+u;
- end
- else begin j:=j+2; v:=v div (str_pool[j-1]-"0");
-@y
- begin print_char(so(str_pool[j])); n:=n-v;
- end;
- if n<=0 then return; {nonpositive input produces no output}
- k:=j+2; u:=v div (so(str_pool[k-1])-"0");
- if str_pool[k-1]=si("2") then
- begin k:=k+2; u:=u div (so(str_pool[k-1])-"0");
- end;
- if n+u>=v then
- begin print_char(so(str_pool[k])); n:=n+u;
- end
- else begin j:=j+2; v:=v div (so(str_pool[j-1])-"0");
-@z
-@x module 70
- begin print_char(str_pool[j]); incr(j);
-@y
- begin print_char(so(str_pool[j])); incr(j);
-@z
-@x module 222
-@d single_base=active_base+128 {equivalents of one-letter control sequences}
-@d null_cs=single_base+128 {equivalent of \.{\\csname\\endcsname}}
-@y
-@d single_base=active_base+256 {equivalents of one-character control sequences}
-@d null_cs=single_base+256 {equivalent of \.{\\csname\\endcsname}}
-@z
-@x module 230
- {table of 128 command codes (the ``catcodes'')}
-@d lc_code_base=cat_code_base+128 {table of 128 lowercase mappings}
-@d uc_code_base=lc_code_base+128 {table of 128 uppercase mappings}
-@d sf_code_base=uc_code_base+128 {table of 128 spacefactor mappings}
-@d math_code_base=sf_code_base+128 {table of 128 math mode mappings}
-@d int_base=math_code_base+128 {beginning of region 5}
-@y
- {table of 256 command codes (the ``catcodes'')}
-@d lc_code_base=cat_code_base+256 {table of 256 lowercase mappings}
-@d uc_code_base=lc_code_base+256 {table of 256 uppercase mappings}
-@d sf_code_base=uc_code_base+256 {table of 256 spacefactor mappings}
-@d math_code_base=sf_code_base+256 {table of 256 math mode mappings}
-@d int_base=math_code_base+256 {beginning of region 5}
-@z
-@x module 232
-for k:=0 to 127 do
-@y
-for k:=0 to 255 do
-@z
-@x module 236
-@d del_code_base=count_base+256 {128 delimiter code mappings}
-@d dimen_base=del_code_base+128 {beginning of region 6}
-@y
-@d del_code_base=count_base+256 {256 delimiter code mappings}
-@d dimen_base=del_code_base+256 {beginning of region 6}
-@z
-@x module 240
-for k:=0 to 127 do del_code(k):=-1;
-@y
-for k:=0 to 255 do del_code(k):=-1;
-@z
-@x module 264
-begin if s<128 then cur_val:=s+single_base
-@y
-begin if s<256 then cur_val:=s+single_base
-@z
-@x ibid
- for j:=0 to l-1 do buffer[j]:=str_pool[k+j];
-@y
- for j:=0 to l-1 do buffer[j]:=so(str_pool[k+j]);
-@z
-@x module 289
-@d cs_token_flag==@'10000 {amount added to the |eqtb| location in a
- token that stands for a control sequence; is a multiple of~256}
-@y
-@d cs_token_flag==@'7777 {amount added to the |eqtb| location in a
- token that stands for a control sequence; is a multiple of~256, less~1}
-@z
-@x module 293
- if (info(p)<0)or(c>127) then print_esc("BAD.")
-@y
- if info(p)<0 then print_esc("BAD.")
-@z
-@x module 341
-@!cat:0..15; {|cat_code(cur_chr)|, usually}
-@y
-@!cat:0..15; {|cat_code(cur_chr)|, usually}
-@!c,@!cc:ASCII_code; {constituents of a possible expanded code}
-@!d:2..3; {number of excess characters in an expanded code}
-@z
-@x module 352
-@<If this |sup_mark| starts a control character...@>=
-begin if (cur_chr=buffer[loc])and(loc<limit) then
- begin if buffer[loc+1]<@'100 then cur_chr:=buffer[loc+1]+@'100
- else cur_chr:=buffer[loc+1]-@'100;
- loc:=loc+2; goto reswitch;
- end;
-@y
-@ Notice that a code like \.{\^\^8} becomes \.x if not followed by a hex digit.
-
-@d is_hex(#)==(((#>="0")and(#<="9"))or((#>="a")and(#<="f")))
-@d hex_to_cur_chr==
- if c<="9" then cur_chr:=c-"0" @+else cur_chr:=c-"a"+10;
- if cc<="9" then cur_chr:=16*cur_chr+cc-"0"
- else cur_chr:=16*cur_chr+cc-"a"+10
-
-@<If this |sup_mark| starts an expanded character...@>=
-begin if cur_chr=buffer[loc] then if loc<limit then
- begin c:=buffer[loc+1]; @+if c<@'200 then {yes we have an expanded char}
- begin loc:=loc+2;
- if is_hex(c) then if loc<=limit then
- begin cc:=buffer[loc]; @+if is_hex(cc) then
- begin incr(loc); hex_to_cur_chr; goto reswitch;
- end;
- end;
- if c<@'100 then cur_chr:=c+@'100 @+else cur_chr:=c-@'100;
- goto reswitch;
- end;
- end;
-@z
-@x module 355
- begin cur_chr:=buffer[k+1];
- if cur_chr<@'100 then buffer[k-1]:=cur_chr+@'100
- else buffer[k-1]:=cur_chr-@'100;
- limit:=limit-2; first:=first-2;
- while k<=limit do
- begin buffer[k]:=buffer[k+2]; incr(k);
- end;
- goto start_cs;
- end;
-@y
-begin c:=buffer[k+1]; @+if c<@'200 then {yes, one is indeed present}
- begin d:=2;
- if is_hex(c) then @+if k+2<=limit then
- begin cc:=buffer[k+2]; @+if is_hex(cc) then incr(d);
- end;
- if d>2 then
- begin hex_to_cur_chr; buffer[k-1]:=cur_chr;
- end
- else if c<@'100 then buffer[k-1]:=c+@'100
- else buffer[k-1]:=c-@'100;
- limit:=limit-d; first:=first-d;
- while k<=limit do
- begin buffer[k]:=buffer[k+d]; incr(k);
- end;
- goto start_cs;
- end;
- end;
-@z
-@x module 360
-There is one more branch.
-@y
-There is one more branch.
-
-@d end_line_char_inactive == (end_line_char<0)or(end_line_char>255)
-@z
-@x ibid
- if (end_line_char<0)or(end_line_char>127) then decr(limit)
-@y
- if end_line_char_inactive then decr(limit)
-@z
-@x modules 362 and 483 and 538 and 1337
-if (end_line_char<0)or(end_line_char>127) then decr(limit)
-@y
-if end_line_char_inactive then decr(limit)
-@z
-@x module 391
-if (info(r)>match_token+127)or(info(r)<match_token) then s:=null
-@y
-if (info(r)>match_token+255)or(info(r)<match_token) then s:=null
-@z
-@x module 407
- ((cur_chr=str_pool[k])or(cur_chr=str_pool[k]-"a"+"A")) then
-@y
- ((cur_chr=so(str_pool[k]))or(cur_chr=so(str_pool[k])-"a"+"A")) then
-@z
-@x module 414
-begin scan_seven_bit_int;
-@y
-begin scan_char_num;
-@z
-@x module 432
-|scan_something_internal|:
-
-@<Declare procedures that scan restricted classes of integers@>=
-procedure scan_seven_bit_int;
-begin scan_int;
-if (cur_val<0)or(cur_val>127) then
- begin print_err("Bad character code");
-@.Bad character code@>
- help2("The numeric code for a character must be between 0 and 127.")@/
- ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
- end;
-end;
-@y
-|scan_something_internal|.
-@z (and I'll interchange modules 434 and 435)
-@x module 442
-if cur_val>127 then
-@y
-if cur_val>255 then
-@z
-@x module 464
- begin t:=str_pool[k];
-@y
- begin t:=so(str_pool[k]);
-@z
-@x module 506 (correction needed twice)
-if (cur_cmd>active_char)or(cur_chr>127) then
-@y
-if (cur_cmd>active_char)or(cur_chr>255) then
-@z
-@x module 519
-for j:=str_start[a] to str_start[a+1]-1 do append_to_name(str_pool[j]);
-for j:=str_start[n] to str_start[n+1]-1 do append_to_name(str_pool[j]);
-for j:=str_start[e] to str_start[e+1]-1 do append_to_name(str_pool[j]);
-@y
-for j:=str_start[a] to str_start[a+1]-1 do append_to_name(so(str_pool[j]));
-for j:=str_start[n] to str_start[n+1]-1 do append_to_name(so(str_pool[j]));
-for j:=str_start[e] to str_start[e+1]-1 do append_to_name(so(str_pool[j]));
-@z
-@x module 526
-if (cur_cmd>active_char)or(cur_chr>127) then
-@y
-if (cur_cmd>active_char)or(cur_chr>255) then
-@z
-@x module 603 (change to be made twice)
- dvi_out(str_pool[k]);
-@y
- dvi_out(so(str_pool[k]));
-@z
-@x module 617
- for s:=str_start[str_ptr] to pool_ptr-1 do dvi_out(str_pool[s]);
-@y
- for s:=str_start[str_ptr] to pool_ptr-1 do dvi_out(so(str_pool[s]));
-@z
-@x module 766
- begin case str_pool[r_type*8+t+magic_offset] of
-@y
- begin case so(str_pool[r_type*8+t+magic_offset]) of
-@z
-@x module 780
-@d span_code=128 {distinct from any character}
-@d cr_code=129 {distinct from |span_code| and from any character}
-@y
-@d span_code=256 {distinct from any character}
-@d cr_code=257 {distinct from |span_code| and from any character}
-@z
-@x module 815
-label done,done1,done2,done3,done4;
-@y
-label done,done1,done2,done3,done4,continue;
-@z
-@x module 896
- else if (type(s)=kern_node)and(subtype(s)=normal) then c:=128
- else if type(s)=whatsit_node then c:=128
- else goto done1;
- if c<128 then if lc_code(c)<>0 then
- if (lc_code(c)=c)or(uc_hyph>0) then goto done2
- else goto done1;
- s:=link(s);
-@y
- else if (type(s)=kern_node)and(subtype(s)=normal) then goto continue
- else if type(s)=whatsit_node then goto continue
- else goto done1;
- if lc_code(c)<>0 then
- if (lc_code(c)=c)or(uc_hyph>0) then goto done2
- else goto done1;
-continue: s:=link(s);
-@z
-@x module 897
- if c>=128 then goto done3;
- if (lc_code(c)=0)or(hn=63) then goto done3;
- hb:=s; incr(hn); hu[hn]:=c; hc[hn]:=lc_code(c)-1;
-@y
- if lc_code(c)=0 then goto done3;
- if hn=63 then goto done3;
- hb:=s; incr(hn); hu[hn]:=c; hc[hn]:=lc_code(c);
-@z
-@x module 898
-if c>=128 then goto done3;
-if (lc_code(c)=0)or(j=63) then goto done3;
-incr(j); hu[j]:=c; hc[j]:=lc_code(c)-1;@/
-@y
-if lc_code(c)=0 then goto done3;
-if j=63 then goto done3;
-incr(j); hu[j]:=c; hc[j]:=lc_code(c);@/
-@z
-@x module 923
-hc[0]:=127; hc[hn+1]:=127; hc[hn+2]:=128; {insert delimiters}
-@y
-hc[0]:=0; hc[hn+1]:=0; hc[hn+2]:=256; {insert delimiters}
-@z
-@x ibid
- while hc[l]=trie_char(z) do
-@y
- while hc[l]=qo(trie_char(z)) do
-@z
-@x module 931
- repeat if str_pool[u]<hc[j] then goto not_found;
- if str_pool[u]>hc[j] then goto done;
-@y
- repeat if so(str_pool[u])<hc[j] then goto not_found;
- if so(str_pool[u])>hc[j] then goto done;
-@z
-@x module 937
-else begin if (cur_chr>127)or(lc_code(cur_chr)=0) then
-@y
-else begin if lc_code(cur_chr)=0 then
-@z
-@x ibid
- begin incr(n); hc[n]:=lc_code(cur_chr)-1;
-@y
- begin incr(n); hc[n]:=lc_code(cur_chr);
-@z
-@x module 945
-@!init @!trie_c:packed array[trie_pointer] of ASCII_code; {characters to match}
-@y
-@!init @!trie_c:packed array[trie_pointer] of packed_ASCII_code;
- {characters to match}
-@z
-% In modules 951--954, change "127" to "255" and "128" to "256"
-@x module 952
-trie_link(0):=0; trie_char(0):=0; trie_op(0):=min_quarterword;
-@y
-trie_link(0):=0; trie_char(0):=min_quarterword; trie_op(0):=min_quarterword;
-@z
-@x module 953
-begin c:=trie_c[p];
-@y
-begin c:=so(trie_c[p]);
-@z
-@x module 955
- begin if trie_link(h+trie_c[q])=0 then goto not_found;
-@y
- begin if trie_link(h+so(trie_c[q]))=0 then goto not_found;
-@z
-@x module 956
-repeat z:=h+trie_c[q]; trie_back(trie_link(z)):=trie_back(z);
-@y
-repeat z:=h+so(trie_c[q]); trie_back(trie_link(z)):=trie_back(z);
-@z
-@x module 959
- begin q:=trie_l[p]; c:=trie_c[p];
- trie_link(z+c):=trie_ref[q]; trie_char(z+c):=c; trie_op(z+c):=trie_o[p];
-@y
- begin q:=trie_l[p]; c:=so(trie_c[p]);
- trie_link(z+c):=trie_ref[q]; trie_char(z+c):=qi(c); trie_op(z+c):=trie_o[p];
-@z
-@x module 962
- begin if cur_chr="." then cur_chr:=128 {edge-of-word delimiter}
- else begin cur_chr:=lc_code(cur_chr);
- if cur_chr=0 then
- begin print_err("Nonletter");
-@.Nonletter@>
- help1("(See Appendix H.)"); error; cur_chr:=128;
- end;
- end;
- if k<63 then
- begin incr(k); hc[k]:=cur_chr-1; hyf[k]:=0; digit_sensed:=false;
- end;
- end
-else begin hyf[k]:=cur_chr-"0";
- if k<63 then digit_sensed:=true;
- end
-@y
- begin if cur_chr="." then cur_chr:=0 {edge-of-word delimiter}
- else begin cur_chr:=lc_code(cur_chr);
- if cur_chr=0 then
- begin print_err("Nonletter");
-@.Nonletter@>
- help1("(See Appendix H.)"); error;
- end;
- end;
- if k<63 then
- begin incr(k); hc[k]:=cur_chr; hyf[k]:=0; digit_sensed:=false;
- end;
- end
- else if k<63 then
- begin hyf[k]:=cur_chr-"0"; digit_sensed:=true;
- end;
- end
-@z
-@x module 963
- while (p>0)and(c>trie_c[p]) do
-@y
- while (p>0)and(c>so(trie_c[p])) do
-@z
-@x ibid
- if (p=0)or(c<trie_c[p]) then
-@y
- if (p=0)or(c<so(trie_c[p])) then
-@z
-@x module 964
-trie_c[p]:=c; trie_o[p]:=min_quarterword;
-@y
-trie_c[p]:=si(c); trie_o[p]:=min_quarterword;
-@z
-@x module 965
-if hc[1]=127 then hyf[0]:=0;
-if hc[k]=127 then hyf[k]:=0;
-@y
-if hc[1]=0 then hyf[0]:=0;
-if hc[k]=0 then hyf[k]:=0;
-@z
-@x module 966
-h.rh:=0; h.b0:=min_quarterword; h.b1:=0; {|trie_link:=0|,
- |trie_op:=min_quarterword|, |trie_char:=0|}
-@y
-h.rh:=0; h.b0:=min_quarterword; h.b1:=min_quarterword; {|trie_link:=0|,
- |trie_op:=min_quarterword|, |trie_char:=qi(0)|}
-@z
-@x module 1034
-if c<128 then
-@y
-@z
-@x ibid
-else space_factor:=1000
-@y
-@z
-@x module 1151
-letter,other_char,char_given: if cur_chr>=128 then c:=cur_chr
- else begin c:=ho(math_code(cur_chr));
-@y
-letter,other_char,char_given: begin c:=ho(math_code(cur_chr));
-@z
-@x module 1154
-mmode+letter,mmode+other_char,mmode+char_given: if cur_chr<128 then
- set_math_char(ho(math_code(cur_chr)))
- else set_math_char(cur_chr);
-mmode+char_num: begin scan_char_num; cur_chr:=cur_val;
- if cur_chr<128 then set_math_char(ho(math_code(cur_chr)))
- else set_math_char(cur_chr);
-@y
-mmode+letter,mmode+other_char,mmode+char_given:
- set_math_char(ho(math_code(cur_chr)));
-mmode+char_num: begin scan_char_num; cur_chr:=cur_val;
- set_math_char(ho(math_code(cur_chr)));
-@z
-@x module 1232
- p:=cur_chr; scan_seven_bit_int; p:=p+cur_val; scan_optional_equals;
-@y
- p:=cur_chr; scan_char_num; p:=p+cur_val; scan_optional_equals;
-@z
-@x module 1233
-else n:=127
-@y
-else n:=255
-@z
-@x module 1289
- begin if t>=cs_token_flag then t:=t-active_base;
- c:=t mod 256;
- if c<128 then if equiv(b+c)<>0 then t:=256*(t div 256)+equiv(b+c);
- if t>=cs_token_flag then info(p):=t+active_base
- else info(p):=t;
-@y
- begin c:=t mod 256;
- if equiv(b+c)<>0 then info(p):=t-c+equiv(b+c);
-@z
-@x module 1309
- w.b0:=str_pool[k]; w.b1:=str_pool[k+1];
- w.b2:=str_pool[k+2]; w.b3:=str_pool[k+3];
-@y [often qi(so(x))=x, but not e.g. when "quarterwords" are two bytes]
- w.b0:=qi(so(str_pool[k])); w.b1:=qi(so(str_pool[k+1]));
- w.b2:=qi(so(str_pool[k+2])); w.b3:=qi(so(str_pool[k+3]));
-@z
-@x module 1310
- str_pool[k]:=w.b0; str_pool[k+1]:=w.b1;
- str_pool[k+2]:=w.b2; str_pool[k+3]:=w.b3
-@y
- str_pool[k]:=si(qo(w.b0)); str_pool[k+1]:=si(qo(w.b1));
- str_pool[k+2]:=si(qo(w.b2)); str_pool[k+3]:=si(qo(w.b3))
-@z
-@x module 1368
-for k:=str_start[str_ptr] to pool_ptr-1 do dvi_out(str_pool[k]);
-@y
-for k:=str_start[str_ptr] to pool_ptr-1 do dvi_out(so(str_pool[k]));
-@z
-
-360. Major change to allow multiple hyphenation tables.
-I've combined this with the code for a minor change:
-361. New parameters \lefthyphenmin and \righthyphenmin.
-@x module 11 (affects most change files!)
-@!trie_size=8000; {space for hyphenation patterns; should be larger for
- \.{INITEX} than it is in production versions of \TeX}
-@y
-@!trie_size=8000; {space for hyphenation patterns; should be larger for
- \.{INITEX} than it is in production versions of \TeX}
-@!trie_op_size=500; {space for ``opcodes'' in the hyphenation patterns}
-@z
-@x module 212
-known as |space_factor|; it holds the current space factor used in spacing
-calculations. In math mode, |aux| is also known as |incompleat_noad|; if
-@y
-known as |space_factor| and |clang|; it holds the current space factor used in
-spacing calculations, and the current language used for hyphenation.
-(The value of |clang| is undefined in restricted horizontal mode.)
-In math mode, |aux| is also known as |incompleat_noad|; if
-@z
-@x ibid
- @!pg_field,@!aux_field,@!ml_field: integer;
-@y
- @!pg_field,@!ml_field: integer;
- @!aux_field: memory_word;
-@z
-@x module 213
-@d prev_depth==aux {the name of |aux| in vertical mode}
-@d space_factor==aux {the name of |aux| in horizontal mode}
-@d incompleat_noad==aux {the name of |aux| in math mode}
-@y
-@d prev_depth==aux.sc {the name of |aux| in vertical mode}
-@d space_factor==aux.hh.lh {part of |aux| in horizontal mode}
-@d clang==aux.hh.rh {the other part of |aux| in horizontal mode}
-@d incompleat_noad==aux.int {the name of |aux| in math mode}
-@z
-@x module 218
-@!a:integer; {auxiliary}
-@y
-@!a:memory_word; {auxiliary}
-@z
-@x module 219
- if a<=ignore_depth then print("ignored")
- else print_scaled(a);
- if nest[p].pg_field<>0 then
- begin print(", prevgraf ");
- print_int(nest[p].pg_field); print(" line");
- if nest[p].pg_field<>1 then print_char("s");
- end;
- end;
-1: begin print_nl("spacefactor "); print_int(a);
- end;
-2: if a<>null then
- begin print("this will be denominator of:"); show_box(a);
-@y
- if a.sc<=ignore_depth then print("ignored")
- else print_scaled(a.sc);
- if nest[p].pg_field<>0 then
- begin print(", prevgraf ");
- print_int(nest[p].pg_field); print(" line");
- if nest[p].pg_field<>1 then print_char("s");
- end;
- end;
-1: begin print_nl("spacefactor "); print_int(a.hh.lh);
- if m>0 then if a.hh.rh>0 then
- begin print(", current language "); print_int(a.hh.rh);
- end;
- end;
-2: if a.int<>null then
- begin print("this will be denominator of:"); show_box(a.int);
-@z
-@x modules 236--238
-@d int_pars=50 {total number of integer parameters}
-@y
-@d language_code=50 {current hyphenation table}
-@d left_hyphen_min_code=51 {minimum left hyphenation fragment size}
-@d right_hyphen_min_code=52 {minimum right hyphenation fragment size}
-@d int_pars=53 {total number of integer parameters}
-@z and define/print these new parameters appropriately (mimicking new_line_char)
-@x module 418
-else begin cur_val:=aux;
- if m=vmode then cur_val_level:=dimen_val@+else cur_val_level:=int_val;
- end
-@y
-else if m=vmode then
- begin cur_val:=prev_depth; cur_val_level:=dimen_val;
- end
-else begin cur_val:=space_factor; cur_val_level:=int_val;
- end
-@z
-@x module 775
- begin mode:=-vmode; prev_depth:=nest[nest_ptr-2].aux_field;
-@y
- begin mode:=-vmode; prev_depth:=nest[nest_ptr-2].aux_field.sc;
-@z
-@x module 786
-begin push_nest; mode:=(-hmode-vmode)-mode; aux:=0;
-@y
-begin push_nest; mode:=(-hmode-vmode)-mode;
-if mode=-hmode then space_factor:=0 @+else prev_depth:=0;
-@z
-@x module 863
-loop@+ begin @<Create an active breakpoint representing the beginning of
- the paragraph@>;
-@y
-loop@+ begin if threshold>inf_bad then threshold:=inf_bad;
- if second_pass then @<Initialize for hyphenating a paragraph@>;
- @<Create an active breakpoint representing the beginning of the paragraph@>;
-@z
-@x module 891
-passes on only about 5 per cent of the paragraphs.
-@y
-passes on only about 5 per cent of the paragraphs.
-
-@<Initialize for hyphenating...@>=
-begin @!init if trie_not_ready then init_trie; @+tini@;@/
-l_hyf:=left_hyphen_min-1;@+if l_hyf<0 then l_hyf:=0;
-r_hyf:=right_hyphen_min-1;@+if r_hyf<0 then r_hyf:=0;
-min_hyf:=l_hyf+r_hyf+2; cur_lang:=0;
-end
-@z
-@x module 892
-@!hyf_char:integer; {hyphen character of the relevant font}
-@y
-@!hyf_char:integer; {hyphen character of the relevant font}
-@!cur_lang:ASCII_code; {current hyphenation table of interest}
-@!l_hyf,@!r_hyf,@!min_hyf:integer; {limits on fragment sizes}
-@z
-@x module 894
-begin s:=link(cur_p);
-@y
-begin if min_hyf>63 then goto done1;
-s:=link(cur_p);
-@z
-@x module 896
- else if type(s)=whatsit_node then goto continue
-@y
- else if type(s)=whatsit_node then
- begin @<Advance \(p)past a whatsit node in the \(p)pre-hyphenation loop@>;
- goto continue;
- end
-@z
-@x module 899 (title of this module also changes appropriately)
-if hn<5 then goto done1;
-@y
-if hn<min_hyf then goto done1;
-@z
-@x module 902
-for j:=2 to hn-3 do if odd(hyf[j]) then goto found1;
-@y
-for j:=l_hyf+1 to hn-r_hyf-1 do if odd(hyf[j]) then goto found1;
-@z
-@x module 920
-$p_1\ldots p_k$ by setting |@t$z_1$@>:=@t$p_1$@>| and then, for |1<i<=k|,
-@y
-$p_1\ldots p_k$ by letting $z_0$ be one greater than the relevant language index
-and then, for |1<=i<=k|,
-@z
-@x ibid
-the letters in |hc[(l-k+1)..l@,]|, we perform all of the required operations
-for this pattern by carrying out the following little program: Set
-|v:=trie_op(@t$z_k$@>)|. Then set |hyf[l-hyf_distance[v]]:=@tmax@>(
-hyf[l-hyf_distance[v]], hyf_num[v])|, and |v:=hyf_next[v]|; repeat, if
-necessary, until |v=min_quarterword|.
-@y
-the letters in |hc[(l-k+1)..l@,]| of language |t|,
-we perform all of the required operations
-for this pattern by carrying out the following little program: Set
-|v:=trie_op(@t$z_k$@>)|. Then set |v:=v+op_start[t]|,
-|hyf[l-hyf_distance[v]]:=@tmax@>(hyf[l-hyf_distance[v]], hyf_num[v])|,
-and |v:=hyf_next[v]|; repeat, if necessary, until |v=min_quarterword|.
-@z
-@x module 921
-@!hyf_distance:array[quarterword] of small_number; {position |k-j| of $n_j$}
-@!hyf_num:array[quarterword] of small_number; {value of $n_j$}
-@!hyf_next:array[quarterword] of quarterword; {continuation of this |trie_op|}
-@y
-@!hyf_distance:array[1..trie_op_size] of small_number; {position |k-j| of $n_j$}
-@!hyf_num:array[1..trie_op_size] of small_number; {value of $n_j$}
-@!hyf_next:array[1..trie_op_size] of quarterword; {continuation code}
-@!op_start:array[ASCII_code] of 0..trie_op_size; {offset for current language}
-@z
-@x module 922
-@!v:quarterword; {an index into |hyf_distance|, etc.}
-@y
-@!v:integer; {an index into |hyf_distance|, etc.}
-@z
-@x module 923
-for j:=0 to hn-2 do
- begin z:=hc[j]; l:=j;
-@y
-if trie_char(cur_lang+1)<>qi(cur_lang) then return; {no patterns for |cur_lang|}
-for j:=0 to hn-r_hyf do
- begin z:=trie_link(cur_lang+1)+hc[j]; l:=j;
-@z
-@x ibid
-found: hyf[1]:=0; hyf[hn-2]:=0; hyf[hn-1]:=0; hyf[hn]:=0
-@y
-found: for j:=0 to l_hyf do hyf[j]:=0;
-for j:=0 to r_hyf do hyf[hn-j]:=0
-@z
-@x module 924
-repeat i:=l-hyf_distance[v];
-@y
-repeat v:=v+op_start[cur_lang]; i:=l-hyf_distance[v];
-@z
-@x module 930
-h:=hc[1];
-@y
-h:=hc[1]; incr(hn); hc[hn]:=cur_lang;
-@z
-@x ibid
-not_found:
-@y
-not_found: decr(hn)
-@z
-@x module 931
- goto found;
-@y
- decr(hn); goto found;
-@z
-@x module 934
-@p procedure new_hyph_exceptions; {enters new exceptions}
-label reswitch, exit, found, not_found, done;
-@y
-@d set_cur_lang==if language<=0 then cur_lang:=0
- else if language>255 then cur_lang:=0
- else cur_lang:=language
-
-@p procedure new_hyph_exceptions; {enters new exceptions}
-label reswitch, exit, found, not_found;
-@z
-@x ibid
-begin scan_left_brace; {a left brace must follow \.{\\hyphenation}}
-@y
-begin scan_left_brace; {a left brace must follow \.{\\hyphenation}}
-set_cur_lang;
-@z
-@x module 935
- spacer,right_brace: begin if n>4 then @<Enter a hyphenation exception@>;
-@y
- spacer,right_brace: begin if n>1 then @<Enter a hyphenation exception@>;
-@z
-@x module 938
-begin if n>1 then
-@y
-begin if n<63 then
-@z
-@x module 939
-begin str_room(n); h:=0;
-@y
-begin incr(n); hc[n]:=cur_lang; str_room(n); h:=0;
-@z
-@x ibid
-loop@+ begin if p=null then goto done;
- if info(p)<n-2 then goto done;
- q:=link(p); free_avail(p); p:=q; {eliminate hyphens that \TeX\ doesn't like}
- end;
-done: @<Insert the \(p)pair |(s,p)| into the exception table@>;
-@y
-@<Insert the \(p)pair |(s,p)| into the exception table@>;
-@z
-@x module 942
-@p@!init @<Declare procedures for preprocessing hyphenation patterns@>@;
-@y
-@<Declare subprocedures for |line_break|@>=
-@!init @<Declare procedures for preprocessing hyphenation patterns@>@;
-@z
-@x module 943
-@d quarterword_diff=max_quarterword-min_quarterword
-@d trie_op_hash_size=quarterword_diff+quarterword_diff {double}
-
-@<Glob...@>=
-@!init@! trie_op_hash:array[0..trie_op_hash_size] of quarterword;
- {trie op codes for triples}
-tini@;@/
-@t\hskip1em@>@!trie_op_ptr:quarterword; {highest |trie_op| assigned}
-@y
-@<Glob...@>=
-@!init@! trie_op_hash:array[-trie_op_size..trie_op_size] of 0..trie_op_size;
- {trie op codes for quadruples}
-@!trie_used:array[ASCII_code] of quarterword;
- {largest opcode used so far for this language}
-@!trie_op_lang:array[1..trie_op_size] of ASCII_code;
- {language part of a hashed quadruple}
-@!trie_op_val:array[1..trie_op_size] of quarterword;
- {opcode corresponding to a hashed quadruple}
-@!trie_op_ptr:0..trie_op_size; {number of stored ops so far}
-tini
-@z
-@x module 944 should be entirely replaced
-@y by the following code:
-@ It's tempting to remove the |overflow| stops in the following procedure;
-|new_trie_op| could return |min_quarterword| (thereby simply ignoring
-part of a hyphenation pattern) instead of aborting the job. However, that would
-lead to different hyphenation results on different installations of \TeX\
-using the same patterns. The |overflow| stops are necessary for portability
-of patterns.
-
-@<Declare procedures for preprocessing hyph...@>=
-function new_trie_op(@!d,@!n:small_number;@!v:quarterword):quarterword;
-label exit;
-var h:-trie_op_size..trie_op_size; {trial hash location}
-@!u:quarterword; {trial op code}
-@!l:0..trie_op_size; {pointer to stored data}
-begin h:=abs(n+313*d+361*v+1009*cur_lang) mod (trie_op_size+trie_op_size)
- - trie_op_size;
-loop@+ begin l:=trie_op_hash[h];
- if l=0 then {empty position found for a new op}
- begin if trie_op_ptr=trie_op_size then
- overflow("pattern memory ops",trie_op_size);
- u:=trie_used[cur_lang];
- if u=max_quarterword then
- overflow("pattern memory ops per language",
- max_quarterword-min_quarterword);
- incr(trie_op_ptr); incr(u); trie_used[cur_lang]:=u;
- hyf_distance[trie_op_ptr]:=d;
- hyf_num[trie_op_ptr]:=n; hyf_next[trie_op_ptr]:=v;
- trie_op_lang[trie_op_ptr]:=cur_lang; trie_op_hash[h]:=trie_op_ptr;
- trie_op_val[trie_op_ptr]:=u; new_trie_op:=u; return;
- end;
- if (hyf_distance[l]=d)and(hyf_num[l]=n)and(hyf_next[l]=v)
- and(trie_op_lang[l]=cur_lang) then
- begin new_trie_op:=trie_op_val[l]; return;
- end;
- if h>-trie_op_size then decr(h)@+else h:=trie_op_size;
- end;
-exit:end;
-@z
-@x module 945: move the code from this module into 946, and introduce new code:
-@y
-@ After |new_trie_op| has compressed the necessary opcode information,
-plenty of information is available to unscramble the data into the
-final form needed by our hyphenation algorithm.
-
-@<Sort the hyphenation op tables into proper order@>=
-op_start[0]:=-min_quarterword;
-for j:=1 to 255 do op_start[j]:=op_start[j-1]+qo(trie_used[j-1]);
-for j:=1 to trie_op_ptr do
- trie_op_hash[j]:=op_start[trie_op_lang[j]]+trie_op_val[j]; {destination}
-for j:=1 to trie_op_ptr do while trie_op_hash[j]>j do
- begin k:=trie_op_hash[j];@/
- t:=hyf_distance[k]; hyf_distance[k]:=hyf_distance[j]; hyf_distance[j]:=t;@/
- t:=hyf_num[k]; hyf_num[k]:=hyf_num[j]; hyf_num[j]:=t;@/
- t:=hyf_next[k]; hyf_next[k]:=hyf_next[j]; hyf_next[j]:=t;@/
- trie_op_hash[j]:=trie_op_hash[k]; trie_op_hash[k]:=k;
- end
-@z
-@x module 949: Move this code to just after the new module 945!
-mentioned so far, let's write a procedure that does the initialization.
-
-@<Declare procedures for preprocessing hyph...@>=
-procedure init_pattern_memory; {gets ready to build a linked trie}
-var h:0..trie_op_hash_size; {an index into |trie_op_hash|}
-@!p:trie_pointer; {an index into |trie_hash|}
-begin for h:=0 to trie_op_hash_size do trie_op_hash[h]:=min_quarterword;
-trie_op_ptr:=min_quarterword; trie_root:=0; trie_c[0]:=0; trie_ptr:=0;
-for p:=0 to trie_size do trie_hash[p]:=0;
-end;
-@y
-mentioned so far, let's write down the code that gets them started.
-
-@<Initialize table entries...@>=
-for k:=-trie_op_size to trie_op_size do trie_op_hash[k]:=0;
-for k:=0 to 255 do trie_used[k]:=min_quarterword;
-trie_op_ptr:=0;
-@z
-@x module 950
-@t\hskip1em@>@!trie_min:trie_pointer;
- {all locations |<=trie_min| are vacant in |trie|}
-tini@;@/
-@t\hskip1em@>@!trie_max:trie_pointer; {largest location used in |trie|}
-@y
-@t\hskip10pt@>@!trie_min:array[ASCII_code] of trie_pointer;
- {the first possible slot for each character}
-@t\hskip10pt@>@!trie_max:trie_pointer; {largest location used in |trie|}
-@t\hskip10pt@>@!trie_not_ready:boolean; {is the trie still in linked form?}
-tini
-@z
-@x modules 951 and 952
-@ Here is how these data structures are initialized.
-
-@<Declare procedures for preprocessing hyph...@>=
-procedure init_trie_memory; {gets ready to pack into |trie|}
-var p:trie_pointer; {index into |trie_ref|, |trie|, |trie_taken|}
-begin for p:=0 to trie_ptr do trie_ref[p]:=0;
-trie_max:=256; trie_min:=256; trie_link(0):=1; trie_taken[0]:=false;
-trie_link(trie_size):=0; trie_back(0):=trie_size; {wrap around}
-for p:=1 to 256 do
- begin trie_back(p):=p-1; trie_link(p):=p+1; trie_taken[p]:=false;
- end;
-end;
-
-@ Each time \.{\\patterns} appears, it overrides any patterns that were
-entered earlier, so the arrays are not initialized until \TeX\ sees
-\.{\\patterns}. However, some of the global variables must be
-initialized when \.{INITEX} is loaded, in case the user never mentions
-any \.{\\patterns}.
-
-@<Initialize table entries...@>=
-trie_op_ptr:=min_quarterword;@/
-trie_link(0):=0; trie_char(0):=min_quarterword; trie_op(0):=min_quarterword;
-for k:=1 to 255 do trie[k]:=trie[0];
-trie_max:=255;
-@y
-@ Each time \.{\\patterns} appears, it contributes further patterns to
-the future trie, which will be built only when hyphenation is attempted or
-when a format file is dumped. The boolean variable |trie_not_ready|
-will change to |false| when the trie is compressed; this will disable
-further patterns.
-
-@<Initialize table entries...@>=
-trie_not_ready:=true; trie_root:=0; trie_c[0]:=si(0); trie_ptr:=0;
-
-@ Here is how the trie-compression data structures are initialized.
-If storage is tight, it would be possible to overlap |trie_op_hash|,
-|trie_op_lang|, and |trie_op_val| with |trie|, |trie_hash|, and |trie_taken|,
-because we finish with the former just before we need the latter.
-
-@<Get ready to compress the trie@>=
-@<Sort the hyphenation...@>;
-for p:=0 to trie_size do trie_hash[p]:=0;
-trie_root:=compress_trie(trie_root); {identify equivalent subtries}
-for p:=0 to trie_ptr do trie_ref[p]:=0;
-for p:=0 to 255 do trie_min[p]:=p+1;
-trie_link(0):=1; trie_max:=0
-@z
-@x module 953
-begin c:=so(trie_c[p]);
-if c<trie_min then trie_min:=c;
-if trie_min=0 then z:=trie_link(trie_size)
-else z:=trie_link(trie_min-1); {get the first conceivably good hole}
-loop@+ begin if z<c then goto not_found;
- h:=z-c;@/
-@y
-@!l,@!r:trie_pointer; {left and right neighbors}
-@!ll:1..256; {upper limit of |trie_min| updating}
-begin c:=so(trie_c[p]);
-z:=trie_min[c]; {get the first conceivably good hole}
-loop@+ begin h:=z-c;@/
-@z
-@x module 956
-repeat z:=h+so(trie_c[q]); trie_back(trie_link(z)):=trie_back(z);
-trie_link(trie_back(z)):=trie_link(z); trie_link(z):=0; q:=trie_r[q];
-@y
-repeat z:=h+so(trie_c[q]); l:=trie_back(z); r:=trie_link(z);
-trie_back(r):=l; trie_link(l):=r; trie_link(z):=0;
-if l<256 then
- begin if z<256 then ll:=z @+else ll:=256;
- repeat trie_min[l]:=r; incr(l);
- until l=ll;
- end;
-q:=trie_r[q];
-@z
-@x module 958 is entirely replaced
-@y by the following new code:
-@ When the whole trie has been allocated into the sequential table, we
-must go through it once again so that |trie| contains the correct
-information. Null pointers in the linked trie will be represented by the
-value~0, which properly implements an ``empty'' family.
-
-@<Move the data into |trie|@>=
-h.rh:=0; h.b0:=min_quarterword; h.b1:=min_quarterword; {|trie_link:=0|,
- |trie_op:=min_quarterword|, |trie_char:=qi(0)|}
-if trie_root=0 then {no patterns were given}
- begin for r:=0 to 256 do trie[r]:=h;
- trie_max:=256;
- end
-else begin trie_fix(trie_root); {this fixes the non-holes in |trie|}
- r:=0; {now we will zero out all the holes}
- repeat s:=trie_link(r); trie[r]:=h; r:=s;
- until r>trie_max;
- end;
-trie_char(0):=qi("?"); {make |trie_char(c)<>c| for all |c|}
-@z
-@x module 960
-@!r,@!s:trie_pointer; {used to clean up the packed |trie|}
-@!h:two_halves; {template used to zero out |trie|'s holes}
-begin scan_left_brace; {a left brace must follow \.{\\patterns}}
-init_pattern_memory;@/
-@<Enter all of the patterns into a linked trie, until coming to a right
- brace@>;
-trie_root:=compress_trie(trie_root); {compress the trie}
-@<Pack the trie@>;
-end;
-@y
-begin if trie_not_ready then
- begin set_cur_lang; scan_left_brace; {a left brace must follow \.{\\patterns}}
- @<Enter all of the patterns into a linked trie, until coming to a right
- brace@>;
- end
-else begin print_err("Too late for "); print_esc("patterns");
- help1("All patterns must be given before typesetting begins.");
- error; link(garbage):=scan_toks(false,false); flush_list(def_ref);
- end;
-end;
-@z
-@x module 963
-q:=0;
-while l<k do
- begin incr(l); c:=hc[l]; p:=trie_l[q]; first_child:=true;
-@y
-q:=0; hc[0]:=cur_lang;
-while l<=k do
- begin c:=hc[l]; incr(l); p:=trie_l[q]; first_child:=true;
-@z
-@x module 966 now says that the first call ``takes'' location 1,
-@y and the Pascal code in this module is entirely replaced by the following:
-@<Declare procedures for preprocessing hyphenation patterns@>=
-procedure init_trie;
-var @!p:trie_pointer; {pointer for initialization}
-@!j,@!k,@!t:integer; {all-purpose registers for initialization}
-@!r,@!s:trie_pointer; {used to clean up the packed |trie|}
-@!h:two_halves; {template used to zero out |trie|'s holes}
-begin @<Get ready to compress the trie@>;
-if trie_root<>0 then
- begin first_fit(trie_root); trie_pack(trie_root);
- end;
-@<Move the data into |trie|@>;
-trie_not_ready:=false;
-end;
-@z
-@x module 1033 gets new code before main_loop_1
-@y
-if mode>0 then if language<>clang then fix_language;
-@z
-@x modules 1091 and 1200
-push_nest; mode:=hmode; space_factor:=1000;
-@y
-push_nest; mode:=hmode; space_factor:=1000; clang:=0;
-@z
-@x module 1324
-for k:=0 to trie_max do dump_hh(trie[k]);
-dump_int(trie_op_ptr);
-for k:=min_quarterword+1 to trie_op_ptr do
- begin dump_int(hyf_distance[k]);
- dump_int(hyf_num[k]);
- dump_int(hyf_next[k]);
- end;
-print_ln; print_int(hyph_count); print(" hyphenation exception");
-if hyph_count<>1 then print_char("s");
-print_nl("Hyphenation trie of length "); print_int(trie_max);
-@.Hyphenation trie...@>
-print(" has "); print_int(qo(trie_op_ptr)); print(" op");
-if trie_op_ptr<>min_quarterword+1 then print_char("s")
-@y
-print_ln; print_int(hyph_count); print(" hyphenation exception");
-if hyph_count<>1 then print_char("s");
-if trie_not_ready then init_trie;
-dump_int(trie_max);
-for k:=0 to trie_max do dump_hh(trie[k]);
-dump_int(trie_op_ptr);
-for k:=1 to trie_op_ptr do
- begin dump_int(hyf_distance[k]);
- dump_int(hyf_num[k]);
- dump_int(hyf_next[k]);
- end;
-print_nl("Hyphenation trie of length "); print_int(trie_max);
-@.Hyphenation trie...@>
-print(" has "); print_int(trie_op_ptr); print(" op");
-if trie_op_ptr<>1 then print_char("s");
-print(" out of "); print_int(trie_op_size);
-for k:=255 downto 0 do if trie_used[k]>min_quarterword then
- begin print_nl(" "); print_int(qo(trie_used[k]));
- print(" for language "); print_int(k);
- dump_int(k); dump_int(qo(trie_used[k]));
- end
-@z
-@x module 1325
-undump_size(0)(trie_size)('trie size')(trie_max);
-for k:=0 to trie_max do undump_hh(trie[k]);
-undump(min_quarterword)(max_quarterword)(trie_op_ptr);
-for k:=min_quarterword+1 to trie_op_ptr do
- begin undump(0)(63)(hyf_distance[k]); {a |small_number|}
- undump(0)(63)(hyf_num[k]);
- undump(min_quarterword)(max_quarterword)(hyf_next[k]);
- end
-@y
-undump_size(0)(trie_size)('trie size')(j); {|trie_max|}
-for k:=0 to j do undump_hh(trie[k]);
-undump_size(0)(trie_op_size)('trie op size')(j); {|trie_op_ptr|}
-for k:=1 to j do
- begin undump(0)(63)(hyf_distance[k]); {a |small_number|}
- undump(0)(63)(hyf_num[k]);
- undump(min_quarterword)(max_quarterword)(hyf_next[k]);
- end;
-k:=256;
-while j>0 do
- begin undump(0)(k-1)(k); undump(1)(j)(x); j:=j-x; op_start[k]:=qo(j);
- end;
-@!init trie_not_ready:=false @+tini
-@z
-@x module 1341 gets two new definitions
-@y
-@d language_node=4 {|subtype| in whatsits that change the current language}
-@d stored_language(#)==mem[#+1].int {language number, in the range |0..255|}
-@z
-@x module 1344 gets a new definition and a new Pascal statement
-@y
-@d set_language_code=5 {command modifier for \.{\\setlanguage}}
-primitive("setlanguage",extension,set_language_code);@/
-@!@:set_language_}{\.{\\setlanguage} primitive@>
-@z
-@x module 1346 gets a new case
-@y
- set_language_code:print_esc("setlanguage");
-@z
-@x module 1348 gets a new case
-@y
-set_language_code:@<Implement \.{\\setlanguage}@>;
-@z
-@x module 1356 gets a new case
-@y
-language_node:begin print_esc("setlanguage");
- print_int(stored_language(p));
- end;
-@z
-% in modules 1357 and 1358, change "close_node" to "close_node,language_node".
-@x module 1362 becomes two modules
-@ @<Advance \(p)past a whatsit node in the |line_break| loop@>=do_nothing
-@y
-@ @<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=
-if subtype(cur_p)=language_node then cur_lang:=stored_language(cur_p)
-
-@ @<Advance \(p)past a whatsit node in the \(p)pre-hyphenation loop@>=
-if subtype(s)=language_node then cur_lang:=stored_language(s)
-@z and old module 1367 is moved to just before the old module 1378
-@x module 1373 gets a new case
-@y
-language_node:do_nothing;
-@z
-@x new modules before the system-dependent changes (i.e. before the old 1376)
-@y
-@ @<Implement \.{\\setlanguage}@>=
-if abs(mode)<>hmode then report_illegal_case
-else begin new_whatsit(language_node,small_node_size);
- scan_int;
- if cur_val<=0 then clang:=0
- else if cur_val>255 then clang:=0
- else clang:=cur_val;
- stored_language(tail):=clang;
- end
-
-@ Finally, we need a subroutine that comes into play when a character of
-a non-|clang| language is being appended to the current paragraph.
-
-@<Declare action...@>=
-procedure fix_language;
-var @!l:ASCII_code; {the new current language}
-begin if language<=0 then l:=0
-else if language>255 then l:=0
-else l:=language;
-if l<>clang then
- begin new_whatsit(language_node,small_node_size);
- stored_language(tail):=l; clang:=l;
- end;
-end;
-@z
-
-362. Major extension to ligature capability.
-@x module 143
-a linked list of character nodes for those characters.
-@y
-a linked list of character nodes for all original characters that have been
-deleted. (This list might be empty if the characters that generated the
-ligature were retained in other nodes.)
-
-The |subtype| field is 0, plus 2 and/or 1 if the original source of the
-ligature included implicit left and/or right boundaries.
-@z
-@x in module 144 add the following procedure to the existing code
-@y
-function new_lig_item(@!c:quarterword):pointer;
-var p:pointer; {the new node}
-begin p:=get_node(small_node_size); character(p):=c; lig_ptr(p):=null;
-new_lig_item:=p;
-end;
-@z
-@x module 193
-font_in_short_display:=font(lig_char(p));
-short_display(lig_ptr(p)); print_char(")");
-@y
-if subtype(p)>1 then print_char("|");
-font_in_short_display:=font(lig_char(p)); short_display(lig_ptr(p));
-if odd(subtype(p)) then print_char("|");
-print_char(")");
-end
-@z
-@x modules 208 and 209
-@d radical=65 {square root and similar signs ( \.{\\radical} )}
-@y
-@d no_boundary=65 {suppress boundary ligatures ( \.{\\noboundary} )}
-@d radical=66 {square root and similar signs ( \.{\\radical} )}
-@z and so on, adding 1 to each definition until getting to max_command=100
-@x module 265 gets a new statement
-@y
-primitive("noboundary",no_boundary,0);@/
-@!@:no_boundary_}{\.{\\noboundary} primitive@>
-@z
-@x module 266 gets a new case
-@y
-no_boundary:print_esc("noboundary");
-@z
-@x module 545 is entirely replaced
-@y by the following new specifications:
-@ The |lig_kern| array contains instructions in a simple programming language
-that explains what to do for special letter pairs. Each word in this array is a
-|@!lig_kern_command| of four bytes.
-
-\yskip\hang first byte: |skip_byte|, indicates that this is the final program
- step if the byte is 128 or more, otherwise the next step is obtained by
- skipping this number of intervening steps.\par
-\hang second byte: |next_char|, ``if |next_char| follows the current character,
- then perform the operation and stop, otherwise continue.''\par
-\hang third byte: |op_byte|, indicates a ligature step if less than~128,
- a kern step otherwise.\par
-\hang fourth byte: |remainder|.\par
-\yskip\noindent
-In a kern step, an
-additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
-between the current character and |next_char|. This amount is
-often negative, so that the characters are brought closer together
-by kerning; but it might be positive.
-
-There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
-$0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
-|remainder| is inserted between the current character and |next_char|;
-then the current character is deleted if $b=0$, and |next_char| is
-deleted if $c=0$; then we pass over $a$~characters to reach the next
-current character (which may have a ligature/kerning program of its own).
-
-If the very first instruction of the |lig_kern| array has |skip_byte=255|,
-the |next_char| byte is the so-called right boundary character of this font;
-the value of |next_char| need not lie between |bc| and~|ec|.
-If the very last instruction of the |lig_kern| array has |skip_byte=255|,
-there is a special ligature/kerning program for a left boundary character,
-beginning at location |256*op_byte+remainder|.
-The interpretation is that \TeX\ puts implicit boundary characters
-before and after each consecutive string of characters from the same font.
-These implicit characters do not appear in the output, but they can affect
-ligatures and kerning.
-
-If the very first instruction of a character's |lig_kern| program has
-|skip_byte>128|, the program actually begins in location
-|256*op_byte+remainder|. This feature allows access to large |lig_kern|
-arrays, because the first instruction must otherwise
-appear in a location |<=255|.
-
-Any instruction with |skip_byte>128| in the |lig_kern| array must have
-|256*op_byte+remainder<nl|. If such an instruction is encountered during
-normal program execution, it denotes an unconditional halt; no ligature
-command is performed.
-
-@d stop_flag=qi(128) {value indicating `\.{STOP}' in a lig/kern program}
-@d kern_flag=qi(128) {op code for a kern step}
-@d skip_byte(#)==#.b0
-@d next_char(#)==#.b1
-@d op_byte(#)==#.b2
-@d rem_byte(#)==#.b3
-@z
-@x module 549
-@<Glob...@>=
-@y
-@d non_char==qi(256) {a |halfword| code that can't match a real character}
-@d non_address==font_mem_size {a spurious |font_index|}
-
-@<Glob...@>=
-@z
-@x module 548 gets a new type definition
-@y
-@!font_index=0..font_mem_size;
-@z
-@x module 549
- {current \.{\\skewchar} values}
-@y
- {current \.{\\skewchar} values}
-@!bchar_label:array[internal_font_number] of font_index;
- {start of |lig_kern| program for left boundary character,
- |non_address| if there is none}
-@!font_bchar:array[internal_font_number] of min_quarterword..non_char;
- {right boundary character, |non_char| if there is none}
-@!font_false_bchar:array[internal_font_number] of min_quarterword..non_char;
- {|font_bchar| if it doesn't exist in the font, otherwise |non_char|}
-@z
-@x module 557
-@d char_kern_end(#)==rem_byte(#)].sc
-@y NOTE: Optimize kern_base_offset in your change file! It's a constant.
-@d char_kern_end(#)==256*op_byte(#)+rem_byte(#)].sc
-@d kern_base_offset==256*(kern_flag)
-@d lig_kern_restart_end(#)==256*op_byte(#)+rem_byte(#)+32768-kern_base_offset
-@d lig_kern_restart(#)==lig_kern_base[#]+lig_kern_restart_end
-@z
-@x module 560
-@!z:scaled; {the design size or the ``at'' size}
-@y
-@!bch_label:integer; {left boundary start location, or infinity}
-@!bchar:0..256; {right boundary character, or 256}
-@!z:scaled; {the design size or the ``at'' size}
-@z
-@x module 566
-kern_base[f]:=lig_kern_base[f]+nl;
-exten_base[f]:=kern_base[f]+nk;
-@y
-kern_base[f]:=lig_kern_base[f]+nl-kern_base_offset;
-exten_base[f]:=kern_base[f]+kern_base_offset+nk;
-@z
-@x module 573: The entire module is replaced
-@y by the following code.
-@ @d check_existence(#)==@t@>@;@/
- begin check_byte_range(#);
- qw:=char_info(f)(#); {N.B.: not |qi(#)|}
- if not char_exists(qw) then abort;
- end
-
-@<Read ligature/kern program@>=
-bch_label:=@'77777; bchar:=256;
-if nl>0 then
- begin for k:=lig_kern_base[f] to kern_base[f]+kern_base_offset-1 do
- begin store_four_quarters(font_info[k].qqqq);
- if a>128 then
- begin if 256*c+d>=nl then abort;
- if a=255 then if k=lig_kern_base[f] then bchar:=b;
- end
- else begin if b<>bchar then check_existence(b);
- if c<128 then check_existence(d) {check ligature}
- else if 256*(c-128)+d>=nk then abort; {check kern}
- if a<128 then if k-lig_kern_base[f]+a+1>=nl then abort;
- end;
- end;
- if a=255 then bch_label:=256*c+d;
- end;
-for k:=kern_base[f]+kern_base_offset to exten_base[f]-1 do
- store_scaled(font_info[k].sc);
-@z
-@x module 574 (actually a bugfix)
- if a<>0 then check_byte_range(a);
- if b<>0 then check_byte_range(b);
- if c<>0 then check_byte_range(c);
- check_byte_range(d);
-@y
- if a<>0 then check_existence(a);
- if b<>0 then check_existence(b);
- if c<>0 then check_existence(c);
- check_existence(d);
-@z
-@x module 576
-font_name[f]:=nom;
-@y
-if bch_label<nl then bchar_label[f]:=bch_label+lig_kern_base[f]
-else bchar_label[f]:=non_address;
-font_bchar[f]:=qi(bchar);
-font_false_bchar[f]:=qi(bchar);
-if bchar<=ec then if bchar>=bc then
- begin qw:=char_info(f)(bchar); {N.B.: not |qi(bchar)|}
- if char_exists(qw) then font_false_bchar[f]:=non_char;
- end;
-font_name[f]:=nom;
-@z
-@x module 708 (slight but optional optimization)
-continue: if (qo(y)>=font_bc[g])and(qo(y)<=font_ec[g]) then
- begin q:=char_info(g)(y);
-@y
-if (qo(y)>=font_bc[g])and(qo(y)<=font_ec[g]) then
- begin continue: q:=char_info(g)(y);
-@z
-@x module 740 (another bugfix)
- i:=char_info(f)(y);
-@y
- i:=char_info(f)(y);
- if not char_exists(i) then goto done;
-@z
-@x module 741
- repeat cur_i:=font_info[a].qqqq;
- if qo(next_char(cur_i))=skew_char[cur_f] then
- begin if op_bit(cur_i)>=kern_flag then
- s:=char_kern(cur_f)(cur_i);
- goto done1;
- end;
- incr(a);
- until stop_bit(cur_i)>=stop_flag;
-@y
- cur_i:=font_info[a].qqqq;
- if skip_byte(cur_i)>stop_flag then
- begin a:=256*(qo(op_byte(cur_i)))+rem_byte(cur_i);
- cur_i:=font_info[a].qqqq;
- end;
- loop begin if qo(next_char(cur_i))=skew_char[cur_f] then
- begin if op_byte(cur_i)>=kern_flag then
- if skip_byte(cur_i)<=stop_flag then s:=char_kern(cur_f)(cur_i);
- goto done1;
- end;
- if skip_byte(cur_i)>=stop_flag then goto done1
- else a:=a+qo(skip_byte(cur_i))+1;
- cur_i:=font_info[a].qqqq;
- end;
-@z
-@x module 749 (yet another bugfix of the same type!)
-@!p,@!v,@!x,@!y,@!z:pointer; {temporary registers for box construction}
-@y
-@!p,@!v,@!x,@!y,@!z:pointer; {temporary registers for box construction}
-@!c:quarterword;@+@!i:four_quarters; {registers for character examination}
-@z
-@x ibid
- begin cur_c:=rem_byte(cur_i); character(nucleus(q)):=cur_c;
- cur_i:=char_info(cur_f)(cur_c);
-@y
- begin c:=rem_byte(cur_i); i:=char_info(cur_f)(c);
- if char_exists(i) then
- begin cur_c:=c; cur_i:=i; character(nucleus(q)):=c;
- end;
-@z
-@x module 752
-@!p:pointer; {temporary register for list manipulation}
-@y
-@!p,@!r:pointer; {temporary registers for list manipulation}
-@z
-@x ibid
- repeat cur_i:=font_info[a].qqqq;@/
- @<If instruction |cur_i| is a kern with |cur_c|,
- attach the kern after |q| and |return|;
- or if it is a ligature with |cur_c|, combine
- noads |q| and |p| and |goto restart|@>;
- incr(a);
- until stop_bit(cur_i)>=stop_flag;
-@y
- cur_i:=font_info[a].qqqq;
- if skip_byte(cur_i)>stop_flag then
- begin a:=lig_kern_restart(cur_f)(cur_i);
- cur_i:=font_info[a].qqqq;
- end;
- loop@+ begin @<If instruction |cur_i| is a kern with |cur_c|, attach
- the kern after~|q|; or if it is a ligature with |cur_c|, combine
- noads |q| and~|p| appropriately; then |return| if the cursor has
- moved past a noad, or |goto restart|@>;
- if skip_byte(cur_i)>=stop_flag then return;
- a:=a+qo(skip_byte(cur_i))+1;
- cur_i:=font_info[a].qqqq;
- end;
-@z
-@x The entire code of module 753 is revised
-@y and should be replaced by the following:
-@ Note that a ligature between an |ord_noad| and another kind of noad
-is replaced by an |ord_noad|, when the two noads collapse into one.
-But we could make a parenthesis (say) change shape when it follows
-certain letters. Presumably a font designer will define such
-ligatures only when this convention makes sense.
-
-\chardef\?='174 % vertical line to indicate character retention
-
-@<If instruction |cur_i| is a kern with |cur_c|, ...@>=
-if next_char(cur_i)=cur_c then if skip_byte(cur_i)<=stop_flag then
- if op_byte(cur_i)>=kern_flag then
- begin p:=new_kern(char_kern(cur_f)(cur_i));
- link(p):=link(q); link(q):=p; return;
- end
- else begin check_interrupt; {allow a way out of infinite ligature loop}
- case op_byte(cur_i) of
- qi(1),qi(5): character(nucleus(q)):=rem_byte(cur_i); {\.{=:\?}, \.{=:\?>}}
- qi(2),qi(6): character(nucleus(p)):=rem_byte(cur_i); {\.{\?=:}, \.{\?=:>}}
- qi(3),qi(7),qi(11):begin r:=new_noad; {\.{\?=:\?}, \.{\?=:\?>}, \.{\?=:\?>>}}
- character(nucleus(r)):=rem_byte(cur_i);
- fam(nucleus(r)):=fam(nucleus(q));@/
- link(q):=r; link(r):=p;
- if op_byte(cur_i)<qi(11) then math_type(nucleus(r)):=math_char
- else math_type(nucleus(r)):=math_text_char; {prevent combination}
- end;
- othercases begin link(q):=link(p);
- character(nucleus(q)):=rem_byte(cur_i); {\.{=:}}
- mem[subscr(q)]:=mem[subscr(p)]; mem[supscr(q)]:=mem[supscr(p)];@/
- free_node(p,noad_size);
- end
- endcases;
- if op_byte(cur_i)>qi(3) then return;
- math_type(nucleus(q)):=math_char; goto restart;
- end
-@z
-@x module 862
-@!q,@!r,@!s:pointer; {miscellaneous nodes of temporary interest}
-@y
-@!q,@!r,@!s,@!prev_s:pointer; {miscellaneous nodes of temporary interest}
-@z
-@x module 892
-nodes $p_a$ and~$p_b$ in the description above are placed into variables
-@y
-nodes $p_{a-1}$ and~$p_b$ in the description above are placed into variables
-@z
-@x ibid
-@!hc:array[0..65] of halfword; {word to be hyphenated}
-@y
-@!hc:array[0..65] of 0..256; {word to be hyphenated}
-@z
-@x ibid
-@!hu:array[1..63] of ASCII_code; {like |hc|, before conversion to lowercase}
-@y
-@!hu:array[0..63] of 0..256; {like |hc|, before conversion to lowercase}
-@z
-@x module 894
-s:=link(cur_p);
-@y
-prev_s:=cur_p; s:=link(prev_s);
-@z
-@x module 895
-label done,found,not_found,found1,exit;
-@y
-label common_ending,done,found,found1,not_found,not_found+1,exit;
-@z
-@x module 896
- else if type(s)=ligature_node then
- begin q:=lig_ptr(s); c:=qo(character(q)); hf:=font(q);
- end
-@y
- else if type(s)=ligature_node then
- if lig_ptr(s)=null then goto continue
- else begin q:=lig_ptr(s); c:=qo(character(q)); hf:=font(q);
- end
-@z
-@x ibid
-continue: s:=link(s);
-@y
-continue: prev_s:=s; s:=link(prev_s);
-@z
-@x ibid
-ha:=s
-@y
-ha:=prev_s
-@z
-@x module 898
-begin j:=hn; q:=lig_ptr(s);
-if font(q)<>hf then goto done3;
-repeat c:=qo(character(q));
-if lc_code(c)=0 then goto done3;
-if j=63 then goto done3;
-incr(j); hu[j]:=c; hc[j]:=lc_code(c);@/
-q:=link(q);
-until q=null;
-@y
-begin if font(lig_char(s))<>hf then goto done3;
-j:=hn; q:=lig_ptr(s);
-while q>null do
- begin c:=qo(character(q));
- if lc_code(c)=0 then goto done3;
- if j=63 then goto done3;
- incr(j); hu[j]:=c; hc[j]:=lc_code(c);@/
- q:=link(q);
- end;
-@z
-@x module 900 gets three new global variables
-@y
-@!init_list:pointer; {list of punctuation characters preceding the word}
-@!init_lig:boolean; {does |init_list| represent a ligature?}
-@!init_lft:boolean; {if so, did the ligature involve a left boundary?}
-@z
-@x module 901
-@!q,@!r,@!s:pointer; {temporary registers for list manipulation}
-@y
-@!p,@!q,@!r,@!s:pointer; {temporary registers for list manipulation}
-@!bchar:halfword; {right boundary character of hyphenated word, or |non_char|}
-@z
-@x module 903 should be entirely replaced
-@y by the following:
-@ If hyphens are in fact going to be inserted, \TeX\ first deletes the
-subsequence of nodes between |ha| and~|hb|. An attempt is made to
-preserve the effect that implicit boundary characters and punctuation marks
-had on ligatures inside the hyphenated word, by storing a left boundary or
-preceding character in |hu[0]| and by storing a possible right boundary
-in |bchar|. We set |j:=0| if |hu[0]| is to be part of the reconstruction;
-otherwise |j:=1|.
-The variable |s| will point to the tail of the current hlist, and
-|q| will point to the node following |hb|, so that
-things can be hooked up after we reconstitute the hyphenated word.
-
-@<Replace nodes |ha..hb| by a sequence of nodes...@>=
-q:=link(hb); link(hb):=null; r:=link(ha); link(ha):=null; bchar:=non_char;
-if type(hb)=ligature_node then if odd(subtype(hb)) then
- bchar:=font_bchar[hf];
-if is_char_node(ha) then
- begin init_list:=ha; init_lig:=false; hu[0]:=qo(character(ha));
- end
-else if type(ha)=ligature_node then
- begin init_list:=lig_ptr(ha); init_lig:=true; init_lft:=(subtype(ha)>1);
- hu[0]:=qo(character(lig_char(ha)));
- if init_list=null then if init_lft then
- begin hu[0]:=256; init_lig:=false;
- end; {in this case a ligature will be reconstructed from scratch}
- free_node(ha,small_node_size);
- end
-else goto not_found+1; {no punctuation found}
-s:=cur_p; {we have |cur_p<>ha| because |type(cur_p)=glue_node|}
-while link(s)<>ha do s:=link(s);
-j:=0; goto common_ending;
-not_found+1: j:=1; s:=ha; init_list:=null;
-if not is_char_node(r) then if type(r)=ligature_node then
- if subtype(r)>1 then
- begin j:=0; hu[0]:=256; init_lig:=false;
- end;
-common_ending: flush_node_list(r);
-@<Reconstitute nodes for the hyphenated word, inserting discretionary hyphens@>;
-flush_list(init_list)
-@z
-@x modules 905--911 are entirely replaced
-@y by the following new code:
-Still further complications arise in the presence of ligatures that do not
-delete the original characters. When punctuation precedes the word being
-hyphenated, \TeX's method is not perfect under all possible scenarios,
-because punctuation marks and letters can propagate information back and forth.
-For example, suppose the original pre-hyphenation pair
-\.{*a} changes to \.{*y} via a \.{\?=:} ligature, which changes to \.{xy}
-via a \.{=:\?} ligature; if $p_{a-1}=\.x$ and $p_a=\.y$, the reconstitution
-procedure isn't smart enough to obtain \.{xy} again. In such cases the
-font designer should include a ligature that goes from \.{xa} to \.{xy}.
-
-@ The processing is facilitated by a subroutine called |reconstitute|. Given
-a string of characters $x_j\ldots x_n$, there is a smallest index $m\ge j$
-such that the ``translation'' of $x_j\ldots x_n$ by ligatures and kerning
-has the form $y_1\ldots y_t$ followed by the translation of $x_{m+1}\ldots x_n$,
-where $y_1\ldots y_t$ is some nonempty sequence of character, ligature, and
-kern nodes. We call $x_j\ldots x_m$ a ``cut prefix'' of $x_j\ldots x_n$.
-For example, if $x_1x_2x_3=\.{fly}$, and if the font contains `fl' as a
-ligature and a kern between `fl' and `y', then $m=2$, $y=2$, and $y_1$ will
-be a ligature node for `fl' followed by an appropriate kern node~$y_2$.
-In the most common case, $x_j$~forms no ligature with $x_{j+1}$ and we
-simply have $m=j$, $y_1=x_j$. If $m<n$ we can repeat the procedure on
-$x_{m+1}\ldots x_n$ until the entire translation has been found.
-
-The |reconstitute| function returns the integer $m$ and puts the nodes
-$y_1\ldots y_t$ into a linked list starting at |link(hold_head)|,
-getting the input $x_j\ldots x_n$ from the |hu| array. If $x_j=256$,
-we consider $x_j$ to be an implicit left boundary character; in this
-case |j| must be strictly less than~|n|. There is a
-parameter |bchar|, which is either 256 or an implicit right boundary character
-assumed to be present just following~$x_n$. (The value |hu[n+1]| is never
-explicitly examined, but the algorithm imagines that |bchar| is there.)
-
-If there exists an index |k| in the range $j\le k\le m$ such that |hyf[k]|
-is odd and such that the result of reconstitute would have been different
-if $x_{k+1}$ had been |hchar|, then |reconstitute| sets |hyphen_passed|
-to the smallest such~|k|. Otherwise it sets |hyphen_passed| to zero.
-
-A special convention is used in the case |j=0|: Then we assume that the
-translation of |hu[0]| appears in a special list of charnodes starting at
-|init_list|; moreover, if |init_lig| is |true|, then |hu[0]| will be
-a ligature character, involving a left boundary if |init_lft| is |true|.
-This facility is provided for cases when a hyphenated
-word is preceded by punctuation (like single or double quotes) that might
-affect the translation of the beginning of the word.
-
-@<Glob...@>=
-@!hyphen_passed:small_number; {first hyphen in a ligature, if any}
-
-@ @<Declare the function called |reconstitute|@>=
-function reconstitute(@!j,@!n:small_number;@!bchar,@!hchar:halfword):
- small_number;
-label continue,done;
-var @!p:pointer; {temporary register for list manipulation}
-@!t:pointer; {a node being appended to}
-@!q:four_quarters; {character information or a lig/kern instruction}
-@!cur_rh:halfword; {hyphen character for ligature testing}
-@!test_char:halfword; {hyphen or other character for ligature testing}
-@!w:scaled; {amount of kerning}
-@!k:font_index; {position of current lig/kern instruction}
-begin hyphen_passed:=0; t:=hold_head; w:=0; link(hold_head):=null;
- {at this point |ligature_present=lft_hit=rt_hit=false|}
-@<Set up data structures with the cursor following position |j|@>;
-continue:@<If there's a ligature or kern at the cursor position, update the data
- structures, possibly advancing~|j|; continue until the cursor moves@>;
-@<Append a ligature and/or kern to the translation;
- |goto continue| if the stack of inserted ligatures is nonempty@>;
-reconstitute:=j;
-end;
-
-@ The reconstitution procedure shares many of the global data structures
-by which \TeX\ has processed the words before they were hyphenated.
-There is an implied ``cursor'' between characters |cur_l| and |cur_r|;
-these characters will be tested for possible ligature activity. If
-|ligature_present| then |cur_l| is a ligature character formed from the
-original characters following |cur_q| in the current translation list.
-There is a ``ligature stack'' between the cursor and character |j+1|,
-consisting of pseudo-ligature nodes linked together by their |link| fields.
-This stack is normally empty unless a ligature command has created a new
-character that will need to be processed later. A pseudo-ligature is
-a special node having a |character| field that represents a potential
-ligature and a |lig_ptr| field that points to a |char_node| or is |null|.
-We have
-$$|cur_r|=\cases{|character(lig_stack)|,&if |lig_stack>null|;\cr
- |qi(hu[j+1])|,&if |lig_stack=null| and |j<n|;\cr
- bchar,&if |lig_stack=null| and |j=n|.\cr}$$
-
-@<Glob...@>=
-@!cur_l,@!cur_r:halfword; {characters before and after the cursor}
-@!cur_q:pointer; {where a ligature should be detached}
-@!lig_stack:pointer; {unfinished business to the right of the cursor}
-@!ligature_present:boolean; {should a ligature node be made for |cur_l|?}
-@!lft_hit,@!rt_hit:boolean; {did we hit a ligature with a boundary character?}
-
-@ @d append_charnode_to_t(#)== begin link(t):=get_avail; t:=link(t);
- font(t):=hf; character(t):=#;
- end
-@d set_cur_r==begin if j<n then cur_r:=qi(hu[j+1])@+else cur_r:=bchar;
- if odd(hyf[j]) then cur_rh:=hchar@+else cur_rh:=non_char;
- end
-
-@<Set up data structures with the cursor following position |j|@>=
-cur_l:=qi(hu[j]); cur_q:=t;
-if j=0 then
- begin ligature_present:=init_lig; p:=init_list;
- if ligature_present then lft_hit:=init_lft;
- while p>null do
- begin append_charnode_to_t(character(p)); p:=link(p);
- end;
- end
-else if cur_l<non_char then append_charnode_to_t(cur_l);
-lig_stack:=null; set_cur_r
-
-@ We may want to look at the lig/kern program twice, once for a hyphen
-and once for a normal letter. (The hyphen might appear after the letter
-in the program, so we'd better not try to look for both at once.)
-
-@<If there's a ligature or kern at the cursor position, update...@>=
-if cur_l=non_char then
- begin k:=bchar_label[hf];
- if k=non_address then goto done@+else q:=font_info[k].qqqq;
- end
-else begin q:=char_info(hf)(cur_l);
- if char_tag(q)<>lig_tag then goto done;
- k:=lig_kern_start(hf)(q); q:=font_info[k].qqqq;
- if skip_byte(q)>stop_flag then
- begin k:=lig_kern_restart(hf)(q); q:=font_info[k].qqqq;
- end;
- end; {now |k| is the starting address of the lig/kern program}
-if cur_rh<non_char then test_char:=cur_rh@+else test_char:=cur_r;
-loop@+begin if next_char(q)=test_char then if skip_byte(q)<=stop_flag then
- if cur_rh<non_char then
- begin hyphen_passed:=j; hchar:=non_char; cur_rh:=non_char;
- goto continue;
- end
- else begin if hchar<non_char then if odd(hyf[j]) then
- begin hyphen_passed:=j; hchar:=non_char;
- end;
- if op_byte(q)<kern_flag then
- @<Carry out a ligature replacement, updating the cursor structure
- and possibly advancing~|j|; |goto continue| if the cursor doesn't
- advance, otherwise |goto done|@>;
- w:=char_kern(hf)(q); goto done; {this kern will be inserted below}
- end;
- if skip_byte(q)>=stop_flag then
- if cur_rh=non_char then goto done
- else begin cur_rh:=non_char; goto continue;
- end;
- k:=k+qo(skip_byte(q))+1; q:=font_info[k].qqqq;
- end;
-done:
-
-@ @d wrap_lig(#)==if ligature_present then
- begin p:=new_ligature(hf,cur_l,link(cur_q));
- if lft_hit then
- begin subtype(p):=2; lft_hit:=false;
- end;
- if # then if lig_stack=null then
- begin incr(subtype(p)); rt_hit:=false;
- end;
- link(cur_q):=p; t:=p; ligature_present:=false;
- end
-@d pop_lig_stack==begin if lig_ptr(lig_stack)>null then
- begin link(t):=lig_ptr(lig_stack); {this is a charnode for |hu[j+1]|}
- t:=link(t); incr(j);
- end;
- p:=lig_stack; lig_stack:=link(p); free_node(p,small_node_size);
- if lig_stack=null then set_cur_r@+else cur_r:=character(lig_stack);
- end {if |lig_stack| isn't |null| we have |cur_rh=non_char|}
-
-@<Append a ligature and/or kern to the translation...@>=
-wrap_lig(rt_hit);
-if w<>0 then
- begin link(t):=new_kern(w); t:=link(t); w:=0;
- end;
-if lig_stack>null then
- begin cur_q:=t; cur_l:=character(lig_stack); ligature_present:=true;
- pop_lig_stack; goto continue;
- end
-
-@ @<Carry out a ligature replacement, updating the cursor structure...@>=
-begin if cur_l=non_char then lft_hit:=true;
-if j=n then if lig_stack=null then rt_hit:=true;
-check_interrupt; {allow a way out in case there's an infinite ligature loop}
-case op_byte(q) of
-qi(1),qi(5):begin cur_l:=rem_byte(q); {\.{=:\?}, \.{=:\?>}}
- ligature_present:=true;
- end;
-qi(2),qi(6):begin cur_r:=rem_byte(q); {\.{\?=:}. \.{\?=:>}}
- if lig_stack>null then character(lig_stack):=cur_r
- else begin lig_stack:=new_lig_item(cur_r);
- if j=n then bchar:=non_char
- else begin p:=get_avail; lig_ptr(lig_stack):=p;
- character(p):=qi(hu[j+1]); font(p):=hf;
- end;
- end;
- end;
-qi(3):begin cur_r:=rem_byte(q); {\.{\?=:\?}}
- p:=lig_stack; lig_stack:=new_lig_item(cur_r); link(lig_stack):=p;
- end;
-qi(7),qi(11):begin wrap_lig(false); {\.{\?=:\?>}, \.{\?=:\?>>}}
- cur_q:=t; cur_l:=rem_byte(q); ligature_present:=true;
- end;
-othercases begin cur_l:=rem_byte(q); ligature_present:=true; {\.{=:}}
- if lig_stack>null then pop_lig_stack
- else if j=n then goto done
- else begin append_charnode_to_t(cur_r); incr(j); set_cur_r;
- end;
- end
-endcases;
-if op_byte(q)>qi(4) then if op_byte(q)<>qi(7) then goto done;
-goto continue;
-end
-@z
-@x module 912
-@!c:ASCII_code; {character temporarily replaced by a hyphen}
-@y
-@!c:ASCII_code; {character temporarily replaced by a hyphen}
-@!c_loc:0..63; {where that character came from}
-@!r_count:integer; {replacement count for discretionary}
-@z
-@x modules 913--918 are to be completely replaced
-@y by the following code:
-@ When the following code is performed, |hyf[0]| and |hyf[hn]| will be zero.
-
-@<Reconstitute nodes for the hyphenated word...@>=
-repeat l:=j; j:=reconstitute(j,hn,bchar,qi(hyf_char))+1;
-if hyphen_passed=0 then
- begin link(s):=link(hold_head);
- while link(s)>null do s:=link(s);
- if odd(hyf[j-1]) then
- begin l:=j; hyphen_passed:=j-1; link(hold_head):=null;
- end;
- end;
-if hyphen_passed>0 then
- @<Create and append a discretionary node as an alternative to the
- unhyphenated word, and continue to develop both branches until they
- become equivalent@>;
-until j>hn;
-link(s):=q
-
-@ @d advance_major_tail==begin major_tail:=link(major_tail); incr(r_count);
- end
-
-@<Create and append a discretionary node as an alternative...@>=
-begin r:=get_node(small_node_size);
-link(r):=link(hold_head); type(r):=disc_node;
-major_tail:=r; r_count:=0;
-while link(major_tail)>null do advance_major_tail;
-i:=hyphen_passed;
-@<Put the \(c)characters |hu[l..i]| and a hyphen into |pre_break(r)|@>;
-@<Put the \(c)characters |hu[i+1..@,]| into |post_break(r)|, appending to this
- list and to |major_tail| until synchronization has been achieved@>;
-@<Move pointer |s| to the end of the current list, and set |replace_count(r)|
- appropriately@>;
-end
-
-@ The new hyphen might combine with the previous character via ligature
-or kern. At this point we have |l-1<=i<=j| and |i<hn|.
-
-@<Put the \(c)characters |hu[l..i]| and a hyphen into |pre_break(r)|@>=
-minor_tail:=null; pre_break(r):=null; hyf_node:=new_character(hf,hyf_char);
-if hyf_node<>null then
- begin incr(i); c:=hu[i]; hu[i]:=hyf_char; free_avail(hyf_node);
- end;
-while l<=i do
- begin l:=reconstitute(l,i,font_bchar[hf],non_char)+1;
- if link(hold_head)>null then
- begin if minor_tail=null then pre_break(r):=link(hold_head)
- else link(minor_tail):=link(hold_head);
- minor_tail:=link(hold_head);
- while link(minor_tail)>null do minor_tail:=link(minor_tail);
- end;
- end;
-if hyf_node<>null then
- begin hu[i]:=c; {restore the character in the hyphen position}
- l:=i; decr(i);
- end
-
-@ The synchronization algorithm begins with |l=i+1<=j|.
-
-@<Put the \(c)characters |hu[i+1..@,]| into |post_break(r)|...@>=
-minor_tail:=null; post_break(r):=null; c_loc:=0;
-if bchar_label[hf]<non_address then {put left boundary at beginning of new line}
- begin decr(l); c:=hu[l]; c_loc:=l; hu[l]:=256;
- end;
-while l<j do
- begin repeat l:=reconstitute(l,hn,bchar,non_char)+1;
- if c_loc>0 then
- begin hu[c_loc]:=c; c_loc:=0;
- end;
- if link(hold_head)>null then
- begin if minor_tail=null then post_break(r):=link(hold_head)
- else link(minor_tail):=link(hold_head);
- minor_tail:=link(hold_head);
- while link(minor_tail)>null do minor_tail:=link(minor_tail);
- end;
- until l>=j;
- while l>j do
- @<Append characters of |hu[j..@,]| to |major_tail|, advancing~|j|@>;
- end
-
-@ @<Append characters of |hu[j..@,]|...@>=
-begin j:=reconstitute(j,hn,bchar,non_char)+1;
-link(major_tail):=link(hold_head);
-while link(major_tail)>null do advance_major_tail;
-end
-
-@ Ligature insertion can cause a word to grow exponentially in size. Therefore
-we must test the size of |r_count| here, even though the hyphenated text
-was at most 63 characters long.
-
-@<Move pointer |s| to the end of the current list...@>=
-if r_count>127 then {we have to forget the discretionary hyphen}
- begin link(s):=link(r); link(r):=null; flush_node_list(r);
- end
-else begin link(s):=r; replace_count(r):=r_count;
- end;
-s:=major_tail
-@z
-@x module 1030
-@d main_loop=70 {go here to typeset |cur_chr| in the current font}
-@d main_loop_1=71 {like |main_loop|, but |(f,c)| = current font and char}
-@d main_loop_2=72 {like |main_loop_1|, but |c| is known to be in range}
-@d main_loop_3=73 {like |main_loop_2|, but several variables are set up}
-@d append_normal_space=74 {go here to append a normal space between words}
-@y
-@d main_loop=70 {go here to typeset a string of consecutive characters}
-@d main_loop_wrapup=80 {go here to finish a character or ligature}
-@d main_loop_move=90 {go here to advance the ligature cursor}
-@d main_loop_move_lig=95 {same, when advancing past a generated ligature}
-@d main_loop_lookahead=100 {go here to bring in another character, if any}
-@d main_lig_loop=110 {go here to check for ligatures or kerning}
-@d append_normal_space=120 {go here to append a normal space between words}
-@z
-@x ibid
-label big_switch,reswitch,main_loop,main_loop_1,main_loop_2,main_loop_3,
-@y
-label big_switch,reswitch,main_loop,main_loop_wrapup,
- main_loop_move,main_loop_move+1,main_loop_move+2,main_loop_move_lig,
- main_loop_lookahead,main_loop_lookahead+1,
- main_lig_loop,main_lig_loop+1,main_lig_loop+2,
-@z
-@x ibid
-@<Local variables for the inner loop of |main_control|@>@;
-@y
-@z
-@x ibid
-hmode+char_num: begin scan_char_num; cur_chr:=cur_val; goto main_loop;
- end;
-@y
-hmode+char_num: begin scan_char_num; cur_chr:=cur_val; goto main_loop;@+end;
-hmode+no_boundary: begin get_x_token;
- if (cur_cmd=letter)or(cur_cmd=other_char)or(cur_cmd=char_given)or
- (cur_cmd=char_num) then cancel_boundary:=true;
- goto reswitch;
- end;
-@z
-@x modules 1032--1040 are all to be replaced
-@y by the following code:
-@ The following part of the program was first written in a structured
-manner, according to the philosophy that ``premature optimization is
-the root of all evil.'' Then it was rearranged into pieces of
-spaghetti so that the most common actions could proceed with little or
-no redundancy.
-
-The original unoptimized form of this algorithm resembles the
-|reconstitute| procedure, which was described earlier in connection with
-hyphenation. Again we have an implied ``cursor`` between characters
-|cur_l| and |cur_r|. The main difference is that the |lig_stack| can now
-contain a charnode as well as pseudo-ligatures; that stack is now
-usually nonempty, because the next character of input (if any) has been
-appended to it. In |main_control| we have
-$$|cur_r|=\cases{|character(lig_stack)|,&if |lig_stack>null|;\cr
- |font_bchar[cur_font]|,&otherwise.\cr}$$
-Several additional global variables are needed.
-
-@<Glob...@>=
-@!main_f:internal_font_number; {the current font}
-@!main_i:four_quarters; {character information bytes for |cur_l|}
-@!main_j:four_quarters; {ligature/kern command}
-@!main_k:font_index; {index into |font_info|}
-@!main_p:pointer; {temporary register for list manipulation}
-@!main_s:integer; {space factor value}
-@!bchar:halfword; {right boundary character of current font, or |non_char|}
-@!false_bchar:halfword; {nonexistent character matching |bchar|, or |non_char|}
-@!cancel_boundary:boolean; {should the left boundary be ignored?}
-@!ins_disc:boolean; {should we insert a discretionary node?}
-
-@ The boolean variables of the main loop are normally false, and always reset
-to false before the loop is left. That saves us the extra work of initializing
-each time.
-
-@<Set init...@>=
-ligature_present:=false; cancel_boundary:=false; lft_hit:=false; rt_hit:=false;
-ins_disc:=false;
-
-@ We leave |space_factor| unchanged if |sf_code(cur_chr)=0|; otherwise we
-set it to |sf_code(cur_chr)|, except that the space factor never changes
-from a value less than 1000 to a value exceeding 1000. The most common
-case is |sf_code(cur_chr)=1000|, so we want that case to be fast.
-
-The overall structure of the main loop is presented here. Some program labels
-are inside the individual sections.
-
-@d adjust_space_factor==@t@>@;@/
- main_s:=sf_code(cur_chr);
- if main_s=1000 then space_factor:=1000
- else if main_s<1000 then
- begin if main_s>0 then space_factor:=main_s;
- end
- else if space_factor<1000 then space_factor:=1000
- else space_factor:=main_s
-
-@<Append character |cur_chr|...@>=
-adjust_space_factor;@/
-main_f:=cur_font;
-bchar:=font_bchar[main_f]; false_bchar:=font_false_bchar[main_f];
-if mode>0 then if language<>clang then fix_language;
-fast_get_avail(lig_stack); font(lig_stack):=main_f; cur_l:=qi(cur_chr);
-character(lig_stack):=cur_l;@/
-cur_q:=tail;
-if cancel_boundary then
- begin cancel_boundary:=false; main_k:=non_address;
- end
-else main_k:=bchar_label[main_f];
-if main_k=non_address then goto main_loop_move+2; {no left boundary processing}
-cur_r:=cur_l; cur_l:=non_char;
-goto main_lig_loop+1; {begin with cursor after left boundary}
-@#
-main_loop_wrapup:@<Make a ligature node, if |ligature_present|;
- insert a null discretionary, if appropriate@>;
-main_loop_move:@<If the cursor is immediately followed by the right boundary,
- |goto reswitch|; if it's followed by an invalid character, |goto big_switch|;
- otherwise move the cursor one step to the right and |goto main_lig_loop|@>;
-main_loop_lookahead:@<Look ahead for another character, or leave |lig_stack|
- empty if there's none there@>;
-main_lig_loop:@<If there's a ligature/kern command relevant to |cur_l| and
- |cur_r|, adjust the text appropriately; exit to |main_loop_wrapup|@>;
-main_loop_move_lig:@<Move the cursor past a pseudo-ligature, then
- |goto main_loop_lookahead| or |main_lig_loop|@>
-
-@ If the current horizontal list is empty, the reference to |character(tail)|
-here is not strictly legal, since |tail| will be a node freshly returned by
-|get_avail|. But this should cause no problem on most implementations, and we
-do want the inner loop to be fast.
-@^dirty Pascal@>
-
-A discretionary break is not inserted for an explicit hyphen when we are in
-restricted horizontal mode. In particular, this avoids putting discretionary
-nodes inside of other discretionaries.
-
-@d pack_lig(#)== {the parameter is either |rt_hit| or |false|}
- begin main_p:=new_ligature(main_f,cur_l,link(cur_q));
- if lft_hit then
- begin subtype(main_p):=2; lft_hit:=false;
- end;
- if # then if lig_stack=null then
- begin incr(subtype(main_p)); rt_hit:=false;
- end;
- link(cur_q):=main_p; tail:=main_p; ligature_present:=false;
- end
-
-@d wrapup(#)==if cur_l<non_char then
- begin if character(tail)=qi(hyphen_char[main_f]) then if link(cur_q)>null then
- ins_disc:=true;
- if ligature_present then pack_lig(#);
- if ins_disc then
- begin ins_disc:=false;
- if mode>0 then tail_append(new_disc);
- end;
- end
-
-@<Make a ligature node, if |ligature_present|;...@>=
-wrapup(rt_hit)
-
-@ @<If the cursor is immediately followed by the right boundary...@>=
-if lig_stack=null then goto reswitch;
-cur_q:=tail; cur_l:=cur_r; {or |character(lig_stack)|}
-main_loop_move+1:if not is_char_node(lig_stack) then goto main_loop_move_lig;
-main_loop_move+2:if(cur_chr<font_bc[main_f])or(cur_chr>font_ec[main_f]) then
- begin char_warning(main_f,cur_chr); free_avail(lig_stack); goto big_switch;
- end;
-main_i:=char_info(main_f)(cur_l);
-if not char_exists(main_i) then
- begin char_warning(main_f,cur_chr); free_avail(lig_stack); goto big_switch;
- end;
-tail_append(lig_stack) {|main_loop_lookahead| is next}
-
-@ Here we are at |main_loop_move_lig|.
-When we begin this code we have |cur_l=character(lig_stack)| and |cur_q=tail|.
-
-@<Move the cursor past a pseudo-ligature...@>=
-main_p:=lig_ptr(lig_stack);
-if main_p>null then tail_append(main_p);
-temp_ptr:=lig_stack; lig_stack:=link(temp_ptr);
-free_node(temp_ptr,small_node_size);
-main_i:=char_info(main_f)(cur_l); ligature_present:=true;
-if lig_stack=null then
- if main_p>null then goto main_loop_lookahead
- else cur_r:=bchar
-else cur_r:=character(lig_stack);
-goto main_lig_loop
-
-@ The result of \.{\\char} can participate in a ligature or kern, so we must
-look ahead for it.
-
-@<Look ahead for another character...@>=
-get_next; {set only |cur_cmd| and |cur_chr|, for speed}
-if cur_cmd=letter then goto main_loop_lookahead+1;
-if cur_cmd=other_char then goto main_loop_lookahead+1;
-if cur_cmd=char_given then goto main_loop_lookahead+1;
-x_token; {now expand and set |cur_cmd|, |cur_chr|, |cur_tok|}
-if cur_cmd=letter then goto main_loop_lookahead+1;
-if cur_cmd=other_char then goto main_loop_lookahead+1;
-if cur_cmd=char_given then goto main_loop_lookahead+1;
-if cur_cmd=char_num then
- begin scan_char_num; cur_chr:=cur_val; goto main_loop_lookahead+1;
- end;
-if cur_cmd=no_boundary then bchar:=non_char;
-cur_r:=bchar; lig_stack:=null; goto main_lig_loop;
-main_loop_lookahead+1: adjust_space_factor;
-fast_get_avail(lig_stack); font(lig_stack):=main_f;
-cur_r:=qi(cur_chr); character(lig_stack):=cur_r;
-if cur_r=false_bchar then cur_r:=non_char {this prevents spurious ligatures}
-
-@ Even though comparatively few characters have a lig/kern program, several
-of the instructions here count as part of \TeX's inner loop, since a
-potentially long sequential search must be performed. For example, tests with
-Computer Modern Roman showed that about 40 per cent of all characters
-actually encountered in practice had a lig/kern program, and that about four
-lig/kern commands were investigated for every such character.
-
-At the beginning of this code we have |main_i=char_info(main_f)(cur_l)|.
-
-@<If there's a ligature/kern command...@>=
-if char_tag(main_i)<>lig_tag then goto main_loop_wrapup;
-main_k:=lig_kern_start(main_f)(main_i); main_j:=font_info[main_k].qqqq;
-if skip_byte(main_j)<=stop_flag then goto main_lig_loop+2;
-main_k:=lig_kern_restart(main_f)(main_j);
-main_lig_loop+1:main_j:=font_info[main_k].qqqq;
-main_lig_loop+2:if next_char(main_j)=cur_r then
- if skip_byte(main_j)<=stop_flag then
- @<Do ligature or kern command, returning to |main_lig_loop|
- or |main_loop_wrapup| or |main_loop_move|@>;
-if skip_byte(main_j)=qi(0) then incr(main_k)
-else begin if skip_byte(main_j)>=stop_flag then goto main_loop_wrapup;
- main_k:=main_k+qo(skip_byte(main_j))+1;
- end;
-goto main_lig_loop+1
-
-@ When a ligature or kern instruction matches a character, we know from
-|read_font_info| that the character exists in the font, even though we
-haven't verified its existence in the normal way.
-
-This section could be made into a subroutine, if the code inside
-|main_control| needs to be shortened.
-
-\chardef\?='174 % vertical line to indicate character retention
-
-@<Do ligature or kern command...@>=
-begin if op_byte(main_j)>=kern_flag then
- begin wrapup(rt_hit);
- tail_append(new_kern(char_kern(main_f)(main_j))); goto main_loop_move;
- end;
-if cur_l=non_char then lft_hit:=true
-else if lig_stack=null then rt_hit:=true;
-check_interrupt; {allow a way out in case there's an infinite ligature loop}
-case op_byte(main_j) of
-qi(1),qi(5):begin cur_l:=rem_byte(main_j); {\.{=:\?}, \.{=:\?>}}
- main_i:=char_info(main_f)(cur_l); ligature_present:=true;
- end;
-qi(2),qi(6):begin cur_r:=rem_byte(main_j); {\.{\?=:}, \.{\?=:>}}
- if lig_stack=null then {right boundary character is being consumed}
- begin lig_stack:=new_lig_item(cur_r); bchar:=non_char;
- end
- else if is_char_node(lig_stack) then {|link(lig_stack)=null|}
- begin main_p:=lig_stack; lig_stack:=new_lig_item(cur_r);
- lig_ptr(lig_stack):=main_p;
- end
- else character(lig_stack):=cur_r;
- end;
-qi(3):begin cur_r:=rem_byte(main_j); {\.{\?=:\?}}
- main_p:=lig_stack; lig_stack:=new_lig_item(cur_r);
- link(lig_stack):=main_p;
- end;
-qi(7),qi(11):begin wrapup(false); {\.{\?=:\?>}, \.{\?=:\?>>}}
- cur_q:=tail; cur_l:=rem_byte(main_j);
- main_i:=char_info(main_f)(cur_l); ligature_present:=true;
- end;
-othercases begin cur_l:=rem_byte(main_j); ligature_present:=true; {\.{=:}}
- if lig_stack=null then goto main_loop_wrapup
- else goto main_loop_move+1;
- end
-endcases;
-if op_byte(main_j)>qi(4) then
- if op_byte(main_j)<>qi(7) then goto main_loop_wrapup;
-if cur_l<non_char then goto main_lig_loop;
-main_k:=bchar_label[main_f]; goto main_lig_loop+1;
-end
-@z
-% HINTS for making main_control shorter if you need to conserve space:
-% (1) make pack_lig(#) a procedure call instead of a macro call
-% (2) make the code of @<Do ligature...@> a function that returns one of
-% four values; you goto a label based on the value returned.
-@x module 1042
-begin p:=font_glue[cur_font];
-if p=null then
- begin f:=cur_font; p:=new_spec(zero_glue); k:=param_base[f]+space_code;
- width(p):=font_info[k].sc; {that's |space(f)|}
- stretch(p):=font_info[k+1].sc; {and |space_stretch(f)|}
- shrink(p):=font_info[k+2].sc; {and |space_shrink(f)|}
- font_glue[f]:=p;
-@y
-begin main_p:=font_glue[cur_font];
-if main_p=null then
- begin main_p:=new_spec(zero_glue); main_k:=param_base[cur_font]+space_code;
- width(main_p):=font_info[main_k].sc; {that's |space(cur_font)|}
- stretch(main_p):=font_info[main_k+1].sc; {and |space_stretch(cur_font)|}
- shrink(main_p):=font_info[main_k+2].sc; {and |space_shrink(cur_font)|}
- font_glue[cur_font]:=main_p;
-@z
-@x module 1045
-any_mode(relax),vmode+spacer,mmode+spacer,mmode+no_boundary:do_nothing;
-@y
-any_mode(relax),vmode+spacer,mmode+spacer:do_nothing;
-@z
-@x module 1090
- vmode+ex_space:@t@>@;@/
-@y
- vmode+ex_space,vmode+no_boundary:@t@>@;@/
-@z
-@x module 1322
-dump_int(font_glue[k]);@/
-@y
-dump_int(font_glue[k]);@/
-dump_int(bchar_label[k]);
-dump_int(font_bchar[k]);
-dump_int(font_false_bchar[k]);@/
-@z
-@x module 1323
-undump(min_halfword)(lo_mem_max)(font_glue[k]);@/
-@y
-undump(min_halfword)(lo_mem_max)(font_glue[k]);@/
-undump(0)(font_mem_size)(bchar_label[k]);
-undump(min_quarterword)(non_char)(font_bchar[k]);
-undump(min_quarterword)(non_char)(font_false_bchar[k]);
-@z
-
-363. New \inputlineno feature desired by Spivak
-@x module 416 gets a new definition and a new statement
-@y
-@d input_line_no_code=glue_val+1 {code for \.{\\inputlineno}}
-primitive("inputlineno",last_item,input_line_no_code);
-@!@:input_line_no_}{\.{\\inputlineno} primitive@>
-@z and module 417 changes in the obvious way
-@x module 424 gets new code at the beginning
-@y
-if cur_chr>glue_val then
- begin cur_val:=line; cur_val_level:=int_val;
- end
-else
-@z
-
-364. New feature \holdinginserts suggested by Mittelbach.
-@x modules 236--238 get a new integer parameter
-@d int_pars=53 {total number of integer parameters}
-@y
-@d holding_inserts_code=53 {do not remove insertion nodes from \.{\\box255}}
-@d int_pars=54 {total number of integer parameters}
-@z and appropriate further lines are added to match all the other parameters
-@x module 1014
-@<Prepare all the boxes involved in insertions to act as queues@>;
-q:=hold_head; link(q):=null; prev_p:=page_head; p:=link(prev_p);
-while p<>best_page_break do
- begin if type(p)=ins_node then @<Either insert the material
- specified by node |p| into the appropriate box, or
- hold it for the next page; also delete node |p| from
- the current page@>
-@y
-if holding_inserts<=0 then
- @<Prepare all the boxes involved in insertions to act as queues@>;
-q:=hold_head; link(q):=null; prev_p:=page_head; p:=link(prev_p);
-while p<>best_page_break do
- begin if type(p)=ins_node then
- begin if holding_inserts<=0 then
- @<Either insert the material specified by node |p| into the
- appropriate box, or hold it for the next page;
- also delete node |p| from the current page@>;
- end
-@z
-% also insert begin...end around the Pascal code of module 1018
-
-365. New \badness feature (which I'd been resisting for years)
-@x module 416 gets a new definition and a new statement
-@y
-@d badness_code=glue_val+2 {code for \.{\\badness}}
-primitive("badness",last_item,badness_code);
-@!@:badness_}{\.{\\badness} primitive@>
-@z and module 417 changes in the obvious way
-@x module 424 (the new code just added in #363)
- begin cur_val:=line; cur_val_level:=int_val;
-@y
- begin if cur_chr=input_line_no_code then cur_val:=line
- else cur_val:=last_badness; {|cur_chr=badness_code|}
- cur_val_level:=int_val;
-@z
-@x module 646 gets a new global variable
-@y
-@!last_badness:integer; {badness of the most recently packaged box}
-@z
-@x module 648
-@ @<Set init...@>=adjust_tail:=null;
-@y
-@ @<Set init...@>=adjust_tail:=null; last_badness:=0;
-@z
-@x modules 649 and 668
-@!b:integer; {badness of the new box}
-begin r:=get_node(box_node_size); type(r):=hlist_node;
-@y (except it's vlist_node in 668)
-begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node;
-@z (except it's vlist_node in 668)
-% change b to last_badness in modules 660&674 (4 times), 667&678 (3 times)
-@x modules 658 and 673
-if (hbadness<inf_bad)and(o=normal)and(list_ptr(r)<>null) then
-@y (except it's vbadness in 673)
-if o=normal then if list_ptr(r)<>null then
-@z
-@x modules 664 and 676
- begin set_glue_ratio_one(glue_set(r)); {this is the maximum shrinkage}
-@y
- begin last_badness:=1000000;
- set_glue_ratio_one(glue_set(r)); {use the maximum shrinkage}
-@z
-@x ibid
-else if (hbadness<100)and(o=normal)and(list_ptr(r)<>null) then
-@y (except it's vbadness in 676)
-else if o=normal then if list_ptr(r)<>null then
-@z
-
-366. New \emergencystretch feature
-@x modules 247--248 get a new dimen parameter
-@d dimen_pars=20 {total number of dimension parameters}
-@y
-@d emergency_stretch_code=20 {reduces badnesses on final pass of line-breaking}
-@d dimen_pars=21 {total number of dimension parameters}
-@z and appropriate further lines are added to match all the other parameters
-@x module 828
-@!second_pass:boolean; {is this our second attempt to break this paragraph?}
-@y
-@!second_pass:boolean; {is this our second attempt to break this paragraph?}
-@!final_pass:boolean; {is this our final attempt to break this paragraph?}
-@z
-% change second_pass to final_pass in modules 854 and 873
-@x module 863
- second_pass:=false;
- end
-else begin threshold:=tolerance; second_pass:=true;
-@y
- second_pass:=false; final_pass:=false;
- end
-else begin threshold:=tolerance; second_pass:=true;
- final_pass:=(emergency_stretch<=0);
-@z
-@x ibid
- @!stat if tracing_paragraphs>0 then print_nl("@@secondpass");@;@+tats@/
- threshold:=tolerance; second_pass:=true; {if at first you don't
- succeed, \dots}
-@y
- if not second_pass then
- begin@!stat if tracing_paragraphs>0 then print_nl("@@secondpass");@;@+tats@/
- threshold:=tolerance; second_pass:=true; final_pass:=(emergency_stretch<=0);
- end {if at first you don't succeed, \dots}
- else begin @!stat if tracing_paragraphs>0 then
- print_nl("@@finalpass");@;@+tats@/
- background[2]:=background[2]+emergency_stretch; final_pass:=true;
- end;
-@z
-
-367. New \errorcontextlines feature suggested by a TUG participant
-@x modules 236--238 get a new integer parameter
-@d int_pars=54 {total number of integer parameters}
-@y
-@d error_context_lines_code=54 {maximum intermediate line pairs shown}
-@d int_pars=55 {total number of integer parameters}
-@z and appropriate further lines are added to match all the other parameters
-@x module 311
-@<Local variables for formatting calculations@>@/
-begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
- {store current state}
-loop@+begin cur_input:=input_stack[base_ptr]; {enter into the context}
- @<Display the current context@>;
- if (state<>token_list) then
- if (name>17) or (base_ptr=0) then goto done;
-@y
-@!nn:integer; {number of contexts shown so far, less one}
-@!bottom_line:boolean; {have we reached the final context to be shown?}
-@<Local variables for formatting calculations@>@/
-begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
- {store current state}
-nn:=-1; bottom_line:=false;
-loop@+begin cur_input:=input_stack[base_ptr]; {enter into the context}
- if (state<>token_list) then
- if (name>17) or (base_ptr=0) then bottom_line:=true;
- if (base_ptr=input_ptr)or bottom_line or(nn<error_context_lines) then
- @<Display the current context@>
- else if nn=error_context_lines then
- begin print_nl("..."); incr(nn); {omitted if |error_context_lines<0|}
- end;
- if bottom_line then goto done;
-@z
-% also insert begin...end around the Pascal code of module 312
-% and add the statement "incr(nn)" to that module
-
-368. char_warning inside hyphenation could clobber old_setting
-@x module 863
-done: @!stat if tracing_paragraphs>0 then end_diagnostic(true);@;@+tats@/
-@y
-done: @!stat if tracing_paragraphs>0 then
- begin end_diagnostic(true); normalize_selector;
- end;@+tats@/
-@z
-
-369. Make ".fmt" more easily switchable (Don Hosek).
-@x module 520 gets a new definition
-@y
-@d format_extension=".fmt" {the extension, as a \.{WEB} constant}
-@z now replace ".fmt" by format_extension in modules 529 and 1328.
-
-370. Possible range check on weird nullfont (Breitenlohner, 16 Oct 89).
-@x module 565
-if (bc>ec+1)or(ec>255) then abort;
-@y
-if (bc>ec+1)or(ec>255) then abort;
-if bc>255 then {|bc=256| and |ec=255|}
- begin bc:=1; ec:=0;
- end;
-@z
-
-371. Prevent save_stack conflicts, e.g. in {\hbox\expandafter{\csname
- \endcsname}} (found by Sullivan).
-@x module 645
-@p procedure scan_spec; {scans a box specification and left brace}
-label found;
-begin if scan_keyword("to") then saved(0):=exactly
-@.to@>
-else if scan_keyword("spread") then saved(0):=additional
-@.spread@>
-else begin saved(0):=additional; saved(1):=0;
- goto found;
- end;
-scan_normal_dimen; saved(1):=cur_val;
-found: save_ptr:=save_ptr+2; scan_left_brace;
-@y
-@p procedure scan_spec(@!c:group_code;@!three_codes:boolean);
- {scans a box specification and left brace}
-label found;
-var @!s:integer; {temporarily saved value}
-@!spec_code:exactly..additional;
-begin if three_codes then s:=saved(0);
-if scan_keyword("to") then spec_code:=exactly
-@.to@>
-else if scan_keyword("spread") then spec_code:=additional
-@.spread@>
-else begin spec_code:=additional; cur_val:=0;
- goto found;
- end;
-scan_normal_dimen;
-found: if three_codes then
- begin saved(0):=s; incr(save_ptr);
- end;
-saved(0):=spec_code; saved(1):=cur_val; save_ptr:=save_ptr+2;
-new_save_level(c); scan_left_brace;
-@z
-@x module 774
-scan_spec; new_save_level(align_group);@/
-@y
-scan_spec(align_group,false);@/
-@z
-@x module 1073
- if t=0 then saved(0):=cur_val@+else saved(0):=-cur_val;
- scan_box;
- end;
-any_mode(leader_ship): begin saved(0):=leader_flag-a_leaders+cur_chr; scan_box;
- end;
-any_mode(make_box): begin saved(0):=0; begin_box;
- end;
-@y
- if t=0 then scan_box(cur_val)@+else scan_box(-cur_val);
- end;
-any_mode(leader_ship): scan_box(leader_flag-a_leaders+cur_chr);
-any_mode(make_box): begin_box(0);
-@z
-@x module 1075
-procedure box_end;
-var p:pointer; {|ord_noad| for new box in math mode}
-begin if saved(0)<box_flag then @<Append box |cur_box| to the current list,
- shifted by |saved(0)|@>
-else if saved(0)<ship_out_flag then @<Store \(c)|cur_box| in a box register@>
-else if cur_box<>null then
- if saved(0)>ship_out_flag then @<Append a new leader node that
- uses |cur_box|@>
-@y
-procedure box_end(@!box_context:integer);
-var p:pointer; {|ord_noad| for new box in math mode}
-begin if box_context<box_flag then @<Append box |cur_box| to the current list,
- shifted by |box_context|@>
-else if box_context<ship_out_flag then @<Store \(c)|cur_box| in a box register@>
-else if cur_box<>null then
- if box_context>ship_out_flag then @<Append a new leader node that
- uses |cur_box|@>
-@z
-@x module 1076
- begin shift_amount(cur_box):=saved(0);
-@y
- begin shift_amount(cur_box):=box_context;
-@z
-@x module 1077
-if saved(0)<box_flag+256 then
- eq_define(box_base-box_flag+saved(0),box_ref,cur_box)
-else geq_define(box_base-box_flag-256+saved(0),box_ref,cur_box)
-@y
-if box_context<box_flag+256 then
- eq_define(box_base-box_flag+box_context,box_ref,cur_box)
-else geq_define(box_base-box_flag-256+box_context,box_ref,cur_box)
-@z
-@x module 1078
- begin append_glue; subtype(tail):=saved(0)-(leader_flag-a_leaders);
-@y
- begin append_glue; subtype(tail):=box_context-(leader_flag-a_leaders);
-@z
-@x module 1079
-procedure begin_box;
-@y
-procedure begin_box(@!box_context:integer);
-@z
-@x ibid
-box_end; {in simple cases, we use the box immediately}
-@y
-box_end(box_context); {in simple cases, we use the box immediately}
-@z
-@x module 1083
-incr(save_ptr); scan_spec;
-if k=hmode then
- if (saved(-3)<box_flag)and(abs(mode)=vmode) then
- new_save_level(adjusted_hbox_group)
- else new_save_level(hbox_group)
-else begin if k=vmode then new_save_level(vbox_group)
- else begin new_save_level(vtop_group); k:=vmode;
-@y
-saved(0):=box_context;
-if k=hmode then
- if (box_context<box_flag)and(abs(mode)=vmode) then
- scan_spec(adjusted_hbox_group,true)
- else scan_spec(hbox_group,true)
-else begin if k=vmode then scan_spec(vbox_group,true)
- else begin scan_spec(vtop_group,true); k:=vmode;
-@z
-@x module 1084
-procedure scan_box; {the next input should specify a box or perhaps a rule}
-begin @<Get the next non-blank non-relax...@>;
-if cur_cmd=make_box then begin_box
-else if (saved(0)>=leader_flag)and((cur_cmd=hrule)or(cur_cmd=vrule)) then
- begin cur_box:=scan_rule_spec; box_end;
-@y
-procedure scan_box(@!box_context:integer);
- {the next input should specify a box or perhaps a rule}
-begin @<Get the next non-blank non-relax...@>;
-if cur_cmd=make_box then begin_box(box_context)
-else if (box_context>=leader_flag)and((cur_cmd=hrule)or(cur_cmd=vrule)) then
- begin cur_box:=scan_rule_spec; box_end(box_context);
-@z
-@x module 1086
-pop_nest; box_end;
-@y
-pop_nest; box_end(saved(0));
-@z
-@x module 1117
-else begin incr(save_ptr); saved(-1):=0; scan_left_brace;
- new_save_level(disc_group); push_nest; mode:=-hmode; space_factor:=1000;
-@y
-else begin incr(save_ptr); saved(-1):=0; new_save_level(disc_group);
- scan_left_brace; push_nest; mode:=-hmode; space_factor:=1000;
-@z
-@x module 1119
-incr(saved(-1)); scan_left_brace; new_save_level(disc_group);
-@y
-incr(saved(-1)); new_save_level(disc_group); scan_left_brace;
-@z
-@x module 1167
-mmode+vcenter: begin scan_spec; new_save_level(vcenter_group); normal_paragraph;
-@y
-mmode+vcenter: begin scan_spec(vcenter_group,false); normal_paragraph;
-@z
-@x module 1172
-scan_left_brace; push_math(math_choice_group);
-@y
-push_math(math_choice_group); scan_left_brace;
-@z
-@x module 1174
-incr(saved(-1)); scan_left_brace; push_math(math_choice_group);
-@y
-incr(saved(-1)); push_math(math_choice_group); scan_left_brace;
-@z
-@x module 1241
- if global then saved(0):=box_flag+256+cur_val
- else saved(0):=box_flag+cur_val;
- scan_optional_equals; scan_box;
-@y
- if global then n:=256+cur_val@+else n:=cur_val;
- scan_optional_equals; scan_box(box_flag+n);
-@z
-
-372. Bugfix 339 didn't go far enough (found by Sch\"opf and Mittelbach).
-@x module 516 [NOTE: THIS AFFECTS ALMOST ALL CHANGE FILES!]
-@ And here's the second.
-@^system dependencies@>
-
-@p function more_name(@!c:ASCII_code):boolean;
-begin if c=" " then more_name:=false
-else begin if (c=">")or(c=":") then
- begin area_delimiter:=pool_ptr; ext_delimiter:=0;
- end
- else if (c=".")and(ext_delimiter=0) then ext_delimiter:=pool_ptr;
- str_room(1); append_char(c); {contribute |c| to the current string}
-@y
-@ And here's the second. The string pool might change as the file name is
-being scanned, since a new \.{\\csname} might be entered; therefore we keep
-|area_delimiter| and |ext_delimiter| relative to the beginning of the current
-string, instead of assigning an absolute address like |pool_ptr| to them.
-@^system dependencies@>
-
-@p function more_name(@!c:ASCII_code):boolean;
-begin if c=" " then more_name:=false
-else begin str_room(1); append_char(c); {contribute |c| to the current string}
- if (c=">")or(c=":") then
- begin area_delimiter:=cur_length; ext_delimiter:=0;
- end
- else if (c=".")and(ext_delimiter=0) then ext_delimiter:=cur_length;
-@z
-@x module 517 [NOTE: THIS DOES TOO, AND SO DOES THE NEXT!]
-else begin cur_area:=str_ptr; incr(str_ptr);
- str_start[str_ptr]:=area_delimiter+1;
-@y
-else begin cur_area:=str_ptr;
- str_start[str_ptr+1]:=str_start[str_ptr]+area_delimiter; incr(str_ptr);
-@z
-@x ibid
-else begin cur_name:=str_ptr; incr(str_ptr);
- str_start[str_ptr]:=ext_delimiter; cur_ext:=make_string;
-@y
-else begin cur_name:=str_ptr;
- str_start[str_ptr+1]:=str_start[str_ptr]+ext_delimiter-area_delimiter-1;
- incr(str_ptr); cur_ext:=make_string;
-@z
-
-373. Allow multiple hyphenmins in the same paragraph (Mike Ferguson).
-@x module 212, two new fields for list_state_record
-@y
- @!lhm_field,@!rhm_field: quarterword;
-@z
-@x module 213, two new macros to access those fields
-@y
-@d lhmin==cur_list.lhm_field {\.{\\lefthyphenmin} at start of paragraph}
-@d rhmin==cur_list.rhm_field {\.{\\righthyphenmin} at start of paragraph}
-@z
-@x module 215, two new initializations
-@y
-lhmin:=0; rhmin:=0;
-@z
-@x module 218
- if nest[p].ml_field<0 then print(" (\output routine)");
-@y
- if m=hmode then@+if(nest[p].lhm_field<>2)or(nest[p].rhm_field<>3)then
- begin print(" (hyphenmin "); print_int(nest[p].lhm_field); print_char(",");
- print_int(nest[p].rhm_field); print_char(")");
- end;
- if nest[p].ml_field<0 then print(" (\output routine)");
-@z
-@x module 891
-l_hyf:=left_hyphen_min-1;@+if l_hyf<0 then l_hyf:=0;
-r_hyf:=right_hyphen_min-1;@+if r_hyf<0 then r_hyf:=0;
-min_hyf:=l_hyf+r_hyf+2; cur_lang:=0;
-@y
-l_hyf:=lhmin; r_hyf:=rhmin; cur_lang:=0;
-@z
-@x module 892
-@!l_hyf,@!r_hyf,@!min_hyf:integer; {limits on fragment sizes}
-@y
-@!l_hyf,@!r_hyf:integer; {limits on fragment sizes}
-@z
-@x module 894
-begin if min_hyf>63 then goto done1;
-prev_s:=cur_p; s:=link(prev_s);
-if s<>null then
- begin @<Skip to node |ha|, or |goto done1| if no hyphenation
- should be attempted@>;
- @<Skip to node |hb|, putting letters into |hu| and |hc|@>;
- @<Check that the nodes following |hb| permit hyphenation and that at least
- |min_hyf| letters have been found, otherwise |goto done1|@>;
-@y
-begin prev_s:=cur_p; s:=link(prev_s);
-if s<>null then
- begin @<Skip to node |ha|, or |goto done1| if no hyphenation
- should be attempted@>;
- if l_hyf+r_hyf>63 then goto done1;
- @<Skip to node |hb|, putting letters into |hu| and |hc|@>;
- @<Check that the nodes following |hb| permit hyphenation and that at least
- |l_hyf+r_hyf| letters have been found, otherwise |goto done1|@>;
-@z
-@x module 899
-if hn<min_hyf then goto done1;
-@y
-if hn<l_hyf+r_hyf then goto done1;
-@z
-@x module 902
-for j:=l_hyf+1 to hn-r_hyf-1 do if odd(hyf[j]) then goto found1;
-@y
-for j:=l_hyf to hn-r_hyf do if odd(hyf[j]) then goto found1;
-@z
-@x module 923
-for j:=0 to hn-r_hyf do
-@y
-for j:=0 to hn-r_hyf+1 do
-@z
-@x ibid
-found: for j:=0 to l_hyf do hyf[j]:=0;
-for j:=0 to r_hyf do hyf[hn-j]:=0
-@y
-found: for j:=0 to l_hyf-1 do hyf[j]:=0;
-for j:=0 to r_hyf-1 do hyf[hn-j]:=0
-@z
-@x module 1091 begins with a new subroutine
-@y
-function norm_min(@!h:integer):small_number;
-begin if h<=0 then norm_min:=1@+else if h>=63 then norm_min:=63@+
-else norm_min:=h;
-end;
-@z
-@x module 1091 then uses the new subroutine
-push_nest; mode:=hmode; space_factor:=1000; clang:=0;
-@y
-lhmin:=norm_min(left_hyphen_min); rhmin:=norm_min(right_hyphen_min);
-push_nest; mode:=hmode; space_factor:=1000; clang:=0;
-@z
-@x module 1341
-@d stored_language(#)==mem[#+1].int {language number, in the range |0..255|}
-@y
-@d what_lang(#)==link(#+1) {language number, in the range |0..255|}
-@d what_lhm(#)==type(#+1) {minimum left fragment, in the range |1..63|}
-@d what_rhm(#)==subtype(#+1) {minimum right fragment, in the range |1..63|}
-@z
-@x module 1356
- print_int(stored_language(p));
-@y
- print_int(what_lang(p)); print(" (hyphenmin ");
- print_int(what_lhm(p)); print_char(",");
- print_int(what_rhm(p)); print_char(")");
-@z
-@x modules 1362 and 1363
-@ @<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=
-if subtype(cur_p)=language_node then cur_lang:=stored_language(cur_p)
-
-@ @<Advance \(p)past a whatsit node in the \(p)pre-hyphenation loop@>=
-if subtype(s)=language_node then cur_lang:=stored_language(s)
-@y
-@ @d adv_past(#)==@+if subtype(#)=language_node then
- begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);@+end
-
-@<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=@+
-adv_past(cur_p)
-
-@ @<Advance \(p)past a whatsit node in the \(p)pre-hyphenation loop@>=@+
-adv_past(s)
-@z
-@x module 1376
- stored_language(tail):=l; clang:=l;
-@y
- what_lang(tail):=l; clang:=l;@/
- what_lhm(tail):=norm_min(left_hyphen_min);
- what_rhm(tail):=norm_min(right_hyphen_min);
-@z
-@x module 1377
- stored_language(tail):=clang;
-@y
- what_lang(tail):=clang;
- what_lhm(tail):=norm_min(left_hyphen_min);
- what_rhm(tail):=norm_min(right_hyphen_min);
-@z
-
-374. Make \par and end_template definitely non-character (Marc van Leeuwen)
-@x module 14 gets a new line
-@y
-if mem_top<256+11 then bad:=7; {we will want |null_list>255|}
-@z
-@x module 334
-primitive("par",par_end,0); par_loc:=cur_val; par_token:=cs_token_flag+par_loc;
-@y
-primitive("par",par_end,256); {cf. |scan_file_name|}
-par_loc:=cur_val; par_token:=cs_token_flag+par_loc;
-@z
-
-375. Alignments must be more robust to prevent crashes (Marc van Leeuwen)
-@x module 324
-else if token_type=u_template then align_state:=0;
-@y
-else if token_type=u_template then
- if align_state>500000 then align_state:=0
- else fatal_error("(interwoven alignment preambles are not allowed)");
-@.interwoven alignment preambles...@>
-@z
-@x module 782
-if (cur_cmd=assign_glue)and(cur_chr=glue_base+tab_skip_code) then
-@y
-if cur_cmd=endv then
- fatal_error("(interwoven alignment preambles are not allowed)");
-@.interwoven alignment preambles...@>
-if (cur_cmd=assign_glue)and(cur_chr=glue_base+tab_skip_code) then
-@z
-@x module 791
-p:=link(q);
-@y
-if align_state<500000 then
- fatal_error("(interwoven alignment preambles are not allowed)");
-@.interwoven alignment preambles...@>
-p:=link(q);
-@z
-
-376. Avoid kern removal in discretionary breaks (Marc van Leeuwen)
-@x module 815
-label done,done1,done2,done3,done4,continue;
-@y
-label done,done1,done2,done3,done4,done5,continue;
-@z
-@x module 866
-glue_node: begin @<If node |cur_p| is a legal breakpoint, call |try_break|@>;
- @<Update the active widths by including the glue in |glue_ptr(cur_p)|@>;
-@y
-glue_node: begin @<If node |cur_p| is a legal breakpoint, call |try_break|;
- then update the active widths by including the glue in |glue_ptr(cur_p)|@>;
-@z
-@x ibid
-disc_node: @<Try to break after a discretionary fragment@>;
-@y
-disc_node: @<Try to break after a discretionary fragment, then |goto done5|@>;
-@z
-@x ibid
-end
-@y
-done5:end
-@z
-Combine modules 868 and 869 into a single module, with a semicolon between.
-@x module 870 (which becomes module 869) gets ... in its title
-@y and the following new code just before its final "end":
-r:=replace_count(cur_p); s:=link(cur_p);
-while r>0 do
- begin @<Add the width of node |s| to |act_width|@>;
- decr(r); s:=link(s);
- end;
-prev_p:=cur_p; cur_p:=s; goto done5;
-@z
-@x Now module 871 becomes 870, and we add a new (very similar) module 871:
-@y
-@ @<Add the width of node |s| to |act_width|@>=
-if is_char_node(s) then
- begin f:=font(s);
- act_width:=act_width+char_width(f)(char_info(f)(character(s)));
- end
-else case type(s) of
- ligature_node: begin f:=font(lig_char(s));
- act_width:=act_width+
- char_width(f)(char_info(f)(character(lig_char(s))));
- end;
- hlist_node,vlist_node,rule_node,kern_node:
- act_width:=act_width+width(s);
- othercases confusion("disc4")
-@:this can't happen disc4}{\quad disc4@>
- endcases
-@z
-@x module 877
-@!disc_break:boolean; {was the current break at a discretionary node?}
-@y
-@!disc_break:boolean; {was the current break at a discretionary node?}
-@!post_disc_break:boolean; {and did it have a nonempty post-break part?}
-@z
-@x ibid
-if cur_p<>null then @<Prune unwanted nodes at the beginning of the next line@>;
-@y
-if cur_p<>null then if not post_disc_break then
- @<Prune unwanted nodes at the beginning of the next line@>;
-@z
-@x module 881
-q:=cur_break(cur_p); disc_break:=false;
-@y
-q:=cur_break(cur_p); disc_break:=false; post_disc_break:=false;
-@z
-@x module 883
- if not is_char_node(s) then if next_break(cur_p)<>null then
- if cur_break(next_break(cur_p))=s then s:=r;
-@y that subtle bug is no longer possible so we can remove the code
-@z
-@x module 884
-link(s):=r; r:=post_break(q); post_break(q):=null;
-@y
-link(s):=r; r:=post_break(q); post_break(q):=null; post_disc_break:=true;
-@z
-
-377. Pick up a few discretionary hyphens that were lost because of
-the new (cautious) algorithm.
-@x module 914
-@ @d advance_major_tail==begin major_tail:=link(major_tail); incr(r_count);
- end
-
-@<Create and append a discretionary node as an alternative...@>=
-begin r:=get_node(small_node_size);
-@y
-@ In this repeat loop we will insert another discretionary if |hyf[j-1]| is
-odd, after both branches of the previous discretionary end at position |j-1|.
-Strictly speaking, we aren't justified in doing this, because we don't know
-that a hyphen after |j-1| is truly independent of those branches. But in almost
-all applications we would rather not lose a potentially valuable hyphenation
-point. (Consider the word `difficult', where the letter `c' is in position |j|.)
-
-@d advance_major_tail==begin major_tail:=link(major_tail); incr(r_count);
- end
-
-@<Create and append a discretionary node as an alternative...@>=
-repeat r:=get_node(small_node_size);
-@z
-@x ibid
-i:=hyphen_passed;
-@y
-i:=hyphen_passed; hyf[i]:=0;
-@z
-@x ibid
-end
-@y
-hyphen_passed:=j-1; link(hold_head):=null;
-until not odd(hyf[j-1])
-@z
-
-378. Undumped trie must also be dumpable again (Breitenlohner, 11 Dec 89)
-@x module 1325
-undump_size(0)(trie_size)('trie size')(j); {|trie_max|}
-for k:=0 to j do undump_hh(trie[k]);
-undump_size(0)(trie_op_size)('trie op size')(j); {|trie_op_ptr|}
-@y
-undump_size(0)(trie_size)('trie size')(j); @+init trie_max:=j;@+tini
-for k:=0 to j do undump_hh(trie[k]);
-undump_size(0)(trie_op_size)('trie op size')(j); @+init trie_op_ptr:=j;@+tini
-@z
-@x ibid
-k:=256;
-while j>0 do
- begin undump(0)(k-1)(k); undump(1)(j)(x); j:=j-x; op_start[k]:=qo(j);
-@y
-init for k:=0 to 255 do trie_used[k]:=min_quarterword;@+tini
-k:=256;
-while j>0 do
- begin undump(0)(k-1)(k); undump(1)(j)(x);@+init trie_used[k]:=qi(x);@+tini
- j:=j-x; op_start[k]:=qo(j);
-@z
-
-379. Allow output routine to access page totals. (Suggested by Frank
-Mittelbach and Chris Rowley, December 1989)
-@x module 421
-begin if page_contents=empty then
-@y
-begin if (page_contents=empty) and (not output_active) then
-@z
-
-380. Slightly more robust recovery and detection of \output anomalies.
-(Suggested by Chris Thompson, provoked by George Russell, January 1990)
-@x module 1026
-begin if loc<>null then @<Recover from an unbalanced output routine@>;
-@y
-begin if (loc<>null) or
- ((token_type<>output_text)and(token_type<>backed_up)) then
- @<Recover from an unbalanced output routine@>;
-@z
-@x module 1027
-help2("Your sneaky output routine has fewer real {'s than }'s.")@/
-@y
-help2("Your sneaky output routine has problematic {'s and/or }'s.")@/
-@z
-
-381. \eqno\aftergroup*$$ should yield * after the $$ (Michael Downes, 29 Jan 90)
-@x module 1194
- begin cur_mlist:=p; cur_style:=text_style; mlist_penalties:=false;
-@y
- begin @<Check that another \.\$ follows@>;
- cur_mlist:=p; cur_style:=text_style; mlist_penalties:=false;
-@z
-@x ibid
-else begin @<Check that another \.\$ follows@>;
-@y
-else begin if a=null then @<Check that another \.\$ follows@>;
-@z
-
-382. Missed a case in the 8-bit change (Wayne Sullivan, 1 Feb 1990)
-@x module 360
- begin if (end_line_char<0)or(end_line_char>127) then incr(limit);
-@y
- begin if end_line_char_inactive then incr(limit);
-@z
-
-383. Linebreaking needs to be more robust when total demerits get
-very high (Frank Mittelbach, 22 Feb 1990)
-@x module 830
-@!artificial_badness:boolean; {has |b| been forced to zero?}
-@y
-@!artificial_demerits:boolean; {has |d| been forced to zero?}
-@z
-@x module 833 (this change is cosmetic only)
-@!minimal_demerits:array[very_loose_fit..tight_fit] of scaled; {best total
- demerits known for current line class and position, given the fitness}
-@!minimum_demerits:scaled; {best total demerits known for current line class
-@y
-@!minimal_demerits:array[very_loose_fit..tight_fit] of integer; {best total
- demerits known for current line class and position, given the fitness}
-@!minimum_demerits:integer; {best total demerits known for current line class
-@z
-@x module 836 here we want to ensure that total_demerits < awful_bad
-minimum_demerits:=minimum_demerits+abs(adj_demerits);
-@y
-if abs(adj_demerits)>=awful_bad-minimum_demerits then
- minimum_demerits:=awful_bad-1
-else minimum_demerits:=minimum_demerits+abs(adj_demerits);
-@z
-@x module 851
-begin @!stat artificial_badness:=false;@+tats@/
-@y
-begin artificial_demerits:=false;@/
-@z
-@x module 854
- begin b:=0; {set badness zero, this break is forced}
- @!stat artificial_badness:=true;@+tats
- end
-@y
- artificial_demerits:=true {set demerits zero, this break is forced}
-@z
-@x module 855
-@<Compute the demerits, |d|, from |r| to |cur_p|@>;
-@y
-if artificial_demerits then d:=0
-else @<Compute the demerits, |d|, from |r| to |cur_p|@>;
-@z
-@x module 856
-if artificial_badness then print_char("*")@+else print_int(b);
-@.*\relax@>
-print(" p="); print_int(pi);
-print(" d="); print_int(d);
-@y
-if b>inf_bad then print_char("*")@+else print_int(b);
-@.*\relax@>
-print(" p="); print_int(pi); print(" d=");
-if artificial_demerits then print_char("*")@+else print_int(d);
-@z
-@x module 859
-d:=line_penalty+b; d:=d*d;
-@y
-begin d:=line_penalty+b;
-if abs(d)>=10000 then d:=100000000@+else d:=d*d;
-@z
-@x ibid
-if abs(fit_class-fitness(r))>1 then d:=d+adj_demerits
-@y
-if abs(fit_class-fitness(r))>1 then d:=d+adj_demerits;
-end
-@z
-
-384. Math fonts may disappear outside of \eqno (Marc van Leeuwen).
-@x module 1194
- if danger then flush_math;
-@y
- danger:=false;
- @<Check that the necessary fonts for math symbols are present;
- if not, flush the current math lists and set |danger:=true|@>;
-@z
-
-385. Forgot to rule out charnode when testing for node type (Marc van Leeuwen).
-@x module 805
- begin if type(q)=unset_node then
- @<Set the unset box |q| and the unset boxes in it@>
- else if type(q)=rule_node then
- @<Make the running dimensions in rule |q| extend to the
- boundaries of the alignment@>;
-@y
- begin if not is_char_node(q) then
- if type(q)=unset_node then
- @<Set the unset box |q| and the unset boxes in it@>
- else if type(q)=rule_node then
- @<Make the running dimensions in rule |q| extend to the
- boundaries of the alignment@>;
-@z
-@x module 903
-if type(hb)=ligature_node then if odd(subtype(hb)) then
-@y
-if not is_char_node(hb) then
- if type(hb)=ligature_node then if odd(subtype(hb)) then
-@z
-@x module 1202
- if p<>null then if type(p)=glue_node then d:=0;
-@y
- if p<>null then if not is_char_node(p) then if type(p)=glue_node then d:=0;
-@z
-
-386. Don't change the font of punctuation before a hyphenated word
- (Scott Allendorf, reported 7 Mar 90)
-@x module 895
-label common_ending,done,found,found1,not_found,not_found+1,exit;
-@y
-label common_ending,done,found,found1,found2,not_found,exit;
-@z
-@x module 903
-if is_char_node(ha) then
- begin init_list:=ha; init_lig:=false; hu[0]:=qo(character(ha));
- end
-else if type(ha)=ligature_node then
- begin init_list:=lig_ptr(ha); init_lig:=true; init_lft:=(subtype(ha)>1);
- hu[0]:=qo(character(lig_char(ha)));
- if init_list=null then if init_lft then
- begin hu[0]:=256; init_lig:=false;
- end; {in this case a ligature will be reconstructed from scratch}
- free_node(ha,small_node_size);
- end
-else goto not_found+1; {no punctuation found}
-s:=cur_p; {we have |cur_p<>ha| because |type(cur_p)=glue_node|}
-while link(s)<>ha do s:=link(s);
-j:=0; goto common_ending;
-not_found+1: j:=1; s:=ha; init_list:=null;
-if not is_char_node(r) then if type(r)=ligature_node then
- if subtype(r)>1 then
- begin j:=0; hu[0]:=256; init_lig:=false;
- end;
-@y
-if is_char_node(ha) then
- if font(ha)<>hf then goto found2
- else begin init_list:=ha; init_lig:=false; hu[0]:=qo(character(ha));
- end
-else if type(ha)=ligature_node then
- if font(lig_char(ha))<>hf then goto found2
- else begin init_list:=lig_ptr(ha); init_lig:=true; init_lft:=(subtype(ha)>1);
- hu[0]:=qo(character(lig_char(ha)));
- if init_list=null then if init_lft then
- begin hu[0]:=256; init_lig:=false;
- end; {in this case a ligature will be reconstructed from scratch}
- free_node(ha,small_node_size);
- end
-else begin {no punctuation found; look for left boundary}
- if not is_char_node(r) then if type(r)=ligature_node then
- if subtype(r)>1 then goto found2;
- j:=1; s:=ha; init_list:=null; goto common_ending;
- end;
-s:=cur_p; {we have |cur_p<>ha| because |type(cur_p)=glue_node|}
-while link(s)<>ha do s:=link(s);
-j:=0; goto common_ending;
-found2: s:=ha; j:=0; hu[0]:=256; init_lig:=false; init_list:=null;
-@z
-
-387. Balance the parens showing on the terminal (for Lispers).
-@x module 304
-@!in_open : 0..max_in_open; {the number of lines in the buffer, less one}
-@y
-@!in_open : 0..max_in_open; {the number of lines in the buffer, less one}
-@!open_parens : 0..max_in_open; {the number of open text files}
-@z
-@x module 331
-in_open:=0; max_buf_stack:=0;
-@y
-in_open:=0; open_parens:=0; max_buf_stack:=0;
-@z
-@x module 362
- begin print_char(")"); force_eof:=false;
- update_terminal; {show user that file has been read}
-@y
- begin print_char(")"); decr(open_parens);
- update_terminal; {show user that file has been read}
- force_eof:=false;
-@z
-@x module 537
-print_char("("); print(name); update_terminal; state:=new_line;
-@y
-print_char("("); incr(open_parens); print(name); update_terminal;
-state:=new_line;
-@z
-@x module 1334
-if job_name=0 then open_log_file;
-@y
-if job_name=0 then open_log_file;
-while open_parens>0 do
- begin print(" )"); decr(open_parens);
- end;
-@z
-
-388. Optimize \ifx\p\q after \let\p=\q (Marc van Leeuwen says that
- AmS-TeX uses this a lot).
-@x module 508
- while (p<>null)and(q<>null) do
- if info(p)<>info(q) then p:=null
- else begin p:=link(p); q:=link(q);
- end;
-b:=((p=null)and(q=null));
-@y
-if p=q then b:=true
-else begin while (p<>null)and(q<>null) do
- if info(p)<>info(q) then p:=null
- else begin p:=link(p); q:=link(q);
- end;
- b:=((p=null)and(q=null));
- end;
-@z
-@x module 538 (while we're at it, might as well optimize this too)
-begin if not input_ln(cur_file,false) then do_nothing;
-@y
-begin if input_ln(cur_file,false) then do_nothing;
-@z
-@x module 1020 (and this)
-else begin wait:=false; s:=ins_ptr(p);
- link(last_ins_ptr(r)):=s; s:=last_ins_ptr(r);
-@y
-else begin wait:=false; s:=last_ins_ptr(r); link(s):=ins_ptr(p);
-@z
-
-389. Treat migration properly in displays (Marc van Leeuwen).
-@x module 1199 (a bad bug that really has bitten)
-adjust_tail:=adjust_head; b:=hpack(p,natural);
-@y
-adjust_tail:=adjust_head; b:=hpack(p,natural); p:=list_ptr(b);
-@z
-@x module 1204
-shift_amount(b):=s+d; append_to_vlist(b);
-if t<>adjust_head then
- begin link(tail):=link(adjust_head); tail:=t;
- end
-@y
-shift_amount(b):=s+d; append_to_vlist(b)
-@z
-@x module 1205
- tail_append(new_penalty(post_display_penalty));
- end
-else begin tail_append(new_penalty(post_display_penalty));
- tail_append(new_param_glue(g2));
- end
-@y
- g2:=0;
- end;
-if t<>adjust_head then {migrating material comes after equation number}
- begin link(tail):=link(adjust_head); tail:=t;
- end;
-tail_append(new_penalty(post_display_penalty));
-if g2>0 then tail_append(new_param_glue(g2))
-@z
-
------------Here I draw the line with respect to further changes
-
-390. Uninitialized nullfont parameters (found by Lance Carnes, 11 May 90).
-@x module 552
-hyphen_char[null_font]:="-"; skew_char[null_font]:=-1;
-@y
-hyphen_char[null_font]:="-"; skew_char[null_font]:=-1;
-bchar_label[null_font]:=non_address;
-font_bchar[null_font]:=non_char; font_false_bchar[null_font]:=non_char;
-@z
-
-391. Disable \write{\the\prevgraf} (B. Jackowski, July 1990).
-@x module 422
-begin nest[nest_ptr]:=cur_list; p:=nest_ptr;
-while abs(nest[p].mode_field)<>vmode do decr(p);
-scanned_result(nest[p].pg_field)(int_val);
-end
-@y
-if mode=0 then scanned_result(0)(int_val) {|prev_graf=0| within \.{\\write}}
-else begin nest[nest_ptr]:=cur_list; p:=nest_ptr;
- while abs(nest[p].mode_field)<>vmode do decr(p);
- scanned_result(nest[p].pg_field)(int_val);
- end
-@z
-
-392. Report correct line number when buffer overflows (George Russell).
-@x module 538
-begin if input_ln(cur_file,false) then do_nothing;
-firm_up_the_line;
-if end_line_char_inactive then decr(limit)
-else buffer[limit]:=end_line_char;
-first:=limit+1; loc:=start; line:=1;
-@y
-begin line:=1;
-if input_ln(cur_file,false) then do_nothing;
-firm_up_the_line;
-if end_line_char_inactive then decr(limit)
-else buffer[limit]:=end_line_char;
-first:=limit+1; loc:=start;
-@z
-
--------------
-Note: When making change 376, I forgot to delete the redundant
-code in module 883, and I should also have changed the name of that
-module. These cosmetic changes (and some changes to the comments)
-were made in version 3.14, in addition to the following two changes.
--------------
-
-393. Show unprintable characters in font id's (Wayne Sullivan, Dec 1990)
-@x module 63
-print(s);
-@y
-slow_print(s);
-@z
-@x module 262 can now be spruced up
-else begin print_esc(""); slow_print(text(p));
-@y
-else begin print_esc(text(p));
-@z
-@x and module 263 likewise
-else begin print_esc(""); slow_print(text(p));
- end;
-@y
-else print_esc(text(p));
-@z
-
-394. Avoid range check if total_pages>65535 (Eberhard Mattes, Dec 1990)
-@x module 642
- dvi_out(total_pages div 256); dvi_out(total_pages mod 256);@/
-@y
- dvi_out((total_pages div 256) mod 256); dvi_out(total_pages mod 256);@/
-@z
-
-395. Less confusing error message (18 Sep 91)
-@x module 436
- begin print_err("Bad math code");
-@.Bad math code@>
- help2("A numeric math code must be between 0 and 32767.")@/
-@y (because a \mathcode can be 32768, but not a \mathchar)
- begin print_err("Bad mathchar");
-@.Bad mathchar@>
- help2("A mathchar number must be between 0 and 32767.")@/
-@z
-
-396. Internal strings should not be expanded even if unprintable;
-i.e., selector=new_string => print(c)==print_char(c), print(s)==slow_print(s).
-This change completes what I began with number 393 (18 Sep 91).
-@x modules 59 and 60 (same change to both)
- else if (@<Character |s| is the current new-line character@>) then
- if selector<pseudo then
- begin print_ln; return;
- end;
-@y
- else if selector>pseudo then
- begin print_char(s); return; {internal strings are not expanded}
- end
- else if (@<Character |s| is the current new-line character@>) then
- if selector<pseudo then
- begin print_ln; return;
- end;
-@z
-@x module 61
-else begin print(format_ident); print_ln;
-@y
-else begin slow_print(format_ident); print_ln;
-@z
-@x module 84
- print(input_stack[base_ptr].name_field);
-@y
- slow_print(input_stack[base_ptr].name_field);
-@z
-@x module 518
-begin print(a); print(n); print(e);
-@y
-begin slow_print(a); slow_print(n); slow_print(e);
-@z
-@x module 536
-print(format_ident); print(" ");
-@y
-slow_print(format_ident); print(" ");
-@z
-@x module 537
-print_char("("); incr(open_parens); print(name); update_terminal;
-@y
-print_char("("); incr(open_parens); slow_print(name); update_terminal;
-@z
-@x module 581
- print(font_name[f]); print_char("!"); end_diagnostic(false);
-@y
- slow_print(font_name[f]); print_char("!"); end_diagnostic(false);
-@z
-@x module 642
- print_nl("Output written on "); print(output_file_name);
-@y
- print_nl("Output written on "); slow_print(output_file_name);
-@z
-@x module 1261
-set_font:begin print("select font "); print(font_name[chr_code]);
-@y
-set_font:begin print("select font "); slow_print(font_name[chr_code]);
-@z
-@x module 1280
-print(s); update_terminal;
-@y
-slow_print(s); update_terminal;
-@z
-@x module 1283
-begin print_err(s);
-@y
-begin print_err(""); slow_print(s);
-@z
-@x module 1328
-print(w_make_name_string(fmt_file)); flush_string;
-print_nl(format_ident)
-@y
-slow_print(w_make_name_string(fmt_file)); flush_string;
-print_nl(""); slow_print(format_ident)
-@z
-@x module 1333
- print(log_name); print_char(".");
-@y
- slow_print(log_name); print_char(".");
-@z
-@x module 1339
-10: print(n);
-@y
-10: slow_print(n);
-@z
-
-397. Retain more right context for reconstructing ligatures (19 Sep 91)
-@x module 892
-@!l_hyf,@!r_hyf:integer; {limits on fragment sizes}
-@y
-@!l_hyf,@!r_hyf:integer; {limits on fragment sizes}
-@!hyf_bchar:halfword; {boundary character after $c_n$}
-@z
-@x module 897
- c:=qo(character(s));
-@y
- hyf_bchar:=character(s); c:=qo(hyf_bchar);
-@z
-@x module 897 again
- s:=link(s);
-@y
- s:=link(s); hyf_bchar:=non_char;
-@z
-@x module 898
-j:=hn; q:=lig_ptr(s);
-@y
-j:=hn; q:=lig_ptr(s);@+if q>null then hyf_bchar:=character(q);
-@z
-@x module 903
-q:=link(hb); link(hb):=null; r:=link(ha); link(ha):=null; bchar:=non_char;
-@y
-q:=link(hb); link(hb):=null; r:=link(ha); link(ha):=null; bchar:=hyf_bchar;
-@z
-
-398. Patch the previous code, which could cause double kerning (CET1, 29 Sep 91)
-@x module 897
- hb:=s; incr(hn); hu[hn]:=c; hc[hn]:=lc_code(c);
- end
- else if type(s)=ligature_node then
- @<Move the characters of a ligature node to |hu| and |hc|;
- but |goto done3| if they are not all letters@>
- else if (type(s)<>kern_node)or(subtype(s)<>normal) then goto done3;
- s:=link(s); hyf_bchar:=non_char;
-@y
- hb:=s; incr(hn); hu[hn]:=c; hc[hn]:=lc_code(c); hyf_bchar:=non_char;
- end
- else if type(s)=ligature_node then
- @<Move the characters of a ligature node to |hu| and |hc|;
- but |goto done3| if they are not all letters@>
- else if (type(s)=kern_node)and(subtype(s)=normal) then hb:=s
- else goto done3;
- s:=link(s);
-@z
-@x module 898
-hb:=s; hn:=j;
-@y
-hb:=s; hn:=j;
-if odd(subtype(s)) then hyf_bchar:=font_bchar[hf]@+else hyf_bchar:=non_char;
-@z
-@x module 903
-if not is_char_node(hb) then
- if type(hb)=ligature_node then if odd(subtype(hb)) then
- bchar:=font_bchar[hf];
-@y
-@z
-
-399. Disallow \setbox in do_assignments (problem found by Robert Hunt, Nov 91)
-@x module 76
-@!deletions_allowed:boolean; {is it safe for |error| to call |get_token|?}
-@y
-@!deletions_allowed:boolean; {is it safe for |error| to call |get_token|?}
-@!set_box_allowed:boolean; {is it safe to do a \.{\\setbox} assignment?}
-@z
-@x module 77
-deletions_allowed:=true; error_count:=0; {|history| is initialized elsewhere}
-@y
-deletions_allowed:=true; set_box_allowed:=true;
-error_count:=0; {|history| is initialized elsewhere}
-@z
-@x module 1241
- scan_optional_equals; scan_box(box_flag+n);
-@y
- if set_box_allowed then scan_box(box_flag+n)
- else begin print_err("Improper "); print_esc("setbox");
-@.Improper \\setbox@>
- help2("Sorry, \setbox is not allowed after \halign in a display,")@/
- ("or between \accent and an accented character."); error;
- end;
-@z
-@x module 1270
- prefixed_command;
-@y
- set_box_allowed:=false; prefixed_command; set_box_allowed:=true;
-@z
-
-400. Defend against negative cur_mu (Wayne Sullivan, Nov 91)
-@x module 716
-begin n:=x_over_n(m,@'200000); f:=remainder;@/
-@y
-begin n:=x_over_n(m,@'200000); f:=remainder;@/
-if f<0 then
- begin decr(n); f:=f+@'200000;
- end;
-@z
-@x module 717
- begin n:=x_over_n(m,@'200000); f:=remainder;@/
-@y
- begin n:=x_over_n(m,@'200000); f:=remainder;@/
- if f<0 then
- begin decr(n); f:=f+@'200000;
- end;
-@z
-
-401. Defend against `|}{|' in |\read| (Michael Downes).
-@x module 483
- store_new_token(cur_tok);
-@y
- if align_state<1000000 then {unmatched `\.\}' aborts the line}
- begin repeat get_token; until cur_tok=0;
- align_state:=1000000; goto done;
- end;
- store_new_token(cur_tok);
-@z
-
-402. Economize string storage under multiple \font defs (B. Jackowski)
-@x module 1257
-@!old_setting:0..max_selector; {holds |selector| setting}
-@y
-@!old_setting:0..max_selector; {holds |selector| setting}
-@!flushable_string:str_number; {string not yet referenced}
-@z
-@x module 1260
-for f:=font_base+1 to font_ptr do
- if str_eq_str(font_name[f],cur_name)and str_eq_str(font_area[f],cur_area) then
- begin if s>0 then
-@y
-flushable_string:=str_ptr-1;
-for f:=font_base+1 to font_ptr do
- if str_eq_str(font_name[f],cur_name)and str_eq_str(font_area[f],cur_area) then
- begin if cur_name=flushable_string then
- begin flush_string; cur_name:=font_name[f];
- end;
- if s>0 then
-@z
-
-403. Don't look for \newlinechar within unprintable chars (B. Raichle, Nov 91)
-@x module 59
-var j:pool_pointer; {current character code position}
-@y
-var j:pool_pointer; {current character code position}
-@!nl:integer; {new-line character to restore}
-@z
-@x
- else if selector>pseudo then
- begin print_char(s); return; {internal strings are not expanded}
- end
- else if (@<Character |s| is the current new-line character@>) then
- if selector<pseudo then
- begin print_ln; return;
- end;
-@y
- else begin if selector>pseudo then
- begin print_char(s); return; {internal strings are not expanded}
- end;
- if (@<Character |s| is the current new-line character@>) then
- if selector<pseudo then
- begin print_ln; return;
- end;
- nl:=new_line_char; new_line_char:=-1;
- {temporarily disable new-line character}
- j:=str_start[s];
- while j<str_start[s+1] do
- begin print_char(so(str_pool[j])); incr(j);
- end;
- new_line_char:=nl; return;
- end;
-@z
-@x module 60
-label exit;
-var j:pool_pointer; {current character code position}
-begin if s>=str_ptr then s:="???" {this can't happen}
-@.???@>
-else if s<256 then
- if s<0 then s:="???" {can't happen}
- else if selector>pseudo then
- begin print_char(s); return; {internal strings are not expanded}
- end
- else if (@<Character |s| is the current new-line character@>) then
- if selector<pseudo then
- begin print_ln; return;
- end;
-j:=str_start[s];
-while j<str_start[s+1] do
- begin print(so(str_pool[j])); incr(j);
- end;
-exit:end;
-label exit;
-var j:pool_pointer; {current character code position}
-begin if s>=str_ptr then s:="???" {this can't happen}
-@.???@>
-else if s<256 then
- if s<0 then s:="???" {can't happen}
- else if selector>pseudo then
- begin print_char(s); return; {internal strings are not expanded}
- end
- else if (@<Character |s| is the current new-line character@>) then
- if selector<pseudo then
- begin print_ln; return;
- end;
-j:=str_start[s];
-while j<str_start[s+1] do
- begin print(so(str_pool[j])); incr(j);
- end;
-exit:end;
-@y
-var j:pool_pointer; {current character code position}
-begin if (s>=str_ptr) or (s<256) then print(s)
-else begin j:=str_start[s];
- while j<str_start[s+1] do
- begin print(so(str_pool[j])); incr(j);
- end;
- end;
-end;
-@z
-
-404. False boundary character logic was incorrect (found by Eberhard
- Mattes and Bernd Raichle, 6 Feb 92)
-@x module 1036
-cur_q:=tail; cur_l:=cur_r; {or |character(lig_stack)|}
-@y the following is needed since cur_r might have been changed to non_char
-cur_q:=tail; cur_l:=character(lig_stack);
-@z
-
-405. New paragraph and resume-after-display should continue current
- \language (Sch\"opf and Thompson, 17 July 92)
-@@@ Undo the changes to modules 212, 213, 215 in change number 373.
-@x module 218
- if m=hmode then@+if(nest[p].lhm_field<>2)or(nest[p].rhm_field<>3)then
- begin print(" (hyphenmin "); print_int(nest[p].lhm_field); print_char(",");
- print_int(nest[p].rhm_field); print_char(")");
- end;
-@y
- if m=hmode then if (nest[p].pg_field <> @'40600000) then
- begin print(" (language"); print_int(nest[p].pg_field mod @'200000);
- print(":hyphenmin"); print_int(nest[p].pg_field div @'20000000);
- print_char(","); print_int((nest[p].pg_field div @'200000) mod @'100);
- print_char(")");
- end;
-@z
-@x module 816
-pop_nest;
-@y prev_graf now carries the language parameters at start of horizontal mode
-init_cur_lang:=prev_graf mod @'200000;
-init_l_hyf:=prev_graf div @'20000000;
-init_r_hyf:=(prev_graf div @'200000) mod @'100;
-pop_nest;
-@z
-@x module 891
-l_hyf:=lhmin; r_hyf:=rhmin; cur_lang:=0;
-@y
-cur_lang:=init_cur_lang; l_hyf:=init_l_hyf; r_hyf:=init_r_hyf;
-@z
-@x module 892
-@!cur_lang:ASCII_code; {current hyphenation table of interest}
-@!l_hyf,@!r_hyf:integer; {limits on fragment sizes}
-@y
-@!cur_lang,@!init_cur_lang:ASCII_code; {current hyphenation table of interest}
-@!l_hyf,@!r_hyf,@!init_l_hyf,@!init_r_hyf:integer; {limits on fragment sizes}
-@z
-@x module 1091
-lhmin:=norm_min(left_hyphen_min); rhmin:=norm_min(right_hyphen_min);
-push_nest; mode:=hmode; space_factor:=1000; clang:=0;@/
-@y
-push_nest; mode:=hmode; space_factor:=1000; set_cur_lang; clang:=cur_lang;
-prev_graf:=(norm_min(left_hyphen_min)*@'100+norm_min(right_hyphen_min))
- *@'200000+cur_lang;
-@z
-@x module 1200
-push_nest; mode:=hmode; space_factor:=1000; clang:=0;
-@y
-push_nest; mode:=hmode; space_factor:=1000; set_cur_lang; clang:=cur_lang;
-prev_graf:=(norm_min(left_hyphen_min)*@'100+norm_min(right_hyphen_min))
- *@'200000+cur_lang;
-@z
-
-406. Avoid (harmless) range errors (Philip Taylor and CET1, 17 Dec 92).
-@x module 934
-var n:small_number; {length of current word}
-@!j:small_number; {an index into |hc|}
-@y
-var n:0..64; {length of current word; not always a |small_number|}
-@!j:0..64; {an index into |hc|}
-@z
-@x module 960
-var k,@!l:small_number; {indices into |hc| and |hyf|}
-@y
-var k,@!l:0..64; {indices into |hc| and |hyf|;
- not always in |small_number| range}
-@z
-
-407. Kerns inserted via boundary chars should not disappear (William E. Baxter,
- 25 Feb 93)
-@x module 837
-Kern nodes for accents are treated specially: They do not
-disappear at a line break.
-@y
-Kern nodes do not disappear at a line break unless they are |explicit|.
-@z
-@x ibid
- math_node,kern_node: if subtype(s)=acc_kern then goto done
- else break_width[1]:=break_width[1]-width(s);
-@y
- math_node: break_width[1]:=break_width[1]-width(s);
- kern_node: if subtype(s)<>explicit then goto done
- else break_width[1]:=break_width[1]-width(s);
-@z
-@x module 839
-plus $l_1$, so the length from |cur_p| to |cur_p| should be $\gamma+l_0+l_1-l$,
-minus the length of nodes that will be discarded after the discretionary break.
-@y (this change and the next two should have been made long ago, with #376!)
-plus $l_1$, so the length from |cur_p| to |cur_p| should be $\gamma+l_0+l_1-l$.
-If the post-break text of the discretionary is empty, a break may also
-discard~|q|; in that unusual case we subtract the length of~|q| and any
-other nodes that will be discarded after the discretionary break.
-@z
-@x module 840
- begin @<Add the width of node |s| to |break_width| and increase |t|,
- unless it's discardable@>;
- s:=link(s);
- end;
-break_width[1]:=break_width[1]+disc_width;
-if t=0 then s:=link(v); {more nodes may also be discardable after the break}
-@y
- begin @<Add the width of node |s| to |break_width|@>;
- s:=link(s);
- end;
-break_width[1]:=break_width[1]+disc_width;
-if post_break(cur_p)=null then s:=link(v);
- {nodes may be discardable after the break}
-@z
-@x module 842 (which now has a new title)
- hlist_node,vlist_node,rule_node:break_width[1]:=break_width[1]+width(s);
- kern_node: if (t=0)and(subtype(s)<>acc_kern) then t:=-1 {discardable}
- othercases confusion("disc2")
-@:this can't happen disc2}{\quad disc2@>
- endcases;
-incr(t)
-@y
- hlist_node,vlist_node,rule_node,kern_node:
- break_width[1]:=break_width[1]+width(s);
- othercases confusion("disc2")
-@:this can't happen disc2}{\quad disc2@>
- endcases
-@z
-@x module 866
-kern_node: kern_break;
-@y
-kern_node: if subtype(cur_p)=explicit then kern_break
- else act_width:=act_width+width(cur_p);
-@z
-@x module 868
- else if precedes_break(prev_p) then try_break(0,unhyphenated);
-@y
- else if precedes_break(prev_p) then try_break(0,unhyphenated)
- else if (type(prev_p)=kern_node)and(subtype(prev_p)<>explicit) then
- try_break(0,unhyphenated);
-@z
-@x module 879
- if subtype(q)=acc_kern then if type(q)=kern_node then goto done1;
-@y
- if type(q)=kern_node then if subtype(q)<>explicit then goto done1;
-@z
-
-408. Prevent boundary kern from disappearing after hyphenation (25 Feb 93)
-@x module 897
- else if (type(s)=kern_node)and(subtype(s)=normal) then hb:=s
-@y
- else if (type(s)=kern_node)and(subtype(s)=normal) then
- begin hb:=s;
- hyf_bchar:=font_bchar[hf];
- end
-@z
-
-409. Avoid potential future bug [P Breitenlohner] (26 Jun 93)
-@x module 628 [shift_amount(leader_box)=0 now but maybe not in extensions]
-dvi_v:=save_v; dvi_h:=save_h; cur_v:=save_v;
-@y
-dvi_v:=save_v; dvi_h:=save_h; cur_v:=base_line;
-@z
-@x module 637
-dvi_v:=save_v; dvi_h:=save_h; cur_h:=save_h;
-@y
-dvi_v:=save_v; dvi_h:=save_h; cur_h:=left_edge;
-@z
-
-410. Mustn't let |non-address| depend on |font_mem_size|
-@x module 549
-@d non_address==font_mem_size {a spurious |font_index|}
-@y
-@d non_address=0 {a spurious |bchar_label|}
-@z
-@x module 916
-if bchar_label[hf]<non_address then {put left boundary at beginning of new line}
-@y
-if bchar_label[hf]<>non_address then {put left boundary at beginning of new line}
-@z
-@x module 1323, this will detect obsolete format files
-undump(0)(font_mem_size)(bchar_label[k]);
-@y
-undump(0)(fmem_ptr-1)(bchar_label[k]);
-@z
-
-411. Allow large |font_mem_size|, many font parameters.
-@x module 549
-@!font_params:array[internal_font_number] of halfword; {how many font
-@y
-@!font_params:array[internal_font_number] of font_index; {how many font
-@z
-
-412. Math kerns are explicit; this matters, after change 405 (W Carlip, Sep 94)
-@x module 717
- width(p):=mu_mult(width(p)); subtype(p):=normal;
-@y
- width(p):=mu_mult(width(p)); subtype(p):=explicit;
-@z
-
-413. Avoid overflow on real-to-integer conversion
-@x module 619
-@!edge:scaled; {left edge of sub-box, or right edge of leader space}
-@y
-@!edge:scaled; {left edge of sub-box, or right edge of leader space}
-@!glue_temp:real; {glue value before rounding}
-@z
-@x module 625
-@ @<Move right or output leaders@>=
-begin g:=glue_ptr(p); rule_wd:=width(g);
-if g_sign<>normal then
- begin if g_sign=stretching then
- begin if stretch_order(g)=g_order then
- rule_wd:=rule_wd+round(float(glue_set(this_box))*stretch(g));
-@^real multiplication@>
- end
- else begin if shrink_order(g)=g_order then
- rule_wd:=rule_wd-round(float(glue_set(this_box))*shrink(g));
-@y
-@ @d vet_glue(#)== glue_temp:=#;
- if glue_temp>float_constant(1000000000) then
- glue_temp:=float_constant(1000000000)
- else if glue_temp<-float_constant(1000000000) then
- glue_temp:=-float_constant(1000000000)
-
-@<Move right or output leaders@>=
-begin g:=glue_ptr(p); rule_wd:=width(g);
-if g_sign<>normal then
- begin if g_sign=stretching then
- begin if stretch_order(g)=g_order then
- begin vet_glue(float(glue_set(this_box))*stretch(g));
-@^real multiplication@>
- rule_wd:=rule_wd+round(glue_temp);
- end;
- end
- else if shrink_order(g)=g_order then
- begin vet_glue(float(glue_set(this_box))*shrink(g));
- rule_wd:=rule_wd-round(glue_temp);
-@z
-@x module 629
-@!edge:scaled; {bottom boundary of leader space}
-@y
-@!edge:scaled; {bottom boundary of leader space}
-@!glue_temp:real; {glue value before rounding}
-@z
-@x module 634
- rule_ht:=rule_ht+round(float(glue_set(this_box))*stretch(g));
-@^real multiplication@>
- end
- else begin if shrink_order(g)=g_order then
- rule_ht:=rule_ht-round(float(glue_set(this_box))*shrink(g));
-@y
- begin vet_glue(float(glue_set(this_box))*stretch(g));
-@^real multiplication@>
- rule_ht:=rule_ht+round(glue_temp);
- end;
- end
- else if shrink_order(g)=g_order then
- begin vet_glue(float(glue_set(this_box))*shrink(g));
- rule_ht:=rule_ht-round(glue_temp);
-@z
-
-414. final cleanup should not retain spurious reference counts (20 Mar 95)
-@x module 1335
-while open_parens>0 do
-@y
-while input_ptr>0 do
- if state=token_list then end_token_list@+else end_file_reading;
-while open_parens>0 do
-@z
-@x module 1335, continued
- cur_if:=subtype(cond_ptr); cond_ptr:=link(cond_ptr);
-@y
- cur_if:=subtype(cond_ptr); temp_ptr:=cond_ptr;
- cond_ptr:=link(cond_ptr); free_node(temp_ptr,if_node_size);
-@z
-@x module 1335, concluded
- begin @!init store_fmt_file; return;@+tini@/
-@y
- begin @!init for c:=top_mark_code to split_bot_mark_code do
- if cur_mark[c]<>null then delete_token_ref(cur_mark[c]);
- store_fmt_file; return;@+tini@/
-@z
-
-415. we need not raise hassles about two-digit years (23 Nov 98)
-@x module 1328
-print_int(year mod 100); print_char(".");
-@y
-print_int(year); print_char(".");
-@z
-
-416. \xleaders often drops the final box (Hiroshi Nakashima, 12 July 99)
-@x modules 627 and 636
- else begin lx:=(2*lr+lq+1) div (2*lq+2); {round|(lr/(lq+1))|}
-@y
- else begin lx:=lr div (lq+1);
-@z
-
-417. disallow 100000 unbalanced }s outside of alignment (Ralf Roth, 30 Aug 01)
-@x module 789
-to another alignment is being scanned.
-
-@<Insert the \(v)\<v_j>...@>=
-begin if scanner_status=aligning then
-@y
-to another alignment is being scanned, or when no alignment preamble is active.
-
-@<Insert the \(v)\<v_j>...@>=
-begin if (scanner_status=aligning) or (cur_align=null) then
-@z
-
-418. don't allow end-template except at end of template (Roth, 30 Aug 01)
-@x module 325
-while (state=token_list)and(loc=null) do end_token_list; {conserve stack space}
-@y
-while (state=token_list)and(loc=null)and(token_type<>v_template) do
- end_token_list; {conserve stack space}
-@z
-@x module 390
-while (state=token_list)and(loc=null) do end_token_list; {conserve stack space}
-@y
-while (state=token_list)and(loc=null)and(token_type<>v_template) do
- end_token_list; {conserve stack space}
-@z
-@x module 1131
-during an entire alignment, until |fin_align| removes it.
-
-@<Declare act...@>=
-procedure do_endv;
-begin if cur_group=align_group then
-@y
-during an entire alignment, until |fin_align| removes it.
-
-A devious user might force an |endv| command to occur just about anywhere;
-we must defeat such hacks.
-
-@<Declare act...@>=
-procedure do_endv;
-begin base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
-while (input_stack[base_ptr].index_field<>v_template) and
- (input_stack[base_ptr].loc_field=null) and
- (input_stack[base_ptr].state_field=token_list) do decr(base_ptr);
-if (input_stack[base_ptr].index_field<>v_template) or
- (input_stack[base_ptr].loc_field<>null) or
- (input_stack[base_ptr].state_field<>token_list) then
- fatal_error("(interwoven alignment preambles are not allowed)");
-@.interwoven alignment preambles...@>
- if cur_group=align_group then
-@z
-
-419. Improve rounding of glue during output.
-@x module 3
-@!@^dirty \PASCAL@>
-@y
-@!@^dirty \PASCAL@>
-
-Incidentally, \PASCAL's standard |round| function can be problematical,
-because it disagrees with the IEEE floating-point standard.
-Many implementors have
-therefore chosen to substitute their own home-grown rounding procedure.
-@z
-@x module 619
-begin this_box:=temp_ptr; g_order:=glue_order(this_box);
-@y
-@!cur_glue:real; {glue seen so far}
-@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
-begin cur_g:=0; cur_glue:=float_constant(0);
-this_box:=temp_ptr; g_order:=glue_order(this_box);
-@z
-@x module 625
-begin g:=glue_ptr(p); rule_wd:=width(g);
-if g_sign<>normal then
- begin if g_sign=stretching then
- begin if stretch_order(g)=g_order then
- begin vet_glue(float(glue_set(this_box))*stretch(g));
-@^real multiplication@>
- rule_wd:=rule_wd+round(glue_temp);
- end;
- end
- else if shrink_order(g)=g_order then
- begin vet_glue(float(glue_set(this_box))*shrink(g));
- rule_wd:=rule_wd-round(glue_temp);
- end;
- end;
-@y
-begin g:=glue_ptr(p); rule_wd:=width(g)-cur_g;
-if g_sign<>normal then
- begin if g_sign=stretching then
- begin if stretch_order(g)=g_order then
- begin cur_glue:=cur_glue+stretch(g);
- vet_glue(float(glue_set(this_box))*cur_glue);
-@^real multiplication@>
- cur_g:=round(glue_temp);
- end;
- end
- else if shrink_order(g)=g_order then
- begin cur_glue:=cur_glue-shrink(g);
- vet_glue(float(glue_set(this_box))*cur_glue);
- cur_g:=round(glue_temp);
- end;
- end;
-rule_wd:=rule_wd+cur_g;
-@z
-@x module 629
-begin this_box:=temp_ptr; g_order:=glue_order(this_box);
-@y
-@!cur_glue:real; {glue seen so far}
-@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio}
-begin cur_g:=0; cur_glue:=float_constant(0);
-this_box:=temp_ptr; g_order:=glue_order(this_box);
-@z
-@x module 634
-begin g:=glue_ptr(p); rule_ht:=width(g);
-if g_sign<>normal then
- begin if g_sign=stretching then
- begin if stretch_order(g)=g_order then
- begin vet_glue(float(glue_set(this_box))*stretch(g));
-@^real multiplication@>
- rule_ht:=rule_ht+round(glue_temp);
- end;
- end
- else if shrink_order(g)=g_order then
- begin vet_glue(float(glue_set(this_box))*shrink(g));
- rule_ht:=rule_ht-round(glue_temp);
- end;
- end;
-@y
-begin g:=glue_ptr(p); rule_ht:=width(g)-cur_g;
-if g_sign<>normal then
- begin if g_sign=stretching then
- begin if stretch_order(g)=g_order then
- begin cur_glue:=cur_glue+stretch(g);
- vet_glue(float(glue_set(this_box))*cur_glue);
-@^real multiplication@>
- cur_g:=round(glue_temp);
- end;
- end
- else if shrink_order(g)=g_order then
- begin cur_glue:=cur_glue-shrink(g);
- vet_glue(float(glue_set(this_box))*cur_glue);
- cur_g:=round(glue_temp);
- end;
- end;
-rule_ht:=rule_ht+cur_g;
-@z
-
-420. Error recovery hindered by missing goto statement (reported by
-David Fuchs, September 2007)
-
-@x module 395
-incr(align_state); long_state:=call; cur_tok:=par_token; ins_error;
-@y
-incr(align_state); long_state:=call; cur_tok:=par_token; ins_error;
-goto continue;
-@z
-
-421. Slight improvement to inner loop speed also eliminates a case
-of "dirty Pascal"
-
-@x module 1035
- begin if character(tail)=qi(hyphen_char[main_f]) then if link(cur_q)>null then
-@y
- begin if link(cur_q)>null then
- if character(tail)=qi(hyphen_char[main_f]) then ins_disc:=true;
-@z
-
-422. Amendment to bugfix 414 (reported by David Fuchs, September 2007)
-
-@x module 1335
- store_fmt_file; return;@+tini@/
-@y
- if last_glue<>max_halfword then delete_glue_ref(last_glue);
- store_fmt_file; return;@+tini@/
-@z
-
-423. Remove leaking glue reference after error (DRF, September 2007)
-
-@x module 1236
- help2("I can't carry out that multiplication or division,")@/
- ("since the result is out of range.");
-@y
- help2("I can't carry out that multiplication or division,")@/
- ("since the result is out of range.");
- if p>=glue_val then delete_glue_ref(cur_val);
-@z
-
-424. Leaders with muglue is henceforth disallowed (indeed, David Fuchs
-observed that it has ever worked, except in 180pt fonts!)
-
-@x module 1078
-if ((cur_cmd=hskip)and(abs(mode)<>vmode))or@|
- ((cur_cmd=vskip)and(abs(mode)=vmode))or@|
- ((cur_cmd=mskip)and(abs(mode)=mmode)) then
-@y
-if ((cur_cmd=hskip)and(abs(mode)<>vmode))or@|
- ((cur_cmd=vskip)and(abs(mode)=vmode)) then
-@z
-
-425. An optimization suggested by Fuchs that I couldn't resist, because
-it improves the inner loop whenever the last letter of a word
-has a lig/kern program. Also another twiddle for the inner loop.
-
-@x module 1039
-if char_tag(main_i)<>lig_tag then goto main_loop_wrapup;
-@y
-if char_tag(main_i)<>lig_tag then goto main_loop_wrapup;
-if cur_r=non_char then goto main_loop_wrapup;
-@z
-@x module 1036
-tail_append(lig_stack) {|main_loop_lookahead| is next}
-@y
-link(tail):=lig_stack; tail:=lig_stack {|main_loop_lookahead| is next}
-@z
-
-426. For robustness, enforce a restriction checked by TFtoPL (suggested
-by DRF)
-
-@x module 365
-if lf<>6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np then abort;
-@y
-if lf<>6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np then abort;
-if (nw=0)or(nh=0)or(nd=0)or(ni=0) then abort;
-@z
-
-427. Tell more precisely the effective size of 1:1 insertions (DEK, 27 Feb 08)
-
-@x module 986
- t:=x_over_n(height(r),1000)*count(t); print_scaled(t);
-@y
- if count(t)=1000 then t:=height(r)
- else t:=x_over_n(height(r),1000)*count(t);
- print_scaled(t);
-@z
-
------------
-999. The absolutely final change (to be made after my death)
-@x module 2
-@d banner=='This is TeX, Version 3.141592' {printed when \TeX\ starts}
-@y
-@d banner=='This is TeX, Version $\pi$' {printed when \TeX\ starts}
-@z
-When this change is made, the corresponding line should be changed in
-Volume B, and also on page 23 of The TeXbook.
-My last will and testament for TeX is that no further changes be made
-under any circumstances. Improved systems should not be called simply `TeX';
-that name, unqualified, should refer only to the program for which I have
-taken personal responsibility. -- Don Knuth
-
- * Possibly nice ideas that will not be implemented
-
-. classes of marks analogous to classes of insertions
-
-. \showcontext to show the current location without stopping for error
-
-. \show commands to be less like errors
-
-. \everyeof to insert tokens before an \input file ends
- (strange example: \everyeof{\noexpand} will allow things
- like \xdef\a{\input foo}!)
-
-. generalize \leftskip and \rightskip to token lists (problems with
- displayed math then)
-
-. generalize \widowline and \clubline to go further into a paragraph
-
-. \lastbox to remove and box a charnode if one is there
-
-. \lastbox to set a new quantity \lastboxshift, to preserve info now lost
-
-. \posttolerance for third pass of line breaking
-
-* Design errors that are too late to fix
-
-. additional parameters should be in symbol fonts to govern the space between
- rules and text in \over, \sqrt, etc.
-
-. multilingual typesetting doesn't work properly when the \lccode changes
- within a paragraph
-
-. large accents cannot be brought close to small letters in math mode
-
-. \hyphenation is not sensitive to \language
-
-* Bad ideas that will not be implemented
-
-. several people want to be able to remove arbitrary elements of lists,
- but that must never be done because some of those elements (e.g. kerns
- for accents) depend on floating point arithmetic
-
-. if anybody wants letter spacing desperately they should put it in their own
- private version (e.g. generalize the hpack routine) and NOT call it TeX.