diff options
Diffstat (limited to 'info/digests/tex-implementors/023')
-rw-r--r-- | info/digests/tex-implementors/023 | 1229 |
1 files changed, 1229 insertions, 0 deletions
diff --git a/info/digests/tex-implementors/023 b/info/digests/tex-implementors/023 new file mode 100644 index 0000000000..ecd29551b0 --- /dev/null +++ b/info/digests/tex-implementors/023 @@ -0,0 +1,1229 @@ +Date: 13 Mar 89 Message No: 023 + +To: TeX implementors and distributors + +From: Barbara Beeton + +Subject: Updates to TEX82.BUG, MF84.BUG + + +The last message was sent to this list two months ago, and though some +additional activity has occurred, I've been delayed in reporting it. +In fact, I'm not sure that what is included here is the latest news, +not having seen my paper mail for more than a week, and Don Knuth is no +longer corresponding with anyone electronically. (I'm preparing this +message from home, having returned from a standards meeting accompanied +by a cold germ.) + +When last I heard from Don, he reported that though a few "trivial" (his +word) bugs had been detected, there was nothing he considered serious +enough to delay his release of TeX 3.0 on the Ides of March -- two days +hence. So, barring the discovery of something of which I'm not aware, I +expect that by the end of this week there will be a new version of TEX.MF +at labrea, with a few inconsequential changes from version 2.993. I will +try to send the information as soon as possible, but I am facing a couple +of deadlines at the Math Society, and for the next week I have promised +to go into seclusion (the AMS thinks it's a vacation) to help prepare the +data for a 10-volume index to TUGboat. + +Enclosed are updates to the files TEX82.BUG and MF84.BUG. Owing to the +quantity of this material and the proximity of the Ides of March, lists +of differences between the new and old WEB files will be sent separately. + + +######################################################################## + +Updates to TEX82.BUG + +% note change in comment on #339; the change code remains the same + +339. \def\\#1{}\input a\\\z failed (Robert Messer, 24Apr88) + ... + +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. (I sincerely hope that there won't be any more) + + +######################################################################## + +Updates to MF84.BUG + +% The following text has been added at the top of the file; the last +% two lines of this block correspond to the first two lines of the +% old file, with some changes. + +This file has been updated periodically ever since METAFONT84 was born. +What you are about to read is "authentic source material" from the +early days before the program converged. Module numbers on the first +entries may bear little relation to those in Volume D. + +Entries are in chronological order; thus the most recent news appears +at the bottom of the file. + +------------------------------------------------------------------------------- + +(rough list of all bugs found in MF after it passed syntax check) +Starting with Version -100.0: [Mar 27, first run, about 00:30] + + #################### + +% New material. + +547. String startup problems corresponding to TeX change 355 (17 Jul 89) +@x module 30 (Warning: This affects most change files!) + overflow("buffer size",buf_size); +@:METAFONT capacity exceeded buffer size}{\quad buffer size@> +@y + @<Report overflow of the input buffer, and abort@>; +@z +@x module 34 +consist of the remainder of the command line, after the part that invoked \MF. +@y +consist of the remainder of the command line, after the part that invoked \MF. + +The first line is special also because it may be read before \MF\ has +input a base 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 base_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); +@:METAFONT capacity exceeded buffer size}{\quad buffer size@> + end +@z +@x module 1193 +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;@/ +max_str_ptr:=str_ptr; max_pool_ptr:=pool_ptr +@z +@x module 1204 +tini@/ +@y +init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr;@/ +max_str_ptr:=str_ptr; max_pool_ptr:=pool_ptr; fix_date_and_time; +tini@/ +@z +@x module 1204 +init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr;@/ +max_str_ptr:=str_ptr; max_pool_ptr:=pool_ptr;@/ +@y +@z + +548. Major changes to allow 8-bit input, cf. TeX82 #359 (11 Sep 89). +@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 22 +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 23 +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 37 +@<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 41 +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 module 60 + begin print(str_pool[j]); incr(j); +@y + begin print(so(str_pool[j])); incr(j); +@z +@x module 85 + begin if str_pool[j]<>"%" then print(str_pool[j]) + else if j+1=str_start[err_help+1] then print_ln + else if str_pool[j+1]<>"%" then print_ln +@y + begin if str_pool[j]<>si("%") then print(so(str_pool[j])) + else if j+1=str_start[err_help+1] then print_ln + else if str_pool[j+1]<>si("%") then print_ln +@z +@x module 199 +char_class[127]:=invalid_class; +@y +for k:=127 to 255 do char_class[k]:=invalid_class; +@z +@x module 200 +@d hash_is_full == (hash_used=1) {test if all positions are occupied} +@d eq_type(#) == eqtb[#].lh {the current ``meaning'' of a symbolic token} +@d equiv(#) == eqtb[#].rh {parametric part of a token's meaning} +@d hash_base=129 {hashing actually starts here} +@y [incidentally I fixed a bug re hash overflow here] +@d eq_type(#) == eqtb[#].lh {the current ``meaning'' of a symbolic token} +@d equiv(#) == eqtb[#].rh {parametric part of a token's meaning} +@d hash_base=257 {hashing actually starts here} +@d hash_is_full == (hash_used=hash_base) {are all positions occupied?} +@z +@x module 210 +for j:=0 to l-1 do buffer[j]:=str_pool[k+j]; +cur_sym:=id_lookup(0,l);@/ +if s>=128 then {we don't want to have the string twice} +@y +for j:=0 to l-1 do buffer[j]:=so(str_pool[k+j]); +cur_sym:=id_lookup(0,l);@/ +if s>=256 then {we don't want to have the string twice} +@z +@x module 223 +begin c:=char_class[str_pool[str_start[r]]]; +@y +begin c:=char_class[so(str_pool[str_start[r]])]; +@z +@x module 717 + begin buffer[first]:=str_pool[j]; incr(j); incr(first); +@y + begin buffer[first]:=so(str_pool[j]); incr(j); incr(first); +@z +@x module 774 +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 912 + else begin cur_exp:=round_unscaled(cur_exp) mod 128; cur_type:=string_type; + if cur_exp<0 then cur_exp:=cur_exp+128; +@y + else begin cur_exp:=round_unscaled(cur_exp) mod 256; cur_type:=string_type; + if cur_exp<0 then cur_exp:=cur_exp+256; +@z +@x module 913 + else n:=str_pool[str_start[cur_exp]] +@y + else n:=so(str_pool[str_start[cur_exp]]) +@z +@x ibid + begin m:=str_pool[k]; +@y + begin m:=so(str_pool[k]); +@z +@x module 976 +for k:=str_start[a] to str_start[a+1]-1 do append_char(str_pool[k]); +for k:=str_start[b] to str_start[b+1]-1 do append_char(str_pool[k]); +@y +for k:=str_start[a] to str_start[a+1]-1 do append_char(so(str_pool[k])); +for k:=str_start[b] to str_start[b+1]-1 do append_char(so(str_pool[k])); +@z +@x module 977 + for k:=str_start[s]+b-1 downto str_start[s]+a do append_char(str_pool[k]) +else for k:=str_start[s]+a to str_start[s]+b-1 do append_char(str_pool[k]); +@y + for k:=str_start[s]+b-1 downto str_start[s]+a do append_char(so(str_pool[k])) +else for k:=str_start[s]+a to str_start[s]+b-1 do append_char(so(str_pool[k])); +@z +@x module 1103 + begin c:=str_pool[str_start[cur_exp]]; goto found; +@y + begin c:=so(str_pool[str_start[cur_exp]]); goto found; +@z +@x module 1160 + for k:=str_start[s] to str_start[s+1]-1 do gf_out(str_pool[k]); + end; +if t<>0 then for k:=str_start[t] to str_start[t+1]-1 do gf_out(str_pool[k]); +@y + for k:=str_start[s] to str_start[s+1]-1 do gf_out(so(str_pool[k])); + end; +if t<>0 then for k:=str_start[t] to str_start[t+1]-1 do gf_out(so(str_pool[k])); +@z +@x module 1192 + 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 1193 + 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 + +549. Make ".base" more easily switchable (see TeX82 log #369). +@x module 775 gets a new definition +@y +@d base_extension=".base" {the extension, as a \.{WEB} constant} +@z now replace ".base" by base_extension in modules 784 and 1200. + +550. "This can't happen" happened because of nonmonotonic rounding + (bug found by Mark Eklof, fixed 7 Oct 89) +@x module 411 +left_x(r):=x_coord(r); +@y +left_x(r):=x_coord(r); +if right_x(p)>x_coord(r) then right_x(p):=x_coord(r); + {we always have |x_coord(p)<=right_x(p)|} +@z +@x ibid +else if x_coord(r)>dest_x then x_coord(r):=dest_x; +@y +else begin if x_coord(r)>dest_x then + begin x_coord(r):=dest_x; left_x(r):=-x_coord(r); right_x(r):=x_coord(r); + end; + if left_x(q)>dest_x then left_x(q):=dest_x + else if left_x(q)<x_coord(r) then left_x(q):=x_coord(r); + end; +@z +@x module 412 +left_x(s):=x_coord(s); +negate(x_coord(s)); right_x(s):=x_coord(s); +negate(left_x(q)); +@y +left_x(s):=x_coord(s); {now |x_coord(r)=right_x(r)<=left_x(s)|} +if left_x(q)<dest_x then left_x(q):=-dest_x +else if left_x(q)>x_coord(s) then left_x(q):=-x_coord(s) +else negate(left_x(q)); +negate(x_coord(s)); right_x(s):=x_coord(s); +@z +@x module 415 +if x_coord(r)>dest_x then x_coord(r):=dest_x +else if x_coord(r)<x_coord(pp) then x_coord(r):=x_coord(pp); +if y_coord(r)<y_coord(pp) then y_coord(r):=y_coord(pp); +left_y(r):=y_coord(r); +@y +if y_coord(r)<y_coord(pp) then y_coord(r):=y_coord(pp); +left_y(r):=y_coord(r); +if right_y(pp)>y_coord(r) then right_y(pp):=y_coord(r); + {we always have |y_coord(pp)<=right_y(pp)|} +@z +@x ibid +else if y_coord(r)>dest_y then y_coord(r):=dest_y; +@y +else begin if y_coord(r)>dest_y then + begin y_coord(r):=dest_y; left_y(r):=-y_coord(r); right_y(r):=y_coord(r); + end; + if left_y(qq)>dest_y then left_y(qq):=dest_y + else if left_y(qq)<y_coord(r) then left_y(qq):=y_coord(r); + end; +@z +@x module 416 +if x_coord(s)>dest_x then x_coord(s):=dest_x +else if x_coord(s)<x_coord(r) then x_coord(s):=x_coord(r); +if y_coord(s)<dest_y then y_coord(s):=dest_y; +if y_coord(s)<y_coord(r) then y_coord(s):=y_coord(r); +right_type(s):=right_type(pp); +left_y(s):=y_coord(s); +negate(y_coord(s)); right_y(s):=y_coord(s); +negate(left_y(qq)); +@y +if y_coord(s)<dest_y then y_coord(s):=dest_y; +if y_coord(s)<y_coord(r) then y_coord(s):=y_coord(r); +right_type(s):=right_type(pp); +left_y(s):=y_coord(s); {now |y_coord(r)=right_y(r)<=left_y(s)|} +if left_y(qq)<dest_y then left_y(qq):=-dest_y +else if left_y(qq)>y_coord(s) then left_y(qq):=-y_coord(s) +else negate(left_y(qq)); +negate(y_coord(s)); right_y(s):=y_coord(s); +@z +@x module 424 +if y_coord(r)>dest_y then y_coord(r):=dest_y +else if y_coord(r)<y_coord(p) then y_coord(r):=y_coord(p); +if x_coord(r)<x_coord(p) then x_coord(r):=x_coord(p); +left_x(r):=x_coord(r);@/ +y_coord(r):=y_coord(r)+x_coord(r); negate(x_coord(r));@/ +right_x(r):=x_coord(r); right_y(r):=right_y(r)-right_x(r);@/ +left_y(q):=left_y(q)+left_x(q); negate(left_x(q));@/ +dest_y:=dest_y+dest_x; negate(dest_x); +@y +if x_coord(p)+y_coord(r)>dest_x+dest_y then + begin y_coord(r):=dest_x+dest_y-x_coord(p); + if left_y(r)>y_coord(r) then + begin left_y(r):=y_coord(r); + if right_y(p)>y_coord(r) then right_y(p):=y_coord(r); + end; + end; +if x_coord(r)<x_coord(p) then x_coord(r):=x_coord(p) +else if x_coord(r)+y_coord(r)>dest_x+dest_y then + x_coord(r):=dest_x+dest_y-y_coord(r); +left_x(r):=x_coord(r); +if right_x(p)>x_coord(r) then right_x(p):=x_coord(r); + {we always have |x_coord(p)<=right_x(p)|} +y_coord(r):=y_coord(r)+x_coord(r); right_y(r):=right_y(r)+x_coord(r);@/ +negate(x_coord(r)); right_x(r):=x_coord(r);@/ +left_y(q):=left_y(q)+left_x(q); negate(left_x(q));@/ +dest_y:=dest_y+dest_x; negate(dest_x); +if right_y(r)>dest_y then right_y(r):=dest_y; +if left_y(q)>dest_y then left_y(q):=dest_y +else if left_y(q)<y_coord(r) then left_y(q):=y_coord(r); +if right_y(r)>left_y(q) then right_y(r):=left_y(q); +@z +@x ibid +else if x_coord(r)>dest_x then x_coord(r):=dest_x +@y +else begin if x_coord(r)>dest_x then + begin x_coord(r):=dest_x; left_x(r):=-x_coord(r); right_x(r):=x_coord(r); + end; + if left_x(q)>dest_x then left_x(q):=dest_x + else if left_x(q)<x_coord(r) then left_x(q):=x_coord(r); + end; +@z +@x module 425 is entirely replace +@y by the following code: +@ @<Subdivide the cubic a second time with respect to $x'-y'$@>= +begin split_cubic(r,t,dest_x,dest_y); s:=link(r);@/ +if x_coord(r)+y_coord(s)>dest_x+dest_y then + begin y_coord(s):=dest_x+dest_y-x_coord(r); + if left_y(s)>y_coord(s) then + begin left_y(s):=y_coord(s); + if right_y(r)>y_coord(s) then right_y(r):=y_coord(s); + end; + end; +if x_coord(s)+y_coord(s)>dest_x+dest_y then x_coord(s):=dest_x+dest_y-y_coord(s) +else begin if x_coord(s)<dest_x then x_coord(s):=dest_x; + if x_coord(s)<x_coord(r) then x_coord(s):=x_coord(r); + end; +right_type(s):=right_type(p); +left_x(s):=x_coord(s); {now |x_coord(r)=right_x(r)<=left_x(s)|} +if left_x(q)<dest_x then + begin left_y(q):=left_y(q)+dest_x; left_x(q):=-dest_x;@+end +else if left_x(q)>x_coord(s) then + begin left_y(q):=left_y(q)+x_coord(s); left_x(q):=-x_coord(s);@+end +else begin left_y(q):=left_y(q)+left_x(q); negate(left_x(q));@+end; +y_coord(s):=y_coord(s)+x_coord(s); right_y(s):=right_y(s)+x_coord(s);@/ +negate(x_coord(s)); right_x(s):=x_coord(s);@/ +dest_y:=dest_y+dest_x; +if right_y(s)>dest_y then right_y(s):=dest_y; +if left_y(q)>dest_y then left_y(q):=dest_y +else if left_y(q)<y_coord(s) then left_y(q):=y_coord(s); +if right_y(s)>left_y(q) then right_y(s):=left_y(q); +end +@z + +551. Major change for extended ligatures. +@x module 11 (this may affect change files) +@!lig_table_size=300; {maximum number of ligature/kern steps} +@y +@!lig_table_size=5000; {maximum number of ligature/kern steps, must be + at least 255 and at most 32510} +@!max_kerns=500; {maximum number of distinct kern amounts} +@z +@x module 14 gets a new line of code +@y +if(lig_table_size<255)or(lig_table_size>32510)then bad:=7; +@z +@x module 186 +@d lig_kern_token=76 {the operators `\&{kern}' and `\.{=:}'} +@d assignment=77 {the operator `\.{:=}'} +@d colon=78 {the operator `\.:'} +@# +@d comma=79 {the operator `\.,'} +@d end_of_statement==cur_cmd>comma +@d semicolon=80 {the operator `\.;', must be |comma+1|} +@d end_group=81 {end a group (\&{endgroup}), must be |semicolon+1|} +@d stop=82 {end a job (\&{end}, \&{dump}), must be |end_group+1|} +@y +@d lig_kern_token=76 + {the operators `\&{kern}' and `\.{=:}' and `\.{=:\char'174}, etc.} +@d assignment=77 {the operator `\.{:=}'} +@d skip_to=78 {the operation `\&{skipto}'} +@d bchar_label=79 {the operator `\.{\char'174\char'174:}'} +@d double_colon=80 {the operator `\.{::}'} +@d colon=81 {the operator `\.:'} +@# +@d comma=82 {the operator `\.,', must be |colon+1|} +@d end_of_statement==cur_cmd>comma +@d semicolon=83 {the operator `\.;', must be |comma+1|} +@d end_group=84 {end a group (\&{endgroup}), must be |semicolon+1|} +@d stop=85 {end a job (\&{end}, \&{dump}), must be |end_group+1|} +@z +@x module 190 +@d max_given_internal=warning_check +@y +@d boundary_char=41 {the right boundary character for ligatures} +@d max_given_internal=41 +@z +@x module 192 gets two new lines of code +@y +primitive("boundarychar",internal_quantity,boundary_char);@/ +@!@:boundary_char_}{\&{boundarychar} primitive@> +@z +@x and module 193 gets one too +@y +int_name[boundary_char]:="boundarychar"; +@z +@x and module 211 gets several +@y (to be inserted in appropriate places) +primitive("::",double_colon,0); +@!@::: }{\.{::} primitive@> +primitive("||:",bchar_label,0); +@!@:::: }{\.{\char'174\char'174:} primitive@> +primitive("skipto",skip_to,0);@/ +@!@:skip_to_}{\&{skipto} primitive@> +@z +@x as does module 212 +@y +bchar_label:print("||:"); +double_colon:print("::"); +skip_to:print("skipto"); +@z +@x module 1093 has new text (see TeX change 362 for module 545) and also this: +@d stop_bit(#)==lig_kern[#].b0 +@d next_char(#)==lig_kern[#].b1 +@d op_bit(#)==lig_kern[#].b2 +@y +@d skip_byte(#)==lig_kern[#].b0 +@d next_char(#)==lig_kern[#].b1 +@d op_byte(#)==lig_kern[#].b2 +@z +@x module 1096 gets a new definition +@y +@d undefined_label==lig_table_size {an undefined local label} +@z +@x ...and some changed declarations +@!char_remainder:array[eight_bits] of eight_bits; {the |remainder| byte} +@!header_byte:array[1..header_size] of -1..255; + {bytes of the \.{TFM} header, or $-1$ if unset} +@!lig_kern:array[0..lig_table_size] of four_quarters; {the ligature/kern table} +@!nl:0..lig_table_size; {the number of ligature/kern steps so far} +@!kern:array[eight_bits] of scaled; {distinct kerning amounts} +@!nk:0..256; {the number of distinct kerns so far} +@y +@!char_remainder:array[eight_bits] of 0..lig_table_size; {the |remainder| byte} +@!header_byte:array[1..header_size] of -1..255; + {bytes of the \.{TFM} header, or $-1$ if unset} +@!lig_kern:array[0..lig_table_size] of four_quarters; {the ligature/kern table} +@!nl:0..32767-256; {the number of ligature/kern steps so far} +@!kern:array[0..max_kerns] of scaled; {distinct kerning amounts} +@!nk:0..max_kerns; {the number of distinct kerns so far} +@z +@x ...and some new declarations +@y +@!skip_table:array[eight_bits] of 0..lig_table_size; {local label status} +@!lk_started:boolean; {has there been a lig/kern step in this command yet?} +@!bchar:integer; {right boundary character} +@!bch_label:0..lig_table_size; {left boundary starting location} +@!ll,@!lll:0..lig_table_size; {registers used for lig/kern processing} +@!label_loc:array[0..256] of -1..lig_table_size; {lig/kern starting addresses} +@!label_char:array[1..256] of eight_bits; {characters for |label_loc|} +@!label_ptr:0..256; {highest position occupied in |label_loc|} +@z +@x module 1097 + end; +for k:=1 to header_size do header_byte[k]:=-1; +bc:=255; ec:=0; nl:=0; nk:=0; ne:=0; np:=0; +@y + skip_table[k]:=undefined_label; + end; +for k:=1 to header_size do header_byte[k]:=-1; +bc:=255; ec:=0; nl:=0; nk:=0; ne:=0; np:=0;@/ +internal[boundary_char]:=-unity; +bch_label:=undefined_label;@/ +label_loc[0]:=-1; label_ptr:=0; +@z +@x module 1104 +procedure set_tag(@!c:eight_bits;@!t:small_number;@!r:eight_bits); +begin if char_tag[c]=no_tag then + begin char_tag[c]:=t; char_remainder[c]:=r; +@y +procedure set_tag(@!c:halfword;@!t:small_number;@!r:halfword); +begin if char_tag[c]=no_tag then + begin char_tag[c]:=t; char_remainder[c]:=r; + if t=lig_tag then + begin incr(label_ptr); label_loc[label_ptr]:=r; label_char[label_ptr]:=c; + end; +@z +@x module 1105 +if (c>" ")and(c<128) then print(c) +@y +if (c>" ")and(c<127) then print(c) +else if c=256 then print("||") +@z +@x module 1106 +label continue; +var @!c,@!cc:eight_bits; {character codes} +@!k:0..256; {index into the |kern| array} +@y +label continue,done; +var @!c,@!cc:0..256; {character codes} +@!k:0..max_kerns; {index into the |kern| array} +@z +% also the previous code of module 1107 is inserted into 1106 +@x modules 1107--1111 are completely replaced +@y by the following new code: +@ @<Store a list of ligature/kern steps@>= +begin lk_started:=false; +continue: get_x_next; +if(cur_cmd=skip_to)and lk_started then + @<Process a |skip_to| command and |goto done|@>; +if cur_cmd=bchar_label then + begin c:=256; cur_cmd:=colon;@+end +else begin back_input; c:=get_code;@+end; +if(cur_cmd=colon)or(cur_cmd=double_colon)then + @<Record a label in a lig/kern subprogram and |goto continue|@>; +if cur_cmd=lig_kern_token then @<Compile a ligature/kern command@> +else begin print_err("Illegal ligtable step"); +@.Illegal ligtable step@> + help1("I was looking for `=:' or `kern' here."); + back_error; next_char(nl):=qi(0); op_byte(nl):=qi(0); rem_byte(nl):=qi(0);@/ + skip_byte(nl):=stop_flag+1; {this specifies an unconditional stop} + end; +if nl=lig_table_size then overflow("ligtable size",lig_table_size); +@:METAFONT capacity exceeded ligtable size}{\quad ligtable size@> +incr(nl); +if cur_cmd=comma then goto continue; +if skip_byte(nl-1)<stop_flag then skip_byte(nl-1):=stop_flag; +done:end + +@ @<Put each...@>= +primitive("=:",lig_kern_token,0); +@!@:=:_}{\.{=:} primitive@> +primitive("=:|",lig_kern_token,1); +@!@:=:/_}{\.{=:\char'174} primitive@> +primitive("=:|>",lig_kern_token,5); +@!@:=:/>_}{\.{=:\char'174>} primitive@> +primitive("|=:",lig_kern_token,2); +@!@:=:/_}{\.{\char'174=:} primitive@> +primitive("|=:>",lig_kern_token,6); +@!@:=:/>_}{\.{\char'174=:>} primitive@> +primitive("|=:|",lig_kern_token,3); +@!@:=:/_}{\.{\char'174=:\char'174} primitive@> +primitive("|=:|>",lig_kern_token,7); +@!@:=:/>_}{\.{\char'174=:\char'174>} primitive@> +primitive("|=:|>>",lig_kern_token,11); +@!@:=:/>_}{\.{\char'174=:\char'174>>} primitive@> +primitive("kern",lig_kern_token,128); +@!@:kern_}{\&{kern} primitive@> + +@ @<Cases of |print_cmd...@>= +lig_kern_token: case m of +0:print("=:"); +1:print("=:|"); +2:print("|=:"); +3:print("|=:|"); +5:print("=:|>"); +6:print("|=:>"); +7:print("|=:|>"); +11:print("|=:|>>"); +othercases print("kern") +endcases; + +@ Local labels are implemented by maintaining the |skip_table| array, +where |skip_table[c]| is either |undefined_label| or the address of the +most recent lig/kern instruction that skips to local label~|c|. In the +latter case, the |skip_byte| in that instruction will (temporarily) +be zero if there were no prior skips to this label, or it will be the +distance to the prior skip. + +We may need to cancel skips that span more than 127 lig/kern steps. + +@d cancel_skips(#)==ll:=#; + repeat lll:=qo(skip_byte(ll)); skip_byte(ll):=stop_flag; ll:=ll-lll; + until lll=0 +@d skip_error(#)==begin print_err("Too far to skip"); +@.Too far to skip@> + help1("At most 127 lig/kern steps can separate skipto1 from 1::."); + error; cancel_skips(#); + end + +@<Process a |skip_to| command and |goto done|@>= +begin c:=get_code; +if nl-skip_table[c]>128 then {|skip_table[c]<<nl<=undefined_label|} + begin skip_error(skip_table[c]); skip_table[c]:=undefined_label; + end; +if skip_table[c]=undefined_label then skip_byte(nl-1):=qi(0) +else skip_byte(nl-1):=qi(nl-skip_table[c]-1); +skip_table[c]:=nl-1; goto done; +end + +@ @<Record a label in a lig/kern subprogram and |goto continue|@>= +begin if cur_cmd=colon then + if c=256 then bch_label:=nl + else set_tag(c,lig_tag,nl) +else if skip_table[c]<undefined_label then + begin ll:=skip_table[c]; skip_table[c]:=undefined_label; + repeat lll:=qo(skip_byte(ll)); + if nl-ll>128 then + begin skip_error(ll); goto continue; + end; + skip_byte(ll):=qi(nl-ll-1); ll:=ll-lll; + until lll=0; + end; +goto continue; +end +@x module 1112 +next_char(nl):=qi(c); op_bit(nl):=qi(cur_mod); stop_bit(nl):=qi(0); +if cur_mod=0 then rem_byte(nl):=qi(get_code) +@y +begin next_char(nl):=qi(c); skip_byte(nl):=qi(0); +if cur_mod<128 then {ligature op} + begin op_byte(nl):=qi(cur_mod); rem_byte(nl):=qi(get_code); + end +@z +@x ibid + begin if nk=256 then overflow("kern",256); +@:METAFONT capacity exceeded kern}{\quad kern@> + incr(nk); + end; + rem_byte(nl):=qi(k); + end +@y + begin if nk=max_kerns then overflow("kern",max_kerns); +@:METAFONT capacity exceeded kern}{\quad kern@> + incr(nk); + end; + op_byte(nl):=kern_flag+(k div 256); + rem_byte(nl):=qi((k mod 256)); + end; +lk_started:=true; +end +@z +@x module 1135 +tfm_two(6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np); + {this is the total number of file words that will be output} +tfm_two(lh); tfm_two(bc); tfm_two(ec); tfm_two(nw); tfm_two(nh); +tfm_two(nd); tfm_two(ni); tfm_two(nl); tfm_two(nk); tfm_two(ne); tfm_two(np); +@y +@<Compute the ligature/kern program offset and implant the + left boundary label@>; +tfm_two(6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+lk_offset+nk+ne+np); + {this is the total number of file words that will be output} +tfm_two(lh); tfm_two(bc); tfm_two(ec); tfm_two(nw); tfm_two(nh); +tfm_two(nd); tfm_two(ni); tfm_two(nl+lk_offset); tfm_two(nk); tfm_two(ne); +tfm_two(np); +@z +% modules 1137&1138 are combined into a single module +% and so are modules 1140--1141, to make room for two new modules. +@x module 1136 is moved to after old module 1141 +@y and changed to the following code: +@ @<Log the subfile sizes of the \.{TFM} file@>= +if bch_label<undefined_label then decr(nl); +wlog_ln('(You used ',nw:1,'w,',@| nh:1,'h,',@| nd:1,'d,',@| ni:1,'i,',@| + nl:1,'l,',@| nk:1,'k,',@| ne:1,'e,',@| + np:1,'p metric file positions'); +wlog_ln(' out of ',@| '256w,16h,16d,64i,',@| + lig_table_size:1,'l,',max_kerns:1,'k,256e,',@| + max_font_dimen:1,'p)'); +end +@z +@x module 1139 is completely replaced +@y by the following three modules: +@ We need to output special instructions at the beginning of the +|lig_kern| array in order to specify the right boundary character +and/or to handle starting addresses that exceed 255. The |label_loc| +and |label_char| arrays have been set up to record all the +starting addesses; we have $-1=|label_loc|[0]<|label_loc|[1]\le\cdots +\le|label_loc|[|label_ptr]|$. + +@<Compute the ligature/kern program offset...@>= +bchar:=round_unscaled(internal[boundary_char]); +if(bchar<0)or(bchar>255)then + begin bchar:=-1; lk_started:=false; lk_offset:=0;@+end +else begin lk_started:=true; lk_offset:=1;@+end; +@<Find the minimum |lk_offset| and adjust all remainders@>; +if bch_label<undefined_label then + begin skip_byte(nl):=qi(255); next_char(nl):=qi(0); + op_byte(nl):=qi(((bch_label+lk_offset)div 256)); + rem_byte(nl):=qi(((bch_label+lk_offset)mod 256)); + incr(nl); {possibly |nl=lig_table_size+1|} + end + +@ @<Find the minimum |lk_offset|...@>= +k:=label_ptr; {pointer to the largest unallocated label} +if label_loc[k]+lk_offset>255 then + begin lk_offset:=0; lk_started:=false; {location 0 can do double duty} + repeat char_remainder[label_char[k]]:=lk_offset; + while label_loc[k-1]=label_loc[k] do + begin decr(k); char_remainder[label_char[k]]:=lk_offset; + end; + incr(lk_offset); decr(k); + until lk_offset+label_loc[k]<256; + {N.B.: |lk_offset=256| satisfies this when |k=0|} + end; +if lk_offset>0 then + while k>0 do + begin char_remainder[label_char[k]] + :=char_remainder[label_char[k]]+lk_offset; + decr(k); + end + +@ @<Output the ligature/kern program@>= +for k:=0 to 255 do if skip_table[k]<undefined_label then + begin print_nl("(local label "); print_int(k); print(":: was missing)"); +@.local label l:: was missing@> + cancel_skips(skip_table[k]); + end; +if lk_started then {|lk_offset=1| for the special |bchar|} + begin tfm_out(255); tfm_out(bchar); tfm_two(0); + end +else for k:=1 to lk_offset do {output the redirection specs} + begin ll:=label_loc[label_ptr]; + if bchar<0 then + begin tfm_out(254); tfm_out(0); + end + else begin tfm_out(255); tfm_out(bchar); + end; + tfm_two(ll+lk_offset); + repeat decr(label_ptr); + until label_loc[label_ptr]<ll; + end; +for k:=0 to nl-1 do tfm_qqqq(lig_kern[k]); +for k:=0 to nk-1 do tfm_four(dimen_out(kern[k])) +@z +@x module 1205 gets a new declaration +@y +@!lk_offset:0..256; {extra words inserted at beginning of |lig_kern| array} +@z + +552. Improved the covering/shortening routines. (18 Dec 89) +@x module 1119 gets a new global variable +@y +@!excess:halfword; {the list is this much too long} +@z +@x module 1120 gives it a value +begin if min_cover(0)<=m then threshold:=0 +@y +begin excess:=min_cover(0)-m; +if excess<=0 then threshold:=0 +@z +@x and module 1122 uses it +begin repeat p:=link(p); info(p):=m; +@y +begin repeat p:=link(p); info(p):=m; +decr(excess);@+if excess=0 then d:=0; +@z +@x and module 1122 also avoids overflow/ambiguous halving +v:=half(l+value(p)); +@y +v:=l+half(value(p)-l); +@z + +553. (Change made by Joe Weening as per message from DEK.) +@x module 1119 +@!excess:halfword; {the list is this much too long} +@y +@!excess:integer; {the list is this much too long} +@z + +554. (I sincerely hope that there won't be any more) + + +######################################################################## + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Character code reference +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Upper case letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ +% Lower case letters: abcdefghijklmnopqrstuvwxyz +% Digits: 0123456789 +% Square, curly, angle braces, parentheses: [] {} <> () +% Backslash, slash, vertical bar: \ / | +% Punctuation: . ? ! , : ; +% Underscore, hyphen, equals sign: _ - = +% Quotes--right left double: ' ` " +%"at", "number" "dollar", "percent", "and": @ # $ % & +% "hat", "star", "plus", "tilde": ^ * + ~ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +[ end of message 023 ] |