diff options
Diffstat (limited to 'Master/texmf-dist/doc/generic/knuth/errata/mf84.bug')
-rw-r--r-- | Master/texmf-dist/doc/generic/knuth/errata/mf84.bug | 2327 |
1 files changed, 2327 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/generic/knuth/errata/mf84.bug b/Master/texmf-dist/doc/generic/knuth/errata/mf84.bug new file mode 100644 index 00000000000..541f3d47e71 --- /dev/null +++ b/Master/texmf-dist/doc/generic/knuth/errata/mf84.bug @@ -0,0 +1,2327 @@ +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] +1. fix_date_and_time was badly patched in INIMF. +2. cur_tok function forgot "cur_tok:=p" at the end; PASCAL doesn't catch that. +3. "multiletter control sequences" msgs should say "symbolic tokens". +Version -99.0: [still Mar 27, done while waiting for WEAVE/TeX output] +4. do_statement should initialize cur_type:=vacuous. +5. find_variable has misplaced p:=equiv(p). +6. one-character primitives shouldn't decrease str_ptr. +7. clear_symbol had "q" at end where I meant to say "p". +8. help message for extra token flushing improved. +9. "buffer[k]" should be "buffer[j]" for 1-character id_lookup. +10. def_delims forgot to get_next afterwards. +11. type_command at beginning of statement wasn't diverted. +12. menu always came out after help message. +13. forgot to return after getting num/str token from token list. +Version -98.0: [March 28] +14. scan_declared_variable flushes too much. +15. ordered pairs: one level of indirection was forgotten. +16. type declarations must add "unknown" bit. +17. semicolon+ added to do_statement cases. +18. base_ident should get max_str_ref. +19. "internal[...]" missing in date for base_ident. +20. do_binary(p,c) should be do_binary(p,d) after continue_path +21. in scan_def after get_clear_symbol I need to get_next. +22. get_next needed at end of scan_def. +23. get_next needed at end of mode_command processing. +24. randomseed missing error typo: `;' for `:='. +25. print_nl("") at beginning of show. +26. refcounts on macro calls were incremented twice. +27. forgot to advance loc after getting num/str token from token list. +28. "/" has the wrong command code. +29. get_x_next needed after, e.g., "1/2" in scan_primary. +30. take_fraction should be make_fraction in call of frac_mult. +31. v:=dep_list(v) forgotten in dep+dep branch of add_or_subtract. +32. q:=link(q) etc misplaced and omitted in p_plus_fq and p_plus_q. +33. dep_finish recycled a dependency list twice. +34. call of dep_finish should use null not cur_exp. +35. decided that "3 3" shouldn't equal 9. +[also put in new code for the addto command] +Version -97.0: [March 29] +36. forget to set q:=qq in scan_expression. +37. first line of print_path: forgot print_ln. +38. typo in set_controls: right_y should be left_y. +39. toss_knot_list forgot that it has a circular list to toss. +40. print_exp shows big nodes backwards. +41. angle brackets didn't look good in print_exp; took them out. +42. left_brace must be between min_tertiary and max_tertiary. +43. prev_dep should point back to tail, not head, of previous list. + (that error was in encapsulate and <Copy the big node>) +44. nonlinear_eq should leave node p vacant, sometimes. +45. conditional routine forgot that get_boolean starts with get_x_next. +46. forgot get_x_next in processing of else. +47. str_ref not initialized by make_string. +48. param_start not initialized properly. +49. "%EXPR" didn't look good in token list. +50. "{loop}" not necessary in forever loops; there's already enough. +51. macro name didn't come out right when tracing macros. +52. macro parameters weren't shown when tracing macros. +53. quote marks missing when displaying strings. +54. parameter names on macro call trace should look nicer. +55. statement beginning with bad token: error message needed. +56. `->' desired in context lines of macro. +57. forgot q:=loop_list_loc(s) in begin_iteration. +[also put in new code for shipout] +Version -96.0: [March 30] +58. forgot loop_type(s):=null in begin_iteration. +59. forgot value(p):=null after type(p):=type(pp) in find_variable. +60. forgot to delete_pen_ref after filling a contour. +61. check that it's a cycle before calling make_spec. +62. "if tracing_stats>0" should be "if internal[tracing_stats]>0"! +63. forgot get_next after showdependencies. +64. forgot link(r):=p at end of dependency list addition. +65. extra `get_x_next' in <Scan a direction...>. +66. typos in last half of <Remove open types...>: mind the p's and q's. +67. take_fraction should be make_fraction in simple case of two givens. +68. in print_exp of unknown type, stop if v=null. +69. showtoken forgot to stop; also should be consistent with TeX. +70. "continue" label needed in error routine, after all. +71. id_lookup should treat length-one identifiers by simpler method. + (in particular, this allows it to find unprintable ones!) +72. need psi[n+1]:=psi[1] in cyclic case of make_choices. +73. tension/controls take primaries as arguments, not expressions. +74. print_spec didn't initialize octant. +75. print_spec: break lines into two, since they are quite long. +76. smooth_moves not called in fill_spec. +77. typo < for > in edge_prep. +78. edge tracing misses half the corners, and forgot to set trace_y. +79. edge_prep needs extra logic when rover=head. +80. make_good should compute cur_d based on good values, not original values; + but we sometimes need the other alternative too. +81. valid_sum: the test was backwards. +82. print_weight blunder: ho(q) should be ho(info(q)). +83. forgot init_gf in shipout. +84. typo in <Finish the GF file>: if total_chars<>1 then print("s"). +85. initializations of ww, prev_w, and m were forgotten in ship_out. +86. typos in initialization of prev_m and gf_min_x. +87. forgot to update prev_n in ship_out. +88. relax becomes "expandable". +89. internal[x]>1 should be internal[x]>unity! +90. forgot to restore normal scanner_status in pass_text. +91. (end occurred when if...) was inevitable. +[also put in new code for openwindow, display] +Version -95.0: [April 1] +92. forgot to unscale the window numbers in that new code. +93. had w<0 test instead of w<=0 in <Record a possible transition...>. +94. prev_w:=w should be done in all cases of <Record a possible...>. +95. forgot get_x_next after scanning `1/2'. +96. in do_assignment, after recycle_value(p) I need to set type(p):=something. +97. omit `.' after the equivalent in showtoken. +98. in <Copy the big node p>, I said "until q=p"; I meant "until q=value(p)". +99. print_macro_name said "info(link(a))"; meant "text(info(info(link(a))))". +100. forgot get_x_next after macro_call in scan_primary. +101. scan_primary installed dependent components badly (data structure error). +102. new_structure failed in case of generic_subscript (data structure error). +103. param_type case of print_cmd_mod had bad if/else nesting (language error). +104. null_path forgot to return a value (language error). +105. p_with_x_becoming_q had typos (q and f for x). +106. <Copy the big node...> should end with cur_exp:=t, not r. +107. subscripted definitions: out of sync; scan_primary loop needs revision. +108. secondarydef went through scan_def instead of make_op_def. +109. make_op_def forgot the final get_next. +110. make_op_def also forgot to insert the general_macro preface. +111. showvar shows too much of macro variables. +Version -94.0: [April 4] +112. single_dependency needs to take account of the scale factor. +113. add_or_subtract starts out with wrong v value. [bug 31 was fixed wrong] +114. print_exp needs a case for t=independent. +115. also numeric_type, and case v=null of pair_type, transform_type. +116. end_token_list thought identity_macro and insertions had ref counts. +117. disp_var should display also in case of generic subscripts. +118. find_var should put value(pp):=null when it sets type(pp):=numeric_type. +119. yet another problem in <Copy the big...>: copy_dep_list(dep_list(q)). +120. scan_primary should flush_node_list(q) before make_exp_copy(p). +121. make_scaled arguments reversed in p_over_v. +[also added code for new internals: smoothing, autorounding] +[also added code for showstats] +Version -90.0: [April 5] +122. Should check range of variables when they become known. +123. <Exclaim about...> should include begin...end (WEB language error). +124. forever should be followed by a colon. +125. dangling else problem in make_eq: "abc"="abc" considered false. +126. showstats, showtoken should read the semicolon before stopping. +127. print_variable_name balked at, e.g., xpart of a capsule. +Version -89.0: [April 6] +128. after &foo, shouldn't assume there's an input file present. +129. forever forgot get_next. +130. pair=path and path=pair should coerce the pair to be a path. +131. similarly in the operand to `addto'. +[added new code for cull command] +[minor revision of internal quantities; e.g., labeling is out, fontmaking is in] +Version -88.0: [April 7] +132. "string" operator is renamed "str". +133. min/max coordinates added to boc command. +134. labeling_command removed; it will be implemented in macros. +135. info(p) should be attr_loc(p) in flush_variable. +136. make_spec didn't realize the need for xh and yh. +137. gf_new_row parameters had sign reversed. +138. the "numeric" case was left out of recycle_value. +[added new code for special/numspecial] +Version -87.0: [April 13] +139. q:=qq should apply also after <Splice...>, in scan_expr. +140. param_size: better defined than a constant. +141. surprise: back_input fails when cur_cmd=expr_arg, as it changes limit. +142. <Subdivide...second time wrt x'-y'> forgot to change right_type(r). +143. show <path> shows the whole path. +144. expr like 0..1 leads to <Determine the path join...> with q undefined. +145. typos in <Decide...clockwise>, clobbered dx2 and used right_type(p) twice. +146. need to adjust expr_arg when macro is inside a macro! +147. expr_arg forbidden to be in a text argument. +148. frozen_relax added to prevent premature termination. +[I took out the code used for debugging the screen interface] +[added "cycle", a unary operator taking path to boolean] +[added the code for concatenation and for str and for xpart..yypart] +Version -86.0: [April 25] +149. not_scolded_yet was never set false after scolding. +150. Missing "q:=s" at the end of <Make variable q known>. +151. In @<Worry...@>, add get_next after back_error. +152. New xpart routine didn't recycle other components of the big node. +[added the "hard_times" case of multiplication] +[added the complete set of boolean expressions] +[added the eight transformations, applied to three kinds of expressions] +[added the save command] +[added the interim command] +[added the let command] +[added the pen operations] +153. Incomplete help message on "Not a variable". +154. forgot begin...end in the last section of materialize_pen. +155. blunder <Insert a new line...>: length(p,s,q) should be length(s,q,r). +156. <Construct the offset...>: forgot begin...end here too. +157. "(newly created)" shd be " (newly created)". +158. path_trans: forgot to unstash the capsule p. +159. set_up_trans: transform_type should be transformed_by, in one place. +160. <Install sines...>: had p instead of q, in several places. +161. edges_trans: an edges variable isn't in a capsule. +Version -85.0: [May 2] +162. begingroup ... endgroup should be allowed as compound statement. +163. pausing shouldn't clobber "showit". (WAITS version only) +164. Improved help message for isolated expressions. +165. Bad error recovery after "Not a variable" in showvar. +166. Typo in clear_symbol: name_type(p) instead of name_type(q). +167. "%" and ";" to be left out of file names being input. +168. dep_finish used v for two purposes; wrong declared type. +169. autorounding 2 suppresses correction when the derivative isn't critical. +170. tab characters should be changed to spaces on input. (WAITS version) +171. harmful goto: Forgot to |return| after path_trans and edge_trans. +[added ord, hex, oct, length, char, decimal, and jobname] +Version -80.0: [May 4] +172. showvar still screwed up. +173. don't clobber screen for prompt_input (WAITS only). +174. length of non-cyclic path is one too high. +175. <Evoke an error message...> evoked the wrong message. +176. better error message needed on `Equation cannot be performed'. +177. ">> " inserted before expression displays. +178. <Finish linking...> should dup_offset also when n=0. +179. pencircle was a factor of 2 too big. +180. cosine of 180 should be -1 exactly. +181. ord "" should be -1. +182. shipout should allow expressions as well as variables. +183. "mod outer_tag" needed in various tests on eq_type. +184. merge_edges forgot to adjust for changes in m_offsets. +185. typo, ww for w in print_pen. +186. typo, "outer" for "errhelp" in print_cmd_mod (message case). +[added "also"] +[added "message", "errmessage", "errhelp"] +[added "outer", "inner"] +[added "readterminal", "readstring"] +Version -79.0: [May 6] +187. read_toks forgot to include the general_macro token. +188. offset_prep should treat n=0 like n=1. +189. cusp transitions (from change 169) must be suppressed in envelope case. +190. <Record a line segment...> shouldn't change xp or yp. +191. <Find the initial slope...> was used too late. +192. <Find the index...> had a redundant test (a relic of old code). +193. <Compute test coeff...> wastefully made the same fraction three times. +194. doublepath <cycle> should split the cycle. +195. `if k=0' in fin_offset_prep should have been `if k=1'. +196. `done:' misplaced in <Make the envelope moves...>. +197. also move[move_ptr] should be initialized to 1 there, not 0. +198. skew is used with p=q in fill_envelope. +199. it's no use tracing subdivision for offsets, since everything is skewed. +200. in <Record a line...>, round_unscaled should be floor_unscaled. +201. unskewing: wrong formula (x was .5 too large). +202. elliptical pens: better correction for the case gamma<=abs(alpha). +203. dual env_move was updated badly, in both <Transfer...> and <Record...>. +204. dual env_move to move: subscripts were off by 1. +205. <Insert...dually...> should set ww:=knil(link(h)), not link(h). +[added ++] +Version -70.0: [May 9] +206. suppressed cusp rounding in envelope case too. +207. `show' should use `>> ' when it shows an expression. +208. streamlined the test for bad lambda and mu in |skew|. +209. after linear_eq, must check if type(cur_exp)=known. +210. print_spec surprise: contours might never travel toward the first octant! +211. t0,t1,t2 sign was reversed in <Complete the offset splitting...>. +Version -69.0: [May 10] +212. "showvar" changed to "showvariable". +213. typo: r for r_delim in <Scan a text parameter...>. +214. "newinternal" feature added. +215. <Record a line...dually...> needs to update envmove at end of loop. +216. smooth_moves shouldn't affect the extreme points. +217. floor(unity*(n-1)/n) is unity when n is large; need to be more careful. +218. major improvements to rounding, based on new theory of (x+eps,y+eps^2). +219. pen offsets made symmetrical about the origin. +220. p:=half(p+q) overflow problem in take_fraction, take_scaled. +221. cull_edges now updates the max/min values too. +222. make_spec needs to be more bullet-proof to rounding errors; added `dest's. +223. xmult/ymult/zmult changed to xscaled/yscaled/zscaled. +224. elliptical pens improved by temporarily allowing zero-length lines. +[added edge transposition algorithm] +Version -67.0: [May 17] +225. copy can encounter a vacuous expression, e.g. in a parameter. +226. xy_swap_edges mustn't change w when inserting a large weight. +227. in #222, had typo pp for r in <split ... second time ... x'-y'>. +228. in #222, incorrectly assumed local max = global max of cubic. +Version -66.0: [May 19] +229. bad_binary(c,p) should have been bad_binary(p,c). +230. enabled comparison of unknown strings. +231. fixed ring_delete to avoid unexpected scolding. +232. should store character width info even when proofing<0. +[added all the TFM commands and output routines] +[added the `substring' operation] +[added `point', `precontrol', `postcontrol'; deleted `direction'] +Version -65.0: [May 24] +233. Change error message `(t)point(u)' to `point(t)of(u)'. +234. newinternal to allow a list of tokens. +235. In <Feed...>, should check for overflow before begin_token_list. +236. scan_def didn't allow for the case warning_info=null. +Version -60.0: [May 25] +237. increased param_size. +238. added <boolean><relation><boolean>. +239. <Remove dead cubics> stopped too early if the first cubic was dead. +240. bad_unary, bad_binary should distinguish pair from unknown pair. +241. yet another "m<env_move[move_ptr]" test needs to be inserted. +242. newinternal names need to go in the dump file. +243. delete_mac_ref(v) should be delete_mac_ref(value(p)) in recycle_value. +244. constant in <Decide...clockwise> was scaled instead of fraction. +Version -59.0: [May 27] +245. break up initialize routine into two parts (cf init_prim in TeX) +Version -58.0: [May 28] +246. do_ship_out should scan_expression, not scan_primary. +247. offset_prep might clobber node q, so we need to search for q again. +248. pair "1" = true! (blunder in type_test) +249. allow strings x in `def f(expr x)=def g=x enddef enddef'. +250. allow exprs in text parameters, in sufficiently easy cases. +251. check right delimiters in macro_call. +252. "Bad window number" message gave unscaled value. +253. turnaround feature improves automatic rounding slightly. +254. primaries changed to expressions in window and cull commands. +255. scan_expression should make (0,0){0,0} a path, not a future path. +256. showvariable and showtoken to allow lists; all shows made consistent. +257. new internal quantity "windingcheck". +258. delete warning message about edges never used. +259. vardef: group the righthand side. +260. show commands stop once each. +261. cur_type should be vacuous after equation or assignment on outer level. +Version -57.0: [June 4] +262. added xyzzy diagnostic about effect of autorounding. +263. make_moves now puts xi_corr,eta_corr into halving. +[otherwise "draw (0,0)..(9,-.00002)" and "draw (0,-.00002)..(9,0)" fail badly!] +Version -56.0: [June 6] +264. smooth_moves changed completely; now is LR symmetric, cleaner. +265. changed "unknown" to "known". +266. pair to path conversion now done on length, makepen, reverse, etc. +267. cycle now defined on arguments of any type. +268. (re 218) sign was flipped in ceiling correction of <insert downward...>. +[added union, subpath, penoffset, directiontime, intersectiontimes] + +Note: the first two draw statements in PENS.mf show an interesting effect. +With autorounding, the curves are noticeably better, esp the small one. +But there are two "holes", because of tiny discrepancies that I believe +are unavoidable. +Added later: Actually these are avoided by the new smooth_moves, but +certain others will not be. +Version -50.0 [June 30] +269. smoothing to be shut off at the retrograde transitions +270. more care needed in the rootfinding part of find_direction_time. +271. improved error recovery after "Isolated expression". +Version -40.0 [July 3] --- the first version to be "complete"! +272. trivial change in <Exit...if the derivative $B(x_1,x_2,x_3;t)$...>. +273. check that halfwords are large enough to hold edge/weight data. +274. `path reverse (0,1)' should be true. +275. xy_swap_edges might empty the structure; then x_reflect will fail! +276. fix_offset was being done too often, due to improper range test. +277. parameters come out even when tracingonline=0. +278. step-until wasted r and didn't check syntax carefully. +279. <Scan a group...> had typo: `line' for `group_line'. +280. "You can't dump in a group" error was impossible. +281. need better ETC cutoff in showmacro. +282. print_exp needs to handle independents, because it's used by disp_var. +283. suppress `#### xpart %CAPSULEnnnn' printouts. +[added code for everyjob; this version wasn't complete after all!] +Version -30.0 [July 9] +284. need better error/help after ` if s1=s2' when the strings are unknown. +285. removed autorounding>2; it was leading to more glitches than it was worth. +286. envelope filling of a cycle to be done by two calls of fill_envelope. +287. "null" changed to "vacuous". +288. cyclic path inserted in another path should retain its last arc. +289. introduce several dozen "put_get" errors for improved recovery. +290. suppress "with autorounding" when autorounding hasn't been set. +291. {loop value} came out even when tracingonline=0. +292. show commands should wake up the terminal before showing their output. +293. forgot error message in `if true else'. +Version -20.0 [July 14] +294. need to catch pens that are too large. +295. make_eq dassn't change lhs (because this clobbers the memory links later). +296. string usage is reported too high by showstats. +297. bilin1 and add_mult_dep can call p_plus_fq with type(q)=proto_dependent. +298. <Transform a known big node> forgot to recycle pp. +299. in change number 286, the weight of the two paths should be the same. +300. print_ln sometimes changed to print_nl("") in order to avoid blank lines. +301. xyzzy to be combined with tracingedges. +302. good3 entries should be 1 and 2 (not 1 and 0), to give desired symmetry. +Version -10.0 [July 17] +303. had to add `new_if_limit' to `conditional'. +304. `else' can be incomplete as well as `if' and `elseif'. +305. new help "You can't redefine a parameter." +306. print_edges should use cur_edges, because print_weight does. +307. cull shouldn't round; it should use ordinary inequalities. +308. obliterated variable left `0' token hanging in scan_primary. +309. forgot recycle_value(p) in <Evoke...>. +310. forgot to check improper culling amounts. +311. `on' to be changed to `inwindow'. +312. >=max_tfm_dimen should be simply >. +Version -9.0 [July 19] +313. max_tfm_dimen needs to be decreased by design_size div 2^21. +314. merge test data reporting into the screen display routines. +315. use @# in printout at time of macro expansion tracing. +316. bad recovery after "Incomplete string" error. +317. @ should be usable as a parameter. +318. spacing bad on `missing of' and `too many parameters' errors messages. +319. keep track of largest str_ptr and pool_ptr values; showstats on two lines. +Version -8.0 [July 26] [introduced new test routines to study memory usage] +320. make_pen doesn't recycle the knots +321. flush_below often says free_node(2) on node of size 3. +322. make_eq should recycle and free; do_equation shouldn't +323. re #298 and #309: should also free the value nodes! +324. the replacement text of a bad_var definition should be recycled. +325. token lists left unrecycled in error recovery of addto, cull, display. +Version -7.0 [July 27] +326. showall to put "(see the transcript file)" after >> if not tracingonline. +327. remove redundant code: hex in print_the_digs; second l=1 in idlookup. +328. procedures never called: b_open_in; round_scaled. +329. need to zero cur_mod after back_expr in <Put the left bracket...>. +330. <Print the coefficient...> now catches also numbers that round to 1.0. +331. known_pair logic was obsolete; now it is massively simpler. +332. fix_check_sum now zeroes the negative bytes; this simplifies other code. +333. show_dependencies not to show parts of capsules. +334. forgot to set fix_needed:=false! +335. move fix_needed from add_or_subtract to dep_finish. +336. test fix_needed in bilin1 and add_mult_dep. +337. after back_expr in <Scan a mediation...>, forgot to unstash p. +Version 0.0 [July 28] [Hurray! The preliminary TRAP test is fully passed.] +338. corrected blunder in definition of trans_spec type. (found by Karney) +339. less extreme starting values of gf_min_x and its cousins. +340. uninitialized left_curl was possible. (found by John Hobby) +341. In <Reduce...straight line...>, need to test sign before the `div 3' ops. +342. In pyth_add, remove `+2' when dividing by 4, to prevent overflow. +343. "Not a variable" changed to "Not a suitable variable". +344. known_pair forgot to reset cur_type. +345. round and floor procedures need to work in the presence of huge arguments. +346. major revision to allow independent variables to disappear silently: +346a. delete null_path and <Declare the null value routines>. +346b. delete the hard part of ring_delete, and delete <Scold...for using...>. +346c. stash/unstash/flush_cur_exp routines to allow independent type. +346d. print_exp to allow a ring that contains only capsules. +346e. <Zero out...> becomes <Recycle an independent variable> (major new code). +346f. stash_in needs code to handle the case cur_type=independent. +346g. negation needs code to handle the case cur_type=independent. +346h. take_part needs code to handle the case cur_type=independent. +346i. do_binary needs code to handle either or both operands independent. +346j. frac_mult needs code to handle the case cur_type=independent. +346k. make_eq and try_eq too. +346l. linear_eq needs to check if cur_exp=x and cur_type=independent. +346m. linear_eq displays new dependency only when lhs is interesting. +347. minor improvement for coding style/brevity: the "interesting" function. +348. test `if t<independent' had been left out of print_exp (was dirty PASCAL). +349. (begingroup save x;x+1000 endgroup,0) caused subtle bug during unsave. +350. print_type(known) changed to "known numeric" for consistency. +351. In <Change...to proto_dependent>, didn't watch for coefficients zeroed. +352. check_mem now checks also the links in the dependency lists. +353. null_pen initialization belongs in <Initialize tab...>, not <Set init...>. +354. fix_dependencies has to worry about coefficients dropping to zero. +355. add tracing to frac_mult. +356. need cur_sym>0 at the time of end_read_terminal. (found by S Robinson) +Version 0.1 [August 30] +357. Don't complain about winding_number<=0 when doing a doublepath. +358. Need to test for max_coef=0 in offset_prep. +359. Cusp detection should allow for more rounding error. +360. Major change to path syntax, allowing {dir}..{dir} path joins. +360a. `Fragments' disappear; new_fragment becomes new_knot. +360b. print_path has simpler conventions. +360c. future_path type disappears. +360d. left_brace renumbered and removed from scan_tertiary. +360e. some scan_tertiary code moves to new subroutine scan_direction. +360f. scan_expression has a bunch of new code. +361. scan_expression shouldn't have returned after cycle_hit. +362. abort_path, scrap_knot logic removed from scan_expression. +Version 0.2 [September 12] +363. new operator: makepath <pen primary>. +364. define point/precontrol/postcontrol at endpoints and beyond. (JDH) +365. union replaced by +; negation and subtraction allowed on edges. +366. another new operator: totalweight <edges primary>. (JDH's idea) +367. undelimited parameters may be preceded by an optional = or :=. +368. base_area_length was wrong. (affects CH files)(found by Pavel) +369. internal names to be allowable in suffixes. +370. label not_found was misplaced in do_add_to. (found by PasMESA translator) +371. progress report should be given at time of shipout. +372. procedures make_choices, make_spec,fill_envelope split into shorter pieces. +373. locals of cubic_intersection made global so that people could split it. +Version 0.3 [September 27] +374. allow <future pen> ::= <pen> <transform> +375. equation that's off by .0001 shouldn't be called inconsistent. +376. bug in skew: must compute x_coord(q) and y_coord(q) exactly. +377. right/left/up/down to be assigned to octants 1/5/2/6; was 1/4/2/7. +378. boundedness to be allowed with any tension, and one-sidedly. +379. eliminate coordinate nodes in path lists by passing angles instead (JDH). +380. known_pair to free cur_exp after error msgs that might showdependencies. +381. scan_primary sometimes accessed num before it had a value (found by Pavel). +382. invalid characters should cause error message (suggested by PMB). +Version 0.4 [October 12] +383. allow `0' in response to error prompts. +384. put loop value on error context lines. +385. change `ord' to `ASCII'. +386. scantokens <string primary> to be permitted; readterminal goes away. +387. expandafter <token> to be permitted. +388. improved overflow conventions on make_fraction, make_scaled. +389. variable=<value over 4096> should get its own error message. +390. nice_pair first argument can be any integer. +391. new feature, shortshow commands that don't pause. +392. "harmless" bug in negate_edges, the sorted list can get out of sorts. +393. ni too skimpy (15 instead of 63). (JDH) +394. loop_ptr not initialized. (found by Paul Richards) +395. bug in <Find the approximate type...>, q=null should goto done1. (Richards) +396. empty_edges macro added for readability. +397. x_reflect_edges might as well fix the offset as it goes. +398. blunder: frozen_bad_vardef had the wrong eq_type. +399. "name" changed to "tag". +400. check_arith inserted after division of numeric tokens. +401. stop_bit was not initialized in <Compile a ligature/kern...>. +402. char 127 to be a string of length 1; slow_print added (therefore). +403. pyth_sub added to the repertoire. +404. minor change to calls on "confusion" in make_fraction, make_scaled. (JJW) +Version 0.5 [November 9] +405. 4095.999999 should be erroneous. +406. length <pair> to give the absolute value; argd changed to "angle". +407. get_next changed to get_x_next wherever possible. +408. z1..z2{curl 0} should be equivalent to z1..{curl 0}z2. +409. scantokens "" should be fast. +410. allow undelimited suffix and text parameters. +411. warningcheck to allow large variable values passed over silently. +412. "edges" changed to "picture". +413. "winding" changed to "turning". +414. <If consecutive knots...> had typo, "p" for "q". +415. elliptical pens should have axis symmetry. +416. slow_add introduced to catch arithmetic overflow on addition. +417. add a turningnumber primitive. +418. no carriage return between ">>" and "Edge structure...". +419. install new memory management routines (from TeX version 1.3). +420. generalized cull command. (suggested by Bruce Leban) +421. bad goto: `x..' reports that x is vacuous, loses value of x. +422. shortshows replaced by an internal variable "showstopping". +423. major change, capsule tokens: lots of code and restrictions gone! (JDH) +424. substring(a,b), subpath(a,b) to reverse the result when a>b. +425. new GF format: z goes away. (suggested by ALS) +426. another GF mod: chardw replaced by chardx/chardy, which are scaled. (PMB) +427. make `&' have the same precedence always (not different for strings). +428. wrong error message for 2"s" (bug introduced in change 369). +429. variable l in show_context has to be declared type integer. +430. bug in chop_path when both limits are large. +Version 0.6 [December 10] +431. xoffset and yoffset to be added by shipout. [this affects GF comments] +432. wake_up_terminal, not t_open_out, before "Ouch..." (Scott Robinson) +433. undelimited suffix parameters to allow an optional delimiter, disallow =. +434. showall... to be eliminated; tracingcapsules added. +435. allow undelimited parameters after delimited ones. +436. nullpen test in addto should test for any one-point pen. +437. granularity parameter to affect autorounding (Bruce Leban) +[this leads to major improvements suggested by JDH; lots of code changes!] +[basically, make_spec is now responsible for autorounding; fill_spec just fills] +438. node_size overflow problem must be prevented. (Paul Richards) +439. allow unary + with a picture. +440. nullpen should transform quickly to itself, if not shifted. +441. print_edges should skip over null rows, if it doesn't already. +442. open_base_file improved (following TeX's change number 302). +443. output initialization improved (following TeX's change number 303). +444. operators shouldn't fail because future pen isn't a pen. (JDH) +445. intersection routine to quit in hard cases. (DRF) +446. angle routine was off by epsilon on negative arguments. (Karney) +447. octant assignment should look ahead further in ambiguous cases. (JDH) +448. <Compute the incoming...> forgot that right_type(r)=endpoint could happen. +449. turning_number calculated directly, not times 8. +450. floor_scaled made more efficient by trading subtraction for multiplication. +451. doublepath autorounding to compromise between east and west. (JDH) +452. codes of picture_type and path_type interchanged, to simplify a "case". +Version 0.7 [January 17, 1985] +453. def to allow both := and =. (NB) +454. "keeping" and "dropping" instead of "including" and "excluding". (HWT) +455. (see the transcript...): why, when tracingonline>0? +456. dead cubics need to be removed also before xy_round. (NB) +457. [re 433] I said get_x_next twice; a blunder. +Version 0.75 [January 23, 1985] +458. Abbreviated boc command makes GF format more attractive for lowres. (GusF) +Version 0.76 [February 2] +459. known and unknown might as well both be primitive. +460. ab_vs_cd(a-d,b,c-b,d) simplifies to ab_vs_cd(a,b,c,d). (JDH) +461. (from change 435) <Absorb undelimited...> must use k, not n. +462. (from change 458) max_new_row added, since 165 wasn't updated to 164. +Version 0.77 [February 16] +463. abbreviated version of tracingspecs is desired for turning number errors. +464. improved octant number in pathological cases of quadrant_subdivide (JDH) +465. xoffset,yoffset communicated to GF file when proofing>0. +466. Poirot changed to Marple. +467. reverse<cycle> starts the reversed path at the wrong time. +468. Extra help given after `undefined coordinate' errors. +469. Keep segment numbers from overflowing max_halfword. (JDH) +470. Ditto for pen offset slope numbers. +471. n_magic had min_halfword with wrong sign. (John Johnson) +Version 0.80 [April 1] +472. In errhelp, % means <return>, %% means %. (BPL) +473. tracing of envelopes should give symbolic octant names. +474. (-x mod y) should be ((-x) mod y) in good_val. +475. crossingpoint could overflow on 32-bit machines. (BPL) +476. Improvements to abbreviated format of number 463. +Version 0.81 [April 4] +477. `I hide(showdependencies)' in hint to become `I ???'. +478. print_strange shouldn't wake up the terminal in scroll mode. (cf 463) +479. flush_list procedure made a bit faster. (DRF) +480. bounded velocities to be multiplied by .999 for safety. +481. Detect error in declaration that tries to extend a vardef. +482. print_strange puts turns in parentheses (cf 463). +483. make_name_string shouldn't ever cause string space overflow. +484. allow <picture primary> xscaled m yscaled n. +485. checksum should consider values relative to designsize. (DRF) +[I also increased max_strings to 2000.] + +[Note: Neenie found a case where missing pixels can occur, due to +inconsistent rounding between left-to-right and right-to-left subdivision: +pickup pencircle; draw +(0,126)..controls (130.29451,126) and (288,126.00002) + ..(288,36)..controls (288,143.99998) and (132.97438,144) + ..(0,144)..controls (0,138) and (0,132) + ..cycle; +The "right" way to fix this would be to develop a make_spec routine for +non-cycles, and to copy a reversed spec, so that double paths would be +guaranteed self-inverse. However, my later experiments showed that +autorounding wasn't nearly as useful as I had expected it to be, hence I +decided not to waste time beefing up this routine; no satisfactory +automatic approach to rounding occurs to me.] +Version 0.90 [May 10] +486. 180-degree turns to be clockwise for half of doublepath cycles. +487. introduce fillin parameter. +488. `numeric_type' moved before `known', so that print_exp works (Richards). +489. numeric_type as unary op should include independent in its range (cf 346). +Version 0.91 [May 13] +490. show_token_list gets null_tally parameter. +491. if bad>0, change the code as in TeX changes 315, 316. +492. batchmode change as in TeX 317. +493. "and double autorounding" to be traced, if appropriate. +494. introduce tracingrestores. + *`restoring a bad variable'? +495. put decimal number into gf extension +496. mediation put into scan_primary, so that round .5[a,b] works properly. +497. cubic_intersection now has |tol| to compensate for rounding errors. +498. find_direction_time needs to worry about degenerate case x3=y3=0. +499. crossing_point(a,b,0) now yields fraction_one if a,b>0. +500. diag_round shouldn't insist that b-a is even (see below). +501. macro_call will show_macro with much larger limit. +502. TFM file statistics are logged too. + +* Here's an example (found by Neenie) explaining bugfix 500: +autorounding:=2; draw +(7.03159,-9.31831)..controls (12.14732,-9.4386) and (17.4299,-6.82948) + ..(21.60132,0)..controls (27.47417,9.61507) and (37.87402,15.58647) + ..(43.74687,25.20154)..controls (51.16223,37.34201) and (57.31,50.171) + ..(63.45776,63.00002) withpen pencircle; +The missing pixels are due to the following curious circumstances: (1) the +middle cubic splits into three, when subdividing into octants; (2) the reverse +curve splits too but with slightly different rounding, off by 1; (3) the old +diag_round routine, when it ensures that b-a is even, computes aa=a+1 on +one side of the curve, but aa=a-1 on the other side, thus making the +rounding "safe" on only one side. (Namely, on one side we have consecutive +values + b=1317666 a=1310720 + b=1329617 a=1310721 +and on the other side, + b=-1329618 a=-1310720 + b=-1317667 a=-1310721.) + +* Here's an example (by JDH) showing the necessary of bugfix 497: +path p[]; +p1 = (1,0)..controls (1,0.10493) and (0.98347,0.20921) + ..(0.95105,0.30902)..controls (0.91862,0.40881) and (0.8707,0.50288) + ..(0.80902,0.58778); +p2 = (0,0)..controls (0.63403,0.20601) and (1.26807,0.41203) + ..(1.9021,0.61804); +show p1 intersectiontimes p2; % (-1,-1), without `tol' +pickup pencircle; +currenttransform := identity scaled 150; +draw p1; draw p2; +showit; % but they clearly intersect +Version 0.95 [Aug 12] +503. `Se' changed to `SSE', etc. (suggested by RFS) +504. Inconsisting diagonal rounding was introduced in bugfix 500. + +[the following lines from @<Determine the before...@> in diag_round: + if aa>bb then cc:=dd-half(aa-bb-1)@+else cc:=dd-half(aa-bb+1) + if a>b then c:=d-half(a-b-1)@+else c:=d-half(a-b+1) +were replaced respectively by: + if right_type(p)>switch_x_and_y then cc:=dd-half(aa-bb+1) + else cc:=dd-half(aa-bb-1) + if right_type(p)>switch_x_and_y then c:=d-half(a-b-1) + else c:=d-half(a-b+1) +in order to make the rounding consistent on adjacent octants; +the following command caused `this can't happen': +fill (33,7)..controls (32.63094,5.70827) and (32.06163,3.716) + ..(31.59488,3.36667)..controls (31.10509,3.00009) and (29.14824,3) + ..(27.85318,3)..controls (27.85286,3) and (23.84952,3) + ..(23.8492,3)..controls (23.73282,2) and (23.61646,1) + ..(23.50008,0)..controls (26.66672,0) and (29.83336,0) + ..(33,0)..controls (33.66667,2.33333) and (34.33333,4.66667) + ..(35,7)..controls (34.33333,7) and (33.66667,7) + ..cycle;] +Version 0.96 [Aug 17] +505. allow comparison of transforms. [test by trying t=t when t is new...] +506. {restoring...} shouldn't get through when tracingonline=0. +507. better error message needed on `interim alpha:=0', `interim 0:=0'. +508. make_op_def should put parameters in the other order. +509. <Worry about...> should say get_x_next, not get_next. +510. unif_rand to allow negative x, save on error messages. +511. tidy up chop_string when b<0 and/or a>l. +512. randomseed is automatically logged. +513. change 495 messed up if gf file couldn't be opened. (found by DRF) +[In INIMF.CH, 3-character extensions now have 0--9 or A--Z as leading digit.] +Version 0.97 [Sep 5] +514. a[b,c] to be tried only if a is numeric type. +515. simplified the code for length_op(string_type). +516. citations of `Chapter xx' now replaced by correct references. +517. <Log the subfile sizes...> to be in stat...tats version only. +518. remove extra space after <insert> and <scantokens>. +519. offsets should be included in the tracingoutput output. +520. a vacuous expression should be considered known. +521. charlist syntax changed from commas to colons. +[also the WAITS version command-line reader was fixed to handle `^^W'] +Version 0.99 [Sep 24] +522. vardef's begingroup...endgroup should be accessible. +523. allow an empty expression in for loops. +Version 0.999 [Oct 1] +524. "charfam" changed to "charext". +525. variable tt makes get_node slightly faster. (PROFILE suggests this) +526. cur_cmd<=max should be tested before cur_cmd>=min. (PROFILE) +527. fast_get_avail used in cur_tok and scan_primary. (PROFILE) +Version 0.9999 [Oct 27] +528. Major change to representation of independent variables + ("serial number" added so that MF's equation solving doesn't depend + on vagaries of storage allocation) + [module number change: new module between old 585 and 586] + [in terms of new numbering, modules 232, 585--587, 589, 594, 597, + 601, 608, 610, 816--817, 855, 1198--1199 were affected] +[I also reordered some of the cases in print_op, module 189, +so that the program could be condensed in published version] +Version 0.99999 [Nov 13] +529. forgot to decrease three_l in change 497! +530. cubic_intersection to give approximation if max_patience exceeded. +[the following example, found by NB, motivated this change: + show ( + (36.00104,26.99951)..controls (36.00131,26.99979) and (36.00146,27.00017) + ..(36.00146,27.00055) + )intersectiontimes( + (36,27.00055)..controls (45.17148,21.12364) and (55.83588,18) + ..(66.72873,18) + );] +Version 0.999999 [Dec 2] +531. hold_head needed (scan_toks calls cur_tok calls copy_edges). (D. Kosower) +Version 1.0 [January 4, 1986] +532. Optimization in module 1174, suggested by LER (3 Feb 86) +@x + if delta=0 then gf_out(skip0) + else begin gf_out(skip1); gf_out(delta); + end +@y + begin gf_out(skip1); gf_out(delta); + end +@z +*** Late copies of version 1.0 include this correction; +in particular, the program listing in Volume D was updated (with scissors)! +Changes subsequent to `Version 1.0' as published in C&T, Volume D: +533. Inconsistent punctuation in user messages (found by Karl Berry, June 86) +@x module 1134 +print_nl("Font metrics written on "); print(metric_file_name); +@y +print_nl("Font metrics written on "); print(metric_file_name); print_char("."); +@z (that was installed in version 1.1) + +534. Possible arithmetic overflows (found by Klaus Guntermann, July 86) +@x module 496 +while max_coef<fraction_one do +@y +while max_coef<fraction_half do +@z (that was installed in version 1.2) + +535. Possible loop in nonstopmode (found by Chris Thompson, July 86) +@x module 1206 + @<Finish the \.{TFM} file@>; +@y + internal[fontmaking]:=0; {avoid loop in case of fatal error} + @<Finish the \.{TFM} file@>; +@z (that too was installed in version 1.2) + +536. Double rounding error should be avoided in make_ellipse (JDH, 22 Nov 86) +@x module 533 +d:=take_fraction(d,delta); +alpha:=abs(u); beta:=abs(v); +if alpha<beta then + begin delta:=alpha; alpha:=beta; beta:=delta; + end; {now $\alpha=\max(\vert u\vert,\vert v\vert)$, + $\beta=\min(\vert u\vert,\vert v\vert)$} +if internal[fillin]<>0 then d:=d-take_fraction(internal[fillin],beta+beta); +d:=(d+4) div 8; alpha:=alpha div half_unit; +@y +alpha:=abs(u); beta:=abs(v); +if alpha<beta then + begin alpha:=abs(v); beta:=abs(u); + end; {now $\alpha=\max(\vert u\vert,\vert v\vert)$, + $\beta=\min(\vert u\vert,\vert v\vert)$} +if internal[fillin]<>0 then + d:=d-take_fraction(internal[fillin],make_fraction(beta+beta,delta)); +d:=take_fraction((d+4) div 8,delta); alpha:=alpha div half_unit; +@z (That was the reason for version 1.3) + +537. Trivial change to a help message (version number is still 1.3). +@x module 1086 + ("Pretend that you're Miss Marple, examine all clues,")@/ +@y + ("Pretend that you're Miss Marple: Examine all clues,")@/ +@z + +538. Storage allocation can be more elegant and efficient (4/21/87) +@x module 169 +if r=p then if ((rlink(p)<>rover) or (llink(p)<>rover)) then +@y +if r=p then if rlink(p)<>p then +@z + +539. Unused variables can be eliminated. (Found by John Sauter, 5/5/87) +@x module 158 +@<Glob...@>= +@!temp_ptr:pointer; {a pointer variable for occasional emergency use} + +@y (I used it only in my change file!) +@z +@x module 280 +@!r,@!s,@!t:pointer; {registers for list traversal} +@y +@!s,@!t:pointer; {registers for list traversal} +@z +@x module 284 +@!sine,@!cosine:fraction; {trig functions of various angles} +@y (the declarations in module 281 are correct, but in 284 they're superfluous) +@z +@x module 497 +var @!q,@!ww:pointer; {for list manipulation} +@!du,@!dv:scaled; {for slope calculation} +@!t0,@!t1,@!t2:integer; {test coefficients} +@!t:fraction; {place where the derivative passes a critical slope} +@!s:fraction; {slope or reciprocal slope} +@!v:integer; {intermediate value for updating |x0..y2|} +begin loop + begin q:=link(p); right_type(p):=k; +@y +var @!ww:pointer; {for list manipulation} +@!du,@!dv:scaled; {for slope calculation} +@!t0,@!t1,@!t2:integer; {test coefficients} +@!t:fraction; {place where the derivative passes a critical slope} +@!s:fraction; {slope or reciprocal slope} +@!v:integer; {intermediate value for updating |x0..y2|} +begin loop + begin right_type(p):=k; +@z +@x module 652 +@!s:0..param_size; {value of |param_start| on the current level} +@y who knows why that line was there? +@z +@x module 862 +var @!p,@!q,@!r:pointer; {for list manipulation} +@y +var @!p:pointer; {for list manipulation} +@z +@x module 985 +@!vv:scaled; {initial value of |v|} +@!q:pointer; {successor of |p|} +begin vv:=v; p:=cur_exp;@/ +@y +@!q:pointer; {successor of |p|} +begin p:=cur_exp;@/ +@z +@x module 1059 +@!t:small_number; {variant of |with_option|} +@y +@z + +540. Typo suppresses an error detection (Chris Thompson, 2May88) +@x module 963 + if txy mod unity=0 then if tyy mod unity=0 then +@y + if txx mod unity=0 then if tyy mod unity=0 then +@z + +541. get_x_token can lose a scanned declared variable (Chris Thompson, 4May88) +@x module 1011 +if equiv(x)=null then new_root(x); +@y +@z +@x module 1011 +done:scan_declared_variable:=h; +@y +done: if eq_type(x)<>tag_token then clear_symbol(x,false); +if equiv(x)=null then new_root(x); +scan_declared_variable:=h; +@z + +542. Avoid negative divisor rounding upward (Chris Thompson, fixed 19Jun88) +@x module 168 +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 + +543. Better strategy when near memory overflow (Chris Thompson) +@x module 168 +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 + +544. Avoid fatal_error after terminal eof (Tim Morgan, reported 25Oct88) +@x module 66 [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 + +545. Force terminal output when open_log_file aborts (6Nov88) +@x module 789 + begin print_err("I can't write on file `"); +@y + begin selector:=term_only; print_err("I can't write on file `"); +@z + +546. By popular request, undo #544 and fix the bug a more complex way. +@x module 66 [this undoes change #544] +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 87 [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 88 + error; +@y + if log_opened then error; +@z +@x module 782 +@!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 783 +@<Initialize the output...@>=job_name:=0; +@y +@<Initialize the output...@>=job_name:=0; log_opened:=false; +@z +@x module 788 +selector:=log_only; +@y +selector:=log_only; log_opened:=true; +@z +@x module 789 +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 1023 [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 1205 +if job_name>0 then +@y +if log_opened then +@z +@x module 1208 +if job_name>0 then {the log file is open} +@y +if log_opened then +@z + +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 replaced +@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:integer; {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. Global variable used prematurely in do_add_to (Alan Jeffrey, 9 Feb 90) +@x module 403 +@!cur_path_type:double_path_code..also_code; {likewise} +@y +@!cur_path_type:double_path_code..contour_code; {likewise} +@z +@x module 1059 +begin get_x_next; var_flag:=thing_to_add; scan_primary; +if cur_type<>token_list then + @<Abandon edges command because there's no variable@> +else begin lhs:=cur_exp; cur_path_type:=cur_mod;@/ + cur_type:=vacuous; get_x_next; scan_expression; + if cur_path_type=also_code then @<Augment some edges by others@> +@y +@!add_to_type:double_path_code..also_code; {modifier of \&{addto}} +begin get_x_next; var_flag:=thing_to_add; scan_primary; +if cur_type<>token_list then + @<Abandon edges command because there's no variable@> +else begin lhs:=cur_exp; add_to_type:=cur_mod;@/ + cur_type:=vacuous; get_x_next; scan_expression; + if add_to_type=also_code then @<Augment some edges by others@> +@z +@x module 1064 +else begin lhs:=null; +@y +else begin lhs:=null; cur_path_type:=add_to_type; +@z + +554. Balance the parens showing on the terminal (for Lispers). +@x module 631 +@!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 657 +in_open:=0; max_buf_stack:=0; +@y +in_open:=0; open_parens:=0; max_buf_stack:=0; +@z +@x module 681 + 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 793 +print_char("("); print(name); update_terminal; +@y +print_char("("); incr(open_parens); print(name); update_terminal; +@z +@x module 1209 +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 + +-----------Here I draw the line with respect to further changes + +555. Don't try system area if an area was given (see tex82.bug number 312; +found by Jonathan Kew, May 1990) +@x module 793 + pack_file_name(cur_name,MF_area,cur_ext); + if a_open_in(cur_file) then goto done; +@y + if cur_area="" then + begin pack_file_name(cur_name,MF_area,cur_ext); + if a_open_in(cur_file) then goto done; + end; +@z + +556. Report correct line number when buffer overflows (CET, Jul 90). +@x module 794 +begin if not input_ln(cur_file,false) then do_nothing; +firm_up_the_line; +buffer[limit]:="%"; first:=limit+1; loc:=start; line:=1; +@y +begin line:=1; +if input_ln(cur_file,false) then do_nothing; +firm_up_the_line; +buffer[limit]:="%"; first:=limit+1; loc:=start; +@z + +557. TeX82 bug 308, corrected in 1985, is also in MF! (Lutz Birkhahn, May91) +@x module 176 +var_used:=lo_mem_stat_max+1-mem_min; dyn_used:=mem_top+1-hi_mem_stat_min; +@y +var_used:=lo_mem_stat_max+1-mem_min; dyn_used:=mem_top+1-hi_mem_min; +@z + +558. Allow unprintable file names, as in TeX change 396 (19 Sep 91) +(Much of this is redundant except for people who make nonportable +versions that allow other 8-bit codes to be in variable names---and for +those people only if they allow input of more codes than they can print! +Still, it seems best to make the programs for TeX and MF as alike as possible.) +@x module 59 +j:=str_start[s]; +while j<str_start[s+1] do + begin print_char(so(str_pool[j])); incr(j); + end; +@y +if (s<256)and(selector>pseudo) then print_char(s) +else begin j:=str_start[s]; + while j<str_start[s+1] do + begin print_char(so(str_pool[j])); incr(j); + end; + end; +@z +@x module 60 +j:=str_start[s]; +while j<str_start[s+1] do + begin print(so(str_pool[j])); incr(j); + end; +@y +if (s<256)and(selector>pseudo) then print_char(s) +else begin j:=str_start[s]; + while j<str_start[s+1] do + begin print(so(str_pool[j])); incr(j); + end; + end; +@z +@x module 61 +else begin print(base_ident); print_ln; +@y +else begin slow_print(base_ident); print_ln; +@z +@x module 79 + print(input_stack[file_ptr].name_field); +@y + slow_print(input_stack[file_ptr].name_field); +@z +@x module 223 +print(r); +@y +slow_print(r); +@z +@x module 254 + print(int_name[q-(hash_end)]); print_char("="); +@y + slow_print(int_name[q-(hash_end)]); print_char("="); +@z +@x module 254 again + print(text(q)); print_char("}"); +@y + slow_print(text(q)); print_char("}"); +@z +@x module 638 + if name<>null then print(text(name)) +@y + if name<>null then slow_print(text(name)) +@z +@x module 664 + if scanner_status=op_defining then print(text(warning_info)) +@y + if scanner_status=op_defining then slow_print(text(warning_info)) +@z +@x module 664 again +loop_defining: begin print("the text of a "); print(text(warning_info)); +@y +loop_defining: begin print("the text of a "); slow_print(text(warning_info)); +@z +@x module 722 +begin if n<>null then print(text(n)) +@y +begin if n<>null then slow_print(text(n)) +@z +@x module 722 again + if p=null then print(text(info(info(link(a))))) +@y + if p=null then slow_print(text(info(info(link(a))))) +@z +@x module 725 + print_nl(" Missing `"); print(text(r_delim)); +@y + print_nl(" Missing `"); slow_print(text(r_delim)); +@z +@x module 773 +begin print(a); print(n); print(e); +@y +begin slow_print(a); slow_print(n); slow_print(e); +@z +@x module 790 +print(base_ident); print(" "); +@y +slow_print(base_ident); print(" "); +@z +@x module 793 +print_char("("); incr(open_parens); print(name); update_terminal; +@y +print_char("("); incr(open_parens); slow_print(name); update_terminal; +@z +@x module 998 +if info(lhs)>hash_end then print(int_name[info(lhs)-(hash_end)]) +@y +if info(lhs)>hash_end then slow_print(int_name[info(lhs)-(hash_end)]) +@z +@x module 999 + print(int_name[info(lhs)-(hash_end)]); +@y + slow_print(int_name[info(lhs)-(hash_end)]); +@z +@x module 1032 +else begin print_err("The token `"); print(text(r_delim)); +@y +else begin print_err("The token `"); slow_print(text(r_delim)); +@z +@x module 1034 + else print(text(cur_sym)); +@y + else slow_print(text(cur_sym)); +@z +@x module 1041 +else begin print(text(cur_sym)); print_char("="); +@y +else begin slow_print(text(cur_sym)); print_char("="); +@z +@x module 1042 +else begin print_char(""""); print(cur_mod); print_char(""""); +@y +else begin print_char(""""); slow_print(cur_mod); print_char(""""); +@z +@x module 1043 + print("t delimiter that matches "); print(text(m)); +@y + print("t delimiter that matches "); slow_print(text(m)); +@z +@x module 1043 again +internal_quantity:print(int_name[m]); +@y +internal_quantity:slow_print(int_name[m]); +@z +@x module 1134 +print_nl("Font metrics written on "); print(metric_file_name); print_char("."); +@y +print_nl("Font metrics written on "); slow_print(metric_file_name); +print_char("."); +@z +@x module 1182 +print_nl("Output written on "); print(output_file_name); +@y +print_nl("Output written on "); slow_print(output_file_name); +@z +@x module 1200 +print(w_make_name_string(base_file)); flush_string(str_ptr-1); +print_nl(base_ident) +@y +slow_print(w_make_name_string(base_file)); flush_string(str_ptr-1); +print_nl(""); slow_print(base_ident) +@z +@x module 1205 + print(log_name); print_char("."); +@y + slow_print(log_name); print_char("."); +@z +@x module 1213 +10: print(n); +@y +10: slow_print(n); +@z + +------ The third printing of Volume D (October 1991) incorporated the above. + +559. Debugging routine never used since change 528; needed update then (JDH). +@x module 617 + p:=dep_list(p); r:=hi_mem_min; + repeat if info(p)>=r then +@y + p:=dep_list(p); r:=inf_val; + repeat if value(info(p))>=value(r) then +@z + +560. Corrections to blunders in change 550 (noted by B Jackowski, Jul 91). +@x module 415 can use more paranoia even though no problems have occurred yet +negate(left_y(qq)); negate(dest_y);@/ +@y +negate(left_y(qq)); negate(dest_y);@/ +if x_coord(r)<x_coord(pp) then x_coord(r):=x_coord(pp) +else if x_coord(r)>dest_x then x_coord(r):=dest_x; +if left_x(r)>x_coord(r) then + begin left_x(r):=x_coord(r); + if right_x(pp)>x_coord(r) then right_x(pp):=x_coord(r); + end; +if right_x(r)<x_coord(r) then + begin right_x(r):=x_coord(r); + if left_x(qq)<x_coord(r) then left_x(qq):=x_coord(r); + end; +@z +@x module 416 similarly +negate(y_coord(s)); right_y(s):=y_coord(s); +@y +negate(y_coord(s)); right_y(s):=y_coord(s); +if x_coord(s)<x_coord(r) then x_coord(s):=x_coord(r) +else if x_coord(s)>dest_x then x_coord(s):=dest_x; +if left_x(s)>x_coord(s) then + begin left_x(s):=x_coord(s); + if right_x(r)>x_coord(s) then right_x(r):=x_coord(s); + end; +if right_x(s)<x_coord(s) then + begin right_x(s):=x_coord(s); + if left_x(qq)<x_coord(s) then left_x(qq):=x_coord(s); + end; +@z +@x module 424 similarly +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; +@y +if y_coord(r)<y_coord(p) then y_coord(r):=y_coord(p) +else if y_coord(r)>dest_y then y_coord(r):=dest_y; +if x_coord(p)+y_coord(r)>dest_x+dest_y then + 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; +if right_y(r)<y_coord(r) then + begin right_y(r):=y_coord(r); + if left_y(q)<y_coord(r) then left_y(q):=y_coord(r); + end; +@z +@x in module 424, here's the serious bug introduced in change #550. +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); +@y +if right_y(r)<y_coord(r) then + begin right_y(r):=y_coord(r); + if left_y(q)<y_coord(r) then left_y(q):=y_coord(r); + end; +@z +@x module 425 is analogous +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; +@y +if y_coord(s)<y_coord(r) then y_coord(s):=y_coord(r) +else if y_coord(s)>dest_y then y_coord(s):=dest_y; +if x_coord(r)+y_coord(s)>dest_x+dest_y then + 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; +if right_y(s)<y_coord(s) then + begin right_y(s):=y_coord(s); + if left_y(q)<y_coord(s) then left_y(q):=y_coord(s); + end; +@z +@x module 425, the analogous bug +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); +@y +if right_y(s)<y_coord(s) then + begin right_y(s):=y_coord(s); + if left_y(q)<y_coord(s) then left_y(q):=y_coord(s); + end; +@z + +561. serious longstanding bug caused overflows and bad rounding (1 Mar 95) +@x module 815 +begin if (max_c[dependent]>=fraction_one)or@| + (max_c[dependent] div @'10000 >= max_c[proto_dependent]) then +@y +begin if (max_c[dependent] div @'10000 >= + max_c[proto_dependent]) then +@z + +562. final cleanup should not retain spurious reference counts (20 Mar 95) +@x module 1209 +while open_parens>0 do +@y +while input_ptr>0 do + if token_state then end_token_list@+else end_file_reading; +while loop_ptr<>null do stop_iteration; +while open_parens>0 do +@z +@x module 1209 + cur_if:=name_type(cond_ptr); cond_ptr:=link(cond_ptr); +@y + cur_if:=name_type(cond_ptr); loop_ptr:=cond_ptr; + cond_ptr:=link(cond_ptr); free_node(loop_ptr,if_node_size); +@z + +563. unprintable strings of length 1 need to be truly length 1 (27 Nov 95, +pointed out by Ulrik Vieth) +@x module 671 + if loc=k+1 then cur_mod:=buffer[k] +@y + if (loc=k+1) and (length(buffer[k])=1) then cur_mod:=buffer[k] +@z + +564. minor improvement to pythagorean addition (22 Jan 97) +@x module 124 +if a>0 then +@y +if b>0 then +@z + +565. we need not raise hackles about two-digit years (23 Nov 98) +@x module 1200 +print_int(round_unscaled(internal[year]) mod 100); print_char("."); +@y +print_int(round_unscaled(internal[year])); print_char("."); +@z + +566. "this can't happen" can happen if coordinates are half vast + (Julian Gilbey, January 2001) +@x module 402 +@!chopped:boolean; {have we truncated any of the data?} +@y +@!chopped:integer; {positive if data truncated, + negative if data dangerously large} +@z +@x module 402 +if internal[autorounding]>0 then xy_round; +octant_subdivide; {complete the subdivision} +if internal[autorounding]>unity then diag_round; +@<Remove dead cubics@>; +@<Insert octant boundaries and compute the turning number@>; +while left_type(cur_spec)<>endpoint do cur_spec:=link(cur_spec); +if tracing>0 then + if internal[autorounding]<=0 then print_spec(", after subdivision") +@y +if (internal[autorounding]>0)and(chopped=0) then xy_round; +octant_subdivide; {complete the subdivision} +if (internal[autorounding]>unity)and(chopped=0) then diag_round; +@<Remove dead cubics@>; +@<Insert octant boundaries and compute the turning number@>; +while left_type(cur_spec)<>endpoint do cur_spec:=link(cur_spec); +if tracing>0 then + if (internal[autorounding]<=0)or(chopped<>0) then + print_spec(", after subdivision") +@z +@x module 404 +@d procrustes(#)==if abs(#)>max_allowed then + begin chopped:=true; + if #>0 then #:=max_allowed@+else #:=-max_allowed; + end + +@<Truncate the values of all coordinates that exceed...@>= +p:=cur_spec; k:=1; chopped:=false; +@y +@d procrustes(#)==if abs(#)>=dmax then + if abs(#)>max_allowed then + begin chopped:=1; + if #>0 then #:=max_allowed@+else #:=-max_allowed; + end + else if chopped=0 then chopped:=-1 + +@<Truncate the values of all coordinates that exceed...@>= +p:=cur_spec; k:=1; chopped:=0; dmax:=half(max_allowed); +@z +@x module 404 +if chopped then +@y +if chopped>0 then +@z + +567. I forgot to update curtype in e.g. boolean b[]; b1=true=b2; + (Thorsten Dahlheimer, June 2004) +@x 1003 + begin nonlinear_eq(v,cur_exp,false); goto done; +@y + begin nonlinear_eq(v,cur_exp,false); unstash_cur_exp(cur_exp); goto done; +@z + +568. Wrong handling of extreme TFM values (T. Dahlheimer, June 2004) +@x 1128 +max_tfm_dimen:=16*internal[design_size]-internal[design_size] div @'10000000; +@y +max_tfm_dimen:=16*internal[design_size]-1-internal[design_size] div @'10000000; +@z +@x 1129 + if x>0 then x:=three_bytes-1@+else x:=1-three_bytes; + end +else x:=make_scaled(x*16,internal[design_size]); +@y + if x>0 then x:=max_tfm_param@+else x:=-max_tfm_param; + end; +x:=make_scaled(x*16,internal[design_size]); +@z + +569. Bug in make_ellipse when theta=180 (T. Dahlheimer, June 2004) +@x 530 + else begin beta:=minor_axis; gamma:=major_axis; +@y + else begin beta:=minor_axis; gamma:=major_axis; theta:=0; +@z + +570. Forgot outer_tag in scan_declared variable (T. Dahlheimer, June 2004) +@x 1011 +done: if eq_type(x)<>tag_token then clear_symbol(x,false); +@y +done: if eq_type(x) mod outer_tag<>tag_token then clear_symbol(x,false); +@z + +571. Apparent bug if init_gf called at incredibly unlikely time (T. Dahlheimer, +June 2004); not REALLY a bug, because str_ptr cannot equal max_strings here +(because this was checked by end_name, and area_delimiter=0 there because +cur_area="" in the output file name); but anyway I'll make a patch to be clean +@x 1163 +str_start[str_ptr+1]:=pool_ptr; gf_string(0,str_ptr); +@y +gf_string(0,make_string); decr(str_ptr); +@z + +------------- +999. The absolutely final change (to be made after my death) +@x module 2 +@d banner=='This is METAFONT, Version 2.7182' {printed when \MF\ starts} +@y +@d banner=='This is METAFONT, Version $e$' {printed when \MF\ starts} +@z +When this change is made, the corresponding line should be changed in +Volume D, and also on page 31 of The METAFONTbook. +My last will and testament for METAFONT is that no further changes be made +under any circumstances. Improved systems should not be called simply +`METAFONT'; that name, unqualified, should refer only to the program for which +I have taken personal responsibility. -- Don Knuth |