diff options
Diffstat (limited to 'Build/source/texk/web2c/mf.tex')
-rw-r--r-- | Build/source/texk/web2c/mf.tex | 34385 |
1 files changed, 0 insertions, 34385 deletions
diff --git a/Build/source/texk/web2c/mf.tex b/Build/source/texk/web2c/mf.tex deleted file mode 100644 index a1a8bda5e63..00000000000 --- a/Build/source/texk/web2c/mf.tex +++ /dev/null @@ -1,34385 +0,0 @@ -\input webmac -% This program is copyright (C) 1984 by D. E. Knuth; all rights are reserved. -% Copying of this file is authorized only if (1) you are D. E. Knuth, or if -% (2) you make absolutely no changes to your copy. (The WEB system provides -% for alterations via an auxiliary file; the master file should stay intact.) -% In other words, METAFONT is under essentially the same ground rules as TeX. - -% TeX is a trademark of the American Mathematical Society. -% METAFONT is a trademark of Addison-Wesley Publishing Company. - -% Version 0 was completed on July 28, 1984. -% Version 1 was completed on January 4, 1986; it corresponds to "Volume D". -% Version 1.1 trivially corrected the punctuation in one message (June 1986). -% Version 1.2 corrected an arithmetic overflow problem (July 1986). -% Version 1.3 improved rounding when elliptical pens are made (November 1986). -% Version 1.4 corrected scan_declared_variable timing (May 1988). -% Version 1.5 fixed negative halving in allocator when mem_min<0 (June 1988). -% Version 1.6 kept open_log_file from calling fatal_error (November 1988). -% Version 1.7 solved that problem a better way (December 1988). -% Version 1.8 introduced major changes for 8-bit extensions (September 1989). -% Version 1.9 improved skimping and was edited for style (December 1989). -% Version 2.0 fixed bug in addto; released with TeX version 3.0 (March 1990). -% Version 2.7 made consistent with TeX version 3.1 (September 1990). -% Version 2.71 fixed bug in draw, allowed unprintable filenames (March 1992). -% Version 2.718 fixed bug in <Choose a dependent...> (March 1995). -% Version 2.7182 fixed bugs related to "<unprintable char>" (August 1996). -% Version 2.71828 suppressed autorounding in dangerous cases (December 2002). - -% A reward of $327.68 will be paid to the first finder of any remaining bug. - -% Although considerable effort has been expended to make the METAFONT program -% correct and reliable, no warranty is implied; the author disclaims any -% obligation or liability for damages, including but not limited to -% special, indirect, or consequential damages arising out of or in -% connection with the use or performance of this software. This work has -% been a ``labor of love'' and the author hopes that users enjoy it. - -% Here is TeX material that gets inserted after \input webmac -\def\hang{\hangindent 3em\noindent\ignorespaces} -\def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces} -\font\ninerm=cmr9 -\let\mc=\ninerm % medium caps for names like SAIL -\def\PASCAL{Pascal} -\def\ph{\hbox{Pascal-H}} -\def\psqrt#1{\sqrt{\mathstrut#1}} -\def\k{_{k+1}} -\def\pct!{{\char`\%}} % percent sign in ordinary text -\font\tenlogo=logo10 % font used for the METAFONT logo -\font\logos=logosl10 -\font\eightlogo=logo8 -\def\MF{{\tenlogo META}\-{\tenlogo FONT}} -\def\<#1>{$\langle#1\rangle$} -\def\section{\mathhexbox278} -\let\swap=\leftrightarrow -\def\round{\mathop{\rm round}\nolimits} - -\def\(#1){} % this is used to make section names sort themselves better -\def\9#1{} % this is used for sort keys in the index via @:sort key}{entry@> - -\outer\def\N#1. \[#2]#3.{\MN#1.\vfil\eject % begin starred section - \def\rhead{PART #2:\uppercase{#3}} % define running headline - \message{*\modno} % progress report - \edef\next{\write\cont{\Z{\?#2]#3}{\modno}{\the\pageno}}}\next - \ifon\startsection{\bf\ignorespaces#3.\quad}\ignorespaces} -\let\?=\relax % we want to be able to \write a \? - -\def\title{{\eightlogo METAFONT}} -\def\topofcontents{\hsize 5.5in - \vglue -30pt plus 1fil minus 1.5in - \def\?##1]{\hbox to 1in{\hfil##1.\ }} - } -\def\botofcontents{\vskip 0pt plus 1fil minus 1.5in} -\pageno=3 -\def\glob{13} % this should be the section number of "<Global...>" -\def\gglob{20, 26} % this should be the next two sections of "<Global...>" - - -\N1. \[1] Introduction. -This is \MF, a font compiler intended to produce typefaces of high quality. -The \PASCAL\ program that follows is the definition of \MF84, a standard -version of \MF\ that is designed to be highly portable so that identical output -will be obtainable on a great variety of computers. The conventions -of \MF84 are the same as those of \TeX82. - -The main purpose of the following program is to explain the algorithms of \MF\ -as clearly as possible. As a result, the program will not necessarily be very -efficient when a particular \PASCAL\ compiler has translated it into a -particular machine language. However, the program has been written so that it -can be tuned to run efficiently in a wide variety of operating environments -by making comparatively few changes. Such flexibility is possible because -the documentation that follows is written in the \.{WEB} language, which is -at a higher level than \PASCAL; the preprocessing step that converts \.{WEB} -to \PASCAL\ is able to introduce most of the necessary refinements. -Semi-automatic translation to other languages is also feasible, because the -program below does not make extensive use of features that are peculiar to -\PASCAL. - -A large piece of software like \MF\ has inherent complexity that cannot -be reduced below a certain level of difficulty, although each individual -part is fairly simple by itself. The \.{WEB} language is intended to make -the algorithms as readable as possible, by reflecting the way the -individual program pieces fit together and by providing the -cross-references that connect different parts. Detailed comments about -what is going on, and about why things were done in certain ways, have -been liberally sprinkled throughout the program. These comments explain -features of the implementation, but they rarely attempt to explain the -\MF\ language itself, since the reader is supposed to be familiar with -{\sl The {\logos METAFONT\/}book}. - -\fi - -\M2. The present implementation has a long ancestry, beginning in the spring -of~1977, when its author wrote a prototype set of subroutines and macros -that were used to develop the first Computer Modern fonts. -This original proto-\MF\ required the user to recompile a {\mc SAIL} program -whenever any character was changed, because it was not a ``language'' for -font design; the language was {\mc SAIL}. After several hundred characters -had been designed in that way, the author developed an interpretable language -called \MF, in which it was possible to express the Computer Modern programs -less cryptically. A complete \MF\ processor was designed and coded by the -author in 1979. This program, written in {\mc SAIL}, was adapted for use -with a variety of typesetting equipment and display terminals by Leo Guibas, -Lyle Ramshaw, and David Fuchs. -Major improvements to the design of Computer Modern fonts were made in the -spring of 1982, after which it became clear that a new language would -better express the needs of letterform designers. Therefore an entirely -new \MF\ language and system were developed in 1984; the present system -retains the name and some of the spirit of \MF79, but all of the details -have changed. - -No doubt there still is plenty of room for improvement, but the author -is firmly committed to keeping \MF84 ``frozen'' from now on; stability -and reliability are to be its main virtues. - -On the other hand, the \.{WEB} description can be extended without changing -the core of \MF84 itself, and the program has been designed so that such -extensions are not extremely difficult to make. -The \\{banner} string defined here should be changed whenever \MF\ -undergoes any modifications, so that it will be clear which version of -\MF\ might be the guilty party when a problem arises. - -If this program is changed, the resulting system should not be called -`\MF\kern.5pt'; the official name `\MF\kern.5pt' by itself is reserved -for software systems that are fully compatible with each other. -A special test suite called the ``\.{TRAP} test'' is available for -helping to determine whether an implementation deserves to be -known as `\MF\kern.5pt' [cf.~Stanford Computer Science report CS1095, -January 1986]. - -\Y\P\D \37$\\{banner}\S\.{\'This\ is\ METAFONT,\ Version\ 2.71828\'}$\C{printed -when \MF\ starts}\par -\fi - -\M3. Different \PASCAL s have slightly different conventions, and the present -program expresses \MF\ in terms of the \PASCAL\ that was -available to the author in 1984. Constructions that apply to -this particular compiler, which we shall call \ph, should help the -reader see how to make an appropriate interface for other systems -if necessary. (\ph\ is Charles Hedrick's modification of a compiler -for the DECsystem-10 that was originally developed at the University of -Hamburg; cf.\ {\sl SOFTWARE---Practice \AM\ Experience \bf6} (1976), -29--42. The \MF\ program below is intended to be adaptable, without -extensive changes, to most other versions of \PASCAL, so it does not fully -use the admirable features of \ph. Indeed, a conscious effort has been -made here to avoid using several idiosyncratic features of standard -\PASCAL\ itself, so that most of the code can be translated mechanically -into other high-level languages. For example, the `\&{with}' and `\\{new}' -features are not used, nor are pointer types, set types, or enumerated -scalar types; there are no `\&{var}' parameters, except in the case of files -or in the system-dependent \\{paint\_row} procedure; -there are no tag fields on variant records; there are no \\{real} variables; -no procedures are declared local to other procedures.) - -The portions of this program that involve system-dependent code, where -changes might be necessary because of differences between \PASCAL\ compilers -and/or differences between -operating systems, can be identified by looking at the sections whose -numbers are listed under `system dependencies' in the index. Furthermore, -the index entries for `dirty \PASCAL' list all places where the restrictions -of \PASCAL\ have not been followed perfectly, for one reason or another. - -\fi - -\M4. The program begins with a normal \PASCAL\ program heading, whose -components will be filled in later, using the conventions of \.{WEB}. -For example, the portion of the program called `\X\glob:Global -variables\X' below will be replaced by a sequence of variable declarations -that starts in $\section\glob$ of this documentation. In this way, we are able -to define each individual global variable when we are prepared to -understand what it means; we do not have to define all of the globals at -once. Cross references in $\section\glob$, where it says ``See also -sections \gglob, \dots,'' also make it possible to look at the set of -all global variables, if desired. Similar remarks apply to the other -portions of the program heading. - -Actually the heading shown here is not quite normal: The \&{program}\ line -does not mention any \\{output} file, because \ph\ would ask the \MF\ user -to specify a file name if \\{output} were specified here. - -\Y\P\D \37$\\{mtype}\S\|t\J\|y\J\|p\J\|e$\C{this is a \.{WEB} coding trick:}\par -\P\F \37$\\{mtype}\S\\{type}$\C{`\&{mtype}' will be equivalent to `\&{type}'}% -\par -\P\F \37$\\{type}\S\\{true}$\C{but `\\{type}' will not be treated as a reserved -word}\par -\Y\P\hbox{\4}\X9:Compiler directives\X\6 -\4\&{program}\1\ \37\\{MF};\C{all file names are defined dynamically}\6 -\4\&{label} \37\X6:Labels in the outer block\X\6 -\4\&{const} \37\X11:Constants in the outer block\X\6 -\4\&{mtype} \37\X18:Types in the outer block\X\6 -\4\&{var} \37\X13:Global variables\X\7 -\4\&{procedure}\1\ \37\\{initialize};\C{this procedure gets things started -properly}\6 -\4\&{var} \37\X19:Local variables for initialization\X\2\6 -\&{begin} \37\X21:Set initial values of key variables\X\6 -\&{end};\7 -\hbox{\4}\X57:Basic printing procedures\X\6 -\hbox{\4}\X73:Error handling procedures\X\par -\fi - -\M5. The overall \MF\ program begins with the heading just shown, after which -comes a bunch of procedure declarations and function declarations. -Finally we will get to the main program, which begins with the -comment `\\{start\_here}'. If you want to skip down to the -main program now, you can look up `\\{start\_here}' in the index. -But the author suggests that the best way to understand this program -is to follow pretty much the order of \MF's components as they appear in the -\.{WEB} description you are now reading, since the present ordering is -intended to combine the advantages of the ``bottom up'' and ``top down'' -approaches to the problem of understanding a somewhat complicated system. - -\fi - -\M6. Three labels must be declared in the main program, so we give them -symbolic names. - -\Y\P\D \37$\\{start\_of\_MF}=1$\C{go here when \MF's variables are initialized}% -\par -\P\D \37$\\{end\_of\_MF}=9998$\C{go here to close files and terminate -gracefully}\par -\P\D \37$\\{final\_end}=9999$\C{this label marks the ending of the program}\par -\Y\P$\4\X6:Labels in the outer block\X\S$\6 -$\\{start\_of\_MF}\hbox{\hskip-2pt},\39\\{end\_of\_MF}\hbox{\hskip-2pt},\39\,% -\\{final\_end}$;\C{key control points}\par -\U4.\fi - -\M7. Some of the code below is intended to be used only when diagnosing the -strange behavior that sometimes occurs when \MF\ is being installed or -when system wizards are fooling around with \MF\ without quite knowing -what they are doing. Such code will not normally be compiled; it is -delimited by the codewords `$ \&{debug} \ldots \&{gubed} $', with apologies -to people who wish to preserve the purity of English. - -Similarly, there is some conditional code delimited by -`$ \&{stat} \ldots \&{tats} $' that is intended for use when statistics are to -be -kept about \MF's memory usage. The \&{stat} $\ldots$ \&{tats} code also -implements special diagnostic information that is printed when -$\\{tracingedges}>1$. - -\Y\P\D \37$\\{debug}\S\B$\C{change this to `$\\{debug}\equiv\null$' when -debugging}\par -\P\D \37$\\{gubed}\S\hbox{}\T$\C{change this to `$\\{gubed}\equiv\null$' when -debugging}\par -\P\F \37$\\{debug}\S\\{begin}$\par -\P\F \37$\\{gubed}\S\\{end}$\Y\par -\P\D \37$\\{stat}\S\B$\C{change this to `$\\{stat}\equiv\null$' when gathering - usage statistics}\par -\P\D \37$\\{tats}\S\hbox{}\T$\C{change this to `$\\{tats}\equiv\null$' when -gathering usage statistics}\par -\P\F \37$\\{stat}\S\\{begin}$\par -\P\F \37$\\{tats}\S\\{end}$\par -\fi - -\M8. This program has two important variations: (1) There is a long and slow -version called \.{INIMF}, which does the extra calculations needed to -initialize \MF's internal tables; and (2)~there is a shorter and faster -production version, which cuts the initialization to a bare minimum. -Parts of the program that are needed in (1) but not in (2) are delimited by -the codewords `$ \&{init} \ldots \&{tini} $'. - -\Y\P\D \37$\\{init}\S$\C{change this to `$\\{init}\equiv\.{@\{}$' in the -production version}\par -\P\D \37$\\{tini}\S$\C{change this to `$\\{tini}\equiv\.{@\}}$' in the -production version}\par -\P\F \37$\\{init}\S\\{begin}$\par -\P\F \37$\\{tini}\S\\{end}$\par -\fi - -\M9. If the first character of a \PASCAL\ comment is a dollar sign, -\ph\ treats the comment as a list of ``compiler directives'' that will -affect the translation of this program into machine language. The -directives shown below specify full checking and inclusion of the \PASCAL\ -debugger when \MF\ is being debugged, but they cause range checking and other -redundant code to be eliminated when the production system is being generated. -Arithmetic overflow will be detected in all cases. - -\Y\P$\4\X9:Compiler directives\X\S$\6 -$\B\J\$\|C-,\39\|A+,\39\|D-\T$\C{no range check, catch arithmetic overflow, no -debug overhead}\6 -\&{debug} \37$\B\J\$\|C+,\39\|D+\T$\ \&{gubed}\C{but turn everything on when -debugging}\par -\U4.\fi - -\M10. This \MF\ implementation conforms to the rules of the {\sl Pascal User -Manual} published by Jensen and Wirth in 1975, except where system-dependent -code is necessary to make a useful system program, and except in another -respect where such conformity would unnecessarily obscure the meaning -and clutter up the code: We assume that \&{case} statements may include a -default case that applies if no matching label is found. Thus, we shall use -constructions like -$$\vbox{\halign{\ignorespaces#\hfil\cr - \&{case} $\|x$ \&{of}\cr -1: $\langle\,$code for $x=1\,\rangle$;\cr -3: $\langle\,$code for $x=3\,\rangle$;\cr - \&{othercases} $\langle\,$code for $\|x\I1$ and $\|x\I3$$\,\rangle$\cr - \&{endcases} \cr}}$$ -since most \PASCAL\ compilers have plugged this hole in the language by -incorporating some sort of default mechanism. For example, the \ph\ -compiler allows `\\{others}:' as a default label, and other \PASCAL s allow -syntaxes like `\&{else}' or `\&{otherwise}' or `\\{otherwise}:', etc. The -definitions of \&{othercases} and \&{endcases} should be changed to agree -with -local conventions. Note that no semicolon appears before \&{endcases} in -this program, so the definition of \&{endcases} should include a semicolon -if the compiler wants one. (Of course, if no default mechanism is -available, the \&{case} statements of \MF\ will have to be laboriously -extended by listing all remaining cases. People who are stuck with such -\PASCAL s have, in fact, done this, successfully but not happily!) - -\Y\P\D \37$\\{othercases}\S\\{others}$: \37\C{default for cases not listed -explicitly}\par -\P\D \37$\\{endcases}\S$\ \&{end} \C{follows the default case in an extended % -\&{case} statement}\par -\P\F \37$\\{othercases}\S\\{else}$\par -\P\F \37$\\{endcases}\S\\{end}$\par -\fi - -\M11. The following parameters can be changed at compile time to extend or -reduce \MF's capacity. They may have different values in \.{INIMF} and -in production versions of \MF. - -\Y\P$\4\X11:Constants in the outer block\X\S$\6 -$\\{mem\_max}=30000$;\C{greatest index in \MF's internal \\{mem} array; must -be strictly less than \\{max\_halfword}; must be equal to \\{mem\_top} in % -\.{INIMF}, otherwise $\G\\{mem\_top}$}\6 -$\\{max\_internal}=100$;\C{maximum number of internal quantities}\6 -$\\{buf\_size}=500$;\C{maximum number of characters simultaneously present in -current lines of open files; must not exceed \\{max\_halfword}}\6 -$\\{error\_line}=72$;\C{width of context lines on terminal error messages}\6 -$\\{half\_error\_line}=42$;\C{width of first lines of contexts in terminal -error messages; should be between 30 and $\\{error\_line}-15$}\6 -$\\{max\_print\_line}=79$;\C{width of longest text lines output; should be at -least 60}\6 -$\\{screen\_width}=768$;\C{number of pixels in each row of screen display}\6 -$\\{screen\_depth}=1024$;\C{number of pixels in each column of screen display}\6 -$\\{stack\_size}=30$;\C{maximum number of simultaneous input sources}\6 -$\\{max\_strings}=2000$;\C{maximum number of strings; must not exceed \\{max% -\_halfword}}\6 -$\\{string\_vacancies}=8000$;\C{the minimum number of characters that should be - available for the user's identifier names and strings, after \MF's own -error messages are stored}\6 -$\\{pool\_size}=32000$;\C{maximum number of characters in strings, including -all error messages and help texts, and the names of all identifiers; must -exceed \\{string\_vacancies} by the total length of \MF's own strings, which -is currently about 22000}\6 -$\\{move\_size}=5000$;\C{space for storing moves in a single octant}\6 -$\\{max\_wiggle}=300$;\C{number of autorounded points per cycle}\6 -$\\{gf\_buf\_size}=800$;\C{size of the output buffer, must be a multiple of 8}\6 -$\\{file\_name\_size}=40$;\C{file names shouldn't be longer than this}\6 -$\\{pool\_name}=\.{\'MFbases:MF.POOL\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -\ \ \ \'}$;\C{string of length \\{file\_name\_size}; tells where the string -pool appears}\6 -$\\{path\_size}=300$;\C{maximum number of knots between breakpoints of a path}\6 -$\\{bistack\_size}=785$;\C{size of stack for bisection algorithms; should -probably be left at this value}\6 -$\\{header\_size}=100$;\C{maximum number of \.{TFM} header words, times~4}\6 -$\\{lig\_table\_size}=5000$;\C{maximum number of ligature/kern steps, must be -at least 255 and at most 32510}\6 -$\\{max\_kerns}=500$;\C{maximum number of distinct kern amounts}\6 -$\\{max\_font\_dimen}=50$;\C{maximum number of \&{fontdimen} parameters}\par -\U4.\fi - -\M12. Like the preceding parameters, the following quantities can be changed -at compile time to extend or reduce \MF's capacity. But if they are changed, -it is necessary to rerun the initialization program \.{INIMF} -to generate new tables for the production \MF\ program. -One can't simply make helter-skelter changes to the following constants, -since certain rather complex initialization -numbers are computed from them. They are defined here using -\.{WEB} macros, instead of being put into \PASCAL's \&{const} list, in order -to -emphasize this distinction. - -\Y\P\D \37$\\{mem\_min}=0$\C{smallest index in the \\{mem} array, must not be -less than \\{min\_halfword}}\par -\P\D \37$\\{mem\_top}\S30000$\C{largest index in the \\{mem} array dumped by % -\.{INIMF}; must be substantially larger than \\{mem\_min} and not greater -than \\{mem\_max}}\par -\P\D \37$\\{hash\_size}=2100$\C{maximum number of symbolic tokens, must be -less than $\\{max\_halfword}-3\ast\\{param\_size}$}\par -\P\D \37$\\{hash\_prime}=1777$\C{a prime number equal to about 85\pct! of % -\\{hash\_size}}\par -\P\D \37$\\{max\_in\_open}=6$\C{maximum number of input files and error -insertions that can be going on simultaneously}\par -\P\D \37$\\{param\_size}=150$\C{maximum number of simultaneous macro -parameters}\par -\fi - -\M13. In case somebody has inadvertently made bad settings of the -``constants,'' -\MF\ checks them using a global variable called \\{bad}. - -This is the first of many sections of \MF\ where global variables are -defined. - -\Y\P$\4\X13:Global variables\X\S$\6 -\4\\{bad}: \37\\{integer};\C{is some ``constant'' wrong?}\par -\As20, 25, 29, 31, 38, 42, 50, 54, 68, 71, 74, 91, 97, 129, 137, 144, 148, 159, -160, 161, 166, 178, 190, 196, 198, 200, 201, 225, 230, 250, 267, 279, 283, 298, -308, 309, 327, 371, 379, 389, 395, 403, 427, 430, 448, 455, 461, 464, 507, 552, -555, 557, 566, 569, 572, 579, 585, 592, 624, 628, 631, 633, 634, 659, 680, 699, -738, 752, 767, 768, 775, 782, 785, 791, 796, 813, 821, 954, 1077, 1084, 1087, -1096, 1119, 1125, 1130, 1149, 1152, 1162, 1183, 1188\ETs1203. -\U4.\fi - -\M14. Later on we will say `\ignorespaces \&{if} $\\{mem\_max}\G\\{max% -\_halfword}$ \&{then} $\\{bad}\K10$', -or something similar. (We can't do that until \\{max\_halfword} has been -defined.) - -\Y\P$\4\X14:Check the ``constant'' values for consistency\X\S$\6 -$\\{bad}\K0$;\6 -\&{if} $(\\{half\_error\_line}<30)\V(\\{half\_error\_line}>\\{error\_line}-15)$ -\1\&{then}\5 -$\\{bad}\K1$;\2\6 -\&{if} $\\{max\_print\_line}<60$ \1\&{then}\5 -$\\{bad}\K2$;\2\6 -\&{if} $\\{gf\_buf\_size}\mathbin{\&{mod}}8\I0$ \1\&{then}\5 -$\\{bad}\K3$;\2\6 -\&{if} $\\{mem\_min}+1100>\\{mem\_top}$ \1\&{then}\5 -$\\{bad}\K4$;\2\6 -\&{if} $\\{hash\_prime}>\\{hash\_size}$ \1\&{then}\5 -$\\{bad}\K5$;\2\6 -\&{if} $\\{header\_size}\mathbin{\&{mod}}4\I0$ \1\&{then}\5 -$\\{bad}\K6$;\2\6 -\&{if} $(\\{lig\_table\_size}<255)\V(\\{lig\_table\_size}>32510)$ \1\&{then}\5 -$\\{bad}\K7$;\2\par -\As154, 204, 214, 310, 553\ETs777. -\U1204.\fi - -\M15. Labels are given symbolic names by the following definitions, so that -occasional \&{goto} statements will be meaningful. We insert the label -`\\{exit}' just before the `\ignorespaces \&{end} \unskip' of a procedure in -which we have used the `\&{return}' statement defined below; the label -`\\{restart}' is occasionally used at the very beginning of a procedure; and -the label `\\{reswitch}' is occasionally used just prior to a \&{case} -statement in which some cases change the conditions and we wish to branch -to the newly applicable case. Loops that are set up with the \~ \&{loop} -construction defined below are commonly exited by going to `\\{done}' or to -`\\{found}' or to `\\{not\_found}', and they are sometimes repeated by going to -`\\{continue}'. If two or more parts of a subroutine start differently but -end up the same, the shared code may be gathered together at -`\\{common\_ending}'. - -Incidentally, this program never declares a label that isn't actually used, -because some fussy \PASCAL\ compilers will complain about redundant labels. - -\Y\P\D \37$\\{exit}=10$\C{go here to leave a procedure}\par -\P\D \37$\\{restart}=20$\C{go here to start a procedure again}\par -\P\D \37$\\{reswitch}=21$\C{go here to start a case statement again}\par -\P\D \37$\\{continue}=22$\C{go here to resume a loop}\par -\P\D \37$\\{done}=30$\C{go here to exit a loop}\par -\P\D \37$\\{done1}=31$\C{like \\{done}, when there is more than one loop}\par -\P\D \37$\\{done2}=32$\C{for exiting the second loop in a long block}\par -\P\D \37$\\{done3}=33$\C{for exiting the third loop in a very long block}\par -\P\D \37$\\{done4}=34$\C{for exiting the fourth loop in an extremely long -block}\par -\P\D \37$\\{done5}=35$\C{for exiting the fifth loop in an immense block}\par -\P\D \37$\\{done6}=36$\C{for exiting the sixth loop in a block}\par -\P\D \37$\\{found}=40$\C{go here when you've found it}\par -\P\D \37$\\{found1}=41$\C{like \\{found}, when there's more than one per -routine}\par -\P\D \37$\\{found2}=42$\C{like \\{found}, when there's more than two per -routine}\par -\P\D \37$\\{not\_found}=45$\C{go here when you've found nothing}\par -\P\D \37$\\{common\_ending}=50$\C{go here when you want to merge with another -branch}\par -\fi - -\M16. Here are some macros for common programming idioms. - -\Y\P\D \37$\\{incr}(\#)\S\#\K\#+1$\C{increase a variable by unity}\par -\P\D \37$\\{decr}(\#)\S\#\K\#-1$\C{decrease a variable by unity}\par -\P\D \37$\\{negate}(\#)\S\#\K-\#$\C{change the sign of a variable}\par -\P\D \37$\\{double}(\#)\S\#\K\#+\#$\C{multiply a variable by two}\par -\P\D \37$\\{loop}\S$\ \&{while} $\\{true}$ \1\&{do}\ \C{repeat over and over -until a \&{goto} happens}\par -\P\F \37$\\{loop}\S\\{xclause}$\C{\.{WEB}'s \~ \&{xclause} acts like `% -\ignorespaces \&{while} $\\{true}$ \&{do}\unskip'}\par -\P\D \37$\\{do\_nothing}\S$\C{empty statement}\par -\P\D \37$\\{return}\S$\1\5 -\&{goto} \37\\{exit}\C{terminate a procedure call}\2\par -\P\F \37$\\{return}\S\\{nil}$\C{\.{WEB} will henceforth say \&{return} instead -of \\{return}}\par -\fi - -\N17. \[2] The character set. -In order to make \MF\ readily portable to a wide variety of -computers, all of its input text is converted to an internal eight-bit -code that includes standard ASCII, the ``American Standard Code for -Information Interchange.'' This conversion is done immediately when each -character is read in. Conversely, characters are converted from ASCII to -the user's external representation just before they are output to a -text file. - -Such an internal code is relevant to users of \MF\ only with respect to -the \&{char} and \&{ASCII} operations, and the comparison of strings. - -\fi - -\M18. Characters of text that have been converted to \MF's internal form -are said to be of type \\{ASCII\_code}, which is a subrange of the integers. - -\Y\P$\4\X18:Types in the outer block\X\S$\6 -$\\{ASCII\_code}=0\to255$;\C{eight-bit numbers}\par -\As24, 37, 101, 105, 106, 156, 186, 565, 571, 627\ETs1151. -\U4.\fi - -\M19. The original \PASCAL\ compiler was designed in the late 60s, when six-bit -character sets were common, so it did not make provision for lowercase -letters. Nowadays, of course, we need to deal with both capital and small -letters in a convenient way, especially in a program for font design; -so the present specification of \MF\ has been written under the assumption -that the \PASCAL\ compiler and run-time system permit the use of text files -with more than 64 distinguishable characters. More precisely, we assume that -the character set contains at least the letters and symbols associated -with ASCII codes \O{40} through \O{176}; all of these characters are now -available on most computer terminals. - -Since we are dealing with more characters than were present in the first -\PASCAL\ compilers, we have to decide what to call the associated data -type. Some \PASCAL s use the original name \\{char} for the -characters in text files, even though there now are more than 64 such -characters, while other \PASCAL s consider \\{char} to be a 64-element -subrange of a larger data type that has some other name. - -In order to accommodate this difference, we shall use the name \\{text\_char} -to stand for the data type of the characters that are converted to and -from \\{ASCII\_code} when they are input and output. We shall also assume -that \\{text\_char} consists of the elements $\\{chr}(\\{first\_text\_char})$ -through -$\\{chr}(\\{last\_text\_char})$, inclusive. The following definitions should be -adjusted if necessary. - -\Y\P\D \37$\\{text\_char}\S\\{char}$\C{the data type of characters in text -files}\par -\P\D \37$\\{first\_text\_char}=0$\C{ordinal number of the smallest element of % -\\{text\_char}}\par -\P\D \37$\\{last\_text\_char}=255$\C{ordinal number of the largest element of % -\\{text\_char}}\par -\Y\P$\4\X19:Local variables for initialization\X\S$\6 -\4\|i: \37\\{integer};\par -\A130. -\U4.\fi - -\M20. The \MF\ processor converts between ASCII code and -the user's external character set by means of arrays \\{xord} and \\{xchr} -that are analogous to \PASCAL's \\{ord} and \\{chr} functions. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{xord}: \37\&{array} $[\\{text\_char}]$ \1\&{of}\5 -\\{ASCII\_code};\C{specifies conversion of input characters}\2\6 -\4\\{xchr}: \37\&{array} $[\\{ASCII\_code}]$ \1\&{of}\5 -\\{text\_char};\C{specifies conversion of output characters}\2\par -\fi - -\M21. Since we are assuming that our \PASCAL\ system is able to read and -write the visible characters of standard ASCII (although not -necessarily using the ASCII codes to represent them), the following -assignment statements initialize the standard part of the \\{xchr} array -properly, without needing any system-dependent changes. On the other -hand, it is possible to implement \MF\ with less complete character -sets, and in such cases it will be necessary to change something here. - -\Y\P$\4\X21:Set initial values of key variables\X\S$\6 -$\\{xchr}[\O{40}]\K\.{\'\ \'}$;\5 -$\\{xchr}[\O{41}]\K\.{\'!\'}$;\5 -$\\{xchr}[\O{42}]\K\.{\'"\'}$;\5 -$\\{xchr}[\O{43}]\K\.{\'\#\'}$;\5 -$\\{xchr}[\O{44}]\K\.{\'\$\'}$;\5 -$\\{xchr}[\O{45}]\K\.{\'\%\'}$;\5 -$\\{xchr}[\O{46}]\K\.{\'\&\'}$;\5 -$\\{xchr}[\O{47}]\K\.{\'\'}\.{\'\'}$;\6 -$\\{xchr}[\O{50}]\K\.{\'(\'}$;\5 -$\\{xchr}[\O{51}]\K\.{\')\'}$;\5 -$\\{xchr}[\O{52}]\K\.{\'*\'}$;\5 -$\\{xchr}[\O{53}]\K\.{\'+\'}$;\5 -$\\{xchr}[\O{54}]\K\.{\',\'}$;\5 -$\\{xchr}[\O{55}]\K\.{\'-\'}$;\5 -$\\{xchr}[\O{56}]\K\.{\'.\'}$;\5 -$\\{xchr}[\O{57}]\K\.{\'/\'}$;\6 -$\\{xchr}[\O{60}]\K\.{\'0\'}$;\5 -$\\{xchr}[\O{61}]\K\.{\'1\'}$;\5 -$\\{xchr}[\O{62}]\K\.{\'2\'}$;\5 -$\\{xchr}[\O{63}]\K\.{\'3\'}$;\5 -$\\{xchr}[\O{64}]\K\.{\'4\'}$;\5 -$\\{xchr}[\O{65}]\K\.{\'5\'}$;\5 -$\\{xchr}[\O{66}]\K\.{\'6\'}$;\5 -$\\{xchr}[\O{67}]\K\.{\'7\'}$;\6 -$\\{xchr}[\O{70}]\K\.{\'8\'}$;\5 -$\\{xchr}[\O{71}]\K\.{\'9\'}$;\5 -$\\{xchr}[\O{72}]\K\.{\':\'}$;\5 -$\\{xchr}[\O{73}]\K\.{\';\'}$;\5 -$\\{xchr}[\O{74}]\K\.{\'<\'}$;\5 -$\\{xchr}[\O{75}]\K\.{\'=\'}$;\5 -$\\{xchr}[\O{76}]\K\.{\'>\'}$;\5 -$\\{xchr}[\O{77}]\K\.{\'?\'}$;\6 -$\\{xchr}[\O{100}]\K\.{\'@\'}$;\5 -$\\{xchr}[\O{101}]\K\.{\'A\'}$;\5 -$\\{xchr}[\O{102}]\K\.{\'B\'}$;\5 -$\\{xchr}[\O{103}]\K\.{\'C\'}$;\5 -$\\{xchr}[\O{104}]\K\.{\'D\'}$;\5 -$\\{xchr}[\O{105}]\K\.{\'E\'}$;\5 -$\\{xchr}[\O{106}]\K\.{\'F\'}$;\5 -$\\{xchr}[\O{107}]\K\.{\'G\'}$;\6 -$\\{xchr}[\O{110}]\K\.{\'H\'}$;\5 -$\\{xchr}[\O{111}]\K\.{\'I\'}$;\5 -$\\{xchr}[\O{112}]\K\.{\'J\'}$;\5 -$\\{xchr}[\O{113}]\K\.{\'K\'}$;\5 -$\\{xchr}[\O{114}]\K\.{\'L\'}$;\5 -$\\{xchr}[\O{115}]\K\.{\'M\'}$;\5 -$\\{xchr}[\O{116}]\K\.{\'N\'}$;\5 -$\\{xchr}[\O{117}]\K\.{\'O\'}$;\6 -$\\{xchr}[\O{120}]\K\.{\'P\'}$;\5 -$\\{xchr}[\O{121}]\K\.{\'Q\'}$;\5 -$\\{xchr}[\O{122}]\K\.{\'R\'}$;\5 -$\\{xchr}[\O{123}]\K\.{\'S\'}$;\5 -$\\{xchr}[\O{124}]\K\.{\'T\'}$;\5 -$\\{xchr}[\O{125}]\K\.{\'U\'}$;\5 -$\\{xchr}[\O{126}]\K\.{\'V\'}$;\5 -$\\{xchr}[\O{127}]\K\.{\'W\'}$;\6 -$\\{xchr}[\O{130}]\K\.{\'X\'}$;\5 -$\\{xchr}[\O{131}]\K\.{\'Y\'}$;\5 -$\\{xchr}[\O{132}]\K\.{\'Z\'}$;\5 -$\\{xchr}[\O{133}]\K\.{\'[\'}$;\5 -$\\{xchr}[\O{134}]\K\.{\'\\\'}$;\5 -$\\{xchr}[\O{135}]\K\.{\']\'}$;\5 -$\\{xchr}[\O{136}]\K\.{\'\^\'}$;\5 -$\\{xchr}[\O{137}]\K\.{\'\_\'}$;\6 -$\\{xchr}[\O{140}]\K\.{\'\`\'}$;\5 -$\\{xchr}[\O{141}]\K\.{\'a\'}$;\5 -$\\{xchr}[\O{142}]\K\.{\'b\'}$;\5 -$\\{xchr}[\O{143}]\K\.{\'c\'}$;\5 -$\\{xchr}[\O{144}]\K\.{\'d\'}$;\5 -$\\{xchr}[\O{145}]\K\.{\'e\'}$;\5 -$\\{xchr}[\O{146}]\K\.{\'f\'}$;\5 -$\\{xchr}[\O{147}]\K\.{\'g\'}$;\6 -$\\{xchr}[\O{150}]\K\.{\'h\'}$;\5 -$\\{xchr}[\O{151}]\K\.{\'i\'}$;\5 -$\\{xchr}[\O{152}]\K\.{\'j\'}$;\5 -$\\{xchr}[\O{153}]\K\.{\'k\'}$;\5 -$\\{xchr}[\O{154}]\K\.{\'l\'}$;\5 -$\\{xchr}[\O{155}]\K\.{\'m\'}$;\5 -$\\{xchr}[\O{156}]\K\.{\'n\'}$;\5 -$\\{xchr}[\O{157}]\K\.{\'o\'}$;\6 -$\\{xchr}[\O{160}]\K\.{\'p\'}$;\5 -$\\{xchr}[\O{161}]\K\.{\'q\'}$;\5 -$\\{xchr}[\O{162}]\K\.{\'r\'}$;\5 -$\\{xchr}[\O{163}]\K\.{\'s\'}$;\5 -$\\{xchr}[\O{164}]\K\.{\'t\'}$;\5 -$\\{xchr}[\O{165}]\K\.{\'u\'}$;\5 -$\\{xchr}[\O{166}]\K\.{\'v\'}$;\5 -$\\{xchr}[\O{167}]\K\.{\'w\'}$;\6 -$\\{xchr}[\O{170}]\K\.{\'x\'}$;\5 -$\\{xchr}[\O{171}]\K\.{\'y\'}$;\5 -$\\{xchr}[\O{172}]\K\.{\'z\'}$;\5 -$\\{xchr}[\O{173}]\K\.{\'\{\'}$;\5 -$\\{xchr}[\O{174}]\K\.{\'|\'}$;\5 -$\\{xchr}[\O{175}]\K\.{\'\}\'}$;\5 -$\\{xchr}[\O{176}]\K\.{\'\~\'}$;\par -\As22, 23, 69, 72, 75, 92, 98, 131, 138, 179, 191, 199, 202, 231, 251, 396, -428, 449, 456, 462, 570, 573, 593, 739, 753, 776, 797, 822, 1078, 1085, 1097, -1150, 1153\ETs1184. -\U4.\fi - -\M22. The ASCII code is ``standard'' only to a certain extent, since many -computer installations have found it advantageous to have ready access -to more than 94 printing characters. If \MF\ is being used -on a garden-variety \PASCAL\ for which only standard ASCII -codes will appear in the input and output files, it doesn't really matter -what codes are specified in $\\{xchr}[0\to\O{37}]$, but the safest policy is to -blank everything out by using the code shown below. - -However, other settings of \\{xchr} will make \MF\ more friendly on -computers that have an extended character set, so that users can type things -like `\.^^Z' instead of `\.{<>}'. -People with extended character sets can -assign codes arbitrarily, giving an \\{xchr} equivalent to whatever -characters the users of \MF\ are allowed to have in their input files. -Appropriate changes to \MF's \\{char\_class} table should then be made. -(Unlike \TeX, each installation of \MF\ has a fixed assignment of category -codes, called the \\{char\_class}.) Such changes make portability of programs -more difficult, so they should be introduced cautiously if at all. - -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -\&{for} $\|i\K0\mathrel{\&{to}}\O{37}$ \1\&{do}\5 -$\\{xchr}[\|i]\K\.{\'\ \'}$;\2\6 -\&{for} $\|i\K\O{177}\mathrel{\&{to}}\O{377}$ \1\&{do}\5 -$\\{xchr}[\|i]\K\.{\'\ \'}$;\2\par -\fi - -\M23. The following system-independent code makes the \\{xord} array contain a -suitable inverse to the information in \\{xchr}. Note that if $\\{xchr}[\|i]=% -\\{xchr}[\|j]$ -where $\|i<\|j<\O{177}$, the value of $\\{xord}[\\{xchr}[\|i]]$ will turn out -to be -\|j or more; hence, standard ASCII code numbers will be used instead of -codes below \O{40} in case there is a coincidence. - -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -\&{for} $\|i\K\\{first\_text\_char}\mathrel{\&{to}}\\{last\_text\_char}$ \1% -\&{do}\5 -$\\{xord}[\\{chr}(\|i)]\K\O{177}$;\2\6 -\&{for} $\|i\K\O{200}\mathrel{\&{to}}\O{377}$ \1\&{do}\5 -$\\{xord}[\\{xchr}[\|i]]\K\|i$;\2\6 -\&{for} $\|i\K0\mathrel{\&{to}}\O{176}$ \1\&{do}\5 -$\\{xord}[\\{xchr}[\|i]]\K\|i$;\2\par -\fi - -\N24. \[3] Input and output. -The bane of portability is the fact that different operating systems treat -input and output quite differently, perhaps because computer scientists -have not given sufficient attention to this problem. People have felt somehow -that input and output are not part of ``real'' programming. Well, it is true -that some kinds of programming are more fun than others. With existing -input/output conventions being so diverse and so messy, the only sources of -joy in such parts of the code are the rare occasions when one can find a -way to make the program a little less bad than it might have been. We have -two choices, either to attack I/O now and get it over with, or to postpone -I/O until near the end. Neither prospect is very attractive, so let's -get it over with. - -The basic operations we need to do are (1)~inputting and outputting of -text, to or from a file or the user's terminal; (2)~inputting and -outputting of eight-bit bytes, to or from a file; (3)~instructing the -operating system to initiate (``open'') or to terminate (``close'') input or -output from a specified file; (4)~testing whether the end of an input -file has been reached; (5)~display of bits on the user's screen. -The bit-display operation will be discussed in a later section; we shall -deal here only with more traditional kinds of I/O. - -\MF\ needs to deal with two kinds of files. -We shall use the term \\{alpha\_file} for a file that contains textual data, -and the term \\{byte\_file} for a file that contains eight-bit binary -information. -These two types turn out to be the same on many computers, but -sometimes there is a significant distinction, so we shall be careful to -distinguish between them. Standard protocols for transferring -such files from computer to computer, via high-speed networks, are -now becoming available to more and more communities of users. - -The program actually makes use also of a third kind of file, called a -\\{word\_file}, when dumping and reloading base information for its own -initialization. We shall define a word file later; but it will be possible -for us to specify simple operations on word files before they are defined. - -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{eight\_bits}=0\to255$;\C{unsigned one-byte quantity}\6 -$\\{alpha\_file}=$\1\5 -\&{packed} \37\&{file} \1\&{of}\5 -\\{text\_char};\C{files that contain textual data}\2\2\6 -$\\{byte\_file}=$\1\5 -\&{packed} \37\&{file} \1\&{of}\5 -\\{eight\_bits};\C{files that contain binary data}\2\2\par -\fi - -\M25. Most of what we need to do with respect to input and output can be -handled -by the I/O facilities that are standard in \PASCAL, i.e., the routines -called \\{get}, \\{put}, \\{eof}, and so on. But -standard \PASCAL\ does not allow file variables to be associated with file -names that are determined at run time, so it cannot be used to implement -\MF; some sort of extension to \PASCAL's ordinary \\{reset} and \\{rewrite} -is crucial for our purposes. We shall assume that \\{name\_of\_file} is a -variable -of an appropriate type such that the \PASCAL\ run-time system being used to -implement \MF\ can open a file whose external name is specified by -\\{name\_of\_file}. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{name\_of\_file}: \37\&{packed} \37\&{array} $[1\to\\{file\_name\_size}]$ % -\1\&{of}\5 -\\{char};\2\6 -\C{on some systems this may be a \&{record} variable}\6 -\4\\{name\_length}: \37$0\to\\{file\_name\_size}$;\6 -\C{this many characters are actually relevant in \\{name\_of\_file} (the rest -are blank)}\par -\fi - -\M26. The \ph\ compiler with which the present version of \MF\ was prepared has -extended the rules of \PASCAL\ in a very convenient way. To open file~\|f, -we can write -$$\vbox{\halign{#\hfil\qquad&#\hfil\cr -$\\{reset}(\|f,\hbox{\\{name}},\.{\'/O\'})$&for input;\cr -$\\{rewrite}(\|f,\hbox{\\{name}},\.{\'/O\'})$&for output.\cr}}$$ -The `\\{name}' parameter, which is of type `\ignorespaces\&{packed} \&{array} -$[\hbox{\<\\{any}>}]$ \&{of} \\{text\_char}', stands for the name of -the external file that is being opened for input or output. -Blank spaces that might appear in \\{name} are ignored. - -The `\.{/O}' parameter tells the operating system not to issue its own -error messages if something goes wrong. If a file of the specified name -cannot be found, or if such a file cannot be opened for some other reason -(e.g., someone may already be trying to write the same file), we will have -$\\{erstat}(\|f)\I0$ after an unsuccessful \\{reset} or \\{rewrite}. This -allows -\MF\ to undertake appropriate corrective action. - -\MF's file-opening procedures return \\{false} if no file identified by -\\{name\_of\_file} could be opened. - -\Y\P\D \37$\\{reset\_OK}(\#)\S\\{erstat}(\#)=0$\par -\P\D \37$\\{rewrite\_OK}(\#)\S\\{erstat}(\#)=0$\par -\Y\P\4\&{function}\1\ \37$\\{a\_open\_in}(\mathop{\&{var}}\|f:\\{alpha% -\_file})$: \37\\{boolean};\C{open a text file for input}\2\6 -\&{begin} \37$\\{reset}(\|f,\39\\{name\_of\_file},\39\.{\'/O\'})$;\5 -$\\{a\_open\_in}\K\\{reset\_OK}(\|f)$;\6 -\&{end};\7 -\4\&{function}\1\ \37$\\{a\_open\_out}(\mathop{\&{var}}\|f:\\{alpha\_file})$: % -\37\\{boolean};\C{open a text file for output}\2\6 -\&{begin} \37$\\{rewrite}(\|f,\39\\{name\_of\_file},\39\.{\'/O\'})$;\5 -$\\{a\_open\_out}\K\\{rewrite\_OK}(\|f)$;\6 -\&{end};\7 -\4\&{function}\1\ \37$\\{b\_open\_out}(\mathop{\&{var}}\|f:\\{byte\_file})$: % -\37\\{boolean};\C{open a binary file for output}\2\6 -\&{begin} \37$\\{rewrite}(\|f,\39\\{name\_of\_file},\39\.{\'/O\'})$;\5 -$\\{b\_open\_out}\K\\{rewrite\_OK}(\|f)$;\6 -\&{end};\7 -\4\&{function}\1\ \37$\\{w\_open\_in}(\mathop{\&{var}}\|f:\\{word\_file})$: % -\37\\{boolean};\C{open a word file for input}\2\6 -\&{begin} \37$\\{reset}(\|f,\39\\{name\_of\_file},\39\.{\'/O\'})$;\5 -$\\{w\_open\_in}\K\\{reset\_OK}(\|f)$;\6 -\&{end};\7 -\4\&{function}\1\ \37$\\{w\_open\_out}(\mathop{\&{var}}\|f:\\{word\_file})$: % -\37\\{boolean};\C{open a word file for output}\2\6 -\&{begin} \37$\\{rewrite}(\|f,\39\\{name\_of\_file},\39\.{\'/O\'})$;\5 -$\\{w\_open\_out}\K\\{rewrite\_OK}(\|f)$;\6 -\&{end};\par -\fi - -\M27. Files can be closed with the \ph\ routine `$\\{close}(\|f)$', which -should be used when all input or output with respect to \|f has been completed. -This makes \|f available to be opened again, if desired; and if \|f was used -for -output, the \\{close} operation makes the corresponding external file appear -on the user's area, ready to be read. - -\Y\P\4\&{procedure}\1\ \37$\\{a\_close}(\mathop{\&{var}}\|f:\\{alpha\_file})$;% -\C{close a text file}\2\6 -\&{begin} \37$\\{close}(\|f)$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{b\_close}(\mathop{\&{var}}\|f:\\{byte\_file})$;% -\C{close a binary file}\2\6 -\&{begin} \37$\\{close}(\|f)$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{w\_close}(\mathop{\&{var}}\|f:\\{word\_file})$;% -\C{close a word file}\2\6 -\&{begin} \37$\\{close}(\|f)$;\6 -\&{end};\par -\fi - -\M28. Binary input and output are done with \PASCAL's ordinary \\{get} and % -\\{put} -procedures, so we don't have to make any other special arrangements for -binary~I/O. Text output is also easy to do with standard \PASCAL\ routines. -The treatment of text input is more difficult, however, because -of the necessary translation to \\{ASCII\_code} values. -\MF's conventions should be efficient, and they should -blend nicely with the user's operating environment. - -\fi - -\M29. Input from text files is read one line at a time, using a routine called -\\{input\_ln}. This function is defined in terms of global variables called -\\{buffer}, \\{first}, and \\{last} that will be described in detail later; for -now, it suffices for us to know that \\{buffer} is an array of \\{ASCII\_code} -values, and that \\{first} and \\{last} are indices into this array -representing the beginning and ending of a line of text. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{buffer}: \37\&{array} $[0\to\\{buf\_size}]$ \1\&{of}\5 -\\{ASCII\_code};\C{lines of characters being read}\2\6 -\4\\{first}: \37$0\to\\{buf\_size}$;\C{the first unused position in \\{buffer}}% -\6 -\4\\{last}: \37$0\to\\{buf\_size}$;\C{end of the line just input to \\{buffer}}% -\6 -\4\\{max\_buf\_stack}: \37$0\to\\{buf\_size}$;\C{largest index used in % -\\{buffer}}\par -\fi - -\M30. The \\{input\_ln} function brings the next line of input from the -specified -field into available positions of the buffer array and returns the value -\\{true}, unless the file has already been entirely read, in which case it -returns \\{false} and sets $\\{last}\K\\{first}$. In general, the \\{ASCII% -\_code} -numbers that represent the next line of the file are input into -$\\{buffer}[\\{first}]$, $\\{buffer}[\\{first}+1]$, \dots, $\\{buffer}[% -\\{last}-1]$; and the -global variable \\{last} is set equal to \\{first} plus the length of the -line. Trailing blanks are removed from the line; thus, either $\\{last}=% -\\{first}$ -(in which case the line was entirely blank) or $\\{buffer}[\\{last}-1]\I\.{"\ -"}$. - -An overflow error is given, however, if the normal actions of \\{input\_ln} -would make $\\{last}\G\\{buf\_size}$; this is done so that other parts of \MF\ -can safely look at the contents of $\\{buffer}[\\{last}+1]$ without -overstepping -the bounds of the \\{buffer} array. Upon entry to \\{input\_ln}, the condition -$\\{first}<\\{buf\_size}$ will always hold, so that there is always room for an -``empty'' line. - -The variable \\{max\_buf\_stack}, which is used to keep track of how large -the \\{buf\_size} parameter must be to accommodate the present job, is -also kept up to date by \\{input\_ln}. - -If the \\{bypass\_eoln} parameter is \\{true}, \\{input\_ln} will do a \\{get} -before looking at the first character of the line; this skips over -an \\{eoln} that was in $\|f\^$. The procedure does not do a \\{get} when it -reaches the end of the line; therefore it can be used to acquire input -from the user's terminal as well as from ordinary text files. - -Standard \PASCAL\ says that a file should have \\{eoln} immediately -before \\{eof}, but \MF\ needs only a weaker restriction: If \\{eof} -occurs in the middle of a line, the system function \\{eoln} should return -a \\{true} result (even though $\|f\^$ will be undefined). - -\Y\P\4\&{function}\1\ \37$\\{input\_ln}(\mathop{\&{var}}\|f:\\{alpha\_file};\,% -\35\\{bypass\_eoln}:\\{boolean})$: \37\\{boolean};\C{inputs the next line or -returns \\{false}}\6 -\4\&{var} \37\\{last\_nonblank}: \37$0\to\\{buf\_size}$;\C{\\{last} with -trailing blanks removed}\2\6 -\&{begin} \37\&{if} $\\{bypass\_eoln}$ \1\&{then}\6 -\&{if} $\R\\{eof}(\|f)$ \1\&{then}\5 -$\\{get}(\|f)$;\C{input the first character of the line into $\|f\^$}\2\2\6 -$\\{last}\K\\{first}$;\C{cf.\ Matthew 19\thinspace:\thinspace30}\6 -\&{if} $\\{eof}(\|f)$ \1\&{then}\5 -$\\{input\_ln}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\\{last\_nonblank}\K\\{first}$;\6 -\&{while} $\R\\{eoln}(\|f)$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{last}\G\\{max\_buf\_stack}$ \1\&{then}\6 -\&{begin} \37$\\{max\_buf\_stack}\K\\{last}+1$;\6 -\&{if} $\\{max\_buf\_stack}=\\{buf\_size}$ \1\&{then}\5 -\X34:Report overflow of the input buffer, and abort\X;\2\6 -\&{end};\2\6 -$\\{buffer}[\\{last}]\K\\{xord}[\|f\^]$;\5 -$\\{get}(\|f)$;\5 -$\\{incr}(\\{last})$;\6 -\&{if} $\\{buffer}[\\{last}-1]\I\.{"\ "}$ \1\&{then}\5 -$\\{last\_nonblank}\K\\{last}$;\2\6 -\&{end};\2\6 -$\\{last}\K\\{last\_nonblank}$;\5 -$\\{input\_ln}\K\\{true}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M31. The user's terminal acts essentially like other files of text, except -that it is used both for input and for output. When the terminal is -considered an input file, the file variable is called \\{term\_in}, and when it -is considered an output file the file variable is \\{term\_out}. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{term\_in}: \37\\{alpha\_file};\C{the terminal as an input file}\6 -\4\\{term\_out}: \37\\{alpha\_file};\C{the terminal as an output file}\par -\fi - -\M32. Here is how to open the terminal files -in \ph. The `\.{/I}' switch suppresses the first \\{get}. - -\Y\P\D \37$\\{t\_open\_in}\S\\{reset}(\\{term\_in},\39\.{\'TTY:\'},\39\.{\'/O/I% -\'})$\C{open the terminal for text input}\par -\P\D \37$\\{t\_open\_out}\S\\{rewrite}(\\{term\_out},\39\.{\'TTY:\'},\39\.{\'/O% -\'})$\C{open the terminal for text output}\par -\fi - -\M33. Sometimes it is necessary to synchronize the input/output mixture that -happens on the user's terminal, and three system-dependent -procedures are used for this -purpose. The first of these, \\{update\_terminal}, is called when we want -to make sure that everything we have output to the terminal so far has -actually left the computer's internal buffers and been sent. -The second, \\{clear\_terminal}, is called when we wish to cancel any -input that the user may have typed ahead (since we are about to -issue an unexpected error message). The third, \\{wake\_up\_terminal}, -is supposed to revive the terminal if the user has disabled it by -some instruction to the operating system. The following macros show how -these operations can be specified in \ph: - -\Y\P\D \37$\\{update\_terminal}\S\\{break}(\\{term\_out})$\C{empty the terminal -output buffer}\par -\P\D \37$\\{clear\_terminal}\S\\{break\_in}(\\{term\_in},\39\\{true})$\C{clear -the terminal input buffer}\par -\P\D \37$\\{wake\_up\_terminal}\S\\{do\_nothing}$\C{cancel the user's -cancellation of output}\par -\fi - -\M34. We need a special routine to read the first line of \MF\ input from -the user's terminal. This line is different because it is read before we -have opened the transcript file; there is sort of a ``chicken and -egg'' problem here. If the user types `\.{input cmr10}' on the first -line, or if some macro invoked by that line does such an \.{input}, -the transcript file will be named `\.{cmr10.log}'; but if no \.{input} -commands are performed during the first line of terminal input, the transcript -file will acquire its default name `\.{mfput.log}'. (The transcript file -will not contain error messages generated by the first line before the -first \.{input} command.) - -The first line is even more special if we are lucky enough to have an operating -system that treats \MF\ differently from a run-of-the-mill \PASCAL\ object -program. It's nice to let the user start running a \MF\ job by typing -a command line like `\.{MF cmr10}'; in such a case, \MF\ will operate -as if the first line of input were `\.{cmr10}', i.e., the first line will -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. -(If the \PASCAL\ compiler does not support non-local \&{goto} , the -statement `\&{goto} \\{final\_end}' should be replaced by something that -quietly terminates the program.) - -\Y\P$\4\X34:Report overflow of the input buffer, and abort\X\S$\6 -\&{if} $\\{base\_ident}=0$ \1\&{then}\6 -\&{begin} \37$\\{write\_ln}(\\{term\_out},\39\.{\'Buffer\ size\ exceeded!\'})$;% -\5 -\&{goto} \37\\{final\_end};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{cur\_input}.\\{loc\_field}\K\\{first}$;\5 -$\\{cur\_input}.\\{limit\_field}\K\\{last}-1$;\5 -$\\{overflow}(\.{"buffer\ size"},\39\\{buf\_size})$;\6 -\&{end}\2\par -\U30.\fi - -\M35. Different systems have different ways to get started. But regardless of -what conventions are adopted, the routine that initializes the terminal -should satisfy the following specifications: - -\yskip\textindent{1)}It should open file \\{term\_in} for input from the -terminal. (The file \\{term\_out} will already be open for output to the -terminal.) - -\textindent{2)}If the user has given a command line, this line should be -considered the first line of terminal input. Otherwise the -user should be prompted with `\.{**}', and the first line of input -should be whatever is typed in response. - -\textindent{3)}The first line of input, which might or might not be a -command line, should appear in locations \\{first} to $\\{last}-1$ of the -\\{buffer} array. - -\textindent{4)}The global variable \\{loc} should be set so that the -character to be read next by \MF\ is in $\\{buffer}[\\{loc}]$. This -character should not be blank, and we should have $\\{loc}<\\{last}$. - -\yskip\noindent(It may be necessary to prompt the user several times -before a non-blank line comes in. The prompt is `\.{**}' instead of the -later `\.*' because the meaning is slightly different: `\.{input}' need -not be typed immediately after~`\.{**}'.) - -\Y\P\D \37$\\{loc}\S\\{cur\_input}.\\{loc\_field}$\C{location of first unread -character in \\{buffer}}\par -\fi - -\M36. The following program does the required initialization -without retrieving a possible command line. -It should be clear how to modify this routine to deal with command lines, -if the system permits them. - -\Y\P\4\&{function}\1\ \37\\{init\_terminal}: \37\\{boolean};\C{gets the -terminal input started}\6 -\4\&{label} \37\\{exit};\2\6 -\&{begin} \37\\{t\_open\_in};\6 -\~ \1\&{loop}\ \&{begin} \37\\{wake\_up\_terminal};\5 -$\\{write}(\\{term\_out},\39\.{\'**\'})$;\5 -\\{update\_terminal};\6 -\&{if} $\R\\{input\_ln}(\\{term\_in},\39\\{true})$ \1\&{then}\C{this shouldn't -happen}\6 -\&{begin} \37$\\{write\_ln}(\\{term\_out})$;\5 -$\\{write}(\\{term\_out},\39\.{\'!\ End\ of\ file\ on\ the\ terminal...\ why?% -\'})$;\5 -$\\{init\_terminal}\K\\{false}$;\5 -\&{return};\6 -\&{end};\2\6 -$\\{loc}\K\\{first}$;\6 -\&{while} $(\\{loc}<\\{last})\W(\\{buffer}[\\{loc}]=\.{"\ "})$ \1\&{do}\5 -$\\{incr}(\\{loc})$;\2\6 -\&{if} $\\{loc}<\\{last}$ \1\&{then}\6 -\&{begin} \37$\\{init\_terminal}\K\\{true}$;\5 -\&{return};\C{return unless the line was all blank}\6 -\&{end};\2\6 -$\\{write\_ln}(\\{term\_out},\39\.{\'Please\ type\ the\ name\ of\ your\ input\ -file.\'})$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\N37. \[4] String handling. -Symbolic token names and diagnostic messages are variable-length strings -of eight-bit characters. Since \PASCAL\ does not have a well-developed string -mechanism, \MF\ does all of its string processing by homegrown methods. - -Elaborate facilities for dynamic strings are not needed, so all of the -necessary operations can be handled with a simple data structure. -The array \\{str\_pool} contains all of the (eight-bit) ASCII codes in all -of the strings, and the array \\{str\_start} contains indices of the starting -points of each string. Strings are referred to by integer numbers, so that -string number \|s comprises the characters $\\{str\_pool}[\|j]$ for -$\\{str\_start}[\|s]\L\|j<\\{str\_start}[\|s+1]$. Additional integer variables -\\{pool\_ptr} and \\{str\_ptr} indicate the number of entries used so far -in \\{str\_pool} and \\{str\_start}, respectively; locations -$\\{str\_pool}[\\{pool\_ptr}]$ and $\\{str\_start}[\\{str\_ptr}]$ are -ready for the next string to be allocated. - -String numbers 0 to 255 are reserved for strings that correspond to single -ASCII characters. This is in accordance with the conventions of \.{WEB}, -which converts single-character strings into the ASCII code number of the -single character involved, while it converts other strings into integers -and builds a string pool file. Thus, when the string constant \.{"."} appears -in the program below, \.{WEB} converts it into the integer 46, which is the -ASCII code for a period, while \.{WEB} will convert a string like \.{"hello"} -into some integer greater than~255. String number 46 will presumably be the -single character `\..'\thinspace; but some ASCII codes have no standard visible -representation, and \MF\ may need to be able to print an arbitrary -ASCII character, so the first 256 strings are used to specify exactly what -should be printed for each of the 256 possibilities. - -Elements of the \\{str\_pool} array must be ASCII codes that can actually be -printed; i.e., they must have an \\{xchr} equivalent in the local -character set. (This restriction applies only to preloaded strings, -not to those generated dynamically by the user.) - -Some \PASCAL\ compilers won't pack integers into a single byte unless the -integers lie in the range $-128\to127$. To accommodate such systems -we access the string pool only via macros that can easily be redefined. - -\Y\P\D \37$\\{si}(\#)\S\#$\C{convert from \\{ASCII\_code} to \\{packed\_ASCII% -\_code}}\par -\P\D \37$\\{so}(\#)\S\#$\C{convert from \\{packed\_ASCII\_code} to \\{ASCII% -\_code}}\par -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{pool\_pointer}=0\to\\{pool\_size}$;\C{for variables that point into \\{str% -\_pool}}\6 -$\\{str\_number}=0\to\\{max\_strings}$;\C{for variables that point into \\{str% -\_start}}\6 -$\\{packed\_ASCII\_code}=0\to255$;\C{elements of \\{str\_pool} array}\par -\fi - -\M38. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{str\_pool}: \37\&{packed} \37\&{array} $[\\{pool\_pointer}]$ \1\&{of}\5 -\\{packed\_ASCII\_code};\C{the characters}\2\6 -\4\\{str\_start}: \37\&{array} $[\\{str\_number}]$ \1\&{of}\5 -\\{pool\_pointer};\C{the starting pointers}\2\6 -\4\\{pool\_ptr}: \37\\{pool\_pointer};\C{first unused position in \\{str% -\_pool}}\6 -\4\\{str\_ptr}: \37\\{str\_number};\C{number of the current string being -created}\6 -\4\\{init\_pool\_ptr}: \37\\{pool\_pointer};\C{the starting value of \\{pool% -\_ptr}}\6 -\4\\{init\_str\_ptr}: \37\\{str\_number};\C{the starting value of \\{str\_ptr}}% -\6 -\4\\{max\_pool\_ptr}: \37\\{pool\_pointer};\C{the maximum so far of \\{pool% -\_ptr}}\6 -\4\\{max\_str\_ptr}: \37\\{str\_number};\C{the maximum so far of \\{str\_ptr}}% -\par -\fi - -\M39. Several of the elementary string operations are performed using \.{WEB} -macros instead of \PASCAL\ procedures, because many of the -operations are done quite frequently and we want to avoid the -overhead of procedure calls. For example, here is -a simple macro that computes the length of a string. - -\Y\P\D \37$\\{length}(\#)\S(\\{str\_start}[\#+1]-\\{str\_start}[\#])$\C{the -number of characters in string number \#}\par -\fi - -\M40. The length of the current string is called \\{cur\_length}: - -\Y\P\D \37$\\{cur\_length}\S(\\{pool\_ptr}-\\{str\_start}[\\{str\_ptr}])$\par -\fi - -\M41. Strings are created by appending character codes to \\{str\_pool}. -The \\{append\_char} macro, defined here, does not check to see if the -value of \\{pool\_ptr} has gotten too high; this test is supposed to be -made before \\{append\_char} is used. - -To test if there is room to append \|l more characters to \\{str\_pool}, -we shall write $\\{str\_room}(\|l)$, which aborts \MF\ and gives an -apologetic error message if there isn't enough room. - -\Y\P\D \37$\\{append\_char}(\#)\S$\C{put \\{ASCII\_code} \# at the end of % -\\{str\_pool}}\6 -\&{begin} \37$\\{str\_pool}[\\{pool\_ptr}]\K\\{si}(\#)$;\5 -$\\{incr}(\\{pool\_ptr})$;\6 -\&{end}\par -\P\D \37$\\{str\_room}(\#)\S$\C{make sure that the pool hasn't overflowed}\6 -\&{begin} \37\&{if} $\\{pool\_ptr}+\#>\\{max\_pool\_ptr}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{pool\_ptr}+\#>\\{pool\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"pool\ size"},\39\\{pool\_size}-\\{init\_pool\_ptr})$;\2\6 -$\\{max\_pool\_ptr}\K\\{pool\_ptr}+\#$;\6 -\&{end};\2\6 -\&{end}\par -\fi - -\M42. \MF's string expressions are implemented in a brute-force way: Every -new string or substring that is needed is simply copied into the string pool. - -Such a scheme can be justified because string expressions aren't a big -deal in \MF\ applications; strings rarely need to be saved from one -statement to the next. But it would waste space needlessly if we didn't -try to reclaim the space of strings that are going to be used only once. - -Therefore a simple reference count mechanism is provided: If there are -no references to a certain string from elsewhere in the program, and -if there are no references to any strings created subsequent to it, -then the string space will be reclaimed. - -The number of references to string number \|s will be $\\{str\_ref}[\|s]$. The -special value $\\{str\_ref}[\|s]=\\{max\_str\_ref}=127$ is used to denote an -unknown -positive number of references; such strings will never be recycled. If -a string is ever referred to more than 126 times, simultaneously, we -put it in this category. Hence a single byte suffices to store each \\{str% -\_ref}. - -\Y\P\D \37$\\{max\_str\_ref}=127$\C{``infinite'' number of references}\par -\P\D \37$\\{add\_str\_ref}(\#)\S$\1\6 -\&{begin} \37\&{if} $\\{str\_ref}[\#]<\\{max\_str\_ref}$ \1\&{then}\5 -$\\{incr}(\\{str\_ref}[\#])$;\2\6 -\&{end}\2\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{str\_ref}: \37\&{array} $[\\{str\_number}]$ \1\&{of}\5 -$0\to\\{max\_str\_ref}$;\2\par -\fi - -\M43. Here's what we do when a string reference disappears: - -\Y\P\D \37$\\{delete\_str\_ref}(\#)\S$\1\6 -\&{begin} \37\&{if} $\\{str\_ref}[\#]<\\{max\_str\_ref}$ \1\&{then}\6 -\&{if} $\\{str\_ref}[\#]>1$ \1\&{then}\5 -$\\{decr}(\\{str\_ref}[\#])$\ \&{else} $\\{flush\_string}(\#)$;\2\2\6 -\&{end}\2\par -\Y\P$\4\X43:Declare the procedure called \\{flush\_string}\X\S$\6 -\4\&{procedure}\1\ \37$\\{flush\_string}(\|s:\\{str\_number})$;\2\6 -\&{begin} \37\&{if} $\|s<\\{str\_ptr}-1$ \1\&{then}\5 -$\\{str\_ref}[\|s]\K0$\6 -\4\&{else} \1\&{repeat} \37$\\{decr}(\\{str\_ptr})$;\6 -\4\&{until}\5 -$\\{str\_ref}[\\{str\_ptr}-1]\I0$;\2\2\6 -$\\{pool\_ptr}\K\\{str\_start}[\\{str\_ptr}]$;\6 -\&{end};\par -\U73.\fi - -\M44. Once a sequence of characters has been appended to \\{str\_pool}, it -officially becomes a string when the function \\{make\_string} is called. -This function returns the identification number of the new string as its -value. - -\Y\P\4\&{function}\1\ \37\\{make\_string}: \37\\{str\_number};\C{current -string enters the pool}\2\6 -\&{begin} \37\&{if} $\\{str\_ptr}=\\{max\_str\_ptr}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{str\_ptr}=\\{max\_strings}$ \1\&{then}\5 -$\\{overflow}(\.{"number\ of\ strings"},\39\\{max\_strings}-\\{init\_str% -\_ptr})$;\2\6 -$\\{incr}(\\{max\_str\_ptr})$;\6 -\&{end};\2\6 -$\\{str\_ref}[\\{str\_ptr}]\K1$;\5 -$\\{incr}(\\{str\_ptr})$;\5 -$\\{str\_start}[\\{str\_ptr}]\K\\{pool\_ptr}$;\5 -$\\{make\_string}\K\\{str\_ptr}-1$;\6 -\&{end};\par -\fi - -\M45. The following subroutine compares string \|s with another string of the -same length that appears in \\{buffer} starting at position \|k; -the result is \\{true} if and only if the strings are equal. - -\Y\P\4\&{function}\1\ \37$\\{str\_eq\_buf}(\|s:\\{str\_number};\,\35\|k:% -\\{integer})$: \37\\{boolean};\C{test equality of strings}\6 -\4\&{label} \37\\{not\_found};\C{loop exit}\6 -\4\&{var} \37\|j: \37\\{pool\_pointer};\C{running index}\6 -\\{result}: \37\\{boolean};\C{result of comparison}\2\6 -\&{begin} \37$\|j\K\\{str\_start}[\|s]$;\6 -\&{while} $\|j<\\{str\_start}[\|s+1]$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{so}(\\{str\_pool}[\|j])\I\\{buffer}[\|k]$ \1\&{then}\6 -\&{begin} \37$\\{result}\K\\{false}$;\5 -\&{goto} \37\\{not\_found};\6 -\&{end};\2\6 -$\\{incr}(\|j)$;\5 -$\\{incr}(\|k)$;\6 -\&{end};\2\6 -$\\{result}\K\\{true}$;\6 -\4\\{not\_found}: \37$\\{str\_eq\_buf}\K\\{result}$;\6 -\&{end};\par -\fi - -\M46. Here is a similar routine, but it compares two strings in the string -pool, -and it does not assume that they have the same length. If the first string -is lexicographically greater than, less than, or equal to the second, -the result is respectively positive, negative, or zero. - -\Y\P\4\&{function}\1\ \37$\\{str\_vs\_str}(\|s,\39\|t:\\{str\_number})$: \37% -\\{integer};\C{test equality of strings}\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|j,\39\|k$: \37\\{pool\_pointer};\C{running indices}\6 -$\\{ls},\39\\{lt}$: \37\\{integer};\C{lengths}\6 -\|l: \37\\{integer};\C{length remaining to test}\2\6 -\&{begin} \37$\\{ls}\K\\{length}(\|s)$;\5 -$\\{lt}\K\\{length}(\|t)$;\6 -\&{if} $\\{ls}\L\\{lt}$ \1\&{then}\5 -$\|l\K\\{ls}$\ \&{else} $\|l\K\\{lt}$;\2\6 -$\|j\K\\{str\_start}[\|s]$;\5 -$\|k\K\\{str\_start}[\|t]$;\6 -\&{while} $\|l>0$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{str\_pool}[\|j]\I\\{str\_pool}[\|k]$ \1\&{then}\6 -\&{begin} \37$\\{str\_vs\_str}\K\\{str\_pool}[\|j]-\\{str\_pool}[\|k]$;\5 -\&{return};\6 -\&{end};\2\6 -$\\{incr}(\|j)$;\5 -$\\{incr}(\|k)$;\5 -$\\{decr}(\|l)$;\6 -\&{end};\2\6 -$\\{str\_vs\_str}\K\\{ls}-\\{lt}$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M47. The initial values of \\{str\_pool}, \\{str\_start}, \\{pool\_ptr}, -and \\{str\_ptr} are computed by the \.{INIMF} program, based in part -on the information that \.{WEB} has output while processing \MF. - -\Y\P\&{init} \37\&{function}\1\ \37\\{get\_strings\_started}: \37\\{boolean};% -\C{initializes the string pool, but returns \\{false} if something goes -wrong}\6 -\4\&{label} \37$\\{done},\39\\{exit}$;\6 -\4\&{var} \37$\|k,\39\|l$: \37$0\to255$;\C{small indices or counters}\6 -$\|m,\39\|n$: \37\\{text\_char};\C{characters input from \\{pool\_file}}\6 -\|g: \37\\{str\_number};\C{garbage}\6 -\|a: \37\\{integer};\C{accumulator for check sum}\6 -\|c: \37\\{boolean};\C{check sum has been checked}\2\6 -\&{begin} \37$\\{pool\_ptr}\K0$;\5 -$\\{str\_ptr}\K0$;\5 -$\\{max\_pool\_ptr}\K0$;\5 -$\\{max\_str\_ptr}\K0$;\5 -$\\{str\_start}[0]\K0$;\5 -\X48:Make the first 256 strings\X;\6 -\X51:Read the other strings from the \.{MF.POOL} file and return \\{true}, or -give an error message and return \\{false}\X;\6 -\4\\{exit}: \37\&{end};\6 -\&{tini}\par -\fi - -\M48. \P\D \37$\\{app\_lc\_hex}(\#)\S\|l\K\#$;\6 -\&{if} $\|l<10$ \1\&{then}\5 -$\\{append\_char}(\|l+\.{"0"})$\ \&{else} $\\{append\_char}(\|l-10+\.{"a"})$\2% -\par -\Y\P$\4\X48:Make the first 256 strings\X\S$\6 -\&{for} $\|k\K0\mathrel{\&{to}}255$ \1\&{do}\6 -\&{begin} \37\&{if} $(\X49:Character \|k cannot be printed\X)$ \1\&{then}\6 -\&{begin} \37$\\{append\_char}(\.{"\^"})$;\5 -$\\{append\_char}(\.{"\^"})$;\6 -\&{if} $\|k<\O{100}$ \1\&{then}\5 -$\\{append\_char}(\|k+\O{100})$\6 -\4\&{else} \&{if} $\|k<\O{200}$ \1\&{then}\5 -$\\{append\_char}(\|k-\O{100})$\6 -\4\&{else} \&{begin} \37$\\{app\_lc\_hex}(\|k\mathbin{\&{div}}16)$;\5 -$\\{app\_lc\_hex}(\|k\mathbin{\&{mod}}16)$;\6 -\&{end};\2\2\6 -\&{end}\6 -\4\&{else} $\\{append\_char}(\|k)$;\2\6 -$\|g\K\\{make\_string}$;\5 -$\\{str\_ref}[\|g]\K\\{max\_str\_ref}$;\6 -\&{end}\2\par -\U47.\fi - -\M49. The first 128 strings will contain 95 standard ASCII characters, and the -other 33 characters will be printed in three-symbol form like `\.{\^\^A}' -unless a system-dependent change is made here. Installations that have -an extended character set, where for example $\\{xchr}[\O{32}]=\hbox{\.{\'^^Z% -\'}}$, -would like string \O{32} to be the single character \O{32} instead of the -three characters \O{136}, \O{136}, \O{132} (\.{\^\^Z}). On the other hand, -even people with an extended character set will want to represent string -\O{15} by \.{\^\^M}, since \O{15} is ASCII's ``carriage return'' code; the idea -is -to produce visible strings instead of tabs or line-feeds or carriage-returns -or bell-rings or characters that are treated anomalously in text files. - -Unprintable characters of codes 128--255 are, similarly, rendered -\.{\^\^80}--\.{\^\^ff}. - -The boolean expression defined here should be \\{true} unless \MF\ internal -code number~\|k corresponds to a non-troublesome visible symbol in the -local character set. -If character \|k cannot be printed, and $\|k<\O{200}$, then character $\|k+% -\O{100}$ or -$\|k-\O{100}$ must be printable; moreover, ASCII codes $[\O{60}\to\O{71},% -\O{141}\to\O{146}]$ -must be printable. - -\Y\P$\4\X49:Character \|k cannot be printed\X\S$\6 -$(\|k<\.{"\ "})\V(\|k>\.{"\~"})$\par -\U48.\fi - -\M50. When the \.{WEB} system program called \.{TANGLE} processes the % -\.{MF.WEB} -description that you are now reading, it outputs the \PASCAL\ program -\.{MF.PAS} and also a string pool file called \.{MF.POOL}. The \.{INIMF} -program reads the latter file, where each string appears as a two-digit decimal -length followed by the string itself, and the information is recorded in -\MF's string memory. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\&{init} \37\\{pool\_file}: \37\\{alpha\_file};\C{the string-pool file output -by \.{TANGLE}}\6 -\&{tini}\par -\fi - -\M51. \P\D \37$\\{bad\_pool}(\#)\S$\1\6 -\&{begin} \37\\{wake\_up\_terminal};\5 -$\\{write\_ln}(\\{term\_out},\39\#)$;\5 -$\\{a\_close}(\\{pool\_file})$;\5 -$\\{get\_strings\_started}\K\\{false}$;\5 -\&{return};\6 -\&{end}\2\par -\Y\P$\4\X51:Read the other strings from the \.{MF.POOL} file and return % -\\{true}, or give an error message and return \\{false}\X\S$\6 -$\\{name\_of\_file}\K\\{pool\_name}$;\C{we needn't set \\{name\_length}}\6 -\&{if} $\\{a\_open\_in}(\\{pool\_file})$ \1\&{then}\6 -\&{begin} \37$\|c\K\\{false}$;\6 -\1\&{repeat} \37\X52:Read one string, but return \\{false} if the string memory -space is getting too tight for comfort\X;\6 -\4\&{until}\5 -\|c;\2\6 -$\\{a\_close}(\\{pool\_file})$;\5 -$\\{get\_strings\_started}\K\\{true}$;\6 -\&{end}\6 -\4\&{else} $\\{bad\_pool}(\.{\'!\ I\ can\'}\.{\'t\ read\ MF.POOL.\'})$\2\par -\U47.\fi - -\M52. \P$\X52:Read one string, but return \\{false} if the string memory space -is getting too tight for comfort\X\S$\6 -\&{begin} \37\&{if} $\\{eof}(\\{pool\_file})$ \1\&{then}\5 -$\\{bad\_pool}(\.{\'!\ MF.POOL\ has\ no\ check\ sum.\'})$;\2\6 -$\\{read}(\\{pool\_file},\39\|m,\39\|n)$;\C{read two digits of string length}\6 -\&{if} $\|m=\.{\'*\'}$ \1\&{then}\5 -\X53:Check the pool check sum\X\6 -\4\&{else} \&{begin} \37\&{if} $(\\{xord}[\|m]<\.{"0"})\V(\\{xord}[\|m]>% -\.{"9"})\V\30(\\{xord}[\|n]<\.{"0"})\V(\\{xord}[\|n]>\.{"9"})$ \1\&{then}\5 -$\\{bad\_pool}(\.{\'!\ MF.POOL\ line\ doesn\'}\.{\'t\ begin\ with\ two\ digits.% -\'})$;\2\6 -$\|l\K\\{xord}[\|m]\ast10+\\{xord}[\|n]-\.{"0"}\ast11$;\C{compute the length}\6 -\&{if} $\\{pool\_ptr}+\|l+\\{string\_vacancies}>\\{pool\_size}$ \1\&{then}\5 -$\\{bad\_pool}(\.{\'!\ You\ have\ to\ increase\ POOLSIZE.\'})$;\2\6 -\&{for} $\|k\K1\mathrel{\&{to}}\|l$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{eoln}(\\{pool\_file})$ \1\&{then}\5 -$\|m\K\.{\'\ \'}$\ \&{else} $\\{read}(\\{pool\_file},\39\|m)$;\2\6 -$\\{append\_char}(\\{xord}[\|m])$;\6 -\&{end};\2\6 -$\\{read\_ln}(\\{pool\_file})$;\5 -$\|g\K\\{make\_string}$;\5 -$\\{str\_ref}[\|g]\K\\{max\_str\_ref}$;\6 -\&{end};\2\6 -\&{end}\par -\U51.\fi - -\M53. The \.{WEB} operation \.{@\$} denotes the value that should be at the -end of this \.{MF.POOL} file; any other value means that the wrong pool -file has been loaded. - -\Y\P$\4\X53:Check the pool check sum\X\S$\6 -\&{begin} \37$\|a\K0$;\5 -$\|k\K1$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $(\\{xord}[\|n]<\.{"0"})\V(\\{xord}[\|n]>% -\.{"9"})$ \1\&{then}\5 -$\\{bad\_pool}(\.{\'!\ MF.POOL\ check\ sum\ doesn\'}\.{\'t\ have\ nine\ digits.% -\'})$;\2\6 -$\|a\K10\ast\|a+\\{xord}[\|n]-\.{"0"}$;\6 -\&{if} $\|k=9$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{incr}(\|k)$;\5 -$\\{read}(\\{pool\_file},\39\|n)$;\6 -\&{end};\2\6 -\4\\{done}: \37\&{if} $\|a\I\)$ \1\&{then}\5 -$\\{bad\_pool}(\.{\'!\ MF.POOL\ doesn\'}\.{\'t\ match;\ TANGLE\ me\ again.% -\'})$;\2\6 -$\|c\K\\{true}$;\6 -\&{end}\par -\U52.\fi - -\N54. \[5] On-line and off-line printing. -Messages that are sent to a user's terminal and to the transcript-log file -are produced by several `\\{print}' procedures. These procedures will -direct their output to a variety of places, based on the setting of -the global variable \\{selector}, which has the following possible -values: - -\yskip -\hang \\{term\_and\_log}, the normal setting, prints on the terminal and on the -transcript file. - -\hang \\{log\_only}, prints only on the transcript file. - -\hang \\{term\_only}, prints only on the terminal. - -\hang \\{no\_print}, doesn't print at all. This is used only in rare cases -before the transcript file is open. - -\hang \\{pseudo}, puts output into a cyclic buffer that is used -by the \\{show\_context} routine; when we get to that routine we shall discuss -the reasoning behind this curious mode. - -\hang \\{new\_string}, appends the output to the current string in the -string pool. - -\yskip -\noindent The symbolic names `\\{term\_and\_log}', etc., have been assigned -numeric codes that satisfy the convenient relations $\\{no\_print}+1=\\{term% -\_only}$, -$\\{no\_print}+2=\\{log\_only}$, $\\{term\_only}+2=\\{log\_only}+1=\\{term\_and% -\_log}$. - -Three additional global variables, \\{tally} and \\{term\_offset} and -\\{file\_offset}, record the number of characters that have been printed -since they were most recently cleared to zero. We use \\{tally} to record -the length of (possibly very long) stretches of printing; \\{term\_offset} -and \\{file\_offset}, on the other hand, keep track of how many characters -have appeared so far on the current line that has been output to the -terminal or to the transcript file, respectively. - -\Y\P\D \37$\\{no\_print}=0$\C{\\{selector} setting that makes data disappear}% -\par -\P\D \37$\\{term\_only}=1$\C{printing is destined for the terminal only}\par -\P\D \37$\\{log\_only}=2$\C{printing is destined for the transcript file only}% -\par -\P\D \37$\\{term\_and\_log}=3$\C{normal \\{selector} setting}\par -\P\D \37$\\{pseudo}=4$\C{special \\{selector} setting for \\{show\_context}}\par -\P\D \37$\\{new\_string}=5$\C{printing is deflected to the string pool}\par -\P\D \37$\\{max\_selector}=5$\C{highest selector setting}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{log\_file}: \37\\{alpha\_file};\C{transcript of \MF\ session}\6 -\4\\{selector}: \37$0\to\\{max\_selector}$;\C{where to print a message}\6 -\4\\{dig}: \37\&{array} $[0\to22]$ \1\&{of}\5 -$0\to15$;\C{digits in a number being output}\2\6 -\4\\{tally}: \37\\{integer};\C{the number of characters recently printed}\6 -\4\\{term\_offset}: \37$0\to\\{max\_print\_line}$;\C{the number of characters -on the current terminal line}\6 -\4\\{file\_offset}: \37$0\to\\{max\_print\_line}$;\C{the number of characters -on the current file line}\6 -\4\\{trick\_buf}: \37\&{array} $[0\to\\{error\_line}]$ \1\&{of}\5 -\\{ASCII\_code};\C{circular buffer for pseudoprinting}\2\6 -\4\\{trick\_count}: \37\\{integer};\C{threshold for pseudoprinting, explained -later}\6 -\4\\{first\_count}: \37\\{integer};\C{another variable for pseudoprinting}\par -\fi - -\M55. \P$\X55:Initialize the output routines\X\S$\6 -$\\{selector}\K\\{term\_only}$;\5 -$\\{tally}\K0$;\5 -$\\{term\_offset}\K0$;\5 -$\\{file\_offset}\K0$;\par -\As61, 783\ETs792. -\U1204.\fi - -\M56. Macro abbreviations for output to the terminal and to the log file are -defined here for convenience. Some systems need special conventions -for terminal output, and it is possible to adhere to those conventions -by changing \\{wterm}, \\{wterm\_ln}, and \\{wterm\_cr} here. - -\Y\P\D \37$\\{wterm}(\#)\S\\{write}(\\{term\_out},\39\#)$\par -\P\D \37$\\{wterm\_ln}(\#)\S\\{write\_ln}(\\{term\_out},\39\#)$\par -\P\D \37$\\{wterm\_cr}\S\\{write\_ln}(\\{term\_out})$\par -\P\D \37$\\{wlog}(\#)\S\\{write}(\\{log\_file},\39\#)$\par -\P\D \37$\\{wlog\_ln}(\#)\S\\{write\_ln}(\\{log\_file},\39\#)$\par -\P\D \37$\\{wlog\_cr}\S\\{write\_ln}(\\{log\_file})$\par -\fi - -\M57. To end a line of text output, we call \\{print\_ln}. - -\Y\P$\4\X57:Basic printing procedures\X\S$\6 -\4\&{procedure}\1\ \37\\{print\_ln};\C{prints an end-of-line}\2\6 -\&{begin} \37\&{case} $\\{selector}$ \1\&{of}\6 -\4\\{term\_and\_log}: \37\&{begin} \37\\{wterm\_cr};\5 -\\{wlog\_cr};\5 -$\\{term\_offset}\K0$;\5 -$\\{file\_offset}\K0$;\6 -\&{end};\6 -\4\\{log\_only}: \37\&{begin} \37\\{wlog\_cr};\5 -$\\{file\_offset}\K0$;\6 -\&{end};\6 -\4\\{term\_only}: \37\&{begin} \37\\{wterm\_cr};\5 -$\\{term\_offset}\K0$;\6 -\&{end};\6 -\4$\\{no\_print},\39\\{pseudo},\39\\{new\_string}$: \37\\{do\_nothing};\2\6 -\&{end};\C{there are no other cases}\6 -\&{end};\C{note that \\{tally} is not affected}\par -\As58, 59, 60, 62, 63, 64, 103, 104, 187, 195, 197\ETs773. -\U4.\fi - -\M58. The \\{print\_char} procedure sends one character to the desired -destination, -using the \\{xchr} array to map it into an external character compatible with -\\{input\_ln}. All printing comes through \\{print\_ln} or \\{print\_char}. - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_char}(\|s:\\{ASCII\_code})$;\C{prints a -single character}\2\6 -\&{begin} \37\&{case} $\\{selector}$ \1\&{of}\6 -\4\\{term\_and\_log}: \37\&{begin} \37$\\{wterm}(\\{xchr}[\|s])$;\5 -$\\{wlog}(\\{xchr}[\|s])$;\5 -$\\{incr}(\\{term\_offset})$;\5 -$\\{incr}(\\{file\_offset})$;\6 -\&{if} $\\{term\_offset}=\\{max\_print\_line}$ \1\&{then}\6 -\&{begin} \37\\{wterm\_cr};\5 -$\\{term\_offset}\K0$;\6 -\&{end};\2\6 -\&{if} $\\{file\_offset}=\\{max\_print\_line}$ \1\&{then}\6 -\&{begin} \37\\{wlog\_cr};\5 -$\\{file\_offset}\K0$;\6 -\&{end};\2\6 -\&{end};\6 -\4\\{log\_only}: \37\&{begin} \37$\\{wlog}(\\{xchr}[\|s])$;\5 -$\\{incr}(\\{file\_offset})$;\6 -\&{if} $\\{file\_offset}=\\{max\_print\_line}$ \1\&{then}\5 -\\{print\_ln};\2\6 -\&{end};\6 -\4\\{term\_only}: \37\&{begin} \37$\\{wterm}(\\{xchr}[\|s])$;\5 -$\\{incr}(\\{term\_offset})$;\6 -\&{if} $\\{term\_offset}=\\{max\_print\_line}$ \1\&{then}\5 -\\{print\_ln};\2\6 -\&{end};\6 -\4\\{no\_print}: \37\\{do\_nothing};\6 -\4\\{pseudo}: \37\&{if} $\\{tally}<\\{trick\_count}$ \1\&{then}\5 -$\\{trick\_buf}[\\{tally}\mathbin{\&{mod}}\\{error\_line}]\K\|s$;\2\6 -\4\\{new\_string}: \37\&{begin} \37\&{if} $\\{pool\_ptr}<\\{pool\_size}$ \1% -\&{then}\5 -$\\{append\_char}(\|s)$;\2\6 -\&{end};\C{we drop characters if the string space is full}\2\6 -\&{end};\C{there are no other cases}\6 -$\\{incr}(\\{tally})$;\6 -\&{end};\par -\fi - -\M59. An entire string is output by calling \\{print}. Note that if we are -outputting -the single standard ASCII character \.c, we could call $\\{print}(\.{"c"})$, -since -$\.{"c"}=99$ is the number of a single-character string, as explained above. -But -$\\{print\_char}(\.{"c"})$ is quicker, so \MF\ goes directly to the \\{print% -\_char} -routine when it knows that this is safe. (The present implementation -assumes that it is always safe to print a visible ASCII character.) - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print}(\|s:\\{integer})$;\C{prints string \|s}\6 -\4\&{var} \37\|j: \37\\{pool\_pointer};\C{current character code position}\2\6 -\&{begin} \37\&{if} $(\|s<0)\V(\|s\G\\{str\_ptr})$ \1\&{then}\5 -$\|s\K\.{"???"}$;\C{this can't happen}\2\6 -\&{if} $(\|s<256)\W(\\{selector}>\\{pseudo})$ \1\&{then}\5 -$\\{print\_char}(\|s)$\6 -\4\&{else} \&{begin} \37$\|j\K\\{str\_start}[\|s]$;\6 -\&{while} $\|j<\\{str\_start}[\|s+1]$ \1\&{do}\6 -\&{begin} \37$\\{print\_char}(\\{so}(\\{str\_pool}[\|j]))$;\5 -$\\{incr}(\|j)$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M60. Sometimes it's necessary to print a string whose characters -may not be visible ASCII codes. In that case \\{slow\_print} is used. - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{slow\_print}(\|s:\\{integer})$;\C{prints string \|s}% -\6 -\4\&{var} \37\|j: \37\\{pool\_pointer};\C{current character code position}\2\6 -\&{begin} \37\&{if} $(\|s<0)\V(\|s\G\\{str\_ptr})$ \1\&{then}\5 -$\|s\K\.{"???"}$;\C{this can't happen}\2\6 -\&{if} $(\|s<256)\W(\\{selector}>\\{pseudo})$ \1\&{then}\5 -$\\{print\_char}(\|s)$\6 -\4\&{else} \&{begin} \37$\|j\K\\{str\_start}[\|s]$;\6 -\&{while} $\|j<\\{str\_start}[\|s+1]$ \1\&{do}\6 -\&{begin} \37$\\{print}(\\{so}(\\{str\_pool}[\|j]))$;\5 -$\\{incr}(\|j)$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M61. Here is the very first thing that \MF\ prints: a headline that identifies -the version number and base name. The \\{term\_offset} variable is temporarily -incorrect, but the discrepancy is not serious since we assume that the banner -and base identifier together will occupy at most \\{max\_print\_line} -character positions. - -\Y\P$\4\X55:Initialize the output routines\X\mathrel{+}\S$\6 -$\\{wterm}(\\{banner})$;\6 -\&{if} $\\{base\_ident}=0$ \1\&{then}\5 -$\\{wterm\_ln}(\.{\'\ (no\ base\ preloaded)\'})$\6 -\4\&{else} \&{begin} \37$\\{slow\_print}(\\{base\_ident})$;\5 -\\{print\_ln};\6 -\&{end};\2\6 -\\{update\_terminal};\par -\fi - -\M62. The procedure \\{print\_nl} is like \\{print}, but it makes sure that the -string appears at the beginning of a new line. - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_nl}(\|s:\\{str\_number})$;\C{prints string % -\|s at beginning of line}\2\6 -\&{begin} \37\&{if} $((\\{term\_offset}>0)\W(\\{odd}(\\{selector})))\V\30((% -\\{file\_offset}>0)\W(\\{selector}\G\\{log\_only}))$ \1\&{then}\5 -\\{print\_ln};\2\6 -$\\{print}(\|s)$;\6 -\&{end};\par -\fi - -\M63. An array of digits in the range $0\to9$ is printed by \\{print\_the% -\_digs}. - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_the\_digs}(\|k:\\{eight\_bits})$;\C{prints $% -\\{dig}[\|k-1]$$\,\ldots\,$$\\{dig}[0]$}\2\6 -\&{begin} \37\&{while} $\|k>0$ \1\&{do}\6 -\&{begin} \37$\\{decr}(\|k)$;\5 -$\\{print\_char}(\.{"0"}+\\{dig}[\|k])$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M64. The following procedure, which prints out the decimal representation of a -given integer \|n, has been written carefully so that it works properly -if $\|n=0$ or if $(-\|n)$ would cause overflow. It does not apply $\mathbin{% -\&{mod}}$ or $\mathbin{\&{div}}$ -to negative arguments, since such operations are not implemented consistently -by all \PASCAL\ compilers. - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_int}(\|n:\\{integer})$;\C{prints an integer -in decimal form}\6 -\4\&{var} \37\|k: \37$0\to23$;\C{index to current digit; we assume that $% -\|n<10^{23}$}\6 -\|m: \37\\{integer};\C{used to negate \|n in possibly dangerous cases}\2\6 -\&{begin} \37$\|k\K0$;\6 -\&{if} $\|n<0$ \1\&{then}\6 -\&{begin} \37$\\{print\_char}(\.{"-"})$;\6 -\&{if} $\|n>-100000000$ \1\&{then}\5 -$\\{negate}(\|n)$\6 -\4\&{else} \&{begin} \37$\|m\K-1-\|n$;\5 -$\|n\K\|m\mathbin{\&{div}}10$;\5 -$\|m\K(\|m\mathbin{\&{mod}}10)+1$;\5 -$\|k\K1$;\6 -\&{if} $\|m<10$ \1\&{then}\5 -$\\{dig}[0]\K\|m$\6 -\4\&{else} \&{begin} \37$\\{dig}[0]\K0$;\5 -$\\{incr}(\|n)$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\2\6 -\1\&{repeat} \37$\\{dig}[\|k]\K\|n\mathbin{\&{mod}}10$;\5 -$\|n\K\|n\mathbin{\&{div}}10$;\5 -$\\{incr}(\|k)$;\6 -\4\&{until}\5 -$\|n=0$;\2\6 -$\\{print\_the\_digs}(\|k)$;\6 -\&{end};\par -\fi - -\M65. \MF\ also makes use of a trivial procedure to print two digits. The -following subroutine is usually called with a parameter in the range $0\L\|n% -\L99$. - -\Y\P\4\&{procedure}\1\ \37$\\{print\_dd}(\|n:\\{integer})$;\C{prints two least -significant digits}\2\6 -\&{begin} \37$\|n\K\\{abs}(\|n)\mathbin{\&{mod}}100$;\5 -$\\{print\_char}(\.{"0"}+(\|n\mathbin{\&{div}}10))$;\5 -$\\{print\_char}(\.{"0"}+(\|n\mathbin{\&{mod}}10))$;\6 -\&{end};\par -\fi - -\M66. Here is a procedure that asks the user to type a line of input, -assuming that the \\{selector} setting is either \\{term\_only} or \\{term\_and% -\_log}. -The input is placed into locations \\{first} through $\\{last}-1$ of the -\\{buffer} array, and echoed on the transcript file if appropriate. - -This procedure is never called when $\\{interaction}<\\{scroll\_mode}$. - -\Y\P\D \37$\\{prompt\_input}(\#)\S$\1\6 -\&{begin} \37\\{wake\_up\_terminal};\5 -$\\{print}(\#)$;\5 -\\{term\_input};\6 -\&{end}\C{prints a string and gets a line of input}\2\par -\Y\P\4\&{procedure}\1\ \37\\{term\_input};\C{gets a line from the terminal}\6 -\4\&{var} \37\|k: \37$0\to\\{buf\_size}$;\C{index into \\{buffer}}\2\6 -\&{begin} \37\\{update\_terminal};\C{now the user sees the prompt for sure}\6 -\&{if} $\R\\{input\_ln}(\\{term\_in},\39\\{true})$ \1\&{then}\5 -$\\{fatal\_error}(\.{"End\ of\ file\ on\ the\ terminal!"})$;\2\6 -$\\{term\_offset}\K0$;\C{the user's line ended with \<\rm return>}\6 -$\\{decr}(\\{selector})$;\C{prepare to echo the input}\6 -\&{if} $\\{last}\I\\{first}$ \1\&{then}\6 -\&{for} $\|k\K\\{first}\mathrel{\&{to}}\\{last}-1$ \1\&{do}\5 -$\\{print}(\\{buffer}[\|k])$;\2\2\6 -\\{print\_ln};\5 -$\\{buffer}[\\{last}]\K\.{"\%"}$;\5 -$\\{incr}(\\{selector})$;\C{restore previous status}\6 -\&{end};\par -\fi - -\N67. \[6] Reporting errors. -When something anomalous is detected, \MF\ typically does something like this: -$$\vbox{\halign{#\hfil\cr -$\\{print\_err}(\.{"Something\ anomalous\ has\ been\ detected"})$;\cr -$\\{help3}(\.{"This\ is\ the\ first\ line\ of\ my\ offer\ to\ help."})$\cr -$(\.{"This\ is\ the\ second\ line.\ I\'m\ trying\ to"})$\cr -$(\.{"explain\ the\ best\ way\ for\ you\ to\ proceed."})$;\cr -\\{error};\cr}}$$ -A two-line help message would be given using \\{help2}, etc.; these informal -helps should use simple vocabulary that complements the words used in the -official error message that was printed. (Outside the U.S.A., the help -messages should preferably be translated into the local vernacular. Each -line of help is at most 60 characters long, in the present implementation, -so that \\{max\_print\_line} will not be exceeded.) - -The \\{print\_err} procedure supplies a `\.!' before the official message, -and makes sure that the terminal is awake if a stop is going to occur. -The \\{error} procedure supplies a `\..' after the official message, then it -shows the location of the error; and if $\\{interaction}=\\{error\_stop% -\_mode}$, -it also enters into a dialog with the user, during which time the help -message may be printed. - -\fi - -\M68. The global variable \\{interaction} has four settings, representing -increasing -amounts of user interaction: - -\Y\P\D \37$\\{batch\_mode}=0$\C{omits all stops and omits terminal output}\par -\P\D \37$\\{nonstop\_mode}=1$\C{omits all stops}\par -\P\D \37$\\{scroll\_mode}=2$\C{omits error stops}\par -\P\D \37$\\{error\_stop\_mode}=3$\C{stops at every opportunity to interact}\par -\P\D \37$\\{print\_err}(\#)\S$\1\6 -\&{begin} \37\&{if} $\\{interaction}=\\{error\_stop\_mode}$ \1\&{then}\5 -\\{wake\_up\_terminal};\2\6 -$\\{print\_nl}(\.{"!\ "})$;\5 -$\\{print}(\#)$;\6 -\&{end}\2\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{interaction}: \37$\\{batch\_mode}\to\\{error\_stop\_mode}$;\C{current -level of interaction}\par -\fi - -\M69. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{interaction}\K\\{error\_stop\_mode}$;\par -\fi - -\M70. \MF\ is careful not to call \\{error} when the print \\{selector} setting -might be unusual. The only possible values of \\{selector} at the time of -error messages are - -\yskip\hang\\{no\_print} (when $\\{interaction}=\\{batch\_mode}$ -and \\{log\_file} not yet open); - -\hang\\{term\_only} (when $\\{interaction}>\\{batch\_mode}$ and \\{log\_file} -not yet open); - -\hang\\{log\_only} (when $\\{interaction}=\\{batch\_mode}$ and \\{log\_file} is -open); - -\hang\\{term\_and\_log} (when $\\{interaction}>\\{batch\_mode}$ and \\{log% -\_file} is open). - -\Y\P$\4\X70:Initialize the print \\{selector} based on \\{interaction}\X\S$\6 -\&{if} $\\{interaction}=\\{batch\_mode}$ \1\&{then}\5 -$\\{selector}\K\\{no\_print}$\ \&{else} $\\{selector}\K\\{term\_only}$\2\par -\Us1023\ET1211.\fi - -\M71. A global variable \\{deletions\_allowed} is set \\{false} if the \\{get% -\_next} -routine is active when \\{error} is called; this ensures that \\{get\_next} -will never be called recursively. - -The global variable \\{history} records the worst level of error that -has been detected. It has four possible values: \\{spotless}, \\{warning% -\_issued}, -\\{error\_message\_issued}, and \\{fatal\_error\_stop}. - -Another global variable, \\{error\_count}, is increased by one when an -\\{error} occurs without an interactive dialog, and it is reset to zero at -the end of every statement. If \\{error\_count} reaches 100, \MF\ decides -that there is no point in continuing further. - -\Y\P\D \37$\\{spotless}=0$\C{\\{history} value when nothing has been amiss yet}% -\par -\P\D \37$\\{warning\_issued}=1$\C{\\{history} value when \\{begin\_diagnostic} -has been called}\par -\P\D \37$\\{error\_message\_issued}=2$\C{\\{history} value when \\{error} has -been called}\par -\P\D \37$\\{fatal\_error\_stop}=3$\C{\\{history} value when termination was -premature}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{deletions\_allowed}: \37\\{boolean};\C{is it safe for \\{error} to call % -\\{get\_next}?}\6 -\4\\{history}: \37$\\{spotless}\to\\{fatal\_error\_stop}$;\C{has the source -input been clean so far?}\6 -\4\\{error\_count}: \37$-1\to100$;\C{the number of scrolled errors since the -last statement ended}\par -\fi - -\M72. The value of \\{history} is initially \\{fatal\_error\_stop}, but it will -be changed to \\{spotless} if \MF\ survives the initialization process. - -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{deletions\_allowed}\K\\{true}$;\5 -$\\{error\_count}\K0$;\C{\\{history} is initialized elsewhere}\par -\fi - -\M73. Since errors can be detected almost anywhere in \MF, we want to declare -the -error procedures near the beginning of the program. But the error procedures -in turn use some other procedures, which need to be declared \\{forward} -before we get to \\{error} itself. - -It is possible for \\{error} to be called recursively if some error arises -when \\{get\_next} is being used to delete a token, and/or if some fatal error -occurs while \MF\ is trying to fix a non-fatal one. But such recursion -is never more than two levels deep. - -\Y\P$\4\X73:Error handling procedures\X\S$\6 -\4\&{procedure}\1\ \37\\{normalize\_selector};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{get\_next};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{term\_input};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{show\_context};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{begin\_file\_reading};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{open\_log\_file};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{close\_files\_and\_terminate};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{clear\_for\_error\_prompt};\5 -\\{forward};\5 -\hbox{\2}\6 -\hbox{\4\hskip-\fontdimen2\font}\ \&{debug} \37\ \&{procedure}\1\ \37\\{debug% -\_help};\5 -\\{forward};\ \&{gubed} \6 -\hbox{\4}\X43:Declare the procedure called \\{flush\_string}\X\par -\As76, 77, 88, 89\ETs90. -\U4.\fi - -\M74. Individual lines of help are recorded in the array \\{help\_line}, which -contains entries in positions $0\to(\\{help\_ptr}-1)$. They should be printed -in reverse order, i.e., with $\\{help\_line}[0]$ appearing last. - -\Y\P\D \37$\\{hlp1}(\#)\S\\{help\_line}[0]\K\#$;\ \&{end} \par -\P\D \37$\\{hlp2}(\#)\S\\{help\_line}[1]\K\#$;\5 -\\{hlp1}\par -\P\D \37$\\{hlp3}(\#)\S\\{help\_line}[2]\K\#$;\5 -\\{hlp2}\par -\P\D \37$\\{hlp4}(\#)\S\\{help\_line}[3]\K\#$;\5 -\\{hlp3}\par -\P\D \37$\\{hlp5}(\#)\S\\{help\_line}[4]\K\#$;\5 -\\{hlp4}\par -\P\D \37$\\{hlp6}(\#)\S\\{help\_line}[5]\K\#$;\5 -\\{hlp5}\par -\P\D \37$\\{help0}\S\\{help\_ptr}\K0$\C{sometimes there might be no help}\par -\P\D \37$\\{help1}\S$\ \&{begin} \37$\\{help\_ptr}\K1$;\5 -\\{hlp1}\C{use this with one help line}\par -\P\D \37$\\{help2}\S$\ \&{begin} \37$\\{help\_ptr}\K2$;\5 -\\{hlp2}\C{use this with two help lines}\par -\P\D \37$\\{help3}\S$\ \&{begin} \37$\\{help\_ptr}\K3$;\5 -\\{hlp3}\C{use this with three help lines}\par -\P\D \37$\\{help4}\S$\ \&{begin} \37$\\{help\_ptr}\K4$;\5 -\\{hlp4}\C{use this with four help lines}\par -\P\D \37$\\{help5}\S$\ \&{begin} \37$\\{help\_ptr}\K5$;\5 -\\{hlp5}\C{use this with five help lines}\par -\P\D \37$\\{help6}\S$\ \&{begin} \37$\\{help\_ptr}\K6$;\5 -\\{hlp6}\C{use this with six help lines}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{help\_line}: \37\&{array} $[0\to5]$ \1\&{of}\5 -\\{str\_number};\C{helps for the next \\{error}}\2\6 -\4\\{help\_ptr}: \37$0\to6$;\C{the number of help lines present}\6 -\4\\{use\_err\_help}: \37\\{boolean};\C{should the \\{err\_help} string be -shown?}\6 -\4\\{err\_help}: \37\\{str\_number};\C{a string set up by \&{errhelp}}\par -\fi - -\M75. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{help\_ptr}\K0$;\5 -$\\{use\_err\_help}\K\\{false}$;\5 -$\\{err\_help}\K0$;\par -\fi - -\M76. The \\{jump\_out} procedure just cuts across all active procedure levels -and -goes to \\{end\_of\_MF}. This is the only nontrivial \&{goto} statement in the -whole program. It is used when there is no recovery from a particular error. - -Some \PASCAL\ compilers do not implement non-local \&{goto} statements. -In such cases the body of \\{jump\_out} should simply be -`\\{close\_files\_and\_terminate};\thinspace' followed by a call on some system -procedure that quietly terminates the program. - -\Y\P$\4\X73:Error handling procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{jump\_out};\2\6 -\&{begin} \37\&{goto} \37\\{end\_of\_MF};\6 -\&{end};\par -\fi - -\M77. Here now is the general \\{error} routine. - -\Y\P$\4\X73:Error handling procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{error};\C{completes the job of error reporting}\6 -\4\&{label} \37$\\{continue},\39\\{exit}$;\6 -\4\&{var} \37\|c: \37\\{ASCII\_code};\C{what the user types}\6 -$\\{s1},\39\\{s2},\39\\{s3}$: \37\\{integer};\C{used to save global variables -when deleting tokens}\6 -\|j: \37\\{pool\_pointer};\C{character position being printed}\2\6 -\&{begin} \37\&{if} $\\{history}<\\{error\_message\_issued}$ \1\&{then}\5 -$\\{history}\K\\{error\_message\_issued}$;\2\6 -$\\{print\_char}(\.{"."})$;\5 -\\{show\_context};\6 -\&{if} $\\{interaction}=\\{error\_stop\_mode}$ \1\&{then}\5 -\X78:Get user's advice and \&{return}\X;\2\6 -$\\{incr}(\\{error\_count})$;\6 -\&{if} $\\{error\_count}=100$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"(That\ makes\ 100\ errors;\ please\ try\ -again.)"})$;\5 -$\\{history}\K\\{fatal\_error\_stop}$;\5 -\\{jump\_out};\6 -\&{end};\2\6 -\X86:Put help message on the transcript file\X;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M78. \P$\X78:Get user's advice and \&{return}\X\S$\6 -\~ \1\&{loop}\ \&{begin} \37\\{continue}: \37\\{clear\_for\_error\_prompt};\5 -$\\{prompt\_input}(\.{"?\ "})$;\6 -\&{if} $\\{last}=\\{first}$ \1\&{then}\5 -\&{return};\2\6 -$\|c\K\\{buffer}[\\{first}]$;\6 -\&{if} $\|c\G\.{"a"}$ \1\&{then}\5 -$\|c\K\|c+\.{"A"}-\.{"a"}$;\C{convert to uppercase}\2\6 -\X79:Interpret code \|c and \&{return} if done\X;\6 -\&{end}\2\par -\U77.\fi - -\M79. It is desirable to provide an `\.E' option here that gives the user -an easy way to return from \MF\ to the system editor, with the offending -line ready to be edited. But such an extension requires some system -wizardry, so the present implementation simply types out the name of the -file that should be -edited and the relevant line number. - -There is a secret `\.D' option available when the debugging routines haven't -been commented~out. - -\Y\P$\4\X79:Interpret code \|c and \&{return} if done\X\S$\6 -\&{case} $\|c$ \1\&{of}\6 -\4$\.{"0"},\39\.{"1"},\39\.{"2"},\39\.{"3"},\39\.{"4"},\39\.{"5"},\39\.{"6"},% -\39\.{"7"},\39\.{"8"},\39\.{"9"}$: \37\&{if} $\\{deletions\_allowed}$ \1% -\&{then}\5 -\X83:Delete $\|c-\.{"0"}$ tokens and \&{goto} \\{continue}\X;\2\6 -\hbox{\4\4}\ \&{debug} \37\.{"D"}: \37\&{begin} \37\\{debug\_help};\5 -\&{goto} \37\\{continue};\ \&{end};\ \&{gubed}\6 -\4\.{"E"}: \37\&{if} $\\{file\_ptr}>0$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"You\ want\ to\ edit\ file\ "})$;\5 -$\\{slow\_print}(\\{input\_stack}[\\{file\_ptr}].\\{name\_field})$;\5 -$\\{print}(\.{"\ at\ line\ "})$;\5 -$\\{print\_int}(\\{line})$;\6 -$\\{interaction}\K\\{scroll\_mode}$;\5 -\\{jump\_out};\6 -\&{end};\2\6 -\4\.{"H"}: \37\X84:Print the help information and \&{goto} \\{continue}\X;\6 -\4\.{"I"}: \37\X82:Introduce new material from the terminal and \&{return}\X;\6 -\4$\.{"Q"},\39\.{"R"},\39\.{"S"}$: \37\X81:Change the interaction level and % -\&{return}\X;\6 -\4\.{"X"}: \37\&{begin} \37$\\{interaction}\K\\{scroll\_mode}$;\5 -\\{jump\_out};\6 -\&{end};\6 -\4\&{othercases} \37\\{do\_nothing}\2\6 -\&{endcases};\6 -\X80:Print the menu of available options\X\par -\U78.\fi - -\M80. \P$\X80:Print the menu of available options\X\S$\6 -\&{begin} \37$\\{print}(\.{"Type\ <return>\ to\ proceed,\ S\ to\ scroll\ future% -\ error\ messages,"})$;\6 -$\\{print\_nl}(\.{"R\ to\ run\ without\ stopping,\ Q\ to\ run\ quietly,"})$;\6 -$\\{print\_nl}(\.{"I\ to\ insert\ something,\ "})$;\6 -\&{if} $\\{file\_ptr}>0$ \1\&{then}\5 -$\\{print}(\.{"E\ to\ edit\ your\ file,"})$;\2\6 -\&{if} $\\{deletions\_allowed}$ \1\&{then}\5 -$\\{print\_nl}(\.{"1\ or\ ...\ or\ 9\ to\ ignore\ the\ next\ 1\ to\ 9\ tokens\ -of\ input,"})$;\2\6 -$\\{print\_nl}(\.{"H\ for\ help,\ X\ to\ quit."})$;\6 -\&{end}\par -\U79.\fi - -\M81. Here the author of \MF\ apologizes for making use of the numerical -relation between \.{"Q"}, \.{"R"}, \.{"S"}, and the desired interaction -settings -\\{batch\_mode}, \\{nonstop\_mode}, \\{scroll\_mode}. - -\Y\P$\4\X81:Change the interaction level and \&{return}\X\S$\6 -\&{begin} \37$\\{error\_count}\K0$;\5 -$\\{interaction}\K\\{batch\_mode}+\|c-\.{"Q"}$;\5 -$\\{print}(\.{"OK,\ entering\ "})$;\6 -\&{case} $\|c$ \1\&{of}\6 -\4\.{"Q"}: \37\&{begin} \37$\\{print}(\.{"batchmode"})$;\5 -$\\{decr}(\\{selector})$;\6 -\&{end};\6 -\4\.{"R"}: \37$\\{print}(\.{"nonstopmode"})$;\6 -\4\.{"S"}: \37$\\{print}(\.{"scrollmode"})$;\2\6 -\&{end};\C{there are no other cases}\6 -$\\{print}(\.{"..."})$;\5 -\\{print\_ln};\5 -\\{update\_terminal};\5 -\&{return};\6 -\&{end}\par -\U79.\fi - -\M82. When the following code is executed, $\\{buffer}[(\\{first}+1)\to(% -\\{last}-1)]$ may -contain the material inserted by the user; otherwise another prompt will -be given. In order to understand this part of the program fully, you need -to be familiar with \MF's input stacks. - -\Y\P$\4\X82:Introduce new material from the terminal and \&{return}\X\S$\6 -\&{begin} \37\\{begin\_file\_reading};\C{enter a new syntactic level for -terminal input}\6 -\&{if} $\\{last}>\\{first}+1$ \1\&{then}\6 -\&{begin} \37$\\{loc}\K\\{first}+1$;\5 -$\\{buffer}[\\{first}]\K\.{"\ "}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{prompt\_input}(\.{"insert>"})$;\5 -$\\{loc}\K\\{first}$;\6 -\&{end};\2\6 -$\\{first}\K\\{last}+1$;\5 -$\\{cur\_input}.\\{limit\_field}\K\\{last}$;\5 -\&{return};\6 -\&{end}\par -\U79.\fi - -\M83. We allow deletion of up to 99 tokens at a time. - -\Y\P$\4\X83:Delete $\|c-\.{"0"}$ tokens and \&{goto} \\{continue}\X\S$\6 -\&{begin} \37$\\{s1}\K\\{cur\_cmd}$;\5 -$\\{s2}\K\\{cur\_mod}$;\5 -$\\{s3}\K\\{cur\_sym}$;\5 -$\\{OK\_to\_interrupt}\K\\{false}$;\6 -\&{if} $(\\{last}>\\{first}+1)\W(\\{buffer}[\\{first}+1]\G\.{"0"})\W(% -\\{buffer}[\\{first}+1]\L\.{"9"})$ \1\&{then}\5 -$\|c\K\|c\ast10+\\{buffer}[\\{first}+1]-\.{"0"}\ast11$\6 -\4\&{else} $\|c\K\|c-\.{"0"}$;\2\6 -\&{while} $\|c>0$ \1\&{do}\6 -\&{begin} \37\\{get\_next};\C{one-level recursive call of \\{error} is -possible}\6 -\X743:Decrease the string reference count, if the current token is a string\X;\6 -$\\{decr}(\|c)$;\6 -\&{end};\2\6 -$\\{cur\_cmd}\K\\{s1}$;\5 -$\\{cur\_mod}\K\\{s2}$;\5 -$\\{cur\_sym}\K\\{s3}$;\5 -$\\{OK\_to\_interrupt}\K\\{true}$;\5 -$\\{help2}(\.{"I\ have\ just\ deleted\ some\ text,\ as\ you\ asked."})$\6 -$(\.{"You\ can\ now\ delete\ more,\ or\ insert,\ or\ whatever."})$;\5 -\\{show\_context};\5 -\&{goto} \37\\{continue};\6 -\&{end}\par -\U79.\fi - -\M84. \P$\X84:Print the help information and \&{goto} \\{continue}\X\S$\6 -\&{begin} \37\&{if} $\\{use\_err\_help}$ \1\&{then}\6 -\&{begin} \37\X85:Print the string \\{err\_help}, possibly on several lines\X;\6 -$\\{use\_err\_help}\K\\{false}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{help\_ptr}=0$ \1\&{then}\5 -$\\{help2}(\.{"Sorry,\ I\ don\'t\ know\ how\ to\ help\ in\ this\ situation."})$% -\2\6 -$\hbox{\kern1em}(\.{"Maybe\ you\ should\ try\ asking\ a\ human?"})$;\6 -\1\&{repeat} \37$\\{decr}(\\{help\_ptr})$;\5 -$\\{print}(\\{help\_line}[\\{help\_ptr}])$;\5 -\\{print\_ln};\6 -\4\&{until}\5 -$\\{help\_ptr}=0$;\2\6 -\&{end};\2\6 -$\\{help4}(\.{"Sorry,\ I\ already\ gave\ what\ help\ I\ could..."})$\6 -$(\.{"Maybe\ you\ should\ try\ asking\ a\ human?"})$\6 -$(\.{"An\ error\ might\ have\ occurred\ before\ I\ noticed\ any\ problems."})$\6 -$(\.{"\`\`If\ all\ else\ fails,\ read\ the\ instructions.\'\'"})$;\6 -\&{goto} \37\\{continue};\6 -\&{end}\par -\U79.\fi - -\M85. \P$\X85:Print the string \\{err\_help}, possibly on several lines\X\S$\6 -$\|j\K\\{str\_start}[\\{err\_help}]$;\6 -\&{while} $\|j<\\{str\_start}[\\{err\_help}+1]$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{str\_pool}[\|j]\I\\{si}(\.{"\%"})$ \1\&{then}\5 -$\\{print}(\\{so}(\\{str\_pool}[\|j]))$\6 -\4\&{else} \&{if} $\|j+1=\\{str\_start}[\\{err\_help}+1]$ \1\&{then}\5 -\\{print\_ln}\6 -\4\&{else} \&{if} $\\{str\_pool}[\|j+1]\I\\{si}(\.{"\%"})$ \1\&{then}\5 -\\{print\_ln}\6 -\4\&{else} \&{begin} \37$\\{incr}(\|j)$;\5 -$\\{print\_char}(\.{"\%"})$;\6 -\&{end};\2\2\2\6 -$\\{incr}(\|j)$;\6 -\&{end}\2\par -\Us84\ET86.\fi - -\M86. \P$\X86:Put help message on the transcript file\X\S$\6 -\&{if} $\\{interaction}>\\{batch\_mode}$ \1\&{then}\5 -$\\{decr}(\\{selector})$;\C{avoid terminal output}\2\6 -\&{if} $\\{use\_err\_help}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{""})$;\5 -\X85:Print the string \\{err\_help}, possibly on several lines\X;\6 -\&{end}\6 -\4\&{else} \&{while} $\\{help\_ptr}>0$ \1\&{do}\6 -\&{begin} \37$\\{decr}(\\{help\_ptr})$;\5 -$\\{print\_nl}(\\{help\_line}[\\{help\_ptr}])$;\6 -\&{end};\2\2\6 -\\{print\_ln};\6 -\&{if} $\\{interaction}>\\{batch\_mode}$ \1\&{then}\5 -$\\{incr}(\\{selector})$;\C{re-enable terminal output}\2\6 -\\{print\_ln}\par -\U77.\fi - -\M87. In anomalous cases, the print selector might be in an unknown state; -the following subroutine is called to fix things just enough to keep -running a bit longer. - -\Y\P\4\&{procedure}\1\ \37\\{normalize\_selector};\2\6 -\&{begin} \37\&{if} $\\{log\_opened}$ \1\&{then}\5 -$\\{selector}\K\\{term\_and\_log}$\6 -\4\&{else} $\\{selector}\K\\{term\_only}$;\2\6 -\&{if} $\\{job\_name}=0$ \1\&{then}\5 -\\{open\_log\_file};\2\6 -\&{if} $\\{interaction}=\\{batch\_mode}$ \1\&{then}\5 -$\\{decr}(\\{selector})$;\2\6 -\&{end};\par -\fi - -\M88. The following procedure prints \MF's last words before dying. - -\Y\P\D \37$\\{succumb}\S$\1\6 -\&{begin} \37\&{if} $\\{interaction}=\\{error\_stop\_mode}$ \1\&{then}\5 -$\\{interaction}\K\\{scroll\_mode}$;\C{no more interaction}\2\6 -\&{if} $\\{log\_opened}$ \1\&{then}\5 -\\{error};\2\6 -\&{debug} \37\&{if} $\\{interaction}>\\{batch\_mode}$ \1\&{then}\5 -\\{debug\_help};\2\ \&{gubed}\6 -$\\{history}\K\\{fatal\_error\_stop}$;\5 -\\{jump\_out};\C{irrecoverable error}\6 -\&{end}\2\par -\Y\P$\4\X73:Error handling procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{fatal\_error}(\|s:\\{str\_number})$;\C{prints \|s, -and that's it}\2\6 -\&{begin} \37\\{normalize\_selector};\6 -$\\{print\_err}(\.{"Emergency\ stop"})$;\5 -$\\{help1}(\|s)$;\5 -\\{succumb};\6 -\&{end};\par -\fi - -\M89. Here is the most dreaded error message. - -\Y\P$\4\X73:Error handling procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{overflow}(\|s:\\{str\_number};\,\35\|n:% -\\{integer})$;\C{stop due to finiteness}\2\6 -\&{begin} \37\\{normalize\_selector};\5 -$\\{print\_err}(\.{"METAFONT\ capacity\ exceeded,\ sorry\ ["})$;\5 -$\\{print}(\|s)$;\5 -$\\{print\_char}(\.{"="})$;\5 -$\\{print\_int}(\|n)$;\5 -$\\{print\_char}(\.{"]"})$;\5 -$\\{help2}(\.{"If\ you\ really\ absolutely\ need\ more\ capacity,"})$\6 -$(\.{"you\ can\ ask\ a\ wizard\ to\ enlarge\ me."})$;\5 -\\{succumb};\6 -\&{end};\par -\fi - -\M90. The program might sometime run completely amok, at which point there is -no choice but to stop. If no previous error has been detected, that's bad -news; a message is printed that is really intended for the \MF\ -maintenance person instead of the user (unless the user has been -particularly diabolical). The index entries for `this can't happen' may -help to pinpoint the problem. - -\Y\P$\4\X73:Error handling procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{confusion}(\|s:\\{str\_number})$;\C{consistency -check violated; \|s tells where}\2\6 -\&{begin} \37\\{normalize\_selector};\6 -\&{if} $\\{history}<\\{error\_message\_issued}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"This\ can\'t\ happen\ ("})$;\5 -$\\{print}(\|s)$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\\{help1}(\.{"I\'m\ broken.\ Please\ show\ this\ to\ someone\ who\ can\ fix\ -can\ fix"})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"I\ can\'t\ go\ on\ meeting\ you\ -like\ this"})$;\5 -$\\{help2}(\.{"One\ of\ your\ faux\ pas\ seems\ to\ have\ wounded\ me\ -deeply..."})$\6 -$(\.{"in\ fact,\ I\'m\ barely\ conscious.\ Please\ fix\ it\ and\ try\ -again."})$;\6 -\&{end};\2\6 -\\{succumb};\6 -\&{end};\par -\fi - -\M91. Users occasionally want to interrupt \MF\ while it's running. -If the \PASCAL\ runtime system allows this, one can implement -a routine that sets the global variable \\{interrupt} to some nonzero value -when such an interrupt is signalled. Otherwise there is probably at least -a way to make \\{interrupt} nonzero using the \PASCAL\ debugger. - -\Y\P\D \37$\\{check\_interrupt}\S$\1\6 -\&{begin} \37\&{if} $\\{interrupt}\I0$ \1\&{then}\5 -\\{pause\_for\_instructions};\2\6 -\&{end}\2\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{interrupt}: \37\\{integer};\C{should \MF\ pause for instructions?}\6 -\4\\{OK\_to\_interrupt}: \37\\{boolean};\C{should interrupts be observed?}\par -\fi - -\M92. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{interrupt}\K0$;\5 -$\\{OK\_to\_interrupt}\K\\{true}$;\par -\fi - -\M93. When an interrupt has been detected, the program goes into its -highest interaction level and lets the user have the full flexibility of -the \\{error} routine. \MF\ checks for interrupts only at times when it is -safe to do this. - -\Y\P\4\&{procedure}\1\ \37\\{pause\_for\_instructions};\2\6 -\&{begin} \37\&{if} $\\{OK\_to\_interrupt}$ \1\&{then}\6 -\&{begin} \37$\\{interaction}\K\\{error\_stop\_mode}$;\6 -\&{if} $(\\{selector}=\\{log\_only})\V(\\{selector}=\\{no\_print})$ \1\&{then}\5 -$\\{incr}(\\{selector})$;\2\6 -$\\{print\_err}(\.{"Interruption"})$;\5 -$\\{help3}(\.{"You\ rang?"})$\6 -$(\.{"Try\ to\ insert\ some\ instructions\ for\ me\ (e.g.,\`I\ show\ x\'),"})$\6 -$(\.{"unless\ you\ just\ want\ to\ quit\ by\ typing\ \`X\'."})$;\5 -$\\{deletions\_allowed}\K\\{false}$;\5 -\\{error};\5 -$\\{deletions\_allowed}\K\\{true}$;\5 -$\\{interrupt}\K0$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M94. Many of \MF's error messages state that a missing token has been -inserted behind the scenes. We can save string space and program space -by putting this common code into a subroutine. - -\Y\P\4\&{procedure}\1\ \37$\\{missing\_err}(\|s:\\{str\_number})$;\2\6 -\&{begin} \37$\\{print\_err}(\.{"Missing\ \`"})$;\5 -$\\{print}(\|s)$;\5 -$\\{print}(\.{"\'\ has\ been\ inserted"})$;\6 -\&{end};\par -\fi - -\N95. \[7] Arithmetic with scaled numbers. -The principal computations performed by \MF\ are done entirely in terms of -integers less than $2^{31}$ in magnitude; thus, the arithmetic specified in -this -program can be carried out in exactly the same way on a wide variety of -computers, including some small ones. - -But \PASCAL\ does not define the $\mathbin{\&{div}}$ -operation in the case of negative dividends; for example, the result of -$(-2\ast\|n-1)\mathbin{\&{div}}2$ is $-(\|n+1)$ on some computers and $-\|n$ on -others. -There are two principal types of arithmetic: ``translation-preserving,'' -in which the identity $(\|a+\|q\ast\|b)\mathbin{\&{div}}\|b=(\|a\mathbin{% -\&{div}}\|b)+\|q$ is valid; and -``negation-preserving,'' in which $(-\|a)\mathbin{\&{div}}\|b=-(\|a\mathbin{% -\&{div}}\|b)$. This leads to -two \MF s, which can produce different results, although the differences -should be negligible when the language is being used properly. -The \TeX\ processor has been defined carefully so that both varieties -of arithmetic will produce identical output, but it would be too -inefficient to constrain \MF\ in a similar way. - -\Y\P\D \37$\\{el\_gordo}\S\O{17777777777}$\C{$2^{31}-1$, the largest value that -\MF\ likes}\par -\fi - -\M96. One of \MF's most common operations is the calculation of -$\lfloor{a+b\over2}\rfloor$, -the midpoint of two given integers \|a and~\|b. The only decent way to do -this in \PASCAL\ is to write `$(\|a+\|b)\mathbin{\&{div}}2$'; but on most -machines it is -far more efficient to calculate `$(\|a+\|b)$ right shifted one bit'. - -Therefore the midpoint operation will always be denoted by `$\\{half}(\|a+% -\|b)$' -in this program. If \MF\ is being implemented with languages that permit -binary shifting, the \\{half} macro should be changed to make this operation -as efficient as possible. - -\Y\P\D \37$\\{half}(\#)\S(\#)\mathbin{\&{div}}2$\par -\fi - -\M97. A single computation might use several subroutine calls, and it is -desirable to avoid producing multiple error messages in case of arithmetic -overflow. So the routines below set the global variable \\{arith\_error} to % -\\{true} -instead of reporting errors directly to the user. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{arith\_error}: \37\\{boolean};\C{has arithmetic overflow occurred -recently?}\par -\fi - -\M98. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{arith\_error}\K\\{false}$;\par -\fi - -\M99. At crucial points the program will say \\{check\_arith}, to test if -an arithmetic error has been detected. - -\Y\P\D \37$\\{check\_arith}\S$\1\6 -\&{begin} \37\&{if} $\\{arith\_error}$ \1\&{then}\5 -\\{clear\_arith};\ \2\6 -\&{end}\2\par -\Y\P\4\&{procedure}\1\ \37\\{clear\_arith};\2\6 -\&{begin} \37$\\{print\_err}(\.{"Arithmetic\ overflow"})$;\5 -$\\{help4}(\.{"Uh,\ oh.\ A\ little\ while\ ago\ one\ of\ the\ quantities\ that\ -I\ was"})$\6 -$(\.{"computing\ got\ too\ large,\ so\ I\'m\ afraid\ your\ answers\ will\ -be"})$\6 -$(\.{"somewhat\ askew.\ You\'ll\ probably\ have\ to\ adopt\ different"})$\6 -$(\.{"tactics\ next\ time.\ But\ I\ shall\ try\ to\ carry\ on\ anyway."})$;\5 -\\{error};\5 -$\\{arith\_error}\K\\{false}$;\6 -\&{end};\par -\fi - -\M100. Addition is not always checked to make sure that it doesn't overflow, -but in places where overflow isn't too unlikely the \\{slow\_add} routine -is used. - -\Y\P\4\&{function}\1\ \37$\\{slow\_add}(\|x,\39\|y:\\{integer})$: \37% -\\{integer};\2\6 -\&{begin} \37\&{if} $\|x\G0$ \1\&{then}\6 -\&{if} $\|y\L\\{el\_gordo}-\|x$ \1\&{then}\5 -$\\{slow\_add}\K\|x+\|y$\6 -\4\&{else} \&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\\{slow\_add}\K\\{el\_gordo}$;\6 -\&{end}\2\6 -\4\&{else} \&{if} $-\|y\L\\{el\_gordo}+\|x$ \1\&{then}\5 -$\\{slow\_add}\K\|x+\|y$\6 -\4\&{else} \&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\\{slow\_add}\K-\\{el\_gordo}$;\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M101. Fixed-point arithmetic is done on {\sl scaled integers\/} that are -multiples -of $2^{-16}$. In other words, a binary point is assumed to be sixteen bit -positions from the right end of a binary computer word. - -\Y\P\D \37$\\{quarter\_unit}\S\O{40000}$\C{$2^{14}$, represents 0.250000}\par -\P\D \37$\\{half\_unit}\S\O{100000}$\C{$2^{15}$, represents 0.50000}\par -\P\D \37$\\{three\_quarter\_unit}\S\O{140000}$\C{$3\cdot2^{14}$, represents -0.75000}\par -\P\D \37$\\{unity}\S\O{200000}$\C{$2^{16}$, represents 1.00000}\par -\P\D \37$\\{two}\S\O{400000}$\C{$2^{17}$, represents 2.00000}\par -\P\D \37$\\{three}\S\O{600000}$\C{$2^{17}+2^{16}$, represents 3.00000}\par -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{scaled}=\\{integer}$;\C{this type is used for scaled integers}\6 -$\\{small\_number}=0\to63$;\C{this type is self-explanatory}\par -\fi - -\M102. The following function is used to create a scaled integer from a given -decimal -fraction $(.d_0d_1\ldots d_{k-1})$, where $0\L\|k\L17$. The digit $d_i$ is -given in $\\{dig}[\|i]$, and the calculation produces a correctly rounded -result. - -\Y\P\4\&{function}\1\ \37$\\{round\_decimals}(\|k:\\{small\_number})$: \37% -\\{scaled};\C{converts a decimal fraction}\6 -\4\&{var} \37\|a: \37\\{integer};\C{the accumulator}\2\6 -\&{begin} \37$\|a\K0$;\6 -\&{while} $\|k>0$ \1\&{do}\6 -\&{begin} \37$\\{decr}(\|k)$;\5 -$\|a\K(\|a+\\{dig}[\|k]\ast\\{two})\mathbin{\&{div}}10$;\6 -\&{end};\2\6 -$\\{round\_decimals}\K\\{half}(\|a+1)$;\6 -\&{end};\par -\fi - -\M103. Conversely, here is a procedure analogous to \\{print\_int}. If the -output -of this procedure is subsequently read by \MF\ and converted by the -\\{round\_decimals} routine above, it turns out that the original value will -be reproduced exactly. A decimal point is printed only if the value is -not an integer. If there is more than one way to print the result with -the optimum number of digits following the decimal point, the closest -possible value is given. - -The invariant relation in the \&{repeat} loop is that a sequence of -decimal digits yet to be printed will yield the original number if and only if -they form a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$. -We can stop if and only if $f=0$ satisfies this condition; the loop will -terminate before $s$ can possibly become zero. - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_scaled}(\|s:\\{scaled})$;\C{prints scaled -real, rounded to five digits}\6 -\4\&{var} \37\\{delta}: \37\\{scaled};\C{amount of allowable inaccuracy}\2\6 -\&{begin} \37\&{if} $\|s<0$ \1\&{then}\6 -\&{begin} \37$\\{print\_char}(\.{"-"})$;\5 -$\\{negate}(\|s)$;\C{print the sign, if negative}\6 -\&{end};\2\6 -$\\{print\_int}(\|s\mathbin{\&{div}}\\{unity})$;\C{print the integer part}\6 -$\|s\K10\ast(\|s\mathbin{\&{mod}}\\{unity})+5$;\6 -\&{if} $\|s\I5$ \1\&{then}\6 -\&{begin} \37$\\{delta}\K10$;\5 -$\\{print\_char}(\.{"."})$;\6 -\1\&{repeat} \37\&{if} $\\{delta}>\\{unity}$ \1\&{then}\5 -$\|s\K\|s+\O{100000}-(\\{delta}\mathbin{\&{div}}2)$;\C{round the final digit}\2% -\6 -$\\{print\_char}(\.{"0"}+(\|s\mathbin{\&{div}}\\{unity}))$;\5 -$\|s\K10\ast(\|s\mathbin{\&{mod}}\\{unity})$;\5 -$\\{delta}\K\\{delta}\ast10$;\6 -\4\&{until}\5 -$\|s\L\\{delta}$;\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M104. We often want to print two scaled quantities in parentheses, -separated by a comma. - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_two}(\|x,\39\|y:\\{scaled})$;\C{prints `$(% -\|x,\|y)$'}\2\6 -\&{begin} \37$\\{print\_char}(\.{"("})$;\5 -$\\{print\_scaled}(\|x)$;\5 -$\\{print\_char}(\.{","})$;\5 -$\\{print\_scaled}(\|y)$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\par -\fi - -\M105. The \\{scaled} quantities in \MF\ programs are generally supposed to be -less than $2^{12}$ in absolute value, so \MF\ does much of its internal -arithmetic with 28~significant bits of precision. A \\{fraction} denotes -a scaled integer whose binary point is assumed to be 28 bit positions -from the right. - -\Y\P\D \37$\\{fraction\_half}\S\O{1000000000}$\C{$2^{27}$, represents -0.50000000}\par -\P\D \37$\\{fraction\_one}\S\O{2000000000}$\C{$2^{28}$, represents 1.00000000}% -\par -\P\D \37$\\{fraction\_two}\S\O{4000000000}$\C{$2^{29}$, represents 2.00000000}% -\par -\P\D \37$\\{fraction\_three}\S\O{6000000000}$\C{$3\cdot2^{28}$, represents -3.00000000}\par -\P\D \37$\\{fraction\_four}\S\O{10000000000}$\C{$2^{30}$, represents -4.00000000}\par -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{fraction}=\\{integer}$;\C{this type is used for scaled fractions}\par -\fi - -\M106. In fact, the two sorts of scaling discussed above aren't quite -sufficient; \MF\ has yet another, used internally to keep track of angles -in units of $2^{-20}$ degrees. - -\Y\P\D \37$\\{forty\_five\_deg}\S\O{264000000}$\C{$45\cdot2^{20}$, represents -$45^\circ$}\par -\P\D \37$\\{ninety\_deg}\S\O{550000000}$\C{$90\cdot2^{20}$, represents $90^% -\circ$}\par -\P\D \37$\\{one\_eighty\_deg}\S\O{1320000000}$\C{$180\cdot2^{20}$, represents -$180^\circ$}\par -\P\D \37$\\{three\_sixty\_deg}\S\O{2640000000}$\C{$360\cdot2^{20}$, represents -$360^\circ$}\par -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{angle}=\\{integer}$;\C{this type is used for scaled angles}\par -\fi - -\M107. The \\{make\_fraction} routine produces the \\{fraction} equivalent of -$\|p/\|q$, given integers \|p and~\|q; it computes the integer -$f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are -positive. If \|p and \|q are both of the same scaled type \|t, -the ``type relation'' $\\{make\_fraction}(\|t,\|t)=\\{fraction}$ is valid; -and it's also possible to use the subroutine ``backwards,'' using -the relation $\\{make\_fraction}(\|t,\\{fraction})=\|t$ between scaled types. - -If the result would have magnitude $2^{31}$ or more, \\{make\_fraction} -sets $\\{arith\_error}\K\\{true}$. Most of \MF's internal computations have -been designed to avoid this sort of error. - -Notice that if 64-bit integer arithmetic were available, -we could simply compute $(\hbox{$(2^{29}$}\ast\|p+\|q)\mathbin{\&{div}}(2\ast% -\|q)$. -But when we are restricted to \PASCAL's 32-bit arithmetic we -must either resort to multiple-precision maneuvering -or use a simple but slow iteration. The multiple-precision technique -would be about three times faster than the code adopted here, but it -would be comparatively long and tricky, involving about sixteen -additional multiplications and divisions. - -This operation is part of \MF's ``inner loop''; indeed, it will -consume nearly 10\pct! of the running time (exclusive of input and output) -if the code below is left unchanged. A machine-dependent recoding -will therefore make \MF\ run faster. The present implementation -is highly portable, but slow; it avoids multiplication and division -except in the initial stage. System wizards should be careful to -replace it with a routine that is guaranteed to produce identical -results in all cases. - -As noted below, a few more routines should also be replaced by -machine-dependent -code, for efficiency. But when a procedure is not part of the ``inner loop,'' -such changes aren't advisable; simplicity and robustness are -preferable to trickery, unless the cost is too high. - -\Y\P\4\&{function}\1\ \37$\\{make\_fraction}(\|p,\39\|q:\\{integer})$: \37% -\\{fraction};\6 -\4\&{var} \37\|f: \37\\{integer};\C{the fraction bits, with a leading 1 bit}\6 -\|n: \37\\{integer};\C{the integer part of $\vert p/q\vert$}\6 -\\{negative}: \37\\{boolean};\C{should the result be negated?}\6 -\\{be\_careful}: \37\\{integer};\C{disables certain compiler optimizations}\2\6 -\&{begin} \37\&{if} $\|p\G0$ \1\&{then}\5 -$\\{negative}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\\{negate}(\|p)$;\5 -$\\{negative}\K\\{true}$;\6 -\&{end};\2\6 -\&{if} $\|q\L0$ \1\&{then}\6 -\&{begin} \37\&{debug} \37\&{if} $\|q=0$ \1\&{then}\5 -$\\{confusion}(\.{"/"})$;\2\ \&{gubed}\6 -$\\{negate}(\|q)$;\5 -$\\{negative}\K\R\\{negative}$;\6 -\&{end};\2\6 -$\|n\K\|p\mathbin{\&{div}}\|q$;\5 -$\|p\K\|p\mathbin{\&{mod}}\|q$;\6 -\&{if} $\|n\G8$ \1\&{then}\6 -\&{begin} \37$\\{arith\_error}\K\\{true}$;\6 -\&{if} $\\{negative}$ \1\&{then}\5 -$\\{make\_fraction}\K-\\{el\_gordo}$\ \&{else} $\\{make\_fraction}\K\\{el% -\_gordo}$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|n\K(\|n-1)\ast\\{fraction\_one}$;\5 -\X108:Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$\X;\6 -\&{if} $\\{negative}$ \1\&{then}\5 -$\\{make\_fraction}\K-(\|f+\|n)$\ \&{else} $\\{make\_fraction}\K\|f+\|n$;\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M108. The \&{repeat} loop here preserves the following invariant relations -between \|f, \|p, and~\|q: -(i)~$0\L\|p<\|q$; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an integer and -$p_0$ is the original value of~$p$. - -Notice that the computation specifies -$(\|p-\|q)+\|p$ instead of $(\|p+\|p)-\|q$, because the latter could overflow. -Let us hope that optimizing compilers do not miss this point; a -special variable \\{be\_careful} is used to emphasize the necessary -order of computation. Optimizing compilers should keep \\{be\_careful} -in a register, not store it in memory. - -\Y\P$\4\X108:Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$\X\S$\6 -$\|f\K1$;\6 -\1\&{repeat} \37$\\{be\_careful}\K\|p-\|q$;\5 -$\|p\K\\{be\_careful}+\|p$;\6 -\&{if} $\|p\G0$ \1\&{then}\5 -$\|f\K\|f+\|f+1$\6 -\4\&{else} \&{begin} \37$\\{double}(\|f)$;\5 -$\|p\K\|p+\|q$;\6 -\&{end};\2\6 -\4\&{until}\5 -$\|f\G\\{fraction\_one}$;\2\6 -$\\{be\_careful}\K\|p-\|q$;\6 -\&{if} $\\{be\_careful}+\|p\G0$ \1\&{then}\5 -$\\{incr}(\|f)$\2\par -\U107.\fi - -\M109. The dual of \\{make\_fraction} is \\{take\_fraction}, which multiplies a -given integer~\|q by a fraction~\|f. When the operands are positive, it -computes $p=\lfloor qf/2^{28}+{1\over2}\rfloor$, a symmetric function -of \|q and~\|f. - -This routine is even more ``inner loopy'' than \\{make\_fraction}; -the present implementation consumes almost 20\pct! of \MF's computation -time during typical jobs, so a machine-language or 64-bit -substitute is advisable. - -\Y\P\4\&{function}\1\ \37$\\{take\_fraction}(\|q:\\{integer};\,\35\|f:% -\\{fraction})$: \37\\{integer};\6 -\4\&{var} \37\|p: \37\\{integer};\C{the fraction so far}\6 -\\{negative}: \37\\{boolean};\C{should the result be negated?}\6 -\|n: \37\\{integer};\C{additional multiple of $q$}\6 -\\{be\_careful}: \37\\{integer};\C{disables certain compiler optimizations}\2\6 -\&{begin} \37\X110:Reduce to the case that $\|f\G0$ and $\|q>0$\X;\6 -\&{if} $\|f<\\{fraction\_one}$ \1\&{then}\5 -$\|n\K0$\6 -\4\&{else} \&{begin} \37$\|n\K\|f\mathbin{\&{div}}\\{fraction\_one}$;\5 -$\|f\K\|f\mathbin{\&{mod}}\\{fraction\_one}$;\6 -\&{if} $\|q\L\\{el\_gordo}\mathbin{\&{div}}\|n$ \1\&{then}\5 -$\|n\K\|n\ast\|q$\6 -\4\&{else} \&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\|n\K\\{el\_gordo}$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\|f\K\|f+\\{fraction\_one}$;\5 -\X111:Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$\X;\6 -$\\{be\_careful}\K\|n-\\{el\_gordo}$;\6 -\&{if} $\\{be\_careful}+\|p>0$ \1\&{then}\6 -\&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\|n\K\\{el\_gordo}-\|p$;\6 -\&{end};\2\6 -\&{if} $\\{negative}$ \1\&{then}\5 -$\\{take\_fraction}\K-(\|n+\|p)$\6 -\4\&{else} $\\{take\_fraction}\K\|n+\|p$;\2\6 -\&{end};\par -\fi - -\M110. \P$\X110:Reduce to the case that $\|f\G0$ and $\|q>0$\X\S$\6 -\&{if} $\|f\G0$ \1\&{then}\5 -$\\{negative}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\\{negate}(\|f)$;\5 -$\\{negative}\K\\{true}$;\6 -\&{end};\2\6 -\&{if} $\|q<0$ \1\&{then}\6 -\&{begin} \37$\\{negate}(\|q)$;\5 -$\\{negative}\K\R\\{negative}$;\6 -\&{end};\2\par -\Us109\ET112.\fi - -\M111. The invariant relations in this case are (i)~$\lfloor(qf+p)/2^k\rfloor -=\lfloor qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and -$f_0$ is the original value of~$f$; (ii)~$2^k\L f<2^{k+1}$. - -\Y\P$\4\X111:Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$\X\S$\6 -$\|p\K\\{fraction\_half}$;\C{that's $2^{27}$; the invariants hold now with -$k=28$}\6 -\&{if} $\|q<\\{fraction\_four}$ \1\&{then}\6 -\1\&{repeat} \37\&{if} $\\{odd}(\|f)$ \1\&{then}\5 -$\|p\K\\{half}(\|p+\|q)$\ \&{else} $\|p\K\\{half}(\|p)$;\2\6 -$\|f\K\\{half}(\|f)$;\6 -\4\&{until}\5 -$\|f=1$\2\6 -\4\&{else} \1\&{repeat} \37\&{if} $\\{odd}(\|f)$ \1\&{then}\5 -$\|p\K\|p+\\{half}(\|q-\|p)$\ \&{else} $\|p\K\\{half}(\|p)$;\2\6 -$\|f\K\\{half}(\|f)$;\6 -\4\&{until}\5 -$\|f=1$\2\2\par -\U109.\fi - -\M112. When we want to multiply something by a \\{scaled} quantity, we use a -scheme -analogous to \\{take\_fraction} but with a different scaling. -Given positive operands, \\{take\_scaled} -computes the quantity $p=\lfloor qf/2^{16}+{1\over2}\rfloor$. - -Once again it is a good idea to use 64-bit arithmetic if -possible; otherwise \\{take\_scaled} will use more than 2\pct! of the running -time -when the Computer Modern fonts are being generated. - -\Y\P\4\&{function}\1\ \37$\\{take\_scaled}(\|q:\\{integer};\,\35\|f:% -\\{scaled})$: \37\\{integer};\6 -\4\&{var} \37\|p: \37\\{integer};\C{the fraction so far}\6 -\\{negative}: \37\\{boolean};\C{should the result be negated?}\6 -\|n: \37\\{integer};\C{additional multiple of $q$}\6 -\\{be\_careful}: \37\\{integer};\C{disables certain compiler optimizations}\2\6 -\&{begin} \37\X110:Reduce to the case that $\|f\G0$ and $\|q>0$\X;\6 -\&{if} $\|f<\\{unity}$ \1\&{then}\5 -$\|n\K0$\6 -\4\&{else} \&{begin} \37$\|n\K\|f\mathbin{\&{div}}\\{unity}$;\5 -$\|f\K\|f\mathbin{\&{mod}}\\{unity}$;\6 -\&{if} $\|q\L\\{el\_gordo}\mathbin{\&{div}}\|n$ \1\&{then}\5 -$\|n\K\|n\ast\|q$\6 -\4\&{else} \&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\|n\K\\{el\_gordo}$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\|f\K\|f+\\{unity}$;\5 -\X113:Compute $p=\lfloor qf/2^{16}+{1\over2}\rfloor-q$\X;\6 -$\\{be\_careful}\K\|n-\\{el\_gordo}$;\6 -\&{if} $\\{be\_careful}+\|p>0$ \1\&{then}\6 -\&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\|n\K\\{el\_gordo}-\|p$;\6 -\&{end};\2\6 -\&{if} $\\{negative}$ \1\&{then}\5 -$\\{take\_scaled}\K-(\|n+\|p)$\6 -\4\&{else} $\\{take\_scaled}\K\|n+\|p$;\2\6 -\&{end};\par -\fi - -\M113. \P$\X113:Compute $p=\lfloor qf/2^{16}+{1\over2}\rfloor-q$\X\S$\6 -$\|p\K\\{half\_unit}$;\C{that's $2^{15}$; the invariants hold now with $k=16$}\6 -\&{if} $\|q<\\{fraction\_four}$ \1\&{then}\6 -\1\&{repeat} \37\&{if} $\\{odd}(\|f)$ \1\&{then}\5 -$\|p\K\\{half}(\|p+\|q)$\ \&{else} $\|p\K\\{half}(\|p)$;\2\6 -$\|f\K\\{half}(\|f)$;\6 -\4\&{until}\5 -$\|f=1$\2\6 -\4\&{else} \1\&{repeat} \37\&{if} $\\{odd}(\|f)$ \1\&{then}\5 -$\|p\K\|p+\\{half}(\|q-\|p)$\ \&{else} $\|p\K\\{half}(\|p)$;\2\6 -$\|f\K\\{half}(\|f)$;\6 -\4\&{until}\5 -$\|f=1$\2\2\par -\U112.\fi - -\M114. For completeness, there's also \\{make\_scaled}, which computes a -quotient as a \\{scaled} number instead of as a \\{fraction}. -In other words, the result is $\lfloor2^{16}p/q+{1\over2}\rfloor$, if the -operands are positive. \ (This procedure is not used especially often, -so it is not part of \MF's inner loop.) - -\Y\P\4\&{function}\1\ \37$\\{make\_scaled}(\|p,\39\|q:\\{integer})$: \37% -\\{scaled};\6 -\4\&{var} \37\|f: \37\\{integer};\C{the fraction bits, with a leading 1 bit}\6 -\|n: \37\\{integer};\C{the integer part of $\vert p/q\vert$}\6 -\\{negative}: \37\\{boolean};\C{should the result be negated?}\6 -\\{be\_careful}: \37\\{integer};\C{disables certain compiler optimizations}\2\6 -\&{begin} \37\&{if} $\|p\G0$ \1\&{then}\5 -$\\{negative}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\\{negate}(\|p)$;\5 -$\\{negative}\K\\{true}$;\6 -\&{end};\2\6 -\&{if} $\|q\L0$ \1\&{then}\6 -\&{begin} \37\&{debug} \37\&{if} $\|q=0$ \1\&{then}\5 -$\\{confusion}(\.{"/"})$;\ \2\6 -\&{gubed}\6 -$\\{negate}(\|q)$;\5 -$\\{negative}\K\R\\{negative}$;\6 -\&{end};\2\6 -$\|n\K\|p\mathbin{\&{div}}\|q$;\5 -$\|p\K\|p\mathbin{\&{mod}}\|q$;\6 -\&{if} $\|n\G\O{100000}$ \1\&{then}\6 -\&{begin} \37$\\{arith\_error}\K\\{true}$;\6 -\&{if} $\\{negative}$ \1\&{then}\5 -$\\{make\_scaled}\K-\\{el\_gordo}$\ \&{else} $\\{make\_scaled}\K\\{el\_gordo}$;% -\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|n\K(\|n-1)\ast\\{unity}$;\5 -\X115:Compute $f=\lfloor 2^{16}(1+p/q)+{1\over2}\rfloor$\X;\6 -\&{if} $\\{negative}$ \1\&{then}\5 -$\\{make\_scaled}\K-(\|f+\|n)$\ \&{else} $\\{make\_scaled}\K\|f+\|n$;\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M115. \P$\X115:Compute $f=\lfloor 2^{16}(1+p/q)+{1\over2}\rfloor$\X\S$\6 -$\|f\K1$;\6 -\1\&{repeat} \37$\\{be\_careful}\K\|p-\|q$;\5 -$\|p\K\\{be\_careful}+\|p$;\6 -\&{if} $\|p\G0$ \1\&{then}\5 -$\|f\K\|f+\|f+1$\6 -\4\&{else} \&{begin} \37$\\{double}(\|f)$;\5 -$\|p\K\|p+\|q$;\6 -\&{end};\2\6 -\4\&{until}\5 -$\|f\G\\{unity}$;\2\6 -$\\{be\_careful}\K\|p-\|q$;\6 -\&{if} $\\{be\_careful}+\|p\G0$ \1\&{then}\5 -$\\{incr}(\|f)$\2\par -\U114.\fi - -\M116. Here is a typical example of how the routines above can be used. -It computes the function -$${1\over3\tau}f(\theta,\phi)= -{\tau^{-1}\bigl(2+\sqrt2\,(\sin\theta-{1\over16}\sin\phi) -(\sin\phi-{1\over16}\sin\theta)(\cos\theta-\cos\phi)\bigr)\over -3\,\bigl(1+{1\over2}(\sqrt5-1)\cos\theta+{1\over2}(3-\sqrt5\,)\cos\phi% -\bigr)},$$ -where $\tau$ is a \\{scaled} ``tension'' parameter. This is \MF's magic -fudge factor for placing the first control point of a curve that starts -at an angle $\theta$ and ends at an angle $\phi$ from the straight path. -(Actually, if the stated quantity exceeds 4, \MF\ reduces it to~4.) - -The trigonometric quantity to be multiplied by $\sqrt2$ is less than $\sqrt2$. -(It's a sum of eight terms whose absolute values can be bounded using -relations such as $\sin\theta\cos\theta\L{1\over2}$.) Thus the numerator -is positive; and since the tension $\tau$ is constrained to be at least -$3\over4$, the numerator is less than $16\over3$. The denominator is -nonnegative and at most~6. Hence the fixed-point calculations below -are guaranteed to stay within the bounds of a 32-bit computer word. - -The angles $\theta$ and $\phi$ are given implicitly in terms of \\{fraction} -arguments \\{st}, \\{ct}, \\{sf}, and \\{cf}, representing $\sin\theta$, $\cos% -\theta$, -$\sin\phi$, and $\cos\phi$, respectively. - -\Y\P\4\&{function}\1\ \37$\\{velocity}(\\{st},\39\\{ct},\39\\{sf},\39\\{cf}:% -\\{fraction};\,\35\|t:\\{scaled})$: \37\\{fraction};\6 -\4\&{var} \37$\\{acc},\39\\{num},\39\\{denom}$: \37\\{integer};\C{registers for -intermediate calculations}\2\6 -\&{begin} \37$\\{acc}\K\\{take\_fraction}(\\{st}-(\\{sf}\mathbin{\&{div}}16),% -\39\\{sf}-(\\{st}\mathbin{\&{div}}16))$;\5 -$\\{acc}\K\\{take\_fraction}(\\{acc},\39\\{ct}-\\{cf})$;\5 -$\\{num}\K\\{fraction\_two}+\\{take\_fraction}(\\{acc},\39379625062)$;% -\C{$2^{28}\sqrt2\approx379625062.497$}\6 -$\\{denom}\K\\{fraction\_three}+\\{take\_fraction}(\\{ct},\39497706707)+\\{take% -\_fraction}(\\{cf},\39307599661)$;\C{$3\cdot2^{27}\cdot(\sqrt5-1)% -\approx497706706.78$ and $3\cdot2^{27}\cdot(3-\sqrt5\,)% -\approx307599661.22$}\6 -\&{if} $\|t\I\\{unity}$ \1\&{then}\5 -$\\{num}\K\\{make\_scaled}(\\{num},\39\|t)$;\C{$\\{make\_scaled}(\\{fraction},% -\\{scaled})=\\{fraction}$}\2\6 -\&{if} $\\{num}\mathbin{\&{div}}4\G\\{denom}$ \1\&{then}\5 -$\\{velocity}\K\\{fraction\_four}$\6 -\4\&{else} $\\{velocity}\K\\{make\_fraction}(\\{num},\39\\{denom})$;\2\6 -\&{end};\par -\fi - -\M117. The following somewhat different subroutine tests rigorously if $ab$ is -greater than, equal to, or less than~$cd$, -given integers $(a,b,c,d)$. In most cases a quick decision is reached. -The result is $+1$, 0, or~$-1$ in the three respective cases. - -\Y\P\D \37$\\{return\_sign}(\#)\S$\1\6 -\&{begin} \37$\\{ab\_vs\_cd}\K\#$;\5 -\&{return};\6 -\&{end}\2\par -\Y\P\4\&{function}\1\ \37$\\{ab\_vs\_cd}(\|a,\39\|b,\39\|c,\39\|d:% -\\{integer})$: \37\\{integer};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|q,\39\|r$: \37\\{integer};\C{temporary registers}\2\6 -\&{begin} \37\X118:Reduce to the case that $\|a,\|c\G0$, $\|b,\|d>0$\X;\6 -\~ \1\&{loop}\ \&{begin} \37$\|q\K\|a\mathbin{\&{div}}\|d$;\5 -$\|r\K\|c\mathbin{\&{div}}\|b$;\6 -\&{if} $\|q\I\|r$ \1\&{then}\6 -\&{if} $\|q>\|r$ \1\&{then}\5 -$\\{return\_sign}(1)$\ \&{else} $\\{return\_sign}(-1)$;\2\2\6 -$\|q\K\|a\mathbin{\&{mod}}\|d$;\5 -$\|r\K\|c\mathbin{\&{mod}}\|b$;\6 -\&{if} $\|r=0$ \1\&{then}\6 -\&{if} $\|q=0$ \1\&{then}\5 -$\\{return\_sign}(0)$\ \&{else} $\\{return\_sign}(1)$;\2\2\6 -\&{if} $\|q=0$ \1\&{then}\5 -$\\{return\_sign}(-1)$;\2\6 -$\|a\K\|b$;\5 -$\|b\K\|q$;\5 -$\|c\K\|d$;\5 -$\|d\K\|r$;\6 -\&{end};\C{now $\|a>\|d>0$ and $\|c>\|b>0$}\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M118. \P$\X118:Reduce to the case that $\|a,\|c\G0$, $\|b,\|d>0$\X\S$\6 -\&{if} $\|a<0$ \1\&{then}\6 -\&{begin} \37$\\{negate}(\|a)$;\5 -$\\{negate}(\|b)$;\6 -\&{end};\2\6 -\&{if} $\|c<0$ \1\&{then}\6 -\&{begin} \37$\\{negate}(\|c)$;\5 -$\\{negate}(\|d)$;\6 -\&{end};\2\6 -\&{if} $\|d\L0$ \1\&{then}\6 -\&{begin} \37\&{if} $\|b\G0$ \1\&{then}\6 -\&{if} $((\|a=0)\V(\|b=0))\W((\|c=0)\V(\|d=0))$ \1\&{then}\5 -$\\{return\_sign}(0)$\6 -\4\&{else} $\\{return\_sign}(1)$;\2\2\6 -\&{if} $\|d=0$ \1\&{then}\6 -\&{if} $\|a=0$ \1\&{then}\5 -$\\{return\_sign}(0)$\ \&{else} $\\{return\_sign}(-1)$;\2\2\6 -$\|q\K\|a$;\5 -$\|a\K\|c$;\5 -$\|c\K\|q$;\5 -$\|q\K-\|b$;\5 -$\|b\K-\|d$;\5 -$\|d\K\|q$;\6 -\&{end}\6 -\4\&{else} \&{if} $\|b\L0$ \1\&{then}\6 -\&{begin} \37\&{if} $\|b<0$ \1\&{then}\6 -\&{if} $\|a>0$ \1\&{then}\5 -$\\{return\_sign}(-1)$;\2\2\6 -\&{if} $\|c=0$ \1\&{then}\5 -$\\{return\_sign}(0)$\6 -\4\&{else} $\\{return\_sign}(-1)$;\2\6 -\&{end}\2\2\par -\U117.\fi - -\M119. We conclude this set of elementary routines with some simple rounding -and truncation operations that are coded in a machine-independent fashion. -The routines are slightly complicated because we want them to work -without overflow whenever $-2^{31}\L x<2^{31}$. - -\Y\P\4\&{function}\1\ \37$\\{floor\_scaled}(\|x:\\{scaled})$: \37\\{scaled};% -\C{$2^{16}\lfloor x/2^{16}\rfloor$}\6 -\4\&{var} \37\\{be\_careful}: \37\\{integer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\|x\G0$ \1\&{then}\5 -$\\{floor\_scaled}\K\|x-(\|x\mathbin{\&{mod}}\\{unity})$\6 -\4\&{else} \&{begin} \37$\\{be\_careful}\K\|x+1$;\5 -$\\{floor\_scaled}\K\|x+((-\\{be\_careful})\mathbin{\&{mod}}\\{unity})+1-% -\\{unity}$;\6 -\&{end};\2\6 -\&{end};\7 -\4\&{function}\1\ \37$\\{floor\_unscaled}(\|x:\\{scaled})$: \37\\{integer};% -\C{$\lfloor x/2^{16}\rfloor$}\6 -\4\&{var} \37\\{be\_careful}: \37\\{integer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\|x\G0$ \1\&{then}\5 -$\\{floor\_unscaled}\K\|x\mathbin{\&{div}}\\{unity}$\6 -\4\&{else} \&{begin} \37$\\{be\_careful}\K\|x+1$;\5 -$\\{floor\_unscaled}\K-(1+((-\\{be\_careful})\mathbin{\&{div}}\\{unity}))$;\6 -\&{end};\2\6 -\&{end};\7 -\4\&{function}\1\ \37$\\{round\_unscaled}(\|x:\\{scaled})$: \37\\{integer};% -\C{$\lfloor x/2^{16}+.5\rfloor$}\6 -\4\&{var} \37\\{be\_careful}: \37\\{integer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\|x\G\\{half\_unit}$ \1\&{then}\5 -$\\{round\_unscaled}\K1+((\|x-\\{half\_unit})\mathbin{\&{div}}\\{unity})$\6 -\4\&{else} \&{if} $\|x\G-\\{half\_unit}$ \1\&{then}\5 -$\\{round\_unscaled}\K0$\6 -\4\&{else} \&{begin} \37$\\{be\_careful}\K\|x+1$;\5 -$\\{round\_unscaled}\K-(1+((-\\{be\_careful}-\\{half\_unit})\mathbin{\&{div}}% -\\{unity}))$;\6 -\&{end};\2\2\6 -\&{end};\7 -\4\&{function}\1\ \37$\\{round\_fraction}(\|x:\\{fraction})$: \37\\{scaled};% -\C{$\lfloor x/2^{12}+.5\rfloor$}\6 -\4\&{var} \37\\{be\_careful}: \37\\{integer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\|x\G2048$ \1\&{then}\5 -$\\{round\_fraction}\K1+((\|x-2048)\mathbin{\&{div}}4096)$\6 -\4\&{else} \&{if} $\|x\G-2048$ \1\&{then}\5 -$\\{round\_fraction}\K0$\6 -\4\&{else} \&{begin} \37$\\{be\_careful}\K\|x+1$;\5 -$\\{round\_fraction}\K-(1+((-\\{be\_careful}-2048)\mathbin{\&{div}}4096))$;\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\N120. \[8] Algebraic and transcendental functions. -\MF\ computes all of the necessary special functions from scratch, without -relying on \\{real} arithmetic or system subroutines for sines, cosines, etc. - -\fi - -\M121. To get the square root of a \\{scaled} number \|x, we want to calculate -$s=\lfloor 2^8\!\sqrt x +{1\over2}\rfloor$. If $x>0$, this is the unique -integer such that $2^{16}x-s\L s^2<2^{16}x+s$. The following subroutine -determines $s$ by an iterative method that maintains the invariant -relations $x=2^{46-2k}x_0\bmod 2^{30}$, $0<y=\lfloor 2^{16-2k}x_0\rfloor --s^2+s\L q=2s$, where $x_0$ is the initial value of $x$. The value of~$y$ -might, however, be zero at the start of the first iteration. - -\Y\P\4\&{function}\1\ \37$\\{square\_rt}(\|x:\\{scaled})$: \37\\{scaled};\6 -\4\&{var} \37\|k: \37\\{small\_number};\C{iteration control counter}\6 -$\|y,\39\|q$: \37\\{integer};\C{registers for intermediate calculations}\2\6 -\&{begin} \37\&{if} $\|x\L0$ \1\&{then}\5 -\X122:Handle square root of zero or negative argument\X\6 -\4\&{else} \&{begin} \37$\|k\K23$;\5 -$\|q\K2$;\6 -\&{while} $\|x<\\{fraction\_two}$ \1\&{do}\C{i.e., \&{while} $\|x<% -\hbox{$2^{29}$}$\unskip}\6 -\&{begin} \37$\\{decr}(\|k)$;\5 -$\|x\K\|x+\|x+\|x+\|x$;\6 -\&{end};\2\6 -\&{if} $\|x<\\{fraction\_four}$ \1\&{then}\5 -$\|y\K0$\6 -\4\&{else} \&{begin} \37$\|x\K\|x-\\{fraction\_four}$;\5 -$\|y\K1$;\6 -\&{end};\2\6 -\1\&{repeat} \37\X123:Decrease \|k by 1, maintaining the invariant relations -between \|x, \|y, and~\|q\X;\6 -\4\&{until}\5 -$\|k=0$;\2\6 -$\\{square\_rt}\K\\{half}(\|q)$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M122. \P$\X122:Handle square root of zero or negative argument\X\S$\6 -\&{begin} \37\&{if} $\|x<0$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Square\ root\ of\ "})$;\5 -$\\{print\_scaled}(\|x)$;\5 -$\\{print}(\.{"\ has\ been\ replaced\ by\ 0"})$;\5 -$\\{help2}(\.{"Since\ I\ don\'t\ take\ square\ roots\ of\ negative\ -numbers,"})$\6 -$(\.{"I\'m\ zeroing\ this\ one.\ Proceed,\ with\ fingers\ crossed."})$;\5 -\\{error};\6 -\&{end};\2\6 -$\\{square\_rt}\K0$;\6 -\&{end}\par -\U121.\fi - -\M123. \P$\X123:Decrease \|k by 1, maintaining the invariant relations between % -\|x, \|y, and~\|q\X\S$\6 -$\\{double}(\|x)$;\5 -$\\{double}(\|y)$;\6 -\&{if} $\|x\G\\{fraction\_four}$ \1\&{then}\C{note that $\\{fraction\_four}=% -\hbox{$2^{30}$}$}\6 -\&{begin} \37$\|x\K\|x-\\{fraction\_four}$;\5 -$\\{incr}(\|y)$;\6 -\&{end};\2\6 -$\\{double}(\|x)$;\5 -$\|y\K\|y+\|y-\|q$;\5 -$\\{double}(\|q)$;\6 -\&{if} $\|x\G\\{fraction\_four}$ \1\&{then}\6 -\&{begin} \37$\|x\K\|x-\\{fraction\_four}$;\5 -$\\{incr}(\|y)$;\6 -\&{end};\2\6 -\&{if} $\|y>\|q$ \1\&{then}\6 -\&{begin} \37$\|y\K\|y-\|q$;\5 -$\|q\K\|q+2$;\6 -\&{end}\6 -\4\&{else} \&{if} $\|y\L0$ \1\&{then}\6 -\&{begin} \37$\|q\K\|q-2$;\5 -$\|y\K\|y+\|q$;\6 -\&{end};\2\2\6 -$\\{decr}(\|k)$\par -\U121.\fi - -\M124. Pythagorean addition $\psqrt{a^2+b^2}$ is implemented by an elegant -iterative scheme due to Cleve Moler and Donald Morrison [{\sl IBM Journal -of Research and Development\/ \bf27} (1983), 577--581]. It modifies \|a and~\|b -in such a way that their Pythagorean sum remains invariant, while the -smaller argument decreases. - -\Y\P\4\&{function}\1\ \37$\\{pyth\_add}(\|a,\39\|b:\\{integer})$: \37% -\\{integer};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|r: \37\\{fraction};\C{register used to transform \|a and \|b}\6 -\\{big}: \37\\{boolean};\C{is the result dangerously near $2^{31}$?}\2\6 -\&{begin} \37$\|a\K\\{abs}(\|a)$;\5 -$\|b\K\\{abs}(\|b)$;\6 -\&{if} $\|a<\|b$ \1\&{then}\6 -\&{begin} \37$\|r\K\|b$;\5 -$\|b\K\|a$;\5 -$\|a\K\|r$;\6 -\&{end};\C{now $0\L\|b\L\|a$}\2\6 -\&{if} $\|b>0$ \1\&{then}\6 -\&{begin} \37\&{if} $\|a<\\{fraction\_two}$ \1\&{then}\5 -$\\{big}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\|a\K\|a\mathbin{\&{div}}4$;\5 -$\|b\K\|b\mathbin{\&{div}}4$;\5 -$\\{big}\K\\{true}$;\6 -\&{end};\C{we reduced the precision to avoid arithmetic overflow}\2\6 -\X125:Replace \|a by an approximation to $\psqrt{a^2+b^2}$\X;\6 -\&{if} $\\{big}$ \1\&{then}\6 -\&{if} $\|a<\\{fraction\_two}$ \1\&{then}\5 -$\|a\K\|a+\|a+\|a+\|a$\6 -\4\&{else} \&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\|a\K\\{el\_gordo}$;\6 -\&{end};\2\2\6 -\&{end};\2\6 -$\\{pyth\_add}\K\|a$;\6 -\&{end};\par -\fi - -\M125. The key idea here is to reflect the vector $(a,b)$ about the -line through $(a,b/2)$. - -\Y\P$\4\X125:Replace \|a by an approximation to $\psqrt{a^2+b^2}$\X\S$\6 -\~ \1\&{loop}\ \&{begin} \37$\|r\K\\{make\_fraction}(\|b,\39\|a)$;\5 -$\|r\K\\{take\_fraction}(\|r,\39\|r)$;\C{now $r\approx b^2/a^2$}\6 -\&{if} $\|r=0$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|r\K\\{make\_fraction}(\|r,\39\\{fraction\_four}+\|r)$;\5 -$\|a\K\|a+\\{take\_fraction}(\|a+\|a,\39\|r)$;\5 -$\|b\K\\{take\_fraction}(\|b,\39\|r)$;\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U124.\fi - -\M126. Here is a similar algorithm for $\psqrt{a^2-b^2}$. -It converges slowly when $b$ is near $a$, but otherwise it works fine. - -\Y\P\4\&{function}\1\ \37$\\{pyth\_sub}(\|a,\39\|b:\\{integer})$: \37% -\\{integer};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|r: \37\\{fraction};\C{register used to transform \|a and \|b}\6 -\\{big}: \37\\{boolean};\C{is the input dangerously near $2^{31}$?}\2\6 -\&{begin} \37$\|a\K\\{abs}(\|a)$;\5 -$\|b\K\\{abs}(\|b)$;\6 -\&{if} $\|a\L\|b$ \1\&{then}\5 -\X128:Handle erroneous \\{pyth\_sub} and set $\|a\K0$\X\6 -\4\&{else} \&{begin} \37\&{if} $\|a<\\{fraction\_four}$ \1\&{then}\5 -$\\{big}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\|a\K\\{half}(\|a)$;\5 -$\|b\K\\{half}(\|b)$;\5 -$\\{big}\K\\{true}$;\6 -\&{end};\2\6 -\X127:Replace \|a by an approximation to $\psqrt{a^2-b^2}$\X;\6 -\&{if} $\\{big}$ \1\&{then}\5 -$\|a\K\|a+\|a$;\2\6 -\&{end};\2\6 -$\\{pyth\_sub}\K\|a$;\6 -\&{end};\par -\fi - -\M127. \P$\X127:Replace \|a by an approximation to $\psqrt{a^2-b^2}$\X\S$\6 -\~ \1\&{loop}\ \&{begin} \37$\|r\K\\{make\_fraction}(\|b,\39\|a)$;\5 -$\|r\K\\{take\_fraction}(\|r,\39\|r)$;\C{now $r\approx b^2/a^2$}\6 -\&{if} $\|r=0$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|r\K\\{make\_fraction}(\|r,\39\\{fraction\_four}-\|r)$;\5 -$\|a\K\|a-\\{take\_fraction}(\|a+\|a,\39\|r)$;\5 -$\|b\K\\{take\_fraction}(\|b,\39\|r)$;\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U126.\fi - -\M128. \P$\X128:Handle erroneous \\{pyth\_sub} and set $\|a\K0$\X\S$\6 -\&{begin} \37\&{if} $\|a<\|b$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Pythagorean\ subtraction\ "})$;\5 -$\\{print\_scaled}(\|a)$;\5 -$\\{print}(\.{"+-+"})$;\5 -$\\{print\_scaled}(\|b)$;\5 -$\\{print}(\.{"\ has\ been\ replaced\ by\ 0"})$;\5 -$\\{help2}(\.{"Since\ I\ don\'t\ take\ square\ roots\ of\ negative\ -numbers,"})$\6 -$(\.{"I\'m\ zeroing\ this\ one.\ Proceed,\ with\ fingers\ crossed."})$;\5 -\\{error};\6 -\&{end};\2\6 -$\|a\K0$;\6 -\&{end}\par -\U126.\fi - -\M129. The subroutines for logarithm and exponential involve two tables. -The first is simple: $\\{two\_to\_the}[\|k]$ equals $2^k$. The second involves -a bit more calculation, which the author claims to have done correctly: -$\\{spec\_log}[\|k]$ is $2^{27}$ times $\ln\bigl(1/(1-2^{-k})\bigr)= -2^{-k}+{1\over2}2^{-2k}+{1\over3}2^{-3k}+\cdots\,$, rounded to the -nearest integer. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{two\_to\_the}: \37\&{array} $[0\to30]$ \1\&{of}\5 -\\{integer};\C{powers of two}\2\6 -\4\\{spec\_log}: \37\&{array} $[1\to28]$ \1\&{of}\5 -\\{integer};\C{special logarithms}\2\par -\fi - -\M130. \P$\X19:Local variables for initialization\X\mathrel{+}\S$\6 -\4\|k: \37\\{integer};\C{all-purpose loop index}\par -\fi - -\M131. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{two\_to\_the}[0]\K1$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}30$ \1\&{do}\5 -$\\{two\_to\_the}[\|k]\K2\ast\\{two\_to\_the}[\|k-1]$;\2\6 -$\\{spec\_log}[1]\K93032640$;\5 -$\\{spec\_log}[2]\K38612034$;\5 -$\\{spec\_log}[3]\K17922280$;\5 -$\\{spec\_log}[4]\K8662214$;\5 -$\\{spec\_log}[5]\K4261238$;\5 -$\\{spec\_log}[6]\K2113709$;\5 -$\\{spec\_log}[7]\K1052693$;\5 -$\\{spec\_log}[8]\K525315$;\5 -$\\{spec\_log}[9]\K262400$;\5 -$\\{spec\_log}[10]\K131136$;\5 -$\\{spec\_log}[11]\K65552$;\5 -$\\{spec\_log}[12]\K32772$;\5 -$\\{spec\_log}[13]\K16385$;\6 -\&{for} $\|k\K14\mathrel{\&{to}}27$ \1\&{do}\5 -$\\{spec\_log}[\|k]\K\\{two\_to\_the}[27-\|k]$;\2\6 -$\\{spec\_log}[28]\K1$;\par -\fi - -\M132. Here is the routine that calculates $2^8$ times the natural logarithm -of a \\{scaled} quantity; it is an integer approximation to $2^{24}% -\ln(x/2^{16})$, -when \|x is a given positive integer. - -The method is based on exercise 1.2.2--25 in {\sl The Art of Computer -Programming\/}: During the main iteration we have $1\L 2^{-30}x<1/(1-2^{1-k})$, -and the logarithm of $2^{30}x$ remains to be added to an accumulator -register called~$y$. Three auxiliary bits of accuracy are retained in~$y$ -during the calculation, and sixteen auxiliary bits to extend \|y are -kept in~\|z during the initial argument reduction. (We add -$100\cdot2^{16}=6553600$ to~\|z and subtract 100 from~\|y so that \|z will -not become negative; also, the actual amount subtracted from~\|y is~96, -not~100, because we want to add~4 for rounding before the final division by~8.) - -\Y\P\4\&{function}\1\ \37$\\{m\_log}(\|x:\\{scaled})$: \37\\{scaled};\6 -\4\&{var} \37$\|y,\39\|z$: \37\\{integer};\C{auxiliary registers}\6 -\|k: \37\\{integer};\C{iteration counter}\2\6 -\&{begin} \37\&{if} $\|x\L0$ \1\&{then}\5 -\X134:Handle non-positive logarithm\X\6 -\4\&{else} \&{begin} \37$\|y\K1302456956+4-100$;\C{$14\times2^{27}\ln2% -\approx1302456956.421063$}\6 -$\|z\K27595+6553600$;\C{and $2^{16}\times .421063\approx 27595$}\6 -\&{while} $\|x<\\{fraction\_four}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\|x)$;\5 -$\|y\K\|y-93032639$;\5 -$\|z\K\|z-48782$;\6 -\&{end};\C{$2^{27}\ln2\approx 93032639.74436163$ and $2^{16}% -\times.74436163\approx 48782$}\2\6 -$\|y\K\|y+(\|z\mathbin{\&{div}}\\{unity})$;\5 -$\|k\K2$;\6 -\&{while} $\|x>\\{fraction\_four}+4$ \1\&{do}\5 -\X133:Increase \|k until \|x can be multiplied by a factor of $2^{-k}$, and -adjust $y$ accordingly\X;\2\6 -$\\{m\_log}\K\|y\mathbin{\&{div}}8$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M133. \P$\X133:Increase \|k until \|x can be multiplied by a factor of -$2^{-k}$, and adjust $y$ accordingly\X\S$\6 -\&{begin} \37$\|z\K((\|x-1)\mathbin{\&{div}}\\{two\_to\_the}[\|k])+1$;\C{$z=% -\lceil x/2^k\rceil$}\6 -\&{while} $\|x<\\{fraction\_four}+\|z$ \1\&{do}\6 -\&{begin} \37$\|z\K\\{half}(\|z+1)$;\5 -$\|k\K\|k+1$;\6 -\&{end};\2\6 -$\|y\K\|y+\\{spec\_log}[\|k]$;\5 -$\|x\K\|x-\|z$;\6 -\&{end}\par -\U132.\fi - -\M134. \P$\X134:Handle non-positive logarithm\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Logarithm\ of\ "})$;\5 -$\\{print\_scaled}(\|x)$;\5 -$\\{print}(\.{"\ has\ been\ replaced\ by\ 0"})$;\5 -$\\{help2}(\.{"Since\ I\ don\'t\ take\ logs\ of\ non-positive\ numbers,"})$\6 -$(\.{"I\'m\ zeroing\ this\ one.\ Proceed,\ with\ fingers\ crossed."})$;\5 -\\{error};\5 -$\\{m\_log}\K0$;\6 -\&{end}\par -\U132.\fi - -\M135. Conversely, the exponential routine calculates $\exp(x/2^8)$, -when \|x is \\{scaled}. The result is an integer approximation to -$2^{16}\exp(x/2^{24})$, when \|x is regarded as an integer. - -\Y\P\4\&{function}\1\ \37$\\{m\_exp}(\|x:\\{scaled})$: \37\\{scaled};\6 -\4\&{var} \37\|k: \37\\{small\_number};\C{loop control index}\6 -$\|y,\39\|z$: \37\\{integer};\C{auxiliary registers}\2\6 -\&{begin} \37\&{if} $\|x>174436200$ \1\&{then}\C{$2^{24}\ln((2^{31}-1)/2^{16})% -\approx 174436199.51$}\6 -\&{begin} \37$\\{arith\_error}\K\\{true}$;\5 -$\\{m\_exp}\K\\{el\_gordo}$;\6 -\&{end}\6 -\4\&{else} \&{if} $\|x<-197694359$ \1\&{then}\5 -$\\{m\_exp}\K0$\C{$2^{24}\ln(2^{-1}/2^{16})\approx-197694359.45$}\6 -\4\&{else} \&{begin} \37\&{if} $\|x\L0$ \1\&{then}\6 -\&{begin} \37$\|z\K-8\ast\|x$;\5 -$\|y\K\O{4000000}$;\C{$y=2^{20}$}\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\|x\L127919879$ \1\&{then}\5 -$\|z\K1023359037-8\ast\|x$\C{$2^{27}\ln((2^{31}-1)/2^{20})\approx -1023359037.125$}\6 -\4\&{else} $\|z\K8\ast(174436200-\|x)$;\C{\|z is always nonnegative}\2\6 -$\|y\K\\{el\_gordo}$;\6 -\&{end};\2\6 -\X136:Multiply \|y by $\exp(-z/2^{27})$\X;\6 -\&{if} $\|x\L127919879$ \1\&{then}\5 -$\\{m\_exp}\K(\|y+8)\mathbin{\&{div}}16$\ \&{else} $\\{m\_exp}\K\|y$;\2\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M136. The idea here is that subtracting $\\{spec\_log}[\|k]$ from \|z -corresponds -to multiplying \|y by $1-2^{-k}$. - -A subtle point (which had to be checked) was that if $x=127919879$, the -value of~\|y will decrease so that $\|y+8$ doesn't overflow. In fact, -$z$ will be 5 in this case, and \|y will decrease by~64 when $\|k=25$ -and by~16 when $\|k=27$. - -\Y\P$\4\X136:Multiply \|y by $\exp(-z/2^{27})$\X\S$\6 -$\|k\K1$;\6 -\&{while} $\|z>0$ \1\&{do}\6 -\&{begin} \37\&{while} $\|z\G\\{spec\_log}[\|k]$ \1\&{do}\6 -\&{begin} \37$\|z\K\|z-\\{spec\_log}[\|k]$;\5 -$\|y\K\|y-1-((\|y-\\{two\_to\_the}[\|k-1])\mathbin{\&{div}}\\{two\_to\_the}[% -\|k])$;\6 -\&{end};\2\6 -$\\{incr}(\|k)$;\6 -\&{end}\2\par -\U135.\fi - -\M137. The trigonometric subroutines use an auxiliary table such that -$\\{spec\_atan}[\|k]$ contains an approximation to the \\{angle} whose tangent -is~$1/2^k$. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{spec\_atan}: \37\&{array} $[1\to26]$ \1\&{of}\5 -\\{angle};\C{$\arctan2^{-k}$ times $2^{20}\cdot180/\pi$}\2\par -\fi - -\M138. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{spec\_atan}[1]\K27855475$;\5 -$\\{spec\_atan}[2]\K14718068$;\5 -$\\{spec\_atan}[3]\K7471121$;\5 -$\\{spec\_atan}[4]\K3750058$;\5 -$\\{spec\_atan}[5]\K1876857$;\5 -$\\{spec\_atan}[6]\K938658$;\5 -$\\{spec\_atan}[7]\K469357$;\5 -$\\{spec\_atan}[8]\K234682$;\5 -$\\{spec\_atan}[9]\K117342$;\5 -$\\{spec\_atan}[10]\K58671$;\5 -$\\{spec\_atan}[11]\K29335$;\5 -$\\{spec\_atan}[12]\K14668$;\5 -$\\{spec\_atan}[13]\K7334$;\5 -$\\{spec\_atan}[14]\K3667$;\5 -$\\{spec\_atan}[15]\K1833$;\5 -$\\{spec\_atan}[16]\K917$;\5 -$\\{spec\_atan}[17]\K458$;\5 -$\\{spec\_atan}[18]\K229$;\5 -$\\{spec\_atan}[19]\K115$;\5 -$\\{spec\_atan}[20]\K57$;\5 -$\\{spec\_atan}[21]\K29$;\5 -$\\{spec\_atan}[22]\K14$;\5 -$\\{spec\_atan}[23]\K7$;\5 -$\\{spec\_atan}[24]\K4$;\5 -$\\{spec\_atan}[25]\K2$;\5 -$\\{spec\_atan}[26]\K1$;\par -\fi - -\M139. Given integers \|x and \|y, not both zero, the \\{n\_arg} function -returns the \\{angle} whose tangent points in the direction $(x,y)$. -This subroutine first determines the correct octant, then solves the -problem for $0\L\|y\L\|x$, then converts the result appropriately to -return an answer in the range $-\\{one\_eighty\_deg}\L\hbox{$\theta$}\L\\{one% -\_eighty\_deg}$. -(The answer is $+\\{one\_eighty\_deg}$ if $\|y=0$ and $\|x<0$, but an answer of -$-\\{one\_eighty\_deg}$ is possible if, for example, $\|y=-1$ and $x=-2^{30}$.) - -The octants are represented in a ``Gray code,'' since that turns out -to be computationally simplest. - -\Y\P\D \37$\\{negate\_x}=1$\par -\P\D \37$\\{negate\_y}=2$\par -\P\D \37$\\{switch\_x\_and\_y}=4$\par -\P\D \37$\\{first\_octant}=1$\par -\P\D \37$\\{second\_octant}=\\{first\_octant}+\\{switch\_x\_and\_y}$\par -\P\D \37$\\{third\_octant}=\\{first\_octant}+\\{switch\_x\_and\_y}+\\{negate% -\_x}$\par -\P\D \37$\\{fourth\_octant}=\\{first\_octant}+\\{negate\_x}$\par -\P\D \37$\\{fifth\_octant}=\\{first\_octant}+\\{negate\_x}+\\{negate\_y}$\par -\P\D \37$\\{sixth\_octant}=\\{first\_octant}+\\{switch\_x\_and\_y}+\\{negate% -\_x}+\\{negate\_y}$\par -\P\D \37$\\{seventh\_octant}=\\{first\_octant}+\\{switch\_x\_and\_y}+\\{negate% -\_y}$\par -\P\D \37$\\{eighth\_octant}=\\{first\_octant}+\\{negate\_y}$\par -\Y\P\4\&{function}\1\ \37$\\{n\_arg}(\|x,\39\|y:\\{integer})$: \37\\{angle};\6 -\4\&{var} \37\|z: \37\\{angle};\C{auxiliary register}\6 -\|t: \37\\{integer};\C{temporary storage}\6 -\|k: \37\\{small\_number};\C{loop counter}\6 -\\{octant}: \37$\\{first\_octant}\to\\{sixth\_octant}$;\C{octant code}\2\6 -\&{begin} \37\&{if} $\|x\G0$ \1\&{then}\5 -$\\{octant}\K\\{first\_octant}$\6 -\4\&{else} \&{begin} \37$\\{negate}(\|x)$;\5 -$\\{octant}\K\\{first\_octant}+\\{negate\_x}$;\6 -\&{end};\2\6 -\&{if} $\|y<0$ \1\&{then}\6 -\&{begin} \37$\\{negate}(\|y)$;\5 -$\\{octant}\K\\{octant}+\\{negate\_y}$;\6 -\&{end};\2\6 -\&{if} $\|x<\|y$ \1\&{then}\6 -\&{begin} \37$\|t\K\|y$;\5 -$\|y\K\|x$;\5 -$\|x\K\|t$;\5 -$\\{octant}\K\\{octant}+\\{switch\_x\_and\_y}$;\6 -\&{end};\2\6 -\&{if} $\|x=0$ \1\&{then}\5 -\X140:Handle undefined arg\X\6 -\4\&{else} \&{begin} \37\X142:Set variable \|z to the arg of $(x,y)$\X;\6 -\X141:Return an appropriate answer based on \|z and \\{octant}\X;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M140. \P$\X140:Handle undefined arg\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"angle(0,0)\ is\ taken\ as\ zero"})$;\5 -$\\{help2}(\.{"The\ \`angle\'\ between\ two\ identical\ points\ is\ -undefined."})$\6 -$(\.{"I\'m\ zeroing\ this\ one.\ Proceed,\ with\ fingers\ crossed."})$;\5 -\\{error};\5 -$\\{n\_arg}\K0$;\6 -\&{end}\par -\U139.\fi - -\M141. \P$\X141:Return an appropriate answer based on \|z and \\{octant}\X\S$\6 -\&{case} $\\{octant}$ \1\&{of}\6 -\4\\{first\_octant}: \37$\\{n\_arg}\K\|z$;\6 -\4\\{second\_octant}: \37$\\{n\_arg}\K\\{ninety\_deg}-\|z$;\6 -\4\\{third\_octant}: \37$\\{n\_arg}\K\\{ninety\_deg}+\|z$;\6 -\4\\{fourth\_octant}: \37$\\{n\_arg}\K\\{one\_eighty\_deg}-\|z$;\6 -\4\\{fifth\_octant}: \37$\\{n\_arg}\K\|z-\\{one\_eighty\_deg}$;\6 -\4\\{sixth\_octant}: \37$\\{n\_arg}\K-\|z-\\{ninety\_deg}$;\6 -\4\\{seventh\_octant}: \37$\\{n\_arg}\K\|z-\\{ninety\_deg}$;\6 -\4\\{eighth\_octant}: \37$\\{n\_arg}\K-\|z$;\2\6 -\&{end}\C{there are no other cases}\par -\U139.\fi - -\M142. At this point we have $\|x\G\|y\G0$, and $\|x>0$. The numbers are scaled -up -or down until $2^{28}\L x<2^{29}$, so that accurate fixed-point calculations -will be made. - -\Y\P$\4\X142:Set variable \|z to the arg of $(x,y)$\X\S$\6 -\&{while} $\|x\G\\{fraction\_two}$ \1\&{do}\6 -\&{begin} \37$\|x\K\\{half}(\|x)$;\5 -$\|y\K\\{half}(\|y)$;\6 -\&{end};\2\6 -$\|z\K0$;\6 -\&{if} $\|y>0$ \1\&{then}\6 -\&{begin} \37\&{while} $\|x<\\{fraction\_one}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\|x)$;\5 -$\\{double}(\|y)$;\6 -\&{end};\2\6 -\X143:Increase \|z to the arg of $(x,y)$\X;\6 -\&{end}\2\par -\U139.\fi - -\M143. During the calculations of this section, variables \|x and~\|y -represent actual coordinates $(x,2^{-k}y)$. We will maintain the -condition $\|x\G\|y$, so that the tangent will be at most $2^{-k}$. -If $x<2y$, the tangent is greater than $2^{-k-1}$. The transformation -$(a,b)\mapsto(a+b\tan\phi,b-a\tan\phi)$ replaces $(a,b)$ by -coordinates whose angle has decreased by~$\phi$; in the special case -$a=x$, $b=2^{-k}y$, and $\tan\phi=2^{-k-1}$, this operation reduces -to the particularly simple iteration shown here. [Cf.~John E. Meggitt, -{\sl IBM Journal of Research and Development\/ \bf6} (1962), 210--226.] - -The initial value of \|x will be multiplied by at most -$(1+{1\over2})(1+{1\over8})(1+{1\over32})\cdots\approx 1.7584$; hence -there is no chance of integer overflow. - -\Y\P$\4\X143:Increase \|z to the arg of $(x,y)$\X\S$\6 -$\|k\K0$;\6 -\1\&{repeat} \37$\\{double}(\|y)$;\5 -$\\{incr}(\|k)$;\6 -\&{if} $\|y>\|x$ \1\&{then}\6 -\&{begin} \37$\|z\K\|z+\\{spec\_atan}[\|k]$;\5 -$\|t\K\|x$;\5 -$\|x\K\|x+(\|y\mathbin{\&{div}}\\{two\_to\_the}[\|k+\|k])$;\5 -$\|y\K\|y-\|t$;\6 -\&{end};\2\6 -\4\&{until}\5 -$\|k=15$;\2\6 -\1\&{repeat} \37$\\{double}(\|y)$;\5 -$\\{incr}(\|k)$;\6 -\&{if} $\|y>\|x$ \1\&{then}\6 -\&{begin} \37$\|z\K\|z+\\{spec\_atan}[\|k]$;\5 -$\|y\K\|y-\|x$;\6 -\&{end};\2\6 -\4\&{until}\5 -$\|k=26$\2\par -\U142.\fi - -\M144. Conversely, the \\{n\_sin\_cos} routine takes an \\{angle} and produces -the sine -and cosine of that angle. The results of this routine are -stored in global integer variables \\{n\_sin} and \\{n\_cos}. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{n\_sin},\39\\{n\_cos}$: \37\\{fraction};\C{results computed by \\{n\_sin% -\_cos}}\par -\fi - -\M145. Given an integer \|z that is $2^{20}$ times an angle $\theta$ in -degrees, -the purpose of $\\{n\_sin\_cos}(\|z)$ is to set -$\|x=\hbox{$r\cos\theta$}$ and $\|y=\hbox{$r\sin\theta$}$ (approximately), -for some rather large number~\|r. The maximum of \|x and \|y -will be between $2^{28}$ and $2^{30}$, so that there will be hardly -any loss of accuracy. Then \|x and~\|y are divided by~\|r. - -\Y\P\4\&{procedure}\1\ \37$\\{n\_sin\_cos}(\|z:\\{angle})$;\C{computes a -multiple of the sine and cosine}\6 -\4\&{var} \37\|k: \37\\{small\_number};\C{loop control variable}\6 -\|q: \37$0\to7$;\C{specifies the quadrant}\6 -\|r: \37\\{fraction};\C{magnitude of $(\|x,\|y)$}\6 -$\|x,\39\|y,\39\|t$: \37\\{integer};\C{temporary registers}\2\6 -\&{begin} \37\&{while} $\|z<0$ \1\&{do}\5 -$\|z\K\|z+\\{three\_sixty\_deg}$;\2\6 -$\|z\K\|z\mathbin{\&{mod}}\\{three\_sixty\_deg}$;\C{now $0\L\|z<\\{three\_sixty% -\_deg}$}\6 -$\|q\K\|z\mathbin{\&{div}}\\{forty\_five\_deg}$;\5 -$\|z\K\|z\mathbin{\&{mod}}\\{forty\_five\_deg}$;\5 -$\|x\K\\{fraction\_one}$;\5 -$\|y\K\|x$;\6 -\&{if} $\R\\{odd}(\|q)$ \1\&{then}\5 -$\|z\K\\{forty\_five\_deg}-\|z$;\2\6 -\X147:Subtract angle \|z from $(\|x,\|y)$\X;\6 -\X146:Convert $(\|x,\|y)$ to the octant determined by~\|q\X;\6 -$\|r\K\\{pyth\_add}(\|x,\39\|y)$;\5 -$\\{n\_cos}\K\\{make\_fraction}(\|x,\39\|r)$;\5 -$\\{n\_sin}\K\\{make\_fraction}(\|y,\39\|r)$;\6 -\&{end};\par -\fi - -\M146. In this case the octants are numbered sequentially. - -\Y\P$\4\X146:Convert $(\|x,\|y)$ to the octant determined by~\|q\X\S$\6 -\&{case} $\|q$ \1\&{of}\6 -\40: \37\\{do\_nothing};\6 -\41: \37\&{begin} \37$\|t\K\|x$;\5 -$\|x\K\|y$;\5 -$\|y\K\|t$;\6 -\&{end};\6 -\42: \37\&{begin} \37$\|t\K\|x$;\5 -$\|x\K-\|y$;\5 -$\|y\K\|t$;\6 -\&{end};\6 -\43: \37$\\{negate}(\|x)$;\6 -\44: \37\&{begin} \37$\\{negate}(\|x)$;\5 -$\\{negate}(\|y)$;\6 -\&{end};\6 -\45: \37\&{begin} \37$\|t\K\|x$;\5 -$\|x\K-\|y$;\5 -$\|y\K-\|t$;\6 -\&{end};\6 -\46: \37\&{begin} \37$\|t\K\|x$;\5 -$\|x\K\|y$;\5 -$\|y\K-\|t$;\6 -\&{end};\6 -\47: \37$\\{negate}(\|y)$;\2\6 -\&{end}\C{there are no other cases}\par -\U145.\fi - -\M147. The main iteration of \\{n\_sin\_cos} is similar to that of \\{n\_arg} -but -applied in reverse. The values of $\\{spec\_atan}[\|k]$ decrease slowly enough -that this loop is guaranteed to terminate before the (nonexistent) value -$\\{spec\_atan}[27]$ would be required. - -\Y\P$\4\X147:Subtract angle \|z from $(\|x,\|y)$\X\S$\6 -$\|k\K1$;\6 -\&{while} $\|z>0$ \1\&{do}\6 -\&{begin} \37\&{if} $\|z\G\\{spec\_atan}[\|k]$ \1\&{then}\6 -\&{begin} \37$\|z\K\|z-\\{spec\_atan}[\|k]$;\5 -$\|t\K\|x$;\6 -$\|x\K\|t+\|y\mathbin{\&{div}}\\{two\_to\_the}[\|k]$;\5 -$\|y\K\|y-\|t\mathbin{\&{div}}\\{two\_to\_the}[\|k]$;\6 -\&{end};\2\6 -$\\{incr}(\|k)$;\6 -\&{end};\2\6 -\&{if} $\|y<0$ \1\&{then}\5 -$\|y\K0$\C{this precaution may never be needed}\2\par -\U145.\fi - -\M148. And now let's complete our collection of numeric utility routines -by considering random number generation. -\MF\ generates pseudo-random numbers with the additive scheme recommended -in Section 3.6 of {\sl The Art of Computer Programming}; however, the -results are random fractions between 0 and $\\{fraction\_one}-1$, inclusive. - -There's an auxiliary array \\{randoms} that contains 55 pseudo-random -fractions. Using the recurrence $x_n=(x_{n-55}-x_{n-24})\bmod 2^{28}$, -we generate batches of 55 new $x_n$'s at a time by calling \\{new\_randoms}. -The global variable \\{j\_random} tells which element has most recently -been consumed. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{randoms}: \37\&{array} $[0\to54]$ \1\&{of}\5 -\\{fraction};\C{the last 55 random values generated}\2\6 -\4\\{j\_random}: \37$0\to54$;\C{the number of unused \\{randoms}}\par -\fi - -\M149. To consume a random fraction, the program below will say `\\{next% -\_random}' -and then it will fetch $\\{randoms}[\\{j\_random}]$. The \\{next\_random} macro -actually accesses the numbers backwards; blocks of 55~$x$'s are -essentially being ``flipped.'' But that doesn't make them less random. - -\Y\P\D \37$\\{next\_random}\S$\1\6 -\&{if} $\\{j\_random}=0$ \1\&{then}\5 -\\{new\_randoms}\6 -\4\&{else} $\\{decr}(\\{j\_random})$\2\2\par -\Y\P\4\&{procedure}\1\ \37\\{new\_randoms};\6 -\4\&{var} \37\|k: \37$0\to54$;\C{index into \\{randoms}}\6 -\|x: \37\\{fraction};\C{accumulator}\2\6 -\&{begin} \37\&{for} $\|k\K0\mathrel{\&{to}}23$ \1\&{do}\6 -\&{begin} \37$\|x\K\\{randoms}[\|k]-\\{randoms}[\|k+31]$;\6 -\&{if} $\|x<0$ \1\&{then}\5 -$\|x\K\|x+\\{fraction\_one}$;\2\6 -$\\{randoms}[\|k]\K\|x$;\6 -\&{end};\2\6 -\&{for} $\|k\K24\mathrel{\&{to}}54$ \1\&{do}\6 -\&{begin} \37$\|x\K\\{randoms}[\|k]-\\{randoms}[\|k-24]$;\6 -\&{if} $\|x<0$ \1\&{then}\5 -$\|x\K\|x+\\{fraction\_one}$;\2\6 -$\\{randoms}[\|k]\K\|x$;\6 -\&{end};\2\6 -$\\{j\_random}\K54$;\6 -\&{end};\par -\fi - -\M150. To initialize the \\{randoms} table, we call the following routine. - -\Y\P\4\&{procedure}\1\ \37$\\{init\_randoms}(\\{seed}:\\{scaled})$;\6 -\4\&{var} \37$\|j,\39\\{jj},\39\|k$: \37\\{fraction};\C{more or less random -integers}\6 -\|i: \37$0\to54$;\C{index into \\{randoms}}\2\6 -\&{begin} \37$\|j\K\\{abs}(\\{seed})$;\6 -\&{while} $\|j\G\\{fraction\_one}$ \1\&{do}\5 -$\|j\K\\{half}(\|j)$;\2\6 -$\|k\K1$;\6 -\&{for} $\|i\K0\mathrel{\&{to}}54$ \1\&{do}\6 -\&{begin} \37$\\{jj}\K\|k$;\5 -$\|k\K\|j-\|k$;\5 -$\|j\K\\{jj}$;\6 -\&{if} $\|k<0$ \1\&{then}\5 -$\|k\K\|k+\\{fraction\_one}$;\2\6 -$\\{randoms}[(\|i\ast21)\mathbin{\&{mod}}55]\K\|j$;\6 -\&{end};\2\6 -\\{new\_randoms};\5 -\\{new\_randoms};\5 -\\{new\_randoms};\C{``warm up'' the array}\6 -\&{end};\par -\fi - -\M151. To produce a uniform random number in the range $0\L\|u<\|x$ or $0\G\|u>% -\|x$ -or $0=\|u=\|x$, given a \\{scaled} value~\|x, we proceed as shown here. - -Note that the call of \\{take\_fraction} will produce the values 0 and~\|x -with about half the probability that it will produce any other particular -values between 0 and~\|x, because it rounds its answers. - -\Y\P\4\&{function}\1\ \37$\\{unif\_rand}(\|x:\\{scaled})$: \37\\{scaled};\6 -\4\&{var} \37\|y: \37\\{scaled};\C{trial value}\2\6 -\&{begin} \37\\{next\_random};\5 -$\|y\K\\{take\_fraction}(\\{abs}(\|x),\39\\{randoms}[\\{j\_random}])$;\6 -\&{if} $\|y=\\{abs}(\|x)$ \1\&{then}\5 -$\\{unif\_rand}\K0$\6 -\4\&{else} \&{if} $\|x>0$ \1\&{then}\5 -$\\{unif\_rand}\K\|y$\6 -\4\&{else} $\\{unif\_rand}\K-\|y$;\2\2\6 -\&{end};\par -\fi - -\M152. Finally, a normal deviate with mean zero and unit standard deviation -can readily be obtained with the ratio method (Algorithm 3.4.1R in -{\sl The Art of Computer Programming\/}). - -\Y\P\4\&{function}\1\ \37\\{norm\_rand}: \37\\{scaled};\6 -\4\&{var} \37$\|x,\39\|u,\39\|l$: \37\\{integer};\C{what the book would call -$2^{16}X$, $2^{28}U$, and $-2^{24}\ln U$}\2\6 -\&{begin} \37\1\&{repeat} \37\1\&{repeat} \37\\{next\_random};\5 -$\|x\K\\{take\_fraction}(112429,\39\\{randoms}[\\{j\_random}]-\\{fraction% -\_half})$;\C{$2^{16}\sqrt{8/e}\approx 112428.82793$}\6 -\\{next\_random};\5 -$\|u\K\\{randoms}[\\{j\_random}]$;\6 -\4\&{until}\5 -$\\{abs}(\|x)<\|u$;\2\6 -$\|x\K\\{make\_fraction}(\|x,\39\|u)$;\5 -$\|l\K139548960-\\{m\_log}(\|u)$;\C{$2^{24}\cdot12\ln2\approx139548959.6165$}\6 -\4\&{until}\5 -$\\{ab\_vs\_cd}(1024,\39\|l,\39\|x,\39\|x)\G0$;\2\6 -$\\{norm\_rand}\K\|x$;\6 -\&{end};\par -\fi - -\N153. \[9] Packed data. -In order to make efficient use of storage space, \MF\ bases its major data -structures on a \\{memory\_word}, which contains either a (signed) integer, -possibly scaled, or a small number of fields that are one half or one -quarter of the size used for storing integers. - -If \|x is a variable of type \\{memory\_word}, it contains up to four -fields that can be referred to as follows: -$$\vbox{\halign{\hfil#&#\hfil&#\hfil\cr -\|x&.\\{int}&(an \\{integer})\cr -\|x&.\\{sc}\qquad&(a \\{scaled} integer)\cr -\|x.\\{hh}.\\{lh}, \|x.\\{hh}&.\\{rh}&(two halfword fields)\cr -\|x.\\{hh}.\\{b0}, \|x.\\{hh}.\\{b1}, \|x.\\{hh}&.\\{rh}&(two quarterword -fields, one halfword -field)\cr -\|x.\\{qqqq}.\\{b0}, \|x.\\{qqqq}.\\{b1}, \|x.\\{qqqq}&.\\{b2}, \|x.\\{qqqq}.% -\\{b3}\hskip-100pt -&\qquad\qquad\qquad(four quarterword fields)\cr}}$$ -This is somewhat cumbersome to write, and not very readable either, but -macros will be used to make the notation shorter and more transparent. -The \PASCAL\ code below gives a formal definition of \\{memory\_word} and -its subsidiary types, using packed variant records. \MF\ makes no -assumptions about the relative positions of the fields within a word. - -Since we are assuming 32-bit integers, a halfword must contain at least -16 bits, and a quarterword must contain at least 8 bits. -But it doesn't hurt to have more bits; for example, with enough 36-bit -words you might be able to have \\{mem\_max} as large as 262142. - -N.B.: Valuable memory space will be dreadfully wasted unless \MF\ is compiled -by a \PASCAL\ that packs all of the \\{memory\_word} variants into -the space of a single integer. Some \PASCAL\ compilers will pack an -integer whose subrange is `$0\to255$' into an eight-bit field, but others -insist on allocating space for an additional sign bit; on such systems you -can get 256 values into a quarterword only if the subrange is `$-128\to127$'. - -The present implementation tries to accommodate as many variations as possible, -so it makes few assumptions. If integers having the subrange -`$\\{min\_quarterword}\to\\{max\_quarterword}$' can be packed into a -quarterword, -and if integers having the subrange `$\\{min\_halfword}\to\\{max\_halfword}$' -can be packed into a halfword, everything should work satisfactorily. - -It is usually most efficient to have $\\{min\_quarterword}=\\{min% -\_halfword}=0$, -so one should try to achieve this unless it causes a severe problem. -The values defined here are recommended for most 32-bit computers. - -\Y\P\D \37$\\{min\_quarterword}=0$\C{smallest allowable value in a % -\\{quarterword}}\par -\P\D \37$\\{max\_quarterword}=255$\C{largest allowable value in a % -\\{quarterword}}\par -\P\D \37$\\{min\_halfword}\S0$\C{smallest allowable value in a \\{halfword}}\par -\P\D \37$\\{max\_halfword}\S65535$\C{largest allowable value in a \\{halfword}}% -\par -\fi - -\M154. Here are the inequalities that the quarterword and halfword values -must satisfy (or rather, the inequalities that they mustn't satisfy): - -\Y\P$\4\X14:Check the ``constant'' values for consistency\X\mathrel{+}\S$\6 -\&{init} \37\&{if} $\\{mem\_max}\I\\{mem\_top}$ \1\&{then}\5 -$\\{bad}\K10$;\ \2\6 -\&{tini}\6 -\&{if} $\\{mem\_max}<\\{mem\_top}$ \1\&{then}\5 -$\\{bad}\K10$;\2\6 -\&{if} $(\\{min\_quarterword}>0)\V(\\{max\_quarterword}<127)$ \1\&{then}\5 -$\\{bad}\K11$;\2\6 -\&{if} $(\\{min\_halfword}>0)\V(\\{max\_halfword}<32767)$ \1\&{then}\5 -$\\{bad}\K12$;\2\6 -\&{if} $(\\{min\_quarterword}<\\{min\_halfword})\V\30(\\{max\_quarterword}>% -\\{max\_halfword})$ \1\&{then}\5 -$\\{bad}\K13$;\2\6 -\&{if} $(\\{mem\_min}<\\{min\_halfword})\V(\\{mem\_max}\G\\{max\_halfword})$ \1% -\&{then}\5 -$\\{bad}\K14$;\2\6 -\&{if} $\\{max\_strings}>\\{max\_halfword}$ \1\&{then}\5 -$\\{bad}\K15$;\2\6 -\&{if} $\\{buf\_size}>\\{max\_halfword}$ \1\&{then}\5 -$\\{bad}\K16$;\2\6 -\&{if} $(\\{max\_quarterword}-\\{min\_quarterword}<255)\V\30(\\{max\_halfword}-% -\\{min\_halfword}<65535)$ \1\&{then}\5 -$\\{bad}\K17$;\2\par -\fi - -\M155. The operation of subtracting \\{min\_halfword} occurs rather frequently -in -\MF, so it is convenient to abbreviate this operation by using the macro -\\{ho} defined here. \MF\ will run faster with respect to compilers that -don't optimize the expression `$\|x-0$', if this macro is simplified in the -obvious way when $\\{min\_halfword}=0$. Similarly, \\{qi} and \\{qo} are used -for -input to and output from quarterwords. - -\Y\P\D \37$\\{ho}(\#)\S\#-\\{min\_halfword}$\C{to take a sixteen-bit item from -a halfword}\par -\P\D \37$\\{qo}(\#)\S\#-\\{min\_quarterword}$\C{to read eight bits from a -quarterword}\par -\P\D \37$\\{qi}(\#)\S\#+\\{min\_quarterword}$\C{to store eight bits in a -quarterword}\par -\fi - -\M156. The reader should study the following definitions closely: - -\Y\P\D \37$\\{sc}\S\\{int}$\C{\\{scaled} data is equivalent to \\{integer}}\par -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{quarterword}=\\{min\_quarterword}\to\\{max\_quarterword}$;\C{1/4 of a word}% -\6 -$\\{halfword}=\\{min\_halfword}\to\\{max\_halfword}$;\C{1/2 of a word}\6 -$\\{two\_choices}=1\to2$;\C{used when there are two variants in a record}\6 -$\\{three\_choices}=1\to3$;\C{used when there are three variants in a record}\6 -$\\{two\_halves}=$\1\5 -\&{packed} \37\1\&{record} \37\\{rh}: \37\\{halfword};\2\6 -\&{case} $\\{two\_choices}$ \1\&{of}\6 -\41: \37$(\\{lh}:\\{halfword})$;\6 -\42: \37$(\\{b0}:\\{quarterword};\,\35\\{b1}:\\{quarterword})$;\2\6 -\&{end};\2\6 -$\\{four\_quarters}=$\1\5 -\&{packed} \37\1\&{record} \37\\{b0}: \37\\{quarterword};\6 -\4\\{b1}: \37\\{quarterword};\6 -\4\\{b2}: \37\\{quarterword};\6 -\4\\{b3}: \37\\{quarterword};\2\6 -\&{end};\2\6 -$\\{memory\_word}=$\1\5 -\1\&{record} \37\2\6 -\&{case} $\\{three\_choices}$ \1\&{of}\6 -\41: \37$(\\{int}:\\{integer})$;\6 -\42: \37$(\\{hh}:\\{two\_halves})$;\6 -\43: \37$(\\{qqqq}:\\{four\_quarters})$;\2\6 -\&{end};\2\6 -$\\{word\_file}=$\1\5 -\&{file} \1\&{of}\5 -\\{memory\_word};\2\2\par -\fi - -\M157. When debugging, we may want to print a \\{memory\_word} without knowing -what type it is; so we print it in all modes. - -\Y\P\&{debug} \37\&{procedure}\1\ \37$\\{print\_word}(\|w:\\{memory\_word})$;% -\C{prints \|w in all ways}\2\6 -\&{begin} \37$\\{print\_int}(\|w.\\{int})$;\5 -$\\{print\_char}(\.{"\ "})$;\6 -$\\{print\_scaled}(\|w.\\{sc})$;\5 -$\\{print\_char}(\.{"\ "})$;\5 -$\\{print\_scaled}(\|w.\\{sc}\mathbin{\&{div}}\O{10000})$;\5 -\\{print\_ln};\6 -$\\{print\_int}(\|w.\\{hh}.\\{lh})$;\5 -$\\{print\_char}(\.{"="})$;\5 -$\\{print\_int}(\|w.\\{hh}.\\{b0})$;\5 -$\\{print\_char}(\.{":"})$;\5 -$\\{print\_int}(\|w.\\{hh}.\\{b1})$;\5 -$\\{print\_char}(\.{";"})$;\5 -$\\{print\_int}(\|w.\\{hh}.\\{rh})$;\5 -$\\{print\_char}(\.{"\ "})$;\6 -$\\{print\_int}(\|w.\\{qqqq}.\\{b0})$;\5 -$\\{print\_char}(\.{":"})$;\5 -$\\{print\_int}(\|w.\\{qqqq}.\\{b1})$;\5 -$\\{print\_char}(\.{":"})$;\5 -$\\{print\_int}(\|w.\\{qqqq}.\\{b2})$;\5 -$\\{print\_char}(\.{":"})$;\5 -$\\{print\_int}(\|w.\\{qqqq}.\\{b3})$;\6 -\&{end};\6 -\&{gubed}\par -\fi - -\N158. \[10] Dynamic memory allocation. -The \MF\ system does nearly all of its own memory allocation, so that it -can readily be transported into environments that do not have automatic -facilities for strings, garbage collection, etc., and so that it can be in -control of what error messages the user receives. The dynamic storage -requirements of \MF\ are handled by providing a large array \\{mem} in -which consecutive blocks of words are used as nodes by the \MF\ routines. - -Pointer variables are indices into this array, or into another array -called \\{eqtb} that will be explained later. A pointer variable might -also be a special flag that lies outside the bounds of \\{mem}, so we -allow pointers to assume any \\{halfword} value. The minimum memory -index represents a null pointer. - -\Y\P\D \37$\\{pointer}\S\\{halfword}$\C{a flag or a location in \\{mem} or % -\\{eqtb}}\par -\P\D \37$\\{null}\S\\{mem\_min}$\C{the null pointer}\par -\fi - -\M159. The \\{mem} array is divided into two regions that are allocated -separately, -but the dividing line between these two regions is not fixed; they grow -together until finding their ``natural'' size in a particular job. -Locations less than or equal to \\{lo\_mem\_max} are used for storing -variable-length records consisting of two or more words each. This region -is maintained using an algorithm similar to the one described in exercise -2.5--19 of {\sl The Art of Computer Programming}. However, no size field -appears in the allocated nodes; the program is responsible for knowing the -relevant size when a node is freed. Locations greater than or equal to -\\{hi\_mem\_min} are used for storing one-word records; a conventional -\.{AVAIL} stack is used for allocation in this region. - -Locations of \\{mem} between \\{mem\_min} and \\{mem\_top} may be dumped as -part -of preloaded format files, by the \.{INIMF} preprocessor. -Production versions of \MF\ may extend the memory at the top end in order to -provide more space; these locations, between \\{mem\_top} and \\{mem\_max}, -are always used for single-word nodes. - -The key pointers that govern \\{mem} allocation have a prescribed order: -$$\hbox{$\\{null}=\\{mem\_min}<\\{lo\_mem\_max}<\\{hi\_mem\_min}<\\{mem\_top}\L% -\\{mem\_end}\L\\{mem\_max}$.}$$ - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{mem}: \37\&{array} $[\\{mem\_min}\to\\{mem\_max}]$ \1\&{of}\5 -\\{memory\_word};\C{the big dynamic storage area}\2\6 -\4\\{lo\_mem\_max}: \37\\{pointer};\C{the largest location of variable-size -memory in use}\6 -\4\\{hi\_mem\_min}: \37\\{pointer};\C{the smallest location of one-word memory -in use}\par -\fi - -\M160. Users who wish to study the memory requirements of specific applications -can -use optional special features that keep track of current and -maximum memory usage. When code between the delimiters \&{stat} $\ldots$ - \&{tats} is not ``commented out,'' \MF\ will run a bit slower but it will -report these statistics when \\{tracing\_stats} is positive. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{var\_used},\39\\{dyn\_used}$: \37\\{integer};\C{how much memory is in -use}\par -\fi - -\M161. Let's consider the one-word memory region first, since it's the -simplest. The pointer variable \\{mem\_end} holds the highest-numbered location -of \\{mem} that has ever been used. The free locations of \\{mem} that -occur between \\{hi\_mem\_min} and \\{mem\_end}, inclusive, are of type -\\{two\_halves}, and we write $\\{info}(\|p)$ and $\\{link}(\|p)$ for the % -\\{lh} -and \\{rh} fields of $\\{mem}[\|p]$ when it is of this type. The single-word -free locations form a linked list -$$\\{avail},\;\hbox{$\\{link}(\\{avail})$},\;\hbox{$\\{link}(\\{link}(% -\\{avail}))$},\;\ldots$$ -terminated by \\{null}. - -\Y\P\D \37$\\{link}(\#)\S\\{mem}[\#].\\{hh}.\\{rh}$\C{the \\{link} field of a -memory word}\par -\P\D \37$\\{info}(\#)\S\\{mem}[\#].\\{hh}.\\{lh}$\C{the \\{info} field of a -memory word}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{avail}: \37\\{pointer};\C{head of the list of available one-word nodes}\6 -\4\\{mem\_end}: \37\\{pointer};\C{the last one-word node used in \\{mem}}\par -\fi - -\M162. If one-word memory is exhausted, it might mean that the user has -forgotten -a token like `\&{enddef}' or `\&{endfor}'. We will define some procedures -later that try to help pinpoint the trouble. - -\Y\P\hbox{\4}\X217:Declare the procedure called \\{show\_token\_list}\X\6 -\hbox{\4}\X665:Declare the procedure called \\{runaway}\X\par -\fi - -\M163. The function \\{get\_avail} returns a pointer to a new one-word node -whose -\\{link} field is null. However, \MF\ will halt if there is no more room left. - -\Y\P\4\&{function}\1\ \37\\{get\_avail}: \37\\{pointer};\C{single-word node -allocation}\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the new node being got}\2\6 -\&{begin} \37$\|p\K\\{avail}$;\C{get top location in the \\{avail} stack}\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\5 -$\\{avail}\K\\{link}(\\{avail})$\C{and pop it off}\6 -\4\&{else} \&{if} $\\{mem\_end}<\\{mem\_max}$ \1\&{then}\C{or go into virgin -territory}\6 -\&{begin} \37$\\{incr}(\\{mem\_end})$;\5 -$\|p\K\\{mem\_end}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{decr}(\\{hi\_mem\_min})$;\5 -$\|p\K\\{hi\_mem\_min}$;\6 -\&{if} $\\{hi\_mem\_min}\L\\{lo\_mem\_max}$ \1\&{then}\6 -\&{begin} \37\\{runaway};\C{if memory is exhausted, display possible runaway -text}\6 -$\\{overflow}(\.{"main\ memory\ size"},\39\\{mem\_max}+1-\\{mem\_min})$;% -\C{quit; all one-word nodes are busy}\6 -\&{end};\2\6 -\&{end};\2\2\6 -$\\{link}(\|p)\K\\{null}$;\C{provide an oft-desired initialization of the new -node}\6 -\&{stat} \37$\\{incr}(\\{dyn\_used})$;\ \&{tats}\C{maintain statistics}\6 -$\\{get\_avail}\K\|p$;\6 -\&{end};\par -\fi - -\M164. Conversely, a one-word node is recycled by calling \\{free\_avail}. - -\Y\P\D \37$\\{free\_avail}(\#)\S$\C{single-word node liberation}\6 -\&{begin} \37$\\{link}(\#)\K\\{avail}$;\5 -$\\{avail}\K\#$;\6 -\&{stat} \37$\\{decr}(\\{dyn\_used})$;\ \&{tats}\6 -\&{end}\par -\fi - -\M165. There's also a \\{fast\_get\_avail} routine, which saves the -procedure-call -overhead at the expense of extra programming. This macro is used in -the places that would otherwise account for the most calls of \\{get\_avail}. - -\Y\P\D \37$\\{fast\_get\_avail}(\#)\S\hbox{}$\6 -\&{begin} \37$\#\K\\{avail}$;\C{avoid \\{get\_avail} if possible, to save time}% -\6 -\&{if} $\#=\\{null}$ \1\&{then}\5 -$\#\K\\{get\_avail}$\6 -\4\&{else} \&{begin} \37$\\{avail}\K\\{link}(\#)$;\5 -$\\{link}(\#)\K\\{null}$;\6 -\&{stat} \37$\\{incr}(\\{dyn\_used})$;\ \&{tats}\6 -\&{end};\2\6 -\&{end}\par -\fi - -\M166. The available-space list that keeps track of the variable-size portion -of \\{mem} is a nonempty, doubly-linked circular list of empty nodes, -pointed to by the roving pointer \\{rover}. - -Each empty node has size 2 or more; the first word contains the special -value \\{max\_halfword} in its \\{link} field and the size in its \\{info} -field; -the second word contains the two pointers for double linking. - -Each nonempty node also has size 2 or more. Its first word is of type -\\{two\_halves}\kern-1pt, and its \\{link} field is never equal to \\{max% -\_halfword}. -Otherwise there is complete flexibility with respect to the contents -of its other fields and its other words. - -(We require $\\{mem\_max}<\\{max\_halfword}$ because terrible things can happen -when \\{max\_halfword} appears in the \\{link} field of a nonempty node.) - -\Y\P\D \37$\\{empty\_flag}\S\\{max\_halfword}$\C{the \\{link} of an empty -variable-size node}\par -\P\D \37$\\{is\_empty}(\#)\S(\\{link}(\#)=\\{empty\_flag})$\C{tests for empty -node}\par -\P\D \37$\\{node\_size}\S\\{info}$\C{the size field in empty variable-size -nodes}\par -\P\D \37$\\{llink}(\#)\S\\{info}(\#+1)$\C{left link in doubly-linked list of -empty nodes}\par -\P\D \37$\\{rlink}(\#)\S\\{link}(\#+1)$\C{right link in doubly-linked list of -empty nodes}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{rover}: \37\\{pointer};\C{points to some node in the list of empties}\par -\fi - -\M167. A call to \\{get\_node} with argument \|s returns a pointer to a new -node -of size~\|s, which must be 2~or more. The \\{link} field of the first word -of this new node is set to null. An overflow stop occurs if no suitable -space exists. - -If \\{get\_node} is called with $s=2^{30}$, it simply merges adjacent free -areas and returns the value \\{max\_halfword}. - -\Y\P\4\&{function}\1\ \37$\\{get\_node}(\|s:\\{integer})$: \37\\{pointer};% -\C{variable-size node allocation}\6 -\4\&{label} \37$\\{found},\39\\{exit},\39\\{restart}$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the node currently under inspection}\6 -\|q: \37\\{pointer};\C{the node physically after node \|p}\6 -\|r: \37\\{integer};\C{the newly allocated node, or a candidate for this honor}% -\6 -$\|t,\39\\{tt}$: \37\\{integer};\C{temporary registers}\2\6 -\&{begin} \37\\{restart}: \37$\|p\K\\{rover}$;\C{start at some free node in the -ring}\6 -\1\&{repeat} \37\X169:Try to allocate within node \|p and its physical -successors, and \&{goto} \\{found} if allocation was possible\X;\6 -$\|p\K\\{rlink}(\|p)$;\C{move to the next node in the ring}\6 -\4\&{until}\5 -$\|p=\\{rover}$;\C{repeat until the whole list has been traversed}\2\6 -\&{if} $\|s=\O{10000000000}$ \1\&{then}\6 -\&{begin} \37$\\{get\_node}\K\\{max\_halfword}$;\5 -\&{return};\6 -\&{end};\2\6 -\&{if} $\\{lo\_mem\_max}+2<\\{hi\_mem\_min}$ \1\&{then}\6 -\&{if} $\\{lo\_mem\_max}+2\L\\{mem\_min}+\\{max\_halfword}$ \1\&{then}\5 -\X168:Grow more variable-size memory and \&{goto} \\{restart}\X;\2\2\6 -$\\{overflow}(\.{"main\ memory\ size"},\39\\{mem\_max}+1-\\{mem\_min})$;% -\C{sorry, nothing satisfactory is left}\6 -\4\\{found}: \37$\\{link}(\|r)\K\\{null}$;\C{this node is now nonempty}\6 -\&{stat} \37$\\{var\_used}\K\\{var\_used}+\|s$;\C{maintain usage statistics}\6 -\&{tats}\6 -$\\{get\_node}\K\|r$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M168. The lower part of \\{mem} grows by 1000 words at a time, unless -we are very close to going under. When it grows, we simply link -a new node into the available-space list. This method of controlled -growth helps to keep the \\{mem} usage consecutive when \MF\ is -implemented on ``virtual memory'' systems. - -\Y\P$\4\X168:Grow more variable-size memory and \&{goto} \\{restart}\X\S$\6 -\&{begin} \37\&{if} $\\{hi\_mem\_min}-\\{lo\_mem\_max}\G1998$ \1\&{then}\5 -$\|t\K\\{lo\_mem\_max}+1000$\6 -\4\&{else} $\|t\K\\{lo\_mem\_max}+1+(\\{hi\_mem\_min}-\\{lo\_mem\_max})% -\mathbin{\&{div}}2$;\C{$\\{lo\_mem\_max}+2\L\|t<\\{hi\_mem\_min}$}\2\6 -\&{if} $\|t>\\{mem\_min}+\\{max\_halfword}$ \1\&{then}\5 -$\|t\K\\{mem\_min}+\\{max\_halfword}$;\2\6 -$\|p\K\\{llink}(\\{rover})$;\5 -$\|q\K\\{lo\_mem\_max}$;\5 -$\\{rlink}(\|p)\K\|q$;\5 -$\\{llink}(\\{rover})\K\|q$;\6 -$\\{rlink}(\|q)\K\\{rover}$;\5 -$\\{llink}(\|q)\K\|p$;\5 -$\\{link}(\|q)\K\\{empty\_flag}$;\5 -$\\{node\_size}(\|q)\K\|t-\\{lo\_mem\_max}$;\6 -$\\{lo\_mem\_max}\K\|t$;\5 -$\\{link}(\\{lo\_mem\_max})\K\\{null}$;\5 -$\\{info}(\\{lo\_mem\_max})\K\\{null}$;\5 -$\\{rover}\K\|q$;\5 -\&{goto} \37\\{restart};\6 -\&{end}\par -\U167.\fi - -\M169. \P$\X169:Try to allocate within node \|p and its physical successors, -and \&{goto} \\{found} if allocation was possible\X\S$\6 -$\|q\K\|p+\\{node\_size}(\|p)$;\C{find the physical successor}\6 -\&{while} $\\{is\_empty}(\|q)$ \1\&{do}\C{merge node \|p with node \|q}\6 -\&{begin} \37$\|t\K\\{rlink}(\|q)$;\5 -$\\{tt}\K\\{llink}(\|q)$;\6 -\&{if} $\|q=\\{rover}$ \1\&{then}\5 -$\\{rover}\K\|t$;\2\6 -$\\{llink}(\|t)\K\\{tt}$;\5 -$\\{rlink}(\\{tt})\K\|t$;\6 -$\|q\K\|q+\\{node\_size}(\|q)$;\6 -\&{end};\2\6 -$\|r\K\|q-\|s$;\6 -\&{if} $\|r>\|p+1$ \1\&{then}\5 -\X170:Allocate from the top of node \|p and \&{goto} \\{found}\X;\2\6 -\&{if} $\|r=\|p$ \1\&{then}\6 -\&{if} $\\{rlink}(\|p)\I\|p$ \1\&{then}\5 -\X171:Allocate entire node \|p and \&{goto} \\{found}\X;\2\2\6 -$\\{node\_size}(\|p)\K\|q-\|p$\C{reset the size in case it grew}\par -\U167.\fi - -\M170. \P$\X170:Allocate from the top of node \|p and \&{goto} \\{found}\X\S$\6 -\&{begin} \37$\\{node\_size}(\|p)\K\|r-\|p$;\C{store the remaining size}\6 -$\\{rover}\K\|p$;\C{start searching here next time}\6 -\&{goto} \37\\{found};\6 -\&{end}\par -\U169.\fi - -\M171. Here we delete node \|p from the ring, and let \\{rover} rove around. - -\Y\P$\4\X171:Allocate entire node \|p and \&{goto} \\{found}\X\S$\6 -\&{begin} \37$\\{rover}\K\\{rlink}(\|p)$;\5 -$\|t\K\\{llink}(\|p)$;\5 -$\\{llink}(\\{rover})\K\|t$;\5 -$\\{rlink}(\|t)\K\\{rover}$;\5 -\&{goto} \37\\{found};\6 -\&{end}\par -\U169.\fi - -\M172. Conversely, when some variable-size node \|p of size \|s is no longer -needed, -the operation $\\{free\_node}(\|p,\|s)$ will make its words available, by -inserting -\|p as a new empty node just before where \\{rover} now points. - -\Y\P\4\&{procedure}\1\ \37$\\{free\_node}(\|p:\\{pointer};\,\35\|s:% -\\{halfword})$;\C{variable-size node liberation}\6 -\4\&{var} \37\|q: \37\\{pointer};\C{$\\{llink}(\\{rover})$}\2\6 -\&{begin} \37$\\{node\_size}(\|p)\K\|s$;\5 -$\\{link}(\|p)\K\\{empty\_flag}$;\5 -$\|q\K\\{llink}(\\{rover})$;\5 -$\\{llink}(\|p)\K\|q$;\5 -$\\{rlink}(\|p)\K\\{rover}$;\C{set both links}\6 -$\\{llink}(\\{rover})\K\|p$;\5 -$\\{rlink}(\|q)\K\|p$;\C{insert \|p into the ring}\6 -\&{stat} \37$\\{var\_used}\K\\{var\_used}-\|s$;\ \&{tats}\C{maintain -statistics}\6 -\&{end};\par -\fi - -\M173. Just before \.{INIMF} writes out the memory, it sorts the doubly linked -available space list. The list is probably very short at such times, so a -simple insertion sort is used. The smallest available location will be -pointed to by \\{rover}, the next-smallest by $\\{rlink}(\\{rover})$, etc. - -\Y\P\&{init} \37\&{procedure}\1\ \37\\{sort\_avail};\C{sorts the available -variable-size nodes by location}\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{indices into \\{mem}}\6 -\\{old\_rover}: \37\\{pointer};\C{initial \\{rover} setting}\2\6 -\&{begin} \37$\|p\K\\{get\_node}(\O{10000000000})$;\C{merge adjacent free -areas}\6 -$\|p\K\\{rlink}(\\{rover})$;\5 -$\\{rlink}(\\{rover})\K\\{max\_halfword}$;\5 -$\\{old\_rover}\K\\{rover}$;\6 -\&{while} $\|p\I\\{old\_rover}$ \1\&{do}\5 -\X174:Sort \|p into the list starting at \\{rover} and advance \|p to $% -\\{rlink}(\|p)$\X;\2\6 -$\|p\K\\{rover}$;\6 -\&{while} $\\{rlink}(\|p)\I\\{max\_halfword}$ \1\&{do}\6 -\&{begin} \37$\\{llink}(\\{rlink}(\|p))\K\|p$;\5 -$\|p\K\\{rlink}(\|p)$;\6 -\&{end};\2\6 -$\\{rlink}(\|p)\K\\{rover}$;\5 -$\\{llink}(\\{rover})\K\|p$;\6 -\&{end};\6 -\&{tini}\par -\fi - -\M174. The following \&{while} loop is guaranteed to -terminate, since the list that starts at -\\{rover} ends with \\{max\_halfword} during the sorting procedure. - -\Y\P$\4\X174:Sort \|p into the list starting at \\{rover} and advance \|p to $% -\\{rlink}(\|p)$\X\S$\6 -\&{if} $\|p<\\{rover}$ \1\&{then}\6 -\&{begin} \37$\|q\K\|p$;\5 -$\|p\K\\{rlink}(\|q)$;\5 -$\\{rlink}(\|q)\K\\{rover}$;\5 -$\\{rover}\K\|q$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|q\K\\{rover}$;\6 -\&{while} $\\{rlink}(\|q)<\|p$ \1\&{do}\5 -$\|q\K\\{rlink}(\|q)$;\2\6 -$\|r\K\\{rlink}(\|p)$;\5 -$\\{rlink}(\|p)\K\\{rlink}(\|q)$;\5 -$\\{rlink}(\|q)\K\|p$;\5 -$\|p\K\|r$;\6 -\&{end}\2\par -\U173.\fi - -\N175. \[11] Memory layout. -Some areas of \\{mem} are dedicated to fixed usage, since static allocation is -more efficient than dynamic allocation when we can get away with it. For -example, locations \\{mem\_min} to $\\{mem\_min}+2$ are always used to store -the -specification for null pen coordinates that are `$(0,0)$'. The -following macro definitions accomplish the static allocation by giving -symbolic names to the fixed positions. Static variable-size nodes appear -in locations \\{mem\_min} through \\{lo\_mem\_stat\_max}, and static -single-word nodes -appear in locations \\{hi\_mem\_stat\_min} through \\{mem\_top}, inclusive. - -\Y\P\D \37$\\{null\_coords}\S\\{mem\_min}$\C{specification for pen offsets of -$(0,0)$}\par -\P\D \37$\\{null\_pen}\S\\{null\_coords}+3$\C{we will define $\\{coord\_node% -\_size}=3$}\par -\P\D \37$\\{dep\_head}\S\\{null\_pen}+10$\C{and $\\{pen\_node\_size}=10$}\par -\P\D \37$\\{zero\_val}\S\\{dep\_head}+2$\C{two words for a permanently zero -value}\par -\P\D \37$\\{temp\_val}\S\\{zero\_val}+2$\C{two words for a temporary value -node}\par -\P\D \37$\\{end\_attr}\S\\{temp\_val}$\C{we use $\\{end\_attr}+2$ only}\par -\P\D \37$\\{inf\_val}\S\\{end\_attr}+2$\C{and $\\{inf\_val}+1$ only}\par -\P\D \37$\\{bad\_vardef}\S\\{inf\_val}+2$\C{two words for \&{vardef} error -recovery}\par -\P\D \37$\\{lo\_mem\_stat\_max}\S\\{bad\_vardef}+1$\C{largest statically -allocated word in the variable-size \\{mem}}\Y\par -\P\D \37$\\{sentinel}\S\\{mem\_top}$\C{end of sorted lists}\par -\P\D \37$\\{temp\_head}\S\\{mem\_top}-1$\C{head of a temporary list of some -kind}\par -\P\D \37$\\{hold\_head}\S\\{mem\_top}-2$\C{head of a temporary list of another -kind}\par -\P\D \37$\\{hi\_mem\_stat\_min}\S\\{mem\_top}-2$\C{smallest statically -allocated word in the one-word \\{mem}}\par -\fi - -\M176. The following code gets the dynamic part of \\{mem} off to a good start, -when \MF\ is initializing itself the slow way. - -\Y\P$\4\X176:Initialize table entries (done by \.{INIMF} only)\X\S$\6 -$\\{rover}\K\\{lo\_mem\_stat\_max}+1$;\C{initialize the dynamic memory}\6 -$\\{link}(\\{rover})\K\\{empty\_flag}$;\5 -$\\{node\_size}(\\{rover})\K1000$;\C{which is a 1000-word available node}\6 -$\\{llink}(\\{rover})\K\\{rover}$;\5 -$\\{rlink}(\\{rover})\K\\{rover}$;\6 -$\\{lo\_mem\_max}\K\\{rover}+1000$;\5 -$\\{link}(\\{lo\_mem\_max})\K\\{null}$;\5 -$\\{info}(\\{lo\_mem\_max})\K\\{null}$;\6 -\&{for} $\|k\K\\{hi\_mem\_stat\_min}\mathrel{\&{to}}\\{mem\_top}$ \1\&{do}\5 -$\\{mem}[\|k]\K\\{mem}[\\{lo\_mem\_max}]$;\C{clear list heads}\2\6 -$\\{avail}\K\\{null}$;\5 -$\\{mem\_end}\K\\{mem\_top}$;\5 -$\\{hi\_mem\_min}\K\\{hi\_mem\_stat\_min}$;\C{initialize the one-word memory}\6 -$\\{var\_used}\K\\{lo\_mem\_stat\_max}+1-\\{mem\_min}$;\5 -$\\{dyn\_used}\K\\{mem\_top}+1-\\{hi\_mem\_min}$;\C{initialize statistics}\par -\As193, 203, 229, 324, 475, 587, 702, 759, 911, 1116, 1127\ETs1185. -\U1210.\fi - -\M177. The procedure $\\{flush\_list}(\|p)$ frees an entire linked list of -one-word -nodes that starts at a given position, until coming to \\{sentinel} or a -pointer that is not in the one-word region. Another procedure, -\\{flush\_node\_list}, frees an entire linked list of one-word and two-word -nodes, until coming to a \\{null} pointer. - -\Y\P\4\&{procedure}\1\ \37$\\{flush\_list}(\|p:\\{pointer})$;\C{makes list of -single-word nodes available}\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\|q,\39\|r$: \37\\{pointer};\C{list traversers}\2\6 -\&{begin} \37\&{if} $\|p\G\\{hi\_mem\_min}$ \1\&{then}\6 -\&{if} $\|p\I\\{sentinel}$ \1\&{then}\6 -\&{begin} \37$\|r\K\|p$;\6 -\1\&{repeat} \37$\|q\K\|r$;\5 -$\|r\K\\{link}(\|r)$;\6 -\&{stat} \37$\\{decr}(\\{dyn\_used})$;\ \&{tats}\6 -\&{if} $\|r<\\{hi\_mem\_min}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\4\&{until}\5 -$\|r=\\{sentinel}$;\2\6 -\4\\{done}: \37\C{now \|q is the last node on the list}\6 -$\\{link}(\|q)\K\\{avail}$;\5 -$\\{avail}\K\|p$;\6 -\&{end};\2\2\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{flush\_node\_list}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the node being recycled}\2\6 -\&{begin} \37\&{while} $\|p\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\|q\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{if} $\|q<\\{hi\_mem\_min}$ \1\&{then}\5 -$\\{free\_node}(\|q,\392)$\ \&{else} $\\{free\_avail}(\|q)$;\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M178. If \MF\ is extended improperly, the \\{mem} array might get screwed up. -For example, some pointers might be wrong, or some ``dead'' nodes might not -have been freed when the last reference to them disappeared. Procedures -\\{check\_mem} and \\{search\_mem} are available to help diagnose such -problems. These procedures make use of two arrays called \\{free} and -\\{was\_free} that are present only if \MF's debugging routines have -been included. (You may want to decrease the size of \\{mem} while you -are debugging.) - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\&{debug} \37\\{free}: \37\&{packed} \37\&{array} $[\\{mem\_min}\to\\{mem% -\_max}]$ \1\&{of}\5 -\\{boolean};\C{free cells}\2\6 -\4\hbox{\hskip1em}\\{was\_free}: \37\&{packed} \37\&{array} $[\\{mem\_min}\to% -\\{mem\_max}]$ \1\&{of}\5 -\\{boolean};\C{previously free cells}\2\6 -\4$\hbox{\hskip1em}\\{was\_mem\_end},\39\\{was\_lo\_max},\39\\{was\_hi\_min}$: % -\37\\{pointer};\C{previous \\{mem\_end}, \\{lo\_mem\_max}, and \\{hi\_mem% -\_min}}\6 -\4\hbox{\hskip1em}\\{panicking}: \37\\{boolean};\C{do we want to check memory -constantly?}\6 -\&{gubed}\par -\fi - -\M179. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -\&{debug} \37$\\{was\_mem\_end}\K\\{mem\_min}$;\C{indicate that everything was -previously free}\6 -$\\{was\_lo\_max}\K\\{mem\_min}$;\5 -$\\{was\_hi\_min}\K\\{mem\_max}$;\5 -$\\{panicking}\K\\{false}$;\6 -\&{gubed}\par -\fi - -\M180. Procedure \\{check\_mem} makes sure that the available space lists of -\\{mem} are well formed, and it optionally prints out all locations -that are reserved now but were free the last time this procedure was called. - -\Y\P\&{debug} \37\&{procedure}\1\ \37$\\{check\_mem}(\\{print\_locs}:% -\\{boolean})$;\6 -\4\&{label} \37$\\{done1},\39\\{done2}$;\C{loop exits}\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{current locations of -interest in \\{mem}}\6 -\\{clobbered}: \37\\{boolean};\C{is something amiss?}\2\6 -\&{begin} \37\&{for} $\|p\K\\{mem\_min}\mathrel{\&{to}}\\{lo\_mem\_max}$ \1% -\&{do}\5 -$\\{free}[\|p]\K\\{false}$;\C{you can probably do this faster}\2\6 -\&{for} $\|p\K\\{hi\_mem\_min}\mathrel{\&{to}}\\{mem\_end}$ \1\&{do}\5 -$\\{free}[\|p]\K\\{false}$;\C{ditto}\2\6 -\X181:Check single-word \\{avail} list\X;\6 -\X182:Check variable-size \\{avail} list\X;\6 -\X183:Check flags of unavailable nodes\X;\6 -\X617:Check the list of linear dependencies\X;\6 -\&{if} $\\{print\_locs}$ \1\&{then}\5 -\X184:Print newly busy locations\X;\2\6 -\&{for} $\|p\K\\{mem\_min}\mathrel{\&{to}}\\{lo\_mem\_max}$ \1\&{do}\5 -$\\{was\_free}[\|p]\K\\{free}[\|p]$;\2\6 -\&{for} $\|p\K\\{hi\_mem\_min}\mathrel{\&{to}}\\{mem\_end}$ \1\&{do}\5 -$\\{was\_free}[\|p]\K\\{free}[\|p]$;\C{$\\{was\_free}\K\\{free}$ might be -faster}\2\6 -$\\{was\_mem\_end}\K\\{mem\_end}$;\5 -$\\{was\_lo\_max}\K\\{lo\_mem\_max}$;\5 -$\\{was\_hi\_min}\K\\{hi\_mem\_min}$;\6 -\&{end};\6 -\&{gubed}\par -\fi - -\M181. \P$\X181:Check single-word \\{avail} list\X\S$\6 -$\|p\K\\{avail}$;\5 -$\|q\K\\{null}$;\5 -$\\{clobbered}\K\\{false}$;\6 -\&{while} $\|p\I\\{null}$ \1\&{do}\6 -\&{begin} \37\&{if} $(\|p>\\{mem\_end})\V(\|p<\\{hi\_mem\_min})$ \1\&{then}\5 -$\\{clobbered}\K\\{true}$\6 -\4\&{else} \&{if} $\\{free}[\|p]$ \1\&{then}\5 -$\\{clobbered}\K\\{true}$;\2\2\6 -\&{if} $\\{clobbered}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"AVAIL\ list\ clobbered\ at\ "})$;\5 -$\\{print\_int}(\|q)$;\5 -\&{goto} \37\\{done1};\6 -\&{end};\2\6 -$\\{free}[\|p]\K\\{true}$;\5 -$\|q\K\|p$;\5 -$\|p\K\\{link}(\|q)$;\6 -\&{end};\2\6 -\4\\{done1}: \37\par -\U180.\fi - -\M182. \P$\X182:Check variable-size \\{avail} list\X\S$\6 -$\|p\K\\{rover}$;\5 -$\|q\K\\{null}$;\5 -$\\{clobbered}\K\\{false}$;\6 -\1\&{repeat} \37\&{if} $(\|p\G\\{lo\_mem\_max})\V(\|p<\\{mem\_min})$ \1\&{then}% -\5 -$\\{clobbered}\K\\{true}$\6 -\4\&{else} \&{if} $(\\{rlink}(\|p)\G\\{lo\_mem\_max})\V(\\{rlink}(\|p)<\\{mem% -\_min})$ \1\&{then}\5 -$\\{clobbered}\K\\{true}$\6 -\4\&{else} \&{if} $\R(\\{is\_empty}(\|p))\V(\\{node\_size}(\|p)<2)\V\30(\|p+% -\\{node\_size}(\|p)>\\{lo\_mem\_max})\V\30(\\{llink}(\\{rlink}(\|p))\I\|p)$ \1% -\&{then}\5 -$\\{clobbered}\K\\{true}$;\2\2\2\6 -\&{if} $\\{clobbered}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"Double-AVAIL\ list\ clobbered\ at\ "})$;\5 -$\\{print\_int}(\|q)$;\5 -\&{goto} \37\\{done2};\6 -\&{end};\2\6 -\&{for} $\|q\K\|p\mathrel{\&{to}}\|p+\\{node\_size}(\|p)-1$ \1\&{do}\C{mark all -locations free}\6 -\&{begin} \37\&{if} $\\{free}[\|q]$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"Doubly\ free\ location\ at\ "})$;\5 -$\\{print\_int}(\|q)$;\5 -\&{goto} \37\\{done2};\6 -\&{end};\2\6 -$\\{free}[\|q]\K\\{true}$;\6 -\&{end};\2\6 -$\|q\K\|p$;\5 -$\|p\K\\{rlink}(\|p)$;\6 -\4\&{until}\5 -$\|p=\\{rover}$;\2\6 -\4\\{done2}: \37\par -\U180.\fi - -\M183. \P$\X183:Check flags of unavailable nodes\X\S$\6 -$\|p\K\\{mem\_min}$;\6 -\&{while} $\|p\L\\{lo\_mem\_max}$ \1\&{do}\C{node \|p should not be empty}\6 -\&{begin} \37\&{if} $\\{is\_empty}(\|p)$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"Bad\ flag\ at\ "})$;\5 -$\\{print\_int}(\|p)$;\6 -\&{end};\2\6 -\&{while} $(\|p\L\\{lo\_mem\_max})\W\R\\{free}[\|p]$ \1\&{do}\5 -$\\{incr}(\|p)$;\2\6 -\&{while} $(\|p\L\\{lo\_mem\_max})\W\\{free}[\|p]$ \1\&{do}\5 -$\\{incr}(\|p)$;\2\6 -\&{end}\2\par -\U180.\fi - -\M184. \P$\X184:Print newly busy locations\X\S$\6 -\&{begin} \37$\\{print\_nl}(\.{"New\ busy\ locs:"})$;\6 -\&{for} $\|p\K\\{mem\_min}\mathrel{\&{to}}\\{lo\_mem\_max}$ \1\&{do}\6 -\&{if} $\R\\{free}[\|p]\W((\|p>\\{was\_lo\_max})\V\\{was\_free}[\|p])$ \1% -\&{then}\6 -\&{begin} \37$\\{print\_char}(\.{"\ "})$;\5 -$\\{print\_int}(\|p)$;\6 -\&{end};\2\2\6 -\&{for} $\|p\K\\{hi\_mem\_min}\mathrel{\&{to}}\\{mem\_end}$ \1\&{do}\6 -\&{if} $\R\\{free}[\|p]\W((\|p<\\{was\_hi\_min})\V(\|p>\\{was\_mem\_end})\V% -\\{was\_free}[\|p])$ \1\&{then}\6 -\&{begin} \37$\\{print\_char}(\.{"\ "})$;\5 -$\\{print\_int}(\|p)$;\6 -\&{end};\2\2\6 -\&{end}\par -\U180.\fi - -\M185. The \\{search\_mem} procedure attempts to answer the question ``Who -points -to node~\|p?'' In doing so, it fetches \\{link} and \\{info} fields of \\{mem} -that might not be of type \\{two\_halves}. Strictly speaking, this is -undefined in \PASCAL, and it can lead to ``false drops'' (words that seem to -point to \|p purely by coincidence). But for debugging purposes, we want -to rule out the places that do {\sl not\/} point to \|p, so a few false -drops are tolerable. - -\Y\P\&{debug} \37\&{procedure}\1\ \37$\\{search\_mem}(\|p:\\{pointer})$;% -\C{look for pointers to \|p}\6 -\4\&{var} \37\|q: \37\\{integer};\C{current position being searched}\2\6 -\&{begin} \37\&{for} $\|q\K\\{mem\_min}\mathrel{\&{to}}\\{lo\_mem\_max}$ \1% -\&{do}\6 -\&{begin} \37\&{if} $\\{link}(\|q)=\|p$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"LINK("})$;\5 -$\\{print\_int}(\|q)$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\2\6 -\&{if} $\\{info}(\|q)=\|p$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"INFO("})$;\5 -$\\{print\_int}(\|q)$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{for} $\|q\K\\{hi\_mem\_min}\mathrel{\&{to}}\\{mem\_end}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{link}(\|q)=\|p$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"LINK("})$;\5 -$\\{print\_int}(\|q)$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\2\6 -\&{if} $\\{info}(\|q)=\|p$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"INFO("})$;\5 -$\\{print\_int}(\|q)$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\2\6 -\&{end};\2\6 -\X209:Search \\{eqtb} for equivalents equal to \|p\X;\6 -\&{end};\6 -\&{gubed}\par -\fi - -\N186. \[12] The command codes. -Before we can go much further, we need to define symbolic names for the -internal -code numbers that represent the various commands obeyed by \MF. These codes -are somewhat arbitrary, but not completely so. For example, -some codes have been made adjacent so that \&{case} statements in the -program need not consider cases that are widely spaced, or so that \&{case} -statements can be replaced by \&{if} statements. A command can begin an -expression if and only if its code lies between \\{min\_primary\_command} and -\\{max\_primary\_command}, inclusive. The first token of a statement that -doesn't -begin with an expression has a command code between \\{min\_command} and -\\{max\_statement\_command}, inclusive. The ordering of the highest-numbered -commands ($\\{comma}<\\{semicolon}<\\{end\_group}<\\{stop}$) is crucial for the -parsing -and error-recovery methods of this program. - -At any rate, here is the list, for future reference. - -\Y\P\D \37$\\{if\_test}=1$\C{conditional text (\&{if})}\par -\P\D \37$\\{fi\_or\_else}=2$\C{delimiters for conditionals (\&{elseif}, % -\&{else}, \&{fi}}\par -\P\D \37$\\{input}=3$\C{input a source file (\&{input}, \&{endinput})}\par -\P\D \37$\\{iteration}=4$\C{iterate (\&{for}, \&{forsuffixes}, \&{forever}, % -\&{endfor})}\par -\P\D \37$\\{repeat\_loop}=5$\C{special command substituted for \&{endfor}}\par -\P\D \37$\\{exit\_test}=6$\C{premature exit from a loop (\&{exitif})}\par -\P\D \37$\\{relax}=7$\C{do nothing (\.{\char`\\})}\par -\P\D \37$\\{scan\_tokens}=8$\C{put a string into the input buffer}\par -\P\D \37$\\{expand\_after}=9$\C{look ahead one token}\par -\P\D \37$\\{defined\_macro}=10$\C{a macro defined by the user}\par -\P\D \37$\\{min\_command}=\\{defined\_macro}+1$\par -\P\D \37$\\{display\_command}=11$\C{online graphic output (\&{display})}\par -\P\D \37$\\{save\_command}=12$\C{save a list of tokens (\&{save})}\par -\P\D \37$\\{interim\_command}=13$\C{save an internal quantity (\&{interim})}\par -\P\D \37$\\{let\_command}=14$\C{redefine a symbolic token (\&{let})}\par -\P\D \37$\\{new\_internal}=15$\C{define a new internal quantity (% -\&{newinternal})}\par -\P\D \37$\\{macro\_def}=16$\C{define a macro (\&{def}, \&{vardef}, etc.)}\par -\P\D \37$\\{ship\_out\_command}=17$\C{output a character (\&{shipout})}\par -\P\D \37$\\{add\_to\_command}=18$\C{add to edges (\&{addto})}\par -\P\D \37$\\{cull\_command}=19$\C{cull and normalize edges (\&{cull})}\par -\P\D \37$\\{tfm\_command}=20$\C{command for font metric info (\&{ligtable}, -etc.)}\par -\P\D \37$\\{protection\_command}=21$\C{set protection flag (\&{outer}, % -\&{inner})}\par -\P\D \37$\\{show\_command}=22$\C{diagnostic output (\&{show}, \&{showvariable}, -etc.)}\par -\P\D \37$\\{mode\_command}=23$\C{set interaction level (\&{batchmode}, etc.)}% -\par -\P\D \37$\\{random\_seed}=24$\C{initialize random number generator (% -\&{randomseed})}\par -\P\D \37$\\{message\_command}=25$\C{communicate to user (\&{message}, % -\&{errmessage})}\par -\P\D \37$\\{every\_job\_command}=26$\C{designate a starting token (% -\&{everyjob})}\par -\P\D \37$\\{delimiters}=27$\C{define a pair of delimiters (\&{delimiters})}\par -\P\D \37$\\{open\_window}=28$\C{define a window on the screen (\&{openwindow})}% -\par -\P\D \37$\\{special\_command}=29$\C{output special info (\&{special}, % -\&{numspecial})}\par -\P\D \37$\\{type\_name}=30$\C{declare a type (\&{numeric}, \&{pair}, etc.}\par -\P\D \37$\\{max\_statement\_command}=\\{type\_name}$\par -\P\D \37$\\{min\_primary\_command}=\\{type\_name}$\par -\P\D \37$\\{left\_delimiter}=31$\C{the left delimiter of a matching pair}\par -\P\D \37$\\{begin\_group}=32$\C{beginning of a group (\&{begingroup})}\par -\P\D \37$\\{nullary}=33$\C{an operator without arguments (e.g., % -\&{normaldeviate})}\par -\P\D \37$\\{unary}=34$\C{an operator with one argument (e.g., \&{sqrt})}\par -\P\D \37$\\{str\_op}=35$\C{convert a suffix to a string (\&{str})}\par -\P\D \37$\\{cycle}=36$\C{close a cyclic path (\&{cycle})}\par -\P\D \37$\\{primary\_binary}=37$\C{binary operation taking `\&{of}' (e.g., % -\&{point})}\par -\P\D \37$\\{capsule\_token}=38$\C{a value that has been put into a token list}% -\par -\P\D \37$\\{string\_token}=39$\C{a string constant (e.g., \.{"hello"})}\par -\P\D \37$\\{internal\_quantity}=40$\C{internal numeric parameter (e.g., % -\&{pausing})}\par -\P\D \37$\\{min\_suffix\_token}=\\{internal\_quantity}$\par -\P\D \37$\\{tag\_token}=41$\C{a symbolic token without a primitive meaning}\par -\P\D \37$\\{numeric\_token}=42$\C{a numeric constant (e.g., \.{3.14159})}\par -\P\D \37$\\{max\_suffix\_token}=\\{numeric\_token}$\par -\P\D \37$\\{plus\_or\_minus}=43$\C{either `\.+' or `\.-'}\par -\P\D \37$\\{max\_primary\_command}=\\{plus\_or\_minus}$\C{should also be $% -\\{numeric\_token}+1$}\par -\P\D \37$\\{min\_tertiary\_command}=\\{plus\_or\_minus}$\par -\P\D \37$\\{tertiary\_secondary\_macro}=44$\C{a macro defined by % -\&{secondarydef}}\par -\P\D \37$\\{tertiary\_binary}=45$\C{an operator at the tertiary level (e.g., `% -\.{++}')}\par -\P\D \37$\\{max\_tertiary\_command}=\\{tertiary\_binary}$\par -\P\D \37$\\{left\_brace}=46$\C{the operator `\.{\char`\{}'}\par -\P\D \37$\\{min\_expression\_command}=\\{left\_brace}$\par -\P\D \37$\\{path\_join}=47$\C{the operator `\.{..}'}\par -\P\D \37$\\{ampersand}=48$\C{the operator `\.\&'}\par -\P\D \37$\\{expression\_tertiary\_macro}=49$\C{a macro defined by % -\&{tertiarydef}}\par -\P\D \37$\\{expression\_binary}=50$\C{an operator at the expression level -(e.g., `\.<')}\par -\P\D \37$\\{equals}=51$\C{the operator `\.='}\par -\P\D \37$\\{max\_expression\_command}=\\{equals}$\par -\P\D \37$\\{and\_command}=52$\C{the operator `\&{and}'}\par -\P\D \37$\\{min\_secondary\_command}=\\{and\_command}$\par -\P\D \37$\\{secondary\_primary\_macro}=53$\C{a macro defined by \&{primarydef}}% -\par -\P\D \37$\\{slash}=54$\C{the operator `\./'}\par -\P\D \37$\\{secondary\_binary}=55$\C{an operator at the binary level (e.g., % -\&{shifted})}\par -\P\D \37$\\{max\_secondary\_command}=\\{secondary\_binary}$\par -\P\D \37$\\{param\_type}=56$\C{type of parameter (\&{primary}, \&{expr}, % -\&{suffix}, etc.)}\par -\P\D \37$\\{controls}=57$\C{specify control points explicitly (\&{controls})}% -\par -\P\D \37$\\{tension}=58$\C{specify tension between knots (\&{tension})}\par -\P\D \37$\\{at\_least}=59$\C{bounded tension value (\&{atleast})}\par -\P\D \37$\\{curl\_command}=60$\C{specify curl at an end knot (\&{curl})}\par -\P\D \37$\\{macro\_special}=61$\C{special macro operators (\&{quote}, \.{\#% -\AT!}, etc.)}\par -\P\D \37$\\{right\_delimiter}=62$\C{the right delimiter of a matching pair}\par -\P\D \37$\\{left\_bracket}=63$\C{the operator `\.['}\par -\P\D \37$\\{right\_bracket}=64$\C{the operator `\.]'}\par -\P\D \37$\\{right\_brace}=65$\C{the operator `\.{\char`\}}'}\par -\P\D \37$\\{with\_option}=66$\C{option for filling (\&{withpen}, % -\&{withweight})}\par -\P\D \37$\\{cull\_op}=67$\C{the operator `\&{keeping}' or `\&{dropping}'}\par -\P\D \37$\\{thing\_to\_add}=68$\C{variant of \&{addto} (\&{contour}, % -\&{doublepath}, \&{also})}\par -\P\D \37$\\{of\_token}=69$\C{the operator `\&{of}'}\par -\P\D \37$\\{from\_token}=70$\C{the operator `\&{from}'}\par -\P\D \37$\\{to\_token}=71$\C{the operator `\&{to}'}\par -\P\D \37$\\{at\_token}=72$\C{the operator `\&{at}'}\par -\P\D \37$\\{in\_window}=73$\C{the operator `\&{inwindow}'}\par -\P\D \37$\\{step\_token}=74$\C{the operator `\&{step}'}\par -\P\D \37$\\{until\_token}=75$\C{the operator `\&{until}'}\par -\P\D \37$\\{lig\_kern\_token}=76$\C{the operators `\&{kern}' and `\.{=:}' and `% -\.{=:\char'174}, etc.}\par -\P\D \37$\\{assignment}=77$\C{the operator `\.{:=}'}\par -\P\D \37$\\{skip\_to}=78$\C{the operation `\&{skipto}'}\par -\P\D \37$\\{bchar\_label}=79$\C{the operator `\.{\char'174\char'174:}'}\par -\P\D \37$\\{double\_colon}=80$\C{the operator `\.{::}'}\par -\P\D \37$\\{colon}=81$\C{the operator `\.:'}\Y\par -\P\D \37$\\{comma}=82$\C{the operator `\.,', must be $\\{colon}+1$}\par -\P\D \37$\\{end\_of\_statement}\S\\{cur\_cmd}>\\{comma}$\par -\P\D \37$\\{semicolon}=83$\C{the operator `\.;', must be $\\{comma}+1$}\par -\P\D \37$\\{end\_group}=84$\C{end a group (\&{endgroup}), must be $% -\\{semicolon}+1$}\par -\P\D \37$\\{stop}=85$\C{end a job (\&{end}, \&{dump}), must be $\\{end% -\_group}+1$}\par -\P\D \37$\\{max\_command\_code}=\\{stop}$\par -\P\D \37$\\{outer\_tag}=\\{max\_command\_code}+1$\C{protection code added to -command code}\par -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{command\_code}=1\to\\{max\_command\_code}$;\par -\fi - -\M187. Variables and capsules in \MF\ have a variety of ``types,'' -distinguished by the following code numbers: - -\Y\P\D \37$\\{undefined}=0$\C{no type has been declared}\par -\P\D \37$\\{unknown\_tag}=1$\C{this constant is added to certain type codes -below}\par -\P\D \37$\\{vacuous}=1$\C{no expression was present}\par -\P\D \37$\\{boolean\_type}=2$\C{\&{boolean} with a known value}\par -\P\D \37$\\{unknown\_boolean}=\\{boolean\_type}+\\{unknown\_tag}$\par -\P\D \37$\\{string\_type}=4$\C{\&{string} with a known value}\par -\P\D \37$\\{unknown\_string}=\\{string\_type}+\\{unknown\_tag}$\par -\P\D \37$\\{pen\_type}=6$\C{\&{pen} with a known value}\par -\P\D \37$\\{unknown\_pen}=\\{pen\_type}+\\{unknown\_tag}$\par -\P\D \37$\\{future\_pen}=8$\C{subexpression that will become a \&{pen} at a -higher level}\par -\P\D \37$\\{path\_type}=9$\C{\&{path} with a known value}\par -\P\D \37$\\{unknown\_path}=\\{path\_type}+\\{unknown\_tag}$\par -\P\D \37$\\{picture\_type}=11$\C{\&{picture} with a known value}\par -\P\D \37$\\{unknown\_picture}=\\{picture\_type}+\\{unknown\_tag}$\par -\P\D \37$\\{transform\_type}=13$\C{\&{transform} variable or capsule}\par -\P\D \37$\\{pair\_type}=14$\C{\&{pair} variable or capsule}\par -\P\D \37$\\{numeric\_type}=15$\C{variable that has been declared \&{numeric} -but not used}\par -\P\D \37$\\{known}=16$\C{\&{numeric} with a known value}\par -\P\D \37$\\{dependent}=17$\C{a linear combination with \\{fraction} -coefficients}\par -\P\D \37$\\{proto\_dependent}=18$\C{a linear combination with \\{scaled} -coefficients}\par -\P\D \37$\\{independent}=19$\C{\&{numeric} with unknown value}\par -\P\D \37$\\{token\_list}=20$\C{variable name or suffix argument or text -argument}\par -\P\D \37$\\{structured}=21$\C{variable with subscripts and attributes}\par -\P\D \37$\\{unsuffixed\_macro}=22$\C{variable defined with \&{vardef} but no % -\.{\AT!\#}}\par -\P\D \37$\\{suffixed\_macro}=23$\C{variable defined with \&{vardef} and \.{\AT!% -\#}}\Y\par -\P\D \37$\\{unknown\_types}\S\\{unknown\_boolean},\39\\{unknown\_string},\39% -\\{unknown\_pen},\39\\{unknown\_picture},\39\\{unknown\_path}$\par -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_type}(\|t:\\{small\_number})$;\2\6 -\&{begin} \37\&{case} $\|t$ \1\&{of}\6 -\4\\{vacuous}: \37$\\{print}(\.{"vacuous"})$;\6 -\4\\{boolean\_type}: \37$\\{print}(\.{"boolean"})$;\6 -\4\\{unknown\_boolean}: \37$\\{print}(\.{"unknown\ boolean"})$;\6 -\4\\{string\_type}: \37$\\{print}(\.{"string"})$;\6 -\4\\{unknown\_string}: \37$\\{print}(\.{"unknown\ string"})$;\6 -\4\\{pen\_type}: \37$\\{print}(\.{"pen"})$;\6 -\4\\{unknown\_pen}: \37$\\{print}(\.{"unknown\ pen"})$;\6 -\4\\{future\_pen}: \37$\\{print}(\.{"future\ pen"})$;\6 -\4\\{path\_type}: \37$\\{print}(\.{"path"})$;\6 -\4\\{unknown\_path}: \37$\\{print}(\.{"unknown\ path"})$;\6 -\4\\{picture\_type}: \37$\\{print}(\.{"picture"})$;\6 -\4\\{unknown\_picture}: \37$\\{print}(\.{"unknown\ picture"})$;\6 -\4\\{transform\_type}: \37$\\{print}(\.{"transform"})$;\6 -\4\\{pair\_type}: \37$\\{print}(\.{"pair"})$;\6 -\4\\{known}: \37$\\{print}(\.{"known\ numeric"})$;\6 -\4\\{dependent}: \37$\\{print}(\.{"dependent"})$;\6 -\4\\{proto\_dependent}: \37$\\{print}(\.{"proto-dependent"})$;\6 -\4\\{numeric\_type}: \37$\\{print}(\.{"numeric"})$;\6 -\4\\{independent}: \37$\\{print}(\.{"independent"})$;\6 -\4\\{token\_list}: \37$\\{print}(\.{"token\ list"})$;\6 -\4\\{structured}: \37$\\{print}(\.{"structured"})$;\6 -\4\\{unsuffixed\_macro}: \37$\\{print}(\.{"unsuffixed\ macro"})$;\6 -\4\\{suffixed\_macro}: \37$\\{print}(\.{"suffixed\ macro"})$;\6 -\4\&{othercases} \37$\\{print}(\.{"undefined"})$\2\6 -\&{endcases};\6 -\&{end};\par -\fi - -\M188. Values inside \MF\ are stored in two-word nodes that have a \\{name% -\_type} -as well as a \\{type}. The possibilities for \\{name\_type} are defined -here; they will be explained in more detail later. - -\Y\P\D \37$\\{root}=0$\C{\\{name\_type} at the top level of a variable}\par -\P\D \37$\\{saved\_root}=1$\C{same, when the variable has been saved}\par -\P\D \37$\\{structured\_root}=2$\C{\\{name\_type} where a \\{structured} branch -occurs}\par -\P\D \37$\\{subscr}=3$\C{\\{name\_type} in a subscript node}\par -\P\D \37$\\{attr}=4$\C{\\{name\_type} in an attribute node}\par -\P\D \37$\\{x\_part\_sector}=5$\C{\\{name\_type} in the \&{xpart} of a node}\par -\P\D \37$\\{y\_part\_sector}=6$\C{\\{name\_type} in the \&{ypart} of a node}\par -\P\D \37$\\{xx\_part\_sector}=7$\C{\\{name\_type} in the \&{xxpart} of a node}% -\par -\P\D \37$\\{xy\_part\_sector}=8$\C{\\{name\_type} in the \&{xypart} of a node}% -\par -\P\D \37$\\{yx\_part\_sector}=9$\C{\\{name\_type} in the \&{yxpart} of a node}% -\par -\P\D \37$\\{yy\_part\_sector}=10$\C{\\{name\_type} in the \&{yypart} of a node}% -\par -\P\D \37$\\{capsule}=11$\C{\\{name\_type} in stashed-away subexpressions}\par -\P\D \37$\\{token}=12$\C{\\{name\_type} in a numeric token or string token}\par -\fi - -\M189. Primitive operations that produce values have a secondary identification -code in addition to their command code; it's something like genera and species. -For example, `\.*' has the command code \\{primary\_binary}, and its -secondary identification is \\{times}. The secondary codes start at 30 so that -they don't overlap with the type codes; some type codes (e.g., \\{string% -\_type}) -are used as operators as well as type identifications. - -\Y\P\D \37$\\{true\_code}=30$\C{operation code for \.{true}}\par -\P\D \37$\\{false\_code}=31$\C{operation code for \.{false}}\par -\P\D \37$\\{null\_picture\_code}=32$\C{operation code for \.{nullpicture}}\par -\P\D \37$\\{null\_pen\_code}=33$\C{operation code for \.{nullpen}}\par -\P\D \37$\\{job\_name\_op}=34$\C{operation code for \.{jobname}}\par -\P\D \37$\\{read\_string\_op}=35$\C{operation code for \.{readstring}}\par -\P\D \37$\\{pen\_circle}=36$\C{operation code for \.{pencircle}}\par -\P\D \37$\\{normal\_deviate}=37$\C{operation code for \.{normaldeviate}}\par -\P\D \37$\\{odd\_op}=38$\C{operation code for \.{odd}}\par -\P\D \37$\\{known\_op}=39$\C{operation code for \.{known}}\par -\P\D \37$\\{unknown\_op}=40$\C{operation code for \.{unknown}}\par -\P\D \37$\\{not\_op}=41$\C{operation code for \.{not}}\par -\P\D \37$\\{decimal}=42$\C{operation code for \.{decimal}}\par -\P\D \37$\\{reverse}=43$\C{operation code for \.{reverse}}\par -\P\D \37$\\{make\_path\_op}=44$\C{operation code for \.{makepath}}\par -\P\D \37$\\{make\_pen\_op}=45$\C{operation code for \.{makepen}}\par -\P\D \37$\\{total\_weight\_op}=46$\C{operation code for \.{totalweight}}\par -\P\D \37$\\{oct\_op}=47$\C{operation code for \.{oct}}\par -\P\D \37$\\{hex\_op}=48$\C{operation code for \.{hex}}\par -\P\D \37$\\{ASCII\_op}=49$\C{operation code for \.{ASCII}}\par -\P\D \37$\\{char\_op}=50$\C{operation code for \.{char}}\par -\P\D \37$\\{length\_op}=51$\C{operation code for \.{length}}\par -\P\D \37$\\{turning\_op}=52$\C{operation code for \.{turningnumber}}\par -\P\D \37$\\{x\_part}=53$\C{operation code for \.{xpart}}\par -\P\D \37$\\{y\_part}=54$\C{operation code for \.{ypart}}\par -\P\D \37$\\{xx\_part}=55$\C{operation code for \.{xxpart}}\par -\P\D \37$\\{xy\_part}=56$\C{operation code for \.{xypart}}\par -\P\D \37$\\{yx\_part}=57$\C{operation code for \.{yxpart}}\par -\P\D \37$\\{yy\_part}=58$\C{operation code for \.{yypart}}\par -\P\D \37$\\{sqrt\_op}=59$\C{operation code for \.{sqrt}}\par -\P\D \37$\\{m\_exp\_op}=60$\C{operation code for \.{mexp}}\par -\P\D \37$\\{m\_log\_op}=61$\C{operation code for \.{mlog}}\par -\P\D \37$\\{sin\_d\_op}=62$\C{operation code for \.{sind}}\par -\P\D \37$\\{cos\_d\_op}=63$\C{operation code for \.{cosd}}\par -\P\D \37$\\{floor\_op}=64$\C{operation code for \.{floor}}\par -\P\D \37$\\{uniform\_deviate}=65$\C{operation code for \.{uniformdeviate}}\par -\P\D \37$\\{char\_exists\_op}=66$\C{operation code for \.{charexists}}\par -\P\D \37$\\{angle\_op}=67$\C{operation code for \.{angle}}\par -\P\D \37$\\{cycle\_op}=68$\C{operation code for \.{cycle}}\par -\P\D \37$\\{plus}=69$\C{operation code for \.+}\par -\P\D \37$\\{minus}=70$\C{operation code for \.-}\par -\P\D \37$\\{times}=71$\C{operation code for \.*}\par -\P\D \37$\\{over}=72$\C{operation code for \./}\par -\P\D \37$\\{pythag\_add}=73$\C{operation code for \.{++}}\par -\P\D \37$\\{pythag\_sub}=74$\C{operation code for \.{+-+}}\par -\P\D \37$\\{or\_op}=75$\C{operation code for \.{or}}\par -\P\D \37$\\{and\_op}=76$\C{operation code for \.{and}}\par -\P\D \37$\\{less\_than}=77$\C{operation code for \.<}\par -\P\D \37$\\{less\_or\_equal}=78$\C{operation code for \.{<=}}\par -\P\D \37$\\{greater\_than}=79$\C{operation code for \.>}\par -\P\D \37$\\{greater\_or\_equal}=80$\C{operation code for \.{>=}}\par -\P\D \37$\\{equal\_to}=81$\C{operation code for \.=}\par -\P\D \37$\\{unequal\_to}=82$\C{operation code for \.{<>}}\par -\P\D \37$\\{concatenate}=83$\C{operation code for \.\&}\par -\P\D \37$\\{rotated\_by}=84$\C{operation code for \.{rotated}}\par -\P\D \37$\\{slanted\_by}=85$\C{operation code for \.{slanted}}\par -\P\D \37$\\{scaled\_by}=86$\C{operation code for \.{scaled}}\par -\P\D \37$\\{shifted\_by}=87$\C{operation code for \.{shifted}}\par -\P\D \37$\\{transformed\_by}=88$\C{operation code for \.{transformed}}\par -\P\D \37$\\{x\_scaled}=89$\C{operation code for \.{xscaled}}\par -\P\D \37$\\{y\_scaled}=90$\C{operation code for \.{yscaled}}\par -\P\D \37$\\{z\_scaled}=91$\C{operation code for \.{zscaled}}\par -\P\D \37$\\{intersect}=92$\C{operation code for \.{intersectiontimes}}\par -\P\D \37$\\{double\_dot}=93$\C{operation code for improper \.{..}}\par -\P\D \37$\\{substring\_of}=94$\C{operation code for \.{substring}}\par -\P\D \37$\\{min\_of}=\\{substring\_of}$\par -\P\D \37$\\{subpath\_of}=95$\C{operation code for \.{subpath}}\par -\P\D \37$\\{direction\_time\_of}=96$\C{operation code for \.{directiontime}}\par -\P\D \37$\\{point\_of}=97$\C{operation code for \.{point}}\par -\P\D \37$\\{precontrol\_of}=98$\C{operation code for \.{precontrol}}\par -\P\D \37$\\{postcontrol\_of}=99$\C{operation code for \.{postcontrol}}\par -\P\D \37$\\{pen\_offset\_of}=100$\C{operation code for \.{penoffset}}\par -\Y\P\4\&{procedure}\1\ \37$\\{print\_op}(\|c:\\{quarterword})$;\2\6 -\&{begin} \37\&{if} $\|c\L\\{numeric\_type}$ \1\&{then}\5 -$\\{print\_type}(\|c)$\6 -\4\&{else} \&{case} $\|c$ \1\&{of}\6 -\4\\{true\_code}: \37$\\{print}(\.{"true"})$;\6 -\4\\{false\_code}: \37$\\{print}(\.{"false"})$;\6 -\4\\{null\_picture\_code}: \37$\\{print}(\.{"nullpicture"})$;\6 -\4\\{null\_pen\_code}: \37$\\{print}(\.{"nullpen"})$;\6 -\4\\{job\_name\_op}: \37$\\{print}(\.{"jobname"})$;\6 -\4\\{read\_string\_op}: \37$\\{print}(\.{"readstring"})$;\6 -\4\\{pen\_circle}: \37$\\{print}(\.{"pencircle"})$;\6 -\4\\{normal\_deviate}: \37$\\{print}(\.{"normaldeviate"})$;\6 -\4\\{odd\_op}: \37$\\{print}(\.{"odd"})$;\6 -\4\\{known\_op}: \37$\\{print}(\.{"known"})$;\6 -\4\\{unknown\_op}: \37$\\{print}(\.{"unknown"})$;\6 -\4\\{not\_op}: \37$\\{print}(\.{"not"})$;\6 -\4\\{decimal}: \37$\\{print}(\.{"decimal"})$;\6 -\4\\{reverse}: \37$\\{print}(\.{"reverse"})$;\6 -\4\\{make\_path\_op}: \37$\\{print}(\.{"makepath"})$;\6 -\4\\{make\_pen\_op}: \37$\\{print}(\.{"makepen"})$;\6 -\4\\{total\_weight\_op}: \37$\\{print}(\.{"totalweight"})$;\6 -\4\\{oct\_op}: \37$\\{print}(\.{"oct"})$;\6 -\4\\{hex\_op}: \37$\\{print}(\.{"hex"})$;\6 -\4\\{ASCII\_op}: \37$\\{print}(\.{"ASCII"})$;\6 -\4\\{char\_op}: \37$\\{print}(\.{"char"})$;\6 -\4\\{length\_op}: \37$\\{print}(\.{"length"})$;\6 -\4\\{turning\_op}: \37$\\{print}(\.{"turningnumber"})$;\6 -\4\\{x\_part}: \37$\\{print}(\.{"xpart"})$;\6 -\4\\{y\_part}: \37$\\{print}(\.{"ypart"})$;\6 -\4\\{xx\_part}: \37$\\{print}(\.{"xxpart"})$;\6 -\4\\{xy\_part}: \37$\\{print}(\.{"xypart"})$;\6 -\4\\{yx\_part}: \37$\\{print}(\.{"yxpart"})$;\6 -\4\\{yy\_part}: \37$\\{print}(\.{"yypart"})$;\6 -\4\\{sqrt\_op}: \37$\\{print}(\.{"sqrt"})$;\6 -\4\\{m\_exp\_op}: \37$\\{print}(\.{"mexp"})$;\6 -\4\\{m\_log\_op}: \37$\\{print}(\.{"mlog"})$;\6 -\4\\{sin\_d\_op}: \37$\\{print}(\.{"sind"})$;\6 -\4\\{cos\_d\_op}: \37$\\{print}(\.{"cosd"})$;\6 -\4\\{floor\_op}: \37$\\{print}(\.{"floor"})$;\6 -\4\\{uniform\_deviate}: \37$\\{print}(\.{"uniformdeviate"})$;\6 -\4\\{char\_exists\_op}: \37$\\{print}(\.{"charexists"})$;\6 -\4\\{angle\_op}: \37$\\{print}(\.{"angle"})$;\6 -\4\\{cycle\_op}: \37$\\{print}(\.{"cycle"})$;\6 -\4\\{plus}: \37$\\{print\_char}(\.{"+"})$;\6 -\4\\{minus}: \37$\\{print\_char}(\.{"-"})$;\6 -\4\\{times}: \37$\\{print\_char}(\.{"*"})$;\6 -\4\\{over}: \37$\\{print\_char}(\.{"/"})$;\6 -\4\\{pythag\_add}: \37$\\{print}(\.{"++"})$;\6 -\4\\{pythag\_sub}: \37$\\{print}(\.{"+-+"})$;\6 -\4\\{or\_op}: \37$\\{print}(\.{"or"})$;\6 -\4\\{and\_op}: \37$\\{print}(\.{"and"})$;\6 -\4\\{less\_than}: \37$\\{print\_char}(\.{"<"})$;\6 -\4\\{less\_or\_equal}: \37$\\{print}(\.{"<="})$;\6 -\4\\{greater\_than}: \37$\\{print\_char}(\.{">"})$;\6 -\4\\{greater\_or\_equal}: \37$\\{print}(\.{">="})$;\6 -\4\\{equal\_to}: \37$\\{print\_char}(\.{"="})$;\6 -\4\\{unequal\_to}: \37$\\{print}(\.{"<>"})$;\6 -\4\\{concatenate}: \37$\\{print}(\.{"\&"})$;\6 -\4\\{rotated\_by}: \37$\\{print}(\.{"rotated"})$;\6 -\4\\{slanted\_by}: \37$\\{print}(\.{"slanted"})$;\6 -\4\\{scaled\_by}: \37$\\{print}(\.{"scaled"})$;\6 -\4\\{shifted\_by}: \37$\\{print}(\.{"shifted"})$;\6 -\4\\{transformed\_by}: \37$\\{print}(\.{"transformed"})$;\6 -\4\\{x\_scaled}: \37$\\{print}(\.{"xscaled"})$;\6 -\4\\{y\_scaled}: \37$\\{print}(\.{"yscaled"})$;\6 -\4\\{z\_scaled}: \37$\\{print}(\.{"zscaled"})$;\6 -\4\\{intersect}: \37$\\{print}(\.{"intersectiontimes"})$;\6 -\4\\{substring\_of}: \37$\\{print}(\.{"substring"})$;\6 -\4\\{subpath\_of}: \37$\\{print}(\.{"subpath"})$;\6 -\4\\{direction\_time\_of}: \37$\\{print}(\.{"directiontime"})$;\6 -\4\\{point\_of}: \37$\\{print}(\.{"point"})$;\6 -\4\\{precontrol\_of}: \37$\\{print}(\.{"precontrol"})$;\6 -\4\\{postcontrol\_of}: \37$\\{print}(\.{"postcontrol"})$;\6 -\4\\{pen\_offset\_of}: \37$\\{print}(\.{"penoffset"})$;\6 -\4\&{othercases} \37$\\{print}(\.{".."})$\2\6 -\&{endcases};\2\6 -\&{end};\par -\fi - -\M190. \MF\ also has a bunch of internal parameters that a user might want to -fuss with. Every such parameter has an identifying code number, defined here. - -\Y\P\D \37$\\{tracing\_titles}=1$\C{show titles online when they appear}\par -\P\D \37$\\{tracing\_equations}=2$\C{show each variable when it becomes known}% -\par -\P\D \37$\\{tracing\_capsules}=3$\C{show capsules too}\par -\P\D \37$\\{tracing\_choices}=4$\C{show the control points chosen for paths}\par -\P\D \37$\\{tracing\_specs}=5$\C{show subdivision of paths into octants before -digitizing}\par -\P\D \37$\\{tracing\_pens}=6$\C{show details of pens that are made}\par -\P\D \37$\\{tracing\_commands}=7$\C{show commands and operations before they -are performed}\par -\P\D \37$\\{tracing\_restores}=8$\C{show when a variable or internal is -restored}\par -\P\D \37$\\{tracing\_macros}=9$\C{show macros before they are expanded}\par -\P\D \37$\\{tracing\_edges}=10$\C{show digitized edges as they are computed}\par -\P\D \37$\\{tracing\_output}=11$\C{show digitized edges as they are output}\par -\P\D \37$\\{tracing\_stats}=12$\C{show memory usage at end of job}\par -\P\D \37$\\{tracing\_online}=13$\C{show long diagnostics on terminal and in the -log file}\par -\P\D \37$\\{year}=14$\C{the current year (e.g., 1984)}\par -\P\D \37$\\{month}=15$\C{the current month (e.g, 3 $\equiv$ March)}\par -\P\D \37$\\{day}=16$\C{the current day of the month}\par -\P\D \37$\\{time}=17$\C{the number of minutes past midnight when this job -started}\par -\P\D \37$\\{char\_code}=18$\C{the number of the next character to be output}\par -\P\D \37$\\{char\_ext}=19$\C{the extension code of the next character to be -output}\par -\P\D \37$\\{char\_wd}=20$\C{the width of the next character to be output}\par -\P\D \37$\\{char\_ht}=21$\C{the height of the next character to be output}\par -\P\D \37$\\{char\_dp}=22$\C{the depth of the next character to be output}\par -\P\D \37$\\{char\_ic}=23$\C{the italic correction of the next character to be -output}\par -\P\D \37$\\{char\_dx}=24$\C{the device's $x$ movement for the next character, -in pixels}\par -\P\D \37$\\{char\_dy}=25$\C{the device's $y$ movement for the next character, -in pixels}\par -\P\D \37$\\{design\_size}=26$\C{the unit of measure used for $\\{char\_wd}\to% -\\{char\_ic}$, in points}\par -\P\D \37$\\{hppp}=27$\C{the number of horizontal pixels per point}\par -\P\D \37$\\{vppp}=28$\C{the number of vertical pixels per point}\par -\P\D \37$\\{x\_offset}=29$\C{horizontal displacement of shipped-out characters}% -\par -\P\D \37$\\{y\_offset}=30$\C{vertical displacement of shipped-out characters}% -\par -\P\D \37$\\{pausing}=31$\C{positive to display lines on the terminal before -they are read}\par -\P\D \37$\\{showstopping}=32$\C{positive to stop after each \&{show} command}% -\par -\P\D \37$\\{fontmaking}=33$\C{positive if font metric output is to be produced}% -\par -\P\D \37$\\{proofing}=34$\C{positive for proof mode, negative to suppress -output}\par -\P\D \37$\\{smoothing}=35$\C{positive if moves are to be ``smoothed''}\par -\P\D \37$\\{autorounding}=36$\C{controls path modification to ``good'' points}% -\par -\P\D \37$\\{granularity}=37$\C{autorounding uses this pixel size}\par -\P\D \37$\\{fillin}=38$\C{extra darkness of diagonal lines}\par -\P\D \37$\\{turning\_check}=39$\C{controls reorientation of clockwise paths}\par -\P\D \37$\\{warning\_check}=40$\C{controls error message when variable value is -large}\par -\P\D \37$\\{boundary\_char}=41$\C{the right boundary character for ligatures}% -\par -\P\D \37$\\{max\_given\_internal}=41$\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{internal}: \37\&{array} $[1\to\\{max\_internal}]$ \1\&{of}\5 -\\{scaled};\C{the values of internal quantities}\2\6 -\4\\{int\_name}: \37\&{array} $[1\to\\{max\_internal}]$ \1\&{of}\5 -\\{str\_number};\C{their names}\2\6 -\4\\{int\_ptr}: \37$\\{max\_given\_internal}\to\\{max\_internal}$;\C{the -maximum internal quantity defined so far}\par -\fi - -\M191. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -\&{for} $\|k\K1\mathrel{\&{to}}\\{max\_given\_internal}$ \1\&{do}\5 -$\\{internal}[\|k]\K0$;\2\6 -$\\{int\_ptr}\K\\{max\_given\_internal}$;\par -\fi - -\M192. The symbolic names for internal quantities are put into \MF's hash table -by using a routine called \\{primitive}, which will be defined later. Let us -enter them now, so that we don't have to list all those names again -anywhere else. - -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\S$\6 -$\\{primitive}(\.{"tracingtitles"},\39\\{internal\_quantity},\39\\{tracing% -\_titles})$;\6 -$\\{primitive}(\.{"tracingequations"},\39\\{internal\_quantity},\39\\{tracing% -\_equations})$;\6 -$\\{primitive}(\.{"tracingcapsules"},\39\\{internal\_quantity},\39\\{tracing% -\_capsules})$;\6 -$\\{primitive}(\.{"tracingchoices"},\39\\{internal\_quantity},\39\\{tracing% -\_choices})$;\6 -$\\{primitive}(\.{"tracingspecs"},\39\\{internal\_quantity},\39\\{tracing% -\_specs})$;\6 -$\\{primitive}(\.{"tracingpens"},\39\\{internal\_quantity},\39\\{tracing% -\_pens})$;\6 -$\\{primitive}(\.{"tracingcommands"},\39\\{internal\_quantity},\39\\{tracing% -\_commands})$;\6 -$\\{primitive}(\.{"tracingrestores"},\39\\{internal\_quantity},\39\\{tracing% -\_restores})$;\6 -$\\{primitive}(\.{"tracingmacros"},\39\\{internal\_quantity},\39\\{tracing% -\_macros})$;\6 -$\\{primitive}(\.{"tracingedges"},\39\\{internal\_quantity},\39\\{tracing% -\_edges})$;\6 -$\\{primitive}(\.{"tracingoutput"},\39\\{internal\_quantity},\39\\{tracing% -\_output})$;\6 -$\\{primitive}(\.{"tracingstats"},\39\\{internal\_quantity},\39\\{tracing% -\_stats})$;\6 -$\\{primitive}(\.{"tracingonline"},\39\\{internal\_quantity},\39\\{tracing% -\_online})$;\6 -$\\{primitive}(\.{"year"},\39\\{internal\_quantity},\39\\{year})$;\6 -$\\{primitive}(\.{"month"},\39\\{internal\_quantity},\39\\{month})$;\6 -$\\{primitive}(\.{"day"},\39\\{internal\_quantity},\39\\{day})$;\6 -$\\{primitive}(\.{"time"},\39\\{internal\_quantity},\39\\{time})$;\6 -$\\{primitive}(\.{"charcode"},\39\\{internal\_quantity},\39\\{char\_code})$;\6 -$\\{primitive}(\.{"charext"},\39\\{internal\_quantity},\39\\{char\_ext})$;\6 -$\\{primitive}(\.{"charwd"},\39\\{internal\_quantity},\39\\{char\_wd})$;\6 -$\\{primitive}(\.{"charht"},\39\\{internal\_quantity},\39\\{char\_ht})$;\6 -$\\{primitive}(\.{"chardp"},\39\\{internal\_quantity},\39\\{char\_dp})$;\6 -$\\{primitive}(\.{"charic"},\39\\{internal\_quantity},\39\\{char\_ic})$;\6 -$\\{primitive}(\.{"chardx"},\39\\{internal\_quantity},\39\\{char\_dx})$;\6 -$\\{primitive}(\.{"chardy"},\39\\{internal\_quantity},\39\\{char\_dy})$;\6 -$\\{primitive}(\.{"designsize"},\39\\{internal\_quantity},\39\\{design% -\_size})$;\6 -$\\{primitive}(\.{"hppp"},\39\\{internal\_quantity},\39\\{hppp})$;\6 -$\\{primitive}(\.{"vppp"},\39\\{internal\_quantity},\39\\{vppp})$;\6 -$\\{primitive}(\.{"xoffset"},\39\\{internal\_quantity},\39\\{x\_offset})$;\6 -$\\{primitive}(\.{"yoffset"},\39\\{internal\_quantity},\39\\{y\_offset})$;\6 -$\\{primitive}(\.{"pausing"},\39\\{internal\_quantity},\39\\{pausing})$;\6 -$\\{primitive}(\.{"showstopping"},\39\\{internal\_quantity},\39% -\\{showstopping})$;\6 -$\\{primitive}(\.{"fontmaking"},\39\\{internal\_quantity},\39\\{fontmaking})$;\6 -$\\{primitive}(\.{"proofing"},\39\\{internal\_quantity},\39\\{proofing})$;\6 -$\\{primitive}(\.{"smoothing"},\39\\{internal\_quantity},\39\\{smoothing})$;\6 -$\\{primitive}(\.{"autorounding"},\39\\{internal\_quantity},\39% -\\{autorounding})$;\6 -$\\{primitive}(\.{"granularity"},\39\\{internal\_quantity},\39% -\\{granularity})$;\6 -$\\{primitive}(\.{"fillin"},\39\\{internal\_quantity},\39\\{fillin})$;\6 -$\\{primitive}(\.{"turningcheck"},\39\\{internal\_quantity},\39\\{turning% -\_check})$;\6 -$\\{primitive}(\.{"warningcheck"},\39\\{internal\_quantity},\39\\{warning% -\_check})$;\6 -$\\{primitive}(\.{"boundarychar"},\39\\{internal\_quantity},\39\\{boundary% -\_char})$;\par -\As211, 683, 688, 695, 709, 740, 893, 1013, 1018, 1024, 1027, 1037, 1052, 1079, -1101, 1108\ETs1176. -\U1210.\fi - -\M193. Well, we do have to list the names one more time, for use in symbolic -printouts. - -\Y\P$\4\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}\S$\6 -$\\{int\_name}[\\{tracing\_titles}]\K\.{"tracingtitles"}$;\5 -$\\{int\_name}[\\{tracing\_equations}]\K\.{"tracingequations"}$;\5 -$\\{int\_name}[\\{tracing\_capsules}]\K\.{"tracingcapsules"}$;\5 -$\\{int\_name}[\\{tracing\_choices}]\K\.{"tracingchoices"}$;\5 -$\\{int\_name}[\\{tracing\_specs}]\K\.{"tracingspecs"}$;\5 -$\\{int\_name}[\\{tracing\_pens}]\K\.{"tracingpens"}$;\5 -$\\{int\_name}[\\{tracing\_commands}]\K\.{"tracingcommands"}$;\5 -$\\{int\_name}[\\{tracing\_restores}]\K\.{"tracingrestores"}$;\5 -$\\{int\_name}[\\{tracing\_macros}]\K\.{"tracingmacros"}$;\5 -$\\{int\_name}[\\{tracing\_edges}]\K\.{"tracingedges"}$;\5 -$\\{int\_name}[\\{tracing\_output}]\K\.{"tracingoutput"}$;\5 -$\\{int\_name}[\\{tracing\_stats}]\K\.{"tracingstats"}$;\5 -$\\{int\_name}[\\{tracing\_online}]\K\.{"tracingonline"}$;\5 -$\\{int\_name}[\\{year}]\K\.{"year"}$;\5 -$\\{int\_name}[\\{month}]\K\.{"month"}$;\5 -$\\{int\_name}[\\{day}]\K\.{"day"}$;\5 -$\\{int\_name}[\\{time}]\K\.{"time"}$;\5 -$\\{int\_name}[\\{char\_code}]\K\.{"charcode"}$;\5 -$\\{int\_name}[\\{char\_ext}]\K\.{"charext"}$;\5 -$\\{int\_name}[\\{char\_wd}]\K\.{"charwd"}$;\5 -$\\{int\_name}[\\{char\_ht}]\K\.{"charht"}$;\5 -$\\{int\_name}[\\{char\_dp}]\K\.{"chardp"}$;\5 -$\\{int\_name}[\\{char\_ic}]\K\.{"charic"}$;\5 -$\\{int\_name}[\\{char\_dx}]\K\.{"chardx"}$;\5 -$\\{int\_name}[\\{char\_dy}]\K\.{"chardy"}$;\5 -$\\{int\_name}[\\{design\_size}]\K\.{"designsize"}$;\5 -$\\{int\_name}[\\{hppp}]\K\.{"hppp"}$;\5 -$\\{int\_name}[\\{vppp}]\K\.{"vppp"}$;\5 -$\\{int\_name}[\\{x\_offset}]\K\.{"xoffset"}$;\5 -$\\{int\_name}[\\{y\_offset}]\K\.{"yoffset"}$;\5 -$\\{int\_name}[\\{pausing}]\K\.{"pausing"}$;\5 -$\\{int\_name}[\\{showstopping}]\K\.{"showstopping"}$;\5 -$\\{int\_name}[\\{fontmaking}]\K\.{"fontmaking"}$;\5 -$\\{int\_name}[\\{proofing}]\K\.{"proofing"}$;\5 -$\\{int\_name}[\\{smoothing}]\K\.{"smoothing"}$;\5 -$\\{int\_name}[\\{autorounding}]\K\.{"autorounding"}$;\5 -$\\{int\_name}[\\{granularity}]\K\.{"granularity"}$;\5 -$\\{int\_name}[\\{fillin}]\K\.{"fillin"}$;\5 -$\\{int\_name}[\\{turning\_check}]\K\.{"turningcheck"}$;\5 -$\\{int\_name}[\\{warning\_check}]\K\.{"warningcheck"}$;\5 -$\\{int\_name}[\\{boundary\_char}]\K\.{"boundarychar"}$;\par -\fi - -\M194. The following procedure, which is called just before \MF\ initializes -its -input and output, establishes the initial values of the date and time. -Since standard \PASCAL\ cannot provide such information, something special -is needed. The program here simply specifies July 4, 1776, at noon; but -users probably want a better approximation to the truth. - -Note that the values are \\{scaled} integers. Hence \MF\ can no longer -be used after the year 32767. - -\Y\P\4\&{procedure}\1\ \37\\{fix\_date\_and\_time};\2\6 -\&{begin} \37$\\{internal}[\\{time}]\K12\ast60\ast\\{unity}$;\C{minutes since -midnight}\6 -$\\{internal}[\\{day}]\K4\ast\\{unity}$;\C{fourth day of the month}\6 -$\\{internal}[\\{month}]\K7\ast\\{unity}$;\C{seventh month of the year}\6 -$\\{internal}[\\{year}]\K1776\ast\\{unity}$;\C{Anno Domini}\6 -\&{end};\par -\fi - -\M195. \MF\ is occasionally supposed to print diagnostic information that -goes only into the transcript file, unless \\{tracing\_online} is positive. -Now that we have defined \\{tracing\_online} we can define -two routines that adjust the destination of print commands: - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{begin\_diagnostic};\C{prepare to do some tracing}\2\6 -\&{begin} \37$\\{old\_setting}\K\\{selector}$;\6 -\&{if} $(\\{internal}[\\{tracing\_online}]\L0)\W(\\{selector}=\\{term\_and% -\_log})$ \1\&{then}\6 -\&{begin} \37$\\{decr}(\\{selector})$;\6 -\&{if} $\\{history}=\\{spotless}$ \1\&{then}\5 -$\\{history}\K\\{warning\_issued}$;\2\6 -\&{end};\2\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{end\_diagnostic}(\\{blank\_line}:\\{boolean})$;% -\C{restore proper conditions after tracing}\2\6 -\&{begin} \37$\\{print\_nl}(\.{""})$;\6 -\&{if} $\\{blank\_line}$ \1\&{then}\5 -\\{print\_ln};\2\6 -$\\{selector}\K\\{old\_setting}$;\6 -\&{end};\par -\fi - -\M196. Of course we had better declare another global variable, if the previous -routines are going to work. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{old\_setting}: \37$0\to\\{max\_selector}$;\par -\fi - -\M197. We will occasionally use \\{begin\_diagnostic} in connection with -line-number -printing, as follows. (The parameter \|s is typically \.{"Path"} or -\.{"Cycle\ spec"}, etc.) - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_diagnostic}(\|s,\39\|t:\\{str\_number};\,\35% -\\{nuline}:\\{boolean})$;\2\6 -\&{begin} \37\\{begin\_diagnostic};\6 -\&{if} $\\{nuline}$ \1\&{then}\5 -$\\{print\_nl}(\|s)$\ \&{else} $\\{print}(\|s)$;\2\6 -$\\{print}(\.{"\ at\ line\ "})$;\5 -$\\{print\_int}(\\{line})$;\5 -$\\{print}(\|t)$;\5 -$\\{print\_char}(\.{":"})$;\6 -\&{end};\par -\fi - -\M198. The 256 \\{ASCII\_code} characters are grouped into classes by means of -the \\{char\_class} table. Individual class numbers have no semantic -or syntactic significance, except in a few instances defined here. -There's also \\{max\_class}, which can be used as a basis for additional -class numbers in nonstandard extensions of \MF. - -\Y\P\D \37$\\{digit\_class}=0$\C{the class number of \.{0123456789}}\par -\P\D \37$\\{period\_class}=1$\C{the class number of `\..'}\par -\P\D \37$\\{space\_class}=2$\C{the class number of spaces and nonstandard -characters}\par -\P\D \37$\\{percent\_class}=3$\C{the class number of `\.\%'}\par -\P\D \37$\\{string\_class}=4$\C{the class number of `\."'}\par -\P\D \37$\\{right\_paren\_class}=8$\C{the class number of `\.)'}\par -\P\D \37$\\{isolated\_classes}\S5,\396,\397,\398$\C{characters that make -length-one tokens only}\par -\P\D \37$\\{letter\_class}=9$\C{letters and the underline character}\par -\P\D \37$\\{left\_bracket\_class}=17$\C{`\.['}\par -\P\D \37$\\{right\_bracket\_class}=18$\C{`\.]'}\par -\P\D \37$\\{invalid\_class}=20$\C{bad character in the input}\par -\P\D \37$\\{max\_class}=20$\C{the largest class number}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{char\_class}: \37\&{array} $[\\{ASCII\_code}]$ \1\&{of}\5 -$0\to\\{max\_class}$;\C{the class numbers}\2\par -\fi - -\M199. If changes are made to accommodate non-ASCII character sets, they should -follow the guidelines in Appendix~C of {\sl The {\logos METAFONT\/}book}. - -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -\&{for} $\|k\K\.{"0"}\mathrel{\&{to}}\.{"9"}$ \1\&{do}\5 -$\\{char\_class}[\|k]\K\\{digit\_class}$;\2\6 -$\\{char\_class}[\.{"."}]\K\\{period\_class}$;\5 -$\\{char\_class}[\.{"\ "}]\K\\{space\_class}$;\5 -$\\{char\_class}[\.{"\%"}]\K\\{percent\_class}$;\5 -$\\{char\_class}[\.{""}\.{""}]\K\\{string\_class}$;\6 -$\\{char\_class}[\.{","}]\K5$;\5 -$\\{char\_class}[\.{";"}]\K6$;\5 -$\\{char\_class}[\.{"("}]\K7$;\5 -$\\{char\_class}[\.{")"}]\K\\{right\_paren\_class}$;\6 -\&{for} $\|k\K\.{"A"}\mathrel{\&{to}}\.{"Z"}$ \1\&{do}\5 -$\\{char\_class}[\|k]\K\\{letter\_class}$;\2\6 -\&{for} $\|k\K\.{"a"}\mathrel{\&{to}}\.{"z"}$ \1\&{do}\5 -$\\{char\_class}[\|k]\K\\{letter\_class}$;\2\6 -$\\{char\_class}[\.{"\_"}]\K\\{letter\_class}$;\6 -$\\{char\_class}[\.{"<"}]\K10$;\5 -$\\{char\_class}[\.{"="}]\K10$;\5 -$\\{char\_class}[\.{">"}]\K10$;\5 -$\\{char\_class}[\.{":"}]\K10$;\5 -$\\{char\_class}[\.{"|"}]\K10$;\6 -$\\{char\_class}[\.{"\`"}]\K11$;\5 -$\\{char\_class}[\.{"\'"}]\K11$;\6 -$\\{char\_class}[\.{"+"}]\K12$;\5 -$\\{char\_class}[\.{"-"}]\K12$;\6 -$\\{char\_class}[\.{"/"}]\K13$;\5 -$\\{char\_class}[\.{"*"}]\K13$;\5 -$\\{char\_class}[\.{"\\"}]\K13$;\6 -$\\{char\_class}[\.{"!"}]\K14$;\5 -$\\{char\_class}[\.{"?"}]\K14$;\6 -$\\{char\_class}[\.{"\#"}]\K15$;\5 -$\\{char\_class}[\.{"\&"}]\K15$;\5 -$\\{char\_class}[\.{"@"}]\K15$;\5 -$\\{char\_class}[\.{"\$"}]\K15$;\6 -$\\{char\_class}[\.{"\^"}]\K16$;\5 -$\\{char\_class}[\.{"\~"}]\K16$;\6 -$\\{char\_class}[\.{"["}]\K\\{left\_bracket\_class}$;\5 -$\\{char\_class}[\.{"]"}]\K\\{right\_bracket\_class}$;\6 -$\\{char\_class}[\.{"\{"}]\K19$;\5 -$\\{char\_class}[\.{"\}"}]\K19$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}\.{"\ "}-1$ \1\&{do}\5 -$\\{char\_class}[\|k]\K\\{invalid\_class}$;\2\6 -\&{for} $\|k\K127\mathrel{\&{to}}255$ \1\&{do}\5 -$\\{char\_class}[\|k]\K\\{invalid\_class}$;\2\par -\fi - -\N200. \[13] The hash table. -Symbolic tokens are stored and retrieved by means of a fairly standard hash -table algorithm called the method of ``coalescing lists'' (cf.\ Algorithm 6.4C -in {\sl The Art of Computer Programming\/}). Once a symbolic token enters the -table, it is never removed. - -The actual sequence of characters forming a symbolic token is -stored in the \\{str\_pool} array together with all the other strings. An -auxiliary array \\{hash} consists of items with two halfword fields per -word. The first of these, called $\\{next}(\|p)$, points to the next identifier -belonging to the same coalesced list as the identifier corresponding to~\|p; -and the other, called $\\{text}(\|p)$, points to the \\{str\_start} entry for -\|p's identifier. If position~\|p of the hash table is empty, we have -$\\{text}(\|p)=0$; if position \|p is either empty or the end of a coalesced -hash list, we have $\\{next}(\|p)=0$. - -An auxiliary pointer variable called \\{hash\_used} is maintained in such a -way that all locations $\|p\G\\{hash\_used}$ are nonempty. The global variable -\\{st\_count} tells how many symbolic tokens have been defined, if statistics -are being kept. - -The first 256 locations of \\{hash} are reserved for symbols of length one. - -There's a parallel array called \\{eqtb} that contains the current equivalent -values of each symbolic token. The entries of this array consist of -two halfwords called \\{eq\_type} (a command code) and \\{equiv} (a secondary -piece of information that qualifies the \\{eq\_type}). - -\Y\P\D \37$\\{next}(\#)\S\\{hash}[\#].\\{lh}$\C{link for coalesced lists}\par -\P\D \37$\\{text}(\#)\S\\{hash}[\#].\\{rh}$\C{string number for symbolic token -name}\par -\P\D \37$\\{eq\_type}(\#)\S\\{eqtb}[\#].\\{lh}$\C{the current ``meaning'' of a -symbolic token}\par -\P\D \37$\\{equiv}(\#)\S\\{eqtb}[\#].\\{rh}$\C{parametric part of a token's -meaning}\par -\P\D \37$\\{hash\_base}=257$\C{hashing actually starts here}\par -\P\D \37$\\{hash\_is\_full}\S(\\{hash\_used}=\\{hash\_base})$\C{are all -positions occupied?}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{hash\_used}: \37\\{pointer};\C{allocation pointer for \\{hash}}\6 -\4\\{st\_count}: \37\\{integer};\C{total number of known identifiers}\par -\fi - -\M201. Certain entries in the hash table are ``frozen'' and not redefinable, -since they are used in error recovery. - -\Y\P\D \37$\\{hash\_top}\S\\{hash\_base}+\\{hash\_size}$\C{the first location -of the frozen area}\par -\P\D \37$\\{frozen\_inaccessible}\S\\{hash\_top}$\C{\\{hash} location to -protect the frozen area}\par -\P\D \37$\\{frozen\_repeat\_loop}\S\\{hash\_top}+1$\C{\\{hash} location of a -loop-repeat token}\par -\P\D \37$\\{frozen\_right\_delimiter}\S\\{hash\_top}+2$\C{\\{hash} location of -a permanent `\.)'}\par -\P\D \37$\\{frozen\_left\_bracket}\S\\{hash\_top}+3$\C{\\{hash} location of a -permanent `\.['}\par -\P\D \37$\\{frozen\_slash}\S\\{hash\_top}+4$\C{\\{hash} location of a permanent -`\./'}\par -\P\D \37$\\{frozen\_colon}\S\\{hash\_top}+5$\C{\\{hash} location of a permanent -`\.:'}\par -\P\D \37$\\{frozen\_semicolon}\S\\{hash\_top}+6$\C{\\{hash} location of a -permanent `\.;'}\par -\P\D \37$\\{frozen\_end\_for}\S\\{hash\_top}+7$\C{\\{hash} location of a -permanent \&{endfor}}\par -\P\D \37$\\{frozen\_end\_def}\S\\{hash\_top}+8$\C{\\{hash} location of a -permanent \&{enddef}}\par -\P\D \37$\\{frozen\_fi}\S\\{hash\_top}+9$\C{\\{hash} location of a permanent % -\&{fi}}\par -\P\D \37$\\{frozen\_end\_group}\S\\{hash\_top}+10$\C{\\{hash} location of a -permanent `\.{endgroup}'}\par -\P\D \37$\\{frozen\_bad\_vardef}\S\\{hash\_top}+11$\C{\\{hash} location of `% -\.{a bad variable}'}\par -\P\D \37$\\{frozen\_undefined}\S\\{hash\_top}+12$\C{\\{hash} location that -never gets defined}\par -\P\D \37$\\{hash\_end}\S\\{hash\_top}+12$\C{the actual size of the \\{hash} and -\\{eqtb} arrays}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{hash}: \37\&{array} $[1\to\\{hash\_end}]$ \1\&{of}\5 -\\{two\_halves};\C{the hash table}\2\6 -\4\\{eqtb}: \37\&{array} $[1\to\\{hash\_end}]$ \1\&{of}\5 -\\{two\_halves};\C{the equivalents}\2\par -\fi - -\M202. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{next}(1)\K0$;\5 -$\\{text}(1)\K0$;\5 -$\\{eq\_type}(1)\K\\{tag\_token}$;\5 -$\\{equiv}(1)\K\\{null}$;\6 -\&{for} $\|k\K2\mathrel{\&{to}}\\{hash\_end}$ \1\&{do}\6 -\&{begin} \37$\\{hash}[\|k]\K\\{hash}[1]$;\5 -$\\{eqtb}[\|k]\K\\{eqtb}[1]$;\6 -\&{end};\2\par -\fi - -\M203. \P$\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}% -\S$\6 -$\\{hash\_used}\K\\{frozen\_inaccessible}$;\C{nothing is used}\6 -$\\{st\_count}\K0$;\6 -$\\{text}(\\{frozen\_bad\_vardef})\K\.{"a\ bad\ variable"}$;\5 -$\\{text}(\\{frozen\_fi})\K\.{"fi"}$;\5 -$\\{text}(\\{frozen\_end\_group})\K\.{"endgroup"}$;\5 -$\\{text}(\\{frozen\_end\_def})\K\.{"enddef"}$;\5 -$\\{text}(\\{frozen\_end\_for})\K\.{"endfor"}$;\6 -$\\{text}(\\{frozen\_semicolon})\K\.{";"}$;\5 -$\\{text}(\\{frozen\_colon})\K\.{":"}$;\5 -$\\{text}(\\{frozen\_slash})\K\.{"/"}$;\5 -$\\{text}(\\{frozen\_left\_bracket})\K\.{"["}$;\5 -$\\{text}(\\{frozen\_right\_delimiter})\K\.{")"}$;\6 -$\\{text}(\\{frozen\_inaccessible})\K\.{"\ INACCESSIBLE"}$;\6 -$\\{eq\_type}(\\{frozen\_right\_delimiter})\K\\{right\_delimiter}$;\par -\fi - -\M204. \P$\X14:Check the ``constant'' values for consistency\X\mathrel{+}\S$\6 -\&{if} $\\{hash\_end}+\\{max\_internal}>\\{max\_halfword}$ \1\&{then}\5 -$\\{bad}\K21$;\2\par -\fi - -\M205. Here is the subroutine that searches the hash table for an identifier -that matches a given string of length~\|l appearing in $\\{buffer}[\|j\to(\|j+% -\|l-1)]$. If the identifier is not found, it is inserted; hence it -will always be found, and the corresponding hash table address -will be returned. - -\Y\P\4\&{function}\1\ \37$\\{id\_lookup}(\|j,\39\|l:\\{integer})$: \37% -\\{pointer};\C{search the hash table}\6 -\4\&{label} \37\\{found};\C{go here when you've found it}\6 -\4\&{var} \37\|h: \37\\{integer};\C{hash code}\6 -\|p: \37\\{pointer};\C{index in \\{hash} array}\6 -\|k: \37\\{pointer};\C{index in \\{buffer} array}\2\6 -\&{begin} \37\&{if} $\|l=1$ \1\&{then}\5 -\X206:Treat special case of length 1 and \&{goto} \\{found}\X;\2\6 -\X208:Compute the hash code \|h\X;\6 -$\|p\K\|h+\\{hash\_base}$;\C{we start searching here; note that $0\L\|h<\\{hash% -\_prime}$}\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\\{text}(\|p)>0$ \1\&{then}\6 -\&{if} $\\{length}(\\{text}(\|p))=\|l$ \1\&{then}\6 -\&{if} $\\{str\_eq\_buf}(\\{text}(\|p),\39\|j)$ \1\&{then}\5 -\&{goto} \37\\{found};\2\2\2\6 -\&{if} $\\{next}(\|p)=0$ \1\&{then}\5 -\X207:Insert a new symbolic token after \|p, then make \|p point to it and % -\&{goto} \\{found}\X;\2\6 -$\|p\K\\{next}(\|p)$;\6 -\&{end};\2\6 -\4\\{found}: \37$\\{id\_lookup}\K\|p$;\6 -\&{end};\par -\fi - -\M206. \P$\X206:Treat special case of length 1 and \&{goto} \\{found}\X\S$\6 -\&{begin} \37$\|p\K\\{buffer}[\|j]+1$;\5 -$\\{text}(\|p)\K\|p-1$;\5 -\&{goto} \37\\{found};\6 -\&{end}\par -\U205.\fi - -\M207. \P$\X207:Insert a new symbolic token after \|p, then make \|p point to -it and \&{goto} \\{found}\X\S$\6 -\&{begin} \37\&{if} $\\{text}(\|p)>0$ \1\&{then}\6 -\&{begin} \37\1\&{repeat} \37\&{if} $\\{hash\_is\_full}$ \1\&{then}\5 -$\\{overflow}(\.{"hash\ size"},\39\\{hash\_size})$;\2\6 -$\\{decr}(\\{hash\_used})$;\6 -\4\&{until}\5 -$\\{text}(\\{hash\_used})=0$;\C{search for an empty location in \\{hash}}\2\6 -$\\{next}(\|p)\K\\{hash\_used}$;\5 -$\|p\K\\{hash\_used}$;\6 -\&{end};\2\6 -$\\{str\_room}(\|l)$;\6 -\&{for} $\|k\K\|j\mathrel{\&{to}}\|j+\|l-1$ \1\&{do}\5 -$\\{append\_char}(\\{buffer}[\|k])$;\2\6 -$\\{text}(\|p)\K\\{make\_string}$;\5 -$\\{str\_ref}[\\{text}(\|p)]\K\\{max\_str\_ref}$;\6 -\&{stat} \37$\\{incr}(\\{st\_count})$;\ \&{tats}\6 -\&{goto} \37\\{found};\6 -\&{end}\par -\U205.\fi - -\M208. The value of \\{hash\_prime} should be roughly 85\pct! of \\{hash% -\_size}, and it -should be a prime number. The theory of hashing tells us to expect fewer -than two table probes, on the average, when the search is successful. -[See J.~S. Vitter, {\sl Journal of the ACM\/ \bf30} (1983), 231--258.] - -\Y\P$\4\X208:Compute the hash code \|h\X\S$\6 -$\|h\K\\{buffer}[\|j]$;\6 -\&{for} $\|k\K\|j+1\mathrel{\&{to}}\|j+\|l-1$ \1\&{do}\6 -\&{begin} \37$\|h\K\|h+\|h+\\{buffer}[\|k]$;\6 -\&{while} $\|h\G\\{hash\_prime}$ \1\&{do}\5 -$\|h\K\|h-\\{hash\_prime}$;\2\6 -\&{end}\2\par -\U205.\fi - -\M209. \P$\X209:Search \\{eqtb} for equivalents equal to \|p\X\S$\6 -\&{for} $\|q\K1\mathrel{\&{to}}\\{hash\_end}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{equiv}(\|q)=\|p$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"EQUIV("})$;\5 -$\\{print\_int}(\|q)$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\2\6 -\&{end}\2\par -\U185.\fi - -\M210. We need to put \MF's ``primitive'' symbolic tokens into the hash -table, together with their command code (which will be the \\{eq\_type}) -and an operand (which will be the \\{equiv}). The \\{primitive} procedure -does this, in a way that no \MF\ user can. The global value \\{cur\_sym} -contains the new \\{eqtb} pointer after \\{primitive} has acted. - -\Y\P\&{init} \37\&{procedure}\1\ \37$\\{primitive}(\|s:\\{str\_number};\,\35% -\|c:\\{halfword};\,\35\|o:\\{halfword})$;\6 -\4\&{var} \37\|k: \37\\{pool\_pointer};\C{index into \\{str\_pool}}\6 -\|j: \37\\{small\_number};\C{index into \\{buffer}}\6 -\|l: \37\\{small\_number};\C{length of the string}\2\6 -\&{begin} \37$\|k\K\\{str\_start}[\|s]$;\5 -$\|l\K\\{str\_start}[\|s+1]-\|k$;\C{we will move \|s into the (empty) % -\\{buffer}}\6 -\&{for} $\|j\K0\mathrel{\&{to}}\|l-1$ \1\&{do}\5 -$\\{buffer}[\|j]\K\\{so}(\\{str\_pool}[\|k+\|j])$;\2\6 -$\\{cur\_sym}\K\\{id\_lookup}(0,\39\|l)$;\6 -\&{if} $\|s\G256$ \1\&{then}\C{we don't want to have the string twice}\6 -\&{begin} \37$\\{flush\_string}(\\{str\_ptr}-1)$;\5 -$\\{text}(\\{cur\_sym})\K\|s$;\6 -\&{end};\2\6 -$\\{eq\_type}(\\{cur\_sym})\K\|c$;\5 -$\\{equiv}(\\{cur\_sym})\K\|o$;\6 -\&{end};\6 -\&{tini}\par -\fi - -\M211. Many of \MF's primitives need no \\{equiv}, since they are identifiable -by their \\{eq\_type} alone. These primitives are loaded into the hash table -as follows: - -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{".."},\39\\{path\_join},\390)$;\6 -$\\{primitive}(\.{"["},\39\\{left\_bracket},\390)$;\5 -$\\{eqtb}[\\{frozen\_left\_bracket}]\K\\{eqtb}[\\{cur\_sym}]$;\6 -$\\{primitive}(\.{"]"},\39\\{right\_bracket},\390)$;\6 -$\\{primitive}(\.{"\}"},\39\\{right\_brace},\390)$;\6 -$\\{primitive}(\.{"\{"},\39\\{left\_brace},\390)$;\6 -$\\{primitive}(\.{":"},\39\\{colon},\390)$;\5 -$\\{eqtb}[\\{frozen\_colon}]\K\\{eqtb}[\\{cur\_sym}]$;\6 -$\\{primitive}(\.{"::"},\39\\{double\_colon},\390)$;\6 -$\\{primitive}(\.{"||:"},\39\\{bchar\_label},\390)$;\6 -$\\{primitive}(\.{":="},\39\\{assignment},\390)$;\6 -$\\{primitive}(\.{","},\39\\{comma},\390)$;\6 -$\\{primitive}(\.{";"},\39\\{semicolon},\390)$;\5 -$\\{eqtb}[\\{frozen\_semicolon}]\K\\{eqtb}[\\{cur\_sym}]$;\6 -$\\{primitive}(\.{"\\"},\39\\{relax},\390)$;\7 -$\\{primitive}(\.{"addto"},\39\\{add\_to\_command},\390)$;\6 -$\\{primitive}(\.{"at"},\39\\{at\_token},\390)$;\6 -$\\{primitive}(\.{"atleast"},\39\\{at\_least},\390)$;\6 -$\\{primitive}(\.{"begingroup"},\39\\{begin\_group},\390)$;\5 -$\\{bg\_loc}\K\\{cur\_sym}$;\6 -$\\{primitive}(\.{"controls"},\39\\{controls},\390)$;\6 -$\\{primitive}(\.{"cull"},\39\\{cull\_command},\390)$;\6 -$\\{primitive}(\.{"curl"},\39\\{curl\_command},\390)$;\6 -$\\{primitive}(\.{"delimiters"},\39\\{delimiters},\390)$;\6 -$\\{primitive}(\.{"display"},\39\\{display\_command},\390)$;\6 -$\\{primitive}(\.{"endgroup"},\39\\{end\_group},\390)$;\5 -$\\{eqtb}[\\{frozen\_end\_group}]\K\\{eqtb}[\\{cur\_sym}]$;\5 -$\\{eg\_loc}\K\\{cur\_sym}$;\6 -$\\{primitive}(\.{"everyjob"},\39\\{every\_job\_command},\390)$;\6 -$\\{primitive}(\.{"exitif"},\39\\{exit\_test},\390)$;\6 -$\\{primitive}(\.{"expandafter"},\39\\{expand\_after},\390)$;\6 -$\\{primitive}(\.{"from"},\39\\{from\_token},\390)$;\6 -$\\{primitive}(\.{"inwindow"},\39\\{in\_window},\390)$;\6 -$\\{primitive}(\.{"interim"},\39\\{interim\_command},\390)$;\6 -$\\{primitive}(\.{"let"},\39\\{let\_command},\390)$;\6 -$\\{primitive}(\.{"newinternal"},\39\\{new\_internal},\390)$;\6 -$\\{primitive}(\.{"of"},\39\\{of\_token},\390)$;\6 -$\\{primitive}(\.{"openwindow"},\39\\{open\_window},\390)$;\6 -$\\{primitive}(\.{"randomseed"},\39\\{random\_seed},\390)$;\6 -$\\{primitive}(\.{"save"},\39\\{save\_command},\390)$;\6 -$\\{primitive}(\.{"scantokens"},\39\\{scan\_tokens},\390)$;\6 -$\\{primitive}(\.{"shipout"},\39\\{ship\_out\_command},\390)$;\6 -$\\{primitive}(\.{"skipto"},\39\\{skip\_to},\390)$;\6 -$\\{primitive}(\.{"step"},\39\\{step\_token},\390)$;\6 -$\\{primitive}(\.{"str"},\39\\{str\_op},\390)$;\6 -$\\{primitive}(\.{"tension"},\39\\{tension},\390)$;\6 -$\\{primitive}(\.{"to"},\39\\{to\_token},\390)$;\6 -$\\{primitive}(\.{"until"},\39\\{until\_token},\390)$;\par -\fi - -\M212. Each primitive has a corresponding inverse, so that it is possible to -display the cryptic numeric contents of \\{eqtb} in symbolic form. -Every call of \\{primitive} in this program is therefore accompanied by some -straightforward code that forms part of the \\{print\_cmd\_mod} routine -explained below. - -\Y\P$\4\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of primitives\X% -\S$\6 -\4\\{add\_to\_command}: \37$\\{print}(\.{"addto"})$;\6 -\4\\{assignment}: \37$\\{print}(\.{":="})$;\6 -\4\\{at\_least}: \37$\\{print}(\.{"atleast"})$;\6 -\4\\{at\_token}: \37$\\{print}(\.{"at"})$;\6 -\4\\{bchar\_label}: \37$\\{print}(\.{"||:"})$;\6 -\4\\{begin\_group}: \37$\\{print}(\.{"begingroup"})$;\6 -\4\\{colon}: \37$\\{print}(\.{":"})$;\6 -\4\\{comma}: \37$\\{print}(\.{","})$;\6 -\4\\{controls}: \37$\\{print}(\.{"controls"})$;\6 -\4\\{cull\_command}: \37$\\{print}(\.{"cull"})$;\6 -\4\\{curl\_command}: \37$\\{print}(\.{"curl"})$;\6 -\4\\{delimiters}: \37$\\{print}(\.{"delimiters"})$;\6 -\4\\{display\_command}: \37$\\{print}(\.{"display"})$;\6 -\4\\{double\_colon}: \37$\\{print}(\.{"::"})$;\6 -\4\\{end\_group}: \37$\\{print}(\.{"endgroup"})$;\6 -\4\\{every\_job\_command}: \37$\\{print}(\.{"everyjob"})$;\6 -\4\\{exit\_test}: \37$\\{print}(\.{"exitif"})$;\6 -\4\\{expand\_after}: \37$\\{print}(\.{"expandafter"})$;\6 -\4\\{from\_token}: \37$\\{print}(\.{"from"})$;\6 -\4\\{in\_window}: \37$\\{print}(\.{"inwindow"})$;\6 -\4\\{interim\_command}: \37$\\{print}(\.{"interim"})$;\6 -\4\\{left\_brace}: \37$\\{print}(\.{"\{"})$;\6 -\4\\{left\_bracket}: \37$\\{print}(\.{"["})$;\6 -\4\\{let\_command}: \37$\\{print}(\.{"let"})$;\6 -\4\\{new\_internal}: \37$\\{print}(\.{"newinternal"})$;\6 -\4\\{of\_token}: \37$\\{print}(\.{"of"})$;\6 -\4\\{open\_window}: \37$\\{print}(\.{"openwindow"})$;\6 -\4\\{path\_join}: \37$\\{print}(\.{".."})$;\6 -\4\\{random\_seed}: \37$\\{print}(\.{"randomseed"})$;\6 -\4\\{relax}: \37$\\{print\_char}(\.{"\\"})$;\6 -\4\\{right\_brace}: \37$\\{print}(\.{"\}"})$;\6 -\4\\{right\_bracket}: \37$\\{print}(\.{"]"})$;\6 -\4\\{save\_command}: \37$\\{print}(\.{"save"})$;\6 -\4\\{scan\_tokens}: \37$\\{print}(\.{"scantokens"})$;\6 -\4\\{semicolon}: \37$\\{print}(\.{";"})$;\6 -\4\\{ship\_out\_command}: \37$\\{print}(\.{"shipout"})$;\6 -\4\\{skip\_to}: \37$\\{print}(\.{"skipto"})$;\6 -\4\\{step\_token}: \37$\\{print}(\.{"step"})$;\6 -\4\\{str\_op}: \37$\\{print}(\.{"str"})$;\6 -\4\\{tension}: \37$\\{print}(\.{"tension"})$;\6 -\4\\{to\_token}: \37$\\{print}(\.{"to"})$;\6 -\4\\{until\_token}: \37$\\{print}(\.{"until"})$;\par -\As684, 689, 696, 710, 741, 894, 1014, 1019, 1025, 1028, 1038, 1043, 1053, -1080, 1102, 1109\ETs1180. -\U625.\fi - -\M213. We will deal with the other primitives later, at some point in the -program -where their \\{eq\_type} and \\{equiv} values are more meaningful. For -example, -the primitives for macro definitions will be loaded when we consider the -routines that define macros. -It is easy to find where each particular -primitive was treated by looking in the index at the end; for example, the -section where \.{"def"} entered \\{eqtb} is listed under `\&{def} primitive'. - -\fi - -\N214. \[14] Token lists. -A \MF\ token is either symbolic or numeric or a string, or it denotes -a macro parameter or capsule; so there are five corresponding ways to encode it -internally: (1)~A symbolic token whose hash code is~\|p -is represented by the number \|p, in the \\{info} field of a single-word -node in~\\{mem}. (2)~A numeric token whose \\{scaled} value is~\|v is -represented in a two-word node of~\\{mem}; the \\{type} field is \\{known}, -the \\{name\_type} field is \\{token}, and the \\{value} field holds~\|v. -The fact that this token appears in a two-word node rather than a -one-word node is, of course, clear from the node address. -(3)~A string token is also represented in a two-word node; the \\{type} -field is \\{string\_type}, the \\{name\_type} field is \\{token}, and the -\\{value} field holds the corresponding \\{str\_number}. (4)~Capsules have -$\\{name\_type}=\\{capsule}$, and their \\{type} and \\{value} fields represent -arbitrary values (in ways to be explained later). (5)~Macro parameters -are like symbolic tokens in that they appear in \\{info} fields of -one-word nodes. The $k$th parameter is represented by $\\{expr\_base}+\|k$ if -it -is of type \&{expr}, or by $\\{suffix\_base}+\|k$ if it is of type \&{suffix}, -or -by $\\{text\_base}+\|k$ if it is of type \&{text}. (Here $0\L\|k<\\{param% -\_size}$.) -Actual values of these parameters are kept in a separate stack, as we will -see later. The constants \\{expr\_base}, \\{suffix\_base}, and \\{text\_base} -are, -of course, chosen so that there will be no confusion between symbolic -tokens and parameters of various types. - -It turns out that $\\{value}(\\{null})=0$, because $\\{null}=\\{null\_coords}$; -we will make use of this coincidence later. - -Incidentally, while we're speaking of coincidences, we might note that -the `\\{type}' field of a node has nothing to do with ``type'' in a -printer's sense. It's curious that the same word is used in such different -ways. - -\Y\P\D \37$\\{type}(\#)\S\\{mem}[\#].\\{hh}.\\{b0}$\C{identifies what kind of -value this is}\par -\P\D \37$\\{name\_type}(\#)\S\\{mem}[\#].\\{hh}.\\{b1}$\C{a clue to the name of -this value}\par -\P\D \37$\\{token\_node\_size}=2$\C{the number of words in a large token node}% -\par -\P\D \37$\\{value\_loc}(\#)\S\#+1$\C{the word that contains the \\{value} -field}\par -\P\D \37$\\{value}(\#)\S\\{mem}[\\{value\_loc}(\#)].\\{int}$\C{the value stored -in a large token node}\par -\P\D \37$\\{expr\_base}\S\\{hash\_end}+1$\C{code for the zeroth \&{expr} -parameter}\par -\P\D \37$\\{suffix\_base}\S\\{expr\_base}+\\{param\_size}$\C{code for the -zeroth \&{suffix} parameter}\par -\P\D \37$\\{text\_base}\S\\{suffix\_base}+\\{param\_size}$\C{code for the -zeroth \&{text} parameter}\par -\Y\P$\4\X14:Check the ``constant'' values for consistency\X\mathrel{+}\S$\6 -\&{if} $\\{text\_base}+\\{param\_size}>\\{max\_halfword}$ \1\&{then}\5 -$\\{bad}\K22$;\2\par -\fi - -\M215. A numeric token is created by the following trivial routine. - -\Y\P\4\&{function}\1\ \37$\\{new\_num\_tok}(\|v:\\{scaled})$: \37\\{pointer};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the new node}\2\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{token\_node\_size})$;\5 -$\\{value}(\|p)\K\|v$;\5 -$\\{type}(\|p)\K\\{known}$;\5 -$\\{name\_type}(\|p)\K\\{token}$;\5 -$\\{new\_num\_tok}\K\|p$;\6 -\&{end};\par -\fi - -\M216. A token list is a singly linked list of nodes in \\{mem}, where -each node contains a token and a link. Here's a subroutine that gets rid -of a token list when it is no longer needed. - -\Y\P\4\&{procedure}\1\ \37\\{token\_recycle};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37$\\{flush\_token\_list}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the node being recycled}\2\6 -\&{begin} \37\&{while} $\|p\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\|q\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{if} $\|q\G\\{hi\_mem\_min}$ \1\&{then}\5 -$\\{free\_avail}(\|q)$\6 -\4\&{else} \&{begin} \37\&{case} $\\{type}(\|q)$ \1\&{of}\6 -\4$\\{vacuous},\39\\{boolean\_type},\39\\{known}$: \37\\{do\_nothing};\6 -\4\\{string\_type}: \37$\\{delete\_str\_ref}(\\{value}(\|q))$;\6 -\4$\\{unknown\_types},\39\\{pen\_type},\39\\{path\_type},\39\\{future\_pen},\39% -\\{picture\_type},\39\\{pair\_type},\39\\{transform\_type},\39\\{dependent},\39% -\\{proto\_dependent},\39\\{independent}$: \37\&{begin} \37$\\{g\_pointer}\K% -\|q$;\5 -\\{token\_recycle};\6 -\&{end};\6 -\4\&{othercases} \37$\\{confusion}(\.{"token"})$\2\6 -\&{endcases};\6 -$\\{free\_node}(\|q,\39\\{token\_node\_size})$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M217. The procedure \\{show\_token\_list}, which prints a symbolic form of -the token list that starts at a given node \|p, illustrates these -conventions. The token list being displayed should not begin with a reference -count. However, the procedure is intended to be fairly robust, so that if the -memory links are awry or if \|p is not really a pointer to a token list, -almost nothing catastrophic can happen. - -An additional parameter \|q is also given; this parameter is either null -or it points to a node in the token list where a certain magic computation -takes place that will be explained later. (Basically, \|q is non-null when -we are printing the two-line context information at the time of an error -message; \|q marks the place corresponding to where the second line -should begin.) - -The generation will stop, and `\.{\char`\ ETC.}' will be printed, if the length -of printing exceeds a given limit~\|l; the length of printing upon entry is -assumed to be a given amount called \\{null\_tally}. (Note that -\\{show\_token\_list} sometimes uses itself recursively to print -variable names within a capsule.) - -Unusual entries are printed in the form of all-caps tokens -preceded by a space, e.g., `\.{\char`\ BAD}'. - -\Y\P$\4\X217:Declare the procedure called \\{show\_token\_list}\X\S$\6 -\4\&{procedure}\1\ \37\\{print\_capsule};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37$\\{show\_token\_list}(\|p,\39\|q:\\{integer};\,\35\|l,% -\39\\{null\_tally}:\\{integer})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\\{class},\39\|c$: \37\\{small\_number};\C{the \\{char\_class} of -previous and new tokens}\6 -$\|r,\39\|v$: \37\\{integer};\C{temporary registers}\2\6 -\&{begin} \37$\\{class}\K\\{percent\_class}$;\5 -$\\{tally}\K\\{null\_tally}$;\6 -\&{while} $(\|p\I\\{null})\W(\\{tally}<\|l)$ \1\&{do}\6 -\&{begin} \37\&{if} $\|p=\|q$ \1\&{then}\5 -\X646:Do magic computation\X;\2\6 -\X218:Display token \|p and set \|c to its class; but \&{return} if there are -problems\X;\6 -$\\{class}\K\|c$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\5 -$\\{print}(\.{"\ ETC."})$;\2\6 -\4\\{exit}: \37\&{end};\par -\U162.\fi - -\M218. \P$\X218:Display token \|p and set \|c to its class; but \&{return} if -there are problems\X\S$\6 -$\|c\K\\{letter\_class}$;\C{the default}\6 -\&{if} $(\|p<\\{mem\_min})\V(\|p>\\{mem\_end})$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\ CLOBBERED"})$;\5 -\&{return};\6 -\&{end};\2\6 -\&{if} $\|p<\\{hi\_mem\_min}$ \1\&{then}\5 -\X219:Display two-word token\X\6 -\4\&{else} \&{begin} \37$\|r\K\\{info}(\|p)$;\6 -\&{if} $\|r\G\\{expr\_base}$ \1\&{then}\5 -\X222:Display a parameter token\X\6 -\4\&{else} \&{if} $\|r<1$ \1\&{then}\6 -\&{if} $\|r=0$ \1\&{then}\5 -\X221:Display a collective subscript\X\6 -\4\&{else} $\\{print}(\.{"\ IMPOSSIBLE"})$\2\6 -\4\&{else} \&{begin} \37$\|r\K\\{text}(\|r)$;\6 -\&{if} $(\|r<0)\V(\|r\G\\{str\_ptr})$ \1\&{then}\5 -$\\{print}(\.{"\ NONEXISTENT"})$\6 -\4\&{else} \X223:Print string \|r as a symbolic token and set \|c to its class% -\X;\2\6 -\&{end};\2\2\6 -\&{end}\2\par -\U217.\fi - -\M219. \P$\X219:Display two-word token\X\S$\6 -\&{if} $\\{name\_type}(\|p)=\\{token}$ \1\&{then}\6 -\&{if} $\\{type}(\|p)=\\{known}$ \1\&{then}\5 -\X220:Display a numeric token\X\6 -\4\&{else} \&{if} $\\{type}(\|p)\I\\{string\_type}$ \1\&{then}\5 -$\\{print}(\.{"\ BAD"})$\6 -\4\&{else} \&{begin} \37$\\{print\_char}(\.{""}\.{""})$;\5 -$\\{slow\_print}(\\{value}(\|p))$;\5 -$\\{print\_char}(\.{""}\.{""})$;\5 -$\|c\K\\{string\_class}$;\6 -\&{end}\2\2\6 -\4\&{else} \&{if} $(\\{name\_type}(\|p)\I\\{capsule})\V(\\{type}(\|p)<% -\\{vacuous})\V(\\{type}(\|p)>\\{independent})$ \1\&{then}\5 -$\\{print}(\.{"\ BAD"})$\6 -\4\&{else} \&{begin} \37$\\{g\_pointer}\K\|p$;\5 -\\{print\_capsule};\5 -$\|c\K\\{right\_paren\_class}$;\6 -\&{end}\2\2\par -\U218.\fi - -\M220. \P$\X220:Display a numeric token\X\S$\6 -\&{begin} \37\&{if} $\\{class}=\\{digit\_class}$ \1\&{then}\5 -$\\{print\_char}(\.{"\ "})$;\2\6 -$\|v\K\\{value}(\|p)$;\6 -\&{if} $\|v<0$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{class}=\\{left\_bracket\_class}$ \1\&{then}\5 -$\\{print\_char}(\.{"\ "})$;\2\6 -$\\{print\_char}(\.{"["})$;\5 -$\\{print\_scaled}(\|v)$;\5 -$\\{print\_char}(\.{"]"})$;\5 -$\|c\K\\{right\_bracket\_class}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print\_scaled}(\|v)$;\5 -$\|c\K\\{digit\_class}$;\6 -\&{end};\2\6 -\&{end}\par -\U219.\fi - -\M221. Strictly speaking, a genuine token will never have $\\{info}(\|p)=0$. -But we will see later (in the \\{print\_variable\_name} routine) that -it is convenient to let $\\{info}(\|p)=0$ stand for `\.{[]}'. - -\Y\P$\4\X221:Display a collective subscript\X\S$\6 -\&{begin} \37\&{if} $\\{class}=\\{left\_bracket\_class}$ \1\&{then}\5 -$\\{print\_char}(\.{"\ "})$;\2\6 -$\\{print}(\.{"[]"})$;\5 -$\|c\K\\{right\_bracket\_class}$;\6 -\&{end}\par -\U218.\fi - -\M222. \P$\X222:Display a parameter token\X\S$\6 -\&{begin} \37\&{if} $\|r<\\{suffix\_base}$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"(EXPR"})$;\5 -$\|r\K\|r-(\\{expr\_base})$;\6 -\&{end}\6 -\4\&{else} \&{if} $\|r<\\{text\_base}$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"(SUFFIX"})$;\5 -$\|r\K\|r-(\\{suffix\_base})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print}(\.{"(TEXT"})$;\5 -$\|r\K\|r-(\\{text\_base})$;\6 -\&{end};\2\2\6 -$\\{print\_int}(\|r)$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\|c\K\\{right\_paren\_class}$;\6 -\&{end}\par -\U218.\fi - -\M223. \P$\X223:Print string \|r as a symbolic token and set \|c to its class\X% -\S$\6 -\&{begin} \37$\|c\K\\{char\_class}[\\{so}(\\{str\_pool}[\\{str\_start}[% -\|r]])]$;\6 -\&{if} $\|c=\\{class}$ \1\&{then}\6 -\&{case} $\|c$ \1\&{of}\6 -\4\\{letter\_class}: \37$\\{print\_char}(\.{"."})$;\6 -\4\\{isolated\_classes}: \37\\{do\_nothing};\6 -\4\&{othercases} \37$\\{print\_char}(\.{"\ "})$\2\6 -\&{endcases};\2\6 -$\\{slow\_print}(\|r)$;\6 -\&{end}\par -\U218.\fi - -\M224. The following procedures have been declared \\{forward} with no -parameters, -because the author dislikes \PASCAL's convention about \\{forward} procedures -with parameters. It was necessary to do something, because \\{show\_token% -\_list} -is recursive (although the recursion is limited to one level), and because -\\{flush\_token\_list} is syntactically (but not semantically) recursive. - -\Y\P$\4\X224:Declare miscellaneous procedures that were declared \\{forward}\X% -\S$\6 -\4\&{procedure}\1\ \37\\{print\_capsule};\2\6 -\&{begin} \37$\\{print\_char}(\.{"("})$;\5 -$\\{print\_exp}(\\{g\_pointer},\390)$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37\\{token\_recycle};\2\6 -\&{begin} \37$\\{recycle\_value}(\\{g\_pointer})$;\6 -\&{end};\par -\U1202.\fi - -\M225. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{g\_pointer}: \37\\{pointer};\C{(global) parameter to the \\{forward} -procedures}\par -\fi - -\M226. Macro definitions are kept in \MF's memory in the form of token lists -that have a few extra one-word nodes at the beginning. - -The first node contains a reference count that is used to tell when the -list is no longer needed. To emphasize the fact that a reference count is -present, we shall refer to the \\{info} field of this special node as the -\\{ref\_count} field. - -The next node or nodes after the reference count serve to describe the -formal parameters. They either contain a code word that specifies all -of the parameters, or they contain zero or more parameter tokens followed -by the code `\\{general\_macro}'. - -\Y\P\D \37$\\{ref\_count}\S\\{info}$\C{reference count preceding a macro -definition or pen header}\par -\P\D \37$\\{add\_mac\_ref}(\#)\S\\{incr}(\\{ref\_count}(\#))$\C{make a new -reference to a macro list}\par -\P\D \37$\\{general\_macro}=0$\C{preface to a macro defined with a parameter -list}\par -\P\D \37$\\{primary\_macro}=1$\C{preface to a macro with a \&{primary} -parameter}\par -\P\D \37$\\{secondary\_macro}=2$\C{preface to a macro with a \&{secondary} -parameter}\par -\P\D \37$\\{tertiary\_macro}=3$\C{preface to a macro with a \&{tertiary} -parameter}\par -\P\D \37$\\{expr\_macro}=4$\C{preface to a macro with an undelimited \&{expr} -parameter}\par -\P\D \37$\\{of\_macro}=5$\C{preface to a macro with undelimited `\&{expr} \|x -\&{of}~\|y' parameters}\par -\P\D \37$\\{suffix\_macro}=6$\C{preface to a macro with an undelimited % -\&{suffix} parameter}\par -\P\D \37$\\{text\_macro}=7$\C{preface to a macro with an undelimited \&{text} -parameter}\par -\Y\P\4\&{procedure}\1\ \37$\\{delete\_mac\_ref}(\|p:\\{pointer})$;\C{\|p -points to the reference count of a macro list that is losing one reference}% -\2\6 -\&{begin} \37\&{if} $\\{ref\_count}(\|p)=\\{null}$ \1\&{then}\5 -$\\{flush\_token\_list}(\|p)$\6 -\4\&{else} $\\{decr}(\\{ref\_count}(\|p))$;\2\6 -\&{end};\par -\fi - -\M227. The following subroutine displays a macro, given a pointer to its -reference count. - -\Y\P\hbox{\4}\X625:Declare the procedure called \\{print\_cmd\_mod}\X\6 -\4\&{procedure}\1\ \37$\\{show\_macro}(\|p:\\{pointer};\,\35\|q,\39\|l:% -\\{integer})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|r: \37\\{pointer};\C{temporary storage}\2\6 -\&{begin} \37$\|p\K\\{link}(\|p)$;\C{bypass the reference count}\6 -\&{while} $\\{info}(\|p)>\\{text\_macro}$ \1\&{do}\6 -\&{begin} \37$\|r\K\\{link}(\|p)$;\5 -$\\{link}(\|p)\K\\{null}$;\5 -$\\{show\_token\_list}(\|p,\39\\{null},\39\|l,\390)$;\5 -$\\{link}(\|p)\K\|r$;\5 -$\|p\K\|r$;\6 -\&{if} $\|l>0$ \1\&{then}\5 -$\|l\K\|l-\\{tally}$\ \&{else} \&{return};\2\6 -\&{end};\C{control printing of `\.{ETC.}'}\2\6 -$\\{tally}\K0$;\6 -\&{case} $\\{info}(\|p)$ \1\&{of}\6 -\4\\{general\_macro}: \37$\\{print}(\.{"->"})$;\6 -\4$\\{primary\_macro},\39\\{secondary\_macro},\39\\{tertiary\_macro}$: \37% -\&{begin} \37$\\{print\_char}(\.{"<"})$;\5 -$\\{print\_cmd\_mod}(\\{param\_type},\39\\{info}(\|p))$;\5 -$\\{print}(\.{">->"})$;\6 -\&{end};\6 -\4\\{expr\_macro}: \37$\\{print}(\.{"<expr>->"})$;\6 -\4\\{of\_macro}: \37$\\{print}(\.{"<expr>of<primary>->"})$;\6 -\4\\{suffix\_macro}: \37$\\{print}(\.{"<suffix>->"})$;\6 -\4\\{text\_macro}: \37$\\{print}(\.{"<text>->"})$;\2\6 -\&{end};\C{there are no other cases}\6 -$\\{show\_token\_list}(\\{link}(\|p),\39\|q,\39\|l-\\{tally},\390)$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\N228. \[15] Data structures for variables. -The variables of \MF\ programs can be simple, like `\.x', or they can -combine the structural properties of arrays and records, like `\.{x20a.b}'. -A \MF\ user assigns a type to a variable like \.{x20a.b} by saying, for -example, `\.{boolean} \.{x20a.b}'. It's time for us to study how such -things are represented inside of the computer. - -Each variable value occupies two consecutive words, either in a two-word -node called a value node, or as a two-word subfield of a larger node. One -of those two words is called the \\{value} field; it is an integer, -containing either a \\{scaled} numeric value or the representation of some -other type of quantity. (It might also be subdivided into halfwords, in -which case it is referred to by other names instead of \\{value}.) The other -word is broken into subfields called \\{type}, \\{name\_type}, and \\{link}. -The -\\{type} field is a quarterword that specifies the variable's type, and -\\{name\_type} is a quarterword from which \MF\ can reconstruct the -variable's name (sometimes by using the \\{link} field as well). Thus, only -1.25 words are actually devoted to the value itself; the other -three-quarters of a word are overhead, but they aren't wasted because they -allow \MF\ to deal with sparse arrays and to provide meaningful diagnostics. - -In this section we shall be concerned only with the structural aspects of -variables, not their values. Later parts of the program will change the -\\{type} and \\{value} fields, but we shall treat those fields as black boxes -whose contents should not be touched. - -However, if the \\{type} field is \\{structured}, there is no \\{value} field, -and the second word is broken into two pointer fields called \\{attr\_head} -and \\{subscr\_head}. Those fields point to additional nodes that -contain structural information, as we shall see. - -\Y\P\D \37$\\{subscr\_head\_loc}(\#)\S\#+1$\C{where \\{value}, \\{subscr% -\_head}, and \\{attr\_head} are}\par -\P\D \37$\\{attr\_head}(\#)\S\\{info}(\\{subscr\_head\_loc}(\#))$\C{pointer to -attribute info}\par -\P\D \37$\\{subscr\_head}(\#)\S\\{link}(\\{subscr\_head\_loc}(\#))$\C{pointer -to subscript info}\par -\P\D \37$\\{value\_node\_size}=2$\C{the number of words in a value node}\par -\fi - -\M229. An attribute node is three words long. Two of these words contain % -\\{type} -and \\{value} fields as described above, and the third word contains -additional information: There is an \\{attr\_loc} field, which contains the -hash address of the token that names this attribute; and there's also a -\\{parent} field, which points to the value node of \\{structured} type at the -next higher level (i.e., at the level to which this attribute is -subsidiary). The \\{name\_type} in an attribute node is `\\{attr}'. The -\\{link} field points to the next attribute with the same parent; these are -arranged in increasing order, so that $\\{attr\_loc}(\\{link}(\|p))>\\{attr% -\_loc}(\|p)$. The -final attribute node links to the constant \\{end\_attr}, whose \\{attr\_loc} -field is greater than any legal hash address. The \\{attr\_head} in the -parent points to a node whose \\{name\_type} is \\{structured\_root}; this -node represents the null attribute, i.e., the variable that is relevant -when no attributes are attached to the parent. The \\{attr\_head} node is -either -a value node, a subscript node, or an attribute node, depending on what -the parent would be if it were not structured; but the subscript and -attribute fields are ignored, so it effectively contains only the data of -a value node. The \\{link} field in this special node points to an attribute -node whose \\{attr\_loc} field is zero; the latter node represents a collective -subscript `\.{[]}' attached to the parent, and its \\{link} field points to -the first non-special attribute node (or to \\{end\_attr} if there are none). - -A subscript node likewise occupies three words, with \\{type} and \\{value} -fields -plus extra information; its \\{name\_type} is \\{subscr}. In this case the -third word is called the \\{subscript} field, which is a \\{scaled} integer. -The \\{link} field points to the subscript node with the next larger -subscript, if any; otherwise the \\{link} points to the attribute node -for collective subscripts at this level. We have seen that the latter node -contains an upward pointer, so that the parent can be deduced. - -The \\{name\_type} in a parent-less value node is \\{root}, and the \\{link} -is the hash address of the token that names this value. - -In other words, variables have a hierarchical structure that includes -enough threads running around so that the program is able to move easily -between siblings, parents, and children. An example should be helpful: -(The reader is advised to draw a picture while reading the following -description, since that will help to firm up the ideas.) -Suppose that `\.x' and `\.{x.a}' and `\.{x[]b}' and `\.{x5}' -and `\.{x20b}' have been mentioned in a user's program, where -\.{x[]b} has been declared to be of \&{boolean} type. Let $\|h(\|x)$, $\|h(% -\|a)$, -and $\|h(\|b)$ be the hash addresses of \.x, \.a, and~\.b. Then -$\\{eq\_type}(\|h(\|x))=\\{tag\_token}$ and $\\{equiv}(\|h(\|x))=\|p$, where % -\|p~is a two-word value -node with $\\{name\_type}(\|p)=\\{root}$ and $\\{link}(\|p)=\|h(\|x)$. We have -$\\{type}(\|p)=\\{structured}$, -$\\{attr\_head}(\|p)=\|q$, and $\\{subscr\_head}(\|p)=\|r$, where \|q points to -a value -node and \|r to a subscript node. (Are you still following this? Use -a pencil to draw a diagram.) The lone variable `\.x' is represented by -$\\{type}(\|q)$ and $\\{value}(\|q)$; furthermore -$\\{name\_type}(\|q)=\\{structured\_root}$ and $\\{link}(\|q)=\\{q1}$, where % -\\{q1} points -to an attribute node representing `\.{x[]}'. Thus $\\{name\_type}(\\{q1})=% -\\{attr}$, -$\\{attr\_loc}(\\{q1})=\\{collective\_subscript}=0$, $\\{parent}(\\{q1})=\|p$, -$\\{type}(\\{q1})=\\{structured}$, $\\{attr\_head}(\\{q1})=\\{qq}$, and $% -\\{subscr\_head}(\\{q1})=\\{qq1}$; -\\{qq} is a value node with $\\{type}(\\{qq})=\\{numeric\_type}$ (assuming that -\.{x5} is -numeric, because \\{qq} represents `\.{x[]}' with no further attributes), -$\\{name\_type}(\\{qq})=\\{structured\_root}$, and -$\\{link}(\\{qq})=\\{qq1}$. (Now pay attention to the next part.) Node \\{qq1} -is -an attribute node representing `\.{x[][]}', which has never yet -occurred; its \\{type} field is \\{undefined}, and its \\{value} field is -undefined. We have $\\{name\_type}(\\{qq1})=\\{attr}$, $\\{attr\_loc}(\\{qq1})=% -\\{collective\_subscript}$, -$\\{parent}(\\{qq1})=\\{q1}$, and $\\{link}(\\{qq1})=\\{qq2}$. Since \\{qq2} -represents -`\.{x[]b}', $\\{type}(\\{qq2})=\\{unknown\_boolean}$; also $\\{attr\_loc}(% -\\{qq2})=\|h(\|b)$, -$\\{parent}(\\{qq2})=\\{q1}$, $\\{name\_type}(\\{qq2})=\\{attr}$, $\\{link}(% -\\{qq2})=\\{end\_attr}$. -(Maybe colored lines will help untangle your picture.) -Node \|r is a subscript node with \\{type} and \\{value} -representing `\.{x5}'; $\\{name\_type}(\|r)=\\{subscr}$, $\\{subscript}(% -\|r)=5.0$, -and $\\{link}(\|r)=\\{r1}$ is another subscript node. To complete the picture, -see if you can guess what $\\{link}(\\{r1})$ is; give up? It's~\\{q1}. -Furthermore $\\{subscript}(\\{r1})=20.0$, $\\{name\_type}(\\{r1})=\\{subscr}$, -$\\{type}(\\{r1})=\\{structured}$, $\\{attr\_head}(\\{r1})=\\{qqq}$, $\\{subscr% -\_head}(\\{r1})=\\{qqq1}$, -and we finish things off with three more nodes -\\{qqq}, \\{qqq1}, and \\{qqq2} hung onto~\\{r1}. (Perhaps you should start -again -with a larger sheet of paper.) The value of variable \.{x20b} -appears in node~\\{qqq2}, as you can well imagine. - -If the example in the previous paragraph doesn't make things crystal -clear, a glance at some of the simpler subroutines below will reveal how -things work out in practice. - -The only really unusual thing about these conventions is the use of -collective subscript attributes. The idea is to avoid repeating a lot of -type information when many elements of an array are identical macros -(for which distinct values need not be stored) or when they don't have -all of the possible attributes. Branches of the structure below collective -subscript attributes do not carry actual values except for macro identifiers; -branches of the structure below subscript nodes do not carry significant -information in their collective subscript attributes. - -\Y\P\D \37$\\{attr\_loc\_loc}(\#)\S\#+2$\C{where the \\{attr\_loc} and % -\\{parent} fields are}\par -\P\D \37$\\{attr\_loc}(\#)\S\\{info}(\\{attr\_loc\_loc}(\#))$\C{hash address of -this attribute}\par -\P\D \37$\\{parent}(\#)\S\\{link}(\\{attr\_loc\_loc}(\#))$\C{pointer to % -\\{structured} variable}\par -\P\D \37$\\{subscript\_loc}(\#)\S\#+2$\C{where the \\{subscript} field lives}% -\par -\P\D \37$\\{subscript}(\#)\S\\{mem}[\\{subscript\_loc}(\#)].\\{sc}$\C{subscript -of this variable}\par -\P\D \37$\\{attr\_node\_size}=3$\C{the number of words in an attribute node}\par -\P\D \37$\\{subscr\_node\_size}=3$\C{the number of words in a subscript node}% -\par -\P\D \37$\\{collective\_subscript}=0$\C{code for the attribute `\.{[]}'}\par -\Y\P$\4\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}\S$\6 -$\\{attr\_loc}(\\{end\_attr})\K\\{hash\_end}+1$;\5 -$\\{parent}(\\{end\_attr})\K\\{null}$;\par -\fi - -\M230. Variables of type \&{pair} will have values that point to four-word -nodes containing two numeric values. The first of these values has -$\\{name\_type}=\\{x\_part\_sector}$ and the second has $\\{name\_type}=\\{y% -\_part\_sector}$; -the \\{link} in the first points back to the node whose \\{value} points -to this four-word node. - -Variables of type \&{transform} are similar, but in this case their -\\{value} points to a 12-word node containing six values, identified by -\\{x\_part\_sector}, \\{y\_part\_sector}, \\{xx\_part\_sector}, \\{xy\_part% -\_sector}, -\\{yx\_part\_sector}, and \\{yy\_part\_sector}. - -When an entire structured variable is saved, the \\{root} indication -is temporarily replaced by \\{saved\_root}. - -Some variables have no name; they just are used for temporary storage -while expressions are being evaluated. We call them {\sl capsules}. - -\Y\P\D \37$\\{x\_part\_loc}(\#)\S\#$\C{where the \&{xpart} is found in a pair -or transform node}\par -\P\D \37$\\{y\_part\_loc}(\#)\S\#+2$\C{where the \&{ypart} is found in a pair -or transform node}\par -\P\D \37$\\{xx\_part\_loc}(\#)\S\#+4$\C{where the \&{xxpart} is found in a -transform node}\par -\P\D \37$\\{xy\_part\_loc}(\#)\S\#+6$\C{where the \&{xypart} is found in a -transform node}\par -\P\D \37$\\{yx\_part\_loc}(\#)\S\#+8$\C{where the \&{yxpart} is found in a -transform node}\par -\P\D \37$\\{yy\_part\_loc}(\#)\S\#+10$\C{where the \&{yypart} is found in a -transform node}\Y\par -\P\D \37$\\{pair\_node\_size}=4$\C{the number of words in a pair node}\par -\P\D \37$\\{transform\_node\_size}=12$\C{the number of words in a transform -node}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{big\_node\_size}: \37\&{array} $[\\{transform\_type}\to\\{pair\_type}]$ \1% -\&{of}\5 -\\{small\_number};\2\par -\fi - -\M231. The \\{big\_node\_size} array simply contains two constants that \MF\ -occasionally needs to know. - -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{big\_node\_size}[\\{transform\_type}]\K\\{transform\_node\_size}$;\5 -$\\{big\_node\_size}[\\{pair\_type}]\K\\{pair\_node\_size}$;\par -\fi - -\M232. If $\\{type}(\|p)=\\{pair\_type}$ or \\{transform\_type} and if $% -\\{value}(\|p)=\\{null}$, the -procedure call $\\{init\_big\_node}(\|p)$ will allocate a pair or transform -node -for~\|p. The individual parts of such nodes are initially of type -\\{independent}. - -\Y\P\4\&{procedure}\1\ \37$\\{init\_big\_node}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the new node}\6 -\|s: \37\\{small\_number};\C{its size}\2\6 -\&{begin} \37$\|s\K\\{big\_node\_size}[\\{type}(\|p)]$;\5 -$\|q\K\\{get\_node}(\|s)$;\6 -\1\&{repeat} \37$\|s\K\|s-2$;\5 -\X586:Make variable $\|q+\|s$ newly independent\X;\6 -$\\{name\_type}(\|q+\|s)\K\\{half}(\|s)+\\{x\_part\_sector}$;\5 -$\\{link}(\|q+\|s)\K\\{null}$;\6 -\4\&{until}\5 -$\|s=0$;\2\6 -$\\{link}(\|q)\K\|p$;\5 -$\\{value}(\|p)\K\|q$;\6 -\&{end};\par -\fi - -\M233. The \\{id\_transform} function creates a capsule for the -identity transformation. - -\Y\P\4\&{function}\1\ \37\\{id\_transform}: \37\\{pointer};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{list manipulation -registers}\2\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{type}(\|p)\K\\{transform\_type}$;\5 -$\\{name\_type}(\|p)\K\\{capsule}$;\5 -$\\{value}(\|p)\K\\{null}$;\5 -$\\{init\_big\_node}(\|p)$;\5 -$\|q\K\\{value}(\|p)$;\5 -$\|r\K\|q+\\{transform\_node\_size}$;\6 -\1\&{repeat} \37$\|r\K\|r-2$;\5 -$\\{type}(\|r)\K\\{known}$;\5 -$\\{value}(\|r)\K0$;\6 -\4\&{until}\5 -$\|r=\|q$;\2\6 -$\\{value}(\\{xx\_part\_loc}(\|q))\K\\{unity}$;\5 -$\\{value}(\\{yy\_part\_loc}(\|q))\K\\{unity}$;\5 -$\\{id\_transform}\K\|p$;\6 -\&{end};\par -\fi - -\M234. Tokens are of type \\{tag\_token} when they first appear, but they point -to \\{null} until they are first used as the root of a variable. -The following subroutine establishes the root node on such grand occasions. - -\Y\P\4\&{procedure}\1\ \37$\\{new\_root}(\|x:\\{pointer})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the new node}\2\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{type}(\|p)\K\\{undefined}$;\5 -$\\{name\_type}(\|p)\K\\{root}$;\5 -$\\{link}(\|p)\K\|x$;\5 -$\\{equiv}(\|x)\K\|p$;\6 -\&{end};\par -\fi - -\M235. These conventions for variable representation are illustrated by the -\\{print\_variable\_name} routine, which displays the full name of a -variable given only a pointer to its two-word value packet. - -\Y\P\4\&{procedure}\1\ \37$\\{print\_variable\_name}(\|p:\\{pointer})$;\6 -\4\&{label} \37$\\{found},\39\\{exit}$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{a token list that will name the variable's -suffix}\6 -\|r: \37\\{pointer};\C{temporary for token list creation}\2\6 -\&{begin} \37\&{while} $\\{name\_type}(\|p)\G\\{x\_part\_sector}$ \1\&{do}\5 -\X237:Preface the output with a part specifier; \&{return} in the case of a -capsule\X;\2\6 -$\|q\K\\{null}$;\6 -\&{while} $\\{name\_type}(\|p)>\\{saved\_root}$ \1\&{do}\5 -\X236:Ascend one level, pushing a token onto list \|q and replacing \|p by its -parent\X;\2\6 -$\|r\K\\{get\_avail}$;\5 -$\\{info}(\|r)\K\\{link}(\|p)$;\5 -$\\{link}(\|r)\K\|q$;\6 -\&{if} $\\{name\_type}(\|p)=\\{saved\_root}$ \1\&{then}\5 -$\\{print}(\.{"(SAVED)"})$;\2\6 -$\\{show\_token\_list}(\|r,\39\\{null},\39\\{el\_gordo},\39\\{tally})$;\5 -$\\{flush\_token\_list}(\|r)$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M236. \P$\X236:Ascend one level, pushing a token onto list \|q and replacing % -\|p by its parent\X\S$\6 -\&{begin} \37\&{if} $\\{name\_type}(\|p)=\\{subscr}$ \1\&{then}\6 -\&{begin} \37$\|r\K\\{new\_num\_tok}(\\{subscript}(\|p))$;\6 -\1\&{repeat} \37$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\\{name\_type}(\|p)=\\{attr}$;\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{name\_type}(\|p)=\\{structured\_root}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{link}(\|p)$;\5 -\&{goto} \37\\{found};\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{name\_type}(\|p)\I\\{attr}$ \1\&{then}\5 -$\\{confusion}(\.{"var"})$;\2\6 -$\|r\K\\{get\_avail}$;\5 -$\\{info}(\|r)\K\\{attr\_loc}(\|p)$;\6 -\&{end};\2\2\6 -$\\{link}(\|r)\K\|q$;\5 -$\|q\K\|r$;\6 -\4\\{found}: \37$\|p\K\\{parent}(\|p)$;\6 -\&{end}\par -\U235.\fi - -\M237. \P$\X237:Preface the output with a part specifier; \&{return} in the -case of a capsule\X\S$\6 -\&{begin} \37\&{case} $\\{name\_type}(\|p)$ \1\&{of}\6 -\4\\{x\_part\_sector}: \37$\\{print\_char}(\.{"x"})$;\6 -\4\\{y\_part\_sector}: \37$\\{print\_char}(\.{"y"})$;\6 -\4\\{xx\_part\_sector}: \37$\\{print}(\.{"xx"})$;\6 -\4\\{xy\_part\_sector}: \37$\\{print}(\.{"xy"})$;\6 -\4\\{yx\_part\_sector}: \37$\\{print}(\.{"yx"})$;\6 -\4\\{yy\_part\_sector}: \37$\\{print}(\.{"yy"})$;\6 -\4\\{capsule}: \37\&{begin} \37$\\{print}(\.{"\%CAPSULE"})$;\5 -$\\{print\_int}(\|p-\\{null})$;\5 -\&{return};\6 -\&{end};\2\6 -\&{end};\C{there are no other cases}\6 -$\\{print}(\.{"part\ "})$;\5 -$\|p\K\\{link}(\|p-2\ast(\\{name\_type}(\|p)-\\{x\_part\_sector}))$;\6 -\&{end}\par -\U235.\fi - -\M238. The \\{interesting} function returns \\{true} if a given variable is not -in a capsule, or if the user wants to trace capsules. - -\Y\P\4\&{function}\1\ \37$\\{interesting}(\|p:\\{pointer})$: \37\\{boolean};\6 -\4\&{var} \37\|t: \37\\{small\_number};\C{a \\{name\_type}}\2\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_capsules}]>0$ \1\&{then}\5 -$\\{interesting}\K\\{true}$\6 -\4\&{else} \&{begin} \37$\|t\K\\{name\_type}(\|p)$;\6 -\&{if} $\|t\G\\{x\_part\_sector}$ \1\&{then}\6 -\&{if} $\|t\I\\{capsule}$ \1\&{then}\5 -$\|t\K\\{name\_type}(\\{link}(\|p-2\ast(\|t-\\{x\_part\_sector})))$;\2\2\6 -$\\{interesting}\K(\|t\I\\{capsule})$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M239. Now here is a subroutine that converts an unstructured type into an -equivalent structured type, by inserting a \\{structured} node that is -capable of growing. This operation is done only when $\\{name\_type}(\|p)=% -\\{root}$, -\\{subscr}, or \\{attr}. - -The procedure returns a pointer to the new node that has taken node~\|p's -place in the structure. Node~\|p itself does not move, nor are its -\\{value} or \\{type} fields changed in any way. - -\Y\P\4\&{function}\1\ \37$\\{new\_structure}(\|p:\\{pointer})$: \37% -\\{pointer};\6 -\4\&{var} \37$\|q,\39\|r$: \37\\{pointer};\C{list manipulation registers}\2\6 -\&{begin} \37\&{case} $\\{name\_type}(\|p)$ \1\&{of}\6 -\4\\{root}: \37\&{begin} \37$\|q\K\\{link}(\|p)$;\5 -$\|r\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{equiv}(\|q)\K\|r$;\6 -\&{end};\6 -\4\\{subscr}: \37\X240:Link a new subscript node \|r in place of node \|p\X;\6 -\4\\{attr}: \37\X241:Link a new attribute node \|r in place of node \|p\X;\6 -\4\&{othercases} \37$\\{confusion}(\.{"struct"})$\2\6 -\&{endcases};\6 -$\\{link}(\|r)\K\\{link}(\|p)$;\5 -$\\{type}(\|r)\K\\{structured}$;\5 -$\\{name\_type}(\|r)\K\\{name\_type}(\|p)$;\5 -$\\{attr\_head}(\|r)\K\|p$;\5 -$\\{name\_type}(\|p)\K\\{structured\_root}$;\6 -$\|q\K\\{get\_node}(\\{attr\_node\_size})$;\5 -$\\{link}(\|p)\K\|q$;\5 -$\\{subscr\_head}(\|r)\K\|q$;\5 -$\\{parent}(\|q)\K\|r$;\5 -$\\{type}(\|q)\K\\{undefined}$;\5 -$\\{name\_type}(\|q)\K\\{attr}$;\5 -$\\{link}(\|q)\K\\{end\_attr}$;\5 -$\\{attr\_loc}(\|q)\K\\{collective\_subscript}$;\5 -$\\{new\_structure}\K\|r$;\6 -\&{end};\par -\fi - -\M240. \P$\X240:Link a new subscript node \|r in place of node \|p\X\S$\6 -\&{begin} \37$\|q\K\|p$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\\{name\_type}(\|q)=\\{attr}$;\2\6 -$\|q\K\\{parent}(\|q)$;\5 -$\|r\K\\{subscr\_head\_loc}(\|q)$;\C{$\\{link}(\|r)=\\{subscr\_head}(\|q)$}\6 -\1\&{repeat} \37$\|q\K\|r$;\5 -$\|r\K\\{link}(\|r)$;\6 -\4\&{until}\5 -$\|r=\|p$;\2\6 -$\|r\K\\{get\_node}(\\{subscr\_node\_size})$;\5 -$\\{link}(\|q)\K\|r$;\5 -$\\{subscript}(\|r)\K\\{subscript}(\|p)$;\6 -\&{end}\par -\U239.\fi - -\M241. If the attribute is \\{collective\_subscript}, there are two pointers to -node~\|p, so we must change both of them. - -\Y\P$\4\X241:Link a new attribute node \|r in place of node \|p\X\S$\6 -\&{begin} \37$\|q\K\\{parent}(\|p)$;\5 -$\|r\K\\{attr\_head}(\|q)$;\6 -\1\&{repeat} \37$\|q\K\|r$;\5 -$\|r\K\\{link}(\|r)$;\6 -\4\&{until}\5 -$\|r=\|p$;\2\6 -$\|r\K\\{get\_node}(\\{attr\_node\_size})$;\5 -$\\{link}(\|q)\K\|r$;\6 -$\\{mem}[\\{attr\_loc\_loc}(\|r)]\K\\{mem}[\\{attr\_loc\_loc}(\|p)]$;\C{copy % -\\{attr\_loc} and \\{parent}}\6 -\&{if} $\\{attr\_loc}(\|p)=\\{collective\_subscript}$ \1\&{then}\6 -\&{begin} \37$\|q\K\\{subscr\_head\_loc}(\\{parent}(\|p))$;\6 -\&{while} $\\{link}(\|q)\I\|p$ \1\&{do}\5 -$\|q\K\\{link}(\|q)$;\2\6 -$\\{link}(\|q)\K\|r$;\6 -\&{end};\2\6 -\&{end}\par -\U239.\fi - -\M242. The \\{find\_variable} routine is given a pointer~\|t to a nonempty -token -list of suffixes; it returns a pointer to the corresponding two-word -value. For example, if \|t points to token \.x followed by a numeric -token containing the value~7, \\{find\_variable} finds where the value of -\.{x7} is stored in memory. This may seem a simple task, and it -usually is, except when \.{x7} has never been referenced before. -Indeed, \.x may never have even been subscripted before; complexities -arise with respect to updating the collective subscript information. - -If a macro type is detected anywhere along path~\|t, or if the first -item on \|t isn't a \\{tag\_token}, the value \\{null} is returned. -Otherwise \|p will be a non-null pointer to a node such that -$\\{undefined}<\\{type}(\|p)<\\{structured}$. - -\Y\P\D \37$\\{abort\_find}\S$\1\6 -\&{begin} \37$\\{find\_variable}\K\\{null}$;\5 -\&{return};\ \&{end}\2\par -\Y\P\4\&{function}\1\ \37$\\{find\_variable}(\|t:\\{pointer})$: \37% -\\{pointer};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{nodes in the -``value'' line}\6 -$\\{pp},\39\\{qq},\39\\{rr},\39\\{ss}$: \37\\{pointer};\C{nodes in the -``collective'' line}\6 -\|n: \37\\{integer};\C{subscript or attribute}\6 -\\{save\_word}: \37\\{memory\_word};\C{temporary storage for a word of \\{mem}}% -\2\6 -\&{begin} \37$\|p\K\\{info}(\|t)$;\5 -$\|t\K\\{link}(\|t)$;\6 -\&{if} $\\{eq\_type}(\|p)\mathbin{\&{mod}}\\{outer\_tag}\I\\{tag\_token}$ \1% -\&{then}\5 -\\{abort\_find};\2\6 -\&{if} $\\{equiv}(\|p)=\\{null}$ \1\&{then}\5 -$\\{new\_root}(\|p)$;\2\6 -$\|p\K\\{equiv}(\|p)$;\5 -$\\{pp}\K\|p$;\6 -\&{while} $\|t\I\\{null}$ \1\&{do}\6 -\&{begin} \37\X243:Make sure that both nodes \|p and \\{pp} are of % -\\{structured} type\X;\6 -\&{if} $\|t<\\{hi\_mem\_min}$ \1\&{then}\5 -\X244:Descend one level for the subscript $\\{value}(\|t)$\X\6 -\4\&{else} \X245:Descend one level for the attribute $\\{info}(\|t)$\X;\2\6 -$\|t\K\\{link}(\|t)$;\6 -\&{end};\2\6 -\&{if} $\\{type}(\\{pp})\G\\{structured}$ \1\&{then}\6 -\&{if} $\\{type}(\\{pp})=\\{structured}$ \1\&{then}\5 -$\\{pp}\K\\{attr\_head}(\\{pp})$\ \&{else} \\{abort\_find};\2\2\6 -\&{if} $\\{type}(\|p)=\\{structured}$ \1\&{then}\5 -$\|p\K\\{attr\_head}(\|p)$;\2\6 -\&{if} $\\{type}(\|p)=\\{undefined}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{type}(\\{pp})=\\{undefined}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\\{pp})\K\\{numeric\_type}$;\5 -$\\{value}(\\{pp})\K\\{null}$;\6 -\&{end};\2\6 -$\\{type}(\|p)\K\\{type}(\\{pp})$;\5 -$\\{value}(\|p)\K\\{null}$;\6 -\&{end};\2\6 -$\\{find\_variable}\K\|p$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M243. Although \\{pp} and \|p begin together, they diverge when a subscript -occurs; -\\{pp}~stays in the collective line while \|p~goes through actual subscript -values. - -\Y\P$\4\X243:Make sure that both nodes \|p and \\{pp} are of \\{structured} -type\X\S$\6 -\&{if} $\\{type}(\\{pp})\I\\{structured}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{type}(\\{pp})>\\{structured}$ \1\&{then}\5 -\\{abort\_find};\2\6 -$\\{ss}\K\\{new\_structure}(\\{pp})$;\6 -\&{if} $\|p=\\{pp}$ \1\&{then}\5 -$\|p\K\\{ss}$;\2\6 -$\\{pp}\K\\{ss}$;\6 -\&{end};\C{now $\\{type}(\\{pp})=\\{structured}$}\2\6 -\&{if} $\\{type}(\|p)\I\\{structured}$ \1\&{then}\C{it cannot be $>% -\\{structured}$}\6 -$\|p\K\\{new\_structure}(\|p)$\C{now $\\{type}(\|p)=\\{structured}$}\2\par -\U242.\fi - -\M244. We want this part of the program to be reasonably fast, in case there -are -lots of subscripts at the same level of the data structure. Therefore -we store an ``infinite'' value in the word that appears at the end of the -subscript list, even though that word isn't part of a subscript node. - -\Y\P$\4\X244:Descend one level for the subscript $\\{value}(\|t)$\X\S$\6 -\&{begin} \37$\|n\K\\{value}(\|t)$;\5 -$\\{pp}\K\\{link}(\\{attr\_head}(\\{pp}))$;\C{now $\\{attr\_loc}(\\{pp})=% -\\{collective\_subscript}$}\6 -$\|q\K\\{link}(\\{attr\_head}(\|p))$;\5 -$\\{save\_word}\K\\{mem}[\\{subscript\_loc}(\|q)]$;\5 -$\\{subscript}(\|q)\K\\{el\_gordo}$;\5 -$\|s\K\\{subscr\_head\_loc}(\|p)$;\C{$\\{link}(\|s)=\\{subscr\_head}(\|p)$}\6 -\1\&{repeat} \37$\|r\K\|s$;\5 -$\|s\K\\{link}(\|s)$;\6 -\4\&{until}\5 -$\|n\L\\{subscript}(\|s)$;\2\6 -\&{if} $\|n=\\{subscript}(\|s)$ \1\&{then}\5 -$\|p\K\|s$\6 -\4\&{else} \&{begin} \37$\|p\K\\{get\_node}(\\{subscr\_node\_size})$;\5 -$\\{link}(\|r)\K\|p$;\5 -$\\{link}(\|p)\K\|s$;\5 -$\\{subscript}(\|p)\K\|n$;\5 -$\\{name\_type}(\|p)\K\\{subscr}$;\5 -$\\{type}(\|p)\K\\{undefined}$;\6 -\&{end};\2\6 -$\\{mem}[\\{subscript\_loc}(\|q)]\K\\{save\_word}$;\6 -\&{end}\par -\U242.\fi - -\M245. \P$\X245:Descend one level for the attribute $\\{info}(\|t)$\X\S$\6 -\&{begin} \37$\|n\K\\{info}(\|t)$;\5 -$\\{ss}\K\\{attr\_head}(\\{pp})$;\6 -\1\&{repeat} \37$\\{rr}\K\\{ss}$;\5 -$\\{ss}\K\\{link}(\\{ss})$;\6 -\4\&{until}\5 -$\|n\L\\{attr\_loc}(\\{ss})$;\2\6 -\&{if} $\|n<\\{attr\_loc}(\\{ss})$ \1\&{then}\6 -\&{begin} \37$\\{qq}\K\\{get\_node}(\\{attr\_node\_size})$;\5 -$\\{link}(\\{rr})\K\\{qq}$;\5 -$\\{link}(\\{qq})\K\\{ss}$;\5 -$\\{attr\_loc}(\\{qq})\K\|n$;\5 -$\\{name\_type}(\\{qq})\K\\{attr}$;\5 -$\\{type}(\\{qq})\K\\{undefined}$;\5 -$\\{parent}(\\{qq})\K\\{pp}$;\5 -$\\{ss}\K\\{qq}$;\6 -\&{end};\2\6 -\&{if} $\|p=\\{pp}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{ss}$;\5 -$\\{pp}\K\\{ss}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{pp}\K\\{ss}$;\5 -$\|s\K\\{attr\_head}(\|p)$;\6 -\1\&{repeat} \37$\|r\K\|s$;\5 -$\|s\K\\{link}(\|s)$;\6 -\4\&{until}\5 -$\|n\L\\{attr\_loc}(\|s)$;\2\6 -\&{if} $\|n=\\{attr\_loc}(\|s)$ \1\&{then}\5 -$\|p\K\|s$\6 -\4\&{else} \&{begin} \37$\|q\K\\{get\_node}(\\{attr\_node\_size})$;\5 -$\\{link}(\|r)\K\|q$;\5 -$\\{link}(\|q)\K\|s$;\5 -$\\{attr\_loc}(\|q)\K\|n$;\5 -$\\{name\_type}(\|q)\K\\{attr}$;\5 -$\\{type}(\|q)\K\\{undefined}$;\5 -$\\{parent}(\|q)\K\|p$;\5 -$\|p\K\|q$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end}\par -\U242.\fi - -\M246. Variables lose their former values when they appear in a type -declaration, -or when they are defined to be macros or \&{let} equal to something else. -A subroutine will be defined later that recycles the storage associated -with any particular \\{type} or \\{value}; our goal now is to study a higher -level process called \\{flush\_variable}, which selectively frees parts of a -variable structure. - -This routine has some complexity because of examples such as -`\hbox{\tt numeric x[]a[]b}', -which recycles all variables of the form \.{x[i]a[j]b} (and no others), while -`\hbox{\tt vardef x[]a[]=...}' -discards all variables of the form \.{x[i]a[j]} followed by an arbitrary -suffix, except for the collective node \.{x[]a[]} itself. The obvious way -to handle such examples is to use recursion; so that's what we~do. - -Parameter \|p points to the root information of the variable; -parameter \|t points to a list of one-word nodes that represent -suffixes, with $\\{info}=\\{collective\_subscript}$ for subscripts. - -\Y\P\hbox{\4}\X257:Declare subroutines for printing expressions\X\6 -\hbox{\4}\X594:Declare basic dependency-list subroutines\X\6 -\hbox{\4}\X268:Declare the recycling subroutines\X\6 -\hbox{\4}\X808:Declare the procedure called \\{flush\_cur\_exp}\X\6 -\hbox{\4}\X247:Declare the procedure called \\{flush\_below\_variable}\X\6 -\4\&{procedure}\1\ \37$\\{flush\_variable}(\|p,\39\|t:\\{pointer};\,\35% -\\{discard\_suffixes}:\\{boolean})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|q,\39\|r$: \37\\{pointer};\C{list manipulation}\6 -\|n: \37\\{halfword};\C{attribute to match}\2\6 -\&{begin} \37\&{while} $\|t\I\\{null}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{type}(\|p)\I\\{structured}$ \1\&{then}\5 -\&{return};\2\6 -$\|n\K\\{info}(\|t)$;\5 -$\|t\K\\{link}(\|t)$;\6 -\&{if} $\|n=\\{collective\_subscript}$ \1\&{then}\6 -\&{begin} \37$\|r\K\\{subscr\_head\_loc}(\|p)$;\5 -$\|q\K\\{link}(\|r)$;\C{$\|q=\\{subscr\_head}(\|p)$}\6 -\&{while} $\\{name\_type}(\|q)=\\{subscr}$ \1\&{do}\6 -\&{begin} \37$\\{flush\_variable}(\|q,\39\|t,\39\\{discard\_suffixes})$;\6 -\&{if} $\|t=\\{null}$ \1\&{then}\6 -\&{if} $\\{type}(\|q)=\\{structured}$ \1\&{then}\5 -$\|r\K\|q$\6 -\4\&{else} \&{begin} \37$\\{link}(\|r)\K\\{link}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{subscr\_node\_size})$;\6 -\&{end}\2\6 -\4\&{else} $\|r\K\|q$;\2\6 -$\|q\K\\{link}(\|r)$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\|p\K\\{attr\_head}(\|p)$;\6 -\1\&{repeat} \37$\|r\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\\{attr\_loc}(\|p)\G\|n$;\2\6 -\&{if} $\\{attr\_loc}(\|p)\I\|n$ \1\&{then}\5 -\&{return};\2\6 -\&{end};\2\6 -\&{if} $\\{discard\_suffixes}$ \1\&{then}\5 -$\\{flush\_below\_variable}(\|p)$\6 -\4\&{else} \&{begin} \37\&{if} $\\{type}(\|p)=\\{structured}$ \1\&{then}\5 -$\|p\K\\{attr\_head}(\|p)$;\2\6 -$\\{recycle\_value}(\|p)$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M247. The next procedure is simpler; it wipes out everything but \|p itself, -which becomes undefined. - -\Y\P$\4\X247:Declare the procedure called \\{flush\_below\_variable}\X\S$\6 -\4\&{procedure}\1\ \37$\\{flush\_below\_variable}(\|p:\\{pointer})$;\6 -\4\&{var} \37$\|q,\39\|r$: \37\\{pointer};\C{list manipulation registers}\2\6 -\&{begin} \37\&{if} $\\{type}(\|p)\I\\{structured}$ \1\&{then}\5 -$\\{recycle\_value}(\|p)$\C{this sets $\\{type}(\|p)=\\{undefined}$}\6 -\4\&{else} \&{begin} \37$\|q\K\\{subscr\_head}(\|p)$;\6 -\&{while} $\\{name\_type}(\|q)=\\{subscr}$ \1\&{do}\6 -\&{begin} \37$\\{flush\_below\_variable}(\|q)$;\5 -$\|r\K\|q$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{free\_node}(\|r,\39\\{subscr\_node\_size})$;\6 -\&{end};\2\6 -$\|r\K\\{attr\_head}(\|p)$;\5 -$\|q\K\\{link}(\|r)$;\5 -$\\{recycle\_value}(\|r)$;\6 -\&{if} $\\{name\_type}(\|p)\L\\{saved\_root}$ \1\&{then}\5 -$\\{free\_node}(\|r,\39\\{value\_node\_size})$\6 -\4\&{else} $\\{free\_node}(\|r,\39\\{subscr\_node\_size})$;\C{we assume that $% -\\{subscr\_node\_size}=\\{attr\_node\_size}$}\2\6 -\1\&{repeat} \37$\\{flush\_below\_variable}(\|q)$;\5 -$\|r\K\|q$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{free\_node}(\|r,\39\\{attr\_node\_size})$;\6 -\4\&{until}\5 -$\|q=\\{end\_attr}$;\2\6 -$\\{type}(\|p)\K\\{undefined}$;\6 -\&{end};\2\6 -\&{end};\par -\U246.\fi - -\M248. Just before assigning a new value to a variable, we will recycle the -old value and make the old value undefined. The \\{und\_type} routine -determines what type of undefined value should be given, based on -the current type before recycling. - -\Y\P\4\&{function}\1\ \37$\\{und\_type}(\|p:\\{pointer})$: \37\\{small% -\_number};\2\6 -\&{begin} \37\&{case} $\\{type}(\|p)$ \1\&{of}\6 -\4$\\{undefined},\39\\{vacuous}$: \37$\\{und\_type}\K\\{undefined}$;\6 -\4$\\{boolean\_type},\39\\{unknown\_boolean}$: \37$\\{und\_type}\K\\{unknown% -\_boolean}$;\6 -\4$\\{string\_type},\39\\{unknown\_string}$: \37$\\{und\_type}\K\\{unknown% -\_string}$;\6 -\4$\\{pen\_type},\39\\{unknown\_pen},\39\\{future\_pen}$: \37$\\{und\_type}\K% -\\{unknown\_pen}$;\6 -\4$\\{path\_type},\39\\{unknown\_path}$: \37$\\{und\_type}\K\\{unknown\_path}$;% -\6 -\4$\\{picture\_type},\39\\{unknown\_picture}$: \37$\\{und\_type}\K\\{unknown% -\_picture}$;\6 -\4$\\{transform\_type},\39\\{pair\_type},\39\\{numeric\_type}$: \37$\\{und% -\_type}\K\\{type}(\|p)$;\6 -\4$\\{known},\39\\{dependent},\39\\{proto\_dependent},\39\\{independent}$: \37$% -\\{und\_type}\K\\{numeric\_type}$;\2\6 -\&{end};\C{there are no other cases}\6 -\&{end};\par -\fi - -\M249. The \\{clear\_symbol} routine is used when we want to redefine the -equivalent -of a symbolic token. It must remove any variable structure or macro -definition that is currently attached to that symbol. If the \\{saving} -parameter is true, a subsidiary structure is saved instead of destroyed. - -\Y\P\4\&{procedure}\1\ \37$\\{clear\_symbol}(\|p:\\{pointer};\,\35\\{saving}:% -\\{boolean})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{$\\{equiv}(\|p)$}\2\6 -\&{begin} \37$\|q\K\\{equiv}(\|p)$;\6 -\&{case} $\\{eq\_type}(\|p)\mathbin{\&{mod}}\\{outer\_tag}$ \1\&{of}\6 -\4$\\{defined\_macro},\39\\{secondary\_primary\_macro},\39\\{tertiary% -\_secondary\_macro},\39\\{expression\_tertiary\_macro}$: \37\&{if} $\R% -\\{saving}$ \1\&{then}\5 -$\\{delete\_mac\_ref}(\|q)$;\2\6 -\4\\{tag\_token}: \37\&{if} $\|q\I\\{null}$ \1\&{then}\6 -\&{if} $\\{saving}$ \1\&{then}\5 -$\\{name\_type}(\|q)\K\\{saved\_root}$\6 -\4\&{else} \&{begin} \37$\\{flush\_below\_variable}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{value\_node\_size})$;\6 -\&{end};\2\6 -\4\&{othercases} \\{do\_nothing}\2\2\6 -\&{endcases};\6 -$\\{eqtb}[\|p]\K\\{eqtb}[\\{frozen\_undefined}]$;\6 -\&{end};\par -\fi - -\N250. \[16] Saving and restoring equivalents. -The nested structure provided by \&{begingroup} and \&{endgroup} -allows \\{eqtb} entries to be saved and restored, so that temporary changes -can be made without difficulty. When the user requests a current value to -be saved, \MF\ puts that value into its ``save stack.'' An appearance of -\&{endgroup} ultimately causes the old values to be removed from the save -stack and put back in their former places. - -The save stack is a linked list containing three kinds of entries, -distinguished by their \\{info} fields. If \|p points to a saved item, -then - -\smallskip\hang -$\\{info}(\|p)=0$ stands for a group boundary; each \&{begingroup} contributes -such an item to the save stack and each \&{endgroup} cuts back the stack -until the most recent such entry has been removed. - -\smallskip\hang -$\\{info}(\|p)=\|q$, where $1\L\|q\L\\{hash\_end}$, means that $\\{mem}[\|p+1]$ -holds the former -contents of $\\{eqtb}[\|q]$. Such save stack entries are generated by \&{save} -commands or suitable \&{interim} commands. - -\smallskip\hang -$\\{info}(\|p)=\\{hash\_end}+\|q$, where $\|q>0$, means that $\\{value}(\|p)$ -is a \\{scaled} -integer to be restored to internal parameter number~\|q. Such entries -are generated by \&{interim} commands. - -\smallskip\noindent -The global variable \\{save\_ptr} points to the top item on the save stack. - -\Y\P\D \37$\\{save\_node\_size}=2$\C{number of words per non-boundary -save-stack node}\par -\P\D \37$\\{saved\_equiv}(\#)\S\\{mem}[\#+1].\\{hh}$\C{where an \\{eqtb} entry -gets saved}\par -\P\D \37$\\{save\_boundary\_item}(\#)\S$\1\6 -\&{begin} \37$\#\K\\{get\_avail}$;\5 -$\\{info}(\#)\K0$;\5 -$\\{link}(\#)\K\\{save\_ptr}$;\5 -$\\{save\_ptr}\K\#$;\6 -\&{end}\2\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{save\_ptr}: \37\\{pointer};\C{the most recently saved item}\par -\fi - -\M251. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{save\_ptr}\K\\{null}$;\par -\fi - -\M252. The \\{save\_variable} routine is given a hash address \|q; it salts -this -address in the save stack, together with its current equivalent, -then makes token~\|q behave as though it were brand new. - -Nothing is stacked when $\\{save\_ptr}=\\{null}$, however; there's no way to -remove -things from the stack when the program is not inside a group, so there's -no point in wasting the space. - -\Y\P\4\&{procedure}\1\ \37$\\{save\_variable}(\|q:\\{pointer})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\\{save\_ptr}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{save\_node\_size})$;\5 -$\\{info}(\|p)\K\|q$;\5 -$\\{link}(\|p)\K\\{save\_ptr}$;\5 -$\\{saved\_equiv}(\|p)\K\\{eqtb}[\|q]$;\5 -$\\{save\_ptr}\K\|p$;\6 -\&{end};\2\6 -$\\{clear\_symbol}(\|q,\39(\\{save\_ptr}\I\\{null}))$;\6 -\&{end};\par -\fi - -\M253. Similarly, \\{save\_internal} is given the location \|q of an internal -quantity like \\{tracing\_pens}. It creates a save stack entry of the -third kind. - -\Y\P\4\&{procedure}\1\ \37$\\{save\_internal}(\|q:\\{halfword})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{new item for the save stack}\2\6 -\&{begin} \37\&{if} $\\{save\_ptr}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{save\_node\_size})$;\5 -$\\{info}(\|p)\K\\{hash\_end}+\|q$;\5 -$\\{link}(\|p)\K\\{save\_ptr}$;\5 -$\\{value}(\|p)\K\\{internal}[\|q]$;\5 -$\\{save\_ptr}\K\|p$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M254. At the end of a group, the \\{unsave} routine restores all of the saved -equivalents in reverse order. This routine will be called only when there -is at least one boundary item on the save stack. - -\Y\P\4\&{procedure}\1\ \37\\{unsave};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{index to saved item}\6 -\|p: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37\&{while} $\\{info}(\\{save\_ptr})\I0$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{info}(\\{save\_ptr})$;\6 -\&{if} $\|q>\\{hash\_end}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_restores}]>0$ \1\&{then}\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{restoring\ "})$;\5 -$\\{slow\_print}(\\{int\_name}[\|q-(\\{hash\_end})])$;\5 -$\\{print\_char}(\.{"="})$;\5 -$\\{print\_scaled}(\\{value}(\\{save\_ptr}))$;\5 -$\\{print\_char}(\.{"\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end};\2\6 -$\\{internal}[\|q-(\\{hash\_end})]\K\\{value}(\\{save\_ptr})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{internal}[\\{tracing\_restores}]>0$ \1% -\&{then}\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{restoring\ "})$;\5 -$\\{slow\_print}(\\{text}(\|q))$;\5 -$\\{print\_char}(\.{"\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end};\2\6 -$\\{clear\_symbol}(\|q,\39\\{false})$;\5 -$\\{eqtb}[\|q]\K\\{saved\_equiv}(\\{save\_ptr})$;\6 -\&{if} $\\{eq\_type}(\|q)\mathbin{\&{mod}}\\{outer\_tag}=\\{tag\_token}$ \1% -\&{then}\6 -\&{begin} \37$\|p\K\\{equiv}(\|q)$;\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\5 -$\\{name\_type}(\|p)\K\\{root}$;\2\6 -\&{end};\2\6 -\&{end};\2\6 -$\|p\K\\{link}(\\{save\_ptr})$;\5 -$\\{free\_node}(\\{save\_ptr},\39\\{save\_node\_size})$;\5 -$\\{save\_ptr}\K\|p$;\6 -\&{end};\2\6 -$\|p\K\\{link}(\\{save\_ptr})$;\5 -$\\{free\_avail}(\\{save\_ptr})$;\5 -$\\{save\_ptr}\K\|p$;\6 -\&{end};\par -\fi - -\N255. \[17] Data structures for paths. -When a \MF\ user specifies a path, \MF\ will create a list of knots -and control points for the associated cubic spline curves. If the -knots are $z_0$, $z_1$, \dots, $z_n$, there are control points -$z_k^+$ and $z_{k+1}^-$ such that the cubic splines between knots -$z_k$ and $z_{k+1}$ are defined by B\'ezier's formula -$$\eqalign{z(t)&=B(z_k,z_k^+,z_{k+1}^-,z_{k+1};t)\cr -&=(1-t)^3z_k+3(1-t)^2tz_k^++3(1-t)t^2z_{k+1}^-+t^3z_{k+1}\cr}$$ -for $0\L\|t\L1$. - -There is a 7-word node for each knot $z_k$, containing one word of -control information and six words for the \|x and \|y coordinates -of $z_k^-$ and $z_k$ and~$z_k^+$. The control information appears -in the \\{left\_type} and \\{right\_type} fields, which each occupy -a quarter of the first word in the node; they specify properties -of the curve as it enters and leaves the knot. There's also a -halfword \\{link} field, which points to the following knot. - -If the path is a closed contour, knots 0 and \|n are identical; -i.e., the \\{link} in knot $\|n-1$ points to knot~0. But if the path -is not closed, the \\{left\_type} of knot~0 and the \\{right\_type} of knot~\|n -are equal to \\{endpoint}. In the latter case the \\{link} in knot~\|n points -to knot~0, and the control points $z_0^-$ and $z_n^+$ are not used. - -\Y\P\D \37$\\{left\_type}(\#)\S\\{mem}[\#].\\{hh}.\\{b0}$\C{characterizes the -path entering this knot}\par -\P\D \37$\\{right\_type}(\#)\S\\{mem}[\#].\\{hh}.\\{b1}$\C{characterizes the -path leaving this knot}\par -\P\D \37$\\{endpoint}=0$\C{\\{left\_type} at path beginning and \\{right\_type} -at path end}\par -\P\D \37$\\{x\_coord}(\#)\S\\{mem}[\#+1].\\{sc}$\C{the \|x coordinate of this -knot}\par -\P\D \37$\\{y\_coord}(\#)\S\\{mem}[\#+2].\\{sc}$\C{the \|y coordinate of this -knot}\par -\P\D \37$\\{left\_x}(\#)\S\\{mem}[\#+3].\\{sc}$\C{the \|x coordinate of -previous control point}\par -\P\D \37$\\{left\_y}(\#)\S\\{mem}[\#+4].\\{sc}$\C{the \|y coordinate of -previous control point}\par -\P\D \37$\\{right\_x}(\#)\S\\{mem}[\#+5].\\{sc}$\C{the \|x coordinate of next -control point}\par -\P\D \37$\\{right\_y}(\#)\S\\{mem}[\#+6].\\{sc}$\C{the \|y coordinate of next -control point}\par -\P\D \37$\\{knot\_node\_size}=7$\C{number of words in a knot node}\par -\fi - -\M256. Before the B\'ezier control points have been calculated, the memory -space they will ultimately occupy is taken up by information that can be -used to compute them. There are four cases: - -\yskip -\textindent{$\bullet$} If $\\{right\_type}=\\{open}$, the curve should leave -the knot in the same direction it entered; \MF\ will figure out a -suitable direction. - -\yskip -\textindent{$\bullet$} If $\\{right\_type}=\\{curl}$, the curve should leave -the -knot in a direction depending on the angle at which it enters the next -knot and on the curl parameter stored in \\{right\_curl}. - -\yskip -\textindent{$\bullet$} If $\\{right\_type}=\\{given}$, the curve should leave -the -knot in a nonzero direction stored as an \\{angle} in \\{right\_given}. - -\yskip -\textindent{$\bullet$} If $\\{right\_type}=\\{explicit}$, the B\'ezier control -point for leaving this knot has already been computed; it is in the -\\{right\_x} and \\{right\_y} fields. - -\yskip\noindent -The rules for \\{left\_type} are similar, but they refer to the curve entering -the knot, and to \\{left} fields instead of \\{right} fields. - -Non-\\{explicit} control points will be chosen based on ``tension'' parameters -in the \\{left\_tension} and \\{right\_tension} fields. The -`\&{atleast}' option is represented by negative tension values. - -For example, the \MF\ path specification -$$\.{z0..z1..tension atleast 1..\{curl 2\}z2..z3\{-1,-2\}..tension -3 and 4..p},$$ -where \.p is the path `\.{z4..controls z45 and z54..z5}', will be represented -by the six knots -\def\lodash{\hbox to 1.1em{\thinspace\hrulefill\thinspace}} -$$\vbox{\halign{#\hfil&&\qquad#\hfil\cr -\\{left\_type}&\\{left} info&$\\{x\_coord},\\{y\_coord}$&\\{right\_type}&% -\\{right} info\cr -\noalign{\yskip} -\\{endpoint}&\lodash$,\,$\lodash&$x_0,y_0$&\\{curl}&$1.0,1.0$\cr -\\{open}&\lodash$,1.0$&$x_1,y_1$&\\{open}&\lodash$,-1.0$\cr -\\{curl}&$2.0,-1.0$&$x_2,y_2$&\\{curl}&$2.0,1.0$\cr -\\{given}&$d,1.0$&$x_3,y_3$&\\{given}&$d,3.0$\cr -\\{open}&\lodash$,4.0$&$x_4,y_4$&\\{explicit}&$x_{45},y_{45}$\cr -\\{explicit}&$x_{54},y_{54}$&$x_5,y_5$&\\{endpoint}&\lodash$,\,$\lodash\cr}}$$ -Here \|d is the \\{angle} obtained by calling $\\{n\_arg}(-\\{unity},-% -\\{two})$. -Of course, this example is more complicated than anything a normal user -would ever write. - -These types must satisfy certain restrictions because of the form of \MF's -path syntax: -(i)~\\{open} type never appears in the same node together with \\{endpoint}, -\\{given}, or \\{curl}. -(ii)~The \\{right\_type} of a node is \\{explicit} if and only if the -\\{left\_type} of the following node is \\{explicit}. -(iii)~\\{endpoint} types occur only at the ends, as mentioned above. - -\Y\P\D \37$\\{left\_curl}\S\\{left\_x}$\C{curl information when entering this -knot}\par -\P\D \37$\\{left\_given}\S\\{left\_x}$\C{given direction when entering this -knot}\par -\P\D \37$\\{left\_tension}\S\\{left\_y}$\C{tension information when entering -this knot}\par -\P\D \37$\\{right\_curl}\S\\{right\_x}$\C{curl information when leaving this -knot}\par -\P\D \37$\\{right\_given}\S\\{right\_x}$\C{given direction when leaving this -knot}\par -\P\D \37$\\{right\_tension}\S\\{right\_y}$\C{tension information when leaving -this knot}\par -\P\D \37$\\{explicit}=1$\C{\\{left\_type} or \\{right\_type} when control -points are known}\par -\P\D \37$\\{given}=2$\C{\\{left\_type} or \\{right\_type} when a direction is -given}\par -\P\D \37$\\{curl}=3$\C{\\{left\_type} or \\{right\_type} when a curl is -desired}\par -\P\D \37$\\{open}=4$\C{\\{left\_type} or \\{right\_type} when \MF\ should -choose the direction}\par -\fi - -\M257. Here is a diagnostic routine that prints a given knot list -in symbolic form. It illustrates the conventions discussed above, -and checks for anomalies that might arise while \MF\ is being debugged. - -\Y\P$\4\X257:Declare subroutines for printing expressions\X\S$\6 -\4\&{procedure}\1\ \37$\\{print\_path}(\|h:\\{pointer};\,\35\|s:\\{str% -\_number};\,\35\\{nuline}:\\{boolean})$;\6 -\4\&{label} \37$\\{done},\39\\{done1}$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{for list traversal}\2\6 -\&{begin} \37$\\{print\_diagnostic}(\.{"Path"},\39\|s,\39\\{nuline})$;\5 -\\{print\_ln};\5 -$\|p\K\|h$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|p)$;\6 -\&{if} $(\|p=\\{null})\V(\|q=\\{null})$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"???"})$;\5 -\&{goto} \37\\{done};\C{this won't happen}\6 -\&{end};\2\6 -\X258:Print information for adjacent knots \|p and \|q\X;\6 -$\|p\K\|q$;\6 -\&{if} $(\|p\I\|h)\V(\\{left\_type}(\|h)\I\\{endpoint})$ \1\&{then}\5 -\X259:Print two dots, followed by \\{given} or \\{curl} if present\X;\2\6 -\4\&{until}\5 -$\|p=\|h$;\2\6 -\&{if} $\\{left\_type}(\|h)\I\\{endpoint}$ \1\&{then}\5 -$\\{print}(\.{"cycle"})$;\2\6 -\4\\{done}: \37$\\{end\_diagnostic}(\\{true})$;\6 -\&{end};\par -\As332, 388, 473, 589, 801\ETs807. -\U246.\fi - -\M258. \P$\X258:Print information for adjacent knots \|p and \|q\X\S$\6 -$\\{print\_two}(\\{x\_coord}(\|p),\39\\{y\_coord}(\|p))$;\6 -\&{case} $\\{right\_type}(\|p)$ \1\&{of}\6 -\4\\{endpoint}: \37\&{begin} \37\&{if} $\\{left\_type}(\|p)=\\{open}$ \1% -\&{then}\5 -$\\{print}(\.{"\{open?\}"})$;\C{can't happen}\2\6 -\&{if} $(\\{left\_type}(\|q)\I\\{endpoint})\V(\|q\I\|h)$ \1\&{then}\5 -$\|q\K\\{null}$;\C{force an error}\2\6 -\&{goto} \37\\{done1};\6 -\&{end};\6 -\4\\{explicit}: \37\X261:Print control points between \|p and \|q, then % -\&{goto} \\{done1}\X;\6 -\4\\{open}: \37\X262:Print information for a curve that begins \\{open}\X;\6 -\4$\\{curl},\39\\{given}$: \37\X263:Print information for a curve that begins % -\\{curl} or \\{given}\X;\6 -\4\&{othercases} \37$\\{print}(\.{"???"})$\C{can't happen}\2\6 -\&{endcases};\6 -\&{if} $\\{left\_type}(\|q)\L\\{explicit}$ \1\&{then}\5 -$\\{print}(\.{"..control?"})$\C{can't happen}\6 -\4\&{else} \&{if} $(\\{right\_tension}(\|p)\I\\{unity})\V(\\{left\_tension}(% -\|q)\I\\{unity})$ \1\&{then}\5 -\X260:Print tension between \|p and \|q\X;\2\2\6 -\4\\{done1}: \37\par -\U257.\fi - -\M259. Since \\{n\_sin\_cos} produces \\{fraction} results, which we will print -as if they -were \\{scaled}, the magnitude of a \\{given} direction vector will be~4096. - -\Y\P$\4\X259:Print two dots, followed by \\{given} or \\{curl} if present\X\S$\6 -\&{begin} \37$\\{print\_nl}(\.{"\ .."})$;\6 -\&{if} $\\{left\_type}(\|p)=\\{given}$ \1\&{then}\6 -\&{begin} \37$\\{n\_sin\_cos}(\\{left\_given}(\|p))$;\5 -$\\{print\_char}(\.{"\{"})$;\5 -$\\{print\_scaled}(\\{n\_cos})$;\5 -$\\{print\_char}(\.{","})$;\5 -$\\{print\_scaled}(\\{n\_sin})$;\5 -$\\{print\_char}(\.{"\}"})$;\6 -\&{end}\6 -\4\&{else} \&{if} $\\{left\_type}(\|p)=\\{curl}$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\{curl\ "})$;\5 -$\\{print\_scaled}(\\{left\_curl}(\|p))$;\5 -$\\{print\_char}(\.{"\}"})$;\6 -\&{end};\2\2\6 -\&{end}\par -\U257.\fi - -\M260. \P$\X260:Print tension between \|p and \|q\X\S$\6 -\&{begin} \37$\\{print}(\.{"..tension\ "})$;\6 -\&{if} $\\{right\_tension}(\|p)<0$ \1\&{then}\5 -$\\{print}(\.{"atleast"})$;\2\6 -$\\{print\_scaled}(\\{abs}(\\{right\_tension}(\|p)))$;\6 -\&{if} $\\{right\_tension}(\|p)\I\\{left\_tension}(\|q)$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\ and\ "})$;\6 -\&{if} $\\{left\_tension}(\|q)<0$ \1\&{then}\5 -$\\{print}(\.{"atleast"})$;\2\6 -$\\{print\_scaled}(\\{abs}(\\{left\_tension}(\|q)))$;\6 -\&{end};\2\6 -\&{end}\par -\U258.\fi - -\M261. \P$\X261:Print control points between \|p and \|q, then \&{goto} % -\\{done1}\X\S$\6 -\&{begin} \37$\\{print}(\.{"..controls\ "})$;\5 -$\\{print\_two}(\\{right\_x}(\|p),\39\\{right\_y}(\|p))$;\5 -$\\{print}(\.{"\ and\ "})$;\6 -\&{if} $\\{left\_type}(\|q)\I\\{explicit}$ \1\&{then}\5 -$\\{print}(\.{"??"})$\C{can't happen}\6 -\4\&{else} $\\{print\_two}(\\{left\_x}(\|q),\39\\{left\_y}(\|q))$;\2\6 -\&{goto} \37\\{done1};\6 -\&{end}\par -\U258.\fi - -\M262. \P$\X262:Print information for a curve that begins \\{open}\X\S$\6 -\&{if} $(\\{left\_type}(\|p)\I\\{explicit})\W(\\{left\_type}(\|p)\I\\{open})$ % -\1\&{then}\5 -$\\{print}(\.{"\{open?\}"})$\C{can't happen}\2\par -\U258.\fi - -\M263. A curl of 1 is shown explicitly, so that the user sees clearly that -\MF's default curl is present. - -The code here uses the fact that $\\{left\_curl}\S\\{left\_given}$ and -$\\{right\_curl}\S\\{right\_given}$. - -\Y\P$\4\X263:Print information for a curve that begins \\{curl} or \\{given}\X% -\S$\6 -\&{begin} \37\&{if} $\\{left\_type}(\|p)=\\{open}$ \1\&{then}\5 -$\\{print}(\.{"??"})$;\C{can't happen}\2\6 -\&{if} $\\{right\_type}(\|p)=\\{curl}$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\{curl\ "})$;\5 -$\\{print\_scaled}(\\{right\_curl}(\|p))$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{n\_sin\_cos}(\\{right\_given}(\|p))$;\5 -$\\{print\_char}(\.{"\{"})$;\5 -$\\{print\_scaled}(\\{n\_cos})$;\5 -$\\{print\_char}(\.{","})$;\5 -$\\{print\_scaled}(\\{n\_sin})$;\6 -\&{end};\2\6 -$\\{print\_char}(\.{"\}"})$;\6 -\&{end}\par -\U258.\fi - -\M264. If we want to duplicate a knot node, we can say \\{copy\_knot}: - -\Y\P\4\&{function}\1\ \37$\\{copy\_knot}(\|p:\\{pointer})$: \37\\{pointer};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the copy}\6 -\|k: \37$0\to\\{knot\_node\_size}-1$;\C{runs through the words of a knot node}% -\2\6 -\&{begin} \37$\|q\K\\{get\_node}(\\{knot\_node\_size})$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{knot\_node\_size}-1$ \1\&{do}\5 -$\\{mem}[\|q+\|k]\K\\{mem}[\|p+\|k]$;\2\6 -$\\{copy\_knot}\K\|q$;\6 -\&{end};\par -\fi - -\M265. The \\{copy\_path} routine makes a clone of a given path. - -\Y\P\4\&{function}\1\ \37$\\{copy\_path}(\|p:\\{pointer})$: \37\\{pointer};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|q,\39\\{pp},\39\\{qq}$: \37\\{pointer};\C{for list -manipulation}\2\6 -\&{begin} \37$\|q\K\\{get\_node}(\\{knot\_node\_size})$;\C{this will correspond -to \|p}\6 -$\\{qq}\K\|q$;\5 -$\\{pp}\K\|p$;\6 -\~ \1\&{loop}\ \&{begin} \37$\\{left\_type}(\\{qq})\K\\{left\_type}(\\{pp})$;\5 -$\\{right\_type}(\\{qq})\K\\{right\_type}(\\{pp})$;\6 -$\\{x\_coord}(\\{qq})\K\\{x\_coord}(\\{pp})$;\5 -$\\{y\_coord}(\\{qq})\K\\{y\_coord}(\\{pp})$;\6 -$\\{left\_x}(\\{qq})\K\\{left\_x}(\\{pp})$;\5 -$\\{left\_y}(\\{qq})\K\\{left\_y}(\\{pp})$;\6 -$\\{right\_x}(\\{qq})\K\\{right\_x}(\\{pp})$;\5 -$\\{right\_y}(\\{qq})\K\\{right\_y}(\\{pp})$;\6 -\&{if} $\\{link}(\\{pp})=\|p$ \1\&{then}\6 -\&{begin} \37$\\{link}(\\{qq})\K\|q$;\5 -$\\{copy\_path}\K\|q$;\5 -\&{return};\6 -\&{end};\2\6 -$\\{link}(\\{qq})\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{qq}\K\\{link}(\\{qq})$;\5 -$\\{pp}\K\\{link}(\\{pp})$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M266. Similarly, there's a way to copy the {\sl reverse\/} of a path. This -procedure -returns a pointer to the first node of the copy, if the path is a cycle, -but to the final node of a non-cyclic copy. The global -variable \\{path\_tail} will point to the final node of the original path; -this trick makes it easier to implement `\&{doublepath}'. - -All node types are assumed to be \\{endpoint} or \\{explicit} only. - -\Y\P\4\&{function}\1\ \37$\\{htap\_ypoc}(\|p:\\{pointer})$: \37\\{pointer};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|q,\39\\{pp},\39\\{qq},\39\\{rr}$: \37\\{pointer};\C{for list -manipulation}\2\6 -\&{begin} \37$\|q\K\\{get\_node}(\\{knot\_node\_size})$;\C{this will correspond -to \|p}\6 -$\\{qq}\K\|q$;\5 -$\\{pp}\K\|p$;\6 -\~ \1\&{loop}\ \&{begin} \37$\\{right\_type}(\\{qq})\K\\{left\_type}(\\{pp})$;\5 -$\\{left\_type}(\\{qq})\K\\{right\_type}(\\{pp})$;\6 -$\\{x\_coord}(\\{qq})\K\\{x\_coord}(\\{pp})$;\5 -$\\{y\_coord}(\\{qq})\K\\{y\_coord}(\\{pp})$;\6 -$\\{right\_x}(\\{qq})\K\\{left\_x}(\\{pp})$;\5 -$\\{right\_y}(\\{qq})\K\\{left\_y}(\\{pp})$;\6 -$\\{left\_x}(\\{qq})\K\\{right\_x}(\\{pp})$;\5 -$\\{left\_y}(\\{qq})\K\\{right\_y}(\\{pp})$;\6 -\&{if} $\\{link}(\\{pp})=\|p$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|q)\K\\{qq}$;\5 -$\\{path\_tail}\K\\{pp}$;\5 -$\\{htap\_ypoc}\K\|q$;\5 -\&{return};\6 -\&{end};\2\6 -$\\{rr}\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{link}(\\{rr})\K\\{qq}$;\5 -$\\{qq}\K\\{rr}$;\5 -$\\{pp}\K\\{link}(\\{pp})$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M267. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{path\_tail}: \37\\{pointer};\C{the node that links to the beginning of a -path}\par -\fi - -\M268. When a cyclic list of knot nodes is no longer needed, it can be recycled -by -calling the following subroutine. - -\Y\P$\4\X268:Declare the recycling subroutines\X\S$\6 -\4\&{procedure}\1\ \37$\\{toss\_knot\_list}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the node being freed}\6 -\|r: \37\\{pointer};\C{the next node}\2\6 -\&{begin} \37$\|q\K\|p$;\6 -\1\&{repeat} \37$\|r\K\\{link}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{knot\_node\_size})$;\5 -$\|q\K\|r$;\6 -\4\&{until}\5 -$\|q=\|p$;\2\6 -\&{end};\par -\As385, 487, 620\ETs809. -\U246.\fi - -\N269. \[18] Choosing control points. -Now we must actually delve into one of \MF's more difficult routines, -the \\{make\_choices} procedure that chooses angles and control points for -the splines of a curve when the user has not specified them explicitly. -The parameter to \\{make\_choices} points to a list of knots and -path information, as described above. - -A path decomposes into independent segments at ``breakpoint'' knots, -which are knots whose left and right angles are both prespecified in -some way (i.e., their \\{left\_type} and \\{right\_type} aren't both open). - -\Y\P\hbox{\4}\X284:Declare the procedure called \\{solve\_choices}\X\6 -\4\&{procedure}\1\ \37$\\{make\_choices}(\\{knots}:\\{pointer})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|h: \37\\{pointer};\C{the first breakpoint}\6 -$\|p,\39\|q$: \37\\{pointer};\C{consecutive breakpoints being processed}\6 -\X280:Other local variables for \\{make\_choices}\X\2\6 -\&{begin} \37\\{check\_arith};\C{make sure that $\\{arith\_error}=\\{false}$}\6 -\&{if} $\\{internal}[\\{tracing\_choices}]>0$ \1\&{then}\5 -$\\{print\_path}(\\{knots},\39\.{",\ before\ choices"},\39\\{true})$;\2\6 -\X271:If consecutive knots are equal, join them explicitly\X;\6 -\X272:Find the first breakpoint, \|h, on the path; insert an artificial -breakpoint if the path is an unbroken cycle\X;\6 -$\|p\K\|h$;\6 -\1\&{repeat} \37\X273:Fill in the control points between \|p and the next -breakpoint, then advance \|p to that breakpoint\X;\6 -\4\&{until}\5 -$\|p=\|h$;\2\6 -\&{if} $\\{internal}[\\{tracing\_choices}]>0$ \1\&{then}\5 -$\\{print\_path}(\\{knots},\39\.{",\ after\ choices"},\39\\{true})$;\2\6 -\&{if} $\\{arith\_error}$ \1\&{then}\5 -\X270:Report an unexpected problem during the choice-making\X;\2\6 -\&{end};\par -\fi - -\M270. \P$\X270:Report an unexpected problem during the choice-making\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Some\ number\ got\ too\ big"})$;\5 -$\\{help2}(\.{"The\ path\ that\ I\ just\ computed\ is\ out\ of\ range."})$\6 -$(\.{"So\ it\ will\ probably\ look\ funny.\ Proceed,\ for\ a\ laugh."})$;\5 -\\{put\_get\_error};\5 -$\\{arith\_error}\K\\{false}$;\6 -\&{end}\par -\U269.\fi - -\M271. Two knots in a row with the same coordinates will always be joined -by an explicit ``curve'' whose control points are identical with the -knots. - -\Y\P$\4\X271:If consecutive knots are equal, join them explicitly\X\S$\6 -$\|p\K\\{knots}$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|p)$;\6 -\&{if} $\\{x\_coord}(\|p)=\\{x\_coord}(\|q)$ \1\&{then}\6 -\&{if} $\\{y\_coord}(\|p)=\\{y\_coord}(\|q)$ \1\&{then}\6 -\&{if} $\\{right\_type}(\|p)>\\{explicit}$ \1\&{then}\6 -\&{begin} \37$\\{right\_type}(\|p)\K\\{explicit}$;\6 -\&{if} $\\{left\_type}(\|p)=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{left\_type}(\|p)\K\\{curl}$;\5 -$\\{left\_curl}(\|p)\K\\{unity}$;\6 -\&{end};\2\6 -$\\{left\_type}(\|q)\K\\{explicit}$;\6 -\&{if} $\\{right\_type}(\|q)=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{right\_type}(\|q)\K\\{curl}$;\5 -$\\{right\_curl}(\|q)\K\\{unity}$;\6 -\&{end};\2\6 -$\\{right\_x}(\|p)\K\\{x\_coord}(\|p)$;\5 -$\\{left\_x}(\|q)\K\\{x\_coord}(\|p)$;\6 -$\\{right\_y}(\|p)\K\\{y\_coord}(\|p)$;\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|p)$;\6 -\&{end};\2\2\2\6 -$\|p\K\|q$;\6 -\4\&{until}\5 -$\|p=\\{knots}$\2\par -\U269.\fi - -\M272. If there are no breakpoints, it is necessary to compute the direction -angles around an entire cycle. In this case the \\{left\_type} of the first -node is temporarily changed to \\{end\_cycle}. - -\Y\P\D \37$\\{end\_cycle}=\\{open}+1$\par -\Y\P$\4\X272:Find the first breakpoint, \|h, on the path; insert an artificial -breakpoint if the path is an unbroken cycle\X\S$\6 -$\|h\K\\{knots}$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\\{left\_type}(\|h)\I\\{open}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{right\_type}(\|h)\I\\{open}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|h\K\\{link}(\|h)$;\6 -\&{if} $\|h=\\{knots}$ \1\&{then}\6 -\&{begin} \37$\\{left\_type}(\|h)\K\\{end\_cycle}$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U269.\fi - -\M273. If $\\{right\_type}(\|p)<\\{given}$ and $\|q=\\{link}(\|p)$, we must -have -$\\{right\_type}(\|p)=\\{left\_type}(\|q)=\\{explicit}$ or \\{endpoint}. - -\Y\P$\4\X273:Fill in the control points between \|p and the next breakpoint, -then advance \|p to that breakpoint\X\S$\6 -$\|q\K\\{link}(\|p)$;\6 -\&{if} $\\{right\_type}(\|p)\G\\{given}$ \1\&{then}\6 -\&{begin} \37\&{while} $(\\{left\_type}(\|q)=\\{open})\W(\\{right\_type}(\|q)=% -\\{open})$ \1\&{do}\5 -$\|q\K\\{link}(\|q)$;\2\6 -\X278:Fill in the control information between consecutive breakpoints \|p and % -\|q\X;\6 -\&{end};\2\6 -$\|p\K\|q$\par -\U269.\fi - -\M274. Before we can go further into the way choices are made, we need to -consider the underlying theory. The basic ideas implemented in \\{make% -\_choices} -are due to John Hobby, who introduced the notion of ``mock curvature'' -at a knot. Angles are chosen so that they preserve mock curvature when -a knot is passed, and this has been found to produce excellent results. - -It is convenient to introduce some notations that simplify the necessary -formulas. Let $d_{k,k+1}=\vert z\k-z_k\vert$ be the (nonzero) distance -between knots \|k and $\|k+1$; and let -$${z\k-z_k\over z_k-z_{k-1}}={d_{k,k+1}\over d_{k-1,k}}e^{i\psi_k}$$ -so that a polygonal line from $z_{k-1}$ to $z_k$ to $z\k$ turns left -through an angle of~$\psi_k$. We assume that $\vert\psi_k\vert\L180^\circ$. -The control points for the spline from $z_k$ to $z\k$ will be denoted by -$$\eqalign{z_k^+&=z_k+ -\textstyle{1\over3}\rho_k e^{i\theta_k}(z\k-z_k),\cr -z\k^-&=z\k- -\textstyle{1\over3}\sigma\k e^{-i\phi\k}(z\k-z_k),\cr}$$ -where $\rho_k$ and $\sigma\k$ are nonnegative ``velocity ratios'' at the -beginning and end of the curve, while $\theta_k$ and $\phi\k$ are the -corresponding ``offset angles.'' These angles satisfy the condition -$$\theta_k+\phi_k+\psi_k=0,\eqno(*)$$ -whenever the curve leaves an intermediate knot~\|k in the direction that -it enters. - -\fi - -\M275. Let $\alpha_k$ and $\beta\k$ be the reciprocals of the ``tension'' of -the curve at its beginning and ending points. This means that -$\rho_k=\alpha_k f(\theta_k,\phi\k)$ and $\sigma\k=\beta\k f(\phi\k,\theta_k)$, -where $f(\theta,\phi)$ is \MF's standard velocity function defined in -the \\{velocity} subroutine. The cubic spline $B(z_k^{\phantom+},z_k^+, -z\k^-,z\k^{\phantom+};t)$ -has curvature -$${2\sigma\k\sin(\theta_k+\phi\k)-6\sin\theta_k\over\rho_k^2d_{k,k+1}} -\qquad{\rm and}\qquad -{2\rho_k\sin(\theta_k+\phi\k)-6\sin\phi\k\over\sigma\k^2d_{k,k+1}}$$ -at $\|t=0$ and $\|t=1$, respectively. The mock curvature is the linear -approximation to this true curvature that arises in the limit for -small $\theta_k$ and~$\phi\k$, if second-order terms are discarded. -The standard velocity function satisfies -$$f(\theta,\phi)=1+O(\theta^2+\theta\phi+\phi^2);$$ -hence the mock curvatures are respectively -$${2\beta\k(\theta_k+\phi\k)-6\theta_k\over\alpha_k^2d_{k,k+1}} -\qquad{\rm and}\qquad -{2\alpha_k(\theta_k+\phi\k)-6\phi\k\over\beta\k^2d_{k,k+1}}.\eqno(**)$$ - -\fi - -\M276. The turning angles $\psi_k$ are given, and equation $(*)$ above -determines $\phi_k$ when $\theta_k$ is known, so the task of -angle selection is essentially to choose appropriate values for each -$\theta_k$. When equation~$(*)$ is used to eliminate $\phi$~variables -from $(**)$, we obtain a system of linear equations of the form -$$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k,$$ -where -$$A_k={\alpha_{k-1}\over\beta_k^2d_{k-1,k}}, -\qquad B_k={3-\alpha_{k-1}\over\beta_k^2d_{k-1,k}}, -\qquad C_k={3-\beta\k\over\alpha_k^2d_{k,k+1}}, -\qquad D_k={\beta\k\over\alpha_k^2d_{k,k+1}}.$$ -The tensions are always $3\over4$ or more, hence each $\alpha$ and~$\beta$ -will be at most $4\over3$. It follows that $B_k\G{5\over4}A_k$ and -$C_k\G{5\over4}D_k$; hence the equations are diagonally dominant; -hence they have a unique solution. Moreover, in most cases the tensions -are equal to~1, so that $B_k=2A_k$ and $C_k=2D_k$. This makes the -solution numerically stable, and there is an exponential damping -effect: The data at knot $k\pm j$ affects the angle at knot~$k$ by -a factor of~$O(2^{-j})$. - -\fi - -\M277. However, we still must consider the angles at the starting and ending -knots of a non-cyclic path. These angles might be given explicitly, or -they might be specified implicitly in terms of an amount of ``curl.'' - -Let's assume that angles need to be determined for a non-cyclic path -starting at $z_0$ and ending at~$z_n$. Then equations of the form -$$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta_{k+1}=R_k$$ -have been given for $0<k<n$, and it will be convenient to introduce -equations of the same form for $k=0$ and $k=n$, where -$$A_0=B_0=C_n=D_n=0.$$ -If $\theta_0$ is supposed to have a given value $E_0$, we simply -define $C_0=0$, $D_0=0$, and $R_0=E_0$. Otherwise a curl -parameter, $\gamma_0$, has been specified at~$z_0$; this means -that the mock curvature at $z_0$ should be $\gamma_0$ times the -mock curvature at $z_1$; i.e., -$${2\beta_1(\theta_0+\phi_1)-6\theta_0\over\alpha_0^2d_{01}} -=\gamma_0{2\alpha_0(\theta_0+\phi_1)-6\phi_1\over\beta_1^2d_{01}}.$$ -This equation simplifies to -$$(\alpha_0\chi_0+3-\beta_1)\theta_0+ -\bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\theta_1= --\bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\psi_1,$$ -where $\chi_0=\alpha_0^2\gamma_0/\beta_1^2$; so we can set $C_0= -\chi_0\alpha_0+3-\beta_1$, $D_0=(3-\alpha_0)\chi_0+\beta_1$, $R_0=-D_0\psi_1$. -It can be shown that $C_0>0$ and $C_0B_1-A_1D_0>0$ when $\gamma_0\G0$, -hence the linear equations remain nonsingular. - -Similar considerations apply at the right end, when the final angle $\phi_n$ -may or may not need to be determined. It is convenient to let $\psi_n=0$, -hence $\theta_n=-\phi_n$. We either have an explicit equation $\theta_n=E_n$, -or we have -$$\bigl((3-\beta_n)\chi_n+\alpha_{n-1}\bigr)\theta_{n-1}+ -(\beta_n\chi_n+3-\alpha_{n-1})\theta_n=0,\qquad -\chi_n={\beta_n^2\gamma_n\over\alpha_{n-1}^2}.$$ - -When \\{make\_choices} chooses angles, it must compute the coefficients of -these linear equations, then solve the equations. To compute the coefficients, -it is necessary to compute arctangents of the given turning angles~$\psi_k$. -When the equations are solved, the chosen directions $\theta_k$ are put -back into the form of control points by essentially computing sines and -cosines. - -\fi - -\M278. OK, we are ready to make the hard choices of \\{make\_choices}. -Most of the work is relegated to an auxiliary procedure -called \\{solve\_choices}, which has been introduced to keep -\\{make\_choices} from being extremely long. - -\Y\P$\4\X278:Fill in the control information between consecutive breakpoints % -\|p and \|q\X\S$\6 -\X281:Calculate the turning angles $\psi_k$ and the distances $d_{k,k+1}$; set -$n$ to the length of the path\X;\6 -\X282:Remove \\{open} types at the breakpoints\X;\6 -$\\{solve\_choices}(\|p,\39\|q,\39\|n)$\par -\U273.\fi - -\M279. It's convenient to precompute quantities that will be needed several -times later. The values of $\\{delta\_x}[\|k]$ and $\\{delta\_y}[\|k]$ will be -the -coordinates of $z\k-z_k$, and the magnitude of this vector will be -$\\{delta}[\|k]=\hbox{$d_{k,k+1}$}$. The path angle $\psi_k$ between -$z_k-z_{k-1}$ -and $z\k-z_k$ will be stored in $\\{psi}[\|k]$. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{delta\_x},\39\\{delta\_y},\39\\{delta}$: \37\&{array} $[0\to\\{path% -\_size}]$ \1\&{of}\5 -\\{scaled};\C{knot differences}\2\6 -\4\\{psi}: \37\&{array} $[1\to\\{path\_size}]$ \1\&{of}\5 -\\{angle};\C{turning angles}\2\par -\fi - -\M280. \P$\X280:Other local variables for \\{make\_choices}\X\S$\6 -\4$\|k,\39\|n$: \37$0\to\\{path\_size}$;\C{current and final knot numbers}\6 -\4$\|s,\39\|t$: \37\\{pointer};\C{registers for list traversal}\6 -\4$\\{delx},\39\\{dely}$: \37\\{scaled};\C{directions where \\{open} meets % -\\{explicit}}\6 -\4$\\{sine},\39\\{cosine}$: \37\\{fraction};\C{trig functions of various -angles}\par -\U269.\fi - -\M281. \P$\X281:Calculate the turning angles $\psi_k$ and the distances -$d_{k,k+1}$; set $n$ to the length of the path\X\S$\6 -$\|k\K0$;\5 -$\|s\K\|p$;\5 -$\|n\K\\{path\_size}$;\6 -\1\&{repeat} \37$\|t\K\\{link}(\|s)$;\5 -$\\{delta\_x}[\|k]\K\\{x\_coord}(\|t)-\\{x\_coord}(\|s)$;\5 -$\\{delta\_y}[\|k]\K\\{y\_coord}(\|t)-\\{y\_coord}(\|s)$;\5 -$\\{delta}[\|k]\K\\{pyth\_add}(\\{delta\_x}[\|k],\39\\{delta\_y}[\|k])$;\6 -\&{if} $\|k>0$ \1\&{then}\6 -\&{begin} \37$\\{sine}\K\\{make\_fraction}(\\{delta\_y}[\|k-1],\39\\{delta}[% -\|k-1])$;\5 -$\\{cosine}\K\\{make\_fraction}(\\{delta\_x}[\|k-1],\39\\{delta}[\|k-1])$;\5 -$\\{psi}[\|k]\K\\{n\_arg}(\\{take\_fraction}(\\{delta\_x}[\|k],\39\\{cosine})+% -\\{take\_fraction}(\\{delta\_y}[\|k],\39\\{sine}),\39\\{take\_fraction}(% -\\{delta\_y}[\|k],\39\\{cosine})-\\{take\_fraction}(\\{delta\_x}[\|k],\39% -\\{sine}))$;\6 -\&{end};\2\6 -$\\{incr}(\|k)$;\5 -$\|s\K\|t$;\6 -\&{if} $\|k=\\{path\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"path\ size"},\39\\{path\_size})$;\2\6 -\&{if} $\|s=\|q$ \1\&{then}\5 -$\|n\K\|k$;\2\6 -\4\&{until}\5 -$(\|k\G\|n)\W(\\{left\_type}(\|s)\I\\{end\_cycle})$;\2\6 -\&{if} $\|k=\|n$ \1\&{then}\5 -$\\{psi}[\|n]\K0$\ \&{else} $\\{psi}[\|k]\K\\{psi}[1]$\2\par -\U278.\fi - -\M282. When we get to this point of the code, $\\{right\_type}(\|p)$ is either -\\{given} or \\{curl} or \\{open}. If it is \\{open}, we must have -$\\{left\_type}(\|p)=\\{end\_cycle}$ or $\\{left\_type}(\|p)=\\{explicit}$. In -the latter -case, the \\{open} type is converted to \\{given}; however, if the -velocity coming into this knot is zero, the \\{open} type is -converted to a \\{curl}, since we don't know the incoming direction. - -Similarly, $\\{left\_type}(\|q)$ is either \\{given} or \\{curl} or \\{open} or -\\{end\_cycle}. The \\{open} possibility is reduced either to \\{given} or to % -\\{curl}. - -\Y\P$\4\X282:Remove \\{open} types at the breakpoints\X\S$\6 -\&{if} $\\{left\_type}(\|q)=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{delx}\K\\{right\_x}(\|q)-\\{x\_coord}(\|q)$;\5 -$\\{dely}\K\\{right\_y}(\|q)-\\{y\_coord}(\|q)$;\6 -\&{if} $(\\{delx}=0)\W(\\{dely}=0)$ \1\&{then}\6 -\&{begin} \37$\\{left\_type}(\|q)\K\\{curl}$;\5 -$\\{left\_curl}(\|q)\K\\{unity}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{left\_type}(\|q)\K\\{given}$;\5 -$\\{left\_given}(\|q)\K\\{n\_arg}(\\{delx},\39\\{dely})$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{if} $(\\{right\_type}(\|p)=\\{open})\W(\\{left\_type}(\|p)=\\{explicit})$ \1% -\&{then}\6 -\&{begin} \37$\\{delx}\K\\{x\_coord}(\|p)-\\{left\_x}(\|p)$;\5 -$\\{dely}\K\\{y\_coord}(\|p)-\\{left\_y}(\|p)$;\6 -\&{if} $(\\{delx}=0)\W(\\{dely}=0)$ \1\&{then}\6 -\&{begin} \37$\\{right\_type}(\|p)\K\\{curl}$;\5 -$\\{right\_curl}(\|p)\K\\{unity}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{right\_type}(\|p)\K\\{given}$;\5 -$\\{right\_given}(\|p)\K\\{n\_arg}(\\{delx},\39\\{dely})$;\6 -\&{end};\2\6 -\&{end}\2\par -\U278.\fi - -\M283. Linear equations need to be solved whenever $\|n>1$; and also when $% -\|n=1$ -and exactly one of the breakpoints involves a curl. The simplest case occurs -when $\|n=1$ and there is a curl at both breakpoints; then we simply draw -a straight line. - -But before coding up the simple cases, we might as well face the general case, -since we must deal with it sooner or later, and since the general case -is likely to give some insight into the way simple cases can be handled best. - -When there is no cycle, the linear equations to be solved form a tri-diagonal -system, and we can apply the standard technique of Gaussian elimination -to convert that system to a sequence of equations of the form -$$\theta_0+u_0\theta_1=v_0,\quad -\theta_1+u_1\theta_2=v_1,\quad\ldots,\quad -\theta_{n-1}+u_{n-1}\theta_n=v_{n-1},\quad -\theta_n=v_n.$$ -It is possible to do this diagonalization while generating the equations. -Once $\theta_n$ is known, it is easy to determine $\theta_{n-1}$, \dots, -$\theta_1$, $\theta_0$; thus, the equations will be solved. - -The procedure is slightly more complex when there is a cycle, but the -basic idea will be nearly the same. In the cyclic case the right-hand -sides will be $v_k+w_k\theta_0$ instead of simply $v_k$, and we will start -the process off with $u_0=v_0=0$, $w_0=1$. The final equation will be not -$\theta_n=v_n$ but $\theta_n+u_n\theta_1=v_n+w_n\theta_0$; an appropriate -ending routine will take account of the fact that $\theta_n=\theta_0$ and -eliminate the $w$'s from the system, after which the solution can be -obtained as before. - -When $u_k$, $v_k$, and $w_k$ are being computed, the three pointer -variables \|r, \|s,~\|t will point respectively to knots $\|k-1$, \|k, -and~$\|k+1$. The $u$'s and $w$'s are scaled by $2^{28}$, i.e., they are -of type \\{fraction}; the $\theta$'s and $v$'s are of type \\{angle}. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{theta}: \37\&{array} $[0\to\\{path\_size}]$ \1\&{of}\5 -\\{angle};\C{values of $\theta_k$}\2\6 -\4\\{uu}: \37\&{array} $[0\to\\{path\_size}]$ \1\&{of}\5 -\\{fraction};\C{values of $u_k$}\2\6 -\4\\{vv}: \37\&{array} $[0\to\\{path\_size}]$ \1\&{of}\5 -\\{angle};\C{values of $v_k$}\2\6 -\4\\{ww}: \37\&{array} $[0\to\\{path\_size}]$ \1\&{of}\5 -\\{fraction};\C{values of $w_k$}\2\par -\fi - -\M284. Our immediate problem is to get the ball rolling by setting up the -first equation or by realizing that no equations are needed, and to fit -this initialization into a framework suitable for the overall computation. - -\Y\P$\4\X284:Declare the procedure called \\{solve\_choices}\X\S$\6 -\hbox{\4}\X296:Declare subroutines needed by \\{solve\_choices}\X\6 -\4\&{procedure}\1\ \37$\\{solve\_choices}(\|p,\39\|q:\\{pointer};\,\35\|n:% -\\{halfword})$;\6 -\4\&{label} \37$\\{found},\39\\{exit}$;\6 -\4\&{var} \37\|k: \37$0\to\\{path\_size}$;\C{current knot number}\6 -$\|r,\39\|s,\39\|t$: \37\\{pointer};\C{registers for list traversal}\6 -\X286:Other local variables for \\{solve\_choices}\X\2\6 -\&{begin} \37$\|k\K0$;\5 -$\|s\K\|p$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|t\K\\{link}(\|s)$;\6 -\&{if} $\|k=0$ \1\&{then}\5 -\X285:Get the linear equations started; or \&{return} with the control points -in place, if linear equations needn't be solved\X\6 -\4\&{else} \&{case} $\\{left\_type}(\|s)$ \1\&{of}\6 -\4$\\{end\_cycle},\39\\{open}$: \37\X287:Set up equation to match mock -curvatures at $z_k$; then \&{goto} \\{found} with $\theta_n$ adjusted to equal -$\theta_0$, if a cycle has ended\X;\6 -\4\\{curl}: \37\X295:Set up equation for a curl at $\theta_n$ and \&{goto} % -\\{found}\X;\6 -\4\\{given}: \37\X292:Calculate the given value of $\theta_n$ and \&{goto} % -\\{found}\X;\2\6 -\&{end};\C{there are no other cases}\2\6 -$\|r\K\|s$;\5 -$\|s\K\|t$;\5 -$\\{incr}(\|k)$;\6 -\&{end};\2\6 -\4\\{found}: \37\X297:Finish choosing angles and assigning control points\X;\6 -\4\\{exit}: \37\&{end};\par -\U269.\fi - -\M285. On the first time through the loop, we have $\|k=0$ and \|r is not yet -defined. The first linear equation, if any, will have $A_0=B_0=0$. - -\Y\P$\4\X285:Get the linear equations started; or \&{return} with the control -points in place, if linear equations needn't be solved\X\S$\6 -\&{case} $\\{right\_type}(\|s)$ \1\&{of}\6 -\4\\{given}: \37\&{if} $\\{left\_type}(\|t)=\\{given}$ \1\&{then}\5 -\X301:Reduce to simple case of two givens and \&{return}\X\6 -\4\&{else} \X293:Set up the equation for a given value of $\theta_0$\X;\2\6 -\4\\{curl}: \37\&{if} $\\{left\_type}(\|t)=\\{curl}$ \1\&{then}\5 -\X302:Reduce to simple case of straight line and \&{return}\X\6 -\4\&{else} \X294:Set up the equation for a curl at $\theta_0$\X;\2\6 -\4\\{open}: \37\&{begin} \37$\\{uu}[0]\K0$;\5 -$\\{vv}[0]\K0$;\5 -$\\{ww}[0]\K\\{fraction\_one}$;\6 -\&{end};\C{this begins a cycle}\2\6 -\&{end}\C{there are no other cases}\par -\U284.\fi - -\M286. The general equation that specifies equality of mock curvature at $z_k$ -is -$$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k,$$ -as derived above. We want to combine this with the already-derived equation -$\theta_{k-1}+u_{k-1}\theta_k=v_{k-1}+w_{k-1}\theta_0$ in order to obtain -a new equation -$\theta_k+u_k\theta\k=v_k+w_k\theta_0$. This can be done by dividing the -equation -$$(B_k-u_{k-1}A_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k-A_kv_{k-1} --A_kw_{k-1}\theta_0$$ -by $B_k-u_{k-1}A_k+C_k$. The trick is to do this carefully with -fixed-point arithmetic, avoiding the chance of overflow while retaining -suitable precision. - -The calculations will be performed in several registers that -provide temporary storage for intermediate quantities. - -\Y\P$\4\X286:Other local variables for \\{solve\_choices}\X\S$\6 -\4$\\{aa},\39\\{bb},\39\\{cc},\39\\{ff},\39\\{acc}$: \37\\{fraction};% -\C{temporary registers}\6 -\4$\\{dd},\39\\{ee}$: \37\\{scaled};\C{likewise, but \\{scaled}}\6 -\4$\\{lt},\39\\{rt}$: \37\\{scaled};\C{tension values}\par -\U284.\fi - -\M287. \P$\X287:Set up equation to match mock curvatures at $z_k$; then % -\&{goto} \\{found} with $\theta_n$ adjusted to equal $\theta_0$, if a cycle has -ended\X\S$\6 -\&{begin} \37\X288:Calculate the values $\\{aa}=A_k/B_k$, $\\{bb}=D_k/C_k$, $% -\\{dd}=(3-\alpha_{k-1})d_{k,k+1}$, $\\{ee}=(3-\beta\k)d_{k-1,k}$, and $% -\\{cc}=(B_k-u_{k-1}A_k)/B_k$\X;\6 -\X289:Calculate the ratio $\\{ff}=C_k/(C_k+B_k-u_{k-1}A_k)$\X;\6 -$\\{uu}[\|k]\K\\{take\_fraction}(\\{ff},\39\\{bb})$;\5 -\X290:Calculate the values of $v_k$ and $w_k$\X;\6 -\&{if} $\\{left\_type}(\|s)=\\{end\_cycle}$ \1\&{then}\5 -\X291:Adjust $\theta_n$ to equal $\theta_0$ and \&{goto} \\{found}\X;\2\6 -\&{end}\par -\U284.\fi - -\M288. Since tension values are never less than 3/4, the values \\{aa} and -\\{bb} computed here are never more than 4/5. - -\Y\P$\4\X288:Calculate the values $\\{aa}=A_k/B_k$, $\\{bb}=D_k/C_k$, $% -\\{dd}=(3-\alpha_{k-1})d_{k,k+1}$, $\\{ee}=(3-\beta\k)d_{k-1,k}$, and $% -\\{cc}=(B_k-u_{k-1}A_k)/B_k$\X\S$\6 -\&{if} $\\{abs}(\\{right\_tension}(\|r))=\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{aa}\K\\{fraction\_half}$;\5 -$\\{dd}\K2\ast\\{delta}[\|k]$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{aa}\K\\{make\_fraction}(\\{unity},\393\ast\\{abs}(% -\\{right\_tension}(\|r))-\\{unity})$;\5 -$\\{dd}\K\\{take\_fraction}(\\{delta}[\|k],\39\\{fraction\_three}-\\{make% -\_fraction}(\\{unity},\39\\{abs}(\\{right\_tension}(\|r))))$;\6 -\&{end};\2\6 -\&{if} $\\{abs}(\\{left\_tension}(\|t))=\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{bb}\K\\{fraction\_half}$;\5 -$\\{ee}\K2\ast\\{delta}[\|k-1]$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{bb}\K\\{make\_fraction}(\\{unity},\393\ast\\{abs}(% -\\{left\_tension}(\|t))-\\{unity})$;\5 -$\\{ee}\K\\{take\_fraction}(\\{delta}[\|k-1],\39\\{fraction\_three}-\\{make% -\_fraction}(\\{unity},\39\\{abs}(\\{left\_tension}(\|t))))$;\6 -\&{end};\2\6 -$\\{cc}\K\\{fraction\_one}-\\{take\_fraction}(\\{uu}[\|k-1],\39\\{aa})$\par -\U287.\fi - -\M289. The ratio to be calculated in this step can be written in the form -$$\beta_k^2\cdot\\{ee}\over\beta_k^2\cdot\\{ee}+\alpha_k^2\cdot -\\{cc}\cdot\\{dd},$$ -because of the quantities just calculated. The values of \\{dd} and \\{ee} -will not be needed after this step has been performed. - -\Y\P$\4\X289:Calculate the ratio $\\{ff}=C_k/(C_k+B_k-u_{k-1}A_k)$\X\S$\6 -$\\{dd}\K\\{take\_fraction}(\\{dd},\39\\{cc})$;\5 -$\\{lt}\K\\{abs}(\\{left\_tension}(\|s))$;\5 -$\\{rt}\K\\{abs}(\\{right\_tension}(\|s))$;\6 -\&{if} $\\{lt}\I\\{rt}$ \1\&{then}\C{$\beta_k^{-1}\ne\alpha_k^{-1}$}\6 -\&{if} $\\{lt}<\\{rt}$ \1\&{then}\6 -\&{begin} \37$\\{ff}\K\\{make\_fraction}(\\{lt},\39\\{rt})$;\5 -$\\{ff}\K\\{take\_fraction}(\\{ff},\39\\{ff})$;\C{$\alpha_k^2/\beta_k^2$}\6 -$\\{dd}\K\\{take\_fraction}(\\{dd},\39\\{ff})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{ff}\K\\{make\_fraction}(\\{rt},\39\\{lt})$;\5 -$\\{ff}\K\\{take\_fraction}(\\{ff},\39\\{ff})$;\C{$\beta_k^2/\alpha_k^2$}\6 -$\\{ee}\K\\{take\_fraction}(\\{ee},\39\\{ff})$;\6 -\&{end};\2\2\6 -$\\{ff}\K\\{make\_fraction}(\\{ee},\39\\{ee}+\\{dd})$\par -\U287.\fi - -\M290. The value of $u_{k-1}$ will be $\L1$ except when $k=1$ and the previous -equation was specified by a curl. In that case we must use a special -method of computation to prevent overflow. - -Fortunately, the calculations turn out to be even simpler in this ``hard'' -case. The curl equation makes $w_0=0$ and $v_0=-u_0\psi_1$, hence -$-B_1\psi_1-A_1v_0=-(B_1-u_0A_1)\psi_1=-\\{cc}\cdot B_1\psi_1$. - -\Y\P$\4\X290:Calculate the values of $v_k$ and $w_k$\X\S$\6 -$\\{acc}\K-\\{take\_fraction}(\\{psi}[\|k+1],\39\\{uu}[\|k])$;\6 -\&{if} $\\{right\_type}(\|r)=\\{curl}$ \1\&{then}\6 -\&{begin} \37$\\{ww}[\|k]\K0$;\5 -$\\{vv}[\|k]\K\\{acc}-\\{take\_fraction}(\\{psi}[1],\39\\{fraction\_one}-% -\\{ff})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{ff}\K\\{make\_fraction}(\\{fraction\_one}-\\{ff},% -\39\\{cc})$;\C{this is $B_k/(C_k+B_k-u_{k-1}A_k)<5$}\6 -$\\{acc}\K\\{acc}-\\{take\_fraction}(\\{psi}[\|k],\39\\{ff})$;\5 -$\\{ff}\K\\{take\_fraction}(\\{ff},\39\\{aa})$;\C{this is -$A_k/(C_k+B_k-u_{k-1}A_k)$}\6 -$\\{vv}[\|k]\K\\{acc}-\\{take\_fraction}(\\{vv}[\|k-1],\39\\{ff})$;\6 -\&{if} $\\{ww}[\|k-1]=0$ \1\&{then}\5 -$\\{ww}[\|k]\K0$\6 -\4\&{else} $\\{ww}[\|k]\K-\\{take\_fraction}(\\{ww}[\|k-1],\39\\{ff})$;\2\6 -\&{end}\2\par -\U287.\fi - -\M291. When a complete cycle has been traversed, we have $\theta_k+u_k\theta\k= -v_k+w_k\theta_0$, for $1\L\|k\L\|n$. We would like to determine the value of -$\theta_n$ and reduce the system to the form $\theta_k+u_k\theta\k=v_k$ -for $0\L\|k<\|n$, so that the cyclic case can be finished up just as if there -were no cycle. - -The idea in the following code is to observe that -$$\eqalign{\theta_n&=v_n+w_n\theta_0-u_n\theta_1=\cdots\cr -&=v_n+w_n\theta_0-u_n\bigl(v_1+w_1\theta_0-u_1(v_2+\cdots --u_{n-2}(v_{n-1}+w_{n-1}\theta_0-u_{n-1}\theta_0)\ldots{})\bigr),\cr}$$ -so we can solve for $\theta_n=\theta_0$. - -\Y\P$\4\X291:Adjust $\theta_n$ to equal $\theta_0$ and \&{goto} \\{found}\X\S$\6 -\&{begin} \37$\\{aa}\K0$;\5 -$\\{bb}\K\\{fraction\_one}$;\C{we have $\|k=\|n$}\6 -\1\&{repeat} \37$\\{decr}(\|k)$;\6 -\&{if} $\|k=0$ \1\&{then}\5 -$\|k\K\|n$;\2\6 -$\\{aa}\K\\{vv}[\|k]-\\{take\_fraction}(\\{aa},\39\\{uu}[\|k])$;\5 -$\\{bb}\K\\{ww}[\|k]-\\{take\_fraction}(\\{bb},\39\\{uu}[\|k])$;\6 -\4\&{until}\5 -$\|k=\|n$;\C{now $\theta_n=\\{aa}+\\{bb}\cdot\theta_n$}\2\6 -$\\{aa}\K\\{make\_fraction}(\\{aa},\39\\{fraction\_one}-\\{bb})$;\5 -$\\{theta}[\|n]\K\\{aa}$;\5 -$\\{vv}[0]\K\\{aa}$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}\|n-1$ \1\&{do}\5 -$\\{vv}[\|k]\K\\{vv}[\|k]+\\{take\_fraction}(\\{aa},\39\\{ww}[\|k])$;\2\6 -\&{goto} \37\\{found};\6 -\&{end}\par -\U287.\fi - -\M292. \P\D \37$\\{reduce\_angle}(\#)\S$\1\6 -\&{if} $\\{abs}(\#)>\\{one\_eighty\_deg}$ \1\&{then}\6 -\&{if} $\#>0$ \1\&{then}\5 -$\#\K\#-\\{three\_sixty\_deg}$\ \&{else} $\#\K\#+\\{three\_sixty\_deg}$\2\2\2% -\par -\Y\P$\4\X292:Calculate the given value of $\theta_n$ and \&{goto} \\{found}\X% -\S$\6 -\&{begin} \37$\\{theta}[\|n]\K\\{left\_given}(\|s)-\\{n\_arg}(\\{delta\_x}[% -\|n-1],\39\\{delta\_y}[\|n-1])$;\5 -$\\{reduce\_angle}(\\{theta}[\|n])$;\5 -\&{goto} \37\\{found};\6 -\&{end}\par -\U284.\fi - -\M293. \P$\X293:Set up the equation for a given value of $\theta_0$\X\S$\6 -\&{begin} \37$\\{vv}[0]\K\\{right\_given}(\|s)-\\{n\_arg}(\\{delta\_x}[0],\39% -\\{delta\_y}[0])$;\5 -$\\{reduce\_angle}(\\{vv}[0])$;\5 -$\\{uu}[0]\K0$;\5 -$\\{ww}[0]\K0$;\6 -\&{end}\par -\U285.\fi - -\M294. \P$\X294:Set up the equation for a curl at $\theta_0$\X\S$\6 -\&{begin} \37$\\{cc}\K\\{right\_curl}(\|s)$;\5 -$\\{lt}\K\\{abs}(\\{left\_tension}(\|t))$;\5 -$\\{rt}\K\\{abs}(\\{right\_tension}(\|s))$;\6 -\&{if} $(\\{rt}=\\{unity})\W(\\{lt}=\\{unity})$ \1\&{then}\5 -$\\{uu}[0]\K\\{make\_fraction}(\\{cc}+\\{cc}+\\{unity},\39\\{cc}+\\{two})$\6 -\4\&{else} $\\{uu}[0]\K\\{curl\_ratio}(\\{cc},\39\\{rt},\39\\{lt})$;\2\6 -$\\{vv}[0]\K-\\{take\_fraction}(\\{psi}[1],\39\\{uu}[0])$;\5 -$\\{ww}[0]\K0$;\6 -\&{end}\par -\U285.\fi - -\M295. \P$\X295:Set up equation for a curl at $\theta_n$ and \&{goto} \\{found}% -\X\S$\6 -\&{begin} \37$\\{cc}\K\\{left\_curl}(\|s)$;\5 -$\\{lt}\K\\{abs}(\\{left\_tension}(\|s))$;\5 -$\\{rt}\K\\{abs}(\\{right\_tension}(\|r))$;\6 -\&{if} $(\\{rt}=\\{unity})\W(\\{lt}=\\{unity})$ \1\&{then}\5 -$\\{ff}\K\\{make\_fraction}(\\{cc}+\\{cc}+\\{unity},\39\\{cc}+\\{two})$\6 -\4\&{else} $\\{ff}\K\\{curl\_ratio}(\\{cc},\39\\{lt},\39\\{rt})$;\2\6 -$\\{theta}[\|n]\K-\\{make\_fraction}(\\{take\_fraction}(\\{vv}[\|n-1],\39% -\\{ff}),\39\\{fraction\_one}-\\{take\_fraction}(\\{ff},\39\\{uu}[\|n-1]))$;\5 -\&{goto} \37\\{found};\6 -\&{end}\par -\U284.\fi - -\M296. The \\{curl\_ratio} subroutine has three arguments, which our previous -notation -encourages us to call $\gamma$, $\alpha^{-1}$, and $\beta^{-1}$. It is -a somewhat tedious program to calculate -$${(3-\alpha)\alpha^2\gamma+\beta^3\over -\alpha^3\gamma+(3-\beta)\beta^2},$$ -with the result reduced to 4 if it exceeds 4. (This reduction of curl -is necessary only if the curl and tension are both large.) -The values of $\alpha$ and $\beta$ will be at most~4/3. - -\Y\P$\4\X296:Declare subroutines needed by \\{solve\_choices}\X\S$\6 -\4\&{function}\1\ \37$\\{curl\_ratio}(\\{gamma},\39\\{a\_tension},\39\\{b% -\_tension}:\\{scaled})$: \37\\{fraction};\6 -\4\&{var} \37$\\{alpha},\39\\{beta},\39\\{num},\39\\{denom},\39\\{ff}$: \37% -\\{fraction};\C{registers}\2\6 -\&{begin} \37$\\{alpha}\K\\{make\_fraction}(\\{unity},\39\\{a\_tension})$;\5 -$\\{beta}\K\\{make\_fraction}(\\{unity},\39\\{b\_tension})$;\6 -\&{if} $\\{alpha}\L\\{beta}$ \1\&{then}\6 -\&{begin} \37$\\{ff}\K\\{make\_fraction}(\\{alpha},\39\\{beta})$;\5 -$\\{ff}\K\\{take\_fraction}(\\{ff},\39\\{ff})$;\5 -$\\{gamma}\K\\{take\_fraction}(\\{gamma},\39\\{ff})$;\6 -$\\{beta}\K\\{beta}\mathbin{\&{div}}\O{10000}$;\C{convert \\{fraction} to % -\\{scaled}}\6 -$\\{denom}\K\\{take\_fraction}(\\{gamma},\39\\{alpha})+\\{three}-\\{beta}$;\5 -$\\{num}\K\\{take\_fraction}(\\{gamma},\39\\{fraction\_three}-\\{alpha})+% -\\{beta}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{ff}\K\\{make\_fraction}(\\{beta},\39\\{alpha})$;\5 -$\\{ff}\K\\{take\_fraction}(\\{ff},\39\\{ff})$;\5 -$\\{beta}\K\\{take\_fraction}(\\{beta},\39\\{ff})\mathbin{\&{div}}\O{10000}$;% -\C{convert \\{fraction} to \\{scaled}}\6 -$\\{denom}\K\\{take\_fraction}(\\{gamma},\39\\{alpha})+(\\{ff}\mathbin{% -\&{div}}1365)-\\{beta}$;\C{$1365\approx 2^{12}/3$}\6 -$\\{num}\K\\{take\_fraction}(\\{gamma},\39\\{fraction\_three}-\\{alpha})+% -\\{beta}$;\6 -\&{end};\2\6 -\&{if} $\\{num}\G\\{denom}+\\{denom}+\\{denom}+\\{denom}$ \1\&{then}\5 -$\\{curl\_ratio}\K\\{fraction\_four}$\6 -\4\&{else} $\\{curl\_ratio}\K\\{make\_fraction}(\\{num},\39\\{denom})$;\2\6 -\&{end};\par -\A299. -\U284.\fi - -\M297. We're in the home stretch now. - -\Y\P$\4\X297:Finish choosing angles and assigning control points\X\S$\6 -\&{for} $\|k\K\|n-1\mathrel{\&{downto}}0$ \1\&{do}\5 -$\\{theta}[\|k]\K\\{vv}[\|k]-\\{take\_fraction}(\\{theta}[\|k+1],\39\\{uu}[% -\|k])$;\2\6 -$\|s\K\|p$;\5 -$\|k\K0$;\6 -\1\&{repeat} \37$\|t\K\\{link}(\|s)$;\6 -$\\{n\_sin\_cos}(\\{theta}[\|k])$;\5 -$\\{st}\K\\{n\_sin}$;\5 -$\\{ct}\K\\{n\_cos}$;\6 -$\\{n\_sin\_cos}(-\\{psi}[\|k+1]-\\{theta}[\|k+1])$;\5 -$\\{sf}\K\\{n\_sin}$;\5 -$\\{cf}\K\\{n\_cos}$;\6 -$\\{set\_controls}(\|s,\39\|t,\39\|k)$;\6 -$\\{incr}(\|k)$;\5 -$\|s\K\|t$;\6 -\4\&{until}\5 -$\|k=\|n$\2\par -\U284.\fi - -\M298. The \\{set\_controls} routine actually puts the control points into -a pair of consecutive nodes \|p and~\|q. Global variables are used to -record the values of $\sin\theta$, $\cos\theta$, $\sin\phi$, and -$\cos\phi$ needed in this calculation. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{st},\39\\{ct},\39\\{sf},\39\\{cf}$: \37\\{fraction};\C{sines and cosines}% -\par -\fi - -\M299. \P$\X296:Declare subroutines needed by \\{solve\_choices}\X\mathrel{+}% -\S$\6 -\4\&{procedure}\1\ \37$\\{set\_controls}(\|p,\39\|q:\\{pointer};\,\35\|k:% -\\{integer})$;\6 -\4\&{var} \37$\\{rr},\39\\{ss}$: \37\\{fraction};\C{velocities, divided by -thrice the tension}\6 -$\\{lt},\39\\{rt}$: \37\\{scaled};\C{tensions}\6 -\\{sine}: \37\\{fraction};\C{$\sin(\theta+\phi)$}\2\6 -\&{begin} \37$\\{lt}\K\\{abs}(\\{left\_tension}(\|q))$;\5 -$\\{rt}\K\\{abs}(\\{right\_tension}(\|p))$;\5 -$\\{rr}\K\\{velocity}(\\{st},\39\\{ct},\39\\{sf},\39\\{cf},\39\\{rt})$;\5 -$\\{ss}\K\\{velocity}(\\{sf},\39\\{cf},\39\\{st},\39\\{ct},\39\\{lt})$;\6 -\&{if} $(\\{right\_tension}(\|p)<0)\V(\\{left\_tension}(\|q)<0)$ \1\&{then}\5 -\X300:Decrease the velocities, if necessary, to stay inside the bounding -triangle\X;\2\6 -$\\{right\_x}(\|p)\K\\{x\_coord}(\|p)+\\{take\_fraction}(\\{take\_fraction}(% -\\{delta\_x}[\|k],\39\\{ct})-\\{take\_fraction}(\\{delta\_y}[\|k],\39\\{st}),% -\39\\{rr})$;\5 -$\\{right\_y}(\|p)\K\\{y\_coord}(\|p)+\\{take\_fraction}(\\{take\_fraction}(% -\\{delta\_y}[\|k],\39\\{ct})+\\{take\_fraction}(\\{delta\_x}[\|k],\39\\{st}),% -\39\\{rr})$;\5 -$\\{left\_x}(\|q)\K\\{x\_coord}(\|q)-\\{take\_fraction}(\\{take\_fraction}(% -\\{delta\_x}[\|k],\39\\{cf})+\\{take\_fraction}(\\{delta\_y}[\|k],\39\\{sf}),% -\39\\{ss})$;\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|q)-\\{take\_fraction}(\\{take\_fraction}(% -\\{delta\_y}[\|k],\39\\{cf})-\\{take\_fraction}(\\{delta\_x}[\|k],\39\\{sf}),% -\39\\{ss})$;\5 -$\\{right\_type}(\|p)\K\\{explicit}$;\5 -$\\{left\_type}(\|q)\K\\{explicit}$;\6 -\&{end};\par -\fi - -\M300. The boundedness conditions $\\{rr}\L\sin\phi\,/\sin(\theta+\phi)$ and -$\\{ss}\L\sin\theta\,/\sin(\theta+\phi)$ are to be enforced if $\sin\theta$, -$\sin\phi$, and $\sin(\theta+\phi)$ all have the same sign. Otherwise -there is no ``bounding triangle.'' - -\Y\P$\4\X300:Decrease the velocities, if necessary, to stay inside the bounding -triangle\X\S$\6 -\&{if} $((\\{st}\G0)\W(\\{sf}\G0))\V((\\{st}\L0)\W(\\{sf}\L0))$ \1\&{then}\6 -\&{begin} \37$\\{sine}\K\\{take\_fraction}(\\{abs}(\\{st}),\39\\{cf})+\\{take% -\_fraction}(\\{abs}(\\{sf}),\39\\{ct})$;\6 -\&{if} $\\{sine}>0$ \1\&{then}\6 -\&{begin} \37$\\{sine}\K\\{take\_fraction}(\\{sine},\39\\{fraction\_one}+% -\\{unity})$;\C{safety factor}\6 -\&{if} $\\{right\_tension}(\|p)<0$ \1\&{then}\6 -\&{if} $\\{ab\_vs\_cd}(\\{abs}(\\{sf}),\39\\{fraction\_one},\39\\{rr},\39% -\\{sine})<0$ \1\&{then}\5 -$\\{rr}\K\\{make\_fraction}(\\{abs}(\\{sf}),\39\\{sine})$;\2\2\6 -\&{if} $\\{left\_tension}(\|q)<0$ \1\&{then}\6 -\&{if} $\\{ab\_vs\_cd}(\\{abs}(\\{st}),\39\\{fraction\_one},\39\\{ss},\39% -\\{sine})<0$ \1\&{then}\5 -$\\{ss}\K\\{make\_fraction}(\\{abs}(\\{st}),\39\\{sine})$;\2\2\6 -\&{end};\2\6 -\&{end}\2\par -\U299.\fi - -\M301. Only the simple cases remain to be handled. - -\Y\P$\4\X301:Reduce to simple case of two givens and \&{return}\X\S$\6 -\&{begin} \37$\\{aa}\K\\{n\_arg}(\\{delta\_x}[0],\39\\{delta\_y}[0])$;\6 -$\\{n\_sin\_cos}(\\{right\_given}(\|p)-\\{aa})$;\5 -$\\{ct}\K\\{n\_cos}$;\5 -$\\{st}\K\\{n\_sin}$;\6 -$\\{n\_sin\_cos}(\\{left\_given}(\|q)-\\{aa})$;\5 -$\\{cf}\K\\{n\_cos}$;\5 -$\\{sf}\K-\\{n\_sin}$;\6 -$\\{set\_controls}(\|p,\39\|q,\390)$;\5 -\&{return};\6 -\&{end}\par -\U285.\fi - -\M302. \P$\X302:Reduce to simple case of straight line and \&{return}\X\S$\6 -\&{begin} \37$\\{right\_type}(\|p)\K\\{explicit}$;\5 -$\\{left\_type}(\|q)\K\\{explicit}$;\5 -$\\{lt}\K\\{abs}(\\{left\_tension}(\|q))$;\5 -$\\{rt}\K\\{abs}(\\{right\_tension}(\|p))$;\6 -\&{if} $\\{rt}=\\{unity}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{delta\_x}[0]\G0$ \1\&{then}\5 -$\\{right\_x}(\|p)\K\\{x\_coord}(\|p)+((\\{delta\_x}[0]+1)\mathbin{\&{div}}3)$\6 -\4\&{else} $\\{right\_x}(\|p)\K\\{x\_coord}(\|p)+((\\{delta\_x}[0]-1)\mathbin{% -\&{div}}3)$;\2\6 -\&{if} $\\{delta\_y}[0]\G0$ \1\&{then}\5 -$\\{right\_y}(\|p)\K\\{y\_coord}(\|p)+((\\{delta\_y}[0]+1)\mathbin{\&{div}}3)$\6 -\4\&{else} $\\{right\_y}(\|p)\K\\{y\_coord}(\|p)+((\\{delta\_y}[0]-1)\mathbin{% -\&{div}}3)$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{ff}\K\\{make\_fraction}(\\{unity},\393\ast\\{rt})$;% -\C{$\alpha/3$}\6 -$\\{right\_x}(\|p)\K\\{x\_coord}(\|p)+\\{take\_fraction}(\\{delta\_x}[0],\39% -\\{ff})$;\5 -$\\{right\_y}(\|p)\K\\{y\_coord}(\|p)+\\{take\_fraction}(\\{delta\_y}[0],\39% -\\{ff})$;\6 -\&{end};\2\6 -\&{if} $\\{lt}=\\{unity}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{delta\_x}[0]\G0$ \1\&{then}\5 -$\\{left\_x}(\|q)\K\\{x\_coord}(\|q)-((\\{delta\_x}[0]+1)\mathbin{\&{div}}3)$\6 -\4\&{else} $\\{left\_x}(\|q)\K\\{x\_coord}(\|q)-((\\{delta\_x}[0]-1)\mathbin{% -\&{div}}3)$;\2\6 -\&{if} $\\{delta\_y}[0]\G0$ \1\&{then}\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|q)-((\\{delta\_y}[0]+1)\mathbin{\&{div}}3)$\6 -\4\&{else} $\\{left\_y}(\|q)\K\\{y\_coord}(\|q)-((\\{delta\_y}[0]-1)\mathbin{% -\&{div}}3)$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{ff}\K\\{make\_fraction}(\\{unity},\393\ast\\{lt})$;% -\C{$\beta/3$}\6 -$\\{left\_x}(\|q)\K\\{x\_coord}(\|q)-\\{take\_fraction}(\\{delta\_x}[0],\39% -\\{ff})$;\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|q)-\\{take\_fraction}(\\{delta\_y}[0],\39% -\\{ff})$;\6 -\&{end};\2\6 -\&{return};\6 -\&{end}\par -\U285.\fi - -\N303. \[19] Generating discrete moves. -The purpose of the next part of \MF\ is to compute discrete approximations -to curves described as parametric polynomial functions $z(t)$. -We shall start with the low level first, because an efficient ``engine'' -is needed to support the high-level constructions. - -Most of the subroutines are based on variations of a single theme, -namely the idea of {\sl bisection}. Given a Bernshte{\u\i}n polynomial -$$B(z_0,z_1,\ldots,z_n;t)=\sum_k{n\choose k}t^k(1-t)^{n-k}z_k,$$ -we can conveniently bisect its range as follows: - -\smallskip -\textindent{1)} Let $z_k^{(0)}=z_k$, for $0\L\|k\L\|n$. - -\smallskip -\textindent{2)} Let $z_k^{(j+1)}={1\over2}(z_k^{(j)}+z\k^{(j)})$, for -$0\L\|k<\|n-\|j$, for $0\L\|j<\|n$. - -\smallskip\noindent -Then -$$B(z_0,z_1,\ldots,z_n;t)=B(z_0^{(0)},z_0^{(1)},\ldots,z_0^{(n)};2t) -=B(z_0^{(n)},z_1^{(n-1)},\ldots,z_n^{(0)};2t-1).$$ -This formula gives us the coefficients of polynomials to use over the ranges -$0\L t\L{1\over2}$ and ${1\over2}\L t\L1$. - -In our applications it will usually be possible to work indirectly with -numbers that allow us to deduce relevant properties of the polynomials -without actually computing the polynomial values. We will deal with -coefficients $Z_k=2^l(z_k-z_{k-1})$ for $1\L\|k\L\|n$, instead of -the actual numbers $z_0$, $z_1$, \dots,~$z_n$, and the value of~\|l will -increase by~1 at each bisection step. This technique reduces the -amount of calculation needed for bisection and also increases the -accuracy of evaluation (since one bit of precision is gained at each -bisection). Indeed, the bisection process now becomes one level shorter: - -\smallskip -\textindent{$1'$)} Let $Z_k^{(1)}=Z_k$, for $1\L\|k\L\|n$. - -\smallskip -\textindent{$2'$)} Let $Z_k^{(j+1)}={1\over2}(Z_k^{(j)}+Z\k^{(j)})$, for -$1\L\|k\L\|n-\|j$, for $1\L\|j<\|n$. - -\smallskip\noindent -The relevant coefficients $(Z'_1,\ldots,Z'_n)$ and $(Z''_1,\ldots,Z''_n)$ -for the two subintervals after bisection are respectively -$(Z_1^{(1)},Z_1^{(2)},\ldots,Z_1^{(n)})$ and -$(Z_1^{(n)},Z_2^{(n-1)},\ldots,Z_n^{(1)})$. -And the values of $z_0$ appropriate for the bisected interval are $z'_0=z_0$ -and $z''_0=z_0+(Z_1+Z_2+\cdots+Z_n)/2^{l+1}$. - -Step $2'$ involves division by~2, which introduces computational errors -of at most $1\over2$ at each step; thus after $l$~levels of bisection the -integers $Z_k$ will differ from their true values by at most $(n-1)l/2$. -This error rate is quite acceptable, considering that we have $l$~more -bits of precision in the $Z$'s by comparison with the~$z$'s. Note also -that the $Z$'s remain bounded; there's no danger of integer overflow, even -though we have the identity $Z_k=2^l(z_k-z_{k-1})$ for arbitrarily large~$l$. - -In fact, we can show not only that the $Z$'s remain bounded, but also that -they become nearly equal, since they are control points for a polynomial -of one less degree. If $\vert Z\k-Z_k\vert\L M$ initially, it is possible -to prove that $\vert Z\k-Z_k\vert\L\lceil M/2^l\rceil$ after $l$~levels -of bisection, even in the presence of rounding errors. Here's the -proof [cf.~Lane and Riesenfeld, {\sl IEEE Trans.\ on Pattern Analysis -and Machine Intelligence\/ \bf PAMI-2} (1980), 35--46]: Assuming that -$\vert Z\k-Z_k\vert\L M$ before bisection, we want to prove that -$\vert Z\k-Z_k\vert\L\lceil M/2\rceil$ afterward. First we show that -$\vert Z\k^{(j)}-Z_k^{(j)}\vert\L M$ for all $j$ and~$k$, by induction -on~$j$; this follows from the fact that -$$\bigl\vert\\{half}(a+b)-\\{half}(b+c)\bigr\vert\L -\max\bigl(\vert a-b\vert,\vert b-c\vert\bigr)$$ -holds for both of the rounding rules $\\{half}(x)=\lfloor x/2\rfloor$ -and $\\{half}(x)={\rm sign}(x)\lfloor\vert x/2\vert\rfloor$. -(If $\vert a-b\vert$ and $\vert b-c\vert$ are equal, then -$a+b$ and $b+c$ are both even or both odd. The rounding errors either -cancel or round the numbers toward each other; hence -$$\eqalign{\bigl\vert\\{half}(a+b)-\\{half}(b+c)\bigr\vert -&\L\textstyle\bigl\vert{1\over2}(a+b)-{1\over2}(b+c)\bigr\vert\cr -&=\textstyle\bigl\vert{1\over2}(a-b)+{1\over2}(b-c)\bigr\vert -\L\max\bigl(\vert a-b\vert,\vert b-c\vert\bigr),\cr}$$ -as required. A simpler argument applies if $\vert a-b\vert$ and -$\vert b-c\vert$ are unequal.) Now it is easy to see that -$\vert Z_1^{(j+1)}-Z_1^{(j)}\vert\L\bigl\lfloor{1\over2} -\vert Z_2^{(j)}-Z_1^{(j)}\vert+{1\over2}\bigr\rfloor -\L\bigl\lfloor{1\over2}(M+1)\bigr\rfloor=\lceil M/2\rceil$. - -Another interesting fact about bisection is the identity -$$Z_1'+\cdots+Z_n'+Z_1''+\cdots+Z_n''=2(Z_1+\cdots+Z_n+E),$$ -where $E$ is the sum of the rounding errors in all of the halving -operations ($\vert E\vert\L n(n-1)/4$). - -\fi - -\M304. We will later reduce the problem of digitizing a complex cubic -$z(t)=B(z_0,z_1,z_2,z_3;t)$ to the following simpler problem: -Given two real cubics -$x(t)=B(x_0,x_1,x_2,x_3;t)$ -and $y(t)=B(y_0,y_1,y_2,y_3;t)$ that are monotone nondecreasing, -determine the set of integer points -$$P=\bigl\{\bigl(\lfloor x(t)\rfloor,\lfloor y(t)\rfloor\bigr) -\bigm\vert 0\L t\L 1\bigr\}.$$ -Well, the problem isn't actually quite so clean as this; when the path -goes very near an integer point $(a,b)$, computational errors may -make us think that $P$ contains $(a-1,b)$ while in reality it should -contain $(a,b-1)$. Furthermore, if the path goes {\sl exactly\/} -through the integer points $(a-1,b-1)$ and -$(a,b)$, we will want $P$ to contain one -of the two points $(a-1,b)$ or $(a,b-1)$, so that $P$ can be described -entirely by ``rook moves'' upwards or to the right; no diagonal -moves from $(a-1,b-1)$ to~$(a,b)$ will be allowed. - -Thus, the set $P$ we wish to compute will merely be an approximation -to the set described in the formula above. It will consist of -$\lfloor x(1)\rfloor-\lfloor x(0)\rfloor$ rightward moves and -$\lfloor y(1)\rfloor-\lfloor y(0)\rfloor$ upward moves, intermixed -in some order. Our job will be to figure out a suitable order. - -The following recursive strategy suggests itself, when we recall that -$x(0)=x_0$, $x(1)=x_3$, $y(0)=y_0$, and $y(1)=y_3$: - -\smallskip -If $\lfloor x_0\rfloor=\lfloor x_3\rfloor$ then take -$\lfloor y_3\rfloor-\lfloor y_0\rfloor$ steps up. - -Otherwise if $\lfloor y_0\rfloor=\lfloor y_3\rfloor$ then take -$\lfloor x_3\rfloor-\lfloor x_0\rfloor$ steps to the right. - -Otherwise bisect the current cubics and repeat the process on both halves. - -\yskip\noindent -This intuitively appealing formulation does not quite solve the problem, -because it may never terminate. For example, it's not hard to see that -no steps will {\sl ever\/} be taken if $(x_0,x_1,x_2,x_3)=(y_0,y_1,y_2,y_3)$! -However, we can surmount this difficulty with a bit of care; so let's -proceed to flesh out the algorithm as stated, before worrying about -such details. - -The bisect-and-double strategy discussed above suggests that we represent -$(x_0,x_1,x_2,x_3)$ by $(X_1,X_2,X_3)$, where $X_k=2^l(x_k-x_{k-1})$ -for some~$l$. Initially $l=16$, since the $x$'s are \\{scaled}. -In order to deal with other aspects of the algorithm we will want to -maintain also the quantities $m=\lfloor x_3\rfloor-\lfloor x_0\rfloor$ -and $R=2^l(x_0\bmod 1)$. Similarly, -$(y_0,y_1,y_2,y_3)$ will be represented by $(Y_1,Y_2,Y_3)$, -$n=\lfloor y_3\rfloor-\lfloor y_0\rfloor$, -and $S=2^l(y_0\bmod 1)$. The algorithm now takes the following form: - -\smallskip -If $m=0$ then take $n$ steps up. - -Otherwise if $n=0$ then take $m$ steps to the right. - -Otherwise bisect the current cubics and repeat the process on both halves. - -\smallskip\noindent -The bisection process for $(X_1,X_2,X_3,m,R,l)$ reduces, in essence, -to the following formulas: -$$\vbox{\halign{$#\hfil$\cr -X_2'=\\{half}(X_1+X_2),\quad -X_2''=\\{half}(X_2+X_3),\quad -X_3'=\\{half}(X_2'+X_2''),\cr -X_1'=X_1,\quad -X_1''=X_3',\quad -X_3''=X_3,\cr -R'=2R,\quad -T=X_1'+X_2'+X_3'+R',\quad -R''=T\bmod 2^{l+1},\cr -m'=\lfloor T/2^{l+1}\rfloor,\quad -m''=m-m'.\cr}}$$ - -\fi - -\M305. When $m=n=1$, the computation can be speeded up because we simply -need to decide between two alternatives, (up,\thinspace right) -versus (right,\thinspace up). There appears to be no simple, direct -way to make the correct decision by looking at the values of -$(X_1,X_2,X_3,R)$ and -$(Y_1,Y_2,Y_3,S)$; but we can streamline the bisection process, and -we can use the fact that only one of the two descendants needs to -be examined after each bisection. Furthermore, we observed earlier -that after several levels of bisection the $X$'s and $Y$'s will be nearly -equal; so we will be justified in assuming that the curve is essentially a -straight line. (This, incidentally, solves the problem of infinite -recursion mentioned earlier.) - -It is possible to show that -$$m=\bigl\lfloor(X_1+X_2+X_3+R+E)\,/\,2^l\bigr\rfloor,$$ -where $E$ is an accumulated rounding error that is at most -$3\cdot(2^{l-16}-1)$ in absolute value. We will make sure that -the $X$'s are less than $2^{28}$; hence when $l=30$ we must -have $\|m\L1$. This proves that the special case $m=n=1$ is -bound to be reached by the time $l=30$. Furthermore $l=30$ is -a suitable time to make the straight line approximation, -if the recursion hasn't already died out, because the maximum -difference between $X$'s will then be $<2^{14}$; this corresponds -to an error of $<1$ with respect to the original scaling. -(Stating this another way, each bisection makes the curve two bits -closer to a straight line, hence 14 bisections are sufficient for -28-bit accuracy.) - -In the case of a straight line, the curve goes first right, then up, -if and only if $(T-2^l)(2^l-S)>(U-2^l)(2^l-R)$, where -$T=X_1+X_2+X_3+R$ and $U=Y_1+Y_2+Y_3+S$. For the actual curve -essentially runs from $(R/2^l,S/2^l)$ to $(T/2^l,U/2^l)$, and -we are testing whether or not $(1,1)$ is above the straight -line connecting these two points. (This formula assumes that $(1,1)$ -is not exactly on the line.) - -\fi - -\M306. We have glossed over the problem of tie-breaking in ambiguous -cases when the cubic curve passes exactly through integer points. -\MF\ finesses this problem by assuming that coordinates -$(x,y)$ actually stand for slightly perturbed values $(x+\xi,y+\eta)$, -where $\xi$ and~$\eta$ are infinitesimals whose signs will determine -what to do when $x$ and/or~$y$ are exact integers. The quantities -$\lfloor x\rfloor$ and~$\lfloor y\rfloor$ in the formulas above -should actually read $\lfloor x+\xi\rfloor$ and $\lfloor y+\eta\rfloor$. - -If $x$ is a \\{scaled} value, we have $\lfloor x+\xi\rfloor=\lfloor x\rfloor$ -if $\xi>0$, and $\lfloor x+\xi\rfloor=\lfloor x-2^{-16}\rfloor$ if -$\xi<0$. It is convenient to represent $\xi$ by the integer \\{xi\_corr}, -defined to be 0~if $\xi>0$ and 1~if $\xi<0$; then, for example, the -integer $\lfloor x+\xi\rfloor$ can be computed as -$\\{floor\_unscaled}(\|x-\\{xi\_corr})$. Similarly, $\eta$ is conveniently -represented by~\\{eta\_corr}. - -In our applications the sign of $\xi-\eta$ will always be the same as -the sign of $\xi$. Therefore it turns out that the rule for straight -lines, as stated above, should be modified as follows in the case of -ties: The line goes first right, then up, if and only if -$(T-2^l)(2^l-S)+\xi>(U-2^l)(2^l-R)$. And this relation holds iff -$\\{ab\_vs\_cd}(T-2^l,2^l-S,U-2^l,2^l-R)-\\{xi\_corr}\ge0$. - -These conventions for rounding are symmetrical, in the sense that the -digitized moves obtained from $(x_0,x_1,x_2,x_3,y_0,y_1,y_2,y_3,\xi,\eta)$ -will be exactly complementary to the moves that would be obtained from -$(-x_3,-x_2,-x_1,-x_0,-y_3,-y_2,-y_1,-y_0,-\xi,-\eta)$, if arithmetic -is exact. However, truncation errors in the bisection process might -upset the symmetry. We can restore much of the lost symmetry by adding -\\{xi\_corr} or \\{eta\_corr} when halving the data. - -\fi - -\M307. One further possibility needs to be mentioned: The algorithm -will be applied only to cubic polynomials $B(x_0,x_1,x_2,x_3;t)$ that -are nondecreasing as $t$~varies from 0 to~1; this condition turns -out to hold if and only if $x_0\L x_1$, $x_2\L x_3$, and either -$x_1\L x_2$ or $(x_1-x_2)^2\L(x_1-x_0)(x_3-x_2)$. If bisection were -carried out with perfect accuracy, these relations would remain -invariant. But rounding errors can creep in, hence the bisection -algorithm can produce non-monotonic subproblems from monotonic -initial conditions. This leads to the potential danger that $m$ or~$n$ -could become negative in the algorithm described above. - -For example, if we start with $(x_1-x_0,x_2-x_1,x_3-x_2)= -(X_1,X_2,X_3)=(7,-16,58)$, the corresponding polynomial is -monotonic, because $16^2<7\cdot39$. But the bisection algorithm -produces the left descendant $(7,-5,3)$, which is nonmonotonic; -its right descendant is~$(0,-1,3)$. - -\def\xt{{\tilde x}} -Fortunately we can prove that such rounding errors will never cause -the algorithm to make a tragic mistake. At every stage we are working -with numbers corresponding to a cubic polynomial $B(\xt_0, -\xt_1,\xt_2,\xt_3)$ that approximates some -monotonic polynomial $B(x_0,x_1,x_2,x_3)$. The accumulated errors are -controlled so that $\vert x_k-\xt_k\vert<\epsilon=3\cdot2^{-16}$. -If bisection is done at some stage of the recursion, we have -$m=\lfloor\xt_3\rfloor-\lfloor\xt_0\rfloor>0$, and the algorithm -computes a bisection value $\bar x$ such that $m'=\lfloor\bar x\rfloor- -\lfloor\xt_0\rfloor$ -and $m''=\lfloor\xt_3\rfloor-\lfloor\bar x\rfloor$. We want to prove -that neither $m'$ nor $m''$ can be negative. Since $\bar x$ is an -approximation to a value in the interval $[x_0,x_3]$, we have -$\bar x>x_0-\epsilon$ and $\bar x<x_3+\epsilon$, hence $\bar x> -\xt_0-2\epsilon$ and $\bar x<\xt_3+2\epsilon$. -If $m'$ is negative we must have $\xt_0\bmod 1<2\epsilon$; -if $m''$ is negative we must have $\xt_3\bmod 1>1-2\epsilon$. -In either case the condition $\lfloor\xt_3\rfloor-\lfloor\xt_0\rfloor>0$ -implies that $\xt_3-\xt_0>1-2\epsilon$, hence $x_3-x_0>1-4\epsilon$. -But it can be shown that if $B(x_0,x_1,x_2,x_3;t)$ is a monotonic -cubic, then $B(x_0,x_1,x_2,x_3;{1\over2})$ is always between -$.14[x_0,x_3]$ and $.86[x_0,x_3]$; and it is impossible for $\bar x$ -to be within~$\epsilon$ of such a number. Contradiction! -(The constant .14 is actually $(7-\sqrt{28}\,)/12$; the worst case -occurs for polynomials like $B(0,28-4\sqrt{28},14-5\sqrt{28},42;t)$.) - -\fi - -\M308. OK, now that a long theoretical preamble has justified the -bisection-and-doubling algorithm, we are ready to proceed with -its actual coding. But we still haven't discussed the -form of the output. - -For reasons to be discussed later, we shall find it convenient to -record the output as follows: Moving one step up is represented by -appending a `1' to a list; moving one step right is represented by -adding unity to the element at the end of the list. Thus, for example, -the net effect of ``(up, right, right, up, right)'' is to append -$(3,2)$. - -The list is kept in a global array called \\{move}. Before starting the -algorithm, \MF\ should check that $\\{move\_ptr}+\lfloor y_3\rfloor --\lfloor y_0\rfloor\L\\{move\_size}$, so that the list won't exceed -the bounds of this array. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{move}: \37\&{array} $[0\to\\{move\_size}]$ \1\&{of}\5 -\\{integer};\C{the recorded moves}\2\6 -\4\\{move\_ptr}: \37$0\to\\{move\_size}$;\C{the number of items in the \\{move} -list}\par -\fi - -\M309. When bisection occurs, we ``push'' the subproblem corresponding -to the right-hand subinterval onto the \\{bisect\_stack} while -we continue to work on the left-hand subinterval. Thus, the \\{bisect\_stack} -will hold $(X_1,X_2,X_3,R,m,Y_1,Y_2,Y_3,S,n,l)$ values for -subproblems yet to be tackled. - -At most 15 subproblems will be on the stack at once (namely, for -$l=15$,~16, \dots,~29); but the stack is bigger than this, because -it is used also for more complicated bisection algorithms. - -\Y\P\D \37$\\{stack\_x1}\S\\{bisect\_stack}[\\{bisect\_ptr}]$\C{stacked value -of $X_1$}\par -\P\D \37$\\{stack\_x2}\S\\{bisect\_stack}[\\{bisect\_ptr}+1]$\C{stacked value -of $X_2$}\par -\P\D \37$\\{stack\_x3}\S\\{bisect\_stack}[\\{bisect\_ptr}+2]$\C{stacked value -of $X_3$}\par -\P\D \37$\\{stack\_r}\S\\{bisect\_stack}[\\{bisect\_ptr}+3]$\C{stacked value of -$R$}\par -\P\D \37$\\{stack\_m}\S\\{bisect\_stack}[\\{bisect\_ptr}+4]$\C{stacked value of -$m$}\par -\P\D \37$\\{stack\_y1}\S\\{bisect\_stack}[\\{bisect\_ptr}+5]$\C{stacked value -of $Y_1$}\par -\P\D \37$\\{stack\_y2}\S\\{bisect\_stack}[\\{bisect\_ptr}+6]$\C{stacked value -of $Y_2$}\par -\P\D \37$\\{stack\_y3}\S\\{bisect\_stack}[\\{bisect\_ptr}+7]$\C{stacked value -of $Y_3$}\par -\P\D \37$\\{stack\_s}\S\\{bisect\_stack}[\\{bisect\_ptr}+8]$\C{stacked value of -$S$}\par -\P\D \37$\\{stack\_n}\S\\{bisect\_stack}[\\{bisect\_ptr}+9]$\C{stacked value of -$n$}\par -\P\D \37$\\{stack\_l}\S\\{bisect\_stack}[\\{bisect\_ptr}+10]$\C{stacked value -of $l$}\par -\P\D \37$\\{move\_increment}=11$\C{number of items pushed by \\{make\_moves}}% -\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{bisect\_stack}: \37\&{array} $[0\to\\{bistack\_size}]$ \1\&{of}\5 -\\{integer};\2\6 -\4\\{bisect\_ptr}: \37$0\to\\{bistack\_size}$;\par -\fi - -\M310. \P$\X14:Check the ``constant'' values for consistency\X\mathrel{+}\S$\6 -\&{if} $15\ast\\{move\_increment}>\\{bistack\_size}$ \1\&{then}\5 -$\\{bad}\K31$;\2\par -\fi - -\M311. The \\{make\_moves} subroutine is given \\{scaled} values -$(x_0,x_1,x_2,x_3)$ -and $(y_0,y_1,y_2,y_3)$ that represent monotone-nondecreasing polynomials; -it makes $\lfloor x_3+\xi\rfloor-\lfloor x_0+\xi\rfloor$ rightward moves -and $\lfloor y_3+\eta\rfloor-\lfloor y_0+\eta\rfloor$ upward moves, as -explained earlier. (Here $\lfloor x+\xi\rfloor$ actually stands for -$\lfloor x/2^{16}-\\{xi\_corr}\rfloor$, if $x$ is regarded as an integer -without scaling.) The unscaled integers $x_k$ and~$y_k$ should be less -than $2^{28}$ in magnitude. - -It is assumed that $\\{move\_ptr} + \lfloor y_3+\eta\rfloor - -\lfloor y_0+\eta\rfloor < \\{move\_size}$ when this procedure is called, -so that the capacity of the \\{move} array will not be exceeded. - -The variables \|r and \|s in this procedure stand respectively for -$R-\\{xi\_corr}$ and $S-\\{eta\_corr}$ in the theory discussed above. - -\Y\P\4\&{procedure}\1\ \37$\\{make\_moves}(\\{xx0},\39\\{xx1},\39\\{xx2},\39% -\\{xx3},\39\\{yy0},\39\\{yy1},\39\\{yy2},\39\\{yy3}:\\{scaled};\,\35\\{xi% -\_corr},\39\\{eta\_corr}:\\{small\_number})$;\6 -\4\&{label} \37$\\{continue},\39\\{done},\39\\{exit}$;\6 -\4\&{var} \37$\\{x1},\39\\{x2},\39\\{x3},\39\|m,\39\|r,\39\\{y1},\39\\{y2},\39% -\\{y3},\39\|n,\39\|s,\39\|l$: \37\\{integer};\C{bisection variables explained -above}\6 -$\|q,\39\|t,\39\|u,\39\\{x2a},\39\\{x3a},\39\\{y2a},\39\\{y3a}$: \37% -\\{integer};\C{additional temporary registers}\2\6 -\&{begin} \37\&{if} $(\\{xx3}<\\{xx0})\V(\\{yy3}<\\{yy0})$ \1\&{then}\5 -$\\{confusion}(\.{"m"})$;\2\6 -$\|l\K16$;\5 -$\\{bisect\_ptr}\K0$;\6 -$\\{x1}\K\\{xx1}-\\{xx0}$;\5 -$\\{x2}\K\\{xx2}-\\{xx1}$;\5 -$\\{x3}\K\\{xx3}-\\{xx2}$;\6 -\&{if} $\\{xx0}\G\\{xi\_corr}$ \1\&{then}\5 -$\|r\K(\\{xx0}-\\{xi\_corr})\mathbin{\&{mod}}\\{unity}$\6 -\4\&{else} $\|r\K\\{unity}-1-((-\\{xx0}+\\{xi\_corr}-1)\mathbin{\&{mod}}% -\\{unity})$;\2\6 -$\|m\K(\\{xx3}-\\{xx0}+\|r)\mathbin{\&{div}}\\{unity}$;\6 -$\\{y1}\K\\{yy1}-\\{yy0}$;\5 -$\\{y2}\K\\{yy2}-\\{yy1}$;\5 -$\\{y3}\K\\{yy3}-\\{yy2}$;\6 -\&{if} $\\{yy0}\G\\{eta\_corr}$ \1\&{then}\5 -$\|s\K(\\{yy0}-\\{eta\_corr})\mathbin{\&{mod}}\\{unity}$\6 -\4\&{else} $\|s\K\\{unity}-1-((-\\{yy0}+\\{eta\_corr}-1)\mathbin{\&{mod}}% -\\{unity})$;\2\6 -$\|n\K(\\{yy3}-\\{yy0}+\|s)\mathbin{\&{div}}\\{unity}$;\6 -\&{if} $(\\{xx3}-\\{xx0}\G\\{fraction\_one})\V(\\{yy3}-\\{yy0}\G\\{fraction% -\_one})$ \1\&{then}\5 -\X313:Divide the variables by two, to avoid overflow problems\X;\2\6 -\~ \1\&{loop}\ \&{begin} \37\\{continue}: \37\X314:Make moves for current -subinterval; if bisection is necessary, push the second subinterval onto the -stack, and \&{goto} \\{continue} in order to handle the first subinterval\X;\6 -\&{if} $\\{bisect\_ptr}=0$ \1\&{then}\5 -\&{return};\2\6 -\X312:Remove a subproblem for \\{make\_moves} from the stack\X;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M312. \P$\X312:Remove a subproblem for \\{make\_moves} from the stack\X\S$\6 -$\\{bisect\_ptr}\K\\{bisect\_ptr}-\\{move\_increment}$;\6 -$\\{x1}\K\\{stack\_x1}$;\5 -$\\{x2}\K\\{stack\_x2}$;\5 -$\\{x3}\K\\{stack\_x3}$;\5 -$\|r\K\\{stack\_r}$;\5 -$\|m\K\\{stack\_m}$;\6 -$\\{y1}\K\\{stack\_y1}$;\5 -$\\{y2}\K\\{stack\_y2}$;\5 -$\\{y3}\K\\{stack\_y3}$;\5 -$\|s\K\\{stack\_s}$;\5 -$\|n\K\\{stack\_n}$;\6 -$\|l\K\\{stack\_l}$\par -\U311.\fi - -\M313. Our variables $(\\{x1},\\{x2},\\{x3})$ correspond to $(X_1,X_2,X_3)$ in -the notation -of the theory developed above. We need to keep them less than $2^{28}$ -in order to avoid integer overflow in weird circumstances. -For example, data like $x_0=-2^{28}+2^{16}-1$ and $x_1=x_2=x_3=2^{28}-1$ -would otherwise be problematical. Hence this part of the code is -needed, if only to thwart malicious users. - -\Y\P$\4\X313:Divide the variables by two, to avoid overflow problems\X\S$\6 -\&{begin} \37$\\{x1}\K\\{half}(\\{x1}+\\{xi\_corr})$;\5 -$\\{x2}\K\\{half}(\\{x2}+\\{xi\_corr})$;\5 -$\\{x3}\K\\{half}(\\{x3}+\\{xi\_corr})$;\5 -$\|r\K\\{half}(\|r+\\{xi\_corr})$;\6 -$\\{y1}\K\\{half}(\\{y1}+\\{eta\_corr})$;\5 -$\\{y2}\K\\{half}(\\{y2}+\\{eta\_corr})$;\5 -$\\{y3}\K\\{half}(\\{y3}+\\{eta\_corr})$;\5 -$\|s\K\\{half}(\|s+\\{eta\_corr})$;\6 -$\|l\K15$;\6 -\&{end}\par -\U311.\fi - -\M314. \P$\X314:Make moves for current subinterval; if bisection is necessary, -push the second subinterval onto the stack, and \&{goto} \\{continue} in order -to handle the first subinterval\X\S$\6 -\&{if} $\|m=0$ \1\&{then}\5 -\X315:Move upward \|n steps\X\6 -\4\&{else} \&{if} $\|n=0$ \1\&{then}\5 -\X316:Move to the right \|m steps\X\6 -\4\&{else} \&{if} $\|m+\|n=2$ \1\&{then}\5 -\X317:Make one move of each kind\X\6 -\4\&{else} \&{begin} \37$\\{incr}(\|l)$;\5 -$\\{stack\_l}\K\|l$;\6 -$\\{stack\_x3}\K\\{x3}$;\5 -$\\{stack\_x2}\K\\{half}(\\{x2}+\\{x3}+\\{xi\_corr})$;\5 -$\\{x2}\K\\{half}(\\{x1}+\\{x2}+\\{xi\_corr})$;\5 -$\\{x3}\K\\{half}(\\{x2}+\\{stack\_x2}+\\{xi\_corr})$;\5 -$\\{stack\_x1}\K\\{x3}$;\6 -$\|r\K\|r+\|r+\\{xi\_corr}$;\5 -$\|t\K\\{x1}+\\{x2}+\\{x3}+\|r$;\6 -$\|q\K\|t\mathbin{\&{div}}\\{two\_to\_the}[\|l]$;\5 -$\\{stack\_r}\K\|t\mathbin{\&{mod}}\\{two\_to\_the}[\|l]$;\6 -$\\{stack\_m}\K\|m-\|q$;\5 -$\|m\K\|q$;\6 -$\\{stack\_y3}\K\\{y3}$;\5 -$\\{stack\_y2}\K\\{half}(\\{y2}+\\{y3}+\\{eta\_corr})$;\5 -$\\{y2}\K\\{half}(\\{y1}+\\{y2}+\\{eta\_corr})$;\5 -$\\{y3}\K\\{half}(\\{y2}+\\{stack\_y2}+\\{eta\_corr})$;\5 -$\\{stack\_y1}\K\\{y3}$;\6 -$\|s\K\|s+\|s+\\{eta\_corr}$;\5 -$\|u\K\\{y1}+\\{y2}+\\{y3}+\|s$;\6 -$\|q\K\|u\mathbin{\&{div}}\\{two\_to\_the}[\|l]$;\5 -$\\{stack\_s}\K\|u\mathbin{\&{mod}}\\{two\_to\_the}[\|l]$;\6 -$\\{stack\_n}\K\|n-\|q$;\5 -$\|n\K\|q$;\6 -$\\{bisect\_ptr}\K\\{bisect\_ptr}+\\{move\_increment}$;\5 -\&{goto} \37\\{continue};\6 -\&{end}\2\2\2\par -\U311.\fi - -\M315. \P$\X315:Move upward \|n steps\X\S$\6 -\&{while} $\|n>0$ \1\&{do}\6 -\&{begin} \37$\\{incr}(\\{move\_ptr})$;\5 -$\\{move}[\\{move\_ptr}]\K1$;\5 -$\\{decr}(\|n)$;\6 -\&{end}\2\par -\U314.\fi - -\M316. \P$\X316:Move to the right \|m steps\X\S$\6 -$\\{move}[\\{move\_ptr}]\K\\{move}[\\{move\_ptr}]+\|m$\par -\U314.\fi - -\M317. \P$\X317:Make one move of each kind\X\S$\6 -\&{begin} \37$\|r\K\\{two\_to\_the}[\|l]-\|r$;\5 -$\|s\K\\{two\_to\_the}[\|l]-\|s$;\6 -\&{while} $\|l<30$ \1\&{do}\6 -\&{begin} \37$\\{x3a}\K\\{x3}$;\5 -$\\{x2a}\K\\{half}(\\{x2}+\\{x3}+\\{xi\_corr})$;\5 -$\\{x2}\K\\{half}(\\{x1}+\\{x2}+\\{xi\_corr})$;\5 -$\\{x3}\K\\{half}(\\{x2}+\\{x2a}+\\{xi\_corr})$;\5 -$\|t\K\\{x1}+\\{x2}+\\{x3}$;\5 -$\|r\K\|r+\|r-\\{xi\_corr}$;\6 -$\\{y3a}\K\\{y3}$;\5 -$\\{y2a}\K\\{half}(\\{y2}+\\{y3}+\\{eta\_corr})$;\5 -$\\{y2}\K\\{half}(\\{y1}+\\{y2}+\\{eta\_corr})$;\5 -$\\{y3}\K\\{half}(\\{y2}+\\{y2a}+\\{eta\_corr})$;\5 -$\|u\K\\{y1}+\\{y2}+\\{y3}$;\5 -$\|s\K\|s+\|s-\\{eta\_corr}$;\6 -\&{if} $\|t<\|r$ \1\&{then}\6 -\&{if} $\|u<\|s$ \1\&{then}\5 -\X318:Switch to the right subinterval\X\6 -\4\&{else} \&{begin} \37\X320:Move up then right\X;\6 -\&{goto} \37\\{done};\6 -\&{end}\2\6 -\4\&{else} \&{if} $\|u<\|s$ \1\&{then}\6 -\&{begin} \37\X319:Move right then up\X;\6 -\&{goto} \37\\{done};\6 -\&{end};\2\2\6 -$\\{incr}(\|l)$;\6 -\&{end};\2\6 -$\|r\K\|r-\\{xi\_corr}$;\5 -$\|s\K\|s-\\{eta\_corr}$;\6 -\&{if} $\\{ab\_vs\_cd}(\\{x1}+\\{x2}+\\{x3},\39\|s,\39\\{y1}+\\{y2}+\\{y3},\39% -\|r)-\\{xi\_corr}\G0$ \1\&{then}\5 -\X319:Move right then up\X\6 -\4\&{else} \X320:Move up then right\X;\2\6 -\4\\{done}: \37\&{end}\par -\U314.\fi - -\M318. \P$\X318:Switch to the right subinterval\X\S$\6 -\&{begin} \37$\\{x1}\K\\{x3}$;\5 -$\\{x2}\K\\{x2a}$;\5 -$\\{x3}\K\\{x3a}$;\5 -$\|r\K\|r-\|t$;\5 -$\\{y1}\K\\{y3}$;\5 -$\\{y2}\K\\{y2a}$;\5 -$\\{y3}\K\\{y3a}$;\5 -$\|s\K\|s-\|u$;\6 -\&{end}\par -\U317.\fi - -\M319. \P$\X319:Move right then up\X\S$\6 -\&{begin} \37$\\{incr}(\\{move}[\\{move\_ptr}])$;\5 -$\\{incr}(\\{move\_ptr})$;\5 -$\\{move}[\\{move\_ptr}]\K1$;\6 -\&{end}\par -\Us317\ET317.\fi - -\M320. \P$\X320:Move up then right\X\S$\6 -\&{begin} \37$\\{incr}(\\{move\_ptr})$;\5 -$\\{move}[\\{move\_ptr}]\K2$;\6 -\&{end}\par -\Us317\ET317.\fi - -\M321. After \\{make\_moves} has acted, possibly for several curves that move -toward -the same octant, a ``smoothing'' operation might be done on the \\{move} array. -This removes optical glitches that can arise even when the curve has been -digitized without rounding errors. - -The smoothing process replaces the integers $a_0\ldots a_n$ in -$\\{move}[\|b\to\|t]$ by ``smoothed'' integers $a_0'\ldots a_n'$ defined as -follows: -$$a_k'=a_k+\delta\k-\delta_k;\qquad -\delta_k=\cases{+1,&if $1<k<n$ and $a_{k-2}\G a_{k-1}\ll a_k\G a\k$;\cr --1,&if $1<k<n$ and $a_{k-2}\L a_{k-1}\gg a_k\L a\k$;\cr -0,&otherwise.\cr}$$ -Here $a\ll b$ means that $a\L b-2$, and $a\gg b$ means that $a\G b+2$. - -The smoothing operation is symmetric in the sense that, if $a_0\ldots a_n$ -smoothes to $a_0'\ldots a_n'$, then the reverse sequence $a_n\ldots a_0$ -smoothes to $a_n'\ldots a_0'$; also the complementary sequence -$(m-a_0)\ldots(m-a_n)$ smoothes to $(m-a_0')\ldots(m-a_n')$. -We have $a_0'+\cdots+a_n'=a_0+\cdots+a_n$ because $\delta_0=\delta_{n+1}=0$. - -\Y\P\4\&{procedure}\1\ \37$\\{smooth\_moves}(\|b,\39\|t:\\{integer})$;\6 -\4\&{var} \37\|k: \37$1\to\\{move\_size}$;\C{index into \\{move}}\6 -$\|a,\39\\{aa},\39\\{aaa}$: \37\\{integer};\C{original values of $\\{move}[% -\|k],\\{move}[\|k-1],\\{move}[\|k-2]$}\2\6 -\&{begin} \37\&{if} $\|t-\|b\G3$ \1\&{then}\6 -\&{begin} \37$\|k\K\|b+2$;\5 -$\\{aa}\K\\{move}[\|k-1]$;\5 -$\\{aaa}\K\\{move}[\|k-2]$;\6 -\1\&{repeat} \37$\|a\K\\{move}[\|k]$;\6 -\&{if} $\\{abs}(\|a-\\{aa})>1$ \1\&{then}\5 -\X322:Increase and decrease $\\{move}[\|k-1]$ and $\\{move}[\|k]$ by $\delta_k$% -\X;\2\6 -$\\{incr}(\|k)$;\5 -$\\{aaa}\K\\{aa}$;\5 -$\\{aa}\K\|a$;\6 -\4\&{until}\5 -$\|k=\|t$;\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M322. \P$\X322:Increase and decrease $\\{move}[\|k-1]$ and $\\{move}[\|k]$ by -$\delta_k$\X\S$\6 -\&{if} $\|a>\\{aa}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{aaa}\G\\{aa}$ \1\&{then}\6 -\&{if} $\|a\G\\{move}[\|k+1]$ \1\&{then}\6 -\&{begin} \37$\\{incr}(\\{move}[\|k-1])$;\5 -$\\{move}[\|k]\K\|a-1$;\6 -\&{end};\2\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{aaa}\L\\{aa}$ \1\&{then}\6 -\&{if} $\|a\L\\{move}[\|k+1]$ \1\&{then}\6 -\&{begin} \37$\\{decr}(\\{move}[\|k-1])$;\5 -$\\{move}[\|k]\K\|a+1$;\6 -\&{end};\2\2\6 -\&{end}\2\par -\U321.\fi - -\N323. \[20] Edge structures. -Now we come to \MF's internal scheme for representing what the user can -actually ``see,'' the edges between pixels. Each pixel has an integer -weight, obtained by summing the weights on all edges to its left. \MF\ -represents only the nonzero edge weights, since most of the edges are -weightless; in this way, the data storage requirements grow only linearly -with respect to the number of pixels per point, even though two-dimensional -data is being represented. (Well, the actual dependence on the underlying -resolution is order $n\log n$, but the the $\log n$ factor is buried in our -implicit restriction on the maximum raster size.) The sum of all edge -weights in each row should be zero. - -The data structure for edge weights must be compact and flexible, -yet it should support efficient updating and display operations. We -want to be able to have many different edge structures in memory at -once, and we want the computer to be able to translate them, reflect them, -and/or merge them together with relative ease. - -\MF's solution to this problem requires one single-word node per -nonzero edge weight, plus one two-word node for each row in a contiguous -set of rows. There's also a header node that provides global information -about the entire structure. - -\fi - -\M324. Let's consider the edge-weight nodes first. The \\{info} field of such -nodes contains both an $m$~value and a weight~$w$, in the form -$8m+w+c$, where $c$ is a constant that depends on data found in the header. -We shall consider $c$ in detail later; for now, it's best just to think -of it as a way to compensate for the fact that $m$ and~$w$ can be negative, -together with the fact that an \\{info} field must have a value between -\\{min\_halfword} and \\{max\_halfword}. The $m$ value is an unscaled -$x$~coordinate, -so it satisfies $\vert m\vert< -4096$; the $w$ value is always in the range $1\L\vert w\vert\L3$. We can -unpack the data in the \\{info} field by fetching $\\{ho}(\\{info}(\|p))=% -\\{info}(\|p)-\\{min\_halfword}$ and dividing this nonnegative number by~8; -the constant~$c$ will be chosen so that the remainder of this division -is $4+w$. Thus, for example, a remainder of~3 will correspond to -the edge weight $w=-1$. - -Every row of an edge structure contains two lists of such edge-weight -nodes, called the \\{sorted} and \\{unsorted} lists, linked together by their -\\{link} fields in the normal way. The difference between them is that we -always have $\\{info}(\|p)\L\\{info}(\\{link}(\|p))$ in the \\{sorted} list, -but there's no -such restriction on the elements of the \\{unsorted} list. The reason for -this distinction is that it would take unnecessarily long to maintain -edge-weight lists in sorted order while they're being updated; but when we -need to process an entire row from left to right in order of the -$m$~values, it's fairly easy and quick to sort a short list of unsorted -elements and to merge them into place among their sorted cohorts. -Furthermore, the fact that the \\{unsorted} list is empty can sometimes be -used to good advantage, because it allows us to conclude that a particular -row has not changed since the last time we sorted it. - -The final \\{link} of the \\{sorted} list will be \\{sentinel}, which points to -a special one-word node whose \\{info} field is essentially infinite; this -facilitates the sorting and merging operations. The final \\{link} of the -\\{unsorted} list will be either \\{null} or \\{void}, where $\\{void}=% -\\{null}+1$ -is used to avoid redisplaying data that has not changed: -A \\{void} value is stored at the head of the -unsorted list whenever the corresponding row has been displayed. - -\Y\P\D \37$\\{zero\_w}=4$\par -\P\D \37$\\{void}\S\\{null}+1$\par -\Y\P$\4\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}\S$\6 -$\\{info}(\\{sentinel})\K\\{max\_halfword}$;\C{$\\{link}(\\{sentinel})=% -\\{null}$}\par -\fi - -\M325. The rows themselves are represented by row-header nodes that -contain four link fields. Two of these four, \\{sorted} and \\{unsorted}, -point to the first items of the edge-weight lists just mentioned. -The other two, \\{link} and \\{knil}, point to the headers of the two -adjacent rows. If \|p points to the header for row number~\|n, then -$\\{link}(\|p)$ points up to the header for row~$\|n+1$, and $\\{knil}(\|p)$ -points -down to the header for row~$\|n-1$. This double linking makes it -convenient to move through consecutive rows either upward or downward; -as usual, we have $\\{link}(\\{knil}(\|p))=\\{knil}(\\{link}(\|p))=\|p$ for all -row headers~\|p. - -The row associated with a given value of \|n contains weights for -edges that run between the lattice points $(\|m,\|n)$ and $(\|m,\|n+1)$. - -\Y\P\D \37$\\{knil}\S\\{info}$\C{inverse of the \\{link} field, in a doubly -linked list}\par -\P\D \37$\\{sorted\_loc}(\#)\S\#+1$\C{where the \\{sorted} link field resides}% -\par -\P\D \37$\\{sorted}(\#)\S\\{link}(\\{sorted\_loc}(\#))$\C{beginning of the list -of sorted edge weights}\par -\P\D \37$\\{unsorted}(\#)\S\\{info}(\#+1)$\C{beginning of the list of unsorted -edge weights}\par -\P\D \37$\\{row\_node\_size}=2$\C{number of words in a row header node}\par -\fi - -\M326. The main header node \|h for an edge structure has \\{link} and \\{knil} -fields that link it above the topmost row and below the bottommost row. -It also has fields called \\{m\_min}, \\{m\_max}, \\{n\_min}, and \\{n\_max} -that -bound the current extent of the edge data: All \|m values in edge-weight -nodes should lie between $\\{m\_min}(\|h)-4096$ and $\\{m\_max}(\|h)-4096$, -inclusive. -Furthermore the topmost row header, pointed to by $\\{knil}(\|h)$, -is for row number $\\{n\_max}(\|h)-4096$; the bottommost row header, pointed to -by -$\\{link}(\|h)$, is for row number $\\{n\_min}(\|h)-4096$. - -The offset constant \|c that's used in all of the edge-weight data is -represented implicitly in $\\{m\_offset}(\|h)$; its actual value is -$$\hbox{$\|c=\\{min\_halfword}+\\{zero\_w}+8\ast\\{m\_offset}(\|h)$.}$$ -Notice that it's possible to shift an entire edge structure by an -amount $(\Delta m,\Delta n)$ by adding $\Delta n$ to $\\{n\_min}(\|h)$ and $% -\\{n\_max}(\|h)$, -adding $\Delta m$ to $\\{m\_min}(\|h)$ and $\\{m\_max}(\|h)$, and subtracting -$\Delta m$ from $\\{m\_offset}(\|h)$; -none of the other edge data needs to be modified. Initially the \\{m\_offset} -field is~4096, but it will change if the user requests such a shift. -The contents of these five fields should always be positive and less than -8192; \\{n\_max} should, in fact, be less than 8191. Furthermore -$\\{m\_min}+\\{m\_offset}-4096$ and $\\{m\_max}+\\{m\_offset}-4096$ must also -lie strictly -between 0 and 8192, so that the \\{info} fields of edge-weight nodes will -fit in a halfword. - -The header node of an edge structure also contains two somewhat unusual -fields that are called $\\{last\_window}(\|h)$ and $\\{last\_window\_time}(% -\|h)$. When this -structure is displayed in window~\|k of the user's screen, after that -window has been updated \|t times, \MF\ sets $\\{last\_window}(\|h)\K\|k$ and -$\\{last\_window\_time}(\|h)\K\|t$; it also sets $\\{unsorted}(\|p)\K\\{void}$ -for all row -headers~\|p, after merging any existing unsorted weights with the sorted -ones. A subsequent display in the same window will be able to avoid -redisplaying rows whose \\{unsorted} list is still \\{void}, if the window -hasn't been used for something else in the meantime. - -A pointer to the row header of row $\\{n\_pos}(\|h)-4096$ is provided in -$\\{n\_rover}(\|h)$. Most of the algorithms that update an edge structure -are able to get by without random row references; they usually -access rows that are neighbors of each other or of the current \\{n\_pos} row. -Exception: If $\\{link}(\|h)=\|h$ (so that the edge structure contains -no rows), we have $\\{n\_rover}(\|h)=\|h$, and $\\{n\_pos}(\|h)$ is irrelevant. - -\Y\P\D \37$\\{zero\_field}=4096$\C{amount added to coordinates to make them -positive}\par -\P\D \37$\\{n\_min}(\#)\S\\{info}(\#+1)$\C{minimum row number present, plus % -\\{zero\_field}}\par -\P\D \37$\\{n\_max}(\#)\S\\{link}(\#+1)$\C{maximum row number present, plus % -\\{zero\_field}}\par -\P\D \37$\\{m\_min}(\#)\S\\{info}(\#+2)$\C{minimum column number present, plus % -\\{zero\_field}}\par -\P\D \37$\\{m\_max}(\#)\S\\{link}(\#+2)$\C{maximum column number present, plus % -\\{zero\_field}}\par -\P\D \37$\\{m\_offset}(\#)\S\\{info}(\#+3)$\C{translation of $m$ data in -edge-weight nodes}\par -\P\D \37$\\{last\_window}(\#)\S\\{link}(\#+3)$\C{the last display went into -this window}\par -\P\D \37$\\{last\_window\_time}(\#)\S\\{mem}[\#+4].\\{int}$\C{after this many -window updates}\par -\P\D \37$\\{n\_pos}(\#)\S\\{info}(\#+5)$\C{the row currently in \\{n\_rover}, -plus \\{zero\_field}}\par -\P\D \37$\\{n\_rover}(\#)\S\\{link}(\#+5)$\C{a row recently referenced}\par -\P\D \37$\\{edge\_header\_size}=6$\C{number of words in an edge-structure -header}\par -\P\D \37$\\{valid\_range}(\#)\S(\\{abs}(\#-4096)<4096)$\C{is $\#$ strictly -between 0 and 8192?}\par -\P\D \37$\\{empty\_edges}(\#)\S\\{link}(\#)=\#$\C{are there no rows in this -edge header?}\par -\Y\P\4\&{procedure}\1\ \37$\\{init\_edges}(\|h:\\{pointer})$;\C{initialize an -edge header to null values}\2\6 -\&{begin} \37$\\{knil}(\|h)\K\|h$;\5 -$\\{link}(\|h)\K\|h$;\6 -$\\{n\_min}(\|h)\K\\{zero\_field}+4095$;\5 -$\\{n\_max}(\|h)\K\\{zero\_field}-4095$;\5 -$\\{m\_min}(\|h)\K\\{zero\_field}+4095$;\5 -$\\{m\_max}(\|h)\K\\{zero\_field}-4095$;\5 -$\\{m\_offset}(\|h)\K\\{zero\_field}$;\6 -$\\{last\_window}(\|h)\K0$;\5 -$\\{last\_window\_time}(\|h)\K0$;\6 -$\\{n\_rover}(\|h)\K\|h$;\5 -$\\{n\_pos}(\|h)\K0$;\6 -\&{end};\par -\fi - -\M327. When a lot of work is being done on a particular edge structure, we -plant -a pointer to its main header in the global variable \\{cur\_edges}. -This saves us from having to pass this pointer as a parameter over and -over again between subroutines. - -Similarly, \\{cur\_wt} is a global weight that is being used by several -procedures at once. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{cur\_edges}: \37\\{pointer};\C{the edge structure of current interest}\6 -\4\\{cur\_wt}: \37\\{integer};\C{the edge weight of current interest}\par -\fi - -\M328. The \\{fix\_offset} routine goes through all the edge-weight nodes of -\\{cur\_edges} and adds a constant to their \\{info} fields, so that -$\\{m\_offset}(\\{cur\_edges})$ can be brought back to \\{zero\_field}. (This -is necessary only in unusual cases when the offset has gotten too -large or too small.) - -\Y\P\4\&{procedure}\1\ \37\\{fix\_offset};\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{list traversers}\6 -\\{delta}: \37\\{integer};\C{the amount of change}\2\6 -\&{begin} \37$\\{delta}\K8\ast(\\{m\_offset}(\\{cur\_edges})-\\{zero\_field})$;% -\5 -$\\{m\_offset}(\\{cur\_edges})\K\\{zero\_field}$;\5 -$\|q\K\\{link}(\\{cur\_edges})$;\6 -\&{while} $\|q\I\\{cur\_edges}$ \1\&{do}\6 -\&{begin} \37$\|p\K\\{sorted}(\|q)$;\6 -\&{while} $\|p\I\\{sentinel}$ \1\&{do}\6 -\&{begin} \37$\\{info}(\|p)\K\\{info}(\|p)-\\{delta}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\|p\K\\{unsorted}(\|q)$;\6 -\&{while} $\|p>\\{void}$ \1\&{do}\6 -\&{begin} \37$\\{info}(\|p)\K\\{info}(\|p)-\\{delta}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M329. The \\{edge\_prep} routine makes the \\{cur\_edges} structure ready to -accept new data whose coordinates satisfy $\\{ml}\L\|m\L\\{mr}$ and $\\{nl}\L% -\|n\L\\{nr}-1$, -assuming that $-4096<\\{ml}\L\\{mr}<4096$ and $-4096<\\{nl}\L\\{nr}<4096$. It -makes -appropriate adjustments to \\{m\_min}, \\{m\_max}, \\{n\_min}, and \\{n\_max}, -adding new empty rows if necessary. - -\Y\P\4\&{procedure}\1\ \37$\\{edge\_prep}(\\{ml},\39\\{mr},\39\\{nl},\39% -\\{nr}:\\{integer})$;\6 -\4\&{var} \37\\{delta}: \37\\{halfword};\C{amount of change}\6 -$\|p,\39\|q$: \37\\{pointer};\C{for list manipulation}\2\6 -\&{begin} \37$\\{ml}\K\\{ml}+\\{zero\_field}$;\5 -$\\{mr}\K\\{mr}+\\{zero\_field}$;\5 -$\\{nl}\K\\{nl}+\\{zero\_field}$;\5 -$\\{nr}\K\\{nr}-1+\\{zero\_field}$;\6 -\&{if} $\\{ml}<\\{m\_min}(\\{cur\_edges})$ \1\&{then}\5 -$\\{m\_min}(\\{cur\_edges})\K\\{ml}$;\2\6 -\&{if} $\\{mr}>\\{m\_max}(\\{cur\_edges})$ \1\&{then}\5 -$\\{m\_max}(\\{cur\_edges})\K\\{mr}$;\2\6 -\&{if} $\R\\{valid\_range}(\\{m\_min}(\\{cur\_edges})+\\{m\_offset}(\\{cur% -\_edges})-\\{zero\_field})\V\30\R\\{valid\_range}(\\{m\_max}(\\{cur\_edges})+% -\\{m\_offset}(\\{cur\_edges})-\\{zero\_field})$ \1\&{then}\5 -\\{fix\_offset};\2\6 -\&{if} $\\{empty\_edges}(\\{cur\_edges})$ \1\&{then}\C{there are no rows}\6 -\&{begin} \37$\\{n\_min}(\\{cur\_edges})\K\\{nr}+1$;\5 -$\\{n\_max}(\\{cur\_edges})\K\\{nr}$;\6 -\&{end};\2\6 -\&{if} $\\{nl}<\\{n\_min}(\\{cur\_edges})$ \1\&{then}\5 -\X330:Insert exactly $\\{n\_min}(\\{cur\_edges})-\\{nl}$ empty rows at the -bottom\X;\2\6 -\&{if} $\\{nr}>\\{n\_max}(\\{cur\_edges})$ \1\&{then}\5 -\X331:Insert exactly $\\{nr}-\\{n\_max}(\\{cur\_edges})$ empty rows at the top% -\X;\2\6 -\&{end};\par -\fi - -\M330. \P$\X330:Insert exactly $\\{n\_min}(\\{cur\_edges})-\\{nl}$ empty rows -at the bottom\X\S$\6 -\&{begin} \37$\\{delta}\K\\{n\_min}(\\{cur\_edges})-\\{nl}$;\5 -$\\{n\_min}(\\{cur\_edges})\K\\{nl}$;\5 -$\|p\K\\{link}(\\{cur\_edges})$;\6 -\1\&{repeat} \37$\|q\K\\{get\_node}(\\{row\_node\_size})$;\5 -$\\{sorted}(\|q)\K\\{sentinel}$;\5 -$\\{unsorted}(\|q)\K\\{void}$;\5 -$\\{knil}(\|p)\K\|q$;\5 -$\\{link}(\|q)\K\|p$;\5 -$\|p\K\|q$;\5 -$\\{decr}(\\{delta})$;\6 -\4\&{until}\5 -$\\{delta}=0$;\2\6 -$\\{knil}(\|p)\K\\{cur\_edges}$;\5 -$\\{link}(\\{cur\_edges})\K\|p$;\6 -\&{if} $\\{n\_rover}(\\{cur\_edges})=\\{cur\_edges}$ \1\&{then}\5 -$\\{n\_pos}(\\{cur\_edges})\K\\{nl}-1$;\2\6 -\&{end}\par -\U329.\fi - -\M331. \P$\X331:Insert exactly $\\{nr}-\\{n\_max}(\\{cur\_edges})$ empty rows -at the top\X\S$\6 -\&{begin} \37$\\{delta}\K\\{nr}-\\{n\_max}(\\{cur\_edges})$;\5 -$\\{n\_max}(\\{cur\_edges})\K\\{nr}$;\5 -$\|p\K\\{knil}(\\{cur\_edges})$;\6 -\1\&{repeat} \37$\|q\K\\{get\_node}(\\{row\_node\_size})$;\5 -$\\{sorted}(\|q)\K\\{sentinel}$;\5 -$\\{unsorted}(\|q)\K\\{void}$;\5 -$\\{link}(\|p)\K\|q$;\5 -$\\{knil}(\|q)\K\|p$;\5 -$\|p\K\|q$;\5 -$\\{decr}(\\{delta})$;\6 -\4\&{until}\5 -$\\{delta}=0$;\2\6 -$\\{link}(\|p)\K\\{cur\_edges}$;\5 -$\\{knil}(\\{cur\_edges})\K\|p$;\6 -\&{if} $\\{n\_rover}(\\{cur\_edges})=\\{cur\_edges}$ \1\&{then}\5 -$\\{n\_pos}(\\{cur\_edges})\K\\{nr}+1$;\2\6 -\&{end}\par -\U329.\fi - -\M332. The \\{print\_edges} subroutine gives a symbolic rendition of an edge -structure, for use in `\&{show}' commands. A rather terse output -format has been chosen since edge structures can grow quite large. - -\Y\P$\4\X257:Declare subroutines for printing expressions\X\mathrel{+}\S$\6 -\hbox{\4}\X333:Declare the procedure called \\{print\_weight}\X\6 -\4\&{procedure}\1\ \37$\\{print\_edges}(\|s:\\{str\_number};\,\35\\{nuline}:% -\\{boolean};\,\35\\{x\_off},\39\\{y\_off}:\\{integer})$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{for list traversal}\6 -\|n: \37\\{integer};\C{row number}\2\6 -\&{begin} \37$\\{print\_diagnostic}(\.{"Edge\ structure"},\39\|s,\39% -\\{nuline})$;\5 -$\|p\K\\{knil}(\\{cur\_edges})$;\5 -$\|n\K\\{n\_max}(\\{cur\_edges})-\\{zero\_field}$;\6 -\&{while} $\|p\I\\{cur\_edges}$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{unsorted}(\|p)$;\5 -$\|r\K\\{sorted}(\|p)$;\6 -\&{if} $(\|q>\\{void})\V(\|r\I\\{sentinel})$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"row\ "})$;\5 -$\\{print\_int}(\|n+\\{y\_off})$;\5 -$\\{print\_char}(\.{":"})$;\6 -\&{while} $\|q>\\{void}$ \1\&{do}\6 -\&{begin} \37$\\{print\_weight}(\|q,\39\\{x\_off})$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -$\\{print}(\.{"\ |"})$;\6 -\&{while} $\|r\I\\{sentinel}$ \1\&{do}\6 -\&{begin} \37$\\{print\_weight}(\|r,\39\\{x\_off})$;\5 -$\|r\K\\{link}(\|r)$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\|p\K\\{knil}(\|p)$;\5 -$\\{decr}(\|n)$;\6 -\&{end};\2\6 -$\\{end\_diagnostic}(\\{true})$;\6 -\&{end};\par -\fi - -\M333. \P$\X333:Declare the procedure called \\{print\_weight}\X\S$\6 -\4\&{procedure}\1\ \37$\\{print\_weight}(\|q:\\{pointer};\,\35\\{x\_off}:% -\\{integer})$;\6 -\4\&{var} \37$\|w,\39\|m$: \37\\{integer};\C{unpacked weight and coordinate}\6 -\|d: \37\\{integer};\C{temporary data register}\2\6 -\&{begin} \37$\|d\K\\{ho}(\\{info}(\|q))$;\5 -$\|w\K\|d\mathbin{\&{mod}}8$;\5 -$\|m\K(\|d\mathbin{\&{div}}8)-\\{m\_offset}(\\{cur\_edges})$;\6 -\&{if} $\\{file\_offset}>\\{max\_print\_line}-9$ \1\&{then}\5 -$\\{print\_nl}(\.{"\ "})$\6 -\4\&{else} $\\{print\_char}(\.{"\ "})$;\2\6 -$\\{print\_int}(\|m+\\{x\_off})$;\6 -\&{while} $\|w>\\{zero\_w}$ \1\&{do}\6 -\&{begin} \37$\\{print\_char}(\.{"+"})$;\5 -$\\{decr}(\|w)$;\6 -\&{end};\2\6 -\&{while} $\|w<\\{zero\_w}$ \1\&{do}\6 -\&{begin} \37$\\{print\_char}(\.{"-"})$;\5 -$\\{incr}(\|w)$;\6 -\&{end};\2\6 -\&{end};\par -\U332.\fi - -\M334. Here's a trivial subroutine that copies an edge structure. (Let's hope -that the given structure isn't too gigantic.) - -\Y\P\4\&{function}\1\ \37$\\{copy\_edges}(\|h:\\{pointer})$: \37\\{pointer};\6 -\4\&{var} \37$\|p,\39\|r$: \37\\{pointer};\C{variables that traverse the given -structure}\6 -$\\{hh},\39\\{pp},\39\\{qq},\39\\{rr},\39\\{ss}$: \37\\{pointer};\C{variables -that traverse the new structure}\2\6 -\&{begin} \37$\\{hh}\K\\{get\_node}(\\{edge\_header\_size})$;\5 -$\\{mem}[\\{hh}+1]\K\\{mem}[\|h+1]$;\5 -$\\{mem}[\\{hh}+2]\K\\{mem}[\|h+2]$;\5 -$\\{mem}[\\{hh}+3]\K\\{mem}[\|h+3]$;\5 -$\\{mem}[\\{hh}+4]\K\\{mem}[\|h+4]$;\C{we've now copied \\{n\_min}, \\{n\_max}, - \\{m\_min}, \\{m\_max}, \\{m\_offset}, \\{last\_window}, and \\{last\_window% -\_time}}\6 -$\\{n\_pos}(\\{hh})\K\\{n\_max}(\\{hh})+1$;\5 -$\\{n\_rover}(\\{hh})\K\\{hh}$;\6 -$\|p\K\\{link}(\|h)$;\5 -$\\{qq}\K\\{hh}$;\6 -\&{while} $\|p\I\|h$ \1\&{do}\6 -\&{begin} \37$\\{pp}\K\\{get\_node}(\\{row\_node\_size})$;\5 -$\\{link}(\\{qq})\K\\{pp}$;\5 -$\\{knil}(\\{pp})\K\\{qq}$;\5 -\X335:Copy both \\{sorted} and \\{unsorted} lists of \|p to \\{pp}\X;\6 -$\|p\K\\{link}(\|p)$;\5 -$\\{qq}\K\\{pp}$;\6 -\&{end};\2\6 -$\\{link}(\\{qq})\K\\{hh}$;\5 -$\\{knil}(\\{hh})\K\\{qq}$;\5 -$\\{copy\_edges}\K\\{hh}$;\6 -\&{end};\par -\fi - -\M335. \P$\X335:Copy both \\{sorted} and \\{unsorted} lists of \|p to \\{pp}\X% -\S$\6 -$\|r\K\\{sorted}(\|p)$;\5 -$\\{rr}\K\\{sorted\_loc}(\\{pp})$;\C{$\\{link}(\\{rr})=\\{sorted}(\\{pp})$}\6 -\&{while} $\|r\I\\{sentinel}$ \1\&{do}\6 -\&{begin} \37$\\{ss}\K\\{get\_avail}$;\5 -$\\{link}(\\{rr})\K\\{ss}$;\5 -$\\{rr}\K\\{ss}$;\5 -$\\{info}(\\{rr})\K\\{info}(\|r)$;\6 -$\|r\K\\{link}(\|r)$;\6 -\&{end};\2\6 -$\\{link}(\\{rr})\K\\{sentinel}$;\6 -$\|r\K\\{unsorted}(\|p)$;\5 -$\\{rr}\K\\{temp\_head}$;\6 -\&{while} $\|r>\\{void}$ \1\&{do}\6 -\&{begin} \37$\\{ss}\K\\{get\_avail}$;\5 -$\\{link}(\\{rr})\K\\{ss}$;\5 -$\\{rr}\K\\{ss}$;\5 -$\\{info}(\\{rr})\K\\{info}(\|r)$;\6 -$\|r\K\\{link}(\|r)$;\6 -\&{end};\2\6 -$\\{link}(\\{rr})\K\|r$;\5 -$\\{unsorted}(\\{pp})\K\\{link}(\\{temp\_head})$\par -\Us334\ET341.\fi - -\M336. Another trivial routine flips \\{cur\_edges} about the \|x-axis -(i.e., negates all the \|y coordinates), assuming that at least -one row is present. - -\Y\P\4\&{procedure}\1\ \37\\{y\_reflect\_edges};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{list manipulation -registers}\2\6 -\&{begin} \37$\|p\K\\{n\_min}(\\{cur\_edges})$;\5 -$\\{n\_min}(\\{cur\_edges})\K\\{zero\_field}+\\{zero\_field}-1-\\{n\_max}(% -\\{cur\_edges})$;\5 -$\\{n\_max}(\\{cur\_edges})\K\\{zero\_field}+\\{zero\_field}-1-\|p$;\5 -$\\{n\_pos}(\\{cur\_edges})\K\\{zero\_field}+\\{zero\_field}-1-\\{n\_pos}(% -\\{cur\_edges})$;\6 -$\|p\K\\{link}(\\{cur\_edges})$;\5 -$\|q\K\\{cur\_edges}$;\C{we assume that $\|p\I\|q$}\6 -\1\&{repeat} \37$\|r\K\\{link}(\|p)$;\5 -$\\{link}(\|p)\K\|q$;\5 -$\\{knil}(\|q)\K\|p$;\5 -$\|q\K\|p$;\5 -$\|p\K\|r$;\6 -\4\&{until}\5 -$\|q=\\{cur\_edges}$;\2\6 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\par -\fi - -\M337. It's somewhat more difficult, yet not too hard, to reflect about the % -\|y-axis. - -\Y\P\4\&{procedure}\1\ \37\\{x\_reflect\_edges};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{list manipulation -registers}\6 -\|m: \37\\{integer};\C{\\{info} fields will be reflected with respect to this -number}\2\6 -\&{begin} \37$\|p\K\\{m\_min}(\\{cur\_edges})$;\5 -$\\{m\_min}(\\{cur\_edges})\K\\{zero\_field}+\\{zero\_field}-\\{m\_max}(\\{cur% -\_edges})$;\5 -$\\{m\_max}(\\{cur\_edges})\K\\{zero\_field}+\\{zero\_field}-\|p$;\5 -$\|m\K(\\{zero\_field}+\\{m\_offset}(\\{cur\_edges}))\ast8+\\{zero\_w}+\\{min% -\_halfword}+\\{zero\_w}+\\{min\_halfword}$;\5 -$\\{m\_offset}(\\{cur\_edges})\K\\{zero\_field}$;\5 -$\|p\K\\{link}(\\{cur\_edges})$;\6 -\1\&{repeat} \37\X339:Reflect the edge-and-weight data in $\\{sorted}(\|p)$\X;\6 -\X338:Reflect the edge-and-weight data in $\\{unsorted}(\|p)$\X;\6 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\|p=\\{cur\_edges}$;\2\6 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\par -\fi - -\M338. We want to change the sign of the weight as we change the sign of the -\|x~coordinate. Fortunately, it's easier to do this than to negate -one without the other. - -\Y\P$\4\X338:Reflect the edge-and-weight data in $\\{unsorted}(\|p)$\X\S$\6 -$\|q\K\\{unsorted}(\|p)$;\6 -\&{while} $\|q>\\{void}$ \1\&{do}\6 -\&{begin} \37$\\{info}(\|q)\K\|m-\\{info}(\|q)$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end}\2\par -\U337.\fi - -\M339. Reversing the order of a linked list is best thought of as the process -of -popping nodes off one stack and pushing them on another. In this case we -pop from stack~\|q and push to stack~\|r. - -\Y\P$\4\X339:Reflect the edge-and-weight data in $\\{sorted}(\|p)$\X\S$\6 -$\|q\K\\{sorted}(\|p)$;\5 -$\|r\K\\{sentinel}$;\6 -\&{while} $\|q\I\\{sentinel}$ \1\&{do}\6 -\&{begin} \37$\|s\K\\{link}(\|q)$;\5 -$\\{link}(\|q)\K\|r$;\5 -$\|r\K\|q$;\5 -$\\{info}(\|r)\K\|m-\\{info}(\|q)$;\5 -$\|q\K\|s$;\6 -\&{end};\2\6 -$\\{sorted}(\|p)\K\|r$\par -\U337.\fi - -\M340. Now let's multiply all the $y$~coordinates of a nonempty edge structure -by a small integer $s>1$: - -\Y\P\4\&{procedure}\1\ \37$\\{y\_scale\_edges}(\|s:\\{integer})$;\6 -\4\&{var} \37$\|p,\39\|q,\39\\{pp},\39\|r,\39\\{rr},\39\\{ss}$: \37\\{pointer};% -\C{list manipulation registers}\6 -\|t: \37\\{integer};\C{replication counter}\2\6 -\&{begin} \37\&{if} $(\|s\ast(\\{n\_max}(\\{cur\_edges})+1-\\{zero\_field})% -\G4096)\V\30(\|s\ast(\\{n\_min}(\\{cur\_edges})-\\{zero\_field})\L-4096)$ \1% -\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Scaled\ picture\ would\ be\ too\ big"})$;\5 -$\\{help3}(\.{"I\ can\'t\ yscale\ the\ picture\ as\ requested---it\ would"})$\6 -$(\.{"make\ some\ coordinates\ too\ large\ or\ too\ small."})$\6 -$(\.{"Proceed,\ and\ I\'ll\ omit\ the\ transformation."})$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{n\_max}(\\{cur\_edges})\K\|s\ast(\\{n\_max}(\\{cur% -\_edges})+1-\\{zero\_field})-1+\\{zero\_field}$;\5 -$\\{n\_min}(\\{cur\_edges})\K\|s\ast(\\{n\_min}(\\{cur\_edges})-\\{zero% -\_field})+\\{zero\_field}$;\5 -\X341:Replicate every row exactly $s$ times\X;\6 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M341. \P$\X341:Replicate every row exactly $s$ times\X\S$\6 -$\|p\K\\{cur\_edges}$;\6 -\1\&{repeat} \37$\|q\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{for} $\|t\K2\mathrel{\&{to}}\|s$ \1\&{do}\6 -\&{begin} \37$\\{pp}\K\\{get\_node}(\\{row\_node\_size})$;\5 -$\\{link}(\|q)\K\\{pp}$;\5 -$\\{knil}(\|p)\K\\{pp}$;\5 -$\\{link}(\\{pp})\K\|p$;\5 -$\\{knil}(\\{pp})\K\|q$;\5 -$\|q\K\\{pp}$;\5 -\X335:Copy both \\{sorted} and \\{unsorted} lists of \|p to \\{pp}\X;\6 -\&{end};\2\6 -\4\&{until}\5 -$\\{link}(\|p)=\\{cur\_edges}$\2\par -\U340.\fi - -\M342. Scaling the $x$~coordinates is, of course, our next task. - -\Y\P\4\&{procedure}\1\ \37$\\{x\_scale\_edges}(\|s:\\{integer})$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{list manipulation registers}\6 -\|t: \37$0\to65535$;\C{unpacked \\{info} field}\6 -\|w: \37$0\to7$;\C{unpacked weight}\6 -\\{delta}: \37\\{integer};\C{amount added to scaled \\{info}}\2\6 -\&{begin} \37\&{if} $(\|s\ast(\\{m\_max}(\\{cur\_edges})-\\{zero\_field})% -\G4096)\V\30(\|s\ast(\\{m\_min}(\\{cur\_edges})-\\{zero\_field})\L-4096)$ \1% -\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Scaled\ picture\ would\ be\ too\ big"})$;\5 -$\\{help3}(\.{"I\ can\'t\ xscale\ the\ picture\ as\ requested---it\ would"})$\6 -$(\.{"make\ some\ coordinates\ too\ large\ or\ too\ small."})$\6 -$(\.{"Proceed,\ and\ I\'ll\ omit\ the\ transformation."})$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} \&{if} $(\\{m\_max}(\\{cur\_edges})\I\\{zero\_field})\V(\\{m\_min}(% -\\{cur\_edges})\I\\{zero\_field})$ \1\&{then}\6 -\&{begin} \37$\\{m\_max}(\\{cur\_edges})\K\|s\ast(\\{m\_max}(\\{cur\_edges})-% -\\{zero\_field})+\\{zero\_field}$;\5 -$\\{m\_min}(\\{cur\_edges})\K\|s\ast(\\{m\_min}(\\{cur\_edges})-\\{zero% -\_field})+\\{zero\_field}$;\5 -$\\{delta}\K8\ast(\\{zero\_field}-\|s\ast\\{m\_offset}(\\{cur\_edges}))+\\{min% -\_halfword}$;\5 -$\\{m\_offset}(\\{cur\_edges})\K\\{zero\_field}$;\6 -\X343:Scale the $x$~coordinates of each row by $s$\X;\6 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M343. The multiplications cannot overflow because we know that $\|s<4096$. - -\Y\P$\4\X343:Scale the $x$~coordinates of each row by $s$\X\S$\6 -$\|q\K\\{link}(\\{cur\_edges})$;\6 -\1\&{repeat} \37$\|p\K\\{sorted}(\|q)$;\6 -\&{while} $\|p\I\\{sentinel}$ \1\&{do}\6 -\&{begin} \37$\|t\K\\{ho}(\\{info}(\|p))$;\5 -$\|w\K\|t\mathbin{\&{mod}}8$;\5 -$\\{info}(\|p)\K(\|t-\|w)\ast\|s+\|w+\\{delta}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\|p\K\\{unsorted}(\|q)$;\6 -\&{while} $\|p>\\{void}$ \1\&{do}\6 -\&{begin} \37$\|t\K\\{ho}(\\{info}(\|p))$;\5 -$\|w\K\|t\mathbin{\&{mod}}8$;\5 -$\\{info}(\|p)\K(\|t-\|w)\ast\|s+\|w+\\{delta}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\|q=\\{cur\_edges}$\2\par -\U342.\fi - -\M344. Here is a routine that changes the signs of all the weights, without -changing anything else. - -\Y\P\4\&{procedure}\1\ \37$\\{negate\_edges}(\|h:\\{pointer})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s,\39\|t,\39\|u$: \37\\{pointer};% -\C{structure traversers}\2\6 -\&{begin} \37$\|p\K\\{link}(\|h)$;\6 -\&{while} $\|p\I\|h$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{unsorted}(\|p)$;\6 -\&{while} $\|q>\\{void}$ \1\&{do}\6 -\&{begin} \37$\\{info}(\|q)\K8-2\ast((\\{ho}(\\{info}(\|q)))\mathbin{% -\&{mod}}8)+\\{info}(\|q)$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -$\|q\K\\{sorted}(\|p)$;\6 -\&{if} $\|q\I\\{sentinel}$ \1\&{then}\6 -\&{begin} \37\1\&{repeat} \37$\\{info}(\|q)\K8-2\ast((\\{ho}(\\{info}(\|q)))% -\mathbin{\&{mod}}8)+\\{info}(\|q)$;\5 -$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\|q=\\{sentinel}$;\2\6 -\X345:Put the list $\\{sorted}(\|p)$ back into sort\X;\6 -\&{end};\2\6 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\\{last\_window\_time}(\|h)\K0$;\6 -\&{end};\par -\fi - -\M345. \MF\ would work even if the code in this section were omitted, because -a list of edge-and-weight data that is sorted only by -\|m but not~\|w turns out to be good enough for correct operation. -However, the author decided not to make the program even trickier than -it is already, since \\{negate\_edges} isn't needed very often. -The simpler-to-state condition, ``keep the \\{sorted} list fully sorted,'' -is therefore being preserved at the cost of extra computation. - -\Y\P$\4\X345:Put the list $\\{sorted}(\|p)$ back into sort\X\S$\6 -$\|u\K\\{sorted\_loc}(\|p)$;\5 -$\|q\K\\{link}(\|u)$;\5 -$\|r\K\|q$;\5 -$\|s\K\\{link}(\|r)$;\C{$\|q=\\{sorted}(\|p)$}\6 -\~ \1\&{loop}\ \&{if} $\\{info}(\|s)>\\{info}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|u)\K\|q$;\6 -\&{if} $\|s=\\{sentinel}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|u\K\|r$;\5 -$\|q\K\|s$;\5 -$\|r\K\|q$;\5 -$\|s\K\\{link}(\|r)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|t\K\|s$;\5 -$\|s\K\\{link}(\|t)$;\5 -$\\{link}(\|t)\K\|q$;\5 -$\|q\K\|t$;\6 -\&{end};\2\2\6 -\4\\{done}: \37$\\{link}(\|r)\K\\{sentinel}$\par -\U344.\fi - -\M346. The \\{unsorted} edges of a row are merged into the \\{sorted} ones by -a subroutine called \\{sort\_edges}. It uses simple insertion sort, -followed by a merge, because the unsorted list is supposedly quite short. -However, the unsorted list is assumed to be nonempty. - -\Y\P\4\&{procedure}\1\ \37$\\{sort\_edges}(\|h:\\{pointer})$;\C{\|h is a row -header}\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|k: \37\\{halfword};\C{key register that we compare to $\\{info}(% -\|q)$}\6 -$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\2\6 -\&{begin} \37$\|r\K\\{unsorted}(\|h)$;\5 -$\\{unsorted}(\|h)\K\\{null}$;\5 -$\|p\K\\{link}(\|r)$;\5 -$\\{link}(\|r)\K\\{sentinel}$;\5 -$\\{link}(\\{temp\_head})\K\|r$;\6 -\&{while} $\|p>\\{void}$ \1\&{do}\C{sort node \|p into the list that starts at % -\\{temp\_head}}\6 -\&{begin} \37$\|k\K\\{info}(\|p)$;\5 -$\|q\K\\{temp\_head}$;\6 -\1\&{repeat} \37$\|r\K\|q$;\5 -$\|q\K\\{link}(\|r)$;\6 -\4\&{until}\5 -$\|k\L\\{info}(\|q)$;\2\6 -$\\{link}(\|r)\K\|p$;\5 -$\|r\K\\{link}(\|p)$;\5 -$\\{link}(\|p)\K\|q$;\5 -$\|p\K\|r$;\6 -\&{end};\2\6 -\X347:Merge the \\{temp\_head} list into $\\{sorted}(\|h)$\X;\6 -\&{end};\par -\fi - -\M347. In this step we use the fact that $\\{sorted}(\|h)=\\{link}(\\{sorted% -\_loc}(\|h))$. - -\Y\P$\4\X347:Merge the \\{temp\_head} list into $\\{sorted}(\|h)$\X\S$\6 -\&{begin} \37$\|r\K\\{sorted\_loc}(\|h)$;\5 -$\|q\K\\{link}(\|r)$;\5 -$\|p\K\\{link}(\\{temp\_head})$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|k\K\\{info}(\|p)$;\6 -\&{while} $\|k>\\{info}(\|q)$ \1\&{do}\6 -\&{begin} \37$\|r\K\|q$;\5 -$\|q\K\\{link}(\|r)$;\6 -\&{end};\2\6 -$\\{link}(\|r)\K\|p$;\5 -$\|s\K\\{link}(\|p)$;\5 -$\\{link}(\|p)\K\|q$;\6 -\&{if} $\|s=\\{sentinel}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|r\K\|p$;\5 -$\|p\K\|s$;\6 -\&{end};\2\6 -\4\\{done}: \37\&{end}\par -\U346.\fi - -\M348. The \\{cull\_edges} procedure ``optimizes'' an edge structure by making -all -the pixel weights either \\{w\_out} or~\\{w\_in}. The weight will be~\\{w\_in} -after the -operation if and only if it was in the closed interval $[\\{w\_lo},\\{w\_hi}]$ -before, where $\\{w\_lo}\L\\{w\_hi}$. Either \\{w\_out} or \\{w\_in} is zero, -while the other is -$\pm1$, $\pm2$, or $\pm3$. The parameters will be such that zero-weight -pixels will remain of weight zero. (This is fortunate, -because there are infinitely many of them.) - -The procedure also computes the tightest possible bounds on the resulting -data, by updating \\{m\_min}, \\{m\_max}, \\{n\_min}, and~\\{n\_max}. - -\Y\P\4\&{procedure}\1\ \37$\\{cull\_edges}(\\{w\_lo},\39\\{w\_hi},\39\\{w% -\_out},\39\\{w\_in}:\\{integer})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{for list -manipulation}\6 -\|w: \37\\{integer};\C{new weight after culling}\6 -\|d: \37\\{integer};\C{data register for unpacking}\6 -\|m: \37\\{integer};\C{the previous column number, including \\{m\_offset}}\6 -\\{mm}: \37\\{integer};\C{the next column number, including \\{m\_offset}}\6 -\\{ww}: \37\\{integer};\C{accumulated weight before culling}\6 -\\{prev\_w}: \37\\{integer};\C{value of \|w before column \|m}\6 -$\|n,\39\\{min\_n},\39\\{max\_n}$: \37\\{pointer};\C{current and extreme row -numbers}\6 -$\\{min\_d},\39\\{max\_d}$: \37\\{pointer};\C{extremes of the new -edge-and-weight data}\2\6 -\&{begin} \37$\\{min\_d}\K\\{max\_halfword}$;\5 -$\\{max\_d}\K\\{min\_halfword}$;\5 -$\\{min\_n}\K\\{max\_halfword}$;\5 -$\\{max\_n}\K\\{min\_halfword}$;\6 -$\|p\K\\{link}(\\{cur\_edges})$;\5 -$\|n\K\\{n\_min}(\\{cur\_edges})$;\6 -\&{while} $\|p\I\\{cur\_edges}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{unsorted}(\|p)>\\{void}$ \1\&{then}\5 -$\\{sort\_edges}(\|p)$;\2\6 -\&{if} $\\{sorted}(\|p)\I\\{sentinel}$ \1\&{then}\5 -\X349:Cull superfluous edge-weight entries from $\\{sorted}(\|p)$\X;\2\6 -$\|p\K\\{link}(\|p)$;\5 -$\\{incr}(\|n)$;\6 -\&{end};\2\6 -\X352:Delete empty rows at the top and/or bottom; update the boundary values in -the header\X;\6 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\par -\fi - -\M349. The entire \\{sorted} list is returned to available memory in this step; -a new list is built starting (temporarily) at \\{temp\_head}. -Since several edges can occur at the same column, we need to be looking -ahead of where the actual culling takes place. This means that it's -slightly tricky to get the iteration started and stopped. - -\Y\P$\4\X349:Cull superfluous edge-weight entries from $\\{sorted}(\|p)$\X\S$\6 -\&{begin} \37$\|r\K\\{temp\_head}$;\5 -$\|q\K\\{sorted}(\|p)$;\5 -$\\{ww}\K0$;\5 -$\|m\K1000000$;\5 -$\\{prev\_w}\K0$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|q=\\{sentinel}$ \1\&{then}\5 -$\\{mm}\K1000000$\6 -\4\&{else} \&{begin} \37$\|d\K\\{ho}(\\{info}(\|q))$;\5 -$\\{mm}\K\|d\mathbin{\&{div}}8$;\5 -$\\{ww}\K\\{ww}+(\|d\mathbin{\&{mod}}8)-\\{zero\_w}$;\6 -\&{end};\2\6 -\&{if} $\\{mm}>\|m$ \1\&{then}\6 -\&{begin} \37\X350:Insert an edge-weight for edge \|m, if the new pixel weight -has changed\X;\6 -\&{if} $\|q=\\{sentinel}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{end};\2\6 -$\|m\K\\{mm}$;\6 -\&{if} $\\{ww}\G\\{w\_lo}$ \1\&{then}\6 -\&{if} $\\{ww}\L\\{w\_hi}$ \1\&{then}\5 -$\|w\K\\{w\_in}$\6 -\4\&{else} $\|w\K\\{w\_out}$\2\6 -\4\&{else} $\|w\K\\{w\_out}$;\2\6 -$\|s\K\\{link}(\|q)$;\5 -$\\{free\_avail}(\|q)$;\5 -$\|q\K\|s$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{link}(\|r)\K\\{sentinel}$;\5 -$\\{sorted}(\|p)\K\\{link}(\\{temp\_head})$;\6 -\&{if} $\|r\I\\{temp\_head}$ \1\&{then}\5 -\X351:Update the max/min amounts\X;\2\6 -\&{end}\par -\U348.\fi - -\M350. \P$\X350:Insert an edge-weight for edge \|m, if the new pixel weight has -changed\X\S$\6 -\&{if} $\|w\I\\{prev\_w}$ \1\&{then}\6 -\&{begin} \37$\|s\K\\{get\_avail}$;\5 -$\\{link}(\|r)\K\|s$;\5 -$\\{info}(\|s)\K8\ast\|m+\\{min\_halfword}+\\{zero\_w}+\|w-\\{prev\_w}$;\5 -$\|r\K\|s$;\5 -$\\{prev\_w}\K\|w$;\6 -\&{end}\2\par -\U349.\fi - -\M351. \P$\X351:Update the max/min amounts\X\S$\6 -\&{begin} \37\&{if} $\\{min\_n}=\\{max\_halfword}$ \1\&{then}\5 -$\\{min\_n}\K\|n$;\2\6 -$\\{max\_n}\K\|n$;\6 -\&{if} $\\{min\_d}>\\{info}(\\{link}(\\{temp\_head}))$ \1\&{then}\5 -$\\{min\_d}\K\\{info}(\\{link}(\\{temp\_head}))$;\2\6 -\&{if} $\\{max\_d}<\\{info}(\|r)$ \1\&{then}\5 -$\\{max\_d}\K\\{info}(\|r)$;\2\6 -\&{end}\par -\U349.\fi - -\M352. \P$\X352:Delete empty rows at the top and/or bottom; update the boundary -values in the header\X\S$\6 -\&{if} $\\{min\_n}>\\{max\_n}$ \1\&{then}\5 -\X353:Delete all the row headers\X\6 -\4\&{else} \&{begin} \37$\|n\K\\{n\_min}(\\{cur\_edges})$;\5 -$\\{n\_min}(\\{cur\_edges})\K\\{min\_n}$;\6 -\&{while} $\\{min\_n}>\|n$ \1\&{do}\6 -\&{begin} \37$\|p\K\\{link}(\\{cur\_edges})$;\5 -$\\{link}(\\{cur\_edges})\K\\{link}(\|p)$;\5 -$\\{knil}(\\{link}(\|p))\K\\{cur\_edges}$;\5 -$\\{free\_node}(\|p,\39\\{row\_node\_size})$;\5 -$\\{incr}(\|n)$;\6 -\&{end};\2\6 -$\|n\K\\{n\_max}(\\{cur\_edges})$;\5 -$\\{n\_max}(\\{cur\_edges})\K\\{max\_n}$;\5 -$\\{n\_pos}(\\{cur\_edges})\K\\{max\_n}+1$;\5 -$\\{n\_rover}(\\{cur\_edges})\K\\{cur\_edges}$;\6 -\&{while} $\\{max\_n}<\|n$ \1\&{do}\6 -\&{begin} \37$\|p\K\\{knil}(\\{cur\_edges})$;\5 -$\\{knil}(\\{cur\_edges})\K\\{knil}(\|p)$;\5 -$\\{link}(\\{knil}(\|p))\K\\{cur\_edges}$;\5 -$\\{free\_node}(\|p,\39\\{row\_node\_size})$;\5 -$\\{decr}(\|n)$;\6 -\&{end};\2\6 -$\\{m\_min}(\\{cur\_edges})\K((\\{ho}(\\{min\_d}))\mathbin{\&{div}}8)-\\{m% -\_offset}(\\{cur\_edges})+\\{zero\_field}$;\5 -$\\{m\_max}(\\{cur\_edges})\K((\\{ho}(\\{max\_d}))\mathbin{\&{div}}8)-\\{m% -\_offset}(\\{cur\_edges})+\\{zero\_field}$;\6 -\&{end}\2\par -\U348.\fi - -\M353. We get here if the edges have been entirely culled away. - -\Y\P$\4\X353:Delete all the row headers\X\S$\6 -\&{begin} \37$\|p\K\\{link}(\\{cur\_edges})$;\6 -\&{while} $\|p\I\\{cur\_edges}$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{row\_node\_size})$;\5 -$\|p\K\|q$;\6 -\&{end};\2\6 -$\\{init\_edges}(\\{cur\_edges})$;\6 -\&{end}\par -\U352.\fi - -\M354. The last and most difficult routine for transforming an edge -structure---and -the most interesting one!---is \\{xy\_swap\_edges}, which interchanges the -r\^^Doles of rows and columns. Its task can be viewed as the job of -creating an edge structure that contains only horizontal edges, linked -together in columns, given an edge structure that contains only -vertical edges linked together in rows; we must do this without changing -the implied pixel weights. - -Given any two adjacent rows of an edge structure, it is not difficult to -determine the horizontal edges that lie ``between'' them: We simply look -for vertically adjacent pixels that have different weight, and insert -a horizontal edge containing the difference in weights. Every horizontal -edge determined in this way should be put into an appropriate linked -list. Since random access to these linked lists is desirable, we use -the \\{move} array to hold the list heads. If we work through the given -edge structure from top to bottom, the constructed lists will not need -to be sorted, since they will already be in order. - -The following algorithm makes use of some ideas suggested by John Hobby. -It assumes that the edge structure is non-null, i.e., that $\\{link}(\\{cur% -\_edges})\I\\{cur\_edges}$, hence $\\{m\_max}(\\{cur\_edges})\G\\{m\_min}(% -\\{cur\_edges})$. - -\Y\P\4\&{procedure}\1\ \37\\{xy\_swap\_edges};\C{interchange \|x and \|y in % -\\{cur\_edges}}\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\\{m\_magic},\39\\{n\_magic}$: \37\\{integer};\C{special values -that account for offsets}\6 -$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{pointers that traverse the given -structure}\6 -\X357:Other local variables for \\{xy\_swap\_edges}\X\2\6 -\&{begin} \37\X356:Initialize the array of new edge list heads\X;\6 -\X355:Insert blank rows at the top and bottom, and set \|p to the new top row% -\X;\6 -\X365:Compute the magic offset values\X;\6 -\1\&{repeat} \37$\|q\K\\{knil}(\|p)$;\ \&{if} $\\{unsorted}(\|q)>\\{void}$ \1% -\&{then}\5 -$\\{sort\_edges}(\|q)$;\2\6 -\X358:Insert the horizontal edges defined by adjacent rows $\|p,\|q$, and -destroy row~\|p\X;\6 -$\|p\K\|q$;\5 -$\\{n\_magic}\K\\{n\_magic}-8$;\6 -\4\&{until}\5 -$\\{knil}(\|p)=\\{cur\_edges}$;\2\6 -$\\{free\_node}(\|p,\39\\{row\_node\_size})$;\C{now all original rows have been -recycled}\6 -\X364:Adjust the header to reflect the new edges\X;\6 -\&{end};\par -\fi - -\M355. Here we don't bother to keep the \\{link} entries up to date, since the -procedure looks only at the \\{knil} fields as it destroys the former -edge structure. - -\Y\P$\4\X355:Insert blank rows at the top and bottom, and set \|p to the new -top row\X\S$\6 -$\|p\K\\{get\_node}(\\{row\_node\_size})$;\5 -$\\{sorted}(\|p)\K\\{sentinel}$;\5 -$\\{unsorted}(\|p)\K\\{null}$;\6 -$\\{knil}(\|p)\K\\{cur\_edges}$;\5 -$\\{knil}(\\{link}(\\{cur\_edges}))\K\|p$;\C{the new bottom row}\6 -$\|p\K\\{get\_node}(\\{row\_node\_size})$;\5 -$\\{sorted}(\|p)\K\\{sentinel}$;\5 -$\\{knil}(\|p)\K\\{knil}(\\{cur\_edges})$;\C{the new top row}\par -\U354.\fi - -\M356. The new lists will become \\{sorted} lists later, so we initialize -empty lists to \\{sentinel}. - -\Y\P$\4\X356:Initialize the array of new edge list heads\X\S$\6 -$\\{m\_spread}\K\\{m\_max}(\\{cur\_edges})-\\{m\_min}(\\{cur\_edges})$;\C{this -is $\G0$ by assumption}\6 -\&{if} $\\{m\_spread}>\\{move\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"move\ table\ size"},\39\\{move\_size})$;\2\6 -\&{for} $\|j\K0\mathrel{\&{to}}\\{m\_spread}$ \1\&{do}\5 -$\\{move}[\|j]\K\\{sentinel}$\2\par -\U354.\fi - -\M357. \P$\X357:Other local variables for \\{xy\_swap\_edges}\X\S$\6 -\4\\{m\_spread}: \37\\{integer};\C{the difference between \\{m\_max} and \\{m% -\_min}}\6 -\4$\|j,\39\\{jj}$: \37$0\to\\{move\_size}$;\C{indices into \\{move}}\6 -\4$\|m,\39\\{mm}$: \37\\{integer};\C{\|m values at vertical edges}\6 -\4$\\{pd},\39\\{rd}$: \37\\{integer};\C{data fields from edge-and-weight nodes}% -\6 -\4$\\{pm},\39\\{rm}$: \37\\{integer};\C{\|m values from edge-and-weight nodes}\6 -\4\|w: \37\\{integer};\C{the difference in accumulated weight}\6 -\4\\{ww}: \37\\{integer};\C{as much of \|w that can be stored in a single node}% -\6 -\4\\{dw}: \37\\{integer};\C{an increment to be added to \|w}\par -\A363. -\U354.\fi - -\M358. At the point where we test $\|w\I0$, variable \|w contains -the accumulated weight from edges already passed in -row~\|p minus the accumulated weight from edges already passed in row~\|q. - -\Y\P$\4\X358:Insert the horizontal edges defined by adjacent rows $\|p,\|q$, -and destroy row~\|p\X\S$\6 -$\|r\K\\{sorted}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{row\_node\_size})$;\5 -$\|p\K\|r$;\6 -$\\{pd}\K\\{ho}(\\{info}(\|p))$;\5 -$\\{pm}\K\\{pd}\mathbin{\&{div}}8$;\6 -$\|r\K\\{sorted}(\|q)$;\5 -$\\{rd}\K\\{ho}(\\{info}(\|r))$;\5 -$\\{rm}\K\\{rd}\mathbin{\&{div}}8$;\5 -$\|w\K0$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\\{pm}<\\{rm}$ \1\&{then}\5 -$\\{mm}\K\\{pm}$\ \&{else} $\\{mm}\K\\{rm}$;\2\6 -\&{if} $\|w\I0$ \1\&{then}\5 -\X362:Insert horizontal edges of weight \|w between \|m and~\\{mm}\X;\2\6 -\&{if} $\\{pd}<\\{rd}$ \1\&{then}\6 -\&{begin} \37$\\{dw}\K(\\{pd}\mathbin{\&{mod}}8)-\\{zero\_w}$;\5 -\X360:Advance pointer \|p to the next vertical edge, after destroying the -previous one\X;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\|r=\\{sentinel}$ \1\&{then}\5 -\&{goto} \37\\{done};\C{$\\{rd}=\\{pd}=\\{ho}(\\{max\_halfword})$}\2\6 -$\\{dw}\K-((\\{rd}\mathbin{\&{mod}}8)-\\{zero\_w})$;\5 -\X359:Advance pointer \|r to the next vertical edge\X;\6 -\&{end};\2\6 -$\|m\K\\{mm}$;\5 -$\|w\K\|w+\\{dw}$;\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U354.\fi - -\M359. \P$\X359:Advance pointer \|r to the next vertical edge\X\S$\6 -$\|r\K\\{link}(\|r)$;\5 -$\\{rd}\K\\{ho}(\\{info}(\|r))$;\5 -$\\{rm}\K\\{rd}\mathbin{\&{div}}8$\par -\U358.\fi - -\M360. \P$\X360:Advance pointer \|p to the next vertical edge, after destroying -the previous one\X\S$\6 -$\|s\K\\{link}(\|p)$;\5 -$\\{free\_avail}(\|p)$;\5 -$\|p\K\|s$;\5 -$\\{pd}\K\\{ho}(\\{info}(\|p))$;\5 -$\\{pm}\K\\{pd}\mathbin{\&{div}}8$\par -\U358.\fi - -\M361. Certain ``magic'' values are needed to make the following code work, -because of the various offsets in our data structure. For now, let's not -worry about their precise values; we shall compute \\{m\_magic} and \\{n% -\_magic} -later, after we see what the code looks like. - -\fi - -\M362. \P$\X362:Insert horizontal edges of weight \|w between \|m and~\\{mm}\X% -\S$\6 -\&{if} $\|m\I\\{mm}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{mm}-\\{m\_magic}\G\\{move\_size}$ \1\&{then}\5 -$\\{confusion}(\.{"xy"})$;\2\6 -$\\{extras}\K(\\{abs}(\|w)-1)\mathbin{\&{div}}3$;\6 -\&{if} $\\{extras}>0$ \1\&{then}\6 -\&{begin} \37\&{if} $\|w>0$ \1\&{then}\5 -$\\{xw}\K+3$\ \&{else} $\\{xw}\K-3$;\2\6 -$\\{ww}\K\|w-\\{extras}\ast\\{xw}$;\6 -\&{end}\6 -\4\&{else} $\\{ww}\K\|w$;\2\6 -\1\&{repeat} \37$\|j\K\|m-\\{m\_magic}$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}\\{extras}$ \1\&{do}\6 -\&{begin} \37$\|s\K\\{get\_avail}$;\5 -$\\{info}(\|s)\K\\{n\_magic}+\\{xw}$;\5 -$\\{link}(\|s)\K\\{move}[\|j]$;\5 -$\\{move}[\|j]\K\|s$;\6 -\&{end};\2\6 -$\|s\K\\{get\_avail}$;\5 -$\\{info}(\|s)\K\\{n\_magic}+\\{ww}$;\5 -$\\{link}(\|s)\K\\{move}[\|j]$;\5 -$\\{move}[\|j]\K\|s$;\6 -$\\{incr}(\|m)$;\6 -\4\&{until}\5 -$\|m=\\{mm}$;\2\6 -\&{end}\2\par -\U358.\fi - -\M363. \P$\X357:Other local variables for \\{xy\_swap\_edges}\X\mathrel{+}\S$\6 -\4\\{extras}: \37\\{integer};\C{the number of additional nodes to make weights -$>3$}\6 -\4\\{xw}: \37$-3\to3$;\C{the additional weight in extra nodes}\6 -\4\|k: \37\\{integer};\C{loop counter for inserting extra nodes}\par -\fi - -\M364. At the beginning of this step, $\\{move}[\\{m\_spread}]=\\{sentinel}$, -because no -horizontal edges will extend to the right of column $\\{m\_max}(\\{cur% -\_edges})$. - -\Y\P$\4\X364:Adjust the header to reflect the new edges\X\S$\6 -$\\{move}[\\{m\_spread}]\K0$;\5 -$\|j\K0$;\6 -\&{while} $\\{move}[\|j]=\\{sentinel}$ \1\&{do}\5 -$\\{incr}(\|j)$;\2\6 -\&{if} $\|j=\\{m\_spread}$ \1\&{then}\5 -$\\{init\_edges}(\\{cur\_edges})$\C{all edge weights are zero}\6 -\4\&{else} \&{begin} \37$\\{mm}\K\\{m\_min}(\\{cur\_edges})$;\5 -$\\{m\_min}(\\{cur\_edges})\K\\{n\_min}(\\{cur\_edges})$;\5 -$\\{m\_max}(\\{cur\_edges})\K\\{n\_max}(\\{cur\_edges})+1$;\5 -$\\{m\_offset}(\\{cur\_edges})\K\\{zero\_field}$;\5 -$\\{jj}\K\\{m\_spread}-1$;\6 -\&{while} $\\{move}[\\{jj}]=\\{sentinel}$ \1\&{do}\5 -$\\{decr}(\\{jj})$;\2\6 -$\\{n\_min}(\\{cur\_edges})\K\|j+\\{mm}$;\5 -$\\{n\_max}(\\{cur\_edges})\K\\{jj}+\\{mm}$;\5 -$\|q\K\\{cur\_edges}$;\6 -\1\&{repeat} \37$\|p\K\\{get\_node}(\\{row\_node\_size})$;\5 -$\\{link}(\|q)\K\|p$;\5 -$\\{knil}(\|p)\K\|q$;\5 -$\\{sorted}(\|p)\K\\{move}[\|j]$;\5 -$\\{unsorted}(\|p)\K\\{null}$;\5 -$\\{incr}(\|j)$;\5 -$\|q\K\|p$;\6 -\4\&{until}\5 -$\|j>\\{jj}$;\2\6 -$\\{link}(\|q)\K\\{cur\_edges}$;\5 -$\\{knil}(\\{cur\_edges})\K\|q$;\5 -$\\{n\_pos}(\\{cur\_edges})\K\\{n\_max}(\\{cur\_edges})+1$;\5 -$\\{n\_rover}(\\{cur\_edges})\K\\{cur\_edges}$;\5 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\2\par -\U354.\fi - -\M365. The values of \\{m\_magic} and \\{n\_magic} can be worked out by trying -the -code above on a small example; if they work correctly in simple cases, -they should work in general. - -\Y\P$\4\X365:Compute the magic offset values\X\S$\6 -$\\{m\_magic}\K\\{m\_min}(\\{cur\_edges})+\\{m\_offset}(\\{cur\_edges})-\\{zero% -\_field}$;\5 -$\\{n\_magic}\K8\ast\\{n\_max}(\\{cur\_edges})+8+\\{zero\_w}+\\{min\_halfword}$% -\par -\U354.\fi - -\M366. Now let's look at the subroutine that merges the edges from a given -edge structure into \\{cur\_edges}. The given edge structure loses all its -edges. - -\Y\P\4\&{procedure}\1\ \37$\\{merge\_edges}(\|h:\\{pointer})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\\{pp},\39\\{qq},\39\\{rr}$: \37\\{pointer};% -\C{list manipulation registers}\6 -\|n: \37\\{integer};\C{row number}\6 -\|k: \37\\{halfword};\C{key register that we compare to $\\{info}(\|q)$}\6 -\\{delta}: \37\\{integer};\C{change to the edge/weight data}\2\6 -\&{begin} \37\&{if} $\\{link}(\|h)\I\|h$ \1\&{then}\6 -\&{begin} \37\&{if} $(\\{m\_min}(\|h)<\\{m\_min}(\\{cur\_edges}))\V(\\{m\_max}(% -\|h)>\\{m\_max}(\\{cur\_edges}))\V\30(\\{n\_min}(\|h)<\\{n\_min}(\\{cur% -\_edges}))\V(\\{n\_max}(\|h)>\\{n\_max}(\\{cur\_edges}))$ \1\&{then}\5 -$\\{edge\_prep}(\\{m\_min}(\|h)-\\{zero\_field},\39\\{m\_max}(\|h)-\\{zero% -\_field},\39\\{n\_min}(\|h)-\\{zero\_field},\39\\{n\_max}(\|h)-\\{zero% -\_field}+1)$;\2\6 -\&{if} $\\{m\_offset}(\|h)\I\\{m\_offset}(\\{cur\_edges})$ \1\&{then}\5 -\X367:Adjust the data of \|h to account for a difference of offsets\X;\2\6 -$\|n\K\\{n\_min}(\\{cur\_edges})$;\5 -$\|p\K\\{link}(\\{cur\_edges})$;\5 -$\\{pp}\K\\{link}(\|h)$;\6 -\&{while} $\|n<\\{n\_min}(\|h)$ \1\&{do}\6 -\&{begin} \37$\\{incr}(\|n)$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\1\&{repeat} \37\X368:Merge row \\{pp} into row \|p\X;\6 -$\\{pp}\K\\{link}(\\{pp})$;\5 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\\{pp}=\|h$;\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M367. \P$\X367:Adjust the data of \|h to account for a difference of offsets\X% -\S$\6 -\&{begin} \37$\\{pp}\K\\{link}(\|h)$;\5 -$\\{delta}\K8\ast(\\{m\_offset}(\\{cur\_edges})-\\{m\_offset}(\|h))$;\6 -\1\&{repeat} \37$\\{qq}\K\\{sorted}(\\{pp})$;\6 -\&{while} $\\{qq}\I\\{sentinel}$ \1\&{do}\6 -\&{begin} \37$\\{info}(\\{qq})\K\\{info}(\\{qq})+\\{delta}$;\5 -$\\{qq}\K\\{link}(\\{qq})$;\6 -\&{end};\2\6 -$\\{qq}\K\\{unsorted}(\\{pp})$;\6 -\&{while} $\\{qq}>\\{void}$ \1\&{do}\6 -\&{begin} \37$\\{info}(\\{qq})\K\\{info}(\\{qq})+\\{delta}$;\5 -$\\{qq}\K\\{link}(\\{qq})$;\6 -\&{end};\2\6 -$\\{pp}\K\\{link}(\\{pp})$;\6 -\4\&{until}\5 -$\\{pp}=\|h$;\2\6 -\&{end}\par -\U366.\fi - -\M368. The \\{sorted} and \\{unsorted} lists are merged separately. After this -step, row~\\{pp} will have no edges remaining, since they will all have -been merged into row~\|p. - -\Y\P$\4\X368:Merge row \\{pp} into row \|p\X\S$\6 -$\\{qq}\K\\{unsorted}(\\{pp})$;\6 -\&{if} $\\{qq}>\\{void}$ \1\&{then}\6 -\&{if} $\\{unsorted}(\|p)\L\\{void}$ \1\&{then}\5 -$\\{unsorted}(\|p)\K\\{qq}$\6 -\4\&{else} \&{begin} \37\&{while} $\\{link}(\\{qq})>\\{void}$ \1\&{do}\5 -$\\{qq}\K\\{link}(\\{qq})$;\2\6 -$\\{link}(\\{qq})\K\\{unsorted}(\|p)$;\5 -$\\{unsorted}(\|p)\K\\{unsorted}(\\{pp})$;\6 -\&{end};\2\2\6 -$\\{unsorted}(\\{pp})\K\\{null}$;\5 -$\\{qq}\K\\{sorted}(\\{pp})$;\6 -\&{if} $\\{qq}\I\\{sentinel}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{unsorted}(\|p)=\\{void}$ \1\&{then}\5 -$\\{unsorted}(\|p)\K\\{null}$;\2\6 -$\\{sorted}(\\{pp})\K\\{sentinel}$;\5 -$\|r\K\\{sorted\_loc}(\|p)$;\5 -$\|q\K\\{link}(\|r)$;\C{$\|q=\\{sorted}(\|p)$}\6 -\&{if} $\|q=\\{sentinel}$ \1\&{then}\5 -$\\{sorted}(\|p)\K\\{qq}$\6 -\4\&{else} \~ \1\&{loop}\ \&{begin} \37$\|k\K\\{info}(\\{qq})$;\6 -\&{while} $\|k>\\{info}(\|q)$ \1\&{do}\6 -\&{begin} \37$\|r\K\|q$;\5 -$\|q\K\\{link}(\|r)$;\6 -\&{end};\2\6 -$\\{link}(\|r)\K\\{qq}$;\5 -$\\{rr}\K\\{link}(\\{qq})$;\5 -$\\{link}(\\{qq})\K\|q$;\6 -\&{if} $\\{rr}=\\{sentinel}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|r\K\\{qq}$;\5 -$\\{qq}\K\\{rr}$;\6 -\&{end};\2\2\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U366.\fi - -\M369. The \\{total\_weight} routine computes the total of all pixel weights -in a given edge structure. It's not difficult to prove that this is -the sum of $(-w)$ times $x$ taken over all edges, -where $w$ and~$x$ are the weight and $x$~coordinates stored in an edge. -It's not necessary to worry that this quantity will overflow the -size of an \\{integer} register, because it will be less than~$2^{31}$ -unless the edge structure has more than 174,762 edges. However, we had -better not try to compute it as a \\{scaled} integer, because a total -weight of almost $12\times 2^{12}$ can be produced by only four edges. - -\Y\P\4\&{function}\1\ \37$\\{total\_weight}(\|h:\\{pointer})$: \37\\{integer};% -\C{\|h is an edge header}\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{variables that traverse the given -structure}\6 -\|n: \37\\{integer};\C{accumulated total so far}\6 -\|m: \37$0\to65535$;\C{packed $x$ and $w$ values, including offsets}\2\6 -\&{begin} \37$\|n\K0$;\5 -$\|p\K\\{link}(\|h)$;\6 -\&{while} $\|p\I\|h$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{sorted}(\|p)$;\6 -\&{while} $\|q\I\\{sentinel}$ \1\&{do}\5 -\X370:Add the contribution of node \|q to the total weight, and set $\|q\K% -\\{link}(\|q)$\X;\2\6 -$\|q\K\\{unsorted}(\|p)$;\6 -\&{while} $\|q>\\{void}$ \1\&{do}\5 -\X370:Add the contribution of node \|q to the total weight, and set $\|q\K% -\\{link}(\|q)$\X;\2\6 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\\{total\_weight}\K\|n$;\6 -\&{end};\par -\fi - -\M370. It's not necessary to add the offsets to the $x$ coordinates, because -an entire edge structure can be shifted without affecting its total weight. -Similarly, we don't need to subtract \\{zero\_field}. - -\Y\P$\4\X370:Add the contribution of node \|q to the total weight, and set $\|q% -\K\\{link}(\|q)$\X\S$\6 -\&{begin} \37$\|m\K\\{ho}(\\{info}(\|q))$;\5 -$\|n\K\|n-((\|m\mathbin{\&{mod}}8)-\\{zero\_w})\ast(\|m\mathbin{\&{div}}8)$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end}\par -\Us369\ET369.\fi - -\M371. So far we've done lots of things to edge structures assuming that -edges are actually present, but we haven't seen how edges get created -in the first place. Let's turn now to the problem of generating new edges. - -\MF\ will display new edges as they are being computed, if \\{tracing\_edges} -is positive. In order to keep such data reasonably compact, only the -points at which the path makes a $90^\circ$ or $180^\circ$ turn are listed. - -The tracing algorithm must remember some past history in order to suppress -unnecessary data. Three variables \\{trace\_x}, \\{trace\_y}, and \\{trace\_yy} -provide this history: The last coordinates printed were $(\\{trace\_x},\\{trace% -\_y})$, -and the previous edge traced ended at $(\\{trace\_x},\\{trace\_yy})$. Before -anything -at all has been traced, $\\{trace\_x}=-4096$. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{trace\_x}: \37\\{integer};\C{$x$~coordinate most recently shown in a -trace}\6 -\4\\{trace\_y}: \37\\{integer};\C{$y$~coordinate most recently shown in a -trace}\6 -\4\\{trace\_yy}: \37\\{integer};\C{$y$~coordinate most recently encountered}\par -\fi - -\M372. Edge tracing is initiated by the \\{begin\_edge\_tracing} routine, -continued by the \\{trace\_a\_corner} routine, and terminated by the -\\{end\_edge\_tracing} routine. - -\Y\P\4\&{procedure}\1\ \37\\{begin\_edge\_tracing};\2\6 -\&{begin} \37$\\{print\_diagnostic}(\.{"Tracing\ edges"},\39\.{""},\39% -\\{true})$;\5 -$\\{print}(\.{"\ (weight\ "})$;\5 -$\\{print\_int}(\\{cur\_wt})$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\\{trace\_x}\K-4096$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37\\{trace\_a\_corner};\2\6 -\&{begin} \37\&{if} $\\{file\_offset}>\\{max\_print\_line}-13$ \1\&{then}\5 -$\\{print\_nl}(\.{""})$;\2\6 -$\\{print\_char}(\.{"("})$;\5 -$\\{print\_int}(\\{trace\_x})$;\5 -$\\{print\_char}(\.{","})$;\5 -$\\{print\_int}(\\{trace\_yy})$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\\{trace\_y}\K\\{trace\_yy}$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37\\{end\_edge\_tracing};\2\6 -\&{begin} \37\&{if} $\\{trace\_x}=-4096$ \1\&{then}\5 -$\\{print\_nl}(\.{"(No\ new\ edges\ added.)"})$\6 -\4\&{else} \&{begin} \37\\{trace\_a\_corner};\5 -$\\{print\_char}(\.{"."})$;\6 -\&{end};\2\6 -$\\{end\_diagnostic}(\\{true})$;\6 -\&{end};\par -\fi - -\M373. Just after a new edge weight has been put into the \\{info} field of -node~\|r, in row~\|n, the following routine continues an ongoing trace. - -\Y\P\4\&{procedure}\1\ \37$\\{trace\_new\_edge}(\|r:\\{pointer};\,\35\|n:% -\\{integer})$;\6 -\4\&{var} \37\|d: \37\\{integer};\C{temporary data register}\6 -\|w: \37$-3\to3$;\C{weight associated with an edge transition}\6 -$\|m,\39\\{n0},\39\\{n1}$: \37\\{integer};\C{column and row numbers}\2\6 -\&{begin} \37$\|d\K\\{ho}(\\{info}(\|r))$;\5 -$\|w\K(\|d\mathbin{\&{mod}}8)-\\{zero\_w}$;\5 -$\|m\K(\|d\mathbin{\&{div}}8)-\\{m\_offset}(\\{cur\_edges})$;\6 -\&{if} $\|w=\\{cur\_wt}$ \1\&{then}\6 -\&{begin} \37$\\{n0}\K\|n+1$;\5 -$\\{n1}\K\|n$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{n0}\K\|n$;\5 -$\\{n1}\K\|n+1$;\6 -\&{end};\C{the edges run from $(\|m,\\{n0})$ to $(\|m,\\{n1})$}\2\6 -\&{if} $\|m\I\\{trace\_x}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{trace\_x}=-4096$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{""})$;\5 -$\\{trace\_yy}\K\\{n0}$;\6 -\&{end}\6 -\4\&{else} \&{if} $\\{trace\_yy}\I\\{n0}$ \1\&{then}\5 -$\\{print\_char}(\.{"?"})$\C{shouldn't happen}\6 -\4\&{else} \\{trace\_a\_corner};\2\2\6 -$\\{trace\_x}\K\|m$;\5 -\\{trace\_a\_corner};\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{n0}\I\\{trace\_yy}$ \1\&{then}\5 -$\\{print\_char}(\.{"!"})$;\C{shouldn't happen}\2\6 -\&{if} $((\\{n0}<\\{n1})\W(\\{trace\_y}>\\{trace\_yy}))\V((\\{n0}>\\{n1})\W(% -\\{trace\_y}<\\{trace\_yy}))$ \1\&{then}\5 -\\{trace\_a\_corner};\2\6 -\&{end};\2\6 -$\\{trace\_yy}\K\\{n1}$;\6 -\&{end};\par -\fi - -\M374. One way to put new edge weights into an edge structure is to use the -following routine, which simply draws a straight line from $(\\{x0},\\{y0})$ to -$(\\{x1},\\{y1})$. More precisely, it introduces weights for the edges of the -discrete path $\bigl(\lfloor t[x_0,x_1]+{1\over2}+\epsilon\rfloor, -\lfloor t[y_0,y_1]+{1\over2}+\epsilon\delta\rfloor\bigr)$, -as $t$ varies from 0 to~1, where $\epsilon$ and $\delta$ are extremely small -positive numbers. - -The structure header is assumed to be \\{cur\_edges}; downward edge weights -will be \\{cur\_wt}, while upward ones will be $-\\{cur\_wt}$. - -Of course, this subroutine will be called only in connection with others -that eventually draw a complete cycle, so that the sum of the edge weights -in each row will be zero whenever the row is displayed. - -\Y\P\4\&{procedure}\1\ \37$\\{line\_edges}(\\{x0},\39\\{y0},\39\\{x1},\39% -\\{y1}:\\{scaled})$;\6 -\4\&{label} \37$\\{done},\39\\{done1}$;\6 -\4\&{var} \37$\\{m0},\39\\{n0},\39\\{m1},\39\\{n1}$: \37\\{integer};\C{rounded -and unscaled coordinates}\6 -$\\{delx},\39\\{dely}$: \37\\{scaled};\C{the coordinate differences of the -line}\6 -\\{yt}: \37\\{scaled};\C{smallest \|y coordinate that rounds the same as % -\\{y0}}\6 -\\{tx}: \37\\{scaled};\C{tentative change in \|x}\6 -$\|p,\39\|r$: \37\\{pointer};\C{list manipulation registers}\6 -\\{base}: \37\\{integer};\C{amount added to edge-and-weight data}\6 -\|n: \37\\{integer};\C{current row number}\2\6 -\&{begin} \37$\\{n0}\K\\{round\_unscaled}(\\{y0})$;\5 -$\\{n1}\K\\{round\_unscaled}(\\{y1})$;\6 -\&{if} $\\{n0}\I\\{n1}$ \1\&{then}\6 -\&{begin} \37$\\{m0}\K\\{round\_unscaled}(\\{x0})$;\5 -$\\{m1}\K\\{round\_unscaled}(\\{x1})$;\5 -$\\{delx}\K\\{x1}-\\{x0}$;\5 -$\\{dely}\K\\{y1}-\\{y0}$;\5 -$\\{yt}\K\\{n0}\ast\\{unity}-\\{half\_unit}$;\5 -$\\{y0}\K\\{y0}-\\{yt}$;\5 -$\\{y1}\K\\{y1}-\\{yt}$;\6 -\&{if} $\\{n0}<\\{n1}$ \1\&{then}\5 -\X375:Insert upward edges for a line\X\6 -\4\&{else} \X376:Insert downward edges for a line\X;\2\6 -$\\{n\_rover}(\\{cur\_edges})\K\|p$;\5 -$\\{n\_pos}(\\{cur\_edges})\K\|n+\\{zero\_field}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M375. Here we are careful to cancel any effect of rounding error. - -\Y\P$\4\X375:Insert upward edges for a line\X\S$\6 -\&{begin} \37$\\{base}\K8\ast\\{m\_offset}(\\{cur\_edges})+\\{min\_halfword}+% -\\{zero\_w}-\\{cur\_wt}$;\6 -\&{if} $\\{m0}\L\\{m1}$ \1\&{then}\5 -$\\{edge\_prep}(\\{m0},\39\\{m1},\39\\{n0},\39\\{n1})$\ \&{else} $\\{edge% -\_prep}(\\{m1},\39\\{m0},\39\\{n0},\39\\{n1})$;\2\6 -\X377:Move to row \\{n0}, pointed to by \|p\X;\6 -$\\{y0}\K\\{unity}-\\{y0}$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|r\K\\{get\_avail}$;\5 -$\\{link}(\|r)\K\\{unsorted}(\|p)$;\5 -$\\{unsorted}(\|p)\K\|r$;\6 -$\\{tx}\K\\{take\_fraction}(\\{delx},\39\\{make\_fraction}(\\{y0},\39% -\\{dely}))$;\6 -\&{if} $\\{ab\_vs\_cd}(\\{delx},\39\\{y0},\39\\{dely},\39\\{tx})<0$ \1\&{then}\5 -$\\{decr}(\\{tx})$;\C{now $\\{tx}=\lfloor\\{y0}\cdot\\{delx}/\\{dely}\rfloor$}% -\2\6 -$\\{info}(\|r)\K8\ast\\{round\_unscaled}(\\{x0}+\\{tx})+\\{base}$;\6 -$\\{y1}\K\\{y1}-\\{unity}$;\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -$\\{trace\_new\_edge}(\|r,\39\|n)$;\2\6 -\&{if} $\\{y1}<\\{unity}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|p\K\\{link}(\|p)$;\5 -$\\{y0}\K\\{y0}+\\{unity}$;\5 -$\\{incr}(\|n)$;\6 -\&{end};\2\6 -\4\\{done}: \37\&{end}\par -\U374.\fi - -\M376. \P$\X376:Insert downward edges for a line\X\S$\6 -\&{begin} \37$\\{base}\K8\ast\\{m\_offset}(\\{cur\_edges})+\\{min\_halfword}+% -\\{zero\_w}+\\{cur\_wt}$;\6 -\&{if} $\\{m0}\L\\{m1}$ \1\&{then}\5 -$\\{edge\_prep}(\\{m0},\39\\{m1},\39\\{n1},\39\\{n0})$\ \&{else} $\\{edge% -\_prep}(\\{m1},\39\\{m0},\39\\{n1},\39\\{n0})$;\2\6 -$\\{decr}(\\{n0})$;\5 -\X377:Move to row \\{n0}, pointed to by \|p\X;\6 -\~ \1\&{loop}\ \&{begin} \37$\|r\K\\{get\_avail}$;\5 -$\\{link}(\|r)\K\\{unsorted}(\|p)$;\5 -$\\{unsorted}(\|p)\K\|r$;\6 -$\\{tx}\K\\{take\_fraction}(\\{delx},\39\\{make\_fraction}(\\{y0},\39% -\\{dely}))$;\6 -\&{if} $\\{ab\_vs\_cd}(\\{delx},\39\\{y0},\39\\{dely},\39\\{tx})<0$ \1\&{then}\5 -$\\{incr}(\\{tx})$;\C{now $\\{tx}=\lceil\\{y0}\cdot\\{delx}/\\{dely}\rceil$, -since $\\{dely}<0$}\2\6 -$\\{info}(\|r)\K8\ast\\{round\_unscaled}(\\{x0}-\\{tx})+\\{base}$;\6 -$\\{y1}\K\\{y1}+\\{unity}$;\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -$\\{trace\_new\_edge}(\|r,\39\|n)$;\2\6 -\&{if} $\\{y1}\G0$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -$\|p\K\\{knil}(\|p)$;\5 -$\\{y0}\K\\{y0}+\\{unity}$;\5 -$\\{decr}(\|n)$;\6 -\&{end};\2\6 -\4\\{done1}: \37\&{end}\par -\U374.\fi - -\M377. \P$\X377:Move to row \\{n0}, pointed to by \|p\X\S$\6 -$\|n\K\\{n\_pos}(\\{cur\_edges})-\\{zero\_field}$;\5 -$\|p\K\\{n\_rover}(\\{cur\_edges})$;\6 -\&{if} $\|n\I\\{n0}$ \1\&{then}\6 -\&{if} $\|n<\\{n0}$ \1\&{then}\6 -\1\&{repeat} \37$\\{incr}(\|n)$;\5 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\|n=\\{n0}$\2\6 -\4\&{else} \1\&{repeat} \37$\\{decr}(\|n)$;\5 -$\|p\K\\{knil}(\|p)$;\6 -\4\&{until}\5 -$\|n=\\{n0}$\2\2\2\par -\Us375, 376, 381, 382, 383\ETs384.\fi - -\M378. \MF\ inserts most of its edges into edge structures via the -\\{move\_to\_edges} subroutine, which uses the data stored in the \\{move} -array -to specify a sequence of ``rook moves.'' The starting point $(\\{m0},\\{n0})$ -and finishing point $(\\{m1},\\{n1})$ of these moves, as seen from the -standpoint -of the first octant, are supplied as parameters; the moves should, however, -be rotated into a given octant. (We're going to study octant -transformations in great detail later; the reader may wish to come back to -this part of the program after mastering the mysteries of octants.) - -The rook moves themselves are defined as follows, from a \\{first\_octant} -point of view: ``Go right $\\{move}[\|k]$ steps, then go up one, for $0\L\|k<% -\\{n1}-\\{n0}$; -then go right $\\{move}[\\{n1}-\\{n0}]$ steps and stop.'' The sum of $\\{move}[% -\|k]$ -for $0\L\|k\L\\{n1}-\\{n0}$ will be equal to $\\{m1}-\\{m0}$. - -As in the \\{line\_edges} routine, we use $+\\{cur\_wt}$ as the weight of -all downward edges and $-\\{cur\_wt}$ as the weight of all upward edges, -after the moves have been rotated to the proper octant direction. - -There are two main cases to consider: \\{fast\_case} is for moves that -travel in the direction of octants 1, 4, 5, and~8, while \\{slow\_case} -is for moves that travel toward octants 2, 3, 6, and~7. The latter directions -are comparatively cumbersome because they generate more upward or downward -edges; a curve that travels horizontally doesn't produce any edges at all, -but a curve that travels vertically touches lots of rows. - -\Y\P\D \37$\\{fast\_case\_up}=60$\C{for octants 1 and 4}\par -\P\D \37$\\{fast\_case\_down}=61$\C{for octants 5 and 8}\par -\P\D \37$\\{slow\_case\_up}=62$\C{for octants 2 and 3}\par -\P\D \37$\\{slow\_case\_down}=63$\C{for octants 6 and 7}\par -\Y\P\4\&{procedure}\1\ \37$\\{move\_to\_edges}(\\{m0},\39\\{n0},\39\\{m1},\39% -\\{n1}:\\{integer})$;\6 -\4\&{label} \37$\\{fast\_case\_up},\39\\{fast\_case\_down},\39\\{slow\_case% -\_up},\39\\{slow\_case\_down},\39\\{done}$;\6 -\4\&{var} \37\\{delta}: \37$0\to\\{move\_size}$;\C{extent of \\{move} data}\6 -\|k: \37$0\to\\{move\_size}$;\C{index into \\{move}}\6 -$\|p,\39\|r$: \37\\{pointer};\C{list manipulation registers}\6 -\\{dx}: \37\\{integer};\C{change in edge-weight \\{info} when \|x changes by 1}% -\6 -\\{edge\_and\_weight}: \37\\{integer};\C{\\{info} to insert}\6 -\|j: \37\\{integer};\C{number of consecutive vertical moves}\6 -\|n: \37\\{integer};\C{the current row pointed to by \|p}\2\6 -\&{debug} \37\\{sum}: \37\\{integer};\ \&{gubed}\6 -\&{begin} \37$\\{delta}\K\\{n1}-\\{n0}$;\6 -\&{debug} \37$\\{sum}\K\\{move}[0]$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}\\{delta}$ \1\&{do}\5 -$\\{sum}\K\\{sum}+\\{abs}(\\{move}[\|k])$;\2\6 -\&{if} $\\{sum}\I\\{m1}-\\{m0}$ \1\&{then}\5 -$\\{confusion}(\.{"0"})$;\ \2\6 -\&{gubed}\6 -\X380:Prepare for and switch to the appropriate case, based on \\{octant}\X;\6 -\4\\{fast\_case\_up}: \37\X381:Add edges for first or fourth octants, then % -\&{goto} \\{done}\X;\6 -\4\\{fast\_case\_down}: \37\X382:Add edges for fifth or eighth octants, then % -\&{goto} \\{done}\X;\6 -\4\\{slow\_case\_up}: \37\X383:Add edges for second or third octants, then % -\&{goto} \\{done}\X;\6 -\4\\{slow\_case\_down}: \37\X384:Add edges for sixth or seventh octants, then % -\&{goto} \\{done}\X;\6 -\4\\{done}: \37$\\{n\_pos}(\\{cur\_edges})\K\|n+\\{zero\_field}$;\5 -$\\{n\_rover}(\\{cur\_edges})\K\|p$;\6 -\&{end};\par -\fi - -\M379. The current octant code appears in a global variable. If, for example, -we have $\\{octant}=\\{third\_octant}$, it means that a curve traveling in a -north to -north-westerly direction has been rotated for the purposes of internal -calculations so that the \\{move} data travels in an east to north-easterly -direction. We want to unrotate as we update the edge structure. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{octant}: \37$\\{first\_octant}\to\\{sixth\_octant}$;\C{the current octant -of interest}\par -\fi - -\M380. \P$\X380:Prepare for and switch to the appropriate case, based on % -\\{octant}\X\S$\6 -\&{case} $\\{octant}$ \1\&{of}\6 -\4\\{first\_octant}: \37\&{begin} \37$\\{dx}\K8$;\5 -$\\{edge\_prep}(\\{m0},\39\\{m1},\39\\{n0},\39\\{n1})$;\5 -\&{goto} \37\\{fast\_case\_up};\6 -\&{end};\6 -\4\\{second\_octant}: \37\&{begin} \37$\\{dx}\K8$;\5 -$\\{edge\_prep}(\\{n0},\39\\{n1},\39\\{m0},\39\\{m1})$;\5 -\&{goto} \37\\{slow\_case\_up};\6 -\&{end};\6 -\4\\{third\_octant}: \37\&{begin} \37$\\{dx}\K-8$;\5 -$\\{edge\_prep}(-\\{n1},\39-\\{n0},\39\\{m0},\39\\{m1})$;\5 -$\\{negate}(\\{n0})$;\5 -\&{goto} \37\\{slow\_case\_up};\6 -\&{end};\6 -\4\\{fourth\_octant}: \37\&{begin} \37$\\{dx}\K-8$;\5 -$\\{edge\_prep}(-\\{m1},\39-\\{m0},\39\\{n0},\39\\{n1})$;\5 -$\\{negate}(\\{m0})$;\5 -\&{goto} \37\\{fast\_case\_up};\6 -\&{end};\6 -\4\\{fifth\_octant}: \37\&{begin} \37$\\{dx}\K-8$;\5 -$\\{edge\_prep}(-\\{m1},\39-\\{m0},\39-\\{n1},\39-\\{n0})$;\5 -$\\{negate}(\\{m0})$;\5 -\&{goto} \37\\{fast\_case\_down};\6 -\&{end};\6 -\4\\{sixth\_octant}: \37\&{begin} \37$\\{dx}\K-8$;\5 -$\\{edge\_prep}(-\\{n1},\39-\\{n0},\39-\\{m1},\39-\\{m0})$;\5 -$\\{negate}(\\{n0})$;\5 -\&{goto} \37\\{slow\_case\_down};\6 -\&{end};\6 -\4\\{seventh\_octant}: \37\&{begin} \37$\\{dx}\K8$;\5 -$\\{edge\_prep}(\\{n0},\39\\{n1},\39-\\{m1},\39-\\{m0})$;\5 -\&{goto} \37\\{slow\_case\_down};\6 -\&{end};\6 -\4\\{eighth\_octant}: \37\&{begin} \37$\\{dx}\K8$;\5 -$\\{edge\_prep}(\\{m0},\39\\{m1},\39-\\{n1},\39-\\{n0})$;\5 -\&{goto} \37\\{fast\_case\_down};\6 -\&{end};\2\6 -\&{end};\C{there are only eight octants}\par -\U378.\fi - -\M381. \P$\X381:Add edges for first or fourth octants, then \&{goto} \\{done}\X% -\S$\6 -\X377:Move to row \\{n0}, pointed to by \|p\X;\6 -\&{if} $\\{delta}>0$ \1\&{then}\6 -\&{begin} \37$\|k\K0$;\5 -$\\{edge\_and\_weight}\K8\ast(\\{m0}+\\{m\_offset}(\\{cur\_edges}))+\\{min% -\_halfword}+\\{zero\_w}-\\{cur\_wt}$;\6 -\1\&{repeat} \37$\\{edge\_and\_weight}\K\\{edge\_and\_weight}+\\{dx}\ast% -\\{move}[\|k]$;\5 -$\\{fast\_get\_avail}(\|r)$;\5 -$\\{link}(\|r)\K\\{unsorted}(\|p)$;\5 -$\\{info}(\|r)\K\\{edge\_and\_weight}$;\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -$\\{trace\_new\_edge}(\|r,\39\|n)$;\2\6 -$\\{unsorted}(\|p)\K\|r$;\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{incr}(\|k)$;\5 -$\\{incr}(\|n)$;\6 -\4\&{until}\5 -$\|k=\\{delta}$;\2\6 -\&{end};\2\6 -\&{goto} \37\\{done}\par -\U378.\fi - -\M382. \P$\X382:Add edges for fifth or eighth octants, then \&{goto} \\{done}\X% -\S$\6 -$\\{n0}\K-\\{n0}-1$;\5 -\X377:Move to row \\{n0}, pointed to by \|p\X;\6 -\&{if} $\\{delta}>0$ \1\&{then}\6 -\&{begin} \37$\|k\K0$;\5 -$\\{edge\_and\_weight}\K8\ast(\\{m0}+\\{m\_offset}(\\{cur\_edges}))+\\{min% -\_halfword}+\\{zero\_w}+\\{cur\_wt}$;\6 -\1\&{repeat} \37$\\{edge\_and\_weight}\K\\{edge\_and\_weight}+\\{dx}\ast% -\\{move}[\|k]$;\5 -$\\{fast\_get\_avail}(\|r)$;\5 -$\\{link}(\|r)\K\\{unsorted}(\|p)$;\5 -$\\{info}(\|r)\K\\{edge\_and\_weight}$;\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -$\\{trace\_new\_edge}(\|r,\39\|n)$;\2\6 -$\\{unsorted}(\|p)\K\|r$;\5 -$\|p\K\\{knil}(\|p)$;\5 -$\\{incr}(\|k)$;\5 -$\\{decr}(\|n)$;\6 -\4\&{until}\5 -$\|k=\\{delta}$;\2\6 -\&{end};\2\6 -\&{goto} \37\\{done}\par -\U378.\fi - -\M383. \P$\X383:Add edges for second or third octants, then \&{goto} \\{done}\X% -\S$\6 -$\\{edge\_and\_weight}\K8\ast(\\{n0}+\\{m\_offset}(\\{cur\_edges}))+\\{min% -\_halfword}+\\{zero\_w}-\\{cur\_wt}$;\5 -$\\{n0}\K\\{m0}$;\5 -$\|k\K0$;\5 -\X377:Move to row \\{n0}, pointed to by \|p\X;\6 -\1\&{repeat} \37$\|j\K\\{move}[\|k]$;\6 -\&{while} $\|j>0$ \1\&{do}\6 -\&{begin} \37$\\{fast\_get\_avail}(\|r)$;\5 -$\\{link}(\|r)\K\\{unsorted}(\|p)$;\5 -$\\{info}(\|r)\K\\{edge\_and\_weight}$;\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -$\\{trace\_new\_edge}(\|r,\39\|n)$;\2\6 -$\\{unsorted}(\|p)\K\|r$;\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{decr}(\|j)$;\5 -$\\{incr}(\|n)$;\6 -\&{end};\2\6 -$\\{edge\_and\_weight}\K\\{edge\_and\_weight}+\\{dx}$;\5 -$\\{incr}(\|k)$;\6 -\4\&{until}\5 -$\|k>\\{delta}$;\2\6 -\&{goto} \37\\{done}\par -\U378.\fi - -\M384. \P$\X384:Add edges for sixth or seventh octants, then \&{goto} \\{done}% -\X\S$\6 -$\\{edge\_and\_weight}\K8\ast(\\{n0}+\\{m\_offset}(\\{cur\_edges}))+\\{min% -\_halfword}+\\{zero\_w}+\\{cur\_wt}$;\5 -$\\{n0}\K-\\{m0}-1$;\5 -$\|k\K0$;\5 -\X377:Move to row \\{n0}, pointed to by \|p\X;\6 -\1\&{repeat} \37$\|j\K\\{move}[\|k]$;\6 -\&{while} $\|j>0$ \1\&{do}\6 -\&{begin} \37$\\{fast\_get\_avail}(\|r)$;\5 -$\\{link}(\|r)\K\\{unsorted}(\|p)$;\5 -$\\{info}(\|r)\K\\{edge\_and\_weight}$;\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -$\\{trace\_new\_edge}(\|r,\39\|n)$;\2\6 -$\\{unsorted}(\|p)\K\|r$;\5 -$\|p\K\\{knil}(\|p)$;\5 -$\\{decr}(\|j)$;\5 -$\\{decr}(\|n)$;\6 -\&{end};\2\6 -$\\{edge\_and\_weight}\K\\{edge\_and\_weight}+\\{dx}$;\5 -$\\{incr}(\|k)$;\6 -\4\&{until}\5 -$\|k>\\{delta}$;\2\6 -\&{goto} \37\\{done}\par -\U378.\fi - -\M385. All the hard work of building an edge structure is undone by the -following -subroutine. - -\Y\P$\4\X268:Declare the recycling subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{toss\_edges}(\|h:\\{pointer})$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{for list manipulation}\2\6 -\&{begin} \37$\|q\K\\{link}(\|h)$;\6 -\&{while} $\|q\I\|h$ \1\&{do}\6 -\&{begin} \37$\\{flush\_list}(\\{sorted}(\|q))$;\6 -\&{if} $\\{unsorted}(\|q)>\\{void}$ \1\&{then}\5 -$\\{flush\_list}(\\{unsorted}(\|q))$;\2\6 -$\|p\K\|q$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{free\_node}(\|p,\39\\{row\_node\_size})$;\6 -\&{end};\2\6 -$\\{free\_node}(\|h,\39\\{edge\_header\_size})$;\6 -\&{end};\par -\fi - -\N386. \[21] Subdivision into octants. -When \MF\ digitizes a path, it reduces the problem to the special -case of paths that travel in ``first octant'' directions; i.e., -each cubic $z(t)=\bigl(x(t),y(t)\bigr)$ being digitized will have the property -that $0\L y'(t)\L x'(t)$. This assumption makes digitizing simpler -and faster than if the direction of motion has to be tested repeatedly. - -When $z(t)$ is cubic, $x'(t)$ and $y'(t)$ are quadratic, hence the four -polynomials $x'(t)$, $y'(t)$, $x'(t)-y'(t)$, and $x'(t)+y'(t)$ cross -through~0 at most twice each. If we subdivide the given cubic at these -places, we get at most nine subintervals in each of which -$x'(t)$, $y'(t)$, $x'(t)-y'(t)$, and $x'(t)+y'(t)$ all have a constant -sign. The curve can be transformed in each of these subintervals so that -it travels entirely in first octant directions, if we reflect $x\swap-x$, -$y\swap-y$, and/or $x\swap y$ as necessary. (Incidentally, it can be -shown that a cubic such that $x'(t)=16(2t-1)^2+2(2t-1)-1$ and -$y'(t)=8(2t-1)^2+4(2t-1)$ does indeed split into nine subintervals.) - -\fi - -\M387. The transformation that rotates coordinates, so that first octant motion -can be assumed, is defined by the \\{skew} subroutine, which sets global -variables \\{cur\_x} and \\{cur\_y} to the values that are appropriate in a -given octant. (Octants are encoded as they were in the \\{n\_arg} subroutine.) - -This transformation is ``skewed'' by replacing $(\|x,\|y)$ by $(\|x-\|y,\|y)$, -once first octant motion has been established. It turns out that -skewed coordinates are somewhat better to work with when curves are -actually digitized. - -\Y\P\D \37$\\{set\_two\_end}(\#)\S\\{cur\_y}\K\#$;\ \&{end} \par -\P\D $\\{set\_two}(\#)\S$ \6 -\&{begin} \37$\\{cur\_x}\K\#$;\5 -\\{set\_two\_end}\par -\Y\P\4\&{procedure}\1\ \37$\\{skew}(\|x,\39\|y:\\{scaled};\,\35\\{octant}:% -\\{small\_number})$;\2\6 -\&{begin} \37\&{case} $\\{octant}$ \1\&{of}\6 -\4\\{first\_octant}: \37$\\{set\_two}(\|x-\|y)(\|y)$;\6 -\4\\{second\_octant}: \37$\\{set\_two}(\|y-\|x)(\|x)$;\6 -\4\\{third\_octant}: \37$\\{set\_two}(\|y+\|x)(-\|x)$;\6 -\4\\{fourth\_octant}: \37$\\{set\_two}(-\|x-\|y)(\|y)$;\6 -\4\\{fifth\_octant}: \37$\\{set\_two}(-\|x+\|y)(-\|y)$;\6 -\4\\{sixth\_octant}: \37$\\{set\_two}(-\|y+\|x)(-\|x)$;\6 -\4\\{seventh\_octant}: \37$\\{set\_two}(-\|y-\|x)(\|x)$;\6 -\4\\{eighth\_octant}: \37$\\{set\_two}(\|x+\|y)(-\|y)$;\2\6 -\&{end};\C{there are no other cases}\6 -\&{end};\par -\fi - -\M388. Conversely, the following subroutine sets \\{cur\_x} and -\\{cur\_y} to the original coordinate values of a point, given an octant -code and the point's coordinates $(\|x,\|y)$ after they have been mapped into -the first octant and skewed. - -\Y\P$\4\X257:Declare subroutines for printing expressions\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{unskew}(\|x,\39\|y:\\{scaled};\,\35\\{octant}:% -\\{small\_number})$;\2\6 -\&{begin} \37\&{case} $\\{octant}$ \1\&{of}\6 -\4\\{first\_octant}: \37$\\{set\_two}(\|x+\|y)(\|y)$;\6 -\4\\{second\_octant}: \37$\\{set\_two}(\|y)(\|x+\|y)$;\6 -\4\\{third\_octant}: \37$\\{set\_two}(-\|y)(\|x+\|y)$;\6 -\4\\{fourth\_octant}: \37$\\{set\_two}(-\|x-\|y)(\|y)$;\6 -\4\\{fifth\_octant}: \37$\\{set\_two}(-\|x-\|y)(-\|y)$;\6 -\4\\{sixth\_octant}: \37$\\{set\_two}(-\|y)(-\|x-\|y)$;\6 -\4\\{seventh\_octant}: \37$\\{set\_two}(\|y)(-\|x-\|y)$;\6 -\4\\{eighth\_octant}: \37$\\{set\_two}(\|x+\|y)(-\|y)$;\2\6 -\&{end};\C{there are no other cases}\6 -\&{end};\par -\fi - -\M389. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{cur\_x},\39\\{cur\_y}$: \37\\{scaled};\C{outputs of \\{rotate}, % -\\{unrotate}, and a few other routines}\par -\fi - -\M390. The conversion to skewed and rotated coordinates takes place in -stages, and at one point in the transformation we will have negated the -$x$ and/or $y$ coordinates so as to make curves travel in the first -{\sl quadrant}. At this point the relevant ``octant'' code will be -either \\{first\_octant} (when no transformation has been done), -or $\\{fourth\_octant}=\\{first\_octant}+\\{negate\_x}$ (when $x$ has been -negated), -or $\\{fifth\_octant}=\\{first\_octant}+\\{negate\_x}+\\{negate\_y}$ (when both -have been -negated), or $\\{eighth\_octant}=\\{first\_octant}+\\{negate\_y}$ (when $y$ has -been -negated). The \\{abnegate} routine is sometimes needed to convert -from one of these transformations to another. - -\Y\P\4\&{procedure}\1\ \37$\\{abnegate}(\|x,\39\|y:\\{scaled};\,\35\\{octant% -\_before},\39\\{octant\_after}:\\{small\_number})$;\2\6 -\&{begin} \37\&{if} $\\{odd}(\\{octant\_before})=\\{odd}(\\{octant\_after})$ \1% -\&{then}\5 -$\\{cur\_x}\K\|x$\6 -\4\&{else} $\\{cur\_x}\K-\|x$;\2\6 -\&{if} $(\\{octant\_before}>\\{negate\_y})=(\\{octant\_after}>\\{negate\_y})$ % -\1\&{then}\5 -$\\{cur\_y}\K\|y$\6 -\4\&{else} $\\{cur\_y}\K-\|y$;\2\6 -\&{end};\par -\fi - -\M391. Now here's a subroutine that's handy for subdivision: Given a -quadratic polynomial $B(a,b,c;t)$, the \\{crossing\_point} function -returns the unique \\{fraction} value \|t between 0 and~1 at which -$B(a,b,c;t)$ changes from positive to negative, or returns -$\|t=\\{fraction\_one}+1$ if no such value exists. If $\|a<0$ (so that -$B(a,b,c;t)$ -is already negative at $\|t=0$), \\{crossing\_point} returns the value zero. - -\Y\P\D \37$\\{no\_crossing}\S$\1\6 -\&{begin} \37$\\{crossing\_point}\K\\{fraction\_one}+1$;\5 -\&{return};\6 -\&{end}\2\par -\P\D \37$\\{one\_crossing}\S$\1\6 -\&{begin} \37$\\{crossing\_point}\K\\{fraction\_one}$;\5 -\&{return};\6 -\&{end}\2\par -\P\D \37$\\{zero\_crossing}\S$\1\6 -\&{begin} \37$\\{crossing\_point}\K0$;\5 -\&{return};\6 -\&{end}\2\par -\Y\P\4\&{function}\1\ \37$\\{crossing\_point}(\|a,\39\|b,\39\|c:\\{integer})$: -\37\\{fraction};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|d: \37\\{integer};\C{recursive counter}\6 -$\|x,\39\\{xx},\39\\{x0},\39\\{x1},\39\\{x2}$: \37\\{integer};\C{temporary -registers for bisection}\2\6 -\&{begin} \37\&{if} $\|a<0$ \1\&{then}\5 -\\{zero\_crossing};\2\6 -\&{if} $\|c\G0$ \1\&{then}\6 -\&{begin} \37\&{if} $\|b\G0$ \1\&{then}\6 -\&{if} $\|c>0$ \1\&{then}\5 -\\{no\_crossing}\6 -\4\&{else} \&{if} $(\|a=0)\W(\|b=0)$ \1\&{then}\5 -\\{no\_crossing}\6 -\4\&{else} \\{one\_crossing};\2\2\2\6 -\&{if} $\|a=0$ \1\&{then}\5 -\\{zero\_crossing};\2\6 -\&{end}\6 -\4\&{else} \&{if} $\|a=0$ \1\&{then}\6 -\&{if} $\|b\L0$ \1\&{then}\5 -\\{zero\_crossing};\2\2\2\6 -\X392:Use bisection to find the crossing point, if one exists\X;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M392. The general bisection method is quite simple when $n=2$, hence -\\{crossing\_point} does not take much time. At each stage in the -recursion we have a subinterval defined by \|l and~\|j such that -$B(a,b,c;2^{-l}(j+t))=B(x_0,x_1,x_2;t)$, and we want to ``zero in'' on -the subinterval where $x_0\G0$ and $\min(x_1,x_2)<0$. - -It is convenient for purposes of calculation to combine the values -of \|l and~\|j in a single variable $d=2^l+j$, because the operation -of bisection then corresponds simply to doubling $d$ and possibly -adding~1. Furthermore it proves to be convenient to modify -our previous conventions for bisection slightly, maintaining the -variables $X_0=2^lx_0$, $X_1=2^l(x_0-x_1)$, and $X_2=2^l(x_1-x_2)$. -With these variables the conditions $x_0\ge0$ and $\min(x_1,x_2)<0$ are -equivalent to $\max(X_1,X_1+X_2)>X_0\ge0$. - -The following code maintains the invariant relations -$0\L\\{x0}<\max(\\{x1},\\{x1}+\\{x2})$, -$\vert\\{x1}\vert<2^{30}$, $\vert\\{x2}\vert<2^{30}$; -it has been constructed in such a way that no arithmetic overflow -will occur if the inputs satisfy -$a<2^{30}$, $\vert a-b\vert<2^{30}$, and $\vert b-c\vert<2^{30}$. - -\Y\P$\4\X392:Use bisection to find the crossing point, if one exists\X\S$\6 -$\|d\K1$;\5 -$\\{x0}\K\|a$;\5 -$\\{x1}\K\|a-\|b$;\5 -$\\{x2}\K\|b-\|c$;\6 -\1\&{repeat} \37$\|x\K\\{half}(\\{x1}+\\{x2})$;\6 -\&{if} $\\{x1}-\\{x0}>\\{x0}$ \1\&{then}\6 -\&{begin} \37$\\{x2}\K\|x$;\5 -$\\{double}(\\{x0})$;\5 -$\\{double}(\|d)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{xx}\K\\{x1}+\|x-\\{x0}$;\6 -\&{if} $\\{xx}>\\{x0}$ \1\&{then}\6 -\&{begin} \37$\\{x2}\K\|x$;\5 -$\\{double}(\\{x0})$;\5 -$\\{double}(\|d)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{x0}\K\\{x0}-\\{xx}$;\6 -\&{if} $\|x\L\\{x0}$ \1\&{then}\6 -\&{if} $\|x+\\{x2}\L\\{x0}$ \1\&{then}\5 -\\{no\_crossing};\2\2\6 -$\\{x1}\K\|x$;\5 -$\|d\K\|d+\|d+1$;\6 -\&{end};\2\6 -\&{end};\2\6 -\4\&{until}\5 -$\|d\G\\{fraction\_one}$;\2\6 -$\\{crossing\_point}\K\|d-\\{fraction\_one}$\par -\U391.\fi - -\M393. Octant subdivision is applied only to cycles, i.e., to closed paths. -A ``cycle spec'' is a data structure that contains specifications of -cubic curves and octant mappings for the cycle that has been subdivided -into segments belonging to single octants. It is composed entirely of -knot nodes, similar to those in the representation of paths; but the -\\{explicit} type indications have been replaced by positive numbers -that give further information. Additional \\{endpoint} data is also -inserted at the octant boundaries. - -Recall that a cubic polynomial is represented by four control points -that appear in adjacent nodes \|p and~\|q of a knot list. The \|x~coordinates -are $\\{x\_coord}(\|p)$, $\\{right\_x}(\|p)$, $\\{left\_x}(\|q)$, and $\\{x% -\_coord}(\|q)$; the -\|y~coordinates are similar. We shall call this ``the cubic following~\|p'' -or ``the cubic between \|p and~\|q'' or ``the cubic preceding~\|q.'' - -Cycle specs are circular lists of cubic curves mixed with octant -boundaries. Like cubics, the octant boundaries are represented in -consecutive knot nodes \|p and~\|q. In such cases $\\{right\_type}(\|p)=\\{left% -\_type}(\|q)=\\{endpoint}$, and the fields $\\{right\_x}(\|p)$, $\\{right\_y}(% -\|p)$, -$\\{left\_x}(\|q)$, and $\\{left\_y}(\|q)$ are replaced by other fields called -$\\{right\_octant}(\|p)$, $\\{right\_transition}(\|p)$, $\\{left\_octant}(% -\|q)$, and -$\\{left\_transition}(\|q)$, respectively. For example, when the curve -direction -moves from the third octant to the fourth octant, the boundary nodes say -$\\{right\_octant}(\|p)=\\{third\_octant}$, $\\{left\_octant}(\|q)=\\{fourth% -\_octant}$, -and $\\{right\_transition}(\|p)=\\{left\_transition}(\|q)=\\{diagonal}$. A % -\\{diagonal} -transition occurs when moving between octants 1~\AM~2, 3~\AM~4, 5~\AM~6, or -7~\AM~8; an \\{axis} transition occurs when moving between octants 8~\AM~1, -2~\AM~3, 4~\AM~5, 6~\AM~7. (Such transition information is redundant -but convenient.) Fields $\\{x\_coord}(\|p)$ and $\\{y\_coord}(\|p)$ will -contain -coordinates of the transition point after rotation from third octant -to first octant; i.e., if the true coordinates are $(x,y)$, the -coordinates $(y,-x)$ will appear in node~\|p. Similarly, a fourth-octant -transformation will have been applied after the transition, so -we will have $\\{x\_coord}(\|q)=\hbox{$-x$}$ and $\\{y\_coord}(\|q)=\|y$. - -The cubic between \|p and \|q will contain positive numbers in the -fields $\\{right\_type}(\|p)$ and $\\{left\_type}(\|q)$; this makes cubics -distinguishable from octant boundaries, because $\\{endpoint}=0$. -The value of $\\{right\_type}(\|p)$ will be the current octant code, -during the time that cycle specs are being constructed; it will -refer later to a pen offset position, if the envelope of a cycle is -being computed. A cubic that comes from some subinterval of the $k$th -step in the original cyclic path will have $\\{left\_type}(\|q)=\|k$. - -\Y\P\D \37$\\{right\_octant}\S\\{right\_x}$\C{the octant code before a -transition}\par -\P\D \37$\\{left\_octant}\S\\{left\_x}$\C{the octant after a transition}\par -\P\D \37$\\{right\_transition}\S\\{right\_y}$\C{the type of transition}\par -\P\D \37$\\{left\_transition}\S\\{left\_y}$\C{ditto, either \\{axis} or % -\\{diagonal}}\par -\P\D \37$\\{axis}=0$\C{a transition across the $x'$- or $y'$-axis}\par -\P\D \37$\\{diagonal}=1$\C{a transition where $y'=\pm x'$}\par -\fi - -\M394. Here's a routine that prints a cycle spec in symbolic form, so that it -is possible to see what subdivision has been made. The point coordinates -are converted back from \MF's internal ``rotated'' form to the external -``true'' form. The global variable~\\{cur\_spec} should point to a knot just -after the beginning of an octant boundary, i.e., such that -$\\{left\_type}(\\{cur\_spec})=\\{endpoint}$. - -\Y\P\D \37$\\{print\_two\_true}(\#)\S\\{unskew}(\#,\39\\{octant})$;\5 -$\\{print\_two}(\\{cur\_x},\39\\{cur\_y})$\par -\Y\P\4\&{procedure}\1\ \37$\\{print\_spec}(\|s:\\{str\_number})$;\6 -\4\&{label} \37$\\{not\_found},\39\\{done}$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{for list traversal}\6 -\\{octant}: \37\\{small\_number};\C{the current octant code}\2\6 -\&{begin} \37$\\{print\_diagnostic}(\.{"Cycle\ spec"},\39\|s,\39\\{true})$;\5 -$\|p\K\\{cur\_spec}$;\5 -$\\{octant}\K\\{left\_octant}(\|p)$;\5 -\\{print\_ln};\5 -$\\{print\_two\_true}(\\{x\_coord}(\\{cur\_spec}),\39\\{y\_coord}(\\{cur% -\_spec}))$;\5 -$\\{print}(\.{"\ \%\ beginning\ in\ octant\ \`"})$;\6 -\~ \1\&{loop}\ \&{begin} \37$\\{print}(\\{octant\_dir}[\\{octant}])$;\5 -$\\{print\_char}(\.{"\'"})$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|q\K\\{link}(\|p)$;\6 -\&{if} $\\{right\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\X397:Print the cubic between \|p and \|q\X;\6 -$\|p\K\|q$;\6 -\&{end};\2\6 -\4\\{not\_found}: \37\&{if} $\|q=\\{cur\_spec}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|p\K\|q$;\5 -$\\{octant}\K\\{left\_octant}(\|p)$;\5 -$\\{print\_nl}(\.{"\%\ entering\ octant\ \`"})$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{print\_nl}(\.{"\ \&\ cycle"})$;\5 -$\\{end\_diagnostic}(\\{true})$;\6 -\&{end};\par -\fi - -\M395. Symbolic octant direction names are kept in the \\{octant\_dir} array. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{octant\_dir}: \37\&{array} $[\\{first\_octant}\to\\{sixth\_octant}]$ \1% -\&{of}\5 -\\{str\_number};\2\par -\fi - -\M396. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{octant\_dir}[\\{first\_octant}]\K\.{"ENE"}$;\5 -$\\{octant\_dir}[\\{second\_octant}]\K\.{"NNE"}$;\5 -$\\{octant\_dir}[\\{third\_octant}]\K\.{"NNW"}$;\5 -$\\{octant\_dir}[\\{fourth\_octant}]\K\.{"WNW"}$;\5 -$\\{octant\_dir}[\\{fifth\_octant}]\K\.{"WSW"}$;\5 -$\\{octant\_dir}[\\{sixth\_octant}]\K\.{"SSW"}$;\5 -$\\{octant\_dir}[\\{seventh\_octant}]\K\.{"SSE"}$;\5 -$\\{octant\_dir}[\\{eighth\_octant}]\K\.{"ESE"}$;\par -\fi - -\M397. \P$\X397:Print the cubic between \|p and \|q\X\S$\6 -\&{begin} \37$\\{print\_nl}(\.{"\ \ \ ..controls\ "})$;\5 -$\\{print\_two\_true}(\\{right\_x}(\|p),\39\\{right\_y}(\|p))$;\5 -$\\{print}(\.{"\ and\ "})$;\5 -$\\{print\_two\_true}(\\{left\_x}(\|q),\39\\{left\_y}(\|q))$;\5 -$\\{print\_nl}(\.{"\ .."})$;\5 -$\\{print\_two\_true}(\\{x\_coord}(\|q),\39\\{y\_coord}(\|q))$;\5 -$\\{print}(\.{"\ \%\ segment\ "})$;\5 -$\\{print\_int}(\\{left\_type}(\|q)-1)$;\6 -\&{end}\par -\U394.\fi - -\M398. A much more compact version of a spec is printed to help users identify -``strange paths.'' - -\Y\P\4\&{procedure}\1\ \37$\\{print\_strange}(\|s:\\{str\_number})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{for list traversal}\6 -\|f: \37\\{pointer};\C{starting point in the cycle}\6 -\|q: \37\\{pointer};\C{octant boundary to be printed}\6 -\|t: \37\\{integer};\C{segment number, plus 1}\2\6 -\&{begin} \37\&{if} $\\{interaction}=\\{error\_stop\_mode}$ \1\&{then}\5 -\\{wake\_up\_terminal};\2\6 -$\\{print\_nl}(\.{">"})$;\5 -\X399:Find the starting point, \|f\X;\6 -\X400:Determine the octant boundary \|q that precedes \|f\X;\6 -$\|t\K0$;\6 -\1\&{repeat} \37\&{if} $\\{left\_type}(\|p)\I\\{endpoint}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{left\_type}(\|p)\I\|t$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{left\_type}(\|p)$;\5 -$\\{print\_char}(\.{"\ "})$;\5 -$\\{print\_int}(\|t-1)$;\6 -\&{end};\2\6 -\&{if} $\|q\I\\{null}$ \1\&{then}\6 -\&{begin} \37\X401:Print the turns, if any, that start at \|q, and advance \|q% -\X;\6 -$\\{print\_char}(\.{"\ "})$;\5 -$\\{print}(\\{octant\_dir}[\\{left\_octant}(\|q)])$;\5 -$\|q\K\\{null}$;\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \&{if} $\|q=\\{null}$ \1\&{then}\5 -$\|q\K\|p$;\2\2\6 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\|p=\|f$;\2\6 -$\\{print\_char}(\.{"\ "})$;\5 -$\\{print\_int}(\\{left\_type}(\|p)-1)$;\6 -\&{if} $\|q\I\\{null}$ \1\&{then}\5 -\X401:Print the turns, if any, that start at \|q, and advance \|q\X;\2\6 -$\\{print\_err}(\|s)$;\6 -\&{end};\par -\fi - -\M399. If the segment numbers on the cycle are $t_1$, $t_2$, \dots, $t_m$, -we have $t_{k-1}\L t_k$ except for at most one value of~$k$. If there are -no exceptions, $f$ will point to $t_1$; otherwise it will point to the -exceptional~$t_k$. - -There is at least one segment number (i.e., we always have $m>0$), because -\\{print\_strange} is never called upon to display an entirely ``dead'' cycle. - -\Y\P$\4\X399:Find the starting point, \|f\X\S$\6 -$\|p\K\\{cur\_spec}$;\5 -$\|t\K\\{max\_quarterword}+1$;\6 -\1\&{repeat} \37$\|p\K\\{link}(\|p)$;\6 -\&{if} $\\{left\_type}(\|p)\I\\{endpoint}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{left\_type}(\|p)<\|t$ \1\&{then}\5 -$\|f\K\|p$;\2\6 -$\|t\K\\{left\_type}(\|p)$;\6 -\&{end};\2\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$\2\par -\U398.\fi - -\M400. \P$\X400:Determine the octant boundary \|q that precedes \|f\X\S$\6 -$\|p\K\\{cur\_spec}$;\5 -$\|q\K\|p$;\6 -\1\&{repeat} \37$\|p\K\\{link}(\|p)$;\6 -\&{if} $\\{left\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -$\|q\K\|p$;\2\6 -\4\&{until}\5 -$\|p=\|f$\2\par -\U398.\fi - -\M401. When two octant boundaries are adjacent, the path is simply changing -direction -without moving. Such octant directions are shown in parentheses. - -\Y\P$\4\X401:Print the turns, if any, that start at \|q, and advance \|q\X\S$\6 -\&{if} $\\{left\_type}(\\{link}(\|q))=\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\ ("})$;\5 -$\\{print}(\\{octant\_dir}[\\{left\_octant}(\|q)])$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{while} $\\{left\_type}(\\{link}(\|q))=\\{endpoint}$ \1\&{do}\6 -\&{begin} \37$\\{print\_char}(\.{"\ "})$;\5 -$\\{print}(\\{octant\_dir}[\\{left\_octant}(\|q)])$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -$\\{print\_char}(\.{")"})$;\6 -\&{end}\2\par -\Us398\ET398.\fi - -\M402. The \\{make\_spec} routine is what subdivides paths into octants: -Given a pointer \\{cur\_spec} to a cyclic path, \\{make\_spec} mungs the path -data -and returns a pointer to the corresponding cyclic spec. -All ``dead'' cubics (i.e., cubics that don't move at all from -their starting points) will have been removed from the result. - -The idea of \\{make\_spec} is fairly simple: Each cubic is first -subdivided, if necessary, into pieces belonging to single octants; -then the octant boundaries are inserted. But some of the details of -this transformation are not quite obvious. - -If $\\{autorounding}>0$, the path will be adjusted so that critical tangent -directions occur at ``good'' points with respect to the pen called \\{cur% -\_pen}. - -The resulting spec will have all \|x and \|y coordinates at most -$2^{28}-\\{half\_unit}-1-\\{safety\_margin}$ in absolute value. The pointer -that is returned will start some octant, as required by \\{print\_spec}. - -\Y\P\hbox{\4}\X405:Declare subroutines needed by \\{make\_spec}\X\6 -\4\&{function}\1\ \37$\\{make\_spec}(\|h:\\{pointer};\,\35\\{safety\_margin}:% -\\{scaled};\,\35\\{tracing}:\\{integer})$: \37\\{pointer};\C{converts a path to -a cycle spec}\6 -\4\&{label} \37$\\{continue},\39\\{done}$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{for traversing the -lists}\6 -\|k: \37\\{integer};\C{serial number of path segment, or octant code}\6 -\\{chopped}: \37\\{integer};\C{positive if data truncated, negative -if data dangerously large}\6 -\X453:Other local variables for \\{make\_spec}\X\2\6 -\&{begin} \37$\\{cur\_spec}\K\|h$;\6 -\&{if} $\\{tracing}>0$ \1\&{then}\5 -$\\{print\_path}(\\{cur\_spec},\39\.{",\ before\ subdivision\ into\ octants"},% -\39\\{true})$;\2\6 -$\\{max\_allowed}\K\\{fraction\_one}-\\{half\_unit}-1-\\{safety\_margin}$;\5 -\X404:Truncate the values of all coordinates that exceed \\{max\_allowed}, and -stamp segment numbers in each \\{left\_type} field\X;\6 -\\{quadrant\_subdivide};\C{subdivide each cubic into pieces belonging to -quadrants}\6 -\&{if} $(\\{internal}[\\{autorounding}]>0)\W(\\{chopped}=0)$ \1\&{then}\5 -\\{xy\_round};\2\6 -\\{octant\_subdivide};\C{complete the subdivision}\6 -\&{if} $(\\{internal}[\\{autorounding}]>\\{unity})\W(\\{chopped}=0)$ \1\&{then}% -\5 -\\{diag\_round};\2\6 -\X447:Remove dead cubics\X;\6 -\X450:Insert octant boundaries and compute the turning number\X;\6 -\&{while} $\\{left\_type}(\\{cur\_spec})\I\\{endpoint}$ \1\&{do}\5 -$\\{cur\_spec}\K\\{link}(\\{cur\_spec})$;\2\6 -\&{if} $\\{tracing}>0$ \1\&{then}\6 -\&{if} $(\\{internal}[\\{autorounding}]\L0)\V(\\{chopped}\I0)$ \1\&{then}\5 -$\\{print\_spec}(\.{",\ after\ subdivision"})$\6 -\4\&{else} \&{if} $\\{internal}[\\{autorounding}]>\\{unity}$ \1\&{then}\5 -$\\{print\_spec}(\.{",\ after\ subdivision\ and\ double\ autorounding"})$\6 -\4\&{else} $\\{print\_spec}(\.{",\ after\ subdivision\ and\ autorounding"})$;\2% -\2\2\6 -$\\{make\_spec}\K\\{cur\_spec}$;\6 -\&{end};\par -\fi - -\M403. The \\{make\_spec} routine has an interesting side effect, namely to set -the global variable \\{turning\_number} to the number of times the tangent -vector of the given cyclic path winds around the origin. - -Another global variable \\{cur\_spec} points to the specification as it is -being made, since several subroutines must go to work on it. - -And there are two global variables that affect the rounding -decisions, as we'll see later; they are called \\{cur\_pen} and \\{cur\_path% -\_type}. -The latter will be \\{double\_path\_code} if \\{make\_spec} is being -applied to a double path. - -\Y\P\D \37$\\{double\_path\_code}=0$\C{command modifier for `\&{doublepath}'}% -\par -\P\D \37$\\{contour\_code}=1$\C{command modifier for `\&{contour}'}\par -\P\D \37$\\{also\_code}=2$\C{command modifier for `\&{also}'}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{cur\_spec}: \37\\{pointer};\C{the principal output of \\{make\_spec}}\6 -\4\\{turning\_number}: \37\\{integer};\C{another output of \\{make\_spec}}\6 -\4\\{cur\_pen}: \37\\{pointer};\C{an implicit input of \\{make\_spec}, used in -autorounding}\6 -\4\\{cur\_path\_type}: \37$\\{double\_path\_code}\to\\{contour\_code}$;% -\C{likewise}\6 -\4\\{max\_allowed}: \37\\{scaled};\C{coordinates must be at most this big}\par -\fi - -\M404. First we do a simple preprocessing step. The segment numbers inserted -here will propagate to all descendants of cubics that are split into -subintervals. These numbers must be nonzero, but otherwise they are -present merely for diagnostic purposes. The cubic from \|p to~\|q -that represents ``time interval'' $(\|t-1)\to\|t$ usually has $\\{right\_type}(% -\|q)=\|t$, -except when \|t is too large to be stored in a quarterword. - -\Y\P\D \37$\\{procrustes}(\#)\S$\ \&{if} $\\{abs}(\#)\G\\{dmax}$ \1\&{then}\6 -\&{if} $\\{abs}(\#)>\\{max\_allowed}$ \1\&{then}\6 -\&{begin} \37$\\{chopped}\K1$;\6 -\&{if} $\#>0$ \1\&{then}\5 -$\#\K\\{max\_allowed}$\ \&{else} $\#\K-\\{max\_allowed}$;\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{chopped}=0$ \1\&{then}\5 -$\\{chopped}\K-1$\2\2\2\par -\Y\P$\4\X404:Truncate the values of all coordinates that exceed \\{max% -\_allowed}, and stamp segment numbers in each \\{left\_type} field\X\S$\6 -$\|p\K\\{cur\_spec}$;\5 -$\|k\K1$;\5 -$\\{chopped}\K0$;\5 -$\\{dmax}\K\\{max\_allowed}/2$;\6 -\1\&{repeat} \37$\\{procrustes}(\\{left\_x}(\|p))$;\5 -$\\{procrustes}(\\{left\_y}(\|p))$;\5 -$\\{procrustes}(\\{x\_coord}(\|p))$;\5 -$\\{procrustes}(\\{y\_coord}(\|p))$;\5 -$\\{procrustes}(\\{right\_x}(\|p))$;\5 -$\\{procrustes}(\\{right\_y}(\|p))$;\6 -$\|p\K\\{link}(\|p)$;\5 -$\\{left\_type}(\|p)\K\|k$;\6 -\&{if} $\|k<\\{max\_quarterword}$ \1\&{then}\5 -$\\{incr}(\|k)$\ \&{else} $\|k\K1$;\2\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\6 -\&{if} $\\{chopped}>0$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Curve\ out\ of\ range"})$;\5 -$\\{help4}(\.{"At\ least\ one\ of\ the\ coordinates\ in\ the\ path\ I\'m\ about% -\ to"})$\6 -$(\.{"digitize\ was\ really\ huge\ (potentially\ bigger\ than\ 4095)."})$\6 -$(\.{"So\ I\'ve\ cut\ it\ back\ to\ the\ maximum\ size."})$\6 -$(\.{"The\ results\ will\ probably\ be\ pretty\ wild."})$;\5 -\\{put\_get\_error};\6 -\&{end}\2\par -\U402.\fi - -\M405. We may need to get rid of constant ``dead'' cubics that clutter up -the data structure and interfere with autorounding. - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\S$\6 -\4\&{procedure}\1\ \37$\\{remove\_cubic}(\|p:\\{pointer})$;\C{removes the -cubic following~\|p}\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the node that disappears}\2\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\5 -$\\{right\_type}(\|p)\K\\{right\_type}(\|q)$;\5 -$\\{link}(\|p)\K\\{link}(\|q)$;\6 -$\\{x\_coord}(\|p)\K\\{x\_coord}(\|q)$;\5 -$\\{y\_coord}(\|p)\K\\{y\_coord}(\|q)$;\6 -$\\{right\_x}(\|p)\K\\{right\_x}(\|q)$;\5 -$\\{right\_y}(\|p)\K\\{right\_y}(\|q)$;\6 -$\\{free\_node}(\|q,\39\\{knot\_node\_size})$;\6 -\&{end};\par -\As406, 419, 426, 429, 431, 432, 433, 440\ETs451. -\U402.\fi - -\M406. The subdivision process proceeds by first swapping $x\swap-x$, if -necessary, to ensure that $x'\G0$; then swapping $y\swap-y$, if necessary, -to ensure that $y'\G0$; and finally swapping $x\swap y$, if necessary, -to ensure that $x'\G y'$. - -Recall that the octant codes have been defined in such a way that, for -example, $\\{third\_octant}=\\{first\_octant}+\\{negate\_x}+\\{switch\_x\_and% -\_y}$. The program -uses the fact that $\\{negate\_x}<\\{negate\_y}<\\{switch\_x\_and\_y}$ to -handle ``double -negation'': If \|c is an octant code that possibly involves \\{negate\_x} -and/or \\{negate\_y}, but not \\{switch\_x\_and\_y}, then negating~\|y changes~% -\|c -either to $\|c+\\{negate\_y}$ or $\|c-\\{negate\_y}$, depending on whether -$\|c\L\\{negate\_y}$ or $\|c>\\{negate\_y}$. Octant codes are always greater -than zero. - -The first step is to subdivide on \|x and \|y only, so that horizontal -and vertical autorounding can be done before we compare $x'$ to $y'$. - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\hbox{\4}\X410:Declare the procedure called \\{split\_cubic}\X\6 -\4\&{procedure}\1\ \37\\{quadrant\_subdivide};\6 -\4\&{label} \37$\\{continue},\39\\{exit}$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s,\39\\{pp},\39\\{qq}$: \37\\{pointer};% -\C{for traversing the lists}\6 -$\\{first\_x},\39\\{first\_y}$: \37\\{scaled};\C{unnegated coordinates of node % -\\{cur\_spec}}\6 -$\\{del1},\39\\{del2},\39\\{del3},\39\\{del},\39\\{dmax}$: \37\\{scaled};% -\C{proportional to the control points of a quadratic derived from a cubic}\6 -\|t: \37\\{fraction};\C{where a quadratic crosses zero}\6 -$\\{dest\_x},\39\\{dest\_y}$: \37\\{scaled};\C{final values of \|x and \|y in -the current cubic}\6 -\\{constant\_x}: \37\\{boolean};\C{is \|x constant between \|p and \|q?}\2\6 -\&{begin} \37$\|p\K\\{cur\_spec}$;\5 -$\\{first\_x}\K\\{x\_coord}(\\{cur\_spec})$;\5 -$\\{first\_y}\K\\{y\_coord}(\\{cur\_spec})$;\6 -\1\&{repeat} \37\\{continue}: \37$\|q\K\\{link}(\|p)$;\5 -\X407:Subdivide the cubic between \|p and \|q so that the results travel toward -the right halfplane\X;\6 -\X413:Subdivide all cubics between \|p and \|q so that the results travel -toward the first quadrant; but \&{return} or \&{goto} \\{continue} if the cubic -from \|p to \|q was dead\X;\6 -$\|p\K\|q$;\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M407. All three subdivision processes are similar, so it's possible to -get the general idea by studying the first one (which is the simplest). -The calculation makes use of the fact that the derivatives of -Bernshte{\u\i}n polynomials satisfy -$B'(z_0,z_1,\ldots,z_n;t)=nB(z_1-z_0,\ldots,z_n-z_{n-1};t)$. - -When this routine begins, $\\{right\_type}(\|p)$ is \\{explicit}; we should -set $\\{right\_type}(\|p)\K\\{first\_octant}$. However, no assignment is made, -because $\\{explicit}=\\{first\_octant}$. The author apologizes for using -such trickery here; it is really hard to do redundant computations -just for the sake of purity. - -\Y\P$\4\X407:Subdivide the cubic between \|p and \|q so that the results travel -toward the right halfplane\X\S$\6 -\&{if} $\|q=\\{cur\_spec}$ \1\&{then}\6 -\&{begin} \37$\\{dest\_x}\K\\{first\_x}$;\5 -$\\{dest\_y}\K\\{first\_y}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{dest\_x}\K\\{x\_coord}(\|q)$;\5 -$\\{dest\_y}\K\\{y\_coord}(\|q)$;\6 -\&{end};\2\6 -$\\{del1}\K\\{right\_x}(\|p)-\\{x\_coord}(\|p)$;\5 -$\\{del2}\K\\{left\_x}(\|q)-\\{right\_x}(\|p)$;\5 -$\\{del3}\K\\{dest\_x}-\\{left\_x}(\|q)$;\5 -\X408:Scale up \\{del1}, \\{del2}, and \\{del3} for greater accuracy; also set % -\\{del} to the first nonzero element of $(\\{del1},\\{del2},\\{del3})$\X;\6 -\&{if} $\\{del}=0$ \1\&{then}\5 -$\\{constant\_x}\K\\{true}$\6 -\4\&{else} \&{begin} \37$\\{constant\_x}\K\\{false}$;\6 -\&{if} $\\{del}<0$ \1\&{then}\5 -\X409:Complement the \|x coordinates of the cubic between \|p and~\|q\X;\2\6 -$\|t\K\\{crossing\_point}(\\{del1},\39\\{del2},\39\\{del3})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\5 -\X411:Subdivide the cubic with respect to $x'$, possibly twice\X;\2\6 -\&{end}\2\par -\U406.\fi - -\M408. If $\\{del1}=\\{del2}=\\{del3}=0$, it's impossible to obey the title of -this -section. We just set $\\{del}=0$ in that case. - -\Y\P$\4\X408:Scale up \\{del1}, \\{del2}, and \\{del3} for greater accuracy; -also set \\{del} to the first nonzero element of $(\\{del1},\\{del2},\\{del3})$% -\X\S$\6 -\&{if} $\\{del1}\I0$ \1\&{then}\5 -$\\{del}\K\\{del1}$\6 -\4\&{else} \&{if} $\\{del2}\I0$ \1\&{then}\5 -$\\{del}\K\\{del2}$\6 -\4\&{else} $\\{del}\K\\{del3}$;\2\2\6 -\&{if} $\\{del}\I0$ \1\&{then}\6 -\&{begin} \37$\\{dmax}\K\\{abs}(\\{del1})$;\6 -\&{if} $\\{abs}(\\{del2})>\\{dmax}$ \1\&{then}\5 -$\\{dmax}\K\\{abs}(\\{del2})$;\2\6 -\&{if} $\\{abs}(\\{del3})>\\{dmax}$ \1\&{then}\5 -$\\{dmax}\K\\{abs}(\\{del3})$;\2\6 -\&{while} $\\{dmax}<\\{fraction\_half}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\\{dmax})$;\5 -$\\{double}(\\{del1})$;\5 -$\\{double}(\\{del2})$;\5 -$\\{double}(\\{del3})$;\6 -\&{end};\2\6 -\&{end}\2\par -\Us407, 413\ETs420.\fi - -\M409. During the subdivision phases of \\{make\_spec}, the \\{x\_coord} and % -\\{y\_coord} -fields of node~\|q are not transformed to agree with the octant -stated in $\\{right\_type}(\|p)$; they remain consistent with $\\{right\_type}(% -\|q)$. -But $\\{left\_x}(\|q)$ and $\\{left\_y}(\|q)$ are governed by $\\{right\_type}(% -\|p)$. - -\Y\P$\4\X409:Complement the \|x coordinates of the cubic between \|p and~\|q\X% -\S$\6 -\&{begin} \37$\\{negate}(\\{x\_coord}(\|p))$;\5 -$\\{negate}(\\{right\_x}(\|p))$;\5 -$\\{negate}(\\{left\_x}(\|q))$;\6 -$\\{negate}(\\{del1})$;\5 -$\\{negate}(\\{del2})$;\5 -$\\{negate}(\\{del3})$;\6 -$\\{negate}(\\{dest\_x})$;\5 -$\\{right\_type}(\|p)\K\\{first\_octant}+\\{negate\_x}$;\6 -\&{end}\par -\U407.\fi - -\M410. When a cubic is split at a \\{fraction} value \|t, we obtain two cubics -whose B\'ezier control points are obtained by a generalization of the -bisection process: The formula -`$z_k^{(j+1)}={1\over2}(z_k^{(j)}+z\k^{(j)})$' becomes -`$z_k^{(j+1)}=t[z_k^{(j)},z\k^{(j)}]$'. - -It is convenient to define a \.{WEB} macro \\{t\_of\_the\_way} such that -$\\{t\_of\_the\_way}(\|a)(\|b)$ expands to $\|a-(\|a-\|b)\ast\|t$, i.e., to $% -\|t[\|a,\|b]$. - -If $0\L\|t\L1$, the quantity $\|t[\|a,\|b]$ is always between \|a and~\|b, even -in -the presence of rounding errors. Our subroutines -also obey the identity $\|t[\|a,\|b]+\|t[\|b,\|a]=\|a+\|b$. - -\Y\P\D \37$\\{t\_of\_the\_way\_end}(\#)\S\#,\39\|t\={)}$\par -\P\D \37$\\{t\_of\_the\_way}(\#)\S\#-\\{take\_fraction}\={(}\#-\\{t\_of\_the% -\_way\_end}$\par -\Y\P$\4\X410:Declare the procedure called \\{split\_cubic}\X\S$\6 -\4\&{procedure}\1\ \37$\\{split\_cubic}(\|p:\\{pointer};\,\35\|t:\\{fraction};% -\,\35\\{xq},\39\\{yq}:\\{scaled})$;\C{splits the cubic after \|p}\6 -\4\&{var} \37\|v: \37\\{scaled};\C{an intermediate value}\6 -$\|q,\39\|r$: \37\\{pointer};\C{for list manipulation}\2\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\5 -$\|r\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{link}(\|p)\K\|r$;\5 -$\\{link}(\|r)\K\|q$;\6 -$\\{left\_type}(\|r)\K\\{left\_type}(\|q)$;\5 -$\\{right\_type}(\|r)\K\\{right\_type}(\|p)$;\7 -$\|v\K\\{t\_of\_the\_way}(\\{right\_x}(\|p))(\\{left\_x}(\|q))$;\5 -$\\{right\_x}(\|p)\K\\{t\_of\_the\_way}(\\{x\_coord}(\|p))(\\{right\_x}(\|p))$;% -\5 -$\\{left\_x}(\|q)\K\\{t\_of\_the\_way}(\\{left\_x}(\|q))(\\{xq})$;\5 -$\\{left\_x}(\|r)\K\\{t\_of\_the\_way}(\\{right\_x}(\|p))(\|v)$;\5 -$\\{right\_x}(\|r)\K\\{t\_of\_the\_way}(\|v)(\\{left\_x}(\|q))$;\5 -$\\{x\_coord}(\|r)\K\\{t\_of\_the\_way}(\\{left\_x}(\|r))(\\{right\_x}(\|r))$;\7 -$\|v\K\\{t\_of\_the\_way}(\\{right\_y}(\|p))(\\{left\_y}(\|q))$;\5 -$\\{right\_y}(\|p)\K\\{t\_of\_the\_way}(\\{y\_coord}(\|p))(\\{right\_y}(\|p))$;% -\5 -$\\{left\_y}(\|q)\K\\{t\_of\_the\_way}(\\{left\_y}(\|q))(\\{yq})$;\5 -$\\{left\_y}(\|r)\K\\{t\_of\_the\_way}(\\{right\_y}(\|p))(\|v)$;\5 -$\\{right\_y}(\|r)\K\\{t\_of\_the\_way}(\|v)(\\{left\_y}(\|q))$;\5 -$\\{y\_coord}(\|r)\K\\{t\_of\_the\_way}(\\{left\_y}(\|r))(\\{right\_y}(\|r))$;\6 -\&{end};\par -\U406.\fi - -\M411. Since $x'(t)$ is a quadratic equation, it can cross through zero -at~most twice. When it does cross zero, we make doubly sure that the -derivative is really zero at the splitting point, in case rounding errors -have caused the split cubic to have an apparently nonzero derivative. -We also make sure that the split cubic is monotonic. - -\Y\P$\4\X411:Subdivide the cubic with respect to $x'$, possibly twice\X\S$\6 -\&{begin} \37$\\{split\_cubic}(\|p,\39\|t,\39\\{dest\_x},\39\\{dest\_y})$;\5 -$\|r\K\\{link}(\|p)$;\6 -\&{if} $\\{right\_type}(\|r)>\\{negate\_x}$ \1\&{then}\5 -$\\{right\_type}(\|r)\K\\{first\_octant}$\6 -\4\&{else} $\\{right\_type}(\|r)\K\\{first\_octant}+\\{negate\_x}$;\2\6 -\&{if} $\\{x\_coord}(\|r)<\\{x\_coord}(\|p)$ \1\&{then}\5 -$\\{x\_coord}(\|r)\K\\{x\_coord}(\|p)$;\2\6 -$\\{left\_x}(\|r)\K\\{x\_coord}(\|r)$;\6 -\&{if} $\\{right\_x}(\|p)>\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{right\_x}(\|p)\K\\{x\_coord}(\|r)$;\C{we always have $\\{x\_coord}(\|p)\L% -\\{right\_x}(\|p)$}\2\6 -$\\{negate}(\\{x\_coord}(\|r))$;\5 -$\\{right\_x}(\|r)\K\\{x\_coord}(\|r)$;\5 -$\\{negate}(\\{left\_x}(\|q))$;\5 -$\\{negate}(\\{dest\_x})$;\6 -$\\{del2}\K\\{t\_of\_the\_way}(\\{del2})(\\{del3})$;\C{now $0,\\{del2},% -\\{del3}$ represent $x'$ on the remaining interval}\6 -\&{if} $\\{del2}>0$ \1\&{then}\5 -$\\{del2}\K0$;\2\6 -$\|t\K\\{crossing\_point}(0,\39-\\{del2},\39-\\{del3})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\5 -\X412:Subdivide the cubic a second time with respect to $x'$\X\6 -\4\&{else} \&{begin} \37\&{if} $\\{x\_coord}(\|r)>\\{dest\_x}$ \1\&{then}\6 -\&{begin} \37$\\{x\_coord}(\|r)\K\\{dest\_x}$;\5 -$\\{left\_x}(\|r)\K-\\{x\_coord}(\|r)$;\5 -$\\{right\_x}(\|r)\K\\{x\_coord}(\|r)$;\6 -\&{end};\2\6 -\&{if} $\\{left\_x}(\|q)>\\{dest\_x}$ \1\&{then}\5 -$\\{left\_x}(\|q)\K\\{dest\_x}$\6 -\4\&{else} \&{if} $\\{left\_x}(\|q)<\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{left\_x}(\|q)\K\\{x\_coord}(\|r)$;\2\2\6 -\&{end};\2\6 -\&{end}\par -\U407.\fi - -\M412. \P$\X412:Subdivide the cubic a second time with respect to $x'$\X\S$\6 -\&{begin} \37$\\{split\_cubic}(\|r,\39\|t,\39\\{dest\_x},\39\\{dest\_y})$;\5 -$\|s\K\\{link}(\|r)$;\6 -\&{if} $\\{x\_coord}(\|s)<\\{dest\_x}$ \1\&{then}\5 -$\\{x\_coord}(\|s)\K\\{dest\_x}$;\2\6 -\&{if} $\\{x\_coord}(\|s)<\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{x\_coord}(\|s)\K\\{x\_coord}(\|r)$;\2\6 -$\\{right\_type}(\|s)\K\\{right\_type}(\|p)$;\5 -$\\{left\_x}(\|s)\K\\{x\_coord}(\|s)$;\C{now $\\{x\_coord}(\|r)=\\{right\_x}(% -\|r)\L\\{left\_x}(\|s)$}\6 -\&{if} $\\{left\_x}(\|q)<\\{dest\_x}$ \1\&{then}\5 -$\\{left\_x}(\|q)\K-\\{dest\_x}$\6 -\4\&{else} \&{if} $\\{left\_x}(\|q)>\\{x\_coord}(\|s)$ \1\&{then}\5 -$\\{left\_x}(\|q)\K-\\{x\_coord}(\|s)$\6 -\4\&{else} $\\{negate}(\\{left\_x}(\|q))$;\2\2\6 -$\\{negate}(\\{x\_coord}(\|s))$;\5 -$\\{right\_x}(\|s)\K\\{x\_coord}(\|s)$;\6 -\&{end}\par -\U411.\fi - -\M413. The process of subdivision with respect to $y'$ is like that with -respect -to~$x'$, with the slight additional complication that two or three cubics -might now appear between \|p and~\|q. - -\Y\P$\4\X413:Subdivide all cubics between \|p and \|q so that the results -travel toward the first quadrant; but \&{return} or \&{goto} \\{continue} if -the cubic from \|p to \|q was dead\X\S$\6 -$\\{pp}\K\|p$;\6 -\1\&{repeat} \37$\\{qq}\K\\{link}(\\{pp})$;\5 -$\\{abnegate}(\\{x\_coord}(\\{qq}),\39\\{y\_coord}(\\{qq}),\39\\{right\_type}(% -\\{qq}),\39\\{right\_type}(\\{pp}))$;\5 -$\\{dest\_x}\K\\{cur\_x}$;\5 -$\\{dest\_y}\K\\{cur\_y}$;\6 -$\\{del1}\K\\{right\_y}(\\{pp})-\\{y\_coord}(\\{pp})$;\5 -$\\{del2}\K\\{left\_y}(\\{qq})-\\{right\_y}(\\{pp})$;\5 -$\\{del3}\K\\{dest\_y}-\\{left\_y}(\\{qq})$;\5 -\X408:Scale up \\{del1}, \\{del2}, and \\{del3} for greater accuracy; also set % -\\{del} to the first nonzero element of $(\\{del1},\\{del2},\\{del3})$\X;\6 -\&{if} $\\{del}\I0$ \1\&{then}\C{they weren't all zero}\6 -\&{begin} \37\&{if} $\\{del}<0$ \1\&{then}\5 -\X414:Complement the \|y coordinates of the cubic between \\{pp} and~\\{qq}\X;% -\2\6 -$\|t\K\\{crossing\_point}(\\{del1},\39\\{del2},\39\\{del3})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\5 -\X415:Subdivide the cubic with respect to $y'$, possibly twice\X;\2\6 -\&{end}\6 -\4\&{else} \X417:Do any special actions needed when \|y is constant; \&{return} -or \&{goto} \\{continue} if a dead cubic from \|p to \|q is removed\X;\2\6 -$\\{pp}\K\\{qq}$;\6 -\4\&{until}\5 -$\\{pp}=\|q$;\2\6 -\&{if} $\\{constant\_x}$ \1\&{then}\5 -\X418:Correct the octant code in segments with decreasing \|y\X\2\par -\U406.\fi - -\M414. \P$\X414:Complement the \|y coordinates of the cubic between \\{pp} and~% -\\{qq}\X\S$\6 -\&{begin} \37$\\{negate}(\\{y\_coord}(\\{pp}))$;\5 -$\\{negate}(\\{right\_y}(\\{pp}))$;\5 -$\\{negate}(\\{left\_y}(\\{qq}))$;\6 -$\\{negate}(\\{del1})$;\5 -$\\{negate}(\\{del2})$;\5 -$\\{negate}(\\{del3})$;\6 -$\\{negate}(\\{dest\_y})$;\5 -$\\{right\_type}(\\{pp})\K\\{right\_type}(\\{pp})+\\{negate\_y}$;\6 -\&{end}\par -\Us413\ET417.\fi - -\M415. \P$\X415:Subdivide the cubic with respect to $y'$, possibly twice\X\S$\6 -\&{begin} \37$\\{split\_cubic}(\\{pp},\39\|t,\39\\{dest\_x},\39\\{dest\_y})$;\5 -$\|r\K\\{link}(\\{pp})$;\6 -\&{if} $\\{right\_type}(\|r)>\\{negate\_y}$ \1\&{then}\5 -$\\{right\_type}(\|r)\K\\{right\_type}(\|r)-\\{negate\_y}$\6 -\4\&{else} $\\{right\_type}(\|r)\K\\{right\_type}(\|r)+\\{negate\_y}$;\2\6 -\&{if} $\\{y\_coord}(\|r)<\\{y\_coord}(\\{pp})$ \1\&{then}\5 -$\\{y\_coord}(\|r)\K\\{y\_coord}(\\{pp})$;\2\6 -$\\{left\_y}(\|r)\K\\{y\_coord}(\|r)$;\6 -\&{if} $\\{right\_y}(\\{pp})>\\{y\_coord}(\|r)$ \1\&{then}\5 -$\\{right\_y}(\\{pp})\K\\{y\_coord}(\|r)$;\C{we always have $\\{y\_coord}(% -\\{pp})\L\\{right\_y}(\\{pp})$}\2\6 -$\\{negate}(\\{y\_coord}(\|r))$;\5 -$\\{right\_y}(\|r)\K\\{y\_coord}(\|r)$;\5 -$\\{negate}(\\{left\_y}(\\{qq}))$;\5 -$\\{negate}(\\{dest\_y})$;\6 -\&{if} $\\{x\_coord}(\|r)<\\{x\_coord}(\\{pp})$ \1\&{then}\5 -$\\{x\_coord}(\|r)\K\\{x\_coord}(\\{pp})$\6 -\4\&{else} \&{if} $\\{x\_coord}(\|r)>\\{dest\_x}$ \1\&{then}\5 -$\\{x\_coord}(\|r)\K\\{dest\_x}$;\2\2\6 -\&{if} $\\{left\_x}(\|r)>\\{x\_coord}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{left\_x}(\|r)\K\\{x\_coord}(\|r)$;\6 -\&{if} $\\{right\_x}(\\{pp})>\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{right\_x}(\\{pp})\K\\{x\_coord}(\|r)$;\2\6 -\&{end};\2\6 -\&{if} $\\{right\_x}(\|r)<\\{x\_coord}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{right\_x}(\|r)\K\\{x\_coord}(\|r)$;\6 -\&{if} $\\{left\_x}(\\{qq})<\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{left\_x}(\\{qq})\K\\{x\_coord}(\|r)$;\2\6 -\&{end};\2\6 -$\\{del2}\K\\{t\_of\_the\_way}(\\{del2})(\\{del3})$;\C{now $0,\\{del2},% -\\{del3}$ represent $y'$ on the remaining interval}\6 -\&{if} $\\{del2}>0$ \1\&{then}\5 -$\\{del2}\K0$;\2\6 -$\|t\K\\{crossing\_point}(0,\39-\\{del2},\39-\\{del3})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\5 -\X416:Subdivide the cubic a second time with respect to $y'$\X\6 -\4\&{else} \&{begin} \37\&{if} $\\{y\_coord}(\|r)>\\{dest\_y}$ \1\&{then}\6 -\&{begin} \37$\\{y\_coord}(\|r)\K\\{dest\_y}$;\5 -$\\{left\_y}(\|r)\K-\\{y\_coord}(\|r)$;\5 -$\\{right\_y}(\|r)\K\\{y\_coord}(\|r)$;\6 -\&{end};\2\6 -\&{if} $\\{left\_y}(\\{qq})>\\{dest\_y}$ \1\&{then}\5 -$\\{left\_y}(\\{qq})\K\\{dest\_y}$\6 -\4\&{else} \&{if} $\\{left\_y}(\\{qq})<\\{y\_coord}(\|r)$ \1\&{then}\5 -$\\{left\_y}(\\{qq})\K\\{y\_coord}(\|r)$;\2\2\6 -\&{end};\2\6 -\&{end}\par -\U413.\fi - -\M416. \P$\X416:Subdivide the cubic a second time with respect to $y'$\X\S$\6 -\&{begin} \37$\\{split\_cubic}(\|r,\39\|t,\39\\{dest\_x},\39\\{dest\_y})$;\5 -$\|s\K\\{link}(\|r)$;\6 -\&{if} $\\{y\_coord}(\|s)<\\{dest\_y}$ \1\&{then}\5 -$\\{y\_coord}(\|s)\K\\{dest\_y}$;\2\6 -\&{if} $\\{y\_coord}(\|s)<\\{y\_coord}(\|r)$ \1\&{then}\5 -$\\{y\_coord}(\|s)\K\\{y\_coord}(\|r)$;\2\6 -$\\{right\_type}(\|s)\K\\{right\_type}(\\{pp})$;\5 -$\\{left\_y}(\|s)\K\\{y\_coord}(\|s)$;\C{now $\\{y\_coord}(\|r)=\\{right\_y}(% -\|r)\L\\{left\_y}(\|s)$}\6 -\&{if} $\\{left\_y}(\\{qq})<\\{dest\_y}$ \1\&{then}\5 -$\\{left\_y}(\\{qq})\K-\\{dest\_y}$\6 -\4\&{else} \&{if} $\\{left\_y}(\\{qq})>\\{y\_coord}(\|s)$ \1\&{then}\5 -$\\{left\_y}(\\{qq})\K-\\{y\_coord}(\|s)$\6 -\4\&{else} $\\{negate}(\\{left\_y}(\\{qq}))$;\2\2\6 -$\\{negate}(\\{y\_coord}(\|s))$;\5 -$\\{right\_y}(\|s)\K\\{y\_coord}(\|s)$;\6 -\&{if} $\\{x\_coord}(\|s)<\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{x\_coord}(\|s)\K\\{x\_coord}(\|r)$\6 -\4\&{else} \&{if} $\\{x\_coord}(\|s)>\\{dest\_x}$ \1\&{then}\5 -$\\{x\_coord}(\|s)\K\\{dest\_x}$;\2\2\6 -\&{if} $\\{left\_x}(\|s)>\\{x\_coord}(\|s)$ \1\&{then}\6 -\&{begin} \37$\\{left\_x}(\|s)\K\\{x\_coord}(\|s)$;\6 -\&{if} $\\{right\_x}(\|r)>\\{x\_coord}(\|s)$ \1\&{then}\5 -$\\{right\_x}(\|r)\K\\{x\_coord}(\|s)$;\2\6 -\&{end};\2\6 -\&{if} $\\{right\_x}(\|s)<\\{x\_coord}(\|s)$ \1\&{then}\6 -\&{begin} \37$\\{right\_x}(\|s)\K\\{x\_coord}(\|s)$;\6 -\&{if} $\\{left\_x}(\\{qq})<\\{x\_coord}(\|s)$ \1\&{then}\5 -$\\{left\_x}(\\{qq})\K\\{x\_coord}(\|s)$;\2\6 -\&{end};\2\6 -\&{end}\par -\U415.\fi - -\M417. If the cubic is constant in $y$ and increasing in $x$, we have -classified -it as traveling in the first octant. If the cubic is constant -in~$y$ and decreasing in~$x$, it is desirable to classify it as traveling -in the fifth octant (not the fourth), because autorounding will be consistent -with respect to doublepaths only if the octant number changes by four when -the path is reversed. Therefore we negate the $y$~coordinates -when they are constant but the curve is decreasing in~$x$; this gives -the desired result except in pathological paths. - -If the cubic is ``dead,'' i.e., constant in both \|x and \|y, we remove -it unless it is the only cubic in the entire path. We \&{goto} \\{continue} -if it wasn't the final cubic, so that the test $\|p=\\{cur\_spec}$ does not -falsely imply that all cubics have been processed. - -\Y\P$\4\X417:Do any special actions needed when \|y is constant; \&{return} or % -\&{goto} \\{continue} if a dead cubic from \|p to \|q is removed\X\S$\6 -\&{if} $\\{constant\_x}$ \1\&{then}\C{$\|p=\\{pp}$, $\|q=\\{qq}$, and the cubic -is dead}\6 -\&{begin} \37\&{if} $\|q\I\|p$ \1\&{then}\6 -\&{begin} \37$\\{remove\_cubic}(\|p)$;\C{remove the dead cycle and recycle node -\|q}\6 -\&{if} $\\{cur\_spec}\I\|q$ \1\&{then}\5 -\&{goto} \37\\{continue}\6 -\4\&{else} \&{begin} \37$\\{cur\_spec}\K\|p$;\5 -\&{return};\6 -\&{end};\C{the final cubic was dead and is gone}\2\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \&{if} $\R\\{odd}(\\{right\_type}(\\{pp}))$ \1\&{then}\C{the $x$ -coordinates were negated}\6 -\X414:Complement the \|y coordinates of the cubic between \\{pp} and~\\{qq}\X\2% -\2\par -\U413.\fi - -\M418. A similar correction to octant codes deserves to be made when \|x is -constant and \|y is decreasing. - -\Y\P$\4\X418:Correct the octant code in segments with decreasing \|y\X\S$\6 -\&{begin} \37$\\{pp}\K\|p$;\6 -\1\&{repeat} \37$\\{qq}\K\\{link}(\\{pp})$;\6 -\&{if} $\\{right\_type}(\\{pp})>\\{negate\_y}$ \1\&{then}\C{the $y$ coordinates -were negated}\6 -\&{begin} \37$\\{right\_type}(\\{pp})\K\\{right\_type}(\\{pp})+\\{negate\_x}$;\5 -$\\{negate}(\\{x\_coord}(\\{pp}))$;\5 -$\\{negate}(\\{right\_x}(\\{pp}))$;\5 -$\\{negate}(\\{left\_x}(\\{qq}))$;\6 -\&{end};\2\6 -$\\{pp}\K\\{qq}$;\6 -\4\&{until}\5 -$\\{pp}=\|q$;\2\6 -\&{end}\par -\U413.\fi - -\M419. Finally, the process of subdividing to make $x'\G y'$ is like the other -two subdivisions, with a few new twists. We skew the coordinates at this time. - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{octant\_subdivide};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{for traversing the -lists}\6 -$\\{del1},\39\\{del2},\39\\{del3},\39\\{del},\39\\{dmax}$: \37\\{scaled};% -\C{proportional to the control points of a quadratic derived from a cubic}\6 -\|t: \37\\{fraction};\C{where a quadratic crosses zero}\6 -$\\{dest\_x},\39\\{dest\_y}$: \37\\{scaled};\C{final values of \|x and \|y in -the current cubic}\2\6 -\&{begin} \37$\|p\K\\{cur\_spec}$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|p)$;\6 -$\\{x\_coord}(\|p)\K\\{x\_coord}(\|p)-\\{y\_coord}(\|p)$;\5 -$\\{right\_x}(\|p)\K\\{right\_x}(\|p)-\\{right\_y}(\|p)$;\5 -$\\{left\_x}(\|q)\K\\{left\_x}(\|q)-\\{left\_y}(\|q)$;\6 -\X420:Subdivide the cubic between \|p and \|q so that the results travel toward -the first octant\X;\6 -$\|p\K\|q$;\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\6 -\&{end};\par -\fi - -\M420. \P$\X420:Subdivide the cubic between \|p and \|q so that the results -travel toward the first octant\X\S$\6 -\X421:Set up the variables $(\\{del1},\\{del2},\\{del3})$ to represent $x'-y'$% -\X;\6 -\X408:Scale up \\{del1}, \\{del2}, and \\{del3} for greater accuracy; also set % -\\{del} to the first nonzero element of $(\\{del1},\\{del2},\\{del3})$\X;\6 -\&{if} $\\{del}\I0$ \1\&{then}\C{they weren't all zero}\6 -\&{begin} \37\&{if} $\\{del}<0$ \1\&{then}\5 -\X423:Swap the \|x and \|y coordinates of the cubic between \|p and~\|q\X;\2\6 -$\|t\K\\{crossing\_point}(\\{del1},\39\\{del2},\39\\{del3})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\5 -\X424:Subdivide the cubic with respect to $x'-y'$, possibly twice\X;\2\6 -\&{end}\2\par -\U419.\fi - -\M421. \P$\X421:Set up the variables $(\\{del1},\\{del2},\\{del3})$ to -represent $x'-y'$\X\S$\6 -\&{if} $\|q=\\{cur\_spec}$ \1\&{then}\6 -\&{begin} \37$\\{unskew}(\\{x\_coord}(\|q),\39\\{y\_coord}(\|q),\39\\{right% -\_type}(\|q))$;\5 -$\\{skew}(\\{cur\_x},\39\\{cur\_y},\39\\{right\_type}(\|p))$;\5 -$\\{dest\_x}\K\\{cur\_x}$;\5 -$\\{dest\_y}\K\\{cur\_y}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{abnegate}(\\{x\_coord}(\|q),\39\\{y\_coord}(\|q),% -\39\\{right\_type}(\|q),\39\\{right\_type}(\|p))$;\5 -$\\{dest\_x}\K\\{cur\_x}-\\{cur\_y}$;\5 -$\\{dest\_y}\K\\{cur\_y}$;\6 -\&{end};\2\6 -$\\{del1}\K\\{right\_x}(\|p)-\\{x\_coord}(\|p)$;\5 -$\\{del2}\K\\{left\_x}(\|q)-\\{right\_x}(\|p)$;\5 -$\\{del3}\K\\{dest\_x}-\\{left\_x}(\|q)$\par -\U420.\fi - -\M422. The swapping here doesn't simply interchange \|x and \|y values, -because the coordinates are skewed. It turns out that this is easier -than ordinary swapping, because it can be done in two assignment statements -rather than three. - -\fi - -\M423. \P$\X423:Swap the \|x and \|y coordinates of the cubic between \|p and~% -\|q\X\S$\6 -\&{begin} \37$\\{y\_coord}(\|p)\K\\{x\_coord}(\|p)+\\{y\_coord}(\|p)$;\5 -$\\{negate}(\\{x\_coord}(\|p))$;\6 -$\\{right\_y}(\|p)\K\\{right\_x}(\|p)+\\{right\_y}(\|p)$;\5 -$\\{negate}(\\{right\_x}(\|p))$;\6 -$\\{left\_y}(\|q)\K\\{left\_x}(\|q)+\\{left\_y}(\|q)$;\5 -$\\{negate}(\\{left\_x}(\|q))$;\6 -$\\{negate}(\\{del1})$;\5 -$\\{negate}(\\{del2})$;\5 -$\\{negate}(\\{del3})$;\6 -$\\{dest\_y}\K\\{dest\_x}+\\{dest\_y}$;\5 -$\\{negate}(\\{dest\_x})$;\6 -$\\{right\_type}(\|p)\K\\{right\_type}(\|p)+\\{switch\_x\_and\_y}$;\6 -\&{end}\par -\U420.\fi - -\M424. A somewhat tedious case analysis is carried out here to make sure that -nasty rounding errors don't destroy our assumptions of monotonicity. - -\Y\P$\4\X424:Subdivide the cubic with respect to $x'-y'$, possibly twice\X\S$\6 -\&{begin} \37$\\{split\_cubic}(\|p,\39\|t,\39\\{dest\_x},\39\\{dest\_y})$;\5 -$\|r\K\\{link}(\|p)$;\6 -\&{if} $\\{right\_type}(\|r)>\\{switch\_x\_and\_y}$ \1\&{then}\5 -$\\{right\_type}(\|r)\K\\{right\_type}(\|r)-\\{switch\_x\_and\_y}$\6 -\4\&{else} $\\{right\_type}(\|r)\K\\{right\_type}(\|r)+\\{switch\_x\_and\_y}$;% -\2\6 -\&{if} $\\{y\_coord}(\|r)<\\{y\_coord}(\|p)$ \1\&{then}\5 -$\\{y\_coord}(\|r)\K\\{y\_coord}(\|p)$\6 -\4\&{else} \&{if} $\\{y\_coord}(\|r)>\\{dest\_y}$ \1\&{then}\5 -$\\{y\_coord}(\|r)\K\\{dest\_y}$;\2\2\6 -\&{if} $\\{x\_coord}(\|p)+\\{y\_coord}(\|r)>\\{dest\_x}+\\{dest\_y}$ \1\&{then}% -\5 -$\\{y\_coord}(\|r)\K\\{dest\_x}+\\{dest\_y}-\\{x\_coord}(\|p)$;\2\6 -\&{if} $\\{left\_y}(\|r)>\\{y\_coord}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{left\_y}(\|r)\K\\{y\_coord}(\|r)$;\6 -\&{if} $\\{right\_y}(\|p)>\\{y\_coord}(\|r)$ \1\&{then}\5 -$\\{right\_y}(\|p)\K\\{y\_coord}(\|r)$;\2\6 -\&{end};\2\6 -\&{if} $\\{right\_y}(\|r)<\\{y\_coord}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{right\_y}(\|r)\K\\{y\_coord}(\|r)$;\6 -\&{if} $\\{left\_y}(\|q)<\\{y\_coord}(\|r)$ \1\&{then}\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|r)$;\2\6 -\&{end};\2\6 -\&{if} $\\{x\_coord}(\|r)<\\{x\_coord}(\|p)$ \1\&{then}\5 -$\\{x\_coord}(\|r)\K\\{x\_coord}(\|p)$\6 -\4\&{else} \&{if} $\\{x\_coord}(\|r)+\\{y\_coord}(\|r)>\\{dest\_x}+\\{dest\_y}$ -\1\&{then}\5 -$\\{x\_coord}(\|r)\K\\{dest\_x}+\\{dest\_y}-\\{y\_coord}(\|r)$;\2\2\6 -$\\{left\_x}(\|r)\K\\{x\_coord}(\|r)$;\6 -\&{if} $\\{right\_x}(\|p)>\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{right\_x}(\|p)\K\\{x\_coord}(\|r)$;\C{we always have $\\{x\_coord}(\|p)\L% -\\{right\_x}(\|p)$}\2\6 -$\\{y\_coord}(\|r)\K\\{y\_coord}(\|r)+\\{x\_coord}(\|r)$;\5 -$\\{right\_y}(\|r)\K\\{right\_y}(\|r)+\\{x\_coord}(\|r)$;\6 -$\\{negate}(\\{x\_coord}(\|r))$;\5 -$\\{right\_x}(\|r)\K\\{x\_coord}(\|r)$;\6 -$\\{left\_y}(\|q)\K\\{left\_y}(\|q)+\\{left\_x}(\|q)$;\5 -$\\{negate}(\\{left\_x}(\|q))$;\6 -$\\{dest\_y}\K\\{dest\_y}+\\{dest\_x}$;\5 -$\\{negate}(\\{dest\_x})$;\6 -\&{if} $\\{right\_y}(\|r)<\\{y\_coord}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{right\_y}(\|r)\K\\{y\_coord}(\|r)$;\6 -\&{if} $\\{left\_y}(\|q)<\\{y\_coord}(\|r)$ \1\&{then}\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|r)$;\2\6 -\&{end};\2\6 -$\\{del2}\K\\{t\_of\_the\_way}(\\{del2})(\\{del3})$;\C{now $0,\\{del2},% -\\{del3}$ represent $x'-y'$ on the remaining interval}\6 -\&{if} $\\{del2}>0$ \1\&{then}\5 -$\\{del2}\K0$;\2\6 -$\|t\K\\{crossing\_point}(0,\39-\\{del2},\39-\\{del3})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\5 -\X425:Subdivide the cubic a second time with respect to $x'-y'$\X\6 -\4\&{else} \&{begin} \37\&{if} $\\{x\_coord}(\|r)>\\{dest\_x}$ \1\&{then}\6 -\&{begin} \37$\\{x\_coord}(\|r)\K\\{dest\_x}$;\5 -$\\{left\_x}(\|r)\K-\\{x\_coord}(\|r)$;\5 -$\\{right\_x}(\|r)\K\\{x\_coord}(\|r)$;\6 -\&{end};\2\6 -\&{if} $\\{left\_x}(\|q)>\\{dest\_x}$ \1\&{then}\5 -$\\{left\_x}(\|q)\K\\{dest\_x}$\6 -\4\&{else} \&{if} $\\{left\_x}(\|q)<\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{left\_x}(\|q)\K\\{x\_coord}(\|r)$;\2\2\6 -\&{end};\2\6 -\&{end}\par -\U420.\fi - -\M425. \P$\X425:Subdivide the cubic a second time with respect to $x'-y'$\X\S$\6 -\&{begin} \37$\\{split\_cubic}(\|r,\39\|t,\39\\{dest\_x},\39\\{dest\_y})$;\5 -$\|s\K\\{link}(\|r)$;\6 -\&{if} $\\{y\_coord}(\|s)<\\{y\_coord}(\|r)$ \1\&{then}\5 -$\\{y\_coord}(\|s)\K\\{y\_coord}(\|r)$\6 -\4\&{else} \&{if} $\\{y\_coord}(\|s)>\\{dest\_y}$ \1\&{then}\5 -$\\{y\_coord}(\|s)\K\\{dest\_y}$;\2\2\6 -\&{if} $\\{x\_coord}(\|r)+\\{y\_coord}(\|s)>\\{dest\_x}+\\{dest\_y}$ \1\&{then}% -\5 -$\\{y\_coord}(\|s)\K\\{dest\_x}+\\{dest\_y}-\\{x\_coord}(\|r)$;\2\6 -\&{if} $\\{left\_y}(\|s)>\\{y\_coord}(\|s)$ \1\&{then}\6 -\&{begin} \37$\\{left\_y}(\|s)\K\\{y\_coord}(\|s)$;\6 -\&{if} $\\{right\_y}(\|r)>\\{y\_coord}(\|s)$ \1\&{then}\5 -$\\{right\_y}(\|r)\K\\{y\_coord}(\|s)$;\2\6 -\&{end};\2\6 -\&{if} $\\{right\_y}(\|s)<\\{y\_coord}(\|s)$ \1\&{then}\6 -\&{begin} \37$\\{right\_y}(\|s)\K\\{y\_coord}(\|s)$;\6 -\&{if} $\\{left\_y}(\|q)<\\{y\_coord}(\|s)$ \1\&{then}\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|s)$;\2\6 -\&{end};\2\6 -\&{if} $\\{x\_coord}(\|s)+\\{y\_coord}(\|s)>\\{dest\_x}+\\{dest\_y}$ \1\&{then}% -\5 -$\\{x\_coord}(\|s)\K\\{dest\_x}+\\{dest\_y}-\\{y\_coord}(\|s)$\6 -\4\&{else} \&{begin} \37\&{if} $\\{x\_coord}(\|s)<\\{dest\_x}$ \1\&{then}\5 -$\\{x\_coord}(\|s)\K\\{dest\_x}$;\2\6 -\&{if} $\\{x\_coord}(\|s)<\\{x\_coord}(\|r)$ \1\&{then}\5 -$\\{x\_coord}(\|s)\K\\{x\_coord}(\|r)$;\2\6 -\&{end};\2\6 -$\\{right\_type}(\|s)\K\\{right\_type}(\|p)$;\5 -$\\{left\_x}(\|s)\K\\{x\_coord}(\|s)$;\C{now $\\{x\_coord}(\|r)=\\{right\_x}(% -\|r)\L\\{left\_x}(\|s)$}\6 -\&{if} $\\{left\_x}(\|q)<\\{dest\_x}$ \1\&{then}\6 -\&{begin} \37$\\{left\_y}(\|q)\K\\{left\_y}(\|q)+\\{dest\_x}$;\5 -$\\{left\_x}(\|q)\K-\\{dest\_x}$;\ \&{end}\6 -\4\&{else} \&{if} $\\{left\_x}(\|q)>\\{x\_coord}(\|s)$ \1\&{then}\6 -\&{begin} \37$\\{left\_y}(\|q)\K\\{left\_y}(\|q)+\\{x\_coord}(\|s)$;\5 -$\\{left\_x}(\|q)\K-\\{x\_coord}(\|s)$;\ \&{end}\6 -\4\&{else} \&{begin} \37$\\{left\_y}(\|q)\K\\{left\_y}(\|q)+\\{left\_x}(\|q)$;\5 -$\\{negate}(\\{left\_x}(\|q))$;\ \&{end};\2\2\6 -$\\{y\_coord}(\|s)\K\\{y\_coord}(\|s)+\\{x\_coord}(\|s)$;\5 -$\\{right\_y}(\|s)\K\\{right\_y}(\|s)+\\{x\_coord}(\|s)$;\6 -$\\{negate}(\\{x\_coord}(\|s))$;\5 -$\\{right\_x}(\|s)\K\\{x\_coord}(\|s)$;\6 -\&{if} $\\{right\_y}(\|s)<\\{y\_coord}(\|s)$ \1\&{then}\6 -\&{begin} \37$\\{right\_y}(\|s)\K\\{y\_coord}(\|s)$;\6 -\&{if} $\\{left\_y}(\|q)<\\{y\_coord}(\|s)$ \1\&{then}\5 -$\\{left\_y}(\|q)\K\\{y\_coord}(\|s)$;\2\6 -\&{end};\2\6 -\&{end}\par -\U424.\fi - -\M426. It's time now to consider ``autorounding,'' which tries to make -horizontal, -vertical, and diagonal tangents occur at places that will produce appropriate -images after the curve is digitized. - -The first job is to fix things so that $\|x(\|t)$ is an integer multiple of the -current ``granularity'' when the derivative $x'(t)$ crosses through zero. -The given cyclic path contains regions where $x'(t)\G0$ and regions -where $x'(t)\L0$. The \\{quadrant\_subdivide} routine is called into action -before any of the path coordinates have been skewed, but some of them -may have been negated. In regions where $x'(t)\G0$ we have $\\{right\_type}=% -\\{first\_octant}$ or $\\{right\_type}=\\{eighth\_octant}$; in regions where -$x'(t)\L0$, -we have $\\{right\_type}=\\{fifth\_octant}$ or $\\{right\_type}=\\{fourth% -\_octant}$. - -Within any such region the transformed $x$ values increase monotonically -from, say, $x_0$ to~$x_1$. We want to modify things by applying a linear -transformation to all $x$ coordinates in the region, after which -the $x$ values will increase monotonically from round$(x_0)$ to round$(x_1)$. - -This rounding scheme sounds quite simple, and it usually is. But several -complications can arise that might make the task more difficult. In the -first place, autorounding is inappropriate at cusps where $x'$ jumps -discontinuously past zero without ever being zero. In the second place, -the current pen might be unsymmetric in such a way that $x$ coordinates -should round differently when $x'$ becomes positive than when it becomes -negative. These considerations imply that round$(x_0)$ might be greater -than round$(x_1)$, even though $x_0\L x_1$; in such cases we do not want -to carry out the linear transformation. Furthermore, it's possible to have -round$(x_1)-\hbox{round} (x_0)$ positive but much greater than $x_1-x_0$; -then the transformation might distort the curve drastically, and again we -want to avoid it. Finally, the rounded points must be consistent between -adjacent regions, hence we can't transform one region without knowing -about its neighbors. - -To handle all these complications, we must first look at the whole -cycle and choose rounded $x$ values that are ``safe.'' The following -procedure does this: Given $m$~values $(b_0,b_1,\ldots,b_{m-1})$ before -rounding and $m$~corresponding values $(a_0,a_1,\ldots,a_{m-1})$ that would -be desirable after rounding, the \\{make\_safe} routine sets $a$'s to $b$'s -if necessary so that $0\L(a\k-a_k)/(b\k-b_k)\L2$ afterwards. It is -symmetric under cyclic permutation, reversal, and/or negation of the inputs. -(Instead of \|a, \|b, and~\|m, the program uses the names \\{after}, -\\{before}, and \\{cur\_rounding\_ptr}.) - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{make\_safe};\6 -\4\&{var} \37\|k: \37$0\to\\{max\_wiggle}$;\C{runs through the list of inputs}\6 -\\{all\_safe}: \37\\{boolean};\C{does everything look OK so far?}\6 -\\{next\_a}: \37\\{scaled};\C{$\\{after}[\|k]$ before it might have changed}\6 -$\\{delta\_a},\39\\{delta\_b}$: \37\\{scaled};\C{$\\{after}[\|k+1]-\\{after}[% -\|k]$ and $\\{before}[\|k+1]-\\{before}[\|k]$}\2\6 -\&{begin} \37$\\{before}[\\{cur\_rounding\_ptr}]\K\\{before}[0]$;\C{wrap -around}\6 -$\\{node\_to\_round}[\\{cur\_rounding\_ptr}]\K\\{node\_to\_round}[0]$;\6 -\1\&{repeat} \37$\\{after}[\\{cur\_rounding\_ptr}]\K\\{after}[0]$;\5 -$\\{all\_safe}\K\\{true}$;\5 -$\\{next\_a}\K\\{after}[0]$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{cur\_rounding\_ptr}-1$ \1\&{do}\6 -\&{begin} \37$\\{delta\_b}\K\\{before}[\|k+1]-\\{before}[\|k]$;\6 -\&{if} $\\{delta\_b}\G0$ \1\&{then}\5 -$\\{delta\_a}\K\\{after}[\|k+1]-\\{next\_a}$\6 -\4\&{else} $\\{delta\_a}\K\\{next\_a}-\\{after}[\|k+1]$;\2\6 -$\\{next\_a}\K\\{after}[\|k+1]$;\6 -\&{if} $(\\{delta\_a}<0)\V(\\{delta\_a}>\\{abs}(\\{delta\_b}+\\{delta\_b}))$ \1% -\&{then}\6 -\&{begin} \37$\\{all\_safe}\K\\{false}$;\5 -$\\{after}[\|k]\K\\{before}[\|k]$;\6 -\&{if} $\|k=\\{cur\_rounding\_ptr}-1$ \1\&{then}\5 -$\\{after}[0]\K\\{before}[0]$\6 -\4\&{else} $\\{after}[\|k+1]\K\\{before}[\|k+1]$;\2\6 -\&{end};\2\6 -\&{end};\2\6 -\4\&{until}\5 -\\{all\_safe};\2\6 -\&{end};\par -\fi - -\M427. The global arrays used by \\{make\_safe} are accompanied by an array of -pointers into the current knot list. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{before},\39\\{after}$: \37\&{array} $[0\to\\{max\_wiggle}]$ \1\&{of}\5 -\\{scaled};\C{data for \\{make\_safe}}\2\6 -\4\\{node\_to\_round}: \37\&{array} $[0\to\\{max\_wiggle}]$ \1\&{of}\5 -\\{pointer};\C{reference back to the path}\2\6 -\4\\{cur\_rounding\_ptr}: \37$0\to\\{max\_wiggle}$;\C{how many are being used}\6 -\4\\{max\_rounding\_ptr}: \37$0\to\\{max\_wiggle}$;\C{how many have been used}% -\par -\fi - -\M428. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{max\_rounding\_ptr}\K0$;\par -\fi - -\M429. New entries go into the tables via the \\{before\_and\_after} routine: - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{before\_and\_after}(\|b,\39\|a:\\{scaled};\,\35\|p:% -\\{pointer})$;\2\6 -\&{begin} \37\&{if} $\\{cur\_rounding\_ptr}=\\{max\_rounding\_ptr}$ \1\&{then}\6 -\&{if} $\\{max\_rounding\_ptr}<\\{max\_wiggle}$ \1\&{then}\5 -$\\{incr}(\\{max\_rounding\_ptr})$\6 -\4\&{else} $\\{overflow}(\.{"rounding\ table\ size"},\39\\{max\_wiggle})$;\2\2\6 -$\\{after}[\\{cur\_rounding\_ptr}]\K\|a$;\5 -$\\{before}[\\{cur\_rounding\_ptr}]\K\|b$;\5 -$\\{node\_to\_round}[\\{cur\_rounding\_ptr}]\K\|p$;\5 -$\\{incr}(\\{cur\_rounding\_ptr})$;\6 -\&{end};\par -\fi - -\M430. A global variable called \\{cur\_gran} is used instead of $\\{internal}[% -\\{granularity}]$, because we want to work with a number that's guaranteed to -be positive. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{cur\_gran}: \37\\{scaled};\C{the current granularity (which normally is % -\\{unity})}\par -\fi - -\M431. The \\{good\_val} function computes a number \|a that's as close as -possible to~\|b, with the property that $\|a+\|o$ is a multiple of -\\{cur\_gran}. - -If we assume that \\{cur\_gran} is even (since it will in fact be a multiple -of \\{unity} in all reasonable applications), we have the identity -$\\{good\_val}(-\|b-1,-\|o)=-\\{good\_val}(\|b,\|o)$. - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{function}\1\ \37$\\{good\_val}(\|b,\39\|o:\\{scaled})$: \37\\{scaled};\6 -\4\&{var} \37\|a: \37\\{scaled};\C{accumulator}\2\6 -\&{begin} \37$\|a\K\|b+\|o$;\6 -\&{if} $\|a\G0$ \1\&{then}\5 -$\|a\K\|a-(\|a\mathbin{\&{mod}}\\{cur\_gran})-\|o$\6 -\4\&{else} $\|a\K\|a+((-(\|a+1))\mathbin{\&{mod}}\\{cur\_gran})-\\{cur% -\_gran}+1-\|o$;\2\6 -\&{if} $\|b-\|a<\|a+\\{cur\_gran}-\|b$ \1\&{then}\5 -$\\{good\_val}\K\|a$\6 -\4\&{else} $\\{good\_val}\K\|a+\\{cur\_gran}$;\2\6 -\&{end};\par -\fi - -\M432. When we're rounding a doublepath, we might need to compromise between -two opposing tendencies, if the pen thickness is not a multiple of the -granularity. The following ``compromise'' adjustment, suggested by -John Hobby, finds the best way out of the dilemma. (Only the value -modulo \\{cur\_gran} is relevant in our applications, so the result turns -out to be essentially symmetric in \|u and~\|v.) - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{function}\1\ \37$\\{compromise}(\|u,\39\|v:\\{scaled})$: \37\\{scaled};\2% -\6 -\&{begin} \37$\\{compromise}\K\\{half}(\\{good\_val}(\|u+\|u,\39-\|u-\|v))$;\6 -\&{end};\par -\fi - -\M433. Here, then, is the procedure that rounds $x$ coordinates as described; -it does the same for $y$ coordinates too, independently. - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{xy\_round};\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{list manipulation registers}\6 -$\|b,\39\|a$: \37\\{scaled};\C{before and after values}\6 -\\{pen\_edge}: \37\\{scaled};\C{offset that governs rounding}\6 -\\{alpha}: \37\\{fraction};\C{coefficient of linear transformation}\2\6 -\&{begin} \37$\\{cur\_gran}\K\\{abs}(\\{internal}[\\{granularity}])$;\6 -\&{if} $\\{cur\_gran}=0$ \1\&{then}\5 -$\\{cur\_gran}\K\\{unity}$;\2\6 -$\|p\K\\{cur\_spec}$;\5 -$\\{cur\_rounding\_ptr}\K0$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|p)$;\5 -\X434:If node \|q is a transition point for \|x coordinates, compute and save -its before-and-after coordinates\X;\6 -$\|p\K\|q$;\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\6 -\&{if} $\\{cur\_rounding\_ptr}>0$ \1\&{then}\5 -\X436:Transform the \|x coordinates\X;\2\6 -$\|p\K\\{cur\_spec}$;\5 -$\\{cur\_rounding\_ptr}\K0$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|p)$;\5 -\X437:If node \|q is a transition point for \|y coordinates, compute and save -its before-and-after coordinates\X;\6 -$\|p\K\|q$;\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\6 -\&{if} $\\{cur\_rounding\_ptr}>0$ \1\&{then}\5 -\X439:Transform the \|y coordinates\X;\2\6 -\&{end};\par -\fi - -\M434. When \|x has been negated, the \\{octant} codes are even. We allow -for an error of up to .01 pixel (i.e., 655 \\{scaled} units) in the -derivative calculations at transition nodes. - -\Y\P$\4\X434:If node \|q is a transition point for \|x coordinates, compute and -save its before-and-after coordinates\X\S$\6 -\&{if} $\\{odd}(\\{right\_type}(\|p))\I\\{odd}(\\{right\_type}(\|q))$ \1% -\&{then}\6 -\&{begin} \37\&{if} $\\{odd}(\\{right\_type}(\|q))$ \1\&{then}\5 -$\|b\K\\{x\_coord}(\|q)$\ \&{else} $\|b\K-\\{x\_coord}(\|q)$;\2\6 -\&{if} $(\\{abs}(\\{x\_coord}(\|q)-\\{right\_x}(\|q))<655)\V\30(\\{abs}(\\{x% -\_coord}(\|q)+\\{left\_x}(\|q))<655)$ \1\&{then}\5 -\X435:Compute before-and-after \|x values based on the current pen\X\6 -\4\&{else} $\|a\K\|b$;\2\6 -\&{if} $\\{abs}(\|a)>\\{max\_allowed}$ \1\&{then}\6 -\&{if} $\|a>0$ \1\&{then}\5 -$\|a\K\\{max\_allowed}$\ \&{else} $\|a\K-\\{max\_allowed}$;\2\2\6 -$\\{before\_and\_after}(\|b,\39\|a,\39\|q)$;\6 -\&{end}\2\par -\U433.\fi - -\M435. When we study the data representation for pens, we'll learn that the -\|x~coordinate of the current pen's west edge is -$$\hbox{$\\{y\_coord}(\\{link}(\\{cur\_pen}+\\{seventh\_octant}))$},$$ -and that there are similar ways to address other important offsets. -An ``\\{east\_west\_edge}'' is computed as a compromise between east and -west, for use in doublepaths, in case the two edges have conflicting -tendencies. - -\Y\P\D \37$\\{north\_edge}(\#)\S\\{y\_coord}(\\{link}(\#+\\{fourth\_octant}))$% -\par -\P\D \37$\\{south\_edge}(\#)\S\\{y\_coord}(\\{link}(\#+\\{first\_octant}))$\par -\P\D \37$\\{east\_edge}(\#)\S\\{y\_coord}(\\{link}(\#+\\{second\_octant}))$\par -\P\D \37$\\{west\_edge}(\#)\S\\{y\_coord}(\\{link}(\#+\\{seventh\_octant}))$\par -\P\D \37$\\{north\_south\_edge}(\#)\S\\{mem}[\#+10].\\{int}$\C{compromise -between north and south}\par -\P\D \37$\\{east\_west\_edge}(\#)\S\\{mem}[\#+11].\\{int}$\C{compromise between -east and west}\par -\P\D \37$\\{NE\_SW\_edge}(\#)\S\\{mem}[\#+12].\\{int}$\C{compromise between -northeast and southwest}\par -\P\D \37$\\{NW\_SE\_edge}(\#)\S\\{mem}[\#+13].\\{int}$\C{compromise between -northwest and southeast}\par -\Y\P$\4\X435:Compute before-and-after \|x values based on the current pen\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_pen}=\\{null\_pen}$ \1\&{then}\5 -$\\{pen\_edge}\K0$\6 -\4\&{else} \&{if} $\\{cur\_path\_type}=\\{double\_path\_code}$ \1\&{then}\5 -$\\{pen\_edge}\K\\{compromise}(\\{east\_edge}(\\{cur\_pen}),\39\\{west\_edge}(% -\\{cur\_pen}))$\6 -\4\&{else} \&{if} $\\{odd}(\\{right\_type}(\|q))$ \1\&{then}\5 -$\\{pen\_edge}\K\\{west\_edge}(\\{cur\_pen})$\6 -\4\&{else} $\\{pen\_edge}\K\\{east\_edge}(\\{cur\_pen})$;\2\2\2\6 -$\|a\K\\{good\_val}(\|b,\39\\{pen\_edge})$;\6 -\&{end}\par -\U434.\fi - -\M436. The monotone transformation computed here with fixed-point arithmetic -is -guaranteed to take consecutive \\{before} values $(b,b')$ into consecutive -\\{after} values $(a,a')$, even in the presence of rounding errors, -as long as $\vert b-b'\vert<2^{28}$. - -\Y\P$\4\X436:Transform the \|x coordinates\X\S$\6 -\&{begin} \37\\{make\_safe};\6 -\1\&{repeat} \37$\\{decr}(\\{cur\_rounding\_ptr})$;\6 -\&{if} $(\\{after}[\\{cur\_rounding\_ptr}]\I\\{before}[\\{cur\_rounding\_ptr}])% -\V\30(\\{after}[\\{cur\_rounding\_ptr}+1]\I\\{before}[\\{cur\_rounding% -\_ptr}+1])$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{node\_to\_round}[\\{cur\_rounding\_ptr}]$;\6 -\&{if} $\\{odd}(\\{right\_type}(\|p))$ \1\&{then}\6 -\&{begin} \37$\|b\K\\{before}[\\{cur\_rounding\_ptr}]$;\5 -$\|a\K\\{after}[\\{cur\_rounding\_ptr}]$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|b\K-\\{before}[\\{cur\_rounding\_ptr}]$;\5 -$\|a\K-\\{after}[\\{cur\_rounding\_ptr}]$;\6 -\&{end};\2\6 -\&{if} $\\{before}[\\{cur\_rounding\_ptr}]=\\{before}[\\{cur\_rounding% -\_ptr}+1]$ \1\&{then}\5 -$\\{alpha}\K\\{fraction\_one}$\6 -\4\&{else} $\\{alpha}\K\\{make\_fraction}(\\{after}[\\{cur\_rounding\_ptr}+1]-% -\\{after}[\\{cur\_rounding\_ptr}],\39\30\\{before}[\\{cur\_rounding\_ptr}+1]-% -\\{before}[\\{cur\_rounding\_ptr}])$;\2\6 -\1\&{repeat} \37$\\{x\_coord}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{x% -\_coord}(\|p)-\|b)+\|a$;\5 -$\\{right\_x}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{right\_x}(\|p)-\|b)+% -\|a$;\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{left\_x}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{left\_x}(\|p)-\|b)+\|a$;\6 -\4\&{until}\5 -$\|p=\\{node\_to\_round}[\\{cur\_rounding\_ptr}+1]$;\2\6 -\&{end};\2\6 -\4\&{until}\5 -$\\{cur\_rounding\_ptr}=0$;\2\6 -\&{end}\par -\U433.\fi - -\M437. When \|y has been negated, the \\{octant} codes are $>\\{negate\_y}$. -Otherwise -these routines are essentially identical to the routines for \|x coordinates -that we have just seen. - -\Y\P$\4\X437:If node \|q is a transition point for \|y coordinates, compute and -save its before-and-after coordinates\X\S$\6 -\&{if} $(\\{right\_type}(\|p)>\\{negate\_y})\I(\\{right\_type}(\|q)>\\{negate% -\_y})$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{right\_type}(\|q)\L\\{negate\_y}$ \1\&{then}\5 -$\|b\K\\{y\_coord}(\|q)$\ \&{else} $\|b\K-\\{y\_coord}(\|q)$;\2\6 -\&{if} $(\\{abs}(\\{y\_coord}(\|q)-\\{right\_y}(\|q))<655)\V\30(\\{abs}(\\{y% -\_coord}(\|q)+\\{left\_y}(\|q))<655)$ \1\&{then}\5 -\X438:Compute before-and-after \|y values based on the current pen\X\6 -\4\&{else} $\|a\K\|b$;\2\6 -\&{if} $\\{abs}(\|a)>\\{max\_allowed}$ \1\&{then}\6 -\&{if} $\|a>0$ \1\&{then}\5 -$\|a\K\\{max\_allowed}$\ \&{else} $\|a\K-\\{max\_allowed}$;\2\2\6 -$\\{before\_and\_after}(\|b,\39\|a,\39\|q)$;\6 -\&{end}\2\par -\U433.\fi - -\M438. \P$\X438:Compute before-and-after \|y values based on the current pen\X% -\S$\6 -\&{begin} \37\&{if} $\\{cur\_pen}=\\{null\_pen}$ \1\&{then}\5 -$\\{pen\_edge}\K0$\6 -\4\&{else} \&{if} $\\{cur\_path\_type}=\\{double\_path\_code}$ \1\&{then}\5 -$\\{pen\_edge}\K\\{compromise}(\\{north\_edge}(\\{cur\_pen}),\39\\{south% -\_edge}(\\{cur\_pen}))$\6 -\4\&{else} \&{if} $\\{right\_type}(\|q)\L\\{negate\_y}$ \1\&{then}\5 -$\\{pen\_edge}\K\\{south\_edge}(\\{cur\_pen})$\6 -\4\&{else} $\\{pen\_edge}\K\\{north\_edge}(\\{cur\_pen})$;\2\2\2\6 -$\|a\K\\{good\_val}(\|b,\39\\{pen\_edge})$;\6 -\&{end}\par -\U437.\fi - -\M439. \P$\X439:Transform the \|y coordinates\X\S$\6 -\&{begin} \37\\{make\_safe};\6 -\1\&{repeat} \37$\\{decr}(\\{cur\_rounding\_ptr})$;\6 -\&{if} $(\\{after}[\\{cur\_rounding\_ptr}]\I\\{before}[\\{cur\_rounding\_ptr}])% -\V\30(\\{after}[\\{cur\_rounding\_ptr}+1]\I\\{before}[\\{cur\_rounding% -\_ptr}+1])$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{node\_to\_round}[\\{cur\_rounding\_ptr}]$;\6 -\&{if} $\\{right\_type}(\|p)\L\\{negate\_y}$ \1\&{then}\6 -\&{begin} \37$\|b\K\\{before}[\\{cur\_rounding\_ptr}]$;\5 -$\|a\K\\{after}[\\{cur\_rounding\_ptr}]$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|b\K-\\{before}[\\{cur\_rounding\_ptr}]$;\5 -$\|a\K-\\{after}[\\{cur\_rounding\_ptr}]$;\6 -\&{end};\2\6 -\&{if} $\\{before}[\\{cur\_rounding\_ptr}]=\\{before}[\\{cur\_rounding% -\_ptr}+1]$ \1\&{then}\5 -$\\{alpha}\K\\{fraction\_one}$\6 -\4\&{else} $\\{alpha}\K\\{make\_fraction}(\\{after}[\\{cur\_rounding\_ptr}+1]-% -\\{after}[\\{cur\_rounding\_ptr}],\39\30\\{before}[\\{cur\_rounding\_ptr}+1]-% -\\{before}[\\{cur\_rounding\_ptr}])$;\2\6 -\1\&{repeat} \37$\\{y\_coord}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{y% -\_coord}(\|p)-\|b)+\|a$;\5 -$\\{right\_y}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{right\_y}(\|p)-\|b)+% -\|a$;\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{left\_y}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{left\_y}(\|p)-\|b)+\|a$;\6 -\4\&{until}\5 -$\|p=\\{node\_to\_round}[\\{cur\_rounding\_ptr}+1]$;\2\6 -\&{end};\2\6 -\4\&{until}\5 -$\\{cur\_rounding\_ptr}=0$;\2\6 -\&{end}\par -\U433.\fi - -\M440. Rounding at diagonal tangents takes place after the subdivision into -octants is complete, hence after the coordinates have been skewed. -The details are somewhat tricky, because we want to round to points -whose skewed coordinates are halfway between integer multiples of -the granularity. Furthermore, both coordinates change when they are -rounded; this means we need a generalization of the \\{make\_safe} routine, -ensuring safety in both \|x and \|y. - -In spite of these extra complications, we can take comfort in the fact -that the basic structure of the routine is the same as before. - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{diag\_round};\6 -\4\&{var} \37$\|p,\39\|q,\39\\{pp}$: \37\\{pointer};\C{list manipulation -registers}\6 -$\|b,\39\|a,\39\\{bb},\39\\{aa},\39\|d,\39\|c,\39\\{dd},\39\\{cc}$: \37% -\\{scaled};\C{before and after values}\6 -\\{pen\_edge}: \37\\{scaled};\C{offset that governs rounding}\6 -$\\{alpha},\39\\{beta}$: \37\\{fraction};\C{coefficients of linear -transformation}\6 -\\{next\_a}: \37\\{scaled};\C{$\\{after}[\|k]$ before it might have changed}\6 -\\{all\_safe}: \37\\{boolean};\C{does everything look OK so far?}\6 -\|k: \37$0\to\\{max\_wiggle}$;\C{runs through before-and-after values}\6 -$\\{first\_x},\39\\{first\_y}$: \37\\{scaled};\C{coordinates before rounding}\2% -\6 -\&{begin} \37$\|p\K\\{cur\_spec}$;\5 -$\\{cur\_rounding\_ptr}\K0$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|p)$;\5 -\X441:If node \|q is a transition point between octants, compute and save its -before-and-after coordinates\X;\6 -$\|p\K\|q$;\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\6 -\&{if} $\\{cur\_rounding\_ptr}>0$ \1\&{then}\5 -\X444:Transform the skewed coordinates\X;\2\6 -\&{end};\par -\fi - -\M441. We negate the skewed \|x coordinates in the before-and-after table when -the octant code is greater than \\{switch\_x\_and\_y}. - -\Y\P$\4\X441:If node \|q is a transition point between octants, compute and -save its before-and-after coordinates\X\S$\6 -\&{if} $\\{right\_type}(\|p)\I\\{right\_type}(\|q)$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{right\_type}(\|q)>\\{switch\_x\_and\_y}$ \1\&{then}\5 -$\|b\K-\\{x\_coord}(\|q)$\6 -\4\&{else} $\|b\K\\{x\_coord}(\|q)$;\2\6 -\&{if} $\\{abs}(\\{right\_type}(\|q)-\\{right\_type}(\|p))=\\{switch\_x\_and% -\_y}$ \1\&{then}\6 -\&{if} $(\\{abs}(\\{x\_coord}(\|q)-\\{right\_x}(\|q))<655)\V(\\{abs}(\\{x% -\_coord}(\|q)+\\{left\_x}(\|q))<655)$ \1\&{then}\5 -\X442:Compute a good coordinate at a diagonal transition\X\6 -\4\&{else} $\|a\K\|b$\2\6 -\4\&{else} $\|a\K\|b$;\2\6 -$\\{before\_and\_after}(\|b,\39\|a,\39\|q)$;\6 -\&{end}\2\par -\U440.\fi - -\M442. In octants whose code number is even, $x$~has been -negated; we want to round ambiguous cases downward instead of upward, -so that the rounding will be consistent with octants whose code -number is odd. This downward bias can be achieved by -subtracting~1 from the first argument of \\{good\_val}. - -\Y\P\D \37$\\{diag\_offset}(\#)\S\\{x\_coord}(\\{knil}(\\{link}(\\{cur\_pen}+% -\#)))$\par -\Y\P$\4\X442:Compute a good coordinate at a diagonal transition\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_pen}=\\{null\_pen}$ \1\&{then}\5 -$\\{pen\_edge}\K0$\6 -\4\&{else} \&{if} $\\{cur\_path\_type}=\\{double\_path\_code}$ \1\&{then}\5 -\X443:Compute a compromise \\{pen\_edge}\X\6 -\4\&{else} \&{if} $\\{right\_type}(\|q)\L\\{switch\_x\_and\_y}$ \1\&{then}\5 -$\\{pen\_edge}\K\\{diag\_offset}(\\{right\_type}(\|q))$\6 -\4\&{else} $\\{pen\_edge}\K-\\{diag\_offset}(\\{right\_type}(\|q))$;\2\2\2\6 -\&{if} $\\{odd}(\\{right\_type}(\|q))$ \1\&{then}\5 -$\|a\K\\{good\_val}(\|b,\39\\{pen\_edge}+\\{half}(\\{cur\_gran}))$\6 -\4\&{else} $\|a\K\\{good\_val}(\|b-1,\39\\{pen\_edge}+\\{half}(\\{cur% -\_gran}))$;\2\6 -\&{end}\par -\U441.\fi - -\M443. (It seems a shame to compute these compromise offsets repeatedly. The -author would have stored them directly in the pen data structure, if the -granularity had been constant.) - -\Y\P$\4\X443:Compute a compromise \\{pen\_edge}\X\S$\6 -\&{case} $\\{right\_type}(\|q)$ \1\&{of}\6 -\4$\\{first\_octant},\39\\{second\_octant}$: \37$\\{pen\_edge}\K\\{compromise}(% -\\{diag\_offset}(\\{first\_octant}),\39\30-\\{diag\_offset}(\\{fifth% -\_octant}))$;\6 -\4$\\{fifth\_octant},\39\\{sixth\_octant}$: \37$\\{pen\_edge}\K-\\{compromise}(% -\\{diag\_offset}(\\{first\_octant}),\39\30-\\{diag\_offset}(\\{fifth% -\_octant}))$;\6 -\4$\\{third\_octant},\39\\{fourth\_octant}$: \37$\\{pen\_edge}\K\\{compromise}(% -\\{diag\_offset}(\\{fourth\_octant}),\39\30-\\{diag\_offset}(\\{eighth% -\_octant}))$;\6 -\4$\\{seventh\_octant},\39\\{eighth\_octant}$: \37$\\{pen\_edge}\K-% -\\{compromise}(\\{diag\_offset}(\\{fourth\_octant}),\39\30-\\{diag\_offset}(% -\\{eighth\_octant}))$;\2\6 -\&{end}\C{there are no other cases}\par -\U442.\fi - -\M444. \P$\X444:Transform the skewed coordinates\X\S$\6 -\&{begin} \37$\|p\K\\{node\_to\_round}[0]$;\5 -$\\{first\_x}\K\\{x\_coord}(\|p)$;\5 -$\\{first\_y}\K\\{y\_coord}(\|p)$;\5 -\X446:Make sure that all the diagonal roundings are safe\X;\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{cur\_rounding\_ptr}-1$ \1\&{do}\6 -\&{begin} \37$\|a\K\\{after}[\|k]$;\5 -$\|b\K\\{before}[\|k]$;\5 -$\\{aa}\K\\{after}[\|k+1]$;\5 -$\\{bb}\K\\{before}[\|k+1]$;\6 -\&{if} $(\|a\I\|b)\V(\\{aa}\I\\{bb})$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{node\_to\_round}[\|k]$;\5 -$\\{pp}\K\\{node\_to\_round}[\|k+1]$;\5 -\X445:Determine the before-and-after values of both coordinates\X;\6 -\&{if} $\|b=\\{bb}$ \1\&{then}\5 -$\\{alpha}\K\\{fraction\_one}$\6 -\4\&{else} $\\{alpha}\K\\{make\_fraction}(\\{aa}-\|a,\39\\{bb}-\|b)$;\2\6 -\&{if} $\|d=\\{dd}$ \1\&{then}\5 -$\\{beta}\K\\{fraction\_one}$\6 -\4\&{else} $\\{beta}\K\\{make\_fraction}(\\{cc}-\|c,\39\\{dd}-\|d)$;\2\6 -\1\&{repeat} \37$\\{x\_coord}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{x% -\_coord}(\|p)-\|b)+\|a$;\5 -$\\{y\_coord}(\|p)\K\\{take\_fraction}(\\{beta},\39\\{y\_coord}(\|p)-\|d)+\|c$;% -\5 -$\\{right\_x}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{right\_x}(\|p)-\|b)+% -\|a$;\5 -$\\{right\_y}(\|p)\K\\{take\_fraction}(\\{beta},\39\\{right\_y}(\|p)-\|d)+\|c$;% -\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{left\_x}(\|p)\K\\{take\_fraction}(\\{alpha},\39\\{left\_x}(\|p)-\|b)+\|a$;\5 -$\\{left\_y}(\|p)\K\\{take\_fraction}(\\{beta},\39\\{left\_y}(\|p)-\|d)+\|c$;\6 -\4\&{until}\5 -$\|p=\\{pp}$;\2\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end}\par -\U440.\fi - -\M445. In node \|p, the coordinates $(\|b,\|d)$ will be rounded to $(\|a,\|c)$; -in node \\{pp}, the coordinates $(\\{bb},\\{dd})$ will be rounded to $(\\{aa},% -\\{cc})$. -(We transform the values from node \\{pp} so that they agree with the -conventions of node \|p.) - -If $\\{aa}\I\\{bb}$, we know that $\\{abs}(\\{right\_type}(\|p)-\\{right% -\_type}(\\{pp}))=\\{switch\_x\_and\_y}$. - -\Y\P$\4\X445:Determine the before-and-after values of both coordinates\X\S$\6 -\&{if} $\\{aa}=\\{bb}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{pp}=\\{node\_to\_round}[0]$ \1\&{then}\5 -$\\{unskew}(\\{first\_x},\39\\{first\_y},\39\\{right\_type}(\\{pp}))$\6 -\4\&{else} $\\{unskew}(\\{x\_coord}(\\{pp}),\39\\{y\_coord}(\\{pp}),\39\\{right% -\_type}(\\{pp}))$;\2\6 -$\\{skew}(\\{cur\_x},\39\\{cur\_y},\39\\{right\_type}(\|p))$;\5 -$\\{bb}\K\\{cur\_x}$;\5 -$\\{aa}\K\\{bb}$;\5 -$\\{dd}\K\\{cur\_y}$;\5 -$\\{cc}\K\\{dd}$;\6 -\&{if} $\\{right\_type}(\|p)>\\{switch\_x\_and\_y}$ \1\&{then}\6 -\&{begin} \37$\|b\K-\|b$;\5 -$\|a\K-\|a$;\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{right\_type}(\|p)>\\{switch\_x\_and\_y}$ \1% -\&{then}\6 -\&{begin} \37$\\{bb}\K-\\{bb}$;\5 -$\\{aa}\K-\\{aa}$;\5 -$\|b\K-\|b$;\5 -$\|a\K-\|a$;\6 -\&{end};\2\6 -\&{if} $\\{pp}=\\{node\_to\_round}[0]$ \1\&{then}\5 -$\\{dd}\K\\{first\_y}-\\{bb}$\ \&{else} $\\{dd}\K\\{y\_coord}(\\{pp})-\\{bb}$;% -\2\6 -\&{if} $\\{odd}(\\{aa}-\\{bb})$ \1\&{then}\6 -\&{if} $\\{right\_type}(\|p)>\\{switch\_x\_and\_y}$ \1\&{then}\5 -$\\{cc}\K\\{dd}-\\{half}(\\{aa}-\\{bb}+1)$\6 -\4\&{else} $\\{cc}\K\\{dd}-\\{half}(\\{aa}-\\{bb}-1)$\2\6 -\4\&{else} $\\{cc}\K\\{dd}-\\{half}(\\{aa}-\\{bb})$;\2\6 -\&{end};\2\6 -$\|d\K\\{y\_coord}(\|p)$;\6 -\&{if} $\\{odd}(\|a-\|b)$ \1\&{then}\6 -\&{if} $\\{right\_type}(\|p)>\\{switch\_x\_and\_y}$ \1\&{then}\5 -$\|c\K\|d-\\{half}(\|a-\|b-1)$\6 -\4\&{else} $\|c\K\|d-\\{half}(\|a-\|b+1)$\2\6 -\4\&{else} $\|c\K\|d-\\{half}(\|a-\|b)$\2\par -\Us444\ET446.\fi - -\M446. \P$\X446:Make sure that all the diagonal roundings are safe\X\S$\6 -$\\{before}[\\{cur\_rounding\_ptr}]\K\\{before}[0]$;\C{cf.~\\{make\_safe}}\6 -$\\{node\_to\_round}[\\{cur\_rounding\_ptr}]\K\\{node\_to\_round}[0]$;\6 -\1\&{repeat} \37$\\{after}[\\{cur\_rounding\_ptr}]\K\\{after}[0]$;\5 -$\\{all\_safe}\K\\{true}$;\5 -$\\{next\_a}\K\\{after}[0]$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{cur\_rounding\_ptr}-1$ \1\&{do}\6 -\&{begin} \37$\|a\K\\{next\_a}$;\5 -$\|b\K\\{before}[\|k]$;\5 -$\\{next\_a}\K\\{after}[\|k+1]$;\5 -$\\{aa}\K\\{next\_a}$;\5 -$\\{bb}\K\\{before}[\|k+1]$;\6 -\&{if} $(\|a\I\|b)\V(\\{aa}\I\\{bb})$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{node\_to\_round}[\|k]$;\5 -$\\{pp}\K\\{node\_to\_round}[\|k+1]$;\5 -\X445:Determine the before-and-after values of both coordinates\X;\6 -\&{if} $(\\{aa}<\|a)\V(\\{cc}<\|c)\V(\\{aa}-\|a>2\ast(\\{bb}-\|b))\V(\\{cc}-% -\|c>2\ast(\\{dd}-\|d))$ \1\&{then}\6 -\&{begin} \37$\\{all\_safe}\K\\{false}$;\5 -$\\{after}[\|k]\K\\{before}[\|k]$;\6 -\&{if} $\|k=\\{cur\_rounding\_ptr}-1$ \1\&{then}\5 -$\\{after}[0]\K\\{before}[0]$\6 -\4\&{else} $\\{after}[\|k+1]\K\\{before}[\|k+1]$;\2\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\2\6 -\4\&{until}\5 -\\{all\_safe}\2\par -\U444.\fi - -\M447. Here we get rid of ``dead'' cubics, i.e., polynomials that don't move at -all when \|t~changes, since the subdivision process might have introduced -such things. If the cycle reduces to a single point, however, we are left -with a single dead cubic that will not be removed until later. - -\Y\P$\4\X447:Remove dead cubics\X\S$\6 -$\|p\K\\{cur\_spec}$;\6 -\1\&{repeat} \37\\{continue}: \37$\|q\K\\{link}(\|p)$;\6 -\&{if} $\|p\I\|q$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{x\_coord}(\|p)=\\{right\_x}(\|p)$ \1\&{then}\6 -\&{if} $\\{y\_coord}(\|p)=\\{right\_y}(\|p)$ \1\&{then}\6 -\&{if} $\\{x\_coord}(\|p)=\\{left\_x}(\|q)$ \1\&{then}\6 -\&{if} $\\{y\_coord}(\|p)=\\{left\_y}(\|q)$ \1\&{then}\6 -\&{begin} \37$\\{unskew}(\\{x\_coord}(\|q),\39\\{y\_coord}(\|q),\39\\{right% -\_type}(\|q))$;\5 -$\\{skew}(\\{cur\_x},\39\\{cur\_y},\39\\{right\_type}(\|p))$;\6 -\&{if} $\\{x\_coord}(\|p)=\\{cur\_x}$ \1\&{then}\6 -\&{if} $\\{y\_coord}(\|p)=\\{cur\_y}$ \1\&{then}\6 -\&{begin} \37$\\{remove\_cubic}(\|p)$;\C{remove the cubic following \|p}\6 -\&{if} $\|q\I\\{cur\_spec}$ \1\&{then}\5 -\&{goto} \37\\{continue};\2\6 -$\\{cur\_spec}\K\|p$;\5 -$\|q\K\|p$;\6 -\&{end};\2\2\6 -\&{end};\2\2\2\2\6 -\&{end};\2\6 -$\|p\K\|q$;\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\par -\U402.\fi - -\M448. Finally we come to the last steps of \\{make\_spec}, when boundary nodes -are inserted between cubics that move in different octants. The main -complication remaining arises from consecutive cubics whose octants -are not adjacent; we should insert more than one octant boundary -at such sharp turns, so that the envelope-forming routine will work. - -For this purpose, conversion tables between numeric and Gray codes for -octants are desirable. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{octant\_number}: \37\&{array} $[\\{first\_octant}\to\\{sixth\_octant}]$ \1% -\&{of}\5 -$1\to8$;\2\6 -\4\\{octant\_code}: \37\&{array} $[1\to8]$ \1\&{of}\5 -$\\{first\_octant}\to\\{sixth\_octant}$;\2\par -\fi - -\M449. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{octant\_code}[1]\K\\{first\_octant}$;\5 -$\\{octant\_code}[2]\K\\{second\_octant}$;\5 -$\\{octant\_code}[3]\K\\{third\_octant}$;\5 -$\\{octant\_code}[4]\K\\{fourth\_octant}$;\5 -$\\{octant\_code}[5]\K\\{fifth\_octant}$;\5 -$\\{octant\_code}[6]\K\\{sixth\_octant}$;\5 -$\\{octant\_code}[7]\K\\{seventh\_octant}$;\5 -$\\{octant\_code}[8]\K\\{eighth\_octant}$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}8$ \1\&{do}\5 -$\\{octant\_number}[\\{octant\_code}[\|k]]\K\|k$;\2\par -\fi - -\M450. The main loop for boundary insertion deals with three consecutive -nodes $\|p,\|q,\|r$. - -\Y\P$\4\X450:Insert octant boundaries and compute the turning number\X\S$\6 -$\\{turning\_number}\K0$;\5 -$\|p\K\\{cur\_spec}$;\5 -$\|q\K\\{link}(\|p)$;\6 -\1\&{repeat} \37$\|r\K\\{link}(\|q)$;\6 -\&{if} $(\\{right\_type}(\|p)\I\\{right\_type}(\|q))\V(\|q=\|r)$ \1\&{then}\5 -\X452:Insert one or more octant boundary nodes just before~\|q\X;\2\6 -$\|p\K\|q$;\5 -$\|q\K\|r$;\6 -\4\&{until}\5 -$\|p=\\{cur\_spec}$;\2\par -\U402.\fi - -\M451. The \\{new\_boundary} subroutine comes in handy at this point. It -inserts -a new boundary node just after a given node \|p, using a given octant code -to transform the new node's coordinates. The ``transition'' fields are -not computed here. - -\Y\P$\4\X405:Declare subroutines needed by \\{make\_spec}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{new\_boundary}(\|p:\\{pointer};\,\35\\{octant}:% -\\{small\_number})$;\6 -\4\&{var} \37$\|q,\39\|r$: \37\\{pointer};\C{for list manipulation}\2\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\C{we assume that $\\{right\_type}(\|q)\I% -\\{endpoint}$}\6 -$\|r\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{link}(\|r)\K\|q$;\5 -$\\{link}(\|p)\K\|r$;\5 -$\\{left\_type}(\|r)\K\\{left\_type}(\|q)$;\C{but possibly $\\{left\_type}(% -\|q)=\\{endpoint}$}\6 -$\\{left\_x}(\|r)\K\\{left\_x}(\|q)$;\5 -$\\{left\_y}(\|r)\K\\{left\_y}(\|q)$;\5 -$\\{right\_type}(\|r)\K\\{endpoint}$;\5 -$\\{left\_type}(\|q)\K\\{endpoint}$;\5 -$\\{right\_octant}(\|r)\K\\{octant}$;\5 -$\\{left\_octant}(\|q)\K\\{right\_type}(\|q)$;\5 -$\\{unskew}(\\{x\_coord}(\|q),\39\\{y\_coord}(\|q),\39\\{right\_type}(\|q))$;\5 -$\\{skew}(\\{cur\_x},\39\\{cur\_y},\39\\{octant})$;\5 -$\\{x\_coord}(\|r)\K\\{cur\_x}$;\5 -$\\{y\_coord}(\|r)\K\\{cur\_y}$;\6 -\&{end};\par -\fi - -\M452. The case $\|q=\|r$ occurs if and only if $\|p=\|q=\|r=\\{cur\_spec}$, -when we want to turn -$360^\circ$ in eight steps and then remove a solitary dead cubic. -The program below happens to work in that case, but the reader isn't -expected to understand why. - -\Y\P$\4\X452:Insert one or more octant boundary nodes just before~\|q\X\S$\6 -\&{begin} \37$\\{new\_boundary}(\|p,\39\\{right\_type}(\|p))$;\5 -$\|s\K\\{link}(\|p)$;\5 -$\\{o1}\K\\{octant\_number}[\\{right\_type}(\|p)]$;\5 -$\\{o2}\K\\{octant\_number}[\\{right\_type}(\|q)]$;\6 -\&{case} $\\{o2}-\\{o1}$ \1\&{of}\6 -\4$1,\39-7,\397,\39-1$: \37\&{goto} \37\\{done};\6 -\4$2,\39-6$: \37$\\{clockwise}\K\\{false}$;\6 -\4$3,\39-5,\394,\39-4,\395,\39-3$: \37\X454:Decide whether or not to go -clockwise\X;\6 -\4$6,\39-2$: \37$\\{clockwise}\K\\{true}$;\6 -\40: \37$\\{clockwise}\K\\{rev\_turns}$;\2\6 -\&{end};\C{there are no other cases}\6 -\X458:Insert additional boundary nodes, then \&{goto} \\{done}\X;\6 -\4\\{done}: \37\&{if} $\|q=\|r$ \1\&{then}\6 -\&{begin} \37$\|q\K\\{link}(\|q)$;\5 -$\|r\K\|q$;\5 -$\|p\K\|s$;\5 -$\\{link}(\|s)\K\|q$;\5 -$\\{left\_octant}(\|q)\K\\{right\_octant}(\|q)$;\5 -$\\{left\_type}(\|q)\K\\{endpoint}$;\5 -$\\{free\_node}(\\{cur\_spec},\39\\{knot\_node\_size})$;\5 -$\\{cur\_spec}\K\|q$;\6 -\&{end};\2\6 -\X459:Fix up the transition fields and adjust the turning number\X;\6 -\&{end}\par -\U450.\fi - -\M453. \P$\X453:Other local variables for \\{make\_spec}\X\S$\6 -\4$\\{o1},\39\\{o2}$: \37\\{small\_number};\C{octant numbers}\6 -\4\\{clockwise}: \37\\{boolean};\C{should we turn clockwise?}\6 -\4$\\{dx1},\39\\{dy1},\39\\{dx2},\39\\{dy2}$: \37\\{integer};\C{directions of -travel at a cusp}\6 -\4$\\{dmax},\39\\{del}$: \37\\{integer};\C{temporary registers}\par -\U402.\fi - -\M454. A tricky question arises when a path jumps four octants. We want the -direction of turning to be counterclockwise if the curve has changed -direction by $180^\circ$, or by something so close to $180^\circ$ that -the difference is probably due to rounding errors; otherwise we want to -turn through an angle of less than $180^\circ$. This decision needs to -be made even when a curve seems to have jumped only three octants, since -a curve may approach direction $(-1,0)$ from the fourth octant, then -it might leave from direction $(+1,0)$ into the first. - -The following code solves the problem by analyzing the incoming -direction $(\\{dx1},\\{dy1})$ and the outgoing direction $(\\{dx2},\\{dy2})$. - -\Y\P$\4\X454:Decide whether or not to go clockwise\X\S$\6 -\&{begin} \37\X457:Compute the incoming and outgoing directions\X;\6 -$\\{unskew}(\\{dx1},\39\\{dy1},\39\\{right\_type}(\|p))$;\5 -$\\{del}\K\\{pyth\_add}(\\{cur\_x},\39\\{cur\_y})$;\6 -$\\{dx1}\K\\{make\_fraction}(\\{cur\_x},\39\\{del})$;\5 -$\\{dy1}\K\\{make\_fraction}(\\{cur\_y},\39\\{del})$;\C{$\cos\theta_1$ and $% -\sin\theta_1$}\6 -$\\{unskew}(\\{dx2},\39\\{dy2},\39\\{right\_type}(\|q))$;\5 -$\\{del}\K\\{pyth\_add}(\\{cur\_x},\39\\{cur\_y})$;\6 -$\\{dx2}\K\\{make\_fraction}(\\{cur\_x},\39\\{del})$;\5 -$\\{dy2}\K\\{make\_fraction}(\\{cur\_y},\39\\{del})$;\C{$\cos\theta_2$ and $% -\sin\theta_2$}\6 -$\\{del}\K\\{take\_fraction}(\\{dx1},\39\\{dy2})-\\{take\_fraction}(\\{dx2},\39% -\\{dy1})$;\C{$\sin(\theta_2-\theta_1)$}\6 -\&{if} $\\{del}>4684844$ \1\&{then}\5 -$\\{clockwise}\K\\{false}$\6 -\4\&{else} \&{if} $\\{del}<-4684844$ \1\&{then}\5 -$\\{clockwise}\K\\{true}$\C{$2^{28}\cdot\sin 1^\circ\approx4684844.68$}\6 -\4\&{else} $\\{clockwise}\K\\{rev\_turns}$;\2\2\6 -\&{end}\par -\U452.\fi - -\M455. Actually the turnarounds just computed will be clockwise, -not counterclockwise, if -the global variable \\{rev\_turns} is \\{true}; it is usually \\{false}. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{rev\_turns}: \37\\{boolean};\C{should we make U-turns in the English -manner?}\par -\fi - -\M456. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{rev\_turns}\K\\{false}$;\par -\fi - -\M457. \P$\X457:Compute the incoming and outgoing directions\X\S$\6 -$\\{dx1}\K\\{x\_coord}(\|s)-\\{left\_x}(\|s)$;\5 -$\\{dy1}\K\\{y\_coord}(\|s)-\\{left\_y}(\|s)$;\6 -\&{if} $\\{dx1}=0$ \1\&{then}\6 -\&{if} $\\{dy1}=0$ \1\&{then}\6 -\&{begin} \37$\\{dx1}\K\\{x\_coord}(\|s)-\\{right\_x}(\|p)$;\5 -$\\{dy1}\K\\{y\_coord}(\|s)-\\{right\_y}(\|p)$;\6 -\&{if} $\\{dx1}=0$ \1\&{then}\6 -\&{if} $\\{dy1}=0$ \1\&{then}\6 -\&{begin} \37$\\{dx1}\K\\{x\_coord}(\|s)-\\{x\_coord}(\|p)$;\5 -$\\{dy1}\K\\{y\_coord}(\|s)-\\{y\_coord}(\|p)$;\6 -\&{end};\C{and they {\sl can't} both be zero}\2\2\6 -\&{end};\2\2\6 -$\\{dmax}\K\\{abs}(\\{dx1})$;\ \&{if} $\\{abs}(\\{dy1})>\\{dmax}$ \1\&{then}\5 -$\\{dmax}\K\\{abs}(\\{dy1})$;\2\6 -\&{while} $\\{dmax}<\\{fraction\_one}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\\{dmax})$;\5 -$\\{double}(\\{dx1})$;\5 -$\\{double}(\\{dy1})$;\6 -\&{end};\2\6 -$\\{dx2}\K\\{right\_x}(\|q)-\\{x\_coord}(\|q)$;\5 -$\\{dy2}\K\\{right\_y}(\|q)-\\{y\_coord}(\|q)$;\6 -\&{if} $\\{dx2}=0$ \1\&{then}\6 -\&{if} $\\{dy2}=0$ \1\&{then}\6 -\&{begin} \37$\\{dx2}\K\\{left\_x}(\|r)-\\{x\_coord}(\|q)$;\5 -$\\{dy2}\K\\{left\_y}(\|r)-\\{y\_coord}(\|q)$;\6 -\&{if} $\\{dx2}=0$ \1\&{then}\6 -\&{if} $\\{dy2}=0$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{right\_type}(\|r)=\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_x}\K\\{x\_coord}(\|r)$;\5 -$\\{cur\_y}\K\\{y\_coord}(\|r)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{unskew}(\\{x\_coord}(\|r),\39\\{y\_coord}(\|r),\39% -\\{right\_type}(\|r))$;\5 -$\\{skew}(\\{cur\_x},\39\\{cur\_y},\39\\{right\_type}(\|q))$;\6 -\&{end};\2\6 -$\\{dx2}\K\\{cur\_x}-\\{x\_coord}(\|q)$;\5 -$\\{dy2}\K\\{cur\_y}-\\{y\_coord}(\|q)$;\6 -\&{end};\C{and they {\sl can't} both be zero}\2\2\6 -\&{end};\2\2\6 -$\\{dmax}\K\\{abs}(\\{dx2})$;\ \&{if} $\\{abs}(\\{dy2})>\\{dmax}$ \1\&{then}\5 -$\\{dmax}\K\\{abs}(\\{dy2})$;\2\6 -\&{while} $\\{dmax}<\\{fraction\_one}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\\{dmax})$;\5 -$\\{double}(\\{dx2})$;\5 -$\\{double}(\\{dy2})$;\6 -\&{end}\2\par -\U454.\fi - -\M458. \P$\X458:Insert additional boundary nodes, then \&{goto} \\{done}\X\S$\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\\{clockwise}$ \1\&{then}\6 -\&{if} $\\{o1}=1$ \1\&{then}\5 -$\\{o1}\K8$\ \&{else} $\\{decr}(\\{o1})$\2\6 -\4\&{else} \&{if} $\\{o1}=8$ \1\&{then}\5 -$\\{o1}\K1$\ \&{else} $\\{incr}(\\{o1})$;\2\2\6 -\&{if} $\\{o1}=\\{o2}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{new\_boundary}(\|s,\39\\{octant\_code}[\\{o1}])$;\5 -$\|s\K\\{link}(\|s)$;\5 -$\\{left\_octant}(\|s)\K\\{right\_octant}(\|s)$;\6 -\&{end}\2\par -\U452.\fi - -\M459. Now it remains to insert the redundant -transition information into the \\{left\_transition} -and \\{right\_transition} fields between adjacent octants, in the octant -boundary nodes that have just been inserted between $\\{link}(\|p)$ and~\|q. -The turning number is easily computed from these transitions. - -\Y\P$\4\X459:Fix up the transition fields and adjust the turning number\X\S$\6 -$\|p\K\\{link}(\|p)$;\6 -\1\&{repeat} \37$\|s\K\\{link}(\|p)$;\5 -$\\{o1}\K\\{octant\_number}[\\{right\_octant}(\|p)]$;\5 -$\\{o2}\K\\{octant\_number}[\\{left\_octant}(\|s)]$;\6 -\&{if} $\\{abs}(\\{o1}-\\{o2})=1$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{o2}<\\{o1}$ \1\&{then}\5 -$\\{o2}\K\\{o1}$;\2\6 -\&{if} $\\{odd}(\\{o2})$ \1\&{then}\5 -$\\{right\_transition}(\|p)\K\\{axis}$\6 -\4\&{else} $\\{right\_transition}(\|p)\K\\{diagonal}$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{o1}=8$ \1\&{then}\5 -$\\{incr}(\\{turning\_number})$\ \&{else} $\\{decr}(\\{turning\_number})$;\2\6 -$\\{right\_transition}(\|p)\K\\{axis}$;\6 -\&{end};\2\6 -$\\{left\_transition}(\|s)\K\\{right\_transition}(\|p)$;\5 -$\|p\K\|s$;\6 -\4\&{until}\5 -$\|p=\|q$\2\par -\U452.\fi - -\N460. \[22] Filling a contour. -Given the low-level machinery for making moves and for transforming a -cyclic path into a cycle spec, we're almost able to fill a digitized path. -All we need is a high-level routine that walks through the cycle spec and -controls the overall process. - -Our overall goal is to plot the integer points $\bigl(\round(x(t)), -\round(y(t))\bigr)$ and to connect them by rook moves, assuming that -$\round(x(t))$ and $\round(y(t))$ don't both jump simultaneously from -one integer to another as $t$~varies; these rook moves will be the edge -of the contour that will be filled. We have reduced this problem to the -case of curves that travel in first octant directions, i.e., curves -such that $0\L y'(t)\L x'(t)$, by transforming the original coordinates. - -\def\xtilde{{\tilde x}} \def\ytilde{{\tilde y}} -Another transformation makes the problem still simpler. We shall say that -we are working with {\sl biased coordinates\/} when $(x,y)$ has been -replaced by $(\xtilde,\ytilde)=(x-y,y+{1\over2})$. When a curve travels -in first octant directions, the corresponding curve with biased -coordinates travels in first {\sl quadrant\/} directions; the latter -condition is symmetric in $x$ and~$y$, so it has advantages for the -design of algorithms. The \\{make\_spec} routine gives us skewed coordinates -$(x-y,y)$, hence we obtain biased coordinates by simply adding $1\over2$ -to the second component. - -The most important fact about biased coordinates is that we can determine the -rounded unbiased path $\bigl(\round(x(t)),\round(y(t))\bigr)$ from the -truncated biased path $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor -\bigr)$ and information about the initial and final endpoints. If the -unrounded and unbiased -path begins at $(x_0,y_0)$ and ends at $(x_1,y_1)$, it's possible to -prove (by induction on the length of truncated biased path) that the -rounded unbiased path is obtained by the following construction: - -\yskip\textindent{1)} Start at $\bigl(\round(x_0),\round(y_0)\bigr)$. - -\yskip\textindent{2)} If $(x_0+{1\over2})\bmod1\G(y_0+{1\over2})\bmod1$, -move one step right. - -\yskip\textindent{3)} Whenever the path -$\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor\bigr)$ -takes an upward step (i.e., when -$\lfloor\xtilde(t+\epsilon)\rfloor=\lfloor\xtilde(t)\rfloor$ and -$\lfloor\ytilde(t+\epsilon)\rfloor=\lfloor\ytilde(t)\rfloor+1$), -move one step up and then one step right. - -\yskip\textindent{4)} Whenever the path -$\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor\bigr)$ -takes a rightward step (i.e., when -$\lfloor\xtilde(t+\epsilon)\rfloor=\lfloor\xtilde(t)\rfloor+1$ and -$\lfloor\ytilde(t+\epsilon)\rfloor=\lfloor\ytilde(t)\rfloor$), -move one step right. - -\yskip\textindent{5)} Finally, if -$(x_1+{1\over2})\bmod1\G(y_1+{1\over2})\bmod1$, move one step left (thereby -cancelling the previous move, which was one step right). You will now be -at the point $\bigl(\round(x_1),\round(y_1)\bigr)$. - -\fi - -\M461. In order to validate the assumption that $\round(x(t))$ and $% -\round(y(t))$ -don't both jump simultaneously, we shall consider that a coordinate pair -$(x,y)$ actually represents $(x+\epsilon,y+\epsilon\delta)$, where -$\epsilon$ and $\delta$ are extremely small positive numbers---so small -that their precise values never matter. This convention makes rounding -unambiguous, since there is always a unique integer point nearest to any -given scaled numbers~$(x,y)$. - -When coordinates are transformed so that \MF\ needs to work only in ``first -octant'' directions, the transformations involve negating~$x$, negating~$y$, -and/or interchanging $x$ with~$y$. Corresponding adjustments to the -rounding conventions must be made so that consistent values will be -obtained. For example, suppose that we're working with coordinates that -have been transformed so that a third-octant curve travels in first-octant -directions. The skewed coordinates $(x,y)$ in our data structure represent -unskewed coordinates $(-y,x+y)$, which are actually $(-y+\epsilon, -x+y+\epsilon\delta)$. We should therefore round as if our skewed coordinates -were $(x+\epsilon+\epsilon\delta,y-\epsilon)$ instead of $(x,y)$. The following -table shows how the skewed coordinates should be perturbed when rounding -decisions are made: -$$\vcenter{\halign{#\hfil&&\quad$#$\hfil&\hskip4em#\hfil\cr -\\{first\_octant}&(x+\epsilon-\epsilon\delta,y+\epsilon\delta)& -\\{fifth\_octant}&(x-\epsilon+\epsilon\delta,y-\epsilon\delta)\cr -\\{second\_octant}&(x-\epsilon+\epsilon\delta,y+\epsilon)& -\\{sixth\_octant}&(x+\epsilon-\epsilon\delta,y-\epsilon)\cr -\\{third\_octant}&(x+\epsilon+\epsilon\delta,y-\epsilon)& -\\{seventh\_octant}&(x-\epsilon-\epsilon\delta,y+\epsilon)\cr -\\{fourth\_octant}&(x-\epsilon-\epsilon\delta,y+\epsilon\delta)& -\\{eighth\_octant}&(x+\epsilon+\epsilon\delta,y-\epsilon\delta)\cr}}$$ - -Four small arrays are set up so that the rounding operations will be -fairly easy in any given octant. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{y\_corr},\39\\{xy\_corr},\39\\{z\_corr}$: \37\&{array} $[\\{first% -\_octant}\to\\{sixth\_octant}]$ \1\&{of}\5 -$0\to1$;\2\6 -\4\\{x\_corr}: \37\&{array} $[\\{first\_octant}\to\\{sixth\_octant}]$ \1\&{of}\5 -$-1\to1$;\2\par -\fi - -\M462. Here \\{xy\_corr} is 1 if and only if the $x$ component of a skewed -coordinate -is to be decreased by an infinitesimal amount; \\{y\_corr} is similar, but for -the $y$ components. The other tables are set up so that the condition -$$(x+y+\\{half\_unit})\bmod\\{unity}\G(y+\\{half\_unit})\bmod\\{unity}$$ -is properly perturbed to the condition -$$(x+y+\\{half\_unit}-\\{x\_corr}-\\{y\_corr})\bmod\\{unity}\G -(y+\\{half\_unit}-\\{y\_corr})\bmod\\{unity}+\\{z\_corr}.$$ - -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{x\_corr}[\\{first\_octant}]\K0$;\5 -$\\{y\_corr}[\\{first\_octant}]\K0$;\5 -$\\{xy\_corr}[\\{first\_octant}]\K0$;\6 -$\\{x\_corr}[\\{second\_octant}]\K0$;\5 -$\\{y\_corr}[\\{second\_octant}]\K0$;\5 -$\\{xy\_corr}[\\{second\_octant}]\K1$;\6 -$\\{x\_corr}[\\{third\_octant}]\K-1$;\5 -$\\{y\_corr}[\\{third\_octant}]\K1$;\5 -$\\{xy\_corr}[\\{third\_octant}]\K0$;\6 -$\\{x\_corr}[\\{fourth\_octant}]\K1$;\5 -$\\{y\_corr}[\\{fourth\_octant}]\K0$;\5 -$\\{xy\_corr}[\\{fourth\_octant}]\K1$;\6 -$\\{x\_corr}[\\{fifth\_octant}]\K0$;\5 -$\\{y\_corr}[\\{fifth\_octant}]\K1$;\5 -$\\{xy\_corr}[\\{fifth\_octant}]\K1$;\6 -$\\{x\_corr}[\\{sixth\_octant}]\K0$;\5 -$\\{y\_corr}[\\{sixth\_octant}]\K1$;\5 -$\\{xy\_corr}[\\{sixth\_octant}]\K0$;\6 -$\\{x\_corr}[\\{seventh\_octant}]\K1$;\5 -$\\{y\_corr}[\\{seventh\_octant}]\K0$;\5 -$\\{xy\_corr}[\\{seventh\_octant}]\K1$;\6 -$\\{x\_corr}[\\{eighth\_octant}]\K-1$;\5 -$\\{y\_corr}[\\{eighth\_octant}]\K1$;\5 -$\\{xy\_corr}[\\{eighth\_octant}]\K0$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}8$ \1\&{do}\5 -$\\{z\_corr}[\|k]\K\\{xy\_corr}[\|k]-\\{x\_corr}[\|k]$;\2\par -\fi - -\M463. Here's a procedure that handles the details of rounding at the -endpoints: Given skewed coordinates $(\|x,\|y)$, it sets $(\\{m1},\\{n1})$ -to the corresponding rounded lattice points, taking the current -\\{octant} into account. Global variable \\{d1} is also set to 1 if -$(x+y+{1\over2})\bmod1\G(y+{1\over2})\bmod1$. - -\Y\P\4\&{procedure}\1\ \37$\\{end\_round}(\|x,\39\|y:\\{scaled})$;\2\6 -\&{begin} \37$\|y\K\|y+\\{half\_unit}-\\{y\_corr}[\\{octant}]$;\5 -$\|x\K\|x+\|y-\\{x\_corr}[\\{octant}]$;\5 -$\\{m1}\K\\{floor\_unscaled}(\|x)$;\5 -$\\{n1}\K\\{floor\_unscaled}(\|y)$;\6 -\&{if} $\|x-\\{unity}\ast\\{m1}\G\|y-\\{unity}\ast\\{n1}+\\{z\_corr}[% -\\{octant}]$ \1\&{then}\5 -$\\{d1}\K1$\ \&{else} $\\{d1}\K0$;\2\6 -\&{end};\par -\fi - -\M464. The outputs $(\\{m1},\\{n1},\\{d1})$ of \\{end\_round} will sometimes be -moved -to $(\\{m0},\\{n0},\\{d0})$. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{m0},\39\\{n0},\39\\{m1},\39\\{n1}$: \37\\{integer};\C{lattice point -coordinates}\6 -\4$\\{d0},\39\\{d1}$: \37$0\to1$;\C{displacement corrections}\par -\fi - -\M465. We're ready now to fill the pixels enclosed by a given cycle spec~\|h; -the knot list that represents the cycle is destroyed in the process. -The edge structure that gets all the resulting data is \\{cur\_edges}, -and the edges are weighted by \\{cur\_wt}. - -\Y\P\4\&{procedure}\1\ \37$\\{fill\_spec}(\|h:\\{pointer})$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{for list traversal}% -\2\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -\\{begin\_edge\_tracing};\2\6 -$\|p\K\|h$;\C{we assume that $\\{left\_type}(\|h)=\\{endpoint}$}\6 -\1\&{repeat} \37$\\{octant}\K\\{left\_octant}(\|p)$;\5 -\X466:Set variable \|q to the node at the end of the current octant\X;\6 -\&{if} $\|q\I\|p$ \1\&{then}\6 -\&{begin} \37\X467:Determine the starting and ending lattice points $(\\{m0},% -\\{n0})$ and $(\\{m1},\\{n1})$\X;\6 -\X468:Make the moves for the current octant\X;\6 -$\\{move\_to\_edges}(\\{m0},\39\\{n0},\39\\{m1},\39\\{n1})$;\6 -\&{end};\2\6 -$\|p\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\|p=\|h$;\2\6 -$\\{toss\_knot\_list}(\|h)$;\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -\\{end\_edge\_tracing};\2\6 -\&{end};\par -\fi - -\M466. \P$\X466:Set variable \|q to the node at the end of the current octant\X% -\S$\6 -$\|q\K\|p$;\6 -\&{while} $\\{right\_type}(\|q)\I\\{endpoint}$ \1\&{do}\5 -$\|q\K\\{link}(\|q)$\2\par -\Us465, 506\ETs506.\fi - -\M467. \P$\X467:Determine the starting and ending lattice points $(\\{m0},% -\\{n0})$ and $(\\{m1},\\{n1})$\X\S$\6 -$\\{end\_round}(\\{x\_coord}(\|p),\39\\{y\_coord}(\|p))$;\5 -$\\{m0}\K\\{m1}$;\5 -$\\{n0}\K\\{n1}$;\5 -$\\{d0}\K\\{d1}$;\6 -$\\{end\_round}(\\{x\_coord}(\|q),\39\\{y\_coord}(\|q))$\par -\U465.\fi - -\M468. Finally we perform the five-step process that was explained at -the very beginning of this part of the program. - -\Y\P$\4\X468:Make the moves for the current octant\X\S$\6 -\&{if} $\\{n1}-\\{n0}\G\\{move\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"move\ table\ size"},\39\\{move\_size})$;\2\6 -$\\{move}[0]\K\\{d0}$;\5 -$\\{move\_ptr}\K0$;\5 -$\|r\K\|p$;\6 -\1\&{repeat} \37$\|s\K\\{link}(\|r)$;\6 -$\\{make\_moves}(\\{x\_coord}(\|r),\39\\{right\_x}(\|r),\39\\{left\_x}(\|s),\39% -\\{x\_coord}(\|s),\39\30\\{y\_coord}(\|r)+\\{half\_unit},\39\\{right\_y}(\|r)+% -\\{half\_unit},\39\\{left\_y}(\|s)+\\{half\_unit},\39\\{y\_coord}(\|s)+\\{half% -\_unit},\39\30\\{xy\_corr}[\\{octant}],\39\\{y\_corr}[\\{octant}])$;\5 -$\|r\K\|s$;\6 -\4\&{until}\5 -$\|r=\|q$;\2\6 -$\\{move}[\\{move\_ptr}]\K\\{move}[\\{move\_ptr}]-\\{d1}$;\6 -\&{if} $\\{internal}[\\{smoothing}]>0$ \1\&{then}\5 -$\\{smooth\_moves}(0,\39\\{move\_ptr})$\2\par -\U465.\fi - -\N469. \[23] Polygonal pens. -The next few parts of the program deal with the additional complications -associated with ``envelopes,'' leading up to an algorithm that fills a -contour with respect to a pen whose boundary is a convex polygon. The -mathematics underlying this algorithm is based on simple aspects of the -theory of tracings developed by Leo Guibas, Lyle Ramshaw, and Jorge -Stolfi [``A kinetic framework for computational geometry,'' -{\sl Proc.\ IEEE Symp.\ Foundations of Computer Science\/ \bf24} (1983), -100--111]. - -If the vertices of the polygon are $w_0$, $w_1$, \dots, $w_{n-1}$, $w_n=w_0$, -in counterclockwise order, the convexity condition requires that ``left -turns'' are made at each vertex when a person proceeds from $w_0$ to -$w_1$ to $\cdots$ to~$w_n$. The envelope is obtained if we offset a given -curve $z(t)$ by $w_k$ when that curve is traveling in a direction -$z'(t)$ lying between the directions $w_k-w_{k-1}$ and $w\k-w_k$. -At times~$t$ when the curve direction $z'(t)$ increases past -$w\k-w_k$, we temporarily stop plotting the offset curve and we insert -a straight line from $z(t)+w_k$ to $z(t)+w\k$; notice that this straight -line is tangent to the offset curve. Similarly, when the curve direction -decreases past $w_k-w_{k-1}$, we stop plotting and insert a straight -line from $z(t)+w_k$ to $z(t)+w_{k-1}$; the latter line is actually a -``retrograde'' step, which won't be part of the final envelope under -\MF's assumptions. The result of this construction is a continuous path -that consists of alternating curves and straight line segments. The -segments are usually so short, in practice, that they blend with the -curves; after all, it's possible to represent any digitized path as -a sequence of digitized straight lines. - -The nicest feature of this approach to envelopes is that it blends -perfectly with the octant subdivision process we have already developed. -The envelope travels in the same direction as the curve itself, as we -plot it, and we need merely be careful what offset is being added. -Retrograde motion presents a problem, but we will see that there is -a decent way to handle it. - -\fi - -\M470. We shall represent pens by maintaining eight lists of offsets, -one for each octant direction. The offsets at the boundary points -where a curve turns into a new octant will appear in the lists for -both octants. This means that we can restrict consideration to -segments of the original polygon whose directions aim in the first -octant, as we have done in the simpler case when envelopes were not -required. - -An example should help to clarify this situation: Consider the -quadrilateral whose vertices are $w_0=(0,-1)$, $w_1=(3,-1)$, -$w_2=(6,1)$, and $w_3=(1,2)$. A curve that travels in the first octant -will be offset by $w_1$ or $w_2$, unless its slope drops to zero -en route to the eighth octant; in the latter case we should switch to $w_0$ as -we cross the octant boundary. Our list for the first octant will -contain the three offsets $w_0$, $w_1$,~$w_2$. By convention we will -duplicate a boundary offset if the angle between octants doesn't -explicitly appear; in this case there is no explicit line of slope~1 -at the end of the list, so the full list is -$$w_0\;w_1\;w_2\;w_2\;=\;(0,-1)\;(3,-1)\;(6,1)\;(6,1).$$ -With skewed coordinates $(u-v,v)$ instead of $(u,v)$ we obtain the list -$$w_0\;w_1\;w_2\;w_2\;\mapsto\;(1,-1)\;(4,-1)\;(5,1)\;(5,1),$$ -which is what actually appears in the data structure. In the second -octant there's only one offset; we list it three times (with coordinates -interchanged, so as to make the second octant look like the first), -and skew those coordinates, obtaining -$$\tabskip\centering -\halign to\hsize{$\hfil#\;\mapsto\;{}$\tabskip=0pt& -$#\hfil$&\quad in the #\hfil\tabskip\centering\cr -w_2\;w_2\;w_2&(-5,6)\;(-5,6)\;(-5,6)\cr -\noalign{\vskip\belowdisplayskip -\vbox{\noindent\strut as the list of transformed and skewed offsets to use -when curves that travel in the second octant. Similarly, we will have\strut} -\vskip\abovedisplayskip} -w_2\;w_2\;w_2&(7,-6)\;(7,-6)\;(7,-6)&third;\cr -w_2\;w_2\;w_3\;w_3&(-7,1)\;(-7,1)\;(-3,2)\;(-3,2)&fourth;\cr -w_3\;w_3\;w_3&(3,-2)\;(3,-2)\;(3,-2)&fifth;\cr -w_3\;w_3\;w_0\;w_0&(-3,1)\;(-3,1)\;(1,0)\;(1,0)&sixth;\cr -w_0\;w_0\;w_0&(1,0)\;(1,0)\;(1,0)&seventh;\cr -w_0\;w_0\;w_0&(-1,1)\;(-1,1)\;(-1,1)&eighth.\cr}$$ -Notice that $w_1$ is considered here to be internal to the first octant; -it's not part of the eighth. We could equally well have taken $w_0$ out -of the first octant list and put it into the eighth; then the first octant -list would have been -$$w_1\;w_1\;w_2\;w_2\;\mapsto\;(4,-1)\;(4,-1)\;(5,1)\;(5,1)$$ -and the eighth octant list would have been -$$w_0\;w_0\;w_1\;\mapsto\;(-1,1)\;(-1,1)\;(2,1).$$ - -Actually, there's one more complication: The order of offsets is reversed -in even-numbered octants, because the transformation of coordinates has -reversed counterclockwise and clockwise orientations in those octants. -The offsets in the fourth octant, for example, are really $w_3$, $w_3$, -$w_2$,~$w_2$, not $w_2$, $w_2$, $w_3$,~$w_3$. - -\fi - -\M471. In general, the list of offsets for an octant will have the form -$$w_0\;\;w_1\;\;\ldots\;\;w_n\;\;w_{n+1}$$ -(if we renumber the subscripts in each list), where $w_0$ and $w_{n+1}$ -are offsets common to the neighboring lists. We'll often have $w_0=w_1$ -and/or $w_n=w_{n+1}$, but the other $w$'s will be distinct. Curves -that travel between slope~0 and direction $w_2-w_1$ will use offset~$w_1$; -curves that travel between directions $w_k-w_{k-1}$ and $w\k-w_k$ will -use offset~$w_k$, for $1<k<n$; curves between direction $w_n-w_{n-1}$ -and slope~1 (actually slope~$\infty$ after skewing) will use offset~$w_n$. -In even-numbered octants, the directions are actually $w_k-w\k$ instead -of $w\k-w_k$, because the offsets have been listed in reverse order. - -Each offset $w_k$ is represented by skewed coordinates $(u_k-v_k,v_k)$, -where $(u_k,v_k)$ is the representation of $w_k$ after it has been rotated -into a first-octant disguise. - -\fi - -\M472. The top-level data structure of a pen polygon is a 10-word node -containing -a reference count followed by pointers to the eight pen lists, followed -by an indication of the pen's range of values. - -If \|p~points to such a node, and if the -offset list for, say, the fourth octant has entries $w_0$, $w_1$, \dots, -$w_n$,~$w_{n+1}$, then $\\{info}(\|p+\\{fourth\_octant})$ will equal~$n$, and -$\\{link}(\|p+\\{fourth\_octant})$ will point to the offset node -containing~$w_0$. -Memory location $\|p+\\{fourth\_octant}$ is said to be the {\sl header\/} of -the pen-offset list for the fourth octant. Since this is an even-numbered -octant, $w_0$ is the offset that goes with the fifth octant, and -$w_{n+1}$ goes with the third. - -The elements of the offset list themselves are doubly linked 3-word nodes, -containing coordinates in their \\{x\_coord} and \\{y\_coord} fields. -The two link fields are called \\{link} and \\{knil}; if \|w~points to -the node for~$w_k$, then $\\{link}(\|w)$ and $\\{knil}(\|w)$ point respectively -to the nodes for $w\k$ and~$w_{k-1}$. If \|h is the list header, -$\\{link}(\|h)$ points to the node for~$w_0$ and $\\{knil}(\\{link}(\|h))$ to -the -node for~$w_{n+1}$. - -The tenth word of a pen header node contains the maximum absolute value of -an $x$ or $y$ coordinate among all of the unskewed pen offsets. - -The \\{link} field of a pen header node should be \\{null} if and only if -the pen has no offsets. - -\Y\P\D \37$\\{pen\_node\_size}=10$\par -\P\D \37$\\{coord\_node\_size}=3$\par -\P\D \37$\\{max\_offset}(\#)\S\\{mem}[\#+9].\\{sc}$\par -\fi - -\M473. The \\{print\_pen} subroutine illustrates these conventions by -reconstructing the vertices of a polygon from \MF's complicated -internal offset representation. - -\Y\P$\4\X257:Declare subroutines for printing expressions\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_pen}(\|p:\\{pointer};\,\35\|s:\\{str% -\_number};\,\35\\{nuline}:\\{boolean})$;\6 -\4\&{var} \37\\{nothing\_printed}: \37\\{boolean};\C{has there been any action -yet?}\6 -\|k: \37$1\to8$;\C{octant number}\6 -\|h: \37\\{pointer};\C{offset list head}\6 -$\|m,\39\|n$: \37\\{integer};\C{offset indices}\6 -$\|w,\39\\{ww}$: \37\\{pointer};\C{pointers that traverse the offset list}\2\6 -\&{begin} \37$\\{print\_diagnostic}(\.{"Pen\ polygon"},\39\|s,\39\\{nuline})$;\5 -$\\{nothing\_printed}\K\\{true}$;\5 -\\{print\_ln};\6 -\&{for} $\|k\K1\mathrel{\&{to}}8$ \1\&{do}\6 -\&{begin} \37$\\{octant}\K\\{octant\_code}[\|k]$;\5 -$\|h\K\|p+\\{octant}$;\5 -$\|n\K\\{info}(\|h)$;\5 -$\|w\K\\{link}(\|h)$;\6 -\&{if} $\R\\{odd}(\|k)$ \1\&{then}\5 -$\|w\K\\{knil}(\|w)$;\C{in even octants, start at $w_{n+1}$}\2\6 -\&{for} $\|m\K1\mathrel{\&{to}}\|n+1$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{odd}(\|k)$ \1\&{then}\5 -$\\{ww}\K\\{link}(\|w)$\ \&{else} $\\{ww}\K\\{knil}(\|w)$;\2\6 -\&{if} $(\\{x\_coord}(\\{ww})\I\\{x\_coord}(\|w))\V(\\{y\_coord}(\\{ww})\I\\{y% -\_coord}(\|w))$ \1\&{then}\5 -\X474:Print the unskewed and unrotated coordinates of node \\{ww}\X;\2\6 -$\|w\K\\{ww}$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{if} $\\{nothing\_printed}$ \1\&{then}\6 -\&{begin} \37$\|w\K\\{link}(\|p+\\{first\_octant})$;\5 -$\\{print\_two}(\\{x\_coord}(\|w)+\\{y\_coord}(\|w),\39\\{y\_coord}(\|w))$;\6 -\&{end};\2\6 -$\\{print\_nl}(\.{"\ ..\ cycle"})$;\5 -$\\{end\_diagnostic}(\\{true})$;\6 -\&{end};\par -\fi - -\M474. \P$\X474:Print the unskewed and unrotated coordinates of node \\{ww}\X% -\S$\6 -\&{begin} \37\&{if} $\\{nothing\_printed}$ \1\&{then}\5 -$\\{nothing\_printed}\K\\{false}$\6 -\4\&{else} $\\{print\_nl}(\.{"\ ..\ "})$;\2\6 -$\\{print\_two\_true}(\\{x\_coord}(\\{ww}),\39\\{y\_coord}(\\{ww}))$;\6 -\&{end}\par -\U473.\fi - -\M475. A null pen polygon, which has just one vertex $(0,0)$, is -predeclared for error recovery. It doesn't need a proper -reference count, because the \\{toss\_pen} procedure below -will never delete it from memory. - -\Y\P$\4\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}\S$\6 -$\\{ref\_count}(\\{null\_pen})\K\\{null}$;\5 -$\\{link}(\\{null\_pen})\K\\{null}$;\6 -$\\{info}(\\{null\_pen}+1)\K1$;\5 -$\\{link}(\\{null\_pen}+1)\K\\{null\_coords}$;\6 -\&{for} $\|k\K\\{null\_pen}+2\mathrel{\&{to}}\\{null\_pen}+8$ \1\&{do}\5 -$\\{mem}[\|k]\K\\{mem}[\\{null\_pen}+1]$;\2\6 -$\\{max\_offset}(\\{null\_pen})\K0$;\6 -$\\{link}(\\{null\_coords})\K\\{null\_coords}$;\5 -$\\{knil}(\\{null\_coords})\K\\{null\_coords}$;\6 -$\\{x\_coord}(\\{null\_coords})\K0$;\5 -$\\{y\_coord}(\\{null\_coords})\K0$;\par -\fi - -\M476. Here's a trivial subroutine that inserts a copy of an offset -on the \\{link} side of its clone in the doubly linked list. - -\Y\P\4\&{procedure}\1\ \37$\\{dup\_offset}(\|w:\\{pointer})$;\6 -\4\&{var} \37\|r: \37\\{pointer};\C{the new node}\2\6 -\&{begin} \37$\|r\K\\{get\_node}(\\{coord\_node\_size})$;\5 -$\\{x\_coord}(\|r)\K\\{x\_coord}(\|w)$;\5 -$\\{y\_coord}(\|r)\K\\{y\_coord}(\|w)$;\5 -$\\{link}(\|r)\K\\{link}(\|w)$;\5 -$\\{knil}(\\{link}(\|w))\K\|r$;\5 -$\\{knil}(\|r)\K\|w$;\5 -$\\{link}(\|w)\K\|r$;\6 -\&{end};\par -\fi - -\M477. The following algorithm is somewhat more interesting: It converts a -knot list for a cyclic path into a pen polygon, ignoring everything -but the \\{x\_coord}, \\{y\_coord}, and \\{link} fields. If the given path -vertices do not define a convex polygon, an error message is issued -and the null pen is returned. - -\Y\P\4\&{function}\1\ \37$\\{make\_pen}(\|h:\\{pointer})$: \37\\{pointer};\6 -\4\&{label} \37$\\{done},\39\\{done1},\39\\{not\_found},\39\\{found}$;\6 -\4\&{var} \37$\|o,\39\\{oo},\39\|k$: \37\\{small\_number};\C{octant -numbers---old, new, and current}\6 -\|p: \37\\{pointer};\C{top-level node for the new pen}\6 -$\|q,\39\|r,\39\|s,\39\|w,\39\\{hh}$: \37\\{pointer};\C{for list manipulation}\6 -\|n: \37\\{integer};\C{offset counter}\6 -$\\{dx},\39\\{dy}$: \37\\{scaled};\C{polygon direction}\6 -\\{mc}: \37\\{scaled};\C{the largest coordinate}\2\6 -\&{begin} \37\X479:Stamp all nodes with an octant code, compute the maximum -offset, and set \\{hh} to the node that begins the first octant; \&{goto} % -\\{not\_found} if there's a problem\X;\6 -\&{if} $\\{mc}\G\\{fraction\_one}-\\{half\_unit}$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\|p\K\\{get\_node}(\\{pen\_node\_size})$;\5 -$\|q\K\\{hh}$;\5 -$\\{max\_offset}(\|p)\K\\{mc}$;\5 -$\\{ref\_count}(\|p)\K\\{null}$;\6 -\&{if} $\\{link}(\|q)\I\|q$ \1\&{then}\5 -$\\{link}(\|p)\K\\{null}+1$;\2\6 -\&{for} $\|k\K1\mathrel{\&{to}}8$ \1\&{do}\5 -\X481:Construct the offset list for the \|kth octant\X;\2\6 -\&{goto} \37\\{found};\6 -\4\\{not\_found}: \37$\|p\K\\{null\_pen}$;\5 -\X478:Complain about a bad pen path\X;\6 -\4\\{found}: \37\&{if} $\\{internal}[\\{tracing\_pens}]>0$ \1\&{then}\5 -$\\{print\_pen}(\|p,\39\.{"\ (newly\ created)"},\39\\{true})$;\2\6 -$\\{make\_pen}\K\|p$;\6 -\&{end};\par -\fi - -\M478. \P$\X478:Complain about a bad pen path\X\S$\6 -\&{if} $\\{mc}\G\\{fraction\_one}-\\{half\_unit}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Pen\ too\ large"})$;\5 -$\\{help2}(\.{"The\ cycle\ you\ specified\ has\ a\ coordinate\ of\ 4095.5\ or\ -more."})$\6 -$(\.{"So\ I\'ve\ replaced\ it\ by\ the\ trivial\ path\ \`(0,0)..cycle\'."})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Pen\ cycle\ must\ be\ convex"})$;\5 -$\\{help3}(\.{"The\ cycle\ you\ specified\ either\ has\ consecutive\ equal\ -points"})$\6 -$(\.{"or\ turns\ right\ or\ turns\ through\ more\ than\ 360\ degrees."})$\6 -$(\.{"So\ I\'ve\ replaced\ it\ by\ the\ trivial\ path\ \`(0,0)..cycle\'."})$;\6 -\&{end};\2\6 -\\{put\_get\_error}\par -\U477.\fi - -\M479. There should be exactly one node whose octant number is less than its -predecessor in the cycle; that is node~\\{hh}. - -The loop here will terminate in all cases, but the proof is somewhat tricky: -If there are at least two distinct $y$~coordinates in the cycle, we will have -$\|o>4$ and $\|o\L4$ at different points of the cycle. Otherwise there are -at least two distinct $x$~coordinates, and we will have $\|o>2$ somewhere, -$\|o\L2$ somewhere. - -\Y\P$\4\X479:Stamp all nodes with an octant code, compute the maximum offset, -and set \\{hh} to the node that begins the first octant; \&{goto} \\{not% -\_found} if there's a problem\X\S$\6 -$\|q\K\|h$;\5 -$\|r\K\\{link}(\|q)$;\5 -$\\{mc}\K\\{abs}(\\{x\_coord}(\|h))$;\6 -\&{if} $\|q=\|r$ \1\&{then}\6 -\&{begin} \37$\\{hh}\K\|h$;\5 -$\\{right\_type}(\|h)\K0$;\C{this trick is explained below}\6 -\&{if} $\\{mc}<\\{abs}(\\{y\_coord}(\|h))$ \1\&{then}\5 -$\\{mc}\K\\{abs}(\\{y\_coord}(\|h))$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|o\K0$;\5 -$\\{hh}\K\\{null}$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|s\K\\{link}(\|r)$;\6 -\&{if} $\\{mc}<\\{abs}(\\{x\_coord}(\|r))$ \1\&{then}\5 -$\\{mc}\K\\{abs}(\\{x\_coord}(\|r))$;\2\6 -\&{if} $\\{mc}<\\{abs}(\\{y\_coord}(\|r))$ \1\&{then}\5 -$\\{mc}\K\\{abs}(\\{y\_coord}(\|r))$;\2\6 -$\\{dx}\K\\{x\_coord}(\|r)-\\{x\_coord}(\|q)$;\5 -$\\{dy}\K\\{y\_coord}(\|r)-\\{y\_coord}(\|q)$;\6 -\&{if} $\\{dx}=0$ \1\&{then}\6 -\&{if} $\\{dy}=0$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\C{double point}\2\2\6 -\&{if} $\\{ab\_vs\_cd}(\\{dx},\39\\{y\_coord}(\|s)-\\{y\_coord}(\|r),\39\\{dy},% -\39\\{x\_coord}(\|s)-\\{x\_coord}(\|r))<0$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\C{right turn}\2\6 -\X480:Determine the octant code for direction $(\\{dx},\\{dy})$\X;\6 -$\\{right\_type}(\|q)\K\\{octant}$;\5 -$\\{oo}\K\\{octant\_number}[\\{octant}]$;\6 -\&{if} $\|o>\\{oo}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{hh}\I\\{null}$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\C{$>360^\circ$}\2\6 -$\\{hh}\K\|q$;\6 -\&{end};\2\6 -$\|o\K\\{oo}$;\6 -\&{if} $(\|q=\|h)\W(\\{hh}\I\\{null})$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|q\K\|r$;\5 -$\|r\K\|s$;\6 -\&{end};\2\6 -\4\\{done}: \37\&{end}\2\par -\U477.\fi - -\M480. We want the octant for $(-\\{dx},-\\{dy})$ to be -exactly opposite the octant for $(\\{dx},\\{dy})$. - -\Y\P$\4\X480:Determine the octant code for direction $(\\{dx},\\{dy})$\X\S$\6 -\&{if} $\\{dx}>0$ \1\&{then}\5 -$\\{octant}\K\\{first\_octant}$\6 -\4\&{else} \&{if} $\\{dx}=0$ \1\&{then}\6 -\&{if} $\\{dy}>0$ \1\&{then}\5 -$\\{octant}\K\\{first\_octant}$\ \&{else} $\\{octant}\K\\{first\_octant}+% -\\{negate\_x}$\2\6 -\4\&{else} \&{begin} \37$\\{negate}(\\{dx})$;\5 -$\\{octant}\K\\{first\_octant}+\\{negate\_x}$;\6 -\&{end};\2\2\6 -\&{if} $\\{dy}<0$ \1\&{then}\6 -\&{begin} \37$\\{negate}(\\{dy})$;\5 -$\\{octant}\K\\{octant}+\\{negate\_y}$;\6 -\&{end}\6 -\4\&{else} \&{if} $\\{dy}=0$ \1\&{then}\6 -\&{if} $\\{octant}>\\{first\_octant}$ \1\&{then}\5 -$\\{octant}\K\\{first\_octant}+\\{negate\_x}+\\{negate\_y}$;\2\2\2\6 -\&{if} $\\{dx}<\\{dy}$ \1\&{then}\5 -$\\{octant}\K\\{octant}+\\{switch\_x\_and\_y}$\2\par -\U479.\fi - -\M481. Now \|q points to the node that the present octant shares with the -previous -octant, and $\\{right\_type}(\|q)$ is the octant code during which \|q~should -advance. -We have set $\\{right\_type}(\|q)=0$ in the special case that \|q should never -advance -(because the pen is degenerate). - -The number of offsets \|n must be smaller than \\{max\_quarterword}, because -the \\{fill\_envelope} routine stores $\|n+1$ in the \\{right\_type} field -of a knot node. - -\Y\P$\4\X481:Construct the offset list for the \|kth octant\X\S$\6 -\&{begin} \37$\\{octant}\K\\{octant\_code}[\|k]$;\5 -$\|n\K0$;\5 -$\|h\K\|p+\\{octant}$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|r\K\\{get\_node}(\\{coord\_node\_size})$;\5 -$\\{skew}(\\{x\_coord}(\|q),\39\\{y\_coord}(\|q),\39\\{octant})$;\5 -$\\{x\_coord}(\|r)\K\\{cur\_x}$;\5 -$\\{y\_coord}(\|r)\K\\{cur\_y}$;\6 -\&{if} $\|n=0$ \1\&{then}\5 -$\\{link}(\|h)\K\|r$\6 -\4\&{else} \X482:Link node \|r to the previous node\X;\2\6 -$\|w\K\|r$;\6 -\&{if} $\\{right\_type}(\|q)\I\\{octant}$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -$\|q\K\\{link}(\|q)$;\5 -$\\{incr}(\|n)$;\6 -\&{end};\2\6 -\4\\{done1}: \37\X483:Finish linking the offset nodes, and duplicate the -borderline offset nodes if necessary\X;\6 -\&{if} $\|n\G\\{max\_quarterword}$ \1\&{then}\5 -$\\{overflow}(\.{"pen\ polygon\ size"},\39\\{max\_quarterword})$;\2\6 -$\\{info}(\|h)\K\|n$;\6 -\&{end}\par -\U477.\fi - -\M482. Now \|w points to the node that was inserted most recently, and -\|k is the current octant number. - -\Y\P$\4\X482:Link node \|r to the previous node\X\S$\6 -\&{if} $\\{odd}(\|k)$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|w)\K\|r$;\5 -$\\{knil}(\|r)\K\|w$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{knil}(\|w)\K\|r$;\5 -$\\{link}(\|r)\K\|w$;\6 -\&{end}\2\par -\U481.\fi - -\M483. We have inserted $\|n+1$ nodes; it remains to duplicate the nodes at the -ends, if slopes 0 and~$\infty$ aren't already represented. At the end of -this section the total number of offset nodes should be $\|n+2$ -(since we call them $w_0$, $w_1$, \dots,~$w_{n+1}$). - -\Y\P$\4\X483:Finish linking the offset nodes, and duplicate the borderline -offset nodes if necessary\X\S$\6 -$\|r\K\\{link}(\|h)$;\6 -\&{if} $\\{odd}(\|k)$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|w)\K\|r$;\5 -$\\{knil}(\|r)\K\|w$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{knil}(\|w)\K\|r$;\5 -$\\{link}(\|r)\K\|w$;\5 -$\\{link}(\|h)\K\|w$;\5 -$\|r\K\|w$;\6 -\&{end};\2\6 -\&{if} $(\\{y\_coord}(\|r)\I\\{y\_coord}(\\{link}(\|r)))\V(\|n=0)$ \1\&{then}\6 -\&{begin} \37$\\{dup\_offset}(\|r)$;\5 -$\\{incr}(\|n)$;\6 -\&{end};\2\6 -$\|r\K\\{knil}(\|r)$;\6 -\&{if} $\\{x\_coord}(\|r)\I\\{x\_coord}(\\{knil}(\|r))$ \1\&{then}\5 -$\\{dup\_offset}(\|r)$\6 -\4\&{else} $\\{decr}(\|n)$\2\par -\U481.\fi - -\M484. Conversely, \\{make\_path} goes back from a pen to a cyclic path that -might have generated it. The structure of this subroutine is essentially -the same as \\{print\_pen}. - -\Y\P\hbox{\4}\X486:Declare the function called \\{trivial\_knot}\X\6 -\4\&{function}\1\ \37$\\{make\_path}(\\{pen\_head}:\\{pointer})$: \37% -\\{pointer};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the most recently copied knot}\6 -\|k: \37$1\to8$;\C{octant number}\6 -\|h: \37\\{pointer};\C{offset list head}\6 -$\|m,\39\|n$: \37\\{integer};\C{offset indices}\6 -$\|w,\39\\{ww}$: \37\\{pointer};\C{pointers that traverse the offset list}\2\6 -\&{begin} \37$\|p\K\\{temp\_head}$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}8$ \1\&{do}\6 -\&{begin} \37$\\{octant}\K\\{octant\_code}[\|k]$;\5 -$\|h\K\\{pen\_head}+\\{octant}$;\5 -$\|n\K\\{info}(\|h)$;\5 -$\|w\K\\{link}(\|h)$;\6 -\&{if} $\R\\{odd}(\|k)$ \1\&{then}\5 -$\|w\K\\{knil}(\|w)$;\C{in even octants, start at $w_{n+1}$}\2\6 -\&{for} $\|m\K1\mathrel{\&{to}}\|n+1$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{odd}(\|k)$ \1\&{then}\5 -$\\{ww}\K\\{link}(\|w)$\ \&{else} $\\{ww}\K\\{knil}(\|w)$;\2\6 -\&{if} $(\\{x\_coord}(\\{ww})\I\\{x\_coord}(\|w))\V(\\{y\_coord}(\\{ww})\I\\{y% -\_coord}(\|w))$ \1\&{then}\5 -\X485:Copy the unskewed and unrotated coordinates of node \\{ww}\X;\2\6 -$\|w\K\\{ww}$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{if} $\|p=\\{temp\_head}$ \1\&{then}\6 -\&{begin} \37$\|w\K\\{link}(\\{pen\_head}+\\{first\_octant})$;\5 -$\|p\K\\{trivial\_knot}(\\{x\_coord}(\|w)+\\{y\_coord}(\|w),\39\\{y\_coord}(% -\|w))$;\5 -$\\{link}(\\{temp\_head})\K\|p$;\6 -\&{end};\2\6 -$\\{link}(\|p)\K\\{link}(\\{temp\_head})$;\5 -$\\{make\_path}\K\\{link}(\\{temp\_head})$;\6 -\&{end};\par -\fi - -\M485. \P$\X485:Copy the unskewed and unrotated coordinates of node \\{ww}\X\S$% -\6 -\&{begin} \37$\\{unskew}(\\{x\_coord}(\\{ww}),\39\\{y\_coord}(\\{ww}),\39% -\\{octant})$;\5 -$\\{link}(\|p)\K\\{trivial\_knot}(\\{cur\_x},\39\\{cur\_y})$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end}\par -\U484.\fi - -\M486. \P$\X486:Declare the function called \\{trivial\_knot}\X\S$\6 -\4\&{function}\1\ \37$\\{trivial\_knot}(\|x,\39\|y:\\{scaled})$: \37% -\\{pointer};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{a new knot for explicit coordinates \|x and -\|y}\2\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{left\_type}(\|p)\K\\{explicit}$;\5 -$\\{right\_type}(\|p)\K\\{explicit}$;\6 -$\\{x\_coord}(\|p)\K\|x$;\5 -$\\{left\_x}(\|p)\K\|x$;\5 -$\\{right\_x}(\|p)\K\|x$;\6 -$\\{y\_coord}(\|p)\K\|y$;\5 -$\\{left\_y}(\|p)\K\|y$;\5 -$\\{right\_y}(\|p)\K\|y$;\6 -$\\{trivial\_knot}\K\|p$;\6 -\&{end};\par -\U484.\fi - -\M487. That which can be created can be destroyed. - -\Y\P\D \37$\\{add\_pen\_ref}(\#)\S\\{incr}(\\{ref\_count}(\#))$\par -\P\D \37$\\{delete\_pen\_ref}(\#)\S$\1\6 -\&{if} $\\{ref\_count}(\#)=\\{null}$ \1\&{then}\5 -$\\{toss\_pen}(\#)$\6 -\4\&{else} $\\{decr}(\\{ref\_count}(\#))$\2\2\par -\Y\P$\4\X268:Declare the recycling subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{toss\_pen}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|k: \37$1\to8$;\C{relative header locations}\6 -$\|w,\39\\{ww}$: \37\\{pointer};\C{pointers to offset nodes}\2\6 -\&{begin} \37\&{if} $\|p\I\\{null\_pen}$ \1\&{then}\6 -\&{begin} \37\&{for} $\|k\K1\mathrel{\&{to}}8$ \1\&{do}\6 -\&{begin} \37$\|w\K\\{link}(\|p+\|k)$;\6 -\1\&{repeat} \37$\\{ww}\K\\{link}(\|w)$;\5 -$\\{free\_node}(\|w,\39\\{coord\_node\_size})$;\5 -$\|w\K\\{ww}$;\6 -\4\&{until}\5 -$\|w=\\{link}(\|p+\|k)$;\2\6 -\&{end};\2\6 -$\\{free\_node}(\|p,\39\\{pen\_node\_size})$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M488. The \\{find\_offset} procedure sets $(\\{cur\_x},\\{cur\_y})$ to the -offset associated -with a given direction~$(\|x,\|y)$ and a given pen~\|p. If $\|x=\|y=0$, the -result is $(0,0)$. If two different offsets apply, one of them is -chosen arbitrarily. - -\Y\P\4\&{procedure}\1\ \37$\\{find\_offset}(\|x,\39\|y:\\{scaled};\,\35\|p:% -\\{pointer})$;\6 -\4\&{label} \37$\\{done},\39\\{exit}$;\6 -\4\&{var} \37\\{octant}: \37$\\{first\_octant}\to\\{sixth\_octant}$;\C{octant -code for $(\|x,\|y)$}\6 -\|s: \37$-1\to+1$;\C{sign of the octant}\6 -\|n: \37\\{integer};\C{number of offsets remaining}\6 -$\|h,\39\|w,\39\\{ww}$: \37\\{pointer};\C{list traversal registers}\2\6 -\&{begin} \37\X489:Compute the octant code; skew and rotate the coordinates $(% -\|x,\|y)$\X;\6 -\&{if} $\\{odd}(\\{octant\_number}[\\{octant}])$ \1\&{then}\5 -$\|s\K-1$\ \&{else} $\|s\K+1$;\2\6 -$\|h\K\|p+\\{octant}$;\5 -$\|w\K\\{link}(\\{link}(\|h))$;\5 -$\\{ww}\K\\{link}(\|w)$;\5 -$\|n\K\\{info}(\|h)$;\6 -\&{while} $\|n>1$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{ab\_vs\_cd}(\|x,\39\\{y\_coord}(\\{ww})-\\{y\_coord}(% -\|w),\39\30\|y,\39\\{x\_coord}(\\{ww})-\\{x\_coord}(\|w))\I\|s$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|w\K\\{ww}$;\5 -$\\{ww}\K\\{link}(\|w)$;\5 -$\\{decr}(\|n)$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{unskew}(\\{x\_coord}(\|w),\39\\{y\_coord}(\|w),\39% -\\{octant})$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M489. \P$\X489:Compute the octant code; skew and rotate the coordinates $(\|x,% -\|y)$\X\S$\6 -\&{if} $\|x>0$ \1\&{then}\5 -$\\{octant}\K\\{first\_octant}$\6 -\4\&{else} \&{if} $\|x=0$ \1\&{then}\6 -\&{if} $\|y\L0$ \1\&{then}\6 -\&{if} $\|y=0$ \1\&{then}\6 -\&{begin} \37$\\{cur\_x}\K0$;\5 -$\\{cur\_y}\K0$;\5 -\&{return};\6 -\&{end}\6 -\4\&{else} $\\{octant}\K\\{first\_octant}+\\{negate\_x}$\2\6 -\4\&{else} $\\{octant}\K\\{first\_octant}$\2\6 -\4\&{else} \&{begin} \37$\|x\K-\|x$;\6 -\&{if} $\|y=0$ \1\&{then}\5 -$\\{octant}\K\\{first\_octant}+\\{negate\_x}+\\{negate\_y}$\6 -\4\&{else} $\\{octant}\K\\{first\_octant}+\\{negate\_x}$;\2\6 -\&{end};\2\2\6 -\&{if} $\|y<0$ \1\&{then}\6 -\&{begin} \37$\\{octant}\K\\{octant}+\\{negate\_y}$;\5 -$\|y\K-\|y$;\6 -\&{end};\2\6 -\&{if} $\|x\G\|y$ \1\&{then}\5 -$\|x\K\|x-\|y$\6 -\4\&{else} \&{begin} \37$\\{octant}\K\\{octant}+\\{switch\_x\_and\_y}$;\5 -$\|x\K\|y-\|x$;\5 -$\|y\K\|y-\|x$;\6 -\&{end}\2\par -\U488.\fi - -\N490. \[24] Filling an envelope. -We are about to reach the culmination of \MF's digital plotting routines: -Almost all of the previous algorithms will be brought to bear on \MF's -most difficult task, which is to fill the envelope of a given cyclic path -with respect to a given pen polygon. - -But we still must complete some of the preparatory work before taking such -a big plunge. - -\fi - -\M491. Given a pointer \|c to a nonempty list of cubics, -and a pointer~\|h to the header information of a pen polygon segment, -the \\{offset\_prep} routine changes the list into cubics that are -associated with particular pen offsets. Namely, the cubic between \|p -and~\|q should be associated with the \|kth offset when $\\{right\_type}(\|p)=% -\|k$. - -List \|c is actually part of a cycle spec, so it terminates at the -first node whose \\{right\_type} is \\{endpoint}. The cubics all have -monotone-nondecreasing $x'(t)$ and $y'(t)$. - -\Y\P\hbox{\4}\X493:Declare subroutines needed by \\{offset\_prep}\X\6 -\4\&{procedure}\1\ \37$\\{offset\_prep}(\|c,\39\|h:\\{pointer})$;\6 -\4\&{label} \37$\\{done},\39\\{not\_found}$;\6 -\4\&{var} \37\|n: \37\\{halfword};\C{the number of pen offsets}\6 -$\|p,\39\|q,\39\|r,\39\\{lh},\39\\{ww}$: \37\\{pointer};\C{for list -manipulation}\6 -\|k: \37\\{halfword};\C{the current offset index}\6 -\|w: \37\\{pointer};\C{a pointer to offset $w_k$}\6 -\X495:Other local variables for \\{offset\_prep}\X\2\6 -\&{begin} \37$\|p\K\|c$;\5 -$\|n\K\\{info}(\|h)$;\5 -$\\{lh}\K\\{link}(\|h)$;\C{now \\{lh} points to $w_0$}\6 -\&{while} $\\{right\_type}(\|p)\I\\{endpoint}$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\5 -\X494:Split the cubic between \|p and \|q, if necessary, into cubics associated -with single offsets, after which \|q should point to the end of the final such -cubic\X;\6 -\X492:Advance \|p to node \|q, removing any ``dead'' cubics that might have -been introduced by the splitting process\X;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M492. \P$\X492:Advance \|p to node \|q, removing any ``dead'' cubics that -might have been introduced by the splitting process\X\S$\6 -\1\&{repeat} \37$\|r\K\\{link}(\|p)$;\6 -\&{if} $\\{x\_coord}(\|p)=\\{right\_x}(\|p)$ \1\&{then}\6 -\&{if} $\\{y\_coord}(\|p)=\\{right\_y}(\|p)$ \1\&{then}\6 -\&{if} $\\{x\_coord}(\|p)=\\{left\_x}(\|r)$ \1\&{then}\6 -\&{if} $\\{y\_coord}(\|p)=\\{left\_y}(\|r)$ \1\&{then}\6 -\&{if} $\\{x\_coord}(\|p)=\\{x\_coord}(\|r)$ \1\&{then}\6 -\&{if} $\\{y\_coord}(\|p)=\\{y\_coord}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{remove\_cubic}(\|p)$;\6 -\&{if} $\|r=\|q$ \1\&{then}\5 -$\|q\K\|p$;\2\6 -$\|r\K\|p$;\6 -\&{end};\2\2\2\2\2\2\6 -$\|p\K\|r$;\6 -\4\&{until}\5 -$\|p=\|q$\2\par -\U491.\fi - -\M493. The splitting process uses a subroutine like \\{split\_cubic}, but -(for ``bulletproof'' operation) we check to make sure that the -resulting (skewed) coordinates satisfy $\Delta x\G0$ and $\Delta y\G0$ -after splitting; \\{make\_spec} has made sure that these relations hold -before splitting. (This precaution is surely unnecessary, now that -\\{make\_spec} is so much more careful than it used to be. But who -wants to take a chance? Maybe the hardware will fail or something.) - -\Y\P$\4\X493:Declare subroutines needed by \\{offset\_prep}\X\S$\6 -\4\&{procedure}\1\ \37$\\{split\_for\_offset}(\|p:\\{pointer};\,\35\|t:% -\\{fraction})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the successor of \|p}\6 -\|r: \37\\{pointer};\C{the new node}\2\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\5 -$\\{split\_cubic}(\|p,\39\|t,\39\\{x\_coord}(\|q),\39\\{y\_coord}(\|q))$;\5 -$\|r\K\\{link}(\|p)$;\6 -\&{if} $\\{y\_coord}(\|r)<\\{y\_coord}(\|p)$ \1\&{then}\5 -$\\{y\_coord}(\|r)\K\\{y\_coord}(\|p)$\6 -\4\&{else} \&{if} $\\{y\_coord}(\|r)>\\{y\_coord}(\|q)$ \1\&{then}\5 -$\\{y\_coord}(\|r)\K\\{y\_coord}(\|q)$;\2\2\6 -\&{if} $\\{x\_coord}(\|r)<\\{x\_coord}(\|p)$ \1\&{then}\5 -$\\{x\_coord}(\|r)\K\\{x\_coord}(\|p)$\6 -\4\&{else} \&{if} $\\{x\_coord}(\|r)>\\{x\_coord}(\|q)$ \1\&{then}\5 -$\\{x\_coord}(\|r)\K\\{x\_coord}(\|q)$;\2\2\6 -\&{end};\par -\A497. -\U491.\fi - -\M494. If the pen polygon has \|n offsets, and if $w_k=(u_k,v_k)$ is the $k$th -of these, the $k$th pen slope is defined by the formula -$$s_k={v\k-v_k\over u\k-u_k},\qquad\hbox{for $0<k<n$}.$$ -In odd-numbered octants, the numerator and denominator of this fraction -will be positive; in even-numbered octants they will both be negative. -Furthermore we always have $0=s_0<s_1<\cdots<s_n=\infty$. The goal of -\\{offset\_prep} is to find an offset index~\|k to associate with -each cubic, such that the slope $s(t)$ of the cubic satisfies -$$s_{k-1}\le s(t)\le s_k\qquad\hbox{for $0\le t\le 1$.}\eqno(*)$$ -We may have to split a cubic into as many as $2n-1$ pieces before each -piece corresponds to a unique offset. - -\Y\P$\4\X494:Split the cubic between \|p and \|q, if necessary, into cubics -associated with single offsets, after which \|q should point to the end of the -final such cubic\X\S$\6 -\&{if} $\|n\L1$ \1\&{then}\5 -$\\{right\_type}(\|p)\K1$\C{this case is easy}\6 -\4\&{else} \&{begin} \37\X496:Prepare for derivative computations; \&{goto} % -\\{not\_found} if the current cubic is dead\X;\6 -\X501:Find the initial slope, $\\{dy}/\\{dx}$\X;\6 -\&{if} $\\{dx}=0$ \1\&{then}\5 -\X505:Handle the special case of infinite slope\X\6 -\4\&{else} \&{begin} \37\X502:Find the index \|k such that $s_{k-1}\L\\{dy}/% -\\{dx}<s_k$\X;\6 -\X503:Complete the offset splitting process\X;\6 -\&{end};\2\6 -\4\\{not\_found}: \37\&{end}\2\par -\U491.\fi - -\M495. The slope of a cubic $B(z_0,z_1,z_2,z_3;t)=\bigl(x(t),y(t)\bigr)$ can be -calculated from the quadratic polynomials -${1\over3}x'(t)=B(x_1-x_0,x_2-x_1,x_3-x_2;t)$ and -${1\over3}y'(t)=B(y_1-y_0,y_2-y_1,y_3-y_2;t)$. -Since we may be calculating slopes from several cubics -split from the current one, it is desirable to do these calculations -without losing too much precision. ``Scaled up'' values of the -derivatives, which will be less tainted by accumulated errors than -derivatives found from the cubics themselves, are maintained in -local variables \\{x0}, \\{x1}, and \\{x2}, representing $X_0=2^l(x_1-x_0)$, -$X_1=2^l(x_2-x_1)$, and $X_2=2^l(x_3-x_2)$; similarly \\{y0}, \\{y1}, and~% -\\{y2} -represent $Y_0=2^l(y_1-y_0)$, $Y_1=2^l(y_2-y_1)$, and $Y_2=2^l(y_3-y_2)$. -To test whether the slope of the cubic is $\ge s$ or $\le s$, we will test -the sign of the quadratic ${1\over3}2^l\bigl(y'(t)-sx'(t)\bigr)$ if $s\le1$, -or ${1\over3}2^l\bigl(y'(t)/s-x'(t)\bigr)$ if $s>1$. - -\Y\P$\4\X495:Other local variables for \\{offset\_prep}\X\S$\6 -\4$\\{x0},\39\\{x1},\39\\{x2},\39\\{y0},\39\\{y1},\39\\{y2}$: \37\\{integer};% -\C{representatives of derivatives}\6 -\4$\\{t0},\39\\{t1},\39\\{t2}$: \37\\{integer};\C{coefficients of polynomial -for slope testing}\6 -\4$\\{du},\39\\{dv},\39\\{dx},\39\\{dy}$: \37\\{integer};\C{for slopes of the -pen and the curve}\6 -\4\\{max\_coef}: \37\\{integer};\C{used while scaling}\6 -\4$\\{x0a},\39\\{x1a},\39\\{x2a},\39\\{y0a},\39\\{y1a},\39\\{y2a}$: \37% -\\{integer};\C{intermediate values}\6 -\4\|t: \37\\{fraction};\C{where the derivative passes through zero}\6 -\4\|s: \37\\{fraction};\C{slope or reciprocal slope}\par -\U491.\fi - -\M496. \P$\X496:Prepare for derivative computations; \&{goto} \\{not\_found} if -the current cubic is dead\X\S$\6 -$\\{x0}\K\\{right\_x}(\|p)-\\{x\_coord}(\|p)$;\C{should be $\G0$}\6 -$\\{x2}\K\\{x\_coord}(\|q)-\\{left\_x}(\|q)$;\C{likewise}\6 -$\\{x1}\K\\{left\_x}(\|q)-\\{right\_x}(\|p)$;\C{but this might be negative}\6 -$\\{y0}\K\\{right\_y}(\|p)-\\{y\_coord}(\|p)$;\5 -$\\{y2}\K\\{y\_coord}(\|q)-\\{left\_y}(\|q)$;\5 -$\\{y1}\K\\{left\_y}(\|q)-\\{right\_y}(\|p)$;\5 -$\\{max\_coef}\K\\{abs}(\\{x0})$;\C{we take \\{abs} just to make sure}\6 -\&{if} $\\{abs}(\\{x1})>\\{max\_coef}$ \1\&{then}\5 -$\\{max\_coef}\K\\{abs}(\\{x1})$;\2\6 -\&{if} $\\{abs}(\\{x2})>\\{max\_coef}$ \1\&{then}\5 -$\\{max\_coef}\K\\{abs}(\\{x2})$;\2\6 -\&{if} $\\{abs}(\\{y0})>\\{max\_coef}$ \1\&{then}\5 -$\\{max\_coef}\K\\{abs}(\\{y0})$;\2\6 -\&{if} $\\{abs}(\\{y1})>\\{max\_coef}$ \1\&{then}\5 -$\\{max\_coef}\K\\{abs}(\\{y1})$;\2\6 -\&{if} $\\{abs}(\\{y2})>\\{max\_coef}$ \1\&{then}\5 -$\\{max\_coef}\K\\{abs}(\\{y2})$;\2\6 -\&{if} $\\{max\_coef}=0$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{while} $\\{max\_coef}<\\{fraction\_half}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\\{max\_coef})$;\5 -$\\{double}(\\{x0})$;\5 -$\\{double}(\\{x1})$;\5 -$\\{double}(\\{x2})$;\5 -$\\{double}(\\{y0})$;\5 -$\\{double}(\\{y1})$;\5 -$\\{double}(\\{y2})$;\6 -\&{end}\2\par -\U494.\fi - -\M497. Let us first solve a special case of the problem: Suppose we -know an index~$k$ such that either (i)~$s(t)\G s_{k-1}$ for all~$t$ -and $s(0)<s_k$, or (ii)~$s(t)\L s_k$ for all~$t$ and $s(0)>s_{k-1}$. -Then, in a sense, we're halfway done, since one of the two inequalities -in $(*)$ is satisfied, and the other couldn't be satisfied for -any other value of~\|k. - -The \\{fin\_offset\_prep} subroutine solves the stated subproblem. -It has a boolean parameter called \\{rising} that is \\{true} in -case~(i), \\{false} in case~(ii). When $\\{rising}=\\{false}$, parameters -\\{x0} through \\{y2} represent the negative of the derivative of -the cubic following \|p; otherwise they represent the actual derivative. -The \|w parameter should point to offset~$w_k$. - -\Y\P$\4\X493:Declare subroutines needed by \\{offset\_prep}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{fin\_offset\_prep}(\|p:\\{pointer};\,\35\|k:% -\\{halfword};\,\35\|w:\\{pointer};\,\35\\{x0},\39\\{x1},\39\\{x2},\39\\{y0},\39% -\\{y1},\39\\{y2}:\\{integer};\,\35\\{rising}:\\{boolean};\,\35\|n:% -\\{integer})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\\{ww}: \37\\{pointer};\C{for list manipulation}\6 -$\\{du},\39\\{dv}$: \37\\{scaled};\C{for slope calculation}\6 -$\\{t0},\39\\{t1},\39\\{t2}$: \37\\{integer};\C{test coefficients}\6 -\|t: \37\\{fraction};\C{place where the derivative passes a critical slope}\6 -\|s: \37\\{fraction};\C{slope or reciprocal slope}\6 -\|v: \37\\{integer};\C{intermediate value for updating $\\{x0}\to\\{y2}$}\2\6 -\&{begin} \37\~ \1\&{loop}\6 -\&{begin} \37$\\{right\_type}(\|p)\K\|k$;\6 -\&{if} $\\{rising}$ \1\&{then}\6 -\&{if} $\|k=\|n$ \1\&{then}\5 -\&{return}\6 -\4\&{else} $\\{ww}\K\\{link}(\|w)$\C{a pointer to $w\k$}\2\6 -\4\&{else} \&{if} $\|k=1$ \1\&{then}\5 -\&{return}\6 -\4\&{else} $\\{ww}\K\\{knil}(\|w)$;\C{a pointer to $w_{k-1}$}\2\2\6 -\X498:Compute test coefficients $(\\{t0},\\{t1},\\{t2})$ for $s(t)$ versus -$s_k$ or $s_{k-1}$\X;\6 -$\|t\K\\{crossing\_point}(\\{t0},\39\\{t1},\39\\{t2})$;\6 -\&{if} $\|t\G\\{fraction\_one}$ \1\&{then}\5 -\&{return};\2\6 -\X499:Split the cubic at $t$, and split off another cubic if the derivative -crosses back\X;\6 -\&{if} $\\{rising}$ \1\&{then}\5 -$\\{incr}(\|k)$\ \&{else} $\\{decr}(\|k)$;\2\6 -$\|w\K\\{ww}$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M498. \P$\X498:Compute test coefficients $(\\{t0},\\{t1},\\{t2})$ for $s(t)$ -versus $s_k$ or $s_{k-1}$\X\S$\6 -$\\{du}\K\\{x\_coord}(\\{ww})-\\{x\_coord}(\|w)$;\5 -$\\{dv}\K\\{y\_coord}(\\{ww})-\\{y\_coord}(\|w)$;\6 -\&{if} $\\{abs}(\\{du})\G\\{abs}(\\{dv})$ \1\&{then}\C{$s_{k\pm1}\le1$}\6 -\&{begin} \37$\|s\K\\{make\_fraction}(\\{dv},\39\\{du})$;\5 -$\\{t0}\K\\{take\_fraction}(\\{x0},\39\|s)-\\{y0}$;\5 -$\\{t1}\K\\{take\_fraction}(\\{x1},\39\|s)-\\{y1}$;\5 -$\\{t2}\K\\{take\_fraction}(\\{x2},\39\|s)-\\{y2}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|s\K\\{make\_fraction}(\\{du},\39\\{dv})$;\5 -$\\{t0}\K\\{x0}-\\{take\_fraction}(\\{y0},\39\|s)$;\5 -$\\{t1}\K\\{x1}-\\{take\_fraction}(\\{y1},\39\|s)$;\5 -$\\{t2}\K\\{x2}-\\{take\_fraction}(\\{y2},\39\|s)$;\6 -\&{end}\2\par -\Us497\ET503.\fi - -\M499. The curve has crossed $s_k$ or $s_{k-1}$; its initial segment satisfies -$(*)$, and it might cross again and return towards $s_k$, yielding another -solution of $(*)$. - -\Y\P$\4\X499:Split the cubic at $t$, and split off another cubic if the -derivative crosses back\X\S$\6 -\&{begin} \37$\\{split\_for\_offset}(\|p,\39\|t)$;\5 -$\\{right\_type}(\|p)\K\|k$;\5 -$\|p\K\\{link}(\|p)$;\6 -$\|v\K\\{t\_of\_the\_way}(\\{x0})(\\{x1})$;\5 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\5 -$\\{x0}\K\\{t\_of\_the\_way}(\|v)(\\{x1})$;\6 -$\|v\K\\{t\_of\_the\_way}(\\{y0})(\\{y1})$;\5 -$\\{y1}\K\\{t\_of\_the\_way}(\\{y1})(\\{y2})$;\5 -$\\{y0}\K\\{t\_of\_the\_way}(\|v)(\\{y1})$;\6 -$\\{t1}\K\\{t\_of\_the\_way}(\\{t1})(\\{t2})$;\6 -\&{if} $\\{t1}>0$ \1\&{then}\5 -$\\{t1}\K0$;\C{without rounding error, \\{t1} would be $\L0$}\2\6 -$\|t\K\\{crossing\_point}(0,\39-\\{t1},\39-\\{t2})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\6 -\&{begin} \37$\\{split\_for\_offset}(\|p,\39\|t)$;\5 -$\\{right\_type}(\\{link}(\|p))\K\|k$;\6 -$\|v\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\5 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x0})(\\{x1})$;\5 -$\\{x2}\K\\{t\_of\_the\_way}(\\{x1})(\|v)$;\6 -$\|v\K\\{t\_of\_the\_way}(\\{y1})(\\{y2})$;\5 -$\\{y1}\K\\{t\_of\_the\_way}(\\{y0})(\\{y1})$;\5 -$\\{y2}\K\\{t\_of\_the\_way}(\\{y1})(\|v)$;\6 -\&{end};\2\6 -\&{end}\par -\U497.\fi - -\M500. Now we must consider the general problem of \\{offset\_prep}, when -nothing is known about a given cubic. We start by finding its -slope $s(0)$ in the vicinity of $\|t=0$. - -If $z'(t)=0$, the given cubic is numerically unstable, since the -slope direction is probably being influenced primarily by rounding -errors. A user who specifies such cuspy curves should expect to generate -rather wild results. The present code tries its best to believe the -existing data, as if no rounding errors were present. - -\fi - -\M501. \P$\X501:Find the initial slope, $\\{dy}/\\{dx}$\X\S$\6 -$\\{dx}\K\\{x0}$;\5 -$\\{dy}\K\\{y0}$;\6 -\&{if} $\\{dx}=0$ \1\&{then}\6 -\&{if} $\\{dy}=0$ \1\&{then}\6 -\&{begin} \37$\\{dx}\K\\{x1}$;\5 -$\\{dy}\K\\{y1}$;\6 -\&{if} $\\{dx}=0$ \1\&{then}\6 -\&{if} $\\{dy}=0$ \1\&{then}\6 -\&{begin} \37$\\{dx}\K\\{x2}$;\5 -$\\{dy}\K\\{y2}$;\6 -\&{end};\2\2\6 -\&{end}\2\2\par -\U494.\fi - -\M502. The next step is to bracket the initial slope between consecutive -slopes of the pen polygon. The most important invariant relation in the -following loop is that $\\{dy}/\\{dx}\G\hbox{$s_{k-1}$}$. - -\Y\P$\4\X502:Find the index \|k such that $s_{k-1}\L\\{dy}/\\{dx}<s_k$\X\S$\6 -$\|k\K1$;\5 -$\|w\K\\{link}(\\{lh})$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|k=\|n$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{ww}\K\\{link}(\|w)$;\6 -\&{if} $\\{ab\_vs\_cd}(\\{dy},\39\\{abs}(\\{x\_coord}(\\{ww})-\\{x\_coord}(% -\|w)),\39\30\\{dx},\39\\{abs}(\\{y\_coord}(\\{ww})-\\{y\_coord}(\|w)))\G0$ \1% -\&{then}\6 -\&{begin} \37$\\{incr}(\|k)$;\5 -$\|w\K\\{ww}$;\6 -\&{end}\6 -\4\&{else} \&{goto} \37\\{done};\2\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U494.\fi - -\M503. Finally we want to reduce the general problem to situations that -\\{fin\_offset\_prep} can handle. If $\|k=1$, we already are in the desired -situation. Otherwise we can split the cubic into at most three parts -with respect to $s_{k-1}$, and apply \\{fin\_offset\_prep} to each part. - -\Y\P$\4\X503:Complete the offset splitting process\X\S$\6 -\&{if} $\|k=1$ \1\&{then}\5 -$\|t\K\\{fraction\_one}+1$\6 -\4\&{else} \&{begin} \37$\\{ww}\K\\{knil}(\|w)$;\5 -\X498:Compute test coefficients $(\\{t0},\\{t1},\\{t2})$ for $s(t)$ versus -$s_k$ or $s_{k-1}$\X;\6 -$\|t\K\\{crossing\_point}(-\\{t0},\39-\\{t1},\39-\\{t2})$;\6 -\&{end};\2\6 -\&{if} $\|t\G\\{fraction\_one}$ \1\&{then}\5 -$\\{fin\_offset\_prep}(\|p,\39\|k,\39\|w,\39\\{x0},\39\\{x1},\39\\{x2},\39% -\\{y0},\39\\{y1},\39\\{y2},\39\\{true},\39\|n)$\6 -\4\&{else} \&{begin} \37$\\{split\_for\_offset}(\|p,\39\|t)$;\5 -$\|r\K\\{link}(\|p)$;\6 -$\\{x1a}\K\\{t\_of\_the\_way}(\\{x0})(\\{x1})$;\5 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\5 -$\\{x2a}\K\\{t\_of\_the\_way}(\\{x1a})(\\{x1})$;\6 -$\\{y1a}\K\\{t\_of\_the\_way}(\\{y0})(\\{y1})$;\5 -$\\{y1}\K\\{t\_of\_the\_way}(\\{y1})(\\{y2})$;\5 -$\\{y2a}\K\\{t\_of\_the\_way}(\\{y1a})(\\{y1})$;\6 -$\\{fin\_offset\_prep}(\|p,\39\|k,\39\|w,\39\\{x0},\39\\{x1a},\39\\{x2a},\39% -\\{y0},\39\\{y1a},\39\\{y2a},\39\\{true},\39\|n)$;\5 -$\\{x0}\K\\{x2a}$;\5 -$\\{y0}\K\\{y2a}$;\5 -$\\{t1}\K\\{t\_of\_the\_way}(\\{t1})(\\{t2})$;\6 -\&{if} $\\{t1}<0$ \1\&{then}\5 -$\\{t1}\K0$;\2\6 -$\|t\K\\{crossing\_point}(0,\39\\{t1},\39\\{t2})$;\6 -\&{if} $\|t<\\{fraction\_one}$ \1\&{then}\5 -\X504:Split off another \\{rising} cubic for \\{fin\_offset\_prep}\X;\2\6 -$\\{fin\_offset\_prep}(\|r,\39\|k-1,\39\\{ww},\39-\\{x0},\39-\\{x1},\39-\\{x2},% -\39-\\{y0},\39-\\{y1},\39-\\{y2},\39\\{false},\39\|n)$;\6 -\&{end}\2\par -\U494.\fi - -\M504. \P$\X504:Split off another \\{rising} cubic for \\{fin\_offset\_prep}\X% -\S$\6 -\&{begin} \37$\\{split\_for\_offset}(\|r,\39\|t)$;\6 -$\\{x1a}\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\5 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x0})(\\{x1})$;\5 -$\\{x0a}\K\\{t\_of\_the\_way}(\\{x1})(\\{x1a})$;\6 -$\\{y1a}\K\\{t\_of\_the\_way}(\\{y1})(\\{y2})$;\5 -$\\{y1}\K\\{t\_of\_the\_way}(\\{y0})(\\{y1})$;\5 -$\\{y0a}\K\\{t\_of\_the\_way}(\\{y1})(\\{y1a})$;\6 -$\\{fin\_offset\_prep}(\\{link}(\|r),\39\|k,\39\|w,\39\\{x0a},\39\\{x1a},\39% -\\{x2},\39\\{y0a},\39\\{y1a},\39\\{y2},\39\\{true},\39\|n)$;\5 -$\\{x2}\K\\{x0a}$;\5 -$\\{y2}\K\\{y0a}$;\6 -\&{end}\par -\U503.\fi - -\M505. \P$\X505:Handle the special case of infinite slope\X\S$\6 -$\\{fin\_offset\_prep}(\|p,\39\|n,\39\\{knil}(\\{knil}(\\{lh})),\39-\\{x0},\39-% -\\{x1},\39-\\{x2},\39-\\{y0},\39-\\{y1},\39-\\{y2},\39\\{false},\39\|n)$\par -\U494.\fi - -\M506. OK, it's time now for the biggie. The \\{fill\_envelope} routine -generalizes -\\{fill\_spec} to polygonal envelopes. Its outer structure is essentially the -same as before, except that octants with no cubics do contribute to -the envelope. - -\Y\P\hbox{\4}\X510:Declare the procedure called \\{skew\_line\_edges}\X\6 -\hbox{\4}\X518:Declare the procedure called \\{dual\_moves}\X\6 -\4\&{procedure}\1\ \37$\\{fill\_envelope}(\\{spec\_head}:\\{pointer})$;\6 -\4\&{label} \37$\\{done},\39\\{done1}$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{for list traversal}\6 -\|h: \37\\{pointer};\C{head of pen offset list for current octant}\6 -\\{www}: \37\\{pointer};\C{a pen offset of temporary interest}\6 -\X511:Other local variables for \\{fill\_envelope}\X\2\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -\\{begin\_edge\_tracing};\2\6 -$\|p\K\\{spec\_head}$;\C{we assume that $\\{left\_type}(\\{spec\_head})=% -\\{endpoint}$}\6 -\1\&{repeat} \37$\\{octant}\K\\{left\_octant}(\|p)$;\5 -$\|h\K\\{cur\_pen}+\\{octant}$;\5 -\X466:Set variable \|q to the node at the end of the current octant\X;\6 -\X508:Determine the envelope's starting and ending lattice points $(\\{m0},% -\\{n0})$ and $(\\{m1},\\{n1})$\X;\6 -$\\{offset\_prep}(\|p,\39\|h)$;\C{this may clobber node~\|q, if it becomes -``dead''}\6 -\X466:Set variable \|q to the node at the end of the current octant\X;\6 -\X512:Make the envelope moves for the current octant and insert them in the -pixel data\X;\6 -$\|p\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\|p=\\{spec\_head}$;\2\6 -\&{if} $\\{internal}[\\{tracing\_edges}]>0$ \1\&{then}\5 -\\{end\_edge\_tracing};\2\6 -$\\{toss\_knot\_list}(\\{spec\_head})$;\6 -\&{end};\par -\fi - -\M507. In even-numbered octants we have reflected the coordinates an odd number -of times, hence clockwise and counterclockwise are reversed; this means that -the envelope is being formed in a ``dual'' manner. For the time being, let's -concentrate on odd-numbered octants, since they're easier to understand. -After we have coded the program for odd-numbered octants, the changes needed -to dualize it will not be so mysterious. - -It is convenient to assume that we enter an odd-numbered octant with -an \\{axis} transition (where the skewed slope is zero) and leave at a -\\{diagonal} one (where the skewed slope is infinite). Then all of the -offset points $z(t)+w(t)$ will lie in a rectangle whose lower left and -upper right corners are the initial and final offset points. If this -assumption doesn't hold we can implicitly change the curve so that it does. -For example, if the entering transition is diagonal, we can draw a -straight line from $z_0+w_{n+1}$ to $z_0+w_0$ and continue as if the -curve were moving rightward. The effect of this on the envelope is simply -to ``doubly color'' the region enveloped by a section of the pen that -goes from $w_0$ to $w_1$ to $\cdots$ to $w_{n+1}$ to~$w_0$. The additional -straight line at the beginning (and a similar one at the end, where it -may be necessary to go from $z_1+w_{n+1}$ to $z_1+w_0$) can be drawn by -the \\{line\_edges} routine; we are thereby saved from the embarrassment that -these lines travel backwards from the current octant direction. - -Once we have established the assumption that the curve goes from -$z_0+w_0$ to $z_1+w_{n+1}$, any further retrograde moves that might -occur within the octant can be essentially ignored; we merely need to -keep track of the rightmost edge in each row, in order to compute -the envelope. - -Envelope moves consist of offset cubics intermixed with straight line -segments. We record them in a separate \\{env\_move} array, which is -something like \\{move} but it keeps track of the rightmost position of the -envelope in each row. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{env\_move}: \37\&{array} $[0\to\\{move\_size}]$ \1\&{of}\5 -\\{integer};\2\par -\fi - -\M508. \P$\X508:Determine the envelope's starting and ending lattice points $(% -\\{m0},\\{n0})$ and $(\\{m1},\\{n1})$\X\S$\6 -$\|w\K\\{link}(\|h)$;\ \&{if} $\\{left\_transition}(\|p)=\\{diagonal}$ \1% -\&{then}\5 -$\|w\K\\{knil}(\|w)$;\2\6 -\&{stat} \37\&{if} $\\{internal}[\\{tracing\_edges}]>\\{unity}$ \1\&{then}\5 -\X509:Print a line of diagnostic info to introduce this octant\X;\2\6 -\&{tats}\6 -$\\{ww}\K\\{link}(\|h)$;\5 -$\\{www}\K\\{ww}$;\C{starting and ending offsets}\6 -\&{if} $\\{odd}(\\{octant\_number}[\\{octant}])$ \1\&{then}\5 -$\\{www}\K\\{knil}(\\{www})$\ \&{else} $\\{ww}\K\\{knil}(\\{ww})$;\2\6 -\&{if} $\|w\I\\{ww}$ \1\&{then}\5 -$\\{skew\_line\_edges}(\|p,\39\|w,\39\\{ww})$;\2\6 -$\\{end\_round}(\\{x\_coord}(\|p)+\\{x\_coord}(\\{ww}),\39\\{y\_coord}(\|p)+% -\\{y\_coord}(\\{ww}))$;\5 -$\\{m0}\K\\{m1}$;\5 -$\\{n0}\K\\{n1}$;\5 -$\\{d0}\K\\{d1}$;\6 -$\\{end\_round}(\\{x\_coord}(\|q)+\\{x\_coord}(\\{www}),\39\\{y\_coord}(\|q)+% -\\{y\_coord}(\\{www}))$;\6 -\&{if} $\\{n1}-\\{n0}\G\\{move\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"move\ table\ size"},\39\\{move\_size})$\2\par -\U506.\fi - -\M509. \P$\X509:Print a line of diagnostic info to introduce this octant\X\S$\6 -\&{begin} \37$\\{print\_nl}(\.{"@\ Octant\ "})$;\5 -$\\{print}(\\{octant\_dir}[\\{octant}])$;\5 -$\\{print}(\.{"\ ("})$;\5 -$\\{print\_int}(\\{info}(\|h))$;\5 -$\\{print}(\.{"\ offset"})$;\6 -\&{if} $\\{info}(\|h)\I1$ \1\&{then}\5 -$\\{print\_char}(\.{"s"})$;\2\6 -$\\{print}(\.{"),\ from\ "})$;\5 -$\\{print\_two\_true}(\\{x\_coord}(\|p)+\\{x\_coord}(\|w),\39\\{y\_coord}(\|p)+% -\\{y\_coord}(\|w))$;\5 -$\\{ww}\K\\{link}(\|h)$;\ \&{if} $\\{right\_transition}(\|q)=\\{diagonal}$ \1% -\&{then}\5 -$\\{ww}\K\\{knil}(\\{ww})$;\2\6 -$\\{print}(\.{"\ to\ "})$;\5 -$\\{print\_two\_true}(\\{x\_coord}(\|q)+\\{x\_coord}(\\{ww}),\39\\{y\_coord}(% -\|q)+\\{y\_coord}(\\{ww}))$;\6 -\&{end}\par -\U508.\fi - -\M510. A slight variation of the \\{line\_edges} procedure comes in handy -when we must draw the retrograde lines for nonstandard entry and exit -conditions. - -\Y\P$\4\X510:Declare the procedure called \\{skew\_line\_edges}\X\S$\6 -\4\&{procedure}\1\ \37$\\{skew\_line\_edges}(\|p,\39\|w,\39\\{ww}:% -\\{pointer})$;\6 -\4\&{var} \37$\\{x0},\39\\{y0},\39\\{x1},\39\\{y1}$: \37\\{scaled};\C{from and -to}\2\6 -\&{begin} \37\&{if} $(\\{x\_coord}(\|w)\I\\{x\_coord}(\\{ww}))\V(\\{y\_coord}(% -\|w)\I\\{y\_coord}(\\{ww}))$ \1\&{then}\6 -\&{begin} \37$\\{x0}\K\\{x\_coord}(\|p)+\\{x\_coord}(\|w)$;\5 -$\\{y0}\K\\{y\_coord}(\|p)+\\{y\_coord}(\|w)$;\6 -$\\{x1}\K\\{x\_coord}(\|p)+\\{x\_coord}(\\{ww})$;\5 -$\\{y1}\K\\{y\_coord}(\|p)+\\{y\_coord}(\\{ww})$;\6 -$\\{unskew}(\\{x0},\39\\{y0},\39\\{octant})$;\C{unskew and unrotate the -coordinates}\6 -$\\{x0}\K\\{cur\_x}$;\5 -$\\{y0}\K\\{cur\_y}$;\6 -$\\{unskew}(\\{x1},\39\\{y1},\39\\{octant})$;\6 -\&{stat} \37\&{if} $\\{internal}[\\{tracing\_edges}]>\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"@\ retrograde\ line\ from\ "})$;\5 -$\\{print\_two}(\\{x0},\39\\{y0})$;\5 -$\\{print}(\.{"\ to\ "})$;\5 -$\\{print\_two}(\\{cur\_x},\39\\{cur\_y})$;\5 -$\\{print\_nl}(\.{""})$;\6 -\&{end};\ \2\6 -\&{tats}\6 -$\\{line\_edges}(\\{x0},\39\\{y0},\39\\{cur\_x},\39\\{cur\_y})$;\C{then draw a -straight line}\6 -\&{end};\2\6 -\&{end};\par -\U506.\fi - -\M511. The envelope calculations require more local variables than we needed -in the simpler case of \\{fill\_spec}. At critical points in the computation, -\|w will point to offset $w_k$; \|m and \|n will record the current -lattice positions. The values of \\{move\_ptr} after the initial and before -the final offset adjustments are stored in \\{smooth\_bot} and \\{smooth\_top}, -respectively. - -\Y\P$\4\X511:Other local variables for \\{fill\_envelope}\X\S$\6 -\4$\|m,\39\|n$: \37\\{integer};\C{current lattice position}\6 -\4$\\{mm0},\39\\{mm1}$: \37\\{integer};\C{skewed equivalents of \\{m0} and % -\\{m1}}\6 -\4\|k: \37\\{integer};\C{current offset number}\6 -\4$\|w,\39\\{ww}$: \37\\{pointer};\C{pointers to the current offset and its -neighbor}\6 -\4$\\{smooth\_bot},\39\\{smooth\_top}$: \37$0\to\\{move\_size}$;\C{boundaries -of smoothing}\6 -\4$\\{xx},\39\\{yy},\39\\{xp},\39\\{yp},\39\\{delx},\39\\{dely},\39\\{tx},\39% -\\{ty}$: \37\\{scaled};\C{registers for coordinate calculations}\par -\Us506\ET518.\fi - -\M512. \P$\X512:Make the envelope moves for the current octant and insert them -in the pixel data\X\S$\6 -\&{if} $\\{odd}(\\{octant\_number}[\\{octant}])$ \1\&{then}\6 -\&{begin} \37\X513:Initialize for ordinary envelope moves\X;\6 -$\|r\K\|p$;\5 -$\\{right\_type}(\|q)\K\\{info}(\|h)+1$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|r=\|q$ \1\&{then}\5 -$\\{smooth\_top}\K\\{move\_ptr}$;\2\6 -\&{while} $\\{right\_type}(\|r)\I\|k$ \1\&{do}\5 -\X515:Insert a line segment to approach the correct offset\X;\2\6 -\&{if} $\|r=\|p$ \1\&{then}\5 -$\\{smooth\_bot}\K\\{move\_ptr}$;\2\6 -\&{if} $\|r=\|q$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{move}[\\{move\_ptr}]\K1$;\5 -$\|n\K\\{move\_ptr}$;\5 -$\|s\K\\{link}(\|r)$;\6 -$\\{make\_moves}(\\{x\_coord}(\|r)+\\{x\_coord}(\|w),\39\\{right\_x}(\|r)+\\{x% -\_coord}(\|w),\39\\{left\_x}(\|s)+\\{x\_coord}(\|w),\39\\{x\_coord}(\|s)+\\{x% -\_coord}(\|w),\39\30\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit},\39% -\\{right\_y}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit},\39\\{left\_y}(\|s)+\\{y% -\_coord}(\|w)+\\{half\_unit},\39\\{y\_coord}(\|s)+\\{y\_coord}(\|w)+\\{half% -\_unit},\39\30\\{xy\_corr}[\\{octant}],\39\\{y\_corr}[\\{octant}])$;\6 -\X514:Transfer moves from the \\{move} array to \\{env\_move}\X;\6 -$\|r\K\|s$;\6 -\&{end};\2\6 -\4\\{done}: \37\X517:Insert the new envelope moves in the pixel data\X;\6 -\&{end}\6 -\4\&{else} $\\{dual\_moves}(\|h,\39\|p,\39\|q)$;\2\6 -$\\{right\_type}(\|q)\K\\{endpoint}$\par -\U506.\fi - -\M513. \P$\X513:Initialize for ordinary envelope moves\X\S$\6 -$\|k\K0$;\5 -$\|w\K\\{link}(\|h)$;\5 -$\\{ww}\K\\{knil}(\|w)$;\5 -$\\{mm0}\K\\{floor\_unscaled}(\\{x\_coord}(\|p)+\\{x\_coord}(\|w)-\\{xy\_corr}[% -\\{octant}])$;\5 -$\\{mm1}\K\\{floor\_unscaled}(\\{x\_coord}(\|q)+\\{x\_coord}(\\{ww})-\\{xy% -\_corr}[\\{octant}])$;\6 -\&{for} $\|n\K0\mathrel{\&{to}}\\{n1}-\\{n0}$ \1\&{do}\5 -$\\{env\_move}[\|n]\K\\{mm0}$;\2\6 -$\\{env\_move}[\\{n1}-\\{n0}]\K\\{mm1}$;\5 -$\\{move\_ptr}\K0$;\5 -$\|m\K\\{mm0}$\par -\U512.\fi - -\M514. At this point \|n holds the value of \\{move\_ptr} that was current -when \\{make\_moves} began to record its moves. - -\Y\P$\4\X514:Transfer moves from the \\{move} array to \\{env\_move}\X\S$\6 -\1\&{repeat} \37$\|m\K\|m+\\{move}[\|n]-1$;\6 -\&{if} $\|m>\\{env\_move}[\|n]$ \1\&{then}\5 -$\\{env\_move}[\|n]\K\|m$;\2\6 -$\\{incr}(\|n)$;\6 -\4\&{until}\5 -$\|n>\\{move\_ptr}$\2\par -\U512.\fi - -\M515. Retrograde lines (when \|k decreases) do not need to be recorded in -\\{env\_move} because their edges are not the furthest right in any row. - -\Y\P$\4\X515:Insert a line segment to approach the correct offset\X\S$\6 -\&{begin} \37$\\{xx}\K\\{x\_coord}(\|r)+\\{x\_coord}(\|w)$;\5 -$\\{yy}\K\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit}$;\6 -\&{stat} \37\&{if} $\\{internal}[\\{tracing\_edges}]>\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"@\ transition\ line\ "})$;\5 -$\\{print\_int}(\|k)$;\5 -$\\{print}(\.{",\ from\ "})$;\5 -$\\{print\_two\_true}(\\{xx},\39\\{yy}-\\{half\_unit})$;\6 -\&{end};\ \2\6 -\&{tats}\6 -\&{if} $\\{right\_type}(\|r)>\|k$ \1\&{then}\6 -\&{begin} \37$\\{incr}(\|k)$;\5 -$\|w\K\\{link}(\|w)$;\5 -$\\{xp}\K\\{x\_coord}(\|r)+\\{x\_coord}(\|w)$;\5 -$\\{yp}\K\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit}$;\6 -\&{if} $\\{yp}\I\\{yy}$ \1\&{then}\5 -\X516:Record a line segment from $(\\{xx},\\{yy})$ to $(\\{xp},\\{yp})$ in % -\\{env\_move}\X;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{decr}(\|k)$;\5 -$\|w\K\\{knil}(\|w)$;\5 -$\\{xp}\K\\{x\_coord}(\|r)+\\{x\_coord}(\|w)$;\5 -$\\{yp}\K\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit}$;\6 -\&{end};\2\6 -\&{stat} \37\&{if} $\\{internal}[\\{tracing\_edges}]>\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\ to\ "})$;\5 -$\\{print\_two\_true}(\\{xp},\39\\{yp}-\\{half\_unit})$;\5 -$\\{print\_nl}(\.{""})$;\6 -\&{end};\ \2\6 -\&{tats}\6 -$\|m\K\\{floor\_unscaled}(\\{xp}-\\{xy\_corr}[\\{octant}])$;\5 -$\\{move\_ptr}\K\\{floor\_unscaled}(\\{yp}-\\{y\_corr}[\\{octant}])-\\{n0}$;\6 -\&{if} $\|m>\\{env\_move}[\\{move\_ptr}]$ \1\&{then}\5 -$\\{env\_move}[\\{move\_ptr}]\K\|m$;\2\6 -\&{end}\par -\U512.\fi - -\M516. In this step we have $\\{xp}\G\\{xx}$ and $\\{yp}\G\\{yy}$. - -\Y\P$\4\X516:Record a line segment from $(\\{xx},\\{yy})$ to $(\\{xp},\\{yp})$ -in \\{env\_move}\X\S$\6 -\&{begin} \37$\\{ty}\K\\{floor\_scaled}(\\{yy}-\\{y\_corr}[\\{octant}])$;\5 -$\\{dely}\K\\{yp}-\\{yy}$;\5 -$\\{yy}\K\\{yy}-\\{ty}$;\5 -$\\{ty}\K\\{yp}-\\{y\_corr}[\\{octant}]-\\{ty}$;\6 -\&{if} $\\{ty}\G\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{delx}\K\\{xp}-\\{xx}$;\5 -$\\{yy}\K\\{unity}-\\{yy}$;\6 -\~ \1\&{loop}\ \&{begin} \37$\\{tx}\K\\{take\_fraction}(\\{delx},\39\\{make% -\_fraction}(\\{yy},\39\\{dely}))$;\6 -\&{if} $\\{ab\_vs\_cd}(\\{tx},\39\\{dely},\39\\{delx},\39\\{yy})+\\{xy\_corr}[% -\\{octant}]>0$ \1\&{then}\5 -$\\{decr}(\\{tx})$;\2\6 -$\|m\K\\{floor\_unscaled}(\\{xx}+\\{tx})$;\6 -\&{if} $\|m>\\{env\_move}[\\{move\_ptr}]$ \1\&{then}\5 -$\\{env\_move}[\\{move\_ptr}]\K\|m$;\2\6 -$\\{ty}\K\\{ty}-\\{unity}$;\6 -\&{if} $\\{ty}<\\{unity}$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -$\\{yy}\K\\{yy}+\\{unity}$;\5 -$\\{incr}(\\{move\_ptr})$;\6 -\&{end};\2\6 -\4\\{done1}: \37\&{end};\2\6 -\&{end}\par -\U515.\fi - -\M517. \P$\X517:Insert the new envelope moves in the pixel data\X\S$\6 -\&{debug} \37\&{if} $(\|m\I\\{mm1})\V(\\{move\_ptr}\I\\{n1}-\\{n0})$ \1\&{then}% -\5 -$\\{confusion}(\.{"1"})$;\ \2\6 -\&{gubed}\6 -$\\{move}[0]\K\\{d0}+\\{env\_move}[0]-\\{mm0}$;\6 -\&{for} $\|n\K1\mathrel{\&{to}}\\{move\_ptr}$ \1\&{do}\5 -$\\{move}[\|n]\K\\{env\_move}[\|n]-\\{env\_move}[\|n-1]+1$;\2\6 -$\\{move}[\\{move\_ptr}]\K\\{move}[\\{move\_ptr}]-\\{d1}$;\6 -\&{if} $\\{internal}[\\{smoothing}]>0$ \1\&{then}\5 -$\\{smooth\_moves}(\\{smooth\_bot},\39\\{smooth\_top})$;\2\6 -$\\{move\_to\_edges}(\\{m0},\39\\{n0},\39\\{m1},\39\\{n1})$;\6 -\&{if} $\\{right\_transition}(\|q)=\\{axis}$ \1\&{then}\6 -\&{begin} \37$\|w\K\\{link}(\|h)$;\5 -$\\{skew\_line\_edges}(\|q,\39\\{knil}(\|w),\39\|w)$;\6 -\&{end}\2\par -\U512.\fi - -\M518. We've done it all in the odd-octant case; the only thing remaining -is to repeat the same ideas, upside down and/or backwards. - -The following code has been split off as a subprocedure of \\{fill\_envelope}, -because some \PASCAL\ compilers cannot handle procedures as large as -\\{fill\_envelope} would otherwise be. - -\Y\P$\4\X518:Declare the procedure called \\{dual\_moves}\X\S$\6 -\4\&{procedure}\1\ \37$\\{dual\_moves}(\|h,\39\|p,\39\|q:\\{pointer})$;\6 -\4\&{label} \37$\\{done},\39\\{done1}$;\6 -\4\&{var} \37$\|r,\39\|s$: \37\\{pointer};\C{for list traversal}\6 -\X511:Other local variables for \\{fill\_envelope}\X\2\6 -\&{begin} \37\X519:Initialize for dual envelope moves\X;\6 -$\|r\K\|p$;\C{recall that $\\{right\_type}(\|q)=\\{endpoint}=0$ now}\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|r=\|q$ \1\&{then}\5 -$\\{smooth\_top}\K\\{move\_ptr}$;\2\6 -\&{while} $\\{right\_type}(\|r)\I\|k$ \1\&{do}\5 -\X521:Insert a line segment dually to approach the correct offset\X;\2\6 -\&{if} $\|r=\|p$ \1\&{then}\5 -$\\{smooth\_bot}\K\\{move\_ptr}$;\2\6 -\&{if} $\|r=\|q$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{move}[\\{move\_ptr}]\K1$;\5 -$\|n\K\\{move\_ptr}$;\5 -$\|s\K\\{link}(\|r)$;\6 -$\\{make\_moves}(\\{x\_coord}(\|r)+\\{x\_coord}(\|w),\39\\{right\_x}(\|r)+\\{x% -\_coord}(\|w),\39\\{left\_x}(\|s)+\\{x\_coord}(\|w),\39\\{x\_coord}(\|s)+\\{x% -\_coord}(\|w),\39\30\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit},\39% -\\{right\_y}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit},\39\\{left\_y}(\|s)+\\{y% -\_coord}(\|w)+\\{half\_unit},\39\\{y\_coord}(\|s)+\\{y\_coord}(\|w)+\\{half% -\_unit},\39\30\\{xy\_corr}[\\{octant}],\39\\{y\_corr}[\\{octant}])$;\5 -\X520:Transfer moves dually from the \\{move} array to \\{env\_move}\X;\6 -$\|r\K\|s$;\6 -\&{end};\2\6 -\4\\{done}: \37\X523:Insert the new envelope moves dually in the pixel data\X;\6 -\&{end};\par -\U506.\fi - -\M519. In the dual case the normal situation is to arrive with a \\{diagonal} -transition and to leave at the \\{axis}. The leftmost edge in each row -is relevant instead of the rightmost one. - -\Y\P$\4\X519:Initialize for dual envelope moves\X\S$\6 -$\|k\K\\{info}(\|h)+1$;\5 -$\\{ww}\K\\{link}(\|h)$;\5 -$\|w\K\\{knil}(\\{ww})$;\6 -$\\{mm0}\K\\{floor\_unscaled}(\\{x\_coord}(\|p)+\\{x\_coord}(\|w)-\\{xy\_corr}[% -\\{octant}])$;\5 -$\\{mm1}\K\\{floor\_unscaled}(\\{x\_coord}(\|q)+\\{x\_coord}(\\{ww})-\\{xy% -\_corr}[\\{octant}])$;\6 -\&{for} $\|n\K1\mathrel{\&{to}}\\{n1}-\\{n0}+1$ \1\&{do}\5 -$\\{env\_move}[\|n]\K\\{mm1}$;\2\6 -$\\{env\_move}[0]\K\\{mm0}$;\5 -$\\{move\_ptr}\K0$;\5 -$\|m\K\\{mm0}$\par -\U518.\fi - -\M520. \P$\X520:Transfer moves dually from the \\{move} array to \\{env\_move}% -\X\S$\6 -\1\&{repeat} \37\&{if} $\|m<\\{env\_move}[\|n]$ \1\&{then}\5 -$\\{env\_move}[\|n]\K\|m$;\2\6 -$\|m\K\|m+\\{move}[\|n]-1$;\5 -$\\{incr}(\|n)$;\6 -\4\&{until}\5 -$\|n>\\{move\_ptr}$\2\par -\U518.\fi - -\M521. Dual retrograde lines occur when \|k increases; the edges of such lines -are not the furthest left in any row. - -\Y\P$\4\X521:Insert a line segment dually to approach the correct offset\X\S$\6 -\&{begin} \37$\\{xx}\K\\{x\_coord}(\|r)+\\{x\_coord}(\|w)$;\5 -$\\{yy}\K\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit}$;\6 -\&{stat} \37\&{if} $\\{internal}[\\{tracing\_edges}]>\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"@\ transition\ line\ "})$;\5 -$\\{print\_int}(\|k)$;\5 -$\\{print}(\.{",\ from\ "})$;\5 -$\\{print\_two\_true}(\\{xx},\39\\{yy}-\\{half\_unit})$;\6 -\&{end};\ \2\6 -\&{tats}\6 -\&{if} $\\{right\_type}(\|r)<\|k$ \1\&{then}\6 -\&{begin} \37$\\{decr}(\|k)$;\5 -$\|w\K\\{knil}(\|w)$;\5 -$\\{xp}\K\\{x\_coord}(\|r)+\\{x\_coord}(\|w)$;\5 -$\\{yp}\K\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit}$;\6 -\&{if} $\\{yp}\I\\{yy}$ \1\&{then}\5 -\X522:Record a line segment from $(\\{xx},\\{yy})$ to $(\\{xp},\\{yp})$ dually -in \\{env\_move}\X;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{incr}(\|k)$;\5 -$\|w\K\\{link}(\|w)$;\5 -$\\{xp}\K\\{x\_coord}(\|r)+\\{x\_coord}(\|w)$;\5 -$\\{yp}\K\\{y\_coord}(\|r)+\\{y\_coord}(\|w)+\\{half\_unit}$;\6 -\&{end};\2\6 -\&{stat} \37\&{if} $\\{internal}[\\{tracing\_edges}]>\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\ to\ "})$;\5 -$\\{print\_two\_true}(\\{xp},\39\\{yp}-\\{half\_unit})$;\5 -$\\{print\_nl}(\.{""})$;\6 -\&{end};\ \2\6 -\&{tats}\6 -$\|m\K\\{floor\_unscaled}(\\{xp}-\\{xy\_corr}[\\{octant}])$;\5 -$\\{move\_ptr}\K\\{floor\_unscaled}(\\{yp}-\\{y\_corr}[\\{octant}])-\\{n0}$;\6 -\&{if} $\|m<\\{env\_move}[\\{move\_ptr}]$ \1\&{then}\5 -$\\{env\_move}[\\{move\_ptr}]\K\|m$;\2\6 -\&{end}\par -\U518.\fi - -\M522. Again, $\\{xp}\G\\{xx}$ and $\\{yp}\G\\{yy}$; but this time we are -interested in the {\sl -smallest\/} \|m that belongs to a given \\{move\_ptr} position, instead of -the largest~\|m. - -\Y\P$\4\X522:Record a line segment from $(\\{xx},\\{yy})$ to $(\\{xp},\\{yp})$ -dually in \\{env\_move}\X\S$\6 -\&{begin} \37$\\{ty}\K\\{floor\_scaled}(\\{yy}-\\{y\_corr}[\\{octant}])$;\5 -$\\{dely}\K\\{yp}-\\{yy}$;\5 -$\\{yy}\K\\{yy}-\\{ty}$;\5 -$\\{ty}\K\\{yp}-\\{y\_corr}[\\{octant}]-\\{ty}$;\6 -\&{if} $\\{ty}\G\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{delx}\K\\{xp}-\\{xx}$;\5 -$\\{yy}\K\\{unity}-\\{yy}$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|m<\\{env\_move}[\\{move\_ptr}]$ \1% -\&{then}\5 -$\\{env\_move}[\\{move\_ptr}]\K\|m$;\2\6 -$\\{tx}\K\\{take\_fraction}(\\{delx},\39\\{make\_fraction}(\\{yy},\39% -\\{dely}))$;\6 -\&{if} $\\{ab\_vs\_cd}(\\{tx},\39\\{dely},\39\\{delx},\39\\{yy})+\\{xy\_corr}[% -\\{octant}]>0$ \1\&{then}\5 -$\\{decr}(\\{tx})$;\2\6 -$\|m\K\\{floor\_unscaled}(\\{xx}+\\{tx})$;\5 -$\\{ty}\K\\{ty}-\\{unity}$;\5 -$\\{incr}(\\{move\_ptr})$;\6 -\&{if} $\\{ty}<\\{unity}$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -$\\{yy}\K\\{yy}+\\{unity}$;\6 -\&{end};\2\6 -\4\\{done1}: \37\&{if} $\|m<\\{env\_move}[\\{move\_ptr}]$ \1\&{then}\5 -$\\{env\_move}[\\{move\_ptr}]\K\|m$;\2\6 -\&{end};\2\6 -\&{end}\par -\U521.\fi - -\M523. Since \\{env\_move} contains minimum values instead of maximum values, -the -finishing-up process is slightly different in the dual case. - -\Y\P$\4\X523:Insert the new envelope moves dually in the pixel data\X\S$\6 -\&{debug} \37\&{if} $(\|m\I\\{mm1})\V(\\{move\_ptr}\I\\{n1}-\\{n0})$ \1\&{then}% -\5 -$\\{confusion}(\.{"2"})$;\ \2\6 -\&{gubed}\6 -$\\{move}[0]\K\\{d0}+\\{env\_move}[1]-\\{mm0}$;\6 -\&{for} $\|n\K1\mathrel{\&{to}}\\{move\_ptr}$ \1\&{do}\5 -$\\{move}[\|n]\K\\{env\_move}[\|n+1]-\\{env\_move}[\|n]+1$;\2\6 -$\\{move}[\\{move\_ptr}]\K\\{move}[\\{move\_ptr}]-\\{d1}$;\6 -\&{if} $\\{internal}[\\{smoothing}]>0$ \1\&{then}\5 -$\\{smooth\_moves}(\\{smooth\_bot},\39\\{smooth\_top})$;\2\6 -$\\{move\_to\_edges}(\\{m0},\39\\{n0},\39\\{m1},\39\\{n1})$;\6 -\&{if} $\\{right\_transition}(\|q)=\\{diagonal}$ \1\&{then}\6 -\&{begin} \37$\|w\K\\{link}(\|h)$;\5 -$\\{skew\_line\_edges}(\|q,\39\|w,\39\\{knil}(\|w))$;\6 -\&{end}\2\par -\U518.\fi - -\N524. \[25] Elliptical pens. -To get the envelope of a cyclic path with respect to an ellipse, \MF\ -calculates the envelope with respect to a polygonal approximation to -the ellipse, using an approach due to John Hobby (Ph.D. thesis, -Stanford University, 1985). -This has two important advantages over trying to obtain the ``exact'' -envelope: - -\yskip\textindent{1)}It gives better results, because the polygon has been -designed to counteract problems that arise from digitization; the -polygon includes sub-pixel corrections to an exact ellipse that make -the results essentially independent of where the path falls on the raster. -For example, the exact envelope with respect to a pen of diameter~1 -blackens a pixel if and only if the path intersects a circle of diameter~1 -inscribed in that pixel; the resulting pattern has ``blots'' when the path -is travelling diagonally in unfortunate raster positions. A much better -result is obtained when pixels are blackened only when the path intersects -an inscribed {\sl diamond\/} of diameter~1. Such a diamond is precisely -the polygon that \MF\ uses in the special case of a circle whose diameter is~1. - -\yskip\textindent{2)}Polygonal envelopes of cubic splines are cubic -splines, hence it isn't necessary to introduce completely different -routines. By contrast, exact envelopes of cubic splines with respect -to circles are complicated curves, more difficult to plot than cubics. - -\fi - -\M525. Hobby's construction involves some interesting number theory. -If $u$ and~$v$ are relatively prime integers, we divide the -set of integer points $(m,n)$ into equivalence classes by saying -that $(m,n)$ belongs to class $um+vn$. Then any two integer points -that lie on a line of slope $-u/v$ belong to the same class, because -such points have the form $(m+tv,n-tu)$. Neighboring lines of slope $-u/v$ -that go through integer points are separated by distance $1/\psqrt{u^2+v^2}$ -from each other, and these lines are perpendicular to lines of slope~$v/u$. -If we start at the origin and travel a distance $k/\psqrt{u^2+v^2}$ in -direction $(u,v)$, we reach the line of slope~$-u/v$ whose points -belong to class~$k$. - -For example, let $u=2$ and $v=3$. Then the points $(0,0)$, $(3,-2)$, -$\ldots$ belong to class~0; the points $(-1,1)$, $(2,-1)$, $\ldots$ belong -to class~1; and the distance between these two lines is $1/\sqrt{13}$. -The point $(2,3)$ itself belongs to class~13, hence its distance from -the origin is $13/\sqrt{13}=\sqrt{13}$ (which we already knew). - -Suppose we wish to plot envelopes with respect to polygons with -integer vertices. Then the best polygon for curves that travel in -direction $(v,-u)$ will contain the points of class~$k$ such that -$k/\psqrt{u^2+v^2}$ is as close as possible to~$d$, where $d$ is the -maximum distance of the given ellipse from the line $ux+vy=0$. - -The \\{fillin} correction assumes that a diagonal line has an -apparent thickness $$2f\cdot\min(\vert u\vert,\vert v\vert)/\psqrt{u^2+v^2}$$ -greater than would be obtained with truly square pixels. (If a -white pixel at an exterior corner is assumed to have apparent -darkness $f_1$ and a black pixel at an interior corner is assumed -to have apparent darkness $1-f_2$, then $f=f_1-f_2$ is the \\{fillin} -parameter.) Under this assumption we want to choose $k$ so that -$\bigl(k+2f\cdot\min(\vert u\vert,\vert v\vert)\bigr)\big/\psqrt{u^2+v^2}$ -is as close as possible to $d$. - -Integer coordinates for the vertices work nicely because the thickness of -the envelope at any given slope is independent of the position of the -path with respect to the raster. It turns out, in fact, that the same -property holds for polygons whose vertices have coordinates that are -integer multiples of~$1\over2$, because ellipses are symmetric about -the origin. It's convenient to double all dimensions and require the -resulting polygon to have vertices with integer coordinates. For example, -to get a circle of {\sl diameter}~$r$, we shall compute integer -coordinates for a circle of {\sl radius}~$r$. The circle of radius~$r$ -will want to be represented by a polygon that contains the boundary -points $(0,\pm r)$ and~$(\pm r,0)$; later we will divide everything -by~2 and get a polygon with $(0,\pm{1\over2}r)$ and $(\pm{1\over2}r,0)$ -on its boundary. - -\fi - -\M526. In practice the important slopes are those having small values of -$u$ and~$v$; these make regular patterns in which our eyes quickly -spot irregularities. For example, horizontal and vertical lines -(when $u=0$ and $\vert v\vert=1$, or $\vert u\vert=1$ and $v=0$) -are the most important; diagonal lines (when $\vert u\vert=\vert v\vert=1$) -are next; and then come lines with slope $\pm2$ or $\pm1/2$. - -The nicest way to generate all rational directions having small -numerators and denominators is to generalize the Stern-Brocot tree -[cf.~{\sl Concrete Mathematics}, section 4.5] -to a ``Stern-Brocot wreath'' as follows: Begin with four nodes -arranged in a circle, containing the respective directions -$(u,v)=(1,0)$, $(0,1)$, $(-1,0)$, and~$(0,-1)$. Then between pairs of -consecutive terms $(u,v)$ and $(u',v')$ of the wreath, insert the -direction $(u+u',v+v')$; continue doing this until some stopping -criterion is fulfilled. - -It is not difficult to verify that, regardless of the stopping -criterion, consecutive directions $(u,v)$ and $(u',v')$ of this -wreath will always satisfy the relation $uv'-u'v=1$. Such pairs -of directions have a nice property with respect to the equivalence -classes described above. Let $l$ be a line of equivalent integer points -$(m+tv,n-tu)$ with respect to~$(u,v)$, and let $l'$ be a line of -equivalent integer points $(m'+tv',n'-tu')$ with respect to~$(u',v')$. -Then $l$ and~$l'$ intersect in an integer point $(m'',n'')$, because -the determinant of the linear equations for intersection is $uv'-u'v=1$. -Notice that the class number of $(m'',n'')$ with respect to $(u+u',v+v')$ -is the sum of its class numbers with respect to $(u,v)$ and~$(u',v')$. -Moreover, consecutive points on~$l$ and~$l'$ belong to classes that -differ by exactly~1 with respect to $(u+u',v+v')$. - -This leads to a nice algorithm in which we construct a polygon having -``correct'' class numbers for as many small-integer directions $(u,v)$ -as possible: Assuming that lines $l$ and~$l'$ contain points of the -correct class for $(u,v)$ and~$(u',v')$, respectively, we determine -the intersection $(m'',n'')$ and compute its class with respect to -$(u+u',v+v')$. If the class is too large to be the best approximation, -we move back the proper number of steps from $(m'',n'')$ toward smaller -class numbers on both $l$ and~$l'$, unless this requires moving to points -that are no longer in the polygon; in this we arrive at two points that -determine a line~$l''$ having the appropriate class. The process continues -recursively, until it cannot proceed without removing the last remaining -point from the class for $(u,v)$ or the class for $(u',v')$. - -\fi - -\M527. The \\{make\_ellipse} subroutine produces a pointer to a cyclic path -whose vertices define a polygon suitable for envelopes. The control -points on this path will be ignored; in fact, the fields in knot nodes -that are usually reserved for control points are occupied by other -data that helps \\{make\_ellipse} compute the desired polygon. - -Parameters \\{major\_axis} and \\{minor\_axis} define the axes of the ellipse; -and parameter \\{theta} is an angle by which the ellipse is rotated -counterclockwise. If $\\{theta}=0$, the ellipse has the equation -$(x/a)^2+(y/b)^2=1$, where $\|a=\\{major\_axis}/2$ and $\|b=\\{minor\_axis}/2$. -In general, the points of the ellipse are generated in the complex plane -by the formula $e^{i\theta}(a\cos t+ib\sin t)$, as $t$~ranges over all -angles. Notice that if $\\{major\_axis}=\\{minor\_axis}=\|d$, we obtain a -circle -of diameter~\|d, regardless of the value of \\{theta}. - -The method sketched above is used to produce the elliptical polygon, -except that the main work is done only in the halfplane obtained from -the three starting directions $(0,-1)$, $(1,0)$,~$(0,1)$. Since the ellipse -has circular symmetry, we use the fact that the last half of the polygon -is simply the negative of the first half. Furthermore, we need to compute only -one quarter of the polygon if the ellipse has axis symmetry. - -\Y\P\4\&{function}\1\ \37$\\{make\_ellipse}(\\{major\_axis},\39\\{minor% -\_axis}:\\{scaled};\,\35\\{theta}:\\{angle})$: \37\\{pointer};\6 -\4\&{label} \37$\\{done},\39\\{done1},\39\\{found}$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s$: \37\\{pointer};\C{for list -manipulation}\6 -\|h: \37\\{pointer};\C{head of the constructed knot list}\6 -$\\{alpha},\39\\{beta},\39\\{gamma},\39\\{delta}$: \37\\{integer};\C{special -points}\6 -$\|c,\39\|d$: \37\\{integer};\C{class numbers}\6 -$\|u,\39\|v$: \37\\{integer};\C{directions}\6 -\\{symmetric}: \37\\{boolean};\C{should the result be symmetric about the -axes?}\2\6 -\&{begin} \37\X528:Initialize the ellipse data structure by beginning with -directions $(0,-1)$, $(1,0)$, $(0,1)$\X;\6 -\X531:Interpolate new vertices in the ellipse data structure until improvement -is impossible\X;\6 -\&{if} $\\{symmetric}$ \1\&{then}\5 -\X536:Complete the half ellipse by reflecting the quarter already computed\X;\2% -\6 -\X537:Complete the ellipse by copying the negative of the half already computed% -\X;\6 -$\\{make\_ellipse}\K\|h$;\6 -\&{end};\par -\fi - -\M528. A special data structure is used only with \\{make\_ellipse}: The -\\{right\_x}, \\{left\_x}, \\{right\_y}, and \\{left\_y} fields of knot nodes -are renamed \\{right\_u}, \\{left\_v}, \\{right\_class}, and \\{left\_length}, -in order to store information that simplifies the necessary computations. - -If \|p and \|q are consecutive knots in this data structure, the -\\{x\_coord} and \\{y\_coord} fields of \|p and~\|q contain current vertices -of the polygon; their values are integer multiples -of \\{half\_unit}. Both of these vertices belong to equivalence class -$\\{right\_class}(\|p)$ with respect to the direction -$\bigl($$\\{right\_u}(\|p),\\{left\_v}(\|q)$$\bigr)$. The number of points of -this class -on the line from vertex~\|p to vertex~\|q is $1+\\{left\_length}(\|q)$. -In particular, $\\{left\_length}(\|q)=0$ means that $\\{x\_coord}(\|p)=\\{x% -\_coord}(\|q)$ -and $\\{y\_coord}(\|p)=\\{y\_coord}(\|q)$; such duplicate vertices will be -discarded during the course of the algorithm. - -The contents of $\\{right\_u}(\|p)$ and $\\{left\_v}(\|q)$ are integer -multiples -of \\{half\_unit}, just like the coordinate fields. Hence, for example, -the point $\bigl($$\\{x\_coord}(\|p)-\\{left\_v}(\|q),\\{y\_coord}(\|p)+% -\\{right\_u}(\|q)$$\bigr)$ -also belongs to class number $\\{right\_class}(\|p)$. This point is one -step closer to the vertex in node~\|q; it equals that vertex -if and only if $\\{left\_length}(\|q)=1$. - -The \\{left\_type} and \\{right\_type} fields are not used, but \\{link} -has its normal meaning. - -To start the process, we create four nodes for the three directions -$(0,-1)$, $(1,0)$, and $(0,1)$. The corresponding vertices are -$(-\alpha,-\beta)$, $(\gamma,-\beta)$, $(\gamma,\beta)$, and -$(\alpha,\beta)$, where $(\alpha,\beta)$ is a half-integer approximation -to where the ellipse rises highest above the $x$-axis, and where -$\gamma$ is a half-integer approximation to the maximum $x$~coordinate -of the ellipse. The fourth of these nodes is not actually calculated -if the ellipse has axis symmetry. - -\Y\P\D \37$\\{right\_u}\S\\{right\_x}$\C{\|u value for a pen edge}\par -\P\D \37$\\{left\_v}\S\\{left\_x}$\C{\|v value for a pen edge}\par -\P\D \37$\\{right\_class}\S\\{right\_y}$\C{equivalence class number of a pen -edge}\par -\P\D \37$\\{left\_length}\S\\{left\_y}$\C{length of a pen edge}\par -\Y\P$\4\X528:Initialize the ellipse data structure by beginning with directions -$(0,-1)$, $(1,0)$, $(0,1)$\X\S$\6 -\X530:Calculate integers $\alpha$, $\beta$, $\gamma$ for the vertex coordinates% -\X;\6 -$\|p\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\|q\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\|r\K\\{get\_node}(\\{knot\_node\_size})$;\6 -\&{if} $\\{symmetric}$ \1\&{then}\5 -$\|s\K\\{null}$\ \&{else} $\|s\K\\{get\_node}(\\{knot\_node\_size})$;\2\6 -$\|h\K\|p$;\5 -$\\{link}(\|p)\K\|q$;\5 -$\\{link}(\|q)\K\|r$;\5 -$\\{link}(\|r)\K\|s$;\C{$\|s=\\{null}$ or $\\{link}(\|s)=\\{null}$}\6 -\X529:Revise the values of $\alpha$, $\beta$, $\gamma$, if necessary, so that -degenerate lines of length zero will not be obtained\X;\6 -$\\{x\_coord}(\|p)\K-\\{alpha}\ast\\{half\_unit}$;\5 -$\\{y\_coord}(\|p)\K-\\{beta}\ast\\{half\_unit}$;\5 -$\\{x\_coord}(\|q)\K\\{gamma}\ast\\{half\_unit}$;\6 -$\\{y\_coord}(\|q)\K\\{y\_coord}(\|p)$;\5 -$\\{x\_coord}(\|r)\K\\{x\_coord}(\|q)$;\6 -$\\{right\_u}(\|p)\K0$;\5 -$\\{left\_v}(\|q)\K-\\{half\_unit}$;\6 -$\\{right\_u}(\|q)\K\\{half\_unit}$;\5 -$\\{left\_v}(\|r)\K0$;\6 -$\\{right\_u}(\|r)\K0$;\5 -$\\{right\_class}(\|p)\K\\{beta}$;\5 -$\\{right\_class}(\|q)\K\\{gamma}$;\5 -$\\{right\_class}(\|r)\K\\{beta}$;\6 -$\\{left\_length}(\|q)\K\\{gamma}+\\{alpha}$;\6 -\&{if} $\\{symmetric}$ \1\&{then}\6 -\&{begin} \37$\\{y\_coord}(\|r)\K0$;\5 -$\\{left\_length}(\|r)\K\\{beta}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{y\_coord}(\|r)\K-\\{y\_coord}(\|p)$;\5 -$\\{left\_length}(\|r)\K\\{beta}+\\{beta}$;\6 -$\\{x\_coord}(\|s)\K-\\{x\_coord}(\|p)$;\5 -$\\{y\_coord}(\|s)\K\\{y\_coord}(\|r)$;\6 -$\\{left\_v}(\|s)\K\\{half\_unit}$;\5 -$\\{left\_length}(\|s)\K\\{gamma}-\\{alpha}$;\6 -\&{end}\2\par -\U527.\fi - -\M529. One of the important invariants of the pen data structure is that -the points are distinct. We may need to correct the pen specification -in order to avoid this. (The result of \&{pencircle} will always be at -least one pixel wide and one pixel tall, although \&{makepen} is -capable of producing smaller pens.) - -\Y\P$\4\X529:Revise the values of $\alpha$, $\beta$, $\gamma$, if necessary, so -that degenerate lines of length zero will not be obtained\X\S$\6 -\&{if} $\\{beta}=0$ \1\&{then}\5 -$\\{beta}\K1$;\2\6 -\&{if} $\\{gamma}=0$ \1\&{then}\5 -$\\{gamma}\K1$;\2\6 -\&{if} $\\{gamma}\L\\{abs}(\\{alpha})$ \1\&{then}\6 -\&{if} $\\{alpha}>0$ \1\&{then}\5 -$\\{alpha}\K\\{gamma}-1$\6 -\4\&{else} $\\{alpha}\K1-\\{gamma}$\2\2\par -\U528.\fi - -\M530. If $a$ and $b$ are the semi-major and semi-minor axes, -the given ellipse rises highest above the $y$-axis at the point -$\bigl((a^2-b^2)\sin\theta\cos\theta/\rho\bigr)+i\rho$, where -$\rho=\sqrt{(a\sin\theta)^2+(b\cos\theta)^2}$. It reaches -furthest to the right of~the $x$-axis at the point -$\sigma+i(a^2-b^2)\sin\theta\cos\theta/\sigma$, where -$\sigma=\sqrt{(a\cos\theta)^2+(b\sin\theta)^2}$. - -\Y\P$\4\X530:Calculate integers $\alpha$, $\beta$, $\gamma$ for the vertex -coordinates\X\S$\6 -\&{if} $(\\{major\_axis}=\\{minor\_axis})\V(\\{theta}\mathbin{\&{mod}}\\{ninety% -\_deg}=0)$ \1\&{then}\6 -\&{begin} \37$\\{symmetric}\K\\{true}$;\5 -$\\{alpha}\K0$;\6 -\&{if} $\\{odd}(\\{theta}\mathbin{\&{div}}\\{ninety\_deg})$ \1\&{then}\6 -\&{begin} \37$\\{beta}\K\\{major\_axis}$;\5 -$\\{gamma}\K\\{minor\_axis}$;\5 -$\\{n\_sin}\K\\{fraction\_one}$;\5 -$\\{n\_cos}\K0$;\C{\\{n\_sin} and \\{n\_cos} are used later}\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{beta}\K\\{minor\_axis}$;\5 -$\\{gamma}\K\\{major\_axis}$;\6 -\&{end};\C{\\{n\_sin} and \\{n\_cos} aren't needed in this case}\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{symmetric}\K\\{false}$;\5 -$\\{n\_sin\_cos}(\\{theta})$;\C{set up $\\{n\_sin}=\sin\theta$ and $\\{n\_cos}=% -\cos\theta$}\6 -$\\{gamma}\K\\{take\_fraction}(\\{major\_axis},\39\\{n\_sin})$;\5 -$\\{delta}\K\\{take\_fraction}(\\{minor\_axis},\39\\{n\_cos})$;\5 -$\\{beta}\K\\{pyth\_add}(\\{gamma},\39\\{delta})$;\5 -$\\{alpha}\K\\{take\_fraction}(\\{take\_fraction}(\\{major\_axis},\39\\{make% -\_fraction}(\\{gamma},\39\\{beta})),\39\\{n\_cos})\30-\\{take\_fraction}(% -\\{take\_fraction}(\\{minor\_axis},\39\\{make\_fraction}(\\{delta},\39% -\\{beta})),\39\\{n\_sin})$;\5 -$\\{alpha}\K(\\{alpha}+\\{half\_unit})\mathbin{\&{div}}\\{unity}$;\5 -$\\{gamma}\K\\{pyth\_add}(\\{take\_fraction}(\\{major\_axis},\39\\{n\_cos}),\39% -\\{take\_fraction}(\\{minor\_axis},\39\\{n\_sin}))$;\6 -\&{end};\2\6 -$\\{beta}\K(\\{beta}+\\{half\_unit})\mathbin{\&{div}}\\{unity}$;\5 -$\\{gamma}\K(\\{gamma}+\\{half\_unit})\mathbin{\&{div}}\\{unity}$\par -\U528.\fi - -\M531. Now \|p, \|q, and \|r march through the list, always representing -three consecutive vertices and two consecutive slope directions. -When a new slope is interpolated, we back up slightly, until -further refinement is impossible; then we march forward again. -The somewhat magical operations performed in this part of the -algorithm are justified by the theory sketched earlier. -Complications arise only from the need to keep zero-length lines -out of the final data structure. - -\Y\P$\4\X531:Interpolate new vertices in the ellipse data structure until -improvement is impossible\X\S$\6 -\~ \1\&{loop}\ \&{begin} \37$\|u\K\\{right\_u}(\|p)+\\{right\_u}(\|q)$;\5 -$\|v\K\\{left\_v}(\|q)+\\{left\_v}(\|r)$;\5 -$\|c\K\\{right\_class}(\|p)+\\{right\_class}(\|q)$;\6 -\X533:Compute the distance \|d from class~0 to the edge of the ellipse in -direction $(\|u,\|v)$, times $\psqrt{u^2+v^2}$, rounded to the nearest integer% -\X;\6 -$\\{delta}\K\|c-\|d$;\C{we want to move \\{delta} steps back from the -intersection vertex~\|q}\6 -\&{if} $\\{delta}>0$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{delta}>\\{left\_length}(\|r)$ \1\&{then}\5 -$\\{delta}\K\\{left\_length}(\|r)$;\2\6 -\&{if} $\\{delta}\G\\{left\_length}(\|q)$ \1\&{then}\5 -\X534:Remove the line from \|p to \|q, and adjust vertex~\|q to introduce a new -line\X\6 -\4\&{else} \X535:Insert a new line for direction $(\|u,\|v)$ between \|p and~% -\|q\X;\2\6 -\&{end}\6 -\4\&{else} $\|p\K\|q$;\2\6 -\X532:Move to the next remaining triple $(\|p,\|q,\|r)$, removing and skipping -past zero-length lines that might be present; \&{goto} \\{done} if all triples -have been processed\X;\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U527.\fi - -\M532. The appearance of a zero-length line means that we should advance \|p -past it. We must not try to straddle a missing direction, because the -algorithm works only on consecutive pairs of directions. - -\Y\P$\4\X532:Move to the next remaining triple $(\|p,\|q,\|r)$, removing and -skipping past zero-length lines that might be present; \&{goto} \\{done} if all -triples have been processed\X\S$\6 -\~ \1\&{loop}\ \&{begin} \37$\|q\K\\{link}(\|p)$;\6 -\&{if} $\|q=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{left\_length}(\|q)=0$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|p)\K\\{link}(\|q)$;\5 -$\\{right\_class}(\|p)\K\\{right\_class}(\|q)$;\5 -$\\{right\_u}(\|p)\K\\{right\_u}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{knot\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|r\K\\{link}(\|q)$;\6 -\&{if} $\|r=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{left\_length}(\|r)=0$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|p)\K\|r$;\5 -$\\{free\_node}(\|q,\39\\{knot\_node\_size})$;\5 -$\|p\K\|r$;\6 -\&{end}\6 -\4\&{else} \&{goto} \37\\{found};\2\6 -\&{end};\2\6 -\&{end};\2\6 -\4\\{found}: \37\par -\U531.\fi - -\M533. The `\&{div} 8' near the end of this step comes from -the fact that \\{delta} is scaled by~$2^{15}$ and $d$~by~$2^{16}$, -while \\{take\_fraction} removes a scale factor of~$2^{28}$. -We also make sure that $d\G\max(\vert u\vert,\vert v\vert)$, so that -the pen will always include a circular pen of diameter~1 as a subset; -then it won't be possible to get disconnected path envelopes. - -\Y\P$\4\X533:Compute the distance \|d from class~0 to the edge of the ellipse -in direction $(\|u,\|v)$, times $\psqrt{u^2+v^2}$, rounded to the nearest -integer\X\S$\6 -$\\{delta}\K\\{pyth\_add}(\|u,\39\|v)$;\6 -\&{if} $\\{major\_axis}=\\{minor\_axis}$ \1\&{then}\5 -$\|d\K\\{major\_axis}$\C{circles are easy}\6 -\4\&{else} \&{begin} \37\&{if} $\\{theta}=0$ \1\&{then}\6 -\&{begin} \37$\\{alpha}\K\|u$;\5 -$\\{beta}\K\|v$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{alpha}\K\\{take\_fraction}(\|u,\39\\{n\_cos})+% -\\{take\_fraction}(\|v,\39\\{n\_sin})$;\5 -$\\{beta}\K\\{take\_fraction}(\|v,\39\\{n\_cos})-\\{take\_fraction}(\|u,\39\\{n% -\_sin})$;\6 -\&{end};\2\6 -$\\{alpha}\K\\{make\_fraction}(\\{alpha},\39\\{delta})$;\5 -$\\{beta}\K\\{make\_fraction}(\\{beta},\39\\{delta})$;\5 -$\|d\K\\{pyth\_add}(\\{take\_fraction}(\\{major\_axis},\39\\{alpha}),\39\\{take% -\_fraction}(\\{minor\_axis},\39\\{beta}))$;\6 -\&{end};\2\6 -$\\{alpha}\K\\{abs}(\|u)$;\5 -$\\{beta}\K\\{abs}(\|v)$;\6 -\&{if} $\\{alpha}<\\{beta}$ \1\&{then}\6 -\&{begin} \37$\\{alpha}\K\\{abs}(\|v)$;\5 -$\\{beta}\K\\{abs}(\|u)$;\6 -\&{end};\C{now $\alpha=\max(\vert u\vert,\vert v\vert)$, $\beta=\min(% -\vert u\vert,\vert v\vert)$}\2\6 -\&{if} $\\{internal}[\\{fillin}]\I0$ \1\&{then}\5 -$\|d\K\|d-\\{take\_fraction}(\\{internal}[\\{fillin}],\39\\{make\_fraction}(% -\\{beta}+\\{beta},\39\\{delta}))$;\2\6 -$\|d\K\\{take\_fraction}((\|d+4)\mathbin{\&{div}}8,\39\\{delta})$;\5 -$\\{alpha}\K\\{alpha}\mathbin{\&{div}}\\{half\_unit}$;\6 -\&{if} $\|d<\\{alpha}$ \1\&{then}\5 -$\|d\K\\{alpha}$\2\par -\U531.\fi - -\M534. At this point there's a line of length $\L\\{delta}$ from vertex~\|p -to vertex~\|q, orthogonal to direction $\bigl($$\\{right\_u}(\|p),\\{left\_v}(% -\|q)$$\bigr)$; -and there's a line of length $\G\\{delta}$ from vertex~\|q to -to vertex~\|r, orthogonal to direction $\bigl($$\\{right\_u}(\|q),\\{left\_v}(% -\|r)$$\bigr)$. -The best line to direction $(u,v)$ should replace the line from -\|p to~\|q; this new line will have the same length as the old. - -\Y\P$\4\X534:Remove the line from \|p to \|q, and adjust vertex~\|q to -introduce a new line\X\S$\6 -\&{begin} \37$\\{delta}\K\\{left\_length}(\|q)$;\6 -$\\{right\_class}(\|p)\K\|c-\\{delta}$;\5 -$\\{right\_u}(\|p)\K\|u$;\5 -$\\{left\_v}(\|q)\K\|v$;\6 -$\\{x\_coord}(\|q)\K\\{x\_coord}(\|q)-\\{delta}\ast\\{left\_v}(\|r)$;\5 -$\\{y\_coord}(\|q)\K\\{y\_coord}(\|q)+\\{delta}\ast\\{right\_u}(\|q)$;\6 -$\\{left\_length}(\|r)\K\\{left\_length}(\|r)-\\{delta}$;\6 -\&{end}\par -\U531.\fi - -\M535. Here is the main case, now that we have dealt with the exception: -We insert a new line of length \\{delta} for direction $(\|u,\|v)$, decreasing -each of the adjacent lines by \\{delta} steps. - -\Y\P$\4\X535:Insert a new line for direction $(\|u,\|v)$ between \|p and~\|q\X% -\S$\6 -\&{begin} \37$\|s\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{link}(\|p)\K\|s$;\5 -$\\{link}(\|s)\K\|q$;\6 -$\\{x\_coord}(\|s)\K\\{x\_coord}(\|q)+\\{delta}\ast\\{left\_v}(\|q)$;\5 -$\\{y\_coord}(\|s)\K\\{y\_coord}(\|q)-\\{delta}\ast\\{right\_u}(\|p)$;\6 -$\\{x\_coord}(\|q)\K\\{x\_coord}(\|q)-\\{delta}\ast\\{left\_v}(\|r)$;\5 -$\\{y\_coord}(\|q)\K\\{y\_coord}(\|q)+\\{delta}\ast\\{right\_u}(\|q)$;\6 -$\\{left\_v}(\|s)\K\\{left\_v}(\|q)$;\5 -$\\{right\_u}(\|s)\K\|u$;\5 -$\\{left\_v}(\|q)\K\|v$;\6 -$\\{right\_class}(\|s)\K\|c-\\{delta}$;\6 -$\\{left\_length}(\|s)\K\\{left\_length}(\|q)-\\{delta}$;\5 -$\\{left\_length}(\|q)\K\\{delta}$;\5 -$\\{left\_length}(\|r)\K\\{left\_length}(\|r)-\\{delta}$;\6 -\&{end}\par -\U531.\fi - -\M536. Only the coordinates need to be copied, not the class numbers and other -stuff. - -\Y\P$\4\X536:Complete the half ellipse by reflecting the quarter already -computed\X\S$\6 -\&{begin} \37$\|s\K\\{null}$;\5 -$\|q\K\|h$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|r\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{link}(\|r)\K\|s$;\5 -$\|s\K\|r$;\6 -$\\{x\_coord}(\|s)\K\\{x\_coord}(\|q)$;\5 -$\\{y\_coord}(\|s)\K-\\{y\_coord}(\|q)$;\6 -\&{if} $\|q=\|p$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -$\|q\K\\{link}(\|q)$;\6 -\&{if} $\\{y\_coord}(\|q)=0$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -\&{end};\2\6 -\4\\{done1}: \37$\\{link}(\|p)\K\|s$;\5 -$\\{beta}\K-\\{y\_coord}(\|h)$;\6 -\&{while} $\\{y\_coord}(\|p)\I\\{beta}$ \1\&{do}\5 -$\|p\K\\{link}(\|p)$;\2\6 -$\|q\K\\{link}(\|p)$;\6 -\&{end}\par -\U527.\fi - -\M537. Now we use a somewhat tricky fact: The pointer \|q will be null if and -only if the line for the final direction $(0,1)$ has been removed. If -that line still survives, it should be combined with a possibly -surviving line in the initial direction $(0,-1)$. - -\Y\P$\4\X537:Complete the ellipse by copying the negative of the half already -computed\X\S$\6 -\&{if} $\|q\I\\{null}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{right\_u}(\|h)=0$ \1\&{then}\6 -\&{begin} \37$\|p\K\|h$;\5 -$\|h\K\\{link}(\|h)$;\5 -$\\{free\_node}(\|p,\39\\{knot\_node\_size})$;\6 -$\\{x\_coord}(\|q)\K-\\{x\_coord}(\|h)$;\6 -\&{end};\2\6 -$\|p\K\|q$;\6 -\&{end}\6 -\4\&{else} $\|q\K\|p$;\2\6 -$\|r\K\\{link}(\|h)$;\C{now $\|p=\|q$, $\\{x\_coord}(\|p)=-\\{x\_coord}(\|h)$, -$\\{y\_coord}(\|p)=-\\{y\_coord}(\|h)$}\6 -\1\&{repeat} \37$\|s\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{link}(\|p)\K\|s$;\5 -$\|p\K\|s$;\6 -$\\{x\_coord}(\|p)\K-\\{x\_coord}(\|r)$;\5 -$\\{y\_coord}(\|p)\K-\\{y\_coord}(\|r)$;\5 -$\|r\K\\{link}(\|r)$;\6 -\4\&{until}\5 -$\|r=\|q$;\2\6 -$\\{link}(\|p)\K\|h$\par -\U527.\fi - -\N538. \[26] Direction and intersection times. -A path of length $n$ is defined parametrically by functions $x(t)$ and -$y(t)$, for $0\L\|t\L\|n$; we can regard $t$ as the ``time'' at which the path -reaches the point $\bigl(x(t),y(t)\bigr)$. In this section of the program -we shall consider operations that determine special times associated with -given paths: the first time that a path travels in a given direction, and -a pair of times at which two paths cross each other. - -\fi - -\M539. Let's start with the easier task. The function \\{find\_direction\_time} -is -given a direction $(\|x,\|y)$ and a path starting at~\|h. If the path never -travels in direction $(\|x,\|y)$, the direction time will be~$-1$; otherwise -it will be nonnegative. - -Certain anomalous cases can arise: If $(\|x,\|y)=(0,0)$, so that the given -direction is undefined, the direction time will be~0. If $\bigl(x'(t), -y'(t)\bigr)=(0,0)$, so that the path direction is undefined, it will be -assumed to match any given direction at time~\|t. - -The routine solves this problem in nondegenerate cases by rotating the path -and the given direction so that $(\|x,\|y)=(1,0)$; i.e., the main task will be -to find when a given path first travels ``due east.'' - -\Y\P\4\&{function}\1\ \37$\\{find\_direction\_time}(\|x,\39\|y:\\{scaled};\,% -\35\|h:\\{pointer})$: \37\\{scaled};\6 -\4\&{label} \37$\\{exit},\39\\{found},\39\\{not\_found},\39\\{done}$;\6 -\4\&{var} \37\\{max}: \37\\{scaled};\C{$\max\bigl(\vert x\vert,\vert y\vert% -\bigr)$}\6 -$\|p,\39\|q$: \37\\{pointer};\C{for list traversal}\6 -\|n: \37\\{scaled};\C{the direction time at knot \|p}\6 -\\{tt}: \37\\{scaled};\C{the direction time within a cubic}\6 -\X542:Other local variables for \\{find\_direction\_time}\X\2\6 -\&{begin} \37\X540:Normalize the given direction for better accuracy; but % -\&{return} with zero result if it's zero\X;\6 -$\|n\K0$;\5 -$\|p\K\|h$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\\{right\_type}(\|p)=\\{endpoint}$ \1% -\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\|q\K\\{link}(\|p)$;\5 -\X541:Rotate the cubic between \|p and \|q; then \&{goto} \\{found} if the -rotated cubic travels due east at some time \\{tt}; but \&{goto} \\{not\_found} -if an entire cyclic path has been traversed\X;\6 -$\|p\K\|q$;\5 -$\|n\K\|n+\\{unity}$;\6 -\&{end};\2\6 -\4\\{not\_found}: \37$\\{find\_direction\_time}\K-\\{unity}$;\5 -\&{return};\6 -\4\\{found}: \37$\\{find\_direction\_time}\K\|n+\\{tt}$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M540. \P$\X540:Normalize the given direction for better accuracy; but % -\&{return} with zero result if it's zero\X\S$\6 -\&{if} $\\{abs}(\|x)<\\{abs}(\|y)$ \1\&{then}\6 -\&{begin} \37$\|x\K\\{make\_fraction}(\|x,\39\\{abs}(\|y))$;\6 -\&{if} $\|y>0$ \1\&{then}\5 -$\|y\K\\{fraction\_one}$\ \&{else} $\|y\K-\\{fraction\_one}$;\2\6 -\&{end}\6 -\4\&{else} \&{if} $\|x=0$ \1\&{then}\6 -\&{begin} \37$\\{find\_direction\_time}\K0$;\5 -\&{return};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|y\K\\{make\_fraction}(\|y,\39\\{abs}(\|x))$;\6 -\&{if} $\|x>0$ \1\&{then}\5 -$\|x\K\\{fraction\_one}$\ \&{else} $\|x\K-\\{fraction\_one}$;\2\6 -\&{end}\2\2\par -\U539.\fi - -\M541. Since we're interested in the tangent directions, we work with the -derivative $${\textstyle1\over3}B'(x_0,x_1,x_2,x_3;t)= -B(x_1-x_0,x_2-x_1,x_3-x_2;t)$$ instead of -$B(x_0,x_1,x_2,x_3;t)$ itself. The derived coefficients are also scaled up -in order to achieve better accuracy. - -The given path may turn abruptly at a knot, and it might pass the critical -tangent direction at such a time. Therefore we remember the direction \\{phi} -in which the previous rotated cubic was traveling. (The value of \\{phi} will -be -undefined on the first cubic, i.e., when $\|n=0$.) - -\Y\P$\4\X541:Rotate the cubic between \|p and \|q; then \&{goto} \\{found} if -the rotated cubic travels due east at some time \\{tt}; but \&{goto} \\{not% -\_found} if an entire cyclic path has been traversed\X\S$\6 -$\\{tt}\K0$;\5 -\X543:Set local variables $\\{x1},\\{x2},\\{x3}$ and $\\{y1},\\{y2},\\{y3}$ to -multiples of the control points of the rotated derivatives\X;\6 -\&{if} $\\{y1}=0$ \1\&{then}\6 -\&{if} $\\{x1}\G0$ \1\&{then}\5 -\&{goto} \37\\{found};\2\2\6 -\&{if} $\|n>0$ \1\&{then}\6 -\&{begin} \37\X544:Exit to \\{found} if an eastward direction occurs at knot % -\|p\X;\6 -\&{if} $\|p=\|h$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{end};\2\6 -\&{if} $(\\{x3}\I0)\V(\\{y3}\I0)$ \1\&{then}\5 -$\\{phi}\K\\{n\_arg}(\\{x3},\39\\{y3})$;\2\6 -\X546:Exit to \\{found} if the curve whose derivatives are specified by $% -\\{x1},\\{x2},\\{x3},\\{y1},\\{y2},\\{y3}$ travels eastward at some time~\\{tt}% -\X\par -\U539.\fi - -\M542. \P$\X542:Other local variables for \\{find\_direction\_time}\X\S$\6 -\4$\\{x1},\39\\{x2},\39\\{x3},\39\\{y1},\39\\{y2},\39\\{y3}$: \37\\{scaled};% -\C{multiples of rotated derivatives}\6 -\4$\\{theta},\39\\{phi}$: \37\\{angle};\C{angles of exit and entry at a knot}\6 -\4\|t: \37\\{fraction};\C{temp storage}\par -\U539.\fi - -\M543. \P$\X543:Set local variables $\\{x1},\\{x2},\\{x3}$ and $\\{y1},\\{y2},% -\\{y3}$ to multiples of the control points of the rotated derivatives\X\S$\6 -$\\{x1}\K\\{right\_x}(\|p)-\\{x\_coord}(\|p)$;\5 -$\\{x2}\K\\{left\_x}(\|q)-\\{right\_x}(\|p)$;\5 -$\\{x3}\K\\{x\_coord}(\|q)-\\{left\_x}(\|q)$;\6 -$\\{y1}\K\\{right\_y}(\|p)-\\{y\_coord}(\|p)$;\5 -$\\{y2}\K\\{left\_y}(\|q)-\\{right\_y}(\|p)$;\5 -$\\{y3}\K\\{y\_coord}(\|q)-\\{left\_y}(\|q)$;\6 -$\\{max}\K\\{abs}(\\{x1})$;\6 -\&{if} $\\{abs}(\\{x2})>\\{max}$ \1\&{then}\5 -$\\{max}\K\\{abs}(\\{x2})$;\2\6 -\&{if} $\\{abs}(\\{x3})>\\{max}$ \1\&{then}\5 -$\\{max}\K\\{abs}(\\{x3})$;\2\6 -\&{if} $\\{abs}(\\{y1})>\\{max}$ \1\&{then}\5 -$\\{max}\K\\{abs}(\\{y1})$;\2\6 -\&{if} $\\{abs}(\\{y2})>\\{max}$ \1\&{then}\5 -$\\{max}\K\\{abs}(\\{y2})$;\2\6 -\&{if} $\\{abs}(\\{y3})>\\{max}$ \1\&{then}\5 -$\\{max}\K\\{abs}(\\{y3})$;\2\6 -\&{if} $\\{max}=0$ \1\&{then}\5 -\&{goto} \37\\{found};\2\6 -\&{while} $\\{max}<\\{fraction\_half}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\\{max})$;\5 -$\\{double}(\\{x1})$;\5 -$\\{double}(\\{x2})$;\5 -$\\{double}(\\{x3})$;\5 -$\\{double}(\\{y1})$;\5 -$\\{double}(\\{y2})$;\5 -$\\{double}(\\{y3})$;\6 -\&{end};\2\6 -$\|t\K\\{x1}$;\5 -$\\{x1}\K\\{take\_fraction}(\\{x1},\39\|x)+\\{take\_fraction}(\\{y1},\39\|y)$;\5 -$\\{y1}\K\\{take\_fraction}(\\{y1},\39\|x)-\\{take\_fraction}(\|t,\39\|y)$;\6 -$\|t\K\\{x2}$;\5 -$\\{x2}\K\\{take\_fraction}(\\{x2},\39\|x)+\\{take\_fraction}(\\{y2},\39\|y)$;\5 -$\\{y2}\K\\{take\_fraction}(\\{y2},\39\|x)-\\{take\_fraction}(\|t,\39\|y)$;\6 -$\|t\K\\{x3}$;\5 -$\\{x3}\K\\{take\_fraction}(\\{x3},\39\|x)+\\{take\_fraction}(\\{y3},\39\|y)$;\5 -$\\{y3}\K\\{take\_fraction}(\\{y3},\39\|x)-\\{take\_fraction}(\|t,\39\|y)$\par -\U541.\fi - -\M544. \P$\X544:Exit to \\{found} if an eastward direction occurs at knot \|p\X% -\S$\6 -$\\{theta}\K\\{n\_arg}(\\{x1},\39\\{y1})$;\6 -\&{if} $\\{theta}\G0$ \1\&{then}\6 -\&{if} $\\{phi}\L0$ \1\&{then}\6 -\&{if} $\\{phi}\G\\{theta}-\\{one\_eighty\_deg}$ \1\&{then}\5 -\&{goto} \37\\{found};\2\2\2\6 -\&{if} $\\{theta}\L0$ \1\&{then}\6 -\&{if} $\\{phi}\G0$ \1\&{then}\6 -\&{if} $\\{phi}\L\\{theta}+\\{one\_eighty\_deg}$ \1\&{then}\5 -\&{goto} \37\\{found}\2\2\2\par -\U541.\fi - -\M545. In this step we want to use the \\{crossing\_point} routine to find the -roots of the quadratic equation $B(y_1,y_2,y_3;t)=0$. -Several complications arise: If the quadratic equation has a double root, -the curve never crosses zero, and \\{crossing\_point} will find nothing; -this case occurs iff $y_1y_3=y_2^2$ and $y_1y_2<0$. If the quadratic -equation has simple roots, or only one root, we may have to negate it -so that $B(y_1,y_2,y_3;t)$ crosses from positive to negative at its first root. -And finally, we need to do special things if $B(y_1,y_2,y_3;t)$ is -identically zero. - -\fi - -\M546. \P$\X546:Exit to \\{found} if the curve whose derivatives are specified -by $\\{x1},\\{x2},\\{x3},\\{y1},\\{y2},\\{y3}$ travels eastward at some time~% -\\{tt}\X\S$\6 -\&{if} $\\{x1}<0$ \1\&{then}\6 -\&{if} $\\{x2}<0$ \1\&{then}\6 -\&{if} $\\{x3}<0$ \1\&{then}\5 -\&{goto} \37\\{done};\2\2\2\6 -\&{if} $\\{ab\_vs\_cd}(\\{y1},\39\\{y3},\39\\{y2},\39\\{y2})=0$ \1\&{then}\5 -\X548:Handle the test for eastward directions when $y_1y_3=y_2^2$; either % -\&{goto} \\{found} or \&{goto} \\{done}\X;\2\6 -\&{if} $\\{y1}\L0$ \1\&{then}\6 -\&{if} $\\{y1}<0$ \1\&{then}\6 -\&{begin} \37$\\{y1}\K-\\{y1}$;\5 -$\\{y2}\K-\\{y2}$;\5 -$\\{y3}\K-\\{y3}$;\6 -\&{end}\6 -\4\&{else} \&{if} $\\{y2}>0$ \1\&{then}\6 -\&{begin} \37$\\{y2}\K-\\{y2}$;\5 -$\\{y3}\K-\\{y3}$;\6 -\&{end};\2\2\2\6 -\X547:Check the places where $B(y_1,y_2,y_3;t)=0$ to see if $B(x_1,x_2,x_3;t)% -\ge0$\X;\6 -\4\\{done}: \37\par -\U541.\fi - -\M547. The quadratic polynomial $B(y_1,y_2,y_3;t)$ begins $\G0$ and has at most -two roots, because we know that it isn't identically zero. - -It must be admitted that the \\{crossing\_point} routine is not perfectly -accurate; -rounding errors might cause it to find a root when $y_1y_3>y_2^2$, or to -miss the roots when $y_1y_3<y_2^2$. The rotation process is itself -subject to rounding errors. Yet this code optimistically tries to -do the right thing. - -\Y\P\D \37$\\{we\_found\_it}\S$\1\6 -\&{begin} \37$\\{tt}\K(\|t+\O{4000})\mathbin{\&{div}}\O{10000}$;\5 -\&{goto} \37\\{found};\6 -\&{end}\2\par -\Y\P$\4\X547:Check the places where $B(y_1,y_2,y_3;t)=0$ to see if -$B(x_1,x_2,x_3;t)\ge0$\X\S$\6 -$\|t\K\\{crossing\_point}(\\{y1},\39\\{y2},\39\\{y3})$;\6 -\&{if} $\|t>\\{fraction\_one}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{y2}\K\\{t\_of\_the\_way}(\\{y2})(\\{y3})$;\5 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\5 -$\\{x2}\K\\{t\_of\_the\_way}(\\{x2})(\\{x3})$;\5 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\6 -\&{if} $\\{x1}\G0$ \1\&{then}\5 -\\{we\_found\_it};\2\6 -\&{if} $\\{y2}>0$ \1\&{then}\5 -$\\{y2}\K0$;\2\6 -$\\{tt}\K\|t$;\5 -$\|t\K\\{crossing\_point}(0,\39-\\{y2},\39-\\{y3})$;\6 -\&{if} $\|t>\\{fraction\_one}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\5 -$\\{x2}\K\\{t\_of\_the\_way}(\\{x2})(\\{x3})$;\6 -\&{if} $\\{t\_of\_the\_way}(\\{x1})(\\{x2})\G0$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{t\_of\_the\_way}(\\{tt})(\\{fraction\_one})$;\5 -\\{we\_found\_it};\6 -\&{end}\2\par -\U546.\fi - -\M548. \P$\X548:Handle the test for eastward directions when $y_1y_3=y_2^2$; -either \&{goto} \\{found} or \&{goto} \\{done}\X\S$\6 -\&{begin} \37\&{if} $\\{ab\_vs\_cd}(\\{y1},\39\\{y2},\390,\390)<0$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{make\_fraction}(\\{y1},\39\\{y1}-\\{y2})$;\5 -$\\{x1}\K\\{t\_of\_the\_way}(\\{x1})(\\{x2})$;\5 -$\\{x2}\K\\{t\_of\_the\_way}(\\{x2})(\\{x3})$;\6 -\&{if} $\\{t\_of\_the\_way}(\\{x1})(\\{x2})\G0$ \1\&{then}\5 -\\{we\_found\_it};\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{y3}=0$ \1\&{then}\6 -\&{if} $\\{y1}=0$ \1\&{then}\5 -\X549:Exit to \\{found} if the derivative $B(x_1,x_2,x_3;t)$ becomes $\G0$\X\6 -\4\&{else} \&{if} $\\{x3}\G0$ \1\&{then}\6 -\&{begin} \37$\\{tt}\K\\{unity}$;\5 -\&{goto} \37\\{found};\6 -\&{end};\2\2\2\2\6 -\&{goto} \37\\{done};\6 -\&{end}\par -\U546.\fi - -\M549. At this point we know that the derivative of $\|y(\|t)$ is identically -zero, -and that $\\{x1}<0$; but either $\\{x2}\G0$ or $\\{x3}\G0$, so there's some -hope of -traveling east. - -\Y\P$\4\X549:Exit to \\{found} if the derivative $B(x_1,x_2,x_3;t)$ becomes $% -\G0$\X\S$\6 -\&{begin} \37$\|t\K\\{crossing\_point}(-\\{x1},\39-\\{x2},\39-\\{x3})$;\6 -\&{if} $\|t\L\\{fraction\_one}$ \1\&{then}\5 -\\{we\_found\_it};\2\6 -\&{if} $\\{ab\_vs\_cd}(\\{x1},\39\\{x3},\39\\{x2},\39\\{x2})\L0$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{make\_fraction}(\\{x1},\39\\{x1}-\\{x2})$;\5 -\\{we\_found\_it};\6 -\&{end};\2\6 -\&{end}\par -\U548.\fi - -\M550. The intersection of two cubics can be found by an interesting variant -of the general bisection scheme described in the introduction to \\{make% -\_moves}.\ -Given $w(t)=B(w_0,w_1,w_2,w_3;t)$ and $z(t)=B(z_0,z_1,z_2,z_3;t)$, -we wish to find a pair of times $(t_1,t_2)$ such that $w(t_1)=z(t_2)$, -if an intersection exists. First we find the smallest rectangle that -encloses the points $\{w_0,w_1,w_2,w_3\}$ and check that it overlaps -the smallest rectangle that encloses -$\{z_0,z_1,z_2,z_3\}$; if not, the cubics certainly don't intersect. -But if the rectangles do overlap, we bisect the intervals, getting -new cubics $w'$ and~$w''$, $z'$~and~$z''$; the intersection routine first -tries for an intersection between $w'$ and~$z'$, then (if unsuccessful) -between $w'$ and~$z''$, then (if still unsuccessful) between $w''$ and~$z'$, -finally (if thrice unsuccessful) between $w''$ and~$z''$. After $l$~successful -levels of bisection we will have determined the intersection times $t_1$ -and~$t_2$ to $l$~bits of accuracy. - -\def\submin{_{\rm min}} \def\submax{_{\rm max}} -As before, it is better to work with the numbers $W_k=2^l(w_k-w_{k-1})$ -and $Z_k=2^l(z_k-z_{k-1})$ rather than the coefficients $w_k$ and $z_k$ -themselves. We also need one other quantity, $\Delta=2^l(w_0-z_0)$, -to determine when the enclosing rectangles overlap. Here's why: -The $x$~coordinates of~$w(t)$ are between $u\submin$ and $u\submax$, -and the $x$~coordinates of~$z(t)$ are between $x\submin$ and $x\submax$, -if we write $w_k=(u_k,v_k)$ and $z_k=(x_k,y_k)$ and $u\submin= -\min(u_0,u_1,u_2,u_3)$, etc. These intervals of $x$~coordinates -overlap if and only if $u\submin\L x\submax$ and -$x\submin\L u\submax$. Letting -$$U\submin=\min(0,U_1,U_1+U_2,U_1+U_2+U_3),\; -U\submax=\max(0,U_1,U_1+U_2,U_1+U_2+U_3),$$ -we have $u\submin=2^lu_0+U\submin$, etc.; the condition for overlap -reduces to -$$X\submin-U\submax\L 2^l(u_0-x_0)\L X\submax-U\submin.$$ -Thus we want to maintain the quantity $2^l(u_0-x_0)$; similarly, -the quantity $2^l(v_0-y_0)$ accounts for the $y$~coordinates. The -coordinates of $\Delta=2^l(w_0-z_0)$ must stay bounded as $l$ increases, -because of the overlap condition; i.e., we know that $X\submin$, -$X\submax$, and their relatives are bounded, hence $X\submax- -U\submin$ and $X\submin-U\submax$ are bounded. - -\fi - -\M551. Incidentally, if the given cubics intersect more than once, the process -just sketched will not necessarily find the lexicographically smallest pair -$(t_1,t_2)$. The solution actually obtained will be smallest in ``shuffled -order''; i.e., if $t_1=(.a_1a_2\ldots a_{16})_2$ and -$t_2=(.b_1b_2\ldots b_{16})_2$, then we will minimize -$a_1b_1a_2b_2\ldots a_{16}b_{16}$, not -$a_1a_2\ldots a_{16}b_1b_2\ldots b_{16}$. -Shuffled order agrees with lexicographic order if all pairs of solutions -$(t_1,t_2)$ and $(t_1',t_2')$ have the property that $t_1<t_1'$ iff -$t_2<t_2'$; but in general, lexicographic order can be quite different, -and the bisection algorithm would be substantially less efficient if it were -constrained by lexicographic order. - -For example, suppose that an overlap has been found for $l=3$ and -$(t_1,t_2)= (.101,.011)$ in binary, but that no overlap is produced by -either of the alternatives $(.1010,.0110)$, $(.1010,.0111)$ at level~4. -Then there is probably an intersection in one of the subintervals -$(.1011,.011x)$; but lexicographic order would require us to explore -$(.1010,.1xxx)$ and $(.1011,.00xx)$ and $(.1011,.010x)$ first. We wouldn't -want to store all of the subdivision data for the second path, so the -subdivisions would have to be regenerated many times. Such inefficiencies -would be associated with every `1' in the binary representation of~$t_1$. - -\fi - -\M552. The subdivision process introduces rounding errors, hence we need to -make a more liberal test for overlap. It is not hard to show that the -computed values of $U_i$ differ from the truth by at most~$l$, on -level~$l$, hence $U\submin$ and $U\submax$ will be at most $3l$ in error. -If $\beta$ is an upper bound on the absolute error in the computed -components of $\Delta=(\\{delx},\\{dely})$ on level~$l$, we will replace -the test `$X\submin-U\submax\L\\{delx}$' by the more liberal test -`$X\submin-U\submax\L\\{delx}+\\{tol}$', where $\\{tol}=6l+\beta$. - -More accuracy is obtained if we try the algorithm first with $\\{tol}=0$; -the more liberal tolerance is used only if an exact approach fails. -It is convenient to do this double-take by letting `3' in the preceding -paragraph be a parameter, which is first 0, then 3. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{tol\_step}: \37$0\to6$;\C{either 0 or 3, usually}\par -\fi - -\M553. We shall use an explicit stack to implement the recursive bisection -method described above. In fact, the \\{bisect\_stack} array is available for -this purpose. It will contain numerous 5-word packets like -$(U_1,U_2,U_3,U\submin,U\submax)$, as well as 20-word packets comprising -the 5-word packets for $U$, $V$, $X$, and~$Y$. - -The following macros define the allocation of stack positions to -the quantities needed for bisection-intersection. - -\Y\P\D \37$\\{stack\_1}(\#)\S\\{bisect\_stack}[\#]$\C{$U_1$, $V_1$, $X_1$, or -$Y_1$}\par -\P\D \37$\\{stack\_2}(\#)\S\\{bisect\_stack}[\#+1]$\C{$U_2$, $V_2$, $X_2$, or -$Y_2$}\par -\P\D \37$\\{stack\_3}(\#)\S\\{bisect\_stack}[\#+2]$\C{$U_3$, $V_3$, $X_3$, or -$Y_3$}\par -\P\D \37$\\{stack\_min}(\#)\S\\{bisect\_stack}[\#+3]$\C{$U\submin$, $V\submin$, -$X\submin$, or $Y\submin$}\par -\P\D \37$\\{stack\_max}(\#)\S\\{bisect\_stack}[\#+4]$\C{$U\submax$, $V\submax$, -$X\submax$, or $Y\submax$}\par -\P\D \37$\\{int\_packets}=20$\C{number of words to represent $U_k$, $V_k$, -$X_k$, and $Y_k$}\Y\par -\P\D \37$\\{u\_packet}(\#)\S\#-5$\par -\P\D \37$\\{v\_packet}(\#)\S\#-10$\par -\P\D \37$\\{x\_packet}(\#)\S\#-15$\par -\P\D \37$\\{y\_packet}(\#)\S\#-20$\par -\P\D \37$\\{l\_packets}\S\\{bisect\_ptr}-\\{int\_packets}$\par -\P\D \37$\\{r\_packets}\S\\{bisect\_ptr}$\par -\P\D \37$\\{ul\_packet}\S\\{u\_packet}(\\{l\_packets})$\C{base of $U'_k$ -variables}\par -\P\D \37$\\{vl\_packet}\S\\{v\_packet}(\\{l\_packets})$\C{base of $V'_k$ -variables}\par -\P\D \37$\\{xl\_packet}\S\\{x\_packet}(\\{l\_packets})$\C{base of $X'_k$ -variables}\par -\P\D \37$\\{yl\_packet}\S\\{y\_packet}(\\{l\_packets})$\C{base of $Y'_k$ -variables}\par -\P\D \37$\\{ur\_packet}\S\\{u\_packet}(\\{r\_packets})$\C{base of $U''_k$ -variables}\par -\P\D \37$\\{vr\_packet}\S\\{v\_packet}(\\{r\_packets})$\C{base of $V''_k$ -variables}\par -\P\D \37$\\{xr\_packet}\S\\{x\_packet}(\\{r\_packets})$\C{base of $X''_k$ -variables}\par -\P\D \37$\\{yr\_packet}\S\\{y\_packet}(\\{r\_packets})$\C{base of $Y''_k$ -variables}\Y\par -\P\D \37$\\{u1l}\S\\{stack\_1}(\\{ul\_packet})$\C{$U'_1$}\par -\P\D \37$\\{u2l}\S\\{stack\_2}(\\{ul\_packet})$\C{$U'_2$}\par -\P\D \37$\\{u3l}\S\\{stack\_3}(\\{ul\_packet})$\C{$U'_3$}\par -\P\D \37$\\{v1l}\S\\{stack\_1}(\\{vl\_packet})$\C{$V'_1$}\par -\P\D \37$\\{v2l}\S\\{stack\_2}(\\{vl\_packet})$\C{$V'_2$}\par -\P\D \37$\\{v3l}\S\\{stack\_3}(\\{vl\_packet})$\C{$V'_3$}\par -\P\D \37$\\{x1l}\S\\{stack\_1}(\\{xl\_packet})$\C{$X'_1$}\par -\P\D \37$\\{x2l}\S\\{stack\_2}(\\{xl\_packet})$\C{$X'_2$}\par -\P\D \37$\\{x3l}\S\\{stack\_3}(\\{xl\_packet})$\C{$X'_3$}\par -\P\D \37$\\{y1l}\S\\{stack\_1}(\\{yl\_packet})$\C{$Y'_1$}\par -\P\D \37$\\{y2l}\S\\{stack\_2}(\\{yl\_packet})$\C{$Y'_2$}\par -\P\D \37$\\{y3l}\S\\{stack\_3}(\\{yl\_packet})$\C{$Y'_3$}\par -\P\D \37$\\{u1r}\S\\{stack\_1}(\\{ur\_packet})$\C{$U''_1$}\par -\P\D \37$\\{u2r}\S\\{stack\_2}(\\{ur\_packet})$\C{$U''_2$}\par -\P\D \37$\\{u3r}\S\\{stack\_3}(\\{ur\_packet})$\C{$U''_3$}\par -\P\D \37$\\{v1r}\S\\{stack\_1}(\\{vr\_packet})$\C{$V''_1$}\par -\P\D \37$\\{v2r}\S\\{stack\_2}(\\{vr\_packet})$\C{$V''_2$}\par -\P\D \37$\\{v3r}\S\\{stack\_3}(\\{vr\_packet})$\C{$V''_3$}\par -\P\D \37$\\{x1r}\S\\{stack\_1}(\\{xr\_packet})$\C{$X''_1$}\par -\P\D \37$\\{x2r}\S\\{stack\_2}(\\{xr\_packet})$\C{$X''_2$}\par -\P\D \37$\\{x3r}\S\\{stack\_3}(\\{xr\_packet})$\C{$X''_3$}\par -\P\D \37$\\{y1r}\S\\{stack\_1}(\\{yr\_packet})$\C{$Y''_1$}\par -\P\D \37$\\{y2r}\S\\{stack\_2}(\\{yr\_packet})$\C{$Y''_2$}\par -\P\D \37$\\{y3r}\S\\{stack\_3}(\\{yr\_packet})$\C{$Y''_3$}\Y\par -\P\D \37$\\{stack\_dx}\S\\{bisect\_stack}[\\{bisect\_ptr}]$\C{stacked value of % -\\{delx}}\par -\P\D \37$\\{stack\_dy}\S\\{bisect\_stack}[\\{bisect\_ptr}+1]$\C{stacked value -of \\{dely}}\par -\P\D \37$\\{stack\_tol}\S\\{bisect\_stack}[\\{bisect\_ptr}+2]$\C{stacked value -of \\{tol}}\par -\P\D \37$\\{stack\_uv}\S\\{bisect\_stack}[\\{bisect\_ptr}+3]$\C{stacked value -of \\{uv}}\par -\P\D \37$\\{stack\_xy}\S\\{bisect\_stack}[\\{bisect\_ptr}+4]$\C{stacked value -of \\{xy}}\par -\P\D \37$\\{int\_increment}=\\{int\_packets}+\\{int\_packets}+5$\C{number of -stack words per level}\par -\Y\P$\4\X14:Check the ``constant'' values for consistency\X\mathrel{+}\S$\6 -\&{if} $\\{int\_packets}+17\ast\\{int\_increment}>\\{bistack\_size}$ \1\&{then}% -\5 -$\\{bad}\K32$;\2\par -\fi - -\M554. Computation of the min and max is a tedious but fairly fast sequence of -instructions; exactly four comparisons are made in each branch. - -\Y\P\D \37$\\{set\_min\_max}(\#)\S$\1\6 -\&{if} $\\{stack\_1}(\#)<0$ \1\&{then}\6 -\&{if} $\\{stack\_3}(\#)\G0$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{stack\_2}(\#)<0$ \1\&{then}\5 -$\\{stack\_min}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)$\6 -\4\&{else} $\\{stack\_min}(\#)\K\\{stack\_1}(\#)$;\2\6 -$\\{stack\_max}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)+\\{stack\_3}(\#)$;\6 -\&{if} $\\{stack\_max}(\#)<0$ \1\&{then}\5 -$\\{stack\_max}(\#)\K0$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{stack\_min}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)+% -\\{stack\_3}(\#)$;\6 -\&{if} $\\{stack\_min}(\#)>\\{stack\_1}(\#)$ \1\&{then}\5 -$\\{stack\_min}(\#)\K\\{stack\_1}(\#)$;\2\6 -$\\{stack\_max}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)$;\6 -\&{if} $\\{stack\_max}(\#)<0$ \1\&{then}\5 -$\\{stack\_max}(\#)\K0$;\2\6 -\&{end}\2\6 -\4\&{else} \&{if} $\\{stack\_3}(\#)\L0$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{stack\_2}(\#)>0$ \1\&{then}\5 -$\\{stack\_max}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)$\6 -\4\&{else} $\\{stack\_max}(\#)\K\\{stack\_1}(\#)$;\2\6 -$\\{stack\_min}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)+\\{stack\_3}(\#)$;\6 -\&{if} $\\{stack\_min}(\#)>0$ \1\&{then}\5 -$\\{stack\_min}(\#)\K0$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{stack\_max}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)+% -\\{stack\_3}(\#)$;\6 -\&{if} $\\{stack\_max}(\#)<\\{stack\_1}(\#)$ \1\&{then}\5 -$\\{stack\_max}(\#)\K\\{stack\_1}(\#)$;\2\6 -$\\{stack\_min}(\#)\K\\{stack\_1}(\#)+\\{stack\_2}(\#)$;\6 -\&{if} $\\{stack\_min}(\#)>0$ \1\&{then}\5 -$\\{stack\_min}(\#)\K0$;\2\6 -\&{end}\2\2\2\par -\fi - -\M555. It's convenient to keep the current values of $l$, $t_1$, and $t_2$ in -the integer form $2^l+2^lt_1$ and $2^l+2^lt_2$. The \\{cubic\_intersection} -routine uses global variables \\{cur\_t} and \\{cur\_tt} for this purpose; -after successful completion, \\{cur\_t} and \\{cur\_tt} will contain \\{unity} -plus the \\{scaled} values of $t_1$ and~$t_2$. - -The values of \\{cur\_t} and \\{cur\_tt} will be set to zero if \\{cubic% -\_intersection} -finds no intersection. The routine gives up and gives an approximate answer -if it has backtracked -more than 5000 times (otherwise there are cases where several minutes -of fruitless computation would be possible). - -\Y\P\D \37$\\{max\_patience}=5000$\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{cur\_t},\39\\{cur\_tt}$: \37\\{integer};\C{controls and results of % -\\{cubic\_intersection}}\6 -\4\\{time\_to\_go}: \37\\{integer};\C{this many backtracks before giving up}\6 -\4\\{max\_t}: \37\\{integer};\C{maximum of $2^{l+1}$ so far achieved}\par -\fi - -\M556. The given cubics $B(w_0,w_1,w_2,w_3;t)$ and -$B(z_0,z_1,z_2,z_3;t)$ are specified in adjacent knot nodes $(\|p,\\{link}(% -\|p))$ -and $(\\{pp},\\{link}(\\{pp}))$, respectively. - -\Y\P\4\&{procedure}\1\ \37$\\{cubic\_intersection}(\|p,\39\\{pp}:% -\\{pointer})$;\6 -\4\&{label} \37$\\{continue},\39\\{not\_found},\39\\{exit}$;\6 -\4\&{var} \37$\|q,\39\\{qq}$: \37\\{pointer};\C{$\\{link}(\|p)$, $\\{link}(% -\\{pp})$}\2\6 -\&{begin} \37$\\{time\_to\_go}\K\\{max\_patience}$;\5 -$\\{max\_t}\K2$;\5 -\X558:Initialize for intersections at level zero\X;\6 -\~ \1\&{loop}\ \&{begin} \37\\{continue}: \37\&{if} $\\{delx}-\\{tol}\L\\{stack% -\_max}(\\{x\_packet}(\\{xy}))-\\{stack\_min}(\\{u\_packet}(\\{uv}))$ \1\&{then}% -\6 -\&{if} $\\{delx}+\\{tol}\G\\{stack\_min}(\\{x\_packet}(\\{xy}))-\\{stack\_max}(% -\\{u\_packet}(\\{uv}))$ \1\&{then}\6 -\&{if} $\\{dely}-\\{tol}\L\\{stack\_max}(\\{y\_packet}(\\{xy}))-\\{stack\_min}(% -\\{v\_packet}(\\{uv}))$ \1\&{then}\6 -\&{if} $\\{dely}+\\{tol}\G\\{stack\_min}(\\{y\_packet}(\\{xy}))-\\{stack\_max}(% -\\{v\_packet}(\\{uv}))$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{cur\_t}\G\\{max\_t}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{max\_t}=\\{two}$ \1\&{then}\C{we've done 17 bisections}% -\6 -\&{begin} \37$\\{cur\_t}\K\\{half}(\\{cur\_t}+1)$;\5 -$\\{cur\_tt}\K\\{half}(\\{cur\_tt}+1)$;\5 -\&{return};\6 -\&{end};\2\6 -$\\{double}(\\{max\_t})$;\5 -$\\{appr\_t}\K\\{cur\_t}$;\5 -$\\{appr\_tt}\K\\{cur\_tt}$;\6 -\&{end};\2\6 -\X559:Subdivide for a new level of intersection\X;\6 -\&{goto} \37\\{continue};\6 -\&{end};\2\2\2\2\6 -\&{if} $\\{time\_to\_go}>0$ \1\&{then}\5 -$\\{decr}(\\{time\_to\_go})$\6 -\4\&{else} \&{begin} \37\&{while} $\\{appr\_t}<\\{unity}$ \1\&{do}\6 -\&{begin} \37$\\{double}(\\{appr\_t})$;\5 -$\\{double}(\\{appr\_tt})$;\6 -\&{end};\2\6 -$\\{cur\_t}\K\\{appr\_t}$;\5 -$\\{cur\_tt}\K\\{appr\_tt}$;\5 -\&{return};\6 -\&{end};\2\6 -\X560:Advance to the next pair $(\\{cur\_t},\\{cur\_tt})$\X;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M557. The following variables are global, although they are used only by -\\{cubic\_intersection}, because it is necessary on some machines to -split \\{cubic\_intersection} up into two procedures. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{delx},\39\\{dely}$: \37\\{integer};\C{the components of $% -\Delta=2^l(w_0-z_0)$}\6 -\4\\{tol}: \37\\{integer};\C{bound on the uncertainly in the overlap test}\6 -\4$\\{uv},\39\\{xy}$: \37$0\to\\{bistack\_size}$;\C{pointers to the current -packets of interest}\6 -\4\\{three\_l}: \37\\{integer};\C{\\{tol\_step} times the bisection level}\6 -\4$\\{appr\_t},\39\\{appr\_tt}$: \37\\{integer};\C{best approximations known to -the answers}\par -\fi - -\M558. We shall assume that the coordinates are sufficiently non-extreme that -integer overflow will not occur. - -\Y\P$\4\X558:Initialize for intersections at level zero\X\S$\6 -$\|q\K\\{link}(\|p)$;\5 -$\\{qq}\K\\{link}(\\{pp})$;\5 -$\\{bisect\_ptr}\K\\{int\_packets}$;\6 -$\\{u1r}\K\\{right\_x}(\|p)-\\{x\_coord}(\|p)$;\5 -$\\{u2r}\K\\{left\_x}(\|q)-\\{right\_x}(\|p)$;\5 -$\\{u3r}\K\\{x\_coord}(\|q)-\\{left\_x}(\|q)$;\5 -$\\{set\_min\_max}(\\{ur\_packet})$;\6 -$\\{v1r}\K\\{right\_y}(\|p)-\\{y\_coord}(\|p)$;\5 -$\\{v2r}\K\\{left\_y}(\|q)-\\{right\_y}(\|p)$;\5 -$\\{v3r}\K\\{y\_coord}(\|q)-\\{left\_y}(\|q)$;\5 -$\\{set\_min\_max}(\\{vr\_packet})$;\6 -$\\{x1r}\K\\{right\_x}(\\{pp})-\\{x\_coord}(\\{pp})$;\5 -$\\{x2r}\K\\{left\_x}(\\{qq})-\\{right\_x}(\\{pp})$;\5 -$\\{x3r}\K\\{x\_coord}(\\{qq})-\\{left\_x}(\\{qq})$;\5 -$\\{set\_min\_max}(\\{xr\_packet})$;\6 -$\\{y1r}\K\\{right\_y}(\\{pp})-\\{y\_coord}(\\{pp})$;\5 -$\\{y2r}\K\\{left\_y}(\\{qq})-\\{right\_y}(\\{pp})$;\5 -$\\{y3r}\K\\{y\_coord}(\\{qq})-\\{left\_y}(\\{qq})$;\5 -$\\{set\_min\_max}(\\{yr\_packet})$;\6 -$\\{delx}\K\\{x\_coord}(\|p)-\\{x\_coord}(\\{pp})$;\5 -$\\{dely}\K\\{y\_coord}(\|p)-\\{y\_coord}(\\{pp})$;\6 -$\\{tol}\K0$;\5 -$\\{uv}\K\\{r\_packets}$;\5 -$\\{xy}\K\\{r\_packets}$;\5 -$\\{three\_l}\K0$;\5 -$\\{cur\_t}\K1$;\5 -$\\{cur\_tt}\K1$\par -\U556.\fi - -\M559. \P$\X559:Subdivide for a new level of intersection\X\S$\6 -$\\{stack\_dx}\K\\{delx}$;\5 -$\\{stack\_dy}\K\\{dely}$;\5 -$\\{stack\_tol}\K\\{tol}$;\5 -$\\{stack\_uv}\K\\{uv}$;\5 -$\\{stack\_xy}\K\\{xy}$;\5 -$\\{bisect\_ptr}\K\\{bisect\_ptr}+\\{int\_increment}$;\6 -$\\{double}(\\{cur\_t})$;\5 -$\\{double}(\\{cur\_tt})$;\6 -$\\{u1l}\K\\{stack\_1}(\\{u\_packet}(\\{uv}))$;\5 -$\\{u3r}\K\\{stack\_3}(\\{u\_packet}(\\{uv}))$;\5 -$\\{u2l}\K\\{half}(\\{u1l}+\\{stack\_2}(\\{u\_packet}(\\{uv})))$;\5 -$\\{u2r}\K\\{half}(\\{u3r}+\\{stack\_2}(\\{u\_packet}(\\{uv})))$;\5 -$\\{u3l}\K\\{half}(\\{u2l}+\\{u2r})$;\5 -$\\{u1r}\K\\{u3l}$;\5 -$\\{set\_min\_max}(\\{ul\_packet})$;\5 -$\\{set\_min\_max}(\\{ur\_packet})$;\6 -$\\{v1l}\K\\{stack\_1}(\\{v\_packet}(\\{uv}))$;\5 -$\\{v3r}\K\\{stack\_3}(\\{v\_packet}(\\{uv}))$;\5 -$\\{v2l}\K\\{half}(\\{v1l}+\\{stack\_2}(\\{v\_packet}(\\{uv})))$;\5 -$\\{v2r}\K\\{half}(\\{v3r}+\\{stack\_2}(\\{v\_packet}(\\{uv})))$;\5 -$\\{v3l}\K\\{half}(\\{v2l}+\\{v2r})$;\5 -$\\{v1r}\K\\{v3l}$;\5 -$\\{set\_min\_max}(\\{vl\_packet})$;\5 -$\\{set\_min\_max}(\\{vr\_packet})$;\6 -$\\{x1l}\K\\{stack\_1}(\\{x\_packet}(\\{xy}))$;\5 -$\\{x3r}\K\\{stack\_3}(\\{x\_packet}(\\{xy}))$;\5 -$\\{x2l}\K\\{half}(\\{x1l}+\\{stack\_2}(\\{x\_packet}(\\{xy})))$;\5 -$\\{x2r}\K\\{half}(\\{x3r}+\\{stack\_2}(\\{x\_packet}(\\{xy})))$;\5 -$\\{x3l}\K\\{half}(\\{x2l}+\\{x2r})$;\5 -$\\{x1r}\K\\{x3l}$;\5 -$\\{set\_min\_max}(\\{xl\_packet})$;\5 -$\\{set\_min\_max}(\\{xr\_packet})$;\6 -$\\{y1l}\K\\{stack\_1}(\\{y\_packet}(\\{xy}))$;\5 -$\\{y3r}\K\\{stack\_3}(\\{y\_packet}(\\{xy}))$;\5 -$\\{y2l}\K\\{half}(\\{y1l}+\\{stack\_2}(\\{y\_packet}(\\{xy})))$;\5 -$\\{y2r}\K\\{half}(\\{y3r}+\\{stack\_2}(\\{y\_packet}(\\{xy})))$;\5 -$\\{y3l}\K\\{half}(\\{y2l}+\\{y2r})$;\5 -$\\{y1r}\K\\{y3l}$;\5 -$\\{set\_min\_max}(\\{yl\_packet})$;\5 -$\\{set\_min\_max}(\\{yr\_packet})$;\6 -$\\{uv}\K\\{l\_packets}$;\5 -$\\{xy}\K\\{l\_packets}$;\5 -$\\{double}(\\{delx})$;\5 -$\\{double}(\\{dely})$;\6 -$\\{tol}\K\\{tol}-\\{three\_l}+\\{tol\_step}$;\5 -$\\{double}(\\{tol})$;\5 -$\\{three\_l}\K\\{three\_l}+\\{tol\_step}$\par -\U556.\fi - -\M560. \P$\X560:Advance to the next pair $(\\{cur\_t},\\{cur\_tt})$\X\S$\6 -\4\\{not\_found}: \37\&{if} $\\{odd}(\\{cur\_tt})$ \1\&{then}\6 -\&{if} $\\{odd}(\\{cur\_t})$ \1\&{then}\5 -\X561:Descend to the previous level and \&{goto} \\{not\_found}\X\6 -\4\&{else} \&{begin} \37$\\{incr}(\\{cur\_t})$;\5 -$\\{delx}\K\\{delx}+\\{stack\_1}(\\{u\_packet}(\\{uv}))+\\{stack\_2}(\\{u% -\_packet}(\\{uv}))+\\{stack\_3}(\\{u\_packet}(\\{uv}))$;\5 -$\\{dely}\K\\{dely}+\\{stack\_1}(\\{v\_packet}(\\{uv}))+\\{stack\_2}(\\{v% -\_packet}(\\{uv}))+\\{stack\_3}(\\{v\_packet}(\\{uv}))$;\5 -$\\{uv}\K\\{uv}+\\{int\_packets}$;\C{switch from \\{l\_packet} to \\{r% -\_packet}}\6 -$\\{decr}(\\{cur\_tt})$;\5 -$\\{xy}\K\\{xy}-\\{int\_packets}$;\C{switch from \\{r\_packet} to \\{l% -\_packet}}\6 -$\\{delx}\K\\{delx}+\\{stack\_1}(\\{x\_packet}(\\{xy}))+\\{stack\_2}(\\{x% -\_packet}(\\{xy}))+\\{stack\_3}(\\{x\_packet}(\\{xy}))$;\5 -$\\{dely}\K\\{dely}+\\{stack\_1}(\\{y\_packet}(\\{xy}))+\\{stack\_2}(\\{y% -\_packet}(\\{xy}))+\\{stack\_3}(\\{y\_packet}(\\{xy}))$;\6 -\&{end}\2\6 -\4\&{else} \&{begin} \37$\\{incr}(\\{cur\_tt})$;\5 -$\\{tol}\K\\{tol}+\\{three\_l}$;\5 -$\\{delx}\K\\{delx}-\\{stack\_1}(\\{x\_packet}(\\{xy}))-\\{stack\_2}(\\{x% -\_packet}(\\{xy}))-\\{stack\_3}(\\{x\_packet}(\\{xy}))$;\5 -$\\{dely}\K\\{dely}-\\{stack\_1}(\\{y\_packet}(\\{xy}))-\\{stack\_2}(\\{y% -\_packet}(\\{xy}))-\\{stack\_3}(\\{y\_packet}(\\{xy}))$;\5 -$\\{xy}\K\\{xy}+\\{int\_packets}$;\C{switch from \\{l\_packet} to \\{r% -\_packet}}\6 -\&{end}\2\par -\U556.\fi - -\M561. \P$\X561:Descend to the previous level and \&{goto} \\{not\_found}\X\S$\6 -\&{begin} \37$\\{cur\_t}\K\\{half}(\\{cur\_t})$;\5 -$\\{cur\_tt}\K\\{half}(\\{cur\_tt})$;\6 -\&{if} $\\{cur\_t}=0$ \1\&{then}\5 -\&{return};\2\6 -$\\{bisect\_ptr}\K\\{bisect\_ptr}-\\{int\_increment}$;\5 -$\\{three\_l}\K\\{three\_l}-\\{tol\_step}$;\5 -$\\{delx}\K\\{stack\_dx}$;\5 -$\\{dely}\K\\{stack\_dy}$;\5 -$\\{tol}\K\\{stack\_tol}$;\5 -$\\{uv}\K\\{stack\_uv}$;\5 -$\\{xy}\K\\{stack\_xy}$;\6 -\&{goto} \37\\{not\_found};\6 -\&{end}\par -\U560.\fi - -\M562. The \\{path\_intersection} procedure is much simpler. -It invokes \\{cubic\_intersection} in lexicographic order until finding a -pair of cubics that intersect. The final intersection times are placed in -\\{cur\_t} and~\\{cur\_tt}. - -\Y\P\4\&{procedure}\1\ \37$\\{path\_intersection}(\|h,\39\\{hh}:\\{pointer})$;% -\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|p,\39\\{pp}$: \37\\{pointer};\C{link registers that traverse -the given paths}\6 -$\|n,\39\\{nn}$: \37\\{integer};\C{integer parts of intersection times, minus % -\\{unity}}\2\6 -\&{begin} \37\X563:Change one-point paths into dead cycles\X;\6 -$\\{tol\_step}\K0$;\6 -\1\&{repeat} \37$\|n\K-\\{unity}$;\5 -$\|p\K\|h$;\6 -\1\&{repeat} \37\&{if} $\\{right\_type}(\|p)\I\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\\{nn}\K-\\{unity}$;\5 -$\\{pp}\K\\{hh}$;\6 -\1\&{repeat} \37\&{if} $\\{right\_type}(\\{pp})\I\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\\{cubic\_intersection}(\|p,\39\\{pp})$;\6 -\&{if} $\\{cur\_t}>0$ \1\&{then}\6 -\&{begin} \37$\\{cur\_t}\K\\{cur\_t}+\|n$;\5 -$\\{cur\_tt}\K\\{cur\_tt}+\\{nn}$;\5 -\&{return};\6 -\&{end};\2\6 -\&{end};\2\6 -$\\{nn}\K\\{nn}+\\{unity}$;\5 -$\\{pp}\K\\{link}(\\{pp})$;\6 -\4\&{until}\5 -$\\{pp}=\\{hh}$;\2\6 -\&{end};\2\6 -$\|n\K\|n+\\{unity}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\|p=\|h$;\2\6 -$\\{tol\_step}\K\\{tol\_step}+3$;\6 -\4\&{until}\5 -$\\{tol\_step}>3$;\2\6 -$\\{cur\_t}\K-\\{unity}$;\5 -$\\{cur\_tt}\K-\\{unity}$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M563. \P$\X563:Change one-point paths into dead cycles\X\S$\6 -\&{if} $\\{right\_type}(\|h)=\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\\{right\_x}(\|h)\K\\{x\_coord}(\|h)$;\5 -$\\{left\_x}(\|h)\K\\{x\_coord}(\|h)$;\5 -$\\{right\_y}(\|h)\K\\{y\_coord}(\|h)$;\5 -$\\{left\_y}(\|h)\K\\{y\_coord}(\|h)$;\5 -$\\{right\_type}(\|h)\K\\{explicit}$;\6 -\&{end};\2\6 -\&{if} $\\{right\_type}(\\{hh})=\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\\{right\_x}(\\{hh})\K\\{x\_coord}(\\{hh})$;\5 -$\\{left\_x}(\\{hh})\K\\{x\_coord}(\\{hh})$;\5 -$\\{right\_y}(\\{hh})\K\\{y\_coord}(\\{hh})$;\5 -$\\{left\_y}(\\{hh})\K\\{y\_coord}(\\{hh})$;\5 -$\\{right\_type}(\\{hh})\K\\{explicit}$;\6 -\&{end};\2\par -\U562.\fi - -\N564. \[27] Online graphic output. -\MF\ displays images on the user's screen by means of a few primitive -operations that are defined below. These operations have deliberately been -kept simple so that they can be implemented without great difficulty on a -wide variety of machines. Since \PASCAL\ has no traditional standards for -graphic output, some system-dependent code needs to be written in order to -support this aspect of \MF; but the necessary routines are usually quite -easy to write. - -In fact, there are exactly four such routines: - -\yskip\hang -\\{init\_screen} does whatever initialization is necessary to -support the other operations; it is a boolean function that returns -\\{false} if graphic output cannot be supported (e.g., if the other three -routines have not been written, or if the user doesn't have the -right kind of terminal). - -\yskip\hang -\\{blank\_rectangle} updates a buffer area in memory so that -all pixels in a specified rectangle will be set to the background color. - -\yskip\hang -\\{paint\_row} assigns values to specified pixels in a row of -the buffer just mentioned, based on ``transition'' indices explained below. - -\yskip\hang -\\{update\_screen} displays the current screen buffer; the -effects of \\{blank\_rectangle} and \\{paint\_row} commands may or may not -become visible until the next \\{update\_screen} operation is performed. -(Thus, \\{update\_screen} is analogous to \\{update\_terminal}.) - -\yskip\noindent -The \PASCAL\ code here is a minimum version of \\{init\_screen} and -\\{update\_screen}, usable on \MF\ installations that don't -support screen output. If \\{init\_screen} is changed to return \\{true} -instead of \\{false}, the other routines will simply log the fact -that they have been called; they won't really display anything. -The standard test routines for \MF\ use this log information to check -that \MF\ is working properly, but the \\{wlog} instructions should be -removed from production versions of \MF. - -\Y\P\4\&{function}\1\ \37\\{init\_screen}: \37\\{boolean};\2\6 -\&{begin} \37$\\{init\_screen}\K\\{false}$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37\\{update\_screen};\C{will be called only if \\{init% -\_screen} returns \\{true}}\2\6 -\&{begin} \37\&{init} \37$\\{wlog\_ln}(\.{\'Calling\ UPDATESCREEN\'})$;\ % -\&{tini}\C{for testing only}\6 -\&{end};\par -\fi - -\M565. The user's screen is assumed to be a rectangular area, \\{screen\_width} -pixels wide and \\{screen\_depth} pixels deep. The pixel in the upper left -corner is said to be in column~0 of row~0; the pixel in the lower right -corner is said to be in column $\\{screen\_width}-1$ of row $\\{screen% -\_depth}-1$. -Notice that row numbers increase from top to bottom, contrary to \MF's -other coordinates. - -Each pixel is assumed to have two states, referred to in this documentation -as \\{black} and \\{white}. The background color is called \\{white} and the -other color is called \\{black}; but any two distinct pixel values -can actually be used. For example, the author developed \MF\ on a -system for which \\{white} was black and \\{black} was bright green. - -\Y\P\D \37$\\{white}=0$\C{background pixels}\par -\P\D \37$\\{black}=1$\C{visible pixels}\par -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{screen\_row}=0\to\\{screen\_depth}$;\C{a row number on the screen}\6 -$\\{screen\_col}=0\to\\{screen\_width}$;\C{a column number on the screen}\6 -$\\{trans\_spec}=$\1\5 -\&{array} $[\\{screen\_col}]$ \1\&{of}\5 -\\{screen\_col};\C{a transition spec, see below}\2\2\6 -$\\{pixel\_color}=\\{white}\to\\{black}$;\C{specifies one of the two pixel -values}\par -\fi - -\M566. We'll illustrate the \\{blank\_rectangle} and \\{paint\_row} operations -by -pretending to declare a screen buffer called \\{screen\_pixel}. This code -is actually commented out, but it does specify the intended effects. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\B\\{screen\_pixel}$: \37\&{array} $[\\{screen\_row},\39\\{screen\_col}]$ \1% -\&{of}\5 -\\{pixel\_color};\ \2\6 -$\T$\par -\fi - -\M567. The \\{blank\_rectangle} routine simply whitens all pixels that lie in -columns \\{left\_col} through $\\{right\_col}-1$, inclusive, of rows -\\{top\_row} through $\\{bot\_row}-1$, inclusive, given four parameters that -satisfy -the relations -$$\hbox{$0\L\\{left\_col}\L\\{right\_col}\L\\{screen\_width}$,\quad -$0\L\\{top\_row}\L\\{bot\_row}\L\\{screen\_depth}$.}$$ -If $\\{left\_col}=\\{right\_col}$ or $\\{top\_row}=\\{bot\_row}$, nothing -happens. - -The commented-out code in the following procedure is for illustrative -purposes only. - -\Y\P\4\&{procedure}\1\ \37$\\{blank\_rectangle}(\\{left\_col},\39\\{right% -\_col}:\\{screen\_col};\,\35\\{top\_row},\39\\{bot\_row}:\\{screen\_row})$;\6 -\4\&{var} \37\|r: \37\\{screen\_row};\5 -\|c: \37\\{screen\_col};\2\6 -\&{begin} \37$\B$\ \&{for} $\|r\K\\{top\_row}\mathrel{\&{to}}\\{bot\_row}-1$ \1% -\&{do}\6 -\&{for} $\|c\K\\{left\_col}\mathrel{\&{to}}\\{right\_col}-1$ \1\&{do}\5 -$\\{screen\_pixel}[\|r,\39\|c]\K\\{white}$;\ \2\2\6 -$\T$\6 -\&{init} \37\\{wlog\_cr};\C{this will be done only after $\\{init\_screen}=% -\\{true}$}\6 -$\\{wlog\_ln}(\.{\'Calling\ BLANKRECTANGLE(\'},\39\\{left\_col}:1,\39\.{\',\'},% -\39\\{right\_col}:1,\39\.{\',\'},\39\\{top\_row}:1,\39\.{\',\'},\39\\{bot% -\_row}:1,\39\.{\')\'})$;\ \&{tini}\6 -\&{end};\par -\fi - -\M568. The real work of screen display is done by \\{paint\_row}. But it's not -hard work, because the operation affects only -one of the screen rows, and it affects only a contiguous set of columns -in that row. There are four parameters: \|r~(the row), -\|b~(the initial color), -\|a~(the array of transition specifications), -and \|n~(the number of transitions). The elements of~\|a will satisfy -$$0\L a[0]<a[1]<\cdots<a[n]\L \\{screen\_width};$$ -the value of \|r will satisfy $0\L\|r<\\{screen\_depth}$; and \|n will be -positive. - -The general idea is to paint blocks of pixels in alternate colors; -the precise details are best conveyed by means of a \PASCAL\ -program (see the commented-out code below). - -\Y\P\4\&{procedure}\1\ \37$\\{paint\_row}(\|r:\\{screen\_row};\,\35\|b:% -\\{pixel\_color};\,\35\mathop{\&{var}}\|a:\\{trans\_spec};\,\35\|n:\\{screen% -\_col})$;\6 -\4\&{var} \37\|k: \37\\{screen\_col};\C{an index into \|a}\6 -\|c: \37\\{screen\_col};\C{an index into \\{screen\_pixel}}\2\6 -\&{begin} \37$\B\|k\K0$;\5 -$\|c\K\|a[0]$;\6 -\1\&{repeat} \37$\\{incr}(\|k)$;\6 -\1\&{repeat} \37$\\{screen\_pixel}[\|r,\39\|c]\K\|b$;\5 -$\\{incr}(\|c)$;\6 -\4\&{until}\5 -$\|c=\|a[\|k]$;\2\6 -$\|b\K\\{black}-\|b$;\C{$\\{black}\swap\\{white}$}\6 -\4\&{until}\5 -$\|k=\|n$;\ \2\6 -$\T$\6 -\&{init} \37$\\{wlog}(\.{\'Calling\ PAINTROW(\'},\39\|r:1,\39\.{\',\'},\39% -\|b:1,\39\.{\';\'})$;\C{this is done only after $\\{init\_screen}=\\{true}$}\6 -\&{for} $\|k\K0\mathrel{\&{to}}\|n$ \1\&{do}\6 -\&{begin} \37$\\{wlog}(\|a[\|k]:1)$;\6 -\&{if} $\|k\I\|n$ \1\&{then}\5 -$\\{wlog}(\.{\',\'})$;\2\6 -\&{end};\2\6 -$\\{wlog\_ln}(\.{\')\'})$;\ \&{tini}\6 -\&{end};\par -\fi - -\M569. The remainder of \MF's screen routines are system-independent calls -on the four primitives just defined. - -First we have a global boolean variable that tells if \\{init\_screen} -has been called, and another one that tells if \\{init\_screen} has -given a \\{true} response. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{screen\_started}: \37\\{boolean};\C{have the screen primitives been -initialized?}\6 -\4\\{screen\_OK}: \37\\{boolean};\C{is it legitimate to call \\{blank% -\_rectangle}, \\{paint\_row}, and \\{update\_screen}?}\par -\fi - -\M570. \P\D \37$\\{start\_screen}\S$\1\6 -\&{begin} \37\&{if} $\R\\{screen\_started}$ \1\&{then}\6 -\&{begin} \37$\\{screen\_OK}\K\\{init\_screen}$;\5 -$\\{screen\_started}\K\\{true}$;\6 -\&{end};\2\6 -\&{end}\2\par -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{screen\_started}\K\\{false}$;\5 -$\\{screen\_OK}\K\\{false}$;\par -\fi - -\M571. \MF\ provides the user with 16 ``window'' areas on the screen, in each -of which it is possible to produce independent displays. - -It should be noted that \MF's windows aren't really independent -``clickable'' entities in the sense of multi-window graphic workstations; -\MF\ simply maps them into subsets of a single screen image that is -controlled by \\{init\_screen}, \\{blank\_rectangle}, \\{paint\_row}, and -\\{update\_screen} as described above. Implementations of \MF\ on a -multi-window workstation probably therefore make use of only two -windows in the other sense: one for the terminal output and another -for the screen with \MF's 16 areas. Henceforth we shall -use the term window only in \MF's sense. - -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{window\_number}=0\to15$;\par -\fi - -\M572. A user doesn't have to use any of the 16 windows. But when a window is -``opened,'' it is allocated to a specific rectangular portion of the screen -and to a specific rectangle with respect to \MF's coordinates. The relevant -data is stored in global arrays \\{window\_open}, \\{left\_col}, \\{right% -\_col}, -\\{top\_row}, \\{bot\_row}, \\{m\_window}, and \\{n\_window}. - -The \\{window\_open} array is boolean, and its significance is obvious. The -\\{left\_col}, \dots, \\{bot\_row} arrays contain screen coordinates that -can be used to blank the entire window with \\{blank\_rectangle}. And the -other two arrays just mentioned handle the conversion between -actual coordinates and screen coordinates: \MF's pixel in column~$m$ -of row~$n$ will appear in screen column $\\{m\_window}+\|m$ and in screen row -$\\{n\_window}-\|n$, provided that these lie inside the boundaries of the -window. - -Another array \\{window\_time} holds the number of times this window has -been updated. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{window\_open}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{boolean};\C{has this window been opened?}\2\6 -\4\\{left\_col}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{screen\_col};\C{leftmost column position on screen}\2\6 -\4\\{right\_col}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{screen\_col};\C{rightmost column position, plus~1}\2\6 -\4\\{top\_row}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{screen\_row};\C{topmost row position on screen}\2\6 -\4\\{bot\_row}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{screen\_row};\C{bottommost row position, plus~1}\2\6 -\4\\{m\_window}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{integer};\C{offset between user and screen columns}\2\6 -\4\\{n\_window}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{integer};\C{offset between user and screen rows}\2\6 -\4\\{window\_time}: \37\&{array} $[\\{window\_number}]$ \1\&{of}\5 -\\{integer};\C{it has been updated this often}\2\par -\fi - -\M573. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -\&{for} $\|k\K0\mathrel{\&{to}}15$ \1\&{do}\6 -\&{begin} \37$\\{window\_open}[\|k]\K\\{false}$;\5 -$\\{window\_time}[\|k]\K0$;\6 -\&{end};\2\par -\fi - -\M574. Opening a window isn't like opening a file, because you can open it -as often as you like, and you never have to close it again. The idea is -simply to define special points on the current screen display. - -Overlapping window specifications may cause complex effects that can -be understood only by scrutinizing \MF's display algorithms; thus it -has been left undefined in the \MF\ user manual, although the behavior -is in fact predictable. - -Here is a subroutine that implements the command `\&{openwindow}~\|k -\&{from}~$(\\{r0},\\{c0})$ \&{to}~$(\\{r1},\\{c1})$ \&{at}~$(x,y)$'. - -\Y\P\4\&{procedure}\1\ \37$\\{open\_a\_window}(\|k:\\{window\_number};\,\35% -\\{r0},\39\\{c0},\39\\{r1},\39\\{c1}:\\{scaled};\,\35\|x,\39\|y:\\{scaled})$;\6 -\4\&{var} \37$\|m,\39\|n$: \37\\{integer};\C{pixel coordinates}\2\6 -\&{begin} \37\X575:Adjust the coordinates $(\\{r0},\\{c0})$ and $(\\{r1},% -\\{c1})$ so that they lie in the proper range\X;\6 -$\\{window\_open}[\|k]\K\\{true}$;\5 -$\\{incr}(\\{window\_time}[\|k])$;\6 -$\\{left\_col}[\|k]\K\\{c0}$;\5 -$\\{right\_col}[\|k]\K\\{c1}$;\5 -$\\{top\_row}[\|k]\K\\{r0}$;\5 -$\\{bot\_row}[\|k]\K\\{r1}$;\6 -\X576:Compute the offsets between screen coordinates and actual coordinates\X;\6 -\\{start\_screen};\6 -\&{if} $\\{screen\_OK}$ \1\&{then}\6 -\&{begin} \37$\\{blank\_rectangle}(\\{c0},\39\\{c1},\39\\{r0},\39\\{r1})$;\5 -\\{update\_screen};\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M575. A window whose coordinates don't fit the existing screen size will be -truncated until they do. - -\Y\P$\4\X575:Adjust the coordinates $(\\{r0},\\{c0})$ and $(\\{r1},\\{c1})$ so -that they lie in the proper range\X\S$\6 -\&{if} $\\{r0}<0$ \1\&{then}\5 -$\\{r0}\K0$\ \&{else} $\\{r0}\K\\{round\_unscaled}(\\{r0})$;\2\6 -$\\{r1}\K\\{round\_unscaled}(\\{r1})$;\6 -\&{if} $\\{r1}>\\{screen\_depth}$ \1\&{then}\5 -$\\{r1}\K\\{screen\_depth}$;\2\6 -\&{if} $\\{r1}<\\{r0}$ \1\&{then}\6 -\&{if} $\\{r0}>\\{screen\_depth}$ \1\&{then}\5 -$\\{r0}\K\\{r1}$\ \&{else} $\\{r1}\K\\{r0}$;\2\2\6 -\&{if} $\\{c0}<0$ \1\&{then}\5 -$\\{c0}\K0$\ \&{else} $\\{c0}\K\\{round\_unscaled}(\\{c0})$;\2\6 -$\\{c1}\K\\{round\_unscaled}(\\{c1})$;\6 -\&{if} $\\{c1}>\\{screen\_width}$ \1\&{then}\5 -$\\{c1}\K\\{screen\_width}$;\2\6 -\&{if} $\\{c1}<\\{c0}$ \1\&{then}\6 -\&{if} $\\{c0}>\\{screen\_width}$ \1\&{then}\5 -$\\{c0}\K\\{c1}$\ \&{else} $\\{c1}\K\\{c0}$\2\2\par -\U574.\fi - -\M576. Three sets of coordinates are rampant, and they must be kept straight! -(i)~\MF's main coordinates refer to the edges between pixels. (ii)~\MF's -pixel coordinates (within edge structures) say that the pixel bounded by -$(m,n)$, $(m,n+1)$, $(m+1,n)$, and~$(m+1,n+1)$ is in pixel row number~$n$ -and pixel column number~$m$. (iii)~Screen coordinates, on the other hand, -have rows numbered in increasing order from top to bottom, as mentioned -above. - -The program here first computes integers $m$ and $n$ such that -pixel column~$m$ of pixel row~$n$ will be at the upper left corner -of the window. Hence pixel column $\|m-\\{c0}$ of pixel row $\|n+\\{r0}$ -will be at the upper left corner of the screen. - -\Y\P$\4\X576:Compute the offsets between screen coordinates and actual -coordinates\X\S$\6 -$\|m\K\\{round\_unscaled}(\|x)$;\5 -$\|n\K\\{round\_unscaled}(\|y)-1$;\6 -$\\{m\_window}[\|k]\K\\{c0}-\|m$;\5 -$\\{n\_window}[\|k]\K\\{r0}+\|n$\par -\U574.\fi - -\M577. Now here comes \MF's most complicated operation related to window -display: Given the number~\|k of an open window, the pixels of positive -weight in \\{cur\_edges} will be shown as \\{black} in the window; all other -pixels will be shown as \\{white}. - -\Y\P\4\&{procedure}\1\ \37$\\{disp\_edges}(\|k:\\{window\_number})$;\6 -\4\&{label} \37$\\{done},\39\\{found}$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{for list manipulation}\6 -\\{already\_there}: \37\\{boolean};\C{is a previous incarnation in the window?}% -\6 -\|r: \37\\{integer};\C{row number}\6 -\X580:Other local variables for \\{disp\_edges}\X\2\6 -\&{begin} \37\&{if} $\\{screen\_OK}$ \1\&{then}\6 -\&{if} $\\{left\_col}[\|k]<\\{right\_col}[\|k]$ \1\&{then}\6 -\&{if} $\\{top\_row}[\|k]<\\{bot\_row}[\|k]$ \1\&{then}\6 -\&{begin} \37$\\{already\_there}\K\\{false}$;\6 -\&{if} $\\{last\_window}(\\{cur\_edges})=\|k$ \1\&{then}\6 -\&{if} $\\{last\_window\_time}(\\{cur\_edges})=\\{window\_time}[\|k]$ \1% -\&{then}\5 -$\\{already\_there}\K\\{true}$;\2\2\6 -\&{if} $\R\\{already\_there}$ \1\&{then}\5 -$\\{blank\_rectangle}(\\{left\_col}[\|k],\39\\{right\_col}[\|k],\39\\{top% -\_row}[\|k],\39\\{bot\_row}[\|k])$;\2\6 -\X581:Initialize for the display computations\X;\6 -$\|p\K\\{link}(\\{cur\_edges})$;\5 -$\|r\K\\{n\_window}[\|k]-(\\{n\_min}(\\{cur\_edges})-\\{zero\_field})$;\6 -\&{while} $(\|p\I\\{cur\_edges})\W(\|r\G\\{top\_row}[\|k])$ \1\&{do}\6 -\&{begin} \37\&{if} $\|r<\\{bot\_row}[\|k]$ \1\&{then}\5 -\X578:Display the pixels of edge row \|p in screen row \|r\X;\2\6 -$\|p\K\\{link}(\|p)$;\5 -$\\{decr}(\|r)$;\6 -\&{end};\2\6 -\\{update\_screen};\5 -$\\{incr}(\\{window\_time}[\|k])$;\5 -$\\{last\_window}(\\{cur\_edges})\K\|k$;\5 -$\\{last\_window\_time}(\\{cur\_edges})\K\\{window\_time}[\|k]$;\6 -\&{end};\2\2\2\6 -\&{end};\par -\fi - -\M578. Since it takes some work to display a row, we try to avoid recomputation -whenever we can. - -\Y\P$\4\X578:Display the pixels of edge row \|p in screen row \|r\X\S$\6 -\&{begin} \37\&{if} $\\{unsorted}(\|p)>\\{void}$ \1\&{then}\5 -$\\{sort\_edges}(\|p)$\6 -\4\&{else} \&{if} $\\{unsorted}(\|p)=\\{void}$ \1\&{then}\6 -\&{if} $\\{already\_there}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\2\2\6 -$\\{unsorted}(\|p)\K\\{void}$;\C{this time we'll paint, but maybe not next -time}\6 -\X582:Set up the parameters needed for \\{paint\_row}; but \&{goto} \\{done} if -no painting is needed after all\X;\6 -$\\{paint\_row}(\|r,\39\|b,\39\\{row\_transition},\39\|n)$;\6 -\4\\{done}: \37\&{end}\par -\U577.\fi - -\M579. The transition-specification parameter to \\{paint\_row} is always the -same -array. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{row\_transition}: \37\\{trans\_spec};\C{an array of \\{black}/\\{white} -transitions}\par -\fi - -\M580. The job remaining is to go through the list $\\{sorted}(\|p)$, unpacking -the -\\{info} fields into \|m and weight, then making \\{black} the pixels whose -accumulated weight~\|w is positive. - -\Y\P$\4\X580:Other local variables for \\{disp\_edges}\X\S$\6 -\4\|n: \37\\{screen\_col};\C{the highest active index in \\{row\_transition}}\6 -\4$\|w,\39\\{ww}$: \37\\{integer};\C{old and new accumulated weights}\6 -\4\|b: \37\\{pixel\_color};\C{status of first pixel in the row transitions}\6 -\4$\|m,\39\\{mm}$: \37\\{integer};\C{old and new screen column positions}\6 -\4\|d: \37\\{integer};\C{edge-and-weight without \\{min\_halfword} -compensation}\6 -\4\\{m\_adjustment}: \37\\{integer};\C{conversion between edge and screen -coordinates}\6 -\4\\{right\_edge}: \37\\{integer};\C{largest edge-and-weight that could affect -the window}\6 -\4\\{min\_col}: \37\\{screen\_col};\C{the smallest screen column number in the -window}\par -\U577.\fi - -\M581. Some precomputed constants make the display calculations faster. - -\Y\P$\4\X581:Initialize for the display computations\X\S$\6 -$\\{m\_adjustment}\K\\{m\_window}[\|k]-\\{m\_offset}(\\{cur\_edges})$;\6 -$\\{right\_edge}\K8\ast(\\{right\_col}[\|k]-\\{m\_adjustment})$;\6 -$\\{min\_col}\K\\{left\_col}[\|k]$\par -\U577.\fi - -\M582. \P$\X582:Set up the parameters needed for \\{paint\_row}; but \&{goto} % -\\{done} if no painting is needed after all\X\S$\6 -$\|n\K0$;\5 -$\\{ww}\K0$;\5 -$\|m\K-1$;\5 -$\|w\K0$;\5 -$\|q\K\\{sorted}(\|p)$;\5 -$\\{row\_transition}[0]\K\\{min\_col}$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|q=\\{sentinel}$ \1\&{then}\5 -$\|d\K\\{right\_edge}$\6 -\4\&{else} $\|d\K\\{ho}(\\{info}(\|q))$;\2\6 -$\\{mm}\K(\|d\mathbin{\&{div}}8)+\\{m\_adjustment}$;\6 -\&{if} $\\{mm}\I\|m$ \1\&{then}\6 -\&{begin} \37\X583:Record a possible transition in column \|m\X;\6 -$\|m\K\\{mm}$;\5 -$\|w\K\\{ww}$;\6 -\&{end};\2\6 -\&{if} $\|d\G\\{right\_edge}$ \1\&{then}\5 -\&{goto} \37\\{found};\2\6 -$\\{ww}\K\\{ww}+(\|d\mathbin{\&{mod}}8)-\\{zero\_w}$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -\4\\{found}: \37\X584:Wind up the \\{paint\_row} parameter calculation by -inserting the final transition; \&{goto} \\{done} if no painting is needed\X;% -\par -\U578.\fi - -\M583. Now \|m is a screen column $<\\{right\_col}[\|k]$. - -\Y\P$\4\X583:Record a possible transition in column \|m\X\S$\6 -\&{if} $\|w\L0$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{ww}>0$ \1\&{then}\6 -\&{if} $\|m>\\{min\_col}$ \1\&{then}\6 -\&{begin} \37\&{if} $\|n=0$ \1\&{then}\6 -\&{if} $\\{already\_there}$ \1\&{then}\6 -\&{begin} \37$\|b\K\\{white}$;\5 -$\\{incr}(\|n)$;\6 -\&{end}\6 -\4\&{else} $\|b\K\\{black}$\2\6 -\4\&{else} $\\{incr}(\|n)$;\2\6 -$\\{row\_transition}[\|n]\K\|m$;\6 -\&{end};\2\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{ww}\L0$ \1\&{then}\6 -\&{if} $\|m>\\{min\_col}$ \1\&{then}\6 -\&{begin} \37\&{if} $\|n=0$ \1\&{then}\5 -$\|b\K\\{black}$;\2\6 -$\\{incr}(\|n)$;\5 -$\\{row\_transition}[\|n]\K\|m$;\6 -\&{end}\2\2\2\par -\U582.\fi - -\M584. If the entire row is \\{white} in the window area, we can omit painting -it -when \\{already\_there} is false, since it has already been blanked out in -that case. - -When the following code is invoked, $\\{row\_transition}[\|n]$ will be -strictly less than $\\{right\_col}[\|k]$. - -\Y\P$\4\X584:Wind up the \\{paint\_row} parameter calculation by inserting the -final transition; \&{goto} \\{done} if no painting is needed\X\S$\6 -\&{if} $\\{already\_there}\V(\\{ww}>0)$ \1\&{then}\6 -\&{begin} \37\&{if} $\|n=0$ \1\&{then}\6 -\&{if} $\\{ww}>0$ \1\&{then}\5 -$\|b\K\\{black}$\6 -\4\&{else} $\|b\K\\{white}$;\2\2\6 -$\\{incr}(\|n)$;\5 -$\\{row\_transition}[\|n]\K\\{right\_col}[\|k]$;\6 -\&{end}\6 -\4\&{else} \&{if} $\|n=0$ \1\&{then}\5 -\&{goto} \37\\{done}\2\2\par -\U582.\fi - -\N585. \[28] Dynamic linear equations. -\MF\ users define variables implicitly by stating equations that should be -satisfied; the computer is supposed to be smart enough to solve those -equations. -And indeed, the computer tries valiantly to do so, by distinguishing five -different types of numeric values: - -\smallskip\hang -$\\{type}(\|p)=\\{known}$ is the nice case, when $\\{value}(\|p)$ is the % -\\{scaled} value -of the variable whose address is~\|p. - -\smallskip\hang -$\\{type}(\|p)=\\{dependent}$ means that $\\{value}(\|p)$ is not present, but $% -\\{dep\_list}(\|p)$ -points to a {\sl dependency list\/} that expresses the value of variable~\|p -as a \\{scaled} number plus a sum of independent variables with \\{fraction} -coefficients. - -\smallskip\hang -$\\{type}(\|p)=\\{independent}$ means that $\\{value}(\|p)=64\|s+\|m$, where $% -\|s>0$ is a ``serial -number'' reflecting the time this variable was first used in an equation; -also $0\L\|m<64$, and each dependent variable -that refers to this one is actually referring to the future value of -this variable times~$2^m$. (Usually $\|m=0$, but higher degrees of -scaling are sometimes needed to keep the coefficients in dependency lists -from getting too large. The value of~\|m will always be even.) - -\smallskip\hang -$\\{type}(\|p)=\\{numeric\_type}$ means that variable \|p hasn't appeared in an -equation before, but it has been explicitly declared to be numeric. - -\smallskip\hang -$\\{type}(\|p)=\\{undefined}$ means that variable \|p hasn't appeared before. - -\smallskip\noindent -We have actually discussed these five types in the reverse order of their -history during a computation: Once \\{known}, a variable never again -becomes \\{dependent}; once \\{dependent}, it almost never again becomes -\\{independent}; once \\{independent}, it never again becomes \\{numeric% -\_type}; -and once \\{numeric\_type}, it never again becomes \\{undefined} (except -of course when the user specifically decides to scrap the old value -and start again). A backward step may, however, take place: Sometimes -a \\{dependent} variable becomes \\{independent} again, when one of the -independent variables it depends on is reverting to \\{undefined}. - -\Y\P\D \37$\\{s\_scale}=64$\C{the serial numbers are multiplied by this factor}% -\par -\P\D \37$\\{new\_indep}(\#)\S$\C{create a new independent variable}\6 -\&{begin} \37$\\{type}(\#)\K\\{independent}$;\5 -$\\{serial\_no}\K\\{serial\_no}+\\{s\_scale}$;\5 -$\\{value}(\#)\K\\{serial\_no}$;\6 -\&{end}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{serial\_no}: \37\\{integer};\C{the most recent serial number, times \\{s% -\_scale}}\par -\fi - -\M586. \P$\X586:Make variable $\|q+\|s$ newly independent\X\S$\6 -$\\{new\_indep}(\|q+\|s)$\par -\U232.\fi - -\M587. But how are dependency lists represented? It's simple: The linear -combination -$\alpha_1v_1+\cdots+\alpha_kv_k+\beta$ appears in $\|k+1$ value nodes. If -$\|q=\\{dep\_list}(\|p)$ points to this list, and if $\|k>0$, then $\\{value}(% -\|q)=\hbox{$\alpha_1$}$ (which is a \\{fraction}); $\\{info}(\|q)$ points to -the location -of $v_1$; and $\\{link}(\|p)$ points to the dependency list -$\alpha_2v_2+\cdots+\alpha_kv_k+\beta$. On the other hand if $\|k=0$, -then $\\{value}(\|q)=\hbox{$\beta$}$ (which is \\{scaled}) and $\\{info}(\|q)=% -\\{null}$. -The independent variables $v_1$, \dots,~$v_k$ have been sorted so that -they appear in decreasing order of their \\{value} fields (i.e., of -their serial numbers). \ (It is convenient to use decreasing order, -since $\\{value}(\\{null})=0$. If the independent variables were not sorted by -serial number but by some other criterion, such as their location in \\{mem}, -the equation-solving mechanism would be too system-dependent, because -the ordering can affect the computed results.) - -The \\{link} field in the node that contains the constant term $\beta$ is -called the {\sl final link\/} of the dependency list. \MF\ maintains -a doubly-linked master list of all dependency lists, in terms of a permanently -allocated node -in \\{mem} called \\{dep\_head}. If there are no dependencies, we have -$\\{link}(\\{dep\_head})=\\{dep\_head}$ and $\\{prev\_dep}(\\{dep\_head})=% -\\{dep\_head}$; -otherwise $\\{link}(\\{dep\_head})$ points to the first dependent variable, -say~\|p, -and $\\{prev\_dep}(\|p)=\\{dep\_head}$. We have $\\{type}(\|p)=\\{dependent}$, -and $\\{dep\_list}(\|p)$ -points to its dependency list. If the final link of that dependency list -occurs in location~\|q, then $\\{link}(\|q)$ points to the next dependent -variable (say~\|r); and we have $\\{prev\_dep}(\|r)=\|q$, etc. - -\Y\P\D \37$\\{dep\_list}(\#)\S\\{link}(\\{value\_loc}(\#))$\C{half of the % -\\{value} field in a \\{dependent} variable}\par -\P\D \37$\\{prev\_dep}(\#)\S\\{info}(\\{value\_loc}(\#))$\C{the other half; -makes a doubly linked list}\par -\P\D \37$\\{dep\_node\_size}=2$\C{the number of words per dependency node}\par -\Y\P$\4\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}\S$\6 -$\\{serial\_no}\K0$;\5 -$\\{link}(\\{dep\_head})\K\\{dep\_head}$;\5 -$\\{prev\_dep}(\\{dep\_head})\K\\{dep\_head}$;\5 -$\\{info}(\\{dep\_head})\K\\{null}$;\5 -$\\{dep\_list}(\\{dep\_head})\K\\{null}$;\par -\fi - -\M588. Actually the description above contains a little white lie. There's -another kind of variable called \\{proto\_dependent}, which is -just like a \\{dependent} one except that the $\alpha$ coefficients -in its dependency list are \\{scaled} instead of being fractions. -Proto-dependency lists are mixed with dependency lists in the -nodes reachable from \\{dep\_head}. - -\fi - -\M589. Here is a procedure that prints a dependency list in symbolic form. -The second parameter should be either \\{dependent} or \\{proto\_dependent}, -to indicate the scaling of the coefficients. - -\Y\P$\4\X257:Declare subroutines for printing expressions\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_dependency}(\|p:\\{pointer};\,\35\|t:\\{small% -\_number})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|v: \37\\{integer};\C{a coefficient}\6 -$\\{pp},\39\|q$: \37\\{pointer};\C{for list manipulation}\2\6 -\&{begin} \37$\\{pp}\K\|p$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|v\K\\{abs}(\\{value}(\|p))$;\5 -$\|q\K\\{info}(\|p)$;\6 -\&{if} $\|q=\\{null}$ \1\&{then}\C{the constant term}\6 -\&{begin} \37\&{if} $(\|v\I0)\V(\|p=\\{pp})$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{value}(\|p)>0$ \1\&{then}\6 -\&{if} $\|p\I\\{pp}$ \1\&{then}\5 -$\\{print\_char}(\.{"+"})$;\2\2\6 -$\\{print\_scaled}(\\{value}(\|p))$;\6 -\&{end};\2\6 -\&{return};\6 -\&{end};\2\6 -\X590:Print the coefficient, unless it's $\pm1.0$\X;\6 -\&{if} $\\{type}(\|q)\I\\{independent}$ \1\&{then}\5 -$\\{confusion}(\.{"dep"})$;\2\6 -$\\{print\_variable\_name}(\|q)$;\5 -$\|v\K\\{value}(\|q)\mathbin{\&{mod}}\\{s\_scale}$;\6 -\&{while} $\|v>0$ \1\&{do}\6 -\&{begin} \37$\\{print}(\.{"*4"})$;\5 -$\|v\K\|v-2$;\6 -\&{end};\2\6 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M590. \P$\X590:Print the coefficient, unless it's $\pm1.0$\X\S$\6 -\&{if} $\\{value}(\|p)<0$ \1\&{then}\5 -$\\{print\_char}(\.{"-"})$\6 -\4\&{else} \&{if} $\|p\I\\{pp}$ \1\&{then}\5 -$\\{print\_char}(\.{"+"})$;\2\2\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\5 -$\|v\K\\{round\_fraction}(\|v)$;\2\6 -\&{if} $\|v\I\\{unity}$ \1\&{then}\5 -$\\{print\_scaled}(\|v)$\2\par -\U589.\fi - -\M591. The maximum absolute value of a coefficient in a given dependency list -is returned by the following simple function. - -\Y\P\4\&{function}\1\ \37$\\{max\_coef}(\|p:\\{pointer})$: \37\\{fraction};\6 -\4\&{var} \37\|x: \37\\{fraction};\C{the maximum so far}\2\6 -\&{begin} \37$\|x\K0$;\6 -\&{while} $\\{info}(\|p)\I\\{null}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{abs}(\\{value}(\|p))>\|x$ \1\&{then}\5 -$\|x\K\\{abs}(\\{value}(\|p))$;\2\6 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\\{max\_coef}\K\|x$;\6 -\&{end};\par -\fi - -\M592. One of the main operations needed on dependency lists is to add a -multiple -of one list to the other; we call this \\{p\_plus\_fq}, where \|p and~\|q point -to dependency lists and \|f is a fraction. - -If the coefficient of any independent variable becomes \\{coef\_bound} or -more, in absolute value, this procedure changes the type of that variable -to `\\{independent\_needing\_fix}', and sets the global variable \\{fix% -\_needed} -to~\\{true}. The value of $\\{coef\_bound}=\mu$ is chosen so that -$\mu^2+\mu<8$; this means that the numbers we deal with won't -get too large. (Instead of the ``optimum'' $\mu=(\sqrt{33}-1)/2\approx -2.3723$, the safer value 7/3 is taken as the threshold.) - -The changes mentioned in the preceding paragraph are actually done only if -the global variable \\{watch\_coefs} is \\{true}. But it usually is; in fact, -it is \\{false} only when \MF\ is making a dependency list that will soon -be equated to zero. - -Several procedures that act on dependency lists, including \\{p\_plus\_fq}, -set the global variable \\{dep\_final} to the final (constant term) node of -the dependency list that they produce. - -\Y\P\D \37$\\{coef\_bound}\S\O{4525252525}$\C{\\{fraction} approximation to -7/3}\par -\P\D \37$\\{independent\_needing\_fix}=0$\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{fix\_needed}: \37\\{boolean};\C{does at least one \\{independent} variable -need scaling?}\6 -\4\\{watch\_coefs}: \37\\{boolean};\C{should we scale coefficients that exceed % -\\{coef\_bound}?}\6 -\4\\{dep\_final}: \37\\{pointer};\C{location of the constant term and final -link}\par -\fi - -\M593. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{fix\_needed}\K\\{false}$;\5 -$\\{watch\_coefs}\K\\{true}$;\par -\fi - -\M594. The \\{p\_plus\_fq} procedure has a fourth parameter, \|t, that should -be -set to \\{proto\_dependent} if \|p is a proto-dependency list. In this -case \|f will be \\{scaled}, not a \\{fraction}. Similarly, the fifth -parameter~\\{tt} -should be \\{proto\_dependent} if \|q is a proto-dependency list. - -List \|q is unchanged by the operation; but list \|p is totally destroyed. - -The final link of the dependency list or proto-dependency list returned -by \\{p\_plus\_fq} is the same as the original final link of~\|p. Indeed, the -constant term of the result will be located in the same \\{mem} location -as the original constant term of~\|p. - -Coefficients of the result are assumed to be zero if they are less than -a certain threshold. This compensates for inevitable rounding errors, -and tends to make more variables `\\{known}'. The threshold is approximately -$10^{-5}$ in the case of normal dependency lists, $10^{-4}$ for -proto-dependencies. - -\Y\P\D \37$\\{fraction\_threshold}=2685$\C{a \\{fraction} coefficient less than -this is zeroed}\par -\P\D \37$\\{half\_fraction\_threshold}=1342$\C{half of \\{fraction\_threshold}}% -\par -\P\D \37$\\{scaled\_threshold}=8$\C{a \\{scaled} coefficient less than this is -zeroed}\par -\P\D \37$\\{half\_scaled\_threshold}=4$\C{half of \\{scaled\_threshold}}\par -\Y\P$\4\X594:Declare basic dependency-list subroutines\X\S$\6 -\4\&{function}\1\ \37$\\{p\_plus\_fq}(\|p:\\{pointer};\,\35\|f:\\{integer};\,% -\35\|q:\\{pointer};\,\35\|t,\39\\{tt}:\\{small\_number})$: \37\\{pointer};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\\{pp},\39\\{qq}$: \37\\{pointer};\C{$\\{info}(\|p)$ and $% -\\{info}(\|q)$, respectively}\6 -$\|r,\39\|s$: \37\\{pointer};\C{for list manipulation}\6 -\\{threshold}: \37\\{integer};\C{defines a neighborhood of zero}\6 -\|v: \37\\{integer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\|t=\\{dependent}$ \1\&{then}\5 -$\\{threshold}\K\\{fraction\_threshold}$\6 -\4\&{else} $\\{threshold}\K\\{scaled\_threshold}$;\2\6 -$\|r\K\\{temp\_head}$;\5 -$\\{pp}\K\\{info}(\|p)$;\5 -$\\{qq}\K\\{info}(\|q)$;\6 -\~ \1\&{loop}\ \&{if} $\\{pp}=\\{qq}$ \1\&{then}\6 -\&{if} $\\{pp}=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done}\6 -\4\&{else} \X595:Contribute a term from \|p, plus \|f times the corresponding -term from \|q\X\2\6 -\4\&{else} \&{if} $\\{value}(\\{pp})<\\{value}(\\{qq})$ \1\&{then}\5 -\X596:Contribute a term from \|q, multiplied by~\|f\X\6 -\4\&{else} \&{begin} \37$\\{link}(\|r)\K\|p$;\5 -$\|r\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{pp}\K\\{info}(\|p)$;\6 -\&{end};\2\2\2\6 -\4\\{done}: \37\&{if} $\|t=\\{dependent}$ \1\&{then}\5 -$\\{value}(\|p)\K\\{slow\_add}(\\{value}(\|p),\39\\{take\_fraction}(\\{value}(% -\|q),\39\|f))$\6 -\4\&{else} $\\{value}(\|p)\K\\{slow\_add}(\\{value}(\|p),\39\\{take\_scaled}(% -\\{value}(\|q),\39\|f))$;\2\6 -$\\{link}(\|r)\K\|p$;\5 -$\\{dep\_final}\K\|p$;\5 -$\\{p\_plus\_fq}\K\\{link}(\\{temp\_head})$;\6 -\&{end};\par -\As600, 602, 603\ETs604. -\U246.\fi - -\M595. \P$\X595:Contribute a term from \|p, plus \|f times the corresponding -term from \|q\X\S$\6 -\&{begin} \37\&{if} $\\{tt}=\\{dependent}$ \1\&{then}\5 -$\|v\K\\{value}(\|p)+\\{take\_fraction}(\|f,\39\\{value}(\|q))$\6 -\4\&{else} $\|v\K\\{value}(\|p)+\\{take\_scaled}(\|f,\39\\{value}(\|q))$;\2\6 -$\\{value}(\|p)\K\|v$;\5 -$\|s\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{if} $\\{abs}(\|v)<\\{threshold}$ \1\&{then}\5 -$\\{free\_node}(\|s,\39\\{dep\_node\_size})$\6 -\4\&{else} \&{begin} \37\&{if} $\\{abs}(\|v)\G\\{coef\_bound}$ \1\&{then}\6 -\&{if} $\\{watch\_coefs}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\\{qq})\K\\{independent\_needing\_fix}$;\5 -$\\{fix\_needed}\K\\{true}$;\6 -\&{end};\2\2\6 -$\\{link}(\|r)\K\|s$;\5 -$\|r\K\|s$;\6 -\&{end};\2\6 -$\\{pp}\K\\{info}(\|p)$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{qq}\K\\{info}(\|q)$;\6 -\&{end}\par -\U594.\fi - -\M596. \P$\X596:Contribute a term from \|q, multiplied by~\|f\X\S$\6 -\&{begin} \37\&{if} $\\{tt}=\\{dependent}$ \1\&{then}\5 -$\|v\K\\{take\_fraction}(\|f,\39\\{value}(\|q))$\6 -\4\&{else} $\|v\K\\{take\_scaled}(\|f,\39\\{value}(\|q))$;\2\6 -\&{if} $\\{abs}(\|v)>\\{half}(\\{threshold})$ \1\&{then}\6 -\&{begin} \37$\|s\K\\{get\_node}(\\{dep\_node\_size})$;\5 -$\\{info}(\|s)\K\\{qq}$;\5 -$\\{value}(\|s)\K\|v$;\6 -\&{if} $\\{abs}(\|v)\G\\{coef\_bound}$ \1\&{then}\6 -\&{if} $\\{watch\_coefs}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\\{qq})\K\\{independent\_needing\_fix}$;\5 -$\\{fix\_needed}\K\\{true}$;\6 -\&{end};\2\2\6 -$\\{link}(\|r)\K\|s$;\5 -$\|r\K\|s$;\6 -\&{end};\2\6 -$\|q\K\\{link}(\|q)$;\5 -$\\{qq}\K\\{info}(\|q)$;\6 -\&{end}\par -\U594.\fi - -\M597. It is convenient to have another subroutine for the special case -of \\{p\_plus\_fq} when $\|f=1.0$. In this routine lists \|p and \|q are -both of the same type~\|t (either \\{dependent} or \\{proto\_dependent}). - -\Y\P\4\&{function}\1\ \37$\\{p\_plus\_q}(\|p:\\{pointer};\,\35\|q:\\{pointer};% -\,\35\|t:\\{small\_number})$: \37\\{pointer};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\\{pp},\39\\{qq}$: \37\\{pointer};\C{$\\{info}(\|p)$ and $% -\\{info}(\|q)$, respectively}\6 -$\|r,\39\|s$: \37\\{pointer};\C{for list manipulation}\6 -\\{threshold}: \37\\{integer};\C{defines a neighborhood of zero}\6 -\|v: \37\\{integer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\|t=\\{dependent}$ \1\&{then}\5 -$\\{threshold}\K\\{fraction\_threshold}$\6 -\4\&{else} $\\{threshold}\K\\{scaled\_threshold}$;\2\6 -$\|r\K\\{temp\_head}$;\5 -$\\{pp}\K\\{info}(\|p)$;\5 -$\\{qq}\K\\{info}(\|q)$;\6 -\~ \1\&{loop}\ \&{if} $\\{pp}=\\{qq}$ \1\&{then}\6 -\&{if} $\\{pp}=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done}\6 -\4\&{else} \X598:Contribute a term from \|p, plus the corresponding term from % -\|q\X\2\6 -\4\&{else} \&{if} $\\{value}(\\{pp})<\\{value}(\\{qq})$ \1\&{then}\6 -\&{begin} \37$\|s\K\\{get\_node}(\\{dep\_node\_size})$;\5 -$\\{info}(\|s)\K\\{qq}$;\5 -$\\{value}(\|s)\K\\{value}(\|q)$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{qq}\K\\{info}(\|q)$;\5 -$\\{link}(\|r)\K\|s$;\5 -$\|r\K\|s$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{link}(\|r)\K\|p$;\5 -$\|r\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{pp}\K\\{info}(\|p)$;\6 -\&{end};\2\2\2\6 -\4\\{done}: \37$\\{value}(\|p)\K\\{slow\_add}(\\{value}(\|p),\39\\{value}(% -\|q))$;\5 -$\\{link}(\|r)\K\|p$;\5 -$\\{dep\_final}\K\|p$;\5 -$\\{p\_plus\_q}\K\\{link}(\\{temp\_head})$;\6 -\&{end};\par -\fi - -\M598. \P$\X598:Contribute a term from \|p, plus the corresponding term from % -\|q\X\S$\6 -\&{begin} \37$\|v\K\\{value}(\|p)+\\{value}(\|q)$;\5 -$\\{value}(\|p)\K\|v$;\5 -$\|s\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\5 -$\\{pp}\K\\{info}(\|p)$;\6 -\&{if} $\\{abs}(\|v)<\\{threshold}$ \1\&{then}\5 -$\\{free\_node}(\|s,\39\\{dep\_node\_size})$\6 -\4\&{else} \&{begin} \37\&{if} $\\{abs}(\|v)\G\\{coef\_bound}$ \1\&{then}\6 -\&{if} $\\{watch\_coefs}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\\{qq})\K\\{independent\_needing\_fix}$;\5 -$\\{fix\_needed}\K\\{true}$;\6 -\&{end};\2\2\6 -$\\{link}(\|r)\K\|s$;\5 -$\|r\K\|s$;\6 -\&{end};\2\6 -$\|q\K\\{link}(\|q)$;\5 -$\\{qq}\K\\{info}(\|q)$;\6 -\&{end}\par -\U597.\fi - -\M599. A somewhat simpler routine will multiply a dependency list -by a given constant~\|v. The constant is either a \\{fraction} less than -\\{fraction\_one}, or it is \\{scaled}. In the latter case we might be forced -to -convert a dependency list to a proto-dependency list. -Parameters \\{t0} and \\{t1} are the list types before and after; -they should agree unless $\\{t0}=\\{dependent}$ and $\\{t1}=\\{proto% -\_dependent}$ -and $\\{v\_is\_scaled}=\\{true}$. - -\Y\P\4\&{function}\1\ \37$\\{p\_times\_v}(\|p:\\{pointer};\,\35\|v:% -\\{integer};\,\35\\{t0},\39\\{t1}:\\{small\_number};\,\35\\{v\_is\_scaled}:% -\\{boolean})$: \37\\{pointer};\6 -\4\&{var} \37$\|r,\39\|s$: \37\\{pointer};\C{for list manipulation}\6 -\|w: \37\\{integer};\C{tentative coefficient}\6 -\\{threshold}: \37\\{integer};\5 -\\{scaling\_down}: \37\\{boolean};\2\6 -\&{begin} \37\&{if} $\\{t0}\I\\{t1}$ \1\&{then}\5 -$\\{scaling\_down}\K\\{true}$\ \&{else} $\\{scaling\_down}\K\R\\{v\_is% -\_scaled}$;\2\6 -\&{if} $\\{t1}=\\{dependent}$ \1\&{then}\5 -$\\{threshold}\K\\{half\_fraction\_threshold}$\6 -\4\&{else} $\\{threshold}\K\\{half\_scaled\_threshold}$;\2\6 -$\|r\K\\{temp\_head}$;\6 -\&{while} $\\{info}(\|p)\I\\{null}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{scaling\_down}$ \1\&{then}\5 -$\|w\K\\{take\_fraction}(\|v,\39\\{value}(\|p))$\6 -\4\&{else} $\|w\K\\{take\_scaled}(\|v,\39\\{value}(\|p))$;\2\6 -\&{if} $\\{abs}(\|w)\L\\{threshold}$ \1\&{then}\6 -\&{begin} \37$\|s\K\\{link}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{dep\_node\_size})$;\5 -$\|p\K\|s$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{abs}(\|w)\G\\{coef\_bound}$ \1\&{then}\6 -\&{begin} \37$\\{fix\_needed}\K\\{true}$;\5 -$\\{type}(\\{info}(\|p))\K\\{independent\_needing\_fix}$;\6 -\&{end};\2\6 -$\\{link}(\|r)\K\|p$;\5 -$\|r\K\|p$;\5 -$\\{value}(\|p)\K\|w$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\\{link}(\|r)\K\|p$;\6 -\&{if} $\\{v\_is\_scaled}$ \1\&{then}\5 -$\\{value}(\|p)\K\\{take\_scaled}(\\{value}(\|p),\39\|v)$\6 -\4\&{else} $\\{value}(\|p)\K\\{take\_fraction}(\\{value}(\|p),\39\|v)$;\2\6 -$\\{p\_times\_v}\K\\{link}(\\{temp\_head})$;\6 -\&{end};\par -\fi - -\M600. Similarly, we sometimes need to divide a dependency list -by a given \\{scaled} constant. - -\Y\P$\4\X594:Declare basic dependency-list subroutines\X\mathrel{+}\S$\6 -\4\&{function}\1\ \37$\\{p\_over\_v}(\|p:\\{pointer};\,\35\|v:\\{scaled};\,\35% -\\{t0},\39\\{t1}:\\{small\_number})$: \37\\{pointer};\6 -\4\&{var} \37$\|r,\39\|s$: \37\\{pointer};\C{for list manipulation}\6 -\|w: \37\\{integer};\C{tentative coefficient}\6 -\\{threshold}: \37\\{integer};\5 -\\{scaling\_down}: \37\\{boolean};\2\6 -\&{begin} \37\&{if} $\\{t0}\I\\{t1}$ \1\&{then}\5 -$\\{scaling\_down}\K\\{true}$\ \&{else} $\\{scaling\_down}\K\\{false}$;\2\6 -\&{if} $\\{t1}=\\{dependent}$ \1\&{then}\5 -$\\{threshold}\K\\{half\_fraction\_threshold}$\6 -\4\&{else} $\\{threshold}\K\\{half\_scaled\_threshold}$;\2\6 -$\|r\K\\{temp\_head}$;\6 -\&{while} $\\{info}(\|p)\I\\{null}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{scaling\_down}$ \1\&{then}\6 -\&{if} $\\{abs}(\|v)<\O{2000000}$ \1\&{then}\5 -$\|w\K\\{make\_scaled}(\\{value}(\|p),\39\|v\ast\O{10000})$\6 -\4\&{else} $\|w\K\\{make\_scaled}(\\{round\_fraction}(\\{value}(\|p)),\39\|v)$% -\2\6 -\4\&{else} $\|w\K\\{make\_scaled}(\\{value}(\|p),\39\|v)$;\2\6 -\&{if} $\\{abs}(\|w)\L\\{threshold}$ \1\&{then}\6 -\&{begin} \37$\|s\K\\{link}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{dep\_node\_size})$;\5 -$\|p\K\|s$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{abs}(\|w)\G\\{coef\_bound}$ \1\&{then}\6 -\&{begin} \37$\\{fix\_needed}\K\\{true}$;\5 -$\\{type}(\\{info}(\|p))\K\\{independent\_needing\_fix}$;\6 -\&{end};\2\6 -$\\{link}(\|r)\K\|p$;\5 -$\|r\K\|p$;\5 -$\\{value}(\|p)\K\|w$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\\{link}(\|r)\K\|p$;\5 -$\\{value}(\|p)\K\\{make\_scaled}(\\{value}(\|p),\39\|v)$;\5 -$\\{p\_over\_v}\K\\{link}(\\{temp\_head})$;\6 -\&{end};\par -\fi - -\M601. Here's another utility routine for dependency lists. When an independent -variable becomes dependent, we want to remove it from all existing -dependencies. The \\{p\_with\_x\_becoming\_q} function computes the -dependency list of~\|p after variable~\|x has been replaced by~\|q. - -This procedure has basically the same calling conventions as \\{p\_plus\_fq}: -List~\|q is unchanged; list~\|p is destroyed; the constant node and the -final link are inherited from~\|p; and the fourth parameter tells whether -or not \|p is \\{proto\_dependent}. However, the global variable \\{dep\_final} -is not altered if \|x does not occur in list~\|p. - -\Y\P\4\&{function}\1\ \37$\\{p\_with\_x\_becoming\_q}(\|p,\39\|x,\39\|q:% -\\{pointer};\,\35\|t:\\{small\_number})$: \37\\{pointer};\6 -\4\&{var} \37$\|r,\39\|s$: \37\\{pointer};\C{for list manipulation}\6 -\|v: \37\\{integer};\C{coefficient of \|x}\6 -\\{sx}: \37\\{integer};\C{serial number of \|x}\2\6 -\&{begin} \37$\|s\K\|p$;\5 -$\|r\K\\{temp\_head}$;\5 -$\\{sx}\K\\{value}(\|x)$;\6 -\&{while} $\\{value}(\\{info}(\|s))>\\{sx}$ \1\&{do}\6 -\&{begin} \37$\|r\K\|s$;\5 -$\|s\K\\{link}(\|s)$;\6 -\&{end};\2\6 -\&{if} $\\{info}(\|s)\I\|x$ \1\&{then}\5 -$\\{p\_with\_x\_becoming\_q}\K\|p$\6 -\4\&{else} \&{begin} \37$\\{link}(\\{temp\_head})\K\|p$;\5 -$\\{link}(\|r)\K\\{link}(\|s)$;\5 -$\|v\K\\{value}(\|s)$;\5 -$\\{free\_node}(\|s,\39\\{dep\_node\_size})$;\5 -$\\{p\_with\_x\_becoming\_q}\K\\{p\_plus\_fq}(\\{link}(\\{temp\_head}),\39\|v,% -\39\|q,\39\|t,\39\\{dependent})$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M602. Here's a simple procedure that reports an error when a variable -has just received a known value that's out of the required range. - -\Y\P$\4\X594:Declare basic dependency-list subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{val\_too\_big}(\|x:\\{scaled})$;\2\6 -\&{begin} \37\&{if} $\\{internal}[\\{warning\_check}]>0$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Value\ is\ too\ large\ ("})$;\5 -$\\{print\_scaled}(\|x)$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\\{help4}(\.{"The\ equation\ I\ just\ processed\ has\ given\ some\ -variable"})$\6 -$(\.{"a\ value\ of\ 4096\ or\ more.\ Continue\ and\ I\'ll\ try\ to\ cope"})$\6 -$(\.{"with\ that\ big\ value;\ but\ it\ might\ be\ dangerous."})$\6 -$(\.{"(Set\ warningcheck:=0\ to\ suppress\ this\ message.)"})$;\5 -\\{error};\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M603. When a dependent variable becomes known, the following routine -removes its dependency list. Here \|p points to the variable, and -\|q points to the dependency list (which is one node long). - -\Y\P$\4\X594:Declare basic dependency-list subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{make\_known}(\|p,\39\|q:\\{pointer})$;\6 -\4\&{var} \37\|t: \37$\\{dependent}\to\\{proto\_dependent}$;\C{the previous -type}\2\6 -\&{begin} \37$\\{prev\_dep}(\\{link}(\|q))\K\\{prev\_dep}(\|p)$;\5 -$\\{link}(\\{prev\_dep}(\|p))\K\\{link}(\|q)$;\5 -$\|t\K\\{type}(\|p)$;\5 -$\\{type}(\|p)\K\\{known}$;\5 -$\\{value}(\|p)\K\\{value}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{dep\_node\_size})$;\6 -\&{if} $\\{abs}(\\{value}(\|p))\G\\{fraction\_one}$ \1\&{then}\5 -$\\{val\_too\_big}(\\{value}(\|p))$;\2\6 -\&{if} $\\{internal}[\\{tracing\_equations}]>0$ \1\&{then}\6 -\&{if} $\\{interesting}(\|p)$ \1\&{then}\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\#\#\#\#\ "})$;\5 -$\\{print\_variable\_name}(\|p)$;\5 -$\\{print\_char}(\.{"="})$;\5 -$\\{print\_scaled}(\\{value}(\|p))$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end};\2\2\6 -\&{if} $\\{cur\_exp}=\|p$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\|t$ \1\&{then}\6 -\&{begin} \37$\\{cur\_type}\K\\{known}$;\5 -$\\{cur\_exp}\K\\{value}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M604. The \\{fix\_dependencies} routine is called into action when \\{fix% -\_needed} -has been triggered. The program keeps a list~\|s of independent variables -whose coefficients must be divided by~4. - -In unusual cases, this fixup process might reduce one or more coefficients -to zero, so that a variable will become known more or less by default. - -\Y\P$\4\X594:Declare basic dependency-list subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{fix\_dependencies};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\|s,\39\|t$: \37\\{pointer};\C{list -manipulation registers}\6 -\|x: \37\\{pointer};\C{an independent variable}\2\6 -\&{begin} \37$\|r\K\\{link}(\\{dep\_head})$;\5 -$\|s\K\\{null}$;\6 -\&{while} $\|r\I\\{dep\_head}$ \1\&{do}\6 -\&{begin} \37$\|t\K\|r$;\5 -\X605:Run through the dependency list for variable \|t, fixing all nodes, and -ending with final link~\|q\X;\6 -$\|r\K\\{link}(\|q)$;\6 -\&{if} $\|q=\\{dep\_list}(\|t)$ \1\&{then}\5 -$\\{make\_known}(\|t,\39\|q)$;\2\6 -\&{end};\2\6 -\&{while} $\|s\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\|p\K\\{link}(\|s)$;\5 -$\|x\K\\{info}(\|s)$;\5 -$\\{free\_avail}(\|s)$;\5 -$\|s\K\|p$;\5 -$\\{type}(\|x)\K\\{independent}$;\5 -$\\{value}(\|x)\K\\{value}(\|x)+2$;\6 -\&{end};\2\6 -$\\{fix\_needed}\K\\{false}$;\6 -\&{end};\par -\fi - -\M605. \P\D \37$\\{independent\_being\_fixed}=1$\C{this variable already -appears in \|s}\par -\Y\P$\4\X605:Run through the dependency list for variable \|t, fixing all -nodes, and ending with final link~\|q\X\S$\6 -$\|r\K\\{value\_loc}(\|t)$;\C{$\\{link}(\|r)=\\{dep\_list}(\|t)$}\6 -\~ \1\&{loop}\ \&{begin} \37$\|q\K\\{link}(\|r)$;\5 -$\|x\K\\{info}(\|q)$;\6 -\&{if} $\|x=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{type}(\|x)\L\\{independent\_being\_fixed}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{type}(\|x)<\\{independent\_being\_fixed}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{get\_avail}$;\5 -$\\{link}(\|p)\K\|s$;\5 -$\|s\K\|p$;\5 -$\\{info}(\|s)\K\|x$;\5 -$\\{type}(\|x)\K\\{independent\_being\_fixed}$;\6 -\&{end};\2\6 -$\\{value}(\|q)\K\\{value}(\|q)\mathbin{\&{div}}4$;\6 -\&{if} $\\{value}(\|q)=0$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|r)\K\\{link}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{dep\_node\_size})$;\5 -$\|q\K\|r$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\|r\K\|q$;\6 -\&{end};\2\6 -\4\\{done}: \37\par -\U604.\fi - -\M606. The \\{new\_dep} routine installs a dependency list~\|p into the value -node~\|q, -linking it into the list of all known dependencies. We assume that -\\{dep\_final} points to the final node of list~\|p. - -\Y\P\4\&{procedure}\1\ \37$\\{new\_dep}(\|q,\39\|p:\\{pointer})$;\6 -\4\&{var} \37\|r: \37\\{pointer};\C{what used to be the first dependency}\2\6 -\&{begin} \37$\\{dep\_list}(\|q)\K\|p$;\5 -$\\{prev\_dep}(\|q)\K\\{dep\_head}$;\5 -$\|r\K\\{link}(\\{dep\_head})$;\5 -$\\{link}(\\{dep\_final})\K\|r$;\5 -$\\{prev\_dep}(\|r)\K\\{dep\_final}$;\5 -$\\{link}(\\{dep\_head})\K\|q$;\6 -\&{end};\par -\fi - -\M607. Here is one of the ways a dependency list gets started. -The \\{const\_dependency} routine produces a list that has nothing but -a constant term. - -\Y\P\4\&{function}\1\ \37$\\{const\_dependency}(\|v:\\{scaled})$: \37% -\\{pointer};\2\6 -\&{begin} \37$\\{dep\_final}\K\\{get\_node}(\\{dep\_node\_size})$;\5 -$\\{value}(\\{dep\_final})\K\|v$;\5 -$\\{info}(\\{dep\_final})\K\\{null}$;\5 -$\\{const\_dependency}\K\\{dep\_final}$;\6 -\&{end};\par -\fi - -\M608. And here's a more interesting way to start a dependency list from -scratch: -The parameter to \\{single\_dependency} is the location of an -independent variable~\|x, and the result is the simple dependency list -`$\|x+0$'. - -In the unlikely event that the given independent variable has been doubled so -often that we can't refer to it with a nonzero coefficient, -\\{single\_dependency} returns the simple list `0'. This case can be -recognized by testing that the returned list pointer is equal to -\\{dep\_final}. - -\Y\P\4\&{function}\1\ \37$\\{single\_dependency}(\|p:\\{pointer})$: \37% -\\{pointer};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the new dependency list}\6 -\|m: \37\\{integer};\C{the number of doublings}\2\6 -\&{begin} \37$\|m\K\\{value}(\|p)\mathbin{\&{mod}}\\{s\_scale}$;\6 -\&{if} $\|m>28$ \1\&{then}\5 -$\\{single\_dependency}\K\\{const\_dependency}(0)$\6 -\4\&{else} \&{begin} \37$\|q\K\\{get\_node}(\\{dep\_node\_size})$;\5 -$\\{value}(\|q)\K\\{two\_to\_the}[28-\|m]$;\5 -$\\{info}(\|q)\K\|p$;\6 -$\\{link}(\|q)\K\\{const\_dependency}(0)$;\5 -$\\{single\_dependency}\K\|q$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M609. We sometimes need to make an exact copy of a dependency list. - -\Y\P\4\&{function}\1\ \37$\\{copy\_dep\_list}(\|p:\\{pointer})$: \37% -\\{pointer};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the new dependency list}\2\6 -\&{begin} \37$\|q\K\\{get\_node}(\\{dep\_node\_size})$;\5 -$\\{dep\_final}\K\|q$;\6 -\~ \1\&{loop}\ \&{begin} \37$\\{info}(\\{dep\_final})\K\\{info}(\|p)$;\5 -$\\{value}(\\{dep\_final})\K\\{value}(\|p)$;\6 -\&{if} $\\{info}(\\{dep\_final})=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{link}(\\{dep\_final})\K\\{get\_node}(\\{dep\_node\_size})$;\5 -$\\{dep\_final}\K\\{link}(\\{dep\_final})$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{copy\_dep\_list}\K\|q$;\6 -\&{end};\par -\fi - -\M610. But how do variables normally become known? Ah, now we get to the heart -of the -equation-solving mechanism. The \\{linear\_eq} procedure is given a % -\\{dependent} -or \\{proto\_dependent} list,~\|p, in which at least one independent variable -appears. It equates this list to zero, by choosing an independent variable -with the largest coefficient and making it dependent on the others. The -newly dependent variable is eliminated from all current dependencies, -thereby possibly making other dependent variables known. - -The given list \|p is, of course, totally destroyed by all this processing. - -\Y\P\4\&{procedure}\1\ \37$\\{linear\_eq}(\|p:\\{pointer};\,\35\|t:\\{small% -\_number})$;\6 -\4\&{var} \37$\|q,\39\|r,\39\|s$: \37\\{pointer};\C{for link manipulation}\6 -\|x: \37\\{pointer};\C{the variable that loses its independence}\6 -\|n: \37\\{integer};\C{the number of times \|x had been halved}\6 -\|v: \37\\{integer};\C{the coefficient of \|x in list \|p}\6 -\\{prev\_r}: \37\\{pointer};\C{lags one step behind \|r}\6 -\\{final\_node}: \37\\{pointer};\C{the constant term of the new dependency -list}\6 -\|w: \37\\{integer};\C{a tentative coefficient}\2\6 -\&{begin} \37\X611:Find a node \|q in list \|p whose coefficient \|v is largest% -\X;\6 -$\|x\K\\{info}(\|q)$;\5 -$\|n\K\\{value}(\|x)\mathbin{\&{mod}}\\{s\_scale}$;\6 -\X612:Divide list \|p by $-\|v$, removing node \|q\X;\6 -\&{if} $\\{internal}[\\{tracing\_equations}]>0$ \1\&{then}\5 -\X613:Display the new dependency\X;\2\6 -\X614:Simplify all existing dependencies by substituting for \|x\X;\6 -\X615:Change variable \|x from \\{independent} to \\{dependent} or \\{known}\X;% -\6 -\&{if} $\\{fix\_needed}$ \1\&{then}\5 -\\{fix\_dependencies};\2\6 -\&{end};\par -\fi - -\M611. \P$\X611:Find a node \|q in list \|p whose coefficient \|v is largest\X% -\S$\6 -$\|q\K\|p$;\5 -$\|r\K\\{link}(\|p)$;\5 -$\|v\K\\{value}(\|q)$;\6 -\&{while} $\\{info}(\|r)\I\\{null}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{abs}(\\{value}(\|r))>\\{abs}(\|v)$ \1\&{then}\6 -\&{begin} \37$\|q\K\|r$;\5 -$\|v\K\\{value}(\|r)$;\6 -\&{end};\2\6 -$\|r\K\\{link}(\|r)$;\6 -\&{end}\2\par -\U610.\fi - -\M612. Here we want to change the coefficients from \\{scaled} to \\{fraction}, -except in the constant term. In the common case of a trivial equation -like `\.{x=3.14}', we will have $\|v=-\\{fraction\_one}$, $\|q=\|p$, and $\|t=% -\\{dependent}$. - -\Y\P$\4\X612:Divide list \|p by $-\|v$, removing node \|q\X\S$\6 -$\|s\K\\{temp\_head}$;\5 -$\\{link}(\|s)\K\|p$;\5 -$\|r\K\|p$;\6 -\1\&{repeat} \37\&{if} $\|r=\|q$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|s)\K\\{link}(\|r)$;\5 -$\\{free\_node}(\|r,\39\\{dep\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|w\K\\{make\_fraction}(\\{value}(\|r),\39\|v)$;\6 -\&{if} $\\{abs}(\|w)\L\\{half\_fraction\_threshold}$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|s)\K\\{link}(\|r)$;\5 -$\\{free\_node}(\|r,\39\\{dep\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{value}(\|r)\K-\|w$;\5 -$\|s\K\|r$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\|r\K\\{link}(\|s)$;\6 -\4\&{until}\5 -$\\{info}(\|r)=\\{null}$;\2\6 -\&{if} $\|t=\\{proto\_dependent}$ \1\&{then}\5 -$\\{value}(\|r)\K-\\{make\_scaled}(\\{value}(\|r),\39\|v)$\6 -\4\&{else} \&{if} $\|v\I-\\{fraction\_one}$ \1\&{then}\5 -$\\{value}(\|r)\K-\\{make\_fraction}(\\{value}(\|r),\39\|v)$;\2\2\6 -$\\{final\_node}\K\|r$;\5 -$\|p\K\\{link}(\\{temp\_head})$\par -\U610.\fi - -\M613. \P$\X613:Display the new dependency\X\S$\6 -\&{if} $\\{interesting}(\|x)$ \1\&{then}\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\#\#\ "})$;\5 -$\\{print\_variable\_name}(\|x)$;\5 -$\|w\K\|n$;\6 -\&{while} $\|w>0$ \1\&{do}\6 -\&{begin} \37$\\{print}(\.{"*4"})$;\5 -$\|w\K\|w-2$;\6 -\&{end};\2\6 -$\\{print\_char}(\.{"="})$;\5 -$\\{print\_dependency}(\|p,\39\\{dependent})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\2\par -\U610.\fi - -\M614. \P$\X614:Simplify all existing dependencies by substituting for \|x\X\S$% -\6 -$\\{prev\_r}\K\\{dep\_head}$;\5 -$\|r\K\\{link}(\\{dep\_head})$;\6 -\&{while} $\|r\I\\{dep\_head}$ \1\&{do}\6 -\&{begin} \37$\|s\K\\{dep\_list}(\|r)$;\5 -$\|q\K\\{p\_with\_x\_becoming\_q}(\|s,\39\|x,\39\|p,\39\\{type}(\|r))$;\6 -\&{if} $\\{info}(\|q)=\\{null}$ \1\&{then}\5 -$\\{make\_known}(\|r,\39\|q)$\6 -\4\&{else} \&{begin} \37$\\{dep\_list}(\|r)\K\|q$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\\{info}(\|q)=\\{null}$;\2\6 -$\\{prev\_r}\K\|q$;\6 -\&{end};\2\6 -$\|r\K\\{link}(\\{prev\_r})$;\6 -\&{end}\2\par -\U610.\fi - -\M615. \P$\X615:Change variable \|x from \\{independent} to \\{dependent} or % -\\{known}\X\S$\6 -\&{if} $\|n>0$ \1\&{then}\5 -\X616:Divide list \|p by $2^n$\X;\2\6 -\&{if} $\\{info}(\|p)=\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\|x)\K\\{known}$;\5 -$\\{value}(\|x)\K\\{value}(\|p)$;\6 -\&{if} $\\{abs}(\\{value}(\|x))\G\\{fraction\_one}$ \1\&{then}\5 -$\\{val\_too\_big}(\\{value}(\|x))$;\2\6 -$\\{free\_node}(\|p,\39\\{dep\_node\_size})$;\6 -\&{if} $\\{cur\_exp}=\|x$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\\{independent}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_exp}\K\\{value}(\|x)$;\5 -$\\{cur\_type}\K\\{known}$;\5 -$\\{free\_node}(\|x,\39\\{value\_node\_size})$;\6 -\&{end};\2\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{type}(\|x)\K\\{dependent}$;\5 -$\\{dep\_final}\K\\{final\_node}$;\5 -$\\{new\_dep}(\|x,\39\|p)$;\6 -\&{if} $\\{cur\_exp}=\|x$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\\{independent}$ \1\&{then}\5 -$\\{cur\_type}\K\\{dependent}$;\2\2\6 -\&{end}\2\par -\U610.\fi - -\M616. \P$\X616:Divide list \|p by $2^n$\X\S$\6 -\&{begin} \37$\|s\K\\{temp\_head}$;\5 -$\\{link}(\\{temp\_head})\K\|p$;\5 -$\|r\K\|p$;\6 -\1\&{repeat} \37\&{if} $\|n>30$ \1\&{then}\5 -$\|w\K0$\6 -\4\&{else} $\|w\K\\{value}(\|r)\mathbin{\&{div}}\\{two\_to\_the}[\|n]$;\2\6 -\&{if} $(\\{abs}(\|w)\L\\{half\_fraction\_threshold})\W(\\{info}(\|r)\I% -\\{null})$ \1\&{then}\6 -\&{begin} \37$\\{link}(\|s)\K\\{link}(\|r)$;\5 -$\\{free\_node}(\|r,\39\\{dep\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{value}(\|r)\K\|w$;\5 -$\|s\K\|r$;\6 -\&{end};\2\6 -$\|r\K\\{link}(\|s)$;\6 -\4\&{until}\5 -$\\{info}(\|s)=\\{null}$;\2\6 -$\|p\K\\{link}(\\{temp\_head})$;\6 -\&{end}\par -\U615.\fi - -\M617. The \\{check\_mem} procedure, which is used only when \MF\ is being -debugged, makes sure that the current dependency lists are well formed. - -\Y\P$\4\X617:Check the list of linear dependencies\X\S$\6 -$\|q\K\\{dep\_head}$;\5 -$\|p\K\\{link}(\|q)$;\6 -\&{while} $\|p\I\\{dep\_head}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{prev\_dep}(\|p)\I\|q$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"Bad\ PREVDEP\ at\ "})$;\5 -$\\{print\_int}(\|p)$;\6 -\&{end};\2\6 -$\|p\K\\{dep\_list}(\|p)$;\5 -$\|r\K\\{inf\_val}$;\6 -\1\&{repeat} \37\&{if} $\\{value}(\\{info}(\|p))\G\\{value}(\|r)$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"Out\ of\ order\ at\ "})$;\5 -$\\{print\_int}(\|p)$;\6 -\&{end};\2\6 -$\|r\K\\{info}(\|p)$;\5 -$\|q\K\|p$;\5 -$\|p\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\|r=\\{null}$;\2\6 -\&{end}\2\par -\U180.\fi - -\N618. \[29] Dynamic nonlinear equations. -Variables of numeric type are maintained by the general scheme of -independent, dependent, and known values that we have just studied; -and the components of pair and transform variables are handled in the -same way. But \MF\ also has five other types of values: \&{boolean}, -\&{string}, \&{pen}, \&{path}, and \&{picture}; what about them? - -Equations are allowed between nonlinear quantities, but only in a -simple form. Two variables that haven't yet been assigned values are -either equal to each other, or they're not. - -Before a boolean variable has received a value, its type is \\{unknown% -\_boolean}; -similarly, there are variables whose type is \\{unknown\_string}, \\{unknown% -\_pen}, -\\{unknown\_path}, and \\{unknown\_picture}. In such cases the value is either -\\{null} (which means that no other variables are equivalent to this one), or -it points to another variable of the same undefined type. The pointers in the -latter case form a cycle of nodes, which we shall call a ``ring.'' -Rings of undefined variables may include capsules, which arise as -intermediate results within expressions or as \&{expr} parameters to macros. - -When one member of a ring receives a value, the same value is given to -all the other members. In the case of paths and pictures, this implies -making separate copies of a potentially large data structure; users should -restrain their enthusiasm for such generality, unless they have lots and -lots of memory space. - -\fi - -\M619. The following procedure is called when a capsule node is being -added to a ring (e.g., when an unknown variable is mentioned in an expression). - -\Y\P\4\&{function}\1\ \37$\\{new\_ring\_entry}(\|p:\\{pointer})$: \37% -\\{pointer};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the new capsule node}\2\6 -\&{begin} \37$\|q\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{name\_type}(\|q)\K\\{capsule}$;\5 -$\\{type}(\|q)\K\\{type}(\|p)$;\6 -\&{if} $\\{value}(\|p)=\\{null}$ \1\&{then}\5 -$\\{value}(\|q)\K\|p$\ \&{else} $\\{value}(\|q)\K\\{value}(\|p)$;\2\6 -$\\{value}(\|p)\K\|q$;\5 -$\\{new\_ring\_entry}\K\|q$;\6 -\&{end};\par -\fi - -\M620. Conversely, we might delete a capsule or a variable before it becomes -known. -The following procedure simply detaches a quantity from its ring, -without recycling the storage. - -\Y\P$\4\X268:Declare the recycling subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{ring\_delete}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\2\6 -\&{begin} \37$\|q\K\\{value}(\|p)$;\6 -\&{if} $\|q\I\\{null}$ \1\&{then}\6 -\&{if} $\|q\I\|p$ \1\&{then}\6 -\&{begin} \37\&{while} $\\{value}(\|q)\I\|p$ \1\&{do}\5 -$\|q\K\\{value}(\|q)$;\2\6 -$\\{value}(\|q)\K\\{value}(\|p)$;\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M621. Eventually there might be an equation that assigns values to all of the -variables in a ring. The \\{nonlinear\_eq} subroutine does the necessary -propagation of values. - -If the parameter \\{flush\_p} is \\{true}, node \|p itself needn't receive a -value; it will soon be recycled. - -\Y\P\4\&{procedure}\1\ \37$\\{nonlinear\_eq}(\|v:\\{integer};\,\35\|p:% -\\{pointer};\,\35\\{flush\_p}:\\{boolean})$;\6 -\4\&{var} \37\|t: \37\\{small\_number};\C{the type of ring \|p}\6 -$\|q,\39\|r$: \37\\{pointer};\C{link manipulation registers}\2\6 -\&{begin} \37$\|t\K\\{type}(\|p)-\\{unknown\_tag}$;\5 -$\|q\K\\{value}(\|p)$;\6 -\&{if} $\\{flush\_p}$ \1\&{then}\5 -$\\{type}(\|p)\K\\{vacuous}$\ \&{else} $\|p\K\|q$;\2\6 -\1\&{repeat} \37$\|r\K\\{value}(\|q)$;\5 -$\\{type}(\|q)\K\|t$;\6 -\&{case} $\|t$ \1\&{of}\6 -\4\\{boolean\_type}: \37$\\{value}(\|q)\K\|v$;\6 -\4\\{string\_type}: \37\&{begin} \37$\\{value}(\|q)\K\|v$;\5 -$\\{add\_str\_ref}(\|v)$;\6 -\&{end};\6 -\4\\{pen\_type}: \37\&{begin} \37$\\{value}(\|q)\K\|v$;\5 -$\\{add\_pen\_ref}(\|v)$;\6 -\&{end};\6 -\4\\{path\_type}: \37$\\{value}(\|q)\K\\{copy\_path}(\|v)$;\6 -\4\\{picture\_type}: \37$\\{value}(\|q)\K\\{copy\_edges}(\|v)$;\2\6 -\&{end};\C{there ain't no more cases}\6 -$\|q\K\|r$;\6 -\4\&{until}\5 -$\|q=\|p$;\2\6 -\&{end};\par -\fi - -\M622. If two members of rings are equated, and if they have the same type, -the \\{ring\_merge} procedure is called on to make them equivalent. - -\Y\P\4\&{procedure}\1\ \37$\\{ring\_merge}(\|p,\39\|q:\\{pointer})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|r: \37\\{pointer};\C{traverses one list}\2\6 -\&{begin} \37$\|r\K\\{value}(\|p)$;\6 -\&{while} $\|r\I\|p$ \1\&{do}\6 -\&{begin} \37\&{if} $\|r=\|q$ \1\&{then}\6 -\&{begin} \37\X623:Exclaim about a redundant equation\X;\6 -\&{return};\6 -\&{end};\2\6 -$\|r\K\\{value}(\|r)$;\6 -\&{end};\2\6 -$\|r\K\\{value}(\|p)$;\5 -$\\{value}(\|p)\K\\{value}(\|q)$;\5 -$\\{value}(\|q)\K\|r$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M623. \P$\X623:Exclaim about a redundant equation\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Redundant\ equation"})$;\6 -$\\{help2}(\.{"I\ already\ knew\ that\ this\ equation\ was\ true."})$\6 -$(\.{"But\ perhaps\ no\ harm\ has\ been\ done;\ let\'s\ continue."})$;\6 -\\{put\_get\_error};\6 -\&{end}\par -\Us622, 1004\ETs1008.\fi - -\N624. \[30] Introduction to the syntactic routines. -Let's pause a moment now and try to look at the Big Picture. -The \MF\ program consists of three main parts: syntactic routines, -semantic routines, and output routines. The chief purpose of the -syntactic routines is to deliver the user's input to the semantic routines, -while parsing expressions and locating operators and operands. The -semantic routines act as an interpreter responding to these operators, -which may be regarded as commands. And the output routines are -periodically called on to produce compact font descriptions that can be -used for typesetting or for making interim proof drawings. We have -discussed the basic data structures and many of the details of semantic -operations, so we are good and ready to plunge into the part of \MF\ that -actually controls the activities. - -Our current goal is to come to grips with the \\{get\_next} procedure, -which is the keystone of \MF's input mechanism. Each call of \\{get\_next} -sets the value of three variables \\{cur\_cmd}, \\{cur\_mod}, and \\{cur\_sym}, -representing the next input token. -$$\vbox{\halign{#\hfil\cr -\hbox{\\{cur\_cmd} denotes a command code from the long list of codes -given earlier;}\cr -\hbox{\\{cur\_mod} denotes a modifier of the command code;}\cr -\hbox{\\{cur\_sym} is the hash address of the symbolic token that was -just scanned,}\cr -\hbox{\qquad or zero in the case of a numeric or string -or capsule token.}\cr}}$$ -Underlying this external behavior of \\{get\_next} is all the machinery -necessary to convert from character files to tokens. At a given time we -may be only partially finished with the reading of several files (for -which \&{input} was specified), and partially finished with the expansion -of some user-defined macros and/or some macro parameters, and partially -finished reading some text that the user has inserted online, -and so on. When reading a character file, the characters must be -converted to tokens; comments and blank spaces must -be removed, numeric and string tokens must be evaluated. - -To handle these situations, which might all be present simultaneously, -\MF\ uses various stacks that hold information about the incomplete -activities, and there is a finite state control for each level of the -input mechanism. These stacks record the current state of an implicitly -recursive process, but the \\{get\_next} procedure is not recursive. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{cur\_cmd}: \37\\{eight\_bits};\C{current command set by \\{get\_next}}\6 -\4\\{cur\_mod}: \37\\{integer};\C{operand of current command}\6 -\4\\{cur\_sym}: \37\\{halfword};\C{hash address of current symbol}\par -\fi - -\M625. The \\{print\_cmd\_mod} routine prints a symbolic interpretation of a -command code and its modifier. -It consists of a rather tedious sequence of print -commands, and most of it is essentially an inverse to the \\{primitive} -routine that enters a \MF\ primitive into \\{hash} and \\{eqtb}. Therefore -almost -all of this procedure appears elsewhere in the program, together with the -corresponding \\{primitive} calls. - -\Y\P$\4\X625:Declare the procedure called \\{print\_cmd\_mod}\X\S$\6 -\4\&{procedure}\1\ \37$\\{print\_cmd\_mod}(\|c,\39\|m:\\{integer})$;\2\6 -\&{begin} \37\&{case} $\|c$ \1\&{of}\6 -\hbox{\4}\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of primitives% -\X\6 -\4\&{othercases} \37$\\{print}(\.{"[unknown\ command\ code!]"})$\2\6 -\&{endcases};\6 -\&{end};\par -\U227.\fi - -\M626. Here is a procedure that displays a given command in braces, in the -user's transcript file. - -\Y\P\D \37$\\{show\_cur\_cmd\_mod}\S\\{show\_cmd\_mod}(\\{cur\_cmd},\39\\{cur% -\_mod})$\par -\Y\P\4\&{procedure}\1\ \37$\\{show\_cmd\_mod}(\|c,\39\|m:\\{integer})$;\2\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{"})$;\5 -$\\{print\_cmd\_mod}(\|c,\39\|m)$;\5 -$\\{print\_char}(\.{"\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end};\par -\fi - -\N627. \[31] Input stacks and states. -The state of \MF's input mechanism appears in the input stack, whose -entries are records with five fields, called \\{index}, \\{start}, \\{loc}, -\\{limit}, and \\{name}. The top element of this stack is maintained in a -global variable for which no subscripting needs to be done; the other -elements of the stack appear in an array. Hence the stack is declared thus: - -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{in\_state\_record}=$\1\5 -\1\&{record} \37\\{index\_field}: \37\\{quarterword};\6 -\4$\\{start\_field},\39\\{loc\_field},\39\\{limit\_field},\39\\{name\_field}$: % -\37\\{halfword};\2\6 -\&{end};\2\par -\fi - -\M628. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{input\_stack}: \37\&{array} $[0\to\\{stack\_size}]$ \1\&{of}\5 -\\{in\_state\_record};\2\6 -\4\\{input\_ptr}: \37$0\to\\{stack\_size}$;\C{first unused location of \\{input% -\_stack}}\6 -\4\\{max\_in\_stack}: \37$0\to\\{stack\_size}$;\C{largest value of \\{input% -\_ptr} when pushing}\6 -\4\\{cur\_input}: \37\\{in\_state\_record};\C{the ``top'' input state}\par -\fi - -\M629. We've already defined the special variable $\\{loc}\S\\{cur\_input}.% -\\{loc\_field}$ -in our discussion of basic input-output routines. The other components of -\\{cur\_input} are defined in the same way: - -\Y\P\D \37$\\{index}\S\\{cur\_input}.\\{index\_field}$\C{reference for buffer -information}\par -\P\D \37$\\{start}\S\\{cur\_input}.\\{start\_field}$\C{starting position in % -\\{buffer}}\par -\P\D \37$\\{limit}\S\\{cur\_input}.\\{limit\_field}$\C{end of current line in % -\\{buffer}}\par -\P\D \37$\\{name}\S\\{cur\_input}.\\{name\_field}$\C{name of the current file}% -\par -\fi - -\M630. Let's look more closely now at the five control variables -(\\{index},~\\{start},~\\{loc},~\\{limit},~\\{name}), -assuming that \MF\ is reading a line of characters that have been input -from some file or from the user's terminal. There is an array called -\\{buffer} that acts as a stack of all lines of characters that are -currently being read from files, including all lines on subsidiary -levels of the input stack that are not yet completed. \MF\ will return to -the other lines when it is finished with the present input file. - -(Incidentally, on a machine with byte-oriented addressing, it would be -appropriate to combine \\{buffer} with the \\{str\_pool} array, -letting the buffer entries grow downward from the top of the string pool -and checking that these two tables don't bump into each other.) - -The line we are currently working on begins in position \\{start} of the -buffer; the next character we are about to read is $\\{buffer}[\\{loc}]$; and -\\{limit} is the location of the last character present. We always have -$\\{loc}\L\\{limit}$. For convenience, $\\{buffer}[\\{limit}]$ has been set to % -\.{"\%"}, so -that the end of a line is easily sensed. - -The \\{name} variable is a string number that designates the name of -the current file, if we are reading a text file. It is 0 if we -are reading from the terminal for normal input, or 1 if we are executing a -\&{readstring} command, or 2 if we are reading a string that was -moved into the buffer by \&{scantokens}. - -\fi - -\M631. Additional information about the current line is available via the -\\{index} variable, which counts how many lines of characters are present -in the buffer below the current level. We have $\\{index}=0$ when reading -from the terminal and prompting the user for each line; then if the user types, -e.g., `\.{input font}', we will have $\\{index}=1$ while reading -the file \.{font.mf}. However, it does not follow that \\{index} is the -same as the input stack pointer, since many of the levels on the input -stack may come from token lists. - -The global variable \\{in\_open} is equal to the \\{index} -value of the highest non-token-list level. Thus, the number of partially read -lines in the buffer is $\\{in\_open}+1$, and we have $\\{in\_open}=\\{index}$ -when we are not reading a token list. - -If we are not currently reading from the terminal, -we are reading from the file variable $\\{input\_file}[\\{index}]$. We use -the notation \\{terminal\_input} as a convenient abbreviation for $\\{name}=0$, -and \\{cur\_file} as an abbreviation for $\\{input\_file}[\\{index}]$. - -The global variable \\{line} contains the line number in the topmost -open file, for use in error messages. If we are not reading from -the terminal, $\\{line\_stack}[\\{index}]$ holds the line number for the -enclosing level, so that \\{line} can be restored when the current -file has been read. - -If more information about the input state is needed, it can be -included in small arrays like those shown here. For example, -the current page or segment number in the input file might be -put into a variable \\{page}, maintained for enclosing levels in -`\ignorespaces \\{page\_stack}: \&{array} $[1\to\\{max\_in\_open}]$ \&{of} % -\\{integer}\unskip' -by analogy with \\{line\_stack}. - -\Y\P\D \37$\\{terminal\_input}\S(\\{name}=0)$\C{are we reading from the -terminal?}\par -\P\D \37$\\{cur\_file}\S\\{input\_file}[\\{index}]$\C{the current \\{alpha% -\_file} variable}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{in\_open}: \37$0\to\\{max\_in\_open}$;\C{the number of lines in the -buffer, less one}\6 -\4\\{open\_parens}: \37$0\to\\{max\_in\_open}$;\C{the number of open text -files}\6 -\4\\{input\_file}: \37\&{array} $[1\to\\{max\_in\_open}]$ \1\&{of}\5 -\\{alpha\_file};\2\6 -\4\\{line}: \37\\{integer};\C{current line number in the current source file}\6 -\4\\{line\_stack}: \37\&{array} $[1\to\\{max\_in\_open}]$ \1\&{of}\5 -\\{integer};\2\par -\fi - -\M632. However, all this discussion about input state really applies only to -the -case that we are inputting from a file. There is another important case, -namely when we are currently getting input from a token list. In this case -$\\{index}>\\{max\_in\_open}$, and the conventions about the other state -variables -are different: - -\yskip\hang\\{loc} is a pointer to the current node in the token list, i.e., -the node that will be read next. If $\\{loc}=\\{null}$, the token list has been -fully read. - -\yskip\hang\\{start} points to the first node of the token list; this node -may or may not contain a reference count, depending on the type of token -list involved. - -\yskip\hang\\{token\_type}, which takes the place of \\{index} in the -discussion above, is a code number that explains what kind of token list -is being scanned. - -\yskip\hang\\{name} points to the \\{eqtb} address of the control sequence -being expanded, if the current token list is a macro not defined by -\&{vardef}. Macros defined by \&{vardef} have $\\{name}=\\{null}$; their name -can be deduced by looking at their first two parameters. - -\yskip\hang\\{param\_start}, which takes the place of \\{limit}, tells where -the parameters of the current macro or loop text begin in the \\{param\_stack}. - -\yskip\noindent The \\{token\_type} can take several values, depending on -where the current token list came from: - -\yskip -\indent\\{forever\_text}, if the token list being scanned is the body of -a \&{forever} loop; - -\indent\\{loop\_text}, if the token list being scanned is the body of -a \&{for} or \&{forsuffixes} loop; - -\indent\\{parameter}, if a \&{text} or \&{suffix} parameter is being scanned; - -\indent\\{backed\_up}, if the token list being scanned has been inserted as -`to be read again'. - -\indent\\{inserted}, if the token list being scanned has been inserted as -part of error recovery; - -\indent\\{macro}, if the expansion of a user-defined symbolic token is being -scanned. - -\yskip\noindent -The token list begins with a reference count if and only if $\\{token\_type}=% -\\{macro}$. - -\Y\P\D \37$\\{token\_type}\S\\{index}$\C{type of current token list}\par -\P\D \37$\\{token\_state}\S(\\{index}>\\{max\_in\_open})$\C{are we scanning a -token list?}\par -\P\D \37$\\{file\_state}\S(\\{index}\L\\{max\_in\_open})$\C{are we scanning a -file line?}\par -\P\D \37$\\{param\_start}\S\\{limit}$\C{base of macro parameters in \\{param% -\_stack}}\par -\P\D \37$\\{forever\_text}=\\{max\_in\_open}+1$\C{\\{token\_type} code for loop -texts}\par -\P\D \37$\\{loop\_text}=\\{max\_in\_open}+2$\C{\\{token\_type} code for loop -texts}\par -\P\D \37$\\{parameter}=\\{max\_in\_open}+3$\C{\\{token\_type} code for -parameter texts}\par -\P\D \37$\\{backed\_up}=\\{max\_in\_open}+4$\C{\\{token\_type} code for texts -to be reread}\par -\P\D \37$\\{inserted}=\\{max\_in\_open}+5$\C{\\{token\_type} code for inserted -texts}\par -\P\D \37$\\{macro}=\\{max\_in\_open}+6$\C{\\{token\_type} code for macro -replacement texts}\par -\fi - -\M633. The \\{param\_stack} is an auxiliary array used to hold pointers to the -token -lists for parameters at the current level and subsidiary levels of input. -This stack grows at a different rate from the others. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{param\_stack}: \37\&{array} $[0\to\\{param\_size}]$ \1\&{of}\5 -\\{pointer};\C{token list pointers for parameters}\2\6 -\4\\{param\_ptr}: \37$0\to\\{param\_size}$;\C{first unused entry in \\{param% -\_stack}}\6 -\4\\{max\_param\_stack}: \37\\{integer};\C{largest value of \\{param\_ptr}}\par -\fi - -\M634. Thus, the ``current input state'' can be very complicated indeed; there -can be many levels and each level can arise in a variety of ways. The -\\{show\_context} procedure, which is used by \MF's error-reporting routine to -print out the current input state on all levels down to the most recent -line of characters from an input file, illustrates most of these conventions. -The global variable \\{file\_ptr} contains the lowest level that was -displayed by this procedure. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{file\_ptr}: \37$0\to\\{stack\_size}$;\C{shallowest level shown by \\{show% -\_context}}\par -\fi - -\M635. The status at each level is indicated by printing two lines, where the -first -line indicates what was read so far and the second line shows what remains -to be read. The context is cropped, if necessary, so that the first line -contains at most \\{half\_error\_line} characters, and the second contains -at most \\{error\_line}. Non-current input levels whose \\{token\_type} is -`\\{backed\_up}' are shown only if they have not been fully read. - -\Y\P\4\&{procedure}\1\ \37\\{show\_context};\C{prints where the scanner is}\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\\{old\_setting}: \37$0\to\\{max\_selector}$;\C{saved \\{selector} -setting}\6 -\X641:Local variables for formatting calculations\X\2\6 -\&{begin} \37$\\{file\_ptr}\K\\{input\_ptr}$;\5 -$\\{input\_stack}[\\{file\_ptr}]\K\\{cur\_input}$;\C{store current state}\6 -\~ \1\&{loop}\ \&{begin} \37$\\{cur\_input}\K\\{input\_stack}[\\{file\_ptr}]$;% -\C{enter into the context}\6 -\X636:Display the current context\X;\6 -\&{if} $\\{file\_state}$ \1\&{then}\6 -\&{if} $(\\{name}>2)\V(\\{file\_ptr}=0)$ \1\&{then}\5 -\&{goto} \37\\{done};\2\2\6 -$\\{decr}(\\{file\_ptr})$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{cur\_input}\K\\{input\_stack}[\\{input\_ptr}]$;\C{restore -original state}\6 -\&{end};\par -\fi - -\M636. \P$\X636:Display the current context\X\S$\6 -\&{if} $(\\{file\_ptr}=\\{input\_ptr})\V\\{file\_state}\V(\\{token\_type}\I% -\\{backed\_up})\V(\\{loc}\I\\{null})$ \1\&{then}\C{we omit backed-up token -lists that have already been read}\6 -\&{begin} \37$\\{tally}\K0$;\C{get ready to count characters}\6 -$\\{old\_setting}\K\\{selector}$;\6 -\&{if} $\\{file\_state}$ \1\&{then}\6 -\&{begin} \37\X637:Print location of current line\X;\6 -\X644:Pseudoprint the line\X;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\X638:Print type of token list\X;\6 -\X645:Pseudoprint the token list\X;\6 -\&{end};\2\6 -$\\{selector}\K\\{old\_setting}$;\C{stop pseudoprinting}\6 -\X643:Print two lines using the tricky pseudoprinted information\X;\6 -\&{end}\2\par -\U635.\fi - -\M637. This routine should be changed, if necessary, to give the best possible -indication of where the current line resides in the input file. -For example, on some systems it is best to print both a page and line number. - -\Y\P$\4\X637:Print location of current line\X\S$\6 -\&{if} $\\{name}\L1$ \1\&{then}\6 -\&{if} $\\{terminal\_input}\W(\\{file\_ptr}=0)$ \1\&{then}\5 -$\\{print\_nl}(\.{"<*>"})$\6 -\4\&{else} $\\{print\_nl}(\.{"<insert>"})$\2\6 -\4\&{else} \&{if} $\\{name}=2$ \1\&{then}\5 -$\\{print\_nl}(\.{"<scantokens>"})$\6 -\4\&{else} \&{begin} \37$\\{print\_nl}(\.{"l."})$;\5 -$\\{print\_int}(\\{line})$;\6 -\&{end};\2\2\6 -$\\{print\_char}(\.{"\ "})$\par -\U636.\fi - -\M638. \P$\X638:Print type of token list\X\S$\6 -\&{case} $\\{token\_type}$ \1\&{of}\6 -\4\\{forever\_text}: \37$\\{print\_nl}(\.{"<forever>\ "})$;\6 -\4\\{loop\_text}: \37\X639:Print the current loop value\X;\6 -\4\\{parameter}: \37$\\{print\_nl}(\.{"<argument>\ "})$;\6 -\4\\{backed\_up}: \37\&{if} $\\{loc}=\\{null}$ \1\&{then}\5 -$\\{print\_nl}(\.{"<recently\ read>\ "})$\6 -\4\&{else} $\\{print\_nl}(\.{"<to\ be\ read\ again>\ "})$;\2\6 -\4\\{inserted}: \37$\\{print\_nl}(\.{"<inserted\ text>\ "})$;\6 -\4\\{macro}: \37\&{begin} \37\\{print\_ln};\6 -\&{if} $\\{name}\I\\{null}$ \1\&{then}\5 -$\\{slow\_print}(\\{text}(\\{name}))$\6 -\4\&{else} \X640:Print the name of a \&{vardef}'d macro\X;\2\6 -$\\{print}(\.{"->"})$;\6 -\&{end};\6 -\4\&{othercases} \37$\\{print\_nl}(\.{"?"})$\C{this should never happen}\2\6 -\&{endcases}\par -\U636.\fi - -\M639. The parameter that corresponds to a loop text is either a token list -(in the case of \&{forsuffixes}) or a ``capsule'' (in the case of \&{for}). -We'll discuss capsules later; for now, all we need to know is that -the \\{link} field in a capsule parameter is \\{void} and that -$\\{print\_exp}(\|p,0)$ displays the value of capsule~\|p in abbreviated form. - -\Y\P$\4\X639:Print the current loop value\X\S$\6 -\&{begin} \37$\\{print\_nl}(\.{"<for("})$;\5 -$\|p\K\\{param\_stack}[\\{param\_start}]$;\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\6 -\&{if} $\\{link}(\|p)=\\{void}$ \1\&{then}\5 -$\\{print\_exp}(\|p,\390)$\C{we're in a \&{for} loop}\6 -\4\&{else} $\\{show\_token\_list}(\|p,\39\\{null},\3920,\39\\{tally})$;\2\2\6 -$\\{print}(\.{")>\ "})$;\6 -\&{end}\par -\U638.\fi - -\M640. The first two parameters of a macro defined by \&{vardef} will be token -lists representing the macro's prefix and ``at point.'' By putting these -together, we get the macro's full name. - -\Y\P$\4\X640:Print the name of a \&{vardef}'d macro\X\S$\6 -\&{begin} \37$\|p\K\\{param\_stack}[\\{param\_start}]$;\6 -\&{if} $\|p=\\{null}$ \1\&{then}\5 -$\\{show\_token\_list}(\\{param\_stack}[\\{param\_start}+1],\39\\{null},\3920,% -\39\\{tally})$\6 -\4\&{else} \&{begin} \37$\|q\K\|p$;\6 -\&{while} $\\{link}(\|q)\I\\{null}$ \1\&{do}\5 -$\|q\K\\{link}(\|q)$;\2\6 -$\\{link}(\|q)\K\\{param\_stack}[\\{param\_start}+1]$;\5 -$\\{show\_token\_list}(\|p,\39\\{null},\3920,\39\\{tally})$;\5 -$\\{link}(\|q)\K\\{null}$;\6 -\&{end};\2\6 -\&{end}\par -\U638.\fi - -\M641. Now it is necessary to explain a little trick. We don't want to store a -long -string that corresponds to a token list, because that string might take up -lots of memory; and we are printing during a time when an error message is -being given, so we dare not do anything that might overflow one of \MF's -tables. So `pseudoprinting' is the answer: We enter a mode of printing -that stores characters into a buffer of length \\{error\_line}, where character -$k+1$ is placed into \hbox{$\\{trick\_buf}[\|k\mathbin{\&{mod}}\\{error% -\_line}]$} if -$\|k<\\{trick\_count}$, otherwise character \|k is dropped. Initially we set -$\\{tally}\K0$ and $\\{trick\_count}\K1000000$; then when we reach the -point where transition from line 1 to line 2 should occur, we -set $\\{first\_count}\K\\{tally}$ and $\\{trick\_count}\K\hbox{max}(\\{error% -\_line},\\{tally}+1+\\{error\_line}-\\{half\_error\_line})$. At the end of the -pseudoprinting, the values of \\{first\_count}, \\{tally}, and -\\{trick\_count} give us all the information we need to print the two lines, -and all of the necessary text is in \\{trick\_buf}. - -Namely, let \|l be the length of the descriptive information that appears -on the first line. The length of the context information gathered for that -line is $\|k=\\{first\_count}$, and the length of the context information -gathered for line~2 is $m=\min(\\{tally}, \\{trick\_count})-k$. If $\|l+\|k\L% -\|h$, -where $\|h=\\{half\_error\_line}$, we print $\\{trick\_buf}[0\to\|k-1]$ after -the -descriptive information on line~1, and set $\|n\K\|l+\|k$; here \|n is the -length of line~1. If $l+k>h$, some cropping is necessary, so we set $\|n\K\|h$ -and print `\.{...}' followed by -$$\hbox{$\\{trick\_buf}[(\|l+\|k-\|h+3)\to\|k-1]$,}$$ -where subscripts of \\{trick\_buf} are circular modulo \\{error\_line}. The -second line consists of \|n~spaces followed by $\\{trick\_buf}[\|k\to(\|k+% -\|m-1)]$, -unless $\|n+\|m>\\{error\_line}$; in the latter case, further cropping is done. -This is easier to program than to explain. - -\Y\P$\4\X641:Local variables for formatting calculations\X\S$\6 -\4\|i: \37$0\to\\{buf\_size}$;\C{index into \\{buffer}}\6 -\4\|l: \37\\{integer};\C{length of descriptive information on line 1}\6 -\4\|m: \37\\{integer};\C{context information gathered for line 2}\6 -\4\|n: \37$0\to\\{error\_line}$;\C{length of line 1}\6 -\4\|p: \37\\{integer};\C{starting or ending place in \\{trick\_buf}}\6 -\4\|q: \37\\{integer};\C{temporary index}\par -\U635.\fi - -\M642. The following code tells the print routines to gather -the desired information. - -\Y\P\D \37$\\{begin\_pseudoprint}\S$\1\6 -\&{begin} \37$\|l\K\\{tally}$;\5 -$\\{tally}\K0$;\5 -$\\{selector}\K\\{pseudo}$;\5 -$\\{trick\_count}\K1000000$;\6 -\&{end}\2\par -\P\D \37$\\{set\_trick\_count}\S$\1\6 -\&{begin} \37$\\{first\_count}\K\\{tally}$;\5 -$\\{trick\_count}\K\\{tally}+1+\\{error\_line}-\\{half\_error\_line}$;\6 -\&{if} $\\{trick\_count}<\\{error\_line}$ \1\&{then}\5 -$\\{trick\_count}\K\\{error\_line}$;\2\6 -\&{end}\2\par -\fi - -\M643. And the following code uses the information after it has been gathered. - -\Y\P$\4\X643:Print two lines using the tricky pseudoprinted information\X\S$\6 -\&{if} $\\{trick\_count}=1000000$ \1\&{then}\5 -\\{set\_trick\_count};\C{\\{set\_trick\_count} must be performed}\2\6 -\&{if} $\\{tally}<\\{trick\_count}$ \1\&{then}\5 -$\|m\K\\{tally}-\\{first\_count}$\6 -\4\&{else} $\|m\K\\{trick\_count}-\\{first\_count}$;\C{context on line 2}\2\6 -\&{if} $\|l+\\{first\_count}\L\\{half\_error\_line}$ \1\&{then}\6 -\&{begin} \37$\|p\K0$;\5 -$\|n\K\|l+\\{first\_count}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print}(\.{"..."})$;\5 -$\|p\K\|l+\\{first\_count}-\\{half\_error\_line}+3$;\5 -$\|n\K\\{half\_error\_line}$;\6 -\&{end};\2\6 -\&{for} $\|q\K\|p\mathrel{\&{to}}\\{first\_count}-1$ \1\&{do}\5 -$\\{print\_char}(\\{trick\_buf}[\|q\mathbin{\&{mod}}\\{error\_line}])$;\2\6 -\\{print\_ln};\6 -\&{for} $\|q\K1\mathrel{\&{to}}\|n$ \1\&{do}\5 -$\\{print\_char}(\.{"\ "})$;\C{print \|n spaces to begin line~2}\2\6 -\&{if} $\|m+\|n\L\\{error\_line}$ \1\&{then}\5 -$\|p\K\\{first\_count}+\|m$\6 -\4\&{else} $\|p\K\\{first\_count}+(\\{error\_line}-\|n-3)$;\2\6 -\&{for} $\|q\K\\{first\_count}\mathrel{\&{to}}\|p-1$ \1\&{do}\5 -$\\{print\_char}(\\{trick\_buf}[\|q\mathbin{\&{mod}}\\{error\_line}])$;\2\6 -\&{if} $\|m+\|n>\\{error\_line}$ \1\&{then}\5 -$\\{print}(\.{"..."})$\2\par -\U636.\fi - -\M644. But the trick is distracting us from our current goal, which is to -understand the input state. So let's concentrate on the data structures that -are being pseudoprinted as we finish up the \\{show\_context} procedure. - -\Y\P$\4\X644:Pseudoprint the line\X\S$\6 -\\{begin\_pseudoprint};\6 -\&{if} $\\{limit}>0$ \1\&{then}\6 -\&{for} $\|i\K\\{start}\mathrel{\&{to}}\\{limit}-1$ \1\&{do}\6 -\&{begin} \37\&{if} $\|i=\\{loc}$ \1\&{then}\5 -\\{set\_trick\_count};\2\6 -$\\{print}(\\{buffer}[\|i])$;\6 -\&{end}\2\2\par -\U636.\fi - -\M645. \P$\X645:Pseudoprint the token list\X\S$\6 -\\{begin\_pseudoprint};\6 -\&{if} $\\{token\_type}\I\\{macro}$ \1\&{then}\5 -$\\{show\_token\_list}(\\{start},\39\\{loc},\39100000,\390)$\6 -\4\&{else} $\\{show\_macro}(\\{start},\39\\{loc},\39100000)$\2\par -\U636.\fi - -\M646. Here is the missing piece of \\{show\_token\_list} that is activated -when the -token beginning line~2 is about to be shown: - -\Y\P$\4\X646:Do magic computation\X\S$\6 -\\{set\_trick\_count}\par -\U217.\fi - -\N647. \[32] Maintaining the input stacks. -The following subroutines change the input status in commonly needed ways. - -First comes \\{push\_input}, which stores the current state and creates a -new level (having, initially, the same properties as the old). - -\Y\P\D \37$\\{push\_input}\S\hbox{}$\C{enter a new input level, save the old}\6 -\&{begin} \37\&{if} $\\{input\_ptr}>\\{max\_in\_stack}$ \1\&{then}\6 -\&{begin} \37$\\{max\_in\_stack}\K\\{input\_ptr}$;\6 -\&{if} $\\{input\_ptr}=\\{stack\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"input\ stack\ size"},\39\\{stack\_size})$;\2\6 -\&{end};\2\6 -$\\{input\_stack}[\\{input\_ptr}]\K\\{cur\_input}$;\C{stack the record}\6 -$\\{incr}(\\{input\_ptr})$;\6 -\&{end}\par -\fi - -\M648. And of course what goes up must come down. - -\Y\P\D \37$\\{pop\_input}\S\hbox{}$\C{leave an input level, re-enter the old}\6 -\&{begin} \37$\\{decr}(\\{input\_ptr})$;\5 -$\\{cur\_input}\K\\{input\_stack}[\\{input\_ptr}]$;\6 -\&{end}\par -\fi - -\M649. Here is a procedure that starts a new level of token-list input, given -a token list \|p and its type \|t. If $\|t=\\{macro}$, the calling routine -should -set \\{name}, reset~\\{loc}, and increase the macro's reference count. - -\Y\P\D \37$\\{back\_list}(\#)\S\\{begin\_token\_list}(\#,\39\\{backed\_up})$% -\C{backs up a simple token list}\par -\Y\P\4\&{procedure}\1\ \37$\\{begin\_token\_list}(\|p:\\{pointer};\,\35\|t:% -\\{quarterword})$;\2\6 -\&{begin} \37\\{push\_input};\5 -$\\{start}\K\|p$;\5 -$\\{token\_type}\K\|t$;\5 -$\\{param\_start}\K\\{param\_ptr}$;\5 -$\\{loc}\K\|p$;\6 -\&{end};\par -\fi - -\M650. When a token list has been fully scanned, the following computations -should be done as we leave that level of input. - -\Y\P\4\&{procedure}\1\ \37\\{end\_token\_list};\C{leave a token-list input -level}\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\\{token\_type}\G\\{backed\_up}$ \1\&{then}\C{token list -to be deleted}\6 -\&{if} $\\{token\_type}\L\\{inserted}$ \1\&{then}\6 -\&{begin} \37$\\{flush\_token\_list}(\\{start})$;\5 -\&{goto} \37\\{done};\6 -\&{end}\6 -\4\&{else} $\\{delete\_mac\_ref}(\\{start})$;\C{update reference count}\2\2\6 -\&{while} $\\{param\_ptr}>\\{param\_start}$ \1\&{do}\C{parameters must be -flushed}\6 -\&{begin} \37$\\{decr}(\\{param\_ptr})$;\5 -$\|p\K\\{param\_stack}[\\{param\_ptr}]$;\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\6 -\&{if} $\\{link}(\|p)=\\{void}$ \1\&{then}\C{it's an \&{expr} parameter}\6 -\&{begin} \37$\\{recycle\_value}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end}\6 -\4\&{else} $\\{flush\_token\_list}(\|p)$;\C{it's a \&{suffix} or \&{text} -parameter}\2\2\6 -\&{end};\2\6 -\4\\{done}: \37\\{pop\_input};\5 -\\{check\_interrupt};\6 -\&{end};\par -\fi - -\M651. The contents of $\\{cur\_cmd},\\{cur\_mod},\\{cur\_sym}$ are placed into -an equivalent -token by the \\{cur\_tok} routine. - -\Y\P\hbox{\4}\X855:Declare the procedure called \\{make\_exp\_copy}\X\6 -\4\&{function}\1\ \37\\{cur\_tok}: \37\\{pointer};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{a new token node}\6 -\\{save\_type}: \37\\{small\_number};\C{\\{cur\_type} to be restored}\6 -\\{save\_exp}: \37\\{integer};\C{\\{cur\_exp} to be restored}\2\6 -\&{begin} \37\&{if} $\\{cur\_sym}=0$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}=\\{capsule\_token}$ \1\&{then}\6 -\&{begin} \37$\\{save\_type}\K\\{cur\_type}$;\5 -$\\{save\_exp}\K\\{cur\_exp}$;\5 -$\\{make\_exp\_copy}(\\{cur\_mod})$;\5 -$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{link}(\|p)\K\\{null}$;\5 -$\\{cur\_type}\K\\{save\_type}$;\5 -$\\{cur\_exp}\K\\{save\_exp}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|p\K\\{get\_node}(\\{token\_node\_size})$;\5 -$\\{value}(\|p)\K\\{cur\_mod}$;\5 -$\\{name\_type}(\|p)\K\\{token}$;\6 -\&{if} $\\{cur\_cmd}=\\{numeric\_token}$ \1\&{then}\5 -$\\{type}(\|p)\K\\{known}$\6 -\4\&{else} $\\{type}(\|p)\K\\{string\_type}$;\2\6 -\&{end}\2\6 -\4\&{else} \&{begin} \37$\\{fast\_get\_avail}(\|p)$;\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\6 -\&{end};\2\6 -$\\{cur\_tok}\K\|p$;\6 -\&{end};\par -\fi - -\M652. Sometimes \MF\ has read too far and wants to ``unscan'' what it has -seen. The \\{back\_input} procedure takes care of this by putting the token -just scanned back into the input stream, ready to be read again. -If $\\{cur\_sym}\I0$, the values of \\{cur\_cmd} and \\{cur\_mod} are -irrelevant. - -\Y\P\4\&{procedure}\1\ \37\\{back\_input};\C{undoes one token of input}\6 -\4\&{var} \37\|p: \37\\{pointer};\C{a token list of length one}\2\6 -\&{begin} \37$\|p\K\\{cur\_tok}$;\6 -\&{while} $\\{token\_state}\W(\\{loc}=\\{null})$ \1\&{do}\5 -\\{end\_token\_list};\C{conserve stack space}\2\6 -$\\{back\_list}(\|p)$;\6 -\&{end};\par -\fi - -\M653. The \\{back\_error} routine is used when we want to restore or replace -an -offending token just before issuing an error message. We disable interrupts -during the call of \\{back\_input} so that the help message won't be lost. - -\Y\P\4\&{procedure}\1\ \37\\{back\_error};\C{back up one token and call % -\\{error}}\2\6 -\&{begin} \37$\\{OK\_to\_interrupt}\K\\{false}$;\5 -\\{back\_input};\5 -$\\{OK\_to\_interrupt}\K\\{true}$;\5 -\\{error};\6 -\&{end};\7 -\4\&{procedure}\1\ \37\\{ins\_error};\C{back up one inserted token and call % -\\{error}}\2\6 -\&{begin} \37$\\{OK\_to\_interrupt}\K\\{false}$;\5 -\\{back\_input};\5 -$\\{token\_type}\K\\{inserted}$;\5 -$\\{OK\_to\_interrupt}\K\\{true}$;\5 -\\{error};\6 -\&{end};\par -\fi - -\M654. The \\{begin\_file\_reading} procedure starts a new level of input for -lines -of characters to be read from a file, or as an insertion from the -terminal. It does not take care of opening the file, nor does it set \\{loc} -or \\{limit} or \\{line}. - -\Y\P\4\&{procedure}\1\ \37\\{begin\_file\_reading};\2\6 -\&{begin} \37\&{if} $\\{in\_open}=\\{max\_in\_open}$ \1\&{then}\5 -$\\{overflow}(\.{"text\ input\ levels"},\39\\{max\_in\_open})$;\2\6 -\&{if} $\\{first}=\\{buf\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"buffer\ size"},\39\\{buf\_size})$;\2\6 -$\\{incr}(\\{in\_open})$;\5 -\\{push\_input};\5 -$\\{index}\K\\{in\_open}$;\5 -$\\{line\_stack}[\\{index}]\K\\{line}$;\5 -$\\{start}\K\\{first}$;\5 -$\\{name}\K0$;\C{\\{terminal\_input} is now \\{true}}\6 -\&{end};\par -\fi - -\M655. Conversely, the variables must be downdated when such a level of input -is finished: - -\Y\P\4\&{procedure}\1\ \37\\{end\_file\_reading};\2\6 -\&{begin} \37$\\{first}\K\\{start}$;\5 -$\\{line}\K\\{line\_stack}[\\{index}]$;\6 -\&{if} $\\{index}\I\\{in\_open}$ \1\&{then}\5 -$\\{confusion}(\.{"endinput"})$;\2\6 -\&{if} $\\{name}>2$ \1\&{then}\5 -$\\{a\_close}(\\{cur\_file})$;\C{forget it}\2\6 -\\{pop\_input};\5 -$\\{decr}(\\{in\_open})$;\6 -\&{end};\par -\fi - -\M656. In order to keep the stack from overflowing during a long sequence of -inserted `\.{show}' commands, the following routine removes completed -error-inserted lines from memory. - -\Y\P\4\&{procedure}\1\ \37\\{clear\_for\_error\_prompt};\2\6 -\&{begin} \37\&{while} $\\{file\_state}\W\\{terminal\_input}\W\30(\\{input% -\_ptr}>0)\W(\\{loc}=\\{limit})$ \1\&{do}\5 -\\{end\_file\_reading};\2\6 -\\{print\_ln};\5 -\\{clear\_terminal};\6 -\&{end};\par -\fi - -\M657. To get \MF's whole input mechanism going, we perform the following -actions. - -\Y\P$\4\X657:Initialize the input routines\X\S$\6 -\&{begin} \37$\\{input\_ptr}\K0$;\5 -$\\{max\_in\_stack}\K0$;\5 -$\\{in\_open}\K0$;\5 -$\\{open\_parens}\K0$;\5 -$\\{max\_buf\_stack}\K0$;\5 -$\\{param\_ptr}\K0$;\5 -$\\{max\_param\_stack}\K0$;\5 -$\\{first}\K1$;\5 -$\\{start}\K1$;\5 -$\\{index}\K0$;\5 -$\\{line}\K0$;\5 -$\\{name}\K0$;\5 -$\\{force\_eof}\K\\{false}$;\6 -\&{if} $\R\\{init\_terminal}$ \1\&{then}\5 -\&{goto} \37\\{final\_end};\2\6 -$\\{limit}\K\\{last}$;\5 -$\\{first}\K\\{last}+1$;\C{\\{init\_terminal} has set \\{loc} and \\{last}}\6 -\&{end};\par -\A660. -\U1211.\fi - -\N658. \[33] Getting the next token. -The heart of \MF's input mechanism is the \\{get\_next} procedure, which -we shall develop in the next few sections of the program. Perhaps we -shouldn't actually call it the ``heart,'' however; it really acts as \MF's -eyes and mouth, reading the source files and gobbling them up. And it also -helps \MF\ to regurgitate stored token lists that are to be processed again. - -The main duty of \\{get\_next} is to input one token and to set \\{cur\_cmd} -and \\{cur\_mod} to that token's command code and modifier. Furthermore, if -the input token is a symbolic token, that token's \\{hash} address -is stored in \\{cur\_sym}; otherwise \\{cur\_sym} is set to zero. - -Underlying this simple description is a certain amount of complexity -because of all the cases that need to be handled. -However, the inner loop of \\{get\_next} is reasonably short and fast. - -\fi - -\M659. Before getting into \\{get\_next}, we need to consider a mechanism by -which -\MF\ helps keep errors from propagating too far. Whenever the program goes -into a mode where it keeps calling \\{get\_next} repeatedly until a certain -condition is met, it sets \\{scanner\_status} to some value other than % -\\{normal}. -Then if an input file ends, or if an `\&{outer}' symbol appears, -an appropriate error recovery will be possible. - -The global variable \\{warning\_info} helps in this error recovery by providing -additional information. For example, \\{warning\_info} might indicate the -name of a macro whose replacement text is being scanned. - -\Y\P\D \37$\\{normal}=0$\C{\\{scanner\_status} at ``quiet times''}\par -\P\D \37$\\{skipping}=1$\C{\\{scanner\_status} when false conditional text is -being skipped}\par -\P\D \37$\\{flushing}=2$\C{\\{scanner\_status} when junk after a statement is -being ignored}\par -\P\D \37$\\{absorbing}=3$\C{\\{scanner\_status} when a \&{text} parameter is -being scanned}\par -\P\D \37$\\{var\_defining}=4$\C{\\{scanner\_status} when a \&{vardef} is being -scanned}\par -\P\D \37$\\{op\_defining}=5$\C{\\{scanner\_status} when a macro \&{def} is -being scanned}\par -\P\D \37$\\{loop\_defining}=6$\C{\\{scanner\_status} when a \&{for} loop is -being scanned}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{scanner\_status}: \37$\\{normal}\to\\{loop\_defining}$;\C{are we scanning -at high speed?}\6 -\4\\{warning\_info}: \37\\{integer};\C{if so, what else do we need to know, -in case an error occurs?}\par -\fi - -\M660. \P$\X657:Initialize the input routines\X\mathrel{+}\S$\6 -$\\{scanner\_status}\K\\{normal}$;\par -\fi - -\M661. The following subroutine -is called when an `\&{outer}' symbolic token has been scanned or -when the end of a file has been reached. These two cases are distinguished -by \\{cur\_sym}, which is zero at the end of a file. - -\Y\P\4\&{function}\1\ \37\\{check\_outer\_validity}: \37\\{boolean};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{points to inserted token list}\2\6 -\&{begin} \37\&{if} $\\{scanner\_status}=\\{normal}$ \1\&{then}\5 -$\\{check\_outer\_validity}\K\\{true}$\6 -\4\&{else} \&{begin} \37$\\{deletions\_allowed}\K\\{false}$;\5 -\X662:Back up an outer symbolic token so that it can be reread\X;\6 -\&{if} $\\{scanner\_status}>\\{skipping}$ \1\&{then}\5 -\X663:Tell the user what has run away and try to recover\X\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Incomplete\ if;\ all\ text\ was\ -ignored\ after\ line\ "})$;\5 -$\\{print\_int}(\\{warning\_info})$;\6 -$\\{help3}(\.{"A\ forbidden\ \`outer\'\ token\ occurred\ in\ skipped\ text."})$% -\6 -$(\.{"This\ kind\ of\ error\ happens\ when\ you\ say\ \`if...\'\ and\ -forget"})$\6 -$(\.{"the\ matching\ \`fi\'.\ I\'ve\ inserted\ a\ \`fi\';\ this\ might\ -work."})$;\6 -\&{if} $\\{cur\_sym}=0$ \1\&{then}\5 -$\\{help\_line}[2]\K\30\.{"The\ file\ ended\ while\ I\ was\ skipping\ -conditional\ text."}$;\2\6 -$\\{cur\_sym}\K\\{frozen\_fi}$;\5 -\\{ins\_error};\6 -\&{end};\2\6 -$\\{deletions\_allowed}\K\\{true}$;\5 -$\\{check\_outer\_validity}\K\\{false}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M662. \P$\X662:Back up an outer symbolic token so that it can be reread\X\S$\6 -\&{if} $\\{cur\_sym}\I0$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{get\_avail}$;\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\5 -$\\{back\_list}(\|p)$;\C{prepare to read the symbolic token again}\6 -\&{end}\2\par -\U661.\fi - -\M663. \P$\X663:Tell the user what has run away and try to recover\X\S$\6 -\&{begin} \37\\{runaway};\C{print the definition-so-far}\6 -\&{if} $\\{cur\_sym}=0$ \1\&{then}\5 -$\\{print\_err}(\.{"File\ ended"})$\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Forbidden\ token\ found"})$;\6 -\&{end};\2\6 -$\\{print}(\.{"\ while\ scanning\ "})$;\5 -$\\{help4}(\.{"I\ suspect\ you\ have\ forgotten\ an\ \`enddef\',"})$\6 -$(\.{"causing\ me\ to\ read\ past\ where\ you\ wanted\ me\ to\ stop."})$\6 -$(\.{"I\'ll\ try\ to\ recover;\ but\ if\ the\ error\ is\ serious,"})$\6 -$(\.{"you\'d\ better\ type\ \`E\'\ or\ \`X\'\ now\ and\ fix\ your\ file."})$;\6 -\&{case} $\\{scanner\_status}$ \1\&{of}\6 -\hbox{\4}\X664:Complete the error message, and set \\{cur\_sym} to a token that -might help recover from the error\X\2\6 -\&{end};\C{there are no other cases}\6 -\\{ins\_error};\6 -\&{end}\par -\U661.\fi - -\M664. As we consider various kinds of errors, it is also appropriate to -change the first line of the help message just given; $\\{help\_line}[3]$ -points to the string that might be changed. - -\Y\P$\4\X664:Complete the error message, and set \\{cur\_sym} to a token that -might help recover from the error\X\S$\6 -\4\\{flushing}: \37\&{begin} \37$\\{print}(\.{"to\ the\ end\ of\ the\ -statement"})$;\5 -$\\{help\_line}[3]\K\.{"A\ previous\ error\ seems\ to\ have\ propagated,"}$;\5 -$\\{cur\_sym}\K\\{frozen\_semicolon}$;\6 -\&{end};\6 -\4\\{absorbing}: \37\&{begin} \37$\\{print}(\.{"a\ text\ argument"})$;\5 -$\\{help\_line}[3]\K\.{"It\ seems\ that\ a\ right\ delimiter\ was\ left\ -out,"}$;\6 -\&{if} $\\{warning\_info}=0$ \1\&{then}\5 -$\\{cur\_sym}\K\\{frozen\_end\_group}$\6 -\4\&{else} \&{begin} \37$\\{cur\_sym}\K\\{frozen\_right\_delimiter}$;\5 -$\\{equiv}(\\{frozen\_right\_delimiter})\K\\{warning\_info}$;\6 -\&{end};\2\6 -\&{end};\6 -\4$\\{var\_defining},\39\\{op\_defining}$: \37\&{begin} \37$\\{print}(\.{"the\ -definition\ of\ "})$;\6 -\&{if} $\\{scanner\_status}=\\{op\_defining}$ \1\&{then}\5 -$\\{slow\_print}(\\{text}(\\{warning\_info}))$\6 -\4\&{else} $\\{print\_variable\_name}(\\{warning\_info})$;\2\6 -$\\{cur\_sym}\K\\{frozen\_end\_def}$;\6 -\&{end};\6 -\4\\{loop\_defining}: \37\&{begin} \37$\\{print}(\.{"the\ text\ of\ a\ "})$;\5 -$\\{slow\_print}(\\{text}(\\{warning\_info}))$;\5 -$\\{print}(\.{"\ loop"})$;\5 -$\\{help\_line}[3]\K\.{"I\ suspect\ you\ have\ forgotten\ an\ \`endfor\',"}$;\5 -$\\{cur\_sym}\K\\{frozen\_end\_for}$;\6 -\&{end};\par -\U663.\fi - -\M665. The \\{runaway} procedure displays the first part of the text that -occurred -when \MF\ began its special \\{scanner\_status}, if that text has been saved. - -\Y\P$\4\X665:Declare the procedure called \\{runaway}\X\S$\6 -\4\&{procedure}\1\ \37\\{runaway};\2\6 -\&{begin} \37\&{if} $\\{scanner\_status}>\\{flushing}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"Runaway\ "})$;\6 -\&{case} $\\{scanner\_status}$ \1\&{of}\6 -\4\\{absorbing}: \37$\\{print}(\.{"text?"})$;\6 -\4$\\{var\_defining},\39\\{op\_defining}$: \37$\\{print}(\.{"definition?"})$;\6 -\4\\{loop\_defining}: \37$\\{print}(\.{"loop?"})$;\2\6 -\&{end};\C{there are no other cases}\6 -\\{print\_ln};\5 -$\\{show\_token\_list}(\\{link}(\\{hold\_head}),\39\\{null},\39\\{error% -\_line}-10,\390)$;\6 -\&{end};\2\6 -\&{end};\par -\U162.\fi - -\M666. We need to mention a procedure that may be called by \\{get\_next}. - -\Y\P\4\&{procedure}\1\ \37\\{firm\_up\_the\_line};\5 -\\{forward};\par -\fi - -\M667. And now we're ready to take the plunge into \\{get\_next} itself. - -\Y\P\D \37$\\{switch}=25$\C{a label in \\{get\_next}}\par -\P\D \37$\\{start\_numeric\_token}=85$\C{another}\par -\P\D \37$\\{start\_decimal\_token}=86$\C{and another}\par -\P\D \37$\\{fin\_numeric\_token}=87$\C{and still another, although \&{goto} is -considered harmful}\par -\Y\P\4\&{procedure}\1\ \37\\{get\_next};\C{sets \\{cur\_cmd}, \\{cur\_mod}, % -\\{cur\_sym} to next token}\6 -\4\&{label} \37$\\{restart},\39$\C{go here to get the next input token}\6 -$\\{exit},\39$\C{go here when the next input token has been got}\6 -$\\{found},\39$\C{go here when the end of a symbolic token has been found}\6 -$\\{switch},\39$\C{go here to branch on the class of an input character}\6 -$\\{start\_numeric\_token},\39\\{start\_decimal\_token},\39\\{fin\_numeric% -\_token},\39\\{done}$;\C{go here at crucial stages when scanning a number}\6 -\4\&{var} \37\|k: \37$0\to\\{buf\_size}$;\C{an index into \\{buffer}}\6 -\|c: \37\\{ASCII\_code};\C{the current character in the buffer}\6 -\\{class}: \37\\{ASCII\_code};\C{its class number}\6 -$\|n,\39\|f$: \37\\{integer};\C{registers for decimal-to-binary conversion}\2\6 -\&{begin} \37\\{restart}: \37$\\{cur\_sym}\K0$;\6 -\&{if} $\\{file\_state}$ \1\&{then}\5 -\X669:Input from external file; \&{goto} \\{restart} if no input found, or % -\&{return} if a non-symbolic token is found\X\6 -\4\&{else} \X676:Input from token list; \&{goto} \\{restart} if end of list or -if a parameter needs to be expanded, or \&{return} if a non-symbolic token is -found\X;\2\6 -\X668:Finish getting the symbolic token in \\{cur\_sym}; \&{goto} \\{restart} -if it is illegal\X;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M668. When a symbolic token is declared to be `\&{outer}', its command code -is increased by \\{outer\_tag}. - -\Y\P$\4\X668:Finish getting the symbolic token in \\{cur\_sym}; \&{goto} % -\\{restart} if it is illegal\X\S$\6 -$\\{cur\_cmd}\K\\{eq\_type}(\\{cur\_sym})$;\5 -$\\{cur\_mod}\K\\{equiv}(\\{cur\_sym})$;\6 -\&{if} $\\{cur\_cmd}\G\\{outer\_tag}$ \1\&{then}\6 -\&{if} $\\{check\_outer\_validity}$ \1\&{then}\5 -$\\{cur\_cmd}\K\\{cur\_cmd}-\\{outer\_tag}$\6 -\4\&{else} \&{goto} \37\\{restart}\2\2\par -\U667.\fi - -\M669. A percent sign appears in $\\{buffer}[\\{limit}]$; this makes it -unnecessary -to have a special test for end-of-line. - -\Y\P$\4\X669:Input from external file; \&{goto} \\{restart} if no input found, -or \&{return} if a non-symbolic token is found\X\S$\6 -\&{begin} \37\\{switch}: \37$\|c\K\\{buffer}[\\{loc}]$;\5 -$\\{incr}(\\{loc})$;\5 -$\\{class}\K\\{char\_class}[\|c]$;\6 -\&{case} $\\{class}$ \1\&{of}\6 -\4\\{digit\_class}: \37\&{goto} \37\\{start\_numeric\_token};\6 -\4\\{period\_class}: \37\&{begin} \37$\\{class}\K\\{char\_class}[\\{buffer}[% -\\{loc}]]$;\6 -\&{if} $\\{class}>\\{period\_class}$ \1\&{then}\5 -\&{goto} \37\\{switch}\6 -\4\&{else} \&{if} $\\{class}<\\{period\_class}$ \1\&{then}\C{$\\{class}=% -\\{digit\_class}$}\6 -\&{begin} \37$\|n\K0$;\5 -\&{goto} \37\\{start\_decimal\_token};\6 -\&{end};\2\2\6 -\&{end};\6 -\4\\{space\_class}: \37\&{goto} \37\\{switch};\6 -\4\\{percent\_class}: \37\&{begin} \37\X679:Move to next line of file, or % -\&{goto} \\{restart} if there is no next line\X;\6 -\\{check\_interrupt};\5 -\&{goto} \37\\{switch};\6 -\&{end};\6 -\4\\{string\_class}: \37\X671:Get a string token and \&{return}\X;\6 -\4\\{isolated\_classes}: \37\&{begin} \37$\|k\K\\{loc}-1$;\5 -\&{goto} \37\\{found};\6 -\&{end};\6 -\4\\{invalid\_class}: \37\X670:Decry the invalid character and \&{goto} % -\\{restart}\X;\6 -\4\&{othercases} \37\\{do\_nothing}\C{letters, etc.}\2\6 -\&{endcases};\6 -$\|k\K\\{loc}-1$;\6 -\&{while} $\\{char\_class}[\\{buffer}[\\{loc}]]=\\{class}$ \1\&{do}\5 -$\\{incr}(\\{loc})$;\2\6 -\&{goto} \37\\{found};\6 -\4\\{start\_numeric\_token}: \37\X673:Get the integer part \|n of a numeric -token; set $\|f\K0$ and \&{goto} \\{fin\_numeric\_token} if there is no decimal -point\X;\6 -\4\\{start\_decimal\_token}: \37\X674:Get the fraction part \|f of a numeric -token\X;\6 -\4\\{fin\_numeric\_token}: \37\X675:Pack the numeric and fraction parts of a -numeric token and \&{return}\X;\6 -\4\\{found}: \37$\\{cur\_sym}\K\\{id\_lookup}(\|k,\39\\{loc}-\|k)$;\6 -\&{end}\par -\U667.\fi - -\M670. We go to \\{restart} instead of to \\{switch}, because \\{state} might -equal -\\{token\_list} after the error has been dealt with -(cf.\ \\{clear\_for\_error\_prompt}). - -\Y\P$\4\X670:Decry the invalid character and \&{goto} \\{restart}\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Text\ line\ contains\ an\ invalid\ -character"})$;\5 -$\\{help2}(\.{"A\ funny\ symbol\ that\ I\ can\'t\ read\ has\ just\ been\ -input."})$\6 -$(\.{"Continue,\ and\ I\'ll\ forget\ that\ it\ ever\ happened."})$;\6 -$\\{deletions\_allowed}\K\\{false}$;\5 -\\{error};\5 -$\\{deletions\_allowed}\K\\{true}$;\5 -\&{goto} \37\\{restart};\6 -\&{end}\par -\U669.\fi - -\M671. \P$\X671:Get a string token and \&{return}\X\S$\6 -\&{begin} \37\&{if} $\\{buffer}[\\{loc}]=\.{""}\.{""}$ \1\&{then}\5 -$\\{cur\_mod}\K\.{""}$\6 -\4\&{else} \&{begin} \37$\|k\K\\{loc}$;\5 -$\\{buffer}[\\{limit}+1]\K\.{""}\.{""}$;\6 -\1\&{repeat} \37$\\{incr}(\\{loc})$;\6 -\4\&{until}\5 -$\\{buffer}[\\{loc}]=\.{""}\.{""}$;\2\6 -\&{if} $\\{loc}>\\{limit}$ \1\&{then}\5 -\X672:Decry the missing string delimiter and \&{goto} \\{restart}\X;\2\6 -\&{if} $(\\{loc}=\|k+1)\W(\\{length}(\\{buffer}[\|k])=1)$ \1\&{then}\5 -$\\{cur\_mod}\K\\{buffer}[\|k]$\6 -\4\&{else} \&{begin} \37$\\{str\_room}(\\{loc}-\|k)$;\6 -\1\&{repeat} \37$\\{append\_char}(\\{buffer}[\|k])$;\5 -$\\{incr}(\|k)$;\6 -\4\&{until}\5 -$\|k=\\{loc}$;\2\6 -$\\{cur\_mod}\K\\{make\_string}$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\\{incr}(\\{loc})$;\5 -$\\{cur\_cmd}\K\\{string\_token}$;\5 -\&{return};\6 -\&{end}\par -\U669.\fi - -\M672. We go to \\{restart} after this error message, not to \\{switch}, -because the \\{clear\_for\_error\_prompt} routine might have reinstated -\\{token\_state} after \\{error} has finished. - -\Y\P$\4\X672:Decry the missing string delimiter and \&{goto} \\{restart}\X\S$\6 -\&{begin} \37$\\{loc}\K\\{limit}$;\C{the next character to be read on this line -will be \.{"\%"}}\6 -$\\{print\_err}(\.{"Incomplete\ string\ token\ has\ been\ flushed"})$;\5 -$\\{help3}(\.{"Strings\ should\ finish\ on\ the\ same\ line\ as\ they\ -began."})$\6 -$(\.{"I\'ve\ deleted\ the\ partial\ string;\ you\ might\ want\ to"})$\6 -$(\.{"insert\ another\ by\ typing,\ e.g.,\ \`I"}\.{"new\ string"}\.{"\'."})$;\6 -$\\{deletions\_allowed}\K\\{false}$;\5 -\\{error};\5 -$\\{deletions\_allowed}\K\\{true}$;\5 -\&{goto} \37\\{restart};\6 -\&{end}\par -\U671.\fi - -\M673. \P$\X673:Get the integer part \|n of a numeric token; set $\|f\K0$ and % -\&{goto} \\{fin\_numeric\_token} if there is no decimal point\X\S$\6 -$\|n\K\|c-\.{"0"}$;\6 -\&{while} $\\{char\_class}[\\{buffer}[\\{loc}]]=\\{digit\_class}$ \1\&{do}\6 -\&{begin} \37\&{if} $\|n<4096$ \1\&{then}\5 -$\|n\K10\ast\|n+\\{buffer}[\\{loc}]-\.{"0"}$;\2\6 -$\\{incr}(\\{loc})$;\6 -\&{end};\2\6 -\&{if} $\\{buffer}[\\{loc}]=\.{"."}$ \1\&{then}\6 -\&{if} $\\{char\_class}[\\{buffer}[\\{loc}+1]]=\\{digit\_class}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\2\6 -$\|f\K0$;\5 -\&{goto} \37\\{fin\_numeric\_token};\6 -\4\\{done}: \37$\\{incr}(\\{loc})$\par -\U669.\fi - -\M674. \P$\X674:Get the fraction part \|f of a numeric token\X\S$\6 -$\|k\K0$;\6 -\1\&{repeat} \37\&{if} $\|k<17$ \1\&{then}\C{digits for $\|k\G17$ cannot affect -the result}\6 -\&{begin} \37$\\{dig}[\|k]\K\\{buffer}[\\{loc}]-\.{"0"}$;\5 -$\\{incr}(\|k)$;\6 -\&{end};\2\6 -$\\{incr}(\\{loc})$;\6 -\4\&{until}\5 -$\\{char\_class}[\\{buffer}[\\{loc}]]\I\\{digit\_class}$;\2\6 -$\|f\K\\{round\_decimals}(\|k)$;\6 -\&{if} $\|f=\\{unity}$ \1\&{then}\6 -\&{begin} \37$\\{incr}(\|n)$;\5 -$\|f\K0$;\6 -\&{end}\2\par -\U669.\fi - -\M675. \P$\X675:Pack the numeric and fraction parts of a numeric token and % -\&{return}\X\S$\6 -\&{if} $\|n<4096$ \1\&{then}\5 -$\\{cur\_mod}\K\|n\ast\\{unity}+\|f$\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Enormous\ number\ has\ been\ -reduced"})$;\5 -$\\{help2}(\.{"I\ can\'t\ handle\ numbers\ bigger\ than\ about\ 4095.99998;"})$% -\6 -$(\.{"so\ I\'ve\ changed\ your\ constant\ to\ that\ maximum\ amount."})$;\6 -$\\{deletions\_allowed}\K\\{false}$;\5 -\\{error};\5 -$\\{deletions\_allowed}\K\\{true}$;\5 -$\\{cur\_mod}\K\O{1777777777}$;\6 -\&{end};\2\6 -$\\{cur\_cmd}\K\\{numeric\_token}$;\5 -\&{return}\par -\U669.\fi - -\M676. Let's consider now what happens when \\{get\_next} is looking at a token -list. - -\Y\P$\4\X676:Input from token list; \&{goto} \\{restart} if end of list or if a -parameter needs to be expanded, or \&{return} if a non-symbolic token is found% -\X\S$\6 -\&{if} $\\{loc}\G\\{hi\_mem\_min}$ \1\&{then}\C{one-word token}\6 -\&{begin} \37$\\{cur\_sym}\K\\{info}(\\{loc})$;\5 -$\\{loc}\K\\{link}(\\{loc})$;\C{move to next}\6 -\&{if} $\\{cur\_sym}\G\\{expr\_base}$ \1\&{then}\6 -\&{if} $\\{cur\_sym}\G\\{suffix\_base}$ \1\&{then}\5 -\X677:Insert a suffix or text parameter and \&{goto} \\{restart}\X\6 -\4\&{else} \&{begin} \37$\\{cur\_cmd}\K\\{capsule\_token}$;\5 -$\\{cur\_mod}\K\\{param\_stack}[\\{param\_start}+\\{cur\_sym}-(\\{expr% -\_base})]$;\5 -$\\{cur\_sym}\K0$;\5 -\&{return};\6 -\&{end};\2\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{loc}>\\{null}$ \1\&{then}\5 -\X678:Get a stored numeric or string or capsule token and \&{return}\X\6 -\4\&{else} \&{begin} \37\C{we are done with this token list}\6 -\\{end\_token\_list};\5 -\&{goto} \37\\{restart};\C{resume previous level}\6 -\&{end}\2\2\par -\U667.\fi - -\M677. \P$\X677:Insert a suffix or text parameter and \&{goto} \\{restart}\X\S$% -\6 -\&{begin} \37\&{if} $\\{cur\_sym}\G\\{text\_base}$ \1\&{then}\5 -$\\{cur\_sym}\K\\{cur\_sym}-\\{param\_size}$;\C{$\\{param\_size}=\\{text% -\_base}-\\{suffix\_base}$}\2\6 -$\\{begin\_token\_list}(\\{param\_stack}[\\{param\_start}+\\{cur\_sym}-(% -\\{suffix\_base})],\39\\{parameter})$;\5 -\&{goto} \37\\{restart};\6 -\&{end}\par -\U676.\fi - -\M678. \P$\X678:Get a stored numeric or string or capsule token and \&{return}% -\X\S$\6 -\&{begin} \37\&{if} $\\{name\_type}(\\{loc})=\\{token}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_mod}\K\\{value}(\\{loc})$;\6 -\&{if} $\\{type}(\\{loc})=\\{known}$ \1\&{then}\5 -$\\{cur\_cmd}\K\\{numeric\_token}$\6 -\4\&{else} \&{begin} \37$\\{cur\_cmd}\K\\{string\_token}$;\5 -$\\{add\_str\_ref}(\\{cur\_mod})$;\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{cur\_mod}\K\\{loc}$;\5 -$\\{cur\_cmd}\K\\{capsule\_token}$;\6 -\&{end};\2\6 -$\\{loc}\K\\{link}(\\{loc})$;\5 -\&{return};\6 -\&{end}\par -\U676.\fi - -\M679. All of the easy branches of \\{get\_next} have now been taken care of. -There is one more branch. - -\Y\P$\4\X679:Move to next line of file, or \&{goto} \\{restart} if there is no -next line\X\S$\6 -\&{if} $\\{name}>2$ \1\&{then}\5 -\X681:Read next line of file into \\{buffer}, or \&{goto} \\{restart} if the -file has ended\X\6 -\4\&{else} \&{begin} \37\&{if} $\\{input\_ptr}>0$ \1\&{then}\C{text was -inserted during error recovery or by \&{scantokens}}\6 -\&{begin} \37\\{end\_file\_reading};\5 -\&{goto} \37\\{restart};\C{resume previous level}\6 -\&{end};\2\6 -\&{if} $\\{selector}<\\{log\_only}$ \1\&{then}\5 -\\{open\_log\_file};\2\6 -\&{if} $\\{interaction}>\\{nonstop\_mode}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{limit}=\\{start}$ \1\&{then}\C{previous line was empty}% -\6 -$\\{print\_nl}(\.{"(Please\ type\ a\ command\ or\ say\ \`end\')"})$;\2\6 -\\{print\_ln};\5 -$\\{first}\K\\{start}$;\5 -$\\{prompt\_input}(\.{"*"})$;\C{input on-line into \\{buffer}}\6 -$\\{limit}\K\\{last}$;\5 -$\\{buffer}[\\{limit}]\K\.{"\%"}$;\5 -$\\{first}\K\\{limit}+1$;\5 -$\\{loc}\K\\{start}$;\6 -\&{end}\6 -\4\&{else} $\\{fatal\_error}(\.{"***\ (job\ aborted,\ no\ legal\ end\ -found)"})$;\C{nonstop mode, which is intended for overnight batch processing, - never waits for on-line input}\2\6 -\&{end}\2\par -\U669.\fi - -\M680. The global variable \\{force\_eof} is normally \\{false}; it is set % -\\{true} -by an \&{endinput} command. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{force\_eof}: \37\\{boolean};\C{should the next \&{input} be aborted -early?}\par -\fi - -\M681. \P$\X681:Read next line of file into \\{buffer}, or \&{goto} \\{restart} -if the file has ended\X\S$\6 -\&{begin} \37$\\{incr}(\\{line})$;\5 -$\\{first}\K\\{start}$;\6 -\&{if} $\R\\{force\_eof}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{input\_ln}(\\{cur\_file},\39\\{true})$ \1\&{then}\C{not -end of file}\6 -\\{firm\_up\_the\_line}\C{this sets \\{limit}}\6 -\4\&{else} $\\{force\_eof}\K\\{true}$;\2\6 -\&{end};\2\6 -\&{if} $\\{force\_eof}$ \1\&{then}\6 -\&{begin} \37$\\{print\_char}(\.{")"})$;\5 -$\\{decr}(\\{open\_parens})$;\5 -\\{update\_terminal};\C{show user that file has been read}\6 -$\\{force\_eof}\K\\{false}$;\5 -\\{end\_file\_reading};\C{resume previous level}\6 -\&{if} $\\{check\_outer\_validity}$ \1\&{then}\5 -\&{goto} \37\\{restart}\ \&{else} \&{goto} \37\\{restart};\2\6 -\&{end};\2\6 -$\\{buffer}[\\{limit}]\K\.{"\%"}$;\5 -$\\{first}\K\\{limit}+1$;\5 -$\\{loc}\K\\{start}$;\C{ready to read}\6 -\&{end}\par -\U679.\fi - -\M682. If the user has set the \\{pausing} parameter to some positive value, -and if nonstop mode has not been selected, each line of input is displayed -on the terminal and the transcript file, followed by `\.{=>}'. -\MF\ waits for a response. If the response is null (i.e., if nothing is -typed except perhaps a few blank spaces), the original -line is accepted as it stands; otherwise the line typed is -used instead of the line in the file. - -\Y\P\4\&{procedure}\1\ \37\\{firm\_up\_the\_line};\6 -\4\&{var} \37\|k: \37$0\to\\{buf\_size}$;\C{an index into \\{buffer}}\2\6 -\&{begin} \37$\\{limit}\K\\{last}$;\6 -\&{if} $\\{internal}[\\{pausing}]>0$ \1\&{then}\6 -\&{if} $\\{interaction}>\\{nonstop\_mode}$ \1\&{then}\6 -\&{begin} \37\\{wake\_up\_terminal};\5 -\\{print\_ln};\6 -\&{if} $\\{start}<\\{limit}$ \1\&{then}\6 -\&{for} $\|k\K\\{start}\mathrel{\&{to}}\\{limit}-1$ \1\&{do}\5 -$\\{print}(\\{buffer}[\|k])$;\2\2\6 -$\\{first}\K\\{limit}$;\5 -$\\{prompt\_input}(\.{"=>"})$;\C{wait for user response}\6 -\&{if} $\\{last}>\\{first}$ \1\&{then}\6 -\&{begin} \37\&{for} $\|k\K\\{first}\mathrel{\&{to}}\\{last}-1$ \1\&{do}\C{move -line down in buffer}\6 -$\\{buffer}[\|k+\\{start}-\\{first}]\K\\{buffer}[\|k]$;\2\6 -$\\{limit}\K\\{start}+\\{last}-\\{first}$;\6 -\&{end};\2\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\N683. \[34] Scanning macro definitions. -\MF\ has a variety of ways to tuck tokens away into token lists for later -use: Macros can be defined with \&{def}, \&{vardef}, \&{primarydef}, etc.; -repeatable code can be defined with \&{for}, \&{forever}, \&{forsuffixes}. -All such operations are handled by the routines in this part of the program. - -The modifier part of each command code is zero for the ``ending delimiters'' -like \&{enddef} and \&{endfor}. - -\Y\P\D \37$\\{start\_def}=1$\C{command modifier for \&{def}}\par -\P\D \37$\\{var\_def}=2$\C{command modifier for \&{vardef}}\par -\P\D \37$\\{end\_def}=0$\C{command modifier for \&{enddef}}\par -\P\D \37$\\{start\_forever}=1$\C{command modifier for \&{forever}}\par -\P\D \37$\\{end\_for}=0$\C{command modifier for \&{endfor}}\par -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"def"},\39\\{macro\_def},\39\\{start\_def})$;\6 -$\\{primitive}(\.{"vardef"},\39\\{macro\_def},\39\\{var\_def})$;\6 -$\\{primitive}(\.{"primarydef"},\39\\{macro\_def},\39\\{secondary\_primary% -\_macro})$;\6 -$\\{primitive}(\.{"secondarydef"},\39\\{macro\_def},\39\\{tertiary\_secondary% -\_macro})$;\6 -$\\{primitive}(\.{"tertiarydef"},\39\\{macro\_def},\39\\{expression\_tertiary% -\_macro})$;\6 -$\\{primitive}(\.{"enddef"},\39\\{macro\_def},\39\\{end\_def})$;\5 -$\\{eqtb}[\\{frozen\_end\_def}]\K\\{eqtb}[\\{cur\_sym}]$;\7 -$\\{primitive}(\.{"for"},\39\\{iteration},\39\\{expr\_base})$;\6 -$\\{primitive}(\.{"forsuffixes"},\39\\{iteration},\39\\{suffix\_base})$;\6 -$\\{primitive}(\.{"forever"},\39\\{iteration},\39\\{start\_forever})$;\6 -$\\{primitive}(\.{"endfor"},\39\\{iteration},\39\\{end\_for})$;\5 -$\\{eqtb}[\\{frozen\_end\_for}]\K\\{eqtb}[\\{cur\_sym}]$;\par -\fi - -\M684. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{macro\_def}: \37\&{if} $\|m\L\\{var\_def}$ \1\&{then}\6 -\&{if} $\|m=\\{start\_def}$ \1\&{then}\5 -$\\{print}(\.{"def"})$\6 -\4\&{else} \&{if} $\|m<\\{start\_def}$ \1\&{then}\5 -$\\{print}(\.{"enddef"})$\6 -\4\&{else} $\\{print}(\.{"vardef"})$\2\2\6 -\4\&{else} \&{if} $\|m=\\{secondary\_primary\_macro}$ \1\&{then}\5 -$\\{print}(\.{"primarydef"})$\6 -\4\&{else} \&{if} $\|m=\\{tertiary\_secondary\_macro}$ \1\&{then}\5 -$\\{print}(\.{"secondarydef"})$\6 -\4\&{else} $\\{print}(\.{"tertiarydef"})$;\2\2\2\6 -\4\\{iteration}: \37\&{if} $\|m\L\\{start\_forever}$ \1\&{then}\6 -\&{if} $\|m=\\{start\_forever}$ \1\&{then}\5 -$\\{print}(\.{"forever"})$\ \&{else} $\\{print}(\.{"endfor"})$\2\6 -\4\&{else} \&{if} $\|m=\\{expr\_base}$ \1\&{then}\5 -$\\{print}(\.{"for"})$\ \&{else} $\\{print}(\.{"forsuffixes"})$;\2\2\par -\fi - -\M685. Different macro-absorbing operations have different syntaxes, but they -also have a lot in common. There is a list of special symbols that are to -be replaced by parameter tokens; there is a special command code that -ends the definition; the quotation conventions are identical. Therefore -it makes sense to have most of the work done by a single subroutine. That -subroutine is called \\{scan\_toks}. - -The first parameter to \\{scan\_toks} is the command code that will -terminate scanning (either \\{macro\_def}, \\{loop\_repeat}, or \\{iteration}). - -The second parameter, \\{subst\_list}, points to a (possibly empty) list -of two-word nodes whose \\{info} and \\{value} fields specify symbol tokens -before and after replacement. The list will be returned to free storage -by \\{scan\_toks}. - -The third parameter is simply appended to the token list that is built. -And the final parameter tells how many of the special operations -\.{\#\AT!}, \.{\AT!}, and \.{\AT!\#} are to be replaced by suffix parameters. -When such parameters are present, they are called \.{(SUFFIX0)}, -\.{(SUFFIX1)}, and \.{(SUFFIX2)}. - -\Y\P\4\&{function}\1\ \37$\\{scan\_toks}(\\{terminator}:\\{command\_code};\,% -\35\\{subst\_list},\39\\{tail\_end}:\\{pointer};\,\35\\{suffix\_count}:\\{small% -\_number})$: \37\\{pointer};\6 -\4\&{label} \37$\\{done},\39\\{found}$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{tail of the token list being built}\6 -\|q: \37\\{pointer};\C{temporary for link management}\6 -\\{balance}: \37\\{integer};\C{left delimiters minus right delimiters}\2\6 -\&{begin} \37$\|p\K\\{hold\_head}$;\5 -$\\{balance}\K1$;\5 -$\\{link}(\\{hold\_head})\K\\{null}$;\6 -\~ \1\&{loop}\ \&{begin} \37\\{get\_next};\6 -\&{if} $\\{cur\_sym}>0$ \1\&{then}\6 -\&{begin} \37\X686:Substitute for \\{cur\_sym}, if it's on the \\{subst\_list}% -\X;\6 -\&{if} $\\{cur\_cmd}=\\{terminator}$ \1\&{then}\5 -\X687:Adjust the balance; \&{goto} \\{done} if it's zero\X\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{macro\_special}$ \1\&{then}\5 -\X690:Handle quoted symbols, \.{\#\AT!}, \.{\AT!}, or \.{\AT!\#}\X;\2\2\6 -\&{end};\2\6 -$\\{link}(\|p)\K\\{cur\_tok}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{link}(\|p)\K\\{tail\_end}$;\5 -$\\{flush\_node\_list}(\\{subst\_list})$;\5 -$\\{scan\_toks}\K\\{link}(\\{hold\_head})$;\6 -\&{end};\par -\fi - -\M686. \P$\X686:Substitute for \\{cur\_sym}, if it's on the \\{subst\_list}\X% -\S$\6 -\&{begin} \37$\|q\K\\{subst\_list}$;\6 -\&{while} $\|q\I\\{null}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{info}(\|q)=\\{cur\_sym}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_sym}\K\\{value}(\|q)$;\5 -$\\{cur\_cmd}\K\\{relax}$;\5 -\&{goto} \37\\{found};\6 -\&{end};\2\6 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -\4\\{found}: \37\&{end}\par -\U685.\fi - -\M687. \P$\X687:Adjust the balance; \&{goto} \\{done} if it's zero\X\S$\6 -\&{if} $\\{cur\_mod}>0$ \1\&{then}\5 -$\\{incr}(\\{balance})$\6 -\4\&{else} \&{begin} \37$\\{decr}(\\{balance})$;\6 -\&{if} $\\{balance}=0$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{end}\2\par -\U685.\fi - -\M688. Four commands are intended to be used only within macro texts: % -\&{quote}, -\.{\#\AT!}, \.{\AT!}, and \.{\AT!\#}. They are variants of a single command -code called \\{macro\_special}. - -\Y\P\D \37$\\{quote}=0$\C{\\{macro\_special} modifier for \&{quote}}\par -\P\D \37$\\{macro\_prefix}=1$\C{\\{macro\_special} modifier for \.{\#\AT!}}\par -\P\D \37$\\{macro\_at}=2$\C{\\{macro\_special} modifier for \.{\AT!}}\par -\P\D \37$\\{macro\_suffix}=3$\C{\\{macro\_special} modifier for \.{\AT!\#}}\par -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"quote"},\39\\{macro\_special},\39\\{quote})$;\6 -$\\{primitive}(\.{"\#@"},\39\\{macro\_special},\39\\{macro\_prefix})$;\6 -$\\{primitive}(\.{"@"},\39\\{macro\_special},\39\\{macro\_at})$;\6 -$\\{primitive}(\.{"@\#"},\39\\{macro\_special},\39\\{macro\_suffix})$;\par -\fi - -\M689. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{macro\_special}: \37\&{case} $\|m$ \1\&{of}\6 -\4\\{macro\_prefix}: \37$\\{print}(\.{"\#@"})$;\6 -\4\\{macro\_at}: \37$\\{print\_char}(\.{"@"})$;\6 -\4\\{macro\_suffix}: \37$\\{print}(\.{"@\#"})$;\6 -\4\&{othercases} \37$\\{print}(\.{"quote"})$\2\6 -\&{endcases};\par -\fi - -\M690. \P$\X690:Handle quoted symbols, \.{\#\AT!}, \.{\AT!}, or \.{\AT!\#}\X\S$% -\6 -\&{begin} \37\&{if} $\\{cur\_mod}=\\{quote}$ \1\&{then}\5 -\\{get\_next}\6 -\4\&{else} \&{if} $\\{cur\_mod}\L\\{suffix\_count}$ \1\&{then}\5 -$\\{cur\_sym}\K\\{suffix\_base}-1+\\{cur\_mod}$;\2\2\6 -\&{end}\par -\U685.\fi - -\M691. Here is a routine that's used whenever a token will be redefined. If -the user's token is unredefinable, the `\\{frozen\_inaccessible}' token is -substituted; the latter is redefinable but essentially impossible to use, -hence \MF's tables won't get fouled up. - -\Y\P\4\&{procedure}\1\ \37\\{get\_symbol};\C{sets \\{cur\_sym} to a safe -symbol}\6 -\4\&{label} \37\\{restart};\2\6 -\&{begin} \37\\{restart}: \37\\{get\_next};\6 -\&{if} $(\\{cur\_sym}=0)\V(\\{cur\_sym}>\\{frozen\_inaccessible})$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Missing\ symbolic\ token\ inserted"})$;\5 -$\\{help3}(\.{"Sorry:\ You\ can\'t\ redefine\ a\ number,\ string,\ or\ -expr."})$\6 -$(\.{"I\'ve\ inserted\ an\ inaccessible\ symbol\ so\ that\ your"})$\6 -$(\.{"definition\ will\ be\ completed\ without\ mixing\ me\ up\ too\ -badly."})$;\6 -\&{if} $\\{cur\_sym}>0$ \1\&{then}\5 -$\\{help\_line}[2]\K\.{"Sorry:\ You\ can\'t\ redefine\ my\ error-recovery\ -tokens."}$\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{string\_token}$ \1\&{then}\5 -$\\{delete\_str\_ref}(\\{cur\_mod})$;\2\2\6 -$\\{cur\_sym}\K\\{frozen\_inaccessible}$;\5 -\\{ins\_error};\5 -\&{goto} \37\\{restart};\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M692. Before we actually redefine a symbolic token, we need to clear away its -former value, if it was a variable. The following stronger version of -\\{get\_symbol} does that. - -\Y\P\4\&{procedure}\1\ \37\\{get\_clear\_symbol};\2\6 -\&{begin} \37\\{get\_symbol};\5 -$\\{clear\_symbol}(\\{cur\_sym},\39\\{false})$;\6 -\&{end};\par -\fi - -\M693. Here's another little subroutine; it checks that an equals sign -or assignment sign comes along at the proper place in a macro definition. - -\Y\P\4\&{procedure}\1\ \37\\{check\_equals};\2\6 -\&{begin} \37\&{if} $\\{cur\_cmd}\I\\{equals}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}\I\\{assignment}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"="})$;\6 -$\\{help5}(\.{"The\ next\ thing\ in\ this\ \`def\'\ should\ have\ been\ \`=% -\',"})$\6 -$(\.{"because\ I\'ve\ already\ looked\ at\ the\ definition\ heading."})$\6 -$(\.{"But\ don\'t\ worry;\ I\'ll\ pretend\ that\ an\ equals\ sign"})$\6 -$(\.{"was\ present.\ Everything\ from\ here\ to\ \`enddef\'"})$\6 -$(\.{"will\ be\ the\ replacement\ text\ of\ this\ macro."})$;\5 -\\{back\_error};\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M694. A \&{primarydef}, \&{secondarydef}, or \&{tertiarydef} is rather easily -handled now that we have \\{scan\_toks}. In this case there are -two parameters, which will be \.{EXPR0} and \.{EXPR1} (i.e., -\\{expr\_base} and $\\{expr\_base}+1$). - -\Y\P\4\&{procedure}\1\ \37\\{make\_op\_def};\6 -\4\&{var} \37\|m: \37\\{command\_code};\C{the type of definition}\6 -$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{for list manipulation}\2\6 -\&{begin} \37$\|m\K\\{cur\_mod}$;\6 -\\{get\_symbol};\5 -$\|q\K\\{get\_node}(\\{token\_node\_size})$;\5 -$\\{info}(\|q)\K\\{cur\_sym}$;\5 -$\\{value}(\|q)\K\\{expr\_base}$;\6 -\\{get\_clear\_symbol};\5 -$\\{warning\_info}\K\\{cur\_sym}$;\6 -\\{get\_symbol};\5 -$\|p\K\\{get\_node}(\\{token\_node\_size})$;\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\5 -$\\{value}(\|p)\K\\{expr\_base}+1$;\5 -$\\{link}(\|p)\K\|q$;\6 -\\{get\_next};\5 -\\{check\_equals};\6 -$\\{scanner\_status}\K\\{op\_defining}$;\5 -$\|q\K\\{get\_avail}$;\5 -$\\{ref\_count}(\|q)\K\\{null}$;\5 -$\|r\K\\{get\_avail}$;\5 -$\\{link}(\|q)\K\|r$;\5 -$\\{info}(\|r)\K\\{general\_macro}$;\5 -$\\{link}(\|r)\K\\{scan\_toks}(\\{macro\_def},\39\|p,\39\\{null},\390)$;\5 -$\\{scanner\_status}\K\\{normal}$;\5 -$\\{eq\_type}(\\{warning\_info})\K\|m$;\5 -$\\{equiv}(\\{warning\_info})\K\|q$;\5 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M695. Parameters to macros are introduced by the keywords \&{expr}, -\&{suffix}, \&{text}, \&{primary}, \&{secondary}, and \&{tertiary}. - -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"expr"},\39\\{param\_type},\39\\{expr\_base})$;\6 -$\\{primitive}(\.{"suffix"},\39\\{param\_type},\39\\{suffix\_base})$;\6 -$\\{primitive}(\.{"text"},\39\\{param\_type},\39\\{text\_base})$;\6 -$\\{primitive}(\.{"primary"},\39\\{param\_type},\39\\{primary\_macro})$;\6 -$\\{primitive}(\.{"secondary"},\39\\{param\_type},\39\\{secondary\_macro})$;\6 -$\\{primitive}(\.{"tertiary"},\39\\{param\_type},\39\\{tertiary\_macro})$;\par -\fi - -\M696. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{param\_type}: \37\&{if} $\|m\G\\{expr\_base}$ \1\&{then}\6 -\&{if} $\|m=\\{expr\_base}$ \1\&{then}\5 -$\\{print}(\.{"expr"})$\6 -\4\&{else} \&{if} $\|m=\\{suffix\_base}$ \1\&{then}\5 -$\\{print}(\.{"suffix"})$\6 -\4\&{else} $\\{print}(\.{"text"})$\2\2\6 -\4\&{else} \&{if} $\|m<\\{secondary\_macro}$ \1\&{then}\5 -$\\{print}(\.{"primary"})$\6 -\4\&{else} \&{if} $\|m=\\{secondary\_macro}$ \1\&{then}\5 -$\\{print}(\.{"secondary"})$\6 -\4\&{else} $\\{print}(\.{"tertiary"})$;\2\2\2\par -\fi - -\M697. Let's turn next to the more complex processing associated with \&{def} -and \&{vardef}. When the following procedure is called, \\{cur\_mod} -should be either \\{start\_def} or \\{var\_def}. - -\Y\P\hbox{\4}\X1032:Declare the procedure called \\{check\_delimiter}\X\6 -\hbox{\4}\X1011:Declare the function called \\{scan\_declared\_variable}\X\6 -\4\&{procedure}\1\ \37\\{scan\_def};\6 -\4\&{var} \37\|m: \37$\\{start\_def}\to\\{var\_def}$;\C{the type of definition}% -\6 -\|n: \37$0\to3$;\C{the number of special suffix parameters}\6 -\|k: \37$0\to\\{param\_size}$;\C{the total number of parameters}\6 -\|c: \37$\\{general\_macro}\to\\{text\_macro}$;\C{the kind of macro we're -defining}\6 -\|r: \37\\{pointer};\C{parameter-substitution list}\6 -\|q: \37\\{pointer};\C{tail of the macro token list}\6 -\|p: \37\\{pointer};\C{temporary storage}\6 -\\{base}: \37\\{halfword};\C{\\{expr\_base}, \\{suffix\_base}, or \\{text% -\_base}}\6 -$\\{l\_delim},\39\\{r\_delim}$: \37\\{pointer};\C{matching delimiters}\2\6 -\&{begin} \37$\|m\K\\{cur\_mod}$;\5 -$\|c\K\\{general\_macro}$;\5 -$\\{link}(\\{hold\_head})\K\\{null}$;\6 -$\|q\K\\{get\_avail}$;\5 -$\\{ref\_count}(\|q)\K\\{null}$;\5 -$\|r\K\\{null}$;\6 -\X700:Scan the token or variable to be defined; set \|n, \\{scanner\_status}, -and \\{warning\_info}\X;\6 -$\|k\K\|n$;\6 -\&{if} $\\{cur\_cmd}=\\{left\_delimiter}$ \1\&{then}\5 -\X703:Absorb delimited parameters, putting them into lists \|q and \|r\X;\2\6 -\&{if} $\\{cur\_cmd}=\\{param\_type}$ \1\&{then}\5 -\X705:Absorb undelimited parameters, putting them into list \|r\X;\2\6 -\\{check\_equals};\5 -$\|p\K\\{get\_avail}$;\5 -$\\{info}(\|p)\K\|c$;\5 -$\\{link}(\|q)\K\|p$;\5 -\X698:Attach the replacement text to the tail of node \|p\X;\6 -$\\{scanner\_status}\K\\{normal}$;\5 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M698. We don't put `\\{frozen\_end\_group}' into the replacement text of -a \&{vardef}, because the user may want to redefine `\.{endgroup}'. - -\Y\P$\4\X698:Attach the replacement text to the tail of node \|p\X\S$\6 -\&{if} $\|m=\\{start\_def}$ \1\&{then}\5 -$\\{link}(\|p)\K\\{scan\_toks}(\\{macro\_def},\39\|r,\39\\{null},\39\|n)$\6 -\4\&{else} \&{begin} \37$\|q\K\\{get\_avail}$;\5 -$\\{info}(\|q)\K\\{bg\_loc}$;\5 -$\\{link}(\|p)\K\|q$;\5 -$\|p\K\\{get\_avail}$;\5 -$\\{info}(\|p)\K\\{eg\_loc}$;\5 -$\\{link}(\|q)\K\\{scan\_toks}(\\{macro\_def},\39\|r,\39\|p,\39\|n)$;\6 -\&{end};\2\6 -\&{if} $\\{warning\_info}=\\{bad\_vardef}$ \1\&{then}\5 -$\\{flush\_token\_list}(\\{value}(\\{bad\_vardef}))$\2\par -\U697.\fi - -\M699. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{bg\_loc},\39\\{eg\_loc}$: \37$1\to\\{hash\_end}$;\C{hash addresses of `% -\.{begingroup}' and `\.{endgroup}'}\par -\fi - -\M700. \P$\X700:Scan the token or variable to be defined; set \|n, \\{scanner% -\_status}, and \\{warning\_info}\X\S$\6 -\&{if} $\|m=\\{start\_def}$ \1\&{then}\6 -\&{begin} \37\\{get\_clear\_symbol};\5 -$\\{warning\_info}\K\\{cur\_sym}$;\5 -\\{get\_next};\5 -$\\{scanner\_status}\K\\{op\_defining}$;\5 -$\|n\K0$;\5 -$\\{eq\_type}(\\{warning\_info})\K\\{defined\_macro}$;\5 -$\\{equiv}(\\{warning\_info})\K\|q$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|p\K\\{scan\_declared\_variable}$;\5 -$\\{flush\_variable}(\\{equiv}(\\{info}(\|p)),\39\\{link}(\|p),\39\\{true})$;\5 -$\\{warning\_info}\K\\{find\_variable}(\|p)$;\5 -$\\{flush\_list}(\|p)$;\6 -\&{if} $\\{warning\_info}=\\{null}$ \1\&{then}\5 -\X701:Change to `\.{a bad variable}'\X;\2\6 -$\\{scanner\_status}\K\\{var\_defining}$;\5 -$\|n\K2$;\6 -\&{if} $\\{cur\_cmd}=\\{macro\_special}$ \1\&{then}\6 -\&{if} $\\{cur\_mod}=\\{macro\_suffix}$ \1\&{then}\C{\.{\AT!\#}}\6 -\&{begin} \37$\|n\K3$;\5 -\\{get\_next};\6 -\&{end};\2\2\6 -$\\{type}(\\{warning\_info})\K\\{unsuffixed\_macro}-2+\|n$;\5 -$\\{value}(\\{warning\_info})\K\|q$;\6 -\&{end}\C{$\\{suffixed\_macro}=\\{unsuffixed\_macro}+1$}\2\par -\U697.\fi - -\M701. \P$\X701:Change to `\.{a bad variable}'\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"This\ variable\ already\ starts\ with\ a\ -macro"})$;\5 -$\\{help2}(\.{"After\ \`vardef\ a\'\ you\ can\'t\ say\ \`vardef\ a.b\'."})$\6 -$(\.{"So\ I\'ll\ have\ to\ discard\ this\ definition."})$;\5 -\\{error};\5 -$\\{warning\_info}\K\\{bad\_vardef}$;\6 -\&{end}\par -\U700.\fi - -\M702. \P$\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}% -\S$\6 -$\\{name\_type}(\\{bad\_vardef})\K\\{root}$;\5 -$\\{link}(\\{bad\_vardef})\K\\{frozen\_bad\_vardef}$;\5 -$\\{equiv}(\\{frozen\_bad\_vardef})\K\\{bad\_vardef}$;\5 -$\\{eq\_type}(\\{frozen\_bad\_vardef})\K\\{tag\_token}$;\par -\fi - -\M703. \P$\X703:Absorb delimited parameters, putting them into lists \|q and % -\|r\X\S$\6 -\1\&{repeat} \37$\\{l\_delim}\K\\{cur\_sym}$;\5 -$\\{r\_delim}\K\\{cur\_mod}$;\5 -\\{get\_next};\6 -\&{if} $(\\{cur\_cmd}=\\{param\_type})\W(\\{cur\_mod}\G\\{expr\_base})$ \1% -\&{then}\5 -$\\{base}\K\\{cur\_mod}$\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Missing\ parameter\ type;\ \`expr\'% -\ will\ be\ assumed"})$;\5 -$\\{help1}(\.{"You\ should\'ve\ had\ \`expr\'\ or\ \`suffix\'\ or\ \`text\'\ -here."})$;\5 -\\{back\_error};\5 -$\\{base}\K\\{expr\_base}$;\6 -\&{end};\2\6 -\X704:Absorb parameter tokens for type \\{base}\X;\6 -$\\{check\_delimiter}(\\{l\_delim},\39\\{r\_delim})$;\5 -\\{get\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{left\_delimiter}$\2\par -\U697.\fi - -\M704. \P$\X704:Absorb parameter tokens for type \\{base}\X\S$\6 -\1\&{repeat} \37$\\{link}(\|q)\K\\{get\_avail}$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{info}(\|q)\K\\{base}+\|k$;\6 -\\{get\_symbol};\5 -$\|p\K\\{get\_node}(\\{token\_node\_size})$;\5 -$\\{value}(\|p)\K\\{base}+\|k$;\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\6 -\&{if} $\|k=\\{param\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"parameter\ stack\ size"},\39\\{param\_size})$;\2\6 -$\\{incr}(\|k)$;\5 -$\\{link}(\|p)\K\|r$;\5 -$\|r\K\|p$;\5 -\\{get\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$\2\par -\U703.\fi - -\M705. \P$\X705:Absorb undelimited parameters, putting them into list \|r\X\S$\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{token\_node\_size})$;\6 -\&{if} $\\{cur\_mod}<\\{expr\_base}$ \1\&{then}\6 -\&{begin} \37$\|c\K\\{cur\_mod}$;\5 -$\\{value}(\|p)\K\\{expr\_base}+\|k$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{value}(\|p)\K\\{cur\_mod}+\|k$;\6 -\&{if} $\\{cur\_mod}=\\{expr\_base}$ \1\&{then}\5 -$\|c\K\\{expr\_macro}$\6 -\4\&{else} \&{if} $\\{cur\_mod}=\\{suffix\_base}$ \1\&{then}\5 -$\|c\K\\{suffix\_macro}$\6 -\4\&{else} $\|c\K\\{text\_macro}$;\2\2\6 -\&{end};\2\6 -\&{if} $\|k=\\{param\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"parameter\ stack\ size"},\39\\{param\_size})$;\2\6 -$\\{incr}(\|k)$;\5 -\\{get\_symbol};\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\5 -$\\{link}(\|p)\K\|r$;\5 -$\|r\K\|p$;\5 -\\{get\_next};\6 -\&{if} $\|c=\\{expr\_macro}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}=\\{of\_token}$ \1\&{then}\6 -\&{begin} \37$\|c\K\\{of\_macro}$;\5 -$\|p\K\\{get\_node}(\\{token\_node\_size})$;\6 -\&{if} $\|k=\\{param\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"parameter\ stack\ size"},\39\\{param\_size})$;\2\6 -$\\{value}(\|p)\K\\{expr\_base}+\|k$;\5 -\\{get\_symbol};\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\5 -$\\{link}(\|p)\K\|r$;\5 -$\|r\K\|p$;\5 -\\{get\_next};\6 -\&{end};\2\2\6 -\&{end}\par -\U697.\fi - -\N706. \[35] Expanding the next token. -Only a few command codes $<\\{min\_command}$ can possibly be returned by -\\{get\_next}; in increasing order, they are -\\{if\_test}, \\{fi\_or\_else}, \\{input}, \\{iteration}, \\{repeat\_loop}, -\\{exit\_test}, \\{relax}, \\{scan\_tokens}, \\{expand\_after}, and \\{defined% -\_macro}. - -\MF\ usually gets the next token of input by saying \\{get\_x\_next}. This is -like \\{get\_next} except that it keeps getting more tokens until -finding $\\{cur\_cmd}\G\\{min\_command}$. In other words, \\{get\_x\_next} -expands -macros and removes conditionals or iterations or input instructions that -might be present. - -It follows that \\{get\_x\_next} might invoke itself recursively. In fact, -there is massive recursion, since macro expansion can involve the -scanning of arbitrarily complex expressions, which in turn involve -macro expansion and conditionals, etc. - -Therefore it's necessary to declare a whole bunch of \\{forward} -procedures at this point, and to insert some other procedures -that will be invoked by \\{get\_x\_next}. - -\Y\P\4\&{procedure}\1\ \37\\{scan\_primary};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{scan\_secondary};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{scan\_tertiary};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{scan\_expression};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{scan\_suffix};\5 -\\{forward};\5 -\hbox{\2}\6 -\hbox{\4}\X720:Declare the procedure called \\{macro\_call}\X\6 -\4\&{procedure}\1\ \37\\{get\_boolean};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{pass\_text};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{conditional};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{start\_input};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{begin\_iteration};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{resume\_iteration};\5 -\\{forward}; \hbox{\2} \6 -\4\&{procedure}\1\ \37\\{stop\_iteration};\5 -\\{forward};\5 -\hbox{\2}\par -\fi - -\M707. An auxiliary subroutine called \\{expand} is used by \\{get\_x\_next} -when it has to do exotic expansion commands. - -\Y\P\4\&{procedure}\1\ \37\\{expand};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{for list manipulation}\6 -\|k: \37\\{integer};\C{something that we hope is $\L\\{buf\_size}$}\6 -\|j: \37\\{pool\_pointer};\C{index into \\{str\_pool}}\2\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_commands}]>\\{unity}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}\I\\{defined\_macro}$ \1\&{then}\5 -\\{show\_cur\_cmd\_mod};\2\2\6 -\&{case} $\\{cur\_cmd}$ \1\&{of}\6 -\4\\{if\_test}: \37\\{conditional};\C{this procedure is discussed in Part 36 -below}\6 -\4\\{fi\_or\_else}: \37\X751:Terminate the current conditional and skip to % -\&{fi}\X;\6 -\4\\{input}: \37\X711:Initiate or terminate input from a file\X;\6 -\4\\{iteration}: \37\&{if} $\\{cur\_mod}=\\{end\_for}$ \1\&{then}\5 -\X708:Scold the user for having an extra \&{endfor}\X\6 -\4\&{else} \\{begin\_iteration};\C{this procedure is discussed in Part 37 -below}\2\6 -\4\\{repeat\_loop}: \37\X712:Repeat a loop\X;\6 -\4\\{exit\_test}: \37\X713:Exit a loop if the proper time has come\X;\6 -\4\\{relax}: \37\\{do\_nothing};\6 -\4\\{expand\_after}: \37\X715:Expand the token after the next token\X;\6 -\4\\{scan\_tokens}: \37\X716:Put a string into the input buffer\X;\6 -\4\\{defined\_macro}: \37$\\{macro\_call}(\\{cur\_mod},\39\\{null},\39\\{cur% -\_sym})$;\2\6 -\&{end};\C{there are no other cases}\6 -\&{end};\par -\fi - -\M708. \P$\X708:Scold the user for having an extra \&{endfor}\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Extra\ \`endfor\'"})$;\5 -$\\{help2}(\.{"I\'m\ not\ currently\ working\ on\ a\ for\ loop,"})$\6 -$(\.{"so\ I\ had\ better\ not\ try\ to\ end\ anything."})$;\6 -\\{error};\6 -\&{end}\par -\U707.\fi - -\M709. The processing of \&{input} involves the \\{start\_input} subroutine, -which will be declared later; the processing of \&{endinput} is trivial. - -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"input"},\39\\{input},\390)$;\6 -$\\{primitive}(\.{"endinput"},\39\\{input},\391)$;\par -\fi - -\M710. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{input}: \37\&{if} $\|m=0$ \1\&{then}\5 -$\\{print}(\.{"input"})$\ \&{else} $\\{print}(\.{"endinput"})$;\2\par -\fi - -\M711. \P$\X711:Initiate or terminate input from a file\X\S$\6 -\&{if} $\\{cur\_mod}>0$ \1\&{then}\5 -$\\{force\_eof}\K\\{true}$\6 -\4\&{else} \\{start\_input}\2\par -\U707.\fi - -\M712. We'll discuss the complicated parts of loop operations later. For now -it suffices to know that there's a global variable called \\{loop\_ptr} -that will be \\{null} if no loop is in progress. - -\Y\P$\4\X712:Repeat a loop\X\S$\6 -\&{begin} \37\&{while} $\\{token\_state}\W(\\{loc}=\\{null})$ \1\&{do}\5 -\\{end\_token\_list};\C{conserve stack space}\2\6 -\&{if} $\\{loop\_ptr}=\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Lost\ loop"})$;\5 -$\\{help2}(\.{"I\'m\ confused;\ after\ exiting\ from\ a\ loop,\ I\ still\ -seem"})$\6 -$(\.{"to\ want\ to\ repeat\ it.\ I\'ll\ try\ to\ forget\ the\ problem."})$;\6 -\\{error};\6 -\&{end}\6 -\4\&{else} \\{resume\_iteration};\C{this procedure is in Part 37 below}\2\6 -\&{end}\par -\U707.\fi - -\M713. \P$\X713:Exit a loop if the proper time has come\X\S$\6 -\&{begin} \37\\{get\_boolean};\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{unity}$ \1\&{then}\5 -$\\{show\_cmd\_mod}(\\{nullary},\39\\{cur\_exp})$;\2\6 -\&{if} $\\{cur\_exp}=\\{true\_code}$ \1\&{then}\6 -\&{if} $\\{loop\_ptr}=\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"No\ loop\ is\ in\ progress"})$;\5 -$\\{help1}(\.{"Why\ say\ \`exitif\'\ when\ there\'s\ nothing\ to\ exit\ -from?"})$;\6 -\&{if} $\\{cur\_cmd}=\\{semicolon}$ \1\&{then}\5 -\\{error}\ \&{else} \\{back\_error};\2\6 -\&{end}\6 -\4\&{else} \X714:Exit prematurely from an iteration\X\2\6 -\4\&{else} \&{if} $\\{cur\_cmd}\I\\{semicolon}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{";"})$;\6 -$\\{help2}(\.{"After\ \`exitif\ <boolean\ exp>\'\ I\ expect\ to\ see\ a\ -semicolon."})$\6 -$(\.{"I\ shall\ pretend\ that\ one\ was\ there."})$;\5 -\\{back\_error};\6 -\&{end};\2\2\6 -\&{end}\par -\U707.\fi - -\M714. Here we use the fact that \\{forever\_text} is the only \\{token\_type} -that -is less than \\{loop\_text}. - -\Y\P$\4\X714:Exit prematurely from an iteration\X\S$\6 -\&{begin} \37$\|p\K\\{null}$;\6 -\1\&{repeat} \37\&{if} $\\{file\_state}$ \1\&{then}\5 -\\{end\_file\_reading}\6 -\4\&{else} \&{begin} \37\&{if} $\\{token\_type}\L\\{loop\_text}$ \1\&{then}\5 -$\|p\K\\{start}$;\2\6 -\\{end\_token\_list};\6 -\&{end};\2\6 -\4\&{until}\5 -$\|p\I\\{null}$;\2\6 -\&{if} $\|p\I\\{info}(\\{loop\_ptr})$ \1\&{then}\5 -$\\{fatal\_error}(\.{"***\ (loop\ confusion)"})$;\2\6 -\\{stop\_iteration};\C{this procedure is in Part 37 below}\6 -\&{end}\par -\U713.\fi - -\M715. \P$\X715:Expand the token after the next token\X\S$\6 -\&{begin} \37\\{get\_next};\5 -$\|p\K\\{cur\_tok}$;\5 -\\{get\_next};\6 -\&{if} $\\{cur\_cmd}<\\{min\_command}$ \1\&{then}\5 -\\{expand}\6 -\4\&{else} \\{back\_input};\2\6 -$\\{back\_list}(\|p)$;\6 -\&{end}\par -\U707.\fi - -\M716. \P$\X716:Put a string into the input buffer\X\S$\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_primary};\6 -\&{if} $\\{cur\_type}\I\\{string\_type}$ \1\&{then}\6 -\&{begin} \37$\\{disp\_err}(\\{null},\39\.{"Not\ a\ string"})$;\5 -$\\{help2}(\.{"I\'m\ going\ to\ flush\ this\ expression,\ since"})$\6 -$(\.{"scantokens\ should\ be\ followed\ by\ a\ known\ string."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\\{back\_input};\6 -\&{if} $\\{length}(\\{cur\_exp})>0$ \1\&{then}\5 -\X717:Pretend we're reading a new one-line file\X;\2\6 -\&{end};\2\6 -\&{end}\par -\U707.\fi - -\M717. \P$\X717:Pretend we're reading a new one-line file\X\S$\6 -\&{begin} \37\\{begin\_file\_reading};\5 -$\\{name}\K2$;\5 -$\|k\K\\{first}+\\{length}(\\{cur\_exp})$;\6 -\&{if} $\|k\G\\{max\_buf\_stack}$ \1\&{then}\6 -\&{begin} \37\&{if} $\|k\G\\{buf\_size}$ \1\&{then}\6 -\&{begin} \37$\\{max\_buf\_stack}\K\\{buf\_size}$;\5 -$\\{overflow}(\.{"buffer\ size"},\39\\{buf\_size})$;\6 -\&{end};\2\6 -$\\{max\_buf\_stack}\K\|k+1$;\6 -\&{end};\2\6 -$\|j\K\\{str\_start}[\\{cur\_exp}]$;\5 -$\\{limit}\K\|k$;\6 -\&{while} $\\{first}<\\{limit}$ \1\&{do}\6 -\&{begin} \37$\\{buffer}[\\{first}]\K\\{so}(\\{str\_pool}[\|j])$;\5 -$\\{incr}(\|j)$;\5 -$\\{incr}(\\{first})$;\6 -\&{end};\2\6 -$\\{buffer}[\\{limit}]\K\.{"\%"}$;\5 -$\\{first}\K\\{limit}+1$;\5 -$\\{loc}\K\\{start}$;\5 -$\\{flush\_cur\_exp}(0)$;\6 -\&{end}\par -\U716.\fi - -\M718. Here finally is \\{get\_x\_next}. - -The expression scanning routines to be considered later -communicate via the global quantities \\{cur\_type} and \\{cur\_exp}; -we must be very careful to save and restore these quantities while -macros are being expanded. - -\Y\P\4\&{procedure}\1\ \37\\{get\_x\_next};\6 -\4\&{var} \37\\{save\_exp}: \37\\{pointer};\C{a capsule to save \\{cur\_type} -and \\{cur\_exp}}\2\6 -\&{begin} \37\\{get\_next};\6 -\&{if} $\\{cur\_cmd}<\\{min\_command}$ \1\&{then}\6 -\&{begin} \37$\\{save\_exp}\K\\{stash\_cur\_exp}$;\6 -\1\&{repeat} \37\&{if} $\\{cur\_cmd}=\\{defined\_macro}$ \1\&{then}\5 -$\\{macro\_call}(\\{cur\_mod},\39\\{null},\39\\{cur\_sym})$\6 -\4\&{else} \\{expand};\2\6 -\\{get\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\G\\{min\_command}$;\2\6 -$\\{unstash\_cur\_exp}(\\{save\_exp})$;\C{that restores \\{cur\_type} and % -\\{cur\_exp}}\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M719. Now let's consider the \\{macro\_call} procedure, which is used to start -up -all user-defined macros. Since the arguments to a macro might be expressions, -\\{macro\_call} is recursive. - -The first parameter to \\{macro\_call} points to the reference count of the -token list that defines the macro. The second parameter contains any -arguments that have already been parsed (see below). The third parameter -points to the symbolic token that names the macro. If the third parameter -is \\{null}, the macro was defined by \&{vardef}, so its name can be -reconstructed from the prefix and ``at'' arguments found within the -second parameter. - -What is this second parameter? It's simply a linked list of one-word items, -whose \\{info} fields point to the arguments. In other words, if $\\{arg% -\_list}=\\{null}$, -no arguments have been scanned yet; otherwise $\\{info}(\\{arg\_list})$ points -to -the first scanned argument, and $\\{link}(\\{arg\_list})$ points to the list of -further arguments (if any). - -Arguments of type \&{expr} are so-called capsules, which we will -discuss later when we concentrate on expressions; they can be -recognized easily because their \\{link} field is \\{void}. Arguments of type -\&{suffix} and \&{text} are token lists without reference counts. - -\fi - -\M720. After argument scanning is complete, the arguments are moved to the -\\{param\_stack}. (They can't be put on that stack any sooner, because -the stack is growing and shrinking in unpredictable ways as more arguments -are being acquired.) Then the macro body is fed to the scanner; i.e., -the replacement text of the macro is placed at the top of the \MF's -input stack, so that \\{get\_next} will proceed to read it next. - -\Y\P$\4\X720:Declare the procedure called \\{macro\_call}\X\S$\6 -\hbox{\4}\X722:Declare the procedure called \\{print\_macro\_name}\X\6 -\hbox{\4}\X723:Declare the procedure called \\{print\_arg}\X\6 -\hbox{\4}\X730:Declare the procedure called \\{scan\_text\_arg}\X\6 -\4\&{procedure}\1\ \37$\\{macro\_call}(\\{def\_ref},\39\\{arg\_list},\39% -\\{macro\_name}:\\{pointer})$;\C{invokes a user-defined control sequence}\6 -\4\&{label} \37\\{found};\6 -\4\&{var} \37\|r: \37\\{pointer};\C{current node in the macro's token list}\6 -$\|p,\39\|q$: \37\\{pointer};\C{for list manipulation}\6 -\|n: \37\\{integer};\C{the number of arguments}\6 -$\\{l\_delim},\39\\{r\_delim}$: \37\\{pointer};\C{a delimiter pair}\6 -\\{tail}: \37\\{pointer};\C{tail of the argument list}\2\6 -\&{begin} \37$\|r\K\\{link}(\\{def\_ref})$;\5 -$\\{add\_mac\_ref}(\\{def\_ref})$;\6 -\&{if} $\\{arg\_list}=\\{null}$ \1\&{then}\5 -$\|n\K0$\6 -\4\&{else} \X724:Determine the number \|n of arguments already supplied, and -set \\{tail} to the tail of \\{arg\_list}\X;\2\6 -\&{if} $\\{internal}[\\{tracing\_macros}]>0$ \1\&{then}\5 -\X721:Show the text of the macro being expanded, and the existing arguments\X;% -\2\6 -\X725:Scan the remaining arguments, if any; set \|r to the first token of the -replacement text\X;\6 -\X736:Feed the arguments and replacement text to the scanner\X;\6 -\&{end};\par -\U706.\fi - -\M721. \P$\X721:Show the text of the macro being expanded, and the existing -arguments\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\5 -\\{print\_ln};\5 -$\\{print\_macro\_name}(\\{arg\_list},\39\\{macro\_name})$;\6 -\&{if} $\|n=3$ \1\&{then}\5 -$\\{print}(\.{"@\#"})$;\C{indicate a suffixed macro}\2\6 -$\\{show\_macro}(\\{def\_ref},\39\\{null},\39100000)$;\6 -\&{if} $\\{arg\_list}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\|n\K0$;\5 -$\|p\K\\{arg\_list}$;\6 -\1\&{repeat} \37$\|q\K\\{info}(\|p)$;\5 -$\\{print\_arg}(\|q,\39\|n,\390)$;\5 -$\\{incr}(\|n)$;\5 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\|p=\\{null}$;\2\6 -\&{end};\2\6 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U720.\fi - -\M722. \P$\X722:Declare the procedure called \\{print\_macro\_name}\X\S$\6 -\4\&{procedure}\1\ \37$\\{print\_macro\_name}(\|a,\39\|n:\\{pointer})$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{they traverse the first part of % -\|a}\2\6 -\&{begin} \37\&{if} $\|n\I\\{null}$ \1\&{then}\5 -$\\{slow\_print}(\\{text}(\|n))$\6 -\4\&{else} \&{begin} \37$\|p\K\\{info}(\|a)$;\6 -\&{if} $\|p=\\{null}$ \1\&{then}\5 -$\\{slow\_print}(\\{text}(\\{info}(\\{info}(\\{link}(\|a)))))$\6 -\4\&{else} \&{begin} \37$\|q\K\|p$;\6 -\&{while} $\\{link}(\|q)\I\\{null}$ \1\&{do}\5 -$\|q\K\\{link}(\|q)$;\2\6 -$\\{link}(\|q)\K\\{info}(\\{link}(\|a))$;\5 -$\\{show\_token\_list}(\|p,\39\\{null},\391000,\390)$;\5 -$\\{link}(\|q)\K\\{null}$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\par -\U720.\fi - -\M723. \P$\X723:Declare the procedure called \\{print\_arg}\X\S$\6 -\4\&{procedure}\1\ \37$\\{print\_arg}(\|q:\\{pointer};\,\35\|n:\\{integer};\,% -\35\|b:\\{pointer})$;\2\6 -\&{begin} \37\&{if} $\\{link}(\|q)=\\{void}$ \1\&{then}\5 -$\\{print\_nl}(\.{"(EXPR"})$\6 -\4\&{else} \&{if} $(\|b<\\{text\_base})\W(\|b\I\\{text\_macro})$ \1\&{then}\5 -$\\{print\_nl}(\.{"(SUFFIX"})$\6 -\4\&{else} $\\{print\_nl}(\.{"(TEXT"})$;\2\2\6 -$\\{print\_int}(\|n)$;\5 -$\\{print}(\.{")<-"})$;\6 -\&{if} $\\{link}(\|q)=\\{void}$ \1\&{then}\5 -$\\{print\_exp}(\|q,\391)$\6 -\4\&{else} $\\{show\_token\_list}(\|q,\39\\{null},\391000,\390)$;\2\6 -\&{end};\par -\U720.\fi - -\M724. \P$\X724:Determine the number \|n of arguments already supplied, and set -\\{tail} to the tail of \\{arg\_list}\X\S$\6 -\&{begin} \37$\|n\K1$;\5 -$\\{tail}\K\\{arg\_list}$;\6 -\&{while} $\\{link}(\\{tail})\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\\{incr}(\|n)$;\5 -$\\{tail}\K\\{link}(\\{tail})$;\6 -\&{end};\2\6 -\&{end}\par -\U720.\fi - -\M725. \P$\X725:Scan the remaining arguments, if any; set \|r to the first -token of the replacement text\X\S$\6 -$\\{cur\_cmd}\K\\{comma}+1$;\C{anything $\I\\{comma}$ will do}\6 -\&{while} $\\{info}(\|r)\G\\{expr\_base}$ \1\&{do}\6 -\&{begin} \37\X726:Scan the delimited argument represented by $\\{info}(\|r)$% -\X;\6 -$\|r\K\\{link}(\|r)$;\6 -\&{end};\2\6 -\&{if} $\\{cur\_cmd}=\\{comma}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Too\ many\ arguments\ to\ "})$;\5 -$\\{print\_macro\_name}(\\{arg\_list},\39\\{macro\_name})$;\5 -$\\{print\_char}(\.{";"})$;\5 -$\\{print\_nl}(\.{"\ \ Missing\ \`"})$;\5 -$\\{slow\_print}(\\{text}(\\{r\_delim}))$;\5 -$\\{print}(\.{"\'\ has\ been\ inserted"})$;\5 -$\\{help3}(\.{"I\'m\ going\ to\ assume\ that\ the\ comma\ I\ just\ read\ was\ -a"})$\6 -$(\.{"right\ delimiter,\ and\ then\ I\'ll\ begin\ expanding\ the\ macro."})$\6 -$(\.{"You\ might\ want\ to\ delete\ some\ tokens\ before\ continuing."})$;\5 -\\{error};\6 -\&{end};\2\6 -\&{if} $\\{info}(\|r)\I\\{general\_macro}$ \1\&{then}\5 -\X733:Scan undelimited argument(s)\X;\2\6 -$\|r\K\\{link}(\|r)$\par -\U720.\fi - -\M726. At this point, the reader will find it advisable to review the -explanation -of token list format that was presented earlier, paying special attention to -the conventions that apply only at the beginning of a macro's token list. - -On the other hand, the reader will have to take the expression-parsing -aspects of the following program on faith; we will explain \\{cur\_type} -and \\{cur\_exp} later. (Several things in this program depend on each other, -and it's necessary to jump into the circle somewhere.) - -\Y\P$\4\X726:Scan the delimited argument represented by $\\{info}(\|r)$\X\S$\6 -\&{if} $\\{cur\_cmd}\I\\{comma}$ \1\&{then}\6 -\&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}\I\\{left\_delimiter}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Missing\ argument\ to\ "})$;\5 -$\\{print\_macro\_name}(\\{arg\_list},\39\\{macro\_name})$;\5 -$\\{help3}(\.{"That\ macro\ has\ more\ parameters\ than\ you\ thought."})$\6 -$(\.{"I\'ll\ continue\ by\ pretending\ that\ each\ missing\ argument"})$\6 -$(\.{"is\ either\ zero\ or\ null."})$;\6 -\&{if} $\\{info}(\|r)\G\\{suffix\_base}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_exp}\K\\{null}$;\5 -$\\{cur\_type}\K\\{token\_list}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{cur\_exp}\K0$;\5 -$\\{cur\_type}\K\\{known}$;\6 -\&{end};\2\6 -\\{back\_error};\5 -$\\{cur\_cmd}\K\\{right\_delimiter}$;\5 -\&{goto} \37\\{found};\6 -\&{end};\2\6 -$\\{l\_delim}\K\\{cur\_sym}$;\5 -$\\{r\_delim}\K\\{cur\_mod}$;\6 -\&{end};\2\6 -\X729:Scan the argument represented by $\\{info}(\|r)$\X;\6 -\&{if} $\\{cur\_cmd}\I\\{comma}$ \1\&{then}\5 -\X727:Check that the proper right delimiter was present\X;\2\6 -\4\\{found}: \37\X728:Append the current expression to \\{arg\_list}\X\par -\U725.\fi - -\M727. \P$\X727:Check that the proper right delimiter was present\X\S$\6 -\&{if} $(\\{cur\_cmd}\I\\{right\_delimiter})\V(\\{cur\_mod}\I\\{l\_delim})$ \1% -\&{then}\6 -\&{if} $\\{info}(\\{link}(\|r))\G\\{expr\_base}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{","})$;\5 -$\\{help3}(\.{"I\'ve\ finished\ reading\ a\ macro\ argument\ and\ am\ about\ -to"})$\6 -$(\.{"read\ another;\ the\ arguments\ weren\'t\ delimited\ correctly."})$\6 -$(\.{"You\ might\ want\ to\ delete\ some\ tokens\ before\ continuing."})$;\5 -\\{back\_error};\5 -$\\{cur\_cmd}\K\\{comma}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{missing\_err}(\\{text}(\\{r\_delim}))$;\5 -$\\{help2}(\.{"I\'ve\ gotten\ to\ the\ end\ of\ the\ macro\ parameter\ -list."})$\6 -$(\.{"You\ might\ want\ to\ delete\ some\ tokens\ before\ continuing."})$;\5 -\\{back\_error};\6 -\&{end}\2\2\par -\U726.\fi - -\M728. A \&{suffix} or \&{text} parameter will be have been scanned as -a token list pointed to by \\{cur\_exp}, in which case we will have -$\\{cur\_type}=\\{token\_list}$. - -\Y\P$\4\X728:Append the current expression to \\{arg\_list}\X\S$\6 -\&{begin} \37$\|p\K\\{get\_avail}$;\6 -\&{if} $\\{cur\_type}=\\{token\_list}$ \1\&{then}\5 -$\\{info}(\|p)\K\\{cur\_exp}$\6 -\4\&{else} $\\{info}(\|p)\K\\{stash\_cur\_exp}$;\2\6 -\&{if} $\\{internal}[\\{tracing\_macros}]>0$ \1\&{then}\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_arg}(\\{info}(\|p),\39\|n,\39\\{info}(\|r))$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end};\2\6 -\&{if} $\\{arg\_list}=\\{null}$ \1\&{then}\5 -$\\{arg\_list}\K\|p$\6 -\4\&{else} $\\{link}(\\{tail})\K\|p$;\2\6 -$\\{tail}\K\|p$;\5 -$\\{incr}(\|n)$;\6 -\&{end}\par -\Us726\ET733.\fi - -\M729. \P$\X729:Scan the argument represented by $\\{info}(\|r)$\X\S$\6 -\&{if} $\\{info}(\|r)\G\\{text\_base}$ \1\&{then}\5 -$\\{scan\_text\_arg}(\\{l\_delim},\39\\{r\_delim})$\6 -\4\&{else} \&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{info}(\|r)\G\\{suffix\_base}$ \1\&{then}\5 -\\{scan\_suffix}\6 -\4\&{else} \\{scan\_expression};\2\6 -\&{end}\2\par -\U726.\fi - -\M730. The parameters to \\{scan\_text\_arg} are either a pair of delimiters -or zero; the latter case is for undelimited text arguments, which -end with the first semicolon or \&{endgroup} or \&{end} that is not -contained in a group. - -\Y\P$\4\X730:Declare the procedure called \\{scan\_text\_arg}\X\S$\6 -\4\&{procedure}\1\ \37$\\{scan\_text\_arg}(\\{l\_delim},\39\\{r\_delim}:% -\\{pointer})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\\{balance}: \37\\{integer};\C{excess of \\{l\_delim} over \\{r% -\_delim}}\6 -\|p: \37\\{pointer};\C{list tail}\2\6 -\&{begin} \37$\\{warning\_info}\K\\{l\_delim}$;\5 -$\\{scanner\_status}\K\\{absorbing}$;\5 -$\|p\K\\{hold\_head}$;\5 -$\\{balance}\K1$;\5 -$\\{link}(\\{hold\_head})\K\\{null}$;\6 -\~ \1\&{loop}\ \&{begin} \37\\{get\_next};\6 -\&{if} $\\{l\_delim}=0$ \1\&{then}\5 -\X732:Adjust the balance for an undelimited argument; \&{goto} \\{done} if done% -\X\6 -\4\&{else} \X731:Adjust the balance for a delimited argument; \&{goto} \\{done} -if done\X;\2\6 -$\\{link}(\|p)\K\\{cur\_tok}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{cur\_exp}\K\\{link}(\\{hold\_head})$;\5 -$\\{cur\_type}\K\\{token\_list}$;\5 -$\\{scanner\_status}\K\\{normal}$;\6 -\&{end};\par -\U720.\fi - -\M731. \P$\X731:Adjust the balance for a delimited argument; \&{goto} \\{done} -if done\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_cmd}=\\{right\_delimiter}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{cur\_mod}=\\{l\_delim}$ \1\&{then}\6 -\&{begin} \37$\\{decr}(\\{balance})$;\6 -\&{if} $\\{balance}=0$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{left\_delimiter}$ \1\&{then}\6 -\&{if} $\\{cur\_mod}=\\{r\_delim}$ \1\&{then}\5 -$\\{incr}(\\{balance})$;\2\2\2\6 -\&{end}\par -\U730.\fi - -\M732. \P$\X732:Adjust the balance for an undelimited argument; \&{goto} % -\\{done} if done\X\S$\6 -\&{begin} \37\&{if} $\\{end\_of\_statement}$ \1\&{then}\C{$\\{cur\_cmd}=% -\\{semicolon}$, \\{end\_group}, or \\{stop}}\6 -\&{begin} \37\&{if} $\\{balance}=1$ \1\&{then}\5 -\&{goto} \37\\{done}\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{end\_group}$ \1\&{then}\5 -$\\{decr}(\\{balance})$;\2\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{begin\_group}$ \1\&{then}\5 -$\\{incr}(\\{balance})$;\2\2\6 -\&{end}\par -\U730.\fi - -\M733. \P$\X733:Scan undelimited argument(s)\X\S$\6 -\&{begin} \37\&{if} $\\{info}(\|r)<\\{text\_macro}$ \1\&{then}\6 -\&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{info}(\|r)\I\\{suffix\_macro}$ \1\&{then}\6 -\&{if} $(\\{cur\_cmd}=\\{equals})\V(\\{cur\_cmd}=\\{assignment})$ \1\&{then}\5 -\\{get\_x\_next};\2\2\6 -\&{end};\2\6 -\&{case} $\\{info}(\|r)$ \1\&{of}\6 -\4\\{primary\_macro}: \37\\{scan\_primary};\6 -\4\\{secondary\_macro}: \37\\{scan\_secondary};\6 -\4\\{tertiary\_macro}: \37\\{scan\_tertiary};\6 -\4\\{expr\_macro}: \37\\{scan\_expression};\6 -\4\\{of\_macro}: \37\X734:Scan an expression followed by `\&{of} $% -\langle$primary$\rangle$'\X;\6 -\4\\{suffix\_macro}: \37\X735:Scan a suffix with optional delimiters\X;\6 -\4\\{text\_macro}: \37$\\{scan\_text\_arg}(0,\390)$;\2\6 -\&{end};\C{there are no other cases}\6 -\\{back\_input};\5 -\X728:Append the current expression to \\{arg\_list}\X;\6 -\&{end}\par -\U725.\fi - -\M734. \P$\X734:Scan an expression followed by `\&{of} $\langle$primary$% -\rangle$'\X\S$\6 -\&{begin} \37\\{scan\_expression};\5 -$\|p\K\\{get\_avail}$;\5 -$\\{info}(\|p)\K\\{stash\_cur\_exp}$;\6 -\&{if} $\\{internal}[\\{tracing\_macros}]>0$ \1\&{then}\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_arg}(\\{info}(\|p),\39\|n,\390)$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end};\2\6 -\&{if} $\\{arg\_list}=\\{null}$ \1\&{then}\5 -$\\{arg\_list}\K\|p$\ \&{else} $\\{link}(\\{tail})\K\|p$;\2\6 -$\\{tail}\K\|p$;\5 -$\\{incr}(\|n)$;\6 -\&{if} $\\{cur\_cmd}\I\\{of\_token}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"of"})$;\5 -$\\{print}(\.{"\ for\ "})$;\5 -$\\{print\_macro\_name}(\\{arg\_list},\39\\{macro\_name})$;\5 -$\\{help1}(\.{"I\'ve\ got\ the\ first\ argument;\ will\ look\ now\ for\ the\ -other."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -\\{scan\_primary};\6 -\&{end}\par -\U733.\fi - -\M735. \P$\X735:Scan a suffix with optional delimiters\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_cmd}\I\\{left\_delimiter}$ \1\&{then}\5 -$\\{l\_delim}\K\\{null}$\6 -\4\&{else} \&{begin} \37$\\{l\_delim}\K\\{cur\_sym}$;\5 -$\\{r\_delim}\K\\{cur\_mod}$;\5 -\\{get\_x\_next};\6 -\&{end};\2\6 -\\{scan\_suffix};\6 -\&{if} $\\{l\_delim}\I\\{null}$ \1\&{then}\6 -\&{begin} \37\&{if} $(\\{cur\_cmd}\I\\{right\_delimiter})\V(\\{cur\_mod}\I\\{l% -\_delim})$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\\{text}(\\{r\_delim}))$;\5 -$\\{help2}(\.{"I\'ve\ gotten\ to\ the\ end\ of\ the\ macro\ parameter\ -list."})$\6 -$(\.{"You\ might\ want\ to\ delete\ some\ tokens\ before\ continuing."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\\{get\_x\_next};\6 -\&{end};\2\6 -\&{end}\par -\U733.\fi - -\M736. Before we put a new token list on the input stack, it is wise to clean -off -all token lists that have recently been depleted. Then a user macro that ends -with a call to itself will not require unbounded stack space. - -\Y\P$\4\X736:Feed the arguments and replacement text to the scanner\X\S$\6 -\&{while} $\\{token\_state}\W(\\{loc}=\\{null})$ \1\&{do}\5 -\\{end\_token\_list};\C{conserve stack space}\2\6 -\&{if} $\\{param\_ptr}+\|n>\\{max\_param\_stack}$ \1\&{then}\6 -\&{begin} \37$\\{max\_param\_stack}\K\\{param\_ptr}+\|n$;\6 -\&{if} $\\{max\_param\_stack}>\\{param\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"parameter\ stack\ size"},\39\\{param\_size})$;\2\6 -\&{end};\2\6 -$\\{begin\_token\_list}(\\{def\_ref},\39\\{macro})$;\5 -$\\{name}\K\\{macro\_name}$;\5 -$\\{loc}\K\|r$;\6 -\&{if} $\|n>0$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{arg\_list}$;\6 -\1\&{repeat} \37$\\{param\_stack}[\\{param\_ptr}]\K\\{info}(\|p)$;\5 -$\\{incr}(\\{param\_ptr})$;\5 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\|p=\\{null}$;\2\6 -$\\{flush\_list}(\\{arg\_list})$;\6 -\&{end}\2\par -\U720.\fi - -\M737. It's sometimes necessary to put a single argument onto \\{param\_stack}. -The \\{stack\_argument} subroutine does this. - -\Y\P\4\&{procedure}\1\ \37$\\{stack\_argument}(\|p:\\{pointer})$;\2\6 -\&{begin} \37\&{if} $\\{param\_ptr}=\\{max\_param\_stack}$ \1\&{then}\6 -\&{begin} \37$\\{incr}(\\{max\_param\_stack})$;\6 -\&{if} $\\{max\_param\_stack}>\\{param\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"parameter\ stack\ size"},\39\\{param\_size})$;\2\6 -\&{end};\2\6 -$\\{param\_stack}[\\{param\_ptr}]\K\|p$;\5 -$\\{incr}(\\{param\_ptr})$;\6 -\&{end};\par -\fi - -\N738. \[36] Conditional processing. -Let's consider now the way \&{if} commands are handled. - -Conditions can be inside conditions, and this nesting has a stack -that is independent of other stacks. -Four global variables represent the top of the condition stack: -\\{cond\_ptr} points to pushed-down entries, if~any; \\{cur\_if} tells whether -we are processing \&{if} or \&{elseif}; \\{if\_limit} specifies -the largest code of a \\{fi\_or\_else} command that is syntactically legal; -and \\{if\_line} is the line number at which the current conditional began. - -If no conditions are currently in progress, the condition stack has the -special state $\\{cond\_ptr}=\\{null}$, $\\{if\_limit}=\\{normal}$, $\\{cur% -\_if}=0$, $\\{if\_line}=0$. -Otherwise \\{cond\_ptr} points to a two-word node; the \\{type}, \\{name% -\_type}, and -\\{link} fields of the first word contain \\{if\_limit}, \\{cur\_if}, and -\\{cond\_ptr} at the next level, and the second word contains the -corresponding \\{if\_line}. - -\Y\P\D \37$\\{if\_node\_size}=2$\C{number of words in stack entry for -conditionals}\par -\P\D \37$\\{if\_line\_field}(\#)\S\\{mem}[\#+1].\\{int}$\par -\P\D \37$\\{if\_code}=1$\C{code for \&{if} being evaluated}\par -\P\D \37$\\{fi\_code}=2$\C{code for \&{fi}}\par -\P\D \37$\\{else\_code}=3$\C{code for \&{else}}\par -\P\D \37$\\{else\_if\_code}=4$\C{code for \&{elseif}}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{cond\_ptr}: \37\\{pointer};\C{top of the condition stack}\6 -\4\\{if\_limit}: \37$\\{normal}\to\\{else\_if\_code}$;\C{upper bound on \\{fi% -\_or\_else} codes}\6 -\4\\{cur\_if}: \37\\{small\_number};\C{type of conditional being worked on}\6 -\4\\{if\_line}: \37\\{integer};\C{line where that conditional began}\par -\fi - -\M739. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{cond\_ptr}\K\\{null}$;\5 -$\\{if\_limit}\K\\{normal}$;\5 -$\\{cur\_if}\K0$;\5 -$\\{if\_line}\K0$;\par -\fi - -\M740. \P$\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}% -\S$\6 -$\\{primitive}(\.{"if"},\39\\{if\_test},\39\\{if\_code})$;\6 -$\\{primitive}(\.{"fi"},\39\\{fi\_or\_else},\39\\{fi\_code})$;\5 -$\\{eqtb}[\\{frozen\_fi}]\K\\{eqtb}[\\{cur\_sym}]$;\6 -$\\{primitive}(\.{"else"},\39\\{fi\_or\_else},\39\\{else\_code})$;\6 -$\\{primitive}(\.{"elseif"},\39\\{fi\_or\_else},\39\\{else\_if\_code})$;\par -\fi - -\M741. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4$\\{if\_test},\39\\{fi\_or\_else}$: \37\&{case} $\|m$ \1\&{of}\6 -\4\\{if\_code}: \37$\\{print}(\.{"if"})$;\6 -\4\\{fi\_code}: \37$\\{print}(\.{"fi"})$;\6 -\4\\{else\_code}: \37$\\{print}(\.{"else"})$;\6 -\4\&{othercases} \37$\\{print}(\.{"elseif"})$\2\6 -\&{endcases};\par -\fi - -\M742. Here is a procedure that ignores text until coming to an \&{elseif}, -\&{else}, or \&{fi} at level zero of $\&{if}\ldots\&{fi}$ -nesting. After it has acted, \\{cur\_mod} will indicate the token that -was found. - -\MF's smallest two command codes are \\{if\_test} and \\{fi\_or\_else}; this -makes the skipping process a bit simpler. - -\Y\P\4\&{procedure}\1\ \37\\{pass\_text};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|l: \37\\{integer};\2\6 -\&{begin} \37$\\{scanner\_status}\K\\{skipping}$;\5 -$\|l\K0$;\5 -$\\{warning\_info}\K\\{line}$;\6 -\~ \1\&{loop}\ \&{begin} \37\\{get\_next};\6 -\&{if} $\\{cur\_cmd}\L\\{fi\_or\_else}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}<\\{fi\_or\_else}$ \1\&{then}\5 -$\\{incr}(\|l)$\6 -\4\&{else} \&{begin} \37\&{if} $\|l=0$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{cur\_mod}=\\{fi\_code}$ \1\&{then}\5 -$\\{decr}(\|l)$;\2\6 -\&{end}\2\6 -\4\&{else} \X743:Decrease the string reference count, if the current token is a -string\X;\2\6 -\&{end};\2\6 -\4\\{done}: \37$\\{scanner\_status}\K\\{normal}$;\6 -\&{end};\par -\fi - -\M743. \P$\X743:Decrease the string reference count, if the current token is a -string\X\S$\6 -\&{if} $\\{cur\_cmd}=\\{string\_token}$ \1\&{then}\5 -$\\{delete\_str\_ref}(\\{cur\_mod})$\2\par -\Us83, 742, 991\ETs1016.\fi - -\M744. When we begin to process a new \&{if}, we set $\\{if\_limit}\K\\{if% -\_code}$; then -if \&{elseif} or \&{else} or \&{fi} occurs before the current \&{if} -condition has been evaluated, a colon will be inserted. -A construction like `\.{if fi}' would otherwise get \MF\ confused. - -\Y\P$\4\X744:Push the condition stack\X\S$\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{if\_node\_size})$;\5 -$\\{link}(\|p)\K\\{cond\_ptr}$;\5 -$\\{type}(\|p)\K\\{if\_limit}$;\5 -$\\{name\_type}(\|p)\K\\{cur\_if}$;\5 -$\\{if\_line\_field}(\|p)\K\\{if\_line}$;\5 -$\\{cond\_ptr}\K\|p$;\5 -$\\{if\_limit}\K\\{if\_code}$;\5 -$\\{if\_line}\K\\{line}$;\5 -$\\{cur\_if}\K\\{if\_code}$;\6 -\&{end}\par -\U748.\fi - -\M745. \P$\X745:Pop the condition stack\X\S$\6 -\&{begin} \37$\|p\K\\{cond\_ptr}$;\5 -$\\{if\_line}\K\\{if\_line\_field}(\|p)$;\5 -$\\{cur\_if}\K\\{name\_type}(\|p)$;\5 -$\\{if\_limit}\K\\{type}(\|p)$;\5 -$\\{cond\_ptr}\K\\{link}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{if\_node\_size})$;\6 -\&{end}\par -\Us748, 749\ETs751.\fi - -\M746. Here's a procedure that changes the \\{if\_limit} code corresponding to -a given value of \\{cond\_ptr}. - -\Y\P\4\&{procedure}\1\ \37$\\{change\_if\_limit}(\|l:\\{small\_number};\,\35% -\|p:\\{pointer})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|q: \37\\{pointer};\2\6 -\&{begin} \37\&{if} $\|p=\\{cond\_ptr}$ \1\&{then}\5 -$\\{if\_limit}\K\|l$\C{that's the easy case}\6 -\4\&{else} \&{begin} \37$\|q\K\\{cond\_ptr}$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|q=\\{null}$ \1\&{then}\5 -$\\{confusion}(\.{"if"})$;\2\6 -\&{if} $\\{link}(\|q)=\|p$ \1\&{then}\6 -\&{begin} \37$\\{type}(\|q)\K\|l$;\5 -\&{return};\6 -\&{end};\2\6 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M747. The user is supposed to put colons into the proper parts of conditional -statements. Therefore, \MF\ has to check for their presence. - -\Y\P\4\&{procedure}\1\ \37\\{check\_colon};\2\6 -\&{begin} \37\&{if} $\\{cur\_cmd}\I\\{colon}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{":"})$;\6 -$\\{help2}(\.{"There\ should\'ve\ been\ a\ colon\ after\ the\ condition."})$\6 -$(\.{"I\ shall\ pretend\ that\ one\ was\ there."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M748. A condition is started when the \\{get\_x\_next} procedure encounters -an \\{if\_test} command; in that case \\{get\_x\_next} calls \\{conditional}, -which is a recursive procedure. - -\Y\P\4\&{procedure}\1\ \37\\{conditional};\6 -\4\&{label} \37$\\{exit},\39\\{done},\39\\{reswitch},\39\\{found}$;\6 -\4\&{var} \37\\{save\_cond\_ptr}: \37\\{pointer};\C{\\{cond\_ptr} corresponding -to this conditional}\6 -\\{new\_if\_limit}: \37$\\{fi\_code}\to\\{else\_if\_code}$;\C{future value of % -\\{if\_limit}}\6 -\|p: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37\X744:Push the condition stack\X;\ $\\{save\_cond\_ptr}\K\\{cond% -\_ptr}$;\6 -\4\\{reswitch}: \37\\{get\_boolean};\5 -$\\{new\_if\_limit}\K\\{else\_if\_code}$;\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{unity}$ \1\&{then}\5 -\X750:Display the boolean value of \\{cur\_exp}\X;\2\6 -\4\\{found}: \37\\{check\_colon};\6 -\&{if} $\\{cur\_exp}=\\{true\_code}$ \1\&{then}\6 -\&{begin} \37$\\{change\_if\_limit}(\\{new\_if\_limit},\39\\{save\_cond% -\_ptr})$;\5 -\&{return};\C{wait for \&{elseif}, \&{else}, or \&{fi}}\6 -\&{end};\2\6 -\X749:Skip to \&{elseif} or \&{else} or \&{fi}, then \&{goto} \\{done}\X;\6 -\4\\{done}: \37$\\{cur\_if}\K\\{cur\_mod}$;\5 -$\\{if\_line}\K\\{line}$;\6 -\&{if} $\\{cur\_mod}=\\{fi\_code}$ \1\&{then}\5 -\X745:Pop the condition stack\X\6 -\4\&{else} \&{if} $\\{cur\_mod}=\\{else\_if\_code}$ \1\&{then}\5 -\&{goto} \37\\{reswitch}\6 -\4\&{else} \&{begin} \37$\\{cur\_exp}\K\\{true\_code}$;\5 -$\\{new\_if\_limit}\K\\{fi\_code}$;\5 -\\{get\_x\_next};\5 -\&{goto} \37\\{found};\6 -\&{end};\2\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M749. In a construction like `\&{if} \&{if} \&{true}: $0=1$: \\{foo} -\&{else}: \\{bar} \&{fi}', the first \&{else} -that we come to after learning that the \&{if} is false is not the -\&{else} we're looking for. Hence the following curious logic is needed. - -\Y\P$\4\X749:Skip to \&{elseif} or \&{else} or \&{fi}, then \&{goto} \\{done}\X% -\S$\6 -\~ \1\&{loop}\ \&{begin} \37\\{pass\_text};\6 -\&{if} $\\{cond\_ptr}=\\{save\_cond\_ptr}$ \1\&{then}\5 -\&{goto} \37\\{done}\6 -\4\&{else} \&{if} $\\{cur\_mod}=\\{fi\_code}$ \1\&{then}\5 -\X745:Pop the condition stack\X;\2\2\6 -\&{end}\2\par -\U748.\fi - -\M750. \P$\X750:Display the boolean value of \\{cur\_exp}\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\6 -\&{if} $\\{cur\_exp}=\\{true\_code}$ \1\&{then}\5 -$\\{print}(\.{"\{true\}"})$\ \&{else} $\\{print}(\.{"\{false\}"})$;\2\6 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U748.\fi - -\M751. The processing of conditionals is complete except for the following -code, which is actually part of \\{get\_x\_next}. It comes into play when -\&{elseif}, \&{else}, or \&{fi} is scanned. - -\Y\P$\4\X751:Terminate the current conditional and skip to \&{fi}\X\S$\6 -\&{if} $\\{cur\_mod}>\\{if\_limit}$ \1\&{then}\6 -\&{if} $\\{if\_limit}=\\{if\_code}$ \1\&{then}\C{condition not yet evaluated}\6 -\&{begin} \37$\\{missing\_err}(\.{":"})$;\5 -\\{back\_input};\5 -$\\{cur\_sym}\K\\{frozen\_colon}$;\5 -\\{ins\_error};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Extra\ "})$;\5 -$\\{print\_cmd\_mod}(\\{fi\_or\_else},\39\\{cur\_mod})$;\5 -$\\{help1}(\.{"I\'m\ ignoring\ this;\ it\ doesn\'t\ match\ any\ if."})$;\5 -\\{error};\6 -\&{end}\2\6 -\4\&{else} \&{begin} \37\&{while} $\\{cur\_mod}\I\\{fi\_code}$ \1\&{do}\5 -\\{pass\_text};\C{skip to \&{fi}}\2\6 -\X745:Pop the condition stack\X;\6 -\&{end}\2\par -\U707.\fi - -\N752. \[37] Iterations. -To bring our treatment of \\{get\_x\_next} to a close, we need to consider what -\MF\ does when it sees \&{for}, \&{forsuffixes}, and \&{forever}. - -There's a global variable \\{loop\_ptr} that keeps track of the \&{for} loops -that are currently active. If $\\{loop\_ptr}=\\{null}$, no loops are in -progress; -otherwise $\\{info}(\\{loop\_ptr})$ points to the iterative text of the current -(innermost) loop, and $\\{link}(\\{loop\_ptr})$ points to the data for any -other -loops that enclose the current one. - -A loop-control node also has two other fields, called \\{loop\_type} and -\\{loop\_list}, whose contents depend on the type of loop: - -\yskip\indent$\\{loop\_type}(\\{loop\_ptr})=\\{null}$ means that $\\{loop% -\_list}(\\{loop\_ptr})$ -points to a list of one-word nodes whose \\{info} fields point to the -remaining argument values of a suffix list and expression list. - -\yskip\indent$\\{loop\_type}(\\{loop\_ptr})=\\{void}$ means that the current -loop is -`\&{forever}'. - -\yskip\indent$\\{loop\_type}(\\{loop\_ptr})=\|p>\\{void}$ means that $% -\\{value}(\|p)$, -$\\{step\_size}(\|p)$, and $\\{final\_value}(\|p)$ contain the data for an -arithmetic -progression. - -\yskip\noindent In the latter case, \|p points to a ``progression node'' -whose first word is not used. (No value could be stored there because the -link field of words in the dynamic memory area cannot be arbitrary.) - -\Y\P\D \37$\\{loop\_list\_loc}(\#)\S\#+1$\C{where the \\{loop\_list} field -resides}\par -\P\D \37$\\{loop\_type}(\#)\S\\{info}(\\{loop\_list\_loc}(\#))$\C{the type of % -\&{for} loop}\par -\P\D \37$\\{loop\_list}(\#)\S\\{link}(\\{loop\_list\_loc}(\#))$\C{the remaining -list elements}\par -\P\D \37$\\{loop\_node\_size}=2$\C{the number of words in a loop control node}% -\par -\P\D \37$\\{progression\_node\_size}=4$\C{the number of words in a progression -node}\par -\P\D \37$\\{step\_size}(\#)\S\\{mem}[\#+2].\\{sc}$\C{the step size in an -arithmetic progression}\par -\P\D \37$\\{final\_value}(\#)\S\\{mem}[\#+3].\\{sc}$\C{the final value in an -arithmetic progression}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{loop\_ptr}: \37\\{pointer};\C{top of the loop-control-node stack}\par -\fi - -\M753. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{loop\_ptr}\K\\{null}$;\par -\fi - -\M754. If the expressions that define an arithmetic progression in -a \&{for} loop don't have known numeric values, the \\{bad\_for} -subroutine screams at the user. - -\Y\P\4\&{procedure}\1\ \37$\\{bad\_for}(\|s:\\{str\_number})$;\2\6 -\&{begin} \37$\\{disp\_err}(\\{null},\39\.{"Improper\ "})$;\C{show the bad -expression above the message}\6 -$\\{print}(\|s)$;\5 -$\\{print}(\.{"\ has\ been\ replaced\ by\ 0"})$;\5 -$\\{help4}(\.{"When\ you\ say\ \`for\ x=a\ step\ b\ until\ c\',"})$\6 -$(\.{"the\ initial\ value\ \`a\'\ and\ the\ step\ size\ \`b\'"})$\6 -$(\.{"and\ the\ final\ value\ \`c\'\ must\ have\ known\ numeric\ values."})$\6 -$(\.{"I\'m\ zeroing\ this\ one.\ Proceed,\ with\ fingers\ crossed."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\par -\fi - -\M755. Here's what \MF\ does when \&{for}, \&{forsuffixes}, or \&{forever} -has just been scanned. (This code requires slight familiarity with -expression-parsing routines that we have not yet discussed; but it seems -to belong in the present part of the program, even though the author -didn't write it until later. The reader may wish to come back to it.) - -\Y\P\4\&{procedure}\1\ \37\\{begin\_iteration};\6 -\4\&{label} \37$\\{continue},\39\\{done},\39\\{found}$;\6 -\4\&{var} \37\|m: \37\\{halfword};\C{\\{expr\_base} (\&{for}) or \\{suffix% -\_base} (\&{forsuffixes})}\6 -\|n: \37\\{halfword};\C{hash address of the current symbol}\6 -$\|p,\39\|q,\39\|s,\39\\{pp}$: \37\\{pointer};\C{link manipulation registers}\2% -\6 -\&{begin} \37$\|m\K\\{cur\_mod}$;\5 -$\|n\K\\{cur\_sym}$;\5 -$\|s\K\\{get\_node}(\\{loop\_node\_size})$;\6 -\&{if} $\|m=\\{start\_forever}$ \1\&{then}\6 -\&{begin} \37$\\{loop\_type}(\|s)\K\\{void}$;\5 -$\|p\K\\{null}$;\5 -\\{get\_x\_next};\5 -\&{goto} \37\\{found};\6 -\&{end};\2\6 -\\{get\_symbol};\5 -$\|p\K\\{get\_node}(\\{token\_node\_size})$;\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\5 -$\\{value}(\|p)\K\|m$;\6 -\\{get\_x\_next};\6 -\&{if} $(\\{cur\_cmd}\I\\{equals})\W(\\{cur\_cmd}\I\\{assignment})$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"="})$;\6 -$\\{help3}(\.{"The\ next\ thing\ in\ this\ loop\ should\ have\ been\ \`=\'\ or\ -\`:=\'."})$\6 -$(\.{"But\ don\'t\ worry;\ I\'ll\ pretend\ that\ an\ equals\ sign"})$\6 -$(\.{"was\ present,\ and\ I\'ll\ look\ for\ the\ values\ next."})$;\6 -\\{back\_error};\6 -\&{end};\2\6 -\X764:Scan the values to be used in the loop\X;\6 -\4\\{found}: \37\X756:Check for the presence of a colon\X;\6 -\X758:Scan the loop text and put it on the loop control stack\X;\6 -\\{resume\_iteration};\6 -\&{end};\par -\fi - -\M756. \P$\X756:Check for the presence of a colon\X\S$\6 -\&{if} $\\{cur\_cmd}\I\\{colon}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{":"})$;\6 -$\\{help3}(\.{"The\ next\ thing\ in\ this\ loop\ should\ have\ been\ a\ \`:% -\'."})$\6 -$(\.{"So\ I\'ll\ pretend\ that\ a\ colon\ was\ present;"})$\6 -$(\.{"everything\ from\ here\ to\ \`endfor\'\ will\ be\ iterated."})$;\5 -\\{back\_error};\6 -\&{end}\2\par -\U755.\fi - -\M757. We append a special \\{frozen\_repeat\_loop} token in place of the -`\&{endfor}' at the end of the loop. This will come through \MF's scanner -at the proper time to cause the loop to be repeated. - -(If the user tries some shenanigan like `\&{for} $\ldots$ \&{let} \&{endfor}', -he will be foiled by the \\{get\_symbol} routine, which keeps frozen -tokens unchanged. Furthermore the \\{frozen\_repeat\_loop} is an \&{outer} -token, so it won't be lost accidentally.) - -\fi - -\M758. \P$\X758:Scan the loop text and put it on the loop control stack\X\S$\6 -$\|q\K\\{get\_avail}$;\5 -$\\{info}(\|q)\K\\{frozen\_repeat\_loop}$;\5 -$\\{scanner\_status}\K\\{loop\_defining}$;\5 -$\\{warning\_info}\K\|n$;\5 -$\\{info}(\|s)\K\\{scan\_toks}(\\{iteration},\39\|p,\39\|q,\390)$;\5 -$\\{scanner\_status}\K\\{normal}$;\6 -$\\{link}(\|s)\K\\{loop\_ptr}$;\5 -$\\{loop\_ptr}\K\|s$\par -\U755.\fi - -\M759. \P$\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}% -\S$\6 -$\\{eq\_type}(\\{frozen\_repeat\_loop})\K\\{repeat\_loop}+\\{outer\_tag}$;\5 -$\\{text}(\\{frozen\_repeat\_loop})\K\.{"\ ENDFOR"}$;\par -\fi - -\M760. The loop text is inserted into \MF's scanning apparatus by the -\\{resume\_iteration} routine. - -\Y\P\4\&{procedure}\1\ \37\\{resume\_iteration};\6 -\4\&{label} \37$\\{not\_found},\39\\{exit}$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{link registers}\2\6 -\&{begin} \37$\|p\K\\{loop\_type}(\\{loop\_ptr})$;\6 -\&{if} $\|p>\\{void}$ \1\&{then}\C{\|p points to a progression node}\6 -\&{begin} \37$\\{cur\_exp}\K\\{value}(\|p)$;\6 -\&{if} $\X761:The arithmetic progression has ended\X$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{cur\_type}\K\\{known}$;\5 -$\|q\K\\{stash\_cur\_exp}$;\C{make \|q an \&{expr} argument}\6 -$\\{value}(\|p)\K\\{cur\_exp}+\\{step\_size}(\|p)$;\C{set $\\{value}(\|p)$ for -the next iteration}\6 -\&{end}\6 -\4\&{else} \&{if} $\|p<\\{void}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{loop\_list}(\\{loop\_ptr})$;\6 -\&{if} $\|p=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{loop\_list}(\\{loop\_ptr})\K\\{link}(\|p)$;\5 -$\|q\K\\{info}(\|p)$;\5 -$\\{free\_avail}(\|p)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{begin\_token\_list}(\\{info}(\\{loop\_ptr}),\39% -\\{forever\_text})$;\5 -\&{return};\6 -\&{end};\2\2\6 -$\\{begin\_token\_list}(\\{info}(\\{loop\_ptr}),\39\\{loop\_text})$;\5 -$\\{stack\_argument}(\|q)$;\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{unity}$ \1\&{then}\5 -\X762:Trace the start of a loop\X;\2\6 -\&{return};\6 -\4\\{not\_found}: \37\\{stop\_iteration};\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M761. \P$\X761:The arithmetic progression has ended\X\S$\6 -$((\\{step\_size}(\|p)>0)\W(\\{cur\_exp}>\\{final\_value}(\|p)))\V\30((\\{step% -\_size}(\|p)<0)\W(\\{cur\_exp}<\\{final\_value}(\|p)))$\par -\U760.\fi - -\M762. \P$\X762:Trace the start of a loop\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{loop\ value="})$;\6 -\&{if} $(\|q\I\\{null})\W(\\{link}(\|q)=\\{void})$ \1\&{then}\5 -$\\{print\_exp}(\|q,\391)$\6 -\4\&{else} $\\{show\_token\_list}(\|q,\39\\{null},\3950,\390)$;\2\6 -$\\{print\_char}(\.{"\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U760.\fi - -\M763. A level of loop control disappears when \\{resume\_iteration} has -decided -not to resume, or when an \&{exitif} construction has removed the loop text -from the input stack. - -\Y\P\4\&{procedure}\1\ \37\\{stop\_iteration};\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{the usual}\2\6 -\&{begin} \37$\|p\K\\{loop\_type}(\\{loop\_ptr})$;\6 -\&{if} $\|p>\\{void}$ \1\&{then}\5 -$\\{free\_node}(\|p,\39\\{progression\_node\_size})$\6 -\4\&{else} \&{if} $\|p<\\{void}$ \1\&{then}\6 -\&{begin} \37$\|q\K\\{loop\_list}(\\{loop\_ptr})$;\6 -\&{while} $\|q\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\|p\K\\{info}(\|q)$;\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\6 -\&{if} $\\{link}(\|p)=\\{void}$ \1\&{then}\C{it's an \&{expr} parameter}\6 -\&{begin} \37$\\{recycle\_value}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end}\6 -\4\&{else} $\\{flush\_token\_list}(\|p)$;\C{it's a \&{suffix} or \&{text} -parameter}\2\2\6 -$\|p\K\|q$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{free\_avail}(\|p)$;\6 -\&{end};\2\6 -\&{end};\2\2\6 -$\|p\K\\{loop\_ptr}$;\5 -$\\{loop\_ptr}\K\\{link}(\|p)$;\5 -$\\{flush\_token\_list}(\\{info}(\|p))$;\5 -$\\{free\_node}(\|p,\39\\{loop\_node\_size})$;\6 -\&{end};\par -\fi - -\M764. Now that we know all about loop control, we can finish up -the missing portion of \\{begin\_iteration} and we'll be done. - -The following code is performed after the `\.=' has been scanned in -a \&{for} construction (if $\|m=\\{expr\_base}$) or a \&{forsuffixes} -construction -(if $\|m=\\{suffix\_base}$). - -\Y\P$\4\X764:Scan the values to be used in the loop\X\S$\6 -$\\{loop\_type}(\|s)\K\\{null}$;\5 -$\|q\K\\{loop\_list\_loc}(\|s)$;\5 -$\\{link}(\|q)\K\\{null}$;\C{$\\{link}(\|q)=\\{loop\_list}(\|s)$}\6 -\1\&{repeat} \37\\{get\_x\_next};\6 -\&{if} $\|m\I\\{expr\_base}$ \1\&{then}\5 -\\{scan\_suffix}\6 -\4\&{else} \&{begin} \37\&{if} $\\{cur\_cmd}\G\\{colon}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}\L\\{comma}$ \1\&{then}\5 -\&{goto} \37\\{continue};\2\2\6 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}=\\{step\_token}$ \1\&{then}\6 -\&{if} $\|q=\\{loop\_list\_loc}(\|s)$ \1\&{then}\5 -\X765:Prepare for step-until construction and \&{goto} \\{done}\X;\2\2\6 -$\\{cur\_exp}\K\\{stash\_cur\_exp}$;\6 -\&{end};\2\6 -$\\{link}(\|q)\K\\{get\_avail}$;\5 -$\|q\K\\{link}(\|q)$;\5 -$\\{info}(\|q)\K\\{cur\_exp}$;\5 -$\\{cur\_type}\K\\{vacuous}$;\6 -\4\\{continue}: \37\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$;\2\6 -\4\\{done}: \37\par -\U755.\fi - -\M765. \P$\X765:Prepare for step-until construction and \&{goto} \\{done}\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -$\\{bad\_for}(\.{"initial\ value"})$;\2\6 -$\\{pp}\K\\{get\_node}(\\{progression\_node\_size})$;\5 -$\\{value}(\\{pp})\K\\{cur\_exp}$;\6 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -$\\{bad\_for}(\.{"step\ size"})$;\2\6 -$\\{step\_size}(\\{pp})\K\\{cur\_exp}$;\6 -\&{if} $\\{cur\_cmd}\I\\{until\_token}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"until"})$;\6 -$\\{help2}(\.{"I\ assume\ you\ meant\ to\ say\ \`until\'\ after\ \`step\'."})$\6 -$(\.{"So\ I\'ll\ look\ for\ the\ final\ value\ and\ colon\ next."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -$\\{bad\_for}(\.{"final\ value"})$;\2\6 -$\\{final\_value}(\\{pp})\K\\{cur\_exp}$;\5 -$\\{loop\_type}(\|s)\K\\{pp}$;\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U764.\fi - -\N766. \[38] File names. -It's time now to fret about file names. Besides the fact that different -operating systems treat files in different ways, we must cope with the -fact that completely different naming conventions are used by different -groups of people. The following programs show what is required for one -particular operating system; similar routines for other systems are not -difficult to devise. - -\MF\ assumes that a file name has three parts: the name proper; its -``extension''; and a ``file area'' where it is found in an external file -system. The extension of an input file is assumed to be -`\.{.mf}' unless otherwise specified; it is `\.{.log}' on the -transcript file that records each run of \MF; it is `\.{.tfm}' on the font -metric files that describe characters in the fonts \MF\ creates; it is -`\.{.gf}' on the output files that specify generic font information; and it -is `\.{.base}' on the base files written by \.{INIMF} to initialize \MF. -The file area can be arbitrary on input files, but files are usually -output to the user's current area. If an input file cannot be -found on the specified area, \MF\ will look for it on a special system -area; this special area is intended for commonly used input files. - -Simple uses of \MF\ refer only to file names that have no explicit -extension or area. For example, a person usually says `\.{input} \.{cmr10}' -instead of `\.{input} \.{cmr10.new}'. Simple file -names are best, because they make the \MF\ source files portable; -whenever a file name consists entirely of letters and digits, it should be -treated in the same way by all implementations of \MF. However, users -need the ability to refer to other files in their environment, especially -when responding to error messages concerning unopenable files; therefore -we want to let them use the syntax that appears in their favorite -operating system. - -\fi - -\M767. \MF\ uses the same conventions that have proved to be satisfactory for -\TeX. In order to isolate the system-dependent aspects of file names, the -system-independent parts of \MF\ are expressed in terms -of three system-dependent -procedures called \\{begin\_name}, \\{more\_name}, and \\{end\_name}. In -essence, if the user-specified characters of the file name are $c_1\ldots c_n$, -the system-independent driver program does the operations -$$\\{begin\_name};\,\\{more\_name}(c_1);\,\ldots\,;\\{more\_name}(c_n); -\,\\{end\_name}.$$ -These three procedures communicate with each other via global variables. -Afterwards the file name will appear in the string pool as three strings -called \\{cur\_name}\penalty10000\hskip-.05em, -\\{cur\_area}, and \\{cur\_ext}; the latter two are null (i.e., -\.{""}), unless they were explicitly specified by the user. - -Actually the situation is slightly more complicated, because \MF\ needs -to know when the file name ends. The \\{more\_name} routine is a function -(with side effects) that returns \\{true} on the calls \\{more\_name}$(c_1)$, -\dots, \\{more\_name}$(c_{n-1})$. The final call \\{more\_name}$(c_n)$ -returns \\{false}; or, it returns \\{true} and $c_n$ is the last character -on the current input line. In other words, -\\{more\_name} is supposed to return \\{true} unless it is sure that the -file name has been completely scanned; and \\{end\_name} is supposed to be able -to finish the assembly of \\{cur\_name}, \\{cur\_area}, and \\{cur\_ext} -regardless of -whether $\\{more\_name}(c_n)$ returned \\{true} or \\{false}. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{cur\_name}: \37\\{str\_number};\C{name of file just scanned}\6 -\4\\{cur\_area}: \37\\{str\_number};\C{file area just scanned, or \.{""}}\6 -\4\\{cur\_ext}: \37\\{str\_number};\C{file extension just scanned, or \.{""}}% -\par -\fi - -\M768. The file names we shall deal with for illustrative purposes have the -following structure: If the name contains `\.>' or `\.:', the file area -consists of all characters up to and including the final such character; -otherwise the file area is null. If the remaining file name contains -`\..', the file extension consists of all such characters from the first -remaining `\..' to the end, otherwise the file extension is null. - -We can scan such file names easily by using two global variables that keep -track -of the occurrences of area and extension delimiters: - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{area\_delimiter}: \37\\{pool\_pointer};\C{the most recent `\.>' or `\.:', -if any}\6 -\4\\{ext\_delimiter}: \37\\{pool\_pointer};\C{the relevant `\..', if any}\par -\fi - -\M769. Input files that can't be found in the user's area may appear in a -standard -system area called \\{MF\_area}. -This system area name will, of course, vary from place to place. - -\Y\P\D \37$\\{MF\_area}\S\.{"MFinputs:"}$\par -\fi - -\M770. Here now is the first of the system-dependent routines for file name -scanning. - -\Y\P\4\&{procedure}\1\ \37\\{begin\_name};\2\6 -\&{begin} \37$\\{area\_delimiter}\K0$;\5 -$\\{ext\_delimiter}\K0$;\6 -\&{end};\par -\fi - -\M771. And here's the second. - -\Y\P\4\&{function}\1\ \37$\\{more\_name}(\|c:\\{ASCII\_code})$: \37% -\\{boolean};\2\6 -\&{begin} \37\&{if} $\|c=\.{"\ "}$ \1\&{then}\5 -$\\{more\_name}\K\\{false}$\6 -\4\&{else} \&{begin} \37\&{if} $(\|c=\.{">"})\V(\|c=\.{":"})$ \1\&{then}\6 -\&{begin} \37$\\{area\_delimiter}\K\\{pool\_ptr}$;\5 -$\\{ext\_delimiter}\K0$;\6 -\&{end}\6 -\4\&{else} \&{if} $(\|c=\.{"."})\W(\\{ext\_delimiter}=0)$ \1\&{then}\5 -$\\{ext\_delimiter}\K\\{pool\_ptr}$;\2\2\6 -$\\{str\_room}(1)$;\5 -$\\{append\_char}(\|c)$;\C{contribute \|c to the current string}\6 -$\\{more\_name}\K\\{true}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M772. The third. - -\Y\P\4\&{procedure}\1\ \37\\{end\_name};\2\6 -\&{begin} \37\&{if} $\\{str\_ptr}+3>\\{max\_str\_ptr}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{str\_ptr}+3>\\{max\_strings}$ \1\&{then}\5 -$\\{overflow}(\.{"number\ of\ strings"},\39\\{max\_strings}-\\{init\_str% -\_ptr})$;\2\6 -$\\{max\_str\_ptr}\K\\{str\_ptr}+3$;\6 -\&{end};\2\6 -\&{if} $\\{area\_delimiter}=0$ \1\&{then}\5 -$\\{cur\_area}\K\.{""}$\6 -\4\&{else} \&{begin} \37$\\{cur\_area}\K\\{str\_ptr}$;\5 -$\\{incr}(\\{str\_ptr})$;\5 -$\\{str\_start}[\\{str\_ptr}]\K\\{area\_delimiter}+1$;\6 -\&{end};\2\6 -\&{if} $\\{ext\_delimiter}=0$ \1\&{then}\6 -\&{begin} \37$\\{cur\_ext}\K\.{""}$;\5 -$\\{cur\_name}\K\\{make\_string}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{cur\_name}\K\\{str\_ptr}$;\5 -$\\{incr}(\\{str\_ptr})$;\5 -$\\{str\_start}[\\{str\_ptr}]\K\\{ext\_delimiter}$;\5 -$\\{cur\_ext}\K\\{make\_string}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M773. Conversely, here is a routine that takes three strings and prints a file -name that might have produced them. (The routine is system dependent, because -some operating systems put the file area last instead of first.) - -\Y\P$\4\X57:Basic printing procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_file\_name}(\|n,\39\|a,\39\|e:\\{integer})$;% -\2\6 -\&{begin} \37$\\{slow\_print}(\|a)$;\5 -$\\{slow\_print}(\|n)$;\5 -$\\{slow\_print}(\|e)$;\6 -\&{end};\par -\fi - -\M774. Another system-dependent routine is needed to convert three internal -\MF\ strings -to the \\{name\_of\_file} value that is used to open files. The present code -allows both lowercase and uppercase letters in the file name. - -\Y\P\D \37$\\{append\_to\_name}(\#)\S$\1\6 -\&{begin} \37$\|c\K\#$;\5 -$\\{incr}(\|k)$;\6 -\&{if} $\|k\L\\{file\_name\_size}$ \1\&{then}\5 -$\\{name\_of\_file}[\|k]\K\\{xchr}[\|c]$;\2\6 -\&{end}\2\par -\Y\P\4\&{procedure}\1\ \37$\\{pack\_file\_name}(\|n,\39\|a,\39\|e:\\{str% -\_number})$;\6 -\4\&{var} \37\|k: \37\\{integer};\C{number of positions filled in \\{name\_of% -\_file}}\6 -\|c: \37\\{ASCII\_code};\C{character being packed}\6 -\|j: \37\\{pool\_pointer};\C{index into \\{str\_pool}}\2\6 -\&{begin} \37$\|k\K0$;\6 -\&{for} $\|j\K\\{str\_start}[\|a]\mathrel{\&{to}}\\{str\_start}[\|a+1]-1$ \1% -\&{do}\5 -$\\{append\_to\_name}(\\{so}(\\{str\_pool}[\|j]))$;\2\6 -\&{for} $\|j\K\\{str\_start}[\|n]\mathrel{\&{to}}\\{str\_start}[\|n+1]-1$ \1% -\&{do}\5 -$\\{append\_to\_name}(\\{so}(\\{str\_pool}[\|j]))$;\2\6 -\&{for} $\|j\K\\{str\_start}[\|e]\mathrel{\&{to}}\\{str\_start}[\|e+1]-1$ \1% -\&{do}\5 -$\\{append\_to\_name}(\\{so}(\\{str\_pool}[\|j]))$;\2\6 -\&{if} $\|k\L\\{file\_name\_size}$ \1\&{then}\5 -$\\{name\_length}\K\|k$\ \&{else} $\\{name\_length}\K\\{file\_name\_size}$;\2\6 -\&{for} $\|k\K\\{name\_length}+1\mathrel{\&{to}}\\{file\_name\_size}$ \1\&{do}\5 -$\\{name\_of\_file}[\|k]\K\.{\'\ \'}$;\2\6 -\&{end};\par -\fi - -\M775. A messier routine is also needed, since base file names must be scanned -before \MF's string mechanism has been initialized. We shall use the -global variable \\{MF\_base\_default} to supply the text for default system -areas -and extensions related to base files. - -\Y\P\D \37$\\{base\_default\_length}=18$\C{length of the \\{MF\_base\_default} -string}\par -\P\D \37$\\{base\_area\_length}=8$\C{length of its area part}\par -\P\D \37$\\{base\_ext\_length}=5$\C{length of its `\.{.base}' part}\par -\P\D \37$\\{base\_extension}=\.{".base"}$\C{the extension, as a \.{WEB} -constant}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{MF\_base\_default}: \37\&{packed} \37\&{array} $[1\to\\{base\_default% -\_length}]$ \1\&{of}\5 -\\{char};\2\par -\fi - -\M776. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{MF\_base\_default}\K\.{\'MFbases:plain.base\'}$;\par -\fi - -\M777. \P$\X14:Check the ``constant'' values for consistency\X\mathrel{+}\S$\6 -\&{if} $\\{base\_default\_length}>\\{file\_name\_size}$ \1\&{then}\5 -$\\{bad}\K41$;\2\par -\fi - -\M778. Here is the messy routine that was just mentioned. It sets \\{name\_of% -\_file} -from the first \|n characters of \\{MF\_base\_default}, followed by -$\\{buffer}[\|a\to\|b]$, followed by the last \\{base\_ext\_length} characters -of -\\{MF\_base\_default}. - -We dare not give error messages here, since \MF\ calls this routine before -the \\{error} routine is ready to roll. Instead, we simply drop excess -characters, -since the error will be detected in another way when a strange file name -isn't found. - -\Y\P\4\&{procedure}\1\ \37$\\{pack\_buffered\_name}(\|n:\\{small\_number};\,% -\35\|a,\39\|b:\\{integer})$;\6 -\4\&{var} \37\|k: \37\\{integer};\C{number of positions filled in \\{name\_of% -\_file}}\6 -\|c: \37\\{ASCII\_code};\C{character being packed}\6 -\|j: \37\\{integer};\C{index into \\{buffer} or \\{MF\_base\_default}}\2\6 -\&{begin} \37\&{if} $\|n+\|b-\|a+1+\\{base\_ext\_length}>\\{file\_name\_size}$ % -\1\&{then}\5 -$\|b\K\|a+\\{file\_name\_size}-\|n-1-\\{base\_ext\_length}$;\2\6 -$\|k\K0$;\6 -\&{for} $\|j\K1\mathrel{\&{to}}\|n$ \1\&{do}\5 -$\\{append\_to\_name}(\\{xord}[\\{MF\_base\_default}[\|j]])$;\2\6 -\&{for} $\|j\K\|a\mathrel{\&{to}}\|b$ \1\&{do}\5 -$\\{append\_to\_name}(\\{buffer}[\|j])$;\2\6 -\&{for} $\|j\K\\{base\_default\_length}-\\{base\_ext\_length}+1\mathrel{\&{to}}% -\\{base\_default\_length}$ \1\&{do}\5 -$\\{append\_to\_name}(\\{xord}[\\{MF\_base\_default}[\|j]])$;\2\6 -\&{if} $\|k\L\\{file\_name\_size}$ \1\&{then}\5 -$\\{name\_length}\K\|k$\ \&{else} $\\{name\_length}\K\\{file\_name\_size}$;\2\6 -\&{for} $\|k\K\\{name\_length}+1\mathrel{\&{to}}\\{file\_name\_size}$ \1\&{do}\5 -$\\{name\_of\_file}[\|k]\K\.{\'\ \'}$;\2\6 -\&{end};\par -\fi - -\M779. Here is the only place we use \\{pack\_buffered\_name}. This part of the -program -becomes active when a ``virgin'' \MF\ is trying to get going, just after -the preliminary initialization, or when the user is substituting another -base file by typing `\.\&' after the initial `\.{**}' prompt. The buffer -contains the first line of input in $\\{buffer}[\\{loc}\to(\\{last}-1)]$, where -$\\{loc}<\\{last}$ and $\\{buffer}[\\{loc}]\I\.{"\ "}$. - -\Y\P$\4\X779:Declare the function called \\{open\_base\_file}\X\S$\6 -\4\&{function}\1\ \37\\{open\_base\_file}: \37\\{boolean};\6 -\4\&{label} \37$\\{found},\39\\{exit}$;\6 -\4\&{var} \37\|j: \37$0\to\\{buf\_size}$;\C{the first space after the file -name}\2\6 -\&{begin} \37$\|j\K\\{loc}$;\6 -\&{if} $\\{buffer}[\\{loc}]=\.{"\&"}$ \1\&{then}\6 -\&{begin} \37$\\{incr}(\\{loc})$;\5 -$\|j\K\\{loc}$;\5 -$\\{buffer}[\\{last}]\K\.{"\ "}$;\6 -\&{while} $\\{buffer}[\|j]\I\.{"\ "}$ \1\&{do}\5 -$\\{incr}(\|j)$;\2\6 -$\\{pack\_buffered\_name}(0,\39\\{loc},\39\|j-1)$;\C{try first without the -system file area}\6 -\&{if} $\\{w\_open\_in}(\\{base\_file})$ \1\&{then}\5 -\&{goto} \37\\{found};\2\6 -$\\{pack\_buffered\_name}(\\{base\_area\_length},\39\\{loc},\39\|j-1)$;\C{now -try the system base file area}\6 -\&{if} $\\{w\_open\_in}(\\{base\_file})$ \1\&{then}\5 -\&{goto} \37\\{found};\2\6 -\\{wake\_up\_terminal};\5 -$\\{wterm\_ln}(\.{\'Sorry,\ I\ can\'}\.{\'t\ find\ that\ base;\'},\39\.{\'\ -will\ try\ PLAIN.\'})$;\5 -\\{update\_terminal};\6 -\&{end};\C{now pull out all the stops: try for the system \.{plain} file}\2\6 -$\\{pack\_buffered\_name}(\\{base\_default\_length}-\\{base\_ext\_length},\391,% -\390)$;\6 -\&{if} $\R\\{w\_open\_in}(\\{base\_file})$ \1\&{then}\6 -\&{begin} \37\\{wake\_up\_terminal};\5 -$\\{wterm\_ln}(\.{\'I\ can\'}\.{\'t\ find\ the\ PLAIN\ base\ file!\'})$;\5 -$\\{open\_base\_file}\K\\{false}$;\5 -\&{return};\6 -\&{end};\2\6 -\4\\{found}: \37$\\{loc}\K\|j$;\5 -$\\{open\_base\_file}\K\\{true}$;\6 -\4\\{exit}: \37\&{end};\par -\U1187.\fi - -\M780. Operating systems often make it possible to determine the exact name -(and -possible version number) of a file that has been opened. The following routine, -which simply makes a \MF\ string from the value of \\{name\_of\_file}, should -ideally be changed to deduce the full name of file~\|f, which is the file -most recently opened, if it is possible to do this in a \PASCAL\ program. - -This routine might be called after string memory has overflowed, hence -we dare not use `\\{str\_room}'. - -\Y\P\4\&{function}\1\ \37\\{make\_name\_string}: \37\\{str\_number};\6 -\4\&{var} \37\|k: \37$1\to\\{file\_name\_size}$;\C{index into \\{name\_of% -\_file}}\2\6 -\&{begin} \37\&{if} $(\\{pool\_ptr}+\\{name\_length}>\\{pool\_size})\V(\\{str% -\_ptr}=\\{max\_strings})$ \1\&{then}\5 -$\\{make\_name\_string}\K\.{"?"}$\6 -\4\&{else} \&{begin} \37\&{for} $\|k\K1\mathrel{\&{to}}\\{name\_length}$ \1% -\&{do}\5 -$\\{append\_char}(\\{xord}[\\{name\_of\_file}[\|k]])$;\2\6 -$\\{make\_name\_string}\K\\{make\_string}$;\6 -\&{end};\2\6 -\&{end};\6 -\4\&{function}\1\ \37$\\{a\_make\_name\_string}(\mathop{\&{var}}\|f:\\{alpha% -\_file})$: \37\\{str\_number};\2\6 -\&{begin} \37$\\{a\_make\_name\_string}\K\\{make\_name\_string}$;\6 -\&{end};\6 -\4\&{function}\1\ \37$\\{b\_make\_name\_string}(\mathop{\&{var}}\|f:\\{byte% -\_file})$: \37\\{str\_number};\2\6 -\&{begin} \37$\\{b\_make\_name\_string}\K\\{make\_name\_string}$;\6 -\&{end};\6 -\4\&{function}\1\ \37$\\{w\_make\_name\_string}(\mathop{\&{var}}\|f:\\{word% -\_file})$: \37\\{str\_number};\2\6 -\&{begin} \37$\\{w\_make\_name\_string}\K\\{make\_name\_string}$;\6 -\&{end};\par -\fi - -\M781. Now let's consider the ``driver'' -routines by which \MF\ deals with file names -in a system-independent manner. First comes a procedure that looks for a -file name in the input by taking the information from the input buffer. -(We can't use \\{get\_next}, because the conversion to tokens would -destroy necessary information.) - -This procedure doesn't allow semicolons or percent signs to be part of -file names, because of other conventions of \MF. The manual doesn't -use semicolons or percents immediately after file names, but some users -no doubt will find it natural to do so; therefore system-dependent -changes to allow such characters in file names should probably -be made with reluctance, and only when an entire file name that -includes special characters is ``quoted'' somehow. - -\Y\P\4\&{procedure}\1\ \37\\{scan\_file\_name};\6 -\4\&{label} \37\\{done};\2\6 -\&{begin} \37\\{begin\_name};\6 -\&{while} $\\{buffer}[\\{loc}]=\.{"\ "}$ \1\&{do}\5 -$\\{incr}(\\{loc})$;\2\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $(\\{buffer}[\\{loc}]=\.{";"})\V(\\{buffer}[% -\\{loc}]=\.{"\%"})$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\R\\{more\_name}(\\{buffer}[\\{loc}])$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{incr}(\\{loc})$;\6 -\&{end};\2\6 -\4\\{done}: \37\\{end\_name};\6 -\&{end};\par -\fi - -\M782. The global variable \\{job\_name} contains the file name that was first -\&{input} by the user. This name is extended by `\.{.log}' and `\.{.gf}' and -`\.{.base}' and `\.{.tfm}' in the names of \MF's output files. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{job\_name}: \37\\{str\_number};\C{principal file name}\6 -\4\\{log\_opened}: \37\\{boolean};\C{has the transcript file been opened?}\6 -\4\\{log\_name}: \37\\{str\_number};\C{full name of the log file}\par -\fi - -\M783. Initially $\\{job\_name}=0$; it becomes nonzero as soon as the true name -is known. -We have $\\{job\_name}=0$ if and only if the `\.{log}' file has not been -opened, -except of course for a short time just after \\{job\_name} has become nonzero. - -\Y\P$\4\X55:Initialize the output routines\X\mathrel{+}\S$\6 -$\\{job\_name}\K0$;\5 -$\\{log\_opened}\K\\{false}$;\par -\fi - -\M784. Here is a routine that manufactures the output file names, assuming that -$\\{job\_name}\I0$. It ignores and changes the current settings of \\{cur% -\_area} -and \\{cur\_ext}. - -\Y\P\D \37$\\{pack\_cur\_name}\S\\{pack\_file\_name}(\\{cur\_name},\39\\{cur% -\_area},\39\\{cur\_ext})$\par -\Y\P\4\&{procedure}\1\ \37$\\{pack\_job\_name}(\|s:\\{str\_number})$;\C{$\|s=% -\.{".log"}$, \.{".gf"}, \.{".tfm"}, or \\{base\_extension}}\2\6 -\&{begin} \37$\\{cur\_area}\K\.{""}$;\5 -$\\{cur\_ext}\K\|s$;\5 -$\\{cur\_name}\K\\{job\_name}$;\5 -\\{pack\_cur\_name};\6 -\&{end};\par -\fi - -\M785. Actually the main output file extension is usually something like -\.{".300gf"} instead of just \.{".gf"}; the additional number indicates the -resolution in pixels per inch, based on the setting of \\{hppp} when -the file is opened. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{gf\_ext}: \37\\{str\_number};\C{default extension for the output file}\par -\fi - -\M786. If some trouble arises when \MF\ tries to open a file, the following -routine calls upon the user to supply another file name. Parameter~\|s -is used in the error message to identify the type of file; parameter~\|e -is the default extension if none is given. Upon exit from the routine, -variables \\{cur\_name}, \\{cur\_area}, \\{cur\_ext}, and \\{name\_of\_file} -are -ready for another attempt at file opening. - -\Y\P\4\&{procedure}\1\ \37$\\{prompt\_file\_name}(\|s,\39\|e:\\{str% -\_number})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|k: \37$0\to\\{buf\_size}$;\C{index into \\{buffer}}\2\6 -\&{begin} \37\&{if} $\\{interaction}=\\{scroll\_mode}$ \1\&{then}\5 -\\{wake\_up\_terminal};\2\6 -\&{if} $\|s=\.{"input\ file\ name"}$ \1\&{then}\5 -$\\{print\_err}(\.{"I\ can\'t\ find\ file\ \`"})$\6 -\4\&{else} $\\{print\_err}(\.{"I\ can\'t\ write\ on\ file\ \`"})$;\2\6 -$\\{print\_file\_name}(\\{cur\_name},\39\\{cur\_area},\39\\{cur\_ext})$;\5 -$\\{print}(\.{"\'."})$;\6 -\&{if} $\|e=\.{".mf"}$ \1\&{then}\5 -\\{show\_context};\2\6 -$\\{print\_nl}(\.{"Please\ type\ another\ "})$;\5 -$\\{print}(\|s)$;\6 -\&{if} $\\{interaction}<\\{scroll\_mode}$ \1\&{then}\5 -$\\{fatal\_error}(\.{"***\ (job\ aborted,\ file\ error\ in\ nonstop\ mode)"})$;% -\2\6 -\\{clear\_terminal};\5 -$\\{prompt\_input}(\.{":\ "})$;\5 -\X787:Scan file name in the buffer\X;\6 -\&{if} $\\{cur\_ext}=\.{""}$ \1\&{then}\5 -$\\{cur\_ext}\K\|e$;\2\6 -\\{pack\_cur\_name};\6 -\&{end};\par -\fi - -\M787. \P$\X787:Scan file name in the buffer\X\S$\6 -\&{begin} \37\\{begin\_name};\5 -$\|k\K\\{first}$;\6 -\&{while} $(\\{buffer}[\|k]=\.{"\ "})\W(\|k<\\{last})$ \1\&{do}\5 -$\\{incr}(\|k)$;\2\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\|k=\\{last}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\R\\{more\_name}(\\{buffer}[\|k])$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\\{incr}(\|k)$;\6 -\&{end};\2\6 -\4\\{done}: \37\\{end\_name};\6 -\&{end}\par -\U786.\fi - -\M788. The \\{open\_log\_file} routine is used to open the transcript file and -to help -it catch up to what has previously been printed on the terminal. - -\Y\P\4\&{procedure}\1\ \37\\{open\_log\_file};\6 -\4\&{var} \37\\{old\_setting}: \37$0\to\\{max\_selector}$;\C{previous % -\\{selector} setting}\6 -\|k: \37$0\to\\{buf\_size}$;\C{index into \\{months} and \\{buffer}}\6 -\|l: \37$0\to\\{buf\_size}$;\C{end of first input line}\6 -\|m: \37\\{integer};\C{the current month}\6 -\\{months}: \37\&{packed} \37\&{array} $[1\to36]$ \1\&{of}\5 -\\{char};\C{abbreviations of month names}\2\2\6 -\&{begin} \37$\\{old\_setting}\K\\{selector}$;\6 -\&{if} $\\{job\_name}=0$ \1\&{then}\5 -$\\{job\_name}\K\.{"mfput"}$;\2\6 -$\\{pack\_job\_name}(\.{".log"})$;\6 -\&{while} $\R\\{a\_open\_out}(\\{log\_file})$ \1\&{do}\5 -\X789:Try to get a different log file name\X;\2\6 -$\\{log\_name}\K\\{a\_make\_name\_string}(\\{log\_file})$;\5 -$\\{selector}\K\\{log\_only}$;\5 -$\\{log\_opened}\K\\{true}$;\5 -\X790:Print the banner line, including the date and time\X;\6 -$\\{input\_stack}[\\{input\_ptr}]\K\\{cur\_input}$;\C{make sure bottom level is -in memory}\6 -$\\{print\_nl}(\.{"**"})$;\5 -$\|l\K\\{input\_stack}[0].\\{limit\_field}-1$;\C{last position of first line}\6 -\&{for} $\|k\K1\mathrel{\&{to}}\|l$ \1\&{do}\5 -$\\{print}(\\{buffer}[\|k])$;\2\6 -\\{print\_ln};\C{now the transcript file contains the first line of input}\6 -$\\{selector}\K\\{old\_setting}+2$;\C{\\{log\_only} or \\{term\_and\_log}}\6 -\&{end};\par -\fi - -\M789. Sometimes \\{open\_log\_file} is called at awkward moments when \MF\ is -unable to print error messages or even to \\{show\_context}. -The \\{prompt\_file\_name} routine can result in a \\{fatal\_error}, but the % -\\{error} -routine will not be invoked because \\{log\_opened} will be false. - -The normal idea of \\{batch\_mode} is that nothing at all should be written -on the terminal. However, in the unusual case that -no log file could be opened, we make an exception and allow -an explanatory message to be seen. - -Incidentally, the program always refers to the log file as a `\.{transcript -file}', because some systems cannot use the extension `\.{.log}' for -this file. - -\Y\P$\4\X789:Try to get a different log file name\X\S$\6 -\&{begin} \37$\\{selector}\K\\{term\_only}$;\5 -$\\{prompt\_file\_name}(\.{"transcript\ file\ name"},\39\.{".log"})$;\6 -\&{end}\par -\U788.\fi - -\M790. \P$\X790:Print the banner line, including the date and time\X\S$\6 -\&{begin} \37$\\{wlog}(\\{banner})$;\5 -$\\{slow\_print}(\\{base\_ident})$;\5 -$\\{print}(\.{"\ \ "})$;\5 -$\\{print\_int}(\\{round\_unscaled}(\\{internal}[\\{day}]))$;\5 -$\\{print\_char}(\.{"\ "})$;\5 -$\\{months}\K\.{\'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC\'}$;\5 -$\|m\K\\{round\_unscaled}(\\{internal}[\\{month}])$;\6 -\&{for} $\|k\K3\ast\|m-2\mathrel{\&{to}}3\ast\|m$ \1\&{do}\5 -$\\{wlog}(\\{months}[\|k])$;\2\6 -$\\{print\_char}(\.{"\ "})$;\5 -$\\{print\_int}(\\{round\_unscaled}(\\{internal}[\\{year}]))$;\5 -$\\{print\_char}(\.{"\ "})$;\5 -$\|m\K\\{round\_unscaled}(\\{internal}[\\{time}])$;\5 -$\\{print\_dd}(\|m\mathbin{\&{div}}60)$;\5 -$\\{print\_char}(\.{":"})$;\5 -$\\{print\_dd}(\|m\mathbin{\&{mod}}60)$;\6 -\&{end}\par -\U788.\fi - -\M791. Here's an example of how these file-name-parsing routines work in -practice. -We shall use the macro \\{set\_output\_file\_name} when it is time to -crank up the output file. - -\Y\P\D \37$\\{set\_output\_file\_name}\S$\1\6 -\&{begin} \37\&{if} $\\{job\_name}=0$ \1\&{then}\5 -\\{open\_log\_file};\2\6 -$\\{pack\_job\_name}(\\{gf\_ext})$;\6 -\&{while} $\R\\{b\_open\_out}(\\{gf\_file})$ \1\&{do}\5 -$\\{prompt\_file\_name}(\.{"file\ name\ for\ output"},\39\\{gf\_ext})$;\2\6 -$\\{output\_file\_name}\K\\{b\_make\_name\_string}(\\{gf\_file})$;\6 -\&{end}\2\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{gf\_file}: \37\\{byte\_file};\C{the generic font output goes here}\6 -\4\\{output\_file\_name}: \37\\{str\_number};\C{full name of the output file}% -\par -\fi - -\M792. \P$\X55:Initialize the output routines\X\mathrel{+}\S$\6 -$\\{output\_file\_name}\K0$;\par -\fi - -\M793. Let's turn now to the procedure that is used to initiate file reading -when an `\.{input}' command is being processed. - -\Y\P\4\&{procedure}\1\ \37\\{start\_input};\C{\MF\ will \.{input} something}\6 -\4\&{label} \37\\{done};\2\6 -\&{begin} \37\X795:Put the desired file name in $(\\{cur\_name},\\{cur\_ext},% -\\{cur\_area})$\X;\6 -\&{if} $\\{cur\_ext}=\.{""}$ \1\&{then}\5 -$\\{cur\_ext}\K\.{".mf"}$;\2\6 -\\{pack\_cur\_name};\6 -\~ \1\&{loop}\ \&{begin} \37\\{begin\_file\_reading};\C{set up \\{cur\_file} -and new level of input}\6 -\&{if} $\\{a\_open\_in}(\\{cur\_file})$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{cur\_area}=\.{""}$ \1\&{then}\6 -\&{begin} \37$\\{pack\_file\_name}(\\{cur\_name},\39\\{MF\_area},\39\\{cur% -\_ext})$;\6 -\&{if} $\\{a\_open\_in}(\\{cur\_file})$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{end};\2\6 -\\{end\_file\_reading};\C{remove the level that didn't work}\6 -$\\{prompt\_file\_name}(\.{"input\ file\ name"},\39\.{".mf"})$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{name}\K\\{a\_make\_name\_string}(\\{cur\_file})$;\5 -$\\{str\_ref}[\\{cur\_name}]\K\\{max\_str\_ref}$;\6 -\&{if} $\\{job\_name}=0$ \1\&{then}\6 -\&{begin} \37$\\{job\_name}\K\\{cur\_name}$;\5 -\\{open\_log\_file};\6 -\&{end};\C{\\{open\_log\_file} doesn't \\{show\_context}, so \\{limit} and % -\\{loc} needn't be set to meaningful values yet}\2\6 -\&{if} $\\{term\_offset}+\\{length}(\\{name})>\\{max\_print\_line}-2$ \1% -\&{then}\5 -\\{print\_ln}\6 -\4\&{else} \&{if} $(\\{term\_offset}>0)\V(\\{file\_offset}>0)$ \1\&{then}\5 -$\\{print\_char}(\.{"\ "})$;\2\2\6 -$\\{print\_char}(\.{"("})$;\5 -$\\{incr}(\\{open\_parens})$;\5 -$\\{slow\_print}(\\{name})$;\5 -\\{update\_terminal};\6 -\&{if} $\\{name}=\\{str\_ptr}-1$ \1\&{then}\C{we can conserve string pool space -now}\6 -\&{begin} \37$\\{flush\_string}(\\{name})$;\5 -$\\{name}\K\\{cur\_name}$;\6 -\&{end};\2\6 -\X794:Read the first line of the new file\X;\6 -\&{end};\par -\fi - -\M794. Here we have to remember to tell the \\{input\_ln} routine not to -start with a \\{get}. If the file is empty, it is considered to -contain a single blank line. - -\Y\P$\4\X794:Read the first line of the new file\X\S$\6 -\&{begin} \37$\\{line}\K1$;\6 -\&{if} $\\{input\_ln}(\\{cur\_file},\39\\{false})$ \1\&{then}\5 -\\{do\_nothing};\2\6 -\\{firm\_up\_the\_line};\5 -$\\{buffer}[\\{limit}]\K\.{"\%"}$;\5 -$\\{first}\K\\{limit}+1$;\5 -$\\{loc}\K\\{start}$;\6 -\&{end}\par -\U793.\fi - -\M795. \P$\X795:Put the desired file name in $(\\{cur\_name},\\{cur\_ext},% -\\{cur\_area})$\X\S$\6 -\&{while} $\\{token\_state}\W(\\{loc}=\\{null})$ \1\&{do}\5 -\\{end\_token\_list};\2\6 -\&{if} $\\{token\_state}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"File\ names\ can\'t\ appear\ within\ -macros"})$;\5 -$\\{help3}(\.{"Sorry...I\'ve\ converted\ what\ follows\ to\ tokens,"})$\6 -$(\.{"possibly\ garbaging\ the\ name\ you\ gave."})$\6 -$(\.{"Please\ delete\ the\ tokens\ and\ insert\ the\ name\ again."})$;\6 -\\{error};\6 -\&{end};\2\6 -\&{if} $\\{file\_state}$ \1\&{then}\5 -\\{scan\_file\_name}\6 -\4\&{else} \&{begin} \37$\\{cur\_name}\K\.{""}$;\5 -$\\{cur\_ext}\K\.{""}$;\5 -$\\{cur\_area}\K\.{""}$;\6 -\&{end}\2\par -\U793.\fi - -\N796. \[39] Introduction to the parsing routines. -We come now to the central nervous system that sparks many of \MF's activities. -By evaluating expressions, from their primary constituents to ever larger -subexpressions, \MF\ builds the structures that ultimately define fonts of -type. - -Four mutually recursive subroutines are involved in this process: We call them -$$\hbox{\\{scan\_primary}, \\{scan\_secondary}, \\{scan\_tertiary}, -and \\{scan\_expression}.}$$ -Each of them is parameterless and begins with the first token to be scanned -already represented in \\{cur\_cmd}, \\{cur\_mod}, and \\{cur\_sym}. After -execution, -the value of the primary or secondary or tertiary or expression that was -found will appear in the global variables \\{cur\_type} and \\{cur\_exp}. The -token following the expression will be represented in \\{cur\_cmd}, \\{cur% -\_mod}, -and \\{cur\_sym}. - -Technically speaking, the parsing algorithms are ``LL(1),'' more or less; -backup mechanisms have been added in order to provide reasonable error -recovery. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{cur\_type}: \37\\{small\_number};\C{the type of the expression just found}% -\6 -\4\\{cur\_exp}: \37\\{integer};\C{the value of the expression just found}\par -\fi - -\M797. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{cur\_exp}\K0$;\par -\fi - -\M798. Many different kinds of expressions are possible, so it is wise to have -precise descriptions of what \\{cur\_type} and \\{cur\_exp} mean in all cases: - -\smallskip\hang -$\\{cur\_type}=\\{vacuous}$ means that this expression didn't turn out to have -a -value at all, because it arose from a \&{begingroup}$\,\ldots\,$\&{endgroup} -construction in which there was no expression before the \&{endgroup}. -In this case \\{cur\_exp} has some irrelevant value. - -\smallskip\hang -$\\{cur\_type}=\\{boolean\_type}$ means that \\{cur\_exp} is either \\{true% -\_code} -or \\{false\_code}. - -\smallskip\hang -$\\{cur\_type}=\\{unknown\_boolean}$ means that \\{cur\_exp} points to a -capsule -node that is in the ring of variables equivalent -to at least one undefined boolean variable. - -\smallskip\hang -$\\{cur\_type}=\\{string\_type}$ means that \\{cur\_exp} is a string number -(i.e., an -integer in the range $0\L\\{cur\_exp}<\\{str\_ptr}$). That string's reference -count -includes this particular reference. - -\smallskip\hang -$\\{cur\_type}=\\{unknown\_string}$ means that \\{cur\_exp} points to a capsule -node that is in the ring of variables equivalent -to at least one undefined string variable. - -\smallskip\hang -$\\{cur\_type}=\\{pen\_type}$ means that \\{cur\_exp} points to a pen header -node. This -node contains a reference count, which takes account of this particular -reference. - -\smallskip\hang -$\\{cur\_type}=\\{unknown\_pen}$ means that \\{cur\_exp} points to a capsule -node that is in the ring of variables equivalent -to at least one undefined pen variable. - -\smallskip\hang -$\\{cur\_type}=\\{future\_pen}$ means that \\{cur\_exp} points to a knot list -that -should eventually be made into a pen. Nobody else points to this particular -knot list. The \\{future\_pen} option occurs only as an output of \\{scan% -\_primary} -and \\{scan\_secondary}, not as an output of \\{scan\_tertiary} or \\{scan% -\_expression}. - -\smallskip\hang -$\\{cur\_type}=\\{path\_type}$ means that \\{cur\_exp} points to a the first -node of -a path; nobody else points to this particular path. The control points of -the path will have been chosen. - -\smallskip\hang -$\\{cur\_type}=\\{unknown\_path}$ means that \\{cur\_exp} points to a capsule -node that is in the ring of variables equivalent -to at least one undefined path variable. - -\smallskip\hang -$\\{cur\_type}=\\{picture\_type}$ means that \\{cur\_exp} points to an edges -header node. -Nobody else points to this particular set of edges. - -\smallskip\hang -$\\{cur\_type}=\\{unknown\_picture}$ means that \\{cur\_exp} points to a -capsule -node that is in the ring of variables equivalent -to at least one undefined picture variable. - -\smallskip\hang -$\\{cur\_type}=\\{transform\_type}$ means that \\{cur\_exp} points to a % -\\{transform\_type} -capsule node. The \\{value} part of this capsule -points to a transform node that contains six numeric values, -each of which is \\{independent}, \\{dependent}, \\{proto\_dependent}, or % -\\{known}. - -\smallskip\hang -$\\{cur\_type}=\\{pair\_type}$ means that \\{cur\_exp} points to a capsule -node whose type is \\{pair\_type}. The \\{value} part of this capsule -points to a pair node that contains two numeric values, -each of which is \\{independent}, \\{dependent}, \\{proto\_dependent}, or % -\\{known}. - -\smallskip\hang -$\\{cur\_type}=\\{known}$ means that \\{cur\_exp} is a \\{scaled} value. - -\smallskip\hang -$\\{cur\_type}=\\{dependent}$ means that \\{cur\_exp} points to a capsule node -whose type -is \\{dependent}. The \\{dep\_list} field in this capsule points to the -associated -dependency list. - -\smallskip\hang -$\\{cur\_type}=\\{proto\_dependent}$ means that \\{cur\_exp} points to a % -\\{proto\_dependent} -capsule node . The \\{dep\_list} field in this capsule -points to the associated dependency list. - -\smallskip\hang -$\\{cur\_type}=\\{independent}$ means that \\{cur\_exp} points to a capsule -node -whose type is \\{independent}. This somewhat unusual case can arise, for -example, in the expression -`$x+\&{begingroup}\penalty0\,\&{string}\,x; 0\,\&{endgroup}$'. - -\smallskip\hang -$\\{cur\_type}=\\{token\_list}$ means that \\{cur\_exp} points to a linked list -of -tokens. This case arises only on the left-hand side of an assignment -(`\.{:=}') operation, under very special circumstances. - -\smallskip\noindent -The possible settings of \\{cur\_type} have been listed here in increasing -numerical order. Notice that \\{cur\_type} will never be \\{numeric\_type} or -\\{suffixed\_macro} or \\{unsuffixed\_macro}, although variables of those types -are allowed. Conversely, \MF\ has no variables of type \\{vacuous} or -\\{token\_list}. - -\fi - -\M799. Capsules are two-word nodes that have a similar meaning -to \\{cur\_type} and \\{cur\_exp}. Such nodes have $\\{name\_type}=\\{capsule}$ -and $\\{link}\L\\{void}$; and their \\{type} field is one of the possibilities -for -\\{cur\_type} listed above. - -The \\{value} field of a capsule is, in most cases, the value that -corresponds to its \\{type}, as \\{cur\_exp} corresponds to \\{cur\_type}. -However, when \\{cur\_exp} would point to a capsule, -no extra layer of indirection is present; the \\{value} -field is what would have been called $\\{value}(\\{cur\_exp})$ if it had not -been -encapsulated. Furthermore, if the type is \\{dependent} or -\\{proto\_dependent}, the \\{value} field of a capsule is replaced by -\\{dep\_list} and \\{prev\_dep} fields, since dependency lists in capsules are -always part of the general \\{dep\_list} structure. - -The \\{get\_x\_next} routine is careful not to change the values of \\{cur% -\_type} -and \\{cur\_exp} when it gets an expanded token. However, \\{get\_x\_next} -might -call a macro, which might parse an expression, which might execute lots of -commands in a group; hence it's possible that \\{cur\_type} might change -from, say, \\{unknown\_boolean} to \\{boolean\_type}, or from \\{dependent} to -\\{known} or \\{independent}, during the time \\{get\_x\_next} is called. The -programs below are careful to stash sensitive intermediate results in -capsules, so that \MF's generality doesn't cause trouble. - -Here's a procedure that illustrates these conventions. It takes -the contents of $(\\{cur\_type}\kern-.3pt,\\{cur\_exp}\kern-.3pt)$ -and stashes them away in a -capsule. It is not used when $\\{cur\_type}=\\{token\_list}$. -After the operation, $\\{cur\_type}=\\{vacuous}$; hence there is no need to -copy path lists or to update reference counts, etc. - -The special link \\{void} is put on the capsule returned by -\\{stash\_cur\_exp}, because this procedure is used to store macro parameters -that must be easily distinguishable from token lists. - -\Y\P$\4\X799:Declare the stashing/unstashing routines\X\S$\6 -\4\&{function}\1\ \37\\{stash\_cur\_exp}: \37\\{pointer};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the capsule that will be returned}\2\6 -\&{begin} \37\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{unknown\_types},\39\\{transform\_type},\39\\{pair\_type},\39% -\\{dependent},\39\\{proto\_dependent},\39\\{independent}$: \37$\|p\K\\{cur% -\_exp}$;\6 -\4\&{othercases} \37\&{begin} \37$\|p\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{name\_type}(\|p)\K\\{capsule}$;\5 -$\\{type}(\|p)\K\\{cur\_type}$;\5 -$\\{value}(\|p)\K\\{cur\_exp}$;\6 -\&{end}\2\6 -\&{endcases};\6 -$\\{cur\_type}\K\\{vacuous}$;\5 -$\\{link}(\|p)\K\\{void}$;\5 -$\\{stash\_cur\_exp}\K\|p$;\6 -\&{end};\par -\A800. -\U801.\fi - -\M800. The inverse of \\{stash\_cur\_exp} is the following procedure, which -deletes an unnecessary capsule and puts its contents into \\{cur\_type} -and \\{cur\_exp}. - -The program steps of \MF\ can be divided into two categories: those in -which \\{cur\_type} and \\{cur\_exp} are ``alive'' and those in which they are -``dead,'' in the sense that \\{cur\_type} and \\{cur\_exp} contain relevant -information or not. It's important not to ignore them when they're alive, -and it's important not to pay attention to them when they're dead. - -There's also an intermediate category: If $\\{cur\_type}=\\{vacuous}$, then -\\{cur\_exp} is irrelevant, hence we can proceed without caring if \\{cur% -\_type} -and \\{cur\_exp} are alive or dead. In such cases we say that \\{cur\_type} -and \\{cur\_exp} are {\sl dormant}. It is permissible to call \\{get\_x\_next} -only when they are alive or dormant. - -The \\{stash} procedure above assumes that \\{cur\_type} and \\{cur\_exp} -are alive or dormant. The \\{unstash} procedure assumes that they are -dead or dormant; it resuscitates them. - -\Y\P$\4\X799:Declare the stashing/unstashing routines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{unstash\_cur\_exp}(\|p:\\{pointer})$;\2\6 -\&{begin} \37$\\{cur\_type}\K\\{type}(\|p)$;\6 -\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{unknown\_types},\39\\{transform\_type},\39\\{pair\_type},\39% -\\{dependent},\39\\{proto\_dependent},\39\\{independent}$: \37$\\{cur\_exp}\K% -\|p$;\6 -\4\&{othercases} \37\&{begin} \37$\\{cur\_exp}\K\\{value}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end}\2\6 -\&{endcases};\6 -\&{end};\par -\fi - -\M801. The following procedure prints the values of expressions in an -abbreviated format. If its first parameter \|p is null, the value of -$(\\{cur\_type},\\{cur\_exp})$ is displayed; otherwise \|p should be a capsule -containing the desired value. The second parameter controls the amount of -output. If it is~0, dependency lists will be abbreviated to -`\.{linearform}' unless they consist of a single term. If it is greater -than~1, complicated structures (pens, pictures, and paths) will be displayed -in full. - -\Y\P$\4\X257:Declare subroutines for printing expressions\X\mathrel{+}\S$\6 -\hbox{\4}\X805:Declare the procedure called \\{print\_dp}\X\6 -\hbox{\4}\X799:Declare the stashing/unstashing routines\X\6 -\4\&{procedure}\1\ \37$\\{print\_exp}(\|p:\\{pointer};\,\35\\{verbosity}:% -\\{small\_number})$;\6 -\4\&{var} \37\\{restore\_cur\_exp}: \37\\{boolean};\C{should \\{cur\_exp} be -restored?}\6 -\|t: \37\\{small\_number};\C{the type of the expression}\6 -\|v: \37\\{integer};\C{the value of the expression}\6 -\|q: \37\\{pointer};\C{a big node being displayed}\2\6 -\&{begin} \37\&{if} $\|p\I\\{null}$ \1\&{then}\5 -$\\{restore\_cur\_exp}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{restore\_cur\_exp}\K\\{true}$;\6 -\&{end};\2\6 -$\|t\K\\{type}(\|p)$;\6 -\&{if} $\|t<\\{dependent}$ \1\&{then}\5 -$\|v\K\\{value}(\|p)$\ \&{else} \&{if} $\|t<\\{independent}$ \1\&{then}\5 -$\|v\K\\{dep\_list}(\|p)$;\2\2\6 -\X802:Print an abbreviated value of \|v with format depending on \|t\X;\6 -\&{if} $\\{restore\_cur\_exp}$ \1\&{then}\5 -$\\{unstash\_cur\_exp}(\|p)$;\2\6 -\&{end};\par -\fi - -\M802. \P$\X802:Print an abbreviated value of \|v with format depending on \|t% -\X\S$\6 -\&{case} $\|t$ \1\&{of}\6 -\4\\{vacuous}: \37$\\{print}(\.{"vacuous"})$;\6 -\4\\{boolean\_type}: \37\&{if} $\|v=\\{true\_code}$ \1\&{then}\5 -$\\{print}(\.{"true"})$\ \&{else} $\\{print}(\.{"false"})$;\2\6 -\4$\\{unknown\_types},\39\\{numeric\_type}$: \37\X806:Display a variable that's -been declared but not defined\X;\6 -\4\\{string\_type}: \37\&{begin} \37$\\{print\_char}(\.{""}\.{""})$;\5 -$\\{slow\_print}(\|v)$;\5 -$\\{print\_char}(\.{""}\.{""})$;\6 -\&{end};\6 -\4$\\{pen\_type},\39\\{future\_pen},\39\\{path\_type},\39\\{picture\_type}$: % -\37\X804:Display a complex type\X;\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37\&{if} $\|v=\\{null}$ \1\&{then}\5 -$\\{print\_type}(\|t)$\6 -\4\&{else} \X803:Display a big node\X;\2\6 -\4\\{known}: \37$\\{print\_scaled}(\|v)$;\6 -\4$\\{dependent},\39\\{proto\_dependent}$: \37$\\{print\_dp}(\|t,\39\|v,\39% -\\{verbosity})$;\6 -\4\\{independent}: \37$\\{print\_variable\_name}(\|p)$;\6 -\4\&{othercases} \37$\\{confusion}(\.{"exp"})$\2\6 -\&{endcases}\par -\U801.\fi - -\M803. \P$\X803:Display a big node\X\S$\6 -\&{begin} \37$\\{print\_char}(\.{"("})$;\5 -$\|q\K\|v+\\{big\_node\_size}[\|t]$;\6 -\1\&{repeat} \37\&{if} $\\{type}(\|v)=\\{known}$ \1\&{then}\5 -$\\{print\_scaled}(\\{value}(\|v))$\6 -\4\&{else} \&{if} $\\{type}(\|v)=\\{independent}$ \1\&{then}\5 -$\\{print\_variable\_name}(\|v)$\6 -\4\&{else} $\\{print\_dp}(\\{type}(\|v),\39\\{dep\_list}(\|v),\39% -\\{verbosity})$;\2\2\6 -$\|v\K\|v+2$;\6 -\&{if} $\|v\I\|q$ \1\&{then}\5 -$\\{print\_char}(\.{","})$;\2\6 -\4\&{until}\5 -$\|v=\|q$;\2\6 -$\\{print\_char}(\.{")"})$;\6 -\&{end}\par -\U802.\fi - -\M804. Values of type \&{picture}, \&{path}, and \&{pen} are displayed -verbosely -in the log file only, unless the user has given a positive value to -\\{tracingonline}. - -\Y\P$\4\X804:Display a complex type\X\S$\6 -\&{if} $\\{verbosity}\L1$ \1\&{then}\5 -$\\{print\_type}(\|t)$\6 -\4\&{else} \&{begin} \37\&{if} $\\{selector}=\\{term\_and\_log}$ \1\&{then}\6 -\&{if} $\\{internal}[\\{tracing\_online}]\L0$ \1\&{then}\6 -\&{begin} \37$\\{selector}\K\\{term\_only}$;\5 -$\\{print\_type}(\|t)$;\5 -$\\{print}(\.{"\ (see\ the\ transcript\ file)"})$;\5 -$\\{selector}\K\\{term\_and\_log}$;\6 -\&{end};\2\2\6 -\&{case} $\|t$ \1\&{of}\6 -\4\\{pen\_type}: \37$\\{print\_pen}(\|v,\39\.{""},\39\\{false})$;\6 -\4\\{future\_pen}: \37$\\{print\_path}(\|v,\39\.{"\ (future\ pen)"},\39% -\\{false})$;\6 -\4\\{path\_type}: \37$\\{print\_path}(\|v,\39\.{""},\39\\{false})$;\6 -\4\\{picture\_type}: \37\&{begin} \37$\\{cur\_edges}\K\|v$;\5 -$\\{print\_edges}(\.{""},\39\\{false},\390,\390)$;\6 -\&{end};\2\6 -\&{end};\C{there are no other cases}\6 -\&{end}\2\par -\U802.\fi - -\M805. \P$\X805:Declare the procedure called \\{print\_dp}\X\S$\6 -\4\&{procedure}\1\ \37$\\{print\_dp}(\|t:\\{small\_number};\,\35\|p:% -\\{pointer};\,\35\\{verbosity}:\\{small\_number})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the node following \|p}\2\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\6 -\&{if} $(\\{info}(\|q)=\\{null})\V(\\{verbosity}>0)$ \1\&{then}\5 -$\\{print\_dependency}(\|p,\39\|t)$\6 -\4\&{else} $\\{print}(\.{"linearform"})$;\2\6 -\&{end};\par -\U801.\fi - -\M806. The displayed name of a variable in a ring will not be a capsule unless -the ring consists entirely of capsules. - -\Y\P$\4\X806:Display a variable that's been declared but not defined\X\S$\6 -\&{begin} \37$\\{print\_type}(\|t)$;\6 -\&{if} $\|v\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{print\_char}(\.{"\ "})$;\6 -\&{while} $(\\{name\_type}(\|v)=\\{capsule})\W(\|v\I\|p)$ \1\&{do}\5 -$\|v\K\\{value}(\|v)$;\2\6 -$\\{print\_variable\_name}(\|v)$;\6 -\&{end};\2\6 -\&{end}\par -\U802.\fi - -\M807. When errors are detected during parsing, it is often helpful to -display an expression just above the error message, using \\{exp\_err} -or \\{disp\_err} instead of \\{print\_err}. - -\Y\P\D \37$\\{exp\_err}(\#)\S\\{disp\_err}(\\{null},\39\#)$\C{displays the -current expression}\par -\Y\P$\4\X257:Declare subroutines for printing expressions\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{disp\_err}(\|p:\\{pointer};\,\35\|s:\\{str% -\_number})$;\2\6 -\&{begin} \37\&{if} $\\{interaction}=\\{error\_stop\_mode}$ \1\&{then}\5 -\\{wake\_up\_terminal};\2\6 -$\\{print\_nl}(\.{">>\ "})$;\5 -$\\{print\_exp}(\|p,\391)$;\C{``medium verbose'' printing of the expression}\6 -\&{if} $\|s\I\.{""}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"!\ "})$;\5 -$\\{print}(\|s)$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M808. If \\{cur\_type} and \\{cur\_exp} contain relevant information that -should -be recycled, we will use the following procedure, which changes \\{cur\_type} -to \\{known} and stores a given value in \\{cur\_exp}. We can think of \\{cur% -\_type} -and \\{cur\_exp} as either alive or dormant after this has been done, -because \\{cur\_exp} will not contain a pointer value. - -\Y\P$\4\X808:Declare the procedure called \\{flush\_cur\_exp}\X\S$\6 -\4\&{procedure}\1\ \37$\\{flush\_cur\_exp}(\|v:\\{scaled})$;\2\6 -\&{begin} \37\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{unknown\_types},\39\\{transform\_type},\39\\{pair\_type},\39\30% -\\{dependent},\39\\{proto\_dependent},\39\\{independent}$: \37\&{begin} \37$% -\\{recycle\_value}(\\{cur\_exp})$;\5 -$\\{free\_node}(\\{cur\_exp},\39\\{value\_node\_size})$;\6 -\&{end};\6 -\4\\{pen\_type}: \37$\\{delete\_pen\_ref}(\\{cur\_exp})$;\6 -\4\\{string\_type}: \37$\\{delete\_str\_ref}(\\{cur\_exp})$;\6 -\4$\\{future\_pen},\39\\{path\_type}$: \37$\\{toss\_knot\_list}(\\{cur\_exp})$;% -\6 -\4\\{picture\_type}: \37$\\{toss\_edges}(\\{cur\_exp})$;\6 -\4\&{othercases} \37\\{do\_nothing}\2\6 -\&{endcases};\6 -$\\{cur\_type}\K\\{known}$;\5 -$\\{cur\_exp}\K\|v$;\6 -\&{end};\par -\A820. -\U246.\fi - -\M809. There's a much more general procedure that is capable of releasing -the storage associated with any two-word value packet. - -\Y\P$\4\X268:Declare the recycling subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{recycle\_value}(\|p:\\{pointer})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|t: \37\\{small\_number};\C{a type code}\6 -\|v: \37\\{integer};\C{a value}\6 -\\{vv}: \37\\{integer};\C{another value}\6 -$\|q,\39\|r,\39\|s,\39\\{pp}$: \37\\{pointer};\C{link manipulation registers}\2% -\6 -\&{begin} \37$\|t\K\\{type}(\|p)$;\6 -\&{if} $\|t<\\{dependent}$ \1\&{then}\5 -$\|v\K\\{value}(\|p)$;\2\6 -\&{case} $\|t$ \1\&{of}\6 -\4$\\{undefined},\39\\{vacuous},\39\\{boolean\_type},\39\\{known},\39\\{numeric% -\_type}$: \37\\{do\_nothing};\6 -\4\\{unknown\_types}: \37$\\{ring\_delete}(\|p)$;\6 -\4\\{string\_type}: \37$\\{delete\_str\_ref}(\|v)$;\6 -\4\\{pen\_type}: \37$\\{delete\_pen\_ref}(\|v)$;\6 -\4$\\{path\_type},\39\\{future\_pen}$: \37$\\{toss\_knot\_list}(\|v)$;\6 -\4\\{picture\_type}: \37$\\{toss\_edges}(\|v)$;\6 -\4$\\{pair\_type},\39\\{transform\_type}$: \37\X810:Recycle a big node\X;\6 -\4$\\{dependent},\39\\{proto\_dependent}$: \37\X811:Recycle a dependency list% -\X;\6 -\4\\{independent}: \37\X812:Recycle an independent variable\X;\6 -\4$\\{token\_list},\39\\{structured}$: \37$\\{confusion}(\.{"recycle"})$;\6 -\4$\\{unsuffixed\_macro},\39\\{suffixed\_macro}$: \37$\\{delete\_mac\_ref}(% -\\{value}(\|p))$;\2\6 -\&{end};\C{there are no other cases}\6 -$\\{type}(\|p)\K\\{undefined}$;\6 -\&{end};\par -\fi - -\M810. \P$\X810:Recycle a big node\X\S$\6 -\&{if} $\|v\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\|q\K\|v+\\{big\_node\_size}[\|t]$;\6 -\1\&{repeat} \37$\|q\K\|q-2$;\5 -$\\{recycle\_value}(\|q)$;\6 -\4\&{until}\5 -$\|q=\|v$;\2\6 -$\\{free\_node}(\|v,\39\\{big\_node\_size}[\|t])$;\6 -\&{end}\2\par -\U809.\fi - -\M811. \P$\X811:Recycle a dependency list\X\S$\6 -\&{begin} \37$\|q\K\\{dep\_list}(\|p)$;\6 -\&{while} $\\{info}(\|q)\I\\{null}$ \1\&{do}\5 -$\|q\K\\{link}(\|q)$;\2\6 -$\\{link}(\\{prev\_dep}(\|p))\K\\{link}(\|q)$;\5 -$\\{prev\_dep}(\\{link}(\|q))\K\\{prev\_dep}(\|p)$;\5 -$\\{link}(\|q)\K\\{null}$;\5 -$\\{flush\_node\_list}(\\{dep\_list}(\|p))$;\6 -\&{end}\par -\U809.\fi - -\M812. When an independent variable disappears, it simply fades away, unless -something depends on it. In the latter case, a dependent variable whose -coefficient of dependence is maximal will take its place. -The relevant algorithm is due to Ignacio~A. Zabala, who implemented it -as part of his Ph.D. thesis (Stanford University, December 1982). - -For example, suppose that variable $x$ is being recycled, and that the -only variables depending on~$x$ are $y=2x+a$ and $z=x+b$. In this case -we want to make $y$ independent and $z=.5y-.5a+b$; no other variables -will depend on~$y$. If $\\{tracingequations}>0$ in this situation, -we will print `\.{\#\#\# -2x=-y+a}'. - -There's a slight complication, however: An independent variable $x$ -can occur both in dependency lists and in proto-dependency lists. -This makes it necessary to be careful when deciding which coefficient -is maximal. - -Furthermore, this complication is not so slight when -a proto-dependent variable is chosen to become independent. For example, -suppose that $y=2x+100a$ is proto-dependent while $z=x+b$ is dependent; -then we must change $z=.5y-50a+b$ to a proto-dependency, because of the -large coefficient `50'. - -In order to deal with these complications without wasting too much time, -we shall link together the occurrences of~$x$ among all the linear -dependencies, maintaining separate lists for the dependent and -proto-dependent cases. - -\Y\P$\4\X812:Recycle an independent variable\X\S$\6 -\&{begin} \37$\\{max\_c}[\\{dependent}]\K0$;\5 -$\\{max\_c}[\\{proto\_dependent}]\K0$;\6 -$\\{max\_link}[\\{dependent}]\K\\{null}$;\5 -$\\{max\_link}[\\{proto\_dependent}]\K\\{null}$;\6 -$\|q\K\\{link}(\\{dep\_head})$;\6 -\&{while} $\|q\I\\{dep\_head}$ \1\&{do}\6 -\&{begin} \37$\|s\K\\{value\_loc}(\|q)$;\C{now $\\{link}(\|s)=\\{dep\_list}(% -\|q)$}\6 -\~ \1\&{loop}\ \&{begin} \37$\|r\K\\{link}(\|s)$;\6 -\&{if} $\\{info}(\|r)=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{info}(\|r)\I\|p$ \1\&{then}\5 -$\|s\K\|r$\6 -\4\&{else} \&{begin} \37$\|t\K\\{type}(\|q)$;\5 -$\\{link}(\|s)\K\\{link}(\|r)$;\5 -$\\{info}(\|r)\K\|q$;\6 -\&{if} $\\{abs}(\\{value}(\|r))>\\{max\_c}[\|t]$ \1\&{then}\5 -\X814:Record a new maximum coefficient of type \|t\X\6 -\4\&{else} \&{begin} \37$\\{link}(\|r)\K\\{max\_link}[\|t]$;\5 -$\\{max\_link}[\|t]\K\|r$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\2\6 -\4\\{done}: \37$\|q\K\\{link}(\|r)$;\6 -\&{end};\2\6 -\&{if} $(\\{max\_c}[\\{dependent}]>0)\V(\\{max\_c}[\\{proto\_dependent}]>0)$ \1% -\&{then}\5 -\X815:Choose a dependent variable to take the place of the disappearing -independent variable, and change all remaining dependencies accordingly\X;\2\6 -\&{end}\par -\U809.\fi - -\M813. The code for independency removal makes use of three two-word arrays. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{max\_c}: \37\&{array} $[\\{dependent}\to\\{proto\_dependent}]$ \1\&{of}\5 -\\{integer};\C{max coefficient magnitude}\2\6 -\4\\{max\_ptr}: \37\&{array} $[\\{dependent}\to\\{proto\_dependent}]$ \1\&{of}\5 -\\{pointer};\C{where \|p occurs with \\{max\_c}}\2\6 -\4\\{max\_link}: \37\&{array} $[\\{dependent}\to\\{proto\_dependent}]$ \1\&{of}% -\5 -\\{pointer};\C{other occurrences of \|p}\2\par -\fi - -\M814. \P$\X814:Record a new maximum coefficient of type \|t\X\S$\6 -\&{begin} \37\&{if} $\\{max\_c}[\|t]>0$ \1\&{then}\6 -\&{begin} \37$\\{link}(\\{max\_ptr}[\|t])\K\\{max\_link}[\|t]$;\5 -$\\{max\_link}[\|t]\K\\{max\_ptr}[\|t]$;\6 -\&{end};\2\6 -$\\{max\_c}[\|t]\K\\{abs}(\\{value}(\|r))$;\5 -$\\{max\_ptr}[\|t]\K\|r$;\6 -\&{end}\par -\U812.\fi - -\M815. \P$\X815:Choose a dependent variable to take the place of the -disappearing independent variable, and change all remaining dependencies -accordingly\X\S$\6 -\&{begin} \37\&{if} $(\\{max\_c}[\\{dependent}]\mathbin{\&{div}}\O{10000}\G% -\\{max\_c}[\\{proto\_dependent}])$ \1\&{then}\5 -$\|t\K\\{dependent}$\6 -\4\&{else} $\|t\K\\{proto\_dependent}$;\2\6 -\X816:Determine the dependency list \|s to substitute for the independent -variable~\|p\X;\6 -$\|t\K\\{dependent}+\\{proto\_dependent}-\|t$;\C{complement \|t}\6 -\&{if} $\\{max\_c}[\|t]>0$ \1\&{then}\C{we need to pick up an unchosen -dependency}\6 -\&{begin} \37$\\{link}(\\{max\_ptr}[\|t])\K\\{max\_link}[\|t]$;\5 -$\\{max\_link}[\|t]\K\\{max\_ptr}[\|t]$;\6 -\&{end};\2\6 -\&{if} $\|t\I\\{dependent}$ \1\&{then}\5 -\X818:Substitute new dependencies in place of \|p\X\6 -\4\&{else} \X819:Substitute new proto-dependencies in place of \|p\X;\2\6 -$\\{flush\_node\_list}(\|s)$;\6 -\&{if} $\\{fix\_needed}$ \1\&{then}\5 -\\{fix\_dependencies};\2\6 -\\{check\_arith};\6 -\&{end}\par -\U812.\fi - -\M816. Let $\|s=\\{max\_ptr}[\|t]$. At this point we have $\\{value}(s)=\pm% -\\{max\_c}[t]$, -and $\\{info}(\|s)$ points to the dependent variable~\\{pp} of type~\|t from -whose dependency list we have removed node~\|s. We must reinsert -node~\|s into the dependency list, with coefficient $-1.0$, and with -\\{pp} as the new independent variable. Since \\{pp} will have a larger serial -number than any other variable, we can put node \|s at the head of the -list. - -\Y\P$\4\X816:Determine the dependency list \|s to substitute for the -independent variable~\|p\X\S$\6 -$\|s\K\\{max\_ptr}[\|t]$;\5 -$\\{pp}\K\\{info}(\|s)$;\5 -$\|v\K\\{value}(\|s)$;\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\5 -$\\{value}(\|s)\K-\\{fraction\_one}$\ \&{else} $\\{value}(\|s)\K-\\{unity}$;\2\6 -$\|r\K\\{dep\_list}(\\{pp})$;\5 -$\\{link}(\|s)\K\|r$;\6 -\&{while} $\\{info}(\|r)\I\\{null}$ \1\&{do}\5 -$\|r\K\\{link}(\|r)$;\2\6 -$\|q\K\\{link}(\|r)$;\5 -$\\{link}(\|r)\K\\{null}$;\5 -$\\{prev\_dep}(\|q)\K\\{prev\_dep}(\\{pp})$;\5 -$\\{link}(\\{prev\_dep}(\\{pp}))\K\|q$;\5 -$\\{new\_indep}(\\{pp})$;\6 -\&{if} $\\{cur\_exp}=\\{pp}$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\|t$ \1\&{then}\5 -$\\{cur\_type}\K\\{independent}$;\2\2\6 -\&{if} $\\{internal}[\\{tracing\_equations}]>0$ \1\&{then}\5 -\X817:Show the transformed dependency\X\2\par -\U815.\fi - -\M817. Now $(-v)$ times the formerly independent variable~\|p is being replaced -by the dependency list~\|s. - -\Y\P$\4\X817:Show the transformed dependency\X\S$\6 -\&{if} $\\{interesting}(\|p)$ \1\&{then}\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\#\#\#\ "})$;\6 -\&{if} $\|v>0$ \1\&{then}\5 -$\\{print\_char}(\.{"-"})$;\2\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\5 -$\\{vv}\K\\{round\_fraction}(\\{max\_c}[\\{dependent}])$\6 -\4\&{else} $\\{vv}\K\\{max\_c}[\\{proto\_dependent}]$;\2\6 -\&{if} $\\{vv}\I\\{unity}$ \1\&{then}\5 -$\\{print\_scaled}(\\{vv})$;\2\6 -$\\{print\_variable\_name}(\|p)$;\6 -\&{while} $\\{value}(\|p)\mathbin{\&{mod}}\\{s\_scale}>0$ \1\&{do}\6 -\&{begin} \37$\\{print}(\.{"*4"})$;\5 -$\\{value}(\|p)\K\\{value}(\|p)-2$;\6 -\&{end};\2\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\5 -$\\{print\_char}(\.{"="})$\ \&{else} $\\{print}(\.{"\ =\ "})$;\2\6 -$\\{print\_dependency}(\|s,\39\|t)$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\2\par -\U816.\fi - -\M818. Finally, there are dependent and proto-dependent variables whose -dependency lists must be brought up to date. - -\Y\P$\4\X818:Substitute new dependencies in place of \|p\X\S$\6 -\&{for} $\|t\K\\{dependent}\mathrel{\&{to}}\\{proto\_dependent}$ \1\&{do}\6 -\&{begin} \37$\|r\K\\{max\_link}[\|t]$;\6 -\&{while} $\|r\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{info}(\|r)$;\5 -$\\{dep\_list}(\|q)\K\\{p\_plus\_fq}(\\{dep\_list}(\|q),\39\30\\{make% -\_fraction}(\\{value}(\|r),\39-\|v),\39\|s,\39\|t,\39\\{dependent})$;\6 -\&{if} $\\{dep\_list}(\|q)=\\{dep\_final}$ \1\&{then}\5 -$\\{make\_known}(\|q,\39\\{dep\_final})$;\2\6 -$\|q\K\|r$;\5 -$\|r\K\\{link}(\|r)$;\5 -$\\{free\_node}(\|q,\39\\{dep\_node\_size})$;\6 -\&{end};\2\6 -\&{end}\2\par -\U815.\fi - -\M819. \P$\X819:Substitute new proto-dependencies in place of \|p\X\S$\6 -\&{for} $\|t\K\\{dependent}\mathrel{\&{to}}\\{proto\_dependent}$ \1\&{do}\6 -\&{begin} \37$\|r\K\\{max\_link}[\|t]$;\6 -\&{while} $\|r\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{info}(\|r)$;\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\C{for safety's sake, we change \|q to % -\\{proto\_dependent}}\6 -\&{begin} \37\&{if} $\\{cur\_exp}=\|q$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\\{dependent}$ \1\&{then}\5 -$\\{cur\_type}\K\\{proto\_dependent}$;\2\2\6 -$\\{dep\_list}(\|q)\K\\{p\_over\_v}(\\{dep\_list}(\|q),\39\\{unity},\39% -\\{dependent},\39\\{proto\_dependent})$;\5 -$\\{type}(\|q)\K\\{proto\_dependent}$;\5 -$\\{value}(\|r)\K\\{round\_fraction}(\\{value}(\|r))$;\6 -\&{end};\2\6 -$\\{dep\_list}(\|q)\K\\{p\_plus\_fq}(\\{dep\_list}(\|q),\39\30\\{make\_scaled}(% -\\{value}(\|r),\39-\|v),\39\|s,\39\\{proto\_dependent},\39\\{proto% -\_dependent})$;\6 -\&{if} $\\{dep\_list}(\|q)=\\{dep\_final}$ \1\&{then}\5 -$\\{make\_known}(\|q,\39\\{dep\_final})$;\2\6 -$\|q\K\|r$;\5 -$\|r\K\\{link}(\|r)$;\5 -$\\{free\_node}(\|q,\39\\{dep\_node\_size})$;\6 -\&{end};\2\6 -\&{end}\2\par -\U815.\fi - -\M820. Here are some routines that provide handy combinations of actions -that are often needed during error recovery. For example, -`\\{flush\_error}' flushes the current expression, replaces it by -a given value, and calls \\{error}. - -Errors often are detected after an extra token has already been scanned. -The `\\{put\_get}' routines put that token back before calling \\{error}; -then they get it back again. (Or perhaps they get another token, if -the user has changed things.) - -\Y\P$\4\X808:Declare the procedure called \\{flush\_cur\_exp}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{flush\_error}(\|v:\\{scaled})$;\ \2\6 -\&{begin} \37\\{error};\5 -$\\{flush\_cur\_exp}(\|v)$;\ \&{end};\7 -\4\&{procedure}\1\ \37\\{back\_error};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{get\_x\_next};\5 -\\{forward};\5 -\hbox{\2}\7 -\4\&{procedure}\1\ \37\\{put\_get\_error};\ \2\6 -\&{begin} \37\\{back\_error};\5 -\\{get\_x\_next};\ \&{end};\7 -\4\&{procedure}\1\ \37$\\{put\_get\_flush\_error}(\|v:\\{scaled})$;\ \2\6 -\&{begin} \37\\{put\_get\_error};\5 -$\\{flush\_cur\_exp}(\|v)$;\ \&{end};\par -\fi - -\M821. A global variable called \\{var\_flag} is set to a special command code -just before \MF\ calls \\{scan\_expression}, if the expression should be -treated as a variable when this command code immediately follows. For -example, \\{var\_flag} is set to \\{assignment} at the beginning of a -statement, because we want to know the {\sl location\/} of a variable at -the left of `\.{:=}', not the {\sl value\/} of that variable. - -The \\{scan\_expression} subroutine calls \\{scan\_tertiary}, -which calls \\{scan\_secondary}, which calls \\{scan\_primary}, which sets -$\\{var\_flag}\K0$. In this way each of the scanning routines ``knows'' -when it has been called with a special \\{var\_flag}, but \\{var\_flag} is -usually zero. - -A variable preceding a command that equals \\{var\_flag} is converted to a -token list rather than a value. Furthermore, an `\.{=}' sign following an -expression with $\\{var\_flag}=\\{assignment}$ is not considered to be a -relation -that produces boolean expressions. - - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{var\_flag}: \37$0\to\\{max\_command\_code}$;\C{command that wants a -variable}\par -\fi - -\M822. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{var\_flag}\K0$;\par -\fi - -\N823. \[40] Parsing primary expressions. -The first parsing routine, \\{scan\_primary}, is also the most complicated one, -since it involves so many different cases. But each case---with one -exception---is fairly simple by itself. - -When \\{scan\_primary} begins, the first token of the primary to be scanned -should already appear in \\{cur\_cmd}, \\{cur\_mod}, and \\{cur\_sym}. The -values -of \\{cur\_type} and \\{cur\_exp} should be either dead or dormant, as -explained -earlier. If \\{cur\_cmd} is not between \\{min\_primary\_command} and -\\{max\_primary\_command}, inclusive, a syntax error will be signalled. - -\Y\P$\4\X823:Declare the basic parsing subroutines\X\S$\6 -\4\&{procedure}\1\ \37\\{scan\_primary};\6 -\4\&{label} \37$\\{restart},\39\\{done},\39\\{done1},\39\\{done2}$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{for list manipulation}\6 -\|c: \37\\{quarterword};\C{a primitive operation code}\6 -\\{my\_var\_flag}: \37$0\to\\{max\_command\_code}$;\C{initial value of \\{my% -\_var\_flag}}\6 -$\\{l\_delim},\39\\{r\_delim}$: \37\\{pointer};\C{hash addresses of a delimiter -pair}\6 -\X831:Other local variables for \\{scan\_primary}\X\2\6 -\&{begin} \37$\\{my\_var\_flag}\K\\{var\_flag}$;\5 -$\\{var\_flag}\K0$;\6 -\4\\{restart}: \37\\{check\_arith};\5 -\X825:Supply diagnostic information, if requested\X;\6 -\&{case} $\\{cur\_cmd}$ \1\&{of}\6 -\4\\{left\_delimiter}: \37\X826:Scan a delimited primary\X;\6 -\4\\{begin\_group}: \37\X832:Scan a grouped primary\X;\6 -\4\\{string\_token}: \37\X833:Scan a string constant\X;\6 -\4\\{numeric\_token}: \37\X837:Scan a primary that starts with a numeric token% -\X;\6 -\4\\{nullary}: \37\X834:Scan a nullary operation\X;\6 -\4$\\{unary},\39\\{type\_name},\39\\{cycle},\39\\{plus\_or\_minus}$: \37% -\X835:Scan a unary operation\X;\6 -\4\\{primary\_binary}: \37\X839:Scan a binary operation with `\&{of}' between -its operands\X;\6 -\4\\{str\_op}: \37\X840:Convert a suffix to a string\X;\6 -\4\\{internal\_quantity}: \37\X841:Scan an internal numeric quantity\X;\6 -\4\\{capsule\_token}: \37$\\{make\_exp\_copy}(\\{cur\_mod})$;\6 -\4\\{tag\_token}: \37\X844:Scan a variable primary; \&{goto} \\{restart} if it -turns out to be a macro\X;\6 -\4\&{othercases} \37\&{begin} \37$\\{bad\_exp}(\.{"A\ primary"})$;\5 -\&{goto} \37\\{restart};\6 -\&{end}\2\6 -\&{endcases};\6 -\\{get\_x\_next};\C{the routines \&{goto} \\{done} if they don't want this}\6 -\4\\{done}: \37\&{if} $\\{cur\_cmd}=\\{left\_bracket}$ \1\&{then}\6 -\&{if} $\\{cur\_type}\G\\{known}$ \1\&{then}\5 -\X859:Scan a mediation construction\X;\2\2\6 -\&{end};\par -\As860, 862, 864, 868\ETs892. -\U1202.\fi - -\M824. Errors at the beginning of expressions are flagged by \\{bad\_exp}. - -\Y\P\4\&{procedure}\1\ \37$\\{bad\_exp}(\|s:\\{str\_number})$;\6 -\4\&{var} \37\\{save\_flag}: \37$0\to\\{max\_command\_code}$;\2\6 -\&{begin} \37$\\{print\_err}(\|s)$;\5 -$\\{print}(\.{"\ expression\ can\'t\ begin\ with\ \`"})$;\5 -$\\{print\_cmd\_mod}(\\{cur\_cmd},\39\\{cur\_mod})$;\5 -$\\{print\_char}(\.{"\'"})$;\5 -$\\{help4}(\.{"I\'m\ afraid\ I\ need\ some\ sort\ of\ value\ in\ order\ to\ -continue,"})$\6 -$(\.{"so\ I\'ve\ tentatively\ inserted\ \`0\'.\ You\ may\ want\ to"})$\6 -$(\.{"delete\ this\ zero\ and\ insert\ something\ else;"})$\6 -$(\.{"see\ Chapter\ 27\ of\ The\ METAFONTbook\ for\ an\ example."})$;\5 -\\{back\_input};\5 -$\\{cur\_sym}\K0$;\5 -$\\{cur\_cmd}\K\\{numeric\_token}$;\5 -$\\{cur\_mod}\K0$;\5 -\\{ins\_error};\6 -$\\{save\_flag}\K\\{var\_flag}$;\5 -$\\{var\_flag}\K0$;\5 -\\{get\_x\_next};\5 -$\\{var\_flag}\K\\{save\_flag}$;\6 -\&{end};\par -\fi - -\M825. \P$\X825:Supply diagnostic information, if requested\X\S$\6 -\&{debug} \37\&{if} $\\{panicking}$ \1\&{then}\5 -$\\{check\_mem}(\\{false})$;\ \2\6 -\&{gubed}\6 -\&{if} $\\{interrupt}\I0$ \1\&{then}\6 -\&{if} $\\{OK\_to\_interrupt}$ \1\&{then}\6 -\&{begin} \37\\{back\_input};\5 -\\{check\_interrupt};\5 -\\{get\_x\_next};\6 -\&{end}\2\2\par -\U823.\fi - -\M826. \P$\X826:Scan a delimited primary\X\S$\6 -\&{begin} \37$\\{l\_delim}\K\\{cur\_sym}$;\5 -$\\{r\_delim}\K\\{cur\_mod}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $(\\{cur\_cmd}=\\{comma})\W(\\{cur\_type}\G\\{known})$ \1\&{then}\5 -\X830:Scan the second of a pair of numerics\X\6 -\4\&{else} $\\{check\_delimiter}(\\{l\_delim},\39\\{r\_delim})$;\2\6 -\&{end}\par -\U823.\fi - -\M827. The \\{stash\_in} subroutine puts the current (numeric) expression into -a field -within a ``big node.'' - -\Y\P\4\&{procedure}\1\ \37$\\{stash\_in}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37$\\{type}(\|p)\K\\{cur\_type}$;\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -$\\{value}(\|p)\K\\{cur\_exp}$\6 -\4\&{else} \&{begin} \37\&{if} $\\{cur\_type}=\\{independent}$ \1\&{then}\5 -\X829:Stash an independent \\{cur\_exp} into a big node\X\6 -\4\&{else} \&{begin} \37$\\{mem}[\\{value\_loc}(\|p)]\K\\{mem}[\\{value\_loc}(% -\\{cur\_exp})]$;\C{$\\{dep\_list}(\|p)\K\\{dep\_list}(\\{cur\_exp})$ and $% -\\{prev\_dep}(\|p)\K\\{prev\_dep}(\\{cur\_exp})$}\6 -$\\{link}(\\{prev\_dep}(\|p))\K\|p$;\6 -\&{end};\2\6 -$\\{free\_node}(\\{cur\_exp},\39\\{value\_node\_size})$;\6 -\&{end};\2\6 -$\\{cur\_type}\K\\{vacuous}$;\6 -\&{end};\par -\fi - -\M828. In rare cases the current expression can become \\{independent}. There -may be many dependency lists pointing to such an independent capsule, -so we can't simply move it into place within a big node. Instead, -we copy it, then recycle it. - -\fi - -\M829. \P$\X829:Stash an independent \\{cur\_exp} into a big node\X\S$\6 -\&{begin} \37$\|q\K\\{single\_dependency}(\\{cur\_exp})$;\6 -\&{if} $\|q=\\{dep\_final}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\|p)\K\\{known}$;\5 -$\\{value}(\|p)\K0$;\5 -$\\{free\_node}(\|q,\39\\{dep\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{type}(\|p)\K\\{dependent}$;\5 -$\\{new\_dep}(\|p,\39\|q)$;\6 -\&{end};\2\6 -$\\{recycle\_value}(\\{cur\_exp})$;\6 -\&{end}\par -\U827.\fi - -\M830. \P$\X830:Scan the second of a pair of numerics\X\S$\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{type}(\|p)\K\\{pair\_type}$;\5 -$\\{name\_type}(\|p)\K\\{capsule}$;\5 -$\\{init\_big\_node}(\|p)$;\5 -$\|q\K\\{value}(\|p)$;\5 -$\\{stash\_in}(\\{x\_part\_loc}(\|q))$;\6 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}<\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Nonnumeric\ ypart\ has\ been\ replaced\ by\ -0"})$;\5 -$\\{help4}(\.{"I\ thought\ you\ were\ giving\ me\ a\ pair\ \`(x,y)\';\ but"})$\6 -$(\.{"after\ finding\ a\ nice\ xpart\ \`x\'\ I\ found\ a\ ypart\ \`y\'"})$\6 -$(\.{"that\ isn\'t\ of\ numeric\ type.\ So\ I\'ve\ changed\ y\ to\ zero."})$\6 -$(\.{"(The\ y\ that\ I\ didn\'t\ like\ appears\ above\ the\ error\ -message.)"})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\2\6 -$\\{stash\_in}(\\{y\_part\_loc}(\|q))$;\5 -$\\{check\_delimiter}(\\{l\_delim},\39\\{r\_delim})$;\5 -$\\{cur\_type}\K\\{pair\_type}$;\5 -$\\{cur\_exp}\K\|p$;\6 -\&{end}\par -\U826.\fi - -\M831. The local variable \\{group\_line} keeps track of the line -where a \&{begingroup} command occurred; this will be useful -in an error message if the group doesn't actually end. - -\Y\P$\4\X831:Other local variables for \\{scan\_primary}\X\S$\6 -\4\\{group\_line}: \37\\{integer};\C{where a group began}\par -\As836\ET843. -\U823.\fi - -\M832. \P$\X832:Scan a grouped primary\X\S$\6 -\&{begin} \37$\\{group\_line}\K\\{line}$;\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>0$ \1\&{then}\5 -\\{show\_cur\_cmd\_mod};\2\6 -$\\{save\_boundary\_item}(\|p)$;\6 -\1\&{repeat} \37\\{do\_statement};\C{ends with $\\{cur\_cmd}\G\\{semicolon}$}\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{semicolon}$;\2\6 -\&{if} $\\{cur\_cmd}\I\\{end\_group}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"A\ group\ begun\ on\ line\ "})$;\5 -$\\{print\_int}(\\{group\_line})$;\5 -$\\{print}(\.{"\ never\ ended"})$;\5 -$\\{help2}(\.{"I\ saw\ a\ \`begingroup\'\ back\ there\ that\ hasn\'t\ been\ -matched"})$\6 -$(\.{"by\ \`endgroup\'.\ So\ I\'ve\ inserted\ \`endgroup\'\ now."})$;\5 -\\{back\_error};\5 -$\\{cur\_cmd}\K\\{end\_group}$;\6 -\&{end};\2\6 -\\{unsave};\C{this might change \\{cur\_type}, if independent variables are -recycled}\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>0$ \1\&{then}\5 -\\{show\_cur\_cmd\_mod};\2\6 -\&{end}\par -\U823.\fi - -\M833. \P$\X833:Scan a string constant\X\S$\6 -\&{begin} \37$\\{cur\_type}\K\\{string\_type}$;\5 -$\\{cur\_exp}\K\\{cur\_mod}$;\6 -\&{end}\par -\U823.\fi - -\M834. Later we'll come to procedures that perform actual operations like -addition, square root, and so on; our purpose now is to do the parsing. -But we might as well mention those future procedures now, so that the -suspense won't be too bad: - -\smallskip -$\\{do\_nullary}(\|c)$ does primitive operations that have no operands (e.g., -`\&{true}' or `\&{pencircle}'); - -\smallskip -$\\{do\_unary}(\|c)$ applies a primitive operation to the current expression; - -\smallskip -$\\{do\_binary}(\|p,\|c)$ applies a primitive operation to the capsule~\|p -and the current expression. - -\Y\P$\4\X834:Scan a nullary operation\X\S$\6 -$\\{do\_nullary}(\\{cur\_mod})$\par -\U823.\fi - -\M835. \P$\X835:Scan a unary operation\X\S$\6 -\&{begin} \37$\|c\K\\{cur\_mod}$;\5 -\\{get\_x\_next};\5 -\\{scan\_primary};\5 -$\\{do\_unary}(\|c)$;\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U823.\fi - -\M836. A numeric token might be a primary by itself, or it might be the -numerator of a fraction composed solely of numeric tokens, or it might -multiply the primary that follows (provided that the primary doesn't begin -with a plus sign or a minus sign). The code here uses the facts that -$\\{max\_primary\_command}=\\{plus\_or\_minus}$ and -$\\{max\_primary\_command}-1=\\{numeric\_token}$. If a fraction is found that -is less -than unity, we try to retain higher precision when we use it in scalar -multiplication. - -\Y\P$\4\X831:Other local variables for \\{scan\_primary}\X\mathrel{+}\S$\6 -\4$\\{num},\39\\{denom}$: \37\\{scaled};\C{for primaries that are fractions, -like `1/2'}\par -\fi - -\M837. \P$\X837:Scan a primary that starts with a numeric token\X\S$\6 -\&{begin} \37$\\{cur\_exp}\K\\{cur\_mod}$;\5 -$\\{cur\_type}\K\\{known}$;\5 -\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}\I\\{slash}$ \1\&{then}\6 -\&{begin} \37$\\{num}\K0$;\5 -$\\{denom}\K0$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}\I\\{numeric\_token}$ \1\&{then}\6 -\&{begin} \37\\{back\_input};\5 -$\\{cur\_cmd}\K\\{slash}$;\5 -$\\{cur\_mod}\K\\{over}$;\5 -$\\{cur\_sym}\K\\{frozen\_slash}$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -$\\{num}\K\\{cur\_exp}$;\5 -$\\{denom}\K\\{cur\_mod}$;\6 -\&{if} $\\{denom}=0$ \1\&{then}\5 -\X838:Protest division by zero\X\6 -\4\&{else} $\\{cur\_exp}\K\\{make\_scaled}(\\{num},\39\\{denom})$;\2\6 -\\{check\_arith};\5 -\\{get\_x\_next};\6 -\&{end};\2\6 -\&{if} $\\{cur\_cmd}\G\\{min\_primary\_command}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}<\\{numeric\_token}$ \1\&{then}\C{in particular, $\\{cur% -\_cmd}\I\\{plus\_or\_minus}$}\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -\\{scan\_primary};\6 -\&{if} $(\\{abs}(\\{num})\G\\{abs}(\\{denom}))\V(\\{cur\_type}<\\{pair\_type})$ -\1\&{then}\5 -$\\{do\_binary}(\|p,\39\\{times})$\6 -\4\&{else} \&{begin} \37$\\{frac\_mult}(\\{num},\39\\{denom})$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end};\2\6 -\&{end};\2\2\6 -\&{goto} \37\\{done};\6 -\&{end}\par -\U823.\fi - -\M838. \P$\X838:Protest division by zero\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Division\ by\ zero"})$;\5 -$\\{help1}(\.{"I\'ll\ pretend\ that\ you\ meant\ to\ divide\ by\ 1."})$;\5 -\\{error};\6 -\&{end}\par -\U837.\fi - -\M839. \P$\X839:Scan a binary operation with `\&{of}' between its operands\X\S$% -\6 -\&{begin} \37$\|c\K\\{cur\_mod}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}\I\\{of\_token}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"of"})$;\5 -$\\{print}(\.{"\ for\ "})$;\5 -$\\{print\_cmd\_mod}(\\{primary\_binary},\39\|c)$;\5 -$\\{help1}(\.{"I\'ve\ got\ the\ first\ argument;\ will\ look\ now\ for\ the\ -other."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -$\|p\K\\{stash\_cur\_exp}$;\5 -\\{get\_x\_next};\5 -\\{scan\_primary};\5 -$\\{do\_binary}(\|p,\39\|c)$;\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U823.\fi - -\M840. \P$\X840:Convert a suffix to a string\X\S$\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_suffix};\5 -$\\{old\_setting}\K\\{selector}$;\5 -$\\{selector}\K\\{new\_string}$;\5 -$\\{show\_token\_list}(\\{cur\_exp},\39\\{null},\39100000,\390)$;\5 -$\\{flush\_token\_list}(\\{cur\_exp})$;\5 -$\\{cur\_exp}\K\\{make\_string}$;\5 -$\\{selector}\K\\{old\_setting}$;\5 -$\\{cur\_type}\K\\{string\_type}$;\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U823.\fi - -\M841. If an internal quantity appears all by itself on the left of an -assignment, we return a token list of length one, containing the address -of the internal quantity plus \\{hash\_end}. (This accords with the conventions -of the save stack, as described earlier.) - -\Y\P$\4\X841:Scan an internal numeric quantity\X\S$\6 -\&{begin} \37$\|q\K\\{cur\_mod}$;\6 -\&{if} $\\{my\_var\_flag}=\\{assignment}$ \1\&{then}\6 -\&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}=\\{assignment}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_exp}\K\\{get\_avail}$;\5 -$\\{info}(\\{cur\_exp})\K\|q+\\{hash\_end}$;\5 -$\\{cur\_type}\K\\{token\_list}$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\\{back\_input};\6 -\&{end};\2\6 -$\\{cur\_type}\K\\{known}$;\5 -$\\{cur\_exp}\K\\{internal}[\|q]$;\6 -\&{end}\par -\U823.\fi - -\M842. The most difficult part of \\{scan\_primary} has been saved for last, -since -it was necessary to build up some confidence first. We can now face the task -of scanning a variable. - -As we scan a variable, we build a token list containing the relevant -names and subscript values, simultaneously following along in the -``collective'' structure to see if we are actually dealing with a macro -instead of a value. - -The local variables \\{pre\_head} and \\{post\_head} will point to the -beginning -of the prefix and suffix lists; \\{tail} will point to the end of the list -that is currently growing. - -Another local variable, \\{tt}, contains partial information about the -declared type of the variable-so-far. If $\\{tt}\G\\{unsuffixed\_macro}$, the -relation $\\{tt}=\\{type}(\|q)$ will always hold. If $\\{tt}=\\{undefined}$, -the routine -doesn't bother to update its information about type. And if -$\\{undefined}<\\{tt}<\\{unsuffixed\_macro}$, the precise value of \\{tt} isn't -critical. - -\fi - -\M843. \P$\X831:Other local variables for \\{scan\_primary}\X\mathrel{+}\S$\6 -\4$\\{pre\_head},\39\\{post\_head},\39\\{tail}$: \37\\{pointer};\C{prefix and -suffix list variables}\6 -\4\\{tt}: \37\\{small\_number};\C{approximation to the type of the -variable-so-far}\6 -\4\|t: \37\\{pointer};\C{a token}\6 -\4\\{macro\_ref}: \37\\{pointer};\C{reference count for a suffixed macro}\par -\fi - -\M844. \P$\X844:Scan a variable primary; \&{goto} \\{restart} if it turns out -to be a macro\X\S$\6 -\&{begin} \37$\\{fast\_get\_avail}(\\{pre\_head})$;\5 -$\\{tail}\K\\{pre\_head}$;\5 -$\\{post\_head}\K\\{null}$;\5 -$\\{tt}\K\\{vacuous}$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|t\K\\{cur\_tok}$;\5 -$\\{link}(\\{tail})\K\|t$;\6 -\&{if} $\\{tt}\I\\{undefined}$ \1\&{then}\6 -\&{begin} \37\X850:Find the approximate type \\{tt} and corresponding~\|q\X;\6 -\&{if} $\\{tt}\G\\{unsuffixed\_macro}$ \1\&{then}\5 -\X845:Either begin an unsuffixed macro call or prepare for a suffixed one\X;\2\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -$\\{tail}\K\|t$;\6 -\&{if} $\\{cur\_cmd}=\\{left\_bracket}$ \1\&{then}\5 -\X846:Scan for a subscript; replace \\{cur\_cmd} by \\{numeric\_token} if found% -\X;\2\6 -\&{if} $\\{cur\_cmd}>\\{max\_suffix\_token}$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -\&{if} $\\{cur\_cmd}<\\{min\_suffix\_token}$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -\&{end};\C{now \\{cur\_cmd} is \\{internal\_quantity}, \\{tag\_token}, or % -\\{numeric\_token}}\2\6 -\4\\{done1}: \37\X852:Handle unusual cases that masquerade as variables, and % -\&{goto} \\{restart} or \&{goto} \\{done} if appropriate; otherwise make a copy -of the variable and \&{goto} \\{done}\X;\6 -\&{end}\par -\U823.\fi - -\M845. \P$\X845:Either begin an unsuffixed macro call or prepare for a suffixed -one\X\S$\6 -\&{begin} \37$\\{link}(\\{tail})\K\\{null}$;\6 -\&{if} $\\{tt}>\\{unsuffixed\_macro}$ \1\&{then}\C{$\\{tt}=\\{suffixed% -\_macro}$}\6 -\&{begin} \37$\\{post\_head}\K\\{get\_avail}$;\5 -$\\{tail}\K\\{post\_head}$;\5 -$\\{link}(\\{tail})\K\|t$;\6 -$\\{tt}\K\\{undefined}$;\5 -$\\{macro\_ref}\K\\{value}(\|q)$;\5 -$\\{add\_mac\_ref}(\\{macro\_ref})$;\6 -\&{end}\6 -\4\&{else} \X853:Set up unsuffixed macro call and \&{goto} \\{restart}\X;\2\6 -\&{end}\par -\U844.\fi - -\M846. \P$\X846:Scan for a subscript; replace \\{cur\_cmd} by \\{numeric% -\_token} if found\X\S$\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}\I\\{right\_bracket}$ \1\&{then}\5 -\X847:Put the left bracket and the expression back to be rescanned\X\6 -\4\&{else} \&{begin} \37\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -\\{bad\_subscript};\2\6 -$\\{cur\_cmd}\K\\{numeric\_token}$;\5 -$\\{cur\_mod}\K\\{cur\_exp}$;\5 -$\\{cur\_sym}\K0$;\6 -\&{end};\2\6 -\&{end}\par -\U844.\fi - -\M847. The left bracket that we thought was introducing a subscript might have -actually been the left bracket in a mediation construction like `\.{x[a,b]}'. -So we don't issue an error message at this point; but we do want to back up -so as to avoid any embarrassment about our incorrect assumption. - -\Y\P$\4\X847:Put the left bracket and the expression back to be rescanned\X\S$\6 -\&{begin} \37\\{back\_input};\C{that was the token following the current -expression}\6 -\\{back\_expr};\5 -$\\{cur\_cmd}\K\\{left\_bracket}$;\5 -$\\{cur\_mod}\K0$;\5 -$\\{cur\_sym}\K\\{frozen\_left\_bracket}$;\6 -\&{end}\par -\Us846\ET859.\fi - -\M848. Here's a routine that puts the current expression back to be read again. - -\Y\P\4\&{procedure}\1\ \37\\{back\_expr};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{capsule token}\2\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{link}(\|p)\K\\{null}$;\5 -$\\{back\_list}(\|p)$;\6 -\&{end};\par -\fi - -\M849. Unknown subscripts lead to the following error message. - -\Y\P\4\&{procedure}\1\ \37\\{bad\_subscript};\2\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ subscript\ has\ been\ replaced\ by\ -zero"})$;\5 -$\\{help3}(\.{"A\ bracketed\ subscript\ must\ have\ a\ known\ numeric\ -value;"})$\6 -$(\.{"unfortunately,\ what\ I\ found\ was\ the\ value\ that\ appears\ just"})$\6 -$(\.{"above\ this\ error\ message.\ So\ I\'ll\ try\ a\ zero\ subscript."})$;\5 -$\\{flush\_error}(0)$;\6 -\&{end};\par -\fi - -\M850. Every time we call \\{get\_x\_next}, there's a chance that the variable -we've -been looking at will disappear. Thus, we cannot safely keep \|q pointing -into the variable structure; we need to start searching from the root each -time. - -\Y\P$\4\X850:Find the approximate type \\{tt} and corresponding~\|q\X\S$\6 -\&{begin} \37$\|p\K\\{link}(\\{pre\_head})$;\5 -$\|q\K\\{info}(\|p)$;\5 -$\\{tt}\K\\{undefined}$;\6 -\&{if} $\\{eq\_type}(\|q)\mathbin{\&{mod}}\\{outer\_tag}=\\{tag\_token}$ \1% -\&{then}\6 -\&{begin} \37$\|q\K\\{equiv}(\|q)$;\6 -\&{if} $\|q=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done2};\2\6 -\~ \1\&{loop}\ \&{begin} \37$\|p\K\\{link}(\|p)$;\6 -\&{if} $\|p=\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{tt}\K\\{type}(\|q)$;\5 -\&{goto} \37\\{done2};\6 -\&{end};\2\6 -\&{if} $\\{type}(\|q)\I\\{structured}$ \1\&{then}\5 -\&{goto} \37\\{done2};\2\6 -$\|q\K\\{link}(\\{attr\_head}(\|q))$;\C{the \\{collective\_subscript} -attribute}\6 -\&{if} $\|p\G\\{hi\_mem\_min}$ \1\&{then}\C{it's not a subscript}\6 -\&{begin} \37\1\&{repeat} \37$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\\{attr\_loc}(\|q)\G\\{info}(\|p)$;\2\6 -\&{if} $\\{attr\_loc}(\|q)>\\{info}(\|p)$ \1\&{then}\5 -\&{goto} \37\\{done2};\2\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\2\6 -\4\\{done2}: \37\&{end}\par -\U844.\fi - -\M851. How do things stand now? Well, we have scanned an entire variable name, -including possible subscripts and/or attributes; \\{cur\_cmd}, \\{cur\_mod}, -and -\\{cur\_sym} represent the token that follows. If $\\{post\_head}=\\{null}$, a -token list for this variable name starts at $\\{link}(\\{pre\_head})$, with all -subscripts evaluated. But if $\\{post\_head}\I\\{null}$, the variable turned -out -to be a suffixed macro; \\{pre\_head} is the head of the prefix list, while -\\{post\_head} is the head of a token list containing both `\.{\AT!}' and -the suffix. - -Our immediate problem is to see if this variable still exists. (Variable -structures can change drastically whenever we call \\{get\_x\_next}; users -aren't supposed to do this, but the fact that it is possible means that -we must be cautious.) - -The following procedure prints an error message when a variable -unexpectedly disappears. Its help message isn't quite right for -our present purposes, but we'll be able to fix that up. - -\Y\P\4\&{procedure}\1\ \37$\\{obliterated}(\|q:\\{pointer})$;\2\6 -\&{begin} \37$\\{print\_err}(\.{"Variable\ "})$;\5 -$\\{show\_token\_list}(\|q,\39\\{null},\391000,\390)$;\5 -$\\{print}(\.{"\ has\ been\ obliterated"})$;\5 -$\\{help5}(\.{"It\ seems\ you\ did\ a\ nasty\ thing---probably\ by\ -accident,"})$\6 -$(\.{"but\ nevertheless\ you\ nearly\ hornswoggled\ me..."})$\6 -$(\.{"While\ I\ was\ evaluating\ the\ right-hand\ side\ of\ this"})$\6 -$(\.{"command,\ something\ happened,\ and\ the\ left-hand\ side"})$\6 -$(\.{"is\ no\ longer\ a\ variable!\ So\ I\ won\'t\ change\ anything."})$;\6 -\&{end};\par -\fi - -\M852. If the variable does exist, we also need to check -for a few other special cases before deciding that a plain old ordinary -variable has, indeed, been scanned. - -\Y\P$\4\X852:Handle unusual cases that masquerade as variables, and \&{goto} % -\\{restart} or \&{goto} \\{done} if appropriate; otherwise make a copy of the -variable and \&{goto} \\{done}\X\S$\6 -\&{if} $\\{post\_head}\I\\{null}$ \1\&{then}\5 -\X854:Set up suffixed macro call and \&{goto} \\{restart}\X;\2\6 -$\|q\K\\{link}(\\{pre\_head})$;\5 -$\\{free\_avail}(\\{pre\_head})$;\6 -\&{if} $\\{cur\_cmd}=\\{my\_var\_flag}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_type}\K\\{token\_list}$;\5 -$\\{cur\_exp}\K\|q$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -$\|p\K\\{find\_variable}(\|q)$;\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\5 -$\\{make\_exp\_copy}(\|p)$\6 -\4\&{else} \&{begin} \37$\\{obliterated}(\|q)$;\6 -$\\{help\_line}[2]\K\.{"While\ I\ was\ evaluating\ the\ suffix\ of\ this\ -variable,"}$;\5 -$\\{help\_line}[1]\K\.{"something\ was\ redefined,\ and\ it\'s\ no\ longer\ a\ -variable!"}$;\5 -$\\{help\_line}[0]\K\.{"In\ order\ to\ get\ back\ on\ my\ feet,\ I\'ve\ -inserted\ \`0\'\ instead."}$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\2\6 -$\\{flush\_node\_list}(\|q)$;\5 -\&{goto} \37\\{done}\par -\U844.\fi - -\M853. The only complication associated with macro calling is that the prefix -and ``at'' parameters must be packaged in an appropriate list of lists. - -\Y\P$\4\X853:Set up unsuffixed macro call and \&{goto} \\{restart}\X\S$\6 -\&{begin} \37$\|p\K\\{get\_avail}$;\5 -$\\{info}(\\{pre\_head})\K\\{link}(\\{pre\_head})$;\5 -$\\{link}(\\{pre\_head})\K\|p$;\5 -$\\{info}(\|p)\K\|t$;\5 -$\\{macro\_call}(\\{value}(\|q),\39\\{pre\_head},\39\\{null})$;\5 -\\{get\_x\_next};\5 -\&{goto} \37\\{restart};\6 -\&{end}\par -\U845.\fi - -\M854. If the ``variable'' that turned out to be a suffixed macro no longer -exists, -we don't care, because we have reserved a pointer (\\{macro\_ref}) to its -token list. - -\Y\P$\4\X854:Set up suffixed macro call and \&{goto} \\{restart}\X\S$\6 -\&{begin} \37\\{back\_input};\5 -$\|p\K\\{get\_avail}$;\5 -$\|q\K\\{link}(\\{post\_head})$;\5 -$\\{info}(\\{pre\_head})\K\\{link}(\\{pre\_head})$;\5 -$\\{link}(\\{pre\_head})\K\\{post\_head}$;\5 -$\\{info}(\\{post\_head})\K\|q$;\5 -$\\{link}(\\{post\_head})\K\|p$;\5 -$\\{info}(\|p)\K\\{link}(\|q)$;\5 -$\\{link}(\|q)\K\\{null}$;\5 -$\\{macro\_call}(\\{macro\_ref},\39\\{pre\_head},\39\\{null})$;\5 -$\\{decr}(\\{ref\_count}(\\{macro\_ref}))$;\5 -\\{get\_x\_next};\5 -\&{goto} \37\\{restart};\6 -\&{end}\par -\U852.\fi - -\M855. Our remaining job is simply to make a copy of the value that has been -found. Some cases are harder than others, but complexity arises solely -because of the multiplicity of possible cases. - -\Y\P$\4\X855:Declare the procedure called \\{make\_exp\_copy}\X\S$\6 -\hbox{\4}\X856:Declare subroutines needed by \\{make\_exp\_copy}\X\6 -\4\&{procedure}\1\ \37$\\{make\_exp\_copy}(\|p:\\{pointer})$;\6 -\4\&{label} \37\\{restart};\6 -\4\&{var} \37$\|q,\39\|r,\39\|t$: \37\\{pointer};\C{registers for list -manipulation}\2\6 -\&{begin} \37\\{restart}: \37$\\{cur\_type}\K\\{type}(\|p)$;\6 -\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{vacuous},\39\\{boolean\_type},\39\\{known}$: \37$\\{cur\_exp}\K\\{value}(% -\|p)$;\6 -\4\\{unknown\_types}: \37$\\{cur\_exp}\K\\{new\_ring\_entry}(\|p)$;\6 -\4\\{string\_type}: \37\&{begin} \37$\\{cur\_exp}\K\\{value}(\|p)$;\5 -$\\{add\_str\_ref}(\\{cur\_exp})$;\6 -\&{end};\6 -\4\\{pen\_type}: \37\&{begin} \37$\\{cur\_exp}\K\\{value}(\|p)$;\5 -$\\{add\_pen\_ref}(\\{cur\_exp})$;\6 -\&{end};\6 -\4\\{picture\_type}: \37$\\{cur\_exp}\K\\{copy\_edges}(\\{value}(\|p))$;\6 -\4$\\{path\_type},\39\\{future\_pen}$: \37$\\{cur\_exp}\K\\{copy\_path}(% -\\{value}(\|p))$;\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37\X857:Copy the big node \|p\X;\6 -\4$\\{dependent},\39\\{proto\_dependent}$: \37$\\{encapsulate}(\\{copy\_dep% -\_list}(\\{dep\_list}(\|p)))$;\6 -\4\\{numeric\_type}: \37\&{begin} \37$\\{new\_indep}(\|p)$;\5 -\&{goto} \37\\{restart};\6 -\&{end};\6 -\4\\{independent}: \37\&{begin} \37$\|q\K\\{single\_dependency}(\|p)$;\6 -\&{if} $\|q=\\{dep\_final}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_type}\K\\{known}$;\5 -$\\{cur\_exp}\K0$;\5 -$\\{free\_node}(\|q,\39\\{value\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{cur\_type}\K\\{dependent}$;\5 -$\\{encapsulate}(\|q)$;\6 -\&{end};\2\6 -\&{end};\6 -\4\&{othercases} \37$\\{confusion}(\.{"copy"})$\2\6 -\&{endcases};\6 -\&{end};\par -\U651.\fi - -\M856. The \\{encapsulate} subroutine assumes that \\{dep\_final} is the -tail of dependency list~\|p. - -\Y\P$\4\X856:Declare subroutines needed by \\{make\_exp\_copy}\X\S$\6 -\4\&{procedure}\1\ \37$\\{encapsulate}(\|p:\\{pointer})$;\2\6 -\&{begin} \37$\\{cur\_exp}\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{type}(\\{cur\_exp})\K\\{cur\_type}$;\5 -$\\{name\_type}(\\{cur\_exp})\K\\{capsule}$;\5 -$\\{new\_dep}(\\{cur\_exp},\39\|p)$;\6 -\&{end};\par -\A858. -\U855.\fi - -\M857. The most tedious case arises when the user refers to a -\&{pair} or \&{transform} variable; we must copy several fields, -each of which can be \\{independent}, \\{dependent}, \\{proto\_dependent}, -or \\{known}. - -\Y\P$\4\X857:Copy the big node \|p\X\S$\6 -\&{begin} \37\&{if} $\\{value}(\|p)=\\{null}$ \1\&{then}\5 -$\\{init\_big\_node}(\|p)$;\2\6 -$\|t\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{name\_type}(\|t)\K\\{capsule}$;\5 -$\\{type}(\|t)\K\\{cur\_type}$;\5 -$\\{init\_big\_node}(\|t)$;\6 -$\|q\K\\{value}(\|p)+\\{big\_node\_size}[\\{cur\_type}]$;\5 -$\|r\K\\{value}(\|t)+\\{big\_node\_size}[\\{cur\_type}]$;\6 -\1\&{repeat} \37$\|q\K\|q-2$;\5 -$\|r\K\|r-2$;\5 -$\\{install}(\|r,\39\|q)$;\6 -\4\&{until}\5 -$\|q=\\{value}(\|p)$;\2\6 -$\\{cur\_exp}\K\|t$;\6 -\&{end}\par -\U855.\fi - -\M858. The \\{install} procedure copies a numeric field~\|q into field~\|r of -a big node that will be part of a capsule. - -\Y\P$\4\X856:Declare subroutines needed by \\{make\_exp\_copy}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{install}(\|r,\39\|q:\\{pointer})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37\&{if} $\\{type}(\|q)=\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{value}(\|r)\K\\{value}(\|q)$;\5 -$\\{type}(\|r)\K\\{known}$;\6 -\&{end}\6 -\4\&{else} \&{if} $\\{type}(\|q)=\\{independent}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{single\_dependency}(\|q)$;\6 -\&{if} $\|p=\\{dep\_final}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\|r)\K\\{known}$;\5 -$\\{value}(\|r)\K0$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{type}(\|r)\K\\{dependent}$;\5 -$\\{new\_dep}(\|r,\39\|p)$;\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{type}(\|r)\K\\{type}(\|q)$;\5 -$\\{new\_dep}(\|r,\39\\{copy\_dep\_list}(\\{dep\_list}(\|q)))$;\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M859. Expressions of the form `\.{a[b,c]}' are converted into -`\.{b+a*(c-b)}', without checking the types of \.b~or~\.c, -provided that \.a is numeric. - -\Y\P$\4\X859:Scan a mediation construction\X\S$\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}\I\\{comma}$ \1\&{then}\6 -\&{begin} \37\X847:Put the left bracket and the expression back to be rescanned% -\X;\6 -$\\{unstash\_cur\_exp}(\|p)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|q\K\\{stash\_cur\_exp}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}\I\\{right\_bracket}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"]"})$;\6 -$\\{help3}(\.{"I\'ve\ scanned\ an\ expression\ of\ the\ form\ \`a[b,c\',"})$\6 -$(\.{"so\ a\ right\ bracket\ should\ have\ come\ next."})$\6 -$(\.{"I\ shall\ pretend\ that\ one\ was\ there."})$;\6 -\\{back\_error};\6 -\&{end};\2\6 -$\|r\K\\{stash\_cur\_exp}$;\5 -$\\{make\_exp\_copy}(\|q)$;\6 -$\\{do\_binary}(\|r,\39\\{minus})$;\5 -$\\{do\_binary}(\|p,\39\\{times})$;\5 -$\\{do\_binary}(\|q,\39\\{plus})$;\5 -\\{get\_x\_next};\6 -\&{end};\2\6 -\&{end}\par -\U823.\fi - -\M860. Here is a comparatively simple routine that is used to scan the -\&{suffix} parameters of a macro. - -\Y\P$\4\X823:Declare the basic parsing subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{scan\_suffix};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37$\|h,\39\|t$: \37\\{pointer};\C{head and tail of the list being -built}\6 -\|p: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37$\|h\K\\{get\_avail}$;\5 -$\|t\K\|h$;\6 -\~ \1\&{loop}\ \&{begin} \37\&{if} $\\{cur\_cmd}=\\{left\_bracket}$ \1\&{then}\5 -\X861:Scan a bracketed subscript and set $\\{cur\_cmd}\K\\{numeric\_token}$\X;% -\2\6 -\&{if} $\\{cur\_cmd}=\\{numeric\_token}$ \1\&{then}\5 -$\|p\K\\{new\_num\_tok}(\\{cur\_mod})$\6 -\4\&{else} \&{if} $(\\{cur\_cmd}=\\{tag\_token})\V(\\{cur\_cmd}=\\{internal% -\_quantity})$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{get\_avail}$;\5 -$\\{info}(\|p)\K\\{cur\_sym}$;\6 -\&{end}\6 -\4\&{else} \&{goto} \37\\{done};\2\2\6 -$\\{link}(\|t)\K\|p$;\5 -$\|t\K\|p$;\5 -\\{get\_x\_next};\6 -\&{end};\2\6 -\4\\{done}: \37$\\{cur\_exp}\K\\{link}(\|h)$;\5 -$\\{free\_avail}(\|h)$;\5 -$\\{cur\_type}\K\\{token\_list}$;\6 -\&{end};\par -\fi - -\M861. \P$\X861:Scan a bracketed subscript and set $\\{cur\_cmd}\K\\{numeric% -\_token}$\X\S$\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -\\{bad\_subscript};\2\6 -\&{if} $\\{cur\_cmd}\I\\{right\_bracket}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"]"})$;\6 -$\\{help3}(\.{"I\'ve\ seen\ a\ \`[\'\ and\ a\ subscript\ value,\ in\ a\ -suffix,"})$\6 -$(\.{"so\ a\ right\ bracket\ should\ have\ come\ next."})$\6 -$(\.{"I\ shall\ pretend\ that\ one\ was\ there."})$;\6 -\\{back\_error};\6 -\&{end};\2\6 -$\\{cur\_cmd}\K\\{numeric\_token}$;\5 -$\\{cur\_mod}\K\\{cur\_exp}$;\6 -\&{end}\par -\U860.\fi - -\N862. \[41] Parsing secondary and higher expressions. -After the intricacies of \\{scan\_primary}\kern-1pt, -the \\{scan\_secondary} routine is -refreshingly simple. It's not trivial, but the operations are relatively -straightforward; the main difficulty is, again, that expressions and data -structures might change drastically every time we call \\{get\_x\_next}, so a -cautious approach is mandatory. For example, a macro defined by -\&{primarydef} might have disappeared by the time its second argument has -been scanned; we solve this by increasing the reference count of its token -list, so that the macro can be called even after it has been clobbered. - -\Y\P$\4\X823:Declare the basic parsing subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{scan\_secondary};\6 -\4\&{label} \37$\\{restart},\39\\{continue}$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{for list manipulation}\6 -$\|c,\39\|d$: \37\\{halfword};\C{operation codes or modifiers}\6 -\\{mac\_name}: \37\\{pointer};\C{token defined with \&{primarydef}}\2\6 -\&{begin} \37\\{restart}: \37\&{if} $(\\{cur\_cmd}<\\{min\_primary\_command})\V% -\30(\\{cur\_cmd}>\\{max\_primary\_command})$ \1\&{then}\5 -$\\{bad\_exp}(\.{"A\ secondary"})$;\2\6 -\\{scan\_primary};\6 -\4\\{continue}: \37\&{if} $\\{cur\_cmd}\L\\{max\_secondary\_command}$ \1% -\&{then}\6 -\&{if} $\\{cur\_cmd}\G\\{min\_secondary\_command}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -$\|c\K\\{cur\_mod}$;\5 -$\|d\K\\{cur\_cmd}$;\6 -\&{if} $\|d=\\{secondary\_primary\_macro}$ \1\&{then}\6 -\&{begin} \37$\\{mac\_name}\K\\{cur\_sym}$;\5 -$\\{add\_mac\_ref}(\|c)$;\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -\\{scan\_primary};\6 -\&{if} $\|d\I\\{secondary\_primary\_macro}$ \1\&{then}\5 -$\\{do\_binary}(\|p,\39\|c)$\6 -\4\&{else} \&{begin} \37\\{back\_input};\5 -$\\{binary\_mac}(\|p,\39\|c,\39\\{mac\_name})$;\5 -$\\{decr}(\\{ref\_count}(\|c))$;\5 -\\{get\_x\_next};\5 -\&{goto} \37\\{restart};\6 -\&{end};\2\6 -\&{goto} \37\\{continue};\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M863. The following procedure calls a macro that has two parameters, -\|p and \\{cur\_exp}. - -\Y\P\4\&{procedure}\1\ \37$\\{binary\_mac}(\|p,\39\|c,\39\|n:\\{pointer})$;\6 -\4\&{var} \37$\|q,\39\|r$: \37\\{pointer};\C{nodes in the parameter list}\2\6 -\&{begin} \37$\|q\K\\{get\_avail}$;\5 -$\|r\K\\{get\_avail}$;\5 -$\\{link}(\|q)\K\|r$;\6 -$\\{info}(\|q)\K\|p$;\5 -$\\{info}(\|r)\K\\{stash\_cur\_exp}$;\6 -$\\{macro\_call}(\|c,\39\|q,\39\|n)$;\6 -\&{end};\par -\fi - -\M864. The next procedure, \\{scan\_tertiary}, is pretty much the same deal. - -\Y\P$\4\X823:Declare the basic parsing subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{scan\_tertiary};\6 -\4\&{label} \37$\\{restart},\39\\{continue}$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{for list manipulation}\6 -$\|c,\39\|d$: \37\\{halfword};\C{operation codes or modifiers}\6 -\\{mac\_name}: \37\\{pointer};\C{token defined with \&{secondarydef}}\2\6 -\&{begin} \37\\{restart}: \37\&{if} $(\\{cur\_cmd}<\\{min\_primary\_command})\V% -\30(\\{cur\_cmd}>\\{max\_primary\_command})$ \1\&{then}\5 -$\\{bad\_exp}(\.{"A\ tertiary"})$;\2\6 -\\{scan\_secondary};\6 -\&{if} $\\{cur\_type}=\\{future\_pen}$ \1\&{then}\5 -\\{materialize\_pen};\2\6 -\4\\{continue}: \37\&{if} $\\{cur\_cmd}\L\\{max\_tertiary\_command}$ \1\&{then}% -\6 -\&{if} $\\{cur\_cmd}\G\\{min\_tertiary\_command}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -$\|c\K\\{cur\_mod}$;\5 -$\|d\K\\{cur\_cmd}$;\6 -\&{if} $\|d=\\{tertiary\_secondary\_macro}$ \1\&{then}\6 -\&{begin} \37$\\{mac\_name}\K\\{cur\_sym}$;\5 -$\\{add\_mac\_ref}(\|c)$;\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -\\{scan\_secondary};\6 -\&{if} $\|d\I\\{tertiary\_secondary\_macro}$ \1\&{then}\5 -$\\{do\_binary}(\|p,\39\|c)$\6 -\4\&{else} \&{begin} \37\\{back\_input};\5 -$\\{binary\_mac}(\|p,\39\|c,\39\\{mac\_name})$;\5 -$\\{decr}(\\{ref\_count}(\|c))$;\5 -\\{get\_x\_next};\5 -\&{goto} \37\\{restart};\6 -\&{end};\2\6 -\&{goto} \37\\{continue};\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M865. A \\{future\_pen} becomes a full-fledged pen here. - -\Y\P\4\&{procedure}\1\ \37\\{materialize\_pen};\6 -\4\&{label} \37\\{common\_ending};\6 -\4\&{var} \37$\\{a\_minus\_b},\39\\{a\_plus\_b},\39\\{major\_axis},\39\\{minor% -\_axis}$: \37\\{scaled};\C{ellipse variables}\6 -\\{theta}: \37\\{angle};\C{amount by which the ellipse has been rotated}\6 -\|p: \37\\{pointer};\C{path traverser}\6 -\|q: \37\\{pointer};\C{the knot list to be made into a pen}\2\6 -\&{begin} \37$\|q\K\\{cur\_exp}$;\6 -\&{if} $\\{left\_type}(\|q)=\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Pen\ path\ must\ be\ a\ cycle"})$;\5 -$\\{help2}(\.{"I\ can\'t\ make\ a\ pen\ from\ the\ given\ path."})$\6 -$(\.{"So\ I\'ve\ replaced\ it\ by\ the\ trivial\ path\ \`(0,0)..cycle\'."})$;\5 -\\{put\_get\_error};\5 -$\\{cur\_exp}\K\\{null\_pen}$;\5 -\&{goto} \37\\{common\_ending};\6 -\&{end}\6 -\4\&{else} \&{if} $\\{left\_type}(\|q)=\\{open}$ \1\&{then}\5 -\X866:Change node \|q to a path for an elliptical pen\X;\2\2\6 -$\\{cur\_exp}\K\\{make\_pen}(\|q)$;\6 -\4\\{common\_ending}: \37$\\{toss\_knot\_list}(\|q)$;\5 -$\\{cur\_type}\K\\{pen\_type}$;\6 -\&{end};\par -\fi - -\M866. We placed the three points $(0,0)$, $(1,0)$, $(0,1)$ into a % -\&{pencircle}, -and they have now been transformed to $(u,v)$, $(A+u,B+v)$, $(C+u,D+v)$; -this gives us enough information to deduce the transformation -$(x,y)\mapsto(Ax+Cy+u,Bx+Dy+v)$. - -Given ($A,B,C,D)$ we can always find $(a,b,\theta,\phi)$ such that -$$\eqalign{A&=a\cos\phi\cos\theta-b\sin\phi\sin\theta;\cr -B&=a\cos\phi\sin\theta+b\sin\phi\cos\theta;\cr -C&=-a\sin\phi\cos\theta-b\cos\phi\sin\theta;\cr -D&=-a\sin\phi\sin\theta+b\cos\phi\cos\theta.\cr}$$ -In this notation, the unit circle $(\cos t,\sin t)$ is transformed into -$$\bigl(a\cos(\phi+t)\cos\theta-b\sin(\phi+t)\sin\theta,\; -a\cos(\phi+t)\sin\theta+b\sin(\phi+t)\cos\theta\bigr)\;+\;(u,v),$$ -which is an ellipse with semi-axes~$(a,b)$, rotated by~$\theta$ and -shifted by~$(u,v)$. To solve the stated equations, we note that it is -necessary and sufficient to solve -$$\eqalign{A-D&=(a-b)\cos(\theta-\phi),\cr -B+C&=(a-b)\sin(\theta-\phi),\cr} -\qquad -\eqalign{A+D&=(a+b)\cos(\theta+\phi),\cr -B-C&=(a+b)\sin(\theta+\phi);\cr}$$ -and it is easy to find $a-b$, $a+b$, $\theta-\phi$, and $\theta+\phi$ -from these formulas. - -The code below uses $(\\{txx},\\{tyx},\\{txy},\\{tyy},\\{tx},\\{ty})$ to stand -for -$(A,B,C,D,u,v)$. - -\Y\P$\4\X866:Change node \|q to a path for an elliptical pen\X\S$\6 -\&{begin} \37$\\{tx}\K\\{x\_coord}(\|q)$;\5 -$\\{ty}\K\\{y\_coord}(\|q)$;\5 -$\\{txx}\K\\{left\_x}(\|q)-\\{tx}$;\5 -$\\{tyx}\K\\{left\_y}(\|q)-\\{ty}$;\5 -$\\{txy}\K\\{right\_x}(\|q)-\\{tx}$;\5 -$\\{tyy}\K\\{right\_y}(\|q)-\\{ty}$;\5 -$\\{a\_minus\_b}\K\\{pyth\_add}(\\{txx}-\\{tyy},\39\\{tyx}+\\{txy})$;\5 -$\\{a\_plus\_b}\K\\{pyth\_add}(\\{txx}+\\{tyy},\39\\{tyx}-\\{txy})$;\5 -$\\{major\_axis}\K\\{half}(\\{a\_minus\_b}+\\{a\_plus\_b})$;\5 -$\\{minor\_axis}\K\\{half}(\\{abs}(\\{a\_plus\_b}-\\{a\_minus\_b}))$;\6 -\&{if} $\\{major\_axis}=\\{minor\_axis}$ \1\&{then}\5 -$\\{theta}\K0$\C{circle}\6 -\4\&{else} $\\{theta}\K\\{half}(\\{n\_arg}(\\{txx}-\\{tyy},\39\\{tyx}+\\{txy})+% -\\{n\_arg}(\\{txx}+\\{tyy},\39\\{tyx}-\\{txy}))$;\2\6 -$\\{free\_node}(\|q,\39\\{knot\_node\_size})$;\5 -$\|q\K\\{make\_ellipse}(\\{major\_axis},\39\\{minor\_axis},\39\\{theta})$;\6 -\&{if} $(\\{tx}\I0)\V(\\{ty}\I0)$ \1\&{then}\5 -\X867:Shift the coordinates of path \|q\X;\2\6 -\&{end}\par -\U865.\fi - -\M867. \P$\X867:Shift the coordinates of path \|q\X\S$\6 -\&{begin} \37$\|p\K\|q$;\6 -\1\&{repeat} \37$\\{x\_coord}(\|p)\K\\{x\_coord}(\|p)+\\{tx}$;\5 -$\\{y\_coord}(\|p)\K\\{y\_coord}(\|p)+\\{ty}$;\5 -$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\|p=\|q$;\2\6 -\&{end}\par -\U866.\fi - -\M868. Finally we reach the deepest level in our quartet of parsing routines. -This one is much like the others; but it has an extra complication from -paths, which materialize here. - -\Y\P\D \37$\\{continue\_path}=25$\C{a label inside of \\{scan\_expression}}\par -\P\D \37$\\{finish\_path}=26$\C{another}\par -\Y\P$\4\X823:Declare the basic parsing subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{scan\_expression};\6 -\4\&{label} \37$\\{restart},\39\\{done},\39\\{continue},\39\\{continue\_path},% -\39\\{finish\_path},\39\\{exit}$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r,\39\\{pp},\39\\{qq}$: \37\\{pointer};\C{for -list manipulation}\6 -$\|c,\39\|d$: \37\\{halfword};\C{operation codes or modifiers}\6 -\\{my\_var\_flag}: \37$0\to\\{max\_command\_code}$;\C{initial value of \\{var% -\_flag}}\6 -\\{mac\_name}: \37\\{pointer};\C{token defined with \&{tertiarydef}}\6 -\\{cycle\_hit}: \37\\{boolean};\C{did a path expression just end with `% -\&{cycle}'?}\6 -$\|x,\39\|y$: \37\\{scaled};\C{explicit coordinates or tension at a path join}\6 -\|t: \37$\\{endpoint}\to\\{open}$;\C{knot type following a path join}\2\6 -\&{begin} \37$\\{my\_var\_flag}\K\\{var\_flag}$;\6 -\4\\{restart}: \37\&{if} $(\\{cur\_cmd}<\\{min\_primary\_command})\V\30(\\{cur% -\_cmd}>\\{max\_primary\_command})$ \1\&{then}\5 -$\\{bad\_exp}(\.{"An"})$;\2\6 -\\{scan\_tertiary};\6 -\4\\{continue}: \37\&{if} $\\{cur\_cmd}\L\\{max\_expression\_command}$ \1% -\&{then}\6 -\&{if} $\\{cur\_cmd}\G\\{min\_expression\_command}$ \1\&{then}\6 -\&{if} $(\\{cur\_cmd}\I\\{equals})\V(\\{my\_var\_flag}\I\\{assignment})$ \1% -\&{then}\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -$\|c\K\\{cur\_mod}$;\5 -$\|d\K\\{cur\_cmd}$;\6 -\&{if} $\|d=\\{expression\_tertiary\_macro}$ \1\&{then}\6 -\&{begin} \37$\\{mac\_name}\K\\{cur\_sym}$;\5 -$\\{add\_mac\_ref}(\|c)$;\6 -\&{end};\2\6 -\&{if} $(\|d<\\{ampersand})\V((\|d=\\{ampersand})\W\30((\\{type}(\|p)=\\{pair% -\_type})\V(\\{type}(\|p)=\\{path\_type})))$ \1\&{then}\5 -\X869:Scan a path construction operation; but \&{return} if \|p has the wrong -type\X\6 -\4\&{else} \&{begin} \37\\{get\_x\_next};\5 -\\{scan\_tertiary};\6 -\&{if} $\|d\I\\{expression\_tertiary\_macro}$ \1\&{then}\5 -$\\{do\_binary}(\|p,\39\|c)$\6 -\4\&{else} \&{begin} \37\\{back\_input};\5 -$\\{binary\_mac}(\|p,\39\|c,\39\\{mac\_name})$;\5 -$\\{decr}(\\{ref\_count}(\|c))$;\5 -\\{get\_x\_next};\5 -\&{goto} \37\\{restart};\6 -\&{end};\2\6 -\&{end};\2\6 -\&{goto} \37\\{continue};\6 -\&{end};\2\2\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M869. The reader should review the data structure conventions for paths before -hoping to understand the next part of this code. - -\Y\P$\4\X869:Scan a path construction operation; but \&{return} if \|p has the -wrong type\X\S$\6 -\&{begin} \37$\\{cycle\_hit}\K\\{false}$;\5 -\X870:Convert the left operand, \|p, into a partial path ending at~\|q; but % -\&{return} if \|p doesn't have a suitable type\X;\6 -\4\\{continue\_path}: \37\X874:Determine the path join parameters; but \&{goto} -\\{finish\_path} if there's only a direction specifier\X;\6 -\&{if} $\\{cur\_cmd}=\\{cycle}$ \1\&{then}\5 -\X886:Get ready to close a cycle\X\6 -\4\&{else} \&{begin} \37\\{scan\_tertiary};\5 -\X885:Convert the right operand, \\{cur\_exp}, into a partial path from \\{pp} -to~\\{qq}\X;\6 -\&{end};\2\6 -\X887:Join the partial paths and reset \|p and \|q to the head and tail of the -result\X;\6 -\&{if} $\\{cur\_cmd}\G\\{min\_expression\_command}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}\L\\{ampersand}$ \1\&{then}\6 -\&{if} $\R\\{cycle\_hit}$ \1\&{then}\5 -\&{goto} \37\\{continue\_path};\2\2\2\6 -\4\\{finish\_path}: \37\X891:Choose control points for the path and put the -result into \\{cur\_exp}\X;\6 -\&{end}\par -\U868.\fi - -\M870. \P$\X870:Convert the left operand, \|p, into a partial path ending at~% -\|q; but \&{return} if \|p doesn't have a suitable type\X\S$\6 -\&{begin} \37$\\{unstash\_cur\_exp}(\|p)$;\6 -\&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\5 -$\|p\K\\{new\_knot}$\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{path\_type}$ \1\&{then}\5 -$\|p\K\\{cur\_exp}$\6 -\4\&{else} \&{return};\2\2\6 -$\|q\K\|p$;\6 -\&{while} $\\{link}(\|q)\I\|p$ \1\&{do}\5 -$\|q\K\\{link}(\|q)$;\2\6 -\&{if} $\\{left\_type}(\|p)\I\\{endpoint}$ \1\&{then}\C{open up a cycle}\6 -\&{begin} \37$\|r\K\\{copy\_knot}(\|p)$;\5 -$\\{link}(\|q)\K\|r$;\5 -$\|q\K\|r$;\6 -\&{end};\2\6 -$\\{left\_type}(\|p)\K\\{open}$;\5 -$\\{right\_type}(\|q)\K\\{open}$;\6 -\&{end}\par -\U869.\fi - -\M871. A pair of numeric values is changed into a knot node for a one-point -path -when \MF\ discovers that the pair is part of a path. - -\Y\P\hbox{\4}\X872:Declare the procedure called \\{known\_pair}\X\6 -\4\&{function}\1\ \37\\{new\_knot}: \37\\{pointer};\C{convert a pair to a knot -with two endpoints}\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the new node}\2\6 -\&{begin} \37$\|q\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{left\_type}(\|q)\K\\{endpoint}$;\5 -$\\{right\_type}(\|q)\K\\{endpoint}$;\5 -$\\{link}(\|q)\K\|q$;\6 -\\{known\_pair};\5 -$\\{x\_coord}(\|q)\K\\{cur\_x}$;\5 -$\\{y\_coord}(\|q)\K\\{cur\_y}$;\5 -$\\{new\_knot}\K\|q$;\6 -\&{end};\par -\fi - -\M872. The \\{known\_pair} subroutine sets \\{cur\_x} and \\{cur\_y} to the -components -of the current expression, assuming that the current expression is a -pair of known numerics. Unknown components are zeroed, and the -current expression is flushed. - -\Y\P$\4\X872:Declare the procedure called \\{known\_pair}\X\S$\6 -\4\&{procedure}\1\ \37\\{known\_pair};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the pair node}\2\6 -\&{begin} \37\&{if} $\\{cur\_type}\I\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Undefined\ coordinates\ have\ been\ replaced\ by% -\ (0,0)"})$;\5 -$\\{help5}(\.{"I\ need\ x\ and\ y\ numbers\ for\ this\ part\ of\ the\ path."})$% -\6 -$(\.{"The\ value\ I\ found\ (see\ above)\ was\ no\ good;"})$\6 -$(\.{"so\ I\'ll\ try\ to\ keep\ going\ by\ using\ zero\ instead."})$\6 -$(\.{"(Chapter\ 27\ of\ The\ METAFONTbook\ explains\ that"})$\6 -$(\.{"you\ might\ want\ to\ type\ \`I\ ???\'\ now.)"})$;\5 -$\\{put\_get\_flush\_error}(0)$;\5 -$\\{cur\_x}\K0$;\5 -$\\{cur\_y}\K0$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\5 -\X873:Make sure that both \|x and \|y parts of \|p are known; copy them into % -\\{cur\_x} and \\{cur\_y}\X;\6 -$\\{flush\_cur\_exp}(0)$;\6 -\&{end};\2\6 -\&{end};\par -\U871.\fi - -\M873. \P$\X873:Make sure that both \|x and \|y parts of \|p are known; copy -them into \\{cur\_x} and \\{cur\_y}\X\S$\6 -\&{if} $\\{type}(\\{x\_part\_loc}(\|p))=\\{known}$ \1\&{then}\5 -$\\{cur\_x}\K\\{value}(\\{x\_part\_loc}(\|p))$\6 -\4\&{else} \&{begin} \37$\\{disp\_err}(\\{x\_part\_loc}(\|p),\39\.{"Undefined\ -x\ coordinate\ has\ been\ replaced\ by\ 0"})$;\5 -$\\{help5}(\.{"I\ need\ a\ \`known\'\ x\ value\ for\ this\ part\ of\ the\ -path."})$\6 -$(\.{"The\ value\ I\ found\ (see\ above)\ was\ no\ good;"})$\6 -$(\.{"so\ I\'ll\ try\ to\ keep\ going\ by\ using\ zero\ instead."})$\6 -$(\.{"(Chapter\ 27\ of\ The\ METAFONTbook\ explains\ that"})$\6 -$(\.{"you\ might\ want\ to\ type\ \`I\ ???\'\ now.)"})$;\5 -\\{put\_get\_error};\5 -$\\{recycle\_value}(\\{x\_part\_loc}(\|p))$;\5 -$\\{cur\_x}\K0$;\6 -\&{end};\2\6 -\&{if} $\\{type}(\\{y\_part\_loc}(\|p))=\\{known}$ \1\&{then}\5 -$\\{cur\_y}\K\\{value}(\\{y\_part\_loc}(\|p))$\6 -\4\&{else} \&{begin} \37$\\{disp\_err}(\\{y\_part\_loc}(\|p),\39\.{"Undefined\ -y\ coordinate\ has\ been\ replaced\ by\ 0"})$;\5 -$\\{help5}(\.{"I\ need\ a\ \`known\'\ y\ value\ for\ this\ part\ of\ the\ -path."})$\6 -$(\.{"The\ value\ I\ found\ (see\ above)\ was\ no\ good;"})$\6 -$(\.{"so\ I\'ll\ try\ to\ keep\ going\ by\ using\ zero\ instead."})$\6 -$(\.{"(Chapter\ 27\ of\ The\ METAFONTbook\ explains\ that"})$\6 -$(\.{"you\ might\ want\ to\ type\ \`I\ ???\'\ now.)"})$;\5 -\\{put\_get\_error};\5 -$\\{recycle\_value}(\\{y\_part\_loc}(\|p))$;\5 -$\\{cur\_y}\K0$;\6 -\&{end}\2\par -\U872.\fi - -\M874. At this point \\{cur\_cmd} is either \\{ampersand}, \\{left\_brace}, or % -\\{path\_join}. - -\Y\P$\4\X874:Determine the path join parameters; but \&{goto} \\{finish\_path} -if there's only a direction specifier\X\S$\6 -\&{if} $\\{cur\_cmd}=\\{left\_brace}$ \1\&{then}\5 -\X879:Put the pre-join direction information into node \|q\X;\2\6 -$\|d\K\\{cur\_cmd}$;\6 -\&{if} $\|d=\\{path\_join}$ \1\&{then}\5 -\X881:Determine the tension and/or control points\X\6 -\4\&{else} \&{if} $\|d\I\\{ampersand}$ \1\&{then}\5 -\&{goto} \37\\{finish\_path};\2\2\6 -\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}=\\{left\_brace}$ \1\&{then}\5 -\X880:Put the post-join direction information into \|x and \|t\X\6 -\4\&{else} \&{if} $\\{right\_type}(\|q)\I\\{explicit}$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{open}$;\5 -$\|x\K0$;\6 -\&{end}\2\2\par -\U869.\fi - -\M875. The \\{scan\_direction} subroutine looks at the directional information -that is enclosed in braces, and also scans ahead to the following character. -A type code is returned, either \\{open} (if the direction was $(0,0)$), -or \\{curl} (if the direction was a curl of known value \\{cur\_exp}), or -\\{given} (if the direction is given by the \\{angle} value that now -appears in \\{cur\_exp}). - -There's nothing difficult about this subroutine, but the program is rather -lengthy because a variety of potential errors need to be nipped in the bud. - -\Y\P\4\&{function}\1\ \37\\{scan\_direction}: \37\\{small\_number};\6 -\4\&{var} \37\|t: \37$\\{given}\to\\{open}$;\C{the type of information found}\6 -\|x: \37\\{scaled};\C{an \|x coordinate}\2\6 -\&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}=\\{curl\_command}$ \1\&{then}\5 -\X876:Scan a curl specification\X\6 -\4\&{else} \X877:Scan a given direction\X;\2\6 -\&{if} $\\{cur\_cmd}\I\\{right\_brace}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"\}"})$;\6 -$\\{help3}(\.{"I\'ve\ scanned\ a\ direction\ spec\ for\ part\ of\ a\ path,"})$\6 -$(\.{"so\ a\ right\ brace\ should\ have\ come\ next."})$\6 -$(\.{"I\ shall\ pretend\ that\ one\ was\ there."})$;\6 -\\{back\_error};\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -$\\{scan\_direction}\K\|t$;\6 -\&{end};\par -\fi - -\M876. \P$\X876:Scan a curl specification\X\S$\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $(\\{cur\_type}\I\\{known})\V(\\{cur\_exp}<0)$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ curl\ has\ been\ replaced\ by\ 1"})$;\5 -$\\{help1}(\.{"A\ curl\ must\ be\ a\ known,\ nonnegative\ number."})$;\5 -$\\{put\_get\_flush\_error}(\\{unity})$;\6 -\&{end};\2\6 -$\|t\K\\{curl}$;\6 -\&{end}\par -\U875.\fi - -\M877. \P$\X877:Scan a given direction\X\S$\6 -\&{begin} \37\\{scan\_expression};\6 -\&{if} $\\{cur\_type}>\\{pair\_type}$ \1\&{then}\5 -\X878:Get given directions separated by commas\X\6 -\4\&{else} \\{known\_pair};\2\6 -\&{if} $(\\{cur\_x}=0)\W(\\{cur\_y}=0)$ \1\&{then}\5 -$\|t\K\\{open}$\6 -\4\&{else} \&{begin} \37$\|t\K\\{given}$;\5 -$\\{cur\_exp}\K\\{n\_arg}(\\{cur\_x},\39\\{cur\_y})$;\6 -\&{end};\2\6 -\&{end}\par -\U875.\fi - -\M878. \P$\X878:Get given directions separated by commas\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Undefined\ x\ coordinate\ has\ been\ replaced\ -by\ 0"})$;\5 -$\\{help5}(\.{"I\ need\ a\ \`known\'\ x\ value\ for\ this\ part\ of\ the\ -path."})$\6 -$(\.{"The\ value\ I\ found\ (see\ above)\ was\ no\ good;"})$\6 -$(\.{"so\ I\'ll\ try\ to\ keep\ going\ by\ using\ zero\ instead."})$\6 -$(\.{"(Chapter\ 27\ of\ The\ METAFONTbook\ explains\ that"})$\6 -$(\.{"you\ might\ want\ to\ type\ \`I\ ???\'\ now.)"})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\2\6 -$\|x\K\\{cur\_exp}$;\6 -\&{if} $\\{cur\_cmd}\I\\{comma}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{","})$;\6 -$\\{help2}(\.{"I\'ve\ got\ the\ x\ coordinate\ of\ a\ path\ direction;"})$\6 -$(\.{"will\ look\ for\ the\ y\ coordinate\ next."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Undefined\ y\ coordinate\ has\ been\ replaced\ -by\ 0"})$;\5 -$\\{help5}(\.{"I\ need\ a\ \`known\'\ y\ value\ for\ this\ part\ of\ the\ -path."})$\6 -$(\.{"The\ value\ I\ found\ (see\ above)\ was\ no\ good;"})$\6 -$(\.{"so\ I\'ll\ try\ to\ keep\ going\ by\ using\ zero\ instead."})$\6 -$(\.{"(Chapter\ 27\ of\ The\ METAFONTbook\ explains\ that"})$\6 -$(\.{"you\ might\ want\ to\ type\ \`I\ ???\'\ now.)"})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\2\6 -$\\{cur\_y}\K\\{cur\_exp}$;\5 -$\\{cur\_x}\K\|x$;\6 -\&{end}\par -\U877.\fi - -\M879. At this point $\\{right\_type}(\|q)$ is usually \\{open}, but it may -have been -set to some other value by a previous splicing operation. We must maintain -the value of $\\{right\_type}(\|q)$ in unusual cases such as -`\.{..z1\{z2\}\&\{z3\}z1\{0,0\}..}'. - -\Y\P$\4\X879:Put the pre-join direction information into node \|q\X\S$\6 -\&{begin} \37$\|t\K\\{scan\_direction}$;\6 -\&{if} $\|t\I\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{right\_type}(\|q)\K\|t$;\5 -$\\{right\_given}(\|q)\K\\{cur\_exp}$;\6 -\&{if} $\\{left\_type}(\|q)=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{left\_type}(\|q)\K\|t$;\5 -$\\{left\_given}(\|q)\K\\{cur\_exp}$;\6 -\&{end};\C{note that $\\{left\_given}(\|q)=\\{left\_curl}(\|q)$}\2\6 -\&{end};\2\6 -\&{end}\par -\U874.\fi - -\M880. Since \\{left\_tension} and \\{left\_y} share the same position in knot -nodes, -and since \\{left\_given} is similarly equivalent to \\{left\_x}, we use -\|x and \|y to hold the given direction and tension information when -there are no explicit control points. - -\Y\P$\4\X880:Put the post-join direction information into \|x and \|t\X\S$\6 -\&{begin} \37$\|t\K\\{scan\_direction}$;\6 -\&{if} $\\{right\_type}(\|q)\I\\{explicit}$ \1\&{then}\5 -$\|x\K\\{cur\_exp}$\6 -\4\&{else} $\|t\K\\{explicit}$;\C{the direction information is superfluous}\2\6 -\&{end}\par -\U874.\fi - -\M881. \P$\X881:Determine the tension and/or control points\X\S$\6 -\&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}=\\{tension}$ \1\&{then}\5 -\X882:Set explicit tensions\X\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{controls}$ \1\&{then}\5 -\X884:Set explicit control points\X\6 -\4\&{else} \&{begin} \37$\\{right\_tension}(\|q)\K\\{unity}$;\5 -$\|y\K\\{unity}$;\5 -\\{back\_input};\C{default tension}\6 -\&{goto} \37\\{done};\6 -\&{end};\2\2\6 -\&{if} $\\{cur\_cmd}\I\\{path\_join}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{".."})$;\6 -$\\{help1}(\.{"A\ path\ join\ command\ should\ end\ with\ two\ dots."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\4\\{done}: \37\&{end}\par -\U874.\fi - -\M882. \P$\X882:Set explicit tensions\X\S$\6 -\&{begin} \37\\{get\_x\_next};\5 -$\|y\K\\{cur\_cmd}$;\6 -\&{if} $\\{cur\_cmd}=\\{at\_least}$ \1\&{then}\5 -\\{get\_x\_next};\2\6 -\\{scan\_primary};\5 -\X883:Make sure that the current expression is a valid tension setting\X;\6 -\&{if} $\|y=\\{at\_least}$ \1\&{then}\5 -$\\{negate}(\\{cur\_exp})$;\2\6 -$\\{right\_tension}(\|q)\K\\{cur\_exp}$;\6 -\&{if} $\\{cur\_cmd}=\\{and\_command}$ \1\&{then}\6 -\&{begin} \37\\{get\_x\_next};\5 -$\|y\K\\{cur\_cmd}$;\6 -\&{if} $\\{cur\_cmd}=\\{at\_least}$ \1\&{then}\5 -\\{get\_x\_next};\2\6 -\\{scan\_primary};\5 -\X883:Make sure that the current expression is a valid tension setting\X;\6 -\&{if} $\|y=\\{at\_least}$ \1\&{then}\5 -$\\{negate}(\\{cur\_exp})$;\2\6 -\&{end};\2\6 -$\|y\K\\{cur\_exp}$;\6 -\&{end}\par -\U881.\fi - -\M883. \P\D \37$\\{min\_tension}\S\\{three\_quarter\_unit}$\par -\Y\P$\4\X883:Make sure that the current expression is a valid tension setting\X% -\S$\6 -\&{if} $(\\{cur\_type}\I\\{known})\V(\\{cur\_exp}<\\{min\_tension})$ \1\&{then}% -\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ tension\ has\ been\ set\ to\ 1"})$;\5 -$\\{help1}(\.{"The\ expression\ above\ should\ have\ been\ a\ number\ ->=3/4."})$;\5 -$\\{put\_get\_flush\_error}(\\{unity})$;\6 -\&{end}\2\par -\Us882\ET882.\fi - -\M884. \P$\X884:Set explicit control points\X\S$\6 -\&{begin} \37$\\{right\_type}(\|q)\K\\{explicit}$;\5 -$\|t\K\\{explicit}$;\5 -\\{get\_x\_next};\5 -\\{scan\_primary};\6 -\\{known\_pair};\5 -$\\{right\_x}(\|q)\K\\{cur\_x}$;\5 -$\\{right\_y}(\|q)\K\\{cur\_y}$;\6 -\&{if} $\\{cur\_cmd}\I\\{and\_command}$ \1\&{then}\6 -\&{begin} \37$\|x\K\\{right\_x}(\|q)$;\5 -$\|y\K\\{right\_y}(\|q)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\\{get\_x\_next};\5 -\\{scan\_primary};\6 -\\{known\_pair};\5 -$\|x\K\\{cur\_x}$;\5 -$\|y\K\\{cur\_y}$;\6 -\&{end};\2\6 -\&{end}\par -\U881.\fi - -\M885. \P$\X885:Convert the right operand, \\{cur\_exp}, into a partial path -from \\{pp} to~\\{qq}\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_type}\I\\{path\_type}$ \1\&{then}\5 -$\\{pp}\K\\{new\_knot}$\6 -\4\&{else} $\\{pp}\K\\{cur\_exp}$;\2\6 -$\\{qq}\K\\{pp}$;\6 -\&{while} $\\{link}(\\{qq})\I\\{pp}$ \1\&{do}\5 -$\\{qq}\K\\{link}(\\{qq})$;\2\6 -\&{if} $\\{left\_type}(\\{pp})\I\\{endpoint}$ \1\&{then}\C{open up a cycle}\6 -\&{begin} \37$\|r\K\\{copy\_knot}(\\{pp})$;\5 -$\\{link}(\\{qq})\K\|r$;\5 -$\\{qq}\K\|r$;\6 -\&{end};\2\6 -$\\{left\_type}(\\{pp})\K\\{open}$;\5 -$\\{right\_type}(\\{qq})\K\\{open}$;\6 -\&{end}\par -\U869.\fi - -\M886. If a person tries to define an entire path by saying `\.{(x,y)\&cycle}', -we silently change the specification to `\.{(x,y)..cycle}', since a cycle -shouldn't have length zero. - -\Y\P$\4\X886:Get ready to close a cycle\X\S$\6 -\&{begin} \37$\\{cycle\_hit}\K\\{true}$;\5 -\\{get\_x\_next};\5 -$\\{pp}\K\|p$;\5 -$\\{qq}\K\|p$;\6 -\&{if} $\|d=\\{ampersand}$ \1\&{then}\6 -\&{if} $\|p=\|q$ \1\&{then}\6 -\&{begin} \37$\|d\K\\{path\_join}$;\5 -$\\{right\_tension}(\|q)\K\\{unity}$;\5 -$\|y\K\\{unity}$;\6 -\&{end};\2\2\6 -\&{end}\par -\U869.\fi - -\M887. \P$\X887:Join the partial paths and reset \|p and \|q to the head and -tail of the result\X\S$\6 -\&{begin} \37\&{if} $\|d=\\{ampersand}$ \1\&{then}\6 -\&{if} $(\\{x\_coord}(\|q)\I\\{x\_coord}(\\{pp}))\V(\\{y\_coord}(\|q)\I\\{y% -\_coord}(\\{pp}))$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Paths\ don\'t\ touch;\ \`\&\'\ will\ be\ -changed\ to\ \`..\'"})$;\5 -$\\{help3}(\.{"When\ you\ join\ paths\ \`p\&q\',\ the\ ending\ point\ of\ p"})$% -\6 -$(\.{"must\ be\ exactly\ equal\ to\ the\ starting\ point\ of\ q."})$\6 -$(\.{"So\ I\'m\ going\ to\ pretend\ that\ you\ said\ \`p..q\'\ instead."})$;\5 -\\{put\_get\_error};\5 -$\|d\K\\{path\_join}$;\5 -$\\{right\_tension}(\|q)\K\\{unity}$;\5 -$\|y\K\\{unity}$;\6 -\&{end};\2\2\6 -\X889:Plug an opening in $\\{right\_type}(\\{pp})$, if possible\X;\6 -\&{if} $\|d=\\{ampersand}$ \1\&{then}\5 -\X890:Splice independent paths together\X\6 -\4\&{else} \&{begin} \37\X888:Plug an opening in $\\{right\_type}(\|q)$, if -possible\X;\6 -$\\{link}(\|q)\K\\{pp}$;\5 -$\\{left\_y}(\\{pp})\K\|y$;\6 -\&{if} $\|t\I\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{left\_x}(\\{pp})\K\|x$;\5 -$\\{left\_type}(\\{pp})\K\|t$;\6 -\&{end};\2\6 -\&{end};\2\6 -$\|q\K\\{qq}$;\6 -\&{end}\par -\U869.\fi - -\M888. \P$\X888:Plug an opening in $\\{right\_type}(\|q)$, if possible\X\S$\6 -\&{if} $\\{right\_type}(\|q)=\\{open}$ \1\&{then}\6 -\&{if} $(\\{left\_type}(\|q)=\\{curl})\V(\\{left\_type}(\|q)=\\{given})$ \1% -\&{then}\6 -\&{begin} \37$\\{right\_type}(\|q)\K\\{left\_type}(\|q)$;\5 -$\\{right\_given}(\|q)\K\\{left\_given}(\|q)$;\6 -\&{end}\2\2\par -\U887.\fi - -\M889. \P$\X889:Plug an opening in $\\{right\_type}(\\{pp})$, if possible\X\S$\6 -\&{if} $\\{right\_type}(\\{pp})=\\{open}$ \1\&{then}\6 -\&{if} $(\|t=\\{curl})\V(\|t=\\{given})$ \1\&{then}\6 -\&{begin} \37$\\{right\_type}(\\{pp})\K\|t$;\5 -$\\{right\_given}(\\{pp})\K\|x$;\6 -\&{end}\2\2\par -\U887.\fi - -\M890. \P$\X890:Splice independent paths together\X\S$\6 -\&{begin} \37\&{if} $\\{left\_type}(\|q)=\\{open}$ \1\&{then}\6 -\&{if} $\\{right\_type}(\|q)=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{left\_type}(\|q)\K\\{curl}$;\5 -$\\{left\_curl}(\|q)\K\\{unity}$;\6 -\&{end};\2\2\6 -\&{if} $\\{right\_type}(\\{pp})=\\{open}$ \1\&{then}\6 -\&{if} $\|t=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{right\_type}(\\{pp})\K\\{curl}$;\5 -$\\{right\_curl}(\\{pp})\K\\{unity}$;\6 -\&{end};\2\2\6 -$\\{right\_type}(\|q)\K\\{right\_type}(\\{pp})$;\5 -$\\{link}(\|q)\K\\{link}(\\{pp})$;\6 -$\\{right\_x}(\|q)\K\\{right\_x}(\\{pp})$;\5 -$\\{right\_y}(\|q)\K\\{right\_y}(\\{pp})$;\5 -$\\{free\_node}(\\{pp},\39\\{knot\_node\_size})$;\6 -\&{if} $\\{qq}=\\{pp}$ \1\&{then}\5 -$\\{qq}\K\|q$;\2\6 -\&{end}\par -\U887.\fi - -\M891. \P$\X891:Choose control points for the path and put the result into % -\\{cur\_exp}\X\S$\6 -\&{if} $\\{cycle\_hit}$ \1\&{then}\6 -\&{begin} \37\&{if} $\|d=\\{ampersand}$ \1\&{then}\5 -$\|p\K\|q$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{left\_type}(\|p)\K\\{endpoint}$;\6 -\&{if} $\\{right\_type}(\|p)=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{right\_type}(\|p)\K\\{curl}$;\5 -$\\{right\_curl}(\|p)\K\\{unity}$;\6 -\&{end};\2\6 -$\\{right\_type}(\|q)\K\\{endpoint}$;\6 -\&{if} $\\{left\_type}(\|q)=\\{open}$ \1\&{then}\6 -\&{begin} \37$\\{left\_type}(\|q)\K\\{curl}$;\5 -$\\{left\_curl}(\|q)\K\\{unity}$;\6 -\&{end};\2\6 -$\\{link}(\|q)\K\|p$;\6 -\&{end};\2\6 -$\\{make\_choices}(\|p)$;\5 -$\\{cur\_type}\K\\{path\_type}$;\5 -$\\{cur\_exp}\K\|p$\par -\U869.\fi - -\M892. Finally, we sometimes need to scan an expression whose value is -supposed to be either \\{true\_code} or \\{false\_code}. - -\Y\P$\4\X823:Declare the basic parsing subroutines\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{get\_boolean};\2\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{boolean\_type}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Undefined\ condition\ will\ be\ treated\ as\ % -\`false\'"})$;\5 -$\\{help2}(\.{"The\ expression\ shown\ above\ should\ have\ had\ a\ -definite"})$\6 -$(\.{"true-or-false\ value.\ I\'m\ changing\ it\ to\ \`false\'."})$;\6 -$\\{put\_get\_flush\_error}(\\{false\_code})$;\5 -$\\{cur\_type}\K\\{boolean\_type}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\N893. \[42] Doing the operations. -The purpose of parsing is primarily to permit people to avoid piles of -parentheses. But the real work is done after the structure of an expression -has been recognized; that's when new expressions are generated. We -turn now to the guts of \MF, which handles individual operators that -have come through the parsing mechanism. - -We'll start with the easy ones that take no operands, then work our way -up to operators with one and ultimately two arguments. In other words, -we will write the three procedures \\{do\_nullary}, \\{do\_unary}, and \\{do% -\_binary} -that are invoked periodically by the expression scanners. - -First let's make sure that all of the primitive operators are in the -hash table. Although \\{scan\_primary} and its relatives made use of the -\\{cmd} code for these operators, the \\{do} routines base everything -on the \\{mod} code. For example, \\{do\_binary} doesn't care whether the -operation it performs is a \\{primary\_binary} or \\{secondary\_binary}, etc. - -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"true"},\39\\{nullary},\39\\{true\_code})$;\6 -$\\{primitive}(\.{"false"},\39\\{nullary},\39\\{false\_code})$;\6 -$\\{primitive}(\.{"nullpicture"},\39\\{nullary},\39\\{null\_picture\_code})$;\6 -$\\{primitive}(\.{"nullpen"},\39\\{nullary},\39\\{null\_pen\_code})$;\6 -$\\{primitive}(\.{"jobname"},\39\\{nullary},\39\\{job\_name\_op})$;\6 -$\\{primitive}(\.{"readstring"},\39\\{nullary},\39\\{read\_string\_op})$;\6 -$\\{primitive}(\.{"pencircle"},\39\\{nullary},\39\\{pen\_circle})$;\6 -$\\{primitive}(\.{"normaldeviate"},\39\\{nullary},\39\\{normal\_deviate})$;\6 -$\\{primitive}(\.{"odd"},\39\\{unary},\39\\{odd\_op})$;\6 -$\\{primitive}(\.{"known"},\39\\{unary},\39\\{known\_op})$;\6 -$\\{primitive}(\.{"unknown"},\39\\{unary},\39\\{unknown\_op})$;\6 -$\\{primitive}(\.{"not"},\39\\{unary},\39\\{not\_op})$;\6 -$\\{primitive}(\.{"decimal"},\39\\{unary},\39\\{decimal})$;\6 -$\\{primitive}(\.{"reverse"},\39\\{unary},\39\\{reverse})$;\6 -$\\{primitive}(\.{"makepath"},\39\\{unary},\39\\{make\_path\_op})$;\6 -$\\{primitive}(\.{"makepen"},\39\\{unary},\39\\{make\_pen\_op})$;\6 -$\\{primitive}(\.{"totalweight"},\39\\{unary},\39\\{total\_weight\_op})$;\6 -$\\{primitive}(\.{"oct"},\39\\{unary},\39\\{oct\_op})$;\6 -$\\{primitive}(\.{"hex"},\39\\{unary},\39\\{hex\_op})$;\6 -$\\{primitive}(\.{"ASCII"},\39\\{unary},\39\\{ASCII\_op})$;\6 -$\\{primitive}(\.{"char"},\39\\{unary},\39\\{char\_op})$;\6 -$\\{primitive}(\.{"length"},\39\\{unary},\39\\{length\_op})$;\6 -$\\{primitive}(\.{"turningnumber"},\39\\{unary},\39\\{turning\_op})$;\6 -$\\{primitive}(\.{"xpart"},\39\\{unary},\39\\{x\_part})$;\6 -$\\{primitive}(\.{"ypart"},\39\\{unary},\39\\{y\_part})$;\6 -$\\{primitive}(\.{"xxpart"},\39\\{unary},\39\\{xx\_part})$;\6 -$\\{primitive}(\.{"xypart"},\39\\{unary},\39\\{xy\_part})$;\6 -$\\{primitive}(\.{"yxpart"},\39\\{unary},\39\\{yx\_part})$;\6 -$\\{primitive}(\.{"yypart"},\39\\{unary},\39\\{yy\_part})$;\6 -$\\{primitive}(\.{"sqrt"},\39\\{unary},\39\\{sqrt\_op})$;\6 -$\\{primitive}(\.{"mexp"},\39\\{unary},\39\\{m\_exp\_op})$;\6 -$\\{primitive}(\.{"mlog"},\39\\{unary},\39\\{m\_log\_op})$;\6 -$\\{primitive}(\.{"sind"},\39\\{unary},\39\\{sin\_d\_op})$;\6 -$\\{primitive}(\.{"cosd"},\39\\{unary},\39\\{cos\_d\_op})$;\6 -$\\{primitive}(\.{"floor"},\39\\{unary},\39\\{floor\_op})$;\6 -$\\{primitive}(\.{"uniformdeviate"},\39\\{unary},\39\\{uniform\_deviate})$;\6 -$\\{primitive}(\.{"charexists"},\39\\{unary},\39\\{char\_exists\_op})$;\6 -$\\{primitive}(\.{"angle"},\39\\{unary},\39\\{angle\_op})$;\6 -$\\{primitive}(\.{"cycle"},\39\\{cycle},\39\\{cycle\_op})$;\6 -$\\{primitive}(\.{"+"},\39\\{plus\_or\_minus},\39\\{plus})$;\6 -$\\{primitive}(\.{"-"},\39\\{plus\_or\_minus},\39\\{minus})$;\6 -$\\{primitive}(\.{"*"},\39\\{secondary\_binary},\39\\{times})$;\6 -$\\{primitive}(\.{"/"},\39\\{slash},\39\\{over})$;\5 -$\\{eqtb}[\\{frozen\_slash}]\K\\{eqtb}[\\{cur\_sym}]$;\6 -$\\{primitive}(\.{"++"},\39\\{tertiary\_binary},\39\\{pythag\_add})$;\6 -$\\{primitive}(\.{"+-+"},\39\\{tertiary\_binary},\39\\{pythag\_sub})$;\6 -$\\{primitive}(\.{"and"},\39\\{and\_command},\39\\{and\_op})$;\6 -$\\{primitive}(\.{"or"},\39\\{tertiary\_binary},\39\\{or\_op})$;\6 -$\\{primitive}(\.{"<"},\39\\{expression\_binary},\39\\{less\_than})$;\6 -$\\{primitive}(\.{"<="},\39\\{expression\_binary},\39\\{less\_or\_equal})$;\6 -$\\{primitive}(\.{">"},\39\\{expression\_binary},\39\\{greater\_than})$;\6 -$\\{primitive}(\.{">="},\39\\{expression\_binary},\39\\{greater\_or\_equal})$;\6 -$\\{primitive}(\.{"="},\39\\{equals},\39\\{equal\_to})$;\6 -$\\{primitive}(\.{"<>"},\39\\{expression\_binary},\39\\{unequal\_to})$;\6 -$\\{primitive}(\.{"substring"},\39\\{primary\_binary},\39\\{substring\_of})$;\6 -$\\{primitive}(\.{"subpath"},\39\\{primary\_binary},\39\\{subpath\_of})$;\6 -$\\{primitive}(\.{"directiontime"},\39\\{primary\_binary},\39\\{direction\_time% -\_of})$;\6 -$\\{primitive}(\.{"point"},\39\\{primary\_binary},\39\\{point\_of})$;\6 -$\\{primitive}(\.{"precontrol"},\39\\{primary\_binary},\39\\{precontrol\_of})$;% -\6 -$\\{primitive}(\.{"postcontrol"},\39\\{primary\_binary},\39\\{postcontrol% -\_of})$;\6 -$\\{primitive}(\.{"penoffset"},\39\\{primary\_binary},\39\\{pen\_offset\_of})$;% -\6 -$\\{primitive}(\.{"\&"},\39\\{ampersand},\39\\{concatenate})$;\6 -$\\{primitive}(\.{"rotated"},\39\\{secondary\_binary},\39\\{rotated\_by})$;\6 -$\\{primitive}(\.{"slanted"},\39\\{secondary\_binary},\39\\{slanted\_by})$;\6 -$\\{primitive}(\.{"scaled"},\39\\{secondary\_binary},\39\\{scaled\_by})$;\6 -$\\{primitive}(\.{"shifted"},\39\\{secondary\_binary},\39\\{shifted\_by})$;\6 -$\\{primitive}(\.{"transformed"},\39\\{secondary\_binary},\39\\{transformed% -\_by})$;\6 -$\\{primitive}(\.{"xscaled"},\39\\{secondary\_binary},\39\\{x\_scaled})$;\6 -$\\{primitive}(\.{"yscaled"},\39\\{secondary\_binary},\39\\{y\_scaled})$;\6 -$\\{primitive}(\.{"zscaled"},\39\\{secondary\_binary},\39\\{z\_scaled})$;\6 -$\\{primitive}(\.{"intersectiontimes"},\39\\{tertiary\_binary},\39% -\\{intersect})$;\par -\fi - -\M894. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4$\\{nullary},\39\\{unary},\39\\{primary\_binary},\39\\{secondary\_binary},\39% -\\{tertiary\_binary},\39\\{expression\_binary},\39\\{cycle},\39\\{plus\_or% -\_minus},\39\\{slash},\39\\{ampersand},\39\\{equals},\39\\{and\_command}$: \37$% -\\{print\_op}(\|m)$;\par -\fi - -\M895. OK, let's look at the simplest \\{do} procedure first. - -\Y\P\4\&{procedure}\1\ \37$\\{do\_nullary}(\|c:\\{quarterword})$;\6 -\4\&{var} \37\|k: \37\\{integer};\C{all-purpose loop index}\2\6 -\&{begin} \37\\{check\_arith};\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{two}$ \1\&{then}\5 -$\\{show\_cmd\_mod}(\\{nullary},\39\|c)$;\2\6 -\&{case} $\|c$ \1\&{of}\6 -\4$\\{true\_code},\39\\{false\_code}$: \37\&{begin} \37$\\{cur\_type}\K% -\\{boolean\_type}$;\5 -$\\{cur\_exp}\K\|c$;\6 -\&{end};\6 -\4\\{null\_picture\_code}: \37\&{begin} \37$\\{cur\_type}\K\\{picture\_type}$;\5 -$\\{cur\_exp}\K\\{get\_node}(\\{edge\_header\_size})$;\5 -$\\{init\_edges}(\\{cur\_exp})$;\6 -\&{end};\6 -\4\\{null\_pen\_code}: \37\&{begin} \37$\\{cur\_type}\K\\{pen\_type}$;\5 -$\\{cur\_exp}\K\\{null\_pen}$;\6 -\&{end};\6 -\4\\{normal\_deviate}: \37\&{begin} \37$\\{cur\_type}\K\\{known}$;\5 -$\\{cur\_exp}\K\\{norm\_rand}$;\6 -\&{end};\6 -\4\\{pen\_circle}: \37\X896:Make a special knot node for \&{pencircle}\X;\6 -\4\\{job\_name\_op}: \37\&{begin} \37\&{if} $\\{job\_name}=0$ \1\&{then}\5 -\\{open\_log\_file};\2\6 -$\\{cur\_type}\K\\{string\_type}$;\5 -$\\{cur\_exp}\K\\{job\_name}$;\6 -\&{end};\6 -\4\\{read\_string\_op}: \37\X897:Read a string from the terminal\X;\2\6 -\&{end};\C{there are no other cases}\6 -\\{check\_arith};\6 -\&{end};\par -\fi - -\M896. \P$\X896:Make a special knot node for \&{pencircle}\X\S$\6 -\&{begin} \37$\\{cur\_type}\K\\{future\_pen}$;\5 -$\\{cur\_exp}\K\\{get\_node}(\\{knot\_node\_size})$;\5 -$\\{left\_type}(\\{cur\_exp})\K\\{open}$;\5 -$\\{right\_type}(\\{cur\_exp})\K\\{open}$;\5 -$\\{link}(\\{cur\_exp})\K\\{cur\_exp}$;\6 -$\\{x\_coord}(\\{cur\_exp})\K0$;\5 -$\\{y\_coord}(\\{cur\_exp})\K0$;\6 -$\\{left\_x}(\\{cur\_exp})\K\\{unity}$;\5 -$\\{left\_y}(\\{cur\_exp})\K0$;\6 -$\\{right\_x}(\\{cur\_exp})\K0$;\5 -$\\{right\_y}(\\{cur\_exp})\K\\{unity}$;\6 -\&{end}\par -\U895.\fi - -\M897. \P$\X897:Read a string from the terminal\X\S$\6 -\&{begin} \37\&{if} $\\{interaction}\L\\{nonstop\_mode}$ \1\&{then}\5 -$\\{fatal\_error}(\.{"***\ (cannot\ readstring\ in\ nonstop\ modes)"})$;\2\6 -\\{begin\_file\_reading};\5 -$\\{name}\K1$;\5 -$\\{prompt\_input}(\.{""})$;\5 -$\\{str\_room}(\\{last}-\\{start})$;\6 -\&{for} $\|k\K\\{start}\mathrel{\&{to}}\\{last}-1$ \1\&{do}\5 -$\\{append\_char}(\\{buffer}[\|k])$;\2\6 -\\{end\_file\_reading};\5 -$\\{cur\_type}\K\\{string\_type}$;\5 -$\\{cur\_exp}\K\\{make\_string}$;\6 -\&{end}\par -\U895.\fi - -\M898. Things get a bit more interesting when there's an operand. The -operand to \\{do\_unary} appears in \\{cur\_type} and \\{cur\_exp}. - -\Y\P\hbox{\4}\X899:Declare unary action procedures\X\6 -\4\&{procedure}\1\ \37$\\{do\_unary}(\|c:\\{quarterword})$;\6 -\4\&{var} \37$\|p,\39\|q$: \37\\{pointer};\C{for list manipulation}\6 -\|x: \37\\{integer};\C{a temporary register}\2\6 -\&{begin} \37\\{check\_arith};\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{two}$ \1\&{then}\5 -\X902:Trace the current unary operation\X;\2\6 -\&{case} $\|c$ \1\&{of}\6 -\4\\{plus}: \37\&{if} $\\{cur\_type}<\\{pair\_type}$ \1\&{then}\6 -\&{if} $\\{cur\_type}\I\\{picture\_type}$ \1\&{then}\5 -$\\{bad\_unary}(\\{plus})$;\2\2\6 -\4\\{minus}: \37\X903:Negate the current expression\X;\6 -\hbox{\4}\X905:Additional cases of unary operators\X\2\6 -\&{end};\C{there are no other cases}\6 -\\{check\_arith};\6 -\&{end};\par -\fi - -\M899. The \\{nice\_pair} function returns \\{true} if both components of a -pair -are known. - -\Y\P$\4\X899:Declare unary action procedures\X\S$\6 -\4\&{function}\1\ \37$\\{nice\_pair}(\|p:\\{integer};\,\35\|t:% -\\{quarterword})$: \37\\{boolean};\6 -\4\&{label} \37\\{exit};\2\6 -\&{begin} \37\&{if} $\|t=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{value}(\|p)$;\6 -\&{if} $\\{type}(\\{x\_part\_loc}(\|p))=\\{known}$ \1\&{then}\6 -\&{if} $\\{type}(\\{y\_part\_loc}(\|p))=\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{nice\_pair}\K\\{true}$;\5 -\&{return};\6 -\&{end};\2\2\6 -\&{end};\2\6 -$\\{nice\_pair}\K\\{false}$;\6 -\4\\{exit}: \37\&{end};\par -\As900, 901, 904, 908, 910, 913, 916\ETs919. -\U898.\fi - -\M900. \P$\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{print\_known\_or\_unknown\_type}(\|t:\\{small% -\_number};\,\35\|v:\\{integer})$;\2\6 -\&{begin} \37$\\{print\_char}(\.{"("})$;\6 -\&{if} $\|t<\\{dependent}$ \1\&{then}\6 -\&{if} $\|t\I\\{pair\_type}$ \1\&{then}\5 -$\\{print\_type}(\|t)$\6 -\4\&{else} \&{if} $\\{nice\_pair}(\|v,\39\\{pair\_type})$ \1\&{then}\5 -$\\{print}(\.{"pair"})$\6 -\4\&{else} $\\{print}(\.{"unknown\ pair"})$\2\2\6 -\4\&{else} $\\{print}(\.{"unknown\ numeric"})$;\2\6 -$\\{print\_char}(\.{")"})$;\6 -\&{end};\par -\fi - -\M901. \P$\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{bad\_unary}(\|c:\\{quarterword})$;\2\6 -\&{begin} \37$\\{exp\_err}(\.{"Not\ implemented:\ "})$;\5 -$\\{print\_op}(\|c)$;\5 -$\\{print\_known\_or\_unknown\_type}(\\{cur\_type},\39\\{cur\_exp})$;\5 -$\\{help3}(\.{"I\'m\ afraid\ I\ don\'t\ know\ how\ to\ apply\ that\ operation\ -to\ that"})$\6 -$(\.{"particular\ type.\ Continue,\ and\ I\'ll\ simply\ return\ the"})$\6 -$(\.{"argument\ (shown\ above)\ as\ the\ result\ of\ the\ operation."})$;\5 -\\{put\_get\_error};\6 -\&{end};\par -\fi - -\M902. \P$\X902:Trace the current unary operation\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{"})$;\5 -$\\{print\_op}(\|c)$;\5 -$\\{print\_char}(\.{"("})$;\6 -$\\{print\_exp}(\\{null},\390)$;\C{show the operand, but not verbosely}\6 -$\\{print}(\.{")\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U898.\fi - -\M903. Negation is easy except when the current expression -is of type \\{independent}, or when it is a pair with one or more -\\{independent} components. - -It is tempting to argue that the negative of an independent variable -is an independent variable, hence we don't have to do anything when -negating it. The fallacy is that other dependent variables pointing -to the current expression must change the sign of their -coefficients if we make no change to the current expression. - -Instead, we work around the problem by copying the current expression -and recycling it afterwards (cf.~the \\{stash\_in} routine). - -\Y\P$\4\X903:Negate the current expression\X\S$\6 -\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{pair\_type},\39\\{independent}$: \37\&{begin} \37$\|q\K\\{cur\_exp}$;\5 -$\\{make\_exp\_copy}(\|q)$;\6 -\&{if} $\\{cur\_type}=\\{dependent}$ \1\&{then}\5 -$\\{negate\_dep\_list}(\\{dep\_list}(\\{cur\_exp}))$\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\6 -\&{if} $\\{type}(\\{x\_part\_loc}(\|p))=\\{known}$ \1\&{then}\5 -$\\{negate}(\\{value}(\\{x\_part\_loc}(\|p)))$\6 -\4\&{else} $\\{negate\_dep\_list}(\\{dep\_list}(\\{x\_part\_loc}(\|p)))$;\2\6 -\&{if} $\\{type}(\\{y\_part\_loc}(\|p))=\\{known}$ \1\&{then}\5 -$\\{negate}(\\{value}(\\{y\_part\_loc}(\|p)))$\6 -\4\&{else} $\\{negate\_dep\_list}(\\{dep\_list}(\\{y\_part\_loc}(\|p)))$;\2\6 -\&{end};\C{if $\\{cur\_type}=\\{known}$ then $\\{cur\_exp}=0$}\2\2\6 -$\\{recycle\_value}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{value\_node\_size})$;\6 -\&{end};\6 -\4$\\{dependent},\39\\{proto\_dependent}$: \37$\\{negate\_dep\_list}(\\{dep% -\_list}(\\{cur\_exp}))$;\6 -\4\\{known}: \37$\\{negate}(\\{cur\_exp})$;\6 -\4\\{picture\_type}: \37$\\{negate\_edges}(\\{cur\_exp})$;\6 -\4\&{othercases} \37$\\{bad\_unary}(\\{minus})$\2\6 -\&{endcases}\par -\U898.\fi - -\M904. \P$\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{negate\_dep\_list}(\|p:\\{pointer})$;\6 -\4\&{label} \37\\{exit};\2\6 -\&{begin} \37\~ \1\&{loop}\ \&{begin} \37$\\{negate}(\\{value}(\|p))$;\6 -\&{if} $\\{info}(\|p)=\\{null}$ \1\&{then}\5 -\&{return};\2\6 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M905. \P$\X905:Additional cases of unary operators\X\S$\6 -\4\\{not\_op}: \37\&{if} $\\{cur\_type}\I\\{boolean\_type}$ \1\&{then}\5 -$\\{bad\_unary}(\\{not\_op})$\6 -\4\&{else} $\\{cur\_exp}\K\\{true\_code}+\\{false\_code}-\\{cur\_exp}$;\2\par -\As906, 907, 909, 912, 915, 917, 918, 920\ETs921. -\U898.\fi - -\M906. \P\D \37$\\{three\_sixty\_units}\S23592960$\C{that's $360\ast\\{unity}$}% -\par -\P\D \37$\\{boolean\_reset}(\#)\S$\1\6 -\&{if} $\#$ \1\&{then}\5 -$\\{cur\_exp}\K\\{true\_code}$\ \&{else} $\\{cur\_exp}\K\\{false\_code}$\2\2\par -\Y\P$\4\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4$\\{sqrt\_op},\39\\{m\_exp\_op},\39\\{m\_log\_op},\39\\{sin\_d\_op},\39\\{cos% -\_d\_op},\39\\{floor\_op},\39\\{uniform\_deviate},\39\\{odd\_op},\39\\{char% -\_exists\_op}$: \37\hbox{}\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -$\\{bad\_unary}(\|c)$\6 -\4\&{else} \&{case} $\|c$ \1\&{of}\6 -\4\\{sqrt\_op}: \37$\\{cur\_exp}\K\\{square\_rt}(\\{cur\_exp})$;\6 -\4\\{m\_exp\_op}: \37$\\{cur\_exp}\K\\{m\_exp}(\\{cur\_exp})$;\6 -\4\\{m\_log\_op}: \37$\\{cur\_exp}\K\\{m\_log}(\\{cur\_exp})$;\6 -\4$\\{sin\_d\_op},\39\\{cos\_d\_op}$: \37\&{begin} \37$\\{n\_sin\_cos}((\\{cur% -\_exp}\mathbin{\&{mod}}\\{three\_sixty\_units})\ast16)$;\6 -\&{if} $\|c=\\{sin\_d\_op}$ \1\&{then}\5 -$\\{cur\_exp}\K\\{round\_fraction}(\\{n\_sin})$\6 -\4\&{else} $\\{cur\_exp}\K\\{round\_fraction}(\\{n\_cos})$;\2\6 -\&{end};\6 -\4\\{floor\_op}: \37$\\{cur\_exp}\K\\{floor\_scaled}(\\{cur\_exp})$;\6 -\4\\{uniform\_deviate}: \37$\\{cur\_exp}\K\\{unif\_rand}(\\{cur\_exp})$;\6 -\4\\{odd\_op}: \37\&{begin} \37$\\{boolean\_reset}(\\{odd}(\\{round\_unscaled}(% -\\{cur\_exp})))$;\5 -$\\{cur\_type}\K\\{boolean\_type}$;\6 -\&{end};\6 -\4\\{char\_exists\_op}: \37\X1181:Determine if a character has been shipped out% -\X;\2\6 -\&{end};\C{there are no other cases}\2\par -\fi - -\M907. \P$\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4\\{angle\_op}: \37\&{if} $\\{nice\_pair}(\\{cur\_exp},\39\\{cur\_type})$ \1% -\&{then}\6 -\&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\5 -$\|x\K\\{n\_arg}(\\{value}(\\{x\_part\_loc}(\|p)),\39\\{value}(\\{y\_part% -\_loc}(\|p)))$;\6 -\&{if} $\|x\G0$ \1\&{then}\5 -$\\{flush\_cur\_exp}((\|x+8)\mathbin{\&{div}}16)$\6 -\4\&{else} $\\{flush\_cur\_exp}(-((-\|x+8)\mathbin{\&{div}}16))$;\2\6 -\&{end}\6 -\4\&{else} $\\{bad\_unary}(\\{angle\_op})$;\2\par -\fi - -\M908. If the current expression is a pair, but the context wants it to -be a path, we call \\{pair\_to\_path}. - -\Y\P$\4\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{pair\_to\_path};\2\6 -\&{begin} \37$\\{cur\_exp}\K\\{new\_knot}$;\5 -$\\{cur\_type}\K\\{path\_type}$;\6 -\&{end};\par -\fi - -\M909. \P$\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4$\\{x\_part},\39\\{y\_part}$: \37\&{if} $(\\{cur\_type}\L\\{pair\_type})\W(% -\\{cur\_type}\G\\{transform\_type})$ \1\&{then}\5 -$\\{take\_part}(\|c)$\6 -\4\&{else} $\\{bad\_unary}(\|c)$;\2\6 -\4$\\{xx\_part},\39\\{xy\_part},\39\\{yx\_part},\39\\{yy\_part}$: \37\&{if} $% -\\{cur\_type}=\\{transform\_type}$ \1\&{then}\5 -$\\{take\_part}(\|c)$\6 -\4\&{else} $\\{bad\_unary}(\|c)$;\2\par -\fi - -\M910. In the following procedure, \\{cur\_exp} points to a capsule, which -points to -a big node. We want to delete all but one part of the big node. - -\Y\P$\4\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{take\_part}(\|c:\\{quarterword})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the big node}\2\6 -\&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\5 -$\\{value}(\\{temp\_val})\K\|p$;\5 -$\\{type}(\\{temp\_val})\K\\{cur\_type}$;\5 -$\\{link}(\|p)\K\\{temp\_val}$;\5 -$\\{free\_node}(\\{cur\_exp},\39\\{value\_node\_size})$;\5 -$\\{make\_exp\_copy}(\|p+2\ast(\|c-\\{x\_part}))$;\5 -$\\{recycle\_value}(\\{temp\_val})$;\6 -\&{end};\par -\fi - -\M911. \P$\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}% -\S$\6 -$\\{name\_type}(\\{temp\_val})\K\\{capsule}$;\par -\fi - -\M912. \P$\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4\\{char\_op}: \37\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -$\\{bad\_unary}(\\{char\_op})$\6 -\4\&{else} \&{begin} \37$\\{cur\_exp}\K\\{round\_unscaled}(\\{cur\_exp})% -\mathbin{\&{mod}}256$;\5 -$\\{cur\_type}\K\\{string\_type}$;\6 -\&{if} $\\{cur\_exp}<0$ \1\&{then}\5 -$\\{cur\_exp}\K\\{cur\_exp}+256$;\2\6 -\&{if} $\\{length}(\\{cur\_exp})\I1$ \1\&{then}\6 -\&{begin} \37$\\{str\_room}(1)$;\5 -$\\{append\_char}(\\{cur\_exp})$;\5 -$\\{cur\_exp}\K\\{make\_string}$;\6 -\&{end};\2\6 -\&{end};\2\6 -\4\\{decimal}: \37\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -$\\{bad\_unary}(\\{decimal})$\6 -\4\&{else} \&{begin} \37$\\{old\_setting}\K\\{selector}$;\5 -$\\{selector}\K\\{new\_string}$;\5 -$\\{print\_scaled}(\\{cur\_exp})$;\5 -$\\{cur\_exp}\K\\{make\_string}$;\5 -$\\{selector}\K\\{old\_setting}$;\5 -$\\{cur\_type}\K\\{string\_type}$;\6 -\&{end};\2\6 -\4$\\{oct\_op},\39\\{hex\_op},\39\\{ASCII\_op}$: \37\&{if} $\\{cur\_type}\I% -\\{string\_type}$ \1\&{then}\5 -$\\{bad\_unary}(\|c)$\6 -\4\&{else} $\\{str\_to\_num}(\|c)$;\2\par -\fi - -\M913. \P$\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{str\_to\_num}(\|c:\\{quarterword})$;\C{converts a -string to a number}\6 -\4\&{var} \37\|n: \37\\{integer};\C{accumulator}\6 -\|m: \37\\{ASCII\_code};\C{current character}\6 -\|k: \37\\{pool\_pointer};\C{index into \\{str\_pool}}\6 -\|b: \37$8\to16$;\C{radix of conversion}\6 -\\{bad\_char}: \37\\{boolean};\C{did the string contain an invalid digit?}\2\6 -\&{begin} \37\&{if} $\|c=\\{ASCII\_op}$ \1\&{then}\6 -\&{if} $\\{length}(\\{cur\_exp})=0$ \1\&{then}\5 -$\|n\K-1$\6 -\4\&{else} $\|n\K\\{so}(\\{str\_pool}[\\{str\_start}[\\{cur\_exp}]])$\2\6 -\4\&{else} \&{begin} \37\&{if} $\|c=\\{oct\_op}$ \1\&{then}\5 -$\|b\K8$\ \&{else} $\|b\K16$;\2\6 -$\|n\K0$;\5 -$\\{bad\_char}\K\\{false}$;\6 -\&{for} $\|k\K\\{str\_start}[\\{cur\_exp}]\mathrel{\&{to}}\\{str\_start}[\\{cur% -\_exp}+1]-1$ \1\&{do}\6 -\&{begin} \37$\|m\K\\{so}(\\{str\_pool}[\|k])$;\6 -\&{if} $(\|m\G\.{"0"})\W(\|m\L\.{"9"})$ \1\&{then}\5 -$\|m\K\|m-\.{"0"}$\6 -\4\&{else} \&{if} $(\|m\G\.{"A"})\W(\|m\L\.{"F"})$ \1\&{then}\5 -$\|m\K\|m-\.{"A"}+10$\6 -\4\&{else} \&{if} $(\|m\G\.{"a"})\W(\|m\L\.{"f"})$ \1\&{then}\5 -$\|m\K\|m-\.{"a"}+10$\6 -\4\&{else} \&{begin} \37$\\{bad\_char}\K\\{true}$;\5 -$\|m\K0$;\6 -\&{end};\2\2\2\6 -\&{if} $\|m\G\|b$ \1\&{then}\6 -\&{begin} \37$\\{bad\_char}\K\\{true}$;\5 -$\|m\K0$;\6 -\&{end};\2\6 -\&{if} $\|n<32768\mathbin{\&{div}}\|b$ \1\&{then}\5 -$\|n\K\|n\ast\|b+\|m$\ \&{else} $\|n\K32767$;\2\6 -\&{end};\2\6 -\X914:Give error messages if \\{bad\_char} or $\|n\G4096$\X;\6 -\&{end};\2\6 -$\\{flush\_cur\_exp}(\|n\ast\\{unity})$;\6 -\&{end};\par -\fi - -\M914. \P$\X914:Give error messages if \\{bad\_char} or $\|n\G4096$\X\S$\6 -\&{if} $\\{bad\_char}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"String\ contains\ illegal\ digits"})$;\6 -\&{if} $\|c=\\{oct\_op}$ \1\&{then}\5 -$\\{help1}(\.{"I\ zeroed\ out\ characters\ that\ weren\'t\ in\ the\ range\ -0..7."})$\6 -\4\&{else} $\\{help1}(\.{"I\ zeroed\ out\ characters\ that\ weren\'t\ hex\ -digits."})$;\2\6 -\\{put\_get\_error};\6 -\&{end};\2\6 -\&{if} $\|n>4095$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Number\ too\ large\ ("})$;\5 -$\\{print\_int}(\|n)$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\\{help1}(\.{"I\ have\ trouble\ with\ numbers\ greater\ than\ 4095;\ watch\ -out."})$;\5 -\\{put\_get\_error};\6 -\&{end}\2\par -\U913.\fi - -\M915. The length operation is somewhat unusual in that it applies to a variety -of different types of operands. - -\Y\P$\4\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4\\{length\_op}: \37\&{if} $\\{cur\_type}=\\{string\_type}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\\{length}(\\{cur\_exp})\ast\\{unity})$\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{path\_type}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\\{path\_length})$\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -$\\{cur\_exp}\K\\{abs}(\\{cur\_exp})$\6 -\4\&{else} \&{if} $\\{nice\_pair}(\\{cur\_exp},\39\\{cur\_type})$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\\{pyth\_add}(\\{value}(\\{x\_part\_loc}(\\{value}(\\{cur% -\_exp}))),\39\30\\{value}(\\{y\_part\_loc}(\\{value}(\\{cur\_exp})))))$\6 -\4\&{else} $\\{bad\_unary}(\|c)$;\2\2\2\2\par -\fi - -\M916. \P$\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{function}\1\ \37\\{path\_length}: \37\\{scaled};\C{computes the length of -the current path}\6 -\4\&{var} \37\|n: \37\\{scaled};\C{the path length so far}\6 -\|p: \37\\{pointer};\C{traverser}\2\6 -\&{begin} \37$\|p\K\\{cur\_exp}$;\6 -\&{if} $\\{left\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -$\|n\K-\\{unity}$\ \&{else} $\|n\K0$;\2\6 -\1\&{repeat} \37$\|p\K\\{link}(\|p)$;\5 -$\|n\K\|n+\\{unity}$;\6 -\4\&{until}\5 -$\|p=\\{cur\_exp}$;\2\6 -$\\{path\_length}\K\|n$;\6 -\&{end};\par -\fi - -\M917. The turning number is computed only with respect to null pens. A -different -pen might affect the turning number, in degenerate cases, because autorounding -will produce a slightly different path, or because excessively large -coordinates -might be truncated. - -\Y\P$\4\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4\\{turning\_op}: \37\&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(0)$\6 -\4\&{else} \&{if} $\\{cur\_type}\I\\{path\_type}$ \1\&{then}\5 -$\\{bad\_unary}(\\{turning\_op})$\6 -\4\&{else} \&{if} $\\{left\_type}(\\{cur\_exp})=\\{endpoint}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(0)$\C{not a cyclic path}\6 -\4\&{else} \&{begin} \37$\\{cur\_pen}\K\\{null\_pen}$;\5 -$\\{cur\_path\_type}\K\\{contour\_code}$;\5 -$\\{cur\_exp}\K\\{make\_spec}(\\{cur\_exp},\39\\{fraction\_one}-\\{half% -\_unit}-1-\\{el\_gordo},\390)$;\5 -$\\{flush\_cur\_exp}(\\{turning\_number}\ast\\{unity})$;\C{convert to % -\\{scaled}}\6 -\&{end};\2\2\2\par -\fi - -\M918. \P\D \37$\\{type\_test\_end}\S\\{flush\_cur\_exp}(\\{true\_code})$\6 -\4\&{else} \37$\\{flush\_cur\_exp}(\\{false\_code})$;\5 -$\\{cur\_type}\K\\{boolean\_type}$; \6 -\&{end} \par -\P\D $\\{type\_range\_end}(\#)\S(\\{cur\_type}\L\#)$ \&{then} \\{type\_test% -\_end}\par -\P\D $\\{type\_range}(\#)\S$ \6 -\&{begin} \6 -\&{if} $(\\{cur\_type}\G\#)\W\\{type\_range\_end}$\par -\P\D $\\{type\_test}(\#)\S$ \6 -\&{begin} \37\&{if} $\\{cur\_type}=\#$ \1\&{then}\5 -\\{type\_test\_end}\2\par -\Y\P$\4\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4\\{boolean\_type}: \37$\\{type\_range}(\\{boolean\_type})(\\{unknown% -\_boolean})$;\6 -\4\\{string\_type}: \37$\\{type\_range}(\\{string\_type})(\\{unknown% -\_string})$;\6 -\4\\{pen\_type}: \37$\\{type\_range}(\\{pen\_type})(\\{future\_pen})$;\6 -\4\\{path\_type}: \37$\\{type\_range}(\\{path\_type})(\\{unknown\_path})$;\6 -\4\\{picture\_type}: \37$\\{type\_range}(\\{picture\_type})(\\{unknown% -\_picture})$;\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37$\\{type\_test}(\|c)$;\6 -\4\\{numeric\_type}: \37$\\{type\_range}(\\{known})(\\{independent})$;\6 -\4$\\{known\_op},\39\\{unknown\_op}$: \37$\\{test\_known}(\|c)$;\par -\fi - -\M919. \P$\X899:Declare unary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{test\_known}(\|c:\\{quarterword})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|b: \37$\\{true\_code}\to\\{false\_code}$;\C{is the current -expression known?}\6 -$\|p,\39\|q$: \37\\{pointer};\C{locations in a big node}\2\6 -\&{begin} \37$\|b\K\\{false\_code}$;\6 -\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{vacuous},\39\\{boolean\_type},\39\\{string\_type},\39\\{pen\_type},\39% -\\{future\_pen},\39\\{path\_type},\39\\{picture\_type},\39\\{known}$: \37$\|b\K% -\\{true\_code}$;\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37\&{begin} \37$\|p\K\\{value}(% -\\{cur\_exp})$;\5 -$\|q\K\|p+\\{big\_node\_size}[\\{cur\_type}]$;\6 -\1\&{repeat} \37$\|q\K\|q-2$;\6 -\&{if} $\\{type}(\|q)\I\\{known}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\4\&{until}\5 -$\|q=\|p$;\2\6 -$\|b\K\\{true\_code}$;\6 -\4\\{done}: \37\&{end};\6 -\4\&{othercases} \37\\{do\_nothing}\2\6 -\&{endcases};\6 -\&{if} $\|c=\\{known\_op}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\|b)$\6 -\4\&{else} $\\{flush\_cur\_exp}(\\{true\_code}+\\{false\_code}-\|b)$;\2\6 -$\\{cur\_type}\K\\{boolean\_type}$;\6 -\&{end};\par -\fi - -\M920. \P$\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4\\{cycle\_op}: \37\&{begin} \37\&{if} $\\{cur\_type}\I\\{path\_type}$ \1% -\&{then}\5 -$\\{flush\_cur\_exp}(\\{false\_code})$\6 -\4\&{else} \&{if} $\\{left\_type}(\\{cur\_exp})\I\\{endpoint}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\\{true\_code})$\6 -\4\&{else} $\\{flush\_cur\_exp}(\\{false\_code})$;\2\2\6 -$\\{cur\_type}\K\\{boolean\_type}$;\6 -\&{end};\par -\fi - -\M921. \P$\X905:Additional cases of unary operators\X\mathrel{+}\S$\6 -\4\\{make\_pen\_op}: \37\&{begin} \37\&{if} $\\{cur\_type}=\\{pair\_type}$ \1% -\&{then}\5 -\\{pair\_to\_path};\2\6 -\&{if} $\\{cur\_type}=\\{path\_type}$ \1\&{then}\5 -$\\{cur\_type}\K\\{future\_pen}$\6 -\4\&{else} $\\{bad\_unary}(\\{make\_pen\_op})$;\2\6 -\&{end};\6 -\4\\{make\_path\_op}: \37\&{begin} \37\&{if} $\\{cur\_type}=\\{future\_pen}$ \1% -\&{then}\5 -\\{materialize\_pen};\2\6 -\&{if} $\\{cur\_type}\I\\{pen\_type}$ \1\&{then}\5 -$\\{bad\_unary}(\\{make\_path\_op})$\6 -\4\&{else} \&{begin} \37$\\{flush\_cur\_exp}(\\{make\_path}(\\{cur\_exp}))$;\5 -$\\{cur\_type}\K\\{path\_type}$;\6 -\&{end};\2\6 -\&{end};\6 -\4\\{total\_weight\_op}: \37\&{if} $\\{cur\_type}\I\\{picture\_type}$ \1% -\&{then}\5 -$\\{bad\_unary}(\\{total\_weight\_op})$\6 -\4\&{else} $\\{flush\_cur\_exp}(\\{total\_weight}(\\{cur\_exp}))$;\2\6 -\4\\{reverse}: \37\&{if} $\\{cur\_type}=\\{path\_type}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{htap\_ypoc}(\\{cur\_exp})$;\6 -\&{if} $\\{right\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -$\|p\K\\{link}(\|p)$;\2\6 -$\\{toss\_knot\_list}(\\{cur\_exp})$;\5 -$\\{cur\_exp}\K\|p$;\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\5 -\\{pair\_to\_path}\6 -\4\&{else} $\\{bad\_unary}(\\{reverse})$;\2\2\par -\fi - -\M922. Finally, we have the operations that combine a capsule~\|p -with the current expression. - -\Y\P\hbox{\4}\X923:Declare binary action procedures\X\6 -\4\&{procedure}\1\ \37$\\{do\_binary}(\|p:\\{pointer};\,\35\|c:% -\\{quarterword})$;\6 -\4\&{label} \37$\\{done},\39\\{done1},\39\\{exit}$;\6 -\4\&{var} \37$\|q,\39\|r,\39\\{rr}$: \37\\{pointer};\C{for list manipulation}\6 -$\\{old\_p},\39\\{old\_exp}$: \37\\{pointer};\C{capsules to recycle}\6 -\|v: \37\\{integer};\C{for numeric manipulation}\2\6 -\&{begin} \37\\{check\_arith};\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{two}$ \1\&{then}\5 -\X924:Trace the current binary operation\X;\2\6 -\X926:Sidestep \\{independent} cases in capsule \|p\X;\6 -\X927:Sidestep \\{independent} cases in the current expression\X;\6 -\&{case} $\|c$ \1\&{of}\6 -\4$\\{plus},\39\\{minus}$: \37\X929:Add or subtract the current expression from -\|p\X;\6 -\hbox{\4}\X936:Additional cases of binary operators\X\2\6 -\&{end};\C{there are no other cases}\6 -$\\{recycle\_value}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\C{\&{return} to avoid this}\6 -\4\\{exit}: \37\\{check\_arith};\5 -\X925:Recycle any sidestepped \\{independent} capsules\X;\6 -\&{end};\par -\fi - -\M923. \P$\X923:Declare binary action procedures\X\S$\6 -\4\&{procedure}\1\ \37$\\{bad\_binary}(\|p:\\{pointer};\,\35\|c:% -\\{quarterword})$;\2\6 -\&{begin} \37$\\{disp\_err}(\|p,\39\.{""})$;\5 -$\\{exp\_err}(\.{"Not\ implemented:\ "})$;\6 -\&{if} $\|c\G\\{min\_of}$ \1\&{then}\5 -$\\{print\_op}(\|c)$;\2\6 -$\\{print\_known\_or\_unknown\_type}(\\{type}(\|p),\39\|p)$;\6 -\&{if} $\|c\G\\{min\_of}$ \1\&{then}\5 -$\\{print}(\.{"of"})$\ \&{else} $\\{print\_op}(\|c)$;\2\6 -$\\{print\_known\_or\_unknown\_type}(\\{cur\_type},\39\\{cur\_exp})$;\6 -$\\{help3}(\.{"I\'m\ afraid\ I\ don\'t\ know\ how\ to\ apply\ that\ operation\ -to\ that"})$\6 -$(\.{"combination\ of\ types.\ Continue,\ and\ I\'ll\ return\ the\ second"})$\6 -$(\.{"argument\ (see\ above)\ as\ the\ result\ of\ the\ operation."})$;\5 -\\{put\_get\_error};\6 -\&{end};\par -\As928, 930, 943, 946, 949, 953, 960, 961, 962, 963, 966, 976, 977, 978, 982, -984\ETs985. -\U922.\fi - -\M924. \P$\X924:Trace the current binary operation\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{("})$;\5 -$\\{print\_exp}(\|p,\390)$;\C{show the operand, but not verbosely}\6 -$\\{print\_char}(\.{")"})$;\5 -$\\{print\_op}(\|c)$;\5 -$\\{print\_char}(\.{"("})$;\6 -$\\{print\_exp}(\\{null},\390)$;\5 -$\\{print}(\.{")\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U922.\fi - -\M925. Several of the binary operations are potentially complicated by the -fact that \\{independent} values can sneak into capsules. For example, -we've seen an instance of this difficulty in the unary operation -of negation. In order to reduce the number of cases that need to be -handled, we first change the two operands (if necessary) -to rid them of \\{independent} components. The original operands are -put into capsules called \\{old\_p} and \\{old\_exp}, which will be -recycled after the binary operation has been safely carried out. - -\Y\P$\4\X925:Recycle any sidestepped \\{independent} capsules\X\S$\6 -\&{if} $\\{old\_p}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{recycle\_value}(\\{old\_p})$;\5 -$\\{free\_node}(\\{old\_p},\39\\{value\_node\_size})$;\6 -\&{end};\2\6 -\&{if} $\\{old\_exp}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{recycle\_value}(\\{old\_exp})$;\5 -$\\{free\_node}(\\{old\_exp},\39\\{value\_node\_size})$;\6 -\&{end}\2\par -\U922.\fi - -\M926. A big node is considered to be ``tarnished'' if it contains at least one -independent component. We will define a simple function called `\\{tarnished}' -that returns \\{null} if and only if its argument is not tarnished. - -\Y\P$\4\X926:Sidestep \\{independent} cases in capsule \|p\X\S$\6 -\&{case} $\\{type}(\|p)$ \1\&{of}\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37$\\{old\_p}\K\\{tarnished}(\|p)$;% -\6 -\4\\{independent}: \37$\\{old\_p}\K\\{void}$;\6 -\4\&{othercases} \37$\\{old\_p}\K\\{null}$\2\6 -\&{endcases};\6 -\&{if} $\\{old\_p}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\|q\K\\{stash\_cur\_exp}$;\5 -$\\{old\_p}\K\|p$;\5 -$\\{make\_exp\_copy}(\\{old\_p})$;\5 -$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\|q)$;\6 -\&{end};\2\par -\U922.\fi - -\M927. \P$\X927:Sidestep \\{independent} cases in the current expression\X\S$\6 -\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37$\\{old\_exp}\K\\{tarnished}(% -\\{cur\_exp})$;\6 -\4\\{independent}: \37$\\{old\_exp}\K\\{void}$;\6 -\4\&{othercases} \37$\\{old\_exp}\K\\{null}$\2\6 -\&{endcases};\6 -\&{if} $\\{old\_exp}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{old\_exp}\K\\{cur\_exp}$;\5 -$\\{make\_exp\_copy}(\\{old\_exp})$;\6 -\&{end}\2\par -\U922.\fi - -\M928. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{function}\1\ \37$\\{tarnished}(\|p:\\{pointer})$: \37\\{pointer};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{beginning of the big node}\6 -\|r: \37\\{pointer};\C{current position in the big node}\2\6 -\&{begin} \37$\|q\K\\{value}(\|p)$;\5 -$\|r\K\|q+\\{big\_node\_size}[\\{type}(\|p)]$;\6 -\1\&{repeat} \37$\|r\K\|r-2$;\6 -\&{if} $\\{type}(\|r)=\\{independent}$ \1\&{then}\6 -\&{begin} \37$\\{tarnished}\K\\{void}$;\5 -\&{return};\6 -\&{end};\2\6 -\4\&{until}\5 -$\|r=\|q$;\2\6 -$\\{tarnished}\K\\{null}$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M929. \P$\X929:Add or subtract the current expression from \|p\X\S$\6 -\&{if} $(\\{cur\_type}<\\{pair\_type})\V(\\{type}(\|p)<\\{pair\_type})$ \1% -\&{then}\6 -\&{if} $(\\{cur\_type}=\\{picture\_type})\W(\\{type}(\|p)=\\{picture\_type})$ % -\1\&{then}\6 -\&{begin} \37\&{if} $\|c=\\{minus}$ \1\&{then}\5 -$\\{negate\_edges}(\\{cur\_exp})$;\2\6 -$\\{cur\_edges}\K\\{cur\_exp}$;\5 -$\\{merge\_edges}(\\{value}(\|p))$;\6 -\&{end}\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\|c)$\2\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\6 -\&{if} $\\{type}(\|p)\I\\{pair\_type}$ \1\&{then}\5 -$\\{bad\_binary}(\|p,\39\|c)$\6 -\4\&{else} \&{begin} \37$\|q\K\\{value}(\|p)$;\5 -$\|r\K\\{value}(\\{cur\_exp})$;\5 -$\\{add\_or\_subtract}(\\{x\_part\_loc}(\|q),\39\\{x\_part\_loc}(\|r),\39\|c)$;% -\5 -$\\{add\_or\_subtract}(\\{y\_part\_loc}(\|q),\39\\{y\_part\_loc}(\|r),\39\|c)$;% -\6 -\&{end}\2\6 -\4\&{else} \&{if} $\\{type}(\|p)=\\{pair\_type}$ \1\&{then}\5 -$\\{bad\_binary}(\|p,\39\|c)$\6 -\4\&{else} $\\{add\_or\_subtract}(\|p,\39\\{null},\39\|c)$\2\2\2\par -\U922.\fi - -\M930. The first argument to \\{add\_or\_subtract} is the location of a value -node -in a capsule or pair node that will soon be recycled. The second argument -is either a location within a pair or transform node of \\{cur\_exp}, -or it is null (which means that \\{cur\_exp} itself should be the second -argument). The third argument is either \\{plus} or \\{minus}. - -The sum or difference of the numeric quantities will replace the second -operand. Arithmetic overflow may go undetected; users aren't supposed to -be monkeying around with really big values. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\hbox{\4}\X935:Declare the procedure called \\{dep\_finish}\X\6 -\4\&{procedure}\1\ \37$\\{add\_or\_subtract}(\|p,\39\|q:\\{pointer};\,\35\|c:% -\\{quarterword})$;\6 -\4\&{label} \37$\\{done},\39\\{exit}$;\6 -\4\&{var} \37$\|s,\39\|t$: \37\\{small\_number};\C{operand types}\6 -\|r: \37\\{pointer};\C{list traverser}\6 -\|v: \37\\{integer};\C{second operand value}\2\6 -\&{begin} \37\&{if} $\|q=\\{null}$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{cur\_type}$;\6 -\&{if} $\|t<\\{dependent}$ \1\&{then}\5 -$\|v\K\\{cur\_exp}$\ \&{else} $\|v\K\\{dep\_list}(\\{cur\_exp})$;\2\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|t\K\\{type}(\|q)$;\6 -\&{if} $\|t<\\{dependent}$ \1\&{then}\5 -$\|v\K\\{value}(\|q)$\ \&{else} $\|v\K\\{dep\_list}(\|q)$;\2\6 -\&{end};\2\6 -\&{if} $\|t=\\{known}$ \1\&{then}\6 -\&{begin} \37\&{if} $\|c=\\{minus}$ \1\&{then}\5 -$\\{negate}(\|v)$;\2\6 -\&{if} $\\{type}(\|p)=\\{known}$ \1\&{then}\6 -\&{begin} \37$\|v\K\\{slow\_add}(\\{value}(\|p),\39\|v)$;\6 -\&{if} $\|q=\\{null}$ \1\&{then}\5 -$\\{cur\_exp}\K\|v$\ \&{else} $\\{value}(\|q)\K\|v$;\2\6 -\&{return};\6 -\&{end};\2\6 -\X931:Add a known value to the constant term of $\\{dep\_list}(\|p)$\X;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\|c=\\{minus}$ \1\&{then}\5 -$\\{negate\_dep\_list}(\|v)$;\2\6 -\X932:Add operand \|p to the dependency list \|v\X;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M931. \P$\X931:Add a known value to the constant term of $\\{dep\_list}(\|p)$% -\X\S$\6 -$\|r\K\\{dep\_list}(\|p)$;\6 -\&{while} $\\{info}(\|r)\I\\{null}$ \1\&{do}\5 -$\|r\K\\{link}(\|r)$;\2\6 -$\\{value}(\|r)\K\\{slow\_add}(\\{value}(\|r),\39\|v)$;\6 -\&{if} $\|q=\\{null}$ \1\&{then}\6 -\&{begin} \37$\|q\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{cur\_exp}\K\|q$;\5 -$\\{cur\_type}\K\\{type}(\|p)$;\5 -$\\{name\_type}(\|q)\K\\{capsule}$;\6 -\&{end};\2\6 -$\\{dep\_list}(\|q)\K\\{dep\_list}(\|p)$;\5 -$\\{type}(\|q)\K\\{type}(\|p)$;\5 -$\\{prev\_dep}(\|q)\K\\{prev\_dep}(\|p)$;\5 -$\\{link}(\\{prev\_dep}(\|p))\K\|q$;\5 -$\\{type}(\|p)\K\\{known}$;\C{this will keep the recycler from collecting -non-garbage}\par -\U930.\fi - -\M932. We prefer \\{dependent} lists to \\{proto\_dependent} ones, because it -is -nice to retain the extra accuracy of \\{fraction} coefficients. -But we have to handle both kinds, and mixtures too. - -\Y\P$\4\X932:Add operand \|p to the dependency list \|v\X\S$\6 -\&{if} $\\{type}(\|p)=\\{known}$ \1\&{then}\5 -\X933:Add the known $\\{value}(\|p)$ to the constant term of \|v\X\6 -\4\&{else} \&{begin} \37$\|s\K\\{type}(\|p)$;\5 -$\|r\K\\{dep\_list}(\|p)$;\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\6 -\&{begin} \37\&{if} $\|s=\\{dependent}$ \1\&{then}\6 -\&{if} $\\{max\_coef}(\|r)+\\{max\_coef}(\|v)<\\{coef\_bound}$ \1\&{then}\6 -\&{begin} \37$\|v\K\\{p\_plus\_q}(\|v,\39\|r,\39\\{dependent})$;\5 -\&{goto} \37\\{done};\6 -\&{end};\C{\\{fix\_needed} will necessarily be false}\2\2\6 -$\|t\K\\{proto\_dependent}$;\5 -$\|v\K\\{p\_over\_v}(\|v,\39\\{unity},\39\\{dependent},\39\\{proto% -\_dependent})$;\6 -\&{end};\2\6 -\&{if} $\|s=\\{proto\_dependent}$ \1\&{then}\5 -$\|v\K\\{p\_plus\_q}(\|v,\39\|r,\39\\{proto\_dependent})$\6 -\4\&{else} $\|v\K\\{p\_plus\_fq}(\|v,\39\\{unity},\39\|r,\39\\{proto% -\_dependent},\39\\{dependent})$;\2\6 -\4\\{done}: \37\X934:Output the answer, \|v (which might have become \\{known})% -\X;\6 -\&{end}\2\par -\U930.\fi - -\M933. \P$\X933:Add the known $\\{value}(\|p)$ to the constant term of \|v\X\S$% -\6 -\&{begin} \37\&{while} $\\{info}(\|v)\I\\{null}$ \1\&{do}\5 -$\|v\K\\{link}(\|v)$;\2\6 -$\\{value}(\|v)\K\\{slow\_add}(\\{value}(\|p),\39\\{value}(\|v))$;\6 -\&{end}\par -\U932.\fi - -\M934. \P$\X934:Output the answer, \|v (which might have become \\{known})\X\S$% -\6 -\&{if} $\|q\I\\{null}$ \1\&{then}\5 -$\\{dep\_finish}(\|v,\39\|q,\39\|t)$\6 -\4\&{else} \&{begin} \37$\\{cur\_type}\K\|t$;\5 -$\\{dep\_finish}(\|v,\39\\{null},\39\|t)$;\6 -\&{end}\2\par -\U932.\fi - -\M935. Here's the current situation: The dependency list \|v of type \|t -should either be put into the current expression (if $\|q=\\{null}$) or -into location \|q within a pair node (otherwise). The destination (\\{cur\_exp} -or \|q) formerly held a dependency list with the same -final pointer as the list \|v. - -\Y\P$\4\X935:Declare the procedure called \\{dep\_finish}\X\S$\6 -\4\&{procedure}\1\ \37$\\{dep\_finish}(\|v,\39\|q:\\{pointer};\,\35\|t:% -\\{small\_number})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the destination}\6 -\\{vv}: \37\\{scaled};\C{the value, if it is \\{known}}\2\6 -\&{begin} \37\&{if} $\|q=\\{null}$ \1\&{then}\5 -$\|p\K\\{cur\_exp}$\ \&{else} $\|p\K\|q$;\2\6 -$\\{dep\_list}(\|p)\K\|v$;\5 -$\\{type}(\|p)\K\|t$;\6 -\&{if} $\\{info}(\|v)=\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{vv}\K\\{value}(\|v)$;\6 -\&{if} $\|q=\\{null}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\\{vv})$\6 -\4\&{else} \&{begin} \37$\\{recycle\_value}(\|p)$;\5 -$\\{type}(\|q)\K\\{known}$;\5 -$\\{value}(\|q)\K\\{vv}$;\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \&{if} $\|q=\\{null}$ \1\&{then}\5 -$\\{cur\_type}\K\|t$;\2\2\6 -\&{if} $\\{fix\_needed}$ \1\&{then}\5 -\\{fix\_dependencies};\2\6 -\&{end};\par -\U930.\fi - -\M936. Let's turn now to the six basic relations of comparison. - -\Y\P$\4\X936:Additional cases of binary operators\X\S$\6 -\4$\\{less\_than},\39\\{less\_or\_equal},\39\\{greater\_than},\39\\{greater\_or% -\_equal},\39\\{equal\_to},\39\\{unequal\_to}$: \37\&{begin} \37\hbox{}\6 -\&{if} $(\\{cur\_type}>\\{pair\_type})\W(\\{type}(\|p)>\\{pair\_type})$ \1% -\&{then}\5 -$\\{add\_or\_subtract}(\|p,\39\\{null},\39\\{minus})$\C{$\\{cur\_exp}\K(\|p)-% -\\{cur\_exp}$}\6 -\4\&{else} \&{if} $\\{cur\_type}\I\\{type}(\|p)$ \1\&{then}\6 -\&{begin} \37$\\{bad\_binary}(\|p,\39\|c)$;\5 -\&{goto} \37\\{done};\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{string\_type}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\\{str\_vs\_str}(\\{value}(\|p),\39\\{cur\_exp}))$\6 -\4\&{else} \&{if} $(\\{cur\_type}=\\{unknown\_string})\V(\\{cur\_type}=% -\\{unknown\_boolean})$ \1\&{then}\5 -\X938:Check if unknowns have been equated\X\6 -\4\&{else} \&{if} $(\\{cur\_type}=\\{pair\_type})\V(\\{cur\_type}=\\{transform% -\_type})$ \1\&{then}\5 -\X939:Reduce comparison of big nodes to comparison of scalars\X\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{boolean\_type}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(\\{cur\_exp}-\\{value}(\|p))$\6 -\4\&{else} \&{begin} \37$\\{bad\_binary}(\|p,\39\|c)$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\2\2\2\2\2\6 -\X937:Compare the current expression with zero\X;\6 -\4\\{done}: \37\&{end};\par -\As940, 941, 948, 951, 952, 975, 983\ETs988. -\U922.\fi - -\M937. \P$\X937:Compare the current expression with zero\X\S$\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{cur\_type}<\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{disp\_err}(\|p,\39\.{""})$;\5 -$\\{help1}(\.{"The\ quantities\ shown\ above\ have\ not\ been\ equated."})$\6 -\&{end}\6 -\4\&{else} $\\{help2}(\.{"Oh\ dear.\ I\ can\'t\ decide\ if\ the\ expression\ -above\ is\ positive,"})$\2\6 -$(\.{"negative,\ or\ zero.\ So\ this\ comparison\ test\ won\'t\ be\ \`true% -\'."})$;\5 -$\\{exp\_err}(\.{"Unknown\ relation\ will\ be\ considered\ false"})$;\5 -$\\{put\_get\_flush\_error}(\\{false\_code})$;\6 -\&{end}\6 -\4\&{else} \&{case} $\|c$ \1\&{of}\6 -\4\\{less\_than}: \37$\\{boolean\_reset}(\\{cur\_exp}<0)$;\6 -\4\\{less\_or\_equal}: \37$\\{boolean\_reset}(\\{cur\_exp}\L0)$;\6 -\4\\{greater\_than}: \37$\\{boolean\_reset}(\\{cur\_exp}>0)$;\6 -\4\\{greater\_or\_equal}: \37$\\{boolean\_reset}(\\{cur\_exp}\G0)$;\6 -\4\\{equal\_to}: \37$\\{boolean\_reset}(\\{cur\_exp}=0)$;\6 -\4\\{unequal\_to}: \37$\\{boolean\_reset}(\\{cur\_exp}\I0)$;\2\6 -\&{end};\C{there are no other cases}\2\6 -$\\{cur\_type}\K\\{boolean\_type}$\par -\U936.\fi - -\M938. When two unknown strings are in the same ring, we know that they are -equal. Otherwise, we don't know whether they are equal or not, so we -make no change. - -\Y\P$\4\X938:Check if unknowns have been equated\X\S$\6 -\&{begin} \37$\|q\K\\{value}(\\{cur\_exp})$;\6 -\&{while} $(\|q\I\\{cur\_exp})\W(\|q\I\|p)$ \1\&{do}\5 -$\|q\K\\{value}(\|q)$;\2\6 -\&{if} $\|q=\|p$ \1\&{then}\5 -$\\{flush\_cur\_exp}(0)$;\2\6 -\&{end}\par -\U936.\fi - -\M939. \P$\X939:Reduce comparison of big nodes to comparison of scalars\X\S$\6 -\&{begin} \37$\|q\K\\{value}(\|p)$;\5 -$\|r\K\\{value}(\\{cur\_exp})$;\5 -$\\{rr}\K\|r+\\{big\_node\_size}[\\{cur\_type}]-2$;\6 -\~ \1\&{loop}\ \&{begin} \37$\\{add\_or\_subtract}(\|q,\39\|r,\39\\{minus})$;\6 -\&{if} $\\{type}(\|r)\I\\{known}$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -\&{if} $\\{value}(\|r)\I0$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -\&{if} $\|r=\\{rr}$ \1\&{then}\5 -\&{goto} \37\\{done1};\2\6 -$\|q\K\|q+2$;\5 -$\|r\K\|r+2$;\6 -\&{end};\2\6 -\4\\{done1}: \37$\\{take\_part}(\\{x\_part}+\\{half}(\|r-\\{value}(\\{cur% -\_exp})))$;\6 -\&{end}\par -\U936.\fi - -\M940. Here we use the sneaky fact that $\\{and\_op}-\\{false\_code}=\\{or% -\_op}-\\{true\_code}$. - -\Y\P$\4\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4$\\{and\_op},\39\\{or\_op}$: \37\&{if} $(\\{type}(\|p)\I\\{boolean\_type})\V(% -\\{cur\_type}\I\\{boolean\_type})$ \1\&{then}\5 -$\\{bad\_binary}(\|p,\39\|c)$\6 -\4\&{else} \&{if} $\\{value}(\|p)=\|c+\\{false\_code}-\\{and\_op}$ \1\&{then}\5 -$\\{cur\_exp}\K\\{value}(\|p)$;\2\2\par -\fi - -\M941. \P$\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4\\{times}: \37\&{if} $(\\{cur\_type}<\\{pair\_type})\V(\\{type}(\|p)<\\{pair% -\_type})$ \1\&{then}\5 -$\\{bad\_binary}(\|p,\39\\{times})$\6 -\4\&{else} \&{if} $(\\{cur\_type}=\\{known})\V(\\{type}(\|p)=\\{known})$ \1% -\&{then}\5 -\X942:Multiply when at least one operand is known\X\6 -\4\&{else} \&{if} $(\\{nice\_pair}(\|p,\39\\{type}(\|p))\W(\\{cur\_type}>% -\\{pair\_type}))\V(\\{nice\_pair}(\\{cur\_exp},\39\\{cur\_type})\W(\\{type}(% -\|p)>\\{pair\_type}))$ \1\&{then}\6 -\&{begin} \37$\\{hard\_times}(\|p)$;\5 -\&{return};\6 -\&{end}\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\\{times})$;\2\2\2\par -\fi - -\M942. \P$\X942:Multiply when at least one operand is known\X\S$\6 -\&{begin} \37\&{if} $\\{type}(\|p)=\\{known}$ \1\&{then}\6 -\&{begin} \37$\|v\K\\{value}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|v\K\\{cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\|p)$;\6 -\&{end};\2\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -$\\{cur\_exp}\K\\{take\_scaled}(\\{cur\_exp},\39\|v)$\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\5 -$\\{dep\_mult}(\\{x\_part\_loc}(\|p),\39\|v,\39\\{true})$;\5 -$\\{dep\_mult}(\\{y\_part\_loc}(\|p),\39\|v,\39\\{true})$;\6 -\&{end}\6 -\4\&{else} $\\{dep\_mult}(\\{null},\39\|v,\39\\{true})$;\2\2\6 -\&{return};\6 -\&{end}\par -\U941.\fi - -\M943. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{dep\_mult}(\|p:\\{pointer};\,\35\|v:\\{integer};\,% -\35\\{v\_is\_scaled}:\\{boolean})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the dependency list being multiplied by % -\|v}\6 -$\|s,\39\|t$: \37\\{small\_number};\C{its type, before and after}\2\6 -\&{begin} \37\&{if} $\|p=\\{null}$ \1\&{then}\5 -$\|q\K\\{cur\_exp}$\6 -\4\&{else} \&{if} $\\{type}(\|p)\I\\{known}$ \1\&{then}\5 -$\|q\K\|p$\6 -\4\&{else} \&{begin} \37\&{if} $\\{v\_is\_scaled}$ \1\&{then}\5 -$\\{value}(\|p)\K\\{take\_scaled}(\\{value}(\|p),\39\|v)$\6 -\4\&{else} $\\{value}(\|p)\K\\{take\_fraction}(\\{value}(\|p),\39\|v)$;\2\6 -\&{return};\6 -\&{end};\2\2\6 -$\|t\K\\{type}(\|q)$;\5 -$\|q\K\\{dep\_list}(\|q)$;\5 -$\|s\K\|t$;\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\6 -\&{if} $\\{v\_is\_scaled}$ \1\&{then}\6 -\&{if} $\\{ab\_vs\_cd}(\\{max\_coef}(\|q),\39\\{abs}(\|v),\39\\{coef\_bound}-1,% -\39\\{unity})\G0$ \1\&{then}\5 -$\|t\K\\{proto\_dependent}$;\2\2\2\6 -$\|q\K\\{p\_times\_v}(\|q,\39\|v,\39\|s,\39\|t,\39\\{v\_is\_scaled})$;\5 -$\\{dep\_finish}(\|q,\39\|p,\39\|t)$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M944. Here is a routine that is similar to \\{times}; but it is invoked only -internally, when \|v is a \\{fraction} whose magnitude is at most~1, -and when $\\{cur\_type}\G\\{pair\_type}$. - -\Y\P\4\&{procedure}\1\ \37$\\{frac\_mult}(\|n,\39\|d:\\{scaled})$;% -\C{multiplies \\{cur\_exp} by $\|n/\|d$}\6 -\4\&{var} \37\|p: \37\\{pointer};\C{a pair node}\6 -\\{old\_exp}: \37\\{pointer};\C{a capsule to recycle}\6 -\|v: \37\\{fraction};\C{$\|n/\|d$}\2\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_commands}]>\\{two}$ \1\&{then}\5 -\X945:Trace the fraction multiplication\X;\2\6 -\&{case} $\\{cur\_type}$ \1\&{of}\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37$\\{old\_exp}\K\\{tarnished}(% -\\{cur\_exp})$;\6 -\4\\{independent}: \37$\\{old\_exp}\K\\{void}$;\6 -\4\&{othercases} \37$\\{old\_exp}\K\\{null}$\2\6 -\&{endcases};\6 -\&{if} $\\{old\_exp}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{old\_exp}\K\\{cur\_exp}$;\5 -$\\{make\_exp\_copy}(\\{old\_exp})$;\6 -\&{end};\2\6 -$\|v\K\\{make\_fraction}(\|n,\39\|d)$;\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -$\\{cur\_exp}\K\\{take\_fraction}(\\{cur\_exp},\39\|v)$\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\5 -$\\{dep\_mult}(\\{x\_part\_loc}(\|p),\39\|v,\39\\{false})$;\5 -$\\{dep\_mult}(\\{y\_part\_loc}(\|p),\39\|v,\39\\{false})$;\6 -\&{end}\6 -\4\&{else} $\\{dep\_mult}(\\{null},\39\|v,\39\\{false})$;\2\2\6 -\&{if} $\\{old\_exp}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{recycle\_value}(\\{old\_exp})$;\5 -$\\{free\_node}(\\{old\_exp},\39\\{value\_node\_size})$;\6 -\&{end}\2\6 -\&{end};\par -\fi - -\M945. \P$\X945:Trace the fraction multiplication\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{("})$;\5 -$\\{print\_scaled}(\|n)$;\5 -$\\{print\_char}(\.{"/"})$;\5 -$\\{print\_scaled}(\|d)$;\5 -$\\{print}(\.{")*("})$;\5 -$\\{print\_exp}(\\{null},\390)$;\5 -$\\{print}(\.{")\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U944.\fi - -\M946. The \\{hard\_times} routine multiplies a nice pair by a dependency list. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{hard\_times}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{a copy of the dependent variable \|p}\6 -\|r: \37\\{pointer};\C{the big node for the nice pair}\6 -$\|u,\39\|v$: \37\\{scaled};\C{the known values of the nice pair}\2\6 -\&{begin} \37\&{if} $\\{type}(\|p)=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|q\K\\{stash\_cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\|p)$;\5 -$\|p\K\|q$;\6 -\&{end};\C{now $\\{cur\_type}=\\{pair\_type}$}\2\6 -$\|r\K\\{value}(\\{cur\_exp})$;\5 -$\|u\K\\{value}(\\{x\_part\_loc}(\|r))$;\5 -$\|v\K\\{value}(\\{y\_part\_loc}(\|r))$;\5 -\X947:Move the dependent variable \|p into both parts of the pair node \|r\X;\6 -$\\{dep\_mult}(\\{x\_part\_loc}(\|r),\39\|u,\39\\{true})$;\5 -$\\{dep\_mult}(\\{y\_part\_loc}(\|r),\39\|v,\39\\{true})$;\6 -\&{end};\par -\fi - -\M947. \P$\X947:Move the dependent variable \|p into both parts of the pair -node \|r\X\S$\6 -$\\{type}(\\{y\_part\_loc}(\|r))\K\\{type}(\|p)$;\5 -$\\{new\_dep}(\\{y\_part\_loc}(\|r),\39\\{copy\_dep\_list}(\\{dep\_list}(% -\|p)))$;\6 -$\\{type}(\\{x\_part\_loc}(\|r))\K\\{type}(\|p)$;\5 -$\\{mem}[\\{value\_loc}(\\{x\_part\_loc}(\|r))]\K\\{mem}[\\{value\_loc}(\|p)]$;% -\5 -$\\{link}(\\{prev\_dep}(\|p))\K\\{x\_part\_loc}(\|r)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$\par -\U946.\fi - -\M948. \P$\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4\\{over}: \37\&{if} $(\\{cur\_type}\I\\{known})\V(\\{type}(\|p)<\\{pair% -\_type})$ \1\&{then}\5 -$\\{bad\_binary}(\|p,\39\\{over})$\6 -\4\&{else} \&{begin} \37$\|v\K\\{cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\|p)$;\6 -\&{if} $\|v=0$ \1\&{then}\5 -\X950:Squeal about division by zero\X\6 -\4\&{else} \&{begin} \37\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -$\\{cur\_exp}\K\\{make\_scaled}(\\{cur\_exp},\39\|v)$\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\5 -$\\{dep\_div}(\\{x\_part\_loc}(\|p),\39\|v)$;\5 -$\\{dep\_div}(\\{y\_part\_loc}(\|p),\39\|v)$;\6 -\&{end}\6 -\4\&{else} $\\{dep\_div}(\\{null},\39\|v)$;\2\2\6 -\&{end};\2\6 -\&{return};\6 -\&{end};\2\par -\fi - -\M949. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{dep\_div}(\|p:\\{pointer};\,\35\|v:\\{scaled})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{the dependency list being divided by \|v}\6 -$\|s,\39\|t$: \37\\{small\_number};\C{its type, before and after}\2\6 -\&{begin} \37\&{if} $\|p=\\{null}$ \1\&{then}\5 -$\|q\K\\{cur\_exp}$\6 -\4\&{else} \&{if} $\\{type}(\|p)\I\\{known}$ \1\&{then}\5 -$\|q\K\|p$\6 -\4\&{else} \&{begin} \37$\\{value}(\|p)\K\\{make\_scaled}(\\{value}(\|p),\39% -\|v)$;\5 -\&{return};\6 -\&{end};\2\2\6 -$\|t\K\\{type}(\|q)$;\5 -$\|q\K\\{dep\_list}(\|q)$;\5 -$\|s\K\|t$;\6 -\&{if} $\|t=\\{dependent}$ \1\&{then}\6 -\&{if} $\\{ab\_vs\_cd}(\\{max\_coef}(\|q),\39\\{unity},\39\\{coef\_bound}-1,\39% -\\{abs}(\|v))\G0$ \1\&{then}\5 -$\|t\K\\{proto\_dependent}$;\2\2\6 -$\|q\K\\{p\_over\_v}(\|q,\39\|v,\39\|s,\39\|t)$;\5 -$\\{dep\_finish}(\|q,\39\|p,\39\|t)$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M950. \P$\X950:Squeal about division by zero\X\S$\6 -\&{begin} \37$\\{exp\_err}(\.{"Division\ by\ zero"})$;\5 -$\\{help2}(\.{"You\'re\ trying\ to\ divide\ the\ quantity\ shown\ above\ the\ -error"})$\6 -$(\.{"message\ by\ zero.\ I\'m\ going\ to\ divide\ it\ by\ one\ instead."})$;\5 -\\{put\_get\_error};\6 -\&{end}\par -\U948.\fi - -\M951. \P$\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4$\\{pythag\_add},\39\\{pythag\_sub}$: \37\&{if} $(\\{cur\_type}=\\{known})\W(% -\\{type}(\|p)=\\{known})$ \1\&{then}\6 -\&{if} $\|c=\\{pythag\_add}$ \1\&{then}\5 -$\\{cur\_exp}\K\\{pyth\_add}(\\{value}(\|p),\39\\{cur\_exp})$\6 -\4\&{else} $\\{cur\_exp}\K\\{pyth\_sub}(\\{value}(\|p),\39\\{cur\_exp})$\2\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\|c)$;\2\par -\fi - -\M952. The next few sections of the program deal with affine transformations -of coordinate data. - -\Y\P$\4\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4$\\{rotated\_by},\39\\{slanted\_by},\39\\{scaled\_by},\39\\{shifted\_by},\39% -\\{transformed\_by},\39\\{x\_scaled},\39\\{y\_scaled},\39\\{z\_scaled}$: \37% -\hbox{}\6 -\&{if} $(\\{type}(\|p)=\\{path\_type})\V(\\{type}(\|p)=\\{future\_pen})\V(% -\\{type}(\|p)=\\{pen\_type})$ \1\&{then}\6 -\&{begin} \37$\\{path\_trans}(\|p,\39\|c)$;\5 -\&{return};\6 -\&{end}\6 -\4\&{else} \&{if} $(\\{type}(\|p)=\\{pair\_type})\V(\\{type}(\|p)=\\{transform% -\_type})$ \1\&{then}\5 -$\\{big\_trans}(\|p,\39\|c)$\6 -\4\&{else} \&{if} $\\{type}(\|p)=\\{picture\_type}$ \1\&{then}\6 -\&{begin} \37$\\{edges\_trans}(\|p,\39\|c)$;\5 -\&{return};\6 -\&{end}\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\|c)$;\2\2\2\par -\fi - -\M953. Let \|c be one of the eight transform operators. The procedure call -$\\{set\_up\_trans}(\|c)$ first changes \\{cur\_exp} to a transform that -corresponds to -\|c and the original value of \\{cur\_exp}. (In particular, \\{cur\_exp} -doesn't -change at all if $\|c=\\{transformed\_by}$.) - -Then, if all components of the resulting transform are \\{known}, they are -moved to the global variables \\{txx}, \\{txy}, \\{tyx}, \\{tyy}, \\{tx}, % -\\{ty}; -and \\{cur\_exp} is changed to the known value zero. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{set\_up\_trans}(\|c:\\{quarterword})$;\6 -\4\&{label} \37$\\{done},\39\\{exit}$;\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{list manipulation -registers}\2\6 -\&{begin} \37\&{if} $(\|c\I\\{transformed\_by})\V(\\{cur\_type}\I\\{transform% -\_type})$ \1\&{then}\5 -\X955:Put the current transform into \\{cur\_exp}\X;\2\6 -\X956:If the current transform is entirely known, stash it in global variables; -otherwise \&{return}\X;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M954. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{txx},\39\\{txy},\39\\{tyx},\39\\{tyy},\39\\{tx},\39\\{ty}$: \37% -\\{scaled};\C{current transform coefficients}\par -\fi - -\M955. \P$\X955:Put the current transform into \\{cur\_exp}\X\S$\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{cur\_exp}\K\\{id\_transform}$;\5 -$\\{cur\_type}\K\\{transform\_type}$;\5 -$\|q\K\\{value}(\\{cur\_exp})$;\6 -\&{case} $\|c$ \1\&{of}\6 -\X957:For each of the eight cases, change the relevant fields of \\{cur\_exp} -and \&{goto} \\{done}; but do nothing if capsule \|p doesn't have the -appropriate type\X\2\6 -\&{end};\C{there are no other cases}\6 -$\\{disp\_err}(\|p,\39\.{"Improper\ transformation\ argument"})$;\5 -$\\{help3}(\.{"The\ expression\ shown\ above\ has\ the\ wrong\ type,"})$\6 -$(\.{"so\ I\ can\'t\ transform\ anything\ using\ it."})$\6 -$(\.{"Proceed,\ and\ I\'ll\ omit\ the\ transformation."})$;\5 -\\{put\_get\_error};\6 -\4\\{done}: \37$\\{recycle\_value}(\|p)$;\5 -$\\{free\_node}(\|p,\39\\{value\_node\_size})$;\6 -\&{end}\par -\U953.\fi - -\M956. \P$\X956:If the current transform is entirely known, stash it in global -variables; otherwise \&{return}\X\S$\6 -$\|q\K\\{value}(\\{cur\_exp})$;\5 -$\|r\K\|q+\\{transform\_node\_size}$;\6 -\1\&{repeat} \37$\|r\K\|r-2$;\6 -\&{if} $\\{type}(\|r)\I\\{known}$ \1\&{then}\5 -\&{return};\2\6 -\4\&{until}\5 -$\|r=\|q$;\2\6 -$\\{txx}\K\\{value}(\\{xx\_part\_loc}(\|q))$;\5 -$\\{txy}\K\\{value}(\\{xy\_part\_loc}(\|q))$;\5 -$\\{tyx}\K\\{value}(\\{yx\_part\_loc}(\|q))$;\5 -$\\{tyy}\K\\{value}(\\{yy\_part\_loc}(\|q))$;\5 -$\\{tx}\K\\{value}(\\{x\_part\_loc}(\|q))$;\5 -$\\{ty}\K\\{value}(\\{y\_part\_loc}(\|q))$;\5 -$\\{flush\_cur\_exp}(0)$\par -\U953.\fi - -\M957. \P$\X957:For each of the eight cases, change the relevant fields of % -\\{cur\_exp} and \&{goto} \\{done}; but do nothing if capsule \|p doesn't have -the appropriate type\X\S$\6 -\4\\{rotated\_by}: \37\&{if} $\\{type}(\|p)=\\{known}$ \1\&{then}\5 -\X958:Install sines and cosines, then \&{goto} \\{done}\X;\2\6 -\4\\{slanted\_by}: \37\&{if} $\\{type}(\|p)>\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\\{install}(\\{xy\_part\_loc}(\|q),\39\|p)$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\4\\{scaled\_by}: \37\&{if} $\\{type}(\|p)>\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\\{install}(\\{xx\_part\_loc}(\|q),\39\|p)$;\5 -$\\{install}(\\{yy\_part\_loc}(\|q),\39\|p)$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\4\\{shifted\_by}: \37\&{if} $\\{type}(\|p)=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|r\K\\{value}(\|p)$;\5 -$\\{install}(\\{x\_part\_loc}(\|q),\39\\{x\_part\_loc}(\|r))$;\5 -$\\{install}(\\{y\_part\_loc}(\|q),\39\\{y\_part\_loc}(\|r))$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\4\\{x\_scaled}: \37\&{if} $\\{type}(\|p)>\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\\{install}(\\{xx\_part\_loc}(\|q),\39\|p)$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\4\\{y\_scaled}: \37\&{if} $\\{type}(\|p)>\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\\{install}(\\{yy\_part\_loc}(\|q),\39\|p)$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\4\\{z\_scaled}: \37\&{if} $\\{type}(\|p)=\\{pair\_type}$ \1\&{then}\5 -\X959:Install a complex multiplier, then \&{goto} \\{done}\X;\2\6 -\4\\{transformed\_by}: \37\\{do\_nothing};\par -\U955.\fi - -\M958. \P$\X958:Install sines and cosines, then \&{goto} \\{done}\X\S$\6 -\&{begin} \37$\\{n\_sin\_cos}((\\{value}(\|p)\mathbin{\&{mod}}\\{three\_sixty% -\_units})\ast16)$;\5 -$\\{value}(\\{xx\_part\_loc}(\|q))\K\\{round\_fraction}(\\{n\_cos})$;\5 -$\\{value}(\\{yx\_part\_loc}(\|q))\K\\{round\_fraction}(\\{n\_sin})$;\5 -$\\{value}(\\{xy\_part\_loc}(\|q))\K-\\{value}(\\{yx\_part\_loc}(\|q))$;\5 -$\\{value}(\\{yy\_part\_loc}(\|q))\K\\{value}(\\{xx\_part\_loc}(\|q))$;\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U957.\fi - -\M959. \P$\X959:Install a complex multiplier, then \&{goto} \\{done}\X\S$\6 -\&{begin} \37$\|r\K\\{value}(\|p)$;\5 -$\\{install}(\\{xx\_part\_loc}(\|q),\39\\{x\_part\_loc}(\|r))$;\5 -$\\{install}(\\{yy\_part\_loc}(\|q),\39\\{x\_part\_loc}(\|r))$;\5 -$\\{install}(\\{yx\_part\_loc}(\|q),\39\\{y\_part\_loc}(\|r))$;\6 -\&{if} $\\{type}(\\{y\_part\_loc}(\|r))=\\{known}$ \1\&{then}\5 -$\\{negate}(\\{value}(\\{y\_part\_loc}(\|r)))$\6 -\4\&{else} $\\{negate\_dep\_list}(\\{dep\_list}(\\{y\_part\_loc}(\|r)))$;\2\6 -$\\{install}(\\{xy\_part\_loc}(\|q),\39\\{y\_part\_loc}(\|r))$;\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U957.\fi - -\M960. Procedure \\{set\_up\_known\_trans} is like \\{set\_up\_trans}, but it -insists that the transformation be entirely known. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{set\_up\_known\_trans}(\|c:\\{quarterword})$;\2\6 -\&{begin} \37$\\{set\_up\_trans}(\|c)$;\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Transform\ components\ aren\'t\ all\ known"})$;\5 -$\\{help3}(\.{"I\'m\ unable\ to\ apply\ a\ partially\ specified\ -transformation"})$\6 -$(\.{"except\ to\ a\ fully\ known\ pair\ or\ transform."})$\6 -$(\.{"Proceed,\ and\ I\'ll\ omit\ the\ transformation."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\5 -$\\{txx}\K\\{unity}$;\5 -$\\{txy}\K0$;\5 -$\\{tyx}\K0$;\5 -$\\{tyy}\K\\{unity}$;\5 -$\\{tx}\K0$;\5 -$\\{ty}\K0$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M961. Here's a procedure that applies the transform $\\{txx}\to\\{ty}$ to a -pair of -coordinates in locations \|p and~\|q. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{trans}(\|p,\39\|q:\\{pointer})$;\6 -\4\&{var} \37\|v: \37\\{scaled};\C{the new \|x value}\2\6 -\&{begin} \37$\|v\K\\{take\_scaled}(\\{mem}[\|p].\\{sc},\39\\{txx})+\\{take% -\_scaled}(\\{mem}[\|q].\\{sc},\39\\{txy})+\\{tx}$;\5 -$\\{mem}[\|q].\\{sc}\K\\{take\_scaled}(\\{mem}[\|p].\\{sc},\39\\{tyx})+\\{take% -\_scaled}(\\{mem}[\|q].\\{sc},\39\\{tyy})+\\{ty}$;\5 -$\\{mem}[\|p].\\{sc}\K\|v$;\6 -\&{end};\par -\fi - -\M962. The simplest transformation procedure applies a transform to all -coordinates of a path. The \\{null\_pen} remains unchanged if it isn't -being shifted. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{path\_trans}(\|p:\\{pointer};\,\35\|c:% -\\{quarterword})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|q: \37\\{pointer};\C{list traverser}\2\6 -\&{begin} \37$\\{set\_up\_known\_trans}(\|c)$;\5 -$\\{unstash\_cur\_exp}(\|p)$;\6 -\&{if} $\\{cur\_type}=\\{pen\_type}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{max\_offset}(\\{cur\_exp})=0$ \1\&{then}\6 -\&{if} $\\{tx}=0$ \1\&{then}\6 -\&{if} $\\{ty}=0$ \1\&{then}\5 -\&{return};\2\2\2\6 -$\\{flush\_cur\_exp}(\\{make\_path}(\\{cur\_exp}))$;\5 -$\\{cur\_type}\K\\{future\_pen}$;\6 -\&{end};\2\6 -$\|q\K\\{cur\_exp}$;\6 -\1\&{repeat} \37\&{if} $\\{left\_type}(\|q)\I\\{endpoint}$ \1\&{then}\5 -$\\{trans}(\|q+3,\39\|q+4)$;\C{that's \\{left\_x} and \\{left\_y}}\2\6 -$\\{trans}(\|q+1,\39\|q+2)$;\C{that's \\{x\_coord} and \\{y\_coord}}\6 -\&{if} $\\{right\_type}(\|q)\I\\{endpoint}$ \1\&{then}\5 -$\\{trans}(\|q+5,\39\|q+6)$;\C{that's \\{right\_x} and \\{right\_y}}\2\6 -$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\|q=\\{cur\_exp}$;\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M963. The next simplest transformation procedure applies to edges. -It is simple primarily because \MF\ doesn't allow very general -transformations to be made, and because the tricky subroutines -for edge transformation have already been written. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{edges\_trans}(\|p:\\{pointer};\,\35\|c:% -\\{quarterword})$;\6 -\4\&{label} \37\\{exit};\2\6 -\&{begin} \37$\\{set\_up\_known\_trans}(\|c)$;\5 -$\\{unstash\_cur\_exp}(\|p)$;\5 -$\\{cur\_edges}\K\\{cur\_exp}$;\6 -\&{if} $\\{empty\_edges}(\\{cur\_edges})$ \1\&{then}\5 -\&{return};\C{the empty set is easy to transform}\2\6 -\&{if} $\\{txx}=0$ \1\&{then}\6 -\&{if} $\\{tyy}=0$ \1\&{then}\6 -\&{if} $\\{txy}\mathbin{\&{mod}}\\{unity}=0$ \1\&{then}\6 -\&{if} $\\{tyx}\mathbin{\&{mod}}\\{unity}=0$ \1\&{then}\6 -\&{begin} \37\\{xy\_swap\_edges};\5 -$\\{txx}\K\\{txy}$;\5 -$\\{tyy}\K\\{tyx}$;\5 -$\\{txy}\K0$;\5 -$\\{tyx}\K0$;\6 -\&{if} $\\{empty\_edges}(\\{cur\_edges})$ \1\&{then}\5 -\&{return};\2\6 -\&{end};\2\2\2\2\6 -\&{if} $\\{txy}=0$ \1\&{then}\6 -\&{if} $\\{tyx}=0$ \1\&{then}\6 -\&{if} $\\{txx}\mathbin{\&{mod}}\\{unity}=0$ \1\&{then}\6 -\&{if} $\\{tyy}\mathbin{\&{mod}}\\{unity}=0$ \1\&{then}\5 -\X964:Scale the edges, shift them, and \&{return}\X;\2\2\2\2\6 -$\\{print\_err}(\.{"That\ transformation\ is\ too\ hard"})$;\5 -$\\{help3}(\.{"I\ can\ apply\ complicated\ transformations\ to\ paths,"})$\6 -$(\.{"but\ I\ can\ only\ do\ integer\ operations\ on\ pictures."})$\6 -$(\.{"Proceed,\ and\ I\'ll\ omit\ the\ transformation."})$;\5 -\\{put\_get\_error};\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M964. \P$\X964:Scale the edges, shift them, and \&{return}\X\S$\6 -\&{begin} \37\&{if} $(\\{txx}=0)\V(\\{tyy}=0)$ \1\&{then}\6 -\&{begin} \37$\\{toss\_edges}(\\{cur\_edges})$;\5 -$\\{cur\_exp}\K\\{get\_node}(\\{edge\_header\_size})$;\5 -$\\{init\_edges}(\\{cur\_exp})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{txx}<0$ \1\&{then}\6 -\&{begin} \37\\{x\_reflect\_edges};\5 -$\\{txx}\K-\\{txx}$;\6 -\&{end};\2\6 -\&{if} $\\{tyy}<0$ \1\&{then}\6 -\&{begin} \37\\{y\_reflect\_edges};\5 -$\\{tyy}\K-\\{tyy}$;\6 -\&{end};\2\6 -\&{if} $\\{txx}\I\\{unity}$ \1\&{then}\5 -$\\{x\_scale\_edges}(\\{txx}\mathbin{\&{div}}\\{unity})$;\2\6 -\&{if} $\\{tyy}\I\\{unity}$ \1\&{then}\5 -$\\{y\_scale\_edges}(\\{tyy}\mathbin{\&{div}}\\{unity})$;\2\6 -\X965:Shift the edges by $(\\{tx},\\{ty})$, rounded\X;\6 -\&{end};\2\6 -\&{return};\6 -\&{end}\par -\U963.\fi - -\M965. \P$\X965:Shift the edges by $(\\{tx},\\{ty})$, rounded\X\S$\6 -$\\{tx}\K\\{round\_unscaled}(\\{tx})$;\5 -$\\{ty}\K\\{round\_unscaled}(\\{ty})$;\6 -\&{if} $(\\{m\_min}(\\{cur\_edges})+\\{tx}\L0)\V(\\{m\_max}(\\{cur\_edges})+% -\\{tx}\G8192)\V\30(\\{n\_min}(\\{cur\_edges})+\\{ty}\L0)\V(\\{n\_max}(\\{cur% -\_edges})+\\{ty}\G8191)\V\30(\\{abs}(\\{tx})\G4096)\V(\\{abs}(\\{ty})\G4096)$ % -\1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Too\ far\ to\ shift"})$;\5 -$\\{help3}(\.{"I\ can\'t\ shift\ the\ picture\ as\ requested---it\ would"})$\6 -$(\.{"make\ some\ coordinates\ too\ large\ or\ too\ small."})$\6 -$(\.{"Proceed,\ and\ I\'ll\ omit\ the\ transformation."})$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $\\{tx}\I0$ \1\&{then}\6 -\&{begin} \37\&{if} $\R\\{valid\_range}(\\{m\_offset}(\\{cur\_edges})-\\{tx})$ % -\1\&{then}\5 -\\{fix\_offset};\2\6 -$\\{m\_min}(\\{cur\_edges})\K\\{m\_min}(\\{cur\_edges})+\\{tx}$;\5 -$\\{m\_max}(\\{cur\_edges})\K\\{m\_max}(\\{cur\_edges})+\\{tx}$;\5 -$\\{m\_offset}(\\{cur\_edges})\K\\{m\_offset}(\\{cur\_edges})-\\{tx}$;\5 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\2\6 -\&{if} $\\{ty}\I0$ \1\&{then}\6 -\&{begin} \37$\\{n\_min}(\\{cur\_edges})\K\\{n\_min}(\\{cur\_edges})+\\{ty}$;\5 -$\\{n\_max}(\\{cur\_edges})\K\\{n\_max}(\\{cur\_edges})+\\{ty}$;\5 -$\\{n\_pos}(\\{cur\_edges})\K\\{n\_pos}(\\{cur\_edges})+\\{ty}$;\5 -$\\{last\_window\_time}(\\{cur\_edges})\K0$;\6 -\&{end};\2\6 -\&{end}\2\par -\U964.\fi - -\M966. The hard cases of transformation occur when big nodes are involved, -and when some of their components are unknown. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\hbox{\4}\X968:Declare subroutines needed by \\{big\_trans}\X\6 -\4\&{procedure}\1\ \37$\\{big\_trans}(\|p:\\{pointer};\,\35\|c:% -\\{quarterword})$;\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37$\|q,\39\|r,\39\\{pp},\39\\{qq}$: \37\\{pointer};\C{list -manipulation registers}\6 -\|s: \37\\{small\_number};\C{size of a big node}\2\6 -\&{begin} \37$\|s\K\\{big\_node\_size}[\\{type}(\|p)]$;\5 -$\|q\K\\{value}(\|p)$;\5 -$\|r\K\|q+\|s$;\6 -\1\&{repeat} \37$\|r\K\|r-2$;\6 -\&{if} $\\{type}(\|r)\I\\{known}$ \1\&{then}\5 -\X967:Transform an unknown big node and \&{return}\X;\2\6 -\4\&{until}\5 -$\|r=\|q$;\2\6 -\X970:Transform a known big node\X;\6 -\4\\{exit}: \37\&{end};\C{node \|p will now be recycled by \\{do\_binary}}\par -\fi - -\M967. \P$\X967:Transform an unknown big node and \&{return}\X\S$\6 -\&{begin} \37$\\{set\_up\_known\_trans}(\|c)$;\5 -$\\{make\_exp\_copy}(\|p)$;\5 -$\|r\K\\{value}(\\{cur\_exp})$;\6 -\&{if} $\\{cur\_type}=\\{transform\_type}$ \1\&{then}\6 -\&{begin} \37$\\{bilin1}(\\{yy\_part\_loc}(\|r),\39\\{tyy},\39\\{xy\_part% -\_loc}(\|q),\39\\{tyx},\390)$;\5 -$\\{bilin1}(\\{yx\_part\_loc}(\|r),\39\\{tyy},\39\\{xx\_part\_loc}(\|q),\39% -\\{tyx},\390)$;\5 -$\\{bilin1}(\\{xy\_part\_loc}(\|r),\39\\{txx},\39\\{yy\_part\_loc}(\|q),\39% -\\{txy},\390)$;\5 -$\\{bilin1}(\\{xx\_part\_loc}(\|r),\39\\{txx},\39\\{yx\_part\_loc}(\|q),\39% -\\{txy},\390)$;\6 -\&{end};\2\6 -$\\{bilin1}(\\{y\_part\_loc}(\|r),\39\\{tyy},\39\\{x\_part\_loc}(\|q),\39% -\\{tyx},\39\\{ty})$;\5 -$\\{bilin1}(\\{x\_part\_loc}(\|r),\39\\{txx},\39\\{y\_part\_loc}(\|q),\39% -\\{txy},\39\\{tx})$;\5 -\&{return};\6 -\&{end}\par -\U966.\fi - -\M968. Let \|p point to a two-word value field inside a big node of \\{cur% -\_exp}, -and let \|q point to a another value field. The \\{bilin1} procedure -replaces \|p by $p\cdot t+q\cdot u+\delta$. - -\Y\P$\4\X968:Declare subroutines needed by \\{big\_trans}\X\S$\6 -\4\&{procedure}\1\ \37$\\{bilin1}(\|p:\\{pointer};\,\35\|t:\\{scaled};\,\35% -\|q:\\{pointer};\,\35\|u,\39\\{delta}:\\{scaled})$;\6 -\4\&{var} \37\|r: \37\\{pointer};\C{list traverser}\2\6 -\&{begin} \37\&{if} $\|t\I\\{unity}$ \1\&{then}\5 -$\\{dep\_mult}(\|p,\39\|t,\39\\{true})$;\2\6 -\&{if} $\|u\I0$ \1\&{then}\6 -\&{if} $\\{type}(\|q)=\\{known}$ \1\&{then}\5 -$\\{delta}\K\\{delta}+\\{take\_scaled}(\\{value}(\|q),\39\|u)$\6 -\4\&{else} \&{begin} \37\X969:Ensure that $\\{type}(\|p)=\\{proto\_dependent}$% -\X;\6 -$\\{dep\_list}(\|p)\K\\{p\_plus\_fq}(\\{dep\_list}(\|p),\39\|u,\39\\{dep% -\_list}(\|q),\39\\{proto\_dependent},\39\\{type}(\|q))$;\6 -\&{end};\2\2\6 -\&{if} $\\{type}(\|p)=\\{known}$ \1\&{then}\5 -$\\{value}(\|p)\K\\{value}(\|p)+\\{delta}$\6 -\4\&{else} \&{begin} \37$\|r\K\\{dep\_list}(\|p)$;\6 -\&{while} $\\{info}(\|r)\I\\{null}$ \1\&{do}\5 -$\|r\K\\{link}(\|r)$;\2\6 -$\\{delta}\K\\{value}(\|r)+\\{delta}$;\6 -\&{if} $\|r\I\\{dep\_list}(\|p)$ \1\&{then}\5 -$\\{value}(\|r)\K\\{delta}$\6 -\4\&{else} \&{begin} \37$\\{recycle\_value}(\|p)$;\5 -$\\{type}(\|p)\K\\{known}$;\5 -$\\{value}(\|p)\K\\{delta}$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{if} $\\{fix\_needed}$ \1\&{then}\5 -\\{fix\_dependencies};\2\6 -\&{end};\par -\As971, 972\ETs974. -\U966.\fi - -\M969. \P$\X969:Ensure that $\\{type}(\|p)=\\{proto\_dependent}$\X\S$\6 -\&{if} $\\{type}(\|p)\I\\{proto\_dependent}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{type}(\|p)=\\{known}$ \1\&{then}\5 -$\\{new\_dep}(\|p,\39\\{const\_dependency}(\\{value}(\|p)))$\6 -\4\&{else} $\\{dep\_list}(\|p)\K\\{p\_times\_v}(\\{dep\_list}(\|p),\39% -\\{unity},\39\\{dependent},\39\\{proto\_dependent},\39\\{true})$;\2\6 -$\\{type}(\|p)\K\\{proto\_dependent}$;\6 -\&{end}\2\par -\U968.\fi - -\M970. \P$\X970:Transform a known big node\X\S$\6 -$\\{set\_up\_trans}(\|c)$;\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -\X973:Transform known by known\X\6 -\4\&{else} \&{begin} \37$\\{pp}\K\\{stash\_cur\_exp}$;\5 -$\\{qq}\K\\{value}(\\{pp})$;\5 -$\\{make\_exp\_copy}(\|p)$;\5 -$\|r\K\\{value}(\\{cur\_exp})$;\6 -\&{if} $\\{cur\_type}=\\{transform\_type}$ \1\&{then}\6 -\&{begin} \37$\\{bilin2}(\\{yy\_part\_loc}(\|r),\39\\{yy\_part\_loc}(\\{qq}),% -\39\\{value}(\\{xy\_part\_loc}(\|q)),\39\\{yx\_part\_loc}(\\{qq}),\39% -\\{null})$;\5 -$\\{bilin2}(\\{yx\_part\_loc}(\|r),\39\\{yy\_part\_loc}(\\{qq}),\39\\{value}(% -\\{xx\_part\_loc}(\|q)),\39\\{yx\_part\_loc}(\\{qq}),\39\\{null})$;\5 -$\\{bilin2}(\\{xy\_part\_loc}(\|r),\39\\{xx\_part\_loc}(\\{qq}),\39\\{value}(% -\\{yy\_part\_loc}(\|q)),\39\\{xy\_part\_loc}(\\{qq}),\39\\{null})$;\5 -$\\{bilin2}(\\{xx\_part\_loc}(\|r),\39\\{xx\_part\_loc}(\\{qq}),\39\\{value}(% -\\{yx\_part\_loc}(\|q)),\39\\{xy\_part\_loc}(\\{qq}),\39\\{null})$;\6 -\&{end};\2\6 -$\\{bilin2}(\\{y\_part\_loc}(\|r),\39\\{yy\_part\_loc}(\\{qq}),\39\\{value}(% -\\{x\_part\_loc}(\|q)),\39\\{yx\_part\_loc}(\\{qq}),\39\\{y\_part\_loc}(% -\\{qq}))$;\5 -$\\{bilin2}(\\{x\_part\_loc}(\|r),\39\\{xx\_part\_loc}(\\{qq}),\39\\{value}(% -\\{y\_part\_loc}(\|q)),\39\\{xy\_part\_loc}(\\{qq}),\39\\{x\_part\_loc}(% -\\{qq}))$;\5 -$\\{recycle\_value}(\\{pp})$;\5 -$\\{free\_node}(\\{pp},\39\\{value\_node\_size})$;\6 -\&{end};\2\par -\U966.\fi - -\M971. Let \|p be a \\{proto\_dependent} value whose dependency list ends -at \\{dep\_final}. The following procedure adds \|v times another -numeric quantity to~\|p. - -\Y\P$\4\X968:Declare subroutines needed by \\{big\_trans}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{add\_mult\_dep}(\|p:\\{pointer};\,\35\|v:\\{scaled};% -\,\35\|r:\\{pointer})$;\2\6 -\&{begin} \37\&{if} $\\{type}(\|r)=\\{known}$ \1\&{then}\5 -$\\{value}(\\{dep\_final})\K\\{value}(\\{dep\_final})+\\{take\_scaled}(% -\\{value}(\|r),\39\|v)$\6 -\4\&{else} \&{begin} \37$\\{dep\_list}(\|p)\K\\{p\_plus\_fq}(\\{dep\_list}(% -\|p),\39\|v,\39\\{dep\_list}(\|r),\39\\{proto\_dependent},\39\\{type}(\|r))$;\6 -\&{if} $\\{fix\_needed}$ \1\&{then}\5 -\\{fix\_dependencies};\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M972. The \\{bilin2} procedure is something like \\{bilin1}, but with known -and unknown quantities reversed. Parameter \|p points to a value field -within the big node for \\{cur\_exp}; and $\\{type}(\|p)=\\{known}$. Parameters -\|t and~\|u point to value fields elsewhere; so does parameter~\|q, -unless it is \\{null} (which stands for zero). Location~\|p will be -replaced by $p\cdot t+v\cdot u+q$. - -\Y\P$\4\X968:Declare subroutines needed by \\{big\_trans}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{bilin2}(\|p,\39\|t:\\{pointer};\,\35\|v:\\{scaled};% -\,\35\|u,\39\|q:\\{pointer})$;\6 -\4\&{var} \37\\{vv}: \37\\{scaled};\C{temporary storage for $\\{value}(\|p)$}\2% -\6 -\&{begin} \37$\\{vv}\K\\{value}(\|p)$;\5 -$\\{type}(\|p)\K\\{proto\_dependent}$;\5 -$\\{new\_dep}(\|p,\39\\{const\_dependency}(0))$;\C{this sets \\{dep\_final}}\6 -\&{if} $\\{vv}\I0$ \1\&{then}\5 -$\\{add\_mult\_dep}(\|p,\39\\{vv},\39\|t)$;\C{\\{dep\_final} doesn't change}\2\6 -\&{if} $\|v\I0$ \1\&{then}\5 -$\\{add\_mult\_dep}(\|p,\39\|v,\39\|u)$;\2\6 -\&{if} $\|q\I\\{null}$ \1\&{then}\5 -$\\{add\_mult\_dep}(\|p,\39\\{unity},\39\|q)$;\2\6 -\&{if} $\\{dep\_list}(\|p)=\\{dep\_final}$ \1\&{then}\6 -\&{begin} \37$\\{vv}\K\\{value}(\\{dep\_final})$;\5 -$\\{recycle\_value}(\|p)$;\5 -$\\{type}(\|p)\K\\{known}$;\5 -$\\{value}(\|p)\K\\{vv}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M973. \P$\X973:Transform known by known\X\S$\6 -\&{begin} \37$\\{make\_exp\_copy}(\|p)$;\5 -$\|r\K\\{value}(\\{cur\_exp})$;\6 -\&{if} $\\{cur\_type}=\\{transform\_type}$ \1\&{then}\6 -\&{begin} \37$\\{bilin3}(\\{yy\_part\_loc}(\|r),\39\\{tyy},\39\\{value}(\\{xy% -\_part\_loc}(\|q)),\39\\{tyx},\390)$;\5 -$\\{bilin3}(\\{yx\_part\_loc}(\|r),\39\\{tyy},\39\\{value}(\\{xx\_part\_loc}(% -\|q)),\39\\{tyx},\390)$;\5 -$\\{bilin3}(\\{xy\_part\_loc}(\|r),\39\\{txx},\39\\{value}(\\{yy\_part\_loc}(% -\|q)),\39\\{txy},\390)$;\5 -$\\{bilin3}(\\{xx\_part\_loc}(\|r),\39\\{txx},\39\\{value}(\\{yx\_part\_loc}(% -\|q)),\39\\{txy},\390)$;\6 -\&{end};\2\6 -$\\{bilin3}(\\{y\_part\_loc}(\|r),\39\\{tyy},\39\\{value}(\\{x\_part\_loc}(% -\|q)),\39\\{tyx},\39\\{ty})$;\5 -$\\{bilin3}(\\{x\_part\_loc}(\|r),\39\\{txx},\39\\{value}(\\{y\_part\_loc}(% -\|q)),\39\\{txy},\39\\{tx})$;\6 -\&{end}\par -\U970.\fi - -\M974. Finally, in \\{bilin3} everything is \\{known}. - -\Y\P$\4\X968:Declare subroutines needed by \\{big\_trans}\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{bilin3}(\|p:\\{pointer};\,\35\|t,\39\|v,\39\|u,\39% -\\{delta}:\\{scaled})$;\2\6 -\&{begin} \37\&{if} $\|t\I\\{unity}$ \1\&{then}\5 -$\\{delta}\K\\{delta}+\\{take\_scaled}(\\{value}(\|p),\39\|t)$\6 -\4\&{else} $\\{delta}\K\\{delta}+\\{value}(\|p)$;\2\6 -\&{if} $\|u\I0$ \1\&{then}\5 -$\\{value}(\|p)\K\\{delta}+\\{take\_scaled}(\|v,\39\|u)$\6 -\4\&{else} $\\{value}(\|p)\K\\{delta}$;\2\6 -\&{end};\par -\fi - -\M975. \P$\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4\\{concatenate}: \37\&{if} $(\\{cur\_type}=\\{string\_type})\W(\\{type}(\|p)=% -\\{string\_type})$ \1\&{then}\5 -$\\{cat}(\|p)$\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\\{concatenate})$;\2\6 -\4\\{substring\_of}: \37\&{if} $\\{nice\_pair}(\|p,\39\\{type}(\|p))\W(\\{cur% -\_type}=\\{string\_type})$ \1\&{then}\5 -$\\{chop\_string}(\\{value}(\|p))$\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\\{substring\_of})$;\2\6 -\4\\{subpath\_of}: \37\&{begin} \37\&{if} $\\{cur\_type}=\\{pair\_type}$ \1% -\&{then}\5 -\\{pair\_to\_path};\2\6 -\&{if} $\\{nice\_pair}(\|p,\39\\{type}(\|p))\W(\\{cur\_type}=\\{path\_type})$ % -\1\&{then}\5 -$\\{chop\_path}(\\{value}(\|p))$\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\\{subpath\_of})$;\2\6 -\&{end};\par -\fi - -\M976. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{cat}(\|p:\\{pointer})$;\6 -\4\&{var} \37$\|a,\39\|b$: \37\\{str\_number};\C{the strings being -concatenated}\6 -\|k: \37\\{pool\_pointer};\C{index into \\{str\_pool}}\2\6 -\&{begin} \37$\|a\K\\{value}(\|p)$;\5 -$\|b\K\\{cur\_exp}$;\5 -$\\{str\_room}(\\{length}(\|a)+\\{length}(\|b))$;\6 -\&{for} $\|k\K\\{str\_start}[\|a]\mathrel{\&{to}}\\{str\_start}[\|a+1]-1$ \1% -\&{do}\5 -$\\{append\_char}(\\{so}(\\{str\_pool}[\|k]))$;\2\6 -\&{for} $\|k\K\\{str\_start}[\|b]\mathrel{\&{to}}\\{str\_start}[\|b+1]-1$ \1% -\&{do}\5 -$\\{append\_char}(\\{so}(\\{str\_pool}[\|k]))$;\2\6 -$\\{cur\_exp}\K\\{make\_string}$;\5 -$\\{delete\_str\_ref}(\|b)$;\6 -\&{end};\par -\fi - -\M977. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{chop\_string}(\|p:\\{pointer})$;\6 -\4\&{var} \37$\|a,\39\|b$: \37\\{integer};\C{start and stop points}\6 -\|l: \37\\{integer};\C{length of the original string}\6 -\|k: \37\\{integer};\C{runs from \|a to \|b}\6 -\|s: \37\\{str\_number};\C{the original string}\6 -\\{reversed}: \37\\{boolean};\C{was $\|a>\|b$?}\2\6 -\&{begin} \37$\|a\K\\{round\_unscaled}(\\{value}(\\{x\_part\_loc}(\|p)))$;\5 -$\|b\K\\{round\_unscaled}(\\{value}(\\{y\_part\_loc}(\|p)))$;\6 -\&{if} $\|a\L\|b$ \1\&{then}\5 -$\\{reversed}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\\{reversed}\K\\{true}$;\5 -$\|k\K\|a$;\5 -$\|a\K\|b$;\5 -$\|b\K\|k$;\6 -\&{end};\2\6 -$\|s\K\\{cur\_exp}$;\5 -$\|l\K\\{length}(\|s)$;\6 -\&{if} $\|a<0$ \1\&{then}\6 -\&{begin} \37$\|a\K0$;\6 -\&{if} $\|b<0$ \1\&{then}\5 -$\|b\K0$;\2\6 -\&{end};\2\6 -\&{if} $\|b>\|l$ \1\&{then}\6 -\&{begin} \37$\|b\K\|l$;\6 -\&{if} $\|a>\|l$ \1\&{then}\5 -$\|a\K\|l$;\2\6 -\&{end};\2\6 -$\\{str\_room}(\|b-\|a)$;\6 -\&{if} $\\{reversed}$ \1\&{then}\6 -\&{for} $\|k\K\\{str\_start}[\|s]+\|b-1\mathrel{\&{downto}}\\{str\_start}[\|s]+% -\|a$ \1\&{do}\5 -$\\{append\_char}(\\{so}(\\{str\_pool}[\|k]))$\2\6 -\4\&{else} \&{for} $\|k\K\\{str\_start}[\|s]+\|a\mathrel{\&{to}}\\{str\_start}[% -\|s]+\|b-1$ \1\&{do}\5 -$\\{append\_char}(\\{so}(\\{str\_pool}[\|k]))$;\2\2\6 -$\\{cur\_exp}\K\\{make\_string}$;\5 -$\\{delete\_str\_ref}(\|s)$;\6 -\&{end};\par -\fi - -\M978. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{chop\_path}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{a knot in the original path}\6 -$\\{pp},\39\\{qq},\39\\{rr},\39\\{ss}$: \37\\{pointer};\C{link variables for -copies of path nodes}\6 -$\|a,\39\|b,\39\|k,\39\|l$: \37\\{scaled};\C{indices for chopping}\6 -\\{reversed}: \37\\{boolean};\C{was $\|a>\|b$?}\2\6 -\&{begin} \37$\|l\K\\{path\_length}$;\5 -$\|a\K\\{value}(\\{x\_part\_loc}(\|p))$;\5 -$\|b\K\\{value}(\\{y\_part\_loc}(\|p))$;\6 -\&{if} $\|a\L\|b$ \1\&{then}\5 -$\\{reversed}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\\{reversed}\K\\{true}$;\5 -$\|k\K\|a$;\5 -$\|a\K\|b$;\5 -$\|b\K\|k$;\6 -\&{end};\2\6 -\X979:Dispense with the cases $\|a<0$ and/or $\|b>\|l$\X;\6 -$\|q\K\\{cur\_exp}$;\6 -\&{while} $\|a\G\\{unity}$ \1\&{do}\6 -\&{begin} \37$\|q\K\\{link}(\|q)$;\5 -$\|a\K\|a-\\{unity}$;\5 -$\|b\K\|b-\\{unity}$;\6 -\&{end};\2\6 -\&{if} $\|b=\|a$ \1\&{then}\5 -\X981:Construct a path from \\{pp} to \\{qq} of length zero\X\6 -\4\&{else} \X980:Construct a path from \\{pp} to \\{qq} of length $\lceil b% -\rceil$\X;\2\6 -$\\{left\_type}(\\{pp})\K\\{endpoint}$;\5 -$\\{right\_type}(\\{qq})\K\\{endpoint}$;\5 -$\\{link}(\\{qq})\K\\{pp}$;\5 -$\\{toss\_knot\_list}(\\{cur\_exp})$;\6 -\&{if} $\\{reversed}$ \1\&{then}\6 -\&{begin} \37$\\{cur\_exp}\K\\{link}(\\{htap\_ypoc}(\\{pp}))$;\5 -$\\{toss\_knot\_list}(\\{pp})$;\6 -\&{end}\6 -\4\&{else} $\\{cur\_exp}\K\\{pp}$;\2\6 -\&{end};\par -\fi - -\M979. \P$\X979:Dispense with the cases $\|a<0$ and/or $\|b>\|l$\X\S$\6 -\&{if} $\|a<0$ \1\&{then}\6 -\&{if} $\\{left\_type}(\\{cur\_exp})=\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\|a\K0$;\6 -\&{if} $\|b<0$ \1\&{then}\5 -$\|b\K0$;\2\6 -\&{end}\6 -\4\&{else} \1\&{repeat} \37$\|a\K\|a+\|l$;\5 -$\|b\K\|b+\|l$;\6 -\4\&{until}\5 -$\|a\G0$;\C{a cycle always has length $\|l>0$}\2\2\2\6 -\&{if} $\|b>\|l$ \1\&{then}\6 -\&{if} $\\{left\_type}(\\{cur\_exp})=\\{endpoint}$ \1\&{then}\6 -\&{begin} \37$\|b\K\|l$;\6 -\&{if} $\|a>\|l$ \1\&{then}\5 -$\|a\K\|l$;\2\6 -\&{end}\6 -\4\&{else} \&{while} $\|a\G\|l$ \1\&{do}\6 -\&{begin} \37$\|a\K\|a-\|l$;\5 -$\|b\K\|b-\|l$;\6 -\&{end}\2\2\2\par -\U978.\fi - -\M980. \P$\X980:Construct a path from \\{pp} to \\{qq} of length $\lceil b% -\rceil$\X\S$\6 -\&{begin} \37$\\{pp}\K\\{copy\_knot}(\|q)$;\5 -$\\{qq}\K\\{pp}$;\6 -\1\&{repeat} \37$\|q\K\\{link}(\|q)$;\5 -$\\{rr}\K\\{qq}$;\5 -$\\{qq}\K\\{copy\_knot}(\|q)$;\5 -$\\{link}(\\{rr})\K\\{qq}$;\5 -$\|b\K\|b-\\{unity}$;\6 -\4\&{until}\5 -$\|b\L0$;\2\6 -\&{if} $\|a>0$ \1\&{then}\6 -\&{begin} \37$\\{ss}\K\\{pp}$;\5 -$\\{pp}\K\\{link}(\\{pp})$;\5 -$\\{split\_cubic}(\\{ss},\39\|a\ast\O{10000},\39\\{x\_coord}(\\{pp}),\39\\{y% -\_coord}(\\{pp}))$;\5 -$\\{pp}\K\\{link}(\\{ss})$;\5 -$\\{free\_node}(\\{ss},\39\\{knot\_node\_size})$;\6 -\&{if} $\\{rr}=\\{ss}$ \1\&{then}\6 -\&{begin} \37$\|b\K\\{make\_scaled}(\|b,\39\\{unity}-\|a)$;\5 -$\\{rr}\K\\{pp}$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{if} $\|b<0$ \1\&{then}\6 -\&{begin} \37$\\{split\_cubic}(\\{rr},\39(\|b+\\{unity})\ast\O{10000},\39\\{x% -\_coord}(\\{qq}),\39\\{y\_coord}(\\{qq}))$;\5 -$\\{free\_node}(\\{qq},\39\\{knot\_node\_size})$;\5 -$\\{qq}\K\\{link}(\\{rr})$;\6 -\&{end};\2\6 -\&{end}\par -\U978.\fi - -\M981. \P$\X981:Construct a path from \\{pp} to \\{qq} of length zero\X\S$\6 -\&{begin} \37\&{if} $\|a>0$ \1\&{then}\6 -\&{begin} \37$\\{qq}\K\\{link}(\|q)$;\5 -$\\{split\_cubic}(\|q,\39\|a\ast\O{10000},\39\\{x\_coord}(\\{qq}),\39\\{y% -\_coord}(\\{qq}))$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -$\\{pp}\K\\{copy\_knot}(\|q)$;\5 -$\\{qq}\K\\{pp}$;\6 -\&{end}\par -\U978.\fi - -\M982. The \\{pair\_value} routine changes the current expression to a -given ordered pair of values. - -\Y\P$\4\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{pair\_value}(\|x,\39\|y:\\{scaled})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{a pair node}\2\6 -\&{begin} \37$\|p\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{flush\_cur\_exp}(\|p)$;\5 -$\\{cur\_type}\K\\{pair\_type}$;\5 -$\\{type}(\|p)\K\\{pair\_type}$;\5 -$\\{name\_type}(\|p)\K\\{capsule}$;\5 -$\\{init\_big\_node}(\|p)$;\5 -$\|p\K\\{value}(\|p)$;\6 -$\\{type}(\\{x\_part\_loc}(\|p))\K\\{known}$;\5 -$\\{value}(\\{x\_part\_loc}(\|p))\K\|x$;\6 -$\\{type}(\\{y\_part\_loc}(\|p))\K\\{known}$;\5 -$\\{value}(\\{y\_part\_loc}(\|p))\K\|y$;\6 -\&{end};\par -\fi - -\M983. \P$\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4$\\{point\_of},\39\\{precontrol\_of},\39\\{postcontrol\_of}$: \37\&{begin} % -\37\&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\5 -\\{pair\_to\_path};\2\6 -\&{if} $(\\{cur\_type}=\\{path\_type})\W(\\{type}(\|p)=\\{known})$ \1\&{then}\5 -$\\{find\_point}(\\{value}(\|p),\39\|c)$\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\|c)$;\2\6 -\&{end};\6 -\4\\{pen\_offset\_of}: \37\&{begin} \37\&{if} $\\{cur\_type}=\\{future\_pen}$ % -\1\&{then}\5 -\\{materialize\_pen};\2\6 -\&{if} $(\\{cur\_type}=\\{pen\_type})\W\\{nice\_pair}(\|p,\39\\{type}(\|p))$ \1% -\&{then}\5 -$\\{set\_up\_offset}(\\{value}(\|p))$\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\\{pen\_offset\_of})$;\2\6 -\&{end};\6 -\4\\{direction\_time\_of}: \37\&{begin} \37\&{if} $\\{cur\_type}=\\{pair% -\_type}$ \1\&{then}\5 -\\{pair\_to\_path};\2\6 -\&{if} $(\\{cur\_type}=\\{path\_type})\W\\{nice\_pair}(\|p,\39\\{type}(\|p))$ % -\1\&{then}\5 -$\\{set\_up\_direction\_time}(\\{value}(\|p))$\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\\{direction\_time\_of})$;\2\6 -\&{end};\par -\fi - -\M984. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{set\_up\_offset}(\|p:\\{pointer})$;\2\6 -\&{begin} \37$\\{find\_offset}(\\{value}(\\{x\_part\_loc}(\|p)),\39\\{value}(% -\\{y\_part\_loc}(\|p)),\39\\{cur\_exp})$;\5 -$\\{pair\_value}(\\{cur\_x},\39\\{cur\_y})$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{set\_up\_direction\_time}(\|p:\\{pointer})$;\2\6 -\&{begin} \37$\\{flush\_cur\_exp}(\\{find\_direction\_time}(\\{value}(\\{x% -\_part\_loc}(\|p)),\39\\{value}(\\{y\_part\_loc}(\|p)),\39\\{cur\_exp}))$;\6 -\&{end};\par -\fi - -\M985. \P$\X923:Declare binary action procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{find\_point}(\|v:\\{scaled};\,\35\|c:% -\\{quarterword})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{the path}\6 -\|n: \37\\{scaled};\C{its length}\6 -\|q: \37\\{pointer};\C{successor of \|p}\2\6 -\&{begin} \37$\|p\K\\{cur\_exp}$;\6 -\&{if} $\\{left\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -$\|n\K-\\{unity}$\ \&{else} $\|n\K0$;\2\6 -\1\&{repeat} \37$\|p\K\\{link}(\|p)$;\5 -$\|n\K\|n+\\{unity}$;\6 -\4\&{until}\5 -$\|p=\\{cur\_exp}$;\2\6 -\&{if} $\|n=0$ \1\&{then}\5 -$\|v\K0$\6 -\4\&{else} \&{if} $\|v<0$ \1\&{then}\6 -\&{if} $\\{left\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -$\|v\K0$\6 -\4\&{else} $\|v\K\|n-1-((-\|v-1)\mathbin{\&{mod}}\|n)$\2\6 -\4\&{else} \&{if} $\|v>\|n$ \1\&{then}\6 -\&{if} $\\{left\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -$\|v\K\|n$\6 -\4\&{else} $\|v\K\|v\mathbin{\&{mod}}\|n$;\2\2\2\2\6 -$\|p\K\\{cur\_exp}$;\6 -\&{while} $\|v\G\\{unity}$ \1\&{do}\6 -\&{begin} \37$\|p\K\\{link}(\|p)$;\5 -$\|v\K\|v-\\{unity}$;\6 -\&{end};\2\6 -\&{if} $\|v\I0$ \1\&{then}\5 -\X986:Insert a fractional node by splitting the cubic\X;\2\6 -\X987:Set the current expression to the desired path coordinates\X;\6 -\&{end};\par -\fi - -\M986. \P$\X986:Insert a fractional node by splitting the cubic\X\S$\6 -\&{begin} \37$\|q\K\\{link}(\|p)$;\5 -$\\{split\_cubic}(\|p,\39\|v\ast\O{10000},\39\\{x\_coord}(\|q),\39\\{y\_coord}(% -\|q))$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end}\par -\U985.\fi - -\M987. \P$\X987:Set the current expression to the desired path coordinates\X\S$% -\6 -\&{case} $\|c$ \1\&{of}\6 -\4\\{point\_of}: \37$\\{pair\_value}(\\{x\_coord}(\|p),\39\\{y\_coord}(\|p))$;\6 -\4\\{precontrol\_of}: \37\&{if} $\\{left\_type}(\|p)=\\{endpoint}$ \1\&{then}\5 -$\\{pair\_value}(\\{x\_coord}(\|p),\39\\{y\_coord}(\|p))$\6 -\4\&{else} $\\{pair\_value}(\\{left\_x}(\|p),\39\\{left\_y}(\|p))$;\2\6 -\4\\{postcontrol\_of}: \37\&{if} $\\{right\_type}(\|p)=\\{endpoint}$ \1\&{then}% -\5 -$\\{pair\_value}(\\{x\_coord}(\|p),\39\\{y\_coord}(\|p))$\6 -\4\&{else} $\\{pair\_value}(\\{right\_x}(\|p),\39\\{right\_y}(\|p))$;\2\2\6 -\&{end}\C{there are no other cases}\par -\U985.\fi - -\M988. \P$\X936:Additional cases of binary operators\X\mathrel{+}\S$\6 -\4\\{intersect}: \37\&{begin} \37\&{if} $\\{type}(\|p)=\\{pair\_type}$ \1% -\&{then}\6 -\&{begin} \37$\|q\K\\{stash\_cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\|p)$;\5 -\\{pair\_to\_path};\5 -$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\|q)$;\6 -\&{end};\2\6 -\&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\5 -\\{pair\_to\_path};\2\6 -\&{if} $(\\{cur\_type}=\\{path\_type})\W(\\{type}(\|p)=\\{path\_type})$ \1% -\&{then}\6 -\&{begin} \37$\\{path\_intersection}(\\{value}(\|p),\39\\{cur\_exp})$;\5 -$\\{pair\_value}(\\{cur\_t},\39\\{cur\_tt})$;\6 -\&{end}\6 -\4\&{else} $\\{bad\_binary}(\|p,\39\\{intersect})$;\2\6 -\&{end};\par -\fi - -\N989. \[43] Statements and commands. -The chief executive of \MF\ is the \\{do\_statement} routine, which -contains the master switch that causes all the various pieces of \MF\ -to do their things, in the right order. - -In a sense, this is the grand climax of the program: It applies all the -tools that we have worked so hard to construct. In another sense, this is -the messiest part of the program: It necessarily refers to other pieces -of code all over the place, so that a person can't fully understand what is -going on without paging back and forth to be reminded of conventions that -are defined elsewhere. We are now at the hub of the web. - -The structure of \\{do\_statement} itself is quite simple. The first token -of the statement is fetched using \\{get\_x\_next}. If it can be the first -token of an expression, we look for an equation, an assignment, or a -title. Otherwise we use a \&{case} construction to branch at high speed to -the appropriate routine for various and sundry other types of commands, -each of which has an ``action procedure'' that does the necessary work. - -The program uses the fact that -$$\hbox{$\\{min\_primary\_command}=\\{max\_statement\_command}=\\{type% -\_name}$}$$ -to interpret a statement that starts with, e.g., `\&{string}', -as a type declaration rather than a boolean expression. - -\Y\P\hbox{\4}\X1154:Declare generic font output procedures\X\6 -\hbox{\4}\X995:Declare action procedures for use by \\{do\_statement}\X\6 -\4\&{procedure}\1\ \37\\{do\_statement};\C{governs \MF's activities}\2\6 -\&{begin} \37$\\{cur\_type}\K\\{vacuous}$;\5 -\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}>\\{max\_primary\_command}$ \1\&{then}\5 -\X990:Worry about bad statement\X\6 -\4\&{else} \&{if} $\\{cur\_cmd}>\\{max\_statement\_command}$ \1\&{then}\5 -\X993:Do an equation, assignment, title, or `$\langle\,$expression$\,\rangle\,$% -\&{endgroup}'\X\6 -\4\&{else} \X992:Do a statement that doesn't begin with an expression\X;\2\2\6 -\&{if} $\\{cur\_cmd}<\\{semicolon}$ \1\&{then}\5 -\X991:Flush unparsable junk that was found after the statement\X;\2\6 -$\\{error\_count}\K0$;\6 -\&{end};\par -\fi - -\M990. The only command codes $>\\{max\_primary\_command}$ that can be present -at the beginning of a statement are \\{semicolon} and higher; these -occur when the statement is null. - -\Y\P$\4\X990:Worry about bad statement\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_cmd}<\\{semicolon}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"A\ statement\ can\'t\ begin\ with\ \`"})$;\5 -$\\{print\_cmd\_mod}(\\{cur\_cmd},\39\\{cur\_mod})$;\5 -$\\{print\_char}(\.{"\'"})$;\5 -$\\{help5}(\.{"I\ was\ looking\ for\ the\ beginning\ of\ a\ new\ statement."})$% -\6 -$(\.{"If\ you\ just\ proceed\ without\ changing\ anything,\ I\'ll\ ignore"})$\6 -$(\.{"everything\ up\ to\ the\ next\ \`;\'.\ Please\ insert\ a\ semicolon"})$\6 -$(\.{"now\ in\ front\ of\ anything\ that\ you\ don\'t\ want\ me\ to\ -delete."})$\6 -$(\.{"(See\ Chapter\ 27\ of\ The\ METAFONTbook\ for\ an\ example.)"})$;\6 -\\{back\_error};\5 -\\{get\_x\_next};\6 -\&{end};\2\6 -\&{end}\par -\U989.\fi - -\M991. The help message printed here says that everything is flushed up to -a semicolon, but actually the commands \\{end\_group} and \\{stop} will -also terminate a statement. - -\Y\P$\4\X991:Flush unparsable junk that was found after the statement\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Extra\ tokens\ will\ be\ flushed"})$;\5 -$\\{help6}(\.{"I\'ve\ just\ read\ as\ much\ of\ that\ statement\ as\ I\ could\ -fathom,"})$\6 -$(\.{"so\ a\ semicolon\ should\ have\ been\ next.\ It\'s\ very\ puzzling..."})$% -\6 -$(\.{"but\ I\'ll\ try\ to\ get\ myself\ back\ together,\ by\ ignoring"})$\6 -$(\.{"everything\ up\ to\ the\ next\ \`;\'.\ Please\ insert\ a\ semicolon"})$\6 -$(\.{"now\ in\ front\ of\ anything\ that\ you\ don\'t\ want\ me\ to\ -delete."})$\6 -$(\.{"(See\ Chapter\ 27\ of\ The\ METAFONTbook\ for\ an\ example.)"})$;\6 -\\{back\_error};\5 -$\\{scanner\_status}\K\\{flushing}$;\6 -\1\&{repeat} \37\\{get\_next};\5 -\X743:Decrease the string reference count, if the current token is a string\X;\6 -\4\&{until}\5 -\\{end\_of\_statement};\C{$\\{cur\_cmd}=\\{semicolon}$, \\{end\_group}, or % -\\{stop}}\2\6 -$\\{scanner\_status}\K\\{normal}$;\6 -\&{end}\par -\U989.\fi - -\M992. If \\{do\_statement} ends with $\\{cur\_cmd}=\\{end\_group}$, we should -have -$\\{cur\_type}=\\{vacuous}$ unless the statement was simply an expression; -in the latter case, \\{cur\_type} and \\{cur\_exp} should represent that -expression. - -\Y\P$\4\X992:Do a statement that doesn't begin with an expression\X\S$\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_commands}]>0$ \1\&{then}\5 -\\{show\_cur\_cmd\_mod};\2\6 -\&{case} $\\{cur\_cmd}$ \1\&{of}\6 -\4\\{type\_name}: \37\\{do\_type\_declaration};\6 -\4\\{macro\_def}: \37\&{if} $\\{cur\_mod}>\\{var\_def}$ \1\&{then}\5 -\\{make\_op\_def}\6 -\4\&{else} \&{if} $\\{cur\_mod}>\\{end\_def}$ \1\&{then}\5 -\\{scan\_def};\2\2\6 -\hbox{\4}\X1020:Cases of \\{do\_statement} that invoke particular commands\X\2\6 -\&{end};\C{there are no other cases}\6 -$\\{cur\_type}\K\\{vacuous}$;\6 -\&{end}\par -\U989.\fi - -\M993. The most important statements begin with expressions. - -\Y\P$\4\X993:Do an equation, assignment, title, or `$\langle\,$expression$\,% -\rangle\,$\&{endgroup}'\X\S$\6 -\&{begin} \37$\\{var\_flag}\K\\{assignment}$;\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}<\\{end\_group}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{cur\_cmd}=\\{equals}$ \1\&{then}\5 -\\{do\_equation}\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{assignment}$ \1\&{then}\5 -\\{do\_assignment}\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{string\_type}$ \1\&{then}\5 -\X994:Do a title\X\6 -\4\&{else} \&{if} $\\{cur\_type}\I\\{vacuous}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Isolated\ expression"})$;\5 -$\\{help3}(\.{"I\ couldn\'t\ find\ an\ \`=\'\ or\ \`:=\'\ after\ the"})$\6 -$(\.{"expression\ that\ is\ shown\ above\ this\ error\ message,"})$\6 -$(\.{"so\ I\ guess\ I\'ll\ just\ ignore\ it\ and\ carry\ on."})$;\5 -\\{put\_get\_error};\6 -\&{end};\2\2\2\2\6 -$\\{flush\_cur\_exp}(0)$;\5 -$\\{cur\_type}\K\\{vacuous}$;\6 -\&{end};\2\6 -\&{end}\par -\U989.\fi - -\M994. \P$\X994:Do a title\X\S$\6 -\&{begin} \37\&{if} $\\{internal}[\\{tracing\_titles}]>0$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{""})$;\5 -$\\{slow\_print}(\\{cur\_exp})$;\5 -\\{update\_terminal};\6 -\&{end};\2\6 -\&{if} $\\{internal}[\\{proofing}]>0$ \1\&{then}\5 -\X1179:Send the current expression as a title to the output file\X;\2\6 -\&{end}\par -\U993.\fi - -\M995. Equations and assignments are performed by the pair of mutually -recursive -routines \\{do\_equation} and \\{do\_assignment}. These routines are called -when -$\\{cur\_cmd}=\\{equals}$ and when $\\{cur\_cmd}=\\{assignment}$, respectively; -the left-hand -side is in \\{cur\_type} and \\{cur\_exp}, while the right-hand side is yet -to be scanned. After the routines are finished, \\{cur\_type} and \\{cur\_exp} -will be equal to the right-hand side (which will normally be equal -to the left-hand side). - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X\S$\6 -\hbox{\4}\X1006:Declare the procedure called \\{try\_eq}\X\6 -\hbox{\4}\X1001:Declare the procedure called \\{make\_eq}\X\6 -\4\&{procedure}\1\ \37\\{do\_assignment};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{do\_equation};\6 -\4\&{var} \37\\{lhs}: \37\\{pointer};\C{capsule for the left-hand side}\6 -\|p: \37\\{pointer};\C{temporary register}\2\6 -\&{begin} \37$\\{lhs}\K\\{stash\_cur\_exp}$;\5 -\\{get\_x\_next};\5 -$\\{var\_flag}\K\\{assignment}$;\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}=\\{equals}$ \1\&{then}\5 -\\{do\_equation}\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{assignment}$ \1\&{then}\5 -\\{do\_assignment};\2\2\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{two}$ \1\&{then}\5 -\X997:Trace the current equation\X;\2\6 -\&{if} $\\{cur\_type}=\\{unknown\_path}$ \1\&{then}\6 -\&{if} $\\{type}(\\{lhs})=\\{pair\_type}$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\\{lhs})$;\5 -$\\{lhs}\K\|p$;\6 -\&{end};\C{in this case \\{make\_eq} will change the pair to a path}\2\2\6 -$\\{make\_eq}(\\{lhs})$;\C{equate \\{lhs} to $(\\{cur\_type},\\{cur\_exp})$}\6 -\&{end};\par -\As996, 1015, 1021, 1029, 1031, 1034, 1035, 1036, 1040, 1041, 1044, 1045, 1046, -1049, 1050, 1051, 1054, 1057, 1059, 1070, 1071, 1072, 1073, 1074, 1082, 1103, -1104, 1106, 1177\ETs1186. -\U989.\fi - -\M996. And \\{do\_assignment} is similar to \\{do\_expression}: - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_assignment};\6 -\4\&{var} \37\\{lhs}: \37\\{pointer};\C{token list for the left-hand side}\6 -\|p: \37\\{pointer};\C{where the left-hand value is stored}\6 -\|q: \37\\{pointer};\C{temporary capsule for the right-hand value}\2\6 -\&{begin} \37\&{if} $\\{cur\_type}\I\\{token\_list}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ \`:=\'\ will\ be\ changed\ to\ \`=% -\'"})$;\5 -$\\{help2}(\.{"I\ didn\'t\ find\ a\ variable\ name\ at\ the\ left\ of\ the\ % -\`:=\',"})$\6 -$(\.{"so\ I\'m\ going\ to\ pretend\ that\ you\ said\ \`=\'\ instead."})$;\6 -\\{error};\5 -\\{do\_equation};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{lhs}\K\\{cur\_exp}$;\5 -$\\{cur\_type}\K\\{vacuous}$;\6 -\\{get\_x\_next};\5 -$\\{var\_flag}\K\\{assignment}$;\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_cmd}=\\{equals}$ \1\&{then}\5 -\\{do\_equation}\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{assignment}$ \1\&{then}\5 -\\{do\_assignment};\2\2\6 -\&{if} $\\{internal}[\\{tracing\_commands}]>\\{two}$ \1\&{then}\5 -\X998:Trace the current assignment\X;\2\6 -\&{if} $\\{info}(\\{lhs})>\\{hash\_end}$ \1\&{then}\5 -\X999:Assign the current expression to an internal variable\X\6 -\4\&{else} \X1000:Assign the current expression to the variable \\{lhs}\X;\2\6 -$\\{flush\_node\_list}(\\{lhs})$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M997. \P$\X997:Trace the current equation\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{("})$;\5 -$\\{print\_exp}(\\{lhs},\390)$;\5 -$\\{print}(\.{")=("})$;\5 -$\\{print\_exp}(\\{null},\390)$;\5 -$\\{print}(\.{")\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U995.\fi - -\M998. \P$\X998:Trace the current assignment\X\S$\6 -\&{begin} \37\\{begin\_diagnostic};\5 -$\\{print\_nl}(\.{"\{"})$;\6 -\&{if} $\\{info}(\\{lhs})>\\{hash\_end}$ \1\&{then}\5 -$\\{slow\_print}(\\{int\_name}[\\{info}(\\{lhs})-(\\{hash\_end})])$\6 -\4\&{else} $\\{show\_token\_list}(\\{lhs},\39\\{null},\391000,\390)$;\2\6 -$\\{print}(\.{":="})$;\5 -$\\{print\_exp}(\\{null},\390)$;\5 -$\\{print\_char}(\.{"\}"})$;\5 -$\\{end\_diagnostic}(\\{false})$;\6 -\&{end}\par -\U996.\fi - -\M999. \P$\X999:Assign the current expression to an internal variable\X\S$\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -$\\{internal}[\\{info}(\\{lhs})-(\\{hash\_end})]\K\\{cur\_exp}$\6 -\4\&{else} \&{begin} \37$\\{exp\_err}(\.{"Internal\ quantity\ \`"})$;\5 -$\\{slow\_print}(\\{int\_name}[\\{info}(\\{lhs})-(\\{hash\_end})])$;\5 -$\\{print}(\.{"\'\ must\ receive\ a\ known\ value"})$;\5 -$\\{help2}(\.{"I\ can\'t\ set\ an\ internal\ quantity\ to\ anything\ but\ a\ -known"})$\6 -$(\.{"numeric\ value,\ so\ I\'ll\ have\ to\ ignore\ this\ assignment."})$;\5 -\\{put\_get\_error};\6 -\&{end}\2\par -\U996.\fi - -\M1000. \P$\X1000:Assign the current expression to the variable \\{lhs}\X\S$\6 -\&{begin} \37$\|p\K\\{find\_variable}(\\{lhs})$;\6 -\&{if} $\|p\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\|q\K\\{stash\_cur\_exp}$;\5 -$\\{cur\_type}\K\\{und\_type}(\|p)$;\5 -$\\{recycle\_value}(\|p)$;\5 -$\\{type}(\|p)\K\\{cur\_type}$;\5 -$\\{value}(\|p)\K\\{null}$;\5 -$\\{make\_exp\_copy}(\|p)$;\5 -$\|p\K\\{stash\_cur\_exp}$;\5 -$\\{unstash\_cur\_exp}(\|q)$;\5 -$\\{make\_eq}(\|p)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{obliterated}(\\{lhs})$;\5 -\\{put\_get\_error};\6 -\&{end};\2\6 -\&{end}\par -\U996.\fi - -\M1001. And now we get to the nitty-gritty. The \\{make\_eq} procedure is given -a pointer to a capsule that is to be equated to the current expression. - -\Y\P$\4\X1001:Declare the procedure called \\{make\_eq}\X\S$\6 -\4\&{procedure}\1\ \37$\\{make\_eq}(\\{lhs}:\\{pointer})$;\6 -\4\&{label} \37$\\{restart},\39\\{done},\39\\{not\_found}$;\6 -\4\&{var} \37\|t: \37\\{small\_number};\C{type of the left-hand side}\6 -\|v: \37\\{integer};\C{value of the left-hand side}\6 -$\|p,\39\|q$: \37\\{pointer};\C{pointers inside of big nodes}\2\6 -\&{begin} \37\\{restart}: \37$\|t\K\\{type}(\\{lhs})$;\6 -\&{if} $\|t\L\\{pair\_type}$ \1\&{then}\5 -$\|v\K\\{value}(\\{lhs})$;\2\6 -\&{case} $\|t$ \1\&{of}\6 -\hbox{\4}\X1003:For each type \|t, make an equation and \&{goto} \\{done} -unless \\{cur\_type} is incompatible with~\|t\X\2\6 -\&{end};\C{all cases have been listed}\6 -\X1002:Announce that the equation cannot be performed\X;\6 -\4\\{done}: \37\\{check\_arith};\5 -$\\{recycle\_value}(\\{lhs})$;\5 -$\\{free\_node}(\\{lhs},\39\\{value\_node\_size})$;\6 -\&{end};\par -\U995.\fi - -\M1002. \P$\X1002:Announce that the equation cannot be performed\X\S$\6 -$\\{disp\_err}(\\{lhs},\39\.{""})$;\5 -$\\{exp\_err}(\.{"Equation\ cannot\ be\ performed\ ("})$;\6 -\&{if} $\\{type}(\\{lhs})\L\\{pair\_type}$ \1\&{then}\5 -$\\{print\_type}(\\{type}(\\{lhs}))$\ \&{else} $\\{print}(\.{"numeric"})$;\2\6 -$\\{print\_char}(\.{"="})$;\6 -\&{if} $\\{cur\_type}\L\\{pair\_type}$ \1\&{then}\5 -$\\{print\_type}(\\{cur\_type})$\ \&{else} $\\{print}(\.{"numeric"})$;\2\6 -$\\{print\_char}(\.{")"})$;\6 -$\\{help2}(\.{"I\'m\ sorry,\ but\ I\ don\'t\ know\ how\ to\ make\ such\ things\ -equal."})$\6 -$(\.{"(See\ the\ two\ expressions\ just\ above\ the\ error\ message.)"})$;\5 -\\{put\_get\_error}\par -\U1001.\fi - -\M1003. \P$\X1003:For each type \|t, make an equation and \&{goto} \\{done} -unless \\{cur\_type} is incompatible with~\|t\X\S$\6 -\4$\\{boolean\_type},\39\\{string\_type},\39\\{pen\_type},\39\\{path\_type},\39% -\\{picture\_type}$: \37\&{if} $\\{cur\_type}=\|t+\\{unknown\_tag}$ \1\&{then}\6 -\&{begin} \37$\\{nonlinear\_eq}(\|v,\39\\{cur\_exp},\39\\{false})$;\5 -\&{goto} \37\\{done};\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_type}=\|t$ \1\&{then}\5 -\X1004:Report redundant or inconsistent equation and \&{goto} \\{done}\X;\2\2\6 -\4\\{unknown\_types}: \37\&{if} $\\{cur\_type}=\|t-\\{unknown\_tag}$ \1\&{then}% -\6 -\&{begin} \37$\\{nonlinear\_eq}(\\{cur\_exp},\39\\{lhs},\39\\{true})$;\5 -\&{goto} \37\\{done};\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_type}=\|t$ \1\&{then}\6 -\&{begin} \37$\\{ring\_merge}(\\{lhs},\39\\{cur\_exp})$;\5 -\&{goto} \37\\{done};\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\6 -\&{if} $\|t=\\{unknown\_path}$ \1\&{then}\6 -\&{begin} \37\\{pair\_to\_path};\5 -\&{goto} \37\\{restart};\6 -\&{end};\2\2\2\2\6 -\4$\\{transform\_type},\39\\{pair\_type}$: \37\&{if} $\\{cur\_type}=\|t$ \1% -\&{then}\5 -\X1005:Do multiple equations and \&{goto} \\{done}\X;\2\6 -\4$\\{known},\39\\{dependent},\39\\{proto\_dependent},\39\\{independent}$: \37% -\&{if} $\\{cur\_type}\G\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{try\_eq}(\\{lhs},\39\\{null})$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\4\\{vacuous}: \37\\{do\_nothing};\par -\U1001.\fi - -\M1004. \P$\X1004:Report redundant or inconsistent equation and \&{goto} % -\\{done}\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_type}\L\\{string\_type}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{cur\_type}=\\{string\_type}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{str\_vs\_str}(\|v,\39\\{cur\_exp})\I0$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{end}\6 -\4\&{else} \&{if} $\|v\I\\{cur\_exp}$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\2\6 -\X623:Exclaim about a redundant equation\X;\6 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -$\\{print\_err}(\.{"Redundant\ or\ inconsistent\ equation"})$;\5 -$\\{help2}(\.{"An\ equation\ between\ already-known\ quantities\ can\'t\ -help."})$\6 -$(\.{"But\ don\'t\ worry;\ continue\ and\ I\'ll\ just\ ignore\ it."})$;\5 -\\{put\_get\_error};\5 -\&{goto} \37\\{done};\6 -\4\\{not\_found}: \37$\\{print\_err}(\.{"Inconsistent\ equation"})$;\5 -$\\{help2}(\.{"The\ equation\ I\ just\ read\ contradicts\ what\ was\ said\ -before."})$\6 -$(\.{"But\ don\'t\ worry;\ continue\ and\ I\'ll\ just\ ignore\ it."})$;\5 -\\{put\_get\_error};\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U1003.\fi - -\M1005. \P$\X1005:Do multiple equations and \&{goto} \\{done}\X\S$\6 -\&{begin} \37$\|p\K\|v+\\{big\_node\_size}[\|t]$;\5 -$\|q\K\\{value}(\\{cur\_exp})+\\{big\_node\_size}[\|t]$;\6 -\1\&{repeat} \37$\|p\K\|p-2$;\5 -$\|q\K\|q-2$;\5 -$\\{try\_eq}(\|p,\39\|q)$;\6 -\4\&{until}\5 -$\|p=\|v$;\2\6 -\&{goto} \37\\{done};\6 -\&{end}\par -\U1003.\fi - -\M1006. The first argument to \\{try\_eq} is the location of a value node -in a capsule that will soon be recycled. The second argument is -either a location within a pair or transform node pointed to by -\\{cur\_exp}, or it is \\{null} (which means that \\{cur\_exp} itself -serves as the second argument). The idea is to leave \\{cur\_exp} unchanged, -but to equate the two operands. - -\Y\P$\4\X1006:Declare the procedure called \\{try\_eq}\X\S$\6 -\4\&{procedure}\1\ \37$\\{try\_eq}(\|l,\39\|r:\\{pointer})$;\6 -\4\&{label} \37$\\{done},\39\\{done1}$;\6 -\4\&{var} \37\|p: \37\\{pointer};\C{dependency list for right operand minus -left operand}\6 -\|t: \37$\\{known}\to\\{independent}$;\C{the type of list \|p}\6 -\|q: \37\\{pointer};\C{the constant term of \|p is here}\6 -\\{pp}: \37\\{pointer};\C{dependency list for right operand}\6 -\\{tt}: \37$\\{dependent}\to\\{independent}$;\C{the type of list \\{pp}}\6 -\\{copied}: \37\\{boolean};\C{have we copied a list that ought to be recycled?}% -\2\6 -\&{begin} \37\X1007:Remove the left operand from its container, negate it, and -put it into dependency list~\|p with constant term~\|q\X;\6 -\X1009:Add the right operand to list \|p\X;\6 -\&{if} $\\{info}(\|p)=\\{null}$ \1\&{then}\5 -\X1008:Deal with redundant or inconsistent equation\X\6 -\4\&{else} \&{begin} \37$\\{linear\_eq}(\|p,\39\|t)$;\6 -\&{if} $\|r=\\{null}$ \1\&{then}\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{if} $\\{type}(\\{cur\_exp})=\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{pp}\K\\{cur\_exp}$;\5 -$\\{cur\_exp}\K\\{value}(\\{cur\_exp})$;\5 -$\\{cur\_type}\K\\{known}$;\5 -$\\{free\_node}(\\{pp},\39\\{value\_node\_size})$;\6 -\&{end};\2\2\2\6 -\&{end};\2\6 -\&{end};\par -\U995.\fi - -\M1007. \P$\X1007:Remove the left operand from its container, negate it, and -put it into dependency list~\|p with constant term~\|q\X\S$\6 -$\|t\K\\{type}(\|l)$;\6 -\&{if} $\|t=\\{known}$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{dependent}$;\5 -$\|p\K\\{const\_dependency}(-\\{value}(\|l))$;\5 -$\|q\K\|p$;\6 -\&{end}\6 -\4\&{else} \&{if} $\|t=\\{independent}$ \1\&{then}\6 -\&{begin} \37$\|t\K\\{dependent}$;\5 -$\|p\K\\{single\_dependency}(\|l)$;\5 -$\\{negate}(\\{value}(\|p))$;\5 -$\|q\K\\{dep\_final}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|p\K\\{dep\_list}(\|l)$;\5 -$\|q\K\|p$;\6 -\~ \1\&{loop}\ \&{begin} \37$\\{negate}(\\{value}(\|q))$;\6 -\&{if} $\\{info}(\|q)=\\{null}$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -\4\\{done}: \37$\\{link}(\\{prev\_dep}(\|l))\K\\{link}(\|q)$;\5 -$\\{prev\_dep}(\\{link}(\|q))\K\\{prev\_dep}(\|l)$;\5 -$\\{type}(\|l)\K\\{known}$;\6 -\&{end}\2\2\par -\U1006.\fi - -\M1008. \P$\X1008:Deal with redundant or inconsistent equation\X\S$\6 -\&{begin} \37\&{if} $\\{abs}(\\{value}(\|p))>64$ \1\&{then}\C{off by .001 or -more}\6 -\&{begin} \37$\\{print\_err}(\.{"Inconsistent\ equation"})$;\6 -$\\{print}(\.{"\ (off\ by\ "})$;\5 -$\\{print\_scaled}(\\{value}(\|p))$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\\{help2}(\.{"The\ equation\ I\ just\ read\ contradicts\ what\ was\ said\ -before."})$\6 -$(\.{"But\ don\'t\ worry;\ continue\ and\ I\'ll\ just\ ignore\ it."})$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} \&{if} $\|r=\\{null}$ \1\&{then}\5 -\X623:Exclaim about a redundant equation\X;\2\2\6 -$\\{free\_node}(\|p,\39\\{dep\_node\_size})$;\6 -\&{end}\par -\U1006.\fi - -\M1009. \P$\X1009:Add the right operand to list \|p\X\S$\6 -\&{if} $\|r=\\{null}$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{value}(\|q)\K\\{value}(\|q)+\\{cur\_exp}$;\5 -\&{goto} \37\\{done1};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{tt}\K\\{cur\_type}$;\6 -\&{if} $\\{tt}=\\{independent}$ \1\&{then}\5 -$\\{pp}\K\\{single\_dependency}(\\{cur\_exp})$\6 -\4\&{else} $\\{pp}\K\\{dep\_list}(\\{cur\_exp})$;\2\6 -\&{end}\2\6 -\4\&{else} \&{if} $\\{type}(\|r)=\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{value}(\|q)\K\\{value}(\|q)+\\{value}(\|r)$;\5 -\&{goto} \37\\{done1};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{tt}\K\\{type}(\|r)$;\6 -\&{if} $\\{tt}=\\{independent}$ \1\&{then}\5 -$\\{pp}\K\\{single\_dependency}(\|r)$\6 -\4\&{else} $\\{pp}\K\\{dep\_list}(\|r)$;\2\6 -\&{end};\2\2\6 -\&{if} $\\{tt}\I\\{independent}$ \1\&{then}\5 -$\\{copied}\K\\{false}$\6 -\4\&{else} \&{begin} \37$\\{copied}\K\\{true}$;\5 -$\\{tt}\K\\{dependent}$;\6 -\&{end};\2\6 -\X1010:Add dependency list \\{pp} of type \\{tt} to dependency list~\|p of -type~\|t\X;\6 -\&{if} $\\{copied}$ \1\&{then}\5 -$\\{flush\_node\_list}(\\{pp})$;\2\6 -\4\\{done1}: \37\par -\U1006.\fi - -\M1010. \P$\X1010:Add dependency list \\{pp} of type \\{tt} to dependency list~% -\|p of type~\|t\X\S$\6 -$\\{watch\_coefs}\K\\{false}$;\6 -\&{if} $\|t=\\{tt}$ \1\&{then}\5 -$\|p\K\\{p\_plus\_q}(\|p,\39\\{pp},\39\|t)$\6 -\4\&{else} \&{if} $\|t=\\{proto\_dependent}$ \1\&{then}\5 -$\|p\K\\{p\_plus\_fq}(\|p,\39\\{unity},\39\\{pp},\39\\{proto\_dependent},\39% -\\{dependent})$\6 -\4\&{else} \&{begin} \37$\|q\K\|p$;\6 -\&{while} $\\{info}(\|q)\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\\{value}(\|q)\K\\{round\_fraction}(\\{value}(\|q))$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -$\|t\K\\{proto\_dependent}$;\5 -$\|p\K\\{p\_plus\_q}(\|p,\39\\{pp},\39\|t)$;\6 -\&{end};\2\2\6 -$\\{watch\_coefs}\K\\{true}$;\par -\U1009.\fi - -\M1011. Our next goal is to process type declarations. For this purpose it's -convenient to have a procedure that scans a $\langle\,$declared -variable$\,\rangle$ and returns the corresponding token list. After the -following procedure has acted, the token after the declared variable -will have been scanned, so it will appear in \\{cur\_cmd}, \\{cur\_mod}, -and~\\{cur\_sym}. - -\Y\P$\4\X1011:Declare the function called \\{scan\_declared\_variable}\X\S$\6 -\4\&{function}\1\ \37\\{scan\_declared\_variable}: \37\\{pointer};\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|x: \37\\{pointer};\C{hash address of the variable's root}\6 -$\|h,\39\|t$: \37\\{pointer};\C{head and tail of the token list to be returned}% -\6 -\|l: \37\\{pointer};\C{hash address of left bracket}\2\6 -\&{begin} \37\\{get\_symbol};\5 -$\|x\K\\{cur\_sym}$;\6 -\&{if} $\\{cur\_cmd}\I\\{tag\_token}$ \1\&{then}\5 -$\\{clear\_symbol}(\|x,\39\\{false})$;\2\6 -$\|h\K\\{get\_avail}$;\5 -$\\{info}(\|h)\K\|x$;\5 -$\|t\K\|h$;\6 -\~ \1\&{loop}\ \&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_sym}=0$ \1\&{then}\5 -\&{goto} \37\\{done};\2\6 -\&{if} $\\{cur\_cmd}\I\\{tag\_token}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}\I\\{internal\_quantity}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}=\\{left\_bracket}$ \1\&{then}\5 -\X1012:Descend past a collective subscript\X\6 -\4\&{else} \&{goto} \37\\{done};\2\2\2\6 -$\\{link}(\|t)\K\\{get\_avail}$;\5 -$\|t\K\\{link}(\|t)$;\5 -$\\{info}(\|t)\K\\{cur\_sym}$;\6 -\&{end};\2\6 -\4\\{done}: \37\&{if} $\\{eq\_type}(\|x)\I\\{tag\_token}$ \1\&{then}\5 -$\\{clear\_symbol}(\|x,\39\\{false})$;\2\6 -\&{if} $\\{equiv}(\|x)=\\{null}$ \1\&{then}\5 -$\\{new\_root}(\|x)$;\2\6 -$\\{scan\_declared\_variable}\K\|h$;\6 -\&{end};\par -\U697.\fi - -\M1012. If the subscript isn't collective, we don't accept it as part of the -declared variable. - -\Y\P$\4\X1012:Descend past a collective subscript\X\S$\6 -\&{begin} \37$\|l\K\\{cur\_sym}$;\5 -\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}\I\\{right\_bracket}$ \1\&{then}\6 -\&{begin} \37\\{back\_input};\5 -$\\{cur\_sym}\K\|l$;\5 -$\\{cur\_cmd}\K\\{left\_bracket}$;\5 -\&{goto} \37\\{done};\6 -\&{end}\6 -\4\&{else} $\\{cur\_sym}\K\\{collective\_subscript}$;\2\6 -\&{end}\par -\U1011.\fi - -\M1013. Type declarations are introduced by the following primitive operations. - -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"numeric"},\39\\{type\_name},\39\\{numeric\_type})$;\6 -$\\{primitive}(\.{"string"},\39\\{type\_name},\39\\{string\_type})$;\6 -$\\{primitive}(\.{"boolean"},\39\\{type\_name},\39\\{boolean\_type})$;\6 -$\\{primitive}(\.{"path"},\39\\{type\_name},\39\\{path\_type})$;\6 -$\\{primitive}(\.{"pen"},\39\\{type\_name},\39\\{pen\_type})$;\6 -$\\{primitive}(\.{"picture"},\39\\{type\_name},\39\\{picture\_type})$;\6 -$\\{primitive}(\.{"transform"},\39\\{type\_name},\39\\{transform\_type})$;\6 -$\\{primitive}(\.{"pair"},\39\\{type\_name},\39\\{pair\_type})$;\par -\fi - -\M1014. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{type\_name}: \37$\\{print\_type}(\|m)$;\par -\fi - -\M1015. Now we are ready to handle type declarations, assuming that a -\\{type\_name} has just been scanned. - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_type\_declaration};\6 -\4\&{var} \37\|t: \37\\{small\_number};\C{the type being declared}\6 -\|p: \37\\{pointer};\C{token list for a declared variable}\6 -\|q: \37\\{pointer};\C{value node for the variable}\2\6 -\&{begin} \37\&{if} $\\{cur\_mod}\G\\{transform\_type}$ \1\&{then}\5 -$\|t\K\\{cur\_mod}$\ \&{else} $\|t\K\\{cur\_mod}+\\{unknown\_tag}$;\2\6 -\1\&{repeat} \37$\|p\K\\{scan\_declared\_variable}$;\5 -$\\{flush\_variable}(\\{equiv}(\\{info}(\|p)),\39\\{link}(\|p),\39\\{false})$;\6 -$\|q\K\\{find\_variable}(\|p)$;\6 -\&{if} $\|q\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{type}(\|q)\K\|t$;\5 -$\\{value}(\|q)\K\\{null}$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Declared\ variable\ conflicts\ with% -\ previous\ vardef"})$;\5 -$\\{help2}(\.{"You\ can\'t\ use,\ e.g.,\ \`numeric\ foo[]\'\ after\ \`vardef\ -foo\'."})$\6 -$(\.{"Proceed,\ and\ I\'ll\ ignore\ the\ illegal\ redeclaration."})$;\5 -\\{put\_get\_error};\6 -\&{end};\2\6 -$\\{flush\_list}(\|p)$;\6 -\&{if} $\\{cur\_cmd}<\\{comma}$ \1\&{then}\5 -\X1016:Flush spurious symbols after the declared variable\X;\2\6 -\4\&{until}\5 -\\{end\_of\_statement};\2\6 -\&{end};\par -\fi - -\M1016. \P$\X1016:Flush spurious symbols after the declared variable\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Illegal\ suffix\ of\ declared\ variable\ will\ -be\ flushed"})$;\5 -$\\{help5}(\.{"Variables\ in\ declarations\ must\ consist\ entirely\ of"})$\6 -$(\.{"names\ and\ collective\ subscripts,\ e.g.,\ \`x[]a\'."})$\6 -$(\.{"Are\ you\ trying\ to\ use\ a\ reserved\ word\ in\ a\ variable\ name?"})$\6 -$(\.{"I\'m\ going\ to\ discard\ the\ junk\ I\ found\ here,"})$\6 -$(\.{"up\ to\ the\ next\ comma\ or\ the\ end\ of\ the\ declaration."})$;\6 -\&{if} $\\{cur\_cmd}=\\{numeric\_token}$ \1\&{then}\5 -$\\{help\_line}[2]\K\.{"Explicit\ subscripts\ like\ \`x15a\'\ aren\'t\ -permitted."}$;\2\6 -\\{put\_get\_error};\5 -$\\{scanner\_status}\K\\{flushing}$;\6 -\1\&{repeat} \37\\{get\_next};\5 -\X743:Decrease the string reference count, if the current token is a string\X;\6 -\4\&{until}\5 -$\\{cur\_cmd}\G\\{comma}$;\C{either \\{end\_of\_statement} or $\\{cur\_cmd}=% -\\{comma}$}\2\6 -$\\{scanner\_status}\K\\{normal}$;\6 -\&{end}\par -\U1015.\fi - -\M1017. \MF's \\{main\_control} procedure just calls \\{do\_statement} -repeatedly -until coming to the end of the user's program. -Each execution of \\{do\_statement} concludes with -$\\{cur\_cmd}=\\{semicolon}$, \\{end\_group}, or \\{stop}. - -\Y\P\4\&{procedure}\1\ \37\\{main\_control};\2\6 -\&{begin} \37\1\&{repeat} \37\\{do\_statement};\6 -\&{if} $\\{cur\_cmd}=\\{end\_group}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Extra\ \`endgroup\'"})$;\5 -$\\{help2}(\.{"I\'m\ not\ currently\ working\ on\ a\ \`begingroup\',"})$\6 -$(\.{"so\ I\ had\ better\ not\ try\ to\ end\ anything."})$;\5 -$\\{flush\_error}(0)$;\6 -\&{end};\2\6 -\4\&{until}\5 -$\\{cur\_cmd}=\\{stop}$;\2\6 -\&{end};\par -\fi - -\M1018. \P$\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}% -\S$\6 -$\\{primitive}(\.{"end"},\39\\{stop},\390)$;\6 -$\\{primitive}(\.{"dump"},\39\\{stop},\391)$;\par -\fi - -\M1019. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{stop}: \37\&{if} $\|m=0$ \1\&{then}\5 -$\\{print}(\.{"end"})$\ \&{else} $\\{print}(\.{"dump"})$;\2\par -\fi - -\N1020. \[44] Commands. -Let's turn now to statements that are classified as ``commands'' because -of their imperative nature. We'll begin with simple ones, so that it -will be clear how to hook command processing into the \\{do\_statement} -routine; -then we'll tackle the tougher commands. - -Here's one of the simplest: - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X\S$\6 -\4\\{random\_seed}: \37\\{do\_random\_seed};\par -\As1023, 1026, 1030, 1033, 1039, 1058, 1069, 1076, 1081, 1100\ETs1175. -\U992.\fi - -\M1021. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_random\_seed};\2\6 -\&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}\I\\{assignment}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{":="})$;\5 -$\\{help1}(\.{"Always\ say\ \`randomseed:=<numeric\ expression>\'."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Unknown\ value\ will\ be\ ignored"})$;\5 -$\\{help2}(\.{"Your\ expression\ was\ too\ random\ for\ me\ to\ handle,"})$\6 -$(\.{"so\ I\ won\'t\ change\ the\ random\ seed\ just\ now."})$;\6 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end}\6 -\4\&{else} \X1022:Initialize the random seed to \\{cur\_exp}\X;\2\6 -\&{end};\par -\fi - -\M1022. \P$\X1022:Initialize the random seed to \\{cur\_exp}\X\S$\6 -\&{begin} \37$\\{init\_randoms}(\\{cur\_exp})$;\6 -\&{if} $\\{selector}\G\\{log\_only}$ \1\&{then}\6 -\&{begin} \37$\\{old\_setting}\K\\{selector}$;\5 -$\\{selector}\K\\{log\_only}$;\5 -$\\{print\_nl}(\.{"\{randomseed:="})$;\5 -$\\{print\_scaled}(\\{cur\_exp})$;\5 -$\\{print\_char}(\.{"\}"})$;\5 -$\\{print\_nl}(\.{""})$;\5 -$\\{selector}\K\\{old\_setting}$;\6 -\&{end};\2\6 -\&{end}\par -\U1021.\fi - -\M1023. And here's another simple one (somewhat different in flavor): - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{mode\_command}: \37\&{begin} \37\\{print\_ln};\5 -$\\{interaction}\K\\{cur\_mod}$;\5 -\X70:Initialize the print \\{selector} based on \\{interaction}\X;\6 -\&{if} $\\{log\_opened}$ \1\&{then}\5 -$\\{selector}\K\\{selector}+2$;\2\6 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M1024. \P$\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}% -\S$\6 -$\\{primitive}(\.{"batchmode"},\39\\{mode\_command},\39\\{batch\_mode})$;\5 -$\\{primitive}(\.{"nonstopmode"},\39\\{mode\_command},\39\\{nonstop\_mode})$;\5 -$\\{primitive}(\.{"scrollmode"},\39\\{mode\_command},\39\\{scroll\_mode})$;\5 -$\\{primitive}(\.{"errorstopmode"},\39\\{mode\_command},\39\\{error\_stop% -\_mode})$;\par -\fi - -\M1025. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{mode\_command}: \37\&{case} $\|m$ \1\&{of}\6 -\4\\{batch\_mode}: \37$\\{print}(\.{"batchmode"})$;\6 -\4\\{nonstop\_mode}: \37$\\{print}(\.{"nonstopmode"})$;\6 -\4\\{scroll\_mode}: \37$\\{print}(\.{"scrollmode"})$;\6 -\4\&{othercases} \37$\\{print}(\.{"errorstopmode"})$\2\6 -\&{endcases};\par -\fi - -\M1026. The `\&{inner}' and `\&{outer}' commands are only slightly harder. - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{protection\_command}: \37\\{do\_protection};\par -\fi - -\M1027. \P$\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}% -\S$\6 -$\\{primitive}(\.{"inner"},\39\\{protection\_command},\390)$;\6 -$\\{primitive}(\.{"outer"},\39\\{protection\_command},\391)$;\par -\fi - -\M1028. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{protection\_command}: \37\&{if} $\|m=0$ \1\&{then}\5 -$\\{print}(\.{"inner"})$\ \&{else} $\\{print}(\.{"outer"})$;\2\par -\fi - -\M1029. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_protection};\6 -\4\&{var} \37\|m: \37$0\to1$;\C{0 to unprotect, 1 to protect}\6 -\|t: \37\\{halfword};\C{the \\{eq\_type} before we change it}\2\6 -\&{begin} \37$\|m\K\\{cur\_mod}$;\6 -\1\&{repeat} \37\\{get\_symbol};\5 -$\|t\K\\{eq\_type}(\\{cur\_sym})$;\6 -\&{if} $\|m=0$ \1\&{then}\6 -\&{begin} \37\&{if} $\|t\G\\{outer\_tag}$ \1\&{then}\5 -$\\{eq\_type}(\\{cur\_sym})\K\|t-\\{outer\_tag}$;\2\6 -\&{end}\6 -\4\&{else} \&{if} $\|t<\\{outer\_tag}$ \1\&{then}\5 -$\\{eq\_type}(\\{cur\_sym})\K\|t+\\{outer\_tag}$;\2\2\6 -\\{get\_x\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$;\2\6 -\&{end};\par -\fi - -\M1030. \MF\ never defines the tokens `\.(' and `\.)' to be primitives, but -plain \MF\ begins with the declaration `\&{delimiters} \.{()}'. Such a -declaration assigns the command code \\{left\_delimiter} to `\.{(}' and -\\{right\_delimiter} to `\.{)}'; the \\{equiv} of each delimiter is the -hash address of its mate. - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{delimiters}: \37\\{def\_delims};\par -\fi - -\M1031. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{def\_delims};\6 -\4\&{var} \37$\\{l\_delim},\39\\{r\_delim}$: \37\\{pointer};\C{the new -delimiter pair}\2\6 -\&{begin} \37\\{get\_clear\_symbol};\5 -$\\{l\_delim}\K\\{cur\_sym}$;\6 -\\{get\_clear\_symbol};\5 -$\\{r\_delim}\K\\{cur\_sym}$;\6 -$\\{eq\_type}(\\{l\_delim})\K\\{left\_delimiter}$;\5 -$\\{equiv}(\\{l\_delim})\K\\{r\_delim}$;\6 -$\\{eq\_type}(\\{r\_delim})\K\\{right\_delimiter}$;\5 -$\\{equiv}(\\{r\_delim})\K\\{l\_delim}$;\6 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M1032. Here is a procedure that is called when \MF\ has reached a point -where some right delimiter is mandatory. - -\Y\P$\4\X1032:Declare the procedure called \\{check\_delimiter}\X\S$\6 -\4\&{procedure}\1\ \37$\\{check\_delimiter}(\\{l\_delim},\39\\{r\_delim}:% -\\{pointer})$;\6 -\4\&{label} \37\\{exit};\2\6 -\&{begin} \37\&{if} $\\{cur\_cmd}=\\{right\_delimiter}$ \1\&{then}\6 -\&{if} $\\{cur\_mod}=\\{l\_delim}$ \1\&{then}\5 -\&{return};\2\2\6 -\&{if} $\\{cur\_sym}\I\\{r\_delim}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\\{text}(\\{r\_delim}))$;\6 -$\\{help2}(\.{"I\ found\ no\ right\ delimiter\ to\ match\ a\ left\ one.\ So\ I% -\'ve"})$\6 -$(\.{"put\ one\ in,\ behind\ the\ scenes;\ this\ may\ fix\ the\ problem."})$;\5 -\\{back\_error};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"The\ token\ \`"})$;\5 -$\\{slow\_print}(\\{text}(\\{r\_delim}))$;\5 -$\\{print}(\.{"\'\ is\ no\ longer\ a\ right\ delimiter"})$;\5 -$\\{help3}(\.{"Strange:\ This\ token\ has\ lost\ its\ former\ meaning!"})$\6 -$(\.{"I\'ll\ read\ it\ as\ a\ right\ delimiter\ this\ time;"})$\6 -$(\.{"but\ watch\ out,\ I\'ll\ probably\ miss\ it\ later."})$;\5 -\\{error};\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\U697.\fi - -\M1033. The next four commands save or change the values associated with -tokens. - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{save\_command}: \37\1\&{repeat} \37\\{get\_symbol};\5 -$\\{save\_variable}(\\{cur\_sym})$;\5 -\\{get\_x\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$;\2\6 -\4\\{interim\_command}: \37\\{do\_interim};\6 -\4\\{let\_command}: \37\\{do\_let};\6 -\4\\{new\_internal}: \37\\{do\_new\_internal};\par -\fi - -\M1034. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_statement};\5 -\\{forward};\5 -\hbox{\2}\6 -\4\&{procedure}\1\ \37\\{do\_interim};\2\6 -\&{begin} \37\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}\I\\{internal\_quantity}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"The\ token\ \`"})$;\6 -\&{if} $\\{cur\_sym}=0$ \1\&{then}\5 -$\\{print}(\.{"(\%CAPSULE)"})$\6 -\4\&{else} $\\{slow\_print}(\\{text}(\\{cur\_sym}))$;\2\6 -$\\{print}(\.{"\'\ isn\'t\ an\ internal\ quantity"})$;\5 -$\\{help1}(\.{"Something\ like\ \`tracingonline\'\ should\ follow\ \`interim% -\'."})$;\5 -\\{back\_error};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{save\_internal}(\\{cur\_mod})$;\5 -\\{back\_input};\6 -\&{end};\2\6 -\\{do\_statement};\6 -\&{end};\par -\fi - -\M1035. The following procedure is careful not to undefine the left-hand symbol -too soon, lest commands like `{\tt let x=x}' have a surprising effect. - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_let};\6 -\4\&{var} \37\|l: \37\\{pointer};\C{hash location of the left-hand symbol}\2\6 -\&{begin} \37\\{get\_symbol};\5 -$\|l\K\\{cur\_sym}$;\5 -\\{get\_x\_next};\6 -\&{if} $\\{cur\_cmd}\I\\{equals}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}\I\\{assignment}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{"="})$;\5 -$\\{help3}(\.{"You\ should\ have\ said\ \`let\ symbol\ =\ something\'."})$\6 -$(\.{"But\ don\'t\ worry;\ I\'ll\ pretend\ that\ an\ equals\ sign"})$\6 -$(\.{"was\ present.\ The\ next\ token\ I\ read\ will\ be\ \`something\'."})$;\5 -\\{back\_error};\6 -\&{end};\2\2\6 -\\{get\_symbol};\6 -\&{case} $\\{cur\_cmd}$ \1\&{of}\6 -\4$\\{defined\_macro},\39\\{secondary\_primary\_macro},\39\\{tertiary% -\_secondary\_macro},\39\\{expression\_tertiary\_macro}$: \37$\\{add\_mac\_ref}(% -\\{cur\_mod})$;\6 -\4\&{othercases} \37\\{do\_nothing}\2\6 -\&{endcases};\6 -$\\{clear\_symbol}(\|l,\39\\{false})$;\5 -$\\{eq\_type}(\|l)\K\\{cur\_cmd}$;\6 -\&{if} $\\{cur\_cmd}=\\{tag\_token}$ \1\&{then}\5 -$\\{equiv}(\|l)\K\\{null}$\6 -\4\&{else} $\\{equiv}(\|l)\K\\{cur\_mod}$;\2\6 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M1036. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_new\_internal};\2\6 -\&{begin} \37\1\&{repeat} \37\&{if} $\\{int\_ptr}=\\{max\_internal}$ \1\&{then}% -\5 -$\\{overflow}(\.{"number\ of\ internals"},\39\\{max\_internal})$;\2\6 -\\{get\_clear\_symbol};\5 -$\\{incr}(\\{int\_ptr})$;\5 -$\\{eq\_type}(\\{cur\_sym})\K\\{internal\_quantity}$;\5 -$\\{equiv}(\\{cur\_sym})\K\\{int\_ptr}$;\5 -$\\{int\_name}[\\{int\_ptr}]\K\\{text}(\\{cur\_sym})$;\5 -$\\{internal}[\\{int\_ptr}]\K0$;\5 -\\{get\_x\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$;\2\6 -\&{end};\par -\fi - -\M1037. The various `\&{show}' commands are distinguished by modifier fields -in the usual way. - -\Y\P\D \37$\\{show\_token\_code}=0$\C{show the meaning of a single token}\par -\P\D \37$\\{show\_stats\_code}=1$\C{show current memory and string usage}\par -\P\D \37$\\{show\_code}=2$\C{show a list of expressions}\par -\P\D \37$\\{show\_var\_code}=3$\C{show a variable and its descendents}\par -\P\D \37$\\{show\_dependencies\_code}=4$\C{show dependent variables in terms of -independents}\par -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"showtoken"},\39\\{show\_command},\39\\{show\_token\_code})$;% -\6 -$\\{primitive}(\.{"showstats"},\39\\{show\_command},\39\\{show\_stats\_code})$;% -\6 -$\\{primitive}(\.{"show"},\39\\{show\_command},\39\\{show\_code})$;\6 -$\\{primitive}(\.{"showvariable"},\39\\{show\_command},\39\\{show\_var% -\_code})$;\6 -$\\{primitive}(\.{"showdependencies"},\39\\{show\_command},\39\\{show% -\_dependencies\_code})$;\par -\fi - -\M1038. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{show\_command}: \37\&{case} $\|m$ \1\&{of}\6 -\4\\{show\_token\_code}: \37$\\{print}(\.{"showtoken"})$;\6 -\4\\{show\_stats\_code}: \37$\\{print}(\.{"showstats"})$;\6 -\4\\{show\_code}: \37$\\{print}(\.{"show"})$;\6 -\4\\{show\_var\_code}: \37$\\{print}(\.{"showvariable"})$;\6 -\4\&{othercases} \37$\\{print}(\.{"showdependencies"})$\2\6 -\&{endcases};\par -\fi - -\M1039. \P$\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{show\_command}: \37\\{do\_show\_whatever};\par -\fi - -\M1040. The value of \\{cur\_mod} controls the \\{verbosity} in the \\{print% -\_exp} routine: -If it's \\{show\_code}, complicated structures are abbreviated, otherwise -they aren't. - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_show};\2\6 -\&{begin} \37\1\&{repeat} \37\\{get\_x\_next};\5 -\\{scan\_expression};\5 -$\\{print\_nl}(\.{">>\ "})$;\5 -$\\{print\_exp}(\\{null},\392)$;\5 -$\\{flush\_cur\_exp}(0)$;\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$;\2\6 -\&{end};\par -\fi - -\M1041. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{disp\_token};\2\6 -\&{begin} \37$\\{print\_nl}(\.{">\ "})$;\6 -\&{if} $\\{cur\_sym}=0$ \1\&{then}\5 -\X1042:Show a numeric or string or capsule token\X\6 -\4\&{else} \&{begin} \37$\\{slow\_print}(\\{text}(\\{cur\_sym}))$;\5 -$\\{print\_char}(\.{"="})$;\6 -\&{if} $\\{eq\_type}(\\{cur\_sym})\G\\{outer\_tag}$ \1\&{then}\5 -$\\{print}(\.{"(outer)\ "})$;\2\6 -$\\{print\_cmd\_mod}(\\{cur\_cmd},\39\\{cur\_mod})$;\6 -\&{if} $\\{cur\_cmd}=\\{defined\_macro}$ \1\&{then}\6 -\&{begin} \37\\{print\_ln};\5 -$\\{show\_macro}(\\{cur\_mod},\39\\{null},\39100000)$;\6 -\&{end};\C{this avoids recursion between \\{show\_macro} and \\{print\_cmd% -\_mod}}\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M1042. \P$\X1042:Show a numeric or string or capsule token\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_cmd}=\\{numeric\_token}$ \1\&{then}\5 -$\\{print\_scaled}(\\{cur\_mod})$\6 -\4\&{else} \&{if} $\\{cur\_cmd}=\\{capsule\_token}$ \1\&{then}\6 -\&{begin} \37$\\{g\_pointer}\K\\{cur\_mod}$;\5 -\\{print\_capsule};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{print\_char}(\.{""}\.{""})$;\5 -$\\{slow\_print}(\\{cur\_mod})$;\5 -$\\{print\_char}(\.{""}\.{""})$;\5 -$\\{delete\_str\_ref}(\\{cur\_mod})$;\6 -\&{end};\2\2\6 -\&{end}\par -\U1041.\fi - -\M1043. The following cases of \\{print\_cmd\_mod} might arise in connection -with \\{disp\_token}, although they don't correspond to any -primitive tokens. - -\Y\P$\4\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of primitives\X% -\mathrel{+}\S$\6 -\4$\\{left\_delimiter},\39\\{right\_delimiter}$: \37\&{begin} \37\&{if} $\|c=% -\\{left\_delimiter}$ \1\&{then}\5 -$\\{print}(\.{"lef"})$\6 -\4\&{else} $\\{print}(\.{"righ"})$;\2\6 -$\\{print}(\.{"t\ delimiter\ that\ matches\ "})$;\5 -$\\{slow\_print}(\\{text}(\|m))$;\6 -\&{end};\6 -\4\\{tag\_token}: \37\&{if} $\|m=\\{null}$ \1\&{then}\5 -$\\{print}(\.{"tag"})$\ \&{else} $\\{print}(\.{"variable"})$;\2\6 -\4\\{defined\_macro}: \37$\\{print}(\.{"macro:"})$;\6 -\4$\\{secondary\_primary\_macro},\39\\{tertiary\_secondary\_macro},\39% -\\{expression\_tertiary\_macro}$: \37\&{begin} \37$\\{print\_cmd\_mod}(\\{macro% -\_def},\39\|c)$;\5 -$\\{print}(\.{"\'d\ macro:"})$;\5 -\\{print\_ln};\5 -$\\{show\_token\_list}(\\{link}(\\{link}(\|m)),\39\\{null},\391000,\390)$;\6 -\&{end};\6 -\4\\{repeat\_loop}: \37$\\{print}(\.{"[repeat\ the\ loop]"})$;\6 -\4\\{internal\_quantity}: \37$\\{slow\_print}(\\{int\_name}[\|m])$;\par -\fi - -\M1044. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_show\_token};\2\6 -\&{begin} \37\1\&{repeat} \37\\{get\_next};\5 -\\{disp\_token};\5 -\\{get\_x\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$;\2\6 -\&{end};\par -\fi - -\M1045. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_show\_stats};\2\6 -\&{begin} \37$\\{print\_nl}(\.{"Memory\ usage\ "})$;\6 -\&{stat} \37$\\{print\_int}(\\{var\_used})$;\5 -$\\{print\_char}(\.{"\&"})$;\5 -$\\{print\_int}(\\{dyn\_used})$;\6 -\&{if} $\\{false}$ \1\&{then}\ \2\6 -\&{tats}\hbox{}\6 -$\\{print}(\.{"unknown"})$;\5 -$\\{print}(\.{"\ ("})$;\5 -$\\{print\_int}(\\{hi\_mem\_min}-\\{lo\_mem\_max}-1)$;\5 -$\\{print}(\.{"\ still\ untouched)"})$;\5 -\\{print\_ln};\5 -$\\{print\_nl}(\.{"String\ usage\ "})$;\5 -$\\{print\_int}(\\{str\_ptr}-\\{init\_str\_ptr})$;\5 -$\\{print\_char}(\.{"\&"})$;\5 -$\\{print\_int}(\\{pool\_ptr}-\\{init\_pool\_ptr})$;\5 -$\\{print}(\.{"\ ("})$;\5 -$\\{print\_int}(\\{max\_strings}-\\{max\_str\_ptr})$;\5 -$\\{print\_char}(\.{"\&"})$;\5 -$\\{print\_int}(\\{pool\_size}-\\{max\_pool\_ptr})$;\5 -$\\{print}(\.{"\ still\ untouched)"})$;\5 -\\{print\_ln};\5 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M1046. Here's a recursive procedure that gives an abbreviated account -of a variable, for use by \\{do\_show\_var}. - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{disp\_var}(\|p:\\{pointer})$;\6 -\4\&{var} \37\|q: \37\\{pointer};\C{traverses attributes and subscripts}\6 -\|n: \37$0\to\\{max\_print\_line}$;\C{amount of macro text to show}\2\6 -\&{begin} \37\&{if} $\\{type}(\|p)=\\{structured}$ \1\&{then}\5 -\X1047:Descend the structure\X\6 -\4\&{else} \&{if} $\\{type}(\|p)\G\\{unsuffixed\_macro}$ \1\&{then}\5 -\X1048:Display a variable macro\X\6 -\4\&{else} \&{if} $\\{type}(\|p)\I\\{undefined}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{""})$;\5 -$\\{print\_variable\_name}(\|p)$;\5 -$\\{print\_char}(\.{"="})$;\5 -$\\{print\_exp}(\|p,\390)$;\6 -\&{end};\2\2\2\6 -\&{end};\par -\fi - -\M1047. \P$\X1047:Descend the structure\X\S$\6 -\&{begin} \37$\|q\K\\{attr\_head}(\|p)$;\6 -\1\&{repeat} \37$\\{disp\_var}(\|q)$;\5 -$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\|q=\\{end\_attr}$;\2\6 -$\|q\K\\{subscr\_head}(\|p)$;\6 -\&{while} $\\{name\_type}(\|q)=\\{subscr}$ \1\&{do}\6 -\&{begin} \37$\\{disp\_var}(\|q)$;\5 -$\|q\K\\{link}(\|q)$;\6 -\&{end};\2\6 -\&{end}\par -\U1046.\fi - -\M1048. \P$\X1048:Display a variable macro\X\S$\6 -\&{begin} \37$\\{print\_nl}(\.{""})$;\5 -$\\{print\_variable\_name}(\|p)$;\6 -\&{if} $\\{type}(\|p)>\\{unsuffixed\_macro}$ \1\&{then}\5 -$\\{print}(\.{"@\#"})$;\C{\\{suffixed\_macro}}\2\6 -$\\{print}(\.{"=macro:"})$;\6 -\&{if} $\\{file\_offset}\G\\{max\_print\_line}-20$ \1\&{then}\5 -$\|n\K5$\6 -\4\&{else} $\|n\K\\{max\_print\_line}-\\{file\_offset}-15$;\2\6 -$\\{show\_macro}(\\{value}(\|p),\39\\{null},\39\|n)$;\6 -\&{end}\par -\U1046.\fi - -\M1049. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_show\_var};\6 -\4\&{label} \37\\{done};\2\6 -\&{begin} \37\1\&{repeat} \37\\{get\_next};\6 -\&{if} $\\{cur\_sym}>0$ \1\&{then}\6 -\&{if} $\\{cur\_sym}\L\\{hash\_end}$ \1\&{then}\6 -\&{if} $\\{cur\_cmd}=\\{tag\_token}$ \1\&{then}\6 -\&{if} $\\{cur\_mod}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{disp\_var}(\\{cur\_mod})$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\2\2\2\6 -\\{disp\_token};\6 -\4\\{done}: \37\\{get\_x\_next};\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$;\2\6 -\&{end};\par -\fi - -\M1050. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_show\_dependencies};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{link that runs through all dependencies}\2\6 -\&{begin} \37$\|p\K\\{link}(\\{dep\_head})$;\6 -\&{while} $\|p\I\\{dep\_head}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{interesting}(\|p)$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{""})$;\5 -$\\{print\_variable\_name}(\|p)$;\6 -\&{if} $\\{type}(\|p)=\\{dependent}$ \1\&{then}\5 -$\\{print\_char}(\.{"="})$\6 -\4\&{else} $\\{print}(\.{"\ =\ "})$;\C{extra spaces imply proto-dependency}\2\6 -$\\{print\_dependency}(\\{dep\_list}(\|p),\39\\{type}(\|p))$;\6 -\&{end};\2\6 -$\|p\K\\{dep\_list}(\|p)$;\6 -\&{while} $\\{info}(\|p)\I\\{null}$ \1\&{do}\5 -$\|p\K\\{link}(\|p)$;\2\6 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M1051. Finally we are ready for the procedure that governs all of the -show commands. - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_show\_whatever};\2\6 -\&{begin} \37\&{if} $\\{interaction}=\\{error\_stop\_mode}$ \1\&{then}\5 -\\{wake\_up\_terminal};\2\6 -\&{case} $\\{cur\_mod}$ \1\&{of}\6 -\4\\{show\_token\_code}: \37\\{do\_show\_token};\6 -\4\\{show\_stats\_code}: \37\\{do\_show\_stats};\6 -\4\\{show\_code}: \37\\{do\_show};\6 -\4\\{show\_var\_code}: \37\\{do\_show\_var};\6 -\4\\{show\_dependencies\_code}: \37\\{do\_show\_dependencies};\2\6 -\&{end};\C{there are no other cases}\6 -\&{if} $\\{internal}[\\{showstopping}]>0$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"OK"})$;\6 -\&{if} $\\{interaction}<\\{error\_stop\_mode}$ \1\&{then}\6 -\&{begin} \37\\{help0};\5 -$\\{decr}(\\{error\_count})$;\6 -\&{end}\6 -\4\&{else} $\\{help1}(\.{"This\ isn\'t\ an\ error\ message;\ I\'m\ just\ -showing\ something."})$;\2\6 -\&{if} $\\{cur\_cmd}=\\{semicolon}$ \1\&{then}\5 -\\{error}\ \&{else} \\{put\_get\_error};\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M1052. The `\&{addto}' command needs the following additional primitives: - -\Y\P\D \37$\\{drop\_code}=0$\C{command modifier for `\&{dropping}'}\par -\P\D \37$\\{keep\_code}=1$\C{command modifier for `\&{keeping}'}\par -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"contour"},\39\\{thing\_to\_add},\39\\{contour\_code})$;\6 -$\\{primitive}(\.{"doublepath"},\39\\{thing\_to\_add},\39\\{double\_path% -\_code})$;\6 -$\\{primitive}(\.{"also"},\39\\{thing\_to\_add},\39\\{also\_code})$;\6 -$\\{primitive}(\.{"withpen"},\39\\{with\_option},\39\\{pen\_type})$;\6 -$\\{primitive}(\.{"withweight"},\39\\{with\_option},\39\\{known})$;\6 -$\\{primitive}(\.{"dropping"},\39\\{cull\_op},\39\\{drop\_code})$;\6 -$\\{primitive}(\.{"keeping"},\39\\{cull\_op},\39\\{keep\_code})$;\par -\fi - -\M1053. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{thing\_to\_add}: \37\&{if} $\|m=\\{contour\_code}$ \1\&{then}\5 -$\\{print}(\.{"contour"})$\6 -\4\&{else} \&{if} $\|m=\\{double\_path\_code}$ \1\&{then}\5 -$\\{print}(\.{"doublepath"})$\6 -\4\&{else} $\\{print}(\.{"also"})$;\2\2\6 -\4\\{with\_option}: \37\&{if} $\|m=\\{pen\_type}$ \1\&{then}\5 -$\\{print}(\.{"withpen"})$\6 -\4\&{else} $\\{print}(\.{"withweight"})$;\2\6 -\4\\{cull\_op}: \37\&{if} $\|m=\\{drop\_code}$ \1\&{then}\5 -$\\{print}(\.{"dropping"})$\6 -\4\&{else} $\\{print}(\.{"keeping"})$;\2\par -\fi - -\M1054. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{function}\1\ \37\\{scan\_with}: \37\\{boolean};\6 -\4\&{var} \37\|t: \37\\{small\_number};\C{\\{known} or \\{pen\_type}}\6 -\\{result}: \37\\{boolean};\C{the value to return}\2\6 -\&{begin} \37$\|t\K\\{cur\_mod}$;\5 -$\\{cur\_type}\K\\{vacuous}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\5 -$\\{result}\K\\{false}$;\6 -\&{if} $\\{cur\_type}\I\|t$ \1\&{then}\5 -\X1055:Complain about improper type\X\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{pen\_type}$ \1\&{then}\5 -$\\{result}\K\\{true}$\6 -\4\&{else} \X1056:Check the tentative weight\X;\2\2\6 -$\\{scan\_with}\K\\{result}$;\6 -\&{end};\par -\fi - -\M1055. \P$\X1055:Complain about improper type\X\S$\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ type"})$;\5 -$\\{help2}(\.{"Next\ time\ say\ \`withweight\ <known\ numeric\ expression>% -\';"})$\6 -$(\.{"I\'ll\ ignore\ the\ bad\ \`with\'\ clause\ and\ look\ for\ another."})$;\6 -\&{if} $\|t=\\{pen\_type}$ \1\&{then}\5 -$\\{help\_line}[1]\K\.{"Next\ time\ say\ \`withpen\ <known\ pen\ expression>% -\';"}$;\2\6 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end}\par -\U1054.\fi - -\M1056. \P$\X1056:Check the tentative weight\X\S$\6 -\&{begin} \37$\\{cur\_exp}\K\\{round\_unscaled}(\\{cur\_exp})$;\6 -\&{if} $(\\{abs}(\\{cur\_exp})<4)\W(\\{cur\_exp}\I0)$ \1\&{then}\5 -$\\{result}\K\\{true}$\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Weight\ must\ be\ -3,\ -2,\ -1,\ -+1,\ +2,\ or\ +3"})$;\5 -$\\{help1}(\.{"I\'ll\ ignore\ the\ bad\ \`with\'\ clause\ and\ look\ for\ -another."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\2\6 -\&{end}\par -\U1054.\fi - -\M1057. One of the things we need to do when we've parsed an \&{addto} or -similar command is set \\{cur\_edges} to the header of a supposed \&{picture} -variable, given a token list for that variable. - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{find\_edges\_var}(\|t:\\{pointer})$;\6 -\4\&{var} \37\|p: \37\\{pointer};\2\6 -\&{begin} \37$\|p\K\\{find\_variable}(\|t)$;\5 -$\\{cur\_edges}\K\\{null}$;\6 -\&{if} $\|p=\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{obliterated}(\|t)$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} \&{if} $\\{type}(\|p)\I\\{picture\_type}$ \1\&{then}\6 -\&{begin} \37$\\{print\_err}(\.{"Variable\ "})$;\5 -$\\{show\_token\_list}(\|t,\39\\{null},\391000,\390)$;\5 -$\\{print}(\.{"\ is\ the\ wrong\ type\ ("})$;\5 -$\\{print\_type}(\\{type}(\|p))$;\5 -$\\{print\_char}(\.{")"})$;\5 -$\\{help2}(\.{"I\ was\ looking\ for\ a\ "}\.{"known"}\.{"\ picture\ -variable."})$\6 -$(\.{"So\ I\'ll\ not\ change\ anything\ just\ now."})$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} $\\{cur\_edges}\K\\{value}(\|p)$;\2\2\6 -$\\{flush\_node\_list}(\|t)$;\6 -\&{end};\par -\fi - -\M1058. \P$\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{add\_to\_command}: \37\\{do\_add\_to};\par -\fi - -\M1059. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_add\_to};\6 -\4\&{label} \37$\\{done},\39\\{not\_found}$;\6 -\4\&{var} \37$\\{lhs},\39\\{rhs}$: \37\\{pointer};\C{variable on left, path on -right}\6 -\|w: \37\\{integer};\C{tentative weight}\6 -\|p: \37\\{pointer};\C{list manipulation register}\6 -\|q: \37\\{pointer};\C{beginning of second half of doubled path}\6 -\\{add\_to\_type}: \37$\\{double\_path\_code}\to\\{also\_code}$;\C{modifier of % -\&{addto}}\2\6 -\&{begin} \37\\{get\_x\_next};\5 -$\\{var\_flag}\K\\{thing\_to\_add}$;\5 -\\{scan\_primary};\6 -\&{if} $\\{cur\_type}\I\\{token\_list}$ \1\&{then}\5 -\X1060:Abandon edges command because there's no variable\X\6 -\4\&{else} \&{begin} \37$\\{lhs}\K\\{cur\_exp}$;\5 -$\\{add\_to\_type}\K\\{cur\_mod}$;\6 -$\\{cur\_type}\K\\{vacuous}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{add\_to\_type}=\\{also\_code}$ \1\&{then}\5 -\X1061:Augment some edges by others\X\6 -\4\&{else} \X1062:Get ready to fill a contour, and fill it\X;\2\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M1060. \P$\X1060:Abandon edges command because there's no variable\X\S$\6 -\&{begin} \37$\\{exp\_err}(\.{"Not\ a\ suitable\ variable"})$;\5 -$\\{help4}(\.{"At\ this\ point\ I\ needed\ to\ see\ the\ name\ of\ a\ picture\ -variable."})$\6 -$(\.{"(Or\ perhaps\ you\ have\ indeed\ presented\ me\ with\ one;\ I\ might"})$\6 -$(\.{"have\ missed\ it,\ if\ it\ wasn\'t\ followed\ by\ the\ proper\ -token.)"})$\6 -$(\.{"So\ I\'ll\ not\ change\ anything\ just\ now."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end}\par -\Us1059, 1070, 1071\ETs1074.\fi - -\M1061. \P$\X1061:Augment some edges by others\X\S$\6 -\&{begin} \37$\\{find\_edges\_var}(\\{lhs})$;\6 -\&{if} $\\{cur\_edges}=\\{null}$ \1\&{then}\5 -$\\{flush\_cur\_exp}(0)$\6 -\4\&{else} \&{if} $\\{cur\_type}\I\\{picture\_type}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ \`addto\'"})$;\5 -$\\{help2}(\.{"This\ expression\ should\ have\ specified\ a\ known\ -picture."})$\6 -$(\.{"So\ I\'ll\ not\ change\ anything\ just\ now."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{merge\_edges}(\\{cur\_exp})$;\5 -$\\{flush\_cur\_exp}(0)$;\6 -\&{end};\2\2\6 -\&{end}\par -\U1059.\fi - -\M1062. \P$\X1062:Get ready to fill a contour, and fill it\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_type}=\\{pair\_type}$ \1\&{then}\5 -\\{pair\_to\_path};\2\6 -\&{if} $\\{cur\_type}\I\\{path\_type}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ \`addto\'"})$;\5 -$\\{help2}(\.{"This\ expression\ should\ have\ been\ a\ known\ path."})$\6 -$(\.{"So\ I\'ll\ not\ change\ anything\ just\ now."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\5 -$\\{flush\_token\_list}(\\{lhs})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{rhs}\K\\{cur\_exp}$;\5 -$\|w\K1$;\5 -$\\{cur\_pen}\K\\{null\_pen}$;\6 -\&{while} $\\{cur\_cmd}=\\{with\_option}$ \1\&{do}\6 -\&{if} $\\{scan\_with}$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\5 -$\|w\K\\{cur\_exp}$\6 -\4\&{else} \X1063:Change the tentative pen\X;\2\2\2\6 -\X1064:Complete the contour filling operation\X;\6 -$\\{delete\_pen\_ref}(\\{cur\_pen})$;\6 -\&{end};\2\6 -\&{end}\par -\U1059.\fi - -\M1063. We could say `$\\{add\_pen\_ref}(\\{cur\_pen})$; $\\{flush\_cur% -\_exp}(0)$' after changing -\\{cur\_pen} here. But that would have no effect, because the current -expression -will not be flushed. Thus we save a bit of code (at the risk of being too -tricky). - -\Y\P$\4\X1063:Change the tentative pen\X\S$\6 -\&{begin} \37$\\{delete\_pen\_ref}(\\{cur\_pen})$;\5 -$\\{cur\_pen}\K\\{cur\_exp}$;\6 -\&{end}\par -\U1062.\fi - -\M1064. \P$\X1064:Complete the contour filling operation\X\S$\6 -$\\{find\_edges\_var}(\\{lhs})$;\6 -\&{if} $\\{cur\_edges}=\\{null}$ \1\&{then}\5 -$\\{toss\_knot\_list}(\\{rhs})$\6 -\4\&{else} \&{begin} \37$\\{lhs}\K\\{null}$;\5 -$\\{cur\_path\_type}\K\\{add\_to\_type}$;\6 -\&{if} $\\{left\_type}(\\{rhs})=\\{endpoint}$ \1\&{then}\6 -\&{if} $\\{cur\_path\_type}=\\{double\_path\_code}$ \1\&{then}\5 -\X1065:Double the path\X\6 -\4\&{else} \X1067:Complain about non-cycle and \&{goto} \\{not\_found}\X\2\6 -\4\&{else} \&{if} $\\{cur\_path\_type}=\\{double\_path\_code}$ \1\&{then}\5 -$\\{lhs}\K\\{htap\_ypoc}(\\{rhs})$;\2\2\6 -$\\{cur\_wt}\K\|w$;\5 -$\\{rhs}\K\\{make\_spec}(\\{rhs},\39\\{max\_offset}(\\{cur\_pen}),\39% -\\{internal}[\\{tracing\_specs}])$;\5 -\X1068:Check the turning number\X;\6 -\&{if} $\\{max\_offset}(\\{cur\_pen})=0$ \1\&{then}\5 -$\\{fill\_spec}(\\{rhs})$\6 -\4\&{else} $\\{fill\_envelope}(\\{rhs})$;\2\6 -\&{if} $\\{lhs}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\\{rev\_turns}\K\\{true}$;\5 -$\\{lhs}\K\\{make\_spec}(\\{lhs},\39\\{max\_offset}(\\{cur\_pen}),\39% -\\{internal}[\\{tracing\_specs}])$;\5 -$\\{rev\_turns}\K\\{false}$;\6 -\&{if} $\\{max\_offset}(\\{cur\_pen})=0$ \1\&{then}\5 -$\\{fill\_spec}(\\{lhs})$\6 -\4\&{else} $\\{fill\_envelope}(\\{lhs})$;\2\6 -\&{end};\2\6 -\4\\{not\_found}: \37\&{end}\2\par -\U1062.\fi - -\M1065. \P$\X1065:Double the path\X\S$\6 -\&{if} $\\{link}(\\{rhs})=\\{rhs}$ \1\&{then}\5 -\X1066:Make a trivial one-point path cycle\X\6 -\4\&{else} \&{begin} \37$\|p\K\\{htap\_ypoc}(\\{rhs})$;\5 -$\|q\K\\{link}(\|p)$;\6 -$\\{right\_x}(\\{path\_tail})\K\\{right\_x}(\|q)$;\5 -$\\{right\_y}(\\{path\_tail})\K\\{right\_y}(\|q)$;\5 -$\\{right\_type}(\\{path\_tail})\K\\{right\_type}(\|q)$;\5 -$\\{link}(\\{path\_tail})\K\\{link}(\|q)$;\5 -$\\{free\_node}(\|q,\39\\{knot\_node\_size})$;\6 -$\\{right\_x}(\|p)\K\\{right\_x}(\\{rhs})$;\5 -$\\{right\_y}(\|p)\K\\{right\_y}(\\{rhs})$;\5 -$\\{right\_type}(\|p)\K\\{right\_type}(\\{rhs})$;\5 -$\\{link}(\|p)\K\\{link}(\\{rhs})$;\5 -$\\{free\_node}(\\{rhs},\39\\{knot\_node\_size})$;\6 -$\\{rhs}\K\|p$;\6 -\&{end}\2\par -\U1064.\fi - -\M1066. \P$\X1066:Make a trivial one-point path cycle\X\S$\6 -\&{begin} \37$\\{right\_x}(\\{rhs})\K\\{x\_coord}(\\{rhs})$;\5 -$\\{right\_y}(\\{rhs})\K\\{y\_coord}(\\{rhs})$;\5 -$\\{left\_x}(\\{rhs})\K\\{x\_coord}(\\{rhs})$;\5 -$\\{left\_y}(\\{rhs})\K\\{y\_coord}(\\{rhs})$;\5 -$\\{left\_type}(\\{rhs})\K\\{explicit}$;\5 -$\\{right\_type}(\\{rhs})\K\\{explicit}$;\6 -\&{end}\par -\U1065.\fi - -\M1067. \P$\X1067:Complain about non-cycle and \&{goto} \\{not\_found}\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Not\ a\ cycle"})$;\5 -$\\{help2}(\.{"That\ contour\ should\ have\ ended\ with\ \`..cycle\'\ or\ \`% -\&cycle\'."})$\6 -$(\.{"So\ I\'ll\ not\ change\ anything\ just\ now."})$;\5 -\\{put\_get\_error};\5 -$\\{toss\_knot\_list}(\\{rhs})$;\5 -\&{goto} \37\\{not\_found};\6 -\&{end}\par -\U1064.\fi - -\M1068. \P$\X1068:Check the turning number\X\S$\6 -\&{if} $\\{turning\_number}\L0$ \1\&{then}\6 -\&{if} $\\{cur\_path\_type}\I\\{double\_path\_code}$ \1\&{then}\6 -\&{if} $\\{internal}[\\{turning\_check}]>0$ \1\&{then}\6 -\&{if} $(\\{turning\_number}<0)\W(\\{link}(\\{cur\_pen})=\\{null})$ \1\&{then}\5 -$\\{negate}(\\{cur\_wt})$\6 -\4\&{else} \&{begin} \37\&{if} $\\{turning\_number}=0$ \1\&{then}\6 -\&{if} $(\\{internal}[\\{turning\_check}]\L\\{unity})\W(\\{link}(\\{cur\_pen})=% -\\{null})$ \1\&{then}\5 -\&{goto} \37\\{done}\6 -\4\&{else} $\\{print\_strange}(\.{"Strange\ path\ (turning\ number\ is\ -zero)"})$\2\6 -\4\&{else} $\\{print\_strange}(\.{"Backwards\ path\ (turning\ number\ is\ -negative)"})$;\2\6 -$\\{help3}(\.{"The\ path\ doesn\'t\ have\ a\ counterclockwise\ orientation,"})$% -\6 -$(\.{"so\ I\'ll\ probably\ have\ trouble\ drawing\ it."})$\6 -$(\.{"(See\ Chapter\ 27\ of\ The\ METAFONTbook\ for\ more\ help.)"})$;\5 -\\{put\_get\_error};\6 -\&{end};\2\2\2\2\6 -\4\\{done}: \37\par -\U1064.\fi - -\M1069. \P$\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{ship\_out\_command}: \37\\{do\_ship\_out};\6 -\4\\{display\_command}: \37\\{do\_display};\6 -\4\\{open\_window}: \37\\{do\_open\_window};\6 -\4\\{cull\_command}: \37\\{do\_cull};\par -\fi - -\M1070. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\hbox{\4}\X1098:Declare the function called \\{tfm\_check}\X\6 -\4\&{procedure}\1\ \37\\{do\_ship\_out};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|c: \37\\{integer};\C{the character code}\2\6 -\&{begin} \37\\{get\_x\_next};\5 -$\\{var\_flag}\K\\{semicolon}$;\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{token\_list}$ \1\&{then}\6 -\&{if} $\\{cur\_type}=\\{picture\_type}$ \1\&{then}\5 -$\\{cur\_edges}\K\\{cur\_exp}$\6 -\4\&{else} \&{begin} \37\X1060:Abandon edges command because there's no -variable\X;\6 -\&{return};\6 -\&{end}\2\6 -\4\&{else} \&{begin} \37$\\{find\_edges\_var}(\\{cur\_exp})$;\5 -$\\{cur\_type}\K\\{vacuous}$;\6 -\&{end};\2\6 -\&{if} $\\{cur\_edges}\I\\{null}$ \1\&{then}\6 -\&{begin} \37$\|c\K\\{round\_unscaled}(\\{internal}[\\{char\_code}])\mathbin{% -\&{mod}}256$;\6 -\&{if} $\|c<0$ \1\&{then}\5 -$\|c\K\|c+256$;\2\6 -\X1099:Store the width information for character code~\|c\X;\6 -\&{if} $\\{internal}[\\{proofing}]\G0$ \1\&{then}\5 -$\\{ship\_out}(\|c)$;\2\6 -\&{end};\2\6 -$\\{flush\_cur\_exp}(0)$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1071. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_display};\6 -\4\&{label} \37$\\{not\_found},\39\\{common\_ending},\39\\{exit}$;\6 -\4\&{var} \37\|e: \37\\{pointer};\C{token list for a picture variable}\2\6 -\&{begin} \37\\{get\_x\_next};\5 -$\\{var\_flag}\K\\{in\_window}$;\5 -\\{scan\_primary};\6 -\&{if} $\\{cur\_type}\I\\{token\_list}$ \1\&{then}\5 -\X1060:Abandon edges command because there's no variable\X\6 -\4\&{else} \&{begin} \37$\|e\K\\{cur\_exp}$;\5 -$\\{cur\_type}\K\\{vacuous}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -\&{goto} \37\\{common\_ending};\2\6 -$\\{cur\_exp}\K\\{round\_unscaled}(\\{cur\_exp})$;\6 -\&{if} $\\{cur\_exp}<0$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{if} $\\{cur\_exp}>15$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{if} $\R\\{window\_open}[\\{cur\_exp}]$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{find\_edges\_var}(\|e)$;\6 -\&{if} $\\{cur\_edges}\I\\{null}$ \1\&{then}\5 -$\\{disp\_edges}(\\{cur\_exp})$;\2\6 -\&{return};\6 -\4\\{not\_found}: \37$\\{cur\_exp}\K\\{cur\_exp}\ast\\{unity}$;\6 -\4\\{common\_ending}: \37$\\{exp\_err}(\.{"Bad\ window\ number"})$;\5 -$\\{help1}(\.{"It\ should\ be\ the\ number\ of\ an\ open\ window."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\5 -$\\{flush\_token\_list}(\|e)$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1072. The only thing difficult about `\&{openwindow}' is that the syntax -allows the user to go astray in many ways. The following subroutine -helps keep the necessary program reasonably short and sweet. - -\Y\P$\4\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{function}\1\ \37$\\{get\_pair}(\|c:\\{command\_code})$: \37\\{boolean};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{a pair of values that are known (we hope)}\6 -\|b: \37\\{boolean};\C{did we find such a pair?}\2\6 -\&{begin} \37\&{if} $\\{cur\_cmd}\I\|c$ \1\&{then}\5 -$\\{get\_pair}\K\\{false}$\6 -\4\&{else} \&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{nice\_pair}(\\{cur\_exp},\39\\{cur\_type})$ \1\&{then}\6 -\&{begin} \37$\|p\K\\{value}(\\{cur\_exp})$;\5 -$\\{cur\_x}\K\\{value}(\\{x\_part\_loc}(\|p))$;\5 -$\\{cur\_y}\K\\{value}(\\{y\_part\_loc}(\|p))$;\5 -$\|b\K\\{true}$;\6 -\&{end}\6 -\4\&{else} $\|b\K\\{false}$;\2\6 -$\\{flush\_cur\_exp}(0)$;\5 -$\\{get\_pair}\K\|b$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M1073. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_open\_window};\6 -\4\&{label} \37$\\{not\_found},\39\\{exit}$;\6 -\4\&{var} \37\|k: \37\\{integer};\C{the window number in question}\6 -$\\{r0},\39\\{c0},\39\\{r1},\39\\{c1}$: \37\\{scaled};\C{window coordinates}\2\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\|k\K\\{round\_unscaled}(\\{cur\_exp})$;\6 -\&{if} $\|k<0$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{if} $\|k>15$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{if} $\R\\{get\_pair}(\\{from\_token})$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{r0}\K\\{cur\_x}$;\5 -$\\{c0}\K\\{cur\_y}$;\6 -\&{if} $\R\\{get\_pair}(\\{to\_token})$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{r1}\K\\{cur\_x}$;\5 -$\\{c1}\K\\{cur\_y}$;\6 -\&{if} $\R\\{get\_pair}(\\{at\_token})$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{open\_a\_window}(\|k,\39\\{r0},\39\\{c0},\39\\{r1},\39\\{c1},\39\\{cur\_x},% -\39\\{cur\_y})$;\5 -\&{return};\6 -\4\\{not\_found}: \37$\\{print\_err}(\.{"Improper\ \`openwindow\'"})$;\5 -$\\{help2}(\.{"Say\ \`openwindow\ k\ from\ (r0,c0)\ to\ (r1,c1)\ at\ (x,y)% -\',"})$\6 -$(\.{"where\ all\ quantities\ are\ known\ and\ k\ is\ between\ 0\ and\ 15."})$;% -\5 -\\{put\_get\_error};\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1074. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_cull};\6 -\4\&{label} \37$\\{not\_found},\39\\{exit}$;\6 -\4\&{var} \37\|e: \37\\{pointer};\C{token list for a picture variable}\6 -\\{keeping}: \37$\\{drop\_code}\to\\{keep\_code}$;\C{modifier of \\{cull\_op}}\6 -$\|w,\39\\{w\_in},\39\\{w\_out}$: \37\\{integer};\C{culling weights}\2\6 -\&{begin} \37$\|w\K1$;\5 -\\{get\_x\_next};\5 -$\\{var\_flag}\K\\{cull\_op}$;\5 -\\{scan\_primary};\6 -\&{if} $\\{cur\_type}\I\\{token\_list}$ \1\&{then}\5 -\X1060:Abandon edges command because there's no variable\X\6 -\4\&{else} \&{begin} \37$\|e\K\\{cur\_exp}$;\5 -$\\{cur\_type}\K\\{vacuous}$;\5 -$\\{keeping}\K\\{cur\_mod}$;\6 -\&{if} $\R\\{get\_pair}(\\{cull\_op})$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{while} $(\\{cur\_cmd}=\\{with\_option})\W(\\{cur\_mod}=\\{known})$ \1\&{do}\6 -\&{if} $\\{scan\_with}$ \1\&{then}\5 -$\|w\K\\{cur\_exp}$;\2\2\6 -\X1075:Set up the culling weights, or \&{goto} \\{not\_found} if the thresholds -are bad\X;\6 -$\\{find\_edges\_var}(\|e)$;\6 -\&{if} $\\{cur\_edges}\I\\{null}$ \1\&{then}\5 -$\\{cull\_edges}(\\{floor\_unscaled}(\\{cur\_x}+\\{unity}-1),\39\\{floor% -\_unscaled}(\\{cur\_y}),\39\\{w\_out},\39\\{w\_in})$;\2\6 -\&{return};\6 -\4\\{not\_found}: \37$\\{print\_err}(\.{"Bad\ culling\ amounts"})$;\5 -$\\{help1}(\.{"Always\ cull\ by\ known\ amounts\ that\ exclude\ 0."})$;\5 -\\{put\_get\_error};\5 -$\\{flush\_token\_list}(\|e)$;\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1075. \P$\X1075:Set up the culling weights, or \&{goto} \\{not\_found} if the -thresholds are bad\X\S$\6 -\&{if} $\\{cur\_x}>\\{cur\_y}$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -\&{if} $\\{keeping}=\\{drop\_code}$ \1\&{then}\6 -\&{begin} \37\&{if} $(\\{cur\_x}>0)\V(\\{cur\_y}<0)$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{w\_out}\K\|w$;\5 -$\\{w\_in}\K0$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\&{if} $(\\{cur\_x}\L0)\W(\\{cur\_y}\G0)$ \1\&{then}\5 -\&{goto} \37\\{not\_found};\2\6 -$\\{w\_out}\K0$;\5 -$\\{w\_in}\K\|w$;\6 -\&{end}\2\par -\U1074.\fi - -\M1076. The \&{everyjob} command simply assigns a nonzero value to the global -variable -\\{start\_sym}. - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{every\_job\_command}: \37\&{begin} \37\\{get\_symbol};\5 -$\\{start\_sym}\K\\{cur\_sym}$;\5 -\\{get\_x\_next};\6 -\&{end};\par -\fi - -\M1077. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{start\_sym}: \37\\{halfword};\C{a symbolic token to insert at beginning of -job}\par -\fi - -\M1078. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{start\_sym}\K0$;\par -\fi - -\M1079. Finally, we have only the ``message'' commands remaining. - -\Y\P\D \37$\\{message\_code}=0$\par -\P\D \37$\\{err\_message\_code}=1$\par -\P\D \37$\\{err\_help\_code}=2$\par -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"message"},\39\\{message\_command},\39\\{message\_code})$;\6 -$\\{primitive}(\.{"errmessage"},\39\\{message\_command},\39\\{err\_message% -\_code})$;\6 -$\\{primitive}(\.{"errhelp"},\39\\{message\_command},\39\\{err\_help\_code})$;% -\par -\fi - -\M1080. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{message\_command}: \37\&{if} $\|m<\\{err\_message\_code}$ \1\&{then}\5 -$\\{print}(\.{"message"})$\6 -\4\&{else} \&{if} $\|m=\\{err\_message\_code}$ \1\&{then}\5 -$\\{print}(\.{"errmessage"})$\6 -\4\&{else} $\\{print}(\.{"errhelp"})$;\2\2\par -\fi - -\M1081. \P$\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{message\_command}: \37\\{do\_message};\par -\fi - -\M1082. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_message};\6 -\4\&{var} \37\|m: \37$\\{message\_code}\to\\{err\_help\_code}$;\C{the type of -message}\2\6 -\&{begin} \37$\|m\K\\{cur\_mod}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{string\_type}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Not\ a\ string"})$;\5 -$\\{help1}(\.{"A\ message\ should\ be\ a\ known\ string\ expression."})$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} \&{case} $\|m$ \1\&{of}\6 -\4\\{message\_code}: \37\&{begin} \37$\\{print\_nl}(\.{""})$;\5 -$\\{slow\_print}(\\{cur\_exp})$;\6 -\&{end};\6 -\4\\{err\_message\_code}: \37\X1086:Print string \\{cur\_exp} as an error -message\X;\6 -\4\\{err\_help\_code}: \37\X1083:Save string \\{cur\_exp} as the \\{err\_help}% -\X;\2\6 -\&{end};\C{there are no other cases}\2\6 -$\\{flush\_cur\_exp}(0)$;\6 -\&{end};\par -\fi - -\M1083. The global variable \\{err\_help} is zero when the user has most -recently -given an empty help string, or if none has ever been given. - -\Y\P$\4\X1083:Save string \\{cur\_exp} as the \\{err\_help}\X\S$\6 -\&{begin} \37\&{if} $\\{err\_help}\I0$ \1\&{then}\5 -$\\{delete\_str\_ref}(\\{err\_help})$;\2\6 -\&{if} $\\{length}(\\{cur\_exp})=0$ \1\&{then}\5 -$\\{err\_help}\K0$\6 -\4\&{else} \&{begin} \37$\\{err\_help}\K\\{cur\_exp}$;\5 -$\\{add\_str\_ref}(\\{err\_help})$;\6 -\&{end};\2\6 -\&{end}\par -\U1082.\fi - -\M1084. If \&{errmessage} occurs often in \\{scroll\_mode}, without -user-defined -\&{errhelp}, we don't want to give a long help message each time. So we -give a verbose explanation only once. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{long\_help\_seen}: \37\\{boolean};\C{has the long \&{errmessage} help been -used?}\par -\fi - -\M1085. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{long\_help\_seen}\K\\{false}$;\par -\fi - -\M1086. \P$\X1086:Print string \\{cur\_exp} as an error message\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{""})$;\5 -$\\{slow\_print}(\\{cur\_exp})$;\6 -\&{if} $\\{err\_help}\I0$ \1\&{then}\5 -$\\{use\_err\_help}\K\\{true}$\6 -\4\&{else} \&{if} $\\{long\_help\_seen}$ \1\&{then}\5 -$\\{help1}(\.{"(That\ was\ another\ \`errmessage\'.)"})$\6 -\4\&{else} \&{begin} \37\&{if} $\\{interaction}<\\{error\_stop\_mode}$ \1% -\&{then}\5 -$\\{long\_help\_seen}\K\\{true}$;\2\6 -$\\{help4}(\.{"This\ error\ message\ was\ generated\ by\ an\ \`errmessage\'"})$% -\6 -$(\.{"command,\ so\ I\ can\'t\ give\ any\ explicit\ help."})$\6 -$(\.{"Pretend\ that\ you\'re\ Miss\ Marple:\ Examine\ all\ clues,"})$\6 -$(\.{"and\ deduce\ the\ truth\ by\ inspired\ guesses."})$;\6 -\&{end};\2\2\6 -\\{put\_get\_error};\5 -$\\{use\_err\_help}\K\\{false}$;\6 -\&{end}\par -\U1082.\fi - -\N1087. \[45] Font metric data. -\TeX\ gets its knowledge about fonts from font metric files, also called -\.{TFM} files; the `\.T' in `\.{TFM}' stands for \TeX, -but other programs know about them too. One of \MF's duties is to -write \.{TFM} files so that the user's fonts can readily be -applied to typesetting. - -The information in a \.{TFM} file appears in a sequence of 8-bit bytes. -Since the number of bytes is always a multiple of~4, we could -also regard the file as a sequence of 32-bit words, but \MF\ uses the -byte interpretation. The format of \.{TFM} files was designed by -Lyle Ramshaw in 1980. The intent is to convey a lot of different kinds -of information in a compact but useful form. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{tfm\_file}: \37\\{byte\_file};\C{the font metric output goes here}\6 -\4\\{metric\_file\_name}: \37\\{str\_number};\C{full name of the font metric -file}\par -\fi - -\M1088. The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit -integers that give the lengths of the various subsequent portions -of the file. These twelve integers are, in order: -$$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr -\\{lf}&length of the entire file, in words;\cr -\\{lh}&length of the header data, in words;\cr -\\{bc}&smallest character code in the font;\cr -\\{ec}&largest character code in the font;\cr -\\{nw}&number of words in the width table;\cr -\\{nh}&number of words in the height table;\cr -\\{nd}&number of words in the depth table;\cr -\\{ni}&number of words in the italic correction table;\cr -\\{nl}&number of words in the lig/kern table;\cr -\\{nk}&number of words in the kern table;\cr -\\{ne}&number of words in the extensible character table;\cr -\\{np}&number of font parameter words.\cr}}$$ -They are all nonnegative and less than $2^{15}$. We must have $\\{bc}-1\L\\{ec}% -\L255$, -$\\{ne}\L256$, and -$$\hbox{$\\{lf}=6+\\{lh}+(\\{ec}-\\{bc}+1)+\\{nw}+\\{nh}+\\{nd}+\\{ni}+\\{nl}+% -\\{nk}+\\{ne}+\\{np}$.}$$ -Note that a font may contain as many as 256 characters (if $\\{bc}=0$ and $% -\\{ec}=255$), -and as few as 0 characters (if $\\{bc}=\\{ec}+1$). - -Incidentally, when two or more 8-bit bytes are combined to form an integer of -16 or more bits, the most significant bytes appear first in the file. -This is called BigEndian order. - -\fi - -\M1089. The rest of the \.{TFM} file may be regarded as a sequence of ten data -arrays having the informal specification -$$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2} -\tabskip\centering -\halign to\displaywidth{\hfil\\{#}\tabskip=0pt&$\,:\,$\arr#\hfil -\tabskip\centering\cr -header&$[0\to\\{lh}-1]\hbox{\\{stuff}}$\cr -char\_info&$[\\{bc}\to\\{ec}]\\{char\_info\_word}$\cr -width&$[0\to\\{nw}-1]\\{fix\_word}$\cr -height&$[0\to\\{nh}-1]\\{fix\_word}$\cr -depth&$[0\to\\{nd}-1]\\{fix\_word}$\cr -italic&$[0\to\\{ni}-1]\\{fix\_word}$\cr -lig\_kern&$[0\to\\{nl}-1]\\{lig\_kern\_command}$\cr -kern&$[0\to\\{nk}-1]\\{fix\_word}$\cr -exten&$[0\to\\{ne}-1]\\{extensible\_recipe}$\cr -param&$[1\to\\{np}]\\{fix\_word}$\cr}$$ -The most important data type used here is a \\{fix\_word}, which is -a 32-bit representation of a binary fraction. A \\{fix\_word} is a signed -quantity, with the two's complement of the entire word used to represent -negation. Of the 32 bits in a \\{fix\_word}, exactly 12 are to the left of the -binary point; thus, the largest \\{fix\_word} value is $2048-2^{-20}$, and -the smallest is $-2048$. We will see below, however, that all but two of -the \\{fix\_word} values must lie between $-16$ and $+16$. - -\fi - -\M1090. The first data array is a block of header information, which contains -general facts about the font. The header must contain at least two words, -$\\{header}[0]$ and $\\{header}[1]$, whose meaning is explained below. -Additional -header information of use to other software routines might also be -included, and \MF\ will generate it if the \.{headerbyte} command occurs. -For example, 16 more words of header information are in use at the Xerox -Palo Alto Research Center; the first ten specify the character coding -scheme used (e.g., `\.{XEROX TEXT}' or `\.{TEX MATHSY}'), the next five -give the font family name (e.g., `\.{HELVETICA}' or `\.{CMSY}'), and the -last gives the ``face byte.'' - -\yskip\hang$\\{header}[0]$ is a 32-bit check sum that \MF\ will copy into -the \.{GF} output file. This helps ensure consistency between files, -since \TeX\ records the check sums from the \.{TFM}'s it reads, and these -should match the check sums on actual fonts that are used. The actual -relation between this check sum and the rest of the \.{TFM} file is not -important; the check sum is simply an identification number with the -property that incompatible fonts almost always have distinct check sums. - -\yskip\hang$\\{header}[1]$ is a \\{fix\_word} containing the design size of the -font, in units of \TeX\ points. This number must be at least 1.0; it is -fairly arbitrary, but usually the design size is 10.0 for a ``10 point'' -font, i.e., a font that was designed to look best at a 10-point size, -whatever that really means. When a \TeX\ user asks for a font `\.{at} -$\delta$ \.{pt}', the effect is to override the design size and replace it -by $\delta$, and to multiply the $x$ and~$y$ coordinates of the points in -the font image by a factor of $\delta$ divided by the design size. {\sl -All other dimensions in the\/ \.{TFM} file are \\{fix\_word}\kern-1pt\ -numbers in design-size units.} Thus, for example, the value of $\\{param}[6]$, -which defines the \.{em} unit, is often the \\{fix\_word} value $2^{20}=1.0$, -since many fonts have a design size equal to one em. The other dimensions -must be less than 16 design-size units in absolute value; thus, -$\\{header}[1]$ and $\\{param}[1]$ are the only \\{fix\_word} entries in the -whole -\.{TFM} file whose first byte might be something besides 0 or 255. - -\fi - -\M1091. Next comes the \\{char\_info} array, which contains one \\{char\_info% -\_word} -per character. Each word in this part of the file contains six fields -packed into four bytes as follows. - -\yskip\hang first byte: \\{width\_index} (8 bits)\par -\hang second byte: \\{height\_index} (4 bits) times 16, plus \\{depth\_index} -(4~bits)\par -\hang third byte: \\{italic\_index} (6 bits) times 4, plus \\{tag} -(2~bits)\par -\hang fourth byte: \\{remainder} (8 bits)\par -\yskip\noindent -The actual width of a character is \\{width}$[\\{width\_index}]$, in -design-size -units; this is a device for compressing information, since many characters -have the same width. Since it is quite common for many characters -to have the same height, depth, or italic correction, the \.{TFM} format -imposes a limit of 16 different heights, 16 different depths, and -64 different italic corrections. - -Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]= -\\{italic}[0]=0$ should always hold, so that an index of zero implies a -value of zero. The \\{width\_index} should never be zero unless the -character does not exist in the font, since a character is valid if and -only if it lies between \\{bc} and \\{ec} and has a nonzero \\{width\_index}. - -\fi - -\M1092. The \\{tag} field in a \\{char\_info\_word} has four values that -explain how to -interpret the \\{remainder} field. - -\def\hangg#1 {\hang\hbox{#1 }} -\yskip\hangg$\\{tag}=0$ (\\{no\_tag}) means that \\{remainder} is unused.\par -\hangg$\\{tag}=1$ (\\{lig\_tag}) means that this character has a -ligature/kerning -program starting at location \\{remainder} in the \\{lig\_kern} array.\par -\hangg$\\{tag}=2$ (\\{list\_tag}) means that this character is part of a chain -of -characters of ascending sizes, and not the largest in the chain. The -\\{remainder} field gives the character code of the next larger character.\par -\hangg$\\{tag}=3$ (\\{ext\_tag}) means that this character code represents an -extensible character, i.e., a character that is built up of smaller pieces -so that it can be made arbitrarily large. The pieces are specified in -$\\{exten}[\\{remainder}]$.\par -\yskip\noindent -Characters with $\\{tag}=2$ and $\\{tag}=3$ are treated as characters with $% -\\{tag}=0$ -unless they are used in special circumstances in math formulas. For example, -\TeX's \.{\\sum} operation looks for a \\{list\_tag}, and the \.{\\left} -operation looks for both \\{list\_tag} and \\{ext\_tag}. - -\Y\P\D \37$\\{no\_tag}=0$\C{vanilla character}\par -\P\D \37$\\{lig\_tag}=1$\C{character has a ligature/kerning program}\par -\P\D \37$\\{list\_tag}=2$\C{character has a successor in a charlist}\par -\P\D \37$\\{ext\_tag}=3$\C{character is extensible}\par -\fi - -\M1093. The \\{lig\_kern} array contains instructions in a simple programming -language -that explains what to do for special letter pairs. Each word in this array is a -\\{lig\_kern\_command} of four bytes. - -\yskip\hang first byte: \\{skip\_byte}, indicates that this is the final -program -step if the byte is 128 or more, otherwise the next step is obtained by -skipping this number of intervening steps.\par -\hang second byte: \\{next\_char}, ``if \\{next\_char} follows the current -character, -then perform the operation and stop, otherwise continue.''\par -\hang third byte: \\{op\_byte}, indicates a ligature step if less than~128, -a kern step otherwise.\par -\hang fourth byte: \\{remainder}.\par -\yskip\noindent -In a kern step, an -additional space equal to $\\{kern}[256\ast(\\{op\_byte}-128)+\\{remainder}]$ -is inserted -between the current character and \\{next\_char}. This amount is -often negative, so that the characters are brought closer together -by kerning; but it might be positive. - -There are eight kinds of ligature steps, having \\{op\_byte} codes $4a+2b+c$ -where -$0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is -\\{remainder} is inserted between the current character and \\{next\_char}; -then the current character is deleted if $b=0$, and \\{next\_char} is -deleted if $c=0$; then we pass over $a$~characters to reach the next -current character (which may have a ligature/kerning program of its own). - -If the very first instruction of the \\{lig\_kern} array has $\\{skip% -\_byte}=255$, -the \\{next\_char} byte is the so-called right boundary character of this font; -the value of \\{next\_char} need not lie between \\{bc} and~\\{ec}. -If the very last instruction of the \\{lig\_kern} array has $\\{skip% -\_byte}=255$, -there is a special ligature/kerning program for a left boundary character, -beginning at location $256\ast\\{op\_byte}+\\{remainder}$. -The interpretation is that \TeX\ puts implicit boundary characters -before and after each consecutive string of characters from the same font. -These implicit characters do not appear in the output, but they can affect -ligatures and kerning. - -If the very first instruction of a character's \\{lig\_kern} program has -$\\{skip\_byte}>128$, the program actually begins in location -$256\ast\\{op\_byte}+\\{remainder}$. This feature allows access to large \\{lig% -\_kern} -arrays, because the first instruction must otherwise -appear in a location $\L255$. - -Any instruction with $\\{skip\_byte}>128$ in the \\{lig\_kern} array must -satisfy -the condition -$$\hbox{$256\ast\\{op\_byte}+\\{remainder}<\\{nl}$.}$$ -If such an instruction is encountered during -normal program execution, it denotes an unconditional halt; no ligature -command is performed. - -\Y\P\D \37$\\{stop\_flag}=128+\\{min\_quarterword}$\C{value indicating `% -\.{STOP}' in a lig/kern program}\par -\P\D \37$\\{kern\_flag}=128+\\{min\_quarterword}$\C{op code for a kern step}\par -\P\D \37$\\{skip\_byte}(\#)\S\\{lig\_kern}[\#].\\{b0}$\par -\P\D \37$\\{next\_char}(\#)\S\\{lig\_kern}[\#].\\{b1}$\par -\P\D \37$\\{op\_byte}(\#)\S\\{lig\_kern}[\#].\\{b2}$\par -\P\D \37$\\{rem\_byte}(\#)\S\\{lig\_kern}[\#].\\{b3}$\par -\fi - -\M1094. Extensible characters are specified by an \\{extensible\_recipe}, which -consists of four bytes called \\{top}, \\{mid}, \\{bot}, and \\{rep} (in this -order). These bytes are the character codes of individual pieces used to -build up a large symbol. If \\{top}, \\{mid}, or \\{bot} are zero, they are -not -present in the built-up result. For example, an extensible vertical line is -like an extensible bracket, except that the top and bottom pieces are missing. - -Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box -if the piece isn't present. Then the extensible characters have the form -$TR^kMR^kB$ from top to bottom, for some $\|k\G0$, unless $M$ is absent; -in the latter case we can have $TR^kB$ for both even and odd values of~\|k. -The width of the extensible character is the width of $R$; and the -height-plus-depth is the sum of the individual height-plus-depths of the -components used, since the pieces are butted together in a vertical list. - -\Y\P\D \37$\\{ext\_top}(\#)\S\\{exten}[\#].\\{b0}$\C{\\{top} piece in a recipe}% -\par -\P\D \37$\\{ext\_mid}(\#)\S\\{exten}[\#].\\{b1}$\C{\\{mid} piece in a recipe}% -\par -\P\D \37$\\{ext\_bot}(\#)\S\\{exten}[\#].\\{b2}$\C{\\{bot} piece in a recipe}% -\par -\P\D \37$\\{ext\_rep}(\#)\S\\{exten}[\#].\\{b3}$\C{\\{rep} piece in a recipe}% -\par -\fi - -\M1095. The final portion of a \.{TFM} file is the \\{param} array, which is -another -sequence of \\{fix\_word} values. - -\yskip\hang$\\{param}[1]=\\{slant}$ is the amount of italic slant, which is -used -to help position accents. For example, $\\{slant}=.25$ means that when you go -up one unit, you also go .25 units to the right. The \\{slant} is a pure -number; it is the only \\{fix\_word} other than the design size itself that is -not scaled by the design size. - -\hang$\\{param}[2]=\\{space}$ is the normal spacing between words in text. -Note that character \O{40} in the font need not have anything to do with -blank spaces. - -\hang$\\{param}[3]=\\{space\_stretch}$ is the amount of glue stretching between -words. - -\hang$\\{param}[4]=\\{space\_shrink}$ is the amount of glue shrinking between -words. - -\hang$\\{param}[5]=\\{x\_height}$ is the size of one ex in the font; it is also -the height of letters for which accents don't have to be raised or lowered. - -\hang$\\{param}[6]=\\{quad}$ is the size of one em in the font. - -\hang$\\{param}[7]=\\{extra\_space}$ is the amount added to $\\{param}[2]$ at -the -ends of sentences. - -\yskip\noindent -If fewer than seven parameters are present, \TeX\ sets the missing parameters -to zero. - -\Y\P\D \37$\\{slant\_code}=1$\par -\P\D \37$\\{space\_code}=2$\par -\P\D \37$\\{space\_stretch\_code}=3$\par -\P\D \37$\\{space\_shrink\_code}=4$\par -\P\D \37$\\{x\_height\_code}=5$\par -\P\D \37$\\{quad\_code}=6$\par -\P\D \37$\\{extra\_space\_code}=7$\par -\fi - -\M1096. So that is what \.{TFM} files hold. One of \MF's duties is to output -such -information, and it does this all at once at the end of a job. -In order to prepare for such frenetic activity, it squirrels away the -necessary facts in various arrays as information becomes available. - -Character dimensions (\&{charwd}, \&{charht}, \&{chardp}, and \&{charic}) -are stored respectively in \\{tfm\_width}, \\{tfm\_height}, \\{tfm\_depth}, and -\\{tfm\_ital\_corr}. Other information about a character (e.g., about -its ligatures or successors) is accessible via the \\{char\_tag} and -\\{char\_remainder} arrays. Other information about the font as a whole -is kept in additional arrays called \\{header\_byte}, \\{lig\_kern}, -\\{kern}, \\{exten}, and \\{param}. - -\Y\P\D \37$\\{undefined\_label}\S\\{lig\_table\_size}$\C{an undefined local -label}\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{bc},\39\\{ec}$: \37\\{eight\_bits};\C{smallest and largest character -codes shipped out}\6 -\4\\{tfm\_width}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{scaled};\C{\&{charwd} values}\2\6 -\4\\{tfm\_height}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{scaled};\C{\&{charht} values}\2\6 -\4\\{tfm\_depth}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{scaled};\C{\&{chardp} values}\2\6 -\4\\{tfm\_ital\_corr}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{scaled};\C{\&{charic} values}\2\6 -\4\\{char\_exists}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{boolean};\C{has this code been shipped out?}\2\6 -\4\\{char\_tag}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -$\\{no\_tag}\to\\{ext\_tag}$;\C{\\{remainder} category}\2\6 -\4\\{char\_remainder}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -$0\to\\{lig\_table\_size}$;\C{the \\{remainder} byte}\2\6 -\4\\{header\_byte}: \37\&{array} $[1\to\\{header\_size}]$ \1\&{of}\5 -$-1\to255$;\C{bytes of the \.{TFM} header, or $-1$ if unset}\2\6 -\4\\{lig\_kern}: \37\&{array} $[0\to\\{lig\_table\_size}]$ \1\&{of}\5 -\\{four\_quarters};\C{the ligature/kern table}\2\6 -\4\\{nl}: \37$0\to32767-256$;\C{the number of ligature/kern steps so far}\6 -\4\\{kern}: \37\&{array} $[0\to\\{max\_kerns}]$ \1\&{of}\5 -\\{scaled};\C{distinct kerning amounts}\2\6 -\4\\{nk}: \37$0\to\\{max\_kerns}$;\C{the number of distinct kerns so far}\6 -\4\\{exten}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{four\_quarters};\C{extensible character recipes}\2\6 -\4\\{ne}: \37$0\to256$;\C{the number of extensible characters so far}\6 -\4\\{param}: \37\&{array} $[1\to\\{max\_font\_dimen}]$ \1\&{of}\5 -\\{scaled};\C{\&{fontinfo} parameters}\2\6 -\4\\{np}: \37$0\to\\{max\_font\_dimen}$;\C{the largest \&{fontinfo} parameter -specified so far}\6 -\4$\\{nw},\39\\{nh},\39\\{nd},\39\\{ni}$: \37$0\to256$;\C{sizes of \.{TFM} -subtables}\6 -\4\\{skip\_table}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -$0\to\\{lig\_table\_size}$;\C{local label status}\2\6 -\4\\{lk\_started}: \37\\{boolean};\C{has there been a lig/kern step in this -command yet?}\6 -\4\\{bchar}: \37\\{integer};\C{right boundary character}\6 -\4\\{bch\_label}: \37$0\to\\{lig\_table\_size}$;\C{left boundary starting -location}\6 -\4$\\{ll},\39\\{lll}$: \37$0\to\\{lig\_table\_size}$;\C{registers used for -lig/kern processing}\6 -\4\\{label\_loc}: \37\&{array} $[0\to256]$ \1\&{of}\5 -$-1\to\\{lig\_table\_size}$;\C{lig/kern starting addresses}\2\6 -\4\\{label\_char}: \37\&{array} $[1\to256]$ \1\&{of}\5 -\\{eight\_bits};\C{characters for \\{label\_loc}}\2\6 -\4\\{label\_ptr}: \37$0\to256$;\C{highest position occupied in \\{label\_loc}}% -\par -\fi - -\M1097. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -\&{for} $\|k\K0\mathrel{\&{to}}255$ \1\&{do}\6 -\&{begin} \37$\\{tfm\_width}[\|k]\K0$;\5 -$\\{tfm\_height}[\|k]\K0$;\5 -$\\{tfm\_depth}[\|k]\K0$;\5 -$\\{tfm\_ital\_corr}[\|k]\K0$;\5 -$\\{char\_exists}[\|k]\K\\{false}$;\5 -$\\{char\_tag}[\|k]\K\\{no\_tag}$;\5 -$\\{char\_remainder}[\|k]\K0$;\5 -$\\{skip\_table}[\|k]\K\\{undefined\_label}$;\6 -\&{end};\2\6 -\&{for} $\|k\K1\mathrel{\&{to}}\\{header\_size}$ \1\&{do}\5 -$\\{header\_byte}[\|k]\K-1$;\2\6 -$\\{bc}\K255$;\5 -$\\{ec}\K0$;\5 -$\\{nl}\K0$;\5 -$\\{nk}\K0$;\5 -$\\{ne}\K0$;\5 -$\\{np}\K0$;\6 -$\\{internal}[\\{boundary\_char}]\K-\\{unity}$;\5 -$\\{bch\_label}\K\\{undefined\_label}$;\6 -$\\{label\_loc}[0]\K-1$;\5 -$\\{label\_ptr}\K0$;\par -\fi - -\M1098. \P$\X1098:Declare the function called \\{tfm\_check}\X\S$\6 -\4\&{function}\1\ \37$\\{tfm\_check}(\|m:\\{small\_number})$: \37\\{scaled};\2% -\6 -\&{begin} \37\&{if} $\\{abs}(\\{internal}[\|m])\G\\{fraction\_half}$ \1\&{then}% -\6 -\&{begin} \37$\\{print\_err}(\.{"Enormous\ "})$;\5 -$\\{print}(\\{int\_name}[\|m])$;\5 -$\\{print}(\.{"\ has\ been\ reduced"})$;\5 -$\\{help1}(\.{"Font\ metric\ dimensions\ must\ be\ less\ than\ 2048pt."})$;\5 -\\{put\_get\_error};\6 -\&{if} $\\{internal}[\|m]>0$ \1\&{then}\5 -$\\{tfm\_check}\K\\{fraction\_half}-1$\6 -\4\&{else} $\\{tfm\_check}\K1-\\{fraction\_half}$;\2\6 -\&{end}\6 -\4\&{else} $\\{tfm\_check}\K\\{internal}[\|m]$;\2\6 -\&{end};\par -\U1070.\fi - -\M1099. \P$\X1099:Store the width information for character code~\|c\X\S$\6 -\&{if} $\|c<\\{bc}$ \1\&{then}\5 -$\\{bc}\K\|c$;\2\6 -\&{if} $\|c>\\{ec}$ \1\&{then}\5 -$\\{ec}\K\|c$;\2\6 -$\\{char\_exists}[\|c]\K\\{true}$;\5 -$\\{gf\_dx}[\|c]\K\\{internal}[\\{char\_dx}]$;\5 -$\\{gf\_dy}[\|c]\K\\{internal}[\\{char\_dy}]$;\5 -$\\{tfm\_width}[\|c]\K\\{tfm\_check}(\\{char\_wd})$;\5 -$\\{tfm\_height}[\|c]\K\\{tfm\_check}(\\{char\_ht})$;\5 -$\\{tfm\_depth}[\|c]\K\\{tfm\_check}(\\{char\_dp})$;\5 -$\\{tfm\_ital\_corr}[\|c]\K\\{tfm\_check}(\\{char\_ic})$\par -\U1070.\fi - -\M1100. Now let's consider \MF's special \.{TFM}-oriented commands. - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{tfm\_command}: \37\\{do\_tfm\_command};\par -\fi - -\M1101. \P\D \37$\\{char\_list\_code}=0$\par -\P\D \37$\\{lig\_table\_code}=1$\par -\P\D \37$\\{extensible\_code}=2$\par -\P\D \37$\\{header\_byte\_code}=3$\par -\P\D \37$\\{font\_dimen\_code}=4$\par -\Y\P$\4\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}\S$\6 -$\\{primitive}(\.{"charlist"},\39\\{tfm\_command},\39\\{char\_list\_code})$;\6 -$\\{primitive}(\.{"ligtable"},\39\\{tfm\_command},\39\\{lig\_table\_code})$;\6 -$\\{primitive}(\.{"extensible"},\39\\{tfm\_command},\39\\{extensible\_code})$;\6 -$\\{primitive}(\.{"headerbyte"},\39\\{tfm\_command},\39\\{header\_byte% -\_code})$;\6 -$\\{primitive}(\.{"fontdimen"},\39\\{tfm\_command},\39\\{font\_dimen\_code})$;% -\par -\fi - -\M1102. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{tfm\_command}: \37\&{case} $\|m$ \1\&{of}\6 -\4\\{char\_list\_code}: \37$\\{print}(\.{"charlist"})$;\6 -\4\\{lig\_table\_code}: \37$\\{print}(\.{"ligtable"})$;\6 -\4\\{extensible\_code}: \37$\\{print}(\.{"extensible"})$;\6 -\4\\{header\_byte\_code}: \37$\\{print}(\.{"headerbyte"})$;\6 -\4\&{othercases} \37$\\{print}(\.{"fontdimen"})$\2\6 -\&{endcases};\par -\fi - -\M1103. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{function}\1\ \37\\{get\_code}: \37\\{eight\_bits};\C{scans a character -code value}\6 -\4\&{label} \37\\{found};\6 -\4\&{var} \37\|c: \37\\{integer};\C{the code value found}\2\6 -\&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}=\\{known}$ \1\&{then}\6 -\&{begin} \37$\|c\K\\{round\_unscaled}(\\{cur\_exp})$;\6 -\&{if} $\|c\G0$ \1\&{then}\6 -\&{if} $\|c<256$ \1\&{then}\5 -\&{goto} \37\\{found};\2\2\6 -\&{end}\6 -\4\&{else} \&{if} $\\{cur\_type}=\\{string\_type}$ \1\&{then}\6 -\&{if} $\\{length}(\\{cur\_exp})=1$ \1\&{then}\6 -\&{begin} \37$\|c\K\\{so}(\\{str\_pool}[\\{str\_start}[\\{cur\_exp}]])$;\5 -\&{goto} \37\\{found};\6 -\&{end};\2\2\2\6 -$\\{exp\_err}(\.{"Invalid\ code\ has\ been\ replaced\ by\ 0"})$;\5 -$\\{help2}(\.{"I\ was\ looking\ for\ a\ number\ between\ 0\ and\ 255,\ or\ for\ -a"})$\6 -$(\.{"string\ of\ length\ 1.\ Didn\'t\ find\ it;\ will\ use\ 0\ instead."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\5 -$\|c\K0$;\6 -\4\\{found}: \37$\\{get\_code}\K\|c$;\6 -\&{end};\par -\fi - -\M1104. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{set\_tag}(\|c:\\{halfword};\,\35\|t:\\{small% -\_number};\,\35\|r:\\{halfword})$;\2\6 -\&{begin} \37\&{if} $\\{char\_tag}[\|c]=\\{no\_tag}$ \1\&{then}\6 -\&{begin} \37$\\{char\_tag}[\|c]\K\|t$;\5 -$\\{char\_remainder}[\|c]\K\|r$;\6 -\&{if} $\|t=\\{lig\_tag}$ \1\&{then}\6 -\&{begin} \37$\\{incr}(\\{label\_ptr})$;\5 -$\\{label\_loc}[\\{label\_ptr}]\K\|r$;\5 -$\\{label\_char}[\\{label\_ptr}]\K\|c$;\6 -\&{end};\2\6 -\&{end}\6 -\4\&{else} \X1105:Complain about a character tag conflict\X;\2\6 -\&{end};\par -\fi - -\M1105. \P$\X1105:Complain about a character tag conflict\X\S$\6 -\&{begin} \37$\\{print\_err}(\.{"Character\ "})$;\6 -\&{if} $(\|c>\.{"\ "})\W(\|c<127)$ \1\&{then}\5 -$\\{print}(\|c)$\6 -\4\&{else} \&{if} $\|c=256$ \1\&{then}\5 -$\\{print}(\.{"||"})$\6 -\4\&{else} \&{begin} \37$\\{print}(\.{"code\ "})$;\5 -$\\{print\_int}(\|c)$;\6 -\&{end};\2\2\6 -$\\{print}(\.{"\ is\ already\ "})$;\6 -\&{case} $\\{char\_tag}[\|c]$ \1\&{of}\6 -\4\\{lig\_tag}: \37$\\{print}(\.{"in\ a\ ligtable"})$;\6 -\4\\{list\_tag}: \37$\\{print}(\.{"in\ a\ charlist"})$;\6 -\4\\{ext\_tag}: \37$\\{print}(\.{"extensible"})$;\2\6 -\&{end};\C{there are no other cases}\6 -$\\{help2}(\.{"It\'s\ not\ legal\ to\ label\ a\ character\ more\ than\ -once."})$\6 -$(\.{"So\ I\'ll\ not\ change\ anything\ just\ now."})$;\5 -\\{put\_get\_error};\6 -\&{end}\par -\U1104.\fi - -\M1106. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_tfm\_command};\6 -\4\&{label} \37$\\{continue},\39\\{done}$;\6 -\4\&{var} \37$\|c,\39\\{cc}$: \37$0\to256$;\C{character codes}\6 -\|k: \37$0\to\\{max\_kerns}$;\C{index into the \\{kern} array}\6 -\|j: \37\\{integer};\C{index into \\{header\_byte} or \\{param}}\2\6 -\&{begin} \37\&{case} $\\{cur\_mod}$ \1\&{of}\6 -\4\\{char\_list\_code}: \37\&{begin} \37$\|c\K\\{get\_code}$;\C{we will store a -list of character successors}\6 -\&{while} $\\{cur\_cmd}=\\{colon}$ \1\&{do}\6 -\&{begin} \37$\\{cc}\K\\{get\_code}$;\5 -$\\{set\_tag}(\|c,\39\\{list\_tag},\39\\{cc})$;\5 -$\|c\K\\{cc}$;\6 -\&{end};\2\6 -\&{end};\6 -\4\\{lig\_table\_code}: \37\X1107:Store a list of ligature/kern steps\X;\6 -\4\\{extensible\_code}: \37\X1113:Define an extensible recipe\X;\6 -\4$\\{header\_byte\_code},\39\\{font\_dimen\_code}$: \37\&{begin} \37$\|c\K% -\\{cur\_mod}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $(\\{cur\_type}\I\\{known})\V(\\{cur\_exp}<\\{half\_unit})$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ location"})$;\5 -$\\{help2}(\.{"I\ was\ looking\ for\ a\ known,\ positive\ number."})$\6 -$(\.{"For\ safety\'s\ sake\ I\'ll\ ignore\ the\ present\ command."})$;\5 -\\{put\_get\_error};\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\|j\K\\{round\_unscaled}(\\{cur\_exp})$;\6 -\&{if} $\\{cur\_cmd}\I\\{colon}$ \1\&{then}\6 -\&{begin} \37$\\{missing\_err}(\.{":"})$;\5 -$\\{help1}(\.{"A\ colon\ should\ follow\ a\ headerbyte\ or\ fontinfo\ -location."})$;\5 -\\{back\_error};\6 -\&{end};\2\6 -\&{if} $\|c=\\{header\_byte\_code}$ \1\&{then}\5 -\X1114:Store a list of header bytes\X\6 -\4\&{else} \X1115:Store a list of font dimensions\X;\2\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\C{there are no other cases}\6 -\&{end};\par -\fi - -\M1107. \P$\X1107:Store a list of ligature/kern steps\X\S$\6 -\&{begin} \37$\\{lk\_started}\K\\{false}$;\6 -\4\\{continue}: \37\\{get\_x\_next};\6 -\&{if} $(\\{cur\_cmd}=\\{skip\_to})\W\\{lk\_started}$ \1\&{then}\5 -\X1110:Process a \\{skip\_to} command and \&{goto} \\{done}\X;\2\6 -\&{if} $\\{cur\_cmd}=\\{bchar\_label}$ \1\&{then}\6 -\&{begin} \37$\|c\K256$;\5 -$\\{cur\_cmd}\K\\{colon}$;\ \&{end}\6 -\4\&{else} \&{begin} \37\\{back\_input};\5 -$\|c\K\\{get\_code}$;\ \&{end};\2\6 -\&{if} $(\\{cur\_cmd}=\\{colon})\V(\\{cur\_cmd}=\\{double\_colon})$ \1\&{then}\5 -\X1111:Record a label in a lig/kern subprogram and \&{goto} \\{continue}\X;\2\6 -\&{if} $\\{cur\_cmd}=\\{lig\_kern\_token}$ \1\&{then}\5 -\X1112:Compile a ligature/kern command\X\6 -\4\&{else} \&{begin} \37$\\{print\_err}(\.{"Illegal\ ligtable\ step"})$;\5 -$\\{help1}(\.{"I\ was\ looking\ for\ \`=:\'\ or\ \`kern\'\ here."})$;\5 -\\{back\_error};\5 -$\\{next\_char}(\\{nl})\K\\{qi}(0)$;\5 -$\\{op\_byte}(\\{nl})\K\\{qi}(0)$;\5 -$\\{rem\_byte}(\\{nl})\K\\{qi}(0)$;\6 -$\\{skip\_byte}(\\{nl})\K\\{stop\_flag}+1$;\C{this specifies an unconditional -stop}\6 -\&{end};\2\6 -\&{if} $\\{nl}=\\{lig\_table\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"ligtable\ size"},\39\\{lig\_table\_size})$;\2\6 -$\\{incr}(\\{nl})$;\6 -\&{if} $\\{cur\_cmd}=\\{comma}$ \1\&{then}\5 -\&{goto} \37\\{continue};\2\6 -\&{if} $\\{skip\_byte}(\\{nl}-1)<\\{stop\_flag}$ \1\&{then}\5 -$\\{skip\_byte}(\\{nl}-1)\K\\{stop\_flag}$;\2\6 -\4\\{done}: \37\&{end}\par -\U1106.\fi - -\M1108. \P$\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}% -\S$\6 -$\\{primitive}(\.{"=:"},\39\\{lig\_kern\_token},\390)$;\5 -$\\{primitive}(\.{"=:|"},\39\\{lig\_kern\_token},\391)$;\5 -$\\{primitive}(\.{"=:|>"},\39\\{lig\_kern\_token},\395)$;\5 -$\\{primitive}(\.{"|=:"},\39\\{lig\_kern\_token},\392)$;\5 -$\\{primitive}(\.{"|=:>"},\39\\{lig\_kern\_token},\396)$;\5 -$\\{primitive}(\.{"|=:|"},\39\\{lig\_kern\_token},\393)$;\5 -$\\{primitive}(\.{"|=:|>"},\39\\{lig\_kern\_token},\397)$;\5 -$\\{primitive}(\.{"|=:|>>"},\39\\{lig\_kern\_token},\3911)$;\5 -$\\{primitive}(\.{"kern"},\39\\{lig\_kern\_token},\39128)$;\par -\fi - -\M1109. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{lig\_kern\_token}: \37\&{case} $\|m$ \1\&{of}\6 -\40: \37$\\{print}(\.{"=:"})$;\6 -\41: \37$\\{print}(\.{"=:|"})$;\6 -\42: \37$\\{print}(\.{"|=:"})$;\6 -\43: \37$\\{print}(\.{"|=:|"})$;\6 -\45: \37$\\{print}(\.{"=:|>"})$;\6 -\46: \37$\\{print}(\.{"|=:>"})$;\6 -\47: \37$\\{print}(\.{"|=:|>"})$;\6 -\411: \37$\\{print}(\.{"|=:|>>"})$;\6 -\4\&{othercases} \37$\\{print}(\.{"kern"})$\2\6 -\&{endcases};\par -\fi - -\M1110. 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. - -\Y\P\D \37$\\{cancel\_skips}(\#)\S\\{ll}\K\#$;\6 -\1\&{repeat} \37$\\{lll}\K\\{qo}(\\{skip\_byte}(\\{ll}))$;\5 -$\\{skip\_byte}(\\{ll})\K\\{stop\_flag}$;\5 -$\\{ll}\K\\{ll}-\\{lll}$;\6 -\4\&{until}\5 -$\\{lll}=0$\2\par -\P\D \37$\\{skip\_error}(\#)\S$\1\6 -\&{begin} \37$\\{print\_err}(\.{"Too\ far\ to\ skip"})$;\5 -$\\{help1}(\.{"At\ most\ 127\ lig/kern\ steps\ can\ separate\ skipto1\ from\ -1::."})$;\5 -\\{error};\5 -$\\{cancel\_skips}(\#)$;\6 -\&{end}\2\par -\Y\P$\4\X1110:Process a \\{skip\_to} command and \&{goto} \\{done}\X\S$\6 -\&{begin} \37$\|c\K\\{get\_code}$;\6 -\&{if} $\\{nl}-\\{skip\_table}[\|c]>128$ \1\&{then}\C{$\\{skip\_table}[\|c]<<% -\\{nl}\L\\{undefined\_label}$}\6 -\&{begin} \37$\\{skip\_error}(\\{skip\_table}[\|c])$;\5 -$\\{skip\_table}[\|c]\K\\{undefined\_label}$;\6 -\&{end};\2\6 -\&{if} $\\{skip\_table}[\|c]=\\{undefined\_label}$ \1\&{then}\5 -$\\{skip\_byte}(\\{nl}-1)\K\\{qi}(0)$\6 -\4\&{else} $\\{skip\_byte}(\\{nl}-1)\K\\{qi}(\\{nl}-\\{skip\_table}[\|c]-1)$;\2% -\6 -$\\{skip\_table}[\|c]\K\\{nl}-1$;\5 -\&{goto} \37\\{done};\6 -\&{end}\par -\U1107.\fi - -\M1111. \P$\X1111:Record a label in a lig/kern subprogram and \&{goto} % -\\{continue}\X\S$\6 -\&{begin} \37\&{if} $\\{cur\_cmd}=\\{colon}$ \1\&{then}\6 -\&{if} $\|c=256$ \1\&{then}\5 -$\\{bch\_label}\K\\{nl}$\6 -\4\&{else} $\\{set\_tag}(\|c,\39\\{lig\_tag},\39\\{nl})$\2\6 -\4\&{else} \&{if} $\\{skip\_table}[\|c]<\\{undefined\_label}$ \1\&{then}\6 -\&{begin} \37$\\{ll}\K\\{skip\_table}[\|c]$;\5 -$\\{skip\_table}[\|c]\K\\{undefined\_label}$;\6 -\1\&{repeat} \37$\\{lll}\K\\{qo}(\\{skip\_byte}(\\{ll}))$;\6 -\&{if} $\\{nl}-\\{ll}>128$ \1\&{then}\6 -\&{begin} \37$\\{skip\_error}(\\{ll})$;\5 -\&{goto} \37\\{continue};\6 -\&{end};\2\6 -$\\{skip\_byte}(\\{ll})\K\\{qi}(\\{nl}-\\{ll}-1)$;\5 -$\\{ll}\K\\{ll}-\\{lll}$;\6 -\4\&{until}\5 -$\\{lll}=0$;\2\6 -\&{end};\2\2\6 -\&{goto} \37\\{continue};\6 -\&{end}\par -\U1107.\fi - -\M1112. \P$\X1112:Compile a ligature/kern command\X\S$\6 -\&{begin} \37$\\{next\_char}(\\{nl})\K\\{qi}(\|c)$;\5 -$\\{skip\_byte}(\\{nl})\K\\{qi}(0)$;\6 -\&{if} $\\{cur\_mod}<128$ \1\&{then}\C{ligature op}\6 -\&{begin} \37$\\{op\_byte}(\\{nl})\K\\{qi}(\\{cur\_mod})$;\5 -$\\{rem\_byte}(\\{nl})\K\\{qi}(\\{get\_code})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ kern"})$;\5 -$\\{help2}(\.{"The\ amount\ of\ kern\ should\ be\ a\ known\ numeric\ value."})$% -\6 -$(\.{"I\'m\ zeroing\ this\ one.\ Proceed,\ with\ fingers\ crossed."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\2\6 -$\\{kern}[\\{nk}]\K\\{cur\_exp}$;\5 -$\|k\K0$;\ \&{while} $\\{kern}[\|k]\I\\{cur\_exp}$ \1\&{do}\5 -$\\{incr}(\|k)$;\2\6 -\&{if} $\|k=\\{nk}$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{nk}=\\{max\_kerns}$ \1\&{then}\5 -$\\{overflow}(\.{"kern"},\39\\{max\_kerns})$;\2\6 -$\\{incr}(\\{nk})$;\6 -\&{end};\2\6 -$\\{op\_byte}(\\{nl})\K\\{kern\_flag}+(\|k\mathbin{\&{div}}256)$;\5 -$\\{rem\_byte}(\\{nl})\K\\{qi}((\|k\mathbin{\&{mod}}256))$;\6 -\&{end};\2\6 -$\\{lk\_started}\K\\{true}$;\6 -\&{end}\par -\U1107.\fi - -\M1113. \P\D \37$\\{missing\_extensible\_punctuation}(\#)\S$\1\6 -\&{begin} \37$\\{missing\_err}(\#)$;\5 -$\\{help1}(\.{"I\'m\ processing\ \`extensible\ c:\ t,m,b,r\'."})$;\5 -\\{back\_error};\6 -\&{end}\2\par -\Y\P$\4\X1113:Define an extensible recipe\X\S$\6 -\&{begin} \37\&{if} $\\{ne}=256$ \1\&{then}\5 -$\\{overflow}(\.{"extensible"},\39256)$;\2\6 -$\|c\K\\{get\_code}$;\5 -$\\{set\_tag}(\|c,\39\\{ext\_tag},\39\\{ne})$;\6 -\&{if} $\\{cur\_cmd}\I\\{colon}$ \1\&{then}\5 -$\\{missing\_extensible\_punctuation}(\.{":"})$;\2\6 -$\\{ext\_top}(\\{ne})\K\\{qi}(\\{get\_code})$;\6 -\&{if} $\\{cur\_cmd}\I\\{comma}$ \1\&{then}\5 -$\\{missing\_extensible\_punctuation}(\.{","})$;\2\6 -$\\{ext\_mid}(\\{ne})\K\\{qi}(\\{get\_code})$;\6 -\&{if} $\\{cur\_cmd}\I\\{comma}$ \1\&{then}\5 -$\\{missing\_extensible\_punctuation}(\.{","})$;\2\6 -$\\{ext\_bot}(\\{ne})\K\\{qi}(\\{get\_code})$;\6 -\&{if} $\\{cur\_cmd}\I\\{comma}$ \1\&{then}\5 -$\\{missing\_extensible\_punctuation}(\.{","})$;\2\6 -$\\{ext\_rep}(\\{ne})\K\\{qi}(\\{get\_code})$;\5 -$\\{incr}(\\{ne})$;\6 -\&{end}\par -\U1106.\fi - -\M1114. \P$\X1114:Store a list of header bytes\X\S$\6 -\1\&{repeat} \37\&{if} $\|j>\\{header\_size}$ \1\&{then}\5 -$\\{overflow}(\.{"headerbyte"},\39\\{header\_size})$;\2\6 -$\\{header\_byte}[\|j]\K\\{get\_code}$;\5 -$\\{incr}(\|j)$;\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$\2\par -\U1106.\fi - -\M1115. \P$\X1115:Store a list of font dimensions\X\S$\6 -\1\&{repeat} \37\&{if} $\|j>\\{max\_font\_dimen}$ \1\&{then}\5 -$\\{overflow}(\.{"fontdimen"},\39\\{max\_font\_dimen})$;\2\6 -\&{while} $\|j>\\{np}$ \1\&{do}\6 -\&{begin} \37$\\{incr}(\\{np})$;\5 -$\\{param}[\\{np}]\K0$;\6 -\&{end};\2\6 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{cur\_type}\I\\{known}$ \1\&{then}\6 -\&{begin} \37$\\{exp\_err}(\.{"Improper\ font\ parameter"})$;\5 -$\\{help1}(\.{"I\'m\ zeroing\ this\ one.\ Proceed,\ with\ fingers\ -crossed."})$;\5 -$\\{put\_get\_flush\_error}(0)$;\6 -\&{end};\2\6 -$\\{param}[\|j]\K\\{cur\_exp}$;\5 -$\\{incr}(\|j)$;\6 -\4\&{until}\5 -$\\{cur\_cmd}\I\\{comma}$\2\par -\U1106.\fi - -\M1116. OK: We've stored all the data that is needed for the \.{TFM} file. -All that remains is to output it in the correct format. - -An interesting problem needs to be solved in this connection, because -the \.{TFM} format allows at most 256~widths, 16~heights, 16~depths, -and 64~italic corrections. If the data has more distinct values than -this, we want to meet the necessary restrictions by perturbing the -given values as little as possible. - -\MF\ solves this problem in two steps. First the values of a given -kind (widths, heights, depths, or italic corrections) are sorted; -then the list of sorted values is perturbed, if necessary. - -The sorting operation is facilitated by having a special node of -essentially infinite \\{value} at the end of the current list. - -\Y\P$\4\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}\S$\6 -$\\{value}(\\{inf\_val})\K\\{fraction\_four}$;\par -\fi - -\M1117. Straight linear insertion is good enough for sorting, since the lists -are usually not terribly long. As we work on the data, the current list -will start at $\\{link}(\\{temp\_head})$ and end at \\{inf\_val}; the nodes in -this -list will be in increasing order of their \\{value} fields. - -Given such a list, the \\{sort\_in} function takes a value and returns a -pointer -to where that value can be found in the list. The value is inserted in -the proper place, if necessary. - -At the time we need to do these operations, most of \MF's work has been -completed, so we will have plenty of memory to play with. The value nodes -that are allocated for sorting will never be returned to free storage. - -\Y\P\D \37$\\{clear\_the\_list}\S\\{link}(\\{temp\_head})\K\\{inf\_val}$\par -\Y\P\4\&{function}\1\ \37$\\{sort\_in}(\|v:\\{scaled})$: \37\\{pointer};\6 -\4\&{label} \37\\{found};\6 -\4\&{var} \37$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{list manipulation -registers}\2\6 -\&{begin} \37$\|p\K\\{temp\_head}$;\6 -\~ \1\&{loop}\ \&{begin} \37$\|q\K\\{link}(\|p)$;\6 -\&{if} $\|v\L\\{value}(\|q)$ \1\&{then}\5 -\&{goto} \37\\{found};\2\6 -$\|p\K\|q$;\6 -\&{end};\2\6 -\4\\{found}: \37\&{if} $\|v<\\{value}(\|q)$ \1\&{then}\6 -\&{begin} \37$\|r\K\\{get\_node}(\\{value\_node\_size})$;\5 -$\\{value}(\|r)\K\|v$;\5 -$\\{link}(\|r)\K\|q$;\5 -$\\{link}(\|p)\K\|r$;\6 -\&{end};\2\6 -$\\{sort\_in}\K\\{link}(\|p)$;\6 -\&{end};\par -\fi - -\M1118. Now we come to the interesting part, where we reduce the list if -necessary -until it has the required size. The \\{min\_cover} routine is basic to this -process; it computes the minimum number~\|m such that the values of the -current sorted list can be covered by \|m~intervals of width~\|d. It -also sets the global value \\{perturbation} to the smallest value $d'>d$ -such that the covering found by this algorithm would be different. - -In particular, $\\{min\_cover}(0)$ returns the number of distinct values in the -current list and sets \\{perturbation} to the minimum distance between -adjacent values. - -\Y\P\4\&{function}\1\ \37$\\{min\_cover}(\|d:\\{scaled})$: \37\\{integer};\6 -\4\&{var} \37\|p: \37\\{pointer};\C{runs through the current list}\6 -\|l: \37\\{scaled};\C{the least element covered by the current interval}\6 -\|m: \37\\{integer};\C{lower bound on the size of the minimum cover}\2\6 -\&{begin} \37$\|m\K0$;\5 -$\|p\K\\{link}(\\{temp\_head})$;\5 -$\\{perturbation}\K\\{el\_gordo}$;\6 -\&{while} $\|p\I\\{inf\_val}$ \1\&{do}\6 -\&{begin} \37$\\{incr}(\|m)$;\5 -$\|l\K\\{value}(\|p)$;\6 -\1\&{repeat} \37$\|p\K\\{link}(\|p)$;\6 -\4\&{until}\5 -$\\{value}(\|p)>\|l+\|d$;\2\6 -\&{if} $\\{value}(\|p)-\|l<\\{perturbation}$ \1\&{then}\5 -$\\{perturbation}\K\\{value}(\|p)-\|l$;\2\6 -\&{end};\2\6 -$\\{min\_cover}\K\|m$;\6 -\&{end};\par -\fi - -\M1119. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{perturbation}: \37\\{scaled};\C{quantity related to \.{TFM} rounding}\6 -\4\\{excess}: \37\\{integer};\C{the list is this much too long}\par -\fi - -\M1120. The smallest \|d such that a given list can be covered with \|m -intervals -is determined by the \\{threshold} routine, which is sort of an inverse -to \\{min\_cover}. The idea is to increase the interval size rapidly until -finding the range, then to go sequentially until the exact borderline has -been discovered. - -\Y\P\4\&{function}\1\ \37$\\{threshold}(\|m:\\{integer})$: \37\\{scaled};\6 -\4\&{var} \37\|d: \37\\{scaled};\C{lower bound on the smallest interval size}\2% -\6 -\&{begin} \37$\\{excess}\K\\{min\_cover}(0)-\|m$;\6 -\&{if} $\\{excess}\L0$ \1\&{then}\5 -$\\{threshold}\K0$\6 -\4\&{else} \&{begin} \37\1\&{repeat} \37$\|d\K\\{perturbation}$;\6 -\4\&{until}\5 -$\\{min\_cover}(\|d+\|d)\L\|m$;\2\6 -\&{while} $\\{min\_cover}(\|d)>\|m$ \1\&{do}\5 -$\|d\K\\{perturbation}$;\2\6 -$\\{threshold}\K\|d$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M1121. The \\{skimp} procedure reduces the current list to at most \|m -entries, -by changing values if necessary. It also sets $\\{info}(\|p)\K\|k$ if $% -\\{value}(\|p)$ -is the \|kth distinct value on the resulting list, and it sets -\\{perturbation} to the maximum amount by which a \\{value} field has -been changed. The size of the resulting list is returned as the -value of \\{skimp}. - -\Y\P\4\&{function}\1\ \37$\\{skimp}(\|m:\\{integer})$: \37\\{integer};\6 -\4\&{var} \37\|d: \37\\{scaled};\C{the size of intervals being coalesced}\6 -$\|p,\39\|q,\39\|r$: \37\\{pointer};\C{list manipulation registers}\6 -\|l: \37\\{scaled};\C{the least value in the current interval}\6 -\|v: \37\\{scaled};\C{a compromise value}\2\6 -\&{begin} \37$\|d\K\\{threshold}(\|m)$;\5 -$\\{perturbation}\K0$;\5 -$\|q\K\\{temp\_head}$;\5 -$\|m\K0$;\5 -$\|p\K\\{link}(\\{temp\_head})$;\6 -\&{while} $\|p\I\\{inf\_val}$ \1\&{do}\6 -\&{begin} \37$\\{incr}(\|m)$;\5 -$\|l\K\\{value}(\|p)$;\5 -$\\{info}(\|p)\K\|m$;\6 -\&{if} $\\{value}(\\{link}(\|p))\L\|l+\|d$ \1\&{then}\5 -\X1122:Replace an interval of values by its midpoint\X;\2\6 -$\|q\K\|p$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\\{skimp}\K\|m$;\6 -\&{end};\par -\fi - -\M1122. \P$\X1122:Replace an interval of values by its midpoint\X\S$\6 -\&{begin} \37\1\&{repeat} \37$\|p\K\\{link}(\|p)$;\5 -$\\{info}(\|p)\K\|m$;\5 -$\\{decr}(\\{excess})$;\ \&{if} $\\{excess}=0$ \1\&{then}\5 -$\|d\K0$;\2\6 -\4\&{until}\5 -$\\{value}(\\{link}(\|p))>\|l+\|d$;\2\6 -$\|v\K\|l+\\{half}(\\{value}(\|p)-\|l)$;\6 -\&{if} $\\{value}(\|p)-\|v>\\{perturbation}$ \1\&{then}\5 -$\\{perturbation}\K\\{value}(\|p)-\|v$;\2\6 -$\|r\K\|q$;\6 -\1\&{repeat} \37$\|r\K\\{link}(\|r)$;\5 -$\\{value}(\|r)\K\|v$;\6 -\4\&{until}\5 -$\|r=\|p$;\2\6 -$\\{link}(\|q)\K\|p$;\C{remove duplicate values from the current list}\6 -\&{end}\par -\U1121.\fi - -\M1123. A warning message is issued whenever something is perturbed by -more than 1/16\thinspace pt. - -\Y\P\4\&{procedure}\1\ \37$\\{tfm\_warning}(\|m:\\{small\_number})$;\2\6 -\&{begin} \37$\\{print\_nl}(\.{"(some\ "})$;\5 -$\\{print}(\\{int\_name}[\|m])$;\5 -$\\{print}(\.{"\ values\ had\ to\ be\ adjusted\ by\ as\ much\ as\ "})$;\5 -$\\{print\_scaled}(\\{perturbation})$;\5 -$\\{print}(\.{"pt)"})$;\6 -\&{end};\par -\fi - -\M1124. Here's an example of how we use these routines. -The width data needs to be perturbed only if there are 256 distinct -widths, but \MF\ must check for this case even though it is -highly unusual. - -An integer variable \|k will be defined when we use this code. -The \\{dimen\_head} array will contain pointers to the sorted -lists of dimensions. - -\Y\P$\4\X1124:Massage the \.{TFM} widths\X\S$\6 -\\{clear\_the\_list};\6 -\&{for} $\|k\K\\{bc}\mathrel{\&{to}}\\{ec}$ \1\&{do}\6 -\&{if} $\\{char\_exists}[\|k]$ \1\&{then}\5 -$\\{tfm\_width}[\|k]\K\\{sort\_in}(\\{tfm\_width}[\|k])$;\2\2\6 -$\\{nw}\K\\{skimp}(255)+1$;\5 -$\\{dimen\_head}[1]\K\\{link}(\\{temp\_head})$;\6 -\&{if} $\\{perturbation}\G\O{10000}$ \1\&{then}\5 -$\\{tfm\_warning}(\\{char\_wd})$\2\par -\U1206.\fi - -\M1125. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{dimen\_head}: \37\&{array} $[1\to4]$ \1\&{of}\5 -\\{pointer};\C{lists of \.{TFM} dimensions}\2\par -\fi - -\M1126. Heights, depths, and italic corrections are different from widths -not only because their list length is more severely restricted, but -also because zero values do not need to be put into the lists. - -\Y\P$\4\X1126:Massage the \.{TFM} heights, depths, and italic corrections\X\S$\6 -\\{clear\_the\_list};\6 -\&{for} $\|k\K\\{bc}\mathrel{\&{to}}\\{ec}$ \1\&{do}\6 -\&{if} $\\{char\_exists}[\|k]$ \1\&{then}\6 -\&{if} $\\{tfm\_height}[\|k]=0$ \1\&{then}\5 -$\\{tfm\_height}[\|k]\K\\{zero\_val}$\6 -\4\&{else} $\\{tfm\_height}[\|k]\K\\{sort\_in}(\\{tfm\_height}[\|k])$;\2\2\2\6 -$\\{nh}\K\\{skimp}(15)+1$;\5 -$\\{dimen\_head}[2]\K\\{link}(\\{temp\_head})$;\6 -\&{if} $\\{perturbation}\G\O{10000}$ \1\&{then}\5 -$\\{tfm\_warning}(\\{char\_ht})$;\2\6 -\\{clear\_the\_list};\6 -\&{for} $\|k\K\\{bc}\mathrel{\&{to}}\\{ec}$ \1\&{do}\6 -\&{if} $\\{char\_exists}[\|k]$ \1\&{then}\6 -\&{if} $\\{tfm\_depth}[\|k]=0$ \1\&{then}\5 -$\\{tfm\_depth}[\|k]\K\\{zero\_val}$\6 -\4\&{else} $\\{tfm\_depth}[\|k]\K\\{sort\_in}(\\{tfm\_depth}[\|k])$;\2\2\2\6 -$\\{nd}\K\\{skimp}(15)+1$;\5 -$\\{dimen\_head}[3]\K\\{link}(\\{temp\_head})$;\6 -\&{if} $\\{perturbation}\G\O{10000}$ \1\&{then}\5 -$\\{tfm\_warning}(\\{char\_dp})$;\2\6 -\\{clear\_the\_list};\6 -\&{for} $\|k\K\\{bc}\mathrel{\&{to}}\\{ec}$ \1\&{do}\6 -\&{if} $\\{char\_exists}[\|k]$ \1\&{then}\6 -\&{if} $\\{tfm\_ital\_corr}[\|k]=0$ \1\&{then}\5 -$\\{tfm\_ital\_corr}[\|k]\K\\{zero\_val}$\6 -\4\&{else} $\\{tfm\_ital\_corr}[\|k]\K\\{sort\_in}(\\{tfm\_ital\_corr}[\|k])$;% -\2\2\2\6 -$\\{ni}\K\\{skimp}(63)+1$;\5 -$\\{dimen\_head}[4]\K\\{link}(\\{temp\_head})$;\6 -\&{if} $\\{perturbation}\G\O{10000}$ \1\&{then}\5 -$\\{tfm\_warning}(\\{char\_ic})$\2\par -\U1206.\fi - -\M1127. \P$\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}% -\S$\6 -$\\{value}(\\{zero\_val})\K0$;\5 -$\\{info}(\\{zero\_val})\K0$;\par -\fi - -\M1128. Bytes 5--8 of the header are set to the design size, unless the user -has -some crazy reason for specifying them differently. - -Error messages are not allowed at the time this procedure is called, -so a warning is printed instead. - -The value of \\{max\_tfm\_dimen} is calculated so that -$$\hbox{$\\{make\_scaled}(16\ast\\{max\_tfm\_dimen},\\{internal}[\\{design% -\_size}])$} -< \\{three\_bytes}.$$ - -\Y\P\D \37$\\{three\_bytes}\S\O{100000000}$\C{$2^{24}$}\par -\Y\P\4\&{procedure}\1\ \37\\{fix\_design\_size};\6 -\4\&{var} \37\|d: \37\\{scaled};\C{the design size}\2\6 -\&{begin} \37$\|d\K\\{internal}[\\{design\_size}]$;\6 -\&{if} $(\|d<\\{unity})\V(\|d\G\\{fraction\_half})$ \1\&{then}\6 -\&{begin} \37\&{if} $\|d\I0$ \1\&{then}\5 -$\\{print\_nl}(\.{"(illegal\ design\ size\ has\ been\ changed\ to\ 128pt)"})$;% -\2\6 -$\|d\K\O{40000000}$;\5 -$\\{internal}[\\{design\_size}]\K\|d$;\6 -\&{end};\2\6 -\&{if} $\\{header\_byte}[5]<0$ \1\&{then}\6 -\&{if} $\\{header\_byte}[6]<0$ \1\&{then}\6 -\&{if} $\\{header\_byte}[7]<0$ \1\&{then}\6 -\&{if} $\\{header\_byte}[8]<0$ \1\&{then}\6 -\&{begin} \37$\\{header\_byte}[5]\K\|d\mathbin{\&{div}}\O{4000000}$;\5 -$\\{header\_byte}[6]\K(\|d\mathbin{\&{div}}4096)\mathbin{\&{mod}}256$;\5 -$\\{header\_byte}[7]\K(\|d\mathbin{\&{div}}16)\mathbin{\&{mod}}256$;\5 -$\\{header\_byte}[8]\K(\|d\mathbin{\&{mod}}16)\ast16$;\6 -\&{end};\2\2\2\2\6 -$\\{max\_tfm\_dimen}\K16\ast\\{internal}[\\{design\_size}]-\\{internal}[% -\\{design\_size}]\mathbin{\&{div}}\O{10000000}$;\6 -\&{if} $\\{max\_tfm\_dimen}\G\\{fraction\_half}$ \1\&{then}\5 -$\\{max\_tfm\_dimen}\K\\{fraction\_half}-1$;\2\6 -\&{end};\par -\fi - -\M1129. The \\{dimen\_out} procedure computes a \\{fix\_word} relative to the -design size. If the data was out of range, it is corrected and the -global variable \\{tfm\_changed} is increased by~one. - -\Y\P\4\&{function}\1\ \37$\\{dimen\_out}(\|x:\\{scaled})$: \37\\{integer};\2\6 -\&{begin} \37\&{if} $\\{abs}(\|x)>\\{max\_tfm\_dimen}$ \1\&{then}\6 -\&{begin} \37$\\{incr}(\\{tfm\_changed})$;\6 -\&{if} $\|x>0$ \1\&{then}\5 -$\|x\K\\{three\_bytes}-1$\ \&{else} $\|x\K1-\\{three\_bytes}$;\2\6 -\&{end}\6 -\4\&{else} $\|x\K\\{make\_scaled}(\|x\ast16,\39\\{internal}[\\{design% -\_size}])$;\2\6 -$\\{dimen\_out}\K\|x$;\6 -\&{end};\par -\fi - -\M1130. \P$\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{max\_tfm\_dimen}: \37\\{scaled};\C{bound on widths, heights, kerns, etc.}\6 -\4\\{tfm\_changed}: \37\\{integer};\C{the number of data entries that were out -of bounds}\par -\fi - -\M1131. If the user has not specified any of the first four header bytes, -the \\{fix\_check\_sum} procedure replaces them by a ``check sum'' computed -from the \\{tfm\_width} data relative to the design size. - -\Y\P\4\&{procedure}\1\ \37\\{fix\_check\_sum};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|k: \37\\{eight\_bits};\C{runs through character codes}\6 -$\\{b1},\39\\{b2},\39\\{b3},\39\\{b4}$: \37\\{eight\_bits};\C{bytes of the -check sum}\6 -\|x: \37\\{integer};\C{hash value used in check sum computation}\2\6 -\&{begin} \37\&{if} $\\{header\_byte}[1]<0$ \1\&{then}\6 -\&{if} $\\{header\_byte}[2]<0$ \1\&{then}\6 -\&{if} $\\{header\_byte}[3]<0$ \1\&{then}\6 -\&{if} $\\{header\_byte}[4]<0$ \1\&{then}\6 -\&{begin} \37\X1132:Compute a check sum in $(\\{b1},\\{b2},\\{b3},\\{b4})$\X;\6 -$\\{header\_byte}[1]\K\\{b1}$;\5 -$\\{header\_byte}[2]\K\\{b2}$;\5 -$\\{header\_byte}[3]\K\\{b3}$;\5 -$\\{header\_byte}[4]\K\\{b4}$;\5 -\&{return};\6 -\&{end};\2\2\2\2\6 -\&{for} $\|k\K1\mathrel{\&{to}}4$ \1\&{do}\6 -\&{if} $\\{header\_byte}[\|k]<0$ \1\&{then}\5 -$\\{header\_byte}[\|k]\K0$;\2\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1132. \P$\X1132:Compute a check sum in $(\\{b1},\\{b2},\\{b3},\\{b4})$\X\S$\6 -$\\{b1}\K\\{bc}$;\5 -$\\{b2}\K\\{ec}$;\5 -$\\{b3}\K\\{bc}$;\5 -$\\{b4}\K\\{ec}$;\5 -$\\{tfm\_changed}\K0$;\6 -\&{for} $\|k\K\\{bc}\mathrel{\&{to}}\\{ec}$ \1\&{do}\6 -\&{if} $\\{char\_exists}[\|k]$ \1\&{then}\6 -\&{begin} \37$\|x\K\\{dimen\_out}(\\{value}(\\{tfm\_width}[\|k]))+(\|k+4)\ast% -\O{20000000}$;\C{this is positive}\6 -$\\{b1}\K(\\{b1}+\\{b1}+\|x)\mathbin{\&{mod}}255$;\5 -$\\{b2}\K(\\{b2}+\\{b2}+\|x)\mathbin{\&{mod}}253$;\5 -$\\{b3}\K(\\{b3}+\\{b3}+\|x)\mathbin{\&{mod}}251$;\5 -$\\{b4}\K(\\{b4}+\\{b4}+\|x)\mathbin{\&{mod}}247$;\6 -\&{end}\2\2\par -\U1131.\fi - -\M1133. Finally we're ready to actually write the \.{TFM} information. -Here are some utility routines for this purpose. - -\Y\P\D \37$\\{tfm\_out}(\#)\S\\{write}(\\{tfm\_file},\39\#)$\C{output one byte -to \\{tfm\_file}}\par -\Y\P\4\&{procedure}\1\ \37$\\{tfm\_two}(\|x:\\{integer})$;\C{output two bytes -to \\{tfm\_file}}\2\6 -\&{begin} \37$\\{tfm\_out}(\|x\mathbin{\&{div}}256)$;\5 -$\\{tfm\_out}(\|x\mathbin{\&{mod}}256)$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{tfm\_four}(\|x:\\{integer})$;\C{output four bytes to -\\{tfm\_file}}\2\6 -\&{begin} \37\&{if} $\|x\G0$ \1\&{then}\5 -$\\{tfm\_out}(\|x\mathbin{\&{div}}\\{three\_bytes})$\6 -\4\&{else} \&{begin} \37$\|x\K\|x+\O{10000000000}$;\C{use two's complement for -negative values}\6 -$\|x\K\|x+\O{10000000000}$;\5 -$\\{tfm\_out}((\|x\mathbin{\&{div}}\\{three\_bytes})+128)$;\6 -\&{end};\2\6 -$\|x\K\|x\mathbin{\&{mod}}\\{three\_bytes}$;\5 -$\\{tfm\_out}(\|x\mathbin{\&{div}}\\{unity})$;\5 -$\|x\K\|x\mathbin{\&{mod}}\\{unity}$;\5 -$\\{tfm\_out}(\|x\mathbin{\&{div}}\O{400})$;\5 -$\\{tfm\_out}(\|x\mathbin{\&{mod}}\O{400})$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{tfm\_qqqq}(\|x:\\{four\_quarters})$;\C{output four -quarterwords to \\{tfm\_file}}\2\6 -\&{begin} \37$\\{tfm\_out}(\\{qo}(\|x.\\{b0}))$;\5 -$\\{tfm\_out}(\\{qo}(\|x.\\{b1}))$;\5 -$\\{tfm\_out}(\\{qo}(\|x.\\{b2}))$;\5 -$\\{tfm\_out}(\\{qo}(\|x.\\{b3}))$;\6 -\&{end};\par -\fi - -\M1134. \P$\X1134:Finish the \.{TFM} file\X\S$\6 -\&{if} $\\{job\_name}=0$ \1\&{then}\5 -\\{open\_log\_file};\2\6 -$\\{pack\_job\_name}(\.{".tfm"})$;\6 -\&{while} $\R\\{b\_open\_out}(\\{tfm\_file})$ \1\&{do}\5 -$\\{prompt\_file\_name}(\.{"file\ name\ for\ font\ metrics"},\39\.{".tfm"})$;\2% -\6 -$\\{metric\_file\_name}\K\\{b\_make\_name\_string}(\\{tfm\_file})$;\5 -\X1135:Output the subfile sizes and header bytes\X;\6 -\X1136:Output the character information bytes, then output the dimensions -themselves\X;\6 -\X1139:Output the ligature/kern program\X;\6 -\X1140:Output the extensible character recipes and the font metric parameters% -\X;\6 -\&{stat} \37\&{if} $\\{internal}[\\{tracing\_stats}]>0$ \1\&{then}\5 -\X1141:Log the subfile sizes of the \.{TFM} file\X;\2\ \&{tats}\6 -$\\{print\_nl}(\.{"Font\ metrics\ written\ on\ "})$;\5 -$\\{slow\_print}(\\{metric\_file\_name})$;\5 -$\\{print\_char}(\.{"."})$;\5 -$\\{b\_close}(\\{tfm\_file})$\par -\U1206.\fi - -\M1135. Integer variables \\{lh}, \|k, and \\{lk\_offset} will be defined when -we use -this code. - -\Y\P$\4\X1135:Output the subfile sizes and header bytes\X\S$\6 -$\|k\K\\{header\_size}$;\6 -\&{while} $\\{header\_byte}[\|k]<0$ \1\&{do}\5 -$\\{decr}(\|k)$;\2\6 -$\\{lh}\K(\|k+3)\mathbin{\&{div}}4$;\C{this is the number of header words}\6 -\&{if} $\\{bc}>\\{ec}$ \1\&{then}\5 -$\\{bc}\K1$;\C{if there are no characters, $\\{ec}=0$ and $\\{bc}=1$}\2\6 -\X1137:Compute the ligature/kern program offset and implant the left boundary -label\X;\6 -$\\{tfm\_two}(6+\\{lh}+(\\{ec}-\\{bc}+1)+\\{nw}+\\{nh}+\\{nd}+\\{ni}+\\{nl}+% -\\{lk\_offset}+\\{nk}+\\{ne}+\\{np})$;\C{this is the total number of file words -that will be output}\6 -$\\{tfm\_two}(\\{lh})$;\5 -$\\{tfm\_two}(\\{bc})$;\5 -$\\{tfm\_two}(\\{ec})$;\5 -$\\{tfm\_two}(\\{nw})$;\5 -$\\{tfm\_two}(\\{nh})$;\5 -$\\{tfm\_two}(\\{nd})$;\5 -$\\{tfm\_two}(\\{ni})$;\5 -$\\{tfm\_two}(\\{nl}+\\{lk\_offset})$;\5 -$\\{tfm\_two}(\\{nk})$;\5 -$\\{tfm\_two}(\\{ne})$;\5 -$\\{tfm\_two}(\\{np})$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}4\ast\\{lh}$ \1\&{do}\6 -\&{begin} \37\&{if} $\\{header\_byte}[\|k]<0$ \1\&{then}\5 -$\\{header\_byte}[\|k]\K0$;\2\6 -$\\{tfm\_out}(\\{header\_byte}[\|k])$;\6 -\&{end}\2\par -\U1134.\fi - -\M1136. \P$\X1136:Output the character information bytes, then output the -dimensions themselves\X\S$\6 -\&{for} $\|k\K\\{bc}\mathrel{\&{to}}\\{ec}$ \1\&{do}\6 -\&{if} $\R\\{char\_exists}[\|k]$ \1\&{then}\5 -$\\{tfm\_four}(0)$\6 -\4\&{else} \&{begin} \37$\\{tfm\_out}(\\{info}(\\{tfm\_width}[\|k]))$;\C{the -width index}\6 -$\\{tfm\_out}((\\{info}(\\{tfm\_height}[\|k]))\ast16+\\{info}(\\{tfm\_depth}[% -\|k]))$;\5 -$\\{tfm\_out}((\\{info}(\\{tfm\_ital\_corr}[\|k]))\ast4+\\{char\_tag}[\|k])$;\5 -$\\{tfm\_out}(\\{char\_remainder}[\|k])$;\6 -\&{end};\2\2\6 -$\\{tfm\_changed}\K0$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}4$ \1\&{do}\6 -\&{begin} \37$\\{tfm\_four}(0)$;\5 -$\|p\K\\{dimen\_head}[\|k]$;\6 -\&{while} $\|p\I\\{inf\_val}$ \1\&{do}\6 -\&{begin} \37$\\{tfm\_four}(\\{dimen\_out}(\\{value}(\|p)))$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -\&{end}\2\par -\U1134.\fi - -\M1137. 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 addresses; we have $-1=\\{label\_loc}[0]<\\{label\_loc}[1]\le\cdots -\le\\{label\_loc}[\\{label\_ptr} ] $. - -\Y\P$\4\X1137:Compute the ligature/kern program offset and implant the left -boundary label\X\S$\6 -$\\{bchar}\K\\{round\_unscaled}(\\{internal}[\\{boundary\_char}])$;\6 -\&{if} $(\\{bchar}<0)\V(\\{bchar}>255)$ \1\&{then}\6 -\&{begin} \37$\\{bchar}\K-1$;\5 -$\\{lk\_started}\K\\{false}$;\5 -$\\{lk\_offset}\K0$;\ \&{end}\6 -\4\&{else} \&{begin} \37$\\{lk\_started}\K\\{true}$;\5 -$\\{lk\_offset}\K1$;\ \&{end};\2\6 -\X1138:Find the minimum \\{lk\_offset} and adjust all remainders\X;\6 -\&{if} $\\{bch\_label}<\\{undefined\_label}$ \1\&{then}\6 -\&{begin} \37$\\{skip\_byte}(\\{nl})\K\\{qi}(255)$;\5 -$\\{next\_char}(\\{nl})\K\\{qi}(0)$;\5 -$\\{op\_byte}(\\{nl})\K\\{qi}(((\\{bch\_label}+\\{lk\_offset})\mathbin{% -\&{div}}256))$;\5 -$\\{rem\_byte}(\\{nl})\K\\{qi}(((\\{bch\_label}+\\{lk\_offset})\mathbin{% -\&{mod}}256))$;\5 -$\\{incr}(\\{nl})$;\C{possibly $\\{nl}=\\{lig\_table\_size}+1$}\6 -\&{end}\2\par -\U1135.\fi - -\M1138. \P$\X1138:Find the minimum \\{lk\_offset} and adjust all remainders\X% -\S$\6 -$\|k\K\\{label\_ptr}$;\C{pointer to the largest unallocated label}\6 -\&{if} $\\{label\_loc}[\|k]+\\{lk\_offset}>255$ \1\&{then}\6 -\&{begin} \37$\\{lk\_offset}\K0$;\5 -$\\{lk\_started}\K\\{false}$;\C{location 0 can do double duty}\6 -\1\&{repeat} \37$\\{char\_remainder}[\\{label\_char}[\|k]]\K\\{lk\_offset}$;\6 -\&{while} $\\{label\_loc}[\|k-1]=\\{label\_loc}[\|k]$ \1\&{do}\6 -\&{begin} \37$\\{decr}(\|k)$;\5 -$\\{char\_remainder}[\\{label\_char}[\|k]]\K\\{lk\_offset}$;\6 -\&{end};\2\6 -$\\{incr}(\\{lk\_offset})$;\5 -$\\{decr}(\|k)$;\6 -\4\&{until}\5 -$\\{lk\_offset}+\\{label\_loc}[\|k]<256$;\C{N.B.: $\\{lk\_offset}=256$ -satisfies this when $\|k=0$}\2\6 -\&{end};\2\6 -\&{if} $\\{lk\_offset}>0$ \1\&{then}\6 -\&{while} $\|k>0$ \1\&{do}\6 -\&{begin} \37$\\{char\_remainder}[\\{label\_char}[\|k]]\K\\{char\_remainder}[% -\\{label\_char}[\|k]]+\\{lk\_offset}$;\5 -$\\{decr}(\|k)$;\6 -\&{end}\2\2\par -\U1137.\fi - -\M1139. \P$\X1139:Output the ligature/kern program\X\S$\6 -\&{for} $\|k\K0\mathrel{\&{to}}255$ \1\&{do}\6 -\&{if} $\\{skip\_table}[\|k]<\\{undefined\_label}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"(local\ label\ "})$;\5 -$\\{print\_int}(\|k)$;\5 -$\\{print}(\.{"::\ was\ missing)"})$;\5 -$\\{cancel\_skips}(\\{skip\_table}[\|k])$;\6 -\&{end};\2\2\6 -\&{if} $\\{lk\_started}$ \1\&{then}\C{$\\{lk\_offset}=1$ for the special % -\\{bchar}}\6 -\&{begin} \37$\\{tfm\_out}(255)$;\5 -$\\{tfm\_out}(\\{bchar})$;\5 -$\\{tfm\_two}(0)$;\6 -\&{end}\6 -\4\&{else} \&{for} $\|k\K1\mathrel{\&{to}}\\{lk\_offset}$ \1\&{do}\C{output the -redirection specs}\6 -\&{begin} \37$\\{ll}\K\\{label\_loc}[\\{label\_ptr}]$;\6 -\&{if} $\\{bchar}<0$ \1\&{then}\6 -\&{begin} \37$\\{tfm\_out}(254)$;\5 -$\\{tfm\_out}(0)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{tfm\_out}(255)$;\5 -$\\{tfm\_out}(\\{bchar})$;\6 -\&{end};\2\6 -$\\{tfm\_two}(\\{ll}+\\{lk\_offset})$;\6 -\1\&{repeat} \37$\\{decr}(\\{label\_ptr})$;\6 -\4\&{until}\5 -$\\{label\_loc}[\\{label\_ptr}]<\\{ll}$;\2\6 -\&{end};\2\2\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{nl}-1$ \1\&{do}\5 -$\\{tfm\_qqqq}(\\{lig\_kern}[\|k])$;\2\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{nk}-1$ \1\&{do}\5 -$\\{tfm\_four}(\\{dimen\_out}(\\{kern}[\|k]))$\2\par -\U1134.\fi - -\M1140. \P$\X1140:Output the extensible character recipes and the font metric -parameters\X\S$\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{ne}-1$ \1\&{do}\5 -$\\{tfm\_qqqq}(\\{exten}[\|k])$;\2\6 -\&{for} $\|k\K1\mathrel{\&{to}}\\{np}$ \1\&{do}\6 -\&{if} $\|k=1$ \1\&{then}\6 -\&{if} $\\{abs}(\\{param}[1])<\\{fraction\_half}$ \1\&{then}\5 -$\\{tfm\_four}(\\{param}[1]\ast16)$\6 -\4\&{else} \&{begin} \37$\\{incr}(\\{tfm\_changed})$;\6 -\&{if} $\\{param}[1]>0$ \1\&{then}\5 -$\\{tfm\_four}(\\{el\_gordo})$\6 -\4\&{else} $\\{tfm\_four}(-\\{el\_gordo})$;\2\6 -\&{end}\2\6 -\4\&{else} $\\{tfm\_four}(\\{dimen\_out}(\\{param}[\|k]))$;\2\2\6 -\&{if} $\\{tfm\_changed}>0$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{tfm\_changed}=1$ \1\&{then}\5 -$\\{print\_nl}(\.{"(a\ font\ metric\ dimension"})$\6 -\4\&{else} \&{begin} \37$\\{print\_nl}(\.{"("})$;\5 -$\\{print\_int}(\\{tfm\_changed})$;\5 -$\\{print}(\.{"\ font\ metric\ dimensions"})$;\6 -\&{end};\2\6 -$\\{print}(\.{"\ had\ to\ be\ decreased)"})$;\6 -\&{end}\2\par -\U1134.\fi - -\M1141. \P$\X1141:Log the subfile sizes of the \.{TFM} file\X\S$\6 -\&{begin} \37$\\{wlog\_ln}(\.{\'\ \'})$;\6 -\&{if} $\\{bch\_label}<\\{undefined\_label}$ \1\&{then}\5 -$\\{decr}(\\{nl})$;\2\6 -$\\{wlog\_ln}(\.{\'(You\ used\ \'},\39\\{nw}:1,\39\.{\'w,\'},\39\30\\{nh}:1,\39% -\.{\'h,\'},\39\30\\{nd}:1,\39\.{\'d,\'},\39\30\\{ni}:1,\39\.{\'i,\'},\39\30% -\\{nl}:1,\39\.{\'l,\'},\39\30\\{nk}:1,\39\.{\'k,\'},\39\30\\{ne}:1,\39\.{\'e,% -\'},\39\30\\{np}:1,\39\.{\'p\ metric\ file\ positions\'})$;\5 -$\\{wlog\_ln}(\.{\'\ \ out\ of\ \'},\39\30\.{\'256w,16h,16d,64i,\'},\39\30% -\\{lig\_table\_size}:1,\39\.{\'l,\'},\39\\{max\_kerns}:1,\39\.{\'k,256e,\'},\39% -\30\\{max\_font\_dimen}:1,\39\.{\'p)\'})$;\6 -\&{end}\par -\U1134.\fi - -\N1142. \[46] Generic font file format. -The most important output produced by a typical run of \MF\ is the -``generic font'' (\.{GF}) file that specifies the bit patterns of the -characters that have been drawn. The term {\sl generic\/} indicates that -this file format doesn't match the conventions of any name-brand manufacturer; -but it is easy to convert \.{GF} files to the special format required by -almost all digital phototypesetting equipment. There's a strong analogy -between the \.{DVI} files written by \TeX\ and the \.{GF} files written -by \MF; and, in fact, the file formats have a lot in common. - -A \.{GF} file is a stream of 8-bit bytes that may be -regarded as a series of commands in a machine-like language. The first -byte of each command is the operation code, and this code is followed by -zero or more bytes that provide parameters to the command. The parameters -themselves may consist of several consecutive bytes; for example, the -`\\{boc}' (beginning of character) command has six parameters, each of -which is four bytes long. Parameters are usually regarded as nonnegative -integers; but four-byte-long parameters can be either positive or -negative, hence they range in value from $-2^{31}$ to $2^{31}-1$. -As in \.{TFM} files, numbers that occupy -more than one byte position appear in BigEndian order, -and negative numbers appear in two's complement notation. - -A \.{GF} file consists of a ``preamble,'' followed by a sequence of one or -more ``characters,'' followed by a ``postamble.'' The preamble is simply a -\\{pre} command, with its parameters that introduce the file; this must come -first. Each ``character'' consists of a \\{boc} command, followed by any -number of other commands that specify ``black'' pixels, -followed by an \\{eoc} command. The characters appear in the order that \MF\ -generated them. If we ignore no-op commands (which are allowed between any -two commands in the file), each \\{eoc} command is immediately followed by a -\\{boc} command, or by a \\{post} command; in the latter case, there are no -more characters in the file, and the remaining bytes form the postamble. -Further details about the postamble will be explained later. - -Some parameters in \.{GF} commands are ``pointers.'' These are four-byte -quantities that give the location number of some other byte in the file; -the first file byte is number~0, then comes number~1, and so on. - -\fi - -\M1143. The \.{GF} format is intended to be both compact and easily interpreted -by a machine. Compactness is achieved by making most of the information -relative instead of absolute. When a \.{GF}-reading program reads the -commands for a character, it keeps track of two quantities: (a)~the current -column number,~\|m; and (b)~the current row number,~\|n. These are 32-bit -signed integers, although most actual font formats produced from \.{GF} -files will need to curtail this vast range because of practical -limitations. (\MF\ output will never allow $\vert m\vert$ or $\vert -n\vert$ to get extremely large, but the \.{GF} format tries to be more -general.) - -How do \.{GF}'s row and column numbers correspond to the conventions -of \TeX\ and \MF? Well, the ``reference point'' of a character, in \TeX's -view, is considered to be at the lower left corner of the pixel in row~0 -and column~0. This point is the intersection of the baseline with the left -edge of the type; it corresponds to location $(0,0)$ in \MF\ programs. -Thus the pixel in \.{GF} row~0 and column~0 is \MF's unit square, comprising -the -region of the plane whose coordinates both lie between 0 and~1. The -pixel in \.{GF} row~\|n and column~\|m consists of the points whose \MF\ -coordinates $(\|x,\|y)$ satisfy $\|m\L\|x\L\|m+1$ and $\|n\L\|y\L\|n+1$. -Negative values of -\|m and~\|x correspond to columns of pixels {\sl left\/} of the reference -point; negative values of \|n and~\|y correspond to rows of pixels {\sl -below\/} the baseline. - -Besides \|m and \|n, there's also a third aspect of the current -state, namely the \\{paint\_switch}, which is always either \\{black} or -\\{white}. Each \\{paint} command advances \|m by a specified amount~\|d, -and blackens the intervening pixels if $\\{paint\_switch}=\\{black}$; then -the \\{paint\_switch} changes to the opposite state. \.{GF}'s commands are -designed so that \|m will never decrease within a row, and \|n will never -increase within a character; hence there is no way to whiten a pixel that -has been blackened. - -\fi - -\M1144. Here is a list of all the commands that may appear in a \.{GF} file. -Each -command is specified by its symbolic name (e.g., \\{boc}), its opcode byte -(e.g., 67), and its parameters (if any). The parameters are followed -by a bracketed number telling how many bytes they occupy; for example, -`$\|d[2]$' means that parameter \|d is two bytes long. - -\yskip\hang\\{paint\_0} 0. This is a \\{paint} command with $\|d=0$; it does -nothing but change the \\{paint\_switch} from \\{black} to \\{white} or -vice~versa. - -\yskip\hang\\{paint\_1} through \\{paint\_63} (opcodes 1 to 63). -These are \\{paint} commands with $\|d=1$ to~63, defined as follows: If -$\\{paint\_switch}=\\{black}$, blacken \|d~pixels of the current row~\|n, -in columns \|m through $\|m+\|d-1$ inclusive. Then, in any case, -complement the \\{paint\_switch} and advance \|m by~\|d. - -\yskip\hang\\{paint1} 64 $\|d[1]$. This is a \\{paint} command with a specified -value of~\|d; \MF\ uses it to paint when $64\L\|d<256$. - -\yskip\hang\\{paint2} 65 $\|d[2]$. Same as \\{paint1}, but \|d~can be as high -as~65535. - -\yskip\hang\\{paint3} 66 $\|d[3]$. Same as \\{paint1}, but \|d~can be as high -as $2^{24}-1$. \MF\ never needs this command, and it is hard to imagine -anybody making practical use of it; surely a more compact encoding will be -desirable when characters can be this large. But the command is there, -anyway, just in case. - -\yskip\hang\\{boc} 67 $\|c[4]$ $\|p[4]$ $\\{min\_m}[4]$ $\\{max\_m}[4]$ $\\{min% -\_n}[4]$ -$\\{max\_n}[4]$. Beginning of a character: Here \|c is the character code, and -\|p points to the previous character beginning (if any) for characters having -this code number modulo 256. (The pointer \|p is $-1$ if there was no -prior character with an equivalent code.) The values of registers \|m and \|n -defined by the instructions that follow for this character must -satisfy $\\{min\_m}\L\|m\L\\{max\_m}$ and $\\{min\_n}\L\|n\L\\{max\_n}$. (The -values of \\{max\_m} and -\\{min\_n} need not be the tightest bounds possible.) When a \.{GF}-reading -program sees a \\{boc}, it can use \\{min\_m}, \\{max\_m}, \\{min\_n}, and % -\\{max\_n} to -initialize the bounds of an array. Then it sets $\|m\K\\{min\_m}$, $\|n\K\\{max% -\_n}$, and -$\\{paint\_switch}\K\\{white}$. - -\yskip\hang\\{boc1} 68 $\|c[1]$ $\\{del\_m}[1]$ $\\{max\_m}[1]$ $\\{del\_n}[1]$ -$\\{max\_n}[1]$. -Same as \\{boc}, but \|p is assumed to be~$-1$; also $\\{del\_m}=\\{max\_m}-% -\\{min\_m}$ -and $\\{del\_n}=\\{max\_n}-\\{min\_n}$ are given instead of \\{min\_m} and % -\\{min\_n}. -The one-byte parameters must be between 0 and 255, inclusive. -\ (This abbreviated \\{boc} saves 19~bytes per character, in common cases.) - -\yskip\hang\\{eoc} 69. End of character: All pixels blackened so far -constitute the pattern for this character. In particular, a completely -blank character might have \\{eoc} immediately following \\{boc}. - -\yskip\hang\\{skip0} 70. Decrease \|n by 1 and set $\|m\K\\{min\_m}$, -$\\{paint\_switch}\K\\{white}$. \ (This finishes one row and begins another, -ready to whiten the leftmost pixel in the new row.) - -\yskip\hang\\{skip1} 71 $\|d[1]$. Decrease \|n by $\|d+1$, set $\|m\K\\{min% -\_m}$, and set -$\\{paint\_switch}\K\\{white}$. This is a way to produce \|d all-white rows. - -\yskip\hang\\{skip2} 72 $\|d[2]$. Same as \\{skip1}, but \|d can be as large -as 65535. - -\yskip\hang\\{skip3} 73 $\|d[3]$. Same as \\{skip1}, but \|d can be as large -as $2^{24}-1$. \MF\ obviously never needs this command. - -\yskip\hang\\{new\_row\_0} 74. Decrease \|n by 1 and set $\|m\K\\{min\_m}$, -$\\{paint\_switch}\K\\{black}$. \ (This finishes one row and begins another, -ready to {\sl blacken\/} the leftmost pixel in the new row.) - -\yskip\hang\\{new\_row\_1} through \\{new\_row\_164} (opcodes 75 to 238). Same -as -\\{new\_row\_0}, but with $\|m\K\\{min\_m}+1$ through $\\{min\_m}+164$, -respectively. - -\yskip\hang\\{xxx1} 239 $\|k[1]$ $\|x[\|k]$. This command is undefined in -general; it functions as a $(k+2)$-byte \\{no\_op} unless special % -\.{GF}-reading -programs are being used. \MF\ generates \\{xxx} commands when encountering -a \&{special} string; this occurs in the \.{GF} file only between -characters, after the preamble, and before the postamble. However, -\\{xxx} commands might appear within characters, -in \.{GF} files generated by other -processors. It is recommended that \|x be a string having the form of a -keyword followed by possible parameters relevant to that keyword. - -\yskip\hang\\{xxx2} 240 $\|k[2]$ $\|x[\|k]$. Like \\{xxx1}, but $0\L\|k<65536$. - -\yskip\hang\\{xxx3} 241 $\|k[3]$ $\|x[\|k]$. Like \\{xxx1}, but $0\L\|k<% -\hbox{$2^{24}$}$. -\MF\ uses this when sending a \&{special} string whose length exceeds~255. - -\yskip\hang\\{xxx4} 242 $\|k[4]$ $\|x[\|k]$. Like \\{xxx1}, but \|k can be -ridiculously large; \|k mustn't be negative. - -\yskip\hang\\{yyy} 243 $\|y[4]$. This command is undefined in general; -it functions as a 5-byte \\{no\_op} unless special \.{GF}-reading programs -are being used. \MF\ puts \\{scaled} numbers into \\{yyy}'s, as a -result of \&{numspecial} commands; the intent is to provide numeric -parameters to \\{xxx} commands that immediately precede. - -\yskip\hang\\{no\_op} 244. No operation, do nothing. Any number of \\{no\_op}'s -may occur between \.{GF} commands, but a \\{no\_op} cannot be inserted between -a command and its parameters or between two parameters. - -\yskip\hang\\{char\_loc} 245 $\|c[1]$ $\\{dx}[4]$ $\\{dy}[4]$ $\|w[4]$ $% -\|p[4]$. -This command will appear only in the postamble, which will be explained -shortly. - -\yskip\hang\\{char\_loc0} 246 $\|c[1]$ $\\{dm}[1]$ $\|w[4]$ $\|p[4]$. -Same as \\{char\_loc}, except that \\{dy} is assumed to be zero, and the value -of~\\{dx} is taken to be $65536\ast\\{dm}$, where $0\L\\{dm}<256$. - -\yskip\hang\\{pre} 247 $\|i[1]$ $\|k[1]$ $\|x[\|k]$. -Beginning of the preamble; this must come at the very beginning of the -file. Parameter \|i is an identifying number for \.{GF} format, currently -131. The other information is merely commentary; it is not given -special interpretation like \\{xxx} commands are. (Note that \\{xxx} -commands may immediately follow the preamble, before the first \\{boc}.) - -\yskip\hang\\{post} 248. Beginning of the postamble, see below. - -\yskip\hang\\{post\_post} 249. Ending of the postamble, see below. - -\yskip\noindent Commands 250--255 are undefined at the present time. - -\Y\P\D \37$\\{gf\_id\_byte}=131$\C{identifies the kind of \.{GF} files -described here}\par -\fi - -\M1145. \MF\ refers to the following opcodes explicitly. - -\Y\P\D \37$\\{paint\_0}=0$\C{beginning of the \\{paint} commands}\par -\P\D \37$\\{paint1}=64$\C{move right a given number of columns, then black${}% -\swap{}$white}\par -\P\D \37$\\{boc}=67$\C{beginning of a character}\par -\P\D \37$\\{boc1}=68$\C{short form of \\{boc}}\par -\P\D \37$\\{eoc}=69$\C{end of a character}\par -\P\D \37$\\{skip0}=70$\C{skip no blank rows}\par -\P\D \37$\\{skip1}=71$\C{skip over blank rows}\par -\P\D \37$\\{new\_row\_0}=74$\C{move down one row and then right}\par -\P\D \37$\\{max\_new\_row}=164$\C{the largest \\{new\_row} command is \\{new% -\_row\_164}}\par -\P\D \37$\\{xxx1}=239$\C{for \&{special} strings}\par -\P\D \37$\\{xxx3}=241$\C{for long \&{special} strings}\par -\P\D \37$\\{yyy}=243$\C{for \&{numspecial} numbers}\par -\P\D \37$\\{char\_loc}=245$\C{character locators in the postamble}\par -\P\D \37$\\{pre}=247$\C{preamble}\par -\P\D \37$\\{post}=248$\C{postamble beginning}\par -\P\D \37$\\{post\_post}=249$\C{postamble ending}\par -\fi - -\M1146. The last character in a \.{GF} file is followed by `\\{post}'; this -command -introduces the postamble, which summarizes important facts that \MF\ has -accumulated. The postamble has the form -$$\vbox{\halign{\hbox{#\hfil}\cr -\\{post} $\|p[4]$ $\\{ds}[4]$ $\\{cs}[4]$ $\\{hppp}[4]$ $\\{vppp}[4]$ -$\\{min\_m}[4]$ $\\{max\_m}[4]$ $\\{min\_n}[4]$ $\\{max\_n}[4]$\cr -$\langle\,$character locators$\,\rangle$\cr -\\{post\_post} $\|q[4]$ $\|i[1]$ 223's$[{\G}4]$\cr}}$$ -Here \|p is a pointer to the byte following the final \\{eoc} in the file -(or to the byte following the preamble, if there are no characters); -it can be used to locate the beginning of \\{xxx} commands -that might have preceded the postamble. The \\{ds} and \\{cs} parameters -give the design size and check sum, respectively, which are exactly the -values put into the header of the \.{TFM} file that \MF\ produces (or -would produce) on this run. Parameters \\{hppp} and \\{vppp} are the ratios of -pixels per point, horizontally and vertically, expressed as \\{scaled} integers -(i.e., multiplied by $2^{16}$); they can be used to correlate the font -with specific device resolutions, magnifications, and ``at sizes.'' Then -come \\{min\_m}, \\{max\_m}, \\{min\_n}, and \\{max\_n}, which bound the values -that -registers \|m and~\|n assume in all characters in this \.{GF} file. -(These bounds need not be the best possible; \\{max\_m} and \\{min\_n} may, on -the -other hand, be tighter than the similar bounds in \\{boc} commands. For -example, some character may have $\\{min\_n}=-100$ in its \\{boc}, but it might -turn out that \|n never gets lower than $-50$ in any character; then -\\{min\_n} can have any value $\L-50$. If there are no characters in the file, -it's possible to have $\\{min\_m}>\\{max\_m}$ and/or $\\{min\_n}>\\{max\_n}$.) - -\fi - -\M1147. Character locators are introduced by \\{char\_loc} commands, -which specify a character residue~\|c, character escapements ($\\{dx},\\{dy}$), -a character width~\|w, and a pointer~\|p -to the beginning of that character. (If two or more characters have the -same code~\|c modulo 256, only the last will be indicated; the others can be -located by following backpointers. Characters whose codes differ by a -multiple of 256 are assumed to share the same font metric information, -hence the \.{TFM} file contains only residues of character codes modulo~256. -This convention is intended for oriental languages, when there are many -character shapes but few distinct widths.) - -The character escapements ($\\{dx},\\{dy}$) are the values of \MF's \&{chardx} -and \&{chardy} parameters; they are in units of \\{scaled} pixels; -i.e., \\{dx} is in horizontal pixel units times $2^{16}$, and \\{dy} is in -vertical pixel units times $2^{16}$. This is the intended amount of -displacement after typesetting the character; for \.{DVI} files, \\{dy} -should be zero, but other document file formats allow nonzero vertical -escapement. - -The character width~\|w duplicates the information in the \.{TFM} file; it -is a \\{fix\_word} value relative to the design size, and it should be -independent of magnification. - -The backpointer \|p points to the character's \\{boc}, or to the first of -a sequence of consecutive \\{xxx} or \\{yyy} or \\{no\_op} commands that -immediately precede the \\{boc}, if such commands exist; such ``special'' -commands essentially belong to the characters, while the special commands -after the final character belong to the postamble (i.e., to the font -as a whole). This convention about \|p applies also to the backpointers -in \\{boc} commands, even though it wasn't explained in the description -of~\\{boc}. - -Pointer \|p might be $-1$ if the character exists in the \.{TFM} file -but not in the \.{GF} file. This unusual situation can arise in \MF\ output -if the user had $\\{proofing}<0$ when the character was being shipped out, -but then made $\\{proofing}\G0$ in order to get a \.{GF} file. - -\fi - -\M1148. The last part of the postamble, following the \\{post\_post} byte that -signifies the end of the character locators, contains \|q, a pointer to the -\\{post} command that started the postamble. An identification byte, \|i, -comes next; this currently equals~131, as in the preamble. - -The \|i byte is followed by four or more bytes that are all equal to -the decimal number 223 (i.e., \O{337} in octal). \MF\ puts out four to seven of -these trailing bytes, until the total length of the file is a multiple of -four bytes, since this works out best on machines that pack four bytes per -word; but any number of 223's is allowed, as long as there are at least four -of them. In effect, 223 is a sort of signature that is added at the very end. - -This curious way to finish off a \.{GF} file makes it feasible for -\.{GF}-reading programs to find the postamble first, on most computers, -even though \MF\ wants to write the postamble last. Most operating -systems permit random access to individual words or bytes of a file, so -the \.{GF} reader can start at the end and skip backwards over the 223's -until finding the identification byte. Then it can back up four bytes, read -\|q, and move to byte \|q of the file. This byte should, of course, -contain the value 248 (\\{post}); now the postamble can be read, so the -\.{GF} reader can discover all the information needed for individual -characters. - -Unfortunately, however, standard \PASCAL\ does not include the ability to -access a random position in a file, or even to determine the length of a file. -Almost all systems nowadays provide the necessary capabilities, so \.{GF} -format has been designed to work most efficiently with modern operating -systems. -But if \.{GF} files have to be processed under the restrictions of standard -\PASCAL, one can simply read them from front to back. This will -be adequate for most applications. However, the postamble-first approach -would facilitate a program that merges two \.{GF} files, replacing data -from one that is overridden by corresponding data in the other. - -\fi - -\N1149. \[47] Shipping characters out. -The \\{ship\_out} procedure, to be described below, is given a pointer to -an edge structure. Its mission is to describe the the positive pixels -in \.{GF} form, outputting a ``character'' to \\{gf\_file}. - -Several global variables hold information about the font file as a whole:\ -\\{gf\_min\_m}, \\{gf\_max\_m}, \\{gf\_min\_n}, and \\{gf\_max\_n} are the -minimum and -maximum \.{GF} coordinates output so far; \\{gf\_prev\_ptr} is the byte number -following the preamble or the last \\{eoc} command in the output; -\\{total\_chars} is the total number of characters (i.e., $\\{boc}\to\\{eoc}$ -segments) -shipped out. There's also an array, \\{char\_ptr}, containing the starting -positions of each character in the file, as required for the postamble. If -character code~\|c has not yet been output, $\\{char\_ptr}[\|c]=-1$. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{gf\_min\_m},\39\\{gf\_max\_m},\39\\{gf\_min\_n},\39\\{gf\_max\_n}$: \37% -\\{integer};\C{bounding rectangle}\6 -\4\\{gf\_prev\_ptr}: \37\\{integer};\C{where the present/next character -started/starts}\6 -\4\\{total\_chars}: \37\\{integer};\C{the number of characters output so far}\6 -\4\\{char\_ptr}: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{integer};\C{where individual characters started}\2\6 -\4$\\{gf\_dx},\39\\{gf\_dy}$: \37\&{array} $[\\{eight\_bits}]$ \1\&{of}\5 -\\{integer};\C{device escapements}\2\par -\fi - -\M1150. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{gf\_prev\_ptr}\K0$;\5 -$\\{total\_chars}\K0$;\par -\fi - -\M1151. The \.{GF} bytes are output to a buffer instead of being sent -byte-by-byte to \\{gf\_file}, because this tends to save a lot of -subroutine-call overhead. \MF\ uses the same conventions for \\{gf\_file} -as \TeX\ uses for its \\{dvi\_file}; hence if system-dependent -changes are needed, they should probably be the same for both programs. - -The output buffer is divided into two parts of equal size; the bytes found -in $\\{gf\_buf}[0\to\\{half\_buf}-1]$ constitute the first half, and those in -$\\{gf\_buf}[\\{half\_buf}\to\\{gf\_buf\_size}-1]$ constitute the second. The -global -variable \\{gf\_ptr} points to the position that will receive the next -output byte. When \\{gf\_ptr} reaches \\{gf\_limit}, which is always equal -to one of the two values \\{half\_buf} or \\{gf\_buf\_size}, the half buffer -that -is about to be invaded next is sent to the output and \\{gf\_limit} is -changed to its other value. Thus, there is always at least a half buffer's -worth of information present, except at the very beginning of the job. - -Bytes of the \.{GF} file are numbered sequentially starting with 0; -the next byte to be generated will be number $\\{gf\_offset}+\\{gf\_ptr}$. - -\Y\P$\4\X18:Types in the outer block\X\mathrel{+}\S$\6 -$\\{gf\_index}=0\to\\{gf\_buf\_size}$;\C{an index into the output buffer}\par -\fi - -\M1152. Some systems may find it more efficient to make \\{gf\_buf} a % -\&{packed} -array, since output of four bytes at once may be facilitated. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{gf\_buf}: \37\&{array} $[\\{gf\_index}]$ \1\&{of}\5 -\\{eight\_bits};\C{buffer for \.{GF} output}\2\6 -\4\\{half\_buf}: \37\\{gf\_index};\C{half of \\{gf\_buf\_size}}\6 -\4\\{gf\_limit}: \37\\{gf\_index};\C{end of the current half buffer}\6 -\4\\{gf\_ptr}: \37\\{gf\_index};\C{the next available buffer address}\6 -\4\\{gf\_offset}: \37\\{integer};\C{\\{gf\_buf\_size} times the number of times -the output buffer has been fully emptied}\par -\fi - -\M1153. Initially the buffer is all in one piece; we will output half of it -only -after it first fills up. - -\Y\P$\4\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{half\_buf}\K\\{gf\_buf\_size}\mathbin{\&{div}}2$;\5 -$\\{gf\_limit}\K\\{gf\_buf\_size}$;\5 -$\\{gf\_ptr}\K0$;\5 -$\\{gf\_offset}\K0$;\par -\fi - -\M1154. The actual output of $\\{gf\_buf}[\|a\to\|b]$ to \\{gf\_file} is -performed by calling -$\\{write\_gf}(\|a,\|b)$. It is safe to assume that \|a and $\|b+1$ will both -be -multiples of 4 when $\\{write\_gf}(\|a,\|b)$ is called; therefore it is -possible on -many machines to use efficient methods to pack four bytes per word and to -output an array of words with one system call. - -\Y\P$\4\X1154:Declare generic font output procedures\X\S$\6 -\4\&{procedure}\1\ \37$\\{write\_gf}(\|a,\39\|b:\\{gf\_index})$;\6 -\4\&{var} \37\|k: \37\\{gf\_index};\2\6 -\&{begin} \37\&{for} $\|k\K\|a\mathrel{\&{to}}\|b$ \1\&{do}\5 -$\\{write}(\\{gf\_file},\39\\{gf\_buf}[\|k])$;\2\6 -\&{end};\par -\As1155, 1157, 1158, 1159, 1160, 1161, 1163\ETs1165. -\U989.\fi - -\M1155. To put a byte in the buffer without paying the cost of invoking a -procedure -each time, we use the macro \\{gf\_out}. - -\Y\P\D \37$\\{gf\_out}(\#)\S$\ \&{begin} \37$\\{gf\_buf}[\\{gf\_ptr}]\K\#$;\5 -$\\{incr}(\\{gf\_ptr})$;\6 -\&{if} $\\{gf\_ptr}=\\{gf\_limit}$ \1\&{then}\5 -\\{gf\_swap};\2\6 -\&{end}\par -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{gf\_swap};\C{outputs half of the buffer}\2\6 -\&{begin} \37\&{if} $\\{gf\_limit}=\\{gf\_buf\_size}$ \1\&{then}\6 -\&{begin} \37$\\{write\_gf}(0,\39\\{half\_buf}-1)$;\5 -$\\{gf\_limit}\K\\{half\_buf}$;\5 -$\\{gf\_offset}\K\\{gf\_offset}+\\{gf\_buf\_size}$;\5 -$\\{gf\_ptr}\K0$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{write\_gf}(\\{half\_buf},\39\\{gf\_buf\_size}-1)$;\5 -$\\{gf\_limit}\K\\{gf\_buf\_size}$;\6 -\&{end};\2\6 -\&{end};\par -\fi - -\M1156. Here is how we clean out the buffer when \MF\ is all through; \\{gf% -\_ptr} -will be a multiple of~4. - -\Y\P$\4\X1156:Empty the last bytes out of \\{gf\_buf}\X\S$\6 -\&{if} $\\{gf\_limit}=\\{half\_buf}$ \1\&{then}\5 -$\\{write\_gf}(\\{half\_buf},\39\\{gf\_buf\_size}-1)$;\2\6 -\&{if} $\\{gf\_ptr}>0$ \1\&{then}\5 -$\\{write\_gf}(0,\39\\{gf\_ptr}-1)$\2\par -\U1182.\fi - -\M1157. The \\{gf\_four} procedure outputs four bytes in two's complement -notation, -without risking arithmetic overflow. - -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{gf\_four}(\|x:\\{integer})$;\2\6 -\&{begin} \37\&{if} $\|x\G0$ \1\&{then}\5 -$\\{gf\_out}(\|x\mathbin{\&{div}}\\{three\_bytes})$\6 -\4\&{else} \&{begin} \37$\|x\K\|x+\O{10000000000}$;\5 -$\|x\K\|x+\O{10000000000}$;\5 -$\\{gf\_out}((\|x\mathbin{\&{div}}\\{three\_bytes})+128)$;\6 -\&{end};\2\6 -$\|x\K\|x\mathbin{\&{mod}}\\{three\_bytes}$;\5 -$\\{gf\_out}(\|x\mathbin{\&{div}}\\{unity})$;\5 -$\|x\K\|x\mathbin{\&{mod}}\\{unity}$;\5 -$\\{gf\_out}(\|x\mathbin{\&{div}}\O{400})$;\5 -$\\{gf\_out}(\|x\mathbin{\&{mod}}\O{400})$;\6 -\&{end};\par -\fi - -\M1158. Of course, it's even easier to output just two or three bytes. - -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{gf\_two}(\|x:\\{integer})$;\2\6 -\&{begin} \37$\\{gf\_out}(\|x\mathbin{\&{div}}\O{400})$;\5 -$\\{gf\_out}(\|x\mathbin{\&{mod}}\O{400})$;\6 -\&{end};\7 -\4\&{procedure}\1\ \37$\\{gf\_three}(\|x:\\{integer})$;\2\6 -\&{begin} \37$\\{gf\_out}(\|x\mathbin{\&{div}}\\{unity})$;\5 -$\\{gf\_out}((\|x\mathbin{\&{mod}}\\{unity})\mathbin{\&{div}}\O{400})$;\5 -$\\{gf\_out}(\|x\mathbin{\&{mod}}\O{400})$;\6 -\&{end};\par -\fi - -\M1159. We need a simple routine to generate a \\{paint} -command of the appropriate type. - -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{gf\_paint}(\|d:\\{integer})$;\C{here $0\L\|d<65536$}% -\2\6 -\&{begin} \37\&{if} $\|d<64$ \1\&{then}\5 -$\\{gf\_out}(\\{paint\_0}+\|d)$\6 -\4\&{else} \&{if} $\|d<256$ \1\&{then}\6 -\&{begin} \37$\\{gf\_out}(\\{paint1})$;\5 -$\\{gf\_out}(\|d)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{gf\_out}(\\{paint1}+1)$;\5 -$\\{gf\_two}(\|d)$;\6 -\&{end};\2\2\6 -\&{end};\par -\fi - -\M1160. And \\{gf\_string} outputs one or two strings. If the first string -number -is nonzero, an \\{xxx} command is generated. - -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{gf\_string}(\|s,\39\|t:\\{str\_number})$;\6 -\4\&{var} \37\|k: \37\\{pool\_pointer};\5 -\|l: \37\\{integer};\C{length of the strings to output}\2\6 -\&{begin} \37\&{if} $\|s\I0$ \1\&{then}\6 -\&{begin} \37$\|l\K\\{length}(\|s)$;\6 -\&{if} $\|t\I0$ \1\&{then}\5 -$\|l\K\|l+\\{length}(\|t)$;\2\6 -\&{if} $\|l\L255$ \1\&{then}\6 -\&{begin} \37$\\{gf\_out}(\\{xxx1})$;\5 -$\\{gf\_out}(\|l)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{gf\_out}(\\{xxx3})$;\5 -$\\{gf\_three}(\|l)$;\6 -\&{end};\2\6 -\&{for} $\|k\K\\{str\_start}[\|s]\mathrel{\&{to}}\\{str\_start}[\|s+1]-1$ \1% -\&{do}\5 -$\\{gf\_out}(\\{so}(\\{str\_pool}[\|k]))$;\2\6 -\&{end};\2\6 -\&{if} $\|t\I0$ \1\&{then}\6 -\&{for} $\|k\K\\{str\_start}[\|t]\mathrel{\&{to}}\\{str\_start}[\|t+1]-1$ \1% -\&{do}\5 -$\\{gf\_out}(\\{so}(\\{str\_pool}[\|k]))$;\2\2\6 -\&{end};\par -\fi - -\M1161. The choice between \\{boc} commands is handled by \\{gf\_boc}. - -\Y\P\D $\\{one\_byte}(\#)\S\#\G0$ \&{then} \6 -\&{if} $\#<256$\par -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{gf\_boc}(\\{min\_m},\39\\{max\_m},\39\\{min\_n},\39% -\\{max\_n}:\\{integer})$;\6 -\4\&{label} \37\\{exit};\2\6 -\&{begin} \37\&{if} $\\{min\_m}<\\{gf\_min\_m}$ \1\&{then}\5 -$\\{gf\_min\_m}\K\\{min\_m}$;\2\6 -\&{if} $\\{max\_n}>\\{gf\_max\_n}$ \1\&{then}\5 -$\\{gf\_max\_n}\K\\{max\_n}$;\2\6 -\&{if} $\\{boc\_p}=-1$ \1\&{then}\6 -\&{if} $\\{one\_byte}(\\{boc\_c})$ \1\&{then}\6 -\&{if} $\\{one\_byte}(\\{max\_m}-\\{min\_m})$ \1\&{then}\6 -\&{if} $\\{one\_byte}(\\{max\_m})$ \1\&{then}\6 -\&{if} $\\{one\_byte}(\\{max\_n}-\\{min\_n})$ \1\&{then}\6 -\&{if} $\\{one\_byte}(\\{max\_n})$ \1\&{then}\6 -\&{begin} \37$\\{gf\_out}(\\{boc1})$;\5 -$\\{gf\_out}(\\{boc\_c})$;\6 -$\\{gf\_out}(\\{max\_m}-\\{min\_m})$;\5 -$\\{gf\_out}(\\{max\_m})$;\5 -$\\{gf\_out}(\\{max\_n}-\\{min\_n})$;\5 -$\\{gf\_out}(\\{max\_n})$;\5 -\&{return};\6 -\&{end};\2\2\2\2\2\2\6 -$\\{gf\_out}(\\{boc})$;\5 -$\\{gf\_four}(\\{boc\_c})$;\5 -$\\{gf\_four}(\\{boc\_p})$;\6 -$\\{gf\_four}(\\{min\_m})$;\5 -$\\{gf\_four}(\\{max\_m})$;\5 -$\\{gf\_four}(\\{min\_n})$;\5 -$\\{gf\_four}(\\{max\_n})$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1162. Two of the parameters to \\{gf\_boc} are global. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4$\\{boc\_c},\39\\{boc\_p}$: \37\\{integer};\C{parameters of the next \\{boc} -command}\par -\fi - -\M1163. Here is a routine that gets a \.{GF} file off to a good start. - -\Y\P\D \37$\\{check\_gf}\S\hbox{}$\ \&{if} $\\{output\_file\_name}=0$ \1% -\&{then}\5 -\\{init\_gf}\2\par -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{init\_gf};\6 -\4\&{var} \37\|k: \37\\{eight\_bits};\C{runs through all possible character -codes}\6 -\|t: \37\\{integer};\C{the time of this run}\2\6 -\&{begin} \37$\\{gf\_min\_m}\K4096$;\5 -$\\{gf\_max\_m}\K-4096$;\5 -$\\{gf\_min\_n}\K4096$;\5 -$\\{gf\_max\_n}\K-4096$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}255$ \1\&{do}\5 -$\\{char\_ptr}[\|k]\K-1$;\2\6 -\X1164:Determine the file extension, \\{gf\_ext}\X;\6 -\\{set\_output\_file\_name};\5 -$\\{gf\_out}(\\{pre})$;\5 -$\\{gf\_out}(\\{gf\_id\_byte})$;\C{begin to output the preamble}\6 -$\\{old\_setting}\K\\{selector}$;\5 -$\\{selector}\K\\{new\_string}$;\5 -$\\{print}(\.{"\ METAFONT\ output\ "})$;\5 -$\\{print\_int}(\\{round\_unscaled}(\\{internal}[\\{year}]))$;\5 -$\\{print\_char}(\.{"."})$;\5 -$\\{print\_dd}(\\{round\_unscaled}(\\{internal}[\\{month}]))$;\5 -$\\{print\_char}(\.{"."})$;\5 -$\\{print\_dd}(\\{round\_unscaled}(\\{internal}[\\{day}]))$;\5 -$\\{print\_char}(\.{":"})$;\6 -$\|t\K\\{round\_unscaled}(\\{internal}[\\{time}])$;\5 -$\\{print\_dd}(\|t\mathbin{\&{div}}60)$;\5 -$\\{print\_dd}(\|t\mathbin{\&{mod}}60)$;\6 -$\\{selector}\K\\{old\_setting}$;\5 -$\\{gf\_out}(\\{cur\_length})$;\5 -$\\{str\_start}[\\{str\_ptr}+1]\K\\{pool\_ptr}$;\5 -$\\{gf\_string}(0,\39\\{str\_ptr})$;\5 -$\\{pool\_ptr}\K\\{str\_start}[\\{str\_ptr}]$;\C{flush that string from memory}% -\6 -$\\{gf\_prev\_ptr}\K\\{gf\_offset}+\\{gf\_ptr}$;\6 -\&{end};\par -\fi - -\M1164. \P$\X1164:Determine the file extension, \\{gf\_ext}\X\S$\6 -\&{if} $\\{internal}[\\{hppp}]\L0$ \1\&{then}\5 -$\\{gf\_ext}\K\.{".gf"}$\6 -\4\&{else} \&{begin} \37$\\{old\_setting}\K\\{selector}$;\5 -$\\{selector}\K\\{new\_string}$;\5 -$\\{print\_char}(\.{"."})$;\5 -$\\{print\_int}(\\{make\_scaled}(\\{internal}[\\{hppp}],\3959429463))$;% -\C{$2^{32}/72.27\approx59429463.07$}\6 -$\\{print}(\.{"gf"})$;\5 -$\\{gf\_ext}\K\\{make\_string}$;\5 -$\\{selector}\K\\{old\_setting}$;\6 -\&{end}\2\par -\U1163.\fi - -\M1165. With those preliminaries out of the way, \\{ship\_out} is not -especially -difficult. - -\Y\P$\4\X1154:Declare generic font output procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37$\\{ship\_out}(\|c:\\{eight\_bits})$;\6 -\4\&{label} \37\\{done};\6 -\4\&{var} \37\|f: \37\\{integer};\C{current character extension}\6 -$\\{prev\_m},\39\|m,\39\\{mm}$: \37\\{integer};\C{previous and current pixel -column numbers}\6 -$\\{prev\_n},\39\|n$: \37\\{integer};\C{previous and current pixel row numbers}% -\6 -$\|p,\39\|q$: \37\\{pointer};\C{for list traversal}\6 -$\\{prev\_w},\39\|w,\39\\{ww}$: \37\\{integer};\C{old and new weights}\6 -\|d: \37\\{integer};\C{data from edge-weight node}\6 -\\{delta}: \37\\{integer};\C{number of rows to skip}\6 -\\{cur\_min\_m}: \37\\{integer};\C{starting column, relative to the current -offset}\6 -$\\{x\_off},\39\\{y\_off}$: \37\\{integer};\C{offsets, rounded to integers}\2\6 -\&{begin} \37\\{check\_gf};\5 -$\|f\K\\{round\_unscaled}(\\{internal}[\\{char\_ext}])$;\6 -$\\{x\_off}\K\\{round\_unscaled}(\\{internal}[\\{x\_offset}])$;\5 -$\\{y\_off}\K\\{round\_unscaled}(\\{internal}[\\{y\_offset}])$;\6 -\&{if} $\\{term\_offset}>\\{max\_print\_line}-9$ \1\&{then}\5 -\\{print\_ln}\6 -\4\&{else} \&{if} $(\\{term\_offset}>0)\V(\\{file\_offset}>0)$ \1\&{then}\5 -$\\{print\_char}(\.{"\ "})$;\2\2\6 -$\\{print\_char}(\.{"["})$;\5 -$\\{print\_int}(\|c)$;\6 -\&{if} $\|f\I0$ \1\&{then}\6 -\&{begin} \37$\\{print\_char}(\.{"."})$;\5 -$\\{print\_int}(\|f)$;\6 -\&{end};\2\6 -\\{update\_terminal};\5 -$\\{boc\_c}\K256\ast\|f+\|c$;\5 -$\\{boc\_p}\K\\{char\_ptr}[\|c]$;\5 -$\\{char\_ptr}[\|c]\K\\{gf\_prev\_ptr}$;\6 -\&{if} $\\{internal}[\\{proofing}]>0$ \1\&{then}\5 -\X1166:Send nonzero offsets to the output file\X;\2\6 -\X1167:Output the character represented in \\{cur\_edges}\X;\6 -$\\{gf\_out}(\\{eoc})$;\5 -$\\{gf\_prev\_ptr}\K\\{gf\_offset}+\\{gf\_ptr}$;\5 -$\\{incr}(\\{total\_chars})$;\5 -$\\{print\_char}(\.{"]"})$;\5 -\\{update\_terminal};\C{progress report}\6 -\&{if} $\\{internal}[\\{tracing\_output}]>0$ \1\&{then}\5 -$\\{print\_edges}(\.{"\ (just\ shipped\ out)"},\39\\{true},\39\\{x\_off},\39% -\\{y\_off})$;\2\6 -\&{end};\par -\fi - -\M1166. \P$\X1166:Send nonzero offsets to the output file\X\S$\6 -\&{begin} \37\&{if} $\\{x\_off}\I0$ \1\&{then}\6 -\&{begin} \37$\\{gf\_string}(\.{"xoffset"},\390)$;\5 -$\\{gf\_out}(\\{yyy})$;\5 -$\\{gf\_four}(\\{x\_off}\ast\\{unity})$;\6 -\&{end};\2\6 -\&{if} $\\{y\_off}\I0$ \1\&{then}\6 -\&{begin} \37$\\{gf\_string}(\.{"yoffset"},\390)$;\5 -$\\{gf\_out}(\\{yyy})$;\5 -$\\{gf\_four}(\\{y\_off}\ast\\{unity})$;\6 -\&{end};\2\6 -\&{end}\par -\U1165.\fi - -\M1167. \P$\X1167:Output the character represented in \\{cur\_edges}\X\S$\6 -$\\{prev\_n}\K4096$;\5 -$\|p\K\\{knil}(\\{cur\_edges})$;\5 -$\|n\K\\{n\_max}(\\{cur\_edges})-\\{zero\_field}$;\6 -\&{while} $\|p\I\\{cur\_edges}$ \1\&{do}\6 -\&{begin} \37\X1169:Output the pixels of edge row \|p to font row \|n\X;\6 -$\|p\K\\{knil}(\|p)$;\5 -$\\{decr}(\|n)$;\6 -\&{end};\2\6 -\&{if} $\\{prev\_n}=4096$ \1\&{then}\5 -\X1168:Finish off an entirely blank character\X\6 -\4\&{else} \&{if} $\\{prev\_n}+\\{y\_off}<\\{gf\_min\_n}$ \1\&{then}\5 -$\\{gf\_min\_n}\K\\{prev\_n}+\\{y\_off}$\2\2\par -\U1165.\fi - -\M1168. \P$\X1168:Finish off an entirely blank character\X\S$\6 -\&{begin} \37$\\{gf\_boc}(0,\390,\390,\390)$;\6 -\&{if} $\\{gf\_max\_m}<0$ \1\&{then}\5 -$\\{gf\_max\_m}\K0$;\2\6 -\&{if} $\\{gf\_min\_n}>0$ \1\&{then}\5 -$\\{gf\_min\_n}\K0$;\2\6 -\&{end}\par -\U1167.\fi - -\M1169. In this loop, \\{prev\_w} represents the weight at column \\{prev\_m}, -which is -the most recent column reflected in the output so far; \|w represents the -weight at column~\|m, which is the most recent column in the edge data. -Several edges might cancel at the same column position, so we need to -look ahead to column~\\{mm} before actually outputting anything. - -\Y\P$\4\X1169:Output the pixels of edge row \|p to font row \|n\X\S$\6 -\&{if} $\\{unsorted}(\|p)>\\{void}$ \1\&{then}\5 -$\\{sort\_edges}(\|p)$;\2\6 -$\|q\K\\{sorted}(\|p)$;\5 -$\|w\K0$;\5 -$\\{prev\_m}\K-\\{fraction\_one}$;\C{$\\{fraction\_one}\approx\infty$}\6 -$\\{ww}\K0$;\5 -$\\{prev\_w}\K0$;\5 -$\|m\K\\{prev\_m}$;\6 -\1\&{repeat} \37\&{if} $\|q=\\{sentinel}$ \1\&{then}\5 -$\\{mm}\K\\{fraction\_one}$\6 -\4\&{else} \&{begin} \37$\|d\K\\{ho}(\\{info}(\|q))$;\5 -$\\{mm}\K\|d\mathbin{\&{div}}8$;\5 -$\\{ww}\K\\{ww}+(\|d\mathbin{\&{mod}}8)-\\{zero\_w}$;\6 -\&{end};\2\6 -\&{if} $\\{mm}\I\|m$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{prev\_w}\L0$ \1\&{then}\6 -\&{begin} \37\&{if} $\|w>0$ \1\&{then}\5 -\X1170:Start black at $(m,n)$\X;\2\6 -\&{end}\6 -\4\&{else} \&{if} $\|w\L0$ \1\&{then}\5 -\X1171:Stop black at $(m,n)$\X;\2\2\6 -$\|m\K\\{mm}$;\6 -\&{end};\2\6 -$\|w\K\\{ww}$;\5 -$\|q\K\\{link}(\|q)$;\6 -\4\&{until}\5 -$\\{mm}=\\{fraction\_one}$;\2\6 -\&{if} $\|w\I0$ \1\&{then}\C{this should be impossible}\6 -$\\{print\_nl}(\.{"(There\'s\ unbounded\ black\ in\ character\ shipped\ -out!)"})$;\2\6 -\&{if} $\\{prev\_m}-\\{m\_offset}(\\{cur\_edges})+\\{x\_off}>\\{gf\_max\_m}$ \1% -\&{then}\5 -$\\{gf\_max\_m}\K\\{prev\_m}-\\{m\_offset}(\\{cur\_edges})+\\{x\_off}$\2\par -\U1167.\fi - -\M1170. \P$\X1170:Start black at $(m,n)$\X\S$\6 -\&{begin} \37\&{if} $\\{prev\_m}=-\\{fraction\_one}$ \1\&{then}\5 -\X1172:Start a new row at $(m,n)$\X\6 -\4\&{else} $\\{gf\_paint}(\|m-\\{prev\_m})$;\2\6 -$\\{prev\_m}\K\|m$;\5 -$\\{prev\_w}\K\|w$;\6 -\&{end}\par -\U1169.\fi - -\M1171. \P$\X1171:Stop black at $(m,n)$\X\S$\6 -\&{begin} \37$\\{gf\_paint}(\|m-\\{prev\_m})$;\5 -$\\{prev\_m}\K\|m$;\5 -$\\{prev\_w}\K\|w$;\6 -\&{end}\par -\U1169.\fi - -\M1172. \P$\X1172:Start a new row at $(m,n)$\X\S$\6 -\&{begin} \37\&{if} $\\{prev\_n}=4096$ \1\&{then}\6 -\&{begin} \37$\\{gf\_boc}(\\{m\_min}(\\{cur\_edges})+\\{x\_off}-\\{zero% -\_field},\39\\{m\_max}(\\{cur\_edges})+\\{x\_off}-\\{zero\_field},\39\30\\{n% -\_min}(\\{cur\_edges})+\\{y\_off}-\\{zero\_field},\39\|n+\\{y\_off})$;\5 -$\\{cur\_min\_m}\K\\{m\_min}(\\{cur\_edges})-\\{zero\_field}+\\{m\_offset}(% -\\{cur\_edges})$;\6 -\&{end}\6 -\4\&{else} \&{if} $\\{prev\_n}>\|n+1$ \1\&{then}\5 -\X1174:Skip down $\\{prev\_n}-\|n$ rows\X\6 -\4\&{else} \X1173:Skip to column $m$ in the next row and \&{goto} \\{done}, or -skip zero rows\X;\2\2\6 -$\\{gf\_paint}(\|m-\\{cur\_min\_m})$;\C{skip to column $m$, painting white}\6 -\4\\{done}: \37$\\{prev\_n}\K\|n$;\6 -\&{end}\par -\U1170.\fi - -\M1173. \P$\X1173:Skip to column $m$ in the next row and \&{goto} \\{done}, or -skip zero rows\X\S$\6 -\&{begin} \37$\\{delta}\K\|m-\\{cur\_min\_m}$;\6 -\&{if} $\\{delta}>\\{max\_new\_row}$ \1\&{then}\5 -$\\{gf\_out}(\\{skip0})$\6 -\4\&{else} \&{begin} \37$\\{gf\_out}(\\{new\_row\_0}+\\{delta})$;\5 -\&{goto} \37\\{done};\6 -\&{end};\2\6 -\&{end}\par -\U1172.\fi - -\M1174. \P$\X1174:Skip down $\\{prev\_n}-\|n$ rows\X\S$\6 -\&{begin} \37$\\{delta}\K\\{prev\_n}-\|n-1$;\6 -\&{if} $\\{delta}<\O{400}$ \1\&{then}\6 -\&{begin} \37$\\{gf\_out}(\\{skip1})$;\5 -$\\{gf\_out}(\\{delta})$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{gf\_out}(\\{skip1}+1)$;\5 -$\\{gf\_two}(\\{delta})$;\6 -\&{end};\2\6 -\&{end}\par -\U1172.\fi - -\M1175. Now that we've finished \\{ship\_out}, let's look at the other commands -by which a user can send things to the \.{GF} file. - -\Y\P$\4\X1020:Cases of \\{do\_statement} that invoke particular commands\X% -\mathrel{+}\S$\6 -\4\\{special\_command}: \37\\{do\_special};\par -\fi - -\M1176. \P$\X192:Put each of \MF's primitives into the hash table\X\mathrel{+}% -\S$\6 -$\\{primitive}(\.{"special"},\39\\{special\_command},\39\\{string\_type})$;\6 -$\\{primitive}(\.{"numspecial"},\39\\{special\_command},\39\\{known})$;\par -\fi - -\M1177. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{do\_special};\6 -\4\&{var} \37\|m: \37\\{small\_number};\C{either \\{string\_type} or \\{known}}% -\2\6 -\&{begin} \37$\|m\K\\{cur\_mod}$;\5 -\\{get\_x\_next};\5 -\\{scan\_expression};\6 -\&{if} $\\{internal}[\\{proofing}]\G0$ \1\&{then}\6 -\&{if} $\\{cur\_type}\I\|m$ \1\&{then}\5 -\X1178:Complain about improper special operation\X\6 -\4\&{else} \&{begin} \37\\{check\_gf};\6 -\&{if} $\|m=\\{string\_type}$ \1\&{then}\5 -$\\{gf\_string}(\\{cur\_exp},\390)$\6 -\4\&{else} \&{begin} \37$\\{gf\_out}(\\{yyy})$;\5 -$\\{gf\_four}(\\{cur\_exp})$;\6 -\&{end};\2\6 -\&{end};\2\2\6 -$\\{flush\_cur\_exp}(0)$;\6 -\&{end};\par -\fi - -\M1178. \P$\X1178:Complain about improper special operation\X\S$\6 -\&{begin} \37$\\{exp\_err}(\.{"Unsuitable\ expression"})$;\5 -$\\{help1}(\.{"The\ expression\ shown\ above\ has\ the\ wrong\ type\ to\ be\ -output."})$;\5 -\\{put\_get\_error};\6 -\&{end}\par -\U1177.\fi - -\M1179. \P$\X1179:Send the current expression as a title to the output file\X% -\S$\6 -\&{begin} \37\\{check\_gf};\5 -$\\{gf\_string}(\.{"title\ "},\39\\{cur\_exp})$;\6 -\&{end}\par -\U994.\fi - -\M1180. \P$\X212:Cases of \\{print\_cmd\_mod} for symbolic printing of -primitives\X\mathrel{+}\S$\6 -\4\\{special\_command}: \37\&{if} $\|m=\\{known}$ \1\&{then}\5 -$\\{print}(\.{"numspecial"})$\6 -\4\&{else} $\\{print}(\.{"special"})$;\2\par -\fi - -\M1181. \P$\X1181:Determine if a character has been shipped out\X\S$\6 -\&{begin} \37$\\{cur\_exp}\K\\{round\_unscaled}(\\{cur\_exp})\mathbin{% -\&{mod}}256$;\6 -\&{if} $\\{cur\_exp}<0$ \1\&{then}\5 -$\\{cur\_exp}\K\\{cur\_exp}+256$;\2\6 -$\\{boolean\_reset}(\\{char\_exists}[\\{cur\_exp}])$;\5 -$\\{cur\_type}\K\\{boolean\_type}$;\6 -\&{end}\par -\U906.\fi - -\M1182. At the end of the program we must finish things off by writing the -postamble. -The \.{TFM} information should have been computed first. - -An integer variable \|k and a \\{scaled} variable \|x will be declared for -use by this routine. - -\Y\P$\4\X1182:Finish the \.{GF} file\X\S$\6 -\&{begin} \37$\\{gf\_out}(\\{post})$;\C{beginning of the postamble}\6 -$\\{gf\_four}(\\{gf\_prev\_ptr})$;\5 -$\\{gf\_prev\_ptr}\K\\{gf\_offset}+\\{gf\_ptr}-5$;\C{\\{post} location}\6 -$\\{gf\_four}(\\{internal}[\\{design\_size}]\ast16)$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}4$ \1\&{do}\5 -$\\{gf\_out}(\\{header\_byte}[\|k])$;\C{the check sum}\2\6 -$\\{gf\_four}(\\{internal}[\\{hppp}])$;\5 -$\\{gf\_four}(\\{internal}[\\{vppp}])$;\6 -$\\{gf\_four}(\\{gf\_min\_m})$;\5 -$\\{gf\_four}(\\{gf\_max\_m})$;\5 -$\\{gf\_four}(\\{gf\_min\_n})$;\5 -$\\{gf\_four}(\\{gf\_max\_n})$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}255$ \1\&{do}\6 -\&{if} $\\{char\_exists}[\|k]$ \1\&{then}\6 -\&{begin} \37$\|x\K\\{gf\_dx}[\|k]\mathbin{\&{div}}\\{unity}$;\6 -\&{if} $(\\{gf\_dy}[\|k]=0)\W(\|x\G0)\W(\|x<256)\W(\\{gf\_dx}[\|k]=\|x\ast% -\\{unity})$ \1\&{then}\6 -\&{begin} \37$\\{gf\_out}(\\{char\_loc}+1)$;\5 -$\\{gf\_out}(\|k)$;\5 -$\\{gf\_out}(\|x)$;\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{gf\_out}(\\{char\_loc})$;\5 -$\\{gf\_out}(\|k)$;\5 -$\\{gf\_four}(\\{gf\_dx}[\|k])$;\5 -$\\{gf\_four}(\\{gf\_dy}[\|k])$;\6 -\&{end};\2\6 -$\|x\K\\{value}(\\{tfm\_width}[\|k])$;\6 -\&{if} $\\{abs}(\|x)>\\{max\_tfm\_dimen}$ \1\&{then}\6 -\&{if} $\|x>0$ \1\&{then}\5 -$\|x\K\\{three\_bytes}-1$\ \&{else} $\|x\K1-\\{three\_bytes}$\2\6 -\4\&{else} $\|x\K\\{make\_scaled}(\|x\ast16,\39\\{internal}[\\{design% -\_size}])$;\2\6 -$\\{gf\_four}(\|x)$;\5 -$\\{gf\_four}(\\{char\_ptr}[\|k])$;\6 -\&{end};\2\2\6 -$\\{gf\_out}(\\{post\_post})$;\5 -$\\{gf\_four}(\\{gf\_prev\_ptr})$;\5 -$\\{gf\_out}(\\{gf\_id\_byte})$;\6 -$\|k\K4+((\\{gf\_buf\_size}-\\{gf\_ptr})\mathbin{\&{mod}}4)$;\C{the number of -223's}\6 -\&{while} $\|k>0$ \1\&{do}\6 -\&{begin} \37$\\{gf\_out}(223)$;\5 -$\\{decr}(\|k)$;\6 -\&{end};\2\6 -\X1156:Empty the last bytes out of \\{gf\_buf}\X;\6 -$\\{print\_nl}(\.{"Output\ written\ on\ "})$;\5 -$\\{slow\_print}(\\{output\_file\_name})$;\5 -$\\{print}(\.{"\ ("})$;\5 -$\\{print\_int}(\\{total\_chars})$;\5 -$\\{print}(\.{"\ character"})$;\6 -\&{if} $\\{total\_chars}\I1$ \1\&{then}\5 -$\\{print\_char}(\.{"s"})$;\2\6 -$\\{print}(\.{",\ "})$;\5 -$\\{print\_int}(\\{gf\_offset}+\\{gf\_ptr})$;\5 -$\\{print}(\.{"\ bytes)."})$;\5 -$\\{b\_close}(\\{gf\_file})$;\6 -\&{end}\par -\U1206.\fi - -\N1183. \[48] Dumping and undumping the tables. -After \.{INIMF} has seen a collection of macros, it -can write all the necessary information on an auxiliary file so -that production versions of \MF\ are able to initialize their -memory at high speed. The present section of the program takes -care of such output and input. We shall consider simultaneously -the processes of storing and restoring, -so that the inverse relation between them is clear. - -The global variable \\{base\_ident} is a string that is printed right -after the \\{banner} line when \MF\ is ready to start. For \.{INIMF} this -string says simply `\.{(INIMF)}'; for other versions of \MF\ it says, -for example, `\.{(preloaded base=plain 84.2.29)}', showing the year, -month, and day that the base file was created. We have $\\{base\_ident}=0$ -before \MF's tables are loaded. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{base\_ident}: \37\\{str\_number};\par -\fi - -\M1184. \P$\X21:Set initial values of key variables\X\mathrel{+}\S$\6 -$\\{base\_ident}\K0$;\par -\fi - -\M1185. \P$\X176:Initialize table entries (done by \.{INIMF} only)\X\mathrel{+}% -\S$\6 -$\\{base\_ident}\K\.{"\ (INIMF)"}$;\par -\fi - -\M1186. \P$\X995:Declare action procedures for use by \\{do\_statement}\X% -\mathrel{+}\S$\6 -\&{init} \37\&{procedure}\1\ \37\\{store\_base\_file};\6 -\4\&{var} \37\|k: \37\\{integer};\C{all-purpose index}\6 -$\|p,\39\|q$: \37\\{pointer};\C{all-purpose pointers}\6 -\|x: \37\\{integer};\C{something to dump}\6 -\|w: \37\\{four\_quarters};\C{four ASCII codes}\2\6 -\&{begin} \37\X1200:Create the \\{base\_ident}, open the base file, and inform -the user that dumping has begun\X;\6 -\X1190:Dump constants for consistency check\X;\6 -\X1192:Dump the string pool\X;\6 -\X1194:Dump the dynamic memory\X;\6 -\X1196:Dump the table of equivalents and the hash table\X;\6 -\X1198:Dump a few more things and the closing check word\X;\6 -\X1201:Close the base file\X;\6 -\&{end};\6 -\&{tini}\par -\fi - -\M1187. Corresponding to the procedure that dumps a base file, we also have a -function -that reads~one~in. The function returns \\{false} if the dumped base is -incompatible with the present \MF\ table sizes, etc. - -\Y\P\D \37$\\{off\_base}=6666$\C{go here if the base file is unacceptable}\par -\P\D \37$\\{too\_small}(\#)\S$\1\6 -\&{begin} \37\\{wake\_up\_terminal};\5 -$\\{wterm\_ln}(\.{\'---!\ Must\ increase\ the\ \'},\39\#)$;\5 -\&{goto} \37\\{off\_base};\6 -\&{end}\2\par -\Y\P\hbox{\4}\X779:Declare the function called \\{open\_base\_file}\X\6 -\4\&{function}\1\ \37\\{load\_base\_file}: \37\\{boolean};\6 -\4\&{label} \37$\\{off\_base},\39\\{exit}$;\6 -\4\&{var} \37\|k: \37\\{integer};\C{all-purpose index}\6 -$\|p,\39\|q$: \37\\{pointer};\C{all-purpose pointers}\6 -\|x: \37\\{integer};\C{something undumped}\6 -\|w: \37\\{four\_quarters};\C{four ASCII codes}\2\6 -\&{begin} \37\X1191:Undump constants for consistency check\X;\6 -\X1193:Undump the string pool\X;\6 -\X1195:Undump the dynamic memory\X;\6 -\X1197:Undump the table of equivalents and the hash table\X;\6 -\X1199:Undump a few more things and the closing check word\X;\6 -$\\{load\_base\_file}\K\\{true}$;\5 -\&{return};\C{it worked!}\6 -\4\\{off\_base}: \37\\{wake\_up\_terminal};\5 -$\\{wterm\_ln}(\.{\'(Fatal\ base\ file\ error;\ I\'}\.{\'m\ stymied)\'})$;\5 -$\\{load\_base\_file}\K\\{false}$;\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1188. Base files consist of \\{memory\_word} items, and we use the following -macros to dump words of different types: - -\Y\P\D \37$\\{dump\_wd}(\#)\S$\1\6 -\&{begin} \37$\\{base\_file}\^\K\#$;\5 -$\\{put}(\\{base\_file})$;\ \&{end}\2\par -\P\D \37$\\{dump\_int}(\#)\S$\1\6 -\&{begin} \37$\\{base\_file}\^.\\{int}\K\#$;\5 -$\\{put}(\\{base\_file})$;\ \&{end}\2\par -\P\D \37$\\{dump\_hh}(\#)\S$\1\6 -\&{begin} \37$\\{base\_file}\^.\\{hh}\K\#$;\5 -$\\{put}(\\{base\_file})$;\ \&{end}\2\par -\P\D \37$\\{dump\_qqqq}(\#)\S$\1\6 -\&{begin} \37$\\{base\_file}\^.\\{qqqq}\K\#$;\5 -$\\{put}(\\{base\_file})$;\ \&{end}\2\par -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{base\_file}: \37\\{word\_file};\C{for input or output of base information}% -\par -\fi - -\M1189. The inverse macros are slightly more complicated, since we need to -check -the range of the values we are reading in. We say `$\\{undump}(\|a)(\|b)(\|x)$' -to -read an integer value \|x that is supposed to be in the range $\|a\L\|x\L\|b$. - -\Y\P\D \37$\\{undump\_wd}(\#)\S$\1\6 -\&{begin} \37$\\{get}(\\{base\_file})$;\5 -$\#\K\\{base\_file}\^$;\ \&{end}\2\par -\P\D \37$\\{undump\_int}(\#)\S$\1\6 -\&{begin} \37$\\{get}(\\{base\_file})$;\5 -$\#\K\\{base\_file}\^.\\{int}$;\ \&{end}\2\par -\P\D \37$\\{undump\_hh}(\#)\S$\1\6 -\&{begin} \37$\\{get}(\\{base\_file})$;\5 -$\#\K\\{base\_file}\^.\\{hh}$;\ \&{end}\2\par -\P\D \37$\\{undump\_qqqq}(\#)\S$\1\6 -\&{begin} \37$\\{get}(\\{base\_file})$;\5 -$\#\K\\{base\_file}\^.\\{qqqq}$;\ \&{end}\2\par -\P\D \37$\\{undump\_end\_end}(\#)\S\#\K\|x$;\ \&{end} \par -\P\D $\\{undump\_end}(\#)\S(\|x>\#)$ \&{then} \&{goto} \37\\{off\_base}\ % -\&{else} \37\\{undump\_end\_end}\par -\P\D $\\{undump}(\#)\S$ \6 -\&{begin} \37$\\{undump\_int}(\|x)$; \6 -\&{if} $(\|x<\#)\V\\{undump\_end}$\par -\P\D \37$\\{undump\_size\_end\_end}(\#)\S\\{too\_small}(\#)$\ \&{else} \37% -\\{undump\_end\_end}\par -\P\D \37$\\{undump\_size\_end}(\#)\S$\1\6 -\&{if} $\|x>\#$ \1\&{then}\5 -\\{undump\_size\_end\_end}\2\2\par -\P\D $\\{undump\_size}(\#)\S$ \6 -\&{begin} \37$\\{undump\_int}(\|x)$;\6 -\&{if} $\|x<\#$ \1\&{then}\5 -\&{goto} \37\\{off\_base};\2\6 -\\{undump\_size\_end}\par -\fi - -\M1190. The next few sections of the program should make it clear how we use -the -dump/undump macros. - -\Y\P$\4\X1190:Dump constants for consistency check\X\S$\6 -$\\{dump\_int}(\))$;\6 -$\\{dump\_int}(\\{mem\_min})$;\6 -$\\{dump\_int}(\\{mem\_top})$;\6 -$\\{dump\_int}(\\{hash\_size})$;\6 -$\\{dump\_int}(\\{hash\_prime})$;\6 -$\\{dump\_int}(\\{max\_in\_open})$\par -\U1186.\fi - -\M1191. Sections of a \.{WEB} program that are ``commented out'' still -contribute -strings to the string pool; therefore \.{INIMF} and \MF\ will have -the same strings. (And it is, of course, a good thing that they do.) - -\Y\P$\4\X1191:Undump constants for consistency check\X\S$\6 -$\|x\K\\{base\_file}\^.\\{int}$;\6 -\&{if} $\|x\I\)$ \1\&{then}\5 -\&{goto} \37\\{off\_base};\C{check that strings are the same}\2\6 -$\\{undump\_int}(\|x)$;\6 -\&{if} $\|x\I\\{mem\_min}$ \1\&{then}\5 -\&{goto} \37\\{off\_base};\2\6 -$\\{undump\_int}(\|x)$;\6 -\&{if} $\|x\I\\{mem\_top}$ \1\&{then}\5 -\&{goto} \37\\{off\_base};\2\6 -$\\{undump\_int}(\|x)$;\6 -\&{if} $\|x\I\\{hash\_size}$ \1\&{then}\5 -\&{goto} \37\\{off\_base};\2\6 -$\\{undump\_int}(\|x)$;\6 -\&{if} $\|x\I\\{hash\_prime}$ \1\&{then}\5 -\&{goto} \37\\{off\_base};\2\6 -$\\{undump\_int}(\|x)$;\6 -\&{if} $\|x\I\\{max\_in\_open}$ \1\&{then}\5 -\&{goto} \37\\{off\_base}\2\par -\U1187.\fi - -\M1192. \P\D \37$\\{dump\_four\_ASCII}\S\|w.\\{b0}\K\\{qi}(\\{so}(\\{str% -\_pool}[\|k]))$;\5 -$\|w.\\{b1}\K\\{qi}(\\{so}(\\{str\_pool}[\|k+1]))$;\5 -$\|w.\\{b2}\K\\{qi}(\\{so}(\\{str\_pool}[\|k+2]))$;\5 -$\|w.\\{b3}\K\\{qi}(\\{so}(\\{str\_pool}[\|k+3]))$;\5 -$\\{dump\_qqqq}(\|w)$\par -\Y\P$\4\X1192:Dump the string pool\X\S$\6 -$\\{dump\_int}(\\{pool\_ptr})$;\5 -$\\{dump\_int}(\\{str\_ptr})$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{str\_ptr}$ \1\&{do}\5 -$\\{dump\_int}(\\{str\_start}[\|k])$;\2\6 -$\|k\K0$;\6 -\&{while} $\|k+4<\\{pool\_ptr}$ \1\&{do}\6 -\&{begin} \37\\{dump\_four\_ASCII};\5 -$\|k\K\|k+4$;\6 -\&{end};\2\6 -$\|k\K\\{pool\_ptr}-4$;\5 -\\{dump\_four\_ASCII};\5 -\\{print\_ln};\5 -$\\{print\_int}(\\{str\_ptr})$;\5 -$\\{print}(\.{"\ strings\ of\ total\ length\ "})$;\5 -$\\{print\_int}(\\{pool\_ptr})$\par -\U1186.\fi - -\M1193. \P\D \37$\\{undump\_four\_ASCII}\S\\{undump\_qqqq}(\|w)$;\5 -$\\{str\_pool}[\|k]\K\\{si}(\\{qo}(\|w.\\{b0}))$;\5 -$\\{str\_pool}[\|k+1]\K\\{si}(\\{qo}(\|w.\\{b1}))$;\5 -$\\{str\_pool}[\|k+2]\K\\{si}(\\{qo}(\|w.\\{b2}))$;\5 -$\\{str\_pool}[\|k+3]\K\\{si}(\\{qo}(\|w.\\{b3}))$\par -\Y\P$\4\X1193:Undump the string pool\X\S$\6 -$\\{undump\_size}(0)(\\{pool\_size})(\.{\'string\ pool\ size\'})(\\{pool% -\_ptr})$;\5 -$\\{undump\_size}(0)(\\{max\_strings})(\.{\'max\ strings\'})(\\{str\_ptr})$;\6 -\&{for} $\|k\K0\mathrel{\&{to}}\\{str\_ptr}$ \1\&{do}\6 -\&{begin} \37$\\{undump}(0)(\\{pool\_ptr})(\\{str\_start}[\|k])$;\5 -$\\{str\_ref}[\|k]\K\\{max\_str\_ref}$;\6 -\&{end};\2\6 -$\|k\K0$;\6 -\&{while} $\|k+4<\\{pool\_ptr}$ \1\&{do}\6 -\&{begin} \37\\{undump\_four\_ASCII};\5 -$\|k\K\|k+4$;\6 -\&{end};\2\6 -$\|k\K\\{pool\_ptr}-4$;\5 -\\{undump\_four\_ASCII};\5 -$\\{init\_str\_ptr}\K\\{str\_ptr}$;\5 -$\\{init\_pool\_ptr}\K\\{pool\_ptr}$;\5 -$\\{max\_str\_ptr}\K\\{str\_ptr}$;\5 -$\\{max\_pool\_ptr}\K\\{pool\_ptr}$\par -\U1187.\fi - -\M1194. By sorting the list of available spaces in the variable-size portion of -\\{mem}, we are usually able to get by without having to dump very much -of the dynamic memory. - -We recompute \\{var\_used} and \\{dyn\_used}, so that \.{INIMF} dumps valid -information even when it has not been gathering statistics. - -\Y\P$\4\X1194:Dump the dynamic memory\X\S$\6 -\\{sort\_avail};\5 -$\\{var\_used}\K0$;\5 -$\\{dump\_int}(\\{lo\_mem\_max})$;\5 -$\\{dump\_int}(\\{rover})$;\5 -$\|p\K\\{mem\_min}$;\5 -$\|q\K\\{rover}$;\5 -$\|x\K0$;\6 -\1\&{repeat} \37\&{for} $\|k\K\|p\mathrel{\&{to}}\|q+1$ \1\&{do}\5 -$\\{dump\_wd}(\\{mem}[\|k])$;\2\6 -$\|x\K\|x+\|q+2-\|p$;\5 -$\\{var\_used}\K\\{var\_used}+\|q-\|p$;\5 -$\|p\K\|q+\\{node\_size}(\|q)$;\5 -$\|q\K\\{rlink}(\|q)$;\6 -\4\&{until}\5 -$\|q=\\{rover}$;\2\6 -$\\{var\_used}\K\\{var\_used}+\\{lo\_mem\_max}-\|p$;\5 -$\\{dyn\_used}\K\\{mem\_end}+1-\\{hi\_mem\_min}$;\6 -\&{for} $\|k\K\|p\mathrel{\&{to}}\\{lo\_mem\_max}$ \1\&{do}\5 -$\\{dump\_wd}(\\{mem}[\|k])$;\2\6 -$\|x\K\|x+\\{lo\_mem\_max}+1-\|p$;\5 -$\\{dump\_int}(\\{hi\_mem\_min})$;\5 -$\\{dump\_int}(\\{avail})$;\6 -\&{for} $\|k\K\\{hi\_mem\_min}\mathrel{\&{to}}\\{mem\_end}$ \1\&{do}\5 -$\\{dump\_wd}(\\{mem}[\|k])$;\2\6 -$\|x\K\|x+\\{mem\_end}+1-\\{hi\_mem\_min}$;\5 -$\|p\K\\{avail}$;\6 -\&{while} $\|p\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\\{decr}(\\{dyn\_used})$;\5 -$\|p\K\\{link}(\|p)$;\6 -\&{end};\2\6 -$\\{dump\_int}(\\{var\_used})$;\5 -$\\{dump\_int}(\\{dyn\_used})$;\5 -\\{print\_ln};\5 -$\\{print\_int}(\|x)$;\5 -$\\{print}(\.{"\ memory\ locations\ dumped;\ current\ usage\ is\ "})$;\5 -$\\{print\_int}(\\{var\_used})$;\5 -$\\{print\_char}(\.{"\&"})$;\5 -$\\{print\_int}(\\{dyn\_used})$\par -\U1186.\fi - -\M1195. \P$\X1195:Undump the dynamic memory\X\S$\6 -$\\{undump}(\\{lo\_mem\_stat\_max}+1000)(\\{hi\_mem\_stat\_min}-1)(\\{lo\_mem% -\_max})$;\5 -$\\{undump}(\\{lo\_mem\_stat\_max}+1)(\\{lo\_mem\_max})(\\{rover})$;\5 -$\|p\K\\{mem\_min}$;\5 -$\|q\K\\{rover}$;\6 -\1\&{repeat} \37\&{for} $\|k\K\|p\mathrel{\&{to}}\|q+1$ \1\&{do}\5 -$\\{undump\_wd}(\\{mem}[\|k])$;\2\6 -$\|p\K\|q+\\{node\_size}(\|q)$;\6 -\&{if} $(\|p>\\{lo\_mem\_max})\V((\|q\G\\{rlink}(\|q))\W(\\{rlink}(\|q)\I% -\\{rover}))$ \1\&{then}\5 -\&{goto} \37\\{off\_base};\2\6 -$\|q\K\\{rlink}(\|q)$;\6 -\4\&{until}\5 -$\|q=\\{rover}$;\2\6 -\&{for} $\|k\K\|p\mathrel{\&{to}}\\{lo\_mem\_max}$ \1\&{do}\5 -$\\{undump\_wd}(\\{mem}[\|k])$;\2\6 -$\\{undump}(\\{lo\_mem\_max}+1)(\\{hi\_mem\_stat\_min})(\\{hi\_mem\_min})$;\5 -$\\{undump}(\\{null})(\\{mem\_top})(\\{avail})$;\5 -$\\{mem\_end}\K\\{mem\_top}$;\6 -\&{for} $\|k\K\\{hi\_mem\_min}\mathrel{\&{to}}\\{mem\_end}$ \1\&{do}\5 -$\\{undump\_wd}(\\{mem}[\|k])$;\2\6 -$\\{undump\_int}(\\{var\_used})$;\5 -$\\{undump\_int}(\\{dyn\_used})$\par -\U1187.\fi - -\M1196. A different scheme is used to compress the hash table, since its lower -region -is usually sparse. When $\\{text}(\|p)\I0$ for $\|p\L\\{hash\_used}$, we output -three -words: \|p, $\\{hash}[\|p]$, and $\\{eqtb}[\|p]$. The hash table is, of course, -densely -packed for $\|p\G\\{hash\_used}$, so the remaining entries are output -in~a~block. - -\Y\P$\4\X1196:Dump the table of equivalents and the hash table\X\S$\6 -$\\{dump\_int}(\\{hash\_used})$;\5 -$\\{st\_count}\K\\{frozen\_inaccessible}-1-\\{hash\_used}$;\6 -\&{for} $\|p\K1\mathrel{\&{to}}\\{hash\_used}$ \1\&{do}\6 -\&{if} $\\{text}(\|p)\I0$ \1\&{then}\6 -\&{begin} \37$\\{dump\_int}(\|p)$;\5 -$\\{dump\_hh}(\\{hash}[\|p])$;\5 -$\\{dump\_hh}(\\{eqtb}[\|p])$;\5 -$\\{incr}(\\{st\_count})$;\6 -\&{end};\2\2\6 -\&{for} $\|p\K\\{hash\_used}+1\mathrel{\&{to}}\\{hash\_end}$ \1\&{do}\6 -\&{begin} \37$\\{dump\_hh}(\\{hash}[\|p])$;\5 -$\\{dump\_hh}(\\{eqtb}[\|p])$;\6 -\&{end};\2\6 -$\\{dump\_int}(\\{st\_count})$;\6 -\\{print\_ln};\5 -$\\{print\_int}(\\{st\_count})$;\5 -$\\{print}(\.{"\ symbolic\ tokens"})$\par -\U1186.\fi - -\M1197. \P$\X1197:Undump the table of equivalents and the hash table\X\S$\6 -$\\{undump}(1)(\\{frozen\_inaccessible})(\\{hash\_used})$;\5 -$\|p\K0$;\6 -\1\&{repeat} \37$\\{undump}(\|p+1)(\\{hash\_used})(\|p)$;\5 -$\\{undump\_hh}(\\{hash}[\|p])$;\5 -$\\{undump\_hh}(\\{eqtb}[\|p])$;\6 -\4\&{until}\5 -$\|p=\\{hash\_used}$;\2\6 -\&{for} $\|p\K\\{hash\_used}+1\mathrel{\&{to}}\\{hash\_end}$ \1\&{do}\6 -\&{begin} \37$\\{undump\_hh}(\\{hash}[\|p])$;\5 -$\\{undump\_hh}(\\{eqtb}[\|p])$;\6 -\&{end};\2\6 -$\\{undump\_int}(\\{st\_count})$\par -\U1187.\fi - -\M1198. We have already printed a lot of statistics, so we set $\\{tracing% -\_stats}\K0$ -to prevent them from appearing again. - -\Y\P$\4\X1198:Dump a few more things and the closing check word\X\S$\6 -$\\{dump\_int}(\\{int\_ptr})$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}\\{int\_ptr}$ \1\&{do}\6 -\&{begin} \37$\\{dump\_int}(\\{internal}[\|k])$;\5 -$\\{dump\_int}(\\{int\_name}[\|k])$;\6 -\&{end};\2\6 -$\\{dump\_int}(\\{start\_sym})$;\5 -$\\{dump\_int}(\\{interaction})$;\5 -$\\{dump\_int}(\\{base\_ident})$;\5 -$\\{dump\_int}(\\{bg\_loc})$;\5 -$\\{dump\_int}(\\{eg\_loc})$;\5 -$\\{dump\_int}(\\{serial\_no})$;\5 -$\\{dump\_int}(69069)$;\5 -$\\{internal}[\\{tracing\_stats}]\K0$\par -\U1186.\fi - -\M1199. \P$\X1199:Undump a few more things and the closing check word\X\S$\6 -$\\{undump}(\\{max\_given\_internal})(\\{max\_internal})(\\{int\_ptr})$;\6 -\&{for} $\|k\K1\mathrel{\&{to}}\\{int\_ptr}$ \1\&{do}\6 -\&{begin} \37$\\{undump\_int}(\\{internal}[\|k])$;\5 -$\\{undump}(0)(\\{str\_ptr})(\\{int\_name}[\|k])$;\6 -\&{end};\2\6 -$\\{undump}(0)(\\{frozen\_inaccessible})(\\{start\_sym})$;\5 -$\\{undump}(\\{batch\_mode})(\\{error\_stop\_mode})(\\{interaction})$;\5 -$\\{undump}(0)(\\{str\_ptr})(\\{base\_ident})$;\5 -$\\{undump}(1)(\\{hash\_end})(\\{bg\_loc})$;\5 -$\\{undump}(1)(\\{hash\_end})(\\{eg\_loc})$;\5 -$\\{undump\_int}(\\{serial\_no})$;\6 -$\\{undump\_int}(\|x)$;\ \&{if} $(\|x\I69069)\V\\{eof}(\\{base\_file})$ \1% -\&{then}\5 -\&{goto} \37\\{off\_base}\2\par -\U1187.\fi - -\M1200. \P$\X1200:Create the \\{base\_ident}, open the base file, and inform -the user that dumping has begun\X\S$\6 -$\\{selector}\K\\{new\_string}$;\5 -$\\{print}(\.{"\ (preloaded\ base="})$;\5 -$\\{print}(\\{job\_name})$;\5 -$\\{print\_char}(\.{"\ "})$;\5 -$\\{print\_int}(\\{round\_unscaled}(\\{internal}[\\{year}]))$;\5 -$\\{print\_char}(\.{"."})$;\5 -$\\{print\_int}(\\{round\_unscaled}(\\{internal}[\\{month}]))$;\5 -$\\{print\_char}(\.{"."})$;\5 -$\\{print\_int}(\\{round\_unscaled}(\\{internal}[\\{day}]))$;\5 -$\\{print\_char}(\.{")"})$;\6 -\&{if} $\\{interaction}=\\{batch\_mode}$ \1\&{then}\5 -$\\{selector}\K\\{log\_only}$\6 -\4\&{else} $\\{selector}\K\\{term\_and\_log}$;\2\6 -$\\{str\_room}(1)$;\5 -$\\{base\_ident}\K\\{make\_string}$;\5 -$\\{str\_ref}[\\{base\_ident}]\K\\{max\_str\_ref}$;\6 -$\\{pack\_job\_name}(\\{base\_extension})$;\6 -\&{while} $\R\\{w\_open\_out}(\\{base\_file})$ \1\&{do}\5 -$\\{prompt\_file\_name}(\.{"base\ file\ name"},\39\\{base\_extension})$;\2\6 -$\\{print\_nl}(\.{"Beginning\ to\ dump\ on\ file\ "})$;\5 -$\\{slow\_print}(\\{w\_make\_name\_string}(\\{base\_file}))$;\5 -$\\{flush\_string}(\\{str\_ptr}-1)$;\5 -$\\{print\_nl}(\.{""})$;\5 -$\\{slow\_print}(\\{base\_ident})$\par -\U1186.\fi - -\M1201. \P$\X1201:Close the base file\X\S$\6 -$\\{w\_close}(\\{base\_file})$\par -\U1186.\fi - -\N1202. \[49] The main program. -This is it: the part of \MF\ that executes all those procedures we have -written. - -Well---almost. We haven't put the parsing subroutines into the -program yet; and we'd better leave space for a few more routines that may -have been forgotten. - -\Y\P\X823:Declare the basic parsing subroutines\X\6 -\X224:Declare miscellaneous procedures that were declared \\{forward}\X\6 -\X1205:Last-minute procedures\X\par -\fi - -\M1203. We've noted that there are two versions of \MF84. One, called % -\.{INIMF}, -has to be run first; it initializes everything from scratch, without -reading a base file, and it has the capability of dumping a base file. -The other one is called `\.{VIRMF}'; it is a ``virgin'' program that needs -to input a base file in order to get started. \.{VIRMF} typically has -a bit more memory capacity than \.{INIMF}, because it does not need the -space consumed by the dumping/undumping routines and the numerous calls on -\\{primitive}, etc. - -The \.{VIRMF} program cannot read a base file instantaneously, of course; -the best implementations therefore allow for production versions of \MF\ that -not only avoid the loading routine for \PASCAL\ object code, they also have -a base file pre-loaded. This is impossible to do if we stick to standard -\PASCAL; but there is a simple way to fool many systems into avoiding the -initialization, as follows:\quad(1)~We declare a global integer variable -called \\{ready\_already}. The probability is negligible that this -variable holds any particular value like 314159 when \.{VIRMF} is first -loaded.\quad(2)~After we have read in a base file and initialized -everything, we set $\\{ready\_already}\K314159$.\quad(3)~Soon \.{VIRMF} -will print `\.*', waiting for more input; and at this point we -interrupt the program and save its core image in some form that the -operating system can reload speedily.\quad(4)~When that core image is -activated, the program starts again at the beginning; but now -$\\{ready\_already}=314159$ and all the other global variables have -their initial values too. The former chastity has vanished! - -In other words, if we allow ourselves to test the condition -$\\{ready\_already}=314159$, before \\{ready\_already} has been -assigned a value, we can avoid the lengthy initialization. Dirty tricks -rarely pay off so handsomely. - -On systems that allow such preloading, the standard program called \.{MF} -should be the one that has \.{plain} base preloaded, since that agrees -with {\sl The {\logos METAFONT\/}book}. Other versions, e.g., \.{cmbase}, -should also be provided for commonly used bases. - -\Y\P$\4\X13:Global variables\X\mathrel{+}\S$\6 -\4\\{ready\_already}: \37\\{integer};\C{a sacrifice of purity for economy}\par -\fi - -\M1204. Now this is really it: \MF\ starts and ends here. - -The initial test involving \\{ready\_already} should be deleted if the -\PASCAL\ runtime system is smart enough to detect such a ``mistake.'' - -\Y\P\&{begin} \37\C{\\{start\_here}}\6 -$\\{history}\K\\{fatal\_error\_stop}$;\C{in case we quit during initialization}% -\6 -\\{t\_open\_out};\C{open the terminal for output}\6 -\&{if} $\\{ready\_already}=314159$ \1\&{then}\5 -\&{goto} \37\\{start\_of\_MF};\2\6 -\X14:Check the ``constant'' values for consistency\X\6 -\&{if} $\\{bad}>0$ \1\&{then}\6 -\&{begin} \37$\\{wterm\_ln}(\.{\'Ouch---my\ internal\ constants\ have\ been\ -clobbered!\'},\39\.{\'---case\ \'},\39\\{bad}:1)$;\5 -\&{goto} \37\\{final\_end};\6 -\&{end};\2\6 -\\{initialize};\C{set global variables to their starting values}\6 -\&{init} \37\&{if} $\R\\{get\_strings\_started}$ \1\&{then}\5 -\&{goto} \37\\{final\_end};\2\6 -\\{init\_tab};\C{initialize the tables}\6 -\\{init\_prim};\C{call \\{primitive} for each primitive}\6 -$\\{init\_str\_ptr}\K\\{str\_ptr}$;\5 -$\\{init\_pool\_ptr}\K\\{pool\_ptr}$;\6 -$\\{max\_str\_ptr}\K\\{str\_ptr}$;\5 -$\\{max\_pool\_ptr}\K\\{pool\_ptr}$;\5 -\\{fix\_date\_and\_time};\6 -\&{tini}\6 -$\\{ready\_already}\K314159$;\6 -\4\\{start\_of\_MF}: \37\X55:Initialize the output routines\X;\6 -\X1211:Get the first line of input and prepare to start\X;\6 -$\\{history}\K\\{spotless}$;\C{ready to go!}\6 -\&{if} $\\{start\_sym}>0$ \1\&{then}\C{insert the `\&{everyjob}' symbol}\6 -\&{begin} \37$\\{cur\_sym}\K\\{start\_sym}$;\5 -\\{back\_input};\6 -\&{end};\2\6 -\\{main\_control};\C{come to life}\6 -\\{final\_cleanup};\C{prepare for death}\6 -\4\\{end\_of\_MF}: \37\\{close\_files\_and\_terminate};\6 -\4\\{final\_end}: \37$\\{ready\_already}\K0$;\6 -\&{end}.\par -\fi - -\M1205. Here we do whatever is needed to complete \MF's job gracefully on the -local operating system. The code here might come into play after a fatal -error; it must therefore consist entirely of ``safe'' operations that -cannot produce error messages. For example, it would be a mistake to call -\\{str\_room} or \\{make\_string} at this time, because a call on \\{overflow} -might lead to an infinite loop. - -This program doesn't bother to close the input files that may still be open. - -\Y\P$\4\X1205:Last-minute procedures\X\S$\6 -\4\&{procedure}\1\ \37\\{close\_files\_and\_terminate};\6 -\4\&{var} \37\|k: \37\\{integer};\C{all-purpose index}\6 -\\{lh}: \37\\{integer};\C{the length of the \.{TFM} header, in words}\6 -\\{lk\_offset}: \37$0\to256$;\C{extra words inserted at beginning of \\{lig% -\_kern} array}\6 -\|p: \37\\{pointer};\C{runs through a list of \.{TFM} dimensions}\6 -\|x: \37\\{scaled};\C{a \\{tfm\_width} value being output to the \.{GF} file}\2% -\6 -\&{begin} \37\&{stat} \37\&{if} $\\{internal}[\\{tracing\_stats}]>0$ \1\&{then}% -\5 -\X1208:Output statistics about this job\X;\2\ \&{tats}\6 -\\{wake\_up\_terminal};\5 -\X1206:Finish the \.{TFM} and \.{GF} files\X;\6 -\&{if} $\\{log\_opened}$ \1\&{then}\6 -\&{begin} \37\\{wlog\_cr};\5 -$\\{a\_close}(\\{log\_file})$;\5 -$\\{selector}\K\\{selector}-2$;\6 -\&{if} $\\{selector}=\\{term\_only}$ \1\&{then}\6 -\&{begin} \37$\\{print\_nl}(\.{"Transcript\ written\ on\ "})$;\5 -$\\{slow\_print}(\\{log\_name})$;\5 -$\\{print\_char}(\.{"."})$;\6 -\&{end};\2\6 -\&{end};\2\6 -\&{end};\par -\As1209, 1210\ETs1212. -\U1202.\fi - -\M1206. We want to finish the \.{GF} file if and only if it has already been -started; -this will be true if and only if \\{gf\_prev\_ptr} is positive. -We want to produce a \.{TFM} file if and only if \\{fontmaking} is positive. -The \.{TFM} widths must be computed if there's a \.{GF} file, even if -there's going to be no \.{TFM}~file. - -We reclaim all of the variable-size memory at this point, so that -there is no chance of another memory overflow after the memory capacity -has already been exceeded. - -\Y\P$\4\X1206:Finish the \.{TFM} and \.{GF} files\X\S$\6 -\&{if} $(\\{gf\_prev\_ptr}>0)\V(\\{internal}[\\{fontmaking}]>0)$ \1\&{then}\6 -\&{begin} \37\X1207:Make the dynamic memory into one big available node\X;\6 -\X1124:Massage the \.{TFM} widths\X;\6 -\\{fix\_design\_size};\5 -\\{fix\_check\_sum};\6 -\&{if} $\\{internal}[\\{fontmaking}]>0$ \1\&{then}\6 -\&{begin} \37\X1126:Massage the \.{TFM} heights, depths, and italic corrections% -\X;\6 -$\\{internal}[\\{fontmaking}]\K0$;\C{avoid loop in case of fatal error}\6 -\X1134:Finish the \.{TFM} file\X;\6 -\&{end};\2\6 -\&{if} $\\{gf\_prev\_ptr}>0$ \1\&{then}\5 -\X1182:Finish the \.{GF} file\X;\2\6 -\&{end}\2\par -\U1205.\fi - -\M1207. \P$\X1207:Make the dynamic memory into one big available node\X\S$\6 -$\\{rover}\K\\{lo\_mem\_stat\_max}+1$;\5 -$\\{link}(\\{rover})\K\\{empty\_flag}$;\5 -$\\{lo\_mem\_max}\K\\{hi\_mem\_min}-1$;\6 -\&{if} $\\{lo\_mem\_max}-\\{rover}>\\{max\_halfword}$ \1\&{then}\5 -$\\{lo\_mem\_max}\K\\{max\_halfword}+\\{rover}$;\2\6 -$\\{node\_size}(\\{rover})\K\\{lo\_mem\_max}-\\{rover}$;\5 -$\\{llink}(\\{rover})\K\\{rover}$;\5 -$\\{rlink}(\\{rover})\K\\{rover}$;\5 -$\\{link}(\\{lo\_mem\_max})\K\\{null}$;\5 -$\\{info}(\\{lo\_mem\_max})\K\\{null}$\par -\U1206.\fi - -\M1208. The present section goes directly to the log file instead of using -\\{print} commands, because there's no need for these strings to take -up \\{str\_pool} memory when a non-{\bf stat} version of \MF\ is being used. - -\Y\P$\4\X1208:Output statistics about this job\X\S$\6 -\&{if} $\\{log\_opened}$ \1\&{then}\6 -\&{begin} \37$\\{wlog\_ln}(\.{\'\ \'})$;\5 -$\\{wlog\_ln}(\.{\'Here\ is\ how\ much\ of\ METAFONT\'}\.{\'s\ memory\'},\39\.{% -\'\ you\ used:\'})$;\5 -$\\{wlog}(\.{\'\ \'},\39\\{max\_str\_ptr}-\\{init\_str\_ptr}:1,\39\.{\'\ string% -\'})$;\6 -\&{if} $\\{max\_str\_ptr}\I\\{init\_str\_ptr}+1$ \1\&{then}\5 -$\\{wlog}(\.{\'s\'})$;\2\6 -$\\{wlog\_ln}(\.{\'\ out\ of\ \'},\39\\{max\_strings}-\\{init\_str\_ptr}:1)$;\6 -$\\{wlog\_ln}(\.{\'\ \'},\39\\{max\_pool\_ptr}-\\{init\_pool\_ptr}:1,\39\.{\'\ -string\ characters\ out\ of\ \'},\39\\{pool\_size}-\\{init\_pool\_ptr}:1)$;\6 -$\\{wlog\_ln}(\.{\'\ \'},\39\\{lo\_mem\_max}-\\{mem\_min}+\\{mem\_end}-\\{hi% -\_mem\_min}+2:1,\39\30\.{\'\ words\ of\ memory\ out\ of\ \'},\39\\{mem\_end}+1-% -\\{mem\_min}:1)$;\6 -$\\{wlog\_ln}(\.{\'\ \'},\39\\{st\_count}:1,\39\.{\'\ symbolic\ tokens\ out\ of% -\ \'},\39\\{hash\_size}:1)$;\6 -$\\{wlog\_ln}(\.{\'\ \'},\39\\{max\_in\_stack}:1,\39\.{\'i,\'},\39\30\\{int% -\_ptr}:1,\39\.{\'n,\'},\39\30\\{max\_rounding\_ptr}:1,\39\.{\'r,\'},\39\30% -\\{max\_param\_stack}:1,\39\.{\'p,\'},\39\30\\{max\_buf\_stack}+1:1,\39\.{\'b\ -stack\ positions\ out\ of\ \'},\39\30\\{stack\_size}:1,\39\.{\'i,\'},\39\\{max% -\_internal}:1,\39\.{\'n,\'},\39\\{max\_wiggle}:1,\39\.{\'r,\'},\39\\{param% -\_size}:1,\39\.{\'p,\'},\39\\{buf\_size}:1,\39\.{\'b\'})$;\6 -\&{end}\2\par -\U1205.\fi - -\M1209. We get to the \\{final\_cleanup} routine when \&{end} or \&{dump} has -been scanned. - -\Y\P$\4\X1205:Last-minute procedures\X\mathrel{+}\S$\6 -\4\&{procedure}\1\ \37\\{final\_cleanup};\6 -\4\&{label} \37\\{exit};\6 -\4\&{var} \37\|c: \37\\{small\_number};\C{0 for \&{end}, 1 for \&{dump}}\2\6 -\&{begin} \37$\|c\K\\{cur\_mod}$;\6 -\&{if} $\\{job\_name}=0$ \1\&{then}\5 -\\{open\_log\_file};\2\6 -\&{while} $\\{input\_ptr}>0$ \1\&{do}\6 -\&{if} $\\{token\_state}$ \1\&{then}\5 -\\{end\_token\_list}\ \&{else} \\{end\_file\_reading};\2\2\6 -\&{while} $\\{loop\_ptr}\I\\{null}$ \1\&{do}\5 -\\{stop\_iteration};\2\6 -\&{while} $\\{open\_parens}>0$ \1\&{do}\6 -\&{begin} \37$\\{print}(\.{"\ )"})$;\5 -$\\{decr}(\\{open\_parens})$;\6 -\&{end};\2\6 -\&{while} $\\{cond\_ptr}\I\\{null}$ \1\&{do}\6 -\&{begin} \37$\\{print\_nl}(\.{"(end\ occurred\ when\ "})$;\6 -$\\{print\_cmd\_mod}(\\{fi\_or\_else},\39\\{cur\_if})$;\C{`\.{if}' or `% -\.{elseif}' or `\.{else}'}\6 -\&{if} $\\{if\_line}\I0$ \1\&{then}\6 -\&{begin} \37$\\{print}(\.{"\ on\ line\ "})$;\5 -$\\{print\_int}(\\{if\_line})$;\6 -\&{end};\2\6 -$\\{print}(\.{"\ was\ incomplete)"})$;\5 -$\\{if\_line}\K\\{if\_line\_field}(\\{cond\_ptr})$;\5 -$\\{cur\_if}\K\\{name\_type}(\\{cond\_ptr})$;\5 -$\\{loop\_ptr}\K\\{cond\_ptr}$;\5 -$\\{cond\_ptr}\K\\{link}(\\{cond\_ptr})$;\5 -$\\{free\_node}(\\{loop\_ptr},\39\\{if\_node\_size})$;\6 -\&{end};\2\6 -\&{if} $\\{history}\I\\{spotless}$ \1\&{then}\6 -\&{if} $((\\{history}=\\{warning\_issued})\V(\\{interaction}<\\{error\_stop% -\_mode}))$ \1\&{then}\6 -\&{if} $\\{selector}=\\{term\_and\_log}$ \1\&{then}\6 -\&{begin} \37$\\{selector}\K\\{term\_only}$;\5 -$\\{print\_nl}(\.{"(see\ the\ transcript\ file\ for\ additional\ -information)"})$;\5 -$\\{selector}\K\\{term\_and\_log}$;\6 -\&{end};\2\2\2\6 -\&{if} $\|c=1$ \1\&{then}\6 -\&{begin} \37\&{init} \37\\{store\_base\_file};\5 -\&{return};\ \&{tini}\6 -$\\{print\_nl}(\.{"(dump\ is\ performed\ only\ by\ INIMF)"})$;\5 -\&{return};\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\par -\fi - -\M1210. \P$\X1205:Last-minute procedures\X\mathrel{+}\S$\6 -\&{init} \37\&{procedure}\1\ \37\\{init\_prim};\C{initialize all the -primitives}\2\6 -\&{begin} \37\X192:Put each of \MF's primitives into the hash table\X;\6 -\&{end};\7 -\4\&{procedure}\1\ \37\\{init\_tab};\C{initialize other tables}\6 -\4\&{var} \37\|k: \37\\{integer};\C{all-purpose index}\2\6 -\&{begin} \37\X176:Initialize table entries (done by \.{INIMF} only)\X\6 -\&{end};\6 -\&{tini}\par -\fi - -\M1211. When we begin the following code, \MF's tables may still contain -garbage; -the strings might not even be present. Thus we must proceed cautiously to get -bootstrapped in. - -But when we finish this part of the program, \MF\ is ready to call on the -\\{main\_control} routine to do its work. - -\Y\P$\4\X1211:Get the first line of input and prepare to start\X\S$\6 -\&{begin} \37\X657:Initialize the input routines\X;\6 -\&{if} $(\\{base\_ident}=0)\V(\\{buffer}[\\{loc}]=\.{"\&"})$ \1\&{then}\6 -\&{begin} \37\&{if} $\\{base\_ident}\I0$ \1\&{then}\5 -\\{initialize};\C{erase preloaded base}\2\6 -\&{if} $\R\\{open\_base\_file}$ \1\&{then}\5 -\&{goto} \37\\{final\_end};\2\6 -\&{if} $\R\\{load\_base\_file}$ \1\&{then}\6 -\&{begin} \37$\\{w\_close}(\\{base\_file})$;\5 -\&{goto} \37\\{final\_end};\6 -\&{end};\2\6 -$\\{w\_close}(\\{base\_file})$;\6 -\&{while} $(\\{loc}<\\{limit})\W(\\{buffer}[\\{loc}]=\.{"\ "})$ \1\&{do}\5 -$\\{incr}(\\{loc})$;\2\6 -\&{end};\2\6 -$\\{buffer}[\\{limit}]\K\.{"\%"}$;\6 -\\{fix\_date\_and\_time};\5 -$\\{init\_randoms}((\\{internal}[\\{time}]\mathbin{\&{div}}\\{unity})+% -\\{internal}[\\{day}])$;\6 -\X70:Initialize the print \\{selector} based on \\{interaction}\X;\6 -\&{if} $\\{loc}<\\{limit}$ \1\&{then}\6 -\&{if} $\\{buffer}[\\{loc}]\I\.{"\\"}$ \1\&{then}\5 -\\{start\_input};\C{\&{input} assumed}\2\2\6 -\&{end}\par -\U1204.\fi - -\N1212. \[50] Debugging. -Once \MF\ is working, you should be able to diagnose most errors with -the \.{show} commands and other diagnostic features. But for the initial -stages of debugging, and for the revelation of really deep mysteries, you -can compile \MF\ with a few more aids, including the \PASCAL\ runtime -checks and its debugger. An additional routine called \\{debug\_help} -will also come into play when you type `\.D' after an error message; -\\{debug\_help} also occurs just before a fatal error causes \MF\ to succumb. - -The interface to \\{debug\_help} is primitive, but it is good enough when used -with a \PASCAL\ debugger that allows you to set breakpoints and to read -variables and change their values. After getting the prompt `\.{debug \#}', you -type either a negative number (this exits \\{debug\_help}), or zero (this -goes to a location where you can set a breakpoint, thereby entering into -dialog with the \PASCAL\ debugger), or a positive number \|m followed by -an argument \|n. The meaning of \|m and \|n will be clear from the -program below. (If $\|m=13$, there is an additional argument, \|l.) - -\Y\P\D \37$\\{breakpoint}=888$\C{place where a breakpoint is desirable}\par -\Y\P$\4\X1205:Last-minute procedures\X\mathrel{+}\S$\6 -\&{debug} \37\&{procedure}\1\ \37\\{debug\_help};\C{routine to display various -things}\6 -\4\&{label} \37$\\{breakpoint},\39\\{exit}$;\6 -\4\&{var} \37$\|k,\39\|l,\39\|m,\39\|n$: \37\\{integer};\2\6 -\&{begin} \37\~ \1\&{loop}\6 -\&{begin} \37\\{wake\_up\_terminal};\5 -$\\{print\_nl}(\.{"debug\ \#\ (-1\ to\ exit):"})$;\5 -\\{update\_terminal};\5 -$\\{read}(\\{term\_in},\39\|m)$;\6 -\&{if} $\|m<0$ \1\&{then}\5 -\&{return}\6 -\4\&{else} \&{if} $\|m=0$ \1\&{then}\6 -\&{begin} \37\&{goto} \37\\{breakpoint};\5 -\]\C{go to every label at least once}\6 -\4\\{breakpoint}: \37$\|m\K0$;\5 -$\B\.{\'BREAKPOINT\'}\T\]$\6 -\&{end}\6 -\4\&{else} \&{begin} \37$\\{read}(\\{term\_in},\39\|n)$;\6 -\&{case} $\|m$ \1\&{of}\6 -\hbox{\4}\X1213:Numbered cases for \\{debug\_help}\X\6 -\4\&{othercases} \37$\\{print}(\.{"?"})$\2\6 -\&{endcases};\6 -\&{end};\2\2\6 -\&{end};\2\6 -\4\\{exit}: \37\&{end};\6 -\&{gubed}\par -\fi - -\M1213. \P$\X1213:Numbered cases for \\{debug\_help}\X\S$\6 -\41: \37$\\{print\_word}(\\{mem}[\|n])$;\C{display $\\{mem}[\|n]$ in all forms}% -\6 -\42: \37$\\{print\_int}(\\{info}(\|n))$;\6 -\43: \37$\\{print\_int}(\\{link}(\|n))$;\6 -\44: \37\&{begin} \37$\\{print\_int}(\\{eq\_type}(\|n))$;\5 -$\\{print\_char}(\.{":"})$;\5 -$\\{print\_int}(\\{equiv}(\|n))$;\6 -\&{end};\6 -\45: \37$\\{print\_variable\_name}(\|n)$;\6 -\46: \37$\\{print\_int}(\\{internal}[\|n])$;\6 -\47: \37\\{do\_show\_dependencies};\6 -\49: \37$\\{show\_token\_list}(\|n,\39\\{null},\39100000,\390)$;\6 -\410: \37$\\{slow\_print}(\|n)$;\6 -\411: \37$\\{check\_mem}(\|n>0)$;\C{check wellformedness; print new busy -locations if $\|n>0$}\6 -\412: \37$\\{search\_mem}(\|n)$;\C{look for pointers to \|n}\6 -\413: \37\&{begin} \37$\\{read}(\\{term\_in},\39\|l)$;\5 -$\\{print\_cmd\_mod}(\|n,\39\|l)$;\6 -\&{end};\6 -\414: \37\&{for} $\|k\K0\mathrel{\&{to}}\|n$ \1\&{do}\5 -$\\{print}(\\{buffer}[\|k])$;\2\6 -\415: \37$\\{panicking}\K\R\\{panicking}$;\par -\U1212.\fi - -\N1214. \[51] System-dependent changes. -This section should be replaced, if necessary, by any special -modifications of the program -that are necessary to make \MF\ work at a particular installation. -It is usually best to design your change file so that all changes to -previous sections preserve the section numbering; then everybody's version -will be consistent with the published program. More extensive changes, -which introduce new sections, can be inserted here; then only the index -itself will get a new section number. - -\fi - -\N1215. \[52] Index. -Here is where you can find all uses of each identifier in the program, -with underlined entries pointing to where the identifier was defined. -If the identifier is only one letter long, however, you get to see only -the underlined entries. {\sl All references are to section numbers instead of -page numbers.} - -This index also lists error messages and other aspects of the program -that you might want to look up some day. For example, the entry -for ``system dependencies'' lists all sections that should receive -special attention from people who are installing \MF\ in a new -operating environment. A list of various things that can't happen appears -under ``this can't happen''. -Approximately 25 sections are listed under ``inner loop''; these account -for more than 60\pct! of \MF's running time, exclusive of input and output. -\fi - - -\inx -\:\9{!!!}{\.{\&} primitive}, \[893]. -\:\.{!\relax}, 68, 807. -\:\9{* }{\.{*} primitive}, \[893]. -\:\.{**}, 36, 788. -\:\.{*\relax}, 679. -\:\9{+ }{\.{+} primitive}, \[893]. -\:\9{++\_}{\.{++} primitive}, \[893]. -\:\9{+-+\_}{\.{+-+} primitive}, \[893]. -\:\9{, }{\., primitive}, \[211]. -\:\9{- }{\.{-} primitive}, \[893]. -\:\.{->}, 227. -\:\9{. }{\..\ token}, 669. -\:\9{..\_}{\.{..} primitive}, \[211]. -\:\9{/ }{\.{/} primitive}, \[893]. -\:\9{: }{\.{:} primitive}, \[211]. -\:\9{:: }{\.{::} primitive}, \[211]. -\:\9{::: }{\.{\char'174\char'174:} primitive}, \[211]. -\:\9{:=\_}{\.{:=} primitive}, \[211]. -\:\9{; }{\.; primitive}, \[211]. -\:\9{< }{\.{<} primitive}, \[893]. -\:\9{<=\_}{\.{<=} primitive}, \[893]. -\:\9{<>\_}{\.{<>} primitive}, \[893]. -\:\9{= }{\.{=} primitive}, \[893]. -\:\9{=:/>\_}{\.{=:\char'174>} primitive}, \[1108]. -\:\9{=:/>\_}{\.{\char'174=:>} primitive}, \[1108]. -\:\9{=:/>\_}{\.{\char'174=:\char'174>>} primitive}, \[1108]. -\:\9{=:/>\_}{\.{\char'174=:\char'174>} primitive}, \[1108]. -\:\9{=:/\_}{\.{=:\char'174} primitive}, \[1108]. -\:\9{=:/\_}{\.{\char'174=:\char'174} primitive}, \[1108]. -\:\9{=:/\_}{\.{\char'174=:} primitive}, \[1108]. -\:\9{=:\_}{\.{=:} primitive}, \[1108]. -\:\.{=>}, 682. -\:\9{> }{\.{>} primitive}, \[893]. -\:\9{>=\_}{\.{>=} primitive}, \[893]. -\:\.{>>}, 807, 1040. -\:\.{>\relax}, 398, 1041. -\:\.{??}, 261, 263. -\:\.{???}, 59, 60, 257, 258. -\:\.{?\relax}, 78, 638. -\:\9{[ }{\.{[} primitive}, \[211]. -\:\9{] }{\.{]} primitive}, \[211]. -\:\9{][}{\.{\char`\{} primitive}, \[211]. -\:\9{]]\\}{\.{\char`\\} primitive}, \[211]. -\:\9{]]]\#\#\#\#\_}{\.{\#\#\#\#}}, 603. -\:\9{]]]\#\#\#\_}{\.{\#\#\#}}, 817. -\:\9{]]]\#\#\_}{\.{\#\#}}, 613. -\:\9{]]]\#\AT!\_}{\.{\#\AT!} primitive}, \[688]. -\:\9{]]]\AT!\#\_}{\.{\AT!\#} primitive}, \[688]. -\:\9{]]]\AT!\_}{\.{\AT!} primitive}, \[688]. -\:\9{]]]\AT!\_Octant}{\.{\AT! Octant...}}, 509. -\:\9{]]]\AT!\_retro\_}{\.{\AT! retrograde line...}}, 510. -\:\9{]]]\AT!\_trans\_}{\.{\AT! transition line...}}, 515, 521. -\:\9{]]}{\.{\char`\}} primitive}, \[211]. -\:\|{a}, \[47], \[102], \[117], \[124], \[126], \[321], \[391], \[429], \[431], -\[433], \[440], \[568], \[722], \[773], \[774], \[778], \[976], \[977], \[978], -\[1154]. -\:\.{a font metric dimension...}, 1140. -\:\.{A group...never ended}, 832. -\:\.{A primary expression...}, 823. -\:\.{A secondary expression...}, 862. -\:\.{A statement can't begin with x}, 990. -\:\.{A tertiary expression...}, 864. -\:\\{a\_close}, \[27], 51, 655, 1205. -\:\\{a\_make\_name\_string}, \[780], 788, 793. -\:\\{a\_minus\_b}, \[865], 866. -\:\\{a\_open\_in}, \[26], 51, 793. -\:\\{a\_open\_out}, \[26], 788. -\:\\{a\_plus\_b}, \[865], 866. -\:\\{a\_tension}, \[296]. -\:\\{aa}, \[286], 288, 290, 291, 301, \[321], 322, \[440], 444, 445, 446. -\:\\{aaa}, \[321], 322. -\:\\{ab\_vs\_cd}, \[117], 152, 300, 306, 317, 375, 376, 479, 488, 502, 516, -522, 546, 548, 549, 943, 949. -\:\\{abnegate}, \[390], 413, 421. -\:\\{abort\_find}, \[242], 243. -\:\\{abs}, 65, 124, 126, 150, 151, 152, 260, 288, 289, 292, 294, 295, 299, 300, -302, 321, 326, 362, 378, 404, 408, 426, 433, 434, 437, 441, 445, 457, 459, 479, -496, 498, 502, 529, 533, 540, 543, 589, 591, 595, 596, 598, 599, 600, 603, 611, -612, 615, 616, 812, 814, 837, 866, 915, 943, 949, 965, 1008, 1056, 1098, 1129, -1140, 1182. -\:\\{absorbing}, \[659], 664, 665, 730. -\:\\{acc}, \[116], \[286], 290. -\:\\{add\_mac\_ref}, \[226], 720, 845, 862, 864, 868, 1035. -\:\\{add\_mult\_dep}, \[971], 972. -\:\\{add\_or\_subtract}, 929, \[930], 936, 939. -\:\\{add\_pen\_ref}, \[487], 621, 855, 1063. -\:\\{add\_str\_ref}, \[42], 621, 678, 855, 1083. -\:\9{add\_to\_}{\&{addto} primitive}, \[211]. -\:\\{add\_to\_command}, \[186], 211, 212, 1058. -\:\\{add\_to\_type}, \[1059], 1064. -\:\\{after}, 426, \[427], 429, 436, 439, 440, 444, 446. -\:\\{all\_safe}, \[426], \[440], 446. -\:\\{alpha}, \[296], \[433], 436, 439, \[440], 444, \[527], 528, 529, 530, 533. -\:\\{alpha\_file}, \[24], 26, 27, 30, 31, 50, 54, 631, 780. -\:\\{already\_there}, \[577], 578, 583, 584. -\:\9{also\_}{\&{also} primitive}, \[1052]. -\:\\{also\_code}, \[403], 1052, 1059. -\:\\{ampersand}, \[186], 868, 869, 874, 886, 887, 891, 893, 894. -\:\.{An expression...}, 868. -\:\9{and\_}{\&{and} primitive}, \[893]. -\:\\{and\_command}, \[186], 882, 884, 893, 894. -\:\\{and\_op}, \[189], 893, 940. -\:\\{angle}, \[106], 137, 139, 144, 145, 256, 279, 283, 527, 542, 865, 875. -\:\.{angle(0,0)...zero}, 140. -\:\9{angle\_}{\&{angle} primitive}, \[893]. -\:\\{angle\_op}, \[189], 893, 907. -\:\\{app\_lc\_hex}, \[48]. -\:\\{append\_char}, \[41], 48, 52, 58, 207, 671, 771, 780, 897, 912, 976, 977. -\:\\{append\_to\_name}, \[774], 778. -\:\\{appr\_t}, 556, \[557]. -\:\\{appr\_tt}, 556, \[557]. -\:\\{area\_delimiter}, \[768], 770, 771, 772. -\:\\{arg\_list}, 719, \[720], 721, 724, 725, 726, 728, 734, 736. -\:\\{arith\_error}, \[97], 98, 99, 100, 107, 109, 112, 114, 124, 135, 269, 270. -\:\.{Arithmetic overflow}, 99. -\:{ASCII code}, 17. -\:\9{ASCII\_}{\&{ASCII} primitive}, \[893]. -\:\\{ASCII\_code}, \[18], 19, 20, 28, 29, 30, 37, 41, 54, 58, 77, 198, 667, -771, 774, 778, 913. -\:\\{ASCII\_op}, \[189], 893, 912, 913. -\:\\{assignment}, \[186], 211, 212, 693, 733, 755, 821, 841, 868, 993, 995, -996, 1021, 1035. -\:\9{at\_}{\&{at} primitive}, \[211]. -\:\\{at\_least}, \[186], 211, 212, 882. -\:\9{at\_least\_}{\&{atleast} primitive}, \[211], \[256], \[300]. -\:\\{at\_token}, \[186], 211, 212, 1073. -\:\\{attr}, \[188], 229, 236, 239, 240, 245. -\:\\{attr\_head}, \[228], 229, 239, 241, 242, 244, 245, 246, 247, 850, 1047. -\:\\{attr\_loc}, \[229], 236, 239, 241, 244, 245, 246, 850. -\:\\{attr\_loc\_loc}, \[229], 241. -\:\\{attr\_node\_size}, \[229], 239, 241, 245, 247. -\:\\{autorounding}, \[190], 192, 193, 402. -\:\9{autorounding\_}{\&{autorounding} primitive}, \[192]. -\:\\{avail}, \[161], 163, 164, 165, 176, 177, 181, 1194, 1195. -\:\.{AVAIL list clobbered...}, 181. -\:\\{axis}, \[393], 459, 507, 517, 519. -\:\|{b}, \[124], \[126], \[321], \[391], \[429], \[431], \[433], \[440], % -\[568], \[580], \[723], \[778], \[913], \[919], \[976], \[977], \[978], % -\[1072], \[1154]. -\:\\{b\_close}, \[27], 1134, 1182. -\:\\{b\_make\_name\_string}, \[780], 791, 1134. -\:\\{b\_open\_out}, \[26], 791, 1134. -\:\\{b\_tension}, \[296]. -\:\\{back\_error}, \[653], 693, 703, 713, 726, 727, 734, 735, 747, 755, 756, -765, 820, 832, 839, 859, 861, 875, 878, 881, 990, 991, 1021, 1032, 1034, 1035, -1106, 1107, 1113. -\:\\{back\_expr}, 847, \[848]. -\:\\{back\_input}, \[652], 653, 715, 716, 733, 751, 824, 825, 837, 841, 847, -854, 862, 864, 868, 881, 1012, 1034, 1107, 1204. -\:\\{back\_list}, \[649], 652, 662, 715, 848. -\:\\{backed\_up}, \[632], 635, 636, 638, 649, 650. -\:{backpointers}, 1147. -\:\.{Backwards path...}, 1068. -\:\.{BAD}, 219. -\:\\{bad}, \[13], 14, 154, 204, 214, 310, 553, 777, 1204. -\:\.{Bad culling amounts}, 1074. -\:\.{Bad flag...}, 183. -\:\.{Bad PREVDEP...}, 617. -\:\.{Bad window number}, 1071. -\:\\{bad\_binary}, \[923], 929, 936, 940, 941, 948, 951, 952, 975, 983, 988. -\:\\{bad\_char}, \[913], 914. -\:\\{bad\_exp}, 823, \[824], 862, 864, 868. -\:\\{bad\_for}, \[754], 765. -\:\\{bad\_pool}, \[51], 52, 53. -\:\\{bad\_subscript}, 846, \[849], 861. -\:\\{bad\_unary}, 898, \[901], 903, 905, 906, 907, 909, 912, 915, 917, 921. -\:\\{bad\_vardef}, \[175], 698, 701, 702. -\:\\{balance}, \[685], 687, \[730], 731, 732. -\:\\{banner}, \[2], 61, 790, 1183. -\:\\{base}, \[374], 375, 376, \[697], 703, 704. -\:\\{base\_area\_length}, \[775], 779. -\:\\{base\_default\_length}, \[775], 777, 778, 779. -\:\\{base\_ext\_length}, \[775], 778, 779. -\:\\{base\_extension}, \[775], 784, 1200. -\:\\{base\_file}, 779, \[1188], 1189, 1191, 1199, 1200, 1201, 1211. -\:\\{base\_ident}, 34, 61, 790, \[1183], 1184, 1185, 1198, 1199, 1200, 1211. -\:\\{batch\_mode}, \[68], 70, 81, 86, 87, 88, 789, 1024, 1025, 1199, 1200. -\:\9{batch\_mode\_}{\&{batchmode} primitive}, \[1024]. -\:\\{bb}, \[286], 287, 288, 291, \[440], 444, 445, 446. -\:\\{bc}, 1088, 1089, 1091, 1093, \[1096], 1097, 1099, 1124, 1126, 1132, 1135, -1136. -\:\\{bch\_label}, \[1096], 1097, 1111, 1137, 1141. -\:\\{bchar}, \[1096], 1137, 1139. -\:\\{bchar\_label}, \[186], 211, 212, 1107. -\:\\{be\_careful}, \[107], 108, \[109], \[112], \[114], 115, \[119]. -\:\\{before}, 426, \[427], 429, 436, 439, 444, 446. -\:\\{before\_and\_after}, \[429], 434, 437, 441. -\:\&{begin}, 7, 8. -\:\\{begin\_diagnostic}, 71, \[195], 197, 254, 603, 613, 626, 721, 728, 734, -750, 762, 817, 902, 924, 945, 997, 998. -\:\\{begin\_edge\_tracing}, \[372], 465, 506. -\:\\{begin\_file\_reading}, 73, 82, \[654], 717, 793, 897. -\:\\{begin\_group}, \[186], 211, 212, 732, 823. -\:\9{begin\_group\_}{\&{begingroup} primitive}, \[211]. -\:\\{begin\_iteration}, 706, 707, \[755], 764. -\:\\{begin\_name}, 767, \[770], 781, 787. -\:\\{begin\_pseudoprint}, \[642], 644, 645. -\:\\{begin\_token\_list}, \[649], 677, 736, 760. -\:\.{Beginning to dump...}, 1200. -\:{Bernshte{\u\i}n, Serge{\u\i} Natanovich}, 303. -\:\\{beta}, \[296], \[440], 444, \[527], 528, 529, 530, 533, 536. -\:\9{Bezier}{B\'ezier, Pierre Etienne}, 255. -\:\\{bg\_loc}, 211, 698, \[699], 1198, 1199. -\:\\{big}, \[124], \[126]. -\:\\{big\_node\_size}, \[230], 231, 232, 803, 810, 857, 919, 928, 939, 966, -1005. -\:\\{big\_trans}, 952, \[966]. -\:{BigEndian order}, \[1088]. -\:\\{bilin1}, 967, \[968], 972. -\:\\{bilin2}, 970, \[972]. -\:\\{bilin3}, 973, \[974]. -\:\\{binary\_mac}, 862, \[863], 864, 868. -\:\\{bisect\_ptr}, \[309], 311, 312, 314, 553, 558, 559, 561. -\:\\{bisect\_stack}, \[309], 553. -\:\\{bistack\_size}, \[11], 309, 310, 553, 557. -\:\\{black}, \[565], 568, 577, 579, 580, 583, 584, 1143, 1144. -\:\\{blank\_line}, \[195]. -\:\\{blank\_rectangle}, 564, 566, \[567], 569, 571, 572, 574, 577. -\:\\{boc}, 1142, 1144, \[1145], 1146, 1147, 1149, 1161, 1162. -\:\\{boc\_c}, 1161, \[1162], 1165. -\:\\{boc\_p}, 1161, \[1162], 1165. -\:\\{boc1}, 1144, \[1145], 1161. -\:\\{boolean}, 26, 30, 36, 45, 47, 71, 74, 91, 97, 107, 109, 112, 114, 124, -126, 178, 180, 195, 197, 238, 246, 249, 257, 332, 406, 426, 440, 453, 455, 473, -497, 527, 564, 569, 572, 577, 592, 599, 600, 621, 661, 680, 771, 779, 782, 801, -868, 899, 913, 943, 977, 978, 1006, 1054, 1072, 1084, 1096, 1187. -\:\9{boolean\_}{\&{boolean} primitive}, \[1013]. -\:\\{boolean\_reset}, \[906], 937, 1181. -\:\\{boolean\_type}, \[187], 216, 248, 621, 798, 799, 802, 809, 855, 892, 895, -905, 906, 918, 919, 920, 936, 937, 940, 1003, 1013, 1181. -\:\\{bot}, \[1094]. -\:\\{bot\_row}, \[567], \[572], 574, 577. -\:\\{boundary\_char}, \[190], 192, 193, 1097, 1137. -\:\9{boundary\_char\_}{\&{boundarychar} primitive}, \[192]. -\:\\{break}, 33. -\:\\{break\_in}, 33. -\:\\{breakpoint}, \[1212]. -\:{Brocot, Achille}, 526. -\:\\{buf\_size}, \[11], 29, 30, 34, 66, 154, 641, 654, 667, 682, 707, 717, 779, -786, 788, 1208. -\:\\{buffer}, \[29], 30, 35, 36, 45, 66, 78, 82, 83, 205, 206, 207, 208, 210, -629, 630, 641, 644, 667, 669, 671, 673, 674, 679, 681, 682, 717, 778, 779, 781, -786, 787, 788, 794, 897, 1211, 1213. -\:\.{Buffer size exceeded}, 34. -\:\\{bypass\_eoln}, \[30]. -\:\\{byte\_file}, \[24], 26, 27, 780, 791, 1087. -\:\\{b0}, 153, \[156], 157, 214, 255, 1093, 1094, 1133, 1192, 1193. -\:\\{b1}, 153, \[156], 157, 214, 255, 1093, 1094, \[1131], 1132, 1133, 1192, -1193. -\:\\{b2}, 153, \[156], 157, 1093, 1094, \[1131], 1132, 1133, 1192, 1193. -\:\\{b3}, 153, \[156], 157, 1093, 1094, \[1131], 1132, 1133, 1192, 1193. -\:\\{b4}, \[1131], 1132. -\:\|{c}, \[47], \[77], \[189], \[210], \[217], \[391], \[440], \[491], \[527], % -\[567], \[568], \[625], \[626], \[667], \[697], \[771], \[774], \[778], \[823], -\[862], \[863], \[864], \[868], \[895], \[898], \[901], \[910], \[913], \[919], -\[922], \[923], \[930], \[953], \[960], \[962], \[963], \[966], \[985], % -\[1070], \[1072], \[1103], \[1104], \[1106], \[1165], \[1209]. -\:\\{cancel\_skips}, \[1110], 1139. -\:\.{CAPSULE}, 237. -\:\\{capsule}, \[188], 214, 219, 233, 237, 238, 619, 799, 806, 830, 856, 857, -911, 931, 982. -\:\\{capsule\_token}, \[186], 651, 676, 678, 823, 1042. -\:\\{cat}, 975, \[976]. -\:\\{cc}, \[286], 288, 289, 290, 294, 295, \[440], 444, 445, 446, \[1106]. -\:\\{cf}, \[116], 297, \[298], 299, 300, 301. -\:\\{change\_if\_limit}, \[746], 748. -\:\\{char}, 19, 25, 775, 788. -\:\9{char\_}{\&{char} primitive}, \[893]. -\:\\{char\_class}, 22, \[198], 199, 217, 223, 669, 673, 674. -\:\\{char\_code}, \[190], 192, 193, 1070. -\:\9{char\_code\_}{\&{charcode} primitive}, \[192]. -\:\\{char\_dp}, \[190], 192, 193, 1099, 1126. -\:\9{char\_dp\_}{\&{chardp} primitive}, \[192]. -\:\\{char\_dx}, \[190], 192, 193, 1099. -\:\9{char\_dx\_}{\&{chardx} primitive}, \[192]. -\:\\{char\_dy}, \[190], 192, 193, 1099. -\:\9{char\_dy\_}{\&{chardy} primitive}, \[192]. -\:\\{char\_exists}, \[1096], 1097, 1099, 1124, 1126, 1132, 1136, 1181, 1182. -\:\9{char\_exists\_}{\&{charexists} primitive}, \[893]. -\:\\{char\_exists\_op}, \[189], 893, 906. -\:\\{char\_ext}, \[190], 192, 193, 1165. -\:\9{char\_ext\_}{\&{charext} primitive}, \[192]. -\:\\{char\_ht}, \[190], 192, 193, 1099, 1126. -\:\9{char\_ht\_}{\&{charht} primitive}, \[192]. -\:\\{char\_ic}, \[190], 192, 193, 1099, 1126. -\:\9{char\_ic\_}{\&{charic} primitive}, \[192]. -\:\\{char\_info}, 1091. -\:\\{char\_info\_word}, 1089, \[1091], 1092. -\:\9{char\_list\_}{\&{charlist} primitive}, \[1101]. -\:\\{char\_list\_code}, \[1101], 1102, 1106. -\:\\{char\_loc}, 1144, \[1145], 1147, 1182. -\:\\{char\_loc0}, \[1144]. -\:\\{char\_op}, \[189], 893, 912. -\:\\{char\_ptr}, \[1149], 1163, 1165, 1182. -\:\\{char\_remainder}, \[1096], 1097, 1104, 1136, 1138. -\:\\{char\_tag}, \[1096], 1097, 1104, 1105, 1136. -\:\\{char\_wd}, \[190], 192, 193, 1099, 1124. -\:\9{char\_wd\_}{\&{charwd} primitive}, \[192]. -\:\.{Character c is already...}, 1105. -\:{character set dependencies}, 22, 49. -\:{check sum}, 53, 1090, 1131, 1146. -\:\\{check\_arith}, \[99], 269, 815, 823, 837, 895, 898, 922, 1001. -\:\\{check\_colon}, \[747], 748. -\:\\{check\_delimiter}, 703, 826, 830, \[1032]. -\:\\{check\_equals}, \[693], 694, 697. -\:\\{check\_gf}, \[1163], 1165, 1177, 1179. -\:\\{check\_interrupt}, \[91], 650, 669, 825. -\:\\{check\_mem}, 178, \[180], 617, 825, 1213. -\:\\{check\_outer\_validity}, \[661], 668, 681. -\:{Chinese characters}, 1147. -\:\\{chop\_path}, 975, \[978]. -\:\\{chop\_string}, 975, \[977]. -\:\\{chopped}, \[402], 404. -\:\\{chr}, 19, 20, 23. -\:\\{class}, \[217], 220, 221, 223, \[667], 669. -\:\\{clear\_arith}, \[99]. -\:\\{clear\_for\_error\_prompt}, 73, 78, \[656], 670, 672. -\:\\{clear\_symbol}, \[249], 252, 254, 692, 1011, 1035. -\:\\{clear\_terminal}, \[33], 656, 786. -\:\\{clear\_the\_list}, \[1117], 1124, 1126. -\:\.{CLOBBERED}, 218. -\:\\{clobbered}, \[180], 181, 182. -\:\\{clockwise}, 452, \[453], 454, 458. -\:\\{close}, 27. -\:\\{close\_files\_and\_terminate}, 73, 76, 1204, \[1205]. -\:\.{cmbase}, 1203. -\:\\{coef\_bound}, \[592], 595, 596, 598, 599, 600, 932, 943, 949. -\:\\{collective\_subscript}, \[229], 239, 241, 244, 246, 850, 1012. -\:\\{colon}, \[186], 211, 212, 747, 756, 764, 1106, 1107, 1111, 1113. -\:\\{comma}, \[186], 211, 212, 704, 725, 726, 727, 764, 826, 859, 878, 1015, -1016, 1029, 1033, 1036, 1040, 1044, 1049, 1107, 1113, 1114, 1115. -\:\\{command\_code}, \[186], 685, 694, 1072. -\:\\{common\_ending}, \[15], 865, 1071. -\:\\{compromise}, \[432], 435, 438, 443. -\:\\{concatenate}, \[189], 893, 975. -\:\\{cond\_ptr}, \[738], 739, 744, 745, 746, 748, 749, 1209. -\:\\{conditional}, 706, 707, \[748]. -\:\\{confusion}, \[90], 107, 114, 216, 236, 239, 311, 362, 378, 517, 523, 589, -655, 746, 802, 809, 855. -\:\\{const\_dependency}, \[607], 608, 969, 972, 1007. -\:\\{constant\_x}, \[406], 407, 413, 417. -\:\\{continue}, \[15], 77, 78, 79, 83, 84, 311, 314, 402, 406, 417, 447, 556, -755, 764, 862, 864, 868, 1106, 1107, 1111. -\:\\{continue\_path}, \[868], 869. -\:\9{contour\_}{\&{contour} primitive}, \[1052]. -\:\\{contour\_code}, \[403], 917, 1052, 1053. -\:\.{control?}, 258. -\:\\{controls}, \[186], 211, 212, 881. -\:\9{controls\_}{\&{controls} primitive}, \[211]. -\:\\{coord\_node\_size}, 175, \[472], 476, 481, 487. -\:{coordinates, explained}, 576. -\:\\{copied}, \[1006], 1009. -\:\\{copy\_dep\_list}, \[609], 855, 858, 947. -\:\\{copy\_edges}, \[334], 621, 855. -\:\\{copy\_knot}, \[264], 870, 885, 980, 981. -\:\\{copy\_path}, \[265], 621, 855. -\:\9{cos\_d\_}{\&{cosd} primitive}, \[893]. -\:\\{cos\_d\_op}, \[189], 893, 906. -\:\\{cosine}, \[280], 281. -\:\\{crossing\_point}, \[391], 392, 407, 411, 413, 415, 420, 424, 497, 499, -503, 545, 547, 549. -\:\\{cs}, \[1146]. -\:\\{ct}, \[116], 297, \[298], 299, 300, 301. -\:\\{cubic\_intersection}, 555, \[556], 557, 562. -\:\9{cull\_}{\&{cull} primitive}, \[211]. -\:\\{cull\_command}, \[186], 211, 212, 1069. -\:\\{cull\_edges}, \[348], 1074. -\:\\{cull\_op}, \[186], 1052, 1053, 1074. -\:\\{cur\_area}, \[767], 772, 784, 786, 793, 795. -\:\\{cur\_cmd}, 83, 186, \[624], 626, 651, 652, 658, 667, 668, 671, 675, 676, -678, 685, 686, 691, 693, 697, 700, 703, 704, 705, 706, 707, 713, 715, 718, 725, -726, 727, 731, 732, 733, 734, 735, 742, 743, 747, 755, 756, 764, 765, 796, 823, -824, 826, 832, 837, 839, 841, 844, 846, 847, 851, 852, 859, 860, 861, 862, 864, -868, 869, 874, 875, 878, 881, 882, 884, 989, 990, 991, 992, 993, 995, 996, -1011, 1012, 1015, 1016, 1017, 1021, 1029, 1032, 1033, 1034, 1035, 1036, 1040, -1041, 1042, 1044, 1049, 1051, 1062, 1072, 1074, 1106, 1107, 1111, 1113, 1114, -1115. -\:\\{cur\_edges}, \[327], 328, 329, 330, 331, 332, 333, 336, 337, 340, 341, -342, 343, 348, 352, 353, 354, 355, 356, 364, 365, 366, 367, 373, 374, 375, 376, -377, 378, 381, 382, 383, 384, 465, 577, 581, 804, 929, 963, 964, 965, 1057, -1061, 1064, 1070, 1071, 1074, 1167, 1169, 1172. -\:\\{cur\_exp}, 603, 615, 651, 713, 716, 717, 718, 726, 728, 730, 748, 750, -760, 761, 764, 765, \[796], 797, 798, 799, 800, 801, 808, 816, 819, 823, 827, -829, 830, 833, 837, 840, 841, 846, 852, 855, 856, 857, 860, 861, 863, 865, 870, -872, 875, 876, 877, 878, 879, 880, 882, 883, 885, 891, 895, 896, 897, 898, 901, -903, 905, 906, 907, 908, 910, 912, 913, 915, 916, 917, 919, 920, 921, 923, 927, -929, 930, 931, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 946, 948, 949, -951, 953, 955, 956, 962, 963, 964, 967, 968, 970, 972, 973, 976, 977, 978, 979, -984, 985, 988, 992, 994, 995, 996, 999, 1003, 1004, 1005, 1006, 1009, 1022, -1056, 1059, 1061, 1062, 1063, 1070, 1071, 1072, 1073, 1074, 1082, 1083, 1086, -1103, 1106, 1112, 1115, 1177, 1179, 1181. -\:\\{cur\_ext}, \[767], 772, 784, 786, 793, 795. -\:\\{cur\_file}, \[631], 655, 681, 793, 794. -\:\\{cur\_gran}, \[430], 431, 432, 433, 442. -\:\\{cur\_if}, \[738], 739, 744, 745, 748, 1209. -\:\\{cur\_input}, 34, 35, 82, \[628], 629, 635, 647, 648, 788. -\:\\{cur\_length}, \[40], 1163. -\:\\{cur\_min\_m}, \[1165], 1172, 1173. -\:\\{cur\_mod}, 83, \[624], 626, 651, 652, 658, 667, 668, 671, 675, 676, 678, -687, 690, 691, 694, 697, 700, 703, 705, 707, 711, 718, 726, 727, 731, 735, 742, -743, 748, 749, 751, 755, 796, 823, 824, 826, 833, 834, 835, 837, 839, 841, 846, -847, 851, 860, 861, 862, 864, 868, 990, 992, 1011, 1015, 1023, 1029, 1032, -1034, 1035, 1040, 1041, 1042, 1049, 1051, 1054, 1059, 1074, 1082, 1106, 1112, -1177, 1209. -\:\\{cur\_name}, \[767], 772, 784, 786, 793, 795. -\:\\{cur\_path\_type}, \[403], 435, 438, 442, 917, 1064, 1068. -\:\\{cur\_pen}, 402, \[403], 435, 438, 442, 506, 917, 1062, 1063, 1064, 1068. -\:\\{cur\_rounding\_ptr}, 426, \[427], 429, 433, 436, 439, 440, 444, 446. -\:\\{cur\_spec}, 394, 399, 400, 402, \[403], 404, 406, 407, 417, 419, 421, 433, -440, 447, 450, 452. -\:\\{cur\_sym}, 83, 210, 211, \[624], 651, 652, 658, 661, 662, 663, 664, 667, -668, 669, 676, 677, 683, 685, 686, 690, 691, 692, 694, 700, 703, 704, 705, 707, -718, 726, 735, 740, 751, 755, 796, 823, 824, 826, 837, 846, 847, 851, 860, 862, -864, 868, 893, 1011, 1012, 1029, 1031, 1032, 1033, 1034, 1035, 1036, 1041, -1049, 1076, 1204. -\:\\{cur\_t}, \[555], 556, 558, 559, 560, 561, 562, 988. -\:\\{cur\_tok}, \[651], 652, 685, 715, 730, 844. -\:\\{cur\_tt}, \[555], 556, 558, 559, 560, 561, 562, 988. -\:\\{cur\_type}, 603, 615, 651, 716, 718, 726, 728, 730, 760, 764, 765, \[796], -798, 799, 800, 801, 808, 816, 819, 823, 826, 827, 830, 832, 833, 837, 840, 841, -846, 852, 855, 856, 857, 860, 861, 864, 865, 870, 872, 876, 877, 878, 883, 885, -891, 892, 895, 896, 897, 898, 901, 903, 905, 906, 907, 908, 909, 910, 912, 915, -917, 918, 919, 920, 921, 923, 927, 929, 930, 931, 934, 935, 936, 937, 939, 940, -941, 942, 944, 946, 948, 951, 953, 955, 960, 962, 967, 970, 973, 975, 982, 983, -988, 989, 992, 993, 995, 996, 999, 1000, 1002, 1003, 1004, 1006, 1009, 1021, -1054, 1059, 1061, 1062, 1070, 1071, 1072, 1073, 1074, 1082, 1103, 1106, 1112, -1115, 1177, 1181. -\:\\{cur\_wt}, \[327], 372, 373, 374, 375, 376, 378, 381, 382, 383, 384, 465, -1064, 1068. -\:\\{cur\_x}, 387, 388, \[389], 390, 394, 413, 421, 445, 447, 451, 454, 457, -481, 485, 488, 489, 510, 871, 872, 873, 877, 878, 884, 984, 1072, 1073, 1074, -1075. -\:\\{cur\_y}, 387, 388, \[389], 390, 394, 413, 421, 445, 447, 451, 454, 457, -481, 485, 488, 489, 510, 871, 872, 873, 877, 878, 884, 984, 1072, 1073, 1074, -1075. -\:\\{curl}, \[256], 258, 259, 263, 271, 282, 284, 285, 290, 875, 876, 888, 889, -890, 891. -\:\9{curl\_}{\&{curl} primitive}, \[211]. -\:\\{curl\_command}, \[186], 211, 212, 875. -\:\\{curl\_ratio}, 294, 295, \[296]. -\:{curvature}, 275. -\:\.{Curve out of range}, 404. -\:\\{cycle}, \[186], 823, 869, 893, 894. -\:{cycle spec}, \[393]. -\:\.{Cycle spec at line...}, 394. -\:\9{cycle\_}{\&{cycle} primitive}, \[893]. -\:\\{cycle\_hit}, \[868], 869, 886, 891. -\:\\{cycle\_op}, \[189], 893, 920. -\:\\{c0}, \[574], 575, 576, \[1073]. -\:\\{c1}, \[574], 575, \[1073]. -\:\|{d}, \[333], \[348], \[373], \[391], \[440], \[527], \[580], \[862], % -\[864], \[868], \[944], \[1118], \[1120], \[1121], \[1128], \[1159], \[1165]. -\:{data structure assumptions}, 176. -\:\\{day}, \[190], 192, 193, 194, 790, 1163, 1200, 1211. -\:\9{day\_}{\&{day} primitive}, \[192]. -\:\\{dd}, \[286], 288, 289, \[440], 444, 445, 446. -\:{dead cubics}, \[402]. -\:\&{debug}, \[7], \[9], \[73], \[79], \[88], \[157], \[178], \[179], \[180], % -\[185], \[1212]. -\:\.{debug \#}, 1212. -\:\\{debug\_help}, 73, 79, 88, \[1212]. -\:{debugging}, 7, 79, 91, 157, 178, 1212. -\:\\{decimal}, \[189], 893, 912. -\:\9{decimal\_}{\&{decimal} primitive}, \[893]. -\:\.{Declared variable conflicts...}, 1015. -\:\\{decr}, \[16], 43, 46, 63, 66, 81, 83, 84, 86, 87, 102, 121, 123, 149, 163, -164, 177, 195, 207, 226, 291, 315, 322, 330, 331, 332, 333, 352, 364, 375, 376, -377, 382, 383, 384, 436, 439, 458, 459, 483, 487, 488, 497, 515, 516, 521, 522, -556, 560, 577, 635, 648, 650, 655, 681, 687, 731, 732, 742, 854, 862, 864, 868, -1051, 1122, 1135, 1138, 1139, 1141, 1167, 1182, 1194, 1209. -\:\9{def\_}{\&{def} primitive}, \[683]. -\:\\{def\_delims}, 1030, \[1031]. -\:\\{def\_ref}, \[720], 721, 736. -\:\\{defined\_macro}, \[186], 249, 700, 706, 707, 718, 1035, 1041, 1043. -\:\\{del}, \[406], 407, 408, 413, \[419], 420, \[453], 454. -\:\\{del\_m}, \[1144]. -\:\\{del\_n}, \[1144]. -\:\\{delete\_mac\_ref}, \[226], 249, 650, 809. -\:\\{delete\_pen\_ref}, \[487], 808, 809, 1062, 1063. -\:\\{delete\_str\_ref}, \[43], 216, 691, 743, 808, 809, 976, 977, 1042, 1083. -\:\\{deletions\_allowed}, \[71], 72, 79, 80, 93, 661, 670, 672, 675. -\:\\{delimiters}, \[186], 211, 212, 1030. -\:\9{delimiters\_}{\&{delimiters} primitive}, \[211]. -\:\\{delta}, \[103], \[279], 281, 288, \[328], \[329], 330, 331, \[342], 343, % -\[366], 367, \[378], 381, 382, 383, 384, \[527], 530, 531, 533, 534, 535, % -\[968], \[974], \[1165], 1173, 1174. -\:\\{delta\_a}, \[426]. -\:\\{delta\_b}, \[426]. -\:\\{delta\_x}, \[279], 281, 292, 293, 299, 301, 302. -\:\\{delta\_y}, \[279], 281, 292, 293, 299, 301, 302. -\:\\{delx}, \[280], 282, \[374], 375, 376, \[511], 516, 522, 552, 553, 556, % -\[557], 558, 559, 560, 561. -\:\\{dely}, \[280], 282, \[374], 375, 376, \[511], 516, 522, 552, 553, 556, % -\[557], 558, 559, 560, 561. -\:\\{del1}, \[406], 407, 408, 409, 413, 414, \[419], 420, 421, 423. -\:\\{del2}, \[406], 407, 408, 409, 411, 413, 414, 415, \[419], 420, 421, 423, -424. -\:\\{del3}, \[406], 407, 408, 409, 411, 413, 414, 415, \[419], 420, 421, 423, -424. -\:\\{denom}, \[116], \[296], \[836], 837. -\:\\{dep\_div}, 948, \[949]. -\:\\{dep\_final}, \[592], 594, 597, 601, 606, 607, 608, 609, 615, 818, 819, -829, 855, 856, 858, 971, 972, 1007. -\:\\{dep\_finish}, 934, \[935], 943, 949. -\:\\{dep\_head}, \[175], 587, 588, 604, 606, 614, 617, 812, 1050. -\:\\{dep\_list}, 585, \[587], 604, 605, 606, 614, 617, 798, 799, 801, 803, 811, -812, 816, 818, 819, 827, 855, 858, 903, 930, 931, 932, 935, 943, 947, 949, 959, -968, 969, 971, 972, 1007, 1009, 1050. -\:\\{dep\_mult}, 942, \[943], 944, 946, 968. -\:\\{dep\_node\_size}, \[587], 595, 596, 597, 598, 599, 600, 601, 603, 605, -607, 608, 609, 612, 615, 616, 818, 819, 829, 1008. -\:\\{dependent}, \[187], 216, 248, 585, 587, 588, 589, 590, 594, 595, 596, 597, -599, 600, 601, 603, 610, 612, 613, 615, 798, 799, 800, 801, 802, 808, 809, 812, -813, 815, 816, 817, 818, 819, 829, 855, 857, 858, 900, 903, 930, 932, 943, 949, -969, 1003, 1006, 1007, 1009, 1010, 1050. -\:\\{depth\_index}, \[1091]. -\:{design size}, 1146. -\:\\{design\_size}, \[190], 192, 193, 1128, 1129, 1182. -\:\9{design\_size\_}{\&{designsize} primitive}, \[192]. -\:\\{dest\_x}, \[406], 407, 409, 411, 412, 413, 415, 416, \[419], 421, 423, -424, 425. -\:\\{dest\_y}, \[406], 407, 411, 412, 413, 414, 415, 416, \[419], 421, 423, -424, 425. -\:\\{diag\_offset}, \[442], 443. -\:\\{diag\_round}, 402, \[440]. -\:\\{diagonal}, \[393], 459, 507, 508, 509, 519, 523. -\:\\{dig}, \[54], 63, 64, 102, 674. -\:\\{digit\_class}, \[198], 199, 220, 669, 673, 674. -\:\\{dimen\_head}, 1124, \[1125], 1126, 1136. -\:\\{dimen\_out}, \[1129], 1132, 1136, 1139, 1140. -\:\9{direction\_time\_}{\&{directiontime} primitive}, \[893]. -\:\\{direction\_time\_of}, \[189], 893, 983. -\:{dirty \PASCAL}, \[3], 157, 185, 1203. -\:\\{discard\_suffixes}, \[246]. -\:\\{disp\_edges}, \[577], 1071. -\:\\{disp\_err}, 716, 754, \[807], 873, 923, 937, 955, 1002. -\:\\{disp\_token}, \[1041], 1043, 1044, 1049. -\:\\{disp\_var}, \[1046], 1047, 1049. -\:\9{display\_}{\&{display} primitive}, \[211]. -\:\\{display\_command}, \[186], 211, 212, 1069. -\:\&{div}, \[95]. -\:\.{Division by zero}, 838, 950. -\:\\{dm}, \[1144]. -\:\\{dmax}, 404, \[406], 408, \[419], \[453], 457. -\:\\{do\_add\_to}, 1058, \[1059]. -\:\\{do\_assignment}, 993, 995, \[996]. -\:\\{do\_binary}, 834, 837, 839, 859, 862, 864, 868, 893, \[922], 966. -\:\\{do\_cull}, 1069, \[1074]. -\:\\{do\_display}, 1069, \[1071]. -\:\\{do\_equation}, 993, \[995], 996. -\:\\{do\_expression}, 996. -\:\\{do\_interim}, 1033, \[1034]. -\:\\{do\_let}, 1033, \[1035]. -\:\\{do\_message}, 1081, \[1082]. -\:\\{do\_new\_internal}, 1033, \[1036]. -\:\\{do\_nothing}, \[16], 33, 57, 58, 79, 146, 216, 223, 249, 669, 707, 794, -808, 809, 919, 957, 1003, 1035. -\:\\{do\_nullary}, 834, 893, \[895]. -\:\\{do\_open\_window}, 1069, \[1073]. -\:\\{do\_protection}, 1026, \[1029]. -\:\\{do\_random\_seed}, 1020, \[1021]. -\:\\{do\_ship\_out}, 1069, \[1070]. -\:\\{do\_show}, \[1040], 1051. -\:\\{do\_show\_dependencies}, \[1050], 1051, 1213. -\:\\{do\_show\_stats}, \[1045], 1051. -\:\\{do\_show\_token}, \[1044], 1051. -\:\\{do\_show\_var}, 1046, \[1049], 1051. -\:\\{do\_show\_whatever}, 1039, \[1051]. -\:\\{do\_special}, 1175, \[1177]. -\:\\{do\_statement}, 832, \[989], 992, 1017, 1020, 1034. -\:\\{do\_tfm\_command}, 1100, \[1106]. -\:\\{do\_type\_declaration}, 992, \[1015]. -\:\\{do\_unary}, 834, 835, 893, \[898]. -\:\\{done}, \[15], 47, 53, 124, 125, 126, 127, 177, 257, 269, 272, 311, 317, -344, 345, 346, 347, 348, 349, 354, 358, 366, 368, 374, 375, 378, 381, 382, 383, -384, 394, 402, 452, 458, 477, 479, 488, 491, 502, 506, 512, 518, 527, 531, 532, -539, 546, 547, 548, 577, 578, 584, 594, 597, 604, 605, 609, 635, 650, 667, 673, -685, 687, 730, 731, 732, 742, 748, 749, 755, 764, 765, 781, 786, 787, 793, 809, -812, 823, 835, 837, 839, 840, 841, 852, 860, 868, 881, 919, 922, 930, 932, 936, -953, 955, 957, 958, 959, 1001, 1003, 1004, 1005, 1006, 1007, 1011, 1012, 1049, -1059, 1068, 1106, 1107, 1110, 1165, 1172, 1173. -\:\\{done1}, \[15], 180, 181, 257, 258, 261, 374, 376, 477, 481, 506, 516, 518, -522, 527, 536, 823, 844, 922, 939, 1006, 1009. -\:\\{done2}, \[15], 180, 182, 823, 850. -\:\\{done3}, \[15]. -\:\\{done4}, \[15]. -\:\\{done5}, \[15]. -\:\\{done6}, \[15]. -\:\\{double}, \[16], 108, 115, 123, 132, 142, 143, 392, 408, 457, 496, 543, -556, 559. -\:\.{Double-AVAIL list clobbered...}, 182. -\:\\{double\_colon}, \[186], 211, 212, 1107. -\:\\{double\_dot}, \[189]. -\:\9{double\_path\_}{\&{doublepath} primitive}, \[1052]. -\:\\{double\_path\_code}, \[403], 435, 438, 442, 1052, 1053, 1059, 1064, 1068. -\:\.{Doubly free location...}, 182. -\:\\{drop\_code}, \[1052], 1053, 1074, 1075. -\:\9{dropping\_}{\&{dropping} primitive}, \[1052]. -\:{dry rot}, 90. -\:\\{ds}, \[1146]. -\:\\{du}, \[495], \[497], 498. -\:\\{dual\_moves}, 512, \[518]. -\:\.{dump...only by INIMF}, 1209. -\:\9{dump\_}{\&{dump} primitive}, \[1018]. -\:\\{dump\_four\_ASCII}, \[1192]. -\:\\{dump\_hh}, \[1188], 1196. -\:\\{dump\_int}, \[1188], 1190, 1192, 1194, 1196, 1198. -\:\\{dump\_qqqq}, \[1188], 1192. -\:\\{dump\_wd}, \[1188], 1194. -\:\\{dup\_offset}, \[476], 483. -\:\\{dv}, \[495], \[497], 498. -\:\\{dw}, \[357], 358. -\:\\{dx}, \[378], 380, 381, 382, 383, 384, \[477], 479, 480, 494, \[495], 501, -502, 1144, 1147. -\:\\{dx1}, \[453], 454, 457. -\:\\{dx2}, \[453], 454, 457. -\:\\{dy}, \[477], 479, 480, \[495], 501, 502, 1144, 1147. -\:\\{dyn\_used}, \[160], 163, 164, 165, 176, 177, 1045, 1194, 1195. -\:\\{dy1}, \[453], 454, 457. -\:\\{dy2}, \[453], 454, 457. -\:\\{d0}, \[464], 467, 468, 508, 517, 523. -\:\\{d1}, 463, \[464], 467, 468, 508, 517, 523. -\:\|{e}, \[773], \[774], \[786], \[1071], \[1074]. -\:\\{east\_edge}, \[435]. -\:\\{east\_west\_edge}, \[435]. -\:\\{ec}, 1088, 1089, 1091, 1093, \[1096], 1097, 1099, 1124, 1126, 1132, 1135, -1136. -\:\\{edge\_and\_weight}, \[378], 381, 382, 383, 384. -\:\\{edge\_header\_size}, \[326], 334, 385, 895, 964. -\:\\{edge\_prep}, \[329], 366, 375, 376, 380. -\:\\{edges\_trans}, 952, \[963]. -\:\\{ee}, \[286], 288, 289. -\:\\{eg\_loc}, 211, 698, \[699], 1198, 1199. -\:\\{eight\_bits}, \[24], 63, 624, 1096, 1103, 1131, 1149, 1152, 1163, 1165. -\:\\{eighth\_octant}, \[139], 141, 380, 387, 388, 390, 396, 426, 443, 449, 461, -462. -\:\\{el\_gordo}, \[95], 100, 107, 109, 112, 114, 124, 135, 235, 244, 917, 1118, -1140. -\:\&{else}, 10. -\:\9{else\_}{\&{else} primitive}, \[740]. -\:\\{else\_code}, \[738], 740, 741. -\:\9{else\_if\_}{\&{elseif} primitive}, \[740]. -\:\\{else\_if\_code}, \[738], 740, 748. -\:\.{Emergency stop}, 88. -\:\\{empty\_edges}, \[326], 329, 963. -\:\\{empty\_flag}, \[166], 168, 172, 176, 1207. -\:\\{encapsulate}, 855, \[856]. -\:\&{end}, 7, 8, 10. -\:\.{end occurred...}, 1209. -\:\.{End of file on the terminal}, 36, 66. -\:\9{end\_}{\&{end} primitive}, \[1018]. -\:\\{end\_attr}, \[175], 229, 239, 247, 1047. -\:\\{end\_cycle}, \[272], 281, 282, 284, 287. -\:\\{end\_def}, \[683], 992. -\:\9{end\_def\_}{\&{enddef} primitive}, \[683]. -\:\\{end\_diagnostic}, \[195], 254, 257, 332, 372, 394, 473, 603, 613, 626, -721, 728, 734, 750, 762, 817, 902, 924, 945, 997, 998. -\:\\{end\_edge\_tracing}, \[372], 465, 506. -\:\\{end\_file\_reading}, \[655], 656, 679, 681, 714, 793, 897, 1209. -\:\\{end\_for}, \[683], 707. -\:\9{end\_for\_}{\&{endfor} primitive}, \[683]. -\:\\{end\_group}, \[186], 211, 212, 732, 832, 991, 992, 993, 1017. -\:\9{end\_input\_}{\&{endinput} primitive}, \[709]. -\:\\{end\_name}, 767, \[772], 781, 787. -\:\\{end\_of\_MF}, \[6], 76, 1204. -\:\\{end\_of\_statement}, \[186], 732, 991, 1015, 1016. -\:\\{end\_round}, \[463], 464, 467, 508. -\:\\{end\_token\_list}, \[650], 652, 676, 712, 714, 736, 795, 1209. -\:\&{endcases}, \[10]. -\:\9{endgroup\_}{\&{endgroup} primitive}, \[211]. -\:\\{endpoint}, \[255], 256, 257, 258, 266, 273, 393, 394, 398, 399, 400, 401, -402, 451, 452, 457, 465, 466, 491, 506, 512, 518, 539, 562, 563, 865, 868, 870, -871, 885, 891, 916, 917, 920, 921, 962, 978, 979, 985, 987, 1064. -\:\.{Enormous chardp...}, 1098. -\:\.{Enormous charht...}, 1098. -\:\.{Enormous charic...}, 1098. -\:\.{Enormous charwd...}, 1098. -\:\.{Enormous designsize...}, 1098. -\:\.{Enormous number...}, 675. -\:\.{entering the nth octant}, 394. -\:\\{env\_move}, \[507], 513, 514, 515, 516, 517, 519, 520, 521, 522, 523. -\:\\{eoc}, 1142, 1144, \[1145], 1146, 1149, 1165. -\:\\{eof}, 25, 30, 52, 1199. -\:\\{eoln}, 30, 52. -\:\\{eq\_type}, \[200], 202, 203, 210, 211, 213, 229, 242, 249, 254, 668, 694, -700, 702, 759, 850, 1011, 1029, 1031, 1035, 1036, 1041, 1213. -\:\\{eqtb}, 158, 200, \[201], 202, 210, 211, 212, 213, 249, 250, 252, 254, 625, -632, 683, 740, 893, 1196, 1197. -\:\\{equal\_to}, \[189], 893, 936, 937. -\:\\{equals}, \[186], 693, 733, 755, 868, 893, 894, 993, 995, 996, 1035. -\:\.{Equation cannot be performed}, 1002. -\:\\{equiv}, \[200], 202, 209, 210, 211, 213, 229, 234, 239, 242, 249, 254, -664, 668, 694, 700, 702, 850, 1011, 1015, 1030, 1031, 1035, 1036, 1213. -\:\\{err\_help}, \[74], 75, 85, 1083, 1086. -\:\9{err\_help\_}{\&{errhelp} primitive}, \[1079]. -\:\\{err\_help\_code}, \[1079], 1082. -\:\9{err\_message\_}{\&{errmessage} primitive}, \[1079]. -\:\\{err\_message\_code}, \[1079], 1080, 1082. -\:\\{error}, 67, 70, 71, 73, 74, \[77], 83, 88, 93, 99, 122, 128, 134, 140, -602, 653, 670, 672, 675, 701, 708, 712, 713, 725, 751, 778, 789, 795, 820, 838, -996, 1032, 1051, 1110. -\:\\{error\_count}, \[71], 72, 77, 81, 989, 1051. -\:\\{error\_line}, \[11], 14, 54, 58, 635, 641, 642, 643, 665. -\:\\{error\_message\_issued}, \[71], 77, 90. -\:\\{error\_stop\_mode}, 67, \[68], 69, 77, 88, 93, 398, 807, 1024, 1051, 1086, -1199, 1209. -\:\9{error\_stop\_mode\_}{\&{errorstopmode} primitive}, \[1024]. -\:\\{erstat}, \[26]. -\:\\{eta\_corr}, 306, \[311], 313, 314, 317. -\:\.{ETC}, 217, 227. -\:\9{every\_job\_}{\&{everyjob} primitive}, \[211]. -\:\\{every\_job\_command}, \[186], 211, 212, 1076. -\:\\{excess}, \[1119], 1120, 1122. -\:\\{exit}, \[15], 16, 36, 46, 47, 77, 117, 167, 217, 227, 235, 242, 246, 265, -266, 284, 311, 391, 406, 488, 497, 539, 556, 562, 589, 622, 667, 746, 748, 760, -779, 868, 899, 904, 922, 928, 930, 943, 949, 953, 962, 963, 966, 1032, 1070, -1071, 1073, 1074, 1131, 1161, 1187, 1209, 1212. -\:\9{exit\_if\_}{\&{exitif} primitive}, \[211]. -\:\\{exit\_test}, \[186], 211, 212, 706, 707. -\:\\{exp\_err}, \[807], 830, 849, 872, 876, 878, 883, 892, 901, 914, 923, 937, -950, 960, 993, 996, 999, 1002, 1021, 1055, 1060, 1061, 1062, 1071, 1082, 1103, -1106, 1112, 1115, 1178. -\:\\{expand}, \[707], 715, 718. -\:\\{expand\_after}, \[186], 211, 212, 706, 707. -\:\9{expand\_after\_}{\&{expandafter} primitive}, \[211]. -\:\\{explicit}, \[256], 258, 261, 262, 266, 271, 273, 280, 282, 299, 302, 393, -407, 486, 563, 874, 880, 884, 1066. -\:\.{EXPR}, 222. -\:\9{expr\_}{\&{expr} primitive}, \[695]. -\:\\{expr\_base}, \[214], 218, 222, 676, 683, 684, 694, 695, 696, 697, 703, -705, 725, 727, 755, 764. -\:\\{expr\_macro}, \[226], 227, 705, 733. -\:\\{expression\_binary}, \[186], 893, 894. -\:\\{expression\_tertiary\_macro}, \[186], 249, 683, 868, 1035, 1043. -\:\\{ext\_bot}, \[1094], 1113. -\:\\{ext\_delimiter}, \[768], 770, 771, 772. -\:\\{ext\_mid}, \[1094], 1113. -\:\\{ext\_rep}, \[1094], 1113. -\:\\{ext\_tag}, \[1092], 1096, 1105, 1113. -\:\\{ext\_top}, \[1094], 1113. -\:\\{exten}, \[1092], 1094, \[1096], 1140. -\:\9{extensible\_}{\&{extensible} primitive}, \[1101]. -\:\\{extensible\_code}, \[1101], 1102, 1106. -\:\\{extensible\_recipe}, 1089, \[1094]. -\:{extensions to \MF}, 2. -\:\.{Extra `endfor'}, 708. -\:\.{Extra `endgroup'}, 1017. -\:\.{Extra else}, 751. -\:\.{Extra elseif}, 751. -\:\.{Extra fi}, 751. -\:\.{Extra tokens will be flushed}, 991. -\:\\{extra\_space}, 1095. -\:\\{extra\_space\_code}, \[1095]. -\:\\{extras}, 362, \[363]. -\:\|{f}, \[26], \[27], \[30], \[107], \[109], \[112], \[114], \[398], \[594], % -\[667], \[780], \[1165]. -\:\\{false}, 26, 30, 36, 45, 47, 51, 71, 75, 83, 84, 93, 98, 99, 107, 110, 114, -124, 126, 179, 180, 181, 182, 254, 269, 270, 407, 426, 446, 452, 454, 455, 456, -474, 497, 503, 505, 530, 564, 570, 573, 577, 592, 593, 600, 603, 604, 613, 626, -653, 657, 661, 670, 672, 675, 680, 681, 692, 721, 728, 734, 750, 762, 767, 771, -779, 783, 794, 801, 804, 817, 825, 869, 899, 902, 913, 924, 944, 945, 977, 978, -997, 998, 1003, 1009, 1010, 1011, 1015, 1035, 1045, 1054, 1064, 1072, 1085, -1086, 1097, 1107, 1137, 1138, 1187. -\:\9{false\_}{\&{false} primitive}, \[893]. -\:\\{false\_code}, \[189], 798, 892, 893, 895, 905, 906, 918, 919, 920, 937, -940. -\:\\{fast\_case\_down}, \[378], 380. -\:\\{fast\_case\_up}, \[378], 380. -\:\\{fast\_get\_avail}, \[165], 381, 382, 383, 384, 651, 844. -\:\.{Fatal base file error}, 1187. -\:\\{fatal\_error}, 66, \[88], 679, 714, 786, 789, 897. -\:\\{fatal\_error\_stop}, \[71], 72, 77, 88, 1204. -\:\\{ff}, \[286], 287, 289, 290, 295, \[296], 302. -\:\9{fi\_}{\&{fi} primitive}, \[740]. -\:\\{fi\_code}, \[738], 740, 741, 742, 748, 749, 751. -\:\\{fi\_or\_else}, \[186], 706, 707, 738, 740, 741, 742, 751, 1209. -\:\\{fifth\_octant}, \[139], 141, 380, 387, 388, 390, 396, 426, 443, 449, 461, -462. -\:\.{File ended while scanning...}, 663. -\:\.{File names can't...}, 795. -\:\\{file\_name\_size}, \[11], 25, 774, 777, 778, 780. -\:\\{file\_offset}, \[54], 55, 57, 58, 62, 333, 372, 793, 1048, 1165. -\:\\{file\_ptr}, 79, 80, \[634], 635, 636, 637. -\:\\{file\_state}, \[632], 635, 636, 656, 667, 714, 795. -\:\\{fill\_envelope}, 481, \[506], 518, 1064. -\:\\{fill\_spec}, \[465], 506, 511, 1064. -\:\\{fillin}, \[190], 192, 193, 525, 533. -\:\9{fillin\_}{\&{fillin} primitive}, \[192]. -\:\\{fin\_numeric\_token}, \[667], 669, 673. -\:\\{fin\_offset\_prep}, \[497], 503, 504, 505. -\:\\{final\_cleanup}, 1204, \[1209]. -\:\\{final\_end}, \[6], 34, 657, 1204, 1211. -\:\\{final\_node}, \[610], 612, 615. -\:\\{final\_value}, \[752], 761, 765. -\:\\{find\_direction\_time}, \[539], 540, 984. -\:\\{find\_edges\_var}, \[1057], 1061, 1064, 1070, 1071, 1074. -\:\\{find\_offset}, \[488], 984. -\:\\{find\_point}, 983, \[985]. -\:\\{find\_variable}, \[242], 700, 852, 1000, 1015, 1057. -\:\\{finish\_path}, \[868], 869, 874. -\:\\{firm\_up\_the\_line}, 666, 681, \[682], 794. -\:\\{first}, \[29], 30, 34, 35, 36, 66, 78, 82, 83, 654, 655, 657, 679, 681, -682, 717, 787, 794. -\:\\{first\_count}, \[54], 641, 642, 643. -\:\\{first\_octant}, \[139], 141, 378, 379, 380, 387, 388, 390, 395, 396, 406, -407, 409, 411, 426, 435, 443, 448, 449, 461, 462, 473, 480, 484, 488, 489. -\:\\{first\_text\_char}, \[19], 23. -\:\\{first\_x}, \[406], 407, \[440], 444, 445. -\:\\{first\_y}, \[406], 407, \[440], 444, 445. -\:\\{fix\_check\_sum}, \[1131], 1206. -\:\\{fix\_date\_and\_time}, \[194], 1204, 1211. -\:\\{fix\_dependencies}, \[604], 610, 815, 935, 968, 971. -\:\\{fix\_design\_size}, \[1128], 1206. -\:\\{fix\_needed}, \[592], 593, 595, 596, 598, 599, 600, 604, 610, 815, 932, -935, 968, 971. -\:\\{fix\_offset}, \[328], 329, 965. -\:\\{fix\_word}, \[1089], 1090, 1095, 1129, 1147. -\:\9{floor\_}{\&{floor} primitive}, \[893]. -\:\\{floor\_op}, \[189], 893, 906. -\:\\{floor\_scaled}, \[119], 516, 522, 906. -\:\\{floor\_unscaled}, \[119], 306, 463, 513, 515, 516, 519, 521, 522, 1074. -\:\\{flush\_below\_variable}, 246, \[247], 249. -\:\\{flush\_cur\_exp}, 717, \[808], 820, 872, 907, 913, 915, 917, 918, 919, -920, 921, 935, 936, 938, 956, 962, 982, 984, 993, 1040, 1061, 1063, 1070, 1072, -1082, 1177. -\:\\{flush\_error}, \[820], 849, 1017. -\:\\{flush\_list}, \[177], 385, 700, 736, 1015. -\:\\{flush\_node\_list}, \[177], 685, 811, 815, 852, 996, 1009, 1057. -\:\\{flush\_p}, \[621]. -\:\\{flush\_string}, \[43], 210, 793, 1200. -\:\\{flush\_token\_list}, \[216], 224, 226, 235, 650, 698, 763, 840, 1062, -1071, 1074. -\:\\{flush\_variable}, \[246], 700, 1015. -\:\\{flushing}, \[659], 664, 665, 991, 1016. -\:\.{font metric dimensions...}, 1140. -\:{font metric files}, 1087. -\:\.{Font metrics written...}, 1134. -\:\9{font\_dimen\_}{\&{fontdimen} primitive}, \[1101]. -\:\\{font\_dimen\_code}, \[1101], 1106. -\:\\{fontmaking}, \[190], 192, 193, 1206. -\:\9{fontmaking\_}{\&{fontmaking} primitive}, \[192]. -\:\9{for\_}{\&{for} primitive}, \[683]. -\:\9{for\_suffixes\_}{\&{forsuffixes} primitive}, \[683]. -\:\.{Forbidden token found...}, 663. -\:\\{force\_eof}, 657, \[680], 681, 711. -\:\9{forever\_}{\&{forever} primitive}, \[683]. -\:\\{forever\_text}, \[632], 638, 714, 760. -\:\\{forty\_five\_deg}, \[106], 145. -\:\\{forward}, 73, 216, 217, 224, 225, 666, 706, 820, 995, 1034. -\:\\{found}, \[15], 167, 170, 171, 205, 206, 207, 235, 236, 284, 291, 292, 295, -477, 527, 532, 539, 541, 543, 544, 547, 548, 577, 582, 667, 669, 685, 686, 720, -726, 748, 755, 779, 1103, 1117. -\:\\{found1}, \[15]. -\:\\{found2}, \[15]. -\:\\{four\_quarters}, \[156], 1096, 1133, 1186, 1187. -\:\\{fourth\_octant}, \[139], 141, 380, 387, 388, 390, 393, 396, 426, 435, 443, -449, 461, 462, 472. -\:\\{frac\_mult}, 837, \[944]. -\:\\{fraction}, \[105], 107, 109, 114, 116, 119, 124, 126, 144, 145, 148, 149, -150, 187, 259, 280, 283, 286, 296, 298, 299, 391, 406, 410, 419, 433, 440, 493, -495, 497, 542, 585, 587, 591, 592, 594, 599, 612, 932, 944. -\:\\{fraction\_four}, \[105], 111, 113, 116, 121, 123, 125, 126, 127, 132, 133, -296, 1116. -\:\\{fraction\_half}, \[105], 111, 152, 288, 408, 496, 543, 1098, 1128, 1140. -\:\\{fraction\_one}, \[105], 107, 108, 109, 142, 145, 148, 149, 150, 285, 288, -290, 291, 295, 300, 311, 391, 392, 402, 407, 411, 413, 415, 420, 424, 436, 439, -444, 457, 477, 478, 497, 499, 503, 530, 540, 547, 549, 599, 603, 612, 615, 816, -917, 1169, 1170. -\:\\{fraction\_three}, \[105], 116, 288, 296. -\:\\{fraction\_threshold}, \[594], 597. -\:\\{fraction\_two}, \[105], 116, 121, 124, 142. -\:\\{free}, \[178], 180, 181, 182, 183, 184. -\:\\{free\_avail}, \[164], 177, 216, 254, 349, 360, 604, 760, 763, 852, 860. -\:\\{free\_node}, \[172], 177, 216, 246, 247, 249, 254, 268, 352, 353, 354, -358, 385, 405, 452, 487, 532, 537, 595, 598, 599, 600, 601, 603, 605, 612, 615, -616, 650, 745, 763, 800, 808, 810, 818, 819, 827, 829, 837, 855, 858, 866, 890, -903, 910, 922, 925, 942, 944, 947, 955, 970, 980, 1001, 1006, 1008, 1065, 1209. -\:\9{from\_}{\&{from} primitive}, \[211]. -\:\\{from\_token}, \[186], 211, 212, 1073. -\:\\{frozen\_bad\_vardef}, \[201], 203, 702. -\:\\{frozen\_colon}, \[201], 203, 211, 751. -\:\\{frozen\_end\_def}, \[201], 203, 664, 683. -\:\\{frozen\_end\_for}, \[201], 203, 664, 683. -\:\\{frozen\_end\_group}, \[201], 203, 211, 664, 698. -\:\\{frozen\_fi}, \[201], 203, 661, 740. -\:\\{frozen\_inaccessible}, \[201], 203, 691, 1196, 1197, 1199. -\:\\{frozen\_left\_bracket}, \[201], 203, 211, 847. -\:\\{frozen\_repeat\_loop}, \[201], 757, 758, 759. -\:\\{frozen\_right\_delimiter}, \[201], 203, 664. -\:\\{frozen\_semicolon}, \[201], 203, 211, 664. -\:\\{frozen\_slash}, \[201], 203, 837, 893. -\:\\{frozen\_undefined}, \[201], 249. -\:{Fuchs, David Raymond}, 2, 1148. -\:\\{future\_pen}, \[187], 216, 248, 798, 802, 804, 808, 809, 855, 864, 865, -896, 918, 919, 921, 952, 962, 983. -\:\|{g}, \[47]. -\:\\{g\_pointer}, 216, 219, 224, \[225], 1042. -\:\\{gamma}, \[296], \[527], 528, 529, 530. -\:\\{general\_macro}, \[226], 227, 694, 697, 725. -\:\\{get}, 25, 28, 30, 32, 794, 1189. -\:\\{get\_avail}, \[163], 165, 235, 236, 250, 335, 350, 362, 375, 376, 605, -662, 694, 697, 698, 704, 728, 734, 758, 764, 841, 845, 853, 854, 860, 863, 1011. -\:\\{get\_boolean}, 706, 713, 748, \[892]. -\:\\{get\_clear\_symbol}, \[692], 694, 700, 1031, 1036. -\:\\{get\_code}, \[1103], 1106, 1107, 1110, 1112, 1113, 1114. -\:\\{get\_next}, 71, 73, 83, 624, 658, 659, 666, \[667], 676, 679, 685, 690, -691, 694, 700, 703, 704, 705, 706, 715, 718, 720, 730, 742, 781, 991, 1016, -1044, 1049. -\:\\{get\_node}, \[167], 173, 215, 232, 233, 234, 239, 240, 241, 244, 245, 252, -253, 264, 265, 266, 330, 331, 334, 341, 355, 364, 410, 451, 476, 477, 481, 486, -528, 535, 536, 537, 596, 597, 607, 608, 609, 619, 651, 694, 704, 705, 744, 755, -765, 799, 830, 856, 857, 871, 895, 896, 931, 964, 982, 1117. -\:\\{get\_pair}, \[1072], 1073, 1074. -\:\\{get\_strings\_started}, \[47], 51, 1204. -\:\\{get\_symbol}, \[691], 692, 694, 704, 705, 755, 757, 1011, 1029, 1033, -1035, 1076. -\:\\{get\_x\_next}, 694, 697, 706, 707, 716, \[718], 726, 729, 733, 734, 735, -748, 751, 752, 755, 764, 765, 799, 800, 820, 823, 824, 825, 826, 830, 835, 837, -839, 840, 841, 844, 846, 850, 851, 853, 854, 859, 860, 861, 862, 864, 868, 874, -875, 876, 878, 881, 882, 884, 886, 892, 989, 990, 995, 996, 1011, 1012, 1021, -1023, 1029, 1031, 1033, 1034, 1035, 1036, 1040, 1044, 1045, 1049, 1050, 1054, -1059, 1070, 1071, 1072, 1073, 1074, 1076, 1082, 1103, 1106, 1107, 1112, 1115, -1177. -\:\\{gf\_boc}, \[1161], 1162, 1168, 1172. -\:\\{gf\_buf}, 1151, \[1152], 1154, 1155. -\:\\{gf\_buf\_size}, \[11], 14, 1151, 1152, 1153, 1155, 1156, 1182. -\:\\{gf\_dx}, 1099, \[1149], 1182. -\:\\{gf\_dy}, 1099, \[1149], 1182. -\:\\{gf\_ext}, \[785], 791, 1164. -\:\\{gf\_file}, \[791], 1149, 1151, 1154, 1182. -\:\\{gf\_four}, \[1157], 1161, 1166, 1177, 1182. -\:\\{gf\_id\_byte}, \[1144], 1163, 1182. -\:\\{gf\_index}, \[1151], 1152, 1154. -\:\\{gf\_limit}, 1151, \[1152], 1153, 1155, 1156. -\:\\{gf\_max\_m}, \[1149], 1163, 1168, 1169, 1182. -\:\\{gf\_max\_n}, \[1149], 1161, 1163, 1182. -\:\\{gf\_min\_m}, \[1149], 1161, 1163, 1182. -\:\\{gf\_min\_n}, \[1149], 1163, 1167, 1168, 1182. -\:\\{gf\_offset}, 1151, \[1152], 1153, 1155, 1163, 1165, 1182. -\:\\{gf\_out}, \[1155], 1157, 1158, 1159, 1160, 1161, 1163, 1165, 1166, 1173, -1174, 1177, 1182. -\:\\{gf\_paint}, \[1159], 1170, 1171, 1172. -\:\\{gf\_prev\_ptr}, \[1149], 1150, 1163, 1165, 1182, 1206. -\:\\{gf\_ptr}, 1151, \[1152], 1153, 1155, 1156, 1163, 1165, 1182. -\:\\{gf\_string}, \[1160], 1163, 1166, 1177, 1179. -\:\\{gf\_swap}, \[1155]. -\:\\{gf\_three}, \[1158], 1160. -\:\\{gf\_two}, \[1158], 1159, 1174. -\:\\{given}, \[256], 258, 259, 273, 282, 284, 285, 875, 877, 888, 889. -\:\\{good\_val}, \[431], 432, 435, 438, 442. -\:\&{goto}, \[34], \[76]. -\:\\{granularity}, \[190], 192, 193, 430, 433. -\:\9{granularity\_}{\&{granularity} primitive}, \[192]. -\:\\{greater\_or\_equal}, \[189], 893, 936, 937. -\:\\{greater\_than}, \[189], 893, 936, 937. -\:\\{group\_line}, \[831], 832. -\:\&{gubed}, \[7]. -\:{Guibas, Leonidas Ioannis}, 2, 469. -\:\|{h}, \[205], \[257], \[269], \[326], \[334], \[344], \[346], \[366], % -\[369], \[385], \[402], \[465], \[473], \[477], \[484], \[488], \[491], \[506], -\[518], \[527], \[539], \[562], \[860], \[1011]. -\:\\{half}, \[96], 102, 111, 113, 121, 126, 133, 142, 150, 232, 313, 314, 317, -392, 432, 442, 445, 556, 559, 561, 596, 866, 939, 1122. -\:\\{half\_buf}, 1151, \[1152], 1153, 1155, 1156. -\:\\{half\_error\_line}, \[11], 14, 635, 641, 642, 643. -\:\\{half\_fraction\_threshold}, \[594], 599, 600, 612, 616. -\:\\{half\_scaled\_threshold}, \[594], 599, 600. -\:\\{half\_unit}, \[101], 113, 119, 374, 402, 462, 463, 468, 477, 478, 512, -515, 518, 521, 528, 530, 533, 917, 1106. -\:\\{halfword}, 153, \[156], 158, 172, 210, 246, 253, 284, 329, 346, 366, 491, -497, 624, 627, 697, 755, 862, 864, 868, 1029, 1077, 1104. -\:\\{hard\_times}, 941, \[946]. -\:\\{hash}, 200, \[201], 202, 205, 207, 625, 658, 1196, 1197. -\:\\{hash\_base}, \[200], 201, 205. -\:\\{hash\_end}, \[201], 202, 204, 209, 214, 229, 250, 253, 254, 699, 841, 996, -998, 999, 1049, 1196, 1197, 1199. -\:\\{hash\_is\_full}, \[200], 207. -\:\\{hash\_prime}, \[12], 14, 205, 208, 1190, 1191. -\:\\{hash\_size}, \[12], 14, 201, 207, 208, 1190, 1191, 1208. -\:\\{hash\_top}, \[201]. -\:\\{hash\_used}, \[200], 203, 207, 1196, 1197. -\:\\{header}, 1090. -\:\\{header\_byte}, \[1096], 1097, 1106, 1114, 1128, 1131, 1135, 1182. -\:\9{header\_byte\_}{\&{headerbyte} primitive}, \[1101]. -\:\\{header\_byte\_code}, \[1101], 1102, 1106. -\:\\{header\_size}, \[11], 14, 1096, 1097, 1114, 1135. -\:{Hedrick, Charles Locke}, 3. -\:\\{height\_index}, \[1091]. -\:\\{help\_line}, \[74], 84, 86, 661, 664, 691, 852, 1016, 1055. -\:\\{help\_ptr}, \[74], 75, 84, 86. -\:\\{help0}, \[74], 1051. -\:\\{help1}, \[74], 88, 90, 703, 713, 734, 751, 838, 839, 876, 881, 883, 914, -937, 1021, 1034, 1051, 1056, 1071, 1074, 1082, 1086, 1098, 1106, 1107, 1110, -1113, 1115, 1178. -\:\\{help2}, 67, \[74], 83, 84, 89, 90, 122, 128, 134, 140, 270, 478, 623, 670, -675, 701, 708, 712, 713, 716, 727, 735, 747, 765, 832, 865, 878, 892, 937, 950, -996, 999, 1002, 1004, 1008, 1015, 1017, 1021, 1032, 1055, 1057, 1061, 1062, -1067, 1073, 1103, 1105, 1106, 1112. -\:\\{help3}, 67, \[74], 93, 340, 342, 478, 661, 672, 691, 725, 726, 727, 755, -756, 795, 849, 859, 861, 875, 887, 901, 923, 955, 960, 963, 965, 993, 1032, -1035, 1068. -\:\\{help4}, \[74], 84, 99, 404, 602, 663, 754, 824, 830, 1060, 1086. -\:\\{help5}, \[74], 693, 851, 872, 873, 878, 990, 1016. -\:\\{help6}, \[74], 991. -\:\.{Here is how much...}, 1208. -\:\9{hex\_}{\&{hex} primitive}, \[893]. -\:\\{hex\_op}, \[189], 893, 912. -\:\\{hh}, 153, \[156], 157, 161, 214, 250, 255, \[334], \[477], 479, \[562], -563, 1188, 1189. -\:\\{hi\_mem\_min}, \[159], 161, 163, 167, 168, 176, 177, 178, 180, 181, 184, -185, 216, 218, 242, 676, 850, 1045, 1194, 1195, 1207, 1208. -\:\\{hi\_mem\_stat\_min}, \[175], 176, 1195. -\:\\{history}, \[71], 72, 77, 88, 90, 195, 1204, 1209. -\:\\{hlp1}, \[74]. -\:\\{hlp2}, \[74]. -\:\\{hlp3}, \[74]. -\:\\{hlp4}, \[74]. -\:\\{hlp5}, \[74]. -\:\\{hlp6}, \[74]. -\:\\{ho}, \[155], 324, 333, 343, 344, 349, 352, 358, 359, 360, 370, 373, 582, -1169. -\:{Hobby, John Douglas}, 274, 354, 432, 524. -\:\\{hold\_head}, \[175], 665, 685, 697, 730. -\:\\{hppp}, \[190], 192, 193, 785, \[1146], 1164, 1182. -\:\9{hppp\_}{\&{hppp} primitive}, \[192]. -\:\\{htap\_ypoc}, \[266], 921, 978, 1064, 1065. -\:\|{i}, \[19], \[150], \[641]. -\:\.{I can't find file x}, 786. -\:\.{I can't find PLAIN...}, 779. -\:\.{I can't go on...}, 90. -\:\.{I can't read MF.POOL}, 51. -\:\.{I can't write on file x}, 786. -\:\\{id\_lookup}, \[205], 210, 669. -\:\\{id\_transform}, \[233], 955. -\:\9{if\_}{\&{if} primitive}, \[740]. -\:\\{if\_code}, \[738], 740, 741, 744, 751. -\:\\{if\_limit}, \[738], 739, 744, 745, 746, 748, 751. -\:\\{if\_line}, \[738], 739, 744, 745, 748, 1209. -\:\\{if\_line\_field}, \[738], 744, 745, 1209. -\:\\{if\_node\_size}, \[738], 744, 745, 1209. -\:\\{if\_test}, \[186], 706, 707, 740, 741, 742, 748. -\:\.{illegal design size...}, 1128. -\:\.{Illegal ligtable step}, 1107. -\:\.{Illegal suffix...flushed}, 1016. -\:\.{IMPOSSIBLE}, 218. -\:\.{Improper `:='}, 996. -\:\.{Improper `addto'}, 1061, 1062. -\:\.{Improper `openwindow'}, 1073. -\:\.{Improper curl}, 876. -\:\.{Improper font parameter}, 1115. -\:\.{Improper kern}, 1112. -\:\.{Improper location}, 1106. -\:\.{Improper subscript...}, 849. -\:\.{Improper tension}, 883. -\:\.{Improper transformation argument}, 955. -\:\.{Improper type}, 1055. -\:\.{Improper...replaced by 0}, 754. -\:\\{in\_open}, \[631], 654, 655, 657. -\:\\{in\_state\_record}, \[627], 628. -\:\\{in\_window}, \[186], 211, 212, 1071. -\:\9{in\_window\_}{\&{inwindow} primitive}, \[211]. -\:\.{Incomplete if...}, 661. -\:\.{Incomplete string token...}, 672. -\:\.{Inconsistent equation}, 1004, 1008. -\:\\{incr}, \[16], 30, 36, 41, 42, 44, 45, 46, 53, 58, 59, 60, 64, 66, 77, 85, -86, 93, 108, 115, 123, 136, 143, 147, 163, 165, 183, 207, 226, 281, 284, 297, -314, 315, 317, 319, 320, 321, 322, 333, 348, 352, 362, 364, 366, 375, 376, 377, -381, 382, 383, 384, 404, 429, 458, 459, 481, 483, 487, 497, 502, 514, 515, 516, -520, 521, 522, 560, 568, 574, 577, 583, 584, 647, 654, 669, 671, 673, 674, 681, -687, 704, 705, 717, 721, 724, 728, 731, 732, 734, 736, 737, 742, 772, 774, 779, -781, 787, 793, 1036, 1104, 1107, 1112, 1113, 1114, 1115, 1118, 1121, 1129, -1137, 1138, 1140, 1155, 1165, 1196, 1211. -\:\\{independent}, \[187], 216, 219, 232, 248, 585, 589, 592, 604, 615, 798, -799, 800, 801, 802, 803, 808, 809, 816, 827, 828, 855, 857, 858, 903, 918, 925, -926, 927, 928, 944, 1003, 1006, 1007, 1009. -\:\\{independent\_being\_fixed}, \[605]. -\:\\{independent\_needing\_fix}, \[592], 595, 596, 598, 599, 600. -\:\\{index}, 627, \[629], 630, 631, 632, 654, 655, 657. -\:\\{index\_field}, \[627], 629. -\:\\{inf\_val}, \[175], 617, 1116, 1117, 1118, 1121, 1136. -\:\\{info}, \[161], 166, 168, 176, 185, 214, 218, 221, 226, 227, 228, 229, 235, -236, 242, 245, 246, 250, 252, 253, 254, 324, 325, 326, 328, 333, 335, 337, 338, -339, 342, 343, 344, 345, 346, 347, 349, 350, 351, 358, 359, 360, 362, 366, 367, -368, 370, 373, 375, 376, 378, 381, 382, 383, 384, 472, 473, 475, 481, 484, 488, -491, 509, 512, 519, 580, 582, 587, 589, 591, 594, 595, 596, 597, 598, 599, 600, -601, 604, 605, 607, 608, 609, 610, 611, 612, 614, 615, 616, 617, 651, 662, 676, -685, 686, 694, 697, 698, 700, 704, 705, 714, 719, 721, 722, 725, 726, 727, 728, -729, 733, 734, 736, 752, 755, 758, 760, 763, 764, 805, 811, 812, 816, 818, 819, -841, 850, 853, 854, 860, 863, 904, 931, 933, 935, 968, 996, 998, 999, 1006, -1007, 1010, 1011, 1015, 1050, 1121, 1122, 1127, 1136, 1169, 1207, 1213. -\:\.{INIMF}, 8, 11, 12, 47, 50, 159, 1183, 1203. -\:\&{init}, \[8], \[47], \[50], \[173], \[210], \[564], \[567], \[568], % -\[1186], \[1204], \[1209], \[1210]. -\:\\{init\_big\_node}, \[232], 233, 830, 857, 982. -\:\\{init\_edges}, \[326], 353, 364, 895, 964. -\:\\{init\_gf}, \[1163]. -\:\\{init\_pool\_ptr}, \[38], 41, 1045, 1193, 1204, 1208. -\:\\{init\_prim}, 1204, \[1210]. -\:\\{init\_randoms}, \[150], 1022, 1211. -\:\\{init\_screen}, \[564], 567, 568, 569, 570, 571. -\:\\{init\_str\_ptr}, \[38], 44, 772, 1045, 1193, 1204, 1208. -\:\\{init\_tab}, 1204, \[1210]. -\:\\{init\_terminal}, \[36], 657. -\:\\{initialize}, \[4], 1204, 1211. -\:{inner loop}, 30, 107, 108, 109, 111, 112, 113, 163, 165, 167, 169, 172, 177, -242, 244, 408, 650, 651, 667, 668, 669, 676, 718, 850. -\:\9{inner\_}{\&{inner} primitive}, \[1027]. -\:\\{input}, \[186], 706, 707, 709, 710. -\:\9{input\_}{\&{input} primitive}, \[709]. -\:\\{input\_file}, \[631]. -\:\\{input\_ln}, 29, \[30], 36, 58, 66, 681, 794. -\:\\{input\_ptr}, \[628], 635, 636, 647, 648, 656, 657, 679, 788, 1209. -\:\\{input\_stack}, 79, \[628], 635, 647, 648, 788. -\:\\{ins\_error}, \[653], 661, 663, 691, 751, 824. -\:\.{insert>}, 82. -\:\\{inserted}, \[632], 638, 650, 653. -\:\\{install}, 857, \[858], 957, 959. -\:\\{int}, 153, \[156], 157, 214, 326, 435, 738, 1188, 1189, 1191. -\:\\{int\_increment}, \[553], 559, 561. -\:\\{int\_name}, \[190], 193, 254, 998, 999, 1036, 1043, 1098, 1123, 1198, 1199. -\:\\{int\_packets}, \[553], 558, 560. -\:\\{int\_ptr}, \[190], 191, 1036, 1198, 1199, 1208. -\:\\{integer}, 13, 19, 45, 46, 47, 54, 59, 60, 64, 65, 77, 89, 91, 100, 101, -102, 105, 106, 107, 109, 112, 114, 116, 117, 119, 121, 124, 126, 129, 130, 132, -135, 139, 145, 152, 153, 156, 160, 167, 185, 200, 205, 217, 227, 242, 299, 308, -309, 311, 321, 327, 328, 329, 332, 333, 337, 340, 342, 348, 354, 357, 363, 366, -369, 371, 373, 374, 378, 391, 398, 402, 403, 453, 464, 473, 477, 484, 488, 495, -497, 507, 511, 527, 555, 557, 562, 572, 574, 577, 580, 585, 589, 594, 597, 599, -600, 601, 608, 610, 621, 624, 625, 626, 631, 633, 641, 651, 659, 667, 685, 707, -720, 723, 730, 738, 742, 773, 774, 778, 788, 796, 801, 809, 813, 831, 895, 898, -899, 900, 913, 922, 930, 943, 977, 1001, 1059, 1070, 1073, 1074, 1096, 1103, -1106, 1118, 1119, 1120, 1121, 1129, 1130, 1131, 1133, 1149, 1152, 1157, 1158, -1159, 1160, 1161, 1162, 1163, 1165, 1186, 1187, 1203, 1205, 1210, 1212. -\:\\{interaction}, 66, 67, \[68], 69, 70, 77, 79, 81, 86, 87, 88, 93, 398, 679, -682, 786, 807, 897, 1023, 1051, 1086, 1198, 1199, 1200, 1209. -\:\\{interesting}, \[238], 603, 613, 817, 1050. -\:\9{interim\_}{\&{interim} primitive}, \[211]. -\:\\{interim\_command}, \[186], 211, 212, 1033. -\:\\{internal}, \[190], 191, 194, 195, 238, 253, 254, 269, 375, 376, 381, 382, -383, 384, 402, 430, 433, 465, 468, 477, 506, 508, 510, 515, 517, 521, 523, 533, -602, 603, 610, 682, 707, 713, 720, 728, 734, 748, 760, 790, 804, 816, 832, 841, -895, 898, 922, 944, 992, 994, 995, 996, 999, 1036, 1051, 1064, 1068, 1070, -1097, 1098, 1099, 1128, 1129, 1134, 1137, 1163, 1164, 1165, 1177, 1182, 1198, -1199, 1200, 1205, 1206, 1211, 1213. -\:\.{Internal quantity...}, 999. -\:\\{internal\_quantity}, \[186], 192, 823, 844, 860, 1011, 1034, 1036, 1043. -\:\\{interrupt}, \[91], 92, 93, 825. -\:\.{Interruption}, 93. -\:\\{intersect}, \[189], 893, 988. -\:\9{intersection\_times\_}{\&{intersectiontimes} primitive}, \[893]. -\:\.{Invalid code...}, 1103. -\:\\{invalid\_class}, \[198], 199, 669. -\:\\{is\_empty}, \[166], 169, 182, 183. -\:\.{Isolated expression}, 993. -\:\\{isolated\_classes}, \[198], 223, 669. -\:\\{italic\_index}, \[1091]. -\:\\{iteration}, \[186], 683, 684, 685, 706, 707, 758. -\:\|{j}, \[45], \[46], \[59], \[60], \[77], \[150], \[205], \[210], \[357], % -\[378], \[707], \[774], \[778], \[779], \[1106]. -\:\\{j\_random}, \[148], 149, 151, 152. -\:{Japanese characters}, 1147. -\:{Jensen, Kathleen}, 10. -\:\\{jj}, \[150], \[357], 364. -\:\.{job aborted}, 679. -\:\.{job aborted, file error...}, 786. -\:\\{job\_name}, 87, \[782], 783, 784, 788, 791, 793, 895, 1134, 1200, 1209. -\:\9{job\_name\_}{\&{jobname} primitive}, \[893]. -\:\\{job\_name\_op}, \[189], 893, 895. -\:\\{jump\_out}, \[76], 77, 79, 88. -\:\|{k}, \[45], \[46], \[47], \[63], \[64], \[66], \[102], \[121], \[130], % -\[132], \[135], \[139], \[145], \[149], \[150], \[205], \[210], \[264], \[280], -\[284], \[299], \[321], \[346], \[363], \[366], \[378], \[402], \[426], \[440], -\[473], \[477], \[484], \[487], \[491], \[497], \[511], \[568], \[574], \[577], -\[667], \[682], \[697], \[707], \[774], \[778], \[780], \[786], \[788], \[895], -\[913], \[976], \[977], \[978], \[1073], \[1106], \[1131], \[1154], \[1160], % -\[1163], \[1186], \[1187], \[1205], \[1210], \[1212]. -\:\\{keep\_code}, \[1052], 1074. -\:\\{keeping}, \[1074], 1075. -\:\9{keeping\_}{\&{keeping} primitive}, \[1052]. -\:\\{kern}, 1093, \[1096], 1106, 1112, 1139. -\:\9{kern\_}{\&{kern} primitive}, \[1108]. -\:\\{kern\_flag}, \[1093], 1112. -\:\\{knil}, \[325], 326, 330, 331, 332, 334, 336, 341, 352, 354, 355, 364, 376, -377, 382, 384, 442, 472, 473, 475, 476, 482, 483, 484, 497, 503, 505, 508, 509, -513, 515, 517, 519, 521, 523, 1167. -\:\\{knot\_node\_size}, \[255], 264, 265, 266, 268, 405, 410, 451, 452, 486, -528, 532, 535, 536, 537, 866, 871, 890, 896, 980, 1065. -\:\\{knots}, \[269], 271, 272. -\:\\{known}, \[187], 214, 215, 216, 219, 233, 248, 585, 594, 603, 615, 651, -678, 726, 760, 765, 798, 799, 802, 803, 808, 809, 823, 826, 827, 829, 830, 837, -841, 846, 855, 857, 858, 861, 873, 876, 878, 883, 895, 899, 903, 906, 912, 915, -918, 919, 930, 931, 932, 935, 937, 939, 941, 942, 943, 944, 948, 949, 951, 953, -956, 957, 959, 960, 966, 968, 969, 970, 971, 972, 974, 982, 983, 999, 1003, -1006, 1007, 1009, 1021, 1052, 1054, 1062, 1071, 1073, 1074, 1103, 1106, 1112, -1115, 1176, 1177, 1180. -\:\9{known\_}{\&{known} primitive}, \[893]. -\:\\{known\_op}, \[189], 893, 918, 919. -\:\\{known\_pair}, 871, \[872], 877, 884. -\:{Knuth, Donald Ervin}, 2, 81. -\:\|{l}, \[46], \[47], \[152], \[205], \[210], \[217], \[227], \[311], \[641], % -\[742], \[746], \[788], \[977], \[978], \[1006], \[1011], \[1035], \[1118], % -\[1121], \[1160], \[1212]. -\:\\{l\_delim}, \[697], 703, \[720], 726, 727, 729, \[730], 731, 735, \[823], -826, 830, \[1031], \[1032]. -\:\\{l\_packet}, 560. -\:\\{l\_packets}, \[553], 559. -\:\\{label\_char}, \[1096], 1104, 1137, 1138. -\:\\{label\_loc}, \[1096], 1097, 1104, 1137, 1138, 1139. -\:\\{label\_ptr}, \[1096], 1097, 1104, 1137, 1138, 1139. -\:{Lane, Jeffrey Michael}, 303. -\:\\{last}, \[29], 30, 34, 35, 36, 66, 78, 82, 83, 657, 679, 682, 779, 787, 897. -\:\\{last\_nonblank}, \[30]. -\:\\{last\_text\_char}, \[19], 23. -\:\\{last\_window}, \[326], 334, 577. -\:\\{last\_window\_time}, \[326], 334, 336, 337, 340, 342, 344, 348, 364, 577, -965. -\:\\{left\_brace}, \[186], 211, 212, 874. -\:\\{left\_bracket}, \[186], 211, 212, 823, 844, 847, 860, 1011, 1012. -\:\\{left\_bracket\_class}, \[198], 199, 220, 221. -\:\\{left\_col}, \[567], \[572], 574, 577, 581. -\:\\{left\_curl}, \[256], 259, 263, 271, 282, 295, 879, 890, 891. -\:\\{left\_delimiter}, \[186], 697, 703, 726, 731, 735, 823, 1030, 1031, 1043. -\:\\{left\_given}, \[256], 259, 263, 282, 292, 301, 879, 880, 888. -\:\\{left\_length}, \[528], 531, 532, 534, 535. -\:\\{left\_octant}, \[393], 394, 398, 401, 451, 452, 458, 459, 465, 506. -\:\\{left\_tension}, \[256], 258, 260, 288, 289, 294, 295, 299, 300, 302, 880. -\:\\{left\_transition}, \[393], 459, 508. -\:\\{left\_type}, \[255], 256, 257, 258, 259, 261, 262, 263, 265, 266, 269, -271, 272, 273, 281, 282, 284, 285, 287, 299, 302, 393, 394, 397, 398, 399, 400, -401, 402, 404, 410, 451, 452, 465, 486, 506, 528, 865, 870, 871, 879, 885, 887, -888, 890, 891, 896, 916, 917, 920, 962, 978, 979, 985, 987, 1064, 1066. -\:\\{left\_v}, \[528], 531, 534, 535. -\:\\{left\_x}, \[255], 256, 261, 265, 266, 271, 282, 299, 302, 393, 397, 404, -407, 409, 410, 411, 412, 415, 416, 418, 419, 421, 423, 424, 425, 434, 436, 441, -444, 447, 451, 457, 468, 486, 492, 496, 512, 518, 528, 543, 558, 563, 866, 880, -887, 896, 962, 987, 1066. -\:\\{left\_y}, \[255], 256, 261, 265, 266, 271, 282, 299, 302, 393, 397, 404, -409, 410, 413, 414, 415, 416, 419, 423, 424, 425, 437, 439, 444, 447, 451, 457, -468, 486, 492, 496, 512, 518, 528, 543, 558, 563, 866, 880, 887, 896, 962, 987, -1066. -\:\\{length}, \[39], 46, 205, 671, 716, 717, 793, 912, 913, 915, 976, 977, -1083, 1103, 1160. -\:\9{length\_}{\&{length} primitive}, \[893]. -\:\\{length\_op}, \[189], 893, 915. -\:\\{less\_or\_equal}, \[189], 893, 936, 937. -\:\\{less\_than}, \[189], 893, 936, 937. -\:\9{let\_}{\&{let} primitive}, \[211]. -\:\\{let\_command}, \[186], 211, 212, 1033. -\:\\{letter\_class}, \[198], 199, 218, 223. -\:\\{lf}, 1088. -\:\\{lh}, 153, \[156], 157, 161, 200, \[491], 502, 505, 1088, 1089, 1135, % -\[1205]. -\:\\{lhs}, \[995], \[996], 997, 998, 999, 1000, \[1001], 1002, 1003, \[1059], -1061, 1062, 1064. -\:\\{lig\_kern}, 1092, 1093, \[1096], 1137, 1139, 1205. -\:\\{lig\_kern\_command}, 1089, \[1093]. -\:\\{lig\_kern\_token}, \[186], 1107, 1108, 1109. -\:\9{lig\_table\_}{\&{ligtable} primitive}, \[1101]. -\:\\{lig\_table\_code}, \[1101], 1102, 1106. -\:\\{lig\_table\_size}, \[11], 14, 1096, 1107, 1137, 1141. -\:\\{lig\_tag}, \[1092], 1104, 1105, 1111. -\:\\{limit}, 627, \[629], 630, 632, 644, 654, 656, 657, 669, 671, 672, 679, -681, 682, 717, 793, 794, 1211. -\:\\{limit\_field}, 34, 82, \[627], 629, 788. -\:\\{line}, 79, 197, \[631], 637, 654, 655, 657, 681, 742, 744, 748, 794, 832. -\:\\{line\_edges}, \[374], 378, 507, 510. -\:\\{line\_stack}, \[631], 654, 655. -\:\\{linear\_eq}, \[610], 1006. -\:\\{link}, \[161], 163, 164, 165, 166, 167, 168, 172, 176, 177, 181, 185, 216, -217, 227, 228, 229, 230, 232, 234, 235, 236, 237, 238, 239, 240, 241, 242, 244, -245, 246, 247, 250, 252, 253, 254, 255, 257, 265, 266, 268, 271, 272, 273, 281, -284, 297, 324, 325, 326, 328, 330, 331, 332, 334, 335, 336, 337, 338, 339, 341, -343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 359, 360, 362, -364, 366, 367, 368, 369, 370, 375, 376, 377, 381, 382, 383, 384, 385, 394, 398, -399, 400, 401, 402, 404, 405, 406, 410, 411, 412, 413, 415, 416, 418, 419, 424, -425, 433, 435, 436, 439, 440, 442, 444, 447, 450, 451, 452, 458, 459, 465, 466, -468, 472, 473, 475, 476, 477, 479, 481, 482, 483, 484, 485, 487, 488, 491, 492, -493, 497, 499, 502, 503, 504, 506, 508, 509, 512, 513, 515, 517, 518, 519, 521, -523, 528, 532, 535, 536, 537, 539, 556, 558, 562, 577, 582, 587, 589, 591, 594, -595, 596, 597, 598, 599, 600, 601, 603, 604, 605, 606, 608, 609, 611, 612, 614, -616, 617, 639, 640, 650, 651, 665, 676, 678, 685, 686, 694, 697, 698, 700, 702, -704, 705, 719, 720, 721, 722, 723, 724, 725, 727, 728, 730, 734, 736, 738, 744, -745, 746, 752, 758, 760, 762, 763, 764, 799, 805, 811, 812, 814, 815, 816, 818, -819, 827, 844, 845, 848, 850, 851, 852, 853, 854, 860, 863, 867, 870, 871, 885, -887, 890, 891, 896, 904, 910, 916, 921, 931, 933, 947, 962, 968, 978, 980, 981, -985, 986, 1007, 1010, 1011, 1015, 1043, 1047, 1050, 1065, 1068, 1117, 1118, -1121, 1122, 1124, 1126, 1136, 1169, 1194, 1207, 1209, 1213. -\:\\{list\_tag}, \[1092], 1105, 1106. -\:\\{lk\_offset}, 1135, 1137, 1138, 1139, \[1205]. -\:\\{lk\_started}, \[1096], 1107, 1112, 1137, 1138, 1139. -\:\\{ll}, \[1096], 1110, 1111, 1139. -\:\\{llink}, \[166], 168, 169, 171, 172, 173, 176, 182, 1207. -\:\\{lll}, \[1096], 1110, 1111. -\:\\{lo\_mem\_max}, \[159], 163, 167, 168, 176, 178, 180, 182, 183, 184, 185, -1045, 1194, 1195, 1207, 1208. -\:\\{lo\_mem\_stat\_max}, \[175], 176, 1195, 1207. -\:\\{load\_base\_file}, \[1187], 1211. -\:\\{loc}, \[35], 36, 82, 627, \[629], 630, 632, 636, 638, 644, 645, 649, 652, -654, 656, 657, 669, 671, 672, 673, 674, 676, 678, 679, 681, 712, 717, 736, 779, -781, 793, 794, 795, 1211. -\:\\{loc\_field}, 34, 35, \[627], 629. -\:\.{local label l:: was missing}, 1139. -\:\\{log\_file}, \[54], 56, 70, 788, 1205. -\:\\{log\_name}, \[782], 788, 1205. -\:\\{log\_only}, \[54], 57, 58, 62, 70, 93, 679, 788, 1022, 1200. -\:\\{log\_opened}, 87, 88, \[782], 783, 788, 789, 1023, 1205, 1208. -\:\.{Logarithm...replaced by 0}, 134. -\:\\{long\_help\_seen}, \[1084], 1085, 1086. -\:\&{loop}, 15, \[16]. -\:\.{loop confusion}, 714. -\:\.{loop value=n}, 762. -\:\\{loop\_defining}, \[659], 664, 665, 758. -\:\\{loop\_list}, \[752], 760, 763, 764. -\:\\{loop\_list\_loc}, \[752], 764. -\:\\{loop\_node\_size}, \[752], 755, 763. -\:\\{loop\_ptr}, 712, 713, 714, \[752], 753, 758, 760, 763, 1209. -\:\\{loop\_repeat}, 685. -\:\\{loop\_text}, \[632], 638, 714, 760. -\:\\{loop\_type}, \[752], 755, 760, 763, 764, 765. -\:\.{Lost loop}, 712. -\:\\{ls}, \[46]. -\:\\{lt}, \[46], \[286], 289, 294, 295, \[299], 302. -\:\|{m}, \[47], \[64], \[311], \[333], \[337], \[348], \[357], \[369], \[373], % -\[473], \[484], \[511], \[574], \[580], \[608], \[625], \[626], \[641], \[694], -\[697], \[755], \[788], \[913], \[1029], \[1082], \[1098], \[1118], \[1120], % -\[1121], \[1123], \[1165], \[1177], \[1212]. -\:\\{m\_adjustment}, \[580], 581, 582. -\:\\{m\_exp}, \[135], 906. -\:\9{m\_exp\_}{\&{mexp} primitive}, \[893]. -\:\\{m\_exp\_op}, \[189], 893, 906. -\:\\{m\_log}, \[132], 134, 152, 906. -\:\9{m\_log\_}{\&{mlog} primitive}, \[893]. -\:\\{m\_log\_op}, \[189], 893, 906. -\:\\{m\_magic}, \[354], 361, 362, 365. -\:\\{m\_max}, \[326], 329, 334, 337, 342, 348, 352, 354, 356, 357, 364, 366, -965, 1172. -\:\\{m\_min}, \[326], 329, 334, 337, 342, 348, 352, 354, 356, 357, 364, 365, -366, 965, 1172. -\:\\{m\_offset}, \[326], 328, 329, 333, 334, 337, 342, 348, 352, 364, 365, 366, -367, 373, 375, 376, 381, 382, 383, 384, 581, 965, 1169, 1172. -\:\\{m\_spread}, 356, \[357], 364. -\:\\{m\_window}, \[572], 576, 581. -\:\\{mac\_name}, \[862], \[864], \[868]. -\:\\{macro}, \[632], 638, 645, 649, 736. -\:\\{macro\_at}, \[688], 689. -\:\\{macro\_call}, 707, 718, 719, \[720], 853, 854, 863. -\:\\{macro\_def}, \[186], 683, 684, 685, 694, 698, 992, 1043. -\:\\{macro\_name}, \[720], 721, 725, 726, 734, 736. -\:\\{macro\_prefix}, \[688], 689. -\:\\{macro\_ref}, \[843], 845, 854. -\:\\{macro\_special}, \[186], 685, 688, 689, 700. -\:\\{macro\_suffix}, \[688], 689, 700. -\:\\{main\_control}, \[1017], 1204, 1211. -\:\\{major\_axis}, \[527], 530, 533, \[865], 866. -\:\\{make\_choices}, \[269], 274, 277, 278, 891. -\:\\{make\_ellipse}, \[527], 528, 866. -\:\\{make\_eq}, 995, 1000, \[1001]. -\:\\{make\_exp\_copy}, 651, 823, 852, \[855], 859, 903, 910, 926, 927, 944, -967, 970, 973, 1000. -\:\\{make\_fraction}, \[107], 109, 116, 125, 127, 145, 152, 281, 288, 289, 290, -291, 294, 295, 296, 300, 302, 375, 376, 436, 439, 444, 454, 498, 516, 522, 530, -533, 540, 548, 549, 612, 818, 944. -\:\\{make\_known}, \[603], 604, 614, 818, 819. -\:\\{make\_moves}, 309, \[311], 321, 468, 512, 514, 518, 550. -\:\\{make\_name\_string}, \[780]. -\:\\{make\_op\_def}, \[694], 992. -\:\\{make\_path}, \[484], 921, 962. -\:\9{make\_path\_}{\&{makepath} primitive}, \[893]. -\:\\{make\_path\_op}, \[189], 893, 921. -\:\\{make\_pen}, \[477], 865. -\:\9{make\_pen\_}{\&{makepen} primitive}, \[893]. -\:\\{make\_pen\_op}, \[189], 893, 921. -\:\\{make\_safe}, \[426], 427, 436, 439, 440, 446. -\:\\{make\_scaled}, \[114], 116, 600, 612, 819, 837, 948, 949, 980, 1128, 1129, -1164, 1182. -\:\\{make\_spec}, \[402], 403, 409, 448, 460, 493, 917, 1064. -\:\\{make\_string}, \[44], 48, 52, 207, 671, 772, 780, 840, 897, 912, 976, 977, -1164, 1200, 1205. -\:{Marple, Jane}, 1086. -\:\\{materialize\_pen}, 864, \[865], 921, 983. -\:\\{max}, \[539], 543. -\:\\{max\_allowed}, 402, \[403], 404, 434, 437. -\:\\{max\_buf\_stack}, \[29], 30, 657, 717, 1208. -\:\\{max\_c}, 812, \[813], 814, 815, 816, 817. -\:\\{max\_class}, \[198]. -\:\\{max\_coef}, \[495], 496, \[591], 932, 943, 949. -\:\\{max\_command\_code}, \[186], 821, 823, 824, 868. -\:\\{max\_d}, \[348], 351, 352. -\:\\{max\_expression\_command}, \[186], 868. -\:\\{max\_font\_dimen}, \[11], 1096, 1115, 1141. -\:\\{max\_given\_internal}, \[190], 191, 1199. -\:\\{max\_halfword}, 11, 12, 14, \[153], 154, 156, 166, 167, 168, 173, 174, -204, 214, 324, 348, 351, 358, 1207. -\:\\{max\_in\_open}, \[12], 631, 632, 654, 1190, 1191. -\:\\{max\_in\_stack}, \[628], 647, 657, 1208. -\:\\{max\_internal}, \[11], 190, 204, 1036, 1199, 1208. -\:\\{max\_kerns}, \[11], 1096, 1106, 1112, 1141. -\:\\{max\_link}, 812, \[813], 814, 815, 818, 819. -\:\\{max\_m}, 1144, \[1146], \[1161]. -\:\\{max\_n}, \[348], 351, 352, 1144, \[1146], \[1161]. -\:\\{max\_new\_row}, \[1145], 1173. -\:\\{max\_offset}, \[472], 475, 477, 962, 1064. -\:\\{max\_param\_stack}, \[633], 657, 736, 737, 1208. -\:\\{max\_patience}, \[555], 556. -\:\\{max\_pool\_ptr}, \[38], 41, 47, 1045, 1193, 1204, 1208. -\:\\{max\_primary\_command}, \[186], 823, 836, 862, 864, 868, 989, 990. -\:\\{max\_print\_line}, \[11], 14, 54, 58, 61, 67, 333, 372, 793, 1046, 1048, -1165. -\:\\{max\_ptr}, \[813], 814, 815, 816. -\:\\{max\_quarterword}, \[153], 154, 156, 399, 404, 481. -\:\\{max\_rounding\_ptr}, \[427], 428, 429, 1208. -\:\\{max\_secondary\_command}, \[186], 862. -\:\\{max\_selector}, \[54], 196, 635, 788. -\:\\{max\_statement\_command}, \[186], 989. -\:\\{max\_str\_ptr}, \[38], 44, 47, 772, 1045, 1193, 1204, 1208. -\:\\{max\_str\_ref}, \[42], 43, 48, 52, 207, 793, 1193, 1200. -\:\\{max\_strings}, \[11], 37, 44, 154, 772, 780, 1045, 1193, 1208. -\:\\{max\_suffix\_token}, \[186], 844. -\:\\{max\_t}, \[555], 556. -\:\\{max\_tertiary\_command}, \[186], 864. -\:\\{max\_tfm\_dimen}, 1128, 1129, \[1130], 1182. -\:\\{max\_wiggle}, \[11], 426, 427, 429, 440, 1208. -\:\\{mc}, \[477], 478, 479. -\:{Meggitt, John E.}, 143. -\:\\{mem}, 11, 12, 158, \[159], 161, 166, 168, 173, 175, 176, 178, 180, 185, -214, 216, 229, 241, 242, 244, 250, 255, 264, 326, 334, 435, 472, 475, 587, 594, -738, 752, 827, 947, 961, 1194, 1195, 1213. -\:\\{mem\_end}, 159, \[161], 163, 176, 178, 180, 181, 184, 185, 218, 1194, -1195, 1208. -\:\\{mem\_max}, \[11], 12, 14, 153, 154, 159, 163, 166, 167, 178, 179. -\:\\{mem\_min}, \[12], 14, 154, 158, 159, 163, 167, 168, 175, 176, 178, 179, -180, 182, 183, 184, 185, 218, 1190, 1191, 1194, 1195, 1208. -\:\\{mem\_top}, 11, \[12], 14, 154, 159, 175, 176, 1190, 1191, 1195. -\:\.{Memory usage...}, 1045. -\:\\{memory\_word}, 153, \[156], 157, 159, 242, 1188. -\:\\{merge\_edges}, \[366], 929, 1061. -\:\9{message\_}{\&{message} primitive}, \[1079]. -\:\\{message\_code}, \[1079], 1082. -\:\\{message\_command}, \[186], 1079, 1080, 1081. -\:\.{METAFONT capacity exceeded ...}, 89. -\:\9{METAFONT capacity exceeded buffer size}{\quad buffer size}, 34, 654, 717. -\:\9{METAFONT capacity exceeded extensible}{\quad extensible}, 1113. -\:\9{METAFONT capacity exceeded fontdimen}{\quad fontdimen}, 1115. -\:\9{METAFONT capacity exceeded hash size}{\quad hash size}, 207. -\:\9{METAFONT capacity exceeded headerbyte}{\quad headerbyte}, 1114. -\:\9{METAFONT capacity exceeded input stack size}{\quad input stack size}, 647. -\:\9{METAFONT capacity exceeded kern}{\quad kern}, 1112. -\:\9{METAFONT capacity exceeded ligtable size}{\quad ligtable size}, 1107. -\:\9{METAFONT capacity exceeded main memory size}{\quad main memory size}, 163, -167. -\:\9{METAFONT capacity exceeded move table size}{\quad move table size}, 356, -468, 508. -\:\9{METAFONT capacity exceeded number of int}{\quad number of internals}, 1036. -\:\9{METAFONT capacity exceeded number of strings}{\quad number of strings}, -44, 772. -\:\9{METAFONT capacity exceeded parameter stack size}{\quad parameter stack -size}, 704, 736, 737. -\:\9{METAFONT capacity exceeded path size}{\quad path size}, 281. -\:\9{METAFONT capacity exceeded pen polygon size}{\quad pen polygon size}, 481. -\:\9{METAFONT capacity exceeded pool size}{\quad pool size}, 41. -\:\9{METAFONT capacity exceeded rounding table size}{\quad rounding table -size}, 429. -\:\9{METAFONT capacity exceeded text input levels}{\quad text input levels}, -654. -\:\9{METAFONTbook}{\sl The {\logos METAFONT\/}book}, 1, 199, 574, 824, 872, -873, 878, 990, 991, 1068, 1203. -\:\9{METAFONT84}{\MF84}, \[1]. -\:\\{metric\_file\_name}, \[1087], 1134. -\:\\{MF}, \[4]. -\:\.{MF.POOL check sum...}, 53. -\:\.{MF.POOL doesn't match}, 53. -\:\.{MF.POOL has no check sum}, 52. -\:\.{MF.POOL line doesn't...}, 52. -\:\\{MF\_area}, \[769], 793. -\:\\{MF\_base\_default}, \[775], 776, 778. -\:\.{MFbases}, 11, 776. -\:\.{MFinputs}, 769. -\:\.{mfput}, 34, 788. -\:\\{mid}, \[1094]. -\:\\{min\_col}, \[580], 581, 582, 583. -\:\\{min\_command}, \[186], 706, 715, 718. -\:\\{min\_cover}, \[1118], 1120. -\:\\{min\_d}, \[348], 351, 352. -\:\\{min\_expression\_command}, \[186], 868, 869. -\:\\{min\_halfword}, 12, \[153], 154, 155, 156, 324, 326, 337, 342, 348, 350, -365, 375, 376, 381, 382, 383, 384, 580. -\:\\{min\_m}, 1144, \[1146], \[1161]. -\:\\{min\_n}, \[348], 351, 352, 1144, \[1146], \[1161]. -\:\\{min\_of}, \[189], 923. -\:\\{min\_primary\_command}, \[186], 823, 837, 862, 864, 868, 989. -\:\\{min\_quarterword}, \[153], 154, 155, 156, 1093. -\:\\{min\_secondary\_command}, \[186], 862. -\:\\{min\_suffix\_token}, \[186], 844. -\:\\{min\_tension}, \[883]. -\:\\{min\_tertiary\_command}, \[186], 864. -\:\\{minor\_axis}, \[527], 530, 533, \[865], 866. -\:\\{minus}, \[189], 859, 893, 898, 903, 922, 929, 930, 936, 939. -\:\.{Missing `)'}, 727, 735, 1032. -\:\.{Missing `)'...}, 725. -\:\.{Missing `,'}, 727, 878. -\:\.{Missing `..'}, 881. -\:\.{Missing `:'}, 747, 751, 756, 1106. -\:\.{Missing `:='}, 1021. -\:\.{Missing `;'}, 713. -\:\.{Missing `='}, 693, 755, 1035. -\:\.{Missing `\char`\#'}, 1113. -\:\.{Missing `\char`\}'}, 875. -\:\.{Missing `]'}, 859, 861. -\:\.{Missing `of'}, 734, 839. -\:\.{Missing `until'}, 765. -\:\.{Missing argument...}, 726. -\:\.{Missing parameter type}, 703. -\:\.{Missing symbolic token...}, 691. -\:\.{Missing...inserted}, 94. -\:\\{missing\_err}, \[94], 693, 713, 727, 734, 735, 747, 751, 755, 756, 765, -839, 859, 861, 875, 878, 881, 1021, 1032, 1035, 1106, 1113. -\:\\{missing\_extensible\_punctuation}, \[1113]. -\:\\{ml}, \[329]. -\:\\{mm}, \[348], 349, \[357], 358, 362, 364, \[580], 582, \[1165], 1169. -\:\\{mm0}, \[511], 513, 517, 519, 523. -\:\\{mm1}, \[511], 513, 517, 519, 523. -\:{mock curvature}, 275. -\:\\{mode\_command}, \[186], 1023, 1024, 1025. -\:{Moler, Cleve Barry}, 124. -\:\\{month}, \[190], 192, 193, 194, 790, 1163, 1200. -\:\9{month\_}{\&{month} primitive}, \[192]. -\:\\{months}, \[788], 790. -\:\\{more\_name}, 767, \[771], 781, 787. -\:{Morrison, Donald Ross}, 124. -\:\\{move}, \[308], 311, 315, 316, 319, 320, 321, 322, 354, 356, 357, 362, 364, -378, 379, 381, 382, 383, 384, 468, 507, 512, 514, 517, 518, 520, 523. -\:\\{move\_increment}, \[309], 310, 312, 314. -\:\\{move\_ptr}, \[308], 311, 315, 316, 319, 320, 468, 511, 512, 513, 514, 515, -516, 517, 518, 519, 520, 521, 522, 523. -\:\\{move\_size}, \[11], 308, 311, 321, 356, 357, 362, 378, 468, 507, 508, 511. -\:\\{move\_to\_edges}, \[378], 465, 517, 523. -\:\\{mr}, \[329]. -\:\&{mtype}, \[4]. -\:\.{Must increase the x}, 1187. -\:\\{my\_var\_flag}, \[823], 841, 852, \[868]. -\:\\{m0}, \[374], 375, 376, \[378], 380, 381, 382, 383, 384, \[464], 465, 467, -508, 511, 517, 523. -\:\\{m1}, \[374], 375, 376, \[378], 380, 463, \[464], 465, 467, 508, 511, 517, -523. -\:\|{n}, \[47], \[64], \[65], \[89], \[107], \[109], \[112], \[114], \[242], % -\[246], \[280], \[284], \[311], \[332], \[348], \[366], \[369], \[373], \[374], -\[378], \[473], \[477], \[484], \[488], \[491], \[497], \[511], \[539], \[562], -\[568], \[574], \[580], \[610], \[641], \[667], \[697], \[720], \[722], \[723], -\[755], \[773], \[774], \[778], \[863], \[913], \[916], \[944], \[985], % -\[1046], \[1165], \[1212]. -\:\\{n\_arg}, \[139], 140, 141, 147, 256, 281, 282, 292, 293, 301, 387, 541, -544, 866, 877, 907. -\:\\{n\_cos}, \[144], 145, 259, 263, 297, 301, 530, 533, 906, 958. -\:\\{n\_magic}, \[354], 361, 362, 365. -\:\\{n\_max}, \[326], 329, 331, 332, 334, 336, 340, 348, 352, 364, 365, 366, -965, 1167. -\:\\{n\_min}, \[326], 329, 330, 334, 336, 340, 348, 352, 364, 366, 577, 965, -1172. -\:\\{n\_pos}, \[326], 330, 331, 334, 336, 352, 364, 374, 377, 378, 965. -\:\\{n\_rover}, \[326], 330, 331, 334, 352, 364, 374, 377, 378. -\:\\{n\_sin}, \[144], 145, 259, 263, 297, 301, 530, 533, 906, 958. -\:\\{n\_sin\_cos}, 144, \[145], 147, 259, 263, 297, 301, 530, 906, 958. -\:\\{n\_window}, \[572], 576, 577. -\:\\{name}, 627, \[629], 630, 631, 632, 635, 637, 638, 649, 654, 655, 657, 679, -717, 736, 793, 897. -\:\\{name\_field}, 79, \[627], 629. -\:\\{name\_length}, \[25], 51, 774, 778, 780. -\:\\{name\_of\_file}, \[25], 26, 51, 774, 778, 780, 786. -\:\\{name\_type}, 188, \[214], 215, 219, 228, 229, 230, 232, 233, 234, 235, -236, 237, 238, 239, 240, 244, 245, 246, 247, 249, 254, 619, 651, 678, 702, 738, -744, 745, 799, 806, 830, 856, 857, 911, 931, 982, 1047, 1209. -\:\\{nd}, 1088, 1089, \[1096], 1126, 1135, 1141. -\:\\{ne}, 1088, 1089, \[1096], 1097, 1113, 1135, 1140, 1141. -\:\\{NE\_SW\_edge}, \[435]. -\:\\{negate}, \[16], 64, 103, 107, 110, 114, 118, 139, 146, 380, 409, 411, 412, -414, 415, 416, 418, 423, 424, 425, 480, 882, 903, 904, 930, 959, 1007, 1068. -\:\\{negate\_dep\_list}, 903, \[904], 930, 959. -\:\\{negate\_edges}, \[344], 345, 903, 929. -\:\\{negate\_x}, \[139], 390, 406, 409, 411, 418, 480, 489. -\:\\{negate\_y}, \[139], 390, 406, 414, 415, 418, 437, 438, 439, 480, 489. -\:\\{negative}, \[107], \[109], 110, \[112], \[114]. -\:\.{New busy locs}, 184. -\:\\{new\_boundary}, \[451], 452, 458. -\:\\{new\_dep}, \[606], 615, 829, 856, 858, 947, 969, 972. -\:\\{new\_if\_limit}, \[748]. -\:\\{new\_indep}, \[585], 586, 816, 855. -\:\\{new\_internal}, \[186], 211, 212, 1033. -\:\9{new\_internal\_}{\&{newinternal} primitive}, \[211]. -\:\\{new\_knot}, 870, \[871], 885, 908. -\:\\{new\_num\_tok}, \[215], 236, 860. -\:\\{new\_randoms}, 148, \[149], 150. -\:\\{new\_ring\_entry}, \[619], 855. -\:\\{new\_root}, \[234], 242, 1011. -\:\\{new\_row\_0}, 1144, \[1145], 1173. -\:\\{new\_row\_1}, \[1144]. -\:\\{new\_row\_164}, \[1144], 1145. -\:\\{new\_string}, \[54], 57, 58, 840, 912, 1163, 1164, 1200. -\:\\{new\_structure}, \[239], 243. -\:\\{next}, \[200], 202, 205, 207. -\:\\{next\_a}, \[426], \[440], 446. -\:\\{next\_char}, \[1093], 1107, 1112, 1137. -\:\\{next\_random}, \[149], 151, 152. -\:\\{nh}, 1088, 1089, \[1096], 1126, 1135, 1141. -\:\\{ni}, 1088, 1089, \[1096], 1126, 1135, 1141. -\:\\{nice\_pair}, \[899], 900, 907, 915, 941, 975, 983, 1072. -\:\&{nil}, 16. -\:\\{ninety\_deg}, \[106], 141, 530. -\:\\{nk}, 1088, 1089, \[1096], 1097, 1112, 1135, 1139, 1141. -\:\\{nl}, \[329], 330, 1088, 1089, 1093, \[1096], 1097, 1107, 1110, 1111, 1112, -1135, 1137, 1139, 1141. -\:\\{nn}, \[562]. -\:\.{No loop is in progress}, 713. -\:\.{No new edges added}, 372. -\:\\{no\_crossing}, \[391], 392. -\:\\{no\_op}, \[1144], 1147. -\:\\{no\_print}, \[54], 57, 58, 70, 93. -\:\\{no\_tag}, \[1092], 1096, 1097, 1104. -\:\\{node\_size}, \[166], 168, 169, 170, 172, 176, 182, 1194, 1195, 1207. -\:\\{node\_to\_round}, 426, \[427], 429, 436, 439, 444, 445, 446. -\:\.{NONEXISTENT}, 218. -\:\\{nonlinear\_eq}, \[621], 1003. -\:\.{Nonnumeric...replaced by 0}, 830. -\:\\{nonstop\_mode}, \[68], 81, 679, 682, 897, 1024, 1025. -\:\9{nonstop\_mode\_}{\&{nonstopmode} primitive}, \[1024]. -\:\\{norm\_rand}, \[152], 895. -\:\\{normal}, \[659], 660, 661, 694, 697, 730, 738, 739, 742, 758, 991, 1016. -\:\\{normal\_deviate}, \[189], 893, 895. -\:\9{normal\_deviate\_}{\&{normaldeviate} primitive}, \[893]. -\:\\{normalize\_selector}, 73, \[87], 88, 89, 90. -\:\\{north\_edge}, \[435], 438. -\:\\{north\_south\_edge}, \[435]. -\:\.{Not a cycle}, 1067. -\:\.{Not a string}, 716, 1082. -\:\.{Not a suitable variable}, 1060. -\:\.{Not implemented...}, 901, 923. -\:\9{not\_}{\&{not} primitive}, \[893]. -\:\\{not\_found}, \[15], 45, 394, 477, 479, 491, 494, 496, 539, 541, 556, 560, -561, 760, 1001, 1004, 1059, 1064, 1067, 1071, 1073, 1074, 1075. -\:\\{not\_op}, \[189], 893, 905. -\:\\{nothing\_printed}, \[473], 474. -\:\\{np}, 1088, 1089, \[1096], 1097, 1115, 1135, 1140, 1141. -\:\\{nr}, \[329], 331. -\:\\{nuline}, \[197], \[257], \[332], \[473]. -\:\\{null}, \[158], 159, 161, 163, 165, 167, 168, 176, 177, 181, 182, 202, 214, -216, 217, 226, 227, 229, 232, 233, 234, 235, 237, 242, 246, 249, 251, 252, 253, -254, 257, 258, 324, 346, 355, 364, 368, 398, 472, 475, 477, 479, 487, 528, 532, -536, 537, 587, 589, 591, 594, 597, 599, 600, 604, 605, 607, 609, 611, 612, 614, -615, 616, 617, 618, 619, 620, 632, 636, 638, 639, 640, 650, 651, 652, 665, 676, -685, 686, 694, 697, 698, 700, 707, 712, 713, 714, 716, 718, 719, 720, 721, 722, -723, 724, 726, 728, 730, 734, 735, 736, 738, 739, 746, 752, 753, 754, 755, 760, -762, 763, 764, 795, 801, 802, 805, 806, 807, 810, 811, 812, 816, 818, 819, 840, -844, 845, 848, 850, 851, 852, 853, 854, 857, 902, 904, 924, 925, 926, 927, 928, -929, 930, 931, 933, 934, 935, 936, 942, 943, 944, 945, 948, 949, 968, 970, 972, -997, 998, 1000, 1003, 1006, 1007, 1008, 1009, 1010, 1011, 1015, 1035, 1040, -1041, 1043, 1048, 1049, 1050, 1057, 1061, 1064, 1068, 1070, 1071, 1074, 1194, -1195, 1207, 1209, 1213. -\:\\{null\_coords}, \[175], 214, 475. -\:\\{null\_pen}, \[175], 435, 438, 442, 475, 477, 487, 865, 895, 917, 962, 1062. -\:\9{null\_pen\_}{\&{nullpen} primitive}, \[893]. -\:\\{null\_pen\_code}, \[189], 893, 895. -\:\9{null\_picture\_}{\&{nullpicture} primitive}, \[893]. -\:\\{null\_picture\_code}, \[189], 893, 895. -\:\\{null\_tally}, \[217]. -\:\\{nullary}, \[186], 713, 823, 893, 894, 895. -\:\\{num}, \[116], \[296], \[836], 837. -\:\9{num\_special\_}{\&{numspecial} primitive}, \[1176]. -\:\.{Number too large}, 914. -\:\9{numeric\_}{\&{numeric} primitive}, \[1013]. -\:\\{numeric\_token}, \[186], 651, 675, 678, 823, 824, 836, 837, 844, 846, 860, -861, 1016, 1042. -\:\\{numeric\_type}, \[187], 189, 229, 242, 248, 585, 798, 802, 809, 855, 918, -1013. -\:\\{nw}, 1088, 1089, \[1096], 1124, 1135, 1141. -\:\\{NW\_SE\_edge}, \[435]. -\:\\{n0}, \[373], \[374], 375, 376, 377, \[378], 380, 382, 383, 384, \[464], -465, 467, 468, 508, 513, 515, 517, 519, 521, 523. -\:\\{n1}, \[373], \[374], 375, 376, \[378], 380, 463, \[464], 465, 467, 468, -508, 513, 517, 519, 523. -\:\|{o}, \[210], \[431], \[477]. -\:\\{obliterated}, \[851], 852, 1000, 1057. -\:\9{oct\_}{\&{oct} primitive}, \[893]. -\:\\{oct\_op}, \[189], 893, 912, 913, 914. -\:\\{octant}, \[139], 141, \[379], 380, \[387], \[388], \[394], 434, 437, % -\[451], 463, 465, 468, 473, 479, 480, 481, 484, 485, \[488], 489, 506, 508, -509, 510, 512, 513, 515, 516, 518, 519, 521, 522. -\:\\{octant\_after}, \[390]. -\:\\{octant\_before}, \[390]. -\:\\{octant\_code}, \[448], 449, 458, 473, 481, 484. -\:\\{octant\_dir}, 394, \[395], 396, 398, 401, 509. -\:\\{octant\_number}, \[448], 449, 452, 459, 479, 488, 508, 512. -\:\\{octant\_subdivide}, 402, \[419]. -\:\\{odd}, 62, 111, 113, 145, 390, 417, 434, 435, 436, 442, 445, 459, 473, 482, -483, 484, 488, 508, 512, 530, 560, 906. -\:\9{odd\_}{\&{odd} primitive}, \[893]. -\:\\{odd\_op}, \[189], 893, 906. -\:\9{of\_}{\&{of} primitive}, \[211]. -\:\\{of\_macro}, \[226], 227, 705, 733. -\:\\{of\_token}, \[186], 211, 212, 705, 734, 839. -\:\\{off\_base}, \[1187], 1189, 1191, 1195, 1199. -\:\\{offset\_prep}, \[491], 494, 500, 506. -\:\.{OK}, 1051. -\:\\{OK\_to\_interrupt}, 83, \[91], 92, 93, 653, 825. -\:\\{old\_exp}, \[922], 925, 927, \[944]. -\:\\{old\_p}, \[922], 925, 926. -\:\\{old\_rover}, \[173]. -\:\\{old\_setting}, 195, \[196], \[635], 636, \[788], 840, 912, 1022, 1163, -1164. -\:\\{one\_byte}, \[1161]. -\:\\{one\_crossing}, \[391]. -\:\\{one\_eighty\_deg}, \[106], 139, 141, 292, 544. -\:\\{oo}, \[477], 479. -\:\\{op\_byte}, \[1093], 1107, 1112, 1137. -\:\\{op\_defining}, \[659], 664, 665, 694, 700. -\:\\{open}, \[256], 258, 262, 263, 271, 272, 273, 280, 282, 284, 285, 865, 868, -870, 874, 875, 877, 879, 885, 887, 888, 889, 890, 891, 896. -\:\.{open?}, 258, 262. -\:\\{open\_a\_window}, \[574], 1073. -\:\\{open\_base\_file}, \[779], 1211. -\:\\{open\_log\_file}, 73, 87, 679, \[788], 789, 791, 793, 895, 1134, 1209. -\:\\{open\_parens}, \[631], 657, 681, 793, 1209. -\:\\{open\_window}, \[186], 211, 212, 1069. -\:\9{open\_window\_}{\&{openwindow} primitive}, \[211]. -\:\9{or\_}{\&{or} primitive}, \[893]. -\:\\{or\_op}, \[189], 893, 940. -\:\\{ord}, 20. -\:{oriental characters}, 1147. -\:\&{othercases}, \[10]. -\:\\{others}, 10. -\:\.{Ouch...clobbered}, 1204. -\:\.{Out of order...}, 617. -\:\9{outer\_}{\&{outer} primitive}, \[1027]. -\:\\{outer\_tag}, \[186], 242, 249, 254, 668, 759, 850, 1029, 1041. -\:\\{output}, \[4]. -\:\.{Output written...}, 1182. -\:\\{output\_file\_name}, \[791], 792, 1163, 1182. -\:\\{over}, \[189], 837, 893, 948. -\:\\{overflow}, 34, 41, 44, \[89], 163, 167, 207, 281, 356, 429, 468, 481, 508, -647, 654, 704, 705, 717, 736, 737, 772, 1036, 1107, 1112, 1113, 1114, 1115, -1205. -\:{Overflow in arithmetic}, 9. -\:\\{o1}, 452, \[453], 458, 459. -\:\\{o2}, 452, \[453], 458, 459. -\:\|{p}, \[107], \[109], \[112], \[114], \[163], \[167], \[172], \[173], % -\[177], \[180], \[185], \[205], \[215], \[216], \[217], \[226], \[227], \[232], -\[233], \[234], \[235], \[238], \[239], \[242], \[246], \[247], \[248], \[249], -\[252], \[253], \[254], \[257], \[264], \[265], \[266], \[268], \[269], \[284], -\[299], \[328], \[329], \[332], \[334], \[336], \[337], \[340], \[342], \[344], -\[346], \[348], \[354], \[366], \[369], \[374], \[378], \[385], \[394], \[398], -\[402], \[405], \[406], \[410], \[419], \[429], \[433], \[440], \[451], \[465], -\[473], \[477], \[484], \[486], \[487], \[488], \[491], \[493], \[497], \[506], -\[510], \[518], \[527], \[539], \[556], \[562], \[577], \[589], \[591], \[594], -\[597], \[599], \[600], \[601], \[603], \[604], \[606], \[608], \[609], \[610], -\[619], \[620], \[621], \[622], \[641], \[649], \[650], \[651], \[652], \[661], -\[685], \[694], \[697], \[707], \[720], \[722], \[730], \[737], \[746], \[748], -\[755], \[760], \[763], \[799], \[800], \[801], \[805], \[807], \[809], \[823], -\[827], \[848], \[855], \[856], \[858], \[860], \[862], \[863], \[864], \[865], -\[868], \[872], \[898], \[899], \[904], \[910], \[916], \[919], \[922], \[923], -\[928], \[930], \[935], \[943], \[944], \[946], \[949], \[953], \[961], \[962], -\[963], \[966], \[968], \[971], \[972], \[974], \[976], \[977], \[978], \[982], -\[984], \[985], \[995], \[996], \[1001], \[1006], \[1015], \[1046], \[1050], % -\[1057], \[1059], \[1072], \[1117], \[1118], \[1121], \[1165], \[1186], % -\[1187], \[1205]. -\:\\{p\_over\_v}, \[600], 819, 932, 949. -\:\\{p\_plus\_fq}, 592, \[594], 597, 601, 818, 819, 932, 968, 971, 1010. -\:\\{p\_plus\_q}, \[597], 932, 1010. -\:\\{p\_times\_v}, \[599], 943, 969. -\:\\{p\_with\_x\_becoming\_q}, \[601], 614. -\:\\{pack\_buffered\_name}, \[778], 779. -\:\\{pack\_cur\_name}, \[784], 786, 793. -\:\\{pack\_file\_name}, \[774], 784, 793. -\:\\{pack\_job\_name}, \[784], 788, 791, 1134, 1200. -\:\\{packed\_ASCII\_code}, \[37], 38. -\:\\{page}, \[631]. -\:\\{page\_stack}, \[631]. -\:\\{paint\_row}, 3, 564, 566, \[568], 569, 571, 578, 579. -\:\\{paint\_switch}, \[1143], 1144. -\:\\{paint\_0}, 1144, \[1145], 1159. -\:\\{paint1}, 1144, \[1145], 1159. -\:\\{paint2}, \[1144]. -\:\\{paint3}, \[1144]. -\:\9{pair\_}{\&{pair} primitive}, \[1013]. -\:\\{pair\_node\_size}, \[230], 231. -\:\\{pair\_to\_path}, \[908], 921, 975, 983, 988, 1003, 1062. -\:\\{pair\_type}, \[187], 216, 230, 231, 232, 248, 798, 799, 800, 802, 808, -809, 830, 837, 855, 868, 870, 872, 877, 898, 899, 900, 903, 909, 917, 918, 919, -921, 926, 927, 929, 936, 941, 942, 944, 946, 948, 952, 957, 975, 982, 983, 988, -995, 1001, 1002, 1003, 1013, 1062. -\:\\{pair\_value}, \[982], 984, 987, 988. -\:\\{panicking}, \[178], 179, 825, 1213. -\:\\{param}, 1090, 1095, \[1096], 1106, 1115, 1140. -\:\\{param\_ptr}, \[633], 649, 650, 657, 736, 737. -\:\\{param\_size}, \[12], 214, 633, 677, 697, 704, 705, 736, 737, 1208. -\:\\{param\_stack}, 632, \[633], 639, 640, 650, 676, 677, 720, 736, 737. -\:\\{param\_start}, \[632], 639, 640, 649, 650, 676, 677. -\:\\{param\_type}, \[186], 227, 695, 696, 697, 703. -\:\\{parameter}, \[632], 638, 677. -\:\\{parent}, \[229], 236, 239, 240, 241, 245. -\:\9{PASCAL H}{\ph}, \[3], 26. -\:\9{PASCAL}{\PASCAL}, 1, 10. -\:\\{pass\_text}, 706, \[742], 749, 751. -\:\.{Path at line...}, 257. -\:\9{path\_}{\&{path} primitive}, \[1013]. -\:\\{path\_intersection}, \[562], 988. -\:\\{path\_join}, \[186], 211, 212, 874, 881, 886, 887. -\:\\{path\_length}, 915, \[916], 978. -\:\\{path\_size}, \[11], 279, 280, 281, 283, 284. -\:\\{path\_tail}, 266, \[267], 1065. -\:\\{path\_trans}, 952, \[962]. -\:\\{path\_type}, \[187], 216, 248, 621, 798, 802, 804, 808, 809, 855, 868, -870, 885, 891, 908, 915, 917, 918, 919, 920, 921, 952, 975, 983, 988, 1003, -1013, 1062. -\:\.{Paths don't touch}, 887. -\:\\{pause\_for\_instructions}, 91, \[93]. -\:\\{pausing}, \[190], 192, 193, 682. -\:\9{pausing\_}{\&{pausing} primitive}, \[192]. -\:\\{pd}, \[357], 358, 360. -\:\.{Pen cycle must be convex}, 478. -\:\.{Pen path must be a cycle}, 865. -\:\.{Pen too large}, 478. -\:\9{pen\_}{\&{pen} primitive}, \[1013]. -\:\\{pen\_circle}, \[189], 893, 895. -\:\9{pen\_circle\_}{\&{pencircle} primitive}, \[893]. -\:\\{pen\_edge}, \[433], 435, 438, \[440], 442, 443. -\:\\{pen\_head}, \[484]. -\:\\{pen\_node\_size}, 175, \[472], 477, 487. -\:\9{pen\_offset\_}{\&{penoffset} primitive}, \[893]. -\:\\{pen\_offset\_of}, \[189], 893, 983. -\:\\{pen\_type}, \[187], 216, 248, 621, 798, 802, 804, 808, 809, 855, 865, 895, -918, 919, 921, 952, 962, 983, 1003, 1013, 1052, 1053, 1054, 1055. -\:\\{percent\_class}, \[198], 199, 217, 669. -\:\\{period\_class}, \[198], 199, 669. -\:\\{perturbation}, 1118, \[1119], 1120, 1121, 1122, 1123, 1124, 1126. -\:\\{phi}, 541, \[542], 544. -\:\9{picture\_}{\&{picture} primitive}, \[1013]. -\:\\{picture\_type}, \[187], 216, 248, 621, 798, 802, 804, 808, 809, 855, 895, -898, 903, 918, 919, 921, 929, 952, 1003, 1013, 1057, 1061, 1070. -\:\\{pixel\_color}, \[565], 566, 568, 580. -\:\.{plain}, 776, 779, 1203. -\:\.{Please type...}, 679, 786. -\:\\{plus}, \[189], 859, 893, 898, 922, 930. -\:\\{plus\_or\_minus}, \[186], 823, 836, 837, 893, 894. -\:\\{pm}, \[357], 358, 360. -\:\9{point\_}{\&{point} primitive}, \[893]. -\:\\{point\_of}, \[189], 893, 983, 987. -\:\\{pointer}, \[158], 159, 161, 163, 166, 167, 172, 173, 177, 178, 180, 185, -200, 205, 215, 216, 225, 226, 227, 232, 233, 234, 235, 238, 239, 242, 246, 247, -248, 249, 250, 252, 253, 254, 257, 264, 265, 266, 267, 268, 269, 280, 284, 299, -326, 327, 328, 329, 332, 333, 334, 336, 337, 340, 342, 344, 346, 348, 354, 366, -369, 373, 374, 378, 385, 394, 398, 402, 403, 405, 406, 410, 419, 427, 429, 433, -440, 451, 465, 473, 476, 477, 484, 486, 487, 488, 491, 493, 497, 506, 510, 511, -518, 527, 539, 556, 562, 577, 589, 591, 592, 594, 597, 599, 600, 601, 603, 604, -606, 607, 608, 609, 610, 619, 620, 621, 622, 633, 649, 650, 651, 652, 661, 685, -694, 697, 707, 718, 720, 722, 723, 730, 737, 738, 746, 748, 752, 755, 760, 763, -799, 800, 801, 805, 807, 809, 813, 823, 827, 843, 848, 851, 855, 856, 858, 860, -862, 863, 864, 865, 868, 871, 872, 898, 904, 910, 916, 919, 922, 923, 928, 930, -935, 943, 944, 946, 949, 953, 961, 962, 963, 966, 968, 971, 972, 974, 976, 977, -978, 982, 984, 985, 995, 996, 1001, 1006, 1011, 1015, 1031, 1032, 1035, 1046, -1050, 1057, 1059, 1071, 1072, 1074, 1117, 1118, 1121, 1125, 1165, 1186, 1187, -1205. -\:\\{pool\_file}, 47, \[50], 51, 52, 53. -\:\\{pool\_name}, \[11], 51. -\:\\{pool\_pointer}, \[37], 38, 45, 46, 59, 60, 77, 210, 707, 768, 774, 913, -976, 1160. -\:\\{pool\_ptr}, 37, \[38], 40, 41, 43, 44, 47, 52, 58, 771, 780, 1045, 1163, -1192, 1193, 1204. -\:\\{pool\_size}, \[11], 37, 41, 52, 58, 780, 1045, 1193, 1208. -\:\\{pop\_input}, \[648], 650, 655. -\:\\{post}, 1142, 1144, \[1145], 1146, 1148, 1182. -\:\\{post\_head}, 842, \[843], 844, 845, 851, 852, 854. -\:\\{post\_post}, 1144, \[1145], 1146, 1148, 1182. -\:\9{postcontrol\_}{\&{postcontrol} primitive}, \[893]. -\:\\{postcontrol\_of}, \[189], 893, 983, 987. -\:\\{pp}, \[242], 243, 244, 245, \[265], \[266], \[334], 335, \[340], 341, % -\[366], 367, 368, \[406], 413, 414, 415, 416, 417, 418, \[440], 444, 445, 446, % -\[556], 558, \[562], \[589], 590, \[594], 595, \[597], 598, \[755], 765, % -\[809], 816, \[868], 885, 886, 887, 889, 890, \[966], 970, \[978], 980, 981, % -\[1006], 1009, 1010. -\:\\{pre}, 1142, 1144, \[1145], 1163. -\:\\{pre\_head}, 842, \[843], 844, 850, 851, 852, 853, 854. -\:\9{precontrol\_}{\&{precontrol} primitive}, \[893]. -\:\\{precontrol\_of}, \[189], 893, 983, 987. -\:\\{prev\_dep}, \[587], 603, 606, 617, 799, 811, 816, 827, 931, 947, 1007. -\:\\{prev\_m}, \[1165], 1169, 1170, 1171. -\:\\{prev\_n}, \[1165], 1167, 1172, 1174. -\:\\{prev\_r}, \[610], 614. -\:\\{prev\_w}, \[348], 349, 350, \[1165], 1169, 1170, 1171. -\:\9{primary\_}{\&{primary} primitive}, \[695]. -\:\\{primary\_binary}, \[186], 189, 823, 839, 893, 894. -\:\9{primary\_def\_}{\&{primarydef} primitive}, \[683]. -\:\\{primary\_macro}, \[226], 227, 695, 733. -\:\\{primitive}, 192, \[210], 211, 212, 625, 683, 688, 695, 709, 740, 893, -1013, 1018, 1024, 1027, 1037, 1052, 1079, 1101, 1108, 1176, 1203, 1204. -\:\\{print}, 54, \[59], 60, 62, 66, 68, 79, 80, 81, 84, 85, 89, 90, 94, 122, -128, 134, 187, 189, 197, 212, 217, 218, 219, 221, 222, 227, 235, 237, 257, 258, -259, 260, 261, 262, 263, 332, 372, 394, 397, 398, 401, 509, 510, 515, 521, 589, -613, 625, 638, 639, 643, 644, 663, 664, 665, 682, 684, 689, 696, 710, 721, 723, -725, 734, 741, 750, 754, 786, 788, 790, 802, 804, 805, 807, 817, 824, 832, 839, -851, 900, 902, 923, 924, 945, 997, 998, 999, 1002, 1008, 1019, 1025, 1028, -1032, 1034, 1038, 1041, 1043, 1045, 1048, 1050, 1053, 1057, 1080, 1098, 1102, -1105, 1109, 1123, 1139, 1140, 1163, 1164, 1180, 1182, 1192, 1194, 1196, 1200, -1208, 1209, 1212, 1213. -\:\\{print\_arg}, 721, \[723], 728, 734. -\:\\{print\_capsule}, 217, 219, \[224], 1042. -\:\\{print\_char}, \[58], 59, 60, 63, 64, 65, 77, 85, 89, 90, 103, 104, 157, -184, 185, 189, 197, 209, 212, 219, 220, 221, 222, 223, 224, 227, 237, 254, 259, -263, 332, 333, 372, 373, 394, 398, 401, 509, 589, 590, 602, 603, 613, 626, 637, -643, 681, 689, 725, 762, 790, 793, 802, 803, 806, 817, 824, 900, 902, 914, 924, -945, 990, 998, 1002, 1008, 1022, 1041, 1042, 1045, 1046, 1050, 1057, 1134, -1163, 1164, 1165, 1182, 1194, 1200, 1205, 1213. -\:\\{print\_cmd\_mod}, 212, 227, \[625], 626, 751, 824, 839, 990, 1041, 1043, -1209, 1213. -\:\\{print\_dd}, \[65], 790, 1163. -\:\\{print\_dependency}, \[589], 613, 805, 817, 1050. -\:\\{print\_diagnostic}, \[197], 257, 332, 372, 394, 473. -\:\\{print\_dp}, 802, 803, \[805]. -\:\\{print\_edges}, \[332], 804, 1165. -\:\\{print\_err}, 67, \[68], 88, 89, 90, 93, 94, 99, 122, 128, 134, 140, 270, -340, 342, 398, 404, 478, 602, 623, 661, 663, 670, 672, 675, 691, 701, 703, 708, -712, 713, 725, 726, 751, 786, 795, 807, 824, 832, 838, 851, 865, 887, 914, 963, -965, 990, 991, 1004, 1008, 1015, 1016, 1017, 1032, 1034, 1051, 1056, 1057, -1067, 1073, 1074, 1086, 1098, 1105, 1107, 1110. -\:\\{print\_exp}, 224, 639, 723, 762, \[801], 807, 902, 924, 945, 997, 998, -1040, 1046. -\:\\{print\_file\_name}, \[773], 786. -\:\\{print\_int}, \[64], 79, 89, 103, 157, 181, 182, 183, 184, 185, 197, 209, -222, 237, 332, 333, 372, 397, 398, 509, 515, 521, 617, 637, 661, 723, 790, 832, -914, 1045, 1105, 1139, 1140, 1163, 1164, 1165, 1182, 1192, 1194, 1196, 1200, -1209, 1213. -\:\\{print\_known\_or\_unknown\_type}, \[900], 901, 923. -\:\\{print\_ln}, \[57], 58, 61, 62, 66, 81, 84, 85, 86, 157, 195, 257, 394, -473, 638, 643, 656, 665, 679, 682, 721, 788, 793, 1023, 1041, 1043, 1045, 1165, -1192, 1194, 1196. -\:\\{print\_locs}, \[180]. -\:\\{print\_macro\_name}, 721, \[722], 725, 726, 734. -\:\\{print\_nl}, \[62], 68, 77, 79, 80, 86, 181, 182, 183, 184, 185, 195, 197, -209, 254, 257, 259, 332, 333, 372, 373, 394, 397, 398, 473, 474, 509, 510, 515, -521, 603, 613, 617, 626, 637, 638, 639, 665, 679, 723, 725, 762, 786, 788, 807, -817, 902, 924, 945, 994, 997, 998, 1022, 1040, 1041, 1045, 1046, 1048, 1050, -1082, 1123, 1128, 1134, 1139, 1140, 1169, 1182, 1200, 1205, 1209, 1212. -\:\\{print\_op}, \[189], 894, 901, 902, 923, 924. -\:\\{print\_path}, \[257], 269, 402, 804. -\:\\{print\_pen}, \[473], 477, 484, 804. -\:\\{print\_scaled}, \[103], 104, 122, 128, 134, 157, 220, 254, 259, 260, 263, -589, 590, 602, 603, 802, 803, 817, 912, 945, 1008, 1022, 1042, 1123. -\:\\{print\_spec}, \[394], 402. -\:\\{print\_strange}, \[398], 399, 1068. -\:\\{print\_the\_digs}, \[63], 64. -\:\\{print\_two}, \[104], 258, 261, 394, 473, 510. -\:\\{print\_two\_true}, \[394], 397, 474, 509, 515, 521. -\:\\{print\_type}, \[187], 189, 802, 804, 806, 900, 1002, 1014, 1057. -\:\\{print\_variable\_name}, 221, \[235], 589, 603, 613, 664, 802, 803, 806, -817, 1046, 1048, 1050, 1213. -\:\\{print\_weight}, 332, \[333]. -\:\\{print\_word}, \[157], 1213. -\:\\{procrustes}, \[404]. -\:\\{progression\_node\_size}, \[752], 763, 765. -\:\\{prompt\_file\_name}, \[786], 789, 791, 793, 1134, 1200. -\:\\{prompt\_input}, \[66], 78, 82, 679, 682, 786, 897. -\:\\{proofing}, \[190], 192, 193, 994, 1070, 1147, 1165, 1177. -\:\9{proofing\_}{\&{proofing} primitive}, \[192]. -\:\\{protection\_command}, \[186], 1026, 1027, 1028. -\:\\{proto\_dependent}, \[187], 216, 248, 588, 589, 594, 597, 599, 601, 603, -610, 612, 798, 799, 800, 802, 808, 809, 812, 813, 815, 817, 818, 819, 855, 857, -903, 932, 943, 949, 968, 969, 971, 972, 1003, 1010. -\:\\{pseudo}, \[54], 57, 58, 59, 60, 642. -\:\\{psi}, \[279], 281, 290, 294, 297. -\:\\{push\_input}, \[647], 649, 654. -\:\\{put}, 25, 28, 1188. -\:\\{put\_get\_error}, 270, 340, 342, 404, 478, 623, \[820], 865, 873, 887, -901, 914, 923, 950, 955, 963, 965, 993, 999, 1000, 1002, 1004, 1008, 1015, -1016, 1051, 1057, 1067, 1068, 1073, 1074, 1082, 1086, 1098, 1105, 1106, 1178. -\:\\{put\_get\_flush\_error}, 716, 754, \[820], 830, 852, 872, 876, 878, 883, -892, 937, 960, 1021, 1055, 1056, 1060, 1061, 1062, 1071, 1103, 1112, 1115. -\:\\{pyth\_add}, \[124], 145, 281, 454, 530, 533, 866, 915, 951. -\:\\{pyth\_sub}, \[126], 951. -\:\\{pythag\_add}, \[189], 893, 951. -\:\\{pythag\_sub}, \[189], 893, 951. -\:\.{Pythagorean...}, 128. -\:\|{q}, \[107], \[109], \[112], \[114], \[117], \[121], \[145], \[167], % -\[172], \[173], \[177], \[180], \[185], \[216], \[217], \[227], \[232], \[233], -\[235], \[239], \[242], \[246], \[247], \[249], \[252], \[253], \[254], \[257], -\[264], \[265], \[266], \[268], \[269], \[284], \[299], \[311], \[328], \[329], -\[332], \[333], \[336], \[337], \[340], \[342], \[344], \[346], \[348], \[354], -\[366], \[369], \[385], \[394], \[398], \[402], \[405], \[406], \[410], \[419], -\[433], \[440], \[451], \[465], \[477], \[491], \[493], \[506], \[518], \[527], -\[539], \[556], \[577], \[589], \[594], \[597], \[601], \[603], \[604], \[606], -\[608], \[609], \[610], \[619], \[620], \[621], \[622], \[641], \[685], \[694], -\[697], \[720], \[722], \[723], \[746], \[755], \[760], \[763], \[801], \[805], -\[809], \[823], \[827], \[851], \[855], \[858], \[863], \[865], \[868], \[871], -\[898], \[919], \[922], \[928], \[930], \[935], \[943], \[946], \[949], \[953], -\[961], \[962], \[966], \[968], \[972], \[978], \[985], \[996], \[1001], % -\[1006], \[1015], \[1046], \[1059], \[1117], \[1121], \[1165], \[1186], \[1187]. -\:\\{qi}, \[155], 1107, 1110, 1111, 1112, 1113, 1137, 1192. -\:\\{qo}, \[155], 1110, 1111, 1133, 1193. -\:\\{qq}, 229, \[242], 245, \[265], \[266], \[334], \[366], 367, 368, \[406], -413, 414, 415, 416, 417, 418, \[556], 558, \[594], 595, 596, \[597], 598, % -\[868], 885, 886, 887, 890, \[966], 970, \[978], 980, 981. -\:\\{qqq}, 229. -\:\\{qqqq}, 153, \[156], 157, 1188, 1189. -\:\\{qqq1}, 229. -\:\\{qqq2}, 229. -\:\\{qq1}, 229. -\:\\{qq2}, 229. -\:\\{quad}, 1095. -\:\\{quad\_code}, \[1095]. -\:\\{quadrant\_subdivide}, 402, \[406], 426. -\:\\{quarter\_unit}, \[101]. -\:\\{quarterword}, 153, \[156], 189, 627, 649, 823, 895, 898, 899, 901, 910, -913, 919, 922, 923, 930, 953, 960, 962, 963, 966, 985. -\:\\{quote}, \[688], 690. -\:\9{quote\_}{\&{quote} primitive}, \[688]. -\:\\{q1}, 229. -\:\|{r}, \[117], \[124], \[126], \[145], \[167], \[173], \[177], \[180], % -\[217], \[227], \[233], \[235], \[239], \[242], \[246], \[247], \[268], \[284], -\[311], \[332], \[334], \[336], \[337], \[340], \[344], \[346], \[348], \[354], -\[366], \[373], \[374], \[378], \[402], \[406], \[410], \[419], \[451], \[465], -\[476], \[477], \[491], \[493], \[506], \[518], \[527], \[567], \[568], \[577], -\[594], \[597], \[599], \[600], \[601], \[604], \[606], \[610], \[621], \[622], -\[694], \[697], \[720], \[809], \[823], \[855], \[858], \[863], \[868], \[922], -\[928], \[930], \[946], \[953], \[966], \[968], \[971], \[1006], \[1104], % -\[1117], \[1121]. -\:\\{r\_delim}, \[697], 703, \[720], 725, 726, 727, 729, \[730], 731, 735, % -\[823], 826, 830, 1031, \[1032]. -\:\\{r\_packet}, 560. -\:\\{r\_packets}, \[553], 558. -\:{Ramshaw, Lyle Harold}, 2, 469, 1087. -\:\\{random\_seed}, \[186], 211, 212, 1020. -\:\9{random\_seed\_}{\&{randomseed} primitive}, \[211]. -\:\\{randoms}, \[148], 149, 150, 151, 152. -\:\\{rd}, \[357], 358, 359. -\:\\{read}, 52, 53, 1212, 1213. -\:\\{read\_ln}, 52. -\:\9{read\_string\_}{\&{readstring} primitive}, \[893]. -\:\\{read\_string\_op}, \[189], 893, 895. -\:\\{ready\_already}, \[1203], 1204. -\:\\{real}, 3, 120. -\:{recursion}, 71, 73, 217, 224, 246, 706, 719, 748, 796, 995, 1041. -\:\\{recycle\_value}, 224, 246, 247, 650, 763, 808, \[809], 810, 829, 873, 903, -910, 922, 925, 935, 944, 955, 968, 970, 972, 1000, 1001. -\:\\{reduce\_angle}, \[292], 293. -\:\.{Redundant equation}, 623. -\:\.{Redundant or inconsistent equation}, 1004. -\:\\{ref\_count}, \[226], 475, 477, 487, 694, 697, 854, 862, 864, 868. -\:{reference counts}, 42, 226, 632. -\:\\{relax}, \[186], 211, 212, 686, 706, 707. -\:\\{rem\_byte}, \[1093], 1107, 1112, 1137. -\:\\{remainder}, \[1091], 1092, 1093, 1096. -\:\\{remove\_cubic}, \[405], 417, 447, 492. -\:\\{rep}, \[1094]. -\:\\{repeat\_loop}, \[186], 706, 707, 759, 1043. -\:\\{reset}, 25, 26, 32. -\:\\{reset\_OK}, \[26]. -\:\\{restart}, \[15], 167, 168, 667, 668, 670, 672, 676, 677, 679, 681, 691, -823, 853, 854, 855, 862, 864, 868, 1001, 1003. -\:\\{restore\_cur\_exp}, \[801]. -\:\\{result}, \[45], \[1054], 1056. -\:\\{resume\_iteration}, 706, 712, 755, \[760], 763. -\:\\{reswitch}, \[15], 748. -\:\.{retrograde line...}, 510. -\:\&{return}, 15, \[16]. -\:\\{return\_sign}, \[117], 118. -\:\\{rev\_turns}, 452, 454, \[455], 456, 1064. -\:\\{reverse}, \[189], 893, 921. -\:\9{reverse\_}{\&{reverse} primitive}, \[893]. -\:\\{reversed}, \[977], \[978]. -\:\\{rewrite}, 25, 26, 32. -\:\\{rewrite\_OK}, \[26]. -\:\\{rh}, 153, \[156], 157, 161, 200. -\:\\{rhs}, \[1059], 1062, 1064, 1065, 1066, 1067. -\:{Riesenfeld, Richard Franklin}, 303. -\:\\{right\_brace}, \[186], 211, 212, 875. -\:\\{right\_bracket}, \[186], 211, 212, 846, 859, 861, 1012. -\:\\{right\_bracket\_class}, \[198], 199, 220, 221. -\:\\{right\_class}, \[528], 531, 532, 534, 535. -\:\\{right\_col}, \[567], \[572], 574, 577, 581, 583, 584. -\:\\{right\_curl}, \[256], 263, 271, 282, 294, 890, 891. -\:\\{right\_delimiter}, \[186], 203, 726, 727, 731, 735, 1030, 1031, 1032, 1043. -\:\\{right\_edge}, \[580], 581, 582. -\:\\{right\_given}, \[256], 263, 282, 293, 301, 879, 888, 889. -\:\\{right\_octant}, \[393], 451, 452, 458, 459. -\:\\{right\_paren\_class}, \[198], 199, 219, 222. -\:\\{right\_tension}, \[256], 258, 260, 288, 289, 294, 295, 299, 300, 302, 881, -882, 886, 887. -\:\\{right\_transition}, \[393], 459, 509, 517, 523. -\:\\{right\_type}, \[255], 256, 258, 263, 265, 266, 269, 271, 272, 273, 282, -285, 290, 299, 302, 393, 394, 404, 405, 407, 409, 410, 411, 412, 413, 414, 415, -416, 417, 418, 421, 423, 424, 425, 426, 434, 435, 436, 437, 438, 439, 441, 442, -443, 445, 447, 450, 451, 452, 454, 457, 466, 479, 481, 486, 491, 494, 497, 499, -512, 515, 518, 521, 528, 539, 562, 563, 870, 871, 874, 879, 880, 884, 885, 888, -889, 890, 891, 896, 921, 962, 978, 987, 1065, 1066. -\:\\{right\_u}, \[528], 531, 532, 534, 535, 537. -\:\\{right\_x}, \[255], 256, 261, 265, 266, 271, 282, 299, 302, 393, 397, 404, -405, 407, 409, 410, 411, 412, 415, 416, 418, 419, 421, 423, 424, 425, 434, 436, -441, 444, 447, 457, 468, 486, 492, 496, 512, 518, 528, 543, 558, 563, 866, 884, -890, 896, 962, 987, 1065, 1066. -\:\\{right\_y}, \[255], 256, 261, 265, 266, 271, 282, 299, 302, 393, 397, 404, -405, 410, 413, 414, 415, 416, 419, 423, 424, 425, 437, 439, 444, 447, 457, 468, -486, 492, 496, 512, 518, 528, 543, 558, 563, 866, 884, 890, 896, 962, 987, -1065, 1066. -\:\\{ring\_delete}, \[620], 809. -\:\\{ring\_merge}, \[622], 1003. -\:\\{rising}, \[497]. -\:\\{rlink}, \[166], 167, 168, 169, 171, 172, 173, 174, 176, 182, 1194, 1195, -1207. -\:\\{rm}, \[357], 358, 359. -\:\\{root}, \[188], 229, 230, 234, 239, 254, 702. -\:\\{rotate}, 389. -\:\9{rotated\_}{\&{rotated} primitive}, \[893]. -\:\\{rotated\_by}, \[189], 893, 952, 957. -\:\\{round\_decimals}, \[102], 103, 674. -\:\\{round\_fraction}, \[119], 590, 600, 817, 819, 906, 958, 1010. -\:\\{round\_unscaled}, \[119], 374, 375, 376, 575, 576, 790, 906, 912, 965, -977, 1056, 1070, 1071, 1073, 1103, 1106, 1137, 1163, 1165, 1181, 1200. -\:\\{rover}, \[166], 167, 168, 169, 170, 171, 172, 173, 174, 176, 182, 1194, -1195, 1207. -\:\\{row\_node\_size}, \[325], 330, 331, 334, 341, 352, 353, 354, 355, 358, -364, 385. -\:\\{row\_transition}, 578, \[579], 580, 582, 583, 584. -\:\\{rr}, \[242], 245, \[266], \[299], 300, \[334], 335, \[340], \[366], 368, % -\[922], 939, \[978], 980. -\:\\{rt}, \[286], 289, 294, 295, \[299], 302. -\:\\{runaway}, 163, 663, \[665]. -\:\\{r0}, \[574], 575, 576, \[1073]. -\:\\{r1}, 229, \[574], 575, \[1073]. -\:\|{s}, \[43], \[45], \[46], \[58], \[59], \[60], \[62], \[88], \[89], \[90], % -\[94], \[103], \[167], \[172], \[197], \[210], \[232], \[242], \[257], \[280], % -\[284], \[311], \[332], \[337], \[340], \[342], \[344], \[346], \[348], \[354], -\[394], \[398], \[402], \[406], \[419], \[465], \[473], \[477], \[488], \[495], -\[497], \[506], \[518], \[527], \[594], \[597], \[599], \[600], \[601], \[604], -\[610], \[754], \[755], \[784], \[786], \[807], \[809], \[824], \[930], \[943], -\[949], \[966], \[977], \[1160]. -\:\\{s\_scale}, \[585], 589, 608, 610, 817. -\:\\{safety\_margin}, \[402]. -\:\9{save\_}{\&{save} primitive}, \[211]. -\:\\{save\_boundary\_item}, \[250], 832. -\:\\{save\_command}, \[186], 211, 212, 1033. -\:\\{save\_cond\_ptr}, \[748], 749. -\:\\{save\_exp}, \[651], \[718]. -\:\\{save\_flag}, \[824]. -\:\\{save\_internal}, \[253], 1034. -\:\\{save\_node\_size}, \[250], 252, 253, 254. -\:\\{save\_ptr}, \[250], 251, 252, 253, 254. -\:\\{save\_type}, \[651]. -\:\\{save\_variable}, \[252], 1033. -\:\\{save\_word}, \[242], 244. -\:\.{SAVED}, 235. -\:\\{saved\_equiv}, \[250], 252, 254. -\:\\{saved\_root}, \[188], 230, 235, 247, 249. -\:\\{saving}, \[249]. -\:\\{sc}, 153, \[156], 157, 229, 255, 472, 752, 961. -\:\\{scaled}, \[101], 102, 103, 104, 105, 112, 114, 116, 119, 121, 132, 135, -150, 151, 152, 153, 156, 187, 190, 194, 214, 215, 228, 229, 250, 259, 279, 280, -286, 296, 299, 304, 306, 311, 369, 374, 387, 388, 389, 390, 402, 403, 406, 410, -419, 426, 427, 429, 430, 431, 432, 433, 434, 440, 463, 477, 486, 488, 497, 510, -511, 527, 539, 542, 555, 574, 585, 587, 588, 594, 599, 600, 602, 607, 612, 798, -808, 820, 836, 865, 868, 875, 916, 917, 935, 944, 946, 949, 954, 961, 968, 971, -972, 974, 978, 982, 985, 1073, 1096, 1098, 1117, 1118, 1119, 1120, 1121, 1128, -1129, 1130, 1144, 1146, 1147, 1182, 1205. -\:\.{Scaled picture...big}, 340, 342. -\:\9{scaled\_}{\&{scaled} primitive}, \[893]. -\:\\{scaled\_by}, \[189], 893, 952, 957. -\:\\{scaled\_threshold}, \[594], 597. -\:\\{scaling\_down}, \[599], \[600]. -\:\\{scan\_declared\_variable}, 700, \[1011], 1015. -\:\\{scan\_def}, \[697], 992. -\:\\{scan\_direction}, \[875], 879, 880. -\:\\{scan\_expression}, 706, 729, 733, 734, 764, 765, 796, 798, 821, 826, 830, -839, 846, 859, 861, \[868], 876, 877, 878, 892, 993, 995, 996, 1021, 1040, -1054, 1059, 1070, 1071, 1072, 1073, 1082, 1103, 1106, 1112, 1115, 1177. -\:\\{scan\_file\_name}, \[781], 795. -\:\\{scan\_primary}, 706, 716, 733, 734, 796, 798, 821, \[823], 835, 837, 839, -842, 862, 882, 884, 893, 1059, 1071, 1074. -\:\\{scan\_secondary}, 706, 733, 796, 798, 821, \[862], 864. -\:\\{scan\_suffix}, 706, 729, 735, 764, 840, \[860]. -\:\\{scan\_tertiary}, 706, 733, 796, 798, 821, \[864], 868, 869. -\:\\{scan\_text\_arg}, 729, \[730], 733. -\:\\{scan\_tokens}, \[186], 211, 212, 706, 707. -\:\9{scan\_tokens\_}{\&{scantokens} primitive}, \[211]. -\:\\{scan\_toks}, \[685], 694, 698, 758. -\:\\{scan\_with}, \[1054], 1062, 1074. -\:\\{scanner\_status}, \[659], 660, 661, 663, 664, 665, 694, 697, 700, 730, -742, 758, 991, 1016. -\:\\{screen\_col}, \[565], 566, 567, 568, 572, 580. -\:\\{screen\_depth}, \[11], 565, 567, 568, 575. -\:\\{screen\_OK}, \[569], 570, 574, 577. -\:\\{screen\_pixel}, \[566], 567, 568. -\:\\{screen\_row}, \[565], 566, 567, 568, 572. -\:\\{screen\_started}, \[569], 570. -\:\\{screen\_width}, \[11], 565, 567, 568, 575. -\:\\{scroll\_mode}, 66, \[68], 79, 81, 88, 786, 1024, 1025, 1084. -\:\9{scroll\_mode\_}{\&{scrollmode} primitive}, \[1024]. -\:\\{search\_mem}, 178, \[185], 1213. -\:\\{second\_octant}, \[139], 141, 380, 387, 388, 396, 435, 443, 449, 461, 462. -\:\9{secondary\_}{\&{secondary} primitive}, \[695]. -\:\\{secondary\_binary}, \[186], 893, 894. -\:\9{secondary\_def\_}{\&{secondarydef} primitive}, \[683]. -\:\\{secondary\_macro}, \[226], 227, 695, 696, 733. -\:\\{secondary\_primary\_macro}, \[186], 249, 683, 684, 862, 1035, 1043. -\:\.{see the transcript file...}, 1209. -\:\\{seed}, \[150]. -\:\\{selector}, \[54], 55, 57, 58, 59, 60, 62, 66, 70, 81, 86, 87, 93, 195, -635, 636, 642, 679, 788, 789, 804, 840, 912, 1022, 1023, 1163, 1164, 1200, -1205, 1209. -\:\\{semicolon}, \[186], 211, 212, 713, 732, 832, 989, 990, 991, 1017, 1051, -1070. -\:\\{sentinel}, \[175], 177, 324, 328, 330, 331, 332, 335, 339, 343, 344, 345, -346, 347, 348, 349, 355, 356, 358, 364, 367, 368, 369, 582, 1169. -\:\\{serial\_no}, \[585], 587, 1198, 1199. -\:\\{set\_controls}, 297, 298, \[299], 301. -\:\\{set\_min\_max}, \[554], 558, 559. -\:\\{set\_output\_file\_name}, \[791], 1163. -\:\\{set\_tag}, \[1104], 1106, 1111, 1113. -\:\\{set\_trick\_count}, \[642], 643, 644, 646. -\:\\{set\_two}, \[387], 388. -\:\\{set\_two\_end}, \[387]. -\:\\{set\_up\_direction\_time}, 983, \[984]. -\:\\{set\_up\_known\_trans}, \[960], 962, 963, 967. -\:\\{set\_up\_offset}, 983, \[984]. -\:\\{set\_up\_trans}, \[953], 960, 970. -\:\\{seventh\_octant}, \[139], 141, 380, 387, 388, 396, 435, 443, 449, 461, 462. -\:\\{sf}, \[116], 297, \[298], 299, 300, 301. -\:\9{shifted\_}{\&{shifted} primitive}, \[893]. -\:\\{shifted\_by}, \[189], 893, 952, 957. -\:\\{ship\_out}, 1070, 1149, \[1165], 1175. -\:\9{ship\_out\_}{\&{shipout} primitive}, \[211]. -\:\\{ship\_out\_command}, \[186], 211, 212, 1069. -\:\9{show\_}{\&{show} primitive}, \[1037]. -\:\\{show\_cmd\_mod}, \[626], 713, 895. -\:\\{show\_code}, \[1037], 1038, 1040, 1051. -\:\\{show\_command}, \[186], 1037, 1038, 1039. -\:\\{show\_context}, 54, 73, 77, 83, 634, \[635], 644, 786, 789, 793. -\:\\{show\_cur\_cmd\_mod}, \[626], 707, 832, 992. -\:\9{show\_dependencies\_}{\&{showdependencies} primitive}, \[1037]. -\:\\{show\_dependencies\_code}, \[1037], 1051. -\:\\{show\_macro}, \[227], 645, 721, 1041, 1048. -\:\9{show\_stats\_}{\&{showstats} primitive}, \[1037]. -\:\\{show\_stats\_code}, \[1037], 1038, 1051. -\:\9{show\_token\_}{\&{showtoken} primitive}, \[1037]. -\:\\{show\_token\_code}, \[1037], 1038, 1051. -\:\\{show\_token\_list}, \[217], 224, 227, 235, 639, 640, 645, 646, 665, 722, -723, 762, 840, 851, 998, 1043, 1057, 1213. -\:\9{show\_var\_}{\&{showvariable} primitive}, \[1037]. -\:\\{show\_var\_code}, \[1037], 1038, 1051. -\:\\{showstopping}, \[190], 192, 193, 1051. -\:\9{showstopping\_}{\&{showstopping} primitive}, \[192]. -\:\\{si}, \[37], 41, 85, 1193. -\:\9{sin\_d\_}{\&{sind} primitive}, \[893]. -\:\\{sin\_d\_op}, \[189], 893, 906. -\:\\{sine}, \[280], 281, \[299], 300. -\:\\{single\_dependency}, \[608], 829, 855, 858, 1007, 1009. -\:\\{sixth\_octant}, \[139], 141, 379, 380, 387, 388, 395, 396, 443, 448, 449, -461, 462, 488. -\:\\{skew}, \[387], 421, 445, 447, 451, 457, 481. -\:\\{skew\_line\_edges}, 508, \[510], 517, 523. -\:\\{skimp}, \[1121], 1124, 1126. -\:\\{skip\_byte}, \[1093], 1107, 1110, 1111, 1112, 1137. -\:\\{skip\_error}, \[1110], 1111. -\:\\{skip\_table}, \[1096], 1097, 1110, 1111, 1139. -\:\\{skip\_to}, \[186], 211, 212, 1107. -\:\9{skip\_to\_}{\&{skipto} primitive}, \[211]. -\:\\{skipping}, \[659], 661, 742. -\:\\{skip0}, 1144, \[1145], 1173. -\:\\{skip1}, 1144, \[1145], 1174. -\:\\{skip2}, \[1144]. -\:\\{skip3}, \[1144]. -\:\\{slant}, 1095. -\:\\{slant\_code}, \[1095]. -\:\9{slanted\_}{\&{slanted} primitive}, \[893]. -\:\\{slanted\_by}, \[189], 893, 952, 957. -\:\\{slash}, \[186], 837, 893, 894. -\:\\{slow\_add}, \[100], 594, 597, 930, 931, 933. -\:\\{slow\_case\_down}, \[378], 380. -\:\\{slow\_case\_up}, \[378], 380. -\:\\{slow\_print}, \[60], 61, 79, 219, 223, 254, 638, 664, 722, 725, 773, 790, -793, 802, 994, 998, 999, 1032, 1034, 1041, 1042, 1043, 1082, 1086, 1134, 1182, -1200, 1205, 1213. -\:{small computers}, 95. -\:\\{small\_number}, \[101], 102, 121, 135, 139, 145, 187, 210, 217, 230, 232, -238, 248, 311, 387, 388, 390, 394, 451, 453, 477, 589, 594, 597, 599, 600, 601, -610, 621, 651, 685, 738, 746, 778, 796, 801, 805, 809, 843, 875, 900, 930, 935, -943, 949, 966, 1001, 1015, 1054, 1098, 1104, 1123, 1177, 1209. -\:\\{smooth\_bot}, \[511], 512, 517, 518, 523. -\:\\{smooth\_moves}, \[321], 468, 517, 523. -\:\\{smooth\_top}, \[511], 512, 517, 518, 523. -\:\\{smoothing}, \[190], 192, 193, 468, 517, 523. -\:\9{smoothing\_}{\&{smoothing} primitive}, \[192]. -\:\\{so}, \[37], 45, 59, 60, 85, 210, 223, 717, 774, 913, 976, 977, 1103, 1160, -1192. -\:\\{solve\_choices}, 278, \[284]. -\:\.{some chardps...}, 1123. -\:\.{some charhts...}, 1123. -\:\.{some charics...}, 1123. -\:\.{some charwds...}, 1123. -\:\.{Some number got too big}, 270. -\:\.{Sorry, I can't find...}, 779. -\:\\{sort\_avail}, \[173], 1194. -\:\\{sort\_edges}, \[346], 348, 354, 578, 1169. -\:\\{sort\_in}, \[1117], 1124, 1126. -\:\\{sorted}, 324, \[325], 328, 330, 331, 332, 335, 339, 343, 344, 345, 346, -347, 348, 349, 355, 356, 358, 364, 367, 368, 369, 385, 580, 582, 1169. -\:\\{sorted\_loc}, \[325], 335, 345, 347, 368. -\:\\{south\_edge}, \[435], 438. -\:\\{space}, 1095. -\:\\{space\_class}, \[198], 199, 669. -\:\\{space\_code}, \[1095]. -\:\\{space\_shrink}, 1095. -\:\\{space\_shrink\_code}, \[1095]. -\:\\{space\_stretch}, 1095. -\:\\{space\_stretch\_code}, \[1095]. -\:\\{spec\_atan}, \[137], 138, 143, 147. -\:\\{spec\_head}, \[506]. -\:\\{spec\_log}, \[129], 131, 133, 136. -\:\9{special\_}{\&{special} primitive}, \[1176]. -\:\\{special\_command}, \[186], 1175, 1176, 1180. -\:\\{split\_cubic}, \[410], 411, 412, 415, 416, 424, 425, 493, 980, 981, 986. -\:\\{split\_for\_offset}, \[493], 499, 503, 504. -\:\\{spotless}, \[71], 72, 195, 1204, 1209. -\:\9{sqrt\_}{\&{sqrt} primitive}, \[893]. -\:\\{sqrt\_op}, \[189], 893, 906. -\:\.{Square root...replaced by 0}, 122. -\:\\{square\_rt}, \[121], 122, 906. -\:\\{ss}, \[242], 243, 245, \[299], 300, \[334], 335, \[340], \[978], 980. -\:\\{st}, \[116], 297, \[298], 299, 300, 301. -\:\\{st\_count}, \[200], 203, 207, 1196, 1197, 1208. -\:\\{stack\_argument}, \[737], 760. -\:\\{stack\_dx}, \[553], 559, 561. -\:\\{stack\_dy}, \[553], 559, 561. -\:\\{stack\_l}, \[309], 312, 314. -\:\\{stack\_m}, \[309], 312, 314. -\:\\{stack\_max}, \[553], 554, 556. -\:\\{stack\_min}, \[553], 554, 556. -\:\\{stack\_n}, \[309], 312, 314. -\:\\{stack\_r}, \[309], 312, 314. -\:\\{stack\_s}, \[309], 312, 314. -\:\\{stack\_size}, \[11], 628, 634, 647, 1208. -\:\\{stack\_tol}, \[553], 559, 561. -\:\\{stack\_uv}, \[553], 559, 561. -\:\\{stack\_xy}, \[553], 559, 561. -\:\\{stack\_x1}, \[309], 312, 314. -\:\\{stack\_x2}, \[309], 312, 314. -\:\\{stack\_x3}, \[309], 312, 314. -\:\\{stack\_y1}, \[309], 312, 314. -\:\\{stack\_y2}, \[309], 312, 314. -\:\\{stack\_y3}, \[309], 312, 314. -\:\\{stack\_1}, \[553], 554, 559, 560. -\:\\{stack\_2}, \[553], 554, 559, 560. -\:\\{stack\_3}, \[553], 554, 559, 560. -\:\\{start}, 627, \[629], 630, 632, 644, 645, 649, 650, 654, 655, 657, 679, -681, 682, 714, 717, 794, 897. -\:\\{start\_decimal\_token}, \[667], 669. -\:\\{start\_def}, \[683], 684, 697, 698, 700. -\:\\{start\_field}, \[627], 629. -\:\\{start\_forever}, \[683], 684, 755. -\:\\{start\_here}, 5, \[1204]. -\:\\{start\_input}, 706, 709, 711, \[793], 1211. -\:\\{start\_numeric\_token}, \[667], 669. -\:\\{start\_of\_MF}, \[6], 1204. -\:\\{start\_screen}, \[570], 574. -\:\\{start\_sym}, 1076, \[1077], 1078, 1198, 1199, 1204. -\:\\{stash\_cur\_exp}, 651, 718, 728, 734, 760, 764, \[799], 800, 801, 837, -839, 848, 859, 862, 863, 864, 868, 926, 946, 955, 970, 988, 995, 1000. -\:\\{stash\_in}, \[827], 830, 903. -\:\&{stat}, \[7], \[160], \[163], \[164], \[165], \[167], \[172], \[177], % -\[207], \[508], \[510], \[515], \[521], \[1045], \[1134], \[1205]. -\:\\{state}, 670. -\:\9{step\_}{\&{step} primitive}, \[211]. -\:\\{step\_size}, \[752], 760, 761, 765. -\:\\{step\_token}, \[186], 211, 212, 764. -\:{Stern, Moritz Abraham}, 526. -\:{Stolfi, Jorge}, 469. -\:\\{stop}, \[186], 732, 991, 1017, 1018, 1019. -\:\\{stop\_flag}, \[1093], 1107, 1110. -\:\\{stop\_iteration}, 706, 714, 760, \[763], 1209. -\:\\{store\_base\_file}, \[1186], 1209. -\:\9{str\_}{\&{str} primitive}, \[211]. -\:\\{str\_eq\_buf}, \[45], 205. -\:\\{str\_number}, \[37], 38, 42, 43, 44, 45, 46, 47, 62, 74, 88, 89, 90, 94, -190, 197, 210, 214, 257, 332, 394, 395, 398, 473, 754, 767, 774, 780, 782, 784, -785, 786, 791, 807, 824, 976, 977, 1087, 1160, 1183. -\:\\{str\_op}, \[186], 211, 212, 823. -\:\\{str\_pool}, 37, \[38], 41, 44, 45, 46, 47, 59, 60, 85, 200, 210, 223, 630, -707, 717, 774, 913, 976, 977, 1103, 1160, 1192, 1193, 1208. -\:\\{str\_ptr}, 37, \[38], 40, 43, 44, 47, 59, 60, 210, 218, 772, 780, 793, -798, 1045, 1163, 1192, 1193, 1199, 1200, 1204. -\:\\{str\_ref}, \[42], 43, 44, 48, 52, 207, 793, 1193, 1200. -\:\\{str\_room}, \[41], 207, 671, 771, 780, 897, 912, 976, 977, 1200, 1205. -\:\\{str\_start}, 37, \[38], 39, 40, 43, 44, 45, 46, 47, 59, 60, 85, 200, 210, -223, 717, 772, 774, 913, 976, 977, 1103, 1160, 1163, 1192, 1193. -\:\\{str\_to\_num}, 912, \[913]. -\:\\{str\_vs\_str}, \[46], 936, 1004. -\:\.{Strange path...}, 1068. -\:\.{String contains illegal digits}, 914. -\:{string pool}, 47, 1191. -\:\9{string\_}{\&{string} primitive}, \[1013]. -\:\\{string\_class}, \[198], 199, 219, 669. -\:\\{string\_token}, \[186], 671, 678, 691, 743, 823. -\:\\{string\_type}, \[187], 189, 214, 216, 219, 248, 621, 651, 716, 798, 802, -808, 809, 833, 840, 855, 895, 897, 912, 915, 918, 919, 936, 975, 993, 1003, -1004, 1013, 1082, 1103, 1176, 1177. -\:\\{string\_vacancies}, \[11], 52. -\:\\{structured}, \[187], 188, 228, 229, 239, 242, 243, 246, 247, 809, 850, -1046. -\:\\{structured\_root}, \[188], 229, 236, 239. -\:\9{subpath\_}{\&{subpath} primitive}, \[893]. -\:\\{subpath\_of}, \[189], 893, 975. -\:\\{subscr}, \[188], 229, 236, 239, 244, 246, 247, 1047. -\:\\{subscr\_head}, \[228], 229, 239, 240, 244, 246, 247, 1047. -\:\\{subscr\_head\_loc}, \[228], 240, 241, 244, 246. -\:\\{subscr\_node\_size}, \[229], 240, 244, 246, 247. -\:\\{subscript}, \[229], 236, 240, 244. -\:\\{subscript\_loc}, \[229], 244. -\:\\{subst\_list}, \[685], 686. -\:\9{substring\_}{\&{substring} primitive}, \[893]. -\:\\{substring\_of}, \[189], 893, 975. -\:\\{succumb}, \[88], 89, 90. -\:\.{SUFFIX}, 222. -\:\9{suffix\_}{\&{suffix} primitive}, \[695]. -\:\\{suffix\_base}, \[214], 222, 676, 677, 683, 690, 695, 696, 697, 705, 726, -729, 755, 764. -\:\\{suffix\_count}, \[685], 690. -\:\\{suffix\_macro}, \[226], 227, 705, 733. -\:\\{suffixed\_macro}, \[187], 700, 798, 809, 845, 1048. -\:\\{sum}, \[378]. -\:\\{switch}, \[667], 669, 670, 672. -\:\\{switch\_x\_and\_y}, \[139], 406, 423, 424, 441, 442, 445, 480, 489. -\:\\{sx}, \[601]. -\:\\{symmetric}, \[527], 528, 530. -\:{system dependencies}, 2, \[3], 4, 9, 10, 11, 12, 19, 21, 22, 25, 26, 27, 31, -32, 33, 34, 36, 49, 56, 59, 67, 76, 79, 91, 107, 109, 153, 155, 156, 194, 199, -564, 567, 568, 631, 637, 654, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, -776, 778, 780, 781, 794, 1148, 1152, 1154, 1203, 1204, 1205, 1212, 1214. -\:\\{s1}, \[77], 83. -\:\\{s2}, \[77], 83. -\:\\{s3}, \[77], 83. -\:\|{t}, \[46], \[116], \[139], \[145], \[167], \[187], \[197], \[238], \[242], -\[246], \[280], \[284], \[311], \[321], \[340], \[342], \[344], \[398], \[406], -\[410], \[419], \[493], \[495], \[497], \[542], \[589], \[594], \[597], \[601], -\[603], \[604], \[610], \[621], \[649], \[801], \[805], \[809], \[843], \[855], -\[860], \[868], \[875], \[899], \[900], \[930], \[935], \[943], \[949], \[968], -\[972], \[974], \[1001], \[1006], \[1011], \[1015], \[1029], \[1054], \[1057], % -\[1104], \[1160], \[1163]. -\:\\{t\_of\_the\_way}, \[410], 411, 415, 424, 499, 503, 504, 547, 548. -\:\\{t\_of\_the\_way\_end}, \[410]. -\:\\{t\_open\_in}, \[32], 36. -\:\\{t\_open\_out}, \[32], 1204. -\:\\{tag}, \[1091], 1092. -\:\\{tag\_token}, \[186], 202, 229, 234, 242, 249, 254, 702, 823, 844, 850, -860, 1011, 1035, 1043, 1049. -\:\\{tail}, \[720], 724, 728, 734, 842, \[843], 844, 845. -\:\\{tail\_end}, \[685]. -\:\\{take\_fraction}, \[109], 112, 116, 125, 127, 151, 152, 281, 287, 288, 289, -290, 291, 294, 295, 296, 297, 299, 300, 302, 375, 376, 410, 436, 439, 444, 454, -498, 516, 522, 530, 533, 543, 594, 595, 596, 599, 943, 944. -\:\\{take\_part}, 909, \[910], 939. -\:\\{take\_scaled}, \[112], 594, 595, 596, 599, 942, 943, 961, 968, 971, 974. -\:\\{tally}, \[54], 55, 57, 58, 217, 227, 235, 636, 639, 640, 641, 642, 643. -\:\\{tarnished}, 926, 927, \[928], 944. -\:\&{tats}, \[7]. -\:\\{temp\_head}, \[175], 335, 346, 347, 349, 351, 484, 594, 597, 599, 600, -601, 612, 616, 1117, 1118, 1121, 1124, 1126. -\:\\{temp\_val}, \[175], 910, 911. -\:\\{tension}, \[186], 211, 212, 881. -\:\9{tension\_}{\&{tension} primitive}, \[211]. -\:\\{term\_and\_log}, \[54], 57, 58, 66, 70, 87, 195, 788, 804, 1200, 1209. -\:\\{term\_in}, \[31], 32, 33, 35, 36, 66, 1212, 1213. -\:\\{term\_input}, \[66], 73. -\:\\{term\_offset}, \[54], 55, 57, 58, 61, 62, 66, 793, 1165. -\:\\{term\_only}, \[54], 55, 57, 58, 66, 70, 87, 789, 804, 1205, 1209. -\:\\{term\_out}, \[31], 32, 33, 34, 35, 36, 51, 56. -\:\\{terminal\_input}, \[631], 637, 654, 656. -\:\\{terminator}, \[685]. -\:\9{tertiary\_}{\&{tertiary} primitive}, \[695]. -\:\\{tertiary\_binary}, \[186], 893, 894. -\:\9{tertiary\_def\_}{\&{tertiarydef} primitive}, \[683]. -\:\\{tertiary\_macro}, \[226], 227, 695, 733. -\:\\{tertiary\_secondary\_macro}, \[186], 249, 683, 684, 864, 1035, 1043. -\:\\{test\_known}, 918, \[919]. -\:\\{text}, \[200], 202, 203, 205, 206, 207, 210, 218, 254, 638, 664, 722, 725, -727, 735, 759, 1032, 1034, 1036, 1041, 1043, 1196. -\:\.{TEXT}, 222. -\:\.{Text line contains...}, 670. -\:\9{text\_}{\&{text} primitive}, \[695]. -\:\\{text\_base}, \[214], 222, 677, 695, 697, 723, 729. -\:\\{text\_char}, \[19], 20, 24, 26, 47. -\:\\{text\_macro}, \[226], 227, 697, 705, 723, 733. -\:\9{TFM files}{\.{TFM} files}, 1087. -\:\\{tfm\_changed}, 1129, \[1130], 1132, 1136, 1140. -\:\\{tfm\_check}, \[1098], 1099. -\:\\{tfm\_command}, \[186], 1100, 1101, 1102. -\:\\{tfm\_depth}, \[1096], 1097, 1099, 1126, 1136. -\:\\{tfm\_file}, \[1087], 1133, 1134. -\:\\{tfm\_four}, \[1133], 1136, 1139, 1140. -\:\\{tfm\_height}, \[1096], 1097, 1099, 1126, 1136. -\:\\{tfm\_ital\_corr}, \[1096], 1097, 1099, 1126, 1136. -\:\\{tfm\_out}, \[1133], 1135, 1136, 1139. -\:\\{tfm\_qqqq}, \[1133], 1139, 1140. -\:\\{tfm\_two}, \[1133], 1135, 1139. -\:\\{tfm\_warning}, \[1123], 1124, 1126. -\:\\{tfm\_width}, \[1096], 1097, 1099, 1124, 1131, 1132, 1136, 1182, 1205. -\:\.{That makes 100 errors...}, 77. -\:\.{That transformation...}, 963. -\:\.{The token...delimiter}, 1032. -\:\.{The token...quantity}, 1034. -\:\.{There's unbounded black...}, 1169. -\:\\{theta}, \[283], 291, 292, 295, 297, \[527], 530, 533, \[542], 544, \[865], -866. -\:\\{thing\_to\_add}, \[186], 1052, 1053, 1059. -\:\\{third\_octant}, \[139], 141, 379, 380, 387, 388, 393, 396, 406, 443, 449, -461, 462. -\:\.{This can't happen}, 90. -\:\9{this can't happen /}{\quad \./}, 107, 114. -\:\9{this can't happen copy}{\quad copy}, 855. -\:\9{this can't happen dep}{\quad dep}, 589. -\:\9{this can't happen endinput}{\quad endinput}, 655. -\:\9{this can't happen exp}{\quad exp}, 802. -\:\9{this can't happen if}{\quad if}, 746. -\:\9{this can't happen m}{\quad m}, 311. -\:\9{this can't happen recycle}{\quad recycle}, 809. -\:\9{this can't happen struct}{\quad struct}, 239. -\:\9{this can't happen token}{\quad token}, 216. -\:\9{this can't happen var}{\quad var}, 236. -\:\9{this can't happen xy}{\quad xy}, 362. -\:\9{this can't happen 0}{\quad 0}, 378. -\:\.{This variable already...}, 701. -\:\\{three}, \[101], 296. -\:\\{three\_bytes}, \[1128], 1129, 1133, 1157, 1182. -\:\\{three\_choices}, \[156]. -\:\\{three\_l}, \[557], 558, 559, 560, 561. -\:\\{three\_quarter\_unit}, \[101], 883. -\:\\{three\_sixty\_deg}, \[106], 145, 292. -\:\\{three\_sixty\_units}, \[906], 958. -\:\\{threshold}, \[594], 595, 596, \[597], 598, \[599], \[600], \[1120], 1121. -\:\\{time}, \[190], 192, 193, 194, 790, 1163, 1211. -\:\9{time\_}{\&{time} primitive}, \[192]. -\:\\{time\_to\_go}, \[555], 556. -\:\\{times}, \[189], 837, 859, 893, 941, 944. -\:\&{tini}, \[8]. -\:\9{to\_}{\&{to} primitive}, \[211]. -\:\\{to\_token}, \[186], 211, 212, 1073. -\:{token}, 214. -\:\\{token}, \[188], 214, 215, 219, 651, 678. -\:\\{token\_list}, \[187], 670, 726, 728, 730, 798, 799, 809, 841, 852, 860, -996, 1059, 1070, 1071, 1074. -\:\\{token\_node\_size}, \[214], 215, 216, 651, 694, 704, 705, 755. -\:\\{token\_recycle}, 216, \[224]. -\:\\{token\_state}, \[632], 652, 672, 712, 736, 795, 1209. -\:\\{token\_type}, \[632], 635, 636, 638, 645, 649, 650, 653, 714. -\:\\{tol}, 552, 553, 556, \[557], 558, 559, 560, 561. -\:\\{tol\_step}, \[552], 557, 559, 561, 562. -\:\.{Too far to shift}, 965. -\:\.{Too far to skip}, 1110. -\:\.{Too many arguments...}, 725. -\:\\{too\_small}, \[1187], 1189. -\:\\{top}, \[1094]. -\:\\{top\_row}, \[567], \[572], 574, 577. -\:\\{toss\_edges}, \[385], 808, 809, 964. -\:\\{toss\_knot\_list}, \[268], 465, 506, 808, 809, 865, 921, 978, 1064, 1067. -\:\\{toss\_pen}, 475, \[487]. -\:\\{total\_chars}, \[1149], 1150, 1165, 1182. -\:\\{total\_weight}, \[369], 921. -\:\9{total\_weight\_}{\&{totalweight} primitive}, \[893]. -\:\\{total\_weight\_op}, \[189], 893, 921. -\:\\{trace\_a\_corner}, \[372], 373. -\:\\{trace\_new\_edge}, \[373], 375, 376, 381, 382, 383, 384. -\:\\{trace\_x}, \[371], 372, 373. -\:\\{trace\_y}, \[371], 372, 373. -\:\\{trace\_yy}, \[371], 372, 373. -\:\\{tracing}, \[402]. -\:\\{tracing\_capsules}, \[190], 192, 193, 238. -\:\9{tracing\_capsules\_}{\&{tracingcapsules} primitive}, \[192]. -\:\\{tracing\_choices}, \[190], 192, 193, 269. -\:\9{tracing\_choices\_}{\&{tracingchoices} primitive}, \[192]. -\:\\{tracing\_commands}, \[190], 192, 193, 707, 713, 748, 760, 832, 895, 898, -922, 944, 992, 995, 996. -\:\9{tracing\_commands\_}{\&{tracingcommands} primitive}, \[192]. -\:\\{tracing\_edges}, \[190], 192, 193, 371, 375, 376, 381, 382, 383, 384, 465, -506, 508, 510, 515, 521. -\:\9{tracing\_edges\_}{\&{tracingedges} primitive}, \[192]. -\:\\{tracing\_equations}, \[190], 192, 193, 603, 610, 816. -\:\9{tracing\_equations\_}{\&{tracingequations} primitive}, \[192]. -\:\\{tracing\_macros}, \[190], 192, 193, 720, 728, 734. -\:\9{tracing\_macros\_}{\&{tracingmacros} primitive}, \[192]. -\:\\{tracing\_online}, \[190], 192, 193, 195, 804. -\:\9{tracing\_online\_}{\&{tracingonline} primitive}, \[192]. -\:\\{tracing\_output}, \[190], 192, 193, 1165. -\:\9{tracing\_output\_}{\&{tracingoutput} primitive}, \[192]. -\:\\{tracing\_pens}, \[190], 192, 193, 253, 477. -\:\9{tracing\_pens\_}{\&{tracingpens} primitive}, \[192]. -\:\\{tracing\_restores}, \[190], 192, 193, 254. -\:\9{tracing\_restores\_}{\&{tracingrestores} primitive}, \[192]. -\:\\{tracing\_specs}, \[190], 192, 193, 1064. -\:\9{tracing\_specs\_}{\&{tracingspecs} primitive}, \[192]. -\:\\{tracing\_stats}, 160, \[190], 192, 193, 1134, 1198, 1205. -\:\9{tracing\_stats\_}{\&{tracingstats} primitive}, \[192]. -\:\\{tracing\_titles}, \[190], 192, 193, 994. -\:\9{tracingtitles\_}{\&{tracingtitles} primitive}, \[192]. -\:\\{trans}, \[961], 962. -\:\\{trans\_spec}, \[565], 568, 579. -\:\.{Transcript written...}, 1205. -\:\.{Transform components...}, 960. -\:\9{transform\_}{\&{transform} primitive}, \[1013]. -\:\\{transform\_node\_size}, \[230], 231, 233, 956. -\:\\{transform\_type}, \[187], 216, 230, 231, 232, 233, 248, 798, 799, 800, -802, 808, 809, 855, 909, 918, 919, 926, 927, 936, 944, 952, 953, 955, 967, 970, -973, 1003, 1013, 1015. -\:\9{transformed\_}{\&{transformed} primitive}, \[893]. -\:\\{transformed\_by}, \[189], 893, 952, 953, 957. -\:\.{transition line...}, 515, 521. -\:\\{trick\_buf}, \[54], 58, 641, 643. -\:\\{trick\_count}, \[54], 58, 641, 642, 643. -\:\\{trivial\_knot}, 484, 485, \[486]. -\:\\{true}, 4, 16, 30, 33, 36, 45, 49, 51, 53, 66, 72, 83, 92, 93, 97, 100, -107, 109, 110, 112, 114, 124, 126, 135, 181, 182, 238, 257, 269, 332, 372, 394, -402, 407, 426, 446, 452, 454, 455, 473, 477, 497, 503, 504, 530, 564, 567, 568, -569, 570, 574, 577, 592, 593, 595, 596, 598, 599, 600, 621, 653, 654, 661, 670, -672, 675, 680, 681, 700, 711, 767, 771, 779, 788, 801, 886, 899, 913, 942, 946, -968, 969, 977, 978, 1003, 1009, 1010, 1054, 1056, 1064, 1072, 1086, 1099, 1112, -1137, 1165, 1187. -\:\9{true\_}{\&{true} primitive}, \[893]. -\:\\{true\_code}, \[189], 713, 748, 750, 798, 802, 892, 893, 895, 905, 906, -918, 919, 920, 940. -\:\\{try\_eq}, 1003, 1005, \[1006]. -\:\\{tt}, \[167], 169, \[539], 541, 547, 548, \[594], 595, 596, 842, \[843], -844, 845, 850, \[1006], 1009, 1010. -\:\\{turning\_check}, \[190], 192, 193, 1068. -\:\9{turning\_check\_}{\&{turningcheck} primitive}, \[192]. -\:\\{turning\_number}, \[403], 450, 459, 917, 1068. -\:\9{turning\_number\_}{\&{turningnumber} primitive}, \[893]. -\:\\{turning\_op}, \[189], 893, 917. -\:\\{two}, \[101], 102, 256, 294, 295, 556, 895, 898, 922, 944, 995, 996. -\:\\{two\_choices}, \[156]. -\:\\{two\_halves}, \[156], 161, 166, 185, 201. -\:\\{two\_to\_the}, \[129], 131, 133, 136, 143, 147, 314, 317, 608, 616. -\:\\{tx}, \[374], 375, 376, \[511], 516, 522, 866, 867, 953, \[954], 956, 960, -961, 962, 965, 967, 973. -\:\\{txx}, 866, 953, \[954], 956, 960, 961, 963, 964, 967, 973. -\:\\{txy}, 866, 953, \[954], 956, 960, 961, 963, 967, 973. -\:\\{ty}, \[511], 516, 522, 866, 867, 953, \[954], 956, 960, 961, 962, 965, -967, 973. -\:\\{type}, \[4], 188, \[214], 215, 216, 219, 228, 229, 232, 233, 234, 239, -242, 243, 244, 245, 246, 247, 248, 585, 587, 589, 595, 596, 598, 599, 600, 603, -604, 605, 614, 615, 619, 621, 651, 678, 700, 738, 744, 745, 746, 799, 800, 801, -803, 809, 812, 819, 827, 829, 830, 842, 850, 855, 856, 857, 858, 868, 873, 899, -903, 910, 919, 923, 926, 928, 929, 930, 931, 932, 935, 936, 939, 940, 941, 942, -943, 946, 947, 948, 949, 951, 952, 956, 957, 959, 966, 968, 969, 971, 972, 975, -982, 983, 988, 995, 1000, 1001, 1002, 1006, 1007, 1009, 1015, 1046, 1048, 1050, -1057. -\:\.{Type <return> to proceed...}, 80. -\:\\{type\_name}, \[186], 823, 989, 992, 1013, 1014, 1015. -\:\\{type\_range}, \[918]. -\:\\{type\_range\_end}, \[918]. -\:\\{type\_test}, \[918]. -\:\\{type\_test\_end}, \[918]. -\:\\{tyx}, 866, 953, \[954], 956, 960, 961, 963, 967, 973. -\:\\{tyy}, 866, 953, \[954], 956, 960, 961, 963, 964, 967, 973. -\:\\{t0}, \[495], \[497], 498, 503, \[599], \[600]. -\:\\{t1}, \[495], \[497], 498, 499, 503, \[599], \[600]. -\:\\{t2}, \[495], \[497], 498, 499, 503. -\:\|{u}, \[152], \[311], \[344], \[432], \[527], \[946], \[968], \[972], \[974]. -\:\\{u\_packet}, \[553], 556, 559, 560. -\:\\{ul\_packet}, \[553], 559. -\:\\{unary}, \[186], 823, 893, 894. -\:\\{und\_type}, \[248], 1000. -\:\\{undefined}, \[187], 229, 234, 239, 242, 244, 245, 247, 248, 585, 809, 842, -844, 845, 850, 1046. -\:\.{Undefined condition...}, 892. -\:\.{Undefined coordinates...}, 872, 873, 878. -\:\\{undefined\_label}, \[1096], 1097, 1110, 1111, 1137, 1139, 1141. -\:\\{undump}, \[1189], 1193, 1195, 1197, 1199. -\:\\{undump\_end}, \[1189]. -\:\\{undump\_end\_end}, \[1189]. -\:\\{undump\_four\_ASCII}, \[1193]. -\:\\{undump\_hh}, \[1189], 1197. -\:\\{undump\_int}, \[1189], 1191, 1195, 1197, 1199. -\:\\{undump\_qqqq}, \[1189], 1193. -\:\\{undump\_size}, \[1189], 1193. -\:\\{undump\_size\_end}, \[1189]. -\:\\{undump\_size\_end\_end}, \[1189]. -\:\\{undump\_wd}, \[1189], 1195. -\:\\{unequal\_to}, \[189], 893, 936, 937. -\:\\{unif\_rand}, \[151], 906. -\:\\{uniform\_deviate}, \[189], 893, 906. -\:\9{uniform\_deviate\_}{\&{uniformdeviate} primitive}, \[893]. -\:\\{unity}, \[101], 103, 112, 114, 115, 116, 119, 132, 194, 233, 256, 258, -271, 282, 288, 294, 295, 296, 300, 302, 311, 374, 375, 376, 402, 430, 431, 433, -462, 463, 508, 510, 515, 516, 521, 522, 530, 539, 548, 555, 556, 562, 590, 674, -675, 707, 713, 748, 760, 816, 817, 819, 876, 881, 883, 886, 887, 890, 891, 896, -906, 913, 915, 916, 917, 932, 943, 949, 960, 963, 964, 968, 969, 972, 974, 978, -980, 985, 1010, 1068, 1071, 1074, 1097, 1128, 1133, 1157, 1158, 1166, 1182, -1211. -\:\.{Unknown relation...}, 937. -\:\.{Unknown value...ignored}, 1021. -\:\9{unknown\_}{\&{unknown} primitive}, \[893]. -\:\\{unknown\_boolean}, \[187], 229, 248, 618, 798, 799, 918, 936. -\:\\{unknown\_op}, \[189], 893, 918. -\:\\{unknown\_path}, \[187], 248, 618, 798, 918, 995, 1003. -\:\\{unknown\_pen}, \[187], 248, 618, 798. -\:\\{unknown\_picture}, \[187], 248, 618, 798, 918. -\:\\{unknown\_string}, \[187], 248, 618, 798, 918, 936. -\:\\{unknown\_tag}, \[187], 621, 1003, 1015. -\:\\{unknown\_types}, \[187], 216, 799, 800, 802, 808, 809, 855, 1003. -\:\\{unrotate}, 389. -\:\\{unsave}, \[254], 832. -\:\\{unskew}, \[388], 394, 421, 445, 447, 451, 454, 457, 485, 488, 510. -\:\\{unsorted}, 324, \[325], 326, 328, 330, 331, 332, 335, 338, 343, 344, 346, -348, 354, 355, 364, 367, 368, 369, 375, 376, 381, 382, 383, 384, 385, 578, 1169. -\:\\{unstash\_cur\_exp}, 718, \[800], 801, 859, 870, 926, 942, 946, 948, 962, -963, 988, 995, 1000. -\:\\{unsuffixed\_macro}, \[187], 700, 798, 809, 842, 844, 845, 1046, 1048. -\:\.{Unsuitable expression}, 1178. -\:\9{until\_}{\&{until} primitive}, \[211]. -\:\\{until\_token}, \[186], 211, 212, 765. -\:\\{update\_screen}, \[564], 569, 571, 574, 577. -\:\\{update\_terminal}, \[33], 36, 61, 66, 81, 564, 681, 779, 793, 994, 1165, -1212. -\:\\{ur\_packet}, \[553], 558, 559. -\:\\{use\_err\_help}, \[74], 75, 84, 86, 1086. -\:\\{uu}, \[283], 285, 287, 288, 290, 291, 293, 294, 295, 297. -\:\\{uv}, 553, 556, \[557], 558, 559, 560, 561. -\:\\{u1l}, \[553], 559. -\:\\{u1r}, \[553], 558, 559. -\:\\{u2l}, \[553], 559. -\:\\{u2r}, \[553], 558, 559. -\:\\{u3l}, \[553], 559. -\:\\{u3r}, \[553], 558, 559. -\:\|{v}, \[215], \[217], \[410], \[432], \[497], \[527], \[589], \[594], % -\[597], \[599], \[600], \[601], \[607], \[610], \[621], \[801], \[808], \[809], -\[820], \[900], \[922], \[930], \[935], \[943], \[944], \[946], \[949], \[961], -\[971], \[972], \[974], \[985], \[1001], \[1117], \[1121]. -\:\\{v\_is\_scaled}, \[599], \[943]. -\:\\{v\_packet}, \[553], 556, 559, 560. -\:\\{vacuous}, \[187], 216, 219, 248, 621, 764, 798, 799, 800, 802, 809, 827, -844, 855, 919, 989, 992, 993, 996, 1003, 1054, 1059, 1070, 1071, 1074. -\:\\{val\_too\_big}, \[602], 603, 615. -\:\\{valid\_range}, \[326], 329, 965. -\:\\{value}, \[214], 215, 216, 219, 220, 228, 229, 230, 232, 233, 239, 242, -244, 246, 250, 253, 254, 585, 587, 589, 590, 591, 594, 595, 596, 597, 598, 599, -600, 601, 603, 604, 605, 607, 608, 609, 610, 611, 612, 615, 616, 617, 619, 620, -621, 622, 651, 678, 685, 686, 694, 698, 700, 704, 705, 752, 755, 760, 765, 798, -799, 800, 801, 803, 806, 809, 812, 814, 816, 817, 818, 819, 827, 829, 830, 845, -853, 855, 857, 858, 872, 873, 899, 903, 904, 907, 910, 915, 919, 928, 929, 930, -931, 933, 935, 936, 938, 939, 940, 942, 943, 944, 946, 948, 949, 951, 955, 956, -957, 958, 959, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, -982, 983, 984, 988, 1000, 1001, 1005, 1006, 1007, 1008, 1009, 1010, 1015, 1048, -1057, 1072, 1116, 1117, 1118, 1121, 1122, 1127, 1132, 1136, 1182. -\:\.{Value is too large}, 602. -\:\\{value\_loc}, \[214], 587, 605, 812, 827, 947. -\:\\{value\_node\_size}, \[228], 233, 234, 239, 247, 249, 603, 615, 619, 650, -763, 799, 800, 808, 827, 830, 837, 855, 856, 857, 858, 903, 910, 922, 925, 931, -942, 944, 947, 955, 970, 982, 1001, 1006, 1117. -\:\\{var\_def}, \[683], 684, 697, 992. -\:\9{var\_def\_}{\&{vardef} primitive}, \[683]. -\:\\{var\_defining}, \[659], 664, 665, 700. -\:\\{var\_flag}, \[821], 822, 823, 824, 868, 993, 995, 996, 1059, 1070, 1071, -1074. -\:\\{var\_used}, \[160], 167, 172, 176, 1045, 1194, 1195. -\:\.{Variable x is the wrong type}, 1057. -\:\.{Variable...obliterated}, 851. -\:\\{velocity}, \[116], 275, 299. -\:\\{verbosity}, \[801], 802, 803, 804, \[805], 1040. -\:\.{VIRMF}, 1203. -\:{virtual memory}, 168. -\:{Vitter, Jeffrey Scott}, 208. -\:\\{vl\_packet}, \[553], 559. -\:\\{void}, \[324], 326, 328, 330, 331, 332, 335, 338, 343, 344, 346, 348, 354, -367, 368, 369, 385, 578, 639, 650, 719, 723, 752, 755, 760, 762, 763, 799, 926, -927, 928, 944, 1169. -\:\\{vppp}, \[190], 192, 193, \[1146], 1182. -\:\9{vppp\_}{\&{vppp} primitive}, \[192]. -\:\\{vr\_packet}, \[553], 558, 559. -\:\\{vv}, \[283], 285, 290, 291, 293, 294, 295, 297, \[809], 817, \[935], % -\[972]. -\:\\{v1l}, \[553], 559. -\:\\{v1r}, \[553], 558, 559. -\:\\{v2l}, \[553], 559. -\:\\{v2r}, \[553], 558, 559. -\:\\{v3l}, \[553], 559. -\:\\{v3r}, \[553], 558, 559. -\:\|{w}, \[157], \[333], \[342], \[348], \[357], \[373], \[473], \[476], % -\[477], \[484], \[487], \[488], \[491], \[497], \[510], \[511], \[580], \[599], -\[600], \[610], \[1059], \[1074], \[1165], \[1186], \[1187]. -\:\\{w\_close}, \[27], 1201, 1211. -\:\\{w\_hi}, \[348], 349. -\:\\{w\_in}, \[348], 349, \[1074], 1075. -\:\\{w\_lo}, \[348], 349. -\:\\{w\_make\_name\_string}, \[780], 1200. -\:\\{w\_open\_in}, \[26], 779. -\:\\{w\_open\_out}, \[26], 1200. -\:\\{w\_out}, \[348], 349, \[1074], 1075. -\:\\{wake\_up\_terminal}, \[33], 36, 51, 66, 68, 398, 682, 779, 786, 807, 1051, -1187, 1205, 1212. -\:\\{warning\_check}, \[190], 192, 193, 602. -\:\9{warning\_check\_}{\&{warningcheck} primitive}, \[192]. -\:\\{warning\_info}, \[659], 661, 664, 694, 698, 700, 701, 730, 742, 758. -\:\\{warning\_issued}, \[71], 195, 1209. -\:\\{was\_free}, \[178], 180, 184. -\:\\{was\_hi\_min}, \[178], 179, 180, 184. -\:\\{was\_lo\_max}, \[178], 179, 180, 184. -\:\\{was\_mem\_end}, \[178], 179, 180, 184. -\:\\{watch\_coefs}, \[592], 593, 595, 596, 598, 1010. -\:\\{we\_found\_it}, \[547], 548, 549. -\:\.{WEB}, 1, 4, 37, 39, 50, 1191. -\:\.{Weight must be...}, 1056. -\:\\{west\_edge}, \[435]. -\:\\{white}, \[565], 567, 568, 577, 579, 583, 584, 1143, 1144. -\:\\{width\_index}, \[1091]. -\:\\{window\_number}, \[571], 572, 574, 577. -\:\\{window\_open}, \[572], 573, 574, 1071. -\:\\{window\_time}, \[572], 573, 574, 577. -\:{Wirth, Niklaus}, 10. -\:\\{with\_option}, \[186], 1052, 1053, 1062, 1074. -\:\9{with\_pen\_}{\&{withpen} primitive}, \[1052]. -\:\9{with\_weight\_}{\&{withweight} primitive}, \[1052]. -\:\\{wlog}, \[56], 58, 564, 568, 790, 1208. -\:\\{wlog\_cr}, \[56], 57, 58, 567, 1205. -\:\\{wlog\_ln}, \[56], 564, 567, 568, 1141, 1208. -\:\\{word\_file}, 24, 26, 27, \[156], 780, 1188. -\:\\{write}, 36, 56, 1133, 1154. -\:\\{write\_gf}, \[1154], 1155, 1156. -\:\\{write\_ln}, 34, 36, 51, 56. -\:\\{wterm}, \[56], 58, 61. -\:\\{wterm\_cr}, \[56], 57, 58. -\:\\{wterm\_ln}, \[56], 61, 779, 1187, 1204. -\:\\{ww}, \[283], 285, 290, 291, 293, 294, \[348], 349, \[357], 362, \[473], -474, \[484], 485, \[487], \[488], \[491], \[497], 498, 502, 503, 508, 509, % -\[510], \[511], 513, 519, \[580], 582, 583, 584, \[1165], 1169. -\:\\{www}, \[506], 508. -\:\|{x}, \[100], \[104], \[119], \[121], \[132], \[135], \[139], \[145], % -\[149], \[151], \[152], \[234], \[387], \[388], \[390], \[391], \[463], \[486], -\[488], \[539], \[574], \[591], \[601], \[602], \[604], \[610], \[868], \[875], -\[898], \[982], \[1011], \[1129], \[1131], \[1133], \[1157], \[1158], \[1186], % -\[1187], \[1205]. -\:\\{x\_coord}, \[255], 256, 258, 265, 266, 271, 281, 282, 299, 302, 393, 394, -397, 404, 405, 406, 407, 409, 410, 411, 412, 413, 415, 416, 418, 419, 421, 423, -424, 425, 434, 436, 441, 442, 444, 445, 447, 451, 457, 467, 468, 472, 473, 474, -475, 476, 477, 479, 481, 483, 484, 485, 486, 488, 492, 493, 496, 498, 502, 508, -509, 510, 512, 513, 515, 518, 519, 521, 528, 534, 535, 536, 537, 543, 558, 563, -866, 867, 871, 887, 896, 962, 980, 981, 986, 987, 1066. -\:\\{x\_corr}, \[461], 462, 463. -\:\\{x\_height}, 1095. -\:\\{x\_height\_code}, \[1095]. -\:\\{x\_off}, \[332], \[333], \[1165], 1166, 1169, 1172. -\:\\{x\_offset}, \[190], 192, 193, 1165. -\:\9{x\_offset\_}{\&{xoffset} primitive}, \[192]. -\:\\{x\_packet}, \[553], 556, 559, 560. -\:\\{x\_part}, \[189], 893, 909, 910, 939. -\:\9{x\_part\_}{\&{xpart} primitive}, \[893]. -\:\\{x\_part\_loc}, \[230], 830, 873, 899, 903, 907, 915, 929, 942, 944, 946, -947, 948, 956, 957, 959, 967, 970, 973, 977, 978, 982, 984, 1072. -\:\\{x\_part\_sector}, \[188], 230, 232, 235, 237, 238. -\:\\{x\_reflect\_edges}, \[337], 964. -\:\\{x\_scale\_edges}, \[342], 964. -\:\\{x\_scaled}, \[189], 893, 952, 957. -\:\9{x\_scaled\_}{\&{xscaled} primitive}, \[893]. -\:\\{xchr}, \[20], 21, 22, 23, 37, 49, 58, 774. -\:\&{xclause}, 16. -\:\\{xi\_corr}, 306, \[311], 313, 314, 317. -\:\\{xl\_packet}, \[553], 559. -\:\\{xord}, \[20], 23, 30, 52, 53, 778, 780. -\:\\{xp}, \[511], 515, 516, 521, 522. -\:\\{xq}, \[410]. -\:\\{xr\_packet}, \[553], 558, 559. -\:\\{xw}, 362, \[363]. -\:\\{xx}, \[391], 392, \[511], 515, 516, 521, 522. -\:\\{xx\_part}, \[189], 893, 909. -\:\9{xx\_part\_}{\&{xxpart} primitive}, \[893]. -\:\\{xx\_part\_loc}, \[230], 233, 956, 957, 958, 959, 967, 970, 973. -\:\\{xx\_part\_sector}, \[188], 230, 237. -\:\\{xxx1}, 1144, \[1145], 1160. -\:\\{xxx2}, \[1144]. -\:\\{xxx3}, 1144, \[1145], 1160. -\:\\{xxx4}, \[1144]. -\:\\{xx0}, \[311]. -\:\\{xx1}, \[311]. -\:\\{xx2}, \[311]. -\:\\{xx3}, \[311]. -\:\\{xy}, 553, 556, \[557], 558, 559, 560, 561. -\:\\{xy\_corr}, \[461], 462, 468, 512, 513, 515, 516, 518, 519, 521, 522. -\:\\{xy\_part}, \[189], 893, 909. -\:\9{xy\_part\_}{\&{xypart} primitive}, \[893]. -\:\\{xy\_part\_loc}, \[230], 956, 957, 958, 959, 967, 970, 973. -\:\\{xy\_part\_sector}, \[188], 230, 237. -\:\\{xy\_round}, 402, \[433]. -\:\\{xy\_swap\_edges}, \[354], 963. -\:\\{x0}, \[374], 375, 376, \[391], 392, \[495], 496, \[497], 498, 499, 501, -503, 504, 505, \[510]. -\:\\{x0a}, \[495], 504. -\:\\{x1}, \[311], 312, 313, 314, 317, 318, \[374], \[391], 392, \[495], 496, % -\[497], 498, 499, 501, 503, 504, 505, \[510], 541, \[542], 543, 544, 546, 547, -548, 549. -\:\\{x1a}, \[495], 503, 504. -\:\\{x1l}, \[553], 559. -\:\\{x1r}, \[553], 558, 559. -\:\\{x2}, \[311], 312, 313, 314, 317, 318, \[391], 392, \[495], 496, \[497], -498, 499, 501, 503, 504, 505, \[542], 543, 546, 547, 548, 549. -\:\\{x2a}, \[311], 317, 318, \[495], 503. -\:\\{x2l}, \[553], 559. -\:\\{x2r}, \[553], 558, 559. -\:\\{x3}, \[311], 312, 313, 314, 317, 318, 541, \[542], 543, 546, 547, 548, 549. -\:\\{x3a}, \[311], 317, 318. -\:\\{x3l}, \[553], 559. -\:\\{x3r}, \[553], 558, 559. -\:\|{y}, \[100], \[104], \[121], \[132], \[135], \[139], \[145], \[151], % -\[387], \[388], \[390], \[463], \[486], \[488], \[539], \[574], \[868], \[982]. -\:\\{y\_coord}, \[255], 256, 258, 265, 266, 271, 281, 282, 299, 302, 393, 394, -397, 404, 405, 406, 407, 409, 410, 413, 414, 415, 416, 419, 421, 423, 424, 425, -435, 437, 439, 444, 445, 447, 451, 457, 467, 468, 472, 473, 474, 475, 476, 477, -479, 481, 483, 484, 485, 486, 488, 492, 493, 496, 498, 502, 508, 509, 510, 512, -515, 518, 521, 528, 534, 535, 536, 537, 543, 558, 563, 866, 867, 871, 887, 896, -962, 980, 981, 986, 987, 1066. -\:\\{y\_corr}, \[461], 462, 463, 468, 512, 515, 516, 518, 521, 522. -\:\\{y\_off}, \[332], \[1165], 1166, 1167, 1172. -\:\\{y\_offset}, \[190], 192, 193, 1165. -\:\9{y\_offset\_}{\&{yoffset} primitive}, \[192]. -\:\\{y\_packet}, \[553], 556, 559, 560. -\:\\{y\_part}, \[189], 893, 909. -\:\9{y\_part\_}{\&{ypart} primitive}, \[893]. -\:\\{y\_part\_loc}, \[230], 830, 873, 899, 903, 907, 915, 929, 942, 944, 946, -947, 948, 956, 957, 959, 967, 970, 973, 977, 978, 982, 984, 1072. -\:\\{y\_part\_sector}, \[188], 230, 237. -\:\\{y\_reflect\_edges}, \[336], 964. -\:\\{y\_scale\_edges}, \[340], 964. -\:\\{y\_scaled}, \[189], 893, 952, 957. -\:\9{y\_scaled\_}{\&{yscaled} primitive}, \[893]. -\:\\{year}, \[190], 192, 193, 194, 790, 1163, 1200. -\:\9{year\_}{\&{year} primitive}, \[192]. -\:\\{yl\_packet}, \[553], 559. -\:\.{You have to increase POOLSIZE}, 52. -\:\.{You want to edit file x}, 79. -\:\\{yp}, \[511], 515, 516, 521, 522. -\:\\{yq}, \[410]. -\:\\{yr\_packet}, \[553], 558, 559. -\:\\{yt}, \[374]. -\:\\{yx\_part}, \[189], 893, 909. -\:\9{yx\_part\_}{\&{yxpart} primitive}, \[893]. -\:\\{yx\_part\_loc}, \[230], 956, 958, 959, 967, 970, 973. -\:\\{yx\_part\_sector}, \[188], 230, 237. -\:\\{yy}, \[511], 515, 516, 521, 522. -\:\\{yy\_part}, \[189], 893, 909. -\:\9{yy\_part\_}{\&{yypart} primitive}, \[893]. -\:\\{yy\_part\_loc}, \[230], 233, 956, 957, 958, 959, 967, 970, 973. -\:\\{yy\_part\_sector}, \[188], 230, 237. -\:\\{yyy}, 1144, \[1145], 1147, 1166, 1177. -\:\\{yy0}, \[311]. -\:\\{yy1}, \[311]. -\:\\{yy2}, \[311]. -\:\\{yy3}, \[311]. -\:\\{y0}, \[374], 375, 376, \[495], 496, \[497], 498, 499, 501, 503, 504, 505, % -\[510]. -\:\\{y0a}, \[495], 504. -\:\\{y1}, \[311], 312, 313, 314, 317, 318, \[374], 375, 376, \[495], 496, % -\[497], 498, 499, 501, 503, 504, 505, \[510], 541, \[542], 543, 544, 546, 547, -548. -\:\\{y1a}, \[495], 503, 504. -\:\\{y1l}, \[553], 559. -\:\\{y1r}, \[553], 558, 559. -\:\\{y2}, \[311], 312, 313, 314, 317, 318, \[495], 496, \[497], 498, 499, 501, -503, 504, 505, \[542], 543, 546, 547, 548. -\:\\{y2a}, \[311], 317, 318, \[495], 503. -\:\\{y2l}, \[553], 559. -\:\\{y2r}, \[553], 558, 559. -\:\\{y3}, \[311], 312, 313, 314, 317, 318, 541, \[542], 543, 546, 547, 548. -\:\\{y3a}, \[311], 317, 318. -\:\\{y3l}, \[553], 559. -\:\\{y3r}, \[553], 558, 559. -\:\|{z}, \[132], \[135], \[139], \[145]. -\:\\{z\_corr}, \[461], 462, 463. -\:\\{z\_scaled}, \[189], 893, 952, 957. -\:\9{z\_scaled\_}{\&{zscaled} primitive}, \[893]. -\:{Zabala Salelles, Ignacio Andres}, 812. -\:\\{zero\_crossing}, \[391]. -\:\\{zero\_field}, \[326], 328, 329, 332, 336, 337, 340, 342, 352, 364, 365, -366, 370, 374, 377, 378, 577, 1167, 1172. -\:\\{zero\_val}, \[175], 1126, 1127. -\:\\{zero\_w}, \[324], 326, 333, 337, 349, 350, 358, 365, 370, 373, 375, 376, -381, 382, 383, 384, 582, 1169. -\fin -\:\X1060:Abandon edges command because there's no variable\X -\Us1059, 1070, 1071\ETs1074. -\:\X703:Absorb delimited parameters, putting them into lists \|q and \|r\X -\U697. -\:\X704:Absorb parameter tokens for type \\{base}\X -\U703. -\:\X705:Absorb undelimited parameters, putting them into list \|r\X -\U697. -\:\X931:Add a known value to the constant term of $\\{dep\_list}(\|p)$\X -\U930. -\:\X1010:Add dependency list \\{pp} of type \\{tt} to dependency list~\|p of -type~\|t\X -\U1009. -\:\X382:Add edges for fifth or eighth octants, then \&{goto} \\{done}\X -\U378. -\:\X381:Add edges for first or fourth octants, then \&{goto} \\{done}\X -\U378. -\:\X383:Add edges for second or third octants, then \&{goto} \\{done}\X -\U378. -\:\X384:Add edges for sixth or seventh octants, then \&{goto} \\{done}\X -\U378. -\:\X932:Add operand \|p to the dependency list \|v\X -\U930. -\:\X929:Add or subtract the current expression from \|p\X -\U922. -\:\X370:Add the contribution of node \|q to the total weight, and set $\|q\K% -\\{link}(\|q)$\X -\Us369\ET369. -\:\X933:Add the known $\\{value}(\|p)$ to the constant term of \|v\X -\U932. -\:\X1009:Add the right operand to list \|p\X -\U1006. -\:\X936, 940, 941, 948, 951, 952, 975, 983, 988:Additional cases of binary -operators\X -\U922. -\:\X905, 906, 907, 909, 912, 915, 917, 918, 920, 921:Additional cases of unary -operators\X -\U898. -\:\X291:Adjust $\theta_n$ to equal $\theta_0$ and \&{goto} \\{found}\X -\U287. -\:\X731:Adjust the balance for a delimited argument; \&{goto} \\{done} if done\X -\U730. -\:\X732:Adjust the balance for an undelimited argument; \&{goto} \\{done} if -done\X -\U730. -\:\X687:Adjust the balance; \&{goto} \\{done} if it's zero\X -\U685. -\:\X575:Adjust the coordinates $(\\{r0},\\{c0})$ and $(\\{r1},\\{c1})$ so that -they lie in the proper range\X -\U574. -\:\X367:Adjust the data of \|h to account for a difference of offsets\X -\U366. -\:\X364:Adjust the header to reflect the new edges\X -\U354. -\:\X360:Advance pointer \|p to the next vertical edge, after destroying the -previous one\X -\U358. -\:\X359:Advance pointer \|r to the next vertical edge\X -\U358. -\:\X560:Advance to the next pair $(\\{cur\_t},\\{cur\_tt})$\X -\U556. -\:\X492:Advance \|p to node \|q, removing any ``dead'' cubics that might have -been introduced by the splitting process\X -\U491. -\:\X171:Allocate entire node \|p and \&{goto} \\{found}\X -\U169. -\:\X170:Allocate from the top of node \|p and \&{goto} \\{found}\X -\U169. -\:\X1002:Announce that the equation cannot be performed\X -\U1001. -\:\X728:Append the current expression to \\{arg\_list}\X -\Us726\ET733. -\:\X236:Ascend one level, pushing a token onto list \|q and replacing \|p by -its parent\X -\U235. -\:\X999:Assign the current expression to an internal variable\X -\U996. -\:\X1000:Assign the current expression to the variable \\{lhs}\X -\U996. -\:\X698:Attach the replacement text to the tail of node \|p\X -\U697. -\:\X1061:Augment some edges by others\X -\U1059. -\:\X662:Back up an outer symbolic token so that it can be reread\X -\U661. -\:\X57, 58, 59, 60, 62, 63, 64, 103, 104, 187, 195, 197, 773:Basic printing -procedures\X -\U4. -\:\X530:Calculate integers $\alpha$, $\beta$, $\gamma$ for the vertex -coordinates\X -\U528. -\:\X292:Calculate the given value of $\theta_n$ and \&{goto} \\{found}\X -\U284. -\:\X289:Calculate the ratio $\\{ff}=C_k/(C_k+B_k-u_{k-1}A_k)$\X -\U287. -\:\X281:Calculate the turning angles $\psi_k$ and the distances $d_{k,k+1}$; -set $n$ to the length of the path\X -\U278. -\:\X288:Calculate the values $\\{aa}=A_k/B_k$, $\\{bb}=D_k/C_k$, $\\{dd}=(3-% -\alpha_{k-1})d_{k,k+1}$, $\\{ee}=(3-\beta\k)d_{k-1,k}$, and $% -\\{cc}=(B_k-u_{k-1}A_k)/B_k$\X -\U287. -\:\X290:Calculate the values of $v_k$ and $w_k$\X -\U287. -\:\X1020, 1023, 1026, 1030, 1033, 1039, 1058, 1069, 1076, 1081, 1100, -1175:Cases of \\{do\_statement} that invoke particular commands\X -\U992. -\:\X212, 684, 689, 696, 710, 741, 894, 1014, 1019, 1025, 1028, 1038, 1043, -1053, 1080, 1102, 1109, 1180:Cases of \\{print\_cmd\_mod} for symbolic printing -of primitives\X -\U625. -\:\X866:Change node \|q to a path for an elliptical pen\X -\U865. -\:\X563:Change one-point paths into dead cycles\X -\U562. -\:\X81:Change the interaction level and \&{return}\X -\U79. -\:\X1063:Change the tentative pen\X -\U1062. -\:\X701:Change to `\.{a bad variable}'\X -\U700. -\:\X615:Change variable \|x from \\{independent} to \\{dependent} or \\{known}\X -\U610. -\:\X49:Character \|k cannot be printed\X -\U48. -\:\X183:Check flags of unavailable nodes\X -\U180. -\:\X756:Check for the presence of a colon\X -\U755. -\:\X938:Check if unknowns have been equated\X -\U936. -\:\X181:Check single-word \\{avail} list\X -\U180. -\:\X727:Check that the proper right delimiter was present\X -\U726. -\:\X14, 154, 204, 214, 310, 553, 777:Check the ``constant'' values for -consistency\X -\U1204. -\:\X617:Check the list of linear dependencies\X -\U180. -\:\X547:Check the places where $B(y_1,y_2,y_3;t)=0$ to see if $B(x_1,x_2,x_3;t)% -\ge0$\X -\U546. -\:\X53:Check the pool check sum\X -\U52. -\:\X1056:Check the tentative weight\X -\U1054. -\:\X1068:Check the turning number\X -\U1064. -\:\X182:Check variable-size \\{avail} list\X -\U180. -\:\X815:Choose a dependent variable to take the place of the disappearing -independent variable, and change all remaining dependencies accordingly\X -\U812. -\:\X891:Choose control points for the path and put the result into \\{cur\_exp}% -\X -\U869. -\:\X1201:Close the base file\X -\U1186. -\:\X937:Compare the current expression with zero\X -\U936. -\:\X1112:Compile a ligature/kern command\X -\U1107. -\:\X9:Compiler directives\X -\U4. -\:\X478:Complain about a bad pen path\X -\U477. -\:\X1105:Complain about a character tag conflict\X -\U1104. -\:\X1178:Complain about improper special operation\X -\U1177. -\:\X1055:Complain about improper type\X -\U1054. -\:\X1067:Complain about non-cycle and \&{goto} \\{not\_found}\X -\U1064. -\:\X409:Complement the \|x coordinates of the cubic between \|p and~\|q\X -\U407. -\:\X414:Complement the \|y coordinates of the cubic between \\{pp} and~\\{qq}\X -\Us413\ET417. -\:\X1064:Complete the contour filling operation\X -\U1062. -\:\X537:Complete the ellipse by copying the negative of the half already -computed\X -\U527. -\:\X664:Complete the error message, and set \\{cur\_sym} to a token that might -help recover from the error\X -\U663. -\:\X536:Complete the half ellipse by reflecting the quarter already computed\X -\U527. -\:\X503:Complete the offset splitting process\X -\U494. -\:\X115:Compute $f=\lfloor 2^{16}(1+p/q)+{1\over2}\rfloor$\X -\U114. -\:\X108:Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$\X -\U107. -\:\X113:Compute $p=\lfloor qf/2^{16}+{1\over2}\rfloor-q$\X -\U112. -\:\X111:Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$\X -\U109. -\:\X1132:Compute a check sum in $(\\{b1},\\{b2},\\{b3},\\{b4})$\X -\U1131. -\:\X443:Compute a compromise \\{pen\_edge}\X -\U442. -\:\X442:Compute a good coordinate at a diagonal transition\X -\U441. -\:\X435:Compute before-and-after \|x values based on the current pen\X -\U434. -\:\X438:Compute before-and-after \|y values based on the current pen\X -\U437. -\:\X498:Compute test coefficients $(\\{t0},\\{t1},\\{t2})$ for $s(t)$ versus -$s_k$ or $s_{k-1}$\X -\Us497\ET503. -\:\X533:Compute the distance \|d from class~0 to the edge of the ellipse in -direction $(\|u,\|v)$, times $\psqrt{u^2+v^2}$, rounded to the nearest integer\X -\U531. -\:\X208:Compute the hash code \|h\X -\U205. -\:\X457:Compute the incoming and outgoing directions\X -\U454. -\:\X1137:Compute the ligature/kern program offset and implant the left boundary -label\X -\U1135. -\:\X365:Compute the magic offset values\X -\U354. -\:\X489:Compute the octant code; skew and rotate the coordinates $(\|x,\|y)$\X -\U488. -\:\X576:Compute the offsets between screen coordinates and actual coordinates\X -\U574. -\:\X11:Constants in the outer block\X -\U4. -\:\X980:Construct a path from \\{pp} to \\{qq} of length $\lceil b\rceil$\X -\U978. -\:\X981:Construct a path from \\{pp} to \\{qq} of length zero\X -\U978. -\:\X481:Construct the offset list for the \|kth octant\X -\U477. -\:\X598:Contribute a term from \|p, plus the corresponding term from \|q\X -\U597. -\:\X595:Contribute a term from \|p, plus \|f times the corresponding term from % -\|q\X -\U594. -\:\X596:Contribute a term from \|q, multiplied by~\|f\X -\U594. -\:\X840:Convert a suffix to a string\X -\U823. -\:\X870:Convert the left operand, \|p, into a partial path ending at~\|q; but % -\&{return} if \|p doesn't have a suitable type\X -\U869. -\:\X885:Convert the right operand, \\{cur\_exp}, into a partial path from % -\\{pp} to~\\{qq}\X -\U869. -\:\X146:Convert $(\|x,\|y)$ to the octant determined by~\|q\X -\U145. -\:\X335:Copy both \\{sorted} and \\{unsorted} lists of \|p to \\{pp}\X -\Us334\ET341. -\:\X857:Copy the big node \|p\X -\U855. -\:\X485:Copy the unskewed and unrotated coordinates of node \\{ww}\X -\U484. -\:\X418:Correct the octant code in segments with decreasing \|y\X -\U413. -\:\X1200:Create the \\{base\_ident}, open the base file, and inform the user -that dumping has begun\X -\U1186. -\:\X349:Cull superfluous edge-weight entries from $\\{sorted}(\|p)$\X -\U348. -\:\X1008:Deal with redundant or inconsistent equation\X -\U1006. -\:\X454:Decide whether or not to go clockwise\X -\U452. -\:\X995, 996, 1015, 1021, 1029, 1031, 1034, 1035, 1036, 1040, 1041, 1044, 1045, -1046, 1049, 1050, 1051, 1054, 1057, 1059, 1070, 1071, 1072, 1073, 1074, 1082, -1103, 1104, 1106, 1177, 1186:Declare action procedures for use by \\{do% -\_statement}\X -\U989. -\:\X594, 600, 602, 603, 604:Declare basic dependency-list subroutines\X -\U246. -\:\X923, 928, 930, 943, 946, 949, 953, 960, 961, 962, 963, 966, 976, 977, 978, -982, 984, 985:Declare binary action procedures\X -\U922. -\:\X1154, 1155, 1157, 1158, 1159, 1160, 1161, 1163, 1165:Declare generic font -output procedures\X -\U989. -\:\X224:Declare miscellaneous procedures that were declared \\{forward}\X -\U1202. -\:\X257, 332, 388, 473, 589, 801, 807:Declare subroutines for printing -expressions\X -\U246. -\:\X968, 971, 972, 974:Declare subroutines needed by \\{big\_trans}\X -\U966. -\:\X856, 858:Declare subroutines needed by \\{make\_exp\_copy}\X -\U855. -\:\X405, 406, 419, 426, 429, 431, 432, 433, 440, 451:Declare subroutines needed -by \\{make\_spec}\X -\U402. -\:\X493, 497:Declare subroutines needed by \\{offset\_prep}\X -\U491. -\:\X296, 299:Declare subroutines needed by \\{solve\_choices}\X -\U284. -\:\X823, 860, 862, 864, 868, 892:Declare the basic parsing subroutines\X -\U1202. -\:\X779:Declare the function called \\{open\_base\_file}\X -\U1187. -\:\X1011:Declare the function called \\{scan\_declared\_variable}\X -\U697. -\:\X1098:Declare the function called \\{tfm\_check}\X -\U1070. -\:\X486:Declare the function called \\{trivial\_knot}\X -\U484. -\:\X1032:Declare the procedure called \\{check\_delimiter}\X -\U697. -\:\X935:Declare the procedure called \\{dep\_finish}\X -\U930. -\:\X518:Declare the procedure called \\{dual\_moves}\X -\U506. -\:\X247:Declare the procedure called \\{flush\_below\_variable}\X -\U246. -\:\X808, 820:Declare the procedure called \\{flush\_cur\_exp}\X -\U246. -\:\X43:Declare the procedure called \\{flush\_string}\X -\U73. -\:\X872:Declare the procedure called \\{known\_pair}\X -\U871. -\:\X720:Declare the procedure called \\{macro\_call}\X -\U706. -\:\X1001:Declare the procedure called \\{make\_eq}\X -\U995. -\:\X855:Declare the procedure called \\{make\_exp\_copy}\X -\U651. -\:\X723:Declare the procedure called \\{print\_arg}\X -\U720. -\:\X625:Declare the procedure called \\{print\_cmd\_mod}\X -\U227. -\:\X805:Declare the procedure called \\{print\_dp}\X -\U801. -\:\X722:Declare the procedure called \\{print\_macro\_name}\X -\U720. -\:\X333:Declare the procedure called \\{print\_weight}\X -\U332. -\:\X665:Declare the procedure called \\{runaway}\X -\U162. -\:\X730:Declare the procedure called \\{scan\_text\_arg}\X -\U720. -\:\X217:Declare the procedure called \\{show\_token\_list}\X -\U162. -\:\X510:Declare the procedure called \\{skew\_line\_edges}\X -\U506. -\:\X284:Declare the procedure called \\{solve\_choices}\X -\U269. -\:\X410:Declare the procedure called \\{split\_cubic}\X -\U406. -\:\X1006:Declare the procedure called \\{try\_eq}\X -\U995. -\:\X268, 385, 487, 620, 809:Declare the recycling subroutines\X -\U246. -\:\X799, 800:Declare the stashing/unstashing routines\X -\U801. -\:\X899, 900, 901, 904, 908, 910, 913, 916, 919:Declare unary action procedures% -\X -\U898. -\:\X743:Decrease the string reference count, if the current token is a string\X -\Us83, 742, 991\ETs1016. -\:\X300:Decrease the velocities, if necessary, to stay inside the bounding -triangle\X -\U299. -\:\X123:Decrease \|k by 1, maintaining the invariant relations between \|x, % -\|y, and~\|q\X -\U121. -\:\X670:Decry the invalid character and \&{goto} \\{restart}\X -\U669. -\:\X672:Decry the missing string delimiter and \&{goto} \\{restart}\X -\U671. -\:\X1113:Define an extensible recipe\X -\U1106. -\:\X353:Delete all the row headers\X -\U352. -\:\X352:Delete empty rows at the top and/or bottom; update the boundary values -in the header\X -\U348. -\:\X83:Delete $\|c-\.{"0"}$ tokens and \&{goto} \\{continue}\X -\U79. -\:\X245:Descend one level for the attribute $\\{info}(\|t)$\X -\U242. -\:\X244:Descend one level for the subscript $\\{value}(\|t)$\X -\U242. -\:\X1012:Descend past a collective subscript\X -\U1011. -\:\X1047:Descend the structure\X -\U1046. -\:\X561:Descend to the previous level and \&{goto} \\{not\_found}\X -\U560. -\:\X1181:Determine if a character has been shipped out\X -\U906. -\:\X445:Determine the before-and-after values of both coordinates\X -\Us444\ET446. -\:\X816:Determine the dependency list \|s to substitute for the independent -variable~\|p\X -\U815. -\:\X508:Determine the envelope's starting and ending lattice points $(\\{m0},% -\\{n0})$ and $(\\{m1},\\{n1})$\X -\U506. -\:\X1164:Determine the file extension, \\{gf\_ext}\X -\U1163. -\:\X724:Determine the number \|n of arguments already supplied, and set % -\\{tail} to the tail of \\{arg\_list}\X -\U720. -\:\X400:Determine the octant boundary \|q that precedes \|f\X -\U398. -\:\X480:Determine the octant code for direction $(\\{dx},\\{dy})$\X -\U479. -\:\X874:Determine the path join parameters; but \&{goto} \\{finish\_path} if -there's only a direction specifier\X -\U869. -\:\X467:Determine the starting and ending lattice points $(\\{m0},\\{n0})$ and -$(\\{m1},\\{n1})$\X -\U465. -\:\X881:Determine the tension and/or control points\X -\U874. -\:\X979:Dispense with the cases $\|a<0$ and/or $\|b>\|l$\X -\U978. -\:\X803:Display a big node\X -\U802. -\:\X221:Display a collective subscript\X -\U218. -\:\X804:Display a complex type\X -\U802. -\:\X220:Display a numeric token\X -\U219. -\:\X222:Display a parameter token\X -\U218. -\:\X1048:Display a variable macro\X -\U1046. -\:\X806:Display a variable that's been declared but not defined\X -\U802. -\:\X750:Display the boolean value of \\{cur\_exp}\X -\U748. -\:\X636:Display the current context\X -\U635. -\:\X613:Display the new dependency\X -\U610. -\:\X578:Display the pixels of edge row \|p in screen row \|r\X -\U577. -\:\X218:Display token \|p and set \|c to its class; but \&{return} if there are -problems\X -\U217. -\:\X219:Display two-word token\X -\U218. -\:\X616:Divide list \|p by $2^n$\X -\U615. -\:\X612:Divide list \|p by $-\|v$, removing node \|q\X -\U610. -\:\X313:Divide the variables by two, to avoid overflow problems\X -\U311. -\:\X992:Do a statement that doesn't begin with an expression\X -\U989. -\:\X994:Do a title\X -\U993. -\:\X993:Do an equation, assignment, title, or `$\langle\,$expression$\,\rangle% -\,$\&{endgroup}'\X -\U989. -\:\X417:Do any special actions needed when \|y is constant; \&{return} or % -\&{goto} \\{continue} if a dead cubic from \|p to \|q is removed\X -\U413. -\:\X646:Do magic computation\X -\U217. -\:\X1005:Do multiple equations and \&{goto} \\{done}\X -\U1003. -\:\X1065:Double the path\X -\U1064. -\:\X1198:Dump a few more things and the closing check word\X -\U1186. -\:\X1190:Dump constants for consistency check\X -\U1186. -\:\X1194:Dump the dynamic memory\X -\U1186. -\:\X1192:Dump the string pool\X -\U1186. -\:\X1196:Dump the table of equivalents and the hash table\X -\U1186. -\:\X845:Either begin an unsuffixed macro call or prepare for a suffixed one\X -\U844. -\:\X1156:Empty the last bytes out of \\{gf\_buf}\X -\U1182. -\:\X969:Ensure that $\\{type}(\|p)=\\{proto\_dependent}$\X -\U968. -\:\X73, 76, 77, 88, 89, 90:Error handling procedures\X -\U4. -\:\X623:Exclaim about a redundant equation\X -\Us622, 1004\ETs1008. -\:\X713:Exit a loop if the proper time has come\X -\U707. -\:\X714:Exit prematurely from an iteration\X -\U713. -\:\X544:Exit to \\{found} if an eastward direction occurs at knot \|p\X -\U541. -\:\X546:Exit to \\{found} if the curve whose derivatives are specified by $% -\\{x1},\\{x2},\\{x3},\\{y1},\\{y2},\\{y3}$ travels eastward at some time~\\{tt}% -\X -\U541. -\:\X549:Exit to \\{found} if the derivative $B(x_1,x_2,x_3;t)$ becomes $\G0$\X -\U548. -\:\X715:Expand the token after the next token\X -\U707. -\:\X736:Feed the arguments and replacement text to the scanner\X -\U720. -\:\X278:Fill in the control information between consecutive breakpoints \|p and -\|q\X -\U273. -\:\X273:Fill in the control points between \|p and the next breakpoint, then -advance \|p to that breakpoint\X -\U269. -\:\X611:Find a node \|q in list \|p whose coefficient \|v is largest\X -\U610. -\:\X850:Find the approximate type \\{tt} and corresponding~\|q\X -\U844. -\:\X272:Find the first breakpoint, \|h, on the path; insert an artificial -breakpoint if the path is an unbroken cycle\X -\U269. -\:\X502:Find the index \|k such that $s_{k-1}\L\\{dy}/\\{dx}<s_k$\X -\U494. -\:\X501:Find the initial slope, $\\{dy}/\\{dx}$\X -\U494. -\:\X1138:Find the minimum \\{lk\_offset} and adjust all remainders\X -\U1137. -\:\X399:Find the starting point, \|f\X -\U398. -\:\X297:Finish choosing angles and assigning control points\X -\U284. -\:\X668:Finish getting the symbolic token in \\{cur\_sym}; \&{goto} \\{restart} -if it is illegal\X -\U667. -\:\X483:Finish linking the offset nodes, and duplicate the borderline offset -nodes if necessary\X -\U481. -\:\X1168:Finish off an entirely blank character\X -\U1167. -\:\X1182:Finish the \.{GF} file\X -\U1206. -\:\X1206:Finish the \.{TFM} and \.{GF} files\X -\U1205. -\:\X1134:Finish the \.{TFM} file\X -\U1206. -\:\X459:Fix up the transition fields and adjust the turning number\X -\U452. -\:\X1016:Flush spurious symbols after the declared variable\X -\U1015. -\:\X991:Flush unparsable junk that was found after the statement\X -\U989. -\:\X957:For each of the eight cases, change the relevant fields of \\{cur\_exp} -and \&{goto} \\{done}; but do nothing if capsule \|p doesn't have the -appropriate type\X -\U955. -\:\X1003:For each type \|t, make an equation and \&{goto} \\{done} unless % -\\{cur\_type} is incompatible with~\|t\X -\U1001. -\:\X678:Get a stored numeric or string or capsule token and \&{return}\X -\U676. -\:\X671:Get a string token and \&{return}\X -\U669. -\:\X878:Get given directions separated by commas\X -\U877. -\:\X886:Get ready to close a cycle\X -\U869. -\:\X1062:Get ready to fill a contour, and fill it\X -\U1059. -\:\X1211:Get the first line of input and prepare to start\X -\U1204. -\:\X674:Get the fraction part \|f of a numeric token\X -\U669. -\:\X673:Get the integer part \|n of a numeric token; set $\|f\K0$ and \&{goto} % -\\{fin\_numeric\_token} if there is no decimal point\X -\U669. -\:\X285:Get the linear equations started; or \&{return} with the control points -in place, if linear equations needn't be solved\X -\U284. -\:\X78:Get user's advice and \&{return}\X -\U77. -\:\X914:Give error messages if \\{bad\_char} or $\|n\G4096$\X -\U913. -\:\X13, 20, 25, 29, 31, 38, 42, 50, 54, 68, 71, 74, 91, 97, 129, 137, 144, 148, -159, 160, 161, 166, 178, 190, 196, 198, 200, 201, 225, 230, 250, 267, 279, 283, -298, 308, 309, 327, 371, 379, 389, 395, 403, 427, 430, 448, 455, 461, 464, 507, -552, 555, 557, 566, 569, 572, 579, 585, 592, 624, 628, 631, 633, 634, 659, 680, -699, 738, 752, 767, 768, 775, 782, 785, 791, 796, 813, 821, 954, 1077, 1084, -1087, 1096, 1119, 1125, 1130, 1149, 1152, 1162, 1183, 1188, 1203:Global -variables\X -\U4. -\:\X168:Grow more variable-size memory and \&{goto} \\{restart}\X -\U167. -\:\X128:Handle erroneous \\{pyth\_sub} and set $\|a\K0$\X -\U126. -\:\X134:Handle non-positive logarithm\X -\U132. -\:\X690:Handle quoted symbols, \.{\#\AT!}, \.{\AT!}, or \.{\AT!\#}\X -\U685. -\:\X122:Handle square root of zero or negative argument\X -\U121. -\:\X505:Handle the special case of infinite slope\X -\U494. -\:\X548:Handle the test for eastward directions when $y_1y_3=y_2^2$; either % -\&{goto} \\{found} or \&{goto} \\{done}\X -\U546. -\:\X140:Handle undefined arg\X -\U139. -\:\X852:Handle unusual cases that masquerade as variables, and \&{goto} % -\\{restart} or \&{goto} \\{done} if appropriate; otherwise make a copy of the -variable and \&{goto} \\{done}\X -\U844. -\:\X271:If consecutive knots are equal, join them explicitly\X -\U269. -\:\X441:If node \|q is a transition point between octants, compute and save its -before-and-after coordinates\X -\U440. -\:\X434:If node \|q is a transition point for \|x coordinates, compute and save -its before-and-after coordinates\X -\U433. -\:\X437:If node \|q is a transition point for \|y coordinates, compute and save -its before-and-after coordinates\X -\U433. -\:\X956:If the current transform is entirely known, stash it in global -variables; otherwise \&{return}\X -\U953. -\:\X322:Increase and decrease $\\{move}[\|k-1]$ and $\\{move}[\|k]$ by $% -\delta_k$\X -\U321. -\:\X133:Increase \|k until \|x can be multiplied by a factor of $2^{-k}$, and -adjust $y$ accordingly\X -\U132. -\:\X143:Increase \|z to the arg of $(x,y)$\X -\U142. -\:\X519:Initialize for dual envelope moves\X -\U518. -\:\X558:Initialize for intersections at level zero\X -\U556. -\:\X513:Initialize for ordinary envelope moves\X -\U512. -\:\X581:Initialize for the display computations\X -\U577. -\:\X176, 193, 203, 229, 324, 475, 587, 702, 759, 911, 1116, 1127, -1185:Initialize table entries (done by \.{INIMF} only)\X -\U1210. -\:\X356:Initialize the array of new edge list heads\X -\U354. -\:\X528:Initialize the ellipse data structure by beginning with directions -$(0,-1)$, $(1,0)$, $(0,1)$\X -\U527. -\:\X657, 660:Initialize the input routines\X -\U1211. -\:\X55, 61, 783, 792:Initialize the output routines\X -\U1204. -\:\X70:Initialize the print \\{selector} based on \\{interaction}\X -\Us1023\ET1211. -\:\X1022:Initialize the random seed to \\{cur\_exp}\X -\U1021. -\:\X711:Initiate or terminate input from a file\X -\U707. -\:\X669:Input from external file; \&{goto} \\{restart} if no input found, or % -\&{return} if a non-symbolic token is found\X -\U667. -\:\X676:Input from token list; \&{goto} \\{restart} if end of list or if a -parameter needs to be expanded, or \&{return} if a non-symbolic token is found\X -\U667. -\:\X986:Insert a fractional node by splitting the cubic\X -\U985. -\:\X521:Insert a line segment dually to approach the correct offset\X -\U518. -\:\X515:Insert a line segment to approach the correct offset\X -\U512. -\:\X535:Insert a new line for direction $(\|u,\|v)$ between \|p and~\|q\X -\U531. -\:\X207:Insert a new symbolic token after \|p, then make \|p point to it and % -\&{goto} \\{found}\X -\U205. -\:\X677:Insert a suffix or text parameter and \&{goto} \\{restart}\X -\U676. -\:\X458:Insert additional boundary nodes, then \&{goto} \\{done}\X -\U452. -\:\X350:Insert an edge-weight for edge \|m, if the new pixel weight has changed% -\X -\U349. -\:\X355:Insert blank rows at the top and bottom, and set \|p to the new top row% -\X -\U354. -\:\X376:Insert downward edges for a line\X -\U374. -\:\X330:Insert exactly $\\{n\_min}(\\{cur\_edges})-\\{nl}$ empty rows at the -bottom\X -\U329. -\:\X331:Insert exactly $\\{nr}-\\{n\_max}(\\{cur\_edges})$ empty rows at the -top\X -\U329. -\:\X362:Insert horizontal edges of weight \|w between \|m and~\\{mm}\X -\U358. -\:\X450:Insert octant boundaries and compute the turning number\X -\U402. -\:\X452:Insert one or more octant boundary nodes just before~\|q\X -\U450. -\:\X358:Insert the horizontal edges defined by adjacent rows $\|p,\|q$, and -destroy row~\|p\X -\U354. -\:\X523:Insert the new envelope moves dually in the pixel data\X -\U518. -\:\X517:Insert the new envelope moves in the pixel data\X -\U512. -\:\X375:Insert upward edges for a line\X -\U374. -\:\X959:Install a complex multiplier, then \&{goto} \\{done}\X -\U957. -\:\X958:Install sines and cosines, then \&{goto} \\{done}\X -\U957. -\:\X531:Interpolate new vertices in the ellipse data structure until -improvement is impossible\X -\U527. -\:\X79:Interpret code \|c and \&{return} if done\X -\U78. -\:\X82:Introduce new material from the terminal and \&{return}\X -\U79. -\:\X887:Join the partial paths and reset \|p and \|q to the head and tail of -the result\X -\U869. -\:\X6:Labels in the outer block\X -\U4. -\:\X1205, 1209, 1210, 1212:Last-minute procedures\X -\U1202. -\:\X241:Link a new attribute node \|r in place of node \|p\X -\U239. -\:\X240:Link a new subscript node \|r in place of node \|p\X -\U239. -\:\X482:Link node \|r to the previous node\X -\U481. -\:\X641:Local variables for formatting calculations\X -\U635. -\:\X19, 130:Local variables for initialization\X -\U4. -\:\X1141:Log the subfile sizes of the \.{TFM} file\X -\U1134. -\:\X896:Make a special knot node for \&{pencircle}\X -\U895. -\:\X1066:Make a trivial one-point path cycle\X -\U1065. -\:\X314:Make moves for current subinterval; if bisection is necessary, push the -second subinterval onto the stack, and \&{goto} \\{continue} in order to handle -the first subinterval\X -\U311. -\:\X317:Make one move of each kind\X -\U314. -\:\X446:Make sure that all the diagonal roundings are safe\X -\U444. -\:\X243:Make sure that both nodes \|p and \\{pp} are of \\{structured} type\X -\U242. -\:\X873:Make sure that both \|x and \|y parts of \|p are known; copy them into % -\\{cur\_x} and \\{cur\_y}\X -\U872. -\:\X883:Make sure that the current expression is a valid tension setting\X -\Us882\ET882. -\:\X1207:Make the dynamic memory into one big available node\X -\U1206. -\:\X512:Make the envelope moves for the current octant and insert them in the -pixel data\X -\U506. -\:\X48:Make the first 256 strings\X -\U47. -\:\X468:Make the moves for the current octant\X -\U465. -\:\X586:Make variable $\|q+\|s$ newly independent\X -\U232. -\:\X1126:Massage the \.{TFM} heights, depths, and italic corrections\X -\U1206. -\:\X1124:Massage the \.{TFM} widths\X -\U1206. -\:\X368:Merge row \\{pp} into row \|p\X -\U366. -\:\X347:Merge the \\{temp\_head} list into $\\{sorted}(\|h)$\X -\U346. -\:\X319:Move right then up\X -\Us317\ET317. -\:\X947:Move the dependent variable \|p into both parts of the pair node \|r\X -\U946. -\:\X679:Move to next line of file, or \&{goto} \\{restart} if there is no next -line\X -\U669. -\:\X377:Move to row \\{n0}, pointed to by \|p\X -\Us375, 376, 381, 382, 383\ETs384. -\:\X532:Move to the next remaining triple $(\|p,\|q,\|r)$, removing and -skipping past zero-length lines that might be present; \&{goto} \\{done} if all -triples have been processed\X -\U531. -\:\X316:Move to the right \|m steps\X -\U314. -\:\X320:Move up then right\X -\Us317\ET317. -\:\X315:Move upward \|n steps\X -\U314. -\:\X942:Multiply when at least one operand is known\X -\U941. -\:\X136:Multiply \|y by $\exp(-z/2^{27})$\X -\U135. -\:\X903:Negate the current expression\X -\U898. -\:\X540:Normalize the given direction for better accuracy; but \&{return} with -zero result if it's zero\X -\U539. -\:\X1213:Numbered cases for \\{debug\_help}\X -\U1212. -\:\X580:Other local variables for \\{disp\_edges}\X -\U577. -\:\X511:Other local variables for \\{fill\_envelope}\X -\Us506\ET518. -\:\X542:Other local variables for \\{find\_direction\_time}\X -\U539. -\:\X280:Other local variables for \\{make\_choices}\X -\U269. -\:\X453:Other local variables for \\{make\_spec}\X -\U402. -\:\X495:Other local variables for \\{offset\_prep}\X -\U491. -\:\X831, 836, 843:Other local variables for \\{scan\_primary}\X -\U823. -\:\X286:Other local variables for \\{solve\_choices}\X -\U284. -\:\X357, 363:Other local variables for \\{xy\_swap\_edges}\X -\U354. -\:\X1208:Output statistics about this job\X -\U1205. -\:\X934:Output the answer, \|v (which might have become \\{known})\X -\U932. -\:\X1136:Output the character information bytes, then output the dimensions -themselves\X -\U1134. -\:\X1167:Output the character represented in \\{cur\_edges}\X -\U1165. -\:\X1140:Output the extensible character recipes and the font metric parameters% -\X -\U1134. -\:\X1139:Output the ligature/kern program\X -\U1134. -\:\X1169:Output the pixels of edge row \|p to font row \|n\X -\U1167. -\:\X1135:Output the subfile sizes and header bytes\X -\U1134. -\:\X675:Pack the numeric and fraction parts of a numeric token and \&{return}\X -\U669. -\:\X889:Plug an opening in $\\{right\_type}(\\{pp})$, if possible\X -\U887. -\:\X888:Plug an opening in $\\{right\_type}(\|q)$, if possible\X -\U887. -\:\X745:Pop the condition stack\X -\Us748, 749\ETs751. -\:\X237:Preface the output with a part specifier; \&{return} in the case of a -capsule\X -\U235. -\:\X380:Prepare for and switch to the appropriate case, based on \\{octant}\X -\U378. -\:\X496:Prepare for derivative computations; \&{goto} \\{not\_found} if the -current cubic is dead\X -\U494. -\:\X765:Prepare for step-until construction and \&{goto} \\{done}\X -\U764. -\:\X717:Pretend we're reading a new one-line file\X -\U716. -\:\X509:Print a line of diagnostic info to introduce this octant\X -\U508. -\:\X802:Print an abbreviated value of \|v with format depending on \|t\X -\U801. -\:\X261:Print control points between \|p and \|q, then \&{goto} \\{done1}\X -\U258. -\:\X263:Print information for a curve that begins \\{curl} or \\{given}\X -\U258. -\:\X262:Print information for a curve that begins \\{open}\X -\U258. -\:\X258:Print information for adjacent knots \|p and \|q\X -\U257. -\:\X637:Print location of current line\X -\U636. -\:\X184:Print newly busy locations\X -\U180. -\:\X1086:Print string \\{cur\_exp} as an error message\X -\U1082. -\:\X223:Print string \|r as a symbolic token and set \|c to its class\X -\U218. -\:\X260:Print tension between \|p and \|q\X -\U258. -\:\X790:Print the banner line, including the date and time\X -\U788. -\:\X590:Print the coefficient, unless it's $\pm1.0$\X -\U589. -\:\X397:Print the cubic between \|p and \|q\X -\U394. -\:\X639:Print the current loop value\X -\U638. -\:\X84:Print the help information and \&{goto} \\{continue}\X -\U79. -\:\X80:Print the menu of available options\X -\U79. -\:\X640:Print the name of a \&{vardef}'d macro\X -\U638. -\:\X85:Print the string \\{err\_help}, possibly on several lines\X -\Us84\ET86. -\:\X401:Print the turns, if any, that start at \|q, and advance \|q\X -\Us398\ET398. -\:\X474:Print the unskewed and unrotated coordinates of node \\{ww}\X -\U473. -\:\X259:Print two dots, followed by \\{given} or \\{curl} if present\X -\U257. -\:\X643:Print two lines using the tricky pseudoprinted information\X -\U636. -\:\X638:Print type of token list\X -\U636. -\:\X1110:Process a \\{skip\_to} command and \&{goto} \\{done}\X -\U1107. -\:\X838:Protest division by zero\X -\U837. -\:\X644:Pseudoprint the line\X -\U636. -\:\X645:Pseudoprint the token list\X -\U636. -\:\X744:Push the condition stack\X -\U748. -\:\X716:Put a string into the input buffer\X -\U707. -\:\X192, 211, 683, 688, 695, 709, 740, 893, 1013, 1018, 1024, 1027, 1037, 1052, -1079, 1101, 1108, 1176:Put each of \MF's primitives into the hash table\X -\U1210. -\:\X86:Put help message on the transcript file\X -\U77. -\:\X955:Put the current transform into \\{cur\_exp}\X -\U953. -\:\X795:Put the desired file name in $(\\{cur\_name},\\{cur\_ext},\\{cur% -\_area})$\X -\U793. -\:\X847:Put the left bracket and the expression back to be rescanned\X -\Us846\ET859. -\:\X345:Put the list $\\{sorted}(\|p)$ back into sort\X -\U344. -\:\X880:Put the post-join direction information into \|x and \|t\X -\U874. -\:\X879:Put the pre-join direction information into node \|q\X -\U874. -\:\X897:Read a string from the terminal\X -\U895. -\:\X681:Read next line of file into \\{buffer}, or \&{goto} \\{restart} if the -file has ended\X -\U679. -\:\X52:Read one string, but return \\{false} if the string memory space is -getting too tight for comfort\X -\U51. -\:\X794:Read the first line of the new file\X -\U793. -\:\X51:Read the other strings from the \.{MF.POOL} file and return \\{true}, or -give an error message and return \\{false}\X -\U47. -\:\X1111:Record a label in a lig/kern subprogram and \&{goto} \\{continue}\X -\U1107. -\:\X522:Record a line segment from $(\\{xx},\\{yy})$ to $(\\{xp},\\{yp})$ -dually in \\{env\_move}\X -\U521. -\:\X516:Record a line segment from $(\\{xx},\\{yy})$ to $(\\{xp},\\{yp})$ in % -\\{env\_move}\X -\U515. -\:\X814:Record a new maximum coefficient of type \|t\X -\U812. -\:\X583:Record a possible transition in column \|m\X -\U582. -\:\X810:Recycle a big node\X -\U809. -\:\X811:Recycle a dependency list\X -\U809. -\:\X812:Recycle an independent variable\X -\U809. -\:\X925:Recycle any sidestepped \\{independent} capsules\X -\U922. -\:\X939:Reduce comparison of big nodes to comparison of scalars\X -\U936. -\:\X302:Reduce to simple case of straight line and \&{return}\X -\U285. -\:\X301:Reduce to simple case of two givens and \&{return}\X -\U285. -\:\X118:Reduce to the case that $\|a,\|c\G0$, $\|b,\|d>0$\X -\U117. -\:\X110:Reduce to the case that $\|f\G0$ and $\|q>0$\X -\Us109\ET112. -\:\X339:Reflect the edge-and-weight data in $\\{sorted}(\|p)$\X -\U337. -\:\X338:Reflect the edge-and-weight data in $\\{unsorted}(\|p)$\X -\U337. -\:\X312:Remove a subproblem for \\{make\_moves} from the stack\X -\U311. -\:\X447:Remove dead cubics\X -\U402. -\:\X1007:Remove the left operand from its container, negate it, and put it into -dependency list~\|p with constant term~\|q\X -\U1006. -\:\X534:Remove the line from \|p to \|q, and adjust vertex~\|q to introduce a -new line\X -\U531. -\:\X282:Remove \\{open} types at the breakpoints\X -\U278. -\:\X712:Repeat a loop\X -\U707. -\:\X1122:Replace an interval of values by its midpoint\X -\U1121. -\:\X125:Replace \|a by an approximation to $\psqrt{a^2+b^2}$\X -\U124. -\:\X127:Replace \|a by an approximation to $\psqrt{a^2-b^2}$\X -\U126. -\:\X341:Replicate every row exactly $s$ times\X -\U340. -\:\X270:Report an unexpected problem during the choice-making\X -\U269. -\:\X34:Report overflow of the input buffer, and abort\X -\U30. -\:\X1004:Report redundant or inconsistent equation and \&{goto} \\{done}\X -\U1003. -\:\X141:Return an appropriate answer based on \|z and \\{octant}\X -\U139. -\:\X529:Revise the values of $\alpha$, $\beta$, $\gamma$, if necessary, so that -degenerate lines of length zero will not be obtained\X -\U528. -\:\X541:Rotate the cubic between \|p and \|q; then \&{goto} \\{found} if the -rotated cubic travels due east at some time \\{tt}; but \&{goto} \\{not\_found} -if an entire cyclic path has been traversed\X -\U539. -\:\X605:Run through the dependency list for variable \|t, fixing all nodes, and -ending with final link~\|q\X -\U604. -\:\X1083:Save string \\{cur\_exp} as the \\{err\_help}\X -\U1082. -\:\X343:Scale the $x$~coordinates of each row by $s$\X -\U342. -\:\X964:Scale the edges, shift them, and \&{return}\X -\U963. -\:\X408:Scale up \\{del1}, \\{del2}, and \\{del3} for greater accuracy; also -set \\{del} to the first nonzero element of $(\\{del1},\\{del2},\\{del3})$\X -\Us407, 413\ETs420. -\:\X839:Scan a binary operation with `\&{of}' between its operands\X -\U823. -\:\X861:Scan a bracketed subscript and set $\\{cur\_cmd}\K\\{numeric\_token}$\X -\U860. -\:\X876:Scan a curl specification\X -\U875. -\:\X826:Scan a delimited primary\X -\U823. -\:\X877:Scan a given direction\X -\U875. -\:\X832:Scan a grouped primary\X -\U823. -\:\X859:Scan a mediation construction\X -\U823. -\:\X834:Scan a nullary operation\X -\U823. -\:\X869:Scan a path construction operation; but \&{return} if \|p has the wrong -type\X -\U868. -\:\X837:Scan a primary that starts with a numeric token\X -\U823. -\:\X833:Scan a string constant\X -\U823. -\:\X735:Scan a suffix with optional delimiters\X -\U733. -\:\X835:Scan a unary operation\X -\U823. -\:\X844:Scan a variable primary; \&{goto} \\{restart} if it turns out to be a -macro\X -\U823. -\:\X734:Scan an expression followed by `\&{of} $\langle$primary$\rangle$'\X -\U733. -\:\X841:Scan an internal numeric quantity\X -\U823. -\:\X787:Scan file name in the buffer\X -\U786. -\:\X846:Scan for a subscript; replace \\{cur\_cmd} by \\{numeric\_token} if -found\X -\U844. -\:\X729:Scan the argument represented by $\\{info}(\|r)$\X -\U726. -\:\X726:Scan the delimited argument represented by $\\{info}(\|r)$\X -\U725. -\:\X758:Scan the loop text and put it on the loop control stack\X -\U755. -\:\X725:Scan the remaining arguments, if any; set \|r to the first token of the -replacement text\X -\U720. -\:\X830:Scan the second of a pair of numerics\X -\U826. -\:\X700:Scan the token or variable to be defined; set \|n, \\{scanner\_status}, -and \\{warning\_info}\X -\U697. -\:\X764:Scan the values to be used in the loop\X -\U755. -\:\X733:Scan undelimited argument(s)\X -\U725. -\:\X708:Scold the user for having an extra \&{endfor}\X -\U707. -\:\X209:Search \\{eqtb} for equivalents equal to \|p\X -\U185. -\:\X1166:Send nonzero offsets to the output file\X -\U1165. -\:\X1179:Send the current expression as a title to the output file\X -\U994. -\:\X884:Set explicit control points\X -\U881. -\:\X882:Set explicit tensions\X -\U881. -\:\X21, 22, 23, 69, 72, 75, 92, 98, 131, 138, 179, 191, 199, 202, 231, 251, -396, 428, 449, 456, 462, 570, 573, 593, 739, 753, 776, 797, 822, 1078, 1085, -1097, 1150, 1153, 1184:Set initial values of key variables\X -\U4. -\:\X543:Set local variables $\\{x1},\\{x2},\\{x3}$ and $\\{y1},\\{y2},\\{y3}$ -to multiples of the control points of the rotated derivatives\X -\U541. -\:\X987:Set the current expression to the desired path coordinates\X -\U985. -\:\X295:Set up equation for a curl at $\theta_n$ and \&{goto} \\{found}\X -\U284. -\:\X287:Set up equation to match mock curvatures at $z_k$; then \&{goto} % -\\{found} with $\theta_n$ adjusted to equal $\theta_0$, if a cycle has ended\X -\U284. -\:\X854:Set up suffixed macro call and \&{goto} \\{restart}\X -\U852. -\:\X1075:Set up the culling weights, or \&{goto} \\{not\_found} if the -thresholds are bad\X -\U1074. -\:\X294:Set up the equation for a curl at $\theta_0$\X -\U285. -\:\X293:Set up the equation for a given value of $\theta_0$\X -\U285. -\:\X582:Set up the parameters needed for \\{paint\_row}; but \&{goto} \\{done} -if no painting is needed after all\X -\U578. -\:\X421:Set up the variables $(\\{del1},\\{del2},\\{del3})$ to represent -$x'-y'$\X -\U420. -\:\X853:Set up unsuffixed macro call and \&{goto} \\{restart}\X -\U845. -\:\X466:Set variable \|q to the node at the end of the current octant\X -\Us465, 506\ETs506. -\:\X142:Set variable \|z to the arg of $(x,y)$\X -\U139. -\:\X867:Shift the coordinates of path \|q\X -\U866. -\:\X965:Shift the edges by $(\\{tx},\\{ty})$, rounded\X -\U964. -\:\X1042:Show a numeric or string or capsule token\X -\U1041. -\:\X721:Show the text of the macro being expanded, and the existing arguments\X -\U720. -\:\X817:Show the transformed dependency\X -\U816. -\:\X926:Sidestep \\{independent} cases in capsule \|p\X -\U922. -\:\X927:Sidestep \\{independent} cases in the current expression\X -\U922. -\:\X614:Simplify all existing dependencies by substituting for \|x\X -\U610. -\:\X1174:Skip down $\\{prev\_n}-\|n$ rows\X -\U1172. -\:\X749:Skip to \&{elseif} or \&{else} or \&{fi}, then \&{goto} \\{done}\X -\U748. -\:\X1173:Skip to column $m$ in the next row and \&{goto} \\{done}, or skip zero -rows\X -\U1172. -\:\X174:Sort \|p into the list starting at \\{rover} and advance \|p to $% -\\{rlink}(\|p)$\X -\U173. -\:\X890:Splice independent paths together\X -\U887. -\:\X504:Split off another \\{rising} cubic for \\{fin\_offset\_prep}\X -\U503. -\:\X499:Split the cubic at $t$, and split off another cubic if the derivative -crosses back\X -\U497. -\:\X494:Split the cubic between \|p and \|q, if necessary, into cubics -associated with single offsets, after which \|q should point to the end of the -final such cubic\X -\U491. -\:\X950:Squeal about division by zero\X -\U948. -\:\X479:Stamp all nodes with an octant code, compute the maximum offset, and -set \\{hh} to the node that begins the first octant; \&{goto} \\{not\_found} if -there's a problem\X -\U477. -\:\X1172:Start a new row at $(m,n)$\X -\U1170. -\:\X1170:Start black at $(m,n)$\X -\U1169. -\:\X829:Stash an independent \\{cur\_exp} into a big node\X -\U827. -\:\X1171:Stop black at $(m,n)$\X -\U1169. -\:\X1115:Store a list of font dimensions\X -\U1106. -\:\X1114:Store a list of header bytes\X -\U1106. -\:\X1107:Store a list of ligature/kern steps\X -\U1106. -\:\X1099:Store the width information for character code~\|c\X -\U1070. -\:\X413:Subdivide all cubics between \|p and \|q so that the results travel -toward the first quadrant; but \&{return} or \&{goto} \\{continue} if the cubic -from \|p to \|q was dead\X -\U406. -\:\X559:Subdivide for a new level of intersection\X -\U556. -\:\X412:Subdivide the cubic a second time with respect to $x'$\X -\U411. -\:\X425:Subdivide the cubic a second time with respect to $x'-y'$\X -\U424. -\:\X416:Subdivide the cubic a second time with respect to $y'$\X -\U415. -\:\X420:Subdivide the cubic between \|p and \|q so that the results travel -toward the first octant\X -\U419. -\:\X407:Subdivide the cubic between \|p and \|q so that the results travel -toward the right halfplane\X -\U406. -\:\X411:Subdivide the cubic with respect to $x'$, possibly twice\X -\U407. -\:\X424:Subdivide the cubic with respect to $x'-y'$, possibly twice\X -\U420. -\:\X415:Subdivide the cubic with respect to $y'$, possibly twice\X -\U413. -\:\X686:Substitute for \\{cur\_sym}, if it's on the \\{subst\_list}\X -\U685. -\:\X818:Substitute new dependencies in place of \|p\X -\U815. -\:\X819:Substitute new proto-dependencies in place of \|p\X -\U815. -\:\X147:Subtract angle \|z from $(\|x,\|y)$\X -\U145. -\:\X825:Supply diagnostic information, if requested\X -\U823. -\:\X423:Swap the \|x and \|y coordinates of the cubic between \|p and~\|q\X -\U420. -\:\X318:Switch to the right subinterval\X -\U317. -\:\X663:Tell the user what has run away and try to recover\X -\U661. -\:\X751:Terminate the current conditional and skip to \&{fi}\X -\U707. -\:\X761:The arithmetic progression has ended\X -\U760. -\:\X998:Trace the current assignment\X -\U996. -\:\X924:Trace the current binary operation\X -\U922. -\:\X997:Trace the current equation\X -\U995. -\:\X902:Trace the current unary operation\X -\U898. -\:\X945:Trace the fraction multiplication\X -\U944. -\:\X762:Trace the start of a loop\X -\U760. -\:\X520:Transfer moves dually from the \\{move} array to \\{env\_move}\X -\U518. -\:\X514:Transfer moves from the \\{move} array to \\{env\_move}\X -\U512. -\:\X970:Transform a known big node\X -\U966. -\:\X967:Transform an unknown big node and \&{return}\X -\U966. -\:\X973:Transform known by known\X -\U970. -\:\X444:Transform the skewed coordinates\X -\U440. -\:\X436:Transform the \|x coordinates\X -\U433. -\:\X439:Transform the \|y coordinates\X -\U433. -\:\X206:Treat special case of length 1 and \&{goto} \\{found}\X -\U205. -\:\X404:Truncate the values of all coordinates that exceed \\{max\_allowed}, -and stamp segment numbers in each \\{left\_type} field\X -\U402. -\:\X169:Try to allocate within node \|p and its physical successors, and % -\&{goto} \\{found} if allocation was possible\X -\U167. -\:\X789:Try to get a different log file name\X -\U788. -\:\X18, 24, 37, 101, 105, 106, 156, 186, 565, 571, 627, 1151:Types in the outer -block\X -\U4. -\:\X1199:Undump a few more things and the closing check word\X -\U1187. -\:\X1191:Undump constants for consistency check\X -\U1187. -\:\X1195:Undump the dynamic memory\X -\U1187. -\:\X1193:Undump the string pool\X -\U1187. -\:\X1197:Undump the table of equivalents and the hash table\X -\U1187. -\:\X351:Update the max/min amounts\X -\U349. -\:\X392:Use bisection to find the crossing point, if one exists\X -\U391. -\:\X584:Wind up the \\{paint\_row} parameter calculation by inserting the final -transition; \&{goto} \\{done} if no painting is needed\X -\U582. -\:\X990:Worry about bad statement\X -\U989. -\con |