modernc.org/knuth@v0.0.4/web/testdata/ctan.org/tex-archive/systems/knuth/dist/mf/mf.web (about)

     1  % This program is copyright (C) 1984 by D. E. Knuth; all rights are reserved.
     2  % Unlimited copying and redistribution of this file are permitted as long
     3  % as this file is not modified. Modifications are permitted, but only if
     4  % the resulting file is not named mf.web. (The WEB system provides
     5  % for alterations via an auxiliary file; the master file should stay intact.)
     6  % In other words, METAFONT is under essentially the same ground rules as TeX.
     7  
     8  % TeX is a trademark of the American Mathematical Society.
     9  % METAFONT is a trademark of Addison-Wesley Publishing Company.
    10  
    11  % Version 0 was completed on July 28, 1984.
    12  % Version 1 was completed on January 4, 1986; it corresponds to "Volume D".
    13  % Version 1.1 trivially corrected the punctuation in one message (June 1986).
    14  % Version 1.2 corrected an arithmetic overflow problem (July 1986).
    15  % Version 1.3 improved rounding when elliptical pens are made (November 1986).
    16  % Version 1.4 corrected scan_declared_variable timing (May 1988).
    17  % Version 1.5 fixed negative halving in allocator when mem_min<0 (June 1988).
    18  % Version 1.6 kept open_log_file from calling fatal_error (November 1988).
    19  % Version 1.7 solved that problem a better way (December 1988).
    20  % Version 1.8 introduced major changes for 8-bit extensions (September 1989).
    21  % Version 1.9 improved skimping and was edited for style (December 1989).
    22  % Version 2.0 fixed bug in addto; released with TeX version 3.0 (March 1990).
    23  % Version 2.7 made consistent with TeX version 3.1 (September 1990).
    24  % Version 2.71 fixed bug in draw, allowed unprintable filenames (March 1992).
    25  % Version 2.718 fixed bug in <Choose a dependent...> (March 1995).
    26  % Version 2.7182 fixed bugs related to "<unprintable char>" (August 1996).
    27  % Version 2.71828 suppressed autorounding in dangerous cases (June 2003).
    28  % Version 2.718281 was a general cleanup with minor fixes (February 2008).
    29  % Version 2.7182818 was similar (January 2014).
    30  % Version 2.71828182 was similar (January 2021).
    31  
    32  % A reward of $327.68 will be paid to the first finder of any remaining bug.
    33  
    34  % Although considerable effort has been expended to make the METAFONT program
    35  % correct and reliable, no warranty is implied; the author disclaims any
    36  % obligation or liability for damages, including but not limited to
    37  % special, indirect, or consequential damages arising out of or in
    38  % connection with the use or performance of this software. This work has
    39  % been a ``labor of love'' and the author hopes that users enjoy it.
    40  
    41  % Here is TeX material that gets inserted after \input webmac
    42  \def\hang{\hangindent 3em\noindent\ignorespaces}
    43  \def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces}
    44  \font\ninerm=cmr9
    45  \let\mc=\ninerm % medium caps for names like SAIL
    46  \def\PASCAL{Pascal}
    47  \def\ph{\hbox{Pascal-H}}
    48  \def\psqrt#1{\sqrt{\mathstrut#1}}
    49  \def\k{_{k+1}}
    50  \def\pct!{{\char`\%}} % percent sign in ordinary text
    51  \font\tenlogo=logo10 % font used for the METAFONT logo
    52  \font\logos=logosl10
    53  \font\eightlogo=logo8
    54  \def\MF{{\tenlogo META}\-{\tenlogo FONT}}
    55  \def\<#1>{$\langle#1\rangle$}
    56  \def\section{\mathhexbox278}
    57  \let\swap=\leftrightarrow
    58  \def\round{\mathop{\rm round}\nolimits}
    59  
    60  \def\(#1){} % this is used to make section names sort themselves better
    61  \def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@>
    62  
    63  \outer\def\N#1. \[#2]#3.{\MN#1.\vfil\eject % begin starred section
    64    \def\rhead{PART #2:\uppercase{#3}} % define running headline
    65    \message{*\modno} % progress report
    66    \edef\next{\write\cont{\Z{\?#2]#3}{\modno}{\the\pageno}}}\next
    67    \ifon\startsection{\bf\ignorespaces#3.\quad}\ignorespaces}
    68  \let\?=\relax % we want to be able to \write a \?
    69  
    70  \def\title{{\eightlogo METAFONT}}
    71  \def\topofcontents{\hsize 5.5in
    72    \vglue -30pt plus 1fil minus 1.5in
    73    \def\?##1]{\hbox to 1in{\hfil##1.\ }}
    74    }
    75  \def\botofcontents{\vskip 0pt plus 1fil minus 1.5in}
    76  \pageno=3
    77  \def\glob{13} % this should be the section number of "<Global...>"
    78  \def\gglob{20, 26} % this should be the next two sections of "<Global...>"
    79  
    80  @* \[1] Introduction.
    81  This is \MF, a font compiler intended to produce typefaces of high quality.
    82  The \PASCAL\ program that follows is the definition of \MF84, a standard
    83  @:PASCAL}{\PASCAL@>
    84  @!@:METAFONT84}{\MF84@>
    85  version of \MF\ that is designed to be highly portable so that identical output
    86  will be obtainable on a great variety of computers. The conventions
    87  of \MF84 are the same as those of \TeX82.
    88  
    89  The main purpose of the following program is to explain the algorithms of \MF\
    90  as clearly as possible. As a result, the program will not necessarily be very
    91  efficient when a particular \PASCAL\ compiler has translated it into a
    92  particular machine language. However, the program has been written so that it
    93  can be tuned to run efficiently in a wide variety of operating environments
    94  by making comparatively few changes. Such flexibility is possible because
    95  the documentation that follows is written in the \.{WEB} language, which is
    96  at a higher level than \PASCAL; the preprocessing step that converts \.{WEB}
    97  to \PASCAL\ is able to introduce most of the necessary refinements.
    98  Semi-automatic translation to other languages is also feasible, because the
    99  program below does not make extensive use of features that are peculiar to
   100  \PASCAL.
   101  
   102  A large piece of software like \MF\ has inherent complexity that cannot
   103  be reduced below a certain level of difficulty, although each individual
   104  part is fairly simple by itself. The \.{WEB} language is intended to make
   105  the algorithms as readable as possible, by reflecting the way the
   106  individual program pieces fit together and by providing the
   107  cross-references that connect different parts. Detailed comments about
   108  what is going on, and about why things were done in certain ways, have
   109  been liberally sprinkled throughout the program.  These comments explain
   110  features of the implementation, but they rarely attempt to explain the
   111  \MF\ language itself, since the reader is supposed to be familiar with
   112  {\sl The {\logos METAFONT\/}book}.
   113  @.WEB@>
   114  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
   115  
   116  @ The present implementation has a long ancestry, beginning in the spring
   117  of~1977, when its author wrote a prototype set of subroutines and macros
   118  @^Knuth, Donald Ervin@>
   119  that were used to develop the first Computer Modern fonts.
   120  This original proto-\MF\ required the user to recompile a {\mc SAIL} program
   121  whenever any character was changed, because it was not a ``language'' for
   122  font design; the language was {\mc SAIL}. After several hundred characters
   123  had been designed in that way, the author developed an interpretable language
   124  called \MF, in which it was possible to express the Computer Modern programs
   125  less cryptically. A complete \MF\ processor was designed and coded by the
   126  author in 1979. This program, written in {\mc SAIL}, was adapted for use
   127  with a variety of typesetting equipment and display terminals by Leo Guibas,
   128  Lyle Ramshaw, and David Fuchs.
   129  @^Guibas, Leonidas Ioannis@>
   130  @^Ramshaw, Lyle Harold@>
   131  @^Fuchs, David Raymond@>
   132  Major improvements to the design of Computer Modern fonts were made in the
   133  spring of 1982, after which it became clear that a new language would
   134  better express the needs of letterform designers. Therefore an entirely
   135  new \MF\ language and system were developed in 1984; the present system
   136  retains the name and some of the spirit of \MF79, but all of the details
   137  have changed.
   138  
   139  No doubt there still is plenty of room for improvement, but the author
   140  is firmly committed to keeping \MF84 ``frozen'' from now on; stability
   141  and reliability are to be its main virtues.
   142  
   143  On the other hand, the \.{WEB} description can be extended without changing
   144  the core of \MF84 itself, and the program has been designed so that such
   145  extensions are not extremely difficult to make.
   146  The |banner| string defined here should be changed whenever \MF\
   147  undergoes any modifications, so that it will be clear which version of
   148  \MF\ might be the guilty party when a problem arises.
   149  @^extensions to \MF@>
   150  @^system dependencies@>
   151  
   152  If this program is changed, the resulting system should not be called
   153  `\MF\kern.5pt'; the official name `\MF\kern.5pt' by itself is reserved
   154  for software systems that are fully compatible with each other.
   155  A special test suite called the ``\.{TRAP} test'' is available for
   156  helping to determine whether an implementation deserves to be
   157  known as `\MF\kern.5pt' [cf.~Stanford Computer Science report CS1095,
   158  January 1986].
   159  
   160  @d banner=='This is METAFONT, Version 2.71828182' {printed when \MF\ starts}
   161  
   162  @ Different \PASCAL s have slightly different conventions, and the present
   163  @!@:PASCAL H}{\ph@>
   164  program expresses \MF\ in terms of the \PASCAL\ that was
   165  available to the author in 1984. Constructions that apply to
   166  this particular compiler, which we shall call \ph, should help the
   167  reader see how to make an appropriate interface for other systems
   168  if necessary. (\ph\ is Charles Hedrick's modification of a compiler
   169  @^Hedrick, Charles Locke@>
   170  for the DECsystem-10 that was originally developed at the University of
   171  Hamburg; cf.\ {\sl Software---Practice and Experience \bf6} (1976),
   172  29--42. The \MF\ program below is intended to be adaptable, without
   173  extensive changes, to most other versions of \PASCAL, so it does not fully
   174  use the admirable features of \ph. Indeed, a conscious effort has been
   175  made here to avoid using several idiosyncratic features of standard
   176  \PASCAL\ itself, so that most of the code can be translated mechanically
   177  into other high-level languages. For example, the `\&{with}' and `\\{new}'
   178  features are not used, nor are pointer types, set types, or enumerated
   179  scalar types; there are no `\&{var}' parameters, except in the case of files
   180  or in the system-dependent |paint_row| procedure;
   181  there are no tag fields on variant records; there are no |real| variables;
   182  no procedures are declared local to other procedures.)
   183  
   184  The portions of this program that involve system-dependent code, where
   185  changes might be necessary because of differences between \PASCAL\ compilers
   186  and/or differences between
   187  operating systems, can be identified by looking at the sections whose
   188  numbers are listed under `system dependencies' in the index. Furthermore,
   189  the index entries for `dirty \PASCAL' list all places where the restrictions
   190  of \PASCAL\ have not been followed perfectly, for one reason or another.
   191  @!@^system dependencies@>
   192  @!@^dirty \PASCAL@>
   193  
   194  @ The program begins with a normal \PASCAL\ program heading, whose
   195  components will be filled in later, using the conventions of \.{WEB}.
   196  @.WEB@>
   197  For example, the portion of the program called `\X\glob:Global
   198  variables\X' below will be replaced by a sequence of variable declarations
   199  that starts in $\section\glob$ of this documentation. In this way, we are able
   200  to define each individual global variable when we are prepared to
   201  understand what it means; we do not have to define all of the globals at
   202  once.  Cross references in $\section\glob$, where it says ``See also
   203  sections \gglob, \dots,'' also make it possible to look at the set of
   204  all global variables, if desired.  Similar remarks apply to the other
   205  portions of the program heading.
   206  
   207  Actually the heading shown here is not quite normal: The |program| line
   208  does not mention any |output| file, because \ph\ would ask the \MF\ user
   209  to specify a file name if |output| were specified here.
   210  @:PASCAL H}{\ph@>
   211  @^system dependencies@>
   212  
   213  @d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:}
   214  @f mtype==type {`\&{mtype}' will be equivalent to `\&{type}'}
   215  @f type==true {but `|type|' will not be treated as a reserved word}
   216  
   217  @p @t\4@>@<Compiler directives@>@/
   218  program MF; {all file names are defined dynamically}
   219  label @<Labels in the outer block@>@/
   220  const @<Constants in the outer block@>@/
   221  mtype @<Types in the outer block@>@/
   222  var @<Global variables@>@/
   223  @#
   224  procedure initialize; {this procedure gets things started properly}
   225    var @<Local variables for initialization@>@/
   226    begin @<Set initial values of key variables@>@/
   227    end;@#
   228  @t\4@>@<Basic printing procedures@>@/
   229  @t\4@>@<Error handling procedures@>@/
   230  
   231  @ The overall \MF\ program begins with the heading just shown, after which
   232  comes a bunch of procedure declarations and function declarations.
   233  Finally we will get to the main program, which begins with the
   234  comment `|start_here|'. If you want to skip down to the
   235  main program now, you can look up `|start_here|' in the index.
   236  But the author suggests that the best way to understand this program
   237  is to follow pretty much the order of \MF's components as they appear in the
   238  \.{WEB} description you are now reading, since the present ordering is
   239  intended to combine the advantages of the ``bottom up'' and ``top down''
   240  approaches to the problem of understanding a somewhat complicated system.
   241  
   242  @ Three labels must be declared in the main program, so we give them
   243  symbolic names.
   244  
   245  @d start_of_MF=1 {go here when \MF's variables are initialized}
   246  @d end_of_MF=9998 {go here to close files and terminate gracefully}
   247  @d final_end=9999 {this label marks the ending of the program}
   248  
   249  @<Labels in the out...@>=
   250  start_of_MF@t\hskip-2pt@>, end_of_MF@t\hskip-2pt@>,@,final_end;
   251    {key control points}
   252  
   253  @ Some of the code below is intended to be used only when diagnosing the
   254  strange behavior that sometimes occurs when \MF\ is being installed or
   255  when system wizards are fooling around with \MF\ without quite knowing
   256  what they are doing. Such code will not normally be compiled; it is
   257  delimited by the codewords `$|debug|\ldots|gubed|$', with apologies
   258  to people who wish to preserve the purity of English.
   259  
   260  Similarly, there is some conditional code delimited by
   261  `$|stat|\ldots|tats|$' that is intended for use when statistics are to be
   262  kept about \MF's memory usage.  The |stat| $\ldots$ |tats| code also
   263  implements special diagnostic information that is printed when
   264  $\\{tracingedges}>1$.
   265  @^debugging@>
   266  
   267  @d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
   268  @d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
   269  @f debug==begin
   270  @f gubed==end
   271  @#
   272  @d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering
   273    usage statistics}
   274  @d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering
   275    usage statistics}
   276  @f stat==begin
   277  @f tats==end
   278  
   279  @ This program has two important variations: (1) There is a long and slow
   280  version called \.{INIMF}, which does the extra calculations needed to
   281  @.INIMF@>
   282  initialize \MF's internal tables; and (2)~there is a shorter and faster
   283  production version, which cuts the initialization to a bare minimum.
   284  Parts of the program that are needed in (1) but not in (2) are delimited by
   285  the codewords `$|init|\ldots|tini|$'.
   286  
   287  @d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
   288  @d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
   289  @f init==begin
   290  @f tini==end
   291  
   292  @ If the first character of a \PASCAL\ comment is a dollar sign,
   293  \ph\ treats the comment as a list of ``compiler directives'' that will
   294  affect the translation of this program into machine language.  The
   295  directives shown below specify full checking and inclusion of the \PASCAL\
   296  debugger when \MF\ is being debugged, but they cause range checking and other
   297  redundant code to be eliminated when the production system is being generated.
   298  Arithmetic overflow will be detected in all cases.
   299  @:PASCAL H}{\ph@>
   300  @^system dependencies@>
   301  @^overflow in arithmetic@>
   302  
   303  @<Compiler directives@>=
   304  @{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead}
   305  @!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
   306  
   307  @ This \MF\ implementation conforms to the rules of the {\sl Pascal User
   308  @:PASCAL}{\PASCAL@>
   309  @^system dependencies@>
   310  Manual} published by Jensen and Wirth in 1975, except where system-dependent
   311  @^Wirth, Niklaus@>
   312  @^Jensen, Kathleen@>
   313  code is necessary to make a useful system program, and except in another
   314  respect where such conformity would unnecessarily obscure the meaning
   315  and clutter up the code: We assume that |case| statements may include a
   316  default case that applies if no matching label is found. Thus, we shall use
   317  constructions like
   318  $$\vbox{\halign{\ignorespaces#\hfil\cr
   319  |case x of|\cr
   320  1: $\langle\,$code for $x=1\,\rangle$;\cr
   321  3: $\langle\,$code for $x=3\,\rangle$;\cr
   322  |othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
   323  |endcases|\cr}}$$
   324  since most \PASCAL\ compilers have plugged this hole in the language by
   325  incorporating some sort of default mechanism. For example, the \ph\
   326  compiler allows `|others|:' as a default label, and other \PASCAL s allow
   327  syntaxes like `\&{else}' or `\&{otherwise}' or `\\{otherwise}:', etc. The
   328  definitions of |othercases| and |endcases| should be changed to agree with
   329  local conventions.  Note that no semicolon appears before |endcases| in
   330  this program, so the definition of |endcases| should include a semicolon
   331  if the compiler wants one. (Of course, if no default mechanism is
   332  available, the |case| statements of \MF\ will have to be laboriously
   333  extended by listing all remaining cases. People who are stuck with such
   334  \PASCAL s have, in fact, done this, successfully but not happily!)
   335  @:PASCAL H}{\ph@>
   336  
   337  @d othercases == others: {default for cases not listed explicitly}
   338  @d endcases == @+end {follows the default case in an extended |case| statement}
   339  @f othercases == else
   340  @f endcases == end
   341  
   342  @ The following parameters can be changed at compile time to extend or
   343  reduce \MF's capacity. They may have different values in \.{INIMF} and
   344  in production versions of \MF.
   345  @.INIMF@>
   346  @^system dependencies@>
   347  
   348  @<Constants...@>=
   349  @!mem_max=30000; {greatest index in \MF's internal |mem| array;
   350    must be strictly less than |max_halfword|;
   351    must be equal to |mem_top| in \.{INIMF}, otherwise |>=mem_top|}
   352  @!max_internal=100; {maximum number of internal quantities}
   353  @!buf_size=500; {maximum number of characters simultaneously present in
   354    current lines of open files; must not exceed |max_halfword|}
   355  @!error_line=72; {width of context lines on terminal error messages}
   356  @!half_error_line=42; {width of first lines of contexts in terminal
   357    error messages; should be between 30 and |error_line-15|}
   358  @!max_print_line=79; {width of longest text lines output; should be at least 60}
   359  @!screen_width=768; {number of pixels in each row of screen display}
   360  @!screen_depth=1024; {number of pixels in each column of screen display}
   361  @!stack_size=30; {maximum number of simultaneous input sources}
   362  @!max_strings=2000; {maximum number of strings; must not exceed |max_halfword|}
   363  @!string_vacancies=8000; {the minimum number of characters that should be
   364    available for the user's identifier names and strings,
   365    after \MF's own error messages are stored}
   366  @!pool_size=32000; {maximum number of characters in strings, including all
   367    error messages and help texts, and the names of all identifiers;
   368    must exceed |string_vacancies| by the total
   369    length of \MF's own strings, which is currently about 22000}
   370  @!move_size=5000; {space for storing moves in a single octant}
   371  @!max_wiggle=300; {number of autorounded points per cycle}
   372  @!gf_buf_size=800; {size of the output buffer, must be a multiple of 8}
   373  @!file_name_size=40; {file names shouldn't be longer than this}
   374  @!pool_name='MFbases:MF.POOL                         ';
   375    {string of length |file_name_size|; tells where the string pool appears}
   376  @.MFbases@>
   377  @!path_size=300; {maximum number of knots between breakpoints of a path}
   378  @!bistack_size=785; {size of stack for bisection algorithms;
   379    should probably be left at this value}
   380  @!header_size=100; {maximum number of \.{TFM} header words, times~4}
   381  @!lig_table_size=5000; {maximum number of ligature/kern steps, must be
   382    at least 255 and at most 32510}
   383  @!max_kerns=500; {maximum number of distinct kern amounts}
   384  @!max_font_dimen=50; {maximum number of \&{fontdimen} parameters}
   385  
   386  @ Like the preceding parameters, the following quantities can be changed
   387  at compile time to extend or reduce \MF's capacity. But if they are changed,
   388  it is necessary to rerun the initialization program \.{INIMF}
   389  @.INIMF@>
   390  to generate new tables for the production \MF\ program.
   391  One can't simply make helter-skelter changes to the following constants,
   392  since certain rather complex initialization
   393  numbers are computed from them. They are defined here using
   394  \.{WEB} macros, instead of being put into \PASCAL's |const| list, in order to
   395  emphasize this distinction.
   396  
   397  @d mem_min=0 {smallest index in the |mem| array, must not be less
   398    than |min_halfword|}
   399  @d mem_top==30000 {largest index in the |mem| array dumped by \.{INIMF};
   400    must be substantially larger than |mem_min|
   401    and not greater than |mem_max|}
   402  @d hash_size=2100 {maximum number of symbolic tokens,
   403    must be less than |max_halfword-3*param_size|}
   404  @d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
   405  @d max_in_open=6 {maximum number of input files and error insertions that
   406    can be going on simultaneously}
   407  @d param_size=150 {maximum number of simultaneous macro parameters}
   408  @^system dependencies@>
   409  
   410  @ In case somebody has inadvertently made bad settings of the ``constants,''
   411  \MF\ checks them using a global variable called |bad|.
   412  
   413  This is the first of many sections of \MF\ where global variables are
   414  defined.
   415  
   416  @<Glob...@>=
   417  @!bad:integer; {is some ``constant'' wrong?}
   418  
   419  @ Later on we will say `\ignorespaces|if mem_max>=max_halfword then bad:=10|',
   420  or something similar. (We can't do that until |max_halfword| has been defined.)
   421  
   422  @<Check the ``constant'' values for consistency@>=
   423  bad:=0;
   424  if (half_error_line<30)or(half_error_line>error_line-15) then bad:=1;
   425  if max_print_line<60 then bad:=2;
   426  if gf_buf_size mod 8<>0 then bad:=3;
   427  if mem_min+1100>mem_top then bad:=4;
   428  if hash_prime>hash_size then bad:=5;
   429  if header_size mod 4 <> 0 then bad:=6;
   430  if(lig_table_size<255)or(lig_table_size>32510)then bad:=7;
   431  
   432  @ Labels are given symbolic names by the following definitions, so that
   433  occasional |goto| statements will be meaningful. We insert the label
   434  `|exit|' just before the `\ignorespaces|end|\unskip' of a procedure in
   435  which we have used the `|return|' statement defined below; the label
   436  `|restart|' is occasionally used at the very beginning of a procedure; and
   437  the label `|reswitch|' is occasionally used just prior to a |case|
   438  statement in which some cases change the conditions and we wish to branch
   439  to the newly applicable case.  Loops that are set up with the |loop|
   440  construction defined below are commonly exited by going to `|done|' or to
   441  `|found|' or to `|not_found|', and they are sometimes repeated by going to
   442  `|continue|'.  If two or more parts of a subroutine start differently but
   443  end up the same, the shared code may be gathered together at
   444  `|common_ending|'.
   445  
   446  Incidentally, this program never declares a label that isn't actually used,
   447  because some fussy \PASCAL\ compilers will complain about redundant labels.
   448  
   449  @d exit=10 {go here to leave a procedure}
   450  @d restart=20 {go here to start a procedure again}
   451  @d reswitch=21 {go here to start a case statement again}
   452  @d continue=22 {go here to resume a loop}
   453  @d done=30 {go here to exit a loop}
   454  @d done1=31 {like |done|, when there is more than one loop}
   455  @d done2=32 {for exiting the second loop in a long block}
   456  @d done3=33 {for exiting the third loop in a very long block}
   457  @d done4=34 {for exiting the fourth loop in an extremely long block}
   458  @d done5=35 {for exiting the fifth loop in an immense block}
   459  @d done6=36 {for exiting the sixth loop in a block}
   460  @d found=40 {go here when you've found it}
   461  @d found1=41 {like |found|, when there's more than one per routine}
   462  @d found2=42 {like |found|, when there's more than two per routine}
   463  @d not_found=45 {go here when you've found nothing}
   464  @d common_ending=50 {go here when you want to merge with another branch}
   465  
   466  @ Here are some macros for common programming idioms.
   467  
   468  @d incr(#) == #:=#+1 {increase a variable by unity}
   469  @d decr(#) == #:=#-1 {decrease a variable by unity}
   470  @d negate(#) == #:=-# {change the sign of a variable}
   471  @d double(#) == #:=#+# {multiply a variable by two}
   472  @d loop == @+ while true do@+ {repeat over and over until a |goto| happens}
   473  @f loop == xclause
   474    {\.{WEB}'s |xclause| acts like `\ignorespaces|while true do|\unskip'}
   475  @d do_nothing == {empty statement}
   476  @d return == goto exit {terminate a procedure call}
   477  @f return == nil {\.{WEB} will henceforth say |return| instead of \\{return}}
   478  
   479  @* \[2] The character set.
   480  In order to make \MF\ readily portable to a wide variety of
   481  computers, all of its input text is converted to an internal eight-bit
   482  code that includes standard ASCII, the ``American Standard Code for
   483  Information Interchange.''  This conversion is done immediately when each
   484  character is read in. Conversely, characters are converted from ASCII to
   485  the user's external representation just before they are output to a
   486  text file.
   487  @^ASCII code@>
   488  
   489  Such an internal code is relevant to users of \MF\ only with respect to
   490  the \&{char} and \&{ASCII} operations, and the comparison of strings.
   491  
   492  @ Characters of text that have been converted to \MF's internal form
   493  are said to be of type |ASCII_code|, which is a subrange of the integers.
   494  
   495  @<Types...@>=
   496  @!ASCII_code=0..255; {eight-bit numbers}
   497  
   498  @ The original \PASCAL\ compiler was designed in the late 60s, when six-bit
   499  character sets were common, so it did not make provision for lowercase
   500  letters. Nowadays, of course, we need to deal with both capital and small
   501  letters in a convenient way, especially in a program for font design;
   502  so the present specification of \MF\ has been written under the assumption
   503  that the \PASCAL\ compiler and run-time system permit the use of text files
   504  with more than 64 distinguishable characters. More precisely, we assume that
   505  the character set contains at least the letters and symbols associated
   506  with ASCII codes @'40 through @'176; all of these characters are now
   507  available on most computer terminals.
   508  
   509  Since we are dealing with more characters than were present in the first
   510  \PASCAL\ compilers, we have to decide what to call the associated data
   511  type. Some \PASCAL s use the original name |char| for the
   512  characters in text files, even though there now are more than 64 such
   513  characters, while other \PASCAL s consider |char| to be a 64-element
   514  subrange of a larger data type that has some other name.
   515  
   516  In order to accommodate this difference, we shall use the name |text_char|
   517  to stand for the data type of the characters that are converted to and
   518  from |ASCII_code| when they are input and output. We shall also assume
   519  that |text_char| consists of the elements |chr(first_text_char)| through
   520  |chr(last_text_char)|, inclusive. The following definitions should be
   521  adjusted if necessary.
   522  @^system dependencies@>
   523  
   524  @d text_char == char {the data type of characters in text files}
   525  @d first_text_char=0 {ordinal number of the smallest element of |text_char|}
   526  @d last_text_char=255 {ordinal number of the largest element of |text_char|}
   527  
   528  @<Local variables for init...@>=
   529  @!i:integer;
   530  
   531  @ The \MF\ processor converts between ASCII code and
   532  the user's external character set by means of arrays |xord| and |xchr|
   533  that are analogous to \PASCAL's |ord| and |chr| functions.
   534  
   535  @<Glob...@>=
   536  @!xord: array [text_char] of ASCII_code;
   537    {specifies conversion of input characters}
   538  @!xchr: array [ASCII_code] of text_char;
   539    {specifies conversion of output characters}
   540  
   541  @ Since we are assuming that our \PASCAL\ system is able to read and
   542  write the visible characters of standard ASCII (although not
   543  necessarily using the ASCII codes to represent them), the following
   544  assignment statements initialize the standard part of the |xchr| array
   545  properly, without needing any system-dependent changes. On the other
   546  hand, it is possible to implement \MF\ with less complete character
   547  sets, and in such cases it will be necessary to change something here.
   548  @^system dependencies@>
   549  
   550  @<Set init...@>=
   551  xchr[@'40]:=' ';
   552  xchr[@'41]:='!';
   553  xchr[@'42]:='"';
   554  xchr[@'43]:='#';
   555  xchr[@'44]:='$';
   556  xchr[@'45]:='%';
   557  xchr[@'46]:='&';
   558  xchr[@'47]:='''';@/
   559  xchr[@'50]:='(';
   560  xchr[@'51]:=')';
   561  xchr[@'52]:='*';
   562  xchr[@'53]:='+';
   563  xchr[@'54]:=',';
   564  xchr[@'55]:='-';
   565  xchr[@'56]:='.';
   566  xchr[@'57]:='/';@/
   567  xchr[@'60]:='0';
   568  xchr[@'61]:='1';
   569  xchr[@'62]:='2';
   570  xchr[@'63]:='3';
   571  xchr[@'64]:='4';
   572  xchr[@'65]:='5';
   573  xchr[@'66]:='6';
   574  xchr[@'67]:='7';@/
   575  xchr[@'70]:='8';
   576  xchr[@'71]:='9';
   577  xchr[@'72]:=':';
   578  xchr[@'73]:=';';
   579  xchr[@'74]:='<';
   580  xchr[@'75]:='=';
   581  xchr[@'76]:='>';
   582  xchr[@'77]:='?';@/
   583  xchr[@'100]:='@@';
   584  xchr[@'101]:='A';
   585  xchr[@'102]:='B';
   586  xchr[@'103]:='C';
   587  xchr[@'104]:='D';
   588  xchr[@'105]:='E';
   589  xchr[@'106]:='F';
   590  xchr[@'107]:='G';@/
   591  xchr[@'110]:='H';
   592  xchr[@'111]:='I';
   593  xchr[@'112]:='J';
   594  xchr[@'113]:='K';
   595  xchr[@'114]:='L';
   596  xchr[@'115]:='M';
   597  xchr[@'116]:='N';
   598  xchr[@'117]:='O';@/
   599  xchr[@'120]:='P';
   600  xchr[@'121]:='Q';
   601  xchr[@'122]:='R';
   602  xchr[@'123]:='S';
   603  xchr[@'124]:='T';
   604  xchr[@'125]:='U';
   605  xchr[@'126]:='V';
   606  xchr[@'127]:='W';@/
   607  xchr[@'130]:='X';
   608  xchr[@'131]:='Y';
   609  xchr[@'132]:='Z';
   610  xchr[@'133]:='[';
   611  xchr[@'134]:='\';
   612  xchr[@'135]:=']';
   613  xchr[@'136]:='^';
   614  xchr[@'137]:='_';@/
   615  xchr[@'140]:='`';
   616  xchr[@'141]:='a';
   617  xchr[@'142]:='b';
   618  xchr[@'143]:='c';
   619  xchr[@'144]:='d';
   620  xchr[@'145]:='e';
   621  xchr[@'146]:='f';
   622  xchr[@'147]:='g';@/
   623  xchr[@'150]:='h';
   624  xchr[@'151]:='i';
   625  xchr[@'152]:='j';
   626  xchr[@'153]:='k';
   627  xchr[@'154]:='l';
   628  xchr[@'155]:='m';
   629  xchr[@'156]:='n';
   630  xchr[@'157]:='o';@/
   631  xchr[@'160]:='p';
   632  xchr[@'161]:='q';
   633  xchr[@'162]:='r';
   634  xchr[@'163]:='s';
   635  xchr[@'164]:='t';
   636  xchr[@'165]:='u';
   637  xchr[@'166]:='v';
   638  xchr[@'167]:='w';@/
   639  xchr[@'170]:='x';
   640  xchr[@'171]:='y';
   641  xchr[@'172]:='z';
   642  xchr[@'173]:='{';
   643  xchr[@'174]:='|';
   644  xchr[@'175]:='}';
   645  xchr[@'176]:='~';@/
   646  
   647  @ The ASCII code is ``standard'' only to a certain extent, since many
   648  computer installations have found it advantageous to have ready access
   649  to more than 94 printing characters.  If \MF\ is being used
   650  on a garden-variety \PASCAL\ for which only standard ASCII
   651  codes will appear in the input and output files, it doesn't really matter
   652  what codes are specified in |xchr[0..@'37]|, but the safest policy is to
   653  blank everything out by using the code shown below.
   654  
   655  However, other settings of |xchr| will make \MF\ more friendly on
   656  computers that have an extended character set, so that users can type things
   657  like `\.^^Z' instead of `\.{<>}'.
   658  People with extended character sets can
   659  assign codes arbitrarily, giving an |xchr| equivalent to whatever
   660  characters the users of \MF\ are allowed to have in their input files.
   661  Appropriate changes to \MF's |char_class| table should then be made.
   662  (Unlike \TeX, each installation of \MF\ has a fixed assignment of category
   663  codes, called the |char_class|.) Such changes make portability of programs
   664  more difficult, so they should be introduced cautiously if at all.
   665  @^character set dependencies@>
   666  @^system dependencies@>
   667  
   668  @<Set init...@>=
   669  for i:=0 to @'37 do xchr[i]:=' ';
   670  for i:=@'177 to @'377 do xchr[i]:=' ';
   671  
   672  @ The following system-independent code makes the |xord| array contain a
   673  suitable inverse to the information in |xchr|. Note that if |xchr[i]=xchr[j]|
   674  where |i<j<@'177|, the value of |xord[xchr[i]]| will turn out to be
   675  |j| or more; hence, standard ASCII code numbers will be used instead of
   676  codes below @'40 in case there is a coincidence.
   677  
   678  @<Set init...@>=
   679  for i:=first_text_char to last_text_char do xord[chr(i)]:=@'177;
   680  for i:=@'200 to @'377 do xord[xchr[i]]:=i;
   681  for i:=0 to @'176 do xord[xchr[i]]:=i;
   682  
   683  @* \[3] Input and output.
   684  The bane of portability is the fact that different operating systems treat
   685  input and output quite differently, perhaps because computer scientists
   686  have not given sufficient attention to this problem. People have felt somehow
   687  that input and output are not part of ``real'' programming. Well, it is true
   688  that some kinds of programming are more fun than others. With existing
   689  input/output conventions being so diverse and so messy, the only sources of
   690  joy in such parts of the code are the rare occasions when one can find a
   691  way to make the program a little less bad than it might have been. We have
   692  two choices, either to attack I/O now and get it over with, or to postpone
   693  I/O until near the end. Neither prospect is very attractive, so let's
   694  get it over with.
   695  
   696  The basic operations we need to do are (1)~inputting and outputting of
   697  text, to or from a file or the user's terminal; (2)~inputting and
   698  outputting of eight-bit bytes, to or from a file; (3)~instructing the
   699  operating system to initiate (``open'') or to terminate (``close'') input or
   700  output from a specified file; (4)~testing whether the end of an input
   701  file has been reached; (5)~display of bits on the user's screen.
   702  The bit-display operation will be discussed in a later section; we shall
   703  deal here only with more traditional kinds of I/O.
   704  
   705  \MF\ needs to deal with two kinds of files.
   706  We shall use the term |alpha_file| for a file that contains textual data,
   707  and the term |byte_file| for a file that contains eight-bit binary information.
   708  These two types turn out to be the same on many computers, but
   709  sometimes there is a significant distinction, so we shall be careful to
   710  distinguish between them. Standard protocols for transferring
   711  such files from computer to computer, via high-speed networks, are
   712  now becoming available to more and more communities of users.
   713  
   714  The program actually makes use also of a third kind of file, called a
   715  |word_file|, when dumping and reloading base information for its own
   716  initialization.  We shall define a word file later; but it will be possible
   717  for us to specify simple operations on word files before they are defined.
   718  
   719  @<Types...@>=
   720  @!eight_bits=0..255; {unsigned one-byte quantity}
   721  @!alpha_file=packed file of text_char; {files that contain textual data}
   722  @!byte_file=packed file of eight_bits; {files that contain binary data}
   723  
   724  @ Most of what we need to do with respect to input and output can be handled
   725  by the I/O facilities that are standard in \PASCAL, i.e., the routines
   726  called |get|, |put|, |eof|, and so on. But
   727  standard \PASCAL\ does not allow file variables to be associated with file
   728  names that are determined at run time, so it cannot be used to implement
   729  \MF; some sort of extension to \PASCAL's ordinary |reset| and |rewrite|
   730  is crucial for our purposes. We shall assume that |name_of_file| is a variable
   731  of an appropriate type such that the \PASCAL\ run-time system being used to
   732  implement \MF\ can open a file whose external name is specified by
   733  |name_of_file|.
   734  @^system dependencies@>
   735  
   736  @<Glob...@>=
   737  @!name_of_file:packed array[1..file_name_size] of char;@;@/
   738    {on some systems this may be a \&{record} variable}
   739  @!name_length:0..file_name_size;@/{this many characters are actually
   740    relevant in |name_of_file| (the rest are blank)}
   741  
   742  @ The \ph\ compiler with which the present version of \MF\ was prepared has
   743  extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
   744  we can write
   745  $$\vbox{\halign{#\hfil\qquad&#\hfil\cr
   746  |reset(f,@t\\{name}@>,'/O')|&for input;\cr
   747  |rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
   748  The `\\{name}' parameter, which is of type `\ignorespaces|packed
   749  array[@t\<\\{any}>@>] of text_char|', stands for the name of
   750  the external file that is being opened for input or output.
   751  Blank spaces that might appear in \\{name} are ignored.
   752  
   753  The `\.{/O}' parameter tells the operating system not to issue its own
   754  error messages if something goes wrong. If a file of the specified name
   755  cannot be found, or if such a file cannot be opened for some other reason
   756  (e.g., someone may already be trying to write the same file), we will have
   757  |@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|.  This allows
   758  \MF\ to undertake appropriate corrective action.
   759  @:PASCAL H}{\ph@>
   760  @^system dependencies@>
   761  
   762  \MF's file-opening procedures return |false| if no file identified by
   763  |name_of_file| could be opened.
   764  
   765  @d reset_OK(#)==erstat(#)=0
   766  @d rewrite_OK(#)==erstat(#)=0
   767  
   768  @p function a_open_in(var @!f:alpha_file):boolean;
   769    {open a text file for input}
   770  begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f);
   771  end;
   772  @#
   773  function a_open_out(var @!f:alpha_file):boolean;
   774    {open a text file for output}
   775  begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f);
   776  end;
   777  @#
   778  function b_open_out(var @!f:byte_file):boolean;
   779    {open a binary file for output}
   780  begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f);
   781  end;
   782  @#
   783  function w_open_in(var @!f:word_file):boolean;
   784    {open a word file for input}
   785  begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f);
   786  end;
   787  @#
   788  function w_open_out(var @!f:word_file):boolean;
   789    {open a word file for output}
   790  begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f);
   791  end;
   792  
   793  @ Files can be closed with the \ph\ routine `|close(f)|', which
   794  @:PASCAL H}{\ph@>
   795  @^system dependencies@>
   796  should be used when all input or output with respect to |f| has been completed.
   797  This makes |f| available to be opened again, if desired; and if |f| was used for
   798  output, the |close| operation makes the corresponding external file appear
   799  on the user's area, ready to be read.
   800  
   801  @p procedure a_close(var @!f:alpha_file); {close a text file}
   802  begin close(f);
   803  end;
   804  @#
   805  procedure b_close(var @!f:byte_file); {close a binary file}
   806  begin close(f);
   807  end;
   808  @#
   809  procedure w_close(var @!f:word_file); {close a word file}
   810  begin close(f);
   811  end;
   812  
   813  @ Binary input and output are done with \PASCAL's ordinary |get| and |put|
   814  procedures, so we don't have to make any other special arrangements for
   815  binary~I/O. Text output is also easy to do with standard \PASCAL\ routines.
   816  The treatment of text input is more difficult, however, because
   817  of the necessary translation to |ASCII_code| values.
   818  \MF's conventions should be efficient, and they should
   819  blend nicely with the user's operating environment.
   820  
   821  @ Input from text files is read one line at a time, using a routine called
   822  |input_ln|. This function is defined in terms of global variables called
   823  |buffer|, |first|, and |last| that will be described in detail later; for
   824  now, it suffices for us to know that |buffer| is an array of |ASCII_code|
   825  values, and that |first| and |last| are indices into this array
   826  representing the beginning and ending of a line of text.
   827  
   828  @<Glob...@>=
   829  @!buffer:array[0..buf_size] of ASCII_code; {lines of characters being read}
   830  @!first:0..buf_size; {the first unused position in |buffer|}
   831  @!last:0..buf_size; {end of the line just input to |buffer|}
   832  @!max_buf_stack:0..buf_size; {largest index used in |buffer|}
   833  
   834  @ The |input_ln| function brings the next line of input from the specified
   835  file into available positions of the buffer array and returns the value
   836  |true|, unless the file has already been entirely read, in which case it
   837  returns |false| and sets |last:=first|.  In general, the |ASCII_code|
   838  numbers that represent the next line of the file are input into
   839  |buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the
   840  global variable |last| is set equal to |first| plus the length of the
   841  line. Trailing blanks are removed from the line; thus, either |last=first|
   842  (in which case the line was entirely blank) or |buffer[last-1]<>" "|.
   843  @^inner loop@>
   844  
   845  An overflow error is given, however, if the normal actions of |input_ln|
   846  would make |last>=buf_size|; this is done so that other parts of \MF\
   847  can safely look at the contents of |buffer[last+1]| without overstepping
   848  the bounds of the |buffer| array. Upon entry to |input_ln|, the condition
   849  |first<buf_size| will always hold, so that there is always room for an
   850  ``empty'' line.
   851  
   852  The variable |max_buf_stack|, which is used to keep track of how large
   853  the |buf_size| parameter must be to accommodate the present job, is
   854  also kept up to date by |input_ln|.
   855  
   856  If the |bypass_eoln| parameter is |true|, |input_ln| will do a |get|
   857  before looking at the first character of the line; this skips over
   858  an |eoln| that was in |f^|. The procedure does not do a |get| when it
   859  reaches the end of the line; therefore it can be used to acquire input
   860  from the user's terminal as well as from ordinary text files.
   861  
   862  Standard \PASCAL\ says that a file should have |eoln| immediately
   863  before |eof|, but \MF\ needs only a weaker restriction: If |eof|
   864  occurs in the middle of a line, the system function |eoln| should return
   865  a |true| result (even though |f^| will be undefined).
   866  
   867  @p function input_ln(var @!f:alpha_file;@!bypass_eoln:boolean):boolean;
   868    {inputs the next line or returns |false|}
   869  var @!last_nonblank:0..buf_size; {|last| with trailing blanks removed}
   870  begin if bypass_eoln then if not eof(f) then get(f);
   871    {input the first character of the line into |f^|}
   872  last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
   873  if eof(f) then input_ln:=false
   874  else  begin last_nonblank:=first;
   875    while not eoln(f) do
   876      begin if last>=max_buf_stack then
   877        begin max_buf_stack:=last+1;
   878        if max_buf_stack=buf_size then
   879          @<Report overflow of the input buffer, and abort@>;
   880        end;
   881      buffer[last]:=xord[f^]; get(f); incr(last);
   882      if buffer[last-1]<>" " then last_nonblank:=last;
   883      end;
   884    last:=last_nonblank; input_ln:=true;
   885    end;
   886  end;
   887  
   888  @ The user's terminal acts essentially like other files of text, except
   889  that it is used both for input and for output. When the terminal is
   890  considered an input file, the file variable is called |term_in|, and when it
   891  is considered an output file the file variable is |term_out|.
   892  @^system dependencies@>
   893  
   894  @<Glob...@>=
   895  @!term_in:alpha_file; {the terminal as an input file}
   896  @!term_out:alpha_file; {the terminal as an output file}
   897  
   898  @ Here is how to open the terminal files
   899  in \ph. The `\.{/I}' switch suppresses the first |get|.
   900  @:PASCAL H}{\ph@>
   901  @^system dependencies@>
   902  
   903  @d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
   904  @d t_open_out==rewrite(term_out,'TTY:','/O')
   905   {open the terminal for text output}
   906  
   907  @ Sometimes it is necessary to synchronize the input/output mixture that
   908  happens on the user's terminal, and three system-dependent
   909  procedures are used for this
   910  purpose. The first of these, |update_terminal|, is called when we want
   911  to make sure that everything we have output to the terminal so far has
   912  actually left the computer's internal buffers and been sent.
   913  The second, |clear_terminal|, is called when we wish to cancel any
   914  input that the user may have typed ahead (since we are about to
   915  issue an unexpected error message). The third, |wake_up_terminal|,
   916  is supposed to revive the terminal if the user has disabled it by
   917  some instruction to the operating system.  The following macros show how
   918  these operations can be specified in \ph:
   919  @:PASCAL H}{\ph@>
   920  @^system dependencies@>
   921  
   922  @d update_terminal == break(term_out) {empty the terminal output buffer}
   923  @d clear_terminal == break_in(term_in,true) {clear the terminal input buffer}
   924  @d wake_up_terminal == do_nothing {cancel the user's cancellation of output}
   925  
   926  @ We need a special routine to read the first line of \MF\ input from
   927  the user's terminal. This line is different because it is read before we
   928  have opened the transcript file; there is sort of a ``chicken and
   929  egg'' problem here. If the user types `\.{input cmr10}' on the first
   930  line, or if some macro invoked by that line does such an \.{input},
   931  the transcript file will be named `\.{cmr10.log}'; but if no \.{input}
   932  commands are performed during the first line of terminal input, the transcript
   933  file will acquire its default name `\.{mfput.log}'. (The transcript file
   934  will not contain error messages generated by the first line before the
   935  first \.{input} command.)
   936  @.mfput@>
   937  
   938  The first line is even more special if we are lucky enough to have an operating
   939  system that treats \MF\ differently from a run-of-the-mill \PASCAL\ object
   940  program. It's nice to let the user start running a \MF\ job by typing
   941  a command line like `\.{MF cmr10}'; in such a case, \MF\ will operate
   942  as if the first line of input were `\.{cmr10}', i.e., the first line will
   943  consist of the remainder of the command line, after the part that invoked \MF.
   944  
   945  The first line is special also because it may be read before \MF\ has
   946  input a base file. In such cases, normal error messages cannot yet
   947  be given. The following code uses concepts that will be explained later.
   948  (If the \PASCAL\ compiler does not support non-local |@!goto|\unskip, the
   949  @^system dependencies@>
   950  statement `|goto final_end|' should be replaced by something that
   951  quietly terminates the program.)
   952  
   953  @<Report overflow of the input buffer, and abort@>=
   954  if base_ident=0 then
   955    begin write_ln(term_out,'Buffer size exceeded!'); goto final_end;
   956  @.Buffer size exceeded@>
   957    end
   958  else begin cur_input.loc_field:=first; cur_input.limit_field:=last-1;
   959    overflow("buffer size",buf_size);
   960  @:METAFONT capacity exceeded buffer size}{\quad buffer size@>
   961    end
   962  
   963  @ Different systems have different ways to get started. But regardless of
   964  what conventions are adopted, the routine that initializes the terminal
   965  should satisfy the following specifications:
   966  
   967  \yskip\textindent{1)}It should open file |term_in| for input from the
   968    terminal. (The file |term_out| will already be open for output to the
   969    terminal.)
   970  
   971  \textindent{2)}If the user has given a command line, this line should be
   972    considered the first line of terminal input. Otherwise the
   973    user should be prompted with `\.{**}', and the first line of input
   974    should be whatever is typed in response.
   975  
   976  \textindent{3)}The first line of input, which might or might not be a
   977    command line, should appear in locations |first| to |last-1| of the
   978    |buffer| array.
   979  
   980  \textindent{4)}The global variable |loc| should be set so that the
   981    character to be read next by \MF\ is in |buffer[loc]|. This
   982    character should not be blank, and we should have |loc<last|.
   983  
   984  \yskip\noindent(It may be necessary to prompt the user several times
   985  before a non-blank line comes in. The prompt is `\.{**}' instead of the
   986  later `\.*' because the meaning is slightly different: `\.{input}' need
   987  not be typed immediately after~`\.{**}'.)
   988  
   989  @d loc==cur_input.loc_field {location of first unread character in |buffer|}
   990  
   991  @ The following program does the required initialization
   992  without retrieving a possible command line.
   993  It should be clear how to modify this routine to deal with command lines,
   994  if the system permits them.
   995  @^system dependencies@>
   996  
   997  @p function init_terminal:boolean; {gets the terminal input started}
   998  label exit;
   999  begin t_open_in;
  1000  loop@+begin wake_up_terminal; write(term_out,'**'); update_terminal;
  1001  @.**@>
  1002    if not input_ln(term_in,true) then {this shouldn't happen}
  1003      begin write_ln(term_out);
  1004      write(term_out,'! End of file on the terminal... why?');
  1005  @.End of file on the terminal@>
  1006      init_terminal:=false; return;
  1007      end;
  1008    loc:=first;
  1009    while (loc<last)and(buffer[loc]=" ") do incr(loc);
  1010    if loc<last then
  1011      begin init_terminal:=true;
  1012      return; {return unless the line was all blank}
  1013      end;
  1014    write_ln(term_out,'Please type the name of your input file.');
  1015    end;
  1016  exit:end;
  1017  
  1018  @* \[4] String handling.
  1019  Symbolic token names and diagnostic messages are variable-length strings
  1020  of eight-bit characters. Since \PASCAL\ does not have a well-developed string
  1021  mechanism, \MF\ does all of its string processing by homegrown methods.
  1022  
  1023  Elaborate facilities for dynamic strings are not needed, so all of the
  1024  necessary operations can be handled with a simple data structure.
  1025  The array |str_pool| contains all of the (eight-bit) ASCII codes in all
  1026  of the strings, and the array |str_start| contains indices of the starting
  1027  points of each string. Strings are referred to by integer numbers, so that
  1028  string number |s| comprises the characters |str_pool[j]| for
  1029  |str_start[s]<=j<str_start[s+1]|. Additional integer variables
  1030  |pool_ptr| and |str_ptr| indicate the number of entries used so far
  1031  in |str_pool| and |str_start|, respectively; locations
  1032  |str_pool[pool_ptr]| and |str_start[str_ptr]| are
  1033  ready for the next string to be allocated.
  1034  
  1035  String numbers 0 to 255 are reserved for strings that correspond to single
  1036  ASCII characters. This is in accordance with the conventions of \.{WEB},
  1037  @.WEB@>
  1038  which converts single-character strings into the ASCII code number of the
  1039  single character involved, while it converts other strings into integers
  1040  and builds a string pool file. Thus, when the string constant \.{"."} appears
  1041  in the program below, \.{WEB} converts it into the integer 46, which is the
  1042  ASCII code for a period, while \.{WEB} will convert a string like \.{"hello"}
  1043  into some integer greater than~255. String number 46 will presumably be the
  1044  single character `\..'\thinspace; but some ASCII codes have no standard visible
  1045  representation, and \MF\ may need to be able to print an arbitrary
  1046  ASCII character, so the first 256 strings are used to specify exactly what
  1047  should be printed for each of the 256 possibilities.
  1048  
  1049  Elements of the |str_pool| array must be ASCII codes that can actually be
  1050  printed; i.e., they must have an |xchr| equivalent in the local
  1051  character set. (This restriction applies only to preloaded strings,
  1052  not to those generated dynamically by the user.)
  1053  
  1054  Some \PASCAL\ compilers won't pack integers into a single byte unless the
  1055  integers lie in the range |-128..127|. To accommodate such systems
  1056  we access the string pool only via macros that can easily be redefined.
  1057  @^system dependencies@>
  1058  
  1059  @d si(#) == # {convert from |ASCII_code| to |packed_ASCII_code|}
  1060  @d so(#) == # {convert from |packed_ASCII_code| to |ASCII_code|}
  1061  
  1062  @<Types...@>=
  1063  @!pool_pointer = 0..pool_size; {for variables that point into |str_pool|}
  1064  @!str_number = 0..max_strings; {for variables that point into |str_start|}
  1065  @!packed_ASCII_code = 0..255; {elements of |str_pool| array}
  1066  
  1067  @ @<Glob...@>=
  1068  @!str_pool:packed array[pool_pointer] of packed_ASCII_code; {the characters}
  1069  @!str_start : array[str_number] of pool_pointer; {the starting pointers}
  1070  @!pool_ptr : pool_pointer; {first unused position in |str_pool|}
  1071  @!str_ptr : str_number; {number of the current string being created}
  1072  @!init_pool_ptr : pool_pointer; {the starting value of |pool_ptr|}
  1073  @!init_str_ptr : str_number; {the starting value of |str_ptr|}
  1074  @!max_pool_ptr : pool_pointer; {the maximum so far of |pool_ptr|}
  1075  @!max_str_ptr : str_number; {the maximum so far of |str_ptr|}
  1076  
  1077  @ Several of the elementary string operations are performed using \.{WEB}
  1078  macros instead of \PASCAL\ procedures, because many of the
  1079  operations are done quite frequently and we want to avoid the
  1080  overhead of procedure calls. For example, here is
  1081  a simple macro that computes the length of a string.
  1082  @.WEB@>
  1083  
  1084  @d length(#)==(str_start[#+1]-str_start[#]) {the number of characters
  1085    in string number \#}
  1086  
  1087  @ The length of the current string is called |cur_length|:
  1088  
  1089  @d cur_length == (pool_ptr - str_start[str_ptr])
  1090  
  1091  @ Strings are created by appending character codes to |str_pool|.
  1092  The |append_char| macro, defined here, does not check to see if the
  1093  value of |pool_ptr| has gotten too high; this test is supposed to be
  1094  made before |append_char| is used.
  1095  
  1096  To test if there is room to append |l| more characters to |str_pool|,
  1097  we shall write |str_room(l)|, which aborts \MF\ and gives an
  1098  apologetic error message if there isn't enough room.
  1099  
  1100  @d append_char(#) == {put |ASCII_code| \# at the end of |str_pool|}
  1101  begin str_pool[pool_ptr]:=si(#); incr(pool_ptr);
  1102  end
  1103  @d str_room(#) == {make sure that the pool hasn't overflowed}
  1104    begin if pool_ptr+# > max_pool_ptr then
  1105      begin if pool_ptr+# > pool_size then
  1106        overflow("pool size",pool_size-init_pool_ptr);
  1107  @:METAFONT capacity exceeded pool size}{\quad pool size@>
  1108      max_pool_ptr:=pool_ptr+#;
  1109      end;
  1110    end
  1111  
  1112  @ \MF's string expressions are implemented in a brute-force way: Every
  1113  new string or substring that is needed is simply copied into the string pool.
  1114  
  1115  Such a scheme can be justified because string expressions aren't a big
  1116  deal in \MF\ applications; strings rarely need to be saved from one
  1117  statement to the next. But it would waste space needlessly if we didn't
  1118  try to reclaim the space of strings that are going to be used only once.
  1119  
  1120  Therefore a simple reference count mechanism is provided: If there are
  1121  @^reference counts@>
  1122  no references to a certain string from elsewhere in the program, and
  1123  if there are no references to any strings created subsequent to it,
  1124  then the string space will be reclaimed.
  1125  
  1126  The number of references to string number |s| will be |str_ref[s]|. The
  1127  special value |str_ref[s]=max_str_ref=127| is used to denote an unknown
  1128  positive number of references; such strings will never be recycled. If
  1129  a string is ever referred to more than 126 times, simultaneously, we
  1130  put it in this category. Hence a single byte suffices to store each |str_ref|.
  1131  
  1132  @d max_str_ref=127 {``infinite'' number of references}
  1133  @d add_str_ref(#)==begin if str_ref[#]<max_str_ref then incr(str_ref[#]);
  1134    end
  1135  
  1136  @<Glob...@>=
  1137  @!str_ref:array[str_number] of 0..max_str_ref;
  1138  
  1139  @ Here's what we do when a string reference disappears:
  1140  
  1141  @d delete_str_ref(#)== begin if str_ref[#]<max_str_ref then
  1142      if str_ref[#]>1 then decr(str_ref[#])@+else flush_string(#);
  1143      end
  1144  
  1145  @<Declare the procedure called |flush_string|@>=
  1146  procedure flush_string(@!s:str_number);
  1147  begin if s<str_ptr-1 then str_ref[s]:=0
  1148  else  repeat decr(str_ptr);
  1149    until str_ref[str_ptr-1]<>0;
  1150  pool_ptr:=str_start[str_ptr];
  1151  end;
  1152  
  1153  @ Once a sequence of characters has been appended to |str_pool|, it
  1154  officially becomes a string when the function |make_string| is called.
  1155  This function returns the identification number of the new string as its
  1156  value.
  1157  
  1158  @p function make_string : str_number; {current string enters the pool}
  1159  begin if str_ptr=max_str_ptr then
  1160    begin if str_ptr=max_strings then
  1161      overflow("number of strings",max_strings-init_str_ptr);
  1162  @:METAFONT capacity exceeded number of strings}{\quad number of strings@>
  1163    incr(max_str_ptr);
  1164    end;
  1165  str_ref[str_ptr]:=1; incr(str_ptr); str_start[str_ptr]:=pool_ptr;
  1166  make_string:=str_ptr-1;
  1167  end;
  1168  
  1169  @ The following subroutine compares string |s| with another string of the
  1170  same length that appears in |buffer| starting at position |k|;
  1171  the result is |true| if and only if the strings are equal.
  1172  
  1173  @p function str_eq_buf(@!s:str_number;@!k:integer):boolean;
  1174    {test equality of strings}
  1175  label not_found; {loop exit}
  1176  var @!j: pool_pointer; {running index}
  1177  @!result: boolean; {result of comparison}
  1178  begin j:=str_start[s];
  1179  while j<str_start[s+1] do
  1180    begin if so(str_pool[j])<>buffer[k] then
  1181      begin result:=false; goto not_found;
  1182      end;
  1183    incr(j); incr(k);
  1184    end;
  1185  result:=true;
  1186  not_found: str_eq_buf:=result;
  1187  end;
  1188  
  1189  @ Here is a similar routine, but it compares two strings in the string pool,
  1190  and it does not assume that they have the same length. If the first string
  1191  is lexicographically greater than, less than, or equal to the second,
  1192  the result is respectively positive, negative, or zero.
  1193  
  1194  @p function str_vs_str(@!s,@!t:str_number):integer;
  1195    {test equality of strings}
  1196  label exit;
  1197  var @!j,@!k: pool_pointer; {running indices}
  1198  @!ls,@!lt:integer; {lengths}
  1199  @!l:integer; {length remaining to test}
  1200  begin ls:=length(s); lt:=length(t);
  1201  if ls<=lt then l:=ls@+else l:=lt;
  1202  j:=str_start[s]; k:=str_start[t];
  1203  while l>0 do
  1204    begin if str_pool[j]<>str_pool[k] then
  1205      begin str_vs_str:=str_pool[j]-str_pool[k]; return;
  1206      end;
  1207    incr(j); incr(k); decr(l);
  1208    end;
  1209  str_vs_str:=ls-lt;
  1210  exit:end;
  1211  
  1212  @ The initial values of |str_pool|, |str_start|, |pool_ptr|,
  1213  and |str_ptr| are computed by the \.{INIMF} program, based in part
  1214  on the information that \.{WEB} has output while processing \MF.
  1215  @.INIMF@>
  1216  @^string pool@>
  1217  
  1218  @p @!init function get_strings_started:boolean; {initializes the string pool,
  1219    but returns |false| if something goes wrong}
  1220  label done,exit;
  1221  var @!k,@!l:0..255; {small indices or counters}
  1222  @!m,@!n:text_char; {characters input from |pool_file|}
  1223  @!g:str_number; {the string just created}
  1224  @!a:integer; {accumulator for check sum}
  1225  @!c:boolean; {check sum has been checked}
  1226  begin pool_ptr:=0; str_ptr:=0; max_pool_ptr:=0; max_str_ptr:=0; str_start[0]:=0;
  1227  @<Make the first 256 strings@>;
  1228  @<Read the other strings from the \.{MF.POOL} file and return |true|,
  1229    or give an error message and return |false|@>;
  1230  exit:end;
  1231  tini
  1232  
  1233  @ @d app_lc_hex(#)==l:=#;
  1234    if l<10 then append_char(l+"0")@+else append_char(l-10+"a")
  1235  
  1236  @<Make the first 256...@>=
  1237  for k:=0 to 255 do
  1238    begin if (@<Character |k| cannot be printed@>) then
  1239      begin append_char("^"); append_char("^");
  1240      if k<@'100 then append_char(k+@'100)
  1241      else if k<@'200 then append_char(k-@'100)
  1242      else begin app_lc_hex(k div 16); app_lc_hex(k mod 16);
  1243        end;
  1244      end
  1245    else append_char(k);
  1246    g:=make_string; str_ref[g]:=max_str_ref;
  1247    end
  1248  
  1249  @ The first 128 strings will contain 95 standard ASCII characters, and the
  1250  other 33 characters will be printed in three-symbol form like `\.{\^\^A}'
  1251  unless a system-dependent change is made here. Installations that have
  1252  an extended character set, where for example |xchr[@'32]=@t\.{\'^^Z\'}@>|,
  1253  would like string @'32 to be the single character @'32 instead of the
  1254  three characters @'136, @'136, @'132 (\.{\^\^Z}). On the other hand,
  1255  even people with an extended character set will want to represent string
  1256  @'15 by \.{\^\^M}, since @'15 is ASCII's ``carriage return'' code; the idea is
  1257  to produce visible strings instead of tabs or line-feeds or carriage-returns
  1258  or bell-rings or characters that are treated anomalously in text files.
  1259  
  1260  Unprintable characters of codes 128--255 are, similarly, rendered
  1261  \.{\^\^80}--\.{\^\^ff}.
  1262  
  1263  The boolean expression defined here should be |true| unless \MF\ internal
  1264  code number~|k| corresponds to a non-troublesome visible symbol in the
  1265  local character set.
  1266  If character |k| cannot be printed, and |k<@'200|, then character |k+@'100| or
  1267  |k-@'100| must be printable; moreover, ASCII codes
  1268  |[@'60..@'71, @'136, @'141..@'146]|
  1269  must be printable.
  1270  @^character set dependencies@>
  1271  @^system dependencies@>
  1272  
  1273  @<Character |k| cannot be printed@>=
  1274    (k<" ")or(k>"~")
  1275  
  1276  @ When the \.{WEB} system program called \.{TANGLE} processes the \.{MF.WEB}
  1277  description that you are now reading, it outputs the \PASCAL\ program
  1278  \.{MF.PAS} and also a string pool file called \.{MF.POOL}. The \.{INIMF}
  1279  @.WEB@>@.INIMF@>
  1280  program reads the latter file, where each string appears as a two-digit decimal
  1281  length followed by the string itself, and the information is recorded in
  1282  \MF's string memory.
  1283  
  1284  @<Glob...@>=
  1285  @!init @!pool_file:alpha_file; {the string-pool file output by \.{TANGLE}}
  1286  tini
  1287  
  1288  @ @d bad_pool(#)==begin wake_up_terminal; write_ln(term_out,#);
  1289    a_close(pool_file); get_strings_started:=false; return;
  1290    end
  1291  @<Read the other strings...@>=
  1292  name_of_file:=pool_name; {we needn't set |name_length|}
  1293  if a_open_in(pool_file) then
  1294    begin c:=false;
  1295    repeat @<Read one string, but return |false| if the
  1296      string memory space is getting too tight for comfort@>;
  1297    until c;
  1298    a_close(pool_file); get_strings_started:=true;
  1299    end
  1300  else  bad_pool('! I can''t read MF.POOL.')
  1301  @.I can't read MF.POOL@>
  1302  
  1303  @ @<Read one string...@>=
  1304  begin if eof(pool_file) then bad_pool('! MF.POOL has no check sum.');
  1305  @.MF.POOL has no check sum@>
  1306  read(pool_file,m,n); {read two digits of string length}
  1307  if m='*' then @<Check the pool check sum@>
  1308  else  begin if (xord[m]<"0")or(xord[m]>"9")or@|
  1309        (xord[n]<"0")or(xord[n]>"9") then
  1310      bad_pool('! MF.POOL line doesn''t begin with two digits.');
  1311  @.MF.POOL line doesn't...@>
  1312    l:=xord[m]*10+xord[n]-"0"*11; {compute the length}
  1313    if pool_ptr+l+string_vacancies>pool_size then
  1314      bad_pool('! You have to increase POOLSIZE.');
  1315  @.You have to increase POOLSIZE@>
  1316    for k:=1 to l do
  1317      begin if eoln(pool_file) then m:=' '@+else read(pool_file,m);
  1318      append_char(xord[m]);
  1319      end;
  1320    read_ln(pool_file); g:=make_string; str_ref[g]:=max_str_ref;
  1321    end;
  1322  end
  1323  
  1324  @ The \.{WEB} operation \.{@@\$} denotes the value that should be at the
  1325  end of this \.{MF.POOL} file; any other value means that the wrong pool
  1326  file has been loaded.
  1327  @^check sum@>
  1328  
  1329  @<Check the pool check sum@>=
  1330  begin a:=0; k:=1;
  1331  loop@+  begin if (xord[n]<"0")or(xord[n]>"9") then
  1332    bad_pool('! MF.POOL check sum doesn''t have nine digits.');
  1333  @.MF.POOL check sum...@>
  1334    a:=10*a+xord[n]-"0";
  1335    if k=9 then goto done;
  1336    incr(k); read(pool_file,n);
  1337    end;
  1338  done: if a<>@$ then bad_pool('! MF.POOL doesn''t match; TANGLE me again.');
  1339  @.MF.POOL doesn't match@>
  1340  c:=true;
  1341  end
  1342  
  1343  @* \[5] On-line and off-line printing.
  1344  Messages that are sent to a user's terminal and to the transcript-log file
  1345  are produced by several `|print|' procedures. These procedures will
  1346  direct their output to a variety of places, based on the setting of
  1347  the global variable |selector|, which has the following possible
  1348  values:
  1349  
  1350  \yskip
  1351  \hang |term_and_log|, the normal setting, prints on the terminal and on the
  1352    transcript file.
  1353  
  1354  \hang |log_only|, prints only on the transcript file.
  1355  
  1356  \hang |term_only|, prints only on the terminal.
  1357  
  1358  \hang |no_print|, doesn't print at all. This is used only in rare cases
  1359    before the transcript file is open.
  1360  
  1361  \hang |pseudo|, puts output into a cyclic buffer that is used
  1362    by the |show_context| routine; when we get to that routine we shall discuss
  1363    the reasoning behind this curious mode.
  1364  
  1365  \hang |new_string|, appends the output to the current string in the
  1366    string pool.
  1367  
  1368  \yskip
  1369  \noindent The symbolic names `|term_and_log|', etc., have been assigned
  1370  numeric codes that satisfy the convenient relations |no_print+1=term_only|,
  1371  |no_print+2=log_only|, |term_only+2=log_only+1=term_and_log|.
  1372  
  1373  Three additional global variables, |tally| and |term_offset| and
  1374  |file_offset|, record the number of characters that have been printed
  1375  since they were most recently cleared to zero. We use |tally| to record
  1376  the length of (possibly very long) stretches of printing; |term_offset|
  1377  and |file_offset|, on the other hand, keep track of how many characters
  1378  have appeared so far on the current line that has been output to the
  1379  terminal or to the transcript file, respectively.
  1380  
  1381  @d no_print=0 {|selector| setting that makes data disappear}
  1382  @d term_only=1 {printing is destined for the terminal only}
  1383  @d log_only=2 {printing is destined for the transcript file only}
  1384  @d term_and_log=3 {normal |selector| setting}
  1385  @d pseudo=4 {special |selector| setting for |show_context|}
  1386  @d new_string=5 {printing is deflected to the string pool}
  1387  @d max_selector=5 {highest selector setting}
  1388  
  1389  @<Glob...@>=
  1390  @!log_file : alpha_file; {transcript of \MF\ session}
  1391  @!selector : 0..max_selector; {where to print a message}
  1392  @!dig : array[0..22] of 0..15; {digits in a number being output}
  1393  @!tally : integer; {the number of characters recently printed}
  1394  @!term_offset : 0..max_print_line;
  1395    {the number of characters on the current terminal line}
  1396  @!file_offset : 0..max_print_line;
  1397    {the number of characters on the current file line}
  1398  @!trick_buf:array[0..error_line] of ASCII_code; {circular buffer for
  1399    pseudoprinting}
  1400  @!trick_count: integer; {threshold for pseudoprinting, explained later}
  1401  @!first_count: integer; {another variable for pseudoprinting}
  1402  
  1403  @ @<Initialize the output routines@>=
  1404  selector:=term_only; tally:=0; term_offset:=0; file_offset:=0;
  1405  
  1406  @ Macro abbreviations for output to the terminal and to the log file are
  1407  defined here for convenience. Some systems need special conventions
  1408  for terminal output, and it is possible to adhere to those conventions
  1409  by changing |wterm|, |wterm_ln|, and |wterm_cr| here.
  1410  @^system dependencies@>
  1411  
  1412  @d wterm(#)==write(term_out,#)
  1413  @d wterm_ln(#)==write_ln(term_out,#)
  1414  @d wterm_cr==write_ln(term_out)
  1415  @d wlog(#)==write(log_file,#)
  1416  @d wlog_ln(#)==write_ln(log_file,#)
  1417  @d wlog_cr==write_ln(log_file)
  1418  
  1419  @ To end a line of text output, we call |print_ln|.
  1420  
  1421  @<Basic print...@>=
  1422  procedure print_ln; {prints an end-of-line}
  1423  begin case selector of
  1424  term_and_log: begin wterm_cr; wlog_cr;
  1425    term_offset:=0; file_offset:=0;
  1426    end;
  1427  log_only: begin wlog_cr; file_offset:=0;
  1428    end;
  1429  term_only: begin wterm_cr; term_offset:=0;
  1430    end;
  1431  no_print,pseudo,new_string: do_nothing;
  1432  end; {there are no other cases}
  1433  end; {note that |tally| is not affected}
  1434  
  1435  @ The |print_char| procedure sends one character to the desired destination,
  1436  using the |xchr| array to map it into an external character compatible with
  1437  |input_ln|. All printing comes through |print_ln| or |print_char|.
  1438  
  1439  @<Basic printing...@>=
  1440  procedure print_char(@!s:ASCII_code); {prints a single character}
  1441  begin case selector of
  1442  term_and_log: begin wterm(xchr[s]); wlog(xchr[s]);
  1443    incr(term_offset); incr(file_offset);
  1444    if term_offset=max_print_line then
  1445      begin wterm_cr; term_offset:=0;
  1446      end;
  1447    if file_offset=max_print_line then
  1448      begin wlog_cr; file_offset:=0;
  1449      end;
  1450    end;
  1451  log_only: begin wlog(xchr[s]); incr(file_offset);
  1452    if file_offset=max_print_line then print_ln;
  1453    end;
  1454  term_only: begin wterm(xchr[s]); incr(term_offset);
  1455    if term_offset=max_print_line then print_ln;
  1456    end;
  1457  no_print: do_nothing;
  1458  pseudo: if tally<trick_count then trick_buf[tally mod error_line]:=s;
  1459  new_string: begin if pool_ptr<pool_size then append_char(s);
  1460    end; {we drop characters if the string space is full}
  1461  end; {there are no other cases}
  1462  incr(tally);
  1463  end;
  1464  
  1465  @ An entire string is output by calling |print|. Note that if we are outputting
  1466  the single standard ASCII character \.c, we could call |print("c")|, since
  1467  |"c"=99| is the number of a single-character string, as explained above. But
  1468  |print_char("c")| is quicker, so \MF\ goes directly to the |print_char|
  1469  routine when it knows that this is safe. (The present implementation
  1470  assumes that it is always safe to print a visible ASCII character.)
  1471  @^system dependencies@>
  1472  
  1473  @<Basic print...@>=
  1474  procedure print(@!s:integer); {prints string |s|}
  1475  var @!j:pool_pointer; {current character code position}
  1476  begin if (s<0)or(s>=str_ptr) then s:="???"; {this can't happen}
  1477  @.???@>
  1478  if (s<256)and(selector>pseudo) then print_char(s)
  1479  else begin j:=str_start[s];
  1480    while j<str_start[s+1] do
  1481      begin print_char(so(str_pool[j])); incr(j);
  1482      end;
  1483    end;
  1484  end;
  1485  
  1486  @ Sometimes it's necessary to print a string whose characters
  1487  may not be visible ASCII codes. In that case |slow_print| is used.
  1488  
  1489  @<Basic print...@>=
  1490  procedure slow_print(@!s:integer); {prints string |s|}
  1491  var @!j:pool_pointer; {current character code position}
  1492  begin if (s<0)or(s>=str_ptr) then s:="???"; {this can't happen}
  1493  @.???@>
  1494  if (s<256)and(selector>pseudo) then print_char(s)
  1495  else begin j:=str_start[s];
  1496    while j<str_start[s+1] do
  1497      begin print(so(str_pool[j])); incr(j);
  1498      end;
  1499    end;
  1500  end;
  1501  
  1502  @ Here is the very first thing that \MF\ prints: a headline that identifies
  1503  the version number and base name. The |term_offset| variable is temporarily
  1504  incorrect, but the discrepancy is not serious since we assume that this
  1505  part of the program is system dependent.
  1506  @^system dependencies@>
  1507  
  1508  @<Initialize the output...@>=
  1509  wterm(banner);
  1510  if base_ident=0 then wterm_ln(' (no base preloaded)')
  1511  else  begin slow_print(base_ident); print_ln;
  1512    end;
  1513  update_terminal;
  1514  
  1515  @ The procedure |print_nl| is like |print|, but it makes sure that the
  1516  string appears at the beginning of a new line.
  1517  
  1518  @<Basic print...@>=
  1519  procedure print_nl(@!s:str_number); {prints string |s| at beginning of line}
  1520  begin if ((term_offset>0)and(odd(selector)))or@|
  1521    ((file_offset>0)and(selector>=log_only)) then print_ln;
  1522  print(s);
  1523  end;
  1524  
  1525  @ An array of digits in the range |0..9| is printed by |print_the_digs|.
  1526  
  1527  @<Basic print...@>=
  1528  procedure print_the_digs(@!k:eight_bits);
  1529    {prints |dig[k-1]|$\,\ldots\,$|dig[0]|}
  1530  begin while k>0 do
  1531    begin decr(k); print_char("0"+dig[k]);
  1532    end;
  1533  end;
  1534  
  1535  @ The following procedure, which prints out the decimal representation of a
  1536  given integer |n|, has been written carefully so that it works properly
  1537  if |n=0| or if |(-n)| would cause overflow. It does not apply |mod| or |div|
  1538  to negative arguments, since such operations are not implemented consistently
  1539  by all \PASCAL\ compilers.
  1540  
  1541  @<Basic print...@>=
  1542  procedure print_int(@!n:integer); {prints an integer in decimal form}
  1543  var k:0..23; {index to current digit; we assume that $\vert n\vert<10^{23}$}
  1544  @!m:integer; {used to negate |n| in possibly dangerous cases}
  1545  begin k:=0;
  1546  if n<0 then
  1547    begin print_char("-");
  1548    if n>-100000000 then negate(n)
  1549    else  begin m:=-1-n; n:=m div 10; m:=(m mod 10)+1; k:=1;
  1550      if m<10 then dig[0]:=m
  1551      else  begin dig[0]:=0; incr(n);
  1552        end;
  1553      end;
  1554    end;
  1555  repeat dig[k]:=n mod 10; n:=n div 10; incr(k);
  1556  until n=0;
  1557  print_the_digs(k);
  1558  end;
  1559  
  1560  @ \MF\ also makes use of a trivial procedure to print two digits. The
  1561  following subroutine is usually called with a parameter in the range |0<=n<=99|.
  1562  
  1563  @p procedure print_dd(@!n:integer); {prints two least significant digits}
  1564  begin n:=abs(n) mod 100; print_char("0"+(n div 10));
  1565  print_char("0"+(n mod 10));
  1566  end;
  1567  
  1568  @ Here is a procedure that asks the user to type a line of input,
  1569  assuming that the |selector| setting is either |term_only| or |term_and_log|.
  1570  The input is placed into locations |first| through |last-1| of the
  1571  |buffer| array, and echoed on the transcript file if appropriate.
  1572  
  1573  This procedure is never called when |interaction<scroll_mode|.
  1574  
  1575  @d prompt_input(#)==begin wake_up_terminal; print(#); term_input;
  1576      end {prints a string and gets a line of input}
  1577  
  1578  @p procedure term_input; {gets a line from the terminal}
  1579  var @!k:0..buf_size; {index into |buffer|}
  1580  begin update_terminal; {now the user sees the prompt for sure}
  1581  if not input_ln(term_in,true) then fatal_error("End of file on the terminal!");
  1582  @.End of file on the terminal@>
  1583  term_offset:=0; {the user's line ended with \<\rm return>}
  1584  decr(selector); {prepare to echo the input}
  1585  if last<>first then for k:=first to last-1 do print(buffer[k]);
  1586  print_ln; buffer[last]:="%"; incr(selector); {restore previous status}
  1587  end;
  1588  
  1589  @* \[6] Reporting errors.
  1590  When something anomalous is detected, \MF\ typically does something like this:
  1591  $$\vbox{\halign{#\hfil\cr
  1592  |print_err("Something anomalous has been detected");|\cr
  1593  |help3("This is the first line of my offer to help.")|\cr
  1594  |("This is the second line. I'm trying to")|\cr
  1595  |("explain the best way for you to proceed.");|\cr
  1596  |error;|\cr}}$$
  1597  A two-line help message would be given using |help2|, etc.; these informal
  1598  helps should use simple vocabulary that complements the words used in the
  1599  official error message that was printed. (Outside the U.S.A., the help
  1600  messages should preferably be translated into the local vernacular. Each
  1601  line of help is at most 60 characters long, in the present implementation,
  1602  so that |max_print_line| will not be exceeded.)
  1603  
  1604  The |print_err| procedure supplies a `\.!' before the official message,
  1605  and makes sure that the terminal is awake if a stop is going to occur.
  1606  The |error| procedure supplies a `\..' after the official message, then it
  1607  shows the location of the error; and if |interaction=error_stop_mode|,
  1608  it also enters into a dialog with the user, during which time the help
  1609  message may be printed.
  1610  @^system dependencies@>
  1611  
  1612  @ The global variable |interaction| has four settings, representing increasing
  1613  amounts of user interaction:
  1614  
  1615  @d batch_mode=0 {omits all stops and omits terminal output}
  1616  @d nonstop_mode=1 {omits all stops}
  1617  @d scroll_mode=2 {omits error stops}
  1618  @d error_stop_mode=3 {stops at every opportunity to interact}
  1619  @d print_err(#)==begin if interaction=error_stop_mode then wake_up_terminal;
  1620    print_nl("! "); print(#);
  1621  @.!\relax@>
  1622    end
  1623  
  1624  @<Glob...@>=
  1625  @!interaction:batch_mode..error_stop_mode; {current level of interaction}
  1626  
  1627  @ @<Set init...@>=interaction:=error_stop_mode;
  1628  
  1629  @ \MF\ is careful not to call |error| when the print |selector| setting
  1630  might be unusual. The only possible values of |selector| at the time of
  1631  error messages are
  1632  
  1633  \yskip\hang|no_print| (when |interaction=batch_mode|
  1634    and |log_file| not yet open);
  1635  
  1636  \hang|term_only| (when |interaction>batch_mode| and |log_file| not yet open);
  1637  
  1638  \hang|log_only| (when |interaction=batch_mode| and |log_file| is open);
  1639  
  1640  \hang|term_and_log| (when |interaction>batch_mode| and |log_file| is open).
  1641  
  1642  @<Initialize the print |selector| based on |interaction|@>=
  1643  if interaction=batch_mode then selector:=no_print@+else selector:=term_only
  1644  
  1645  @ A global variable |deletions_allowed| is set |false| if the |get_next|
  1646  routine is active when |error| is called; this ensures that |get_next|
  1647  will never be called recursively.
  1648  @^recursion@>
  1649  
  1650  The global variable |history| records the worst level of error that
  1651  has been detected. It has four possible values: |spotless|, |warning_issued|,
  1652  |error_message_issued|, and |fatal_error_stop|.
  1653  
  1654  Another global variable, |error_count|, is increased by one when an
  1655  |error| occurs without an interactive dialog, and it is reset to zero at
  1656  the end of every statement.  If |error_count| reaches 100, \MF\ decides
  1657  that there is no point in continuing further.
  1658  
  1659  @d spotless=0 {|history| value when nothing has been amiss yet}
  1660  @d warning_issued=1 {|history| value when |begin_diagnostic| has been called}
  1661  @d error_message_issued=2 {|history| value when |error| has been called}
  1662  @d fatal_error_stop=3 {|history| value when termination was premature}
  1663  
  1664  @<Glob...@>=
  1665  @!deletions_allowed:boolean; {is it safe for |error| to call |get_next|?}
  1666  @!history:spotless..fatal_error_stop; {has the source input been clean so far?}
  1667  @!error_count:-1..100; {the number of scrolled errors since the
  1668    last statement ended}
  1669  
  1670  @ The value of |history| is initially |fatal_error_stop|, but it will
  1671  be changed to |spotless| if \MF\ survives the initialization process.
  1672  
  1673  @<Set init...@>=
  1674  deletions_allowed:=true; error_count:=0; {|history| is initialized elsewhere}
  1675  
  1676  @ Since errors can be detected almost anywhere in \MF, we want to declare the
  1677  error procedures near the beginning of the program. But the error procedures
  1678  in turn use some other procedures, which need to be declared |forward|
  1679  before we get to |error| itself.
  1680  
  1681  It is possible for |error| to be called recursively if some error arises
  1682  when |get_next| is being used to delete a token, and/or if some fatal error
  1683  occurs while \MF\ is trying to fix a non-fatal one. But such recursion
  1684  @^recursion@>
  1685  is never more than two levels deep.
  1686  
  1687  @<Error handling...@>=
  1688  procedure@?normalize_selector; forward;@t\2@>@/
  1689  procedure@?get_next; forward;@t\2@>@/
  1690  procedure@?term_input; forward;@t\2@>@/
  1691  procedure@?show_context; forward;@t\2@>@/
  1692  procedure@?begin_file_reading; forward;@t\2@>@/
  1693  procedure@?open_log_file; forward;@t\2@>@/
  1694  procedure@?close_files_and_terminate; forward;@t\2@>@/
  1695  procedure@?clear_for_error_prompt; forward;@t\2@>@/
  1696  @t\4\hskip-\fontdimen2\font@>@;@+@!debug@+procedure@?debug_help;
  1697    forward;@;@+gubed@;@/
  1698  @t\4@>@<Declare the procedure called |flush_string|@>
  1699  
  1700  @ Individual lines of help are recorded in the array |help_line|, which
  1701  contains entries in positions |0..(help_ptr-1)|. They should be printed
  1702  in reverse order, i.e., with |help_line[0]| appearing last.
  1703  
  1704  @d hlp1(#)==help_line[0]:=#;@+end
  1705  @d hlp2(#)==help_line[1]:=#; hlp1
  1706  @d hlp3(#)==help_line[2]:=#; hlp2
  1707  @d hlp4(#)==help_line[3]:=#; hlp3
  1708  @d hlp5(#)==help_line[4]:=#; hlp4
  1709  @d hlp6(#)==help_line[5]:=#; hlp5
  1710  @d help0==help_ptr:=0 {sometimes there might be no help}
  1711  @d help1==@+begin help_ptr:=1; hlp1 {use this with one help line}
  1712  @d help2==@+begin help_ptr:=2; hlp2 {use this with two help lines}
  1713  @d help3==@+begin help_ptr:=3; hlp3 {use this with three help lines}
  1714  @d help4==@+begin help_ptr:=4; hlp4 {use this with four help lines}
  1715  @d help5==@+begin help_ptr:=5; hlp5 {use this with five help lines}
  1716  @d help6==@+begin help_ptr:=6; hlp6 {use this with six help lines}
  1717  
  1718  @<Glob...@>=
  1719  @!help_line:array[0..5] of str_number; {helps for the next |error|}
  1720  @!help_ptr:0..6; {the number of help lines present}
  1721  @!use_err_help:boolean; {should the |err_help| string be shown?}
  1722  @!err_help:str_number; {a string set up by \&{errhelp}}
  1723  
  1724  @ @<Set init...@>=
  1725  help_ptr:=0; use_err_help:=false; err_help:=0;
  1726  
  1727  @ The |jump_out| procedure just cuts across all active procedure levels and
  1728  goes to |end_of_MF|. This is the only nontrivial |@!goto| statement in the
  1729  whole program. It is used when there is no recovery from a particular error.
  1730  
  1731  Some \PASCAL\ compilers do not implement non-local |goto| statements.
  1732  @^system dependencies@>
  1733  In such cases the body of |jump_out| should simply be
  1734  `|close_files_and_terminate|;\thinspace' followed by a call on some system
  1735  procedure that quietly terminates the program.
  1736  
  1737  @<Error hand...@>=
  1738  procedure jump_out;
  1739  begin goto end_of_MF;
  1740  end;
  1741  
  1742  @ Here now is the general |error| routine.
  1743  
  1744  @<Error hand...@>=
  1745  procedure error; {completes the job of error reporting}
  1746  label continue,exit;
  1747  var @!c:ASCII_code; {what the user types}
  1748  @!s1,@!s2,@!s3:integer; {used to save global variables when deleting tokens}
  1749  @!j:pool_pointer; {character position being printed}
  1750  begin if history<error_message_issued then history:=error_message_issued;
  1751  print_char("."); show_context;
  1752  if interaction=error_stop_mode then @<Get user's advice and |return|@>;
  1753  incr(error_count);
  1754  if error_count=100 then
  1755    begin print_nl("(That makes 100 errors; please try again.)");
  1756  @.That makes 100 errors...@>
  1757    history:=fatal_error_stop; jump_out;
  1758    end;
  1759  @<Put help message on the transcript file@>;
  1760  exit:end;
  1761  
  1762  @ @<Get user's advice...@>=
  1763  loop@+begin continue: if interaction<>error_stop_mode then return;
  1764    clear_for_error_prompt; prompt_input("? ");
  1765  @.?\relax@>
  1766    if last=first then return;
  1767    c:=buffer[first];
  1768    if c>="a" then c:=c+"A"-"a"; {convert to uppercase}
  1769    @<Interpret code |c| and |return| if done@>;
  1770    end
  1771  
  1772  @ It is desirable to provide an `\.E' option here that gives the user
  1773  an easy way to return from \MF\ to the system editor, with the offending
  1774  line ready to be edited. But such an extension requires some system
  1775  wizardry, so the present implementation simply types out the name of the
  1776  file that should be
  1777  edited and the relevant line number.
  1778  @^system dependencies@>
  1779  
  1780  There is a secret `\.D' option available when the debugging routines haven't
  1781  been commented~out.
  1782  @^debugging@>
  1783  
  1784  @<Interpret code |c| and |return| if done@>=
  1785  case c of
  1786  "0","1","2","3","4","5","6","7","8","9": if deletions_allowed then
  1787    @<Delete |c-"0"| tokens and |goto continue|@>;
  1788  @t\4\4@>@;@+@!debug "D":begin debug_help;goto continue;@+end;@+gubed@/
  1789  "E": if file_ptr>0 then if input_stack[file_ptr].name_field>=256 then
  1790    begin print_nl("You want to edit file ");
  1791  @.You want to edit file x@>
  1792    slow_print(input_stack[file_ptr].name_field);
  1793    print(" at line "); print_int(line);@/
  1794    interaction:=scroll_mode; jump_out;
  1795    end;
  1796  "H": @<Print the help information and |goto continue|@>;
  1797  "I":@<Introduce new material from the terminal and |return|@>;
  1798  "Q","R","S":@<Change the interaction level and |return|@>;
  1799  "X":begin interaction:=scroll_mode; jump_out;
  1800    end;
  1801  othercases do_nothing
  1802  endcases;@/
  1803  @<Print the menu of available options@>
  1804  
  1805  @ @<Print the menu...@>=
  1806  begin print("Type <return> to proceed, S to scroll future error messages,");@/
  1807  @.Type <return> to proceed...@>
  1808  print_nl("R to run without stopping, Q to run quietly,");@/
  1809  print_nl("I to insert something, ");
  1810  if file_ptr>0 then if input_stack[file_ptr].name_field>=256 then
  1811    print("E to edit your file,");
  1812  if deletions_allowed then
  1813    print_nl("1 or ... or 9 to ignore the next 1 to 9 tokens of input,");
  1814  print_nl("H for help, X to quit.");
  1815  end
  1816  
  1817  @ Here the author of \MF\ apologizes for making use of the numerical
  1818  relation between |"Q"|, |"R"|, |"S"|, and the desired interaction settings
  1819  |batch_mode|, |nonstop_mode|, |scroll_mode|.
  1820  @^Knuth, Donald Ervin@>
  1821  
  1822  @<Change the interaction...@>=
  1823  begin error_count:=0; interaction:=batch_mode+c-"Q";
  1824  print("OK, entering ");
  1825  case c of
  1826  "Q":begin print("batchmode"); decr(selector);
  1827    end;
  1828  "R":print("nonstopmode");
  1829  "S":print("scrollmode");
  1830  end; {there are no other cases}
  1831  print("..."); print_ln; update_terminal; return;
  1832  end
  1833  
  1834  @ When the following code is executed, |buffer[(first+1)..(last-1)]| may
  1835  contain the material inserted by the user; otherwise another prompt will
  1836  be given. In order to understand this part of the program fully, you need
  1837  to be familiar with \MF's input stacks.
  1838  
  1839  @<Introduce new material...@>=
  1840  begin begin_file_reading; {enter a new syntactic level for terminal input}
  1841  if last>first+1 then
  1842    begin loc:=first+1; buffer[first]:=" ";
  1843    end
  1844  else  begin prompt_input("insert>"); loc:=first;
  1845  @.insert>@>
  1846    end;
  1847  first:=last+1; cur_input.limit_field:=last; return;
  1848  end
  1849  
  1850  @ We allow deletion of up to 99 tokens at a time.
  1851  
  1852  @<Delete |c-"0"| tokens...@>=
  1853  begin s1:=cur_cmd; s2:=cur_mod; s3:=cur_sym; OK_to_interrupt:=false;
  1854  if (last>first+1) and (buffer[first+1]>="0")and(buffer[first+1]<="9") then
  1855    c:=c*10+buffer[first+1]-"0"*11
  1856  else c:=c-"0";
  1857  while c>0 do
  1858    begin get_next; {one-level recursive call of |error| is possible}
  1859    @<Decrease the string reference count, if the current token is a string@>;
  1860    decr(c);
  1861    end;
  1862  cur_cmd:=s1; cur_mod:=s2; cur_sym:=s3; OK_to_interrupt:=true;
  1863  help2("I have just deleted some text, as you asked.")@/
  1864  ("You can now delete more, or insert, or whatever.");
  1865  show_context; goto continue;
  1866  end
  1867  
  1868  @ @<Print the help info...@>=
  1869  begin if use_err_help then
  1870    begin @<Print the string |err_help|, possibly on several lines@>;
  1871    use_err_help:=false;
  1872    end
  1873  else  begin if help_ptr=0 then
  1874      help2("Sorry, I don't know how to help in this situation.")@/
  1875      @t\kern1em@>("Maybe you should try asking a human?");
  1876    repeat decr(help_ptr); print(help_line[help_ptr]); print_ln;
  1877    until help_ptr=0;
  1878    end;
  1879  help4("Sorry, I already gave what help I could...")@/
  1880    ("Maybe you should try asking a human?")@/
  1881    ("An error might have occurred before I noticed any problems.")@/
  1882    ("``If all else fails, read the instructions.''");@/
  1883  goto continue;
  1884  end
  1885  
  1886  @ @<Print the string |err_help|, possibly on several lines@>=
  1887  j:=str_start[err_help];
  1888  while j<str_start[err_help+1] do
  1889    begin if str_pool[j]<>si("%") then print(so(str_pool[j]))
  1890    else if j+1=str_start[err_help+1] then print_ln
  1891    else if str_pool[j+1]<>si("%") then print_ln
  1892    else  begin incr(j); print_char("%");
  1893      end;
  1894    incr(j);
  1895    end
  1896  
  1897  @ @<Put help message on the transcript file@>=
  1898  if interaction>batch_mode then decr(selector); {avoid terminal output}
  1899  if use_err_help then
  1900    begin print_nl("");
  1901    @<Print the string |err_help|, possibly on several lines@>;
  1902    end
  1903  else while help_ptr>0 do
  1904    begin decr(help_ptr); print_nl(help_line[help_ptr]);
  1905    end;
  1906  print_ln;
  1907  if interaction>batch_mode then incr(selector); {re-enable terminal output}
  1908  print_ln
  1909  
  1910  @ In anomalous cases, the print selector might be in an unknown state;
  1911  the following subroutine is called to fix things just enough to keep
  1912  running a bit longer.
  1913  
  1914  @p procedure normalize_selector;
  1915  begin if log_opened then selector:=term_and_log
  1916  else selector:=term_only;
  1917  if job_name=0 then open_log_file;
  1918  if interaction=batch_mode then decr(selector);
  1919  end;
  1920  
  1921  @ The following procedure prints \MF's last words before dying.
  1922  
  1923  @d succumb==begin if interaction=error_stop_mode then
  1924      interaction:=scroll_mode; {no more interaction}
  1925    if log_opened then error;
  1926    @!debug if interaction>batch_mode then debug_help;@;@+gubed@;@/
  1927    history:=fatal_error_stop; jump_out; {irrecoverable error}
  1928    end
  1929  
  1930  @<Error hand...@>=
  1931  procedure fatal_error(@!s:str_number); {prints |s|, and that's it}
  1932  begin normalize_selector;@/
  1933  print_err("Emergency stop"); help1(s); succumb;
  1934  @.Emergency stop@>
  1935  end;
  1936  
  1937  @ Here is the most dreaded error message.
  1938  
  1939  @<Error hand...@>=
  1940  procedure overflow(@!s:str_number;@!n:integer); {stop due to finiteness}
  1941  begin normalize_selector;
  1942  print_err("METAFONT capacity exceeded, sorry [");
  1943  @.METAFONT capacity exceeded ...@>
  1944  print(s); print_char("="); print_int(n); print_char("]");
  1945  help2("If you really absolutely need more capacity,")@/
  1946    ("you can ask a wizard to enlarge me.");
  1947  succumb;
  1948  end;
  1949  
  1950  @ The program might sometime run completely amok, at which point there is
  1951  no choice but to stop. If no previous error has been detected, that's bad
  1952  news; a message is printed that is really intended for the \MF\
  1953  maintenance person instead of the user (unless the user has been
  1954  particularly diabolical).  The index entries for `this can't happen' may
  1955  help to pinpoint the problem.
  1956  @^dry rot@>
  1957  
  1958  @<Error hand...@>=
  1959  procedure confusion(@!s:str_number);
  1960    {consistency check violated; |s| tells where}
  1961  begin normalize_selector;
  1962  if history<error_message_issued then
  1963    begin print_err("This can't happen ("); print(s); print_char(")");
  1964  @.This can't happen@>
  1965    help1("I'm broken. Please show this to someone who can fix can fix");
  1966    end
  1967  else  begin print_err("I can't go on meeting you like this");
  1968  @.I can't go on...@>
  1969    help2("One of your faux pas seems to have wounded me deeply...")@/
  1970      ("in fact, I'm barely conscious. Please fix it and try again.");
  1971    end;
  1972  succumb;
  1973  end;
  1974  
  1975  @ Users occasionally want to interrupt \MF\ while it's running.
  1976  If the \PASCAL\ runtime system allows this, one can implement
  1977  a routine that sets the global variable |interrupt| to some nonzero value
  1978  when such an interrupt is signalled. Otherwise there is probably at least
  1979  a way to make |interrupt| nonzero using the \PASCAL\ debugger.
  1980  @^system dependencies@>
  1981  @^debugging@>
  1982  
  1983  @d check_interrupt==begin if interrupt<>0 then pause_for_instructions;
  1984    end
  1985  
  1986  @<Global...@>=
  1987  @!interrupt:integer; {should \MF\ pause for instructions?}
  1988  @!OK_to_interrupt:boolean; {should interrupts be observed?}
  1989  
  1990  @ @<Set init...@>=
  1991  interrupt:=0; OK_to_interrupt:=true;
  1992  
  1993  @ When an interrupt has been detected, the program goes into its
  1994  highest interaction level and lets the user have the full flexibility of
  1995  the |error| routine.  \MF\ checks for interrupts only at times when it is
  1996  safe to do this.
  1997  
  1998  @p procedure pause_for_instructions;
  1999  begin if OK_to_interrupt then
  2000    begin interaction:=error_stop_mode;
  2001    if (selector=log_only)or(selector=no_print) then
  2002      incr(selector);
  2003    print_err("Interruption");
  2004  @.Interruption@>
  2005    help3("You rang?")@/
  2006    ("Try to insert an instruction for me (e.g., `I show x;'),")@/
  2007    ("unless you just want to quit by typing `X'.");
  2008    deletions_allowed:=false; error; deletions_allowed:=true;
  2009    interrupt:=0;
  2010    end;
  2011  end;
  2012  
  2013  @ Many of \MF's error messages state that a missing token has been
  2014  inserted behind the scenes. We can save string space and program space
  2015  by putting this common code into a subroutine.
  2016  
  2017  @p procedure missing_err(@!s:str_number);
  2018  begin print_err("Missing `"); print(s); print("' has been inserted");
  2019  @.Missing...inserted@>
  2020  end;
  2021  
  2022  @* \[7] Arithmetic with scaled numbers.
  2023  The principal computations performed by \MF\ are done entirely in terms of
  2024  integers less than $2^{31}$ in magnitude; thus, the arithmetic specified in this
  2025  program can be carried out in exactly the same way on a wide variety of
  2026  computers, including some small ones.
  2027  @^small computers@>
  2028  
  2029  But \PASCAL\ does not define the @!|div|
  2030  operation in the case of negative dividends; for example, the result of
  2031  |(-2*n-1) div 2| is |-(n+1)| on some computers and |-n| on others.
  2032  There are two principal types of arithmetic: ``translation-preserving,''
  2033  in which the identity |(a+q*b)div b=(a div b)+q| is valid; and
  2034  ``negation-preserving,'' in which |(-a)div b=-(a div b)|. This leads to
  2035  two \MF s, which can produce different results, although the differences
  2036  should be negligible when the language is being used properly.
  2037  The \TeX\ processor has been defined carefully so that both varieties
  2038  of arithmetic will produce identical output, but it would be too
  2039  inefficient to constrain \MF\ in a similar way.
  2040  
  2041  @d el_gordo == @'17777777777 {$2^{31}-1$, the largest value that \MF\ likes}
  2042  
  2043  @ One of \MF's most common operations is the calculation of
  2044  $\lfloor{a+b\over2}\rfloor$,
  2045  the midpoint of two given integers |a| and~|b|. The only decent way to do
  2046  this in \PASCAL\ is to write `|(a+b) div 2|'; but on most machines it is
  2047  far more efficient to calculate `|(a+b)| right shifted one bit'.
  2048  
  2049  Therefore the midpoint operation will always be denoted by `|half(a+b)|'
  2050  in this program. If \MF\ is being implemented with languages that permit
  2051  binary shifting, the |half| macro should be changed to make this operation
  2052  as efficient as possible.
  2053  
  2054  @d half(#)==(#) div 2
  2055  
  2056  @ A single computation might use several subroutine calls, and it is
  2057  desirable to avoid producing multiple error messages in case of arithmetic
  2058  overflow. So the routines below set the global variable |arith_error| to |true|
  2059  instead of reporting errors directly to the user.
  2060  @^overflow in arithmetic@>
  2061  
  2062  @<Glob...@>=
  2063  @!arith_error:boolean; {has arithmetic overflow occurred recently?}
  2064  
  2065  @ @<Set init...@>=
  2066  arith_error:=false;
  2067  
  2068  @ At crucial points the program will say |check_arith|, to test if
  2069  an arithmetic error has been detected.
  2070  
  2071  @d check_arith==begin if arith_error then clear_arith;@+end
  2072  
  2073  @p procedure clear_arith;
  2074  begin print_err("Arithmetic overflow");
  2075  @.Arithmetic overflow@>
  2076  help4("Uh, oh. A little while ago one of the quantities that I was")@/
  2077    ("computing got too large, so I'm afraid your answers will be")@/
  2078    ("somewhat askew. You'll probably have to adopt different")@/
  2079    ("tactics next time. But I shall try to carry on anyway.");
  2080  error; arith_error:=false;
  2081  end;
  2082  
  2083  @ Addition is not always checked to make sure that it doesn't overflow,
  2084  but in places where overflow isn't too unlikely the |slow_add| routine
  2085  is used.
  2086  
  2087  @p function slow_add(@!x,@!y:integer):integer;
  2088  begin if x>=0 then
  2089    if y<=el_gordo-x then slow_add:=x+y
  2090    else  begin arith_error:=true; slow_add:=el_gordo;
  2091      end
  2092  else  if -y<=el_gordo+x then slow_add:=x+y
  2093    else  begin arith_error:=true; slow_add:=-el_gordo;
  2094      end;
  2095  end;
  2096  
  2097  @ Fixed-point arithmetic is done on {\sl scaled integers\/} that are multiples
  2098  of $2^{-16}$. In other words, a binary point is assumed to be sixteen bit
  2099  positions from the right end of a binary computer word.
  2100  
  2101  @d quarter_unit == @'40000 {$2^{14}$, represents 0.250000}
  2102  @d half_unit == @'100000 {$2^{15}$, represents 0.50000}
  2103  @d three_quarter_unit == @'140000 {$3\cdot2^{14}$, represents 0.75000}
  2104  @d unity == @'200000 {$2^{16}$, represents 1.00000}
  2105  @d two == @'400000 {$2^{17}$, represents 2.00000}
  2106  @d three == @'600000 {$2^{17}+2^{16}$, represents 3.00000}
  2107  
  2108  @<Types...@>=
  2109  @!scaled = integer; {this type is used for scaled integers}
  2110  @!small_number=0..63; {this type is self-explanatory}
  2111  
  2112  @ The following function is used to create a scaled integer from a given decimal
  2113  fraction $(.d_0d_1\ldots d_{k-1})$, where |0<=k<=17|. The digit $d_i$ is
  2114  given in |dig[i]|, and the calculation produces a correctly rounded result.
  2115  
  2116  @p function round_decimals(@!k:small_number) : scaled;
  2117    {converts a decimal fraction}
  2118  var @!a:integer; {the accumulator}
  2119  begin a:=0;
  2120  while k>0 do
  2121    begin decr(k); a:=(a+dig[k]*two) div 10;
  2122    end;
  2123  round_decimals:=half(a+1);
  2124  end;
  2125  
  2126  @ Conversely, here is a procedure analogous to |print_int|. If the output
  2127  of this procedure is subsequently read by \MF\ and converted by the
  2128  |round_decimals| routine above, it turns out that the original value will
  2129  be reproduced exactly. A decimal point is printed only if the value is
  2130  not an integer. If there is more than one way to print the result with
  2131  the optimum number of digits following the decimal point, the closest
  2132  possible value is given.
  2133  
  2134  The invariant relation in the \&{repeat} loop is that a sequence of
  2135  decimal digits yet to be printed will yield the original number if and only if
  2136  they form a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$.
  2137  We can stop if and only if $f=0$ satisfies this condition; the loop will
  2138  terminate before $s$ can possibly become zero.
  2139  
  2140  @<Basic printing...@>=
  2141  procedure print_scaled(@!s:scaled); {prints scaled real, rounded to five
  2142    digits}
  2143  var @!delta:scaled; {amount of allowable inaccuracy}
  2144  begin if s<0 then
  2145    begin print_char("-"); negate(s); {print the sign, if negative}
  2146    end;
  2147  print_int(s div unity); {print the integer part}
  2148  s:=10*(s mod unity)+5;
  2149  if s<>5 then
  2150    begin delta:=10; print_char(".");
  2151    repeat if delta>unity then
  2152      s:=s+@'100000-(delta div 2); {round the final digit}
  2153    print_char("0"+(s div unity)); s:=10*(s mod unity); delta:=delta*10;
  2154    until s<=delta;
  2155    end;
  2156  end;
  2157  
  2158  @ We often want to print two scaled quantities in parentheses,
  2159  separated by a comma.
  2160  
  2161  @<Basic printing...@>=
  2162  procedure print_two(@!x,@!y:scaled); {prints `|(x,y)|'}
  2163  begin print_char("("); print_scaled(x); print_char(","); print_scaled(y);
  2164  print_char(")");
  2165  end;
  2166  
  2167  @ The |scaled| quantities in \MF\ programs are generally supposed to be
  2168  less than $2^{12}$ in absolute value, so \MF\ does much of its internal
  2169  arithmetic with 28~significant bits of precision. A |fraction| denotes
  2170  a scaled integer whose binary point is assumed to be 28 bit positions
  2171  from the right.
  2172  
  2173  @d fraction_half==@'1000000000 {$2^{27}$, represents 0.50000000}
  2174  @d fraction_one==@'2000000000 {$2^{28}$, represents 1.00000000}
  2175  @d fraction_two==@'4000000000 {$2^{29}$, represents 2.00000000}
  2176  @d fraction_three==@'6000000000 {$3\cdot2^{28}$, represents 3.00000000}
  2177  @d fraction_four==@'10000000000 {$2^{30}$, represents 4.00000000}
  2178  
  2179  @<Types...@>=
  2180  @!fraction=integer; {this type is used for scaled fractions}
  2181  
  2182  @ In fact, the two sorts of scaling discussed above aren't quite
  2183  sufficient; \MF\ has yet another, used internally to keep track of angles
  2184  in units of $2^{-20}$ degrees.
  2185  
  2186  @d forty_five_deg==@'264000000 {$45\cdot2^{20}$, represents $45^\circ$}
  2187  @d ninety_deg==@'550000000 {$90\cdot2^{20}$, represents $90^\circ$}
  2188  @d one_eighty_deg==@'1320000000 {$180\cdot2^{20}$, represents $180^\circ$}
  2189  @d three_sixty_deg==@'2640000000 {$360\cdot2^{20}$, represents $360^\circ$}
  2190  
  2191  @<Types...@>=
  2192  @!angle=integer; {this type is used for scaled angles}
  2193  
  2194  @ The |make_fraction| routine produces the |fraction| equivalent of
  2195  |p/q|, given integers |p| and~|q|; it computes the integer
  2196  $f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are
  2197  positive. If |p| and |q| are both of the same scaled type |t|,
  2198  the ``type relation'' |make_fraction(t,t)=fraction| is valid;
  2199  and it's also possible to use the subroutine ``backwards,'' using
  2200  the relation |make_fraction(t,fraction)=t| between scaled types.
  2201  
  2202  If the result would have magnitude $2^{31}$ or more, |make_fraction|
  2203  sets |arith_error:=true|. Most of \MF's internal computations have
  2204  been designed to avoid this sort of error.
  2205  
  2206  Notice that if 64-bit integer arithmetic were available,
  2207  we could simply compute |@t$(2^{29}$@>*p+q)div (2*q)|.
  2208  But when we are restricted to \PASCAL's 32-bit arithmetic we
  2209  must either resort to multiple-precision maneuvering
  2210  or use a simple but slow iteration. The multiple-precision technique
  2211  would be about three times faster than the code adopted here, but it
  2212  would be comparatively long and tricky, involving about sixteen
  2213  additional multiplications and divisions.
  2214  
  2215  This operation is part of \MF's ``inner loop''; indeed, it will
  2216  consume nearly 10\pct! of the running time (exclusive of input and output)
  2217  if the code below is left unchanged. A machine-dependent recoding
  2218  will therefore make \MF\ run faster. The present implementation
  2219  is highly portable, but slow; it avoids multiplication and division
  2220  except in the initial stage. System wizards should be careful to
  2221  replace it with a routine that is guaranteed to produce identical
  2222  results in all cases.
  2223  @^system dependencies@>
  2224  
  2225  As noted below, a few more routines should also be replaced by machine-dependent
  2226  code, for efficiency. But when a procedure is not part of the ``inner loop,''
  2227  such changes aren't advisable; simplicity and robustness are
  2228  preferable to trickery, unless the cost is too high.
  2229  @^inner loop@>
  2230  
  2231  @p function make_fraction(@!p,@!q:integer):fraction;
  2232  var @!f:integer; {the fraction bits, with a leading 1 bit}
  2233  @!n:integer; {the integer part of $\vert p/q\vert$}
  2234  @!negative:boolean; {should the result be negated?}
  2235  @!be_careful:integer; {disables certain compiler optimizations}
  2236  begin if p>=0 then negative:=false
  2237  else  begin negate(p); negative:=true;
  2238    end;
  2239  if q<=0 then
  2240    begin debug if q=0 then confusion("/");@;@+gubed@;@/
  2241  @:this can't happen /}{\quad \./@>
  2242    negate(q); negative:=not negative;
  2243    end;
  2244  n:=p div q; p:=p mod q;
  2245  if n>=8 then
  2246    begin arith_error:=true;
  2247    if negative then make_fraction:=-el_gordo@+else make_fraction:=el_gordo;
  2248    end
  2249  else  begin n:=(n-1)*fraction_one;
  2250    @<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>;
  2251    if negative then make_fraction:=-(f+n)@+else make_fraction:=f+n;
  2252    end;
  2253  end;
  2254  
  2255  @ The |repeat| loop here preserves the following invariant relations
  2256  between |f|, |p|, and~|q|:
  2257  (i)~|0<=p<q|; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an integer and
  2258  $p_0$ is the original value of~$p$.
  2259  
  2260  Notice that the computation specifies
  2261  |(p-q)+p| instead of |(p+p)-q|, because the latter could overflow.
  2262  Let us hope that optimizing compilers do not miss this point; a
  2263  special variable |be_careful| is used to emphasize the necessary
  2264  order of computation. Optimizing compilers should keep |be_careful|
  2265  in a register, not store it in memory.
  2266  @^inner loop@>
  2267  
  2268  @<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>=
  2269  f:=1;
  2270  repeat be_careful:=p-q; p:=be_careful+p;
  2271  if p>=0 then f:=f+f+1
  2272  else  begin double(f); p:=p+q;
  2273    end;
  2274  until f>=fraction_one;
  2275  be_careful:=p-q;
  2276  if be_careful+p>=0 then incr(f)
  2277  
  2278  @ The dual of |make_fraction| is |take_fraction|, which multiplies a
  2279  given integer~|q| by a fraction~|f|. When the operands are positive, it
  2280  computes $p=\lfloor qf/2^{28}+{1\over2}\rfloor$, a symmetric function
  2281  of |q| and~|f|.
  2282  
  2283  This routine is even more ``inner loopy'' than |make_fraction|;
  2284  the present implementation consumes almost 20\pct! of \MF's computation
  2285  time during typical jobs, so a machine-language or 64-bit
  2286  substitute is advisable.
  2287  @^inner loop@> @^system dependencies@>
  2288  
  2289  @p function take_fraction(@!q:integer;@!f:fraction):integer;
  2290  var @!p:integer; {the fraction so far}
  2291  @!negative:boolean; {should the result be negated?}
  2292  @!n:integer; {additional multiple of $q$}
  2293  @!be_careful:integer; {disables certain compiler optimizations}
  2294  begin @<Reduce to the case that |f>=0| and |q>=0|@>;
  2295  if f<fraction_one then n:=0
  2296  else  begin n:=f div fraction_one; f:=f mod fraction_one;
  2297    if q<=el_gordo div n then n:=n*q
  2298    else  begin arith_error:=true; n:=el_gordo;
  2299      end;
  2300    end;
  2301  f:=f+fraction_one;
  2302  @<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>;
  2303  be_careful:=n-el_gordo;
  2304  if be_careful+p>0 then
  2305    begin arith_error:=true; n:=el_gordo-p;
  2306    end;
  2307  if negative then take_fraction:=-(n+p)
  2308  else take_fraction:=n+p;
  2309  end;
  2310  
  2311  @ @<Reduce to the case that |f>=0| and |q>=0|@>=
  2312  if f>=0 then negative:=false
  2313  else  begin negate(f); negative:=true;
  2314    end;
  2315  if q<0 then
  2316    begin negate(q); negative:=not negative;
  2317    end;
  2318  
  2319  @ The invariant relations in this case are (i)~$\lfloor(qf+p)/2^k\rfloor
  2320  =\lfloor qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and
  2321  $f_0$ is the original value of~$f$; (ii)~$2^k\L f<2^{k+1}$.
  2322  @^inner loop@>
  2323  
  2324  @<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>=
  2325  p:=fraction_half; {that's $2^{27}$; the invariants hold now with $k=28$}
  2326  if q<fraction_four then
  2327    repeat if odd(f) then p:=half(p+q)@+else p:=half(p);
  2328    f:=half(f);
  2329    until f=1
  2330  else  repeat if odd(f) then p:=p+half(q-p)@+else p:=half(p);
  2331    f:=half(f);
  2332    until f=1
  2333  
  2334  
  2335  @ When we want to multiply something by a |scaled| quantity, we use a scheme
  2336  analogous to |take_fraction| but with a different scaling.
  2337  Given positive operands, |take_scaled|
  2338  computes the quantity $p=\lfloor qf/2^{16}+{1\over2}\rfloor$.
  2339  
  2340  Once again it is a good idea to use 64-bit arithmetic if
  2341  possible; otherwise |take_scaled| will use more than 2\pct! of the running time
  2342  when the Computer Modern fonts are being generated.
  2343  @^inner loop@>
  2344  
  2345  @p function take_scaled(@!q:integer;@!f:scaled):integer;
  2346  var @!p:integer; {the fraction so far}
  2347  @!negative:boolean; {should the result be negated?}
  2348  @!n:integer; {additional multiple of $q$}
  2349  @!be_careful:integer; {disables certain compiler optimizations}
  2350  begin @<Reduce to the case that |f>=0| and |q>=0|@>;
  2351  if f<unity then n:=0
  2352  else  begin n:=f div unity; f:=f mod unity;
  2353    if q<=el_gordo div n then n:=n*q
  2354    else  begin arith_error:=true; n:=el_gordo;
  2355      end;
  2356    end;
  2357  f:=f+unity;
  2358  @<Compute $p=\lfloor qf/2^{16}+{1\over2}\rfloor-q$@>;
  2359  be_careful:=n-el_gordo;
  2360  if be_careful+p>0 then
  2361    begin arith_error:=true; n:=el_gordo-p;
  2362    end;
  2363  if negative then take_scaled:=-(n+p)
  2364  else take_scaled:=n+p;
  2365  end;
  2366  
  2367  @ @<Compute $p=\lfloor qf/2^{16}+{1\over2}\rfloor-q$@>=
  2368  p:=half_unit; {that's $2^{15}$; the invariants hold now with $k=16$}
  2369  @^inner loop@>
  2370  if q<fraction_four then
  2371    repeat if odd(f) then p:=half(p+q)@+else p:=half(p);
  2372    f:=half(f);
  2373    until f=1
  2374  else  repeat if odd(f) then p:=p+half(q-p)@+else p:=half(p);
  2375    f:=half(f);
  2376    until f=1
  2377  
  2378  @ For completeness, there's also |make_scaled|, which computes a
  2379  quotient as a |scaled| number instead of as a |fraction|.
  2380  In other words, the result is $\lfloor2^{16}p/q+{1\over2}\rfloor$, if the
  2381  operands are positive. \ (This procedure is not used especially often,
  2382  so it is not part of \MF's inner loop.)
  2383  
  2384  @p function make_scaled(@!p,@!q:integer):scaled;
  2385  var @!f:integer; {the fraction bits, with a leading 1 bit}
  2386  @!n:integer; {the integer part of $\vert p/q\vert$}
  2387  @!negative:boolean; {should the result be negated?}
  2388  @!be_careful:integer; {disables certain compiler optimizations}
  2389  begin if p>=0 then negative:=false
  2390  else  begin negate(p); negative:=true;
  2391    end;
  2392  if q<=0 then
  2393    begin debug if q=0 then confusion("/");@+gubed@;@/
  2394  @:this can't happen /}{\quad \./@>
  2395    negate(q); negative:=not negative;
  2396    end;
  2397  n:=p div q; p:=p mod q;
  2398  if n>=@'100000 then
  2399    begin arith_error:=true;
  2400    if negative then make_scaled:=-el_gordo@+else make_scaled:=el_gordo;
  2401    end
  2402  else  begin n:=(n-1)*unity;
  2403    @<Compute $f=\lfloor 2^{16}(1+p/q)+{1\over2}\rfloor$@>;
  2404    if negative then make_scaled:=-(f+n)@+else make_scaled:=f+n;
  2405    end;
  2406  end;
  2407  
  2408  @ @<Compute $f=\lfloor 2^{16}(1+p/q)+{1\over2}\rfloor$@>=
  2409  f:=1;
  2410  repeat be_careful:=p-q; p:=be_careful+p;
  2411  if p>=0 then f:=f+f+1
  2412  else  begin double(f); p:=p+q;
  2413    end;
  2414  until f>=unity;
  2415  be_careful:=p-q;
  2416  if be_careful+p>=0 then incr(f)
  2417  
  2418  @ Here is a typical example of how the routines above can be used.
  2419  It computes the function
  2420  $${1\over3\tau}f(\theta,\phi)=
  2421  {\tau^{-1}\bigl(2+\sqrt2\,(\sin\theta-{1\over16}\sin\phi)
  2422   (\sin\phi-{1\over16}\sin\theta)(\cos\theta-\cos\phi)\bigr)\over
  2423  3\,\bigl(1+{1\over2}(\sqrt5-1)\cos\theta+{1\over2}(3-\sqrt5\,)\cos\phi\bigr)},$$
  2424  where $\tau$ is a |scaled| ``tension'' parameter. This is \MF's magic
  2425  fudge factor for placing the first control point of a curve that starts
  2426  at an angle $\theta$ and ends at an angle $\phi$ from the straight path.
  2427  (Actually, if the stated quantity exceeds 4, \MF\ reduces it to~4.)
  2428  
  2429  The trigonometric quantity to be multiplied by $\sqrt2$ is less than $\sqrt2$.
  2430  (It's a sum of eight terms whose absolute values can be bounded using
  2431  relations such as $\sin\theta\cos\theta\L{1\over2}$.) Thus the numerator
  2432  is positive; and since the tension $\tau$ is constrained to be at least
  2433  $3\over4$, the numerator is less than $16\over3$. The denominator is
  2434  nonnegative and at most~6.  Hence the fixed-point calculations below
  2435  are guaranteed to stay within the bounds of a 32-bit computer word.
  2436  
  2437  The angles $\theta$ and $\phi$ are given implicitly in terms of |fraction|
  2438  arguments |st|, |ct|, |sf|, and |cf|, representing $\sin\theta$, $\cos\theta$,
  2439  $\sin\phi$, and $\cos\phi$, respectively.
  2440  
  2441  @p function velocity(@!st,@!ct,@!sf,@!cf:fraction;@!t:scaled):fraction;
  2442  var @!acc,@!num,@!denom:integer; {registers for intermediate calculations}
  2443  begin acc:=take_fraction(st-(sf div 16), sf-(st div 16));
  2444  acc:=take_fraction(acc,ct-cf);
  2445  num:=fraction_two+take_fraction(acc,379625062);
  2446    {$2^{28}\sqrt2\approx379625062.497$}
  2447  denom:=fraction_three+take_fraction(ct,497706707)+take_fraction(cf,307599661);
  2448    {$3\cdot2^{27}\cdot(\sqrt5-1)\approx497706706.78$ and
  2449      $3\cdot2^{27}\cdot(3-\sqrt5\,)\approx307599661.22$}
  2450  if t<>unity then num:=make_scaled(num,t);
  2451    {|make_scaled(fraction,scaled)=fraction|}
  2452  if num div 4>=denom then velocity:=fraction_four
  2453  else velocity:=make_fraction(num,denom);
  2454  end;
  2455  
  2456  @ The following somewhat different subroutine tests rigorously if $ab$ is
  2457  greater than, equal to, or less than~$cd$,
  2458  given integers $(a,b,c,d)$. In most cases a quick decision is reached.
  2459  The result is $+1$, 0, or~$-1$ in the three respective cases.
  2460  
  2461  @d return_sign(#)==begin ab_vs_cd:=#; return;
  2462    end
  2463  
  2464  @p function ab_vs_cd(@!a,b,c,d:integer):integer;
  2465  label exit;
  2466  var @!q,@!r:integer; {temporary registers}
  2467  begin @<Reduce to the case that |a,c>=0|, |b,d>0|@>;
  2468  loop@+  begin q := a div d; r := c div b;
  2469    if q<>r then
  2470      if q>r then return_sign(1)@+else return_sign(-1);
  2471    q := a mod d; r := c mod b;
  2472    if r=0 then
  2473      if q=0 then return_sign(0)@+else return_sign(1);
  2474    if q=0 then return_sign(-1);
  2475    a:=b; b:=q; c:=d; d:=r;
  2476    end; {now |a>d>0| and |c>b>0|}
  2477  exit:end;
  2478  
  2479  @ @<Reduce to the case that |a...@>=
  2480  if a<0 then
  2481    begin negate(a); negate(b);
  2482    end;
  2483  if c<0 then
  2484    begin negate(c); negate(d);
  2485    end;
  2486  if d<=0 then
  2487    begin if b>=0 then
  2488      if ((a=0)or(b=0))and((c=0)or(d=0)) then return_sign(0)
  2489      else return_sign(1);
  2490    if d=0 then
  2491      if a=0 then return_sign(0)@+else return_sign(-1);
  2492    q:=a; a:=c; c:=q; q:=-b; b:=-d; d:=q;
  2493    end
  2494  else if b<=0 then
  2495    begin if b<0 then if a>0 then return_sign(-1);
  2496    if c=0 then return_sign(0) else return_sign(-1);
  2497    end
  2498  
  2499  @ We conclude this set of elementary routines with some simple rounding
  2500  and truncation operations that are coded in a machine-independent fashion.
  2501  The routines are slightly complicated because we want them to work
  2502  without overflow whenever $-2^{31}\L x<2^{31}$.
  2503  
  2504  @p function floor_scaled(@!x:scaled):scaled;
  2505    {$2^{16}\lfloor x/2^{16}\rfloor$}
  2506  var @!be_careful:integer; {temporary register}
  2507  begin if x>=0 then floor_scaled:=x-(x mod unity)
  2508  else  begin be_careful:=x+1;
  2509    floor_scaled:=x+((-be_careful) mod unity)+1-unity;
  2510    end;
  2511  end;
  2512  @#
  2513  function floor_unscaled(@!x:scaled):integer;
  2514    {$\lfloor x/2^{16}\rfloor$}
  2515  var @!be_careful:integer; {temporary register}
  2516  begin if x>=0 then floor_unscaled:=x div unity
  2517  else  begin be_careful:=x+1; floor_unscaled:=-(1+((-be_careful) div unity));
  2518    end;
  2519  end;
  2520  @#
  2521  function round_unscaled(@!x:scaled):integer;
  2522    {$\lfloor x/2^{16}+.5\rfloor$}
  2523  var @!be_careful:integer; {temporary register}
  2524  begin if x>=half_unit then round_unscaled:=1+((x-half_unit) div unity)
  2525  else if x>=-half_unit then round_unscaled:=0
  2526  else  begin be_careful:=x+1;
  2527    round_unscaled:=-(1+((-be_careful-half_unit) div unity));
  2528    end;
  2529  end;
  2530  @#
  2531  function round_fraction(@!x:fraction):scaled;
  2532    {$\lfloor x/2^{12}+.5\rfloor$}
  2533  var @!be_careful:integer; {temporary register}
  2534  begin if x>=2048 then round_fraction:=1+((x-2048) div 4096)
  2535  else if x>=-2048 then round_fraction:=0
  2536  else  begin be_careful:=x+1;
  2537    round_fraction:=-(1+((-be_careful-2048) div 4096));
  2538    end;
  2539  end;
  2540  
  2541  @* \[8] Algebraic and transcendental functions.
  2542  \MF\ computes all of the necessary special functions from scratch, without
  2543  relying on |real| arithmetic or system subroutines for sines, cosines, etc.
  2544  
  2545  @ To get the square root of a |scaled| number |x|, we want to calculate
  2546  $s=\lfloor 2^8\!\sqrt x +{1\over2}\rfloor$. If $x>0$, this is the unique
  2547  integer such that $2^{16}x-s\L s^2<2^{16}x+s$. The following subroutine
  2548  determines $s$ by an iterative method that maintains the invariant
  2549  relations $x=2^{46-2k}x_0\bmod 2^{30}$, $0<y=\lfloor 2^{16-2k}x_0\rfloor
  2550  -s^2+s\L q=2s$, where $x_0$ is the initial value of $x$. The value of~$y$
  2551  might, however, be zero at the start of the first iteration.
  2552  
  2553  @p function square_rt(@!x:scaled):scaled;
  2554  var @!k:small_number; {iteration control counter}
  2555  @!y,@!q:integer; {registers for intermediate calculations}
  2556  begin if x<=0 then @<Handle square root of zero or negative argument@>
  2557  else  begin k:=23; q:=2;
  2558    while x<fraction_two do {i.e., |while x<@t$2^{29}$@>|\unskip}
  2559      begin decr(k); x:=x+x+x+x;
  2560      end;
  2561    if x<fraction_four then y:=0
  2562    else  begin x:=x-fraction_four; y:=1;
  2563      end;
  2564    repeat @<Decrease |k| by 1, maintaining the invariant
  2565      relations between |x|, |y|, and~|q|@>;
  2566    until k=0;
  2567    square_rt:=half(q);
  2568    end;
  2569  end;
  2570  
  2571  @ @<Handle square root of zero...@>=
  2572  begin if x<0 then
  2573    begin print_err("Square root of ");
  2574  @.Square root...replaced by 0@>
  2575    print_scaled(x); print(" has been replaced by 0");
  2576    help2("Since I don't take square roots of negative numbers,")@/
  2577      ("I'm zeroing this one. Proceed, with fingers crossed.");
  2578    error;
  2579    end;
  2580  square_rt:=0;
  2581  end
  2582  
  2583  @ @<Decrease |k| by 1, maintaining...@>=
  2584  double(x); double(y);
  2585  if x>=fraction_four then {note that |fraction_four=@t$2^{30}$@>|}
  2586    begin x:=x-fraction_four; incr(y);
  2587    end;
  2588  double(x); y:=y+y-q; double(q);
  2589  if x>=fraction_four then
  2590    begin x:=x-fraction_four; incr(y);
  2591    end;
  2592  if y>q then
  2593    begin y:=y-q; q:=q+2;
  2594    end
  2595  else if y<=0 then
  2596    begin q:=q-2; y:=y+q;
  2597    end;
  2598  decr(k)
  2599  
  2600  @ Pythagorean addition $\psqrt{a^2+b^2}$ is implemented by an elegant
  2601  iterative scheme due to Cleve Moler and Donald Morrison [{\sl IBM Journal
  2602  @^Moler, Cleve Barry@>
  2603  @^Morrison, Donald Ross@>
  2604  of Research and Development\/ \bf27} (1983), 577--581]. It modifies |a| and~|b|
  2605  in such a way that their Pythagorean sum remains invariant, while the
  2606  smaller argument decreases.
  2607  
  2608  @p function pyth_add(@!a,@!b:integer):integer;
  2609  label done;
  2610  var @!r:fraction; {register used to transform |a| and |b|}
  2611  @!big:boolean; {is the result dangerously near $2^{31}$?}
  2612  begin a:=abs(a); b:=abs(b);
  2613  if a<b then
  2614    begin r:=b; b:=a; a:=r;
  2615    end; {now |0<=b<=a|}
  2616  if b>0 then
  2617    begin if a<fraction_two then big:=false
  2618    else  begin a:=a div 4; b:=b div 4; big:=true;
  2619      end; {we reduced the precision to avoid arithmetic overflow}
  2620    @<Replace |a| by an approximation to $\psqrt{a^2+b^2}$@>;
  2621    if big then
  2622      if a<fraction_two then a:=a+a+a+a
  2623      else  begin arith_error:=true; a:=el_gordo;
  2624        end;
  2625    end;
  2626  pyth_add:=a;
  2627  end;
  2628  
  2629  @ The key idea here is to reflect the vector $(a,b)$ about the
  2630  line through $(a,b/2)$.
  2631  
  2632  @<Replace |a| by an approximation to $\psqrt{a^2+b^2}$@>=
  2633  loop@+  begin r:=make_fraction(b,a);
  2634    r:=take_fraction(r,r); {now $r\approx b^2/a^2$}
  2635    if r=0 then goto done;
  2636    r:=make_fraction(r,fraction_four+r);
  2637    a:=a+take_fraction(a+a,r); b:=take_fraction(b,r);
  2638    end;
  2639  done:
  2640  
  2641  @ Here is a similar algorithm for $\psqrt{a^2-b^2}$.
  2642  It converges slowly when $b$ is near $a$, but otherwise it works fine.
  2643  
  2644  @p function pyth_sub(@!a,@!b:integer):integer;
  2645  label done;
  2646  var @!r:fraction; {register used to transform |a| and |b|}
  2647  @!big:boolean; {is the input dangerously near $2^{31}$?}
  2648  begin a:=abs(a); b:=abs(b);
  2649  if a<=b then @<Handle erroneous |pyth_sub| and set |a:=0|@>
  2650  else  begin if a<fraction_four then big:=false
  2651    else  begin a:=half(a); b:=half(b); big:=true;
  2652      end;
  2653    @<Replace |a| by an approximation to $\psqrt{a^2-b^2}$@>;
  2654    if big then a:=a+a;
  2655    end;
  2656  pyth_sub:=a;
  2657  end;
  2658  
  2659  @ @<Replace |a| by an approximation to $\psqrt{a^2-b^2}$@>=
  2660  loop@+  begin r:=make_fraction(b,a);
  2661    r:=take_fraction(r,r); {now $r\approx b^2/a^2$}
  2662    if r=0 then goto done;
  2663    r:=make_fraction(r,fraction_four-r);
  2664    a:=a-take_fraction(a+a,r); b:=take_fraction(b,r);
  2665    end;
  2666  done:
  2667  
  2668  @ @<Handle erroneous |pyth_sub| and set |a:=0|@>=
  2669  begin if a<b then
  2670    begin print_err("Pythagorean subtraction "); print_scaled(a);
  2671    print("+-+"); print_scaled(b); print(" has been replaced by 0");
  2672  @.Pythagorean...@>
  2673    help2("Since I don't take square roots of negative numbers,")@/
  2674      ("I'm zeroing this one. Proceed, with fingers crossed.");
  2675    error;
  2676    end;
  2677  a:=0;
  2678  end
  2679  
  2680  @ The subroutines for logarithm and exponential involve two tables.
  2681  The first is simple: |two_to_the[k]| equals $2^k$. The second involves
  2682  a bit more calculation, which the author claims to have done correctly:
  2683  |spec_log[k]| is $2^{27}$ times $\ln\bigl(1/(1-2^{-k})\bigr)=
  2684  2^{-k}+{1\over2}2^{-2k}+{1\over3}2^{-3k}+\cdots\,$, rounded to the
  2685  nearest integer.
  2686  
  2687  @<Glob...@>=
  2688  @!two_to_the:array[0..30] of integer; {powers of two}
  2689  @!spec_log:array[1..28] of integer; {special logarithms}
  2690  
  2691  @ @<Local variables for initialization@>=
  2692  @!k:integer; {all-purpose loop index}
  2693  
  2694  @ @<Set init...@>=
  2695  two_to_the[0]:=1;
  2696  for k:=1 to 30 do two_to_the[k]:=2*two_to_the[k-1];
  2697  spec_log[1]:=93032640;
  2698  spec_log[2]:=38612034;
  2699  spec_log[3]:=17922280;
  2700  spec_log[4]:=8662214;
  2701  spec_log[5]:=4261238;
  2702  spec_log[6]:=2113709;
  2703  spec_log[7]:=1052693;
  2704  spec_log[8]:=525315;
  2705  spec_log[9]:=262400;
  2706  spec_log[10]:=131136;
  2707  spec_log[11]:=65552;
  2708  spec_log[12]:=32772;
  2709  spec_log[13]:=16385;
  2710  for k:=14 to 27 do spec_log[k]:=two_to_the[27-k];
  2711  spec_log[28]:=1;
  2712  
  2713  @ Here is the routine that calculates $2^8$ times the natural logarithm
  2714  of a |scaled| quantity; it is an integer approximation to $2^{24}\ln(x/2^{16})$,
  2715  when |x| is a given positive integer.
  2716  
  2717  The method is based on exercise 1.2.2--25 in {\sl The Art of Computer
  2718  Programming\/}: During the main iteration we have $1\L 2^{-30}x<1/(1-2^{1-k})$,
  2719  and the logarithm of $2^{30}x$ remains to be added to an accumulator
  2720  register called~$y$. Three auxiliary bits of accuracy are retained in~$y$
  2721  during the calculation, and sixteen auxiliary bits to extend |y| are
  2722  kept in~|z| during the initial argument reduction. (We add
  2723  $100\cdot2^{16}=6553600$ to~|z| and subtract 100 from~|y| so that |z| will
  2724  not become negative; also, the actual amount subtracted from~|y| is~96,
  2725  not~100, because we want to add~4 for rounding before the final division by~8.)
  2726  
  2727  @p function m_log(@!x:scaled):scaled;
  2728  var @!y,@!z:integer; {auxiliary registers}
  2729  @!k:integer; {iteration counter}
  2730  begin if x<=0 then @<Handle non-positive logarithm@>
  2731  else  begin y:=1302456956+4-100; {$14\times2^{27}\ln2\approx1302456956.421063$}
  2732    z:=27595+6553600; {and $2^{16}\times .421063\approx 27595$}
  2733    while x<fraction_four do
  2734      begin double(x); y:=y-93032639; z:=z-48782;
  2735      end; {$2^{27}\ln2\approx 93032639.74436163$
  2736        and $2^{16}\times.74436163\approx 48782$}
  2737    y:=y+(z div unity); k:=2;
  2738    while x>fraction_four+4 do
  2739      @<Increase |k| until |x| can be multiplied by a
  2740        factor of $2^{-k}$, and adjust $y$ accordingly@>;
  2741    m_log:=y div 8;
  2742    end;
  2743  end;
  2744  
  2745  @ @<Increase |k| until |x| can...@>=
  2746  begin z:=((x-1) div two_to_the[k])+1; {$z=\lceil x/2^k\rceil$}
  2747  while x<fraction_four+z do
  2748    begin z:=half(z+1); k:=k+1;
  2749    end;
  2750  y:=y+spec_log[k]; x:=x-z;
  2751  end
  2752  
  2753  @ @<Handle non-positive logarithm@>=
  2754  begin print_err("Logarithm of ");
  2755  @.Logarithm...replaced by 0@>
  2756  print_scaled(x); print(" has been replaced by 0");
  2757  help2("Since I don't take logs of non-positive numbers,")@/
  2758    ("I'm zeroing this one. Proceed, with fingers crossed.");
  2759  error; m_log:=0;
  2760  end
  2761  
  2762  @ Conversely, the exponential routine calculates $\exp(x/2^8)$,
  2763  when |x| is |scaled|. The result is an integer approximation to
  2764  $2^{16}\exp(x/2^{24})$, when |x| is regarded as an integer.
  2765  
  2766  @p function m_exp(@!x:scaled):scaled;
  2767  var @!k:small_number; {loop control index}
  2768  @!y,@!z:integer; {auxiliary registers}
  2769  begin if x>174436200 then
  2770      {$2^{24}\ln((2^{31}-1)/2^{16})\approx 174436199.51$}
  2771    begin arith_error:=true; m_exp:=el_gordo;
  2772    end
  2773  else if x<-197694359 then m_exp:=0
  2774      {$2^{24}\ln(2^{-1}/2^{16})\approx-197694359.45$}
  2775  else  begin if x<=0 then
  2776      begin z:=-8*x; y:=@'4000000; {$y=2^{20}$}
  2777      end
  2778    else  begin if x<=127919879 then z:=1023359037-8*x
  2779        {$2^{27}\ln((2^{31}-1)/2^{20})\approx 1023359037.125$}
  2780      else z:=8*(174436200-x); {|z| is always nonnegative}
  2781      y:=el_gordo;
  2782      end;
  2783    @<Multiply |y| by $\exp(-z/2^{27})$@>;
  2784    if x<=127919879 then m_exp:=(y+8) div 16@+else m_exp:=y;
  2785    end;
  2786  end;
  2787  
  2788  @ The idea here is that subtracting |spec_log[k]| from |z| corresponds
  2789  to multiplying |y| by $1-2^{-k}$.
  2790  
  2791  A subtle point (which had to be checked) was that if $x=127919879$, the
  2792  value of~|y| will decrease so that |y+8| doesn't overflow. In fact,
  2793  $z$ will be 5 in this case, and |y| will decrease by~64 when |k=25|
  2794  and by~16 when |k=27|.
  2795  
  2796  @<Multiply |y| by...@>=
  2797  k:=1;
  2798  while z>0 do
  2799    begin while z>=spec_log[k] do
  2800      begin z:=z-spec_log[k];
  2801      y:=y-1-((y-two_to_the[k-1]) div two_to_the[k]);
  2802      end;
  2803    incr(k);
  2804    end
  2805  
  2806  @ The trigonometric subroutines use an auxiliary table such that
  2807  |spec_atan[k]| contains an approximation to the |angle| whose tangent
  2808  is~$1/2^k$.
  2809  
  2810  @<Glob...@>=
  2811  @!spec_atan:array[1..26] of angle; {$\arctan2^{-k}$ times $2^{20}\cdot180/\pi$}
  2812  
  2813  @ @<Set init...@>=
  2814  spec_atan[1]:=27855475;
  2815  spec_atan[2]:=14718068;
  2816  spec_atan[3]:=7471121;
  2817  spec_atan[4]:=3750058;
  2818  spec_atan[5]:=1876857;
  2819  spec_atan[6]:=938658;
  2820  spec_atan[7]:=469357;
  2821  spec_atan[8]:=234682;
  2822  spec_atan[9]:=117342;
  2823  spec_atan[10]:=58671;
  2824  spec_atan[11]:=29335;
  2825  spec_atan[12]:=14668;
  2826  spec_atan[13]:=7334;
  2827  spec_atan[14]:=3667;
  2828  spec_atan[15]:=1833;
  2829  spec_atan[16]:=917;
  2830  spec_atan[17]:=458;
  2831  spec_atan[18]:=229;
  2832  spec_atan[19]:=115;
  2833  spec_atan[20]:=57;
  2834  spec_atan[21]:=29;
  2835  spec_atan[22]:=14;
  2836  spec_atan[23]:=7;
  2837  spec_atan[24]:=4;
  2838  spec_atan[25]:=2;
  2839  spec_atan[26]:=1;
  2840  
  2841  @ Given integers |x| and |y|, not both zero, the |n_arg| function
  2842  returns the |angle| whose tangent points in the direction $(x,y)$.
  2843  This subroutine first determines the correct octant, then solves the
  2844  problem for |0<=y<=x|, then converts the result appropriately to
  2845  return an answer in the range |-one_eighty_deg<=@t$\theta$@><=one_eighty_deg|.
  2846  (The answer is |+one_eighty_deg| if |y=0| and |x<0|, but an answer of
  2847  |-one_eighty_deg| is possible if, for example, |y=-1| and $x=-2^{30}$.)
  2848  
  2849  The octants are represented in a ``Gray code,'' since that turns out
  2850  to be computationally simplest.
  2851  
  2852  @d negate_x=1
  2853  @d negate_y=2
  2854  @d switch_x_and_y=4
  2855  @d first_octant=1
  2856  @d second_octant=first_octant+switch_x_and_y
  2857  @d third_octant=first_octant+switch_x_and_y+negate_x
  2858  @d fourth_octant=first_octant+negate_x
  2859  @d fifth_octant=first_octant+negate_x+negate_y
  2860  @d sixth_octant=first_octant+switch_x_and_y+negate_x+negate_y
  2861  @d seventh_octant=first_octant+switch_x_and_y+negate_y
  2862  @d eighth_octant=first_octant+negate_y
  2863  
  2864  @p function n_arg(@!x,@!y:integer):angle;
  2865  var @!z:angle; {auxiliary register}
  2866  @!t:integer; {temporary storage}
  2867  @!k:small_number; {loop counter}
  2868  @!octant:first_octant..sixth_octant; {octant code}
  2869  begin if x>=0 then octant:=first_octant
  2870  else  begin negate(x); octant:=first_octant+negate_x;
  2871    end;
  2872  if y<0 then
  2873    begin negate(y); octant:=octant+negate_y;
  2874    end;
  2875  if x<y then
  2876    begin t:=y; y:=x; x:=t; octant:=octant+switch_x_and_y;
  2877    end;
  2878  if x=0 then @<Handle undefined arg@>
  2879  else  begin @<Set variable |z| to the arg of $(x,y)$@>;
  2880    @<Return an appropriate answer based on |z| and |octant|@>;
  2881    end;
  2882  end;
  2883  
  2884  @ @<Handle undefined arg@>=
  2885  begin print_err("angle(0,0) is taken as zero");
  2886  @.angle(0,0)...zero@>
  2887  help2("The `angle' between two identical points is undefined.")@/
  2888    ("I'm zeroing this one. Proceed, with fingers crossed.");
  2889  error; n_arg:=0;
  2890  end
  2891  
  2892  @ @<Return an appropriate answer...@>=
  2893  case octant of
  2894  first_octant:n_arg:=z;
  2895  second_octant:n_arg:=ninety_deg-z;
  2896  third_octant:n_arg:=ninety_deg+z;
  2897  fourth_octant:n_arg:=one_eighty_deg-z;
  2898  fifth_octant:n_arg:=z-one_eighty_deg;
  2899  sixth_octant:n_arg:=-z-ninety_deg;
  2900  seventh_octant:n_arg:=z-ninety_deg;
  2901  eighth_octant:n_arg:=-z;
  2902  end {there are no other cases}
  2903  
  2904  @ At this point we have |x>=y>=0|, and |x>0|. The numbers are scaled up
  2905  or down until $2^{28}\L x<2^{29}$, so that accurate fixed-point calculations
  2906  will be made.
  2907  
  2908  @<Set variable |z| to the arg...@>=
  2909  while x>=fraction_two do
  2910    begin x:=half(x); y:=half(y);
  2911    end;
  2912  z:=0;
  2913  if y>0 then
  2914    begin while x<fraction_one do
  2915      begin double(x); double(y);
  2916      end;
  2917    @<Increase |z| to the arg of $(x,y)$@>;
  2918    end
  2919  
  2920  @ During the calculations of this section, variables |x| and~|y|
  2921  represent actual coordinates $(x,2^{-k}y)$. We will maintain the
  2922  condition |x>=y|, so that the tangent will be at most $2^{-k}$.
  2923  If $x<2y$, the tangent is greater than $2^{-k-1}$. The transformation
  2924  $(a,b)\mapsto(a+b\tan\phi,b-a\tan\phi)$ replaces $(a,b)$ by
  2925  coordinates whose angle has decreased by~$\phi$; in the special case
  2926  $a=x$, $b=2^{-k}y$, and $\tan\phi=2^{-k-1}$, this operation reduces
  2927  to the particularly simple iteration shown here. [Cf.~John E. Meggitt,
  2928  @^Meggitt, John E.@>
  2929  {\sl IBM Journal of Research and Development\/ \bf6} (1962), 210--226.]
  2930  
  2931  The initial value of |x| will be multiplied by at most
  2932  $(1+{1\over2})(1+{1\over8})(1+{1\over32})\cdots\approx 1.7584$; hence
  2933  there is no chance of integer overflow.
  2934  
  2935  @<Increase |z|...@>=
  2936  k:=0;
  2937  repeat double(y); incr(k);
  2938  if y>x then
  2939    begin z:=z+spec_atan[k]; t:=x; x:=x+(y div two_to_the[k+k]); y:=y-t;
  2940    end;
  2941  until k=15;
  2942  repeat double(y); incr(k);
  2943  if y>x then
  2944    begin z:=z+spec_atan[k]; y:=y-x;
  2945    end;
  2946  until k=26
  2947  
  2948  @ Conversely, the |n_sin_cos| routine takes an |angle| and produces the sine
  2949  and cosine of that angle. The results of this routine are
  2950  stored in global integer variables |n_sin| and |n_cos|.
  2951  
  2952  @<Glob...@>=
  2953  @!n_sin,@!n_cos:fraction; {results computed by |n_sin_cos|}
  2954  
  2955  @ Given an integer |z| that is $2^{20}$ times an angle $\theta$ in degrees,
  2956  the purpose of |n_sin_cos(z)| is to set
  2957  |x=@t$r\cos\theta$@>| and |y=@t$r\sin\theta$@>| (approximately),
  2958  for some rather large number~|r|. The maximum of |x| and |y|
  2959  will be between $2^{28}$ and $2^{30}$, so that there will be hardly
  2960  any loss of accuracy. Then |x| and~|y| are divided by~|r|.
  2961  
  2962  @p procedure n_sin_cos(@!z:angle); {computes a multiple of the sine and cosine}
  2963  var @!k:small_number; {loop control variable}
  2964  @!q:0..7; {specifies the quadrant}
  2965  @!r:fraction; {magnitude of |(x,y)|}
  2966  @!x,@!y,@!t:integer; {temporary registers}
  2967  begin while z<0 do z:=z+three_sixty_deg;
  2968  z:=z mod three_sixty_deg; {now |0<=z<three_sixty_deg|}
  2969  q:=z div forty_five_deg; z:=z mod forty_five_deg;
  2970  x:=fraction_one; y:=x;
  2971  if not odd(q) then z:=forty_five_deg-z;
  2972  @<Subtract angle |z| from |(x,y)|@>;
  2973  @<Convert |(x,y)| to the octant determined by~|q|@>;
  2974  r:=pyth_add(x,y); n_cos:=make_fraction(x,r); n_sin:=make_fraction(y,r);
  2975  end;
  2976  
  2977  @ In this case the octants are numbered sequentially.
  2978  
  2979  @<Convert |(x,...@>=
  2980  case q of
  2981  0:do_nothing;
  2982  1:begin t:=x; x:=y; y:=t;
  2983    end;
  2984  2:begin t:=x; x:=-y; y:=t;
  2985    end;
  2986  3:negate(x);
  2987  4:begin negate(x); negate(y);
  2988    end;
  2989  5:begin t:=x; x:=-y; y:=-t;
  2990    end;
  2991  6:begin t:=x; x:=y; y:=-t;
  2992    end;
  2993  7:negate(y);
  2994  end {there are no other cases}
  2995  
  2996  @ The main iteration of |n_sin_cos| is similar to that of |n_arg| but
  2997  applied in reverse. The values of |spec_atan[k]| decrease slowly enough
  2998  that this loop is guaranteed to terminate before the (nonexistent) value
  2999  |spec_atan[27]| would be required.
  3000  
  3001  @<Subtract angle |z|...@>=
  3002  k:=1;
  3003  while z>0 do
  3004    begin if z>=spec_atan[k] then
  3005      begin z:=z-spec_atan[k]; t:=x;@/
  3006      x:=t+y div two_to_the[k];
  3007      y:=y-t div two_to_the[k];
  3008      end;
  3009    incr(k);
  3010    end;
  3011  if y<0 then y:=0 {this precaution may never be needed}
  3012  
  3013  @ And now let's complete our collection of numeric utility routines
  3014  by considering random number generation.
  3015  \MF\ generates pseudo-random numbers with the additive scheme recommended
  3016  in Section 3.6 of {\sl The Art of Computer Programming}; however, the
  3017  results are random fractions between 0 and |fraction_one-1|, inclusive.
  3018  
  3019  There's an auxiliary array |randoms| that contains 55 pseudo-random
  3020  fractions. Using the recurrence $x_n=(x_{n-55}-x_{n-24})\bmod 2^{28}$,
  3021  we generate batches of 55 new $x_n$'s at a time by calling |new_randoms|.
  3022  The global variable |j_random| tells which element has most recently
  3023  been consumed.
  3024  
  3025  @<Glob...@>=
  3026  @!randoms:array[0..54] of fraction; {the last 55 random values generated}
  3027  @!j_random:0..54; {the number of unused |randoms|}
  3028  
  3029  @ To consume a random fraction, the program below will say `|next_random|'
  3030  and then it will fetch |randoms[j_random]|. The |next_random| macro
  3031  actually accesses the numbers backwards; blocks of 55~$x$'s are
  3032  essentially being ``flipped.'' But that doesn't make them less random.
  3033  
  3034  @d next_random==if j_random=0 then new_randoms
  3035    else decr(j_random)
  3036  
  3037  @p procedure new_randoms;
  3038  var @!k:0..54; {index into |randoms|}
  3039  @!x:fraction; {accumulator}
  3040  begin for k:=0 to 23 do
  3041    begin x:=randoms[k]-randoms[k+31];
  3042    if x<0 then x:=x+fraction_one;
  3043    randoms[k]:=x;
  3044    end;
  3045  for k:=24 to 54 do
  3046    begin x:=randoms[k]-randoms[k-24];
  3047    if x<0 then x:=x+fraction_one;
  3048    randoms[k]:=x;
  3049    end;
  3050  j_random:=54;
  3051  end;
  3052  
  3053  @ To initialize the |randoms| table, we call the following routine.
  3054  
  3055  @p procedure init_randoms(@!seed:scaled);
  3056  var @!j,@!jj,@!k:fraction; {more or less random integers}
  3057  @!i:0..54; {index into |randoms|}
  3058  begin j:=abs(seed);
  3059  while j>=fraction_one do j:=half(j);
  3060  k:=1;
  3061  for i:=0 to 54 do
  3062    begin jj:=k; k:=j-k; j:=jj;
  3063    if k<0 then k:=k+fraction_one;
  3064    randoms[(i*21)mod 55]:=j;
  3065    end;
  3066  new_randoms; new_randoms; new_randoms; {``warm up'' the array}
  3067  end;
  3068  
  3069  @ To produce a uniform random number in the range |0<=u<x| or |0>=u>x|
  3070  or |0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
  3071  
  3072  Note that the call of |take_fraction| will produce the values 0 and~|x|
  3073  with about half the probability that it will produce any other particular
  3074  values between 0 and~|x|, because it rounds its answers.
  3075  
  3076  @p function unif_rand(@!x:scaled):scaled;
  3077  var @!y:scaled; {trial value}
  3078  begin next_random; y:=take_fraction(abs(x),randoms[j_random]);
  3079  if y=abs(x) then unif_rand:=0
  3080  else if x>0 then unif_rand:=y
  3081  else unif_rand:=-y;
  3082  end;
  3083  
  3084  @ Finally, a normal deviate with mean zero and unit standard deviation
  3085  can readily be obtained with the ratio method (Algorithm 3.4.1R in
  3086  {\sl The Art of Computer Programming\/}).
  3087  
  3088  @p function norm_rand:scaled;
  3089  var @!x,@!u,@!l:integer; {what the book would call $2^{16}X$, $2^{28}U$,
  3090    and $-2^{24}\ln U$}
  3091  begin repeat
  3092    repeat next_random;
  3093    x:=take_fraction(112429,randoms[j_random]-fraction_half);
  3094      {$2^{16}\sqrt{8/e}\approx 112428.82793$}
  3095    next_random; u:=randoms[j_random];
  3096    until abs(x)<u;
  3097  x:=make_fraction(x,u);
  3098  l:=139548960-m_log(u); {$2^{24}\cdot12\ln2\approx139548959.6165$}
  3099  until ab_vs_cd(1024,l,x,x)>=0;
  3100  norm_rand:=x;
  3101  end;
  3102  
  3103  @* \[9] Packed data.
  3104  In order to make efficient use of storage space, \MF\ bases its major data
  3105  structures on a |memory_word|, which contains either a (signed) integer,
  3106  possibly scaled, or a small number of fields that are one half or one
  3107  quarter of the size used for storing integers.
  3108  
  3109  If |x| is a variable of type |memory_word|, it contains up to four
  3110  fields that can be referred to as follows:
  3111  $$\vbox{\halign{\hfil#&#\hfil&#\hfil\cr
  3112  |x|&.|int|&(an |integer|)\cr
  3113  |x|&.|sc|\qquad&(a |scaled| integer)\cr
  3114  |x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr
  3115  |x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword
  3116    field)\cr
  3117  |x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt
  3118    &\qquad\qquad\qquad(four quarterword fields)\cr}}$$
  3119  This is somewhat cumbersome to write, and not very readable either, but
  3120  macros will be used to make the notation shorter and more transparent.
  3121  The \PASCAL\ code below gives a formal definition of |memory_word| and
  3122  its subsidiary types, using packed variant records. \MF\ makes no
  3123  assumptions about the relative positions of the fields within a word.
  3124  
  3125  Since we are assuming 32-bit integers, a halfword must contain at least
  3126  16 bits, and a quarterword must contain at least 8 bits.
  3127  @^system dependencies@>
  3128  But it doesn't hurt to have more bits; for example, with enough 36-bit
  3129  words you might be able to have |mem_max| as large as 262142.
  3130  
  3131  N.B.: Valuable memory space will be dreadfully wasted unless \MF\ is compiled
  3132  by a \PASCAL\ that packs all of the |memory_word| variants into
  3133  the space of a single integer. Some \PASCAL\ compilers will pack an
  3134  integer whose subrange is `|0..255|' into an eight-bit field, but others
  3135  insist on allocating space for an additional sign bit; on such systems you
  3136  can get 256 values into a quarterword only if the subrange is `|-128..127|'.
  3137  
  3138  The present implementation tries to accommodate as many variations as possible,
  3139  so it makes few assumptions. If integers having the subrange
  3140  `|min_quarterword..max_quarterword|' can be packed into a quarterword,
  3141  and if integers having the subrange `|min_halfword..max_halfword|'
  3142  can be packed into a halfword, everything should work satisfactorily.
  3143  
  3144  It is usually most efficient to have |min_quarterword=min_halfword=0|,
  3145  so one should try to achieve this unless it causes a severe problem.
  3146  The values defined here are recommended for most 32-bit computers.
  3147  
  3148  @d min_quarterword=0 {smallest allowable value in a |quarterword|}
  3149  @d max_quarterword=255 {largest allowable value in a |quarterword|}
  3150  @d min_halfword==0 {smallest allowable value in a |halfword|}
  3151  @d max_halfword==65535 {largest allowable value in a |halfword|}
  3152  
  3153  @ Here are the inequalities that the quarterword and halfword values
  3154  must satisfy (or rather, the inequalities that they mustn't satisfy):
  3155  
  3156  @<Check the ``constant''...@>=
  3157  init if mem_max<>mem_top then bad:=10;@+tini@;@/
  3158  if mem_max<mem_top then bad:=10;
  3159  if (min_quarterword>0)or(max_quarterword<127) then bad:=11;
  3160  if (min_halfword>0)or(max_halfword<32767) then bad:=12;
  3161  if (min_quarterword<min_halfword)or@|
  3162    (max_quarterword>max_halfword) then bad:=13;
  3163  if (mem_min<min_halfword)or(mem_max>=max_halfword) then bad:=14;
  3164  if max_strings>max_halfword then bad:=15;
  3165  if buf_size>max_halfword then bad:=16;
  3166  if (max_quarterword-min_quarterword<255)or@|
  3167    (max_halfword-min_halfword<65535) then bad:=17;
  3168  
  3169  @ The operation of subtracting |min_halfword| occurs rather frequently in
  3170  \MF, so it is convenient to abbreviate this operation by using the macro
  3171  |ho| defined here.  \MF\ will run faster with respect to compilers that
  3172  don't optimize the expression `|x-0|', if this macro is simplified in the
  3173  obvious way when |min_halfword=0|. Similarly, |qi| and |qo| are used for
  3174  input to and output from quarterwords.
  3175  @^system dependencies@>
  3176  
  3177  @d ho(#)==#-min_halfword
  3178    {to take a sixteen-bit item from a halfword}
  3179  @d qo(#)==#-min_quarterword {to read eight bits from a quarterword}
  3180  @d qi(#)==#+min_quarterword {to store eight bits in a quarterword}
  3181  
  3182  @ The reader should study the following definitions closely:
  3183  @^system dependencies@>
  3184  
  3185  @d sc==int {|scaled| data is equivalent to |integer|}
  3186  
  3187  @<Types...@>=
  3188  @!quarterword = min_quarterword..max_quarterword; {1/4 of a word}
  3189  @!halfword=min_halfword..max_halfword; {1/2 of a word}
  3190  @!two_choices = 1..2; {used when there are two variants in a record}
  3191  @!three_choices = 1..3; {used when there are three variants in a record}
  3192  @!two_halves = packed record@;@/
  3193    @!rh:halfword;
  3194    case two_choices of
  3195    1: (@!lh:halfword);
  3196    2: (@!b0:quarterword; @!b1:quarterword);
  3197    end;
  3198  @!four_quarters = packed record@;@/
  3199    @!b0:quarterword;
  3200    @!b1:quarterword;
  3201    @!b2:quarterword;
  3202    @!b3:quarterword;
  3203    end;
  3204  @!memory_word = record@;@/
  3205    case three_choices of
  3206    1: (@!int:integer);
  3207    2: (@!hh:two_halves);
  3208    3: (@!qqqq:four_quarters);
  3209    end;
  3210  @!word_file = file of memory_word;
  3211  
  3212  @ When debugging, we may want to print a |memory_word| without knowing
  3213  what type it is; so we print it in all modes.
  3214  @^dirty \PASCAL@>@^debugging@>
  3215  
  3216  @p @!debug procedure print_word(@!w:memory_word);
  3217    {prints |w| in all ways}
  3218  begin print_int(w.int); print_char(" ");@/
  3219  print_scaled(w.sc); print_char(" "); print_scaled(w.sc div @'10000); print_ln;@/
  3220  print_int(w.hh.lh); print_char("="); print_int(w.hh.b0); print_char(":");
  3221  print_int(w.hh.b1); print_char(";"); print_int(w.hh.rh); print_char(" ");@/
  3222  print_int(w.qqqq.b0); print_char(":"); print_int(w.qqqq.b1); print_char(":");
  3223  print_int(w.qqqq.b2); print_char(":"); print_int(w.qqqq.b3);
  3224  end;
  3225  gubed
  3226  
  3227  @* \[10] Dynamic memory allocation.
  3228  The \MF\ system does nearly all of its own memory allocation, so that it
  3229  can readily be transported into environments that do not have automatic
  3230  facilities for strings, garbage collection, etc., and so that it can be in
  3231  control of what error messages the user receives. The dynamic storage
  3232  requirements of \MF\ are handled by providing a large array |mem| in
  3233  which consecutive blocks of words are used as nodes by the \MF\ routines.
  3234  
  3235  Pointer variables are indices into this array, or into another array
  3236  called |eqtb| that will be explained later. A pointer variable might
  3237  also be a special flag that lies outside the bounds of |mem|, so we
  3238  allow pointers to assume any |halfword| value. The minimum memory
  3239  index represents a null pointer.
  3240  
  3241  @d pointer==halfword {a flag or a location in |mem| or |eqtb|}
  3242  @d null==mem_min {the null pointer}
  3243  
  3244  @ The |mem| array is divided into two regions that are allocated separately,
  3245  but the dividing line between these two regions is not fixed; they grow
  3246  together until finding their ``natural'' size in a particular job.
  3247  Locations less than or equal to |lo_mem_max| are used for storing
  3248  variable-length records consisting of two or more words each. This region
  3249  is maintained using an algorithm similar to the one described in exercise
  3250  2.5--19 of {\sl The Art of Computer Programming}. However, no size field
  3251  appears in the allocated nodes; the program is responsible for knowing the
  3252  relevant size when a node is freed. Locations greater than or equal to
  3253  |hi_mem_min| are used for storing one-word records; a conventional
  3254  \.{AVAIL} stack is used for allocation in this region.
  3255  
  3256  Locations of |mem| between |mem_min| and |mem_top| may be dumped as part
  3257  of preloaded base files, by the \.{INIMF} preprocessor.
  3258  @.INIMF@>
  3259  Production versions of \MF\ may extend the memory at the top end in order to
  3260  provide more space; these locations, between |mem_top| and |mem_max|,
  3261  are always used for single-word nodes.
  3262  
  3263  The key pointers that govern |mem| allocation have a prescribed order:
  3264  $$\hbox{|null=mem_min<lo_mem_max<hi_mem_min<mem_top<=mem_end<=mem_max|.}$$
  3265  
  3266  @<Glob...@>=
  3267  @!mem : array[mem_min..mem_max] of memory_word; {the big dynamic storage area}
  3268  @!lo_mem_max : pointer; {the largest location of variable-size memory in use}
  3269  @!hi_mem_min : pointer; {the smallest location of one-word memory in use}
  3270  
  3271  @ Users who wish to study the memory requirements of specific applications can
  3272  use optional special features that keep track of current and
  3273  maximum memory usage. When code between the delimiters |@!stat| $\ldots$
  3274  |tats| is not ``commented out,'' \MF\ will run a bit slower but it will
  3275  report these statistics when |tracing_stats| is positive.
  3276  
  3277  @<Glob...@>=
  3278  @!var_used, @!dyn_used : integer; {how much memory is in use}
  3279  
  3280  @ Let's consider the one-word memory region first, since it's the
  3281  simplest. The pointer variable |mem_end| holds the highest-numbered location
  3282  of |mem| that has ever been used. The free locations of |mem| that
  3283  occur between |hi_mem_min| and |mem_end|, inclusive, are of type
  3284  |two_halves|, and we write |info(p)| and |link(p)| for the |lh|
  3285  and |rh| fields of |mem[p]| when it is of this type. The single-word
  3286  free locations form a linked list
  3287  $$|avail|,\;\hbox{|link(avail)|},\;\hbox{|link(link(avail))|},\;\ldots$$
  3288  terminated by |null|.
  3289  
  3290  @d link(#) == mem[#].hh.rh {the |link| field of a memory word}
  3291  @d info(#) == mem[#].hh.lh {the |info| field of a memory word}
  3292  
  3293  @<Glob...@>=
  3294  @!avail : pointer; {head of the list of available one-word nodes}
  3295  @!mem_end : pointer; {the last one-word node used in |mem|}
  3296  
  3297  @ If one-word memory is exhausted, it might mean that the user has forgotten
  3298  a token like `\&{enddef}' or `\&{endfor}'. We will define some procedures
  3299  later that try to help pinpoint the trouble.
  3300  
  3301  @p @t\4@>@<Declare the procedure called |show_token_list|@>@;
  3302  @t\4@>@<Declare the procedure called |runaway|@>
  3303  
  3304  @ The function |get_avail| returns a pointer to a new one-word node whose
  3305  |link| field is null. However, \MF\ will halt if there is no more room left.
  3306  @^inner loop@>
  3307  
  3308  @p function get_avail : pointer; {single-word node allocation}
  3309  var @!p:pointer; {the new node being got}
  3310  begin p:=avail; {get top location in the |avail| stack}
  3311  if p<>null then avail:=link(avail) {and pop it off}
  3312  else if mem_end<mem_max then {or go into virgin territory}
  3313    begin incr(mem_end); p:=mem_end;
  3314    end
  3315  else   begin decr(hi_mem_min); p:=hi_mem_min;
  3316    if hi_mem_min<=lo_mem_max then
  3317      begin runaway; {if memory is exhausted, display possible runaway text}
  3318      overflow("main memory size",mem_max+1-mem_min);
  3319        {quit; all one-word nodes are busy}
  3320  @:METAFONT capacity exceeded main memory size}{\quad main memory size@>
  3321      end;
  3322    end;
  3323  link(p):=null; {provide an oft-desired initialization of the new node}
  3324  @!stat incr(dyn_used);@+tats@;{maintain statistics}
  3325  get_avail:=p;
  3326  end;
  3327  
  3328  @ Conversely, a one-word node is recycled by calling |free_avail|.
  3329  
  3330  @d free_avail(#)== {single-word node liberation}
  3331    begin link(#):=avail; avail:=#;
  3332    @!stat decr(dyn_used);@+tats@/
  3333    end
  3334  
  3335  @ There's also a |fast_get_avail| routine, which saves the procedure-call
  3336  overhead at the expense of extra programming. This macro is used in
  3337  the places that would otherwise account for the most calls of |get_avail|.
  3338  @^inner loop@>
  3339  
  3340  @d fast_get_avail(#)==@t@>@;@/
  3341    begin #:=avail; {avoid |get_avail| if possible, to save time}
  3342    if #=null then #:=get_avail
  3343    else  begin avail:=link(#); link(#):=null;
  3344      @!stat incr(dyn_used);@+tats@/
  3345      end;
  3346    end
  3347  
  3348  @ The available-space list that keeps track of the variable-size portion
  3349  of |mem| is a nonempty, doubly-linked circular list of empty nodes,
  3350  pointed to by the roving pointer |rover|.
  3351  
  3352  Each empty node has size 2 or more; the first word contains the special
  3353  value |max_halfword| in its |link| field and the size in its |info| field;
  3354  the second word contains the two pointers for double linking.
  3355  
  3356  Each nonempty node also has size 2 or more. Its first word is of type
  3357  |two_halves|\kern-1pt, and its |link| field is never equal to |max_halfword|.
  3358  Otherwise there is complete flexibility with respect to the contents
  3359  of its other fields and its other words.
  3360  
  3361  (We require |mem_max<max_halfword| because terrible things can happen
  3362  when |max_halfword| appears in the |link| field of a nonempty node.)
  3363  
  3364  @d empty_flag == max_halfword {the |link| of an empty variable-size node}
  3365  @d is_empty(#) == (link(#)=empty_flag) {tests for empty node}
  3366  @d node_size == info {the size field in empty variable-size nodes}
  3367  @d llink(#) == info(#+1) {left link in doubly-linked list of empty nodes}
  3368  @d rlink(#) == link(#+1) {right link in doubly-linked list of empty nodes}
  3369  
  3370  @<Glob...@>=
  3371  @!rover : pointer; {points to some node in the list of empties}
  3372  
  3373  @ A call to |get_node| with argument |s| returns a pointer to a new node
  3374  of size~|s|, which must be 2~or more. The |link| field of the first word
  3375  of this new node is set to null. An overflow stop occurs if no suitable
  3376  space exists.
  3377  
  3378  If |get_node| is called with $s=2^{30}$, it simply merges adjacent free
  3379  areas and returns the value |max_halfword|.
  3380  
  3381  @p function get_node(@!s:integer):pointer; {variable-size node allocation}
  3382  label found,exit,restart;
  3383  var @!p:pointer; {the node currently under inspection}
  3384  @!q:pointer; {the node physically after node |p|}
  3385  @!r:integer; {the newly allocated node, or a candidate for this honor}
  3386  @!t,@!tt:integer; {temporary registers}
  3387  @^inner loop@>
  3388  begin restart: p:=rover; {start at some free node in the ring}
  3389  repeat @<Try to allocate within node |p| and its physical successors,
  3390    and |goto found| if allocation was possible@>;
  3391  p:=rlink(p); {move to the next node in the ring}
  3392  until p=rover; {repeat until the whole list has been traversed}
  3393  if s=@'10000000000 then
  3394    begin get_node:=max_halfword; return;
  3395    end;
  3396  if lo_mem_max+2<hi_mem_min then if lo_mem_max+2<=mem_min+max_halfword then
  3397    @<Grow more variable-size memory and |goto restart|@>;
  3398  overflow("main memory size",mem_max+1-mem_min);
  3399    {sorry, nothing satisfactory is left}
  3400  @:METAFONT capacity exceeded main memory size}{\quad main memory size@>
  3401  found: link(r):=null; {this node is now nonempty}
  3402  @!stat var_used:=var_used+s; {maintain usage statistics}
  3403  tats@;@/
  3404  get_node:=r;
  3405  exit:end;
  3406  
  3407  @ The lower part of |mem| grows by 1000 words at a time, unless
  3408  we are very close to going under. When it grows, we simply link
  3409  a new node into the available-space list. This method of controlled
  3410  growth helps to keep the |mem| usage consecutive when \MF\ is
  3411  implemented on ``virtual memory'' systems.
  3412  @^virtual memory@>
  3413  
  3414  @<Grow more variable-size memory and |goto restart|@>=
  3415  begin if hi_mem_min-lo_mem_max>=1998 then t:=lo_mem_max+1000
  3416  else t:=lo_mem_max+1+(hi_mem_min-lo_mem_max) div 2;
  3417    {|lo_mem_max+2<=t<hi_mem_min|}
  3418  if t>mem_min+max_halfword then t:=mem_min+max_halfword;
  3419  p:=llink(rover); q:=lo_mem_max; rlink(p):=q; llink(rover):=q;@/
  3420  rlink(q):=rover; llink(q):=p; link(q):=empty_flag; node_size(q):=t-lo_mem_max;@/
  3421  lo_mem_max:=t; link(lo_mem_max):=null; info(lo_mem_max):=null;
  3422  rover:=q; goto restart;
  3423  end
  3424  
  3425  @ @<Try to allocate...@>=
  3426  q:=p+node_size(p); {find the physical successor}
  3427  while is_empty(q) do {merge node |p| with node |q|}
  3428    begin t:=rlink(q); tt:=llink(q);
  3429  @^inner loop@>
  3430    if q=rover then rover:=t;
  3431    llink(t):=tt; rlink(tt):=t;@/
  3432    q:=q+node_size(q);
  3433    end;
  3434  r:=q-s;
  3435  if r>p+1 then @<Allocate from the top of node |p| and |goto found|@>;
  3436  if r=p then if rlink(p)<>p then
  3437    @<Allocate entire node |p| and |goto found|@>;
  3438  node_size(p):=q-p {reset the size in case it grew}
  3439  
  3440  @ @<Allocate from the top...@>=
  3441  begin node_size(p):=r-p; {store the remaining size}
  3442  rover:=p; {start searching here next time}
  3443  goto found;
  3444  end
  3445  
  3446  @ Here we delete node |p| from the ring, and let |rover| rove around.
  3447  
  3448  @<Allocate entire...@>=
  3449  begin rover:=rlink(p); t:=llink(p);
  3450  llink(rover):=t; rlink(t):=rover;
  3451  goto found;
  3452  end
  3453  
  3454  @ Conversely, when some variable-size node |p| of size |s| is no longer needed,
  3455  the operation |free_node(p,s)| will make its words available, by inserting
  3456  |p| as a new empty node just before where |rover| now points.
  3457  
  3458  @p procedure free_node(@!p:pointer; @!s:halfword); {variable-size node
  3459    liberation}
  3460  var @!q:pointer; {|llink(rover)|}
  3461  begin node_size(p):=s; link(p):=empty_flag;
  3462  @^inner loop@>
  3463  q:=llink(rover); llink(p):=q; rlink(p):=rover; {set both links}
  3464  llink(rover):=p; rlink(q):=p; {insert |p| into the ring}
  3465  @!stat var_used:=var_used-s;@+tats@;{maintain statistics}
  3466  end;
  3467  
  3468  @ Just before \.{INIMF} writes out the memory, it sorts the doubly linked
  3469  available space list. The list is probably very short at such times, so a
  3470  simple insertion sort is used. The smallest available location will be
  3471  pointed to by |rover|, the next-smallest by |rlink(rover)|, etc.
  3472  
  3473  @p @!init procedure sort_avail; {sorts the available variable-size nodes
  3474    by location}
  3475  var @!p,@!q,@!r: pointer; {indices into |mem|}
  3476  @!old_rover:pointer; {initial |rover| setting}
  3477  begin p:=get_node(@'10000000000); {merge adjacent free areas}
  3478  p:=rlink(rover); rlink(rover):=max_halfword; old_rover:=rover;
  3479  while p<>old_rover do @<Sort |p| into the list starting at |rover|
  3480    and advance |p| to |rlink(p)|@>;
  3481  p:=rover;
  3482  while rlink(p)<>max_halfword do
  3483    begin llink(rlink(p)):=p; p:=rlink(p);
  3484    end;
  3485  rlink(p):=rover; llink(rover):=p;
  3486  end;
  3487  tini
  3488  
  3489  @ The following |while| loop is guaranteed to
  3490  terminate, since the list that starts at
  3491  |rover| ends with |max_halfword| during the sorting procedure.
  3492  
  3493  @<Sort |p|...@>=
  3494  if p<rover then
  3495    begin q:=p; p:=rlink(q); rlink(q):=rover; rover:=q;
  3496    end
  3497  else  begin q:=rover;
  3498    while rlink(q)<p do q:=rlink(q);
  3499    r:=rlink(p); rlink(p):=rlink(q); rlink(q):=p; p:=r;
  3500    end
  3501  
  3502  @* \[11] Memory layout.
  3503  Some areas of |mem| are dedicated to fixed usage, since static allocation is
  3504  more efficient than dynamic allocation when we can get away with it. For
  3505  example, locations |mem_min| to |mem_min+2| are always used to store the
  3506  specification for null pen coordinates that are `$(0,0)$'. The
  3507  following macro definitions accomplish the static allocation by giving
  3508  symbolic names to the fixed positions. Static variable-size nodes appear
  3509  in locations |mem_min| through |lo_mem_stat_max|, and static single-word nodes
  3510  appear in locations |hi_mem_stat_min| through |mem_top|, inclusive.
  3511  
  3512  @d null_coords==mem_min {specification for pen offsets of $(0,0)$}
  3513  @d null_pen==null_coords+3 {we will define |coord_node_size=3|}
  3514  @d dep_head==null_pen+10 {and |pen_node_size=10|}
  3515  @d zero_val==dep_head+2 {two words for a permanently zero value}
  3516  @d temp_val==zero_val+2 {two words for a temporary value node}
  3517  @d end_attr==temp_val {we use |end_attr+2| only}
  3518  @d inf_val==end_attr+2 {and |inf_val+1| only}
  3519  @d bad_vardef==inf_val+2 {two words for \&{vardef} error recovery}
  3520  @d lo_mem_stat_max==bad_vardef+1  {largest statically
  3521    allocated word in the variable-size |mem|}
  3522  @#
  3523  @d sentinel==mem_top {end of sorted lists}
  3524  @d temp_head==mem_top-1 {head of a temporary list of some kind}
  3525  @d hold_head==mem_top-2 {head of a temporary list of another kind}
  3526  @d hi_mem_stat_min==mem_top-2 {smallest statically allocated word in
  3527    the one-word |mem|}
  3528  
  3529  @ The following code gets the dynamic part of |mem| off to a good start,
  3530  when \MF\ is initializing itself the slow way.
  3531  
  3532  @<Initialize table entries (done by \.{INIMF} only)@>=
  3533  rover:=lo_mem_stat_max+1; {initialize the dynamic memory}
  3534  link(rover):=empty_flag;
  3535  node_size(rover):=1000; {which is a 1000-word available node}
  3536  llink(rover):=rover; rlink(rover):=rover;@/
  3537  lo_mem_max:=rover+1000; link(lo_mem_max):=null; info(lo_mem_max):=null;@/
  3538  for k:=hi_mem_stat_min to mem_top do
  3539    mem[k]:=mem[lo_mem_max]; {clear list heads}
  3540  avail:=null; mem_end:=mem_top;
  3541  hi_mem_min:=hi_mem_stat_min; {initialize the one-word memory}
  3542  var_used:=lo_mem_stat_max+1-mem_min; dyn_used:=mem_top+1-hi_mem_min;
  3543    {initialize statistics}
  3544  
  3545  @ The procedure |flush_list(p)| frees an entire linked list of one-word
  3546  nodes that starts at a given position, until coming to |sentinel| or a
  3547  pointer that is not in the one-word region. Another procedure,
  3548  |flush_node_list|, frees an entire linked list of one-word and two-word
  3549  nodes, until coming to a |null| pointer.
  3550  @^inner loop@>
  3551  
  3552  @p procedure flush_list(@!p:pointer); {makes list of single-word nodes
  3553    available}
  3554  label done;
  3555  var @!q,@!r:pointer; {list traversers}
  3556  begin if p>=hi_mem_min then if p<>sentinel then
  3557    begin r:=p;
  3558    repeat q:=r; r:=link(r); @!stat decr(dyn_used);@+tats@/
  3559    if r<hi_mem_min then goto done;
  3560    until r=sentinel;
  3561    done: {now |q| is the last node on the list}
  3562    link(q):=avail; avail:=p;
  3563    end;
  3564  end;
  3565  @#
  3566  procedure flush_node_list(@!p:pointer);
  3567  var @!q:pointer; {the node being recycled}
  3568  begin while p<>null do
  3569    begin q:=p; p:=link(p);
  3570    if q<hi_mem_min then free_node(q,2)@+else free_avail(q);
  3571    end;
  3572  end;
  3573  
  3574  @ If \MF\ is extended improperly, the |mem| array might get screwed up.
  3575  For example, some pointers might be wrong, or some ``dead'' nodes might not
  3576  have been freed when the last reference to them disappeared. Procedures
  3577  |check_mem| and |search_mem| are available to help diagnose such
  3578  problems. These procedures make use of two arrays called |free| and
  3579  |was_free| that are present only if \MF's debugging routines have
  3580  been included. (You may want to decrease the size of |mem| while you
  3581  @^debugging@>
  3582  are debugging.)
  3583  
  3584  @<Glob...@>=
  3585  @!debug @!free: packed array [mem_min..mem_max] of boolean; {free cells}
  3586  @t\hskip1em@>@!was_free: packed array [mem_min..mem_max] of boolean;
  3587    {previously free cells}
  3588  @t\hskip1em@>@!was_mem_end,@!was_lo_max,@!was_hi_min: pointer;
  3589    {previous |mem_end|, |lo_mem_max|, and |hi_mem_min|}
  3590  @t\hskip1em@>@!panicking:boolean; {do we want to check memory constantly?}
  3591  gubed
  3592  
  3593  @ @<Set initial...@>=
  3594  @!debug was_mem_end:=mem_min; {indicate that everything was previously free}
  3595  was_lo_max:=mem_min; was_hi_min:=mem_max;
  3596  panicking:=false;
  3597  gubed
  3598  
  3599  @ Procedure |check_mem| makes sure that the available space lists of
  3600  |mem| are well formed, and it optionally prints out all locations
  3601  that are reserved now but were free the last time this procedure was called.
  3602  
  3603  @p @!debug procedure check_mem(@!print_locs : boolean);
  3604  label done1,done2; {loop exits}
  3605  var @!p,@!q,@!r:pointer; {current locations of interest in |mem|}
  3606  @!clobbered:boolean; {is something amiss?}
  3607  begin for p:=mem_min to lo_mem_max do free[p]:=false; {you can probably
  3608    do this faster}
  3609  for p:=hi_mem_min to mem_end do free[p]:=false; {ditto}
  3610  @<Check single-word |avail| list@>;
  3611  @<Check variable-size |avail| list@>;
  3612  @<Check flags of unavailable nodes@>;
  3613  @<Check the list of linear dependencies@>;
  3614  if print_locs then @<Print newly busy locations@>;
  3615  for p:=mem_min to lo_mem_max do was_free[p]:=free[p];
  3616  for p:=hi_mem_min to mem_end do was_free[p]:=free[p];
  3617    {|was_free:=free| might be faster}
  3618  was_mem_end:=mem_end; was_lo_max:=lo_mem_max; was_hi_min:=hi_mem_min;
  3619  end;
  3620  gubed
  3621  
  3622  @ @<Check single-word...@>=
  3623  p:=avail; q:=null; clobbered:=false;
  3624  while p<>null do
  3625    begin if (p>mem_end)or(p<hi_mem_min) then clobbered:=true
  3626    else if free[p] then clobbered:=true;
  3627    if clobbered then
  3628      begin print_nl("AVAIL list clobbered at ");
  3629  @.AVAIL list clobbered...@>
  3630      print_int(q); goto done1;
  3631      end;
  3632    free[p]:=true; q:=p; p:=link(q);
  3633    end;
  3634  done1:
  3635  
  3636  @ @<Check variable-size...@>=
  3637  p:=rover; q:=null; clobbered:=false;
  3638  repeat if (p>=lo_mem_max)or(p<mem_min) then clobbered:=true
  3639    else if (rlink(p)>=lo_mem_max)or(rlink(p)<mem_min) then clobbered:=true
  3640    else if  not(is_empty(p))or(node_size(p)<2)or@|
  3641     (p+node_size(p)>lo_mem_max)or@| (llink(rlink(p))<>p) then clobbered:=true;
  3642    if clobbered then
  3643    begin print_nl("Double-AVAIL list clobbered at ");
  3644  @.Double-AVAIL list clobbered...@>
  3645    print_int(q); goto done2;
  3646    end;
  3647  for q:=p to p+node_size(p)-1 do {mark all locations free}
  3648    begin if free[q] then
  3649      begin print_nl("Doubly free location at ");
  3650  @.Doubly free location...@>
  3651      print_int(q); goto done2;
  3652      end;
  3653    free[q]:=true;
  3654    end;
  3655  q:=p; p:=rlink(p);
  3656  until p=rover;
  3657  done2:
  3658  
  3659  @ @<Check flags...@>=
  3660  p:=mem_min;
  3661  while p<=lo_mem_max do {node |p| should not be empty}
  3662    begin if is_empty(p) then
  3663      begin print_nl("Bad flag at "); print_int(p);
  3664  @.Bad flag...@>
  3665      end;
  3666    while (p<=lo_mem_max) and not free[p] do incr(p);
  3667    while (p<=lo_mem_max) and free[p] do incr(p);
  3668    end
  3669  
  3670  @ @<Print newly busy...@>=
  3671  begin print_nl("New busy locs:");
  3672  @.New busy locs@>
  3673  for p:=mem_min to lo_mem_max do
  3674    if not free[p] and ((p>was_lo_max) or was_free[p]) then
  3675      begin print_char(" "); print_int(p);
  3676      end;
  3677  for p:=hi_mem_min to mem_end do
  3678    if not free[p] and
  3679     ((p<was_hi_min) or (p>was_mem_end) or was_free[p]) then
  3680      begin print_char(" "); print_int(p);
  3681      end;
  3682  end
  3683  
  3684  @ The |search_mem| procedure attempts to answer the question ``Who points
  3685  to node~|p|?'' In doing so, it fetches |link| and |info| fields of |mem|
  3686  that might not be of type |two_halves|. Strictly speaking, this is
  3687  @^dirty \PASCAL@>
  3688  undefined in \PASCAL, and it can lead to ``false drops'' (words that seem to
  3689  point to |p| purely by coincidence). But for debugging purposes, we want
  3690  to rule out the places that do {\sl not\/} point to |p|, so a few false
  3691  drops are tolerable.
  3692  
  3693  @p @!debug procedure search_mem(@!p:pointer); {look for pointers to |p|}
  3694  var @!q:integer; {current position being searched}
  3695  begin for q:=mem_min to lo_mem_max do
  3696    begin if link(q)=p then
  3697      begin print_nl("LINK("); print_int(q); print_char(")");
  3698      end;
  3699    if info(q)=p then
  3700      begin print_nl("INFO("); print_int(q); print_char(")");
  3701      end;
  3702    end;
  3703  for q:=hi_mem_min to mem_end do
  3704    begin if link(q)=p then
  3705      begin print_nl("LINK("); print_int(q); print_char(")");
  3706      end;
  3707    if info(q)=p then
  3708      begin print_nl("INFO("); print_int(q); print_char(")");
  3709      end;
  3710    end;
  3711  @<Search |eqtb| for equivalents equal to |p|@>;
  3712  end;
  3713  gubed
  3714  
  3715  @* \[12] The command codes.
  3716  Before we can go much further, we need to define symbolic names for the internal
  3717  code numbers that represent the various commands obeyed by \MF. These codes
  3718  are somewhat arbitrary, but not completely so. For example,
  3719  some codes have been made adjacent so that |case| statements in the
  3720  program need not consider cases that are widely spaced, or so that |case|
  3721  statements can be replaced by |if| statements. A command can begin an
  3722  expression if and only if its code lies between |min_primary_command| and
  3723  |max_primary_command|, inclusive. The first token of a statement that doesn't
  3724  begin with an expression has a command code between |min_command| and
  3725  |max_statement_command|, inclusive. The ordering of the highest-numbered
  3726  commands (|comma<semicolon<end_group<stop|) is crucial for the parsing
  3727  and error-recovery methods of this program.
  3728  
  3729  At any rate, here is the list, for future reference.
  3730  
  3731  @d if_test=1 {conditional text (\&{if})}
  3732  @d fi_or_else=2 {delimiters for conditionals (\&{elseif}, \&{else}, \&{fi})}
  3733  @d input=3 {input a source file (\&{input}, \&{endinput})}
  3734  @d iteration=4 {iterate (\&{for}, \&{forsuffixes}, \&{forever}, \&{endfor})}
  3735  @d repeat_loop=5 {special command substituted for \&{endfor}}
  3736  @d exit_test=6 {premature exit from a loop (\&{exitif})}
  3737  @d relax=7 {do nothing (\.{\char`\\})}
  3738  @d scan_tokens=8 {put a string into the input buffer}
  3739  @d expand_after=9 {look ahead one token}
  3740  @d defined_macro=10 {a macro defined by the user}
  3741  @d min_command=defined_macro+1
  3742  @d display_command=11 {online graphic output (\&{display})}
  3743  @d save_command=12 {save a list of tokens (\&{save})}
  3744  @d interim_command=13 {save an internal quantity (\&{interim})}
  3745  @d let_command=14 {redefine a symbolic token (\&{let})}
  3746  @d new_internal=15 {define a new internal quantity (\&{newinternal})}
  3747  @d macro_def=16 {define a macro (\&{def}, \&{vardef}, etc.)}
  3748  @d ship_out_command=17 {output a character (\&{shipout})}
  3749  @d add_to_command=18 {add to edges (\&{addto})}
  3750  @d cull_command=19 {cull and normalize edges (\&{cull})}
  3751  @d tfm_command=20 {command for font metric info (\&{ligtable}, etc.)}
  3752  @d protection_command=21 {set protection flag (\&{outer}, \&{inner})}
  3753  @d show_command=22 {diagnostic output (\&{show}, \&{showvariable}, etc.)}
  3754  @d mode_command=23 {set interaction level (\&{batchmode}, etc.)}
  3755  @d random_seed=24 {initialize random number generator (\&{randomseed})}
  3756  @d message_command=25 {communicate to user (\&{message}, \&{errmessage})}
  3757  @d every_job_command=26 {designate a starting token (\&{everyjob})}
  3758  @d delimiters=27 {define a pair of delimiters (\&{delimiters})}
  3759  @d open_window=28 {define a window on the screen (\&{openwindow})}
  3760  @d special_command=29 {output special info (\&{special}, \&{numspecial})}
  3761  @d type_name=30 {declare a type (\&{numeric}, \&{pair}, etc.)}
  3762  @d max_statement_command=type_name
  3763  @d min_primary_command=type_name
  3764  @d left_delimiter=31 {the left delimiter of a matching pair}
  3765  @d begin_group=32 {beginning of a group (\&{begingroup})}
  3766  @d nullary=33 {an operator without arguments (e.g., \&{normaldeviate})}
  3767  @d unary=34 {an operator with one argument (e.g., \&{sqrt})}
  3768  @d str_op=35 {convert a suffix to a string (\&{str})}
  3769  @d cycle=36 {close a cyclic path (\&{cycle})}
  3770  @d primary_binary=37 {binary operation taking `\&{of}' (e.g., \&{point})}
  3771  @d capsule_token=38 {a value that has been put into a token list}
  3772  @d string_token=39 {a string constant (e.g., |"hello"|)}
  3773  @d internal_quantity=40 {internal numeric parameter (e.g., \&{pausing})}
  3774  @d min_suffix_token=internal_quantity
  3775  @d tag_token=41 {a symbolic token without a primitive meaning}
  3776  @d numeric_token=42 {a numeric constant (e.g., \.{3.14159})}
  3777  @d max_suffix_token=numeric_token
  3778  @d plus_or_minus=43 {either `\.+' or `\.-'}
  3779  @d max_primary_command=plus_or_minus {should also be |numeric_token+1|}
  3780  @d min_tertiary_command=plus_or_minus
  3781  @d tertiary_secondary_macro=44 {a macro defined by \&{secondarydef}}
  3782  @d tertiary_binary=45 {an operator at the tertiary level (e.g., `\.{++}')}
  3783  @d max_tertiary_command=tertiary_binary
  3784  @d left_brace=46 {the operator `\.{\char`\{}'}
  3785  @d min_expression_command=left_brace
  3786  @d path_join=47 {the operator `\.{..}'}
  3787  @d ampersand=48 {the operator `\.\&'}
  3788  @d expression_tertiary_macro=49 {a macro defined by \&{tertiarydef}}
  3789  @d expression_binary=50 {an operator at the expression level (e.g., `\.<')}
  3790  @d equals=51 {the operator `\.='}
  3791  @d max_expression_command=equals
  3792  @d and_command=52 {the operator `\&{and}'}
  3793  @d min_secondary_command=and_command
  3794  @d secondary_primary_macro=53 {a macro defined by \&{primarydef}}
  3795  @d slash=54 {the operator `\./'}
  3796  @d secondary_binary=55 {an operator at the binary level (e.g., \&{shifted})}
  3797  @d max_secondary_command=secondary_binary
  3798  @d param_type=56 {type of parameter (\&{primary}, \&{expr}, \&{suffix}, etc.)}
  3799  @d controls=57 {specify control points explicitly (\&{controls})}
  3800  @d tension=58 {specify tension between knots (\&{tension})}
  3801  @d at_least=59 {bounded tension value (\&{atleast})}
  3802  @d curl_command=60 {specify curl at an end knot (\&{curl})}
  3803  @d macro_special=61 {special macro operators (\&{quote}, \.{\#\AT!}, etc.)}
  3804  @d right_delimiter=62 {the right delimiter of a matching pair}
  3805  @d left_bracket=63 {the operator `\.['}
  3806  @d right_bracket=64 {the operator `\.]'}
  3807  @d right_brace=65 {the operator `\.{\char`\}}'}
  3808  @d with_option=66 {option for filling (\&{withpen}, \&{withweight})}
  3809  @d cull_op=67 {the operator `\&{keeping}' or `\&{dropping}'}
  3810  @d thing_to_add=68
  3811    {variant of \&{addto} (\&{contour}, \&{doublepath}, \&{also})}
  3812  @d of_token=69 {the operator `\&{of}'}
  3813  @d from_token=70 {the operator `\&{from}'}
  3814  @d to_token=71 {the operator `\&{to}'}
  3815  @d at_token=72 {the operator `\&{at}'}
  3816  @d in_window=73 {the operator `\&{inwindow}'}
  3817  @d step_token=74 {the operator `\&{step}'}
  3818  @d until_token=75 {the operator `\&{until}'}
  3819  @d lig_kern_token=76
  3820    {the operators `\&{kern}' and `\.{=:}' and `\.{=:\char'174}', etc.}
  3821  @d assignment=77 {the operator `\.{:=}'}
  3822  @d skip_to=78 {the operation `\&{skipto}'}
  3823  @d bchar_label=79 {the operator `\.{\char'174\char'174:}'}
  3824  @d double_colon=80 {the operator `\.{::}'}
  3825  @d colon=81 {the operator `\.:'}
  3826  @#
  3827  @d comma=82 {the operator `\.,', must be |colon+1|}
  3828  @d end_of_statement==cur_cmd>comma
  3829  @d semicolon=83 {the operator `\.;', must be |comma+1|}
  3830  @d end_group=84 {end a group (\&{endgroup}), must be |semicolon+1|}
  3831  @d stop=85 {end a job (\&{end}, \&{dump}), must be |end_group+1|}
  3832  @d max_command_code=stop
  3833  @d outer_tag=max_command_code+1 {protection code added to command code}
  3834  
  3835  @<Types...@>=
  3836  @!command_code=1..max_command_code;
  3837  
  3838  @ Variables and capsules in \MF\ have a variety of ``types,''
  3839  distinguished by the following code numbers:
  3840  
  3841  @d undefined=0 {no type has been declared}
  3842  @d unknown_tag=1 {this constant is added to certain type codes below}
  3843  @d vacuous=1 {no expression was present}
  3844  @d boolean_type=2 {\&{boolean} with a known value}
  3845  @d unknown_boolean=boolean_type+unknown_tag
  3846  @d string_type=4 {\&{string} with a known value}
  3847  @d unknown_string=string_type+unknown_tag
  3848  @d pen_type=6 {\&{pen} with a known value}
  3849  @d unknown_pen=pen_type+unknown_tag
  3850  @d future_pen=8 {subexpression that will become a \&{pen} at a higher level}
  3851  @d path_type=9 {\&{path} with a known value}
  3852  @d unknown_path=path_type+unknown_tag
  3853  @d picture_type=11 {\&{picture} with a known value}
  3854  @d unknown_picture=picture_type+unknown_tag
  3855  @d transform_type=13 {\&{transform} variable or capsule}
  3856  @d pair_type=14 {\&{pair} variable or capsule}
  3857  @d numeric_type=15 {variable that has been declared \&{numeric} but not used}
  3858  @d known=16 {\&{numeric} with a known value}
  3859  @d dependent=17 {a linear combination with |fraction| coefficients}
  3860  @d proto_dependent=18 {a linear combination with |scaled| coefficients}
  3861  @d independent=19 {\&{numeric} with unknown value}
  3862  @d token_list=20 {variable name or suffix argument or text argument}
  3863  @d structured=21 {variable with subscripts and attributes}
  3864  @d unsuffixed_macro=22 {variable defined with \&{vardef} but no \.{\AT!\#}}
  3865  @d suffixed_macro=23 {variable defined with \&{vardef} and \.{\AT!\#}}
  3866  @#
  3867  @d unknown_types==unknown_boolean,unknown_string,
  3868    unknown_pen,unknown_picture,unknown_path
  3869  
  3870  @<Basic printing procedures@>=
  3871  procedure print_type(@!t:small_number);
  3872  begin case t of
  3873  vacuous:print("vacuous");
  3874  boolean_type:print("boolean");
  3875  unknown_boolean:print("unknown boolean");
  3876  string_type:print("string");
  3877  unknown_string:print("unknown string");
  3878  pen_type:print("pen");
  3879  unknown_pen:print("unknown pen");
  3880  future_pen:print("future pen");
  3881  path_type:print("path");
  3882  unknown_path:print("unknown path");
  3883  picture_type:print("picture");
  3884  unknown_picture:print("unknown picture");
  3885  transform_type:print("transform");
  3886  pair_type:print("pair");
  3887  known:print("known numeric");
  3888  dependent:print("dependent");
  3889  proto_dependent:print("proto-dependent");
  3890  numeric_type:print("numeric");
  3891  independent:print("independent");
  3892  token_list:print("token list");
  3893  structured:print("structured");
  3894  unsuffixed_macro:print("unsuffixed macro");
  3895  suffixed_macro:print("suffixed macro");
  3896  othercases print("undefined")
  3897  endcases;
  3898  end;
  3899  
  3900  @ Values inside \MF\ are stored in two-word nodes that have a |name_type|
  3901  as well as a |type|. The possibilities for |name_type| are defined
  3902  here; they will be explained in more detail later.
  3903  
  3904  @d root=0 {|name_type| at the top level of a variable}
  3905  @d saved_root=1 {same, when the variable has been saved}
  3906  @d structured_root=2 {|name_type| where a |structured| branch occurs}
  3907  @d subscr=3 {|name_type| in a subscript node}
  3908  @d attr=4 {|name_type| in an attribute node}
  3909  @d x_part_sector=5 {|name_type| in the \&{xpart} of a node}
  3910  @d y_part_sector=6 {|name_type| in the \&{ypart} of a node}
  3911  @d xx_part_sector=7 {|name_type| in the \&{xxpart} of a node}
  3912  @d xy_part_sector=8 {|name_type| in the \&{xypart} of a node}
  3913  @d yx_part_sector=9 {|name_type| in the \&{yxpart} of a node}
  3914  @d yy_part_sector=10 {|name_type| in the \&{yypart} of a node}
  3915  @d capsule=11 {|name_type| in stashed-away subexpressions}
  3916  @d token=12 {|name_type| in a numeric token or string token}
  3917  
  3918  @ Primitive operations that produce values have a secondary identification
  3919  code in addition to their command code; it's something like genera and species.
  3920  For example, `\.*' has the command code |primary_binary|, and its
  3921  secondary identification is |times|. The secondary codes start at 30 so that
  3922  they don't overlap with the type codes; some type codes (e.g., |string_type|)
  3923  are used as operators as well as type identifications.
  3924  
  3925  @d true_code=30 {operation code for \.{true}}
  3926  @d false_code=31 {operation code for \.{false}}
  3927  @d null_picture_code=32 {operation code for \.{nullpicture}}
  3928  @d null_pen_code=33 {operation code for \.{nullpen}}
  3929  @d job_name_op=34 {operation code for \.{jobname}}
  3930  @d read_string_op=35 {operation code for \.{readstring}}
  3931  @d pen_circle=36 {operation code for \.{pencircle}}
  3932  @d normal_deviate=37 {operation code for \.{normaldeviate}}
  3933  @d odd_op=38 {operation code for \.{odd}}
  3934  @d known_op=39 {operation code for \.{known}}
  3935  @d unknown_op=40 {operation code for \.{unknown}}
  3936  @d not_op=41 {operation code for \.{not}}
  3937  @d decimal=42 {operation code for \.{decimal}}
  3938  @d reverse=43 {operation code for \.{reverse}}
  3939  @d make_path_op=44 {operation code for \.{makepath}}
  3940  @d make_pen_op=45 {operation code for \.{makepen}}
  3941  @d total_weight_op=46 {operation code for \.{totalweight}}
  3942  @d oct_op=47 {operation code for \.{oct}}
  3943  @d hex_op=48 {operation code for \.{hex}}
  3944  @d ASCII_op=49 {operation code for \.{ASCII}}
  3945  @d char_op=50 {operation code for \.{char}}
  3946  @d length_op=51 {operation code for \.{length}}
  3947  @d turning_op=52 {operation code for \.{turningnumber}}
  3948  @d x_part=53 {operation code for \.{xpart}}
  3949  @d y_part=54 {operation code for \.{ypart}}
  3950  @d xx_part=55 {operation code for \.{xxpart}}
  3951  @d xy_part=56 {operation code for \.{xypart}}
  3952  @d yx_part=57 {operation code for \.{yxpart}}
  3953  @d yy_part=58 {operation code for \.{yypart}}
  3954  @d sqrt_op=59 {operation code for \.{sqrt}}
  3955  @d m_exp_op=60 {operation code for \.{mexp}}
  3956  @d m_log_op=61 {operation code for \.{mlog}}
  3957  @d sin_d_op=62 {operation code for \.{sind}}
  3958  @d cos_d_op=63 {operation code for \.{cosd}}
  3959  @d floor_op=64 {operation code for \.{floor}}
  3960  @d uniform_deviate=65 {operation code for \.{uniformdeviate}}
  3961  @d char_exists_op=66 {operation code for \.{charexists}}
  3962  @d angle_op=67 {operation code for \.{angle}}
  3963  @d cycle_op=68 {operation code for \.{cycle}}
  3964  @d plus=69 {operation code for \.+}
  3965  @d minus=70 {operation code for \.-}
  3966  @d times=71 {operation code for \.*}
  3967  @d over=72 {operation code for \./}
  3968  @d pythag_add=73 {operation code for \.{++}}
  3969  @d pythag_sub=74 {operation code for \.{+-+}}
  3970  @d or_op=75 {operation code for \.{or}}
  3971  @d and_op=76 {operation code for \.{and}}
  3972  @d less_than=77 {operation code for \.<}
  3973  @d less_or_equal=78 {operation code for \.{<=}}
  3974  @d greater_than=79 {operation code for \.>}
  3975  @d greater_or_equal=80 {operation code for \.{>=}}
  3976  @d equal_to=81 {operation code for \.=}
  3977  @d unequal_to=82 {operation code for \.{<>}}
  3978  @d concatenate=83 {operation code for \.\&}
  3979  @d rotated_by=84 {operation code for \.{rotated}}
  3980  @d slanted_by=85 {operation code for \.{slanted}}
  3981  @d scaled_by=86 {operation code for \.{scaled}}
  3982  @d shifted_by=87 {operation code for \.{shifted}}
  3983  @d transformed_by=88 {operation code for \.{transformed}}
  3984  @d x_scaled=89 {operation code for \.{xscaled}}
  3985  @d y_scaled=90 {operation code for \.{yscaled}}
  3986  @d z_scaled=91 {operation code for \.{zscaled}}
  3987  @d intersect=92 {operation code for \.{intersectiontimes}}
  3988  @d double_dot=93 {operation code for improper \.{..}}
  3989  @d substring_of=94 {operation code for \.{substring}}
  3990  @d min_of=substring_of
  3991  @d subpath_of=95 {operation code for \.{subpath}}
  3992  @d direction_time_of=96 {operation code for \.{directiontime}}
  3993  @d point_of=97 {operation code for \.{point}}
  3994  @d precontrol_of=98 {operation code for \.{precontrol}}
  3995  @d postcontrol_of=99 {operation code for \.{postcontrol}}
  3996  @d pen_offset_of=100 {operation code for \.{penoffset}}
  3997  
  3998  @p procedure print_op(@!c:quarterword);
  3999  begin if c<=numeric_type then print_type(c)
  4000  else case c of
  4001  true_code:print("true");
  4002  false_code:print("false");
  4003  null_picture_code:print("nullpicture");
  4004  null_pen_code:print("nullpen");
  4005  job_name_op:print("jobname");
  4006  read_string_op:print("readstring");
  4007  pen_circle:print("pencircle");
  4008  normal_deviate:print("normaldeviate");
  4009  odd_op:print("odd");
  4010  known_op:print("known");
  4011  unknown_op:print("unknown");
  4012  not_op:print("not");
  4013  decimal:print("decimal");
  4014  reverse:print("reverse");
  4015  make_path_op:print("makepath");
  4016  make_pen_op:print("makepen");
  4017  total_weight_op:print("totalweight");
  4018  oct_op:print("oct");
  4019  hex_op:print("hex");
  4020  ASCII_op:print("ASCII");
  4021  char_op:print("char");
  4022  length_op:print("length");
  4023  turning_op:print("turningnumber");
  4024  x_part:print("xpart");
  4025  y_part:print("ypart");
  4026  xx_part:print("xxpart");
  4027  xy_part:print("xypart");
  4028  yx_part:print("yxpart");
  4029  yy_part:print("yypart");
  4030  sqrt_op:print("sqrt");
  4031  m_exp_op:print("mexp");
  4032  m_log_op:print("mlog");
  4033  sin_d_op:print("sind");
  4034  cos_d_op:print("cosd");
  4035  floor_op:print("floor");
  4036  uniform_deviate:print("uniformdeviate");
  4037  char_exists_op:print("charexists");
  4038  angle_op:print("angle");
  4039  cycle_op:print("cycle");
  4040  plus:print_char("+");
  4041  minus:print_char("-");
  4042  times:print_char("*");
  4043  over:print_char("/");
  4044  pythag_add:print("++");
  4045  pythag_sub:print("+-+");
  4046  or_op:print("or");
  4047  and_op:print("and");
  4048  less_than:print_char("<");
  4049  less_or_equal:print("<=");
  4050  greater_than:print_char(">");
  4051  greater_or_equal:print(">=");
  4052  equal_to:print_char("=");
  4053  unequal_to:print("<>");
  4054  concatenate:print("&");
  4055  rotated_by:print("rotated");
  4056  slanted_by:print("slanted");
  4057  scaled_by:print("scaled");
  4058  shifted_by:print("shifted");
  4059  transformed_by:print("transformed");
  4060  x_scaled:print("xscaled");
  4061  y_scaled:print("yscaled");
  4062  z_scaled:print("zscaled");
  4063  intersect:print("intersectiontimes");
  4064  substring_of:print("substring");
  4065  subpath_of:print("subpath");
  4066  direction_time_of:print("directiontime");
  4067  point_of:print("point");
  4068  precontrol_of:print("precontrol");
  4069  postcontrol_of:print("postcontrol");
  4070  pen_offset_of:print("penoffset");
  4071  othercases print("..")
  4072  endcases;
  4073  end;
  4074  
  4075  @ \MF\ also has a bunch of internal parameters that a user might want to
  4076  fuss with. Every such parameter has an identifying code number, defined here.
  4077  
  4078  @d tracing_titles=1 {show titles online when they appear}
  4079  @d tracing_equations=2 {show each variable when it becomes known}
  4080  @d tracing_capsules=3 {show capsules too}
  4081  @d tracing_choices=4 {show the control points chosen for paths}
  4082  @d tracing_specs=5 {show subdivision of paths into octants before digitizing}
  4083  @d tracing_pens=6 {show details of pens that are made}
  4084  @d tracing_commands=7 {show commands and operations before they are performed}
  4085  @d tracing_restores=8 {show when a variable or internal is restored}
  4086  @d tracing_macros=9 {show macros before they are expanded}
  4087  @d tracing_edges=10 {show digitized edges as they are computed}
  4088  @d tracing_output=11 {show digitized edges as they are output}
  4089  @d tracing_stats=12 {show memory usage at end of job}
  4090  @d tracing_online=13 {show long diagnostics on terminal and in the log file}
  4091  @d year=14 {the current year (e.g., 1984)}
  4092  @d month=15 {the current month (e.g., 3 $\equiv$ March)}
  4093  @d day=16 {the current day of the month}
  4094  @d time=17 {the number of minutes past midnight when this job started}
  4095  @d char_code=18 {the number of the next character to be output}
  4096  @d char_ext=19 {the extension code of the next character to be output}
  4097  @d char_wd=20 {the width of the next character to be output}
  4098  @d char_ht=21 {the height of the next character to be output}
  4099  @d char_dp=22 {the depth of the next character to be output}
  4100  @d char_ic=23 {the italic correction of the next character to be output}
  4101  @d char_dx=24 {the device's $x$ movement for the next character, in pixels}
  4102  @d char_dy=25 {the device's $y$ movement for the next character, in pixels}
  4103  @d design_size=26 {the unit of measure used for |char_wd..char_ic|, in points}
  4104  @d hppp=27 {the number of horizontal pixels per point}
  4105  @d vppp=28 {the number of vertical pixels per point}
  4106  @d x_offset=29 {horizontal displacement of shipped-out characters}
  4107  @d y_offset=30 {vertical displacement of shipped-out characters}
  4108  @d pausing=31 {positive to display lines on the terminal before they are read}
  4109  @d showstopping=32 {positive to stop after each \&{show} command}
  4110  @d fontmaking=33 {positive if font metric output is to be produced}
  4111  @d proofing=34 {positive for proof mode, negative to suppress output}
  4112  @d smoothing=35 {positive if moves are to be ``smoothed''}
  4113  @d autorounding=36 {controls path modification to ``good'' points}
  4114  @d granularity=37 {autorounding uses this pixel size}
  4115  @d fillin=38 {extra darkness of diagonal lines}
  4116  @d turning_check=39 {controls reorientation of clockwise paths}
  4117  @d warning_check=40 {controls error message when variable value is large}
  4118  @d boundary_char=41 {the boundary character for ligatures}
  4119  @d max_given_internal=41
  4120  
  4121  @<Glob...@>=
  4122  @!internal:array[1..max_internal] of scaled;
  4123    {the values of internal quantities}
  4124  @!int_name:array[1..max_internal] of str_number;
  4125    {their names}
  4126  @!int_ptr:max_given_internal..max_internal;
  4127    {the maximum internal quantity defined so far}
  4128  
  4129  @ @<Set init...@>=
  4130  for k:=1 to max_given_internal do internal[k]:=0;
  4131  int_ptr:=max_given_internal;
  4132  
  4133  @ The symbolic names for internal quantities are put into \MF's hash table
  4134  by using a routine called |primitive|, which will be defined later. Let us
  4135  enter them now, so that we don't have to list all those names again
  4136  anywhere else.
  4137  
  4138  @<Put each of \MF's primitives into the hash table@>=
  4139  primitive("tracingtitles",internal_quantity,tracing_titles);@/
  4140  @!@:tracingtitles_}{\&{tracingtitles} primitive@>
  4141  primitive("tracingequations",internal_quantity,tracing_equations);@/
  4142  @!@:tracing_equations_}{\&{tracingequations} primitive@>
  4143  primitive("tracingcapsules",internal_quantity,tracing_capsules);@/
  4144  @!@:tracing_capsules_}{\&{tracingcapsules} primitive@>
  4145  primitive("tracingchoices",internal_quantity,tracing_choices);@/
  4146  @!@:tracing_choices_}{\&{tracingchoices} primitive@>
  4147  primitive("tracingspecs",internal_quantity,tracing_specs);@/
  4148  @!@:tracing_specs_}{\&{tracingspecs} primitive@>
  4149  primitive("tracingpens",internal_quantity,tracing_pens);@/
  4150  @!@:tracing_pens_}{\&{tracingpens} primitive@>
  4151  primitive("tracingcommands",internal_quantity,tracing_commands);@/
  4152  @!@:tracing_commands_}{\&{tracingcommands} primitive@>
  4153  primitive("tracingrestores",internal_quantity,tracing_restores);@/
  4154  @!@:tracing_restores_}{\&{tracingrestores} primitive@>
  4155  primitive("tracingmacros",internal_quantity,tracing_macros);@/
  4156  @!@:tracing_macros_}{\&{tracingmacros} primitive@>
  4157  primitive("tracingedges",internal_quantity,tracing_edges);@/
  4158  @!@:tracing_edges_}{\&{tracingedges} primitive@>
  4159  primitive("tracingoutput",internal_quantity,tracing_output);@/
  4160  @!@:tracing_output_}{\&{tracingoutput} primitive@>
  4161  primitive("tracingstats",internal_quantity,tracing_stats);@/
  4162  @!@:tracing_stats_}{\&{tracingstats} primitive@>
  4163  primitive("tracingonline",internal_quantity,tracing_online);@/
  4164  @!@:tracing_online_}{\&{tracingonline} primitive@>
  4165  primitive("year",internal_quantity,year);@/
  4166  @!@:year_}{\&{year} primitive@>
  4167  primitive("month",internal_quantity,month);@/
  4168  @!@:month_}{\&{month} primitive@>
  4169  primitive("day",internal_quantity,day);@/
  4170  @!@:day_}{\&{day} primitive@>
  4171  primitive("time",internal_quantity,time);@/
  4172  @!@:time_}{\&{time} primitive@>
  4173  primitive("charcode",internal_quantity,char_code);@/
  4174  @!@:char_code_}{\&{charcode} primitive@>
  4175  primitive("charext",internal_quantity,char_ext);@/
  4176  @!@:char_ext_}{\&{charext} primitive@>
  4177  primitive("charwd",internal_quantity,char_wd);@/
  4178  @!@:char_wd_}{\&{charwd} primitive@>
  4179  primitive("charht",internal_quantity,char_ht);@/
  4180  @!@:char_ht_}{\&{charht} primitive@>
  4181  primitive("chardp",internal_quantity,char_dp);@/
  4182  @!@:char_dp_}{\&{chardp} primitive@>
  4183  primitive("charic",internal_quantity,char_ic);@/
  4184  @!@:char_ic_}{\&{charic} primitive@>
  4185  primitive("chardx",internal_quantity,char_dx);@/
  4186  @!@:char_dx_}{\&{chardx} primitive@>
  4187  primitive("chardy",internal_quantity,char_dy);@/
  4188  @!@:char_dy_}{\&{chardy} primitive@>
  4189  primitive("designsize",internal_quantity,design_size);@/
  4190  @!@:design_size_}{\&{designsize} primitive@>
  4191  primitive("hppp",internal_quantity,hppp);@/
  4192  @!@:hppp_}{\&{hppp} primitive@>
  4193  primitive("vppp",internal_quantity,vppp);@/
  4194  @!@:vppp_}{\&{vppp} primitive@>
  4195  primitive("xoffset",internal_quantity,x_offset);@/
  4196  @!@:x_offset_}{\&{xoffset} primitive@>
  4197  primitive("yoffset",internal_quantity,y_offset);@/
  4198  @!@:y_offset_}{\&{yoffset} primitive@>
  4199  primitive("pausing",internal_quantity,pausing);@/
  4200  @!@:pausing_}{\&{pausing} primitive@>
  4201  primitive("showstopping",internal_quantity,showstopping);@/
  4202  @!@:showstopping_}{\&{showstopping} primitive@>
  4203  primitive("fontmaking",internal_quantity,fontmaking);@/
  4204  @!@:fontmaking_}{\&{fontmaking} primitive@>
  4205  primitive("proofing",internal_quantity,proofing);@/
  4206  @!@:proofing_}{\&{proofing} primitive@>
  4207  primitive("smoothing",internal_quantity,smoothing);@/
  4208  @!@:smoothing_}{\&{smoothing} primitive@>
  4209  primitive("autorounding",internal_quantity,autorounding);@/
  4210  @!@:autorounding_}{\&{autorounding} primitive@>
  4211  primitive("granularity",internal_quantity,granularity);@/
  4212  @!@:granularity_}{\&{granularity} primitive@>
  4213  primitive("fillin",internal_quantity,fillin);@/
  4214  @!@:fillin_}{\&{fillin} primitive@>
  4215  primitive("turningcheck",internal_quantity,turning_check);@/
  4216  @!@:turning_check_}{\&{turningcheck} primitive@>
  4217  primitive("warningcheck",internal_quantity,warning_check);@/
  4218  @!@:warning_check_}{\&{warningcheck} primitive@>
  4219  primitive("boundarychar",internal_quantity,boundary_char);@/
  4220  @!@:boundary_char_}{\&{boundarychar} primitive@>
  4221  
  4222  @ Well, we do have to list the names one more time, for use in symbolic
  4223  printouts.
  4224  
  4225  @<Initialize table...@>=
  4226  int_name[tracing_titles]:="tracingtitles";
  4227  int_name[tracing_equations]:="tracingequations";
  4228  int_name[tracing_capsules]:="tracingcapsules";
  4229  int_name[tracing_choices]:="tracingchoices";
  4230  int_name[tracing_specs]:="tracingspecs";
  4231  int_name[tracing_pens]:="tracingpens";
  4232  int_name[tracing_commands]:="tracingcommands";
  4233  int_name[tracing_restores]:="tracingrestores";
  4234  int_name[tracing_macros]:="tracingmacros";
  4235  int_name[tracing_edges]:="tracingedges";
  4236  int_name[tracing_output]:="tracingoutput";
  4237  int_name[tracing_stats]:="tracingstats";
  4238  int_name[tracing_online]:="tracingonline";
  4239  int_name[year]:="year";
  4240  int_name[month]:="month";
  4241  int_name[day]:="day";
  4242  int_name[time]:="time";
  4243  int_name[char_code]:="charcode";
  4244  int_name[char_ext]:="charext";
  4245  int_name[char_wd]:="charwd";
  4246  int_name[char_ht]:="charht";
  4247  int_name[char_dp]:="chardp";
  4248  int_name[char_ic]:="charic";
  4249  int_name[char_dx]:="chardx";
  4250  int_name[char_dy]:="chardy";
  4251  int_name[design_size]:="designsize";
  4252  int_name[hppp]:="hppp";
  4253  int_name[vppp]:="vppp";
  4254  int_name[x_offset]:="xoffset";
  4255  int_name[y_offset]:="yoffset";
  4256  int_name[pausing]:="pausing";
  4257  int_name[showstopping]:="showstopping";
  4258  int_name[fontmaking]:="fontmaking";
  4259  int_name[proofing]:="proofing";
  4260  int_name[smoothing]:="smoothing";
  4261  int_name[autorounding]:="autorounding";
  4262  int_name[granularity]:="granularity";
  4263  int_name[fillin]:="fillin";
  4264  int_name[turning_check]:="turningcheck";
  4265  int_name[warning_check]:="warningcheck";
  4266  int_name[boundary_char]:="boundarychar";
  4267  
  4268  @ The following procedure, which is called just before \MF\ initializes its
  4269  input and output, establishes the initial values of the date and time.
  4270  @^system dependencies@>
  4271  Since standard \PASCAL\ cannot provide such information, something special
  4272  is needed. The program here simply assumes that suitable values appear in
  4273  the global variables \\{sys\_time}, \\{sys\_day}, \\{sys\_month}, and
  4274  \\{sys\_year} (which are initialized to noon on 4 July 1776,
  4275  in case the implementor is careless).
  4276  
  4277  Note that the values are |scaled| integers. Hence \MF\ can no longer
  4278  be used after the year 32767.
  4279  
  4280  @p procedure fix_date_and_time;
  4281  begin sys_time:=12*60;
  4282  sys_day:=4; sys_month:=7; sys_year:=1776;  {self-evident truths}
  4283  internal[time]:=sys_time*unity; {minutes since midnight}
  4284  internal[day]:=sys_day*unity; {day of the month}
  4285  internal[month]:=sys_month*unity; {month of the year}
  4286  internal[year]:=sys_year*unity; {Anno Domini}
  4287  end;
  4288  
  4289  @ \MF\ is occasionally supposed to print diagnostic information that
  4290  goes only into the transcript file, unless |tracing_online| is positive.
  4291  Now that we have defined |tracing_online| we can define
  4292  two routines that adjust the destination of print commands:
  4293  
  4294  @<Basic printing...@>=
  4295  procedure begin_diagnostic; {prepare to do some tracing}
  4296  begin old_setting:=selector;
  4297  if(internal[tracing_online]<=0)and(selector=term_and_log) then
  4298    begin decr(selector);
  4299    if history=spotless then history:=warning_issued;
  4300    end;
  4301  end;
  4302  @#
  4303  procedure end_diagnostic(@!blank_line:boolean);
  4304    {restore proper conditions after tracing}
  4305  begin print_nl("");
  4306  if blank_line then print_ln;
  4307  selector:=old_setting;
  4308  end;
  4309  
  4310  @ Of course we had better declare a few more global variables, if the previous
  4311  routines are going to work.
  4312  
  4313  @<Glob...@>=
  4314  @!old_setting:0..max_selector;
  4315  @!sys_time,@!sys_day,@!sys_month,@!sys_year:integer;
  4316      {date and time supplied by external system}
  4317  
  4318  @ We will occasionally use |begin_diagnostic| in connection with line-number
  4319  printing, as follows. (The parameter |s| is typically |"Path"| or
  4320  |"Cycle spec"|, etc.)
  4321  
  4322  @<Basic printing...@>=
  4323  procedure print_diagnostic(@!s,@!t:str_number;@!nuline:boolean);
  4324  begin begin_diagnostic;
  4325  if nuline then print_nl(s)@+else print(s);
  4326  print(" at line "); print_int(line);
  4327  print(t); print_char(":");
  4328  end;
  4329  
  4330  @ The 256 |ASCII_code| characters are grouped into classes by means of
  4331  the |char_class| table. Individual class numbers have no semantic
  4332  or syntactic significance, except in a few instances defined here.
  4333  There's also |max_class|, which can be used as a basis for additional
  4334  class numbers in nonstandard extensions of \MF.
  4335  
  4336  @d digit_class=0 {the class number of \.{0123456789}}
  4337  @d period_class=1 {the class number of `\..'}
  4338  @d space_class=2 {the class number of spaces and nonstandard characters}
  4339  @d percent_class=3 {the class number of `\.\%'}
  4340  @d string_class=4 {the class number of `\."'}
  4341  @d right_paren_class=8 {the class number of `\.)'}
  4342  @d isolated_classes==5,6,7,8 {characters that make length-one tokens only}
  4343  @d letter_class=9 {letters and the underline character}
  4344  @d left_bracket_class=17 {`\.['}
  4345  @d right_bracket_class=18 {`\.]'}
  4346  @d invalid_class=20 {bad character in the input}
  4347  @d max_class=20 {the largest class number}
  4348  
  4349  @<Glob...@>=
  4350  @!char_class:array[ASCII_code] of 0..max_class; {the class numbers}
  4351  
  4352  @ If changes are made to accommodate non-ASCII character sets, they should
  4353  follow the guidelines in Appendix~C of {\sl The {\logos METAFONT\/}book}.
  4354  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
  4355  @^system dependencies@>
  4356  
  4357  @<Set init...@>=
  4358  for k:="0" to "9" do char_class[k]:=digit_class;
  4359  char_class["."]:=period_class;
  4360  char_class[" "]:=space_class;
  4361  char_class["%"]:=percent_class;
  4362  char_class[""""]:=string_class;@/
  4363  char_class[","]:=5;
  4364  char_class[";"]:=6;
  4365  char_class["("]:=7;
  4366  char_class[")"]:=right_paren_class;
  4367  for k:="A" to "Z" do char_class[k]:=letter_class;
  4368  for k:="a" to "z" do char_class[k]:=letter_class;
  4369  char_class["_"]:=letter_class;@/
  4370  char_class["<"]:=10;
  4371  char_class["="]:=10;
  4372  char_class[">"]:=10;
  4373  char_class[":"]:=10;
  4374  char_class["|"]:=10;@/
  4375  char_class["`"]:=11;
  4376  char_class["'"]:=11;@/
  4377  char_class["+"]:=12;
  4378  char_class["-"]:=12;@/
  4379  char_class["/"]:=13;
  4380  char_class["*"]:=13;
  4381  char_class["\"]:=13;@/
  4382  char_class["!"]:=14;
  4383  char_class["?"]:=14;@/
  4384  char_class["#"]:=15;
  4385  char_class["&"]:=15;
  4386  char_class["@@"]:=15;
  4387  char_class["$"]:=15;@/
  4388  char_class["^"]:=16;
  4389  char_class["~"]:=16;@/
  4390  char_class["["]:=left_bracket_class;
  4391  char_class["]"]:=right_bracket_class;@/
  4392  char_class["{"]:=19;
  4393  char_class["}"]:=19;@/
  4394  for k:=0 to " "-1 do char_class[k]:=invalid_class;
  4395  for k:=127 to 255 do char_class[k]:=invalid_class;
  4396  
  4397  @* \[13] The hash table.
  4398  Symbolic tokens are stored and retrieved by means of a fairly standard hash
  4399  table algorithm called the method of ``coalescing lists'' (cf.\ Algorithm 6.4C
  4400  in {\sl The Art of Computer Programming\/}). Once a symbolic token enters the
  4401  table, it is never removed.
  4402  
  4403  The actual sequence of characters forming a symbolic token is
  4404  stored in the |str_pool| array together with all the other strings. An
  4405  auxiliary array |hash| consists of items with two halfword fields per
  4406  word. The first of these, called |next(p)|, points to the next identifier
  4407  belonging to the same coalesced list as the identifier corresponding to~|p|;
  4408  and the other, called |text(p)|, points to the |str_start| entry for
  4409  |p|'s identifier. If position~|p| of the hash table is empty, we have
  4410  |text(p)=0|; if position |p| is either empty or the end of a coalesced
  4411  hash list, we have |next(p)=0|.
  4412  
  4413  An auxiliary pointer variable called |hash_used| is maintained in such a
  4414  way that all locations |p>=hash_used| are nonempty. The global variable
  4415  |st_count| tells how many symbolic tokens have been defined, if statistics
  4416  are being kept.
  4417  
  4418  The first 256 locations of |hash| are reserved for symbols of length one.
  4419  
  4420  There's a parallel array called |eqtb| that contains the current equivalent
  4421  values of each symbolic token. The entries of this array consist of
  4422  two halfwords called |eq_type| (a command code) and |equiv| (a secondary
  4423  piece of information that qualifies the |eq_type|).
  4424  
  4425  @d next(#) == hash[#].lh {link for coalesced lists}
  4426  @d text(#) == hash[#].rh {string number for symbolic token name}
  4427  @d eq_type(#) == eqtb[#].lh {the current ``meaning'' of a symbolic token}
  4428  @d equiv(#) == eqtb[#].rh {parametric part of a token's meaning}
  4429  @d hash_base=257 {hashing actually starts here}
  4430  @d hash_is_full == (hash_used=hash_base) {are all positions occupied?}
  4431  
  4432  @<Glob...@>=
  4433  @!hash_used:pointer; {allocation pointer for |hash|}
  4434  @!st_count:integer; {total number of known identifiers}
  4435  
  4436  @ Certain entries in the hash table are ``frozen'' and not redefinable,
  4437  since they are used in error recovery.
  4438  
  4439  @d hash_top==hash_base+hash_size {the first location of the frozen area}
  4440  @d frozen_inaccessible==hash_top {|hash| location to protect the frozen area}
  4441  @d frozen_repeat_loop==hash_top+1 {|hash| location of a loop-repeat token}
  4442  @d frozen_right_delimiter==hash_top+2 {|hash| location of a permanent `\.)'}
  4443  @d frozen_left_bracket==hash_top+3 {|hash| location of a permanent `\.['}
  4444  @d frozen_slash==hash_top+4 {|hash| location of a permanent `\./'}
  4445  @d frozen_colon==hash_top+5 {|hash| location of a permanent `\.:'}
  4446  @d frozen_semicolon==hash_top+6 {|hash| location of a permanent `\.;'}
  4447  @d frozen_end_for==hash_top+7 {|hash| location of a permanent \&{endfor}}
  4448  @d frozen_end_def==hash_top+8 {|hash| location of a permanent \&{enddef}}
  4449  @d frozen_fi==hash_top+9 {|hash| location of a permanent \&{fi}}
  4450  @d frozen_end_group==hash_top+10
  4451    {|hash| location of a permanent `\.{endgroup}'}
  4452  @d frozen_bad_vardef==hash_top+11 {|hash| location of `\.{a bad variable}'}
  4453  @d frozen_undefined==hash_top+12 {|hash| location that never gets defined}
  4454  @d hash_end==hash_top+12 {the actual size of the |hash| and |eqtb| arrays}
  4455  
  4456  @<Glob...@>=
  4457  @!hash: array[1..hash_end] of two_halves; {the hash table}
  4458  @!eqtb: array[1..hash_end] of two_halves; {the equivalents}
  4459  
  4460  @ @<Set init...@>=
  4461  next(1):=0; text(1):=0; eq_type(1):=tag_token; equiv(1):=null;
  4462  for k:=2 to hash_end do
  4463    begin hash[k]:=hash[1]; eqtb[k]:=eqtb[1];
  4464    end;
  4465  
  4466  @ @<Initialize table entries...@>=
  4467  hash_used:=frozen_inaccessible; {nothing is used}
  4468  st_count:=0;@/
  4469  text(frozen_bad_vardef):="a bad variable";
  4470  text(frozen_fi):="fi";
  4471  text(frozen_end_group):="endgroup";
  4472  text(frozen_end_def):="enddef";
  4473  text(frozen_end_for):="endfor";@/
  4474  text(frozen_semicolon):=";";
  4475  text(frozen_colon):=":";
  4476  text(frozen_slash):="/";
  4477  text(frozen_left_bracket):="[";
  4478  text(frozen_right_delimiter):=")";@/
  4479  text(frozen_inaccessible):=" INACCESSIBLE";@/
  4480  eq_type(frozen_right_delimiter):=right_delimiter;
  4481  
  4482  @ @<Check the ``constant'' values...@>=
  4483  if hash_end+max_internal>max_halfword then bad:=21;
  4484  
  4485  @ Here is the subroutine that searches the hash table for an identifier
  4486  that matches a given string of length~|l| appearing in |buffer[j..
  4487  (j+l-1)]|. If the identifier is not found, it is inserted; hence it
  4488  will always be found, and the corresponding hash table address
  4489  will be returned.
  4490  
  4491  @p function id_lookup(@!j,@!l:integer):pointer; {search the hash table}
  4492  label found; {go here when you've found it}
  4493  var @!h:integer; {hash code}
  4494  @!p:pointer; {index in |hash| array}
  4495  @!k:pointer; {index in |buffer| array}
  4496  begin if l=1 then @<Treat special case of length 1 and |goto found|@>;
  4497  @<Compute the hash code |h|@>;
  4498  p:=h+hash_base; {we start searching here; note that |0<=h<hash_prime|}
  4499  loop@+  begin if text(p)>0 then if length(text(p))=l then
  4500      if str_eq_buf(text(p),j) then goto found;
  4501    if next(p)=0 then
  4502      @<Insert a new symbolic token after |p|, then
  4503        make |p| point to it and |goto found|@>;
  4504    p:=next(p);
  4505    end;
  4506  found: id_lookup:=p;
  4507  end;
  4508  
  4509  @ @<Treat special case of length 1...@>=
  4510  begin p:=buffer[j]+1; text(p):=p-1; goto found;
  4511  end
  4512  
  4513  @ @<Insert a new symbolic...@>=
  4514  begin if text(p)>0 then
  4515    begin repeat if hash_is_full then
  4516      overflow("hash size",hash_size);
  4517  @:METAFONT capacity exceeded hash size}{\quad hash size@>
  4518    decr(hash_used);
  4519    until text(hash_used)=0; {search for an empty location in |hash|}
  4520    next(p):=hash_used; p:=hash_used;
  4521    end;
  4522  str_room(l);
  4523  for k:=j to j+l-1 do append_char(buffer[k]);
  4524  text(p):=make_string; str_ref[text(p)]:=max_str_ref;
  4525  @!stat incr(st_count);@+tats@;@/
  4526  goto found;
  4527  end
  4528  
  4529  @ The value of |hash_prime| should be roughly 85\pct! of |hash_size|, and it
  4530  should be a prime number.  The theory of hashing tells us to expect fewer
  4531  than two table probes, on the average, when the search is successful.
  4532  [See J.~S. Vitter, {\sl Journal of the ACM\/ \bf30} (1983), 231--258.]
  4533  @^Vitter, Jeffrey Scott@>
  4534  
  4535  @<Compute the hash code |h|@>=
  4536  h:=buffer[j];
  4537  for k:=j+1 to j+l-1 do
  4538    begin h:=h+h+buffer[k];
  4539    while h>=hash_prime do h:=h-hash_prime;
  4540    end
  4541  
  4542  @ @<Search |eqtb| for equivalents equal to |p|@>=
  4543  for q:=1 to hash_end do
  4544    begin if equiv(q)=p then
  4545      begin print_nl("EQUIV("); print_int(q); print_char(")");
  4546      end;
  4547    end
  4548  
  4549  @ We need to put \MF's ``primitive'' symbolic tokens into the hash
  4550  table, together with their command code (which will be the |eq_type|)
  4551  and an operand (which will be the |equiv|). The |primitive| procedure
  4552  does this, in a way that no \MF\ user can. The global value |cur_sym|
  4553  contains the new |eqtb| pointer after |primitive| has acted.
  4554  
  4555  @p @!init procedure primitive(@!s:str_number;@!c:halfword;@!o:halfword);
  4556  var @!k:pool_pointer; {index into |str_pool|}
  4557  @!j:small_number; {index into |buffer|}
  4558  @!l:small_number; {length of the string}
  4559  begin k:=str_start[s]; l:=str_start[s+1]-k;
  4560    {we will move |s| into the (empty) |buffer|}
  4561  for j:=0 to l-1 do buffer[j]:=so(str_pool[k+j]);
  4562  cur_sym:=id_lookup(0,l);@/
  4563  if s>=256 then {we don't want to have the string twice}
  4564    begin flush_string(str_ptr-1); text(cur_sym):=s;
  4565    end;
  4566  eq_type(cur_sym):=c; equiv(cur_sym):=o;
  4567  end;
  4568  tini
  4569  
  4570  @ Many of \MF's primitives need no |equiv|, since they are identifiable
  4571  by their |eq_type| alone. These primitives are loaded into the hash table
  4572  as follows:
  4573  
  4574  @<Put each of \MF's primitives into the hash table@>=
  4575  primitive("..",path_join,0);@/
  4576  @!@:.._}{\.{..} primitive@>
  4577  primitive("[",left_bracket,0); eqtb[frozen_left_bracket]:=eqtb[cur_sym];@/
  4578  @!@:[ }{\.{[} primitive@>
  4579  primitive("]",right_bracket,0);@/
  4580  @!@:] }{\.{]} primitive@>
  4581  primitive("}",right_brace,0);@/
  4582  @!@:]]}{\.{\char`\}} primitive@>
  4583  primitive("{",left_brace,0);@/
  4584  @!@:][}{\.{\char`\{} primitive@>
  4585  primitive(":",colon,0); eqtb[frozen_colon]:=eqtb[cur_sym];@/
  4586  @!@:: }{\.{:} primitive@>
  4587  primitive("::",double_colon,0);@/
  4588  @!@::: }{\.{::} primitive@>
  4589  primitive("||:",bchar_label,0);@/
  4590  @!@:::: }{\.{\char'174\char'174:} primitive@>
  4591  primitive(":=",assignment,0);@/
  4592  @!@::=_}{\.{:=} primitive@>
  4593  primitive(",",comma,0);@/
  4594  @!@:, }{\., primitive@>
  4595  primitive(";",semicolon,0); eqtb[frozen_semicolon]:=eqtb[cur_sym];@/
  4596  @!@:; }{\.; primitive@>
  4597  primitive("\",relax,0);@/
  4598  @!@:]]\\}{\.{\char`\\} primitive@>
  4599  @#
  4600  primitive("addto",add_to_command,0);@/
  4601  @!@:add_to_}{\&{addto} primitive@>
  4602  primitive("at",at_token,0);@/
  4603  @!@:at_}{\&{at} primitive@>
  4604  primitive("atleast",at_least,0);@/
  4605  @!@:at_least_}{\&{atleast} primitive@>
  4606  primitive("begingroup",begin_group,0); bg_loc:=cur_sym;@/
  4607  @!@:begin_group_}{\&{begingroup} primitive@>
  4608  primitive("controls",controls,0);@/
  4609  @!@:controls_}{\&{controls} primitive@>
  4610  primitive("cull",cull_command,0);@/
  4611  @!@:cull_}{\&{cull} primitive@>
  4612  primitive("curl",curl_command,0);@/
  4613  @!@:curl_}{\&{curl} primitive@>
  4614  primitive("delimiters",delimiters,0);@/
  4615  @!@:delimiters_}{\&{delimiters} primitive@>
  4616  primitive("display",display_command,0);@/
  4617  @!@:display_}{\&{display} primitive@>
  4618  primitive("endgroup",end_group,0);
  4619   eqtb[frozen_end_group]:=eqtb[cur_sym]; eg_loc:=cur_sym;@/
  4620  @!@:endgroup_}{\&{endgroup} primitive@>
  4621  primitive("everyjob",every_job_command,0);@/
  4622  @!@:every_job_}{\&{everyjob} primitive@>
  4623  primitive("exitif",exit_test,0);@/
  4624  @!@:exit_if_}{\&{exitif} primitive@>
  4625  primitive("expandafter",expand_after,0);@/
  4626  @!@:expand_after_}{\&{expandafter} primitive@>
  4627  primitive("from",from_token,0);@/
  4628  @!@:from_}{\&{from} primitive@>
  4629  primitive("inwindow",in_window,0);@/
  4630  @!@:in_window_}{\&{inwindow} primitive@>
  4631  primitive("interim",interim_command,0);@/
  4632  @!@:interim_}{\&{interim} primitive@>
  4633  primitive("let",let_command,0);@/
  4634  @!@:let_}{\&{let} primitive@>
  4635  primitive("newinternal",new_internal,0);@/
  4636  @!@:new_internal_}{\&{newinternal} primitive@>
  4637  primitive("of",of_token,0);@/
  4638  @!@:of_}{\&{of} primitive@>
  4639  primitive("openwindow",open_window,0);@/
  4640  @!@:open_window_}{\&{openwindow} primitive@>
  4641  primitive("randomseed",random_seed,0);@/
  4642  @!@:random_seed_}{\&{randomseed} primitive@>
  4643  primitive("save",save_command,0);@/
  4644  @!@:save_}{\&{save} primitive@>
  4645  primitive("scantokens",scan_tokens,0);@/
  4646  @!@:scan_tokens_}{\&{scantokens} primitive@>
  4647  primitive("shipout",ship_out_command,0);@/
  4648  @!@:ship_out_}{\&{shipout} primitive@>
  4649  primitive("skipto",skip_to,0);@/
  4650  @!@:skip_to_}{\&{skipto} primitive@>
  4651  primitive("step",step_token,0);@/
  4652  @!@:step_}{\&{step} primitive@>
  4653  primitive("str",str_op,0);@/
  4654  @!@:str_}{\&{str} primitive@>
  4655  primitive("tension",tension,0);@/
  4656  @!@:tension_}{\&{tension} primitive@>
  4657  primitive("to",to_token,0);@/
  4658  @!@:to_}{\&{to} primitive@>
  4659  primitive("until",until_token,0);@/
  4660  @!@:until_}{\&{until} primitive@>
  4661  
  4662  @ Each primitive has a corresponding inverse, so that it is possible to
  4663  display the cryptic numeric contents of |eqtb| in symbolic form.
  4664  Every call of |primitive| in this program is therefore accompanied by some
  4665  straightforward code that forms part of the |print_cmd_mod| routine
  4666  explained below.
  4667  
  4668  @<Cases of |print_cmd_mod| for symbolic printing of primitives@>=
  4669  add_to_command:print("addto");
  4670  assignment:print(":=");
  4671  at_least:print("atleast");
  4672  at_token:print("at");
  4673  bchar_label:print("||:");
  4674  begin_group:print("begingroup");
  4675  colon:print(":");
  4676  comma:print(",");
  4677  controls:print("controls");
  4678  cull_command:print("cull");
  4679  curl_command:print("curl");
  4680  delimiters:print("delimiters");
  4681  display_command:print("display");
  4682  double_colon:print("::");
  4683  end_group:print("endgroup");
  4684  every_job_command:print("everyjob");
  4685  exit_test:print("exitif");
  4686  expand_after:print("expandafter");
  4687  from_token:print("from");
  4688  in_window:print("inwindow");
  4689  interim_command:print("interim");
  4690  left_brace:print("{");
  4691  left_bracket:print("[");
  4692  let_command:print("let");
  4693  new_internal:print("newinternal");
  4694  of_token:print("of");
  4695  open_window:print("openwindow");
  4696  path_join:print("..");
  4697  random_seed:print("randomseed");
  4698  relax:print_char("\");
  4699  right_brace:print("}");
  4700  right_bracket:print("]");
  4701  save_command:print("save");
  4702  scan_tokens:print("scantokens");
  4703  semicolon:print(";");
  4704  ship_out_command:print("shipout");
  4705  skip_to:print("skipto");
  4706  step_token:print("step");
  4707  str_op:print("str");
  4708  tension:print("tension");
  4709  to_token:print("to");
  4710  until_token:print("until");
  4711  
  4712  @ We will deal with the other primitives later, at some point in the program
  4713  where their |eq_type| and |equiv| values are more meaningful.  For example,
  4714  the primitives for macro definitions will be loaded when we consider the
  4715  routines that define macros.
  4716  It is easy to find where each particular
  4717  primitive was treated by looking in the index at the end; for example, the
  4718  section where |"def"| entered |eqtb| is listed under `\&{def} primitive'.
  4719  
  4720  @* \[14] Token lists.
  4721  A \MF\ token is either symbolic or numeric or a string, or it denotes
  4722  a macro parameter or capsule; so there are five corresponding ways to encode it
  4723  @^token@>
  4724  internally: (1)~A symbolic token whose hash code is~|p|
  4725  is represented by the number |p|, in the |info| field of a single-word
  4726  node in~|mem|. (2)~A numeric token whose |scaled| value is~|v| is
  4727  represented in a two-word node of~|mem|; the |type| field is |known|,
  4728  the |name_type| field is |token|, and the |value| field holds~|v|.
  4729  The fact that this token appears in a two-word node rather than a
  4730  one-word node is, of course, clear from the node address.
  4731  (3)~A string token is also represented in a two-word node; the |type|
  4732  field is |string_type|, the |name_type| field is |token|, and the
  4733  |value| field holds the corresponding |str_number|.  (4)~Capsules have
  4734  |name_type=capsule|, and their |type| and |value| fields represent
  4735  arbitrary values (in ways to be explained later).  (5)~Macro parameters
  4736  are like symbolic tokens in that they appear in |info| fields of
  4737  one-word nodes. The $k$th parameter is represented by |expr_base+k| if it
  4738  is of type \&{expr}, or by |suffix_base+k| if it is of type \&{suffix}, or
  4739  by |text_base+k| if it is of type \&{text}.  (Here |0<=k<param_size|.)
  4740  Actual values of these parameters are kept in a separate stack, as we will
  4741  see later.  The constants |expr_base|, |suffix_base|, and |text_base| are,
  4742  of course, chosen so that there will be no confusion between symbolic
  4743  tokens and parameters of various types.
  4744  
  4745  It turns out that |value(null)=0|, because |null=null_coords|;
  4746  we will make use of this coincidence later.
  4747  
  4748  Incidentally, while we're speaking of coincidences, we might note that
  4749  the `\\{type}' field of a node has nothing to do with ``type'' in a
  4750  printer's sense. It's curious that the same word is used in such different ways.
  4751  
  4752  @d type(#) == mem[#].hh.b0 {identifies what kind of value this is}
  4753  @d name_type(#) == mem[#].hh.b1 {a clue to the name of this value}
  4754  @d token_node_size=2 {the number of words in a large token node}
  4755  @d value_loc(#)==#+1 {the word that contains the |value| field}
  4756  @d value(#)==mem[value_loc(#)].int {the value stored in a large token node}
  4757  @d expr_base==hash_end+1 {code for the zeroth \&{expr} parameter}
  4758  @d suffix_base==expr_base+param_size {code for the zeroth \&{suffix} parameter}
  4759  @d text_base==suffix_base+param_size {code for the zeroth \&{text} parameter}
  4760  
  4761  @<Check the ``constant''...@>=
  4762  if text_base+param_size>max_halfword then bad:=22;
  4763  
  4764  @ A numeric token is created by the following trivial routine.
  4765  
  4766  @p function new_num_tok(@!v:scaled):pointer;
  4767  var @!p:pointer; {the new node}
  4768  begin p:=get_node(token_node_size); value(p):=v;
  4769  type(p):=known; name_type(p):=token; new_num_tok:=p;
  4770  end;
  4771  
  4772  @ A token list is a singly linked list of nodes in |mem|, where
  4773  each node contains a token and a link.  Here's a subroutine that gets rid
  4774  of a token list when it is no longer needed.
  4775  
  4776  @p procedure@?token_recycle; forward;@t\2@>@;@/
  4777  procedure flush_token_list(@!p:pointer);
  4778  var @!q:pointer; {the node being recycled}
  4779  begin while p<>null do
  4780    begin q:=p; p:=link(p);
  4781    if q>=hi_mem_min then free_avail(q)
  4782    else  begin case type(q) of
  4783      vacuous,boolean_type,known:do_nothing;
  4784      string_type:delete_str_ref(value(q));
  4785      unknown_types,pen_type,path_type,future_pen,picture_type,
  4786       pair_type,transform_type,dependent,proto_dependent,independent:
  4787        begin g_pointer:=q; token_recycle;
  4788        end;
  4789      othercases confusion("token")
  4790  @:this can't happen token}{\quad token@>
  4791      endcases;@/
  4792      free_node(q,token_node_size);
  4793      end;
  4794    end;
  4795  end;
  4796  
  4797  @ The procedure |show_token_list|, which prints a symbolic form of
  4798  the token list that starts at a given node |p|, illustrates these
  4799  conventions. The token list being displayed should not begin with a reference
  4800  count. However, the procedure is intended to be fairly robust, so that if the
  4801  memory links are awry or if |p| is not really a pointer to a token list,
  4802  almost nothing catastrophic can happen.
  4803  
  4804  An additional parameter |q| is also given; this parameter is either null
  4805  or it points to a node in the token list where a certain magic computation
  4806  takes place that will be explained later. (Basically, |q| is non-null when
  4807  we are printing the two-line context information at the time of an error
  4808  message; |q| marks the place corresponding to where the second line
  4809  should begin.)
  4810  
  4811  The generation will stop, and `\.{\char`\ ETC.}' will be printed, if the length
  4812  of printing exceeds a given limit~|l|; the length of printing upon entry is
  4813  assumed to be a given amount called |null_tally|. (Note that
  4814  |show_token_list| sometimes uses itself recursively to print
  4815  variable names within a capsule.)
  4816  @^recursion@>
  4817  
  4818  Unusual entries are printed in the form of all-caps tokens
  4819  preceded by a space, e.g., `\.{\char`\ BAD}'.
  4820  
  4821  @<Declare the procedure called |show_token_list|@>=
  4822  procedure@?print_capsule; forward; @t\2@>@;@/
  4823  procedure show_token_list(@!p,@!q:integer;@!l,@!null_tally:integer);
  4824  label exit;
  4825  var @!class,@!c:small_number; {the |char_class| of previous and new tokens}
  4826  @!r,@!v:integer; {temporary registers}
  4827  begin class:=percent_class;
  4828  tally:=null_tally;
  4829  while (p<>null) and (tally<l) do
  4830    begin if p=q then @<Do magic computation@>;
  4831    @<Display token |p| and set |c| to its class;
  4832      but |return| if there are problems@>;
  4833    class:=c; p:=link(p);
  4834    end;
  4835  if p<>null then print(" ETC.");
  4836  @.ETC@>
  4837  exit:
  4838  end;
  4839  
  4840  @ @<Display token |p| and set |c| to its class...@>=
  4841  c:=letter_class; {the default}
  4842  if (p<mem_min)or(p>mem_end) then
  4843    begin print(" CLOBBERED"); return;
  4844  @.CLOBBERED@>
  4845    end;
  4846  if p<hi_mem_min then @<Display two-word token@>
  4847  else  begin r:=info(p);
  4848    if r>=expr_base then @<Display a parameter token@>
  4849    else if r<1 then
  4850      if r=0 then @<Display a collective subscript@>
  4851      else print(" IMPOSSIBLE")
  4852  @.IMPOSSIBLE@>
  4853    else  begin r:=text(r);
  4854      if (r<0)or(r>=str_ptr) then print(" NONEXISTENT")
  4855  @.NONEXISTENT@>
  4856      else @<Print string |r| as a symbolic token
  4857        and set |c| to its class@>;
  4858      end;
  4859    end
  4860  
  4861  @ @<Display two-word token@>=
  4862  if name_type(p)=token then
  4863    if type(p)=known then @<Display a numeric token@>
  4864    else if type(p)<>string_type then print(" BAD")
  4865  @.BAD@>
  4866    else  begin print_char(""""); slow_print(value(p)); print_char("""");
  4867      c:=string_class;
  4868      end
  4869  else if (name_type(p)<>capsule)or(type(p)<vacuous)or(type(p)>independent) then
  4870    print(" BAD")
  4871  else  begin g_pointer:=p; print_capsule; c:=right_paren_class;
  4872    end
  4873  
  4874  @ @<Display a numeric token@>=
  4875  begin if class=digit_class then print_char(" ");
  4876  v:=value(p);
  4877  if v<0 then
  4878    begin if class=left_bracket_class then print_char(" ");
  4879    print_char("["); print_scaled(v); print_char("]");
  4880    c:=right_bracket_class;
  4881    end
  4882  else  begin print_scaled(v); c:=digit_class;
  4883    end;
  4884  end
  4885  
  4886  @ Strictly speaking, a genuine token will never have |info(p)=0|.
  4887  But we will see later (in the definition of attribute nodes) that
  4888  it is convenient to let |info(p)=0| stand for `\.{[]}'.
  4889  
  4890  @<Display a collective subscript@>=
  4891  begin if class=left_bracket_class then print_char(" ");
  4892  print("[]"); c:=right_bracket_class;
  4893  end
  4894  
  4895  @ @<Display a parameter token@>=
  4896  begin if r<suffix_base then
  4897    begin print("(EXPR"); r:=r-(expr_base);
  4898  @.EXPR@>
  4899    end
  4900  else if r<text_base then
  4901    begin print("(SUFFIX"); r:=r-(suffix_base);
  4902  @.SUFFIX@>
  4903    end
  4904  else  begin print("(TEXT"); r:=r-(text_base);
  4905  @.TEXT@>
  4906    end;
  4907  print_int(r); print_char(")"); c:=right_paren_class;
  4908  end
  4909  
  4910  @ @<Print string |r| as a symbolic token...@>=
  4911  begin c:=char_class[so(str_pool[str_start[r]])];
  4912  if c=class then
  4913    case c of
  4914    letter_class:print_char(".");
  4915    isolated_classes:do_nothing;
  4916    othercases print_char(" ")
  4917    endcases;
  4918  slow_print(r);
  4919  end
  4920  
  4921  @ The following procedures have been declared |forward| with no parameters,
  4922  because the author dislikes \PASCAL's convention about |forward| procedures
  4923  with parameters. It was necessary to do something, because |show_token_list|
  4924  is recursive (although the recursion is limited to one level), and because
  4925  |flush_token_list| is syntactically (but not semantically) recursive.
  4926  @^recursion@>
  4927  
  4928  @<Declare miscellaneous procedures that were declared |forward|@>=
  4929  procedure print_capsule;
  4930  begin print_char("("); print_exp(g_pointer,0); print_char(")");
  4931  end;
  4932  @#
  4933  procedure token_recycle;
  4934  begin recycle_value(g_pointer);
  4935  end;
  4936  
  4937  @ @<Glob...@>=
  4938  @!g_pointer:pointer; {(global) parameter to the |forward| procedures}
  4939  
  4940  @ Macro definitions are kept in \MF's memory in the form of token lists
  4941  that have a few extra one-word nodes at the beginning.
  4942  
  4943  The first node contains a reference count that is used to tell when the
  4944  list is no longer needed. To emphasize the fact that a reference count is
  4945  present, we shall refer to the |info| field of this special node as the
  4946  |ref_count| field.
  4947  @^reference counts@>
  4948  
  4949  The next node or nodes after the reference count serve to describe the
  4950  formal parameters. They consist of zero or more parameter tokens followed
  4951  by a code for the type of macro.
  4952  
  4953  @d ref_count==info {reference count preceding a macro definition or pen header}
  4954  @d add_mac_ref(#)==incr(ref_count(#)) {make a new reference to a macro list}
  4955  @d general_macro=0 {preface to a macro defined with a parameter list}
  4956  @d primary_macro=1 {preface to a macro with a \&{primary} parameter}
  4957  @d secondary_macro=2 {preface to a macro with a \&{secondary} parameter}
  4958  @d tertiary_macro=3 {preface to a macro with a \&{tertiary} parameter}
  4959  @d expr_macro=4 {preface to a macro with an undelimited \&{expr} parameter}
  4960  @d of_macro=5 {preface to a macro with
  4961    undelimited `\&{expr} |x| \&{of}~|y|' parameters}
  4962  @d suffix_macro=6 {preface to a macro with an undelimited \&{suffix} parameter}
  4963  @d text_macro=7 {preface to a macro with an undelimited \&{text} parameter}
  4964  
  4965  @p procedure delete_mac_ref(@!p:pointer);
  4966    {|p| points to the reference count of a macro list that is
  4967      losing one reference}
  4968  begin if ref_count(p)=null then flush_token_list(p)
  4969  else decr(ref_count(p));
  4970  end;
  4971  
  4972  @ The following subroutine displays a macro, given a pointer to its
  4973  reference count.
  4974  
  4975  @p @t\4@>@<Declare the procedure called |print_cmd_mod|@>@;
  4976  procedure show_macro(@!p:pointer;@!q,@!l:integer);
  4977  label exit;
  4978  var @!r:pointer; {temporary storage}
  4979  begin p:=link(p); {bypass the reference count}
  4980  while info(p)>text_macro do
  4981    begin r:=link(p); link(p):=null;
  4982    show_token_list(p,null,l,0); link(p):=r; p:=r;
  4983    if l>0 then l:=l-tally@+else return;
  4984    end; {control printing of `\.{ETC.}'}
  4985  @.ETC@>
  4986  tally:=0;
  4987  case info(p) of
  4988  general_macro:print("->");
  4989  @.->@>
  4990  primary_macro,secondary_macro,tertiary_macro:begin print_char("<");
  4991    print_cmd_mod(param_type,info(p)); print(">->");
  4992    end;
  4993  expr_macro:print("<expr>->");
  4994  of_macro:print("<expr>of<primary>->");
  4995  suffix_macro:print("<suffix>->");
  4996  text_macro:print("<text>->");
  4997  end; {there are no other cases}
  4998  show_token_list(link(p),q,l-tally,0);
  4999  exit:end;
  5000  
  5001  @* \[15] Data structures for variables.
  5002  The variables of \MF\ programs can be simple, like `\.x', or they can
  5003  combine the structural properties of arrays and records, like `\.{x20a.b}'.
  5004  A \MF\ user assigns a type to a variable like \.{x20a.b} by saying, for
  5005  example, `\.{boolean} \.{x[]a.b}'. It's time for us to study how such
  5006  things are represented inside of the computer.
  5007  
  5008  Each variable value occupies two consecutive words, either in a two-word
  5009  node called a value node, or as a two-word subfield of a larger node.  One
  5010  of those two words is called the |value| field; it is an integer,
  5011  containing either a |scaled| numeric value or the representation of some
  5012  other type of quantity. (It might also be subdivided into halfwords, in
  5013  which case it is referred to by other names instead of |value|.) The other
  5014  word is broken into subfields called |type|, |name_type|, and |link|.  The
  5015  |type| field is a quarterword that specifies the variable's type, and
  5016  |name_type| is a quarterword from which \MF\ can reconstruct the
  5017  variable's name (sometimes by using the |link| field as well).  Thus, only
  5018  1.25 words are actually devoted to the value itself; the other
  5019  three-quarters of a word are overhead, but they aren't wasted because they
  5020  allow \MF\ to deal with sparse arrays and to provide meaningful diagnostics.
  5021  
  5022  In this section we shall be concerned only with the structural aspects of
  5023  variables, not their values. Later parts of the program will change the
  5024  |type| and |value| fields, but we shall treat those fields as black boxes
  5025  whose contents should not be touched.
  5026  
  5027  However, if the |type| field is |structured|, there is no |value| field,
  5028  and the second word is broken into two pointer fields called |attr_head|
  5029  and |subscr_head|. Those fields point to additional nodes that
  5030  contain structural information, as we shall see.
  5031  
  5032  @d subscr_head_loc(#) == #+1 {where |value|, |subscr_head|, and |attr_head| are}
  5033  @d attr_head(#) == info(subscr_head_loc(#)) {pointer to attribute info}
  5034  @d subscr_head(#) == link(subscr_head_loc(#)) {pointer to subscript info}
  5035  @d value_node_size=2 {the number of words in a value node}
  5036  
  5037  @ An attribute node is three words long. Two of these words contain |type|
  5038  and |value| fields as described above, and the third word contains
  5039  additional information:  There is an |attr_loc| field, which contains the
  5040  hash address of the token that names this attribute; and there's also a
  5041  |parent| field, which points to the value node of |structured| type at the
  5042  next higher level (i.e., at the level to which this attribute is
  5043  subsidiary).  The |name_type| in an attribute node is `|attr|'.  The
  5044  |link| field points to the next attribute with the same parent; these are
  5045  arranged in increasing order, so that |attr_loc(link(p))>attr_loc(p)|. The
  5046  final attribute node links to the constant |end_attr|, whose |attr_loc|
  5047  field is greater than any legal hash address. The |attr_head| in the
  5048  parent points to a node whose |name_type| is |structured_root|; this
  5049  node represents the null attribute, i.e., the variable that is relevant
  5050  when no attributes are attached to the parent. The |attr_head| node
  5051  has the fields of either
  5052  a value node, a subscript node, or an attribute node, depending on what
  5053  the parent would be if it were not structured; but the subscript and
  5054  attribute fields are ignored, so it effectively contains only the data of
  5055  a value node. The |link| field in this special node points to an attribute
  5056  node whose |attr_loc| field is zero; the latter node represents a collective
  5057  subscript `\.{[]}' attached to the parent, and its |link| field points to
  5058  the first non-special attribute node (or to |end_attr| if there are none).
  5059  
  5060  A subscript node likewise occupies three words, with |type| and |value| fields
  5061  plus extra information; its |name_type| is |subscr|. In this case the
  5062  third word is called the |subscript| field, which is a |scaled| integer.
  5063  The |link| field points to the subscript node with the next larger
  5064  subscript, if any; otherwise the |link| points to the attribute node
  5065  for collective subscripts at this level. We have seen that the latter node
  5066  contains an upward pointer, so that the parent can be deduced.
  5067  
  5068  The |name_type| in a parent-less value node is |root|, and the |link|
  5069  is the hash address of the token that names this value.
  5070  
  5071  In other words, variables have a hierarchical structure that includes
  5072  enough threads running around so that the program is able to move easily
  5073  between siblings, parents, and children. An example should be helpful:
  5074  (The reader is advised to draw a picture while reading the following
  5075  description, since that will help to firm up the ideas.)
  5076  Suppose that `\.x' and `\.{x.a}' and `\.{x[]b}' and `\.{x5}'
  5077  and `\.{x20b}' have been mentioned in a user's program, where
  5078  \.{x[]b} has been declared to be of \&{boolean} type. Let |h(x)|, |h(a)|,
  5079  and |h(b)| be the hash addresses of \.x, \.a, and~\.b. Then
  5080  |eq_type(h(x))=tag_token| and |equiv(h(x))=p|, where |p|~is a two-word value
  5081  node with |name_type(p)=root| and |link(p)=h(x)|. We have |type(p)=structured|,
  5082  |attr_head(p)=q|, and |subscr_head(p)=r|, where |q| points to a value
  5083  node and |r| to a subscript node. (Are you still following this? Use
  5084  a pencil to draw a diagram.) The lone variable `\.x' is represented by
  5085  |type(q)| and |value(q)|; furthermore
  5086  |name_type(q)=structured_root| and |link(q)=q1|, where |q1| points
  5087  to an attribute node representing `\.{x[]}'. Thus |name_type(q1)=attr|,
  5088  |attr_loc(q1)=collective_subscript=0|, |parent(q1)=p|,
  5089  |type(q1)=structured|, |attr_head(q1)=qq|, and |subscr_head(q1)=qq1|;
  5090  |qq| is a three-word ``attribute-as-value'' node with |type(qq)=numeric_type|
  5091  (assuming that \.{x5} is numeric, because |qq| represents `\.{x[]}'
  5092  with no further attributes), |name_type(qq)=structured_root|,
  5093  |attr_loc(qq)=0|, |parent(qq)=p|, and
  5094  |link(qq)=qq1|. (Now pay attention to the next part.) Node |qq1| is
  5095  an attribute node representing `\.{x[][]}', which has never yet
  5096  occurred; its |type| field is |undefined|, and its |value| field is
  5097  undefined. We have |name_type(qq1)=attr|, |attr_loc(qq1)=collective_subscript|,
  5098  |parent(qq1)=q1|, and |link(qq1)=qq2|. Since |qq2| represents
  5099  `\.{x[]b}', |type(qq2)=unknown_boolean|; also |attr_loc(qq2)=h(b)|,
  5100  |parent(qq2)=q1|, |name_type(qq2)=attr|, |link(qq2)=end_attr|.
  5101  (Maybe colored lines will help untangle your picture.)
  5102   Node |r| is a subscript node with |type| and |value|
  5103  representing `\.{x5}'; |name_type(r)=subscr|, |subscript(r)=5.0|,
  5104  and |link(r)=r1| is another subscript node. To complete the picture,
  5105  see if you can guess what |link(r1)| is; give up? It's~|q1|.
  5106  Furthermore |subscript(r1)=20.0|, |name_type(r1)=subscr|,
  5107  |type(r1)=structured|, |attr_head(r1)=qqq|, |subscr_head(r1)=qqq1|,
  5108  and we finish things off with three more nodes
  5109  |qqq|, |qqq1|, and |qqq2| hung onto~|r1|. (Perhaps you should start again
  5110  with a larger sheet of paper.) The value of variable `\.{x20b}'
  5111  appears in node~|qqq2=link(qqq1)|, as you can well imagine.
  5112  Similarly, the value of `\.{x.a}' appears in node |q2=link(q1)|, where
  5113  |attr_loc(q2)=h(a)| and |parent(q2)=p|.
  5114  
  5115  If the example in the previous paragraph doesn't make things crystal
  5116  clear, a glance at some of the simpler subroutines below will reveal how
  5117  things work out in practice.
  5118  
  5119  The only really unusual thing about these conventions is the use of
  5120  collective subscript attributes. The idea is to avoid repeating a lot of
  5121  type information when many elements of an array are identical macros
  5122  (for which distinct values need not be stored) or when they don't have
  5123  all of the possible attributes. Branches of the structure below collective
  5124  subscript attributes do not carry actual values except for macro identifiers;
  5125  branches of the structure below subscript nodes do not carry significant
  5126  information in their collective subscript attributes.
  5127  
  5128  @d attr_loc_loc(#)==#+2 {where the |attr_loc| and |parent| fields are}
  5129  @d attr_loc(#)==info(attr_loc_loc(#)) {hash address of this attribute}
  5130  @d parent(#)==link(attr_loc_loc(#)) {pointer to |structured| variable}
  5131  @d subscript_loc(#)==#+2 {where the |subscript| field lives}
  5132  @d subscript(#)==mem[subscript_loc(#)].sc {subscript of this variable}
  5133  @d attr_node_size=3 {the number of words in an attribute node}
  5134  @d subscr_node_size=3 {the number of words in a subscript node}
  5135  @d collective_subscript=0 {code for the attribute `\.{[]}'}
  5136  
  5137  @<Initialize table...@>=
  5138  attr_loc(end_attr):=hash_end+1; parent(end_attr):=null;
  5139  
  5140  @ Variables of type \&{pair} will have values that point to four-word
  5141  nodes containing two numeric values. The first of these values has
  5142  |name_type=x_part_sector| and the second has |name_type=y_part_sector|;
  5143  the |link| in the first points back to the node whose |value| points
  5144  to this four-word node.
  5145  
  5146  Variables of type \&{transform} are similar, but in this case their
  5147  |value| points to a 12-word node containing six values, identified by
  5148  |x_part_sector|, |y_part_sector|, |xx_part_sector|, |xy_part_sector|,
  5149  |yx_part_sector|, and |yy_part_sector|.
  5150  
  5151  When an entire structured variable is saved, the |root| indication
  5152  is temporarily replaced by |saved_root|.
  5153  
  5154  Some variables have no name; they just are used for temporary storage
  5155  while expressions are being evaluated. We call them {\sl capsules}.
  5156  
  5157  @d x_part_loc(#)==# {where the \&{xpart} is found in a pair or transform node}
  5158  @d y_part_loc(#)==#+2 {where the \&{ypart} is found in a pair or transform node}
  5159  @d xx_part_loc(#)==#+4 {where the \&{xxpart} is found in a transform node}
  5160  @d xy_part_loc(#)==#+6 {where the \&{xypart} is found in a transform node}
  5161  @d yx_part_loc(#)==#+8 {where the \&{yxpart} is found in a transform node}
  5162  @d yy_part_loc(#)==#+10 {where the \&{yypart} is found in a transform node}
  5163  @#
  5164  @d pair_node_size=4 {the number of words in a pair node}
  5165  @d transform_node_size=12 {the number of words in a transform node}
  5166  
  5167  @<Glob...@>=
  5168  @!big_node_size:array[transform_type..pair_type] of small_number;
  5169  
  5170  @ The |big_node_size| array simply contains two constants that \MF\
  5171  occasionally needs to know.
  5172  
  5173  @<Set init...@>=
  5174  big_node_size[transform_type]:=transform_node_size;
  5175  big_node_size[pair_type]:=pair_node_size;
  5176  
  5177  @ If |type(p)=pair_type| or |transform_type| and if |value(p)=null|, the
  5178  procedure call |init_big_node(p)| will allocate a pair or transform node
  5179  for~|p|.  The individual parts of such nodes are initially of type
  5180  |independent|.
  5181  
  5182  @p procedure init_big_node(@!p:pointer);
  5183  var @!q:pointer; {the new node}
  5184  @!s:small_number; {its size}
  5185  begin s:=big_node_size[type(p)]; q:=get_node(s);
  5186  repeat s:=s-2; @<Make variable |q+s| newly independent@>;
  5187  name_type(q+s):=half(s)+x_part_sector; link(q+s):=null;
  5188  until s=0;
  5189  link(q):=p; value(p):=q;
  5190  end;
  5191  
  5192  @ The |id_transform| function creates a capsule for the
  5193  identity transformation.
  5194  
  5195  @p function id_transform:pointer;
  5196  var @!p,@!q,@!r:pointer; {list manipulation registers}
  5197  begin p:=get_node(value_node_size); type(p):=transform_type;
  5198  name_type(p):=capsule; value(p):=null; init_big_node(p); q:=value(p);
  5199  r:=q+transform_node_size;
  5200  repeat r:=r-2;
  5201  type(r):=known; value(r):=0;
  5202  until r=q;
  5203  value(xx_part_loc(q)):=unity; value(yy_part_loc(q)):=unity;
  5204  id_transform:=p;
  5205  end;
  5206  
  5207  @ Tokens are of type |tag_token| when they first appear, but they point
  5208  to |null| until they are first used as the root of a variable.
  5209  The following subroutine establishes the root node on such grand occasions.
  5210  
  5211  @p procedure new_root(@!x:pointer);
  5212  var @!p:pointer; {the new node}
  5213  begin p:=get_node(value_node_size); type(p):=undefined; name_type(p):=root;
  5214  link(p):=x; equiv(x):=p;
  5215  end;
  5216  
  5217  @ These conventions for variable representation are illustrated by the
  5218  |print_variable_name| routine, which displays the full name of a
  5219  variable given only a pointer to its two-word value packet.
  5220  
  5221  @p procedure print_variable_name(@!p:pointer);
  5222  label found,exit;
  5223  var @!q:pointer; {a token list that will name the variable's suffix}
  5224  @!r:pointer; {temporary for token list creation}
  5225  begin while name_type(p)>=x_part_sector do
  5226    @<Preface the output with a part specifier; |return| in the
  5227      case of a capsule@>;
  5228  q:=null;
  5229  while name_type(p)>saved_root do
  5230    @<Ascend one level, pushing a token onto list |q|
  5231     and replacing |p| by its parent@>;
  5232  r:=get_avail; info(r):=link(p); link(r):=q;
  5233  if name_type(p)=saved_root then print("(SAVED)");
  5234  @.SAVED@>
  5235  show_token_list(r,null,el_gordo,tally); flush_token_list(r);
  5236  exit:end;
  5237  
  5238  @ @<Ascend one level, pushing a token onto list |q|...@>=
  5239  begin if name_type(p)=subscr then
  5240    begin r:=new_num_tok(subscript(p));
  5241    repeat p:=link(p);
  5242    until name_type(p)=attr;
  5243    end
  5244  else if name_type(p)=structured_root then
  5245      begin p:=link(p); goto found;
  5246      end
  5247  else  begin if name_type(p)<>attr then confusion("var");
  5248  @:this can't happen var}{\quad var@>
  5249    r:=get_avail; info(r):=attr_loc(p);
  5250    end;
  5251  link(r):=q; q:=r;
  5252  found:  p:=parent(p);
  5253  end
  5254  
  5255  @ @<Preface the output with a part specifier...@>=
  5256  begin case name_type(p) of
  5257  x_part_sector: print_char("x");
  5258  y_part_sector: print_char("y");
  5259  xx_part_sector: print("xx");
  5260  xy_part_sector: print("xy");
  5261  yx_part_sector: print("yx");
  5262  yy_part_sector: print("yy");
  5263  capsule: begin print("%CAPSULE"); print_int(p-null); return;
  5264  @.CAPSULE@>
  5265    end;
  5266  end; {there are no other cases}
  5267  print("part "); p:=link(p-2*(name_type(p)-x_part_sector));
  5268  end
  5269  
  5270  @ The |interesting| function returns |true| if a given variable is not
  5271  in a capsule, or if the user wants to trace capsules.
  5272  
  5273  @p function interesting(@!p:pointer):boolean;
  5274  var @!t:small_number; {a |name_type|}
  5275  begin if internal[tracing_capsules]>0 then interesting:=true
  5276  else  begin t:=name_type(p);
  5277    if t>=x_part_sector then if t<>capsule then
  5278      t:=name_type(link(p-2*(t-x_part_sector)));
  5279    interesting:=(t<>capsule);
  5280    end;
  5281  end;
  5282  
  5283  @ Now here is a subroutine that converts an unstructured type into an
  5284  equivalent structured type, by inserting a |structured| node that is
  5285  capable of growing. This operation is done only when |name_type(p)=root|,
  5286  |subscr|, or |attr|.
  5287  
  5288  The procedure returns a pointer to the new node that has taken node~|p|'s
  5289  place in the structure. Node~|p| itself does not move, nor are its
  5290  |value| or |type| fields changed in any way.
  5291  
  5292  @p function new_structure(@!p:pointer):pointer;
  5293  var @!q,@!r:pointer; {list manipulation registers}
  5294  begin case name_type(p) of
  5295  root: begin q:=link(p); r:=get_node(value_node_size); equiv(q):=r;
  5296    end;
  5297  subscr: @<Link a new subscript node |r| in place of node |p|@>;
  5298  attr: @<Link a new attribute node |r| in place of node |p|@>;
  5299  othercases confusion("struct")
  5300  @:this can't happen struct}{\quad struct@>
  5301  endcases;@/
  5302  link(r):=link(p); type(r):=structured; name_type(r):=name_type(p);
  5303  attr_head(r):=p; name_type(p):=structured_root;@/
  5304  q:=get_node(attr_node_size); link(p):=q; subscr_head(r):=q;
  5305  parent(q):=r; type(q):=undefined; name_type(q):=attr; link(q):=end_attr;
  5306  attr_loc(q):=collective_subscript; new_structure:=r;
  5307  end;
  5308  
  5309  @ @<Link a new subscript node |r| in place of node |p|@>=
  5310  begin q:=p;
  5311  repeat q:=link(q);
  5312  until name_type(q)=attr;
  5313  q:=parent(q); r:=subscr_head_loc(q); {|link(r)=subscr_head(q)|}
  5314  repeat q:=r; r:=link(r);
  5315  until r=p;
  5316  r:=get_node(subscr_node_size);
  5317  link(q):=r; subscript(r):=subscript(p);
  5318  end
  5319  
  5320  @ If the attribute is |collective_subscript|, there are two pointers to
  5321  node~|p|, so we must change both of them.
  5322  
  5323  @<Link a new attribute node |r| in place of node |p|@>=
  5324  begin q:=parent(p); r:=attr_head(q);
  5325  repeat q:=r; r:=link(r);
  5326  until r=p;
  5327  r:=get_node(attr_node_size); link(q):=r;@/
  5328  mem[attr_loc_loc(r)]:=mem[attr_loc_loc(p)]; {copy |attr_loc| and |parent|}
  5329  if attr_loc(p)=collective_subscript then
  5330    begin q:=subscr_head_loc(parent(p));
  5331    while link(q)<>p do q:=link(q);
  5332    link(q):=r;
  5333    end;
  5334  end
  5335  
  5336  @ The |find_variable| routine is given a pointer~|t| to a nonempty token
  5337  list of suffixes; it returns a pointer to the corresponding two-word
  5338  value. For example, if |t| points to token \.x followed by a numeric
  5339  token containing the value~7, |find_variable| finds where the value of
  5340  \.{x7} is stored in memory. This may seem a simple task, and it
  5341  usually is, except when \.{x7} has never been referenced before.
  5342  Indeed, \.x may never have even been subscripted before; complexities
  5343  arise with respect to updating the collective subscript information.
  5344  
  5345  If a macro type is detected anywhere along path~|t|, or if the first
  5346  item on |t| isn't a |tag_token|, the value |null| is returned.
  5347  Otherwise |p| will be a non-null pointer to a node such that
  5348  |undefined<type(p)<structured|.
  5349  
  5350  @d abort_find==begin find_variable:=null; return;@+end
  5351  
  5352  @p function find_variable(@!t:pointer):pointer;
  5353  label exit;
  5354  var @!p,@!q,@!r,@!s:pointer; {nodes in the ``value'' line}
  5355  @!pp,@!qq,@!rr,@!ss:pointer; {nodes in the ``collective'' line}
  5356  @!n:integer; {subscript or attribute}
  5357  @!save_word:memory_word; {temporary storage for a word of |mem|}
  5358  @^inner loop@>
  5359  begin p:=info(t); t:=link(t);
  5360  if eq_type(p) mod outer_tag<>tag_token then abort_find;
  5361  if equiv(p)=null then new_root(p);
  5362  p:=equiv(p); pp:=p;
  5363  while t<>null do
  5364    begin @<Make sure that both nodes |p| and |pp| are of |structured| type@>;
  5365    if t<hi_mem_min then
  5366      @<Descend one level for the subscript |value(t)|@>
  5367    else @<Descend one level for the attribute |info(t)|@>;
  5368    t:=link(t);
  5369    end;
  5370  if type(pp)>=structured then
  5371    if type(pp)=structured then pp:=attr_head(pp)@+else abort_find;
  5372  if type(p)=structured then p:=attr_head(p);
  5373  if type(p)=undefined then
  5374    begin if type(pp)=undefined then
  5375      begin type(pp):=numeric_type; value(pp):=null;
  5376      end;
  5377    type(p):=type(pp); value(p):=null;
  5378    end;
  5379  find_variable:=p;
  5380  exit:end;
  5381  
  5382  @ Although |pp| and |p| begin together, they diverge when a subscript occurs;
  5383  |pp|~stays in the collective line while |p|~goes through actual subscript
  5384  values.
  5385  
  5386  @<Make sure that both nodes |p| and |pp|...@>=
  5387  if type(pp)<>structured then
  5388    begin if type(pp)>structured then abort_find;
  5389    ss:=new_structure(pp);
  5390    if p=pp then p:=ss;
  5391    pp:=ss;
  5392    end; {now |type(pp)=structured|}
  5393  if type(p)<>structured then {it cannot be |>structured|}
  5394    p:=new_structure(p) {now |type(p)=structured|}
  5395  
  5396  @ We want this part of the program to be reasonably fast, in case there are
  5397  @^inner loop@>
  5398  lots of subscripts at the same level of the data structure. Therefore
  5399  we store an ``infinite'' value in the word that appears at the end of the
  5400  subscript list, even though that word isn't part of a subscript node.
  5401  
  5402  @<Descend one level for the subscript |value(t)|@>=
  5403  begin n:=value(t);
  5404  pp:=link(attr_head(pp)); {now |attr_loc(pp)=collective_subscript|}
  5405  q:=link(attr_head(p)); save_word:=mem[subscript_loc(q)];
  5406  subscript(q):=el_gordo; s:=subscr_head_loc(p); {|link(s)=subscr_head(p)|}
  5407  repeat r:=s; s:=link(s);
  5408  until n<=subscript(s);
  5409  if n=subscript(s) then p:=s
  5410  else  begin p:=get_node(subscr_node_size); link(r):=p; link(p):=s;
  5411    subscript(p):=n; name_type(p):=subscr; type(p):=undefined;
  5412    end;
  5413  mem[subscript_loc(q)]:=save_word;
  5414  end
  5415  
  5416  @ @<Descend one level for the attribute |info(t)|@>=
  5417  begin n:=info(t);
  5418  ss:=attr_head(pp);
  5419  repeat rr:=ss; ss:=link(ss);
  5420  until n<=attr_loc(ss);
  5421  if n<attr_loc(ss) then
  5422    begin qq:=get_node(attr_node_size); link(rr):=qq; link(qq):=ss;
  5423    attr_loc(qq):=n; name_type(qq):=attr; type(qq):=undefined;
  5424    parent(qq):=pp; ss:=qq;
  5425    end;
  5426  if p=pp then
  5427    begin p:=ss; pp:=ss;
  5428    end
  5429  else  begin pp:=ss; s:=attr_head(p);
  5430    repeat r:=s; s:=link(s);
  5431    until n<=attr_loc(s);
  5432    if n=attr_loc(s) then p:=s
  5433    else  begin q:=get_node(attr_node_size); link(r):=q; link(q):=s;
  5434      attr_loc(q):=n; name_type(q):=attr; type(q):=undefined;
  5435      parent(q):=p; p:=q;
  5436      end;
  5437    end;
  5438  end
  5439  
  5440  @ Variables lose their former values when they appear in a type declaration,
  5441  or when they are defined to be macros or \&{let} equal to something else.
  5442  A subroutine will be defined later that recycles the storage associated
  5443  with any particular |type| or |value|; our goal now is to study a higher
  5444  level process called |flush_variable|, which selectively frees parts of a
  5445  variable structure.
  5446  
  5447  This routine has some complexity because of examples such as
  5448  `\hbox{\tt numeric x[]a[]b}',
  5449  which recycles all variables of the form \.{x[i]a[j]b} (and no others), while
  5450  `\hbox{\tt vardef x[]a[]=...}'
  5451  discards all variables of the form \.{x[i]a[j]} followed by an arbitrary
  5452  suffix, except for the collective node \.{x[]a[]} itself. The obvious way
  5453  to handle such examples is to use recursion; so that's what we~do.
  5454  @^recursion@>
  5455  
  5456  Parameter |p| points to the root information of the variable;
  5457  parameter |t| points to a list of one-word nodes that represent
  5458  suffixes, with |info=collective_subscript| for subscripts.
  5459  
  5460  @p @t\4@>@<Declare subroutines for printing expressions@>@;@/
  5461  @t\4@>@<Declare basic dependency-list subroutines@>@;
  5462  @t\4@>@<Declare the recycling subroutines@>@;
  5463  @t\4@>@<Declare the procedure called |flush_cur_exp|@>@;
  5464  @t\4@>@<Declare the procedure called |flush_below_variable|@>@;
  5465  procedure flush_variable(@!p,@!t:pointer;@!discard_suffixes:boolean);
  5466  label exit;
  5467  var @!q,@!r:pointer; {list manipulation}
  5468  @!n:halfword; {attribute to match}
  5469  begin while t<>null do
  5470    begin if type(p)<>structured then return;
  5471    n:=info(t); t:=link(t);
  5472    if n=collective_subscript then
  5473      begin r:=subscr_head_loc(p); q:=link(r); {|q=subscr_head(p)|}
  5474      while name_type(q)=subscr do
  5475        begin flush_variable(q,t,discard_suffixes);
  5476        if t=null then
  5477          if type(q)=structured then r:=q
  5478          else  begin link(r):=link(q); free_node(q,subscr_node_size);
  5479            end
  5480        else r:=q;
  5481        q:=link(r);
  5482        end;
  5483      end;
  5484    p:=attr_head(p);
  5485    repeat r:=p; p:=link(p);
  5486    until attr_loc(p)>=n;
  5487    if attr_loc(p)<>n then return;
  5488    end;
  5489  if discard_suffixes then flush_below_variable(p)
  5490  else  begin if type(p)=structured then p:=attr_head(p);
  5491    recycle_value(p);
  5492    end;
  5493  exit:end;
  5494  
  5495  @ The next procedure is simpler; it wipes out everything but |p| itself,
  5496  which becomes undefined.
  5497  
  5498  @<Declare the procedure called |flush_below_variable|@>=
  5499  procedure flush_below_variable(@!p:pointer);
  5500  var @!q,@!r:pointer; {list manipulation registers}
  5501  begin if type(p)<>structured then
  5502    recycle_value(p) {this sets |type(p)=undefined|}
  5503  else  begin q:=subscr_head(p);
  5504    while name_type(q)=subscr do
  5505      begin flush_below_variable(q); r:=q; q:=link(q);
  5506      free_node(r,subscr_node_size);
  5507      end;
  5508    r:=attr_head(p); q:=link(r); recycle_value(r);
  5509    if name_type(p)<=saved_root then free_node(r,value_node_size)
  5510    else free_node(r,subscr_node_size);
  5511      {we assume that |subscr_node_size=attr_node_size|}
  5512    repeat flush_below_variable(q); r:=q; q:=link(q); free_node(r,attr_node_size);
  5513    until q=end_attr;
  5514    type(p):=undefined;
  5515    end;
  5516  end;
  5517  
  5518  @ Just before assigning a new value to a variable, we will recycle the
  5519  old value and make the old value undefined. The |und_type| routine
  5520  determines what type of undefined value should be given, based on
  5521  the current type before recycling.
  5522  
  5523  @p function und_type(@!p:pointer):small_number;
  5524  begin case type(p) of
  5525  undefined,vacuous:und_type:=undefined;
  5526  boolean_type,unknown_boolean:und_type:=unknown_boolean;
  5527  string_type,unknown_string:und_type:=unknown_string;
  5528  pen_type,unknown_pen,future_pen:und_type:=unknown_pen;
  5529  path_type,unknown_path:und_type:=unknown_path;
  5530  picture_type,unknown_picture:und_type:=unknown_picture;
  5531  transform_type,pair_type,numeric_type:und_type:=type(p);
  5532  known,dependent,proto_dependent,independent:und_type:=numeric_type;
  5533  end; {there are no other cases}
  5534  end;
  5535  
  5536  @ The |clear_symbol| routine is used when we want to redefine the equivalent
  5537  of a symbolic token. It must remove any variable structure or macro
  5538  definition that is currently attached to that symbol. If the |saving|
  5539  parameter is true, a subsidiary structure is saved instead of destroyed.
  5540  
  5541  @p procedure clear_symbol(@!p:pointer;@!saving:boolean);
  5542  var @!q:pointer; {|equiv(p)|}
  5543  begin q:=equiv(p);
  5544  case eq_type(p) mod outer_tag of
  5545  defined_macro,secondary_primary_macro,tertiary_secondary_macro,
  5546   expression_tertiary_macro: if not saving then delete_mac_ref(q);
  5547  tag_token:if q<>null then
  5548    if saving then name_type(q):=saved_root
  5549    else  begin flush_below_variable(q); free_node(q,value_node_size);
  5550      end;@;
  5551  othercases do_nothing
  5552  endcases;@/
  5553  eqtb[p]:=eqtb[frozen_undefined];
  5554  end;
  5555  
  5556  @* \[16] Saving and restoring equivalents.
  5557  The nested structure provided by \&{begingroup} and \&{endgroup}
  5558  allows |eqtb| entries to be saved and restored, so that temporary changes
  5559  can be made without difficulty.  When the user requests a current value to
  5560  be saved, \MF\ puts that value into its ``save stack.'' An appearance of
  5561  \&{endgroup} ultimately causes the old values to be removed from the save
  5562  stack and put back in their former places.
  5563  
  5564  The save stack is a linked list containing three kinds of entries,
  5565  distinguished by their |info| fields. If |p| points to a saved item,
  5566  then
  5567  
  5568  \smallskip\hang
  5569  |info(p)=0| stands for a group boundary; each \&{begingroup} contributes
  5570  such an item to the save stack and each \&{endgroup} cuts back the stack
  5571  until the most recent such entry has been removed.
  5572  
  5573  \smallskip\hang
  5574  |info(p)=q|, where |1<=q<=hash_end|, means that |mem[p+1]| holds the former
  5575  contents of |eqtb[q]|. Such save stack entries are generated by \&{save}
  5576  commands.
  5577  
  5578  \smallskip\hang
  5579  |info(p)=hash_end+q|, where |q>0|, means that |value(p)| is a |scaled|
  5580  integer to be restored to internal parameter number~|q|. Such entries
  5581  are generated by \&{interim} commands.
  5582  
  5583  \smallskip\noindent
  5584  The global variable |save_ptr| points to the top item on the save stack.
  5585  
  5586  @d save_node_size=2 {number of words per non-boundary save-stack node}
  5587  @d saved_equiv(#)==mem[#+1].hh {where an |eqtb| entry gets saved}
  5588  @d save_boundary_item(#)==begin #:=get_avail; info(#):=0;
  5589    link(#):=save_ptr; save_ptr:=#;
  5590    end
  5591  
  5592  @<Glob...@>=@!save_ptr:pointer; {the most recently saved item}
  5593  
  5594  @ @<Set init...@>=save_ptr:=null;
  5595  
  5596  @ The |save_variable| routine is given a hash address |q|; it salts this
  5597  address away in the save stack, together with its current equivalent,
  5598  then makes token~|q| behave as though it were brand new.
  5599  
  5600  Nothing is stacked when |save_ptr=null|, however; there's no way to remove
  5601  things from the stack when the program is not inside a group, so there's
  5602  no point in wasting the space.
  5603  
  5604  @p procedure save_variable(@!q:pointer);
  5605  var @!p:pointer; {temporary register}
  5606  begin if save_ptr<>null then
  5607    begin p:=get_node(save_node_size); info(p):=q; link(p):=save_ptr;
  5608    saved_equiv(p):=eqtb[q]; save_ptr:=p;
  5609    end;
  5610  clear_symbol(q,(save_ptr<>null));
  5611  end;
  5612  
  5613  @ Similarly, |save_internal| is given the location |q| of an internal
  5614  quantity like |tracing_pens|. It creates a save stack entry of the
  5615  third kind.
  5616  
  5617  @p procedure save_internal(@!q:halfword);
  5618  var @!p:pointer; {new item for the save stack}
  5619  begin if save_ptr<>null then
  5620    begin p:=get_node(save_node_size); info(p):=hash_end+q;
  5621    link(p):=save_ptr; value(p):=internal[q]; save_ptr:=p;
  5622    end;
  5623  end;
  5624  
  5625  @ At the end of a group, the |unsave| routine restores all of the saved
  5626  equivalents in reverse order. This routine will be called only when there
  5627  is at least one boundary item on the save stack.
  5628  
  5629  @p procedure unsave;
  5630  var @!q:pointer; {index to saved item}
  5631  @!p:pointer; {temporary register}
  5632  begin while info(save_ptr)<>0 do
  5633    begin q:=info(save_ptr);
  5634    if q>hash_end then
  5635      begin if internal[tracing_restores]>0 then
  5636        begin begin_diagnostic; print_nl("{restoring ");
  5637        slow_print(int_name[q-(hash_end)]); print_char("=");
  5638        print_scaled(value(save_ptr)); print_char("}");
  5639        end_diagnostic(false);
  5640        end;
  5641      internal[q-(hash_end)]:=value(save_ptr);
  5642      end
  5643    else  begin if internal[tracing_restores]>0 then
  5644        begin begin_diagnostic; print_nl("{restoring ");
  5645        slow_print(text(q)); print_char("}");
  5646        end_diagnostic(false);
  5647        end;
  5648      clear_symbol(q,false);
  5649      eqtb[q]:=saved_equiv(save_ptr);
  5650      if eq_type(q) mod outer_tag=tag_token then
  5651        begin p:=equiv(q);
  5652        if p<>null then name_type(p):=root;
  5653        end;
  5654      end;
  5655    p:=link(save_ptr); free_node(save_ptr,save_node_size); save_ptr:=p;
  5656    end;
  5657  p:=link(save_ptr); free_avail(save_ptr); save_ptr:=p;
  5658  end;
  5659  
  5660  @* \[17] Data structures for paths.
  5661  When a \MF\ user specifies a path, \MF\ will create a list of knots
  5662  and control points for the associated cubic spline curves. If the
  5663  knots are $z_0$, $z_1$, \dots, $z_n$, there are control points
  5664  $z_k^+$ and $z_{k+1}^-$ such that the cubic splines between knots
  5665  $z_k$ and $z_{k+1}$ are defined by B\'ezier's formula
  5666  @:Bezier}{B\'ezier, Pierre Etienne@>
  5667  $$\eqalign{z(t)&=B(z_k,z_k^+,z_{k+1}^-,z_{k+1};t)\cr
  5668  &=(1-t)^3z_k+3(1-t)^2tz_k^++3(1-t)t^2z_{k+1}^-+t^3z_{k+1}\cr}$$
  5669  for |0<=t<=1|.
  5670  
  5671  There is a 7-word node for each knot $z_k$, containing one word of
  5672  control information and six words for the |x| and |y| coordinates
  5673  of $z_k^-$ and $z_k$ and~$z_k^+$. The control information appears
  5674  in the |left_type| and |right_type| fields, which each occupy
  5675  a quarter of the first word in the node; they specify properties
  5676  of the curve as it enters and leaves the knot. There's also a
  5677  halfword |link| field, which points to the following knot.
  5678  
  5679  If the path is a closed contour, knots 0 and |n| are identical;
  5680  i.e., the |link| in knot |n-1| points to knot~0. But if the path
  5681  is not closed, the |left_type| of knot~0 and the |right_type| of knot~|n|
  5682  are equal to |endpoint|. In the latter case the |link| in knot~|n| points
  5683  to knot~0, and the control points $z_0^-$ and $z_n^+$ are not used.
  5684  
  5685  @d left_type(#) == mem[#].hh.b0 {characterizes the path entering this knot}
  5686  @d right_type(#) == mem[#].hh.b1 {characterizes the path leaving this knot}
  5687  @d endpoint=0 {|left_type| at path beginning and |right_type| at path end}
  5688  @d x_coord(#) == mem[#+1].sc {the |x| coordinate of this knot}
  5689  @d y_coord(#) == mem[#+2].sc {the |y| coordinate of this knot}
  5690  @d left_x(#) == mem[#+3].sc {the |x| coordinate of previous control point}
  5691  @d left_y(#) == mem[#+4].sc {the |y| coordinate of previous control point}
  5692  @d right_x(#) == mem[#+5].sc {the |x| coordinate of next control point}
  5693  @d right_y(#) == mem[#+6].sc {the |y| coordinate of next control point}
  5694  @d knot_node_size=7 {number of words in a knot node}
  5695  
  5696  @ Before the B\'ezier control points have been calculated, the memory
  5697  space they will ultimately occupy is taken up by information that can be
  5698  used to compute them. There are four cases:
  5699  
  5700  \yskip
  5701  \textindent{$\bullet$} If |right_type=open|, the curve should leave
  5702  the knot in the same direction it entered; \MF\ will figure out a
  5703  suitable direction.
  5704  
  5705  \yskip
  5706  \textindent{$\bullet$} If |right_type=curl|, the curve should leave the
  5707  knot in a direction depending on the angle at which it enters the next
  5708  knot and on the curl parameter stored in |right_curl|.
  5709  
  5710  \yskip
  5711  \textindent{$\bullet$} If |right_type=given|, the curve should leave the
  5712  knot in a nonzero direction stored as an |angle| in |right_given|.
  5713  
  5714  \yskip
  5715  \textindent{$\bullet$} If |right_type=explicit|, the B\'ezier control
  5716  point for leaving this knot has already been computed; it is in the
  5717  |right_x| and |right_y| fields.
  5718  
  5719  \yskip\noindent
  5720  The rules for |left_type| are similar, but they refer to the curve entering
  5721  the knot, and to \\{left} fields instead of \\{right} fields.
  5722  
  5723  Non-|explicit| control points will be chosen based on ``tension'' parameters
  5724  in the |left_tension| and |right_tension| fields. The
  5725  `\&{atleast}' option is represented by negative tension values.
  5726  @:at_least_}{\&{atleast} primitive@>
  5727  
  5728  For example, the \MF\ path specification
  5729  $$\.{z0..z1..tension atleast 1..\{curl 2\}z2..z3\{-1,-2\}..tension
  5730    3 and 4..p},$$
  5731  where \.p is the path `\.{z4..controls z45 and z54..z5}', will be represented
  5732  by the six knots
  5733  \def\lodash{\hbox to 1.1em{\thinspace\hrulefill\thinspace}}
  5734  $$\vbox{\halign{#\hfil&&\qquad#\hfil\cr
  5735  |left_type|&\\{left} info&|x_coord,y_coord|&|right_type|&\\{right} info\cr
  5736  \noalign{\yskip}
  5737  |endpoint|&\lodash$,\,$\lodash&$x_0,y_0$&|curl|&$1.0,1.0$\cr
  5738  |open|&\lodash$,1.0$&$x_1,y_1$&|open|&\lodash$,-1.0$\cr
  5739  |curl|&$2.0,-1.0$&$x_2,y_2$&|curl|&$2.0,1.0$\cr
  5740  |given|&$d,1.0$&$x_3,y_3$&|given|&$d,3.0$\cr
  5741  |open|&\lodash$,4.0$&$x_4,y_4$&|explicit|&$x_{45},y_{45}$\cr
  5742  |explicit|&$x_{54},y_{54}$&$x_5,y_5$&|endpoint|&\lodash$,\,$\lodash\cr}}$$
  5743  Here |d| is the |angle| obtained by calling |n_arg(-unity,-two)|.
  5744  Of course, this example is more complicated than anything a normal user
  5745  would ever write.
  5746  
  5747  These types must satisfy certain restrictions because of the form of \MF's
  5748  path syntax:
  5749  (i)~|open| type never appears in the same node together with |endpoint|,
  5750  |given|, or |curl|.
  5751  (ii)~The |right_type| of a node is |explicit| if and only if the
  5752  |left_type| of the following node is |explicit|.
  5753  (iii)~|endpoint| types occur only at the ends, as mentioned above.
  5754  
  5755  @d left_curl==left_x {curl information when entering this knot}
  5756  @d left_given==left_x {given direction when entering this knot}
  5757  @d left_tension==left_y {tension information when entering this knot}
  5758  @d right_curl==right_x {curl information when leaving this knot}
  5759  @d right_given==right_x {given direction when leaving this knot}
  5760  @d right_tension==right_y {tension information when leaving this knot}
  5761  @d explicit=1 {|left_type| or |right_type| when control points are known}
  5762  @d given=2 {|left_type| or |right_type| when a direction is given}
  5763  @d curl=3 {|left_type| or |right_type| when a curl is desired}
  5764  @d open=4 {|left_type| or |right_type| when \MF\ should choose the direction}
  5765  
  5766  @ Here is a diagnostic routine that prints a given knot list
  5767  in symbolic form. It illustrates the conventions discussed above,
  5768  and checks for anomalies that might arise while \MF\ is being debugged.
  5769  
  5770  @<Declare subroutines for printing expressions@>=
  5771  procedure print_path(@!h:pointer;@!s:str_number;@!nuline:boolean);
  5772  label done,done1;
  5773  var @!p,@!q:pointer; {for list traversal}
  5774  begin print_diagnostic("Path",s,nuline); print_ln;
  5775  @.Path at line...@>
  5776  p:=h;
  5777  repeat q:=link(p);
  5778  if (p=null)or(q=null) then
  5779    begin print_nl("???"); goto done; {this won't happen}
  5780  @.???@>
  5781    end;
  5782  @<Print information for adjacent knots |p| and |q|@>;
  5783  p:=q;
  5784  if (p<>h)or(left_type(h)<>endpoint) then
  5785    @<Print two dots, followed by |given| or |curl| if present@>;
  5786  until p=h;
  5787  if left_type(h)<>endpoint then print("cycle");
  5788  done:end_diagnostic(true);
  5789  end;
  5790  
  5791  @ @<Print information for adjacent knots...@>=
  5792  print_two(x_coord(p),y_coord(p));
  5793  case right_type(p) of
  5794  endpoint: begin if left_type(p)=open then print("{open?}"); {can't happen}
  5795  @.open?@>
  5796    if (left_type(q)<>endpoint)or(q<>h) then q:=null; {force an error}
  5797    goto done1;
  5798    end;
  5799  explicit: @<Print control points between |p| and |q|, then |goto done1|@>;
  5800  open: @<Print information for a curve that begins |open|@>;
  5801  curl,given: @<Print information for a curve that begins |curl| or |given|@>;
  5802  othercases print("???") {can't happen}
  5803  @.???@>
  5804  endcases;@/
  5805  if left_type(q)<=explicit then print("..control?") {can't happen}
  5806  @.control?@>
  5807  else if (right_tension(p)<>unity)or(left_tension(q)<>unity) then
  5808    @<Print tension between |p| and |q|@>;
  5809  done1:
  5810  
  5811  @ Since |n_sin_cos| produces |fraction| results, which we will print as if they
  5812  were |scaled|, the magnitude of a |given| direction vector will be~4096.
  5813  
  5814  @<Print two dots...@>=
  5815  begin print_nl(" ..");
  5816  if left_type(p)=given then
  5817    begin n_sin_cos(left_given(p)); print_char("{");
  5818    print_scaled(n_cos); print_char(",");
  5819    print_scaled(n_sin); print_char("}");
  5820    end
  5821  else if left_type(p)=curl then
  5822    begin print("{curl "); print_scaled(left_curl(p)); print_char("}");
  5823    end;
  5824  end
  5825  
  5826  @ @<Print tension between |p| and |q|@>=
  5827  begin print("..tension ");
  5828  if right_tension(p)<0 then print("atleast");
  5829  print_scaled(abs(right_tension(p)));
  5830  if right_tension(p)<>left_tension(q) then
  5831    begin print(" and ");
  5832    if left_tension(q)<0 then print("atleast");
  5833    print_scaled(abs(left_tension(q)));
  5834    end;
  5835  end
  5836  
  5837  @ @<Print control points between |p| and |q|, then |goto done1|@>=
  5838  begin print("..controls "); print_two(right_x(p),right_y(p)); print(" and ");
  5839  if left_type(q)<>explicit then print("??") {can't happen}
  5840  @.??@>
  5841  else print_two(left_x(q),left_y(q));
  5842  goto done1;
  5843  end
  5844  
  5845  @ @<Print information for a curve that begins |open|@>=
  5846  if (left_type(p)<>explicit)and(left_type(p)<>open) then
  5847    print("{open?}") {can't happen}
  5848  @.open?@>
  5849  
  5850  @ A curl of 1 is shown explicitly, so that the user sees clearly that
  5851  \MF's default curl is present.
  5852  
  5853  @<Print information for a curve that begins |curl|...@>=
  5854  begin if left_type(p)=open then print("??"); {can't happen}
  5855  @.??@>
  5856  if right_type(p)=curl then
  5857    begin print("{curl "); print_scaled(right_curl(p));
  5858    end
  5859  else  begin n_sin_cos(right_given(p)); print_char("{");
  5860    print_scaled(n_cos); print_char(","); print_scaled(n_sin);
  5861    end;
  5862  print_char("}");
  5863  end
  5864  
  5865  @ If we want to duplicate a knot node, we can say |copy_knot|:
  5866  
  5867  @p function copy_knot(@!p:pointer):pointer;
  5868  var @!q:pointer; {the copy}
  5869  @!k:0..knot_node_size-1; {runs through the words of a knot node}
  5870  begin q:=get_node(knot_node_size);
  5871  for k:=0 to knot_node_size-1 do mem[q+k]:=mem[p+k];
  5872  copy_knot:=q;
  5873  end;
  5874  
  5875  @ The |copy_path| routine makes a clone of a given path.
  5876  
  5877  @p function copy_path(@!p:pointer):pointer;
  5878  label exit;
  5879  var @!q,@!pp,@!qq:pointer; {for list manipulation}
  5880  begin q:=get_node(knot_node_size); {this will correspond to |p|}
  5881  qq:=q; pp:=p;
  5882  loop@+  begin left_type(qq):=left_type(pp);
  5883    right_type(qq):=right_type(pp);@/
  5884    x_coord(qq):=x_coord(pp); y_coord(qq):=y_coord(pp);@/
  5885    left_x(qq):=left_x(pp); left_y(qq):=left_y(pp);@/
  5886    right_x(qq):=right_x(pp); right_y(qq):=right_y(pp);@/
  5887    if link(pp)=p then
  5888      begin link(qq):=q; copy_path:=q; return;
  5889      end;
  5890    link(qq):=get_node(knot_node_size); qq:=link(qq); pp:=link(pp);
  5891    end;
  5892  exit:end;
  5893  
  5894  @ Similarly, there's a way to copy the {\sl reverse\/} of a path. This procedure
  5895  returns a pointer to the first node of the copy, if the path is a cycle,
  5896  but to the final node of a non-cyclic copy. The global
  5897  variable |path_tail| will point to the final node of the original path;
  5898  this trick makes it easier to implement `\&{doublepath}'.
  5899  
  5900  All node types are assumed to be |endpoint| or |explicit| only.
  5901  
  5902  @p function htap_ypoc(@!p:pointer):pointer;
  5903  label exit;
  5904  var @!q,@!pp,@!qq,@!rr:pointer; {for list manipulation}
  5905  begin q:=get_node(knot_node_size); {this will correspond to |p|}
  5906  qq:=q; pp:=p;
  5907  loop@+  begin right_type(qq):=left_type(pp); left_type(qq):=right_type(pp);@/
  5908    x_coord(qq):=x_coord(pp); y_coord(qq):=y_coord(pp);@/
  5909    right_x(qq):=left_x(pp); right_y(qq):=left_y(pp);@/
  5910    left_x(qq):=right_x(pp); left_y(qq):=right_y(pp);@/
  5911    if link(pp)=p then
  5912      begin link(q):=qq; path_tail:=pp; htap_ypoc:=q; return;
  5913      end;
  5914    rr:=get_node(knot_node_size); link(rr):=qq; qq:=rr; pp:=link(pp);
  5915    end;
  5916  exit:end;
  5917  
  5918  @ @<Glob...@>=
  5919  @!path_tail:pointer; {the node that links to the beginning of a path}
  5920  
  5921  @ When a cyclic list of knot nodes is no longer needed, it can be recycled by
  5922  calling the following subroutine.
  5923  
  5924  @<Declare the recycling subroutines@>=
  5925  procedure toss_knot_list(@!p:pointer);
  5926  var @!q:pointer; {the node being freed}
  5927  @!r:pointer; {the next node}
  5928  begin q:=p;
  5929  repeat r:=link(q); free_node(q,knot_node_size); q:=r;
  5930  until q=p;
  5931  end;
  5932  
  5933  @* \[18] Choosing control points.
  5934  Now we must actually delve into one of \MF's more difficult routines,
  5935  the |make_choices| procedure that chooses angles and control points for
  5936  the splines of a curve when the user has not specified them explicitly.
  5937  The parameter to |make_choices| points to a list of knots and
  5938  path information, as described above.
  5939  
  5940  A path decomposes into independent segments at ``breakpoint'' knots,
  5941  which are knots whose left and right angles are both prespecified in
  5942  some way (i.e., their |left_type| and |right_type| aren't both open).
  5943  
  5944  @p @t\4@>@<Declare the procedure called |solve_choices|@>@;
  5945  procedure make_choices(@!knots:pointer);
  5946  label done;
  5947  var @!h:pointer; {the first breakpoint}
  5948  @!p,@!q:pointer; {consecutive breakpoints being processed}
  5949  @<Other local variables for |make_choices|@>@;
  5950  begin check_arith; {make sure that |arith_error=false|}
  5951  if internal[tracing_choices]>0 then
  5952    print_path(knots,", before choices",true);
  5953  @<If consecutive knots are equal, join them explicitly@>;
  5954  @<Find the first breakpoint, |h|, on the path;
  5955    insert an artificial breakpoint if the path is an unbroken cycle@>;
  5956  p:=h;
  5957  repeat @<Fill in the control points between |p| and the next breakpoint,
  5958    then advance |p| to that breakpoint@>;
  5959  until p=h;
  5960  if internal[tracing_choices]>0 then
  5961    print_path(knots,", after choices",true);
  5962  if arith_error then @<Report an unexpected problem during the choice-making@>;
  5963  end;
  5964  
  5965  @ @<Report an unexpected problem during the choice...@>=
  5966  begin print_err("Some number got too big");
  5967  @.Some number got too big@>
  5968  help2("The path that I just computed is out of range.")@/
  5969    ("So it will probably look funny. Proceed, for a laugh.");
  5970  put_get_error; arith_error:=false;
  5971  end
  5972  
  5973  @ Two knots in a row with the same coordinates will always be joined
  5974  by an explicit ``curve'' whose control points are identical with the
  5975  knots.
  5976  
  5977  @<If consecutive knots are equal, join them explicitly@>=
  5978  p:=knots;
  5979  repeat q:=link(p);
  5980  if x_coord(p)=x_coord(q) then if y_coord(p)=y_coord(q) then
  5981   if right_type(p)>explicit then
  5982    begin right_type(p):=explicit;
  5983    if left_type(p)=open then
  5984      begin left_type(p):=curl; left_curl(p):=unity;
  5985      end;
  5986    left_type(q):=explicit;
  5987    if right_type(q)=open then
  5988      begin right_type(q):=curl; right_curl(q):=unity;
  5989      end;
  5990    right_x(p):=x_coord(p); left_x(q):=x_coord(p);@/
  5991    right_y(p):=y_coord(p); left_y(q):=y_coord(p);
  5992    end;
  5993  p:=q;
  5994  until p=knots
  5995  
  5996  @ If there are no breakpoints, it is necessary to compute the direction
  5997  angles around an entire cycle. In this case the |left_type| of the first
  5998  node is temporarily changed to |end_cycle|.
  5999  
  6000  @d end_cycle=open+1
  6001  
  6002  @<Find the first breakpoint, |h|, on the path...@>=
  6003  h:=knots;
  6004  loop@+  begin if left_type(h)<>open then goto done;
  6005    if right_type(h)<>open then goto done;
  6006    h:=link(h);
  6007    if h=knots then
  6008      begin left_type(h):=end_cycle; goto done;
  6009      end;
  6010    end;
  6011  done:
  6012  
  6013  @ If |right_type(p)<given| and |q=link(p)|, we must have
  6014  |right_type(p)=left_type(q)=explicit| or |endpoint|.
  6015  
  6016  @<Fill in the control points between |p| and the next breakpoint...@>=
  6017  q:=link(p);
  6018  if right_type(p)>=given then
  6019    begin while (left_type(q)=open)and(right_type(q)=open) do q:=link(q);
  6020    @<Fill in the control information between
  6021      consecutive breakpoints |p| and |q|@>;
  6022    end;
  6023  p:=q
  6024  
  6025  @ Before we can go further into the way choices are made, we need to
  6026  consider the underlying theory. The basic ideas implemented in |make_choices|
  6027  are due to John Hobby, who introduced the notion of ``mock curvature''
  6028  @^Hobby, John Douglas@>
  6029  at a knot. Angles are chosen so that they preserve mock curvature when
  6030  a knot is passed, and this has been found to produce excellent results.
  6031  
  6032  It is convenient to introduce some notations that simplify the necessary
  6033  formulas. Let $d_{k,k+1}=\vert z\k-z_k\vert$ be the (nonzero) distance
  6034  between knots |k| and |k+1|; and let
  6035  $${z\k-z_k\over z_k-z_{k-1}}={d_{k,k+1}\over d_{k-1,k}}e^{i\psi_k}$$
  6036  so that a polygonal line from $z_{k-1}$ to $z_k$ to $z\k$ turns left
  6037  through an angle of~$\psi_k$. We assume that $\vert\psi_k\vert\L180^\circ$.
  6038  The control points for the spline from $z_k$ to $z\k$ will be denoted by
  6039  $$\eqalign{z_k^+&=z_k+
  6040    \textstyle{1\over3}\rho_k e^{i\theta_k}(z\k-z_k),\cr
  6041   z\k^-&=z\k-
  6042    \textstyle{1\over3}\sigma\k e^{-i\phi\k}(z\k-z_k),\cr}$$
  6043  where $\rho_k$ and $\sigma\k$ are nonnegative ``velocity ratios'' at the
  6044  beginning and end of the curve, while $\theta_k$ and $\phi\k$ are the
  6045  corresponding ``offset angles.'' These angles satisfy the condition
  6046  $$\theta_k+\phi_k+\psi_k=0,\eqno(*)$$
  6047  whenever the curve leaves an intermediate knot~|k| in the direction that
  6048  it enters.
  6049  
  6050  @ Let $\alpha_k$ and $\beta\k$ be the reciprocals of the ``tension'' of
  6051  the curve at its beginning and ending points. This means that
  6052  $\rho_k=\alpha_k f(\theta_k,\phi\k)$ and $\sigma\k=\beta\k f(\phi\k,\theta_k)$,
  6053  where $f(\theta,\phi)$ is \MF's standard velocity function defined in
  6054  the |velocity| subroutine. The cubic spline $B(z_k^{\phantom+},z_k^+,
  6055  z\k^-,z\k^{\phantom+};t)$
  6056  has curvature
  6057  @^curvature@>
  6058  $${2\sigma\k\sin(\theta_k+\phi\k)-6\sin\theta_k\over\rho_k^2d_{k,k+1}}
  6059  \qquad{\rm and}\qquad
  6060  {2\rho_k\sin(\theta_k+\phi\k)-6\sin\phi\k\over\sigma\k^2d_{k,k+1}}$$
  6061  at |t=0| and |t=1|, respectively. The mock curvature is the linear
  6062  @^mock curvature@>
  6063  approximation to this true curvature that arises in the limit for
  6064  small $\theta_k$ and~$\phi\k$, if second-order terms are discarded.
  6065  The standard velocity function satisfies
  6066  $$f(\theta,\phi)=1+O(\theta^2+\theta\phi+\phi^2);$$
  6067  hence the mock curvatures are respectively
  6068  $${2\beta\k(\theta_k+\phi\k)-6\theta_k\over\alpha_k^2d_{k,k+1}}
  6069  \qquad{\rm and}\qquad
  6070  {2\alpha_k(\theta_k+\phi\k)-6\phi\k\over\beta\k^2d_{k,k+1}}.\eqno(**)$$
  6071  
  6072  @ The turning angles $\psi_k$ are given, and equation $(*)$ above
  6073  determines $\phi_k$ when $\theta_k$ is known, so the task of
  6074  angle selection is essentially to choose appropriate values for each
  6075  $\theta_k$. When equation~$(*)$ is used to eliminate $\phi$~variables
  6076  from $(**)$, we obtain a system of linear equations of the form
  6077  $$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k,$$
  6078  where
  6079  $$A_k={\alpha_{k-1}\over\beta_k^2d_{k-1,k}},
  6080  \qquad B_k={3-\alpha_{k-1}\over\beta_k^2d_{k-1,k}},
  6081  \qquad C_k={3-\beta\k\over\alpha_k^2d_{k,k+1}},
  6082  \qquad D_k={\beta\k\over\alpha_k^2d_{k,k+1}}.$$
  6083  The tensions are always $3\over4$ or more, hence each $\alpha$ and~$\beta$
  6084  will be at most $4\over3$. It follows that $B_k\G{5\over4}A_k$ and
  6085  $C_k\G{5\over4}D_k$; hence the equations are diagonally dominant;
  6086  hence they have a unique solution. Moreover, in most cases the tensions
  6087  are equal to~1, so that $B_k=2A_k$ and $C_k=2D_k$. This makes the
  6088  solution numerically stable, and there is an exponential damping
  6089  effect: The data at knot $k\pm j$ affects the angle at knot~$k$ by
  6090  a factor of~$O(2^{-j})$.
  6091  
  6092  @ However, we still must consider the angles at the starting and ending
  6093  knots of a non-cyclic path. These angles might be given explicitly, or
  6094  they might be specified implicitly in terms of an amount of ``curl.''
  6095  
  6096  Let's assume that angles need to be determined for a non-cyclic path
  6097  starting at $z_0$ and ending at~$z_n$. Then equations of the form
  6098  $$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta_{k+1}=R_k$$
  6099  have been given for $0<k<n$, and it will be convenient to introduce
  6100  equations of the same form for $k=0$ and $k=n$, where
  6101  $$A_0=B_0=C_n=D_n=0.$$
  6102  If $\theta_0$ is supposed to have a given value $E_0$, we simply
  6103  define $C_0=1$, $D_0=0$, and $R_0=E_0$. Otherwise a curl
  6104  parameter, $\gamma_0$, has been specified at~$z_0$; this means
  6105  that the mock curvature at $z_0$ should be $\gamma_0$ times the
  6106  mock curvature at $z_1$; i.e.,
  6107  $${2\beta_1(\theta_0+\phi_1)-6\theta_0\over\alpha_0^2d_{01}}
  6108  =\gamma_0{2\alpha_0(\theta_0+\phi_1)-6\phi_1\over\beta_1^2d_{01}}.$$
  6109  This equation simplifies to
  6110  $$(\alpha_0\chi_0+3-\beta_1)\theta_0+
  6111   \bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\theta_1=
  6112   -\bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\psi_1,$$
  6113  where $\chi_0=\alpha_0^2\gamma_0/\beta_1^2$; so we can set $C_0=
  6114  \chi_0\alpha_0+3-\beta_1$, $D_0=(3-\alpha_0)\chi_0+\beta_1$, $R_0=-D_0\psi_1$.
  6115  It can be shown that $C_0>0$ and $C_0B_1-A_1D_0>0$ when $\gamma_0\G0$,
  6116  hence the linear equations remain nonsingular.
  6117  
  6118  Similar considerations apply at the right end, when the final angle $\phi_n$
  6119  may or may not need to be determined. It is convenient to let $\psi_n=0$,
  6120  hence $\theta_n=-\phi_n$. We either have an explicit equation $\theta_n=E_n$,
  6121  or we have
  6122  $$\bigl((3-\beta_n)\chi_n+\alpha_{n-1}\bigr)\theta_{n-1}+
  6123  (\beta_n\chi_n+3-\alpha_{n-1})\theta_n=0,\qquad
  6124    \chi_n={\beta_n^2\gamma_n\over\alpha_{n-1}^2}.$$
  6125  
  6126  When |make_choices| chooses angles, it must compute the coefficients of
  6127  these linear equations, then solve the equations. To compute the coefficients,
  6128  it is necessary to compute arctangents of the given turning angles~$\psi_k$.
  6129  When the equations are solved, the chosen directions $\theta_k$ are put
  6130  back into the form of control points by essentially computing sines and
  6131  cosines.
  6132  
  6133  @ OK, we are ready to make the hard choices of |make_choices|.
  6134  Most of the work is relegated to an auxiliary procedure
  6135  called |solve_choices|, which has been introduced to keep
  6136  |make_choices| from being extremely long.
  6137  
  6138  @<Fill in the control information between...@>=
  6139  @<Calculate the turning angles $\psi_k$ and the distances $d_{k,k+1}$;
  6140    set $n$ to the length of the path@>;
  6141  @<Remove |open| types at the breakpoints@>;
  6142  solve_choices(p,q,n)
  6143  
  6144  @ It's convenient to precompute quantities that will be needed several
  6145  times later. The values of |delta_x[k]| and |delta_y[k]| will be the
  6146  coordinates of $z\k-z_k$, and the magnitude of this vector will be
  6147  |delta[k]=@t$d_{k,k+1}$@>|. The path angle $\psi_k$ between $z_k-z_{k-1}$
  6148  and $z\k-z_k$ will be stored in |psi[k]|.
  6149  
  6150  @<Glob...@>=
  6151  @!delta_x,@!delta_y,@!delta:array[0..path_size] of scaled; {knot differences}
  6152  @!psi:array[1..path_size] of angle; {turning angles}
  6153  
  6154  @ @<Other local variables for |make_choices|@>=
  6155  @!k,@!n:0..path_size; {current and final knot numbers}
  6156  @!s,@!t:pointer; {registers for list traversal}
  6157  @!delx,@!dely:scaled; {directions where |open| meets |explicit|}
  6158  @!sine,@!cosine:fraction; {trig functions of various angles}
  6159  
  6160  @ @<Calculate the turning angles...@>=
  6161  k:=0; s:=p; n:=path_size;
  6162  repeat t:=link(s);
  6163  delta_x[k]:=x_coord(t)-x_coord(s);
  6164  delta_y[k]:=y_coord(t)-y_coord(s);
  6165  delta[k]:=pyth_add(delta_x[k],delta_y[k]);
  6166  if k>0 then
  6167    begin sine:=make_fraction(delta_y[k-1],delta[k-1]);
  6168    cosine:=make_fraction(delta_x[k-1],delta[k-1]);
  6169    psi[k]:=n_arg(take_fraction(delta_x[k],cosine)+
  6170        take_fraction(delta_y[k],sine),
  6171      take_fraction(delta_y[k],cosine)-
  6172        take_fraction(delta_x[k],sine));
  6173    end;
  6174  @:METAFONT capacity exceeded path size}{\quad path size@>
  6175  incr(k); s:=t;
  6176  if k=path_size then overflow("path size",path_size);
  6177  if s=q then n:=k;
  6178  until (k>=n)and(left_type(s)<>end_cycle);
  6179  if k=n then psi[n]:=0@+else psi[k]:=psi[1]
  6180  
  6181  @ When we get to this point of the code, |right_type(p)| is either
  6182  |given| or |curl| or |open|. If it is |open|, we must have
  6183  |left_type(p)=end_cycle| or |left_type(p)=explicit|. In the latter
  6184  case, the |open| type is converted to |given|; however, if the
  6185  velocity coming into this knot is zero, the |open| type is
  6186  converted to a |curl|, since we don't know the incoming direction.
  6187  
  6188  Similarly, |left_type(q)| is either |given| or |curl| or |open| or
  6189  |end_cycle|. The |open| possibility is reduced either to |given| or to |curl|.
  6190  
  6191  @<Remove |open| types at the breakpoints@>=
  6192  if left_type(q)=open then
  6193    begin delx:=right_x(q)-x_coord(q); dely:=right_y(q)-y_coord(q);
  6194    if (delx=0)and(dely=0) then
  6195      begin left_type(q):=curl; left_curl(q):=unity;
  6196      end
  6197    else  begin left_type(q):=given; left_given(q):=n_arg(delx,dely);
  6198      end;
  6199    end;
  6200  if (right_type(p)=open)and(left_type(p)=explicit) then
  6201    begin delx:=x_coord(p)-left_x(p); dely:=y_coord(p)-left_y(p);
  6202    if (delx=0)and(dely=0) then
  6203      begin right_type(p):=curl; right_curl(p):=unity;
  6204      end
  6205    else  begin right_type(p):=given; right_given(p):=n_arg(delx,dely);
  6206      end;
  6207    end
  6208  
  6209  @ Linear equations need to be solved whenever |n>1|; and also when |n=1|
  6210  and exactly one of the breakpoints involves a curl. The simplest case occurs
  6211  when |n=1| and there is a curl at both breakpoints; then we simply draw
  6212  a straight line.
  6213  
  6214  But before coding up the simple cases, we might as well face the general case,
  6215  since we must deal with it sooner or later, and since the general case
  6216  is likely to give some insight into the way simple cases can be handled best.
  6217  
  6218  When there is no cycle, the linear equations to be solved form a tri-diagonal
  6219  system, and we can apply the standard technique of Gaussian elimination
  6220  to convert that system to a sequence of equations of the form
  6221  $$\theta_0+u_0\theta_1=v_0,\quad
  6222  \theta_1+u_1\theta_2=v_1,\quad\ldots,\quad
  6223  \theta_{n-1}+u_{n-1}\theta_n=v_{n-1},\quad
  6224  \theta_n=v_n.$$
  6225  It is possible to do this diagonalization while generating the equations.
  6226  Once $\theta_n$ is known, it is easy to determine $\theta_{n-1}$, \dots,
  6227  $\theta_1$, $\theta_0$; thus, the equations will be solved.
  6228  
  6229  The procedure is slightly more complex when there is a cycle, but the
  6230  basic idea will be nearly the same. In the cyclic case the right-hand
  6231  sides will be $v_k+w_k\theta_0$ instead of simply $v_k$, and we will start
  6232  the process off with $u_0=v_0=0$, $w_0=1$. The final equation will be not
  6233  $\theta_n=v_n$ but $\theta_n+u_n\theta_1=v_n+w_n\theta_0$; an appropriate
  6234  ending routine will take account of the fact that $\theta_n=\theta_0$ and
  6235  eliminate the $w$'s from the system, after which the solution can be
  6236  obtained as before.
  6237  
  6238  When $u_k$, $v_k$, and $w_k$ are being computed, the three pointer
  6239  variables |r|, |s|,~|t| will point respectively to knots |k-1|, |k|,
  6240  and~|k+1|. The $u$'s and $w$'s are scaled by $2^{28}$, i.e., they are
  6241  of type |fraction|; the $\theta$'s and $v$'s are of type |angle|.
  6242  
  6243  @<Glob...@>=
  6244  @!theta:array[0..path_size] of angle; {values of $\theta_k$}
  6245  @!uu:array[0..path_size] of fraction; {values of $u_k$}
  6246  @!vv:array[0..path_size] of angle; {values of $v_k$}
  6247  @!ww:array[0..path_size] of fraction; {values of $w_k$}
  6248  
  6249  @ Our immediate problem is to get the ball rolling by setting up the
  6250  first equation or by realizing that no equations are needed, and to fit
  6251  this initialization into a framework suitable for the overall computation.
  6252  
  6253  @<Declare the procedure called |solve_choices|@>=
  6254  @t\4@>@<Declare subroutines needed by |solve_choices|@>@;
  6255  procedure solve_choices(@!p,@!q:pointer;@!n:halfword);
  6256  label found,exit;
  6257  var @!k:0..path_size; {current knot number}
  6258  @!r,@!s,@!t:pointer; {registers for list traversal}
  6259  @<Other local variables for |solve_choices|@>@;
  6260  begin k:=0; s:=p;
  6261  loop@+  begin t:=link(s);
  6262    if k=0 then @<Get the linear equations started; or |return|
  6263      with the control points in place, if linear equations
  6264      needn't be solved@>
  6265    else  case left_type(s) of
  6266      end_cycle,open:@<Set up equation to match mock curvatures
  6267        at $z_k$; then |goto found| with $\theta_n$
  6268        adjusted to equal $\theta_0$, if a cycle has ended@>;
  6269      curl:@<Set up equation for a curl at $\theta_n$
  6270        and |goto found|@>;
  6271      given:@<Calculate the given value of $\theta_n$
  6272        and |goto found|@>;
  6273      end; {there are no other cases}
  6274    r:=s; s:=t; incr(k);
  6275    end;
  6276  found:@<Finish choosing angles and assigning control points@>;
  6277  exit:end;
  6278  
  6279  @ On the first time through the loop, we have |k=0| and |r| is not yet
  6280  defined. The first linear equation, if any, will have $A_0=B_0=0$.
  6281  
  6282  @<Get the linear equations started...@>=
  6283  case right_type(s) of
  6284  given: if left_type(t)=given then @<Reduce to simple case of two givens
  6285      and |return|@>
  6286    else @<Set up the equation for a given value of $\theta_0$@>;
  6287  curl: if left_type(t)=curl then @<Reduce to simple case of straight line
  6288      and |return|@>
  6289    else @<Set up the equation for a curl at $\theta_0$@>;
  6290  open: begin uu[0]:=0; vv[0]:=0; ww[0]:=fraction_one;
  6291    end; {this begins a cycle}
  6292  end {there are no other cases}
  6293  
  6294  @ The general equation that specifies equality of mock curvature at $z_k$ is
  6295  $$A_k\theta_{k-1}+(B_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k,$$
  6296  as derived above. We want to combine this with the already-derived equation
  6297  $\theta_{k-1}+u_{k-1}\theta_k=v_{k-1}+w_{k-1}\theta_0$ in order to obtain
  6298  a new equation
  6299  $\theta_k+u_k\theta\k=v_k+w_k\theta_0$. This can be done by dividing the
  6300  equation
  6301  $$(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}
  6302      -A_kw_{k-1}\theta_0$$
  6303  by $B_k-u_{k-1}A_k+C_k$. The trick is to do this carefully with
  6304  fixed-point arithmetic, avoiding the chance of overflow while retaining
  6305  suitable precision.
  6306  
  6307  The calculations will be performed in several registers that
  6308  provide temporary storage for intermediate quantities.
  6309  
  6310  @<Other local variables for |solve_choices|@>=
  6311  @!aa,@!bb,@!cc,@!ff,@!acc:fraction; {temporary registers}
  6312  @!dd,@!ee:scaled; {likewise, but |scaled|}
  6313  @!lt,@!rt:scaled; {tension values}
  6314  
  6315  @ @<Set up equation to match mock curvatures...@>=
  6316  begin @<Calculate the values $\\{aa}=A_k/B_k$, $\\{bb}=D_k/C_k$,
  6317    $\\{dd}=(3-\alpha_{k-1})d_{k,k+1}$, $\\{ee}=(3-\beta\k)d_{k-1,k}$,
  6318    and $\\{cc}=(B_k-u_{k-1}A_k)/B_k$@>;
  6319  @<Calculate the ratio $\\{ff}=C_k/(C_k+B_k-u_{k-1}A_k)$@>;
  6320  uu[k]:=take_fraction(ff,bb);
  6321  @<Calculate the values of $v_k$ and $w_k$@>;
  6322  if left_type(s)=end_cycle then
  6323    @<Adjust $\theta_n$ to equal $\theta_0$ and |goto found|@>;
  6324  end
  6325  
  6326  @ Since tension values are never less than 3/4, the values |aa| and
  6327  |bb| computed here are never more than 4/5.
  6328  
  6329  @<Calculate the values $\\{aa}=...@>=
  6330  if abs(right_tension(r))=unity then
  6331    begin aa:=fraction_half; dd:=2*delta[k];
  6332    end
  6333  else  begin aa:=make_fraction(unity,3*abs(right_tension(r))-unity);
  6334    dd:=take_fraction(delta[k],
  6335      fraction_three-make_fraction(unity,abs(right_tension(r))));
  6336    end;
  6337  if abs(left_tension(t))=unity then
  6338    begin bb:=fraction_half; ee:=2*delta[k-1];
  6339    end
  6340  else  begin bb:=make_fraction(unity,3*abs(left_tension(t))-unity);
  6341    ee:=take_fraction(delta[k-1],
  6342      fraction_three-make_fraction(unity,abs(left_tension(t))));
  6343    end;
  6344  cc:=fraction_one-take_fraction(uu[k-1],aa)
  6345  
  6346  @ The ratio to be calculated in this step can be written in the form
  6347  $$\beta_k^2\cdot\\{ee}\over\beta_k^2\cdot\\{ee}+\alpha_k^2\cdot
  6348    \\{cc}\cdot\\{dd},$$
  6349  because of the quantities just calculated. The values of |dd| and |ee|
  6350  will not be needed after this step has been performed.
  6351  
  6352  @<Calculate the ratio $\\{ff}=C_k/(C_k+B_k-u_{k-1}A_k)$@>=
  6353  dd:=take_fraction(dd,cc); lt:=abs(left_tension(s)); rt:=abs(right_tension(s));
  6354  if lt<>rt then {$\beta_k^{-1}\ne\alpha_k^{-1}$}
  6355    if lt<rt then
  6356      begin ff:=make_fraction(lt,rt);
  6357      ff:=take_fraction(ff,ff); {$\alpha_k^2/\beta_k^2$}
  6358      dd:=take_fraction(dd,ff);
  6359      end
  6360    else  begin ff:=make_fraction(rt,lt);
  6361      ff:=take_fraction(ff,ff); {$\beta_k^2/\alpha_k^2$}
  6362      ee:=take_fraction(ee,ff);
  6363      end;
  6364  ff:=make_fraction(ee,ee+dd)
  6365  
  6366  @ The value of $u_{k-1}$ will be |<=1| except when $k=1$ and the previous
  6367  equation was specified by a curl. In that case we must use a special
  6368  method of computation to prevent overflow.
  6369  
  6370  Fortunately, the calculations turn out to be even simpler in this ``hard''
  6371  case. The curl equation makes $w_0=0$ and $v_0=-u_0\psi_1$, hence
  6372  $-B_1\psi_1-A_1v_0=-(B_1-u_0A_1)\psi_1=-\\{cc}\cdot B_1\psi_1$.
  6373  
  6374  @<Calculate the values of $v_k$ and $w_k$@>=
  6375  acc:=-take_fraction(psi[k+1],uu[k]);
  6376  if right_type(r)=curl then
  6377    begin ww[k]:=0;
  6378    vv[k]:=acc-take_fraction(psi[1],fraction_one-ff);
  6379    end
  6380  else  begin ff:=make_fraction(fraction_one-ff,cc); {this is
  6381      $B_k/(C_k+B_k-u_{k-1}A_k)<5$}
  6382    acc:=acc-take_fraction(psi[k],ff);
  6383    ff:=take_fraction(ff,aa); {this is $A_k/(C_k+B_k-u_{k-1}A_k)$}
  6384    vv[k]:=acc-take_fraction(vv[k-1],ff);
  6385    if ww[k-1]=0 then ww[k]:=0
  6386    else ww[k]:=-take_fraction(ww[k-1],ff);
  6387    end
  6388  
  6389  @ When a complete cycle has been traversed, we have $\theta_k+u_k\theta\k=
  6390  v_k+w_k\theta_0$, for |1<=k<=n|. We would like to determine the value of
  6391  $\theta_n$ and reduce the system to the form $\theta_k+u_k\theta\k=v_k$
  6392  for |0<=k<n|, so that the cyclic case can be finished up just as if there
  6393  were no cycle.
  6394  
  6395  The idea in the following code is to observe that
  6396  $$\eqalign{\theta_n&=v_n+w_n\theta_0-u_n\theta_1=\cdots\cr
  6397  &=v_n+w_n\theta_0-u_n\bigl(v_1+w_1\theta_0-u_1(v_2+\cdots
  6398    -u_{n-2}(v_{n-1}+w_{n-1}\theta_0-u_{n-1}\theta_0)\ldots{})\bigr),\cr}$$
  6399  so we can solve for $\theta_n=\theta_0$.
  6400  
  6401  @<Adjust $\theta_n$ to equal $\theta_0$ and |goto found|@>=
  6402  begin aa:=0; bb:=fraction_one; {we have |k=n|}
  6403  repeat decr(k);
  6404  if k=0 then k:=n;
  6405  aa:=vv[k]-take_fraction(aa,uu[k]);
  6406  bb:=ww[k]-take_fraction(bb,uu[k]);
  6407  until k=n; {now $\theta_n=\\{aa}+\\{bb}\cdot\theta_n$}
  6408  aa:=make_fraction(aa,fraction_one-bb);
  6409  theta[n]:=aa; vv[0]:=aa;
  6410  for k:=1 to n-1 do vv[k]:=vv[k]+take_fraction(aa,ww[k]);
  6411  goto found;
  6412  end
  6413  
  6414  @ @d reduce_angle(#)==if abs(#)>one_eighty_deg then
  6415    if #>0 then #:=#-three_sixty_deg@+else #:=#+three_sixty_deg
  6416  
  6417  @<Calculate the given value of $\theta_n$...@>=
  6418  begin theta[n]:=left_given(s)-n_arg(delta_x[n-1],delta_y[n-1]);
  6419  reduce_angle(theta[n]);
  6420  goto found;
  6421  end
  6422  
  6423  @ @<Set up the equation for a given value of $\theta_0$@>=
  6424  begin vv[0]:=right_given(s)-n_arg(delta_x[0],delta_y[0]);
  6425  reduce_angle(vv[0]);
  6426  uu[0]:=0; ww[0]:=0;
  6427  end
  6428  
  6429  @ @<Set up the equation for a curl at $\theta_0$@>=
  6430  begin cc:=right_curl(s); lt:=abs(left_tension(t)); rt:=abs(right_tension(s));
  6431  if (rt=unity)and(lt=unity) then
  6432    uu[0]:=make_fraction(cc+cc+unity,cc+two)
  6433  else uu[0]:=curl_ratio(cc,rt,lt);
  6434  vv[0]:=-take_fraction(psi[1],uu[0]); ww[0]:=0;
  6435  end
  6436  
  6437  @ @<Set up equation for a curl at $\theta_n$...@>=
  6438  begin cc:=left_curl(s); lt:=abs(left_tension(s)); rt:=abs(right_tension(r));
  6439  if (rt=unity)and(lt=unity) then
  6440    ff:=make_fraction(cc+cc+unity,cc+two)
  6441  else ff:=curl_ratio(cc,lt,rt);
  6442  theta[n]:=-make_fraction(take_fraction(vv[n-1],ff),
  6443      fraction_one-take_fraction(ff,uu[n-1]));
  6444  goto found;
  6445  end
  6446  
  6447  @ The |curl_ratio| subroutine has three arguments, which our previous notation
  6448  encourages us to call $\gamma$, $\alpha^{-1}$, and $\beta^{-1}$. It is
  6449  a somewhat tedious program to calculate
  6450  $${(3-\alpha)\alpha^2\gamma+\beta^3\over
  6451    \alpha^3\gamma+(3-\beta)\beta^2},$$
  6452  with the result reduced to 4 if it exceeds 4. (This reduction of curl
  6453  is necessary only if the curl and tension are both large.)
  6454  The values of $\alpha$ and $\beta$ will be at most~4/3.
  6455  
  6456  @<Declare subroutines needed by |solve_choices|@>=
  6457  function curl_ratio(@!gamma,@!a_tension,@!b_tension:scaled):fraction;
  6458  var @!alpha,@!beta,@!num,@!denom,@!ff:fraction; {registers}
  6459  begin alpha:=make_fraction(unity,a_tension);
  6460  beta:=make_fraction(unity,b_tension);@/
  6461  if alpha<=beta then
  6462    begin ff:=make_fraction(alpha,beta); ff:=take_fraction(ff,ff);
  6463    gamma:=take_fraction(gamma,ff);@/
  6464    beta:=beta div @'10000; {convert |fraction| to |scaled|}
  6465    denom:=take_fraction(gamma,alpha)+three-beta;
  6466    num:=take_fraction(gamma,fraction_three-alpha)+beta;
  6467    end
  6468  else  begin ff:=make_fraction(beta,alpha); ff:=take_fraction(ff,ff);
  6469    beta:=take_fraction(beta,ff) div @'10000; {convert |fraction| to |scaled|}
  6470    denom:=take_fraction(gamma,alpha)+(ff div 1365)-beta;
  6471      {$1365\approx 2^{12}/3$}
  6472    num:=take_fraction(gamma,fraction_three-alpha)+beta;
  6473    end;
  6474  if num>=denom+denom+denom+denom then curl_ratio:=fraction_four
  6475  else curl_ratio:=make_fraction(num,denom);
  6476  end;
  6477  
  6478  @ We're in the home stretch now.
  6479  
  6480  @<Finish choosing angles and assigning control points@>=
  6481  for k:=n-1 downto 0 do theta[k]:=vv[k]-take_fraction(theta[k+1],uu[k]);
  6482  s:=p; k:=0;
  6483  repeat t:=link(s);@/
  6484  n_sin_cos(theta[k]); st:=n_sin; ct:=n_cos;@/
  6485  n_sin_cos(-psi[k+1]-theta[k+1]); sf:=n_sin; cf:=n_cos;@/
  6486  set_controls(s,t,k);@/
  6487  incr(k); s:=t;
  6488  until k=n
  6489  
  6490  @ The |set_controls| routine actually puts the control points into
  6491  a pair of consecutive nodes |p| and~|q|. Global variables are used to
  6492  record the values of $\sin\theta$, $\cos\theta$, $\sin\phi$, and
  6493  $\cos\phi$ needed in this calculation.
  6494  
  6495  @<Glob...@>=
  6496  @!st,@!ct,@!sf,@!cf:fraction; {sines and cosines}
  6497  
  6498  @ @<Declare subroutines needed by |solve_choices|@>=
  6499  procedure set_controls(@!p,@!q:pointer;@!k:integer);
  6500  var @!rr,@!ss:fraction; {velocities, divided by thrice the tension}
  6501  @!lt,@!rt:scaled; {tensions}
  6502  @!sine:fraction; {$\sin(\theta+\phi)$}
  6503  begin lt:=abs(left_tension(q)); rt:=abs(right_tension(p));
  6504  rr:=velocity(st,ct,sf,cf,rt);
  6505  ss:=velocity(sf,cf,st,ct,lt);
  6506  if (right_tension(p)<0)or(left_tension(q)<0) then @<Decrease the velocities,
  6507    if necessary, to stay inside the bounding triangle@>;
  6508  right_x(p):=x_coord(p)+take_fraction(
  6509    take_fraction(delta_x[k],ct)-take_fraction(delta_y[k],st),rr);
  6510  right_y(p):=y_coord(p)+take_fraction(
  6511    take_fraction(delta_y[k],ct)+take_fraction(delta_x[k],st),rr);
  6512  left_x(q):=x_coord(q)-take_fraction(
  6513    take_fraction(delta_x[k],cf)+take_fraction(delta_y[k],sf),ss);
  6514  left_y(q):=y_coord(q)-take_fraction(
  6515    take_fraction(delta_y[k],cf)-take_fraction(delta_x[k],sf),ss);
  6516  right_type(p):=explicit; left_type(q):=explicit;
  6517  end;
  6518  
  6519  @ The boundedness conditions $\\{rr}\L\sin\phi\,/\sin(\theta+\phi)$ and
  6520  $\\{ss}\L\sin\theta\,/\sin(\theta+\phi)$ are to be enforced if $\sin\theta$,
  6521  $\sin\phi$, and $\sin(\theta+\phi)$ all have the same sign. Otherwise
  6522  there is no ``bounding triangle.''
  6523  
  6524  @<Decrease the velocities, if necessary...@>=
  6525  if((st>=0)and(sf>=0))or((st<=0)and(sf<=0)) then
  6526    begin sine:=take_fraction(abs(st),cf)+take_fraction(abs(sf),ct);
  6527    if sine>0 then
  6528      begin sine:=take_fraction(sine,fraction_one+unity); {safety factor}
  6529      if right_tension(p)<0 then
  6530       if ab_vs_cd(abs(sf),fraction_one,rr,sine)<0 then
  6531        rr:=make_fraction(abs(sf),sine);
  6532      if left_tension(q)<0 then
  6533       if ab_vs_cd(abs(st),fraction_one,ss,sine)<0 then
  6534        ss:=make_fraction(abs(st),sine);
  6535      end;
  6536    end
  6537  
  6538  @ Only the simple cases remain to be handled.
  6539  
  6540  @<Reduce to simple case of two givens and |return|@>=
  6541  begin aa:=n_arg(delta_x[0],delta_y[0]);@/
  6542  n_sin_cos(right_given(p)-aa); ct:=n_cos; st:=n_sin;@/
  6543  n_sin_cos(left_given(q)-aa); cf:=n_cos; sf:=-n_sin;@/
  6544  set_controls(p,q,0); return;
  6545  end
  6546  
  6547  @ @<Reduce to simple case of straight line and |return|@>=
  6548  begin right_type(p):=explicit; left_type(q):=explicit;
  6549  lt:=abs(left_tension(q)); rt:=abs(right_tension(p));
  6550  if rt=unity then
  6551    begin if delta_x[0]>=0 then right_x(p):=x_coord(p)+((delta_x[0]+1) div 3)
  6552    else right_x(p):=x_coord(p)+((delta_x[0]-1) div 3);
  6553    if delta_y[0]>=0 then right_y(p):=y_coord(p)+((delta_y[0]+1) div 3)
  6554    else right_y(p):=y_coord(p)+((delta_y[0]-1) div 3);
  6555    end
  6556  else  begin ff:=make_fraction(unity,3*rt); {$\alpha/3$}
  6557    right_x(p):=x_coord(p)+take_fraction(delta_x[0],ff);
  6558    right_y(p):=y_coord(p)+take_fraction(delta_y[0],ff);
  6559    end;
  6560  if lt=unity then
  6561    begin if delta_x[0]>=0 then left_x(q):=x_coord(q)-((delta_x[0]+1) div 3)
  6562    else left_x(q):=x_coord(q)-((delta_x[0]-1) div 3);
  6563    if delta_y[0]>=0 then left_y(q):=y_coord(q)-((delta_y[0]+1) div 3)
  6564    else left_y(q):=y_coord(q)-((delta_y[0]-1) div 3);
  6565    end
  6566  else  begin ff:=make_fraction(unity,3*lt); {$\beta/3$}
  6567    left_x(q):=x_coord(q)-take_fraction(delta_x[0],ff);
  6568    left_y(q):=y_coord(q)-take_fraction(delta_y[0],ff);
  6569    end;
  6570  return;
  6571  end
  6572  
  6573  @* \[19] Generating discrete moves.
  6574  The purpose of the next part of \MF\ is to compute discrete approximations
  6575  to curves described as parametric polynomial functions $z(t)$.
  6576  We shall start with the low level first, because an efficient ``engine''
  6577  is needed to support the high-level constructions.
  6578  
  6579  Most of the subroutines are based on variations of a single theme,
  6580  namely the idea of {\sl bisection}. Given a Bernshte{\u\i}n polynomial
  6581  @^Bernshte{\u\i}n, Serge{\u\i} Natanovich@>
  6582  $$B(z_0,z_1,\ldots,z_n;t)=\sum_k{n\choose k}t^k(1-t)^{n-k}z_k,$$
  6583  we can conveniently bisect its range as follows:
  6584  
  6585  \smallskip
  6586  \textindent{1)} Let $z_k^{(0)}=z_k$, for |0<=k<=n|.
  6587  
  6588  \smallskip
  6589  \textindent{2)} Let $z_k^{(j+1)}={1\over2}(z_k^{(j)}+z\k^{(j)})$, for
  6590  |0<=k<n-j|, for |0<=j<n|.
  6591  
  6592  \smallskip\noindent
  6593  Then
  6594  $$B(z_0,z_1,\ldots,z_n;t)=B(z_0^{(0)},z_0^{(1)},\ldots,z_0^{(n)};2t)
  6595   =B(z_0^{(n)},z_1^{(n-1)},\ldots,z_n^{(0)};2t-1).$$
  6596  This formula gives us the coefficients of polynomials to use over the ranges
  6597  $0\L t\L{1\over2}$ and ${1\over2}\L t\L1$.
  6598  
  6599  In our applications it will usually be possible to work indirectly with
  6600  numbers that allow us to deduce relevant properties of the polynomials
  6601  without actually computing the polynomial values. We will deal with
  6602  coefficients $Z_k=2^l(z_k-z_{k-1})$ for |1<=k<=n|, instead of
  6603  the actual numbers $z_0$, $z_1$, \dots,~$z_n$, and the value of~|l| will
  6604  increase by~1 at each bisection step. This technique reduces the
  6605  amount of calculation needed for bisection and also increases the
  6606  accuracy of evaluation (since one bit of precision is gained at each
  6607  bisection). Indeed, the bisection process now becomes one level shorter:
  6608  
  6609  \smallskip
  6610  \textindent{$1'$)} Let $Z_k^{(1)}=Z_k$, for |1<=k<=n|.
  6611  
  6612  \smallskip
  6613  \textindent{$2'$)} Let $Z_k^{(j+1)}={1\over2}(Z_k^{(j)}+Z\k^{(j)})$, for
  6614  |1<=k<=n-j|, for |1<=j<n|.
  6615  
  6616  \smallskip\noindent
  6617  The relevant coefficients $(Z'_1,\ldots,Z'_n)$ and $(Z''_1,\ldots,Z''_n)$
  6618  for the two subintervals after bisection are respectively
  6619  $(Z_1^{(1)},Z_1^{(2)},\ldots,Z_1^{(n)})$ and
  6620  $(Z_1^{(n)},Z_2^{(n-1)},\ldots,Z_n^{(1)})$.
  6621  And the values of $z_0$ appropriate for the bisected interval are $z'_0=z_0$
  6622  and $z''_0=z_0+(Z'_1+Z'_2+\cdots+Z'_n)/2^{l+1}$.
  6623  
  6624  Step $2'$ involves division by~2, which introduces computational errors
  6625  of at most $1\over2$ at each step; thus after $l$~levels of bisection the
  6626  integers $Z_k$ will differ from their true values by at most $(n-1)l/2$.
  6627  This error rate is quite acceptable, considering that we have $l$~more
  6628  bits of precision in the $Z$'s by comparison with the~$z$'s.  Note also
  6629  that the $Z$'s remain bounded; there's no danger of integer overflow, even
  6630  though we have the identity $Z_k=2^l(z_k-z_{k-1})$ for arbitrarily large~$l$.
  6631  
  6632  In fact, we can show not only that the $Z$'s remain bounded, but also that
  6633  they become nearly equal, since they are control points for a polynomial
  6634  of one less degree. If $\vert Z\k-Z_k\vert\L M$ initially, it is possible
  6635  to prove that $\vert Z\k-Z_k\vert\L\lceil M/2^l\rceil$ after $l$~levels
  6636  of bisection, even in the presence of rounding errors. Here's the
  6637  proof [cf.~Lane and Riesenfeld, {\sl IEEE Trans.\ on Pattern Analysis
  6638  @^Lane, Jeffrey Michael@>
  6639  @^Riesenfeld, Richard Franklin@>
  6640  and Machine Intelligence\/ \bf PAMI-2} (1980), 35--46]: Assuming that
  6641  $\vert Z\k-Z_k\vert\L M$ before bisection, we want to prove that
  6642  $\vert Z\k-Z_k\vert\L\lceil M/2\rceil$ afterward. First we show that
  6643  $\vert Z\k^{(j)}-Z_k^{(j)}\vert\L M$ for all $j$ and~$k$, by induction
  6644  on~$j$; this follows from the fact that
  6645  $$\bigl\vert\\{half}(a+b)-\\{half}(b+c)\bigr\vert\L
  6646   \max\bigl(\vert a-b\vert,\vert b-c\vert\bigr)$$
  6647  holds for both of the rounding rules $\\{half}(x)=\lfloor x/2\rfloor$
  6648  and $\\{half}(x)={\rm sign}(x)\lfloor\vert x/2\vert\rfloor$.
  6649  (If $\vert a-b\vert$ and $\vert b-c\vert$ are equal, then
  6650  $a+b$ and $b+c$ are both even or both odd. The rounding errors either
  6651  cancel or round the numbers toward each other; hence
  6652  $$\eqalign{\bigl\vert\\{half}(a+b)-\\{half}(b+c)\bigr\vert
  6653  &\L\textstyle\bigl\vert{1\over2}(a+b)-{1\over2}(b+c)\bigr\vert\cr
  6654  &=\textstyle\bigl\vert{1\over2}(a-b)+{1\over2}(b-c)\bigr\vert
  6655  \L\max\bigl(\vert a-b\vert,\vert b-c\vert\bigr),\cr}$$
  6656  as required. A simpler argument applies if $\vert a-b\vert$ and
  6657  $\vert b-c\vert$ are unequal.)  Now it is easy to see that
  6658  $\vert Z_1^{(j+1)}-Z_1^{(j)}\vert\L\bigl\lfloor{1\over2}
  6659  \vert Z_2^{(j)}-Z_1^{(j)}\vert+{1\over2}\bigr\rfloor
  6660  \L\bigl\lfloor{1\over2}(M+1)\bigr\rfloor=\lceil M/2\rceil$.
  6661  
  6662  Another interesting fact about bisection is the identity
  6663  $$Z_1'+\cdots+Z_n'+Z_1''+\cdots+Z_n''=2(Z_1+\cdots+Z_n+E),$$
  6664  where $E$ is the sum of the rounding errors in all of the halving
  6665  operations ($\vert E\vert\L n(n-1)/4$).
  6666  
  6667  @ We will later reduce the problem of digitizing a complex cubic
  6668  $z(t)=B(z_0,z_1,z_2,z_3;t)$ to the following simpler problem:
  6669  Given two real cubics
  6670  $x(t)=B(x_0,x_1,x_2,x_3;t)$
  6671  and $y(t)=B(y_0,y_1,y_2,y_3;t)$ that are monotone nondecreasing,
  6672  determine the set of integer points
  6673  $$P=\bigl\{\bigl(\lfloor x(t)\rfloor,\lfloor y(t)\rfloor\bigr)
  6674  \bigm\vert 0\L t\L 1\bigr\}.$$
  6675  Well, the problem isn't actually quite so clean as this; when the path
  6676  goes very near an integer point $(a,b)$, computational errors may
  6677  make us think that $P$ contains $(a-1,b)$ while in reality it should
  6678  contain $(a,b-1)$. Furthermore, if the path goes {\sl exactly\/}
  6679  through the integer points $(a-1,b-1)$ and
  6680  $(a,b)$, we will want $P$ to contain one
  6681  of the two points $(a-1,b)$ or $(a,b-1)$, so that $P$ can be described
  6682  entirely by ``rook moves'' upwards or to the right; no diagonal
  6683  moves from $(a-1,b-1)$ to~$(a,b)$ will be allowed.
  6684  
  6685  Thus, the set $P$ we wish to compute will merely be an approximation
  6686  to the set described in the formula above. It will consist of
  6687  $\lfloor x(1)\rfloor-\lfloor x(0)\rfloor$ rightward moves and
  6688  $\lfloor y(1)\rfloor-\lfloor y(0)\rfloor$ upward moves, intermixed
  6689  in some order. Our job will be to figure out a suitable order.
  6690  
  6691  The following recursive strategy suggests itself, when we recall that
  6692  $x(0)=x_0$, $x(1)=x_3$, $y(0)=y_0$, and $y(1)=y_3$:
  6693  
  6694  \smallskip
  6695  If $\lfloor x_0\rfloor=\lfloor x_3\rfloor$ then take
  6696  $\lfloor y_3\rfloor-\lfloor y_0\rfloor$ steps up.
  6697  
  6698  Otherwise if $\lfloor y_0\rfloor=\lfloor y_3\rfloor$ then take
  6699  $\lfloor x_3\rfloor-\lfloor x_0\rfloor$ steps to the right.
  6700  
  6701  Otherwise bisect the current cubics and repeat the process on both halves.
  6702  
  6703  \yskip\noindent
  6704  This intuitively appealing formulation does not quite solve the problem,
  6705  because it may never terminate. For example, it's not hard to see that
  6706  no steps will {\sl ever\/} be taken if $(x_0,x_1,x_2,x_3)=(y_0,y_1,y_2,y_3)$!
  6707  However, we can surmount this difficulty with a bit of care; so let's
  6708  proceed to flesh out the algorithm as stated, before worrying about
  6709  such details.
  6710  
  6711  The bisect-and-double strategy discussed above suggests that we represent
  6712  $(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})$
  6713  for some~$l$. Initially $l=16$, since the $x$'s are |scaled|.
  6714  In order to deal with other aspects of the algorithm we will want to
  6715  maintain also the quantities $m=\lfloor x_3\rfloor-\lfloor x_0\rfloor$
  6716  and $R=2^l(x_0\bmod 1)$. Similarly,
  6717  $(y_0,y_1,y_2,y_3)$ will be represented by $(Y_1,Y_2,Y_3)$,
  6718  $n=\lfloor y_3\rfloor-\lfloor y_0\rfloor$,
  6719  and $S=2^l(y_0\bmod 1)$. The algorithm now takes the following form:
  6720  
  6721  \smallskip
  6722  If $m=0$ then take $n$ steps up.
  6723  
  6724  Otherwise if $n=0$ then take $m$ steps to the right.
  6725  
  6726  Otherwise bisect the current cubics and repeat the process on both halves.
  6727  
  6728  \smallskip\noindent
  6729  The bisection process for $(X_1,X_2,X_3,m,R,l)$ reduces, in essence,
  6730  to the following formulas:
  6731  $$\vbox{\halign{$#\hfil$\cr
  6732  X_2'=\\{half}(X_1+X_2),\quad
  6733  X_2''=\\{half}(X_2+X_3),\quad
  6734  X_3'=\\{half}(X_2'+X_2''),\cr
  6735  X_1'=X_1,\quad
  6736  X_1''=X_3',\quad
  6737  X_3''=X_3,\cr
  6738  R'=2R,\quad
  6739  T=X_1'+X_2'+X_3'+R',\quad
  6740  R''=T\bmod 2^{l+1},\cr
  6741  m'=\lfloor T/2^{l+1}\rfloor,\quad
  6742  m''=m-m'.\cr}}$$
  6743  
  6744  @ When $m=n=1$, the computation can be speeded up because we simply
  6745  need to decide between two alternatives, (up,\thinspace right)
  6746  versus (right,\thinspace up). There appears to be no simple, direct
  6747  way to make the correct decision by looking at the values of
  6748  $(X_1,X_2,X_3,R)$ and
  6749  $(Y_1,Y_2,Y_3,S)$; but we can streamline the bisection process, and
  6750  we can use the fact that only one of the two descendants needs to
  6751  be examined after each bisection. Furthermore, we observed earlier
  6752  that after several levels of bisection the $X$'s and $Y$'s will be nearly
  6753  equal; so we will be justified in assuming that the curve is essentially a
  6754  straight line. (This, incidentally, solves the problem of infinite
  6755  recursion mentioned earlier.)
  6756  
  6757  It is possible to show that
  6758  $$m=\bigl\lfloor(X_1+X_2+X_3+R+E)\,/\,2^l\bigr\rfloor,$$
  6759  where $E$ is an accumulated rounding error that is at most
  6760  $3\cdot(2^{l-16}-1)$ in absolute value. We will make sure that
  6761  the $X$'s are less than $2^{28}$; hence when $l=30$ we must
  6762  have |m<=1|. This proves that the special case $m=n=1$ is
  6763  bound to be reached by the time $l=30$. Furthermore $l=30$ is
  6764  a suitable time to make the straight line approximation,
  6765  if the recursion hasn't already died out, because the maximum
  6766  difference between $X$'s will then be $<2^{14}$; this corresponds
  6767  to an error of $<1$ with respect to the original scaling.
  6768  (Stating this another way, each bisection makes the curve two bits
  6769  closer to a straight line, hence 14 bisections are sufficient for
  6770  28-bit accuracy.)
  6771  
  6772  In the case of a straight line, the curve goes first right, then up,
  6773  if and only if $(T-2^l)(2^l-S)>(U-2^l)(2^l-R)$, where
  6774  $T=X_1+X_2+X_3+R$ and $U=Y_1+Y_2+Y_3+S$. For the actual curve
  6775  essentially runs from $(R/2^l,S/2^l)$ to $(T/2^l,U/2^l)$, and
  6776  we are testing whether or not $(1,1)$ is above the straight
  6777  line connecting these two points. (This formula assumes that $(1,1)$
  6778  is not exactly on the line.)
  6779  
  6780  @ We have glossed over the problem of tie-breaking in ambiguous
  6781  cases when the cubic curve passes exactly through integer points.
  6782  \MF\ finesses this problem by assuming that coordinates
  6783  $(x,y)$ actually stand for slightly perturbed values $(x+\xi,y+\eta)$,
  6784  where $\xi$ and~$\eta$ are infinitesimals whose signs will determine
  6785  what to do when $x$ and/or~$y$ are exact integers. The quantities
  6786  $\lfloor x\rfloor$ and~$\lfloor y\rfloor$ in the formulas above
  6787  should actually read $\lfloor x+\xi\rfloor$ and $\lfloor y+\eta\rfloor$.
  6788  
  6789  If $x$ is a |scaled| value, we have $\lfloor x+\xi\rfloor=\lfloor x\rfloor$
  6790  if $\xi>0$, and $\lfloor x+\xi\rfloor=\lfloor x-2^{-16}\rfloor$ if
  6791  $\xi<0$. It is convenient to represent $\xi$ by the integer |xi_corr|,
  6792  defined to be 0~if $\xi>0$ and 1~if $\xi<0$; then, for example, the
  6793  integer $\lfloor x+\xi\rfloor$ can be computed as
  6794  |floor_unscaled(x-xi_corr)|. Similarly, $\eta$ is conveniently
  6795  represented by~|eta_corr|.
  6796  
  6797  In our applications the sign of $\xi-\eta$ will always be the same as
  6798  the sign of $\xi$. Therefore it turns out that the rule for straight
  6799  lines, as stated above, should be modified as follows in the case of
  6800  ties: The line goes first right, then up, if and only if
  6801  $(T-2^l)(2^l-S)+\xi>(U-2^l)(2^l-R)$. And this relation holds iff
  6802  $|ab_vs_cd|(T-2^l,2^l-S,U-2^l,2^l-R)-|xi_corr|\ge0$.
  6803  
  6804  These conventions for rounding are symmetrical, in the sense that the
  6805  digitized moves obtained from $(x_0,x_1,x_2,x_3,y_0,y_1,y_2,y_3,\xi,\eta)$
  6806  will be exactly complementary to the moves that would be obtained from
  6807  $(-x_3,-x_2,-x_1,-x_0,-y_3,-y_2,-y_1,-y_0,-\xi,-\eta)$, if arithmetic
  6808  is exact. However, truncation errors in the bisection process might
  6809  upset the symmetry. We can restore much of the lost symmetry by adding
  6810  |xi_corr| or |eta_corr| when halving the data.
  6811  
  6812  @ One further possibility needs to be mentioned: The algorithm
  6813  will be applied only to cubic polynomials $B(x_0,x_1,x_2,x_3;t)$ that
  6814  are nondecreasing as $t$~varies from 0 to~1; this condition turns
  6815  out to hold if and only if $x_0\L x_1$ and $x_2\L x_3$, and either
  6816  $x_1\L x_2$ or $(x_1-x_2)^2\L(x_1-x_0)(x_3-x_2)$. If bisection were
  6817  carried out with perfect accuracy, these relations would remain
  6818  invariant. But rounding errors can creep in, hence the bisection
  6819  algorithm can produce non-monotonic subproblems from monotonic
  6820  initial conditions. This leads to the potential danger that $m$ or~$n$
  6821  could become negative in the algorithm described above.
  6822  
  6823  For example, if we start with $(x_1-x_0,x_2-x_1,x_3-x_2)=
  6824  (X_1,X_2,X_3)=(7,-16,39)$, the corresponding polynomial is
  6825  monotonic, because $16^2<7\cdot39$. But the bisection algorithm
  6826  produces the left descendant $(7,-5,3)$, which is nonmonotonic;
  6827  its right descendant is~$(0,-1,3)$.
  6828  
  6829  \def\xt{{\tilde x}}
  6830  Fortunately we can prove that such rounding errors will never cause
  6831  the algorithm to make a tragic mistake. At every stage we are working
  6832  with numbers corresponding to a cubic polynomial $B(\xt_0,
  6833  \xt_1,\xt_2,\xt_3)$ that approximates some
  6834  monotonic polynomial $B(x_0,x_1,x_2,x_3)$. The accumulated errors are
  6835  controlled so that $\vert x_k-\xt_k\vert<\epsilon=3\cdot2^{-16}$.
  6836  If bisection is done at some stage of the recursion, we have
  6837  $m=\lfloor\xt_3\rfloor-\lfloor\xt_0\rfloor>0$, and the algorithm
  6838  computes a bisection value $\bar x$ such that $m'=\lfloor\bar x\rfloor-
  6839  \lfloor\xt_0\rfloor$
  6840  and $m''=\lfloor\xt_3\rfloor-\lfloor\bar x\rfloor$. We want to prove
  6841  that neither $m'$ nor $m''$ can be negative. Since $\bar x$ is an
  6842  approximation to a value in the interval $[x_0,x_3]$, we have
  6843  $\bar x>x_0-\epsilon$ and $\bar x<x_3+\epsilon$, hence $\bar x>
  6844  \xt_0-2\epsilon$ and $\bar x<\xt_3+2\epsilon$.
  6845  If $m'$ is negative we must have $\xt_0\bmod 1<2\epsilon$;
  6846  if $m''$ is negative we must have $\xt_3\bmod 1>1-2\epsilon$.
  6847  In either case the condition $\lfloor\xt_3\rfloor-\lfloor\xt_0\rfloor>0$
  6848  implies that $\xt_3-\xt_0>1-2\epsilon$, hence $x_3-x_0>1-4\epsilon$.
  6849  But it can be shown that if $B(x_0,x_1,x_2,x_3;t)$ is a monotonic
  6850  cubic, then $B(x_0,x_1,x_2,x_3;{1\over2})$ is always between
  6851  $.06[x_0,x_3]$ and $.94[x_0,x_3]$; and it is impossible for $\bar x$
  6852  to be within~$\epsilon$ of such a number. Contradiction!
  6853  (The constant .06 is actually $(2-\sqrt3\,)/4$; the worst case
  6854  occurs for polynomials like $B(0,2-\sqrt3,1-\sqrt3,3;t)$.)
  6855  
  6856  @ OK, now that a long theoretical preamble has justified the
  6857  bisection-and-doubling algorithm, we are ready to proceed with
  6858  its actual coding. But we still haven't discussed the
  6859  form of the output.
  6860  
  6861  For reasons to be discussed later, we shall find it convenient to
  6862  record the output as follows: Moving one step up is represented by
  6863  appending a `1' to a list; moving one step right is represented by
  6864  adding unity to the element at the end of the list. Thus, for example,
  6865  the net effect of ``(up, right, right, up, right)'' is to append
  6866  $(3,2)$.
  6867  
  6868  The list is kept in a global array called |move|. Before starting the
  6869  algorithm, \MF\ should check that $\\{move\_ptr}+\lfloor y_3\rfloor
  6870  -\lfloor y_0\rfloor\L\\{move\_size}$, so that the list won't exceed
  6871  the bounds of this array.
  6872  
  6873  @<Glob...@>=
  6874  @!move:array[0..move_size] of integer; {the recorded moves}
  6875  @!move_ptr:0..move_size; {the number of items in the |move| list}
  6876  
  6877  @ When bisection occurs, we ``push'' the subproblem corresponding
  6878  to the right-hand subinterval onto the |bisect_stack| while
  6879  we continue to work on the left-hand subinterval. Thus, the |bisect_stack|
  6880  will hold $(X_1,X_2,X_3,R,m,Y_1,Y_2,Y_3,S,n,l)$ values for
  6881  subproblems yet to be tackled.
  6882  
  6883  At most 15 subproblems will be on the stack at once (namely, for
  6884  $l=15$,~16, \dots,~29); but the stack is bigger than this, because
  6885  it is used also for more complicated bisection algorithms.
  6886  
  6887  @d stack_x1==bisect_stack[bisect_ptr] {stacked value of $X_1$}
  6888  @d stack_x2==bisect_stack[bisect_ptr+1] {stacked value of $X_2$}
  6889  @d stack_x3==bisect_stack[bisect_ptr+2] {stacked value of $X_3$}
  6890  @d stack_r==bisect_stack[bisect_ptr+3] {stacked value of $R$}
  6891  @d stack_m==bisect_stack[bisect_ptr+4] {stacked value of $m$}
  6892  @d stack_y1==bisect_stack[bisect_ptr+5] {stacked value of $Y_1$}
  6893  @d stack_y2==bisect_stack[bisect_ptr+6] {stacked value of $Y_2$}
  6894  @d stack_y3==bisect_stack[bisect_ptr+7] {stacked value of $Y_3$}
  6895  @d stack_s==bisect_stack[bisect_ptr+8] {stacked value of $S$}
  6896  @d stack_n==bisect_stack[bisect_ptr+9] {stacked value of $n$}
  6897  @d stack_l==bisect_stack[bisect_ptr+10] {stacked value of $l$}
  6898  @d move_increment=11 {number of items pushed by |make_moves|}
  6899  
  6900  @<Glob...@>=
  6901  @!bisect_stack:array[0..bistack_size] of integer;
  6902  @!bisect_ptr:0..bistack_size;
  6903  
  6904  @ @<Check the ``constant'' values...@>=
  6905  if 15*move_increment>bistack_size then bad:=31;
  6906  
  6907  @ The |make_moves| subroutine is given |scaled| values $(x_0,x_1,x_2,x_3)$
  6908  and $(y_0,y_1,y_2,y_3)$ that represent monotone-nondecreasing polynomials;
  6909  it makes $\lfloor x_3+\xi\rfloor-\lfloor x_0+\xi\rfloor$ rightward moves
  6910  and $\lfloor y_3+\eta\rfloor-\lfloor y_0+\eta\rfloor$ upward moves, as
  6911  explained earlier.  (Here $\lfloor x+\xi\rfloor$ actually stands for
  6912  $\lfloor x/2^{16}-|xi_corr|\rfloor$, if $x$ is regarded as an integer
  6913  without scaling.) The unscaled integers $x_k$ and~$y_k$ should be less
  6914  than $2^{28}$ in magnitude.
  6915  
  6916  It is assumed that $|move_ptr| + \lfloor y_3+\eta\rfloor -
  6917  \lfloor y_0+\eta\rfloor < |move_size|$ when this procedure is called,
  6918  so that the capacity of the |move| array will not be exceeded.
  6919  
  6920  The variables |r| and |s| in this procedure stand respectively for
  6921  $R-|xi_corr|$ and $S-|eta_corr|$ in the theory discussed above.
  6922  
  6923  @p procedure make_moves(@!xx0,@!xx1,@!xx2,@!xx3,@!yy0,@!yy1,@!yy2,@!yy3:
  6924    scaled;@!xi_corr,@!eta_corr:small_number);
  6925  label continue, done, exit;
  6926  var @!x1,@!x2,@!x3,@!m,@!r,@!y1,@!y2,@!y3,@!n,@!s,@!l:integer;
  6927    {bisection variables explained above}
  6928  @!q,@!t,@!u,@!x2a,@!x3a,@!y2a,@!y3a:integer; {additional temporary registers}
  6929  begin if (xx3<xx0)or(yy3<yy0) then confusion("m");
  6930  @:this can't happen m}{\quad m@>
  6931  l:=16; bisect_ptr:=0;@/
  6932  x1:=xx1-xx0; x2:=xx2-xx1; x3:=xx3-xx2;
  6933  if xx0>=xi_corr then r:=(xx0-xi_corr) mod unity
  6934  else r:=unity-1-((-xx0+xi_corr-1) mod unity);
  6935  m:=(xx3-xx0+r) div unity;@/
  6936  y1:=yy1-yy0; y2:=yy2-yy1; y3:=yy3-yy2;
  6937  if yy0>=eta_corr then s:=(yy0-eta_corr) mod unity
  6938  else s:=unity-1-((-yy0+eta_corr-1) mod unity);
  6939  n:=(yy3-yy0+s) div unity;@/
  6940  if (xx3-xx0>=fraction_one)or(yy3-yy0>=fraction_one) then
  6941    @<Divide the variables by two, to avoid overflow problems@>;
  6942  loop@+  begin continue:@<Make moves for current subinterval;
  6943      if bisection is necessary, push the second subinterval
  6944      onto the stack, and |goto continue| in order to handle
  6945      the first subinterval@>;
  6946    if bisect_ptr=0 then return;
  6947    @<Remove a subproblem for |make_moves| from the stack@>;
  6948    end;
  6949  exit: end;
  6950  
  6951  @ @<Remove a subproblem for |make_moves| from the stack@>=
  6952  bisect_ptr:=bisect_ptr-move_increment;@/
  6953  x1:=stack_x1; x2:=stack_x2; x3:=stack_x3; r:=stack_r; m:=stack_m;@/
  6954  y1:=stack_y1; y2:=stack_y2; y3:=stack_y3; s:=stack_s; n:=stack_n;@/
  6955  l:=stack_l
  6956  
  6957  @ Our variables |(x1,x2,x3)| correspond to $(X_1,X_2,X_3)$ in the notation
  6958  of the theory developed above. We need to keep them less than $2^{28}$
  6959  in order to avoid integer overflow in weird circumstances.
  6960  For example, data like $x_0=-2^{28}+2^{16}-1$ and $x_1=x_2=x_3=2^{28}-1$
  6961  would otherwise be problematical. Hence this part of the code is
  6962  needed, if only to thwart malicious users.
  6963  
  6964  @<Divide the variables by two, to avoid overflow problems@>=
  6965  begin x1:=half(x1+xi_corr); x2:=half(x2+xi_corr); x3:=half(x3+xi_corr);
  6966  r:=half(r+xi_corr);@/
  6967  y1:=half(y1+eta_corr); y2:=half(y2+eta_corr); y3:=half(y3+eta_corr);
  6968  s:=half(s+eta_corr);@/
  6969  l:=15;
  6970  end
  6971  
  6972  @ @<Make moves...@>=
  6973  if m=0 then @<Move upward |n| steps@>
  6974  else if n=0 then @<Move to the right |m| steps@>
  6975  else if m+n=2 then @<Make one move of each kind@>
  6976  else  begin incr(l); stack_l:=l;@/
  6977    stack_x3:=x3; stack_x2:=half(x2+x3+xi_corr); x2:=half(x1+x2+xi_corr);
  6978    x3:=half(x2+stack_x2+xi_corr); stack_x1:=x3;@/
  6979    r:=r+r+xi_corr; t:=x1+x2+x3+r;@/
  6980    q:=t div two_to_the[l]; stack_r:=t mod two_to_the[l];@/
  6981    stack_m:=m-q; m:=q;@/
  6982    stack_y3:=y3; stack_y2:=half(y2+y3+eta_corr); y2:=half(y1+y2+eta_corr);
  6983    y3:=half(y2+stack_y2+eta_corr); stack_y1:=y3;@/
  6984    s:=s+s+eta_corr; u:=y1+y2+y3+s;@/
  6985    q:=u div two_to_the[l]; stack_s:=u mod two_to_the[l];@/
  6986    stack_n:=n-q; n:=q;@/
  6987    bisect_ptr:=bisect_ptr+move_increment; goto continue;
  6988    end
  6989  
  6990  @ @<Move upward |n| steps@>=
  6991  while n>0 do
  6992    begin incr(move_ptr); move[move_ptr]:=1; decr(n);
  6993    end
  6994  
  6995  @ @<Move to the right |m| steps@>=
  6996  move[move_ptr]:=move[move_ptr]+m
  6997  
  6998  @ @<Make one move of each kind@>=
  6999  begin r:=two_to_the[l]-r; s:=two_to_the[l]-s;@/
  7000  while l<30 do
  7001    begin x3a:=x3; x2a:=half(x2+x3+xi_corr); x2:=half(x1+x2+xi_corr);
  7002    x3:=half(x2+x2a+xi_corr);
  7003    t:=x1+x2+x3; r:=r+r-xi_corr;@/
  7004    y3a:=y3; y2a:=half(y2+y3+eta_corr); y2:=half(y1+y2+eta_corr);
  7005    y3:=half(y2+y2a+eta_corr);
  7006    u:=y1+y2+y3; s:=s+s-eta_corr;@/
  7007    if t<r then if u<s then @<Switch to the right subinterval@>
  7008      else  begin @<Move up then right@>; goto done;
  7009        end
  7010    else if u<s then
  7011      begin @<Move right then up@>; goto done;
  7012      end;
  7013    incr(l);
  7014    end;
  7015  r:=r-xi_corr; s:=s-eta_corr;
  7016  if ab_vs_cd(x1+x2+x3,s,y1+y2+y3,r)-xi_corr>=0 then @<Move right then up@>
  7017    else @<Move up then right@>;
  7018  done:
  7019  end
  7020  
  7021  @ @<Switch to the right subinterval@>=
  7022  begin x1:=x3; x2:=x2a; x3:=x3a; r:=r-t;
  7023  y1:=y3; y2:=y2a; y3:=y3a; s:=s-u;
  7024  end
  7025  
  7026  @ @<Move right then up@>=
  7027  begin incr(move[move_ptr]); incr(move_ptr); move[move_ptr]:=1;
  7028  end
  7029  
  7030  @ @<Move up then right@>=
  7031  begin incr(move_ptr); move[move_ptr]:=2;
  7032  end
  7033  
  7034  @ After |make_moves| has acted, possibly for several curves that move toward
  7035  the same octant, a ``smoothing'' operation might be done on the |move| array.
  7036  This removes optical glitches that can arise even when the curve has been
  7037  digitized without rounding errors.
  7038  
  7039  The smoothing process replaces the integers $a_0\ldots a_n$ in
  7040  |move[b..t]| by ``smoothed'' integers $a_0'\ldots a_n'$ defined as
  7041  follows:
  7042  $$a_k'=a_k+\delta\k-\delta_k;\qquad
  7043  \delta_k=\cases{+1,&if $1<k<n$ and $a_{k-2}\G a_{k-1}\ll a_k\G a\k$;\cr
  7044  -1,&if $1<k<n$ and $a_{k-2}\L a_{k-1}\gg a_k\L a\k$;\cr
  7045  0,&otherwise.\cr}$$
  7046  Here $a\ll b$ means that $a\L b-2$, and $a\gg b$ means that $a\G b+2$.
  7047  
  7048  The smoothing operation is symmetric in the sense that, if $a_0\ldots a_n$
  7049  smooths to $a_0'\ldots a_n'$, then the reverse sequence $a_n\ldots a_0$
  7050  smooths to $a_n'\ldots a_0'$; also the complementary sequence
  7051  $(m-a_0)\ldots(m-a_n)$ smooths to $(m-a_0')\ldots(m-a_n')$.
  7052  We have $a_0'+\cdots+a_n'=a_0+\cdots+a_n$ because $\delta_0=\delta_{n+1}=0$.
  7053  
  7054  @p procedure smooth_moves(@!b,@!t:integer);
  7055  var@!k:1..move_size; {index into |move|}
  7056  @!a,@!aa,@!aaa:integer; {original values of |move[k],move[k-1],move[k-2]|}
  7057  begin if t-b>=3 then
  7058    begin k:=b+2; aa:=move[k-1]; aaa:=move[k-2];
  7059    repeat a:=move[k];
  7060    if abs(a-aa)>1 then
  7061      @<Increase and decrease |move[k-1]| and |move[k]| by $\delta_k$@>;
  7062    incr(k); aaa:=aa; aa:=a;
  7063    until k=t;
  7064    end;
  7065  end;
  7066  
  7067  @ @<Increase and decrease |move[k-1]| and |move[k]| by $\delta_k$@>=
  7068  if a>aa then
  7069    begin if aaa>=aa then if a>=move[k+1] then
  7070      begin incr(move[k-1]); move[k]:=a-1;
  7071      end;
  7072    end
  7073  else  begin if aaa<=aa then if a<=move[k+1] then
  7074      begin decr(move[k-1]); move[k]:=a+1;
  7075      end;
  7076    end
  7077  
  7078  @* \[20] Edge structures.
  7079  Now we come to \MF's internal scheme for representing what the user can
  7080  actually ``see,'' the edges between pixels. Each pixel has an integer
  7081  weight, obtained by summing the weights on all edges to its left. \MF\
  7082  represents only the nonzero edge weights, since most of the edges are
  7083  weightless; in this way, the data storage requirements grow only linearly
  7084  with respect to the number of pixels per point, even though two-dimensional
  7085  data is being represented. (Well, the actual dependence on the underlying
  7086  resolution is order $n\log n$, but the $\log n$ factor is buried in our
  7087  implicit restriction on the maximum raster size.) The sum of all edge
  7088  weights in each row should be zero.
  7089  
  7090  The data structure for edge weights must be compact and flexible,
  7091  yet it should support efficient updating and display operations. We
  7092  want to be able to have many different edge structures in memory at
  7093  once, and we want the computer to be able to translate them, reflect them,
  7094  and/or merge them together with relative ease.
  7095  
  7096  \MF's solution to this problem requires one single-word node per
  7097  nonzero edge weight, plus one two-word node for each row in a contiguous
  7098  set of rows. There's also a header node that provides global information
  7099  about the entire structure.
  7100  
  7101  @ Let's consider the edge-weight nodes first. The |info| field of such
  7102  nodes contains both an $m$~value and a weight~$w$, in the form
  7103  $8m+w+c$, where $c$ is a constant that depends on data found in the header.
  7104  We shall consider $c$ in detail later; for now, it's best just to think
  7105  of it as a way to compensate for the fact that $m$ and~$w$ can be negative,
  7106  together with the fact that an |info| field must have a value between
  7107  |min_halfword| and |max_halfword|. The $m$ value is an unscaled $x$~coordinate,
  7108  so it satisfies $\vert m\vert<
  7109  4096$; the $w$ value is always in the range $1\L\vert w\vert\L3$. We can
  7110  unpack the data in the |info| field by fetching |ho(info(p))=
  7111  info(p)-min_halfword| and dividing this nonnegative number by~8;
  7112  the constant~$c$ will be chosen so that the remainder of this division
  7113  is $4+w$. Thus, for example, a remainder of~3 will correspond to
  7114  the edge weight $w=-1$.
  7115  
  7116  Every row of an edge structure contains two lists of such edge-weight
  7117  nodes, called the |sorted| and |unsorted| lists, linked together by their
  7118  |link| fields in the normal way. The difference between them is that we
  7119  always have |info(p)<=info(link(p))| in the |sorted| list, but there's no
  7120  such restriction on the elements of the |unsorted| list. The reason for
  7121  this distinction is that it would take unnecessarily long to maintain
  7122  edge-weight lists in sorted order while they're being updated; but when we
  7123  need to process an entire row from left to right in order of the
  7124  $m$~values, it's fairly easy and quick to sort a short list of unsorted
  7125  elements and to merge them into place among their sorted cohorts.
  7126  Furthermore, the fact that the |unsorted| list is empty can sometimes be
  7127  used to good advantage, because it allows us to conclude that a particular
  7128  row has not changed since the last time we sorted it.
  7129  
  7130  The final |link| of the |sorted| list will be |sentinel|, which points to
  7131  a special one-word node whose |info| field is essentially infinite; this
  7132  facilitates the sorting and merging operations. The final |link| of the
  7133  |unsorted| list will be either |null| or |void|, where |void=null+1|
  7134  is used to avoid redisplaying data that has not changed:
  7135  A |void| value is stored at the head of the
  7136  unsorted list whenever the corresponding row has been displayed.
  7137  
  7138  @d zero_w=4
  7139  @d void==null+1
  7140  
  7141  @<Initialize table entries...@>=
  7142  info(sentinel):=max_halfword; {|link(sentinel)=null|}
  7143  
  7144  @ The rows themselves are represented by row header nodes that
  7145  contain four link fields. Two of these four, |sorted| and |unsorted|,
  7146  point to the first items of the edge-weight lists just mentioned.
  7147  The other two, |link| and |knil|, point to the headers of the two
  7148  adjacent rows. If |p| points to the header for row number~|n|, then
  7149  |link(p)| points up to the header for row~|n+1|, and |knil(p)| points
  7150  down to the header for row~|n-1|. This double linking makes it
  7151  convenient to move through consecutive rows either upward or downward;
  7152  as usual, we have |link(knil(p))=knil(link(p))=p| for all row headers~|p|.
  7153  
  7154  The row associated with a given value of |n| contains weights for
  7155  edges that run between the lattice points |(m,n)| and |(m,n+1)|.
  7156  
  7157  @d knil==info {inverse of the |link| field, in a doubly linked list}
  7158  @d sorted_loc(#)==#+1 {where the |sorted| link field resides}
  7159  @d sorted(#)==link(sorted_loc(#)) {beginning of the list of sorted edge weights}
  7160  @d unsorted(#)==info(#+1) {beginning of the list of unsorted edge weights}
  7161  @d row_node_size=2 {number of words in a row header node}
  7162  
  7163  @ The main header node |h| for an edge structure has |link| and |knil|
  7164  fields that link it above the topmost row and below the bottommost row.
  7165  It also has fields called |m_min|, |m_max|, |n_min|, and |n_max| that
  7166  bound the current extent of the edge data: All |m| values in edge-weight
  7167  nodes should lie between |m_min(h)-4096| and |m_max(h)-4096|, inclusive.
  7168  Furthermore the topmost row header, pointed to by |knil(h)|,
  7169  is for row number |n_max(h)-4096|; the bottommost row header, pointed to by
  7170  |link(h)|, is for row number |n_min(h)-4096|.
  7171  
  7172  The offset constant |c| that's used in all of the edge-weight data is
  7173  represented implicitly in |m_offset(h)|; its actual value is
  7174  $$\hbox{|c=min_halfword+zero_w+8*m_offset(h)|.}$$
  7175  Notice that it's possible to shift an entire edge structure by an
  7176  amount $(\Delta m,\Delta n)$ by adding $\Delta n$ to |n_min(h)| and |n_max(h)|,
  7177  adding $\Delta m$ to |m_min(h)| and |m_max(h)|, and subtracting
  7178  $\Delta m$ from |m_offset(h)|;
  7179  none of the other edge data needs to be modified. Initially the |m_offset|
  7180  field is~4096, but it will change if the user requests such a shift.
  7181  The contents of these five fields should always be positive and less than
  7182  8192; |n_max| should, in fact, be less than 8191.  Furthermore
  7183  |m_min+m_offset-4096| and |m_max+m_offset-4096| must also lie strictly
  7184  between 0 and 8192, so that the |info| fields of edge-weight nodes will
  7185  fit in a halfword.
  7186  
  7187  The header node of an edge structure also contains two somewhat unusual
  7188  fields that are called |last_window(h)| and |last_window_time(h)|. When this
  7189  structure is displayed in window~|k| of the user's screen, after that
  7190  window has been updated |t| times, \MF\ sets |last_window(h):=k| and
  7191  |last_window_time(h):=t|; it also sets |unsorted(p):=void| for all row
  7192  headers~|p|, after merging any existing unsorted weights with the sorted
  7193  ones.  A subsequent display in the same window will be able to avoid
  7194  redisplaying rows whose |unsorted| list is still |void|, if the window
  7195  hasn't been used for something else in the meantime.
  7196  
  7197  A pointer to the row header of row |n_pos(h)-4096| is provided in
  7198  |n_rover(h)|. Most of the algorithms that update an edge structure
  7199  are able to get by without random row references; they usually
  7200  access rows that are neighbors of each other or of the current |n_pos| row.
  7201  Exception: If |link(h)=h| (so that the edge structure contains
  7202  no rows), we have |n_rover(h)=h|, and |n_pos(h)| is irrelevant.
  7203  
  7204  @d zero_field=4096 {amount added to coordinates to make them positive}
  7205  @d n_min(#)==info(#+1) {minimum row number present, plus |zero_field|}
  7206  @d n_max(#)==link(#+1) {maximum row number present, plus |zero_field|}
  7207  @d m_min(#)==info(#+2) {minimum column number present, plus |zero_field|}
  7208  @d m_max(#)==link(#+2) {maximum column number present, plus |zero_field|}
  7209  @d m_offset(#)==info(#+3) {translation of $m$ data in edge-weight nodes}
  7210  @d last_window(#)==link(#+3) {the last display went into this window}
  7211  @d last_window_time(#)==mem[#+4].int {after this many window updates}
  7212  @d n_pos(#)==info(#+5) {the row currently in |n_rover|, plus |zero_field|}
  7213  @d n_rover(#)==link(#+5) {a row recently referenced}
  7214  @d edge_header_size=6 {number of words in an edge-structure header}
  7215  @d valid_range(#)==(abs(#-4096)<4096) {is |#| strictly between 0 and 8192?}
  7216  @d empty_edges(#)==link(#)=# {are there no rows in this edge header?}
  7217  
  7218  @p procedure init_edges(@!h:pointer); {initialize an edge header to null values}
  7219  begin knil(h):=h; link(h):=h;@/
  7220  n_min(h):=zero_field+4095; n_max(h):=zero_field-4095;
  7221  m_min(h):=zero_field+4095; m_max(h):=zero_field-4095;
  7222  m_offset(h):=zero_field;@/
  7223  last_window(h):=0; last_window_time(h):=0;@/
  7224  n_rover(h):=h; n_pos(h):=0;@/
  7225  end;
  7226  
  7227  @ When a lot of work is being done on a particular edge structure, we plant
  7228  a pointer to its main header in the global variable |cur_edges|.
  7229  This saves us from having to pass this pointer as a parameter over and
  7230  over again between subroutines.
  7231  
  7232  Similarly, |cur_wt| is a global weight that is being used by several
  7233  procedures at once.
  7234  
  7235  @<Glob...@>=
  7236  @!cur_edges:pointer; {the edge structure of current interest}
  7237  @!cur_wt:integer; {the edge weight of current interest}
  7238  
  7239  @ The |fix_offset| routine goes through all the edge-weight nodes of
  7240  |cur_edges| and adds a constant to their |info| fields, so that
  7241  |m_offset(cur_edges)| can be brought back to |zero_field|. (This
  7242  is necessary only in unusual cases when the offset has gotten too
  7243  large or too small.)
  7244  
  7245  @p procedure fix_offset;
  7246  var @!p,@!q:pointer; {list traversers}
  7247  @!delta:integer; {the amount of change}
  7248  begin delta:=8*(m_offset(cur_edges)-zero_field);
  7249  m_offset(cur_edges):=zero_field;
  7250  q:=link(cur_edges);
  7251  while q<>cur_edges do
  7252    begin p:=sorted(q);
  7253    while p<>sentinel do
  7254      begin info(p):=info(p)-delta; p:=link(p);
  7255      end;
  7256    p:=unsorted(q);
  7257    while p>void do
  7258      begin info(p):=info(p)-delta; p:=link(p);
  7259      end;
  7260    q:=link(q);
  7261    end;
  7262  end;
  7263  
  7264  @ The |edge_prep| routine makes the |cur_edges| structure ready to
  7265  accept new data whose coordinates satisfy |ml<=m<=mr| and |nl<=n<=nr-1|,
  7266  assuming that |-4096<ml<=mr<4096| and |-4096<nl<=nr<4096|. It makes
  7267  appropriate adjustments to |m_min|, |m_max|, |n_min|, and |n_max|,
  7268  adding new empty rows if necessary.
  7269  
  7270  @p procedure edge_prep(@!ml,@!mr,@!nl,@!nr:integer);
  7271  var @!delta:halfword; {amount of change}
  7272  @!p,@!q:pointer; {for list manipulation}
  7273  begin ml:=ml+zero_field; mr:=mr+zero_field;
  7274  nl:=nl+zero_field; nr:=nr-1+zero_field;@/
  7275  if ml<m_min(cur_edges) then m_min(cur_edges):=ml;
  7276  if mr>m_max(cur_edges) then m_max(cur_edges):=mr;
  7277  if not valid_range(m_min(cur_edges)+m_offset(cur_edges)-zero_field) or@|
  7278   not valid_range(m_max(cur_edges)+m_offset(cur_edges)-zero_field) then
  7279    fix_offset;
  7280  if empty_edges(cur_edges) then {there are no rows}
  7281    begin n_min(cur_edges):=nr+1; n_max(cur_edges):=nr;
  7282    end;
  7283  if nl<n_min(cur_edges) then
  7284    @<Insert exactly |n_min(cur_edges)-nl| empty rows at the bottom@>;
  7285  if nr>n_max(cur_edges) then
  7286    @<Insert exactly |nr-n_max(cur_edges)| empty rows at the top@>;
  7287  end;
  7288  
  7289  @ @<Insert exactly |n_min(cur_edges)-nl| empty rows at the bottom@>=
  7290  begin delta:=n_min(cur_edges)-nl; n_min(cur_edges):=nl;
  7291  p:=link(cur_edges);
  7292  repeat q:=get_node(row_node_size); sorted(q):=sentinel; unsorted(q):=void;
  7293  knil(p):=q; link(q):=p; p:=q; decr(delta);
  7294  until delta=0;
  7295  knil(p):=cur_edges; link(cur_edges):=p;
  7296  if n_rover(cur_edges)=cur_edges then n_pos(cur_edges):=nl-1;
  7297  end
  7298  
  7299  @ @<Insert exactly |nr-n_max(cur_edges)| empty rows at the top@>=
  7300  begin delta:=nr-n_max(cur_edges); n_max(cur_edges):=nr;
  7301  p:=knil(cur_edges);
  7302  repeat q:=get_node(row_node_size); sorted(q):=sentinel; unsorted(q):=void;
  7303  link(p):=q; knil(q):=p; p:=q; decr(delta);
  7304  until delta=0;
  7305  link(p):=cur_edges; knil(cur_edges):=p;
  7306  if n_rover(cur_edges)=cur_edges then n_pos(cur_edges):=nr+1;
  7307  end
  7308  
  7309  @ The |print_edges| subroutine gives a symbolic rendition of an edge
  7310  structure, for use in `\&{show}' commands. A rather terse output
  7311  format has been chosen since edge structures can grow quite large.
  7312  
  7313  @<Declare subroutines for printing expressions@>=
  7314  @t\4@>@<Declare the procedure called |print_weight|@>@;@/
  7315  procedure print_edges(@!s:str_number;@!nuline:boolean;@!x_off,@!y_off:integer);
  7316  var @!p,@!q,@!r:pointer; {for list traversal}
  7317  @!n:integer; {row number}
  7318  begin print_diagnostic("Edge structure",s,nuline);
  7319  p:=knil(cur_edges); n:=n_max(cur_edges)-zero_field;
  7320  while p<>cur_edges do
  7321    begin q:=unsorted(p); r:=sorted(p);
  7322    if(q>void)or(r<>sentinel) then
  7323      begin print_nl("row "); print_int(n+y_off); print_char(":");
  7324      while q>void do
  7325        begin print_weight(q,x_off); q:=link(q);
  7326        end;
  7327      print(" |");
  7328      while r<>sentinel do
  7329        begin print_weight(r,x_off); r:=link(r);
  7330        end;
  7331      end;
  7332    p:=knil(p); decr(n);
  7333    end;
  7334  end_diagnostic(true);
  7335  end;
  7336  
  7337  @ @<Declare the procedure called |print_weight|@>=
  7338  procedure print_weight(@!q:pointer;@!x_off:integer);
  7339  var @!w,@!m:integer; {unpacked weight and coordinate}
  7340  @!d:integer; {temporary data register}
  7341  begin d:=ho(info(q)); w:=d mod 8; m:=(d div 8)-m_offset(cur_edges);
  7342  if file_offset>max_print_line-9 then print_nl(" ")
  7343  else print_char(" ");
  7344  print_int(m+x_off);
  7345  while w>zero_w do
  7346    begin print_char("+"); decr(w);
  7347    end;
  7348  while w<zero_w do
  7349    begin print_char("-"); incr(w);
  7350    end;
  7351  end;
  7352  
  7353  @ Here's a trivial subroutine that copies an edge structure. (Let's hope
  7354  that the given structure isn't too gigantic.)
  7355  
  7356  @p function copy_edges(@!h:pointer):pointer;
  7357  var @!p,@!r:pointer; {variables that traverse the given structure}
  7358  @!hh,@!pp,@!qq,@!rr,@!ss:pointer; {variables that traverse the new structure}
  7359  begin hh:=get_node(edge_header_size);
  7360  mem[hh+1]:=mem[h+1]; mem[hh+2]:=mem[h+2];
  7361  mem[hh+3]:=mem[h+3]; mem[hh+4]:=mem[h+4]; {we've now copied |n_min|, |n_max|,
  7362    |m_min|, |m_max|, |m_offset|, |last_window|, and |last_window_time|}
  7363  n_pos(hh):=n_max(hh)+1;n_rover(hh):=hh;@/
  7364  p:=link(h); qq:=hh;
  7365  while p<>h do
  7366    begin pp:=get_node(row_node_size); link(qq):=pp; knil(pp):=qq;
  7367    @<Copy both |sorted| and |unsorted| lists of |p| to |pp|@>;
  7368    p:=link(p); qq:=pp;
  7369    end;
  7370  link(qq):=hh; knil(hh):=qq;
  7371  copy_edges:=hh;
  7372  end;
  7373  
  7374  @ @<Copy both |sorted| and |unsorted|...@>=
  7375  r:=sorted(p); rr:=sorted_loc(pp); {|link(rr)=sorted(pp)|}
  7376  while r<>sentinel do
  7377    begin ss:=get_avail; link(rr):=ss; rr:=ss; info(rr):=info(r);@/
  7378    r:=link(r);
  7379    end;
  7380  link(rr):=sentinel;@/
  7381  r:=unsorted(p); rr:=temp_head;
  7382  while r>void do
  7383    begin ss:=get_avail; link(rr):=ss; rr:=ss; info(rr):=info(r);@/
  7384    r:=link(r);
  7385    end;
  7386  link(rr):=r; unsorted(pp):=link(temp_head)
  7387  
  7388  @ Another trivial routine flips |cur_edges| about the |x|-axis
  7389  (i.e., negates all the |y| coordinates), assuming that at least
  7390  one row is present.
  7391  
  7392  @p procedure y_reflect_edges;
  7393  var @!p,@!q,@!r:pointer; {list manipulation registers}
  7394  begin p:=n_min(cur_edges);
  7395  n_min(cur_edges):=zero_field+zero_field-1-n_max(cur_edges);
  7396  n_max(cur_edges):=zero_field+zero_field-1-p;
  7397  n_pos(cur_edges):=zero_field+zero_field-1-n_pos(cur_edges);@/
  7398  p:=link(cur_edges); q:=cur_edges; {we assume that |p<>q|}
  7399  repeat r:=link(p); link(p):=q; knil(q):=p; q:=p; p:=r;
  7400  until q=cur_edges;
  7401  last_window_time(cur_edges):=0;
  7402  end;
  7403  
  7404  @ It's somewhat more difficult, yet not too hard, to reflect about the |y|-axis.
  7405  
  7406  @p procedure x_reflect_edges;
  7407  var @!p,@!q,@!r,@!s:pointer; {list manipulation registers}
  7408  @!m:integer; {|info| fields will be reflected with respect to this number}
  7409  begin p:=m_min(cur_edges);
  7410  m_min(cur_edges):=zero_field+zero_field-m_max(cur_edges);
  7411  m_max(cur_edges):=zero_field+zero_field-p;
  7412  m:=(zero_field+m_offset(cur_edges))*8+zero_w+min_halfword+zero_w+min_halfword;
  7413  m_offset(cur_edges):=zero_field;
  7414  p:=link(cur_edges);
  7415  repeat @<Reflect the edge-and-weight data in |sorted(p)|@>;
  7416  @<Reflect the edge-and-weight data in |unsorted(p)|@>;
  7417  p:=link(p);
  7418  until p=cur_edges;
  7419  last_window_time(cur_edges):=0;
  7420  end;
  7421  
  7422  @ We want to change the sign of the weight as we change the sign of the
  7423  |x|~coordinate. Fortunately, it's easier to do this than to negate
  7424  one without the other.
  7425  
  7426  @<Reflect the edge-and-weight data in |unsorted(p)|@>=
  7427  q:=unsorted(p);
  7428  while q>void do
  7429    begin info(q):=m-info(q); q:=link(q);
  7430    end
  7431  
  7432  @ Reversing the order of a linked list is best thought of as the process of
  7433  popping nodes off one stack and pushing them on another. In this case we
  7434  pop from stack~|q| and push to stack~|r|.
  7435  
  7436  @<Reflect the edge-and-weight data in |sorted(p)|@>=
  7437  q:=sorted(p); r:=sentinel;
  7438  while q<>sentinel do
  7439    begin s:=link(q); link(q):=r; r:=q; info(r):=m-info(q); q:=s;
  7440    end;
  7441  sorted(p):=r
  7442  
  7443  @ Now let's multiply all the $y$~coordinates of a nonempty edge structure
  7444  by a small integer $s>1$:
  7445  
  7446  @p procedure y_scale_edges(@!s:integer);
  7447  var @!p,@!q,@!pp,@!r,@!rr,@!ss:pointer; {list manipulation registers}
  7448  @!t:integer; {replication counter}
  7449  begin if (s*(n_max(cur_edges)+1-zero_field)>=4096) or@|
  7450   (s*(n_min(cur_edges)-zero_field)<=-4096) then
  7451    begin print_err("Scaled picture would be too big");
  7452  @.Scaled picture...big@>
  7453    help3("I can't yscale the picture as requested---it would")@/
  7454      ("make some coordinates too large or too small.")@/
  7455      ("Proceed, and I'll omit the transformation.");
  7456    put_get_error;
  7457    end
  7458  else  begin n_max(cur_edges):=s*(n_max(cur_edges)+1-zero_field)-1+zero_field;
  7459    n_min(cur_edges):=s*(n_min(cur_edges)-zero_field)+zero_field;
  7460    @<Replicate every row exactly $s$ times@>;
  7461    last_window_time(cur_edges):=0;
  7462    end;
  7463  end;
  7464  
  7465  @ @<Replicate...@>=
  7466  p:=cur_edges;
  7467  repeat q:=p; p:=link(p);
  7468  for t:=2 to s do
  7469    begin pp:=get_node(row_node_size); link(q):=pp; knil(p):=pp;
  7470    link(pp):=p; knil(pp):=q; q:=pp;
  7471    @<Copy both |sorted| and |unsorted|...@>;
  7472    end;
  7473  until link(p)=cur_edges
  7474  
  7475  @ Scaling the $x$~coordinates is, of course, our next task.
  7476  
  7477  @p procedure x_scale_edges(@!s:integer);
  7478  var @!p,@!q:pointer; {list manipulation registers}
  7479  @!t:0..65535; {unpacked |info| field}
  7480  @!w:0..7; {unpacked weight}
  7481  @!delta:integer; {amount added to scaled |info|}
  7482  begin if (s*(m_max(cur_edges)-zero_field)>=4096) or@|
  7483   (s*(m_min(cur_edges)-zero_field)<=-4096) then
  7484    begin print_err("Scaled picture would be too big");
  7485  @.Scaled picture...big@>
  7486    help3("I can't xscale the picture as requested---it would")@/
  7487      ("make some coordinates too large or too small.")@/
  7488      ("Proceed, and I'll omit the transformation.");
  7489    put_get_error;
  7490    end
  7491  else if (m_max(cur_edges)<>zero_field)or(m_min(cur_edges)<>zero_field) then
  7492    begin m_max(cur_edges):=s*(m_max(cur_edges)-zero_field)+zero_field;
  7493    m_min(cur_edges):=s*(m_min(cur_edges)-zero_field)+zero_field;
  7494    delta:=8*(zero_field-s*m_offset(cur_edges))+min_halfword;
  7495    m_offset(cur_edges):=zero_field;@/
  7496    @<Scale the $x$~coordinates of each row by $s$@>;
  7497    last_window_time(cur_edges):=0;
  7498    end;
  7499  end;
  7500  
  7501  @ The multiplications cannot overflow because we know that |s<4096|.
  7502  
  7503  @<Scale the $x$~coordinates of each row by $s$@>=
  7504  q:=link(cur_edges);
  7505  repeat p:=sorted(q);
  7506  while p<>sentinel do
  7507    begin t:=ho(info(p)); w:=t mod 8; info(p):=(t-w)*s+w+delta; p:=link(p);
  7508    end;
  7509  p:=unsorted(q);
  7510  while p>void do
  7511    begin t:=ho(info(p)); w:=t mod 8; info(p):=(t-w)*s+w+delta; p:=link(p);
  7512    end;
  7513  q:=link(q);
  7514  until q=cur_edges
  7515  
  7516  @ Here is a routine that changes the signs of all the weights, without
  7517  changing anything else.
  7518  
  7519  @p procedure negate_edges(@!h:pointer);
  7520  label done;
  7521  var @!p,@!q,@!r,@!s,@!t,@!u:pointer; {structure traversers}
  7522  begin p:=link(h);
  7523  while p<>h do
  7524    begin q:=unsorted(p);
  7525    while q>void do
  7526      begin info(q):=8-2*((ho(info(q))) mod 8)+info(q); q:=link(q);
  7527      end;
  7528    q:=sorted(p);
  7529    if q<>sentinel then
  7530      begin repeat info(q):=8-2*((ho(info(q))) mod 8)+info(q); q:=link(q);
  7531      until q=sentinel;
  7532      @<Put the list |sorted(p)| back into sort@>;
  7533      end;
  7534    p:=link(p);
  7535    end;
  7536  last_window_time(h):=0;
  7537  end;
  7538  
  7539  @ \MF\ would work even if the code in this section were omitted, because
  7540  a list of edge-and-weight data that is sorted only by
  7541  |m| but not~|w| turns out to be good enough for correct operation.
  7542  However, the author decided not to make the program even trickier than
  7543  it is already, since |negate_edges| isn't needed very often.
  7544  The simpler-to-state condition, ``keep the |sorted| list fully sorted,''
  7545  is therefore being preserved at the cost of extra computation.
  7546  
  7547  @<Put the list |sorted(p)|...@>=
  7548  u:=sorted_loc(p); q:=link(u); r:=q; s:=link(r); {|q=sorted(p)|}
  7549  loop@+  if info(s)>info(r) then
  7550      begin link(u):=q;
  7551      if s=sentinel then goto done;
  7552      u:=r; q:=s; r:=q; s:=link(r);
  7553      end
  7554    else  begin t:=s; s:=link(t); link(t):=q; q:=t;
  7555      end;
  7556  done: link(r):=sentinel
  7557  
  7558  @ The |unsorted| edges of a row are merged into the |sorted| ones by
  7559  a subroutine called |sort_edges|. It uses simple insertion sort,
  7560  followed by a merge, because the unsorted list is supposedly quite short.
  7561  However, the unsorted list is assumed to be nonempty.
  7562  
  7563  @p procedure sort_edges(@!h:pointer); {|h| is a row header}
  7564  label done;
  7565  var @!k:halfword; {key register that we compare to |info(q)|}
  7566  @!p,@!q,@!r,@!s:pointer;
  7567  begin r:=unsorted(h); unsorted(h):=null;
  7568  p:=link(r); link(r):=sentinel; link(temp_head):=r;
  7569  while p>void do {sort node |p| into the list that starts at |temp_head|}
  7570    begin k:=info(p); q:=temp_head;
  7571    repeat r:=q; q:=link(r);
  7572    until k<=info(q);
  7573    link(r):=p; r:=link(p); link(p):=q; p:=r;
  7574    end;
  7575  @<Merge the |temp_head| list into |sorted(h)|@>;
  7576  end;
  7577  
  7578  @ In this step we use the fact that |sorted(h)=link(sorted_loc(h))|.
  7579  
  7580  @<Merge the |temp_head| list into |sorted(h)|@>=
  7581  begin r:=sorted_loc(h); q:=link(r); p:=link(temp_head);
  7582  loop@+  begin k:=info(p);
  7583    while k>info(q) do
  7584      begin r:=q; q:=link(r);
  7585      end;
  7586    link(r):=p; s:=link(p); link(p):=q;
  7587    if s=sentinel then goto done;
  7588    r:=p; p:=s;
  7589    end;
  7590  done:end
  7591  
  7592  @ The |cull_edges| procedure ``optimizes'' an edge structure by making all
  7593  the pixel weights either |w_out| or~|w_in|. The weight will be~|w_in| after the
  7594  operation if and only if it was in the closed interval |[w_lo,w_hi]|
  7595  before, where |w_lo<=w_hi|. Either |w_out| or |w_in| is zero, while the other is
  7596  $\pm1$, $\pm2$, or $\pm3$. The parameters will be such that zero-weight
  7597  pixels will remain of weight zero.  (This is fortunate,
  7598  because there are infinitely many of them.)
  7599  
  7600  The procedure also computes the tightest possible bounds on the resulting
  7601  data, by updating |m_min|, |m_max|, |n_min|, and~|n_max|.
  7602  
  7603  @p procedure cull_edges(@!w_lo,@!w_hi,@!w_out,@!w_in:integer);
  7604  label done;
  7605  var @!p,@!q,@!r,@!s:pointer; {for list manipulation}
  7606  @!w:integer; {new weight after culling}
  7607  @!d:integer; {data register for unpacking}
  7608  @!m:integer; {the previous column number, including |m_offset|}
  7609  @!mm:integer; {the next column number, including |m_offset|}
  7610  @!ww:integer; {accumulated weight before culling}
  7611  @!prev_w:integer; {value of |w| before column |m|}
  7612  @!n,@!min_n,@!max_n:pointer; {current and extreme row numbers}
  7613  @!min_d,@!max_d:pointer; {extremes of the new edge-and-weight data}
  7614  begin min_d:=max_halfword; max_d:=min_halfword;
  7615  min_n:=max_halfword; max_n:=min_halfword;@/
  7616  p:=link(cur_edges); n:=n_min(cur_edges);
  7617  while p<>cur_edges do
  7618    begin if unsorted(p)>void then sort_edges(p);
  7619    if sorted(p)<>sentinel then
  7620      @<Cull superfluous edge-weight entries from |sorted(p)|@>;
  7621    p:=link(p); incr(n);
  7622    end;
  7623  @<Delete empty rows at the top and/or bottom;
  7624    update the boundary values in the header@>;
  7625  last_window_time(cur_edges):=0;
  7626  end;
  7627  
  7628  @ The entire |sorted| list is returned to available memory in this step;
  7629  a new list is built starting (temporarily) at |temp_head|.
  7630  Since several edges can occur at the same column, we need to be looking
  7631  ahead of where the actual culling takes place. This means that it's
  7632  slightly tricky to get the iteration started and stopped.
  7633  
  7634  @<Cull superfluous...@>=
  7635  begin r:=temp_head; q:=sorted(p); ww:=0; m:=1000000; prev_w:=0;
  7636  loop@+  begin if q=sentinel then mm:=1000000
  7637    else  begin d:=ho(info(q)); mm:=d div 8; ww:=ww+(d mod 8)-zero_w;
  7638      end;
  7639    if mm>m then
  7640      begin @<Insert an edge-weight for edge |m|, if the new pixel
  7641        weight has changed@>;
  7642      if q=sentinel then goto done;
  7643      end;
  7644    m:=mm;
  7645    if ww>=w_lo then if ww<=w_hi then w:=w_in
  7646      else w:=w_out
  7647    else w:=w_out;
  7648    s:=link(q); free_avail(q); q:=s;
  7649    end;
  7650  done: link(r):=sentinel; sorted(p):=link(temp_head);
  7651  if r<>temp_head then @<Update the max/min amounts@>;
  7652  end
  7653  
  7654  @ @<Insert an edge-weight for edge |m|, if...@>=
  7655  if w<>prev_w then
  7656    begin s:=get_avail; link(r):=s;
  7657    info(s):=8*m+min_halfword+zero_w+w-prev_w;
  7658    r:=s; prev_w:=w;
  7659    end
  7660  
  7661  @ @<Update the max/min amounts@>=
  7662  begin if min_n=max_halfword then min_n:=n;
  7663  max_n:=n;
  7664  if min_d>info(link(temp_head)) then min_d:=info(link(temp_head));
  7665  if max_d<info(r) then max_d:=info(r);
  7666  end
  7667  
  7668  @ @<Delete empty rows at the top and/or bottom...@>=
  7669  if min_n>max_n then @<Delete all the row headers@>
  7670  else  begin n:=n_min(cur_edges); n_min(cur_edges):=min_n;
  7671    while min_n>n do
  7672      begin p:=link(cur_edges); link(cur_edges):=link(p);
  7673      knil(link(p)):=cur_edges;
  7674      free_node(p,row_node_size); incr(n);
  7675      end;
  7676    n:=n_max(cur_edges); n_max(cur_edges):=max_n;
  7677    n_pos(cur_edges):=max_n+1; n_rover(cur_edges):=cur_edges;
  7678    while max_n<n do
  7679      begin p:=knil(cur_edges); knil(cur_edges):=knil(p);
  7680      link(knil(p)):=cur_edges;
  7681      free_node(p,row_node_size); decr(n);
  7682      end;
  7683    m_min(cur_edges):=((ho(min_d)) div 8)-m_offset(cur_edges)+zero_field;
  7684    m_max(cur_edges):=((ho(max_d)) div 8)-m_offset(cur_edges)+zero_field;
  7685    end
  7686  
  7687  @ We get here if the edges have been entirely culled away.
  7688  
  7689  @<Delete all the row headers@>=
  7690  begin p:=link(cur_edges);
  7691  while p<>cur_edges do
  7692    begin q:=link(p); free_node(p,row_node_size); p:=q;
  7693    end;
  7694  init_edges(cur_edges);
  7695  end
  7696  
  7697  
  7698  @ The last and most difficult routine for transforming an edge structure---and
  7699  the most interesting one!---is |xy_swap_edges|, which interchanges the
  7700  r\^^Doles of rows and columns. Its task can be viewed as the job of
  7701  creating an edge structure that contains only horizontal edges, linked
  7702  together in columns, given an edge structure that contains only
  7703  vertical edges linked together in rows; we must do this without changing
  7704  the implied pixel weights.
  7705  
  7706  Given any two adjacent rows of an edge structure, it is not difficult to
  7707  determine the horizontal edges that lie ``between'' them: We simply look
  7708  for vertically adjacent pixels that have different weight, and insert
  7709  a horizontal edge containing the difference in weights. Every horizontal
  7710  edge determined in this way should be put into an appropriate linked
  7711  list. Since random access to these linked lists is desirable, we use
  7712  the |move| array to hold the list heads. If we work through the given
  7713  edge structure from top to bottom, the constructed lists will not need
  7714  to be sorted, since they will already be in order.
  7715  
  7716  The following algorithm makes use of some ideas suggested by John Hobby.
  7717  @^Hobby, John Douglas@>
  7718  It assumes that the edge structure is non-null, i.e., that |link(cur_edges)
  7719  <>cur_edges|, hence |m_max(cur_edges)>=m_min(cur_edges)|.
  7720  
  7721  @p procedure xy_swap_edges; {interchange |x| and |y| in |cur_edges|}
  7722  label done;
  7723  var @!m_magic,@!n_magic:integer; {special values that account for offsets}
  7724  @!p,@!q,@!r,@!s:pointer; {pointers that traverse the given structure}
  7725  @<Other local variables for |xy_swap_edges|@>@;
  7726  begin @<Initialize the array of new edge list heads@>;
  7727  @<Insert blank rows at the top and bottom, and set |p| to the new top row@>;
  7728  @<Compute the magic offset values@>;
  7729  repeat q:=knil(p);@+if unsorted(q)>void then sort_edges(q);
  7730  @<Insert the horizontal edges defined by adjacent rows |p,q|,
  7731    and destroy row~|p|@>;
  7732  p:=q; n_magic:=n_magic-8;
  7733  until knil(p)=cur_edges;
  7734  free_node(p,row_node_size); {now all original rows have been recycled}
  7735  @<Adjust the header to reflect the new edges@>;
  7736  end;
  7737  
  7738  @ Here we don't bother to keep the |link| entries up to date, since the
  7739  procedure looks only at the |knil| fields as it destroys the former
  7740  edge structure.
  7741  
  7742  @<Insert blank rows at the top and bottom...@>=
  7743  p:=get_node(row_node_size); sorted(p):=sentinel; unsorted(p):=null;@/
  7744  knil(p):=cur_edges; knil(link(cur_edges)):=p; {the new bottom row}
  7745  p:=get_node(row_node_size); sorted(p):=sentinel;
  7746  knil(p):=knil(cur_edges); {the new top row}
  7747  
  7748  @ The new lists will become |sorted| lists later, so we initialize
  7749  empty lists to |sentinel|.
  7750  
  7751  @<Initialize the array of new edge list heads@>=
  7752  m_spread:=m_max(cur_edges)-m_min(cur_edges); {this is |>=0| by assumption}
  7753  if m_spread>move_size then overflow("move table size",move_size);
  7754  @:METAFONT capacity exceeded move table size}{\quad move table size@>
  7755  for j:=0 to m_spread do move[j]:=sentinel
  7756  
  7757  @ @<Other local variables for |xy_swap_edges|@>=
  7758  @!m_spread:integer; {the difference between |m_max| and |m_min|}
  7759  @!j,@!jj:0..move_size; {indices into |move|}
  7760  @!m,@!mm:integer; {|m| values at vertical edges}
  7761  @!pd,@!rd:integer; {data fields from edge-and-weight nodes}
  7762  @!pm,@!rm:integer; {|m| values from edge-and-weight nodes}
  7763  @!w:integer; {the difference in accumulated weight}
  7764  @!ww:integer; {as much of |w| that can be stored in a single node}
  7765  @!dw:integer; {an increment to be added to |w|}
  7766  
  7767  @ At the point where we test |w<>0|, variable |w| contains
  7768  the accumulated weight from edges already passed in
  7769  row~|p| minus the accumulated weight from edges already passed in row~|q|.
  7770  
  7771  @<Insert the horizontal edges defined by adjacent rows |p,q|...@>=
  7772  r:=sorted(p); free_node(p,row_node_size); p:=r;@/
  7773  pd:=ho(info(p)); pm:=pd div 8;@/
  7774  r:=sorted(q); rd:=ho(info(r)); rm:=rd div 8; w:=0;
  7775  loop@+  begin if pm<rm then mm:=pm@+else mm:=rm;
  7776    if w<>0 then
  7777      @<Insert horizontal edges of weight |w| between |m| and~|mm|@>;
  7778    if pd<rd then
  7779      begin dw:=(pd mod 8)-zero_w;
  7780      @<Advance pointer |p| to the next vertical edge,
  7781        after destroying the previous one@>;
  7782      end
  7783    else  begin if r=sentinel then goto done; {|rd=pd=ho(max_halfword)|}
  7784      dw:=-((rd mod 8)-zero_w);
  7785      @<Advance pointer |r| to the next vertical edge@>;
  7786      end;
  7787    m:=mm; w:=w+dw;
  7788    end;
  7789  done:
  7790  
  7791  @ @<Advance pointer |r| to the next vertical edge@>=
  7792  r:=link(r); rd:=ho(info(r)); rm:=rd div 8
  7793  
  7794  @ @<Advance pointer |p| to the next vertical edge...@>=
  7795  s:=link(p); free_avail(p); p:=s; pd:=ho(info(p)); pm:=pd div 8
  7796  
  7797  @ Certain ``magic'' values are needed to make the following code work,
  7798  because of the various offsets in our data structure. For now, let's not
  7799  worry about their precise values; we shall compute |m_magic| and |n_magic|
  7800  later, after we see what the code looks like.
  7801  
  7802  @ @<Insert horizontal edges of weight |w| between |m| and~|mm|@>=
  7803  if m<>mm then
  7804    begin if mm-m_magic>=move_size then confusion("xy");
  7805  @:this can't happen xy}{\quad xy@>
  7806    extras:=(abs(w)-1) div 3;
  7807    if extras>0 then
  7808      begin if w>0 then xw:=+3@+else xw:=-3;
  7809      ww:=w-extras*xw;
  7810      end
  7811    else ww:=w;
  7812    repeat j:=m-m_magic;
  7813    for k:=1 to extras do
  7814      begin s:=get_avail; info(s):=n_magic+xw;
  7815      link(s):=move[j]; move[j]:=s;
  7816      end;
  7817    s:=get_avail; info(s):=n_magic+ww;
  7818    link(s):=move[j]; move[j]:=s;@/
  7819    incr(m);
  7820    until m=mm;
  7821    end
  7822  
  7823  @ @<Other local variables for |xy...@>=
  7824  @!extras:integer; {the number of additional nodes to make weights |>3|}
  7825  @!xw:-3..3; {the additional weight in extra nodes}
  7826  @!k:integer; {loop counter for inserting extra nodes}
  7827  
  7828  @ At the beginning of this step, |move[m_spread]=sentinel|, because no
  7829  horizontal edges will extend to the right of column |m_max(cur_edges)|.
  7830  
  7831  @<Adjust the header to reflect the new edges@>=
  7832  move[m_spread]:=0; j:=0;
  7833  while move[j]=sentinel do incr(j);
  7834  if j=m_spread then init_edges(cur_edges) {all edge weights are zero}
  7835  else  begin mm:=m_min(cur_edges);
  7836    m_min(cur_edges):=n_min(cur_edges);
  7837    m_max(cur_edges):=n_max(cur_edges)+1;
  7838    m_offset(cur_edges):=zero_field;
  7839    jj:=m_spread-1;
  7840    while move[jj]=sentinel do decr(jj);
  7841    n_min(cur_edges):=j+mm; n_max(cur_edges):=jj+mm; q:=cur_edges;
  7842    repeat p:=get_node(row_node_size); link(q):=p; knil(p):=q;
  7843    sorted(p):=move[j]; unsorted(p):=null; incr(j); q:=p;
  7844    until j>jj;
  7845    link(q):=cur_edges; knil(cur_edges):=q;
  7846    n_pos(cur_edges):=n_max(cur_edges)+1; n_rover(cur_edges):=cur_edges;
  7847    last_window_time(cur_edges):=0;
  7848    end;
  7849  
  7850  @ The values of |m_magic| and |n_magic| can be worked out by trying the
  7851  code above on a small example; if they work correctly in simple cases,
  7852  they should work in general.
  7853  
  7854  @<Compute the magic offset values@>=
  7855  m_magic:=m_min(cur_edges)+m_offset(cur_edges)-zero_field;
  7856  n_magic:=8*n_max(cur_edges)+8+zero_w+min_halfword
  7857  
  7858  @ Now let's look at the subroutine that merges the edges from a given
  7859  edge structure into |cur_edges|. The given edge structure loses all its
  7860  edges.
  7861  
  7862  @p procedure merge_edges(@!h:pointer);
  7863  label done;
  7864  var @!p,@!q,@!r,@!pp,@!qq,@!rr:pointer; {list manipulation registers}
  7865  @!n:integer; {row number}
  7866  @!k:halfword; {key register that we compare to |info(q)|}
  7867  @!delta:integer; {change to the edge/weight data}
  7868  begin if link(h)<>h then
  7869    begin if (m_min(h)<m_min(cur_edges))or(m_max(h)>m_max(cur_edges))or@|
  7870      (n_min(h)<n_min(cur_edges))or(n_max(h)>n_max(cur_edges)) then
  7871      edge_prep(m_min(h)-zero_field,m_max(h)-zero_field,
  7872        n_min(h)-zero_field,n_max(h)-zero_field+1);
  7873    if m_offset(h)<>m_offset(cur_edges) then
  7874      @<Adjust the data of |h| to account for a difference of offsets@>;
  7875    n:=n_min(cur_edges); p:=link(cur_edges); pp:=link(h);
  7876    while n<n_min(h) do
  7877      begin incr(n); p:=link(p);
  7878      end;
  7879    repeat @<Merge row |pp| into row |p|@>;
  7880    pp:=link(pp); p:=link(p);
  7881    until pp=h;
  7882    end;
  7883  end;
  7884  
  7885  @ @<Adjust the data of |h| to account for a difference of offsets@>=
  7886  begin pp:=link(h); delta:=8*(m_offset(cur_edges)-m_offset(h));
  7887  repeat qq:=sorted(pp);
  7888  while qq<>sentinel do
  7889    begin info(qq):=info(qq)+delta; qq:=link(qq);
  7890    end;
  7891  qq:=unsorted(pp);
  7892  while qq>void do
  7893    begin info(qq):=info(qq)+delta; qq:=link(qq);
  7894    end;
  7895  pp:=link(pp);
  7896  until pp=h;
  7897  end
  7898  
  7899  @ The |sorted| and |unsorted| lists are merged separately. After this
  7900  step, row~|pp| will have no edges remaining, since they will all have
  7901  been merged into row~|p|.
  7902  
  7903  @<Merge row |pp|...@>=
  7904  qq:=unsorted(pp);
  7905  if qq>void then
  7906    if unsorted(p)<=void then unsorted(p):=qq
  7907    else  begin while link(qq)>void do qq:=link(qq);
  7908      link(qq):=unsorted(p); unsorted(p):=unsorted(pp);
  7909      end;
  7910  unsorted(pp):=null; qq:=sorted(pp);
  7911  if qq<>sentinel then
  7912    begin if unsorted(p)=void then unsorted(p):=null;
  7913    sorted(pp):=sentinel; r:=sorted_loc(p); q:=link(r); {|q=sorted(p)|}
  7914    if q=sentinel then sorted(p):=qq
  7915    else loop@+begin k:=info(qq);
  7916      while k>info(q) do
  7917        begin r:=q; q:=link(r);
  7918        end;
  7919      link(r):=qq; rr:=link(qq); link(qq):=q;
  7920      if rr=sentinel then goto done;
  7921      r:=qq; qq:=rr;
  7922      end;
  7923    end;
  7924  done:
  7925  
  7926  @ The |total_weight| routine computes the total of all pixel weights
  7927  in a given edge structure. It's not difficult to prove that this is
  7928  the sum of $(-w)$ times $x$ taken over all edges,
  7929  where $w$ and~$x$ are the weight and $x$~coordinates stored in an edge.
  7930  It's not necessary to worry that this quantity will overflow the
  7931  size of an |integer| register, because it will be less than~$2^{31}$
  7932  unless the edge structure has more than 174,762 edges. However, we had
  7933  better not try to compute it as a |scaled| integer, because a total
  7934  weight of almost $12\times 2^{12}$ can be produced by only four edges.
  7935  
  7936  @p function total_weight(@!h:pointer):integer; {|h| is an edge header}
  7937  var @!p,@!q:pointer; {variables that traverse the given structure}
  7938  @!n:integer; {accumulated total so far}
  7939  @!m:0..65535; {packed $x$ and $w$ values, including offsets}
  7940  begin n:=0; p:=link(h);
  7941  while p<>h do
  7942    begin q:=sorted(p);
  7943    while q<>sentinel do
  7944      @<Add the contribution of node |q| to the total weight,
  7945        and set |q:=link(q)|@>;
  7946    q:=unsorted(p);
  7947    while q>void do
  7948      @<Add the contribution of node |q| to the total weight,
  7949        and set |q:=link(q)|@>;
  7950    p:=link(p);
  7951    end;
  7952  total_weight:=n;
  7953  end;
  7954  
  7955  @ It's not necessary to add the offsets to the $x$ coordinates, because
  7956  an entire edge structure can be shifted without affecting its total weight.
  7957  Similarly, we don't need to subtract |zero_field|.
  7958  
  7959  @<Add the contribution of node |q| to the total weight...@>=
  7960  begin m:=ho(info(q)); n:=n-((m mod 8)-zero_w)*(m div 8);
  7961  q:=link(q);
  7962  end
  7963  
  7964  @ So far we've done lots of things to edge structures assuming that
  7965  edges are actually present, but we haven't seen how edges get created
  7966  in the first place. Let's turn now to the problem of generating new edges.
  7967  
  7968  \MF\ will display new edges as they are being computed, if |tracing_edges|
  7969  is positive. In order to keep such data reasonably compact, only the
  7970  points at which the path makes a $90^\circ$ or $180^\circ$ turn are listed.
  7971  
  7972  The tracing algorithm must remember some past history in order to suppress
  7973  unnecessary data. Three variables |trace_x|, |trace_y|, and |trace_yy|
  7974  provide this history: The last coordinates printed were |(trace_x,trace_y)|,
  7975  and the previous edge traced ended at |(trace_x,trace_yy)|. Before anything
  7976  at all has been traced, |trace_x=-4096|.
  7977  
  7978  @<Glob...@>=
  7979  @!trace_x:integer; {$x$~coordinate most recently shown in a trace}
  7980  @!trace_y:integer; {$y$~coordinate most recently shown in a trace}
  7981  @!trace_yy:integer; {$y$~coordinate most recently encountered}
  7982  
  7983  @ Edge tracing is initiated by the |begin_edge_tracing| routine,
  7984  continued by the |trace_a_corner| routine, and terminated by the
  7985  |end_edge_tracing| routine.
  7986  
  7987  @p procedure begin_edge_tracing;
  7988  begin print_diagnostic("Tracing edges","",true);
  7989  print(" (weight "); print_int(cur_wt); print_char(")"); trace_x:=-4096;
  7990  end;
  7991  @#
  7992  procedure trace_a_corner;
  7993  begin if file_offset>max_print_line-13 then print_nl("");
  7994  print_char("("); print_int(trace_x); print_char(","); print_int(trace_yy);
  7995  print_char(")"); trace_y:=trace_yy;
  7996  end;
  7997  @#
  7998  procedure end_edge_tracing;
  7999  begin if trace_x=-4096 then print_nl("(No new edges added.)")
  8000  @.No new edges added@>
  8001  else  begin trace_a_corner; print_char(".");
  8002    end;
  8003  end_diagnostic(true);
  8004  end;
  8005  
  8006  @ Just after a new edge weight has been put into the |info| field of
  8007  node~|r|, in row~|n|, the following routine continues an ongoing trace.
  8008  
  8009  @p procedure trace_new_edge(@!r:pointer;@!n:integer);
  8010  var @!d:integer; {temporary data register}
  8011  @!w:-3..3; {weight associated with an edge transition}
  8012  @!m,@!n0,@!n1:integer; {column and row numbers}
  8013  begin d:=ho(info(r)); w:=(d mod 8)-zero_w; m:=(d div 8)-m_offset(cur_edges);
  8014  if w=cur_wt then
  8015    begin n0:=n+1; n1:=n;
  8016    end
  8017  else  begin n0:=n; n1:=n+1;
  8018    end; {the edges run from |(m,n0)| to |(m,n1)|}
  8019  if m<>trace_x then
  8020    begin if trace_x=-4096 then
  8021      begin print_nl(""); trace_yy:=n0;
  8022      end
  8023    else if trace_yy<>n0 then print_char("?") {shouldn't happen}
  8024    else trace_a_corner;
  8025    trace_x:=m; trace_a_corner;
  8026    end
  8027  else  begin if n0<>trace_yy then print_char("!"); {shouldn't happen}
  8028    if ((n0<n1)and(trace_y>trace_yy))or((n0>n1)and(trace_y<trace_yy)) then
  8029      trace_a_corner;
  8030    end;
  8031  trace_yy:=n1;
  8032  end;
  8033  
  8034  @ One way to put new edge weights into an edge structure is to use the
  8035  following routine, which simply draws a straight line from |(x0,y0)| to
  8036  |(x1,y1)|. More precisely, it introduces weights for the edges of the
  8037  discrete path $\bigl(\lfloor t[x_0,x_1]+{1\over2}+\epsilon\rfloor,
  8038  \lfloor t[y_0,y_1]+{1\over2}+\epsilon\delta\rfloor\bigr)$,
  8039  as $t$ varies from 0 to~1, where $\epsilon$ and $\delta$ are extremely small
  8040  positive numbers.
  8041  
  8042  The structure header is assumed to be |cur_edges|; downward edge weights
  8043  will be |cur_wt|, while upward ones will be |-cur_wt|.
  8044  
  8045  Of course, this subroutine will be called only in connection with others
  8046  that eventually draw a complete cycle, so that the sum of the edge weights
  8047  in each row will be zero whenever the row is displayed.
  8048  
  8049  @p procedure line_edges(@!x0,@!y0,@!x1,@!y1:scaled);
  8050  label done,done1;
  8051  var @!m0,@!n0,@!m1,@!n1:integer; {rounded and unscaled coordinates}
  8052  @!delx,@!dely:scaled; {the coordinate differences of the line}
  8053  @!yt:scaled; {smallest |y| coordinate that rounds the same as |y0|}
  8054  @!tx:scaled; {tentative change in |x|}
  8055  @!p,@!r:pointer; {list manipulation registers}
  8056  @!base:integer; {amount added to edge-and-weight data}
  8057  @!n:integer; {current row number}
  8058  begin n0:=round_unscaled(y0);
  8059  n1:=round_unscaled(y1);
  8060  if n0<>n1 then
  8061    begin m0:=round_unscaled(x0); m1:=round_unscaled(x1);
  8062    delx:=x1-x0; dely:=y1-y0;
  8063    yt:=n0*unity-half_unit; y0:=y0-yt; y1:=y1-yt;
  8064    if n0<n1 then @<Insert upward edges for a line@>
  8065    else @<Insert downward edges for a line@>;
  8066    n_rover(cur_edges):=p; n_pos(cur_edges):=n+zero_field;
  8067    end;
  8068  end;
  8069  
  8070  @ Here we are careful to cancel any effect of rounding error.
  8071  
  8072  @<Insert upward edges for a line@>=
  8073  begin base:=8*m_offset(cur_edges)+min_halfword+zero_w-cur_wt;
  8074  if m0<=m1 then edge_prep(m0,m1,n0,n1)@+else edge_prep(m1,m0,n0,n1);
  8075  @<Move to row |n0|, pointed to by |p|@>;
  8076  y0:=unity-y0;
  8077  loop@+  begin r:=get_avail; link(r):=unsorted(p); unsorted(p):=r;@/
  8078    tx:=take_fraction(delx,make_fraction(y0,dely));
  8079    if ab_vs_cd(delx,y0,dely,tx)<0 then decr(tx);
  8080      {now $|tx|=\lfloor|y0|\cdot|delx|/|dely|\rfloor$}
  8081    info(r):=8*round_unscaled(x0+tx)+base;@/
  8082    y1:=y1-unity;
  8083    if internal[tracing_edges]>0 then trace_new_edge(r,n);
  8084    if y1<unity then goto done;
  8085    p:=link(p); y0:=y0+unity; incr(n);
  8086    end;
  8087  done: end
  8088  
  8089  @ @<Insert downward edges for a line@>=
  8090  begin base:=8*m_offset(cur_edges)+min_halfword+zero_w+cur_wt;
  8091  if m0<=m1 then edge_prep(m0,m1,n1,n0)@+else edge_prep(m1,m0,n1,n0);
  8092  decr(n0); @<Move to row |n0|, pointed to by |p|@>;
  8093  loop@+  begin r:=get_avail; link(r):=unsorted(p); unsorted(p):=r;@/
  8094    tx:=take_fraction(delx,make_fraction(y0,dely));
  8095    if ab_vs_cd(delx,y0,dely,tx)<0 then incr(tx);
  8096      {now $|tx|=\lceil|y0|\cdot|delx|/|dely|\rceil$, since |dely<0|}
  8097    info(r):=8*round_unscaled(x0-tx)+base;@/
  8098    y1:=y1+unity;
  8099    if internal[tracing_edges]>0 then trace_new_edge(r,n);
  8100    if y1>=0 then goto done1;
  8101    p:=knil(p); y0:=y0+unity; decr(n);
  8102    end;
  8103  done1: end
  8104  
  8105  @ @<Move to row |n0|, pointed to by |p|@>=
  8106  n:=n_pos(cur_edges)-zero_field; p:=n_rover(cur_edges);
  8107  if n<>n0 then
  8108    if n<n0 then
  8109      repeat incr(n); p:=link(p);
  8110      until n=n0
  8111    else  repeat decr(n); p:=knil(p);
  8112      until n=n0
  8113  
  8114  @ \MF\ inserts most of its edges into edge structures via the
  8115  |move_to_edges| subroutine, which uses the data stored in the |move| array
  8116  to specify a sequence of ``rook moves.'' The starting point |(m0,n0)|
  8117  and finishing point |(m1,n1)| of these moves, as seen from the standpoint
  8118  of the first octant, are supplied as parameters; the moves should, however,
  8119  be rotated into a given octant.  (We're going to study octant
  8120  transformations in great detail later; the reader may wish to come back to
  8121  this part of the program after mastering the mysteries of octants.)
  8122  
  8123  The rook moves themselves are defined as follows, from a |first_octant|
  8124  point of view: ``Go right |move[k]| steps, then go up one, for |0<=k<n1-n0|;
  8125  then go right |move[n1-n0]| steps and stop.'' The sum of |move[k]|
  8126  for |0<=k<=n1-n0| will be equal to |m1-m0|.
  8127  
  8128  As in the |line_edges| routine, we use |+cur_wt| as the weight of
  8129  all downward edges and |-cur_wt| as the weight of all upward edges,
  8130  after the moves have been rotated to the proper octant direction.
  8131  
  8132  There are two main cases to consider: \\{fast\_case} is for moves that
  8133  travel in the direction of octants 1, 4, 5, and~8, while \\{slow\_case}
  8134  is for moves that travel toward octants 2, 3, 6, and~7. The latter directions
  8135  are comparatively cumbersome because they generate more upward or downward
  8136  edges; a curve that travels horizontally doesn't produce any edges at all,
  8137  but a curve that travels vertically touches lots of rows.
  8138  
  8139  @d fast_case_up=60 {for octants 1 and 4}
  8140  @d fast_case_down=61 {for octants 5 and 8}
  8141  @d slow_case_up=62 {for octants 2 and 3}
  8142  @d slow_case_down=63 {for octants 6 and 7}
  8143  
  8144  @p procedure move_to_edges(@!m0,@!n0,@!m1,@!n1:integer);
  8145  label fast_case_up,fast_case_down,slow_case_up,slow_case_down,done;
  8146  var @!delta:0..move_size; {extent of |move| data}
  8147  @!k:0..move_size; {index into |move|}
  8148  @!p,@!r:pointer; {list manipulation registers}
  8149  @!dx:integer; {change in edge-weight |info| when |x| changes by 1}
  8150  @!edge_and_weight:integer; {|info| to insert}
  8151  @!j:integer; {number of consecutive vertical moves}
  8152  @!n:integer; {the current row pointed to by |p|}
  8153  debug @!sum:integer;@+gubed@;@/
  8154  begin delta:=n1-n0;
  8155  debug sum:=move[0]; for k:=1 to delta do sum:=sum+abs(move[k]);
  8156  if sum<>m1-m0 then confusion("0");@+gubed@;@/
  8157  @:this can't happen 0}{\quad 0@>
  8158  @<Prepare for and switch to the appropriate case, based on |octant|@>;
  8159  fast_case_up:@<Add edges for first or fourth octants, then |goto done|@>;
  8160  fast_case_down:@<Add edges for fifth or eighth octants, then |goto done|@>;
  8161  slow_case_up:@<Add edges for second or third octants, then |goto done|@>;
  8162  slow_case_down:@<Add edges for sixth or seventh octants, then |goto done|@>;
  8163  done: n_pos(cur_edges):=n+zero_field; n_rover(cur_edges):=p;
  8164  end;
  8165  
  8166  @ The current octant code appears in a global variable. If, for example,
  8167  we have |octant=third_octant|, it means that a curve traveling in a north to
  8168  north-westerly direction has been rotated for the purposes of internal
  8169  calculations so that the |move| data travels in an east to north-easterly
  8170  direction. We want to unrotate as we update the edge structure.
  8171  
  8172  @<Glob...@>=
  8173  @!octant:first_octant..sixth_octant; {the current octant of interest}
  8174  
  8175  @ @<Prepare for and switch to the appropriate case, based on |octant|@>=
  8176  case octant of
  8177  first_octant:begin dx:=8; edge_prep(m0,m1,n0,n1); goto fast_case_up;
  8178    end;
  8179  second_octant:begin dx:=8; edge_prep(n0,n1,m0,m1); goto slow_case_up;
  8180    end;
  8181  third_octant:begin dx:=-8; edge_prep(-n1,-n0,m0,m1); negate(n0);
  8182    goto slow_case_up;
  8183    end;
  8184  fourth_octant:begin dx:=-8; edge_prep(-m1,-m0,n0,n1); negate(m0);
  8185    goto fast_case_up;
  8186    end;
  8187  fifth_octant:begin dx:=-8; edge_prep(-m1,-m0,-n1,-n0); negate(m0);
  8188    goto fast_case_down;
  8189    end;
  8190  sixth_octant:begin dx:=-8; edge_prep(-n1,-n0,-m1,-m0); negate(n0);
  8191    goto slow_case_down;
  8192    end;
  8193  seventh_octant:begin dx:=8; edge_prep(n0,n1,-m1,-m0); goto slow_case_down;
  8194    end;
  8195  eighth_octant:begin dx:=8; edge_prep(m0,m1,-n1,-n0); goto fast_case_down;
  8196    end;
  8197  end; {there are only eight octants}
  8198  
  8199  @ @<Add edges for first or fourth octants, then |goto done|@>=
  8200  @<Move to row |n0|, pointed to by |p|@>;
  8201  if delta>0 then
  8202    begin k:=0;
  8203    edge_and_weight:=8*(m0+m_offset(cur_edges))+min_halfword+zero_w-cur_wt;
  8204    repeat edge_and_weight:=edge_and_weight+dx*move[k];
  8205    fast_get_avail(r); link(r):=unsorted(p); info(r):=edge_and_weight;
  8206    if internal[tracing_edges]>0 then trace_new_edge(r,n);
  8207    unsorted(p):=r; p:=link(p); incr(k); incr(n);
  8208    until k=delta;
  8209    end;
  8210  goto done
  8211  
  8212  @ @<Add edges for fifth or eighth octants, then |goto done|@>=
  8213  n0:=-n0-1; @<Move to row |n0|, pointed to by |p|@>;
  8214  if delta>0 then
  8215    begin k:=0;
  8216    edge_and_weight:=8*(m0+m_offset(cur_edges))+min_halfword+zero_w+cur_wt;
  8217    repeat edge_and_weight:=edge_and_weight+dx*move[k];
  8218    fast_get_avail(r); link(r):=unsorted(p); info(r):=edge_and_weight;
  8219    if internal[tracing_edges]>0 then trace_new_edge(r,n);
  8220    unsorted(p):=r; p:=knil(p); incr(k); decr(n);
  8221    until k=delta;
  8222    end;
  8223  goto done
  8224  
  8225  @ @<Add edges for second or third octants, then |goto done|@>=
  8226  edge_and_weight:=8*(n0+m_offset(cur_edges))+min_halfword+zero_w-cur_wt;
  8227  n0:=m0; k:=0; @<Move to row |n0|, pointed to by |p|@>;
  8228  repeat j:=move[k];
  8229  while j>0 do
  8230    begin fast_get_avail(r); link(r):=unsorted(p); info(r):=edge_and_weight;
  8231    if internal[tracing_edges]>0 then trace_new_edge(r,n);
  8232    unsorted(p):=r; p:=link(p); decr(j); incr(n);
  8233    end;
  8234  edge_and_weight:=edge_and_weight+dx; incr(k);
  8235  until k>delta;
  8236  goto done
  8237  
  8238  @ @<Add edges for sixth or seventh octants, then |goto done|@>=
  8239  edge_and_weight:=8*(n0+m_offset(cur_edges))+min_halfword+zero_w+cur_wt;
  8240  n0:=-m0-1; k:=0; @<Move to row |n0|, pointed to by |p|@>;
  8241  repeat j:=move[k];
  8242  while j>0 do
  8243    begin fast_get_avail(r); link(r):=unsorted(p); info(r):=edge_and_weight;
  8244    if internal[tracing_edges]>0 then trace_new_edge(r,n);
  8245    unsorted(p):=r; p:=knil(p); decr(j); decr(n);
  8246    end;
  8247  edge_and_weight:=edge_and_weight+dx; incr(k);
  8248  until k>delta;
  8249  goto done
  8250  
  8251  @ All the hard work of building an edge structure is undone by the following
  8252  subroutine.
  8253  
  8254  @<Declare the recycling subroutines@>=
  8255  procedure toss_edges(@!h:pointer);
  8256  var @!p,@!q:pointer; {for list manipulation}
  8257  begin q:=link(h);
  8258  while q<>h do
  8259    begin flush_list(sorted(q));
  8260    if unsorted(q)>void then flush_list(unsorted(q));
  8261    p:=q; q:=link(q); free_node(p,row_node_size);
  8262    end;
  8263  free_node(h,edge_header_size);
  8264  end;
  8265  
  8266  @* \[21] Subdivision into octants.
  8267  When \MF\ digitizes a path, it reduces the problem to the special
  8268  case of paths that travel in ``first octant'' directions; i.e.,
  8269  each cubic $z(t)=\bigl(x(t),y(t)\bigr)$ being digitized will have the property
  8270  that $0\L y'(t)\L x'(t)$. This assumption makes digitizing simpler
  8271  and faster than if the direction of motion has to be tested repeatedly.
  8272  
  8273  When $z(t)$ is cubic, $x'(t)$ and $y'(t)$ are quadratic, hence the four
  8274  polynomials $x'(t)$, $y'(t)$, $x'(t)-y'(t)$, and $x'(t)+y'(t)$ cross
  8275  through~0 at most twice each. If we subdivide the given cubic at these
  8276  places, we get at most nine subintervals in each of which
  8277  $x'(t)$, $y'(t)$, $x'(t)-y'(t)$, and $x'(t)+y'(t)$ all have a constant
  8278  sign. The curve can be transformed in each of these subintervals so that
  8279  it travels entirely in first octant directions, if we reflect $x\swap-x$,
  8280  $y\swap-y$, and/or $x\swap y$ as necessary. (Incidentally, it can be
  8281  shown that a cubic such that $x'(t)=16(2t-1)^2+2(2t-1)-1$ and
  8282  $y'(t)=8(2t-1)^2+4(2t-1)$ does indeed split into nine subintervals.)
  8283  
  8284  @ The transformation that rotates coordinates, so that first octant motion
  8285  can be assumed, is defined by the |skew| subroutine, which sets global
  8286  variables |cur_x| and |cur_y| to the values that are appropriate in a
  8287  given octant.  (Octants are encoded as they were in the |n_arg| subroutine.)
  8288  
  8289  This transformation is ``skewed'' by replacing |(x,y)| by |(x-y,y)|,
  8290  once first octant motion has been established. It turns out that
  8291  skewed coordinates are somewhat better to work with when curves are
  8292  actually digitized.
  8293  
  8294  @d set_two_end(#)==cur_y:=#;@+end
  8295  @d set_two(#)==begin cur_x:=#; set_two_end
  8296  
  8297  @p procedure skew(@!x,@!y:scaled;@!octant:small_number);
  8298  begin case octant of
  8299  first_octant: set_two(x-y)(y);
  8300  second_octant: set_two(y-x)(x);
  8301  third_octant: set_two(y+x)(-x);
  8302  fourth_octant: set_two(-x-y)(y);
  8303  fifth_octant: set_two(-x+y)(-y);
  8304  sixth_octant: set_two(-y+x)(-x);
  8305  seventh_octant: set_two(-y-x)(x);
  8306  eighth_octant: set_two(x+y)(-y);
  8307  end; {there are no other cases}
  8308  end;
  8309  
  8310  @ Conversely, the following subroutine sets |cur_x| and
  8311  |cur_y| to the original coordinate values of a point, given an octant
  8312  code and the point's coordinates |(x,y)| after they have been mapped into
  8313  the first octant and skewed.
  8314  
  8315  @<Declare subroutines for printing expressions@>=
  8316  procedure unskew(@!x,@!y:scaled;@!octant:small_number);
  8317  begin case octant of
  8318  first_octant: set_two(x+y)(y);
  8319  second_octant: set_two(y)(x+y);
  8320  third_octant: set_two(-y)(x+y);
  8321  fourth_octant: set_two(-x-y)(y);
  8322  fifth_octant: set_two(-x-y)(-y);
  8323  sixth_octant: set_two(-y)(-x-y);
  8324  seventh_octant: set_two(y)(-x-y);
  8325  eighth_octant: set_two(x+y)(-y);
  8326  end; {there are no other cases}
  8327  end;
  8328  
  8329  @ @<Glob...@>=
  8330  @!cur_x,@!cur_y:scaled;
  8331    {outputs of |skew|, |unskew|, and a few other routines}
  8332  
  8333  @ The conversion to skewed and rotated coordinates takes place in
  8334  stages, and at one point in the transformation we will have negated the
  8335  $x$ and/or $y$ coordinates so as to make curves travel in the first
  8336  {\sl quadrant}. At this point the relevant ``octant'' code will be
  8337  either |first_octant| (when no transformation has been done),
  8338  or |fourth_octant=first_octant+negate_x| (when $x$ has been negated),
  8339  or |fifth_octant=first_octant+negate_x+negate_y| (when both have been
  8340  negated), or |eighth_octant=first_octant+negate_y| (when $y$ has been
  8341  negated). The |abnegate| routine is sometimes needed to convert
  8342  from one of these transformations to another.
  8343  
  8344  @p procedure abnegate(@!x,@!y:scaled;
  8345    @!octant_before,@!octant_after:small_number);
  8346  begin if odd(octant_before)=odd(octant_after) then cur_x:=x
  8347    else cur_x:=-x;
  8348  if (octant_before>negate_y)=(octant_after>negate_y) then cur_y:=y
  8349    else cur_y:=-y;
  8350  end;
  8351  
  8352  @ Now here's a subroutine that's handy for subdivision: Given a
  8353  quadratic polynomial $B(a,b,c;t)$, the |crossing_point| function
  8354  returns the unique |fraction| value |t| between 0 and~1 at which
  8355  $B(a,b,c;t)$ changes from positive to negative, or returns
  8356  |t=fraction_one+1| if no such value exists. If |a<0| (so that $B(a,b,c;t)$
  8357  is already negative at |t=0|), |crossing_point| returns the value zero.
  8358  
  8359  @d no_crossing==begin crossing_point:=fraction_one+1; return;
  8360    end
  8361  @d one_crossing==begin crossing_point:=fraction_one; return;
  8362    end
  8363  @d zero_crossing==begin crossing_point:=0; return;
  8364    end
  8365  
  8366  @p function crossing_point(@!a,@!b,@!c:integer):fraction;
  8367  label exit;
  8368  var @!d:integer; {recursive counter}
  8369  @!x,@!xx,@!x0,@!x1,@!x2:integer; {temporary registers for bisection}
  8370  begin if a<0 then zero_crossing;
  8371  if c>=0 then
  8372    begin if b>=0 then
  8373      if c>0 then no_crossing
  8374      else if (a=0)and(b=0) then no_crossing
  8375      else one_crossing;
  8376    if a=0 then zero_crossing;
  8377    end
  8378  else if a=0 then if b<=0 then zero_crossing;
  8379  @<Use bisection to find the crossing point, if one exists@>;
  8380  exit:end;
  8381  
  8382  @ The general bisection method is quite simple when $n=2$, hence
  8383  |crossing_point| does not take much time. At each stage in the
  8384  recursion we have a subinterval defined by |l| and~|j| such that
  8385  $B(a,b,c;2^{-l}(j+t))=B(x_0,x_1,x_2;t)$, and we want to ``zero in'' on
  8386  the subinterval where $x_0\G0$ and $\min(x_1,x_2)<0$.
  8387  
  8388  It is convenient for purposes of calculation to combine the values
  8389  of |l| and~|j| in a single variable $d=2^l+j$, because the operation
  8390  of bisection then corresponds simply to doubling $d$ and possibly
  8391  adding~1. Furthermore it proves to be convenient to modify
  8392  our previous conventions for bisection slightly, maintaining the
  8393  variables $X_0=2^lx_0$, $X_1=2^l(x_0-x_1)$, and $X_2=2^l(x_1-x_2)$.
  8394  With these variables the conditions $x_0\ge0$ and $\min(x_1,x_2)<0$ are
  8395  equivalent to $\max(X_1,X_1+X_2)>X_0\ge0$.
  8396  
  8397  The following code maintains the invariant relations
  8398  $0\L|x0|<\max(|x1|,|x1|+|x2|)$,
  8399  $\vert|x1|\vert<2^{30}$, $\vert|x2|\vert<2^{30}$;
  8400  it has been constructed in such a way that no arithmetic overflow
  8401  will occur if the inputs satisfy
  8402  $a<2^{30}$, $\vert a-b\vert<2^{30}$, and $\vert b-c\vert<2^{30}$.
  8403  
  8404  @<Use bisection to find the crossing point...@>=
  8405  d:=1; x0:=a; x1:=a-b; x2:=b-c;
  8406  repeat x:=half(x1+x2);
  8407  if x1-x0>x0 then
  8408    begin x2:=x; double(x0); double(d);
  8409    end
  8410  else  begin xx:=x1+x-x0;
  8411    if xx>x0 then
  8412      begin x2:=x; double(x0); double(d);
  8413      end
  8414    else  begin x0:=x0-xx;
  8415      if x<=x0 then if x+x2<=x0 then no_crossing;
  8416      x1:=x; d:=d+d+1;
  8417      end;
  8418    end;
  8419  until d>=fraction_one;
  8420  crossing_point:=d-fraction_one
  8421  
  8422  @ Octant subdivision is applied only to cycles, i.e., to closed paths.
  8423  A ``cycle spec'' is a data structure that contains specifications of
  8424  @!@^cycle spec@>
  8425  cubic curves and octant mappings for the cycle that has been subdivided
  8426  into segments belonging to single octants. It is composed entirely of
  8427  knot nodes, similar to those in the representation of paths; but the
  8428  |explicit| type indications have been replaced by positive numbers
  8429  that give further information. Additional |endpoint| data is also
  8430  inserted at the octant boundaries.
  8431  
  8432  Recall that a cubic polynomial is represented by four control points
  8433  that appear in adjacent nodes |p| and~|q| of a knot list. The |x|~coordinates
  8434  are |x_coord(p)|, |right_x(p)|, |left_x(q)|, and |x_coord(q)|; the
  8435  |y|~coordinates are similar. We shall call this ``the cubic following~|p|''
  8436  or ``the cubic between |p| and~|q|'' or ``the cubic preceding~|q|.''
  8437  
  8438  Cycle specs are circular lists of cubic curves mixed with octant
  8439  boundaries. Like cubics, the octant boundaries are represented in
  8440  consecutive knot nodes |p| and~|q|. In such cases |right_type(p)=
  8441  left_type(q)=endpoint|, and the fields |right_x(p)|, |right_y(p)|,
  8442  |left_x(q)|, and |left_y(q)| are replaced by other fields called
  8443  |right_octant(p)|, |right_transition(p)|, |left_octant(q)|, and
  8444  |left_transition(q)|, respectively. For example, when the curve direction
  8445  moves from the third octant to the fourth octant, the boundary nodes say
  8446  |right_octant(p)=third_octant|, |left_octant(q)=fourth_octant|,
  8447  and |right_transition(p)=left_transition(q)=diagonal|. A |diagonal|
  8448  transition occurs when moving between octants 1~\AM~2, 3~\AM~4, 5~\AM~6, or
  8449  7~\AM~8; an |axis| transition occurs when moving between octants 8~\AM~1,
  8450  2~\AM~3, 4~\AM~5, 6~\AM~7. (Such transition information is redundant
  8451  but convenient.) Fields |x_coord(p)| and |y_coord(p)| will contain
  8452  coordinates of the transition point after rotation from third octant
  8453  to first octant; i.e., if the true coordinates are $(x,y)$, the
  8454  coordinates $(y,-x)$ will appear in node~|p|. Similarly, a fourth-octant
  8455  transformation will have been applied after the transition, so
  8456  we will have |x_coord(q)=@t$-x$@>| and |y_coord(q)=y|.
  8457  
  8458  The cubic between |p| and |q| will contain positive numbers in the
  8459  fields |right_type(p)| and |left_type(q)|; this makes cubics
  8460  distinguishable from octant boundaries, because |endpoint=0|.
  8461  The value of |right_type(p)| will be the current octant code,
  8462  during the time that cycle specs are being constructed; it will
  8463  refer later to a pen offset position, if the envelope of a cycle is
  8464  being computed. A cubic that comes from some subinterval of the $k$th
  8465  step in the original cyclic path will have |left_type(q)=k|.
  8466  
  8467  @d right_octant==right_x {the octant code before a transition}
  8468  @d left_octant==left_x {the octant after a transition}
  8469  @d right_transition==right_y {the type of transition}
  8470  @d left_transition==left_y {ditto, either |axis| or |diagonal|}
  8471  @d axis=0 {a transition across the $x'$- or $y'$-axis}
  8472  @d diagonal=1 {a transition where $y'=\pm x'$}
  8473  
  8474  @ Here's a routine that prints a cycle spec in symbolic form, so that it
  8475  is possible to see what subdivision has been made.  The point coordinates
  8476  are converted back from \MF's internal ``rotated'' form to the external
  8477  ``true'' form. The global variable~|cur_spec| should point to a knot just
  8478  after the beginning of an octant boundary, i.e., such that
  8479  |left_type(cur_spec)=endpoint|.
  8480  
  8481  @d print_two_true(#)==unskew(#,octant); print_two(cur_x,cur_y)
  8482  
  8483  @p procedure print_spec(@!s:str_number);
  8484  label not_found,done;
  8485  var @!p,@!q:pointer; {for list traversal}
  8486  @!octant:small_number; {the current octant code}
  8487  begin print_diagnostic("Cycle spec",s,true);
  8488  @.Cycle spec at line...@>
  8489  p:=cur_spec; octant:=left_octant(p); print_ln;
  8490  print_two_true(x_coord(cur_spec),y_coord(cur_spec));
  8491  print(" % beginning in octant `");
  8492  loop@+  begin print(octant_dir[octant]); print_char("'");
  8493    loop@+  begin q:=link(p);
  8494      if right_type(p)=endpoint then goto not_found;
  8495      @<Print the cubic between |p| and |q|@>;
  8496      p:=q;
  8497      end;
  8498  not_found: if q=cur_spec then goto done;
  8499    p:=q; octant:=left_octant(p); print_nl("% entering octant `");
  8500    end;
  8501  @.entering the nth octant@>
  8502  done: print_nl(" & cycle"); end_diagnostic(true);
  8503  end;
  8504  
  8505  @ Symbolic octant direction names are kept in the |octant_dir| array.
  8506  
  8507  @<Glob...@>=
  8508  @!octant_dir:array[first_octant..sixth_octant] of str_number;
  8509  
  8510  @ @<Set init...@>=
  8511  octant_dir[first_octant]:="ENE";
  8512  octant_dir[second_octant]:="NNE";
  8513  octant_dir[third_octant]:="NNW";
  8514  octant_dir[fourth_octant]:="WNW";
  8515  octant_dir[fifth_octant]:="WSW";
  8516  octant_dir[sixth_octant]:="SSW";
  8517  octant_dir[seventh_octant]:="SSE";
  8518  octant_dir[eighth_octant]:="ESE";
  8519  
  8520  @ @<Print the cubic between...@>=
  8521  begin print_nl("   ..controls ");
  8522  print_two_true(right_x(p),right_y(p));
  8523  print(" and ");
  8524  print_two_true(left_x(q),left_y(q));
  8525  print_nl(" ..");
  8526  print_two_true(x_coord(q),y_coord(q));
  8527  print(" % segment "); print_int(left_type(q)-1);
  8528  end
  8529  
  8530  @ A much more compact version of a spec is printed to help users identify
  8531  ``strange paths.''
  8532  
  8533  @p procedure print_strange(@!s:str_number);
  8534  var @!p:pointer; {for list traversal}
  8535  @!f:pointer; {starting point in the cycle}
  8536  @!q:pointer; {octant boundary to be printed}
  8537  @!t:integer; {segment number, plus 1}
  8538  begin if interaction=error_stop_mode then wake_up_terminal;
  8539  print_nl(">");
  8540  @.>\relax@>
  8541  @<Find the starting point, |f|@>;
  8542  @<Determine the octant boundary |q| that precedes |f|@>;
  8543  t:=0;
  8544  repeat if left_type(p)<>endpoint then
  8545    begin if left_type(p)<>t then
  8546      begin t:=left_type(p); print_char(" "); print_int(t-1);
  8547      end;
  8548    if q<>null then
  8549      begin @<Print the turns, if any, that start at |q|, and advance |q|@>;
  8550      print_char(" "); print(octant_dir[left_octant(q)]); q:=null;
  8551      end;
  8552    end
  8553  else if q=null then q:=p;
  8554  p:=link(p);
  8555  until p=f;
  8556  print_char(" "); print_int(left_type(p)-1);
  8557  if q<>null then @<Print the turns...@>;
  8558  print_err(s);
  8559  end;
  8560  
  8561  @ If the segment numbers on the cycle are $t_1$, $t_2$, \dots, $t_m$,
  8562  and if |m<=max_quarterword|,
  8563  we have $t_{k-1}\L t_k$ except for at most one value of~$k$. If there are
  8564  no exceptions, $f$ will point to $t_1$; otherwise it will point to the
  8565  exceptional~$t_k$.
  8566  
  8567  There is at least one segment number (i.e., we always have $m>0$), because
  8568  |print_strange| is never called upon to display an entirely ``dead'' cycle.
  8569  
  8570  @<Find the starting point, |f|@>=
  8571  p:=cur_spec; t:=max_quarterword+1;
  8572  repeat p:=link(p);
  8573  if left_type(p)<>endpoint then
  8574    begin if left_type(p)<t then f:=p;
  8575    t:=left_type(p);
  8576    end;
  8577  until p=cur_spec
  8578  
  8579  @ @<Determine the octant boundary...@>=
  8580  p:=cur_spec; q:=p;
  8581  repeat p:=link(p);
  8582  if left_type(p)=endpoint then q:=p;
  8583  until p=f
  8584  
  8585  @ When two octant boundaries are adjacent, the path is simply changing direction
  8586  without moving. Such octant directions are shown in parentheses.
  8587  
  8588  @<Print the turns...@>=
  8589  if left_type(link(q))=endpoint then
  8590    begin print(" ("); print(octant_dir[left_octant(q)]); q:=link(q);
  8591    while left_type(link(q))=endpoint do
  8592      begin print_char(" "); print(octant_dir[left_octant(q)]); q:=link(q);
  8593      end;
  8594    print_char(")");
  8595    end
  8596  
  8597  @ The |make_spec| routine is what subdivides paths into octants:
  8598  Given a pointer |cur_spec| to a cyclic path, |make_spec| mungs the path data
  8599  and returns a pointer to the corresponding cyclic spec.
  8600  All ``dead'' cubics (i.e., cubics that don't move at all from
  8601  their starting points) will have been removed from the result.
  8602  @!@^dead cubics@>
  8603  
  8604  The idea of |make_spec| is fairly simple: Each cubic is first
  8605  subdivided, if necessary, into pieces belonging to single octants;
  8606  then the octant boundaries are inserted. But some of the details of
  8607  this transformation are not quite obvious.
  8608  
  8609  If |autorounding>0|, the path will be adjusted so that critical tangent
  8610  directions occur at ``good'' points with respect to the pen called |cur_pen|.
  8611  
  8612  The resulting spec will have all |x| and |y| coordinates at most
  8613  $2^{28}-|half_unit|-1-|safety_margin|$ in absolute value.  The pointer
  8614  that is returned will start some octant, as required by |print_spec|.
  8615  
  8616  @p @t\4@>@<Declare subroutines needed by |make_spec|@>@;
  8617  function make_spec(@!h:pointer;
  8618    @!safety_margin:scaled;@!tracing:integer):pointer;
  8619    {converts a path to a cycle spec}
  8620  label continue,done;
  8621  var @!p,@!q,@!r,@!s:pointer; {for traversing the lists}
  8622  @!k:integer; {serial number of path segment, or octant code}
  8623  @!chopped:integer; {positive if data truncated,
  8624            negative if data dangerously large}
  8625  @<Other local variables for |make_spec|@>@;
  8626  begin cur_spec:=h;
  8627  if tracing>0 then
  8628    print_path(cur_spec,", before subdivision into octants",true);
  8629  max_allowed:=fraction_one-half_unit-1-safety_margin;
  8630  @<Truncate the values of all coordinates that exceed |max_allowed|, and stamp
  8631    segment numbers in each |left_type| field@>;
  8632  quadrant_subdivide; {subdivide each cubic into pieces belonging to quadrants}
  8633  if (internal[autorounding]>0)and(chopped=0) then xy_round;
  8634  octant_subdivide; {complete the subdivision}
  8635  if (internal[autorounding]>unity)and(chopped=0) then diag_round;
  8636  @<Remove dead cubics@>;
  8637  @<Insert octant boundaries and compute the turning number@>;
  8638  while left_type(cur_spec)<>endpoint do cur_spec:=link(cur_spec);
  8639  if tracing>0 then
  8640    if (internal[autorounding]<=0)or(chopped<>0) then
  8641      print_spec(", after subdivision")
  8642    else if internal[autorounding]>unity then
  8643      print_spec(", after subdivision and double autorounding")
  8644    else print_spec(", after subdivision and autorounding");
  8645  make_spec:=cur_spec;
  8646  end;
  8647  
  8648  @ The |make_spec| routine has an interesting side effect, namely to set
  8649  the global variable |turning_number| to the number of times the tangent
  8650  vector of the given cyclic path winds around the origin.
  8651  
  8652  Another global variable |cur_spec| points to the specification as it is
  8653  being made, since several subroutines must go to work on it.
  8654  
  8655  And there are two global variables that affect the rounding
  8656  decisions, as we'll see later; they are called |cur_pen| and |cur_path_type|.
  8657  The latter will be |double_path_code| if |make_spec| is being
  8658  applied to a double path.
  8659  
  8660  @d double_path_code=0 {command modifier for `\&{doublepath}'}
  8661  @d contour_code=1 {command modifier for `\&{contour}'}
  8662  @d also_code=2 {command modifier for `\&{also}'}
  8663  
  8664  @<Glob...@>=
  8665  @!cur_spec:pointer; {the principal output of |make_spec|}
  8666  @!turning_number:integer; {another output of |make_spec|}
  8667  @!cur_pen:pointer; {an implicit input of |make_spec|, used in autorounding}
  8668  @!cur_path_type:double_path_code..contour_code; {likewise}
  8669  @!max_allowed:scaled; {coordinates must be at most this big}
  8670  
  8671  @ First we do a simple preprocessing step. The segment numbers inserted
  8672  here will propagate to all descendants of cubics that are split into
  8673  subintervals. These numbers must be nonzero, but otherwise they are
  8674  present merely for diagnostic purposes. The cubic from |p| to~|q|
  8675  that represents ``time interval'' |(t-1)..t| usually has |left_type(q)=t|,
  8676  except when |t| is too large to be stored in a quarterword.
  8677  
  8678  @d procrustes(#)==@+if abs(#)>=dmax then
  8679    if abs(#)>max_allowed then
  8680      begin chopped:=1;
  8681      if #>0 then #:=max_allowed@+else #:=-max_allowed;
  8682      end
  8683    else if chopped=0 then chopped:=-1
  8684  
  8685  @<Truncate the values of all coordinates that exceed...@>=
  8686  p:=cur_spec; k:=1; chopped:=0; dmax:=half(max_allowed);
  8687  repeat procrustes(left_x(p)); procrustes(left_y(p));
  8688  procrustes(x_coord(p)); procrustes(y_coord(p));
  8689  procrustes(right_x(p)); procrustes(right_y(p));@/
  8690  p:=link(p); left_type(p):=k;
  8691  if k<max_quarterword then incr(k)@+else k:=1;
  8692  until p=cur_spec;
  8693  if chopped>0 then
  8694    begin print_err("Curve out of range");
  8695  @.Curve out of range@>
  8696    help4("At least one of the coordinates in the path I'm about to")@/
  8697      ("digitize was really huge (potentially bigger than 4095).")@/
  8698      ("So I've cut it back to the maximum size.")@/
  8699      ("The results will probably be pretty wild.");
  8700    put_get_error;
  8701    end
  8702  
  8703  @ We may need to get rid of constant ``dead'' cubics that clutter up
  8704  the data structure and interfere with autorounding.
  8705  
  8706  @<Declare subroutines needed by |make_spec|@>=
  8707  procedure remove_cubic(@!p:pointer); {removes the cubic following~|p|}
  8708  var @!q:pointer; {the node that disappears}
  8709  begin q:=link(p); right_type(p):=right_type(q); link(p):=link(q);@/
  8710  x_coord(p):=x_coord(q); y_coord(p):=y_coord(q);@/
  8711  right_x(p):=right_x(q); right_y(p):=right_y(q);@/
  8712  free_node(q,knot_node_size);
  8713  end;
  8714  
  8715  @ The subdivision process proceeds by first swapping $x\swap-x$, if
  8716  necessary, to ensure that $x'\G0$; then swapping $y\swap-y$, if necessary,
  8717  to ensure that $y'\G0$; and finally swapping $x\swap y$, if necessary,
  8718  to ensure that $x'\G y'$.
  8719  
  8720  Recall that the octant codes have been defined in such a way that, for
  8721  example, |third_octant=first_octant+negate_x+switch_x_and_y|. The program
  8722  uses the fact that |negate_x<negate_y<switch_x_and_y| to handle ``double
  8723  negation'': If |c| is an octant code that possibly involves |negate_x|
  8724  and/or |negate_y|, but not |switch_x_and_y|, then negating~|y| changes~|c|
  8725  either to |c+negate_y| or |c-negate_y|, depending on whether
  8726  |c<=negate_y| or |c>negate_y|. Octant codes are always greater than zero.
  8727  
  8728  The first step is to subdivide on |x| and |y| only, so that horizontal
  8729  and vertical autorounding can be done before we compare $x'$ to $y'$.
  8730  
  8731  @<Declare subroutines needed by |make_spec|@>=
  8732  @t\4@>@<Declare the procedure called |split_cubic|@>@;
  8733  procedure quadrant_subdivide;
  8734  label continue,exit;
  8735  var @!p,@!q,@!r,@!s,@!pp,@!qq:pointer; {for traversing the lists}
  8736  @!first_x,@!first_y:scaled; {unnegated coordinates of node |cur_spec|}
  8737  @!del1,@!del2,@!del3,@!del,@!dmax:scaled; {proportional to the control
  8738    points of a quadratic derived from a cubic}
  8739  @!t:fraction; {where a quadratic crosses zero}
  8740  @!dest_x,@!dest_y:scaled; {final values of |x| and |y| in the current cubic}
  8741  @!constant_x:boolean; {is |x| constant between |p| and |q|?}
  8742  begin p:=cur_spec; first_x:=x_coord(cur_spec); first_y:=y_coord(cur_spec);
  8743  repeat continue: q:=link(p);
  8744  @<Subdivide the cubic between |p| and |q| so that the results travel
  8745    toward the right halfplane@>;
  8746  @<Subdivide all cubics between |p| and |q| so that the results travel
  8747    toward the first quadrant; but |return| or |goto continue| if the
  8748    cubic from |p| to |q| was dead@>;
  8749  p:=q;
  8750  until p=cur_spec;
  8751  exit:end;
  8752  
  8753  @ All three subdivision processes are similar, so it's possible to
  8754  get the general idea by studying the first one (which is the simplest).
  8755  The calculation makes use of the fact that the derivatives of
  8756  Bernshte{\u\i}n polynomials satisfy
  8757  $B'(z_0,z_1,\ldots,z_n;t)=nB(z_1-z_0,\ldots,z_n-z_{n-1};t)$.
  8758  
  8759  When this routine begins, |right_type(p)| is |explicit|; we should
  8760  set |right_type(p):=first_octant|. However, no assignment is made,
  8761  because |explicit=first_octant|. The author apologizes for using
  8762  such trickery here; it is really hard to do redundant computations
  8763  just for the sake of purity.
  8764  
  8765  @<Subdivide the cubic between |p| and |q| so that the results travel
  8766    toward the right halfplane...@>=
  8767  if q=cur_spec then
  8768    begin dest_x:=first_x; dest_y:=first_y;
  8769    end
  8770  else  begin dest_x:=x_coord(q); dest_y:=y_coord(q);
  8771    end;
  8772  del1:=right_x(p)-x_coord(p); del2:=left_x(q)-right_x(p);
  8773  del3:=dest_x-left_x(q);
  8774  @<Scale up |del1|, |del2|, and |del3| for greater accuracy;
  8775    also set |del| to the first nonzero element of |(del1,del2,del3)|@>;
  8776  if del=0 then constant_x:=true
  8777  else  begin constant_x:=false;
  8778    if del<0 then @<Complement the |x| coordinates of the
  8779      cubic between |p| and~|q|@>;
  8780    t:=crossing_point(del1,del2,del3);
  8781    if t<fraction_one then
  8782      @<Subdivide the cubic with respect to $x'$, possibly twice@>;
  8783    end
  8784  
  8785  @ If |del1=del2=del3=0|, it's impossible to obey the title of this
  8786  section. We just set |del=0| in that case.
  8787  @^inner loop@>
  8788  
  8789  @<Scale up |del1|, |del2|, and |del3| for greater accuracy...@>=
  8790  if del1<>0 then del:=del1
  8791  else if del2<>0 then del:=del2
  8792  else del:=del3;
  8793  if del<>0 then
  8794    begin dmax:=abs(del1);
  8795    if abs(del2)>dmax then dmax:=abs(del2);
  8796    if abs(del3)>dmax then dmax:=abs(del3);
  8797    while dmax<fraction_half do
  8798      begin double(dmax); double(del1); double(del2); double(del3);
  8799      end;
  8800    end
  8801  
  8802  @ During the subdivision phases of |make_spec|, the |x_coord| and |y_coord|
  8803  fields of node~|q| are not transformed to agree with the octant
  8804  stated in |right_type(p)|; they remain consistent with |right_type(q)|.
  8805  But |left_x(q)| and |left_y(q)| are governed by |right_type(p)|.
  8806  
  8807  @<Complement the |x| coordinates...@>=
  8808  begin negate(x_coord(p)); negate(right_x(p));
  8809  negate(left_x(q));@/
  8810  negate(del1); negate(del2); negate(del3);@/
  8811  negate(dest_x);
  8812  right_type(p):=first_octant+negate_x;
  8813  end
  8814  
  8815  @ When a cubic is split at a |fraction| value |t|, we obtain two cubics
  8816  whose B\'ezier control points are obtained by a generalization of the
  8817  bisection process: The formula
  8818  `$z_k^{(j+1)}={1\over2}(z_k^{(j)}+z\k^{(j)})$' becomes
  8819  `$z_k^{(j+1)}=t[z_k^{(j)},z\k^{(j)}]$'.
  8820  
  8821  It is convenient to define a \.{WEB} macro |t_of_the_way| such that
  8822  |t_of_the_way(a)(b)| expands to |a-(a-b)*t|, i.e., to |t[a,b]|.
  8823  
  8824  If |0<=t<=1|, the quantity |t[a,b]| is always between |a| and~|b|, even in
  8825  the presence of rounding errors. Our subroutines
  8826  also obey the identity |t[a,b]+t[b,a]=a+b|.
  8827  
  8828  @d t_of_the_way_end(#)==#,t@=)@>
  8829  @d t_of_the_way(#)==#-take_fraction@=(@>#-t_of_the_way_end
  8830  
  8831  @<Declare the procedure called |split_cubic|@>=
  8832  procedure split_cubic(@!p:pointer;@!t:fraction;
  8833    @!xq,@!yq:scaled); {splits the cubic after |p|}
  8834  var @!v:scaled; {an intermediate value}
  8835  @!q,@!r:pointer; {for list manipulation}
  8836  begin q:=link(p); r:=get_node(knot_node_size); link(p):=r; link(r):=q;@/
  8837  left_type(r):=left_type(q); right_type(r):=right_type(p);@#
  8838  v:=t_of_the_way(right_x(p))(left_x(q));
  8839  right_x(p):=t_of_the_way(x_coord(p))(right_x(p));
  8840  left_x(q):=t_of_the_way(left_x(q))(xq);
  8841  left_x(r):=t_of_the_way(right_x(p))(v);
  8842  right_x(r):=t_of_the_way(v)(left_x(q));
  8843  x_coord(r):=t_of_the_way(left_x(r))(right_x(r));@#
  8844  v:=t_of_the_way(right_y(p))(left_y(q));
  8845  right_y(p):=t_of_the_way(y_coord(p))(right_y(p));
  8846  left_y(q):=t_of_the_way(left_y(q))(yq);
  8847  left_y(r):=t_of_the_way(right_y(p))(v);
  8848  right_y(r):=t_of_the_way(v)(left_y(q));
  8849  y_coord(r):=t_of_the_way(left_y(r))(right_y(r));
  8850  end;
  8851  
  8852  @ Since $x'(t)$ is a quadratic equation, it can cross through zero
  8853  at~most twice. When it does cross zero, we make doubly sure that the
  8854  derivative is really zero at the splitting point, in case rounding errors
  8855  have caused the split cubic to have an apparently nonzero derivative.
  8856  We also make sure that the split cubic is monotonic.
  8857  
  8858  @<Subdivide the cubic with respect to $x'$, possibly twice@>=
  8859  begin split_cubic(p,t,dest_x,dest_y); r:=link(p);
  8860  if right_type(r)>negate_x then right_type(r):=first_octant
  8861  else right_type(r):=first_octant+negate_x;
  8862  if x_coord(r)<x_coord(p) then x_coord(r):=x_coord(p);
  8863  left_x(r):=x_coord(r);
  8864  if right_x(p)>x_coord(r) then right_x(p):=x_coord(r);
  8865   {we always have |x_coord(p)<=right_x(p)|}
  8866  negate(x_coord(r)); right_x(r):=x_coord(r);
  8867  negate(left_x(q)); negate(dest_x);@/
  8868  del2:=t_of_the_way(del2)(del3);
  8869    {now |0,del2,del3| represent $x'$ on the remaining interval}
  8870  if del2>0 then del2:=0;
  8871  t:=crossing_point(0,-del2,-del3);
  8872  if t<fraction_one then @<Subdivide the cubic a second time
  8873    with respect to $x'$@>
  8874  else begin if x_coord(r)>dest_x then
  8875      begin x_coord(r):=dest_x; left_x(r):=-x_coord(r); right_x(r):=x_coord(r);
  8876      end;
  8877    if left_x(q)>dest_x then left_x(q):=dest_x
  8878    else if left_x(q)<x_coord(r) then left_x(q):=x_coord(r);
  8879    end;
  8880  end
  8881  
  8882  @ @<Subdivide the cubic a second time with respect to $x'$@>=
  8883  begin split_cubic(r,t,dest_x,dest_y); s:=link(r);
  8884  if x_coord(s)<dest_x then x_coord(s):=dest_x;
  8885  if x_coord(s)<x_coord(r) then x_coord(s):=x_coord(r);
  8886  right_type(s):=right_type(p);
  8887  left_x(s):=x_coord(s); {now |x_coord(r)=right_x(r)<=left_x(s)|}
  8888  if left_x(q)<dest_x then left_x(q):=-dest_x
  8889  else if left_x(q)>x_coord(s) then left_x(q):=-x_coord(s)
  8890  else negate(left_x(q));
  8891  negate(x_coord(s)); right_x(s):=x_coord(s);
  8892  end
  8893  
  8894  @ The process of subdivision with respect to $y'$ is like that with respect
  8895  to~$x'$, with the slight additional complication that two or three cubics
  8896  might now appear between |p| and~|q|.
  8897  
  8898  @<Subdivide all cubics between |p| and |q| so that the results travel
  8899    toward the first quadrant...@>=
  8900  pp:=p;
  8901  repeat qq:=link(pp);
  8902  abnegate(x_coord(qq),y_coord(qq),right_type(qq),right_type(pp));
  8903  dest_x:=cur_x; dest_y:=cur_y;@/
  8904  del1:=right_y(pp)-y_coord(pp); del2:=left_y(qq)-right_y(pp);
  8905  del3:=dest_y-left_y(qq);
  8906  @<Scale up |del1|, |del2|, and |del3| for greater accuracy;
  8907    also set |del| to the first nonzero element of |(del1,del2,del3)|@>;
  8908  if del<>0 then {they weren't all zero}
  8909    begin if del<0 then @<Complement the |y| coordinates of the
  8910      cubic between |pp| and~|qq|@>;
  8911    t:=crossing_point(del1,del2,del3);
  8912    if t<fraction_one then
  8913      @<Subdivide the cubic with respect to $y'$, possibly twice@>;
  8914    end
  8915  else @<Do any special actions needed when |y| is constant;
  8916    |return| or |goto continue| if a dead cubic from |p| to |q| is removed@>;
  8917  pp:=qq;
  8918  until pp=q;
  8919  if constant_x then @<Correct the octant code in segments with decreasing |y|@>
  8920  
  8921  @ @<Complement the |y| coordinates...@>=
  8922  begin negate(y_coord(pp)); negate(right_y(pp));
  8923  negate(left_y(qq));@/
  8924  negate(del1); negate(del2); negate(del3);@/
  8925  negate(dest_y);
  8926  right_type(pp):=right_type(pp)+negate_y;
  8927  end
  8928  
  8929  @ @<Subdivide the cubic with respect to $y'$, possibly twice@>=
  8930  begin split_cubic(pp,t,dest_x,dest_y); r:=link(pp);
  8931  if right_type(r)>negate_y then right_type(r):=right_type(r)-negate_y
  8932  else right_type(r):=right_type(r)+negate_y;
  8933  if y_coord(r)<y_coord(pp) then y_coord(r):=y_coord(pp);
  8934  left_y(r):=y_coord(r);
  8935  if right_y(pp)>y_coord(r) then right_y(pp):=y_coord(r);
  8936   {we always have |y_coord(pp)<=right_y(pp)|}
  8937  negate(y_coord(r)); right_y(r):=y_coord(r);
  8938  negate(left_y(qq)); negate(dest_y);@/
  8939  if x_coord(r)<x_coord(pp) then x_coord(r):=x_coord(pp)
  8940  else if x_coord(r)>dest_x then x_coord(r):=dest_x;
  8941  if left_x(r)>x_coord(r) then
  8942    begin left_x(r):=x_coord(r);
  8943    if right_x(pp)>x_coord(r) then right_x(pp):=x_coord(r);
  8944    end;
  8945  if right_x(r)<x_coord(r) then
  8946    begin right_x(r):=x_coord(r);
  8947    if left_x(qq)<x_coord(r) then left_x(qq):=x_coord(r);
  8948    end;
  8949  del2:=t_of_the_way(del2)(del3);
  8950    {now |0,del2,del3| represent $y'$ on the remaining interval}
  8951  if del2>0 then del2:=0;
  8952  t:=crossing_point(0,-del2,-del3);
  8953  if t<fraction_one then @<Subdivide the cubic a second time
  8954    with respect to $y'$@>
  8955  else begin if y_coord(r)>dest_y then
  8956      begin y_coord(r):=dest_y; left_y(r):=-y_coord(r); right_y(r):=y_coord(r);
  8957      end;
  8958    if left_y(qq)>dest_y then left_y(qq):=dest_y
  8959    else if left_y(qq)<y_coord(r) then left_y(qq):=y_coord(r);
  8960    end;
  8961  end
  8962  
  8963  @ @<Subdivide the cubic a second time with respect to $y'$@>=
  8964  begin split_cubic(r,t,dest_x,dest_y); s:=link(r);@/
  8965  if y_coord(s)<dest_y then y_coord(s):=dest_y;
  8966  if y_coord(s)<y_coord(r) then y_coord(s):=y_coord(r);
  8967  right_type(s):=right_type(pp);
  8968  left_y(s):=y_coord(s); {now |y_coord(r)=right_y(r)<=left_y(s)|}
  8969  if left_y(qq)<dest_y then left_y(qq):=-dest_y
  8970  else if left_y(qq)>y_coord(s) then left_y(qq):=-y_coord(s)
  8971  else negate(left_y(qq));
  8972  negate(y_coord(s)); right_y(s):=y_coord(s);
  8973  if x_coord(s)<x_coord(r) then x_coord(s):=x_coord(r)
  8974  else if x_coord(s)>dest_x then x_coord(s):=dest_x;
  8975  if left_x(s)>x_coord(s) then
  8976    begin left_x(s):=x_coord(s);
  8977    if right_x(r)>x_coord(s) then right_x(r):=x_coord(s);
  8978    end;
  8979  if right_x(s)<x_coord(s) then
  8980    begin right_x(s):=x_coord(s);
  8981    if left_x(qq)<x_coord(s) then left_x(qq):=x_coord(s);
  8982    end;
  8983  end
  8984  
  8985  @ If the cubic is constant in $y$ and increasing in $x$, we have classified
  8986  it as traveling in the first octant. If the cubic is constant
  8987  in~$y$ and decreasing in~$x$, it is desirable to classify it as traveling
  8988  in the fifth octant (not the fourth), because autorounding will be consistent
  8989  with respect to doublepaths only if the octant number changes by four when
  8990  the path is reversed. Therefore we negate the $y$~coordinates
  8991  when they are constant but the curve is decreasing in~$x$; this gives
  8992  the desired result except in pathological paths.
  8993  
  8994  If the cubic is ``dead,'' i.e., constant in both |x| and |y|, we remove
  8995  it unless it is the only cubic in the entire path. We |goto continue|
  8996  if it wasn't the final cubic, so that the test |p=cur_spec| does not
  8997  falsely imply that all cubics have been processed.
  8998  
  8999  @<Do any special actions needed when |y| is constant...@>=
  9000  if constant_x then {|p=pp|, |q=qq|, and the cubic is dead}
  9001    begin if q<>p then
  9002      begin remove_cubic(p); {remove the dead cycle and recycle node |q|}
  9003      if cur_spec<>q then goto continue
  9004      else  begin cur_spec:=p; return;
  9005        end; {the final cubic was dead and is gone}
  9006      end;
  9007    end
  9008  else if not odd(right_type(pp)) then {the $x$ coordinates were negated}
  9009    @<Complement the |y| coordinates...@>
  9010  
  9011  @ A similar correction to octant codes deserves to be made when |x| is
  9012  constant and |y| is decreasing.
  9013  
  9014  @<Correct the octant code in segments with decreasing |y|@>=
  9015  begin pp:=p;
  9016  repeat qq:=link(pp);
  9017  if right_type(pp)>negate_y then {the $y$ coordinates were negated}
  9018    begin right_type(pp):=right_type(pp)+negate_x;
  9019    negate(x_coord(pp)); negate(right_x(pp)); negate(left_x(qq));
  9020    end;
  9021  pp:=qq;
  9022  until pp=q;
  9023  end
  9024  
  9025  @ Finally, the process of subdividing to make $x'\G y'$ is like the other
  9026  two subdivisions, with a few new twists. We skew the coordinates at this time.
  9027  
  9028  @<Declare subroutines needed by |make_spec|@>=
  9029  procedure octant_subdivide;
  9030  var @!p,@!q,@!r,@!s:pointer; {for traversing the lists}
  9031  @!del1,@!del2,@!del3,@!del,@!dmax:scaled; {proportional to the control
  9032    points of a quadratic derived from a cubic}
  9033  @!t:fraction; {where a quadratic crosses zero}
  9034  @!dest_x,@!dest_y:scaled; {final values of |x| and |y| in the current cubic}
  9035  begin p:=cur_spec;
  9036  repeat q:=link(p);@/
  9037  x_coord(p):=x_coord(p)-y_coord(p);
  9038  right_x(p):=right_x(p)-right_y(p);
  9039  left_x(q):=left_x(q)-left_y(q);@/
  9040  @<Subdivide the cubic between |p| and |q| so that the results travel
  9041    toward the first octant@>;
  9042  p:=q;
  9043  until p=cur_spec;
  9044  end;
  9045  
  9046  @ @<Subdivide the cubic between |p| and |q| so that the results travel
  9047    toward the first octant@>=
  9048  @<Set up the variables |(del1,del2,del3)| to represent $x'-y'$@>;
  9049  @<Scale up |del1|, |del2|, and |del3| for greater accuracy;
  9050    also set |del| to the first nonzero element of |(del1,del2,del3)|@>;
  9051  if del<>0 then {they weren't all zero}
  9052    begin if del<0 then @<Swap the |x| and |y| coordinates of the
  9053      cubic between |p| and~|q|@>;
  9054    t:=crossing_point(del1,del2,del3);
  9055    if t<fraction_one then
  9056      @<Subdivide the cubic with respect to $x'-y'$, possibly twice@>;
  9057    end
  9058  
  9059  @ @<Set up the variables |(del1,del2,del3)| to represent $x'-y'$@>=
  9060  if q=cur_spec then
  9061    begin unskew(x_coord(q),y_coord(q),right_type(q));
  9062    skew(cur_x,cur_y,right_type(p)); dest_x:=cur_x; dest_y:=cur_y;
  9063    end
  9064  else  begin abnegate(x_coord(q),y_coord(q),right_type(q),right_type(p));
  9065    dest_x:=cur_x-cur_y; dest_y:=cur_y;
  9066    end;
  9067  del1:=right_x(p)-x_coord(p); del2:=left_x(q)-right_x(p);
  9068  del3:=dest_x-left_x(q)
  9069  
  9070  @ The swapping here doesn't simply interchange |x| and |y| values,
  9071  because the coordinates are skewed. It turns out that this is easier
  9072  than ordinary swapping, because it can be done in two assignment statements
  9073  rather than three.
  9074  
  9075  @ @<Swap the |x| and |y| coordinates...@>=
  9076  begin y_coord(p):=x_coord(p)+y_coord(p); negate(x_coord(p));@/
  9077  right_y(p):=right_x(p)+right_y(p); negate(right_x(p));@/
  9078  left_y(q):=left_x(q)+left_y(q); negate(left_x(q));@/
  9079  negate(del1); negate(del2); negate(del3);@/
  9080  dest_y:=dest_x+dest_y; negate(dest_x);@/
  9081  right_type(p):=right_type(p)+switch_x_and_y;
  9082  end
  9083  
  9084  @ A somewhat tedious case analysis is carried out here to make sure that
  9085  nasty rounding errors don't destroy our assumptions of monotonicity.
  9086  
  9087  @<Subdivide the cubic with respect to $x'-y'$, possibly twice@>=
  9088  begin split_cubic(p,t,dest_x,dest_y); r:=link(p);
  9089  if right_type(r)>switch_x_and_y then right_type(r):=right_type(r)-switch_x_and_y
  9090  else right_type(r):=right_type(r)+switch_x_and_y;
  9091  if y_coord(r)<y_coord(p) then y_coord(r):=y_coord(p)
  9092  else if y_coord(r)>dest_y then y_coord(r):=dest_y;
  9093  if x_coord(p)+y_coord(r)>dest_x+dest_y then
  9094    y_coord(r):=dest_x+dest_y-x_coord(p);
  9095  if left_y(r)>y_coord(r) then
  9096    begin left_y(r):=y_coord(r);
  9097    if right_y(p)>y_coord(r) then right_y(p):=y_coord(r);
  9098    end;
  9099  if right_y(r)<y_coord(r) then
  9100    begin right_y(r):=y_coord(r);
  9101    if left_y(q)<y_coord(r) then left_y(q):=y_coord(r);
  9102    end;
  9103  if x_coord(r)<x_coord(p) then x_coord(r):=x_coord(p)
  9104  else if x_coord(r)+y_coord(r)>dest_x+dest_y then
  9105    x_coord(r):=dest_x+dest_y-y_coord(r);
  9106  left_x(r):=x_coord(r);
  9107  if right_x(p)>x_coord(r) then right_x(p):=x_coord(r);
  9108   {we always have |x_coord(p)<=right_x(p)|}
  9109  y_coord(r):=y_coord(r)+x_coord(r); right_y(r):=right_y(r)+x_coord(r);@/
  9110  negate(x_coord(r)); right_x(r):=x_coord(r);@/
  9111  left_y(q):=left_y(q)+left_x(q); negate(left_x(q));@/
  9112  dest_y:=dest_y+dest_x; negate(dest_x);
  9113  if right_y(r)<y_coord(r) then
  9114    begin right_y(r):=y_coord(r);
  9115    if left_y(q)<y_coord(r) then left_y(q):=y_coord(r);
  9116    end;
  9117  del2:=t_of_the_way(del2)(del3);
  9118    {now |0,del2,del3| represent $x'-y'$ on the remaining interval}
  9119  if del2>0 then del2:=0;
  9120  t:=crossing_point(0,-del2,-del3);
  9121  if t<fraction_one then
  9122    @<Subdivide the cubic a second time with respect to $x'-y'$@>
  9123  else begin if x_coord(r)>dest_x then
  9124      begin x_coord(r):=dest_x; left_x(r):=-x_coord(r); right_x(r):=x_coord(r);
  9125      end;
  9126    if left_x(q)>dest_x then left_x(q):=dest_x
  9127    else if left_x(q)<x_coord(r) then left_x(q):=x_coord(r);
  9128    end;
  9129  end
  9130  
  9131  @ @<Subdivide the cubic a second time with respect to $x'-y'$@>=
  9132  begin split_cubic(r,t,dest_x,dest_y); s:=link(r);@/
  9133  if y_coord(s)<y_coord(r) then y_coord(s):=y_coord(r)
  9134  else if y_coord(s)>dest_y then y_coord(s):=dest_y;
  9135  if x_coord(r)+y_coord(s)>dest_x+dest_y then
  9136    y_coord(s):=dest_x+dest_y-x_coord(r);
  9137  if left_y(s)>y_coord(s) then
  9138    begin left_y(s):=y_coord(s);
  9139    if right_y(r)>y_coord(s) then right_y(r):=y_coord(s);
  9140    end;
  9141  if right_y(s)<y_coord(s) then
  9142    begin right_y(s):=y_coord(s);
  9143    if left_y(q)<y_coord(s) then left_y(q):=y_coord(s);
  9144    end;
  9145  if x_coord(s)+y_coord(s)>dest_x+dest_y then x_coord(s):=dest_x+dest_y-y_coord(s)
  9146  else begin if x_coord(s)<dest_x then x_coord(s):=dest_x;
  9147    if x_coord(s)<x_coord(r) then x_coord(s):=x_coord(r);
  9148    end;
  9149  right_type(s):=right_type(p);
  9150  left_x(s):=x_coord(s); {now |x_coord(r)=right_x(r)<=left_x(s)|}
  9151  if left_x(q)<dest_x then
  9152    begin left_y(q):=left_y(q)+dest_x; left_x(q):=-dest_x;@+end
  9153  else if left_x(q)>x_coord(s) then
  9154    begin left_y(q):=left_y(q)+x_coord(s); left_x(q):=-x_coord(s);@+end
  9155  else begin left_y(q):=left_y(q)+left_x(q); negate(left_x(q));@+end;
  9156  y_coord(s):=y_coord(s)+x_coord(s); right_y(s):=right_y(s)+x_coord(s);@/
  9157  negate(x_coord(s)); right_x(s):=x_coord(s);@/
  9158  if right_y(s)<y_coord(s) then
  9159    begin right_y(s):=y_coord(s);
  9160    if left_y(q)<y_coord(s) then left_y(q):=y_coord(s);
  9161    end;
  9162  end
  9163  
  9164  @ It's time now to consider ``autorounding,'' which tries to make horizontal,
  9165  vertical, and diagonal tangents occur at places that will produce appropriate
  9166  images after the curve is digitized.
  9167  
  9168  The first job is to fix things so that |x(t)| plus the horizontal pen offset
  9169  is an integer multiple of the
  9170  current ``granularity'' when the derivative $x'(t)$ crosses through zero.
  9171  The given cyclic path contains regions where $x'(t)\G0$ and regions
  9172  where $x'(t)\L0$. The |quadrant_subdivide| routine is called into action
  9173  before any of the path coordinates have been skewed, but some of them
  9174  may have been negated. In regions where $x'(t)\G0$ we have |right_type=
  9175  first_octant| or |right_type=eighth_octant|; in regions where $x'(t)\L0$,
  9176  we have |right_type=fifth_octant| or |right_type=fourth_octant|.
  9177  
  9178  Within any such region the transformed $x$ values increase monotonically
  9179  from, say, $x_0$ to~$x_1$. We want to modify things by applying a linear
  9180  transformation to all $x$ coordinates in the region, after which
  9181  the $x$ values will increase monotonically from round$(x_0)$ to round$(x_1)$.
  9182  
  9183  This rounding scheme sounds quite simple, and it usually is. But several
  9184  complications can arise that might make the task more difficult. In the
  9185  first place, autorounding is inappropriate at cusps where $x'$ jumps
  9186  discontinuously past zero without ever being zero. In the second place,
  9187  the current pen might be unsymmetric in such a way that $x$ coordinates
  9188  should round differently in different parts of the curve.
  9189  These considerations imply that round$(x_0)$ might be greater
  9190  than round$(x_1)$, even though $x_0\L x_1$; in such cases we do not want
  9191  to carry out the linear transformation. Furthermore, it's possible to have
  9192  round$(x_1)-\hbox{round} (x_0)$ positive but much greater than $x_1-x_0$;
  9193  then the transformation might distort the curve drastically, and again we
  9194  want to avoid it. Finally, the rounded points must be consistent between
  9195  adjacent regions, hence we can't transform one region without knowing
  9196  about its neighbors.
  9197  
  9198  To handle all these complications, we must first look at the whole
  9199  cycle and choose rounded $x$ values that are ``safe.'' The following
  9200  procedure does this: Given $m$~values $(b_0,b_1,\ldots,b_{m-1})$ before
  9201  rounding and $m$~corresponding values $(a_0,a_1,\ldots,a_{m-1})$ that would
  9202  be desirable after rounding, the |make_safe| routine sets $a$'s to $b$'s
  9203  if necessary so that $0\L(a\k-a_k)/(b\k-b_k)\L2$ afterwards. It is
  9204  symmetric under cyclic permutation, reversal, and/or negation of the inputs.
  9205  (Instead of |a|, |b|, and~|m|, the program uses the names |after|,
  9206  |before|, and |cur_rounding_ptr|.)
  9207  
  9208  @<Declare subroutines needed by |make_spec|@>=
  9209  procedure make_safe;
  9210  var @!k:0..max_wiggle; {runs through the list of inputs}
  9211  @!all_safe:boolean; {does everything look OK so far?}
  9212  @!next_a:scaled; {|after[k]| before it might have changed}
  9213  @!delta_a,@!delta_b:scaled; {|after[k+1]-after[k]| and |before[k+1]-before[k]|}
  9214  begin before[cur_rounding_ptr]:=before[0]; {wrap around}
  9215  node_to_round[cur_rounding_ptr]:=node_to_round[0];
  9216  repeat after[cur_rounding_ptr]:=after[0]; all_safe:=true; next_a:=after[0];
  9217  for k:=0 to cur_rounding_ptr-1 do
  9218    begin delta_b:=before[k+1]-before[k];
  9219    if delta_b>=0 then delta_a:=after[k+1]-next_a
  9220    else delta_a:=next_a-after[k+1];
  9221    next_a:=after[k+1];
  9222    if (delta_a<0)or(delta_a>abs(delta_b+delta_b)) then
  9223      begin all_safe:=false; after[k]:=before[k];
  9224      if k=cur_rounding_ptr-1 then after[0]:=before[0]
  9225      else after[k+1]:=before[k+1];
  9226      end;
  9227    end;
  9228  until all_safe;
  9229  end;
  9230  
  9231  @ The global arrays used by |make_safe| are accompanied by an array of
  9232  pointers into the current knot list.
  9233  
  9234  @<Glob...@>=
  9235  @!before,@!after:array[0..max_wiggle] of scaled; {data for |make_safe|}
  9236  @!node_to_round:array[0..max_wiggle] of pointer; {reference back to the path}
  9237  @!cur_rounding_ptr:0..max_wiggle; {how many are being used}
  9238  @!max_rounding_ptr:0..max_wiggle; {how many have been used}
  9239  
  9240  @ @<Set init...@>=
  9241  max_rounding_ptr:=0;
  9242  
  9243  @ New entries go into the tables via the |before_and_after| routine:
  9244  
  9245  @<Declare subroutines needed by |make_spec|@>=
  9246  procedure before_and_after(@!b,@!a:scaled;@!p:pointer);
  9247  begin if cur_rounding_ptr=max_rounding_ptr then
  9248    if max_rounding_ptr<max_wiggle then incr(max_rounding_ptr)
  9249    else overflow("rounding table size",max_wiggle);
  9250  @:METAFONT capacity exceeded rounding table size}{\quad rounding table size@>
  9251  after[cur_rounding_ptr]:=a; before[cur_rounding_ptr]:=b;
  9252  node_to_round[cur_rounding_ptr]:=p; incr(cur_rounding_ptr);
  9253  end;
  9254  
  9255  @ A global variable called |cur_gran| is used instead of |internal[
  9256  granularity]|, because we want to work with a number that's guaranteed to
  9257  be positive.
  9258  
  9259  @<Glob...@>=
  9260  @!cur_gran:scaled; {the current granularity (which normally is |unity|)}
  9261  
  9262  @ The |good_val| function computes a number |a| that's as close as
  9263  possible to~|b|, with the property that |a+o| is a multiple of
  9264  |cur_gran|.
  9265  
  9266  If we assume that |cur_gran| is even (since it will in fact be a multiple
  9267  of |unity| in all reasonable applications), we have the identity
  9268  |good_val(-b-1,-o)=-good_val(b,o)|.
  9269  
  9270  @<Declare subroutines needed by |make_spec|@>=
  9271  function good_val(@!b,@!o:scaled):scaled;
  9272  var @!a:scaled; {accumulator}
  9273  begin a:=b+o;
  9274  if a>=0 then a:=a-(a mod cur_gran)-o
  9275  else a:=a+((-(a+1)) mod cur_gran)-cur_gran+1-o;
  9276  if b-a<a+cur_gran-b then good_val:=a
  9277  else good_val:=a+cur_gran;
  9278  end;
  9279  
  9280  @ When we're rounding a doublepath, we might need to compromise between
  9281  two opposing tendencies, if the pen thickness is not a multiple of the
  9282  granularity. The following ``compromise'' adjustment, suggested by
  9283  John Hobby, finds the best way out of the dilemma. (Only the value
  9284  @^Hobby, John Douglas@>
  9285  modulo |cur_gran| is relevant in our applications, so the result turns
  9286  out to be essentially symmetric in |u| and~|v|.)
  9287  
  9288  @<Declare subroutines needed by |make_spec|@>=
  9289  function compromise(@!u,@!v:scaled):scaled;
  9290  begin compromise:=half(good_val(u+u,-u-v));
  9291  end;
  9292  
  9293  @ Here, then, is the procedure that rounds $x$ coordinates as described;
  9294  it does the same for $y$ coordinates too, independently.
  9295  
  9296  @<Declare subroutines needed by |make_spec|@>=
  9297  procedure xy_round;
  9298  var @!p,@!q:pointer; {list manipulation registers}
  9299  @!b,@!a:scaled; {before and after values}
  9300  @!pen_edge:scaled; {offset that governs rounding}
  9301  @!alpha:fraction; {coefficient of linear transformation}
  9302  begin cur_gran:=abs(internal[granularity]);
  9303  if cur_gran=0 then cur_gran:=unity;
  9304  p:=cur_spec; cur_rounding_ptr:=0;
  9305  repeat q:=link(p);
  9306  @<If node |q| is a transition point for |x| coordinates,
  9307    compute and save its before-and-after coordinates@>;
  9308  p:=q;
  9309  until p=cur_spec;
  9310  if cur_rounding_ptr>0 then @<Transform the |x| coordinates@>;
  9311  p:=cur_spec; cur_rounding_ptr:=0;
  9312  repeat q:=link(p);
  9313  @<If node |q| is a transition point for |y| coordinates,
  9314    compute and save its before-and-after coordinates@>;
  9315  p:=q;
  9316  until p=cur_spec;
  9317  if cur_rounding_ptr>0 then @<Transform the |y| coordinates@>;
  9318  end;
  9319  
  9320  @ When |x| has been negated, the |octant| codes are even. We allow
  9321  for an error of up to .01 pixel (i.e., 655 |scaled| units) in the
  9322  derivative calculations at transition nodes.
  9323  
  9324  @<If node |q| is a transition point for |x| coordinates...@>=
  9325  if odd(right_type(p))<>odd(right_type(q)) then
  9326    begin if odd(right_type(q)) then b:=x_coord(q)@+else b:=-x_coord(q);
  9327    if (abs(x_coord(q)-right_x(q))<655)or@|
  9328      (abs(x_coord(q)+left_x(q))<655) then
  9329      @<Compute before-and-after |x| values based on the current pen@>
  9330    else a:=b;
  9331    if abs(a)>max_allowed then
  9332      if a>0 then a:=max_allowed@+else a:=-max_allowed;
  9333    before_and_after(b,a,q);
  9334    end
  9335  
  9336  @ When we study the data representation for pens, we'll learn that the
  9337  |x|~coordinate of the current pen's west edge is
  9338  $$\hbox{|y_coord(link(cur_pen+seventh_octant))|},$$
  9339  and that there are similar ways to address other important offsets.
  9340  
  9341  @d north_edge(#)==y_coord(link(#+fourth_octant))
  9342  @d south_edge(#)==y_coord(link(#+first_octant))
  9343  @d east_edge(#)==y_coord(link(#+second_octant))
  9344  @d west_edge(#)==y_coord(link(#+seventh_octant))
  9345  
  9346  @<Compute before-and-after |x| values based on the current pen@>=
  9347  begin if cur_pen=null_pen then pen_edge:=0
  9348  else if cur_path_type=double_path_code then
  9349    pen_edge:=compromise(east_edge(cur_pen),west_edge(cur_pen))
  9350  else if odd(right_type(q)) then pen_edge:=west_edge(cur_pen)
  9351  else pen_edge:=east_edge(cur_pen);
  9352  a:=good_val(b,pen_edge);
  9353  end
  9354  
  9355  @  The monotone transformation computed here with fixed-point arithmetic is
  9356  guaranteed to take consecutive |before| values $(b,b')$ into consecutive
  9357  |after| values $(a,a')$, even in the presence of rounding errors,
  9358  as long as $\vert b-b'\vert<2^{28}$.
  9359  
  9360  @<Transform the |x| coordinates@>=
  9361  begin make_safe;
  9362  repeat decr(cur_rounding_ptr);
  9363  if (after[cur_rounding_ptr]<>before[cur_rounding_ptr])or@|
  9364   (after[cur_rounding_ptr+1]<>before[cur_rounding_ptr+1]) then
  9365    begin p:=node_to_round[cur_rounding_ptr];
  9366    if odd(right_type(p)) then
  9367      begin b:=before[cur_rounding_ptr]; a:=after[cur_rounding_ptr];
  9368      end
  9369    else  begin b:=-before[cur_rounding_ptr]; a:=-after[cur_rounding_ptr];
  9370      end;
  9371    if before[cur_rounding_ptr]=before[cur_rounding_ptr+1] then
  9372      alpha:=fraction_one
  9373    else alpha:=make_fraction(after[cur_rounding_ptr+1]-after[cur_rounding_ptr],@|
  9374      before[cur_rounding_ptr+1]-before[cur_rounding_ptr]);
  9375    repeat x_coord(p):=take_fraction(alpha,x_coord(p)-b)+a;
  9376    right_x(p):=take_fraction(alpha,right_x(p)-b)+a;
  9377    p:=link(p); left_x(p):=take_fraction(alpha,left_x(p)-b)+a;
  9378    until p=node_to_round[cur_rounding_ptr+1];
  9379    end;
  9380  until cur_rounding_ptr=0;
  9381  end
  9382  
  9383  @ When |y| has been negated, the |octant| codes are |>negate_y|. Otherwise
  9384  these routines are essentially identical to the routines for |x| coordinates
  9385  that we have just seen.
  9386  
  9387  @<If node |q| is a transition point for |y| coordinates...@>=
  9388  if (right_type(p)>negate_y)<>(right_type(q)>negate_y) then
  9389    begin if right_type(q)<=negate_y then b:=y_coord(q)@+else b:=-y_coord(q);
  9390    if (abs(y_coord(q)-right_y(q))<655)or@|
  9391      (abs(y_coord(q)+left_y(q))<655) then
  9392      @<Compute before-and-after |y| values based on the current pen@>
  9393    else a:=b;
  9394    if abs(a)>max_allowed then
  9395      if a>0 then a:=max_allowed@+else a:=-max_allowed;
  9396    before_and_after(b,a,q);
  9397    end
  9398  
  9399  @ @<Compute before-and-after |y| values based on the current pen@>=
  9400  begin if cur_pen=null_pen then pen_edge:=0
  9401  else if cur_path_type=double_path_code then
  9402    pen_edge:=compromise(north_edge(cur_pen),south_edge(cur_pen))
  9403  else if right_type(q)<=negate_y then pen_edge:=south_edge(cur_pen)
  9404  else pen_edge:=north_edge(cur_pen);
  9405  a:=good_val(b,pen_edge);
  9406  end
  9407  
  9408  @ @<Transform the |y| coordinates@>=
  9409  begin make_safe;
  9410  repeat decr(cur_rounding_ptr);
  9411  if (after[cur_rounding_ptr]<>before[cur_rounding_ptr])or@|
  9412   (after[cur_rounding_ptr+1]<>before[cur_rounding_ptr+1]) then
  9413    begin p:=node_to_round[cur_rounding_ptr];
  9414    if right_type(p)<=negate_y then
  9415      begin b:=before[cur_rounding_ptr]; a:=after[cur_rounding_ptr];
  9416      end
  9417    else  begin b:=-before[cur_rounding_ptr]; a:=-after[cur_rounding_ptr];
  9418      end;
  9419    if before[cur_rounding_ptr]=before[cur_rounding_ptr+1] then
  9420      alpha:=fraction_one
  9421    else alpha:=make_fraction(after[cur_rounding_ptr+1]-after[cur_rounding_ptr],@|
  9422      before[cur_rounding_ptr+1]-before[cur_rounding_ptr]);
  9423    repeat y_coord(p):=take_fraction(alpha,y_coord(p)-b)+a;
  9424    right_y(p):=take_fraction(alpha,right_y(p)-b)+a;
  9425    p:=link(p); left_y(p):=take_fraction(alpha,left_y(p)-b)+a;
  9426    until p=node_to_round[cur_rounding_ptr+1];
  9427    end;
  9428  until cur_rounding_ptr=0;
  9429  end
  9430  
  9431  @ Rounding at diagonal tangents takes place after the subdivision into
  9432  octants is complete, hence after the coordinates have been skewed.
  9433  The details are somewhat tricky, because we want to round to points
  9434  whose skewed coordinates are halfway between integer multiples of
  9435  the granularity. Furthermore, both coordinates change when they are
  9436  rounded; this means we need a generalization of the |make_safe| routine,
  9437  ensuring safety in both |x| and |y|.
  9438  
  9439  In spite of these extra complications, we can take comfort in the fact
  9440  that the basic structure of the routine is the same as before.
  9441  
  9442  @<Declare subroutines needed by |make_spec|@>=
  9443  procedure diag_round;
  9444  var @!p,@!q,@!pp:pointer; {list manipulation registers}
  9445  @!b,@!a,@!bb,@!aa,@!d,@!c,@!dd,@!cc:scaled; {before and after values}
  9446  @!pen_edge:scaled; {offset that governs rounding}
  9447  @!alpha,@!beta:fraction; {coefficients of linear transformation}
  9448  @!next_a:scaled; {|after[k]| before it might have changed}
  9449  @!all_safe:boolean; {does everything look OK so far?}
  9450  @!k:0..max_wiggle; {runs through before-and-after values}
  9451  @!first_x,@!first_y:scaled; {coordinates before rounding}
  9452  begin p:=cur_spec; cur_rounding_ptr:=0;
  9453  repeat q:=link(p);
  9454  @<If node |q| is a transition point between octants,
  9455    compute and save its before-and-after coordinates@>;
  9456  p:=q;
  9457  until p=cur_spec;
  9458  if cur_rounding_ptr>0 then @<Transform the skewed coordinates@>;
  9459  end;
  9460  
  9461  @ We negate the skewed |x| coordinates in the before-and-after table when
  9462  the octant code is greater than |switch_x_and_y|.
  9463  
  9464  @<If node |q| is a transition point between octants...@>=
  9465  if right_type(p)<>right_type(q) then
  9466    begin if right_type(q)>switch_x_and_y then b:=-x_coord(q)
  9467    else b:=x_coord(q);
  9468    if abs(right_type(q)-right_type(p))=switch_x_and_y then
  9469      if (abs(x_coord(q)-right_x(q))<655)or(abs(x_coord(q)+left_x(q))<655) then
  9470        @<Compute a good coordinate at a diagonal transition@>
  9471      else a:=b
  9472    else a:=b;
  9473    before_and_after(b,a,q);
  9474    end
  9475  
  9476  @ In octants whose code number is even, $x$~has been
  9477  negated; we want to round ambiguous cases downward instead of upward,
  9478  so that the rounding will be consistent with octants whose code
  9479  number is odd. This downward bias can be achieved by
  9480  subtracting~1 from the first argument of |good_val|.
  9481  
  9482  @d diag_offset(#)==x_coord(knil(link(cur_pen+#)))
  9483  
  9484  @<Compute a good coordinate at a diagonal transition@>=
  9485  begin if cur_pen=null_pen then pen_edge:=0
  9486  else if cur_path_type=double_path_code then @<Compute a compromise |pen_edge|@>
  9487  else if right_type(q)<=switch_x_and_y then pen_edge:=diag_offset(right_type(q))
  9488  else pen_edge:=-diag_offset(right_type(q));
  9489  if odd(right_type(q)) then a:=good_val(b,pen_edge+half(cur_gran))
  9490  else a:=good_val(b-1,pen_edge+half(cur_gran));
  9491  end
  9492  
  9493  @ (It seems a shame to compute these compromise offsets repeatedly. The
  9494  author would have stored them directly in the pen data structure, if the
  9495  granularity had been constant.)
  9496  
  9497  @<Compute a compromise...@>=
  9498  case right_type(q) of
  9499  first_octant,second_octant:pen_edge:=compromise(diag_offset(first_octant),@|
  9500      -diag_offset(fifth_octant));
  9501  fifth_octant,sixth_octant:pen_edge:=-compromise(diag_offset(first_octant),@|
  9502      -diag_offset(fifth_octant));
  9503  third_octant,fourth_octant:pen_edge:=compromise(diag_offset(fourth_octant),@|
  9504      -diag_offset(eighth_octant));
  9505  seventh_octant,eighth_octant:pen_edge:=-compromise(diag_offset(fourth_octant),@|
  9506      -diag_offset(eighth_octant));
  9507  end {there are no other cases}
  9508  
  9509  @ @<Transform the skewed coordinates@>=
  9510  begin p:=node_to_round[0]; first_x:=x_coord(p); first_y:=y_coord(p);
  9511  @<Make sure that all the diagonal roundings are safe@>;
  9512  for k:=0 to cur_rounding_ptr-1 do
  9513    begin a:=after[k]; b:=before[k];
  9514    aa:=after[k+1]; bb:=before[k+1];
  9515    if (a<>b)or(aa<>bb) then
  9516      begin p:=node_to_round[k]; pp:=node_to_round[k+1];
  9517      @<Determine the before-and-after values of both coordinates@>;
  9518      if b=bb then alpha:=fraction_one
  9519      else alpha:=make_fraction(aa-a,bb-b);
  9520      if d=dd then beta:=fraction_one
  9521      else beta:=make_fraction(cc-c,dd-d);
  9522      repeat x_coord(p):=take_fraction(alpha,x_coord(p)-b)+a;
  9523      y_coord(p):=take_fraction(beta,y_coord(p)-d)+c;
  9524      right_x(p):=take_fraction(alpha,right_x(p)-b)+a;
  9525      right_y(p):=take_fraction(beta,right_y(p)-d)+c;
  9526      p:=link(p); left_x(p):=take_fraction(alpha,left_x(p)-b)+a;
  9527      left_y(p):=take_fraction(beta,left_y(p)-d)+c;
  9528      until p=pp;
  9529      end;
  9530    end;
  9531  end
  9532  
  9533  @ In node |p|, the coordinates |(b,d)| will be rounded to |(a,c)|;
  9534  in node |pp|, the coordinates |(bb,dd)| will be rounded to |(aa,cc)|.
  9535  (We transform the values from node |pp| so that they agree with the
  9536  conventions of node |p|.)
  9537  
  9538  If |aa<>bb|, we know that |abs(right_type(p)-right_type(pp))=switch_x_and_y|.
  9539  
  9540  @<Determine the before-and-after values of both coordinates@>=
  9541  if aa=bb then
  9542    begin if pp=node_to_round[0] then
  9543      unskew(first_x,first_y,right_type(pp))
  9544    else unskew(x_coord(pp),y_coord(pp),right_type(pp));
  9545    skew(cur_x,cur_y,right_type(p));
  9546    bb:=cur_x; aa:=bb; dd:=cur_y; cc:=dd;
  9547    if right_type(p)>switch_x_and_y then
  9548      begin b:=-b; a:=-a;
  9549      end;
  9550    end
  9551  else  begin if right_type(p)>switch_x_and_y then
  9552      begin bb:=-bb; aa:=-aa; b:=-b; a:=-a;
  9553      end;
  9554    if pp=node_to_round[0] then dd:=first_y-bb@+else dd:=y_coord(pp)-bb;
  9555    if odd(aa-bb) then
  9556      if right_type(p)>switch_x_and_y then cc:=dd-half(aa-bb+1)
  9557      else cc:=dd-half(aa-bb-1)
  9558    else cc:=dd-half(aa-bb);
  9559    end;
  9560  d:=y_coord(p);
  9561  if odd(a-b) then
  9562    if right_type(p)>switch_x_and_y then c:=d-half(a-b-1)
  9563    else c:=d-half(a-b+1)
  9564  else c:=d-half(a-b)
  9565  
  9566  @ @<Make sure that all the diagonal roundings are safe@>=
  9567  before[cur_rounding_ptr]:=before[0]; {cf.~|make_safe|}
  9568  node_to_round[cur_rounding_ptr]:=node_to_round[0];
  9569  repeat after[cur_rounding_ptr]:=after[0]; all_safe:=true; next_a:=after[0];
  9570  for k:=0 to cur_rounding_ptr-1 do
  9571    begin a:=next_a; b:=before[k]; next_a:=after[k+1];
  9572    aa:=next_a; bb:=before[k+1];
  9573    if (a<>b)or(aa<>bb) then
  9574      begin p:=node_to_round[k]; pp:=node_to_round[k+1];
  9575      @<Determine the before-and-after values of both coordinates@>;
  9576      if (aa<a)or(cc<c)or(aa-a>2*(bb-b))or(cc-c>2*(dd-d)) then
  9577        begin all_safe:=false; after[k]:=before[k];
  9578        if k=cur_rounding_ptr-1 then after[0]:=before[0]
  9579        else after[k+1]:=before[k+1];
  9580        end;
  9581      end;
  9582    end;
  9583  until all_safe
  9584  
  9585  @ Here we get rid of ``dead'' cubics, i.e., polynomials that don't move at
  9586  all when |t|~changes, since the subdivision process might have introduced
  9587  such things.  If the cycle reduces to a single point, however, we are left
  9588  with a single dead cubic that will not be removed until later.
  9589  
  9590  @<Remove dead cubics@>=
  9591  p:=cur_spec;
  9592  repeat continue: q:=link(p);
  9593  if p<>q then
  9594    begin if x_coord(p)=right_x(p) then
  9595     if y_coord(p)=right_y(p) then
  9596      if x_coord(p)=left_x(q) then
  9597       if y_coord(p)=left_y(q) then
  9598      begin unskew(x_coord(q),y_coord(q),right_type(q));
  9599      skew(cur_x,cur_y,right_type(p));
  9600      if x_coord(p)=cur_x then if y_coord(p)=cur_y then
  9601        begin remove_cubic(p); {remove the cubic following |p|}
  9602        if q<>cur_spec then goto continue;
  9603        cur_spec:=p; q:=p;
  9604        end;
  9605      end;
  9606    end;
  9607  p:=q;
  9608  until p=cur_spec;
  9609  
  9610  @ Finally we come to the last steps of |make_spec|, when boundary nodes
  9611  are inserted between cubics that move in different octants. The main
  9612  complication remaining arises from consecutive cubics whose octants
  9613  are not adjacent; we should insert more than one octant boundary
  9614  at such sharp turns, so that the envelope-forming routine will work.
  9615  
  9616  For this purpose, conversion tables between numeric and Gray codes for
  9617  octants are desirable.
  9618  
  9619  @<Glob...@>=
  9620  @!octant_number:array[first_octant..sixth_octant] of 1..8;
  9621  @!octant_code:array[1..8] of first_octant..sixth_octant;
  9622  
  9623  @ @<Set init...@>=
  9624  octant_code[1]:=first_octant;
  9625  octant_code[2]:=second_octant;
  9626  octant_code[3]:=third_octant;
  9627  octant_code[4]:=fourth_octant;
  9628  octant_code[5]:=fifth_octant;
  9629  octant_code[6]:=sixth_octant;
  9630  octant_code[7]:=seventh_octant;
  9631  octant_code[8]:=eighth_octant;
  9632  for k:=1 to 8 do octant_number[octant_code[k]]:=k;
  9633  
  9634  @ The main loop for boundary insertion deals with three consecutive
  9635  nodes |p,q,r|.
  9636  
  9637  @<Insert octant boundaries and compute the turning number@>=
  9638  turning_number:=0;
  9639  p:=cur_spec; q:=link(p);
  9640  repeat r:=link(q);
  9641  if (right_type(p)<>right_type(q))or(q=r) then
  9642    @<Insert one or more octant boundary nodes just before~|q|@>;
  9643  p:=q; q:=r;
  9644  until p=cur_spec;
  9645  
  9646  @ The |new_boundary| subroutine comes in handy at this point. It inserts
  9647  a new boundary node just after a given node |p|, using a given octant code
  9648  to transform the new node's coordinates. The ``transition'' fields are
  9649  not computed here.
  9650  
  9651  @<Declare subroutines needed by |make_spec|@>=
  9652  procedure new_boundary(@!p:pointer;@!octant:small_number);
  9653  var @!q,@!r:pointer; {for list manipulation}
  9654  begin q:=link(p); {we assume that |right_type(q)<>endpoint|}
  9655  r:=get_node(knot_node_size); link(r):=q; link(p):=r;
  9656  left_type(r):=left_type(q); {but possibly |left_type(q)=endpoint|}
  9657  left_x(r):=left_x(q); left_y(r):=left_y(q);
  9658  right_type(r):=endpoint; left_type(q):=endpoint;
  9659  right_octant(r):=octant; left_octant(q):=right_type(q);
  9660  unskew(x_coord(q),y_coord(q),right_type(q));
  9661  skew(cur_x,cur_y,octant); x_coord(r):=cur_x; y_coord(r):=cur_y;
  9662  end;
  9663  
  9664  @ The case |q=r| occurs if and only if |p=q=r=cur_spec|, when we want to turn
  9665  $360^\circ$ in eight steps and then remove a solitary dead cubic.
  9666  The program below happens to work in that case, but the reader isn't
  9667  expected to understand why.
  9668  
  9669  @<Insert one or more octant boundary nodes just before~|q|@>=
  9670  begin new_boundary(p,right_type(p)); s:=link(p);
  9671  o1:=octant_number[right_type(p)]; o2:=octant_number[right_type(q)];
  9672  case o2-o1 of
  9673  1,-7,7,-1: goto done;
  9674  2,-6: clockwise:=false;
  9675  3,-5,4,-4,5,-3: @<Decide whether or not to go clockwise@>;
  9676  6,-2: clockwise:=true;
  9677  0:clockwise:=rev_turns;
  9678  end; {there are no other cases}
  9679  @<Insert additional boundary nodes, then |goto done|@>;
  9680  done: if q=r then
  9681    begin q:=link(q); r:=q; p:=s; link(s):=q; left_octant(q):=right_octant(q);
  9682    left_type(q):=endpoint; free_node(cur_spec,knot_node_size); cur_spec:=q;
  9683    end;
  9684  @<Fix up the transition fields and adjust the turning number@>;
  9685  end
  9686  
  9687  @ @<Other local variables for |make_spec|@>=
  9688  @!o1,@!o2:small_number; {octant numbers}
  9689  @!clockwise:boolean; {should we turn clockwise?}
  9690  @!dx1,@!dy1,@!dx2,@!dy2:integer; {directions of travel at a cusp}
  9691  @!dmax,@!del:integer; {temporary registers}
  9692  
  9693  @ A tricky question arises when a path jumps four octants. We want the
  9694  direction of turning to be counterclockwise if the curve has changed
  9695  direction by $180^\circ$, or by something so close to $180^\circ$ that
  9696  the difference is probably due to rounding errors; otherwise we want to
  9697  turn through an angle of less than $180^\circ$. This decision needs to
  9698  be made even when a curve seems to have jumped only three octants, since
  9699  a curve may approach direction $(-1,0)$ from the fourth octant, then
  9700  it might leave from direction $(+1,0)$ into the first.
  9701  
  9702  The following code solves the problem by analyzing the incoming
  9703  direction |(dx1,dy1)| and the outgoing direction |(dx2,dy2)|.
  9704  
  9705  @<Decide whether or not to go clockwise@>=
  9706  begin @<Compute the incoming and outgoing directions@>;
  9707  unskew(dx1,dy1,right_type(p)); del:=pyth_add(cur_x,cur_y);@/
  9708  dx1:=make_fraction(cur_x,del); dy1:=make_fraction(cur_y,del);
  9709    {$\cos\theta_1$ and $\sin\theta_1$}
  9710  unskew(dx2,dy2,right_type(q)); del:=pyth_add(cur_x,cur_y);@/
  9711  dx2:=make_fraction(cur_x,del); dy2:=make_fraction(cur_y,del);
  9712    {$\cos\theta_2$ and $\sin\theta_2$}
  9713  del:=take_fraction(dx1,dy2)-take_fraction(dx2,dy1); {$\sin(\theta_2-\theta_1)$}
  9714  if del>4684844 then clockwise:=false
  9715  else if del<-4684844 then clockwise:=true
  9716    {$2^{28}\cdot\sin 1^\circ\approx4684844.68$}
  9717  else clockwise:=rev_turns;
  9718  end
  9719  
  9720  @ Actually the turnarounds just computed will be clockwise,
  9721  not counterclockwise, if
  9722  the global variable |rev_turns| is |true|; it is usually |false|.
  9723  
  9724  @<Glob...@>=
  9725  @!rev_turns:boolean; {should we make U-turns in the English manner?}
  9726  
  9727  @ @<Set init...@>=
  9728  rev_turns:=false;
  9729  
  9730  @ @<Compute the incoming and outgoing directions@>=
  9731  dx1:=x_coord(s)-left_x(s); dy1:=y_coord(s)-left_y(s);
  9732  if dx1=0 then if dy1=0 then
  9733    begin dx1:=x_coord(s)-right_x(p); dy1:=y_coord(s)-right_y(p);
  9734    if dx1=0 then if dy1=0 then
  9735      begin dx1:=x_coord(s)-x_coord(p); dy1:=y_coord(s)-y_coord(p);
  9736      end;  {and they {\sl can't} both be zero}
  9737    end;
  9738  dmax:=abs(dx1);@+if abs(dy1)>dmax then dmax:=abs(dy1);
  9739  while dmax<fraction_one do
  9740    begin double(dmax); double(dx1); double(dy1);
  9741    end;
  9742  dx2:=right_x(q)-x_coord(q); dy2:=right_y(q)-y_coord(q);
  9743  if dx2=0 then if dy2=0 then
  9744    begin dx2:=left_x(r)-x_coord(q); dy2:=left_y(r)-y_coord(q);
  9745    if dx2=0 then if dy2=0 then
  9746      begin if right_type(r)=endpoint then
  9747        begin cur_x:=x_coord(r); cur_y:=y_coord(r);
  9748        end
  9749      else  begin unskew(x_coord(r),y_coord(r),right_type(r));
  9750        skew(cur_x,cur_y,right_type(q));
  9751        end;
  9752      dx2:=cur_x-x_coord(q); dy2:=cur_y-y_coord(q);
  9753      end;  {and they {\sl can't} both be zero}
  9754    end;
  9755  dmax:=abs(dx2);@+if abs(dy2)>dmax then dmax:=abs(dy2);
  9756  while dmax<fraction_one do
  9757    begin double(dmax); double(dx2); double(dy2);
  9758    end
  9759  
  9760  @ @<Insert additional boundary nodes...@>=
  9761  loop@+  begin if clockwise then
  9762      if o1=1 then o1:=8@+else decr(o1)
  9763    else if o1=8 then o1:=1@+else incr(o1);
  9764    if o1=o2 then goto done;
  9765    new_boundary(s,octant_code[o1]);
  9766    s:=link(s); left_octant(s):=right_octant(s);
  9767    end
  9768  
  9769  @ Now it remains to insert the redundant
  9770  transition information into the |left_transition|
  9771  and |right_transition| fields between adjacent octants, in the octant
  9772  boundary nodes that have just been inserted between |link(p)| and~|q|.
  9773  The turning number is easily computed from these transitions.
  9774  
  9775  @<Fix up the transition fields and adjust the turning number@>=
  9776  p:=link(p);
  9777  repeat s:=link(p);
  9778  o1:=octant_number[right_octant(p)]; o2:=octant_number[left_octant(s)];
  9779  if abs(o1-o2)=1 then
  9780    begin if o2<o1 then o2:=o1;
  9781    if odd(o2) then right_transition(p):=axis
  9782    else right_transition(p):=diagonal;
  9783    end
  9784  else  begin if o1=8 then incr(turning_number)@+else decr(turning_number);
  9785    right_transition(p):=axis;
  9786    end;
  9787  left_transition(s):=right_transition(p);
  9788  p:=s;
  9789  until p=q
  9790  
  9791  @* \[22] Filling a contour.
  9792  Given the low-level machinery for making moves and for transforming a
  9793  cyclic path into a cycle spec, we're almost able to fill a digitized path.
  9794  All we need is a high-level routine that walks through the cycle spec and
  9795  controls the overall process.
  9796  
  9797  Our overall goal is to plot the integer points $\bigl(\round(x(t)),
  9798  \round(y(t))\bigr)$ and to connect them by rook moves, assuming that
  9799  $\round(x(t))$ and $\round(y(t))$ don't both jump simultaneously from
  9800  one integer to another as $t$~varies; these rook moves will be the edge
  9801  of the contour that will be filled. We have reduced this problem to the
  9802  case of curves that travel in first octant directions, i.e., curves
  9803  such that $0\L y'(t)\L x'(t)$, by transforming the original coordinates.
  9804  
  9805  \def\xtilde{{\tilde x}} \def\ytilde{{\tilde y}}
  9806  Another transformation makes the problem still simpler. We shall say that
  9807  we are working with {\sl biased coordinates\/} when $(x,y)$ has been
  9808  replaced by $(\xtilde,\ytilde)=(x-y,y+{1\over2})$. When a curve travels
  9809  in first octant directions, the corresponding curve with biased
  9810  coordinates travels in first {\sl quadrant\/} directions; the latter
  9811  condition is symmetric in $x$ and~$y$, so it has advantages for the
  9812  design of algorithms. The |make_spec| routine gives us skewed coordinates
  9813  $(x-y,y)$, hence we obtain biased coordinates by simply adding $1\over2$
  9814  to the second component.
  9815  
  9816  The most important fact about biased coordinates is that we can determine the
  9817  rounded unbiased path $\bigl(\round(x(t)),\round(y(t))\bigr)$ from the
  9818  truncated biased path $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor
  9819  \bigr)$ and information about the initial and final endpoints. If the
  9820  unrounded and unbiased
  9821  path begins at $(x_0,y_0)$ and ends at $(x_1,y_1)$, it's possible to
  9822  prove (by induction on the length of the truncated biased path) that the
  9823  rounded unbiased path is obtained by the following construction:
  9824  
  9825  \yskip\textindent{1)} Start at $\bigl(\round(x_0),\round(y_0)\bigr)$.
  9826  
  9827  \yskip\textindent{2)} If $(x_0+{1\over2})\bmod1\G(y_0+{1\over2})\bmod1$,
  9828  move one step right.
  9829  
  9830  \yskip\textindent{3)} Whenever the path
  9831  $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor\bigr)$
  9832  takes an upward step (i.e., when
  9833  $\lfloor\xtilde(t+\epsilon)\rfloor=\lfloor\xtilde(t)\rfloor$ and
  9834  $\lfloor\ytilde(t+\epsilon)\rfloor=\lfloor\ytilde(t)\rfloor+1$),
  9835  move one step up and then one step right.
  9836  
  9837  \yskip\textindent{4)} Whenever the path
  9838  $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor\bigr)$
  9839  takes a rightward step (i.e., when
  9840  $\lfloor\xtilde(t+\epsilon)\rfloor=\lfloor\xtilde(t)\rfloor+1$ and
  9841  $\lfloor\ytilde(t+\epsilon)\rfloor=\lfloor\ytilde(t)\rfloor$),
  9842  move one step right.
  9843  
  9844  \yskip\textindent{5)} Finally, if
  9845  $(x_1+{1\over2})\bmod1\G(y_1+{1\over2})\bmod1$, move one step left (thereby
  9846  cancelling the previous move, which was one step right). You will now be
  9847  at the point $\bigl(\round(x_1),\round(y_1)\bigr)$.
  9848  
  9849  @ In order to validate the assumption that $\round(x(t))$ and $\round(y(t))$
  9850  don't both jump simultaneously, we shall consider that a coordinate pair
  9851  $(x,y)$ actually represents $(x+\epsilon,y+\epsilon\delta)$, where
  9852  $\epsilon$ and $\delta$ are extremely small positive numbers---so small
  9853  that their precise values never matter.  This convention makes rounding
  9854  unambiguous, since there is always a unique integer point nearest to any
  9855  given scaled numbers~$(x,y)$.
  9856  
  9857  When coordinates are transformed so that \MF\ needs to work only in ``first
  9858  octant'' directions, the transformations involve negating~$x$, negating~$y$,
  9859  and/or interchanging $x$ with~$y$. Corresponding adjustments to the
  9860  rounding conventions must be made so that consistent values will be
  9861  obtained. For example, suppose that we're working with coordinates that
  9862  have been transformed so that a third-octant curve travels in first-octant
  9863  directions. The skewed coordinates $(x,y)$ in our data structure represent
  9864  unskewed coordinates $(-y,x+y)$, which are actually $(-y+\epsilon,
  9865  x+y+\epsilon\delta)$. We should therefore round as if our skewed coordinates
  9866  were $(x+\epsilon+\epsilon\delta,y-\epsilon)$ instead of $(x,y)$. The following
  9867  table shows how the skewed coordinates should be perturbed when rounding
  9868  decisions are made:
  9869  $$\vcenter{\halign{#\hfil&&\quad$#$\hfil&\hskip4em#\hfil\cr
  9870  |first_octant|&(x+\epsilon-\epsilon\delta,y+\epsilon\delta)&
  9871   |fifth_octant|&(x-\epsilon+\epsilon\delta,y-\epsilon\delta)\cr
  9872  |second_octant|&(x-\epsilon+\epsilon\delta,y+\epsilon)&
  9873   |sixth_octant|&(x+\epsilon-\epsilon\delta,y-\epsilon)\cr
  9874  |third_octant|&(x+\epsilon+\epsilon\delta,y-\epsilon)&
  9875   |seventh_octant|&(x-\epsilon-\epsilon\delta,y+\epsilon)\cr
  9876  |fourth_octant|&(x-\epsilon-\epsilon\delta,y+\epsilon\delta)&
  9877   |eighth_octant|&(x+\epsilon+\epsilon\delta,y-\epsilon\delta)\cr}}$$
  9878  
  9879  Four small arrays are set up so that the rounding operations will be
  9880  fairly easy in any given octant.
  9881  
  9882  @<Glob...@>=
  9883  @!y_corr,@!xy_corr,@!z_corr:array[first_octant..sixth_octant] of 0..1;
  9884  @!x_corr:array[first_octant..sixth_octant] of -1..1;
  9885  
  9886  @ Here |xy_corr| is 1 if and only if the $x$ component of a skewed coordinate
  9887  is to be decreased by an infinitesimal amount; |y_corr| is similar, but for
  9888  the $y$ components. The other tables are set up so that the condition
  9889  $$(x+y+|half_unit|)\bmod|unity|\G(y+|half_unit|)\bmod|unity|$$
  9890  is properly perturbed to the condition
  9891  $$(x+y+|half_unit|-|x_corr|-|y_corr|)\bmod|unity|\G
  9892    (y+|half_unit|-|y_corr|)\bmod|unity|+|z_corr|.$$
  9893  
  9894  @<Set init...@>=
  9895  x_corr[first_octant]:=0; y_corr[first_octant]:=0;
  9896  xy_corr[first_octant]:=0;@/
  9897  x_corr[second_octant]:=0; y_corr[second_octant]:=0;
  9898  xy_corr[second_octant]:=1;@/
  9899  x_corr[third_octant]:=-1; y_corr[third_octant]:=1;
  9900  xy_corr[third_octant]:=0;@/
  9901  x_corr[fourth_octant]:=1; y_corr[fourth_octant]:=0;
  9902  xy_corr[fourth_octant]:=1;@/
  9903  x_corr[fifth_octant]:=0; y_corr[fifth_octant]:=1;
  9904  xy_corr[fifth_octant]:=1;@/
  9905  x_corr[sixth_octant]:=0; y_corr[sixth_octant]:=1;
  9906  xy_corr[sixth_octant]:=0;@/
  9907  x_corr[seventh_octant]:=1; y_corr[seventh_octant]:=0;
  9908  xy_corr[seventh_octant]:=1;@/
  9909  x_corr[eighth_octant]:=-1; y_corr[eighth_octant]:=1;
  9910  xy_corr[eighth_octant]:=0;@/
  9911  for k:=1 to 8 do z_corr[k]:=xy_corr[k]-x_corr[k];
  9912  
  9913  @ Here's a procedure that handles the details of rounding at the
  9914  endpoints: Given skewed coordinates |(x,y)|, it sets |(m1,n1)|
  9915  to the corresponding rounded lattice points, taking the current
  9916  |octant| into account. Global variable |d1| is also set to 1 if
  9917  $(x+y+{1\over2})\bmod1\G(y+{1\over2})\bmod1$.
  9918  
  9919  @p procedure end_round(@!x,@!y:scaled);
  9920  begin y:=y+half_unit-y_corr[octant];
  9921  x:=x+y-x_corr[octant];
  9922  m1:=floor_unscaled(x); n1:=floor_unscaled(y);
  9923  if x-unity*m1>=y-unity*n1+z_corr[octant] then d1:=1@+else d1:=0;
  9924  end;
  9925  
  9926  @ The outputs |(m1,n1,d1)| of |end_round| will sometimes be moved
  9927  to |(m0,n0,d0)|.
  9928  
  9929  @<Glob...@>=
  9930  @!m0,@!n0,@!m1,@!n1:integer; {lattice point coordinates}
  9931  @!d0,@!d1:0..1; {displacement corrections}
  9932  
  9933  @ We're ready now to fill the pixels enclosed by a given cycle spec~|h|;
  9934  the knot list that represents the cycle is destroyed in the process.
  9935  The edge structure that gets all the resulting data is |cur_edges|,
  9936  and the edges are weighted by |cur_wt|.
  9937  
  9938  @p procedure fill_spec(@!h:pointer);
  9939  var @!p,@!q,@!r,@!s:pointer; {for list traversal}
  9940  begin if internal[tracing_edges]>0 then begin_edge_tracing;
  9941  p:=h; {we assume that |left_type(h)=endpoint|}
  9942  repeat octant:=left_octant(p);
  9943  @<Set variable |q| to the node at the end of the current octant@>;
  9944  if q<>p then
  9945    begin @<Determine the starting and ending
  9946      lattice points |(m0,n0)| and |(m1,n1)|@>;
  9947    @<Make the moves for the current octant@>;
  9948    move_to_edges(m0,n0,m1,n1);
  9949    end;
  9950  p:=link(q);
  9951  until p=h;
  9952  toss_knot_list(h);
  9953  if internal[tracing_edges]>0 then end_edge_tracing;
  9954  end;
  9955  
  9956  @ @<Set variable |q| to the node at the end of the current octant@>=
  9957  q:=p;
  9958  while right_type(q)<>endpoint do q:=link(q)
  9959  
  9960  @ @<Determine the starting and ending lattice points |(m0,n0)| and |(m1,n1)|@>=
  9961  end_round(x_coord(p),y_coord(p)); m0:=m1; n0:=n1; d0:=d1;@/
  9962  end_round(x_coord(q),y_coord(q))
  9963  
  9964  @ Finally we perform the five-step process that was explained at
  9965  the very beginning of this part of the program.
  9966  
  9967  @<Make the moves for the current octant@>=
  9968  if n1-n0>=move_size then overflow("move table size",move_size);
  9969  @:METAFONT capacity exceeded move table size}{\quad move table size@>
  9970  move[0]:=d0; move_ptr:=0; r:=p;
  9971  repeat s:=link(r);@/
  9972  make_moves(x_coord(r),right_x(r),left_x(s),x_coord(s),@|
  9973    y_coord(r)+half_unit,right_y(r)+half_unit,left_y(s)+half_unit,
  9974    y_coord(s)+half_unit,@| xy_corr[octant],y_corr[octant]);
  9975  r:=s;
  9976  until r=q;
  9977  move[move_ptr]:=move[move_ptr]-d1;
  9978  if internal[smoothing]>0 then smooth_moves(0,move_ptr)
  9979  
  9980  @* \[23] Polygonal pens.
  9981  The next few parts of the program deal with the additional complications
  9982  associated with ``envelopes,'' leading up to an algorithm that fills a
  9983  contour with respect to a pen whose boundary is a convex polygon. The
  9984  mathematics underlying this algorithm is based on simple aspects of the
  9985  theory of tracings developed by Leo Guibas, Lyle Ramshaw, and Jorge
  9986  Stolfi [``A kinetic framework for computational geometry,''
  9987  {\sl Proc.\ IEEE Symp.\ Foundations of Computer Science\/ \bf24} (1983),
  9988  100--111].
  9989  @^Guibas, Leonidas Ioannis@>
  9990  @^Ramshaw, Lyle Harold@>
  9991  @^Stolfi, Jorge@>
  9992  
  9993  If the vertices of the polygon are $w_0$, $w_1$, \dots, $w_{n-1}$, $w_n=w_0$,
  9994  in counterclockwise order, the convexity condition requires that ``left
  9995  turns'' are made at each vertex when a person proceeds from $w_0$ to
  9996  $w_1$ to $\cdots$ to~$w_n$. The envelope is obtained if we offset a given
  9997  curve $z(t)$ by $w_k$ when that curve is traveling in a direction
  9998  $z'(t)$ lying between the directions $w_k-w_{k-1}$ and $w\k-w_k$.
  9999  At times~$t$ when the curve direction $z'(t)$ increases past
 10000  $w\k-w_k$, we temporarily stop plotting the offset curve and we insert
 10001  a straight line from $z(t)+w_k$ to $z(t)+w\k$; notice that this straight
 10002  line is tangent to the offset curve. Similarly, when the curve direction
 10003  decreases past $w_k-w_{k-1}$, we stop plotting and insert a straight
 10004  line from $z(t)+w_k$ to $z(t)+w_{k-1}$; the latter line is actually a
 10005  ``retrograde'' step, which won't be part of the final envelope under
 10006  \MF's assumptions. The result of this construction is a continuous path
 10007  that consists of alternating curves and straight line segments. The
 10008  segments are usually so short, in practice, that they blend with the
 10009  curves; after all, it's possible to represent any digitized path as
 10010  a sequence of digitized straight lines.
 10011  
 10012  The nicest feature of this approach to envelopes is that it blends
 10013  perfectly with the octant subdivision process we have already developed.
 10014  The envelope travels in the same direction as the curve itself, as we
 10015  plot it, and we need merely be careful what offset is being added.
 10016  Retrograde motion presents a problem, but we will see that there is
 10017  a decent way to handle it.
 10018  
 10019  @ We shall represent pens by maintaining eight lists of offsets,
 10020  one for each octant direction. The offsets at the boundary points
 10021  where a curve turns into a new octant will appear in the lists for
 10022  both octants. This means that we can restrict consideration to
 10023  segments of the original polygon whose directions aim in the first
 10024  octant, as we have done in the simpler case when envelopes were not
 10025  required.
 10026  
 10027  An example should help to clarify this situation: Consider the
 10028  quadrilateral whose vertices are $w_0=(0,-1)$, $w_1=(3,-1)$,
 10029  $w_2=(6,1)$, and $w_3=(1,2)$. A curve that travels in the first octant
 10030  will be offset by $w_1$ or $w_2$, unless its slope drops to zero
 10031  en route to the eighth octant; in the latter case we should switch to $w_0$ as
 10032  we cross the octant boundary. Our list for the first octant will
 10033  contain the three offsets $w_0$, $w_1$,~$w_2$. By convention we will
 10034  duplicate a boundary offset if the angle between octants doesn't
 10035  explicitly appear; in this case there is no explicit line of slope~1
 10036  at the end of the list, so the full list is
 10037  $$w_0\;w_1\;w_2\;w_2\;=\;(0,-1)\;(3,-1)\;(6,1)\;(6,1).$$
 10038  With skewed coordinates $(u-v,v)$ instead of $(u,v)$ we obtain the list
 10039  $$w_0\;w_1\;w_2\;w_2\;\mapsto\;(1,-1)\;(4,-1)\;(5,1)\;(5,1),$$
 10040  which is what actually appears in the data structure. In the second
 10041  octant there's only one offset; we list it twice (with coordinates
 10042  interchanged, so as to make the second octant look like the first),
 10043  and skew those coordinates, obtaining
 10044  $$\tabskip\centering
 10045  \halign to\hsize{$\hfil#\;\mapsto\;{}$\tabskip=0pt&
 10046    $#\hfil$&\quad in the #\hfil\tabskip\centering\cr
 10047  w_2\;w_2&(-5,6)\;(-5,6)\cr
 10048  \noalign{\vskip\belowdisplayskip
 10049  \vbox{\noindent\strut as the list of transformed and skewed offsets to use
 10050  when curves travel in the second octant. Similarly, we will have\strut}
 10051  \vskip\abovedisplayskip}
 10052  w_2\;w_2&(7,-6)\;(7,-6)&third;\cr
 10053  w_2\;w_2\;w_3\;w_3&(-7,1)\;(-7,1)\;(-3,2)\;(-3,2)&fourth;\cr
 10054  w_3\;w_3&(1,-2)\;(1,-2)&fifth;\cr
 10055  w_3\;w_3\;w_0\;w_0&(-1,1)\;(-1,1)\;(1,0)\;(1,0)&sixth;\cr
 10056  w_0\;w_0&(1,0)\;(1,0)&seventh;\cr
 10057  w_0\;w_0&(-1,1)\;(-1,1)&eighth.\cr}$$
 10058  Notice that $w_1$ is considered here to be internal to the first octant;
 10059  it's not part of the eighth. We could equally well have taken $w_0$ out
 10060  of the first octant list and put it into the eighth; then the first octant
 10061  list would have been
 10062  $$w_1\;w_1\;w_2\;w_2\;\mapsto\;(4,-1)\;(4,-1)\;(5,1)\;(5,1)$$
 10063  and the eighth octant list would have been
 10064  $$w_0\;w_0\;w_1\;\mapsto\;(-1,1)\;(-1,1)\;(2,1).$$
 10065  
 10066  Actually, there's one more complication: The order of offsets is reversed
 10067  in even-numbered octants, because the transformation of coordinates has
 10068  reversed counterclockwise and clockwise orientations in those octants.
 10069  The offsets in the fourth octant, for example, are really $w_3$, $w_3$,
 10070  $w_2$,~$w_2$, not $w_2$, $w_2$, $w_3$,~$w_3$.
 10071  
 10072  @ In general, the list of offsets for an octant will have the form
 10073  $$w_0\;\;w_1\;\;\ldots\;\;w_n\;\;w_{n+1}$$
 10074  (if we renumber the subscripts in each list), where $w_0$ and $w_{n+1}$
 10075  are offsets common to the neighboring lists. We'll often have $w_0=w_1$
 10076  and/or $w_n=w_{n+1}$, but the other $w$'s will be distinct. Curves
 10077  that travel between slope~0 and direction $w_2-w_1$ will use offset~$w_1$;
 10078  curves that travel between directions $w_k-w_{k-1}$ and $w\k-w_k$ will
 10079  use offset~$w_k$, for $1<k<n$; curves between direction $w_n-w_{n-1}$
 10080  and slope~1 (actually slope~$\infty$ after skewing) will use offset~$w_n$.
 10081  In even-numbered octants, the directions are actually $w_k-w\k$ instead
 10082  of $w\k-w_k$, because the offsets have been listed in reverse order.
 10083  
 10084  Each offset $w_k$ is represented by skewed coordinates $(u_k-v_k,v_k)$,
 10085  where $(u_k,v_k)$ is the representation of $w_k$ after it has been rotated
 10086  into a first-octant disguise.
 10087  
 10088  @ The top-level data structure of a pen polygon is a 10-word node containing
 10089  a reference count followed by pointers to the eight offset lists, followed
 10090  by an indication of the pen's range of values.
 10091  @^reference counts@>
 10092  
 10093  If |p|~points to such a node, and if the
 10094  offset list for, say, the fourth octant has entries $w_0$, $w_1$, \dots,
 10095  $w_n$,~$w_{n+1}$, then |info(p+fourth_octant)| will equal~$n$, and
 10096  |link(p+fourth_octant)| will point to the offset node containing~$w_0$.
 10097  Memory location |p+fourth_octant| is said to be the {\sl header\/} of
 10098  the pen-offset list for the fourth octant. Since this is an even-numbered
 10099  octant, $w_0$ is the offset that goes with the fifth octant, and
 10100  $w_{n+1}$ goes with the third.
 10101  
 10102  The elements of the offset list themselves are doubly linked 3-word nodes,
 10103  containing coordinates in their |x_coord| and |y_coord| fields.
 10104  The two link fields are called |link| and |knil|; if |w|~points to
 10105  the node for~$w_k$, then |link(w)| and |knil(w)| point respectively
 10106  to the nodes for $w\k$ and~$w_{k-1}$. If |h| is the list header,
 10107  |link(h)| points to the node for~$w_0$ and |knil(link(h))| to the
 10108  node for~$w_{n+1}$.
 10109  
 10110  The tenth word of a pen header node contains the maximum absolute value of
 10111  an $x$ or $y$ coordinate among all of the unskewed pen offsets.
 10112  
 10113  The |link| field of a pen header node should be |null| if and only if
 10114  the pen is a single point.
 10115  
 10116  @d pen_node_size=10
 10117  @d coord_node_size=3
 10118  @d max_offset(#)==mem[#+9].sc
 10119  
 10120  @ The |print_pen| subroutine illustrates these conventions by
 10121  reconstructing the vertices of a polygon from \MF's complicated
 10122  internal offset representation.
 10123  
 10124  @<Declare subroutines for printing expressions@>=
 10125  procedure print_pen(@!p:pointer;@!s:str_number;@!nuline:boolean);
 10126  var @!nothing_printed:boolean; {has there been any action yet?}
 10127  @!k:1..8; {octant number}
 10128  @!h:pointer; {offset list head}
 10129  @!m,@!n:integer; {offset indices}
 10130  @!w,@!ww:pointer; {pointers that traverse the offset list}
 10131  begin print_diagnostic("Pen polygon",s,nuline);
 10132  nothing_printed:=true; print_ln;
 10133  for k:=1 to 8 do
 10134    begin octant:=octant_code[k]; h:=p+octant; n:=info(h); w:=link(h);
 10135    if not odd(k) then w:=knil(w); {in even octants, start at $w_{n+1}$}
 10136    for m:=1 to n+1 do
 10137      begin if odd(k) then ww:=link(w)@+else ww:=knil(w);
 10138      if (x_coord(ww)<>x_coord(w))or(y_coord(ww)<>y_coord(w)) then
 10139        @<Print the unskewed and unrotated coordinates of node |ww|@>;
 10140      w:=ww;
 10141      end;
 10142    end;
 10143  if nothing_printed then
 10144    begin w:=link(p+first_octant); print_two(x_coord(w)+y_coord(w),y_coord(w));
 10145    end;
 10146  print_nl(" .. cycle"); end_diagnostic(true);
 10147  end;
 10148  
 10149  @ @<Print the unskewed and unrotated coordinates of node |ww|@>=
 10150  begin if nothing_printed then nothing_printed:=false
 10151  else print_nl(" .. ");
 10152  print_two_true(x_coord(ww),y_coord(ww));
 10153  end
 10154  
 10155  @ A null pen polygon, which has just one vertex $(0,0)$, is
 10156  predeclared for error recovery. It doesn't need a proper
 10157  reference count, because the |toss_pen| procedure below
 10158  will never delete it from memory.
 10159  @^reference counts@>
 10160  
 10161  @<Initialize table entries...@>=
 10162  ref_count(null_pen):=null; link(null_pen):=null;@/
 10163  info(null_pen+1):=1; link(null_pen+1):=null_coords;
 10164  for k:=null_pen+2 to null_pen+8 do mem[k]:=mem[null_pen+1];
 10165  max_offset(null_pen):=0;@/
 10166  link(null_coords):=null_coords;
 10167  knil(null_coords):=null_coords;@/
 10168  x_coord(null_coords):=0;
 10169  y_coord(null_coords):=0;
 10170  
 10171  @ Here's a trivial subroutine that inserts a copy of an offset
 10172  on the |link| side of its clone in the doubly linked list.
 10173  
 10174  @p procedure dup_offset(@!w:pointer);
 10175  var @!r:pointer; {the new node}
 10176  begin r:=get_node(coord_node_size);
 10177  x_coord(r):=x_coord(w);
 10178  y_coord(r):=y_coord(w);
 10179  link(r):=link(w); knil(link(w)):=r;
 10180  knil(r):=w; link(w):=r;
 10181  end;
 10182  
 10183  @ The following algorithm is somewhat more interesting: It converts a
 10184  knot list for a cyclic path into a pen polygon, ignoring everything
 10185  but the |x_coord|, |y_coord|, and |link| fields. If the given path
 10186  vertices do not define a convex polygon, an error message is issued
 10187  and the null pen is returned.
 10188  
 10189  @p function make_pen(@!h:pointer):pointer;
 10190  label done,done1,not_found,found;
 10191  var @!o,@!oo,@!k:small_number; {octant numbers---old, new, and current}
 10192  @!p:pointer; {top-level node for the new pen}
 10193  @!q,@!r,@!s,@!w,@!hh:pointer; {for list manipulation}
 10194  @!n:integer; {offset counter}
 10195  @!dx,@!dy:scaled; {polygon direction}
 10196  @!mc:scaled; {the largest coordinate}
 10197  begin @<Stamp all nodes with an octant code, compute the maximum offset,
 10198    and set |hh| to the node that begins the first octant;
 10199    |goto not_found| if there's a problem@>;
 10200  if mc>=fraction_one-half_unit then goto not_found;
 10201  p:=get_node(pen_node_size); q:=hh; max_offset(p):=mc; ref_count(p):=null;
 10202  if link(q)<>q then link(p):=null+1;
 10203  for k:=1 to 8 do @<Construct the offset list for the |k|th octant@>;
 10204  goto found;
 10205  not_found:p:=null_pen; @<Complain about a bad pen path@>;
 10206  found: if internal[tracing_pens]>0 then print_pen(p," (newly created)",true);
 10207  make_pen:=p;
 10208  end;
 10209  
 10210  @ @<Complain about a bad pen path@>=
 10211  if mc>=fraction_one-half_unit then
 10212    begin print_err("Pen too large");
 10213  @.Pen too large@>
 10214    help2("The cycle you specified has a coordinate of 4095.5 or more.")@/
 10215    ("So I've replaced it by the trivial path `(0,0)..cycle'.");@/
 10216    end
 10217  else  begin print_err("Pen cycle must be convex");
 10218  @.Pen cycle must be convex@>
 10219    help3("The cycle you specified either has consecutive equal points")@/
 10220      ("or turns right or turns through more than 360 degrees.")@/
 10221    ("So I've replaced it by the trivial path `(0,0)..cycle'.");@/
 10222    end;
 10223  put_get_error
 10224  
 10225  @ There should be exactly one node whose octant number is less than its
 10226  predecessor in the cycle; that is node~|hh|.
 10227  
 10228  The loop here will terminate in all cases, but the proof is somewhat tricky:
 10229  If there are at least two distinct $y$~coordinates in the cycle, we will have
 10230  |o>4| and |o<=4| at different points of the cycle. Otherwise there are
 10231  at least two distinct $x$~coordinates, and we will have |o>2| somewhere,
 10232  |o<=2| somewhere.
 10233  
 10234  @<Stamp all nodes...@>=
 10235  q:=h; r:=link(q); mc:=abs(x_coord(h));
 10236  if q=r then
 10237    begin hh:=h; right_type(h):=0; {this trick is explained below}
 10238    if mc<abs(y_coord(h)) then mc:=abs(y_coord(h));
 10239    end
 10240  else  begin o:=0; hh:=null;
 10241    loop@+  begin s:=link(r);
 10242      if mc<abs(x_coord(r)) then mc:=abs(x_coord(r));
 10243      if mc<abs(y_coord(r)) then mc:=abs(y_coord(r));
 10244      dx:=x_coord(r)-x_coord(q); dy:=y_coord(r)-y_coord(q);
 10245      if dx=0 then if dy=0 then goto not_found; {double point}
 10246      if ab_vs_cd(dx,y_coord(s)-y_coord(r),dy,x_coord(s)-x_coord(r))<0 then
 10247        goto not_found; {right turn}
 10248      @<Determine the octant code for direction |(dx,dy)|@>;
 10249      right_type(q):=octant; oo:=octant_number[octant];
 10250      if o>oo then
 10251        begin if hh<>null then goto not_found; {$>360^\circ$}
 10252        hh:=q;
 10253        end;
 10254      o:=oo;
 10255      if (q=h)and(hh<>null) then goto done;
 10256      q:=r; r:=s;
 10257      end;
 10258    done:end
 10259  
 10260  
 10261  @ We want the octant for |(-dx,-dy)| to be
 10262  exactly opposite the octant for |(dx,dy)|.
 10263  
 10264  @<Determine the octant code for direction |(dx,dy)|@>=
 10265  if dx>0 then octant:=first_octant
 10266  else if dx=0 then
 10267    if dy>0 then octant:=first_octant@+else octant:=first_octant+negate_x
 10268  else  begin negate(dx); octant:=first_octant+negate_x;
 10269    end;
 10270  if dy<0 then
 10271    begin negate(dy); octant:=octant+negate_y;
 10272    end
 10273  else if dy=0 then
 10274    if octant>first_octant then octant:=first_octant+negate_x+negate_y;
 10275  if dx<dy then octant:=octant+switch_x_and_y
 10276  
 10277  @ Now |q| points to the node that the present octant shares with the previous
 10278  octant, and |right_type(q)| is the octant code during which |q|~should advance.
 10279  We have set |right_type(q)=0| in the special case that |q| should never advance
 10280  (because the pen is degenerate).
 10281  
 10282  The number of offsets |n| must be smaller than |max_quarterword|, because
 10283  the |fill_envelope| routine stores |n+1| in the |right_type| field
 10284  of a knot node.
 10285  
 10286  @<Construct the offset list...@>=
 10287  begin octant:=octant_code[k]; n:=0; h:=p+octant;
 10288  loop@+  begin r:=get_node(coord_node_size);
 10289    skew(x_coord(q),y_coord(q),octant); x_coord(r):=cur_x; y_coord(r):=cur_y;
 10290    if n=0 then link(h):=r
 10291    else  @<Link node |r| to the previous node@>;
 10292    w:=r;
 10293    if right_type(q)<>octant then goto done1;
 10294    q:=link(q); incr(n);
 10295    end;
 10296  done1: @<Finish linking the offset nodes, and duplicate the
 10297    borderline offset nodes if necessary@>;
 10298  if n>=max_quarterword then overflow("pen polygon size",max_quarterword);
 10299  @:METAFONT capacity exceeded pen polygon size}{\quad pen polygon size@>
 10300  info(h):=n;
 10301  end
 10302  
 10303  @ Now |w| points to the node that was inserted most recently, and
 10304  |k| is the current octant number.
 10305  
 10306  @<Link node |r| to the previous node@>=
 10307  if odd(k) then
 10308    begin link(w):=r; knil(r):=w;
 10309    end
 10310  else  begin knil(w):=r; link(r):=w;
 10311    end
 10312  
 10313  @ We have inserted |n+1| nodes; it remains to duplicate the nodes at the
 10314  ends, if slopes 0 and~$\infty$ aren't already represented. At the end of
 10315  this section the total number of offset nodes should be |n+2|
 10316  (since we call them $w_0$, $w_1$, \dots,~$w_{n+1}$).
 10317  
 10318  @<Finish linking the offset nodes, and duplicate...@>=
 10319  r:=link(h);
 10320  if odd(k) then
 10321    begin link(w):=r; knil(r):=w;
 10322    end
 10323  else  begin knil(w):=r; link(r):=w; link(h):=w; r:=w;
 10324    end;
 10325  if (y_coord(r)<>y_coord(link(r)))or(n=0) then
 10326    begin dup_offset(r); incr(n);
 10327    end;
 10328  r:=knil(r);
 10329  if x_coord(r)<>x_coord(knil(r)) then dup_offset(r)
 10330  else decr(n)
 10331  
 10332  @ Conversely, |make_path| goes back from a pen to a cyclic path that
 10333  might have generated it. The structure of this subroutine is essentially
 10334  the same as |print_pen|.
 10335  
 10336  @p @t\4@>@<Declare the function called |trivial_knot|@>@;
 10337  function make_path(@!pen_head:pointer):pointer;
 10338  var @!p:pointer; {the most recently copied knot}
 10339  @!k:1..8; {octant number}
 10340  @!h:pointer; {offset list head}
 10341  @!m,@!n:integer; {offset indices}
 10342  @!w,@!ww:pointer; {pointers that traverse the offset list}
 10343  begin p:=temp_head;
 10344  for k:=1 to 8 do
 10345    begin octant:=octant_code[k]; h:=pen_head+octant; n:=info(h); w:=link(h);
 10346    if not odd(k) then w:=knil(w); {in even octants, start at $w_{n+1}$}
 10347    for m:=1 to n+1 do
 10348      begin if odd(k) then ww:=link(w)@+else ww:=knil(w);
 10349      if (x_coord(ww)<>x_coord(w))or(y_coord(ww)<>y_coord(w)) then
 10350        @<Copy the unskewed and unrotated coordinates of node |ww|@>;
 10351      w:=ww;
 10352      end;
 10353    end;
 10354  if p=temp_head then
 10355    begin w:=link(pen_head+first_octant);
 10356    p:=trivial_knot(x_coord(w)+y_coord(w),y_coord(w)); link(temp_head):=p;
 10357    end;
 10358  link(p):=link(temp_head); make_path:=link(temp_head);
 10359  end;
 10360  
 10361  @ @<Copy the unskewed and unrotated coordinates of node |ww|@>=
 10362  begin unskew(x_coord(ww),y_coord(ww),octant);
 10363  link(p):=trivial_knot(cur_x,cur_y); p:=link(p);
 10364  end
 10365  
 10366  @ @<Declare the function called |trivial_knot|@>=
 10367  function trivial_knot(@!x,@!y:scaled):pointer;
 10368  var @!p:pointer; {a new knot for explicit coordinates |x| and |y|}
 10369  begin p:=get_node(knot_node_size);
 10370  left_type(p):=explicit; right_type(p):=explicit;@/
 10371  x_coord(p):=x; left_x(p):=x; right_x(p):=x;@/
 10372  y_coord(p):=y; left_y(p):=y; right_y(p):=y;@/
 10373  trivial_knot:=p;
 10374  end;
 10375  
 10376  @ That which can be created can be destroyed.
 10377  
 10378  @d add_pen_ref(#)==incr(ref_count(#))
 10379  @d delete_pen_ref(#)==if ref_count(#)=null then toss_pen(#)
 10380    else decr(ref_count(#))
 10381  
 10382  @<Declare the recycling subroutines@>=
 10383  procedure toss_pen(@!p:pointer);
 10384  var @!k:1..8; {relative header locations}
 10385  @!w,@!ww:pointer; {pointers to offset nodes}
 10386  begin if p<>null_pen then
 10387    begin for k:=1 to 8 do
 10388      begin w:=link(p+k);
 10389      repeat ww:=link(w); free_node(w,coord_node_size); w:=ww;
 10390      until w=link(p+k);
 10391      end;
 10392    free_node(p,pen_node_size);
 10393    end;
 10394  end;
 10395  
 10396  @ The |find_offset| procedure sets |(cur_x,cur_y)| to the offset associated
 10397  with a given direction~|(x,y)| and a given pen~|p|. If |x=y=0|, the
 10398  result is |(0,0)|. If two different offsets apply, one of them is
 10399  chosen arbitrarily.
 10400  
 10401  @p procedure find_offset(@!x,@!y:scaled; @!p:pointer);
 10402  label done,exit;
 10403  var @!octant:first_octant..sixth_octant; {octant code for |(x,y)|}
 10404  @!s:-1..+1; {sign of the octant}
 10405  @!n:integer; {number of offsets remaining}
 10406  @!h,@!w,@!ww:pointer; {list traversal registers}
 10407  begin @<Compute the octant code; skew and rotate the coordinates |(x,y)|@>;
 10408  if odd(octant_number[octant]) then s:=-1@+else s:=+1;
 10409  h:=p+octant; w:=link(link(h)); ww:=link(w); n:=info(h);
 10410  while n>1 do
 10411    begin if ab_vs_cd(x,y_coord(ww)-y_coord(w),@|
 10412      y,x_coord(ww)-x_coord(w))<>s then goto done;
 10413    w:=ww; ww:=link(w); decr(n);
 10414    end;
 10415  done:unskew(x_coord(w),y_coord(w),octant);
 10416  exit:end;
 10417  
 10418  @ @<Compute the octant code; skew and rotate the coordinates |(x,y)|@>=
 10419  if x>0 then octant:=first_octant
 10420  else if x=0 then
 10421    if y<=0 then
 10422      if y=0 then
 10423        begin cur_x:=0; cur_y:=0; return;
 10424        end
 10425      else octant:=first_octant+negate_x
 10426    else octant:=first_octant
 10427  else  begin x:=-x;
 10428    if y=0 then octant:=first_octant+negate_x+negate_y
 10429    else octant:=first_octant+negate_x;
 10430    end;
 10431  if y<0 then
 10432    begin octant:=octant+negate_y; y:=-y;
 10433    end;
 10434  if x>=y then x:=x-y
 10435  else  begin octant:=octant+switch_x_and_y; x:=y-x; y:=y-x;
 10436    end
 10437  
 10438  @* \[24] Filling an envelope.
 10439  We are about to reach the culmination of \MF's digital plotting routines:
 10440  Almost all of the previous algorithms will be brought to bear on \MF's
 10441  most difficult task, which is to fill the envelope of a given cyclic path
 10442  with respect to a given pen polygon.
 10443  
 10444  But we still must complete some of the preparatory work before taking such
 10445  a big plunge.
 10446  
 10447  @ Given a pointer |c| to a nonempty list of cubics,
 10448  and a pointer~|h| to the header information of a pen polygon segment,
 10449  the |offset_prep| routine changes the list into cubics that are
 10450  associated with particular pen offsets. Namely, the cubic between |p|
 10451  and~|q| should be associated with the |k|th offset when |right_type(p)=k|.
 10452  
 10453  List |c| is actually part of a cycle spec, so it terminates at the
 10454  first node whose |right_type| is |endpoint|. The cubics all have
 10455  monotone-nondecreasing $x(t)$ and $y(t)$.
 10456  
 10457  @p @t\4@>@<Declare subroutines needed by |offset_prep|@>@;
 10458  procedure offset_prep(@!c,@!h:pointer);
 10459  label done,not_found;
 10460  var @!n:halfword; {the number of pen offsets}
 10461  @!p,@!q,@!r,@!lh,@!ww:pointer; {for list manipulation}
 10462  @!k:halfword; {the current offset index}
 10463  @!w:pointer; {a pointer to offset $w_k$}
 10464  @<Other local variables for |offset_prep|@>@;
 10465  begin p:=c; n:=info(h); lh:=link(h); {now |lh| points to $w_0$}
 10466  while right_type(p)<>endpoint do
 10467    begin q:=link(p);
 10468    @<Split the cubic between |p| and |q|, if necessary, into cubics
 10469      associated with single offsets, after which |q| should
 10470      point to the end of the final such cubic@>;
 10471    @<Advance |p| to node |q|, removing any ``dead'' cubics that
 10472      might have been introduced by the splitting process@>;
 10473    end;
 10474  end;
 10475  
 10476  @ @<Advance |p| to node |q|, removing any ``dead'' cubics...@>=
 10477  repeat r:=link(p);
 10478  if x_coord(p)=right_x(p) then if y_coord(p)=right_y(p) then
 10479   if x_coord(p)=left_x(r) then if y_coord(p)=left_y(r) then
 10480    if x_coord(p)=x_coord(r) then if y_coord(p)=y_coord(r) then
 10481    begin remove_cubic(p);
 10482    if r=q then q:=p;
 10483    r:=p;
 10484    end;
 10485  p:=r;
 10486  until p=q
 10487  
 10488  @ The splitting process uses a subroutine like |split_cubic|, but
 10489  (for ``bulletproof'' operation) we check to make sure that the
 10490  resulting (skewed) coordinates satisfy $\Delta x\G0$ and $\Delta y\G0$
 10491  after splitting; |make_spec| has made sure that these relations hold
 10492  before splitting. (This precaution is surely unnecessary, now that
 10493  |make_spec| is so much more careful than it used to be. But who
 10494  wants to take a chance? Maybe the hardware will fail or something.)
 10495  
 10496  @<Declare subroutines needed by |offset_prep|@>=
 10497  procedure split_for_offset(@!p:pointer;@!t:fraction);
 10498  var @!q:pointer; {the successor of |p|}
 10499  @!r:pointer; {the new node}
 10500  begin q:=link(p); split_cubic(p,t,x_coord(q),y_coord(q)); r:=link(p);
 10501  if y_coord(r)<y_coord(p) then y_coord(r):=y_coord(p)
 10502  else if y_coord(r)>y_coord(q) then y_coord(r):=y_coord(q);
 10503  if x_coord(r)<x_coord(p) then x_coord(r):=x_coord(p)
 10504  else if x_coord(r)>x_coord(q) then x_coord(r):=x_coord(q);
 10505  end;
 10506  
 10507  @ If the pen polygon has |n| offsets, and if $w_k=(u_k,v_k)$ is the $k$th
 10508  of these, the $k$th pen slope is defined by the formula
 10509  $$s_k={v\k-v_k\over u\k-u_k},\qquad\hbox{for $0<k<n$}.$$
 10510  In odd-numbered octants, the numerator and denominator of this fraction
 10511  will be nonnegative; in even-numbered octants they will both be nonpositive.
 10512  Furthermore we always have $0=s_0\le s_1\le\cdots\le s_n=\infty$. The goal of
 10513  |offset_prep| is to find an offset index~|k| to associate with
 10514  each cubic, such that the slope $s(t)$ of the cubic satisfies
 10515  $$s_{k-1}\le s(t)\le s_k\qquad\hbox{for $0\le t\le 1$.}\eqno(*)$$
 10516  We may have to split a cubic into as many as $2n-1$ pieces before each
 10517  piece corresponds to a unique offset.
 10518  
 10519  @<Split the cubic between |p| and |q|, if necessary, into cubics...@>=
 10520  if n<=1 then right_type(p):=1 {this case is easy}
 10521  else  begin @<Prepare for derivative computations;
 10522      |goto not_found| if the current cubic is dead@>;
 10523    @<Find the initial slope, |dy/dx|@>;
 10524    if dx=0 then @<Handle the special case of infinite slope@>
 10525    else  begin @<Find the index |k| such that $s_{k-1}\L\\{dy}/\\{dx}<s_k$@>;
 10526      @<Complete the offset splitting process@>;
 10527      end;
 10528  not_found: end
 10529  
 10530  @ The slope of a cubic $B(z_0,z_1,z_2,z_3;t)=\bigl(x(t),y(t)\bigr)$ can be
 10531  calculated from the quadratic polynomials
 10532  ${1\over3}x'(t)=B(x_1-x_0,x_2-x_1,x_3-x_2;t)$ and
 10533  ${1\over3}y'(t)=B(y_1-y_0,y_2-y_1,y_3-y_2;t)$.
 10534  Since we may be calculating slopes from several cubics
 10535  split from the current one, it is desirable to do these calculations
 10536  without losing too much precision. ``Scaled up'' values of the
 10537  derivatives, which will be less tainted by accumulated errors than
 10538  derivatives found from the cubics themselves, are maintained in
 10539  local variables |x0|, |x1|, and |x2|, representing $X_0=2^l(x_1-x_0)$,
 10540  $X_1=2^l(x_2-x_1)$, and $X_2=2^l(x_3-x_2)$; similarly |y0|, |y1|, and~|y2|
 10541  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)$.
 10542  To test whether the slope of the cubic is $\ge s$ or $\le s$, we will test
 10543  the sign of the quadratic ${1\over3}2^l\bigl(y'(t)-sx'(t)\bigr)$ if $s\le1$,
 10544  or ${1\over3}2^l\bigl(y'(t)/s-x'(t)\bigr)$ if $s>1$.
 10545  
 10546  @<Other local variables for |offset_prep|@>=
 10547  @!x0,@!x1,@!x2,@!y0,@!y1,@!y2:integer; {representatives of derivatives}
 10548  @!t0,@!t1,@!t2:integer; {coefficients of polynomial for slope testing}
 10549  @!du,@!dv,@!dx,@!dy:integer; {for slopes of the pen and the curve}
 10550  @!max_coef:integer; {used while scaling}
 10551  @!x0a,@!x1a,@!x2a,@!y0a,@!y1a,@!y2a:integer; {intermediate values}
 10552  @!t:fraction; {where the derivative passes through zero}
 10553  @!s:fraction; {slope or reciprocal slope}
 10554  
 10555  @ @<Prepare for derivative computations...@>=
 10556  x0:=right_x(p)-x_coord(p); {should be |>=0|}
 10557  x2:=x_coord(q)-left_x(q); {likewise}
 10558  x1:=left_x(q)-right_x(p); {but this might be negative}
 10559  y0:=right_y(p)-y_coord(p); y2:=y_coord(q)-left_y(q);
 10560  y1:=left_y(q)-right_y(p);
 10561  max_coef:=abs(x0); {we take |abs| just to make sure}
 10562  if abs(x1)>max_coef then max_coef:=abs(x1);
 10563  if abs(x2)>max_coef then max_coef:=abs(x2);
 10564  if abs(y0)>max_coef then max_coef:=abs(y0);
 10565  if abs(y1)>max_coef then max_coef:=abs(y1);
 10566  if abs(y2)>max_coef then max_coef:=abs(y2);
 10567  if max_coef=0 then goto not_found;
 10568  while max_coef<fraction_half do
 10569    begin double(max_coef);
 10570    double(x0); double(x1); double(x2);
 10571    double(y0); double(y1); double(y2);
 10572    end
 10573  
 10574  @ Let us first solve a special case of the problem: Suppose we
 10575  know an index~$k$ such that either (i)~$s(t)\G s_{k-1}$ for all~$t$
 10576  and $s(0)<s_k$, or (ii)~$s(t)\L s_k$ for all~$t$ and $s(0)>s_{k-1}$.
 10577  Then, in a sense, we're halfway done, since one of the two inequalities
 10578  in $(*)$ is satisfied, and the other couldn't be satisfied for
 10579  any other value of~|k|.
 10580  
 10581  The |fin_offset_prep| subroutine solves the stated subproblem.
 10582  It has a boolean parameter called |rising| that is |true| in
 10583  case~(i), |false| in case~(ii). When |rising=false|, parameters
 10584  |x0| through |y2| represent the negative of the derivative of
 10585  the cubic following |p|; otherwise they represent the actual derivative.
 10586  The |w| parameter should point to offset~$w_k$.
 10587  
 10588  @<Declare subroutines needed by |offset_prep|@>=
 10589  procedure fin_offset_prep(@!p:pointer;@!k:halfword;@!w:pointer;
 10590    @!x0,@!x1,@!x2,@!y0,@!y1,@!y2:integer;@!rising:boolean;@!n:integer);
 10591  label exit;
 10592  var @!ww:pointer; {for list manipulation}
 10593  @!du,@!dv:scaled; {for slope calculation}
 10594  @!t0,@!t1,@!t2:integer; {test coefficients}
 10595  @!t:fraction; {place where the derivative passes a critical slope}
 10596  @!s:fraction; {slope or reciprocal slope}
 10597  @!v:integer; {intermediate value for updating |x0..y2|}
 10598  begin loop
 10599    begin right_type(p):=k;
 10600    if rising then
 10601      if k=n then return
 10602      else ww:=link(w) {a pointer to $w\k$}
 10603    else  if k=1 then return
 10604      else ww:=knil(w); {a pointer to $w_{k-1}$}
 10605    @<Compute test coefficients |(t0,t1,t2)|
 10606      for $s(t)$ versus $s_k$ or $s_{k-1}$@>;
 10607    t:=crossing_point(t0,t1,t2);
 10608    if t>=fraction_one then return;
 10609    @<Split the cubic at $t$,
 10610      and split off another cubic if the derivative crosses back@>;
 10611    if rising then incr(k)@+else decr(k);
 10612    w:=ww;
 10613    end;
 10614  exit:end;
 10615  
 10616  @ @<Compute test coefficients |(t0,t1,t2)| for $s(t)$ versus...@>=
 10617  du:=x_coord(ww)-x_coord(w); dv:=y_coord(ww)-y_coord(w);
 10618  if abs(du)>=abs(dv) then {$s_{k-1}\le1$ or $s_k\le1$}
 10619    begin s:=make_fraction(dv,du);
 10620    t0:=take_fraction(x0,s)-y0;
 10621    t1:=take_fraction(x1,s)-y1;
 10622    t2:=take_fraction(x2,s)-y2;
 10623    end
 10624  else  begin s:=make_fraction(du,dv);
 10625    t0:=x0-take_fraction(y0,s);
 10626    t1:=x1-take_fraction(y1,s);
 10627    t2:=x2-take_fraction(y2,s);
 10628    end
 10629  
 10630  @ The curve has crossed $s_k$ or $s_{k-1}$; its initial segment satisfies
 10631  $(*)$, and it might cross again and return towards $s_{k-1}$ or $s_k$,
 10632  respectively, yielding another solution of $(*)$.
 10633  
 10634  @<Split the cubic at $t$, and split off another...@>=
 10635  begin split_for_offset(p,t); right_type(p):=k; p:=link(p);@/
 10636  v:=t_of_the_way(x0)(x1); x1:=t_of_the_way(x1)(x2);
 10637  x0:=t_of_the_way(v)(x1);@/
 10638  v:=t_of_the_way(y0)(y1); y1:=t_of_the_way(y1)(y2);
 10639  y0:=t_of_the_way(v)(y1);@/
 10640  t1:=t_of_the_way(t1)(t2);
 10641  if t1>0 then t1:=0; {without rounding error, |t1| would be |<=0|}
 10642  t:=crossing_point(0,-t1,-t2);
 10643  if t<fraction_one then
 10644    begin split_for_offset(p,t); right_type(link(p)):=k;@/
 10645    v:=t_of_the_way(x1)(x2); x1:=t_of_the_way(x0)(x1);
 10646    x2:=t_of_the_way(x1)(v);@/
 10647    v:=t_of_the_way(y1)(y2); y1:=t_of_the_way(y0)(y1);
 10648    y2:=t_of_the_way(y1)(v);
 10649    end;
 10650  end
 10651  
 10652  @ Now we must consider the general problem of |offset_prep|, when
 10653  nothing is known about a given cubic. We start by finding its
 10654  slope $s(0)$ in the vicinity of |t=0|.
 10655  
 10656  If $z'(t)=0$, the given cubic is numerically unstable, since the
 10657  slope direction is probably being influenced primarily by rounding
 10658  errors. A user who specifies such cuspy curves should expect to generate
 10659  rather wild results. The present code tries its best to believe the
 10660  existing data, as if no rounding errors were present.
 10661  
 10662  @ @<Find the initial slope, |dy/dx|@>=
 10663  dx:=x0; dy:=y0;
 10664  if dx=0 then if dy=0 then
 10665    begin dx:=x1; dy:=y1;
 10666    if dx=0 then if dy=0 then
 10667      begin dx:=x2; dy:=y2;
 10668      end;
 10669    end
 10670  
 10671  @ The next step is to bracket the initial slope between consecutive
 10672  slopes of the pen polygon. The most important invariant relation in the
 10673  following loop is that |dy/dx>=@t$s_{k-1}$@>|.
 10674  
 10675  @<Find the index |k| such that $s_{k-1}\L\\{dy}/\\{dx}<s_k$@>=
 10676  k:=1; w:=link(lh);
 10677  loop@+  begin if k=n then goto done;
 10678    ww:=link(w);
 10679    if ab_vs_cd(dy,abs(x_coord(ww)-x_coord(w)),@|
 10680     dx,abs(y_coord(ww)-y_coord(w)))>=0 then
 10681      begin incr(k); w:=ww;
 10682      end
 10683    else goto done;
 10684    end;
 10685  done:
 10686  
 10687  @ Finally we want to reduce the general problem to situations that
 10688  |fin_offset_prep| can handle. If |k=1|, we already are in the desired
 10689  situation. Otherwise we can split the cubic into at most three parts
 10690  with respect to $s_{k-1}$, and apply |fin_offset_prep| to each part.
 10691  
 10692  @<Complete the offset splitting process@>=
 10693  if k=1 then t:=fraction_one+1
 10694  else  begin ww:=knil(w); @<Compute test coeff...@>;
 10695    t:=crossing_point(-t0,-t1,-t2);
 10696    end;
 10697  if t>=fraction_one then fin_offset_prep(p,k,w,x0,x1,x2,y0,y1,y2,true,n)
 10698  else  begin split_for_offset(p,t); r:=link(p);@/
 10699    x1a:=t_of_the_way(x0)(x1); x1:=t_of_the_way(x1)(x2);
 10700    x2a:=t_of_the_way(x1a)(x1);@/
 10701    y1a:=t_of_the_way(y0)(y1); y1:=t_of_the_way(y1)(y2);
 10702    y2a:=t_of_the_way(y1a)(y1);@/
 10703    fin_offset_prep(p,k,w,x0,x1a,x2a,y0,y1a,y2a,true,n); x0:=x2a; y0:=y2a;
 10704    t1:=t_of_the_way(t1)(t2);
 10705    if t1<0 then t1:=0;
 10706    t:=crossing_point(0,t1,t2);
 10707    if t<fraction_one then
 10708      @<Split off another |rising| cubic for |fin_offset_prep|@>;
 10709    fin_offset_prep(r,k-1,ww,-x0,-x1,-x2,-y0,-y1,-y2,false,n);
 10710    end
 10711  
 10712  @ @<Split off another |rising| cubic for |fin_offset_prep|@>=
 10713  begin split_for_offset(r,t);@/
 10714  x1a:=t_of_the_way(x1)(x2); x1:=t_of_the_way(x0)(x1);
 10715  x0a:=t_of_the_way(x1)(x1a);@/
 10716  y1a:=t_of_the_way(y1)(y2); y1:=t_of_the_way(y0)(y1);
 10717  y0a:=t_of_the_way(y1)(y1a);@/
 10718  fin_offset_prep(link(r),k,w,x0a,x1a,x2,y0a,y1a,y2,true,n);
 10719  x2:=x0a; y2:=y0a;
 10720  end
 10721  
 10722  @ @<Handle the special case of infinite slope@>=
 10723  fin_offset_prep(p,n,knil(knil(lh)),-x0,-x1,-x2,-y0,-y1,-y2,false,n)
 10724  
 10725  @ OK, it's time now for the biggie. The |fill_envelope| routine generalizes
 10726  |fill_spec| to polygonal envelopes. Its outer structure is essentially the
 10727  same as before, except that octants with no cubics do contribute to
 10728  the envelope.
 10729  
 10730  @p @t\4@>@<Declare the procedure called |skew_line_edges|@>@;
 10731  @t\4@>@<Declare the procedure called |dual_moves|@>@;
 10732  procedure fill_envelope(@!spec_head:pointer);
 10733  label done, done1;
 10734  var @!p,@!q,@!r,@!s:pointer; {for list traversal}
 10735  @!h:pointer; {head of pen offset list for current octant}
 10736  @!www:pointer; {a pen offset of temporary interest}
 10737  @<Other local variables for |fill_envelope|@>@;
 10738  begin if internal[tracing_edges]>0 then begin_edge_tracing;
 10739  p:=spec_head; {we assume that |left_type(spec_head)=endpoint|}
 10740  repeat octant:=left_octant(p); h:=cur_pen+octant;
 10741  @<Set variable |q| to the node at the end of the current octant@>;
 10742  @<Determine the envelope's starting and ending
 10743      lattice points |(m0,n0)| and |(m1,n1)|@>;
 10744  offset_prep(p,h); {this may clobber node~|q|, if it becomes ``dead''}
 10745  @<Set variable |q| to the node at the end of the current octant@>;
 10746  @<Make the envelope moves for the current octant and insert them
 10747    in the pixel data@>;
 10748  p:=link(q);
 10749  until p=spec_head;
 10750  if internal[tracing_edges]>0 then end_edge_tracing;
 10751  toss_knot_list(spec_head);
 10752  end;
 10753  
 10754  @ In even-numbered octants we have reflected the coordinates an odd number
 10755  of times, hence clockwise and counterclockwise are reversed; this means that
 10756  the envelope is being formed in a ``dual'' manner. For the time being, let's
 10757  concentrate on odd-numbered octants, since they're easier to understand.
 10758  After we have coded the program for odd-numbered octants, the changes needed
 10759  to dualize it will not be so mysterious.
 10760  
 10761  It is convenient to assume that we enter an odd-numbered octant with
 10762  an |axis| transition (where the skewed slope is zero) and leave at a
 10763  |diagonal| one (where the skewed slope is infinite). Then all of the
 10764  offset points $z(t)+w(t)$ will lie in a rectangle whose lower left and
 10765  upper right corners are the initial and final offset points. If this
 10766  assumption doesn't hold we can implicitly change the curve so that it does.
 10767  For example, if the entering transition is diagonal, we can draw a
 10768  straight line from $z_0+w_{n+1}$ to $z_0+w_0$ and continue as if the
 10769  curve were moving rightward. The effect of this on the envelope is simply
 10770  to ``doubly color'' the region enveloped by a section of the pen that
 10771  goes from $w_0$ to $w_1$ to $\cdots$ to $w_{n+1}$ to~$w_0$. The additional
 10772  straight line at the beginning (and a similar one at the end, where it
 10773  may be necessary to go from $z_1+w_{n+1}$ to $z_1+w_0$) can be drawn by
 10774  the |line_edges| routine; we are thereby saved from the embarrassment that
 10775  these lines travel backwards from the current octant direction.
 10776  
 10777  Once we have established the assumption that the curve goes from
 10778  $z_0+w_0$ to $z_1+w_{n+1}$, any further retrograde moves that might
 10779  occur within the octant can be essentially ignored; we merely need to
 10780  keep track of the rightmost edge in each row, in order to compute
 10781  the envelope.
 10782  
 10783  Envelope moves consist of offset cubics intermixed with straight line
 10784  segments. We record them in a separate |env_move| array, which is
 10785  something like |move| but it keeps track of the rightmost position of the
 10786  envelope in each row.
 10787  
 10788  @<Glob...@>=
 10789  @!env_move:array[0..move_size] of integer;
 10790  
 10791  @ @<Determine the envelope's starting and ending...@>=
 10792  w:=link(h);@+if left_transition(p)=diagonal then w:=knil(w);
 10793  @!stat if internal[tracing_edges]>unity then
 10794    @<Print a line of diagnostic info to introduce this octant@>;
 10795  tats@;@/
 10796  ww:=link(h); www:=ww; {starting and ending offsets}
 10797  if odd(octant_number[octant]) then www:=knil(www)@+else ww:=knil(ww);
 10798  if w<>ww then skew_line_edges(p,w,ww);
 10799  end_round(x_coord(p)+x_coord(ww),y_coord(p)+y_coord(ww));
 10800  m0:=m1; n0:=n1; d0:=d1;@/
 10801  end_round(x_coord(q)+x_coord(www),y_coord(q)+y_coord(www));
 10802  if n1-n0>=move_size then overflow("move table size",move_size)
 10803  @:METAFONT capacity exceeded move table size}{\quad move table size@>
 10804  
 10805  @ @<Print a line of diagnostic info to introduce this octant@>=
 10806  begin print_nl("@@ Octant "); print(octant_dir[octant]);
 10807  @:]]]\AT!_Octant}{\.{\AT! Octant...}@>
 10808  print(" ("); print_int(info(h)); print(" offset");
 10809  if info(h)<>1 then print_char("s");
 10810  print("), from ");
 10811  print_two_true(x_coord(p)+x_coord(w),y_coord(p)+y_coord(w));@/
 10812  ww:=link(h);@+if right_transition(q)=diagonal then ww:=knil(ww);
 10813  print(" to ");
 10814  print_two_true(x_coord(q)+x_coord(ww),y_coord(q)+y_coord(ww));
 10815  end
 10816  
 10817  @ A slight variation of the |line_edges| procedure comes in handy
 10818  when we must draw the retrograde lines for nonstandard entry and exit
 10819  conditions.
 10820  
 10821  @<Declare the procedure called |skew_line_edges|@>=
 10822  procedure skew_line_edges(@!p,@!w,@!ww:pointer);
 10823  var @!x0,@!y0,@!x1,@!y1:scaled; {from and to}
 10824  begin if (x_coord(w)<>x_coord(ww))or(y_coord(w)<>y_coord(ww)) then
 10825    begin x0:=x_coord(p)+x_coord(w); y0:=y_coord(p)+y_coord(w);@/
 10826    x1:=x_coord(p)+x_coord(ww); y1:=y_coord(p)+y_coord(ww);@/
 10827    unskew(x0,y0,octant); {unskew and unrotate the coordinates}
 10828    x0:=cur_x; y0:=cur_y;@/
 10829    unskew(x1,y1,octant);@/
 10830    @!stat if internal[tracing_edges]>unity then
 10831      begin print_nl("@@ retrograde line from ");
 10832  @:]]]\AT!_retro_}{\.{\AT! retrograde line...}@>
 10833    @.retrograde line...@>
 10834      print_two(x0,y0); print(" to "); print_two(cur_x,cur_y); print_nl("");
 10835      end;@+tats@;@/
 10836    line_edges(x0,y0,cur_x,cur_y); {then draw a straight line}
 10837    end;
 10838  end;
 10839  
 10840  @ The envelope calculations require more local variables than we needed
 10841  in the simpler case of |fill_spec|. At critical points in the computation,
 10842  |w| will point to offset $w_k$; |m| and |n| will record the current
 10843  lattice positions.  The values of |move_ptr| after the initial and before
 10844  the final offset adjustments are stored in |smooth_bot| and |smooth_top|,
 10845  respectively.
 10846  
 10847  @<Other local variables for |fill_envelope|@>=
 10848  @!m,@!n:integer; {current lattice position}
 10849  @!mm0,@!mm1:integer; {skewed equivalents of |m0| and |m1|}
 10850  @!k:integer; {current offset number}
 10851  @!w,@!ww:pointer; {pointers to the current offset and its neighbor}
 10852  @!smooth_bot,@!smooth_top:0..move_size; {boundaries of smoothing}
 10853  @!xx,@!yy,@!xp,@!yp,@!delx,@!dely,@!tx,@!ty:scaled;
 10854    {registers for coordinate calculations}
 10855  
 10856  @ @<Make the envelope moves for the current octant...@>=
 10857  if odd(octant_number[octant]) then
 10858    begin @<Initialize for ordinary envelope moves@>;
 10859    r:=p; right_type(q):=info(h)+1;
 10860    loop@+  begin if r=q then smooth_top:=move_ptr;
 10861      while right_type(r)<>k do
 10862        @<Insert a line segment to approach the correct offset@>;
 10863      if r=p then smooth_bot:=move_ptr;
 10864      if r=q then goto done;
 10865      move[move_ptr]:=1; n:=move_ptr; s:=link(r);@/
 10866      make_moves(x_coord(r)+x_coord(w),right_x(r)+x_coord(w),
 10867        left_x(s)+x_coord(w),x_coord(s)+x_coord(w),@|
 10868        y_coord(r)+y_coord(w)+half_unit,right_y(r)+y_coord(w)+half_unit,
 10869        left_y(s)+y_coord(w)+half_unit,y_coord(s)+y_coord(w)+half_unit,@|
 10870        xy_corr[octant],y_corr[octant]);@/
 10871      @<Transfer moves from the |move| array to |env_move|@>;
 10872      r:=s;
 10873      end;
 10874  done:  @<Insert the new envelope moves in the pixel data@>;
 10875    end
 10876  else dual_moves(h,p,q);
 10877  right_type(q):=endpoint
 10878  
 10879  @ @<Initialize for ordinary envelope moves@>=
 10880  k:=0; w:=link(h); ww:=knil(w);
 10881  mm0:=floor_unscaled(x_coord(p)+x_coord(w)-xy_corr[octant]);
 10882  mm1:=floor_unscaled(x_coord(q)+x_coord(ww)-xy_corr[octant]);
 10883  for n:=0 to n1-n0-1 do env_move[n]:=mm0;
 10884  env_move[n1-n0]:=mm1; move_ptr:=0; m:=mm0
 10885  
 10886  @ At this point |n| holds the value of |move_ptr| that was current
 10887  when |make_moves| began to record its moves.
 10888  
 10889  @<Transfer moves from the |move| array to |env_move|@>=
 10890  repeat m:=m+move[n]-1;
 10891  if m>env_move[n] then env_move[n]:=m;
 10892  incr(n);
 10893  until n>move_ptr
 10894  
 10895  @ Retrograde lines (when |k| decreases) do not need to be recorded in
 10896  |env_move| because their edges are not the furthest right in any row.
 10897  
 10898  @<Insert a line segment to approach the correct offset@>=
 10899  begin xx:=x_coord(r)+x_coord(w); yy:=y_coord(r)+y_coord(w)+half_unit;
 10900  @!stat if internal[tracing_edges]>unity then
 10901    begin print_nl("@@ transition line "); print_int(k); print(", from ");
 10902  @:]]]\AT!_trans_}{\.{\AT! transition line...}@>
 10903  @.transition line...@>
 10904    print_two_true(xx,yy-half_unit);
 10905    end;@+tats@;@/
 10906  if right_type(r)>k then
 10907    begin incr(k); w:=link(w);
 10908    xp:=x_coord(r)+x_coord(w); yp:=y_coord(r)+y_coord(w)+half_unit;
 10909    if yp<>yy then
 10910      @<Record a line segment from |(xx,yy)| to |(xp,yp)| in |env_move|@>;
 10911    end
 10912  else  begin decr(k); w:=knil(w);
 10913    xp:=x_coord(r)+x_coord(w); yp:=y_coord(r)+y_coord(w)+half_unit;
 10914    end;
 10915  stat if internal[tracing_edges]>unity then
 10916    begin print(" to ");
 10917    print_two_true(xp,yp-half_unit);
 10918    print_nl("");
 10919    end;@+tats@;@/
 10920  m:=floor_unscaled(xp-xy_corr[octant]);
 10921  move_ptr:=floor_unscaled(yp-y_corr[octant])-n0;
 10922  if m>env_move[move_ptr] then env_move[move_ptr]:=m;
 10923  end
 10924  
 10925  @ In this step we have |xp>=xx| and |yp>=yy|.
 10926  
 10927  @<Record a line segment from |(xx,yy)| to |(xp,yp)| in |env_move|@>=
 10928  begin ty:=floor_scaled(yy-y_corr[octant]); dely:=yp-yy; yy:=yy-ty;
 10929  ty:=yp-y_corr[octant]-ty;
 10930  if ty>=unity then
 10931    begin delx:=xp-xx; yy:=unity-yy;
 10932    loop@+  begin tx:=take_fraction(delx,make_fraction(yy,dely));
 10933      if ab_vs_cd(tx,dely,delx,yy)+xy_corr[octant]>0 then decr(tx);
 10934      m:=floor_unscaled(xx+tx);
 10935      if m>env_move[move_ptr] then env_move[move_ptr]:=m;
 10936      ty:=ty-unity;
 10937      if ty<unity then goto done1;
 10938      yy:=yy+unity; incr(move_ptr);
 10939      end;
 10940    done1:end;
 10941  end
 10942  
 10943  @ @<Insert the new envelope moves in the pixel data@>=
 10944  debug if (m<>mm1)or(move_ptr<>n1-n0) then confusion("1");@+gubed@;@/
 10945  @:this can't happen /}{\quad 1@>
 10946  move[0]:=d0+env_move[0]-mm0;
 10947  for n:=1 to move_ptr do
 10948    move[n]:=env_move[n]-env_move[n-1]+1;
 10949  move[move_ptr]:=move[move_ptr]-d1;
 10950  if internal[smoothing]>0 then smooth_moves(smooth_bot,smooth_top);
 10951  move_to_edges(m0,n0,m1,n1);
 10952  if right_transition(q)=axis then
 10953    begin w:=link(h); skew_line_edges(q,knil(w),w);
 10954    end
 10955  
 10956  @ We've done it all in the odd-octant case; the only thing remaining
 10957  is to repeat the same ideas, upside down and/or backwards.
 10958  
 10959  The following code has been split off as a subprocedure of |fill_envelope|,
 10960  because some \PASCAL\ compilers cannot handle procedures as large as
 10961  |fill_envelope| would otherwise be.
 10962  
 10963  @<Declare the procedure called |dual_moves|@>=
 10964  procedure dual_moves(@!h,@!p,@!q:pointer);
 10965  label done,done1;
 10966  var @!r,@!s:pointer; {for list traversal}
 10967  @<Other local variables for |fill_envelope|@>@;
 10968  begin @<Initialize for dual envelope moves@>;
 10969  r:=p; {recall that |right_type(q)=endpoint=0| now}
 10970  loop@+  begin if r=q then smooth_top:=move_ptr;
 10971    while right_type(r)<>k do
 10972      @<Insert a line segment dually to approach the correct offset@>;
 10973    if r=p then smooth_bot:=move_ptr;
 10974    if r=q then goto done;
 10975    move[move_ptr]:=1; n:=move_ptr; s:=link(r);@/
 10976    make_moves(x_coord(r)+x_coord(w),right_x(r)+x_coord(w),
 10977      left_x(s)+x_coord(w),x_coord(s)+x_coord(w),@|
 10978      y_coord(r)+y_coord(w)+half_unit,right_y(r)+y_coord(w)+half_unit,
 10979      left_y(s)+y_coord(w)+half_unit,y_coord(s)+y_coord(w)+half_unit,@|
 10980      xy_corr[octant],y_corr[octant]);
 10981    @<Transfer moves dually from the |move| array to |env_move|@>;
 10982    r:=s;
 10983    end;
 10984  done:@<Insert the new envelope moves dually in the pixel data@>;
 10985  end;
 10986  
 10987  @ In the dual case the normal situation is to arrive with a |diagonal|
 10988  transition and to leave at the |axis|. The leftmost edge in each row
 10989  is relevant instead of the rightmost one.
 10990  
 10991  @<Initialize for dual envelope moves@>=
 10992  k:=info(h)+1; ww:=link(h); w:=knil(ww);@/
 10993  mm0:=floor_unscaled(x_coord(p)+x_coord(w)-xy_corr[octant]);
 10994  mm1:=floor_unscaled(x_coord(q)+x_coord(ww)-xy_corr[octant]);
 10995  for n:=1 to n1-n0+1 do env_move[n]:=mm1;
 10996  env_move[0]:=mm0; move_ptr:=0; m:=mm0
 10997  
 10998  @ @<Transfer moves dually from the |move| array to |env_move|@>=
 10999  repeat if m<env_move[n] then env_move[n]:=m;
 11000  m:=m+move[n]-1;
 11001  incr(n);
 11002  until n>move_ptr
 11003  
 11004  @ Dual retrograde lines occur when |k| increases; the edges of such lines
 11005  are not the furthest left in any row.
 11006  
 11007  @<Insert a line segment dually to approach the correct offset@>=
 11008  begin xx:=x_coord(r)+x_coord(w); yy:=y_coord(r)+y_coord(w)+half_unit;
 11009  @!stat if internal[tracing_edges]>unity then
 11010    begin print_nl("@@ transition line "); print_int(k); print(", from ");
 11011  @:]]]\AT!_trans_}{\.{\AT! transition line...}@>
 11012  @.transition line...@>
 11013    print_two_true(xx,yy-half_unit);
 11014    end;@+tats@;@/
 11015  if right_type(r)<k then
 11016    begin decr(k); w:=knil(w);
 11017    xp:=x_coord(r)+x_coord(w); yp:=y_coord(r)+y_coord(w)+half_unit;
 11018    if yp<>yy then
 11019      @<Record a line segment from |(xx,yy)| to |(xp,yp)| dually in |env_move|@>;
 11020    end
 11021  else  begin incr(k); w:=link(w);
 11022    xp:=x_coord(r)+x_coord(w); yp:=y_coord(r)+y_coord(w)+half_unit;
 11023    end;
 11024  stat if internal[tracing_edges]>unity then
 11025    begin print(" to ");
 11026    print_two_true(xp,yp-half_unit);
 11027    print_nl("");
 11028    end;@+tats@;@/
 11029  m:=floor_unscaled(xp-xy_corr[octant]);
 11030  move_ptr:=floor_unscaled(yp-y_corr[octant])-n0;
 11031  if m<env_move[move_ptr] then env_move[move_ptr]:=m;
 11032  end
 11033  
 11034  @ Again, |xp>=xx| and |yp>=yy|; but this time we are interested in the {\sl
 11035  smallest\/} |m| that belongs to a given |move_ptr| position, instead of
 11036  the largest~|m|.
 11037  
 11038  @<Record a line segment from |(xx,yy)| to |(xp,yp)| dually in |env_move|@>=
 11039  begin ty:=floor_scaled(yy-y_corr[octant]); dely:=yp-yy; yy:=yy-ty;
 11040  ty:=yp-y_corr[octant]-ty;
 11041  if ty>=unity then
 11042    begin delx:=xp-xx; yy:=unity-yy;
 11043    loop@+  begin if m<env_move[move_ptr] then env_move[move_ptr]:=m;
 11044      tx:=take_fraction(delx,make_fraction(yy,dely));
 11045      if ab_vs_cd(tx,dely,delx,yy)+xy_corr[octant]>0 then decr(tx);
 11046      m:=floor_unscaled(xx+tx);
 11047      ty:=ty-unity; incr(move_ptr);
 11048      if ty<unity then goto done1;
 11049      yy:=yy+unity;
 11050      end;
 11051  done1:  if m<env_move[move_ptr] then env_move[move_ptr]:=m;
 11052    end;
 11053  end
 11054  
 11055  @ Since |env_move| contains minimum values instead of maximum values, the
 11056  finishing-up process is slightly different in the dual case.
 11057  
 11058  @<Insert the new envelope moves dually in the pixel data@>=
 11059  debug if (m<>mm1)or(move_ptr<>n1-n0) then confusion("2");@+gubed@;@/
 11060  @:this can't happen /}{\quad 2@>
 11061  move[0]:=d0+env_move[1]-mm0;
 11062  for n:=1 to move_ptr do
 11063    move[n]:=env_move[n+1]-env_move[n]+1;
 11064  move[move_ptr]:=move[move_ptr]-d1;
 11065  if internal[smoothing]>0 then smooth_moves(smooth_bot,smooth_top);
 11066  move_to_edges(m0,n0,m1,n1);
 11067  if right_transition(q)=diagonal then
 11068    begin w:=link(h); skew_line_edges(q,w,knil(w));
 11069    end
 11070  
 11071  @* \[25] Elliptical pens.
 11072  To get the envelope of a cyclic path with respect to an ellipse, \MF\
 11073  calculates the envelope with respect to a polygonal approximation to
 11074  the ellipse, using an approach due to John Hobby (Ph.D. thesis,
 11075  Stanford University, 1985).
 11076  @^Hobby, John Douglas@>
 11077  This has two important advantages over trying to obtain the ``exact''
 11078  envelope:
 11079  
 11080  \yskip\textindent{1)}It gives better results, because the polygon has been
 11081  designed to counteract problems that arise from digitization; the
 11082  polygon includes sub-pixel corrections to an exact ellipse that make
 11083  the results essentially independent of where the path falls on the raster.
 11084  For example, the exact envelope with respect to a pen of diameter~1
 11085  blackens a pixel if and only if the path intersects a circle of diameter~1
 11086  inscribed in that pixel; the resulting pattern has ``blots'' when the path
 11087  is traveling diagonally in unfortunate raster positions. A much better
 11088  result is obtained when pixels are blackened only when the path intersects
 11089  an inscribed {\sl diamond\/} of diameter~1. Such a diamond is precisely
 11090  the polygon that \MF\ uses in the special case of a circle whose diameter is~1.
 11091  
 11092  \yskip\textindent{2)}Polygonal envelopes of cubic splines are cubic
 11093  splines, hence it isn't necessary to introduce completely different
 11094  routines. By contrast, exact envelopes of cubic splines with respect
 11095  to circles are complicated curves, more difficult to plot than cubics.
 11096  
 11097  @ Hobby's construction involves some interesting number theory.
 11098  If $u$ and~$v$ are relatively prime integers, we divide the
 11099  set of integer points $(m,n)$ into equivalence classes by saying
 11100  that $(m,n)$ belongs to class $um+vn$. Then any two integer points
 11101  that lie on a line of slope $-u/v$ belong to the same class, because
 11102  such points have the form $(m+tv,n-tu)$. Neighboring lines of slope $-u/v$
 11103  that go through integer points are separated by distance $1/\psqrt{u^2+v^2}$
 11104  from each other, and these lines are perpendicular to lines of slope~$v/u$.
 11105  If we start at the origin and travel a distance $k/\psqrt{u^2+v^2}$ in
 11106  direction $(u,v)$, we reach the line of slope~$-u/v$ whose points
 11107  belong to class~$k$.
 11108  
 11109  For example, let $u=2$ and $v=3$. Then the points $(0,0)$, $(3,-2)$,
 11110  $\ldots$ belong to class~0; the points $(-1,1)$, $(2,-1)$, $\ldots$ belong
 11111  to class~1; and the distance between these two lines is $1/\sqrt{13}$.
 11112  The point $(2,3)$ itself belongs to class~13, hence its distance from
 11113  the origin is $13/\sqrt{13}=\sqrt{13}$ (which we already knew).
 11114  
 11115  Suppose we wish to plot envelopes with respect to polygons with
 11116  integer vertices. Then the best polygon for curves that travel in
 11117  direction $(v,-u)$ will contain the points of class~$k$ such that
 11118  $k/\psqrt{u^2+v^2}$ is as close as possible to~$d$, where $d$ is the
 11119  maximum distance of the given ellipse from the line $ux+vy=0$.
 11120  
 11121  The |fillin| correction assumes that a diagonal line has an
 11122  apparent thickness $$2f\cdot\min(\vert u\vert,\vert v\vert)/\psqrt{u^2+v^2}$$
 11123  greater than would be obtained with truly square pixels. (If a
 11124  white pixel at an exterior corner is assumed to have apparent
 11125  darkness $f_1$ and a black pixel at an interior corner is assumed
 11126  to have apparent darkness $1-f_2$, then $f=f_1-f_2$ is the |fillin|
 11127  parameter.) Under this assumption we want to choose $k$ so that
 11128  $\bigl(k+2f\cdot\min(\vert u\vert,\vert v\vert)\bigr)\big/\psqrt{u^2+v^2}$
 11129  is as close as possible to $d$.
 11130  
 11131  Integer coordinates for the vertices work nicely because the thickness of
 11132  the envelope at any given slope is independent of the position of the
 11133  path with respect to the raster. It turns out, in fact, that the same
 11134  property holds for polygons whose vertices have coordinates that are
 11135  integer multiples of~$1\over2$, because ellipses are symmetric about
 11136  the origin. It's convenient to double all dimensions and require the
 11137  resulting polygon to have vertices with integer coordinates. For example,
 11138  to get a circle of {\sl diameter}~$r$, we shall compute integer
 11139  coordinates for a circle of {\sl radius}~$r$. The circle of radius~$r$
 11140  will want to be represented by a polygon that contains the boundary
 11141  points $(0,\pm r)$ and~$(\pm r,0)$; later we will divide everything
 11142  by~2 and get a polygon with $(0,\pm{1\over2}r)$ and $(\pm{1\over2}r,0)$
 11143  on its boundary.
 11144  
 11145  @ In practice the important slopes are those having small values of
 11146  $u$ and~$v$; these make regular patterns in which our eyes quickly
 11147  spot irregularities. For example, horizontal and vertical lines
 11148  (when $u=0$ and $\vert v\vert=1$, or $\vert u\vert=1$ and $v=0$)
 11149  are the most important; diagonal lines (when $\vert u\vert=\vert v\vert=1$)
 11150  are next; and then come lines with slope $\pm2$ or $\pm1/2$.
 11151  
 11152  The nicest way to generate all rational directions having small
 11153  numerators and denominators is to generalize the Stern--Brocot tree
 11154  [cf.~{\sl Concrete Mathematics}, section 4.5]
 11155  @^Brocot, Achille@>
 11156  @^Stern, Moritz Abraham@>
 11157  to a ``Stern--Brocot wreath'' as follows: Begin with four nodes
 11158  arranged in a circle, containing the respective directions
 11159  $(u,v)=(1,0)$, $(0,1)$, $(-1,0)$, and~$(0,-1)$. Then between pairs of
 11160  consecutive terms $(u,v)$ and $(u',v')$ of the wreath, insert the
 11161  direction $(u+u',v+v')$; continue doing this until some stopping
 11162  criterion is fulfilled.
 11163  
 11164  It is not difficult to verify that, regardless of the stopping
 11165  criterion, consecutive directions $(u,v)$ and $(u',v')$ of this
 11166  wreath will always satisfy the relation $uv'-u'v=1$. Such pairs
 11167  of directions have a nice property with respect to the equivalence
 11168  classes described above. Let $l$ be a line of equivalent integer points
 11169  $(m+tv,n-tu)$ with respect to~$(u,v)$, and let $l'$ be a line of
 11170  equivalent integer points $(m'+tv',n'-tu')$ with respect to~$(u',v')$.
 11171  Then $l$ and~$l'$ intersect in an integer point $(m'',n'')$, because
 11172  the determinant of the linear equations for intersection is $uv'-u'v=1$.
 11173  Notice that the class number of $(m'',n'')$ with respect to $(u+u',v+v')$
 11174  is the sum of its class numbers with respect to $(u,v)$ and~$(u',v')$.
 11175  Moreover, consecutive points on~$l$ and~$l'$ belong to classes that
 11176  differ by exactly~1 with respect to $(u+u',v+v')$.
 11177  
 11178  This leads to a nice algorithm in which we construct a polygon having
 11179  ``correct'' class numbers for as many small-integer directions $(u,v)$
 11180  as possible: Assuming that lines $l$ and~$l'$ contain points of the
 11181  correct class for $(u,v)$ and~$(u',v')$, respectively, we determine
 11182  the intersection $(m'',n'')$ and compute its class with respect to
 11183  $(u+u',v+v')$. If the class is too large to be the best approximation,
 11184  we move back the proper number of steps from $(m'',n'')$ toward smaller
 11185  class numbers on both $l$ and~$l'$, unless this requires moving to points
 11186  that are no longer in the polygon; in this way we arrive at two points that
 11187  determine a line~$l''$ having the appropriate class. The process continues
 11188  recursively, until it cannot proceed without removing the last remaining
 11189  point from the class for $(u,v)$ or the class for $(u',v')$.
 11190  
 11191  @ The |make_ellipse| subroutine produces a pointer to a cyclic path
 11192  whose vertices define a polygon suitable for envelopes. The control
 11193  points on this path will be ignored; in fact, the fields in knot nodes
 11194  that are usually reserved for control points are occupied by other
 11195  data that helps |make_ellipse| compute the desired polygon.
 11196  
 11197  Parameters |major_axis| and |minor_axis| define the axes of the ellipse;
 11198  and parameter |theta| is an angle by which the ellipse is rotated
 11199  counterclockwise. If |theta=0|, the ellipse has the equation
 11200  $(x/a)^2+(y/b)^2=1$, where |a=major_axis/2| and |b=minor_axis/2|.
 11201  In general, the points of the ellipse are generated in the complex plane
 11202  by the formula $e^{i\theta}(a\cos t+ib\sin t)$, as $t$~ranges over all
 11203  angles. Notice that if |major_axis=minor_axis=d|, we obtain a circle
 11204  of diameter~|d|, regardless of the value of |theta|.
 11205  
 11206  The method sketched above is used to produce the elliptical polygon,
 11207  except that the main work is done only in the halfplane obtained from
 11208  the three starting directions $(0,-1)$, $(1,0)$,~$(0,1)$. Since the ellipse
 11209  has circular symmetry, we use the fact that the last half of the polygon
 11210  is simply the negative of the first half. Furthermore, we need to compute only
 11211  one quarter of the polygon if the ellipse has axis symmetry.
 11212  
 11213  @p function make_ellipse(@!major_axis,@!minor_axis:scaled;
 11214    @!theta:angle):pointer;
 11215  label done,done1,found;
 11216  var @!p,@!q,@!r,@!s:pointer; {for list manipulation}
 11217  @!h:pointer; {head of the constructed knot list}
 11218  @!alpha,@!beta,@!gamma,@!delta:integer; {special points}
 11219  @!c,@!d:integer; {class numbers}
 11220  @!u,@!v:integer; {directions}
 11221  @!symmetric:boolean; {should the result be symmetric about the axes?}
 11222  begin @<Initialize the ellipse data structure by beginning with
 11223    directions $(0,-1)$, $(1,0)$, $(0,1)$@>;
 11224  @<Interpolate new vertices in the ellipse data structure until
 11225    improvement is impossible@>;
 11226  if symmetric then
 11227    @<Complete the half ellipse by reflecting the quarter already computed@>;
 11228  @<Complete the ellipse by copying the negative of the half already computed@>;
 11229  make_ellipse:=h;
 11230  end;
 11231  
 11232  @ A special data structure is used only with |make_ellipse|: The
 11233  |right_x|, |left_x|, |right_y|, and |left_y| fields of knot nodes
 11234  are renamed |right_u|, |left_v|, |right_class|, and |left_length|,
 11235  in order to store information that simplifies the necessary computations.
 11236  
 11237  If |p| and |q| are consecutive knots in this data structure, the
 11238  |x_coord| and |y_coord| fields of |p| and~|q| contain current vertices
 11239  of the polygon; their values are integer multiples
 11240  of |half_unit|. Both of these vertices belong to equivalence class
 11241  |right_class(p)| with respect to the direction
 11242  $\bigl($|right_u(p),left_v(q)|$\bigr)$. The number of points of this class
 11243  on the line from vertex~|p| to vertex~|q| is |1+left_length(q)|.
 11244  In particular, |left_length(q)=0| means that |x_coord(p)=x_coord(q)|
 11245  and |y_coord(p)=y_coord(q)|; such duplicate vertices will be
 11246  discarded during the course of the algorithm.
 11247  
 11248  The contents of |right_u(p)| and |left_v(q)| are integer multiples
 11249  of |half_unit|, just like the coordinate fields. Hence, for example,
 11250  the point $\bigl($|x_coord(p)-left_v(q),y_coord(p)+right_u(p)|$\bigr)$
 11251  also belongs to class number |right_class(p)|. This point is one
 11252  step closer to the vertex in node~|q|; it equals that vertex
 11253  if and only if |left_length(q)=1|.
 11254  
 11255  The |left_type| and |right_type| fields are not used, but |link|
 11256  has its normal meaning.
 11257  
 11258  To start the process, we create four nodes for the three directions
 11259  $(0,-1)$, $(1,0)$, and $(0,1)$. The corresponding vertices are
 11260  $(-\alpha,-\beta)$, $(\gamma,-\beta)$, $(\gamma,\beta)$, and
 11261  $(\alpha,\beta)$, where $(\alpha,\beta)$ is a half-integer approximation
 11262  to where the ellipse rises highest above the $x$-axis, and where
 11263  $\gamma$ is a half-integer approximation to the maximum $x$~coordinate
 11264  of the ellipse. The fourth of these nodes is not actually calculated
 11265  if the ellipse has axis symmetry.
 11266  
 11267  @d right_u==right_x {|u| value for a pen edge}
 11268  @d left_v==left_x {|v| value for a pen edge}
 11269  @d right_class==right_y {equivalence class number of a pen edge}
 11270  @d left_length==left_y {length of a pen edge}
 11271  
 11272  @<Initialize the ellipse data structure...@>=
 11273  @<Calculate integers $\alpha$, $\beta$, $\gamma$ for the vertex
 11274    coordinates@>;
 11275  p:=get_node(knot_node_size); q:=get_node(knot_node_size);
 11276  r:=get_node(knot_node_size);
 11277  if symmetric then s:=null@+else s:=get_node(knot_node_size);
 11278  h:=p; link(p):=q; link(q):=r; link(r):=s; {|s=null| or |link(s)=null|}
 11279  @<Revise the values of $\alpha$, $\beta$, $\gamma$, if necessary,
 11280    so that degenerate lines of length zero will not be obtained@>;
 11281  x_coord(p):=-alpha*half_unit;
 11282  y_coord(p):=-beta*half_unit;
 11283  x_coord(q):=gamma*half_unit;@/
 11284  y_coord(q):=y_coord(p); x_coord(r):=x_coord(q);@/
 11285  right_u(p):=0; left_v(q):=-half_unit;@/
 11286  right_u(q):=half_unit; left_v(r):=0;@/
 11287  right_u(r):=0;
 11288  right_class(p):=beta; right_class(q):=gamma; right_class(r):=beta;@/
 11289  left_length(q):=gamma+alpha;
 11290  if symmetric then
 11291    begin y_coord(r):=0; left_length(r):=beta;
 11292    end
 11293  else  begin y_coord(r):=-y_coord(p); left_length(r):=beta+beta;@/
 11294    x_coord(s):=-x_coord(p); y_coord(s):=y_coord(r);@/
 11295    left_v(s):=half_unit; left_length(s):=gamma-alpha;
 11296    end
 11297  
 11298  @ One of the important invariants of the pen data structure is that
 11299  the points are distinct. We may need to correct the pen specification
 11300  in order to avoid this. (The result of \&{pencircle} will always be at
 11301  least one pixel wide and one pixel tall, although \&{makepen} is
 11302  capable of producing smaller pens.)
 11303  
 11304  @<Revise the values of $\alpha$, $\beta$, $\gamma$, if necessary...@>=
 11305  if beta=0 then beta:=1;
 11306  if gamma=0 then gamma:=1;
 11307  if gamma<=abs(alpha) then
 11308    if alpha>0 then alpha:=gamma-1
 11309    else alpha:=1-gamma
 11310  
 11311  @ If $a$ and $b$ are the semi-major and semi-minor axes,
 11312  the given ellipse rises highest above the $x$-axis at the point
 11313  $\bigl((a^2-b^2)\sin\theta\cos\theta/\rho\bigr)+i\rho$, where
 11314  $\rho=\sqrt{(a\sin\theta)^2+(b\cos\theta)^2}$. It reaches
 11315  furthest to the right of~the $y$-axis at the point
 11316  $\sigma+i(a^2-b^2)\sin\theta\cos\theta/\sigma$, where
 11317  $\sigma=\sqrt{(a\cos\theta)^2+(b\sin\theta)^2}$.
 11318  
 11319  @<Calculate integers $\alpha$, $\beta$, $\gamma$...@>=
 11320  if (major_axis=minor_axis)or(theta mod ninety_deg=0) then
 11321    begin symmetric:=true; alpha:=0;
 11322    if odd(theta div ninety_deg) then
 11323      begin beta:=major_axis; gamma:=minor_axis;
 11324      n_sin:=fraction_one; n_cos:=0; {|n_sin| and |n_cos| are used later}
 11325      end
 11326    else  begin beta:=minor_axis; gamma:=major_axis; theta:=0;
 11327      end; {|n_sin| and |n_cos| aren't needed in this case}
 11328    end
 11329  else  begin symmetric:=false;
 11330    n_sin_cos(theta); {set up $|n_sin|=\sin\theta$ and $|n_cos|=\cos\theta$}
 11331    gamma:=take_fraction(major_axis,n_sin);
 11332    delta:=take_fraction(minor_axis,n_cos);
 11333    beta:=pyth_add(gamma,delta);
 11334    alpha:=take_fraction(take_fraction(major_axis,
 11335        make_fraction(gamma,beta)),n_cos)@|
 11336      -take_fraction(take_fraction(minor_axis,
 11337        make_fraction(delta,beta)),n_sin);
 11338    alpha:=(alpha+half_unit) div unity;
 11339    gamma:=pyth_add(take_fraction(major_axis,n_cos),
 11340      take_fraction(minor_axis,n_sin));
 11341    end;
 11342  beta:=(beta+half_unit) div unity;
 11343  gamma:=(gamma+half_unit) div unity
 11344  
 11345  @ Now |p|, |q|, and |r| march through the list, always representing
 11346  three consecutive vertices and two consecutive slope directions.
 11347  When a new slope is interpolated, we back up slightly, until
 11348  further refinement is impossible; then we march forward again.
 11349  The somewhat magical operations performed in this part of the
 11350  algorithm are justified by the theory sketched earlier.
 11351  Complications arise only from the need to keep zero-length lines
 11352  out of the final data structure.
 11353  
 11354  @<Interpolate new vertices in the ellipse data structure...@>=
 11355  loop@+  begin u:=right_u(p)+right_u(q); v:=left_v(q)+left_v(r);
 11356    c:=right_class(p)+right_class(q);@/
 11357    @<Compute the distance |d| from class~0 to the edge of the ellipse
 11358      in direction |(u,v)|, times $\psqrt{u^2+v^2}$,
 11359      rounded to the nearest integer@>;
 11360    delta:=c-d; {we want to move |delta| steps back
 11361        from the intersection vertex~|q|}
 11362    if delta>0 then
 11363      begin if delta>left_length(r) then delta:=left_length(r);
 11364      if delta>=left_length(q) then
 11365        @<Remove the line from |p| to |q|,
 11366          and adjust vertex~|q| to introduce a new line@>
 11367      else @<Insert a new line for direction |(u,v)| between |p| and~|q|@>;
 11368      end
 11369    else p:=q;
 11370    @<Move to the next remaining triple |(p,q,r)|, removing and skipping past
 11371      zero-length lines that might be present; |goto done| if all
 11372      triples have been processed@>;
 11373    end;
 11374  done:
 11375  
 11376  @ The appearance of a zero-length line means that we should advance |p|
 11377  past it. We must not try to straddle a missing direction, because the
 11378  algorithm works only on consecutive pairs of directions.
 11379  
 11380  @<Move to the next remaining triple |(p,q,r)|...@>=
 11381  loop@+  begin q:=link(p);
 11382    if q=null then goto done;
 11383    if left_length(q)=0 then
 11384      begin link(p):=link(q); right_class(p):=right_class(q);
 11385      right_u(p):=right_u(q); free_node(q,knot_node_size);
 11386      end
 11387    else  begin r:=link(q);
 11388      if r=null then goto done;
 11389      if left_length(r)=0 then
 11390        begin link(p):=r; free_node(q,knot_node_size); p:=r;
 11391        end
 11392      else goto found;
 11393      end;
 11394    end;
 11395  found:
 11396  
 11397  @ The `\&{div} 8' near the end of this step comes from
 11398  the fact that |delta| is scaled by~$2^{15}$ and $d$~by~$2^{16}$,
 11399  while |take_fraction| removes a scale factor of~$2^{28}$.
 11400  We also make sure that $d\G\max(\vert u\vert,\vert v\vert)$, so that
 11401  the pen will always include a circular pen of diameter~1 as a subset;
 11402  then it won't be possible to get disconnected path envelopes.
 11403  
 11404  @<Compute the distance |d| from class~0 to the edge of the ellipse...@>=
 11405  delta:=pyth_add(u,v);
 11406  if major_axis=minor_axis then d:=major_axis {circles are easy}
 11407  else  begin if theta=0 then
 11408      begin alpha:=u; beta:=v;
 11409      end
 11410    else  begin alpha:=take_fraction(u,n_cos)+take_fraction(v,n_sin);
 11411      beta:=take_fraction(v,n_cos)-take_fraction(u,n_sin);
 11412      end;
 11413    alpha:=make_fraction(alpha,delta);
 11414    beta:=make_fraction(beta,delta);
 11415    d:=pyth_add(take_fraction(major_axis,alpha),
 11416      take_fraction(minor_axis,beta));
 11417    end;
 11418  alpha:=abs(u); beta:=abs(v);
 11419  if alpha<beta then
 11420    begin alpha:=abs(v); beta:=abs(u);
 11421    end; {now $\alpha=\max(\vert u\vert,\vert v\vert)$,
 11422        $\beta=\min(\vert u\vert,\vert v\vert)$}
 11423  if internal[fillin]<>0 then
 11424    d:=d-take_fraction(internal[fillin],make_fraction(beta+beta,delta));
 11425  d:=take_fraction((d+4) div 8,delta); alpha:=alpha div half_unit;
 11426  if d<alpha then d:=alpha
 11427  
 11428  @ At this point there's a line of length |<=delta| from vertex~|p|
 11429  to vertex~|q|, orthogonal to direction $\bigl($|right_u(p),left_v(q)|$\bigr)$;
 11430  and there's a line of length |>=delta| from vertex~|q|
 11431  to vertex~|r|, orthogonal to direction $\bigl($|right_u(q),left_v(r)|$\bigr)$.
 11432  The best line to direction $(u,v)$ should replace the line from
 11433  |p| to~|q|; this new line will have the same length as the old.
 11434  
 11435  @<Remove the line from |p| to |q|...@>=
 11436  begin delta:=left_length(q);@/
 11437  right_class(p):=c-delta; right_u(p):=u; left_v(q):=v;@/
 11438  x_coord(q):=x_coord(q)-delta*left_v(r);
 11439  y_coord(q):=y_coord(q)+delta*right_u(q);@/
 11440  left_length(r):=left_length(r)-delta;
 11441  end
 11442  
 11443  @ Here is the main case, now that we have dealt with the exception:
 11444  We insert a new line of length |delta| for direction |(u,v)|, decreasing
 11445  each of the adjacent lines by |delta| steps.
 11446  
 11447  @<Insert a new line for direction |(u,v)| between |p| and~|q|@>=
 11448  begin s:=get_node(knot_node_size); link(p):=s; link(s):=q;@/
 11449  x_coord(s):=x_coord(q)+delta*left_v(q);
 11450  y_coord(s):=y_coord(q)-delta*right_u(p);@/
 11451  x_coord(q):=x_coord(q)-delta*left_v(r);
 11452  y_coord(q):=y_coord(q)+delta*right_u(q);@/
 11453  left_v(s):=left_v(q); right_u(s):=u; left_v(q):=v;@/
 11454  right_class(s):=c-delta;@/
 11455  left_length(s):=left_length(q)-delta; left_length(q):=delta;
 11456  left_length(r):=left_length(r)-delta;
 11457  end
 11458  
 11459  @ Only the coordinates need to be copied, not the class numbers and other stuff.
 11460  At this point either |link(p)| or |link(link(p))| is |null|.
 11461  
 11462  @<Complete the half ellipse...@>=
 11463  begin s:=null; q:=h;
 11464  loop@+  begin r:=get_node(knot_node_size); link(r):=s; s:=r;@/
 11465    x_coord(s):=x_coord(q); y_coord(s):=-y_coord(q);
 11466    if q=p then goto done1;
 11467    q:=link(q);
 11468    if y_coord(q)=0 then goto done1;
 11469    end;
 11470  done1: if (link(p)<>null) then free_node(link(p),knot_node_size);
 11471  link(p):=s; beta:=-y_coord(h);
 11472  while y_coord(p)<>beta do p:=link(p);
 11473  q:=link(p);
 11474  end
 11475  
 11476  @ Now we use a somewhat tricky fact: The pointer |q| will be null if and
 11477  only if the line for the final direction $(0,1)$ has been removed. If
 11478  that line still survives, it should be combined with a possibly
 11479  surviving line in the initial direction $(0,-1)$.
 11480  
 11481  @<Complete the ellipse by copying...@>=
 11482  if q<>null then
 11483    begin if right_u(h)=0 then
 11484      begin p:=h; h:=link(h); free_node(p,knot_node_size);@/
 11485      x_coord(q):=-x_coord(h);
 11486      end;
 11487    p:=q;
 11488    end
 11489  else q:=p;
 11490  r:=link(h); {now |p=q|, |x_coord(p)=-x_coord(h)|, |y_coord(p)=-y_coord(h)|}
 11491  repeat s:=get_node(knot_node_size); link(p):=s; p:=s;@/
 11492  x_coord(p):=-x_coord(r); y_coord(p):=-y_coord(r); r:=link(r);
 11493  until r=q;
 11494  link(p):=h
 11495  
 11496  @* \[26] Direction and intersection times.
 11497  A path of length $n$ is defined parametrically by functions $x(t)$ and
 11498  $y(t)$, for |0<=t<=n|; we can regard $t$ as the ``time'' at which the path
 11499  reaches the point $\bigl(x(t),y(t)\bigr)$.  In this section of the program
 11500  we shall consider operations that determine special times associated with
 11501  given paths: the first time that a path travels in a given direction, and
 11502  a pair of times at which two paths cross each other.
 11503  
 11504  @ Let's start with the easier task. The function |find_direction_time| is
 11505  given a direction |(x,y)| and a path starting at~|h|. If the path never
 11506  travels in direction |(x,y)|, the direction time will be~|-1|; otherwise
 11507  it will be nonnegative.
 11508  
 11509  Certain anomalous cases can arise: If |(x,y)=(0,0)|, so that the given
 11510  direction is undefined, the direction time will be~0. If $\bigl(x'(t),
 11511  y'(t)\bigr)=(0,0)$, so that the path direction is undefined, it will be
 11512  assumed to match any given direction at time~|t|.
 11513  
 11514  The routine solves this problem in nondegenerate cases by rotating the path
 11515  and the given direction so that |(x,y)=(1,0)|; i.e., the main task will be
 11516  to find when a given path first travels ``due east.''
 11517  
 11518  @p function find_direction_time(@!x,@!y:scaled;@!h:pointer):scaled;
 11519  label exit,found,not_found,done;
 11520  var @!max:scaled; {$\max\bigl(\vert x\vert,\vert y\vert\bigr)$}
 11521  @!p,@!q:pointer; {for list traversal}
 11522  @!n:scaled; {the direction time at knot |p|}
 11523  @!tt:scaled; {the direction time within a cubic}
 11524  @<Other local variables for |find_direction_time|@>@;
 11525  begin @<Normalize the given direction for better accuracy;
 11526    but |return| with zero result if it's zero@>;
 11527  n:=0; p:=h;
 11528  loop@+  begin if right_type(p)=endpoint then goto not_found;
 11529    q:=link(p);
 11530    @<Rotate the cubic between |p| and |q|; then
 11531      |goto found| if the rotated cubic travels due east at some time |tt|;
 11532      but |goto not_found| if an entire cyclic path has been traversed@>;
 11533    p:=q; n:=n+unity;
 11534    end;
 11535  not_found: find_direction_time:=-unity; return;
 11536  found: find_direction_time:=n+tt;
 11537  exit:end;
 11538  
 11539  @ @<Normalize the given direction for better accuracy...@>=
 11540  if abs(x)<abs(y) then
 11541    begin x:=make_fraction(x,abs(y));
 11542    if y>0 then y:=fraction_one@+else y:=-fraction_one;
 11543    end
 11544  else if x=0 then
 11545    begin find_direction_time:=0; return;
 11546    end
 11547  else  begin y:=make_fraction(y,abs(x));
 11548    if x>0 then x:=fraction_one@+else x:=-fraction_one;
 11549    end
 11550  
 11551  @ Since we're interested in the tangent directions, we work with the
 11552  derivative $${1\over3}B'(x_0,x_1,x_2,x_3;t)=
 11553  B(x_1-x_0,x_2-x_1,x_3-x_2;t)$$ instead of
 11554  $B(x_0,x_1,x_2,x_3;t)$ itself. The derived coefficients are also scaled up
 11555  in order to achieve better accuracy.
 11556  
 11557  The given path may turn abruptly at a knot, and it might pass the critical
 11558  tangent direction at such a time. Therefore we remember the direction |phi|
 11559  in which the previous rotated cubic was traveling. (The value of |phi| will be
 11560  undefined on the first cubic, i.e., when |n=0|.)
 11561  
 11562  @<Rotate the cubic between |p| and |q|; then...@>=
 11563  tt:=0;
 11564  @<Set local variables |x1,x2,x3| and |y1,y2,y3| to multiples of the control
 11565    points of the rotated derivatives@>;
 11566  if y1=0 then if x1>=0 then goto found;
 11567  if n>0 then
 11568    begin @<Exit to |found| if an eastward direction occurs at knot |p|@>;
 11569    if p=h then goto not_found;
 11570    end;
 11571  if (x3<>0)or(y3<>0) then phi:=n_arg(x3,y3);
 11572  @<Exit to |found| if the curve whose derivatives are specified by
 11573    |x1,x2,x3,y1,y2,y3| travels eastward at some time~|tt|@>
 11574  
 11575  @ @<Other local variables for |find_direction_time|@>=
 11576  @!x1,@!x2,@!x3,@!y1,@!y2,@!y3:scaled; {multiples of rotated derivatives}
 11577  @!theta,@!phi:angle; {angles of exit and entry at a knot}
 11578  @!t:fraction; {temp storage}
 11579  
 11580  @ @<Set local variables |x1,x2,x3| and |y1,y2,y3| to multiples...@>=
 11581  x1:=right_x(p)-x_coord(p); x2:=left_x(q)-right_x(p);
 11582  x3:=x_coord(q)-left_x(q);@/
 11583  y1:=right_y(p)-y_coord(p); y2:=left_y(q)-right_y(p);
 11584  y3:=y_coord(q)-left_y(q);@/
 11585  max:=abs(x1);
 11586  if abs(x2)>max then max:=abs(x2);
 11587  if abs(x3)>max then max:=abs(x3);
 11588  if abs(y1)>max then max:=abs(y1);
 11589  if abs(y2)>max then max:=abs(y2);
 11590  if abs(y3)>max then max:=abs(y3);
 11591  if max=0 then goto found;
 11592  while max<fraction_half do
 11593    begin double(max); double(x1); double(x2); double(x3);
 11594    double(y1); double(y2); double(y3);
 11595    end;
 11596  t:=x1; x1:=take_fraction(x1,x)+take_fraction(y1,y);
 11597  y1:=take_fraction(y1,x)-take_fraction(t,y);@/
 11598  t:=x2; x2:=take_fraction(x2,x)+take_fraction(y2,y);
 11599  y2:=take_fraction(y2,x)-take_fraction(t,y);@/
 11600  t:=x3; x3:=take_fraction(x3,x)+take_fraction(y3,y);
 11601  y3:=take_fraction(y3,x)-take_fraction(t,y)
 11602  
 11603  @ @<Exit to |found| if an eastward direction occurs at knot |p|@>=
 11604  theta:=n_arg(x1,y1);
 11605  if theta>=0 then if phi<=0 then if phi>=theta-one_eighty_deg then goto found;
 11606  if theta<=0 then if phi>=0 then if phi<=theta+one_eighty_deg then goto found
 11607  
 11608  @ In this step we want to use the |crossing_point| routine to find the
 11609  roots of the quadratic equation $B(y_1,y_2,y_3;t)=0$.
 11610  Several complications arise: If the quadratic equation has a double root,
 11611  the curve never crosses zero, and |crossing_point| will find nothing;
 11612  this case occurs iff $y_1y_3=y_2^2$ and $y_1y_2<0$. If the quadratic
 11613  equation has simple roots, or only one root, we may have to negate it
 11614  so that $B(y_1,y_2,y_3;t)$ crosses from positive to negative at its first root.
 11615  And finally, we need to do special things if $B(y_1,y_2,y_3;t)$ is
 11616  identically zero.
 11617  
 11618  @ @<Exit to |found| if the curve whose derivatives are specified by...@>=
 11619  if x1<0 then if x2<0 then if x3<0 then goto done;
 11620  if ab_vs_cd(y1,y3,y2,y2)=0 then
 11621    @<Handle the test for eastward directions when $y_1y_3=y_2^2$;
 11622      either |goto found| or |goto done|@>;
 11623  if y1<=0 then
 11624    if y1<0 then
 11625      begin y1:=-y1; y2:=-y2; y3:=-y3;
 11626      end
 11627    else if y2>0 then
 11628      begin y2:=-y2; y3:=-y3;
 11629      end;
 11630  @<Check the places where $B(y_1,y_2,y_3;t)=0$ to see if
 11631    $B(x_1,x_2,x_3;t)\ge0$@>;
 11632  done:
 11633  
 11634  @ The quadratic polynomial $B(y_1,y_2,y_3;t)$ begins |>=0| and has at most
 11635  two roots, because we know that it isn't identically zero.
 11636  
 11637  It must be admitted that the |crossing_point| routine is not perfectly accurate;
 11638  rounding errors might cause it to find a root when $y_1y_3>y_2^2$, or to
 11639  miss the roots when $y_1y_3<y_2^2$. The rotation process is itself
 11640  subject to rounding errors. Yet this code optimistically tries to
 11641  do the right thing.
 11642  
 11643  @d we_found_it==begin tt:=(t+@'4000) div @'10000; goto found;
 11644    end
 11645  
 11646  @<Check the places where $B(y_1,y_2,y_3;t)=0$...@>=
 11647  t:=crossing_point(y1,y2,y3);
 11648  if t>fraction_one then goto done;
 11649  y2:=t_of_the_way(y2)(y3);
 11650  x1:=t_of_the_way(x1)(x2);
 11651  x2:=t_of_the_way(x2)(x3);
 11652  x1:=t_of_the_way(x1)(x2);
 11653  if x1>=0 then we_found_it;
 11654  if y2>0 then y2:=0;
 11655  tt:=t; t:=crossing_point(0,-y2,-y3);
 11656  if t>fraction_one then goto done;
 11657  x1:=t_of_the_way(x1)(x2);
 11658  x2:=t_of_the_way(x2)(x3);
 11659  if t_of_the_way(x1)(x2)>=0 then
 11660    begin t:=t_of_the_way(tt)(fraction_one); we_found_it;
 11661    end
 11662  
 11663  @ @<Handle the test for eastward directions when $y_1y_3=y_2^2$;
 11664      either |goto found| or |goto done|@>=
 11665  begin if ab_vs_cd(y1,y2,0,0)<0 then
 11666    begin t:=make_fraction(y1,y1-y2);
 11667    x1:=t_of_the_way(x1)(x2);
 11668    x2:=t_of_the_way(x2)(x3);
 11669    if t_of_the_way(x1)(x2)>=0 then we_found_it;
 11670    end
 11671  else if y3=0 then
 11672    if y1=0 then
 11673      @<Exit to |found| if the derivative $B(x_1,x_2,x_3;t)$ becomes |>=0|@>
 11674    else if x3>=0 then
 11675      begin tt:=unity; goto found;
 11676      end;
 11677  goto done;
 11678  end
 11679  
 11680  @ At this point we know that the derivative of |y(t)| is identically zero,
 11681  and that |x1<0|; but either |x2>=0| or |x3>=0|, so there's some hope of
 11682  traveling east.
 11683  
 11684  @<Exit to |found| if the derivative $B(x_1,x_2,x_3;t)$ becomes |>=0|...@>=
 11685  begin t:=crossing_point(-x1,-x2,-x3);
 11686  if t<=fraction_one then we_found_it;
 11687  if ab_vs_cd(x1,x3,x2,x2)<=0 then
 11688    begin t:=make_fraction(x1,x1-x2); we_found_it;
 11689    end;
 11690  end
 11691  
 11692  @ The intersection of two cubics can be found by an interesting variant
 11693  of the general bisection scheme described in the introduction to |make_moves|.\
 11694  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)$,
 11695  we wish to find a pair of times $(t_1,t_2)$ such that $w(t_1)=z(t_2)$,
 11696  if an intersection exists. First we find the smallest rectangle that
 11697  encloses the points $\{w_0,w_1,w_2,w_3\}$ and check that it overlaps
 11698  the smallest rectangle that encloses
 11699  $\{z_0,z_1,z_2,z_3\}$; if not, the cubics certainly don't intersect.
 11700  But if the rectangles do overlap, we bisect the intervals, getting
 11701  new cubics $w'$ and~$w''$, $z'$~and~$z''$; the intersection routine first
 11702  tries for an intersection between $w'$ and~$z'$, then (if unsuccessful)
 11703  between $w'$ and~$z''$, then (if still unsuccessful) between $w''$ and~$z'$,
 11704  finally (if thrice unsuccessful) between $w''$ and~$z''$. After $l$~successful
 11705  levels of bisection we will have determined the intersection times $t_1$
 11706  and~$t_2$ to $l$~bits of accuracy.
 11707  
 11708  \def\submin{_{\rm min}} \def\submax{_{\rm max}}
 11709  As before, it is better to work with the numbers $W_k=2^l(w_k-w_{k-1})$
 11710  and $Z_k=2^l(z_k-z_{k-1})$ rather than the coefficients $w_k$ and $z_k$
 11711  themselves. We also need one other quantity, $\Delta=2^l(w_0-z_0)$,
 11712  to determine when the enclosing rectangles overlap. Here's why:
 11713  The $x$~coordinates of~$w(t)$ are between $u\submin$ and $u\submax$,
 11714  and the $x$~coordinates of~$z(t)$ are between $x\submin$ and $x\submax$,
 11715  if we write $w_k=(u_k,v_k)$ and $z_k=(x_k,y_k)$ and $u\submin=
 11716  \min(u_0,u_1,u_2,u_3)$, etc. These intervals of $x$~coordinates
 11717  overlap if and only if $u\submin\L x\submax$ and
 11718  $x\submin\L u\submax$. Letting
 11719  $$U\submin=\min(0,U_1,U_1+U_2,U_1+U_2+U_3),\;
 11720    U\submax=\max(0,U_1,U_1+U_2,U_1+U_2+U_3),$$
 11721  we have $2^lu\submin=2^lu_0+U\submin$, etc.; the condition for overlap
 11722  reduces to
 11723  $$X\submin-U\submax\L 2^l(u_0-x_0)\L X\submax-U\submin.$$
 11724  Thus we want to maintain the quantity $2^l(u_0-x_0)$; similarly,
 11725  the quantity $2^l(v_0-y_0)$ accounts for the $y$~coordinates. The
 11726  coordinates of $\Delta=2^l(w_0-z_0)$ must stay bounded as $l$ increases,
 11727  because of the overlap condition; i.e., we know that $X\submin$,
 11728  $X\submax$, and their relatives are bounded, hence $X\submax-
 11729  U\submin$ and $X\submin-U\submax$ are bounded.
 11730  
 11731  @ Incidentally, if the given cubics intersect more than once, the process
 11732  just sketched will not necessarily find the lexicographically smallest pair
 11733  $(t_1,t_2)$. The solution actually obtained will be smallest in ``shuffled
 11734  order''; i.e., if $t_1=(.a_1a_2\ldots a_{16})_2$ and
 11735  $t_2=(.b_1b_2\ldots b_{16})_2$, then we will minimize
 11736  $a_1b_1a_2b_2\ldots a_{16}b_{16}$, not
 11737  $a_1a_2\ldots a_{16}b_1b_2\ldots b_{16}$.
 11738  Shuffled order agrees with lexicographic order if all pairs of solutions
 11739  $(t_1,t_2)$ and $(t_1',t_2')$ have the property that $t_1<t_1'$ iff
 11740  $t_2<t_2'$; but in general, lexicographic order can be quite different,
 11741  and the bisection algorithm would be substantially less efficient if it were
 11742  constrained by lexicographic order.
 11743  
 11744  For example, suppose that an overlap has been found for $l=3$ and
 11745  $(t_1,t_2)= (.101,.011)$ in binary, but that no overlap is produced by
 11746  either of the alternatives $(.1010,.0110)$, $(.1010,.0111)$ at level~4.
 11747  Then there is probably an intersection in one of the subintervals
 11748  $(.1011,.011x)$; but lexicographic order would require us to explore
 11749  $(.1010,.1xxx)$ and $(.1011,.00xx)$ and $(.1011,.010x)$ first. We wouldn't
 11750  want to store all of the subdivision data for the second path, so the
 11751  subdivisions would have to be regenerated many times. Such inefficiencies
 11752  would be associated with every `1' in the binary representation of~$t_1$.
 11753  
 11754  @ The subdivision process introduces rounding errors, hence we need to
 11755  make a more liberal test for overlap. It is not hard to show that the
 11756  computed values of $U_i$ differ from the truth by at most~$l$, on
 11757  level~$l$, hence $U\submin$ and $U\submax$ will be at most $3l$ in error.
 11758  If $\beta$ is an upper bound on the absolute error in the computed
 11759  components of $\Delta=(|delx|,|dely|)$ on level~$l$, we will replace
 11760  the test `$X\submin-U\submax\L|delx|$' by the more liberal test
 11761  `$X\submin-U\submax\L|delx|+|tol|$', where $|tol|=6l+\beta$.
 11762  
 11763  More accuracy is obtained if we try the algorithm first with |tol=0|;
 11764  the more liberal tolerance is used only if an exact approach fails.
 11765  It is convenient to do this double-take by letting `3' in the preceding
 11766  paragraph be a parameter, which is first 0, then 3.
 11767  
 11768  @<Glob...@>=
 11769  @!tol_step:0..6; {either 0 or 3, usually}
 11770  
 11771  @ We shall use an explicit stack to implement the recursive bisection
 11772  method described above. In fact, the |bisect_stack| array is available for
 11773  this purpose. It will contain numerous 5-word packets like
 11774  $(U_1,U_2,U_3,U\submin,U\submax)$, as well as 20-word packets comprising
 11775  the 5-word packets for $U$, $V$, $X$, and~$Y$.
 11776  
 11777  The following macros define the allocation of stack positions to
 11778  the quantities needed for bisection-intersection.
 11779  
 11780  @d stack_1(#)==bisect_stack[#] {$U_1$, $V_1$, $X_1$, or $Y_1$}
 11781  @d stack_2(#)==bisect_stack[#+1] {$U_2$, $V_2$, $X_2$, or $Y_2$}
 11782  @d stack_3(#)==bisect_stack[#+2] {$U_3$, $V_3$, $X_3$, or $Y_3$}
 11783  @d stack_min(#)==bisect_stack[#+3]
 11784    {$U\submin$, $V\submin$, $X\submin$, or $Y\submin$}
 11785  @d stack_max(#)==bisect_stack[#+4]
 11786    {$U\submax$, $V\submax$, $X\submax$, or $Y\submax$}
 11787  @d int_packets=20 {number of words to represent $U_k$, $V_k$, $X_k$, and $Y_k$}
 11788  @#
 11789  @d u_packet(#)==#-5
 11790  @d v_packet(#)==#-10
 11791  @d x_packet(#)==#-15
 11792  @d y_packet(#)==#-20
 11793  @d l_packets==bisect_ptr-int_packets
 11794  @d r_packets==bisect_ptr
 11795  @d ul_packet==u_packet(l_packets) {base of $U'_k$ variables}
 11796  @d vl_packet==v_packet(l_packets) {base of $V'_k$ variables}
 11797  @d xl_packet==x_packet(l_packets) {base of $X'_k$ variables}
 11798  @d yl_packet==y_packet(l_packets) {base of $Y'_k$ variables}
 11799  @d ur_packet==u_packet(r_packets) {base of $U''_k$ variables}
 11800  @d vr_packet==v_packet(r_packets) {base of $V''_k$ variables}
 11801  @d xr_packet==x_packet(r_packets) {base of $X''_k$ variables}
 11802  @d yr_packet==y_packet(r_packets) {base of $Y''_k$ variables}
 11803  @#
 11804  @d u1l==stack_1(ul_packet) {$U'_1$}
 11805  @d u2l==stack_2(ul_packet) {$U'_2$}
 11806  @d u3l==stack_3(ul_packet) {$U'_3$}
 11807  @d v1l==stack_1(vl_packet) {$V'_1$}
 11808  @d v2l==stack_2(vl_packet) {$V'_2$}
 11809  @d v3l==stack_3(vl_packet) {$V'_3$}
 11810  @d x1l==stack_1(xl_packet) {$X'_1$}
 11811  @d x2l==stack_2(xl_packet) {$X'_2$}
 11812  @d x3l==stack_3(xl_packet) {$X'_3$}
 11813  @d y1l==stack_1(yl_packet) {$Y'_1$}
 11814  @d y2l==stack_2(yl_packet) {$Y'_2$}
 11815  @d y3l==stack_3(yl_packet) {$Y'_3$}
 11816  @d u1r==stack_1(ur_packet) {$U''_1$}
 11817  @d u2r==stack_2(ur_packet) {$U''_2$}
 11818  @d u3r==stack_3(ur_packet) {$U''_3$}
 11819  @d v1r==stack_1(vr_packet) {$V''_1$}
 11820  @d v2r==stack_2(vr_packet) {$V''_2$}
 11821  @d v3r==stack_3(vr_packet) {$V''_3$}
 11822  @d x1r==stack_1(xr_packet) {$X''_1$}
 11823  @d x2r==stack_2(xr_packet) {$X''_2$}
 11824  @d x3r==stack_3(xr_packet) {$X''_3$}
 11825  @d y1r==stack_1(yr_packet) {$Y''_1$}
 11826  @d y2r==stack_2(yr_packet) {$Y''_2$}
 11827  @d y3r==stack_3(yr_packet) {$Y''_3$}
 11828  @#
 11829  @d stack_dx==bisect_stack[bisect_ptr] {stacked value of |delx|}
 11830  @d stack_dy==bisect_stack[bisect_ptr+1] {stacked value of |dely|}
 11831  @d stack_tol==bisect_stack[bisect_ptr+2] {stacked value of |tol|}
 11832  @d stack_uv==bisect_stack[bisect_ptr+3] {stacked value of |uv|}
 11833  @d stack_xy==bisect_stack[bisect_ptr+4] {stacked value of |xy|}
 11834  @d int_increment=int_packets+int_packets+5 {number of stack words per level}
 11835  
 11836  @<Check the ``constant''...@>=
 11837  if int_packets+17*int_increment>bistack_size then bad:=32;
 11838  
 11839  @ Computation of the min and max is a tedious but fairly fast sequence of
 11840  instructions; exactly four comparisons are made in each branch.
 11841  
 11842  @d set_min_max(#)==
 11843    if stack_1(#)<0 then
 11844      if stack_3(#)>=0 then
 11845        begin if stack_2(#)<0 then stack_min(#):=stack_1(#)+stack_2(#)
 11846          else stack_min(#):=stack_1(#);
 11847        stack_max(#):=stack_1(#)+stack_2(#)+stack_3(#);
 11848        if stack_max(#)<0 then stack_max(#):=0;
 11849        end
 11850      else  begin stack_min(#):=stack_1(#)+stack_2(#)+stack_3(#);
 11851        if stack_min(#)>stack_1(#) then stack_min(#):=stack_1(#);
 11852        stack_max(#):=stack_1(#)+stack_2(#);
 11853        if stack_max(#)<0 then stack_max(#):=0;
 11854        end
 11855    else if stack_3(#)<=0 then
 11856      begin if stack_2(#)>0 then stack_max(#):=stack_1(#)+stack_2(#)
 11857        else stack_max(#):=stack_1(#);
 11858      stack_min(#):=stack_1(#)+stack_2(#)+stack_3(#);
 11859      if stack_min(#)>0 then stack_min(#):=0;
 11860      end
 11861    else  begin stack_max(#):=stack_1(#)+stack_2(#)+stack_3(#);
 11862      if stack_max(#)<stack_1(#) then stack_max(#):=stack_1(#);
 11863      stack_min(#):=stack_1(#)+stack_2(#);
 11864      if stack_min(#)>0 then stack_min(#):=0;
 11865      end
 11866  
 11867  @ It's convenient to keep the current values of $l$, $t_1$, and $t_2$ in
 11868  the integer form $2^l+2^lt_1$ and $2^l+2^lt_2$. The |cubic_intersection|
 11869  routine uses global variables |cur_t| and |cur_tt| for this purpose;
 11870  after successful completion, |cur_t| and |cur_tt| will contain |unity|
 11871  plus the |scaled| values of $t_1$ and~$t_2$.
 11872  
 11873  The values of |cur_t| and |cur_tt| will be set to zero if |cubic_intersection|
 11874  finds no intersection. The routine gives up and gives an approximate answer
 11875  if it has backtracked
 11876  more than 5000 times (otherwise there are cases where several minutes
 11877  of fruitless computation would be possible).
 11878  
 11879  @d max_patience=5000
 11880  
 11881  @<Glob...@>=
 11882  @!cur_t,@!cur_tt:integer; {controls and results of |cubic_intersection|}
 11883  @!time_to_go:integer; {this many backtracks before giving up}
 11884  @!max_t:integer; {maximum of $2^{l+1}$ so far achieved}
 11885  
 11886  @ The given cubics $B(w_0,w_1,w_2,w_3;t)$ and
 11887  $B(z_0,z_1,z_2,z_3;t)$ are specified in adjacent knot nodes |(p,link(p))|
 11888  and |(pp,link(pp))|, respectively.
 11889  
 11890  @p procedure cubic_intersection(@!p,@!pp:pointer);
 11891  label continue, not_found, exit;
 11892  var @!q,@!qq:pointer; {|link(p)|, |link(pp)|}
 11893  begin time_to_go:=max_patience; max_t:=2;
 11894  @<Initialize for intersections at level zero@>;
 11895  loop@+  begin continue:
 11896    if delx-tol<=stack_max(x_packet(xy))-stack_min(u_packet(uv)) then
 11897     if delx+tol>=stack_min(x_packet(xy))-stack_max(u_packet(uv)) then
 11898     if dely-tol<=stack_max(y_packet(xy))-stack_min(v_packet(uv)) then
 11899     if dely+tol>=stack_min(y_packet(xy))-stack_max(v_packet(uv)) then
 11900      begin if cur_t>=max_t then
 11901        begin if max_t=two then {we've done 17 bisections}
 11902          begin cur_t:=half(cur_t+1); cur_tt:=half(cur_tt+1); return;
 11903          end;
 11904        double(max_t); appr_t:=cur_t; appr_tt:=cur_tt;
 11905        end;
 11906      @<Subdivide for a new level of intersection@>;
 11907      goto continue;
 11908      end;
 11909    if time_to_go>0 then decr(time_to_go)
 11910    else  begin while appr_t<unity do
 11911        begin double(appr_t); double(appr_tt);
 11912        end;
 11913      cur_t:=appr_t; cur_tt:=appr_tt; return;
 11914      end;
 11915    @<Advance to the next pair |(cur_t,cur_tt)|@>;
 11916    end;
 11917  exit:end;
 11918  
 11919  @ The following variables are global, although they are used only by
 11920  |cubic_intersection|, because it is necessary on some machines to
 11921  split |cubic_intersection| up into two procedures.
 11922  
 11923  @<Glob...@>=
 11924  @!delx,@!dely:integer; {the components of $\Delta=2^l(w_0-z_0)$}
 11925  @!tol:integer; {bound on the uncertainty in the overlap test}
 11926  @!uv,@!xy:0..bistack_size; {pointers to the current packets of interest}
 11927  @!three_l:integer; {|tol_step| times the bisection level}
 11928  @!appr_t,@!appr_tt:integer; {best approximations known to the answers}
 11929  
 11930  @ We shall assume that the coordinates are sufficiently non-extreme that
 11931  integer overflow will not occur.
 11932  @^overflow in arithmetic@>
 11933  
 11934  @<Initialize for intersections at level zero@>=
 11935  q:=link(p); qq:=link(pp); bisect_ptr:=int_packets;@/
 11936  u1r:=right_x(p)-x_coord(p); u2r:=left_x(q)-right_x(p);
 11937  u3r:=x_coord(q)-left_x(q); set_min_max(ur_packet);@/
 11938  v1r:=right_y(p)-y_coord(p); v2r:=left_y(q)-right_y(p);
 11939  v3r:=y_coord(q)-left_y(q); set_min_max(vr_packet);@/
 11940  x1r:=right_x(pp)-x_coord(pp); x2r:=left_x(qq)-right_x(pp);
 11941  x3r:=x_coord(qq)-left_x(qq); set_min_max(xr_packet);@/
 11942  y1r:=right_y(pp)-y_coord(pp); y2r:=left_y(qq)-right_y(pp);
 11943  y3r:=y_coord(qq)-left_y(qq); set_min_max(yr_packet);@/
 11944  delx:=x_coord(p)-x_coord(pp); dely:=y_coord(p)-y_coord(pp);@/
 11945  tol:=0; uv:=r_packets; xy:=r_packets; three_l:=0; cur_t:=1; cur_tt:=1
 11946  
 11947  @ @<Subdivide for a new level of intersection@>=
 11948  stack_dx:=delx; stack_dy:=dely; stack_tol:=tol; stack_uv:=uv; stack_xy:=xy;
 11949  bisect_ptr:=bisect_ptr+int_increment;@/
 11950  double(cur_t); double(cur_tt);@/
 11951  u1l:=stack_1(u_packet(uv)); u3r:=stack_3(u_packet(uv));
 11952  u2l:=half(u1l+stack_2(u_packet(uv)));
 11953  u2r:=half(u3r+stack_2(u_packet(uv)));
 11954  u3l:=half(u2l+u2r); u1r:=u3l;
 11955  set_min_max(ul_packet); set_min_max(ur_packet);@/
 11956  v1l:=stack_1(v_packet(uv)); v3r:=stack_3(v_packet(uv));
 11957  v2l:=half(v1l+stack_2(v_packet(uv)));
 11958  v2r:=half(v3r+stack_2(v_packet(uv)));
 11959  v3l:=half(v2l+v2r); v1r:=v3l;
 11960  set_min_max(vl_packet); set_min_max(vr_packet);@/
 11961  x1l:=stack_1(x_packet(xy)); x3r:=stack_3(x_packet(xy));
 11962  x2l:=half(x1l+stack_2(x_packet(xy)));
 11963  x2r:=half(x3r+stack_2(x_packet(xy)));
 11964  x3l:=half(x2l+x2r); x1r:=x3l;
 11965  set_min_max(xl_packet); set_min_max(xr_packet);@/
 11966  y1l:=stack_1(y_packet(xy)); y3r:=stack_3(y_packet(xy));
 11967  y2l:=half(y1l+stack_2(y_packet(xy)));
 11968  y2r:=half(y3r+stack_2(y_packet(xy)));
 11969  y3l:=half(y2l+y2r); y1r:=y3l;
 11970  set_min_max(yl_packet); set_min_max(yr_packet);@/
 11971  uv:=l_packets; xy:=l_packets;
 11972  double(delx); double(dely);@/
 11973  tol:=tol-three_l+tol_step; double(tol); three_l:=three_l+tol_step
 11974  
 11975  @ @<Advance to the next pair |(cur_t,cur_tt)|@>=
 11976  not_found: if odd(cur_tt) then
 11977    if odd(cur_t) then @<Descend to the previous level and |goto not_found|@>
 11978    else  begin incr(cur_t);
 11979      delx:=delx+stack_1(u_packet(uv))+stack_2(u_packet(uv))
 11980        +stack_3(u_packet(uv));
 11981      dely:=dely+stack_1(v_packet(uv))+stack_2(v_packet(uv))
 11982        +stack_3(v_packet(uv));
 11983      uv:=uv+int_packets; {switch from |l_packets| to |r_packets|}
 11984      decr(cur_tt); xy:=xy-int_packets; {switch from |r_packets| to |l_packets|}
 11985      delx:=delx+stack_1(x_packet(xy))+stack_2(x_packet(xy))
 11986        +stack_3(x_packet(xy));
 11987      dely:=dely+stack_1(y_packet(xy))+stack_2(y_packet(xy))
 11988        +stack_3(y_packet(xy));
 11989      end
 11990  else  begin incr(cur_tt); tol:=tol+three_l;
 11991    delx:=delx-stack_1(x_packet(xy))-stack_2(x_packet(xy))
 11992      -stack_3(x_packet(xy));
 11993    dely:=dely-stack_1(y_packet(xy))-stack_2(y_packet(xy))
 11994      -stack_3(y_packet(xy));
 11995    xy:=xy+int_packets; {switch from |l_packets| to |r_packets|}
 11996    end
 11997  
 11998  @ @<Descend to the previous level...@>=
 11999  begin cur_t:=half(cur_t); cur_tt:=half(cur_tt);
 12000  if cur_t=0 then return;
 12001  bisect_ptr:=bisect_ptr-int_increment; three_l:=three_l-tol_step;
 12002  delx:=stack_dx; dely:=stack_dy; tol:=stack_tol; uv:=stack_uv; xy:=stack_xy;@/
 12003  goto not_found;
 12004  end
 12005  
 12006  @ The |path_intersection| procedure is much simpler.
 12007  It invokes |cubic_intersection| in lexicographic order until finding a
 12008  pair of cubics that intersect. The final intersection times are placed in
 12009  |cur_t| and~|cur_tt|.
 12010  
 12011  @p procedure path_intersection(@!h,@!hh:pointer);
 12012  label exit;
 12013  var @!p,@!pp:pointer; {link registers that traverse the given paths}
 12014  @!n,@!nn:integer; {integer parts of intersection times, minus |unity|}
 12015  begin @<Change one-point paths into dead cycles@>;
 12016  tol_step:=0;
 12017  repeat n:=-unity; p:=h;
 12018    repeat if right_type(p)<>endpoint then
 12019      begin nn:=-unity; pp:=hh;
 12020      repeat if right_type(pp)<>endpoint then
 12021        begin cubic_intersection(p,pp);
 12022        if cur_t>0 then
 12023          begin cur_t:=cur_t+n; cur_tt:=cur_tt+nn; return;
 12024          end;
 12025        end;
 12026      nn:=nn+unity; pp:=link(pp);
 12027      until pp=hh;
 12028      end;
 12029    n:=n+unity; p:=link(p);
 12030    until p=h;
 12031  tol_step:=tol_step+3;
 12032  until tol_step>3;
 12033  cur_t:=-unity; cur_tt:=-unity;
 12034  exit:end;
 12035  
 12036  @ @<Change one-point paths...@>=
 12037  if right_type(h)=endpoint then
 12038    begin right_x(h):=x_coord(h); left_x(h):=x_coord(h);
 12039    right_y(h):=y_coord(h); left_y(h):=y_coord(h); right_type(h):=explicit;
 12040    end;
 12041  if right_type(hh)=endpoint then
 12042    begin right_x(hh):=x_coord(hh); left_x(hh):=x_coord(hh);
 12043    right_y(hh):=y_coord(hh); left_y(hh):=y_coord(hh); right_type(hh):=explicit;
 12044    end;
 12045  
 12046  @* \[27] Online graphic output.
 12047  \MF\ displays images on the user's screen by means of a few primitive
 12048  operations that are defined below. These operations have deliberately been
 12049  kept simple so that they can be implemented without great difficulty on a
 12050  wide variety of machines. Since \PASCAL\ has no traditional standards for
 12051  graphic output, some system-dependent code needs to be written in order to
 12052  support this aspect of \MF; but the necessary routines are usually quite
 12053  easy to write.
 12054  @^system dependencies@>
 12055  
 12056  In fact, there are exactly four such routines:
 12057  
 12058  \yskip\hang
 12059  |init_screen| does whatever initialization is necessary to
 12060  support the other operations; it is a boolean function that returns
 12061  |false| if graphic output cannot be supported (e.g., if the other three
 12062  routines have not been written, or if the user doesn't have the
 12063  right kind of terminal).
 12064  
 12065  \yskip\hang
 12066  |blank_rectangle| updates a buffer area in memory so that
 12067  all pixels in a specified rectangle will be set to the background color.
 12068  
 12069  \yskip\hang
 12070  |paint_row| assigns values to specified pixels in a row of
 12071  the buffer just mentioned, based on ``transition'' indices explained below.
 12072  
 12073  \yskip\hang
 12074  |update_screen| displays the current screen buffer; the
 12075  effects of |blank_rectangle| and |paint_row| commands may or may not
 12076  become visible until the next |update_screen| operation is performed.
 12077  (Thus, |update_screen| is analogous to |update_terminal|.)
 12078  
 12079  \yskip\noindent
 12080  The \PASCAL\ code here is a minimum version of |init_screen| and
 12081  |update_screen|, usable on \MF\ installations that don't
 12082  support screen output. If |init_screen| is changed to return |true|
 12083  instead of |false|, the other routines will simply log the fact
 12084  that they have been called; they won't really display anything.
 12085  The standard test routines for \MF\ use this log information to check
 12086  that \MF\ is working properly, but the |wlog| instructions should be
 12087  removed from production versions of \MF.
 12088  
 12089  @p function init_screen:boolean;
 12090  begin init_screen:=false;
 12091  end;
 12092  @#
 12093  procedure update_screen; {will be called only if |init_screen| returns |true|}
 12094  begin @!init wlog_ln('Calling UPDATESCREEN');@+tini {for testing only}
 12095  end;
 12096  
 12097  @ The user's screen is assumed to be a rectangular area, |screen_width|
 12098  pixels wide and |screen_depth| pixels deep. The pixel in the upper left
 12099  corner is said to be in column~0 of row~0; the pixel in the lower right
 12100  corner is said to be in column |screen_width-1| of row |screen_depth-1|.
 12101  Notice that row numbers increase from top to bottom, contrary to \MF's
 12102  other coordinates.
 12103  
 12104  Each pixel is assumed to have two states, referred to in this documentation
 12105  as |black| and |white|. The background color is called |white| and the
 12106  other color is called |black|; but any two distinct pixel values
 12107  can actually be used. For example, the author developed \MF\ on a
 12108  system for which |white| was black and |black| was bright green.
 12109  
 12110  @d white=0 {background pixels}
 12111  @d black=1 {visible pixels}
 12112  
 12113  @<Types...@>=
 12114  @!screen_row=0..screen_depth; {a row number on the screen}
 12115  @!screen_col=0..screen_width; {a column number on the screen}
 12116  @!trans_spec=array[screen_col] of screen_col; {a transition spec, see below}
 12117  @!pixel_color=white..black; {specifies one of the two pixel values}
 12118  
 12119  @ We'll illustrate the |blank_rectangle| and |paint_row| operations by
 12120  pretending to declare a screen buffer called |screen_pixel|. This code
 12121  is actually commented out, but it does specify the intended effects.
 12122  
 12123  @<Glob...@>=
 12124  @{@+@!screen_pixel:array[screen_row,screen_col] of pixel_color@t; @>@}
 12125  
 12126  @ The |blank_rectangle| routine simply whitens all pixels that lie in
 12127  columns |left_col| through |right_col-1|, inclusive, of rows
 12128  |top_row| through |bot_row-1|, inclusive, given four parameters that satisfy
 12129  the relations
 12130  $$\hbox{|0<=left_col<=right_col<=screen_width|,\quad
 12131    |0<=top_row<=bot_row<=screen_depth|.}$$
 12132  If |left_col=right_col| or |top_row=bot_row|, nothing happens.
 12133  
 12134  The commented-out code in the following procedure is for illustrative
 12135  purposes only.
 12136  @^system dependencies@>
 12137  
 12138  @p procedure blank_rectangle(@!left_col,@!right_col:screen_col;
 12139    @!top_row,@!bot_row:screen_row);
 12140  var @!r:screen_row;
 12141  @!c:screen_col;
 12142  begin @{@+for r:=top_row to bot_row-1 do
 12143    for c:=left_col to right_col-1 do
 12144      screen_pixel[r,c]:=white;@+@}@/
 12145  @!init wlog_cr; {this will be done only after |init_screen=true|}
 12146  wlog_ln('Calling BLANKRECTANGLE(',left_col:1,',',
 12147    right_col:1,',',top_row:1,',',bot_row:1,')');@+tini
 12148  end;
 12149  
 12150  @ The real work of screen display is done by |paint_row|. But it's not
 12151  hard work, because the operation affects only
 12152  one of the screen rows, and it affects only a contiguous set of columns
 12153  in that row. There are four parameters: |r|~(the row),
 12154  |b|~(the initial color),
 12155  |a|~(the array of transition specifications),
 12156  and |n|~(the number of transitions). The elements of~|a| will satisfy
 12157  $$0\L a[0]<a[1]<\cdots<a[n]\L |screen_width|;$$
 12158  the value of |r| will satisfy |0<=r<screen_depth|; and |n| will be positive.
 12159  
 12160  The general idea is to paint blocks of pixels in alternate colors;
 12161  the precise details are best conveyed by means of a \PASCAL\
 12162  program (see the commented-out code below).
 12163  @^system dependencies@>
 12164  
 12165  @p procedure paint_row(@!r:screen_row;@!b:pixel_color;var @!a:trans_spec;
 12166    @!n:screen_col);
 12167  var @!k:screen_col; {an index into |a|}
 12168  @!c:screen_col; {an index into |screen_pixel|}
 12169  begin @{@+k:=0; c:=a[0];
 12170  repeat incr(k);
 12171    repeat screen_pixel[r,c]:=b; incr(c);
 12172    until c=a[k];
 12173    b:=black-b; {$|black|\swap|white|$}
 12174    until k=n;@+@}@/
 12175  @!init wlog('Calling PAINTROW(',r:1,',',b:1,';');
 12176    {this is done only after |init_screen=true|}
 12177  for k:=0 to n do
 12178    begin wlog(a[k]:1); if k<>n then wlog(',');
 12179    end;
 12180  wlog_ln(')');@+tini
 12181  end;
 12182  
 12183  @ The remainder of \MF's screen routines are system-independent calls
 12184  on the four primitives just defined.
 12185  
 12186  First we have a global boolean variable that tells if |init_screen|
 12187  has been called, and another one that tells if |init_screen| has
 12188  given a |true| response.
 12189  
 12190  @<Glob...@>=
 12191  @!screen_started:boolean; {have the screen primitives been initialized?}
 12192  @!screen_OK:boolean; {is it legitimate to call |blank_rectangle|,
 12193    |paint_row|, and |update_screen|?}
 12194  
 12195  @ @d start_screen==begin if not screen_started then
 12196      begin screen_OK:=init_screen; screen_started:=true;
 12197      end;
 12198    end
 12199  
 12200  @<Set init...@>=
 12201  screen_started:=false; screen_OK:=false;
 12202  
 12203  @ \MF\ provides the user with 16 ``window'' areas on the screen, in each
 12204  of which it is possible to produce independent displays.
 12205  
 12206  It should be noted that \MF's windows aren't really independent
 12207  ``clickable'' entities in the sense of multi-window graphic workstations;
 12208  \MF\ simply maps them into subsets of a single screen image that is
 12209  controlled by |init_screen|, |blank_rectangle|, |paint_row|, and
 12210  |update_screen| as described above. Implementations of \MF\ on a
 12211  multi-window workstation probably therefore make use of only two
 12212  windows in the other sense: one for the terminal output and another
 12213  for the screen with \MF's 16 areas. Henceforth we shall
 12214  use the term window only in \MF's sense.
 12215  
 12216  @<Types...@>=
 12217  @!window_number=0..15;
 12218  
 12219  @ A user doesn't have to use any of the 16 windows. But when a window is
 12220  ``opened,'' it is allocated to a specific rectangular portion of the screen
 12221  and to a specific rectangle with respect to \MF's coordinates. The relevant
 12222  data is stored in global arrays |window_open|, |left_col|, |right_col|,
 12223  |top_row|, |bot_row|, |m_window|, and |n_window|.
 12224  
 12225  The |window_open| array is boolean, and its significance is obvious. The
 12226  |left_col|, \dots, |bot_row| arrays contain screen coordinates that
 12227  can be used to blank the entire window with |blank_rectangle|. And the
 12228  other two arrays just mentioned handle the conversion between
 12229  actual coordinates and screen coordinates: \MF's pixel in column~$m$
 12230  of row~$n$ will appear in screen column |m_window+m| and in screen row
 12231  |n_window-n|, provided that these lie inside the boundaries of the window.
 12232  
 12233  Another array |window_time| holds the number of times this window has
 12234  been updated.
 12235  
 12236  @<Glob...@>=
 12237  @!window_open:array[window_number] of boolean;
 12238    {has this window been opened?}
 12239  @!left_col:array[window_number] of screen_col;
 12240    {leftmost column position on screen}
 12241  @!right_col:array[window_number] of screen_col;
 12242    {rightmost column position, plus~1}
 12243  @!top_row:array[window_number] of screen_row;
 12244    {topmost row position on screen}
 12245  @!bot_row:array[window_number] of screen_row;
 12246    {bottommost row position, plus~1}
 12247  @!m_window:array[window_number] of integer;
 12248    {offset between user and screen columns}
 12249  @!n_window:array[window_number] of integer;
 12250    {offset between user and screen rows}
 12251  @!window_time:array[window_number] of integer;
 12252    {it has been updated this often}
 12253  
 12254  @ @<Set init...@>=
 12255  for k:=0 to 15 do
 12256    begin window_open[k]:=false; window_time[k]:=0;
 12257    end;
 12258  
 12259  @ Opening a window isn't like opening a file, because you can open it
 12260  as often as you like, and you never have to close it again. The idea is
 12261  simply to define special points on the current screen display.
 12262  
 12263  Overlapping window specifications may cause complex effects that can
 12264  be understood only by scrutinizing \MF's display algorithms; thus it
 12265  has been left undefined in the \MF\ user manual, although the behavior
 12266  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 12267  is in fact predictable.
 12268  
 12269  Here is a subroutine that implements the command `\&{openwindow}~|k|
 12270  \&{from}~$(\\{r0},\\{c0})$ \&{to}~$(\\{r1},\\{c1})$ \&{at}~$(x,y)$'.
 12271  
 12272  @p procedure open_a_window(@!k:window_number;@!r0,@!c0,@!r1,@!c1:scaled;
 12273      @!x,@!y:scaled);
 12274  var @!m,@!n:integer; {pixel coordinates}
 12275  begin @<Adjust the coordinates |(r0,c0)| and |(r1,c1)| so that
 12276    they lie in the proper range@>;
 12277  window_open[k]:=true; incr(window_time[k]);@/
 12278  left_col[k]:=c0; right_col[k]:=c1; top_row[k]:=r0; bot_row[k]:=r1;@/
 12279  @<Compute the offsets between screen coordinates and actual coordinates@>;
 12280  start_screen;
 12281  if screen_OK then
 12282    begin blank_rectangle(c0,c1,r0,r1); update_screen;
 12283    end;
 12284  end;
 12285  
 12286  @ A window whose coordinates don't fit the existing screen size will be
 12287  truncated until they do.
 12288  
 12289  @<Adjust the coordinates |(r0,c0)| and |(r1,c1)|...@>=
 12290  if r0<0 then r0:=0@+else r0:=round_unscaled(r0);
 12291  r1:=round_unscaled(r1);
 12292  if r1>screen_depth then r1:=screen_depth;
 12293  if r1<r0 then
 12294    if r0>screen_depth then r0:=r1@+else r1:=r0;
 12295  if c0<0 then c0:=0@+else c0:=round_unscaled(c0);
 12296  c1:=round_unscaled(c1);
 12297  if c1>screen_width then c1:=screen_width;
 12298  if c1<c0 then
 12299    if c0>screen_width then c0:=c1@+else c1:=c0
 12300  
 12301  @ Three sets of coordinates are rampant, and they must be kept straight!
 12302  (i)~\MF's main coordinates refer to the edges between pixels. (ii)~\MF's
 12303  pixel coordinates (within edge structures) say that the pixel bounded by
 12304  $(m,n)$, $(m,n+1)$, $(m+1,n)$, and~$(m+1,n+1)$ is in pixel row number~$n$
 12305  and pixel column number~$m$. (iii)~Screen coordinates, on the other hand,
 12306  have rows numbered in increasing order from top to bottom, as mentioned
 12307  above.
 12308  @^coordinates, explained@>
 12309  
 12310  The program here first computes integers $m$ and $n$ such that
 12311  pixel column~$m$ of pixel row~$n$ will be at the upper left corner
 12312  of the window. Hence pixel column |m-c0| of pixel row |n+r0|
 12313  will be at the upper left corner of the screen.
 12314  
 12315  @<Compute the offsets between screen coordinates and actual coordinates@>=
 12316  m:=round_unscaled(x); n:=round_unscaled(y)-1;@/
 12317  m_window[k]:=c0-m; n_window[k]:=r0+n
 12318  
 12319  @ Now here comes \MF's most complicated operation related to window
 12320  display: Given the number~|k| of an open window, the pixels of positive
 12321  weight in |cur_edges| will be shown as |black| in the window; all other
 12322  pixels will be shown as |white|.
 12323  
 12324  @p procedure disp_edges(@!k:window_number);
 12325  label done,found;
 12326  var @!p,@!q:pointer; {for list manipulation}
 12327  @!already_there:boolean; {is a previous incarnation in the window?}
 12328  @!r:integer; {row number}
 12329  @<Other local variables for |disp_edges|@>@;
 12330  begin if screen_OK then
 12331   if left_col[k]<right_col[k] then if top_row[k]<bot_row[k] then
 12332    begin already_there:=false;
 12333    if last_window(cur_edges)=k then
 12334     if last_window_time(cur_edges)=window_time[k] then
 12335      already_there:=true;
 12336    if not already_there then
 12337      blank_rectangle(left_col[k],right_col[k],top_row[k],bot_row[k]);
 12338    @<Initialize for the display computations@>;
 12339    p:=link(cur_edges); r:=n_window[k]-(n_min(cur_edges)-zero_field);
 12340    while (p<>cur_edges)and(r>=top_row[k]) do
 12341      begin if r<bot_row[k] then
 12342        @<Display the pixels of edge row |p| in screen row |r|@>;
 12343      p:=link(p); decr(r);
 12344      end;
 12345    update_screen;
 12346    incr(window_time[k]);
 12347    last_window(cur_edges):=k; last_window_time(cur_edges):=window_time[k];
 12348    end;
 12349  end;
 12350  
 12351  @ Since it takes some work to display a row, we try to avoid recomputation
 12352  whenever we can.
 12353  
 12354  @<Display the pixels of edge row |p| in screen row |r|@>=
 12355  begin if unsorted(p)>void then sort_edges(p)
 12356  else if unsorted(p)=void then if already_there then goto done;
 12357  unsorted(p):=void; {this time we'll paint, but maybe not next time}
 12358  @<Set up the parameters needed for |paint_row|;
 12359    but |goto done| if no painting is needed after all@>;
 12360  paint_row(r,b,row_transition,n);
 12361  done: end
 12362  
 12363  @ The transition-specification parameter to |paint_row| is always the same
 12364  array.
 12365  
 12366  @<Glob...@>=
 12367  @!row_transition:trans_spec; {an array of |black|/|white| transitions}
 12368  
 12369  @ The job remaining is to go through the list |sorted(p)|, unpacking the
 12370  |info| fields into |m| and weight, then making |black| the pixels whose
 12371  accumulated weight~|w| is positive.
 12372  
 12373  @<Other local variables for |disp_edges|@>=
 12374  @!n:screen_col; {the highest active index in |row_transition|}
 12375  @!w,@!ww:integer; {old and new accumulated weights}
 12376  @!b:pixel_color; {status of first pixel in the row transitions}
 12377  @!m,@!mm:integer; {old and new screen column positions}
 12378  @!d:integer; {edge-and-weight without |min_halfword| compensation}
 12379  @!m_adjustment:integer; {conversion between edge and screen coordinates}
 12380  @!right_edge:integer; {largest edge-and-weight that could affect the window}
 12381  @!min_col:screen_col; {the smallest screen column number in the window}
 12382  
 12383  @ Some precomputed constants make the display calculations faster.
 12384  
 12385  @<Initialize for the display computations@>=
 12386  m_adjustment:=m_window[k]-m_offset(cur_edges);@/
 12387  right_edge:=8*(right_col[k]-m_adjustment);@/
 12388  min_col:=left_col[k]
 12389  
 12390  @ @<Set up the parameters needed for |paint_row|...@>=
 12391  n:=0; ww:=0; m:=-1; w:=0;
 12392  q:=sorted(p); row_transition[0]:=min_col;
 12393  loop@+  begin if q=sentinel then d:=right_edge
 12394    else d:=ho(info(q));
 12395    mm:=(d div 8)+m_adjustment;
 12396    if mm<>m then
 12397      begin @<Record a possible transition in column |m|@>;
 12398      m:=mm; w:=ww;
 12399      end;
 12400    if d>=right_edge then goto found;
 12401    ww:=ww+(d mod 8)-zero_w;
 12402    q:=link(q);
 12403    end;
 12404  found:@<Wind up the |paint_row| parameter calculation by inserting the
 12405    final transition; |goto done| if no painting is needed@>;
 12406  
 12407  @ Now |m| is a screen column |<right_col[k]|.
 12408  
 12409  @<Record a possible transition in column |m|@>=
 12410  if w<=0 then
 12411    begin if ww>0 then if m>min_col then
 12412      begin if n=0 then
 12413        if already_there then
 12414          begin b:=white; incr(n);
 12415          end
 12416        else b:=black
 12417      else incr(n);
 12418      row_transition[n]:=m;
 12419      end;
 12420    end
 12421  else if ww<=0 then if m>min_col then
 12422    begin if n=0 then b:=black;
 12423    incr(n); row_transition[n]:=m;
 12424    end
 12425  
 12426  @ If the entire row is |white| in the window area, we can omit painting it
 12427  when |already_there| is false, since it has already been blanked out in
 12428  that case.
 12429  
 12430  When the following code is invoked, |row_transition[n]| will be
 12431  strictly less than |right_col[k]|.
 12432  
 12433  @<Wind up the |paint_row|...@>=
 12434  if already_there or(ww>0) then
 12435    begin if n=0 then
 12436      if ww>0 then b:=black
 12437      else b:=white;
 12438    incr(n); row_transition[n]:=right_col[k];
 12439    end
 12440  else if n=0 then goto done
 12441  
 12442  @* \[28] Dynamic linear equations.
 12443  \MF\ users define variables implicitly by stating equations that should be
 12444  satisfied; the computer is supposed to be smart enough to solve those equations.
 12445  And indeed, the computer tries valiantly to do so, by distinguishing five
 12446  different types of numeric values:
 12447  
 12448  \smallskip\hang
 12449  |type(p)=known| is the nice case, when |value(p)| is the |scaled| value
 12450  of the variable whose address is~|p|.
 12451  
 12452  \smallskip\hang
 12453  |type(p)=dependent| means that |value(p)| is not present, but |dep_list(p)|
 12454  points to a {\sl dependency list\/} that expresses the value of variable~|p|
 12455  as a |scaled| number plus a sum of independent variables with |fraction|
 12456  coefficients.
 12457  
 12458  \smallskip\hang
 12459  |type(p)=independent| means that |value(p)=64s+m|, where |s>0| is a ``serial
 12460  number'' reflecting the time this variable was first used in an equation;
 12461  also |0<=m<64|, and each dependent variable
 12462  that refers to this one is actually referring to the future value of
 12463  this variable times~$2^m$. (Usually |m=0|, but higher degrees of
 12464  scaling are sometimes needed to keep the coefficients in dependency lists
 12465  from getting too large. The value of~|m| will always be even.)
 12466  
 12467  \smallskip\hang
 12468  |type(p)=numeric_type| means that variable |p| hasn't appeared in an
 12469  equation before, but it has been explicitly declared to be numeric.
 12470  
 12471  \smallskip\hang
 12472  |type(p)=undefined| means that variable |p| hasn't appeared before.
 12473  
 12474  \smallskip\noindent
 12475  We have actually discussed these five types in the reverse order of their
 12476  history during a computation: Once |known|, a variable never again
 12477  becomes |dependent|; once |dependent|, it almost never again becomes
 12478  |independent|; once |independent|, it never again becomes |numeric_type|;
 12479  and once |numeric_type|, it never again becomes |undefined| (except
 12480  of course when the user specifically decides to scrap the old value
 12481  and start again). A backward step may, however, take place: Sometimes
 12482  a |dependent| variable becomes |independent| again, when one of the
 12483  independent variables it depends on is reverting to |undefined|.
 12484  
 12485  @d s_scale=64 {the serial numbers are multiplied by this factor}
 12486  @d new_indep(#)== {create a new independent variable}
 12487    begin if serial_no>el_gordo-s_scale then
 12488        overflow("independent variables",serial_no div s_scale);
 12489  @:METAFONT capacity exceeded independent variables}{\quad independent variables@>
 12490    type(#):=independent; serial_no:=serial_no+s_scale;
 12491    value(#):=serial_no;
 12492    end
 12493  
 12494  @<Glob...@>=
 12495  @!serial_no:integer; {the most recent serial number, times |s_scale|}
 12496  
 12497  @ @<Make variable |q+s| newly independent@>=new_indep(q+s)
 12498  
 12499  @ But how are dependency lists represented? It's simple: The linear combination
 12500  $\alpha_1v_1+\cdots+\alpha_kv_k+\beta$ appears in |k+1| value nodes. If
 12501  |q=dep_list(p)| points to this list, and if |k>0|, then |value(q)=
 12502  @t$\alpha_1$@>| (which is a |fraction|); |info(q)| points to the location
 12503  of $v_1$; and |link(p)| points to the dependency list
 12504  $\alpha_2v_2+\cdots+\alpha_kv_k+\beta$. On the other hand if |k=0|,
 12505  then |value(q)=@t$\beta$@>| (which is |scaled|) and |info(q)=null|.
 12506  The independent variables $v_1$, \dots,~$v_k$ have been sorted so that
 12507  they appear in decreasing order of their |value| fields (i.e., of
 12508  their serial numbers). \ (It is convenient to use decreasing order,
 12509  since |value(null)=0|. If the independent variables were not sorted by
 12510  serial number but by some other criterion, such as their location in |mem|,
 12511  the equation-solving mechanism would be too system-dependent, because
 12512  the ordering can affect the computed results.)
 12513  
 12514  The |link| field in the node that contains the constant term $\beta$ is
 12515  called the {\sl final link\/} of the dependency list. \MF\ maintains
 12516  a doubly-linked master list of all dependency lists, in terms of a permanently
 12517  allocated node
 12518  in |mem| called |dep_head|. If there are no dependencies, we have
 12519  |link(dep_head)=dep_head| and |prev_dep(dep_head)=dep_head|;
 12520  otherwise |link(dep_head)| points to the first dependent variable, say~|p|,
 12521  and |prev_dep(p)=dep_head|. We have |type(p)=dependent|, and |dep_list(p)|
 12522  points to its dependency list. If the final link of that dependency list
 12523  occurs in location~|q|, then |link(q)| points to the next dependent
 12524  variable (say~|r|); and we have |prev_dep(r)=q|, etc.
 12525  
 12526  @d dep_list(#)==link(value_loc(#))
 12527    {half of the |value| field in a |dependent| variable}
 12528  @d prev_dep(#)==info(value_loc(#))
 12529    {the other half; makes a doubly linked list}
 12530  @d dep_node_size=2 {the number of words per dependency node}
 12531  
 12532  @<Initialize table entries...@>= serial_no:=0;
 12533  link(dep_head):=dep_head; prev_dep(dep_head):=dep_head;
 12534  info(dep_head):=null; dep_list(dep_head):=null;
 12535  
 12536  @ Actually the description above contains a little white lie. There's
 12537  another kind of variable called |proto_dependent|, which is
 12538  just like a |dependent| one except that the $\alpha$ coefficients
 12539  in its dependency list are |scaled| instead of being fractions.
 12540  Proto-dependency lists are mixed with dependency lists in the
 12541  nodes reachable from |dep_head|.
 12542  
 12543  @ Here is a procedure that prints a dependency list in symbolic form.
 12544  The second parameter should be either |dependent| or |proto_dependent|,
 12545  to indicate the scaling of the coefficients.
 12546  
 12547  @<Declare subroutines for printing expressions@>=
 12548  procedure print_dependency(@!p:pointer;@!t:small_number);
 12549  label exit;
 12550  var @!v:integer; {a coefficient}
 12551  @!pp,@!q:pointer; {for list manipulation}
 12552  begin pp:=p;
 12553  loop@+  begin v:=abs(value(p)); q:=info(p);
 12554    if q=null then {the constant term}
 12555      begin if (v<>0)or(p=pp) then
 12556        begin if value(p)>0 then if p<>pp then print_char("+");
 12557        print_scaled(value(p));
 12558        end;
 12559      return;
 12560      end;
 12561    @<Print the coefficient, unless it's $\pm1.0$@>;
 12562    if type(q)<>independent then confusion("dep");
 12563  @:this can't happen dep}{\quad dep@>
 12564    print_variable_name(q); v:=value(q) mod s_scale;
 12565    while v>0 do
 12566      begin print("*4"); v:=v-2;
 12567      end;
 12568    p:=link(p);
 12569    end;
 12570  exit:end;
 12571  
 12572  @ @<Print the coefficient, unless it's $\pm1.0$@>=
 12573  if value(p)<0 then print_char("-")
 12574  else if p<>pp then print_char("+");
 12575  if t=dependent then v:=round_fraction(v);
 12576  if v<>unity then print_scaled(v)
 12577  
 12578  @ The maximum absolute value of a coefficient in a given dependency list
 12579  is returned by the following simple function.
 12580  
 12581  @p function max_coef(@!p:pointer):fraction;
 12582  var @!x:fraction; {the maximum so far}
 12583  begin x:=0;
 12584  while info(p)<>null do
 12585    begin if abs(value(p))>x then x:=abs(value(p));
 12586    p:=link(p);
 12587    end;
 12588  max_coef:=x;
 12589  end;
 12590  
 12591  @ One of the main operations needed on dependency lists is to add a multiple
 12592  of one list to the other; we call this |p_plus_fq|, where |p| and~|q| point
 12593  to dependency lists and |f| is a fraction.
 12594  
 12595  If the coefficient of any independent variable becomes |coef_bound| or
 12596  more, in absolute value, this procedure changes the type of that variable
 12597  to `|independent_needing_fix|', and sets the global variable |fix_needed|
 12598  to~|true|. The value of $|coef_bound|=\mu$ is chosen so that
 12599  $\mu^2+\mu<8$; this means that the numbers we deal with won't
 12600  get too large. (Instead of the ``optimum'' $\mu=(\sqrt{33}-1)/2\approx
 12601  2.3723$, the safer value 7/3 is taken as the threshold.)
 12602  
 12603  The changes mentioned in the preceding paragraph are actually done only if
 12604  the global variable |watch_coefs| is |true|. But it usually is; in fact,
 12605  it is |false| only when \MF\ is making a dependency list that will soon
 12606  be equated to zero.
 12607  
 12608  Several procedures that act on dependency lists, including |p_plus_fq|,
 12609  set the global variable |dep_final| to the final (constant term) node of
 12610  the dependency list that they produce.
 12611  
 12612  @d coef_bound==@'4525252525 {|fraction| approximation to 7/3}
 12613  @d independent_needing_fix=0
 12614  
 12615  @<Glob...@>=
 12616  @!fix_needed:boolean; {does at least one |independent| variable need scaling?}
 12617  @!watch_coefs:boolean; {should we scale coefficients that exceed |coef_bound|?}
 12618  @!dep_final:pointer; {location of the constant term and final link}
 12619  
 12620  @ @<Set init...@>=
 12621  fix_needed:=false; watch_coefs:=true;
 12622  
 12623  @ The |p_plus_fq| procedure has a fourth parameter, |t|, that should be
 12624  set to |proto_dependent| if |p| is a proto-dependency list. In this
 12625  case |f| will be |scaled|, not a |fraction|. Similarly, the fifth parameter~|tt|
 12626  should be |proto_dependent| if |q| is a proto-dependency list.
 12627  
 12628  List |q| is unchanged by the operation; but list |p| is totally destroyed.
 12629  
 12630  The final link of the dependency list or proto-dependency list returned
 12631  by |p_plus_fq| is the same as the original final link of~|p|. Indeed, the
 12632  constant term of the result will be located in the same |mem| location
 12633  as the original constant term of~|p|.
 12634  
 12635  Coefficients of the result are assumed to be zero if they are less than
 12636  a certain threshold. This compensates for inevitable rounding errors,
 12637  and tends to make more variables `|known|'. The threshold is approximately
 12638  $10^{-5}$ in the case of normal dependency lists, $10^{-4}$ for
 12639  proto-dependencies.
 12640  
 12641  @d fraction_threshold=2685 {a |fraction| coefficient less than this is zeroed}
 12642  @d half_fraction_threshold=1342 {half of |fraction_threshold|}
 12643  @d scaled_threshold=8 {a |scaled| coefficient less than this is zeroed}
 12644  @d half_scaled_threshold=4 {half of |scaled_threshold|}
 12645  
 12646  @<Declare basic dependency-list subroutines@>=
 12647  function p_plus_fq(@!p:pointer;@!f:integer;@!q:pointer;
 12648    @!t,@!tt:small_number):pointer;
 12649  label done;
 12650  var @!pp,@!qq:pointer; {|info(p)| and |info(q)|, respectively}
 12651  @!r,@!s:pointer; {for list manipulation}
 12652  @!threshold:integer; {defines a neighborhood of zero}
 12653  @!v:integer; {temporary register}
 12654  begin if t=dependent then threshold:=fraction_threshold
 12655  else threshold:=scaled_threshold;
 12656  r:=temp_head; pp:=info(p); qq:=info(q);
 12657  loop@+  if pp=qq then
 12658      if pp=null then goto done
 12659      else @<Contribute a term from |p|, plus |f| times the
 12660        corresponding term from |q|@>
 12661    else if value(pp)<value(qq) then
 12662      @<Contribute a term from |q|, multiplied by~|f|@>
 12663    else  begin link(r):=p; r:=p; p:=link(p); pp:=info(p);
 12664      end;
 12665  done: if t=dependent then
 12666    value(p):=slow_add(value(p),take_fraction(value(q),f))
 12667  else  value(p):=slow_add(value(p),take_scaled(value(q),f));
 12668  link(r):=p; dep_final:=p; p_plus_fq:=link(temp_head);
 12669  end;
 12670  
 12671  @ @<Contribute a term from |p|, plus |f|...@>=
 12672  begin if tt=dependent then v:=value(p)+take_fraction(f,value(q))
 12673  else v:=value(p)+take_scaled(f,value(q));
 12674  value(p):=v; s:=p; p:=link(p);
 12675  if abs(v)<threshold then free_node(s,dep_node_size)
 12676  else  begin if abs(v)>=coef_bound then if watch_coefs then
 12677      begin type(qq):=independent_needing_fix; fix_needed:=true;
 12678      end;
 12679    link(r):=s; r:=s;
 12680    end;
 12681  pp:=info(p); q:=link(q); qq:=info(q);
 12682  end
 12683  
 12684  @ @<Contribute a term from |q|, multiplied by~|f|@>=
 12685  begin if tt=dependent then v:=take_fraction(f,value(q))
 12686  else v:=take_scaled(f,value(q));
 12687  if abs(v)>half(threshold) then
 12688    begin s:=get_node(dep_node_size); info(s):=qq; value(s):=v;
 12689    if abs(v)>=coef_bound then if watch_coefs then
 12690      begin type(qq):=independent_needing_fix; fix_needed:=true;
 12691      end;
 12692    link(r):=s; r:=s;
 12693    end;
 12694  q:=link(q); qq:=info(q);
 12695  end
 12696  
 12697  @ It is convenient to have another subroutine for the special case
 12698  of |p_plus_fq| when |f=1.0|. In this routine lists |p| and |q| are
 12699  both of the same type~|t| (either |dependent| or |proto_dependent|).
 12700  
 12701  @p function p_plus_q(@!p:pointer;@!q:pointer;@!t:small_number):pointer;
 12702  label done;
 12703  var @!pp,@!qq:pointer; {|info(p)| and |info(q)|, respectively}
 12704  @!r,@!s:pointer; {for list manipulation}
 12705  @!threshold:integer; {defines a neighborhood of zero}
 12706  @!v:integer; {temporary register}
 12707  begin if t=dependent then threshold:=fraction_threshold
 12708  else threshold:=scaled_threshold;
 12709  r:=temp_head; pp:=info(p); qq:=info(q);
 12710  loop@+  if pp=qq then
 12711      if pp=null then goto done
 12712      else @<Contribute a term from |p|, plus the
 12713        corresponding term from |q|@>
 12714    else if value(pp)<value(qq) then
 12715      begin s:=get_node(dep_node_size); info(s):=qq; value(s):=value(q);
 12716      q:=link(q); qq:=info(q); link(r):=s; r:=s;
 12717      end
 12718    else  begin link(r):=p; r:=p; p:=link(p); pp:=info(p);
 12719      end;
 12720  done: value(p):=slow_add(value(p),value(q));
 12721  link(r):=p; dep_final:=p; p_plus_q:=link(temp_head);
 12722  end;
 12723  
 12724  @ @<Contribute a term from |p|, plus the...@>=
 12725  begin v:=value(p)+value(q);
 12726  value(p):=v; s:=p; p:=link(p); pp:=info(p);
 12727  if abs(v)<threshold then free_node(s,dep_node_size)
 12728  else  begin if abs(v)>=coef_bound then if watch_coefs then
 12729      begin type(qq):=independent_needing_fix; fix_needed:=true;
 12730      end;
 12731    link(r):=s; r:=s;
 12732    end;
 12733  q:=link(q); qq:=info(q);
 12734  end
 12735  
 12736  @ A somewhat simpler routine will multiply a dependency list
 12737  by a given constant~|v|. The constant is either a |fraction| less than
 12738  |fraction_one|, or it is |scaled|. In the latter case we might be forced to
 12739  convert a dependency list to a proto-dependency list.
 12740  Parameters |t0| and |t1| are the list types before and after;
 12741  they should agree unless |t0=dependent| and |t1=proto_dependent|
 12742  and |v_is_scaled=true|.
 12743  
 12744  @p function p_times_v(@!p:pointer;@!v:integer;
 12745    @!t0,@!t1:small_number;@!v_is_scaled:boolean):pointer;
 12746  var @!r,@!s:pointer; {for list manipulation}
 12747  @!w:integer; {tentative coefficient}
 12748  @!threshold:integer;
 12749  @!scaling_down:boolean;
 12750  begin if t0<>t1 then scaling_down:=true@+else scaling_down:=not v_is_scaled;
 12751  if t1=dependent then threshold:=half_fraction_threshold
 12752  else threshold:=half_scaled_threshold;
 12753  r:=temp_head;
 12754  while info(p)<>null do
 12755    begin if scaling_down then w:=take_fraction(v,value(p))
 12756    else w:=take_scaled(v,value(p));
 12757    if abs(w)<=threshold then
 12758      begin s:=link(p); free_node(p,dep_node_size); p:=s;
 12759      end
 12760    else  begin if abs(w)>=coef_bound then
 12761        begin fix_needed:=true; type(info(p)):=independent_needing_fix;
 12762        end;
 12763      link(r):=p; r:=p; value(p):=w; p:=link(p);
 12764      end;
 12765    end;
 12766  link(r):=p;
 12767  if v_is_scaled then value(p):=take_scaled(value(p),v)
 12768  else value(p):=take_fraction(value(p),v);
 12769  p_times_v:=link(temp_head);
 12770  end;
 12771  
 12772  @ Similarly, we sometimes need to divide a dependency list
 12773  by a given |scaled| constant.
 12774  
 12775  @<Declare basic dependency-list subroutines@>=
 12776  function p_over_v(@!p:pointer;@!v:scaled;
 12777    @!t0,@!t1:small_number):pointer;
 12778  var @!r,@!s:pointer; {for list manipulation}
 12779  @!w:integer; {tentative coefficient}
 12780  @!threshold:integer;
 12781  @!scaling_down:boolean;
 12782  begin if t0<>t1 then scaling_down:=true@+else scaling_down:=false;
 12783  if t1=dependent then threshold:=half_fraction_threshold
 12784  else threshold:=half_scaled_threshold;
 12785  r:=temp_head;
 12786  while info(p)<>null do
 12787    begin if scaling_down then
 12788      if abs(v)<@'2000000 then w:=make_scaled(value(p),v*@'10000)
 12789      else w:=make_scaled(round_fraction(value(p)),v)
 12790    else w:=make_scaled(value(p),v);
 12791    if abs(w)<=threshold then
 12792      begin s:=link(p); free_node(p,dep_node_size); p:=s;
 12793      end
 12794    else  begin if abs(w)>=coef_bound then
 12795        begin fix_needed:=true; type(info(p)):=independent_needing_fix;
 12796        end;
 12797      link(r):=p; r:=p; value(p):=w; p:=link(p);
 12798      end;
 12799    end;
 12800  link(r):=p; value(p):=make_scaled(value(p),v);
 12801  p_over_v:=link(temp_head);
 12802  end;
 12803  
 12804  @ Here's another utility routine for dependency lists. When an independent
 12805  variable becomes dependent, we want to remove it from all existing
 12806  dependencies. The |p_with_x_becoming_q| function computes the
 12807  dependency list of~|p| after variable~|x| has been replaced by~|q|.
 12808  
 12809  This procedure has basically the same calling conventions as |p_plus_fq|:
 12810  List~|q| is unchanged; list~|p| is destroyed; the constant node and the
 12811  final link are inherited from~|p|; and the fourth parameter tells whether
 12812  or not |p| is |proto_dependent|. However, the global variable |dep_final|
 12813  is not altered if |x| does not occur in list~|p|.
 12814  
 12815  @p function p_with_x_becoming_q(@!p,@!x,@!q:pointer;@!t:small_number):pointer;
 12816  var @!r,@!s:pointer; {for list manipulation}
 12817  @!v:integer; {coefficient of |x|}
 12818  @!sx:integer; {serial number of |x|}
 12819  begin s:=p; r:=temp_head; sx:=value(x);
 12820  while value(info(s))>sx do
 12821    begin r:=s; s:=link(s);
 12822    end;
 12823  if info(s)<>x then p_with_x_becoming_q:=p
 12824  else  begin link(temp_head):=p; link(r):=link(s); v:=value(s);
 12825    free_node(s,dep_node_size);
 12826    p_with_x_becoming_q:=p_plus_fq(link(temp_head),v,q,t,dependent);
 12827    end;
 12828  end;
 12829  
 12830  @ Here's a simple procedure that reports an error when a variable
 12831  has just received a known value that's out of the required range.
 12832  
 12833  @<Declare basic dependency-list subroutines@>=
 12834  procedure val_too_big(@!x:scaled);
 12835  begin if internal[warning_check]>0 then
 12836    begin print_err("Value is too large ("); print_scaled(x); print_char(")");
 12837  @.Value is too large@>
 12838    help4("The equation I just processed has given some variable")@/
 12839      ("a value of 4096 or more. Continue and I'll try to cope")@/
 12840      ("with that big value; but it might be dangerous.")@/
 12841      ("(Set warningcheck:=0 to suppress this message.)");
 12842    error;
 12843    end;
 12844  end;
 12845  
 12846  @ When a dependent variable becomes known, the following routine
 12847  removes its dependency list. Here |p| points to the variable, and
 12848  |q| points to the dependency list (which is one node long).
 12849  
 12850  @<Declare basic dependency-list subroutines@>=
 12851  procedure make_known(@!p,@!q:pointer);
 12852  var @!t:dependent..proto_dependent; {the previous type}
 12853  begin prev_dep(link(q)):=prev_dep(p);
 12854  link(prev_dep(p)):=link(q); t:=type(p);
 12855  type(p):=known; value(p):=value(q); free_node(q,dep_node_size);
 12856  if abs(value(p))>=fraction_one then val_too_big(value(p));
 12857  if internal[tracing_equations]>0 then if interesting(p) then
 12858    begin begin_diagnostic; print_nl("#### ");
 12859  @:]]]\#\#\#\#_}{\.{\#\#\#\#}@>
 12860    print_variable_name(p); print_char("="); print_scaled(value(p));
 12861    end_diagnostic(false);
 12862    end;
 12863  if cur_exp=p then if cur_type=t then
 12864    begin cur_type:=known; cur_exp:=value(p);
 12865    free_node(p,value_node_size);
 12866    end;
 12867  end;
 12868  
 12869  @ The |fix_dependencies| routine is called into action when |fix_needed|
 12870  has been triggered. The program keeps a list~|s| of independent variables
 12871  whose coefficients must be divided by~4.
 12872  
 12873  In unusual cases, this fixup process might reduce one or more coefficients
 12874  to zero, so that a variable will become known more or less by default.
 12875  
 12876  @<Declare basic dependency-list subroutines@>=
 12877  procedure fix_dependencies;
 12878  label done;
 12879  var @!p,@!q,@!r,@!s,@!t:pointer; {list manipulation registers}
 12880  @!x:pointer; {an independent variable}
 12881  begin r:=link(dep_head); s:=null;
 12882  while r<>dep_head do
 12883    begin t:=r;
 12884    @<Run through the dependency list for variable |t|, fixing
 12885      all nodes, and ending with final link~|q|@>;
 12886    r:=link(q);
 12887    if q=dep_list(t) then make_known(t,q);
 12888    end;
 12889  while s<>null do
 12890    begin p:=link(s); x:=info(s); free_avail(s); s:=p;
 12891    type(x):=independent; value(x):=value(x)+2;
 12892    end;
 12893  fix_needed:=false;
 12894  end;
 12895  
 12896  @ @d independent_being_fixed=1 {this variable already appears in |s|}
 12897  
 12898  @<Run through the dependency list for variable |t|...@>=
 12899  r:=value_loc(t); {|link(r)=dep_list(t)|}
 12900  loop@+  begin q:=link(r); x:=info(q);
 12901    if x=null then goto done;
 12902    if type(x)<=independent_being_fixed then
 12903      begin if type(x)<independent_being_fixed then
 12904        begin p:=get_avail; link(p):=s; s:=p;
 12905        info(s):=x; type(x):=independent_being_fixed;
 12906        end;
 12907      value(q):=value(q) div 4;
 12908      if value(q)=0 then
 12909        begin link(r):=link(q); free_node(q,dep_node_size); q:=r;
 12910        end;
 12911      end;
 12912    r:=q;
 12913    end;
 12914  done:
 12915  
 12916  @ The |new_dep| routine installs a dependency list~|p| into the value node~|q|,
 12917  linking it into the list of all known dependencies. We assume that
 12918  |dep_final| points to the final node of list~|p|.
 12919  
 12920  @p procedure new_dep(@!q,@!p:pointer);
 12921  var @!r:pointer; {what used to be the first dependency}
 12922  begin dep_list(q):=p; prev_dep(q):=dep_head;
 12923  r:=link(dep_head); link(dep_final):=r; prev_dep(r):=dep_final;
 12924  link(dep_head):=q;
 12925  end;
 12926  
 12927  @ Here is one of the ways a dependency list gets started.
 12928  The |const_dependency| routine produces a list that has nothing but
 12929  a constant term.
 12930  
 12931  @p function const_dependency(@!v:scaled):pointer;
 12932  begin dep_final:=get_node(dep_node_size);
 12933  value(dep_final):=v; info(dep_final):=null;
 12934  const_dependency:=dep_final;
 12935  end;
 12936  
 12937  @ And here's a more interesting way to start a dependency list from scratch:
 12938  The parameter to |single_dependency| is the location of an
 12939  independent variable~|x|, and the result is the simple dependency list
 12940  `|x+0|'.
 12941  
 12942  In the unlikely event that the given independent variable has been doubled so
 12943  often that we can't refer to it with a nonzero coefficient,
 12944  |single_dependency| returns the simple list `0'.  This case can be
 12945  recognized by testing that the returned list pointer is equal to
 12946  |dep_final|.
 12947  
 12948  @p function single_dependency(@!p:pointer):pointer;
 12949  var @!q:pointer; {the new dependency list}
 12950  @!m:integer; {the number of doublings}
 12951  begin m:=value(p) mod s_scale;
 12952  if m>28 then single_dependency:=const_dependency(0)
 12953  else  begin q:=get_node(dep_node_size);
 12954    value(q):=two_to_the[28-m]; info(q):=p;@/
 12955    link(q):=const_dependency(0); single_dependency:=q;
 12956    end;
 12957  end;
 12958  
 12959  @ We sometimes need to make an exact copy of a dependency list.
 12960  
 12961  @p function copy_dep_list(@!p:pointer):pointer;
 12962  label done;
 12963  var @!q:pointer; {the new dependency list}
 12964  begin q:=get_node(dep_node_size); dep_final:=q;
 12965  loop@+  begin info(dep_final):=info(p); value(dep_final):=value(p);
 12966    if info(dep_final)=null then goto done;
 12967    link(dep_final):=get_node(dep_node_size);
 12968    dep_final:=link(dep_final); p:=link(p);
 12969    end;
 12970  done:copy_dep_list:=q;
 12971  end;
 12972  
 12973  @ But how do variables normally become known? Ah, now we get to the heart of the
 12974  equation-solving mechanism. The |linear_eq| procedure is given a |dependent|
 12975  or |proto_dependent| list,~|p|, in which at least one independent variable
 12976  appears. It equates this list to zero, by choosing an independent variable
 12977  with the largest coefficient and making it dependent on the others. The
 12978  newly dependent variable is eliminated from all current dependencies,
 12979  thereby possibly making other dependent variables known.
 12980  
 12981  The given list |p| is, of course, totally destroyed by all this processing.
 12982  
 12983  @p procedure linear_eq(@!p:pointer;@!t:small_number);
 12984  var @!q,@!r,@!s:pointer; {for link manipulation}
 12985  @!x:pointer; {the variable that loses its independence}
 12986  @!n:integer; {the number of times |x| had been halved}
 12987  @!v:integer; {the coefficient of |x| in list |p|}
 12988  @!prev_r:pointer; {lags one step behind |r|}
 12989  @!final_node:pointer; {the constant term of the new dependency list}
 12990  @!w:integer; {a tentative coefficient}
 12991  begin @<Find a node |q| in list |p| whose coefficient |v| is largest@>;
 12992  x:=info(q); n:=value(x) mod s_scale;@/
 12993  @<Divide list |p| by |-v|, removing node |q|@>;
 12994  if internal[tracing_equations]>0 then @<Display the new dependency@>;
 12995  @<Simplify all existing dependencies by substituting for |x|@>;
 12996  @<Change variable |x| from |independent| to |dependent| or |known|@>;
 12997  if fix_needed then fix_dependencies;
 12998  end;
 12999  
 13000  @ @<Find a node |q| in list |p| whose coefficient |v| is largest@>=
 13001  q:=p; r:=link(p); v:=value(q);
 13002  while info(r)<>null do
 13003    begin if abs(value(r))>abs(v) then
 13004      begin q:=r; v:=value(r);
 13005      end;
 13006    r:=link(r);
 13007    end
 13008  
 13009  @ Here we want to change the coefficients from |scaled| to |fraction|,
 13010  except in the constant term. In the common case of a trivial equation
 13011  like `\.{x=3.14}', we will have |v=-fraction_one|, |q=p|, and |t=dependent|.
 13012  
 13013  @<Divide list |p| by |-v|, removing node |q|@>=
 13014  s:=temp_head; link(s):=p; r:=p;
 13015  repeat if r=q then
 13016    begin link(s):=link(r); free_node(r,dep_node_size);
 13017    end
 13018  else  begin w:=make_fraction(value(r),v);
 13019    if abs(w)<=half_fraction_threshold then
 13020      begin link(s):=link(r); free_node(r,dep_node_size);
 13021      end
 13022    else  begin value(r):=-w; s:=r;
 13023      end;
 13024    end;
 13025  r:=link(s);
 13026  until info(r)=null;
 13027  if t=proto_dependent then value(r):=-make_scaled(value(r),v)
 13028  else if v<>-fraction_one then value(r):=-make_fraction(value(r),v);
 13029  final_node:=r; p:=link(temp_head)
 13030  
 13031  @ @<Display the new dependency@>=
 13032  if interesting(x) then
 13033    begin begin_diagnostic; print_nl("## "); print_variable_name(x);
 13034  @:]]]\#\#_}{\.{\#\#}@>
 13035    w:=n;
 13036    while w>0 do
 13037      begin print("*4"); w:=w-2;
 13038      end;
 13039    print_char("="); print_dependency(p,dependent); end_diagnostic(false);
 13040    end
 13041  
 13042  @ @<Simplify all existing dependencies by substituting for |x|@>=
 13043  prev_r:=dep_head; r:=link(dep_head);
 13044  while r<>dep_head do
 13045    begin s:=dep_list(r); q:=p_with_x_becoming_q(s,x,p,type(r));
 13046    if info(q)=null then make_known(r,q)
 13047    else  begin dep_list(r):=q;
 13048      repeat q:=link(q);
 13049      until info(q)=null;
 13050      prev_r:=q;
 13051      end;
 13052    r:=link(prev_r);
 13053    end
 13054  
 13055  @ @<Change variable |x| from |independent| to |dependent| or |known|@>=
 13056  if n>0 then @<Divide list |p| by $2^n$@>;
 13057  if info(p)=null then
 13058    begin type(x):=known;
 13059    value(x):=value(p);
 13060    if abs(value(x))>=fraction_one then val_too_big(value(x));
 13061    free_node(p,dep_node_size);
 13062    if cur_exp=x then if cur_type=independent then
 13063      begin cur_exp:=value(x); cur_type:=known;
 13064      free_node(x,value_node_size);
 13065      end;
 13066    end
 13067  else  begin type(x):=dependent; dep_final:=final_node; new_dep(x,p);
 13068    if cur_exp=x then if cur_type=independent then cur_type:=dependent;
 13069    end
 13070  
 13071  @ @<Divide list |p| by $2^n$@>=
 13072  begin s:=temp_head; link(temp_head):=p; r:=p;
 13073  repeat if n>30 then w:=0
 13074  else w:=value(r) div two_to_the[n];
 13075  if (abs(w)<=half_fraction_threshold)and(info(r)<>null) then
 13076    begin link(s):=link(r);
 13077    free_node(r,dep_node_size);
 13078    end
 13079  else  begin value(r):=w; s:=r;
 13080    end;
 13081  r:=link(s);
 13082  until info(s)=null;
 13083  p:=link(temp_head);
 13084  end
 13085  
 13086  @ The |check_mem| procedure, which is used only when \MF\ is being
 13087  debugged, makes sure that the current dependency lists are well formed.
 13088  
 13089  @<Check the list of linear dependencies@>=
 13090  q:=dep_head; p:=link(q);
 13091  while p<>dep_head do
 13092    begin if prev_dep(p)<>q then
 13093      begin print_nl("Bad PREVDEP at "); print_int(p);
 13094  @.Bad PREVDEP...@>
 13095      end;
 13096    p:=dep_list(p); r:=inf_val;
 13097    repeat if value(info(p))>=value(r) then
 13098      begin print_nl("Out of order at "); print_int(p);
 13099  @.Out of order...@>
 13100      end;
 13101    r:=info(p); q:=p; p:=link(q);
 13102    until r=null;
 13103    end
 13104  
 13105  @* \[29] Dynamic nonlinear equations.
 13106  Variables of numeric type are maintained by the general scheme of
 13107  independent, dependent, and known values that we have just studied;
 13108  and the components of pair and transform variables are handled in the
 13109  same way. But \MF\ also has five other types of values: \&{boolean},
 13110  \&{string}, \&{pen}, \&{path}, and \&{picture}; what about them?
 13111  
 13112  Equations are allowed between nonlinear quantities, but only in a
 13113  simple form. Two variables that haven't yet been assigned values are
 13114  either equal to each other, or they're not.
 13115  
 13116  Before a boolean variable has received a value, its type is |unknown_boolean|;
 13117  similarly, there are variables whose type is |unknown_string|, |unknown_pen|,
 13118  |unknown_path|, and |unknown_picture|. In such cases the value is either
 13119  |null| (which means that no other variables are equivalent to this one), or
 13120  it points to another variable of the same undefined type. The pointers in the
 13121  latter case form a cycle of nodes, which we shall call a ``ring.''
 13122  Rings of undefined variables may include capsules, which arise as
 13123  intermediate results within expressions or as \&{expr} parameters to macros.
 13124  
 13125  When one member of a ring receives a value, the same value is given to
 13126  all the other members. In the case of paths and pictures, this implies
 13127  making separate copies of a potentially large data structure; users should
 13128  restrain their enthusiasm for such generality, unless they have lots and
 13129  lots of memory space.
 13130  
 13131  @ The following procedure is called when a capsule node is being
 13132  added to a ring (e.g., when an unknown variable is mentioned in an expression).
 13133  
 13134  @p function new_ring_entry(@!p:pointer):pointer;
 13135  var q:pointer; {the new capsule node}
 13136  begin q:=get_node(value_node_size); name_type(q):=capsule;
 13137  type(q):=type(p);
 13138  if value(p)=null then value(q):=p@+else value(q):=value(p);
 13139  value(p):=q;
 13140  new_ring_entry:=q;
 13141  end;
 13142  
 13143  @ Conversely, we might delete a capsule or a variable before it becomes known.
 13144  The following procedure simply detaches a quantity from its ring,
 13145  without recycling the storage.
 13146  
 13147  @<Declare the recycling subroutines@>=
 13148  procedure ring_delete(@!p:pointer);
 13149  var @!q:pointer;
 13150  begin q:=value(p);
 13151  if q<>null then if q<>p then
 13152    begin while value(q)<>p do q:=value(q);
 13153    value(q):=value(p);
 13154    end;
 13155  end;
 13156  
 13157  @ Eventually there might be an equation that assigns values to all of the
 13158  variables in a ring. The |nonlinear_eq| subroutine does the necessary
 13159  propagation of values.
 13160  
 13161  If the parameter |flush_p| is |true|, node |p| itself needn't receive a
 13162  value; it will soon be recycled.
 13163  
 13164  @p procedure nonlinear_eq(@!v:integer;@!p:pointer;@!flush_p:boolean);
 13165  var @!t:small_number; {the type of ring |p|}
 13166  @!q,@!r:pointer; {link manipulation registers}
 13167  begin t:=type(p)-unknown_tag; q:=value(p);
 13168  if flush_p then type(p):=vacuous@+else p:=q;
 13169  repeat r:=value(q); type(q):=t;
 13170  case t of
 13171  boolean_type: value(q):=v;
 13172  string_type: begin value(q):=v; add_str_ref(v);
 13173    end;
 13174  pen_type: begin value(q):=v; add_pen_ref(v);
 13175    end;
 13176  path_type: value(q):=copy_path(v);
 13177  picture_type: value(q):=copy_edges(v);
 13178  end; {there ain't no more cases}
 13179  q:=r;
 13180  until q=p;
 13181  end;
 13182  
 13183  @ If two members of rings are equated, and if they have the same type,
 13184  the |ring_merge| procedure is called on to make them equivalent.
 13185  
 13186  @p procedure ring_merge(@!p,@!q:pointer);
 13187  label exit;
 13188  var @!r:pointer; {traverses one list}
 13189  begin r:=value(p);
 13190  while r<>p do
 13191    begin if r=q then
 13192      begin @<Exclaim about a redundant equation@>;
 13193      return;
 13194      end;
 13195    r:=value(r);
 13196    end;
 13197  r:=value(p); value(p):=value(q); value(q):=r;
 13198  exit:end;
 13199  
 13200  @ @<Exclaim about a redundant equation@>=
 13201  begin print_err("Redundant equation");@/
 13202  @.Redundant equation@>
 13203  help2("I already knew that this equation was true.")@/
 13204    ("But perhaps no harm has been done; let's continue.");@/
 13205  put_get_error;
 13206  end
 13207  
 13208  @* \[30] Introduction to the syntactic routines.
 13209  Let's pause a moment now and try to look at the Big Picture.
 13210  The \MF\ program consists of three main parts: syntactic routines,
 13211  semantic routines, and output routines. The chief purpose of the
 13212  syntactic routines is to deliver the user's input to the semantic routines,
 13213  while parsing expressions and locating operators and operands. The
 13214  semantic routines act as an interpreter responding to these operators,
 13215  which may be regarded as commands. And the output routines are
 13216  periodically called on to produce compact font descriptions that can be
 13217  used for typesetting or for making interim proof drawings. We have
 13218  discussed the basic data structures and many of the details of semantic
 13219  operations, so we are good and ready to plunge into the part of \MF\ that
 13220  actually controls the activities.
 13221  
 13222  Our current goal is to come to grips with the |get_next| procedure,
 13223  which is the keystone of \MF's input mechanism. Each call of |get_next|
 13224  sets the value of three variables |cur_cmd|, |cur_mod|, and |cur_sym|,
 13225  representing the next input token.
 13226  $$\vbox{\halign{#\hfil\cr
 13227    \hbox{|cur_cmd| denotes a command code from the long list of codes
 13228     given earlier;}\cr
 13229    \hbox{|cur_mod| denotes a modifier of the command code;}\cr
 13230    \hbox{|cur_sym| is the hash address of the symbolic token that was
 13231     just scanned,}\cr
 13232    \hbox{\qquad or zero in the case of a numeric or string
 13233     or capsule token.}\cr}}$$
 13234  Underlying this external behavior of |get_next| is all the machinery
 13235  necessary to convert from character files to tokens. At a given time we
 13236  may be only partially finished with the reading of several files (for
 13237  which \&{input} was specified), and partially finished with the expansion
 13238  of some user-defined macros and/or some macro parameters, and partially
 13239  finished reading some text that the user has inserted online,
 13240  and so on. When reading a character file, the characters must be
 13241  converted to tokens; comments and blank spaces must
 13242  be removed, numeric and string tokens must be evaluated.
 13243  
 13244  To handle these situations, which might all be present simultaneously,
 13245  \MF\ uses various stacks that hold information about the incomplete
 13246  activities, and there is a finite state control for each level of the
 13247  input mechanism. These stacks record the current state of an implicitly
 13248  recursive process, but the |get_next| procedure is not recursive.
 13249  
 13250  @<Glob...@>=
 13251  @!cur_cmd: eight_bits; {current command set by |get_next|}
 13252  @!cur_mod: integer; {operand of current command}
 13253  @!cur_sym: halfword; {hash address of current symbol}
 13254  
 13255  @ The |print_cmd_mod| routine prints a symbolic interpretation of a
 13256  command code and its modifier.
 13257  It consists of a rather tedious sequence of print
 13258  commands, and most of it is essentially an inverse to the |primitive|
 13259  routine that enters a \MF\ primitive into |hash| and |eqtb|. Therefore almost
 13260  all of this procedure appears elsewhere in the program, together with the
 13261  corresponding |primitive| calls.
 13262  
 13263  @<Declare the procedure called |print_cmd_mod|@>=
 13264  procedure print_cmd_mod(@!c,@!m:integer);
 13265  begin case c of
 13266  @t\4@>@<Cases of |print_cmd_mod| for symbolic printing of primitives@>@/
 13267  othercases print("[unknown command code!]")
 13268  endcases;
 13269  end;
 13270  
 13271  @ Here is a procedure that displays a given command in braces, in the
 13272  user's transcript file.
 13273  
 13274  @d show_cur_cmd_mod==show_cmd_mod(cur_cmd,cur_mod)
 13275  
 13276  @p procedure show_cmd_mod(@!c,@!m:integer);
 13277  begin begin_diagnostic; print_nl("{");
 13278  print_cmd_mod(c,m); print_char("}");
 13279  end_diagnostic(false);
 13280  end;
 13281  
 13282  @* \[31] Input stacks and states.
 13283  The state of \MF's input mechanism appears in the input stack, whose
 13284  entries are records with five fields, called |index|, |start|, |loc|,
 13285  |limit|, and |name|. The top element of this stack is maintained in a
 13286  global variable for which no subscripting needs to be done; the other
 13287  elements of the stack appear in an array. Hence the stack is declared thus:
 13288  
 13289  @<Types...@>=
 13290  @!in_state_record = record
 13291    @!index_field: quarterword;
 13292    @!start_field,@!loc_field, @!limit_field, @!name_field: halfword;
 13293    end;
 13294  
 13295  @ @<Glob...@>=
 13296  @!input_stack : array[0..stack_size] of in_state_record;
 13297  @!input_ptr : 0..stack_size; {first unused location of |input_stack|}
 13298  @!max_in_stack: 0..stack_size; {largest value of |input_ptr| when pushing}
 13299  @!cur_input : in_state_record; {the ``top'' input state}
 13300  
 13301  @ We've already defined the special variable |@!loc==cur_input.loc_field|
 13302  in our discussion of basic input-output routines. The other components of
 13303  |cur_input| are defined in the same way:
 13304  
 13305  @d index==cur_input.index_field {reference for buffer information}
 13306  @d start==cur_input.start_field {starting position in |buffer|}
 13307  @d limit==cur_input.limit_field {end of current line in |buffer|}
 13308  @d name==cur_input.name_field {name of the current file}
 13309  
 13310  @ Let's look more closely now at the five control variables
 13311  (|index|,~|start|,~|loc|,~|limit|,~|name|),
 13312  assuming that \MF\ is reading a line of characters that have been input
 13313  from some file or from the user's terminal. There is an array called
 13314  |buffer| that acts as a stack of all lines of characters that are
 13315  currently being read from files, including all lines on subsidiary
 13316  levels of the input stack that are not yet completed. \MF\ will return to
 13317  the other lines when it is finished with the present input file.
 13318  
 13319  (Incidentally, on a machine with byte-oriented addressing, it would be
 13320  appropriate to combine |buffer| with the |str_pool| array,
 13321  letting the buffer entries grow downward from the top of the string pool
 13322  and checking that these two tables don't bump into each other.)
 13323  
 13324  The line we are currently working on begins in position |start| of the
 13325  buffer; the next character we are about to read is |buffer[loc]|; and
 13326  |limit| is the location of the last character present. We always have
 13327  |loc<=limit|. For convenience, |buffer[limit]| has been set to |"%"|, so
 13328  that the end of a line is easily sensed.
 13329  
 13330  The |name| variable is a string number that designates the name of
 13331  the current file, if we are reading a text file. It is 0 if we
 13332  are reading from the terminal for normal input, or 1 if we are executing a
 13333  \&{readstring} command, or 2 if we are reading a string that was
 13334  moved into the buffer by \&{scantokens}.
 13335  
 13336  @ Additional information about the current line is available via the
 13337  |index| variable, which counts how many lines of characters are present
 13338  in the buffer below the current level. We have |index=0| when reading
 13339  from the terminal and prompting the user for each line; then if the user types,
 13340  e.g., `\.{input font}', we will have |index=1| while reading
 13341  the file \.{font.mf}. However, it does not follow that |index| is the
 13342  same as the input stack pointer, since many of the levels on the input
 13343  stack may come from token lists.
 13344  
 13345  The global variable |in_open| is equal to the |index|
 13346  value of the highest non-token-list level. Thus, the number of partially read
 13347  lines in the buffer is |in_open+1|, and we have |in_open=index|
 13348  when we are not reading a token list.
 13349  
 13350  If we are not currently reading from the terminal,
 13351  we are reading from the file variable |input_file[index]|. We use
 13352  the notation |terminal_input| as a convenient abbreviation for |name=0|,
 13353  and |cur_file| as an abbreviation for |input_file[index]|.
 13354  
 13355  The global variable |line| contains the line number in the topmost
 13356  open file, for use in error messages. If we are not reading from
 13357  the terminal, |line_stack[index]| holds the line number for the
 13358  enclosing level, so that |line| can be restored when the current
 13359  file has been read.
 13360  
 13361  If more information about the input state is needed, it can be
 13362  included in small arrays like those shown here. For example,
 13363  the current page or segment number in the input file might be
 13364  put into a variable |@!page|, maintained for enclosing levels in
 13365  `\ignorespaces|@!page_stack:array[1..max_in_open] of integer|\unskip'
 13366  by analogy with |line_stack|.
 13367  @^system dependencies@>
 13368  
 13369  @d terminal_input==(name=0) {are we reading from the terminal?}
 13370  @d cur_file==input_file[index] {the current |alpha_file| variable}
 13371  
 13372  @<Glob...@>=
 13373  @!in_open : 0..max_in_open; {the number of lines in the buffer, less one}
 13374  @!open_parens : 0..max_in_open; {the number of open text files}
 13375  @!input_file : array[1..max_in_open] of alpha_file;
 13376  @!line : integer; {current line number in the current source file}
 13377  @!line_stack : array[1..max_in_open] of integer;
 13378  
 13379  @ However, all this discussion about input state really applies only to the
 13380  case that we are inputting from a file. There is another important case,
 13381  namely when we are currently getting input from a token list. In this case
 13382  |index>max_in_open|, and the conventions about the other state variables
 13383  are different:
 13384  
 13385  \yskip\hang|loc| is a pointer to the current node in the token list, i.e.,
 13386  the node that will be read next. If |loc=null|, the token list has been
 13387  fully read.
 13388  
 13389  \yskip\hang|start| points to the first node of the token list; this node
 13390  may or may not contain a reference count, depending on the type of token
 13391  list involved.
 13392  
 13393  \yskip\hang|token_type|, which takes the place of |index| in the
 13394  discussion above, is a code number that explains what kind of token list
 13395  is being scanned.
 13396  
 13397  \yskip\hang|name| points to the |eqtb| address of the macro
 13398  being expanded, if the current token list is a macro not defined by
 13399  \&{vardef}. Macros defined by \&{vardef} have |name=null|; their name
 13400  can be deduced by looking at their first two parameters.
 13401  
 13402  \yskip\hang|param_start|, which takes the place of |limit|, tells where
 13403  the parameters of the current macro or loop text begin in the |param_stack|.
 13404  
 13405  \yskip\noindent The |token_type| can take several values, depending on
 13406  where the current token list came from:
 13407  
 13408  \yskip
 13409  \indent|forever_text|, if the token list being scanned is the body of
 13410  a \&{forever} loop;
 13411  
 13412  \indent|loop_text|, if the token list being scanned is the body of
 13413  a \&{for} or \&{forsuffixes} loop;
 13414  
 13415  \indent|parameter|, if a \&{text} or \&{suffix} parameter is being scanned;
 13416  
 13417  \indent|backed_up|, if the token list being scanned has been inserted as
 13418  `to be read again';
 13419  
 13420  \indent|inserted|, if the token list being scanned has been inserted as
 13421  part of error recovery;
 13422  
 13423  \indent|macro|, if the expansion of a user-defined symbolic token is being
 13424  scanned.
 13425  
 13426  \yskip\noindent
 13427  The token list begins with a reference count if and only if |token_type=
 13428  macro|.
 13429  @^reference counts@>
 13430  
 13431  @d token_type==index {type of current token list}
 13432  @d token_state==(index>max_in_open) {are we scanning a token list?}
 13433  @d file_state==(index<=max_in_open) {are we scanning a file line?}
 13434  @d param_start==limit {base of macro parameters in |param_stack|}
 13435  @d forever_text=max_in_open+1 {|token_type| code for loop texts}
 13436  @d loop_text=max_in_open+2 {|token_type| code for loop texts}
 13437  @d parameter=max_in_open+3 {|token_type| code for parameter texts}
 13438  @d backed_up=max_in_open+4 {|token_type| code for texts to be reread}
 13439  @d inserted=max_in_open+5 {|token_type| code for inserted texts}
 13440  @d macro=max_in_open+6 {|token_type| code for macro replacement texts}
 13441  
 13442  @ The |param_stack| is an auxiliary array used to hold pointers to the token
 13443  lists for parameters at the current level and subsidiary levels of input.
 13444  This stack grows at a different rate from the others.
 13445  
 13446  @<Glob...@>=
 13447  @!param_stack:array [0..param_size] of pointer;
 13448    {token list pointers for parameters}
 13449  @!param_ptr:0..param_size; {first unused entry in |param_stack|}
 13450  @!max_param_stack:integer;
 13451    {largest value of |param_ptr|}
 13452  
 13453  @ Thus, the ``current input state'' can be very complicated indeed; there
 13454  can be many levels and each level can arise in a variety of ways. The
 13455  |show_context| procedure, which is used by \MF's error-reporting routine to
 13456  print out the current input state on all levels down to the most recent
 13457  line of characters from an input file, illustrates most of these conventions.
 13458  The global variable |file_ptr| contains the lowest level that was
 13459  displayed by this procedure.
 13460  
 13461  @<Glob...@>=
 13462  @!file_ptr:0..stack_size; {shallowest level shown by |show_context|}
 13463  
 13464  @ The status at each level is indicated by printing two lines, where the first
 13465  line indicates what was read so far and the second line shows what remains
 13466  to be read. The context is cropped, if necessary, so that the first line
 13467  contains at most |half_error_line| characters, and the second contains
 13468  at most |error_line|. Non-current input levels whose |token_type| is
 13469  `|backed_up|' are shown only if they have not been fully read.
 13470  
 13471  @p procedure show_context; {prints where the scanner is}
 13472  label done;
 13473  var @!old_setting:0..max_selector; {saved |selector| setting}
 13474  @<Local variables for formatting calculations@>@/
 13475  begin file_ptr:=input_ptr; input_stack[file_ptr]:=cur_input;
 13476    {store current state}
 13477  loop@+begin cur_input:=input_stack[file_ptr]; {enter into the context}
 13478    @<Display the current context@>;
 13479    if file_state then
 13480      if (name>2) or (file_ptr=0) then goto done;
 13481    decr(file_ptr);
 13482    end;
 13483  done: cur_input:=input_stack[input_ptr]; {restore original state}
 13484  end;
 13485  
 13486  @ @<Display the current context@>=
 13487  if (file_ptr=input_ptr) or file_state or
 13488     (token_type<>backed_up) or (loc<>null) then
 13489      {we omit backed-up token lists that have already been read}
 13490    begin tally:=0; {get ready to count characters}
 13491    old_setting:=selector;
 13492    if file_state then
 13493      begin @<Print location of current line@>;
 13494      @<Pseudoprint the line@>;
 13495      end
 13496    else  begin @<Print type of token list@>;
 13497      @<Pseudoprint the token list@>;
 13498      end;
 13499    selector:=old_setting; {stop pseudoprinting}
 13500    @<Print two lines using the tricky pseudoprinted information@>;
 13501    end
 13502  
 13503  @ This routine should be changed, if necessary, to give the best possible
 13504  indication of where the current line resides in the input file.
 13505  For example, on some systems it is best to print both a page and line number.
 13506  @^system dependencies@>
 13507  
 13508  @<Print location of current line@>=
 13509  if name<=1 then
 13510    if terminal_input and(file_ptr=0) then print_nl("<*>")
 13511    else print_nl("<insert>")
 13512  else if name=2 then print_nl("<scantokens>")
 13513  else  begin print_nl("l."); print_int(line);
 13514    end;
 13515  print_char(" ")
 13516  
 13517  @ @<Print type of token list@>=
 13518  case token_type of
 13519  forever_text: print_nl("<forever> ");
 13520  loop_text: @<Print the current loop value@>;
 13521  parameter: print_nl("<argument> ");
 13522  backed_up: if loc=null then print_nl("<recently read> ")
 13523    else print_nl("<to be read again> ");
 13524  inserted: print_nl("<inserted text> ");
 13525  macro: begin print_ln;
 13526    if name<>null then slow_print(text(name))
 13527    else @<Print the name of a \&{vardef}'d macro@>;
 13528    print("->");
 13529    end;
 13530  othercases print_nl("?") {this should never happen}
 13531  @.?\relax@>
 13532  endcases
 13533  
 13534  @ The parameter that corresponds to a loop text is either a token list
 13535  (in the case of \&{forsuffixes}) or a ``capsule'' (in the case of \&{for}).
 13536  We'll discuss capsules later; for now, all we need to know is that
 13537  the |link| field in a capsule parameter is |void| and that
 13538  |print_exp(p,0)| displays the value of capsule~|p| in abbreviated form.
 13539  
 13540  @<Print the current loop value@>=
 13541  begin print_nl("<for("); p:=param_stack[param_start];
 13542  if p<>null then
 13543    if link(p)=void then print_exp(p,0) {we're in a \&{for} loop}
 13544    else show_token_list(p,null,20,tally);
 13545  print(")> ");
 13546  end
 13547  
 13548  @ The first two parameters of a macro defined by \&{vardef} will be token
 13549  lists representing the macro's prefix and ``at point.'' By putting these
 13550  together, we get the macro's full name.
 13551  
 13552  @<Print the name of a \&{vardef}'d macro@>=
 13553  begin p:=param_stack[param_start];
 13554  if p=null then show_token_list(param_stack[param_start+1],null,20,tally)
 13555  else  begin q:=p;
 13556    while link(q)<>null do q:=link(q);
 13557    link(q):=param_stack[param_start+1];
 13558    show_token_list(p,null,20,tally);
 13559    link(q):=null;
 13560    end;
 13561  end
 13562  
 13563  @ Now it is necessary to explain a little trick. We don't want to store a long
 13564  string that corresponds to a token list, because that string might take up
 13565  lots of memory; and we are printing during a time when an error message is
 13566  being given, so we dare not do anything that might overflow one of \MF's
 13567  tables. So `pseudoprinting' is the answer: We enter a mode of printing
 13568  that stores characters into a buffer of length |error_line|, where character
 13569  $k+1$ is placed into \hbox{|trick_buf[k mod error_line]|} if
 13570  |k<trick_count|, otherwise character |k| is dropped. Initially we set
 13571  |tally:=0| and |trick_count:=1000000|; then when we reach the
 13572  point where transition from line 1 to line 2 should occur, we
 13573  set |first_count:=tally| and |trick_count:=@tmax@>(error_line,
 13574  tally+1+error_line-half_error_line)|. At the end of the
 13575  pseudoprinting, the values of |first_count|, |tally|, and
 13576  |trick_count| give us all the information we need to print the two lines,
 13577  and all of the necessary text is in |trick_buf|.
 13578  
 13579  Namely, let |l| be the length of the descriptive information that appears
 13580  on the first line. The length of the context information gathered for that
 13581  line is |k=first_count|, and the length of the context information
 13582  gathered for line~2 is $m=\min(|tally|, |trick_count|)-k$. If |l+k<=h|,
 13583  where |h=half_error_line|, we print |trick_buf[0..k-1]| after the
 13584  descriptive information on line~1, and set |n:=l+k|; here |n| is the
 13585  length of line~1. If $l+k>h$, some cropping is necessary, so we set |n:=h|
 13586  and print `\.{...}' followed by
 13587  $$\hbox{|trick_buf[(l+k-h+3)..k-1]|,}$$
 13588  where subscripts of |trick_buf| are circular modulo |error_line|. The
 13589  second line consists of |n|~spaces followed by |trick_buf[k..(k+m-1)]|,
 13590  unless |n+m>error_line|; in the latter case, further cropping is done.
 13591  This is easier to program than to explain.
 13592  
 13593  @<Local variables for formatting...@>=
 13594  @!i:0..buf_size; {index into |buffer|}
 13595  @!l:integer; {length of descriptive information on line 1}
 13596  @!m:integer; {context information gathered for line 2}
 13597  @!n:0..error_line; {length of line 1}
 13598  @!p: integer; {starting or ending place in |trick_buf|}
 13599  @!q: integer; {temporary index}
 13600  
 13601  @ The following code tells the print routines to gather
 13602  the desired information.
 13603  
 13604  @d begin_pseudoprint==
 13605    begin l:=tally; tally:=0; selector:=pseudo;
 13606    trick_count:=1000000;
 13607    end
 13608  @d set_trick_count==
 13609    begin first_count:=tally;
 13610    trick_count:=tally+1+error_line-half_error_line;
 13611    if trick_count<error_line then trick_count:=error_line;
 13612    end
 13613  
 13614  @ And the following code uses the information after it has been gathered.
 13615  
 13616  @<Print two lines using the tricky pseudoprinted information@>=
 13617  if trick_count=1000000 then set_trick_count;
 13618    {|set_trick_count| must be performed}
 13619  if tally<trick_count then m:=tally-first_count
 13620  else m:=trick_count-first_count; {context on line 2}
 13621  if l+first_count<=half_error_line then
 13622    begin p:=0; n:=l+first_count;
 13623    end
 13624  else  begin print("..."); p:=l+first_count-half_error_line+3;
 13625    n:=half_error_line;
 13626    end;
 13627  for q:=p to first_count-1 do print_char(trick_buf[q mod error_line]);
 13628  print_ln;
 13629  for q:=1 to n do print_char(" "); {print |n| spaces to begin line~2}
 13630  if m+n<=error_line then p:=first_count+m else p:=first_count+(error_line-n-3);
 13631  for q:=first_count to p-1 do print_char(trick_buf[q mod error_line]);
 13632  if m+n>error_line then print("...")
 13633  
 13634  @ But the trick is distracting us from our current goal, which is to
 13635  understand the input state. So let's concentrate on the data structures that
 13636  are being pseudoprinted as we finish up the |show_context| procedure.
 13637  
 13638  @<Pseudoprint the line@>=
 13639  begin_pseudoprint;
 13640  if limit>0 then for i:=start to limit-1 do
 13641    begin if i=loc then set_trick_count;
 13642    print(buffer[i]);
 13643    end
 13644  
 13645  @ @<Pseudoprint the token list@>=
 13646  begin_pseudoprint;
 13647  if token_type<>macro then show_token_list(start,loc,100000,0)
 13648  else show_macro(start,loc,100000)
 13649  
 13650  @ Here is the missing piece of |show_token_list| that is activated when the
 13651  token beginning line~2 is about to be shown:
 13652  
 13653  @<Do magic computation@>=set_trick_count
 13654  
 13655  @* \[32] Maintaining the input stacks.
 13656  The following subroutines change the input status in commonly needed ways.
 13657  
 13658  First comes |push_input|, which stores the current state and creates a
 13659  new level (having, initially, the same properties as the old).
 13660  
 13661  @d push_input==@t@> {enter a new input level, save the old}
 13662    begin if input_ptr>max_in_stack then
 13663      begin max_in_stack:=input_ptr;
 13664      if input_ptr=stack_size then overflow("input stack size",stack_size);
 13665  @:METAFONT capacity exceeded input stack size}{\quad input stack size@>
 13666      end;
 13667    input_stack[input_ptr]:=cur_input; {stack the record}
 13668    incr(input_ptr);
 13669    end
 13670  
 13671  @ And of course what goes up must come down.
 13672  
 13673  @d pop_input==@t@> {leave an input level, re-enter the old}
 13674    begin decr(input_ptr); cur_input:=input_stack[input_ptr];
 13675    end
 13676  
 13677  @ Here is a procedure that starts a new level of token-list input, given
 13678  a token list |p| and its type |t|. If |t=macro|, the calling routine should
 13679  set |name|, reset~|loc|, and increase the macro's reference count.
 13680  
 13681  @d back_list(#)==begin_token_list(#,backed_up) {backs up a simple token list}
 13682  
 13683  @p procedure begin_token_list(@!p:pointer;@!t:quarterword);
 13684  begin push_input; start:=p; token_type:=t;
 13685  param_start:=param_ptr; loc:=p;
 13686  end;
 13687  
 13688  @ When a token list has been fully scanned, the following computations
 13689  should be done as we leave that level of input.
 13690  @^inner loop@>
 13691  
 13692  @p procedure end_token_list; {leave a token-list input level}
 13693  label done;
 13694  var @!p:pointer; {temporary register}
 13695  begin if token_type>=backed_up then {token list to be deleted}
 13696    if token_type<=inserted then
 13697      begin flush_token_list(start); goto done;
 13698      end
 13699    else delete_mac_ref(start); {update reference count}
 13700  while param_ptr>param_start do {parameters must be flushed}
 13701    begin decr(param_ptr);
 13702    p:=param_stack[param_ptr];
 13703    if p<>null then
 13704      if link(p)=void then {it's an \&{expr} parameter}
 13705        begin recycle_value(p); free_node(p,value_node_size);
 13706        end
 13707      else flush_token_list(p); {it's a \&{suffix} or \&{text} parameter}
 13708    end;
 13709  done: pop_input; check_interrupt;
 13710  end;
 13711  
 13712  @ The contents of |cur_cmd,cur_mod,cur_sym| are placed into an equivalent
 13713  token by the |cur_tok| routine.
 13714  @^inner loop@>
 13715  
 13716  @p @t\4@>@<Declare the procedure called |make_exp_copy|@>@;@/
 13717  function cur_tok:pointer;
 13718  var @!p:pointer; {a new token node}
 13719  @!save_type:small_number; {|cur_type| to be restored}
 13720  @!save_exp:integer; {|cur_exp| to be restored}
 13721  begin if cur_sym=0 then
 13722    if cur_cmd=capsule_token then
 13723      begin save_type:=cur_type; save_exp:=cur_exp;
 13724      make_exp_copy(cur_mod); p:=stash_cur_exp; link(p):=null;
 13725      cur_type:=save_type; cur_exp:=save_exp;
 13726      end
 13727    else  begin p:=get_node(token_node_size);
 13728      value(p):=cur_mod; name_type(p):=token;
 13729      if cur_cmd=numeric_token then type(p):=known
 13730      else type(p):=string_type;
 13731      end
 13732  else  begin fast_get_avail(p); info(p):=cur_sym;
 13733    end;
 13734  cur_tok:=p;
 13735  end;
 13736  
 13737  @ Sometimes \MF\ has read too far and wants to ``unscan'' what it has
 13738  seen. The |back_input| procedure takes care of this by putting the token
 13739  just scanned back into the input stream, ready to be read again.
 13740  If |cur_sym<>0|, the values of |cur_cmd| and |cur_mod| are irrelevant.
 13741  
 13742  @p procedure back_input; {undoes one token of input}
 13743  var @!p:pointer; {a token list of length one}
 13744  begin p:=cur_tok;
 13745  while token_state and(loc=null) do end_token_list; {conserve stack space}
 13746  back_list(p);
 13747  end;
 13748  
 13749  @ The |back_error| routine is used when we want to restore or replace an
 13750  offending token just before issuing an error message.  We disable interrupts
 13751  during the call of |back_input| so that the help message won't be lost.
 13752  
 13753  @p procedure back_error; {back up one token and call |error|}
 13754  begin OK_to_interrupt:=false; back_input; OK_to_interrupt:=true; error;
 13755  end;
 13756  @#
 13757  procedure ins_error; {back up one inserted token and call |error|}
 13758  begin OK_to_interrupt:=false; back_input; token_type:=inserted;
 13759  OK_to_interrupt:=true; error;
 13760  end;
 13761  
 13762  @ The |begin_file_reading| procedure starts a new level of input for lines
 13763  of characters to be read from a file, or as an insertion from the
 13764  terminal. It does not take care of opening the file, nor does it set |loc|
 13765  or |limit| or |line|.
 13766  @^system dependencies@>
 13767  
 13768  @p procedure begin_file_reading;
 13769  begin if in_open=max_in_open then overflow("text input levels",max_in_open);
 13770  @:METAFONT capacity exceeded text input levels}{\quad text input levels@>
 13771  if first=buf_size then overflow("buffer size",buf_size);
 13772  @:METAFONT capacity exceeded buffer size}{\quad buffer size@>
 13773  incr(in_open); push_input; index:=in_open;
 13774  line_stack[index]:=line; start:=first;
 13775  name:=0; {|terminal_input| is now |true|}
 13776  end;
 13777  
 13778  @ Conversely, the variables must be downdated when such a level of input
 13779  is finished:
 13780  
 13781  @p procedure end_file_reading;
 13782  begin first:=start; line:=line_stack[index];
 13783  if index<>in_open then confusion("endinput");
 13784  @:this can't happen endinput}{\quad endinput@>
 13785  if name>2 then a_close(cur_file); {forget it}
 13786  pop_input; decr(in_open);
 13787  end;
 13788  
 13789  @ In order to keep the stack from overflowing during a long sequence of
 13790  inserted `\.{show}' commands, the following routine removes completed
 13791  error-inserted lines from memory.
 13792  
 13793  @p procedure clear_for_error_prompt;
 13794  begin while file_state and terminal_input and@|
 13795    (input_ptr>0)and(loc=limit) do end_file_reading;
 13796  print_ln; clear_terminal;
 13797  end;
 13798  
 13799  @ To get \MF's whole input mechanism going, we perform the following
 13800  actions.
 13801  
 13802  @<Initialize the input routines@>=
 13803  begin input_ptr:=0; max_in_stack:=0;
 13804  in_open:=0; open_parens:=0; max_buf_stack:=0;
 13805  param_ptr:=0; max_param_stack:=0;
 13806  first:=1;
 13807  start:=1; index:=0; line:=0; name:=0;
 13808  force_eof:=false;
 13809  if not init_terminal then goto final_end;
 13810  limit:=last; first:=last+1; {|init_terminal| has set |loc| and |last|}
 13811  end;
 13812  
 13813  @* \[33] Getting the next token.
 13814  The heart of \MF's input mechanism is the |get_next| procedure, which
 13815  we shall develop in the next few sections of the program. Perhaps we
 13816  shouldn't actually call it the ``heart,'' however; it really acts as \MF's
 13817  eyes and mouth, reading the source files and gobbling them up. And it also
 13818  helps \MF\ to regurgitate stored token lists that are to be processed again.
 13819  
 13820  The main duty of |get_next| is to input one token and to set |cur_cmd|
 13821  and |cur_mod| to that token's command code and modifier. Furthermore, if
 13822  the input token is a symbolic token, that token's |hash| address
 13823  is stored in |cur_sym|; otherwise |cur_sym| is set to zero.
 13824  
 13825  Underlying this simple description is a certain amount of complexity
 13826  because of all the cases that need to be handled.
 13827  However, the inner loop of |get_next| is reasonably short and fast.
 13828  
 13829  @ Before getting into |get_next|, we need to consider a mechanism by which
 13830  \MF\ helps keep errors from propagating too far. Whenever the program goes
 13831  into a mode where it keeps calling |get_next| repeatedly until a certain
 13832  condition is met, it sets |scanner_status| to some value other than |normal|.
 13833  Then if an input file ends, or if an `\&{outer}' symbol appears,
 13834  an appropriate error recovery will be possible.
 13835  
 13836  The global variable |warning_info| helps in this error recovery by providing
 13837  additional information. For example, |warning_info| might indicate the
 13838  name of a macro whose replacement text is being scanned.
 13839  
 13840  @d normal=0 {|scanner_status| at ``quiet times''}
 13841  @d skipping=1 {|scanner_status| when false conditional text is being skipped}
 13842  @d flushing=2 {|scanner_status| when junk after a statement is being ignored}
 13843  @d absorbing=3 {|scanner_status| when a \&{text} parameter is being scanned}
 13844  @d var_defining=4 {|scanner_status| when a \&{vardef} is being scanned}
 13845  @d op_defining=5 {|scanner_status| when a macro \&{def} is being scanned}
 13846  @d loop_defining=6 {|scanner_status| when a \&{for} loop is being scanned}
 13847  
 13848  @<Glob...@>=
 13849  @!scanner_status:normal..loop_defining; {are we scanning at high speed?}
 13850  @!warning_info:integer; {if so, what else do we need to know,
 13851      in case an error occurs?}
 13852  
 13853  @ @<Initialize the input routines@>=
 13854  scanner_status:=normal;
 13855  
 13856  @ The following subroutine
 13857  is called when an `\&{outer}' symbolic token has been scanned or
 13858  when the end of a file has been reached. These two cases are distinguished
 13859  by |cur_sym|, which is zero at the end of a file.
 13860  
 13861  @p function check_outer_validity:boolean;
 13862  var @!p:pointer; {points to inserted token list}
 13863  begin if scanner_status=normal then check_outer_validity:=true
 13864  else  begin deletions_allowed:=false;
 13865    @<Back up an outer symbolic token so that it can be reread@>;
 13866    if scanner_status>skipping then
 13867      @<Tell the user what has run away and try to recover@>
 13868    else  begin print_err("Incomplete if; all text was ignored after line ");
 13869  @.Incomplete if...@>
 13870      print_int(warning_info);@/
 13871      help3("A forbidden `outer' token occurred in skipped text.")@/
 13872      ("This kind of error happens when you say `if...' and forget")@/
 13873      ("the matching `fi'. I've inserted a `fi'; this might work.");
 13874      if cur_sym=0 then help_line[2]:=@|
 13875        "The file ended while I was skipping conditional text.";
 13876      cur_sym:=frozen_fi; ins_error;
 13877      end;
 13878    deletions_allowed:=true; check_outer_validity:=false;
 13879    end;
 13880  end;
 13881  
 13882  @ @<Back up an outer symbolic token so that it can be reread@>=
 13883  if cur_sym<>0 then
 13884    begin p:=get_avail; info(p):=cur_sym;
 13885    back_list(p); {prepare to read the symbolic token again}
 13886    end
 13887  
 13888  @ @<Tell the user what has run away...@>=
 13889  begin runaway; {print the definition-so-far}
 13890  if cur_sym=0 then print_err("File ended")
 13891  @.File ended while scanning...@>
 13892  else  begin print_err("Forbidden token found");
 13893  @.Forbidden token found...@>
 13894    end;
 13895  print(" while scanning ");
 13896  help4("I suspect you have forgotten an `enddef',")@/
 13897  ("causing me to read past where you wanted me to stop.")@/
 13898  ("I'll try to recover; but if the error is serious,")@/
 13899  ("you'd better type `E' or `X' now and fix your file.");@/
 13900  case scanner_status of
 13901  @t\4@>@<Complete the error message,
 13902    and set |cur_sym| to a token that might help recover from the error@>@;
 13903  end; {there are no other cases}
 13904  ins_error;
 13905  end
 13906  
 13907  @ As we consider various kinds of errors, it is also appropriate to
 13908  change the first line of the help message just given; |help_line[3]|
 13909  points to the string that might be changed.
 13910  
 13911  @<Complete the error message,...@>=
 13912  flushing: begin print("to the end of the statement");
 13913    help_line[3]:="A previous error seems to have propagated,";
 13914    cur_sym:=frozen_semicolon;
 13915    end;
 13916  absorbing: begin print("a text argument");
 13917    help_line[3]:="It seems that a right delimiter was left out,";
 13918    if warning_info=0 then cur_sym:=frozen_end_group
 13919    else  begin cur_sym:=frozen_right_delimiter;
 13920      equiv(frozen_right_delimiter):=warning_info;
 13921      end;
 13922    end;
 13923  var_defining, op_defining: begin print("the definition of ");
 13924    if scanner_status=op_defining then slow_print(text(warning_info))
 13925    else print_variable_name(warning_info);
 13926    cur_sym:=frozen_end_def;
 13927    end;
 13928  loop_defining: begin print("the text of a "); slow_print(text(warning_info));
 13929    print(" loop");
 13930    help_line[3]:="I suspect you have forgotten an `endfor',";
 13931    cur_sym:=frozen_end_for;
 13932    end;
 13933  
 13934  @ The |runaway| procedure displays the first part of the text that occurred
 13935  when \MF\ began its special |scanner_status|, if that text has been saved.
 13936  
 13937  @<Declare the procedure called |runaway|@>=
 13938  procedure runaway;
 13939  begin if scanner_status>flushing then
 13940    begin print_nl("Runaway ");
 13941    case scanner_status of
 13942    absorbing: print("text?");
 13943    var_defining,op_defining: print("definition?");
 13944    loop_defining: print("loop?");
 13945    end; {there are no other cases}
 13946    print_ln; show_token_list(link(hold_head),null,error_line-10,0);
 13947    end;
 13948  end;
 13949  
 13950  @ We need to mention a procedure that may be called by |get_next|.
 13951  
 13952  @p procedure@?firm_up_the_line; forward;
 13953  
 13954  @ And now we're ready to take the plunge into |get_next| itself.
 13955  
 13956  @d switch=25 {a label in |get_next|}
 13957  @d start_numeric_token=85 {another}
 13958  @d start_decimal_token=86 {and another}
 13959  @d fin_numeric_token=87
 13960    {and still another, although |goto| is considered harmful}
 13961  
 13962  @p procedure get_next; {sets |cur_cmd|, |cur_mod|, |cur_sym| to next token}
 13963  @^inner loop@>
 13964  label restart, {go here to get the next input token}
 13965    exit, {go here when the next input token has been got}
 13966    found, {go here when the end of a symbolic token has been found}
 13967    switch, {go here to branch on the class of an input character}
 13968    start_numeric_token,start_decimal_token,fin_numeric_token,done;
 13969      {go here at crucial stages when scanning a number}
 13970  var @!k:0..buf_size; {an index into |buffer|}
 13971  @!c:ASCII_code; {the current character in the buffer}
 13972  @!class:ASCII_code; {its class number}
 13973  @!n,@!f:integer; {registers for decimal-to-binary conversion}
 13974  begin restart: cur_sym:=0;
 13975  if file_state then
 13976  @<Input from external file; |goto restart| if no input found,
 13977    or |return| if a non-symbolic token is found@>
 13978  else @<Input from token list; |goto restart| if end of list or
 13979    if a parameter needs to be expanded,
 13980    or |return| if a non-symbolic token is found@>;
 13981  @<Finish getting the symbolic token in |cur_sym|;
 13982    |goto restart| if it is illegal@>;
 13983  exit:end;
 13984  
 13985  @ When a symbolic token is declared to be `\&{outer}', its command code
 13986  is increased by |outer_tag|.
 13987  @^inner loop@>
 13988  
 13989  @<Finish getting the symbolic token in |cur_sym|...@>=
 13990  cur_cmd:=eq_type(cur_sym); cur_mod:=equiv(cur_sym);
 13991  if cur_cmd>=outer_tag then
 13992    if check_outer_validity then cur_cmd:=cur_cmd-outer_tag
 13993    else goto restart
 13994  
 13995  @ A percent sign appears in |buffer[limit]|; this makes it unnecessary
 13996  to have a special test for end-of-line.
 13997  @^inner loop@>
 13998  
 13999  @<Input from external file;...@>=
 14000  begin switch: c:=buffer[loc]; incr(loc); class:=char_class[c];
 14001  case class of
 14002  digit_class: goto start_numeric_token;
 14003  period_class: begin class:=char_class[buffer[loc]];
 14004    if class>period_class then goto switch
 14005    else if class<period_class then {|class=digit_class|}
 14006      begin n:=0; goto start_decimal_token;
 14007      end;
 14008  @:. }{\..\ token@>
 14009    end;
 14010  space_class: goto switch;
 14011  percent_class: begin @<Move to next line of file,
 14012      or |goto restart| if there is no next line@>;
 14013    check_interrupt;
 14014    goto switch;
 14015    end;
 14016  string_class: @<Get a string token and |return|@>;
 14017  isolated_classes: begin k:=loc-1; goto found;
 14018    end;
 14019  invalid_class: @<Decry the invalid character and |goto restart|@>;
 14020  othercases do_nothing {letters, etc.}
 14021  endcases;@/
 14022  k:=loc-1;
 14023  while char_class[buffer[loc]]=class do incr(loc);
 14024  goto found;
 14025  start_numeric_token:@<Get the integer part |n| of a numeric token;
 14026    set |f:=0| and |goto fin_numeric_token| if there is no decimal point@>;
 14027  start_decimal_token:@<Get the fraction part |f| of a numeric token@>;
 14028  fin_numeric_token:@<Pack the numeric and fraction parts of a numeric token
 14029    and |return|@>;
 14030  found: cur_sym:=id_lookup(k,loc-k);
 14031  end
 14032  
 14033  @ We go to |restart| instead of to |switch|, because we might enter
 14034  |token_state| after the error has been dealt with
 14035  (cf.\ |clear_for_error_prompt|).
 14036  
 14037  @<Decry the invalid...@>=
 14038  begin print_err("Text line contains an invalid character");
 14039  @.Text line contains...@>
 14040  help2("A funny symbol that I can't read has just been input.")@/
 14041  ("Continue, and I'll forget that it ever happened.");@/
 14042  deletions_allowed:=false; error; deletions_allowed:=true;
 14043  goto restart;
 14044  end
 14045  
 14046  @ @<Get a string token and |return|@>=
 14047  begin if buffer[loc]="""" then cur_mod:=""
 14048  else  begin k:=loc; buffer[limit+1]:="""";
 14049    repeat incr(loc);
 14050    until buffer[loc]="""";
 14051    if loc>limit then @<Decry the missing string delimiter and |goto restart|@>;
 14052    if (loc=k+1) and (length(buffer[k])=1) then cur_mod:=buffer[k]
 14053    else  begin str_room(loc-k);
 14054      repeat append_char(buffer[k]); incr(k);
 14055      until k=loc;
 14056      cur_mod:=make_string;
 14057      end;
 14058    end;
 14059  incr(loc); cur_cmd:=string_token; return;
 14060  end
 14061  
 14062  @ We go to |restart| after this error message, not to |switch|,
 14063  because the |clear_for_error_prompt| routine might have reinstated
 14064  |token_state| after |error| has finished.
 14065  
 14066  @<Decry the missing string delimiter and |goto restart|@>=
 14067  begin loc:=limit; {the next character to be read on this line will be |"%"|}
 14068  print_err("Incomplete string token has been flushed");
 14069  @.Incomplete string token...@>
 14070  help3("Strings should finish on the same line as they began.")@/
 14071    ("I've deleted the partial string; you might want to")@/
 14072    ("insert another by typing, e.g., `I""new string""'.");@/
 14073  deletions_allowed:=false; error; deletions_allowed:=true; goto restart;
 14074  end
 14075  
 14076  @ @<Get the integer part |n| of a numeric token...@>=
 14077  n:=c-"0";
 14078  while char_class[buffer[loc]]=digit_class do
 14079    begin if n<4096 then n:=10*n+buffer[loc]-"0";
 14080    incr(loc);
 14081    end;
 14082  if buffer[loc]="." then if char_class[buffer[loc+1]]=digit_class then goto done;
 14083  f:=0; goto fin_numeric_token;
 14084  done: incr(loc)
 14085  
 14086  @ @<Get the fraction part |f| of a numeric token@>=
 14087  k:=0;
 14088  repeat if k<17 then {digits for |k>=17| cannot affect the result}
 14089    begin dig[k]:=buffer[loc]-"0"; incr(k);
 14090    end;
 14091  incr(loc);
 14092  until char_class[buffer[loc]]<>digit_class;
 14093  f:=round_decimals(k);
 14094  if f=unity then
 14095    begin incr(n); f:=0;
 14096    end
 14097  
 14098  @ @<Pack the numeric and fraction parts of a numeric token and |return|@>=
 14099  if n<4096 then cur_mod:=n*unity+f
 14100  else  begin print_err("Enormous number has been reduced");
 14101  @.Enormous number...@>
 14102    help2("I can't handle numbers bigger than about 4095.99998;")@/
 14103    ("so I've changed your constant to that maximum amount.");@/
 14104    deletions_allowed:=false; error; deletions_allowed:=true;
 14105    cur_mod:=@'1777777777;
 14106    end;
 14107  cur_cmd:=numeric_token; return
 14108  
 14109  @ Let's consider now what happens when |get_next| is looking at a token list.
 14110  @^inner loop@>
 14111  
 14112  @<Input from token list;...@>=
 14113  if loc>=hi_mem_min then {one-word token}
 14114    begin cur_sym:=info(loc); loc:=link(loc); {move to next}
 14115    if cur_sym>=expr_base then
 14116      if cur_sym>=suffix_base then
 14117        @<Insert a suffix or text parameter and |goto restart|@>
 14118      else  begin cur_cmd:=capsule_token;
 14119        cur_mod:=param_stack[param_start+cur_sym-(expr_base)];
 14120        cur_sym:=0; return;
 14121        end;
 14122    end
 14123  else if loc>null then
 14124    @<Get a stored numeric or string or capsule token and |return|@>
 14125  else  begin {we are done with this token list}
 14126    end_token_list; goto restart; {resume previous level}
 14127    end
 14128  
 14129  @ @<Insert a suffix or text parameter...@>=
 14130  begin if cur_sym>=text_base then cur_sym:=cur_sym-param_size;
 14131    {|param_size=text_base-suffix_base|}
 14132  begin_token_list(param_stack[param_start+cur_sym-(suffix_base)],parameter);
 14133  goto restart;
 14134  end
 14135  
 14136  @ @<Get a stored numeric or string or capsule token...@>=
 14137  begin if name_type(loc)=token then
 14138    begin cur_mod:=value(loc);
 14139    if type(loc)=known then cur_cmd:=numeric_token
 14140    else  begin cur_cmd:=string_token; add_str_ref(cur_mod);
 14141      end;
 14142    end
 14143  else  begin cur_mod:=loc; cur_cmd:=capsule_token;
 14144    end;
 14145  loc:=link(loc); return;
 14146  end
 14147  
 14148  @ All of the easy branches of |get_next| have now been taken care of.
 14149  There is one more branch.
 14150  
 14151  @<Move to next line of file, or |goto restart|...@>=
 14152  if name>2 then @<Read next line of file into |buffer|, or
 14153    |goto restart| if the file has ended@>
 14154  else  begin if input_ptr>0 then
 14155       {text was inserted during error recovery or by \&{scantokens}}
 14156      begin end_file_reading; goto restart; {resume previous level}
 14157      end;
 14158    if selector<log_only then open_log_file;
 14159    if interaction>nonstop_mode then
 14160      begin if limit=start then {previous line was empty}
 14161        print_nl("(Please type a command or say `end')");
 14162  @.Please type...@>
 14163      print_ln; first:=start;
 14164      prompt_input("*"); {input on-line into |buffer|}
 14165  @.*\relax@>
 14166      limit:=last; buffer[limit]:="%";
 14167      first:=limit+1; loc:=start;
 14168      end
 14169    else fatal_error("*** (job aborted, no legal end found)");
 14170  @.job aborted@>
 14171      {nonstop mode, which is intended for overnight batch processing,
 14172      never waits for on-line input}
 14173    end
 14174  
 14175  @ The global variable |force_eof| is normally |false|; it is set |true|
 14176  by an \&{endinput} command.
 14177  
 14178  @<Glob...@>=
 14179  @!force_eof:boolean; {should the next \&{input} be aborted early?}
 14180  
 14181  @ @<Read next line of file into |buffer|, or
 14182    |goto restart| if the file has ended@>=
 14183  begin incr(line); first:=start;
 14184  if not force_eof then
 14185    begin if input_ln(cur_file,true) then {not end of file}
 14186      firm_up_the_line {this sets |limit|}
 14187    else force_eof:=true;
 14188    end;
 14189  if force_eof then
 14190    begin print_char(")"); decr(open_parens);
 14191    update_terminal; {show user that file has been read}
 14192    force_eof:=false;
 14193    end_file_reading; {resume previous level}
 14194    if check_outer_validity then goto restart@+else goto restart;
 14195    end;
 14196  buffer[limit]:="%"; first:=limit+1; loc:=start; {ready to read}
 14197  end
 14198  
 14199  @ If the user has set the |pausing| parameter to some positive value,
 14200  and if nonstop mode has not been selected, each line of input is displayed
 14201  on the terminal and the transcript file, followed by `\.{=>}'.
 14202  \MF\ waits for a response. If the response is null (i.e., if nothing is
 14203  typed except perhaps a few blank spaces), the original
 14204  line is accepted as it stands; otherwise the line typed is
 14205  used instead of the line in the file.
 14206  
 14207  @p procedure firm_up_the_line;
 14208  var @!k:0..buf_size; {an index into |buffer|}
 14209  begin limit:=last;
 14210  if internal[pausing]>0 then if interaction>nonstop_mode then
 14211    begin wake_up_terminal; print_ln;
 14212    if start<limit then for k:=start to limit-1 do print(buffer[k]);
 14213    first:=limit; prompt_input("=>"); {wait for user response}
 14214  @.=>@>
 14215    if last>first then
 14216      begin for k:=first to last-1 do {move line down in buffer}
 14217        buffer[k+start-first]:=buffer[k];
 14218      limit:=start+last-first;
 14219      end;
 14220    end;
 14221  end;
 14222  
 14223  @* \[34] Scanning macro definitions.
 14224  \MF\ has a variety of ways to tuck tokens away into token lists for later
 14225  use: Macros can be defined with \&{def}, \&{vardef}, \&{primarydef}, etc.;
 14226  repeatable code can be defined with \&{for}, \&{forever}, \&{forsuffixes}.
 14227  All such operations are handled by the routines in this part of the program.
 14228  
 14229  The modifier part of each command code is zero for the ``ending delimiters''
 14230  like \&{enddef} and \&{endfor}.
 14231  
 14232  @d start_def=1 {command modifier for \&{def}}
 14233  @d var_def=2 {command modifier for \&{vardef}}
 14234  @d end_def=0 {command modifier for \&{enddef}}
 14235  @d start_forever=1 {command modifier for \&{forever}}
 14236  @d end_for=0 {command modifier for \&{endfor}}
 14237  
 14238  @<Put each...@>=
 14239  primitive("def",macro_def,start_def);@/
 14240  @!@:def_}{\&{def} primitive@>
 14241  primitive("vardef",macro_def,var_def);@/
 14242  @!@:var_def_}{\&{vardef} primitive@>
 14243  primitive("primarydef",macro_def,secondary_primary_macro);@/
 14244  @!@:primary_def_}{\&{primarydef} primitive@>
 14245  primitive("secondarydef",macro_def,tertiary_secondary_macro);@/
 14246  @!@:secondary_def_}{\&{secondarydef} primitive@>
 14247  primitive("tertiarydef",macro_def,expression_tertiary_macro);@/
 14248  @!@:tertiary_def_}{\&{tertiarydef} primitive@>
 14249  primitive("enddef",macro_def,end_def); eqtb[frozen_end_def]:=eqtb[cur_sym];@/
 14250  @!@:end_def_}{\&{enddef} primitive@>
 14251  @#
 14252  primitive("for",iteration,expr_base);@/
 14253  @!@:for_}{\&{for} primitive@>
 14254  primitive("forsuffixes",iteration,suffix_base);@/
 14255  @!@:for_suffixes_}{\&{forsuffixes} primitive@>
 14256  primitive("forever",iteration,start_forever);@/
 14257  @!@:forever_}{\&{forever} primitive@>
 14258  primitive("endfor",iteration,end_for); eqtb[frozen_end_for]:=eqtb[cur_sym];@/
 14259  @!@:end_for_}{\&{endfor} primitive@>
 14260  
 14261  @ @<Cases of |print_cmd...@>=
 14262  macro_def:if m<=var_def then
 14263      if m=start_def then print("def")
 14264      else if m<start_def then print("enddef")
 14265      else print("vardef")
 14266    else if m=secondary_primary_macro then print("primarydef")
 14267    else if m=tertiary_secondary_macro then print("secondarydef")
 14268    else print("tertiarydef");
 14269  iteration: if m<=start_forever then
 14270      if m=start_forever then print("forever")@+else print("endfor")
 14271    else if m=expr_base then print("for")@+else print("forsuffixes");
 14272  
 14273  @ Different macro-absorbing operations have different syntaxes, but they
 14274  also have a lot in common. There is a list of special symbols that are to
 14275  be replaced by parameter tokens; there is a special command code that
 14276  ends the definition; the quotation conventions are identical.  Therefore
 14277  it makes sense to have most of the work done by a single subroutine. That
 14278  subroutine is called |scan_toks|.
 14279  
 14280  The first parameter to |scan_toks| is the command code that will
 14281  terminate scanning (either |macro_def| or |iteration|).
 14282  
 14283  The second parameter, |subst_list|, points to a (possibly empty) list
 14284  of two-word nodes whose |info| and |value| fields specify symbol tokens
 14285  before and after replacement. The list will be returned to free storage
 14286  by |scan_toks|.
 14287  
 14288  The third parameter is simply appended to the token list that is built.
 14289  And the final parameter tells how many of the special operations
 14290  \.{\#\AT!}, \.{\AT!}, and \.{\AT!\#} are to be replaced by suffix parameters.
 14291  When such parameters are present, they are called \.{(SUFFIX0)},
 14292  \.{(SUFFIX1)}, and \.{(SUFFIX2)}.
 14293  
 14294  @p function scan_toks(@!terminator:command_code;
 14295    @!subst_list,@!tail_end:pointer;@!suffix_count:small_number):pointer;
 14296  label done,found;
 14297  var @!p:pointer; {tail of the token list being built}
 14298  @!q:pointer; {temporary for link management}
 14299  @!balance:integer; {left delimiters minus right delimiters}
 14300  begin p:=hold_head; balance:=1; link(hold_head):=null;
 14301  loop@+  begin get_next;
 14302    if cur_sym>0 then
 14303      begin @<Substitute for |cur_sym|, if it's on the |subst_list|@>;
 14304      if cur_cmd=terminator then
 14305        @<Adjust the balance; |goto done| if it's zero@>
 14306      else if cur_cmd=macro_special then
 14307        @<Handle quoted symbols, \.{\#\AT!}, \.{\AT!}, or \.{\AT!\#}@>;
 14308      end;
 14309    link(p):=cur_tok; p:=link(p);
 14310    end;
 14311  done: link(p):=tail_end; flush_node_list(subst_list);
 14312  scan_toks:=link(hold_head);
 14313  end;
 14314  
 14315  @ @<Substitute for |cur_sym|...@>=
 14316  begin q:=subst_list;
 14317  while q<>null do
 14318    begin if info(q)=cur_sym then
 14319      begin cur_sym:=value(q); cur_cmd:=relax; goto found;
 14320      end;
 14321    q:=link(q);
 14322    end;
 14323  found:end
 14324  
 14325  @ @<Adjust the balance; |goto done| if it's zero@>=
 14326  if cur_mod>0 then incr(balance)
 14327  else  begin decr(balance);
 14328    if balance=0 then goto done;
 14329    end
 14330  
 14331  @ Four commands are intended to be used only within macro texts: \&{quote},
 14332  \.{\#\AT!}, \.{\AT!}, and \.{\AT!\#}. They are variants of a single command
 14333  code called |macro_special|.
 14334  
 14335  @d quote=0 {|macro_special| modifier for \&{quote}}
 14336  @d macro_prefix=1 {|macro_special| modifier for \.{\#\AT!}}
 14337  @d macro_at=2 {|macro_special| modifier for \.{\AT!}}
 14338  @d macro_suffix=3 {|macro_special| modifier for \.{\AT!\#}}
 14339  
 14340  @<Put each...@>=
 14341  primitive("quote",macro_special,quote);@/
 14342  @!@:quote_}{\&{quote} primitive@>
 14343  primitive("#@@",macro_special,macro_prefix);@/
 14344  @!@:]]]\#\AT!_}{\.{\#\AT!} primitive@>
 14345  primitive("@@",macro_special,macro_at);@/
 14346  @!@:]]]\AT!_}{\.{\AT!} primitive@>
 14347  primitive("@@#",macro_special,macro_suffix);@/
 14348  @!@:]]]\AT!\#_}{\.{\AT!\#} primitive@>
 14349  
 14350  @ @<Cases of |print_cmd...@>=
 14351  macro_special: case m of
 14352    macro_prefix: print("#@@");
 14353    macro_at: print_char("@@");
 14354    macro_suffix: print("@@#");
 14355    othercases print("quote")
 14356    endcases;
 14357  
 14358  @ @<Handle quoted...@>=
 14359  begin if cur_mod=quote then get_next
 14360  else if cur_mod<=suffix_count then cur_sym:=suffix_base-1+cur_mod;
 14361  end
 14362  
 14363  @ Here is a routine that's used whenever a token will be redefined. If
 14364  the user's token is unredefinable, the `|frozen_inaccessible|' token is
 14365  substituted; the latter is redefinable but essentially impossible to use,
 14366  hence \MF's tables won't get fouled up.
 14367  
 14368  @p procedure get_symbol; {sets |cur_sym| to a safe symbol}
 14369  label restart;
 14370  begin restart: get_next;
 14371  if (cur_sym=0)or(cur_sym>frozen_inaccessible) then
 14372    begin print_err("Missing symbolic token inserted");
 14373  @.Missing symbolic token...@>
 14374    help3("Sorry: You can't redefine a number, string, or expr.")@/
 14375      ("I've inserted an inaccessible symbol so that your")@/
 14376      ("definition will be completed without mixing me up too badly.");
 14377    if cur_sym>0 then
 14378      help_line[2]:="Sorry: You can't redefine my error-recovery tokens."
 14379    else if cur_cmd=string_token then delete_str_ref(cur_mod);
 14380    cur_sym:=frozen_inaccessible; ins_error; goto restart;
 14381    end;
 14382  end;
 14383  
 14384  @ Before we actually redefine a symbolic token, we need to clear away its
 14385  former value, if it was a variable. The following stronger version of
 14386  |get_symbol| does that.
 14387  
 14388  @p procedure get_clear_symbol;
 14389  begin get_symbol; clear_symbol(cur_sym,false);
 14390  end;
 14391  
 14392  @ Here's another little subroutine; it checks that an equals sign
 14393  or assignment sign comes along at the proper place in a macro definition.
 14394  
 14395  @p procedure check_equals;
 14396  begin if cur_cmd<>equals then if cur_cmd<>assignment then
 14397    begin missing_err("=");@/
 14398  @.Missing `='@>
 14399    help5("The next thing in this `def' should have been `=',")@/
 14400      ("because I've already looked at the definition heading.")@/
 14401      ("But don't worry; I'll pretend that an equals sign")@/
 14402      ("was present. Everything from here to `enddef'")@/
 14403      ("will be the replacement text of this macro.");
 14404    back_error;
 14405    end;
 14406  end;
 14407  
 14408  @ A \&{primarydef}, \&{secondarydef}, or \&{tertiarydef} is rather easily
 14409  handled now that we have |scan_toks|.  In this case there are
 14410  two parameters, which will be \.{EXPR0} and \.{EXPR1} (i.e.,
 14411  |expr_base| and |expr_base+1|).
 14412  
 14413  @p procedure make_op_def;
 14414  var @!m:command_code; {the type of definition}
 14415  @!p,@!q,@!r:pointer; {for list manipulation}
 14416  begin m:=cur_mod;@/
 14417  get_symbol; q:=get_node(token_node_size);
 14418  info(q):=cur_sym; value(q):=expr_base;@/
 14419  get_clear_symbol; warning_info:=cur_sym;@/
 14420  get_symbol; p:=get_node(token_node_size);
 14421  info(p):=cur_sym; value(p):=expr_base+1; link(p):=q;@/
 14422  get_next; check_equals;@/
 14423  scanner_status:=op_defining; q:=get_avail; ref_count(q):=null;
 14424  r:=get_avail; link(q):=r; info(r):=general_macro;
 14425  link(r):=scan_toks(macro_def,p,null,0);
 14426  scanner_status:=normal; eq_type(warning_info):=m;
 14427  equiv(warning_info):=q; get_x_next;
 14428  end;
 14429  
 14430  @ Parameters to macros are introduced by the keywords \&{expr},
 14431  \&{suffix}, \&{text}, \&{primary}, \&{secondary}, and \&{tertiary}.
 14432  
 14433  @<Put each...@>=
 14434  primitive("expr",param_type,expr_base);@/
 14435  @!@:expr_}{\&{expr} primitive@>
 14436  primitive("suffix",param_type,suffix_base);@/
 14437  @!@:suffix_}{\&{suffix} primitive@>
 14438  primitive("text",param_type,text_base);@/
 14439  @!@:text_}{\&{text} primitive@>
 14440  primitive("primary",param_type,primary_macro);@/
 14441  @!@:primary_}{\&{primary} primitive@>
 14442  primitive("secondary",param_type,secondary_macro);@/
 14443  @!@:secondary_}{\&{secondary} primitive@>
 14444  primitive("tertiary",param_type,tertiary_macro);@/
 14445  @!@:tertiary_}{\&{tertiary} primitive@>
 14446  
 14447  @ @<Cases of |print_cmd...@>=
 14448  param_type:if m>=expr_base then
 14449      if m=expr_base then print("expr")
 14450      else if m=suffix_base then print("suffix")
 14451      else print("text")
 14452    else if m<secondary_macro then print("primary")
 14453    else if m=secondary_macro then print("secondary")
 14454    else print("tertiary");
 14455  
 14456  @ Let's turn next to the more complex processing associated with \&{def}
 14457  and \&{vardef}. When the following procedure is called, |cur_mod|
 14458  should be either |start_def| or |var_def|.
 14459  
 14460  @p @t\4@>@<Declare the procedure called |check_delimiter|@>@;
 14461  @t\4@>@<Declare the function called |scan_declared_variable|@>@;
 14462  procedure scan_def;
 14463  var @!m:start_def..var_def; {the type of definition}
 14464  @!n:0..3; {the number of special suffix parameters}
 14465  @!k:0..param_size; {the total number of parameters}
 14466  @!c:general_macro..text_macro; {the kind of macro we're defining}
 14467  @!r:pointer; {parameter-substitution list}
 14468  @!q:pointer; {tail of the macro token list}
 14469  @!p:pointer; {temporary storage}
 14470  @!base:halfword; {|expr_base|, |suffix_base|, or |text_base|}
 14471  @!l_delim,@!r_delim:pointer; {matching delimiters}
 14472  begin m:=cur_mod; c:=general_macro; link(hold_head):=null;@/
 14473  q:=get_avail; ref_count(q):=null; r:=null;@/
 14474  @<Scan the token or variable to be defined;
 14475    set |n|, |scanner_status|, and |warning_info|@>;
 14476  k:=n;
 14477  if cur_cmd=left_delimiter then
 14478    @<Absorb delimited parameters, putting them into lists |q| and |r|@>;
 14479  if cur_cmd=param_type then
 14480    @<Absorb undelimited parameters, putting them into list |r|@>;
 14481  check_equals;
 14482  p:=get_avail; info(p):=c; link(q):=p;
 14483  @<Attach the replacement text to the tail of node |p|@>;
 14484  scanner_status:=normal; get_x_next;
 14485  end;
 14486  
 14487  @ We don't put `|frozen_end_group|' into the replacement text of
 14488  a \&{vardef}, because the user may want to redefine `\.{endgroup}'.
 14489  
 14490  @<Attach the replacement text to the tail of node |p|@>=
 14491  if m=start_def then link(p):=scan_toks(macro_def,r,null,n)
 14492  else  begin q:=get_avail; info(q):=bg_loc; link(p):=q;
 14493    p:=get_avail; info(p):=eg_loc;
 14494    link(q):=scan_toks(macro_def,r,p,n);
 14495    end;
 14496  if warning_info=bad_vardef then flush_token_list(value(bad_vardef))
 14497  
 14498  @ @<Glob...@>=
 14499  @!bg_loc,@!eg_loc:1..hash_end;
 14500    {hash addresses of `\.{begingroup}' and `\.{endgroup}'}
 14501  
 14502  @ @<Scan the token or variable to be defined;...@>=
 14503  if m=start_def then
 14504    begin get_clear_symbol; warning_info:=cur_sym; get_next;
 14505    scanner_status:=op_defining; n:=0;
 14506    eq_type(warning_info):=defined_macro; equiv(warning_info):=q;
 14507    end
 14508  else  begin p:=scan_declared_variable;
 14509    flush_variable(equiv(info(p)),link(p),true);
 14510    warning_info:=find_variable(p); flush_list(p);
 14511    if warning_info=null then @<Change to `\.{a bad variable}'@>;
 14512    scanner_status:=var_defining; n:=2;
 14513    if cur_cmd=macro_special then if cur_mod=macro_suffix then {\.{\AT!\#}}
 14514      begin n:=3; get_next;
 14515      end;
 14516    type(warning_info):=unsuffixed_macro-2+n; value(warning_info):=q;
 14517    end {|suffixed_macro=unsuffixed_macro+1|}
 14518  
 14519  @ @<Change to `\.{a bad variable}'@>=
 14520  begin print_err("This variable already starts with a macro");
 14521  @.This variable already...@>
 14522  help2("After `vardef a' you can't say `vardef a.b'.")@/
 14523    ("So I'll have to discard this definition.");
 14524  error; warning_info:=bad_vardef;
 14525  end
 14526  
 14527  @ @<Initialize table entries...@>=
 14528  name_type(bad_vardef):=root; link(bad_vardef):=frozen_bad_vardef;
 14529  equiv(frozen_bad_vardef):=bad_vardef; eq_type(frozen_bad_vardef):=tag_token;
 14530  
 14531  @ @<Absorb delimited parameters, putting them into lists |q| and |r|@>=
 14532  repeat l_delim:=cur_sym; r_delim:=cur_mod; get_next;
 14533  if (cur_cmd=param_type)and(cur_mod>=expr_base) then base:=cur_mod
 14534  else  begin print_err("Missing parameter type; `expr' will be assumed");
 14535  @.Missing parameter type@>
 14536    help1("You should've had `expr' or `suffix' or `text' here.");
 14537    back_error; base:=expr_base;
 14538    end;
 14539  @<Absorb parameter tokens for type |base|@>;
 14540  check_delimiter(l_delim,r_delim);
 14541  get_next;
 14542  until cur_cmd<>left_delimiter
 14543  
 14544  @ @<Absorb parameter tokens for type |base|@>=
 14545  repeat link(q):=get_avail; q:=link(q); info(q):=base+k;@/
 14546  get_symbol; p:=get_node(token_node_size); value(p):=base+k; info(p):=cur_sym;
 14547  if k=param_size then overflow("parameter stack size",param_size);
 14548  @:METAFONT capacity exceeded parameter stack size}{\quad parameter stack size@>
 14549  incr(k); link(p):=r; r:=p; get_next;
 14550  until cur_cmd<>comma
 14551  
 14552  @ @<Absorb undelimited parameters, putting them into list |r|@>=
 14553  begin p:=get_node(token_node_size);
 14554  if cur_mod<expr_base then
 14555    begin c:=cur_mod; value(p):=expr_base+k;
 14556    end
 14557  else  begin value(p):=cur_mod+k;
 14558    if cur_mod=expr_base then c:=expr_macro
 14559    else if cur_mod=suffix_base then c:=suffix_macro
 14560    else c:=text_macro;
 14561    end;
 14562  if k=param_size then overflow("parameter stack size",param_size);
 14563  incr(k); get_symbol; info(p):=cur_sym; link(p):=r; r:=p; get_next;
 14564  if c=expr_macro then if cur_cmd=of_token then
 14565    begin c:=of_macro; p:=get_node(token_node_size);
 14566    if k=param_size then overflow("parameter stack size",param_size);
 14567    value(p):=expr_base+k; get_symbol; info(p):=cur_sym;
 14568    link(p):=r; r:=p; get_next;
 14569    end;
 14570  end
 14571  
 14572  @* \[35] Expanding the next token.
 14573  Only a few command codes |<min_command| can possibly be returned by
 14574  |get_next|; in increasing order, they are
 14575  |if_test|, |fi_or_else|, |input|, |iteration|, |repeat_loop|,
 14576  |exit_test|, |relax|, |scan_tokens|, |expand_after|, and |defined_macro|.
 14577  
 14578  \MF\ usually gets the next token of input by saying |get_x_next|. This is
 14579  like |get_next| except that it keeps getting more tokens until
 14580  finding |cur_cmd>=min_command|. In other words, |get_x_next| expands
 14581  macros and removes conditionals or iterations or input instructions that
 14582  might be present.
 14583  
 14584  It follows that |get_x_next| might invoke itself recursively. In fact,
 14585  there is massive recursion, since macro expansion can involve the
 14586  scanning of arbitrarily complex expressions, which in turn involve
 14587  macro expansion and conditionals, etc.
 14588  @^recursion@>
 14589  
 14590  Therefore it's necessary to declare a whole bunch of |forward|
 14591  procedures at this point, and to insert some other procedures
 14592  that will be invoked by |get_x_next|.
 14593  
 14594  @p procedure@?scan_primary; forward;@t\2@>
 14595  procedure@?scan_secondary; forward;@t\2@>
 14596  procedure@?scan_tertiary; forward;@t\2@>
 14597  procedure@?scan_expression; forward;@t\2@>
 14598  procedure@?scan_suffix; forward;@t\2@>@/
 14599  @t\4@>@<Declare the procedure called |macro_call|@>@;@/
 14600  procedure@?get_boolean; forward;@t\2@>
 14601  procedure@?pass_text; forward;@t\2@>
 14602  procedure@?conditional; forward;@t\2@>
 14603  procedure@?start_input; forward;@t\2@>
 14604  procedure@?begin_iteration; forward;@t\2@>
 14605  procedure@?resume_iteration; forward;@t\2@>
 14606  procedure@?stop_iteration; forward;@t\2@>
 14607  
 14608  @ An auxiliary subroutine called |expand| is used by |get_x_next|
 14609  when it has to do exotic expansion commands.
 14610  
 14611  @p procedure expand;
 14612  var @!p:pointer; {for list manipulation}
 14613  @!k:integer; {something that we hope is |<=buf_size|}
 14614  @!j:pool_pointer; {index into |str_pool|}
 14615  begin if internal[tracing_commands]>unity then if cur_cmd<>defined_macro then
 14616    show_cur_cmd_mod;
 14617  case cur_cmd of
 14618  if_test:conditional; {this procedure is discussed in Part 36 below}
 14619  fi_or_else:@<Terminate the current conditional and skip to \&{fi}@>;
 14620  input:@<Initiate or terminate input from a file@>;
 14621  iteration:if cur_mod=end_for then
 14622      @<Scold the user for having an extra \&{endfor}@>
 14623    else begin_iteration; {this procedure is discussed in Part 37 below}
 14624  repeat_loop: @<Repeat a loop@>;
 14625  exit_test: @<Exit a loop if the proper time has come@>;
 14626  relax: do_nothing;
 14627  expand_after: @<Expand the token after the next token@>;
 14628  scan_tokens: @<Put a string into the input buffer@>;
 14629  defined_macro:macro_call(cur_mod,null,cur_sym);
 14630  end; {there are no other cases}
 14631  end;
 14632  
 14633  @ @<Scold the user...@>=
 14634  begin print_err("Extra `endfor'");
 14635  @.Extra `endfor'@>
 14636  help2("I'm not currently working on a for loop,")@/
 14637    ("so I had better not try to end anything.");@/
 14638  error;
 14639  end
 14640  
 14641  @ The processing of \&{input} involves the |start_input| subroutine,
 14642  which will be declared later; the processing of \&{endinput} is trivial.
 14643  
 14644  @<Put each...@>=
 14645  primitive("input",input,0);@/
 14646  @!@:input_}{\&{input} primitive@>
 14647  primitive("endinput",input,1);@/
 14648  @!@:end_input_}{\&{endinput} primitive@>
 14649  
 14650  @ @<Cases of |print_cmd_mod|...@>=
 14651  input: if m=0 then print("input")@+else print("endinput");
 14652  
 14653  @ @<Initiate or terminate input...@>=
 14654  if cur_mod>0 then force_eof:=true
 14655  else start_input
 14656  
 14657  @ We'll discuss the complicated parts of loop operations later. For now
 14658  it suffices to know that there's a global variable called |loop_ptr|
 14659  that will be |null| if no loop is in progress.
 14660  
 14661  @<Repeat a loop@>=
 14662  begin while token_state and(loc=null) do end_token_list; {conserve stack space}
 14663  if loop_ptr=null then
 14664    begin print_err("Lost loop");
 14665  @.Lost loop@>
 14666    help2("I'm confused; after exiting from a loop, I still seem")@/
 14667      ("to want to repeat it. I'll try to forget the problem.");@/
 14668    error;
 14669    end
 14670  else resume_iteration; {this procedure is in Part 37 below}
 14671  end
 14672  
 14673  @ @<Exit a loop if the proper time has come@>=
 14674  begin get_boolean;
 14675  if internal[tracing_commands]>unity then show_cmd_mod(nullary,cur_exp);
 14676  if cur_exp=true_code then
 14677    if loop_ptr=null then
 14678      begin print_err("No loop is in progress");
 14679  @.No loop is in progress@>
 14680      help1("Why say `exitif' when there's nothing to exit from?");
 14681      if cur_cmd=semicolon then error@+else back_error;
 14682      end
 14683    else @<Exit prematurely from an iteration@>
 14684  else if cur_cmd<>semicolon then
 14685    begin missing_err(";");@/
 14686  @.Missing `;'@>
 14687    help2("After `exitif <boolean expr>' I expect to see a semicolon.")@/
 14688    ("I shall pretend that one was there."); back_error;
 14689    end;
 14690  end
 14691  
 14692  @ Here we use the fact that |forever_text| is the only |token_type| that
 14693  is less than |loop_text|.
 14694  
 14695  @<Exit prematurely...@>=
 14696  begin p:=null;
 14697  repeat if file_state then end_file_reading
 14698  else  begin if token_type<=loop_text then p:=start;
 14699    end_token_list;
 14700    end;
 14701  until p<>null;
 14702  if p<>info(loop_ptr) then fatal_error("*** (loop confusion)");
 14703  @.loop confusion@>
 14704  stop_iteration; {this procedure is in Part 37 below}
 14705  end
 14706  
 14707  @ @<Expand the token after the next token@>=
 14708  begin get_next;
 14709  p:=cur_tok; get_next;
 14710  if cur_cmd<min_command then expand else back_input;
 14711  back_list(p);
 14712  end
 14713  
 14714  @ @<Put a string into the input buffer@>=
 14715  begin get_x_next; scan_primary;
 14716  if cur_type<>string_type then
 14717    begin disp_err(null,"Not a string");
 14718  @.Not a string@>
 14719    help2("I'm going to flush this expression, since")@/
 14720      ("scantokens should be followed by a known string.");
 14721    put_get_flush_error(0);
 14722    end
 14723  else  begin back_input;
 14724    if length(cur_exp)>0 then @<Pretend we're reading a new one-line file@>;
 14725    end;
 14726  end
 14727  
 14728  @ @<Pretend we're reading a new one-line file@>=
 14729  begin begin_file_reading; name:=2;
 14730  k:=first+length(cur_exp);
 14731  if k>=max_buf_stack then
 14732    begin if k>=buf_size then
 14733      begin max_buf_stack:=buf_size;
 14734      overflow("buffer size",buf_size);
 14735  @:METAFONT capacity exceeded buffer size}{\quad buffer size@>
 14736      end;
 14737    max_buf_stack:=k+1;
 14738    end;
 14739  j:=str_start[cur_exp]; limit:=k;
 14740  while first<limit do
 14741    begin buffer[first]:=so(str_pool[j]); incr(j); incr(first);
 14742    end;
 14743  buffer[limit]:="%"; first:=limit+1; loc:=start; flush_cur_exp(0);
 14744  end
 14745  
 14746  @ Here finally is |get_x_next|.
 14747  
 14748  The expression scanning routines to be considered later
 14749  communicate via the global quantities |cur_type| and |cur_exp|;
 14750  we must be very careful to save and restore these quantities while
 14751  macros are being expanded.
 14752  @^inner loop@>
 14753  
 14754  @p procedure get_x_next;
 14755  var @!save_exp:pointer; {a capsule to save |cur_type| and |cur_exp|}
 14756  begin get_next;
 14757  if cur_cmd<min_command then
 14758    begin save_exp:=stash_cur_exp;
 14759    repeat if cur_cmd=defined_macro then macro_call(cur_mod,null,cur_sym)
 14760    else expand;
 14761    get_next;
 14762    until cur_cmd>=min_command;
 14763    unstash_cur_exp(save_exp); {that restores |cur_type| and |cur_exp|}
 14764    end;
 14765  end;
 14766  
 14767  @ Now let's consider the |macro_call| procedure, which is used to start up
 14768  all user-defined macros. Since the arguments to a macro might be expressions,
 14769  |macro_call| is recursive.
 14770  @^recursion@>
 14771  
 14772  The first parameter to |macro_call| points to the reference count of the
 14773  token list that defines the macro. The second parameter contains any
 14774  arguments that have already been parsed (see below).  The third parameter
 14775  points to the symbolic token that names the macro. If the third parameter
 14776  is |null|, the macro was defined by \&{vardef}, so its name can be
 14777  reconstructed from the prefix and ``at'' arguments found within the
 14778  second parameter.
 14779  
 14780  What is this second parameter? It's simply a linked list of one-word items,
 14781  whose |info| fields point to the arguments. In other words, if |arg_list=null|,
 14782  no arguments have been scanned yet; otherwise |info(arg_list)| points to
 14783  the first scanned argument, and |link(arg_list)| points to the list of
 14784  further arguments (if any).
 14785  
 14786  Arguments of type \&{expr} are so-called capsules, which we will
 14787  discuss later when we concentrate on expressions; they can be
 14788  recognized easily because their |link| field is |void|. Arguments of type
 14789  \&{suffix} and \&{text} are token lists without reference counts.
 14790  
 14791  @ After argument scanning is complete, the arguments are moved to the
 14792  |param_stack|. (They can't be put on that stack any sooner, because
 14793  the stack is growing and shrinking in unpredictable ways as more arguments
 14794  are being acquired.)  Then the macro body is fed to the scanner; i.e.,
 14795  the replacement text of the macro is placed at the top of the \MF's
 14796  input stack, so that |get_next| will proceed to read it next.
 14797  
 14798  @<Declare the procedure called |macro_call|@>=
 14799  @t\4@>@<Declare the procedure called |print_macro_name|@>@;
 14800  @t\4@>@<Declare the procedure called |print_arg|@>@;
 14801  @t\4@>@<Declare the procedure called |scan_text_arg|@>@;
 14802  procedure macro_call(@!def_ref,@!arg_list,@!macro_name:pointer);
 14803    {invokes a user-defined sequence of commands}
 14804  label found;
 14805  var @!r:pointer; {current node in the macro's token list}
 14806  @!p,@!q:pointer; {for list manipulation}
 14807  @!n:integer; {the number of arguments}
 14808  @!l_delim,@!r_delim:pointer; {a delimiter pair}
 14809  @!tail:pointer; {tail of the argument list}
 14810  begin r:=link(def_ref); add_mac_ref(def_ref);
 14811  if arg_list=null then n:=0
 14812  else @<Determine the number |n| of arguments already supplied,
 14813    and set |tail| to the tail of |arg_list|@>;
 14814  if internal[tracing_macros]>0 then
 14815    @<Show the text of the macro being expanded, and the existing arguments@>;
 14816  @<Scan the remaining arguments, if any; set |r| to the first token
 14817    of the replacement text@>;
 14818  @<Feed the arguments and replacement text to the scanner@>;
 14819  end;
 14820  
 14821  @ @<Show the text of the macro...@>=
 14822  begin begin_diagnostic; print_ln; print_macro_name(arg_list,macro_name);
 14823  if n=3 then print("@@#"); {indicate a suffixed macro}
 14824  show_macro(def_ref,null,100000);
 14825  if arg_list<>null then
 14826    begin n:=0; p:=arg_list;
 14827    repeat q:=info(p);
 14828    print_arg(q,n,0);
 14829    incr(n); p:=link(p);
 14830    until p=null;
 14831    end;
 14832  end_diagnostic(false);
 14833  end
 14834  
 14835  @ @<Declare the procedure called |print_macro_name|@>=
 14836  procedure print_macro_name(@!a,@!n:pointer);
 14837  var @!p,@!q:pointer; {they traverse the first part of |a|}
 14838  begin if n<>null then slow_print(text(n))
 14839  else  begin p:=info(a);
 14840    if p=null then slow_print(text(info(info(link(a)))))
 14841    else  begin q:=p;
 14842      while link(q)<>null do q:=link(q);
 14843      link(q):=info(link(a));
 14844      show_token_list(p,null,1000,0);
 14845      link(q):=null;
 14846      end;
 14847    end;
 14848  end;
 14849  
 14850  @ @<Declare the procedure called |print_arg|@>=
 14851  procedure print_arg(@!q:pointer;@!n:integer;@!b:pointer);
 14852  begin if link(q)=void then print_nl("(EXPR")
 14853  else if (b<text_base)and(b<>text_macro) then print_nl("(SUFFIX")
 14854  else print_nl("(TEXT");
 14855  print_int(n); print(")<-");
 14856  if link(q)=void then print_exp(q,1)
 14857  else show_token_list(q,null,1000,0);
 14858  end;
 14859  
 14860  @ @<Determine the number |n| of arguments already supplied...@>=
 14861  begin n:=1; tail:=arg_list;
 14862  while link(tail)<>null do
 14863    begin incr(n); tail:=link(tail);
 14864    end;
 14865  end
 14866  
 14867  @ @<Scan the remaining arguments, if any; set |r|...@>=
 14868  cur_cmd:=comma+1; {anything |<>comma| will do}
 14869  while info(r)>=expr_base do
 14870    begin @<Scan the delimited argument represented by |info(r)|@>;
 14871    r:=link(r);
 14872    end;
 14873  if cur_cmd=comma then
 14874    begin print_err("Too many arguments to ");
 14875  @.Too many arguments...@>
 14876    print_macro_name(arg_list,macro_name); print_char(";");
 14877    print_nl("  Missing `"); slow_print(text(r_delim));
 14878  @.Missing `)'...@>
 14879    print("' has been inserted");
 14880    help3("I'm going to assume that the comma I just read was a")@/
 14881     ("right delimiter, and then I'll begin expanding the macro.")@/
 14882     ("You might want to delete some tokens before continuing.");
 14883    error;
 14884    end;
 14885  if info(r)<>general_macro then @<Scan undelimited argument(s)@>;
 14886  r:=link(r)
 14887  
 14888  @ At this point, the reader will find it advisable to review the explanation
 14889  of token list format that was presented earlier, paying special attention to
 14890  the conventions that apply only at the beginning of a macro's token list.
 14891  
 14892  On the other hand, the reader will have to take the expression-parsing
 14893  aspects of the following program on faith; we will explain |cur_type|
 14894  and |cur_exp| later. (Several things in this program depend on each other,
 14895  and it's necessary to jump into the circle somewhere.)
 14896  
 14897  @<Scan the delimited argument represented by |info(r)|@>=
 14898  if cur_cmd<>comma then
 14899    begin get_x_next;
 14900    if cur_cmd<>left_delimiter then
 14901      begin print_err("Missing argument to ");
 14902  @.Missing argument...@>
 14903      print_macro_name(arg_list,macro_name);
 14904      help3("That macro has more parameters than you thought.")@/
 14905       ("I'll continue by pretending that each missing argument")@/
 14906       ("is either zero or null.");
 14907      if info(r)>=suffix_base then
 14908        begin cur_exp:=null; cur_type:=token_list;
 14909        end
 14910      else  begin cur_exp:=0; cur_type:=known;
 14911        end;
 14912      back_error; cur_cmd:=right_delimiter; goto found;
 14913      end;
 14914    l_delim:=cur_sym; r_delim:=cur_mod;
 14915    end;
 14916  @<Scan the argument represented by |info(r)|@>;
 14917  if cur_cmd<>comma then @<Check that the proper right delimiter was present@>;
 14918  found:  @<Append the current expression to |arg_list|@>
 14919  
 14920  @ @<Check that the proper right delim...@>=
 14921  if (cur_cmd<>right_delimiter)or(cur_mod<>l_delim) then
 14922    if info(link(r))>=expr_base then
 14923      begin missing_err(",");
 14924  @.Missing `,'@>
 14925      help3("I've finished reading a macro argument and am about to")@/
 14926        ("read another; the arguments weren't delimited correctly.")@/
 14927         ("You might want to delete some tokens before continuing.");
 14928      back_error; cur_cmd:=comma;
 14929      end
 14930    else  begin missing_err(text(r_delim));
 14931  @.Missing `)'@>
 14932      help2("I've gotten to the end of the macro parameter list.")@/
 14933         ("You might want to delete some tokens before continuing.");
 14934      back_error;
 14935      end
 14936  
 14937  @ A \&{suffix} or \&{text} parameter will have been scanned as
 14938  a token list pointed to by |cur_exp|, in which case we will have
 14939  |cur_type=token_list|.
 14940  
 14941  @<Append the current expression to |arg_list|@>=
 14942  begin p:=get_avail;
 14943  if cur_type=token_list then info(p):=cur_exp
 14944  else info(p):=stash_cur_exp;
 14945  if internal[tracing_macros]>0 then
 14946    begin begin_diagnostic; print_arg(info(p),n,info(r)); end_diagnostic(false);
 14947    end;
 14948  if arg_list=null then arg_list:=p
 14949  else link(tail):=p;
 14950  tail:=p; incr(n);
 14951  end
 14952  
 14953  @ @<Scan the argument represented by |info(r)|@>=
 14954  if info(r)>=text_base then scan_text_arg(l_delim,r_delim)
 14955  else  begin get_x_next;
 14956    if info(r)>=suffix_base then scan_suffix
 14957    else scan_expression;
 14958    end
 14959  
 14960  @ The parameters to |scan_text_arg| are either a pair of delimiters
 14961  or zero; the latter case is for undelimited text arguments, which
 14962  end with the first semicolon or \&{endgroup} or \&{end} that is not
 14963  contained in a group.
 14964  
 14965  @<Declare the procedure called |scan_text_arg|@>=
 14966  procedure scan_text_arg(@!l_delim,@!r_delim:pointer);
 14967  label done;
 14968  var @!balance:integer; {excess of |l_delim| over |r_delim|}
 14969  @!p:pointer; {list tail}
 14970  begin warning_info:=l_delim; scanner_status:=absorbing;
 14971  p:=hold_head; balance:=1; link(hold_head):=null;
 14972  loop@+  begin get_next;
 14973    if l_delim=0 then @<Adjust the balance for an undelimited argument;
 14974      |goto done| if done@>
 14975    else @<Adjust the balance for a delimited argument;
 14976      |goto done| if done@>;
 14977    link(p):=cur_tok; p:=link(p);
 14978    end;
 14979  done: cur_exp:=link(hold_head); cur_type:=token_list;
 14980  scanner_status:=normal;
 14981  end;
 14982  
 14983  @ @<Adjust the balance for a delimited argument...@>=
 14984  begin if cur_cmd=right_delimiter then
 14985    begin if cur_mod=l_delim then
 14986      begin decr(balance);
 14987      if balance=0 then goto done;
 14988      end;
 14989    end
 14990  else if cur_cmd=left_delimiter then if cur_mod=r_delim then incr(balance);
 14991  end
 14992  
 14993  @ @<Adjust the balance for an undelimited...@>=
 14994  begin if end_of_statement then {|cur_cmd=semicolon|, |end_group|, or |stop|}
 14995    begin if balance=1 then goto done
 14996    else if cur_cmd=end_group then decr(balance);
 14997    end
 14998  else if cur_cmd=begin_group then incr(balance);
 14999  end
 15000  
 15001  @ @<Scan undelimited argument(s)@>=
 15002  begin if info(r)<text_macro then
 15003    begin get_x_next;
 15004    if info(r)<>suffix_macro then
 15005      if (cur_cmd=equals)or(cur_cmd=assignment) then get_x_next;
 15006    end;
 15007  case info(r) of
 15008  primary_macro:scan_primary;
 15009  secondary_macro:scan_secondary;
 15010  tertiary_macro:scan_tertiary;
 15011  expr_macro:scan_expression;
 15012  of_macro:@<Scan an expression followed by `\&{of} $\langle$primary$\rangle$'@>;
 15013  suffix_macro:@<Scan a suffix with optional delimiters@>;
 15014  text_macro:scan_text_arg(0,0);
 15015  end; {there are no other cases}
 15016  back_input; @<Append the current expression to |arg_list|@>;
 15017  end
 15018  
 15019  @ @<Scan an expression followed by `\&{of} $\langle$primary$\rangle$'@>=
 15020  begin scan_expression; p:=get_avail; info(p):=stash_cur_exp;
 15021  if internal[tracing_macros]>0 then
 15022    begin begin_diagnostic; print_arg(info(p),n,0); end_diagnostic(false);
 15023    end;
 15024  if arg_list=null then arg_list:=p@+else link(tail):=p;
 15025  tail:=p;incr(n);
 15026  if cur_cmd<>of_token then
 15027    begin missing_err("of"); print(" for ");
 15028  @.Missing `of'@>
 15029    print_macro_name(arg_list,macro_name);
 15030    help1("I've got the first argument; will look now for the other.");
 15031    back_error;
 15032    end;
 15033  get_x_next; scan_primary;
 15034  end
 15035  
 15036  @ @<Scan a suffix with optional delimiters@>=
 15037  begin if cur_cmd<>left_delimiter then l_delim:=null
 15038  else  begin l_delim:=cur_sym; r_delim:=cur_mod; get_x_next;
 15039    end;
 15040  scan_suffix;
 15041  if l_delim<>null then
 15042    begin if(cur_cmd<>right_delimiter)or(cur_mod<>l_delim) then
 15043      begin missing_err(text(r_delim));
 15044  @.Missing `)'@>
 15045      help2("I've gotten to the end of the macro parameter list.")@/
 15046         ("You might want to delete some tokens before continuing.");
 15047      back_error;
 15048      end;
 15049    get_x_next;
 15050    end;
 15051  end
 15052  
 15053  @ Before we put a new token list on the input stack, it is wise to clean off
 15054  all token lists that have recently been depleted. Then a user macro that ends
 15055  with a call to itself will not require unbounded stack space.
 15056  
 15057  @<Feed the arguments and replacement text to the scanner@>=
 15058  while token_state and(loc=null) do end_token_list; {conserve stack space}
 15059  if param_ptr+n>max_param_stack then
 15060    begin max_param_stack:=param_ptr+n;
 15061    if max_param_stack>param_size then
 15062      overflow("parameter stack size",param_size);
 15063  @:METAFONT capacity exceeded parameter stack size}{\quad parameter stack size@>
 15064    end;
 15065  begin_token_list(def_ref,macro); name:=macro_name; loc:=r;
 15066  if n>0 then
 15067    begin p:=arg_list;
 15068    repeat param_stack[param_ptr]:=info(p); incr(param_ptr); p:=link(p);
 15069    until p=null;
 15070    flush_list(arg_list);
 15071    end
 15072  
 15073  @ It's sometimes necessary to put a single argument onto |param_stack|.
 15074  The |stack_argument| subroutine does this.
 15075  
 15076  @p procedure stack_argument(@!p:pointer);
 15077  begin if param_ptr=max_param_stack then
 15078    begin incr(max_param_stack);
 15079    if max_param_stack>param_size then
 15080      overflow("parameter stack size",param_size);
 15081  @:METAFONT capacity exceeded parameter stack size}{\quad parameter stack size@>
 15082    end;
 15083  param_stack[param_ptr]:=p; incr(param_ptr);
 15084  end;
 15085  
 15086  @* \[36] Conditional processing.
 15087  Let's consider now the way \&{if} commands are handled.
 15088  
 15089  Conditions can be inside conditions, and this nesting has a stack
 15090  that is independent of other stacks.
 15091  Four global variables represent the top of the condition stack:
 15092  |cond_ptr| points to pushed-down entries, if~any; |cur_if| tells whether
 15093  we are processing \&{if} or \&{elseif}; |if_limit| specifies
 15094  the largest code of a |fi_or_else| command that is syntactically legal;
 15095  and |if_line| is the line number at which the current conditional began.
 15096  
 15097  If no conditions are currently in progress, the condition stack has the
 15098  special state |cond_ptr=null|, |if_limit=normal|, |cur_if=0|, |if_line=0|.
 15099  Otherwise |cond_ptr| points to a two-word node; the |type|, |name_type|, and
 15100  |link| fields of the first word contain |if_limit|, |cur_if|, and
 15101  |cond_ptr| at the next level, and the second word contains the
 15102  corresponding |if_line|.
 15103  
 15104  @d if_node_size=2 {number of words in stack entry for conditionals}
 15105  @d if_line_field(#)==mem[#+1].int
 15106  @d if_code=1 {code for \&{if} being evaluated}
 15107  @d fi_code=2 {code for \&{fi}}
 15108  @d else_code=3 {code for \&{else}}
 15109  @d else_if_code=4 {code for \&{elseif}}
 15110  
 15111  @<Glob...@>=
 15112  @!cond_ptr:pointer; {top of the condition stack}
 15113  @!if_limit:normal..else_if_code; {upper bound on |fi_or_else| codes}
 15114  @!cur_if:small_number; {type of conditional being worked on}
 15115  @!if_line:integer; {line where that conditional began}
 15116  
 15117  @ @<Set init...@>=
 15118  cond_ptr:=null; if_limit:=normal; cur_if:=0; if_line:=0;
 15119  
 15120  @ @<Put each...@>=
 15121  primitive("if",if_test,if_code);@/
 15122  @!@:if_}{\&{if} primitive@>
 15123  primitive("fi",fi_or_else,fi_code); eqtb[frozen_fi]:=eqtb[cur_sym];@/
 15124  @!@:fi_}{\&{fi} primitive@>
 15125  primitive("else",fi_or_else,else_code);@/
 15126  @!@:else_}{\&{else} primitive@>
 15127  primitive("elseif",fi_or_else,else_if_code);@/
 15128  @!@:else_if_}{\&{elseif} primitive@>
 15129  
 15130  @ @<Cases of |print_cmd_mod|...@>=
 15131  if_test,fi_or_else: case m of
 15132    if_code:print("if");
 15133    fi_code:print("fi");
 15134    else_code:print("else");
 15135    othercases print("elseif")
 15136    endcases;
 15137  
 15138  @ Here is a procedure that ignores text until coming to an \&{elseif},
 15139  \&{else}, or \&{fi} at the current level of $\&{if}\ldots\&{fi}$
 15140  nesting. After it has acted, |cur_mod| will indicate the token that
 15141  was found.
 15142  
 15143  \MF's smallest two command codes are |if_test| and |fi_or_else|; this
 15144  makes the skipping process a bit simpler.
 15145  
 15146  @p procedure pass_text;
 15147  label done;
 15148  var l:integer;
 15149  begin scanner_status:=skipping; l:=0; warning_info:=line;
 15150  loop@+  begin get_next;
 15151    if cur_cmd<=fi_or_else then
 15152      if cur_cmd<fi_or_else then incr(l)
 15153      else  begin if l=0 then goto done;
 15154        if cur_mod=fi_code then decr(l);
 15155        end
 15156    else @<Decrease the string reference count,
 15157      if the current token is a string@>;
 15158    end;
 15159  done: scanner_status:=normal;
 15160  end;
 15161  
 15162  @ @<Decrease the string reference count...@>=
 15163  if cur_cmd=string_token then delete_str_ref(cur_mod)
 15164  
 15165  @ When we begin to process a new \&{if}, we set |if_limit:=if_code|; then
 15166  if \&{elseif} or \&{else} or \&{fi} occurs before the current \&{if}
 15167  condition has been evaluated, a colon will be inserted.
 15168  A construction like `\.{if fi}' would otherwise get \MF\ confused.
 15169  
 15170  @<Push the condition stack@>=
 15171  begin p:=get_node(if_node_size); link(p):=cond_ptr; type(p):=if_limit;
 15172  name_type(p):=cur_if; if_line_field(p):=if_line;
 15173  cond_ptr:=p; if_limit:=if_code; if_line:=line; cur_if:=if_code;
 15174  end
 15175  
 15176  @ @<Pop the condition stack@>=
 15177  begin p:=cond_ptr; if_line:=if_line_field(p);
 15178  cur_if:=name_type(p); if_limit:=type(p); cond_ptr:=link(p);
 15179  free_node(p,if_node_size);
 15180  end
 15181  
 15182  @ Here's a procedure that changes the |if_limit| code corresponding to
 15183  a given value of |cond_ptr|.
 15184  
 15185  @p procedure change_if_limit(@!l:small_number;@!p:pointer);
 15186  label exit;
 15187  var q:pointer;
 15188  begin if p=cond_ptr then if_limit:=l {that's the easy case}
 15189  else  begin q:=cond_ptr;
 15190    loop@+  begin if q=null then confusion("if");
 15191  @:this can't happen if}{\quad if@>
 15192      if link(q)=p then
 15193        begin type(q):=l; return;
 15194        end;
 15195      q:=link(q);
 15196      end;
 15197    end;
 15198  exit:end;
 15199  
 15200  @ The user is supposed to put colons into the proper parts of conditional
 15201  statements. Therefore, \MF\ has to check for their presence.
 15202  
 15203  @p procedure check_colon;
 15204  begin if cur_cmd<>colon then
 15205    begin missing_err(":");@/
 15206  @.Missing `:'@>
 15207    help2("There should've been a colon after the condition.")@/
 15208      ("I shall pretend that one was there.");@;
 15209    back_error;
 15210    end;
 15211  end;
 15212  
 15213  @ A condition is started when the |get_x_next| procedure encounters
 15214  an |if_test| command; in that case |get_x_next| calls |conditional|,
 15215  which is a recursive procedure.
 15216  @^recursion@>
 15217  
 15218  @p procedure conditional;
 15219  label exit,done,reswitch,found;
 15220  var @!save_cond_ptr:pointer; {|cond_ptr| corresponding to this conditional}
 15221  @!new_if_limit:fi_code..else_if_code; {future value of |if_limit|}
 15222  @!p:pointer; {temporary register}
 15223  begin @<Push the condition stack@>;@+save_cond_ptr:=cond_ptr;
 15224  reswitch: get_boolean; new_if_limit:=else_if_code;
 15225  if internal[tracing_commands]>unity then
 15226    @<Display the boolean value of |cur_exp|@>;
 15227  found: check_colon;
 15228  if cur_exp=true_code then
 15229    begin change_if_limit(new_if_limit,save_cond_ptr);
 15230    return; {wait for \&{elseif}, \&{else}, or \&{fi}}
 15231    end;
 15232  @<Skip to \&{elseif} or \&{else} or \&{fi}, then |goto done|@>;
 15233  done: cur_if:=cur_mod; if_line:=line;
 15234  if cur_mod=fi_code then @<Pop the condition stack@>
 15235  else if cur_mod=else_if_code then goto reswitch
 15236  else  begin cur_exp:=true_code; new_if_limit:=fi_code; get_x_next; goto found;
 15237    end;
 15238  exit:end;
 15239  
 15240  @ In a construction like `\&{if} \&{if} \&{true}: $0=1$: \\{foo}
 15241  \&{else}: \\{bar} \&{fi}', the first \&{else}
 15242  that we come to after learning that the \&{if} is false is not the
 15243  \&{else} we're looking for. Hence the following curious logic is needed.
 15244  
 15245  @<Skip to \&{elseif}...@>=
 15246  loop@+  begin pass_text;
 15247    if cond_ptr=save_cond_ptr then goto done
 15248    else if cur_mod=fi_code then @<Pop the condition stack@>;
 15249    end
 15250  
 15251  
 15252  @ @<Display the boolean value...@>=
 15253  begin begin_diagnostic;
 15254  if cur_exp=true_code then print("{true}")@+else print("{false}");
 15255  end_diagnostic(false);
 15256  end
 15257  
 15258  @ The processing of conditionals is complete except for the following
 15259  code, which is actually part of |get_x_next|. It comes into play when
 15260  \&{elseif}, \&{else}, or \&{fi} is scanned.
 15261  
 15262  @<Terminate the current conditional and skip to \&{fi}@>=
 15263  if cur_mod>if_limit then
 15264    if if_limit=if_code then {condition not yet evaluated}
 15265      begin missing_err(":");
 15266  @.Missing `:'@>
 15267      back_input; cur_sym:=frozen_colon; ins_error;
 15268      end
 15269    else  begin print_err("Extra "); print_cmd_mod(fi_or_else,cur_mod);
 15270  @.Extra else@>
 15271  @.Extra elseif@>
 15272  @.Extra fi@>
 15273      help1("I'm ignoring this; it doesn't match any if.");
 15274      error;
 15275      end
 15276  else  begin while cur_mod<>fi_code do pass_text; {skip to \&{fi}}
 15277    @<Pop the condition stack@>;
 15278    end
 15279  
 15280  @* \[37] Iterations.
 15281  To bring our treatment of |get_x_next| to a close, we need to consider what
 15282  \MF\ does when it sees \&{for}, \&{forsuffixes}, and \&{forever}.
 15283  
 15284  There's a global variable |loop_ptr| that keeps track of the \&{for} loops
 15285  that are currently active. If |loop_ptr=null|, no loops are in progress;
 15286  otherwise |info(loop_ptr)| points to the iterative text of the current
 15287  (innermost) loop, and |link(loop_ptr)| points to the data for any other
 15288  loops that enclose the current one.
 15289  
 15290  A loop-control node also has two other fields, called |loop_type| and
 15291  |loop_list|, whose contents depend on the type of loop:
 15292  
 15293  \yskip\indent|loop_type(loop_ptr)=null| means that |loop_list(loop_ptr)|
 15294  points to a list of one-word nodes whose |info| fields point to the
 15295  remaining argument values of a suffix list and expression list.
 15296  
 15297  \yskip\indent|loop_type(loop_ptr)=void| means that the current loop is
 15298  `\&{forever}'.
 15299  
 15300  \yskip\indent|loop_type(loop_ptr)=p>void| means that |value(p)|,
 15301  |step_size(p)|, and |final_value(p)| contain the data for an arithmetic
 15302  progression.
 15303  
 15304  \yskip\noindent In the latter case, |p| points to a ``progression node''
 15305  whose first word is not used. (No value could be stored there because the
 15306  link field of words in the dynamic memory area cannot be arbitrary.)
 15307  
 15308  @d loop_list_loc(#)==#+1 {where the |loop_list| field resides}
 15309  @d loop_type(#)==info(loop_list_loc(#)) {the type of \&{for} loop}
 15310  @d loop_list(#)==link(loop_list_loc(#)) {the remaining list elements}
 15311  @d loop_node_size=2 {the number of words in a loop control node}
 15312  @d progression_node_size=4 {the number of words in a progression node}
 15313  @d step_size(#)==mem[#+2].sc {the step size in an arithmetic progression}
 15314  @d final_value(#)==mem[#+3].sc {the final value in an arithmetic progression}
 15315  
 15316  @<Glob...@>=
 15317  @!loop_ptr:pointer; {top of the loop-control-node stack}
 15318  
 15319  @ @<Set init...@>=
 15320  loop_ptr:=null;
 15321  
 15322  @ If the expressions that define an arithmetic progression in
 15323  a \&{for} loop don't have known numeric values, the |bad_for|
 15324  subroutine screams at the user.
 15325  
 15326  @p procedure bad_for(@!s:str_number);
 15327  begin disp_err(null,"Improper "); {show the bad expression above the message}
 15328  @.Improper...replaced by 0@>
 15329  print(s); print(" has been replaced by 0");
 15330  help4("When you say `for x=a step b until c',")@/
 15331    ("the initial value `a' and the step size `b'")@/
 15332    ("and the final value `c' must have known numeric values.")@/
 15333    ("I'm zeroing this one. Proceed, with fingers crossed.");
 15334  put_get_flush_error(0);
 15335  end;
 15336  
 15337  @ Here's what \MF\ does when \&{for}, \&{forsuffixes}, or \&{forever}
 15338  has just been scanned. (This code requires slight familiarity with
 15339  expression-parsing routines that we have not yet discussed; but it seems
 15340  to belong in the present part of the program, even though the author
 15341  didn't write it until later. The reader may wish to come back to it.)
 15342  
 15343  @p procedure begin_iteration;
 15344  label continue,done,found;
 15345  var @!m:halfword; {|expr_base| (\&{for}) or |suffix_base| (\&{forsuffixes})}
 15346  @!n:halfword; {hash address of the current symbol}
 15347  @!p,@!q,@!s,@!pp:pointer; {link manipulation registers}
 15348  begin m:=cur_mod; n:=cur_sym; s:=get_node(loop_node_size);
 15349  if m=start_forever then
 15350    begin loop_type(s):=void; p:=null; get_x_next; goto found;
 15351    end;
 15352  get_symbol; p:=get_node(token_node_size); info(p):=cur_sym; value(p):=m;@/
 15353  get_x_next;
 15354  if (cur_cmd<>equals)and(cur_cmd<>assignment) then
 15355    begin missing_err("=");@/
 15356  @.Missing `='@>
 15357    help3("The next thing in this loop should have been `=' or `:='.")@/
 15358      ("But don't worry; I'll pretend that an equals sign")@/
 15359      ("was present, and I'll look for the values next.");@/
 15360    back_error;
 15361    end;
 15362  @<Scan the values to be used in the loop@>;
 15363  found:@<Check for the presence of a colon@>;
 15364  @<Scan the loop text and put it on the loop control stack@>;
 15365  resume_iteration;
 15366  end;
 15367  
 15368  @ @<Check for the presence of a colon@>=
 15369  if cur_cmd<>colon then
 15370    begin missing_err(":");@/
 15371  @.Missing `:'@>
 15372    help3("The next thing in this loop should have been a `:'.")@/
 15373      ("So I'll pretend that a colon was present;")@/
 15374      ("everything from here to `endfor' will be iterated.");
 15375    back_error;
 15376    end
 15377  
 15378  @ We append a special |frozen_repeat_loop| token in place of the
 15379  `\&{endfor}' at the end of the loop. This will come through \MF's scanner
 15380  at the proper time to cause the loop to be repeated.
 15381  
 15382  (A user who tries some shenanigan like `\&{for} $\ldots$ \&{let} \&{endfor}'
 15383  will be foiled by the |get_symbol| routine, which keeps frozen
 15384  tokens unchanged. Furthermore the |frozen_repeat_loop| is an \&{outer}
 15385  token, so it won't be lost accidentally.)
 15386  
 15387  @ @<Scan the loop text...@>=
 15388  q:=get_avail; info(q):=frozen_repeat_loop;
 15389  scanner_status:=loop_defining; warning_info:=n;
 15390  info(s):=scan_toks(iteration,p,q,0); scanner_status:=normal;@/
 15391  link(s):=loop_ptr; loop_ptr:=s
 15392  
 15393  @ @<Initialize table...@>=
 15394  eq_type(frozen_repeat_loop):=repeat_loop+outer_tag;
 15395  text(frozen_repeat_loop):=" ENDFOR";
 15396  
 15397  @ The loop text is inserted into \MF's scanning apparatus by the
 15398  |resume_iteration| routine.
 15399  
 15400  @p procedure resume_iteration;
 15401  label not_found,exit;
 15402  var @!p,@!q:pointer; {link registers}
 15403  begin p:=loop_type(loop_ptr);
 15404  if p>void then {|p| points to a progression node}
 15405    begin cur_exp:=value(p);
 15406    if @<The arithmetic progression has ended@> then goto not_found;
 15407    cur_type:=known; q:=stash_cur_exp; {make |q| an \&{expr} argument}
 15408    value(p):=cur_exp+step_size(p); {set |value(p)| for the next iteration}
 15409    end
 15410  else if p<void then
 15411    begin p:=loop_list(loop_ptr);
 15412    if p=null then goto not_found;
 15413    loop_list(loop_ptr):=link(p); q:=info(p); free_avail(p);
 15414    end
 15415  else  begin begin_token_list(info(loop_ptr),forever_text); return;
 15416    end;
 15417  begin_token_list(info(loop_ptr),loop_text);
 15418  stack_argument(q);
 15419  if internal[tracing_commands]>unity then @<Trace the start of a loop@>;
 15420  return;
 15421  not_found:stop_iteration;
 15422  exit:end;
 15423  
 15424  @ @<The arithmetic progression has ended@>=
 15425  ((step_size(p)>0)and(cur_exp>final_value(p)))or@|
 15426   ((step_size(p)<0)and(cur_exp<final_value(p)))
 15427  
 15428  @ @<Trace the start of a loop@>=
 15429  begin begin_diagnostic; print_nl("{loop value=");
 15430  @.loop value=n@>
 15431  if (q<>null)and(link(q)=void) then print_exp(q,1)
 15432  else show_token_list(q,null,50,0);
 15433  print_char("}"); end_diagnostic(false);
 15434  end
 15435  
 15436  @ A level of loop control disappears when |resume_iteration| has decided
 15437  not to resume, or when an \&{exitif} construction has removed the loop text
 15438  from the input stack.
 15439  
 15440  @p procedure stop_iteration;
 15441  var @!p,@!q:pointer; {the usual}
 15442  begin p:=loop_type(loop_ptr);
 15443  if p>void then free_node(p,progression_node_size)
 15444  else if p<void then
 15445    begin q:=loop_list(loop_ptr);
 15446    while q<>null do
 15447      begin p:=info(q);
 15448      if p<>null then
 15449        if link(p)=void then {it's an \&{expr} parameter}
 15450          begin recycle_value(p); free_node(p,value_node_size);
 15451          end
 15452        else flush_token_list(p); {it's a \&{suffix} or \&{text} parameter}
 15453      p:=q; q:=link(q); free_avail(p);
 15454      end;
 15455    end;
 15456  p:=loop_ptr; loop_ptr:=link(p); flush_token_list(info(p));
 15457  free_node(p,loop_node_size);
 15458  end;
 15459  
 15460  @ Now that we know all about loop control, we can finish up
 15461  the missing portion of |begin_iteration| and we'll be done.
 15462  
 15463  The following code is performed after the `\.=' has been scanned in
 15464  a \&{for} construction (if |m=expr_base|) or a \&{forsuffixes} construction
 15465  (if |m=suffix_base|).
 15466  
 15467  @<Scan the values to be used in the loop@>=
 15468  loop_type(s):=null; q:=loop_list_loc(s); link(q):=null; {|link(q)=loop_list(s)|}
 15469  repeat get_x_next;
 15470  if m<>expr_base then scan_suffix
 15471  else  begin if cur_cmd>=colon then if cur_cmd<=comma then goto continue;
 15472    scan_expression;
 15473    if cur_cmd=step_token then if q=loop_list_loc(s) then
 15474      @<Prepare for step-until construction and |goto done|@>;
 15475    cur_exp:=stash_cur_exp;
 15476    end;
 15477  link(q):=get_avail; q:=link(q); info(q):=cur_exp; cur_type:=vacuous;
 15478  continue: until cur_cmd<>comma;
 15479  done:
 15480  
 15481  @ @<Prepare for step-until construction and |goto done|@>=
 15482  begin if cur_type<>known then bad_for("initial value");
 15483  pp:=get_node(progression_node_size); value(pp):=cur_exp;@/
 15484  get_x_next; scan_expression;
 15485  if cur_type<>known then bad_for("step size");
 15486  step_size(pp):=cur_exp;
 15487  if cur_cmd<>until_token then
 15488    begin missing_err("until");@/
 15489  @.Missing `until'@>
 15490    help2("I assume you meant to say `until' after `step'.")@/
 15491      ("So I'll look for the final value and colon next.");
 15492    back_error;
 15493    end;
 15494  get_x_next; scan_expression;
 15495  if cur_type<>known then bad_for("final value");
 15496  final_value(pp):=cur_exp; loop_type(s):=pp; goto done;
 15497  end
 15498  
 15499  @* \[38] File names.
 15500  It's time now to fret about file names.  Besides the fact that different
 15501  operating systems treat files in different ways, we must cope with the
 15502  fact that completely different naming conventions are used by different
 15503  groups of people. The following programs show what is required for one
 15504  particular operating system; similar routines for other systems are not
 15505  difficult to devise.
 15506  @^system dependencies@>
 15507  
 15508  \MF\ assumes that a file name has three parts: the name proper; its
 15509  ``extension''; and a ``file area'' where it is found in an external file
 15510  system.  The extension of an input file is assumed to be
 15511  `\.{.mf}' unless otherwise specified; it is `\.{.log}' on the
 15512  transcript file that records each run of \MF; it is `\.{.tfm}' on the font
 15513  metric files that describe characters in the fonts \MF\ creates; it is
 15514  `\.{.gf}' on the output files that specify generic font information; and it
 15515  is `\.{.base}' on the base files written by \.{INIMF} to initialize \MF.
 15516  The file area can be arbitrary on input files, but files are usually
 15517  output to the user's current area.  If an input file cannot be
 15518  found on the specified area, \MF\ will look for it on a special system
 15519  area; this special area is intended for commonly used input files.
 15520  
 15521  Simple uses of \MF\ refer only to file names that have no explicit
 15522  extension or area. For example, a person usually says `\.{input} \.{cmr10}'
 15523  instead of `\.{input} \.{cmr10.new}'. Simple file
 15524  names are best, because they make the \MF\ source files portable;
 15525  whenever a file name consists entirely of letters and digits, it should be
 15526  treated in the same way by all implementations of \MF. However, users
 15527  need the ability to refer to other files in their environment, especially
 15528  when responding to error messages concerning unopenable files; therefore
 15529  we want to let them use the syntax that appears in their favorite
 15530  operating system.
 15531  
 15532  @ \MF\ uses the same conventions that have proved to be satisfactory for
 15533  \TeX. In order to isolate the system-dependent aspects of file names, the
 15534  @^system dependencies@>
 15535  system-independent parts of \MF\ are expressed in terms
 15536  of three system-dependent
 15537  procedures called |begin_name|, |more_name|, and |end_name|. In
 15538  essence, if the user-specified characters of the file name are $c_1\ldots c_n$,
 15539  the system-independent driver program does the operations
 15540  $$|begin_name|;\,|more_name|(c_1);\,\ldots\,;\,|more_name|(c_n);
 15541  \,|end_name|.$$
 15542  These three procedures communicate with each other via global variables.
 15543  Afterwards the file name will appear in the string pool as three strings
 15544  called |cur_name|\penalty10000\hskip-.05em,
 15545  |cur_area|, and |cur_ext|; the latter two are null (i.e.,
 15546  |""|), unless they were explicitly specified by the user.
 15547  
 15548  Actually the situation is slightly more complicated, because \MF\ needs
 15549  to know when the file name ends. The |more_name| routine is a function
 15550  (with side effects) that returns |true| on the calls |more_name|$(c_1)$,
 15551  \dots, |more_name|$(c_{n-1})$. The final call |more_name|$(c_n)$
 15552  returns |false|; or, it returns |true| and $c_n$ is the last character
 15553  on the current input line. In other words,
 15554  |more_name| is supposed to return |true| unless it is sure that the
 15555  file name has been completely scanned; and |end_name| is supposed to be able
 15556  to finish the assembly of |cur_name|, |cur_area|, and |cur_ext| regardless of
 15557  whether $|more_name|(c_n)$ returned |true| or |false|.
 15558  
 15559  @<Glob...@>=
 15560  @!cur_name:str_number; {name of file just scanned}
 15561  @!cur_area:str_number; {file area just scanned, or \.{""}}
 15562  @!cur_ext:str_number; {file extension just scanned, or \.{""}}
 15563  
 15564  @ The file names we shall deal with for illustrative purposes have the
 15565  following structure:  If the name contains `\.>' or `\.:', the file area
 15566  consists of all characters up to and including the final such character;
 15567  otherwise the file area is null.  If the remaining file name contains
 15568  `\..', the file extension consists of all such characters from the first
 15569  remaining `\..' to the end, otherwise the file extension is null.
 15570  @^system dependencies@>
 15571  
 15572  We can scan such file names easily by using two global variables that keep track
 15573  of the occurrences of area and extension delimiters:
 15574  
 15575  @<Glob...@>=
 15576  @!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any}
 15577  @!ext_delimiter:pool_pointer; {the relevant `\..', if any}
 15578  
 15579  @ Input files that can't be found in the user's area may appear in a standard
 15580  system area called |MF_area|.
 15581  This system area name will, of course, vary from place to place.
 15582  @^system dependencies@>
 15583  
 15584  @d MF_area=="MFinputs:"
 15585  @.MFinputs@>
 15586  
 15587  @ Here now is the first of the system-dependent routines for file name scanning.
 15588  @^system dependencies@>
 15589  
 15590  @p procedure begin_name;
 15591  begin area_delimiter:=0; ext_delimiter:=0;
 15592  end;
 15593  
 15594  @ And here's the second.
 15595  @^system dependencies@>
 15596  
 15597  @p function more_name(@!c:ASCII_code):boolean;
 15598  begin if c=" " then more_name:=false
 15599  else  begin if (c=">")or(c=":") then
 15600      begin area_delimiter:=pool_ptr; ext_delimiter:=0;
 15601      end
 15602    else if (c=".")and(ext_delimiter=0) then ext_delimiter:=pool_ptr;
 15603    str_room(1); append_char(c); {contribute |c| to the current string}
 15604    more_name:=true;
 15605    end;
 15606  end;
 15607  
 15608  @ The third.
 15609  @^system dependencies@>
 15610  
 15611  @p procedure end_name;
 15612  begin if str_ptr+3>max_str_ptr then
 15613    begin if str_ptr+3>max_strings then
 15614      overflow("number of strings",max_strings-init_str_ptr);
 15615  @:METAFONT capacity exceeded number of strings}{\quad number of strings@>
 15616    max_str_ptr:=str_ptr+3;
 15617    end;
 15618  if area_delimiter=0 then cur_area:=""
 15619  else  begin cur_area:=str_ptr; incr(str_ptr);
 15620    str_start[str_ptr]:=area_delimiter+1;
 15621    end;
 15622  if ext_delimiter=0 then
 15623    begin cur_ext:=""; cur_name:=make_string;
 15624    end
 15625  else  begin cur_name:=str_ptr; incr(str_ptr);
 15626    str_start[str_ptr]:=ext_delimiter; cur_ext:=make_string;
 15627    end;
 15628  end;
 15629  
 15630  @ Conversely, here is a routine that takes three strings and prints a file
 15631  name that might have produced them. (The routine is system dependent, because
 15632  some operating systems put the file area last instead of first.)
 15633  @^system dependencies@>
 15634  
 15635  @<Basic printing...@>=
 15636  procedure print_file_name(@!n,@!a,@!e:integer);
 15637  begin slow_print(a); slow_print(n); slow_print(e);
 15638  end;
 15639  
 15640  @ Another system-dependent routine is needed to convert three internal
 15641  \MF\ strings
 15642  to the |name_of_file| value that is used to open files. The present code
 15643  allows both lowercase and uppercase letters in the file name.
 15644  @^system dependencies@>
 15645  
 15646  @d append_to_name(#)==begin c:=#; incr(k);
 15647    if k<=file_name_size then name_of_file[k]:=xchr[c];
 15648    end
 15649  
 15650  @p procedure pack_file_name(@!n,@!a,@!e:str_number);
 15651  var @!k:integer; {number of positions filled in |name_of_file|}
 15652  @!c: ASCII_code; {character being packed}
 15653  @!j:pool_pointer; {index into |str_pool|}
 15654  begin k:=0;
 15655  for j:=str_start[a] to str_start[a+1]-1 do append_to_name(so(str_pool[j]));
 15656  for j:=str_start[n] to str_start[n+1]-1 do append_to_name(so(str_pool[j]));
 15657  for j:=str_start[e] to str_start[e+1]-1 do append_to_name(so(str_pool[j]));
 15658  if k<=file_name_size then name_length:=k@+else name_length:=file_name_size;
 15659  for k:=name_length+1 to file_name_size do name_of_file[k]:=' ';
 15660  end;
 15661  
 15662  @ A messier routine is also needed, since base file names must be scanned
 15663  before \MF's string mechanism has been initialized. We shall use the
 15664  global variable |MF_base_default| to supply the text for default system areas
 15665  and extensions related to base files.
 15666  @^system dependencies@>
 15667  
 15668  @d base_default_length=18 {length of the |MF_base_default| string}
 15669  @d base_area_length=8 {length of its area part}
 15670  @d base_ext_length=5 {length of its `\.{.base}' part}
 15671  @d base_extension=".base" {the extension, as a \.{WEB} constant}
 15672  
 15673  @<Glob...@>=
 15674  @!MF_base_default:packed array[1..base_default_length] of char;
 15675  
 15676  @ @<Set init...@>=
 15677  MF_base_default:='MFbases:plain.base';
 15678  @.MFbases@>
 15679  @.plain@>
 15680  @^system dependencies@>
 15681  
 15682  @ @<Check the ``constant'' values for consistency@>=
 15683  if base_default_length>file_name_size then bad:=41;
 15684  
 15685  @ Here is the messy routine that was just mentioned. It sets |name_of_file|
 15686  from the first |n| characters of |MF_base_default|, followed by
 15687  |buffer[a..b]|, followed by the last |base_ext_length| characters of
 15688  |MF_base_default|.
 15689  
 15690  We dare not give error messages here, since \MF\ calls this routine before
 15691  the |error| routine is ready to roll. Instead, we simply drop excess characters,
 15692  since the error will be detected in another way when a strange file name
 15693  isn't found.
 15694  @^system dependencies@>
 15695  
 15696  @p procedure pack_buffered_name(@!n:small_number;@!a,@!b:integer);
 15697  var @!k:integer; {number of positions filled in |name_of_file|}
 15698  @!c: ASCII_code; {character being packed}
 15699  @!j:integer; {index into |buffer| or |MF_base_default|}
 15700  begin if n+b-a+1+base_ext_length>file_name_size then
 15701    b:=a+file_name_size-n-1-base_ext_length;
 15702  k:=0;
 15703  for j:=1 to n do append_to_name(xord[MF_base_default[j]]);
 15704  for j:=a to b do append_to_name(buffer[j]);
 15705  for j:=base_default_length-base_ext_length+1 to base_default_length do
 15706    append_to_name(xord[MF_base_default[j]]);
 15707  if k<=file_name_size then name_length:=k@+else name_length:=file_name_size;
 15708  for k:=name_length+1 to file_name_size do name_of_file[k]:=' ';
 15709  end;
 15710  
 15711  @ Here is the only place we use |pack_buffered_name|. This part of the program
 15712  becomes active when a ``virgin'' \MF\ is trying to get going, just after
 15713  the preliminary initialization, or when the user is substituting another
 15714  base file by typing `\.\&' after the initial `\.{**}' prompt.  The buffer
 15715  contains the first line of input in |buffer[loc..(last-1)]|, where
 15716  |loc<last| and |buffer[loc]<>" "|.
 15717  
 15718  @<Declare the function called |open_base_file|@>=
 15719  function open_base_file:boolean;
 15720  label found,exit;
 15721  var @!j:0..buf_size; {the first space after the file name}
 15722  begin j:=loc;
 15723  if buffer[loc]="&" then
 15724    begin incr(loc); j:=loc; buffer[last]:=" ";
 15725    while buffer[j]<>" " do incr(j);
 15726    pack_buffered_name(0,loc,j-1); {try first without the system file area}
 15727    if w_open_in(base_file) then goto found;
 15728    pack_buffered_name(base_area_length,loc,j-1);
 15729      {now try the system base file area}
 15730    if w_open_in(base_file) then goto found;
 15731    wake_up_terminal;
 15732    wterm_ln('Sorry, I can''t find that base;',' will try PLAIN.');
 15733  @.Sorry, I can't find...@>
 15734    update_terminal;
 15735    end;
 15736    {now pull out all the stops: try for the system \.{plain} file}
 15737  pack_buffered_name(base_default_length-base_ext_length,1,0);
 15738  if not w_open_in(base_file) then
 15739    begin wake_up_terminal;
 15740    wterm_ln('I can''t find the PLAIN base file!');
 15741  @.I can't find PLAIN...@>
 15742  @.plain@>
 15743    open_base_file:=false; return;
 15744    end;
 15745  found:loc:=j; open_base_file:=true;
 15746  exit:end;
 15747  
 15748  @ Operating systems often make it possible to determine the exact name (and
 15749  possible version number) of a file that has been opened. The following routine,
 15750  which simply makes a \MF\ string from the value of |name_of_file|, should
 15751  ideally be changed to deduce the full name of file~|f|, which is the file
 15752  most recently opened, if it is possible to do this in a \PASCAL\ program.
 15753  @^system dependencies@>
 15754  
 15755  This routine might be called after string memory has overflowed, hence
 15756  we dare not use `|str_room|'.
 15757  
 15758  @p function make_name_string:str_number;
 15759  var @!k:1..file_name_size; {index into |name_of_file|}
 15760  begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings) then
 15761    make_name_string:="?"
 15762  else  begin for k:=1 to name_length do append_char(xord[name_of_file[k]]);
 15763    make_name_string:=make_string;
 15764    end;
 15765  end;
 15766  function a_make_name_string(var @!f:alpha_file):str_number;
 15767  begin a_make_name_string:=make_name_string;
 15768  end;
 15769  function b_make_name_string(var @!f:byte_file):str_number;
 15770  begin b_make_name_string:=make_name_string;
 15771  end;
 15772  function w_make_name_string(var @!f:word_file):str_number;
 15773  begin w_make_name_string:=make_name_string;
 15774  end;
 15775  
 15776  @ Now let's consider the ``driver''
 15777  routines by which \MF\ deals with file names
 15778  in a system-independent manner.  First comes a procedure that looks for a
 15779  file name in the input by taking the information from the input buffer.
 15780  (We can't use |get_next|, because the conversion to tokens would
 15781  destroy necessary information.)
 15782  
 15783  This procedure doesn't allow semicolons or percent signs to be part of
 15784  file names, because of other conventions of \MF. The manual doesn't
 15785  use semicolons or percents immediately after file names, but some users
 15786  no doubt will find it natural to do so; therefore system-dependent
 15787  changes to allow such characters in file names should probably
 15788  be made with reluctance, and only when an entire file name that
 15789  includes special characters is ``quoted'' somehow.
 15790  @^system dependencies@>
 15791  
 15792  @p procedure scan_file_name;
 15793  label done;
 15794  begin begin_name;
 15795  while buffer[loc]=" " do incr(loc);
 15796  loop@+begin if (buffer[loc]=";")or(buffer[loc]="%") then goto done;
 15797    if not more_name(buffer[loc]) then goto done;
 15798    incr(loc);
 15799    end;
 15800  done: end_name;
 15801  end;
 15802  
 15803  @ The global variable |job_name| contains the file name that was first
 15804  \&{input} by the user. This name is extended by `\.{.log}' and `\.{.gf}' and
 15805  `\.{.base}' and `\.{.tfm}' in the names of \MF's output files.
 15806  
 15807  @<Glob...@>=
 15808  @!job_name:str_number; {principal file name}
 15809  @!log_opened:boolean; {has the transcript file been opened?}
 15810  @!log_name:str_number; {full name of the log file}
 15811  
 15812  @ Initially |job_name=0|; it becomes nonzero as soon as the true name is known.
 15813  We have |job_name=0| if and only if the `\.{log}' file has not been opened,
 15814  except of course for a short time just after |job_name| has become nonzero.
 15815  
 15816  @<Initialize the output...@>=job_name:=0; log_opened:=false;
 15817  
 15818  @ Here is a routine that manufactures the output file names, assuming that
 15819  |job_name<>0|. It ignores and changes the current settings of |cur_area|
 15820  and |cur_ext|.
 15821  
 15822  @d pack_cur_name==pack_file_name(cur_name,cur_area,cur_ext)
 15823  
 15824  @p procedure pack_job_name(@!s:str_number); {|s = ".log"|, |".gf"|,
 15825    |".tfm"|, or |base_extension|}
 15826  begin cur_area:=""; cur_ext:=s;
 15827  cur_name:=job_name; pack_cur_name;
 15828  end;
 15829  
 15830  @ Actually the main output file extension is usually something like
 15831  |".300gf"| instead of just |".gf"|; the additional number indicates the
 15832  resolution in pixels per inch, based on the setting of |hppp| when
 15833  the file is opened.
 15834  
 15835  @<Glob...@>=
 15836  @!gf_ext:str_number; {default extension for the output file}
 15837  
 15838  @ If some trouble arises when \MF\ tries to open a file, the following
 15839  routine calls upon the user to supply another file name. Parameter~|s|
 15840  is used in the error message to identify the type of file; parameter~|e|
 15841  is the default extension if none is given. Upon exit from the routine,
 15842  variables |cur_name|, |cur_area|, |cur_ext|, and |name_of_file| are
 15843  ready for another attempt at file opening.
 15844  
 15845  @p procedure prompt_file_name(@!s,@!e:str_number);
 15846  label done;
 15847  var @!k:0..buf_size; {index into |buffer|}
 15848  begin if interaction=scroll_mode then wake_up_terminal;
 15849  if s="input file name" then print_err("I can't find file `")
 15850  @.I can't find file x@>
 15851  else print_err("I can't write on file `");
 15852  @.I can't write on file x@>
 15853  print_file_name(cur_name,cur_area,cur_ext); print("'.");
 15854  if e=".mf" then show_context;
 15855  print_nl("Please type another "); print(s);
 15856  @.Please type...@>
 15857  if interaction<scroll_mode then
 15858    fatal_error("*** (job aborted, file error in nonstop mode)");
 15859  @.job aborted, file error...@>
 15860  clear_terminal; prompt_input(": "); @<Scan file name in the buffer@>;
 15861  if cur_ext="" then cur_ext:=e;
 15862  pack_cur_name;
 15863  end;
 15864  
 15865  @ @<Scan file name in the buffer@>=
 15866  begin begin_name; k:=first;
 15867  while (buffer[k]=" ")and(k<last) do incr(k);
 15868  loop@+  begin if k=last then goto done;
 15869    if not more_name(buffer[k]) then goto done;
 15870    incr(k);
 15871    end;
 15872  done:end_name;
 15873  end
 15874  
 15875  @ The |open_log_file| routine is used to open the transcript file and to help
 15876  it catch up to what has previously been printed on the terminal.
 15877  
 15878  @p procedure open_log_file;
 15879  var @!old_setting:0..max_selector; {previous |selector| setting}
 15880  @!k:0..buf_size; {index into |months| and |buffer|}
 15881  @!l:0..buf_size; {end of first input line}
 15882  @!m:integer; {the current month}
 15883  @!months:packed array [1..36] of char; {abbreviations of month names}
 15884  begin old_setting:=selector;
 15885  if job_name=0 then job_name:="mfput";
 15886  @.mfput@>
 15887  pack_job_name(".log");
 15888  while not a_open_out(log_file) do @<Try to get a different log file name@>;
 15889  log_name:=a_make_name_string(log_file);
 15890  selector:=log_only; log_opened:=true;
 15891  @<Print the banner line, including the date and time@>;
 15892  input_stack[input_ptr]:=cur_input; {make sure bottom level is in memory}
 15893  print_nl("**");
 15894  @.**@>
 15895  l:=input_stack[0].limit_field-1; {last position of first line}
 15896  for k:=1 to l do print(buffer[k]);
 15897  print_ln; {now the transcript file contains the first line of input}
 15898  selector:=old_setting+2; {|log_only| or |term_and_log|}
 15899  end;
 15900  
 15901  @ Sometimes |open_log_file| is called at awkward moments when \MF\ is
 15902  unable to print error messages or even to |show_context|.
 15903  The |prompt_file_name| routine can result in a |fatal_error|, but the |error|
 15904  routine will not be invoked because |log_opened| will be false.
 15905  
 15906  The normal idea of |batch_mode| is that nothing at all should be written
 15907  on the terminal. However, in the unusual case that
 15908  no log file could be opened, we make an exception and allow
 15909  an explanatory message to be seen.
 15910  
 15911  Incidentally, the program always refers to the log file as a `\.{transcript
 15912  file}', because some systems cannot use the extension `\.{.log}' for
 15913  this file.
 15914  
 15915  @<Try to get a different log file name@>=
 15916  begin selector:=term_only;
 15917  prompt_file_name("transcript file name",".log");
 15918  end
 15919  
 15920  @ @<Print the banner...@>=
 15921  begin wlog(banner);
 15922  slow_print(base_ident); print("  ");
 15923  print_int(sys_day); print_char(" ");
 15924  months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
 15925  for k:=3*sys_month-2 to 3*sys_month do wlog(months[k]);
 15926  print_char(" "); print_int(sys_year); print_char(" ");
 15927  print_dd(sys_time div 60); print_char(":"); print_dd(sys_time mod 60);
 15928  end
 15929  
 15930  @ Here's an example of how these file-name-parsing routines work in practice.
 15931  We shall use the macro |set_output_file_name| when it is time to
 15932  crank up the output file.
 15933  
 15934  @d set_output_file_name==
 15935    begin if job_name=0 then open_log_file;
 15936    pack_job_name(gf_ext);
 15937    while not b_open_out(gf_file) do
 15938      prompt_file_name("file name for output",gf_ext);
 15939    output_file_name:=b_make_name_string(gf_file);
 15940    end
 15941  
 15942  @<Glob...@>=
 15943  @!gf_file: byte_file; {the generic font output goes here}
 15944  @!output_file_name: str_number; {full name of the output file}
 15945  
 15946  @ @<Initialize the output...@>=output_file_name:=0;
 15947  
 15948  @ Let's turn now to the procedure that is used to initiate file reading
 15949  when an `\.{input}' command is being processed.
 15950  Beware: For historic reasons, this code foolishly conserves a tiny bit
 15951  of string pool space; but that can confuse the interactive `\.E' option.
 15952  @^system dependencies@>
 15953  
 15954  @p procedure start_input; {\MF\ will \.{input} something}
 15955  label done;
 15956  begin @<Put the desired file name in |(cur_name,cur_ext,cur_area)|@>;
 15957  if cur_ext="" then cur_ext:=".mf";
 15958  pack_cur_name;
 15959  loop@+  begin begin_file_reading; {set up |cur_file| and new level of input}
 15960    if a_open_in(cur_file) then goto done;
 15961    if cur_area="" then
 15962      begin pack_file_name(cur_name,MF_area,cur_ext);
 15963      if a_open_in(cur_file) then goto done;
 15964      end;
 15965    end_file_reading; {remove the level that didn't work}
 15966    prompt_file_name("input file name",".mf");
 15967    end;
 15968  done: name:=a_make_name_string(cur_file); str_ref[cur_name]:=max_str_ref;
 15969  if job_name=0 then
 15970    begin job_name:=cur_name; open_log_file;
 15971    end; {|open_log_file| doesn't |show_context|, so |limit|
 15972      and |loc| needn't be set to meaningful values yet}
 15973  if term_offset+length(name)>max_print_line-2 then print_ln
 15974  else if (term_offset>0)or(file_offset>0) then print_char(" ");
 15975  print_char("("); incr(open_parens); slow_print(name); update_terminal;
 15976  if name=str_ptr-1 then {conserve string pool space (but see note above)}
 15977    begin flush_string(name); name:=cur_name;
 15978    end;
 15979  @<Read the first line of the new file@>;
 15980  end;
 15981  
 15982  @ Here we have to remember to tell the |input_ln| routine not to
 15983  start with a |get|. If the file is empty, it is considered to
 15984  contain a single blank line.
 15985  @^system dependencies@>
 15986  
 15987  @<Read the first line...@>=
 15988  begin line:=1;
 15989  if input_ln(cur_file,false) then do_nothing;
 15990  firm_up_the_line;
 15991  buffer[limit]:="%"; first:=limit+1; loc:=start;
 15992  end
 15993  
 15994  @ @<Put the desired file name in |(cur_name,cur_ext,cur_area)|@>=
 15995  while token_state and(loc=null) do end_token_list;
 15996  if token_state then
 15997    begin print_err("File names can't appear within macros");
 15998  @.File names can't...@>
 15999    help3("Sorry...I've converted what follows to tokens,")@/
 16000      ("possibly garbaging the name you gave.")@/
 16001      ("Please delete the tokens and insert the name again.");@/
 16002    error;
 16003    end;
 16004  if file_state then scan_file_name
 16005  else  begin cur_name:=""; cur_ext:=""; cur_area:="";
 16006    end
 16007  
 16008  @* \[39] Introduction to the parsing routines.
 16009  We come now to the central nervous system that sparks many of \MF's activities.
 16010  By evaluating expressions, from their primary constituents to ever larger
 16011  subexpressions, \MF\ builds the structures that ultimately define fonts of type.
 16012  
 16013  Four mutually recursive subroutines are involved in this process: We call them
 16014  $$\hbox{|scan_primary|, |scan_secondary|, |scan_tertiary|,
 16015  and |scan_expression|.}$$
 16016  @^recursion@>
 16017  Each of them is parameterless and begins with the first token to be scanned
 16018  already represented in |cur_cmd|, |cur_mod|, and |cur_sym|. After execution,
 16019  the value of the primary or secondary or tertiary or expression that was
 16020  found will appear in the global variables |cur_type| and |cur_exp|. The
 16021  token following the expression will be represented in |cur_cmd|, |cur_mod|,
 16022  and |cur_sym|.
 16023  
 16024  Technically speaking, the parsing algorithms are ``LL(1),'' more or less;
 16025  backup mechanisms have been added in order to provide reasonable error
 16026  recovery.
 16027  
 16028  @<Glob...@>=
 16029  @!cur_type:small_number; {the type of the expression just found}
 16030  @!cur_exp:integer; {the value of the expression just found}
 16031  
 16032  @ @<Set init...@>=
 16033  cur_exp:=0;
 16034  
 16035  @ Many different kinds of expressions are possible, so it is wise to have
 16036  precise descriptions of what |cur_type| and |cur_exp| mean in all cases:
 16037  
 16038  \smallskip\hang
 16039  |cur_type=vacuous| means that this expression didn't turn out to have a
 16040  value at all, because it arose from a \&{begingroup}$\,\ldots\,$\&{endgroup}
 16041  construction in which there was no expression before the \&{endgroup}.
 16042  In this case |cur_exp| has some irrelevant value.
 16043  
 16044  \smallskip\hang
 16045  |cur_type=boolean_type| means that |cur_exp| is either |true_code|
 16046  or |false_code|.
 16047  
 16048  \smallskip\hang
 16049  |cur_type=unknown_boolean| means that |cur_exp| points to a capsule
 16050  node that is in
 16051  a ring of equivalent booleans whose value has not yet been defined.
 16052  
 16053  \smallskip\hang
 16054  |cur_type=string_type| means that |cur_exp| is a string number (i.e., an
 16055  integer in the range |0<=cur_exp<str_ptr|). That string's reference count
 16056  includes this particular reference.
 16057  
 16058  \smallskip\hang
 16059  |cur_type=unknown_string| means that |cur_exp| points to a capsule
 16060  node that is in
 16061  a ring of equivalent strings whose value has not yet been defined.
 16062  
 16063  \smallskip\hang
 16064  |cur_type=pen_type| means that |cur_exp| points to a pen header node. This
 16065  node contains a reference count, which takes account of this particular
 16066  reference.
 16067  
 16068  \smallskip\hang
 16069  |cur_type=unknown_pen| means that |cur_exp| points to a capsule
 16070  node that is in
 16071  a ring of equivalent pens whose value has not yet been defined.
 16072  
 16073  \smallskip\hang
 16074  |cur_type=future_pen| means that |cur_exp| points to a knot list that
 16075  should eventually be made into a pen. Nobody else points to this particular
 16076  knot list. The |future_pen| option occurs only as an output of |scan_primary|
 16077  and |scan_secondary|, not as an output of |scan_tertiary| or |scan_expression|.
 16078  
 16079  \smallskip\hang
 16080  |cur_type=path_type| means that |cur_exp| points to the first node of
 16081  a path; nobody else points to this particular path. The control points of
 16082  the path will have been chosen.
 16083  
 16084  \smallskip\hang
 16085  |cur_type=unknown_path| means that |cur_exp| points to a capsule
 16086  node that is in
 16087  a ring of equivalent paths whose value has not yet been defined.
 16088  
 16089  \smallskip\hang
 16090  |cur_type=picture_type| means that |cur_exp| points to an edges header node.
 16091  Nobody else points to this particular set of edges.
 16092  
 16093  \smallskip\hang
 16094  |cur_type=unknown_picture| means that |cur_exp| points to a capsule
 16095  node that is in
 16096  a ring of equivalent pictures whose value has not yet been defined.
 16097  
 16098  \smallskip\hang
 16099  |cur_type=transform_type| means that |cur_exp| points to a |transform_type|
 16100  capsule node. The |value| part of this capsule
 16101  points to a transform node that contains six numeric values,
 16102  each of which is |independent|, |dependent|, |proto_dependent|, or |known|.
 16103  
 16104  \smallskip\hang
 16105  |cur_type=pair_type| means that |cur_exp| points to a capsule
 16106  node whose type is |pair_type|. The |value| part of this capsule
 16107  points to a pair node that contains two numeric values,
 16108  each of which is |independent|, |dependent|, |proto_dependent|, or |known|.
 16109  
 16110  \smallskip\hang
 16111  |cur_type=known| means that |cur_exp| is a |scaled| value.
 16112  
 16113  \smallskip\hang
 16114  |cur_type=dependent| means that |cur_exp| points to a capsule node whose type
 16115  is |dependent|. The |dep_list| field in this capsule points to the associated
 16116  dependency list.
 16117  
 16118  \smallskip\hang
 16119  |cur_type=proto_dependent| means that |cur_exp| points to a |proto_dependent|
 16120  capsule node. The |dep_list| field in this capsule
 16121  points to the associated dependency list.
 16122  
 16123  \smallskip\hang
 16124  |cur_type=independent| means that |cur_exp| points to a capsule node
 16125  whose type is |independent|. This somewhat unusual case can arise, for
 16126  example, in the expression
 16127  `$x+\&{begingroup}\penalty0\,\&{string}\,x; 0\,\&{endgroup}$'.
 16128  
 16129  \smallskip\hang
 16130  |cur_type=token_list| means that |cur_exp| points to a linked list of
 16131  tokens.
 16132  
 16133  \smallskip\noindent
 16134  The possible settings of |cur_type| have been listed here in increasing
 16135  numerical order. Notice that |cur_type| will never be |numeric_type| or
 16136  |suffixed_macro| or |unsuffixed_macro|, although variables of those types
 16137  are allowed.  Conversely, \MF\ has no variables of type |vacuous| or
 16138  |token_list|.
 16139  
 16140  @ Capsules are two-word nodes that have a similar meaning
 16141  to |cur_type| and |cur_exp|. Such nodes have |name_type=capsule|,
 16142  and their |type| field is one of the possibilities for |cur_type| listed above.
 16143  Also |link<=void| in capsules that aren't part of a token list.
 16144  
 16145  The |value| field of a capsule is, in most cases, the value that
 16146  corresponds to its |type|, as |cur_exp| corresponds to |cur_type|.
 16147  However, when |cur_exp| would point to a capsule,
 16148  no extra layer of indirection is present; the |value|
 16149  field is what would have been called |value(cur_exp)| if it had not been
 16150  encapsulated.  Furthermore, if the type is |dependent| or
 16151  |proto_dependent|, the |value| field of a capsule is replaced by
 16152  |dep_list| and |prev_dep| fields, since dependency lists in capsules are
 16153  always part of the general |dep_list| structure.
 16154  
 16155  The |get_x_next| routine is careful not to change the values of |cur_type|
 16156  and |cur_exp| when it gets an expanded token. However, |get_x_next| might
 16157  call a macro, which might parse an expression, which might execute lots of
 16158  commands in a group; hence it's possible that |cur_type| might change
 16159  from, say, |unknown_boolean| to |boolean_type|, or from |dependent| to
 16160  |known| or |independent|, during the time |get_x_next| is called. The
 16161  programs below are careful to stash sensitive intermediate results in
 16162  capsules, so that \MF's generality doesn't cause trouble.
 16163  
 16164  Here's a procedure that illustrates these conventions. It takes
 16165  the contents of $(|cur_type|\kern-.3pt,|cur_exp|\kern-.3pt)$
 16166  and stashes them away in a
 16167  capsule. It is not used when |cur_type=token_list|.
 16168  After the operation, |cur_type=vacuous|; hence there is no need to
 16169  copy path lists or to update reference counts, etc.
 16170  
 16171  The special link |void| is put on the capsule returned by
 16172  |stash_cur_exp|, because this procedure is used to store macro parameters
 16173  that must be easily distinguishable from token lists.
 16174  
 16175  @<Declare the stashing/unstashing routines@>=
 16176  function stash_cur_exp:pointer;
 16177  var @!p:pointer; {the capsule that will be returned}
 16178  begin case cur_type of
 16179  unknown_types,transform_type,pair_type,dependent,proto_dependent,
 16180    independent:p:=cur_exp;
 16181  othercases begin  p:=get_node(value_node_size); name_type(p):=capsule;
 16182    type(p):=cur_type; value(p):=cur_exp;
 16183    end
 16184  endcases;@/
 16185  cur_type:=vacuous; link(p):=void; stash_cur_exp:=p;
 16186  end;
 16187  
 16188  @ The inverse of |stash_cur_exp| is the following procedure, which
 16189  deletes an unnecessary capsule and puts its contents into |cur_type|
 16190  and |cur_exp|.
 16191  
 16192  The program steps of \MF\ can be divided into two categories: those in
 16193  which |cur_type| and |cur_exp| are ``alive'' and those in which they are
 16194  ``dead,'' in the sense that |cur_type| and |cur_exp| contain relevant
 16195  information or not. It's important not to ignore them when they're alive,
 16196  and it's important not to pay attention to them when they're dead.
 16197  
 16198  There's also an intermediate category: If |cur_type=vacuous|, then
 16199  |cur_exp| is irrelevant, hence we can proceed without caring if |cur_type|
 16200  and |cur_exp| are alive or dead. In such cases we say that |cur_type|
 16201  and |cur_exp| are {\sl dormant}. It is permissible to call |get_x_next|
 16202  only when they are alive or dormant.
 16203  
 16204  The \\{stash} procedure above assumes that |cur_type| and |cur_exp|
 16205  are alive or dormant. The \\{unstash} procedure assumes that they are
 16206  dead or dormant; it resuscitates them.
 16207  
 16208  @<Declare the stashing/unstashing...@>=
 16209  procedure unstash_cur_exp(@!p:pointer);
 16210  begin cur_type:=type(p);
 16211  case cur_type of
 16212  unknown_types,transform_type,pair_type,dependent,proto_dependent,
 16213    independent: cur_exp:=p;
 16214  othercases begin cur_exp:=value(p);
 16215    free_node(p,value_node_size);
 16216    end
 16217  endcases;@/
 16218  end;
 16219  
 16220  @ The following procedure prints the values of expressions in an
 16221  abbreviated format. If its first parameter |p| is null, the value of
 16222  |(cur_type,cur_exp)| is displayed; otherwise |p| should be a capsule
 16223  containing the desired value. The second parameter controls the amount of
 16224  output. If it is~0, dependency lists will be abbreviated to
 16225  `\.{linearform}' unless they consist of a single term.  If it is greater
 16226  than~1, complicated structures (pens, pictures, and paths) will be displayed
 16227  in full.
 16228  @.linearform@>
 16229  
 16230  @<Declare subroutines for printing expressions@>=
 16231  @t\4@>@<Declare the procedure called |print_dp|@>@;
 16232  @t\4@>@<Declare the stashing/unstashing routines@>@;
 16233  procedure print_exp(@!p:pointer;@!verbosity:small_number);
 16234  var @!restore_cur_exp:boolean; {should |cur_exp| be restored?}
 16235  @!t:small_number; {the type of the expression}
 16236  @!v:integer; {the value of the expression}
 16237  @!q:pointer; {a big node being displayed}
 16238  begin if p<>null then restore_cur_exp:=false
 16239  else  begin p:=stash_cur_exp; restore_cur_exp:=true;
 16240    end;
 16241  t:=type(p);
 16242  if t<dependent then v:=value(p)@+else if t<independent then v:=dep_list(p);
 16243  @<Print an abbreviated value of |v| with format depending on |t|@>;
 16244  if restore_cur_exp then unstash_cur_exp(p);
 16245  end;
 16246  
 16247  @ @<Print an abbreviated value of |v| with format depending on |t|@>=
 16248  case t of
 16249  vacuous:print("vacuous");
 16250  boolean_type:if v=true_code then print("true")@+else print("false");
 16251  unknown_types,numeric_type:@<Display a variable
 16252    that's been declared but not defined@>;
 16253  string_type:begin print_char(""""); slow_print(v); print_char("""");
 16254    end;
 16255  pen_type,future_pen,path_type,picture_type:@<Display a complex type@>;
 16256  transform_type,pair_type:if v=null then print_type(t)
 16257    else @<Display a big node@>;
 16258  known:print_scaled(v);
 16259  dependent,proto_dependent:print_dp(t,v,verbosity);
 16260  independent:print_variable_name(p);
 16261  othercases confusion("exp")
 16262  @:this can't happen exp}{\quad exp@>
 16263  endcases
 16264  
 16265  @ @<Display a big node@>=
 16266  begin print_char("("); q:=v+big_node_size[t];
 16267  repeat if type(v)=known then print_scaled(value(v))
 16268  else if type(v)=independent then print_variable_name(v)
 16269  else print_dp(type(v),dep_list(v),verbosity);
 16270  v:=v+2;
 16271  if v<>q then print_char(",");
 16272  until v=q;
 16273  print_char(")");
 16274  end
 16275  
 16276  @ Values of type \&{picture}, \&{path}, and \&{pen} are displayed verbosely
 16277  in the log file only, unless the user has given a positive value to
 16278  \\{tracingonline}.
 16279  
 16280  @<Display a complex type@>=
 16281  if verbosity<=1 then print_type(t)
 16282  else  begin if selector=term_and_log then
 16283     if internal[tracing_online]<=0 then
 16284      begin selector:=term_only;
 16285      print_type(t); print(" (see the transcript file)");
 16286      selector:=term_and_log;
 16287      end;
 16288    case t of
 16289    pen_type:print_pen(v,"",false);
 16290    future_pen:print_path(v," (future pen)",false);
 16291    path_type:print_path(v,"",false);
 16292    picture_type:begin cur_edges:=v; print_edges("",false,0,0);
 16293      end;
 16294    end; {there are no other cases}
 16295    end
 16296  
 16297  @ @<Declare the procedure called |print_dp|@>=
 16298  procedure print_dp(@!t:small_number;@!p:pointer;@!verbosity:small_number);
 16299  var @!q:pointer; {the node following |p|}
 16300  begin q:=link(p);
 16301  if (info(q)=null) or (verbosity>0) then print_dependency(p,t)
 16302  else print("linearform");
 16303  @.linearform@>
 16304  end;
 16305  
 16306  @ The displayed name of a variable in a ring will not be a capsule unless
 16307  the ring consists entirely of capsules.
 16308  
 16309  @<Display a variable that's been declared but not defined@>=
 16310  begin print_type(t);
 16311  if v<>null then
 16312    begin print_char(" ");
 16313    while (name_type(v)=capsule) and (v<>p) do v:=value(v);
 16314    print_variable_name(v);
 16315    end;
 16316  end
 16317  
 16318  @ When errors are detected during parsing, it is often helpful to
 16319  display an expression just above the error message, using |exp_err|
 16320  or |disp_err| instead of |print_err|.
 16321  
 16322  @d exp_err(#)==disp_err(null,#) {displays the current expression}
 16323  
 16324  @<Declare subroutines for printing expressions@>=
 16325  procedure disp_err(@!p:pointer;@!s:str_number);
 16326  begin if interaction=error_stop_mode then wake_up_terminal;
 16327  print_nl(">> ");
 16328  @.>>@>
 16329  print_exp(p,1); {``medium verbose'' printing of the expression}
 16330  if s<>"" then
 16331    begin print_nl("! "); print(s);
 16332  @.!\relax@>
 16333    end;
 16334  end;
 16335  
 16336  @ If |cur_type| and |cur_exp| contain relevant information that should
 16337  be recycled, we will use the following procedure, which changes |cur_type|
 16338  to |known| and stores a given value in |cur_exp|. We can think of |cur_type|
 16339  and |cur_exp| as either alive or dormant after this has been done,
 16340  because |cur_exp| will not contain a pointer value.
 16341  
 16342  @<Declare the procedure called |flush_cur_exp|@>=
 16343  procedure flush_cur_exp(@!v:scaled);
 16344  begin case cur_type of
 16345  unknown_types,transform_type,pair_type,@|dependent,proto_dependent,independent:
 16346    begin recycle_value(cur_exp); free_node(cur_exp,value_node_size);
 16347    end;
 16348  pen_type: delete_pen_ref(cur_exp);
 16349  string_type:delete_str_ref(cur_exp);
 16350  future_pen,path_type: toss_knot_list(cur_exp);
 16351  picture_type:toss_edges(cur_exp);
 16352  othercases do_nothing
 16353  endcases;@/
 16354  cur_type:=known; cur_exp:=v;
 16355  end;
 16356  
 16357  @ There's a much more general procedure that is capable of releasing
 16358  the storage associated with any two-word value packet.
 16359  
 16360  @<Declare the recycling subroutines@>=
 16361  procedure recycle_value(@!p:pointer);
 16362  label done;
 16363  var @!t:small_number; {a type code}
 16364  @!v:integer; {a value}
 16365  @!vv:integer; {another value}
 16366  @!q,@!r,@!s,@!pp:pointer; {link manipulation registers}
 16367  begin t:=type(p);
 16368  if t<dependent then v:=value(p);
 16369  case t of
 16370  undefined,vacuous,boolean_type,known,numeric_type:do_nothing;
 16371  unknown_types:ring_delete(p);
 16372  string_type:delete_str_ref(v);
 16373  pen_type:delete_pen_ref(v);
 16374  path_type,future_pen:toss_knot_list(v);
 16375  picture_type:toss_edges(v);
 16376  pair_type,transform_type:@<Recycle a big node@>;
 16377  dependent,proto_dependent:@<Recycle a dependency list@>;
 16378  independent:@<Recycle an independent variable@>;
 16379  token_list,structured:confusion("recycle");
 16380  @:this can't happen recycle}{\quad recycle@>
 16381  unsuffixed_macro,suffixed_macro:delete_mac_ref(value(p));
 16382  end; {there are no other cases}
 16383  type(p):=undefined;
 16384  end;
 16385  
 16386  @ @<Recycle a big node@>=
 16387  if v<>null then
 16388    begin q:=v+big_node_size[t];
 16389    repeat q:=q-2; recycle_value(q);
 16390    until q=v;
 16391    free_node(v,big_node_size[t]);
 16392    end
 16393  
 16394  @ @<Recycle a dependency list@>=
 16395  begin q:=dep_list(p);
 16396  while info(q)<>null do q:=link(q);
 16397  link(prev_dep(p)):=link(q);
 16398  prev_dep(link(q)):=prev_dep(p);
 16399  link(q):=null; flush_node_list(dep_list(p));
 16400  end
 16401  
 16402  @ When an independent variable disappears, it simply fades away, unless
 16403  something depends on it. In the latter case, a dependent variable whose
 16404  coefficient of dependence is maximal will take its place.
 16405  The relevant algorithm is due to Ignacio~A. Zabala, who implemented it
 16406  as part of his Ph.D. thesis (Stanford University, December 1982).
 16407  @^Zabala Salelles, Ignacio Andr\'es@>
 16408  
 16409  For example, suppose that variable $x$ is being recycled, and that the
 16410  only variables depending on~$x$ are $y=2x+a$ and $z=x+b$. In this case
 16411  we want to make $y$ independent and $z=.5y-.5a+b$; no other variables
 16412  will depend on~$y$. If $\\{tracingequations}>0$ in this situation,
 16413  we will print `\.{\#\#\# -2x=-y+a}'.
 16414  
 16415  There's a slight complication, however: An independent variable $x$
 16416  can occur both in dependency lists and in proto-dependency lists.
 16417  This makes it necessary to be careful when deciding which coefficient
 16418  is maximal.
 16419  
 16420  Furthermore, this complication is not so slight when
 16421  a proto-dependent variable is chosen to become independent. For example,
 16422  suppose that $y=2x+100a$ is proto-dependent while $z=x+b$ is dependent;
 16423  then we must change $z=.5y-50a+b$ to a proto-dependency, because of the
 16424  large coefficient `50'.
 16425  
 16426  In order to deal with these complications without wasting too much time,
 16427  we shall link together the occurrences of~$x$ among all the linear
 16428  dependencies, maintaining separate lists for the dependent and
 16429  proto-dependent cases.
 16430  
 16431  @<Recycle an independent variable@>=
 16432  begin max_c[dependent]:=0; max_c[proto_dependent]:=0;@/
 16433  max_link[dependent]:=null; max_link[proto_dependent]:=null;@/
 16434  q:=link(dep_head);
 16435  while q<>dep_head do
 16436    begin s:=value_loc(q); {now |link(s)=dep_list(q)|}
 16437    loop@+  begin r:=link(s);
 16438      if info(r)=null then goto done;
 16439      if info(r)<>p then s:=r
 16440      else  begin t:=type(q); link(s):=link(r); info(r):=q;
 16441        if abs(value(r))>max_c[t] then
 16442          @<Record a new maximum coefficient of type |t|@>
 16443        else  begin link(r):=max_link[t]; max_link[t]:=r;
 16444          end;
 16445        end;
 16446      end;
 16447  done:  q:=link(r);
 16448    end;
 16449  if (max_c[dependent]>0)or(max_c[proto_dependent]>0) then
 16450    @<Choose a dependent variable to take the place of the disappearing
 16451      independent variable, and change all remaining dependencies
 16452      accordingly@>;
 16453  end
 16454  
 16455  @ The code for independency removal makes use of three two-word arrays.
 16456  
 16457  @<Glob...@>=
 16458  @!max_c:array[dependent..proto_dependent] of integer;
 16459    {max coefficient magnitude}
 16460  @!max_ptr:array[dependent..proto_dependent] of pointer;
 16461    {where |p| occurs with |max_c|}
 16462  @!max_link:array[dependent..proto_dependent] of pointer;
 16463    {other occurrences of |p|}
 16464  
 16465  @ @<Record a new maximum coefficient...@>=
 16466  begin if max_c[t]>0 then
 16467    begin link(max_ptr[t]):=max_link[t]; max_link[t]:=max_ptr[t];
 16468    end;
 16469  max_c[t]:=abs(value(r)); max_ptr[t]:=r;
 16470  end
 16471  
 16472  @ @<Choose a dependent...@>=
 16473  begin if (max_c[dependent] div @'10000 >=
 16474            max_c[proto_dependent]) then
 16475    t:=dependent
 16476  else t:=proto_dependent;
 16477  @<Determine the dependency list |s| to substitute for the independent
 16478    variable~|p|@>;
 16479  t:=dependent+proto_dependent-t; {complement |t|}
 16480  if max_c[t]>0 then {we need to pick up an unchosen dependency}
 16481    begin link(max_ptr[t]):=max_link[t]; max_link[t]:=max_ptr[t];
 16482    end;
 16483  if t<>dependent then @<Substitute new dependencies in place of |p|@>
 16484  else @<Substitute new proto-dependencies in place of |p|@>;
 16485  flush_node_list(s);
 16486  if fix_needed then fix_dependencies;
 16487  check_arith;
 16488  end
 16489  
 16490  @ Let |s=max_ptr[t]|. At this point we have $|value|(s)=\pm|max_c|[t]$,
 16491  and |info(s)| points to the dependent variable~|pp| of type~|t| from
 16492  whose dependency list we have removed node~|s|. We must reinsert
 16493  node~|s| into the dependency list, with coefficient $-1.0$, and with
 16494  |pp| as the new independent variable. Since |pp| will have a larger serial
 16495  number than any other variable, we can put node |s| at the head of the
 16496  list.
 16497  
 16498  @<Determine the dep...@>=
 16499  s:=max_ptr[t]; pp:=info(s); v:=value(s);
 16500  if t=dependent then value(s):=-fraction_one@+else value(s):=-unity;
 16501  r:=dep_list(pp); link(s):=r;
 16502  while info(r)<>null do r:=link(r);
 16503  q:=link(r); link(r):=null;
 16504  prev_dep(q):=prev_dep(pp); link(prev_dep(pp)):=q;
 16505  new_indep(pp);
 16506  if cur_exp=pp then if cur_type=t then cur_type:=independent;
 16507  if internal[tracing_equations]>0 then @<Show the transformed dependency@>
 16508  
 16509  @ Now $(-v)$ times the formerly independent variable~|p| is being replaced
 16510  by the dependency list~|s|.
 16511  
 16512  @<Show the transformed...@>=
 16513  if interesting(p) then
 16514    begin begin_diagnostic; print_nl("### ");
 16515  @:]]]\#\#\#_}{\.{\#\#\#}@>
 16516    if v>0 then print_char("-");
 16517    if t=dependent then vv:=round_fraction(max_c[dependent])
 16518    else vv:=max_c[proto_dependent];
 16519    if vv<>unity then print_scaled(vv);
 16520    print_variable_name(p);
 16521    while value(p) mod s_scale>0 do
 16522      begin print("*4"); value(p):=value(p)-2;
 16523      end;
 16524    if t=dependent then print_char("=")@+else print(" = ");
 16525    print_dependency(s,t);
 16526    end_diagnostic(false);
 16527    end
 16528  
 16529  @ Finally, there are dependent and proto-dependent variables whose
 16530  dependency lists must be brought up to date.
 16531  
 16532  @<Substitute new dependencies...@>=
 16533  for t:=dependent to proto_dependent do
 16534    begin r:=max_link[t];
 16535    while r<>null do
 16536      begin q:=info(r);
 16537      dep_list(q):=p_plus_fq(dep_list(q),@|
 16538       make_fraction(value(r),-v),s,t,dependent);
 16539      if dep_list(q)=dep_final then make_known(q,dep_final);
 16540      q:=r; r:=link(r); free_node(q,dep_node_size);
 16541      end;
 16542    end
 16543  
 16544  @ @<Substitute new proto...@>=
 16545  for t:=dependent to proto_dependent do
 16546    begin r:=max_link[t];
 16547    while r<>null do
 16548      begin q:=info(r);
 16549      if t=dependent then {for safety's sake, we change |q| to |proto_dependent|}
 16550        begin if cur_exp=q then if cur_type=dependent then
 16551          cur_type:=proto_dependent;
 16552        dep_list(q):=p_over_v(dep_list(q),unity,dependent,proto_dependent);
 16553        type(q):=proto_dependent; value(r):=round_fraction(value(r));
 16554        end;
 16555      dep_list(q):=p_plus_fq(dep_list(q),@|
 16556       make_scaled(value(r),-v),s,proto_dependent,proto_dependent);
 16557      if dep_list(q)=dep_final then make_known(q,dep_final);
 16558      q:=r; r:=link(r); free_node(q,dep_node_size);
 16559      end;
 16560    end
 16561  
 16562  @ Here are some routines that provide handy combinations of actions
 16563  that are often needed during error recovery. For example,
 16564  `|flush_error|' flushes the current expression, replaces it by
 16565  a given value, and calls |error|.
 16566  
 16567  Errors often are detected after an extra token has already been scanned.
 16568  The `\\{put\_get}' routines put that token back before calling |error|;
 16569  then they get it back again. (Or perhaps they get another token, if
 16570  the user has changed things.)
 16571  
 16572  @<Declare the procedure called |flush_cur_exp|@>=
 16573  procedure flush_error(@!v:scaled);@+begin error; flush_cur_exp(v);@+end;
 16574  @#
 16575  procedure@?back_error; forward;@t\2@>@/
 16576  procedure@?get_x_next; forward;@t\2@>@/
 16577  @#
 16578  procedure put_get_error;@+begin back_error; get_x_next;@+end;
 16579  @#
 16580  procedure put_get_flush_error(@!v:scaled);@+begin put_get_error;
 16581   flush_cur_exp(v);@+end;
 16582  
 16583  @ A global variable called |var_flag| is set to a special command code
 16584  just before \MF\ calls |scan_expression|, if the expression should be
 16585  treated as a variable when this command code immediately follows. For
 16586  example, |var_flag| is set to |assignment| at the beginning of a
 16587  statement, because we want to know the {\sl location\/} of a variable at
 16588  the left of `\.{:=}', not the {\sl value\/} of that variable.
 16589  
 16590  The |scan_expression| subroutine calls |scan_tertiary|,
 16591  which calls |scan_secondary|, which calls |scan_primary|, which sets
 16592  |var_flag:=0|. In this way each of the scanning routines ``knows''
 16593  when it has been called with a special |var_flag|, but |var_flag| is
 16594  usually zero.
 16595  
 16596  A variable preceding a command that equals |var_flag| is converted to a
 16597  token list rather than a value. Furthermore, an `\.{=}' sign following an
 16598  expression with |var_flag=assignment| is not considered to be a relation
 16599  that produces boolean expressions.
 16600  
 16601  
 16602  @<Glob...@>=
 16603  @!var_flag:0..max_command_code; {command that wants a variable}
 16604  
 16605  @ @<Set init...@>=
 16606  var_flag:=0;
 16607  
 16608  @* \[40] Parsing primary expressions.
 16609  The first parsing routine, |scan_primary|, is also the most complicated one,
 16610  since it involves so many different cases. But each case---with one
 16611  exception---is fairly simple by itself.
 16612  
 16613  When |scan_primary| begins, the first token of the primary to be scanned
 16614  should already appear in |cur_cmd|, |cur_mod|, and |cur_sym|. The values
 16615  of |cur_type| and |cur_exp| should be either dead or dormant, as explained
 16616  earlier. If |cur_cmd| is not between |min_primary_command| and
 16617  |max_primary_command|, inclusive, a syntax error will be signalled.
 16618  
 16619  @<Declare the basic parsing subroutines@>=
 16620  procedure scan_primary;
 16621  label restart, done, done1, done2;
 16622  var @!p,@!q,@!r:pointer; {for list manipulation}
 16623  @!c:quarterword; {a primitive operation code}
 16624  @!my_var_flag:0..max_command_code; {initial value of |var_flag|}
 16625  @!l_delim,@!r_delim:pointer; {hash addresses of a delimiter pair}
 16626  @<Other local variables for |scan_primary|@>@;
 16627  begin my_var_flag:=var_flag; var_flag:=0;
 16628  restart:check_arith;
 16629  @<Supply diagnostic information, if requested@>;
 16630  case cur_cmd of
 16631  left_delimiter:@<Scan a delimited primary@>;
 16632  begin_group:@<Scan a grouped primary@>;
 16633  string_token:@<Scan a string constant@>;
 16634  numeric_token:@<Scan a primary that starts with a numeric token@>;
 16635  nullary:@<Scan a nullary operation@>;
 16636  unary,type_name,cycle,plus_or_minus:@<Scan a unary operation@>;
 16637  primary_binary:@<Scan a binary operation with `\&{of}' between its operands@>;
 16638  str_op:@<Convert a suffix to a string@>;
 16639  internal_quantity:@<Scan an internal numeric quantity@>;
 16640  capsule_token:make_exp_copy(cur_mod);
 16641  tag_token:@<Scan a variable primary;
 16642    |goto restart| if it turns out to be a macro@>;
 16643  othercases begin bad_exp("A primary"); goto restart;
 16644  @.A primary expression...@>
 16645    end
 16646  endcases;@/
 16647  get_x_next; {the routines |goto done| if they don't want this}
 16648  done: if cur_cmd=left_bracket then
 16649    if cur_type>=known then @<Scan a mediation construction@>;
 16650  end;
 16651  
 16652  @ Errors at the beginning of expressions are flagged by |bad_exp|.
 16653  
 16654  @p procedure bad_exp(@!s:str_number);
 16655  var save_flag:0..max_command_code;
 16656  begin print_err(s); print(" expression can't begin with `");
 16657  print_cmd_mod(cur_cmd,cur_mod); print_char("'");
 16658  help4("I'm afraid I need some sort of value in order to continue,")@/
 16659    ("so I've tentatively inserted `0'. You may want to")@/
 16660    ("delete this zero and insert something else;")@/
 16661    ("see Chapter 27 of The METAFONTbook for an example.");
 16662  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 16663  back_input; cur_sym:=0; cur_cmd:=numeric_token; cur_mod:=0; ins_error;@/
 16664  save_flag:=var_flag; var_flag:=0; get_x_next;
 16665  var_flag:=save_flag;
 16666  end;
 16667  
 16668  @ @<Supply diagnostic information, if requested@>=
 16669  debug if panicking then check_mem(false);@+gubed@;@/
 16670  if interrupt<>0 then if OK_to_interrupt then
 16671    begin back_input; check_interrupt; get_x_next;
 16672    end
 16673  
 16674  @ @<Scan a delimited primary@>=
 16675  begin l_delim:=cur_sym; r_delim:=cur_mod; get_x_next; scan_expression;
 16676  if (cur_cmd=comma) and (cur_type>=known) then
 16677    @<Scan the second of a pair of numerics@>
 16678  else check_delimiter(l_delim,r_delim);
 16679  end
 16680  
 16681  @ The |stash_in| subroutine puts the current (numeric) expression into a field
 16682  within a ``big node.''
 16683  
 16684  @p procedure stash_in(@!p:pointer);
 16685  var @!q:pointer; {temporary register}
 16686  begin type(p):=cur_type;
 16687  if cur_type=known then value(p):=cur_exp
 16688  else  begin if cur_type=independent then
 16689      @<Stash an independent |cur_exp| into a big node@>
 16690    else  begin mem[value_loc(p)]:=mem[value_loc(cur_exp)];
 16691       {|dep_list(p):=dep_list(cur_exp)| and |prev_dep(p):=prev_dep(cur_exp)|}
 16692      link(prev_dep(p)):=p;
 16693      end;
 16694    free_node(cur_exp,value_node_size);
 16695    end;
 16696  cur_type:=vacuous;
 16697  end;
 16698  
 16699  @ In rare cases the current expression can become |independent|. There
 16700  may be many dependency lists pointing to such an independent capsule,
 16701  so we can't simply move it into place within a big node. Instead,
 16702  we copy it, then recycle it.
 16703  
 16704  @ @<Stash an independent |cur_exp|...@>=
 16705  begin q:=single_dependency(cur_exp);
 16706  if q=dep_final then
 16707    begin type(p):=known; value(p):=0; free_node(q,dep_node_size);
 16708    end
 16709  else  begin type(p):=dependent; new_dep(p,q);
 16710    end;
 16711  recycle_value(cur_exp);
 16712  end
 16713  
 16714  @ @<Scan the second of a pair of numerics@>=
 16715  begin p:=get_node(value_node_size); type(p):=pair_type; name_type(p):=capsule;
 16716  init_big_node(p); q:=value(p); stash_in(x_part_loc(q));@/
 16717  get_x_next; scan_expression;
 16718  if cur_type<known then
 16719    begin exp_err("Nonnumeric ypart has been replaced by 0");
 16720  @.Nonnumeric...replaced by 0@>
 16721    help4("I thought you were giving me a pair `(x,y)'; but")@/
 16722      ("after finding a nice xpart `x' I found a ypart `y'")@/
 16723      ("that isn't of numeric type. So I've changed y to zero.")@/
 16724      ("(The y that I didn't like appears above the error message.)");
 16725    put_get_flush_error(0);
 16726    end;
 16727  stash_in(y_part_loc(q));
 16728  check_delimiter(l_delim,r_delim);
 16729  cur_type:=pair_type; cur_exp:=p;
 16730  end
 16731  
 16732  @ The local variable |group_line| keeps track of the line
 16733  where a \&{begingroup} command occurred; this will be useful
 16734  in an error message if the group doesn't actually end.
 16735  
 16736  @<Other local variables for |scan_primary|@>=
 16737  @!group_line:integer; {where a group began}
 16738  
 16739  @ @<Scan a grouped primary@>=
 16740  begin group_line:=line;
 16741  if internal[tracing_commands]>0 then show_cur_cmd_mod;
 16742  save_boundary_item(p);
 16743  repeat do_statement; {ends with |cur_cmd>=semicolon|}
 16744  until cur_cmd<>semicolon;
 16745  if cur_cmd<>end_group then
 16746    begin print_err("A group begun on line ");
 16747  @.A group...never ended@>
 16748    print_int(group_line);
 16749    print(" never ended");
 16750    help2("I saw a `begingroup' back there that hasn't been matched")@/
 16751      ("by `endgroup'. So I've inserted `endgroup' now.");
 16752    back_error; cur_cmd:=end_group;
 16753    end;
 16754  unsave; {this might change |cur_type|, if independent variables are recycled}
 16755  if internal[tracing_commands]>0 then show_cur_cmd_mod;
 16756  end
 16757  
 16758  @ @<Scan a string constant@>=
 16759  begin cur_type:=string_type; cur_exp:=cur_mod;
 16760  end
 16761  
 16762  @ Later we'll come to procedures that perform actual operations like
 16763  addition, square root, and so on; our purpose now is to do the parsing.
 16764  But we might as well mention those future procedures now, so that the
 16765  suspense won't be too bad:
 16766  
 16767  \smallskip
 16768  |do_nullary(c)| does primitive operations that have no operands (e.g.,
 16769  `\&{true}' or `\&{pencircle}');
 16770  
 16771  \smallskip
 16772  |do_unary(c)| applies a primitive operation to the current expression;
 16773  
 16774  \smallskip
 16775  |do_binary(p,c)| applies a primitive operation to the capsule~|p|
 16776  and the current expression.
 16777  
 16778  @<Scan a nullary operation@>=do_nullary(cur_mod)
 16779  
 16780  @ @<Scan a unary operation@>=
 16781  begin c:=cur_mod; get_x_next; scan_primary; do_unary(c); goto done;
 16782  end
 16783  
 16784  @ A numeric token might be a primary by itself, or it might be the
 16785  numerator of a fraction composed solely of numeric tokens, or it might
 16786  multiply the primary that follows (provided that the primary doesn't begin
 16787  with a plus sign or a minus sign). The code here uses the facts that
 16788  |max_primary_command=plus_or_minus| and
 16789  |max_primary_command-1=numeric_token|. If a fraction is found that is less
 16790  than unity, we try to retain higher precision when we use it in scalar
 16791  multiplication.
 16792  
 16793  @<Other local variables for |scan_primary|@>=
 16794  @!num,@!denom:scaled; {for primaries that are fractions, like `1/2'}
 16795  
 16796  @ @<Scan a primary that starts with a numeric token@>=
 16797  begin cur_exp:=cur_mod; cur_type:=known; get_x_next;
 16798  if cur_cmd<>slash then
 16799    begin num:=0; denom:=0;
 16800    end
 16801  else  begin get_x_next;
 16802    if cur_cmd<>numeric_token then
 16803      begin back_input;
 16804      cur_cmd:=slash; cur_mod:=over; cur_sym:=frozen_slash;
 16805      goto done;
 16806      end;
 16807    num:=cur_exp; denom:=cur_mod;
 16808    if denom=0 then @<Protest division by zero@>
 16809    else cur_exp:=make_scaled(num,denom);
 16810    check_arith; get_x_next;
 16811    end;
 16812  if cur_cmd>=min_primary_command then
 16813   if cur_cmd<numeric_token then {in particular, |cur_cmd<>plus_or_minus|}
 16814    begin p:=stash_cur_exp; scan_primary;
 16815    if (abs(num)>=abs(denom))or(cur_type<pair_type) then do_binary(p,times)
 16816    else  begin frac_mult(num,denom);
 16817      free_node(p,value_node_size);
 16818      end;
 16819    end;
 16820  goto done;
 16821  end
 16822  
 16823  @ @<Protest division...@>=
 16824  begin print_err("Division by zero");
 16825  @.Division by zero@>
 16826  help1("I'll pretend that you meant to divide by 1."); error;
 16827  end
 16828  
 16829  @ @<Scan a binary operation with `\&{of}' between its operands@>=
 16830  begin c:=cur_mod; get_x_next; scan_expression;
 16831  if cur_cmd<>of_token then
 16832    begin missing_err("of"); print(" for "); print_cmd_mod(primary_binary,c);
 16833  @.Missing `of'@>
 16834    help1("I've got the first argument; will look now for the other.");
 16835    back_error;
 16836    end;
 16837  p:=stash_cur_exp; get_x_next; scan_primary; do_binary(p,c); goto done;
 16838  end
 16839  
 16840  @ @<Convert a suffix to a string@>=
 16841  begin get_x_next; scan_suffix; old_setting:=selector; selector:=new_string;
 16842  show_token_list(cur_exp,null,100000,0); flush_token_list(cur_exp);
 16843  cur_exp:=make_string; selector:=old_setting; cur_type:=string_type;
 16844  goto done;
 16845  end
 16846  
 16847  @ If an internal quantity appears all by itself on the left of an
 16848  assignment, we return a token list of length one, containing the address
 16849  of the internal quantity plus |hash_end|. (This accords with the conventions
 16850  of the save stack, as described earlier.)
 16851  
 16852  @<Scan an internal...@>=
 16853  begin q:=cur_mod;
 16854  if my_var_flag=assignment then
 16855    begin get_x_next;
 16856    if cur_cmd=assignment then
 16857      begin cur_exp:=get_avail;
 16858      info(cur_exp):=q+hash_end; cur_type:=token_list; goto done;
 16859      end;
 16860    back_input;
 16861    end;
 16862  cur_type:=known; cur_exp:=internal[q];
 16863  end
 16864  
 16865  @ The most difficult part of |scan_primary| has been saved for last, since
 16866  it was necessary to build up some confidence first. We can now face the task
 16867  of scanning a variable.
 16868  
 16869  As we scan a variable, we build a token list containing the relevant
 16870  names and subscript values, simultaneously following along in the
 16871  ``collective'' structure to see if we are actually dealing with a macro
 16872  instead of a value.
 16873  
 16874  The local variables |pre_head| and |post_head| will point to the beginning
 16875  of the prefix and suffix lists; |tail| will point to the end of the list
 16876  that is currently growing.
 16877  
 16878  Another local variable, |tt|, contains partial information about the
 16879  declared type of the variable-so-far. If |tt>=unsuffixed_macro|, the
 16880  relation |tt=type(q)| will always hold. If |tt=undefined|, the routine
 16881  doesn't bother to update its information about type. And if
 16882  |undefined<tt<unsuffixed_macro|, the precise value of |tt| isn't critical.
 16883  
 16884  @ @<Other local variables for |scan_primary|@>=
 16885  @!pre_head,@!post_head,@!tail:pointer;
 16886    {prefix and suffix list variables}
 16887  @!tt:small_number; {approximation to the type of the variable-so-far}
 16888  @!t:pointer; {a token}
 16889  @!macro_ref:pointer; {reference count for a suffixed macro}
 16890  
 16891  @ @<Scan a variable primary...@>=
 16892  begin fast_get_avail(pre_head); tail:=pre_head; post_head:=null; tt:=vacuous;
 16893  loop@+  begin t:=cur_tok; link(tail):=t;
 16894    if tt<>undefined then
 16895      begin @<Find the approximate type |tt| and corresponding~|q|@>;
 16896      if tt>=unsuffixed_macro then
 16897        @<Either begin an unsuffixed macro call or
 16898          prepare for a suffixed one@>;
 16899      end;
 16900    get_x_next; tail:=t;
 16901    if cur_cmd=left_bracket then
 16902      @<Scan for a subscript; replace |cur_cmd| by |numeric_token| if found@>;
 16903    if cur_cmd>max_suffix_token then goto done1;
 16904    if cur_cmd<min_suffix_token then goto done1;
 16905    end; {now |cur_cmd| is |internal_quantity|, |tag_token|, or |numeric_token|}
 16906  done1:@<Handle unusual cases that masquerade as variables, and |goto restart|
 16907    or |goto done| if appropriate;
 16908    otherwise make a copy of the variable and |goto done|@>;
 16909  end
 16910  
 16911  @ @<Either begin an unsuffixed macro call or...@>=
 16912  begin link(tail):=null;
 16913  if tt>unsuffixed_macro then {|tt=suffixed_macro|}
 16914    begin post_head:=get_avail; tail:=post_head; link(tail):=t;@/
 16915    tt:=undefined; macro_ref:=value(q); add_mac_ref(macro_ref);
 16916    end
 16917  else @<Set up unsuffixed macro call and |goto restart|@>;
 16918  end
 16919  
 16920  @ @<Scan for a subscript; replace |cur_cmd| by |numeric_token| if found@>=
 16921  begin get_x_next; scan_expression;
 16922  if cur_cmd<>right_bracket then
 16923    @<Put the left bracket and the expression back to be rescanned@>
 16924  else  begin if cur_type<>known then bad_subscript;
 16925    cur_cmd:=numeric_token; cur_mod:=cur_exp; cur_sym:=0;
 16926    end;
 16927  end
 16928  
 16929  @ The left bracket that we thought was introducing a subscript might have
 16930  actually been the left bracket in a mediation construction like `\.{x[a,b]}'.
 16931  So we don't issue an error message at this point; but we do want to back up
 16932  so as to avoid any embarrassment about our incorrect assumption.
 16933  
 16934  @<Put the left bracket and the expression back to be rescanned@>=
 16935  begin back_input; {that was the token following the current expression}
 16936  back_expr; cur_cmd:=left_bracket; cur_mod:=0; cur_sym:=frozen_left_bracket;
 16937  end
 16938  
 16939  @ Here's a routine that puts the current expression back to be read again.
 16940  
 16941  @p procedure back_expr;
 16942  var @!p:pointer; {capsule token}
 16943  begin p:=stash_cur_exp; link(p):=null; back_list(p);
 16944  end;
 16945  
 16946  @ Unknown subscripts lead to the following error message.
 16947  
 16948  @p procedure bad_subscript;
 16949  begin exp_err("Improper subscript has been replaced by zero");
 16950  @.Improper subscript...@>
 16951  help3("A bracketed subscript must have a known numeric value;")@/
 16952    ("unfortunately, what I found was the value that appears just")@/
 16953    ("above this error message. So I'll try a zero subscript.");
 16954  flush_error(0);
 16955  end;
 16956  
 16957  @ Every time we call |get_x_next|, there's a chance that the variable we've
 16958  been looking at will disappear. Thus, we cannot safely keep |q| pointing
 16959  into the variable structure; we need to start searching from the root each time.
 16960  
 16961  @<Find the approximate type |tt| and corresponding~|q|@>=
 16962  @^inner loop@>
 16963  begin p:=link(pre_head); q:=info(p); tt:=undefined;
 16964  if eq_type(q) mod outer_tag=tag_token then
 16965    begin q:=equiv(q);
 16966    if q=null then goto done2;
 16967    loop@+  begin p:=link(p);
 16968      if p=null then
 16969        begin tt:=type(q); goto done2;
 16970        end;
 16971      if type(q)<>structured then goto done2;
 16972      q:=link(attr_head(q)); {the |collective_subscript| attribute}
 16973      if p>=hi_mem_min then {it's not a subscript}
 16974        begin repeat q:=link(q);
 16975        until attr_loc(q)>=info(p);
 16976        if attr_loc(q)>info(p) then goto done2;
 16977        end;
 16978      end;
 16979    end;
 16980  done2:end
 16981  
 16982  @ How do things stand now? Well, we have scanned an entire variable name,
 16983  including possible subscripts and/or attributes; |cur_cmd|, |cur_mod|, and
 16984  |cur_sym| represent the token that follows. If |post_head=null|, a
 16985  token list for this variable name starts at |link(pre_head)|, with all
 16986  subscripts evaluated. But if |post_head<>null|, the variable turned out
 16987  to be a suffixed macro; |pre_head| is the head of the prefix list, while
 16988  |post_head| is the head of a token list containing both `\.{\AT!}' and
 16989  the suffix.
 16990  
 16991  Our immediate problem is to see if this variable still exists. (Variable
 16992  structures can change drastically whenever we call |get_x_next|; users
 16993  aren't supposed to do this, but the fact that it is possible means that
 16994  we must be cautious.)
 16995  
 16996  The following procedure prints an error message when a variable
 16997  unexpectedly disappears. Its help message isn't quite right for
 16998  our present purposes, but we'll be able to fix that up.
 16999  
 17000  @p procedure obliterated(@!q:pointer);
 17001  begin print_err("Variable "); show_token_list(q,null,1000,0);
 17002  print(" has been obliterated");
 17003  @.Variable...obliterated@>
 17004  help5("It seems you did a nasty thing---probably by accident,")@/
 17005    ("but nevertheless you nearly hornswoggled me...")@/
 17006    ("While I was evaluating the right-hand side of this")@/
 17007    ("command, something happened, and the left-hand side")@/
 17008    ("is no longer a variable! So I won't change anything.");
 17009  end;
 17010  
 17011  @ If the variable does exist, we also need to check
 17012  for a few other special cases before deciding that a plain old ordinary
 17013  variable has, indeed, been scanned.
 17014  
 17015  @<Handle unusual cases that masquerade as variables...@>=
 17016  if post_head<>null then @<Set up suffixed macro call and |goto restart|@>;
 17017  q:=link(pre_head); free_avail(pre_head);
 17018  if cur_cmd=my_var_flag then
 17019    begin cur_type:=token_list; cur_exp:=q; goto done;
 17020    end;
 17021  p:=find_variable(q);
 17022  if p<>null then make_exp_copy(p)
 17023  else  begin obliterated(q);@/
 17024    help_line[2]:="While I was evaluating the suffix of this variable,";
 17025    help_line[1]:="something was redefined, and it's no longer a variable!";
 17026    help_line[0]:="In order to get back on my feet, I've inserted `0' instead.";
 17027    put_get_flush_error(0);
 17028    end;
 17029  flush_node_list(q); goto done
 17030  
 17031  @ The only complication associated with macro calling is that the prefix
 17032  and ``at'' parameters must be packaged in an appropriate list of lists.
 17033  
 17034  @<Set up unsuffixed macro call and |goto restart|@>=
 17035  begin p:=get_avail; info(pre_head):=link(pre_head); link(pre_head):=p;
 17036  info(p):=t; macro_call(value(q),pre_head,null); get_x_next; goto restart;
 17037  end
 17038  
 17039  @ If the ``variable'' that turned out to be a suffixed macro no longer exists,
 17040  we don't care, because we have reserved a pointer (|macro_ref|) to its
 17041  token list.
 17042  
 17043  @<Set up suffixed macro call and |goto restart|@>=
 17044  begin back_input; p:=get_avail; q:=link(post_head);
 17045  info(pre_head):=link(pre_head); link(pre_head):=post_head;
 17046  info(post_head):=q; link(post_head):=p; info(p):=link(q); link(q):=null;
 17047  macro_call(macro_ref,pre_head,null); decr(ref_count(macro_ref));
 17048  get_x_next; goto restart;
 17049  end
 17050  
 17051  @ Our remaining job is simply to make a copy of the value that has been
 17052  found. Some cases are harder than others, but complexity arises solely
 17053  because of the multiplicity of possible cases.
 17054  
 17055  @<Declare the procedure called |make_exp_copy|@>=
 17056  @t\4@>@<Declare subroutines needed by |make_exp_copy|@>@;
 17057  procedure make_exp_copy(@!p:pointer);
 17058  label restart;
 17059  var @!q,@!r,@!t:pointer; {registers for list manipulation}
 17060  begin restart: cur_type:=type(p);
 17061  case cur_type of
 17062  vacuous,boolean_type,known:cur_exp:=value(p);
 17063  unknown_types:cur_exp:=new_ring_entry(p);
 17064  string_type:begin cur_exp:=value(p); add_str_ref(cur_exp);
 17065    end;
 17066  pen_type:begin cur_exp:=value(p); add_pen_ref(cur_exp);
 17067    end;
 17068  picture_type:cur_exp:=copy_edges(value(p));
 17069  path_type,future_pen:cur_exp:=copy_path(value(p));
 17070  transform_type,pair_type:@<Copy the big node |p|@>;
 17071  dependent,proto_dependent:encapsulate(copy_dep_list(dep_list(p)));
 17072  numeric_type:begin new_indep(p); goto restart;
 17073    end;
 17074  independent: begin q:=single_dependency(p);
 17075    if q=dep_final then
 17076      begin cur_type:=known; cur_exp:=0; free_node(q,dep_node_size);
 17077      end
 17078    else  begin cur_type:=dependent; encapsulate(q);
 17079      end;
 17080    end;
 17081  othercases confusion("copy")
 17082  @:this can't happen copy}{\quad copy@>
 17083  endcases;
 17084  end;
 17085  
 17086  @ The |encapsulate| subroutine assumes that |dep_final| is the
 17087  tail of dependency list~|p|.
 17088  
 17089  @<Declare subroutines needed by |make_exp_copy|@>=
 17090  procedure encapsulate(@!p:pointer);
 17091  begin cur_exp:=get_node(value_node_size); type(cur_exp):=cur_type;
 17092  name_type(cur_exp):=capsule; new_dep(cur_exp,p);
 17093  end;
 17094  
 17095  @ The most tedious case arises when the user refers to a
 17096  \&{pair} or \&{transform} variable; we must copy several fields,
 17097  each of which can be |independent|, |dependent|, |proto_dependent|,
 17098  or |known|.
 17099  
 17100  @<Copy the big node |p|@>=
 17101  begin if value(p)=null then init_big_node(p);
 17102  t:=get_node(value_node_size); name_type(t):=capsule; type(t):=cur_type;
 17103  init_big_node(t);@/
 17104  q:=value(p)+big_node_size[cur_type]; r:=value(t)+big_node_size[cur_type];
 17105  repeat q:=q-2; r:=r-2; install(r,q);
 17106  until q=value(p);
 17107  cur_exp:=t;
 17108  end
 17109  
 17110  @ The |install| procedure copies a numeric field~|q| into field~|r| of
 17111  a big node that will be part of a capsule.
 17112  
 17113  @<Declare subroutines needed by |make_exp_copy|@>=
 17114  procedure install(@!r,@!q:pointer);
 17115  var p:pointer; {temporary register}
 17116  begin if type(q)=known then
 17117    begin value(r):=value(q); type(r):=known;
 17118    end
 17119  else  if type(q)=independent then
 17120      begin p:=single_dependency(q);
 17121      if p=dep_final then
 17122        begin type(r):=known; value(r):=0; free_node(p,dep_node_size);
 17123        end
 17124      else  begin type(r):=dependent; new_dep(r,p);
 17125        end;
 17126      end
 17127    else  begin type(r):=type(q); new_dep(r,copy_dep_list(dep_list(q)));
 17128      end;
 17129  end;
 17130  
 17131  @ Expressions of the form `\.{a[b,c]}' are converted into
 17132  `\.{b+a*(c-b)}', without checking the types of \.b~or~\.c,
 17133  provided that \.a is numeric.
 17134  
 17135  @<Scan a mediation...@>=
 17136  begin p:=stash_cur_exp; get_x_next; scan_expression;
 17137  if cur_cmd<>comma then
 17138    begin @<Put the left bracket and the expression back...@>;
 17139    unstash_cur_exp(p);
 17140    end
 17141  else  begin q:=stash_cur_exp; get_x_next; scan_expression;
 17142    if cur_cmd<>right_bracket then
 17143      begin missing_err("]");@/
 17144  @.Missing `]'@>
 17145      help3("I've scanned an expression of the form `a[b,c',")@/
 17146        ("so a right bracket should have come next.")@/
 17147        ("I shall pretend that one was there.");@/
 17148      back_error;
 17149      end;
 17150    r:=stash_cur_exp; make_exp_copy(q);@/
 17151    do_binary(r,minus); do_binary(p,times); do_binary(q,plus); get_x_next;
 17152    end;
 17153  end
 17154  
 17155  @ Here is a comparatively simple routine that is used to scan the
 17156  \&{suffix} parameters of a macro.
 17157  
 17158  @<Declare the basic parsing subroutines@>=
 17159  procedure scan_suffix;
 17160  label done;
 17161  var @!h,@!t:pointer; {head and tail of the list being built}
 17162  @!p:pointer; {temporary register}
 17163  begin h:=get_avail; t:=h;
 17164  loop@+  begin if cur_cmd=left_bracket then
 17165      @<Scan a bracketed subscript and set |cur_cmd:=numeric_token|@>;
 17166    if cur_cmd=numeric_token then p:=new_num_tok(cur_mod)
 17167    else if (cur_cmd=tag_token)or(cur_cmd=internal_quantity) then
 17168      begin p:=get_avail; info(p):=cur_sym;
 17169      end
 17170    else goto done;
 17171    link(t):=p; t:=p; get_x_next;
 17172    end;
 17173  done: cur_exp:=link(h); free_avail(h); cur_type:=token_list;
 17174  end;
 17175  
 17176  @ @<Scan a bracketed subscript and set |cur_cmd:=numeric_token|@>=
 17177  begin get_x_next; scan_expression;
 17178  if cur_type<>known then bad_subscript;
 17179  if cur_cmd<>right_bracket then
 17180    begin missing_err("]");@/
 17181  @.Missing `]'@>
 17182    help3("I've seen a `[' and a subscript value, in a suffix,")@/
 17183      ("so a right bracket should have come next.")@/
 17184      ("I shall pretend that one was there.");@/
 17185    back_error;
 17186    end;
 17187  cur_cmd:=numeric_token; cur_mod:=cur_exp;
 17188  end
 17189  
 17190  @* \[41] Parsing secondary and higher expressions.
 17191  After the intricacies of |scan_primary|\kern-1pt,
 17192  the |scan_secondary| routine is
 17193  refreshingly simple. It's not trivial, but the operations are relatively
 17194  straightforward; the main difficulty is, again, that expressions and data
 17195  structures might change drastically every time we call |get_x_next|, so a
 17196  cautious approach is mandatory. For example, a macro defined by
 17197  \&{primarydef} might have disappeared by the time its second argument has
 17198  been scanned; we solve this by increasing the reference count of its token
 17199  list, so that the macro can be called even after it has been clobbered.
 17200  
 17201  @<Declare the basic parsing subroutines@>=
 17202  procedure scan_secondary;
 17203  label restart,continue;
 17204  var @!p:pointer; {for list manipulation}
 17205  @!c,@!d:halfword; {operation codes or modifiers}
 17206  @!mac_name:pointer; {token defined with \&{primarydef}}
 17207  begin restart:if(cur_cmd<min_primary_command)or@|
 17208   (cur_cmd>max_primary_command) then
 17209    bad_exp("A secondary");
 17210  @.A secondary expression...@>
 17211  scan_primary;
 17212  continue: if cur_cmd<=max_secondary_command then
 17213   if cur_cmd>=min_secondary_command then
 17214    begin p:=stash_cur_exp; c:=cur_mod; d:=cur_cmd;
 17215    if d=secondary_primary_macro then
 17216      begin mac_name:=cur_sym; add_mac_ref(c);
 17217      end;
 17218    get_x_next; scan_primary;
 17219    if d<>secondary_primary_macro then do_binary(p,c)
 17220    else  begin back_input; binary_mac(p,c,mac_name);
 17221      decr(ref_count(c)); get_x_next; goto restart;
 17222      end;
 17223    goto continue;
 17224    end;
 17225  end;
 17226  
 17227  @ The following procedure calls a macro that has two parameters,
 17228  |p| and |cur_exp|.
 17229  
 17230  @p procedure binary_mac(@!p,@!c,@!n:pointer);
 17231  var @!q,@!r:pointer; {nodes in the parameter list}
 17232  begin q:=get_avail; r:=get_avail; link(q):=r;@/
 17233  info(q):=p; info(r):=stash_cur_exp;@/
 17234  macro_call(c,q,n);
 17235  end;
 17236  
 17237  @ The next procedure, |scan_tertiary|, is pretty much the same deal.
 17238  
 17239  @<Declare the basic parsing subroutines@>=
 17240  procedure scan_tertiary;
 17241  label restart,continue;
 17242  var @!p:pointer; {for list manipulation}
 17243  @!c,@!d:halfword; {operation codes or modifiers}
 17244  @!mac_name:pointer; {token defined with \&{secondarydef}}
 17245  begin restart:if(cur_cmd<min_primary_command)or@|
 17246   (cur_cmd>max_primary_command) then
 17247    bad_exp("A tertiary");
 17248  @.A tertiary expression...@>
 17249  scan_secondary;
 17250  if cur_type=future_pen then materialize_pen;
 17251  continue: if cur_cmd<=max_tertiary_command then
 17252   if cur_cmd>=min_tertiary_command then
 17253    begin p:=stash_cur_exp; c:=cur_mod; d:=cur_cmd;
 17254    if d=tertiary_secondary_macro then
 17255      begin mac_name:=cur_sym; add_mac_ref(c);
 17256      end;
 17257    get_x_next; scan_secondary;
 17258    if d<>tertiary_secondary_macro then do_binary(p,c)
 17259    else  begin back_input; binary_mac(p,c,mac_name);
 17260      decr(ref_count(c)); get_x_next; goto restart;
 17261      end;
 17262    goto continue;
 17263    end;
 17264  end;
 17265  
 17266  @ A |future_pen| becomes a full-fledged pen here.
 17267  
 17268  @p procedure materialize_pen;
 17269  label common_ending;
 17270  var @!a_minus_b,@!a_plus_b,@!major_axis,@!minor_axis:scaled; {ellipse variables}
 17271  @!theta:angle; {amount by which the ellipse has been rotated}
 17272  @!p:pointer; {path traverser}
 17273  @!q:pointer; {the knot list to be made into a pen}
 17274  begin q:=cur_exp;
 17275  if left_type(q)=endpoint then
 17276    begin print_err("Pen path must be a cycle");
 17277  @.Pen path must be a cycle@>
 17278    help2("I can't make a pen from the given path.")@/
 17279    ("So I've replaced it by the trivial path `(0,0)..cycle'.");
 17280    put_get_error; cur_exp:=null_pen; goto common_ending;
 17281    end
 17282  else if left_type(q)=open then
 17283    @<Change node |q| to a path for an elliptical pen@>;
 17284  cur_exp:=make_pen(q);
 17285  common_ending: toss_knot_list(q); cur_type:=pen_type;
 17286  end;
 17287  
 17288  @ We placed the three points $(0,0)$, $(1,0)$, $(0,1)$ into a \&{pencircle},
 17289  and they have now been transformed to $(u,v)$, $(A+u,B+v)$, $(C+u,D+v)$;
 17290  this gives us enough information to deduce the transformation
 17291  $(x,y)\mapsto(Ax+Cy+u,Bx+Dy+v)$.
 17292  
 17293  Given ($A,B,C,D)$ we can always find $(a,b,\theta,\phi)$ such that
 17294  $$\eqalign{A&=a\cos\phi\cos\theta-b\sin\phi\sin\theta;\cr
 17295  B&=a\cos\phi\sin\theta+b\sin\phi\cos\theta;\cr
 17296  C&=-a\sin\phi\cos\theta-b\cos\phi\sin\theta;\cr
 17297  D&=-a\sin\phi\sin\theta+b\cos\phi\cos\theta.\cr}$$
 17298  In this notation, the unit circle $(\cos t,\sin t)$ is transformed into
 17299  $$\bigl(a\cos(\phi+t)\cos\theta-b\sin(\phi+t)\sin\theta,\;
 17300  a\cos(\phi+t)\sin\theta+b\sin(\phi+t)\cos\theta\bigr)\;+\;(u,v),$$
 17301  which is an ellipse with semi-axes~$(a,b)$, rotated by~$\theta$ and
 17302  shifted by~$(u,v)$. To solve the stated equations, we note that it is
 17303  necessary and sufficient to solve
 17304  $$\eqalign{A-D&=(a-b)\cos(\theta-\phi),\cr
 17305  B+C&=(a-b)\sin(\theta-\phi),\cr}
 17306  \qquad
 17307  \eqalign{A+D&=(a+b)\cos(\theta+\phi),\cr
 17308  B-C&=(a+b)\sin(\theta+\phi);\cr}$$
 17309  and it is easy to find $a-b$, $a+b$, $\theta-\phi$, and $\theta+\phi$
 17310  from these formulas.
 17311  
 17312  The code below uses |(txx,tyx,txy,tyy,tx,ty)| to stand for
 17313  $(A,B,C,D,u,v)$.
 17314  
 17315  @<Change node |q|...@>=
 17316  begin tx:=x_coord(q); ty:=y_coord(q);
 17317  txx:=left_x(q)-tx; tyx:=left_y(q)-ty;
 17318  txy:=right_x(q)-tx; tyy:=right_y(q)-ty;
 17319  a_minus_b:=pyth_add(txx-tyy,tyx+txy); a_plus_b:=pyth_add(txx+tyy,tyx-txy);
 17320  major_axis:=half(a_minus_b+a_plus_b); minor_axis:=half(abs(a_plus_b-a_minus_b));
 17321  if major_axis=minor_axis then theta:=0 {circle}
 17322  else theta:=half(n_arg(txx-tyy,tyx+txy)+n_arg(txx+tyy,tyx-txy));
 17323  free_node(q,knot_node_size);
 17324  q:=make_ellipse(major_axis,minor_axis,theta);
 17325  if (tx<>0)or(ty<>0) then @<Shift the coordinates of path |q|@>;
 17326  end
 17327  
 17328  @ @<Shift the coordinates of path |q|@>=
 17329  begin p:=q;
 17330  repeat x_coord(p):=x_coord(p)+tx; y_coord(p):=y_coord(p)+ty; p:=link(p);
 17331  until p=q;
 17332  end
 17333  
 17334  @ Finally we reach the deepest level in our quartet of parsing routines.
 17335  This one is much like the others; but it has an extra complication from
 17336  paths, which materialize here.
 17337  
 17338  @d continue_path=25 {a label inside of |scan_expression|}
 17339  @d finish_path=26 {another}
 17340  
 17341  @<Declare the basic parsing subroutines@>=
 17342  procedure scan_expression;
 17343  label restart,done,continue,continue_path,finish_path,exit;
 17344  var @!p,@!q,@!r,@!pp,@!qq:pointer; {for list manipulation}
 17345  @!c,@!d:halfword; {operation codes or modifiers}
 17346  @!my_var_flag:0..max_command_code; {initial value of |var_flag|}
 17347  @!mac_name:pointer; {token defined with \&{tertiarydef}}
 17348  @!cycle_hit:boolean; {did a path expression just end with `\&{cycle}'?}
 17349  @!x,@!y:scaled; {explicit coordinates or tension at a path join}
 17350  @!t:endpoint..open; {knot type following a path join}
 17351  begin my_var_flag:=var_flag;
 17352  restart:if(cur_cmd<min_primary_command)or@|
 17353   (cur_cmd>max_primary_command) then
 17354    bad_exp("An");
 17355  @.An expression...@>
 17356  scan_tertiary;
 17357  continue: if cur_cmd<=max_expression_command then
 17358   if cur_cmd>=min_expression_command then
 17359    if (cur_cmd<>equals)or(my_var_flag<>assignment) then
 17360    begin p:=stash_cur_exp; c:=cur_mod; d:=cur_cmd;
 17361    if d=expression_tertiary_macro then
 17362      begin mac_name:=cur_sym; add_mac_ref(c);
 17363      end;
 17364    if (d<ampersand)or((d=ampersand)and@|
 17365     ((type(p)=pair_type)or(type(p)=path_type))) then
 17366      @<Scan a path construction operation;
 17367        but |return| if |p| has the wrong type@>
 17368    else  begin get_x_next; scan_tertiary;
 17369      if d<>expression_tertiary_macro then do_binary(p,c)
 17370      else  begin back_input; binary_mac(p,c,mac_name);
 17371        decr(ref_count(c)); get_x_next; goto restart;
 17372        end;
 17373      end;
 17374    goto continue;
 17375    end;
 17376  exit:end;
 17377  
 17378  @ The reader should review the data structure conventions for paths before
 17379  hoping to understand the next part of this code.
 17380  
 17381  @<Scan a path construction operation...@>=
 17382  begin cycle_hit:=false;
 17383  @<Convert the left operand, |p|, into a partial path ending at~|q|;
 17384    but |return| if |p| doesn't have a suitable type@>;
 17385  continue_path: @<Determine the path join parameters;
 17386    but |goto finish_path| if there's only a direction specifier@>;
 17387  if cur_cmd=cycle then @<Get ready to close a cycle@>
 17388  else  begin scan_tertiary;
 17389    @<Convert the right operand, |cur_exp|,
 17390      into a partial path from |pp| to~|qq|@>;
 17391    end;
 17392  @<Join the partial paths and reset |p| and |q| to the head and tail
 17393    of the result@>;
 17394  if cur_cmd>=min_expression_command then
 17395   if cur_cmd<=ampersand then if not cycle_hit then goto continue_path;
 17396  finish_path:
 17397  @<Choose control points for the path and put the result into |cur_exp|@>;
 17398  end
 17399  
 17400  @ @<Convert the left operand, |p|, into a partial path ending at~|q|...@>=
 17401  begin unstash_cur_exp(p);
 17402  if cur_type=pair_type then p:=new_knot
 17403  else if cur_type=path_type then p:=cur_exp
 17404  else return;
 17405  q:=p;
 17406  while link(q)<>p do q:=link(q);
 17407  if left_type(p)<>endpoint then {open up a cycle}
 17408    begin r:=copy_knot(p); link(q):=r; q:=r;
 17409    end;
 17410  left_type(p):=open; right_type(q):=open;
 17411  end
 17412  
 17413  @ A pair of numeric values is changed into a knot node for a one-point path
 17414  when \MF\ discovers that the pair is part of a path.
 17415  
 17416  @p@t\4@>@<Declare the procedure called |known_pair|@>@;
 17417  function new_knot:pointer; {convert a pair to a knot with two endpoints}
 17418  var @!q:pointer; {the new node}
 17419  begin q:=get_node(knot_node_size); left_type(q):=endpoint;
 17420  right_type(q):=endpoint; link(q):=q;@/
 17421  known_pair; x_coord(q):=cur_x; y_coord(q):=cur_y;
 17422  new_knot:=q;
 17423  end;
 17424  
 17425  @ The |known_pair| subroutine sets |cur_x| and |cur_y| to the components
 17426  of the current expression, assuming that the current expression is a
 17427  pair of known numerics. Unknown components are zeroed, and the
 17428  current expression is flushed.
 17429  
 17430  @<Declare the procedure called |known_pair|@>=
 17431  procedure known_pair;
 17432  var @!p:pointer; {the pair node}
 17433  begin if cur_type<>pair_type then
 17434    begin exp_err("Undefined coordinates have been replaced by (0,0)");
 17435  @.Undefined coordinates...@>
 17436    help5("I need x and y numbers for this part of the path.")@/
 17437      ("The value I found (see above) was no good;")@/
 17438      ("so I'll try to keep going by using zero instead.")@/
 17439      ("(Chapter 27 of The METAFONTbook explains that")@/
 17440  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 17441      ("you might want to type `I ???' now.)");
 17442    put_get_flush_error(0); cur_x:=0; cur_y:=0;
 17443    end
 17444  else  begin p:=value(cur_exp);
 17445    @<Make sure that both |x| and |y| parts of |p| are known;
 17446      copy them into |cur_x| and |cur_y|@>;
 17447    flush_cur_exp(0);
 17448    end;
 17449  end;
 17450  
 17451  @ @<Make sure that both |x| and |y| parts of |p| are known...@>=
 17452  if type(x_part_loc(p))=known then cur_x:=value(x_part_loc(p))
 17453  else  begin disp_err(x_part_loc(p),
 17454      "Undefined x coordinate has been replaced by 0");
 17455  @.Undefined coordinates...@>
 17456    help5("I need a `known' x value for this part of the path.")@/
 17457      ("The value I found (see above) was no good;")@/
 17458      ("so I'll try to keep going by using zero instead.")@/
 17459      ("(Chapter 27 of The METAFONTbook explains that")@/
 17460  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 17461      ("you might want to type `I ???' now.)");
 17462    put_get_error; recycle_value(x_part_loc(p)); cur_x:=0;
 17463    end;
 17464  if type(y_part_loc(p))=known then cur_y:=value(y_part_loc(p))
 17465  else  begin disp_err(y_part_loc(p),
 17466      "Undefined y coordinate has been replaced by 0");
 17467    help5("I need a `known' y value for this part of the path.")@/
 17468      ("The value I found (see above) was no good;")@/
 17469      ("so I'll try to keep going by using zero instead.")@/
 17470      ("(Chapter 27 of The METAFONTbook explains that")@/
 17471      ("you might want to type `I ???' now.)");
 17472    put_get_error; recycle_value(y_part_loc(p)); cur_y:=0;
 17473    end
 17474  
 17475  @ At this point |cur_cmd| is either |ampersand|, |left_brace|, or |path_join|.
 17476  
 17477  @<Determine the path join parameters...@>=
 17478  if cur_cmd=left_brace then
 17479    @<Put the pre-join direction information into node |q|@>;
 17480  d:=cur_cmd;
 17481  if d=path_join then @<Determine the tension and/or control points@>
 17482  else if d<>ampersand then goto finish_path;
 17483  get_x_next;
 17484  if cur_cmd=left_brace then
 17485    @<Put the post-join direction information into |x| and |t|@>
 17486  else if right_type(q)<>explicit then
 17487    begin t:=open; x:=0;
 17488    end
 17489  
 17490  @ The |scan_direction| subroutine looks at the directional information
 17491  that is enclosed in braces, and also scans ahead to the following character.
 17492  A type code is returned, either |open| (if the direction was $(0,0)$),
 17493  or |curl| (if the direction was a curl of known value |cur_exp|), or
 17494  |given| (if the direction is given by the |angle| value that now
 17495  appears in |cur_exp|).
 17496  
 17497  There's nothing difficult about this subroutine, but the program is rather
 17498  lengthy because a variety of potential errors need to be nipped in the bud.
 17499  
 17500  @p function scan_direction:small_number;
 17501  var @!t:given..open; {the type of information found}
 17502  @!x:scaled; {an |x| coordinate}
 17503  begin get_x_next;
 17504  if cur_cmd=curl_command then @<Scan a curl specification@>
 17505  else @<Scan a given direction@>;
 17506  if cur_cmd<>right_brace then
 17507    begin missing_err("}");@/
 17508  @.Missing `\char`\}'@>
 17509    help3("I've scanned a direction spec for part of a path,")@/
 17510      ("so a right brace should have come next.")@/
 17511      ("I shall pretend that one was there.");@/
 17512    back_error;
 17513    end;
 17514  get_x_next; scan_direction:=t;
 17515  end;
 17516  
 17517  @ @<Scan a curl specification@>=
 17518  begin get_x_next; scan_expression;
 17519  if (cur_type<>known)or(cur_exp<0) then
 17520    begin exp_err("Improper curl has been replaced by 1");
 17521  @.Improper curl@>
 17522    help1("A curl must be a known, nonnegative number.");
 17523    put_get_flush_error(unity);
 17524    end;
 17525  t:=curl;
 17526  end
 17527  
 17528  @ @<Scan a given direction@>=
 17529  begin scan_expression;
 17530  if cur_type>pair_type then @<Get given directions separated by commas@>
 17531  else known_pair;
 17532  if (cur_x=0)and(cur_y=0) then t:=open
 17533  else  begin t:=given; cur_exp:=n_arg(cur_x,cur_y);
 17534    end;
 17535  end
 17536  
 17537  @ @<Get given directions separated by commas@>=
 17538  begin if cur_type<>known then
 17539    begin exp_err("Undefined x coordinate has been replaced by 0");
 17540  @.Undefined coordinates...@>
 17541    help5("I need a `known' x value for this part of the path.")@/
 17542      ("The value I found (see above) was no good;")@/
 17543      ("so I'll try to keep going by using zero instead.")@/
 17544      ("(Chapter 27 of The METAFONTbook explains that")@/
 17545  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 17546      ("you might want to type `I ???' now.)");
 17547    put_get_flush_error(0);
 17548    end;
 17549  x:=cur_exp;
 17550  if cur_cmd<>comma then
 17551    begin missing_err(",");@/
 17552  @.Missing `,'@>
 17553    help2("I've got the x coordinate of a path direction;")@/
 17554      ("will look for the y coordinate next.");
 17555    back_error;
 17556    end;
 17557  get_x_next; scan_expression;
 17558  if cur_type<>known then
 17559    begin exp_err("Undefined y coordinate has been replaced by 0");
 17560    help5("I need a `known' y value for this part of the path.")@/
 17561      ("The value I found (see above) was no good;")@/
 17562      ("so I'll try to keep going by using zero instead.")@/
 17563      ("(Chapter 27 of The METAFONTbook explains that")@/
 17564      ("you might want to type `I ???' now.)");
 17565    put_get_flush_error(0);
 17566    end;
 17567  cur_y:=cur_exp; cur_x:=x;
 17568  end
 17569  
 17570  @ At this point |right_type(q)| is usually |open|, but it may have been
 17571  set to some other value by a previous operation. We must maintain
 17572  the value of |right_type(q)| in cases such as
 17573  `\.{..\{curl2\}z\{0,0\}..}'.
 17574  
 17575  @<Put the pre-join...@>=
 17576  begin t:=scan_direction;
 17577  if t<>open then
 17578    begin right_type(q):=t; right_given(q):=cur_exp;
 17579    if left_type(q)=open then
 17580      begin left_type(q):=t; left_given(q):=cur_exp;
 17581      end; {note that |left_given(q)=left_curl(q)|}
 17582    end;
 17583  end
 17584  
 17585  @ Since |left_tension| and |left_y| share the same position in knot nodes,
 17586  and since |left_given| is similarly equivalent to |left_x|, we use
 17587  |x| and |y| to hold the given direction and tension information when
 17588  there are no explicit control points.
 17589  
 17590  @<Put the post-join...@>=
 17591  begin t:=scan_direction;
 17592  if right_type(q)<>explicit then x:=cur_exp
 17593  else t:=explicit; {the direction information is superfluous}
 17594  end
 17595  
 17596  @ @<Determine the tension and/or...@>=
 17597  begin get_x_next;
 17598  if cur_cmd=tension then @<Set explicit tensions@>
 17599  else if cur_cmd=controls then @<Set explicit control points@>
 17600  else  begin right_tension(q):=unity; y:=unity; back_input; {default tension}
 17601    goto done;
 17602    end;
 17603  if cur_cmd<>path_join then
 17604    begin missing_err("..");@/
 17605  @.Missing `..'@>
 17606    help1("A path join command should end with two dots.");
 17607    back_error;
 17608    end;
 17609  done:end
 17610  
 17611  @ @<Set explicit tensions@>=
 17612  begin get_x_next; y:=cur_cmd;
 17613  if cur_cmd=at_least then get_x_next;
 17614  scan_primary;
 17615  @<Make sure that the current expression is a valid tension setting@>;
 17616  if y=at_least then negate(cur_exp);
 17617  right_tension(q):=cur_exp;
 17618  if cur_cmd=and_command then
 17619    begin get_x_next; y:=cur_cmd;
 17620    if cur_cmd=at_least then get_x_next;
 17621    scan_primary;
 17622    @<Make sure that the current expression is a valid tension setting@>;
 17623    if y=at_least then negate(cur_exp);
 17624    end;
 17625  y:=cur_exp;
 17626  end
 17627  
 17628  @ @d min_tension==three_quarter_unit
 17629  
 17630  @<Make sure that the current expression is a valid tension setting@>=
 17631  if (cur_type<>known)or(cur_exp<min_tension) then
 17632    begin exp_err("Improper tension has been set to 1");
 17633  @.Improper tension@>
 17634    help1("The expression above should have been a number >=3/4.");
 17635    put_get_flush_error(unity);
 17636    end
 17637  
 17638  @ @<Set explicit control points@>=
 17639  begin right_type(q):=explicit; t:=explicit; get_x_next; scan_primary;@/
 17640  known_pair; right_x(q):=cur_x; right_y(q):=cur_y;
 17641  if cur_cmd<>and_command then
 17642    begin x:=right_x(q); y:=right_y(q);
 17643    end
 17644  else  begin get_x_next; scan_primary;@/
 17645    known_pair; x:=cur_x; y:=cur_y;
 17646    end;
 17647  end
 17648  
 17649  @ @<Convert the right operand, |cur_exp|, into a partial path...@>=
 17650  begin if cur_type<>path_type then pp:=new_knot
 17651  else pp:=cur_exp;
 17652  qq:=pp;
 17653  while link(qq)<>pp do qq:=link(qq);
 17654  if left_type(pp)<>endpoint then {open up a cycle}
 17655    begin r:=copy_knot(pp); link(qq):=r; qq:=r;
 17656    end;
 17657  left_type(pp):=open; right_type(qq):=open;
 17658  end
 17659  
 17660  @ If a person tries to define an entire path by saying `\.{(x,y)\&cycle}',
 17661  we silently change the specification to `\.{(x,y)..cycle}', since a cycle
 17662  shouldn't have length zero.
 17663  
 17664  @<Get ready to close a cycle@>=
 17665  begin cycle_hit:=true; get_x_next; pp:=p; qq:=p;
 17666  if d=ampersand then if p=q then
 17667    begin d:=path_join; right_tension(q):=unity; y:=unity;
 17668    end;
 17669  end
 17670  
 17671  @ @<Join the partial paths and reset |p| and |q|...@>=
 17672  begin if d=ampersand then
 17673   if (x_coord(q)<>x_coord(pp))or(y_coord(q)<>y_coord(pp)) then
 17674    begin print_err("Paths don't touch; `&' will be changed to `..'");
 17675  @.Paths don't touch@>
 17676    help3("When you join paths `p&q', the ending point of p")@/
 17677      ("must be exactly equal to the starting point of q.")@/
 17678      ("So I'm going to pretend that you said `p..q' instead.");
 17679    put_get_error; d:=path_join; right_tension(q):=unity; y:=unity;
 17680    end;
 17681  @<Plug an opening in |right_type(pp)|, if possible@>;
 17682  if d=ampersand then @<Splice independent paths together@>
 17683  else  begin @<Plug an opening in |right_type(q)|, if possible@>;
 17684    link(q):=pp; left_y(pp):=y;
 17685    if t<>open then
 17686      begin left_x(pp):=x; left_type(pp):=t;
 17687      end;
 17688    end;
 17689  q:=qq;
 17690  end
 17691  
 17692  @ @<Plug an opening in |right_type(q)|...@>=
 17693  if right_type(q)=open then
 17694    if (left_type(q)=curl)or(left_type(q)=given) then
 17695      begin right_type(q):=left_type(q); right_given(q):=left_given(q);
 17696      end
 17697  
 17698  @ @<Plug an opening in |right_type(pp)|...@>=
 17699  if right_type(pp)=open then
 17700    if (t=curl)or(t=given) then
 17701      begin right_type(pp):=t; right_given(pp):=x;
 17702      end
 17703  
 17704  @ @<Splice independent paths together@>=
 17705  begin if left_type(q)=open then if right_type(q)=open then
 17706      begin left_type(q):=curl; left_curl(q):=unity;
 17707      end;
 17708  if right_type(pp)=open then if t=open then
 17709    begin right_type(pp):=curl; right_curl(pp):=unity;
 17710    end;
 17711  right_type(q):=right_type(pp); link(q):=link(pp);@/
 17712  right_x(q):=right_x(pp); right_y(q):=right_y(pp);
 17713  free_node(pp,knot_node_size);
 17714  if qq=pp then qq:=q;
 17715  end
 17716  
 17717  @ @<Choose control points for the path...@>=
 17718  if cycle_hit then
 17719    begin if d=ampersand then p:=q;
 17720    end
 17721  else  begin left_type(p):=endpoint;
 17722    if right_type(p)=open then
 17723      begin right_type(p):=curl; right_curl(p):=unity;
 17724      end;
 17725    right_type(q):=endpoint;
 17726    if left_type(q)=open then
 17727      begin left_type(q):=curl; left_curl(q):=unity;
 17728      end;
 17729    link(q):=p;
 17730    end;
 17731  make_choices(p);
 17732  cur_type:=path_type; cur_exp:=p
 17733  
 17734  @ Finally, we sometimes need to scan an expression whose value is
 17735  supposed to be either |true_code| or |false_code|.
 17736  
 17737  @<Declare the basic parsing subroutines@>=
 17738  procedure get_boolean;
 17739  begin get_x_next; scan_expression;
 17740  if cur_type<>boolean_type then
 17741    begin exp_err("Undefined condition will be treated as `false'");
 17742  @.Undefined condition...@>
 17743    help2("The expression shown above should have had a definite")@/
 17744      ("true-or-false value. I'm changing it to `false'.");@/
 17745    put_get_flush_error(false_code); cur_type:=boolean_type;
 17746    end;
 17747  end;
 17748  
 17749  @* \[42] Doing the operations.
 17750  The purpose of parsing is primarily to permit people to avoid piles of
 17751  parentheses. But the real work is done after the structure of an expression
 17752  has been recognized; that's when new expressions are generated. We
 17753  turn now to the guts of \MF, which handles individual operators that
 17754  have come through the parsing mechanism.
 17755  
 17756  We'll start with the easy ones that take no operands, then work our way
 17757  up to operators with one and ultimately two arguments. In other words,
 17758  we will write the three procedures |do_nullary|, |do_unary|, and |do_binary|
 17759  that are invoked periodically by the expression scanners.
 17760  
 17761  First let's make sure that all of the primitive operators are in the
 17762  hash table. Although |scan_primary| and its relatives made use of the
 17763  \\{cmd} code for these operators, the \\{do} routines base everything
 17764  on the \\{mod} code. For example, |do_binary| doesn't care whether the
 17765  operation it performs is a |primary_binary| or |secondary_binary|, etc.
 17766  
 17767  @<Put each...@>=
 17768  primitive("true",nullary,true_code);@/
 17769  @!@:true_}{\&{true} primitive@>
 17770  primitive("false",nullary,false_code);@/
 17771  @!@:false_}{\&{false} primitive@>
 17772  primitive("nullpicture",nullary,null_picture_code);@/
 17773  @!@:null_picture_}{\&{nullpicture} primitive@>
 17774  primitive("nullpen",nullary,null_pen_code);@/
 17775  @!@:null_pen_}{\&{nullpen} primitive@>
 17776  primitive("jobname",nullary,job_name_op);@/
 17777  @!@:job_name_}{\&{jobname} primitive@>
 17778  primitive("readstring",nullary,read_string_op);@/
 17779  @!@:read_string_}{\&{readstring} primitive@>
 17780  primitive("pencircle",nullary,pen_circle);@/
 17781  @!@:pen_circle_}{\&{pencircle} primitive@>
 17782  primitive("normaldeviate",nullary,normal_deviate);@/
 17783  @!@:normal_deviate_}{\&{normaldeviate} primitive@>
 17784  primitive("odd",unary,odd_op);@/
 17785  @!@:odd_}{\&{odd} primitive@>
 17786  primitive("known",unary,known_op);@/
 17787  @!@:known_}{\&{known} primitive@>
 17788  primitive("unknown",unary,unknown_op);@/
 17789  @!@:unknown_}{\&{unknown} primitive@>
 17790  primitive("not",unary,not_op);@/
 17791  @!@:not_}{\&{not} primitive@>
 17792  primitive("decimal",unary,decimal);@/
 17793  @!@:decimal_}{\&{decimal} primitive@>
 17794  primitive("reverse",unary,reverse);@/
 17795  @!@:reverse_}{\&{reverse} primitive@>
 17796  primitive("makepath",unary,make_path_op);@/
 17797  @!@:make_path_}{\&{makepath} primitive@>
 17798  primitive("makepen",unary,make_pen_op);@/
 17799  @!@:make_pen_}{\&{makepen} primitive@>
 17800  primitive("totalweight",unary,total_weight_op);@/
 17801  @!@:total_weight_}{\&{totalweight} primitive@>
 17802  primitive("oct",unary,oct_op);@/
 17803  @!@:oct_}{\&{oct} primitive@>
 17804  primitive("hex",unary,hex_op);@/
 17805  @!@:hex_}{\&{hex} primitive@>
 17806  primitive("ASCII",unary,ASCII_op);@/
 17807  @!@:ASCII_}{\&{ASCII} primitive@>
 17808  primitive("char",unary,char_op);@/
 17809  @!@:char_}{\&{char} primitive@>
 17810  primitive("length",unary,length_op);@/
 17811  @!@:length_}{\&{length} primitive@>
 17812  primitive("turningnumber",unary,turning_op);@/
 17813  @!@:turning_number_}{\&{turningnumber} primitive@>
 17814  primitive("xpart",unary,x_part);@/
 17815  @!@:x_part_}{\&{xpart} primitive@>
 17816  primitive("ypart",unary,y_part);@/
 17817  @!@:y_part_}{\&{ypart} primitive@>
 17818  primitive("xxpart",unary,xx_part);@/
 17819  @!@:xx_part_}{\&{xxpart} primitive@>
 17820  primitive("xypart",unary,xy_part);@/
 17821  @!@:xy_part_}{\&{xypart} primitive@>
 17822  primitive("yxpart",unary,yx_part);@/
 17823  @!@:yx_part_}{\&{yxpart} primitive@>
 17824  primitive("yypart",unary,yy_part);@/
 17825  @!@:yy_part_}{\&{yypart} primitive@>
 17826  primitive("sqrt",unary,sqrt_op);@/
 17827  @!@:sqrt_}{\&{sqrt} primitive@>
 17828  primitive("mexp",unary,m_exp_op);@/
 17829  @!@:m_exp_}{\&{mexp} primitive@>
 17830  primitive("mlog",unary,m_log_op);@/
 17831  @!@:m_log_}{\&{mlog} primitive@>
 17832  primitive("sind",unary,sin_d_op);@/
 17833  @!@:sin_d_}{\&{sind} primitive@>
 17834  primitive("cosd",unary,cos_d_op);@/
 17835  @!@:cos_d_}{\&{cosd} primitive@>
 17836  primitive("floor",unary,floor_op);@/
 17837  @!@:floor_}{\&{floor} primitive@>
 17838  primitive("uniformdeviate",unary,uniform_deviate);@/
 17839  @!@:uniform_deviate_}{\&{uniformdeviate} primitive@>
 17840  primitive("charexists",unary,char_exists_op);@/
 17841  @!@:char_exists_}{\&{charexists} primitive@>
 17842  primitive("angle",unary,angle_op);@/
 17843  @!@:angle_}{\&{angle} primitive@>
 17844  primitive("cycle",cycle,cycle_op);@/
 17845  @!@:cycle_}{\&{cycle} primitive@>
 17846  primitive("+",plus_or_minus,plus);@/
 17847  @!@:+ }{\.{+} primitive@>
 17848  primitive("-",plus_or_minus,minus);@/
 17849  @!@:- }{\.{-} primitive@>
 17850  primitive("*",secondary_binary,times);@/
 17851  @!@:* }{\.{*} primitive@>
 17852  primitive("/",slash,over); eqtb[frozen_slash]:=eqtb[cur_sym];@/
 17853  @!@:/ }{\.{/} primitive@>
 17854  primitive("++",tertiary_binary,pythag_add);@/
 17855  @!@:++_}{\.{++} primitive@>
 17856  primitive("+-+",tertiary_binary,pythag_sub);@/
 17857  @!@:+-+_}{\.{+-+} primitive@>
 17858  primitive("and",and_command,and_op);@/
 17859  @!@:and_}{\&{and} primitive@>
 17860  primitive("or",tertiary_binary,or_op);@/
 17861  @!@:or_}{\&{or} primitive@>
 17862  primitive("<",expression_binary,less_than);@/
 17863  @!@:< }{\.{<} primitive@>
 17864  primitive("<=",expression_binary,less_or_equal);@/
 17865  @!@:<=_}{\.{<=} primitive@>
 17866  primitive(">",expression_binary,greater_than);@/
 17867  @!@:> }{\.{>} primitive@>
 17868  primitive(">=",expression_binary,greater_or_equal);@/
 17869  @!@:>=_}{\.{>=} primitive@>
 17870  primitive("=",equals,equal_to);@/
 17871  @!@:= }{\.{=} primitive@>
 17872  primitive("<>",expression_binary,unequal_to);@/
 17873  @!@:<>_}{\.{<>} primitive@>
 17874  primitive("substring",primary_binary,substring_of);@/
 17875  @!@:substring_}{\&{substring} primitive@>
 17876  primitive("subpath",primary_binary,subpath_of);@/
 17877  @!@:subpath_}{\&{subpath} primitive@>
 17878  primitive("directiontime",primary_binary,direction_time_of);@/
 17879  @!@:direction_time_}{\&{directiontime} primitive@>
 17880  primitive("point",primary_binary,point_of);@/
 17881  @!@:point_}{\&{point} primitive@>
 17882  primitive("precontrol",primary_binary,precontrol_of);@/
 17883  @!@:precontrol_}{\&{precontrol} primitive@>
 17884  primitive("postcontrol",primary_binary,postcontrol_of);@/
 17885  @!@:postcontrol_}{\&{postcontrol} primitive@>
 17886  primitive("penoffset",primary_binary,pen_offset_of);@/
 17887  @!@:pen_offset_}{\&{penoffset} primitive@>
 17888  primitive("&",ampersand,concatenate);@/
 17889  @!@:!!!}{\.{\&} primitive@>
 17890  primitive("rotated",secondary_binary,rotated_by);@/
 17891  @!@:rotated_}{\&{rotated} primitive@>
 17892  primitive("slanted",secondary_binary,slanted_by);@/
 17893  @!@:slanted_}{\&{slanted} primitive@>
 17894  primitive("scaled",secondary_binary,scaled_by);@/
 17895  @!@:scaled_}{\&{scaled} primitive@>
 17896  primitive("shifted",secondary_binary,shifted_by);@/
 17897  @!@:shifted_}{\&{shifted} primitive@>
 17898  primitive("transformed",secondary_binary,transformed_by);@/
 17899  @!@:transformed_}{\&{transformed} primitive@>
 17900  primitive("xscaled",secondary_binary,x_scaled);@/
 17901  @!@:x_scaled_}{\&{xscaled} primitive@>
 17902  primitive("yscaled",secondary_binary,y_scaled);@/
 17903  @!@:y_scaled_}{\&{yscaled} primitive@>
 17904  primitive("zscaled",secondary_binary,z_scaled);@/
 17905  @!@:z_scaled_}{\&{zscaled} primitive@>
 17906  primitive("intersectiontimes",tertiary_binary,intersect);@/
 17907  @!@:intersection_times_}{\&{intersectiontimes} primitive@>
 17908  
 17909  @ @<Cases of |print_cmd...@>=
 17910  nullary,unary,primary_binary,secondary_binary,tertiary_binary,
 17911   expression_binary,cycle,plus_or_minus,slash,ampersand,equals,and_command:
 17912    print_op(m);
 17913  
 17914  @ OK, let's look at the simplest \\{do} procedure first.
 17915  
 17916  @p procedure do_nullary(@!c:quarterword);
 17917  var @!k:integer; {all-purpose loop index}
 17918  begin check_arith;
 17919  if internal[tracing_commands]>two then
 17920    show_cmd_mod(nullary,c);
 17921  case c of
 17922  true_code,false_code:begin cur_type:=boolean_type; cur_exp:=c;
 17923    end;
 17924  null_picture_code:begin cur_type:=picture_type;
 17925    cur_exp:=get_node(edge_header_size); init_edges(cur_exp);
 17926    end;
 17927  null_pen_code:begin cur_type:=pen_type; cur_exp:=null_pen;
 17928    end;
 17929  normal_deviate:begin cur_type:=known; cur_exp:=norm_rand;
 17930    end;
 17931  pen_circle:@<Make a special knot node for \&{pencircle}@>;
 17932  job_name_op: begin if job_name=0 then open_log_file;
 17933    cur_type:=string_type; cur_exp:=job_name;
 17934    end;
 17935  read_string_op:@<Read a string from the terminal@>;
 17936  end; {there are no other cases}
 17937  check_arith;
 17938  end;
 17939  
 17940  @ @<Make a special knot node for \&{pencircle}@>=
 17941  begin cur_type:=future_pen; cur_exp:=get_node(knot_node_size);
 17942  left_type(cur_exp):=open; right_type(cur_exp):=open;
 17943  link(cur_exp):=cur_exp;@/
 17944  x_coord(cur_exp):=0; y_coord(cur_exp):=0;@/
 17945  left_x(cur_exp):=unity; left_y(cur_exp):=0;@/
 17946  right_x(cur_exp):=0; right_y(cur_exp):=unity;@/
 17947  end
 17948  
 17949  @ @<Read a string...@>=
 17950  begin if interaction<=nonstop_mode then
 17951    fatal_error("*** (cannot readstring in nonstop modes)");
 17952  begin_file_reading; name:=1; prompt_input("");
 17953  str_room(last-start);
 17954  for k:=start to last-1 do append_char(buffer[k]);
 17955  end_file_reading; cur_type:=string_type; cur_exp:=make_string;
 17956  end
 17957  
 17958  @ Things get a bit more interesting when there's an operand. The
 17959  operand to |do_unary| appears in |cur_type| and |cur_exp|.
 17960  
 17961  @p @t\4@>@<Declare unary action procedures@>@;
 17962  procedure do_unary(@!c:quarterword);
 17963  var @!p,@!q:pointer; {for list manipulation}
 17964  @!x:integer; {a temporary register}
 17965  begin check_arith;
 17966  if internal[tracing_commands]>two then
 17967    @<Trace the current unary operation@>;
 17968  case c of
 17969  plus:if cur_type<pair_type then
 17970    if cur_type<>picture_type then bad_unary(plus);
 17971  minus:@<Negate the current expression@>;
 17972  @t\4@>@<Additional cases of unary operators@>@;
 17973  end; {there are no other cases}
 17974  check_arith;
 17975  end;
 17976  
 17977  @ The |nice_pair| function returns |true| if both components of a pair
 17978  are known.
 17979  
 17980  @<Declare unary action procedures@>=
 17981  function nice_pair(@!p:integer;@!t:quarterword):boolean;
 17982  label exit;
 17983  begin if t=pair_type then
 17984    begin p:=value(p);
 17985    if type(x_part_loc(p))=known then
 17986     if type(y_part_loc(p))=known then
 17987      begin nice_pair:=true; return;
 17988      end;
 17989    end;
 17990  nice_pair:=false;
 17991  exit:end;
 17992  
 17993  @ @<Declare unary action...@>=
 17994  procedure print_known_or_unknown_type(@!t:small_number;@!v:integer);
 17995  begin print_char("(");
 17996  if t<dependent then
 17997    if t<>pair_type then print_type(t)
 17998    else if nice_pair(v,pair_type) then print("pair")
 17999    else print("unknown pair")
 18000  else print("unknown numeric");
 18001  print_char(")");
 18002  end;
 18003  
 18004  @ @<Declare unary action...@>=
 18005  procedure bad_unary(@!c:quarterword);
 18006  begin exp_err("Not implemented: "); print_op(c);
 18007  @.Not implemented...@>
 18008  print_known_or_unknown_type(cur_type,cur_exp);
 18009  help3("I'm afraid I don't know how to apply that operation to that")@/
 18010    ("particular type. Continue, and I'll simply return the")@/
 18011    ("argument (shown above) as the result of the operation.");
 18012  put_get_error;
 18013  end;
 18014  
 18015  @ @<Trace the current unary operation@>=
 18016  begin begin_diagnostic; print_nl("{"); print_op(c); print_char("(");@/
 18017  print_exp(null,0); {show the operand, but not verbosely}
 18018  print(")}"); end_diagnostic(false);
 18019  end
 18020  
 18021  @ Negation is easy except when the current expression
 18022  is of type |independent|, or when it is a pair with one or more
 18023  |independent| components.
 18024  
 18025  It is tempting to argue that the negative of an independent variable
 18026  is an independent variable, hence we don't have to do anything when
 18027  negating it. The fallacy is that other dependent variables pointing
 18028  to the current expression must change the sign of their
 18029  coefficients if we make no change to the current expression.
 18030  
 18031  Instead, we work around the problem by copying the current expression
 18032  and recycling it afterwards (cf.~the |stash_in| routine).
 18033  
 18034  @<Negate the current expression@>=
 18035  case cur_type of
 18036  pair_type,independent: begin q:=cur_exp; make_exp_copy(q);
 18037    if cur_type=dependent then negate_dep_list(dep_list(cur_exp))
 18038    else if cur_type=pair_type then
 18039      begin p:=value(cur_exp);
 18040      if type(x_part_loc(p))=known then negate(value(x_part_loc(p)))
 18041      else negate_dep_list(dep_list(x_part_loc(p)));
 18042      if type(y_part_loc(p))=known then negate(value(y_part_loc(p)))
 18043      else negate_dep_list(dep_list(y_part_loc(p)));
 18044      end; {if |cur_type=known| then |cur_exp=0|}
 18045    recycle_value(q); free_node(q,value_node_size);
 18046    end;
 18047  dependent,proto_dependent:negate_dep_list(dep_list(cur_exp));
 18048  known:negate(cur_exp);
 18049  picture_type:negate_edges(cur_exp);
 18050  othercases bad_unary(minus)
 18051  endcases
 18052  
 18053  @ @<Declare unary action...@>=
 18054  procedure negate_dep_list(@!p:pointer);
 18055  label exit;
 18056  begin loop@+begin negate(value(p));
 18057    if info(p)=null then return;
 18058    p:=link(p);
 18059    end;
 18060  exit:end;
 18061  
 18062  @ @<Additional cases of unary operators@>=
 18063  not_op: if cur_type<>boolean_type then bad_unary(not_op)
 18064    else cur_exp:=true_code+false_code-cur_exp;
 18065  
 18066  @ @d three_sixty_units==23592960 {that's |360*unity|}
 18067  @d boolean_reset(#)==if # then cur_exp:=true_code@+else cur_exp:=false_code
 18068  
 18069  @<Additional cases of unary operators@>=
 18070  sqrt_op,m_exp_op,m_log_op,sin_d_op,cos_d_op,floor_op,
 18071   uniform_deviate,odd_op,char_exists_op:@t@>@;@/
 18072    if cur_type<>known then bad_unary(c)
 18073    else case c of
 18074    sqrt_op:cur_exp:=square_rt(cur_exp);
 18075    m_exp_op:cur_exp:=m_exp(cur_exp);
 18076    m_log_op:cur_exp:=m_log(cur_exp);
 18077    sin_d_op,cos_d_op:begin n_sin_cos((cur_exp mod three_sixty_units)*16);
 18078      if c=sin_d_op then cur_exp:=round_fraction(n_sin)
 18079      else cur_exp:=round_fraction(n_cos);
 18080      end;
 18081    floor_op:cur_exp:=floor_scaled(cur_exp);
 18082    uniform_deviate:cur_exp:=unif_rand(cur_exp);
 18083    odd_op: begin boolean_reset(odd(round_unscaled(cur_exp)));
 18084      cur_type:=boolean_type;
 18085      end;
 18086    char_exists_op:@<Determine if a character has been shipped out@>;
 18087    end; {there are no other cases}
 18088  
 18089  @ @<Additional cases of unary operators@>=
 18090  angle_op:if nice_pair(cur_exp,cur_type) then
 18091      begin p:=value(cur_exp);
 18092      x:=n_arg(value(x_part_loc(p)),value(y_part_loc(p)));
 18093      if x>=0 then flush_cur_exp((x+8)div 16)
 18094      else flush_cur_exp(-((-x+8)div 16));
 18095      end
 18096    else bad_unary(angle_op);
 18097  
 18098  @ If the current expression is a pair, but the context wants it to
 18099  be a path, we call |pair_to_path|.
 18100  
 18101  @<Declare unary action...@>=
 18102  procedure pair_to_path;
 18103  begin cur_exp:=new_knot; cur_type:=path_type;
 18104  end;
 18105  
 18106  @ @<Additional cases of unary operators@>=
 18107  x_part,y_part:if (cur_type<=pair_type)and(cur_type>=transform_type) then
 18108      take_part(c)
 18109    else bad_unary(c);
 18110  xx_part,xy_part,yx_part,yy_part: if cur_type=transform_type then take_part(c)
 18111    else bad_unary(c);
 18112  
 18113  @ In the following procedure, |cur_exp| points to a capsule, which points to
 18114  a big node. We want to delete all but one part of the big node.
 18115  
 18116  @<Declare unary action...@>=
 18117  procedure take_part(@!c:quarterword);
 18118  var @!p:pointer; {the big node}
 18119  begin p:=value(cur_exp); value(temp_val):=p; type(temp_val):=cur_type;
 18120  link(p):=temp_val; free_node(cur_exp,value_node_size);
 18121  make_exp_copy(p+2*(c-x_part));
 18122  recycle_value(temp_val);
 18123  end;
 18124  
 18125  @ @<Initialize table entries...@>=
 18126  name_type(temp_val):=capsule;
 18127  
 18128  @ @<Additional cases of unary...@>=
 18129  char_op: if cur_type<>known then bad_unary(char_op)
 18130    else  begin cur_exp:=round_unscaled(cur_exp) mod 256; cur_type:=string_type;
 18131      if cur_exp<0 then cur_exp:=cur_exp+256;
 18132      if length(cur_exp)<>1 then
 18133        begin str_room(1); append_char(cur_exp); cur_exp:=make_string;
 18134        end;
 18135      end;
 18136  decimal: if cur_type<>known then bad_unary(decimal)
 18137    else  begin old_setting:=selector; selector:=new_string;
 18138      print_scaled(cur_exp); cur_exp:=make_string;
 18139      selector:=old_setting; cur_type:=string_type;
 18140      end;
 18141  oct_op,hex_op,ASCII_op: if cur_type<>string_type then bad_unary(c)
 18142    else str_to_num(c);
 18143  
 18144  @ @<Declare unary action...@>=
 18145  procedure str_to_num(@!c:quarterword); {converts a string to a number}
 18146  var @!n:integer; {accumulator}
 18147  @!m:ASCII_code; {current character}
 18148  @!k:pool_pointer; {index into |str_pool|}
 18149  @!b:8..16; {radix of conversion}
 18150  @!bad_char:boolean; {did the string contain an invalid digit?}
 18151  begin if c=ASCII_op then
 18152    if length(cur_exp)=0 then n:=-1
 18153    else n:=so(str_pool[str_start[cur_exp]])
 18154  else  begin if c=oct_op then b:=8@+else b:=16;
 18155    n:=0; bad_char:=false;
 18156    for k:=str_start[cur_exp] to str_start[cur_exp+1]-1 do
 18157      begin m:=so(str_pool[k]);
 18158      if (m>="0")and(m<="9") then m:=m-"0"
 18159      else if (m>="A")and(m<="F") then m:=m-"A"+10
 18160      else if (m>="a")and(m<="f") then m:=m-"a"+10
 18161      else  begin bad_char:=true; m:=0;
 18162        end;
 18163      if m>=b then
 18164        begin bad_char:=true; m:=0;
 18165        end;
 18166      if n<32768 div b then n:=n*b+m@+else n:=32767;
 18167      end;
 18168    @<Give error messages if |bad_char| or |n>=4096|@>;
 18169    end;
 18170  flush_cur_exp(n*unity);
 18171  end;
 18172  
 18173  @ @<Give error messages if |bad_char|...@>=
 18174  if bad_char then
 18175    begin exp_err("String contains illegal digits");
 18176  @.String contains illegal digits@>
 18177    if c=oct_op then
 18178      help1("I zeroed out characters that weren't in the range 0..7.")
 18179    else help1("I zeroed out characters that weren't hex digits.");
 18180    put_get_error;
 18181    end;
 18182  if n>4095 then
 18183    begin print_err("Number too large ("); print_int(n); print_char(")");
 18184  @.Number too large@>
 18185    help1("I have trouble with numbers greater than 4095; watch out.");
 18186    put_get_error;
 18187    end
 18188  
 18189  @ The length operation is somewhat unusual in that it applies to a variety
 18190  of different types of operands.
 18191  
 18192  @<Additional cases of unary...@>=
 18193  length_op: if cur_type=string_type then flush_cur_exp(length(cur_exp)*unity)
 18194    else if cur_type=path_type then flush_cur_exp(path_length)
 18195    else if cur_type=known then cur_exp:=abs(cur_exp)
 18196    else if nice_pair(cur_exp,cur_type) then
 18197      flush_cur_exp(pyth_add(value(x_part_loc(value(cur_exp))),@|
 18198        value(y_part_loc(value(cur_exp)))))
 18199    else bad_unary(c);
 18200  
 18201  @ @<Declare unary action...@>=
 18202  function path_length:scaled; {computes the length of the current path}
 18203  var @!n:scaled; {the path length so far}
 18204  @!p:pointer; {traverser}
 18205  begin p:=cur_exp;
 18206  if left_type(p)=endpoint then n:=-unity@+else n:=0;
 18207  repeat p:=link(p); n:=n+unity;
 18208  until p=cur_exp;
 18209  path_length:=n;
 18210  end;
 18211  
 18212  @ The turning number is computed only with respect to null pens. A different
 18213  pen might affect the turning number, in degenerate cases, because autorounding
 18214  will produce a slightly different path, or because excessively large coordinates
 18215  might be truncated.
 18216  
 18217  @<Additional cases of unary...@>=
 18218  turning_op:if cur_type=pair_type then flush_cur_exp(0)
 18219    else if cur_type<>path_type then bad_unary(turning_op)
 18220    else if left_type(cur_exp)=endpoint then
 18221       flush_cur_exp(0) {not a cyclic path}
 18222    else  begin cur_pen:=null_pen; cur_path_type:=contour_code;
 18223      cur_exp:=make_spec(cur_exp,
 18224        fraction_one-half_unit-1-el_gordo,0);
 18225      flush_cur_exp(turning_number*unity); {convert to |scaled|}
 18226      end;
 18227  
 18228  @ @d type_test_end== flush_cur_exp(true_code)
 18229    else flush_cur_exp(false_code);
 18230    cur_type:=boolean_type;
 18231    end
 18232  @d type_range_end(#)==(cur_type<=#) then type_test_end
 18233  @d type_range(#)==begin if (cur_type>=#) and type_range_end
 18234  @d type_test(#)==begin if cur_type=# then type_test_end
 18235  
 18236  @<Additional cases of unary operators@>=
 18237  boolean_type: type_range(boolean_type)(unknown_boolean);
 18238  string_type: type_range(string_type)(unknown_string);
 18239  pen_type: type_range(pen_type)(future_pen);
 18240  path_type: type_range(path_type)(unknown_path);
 18241  picture_type: type_range(picture_type)(unknown_picture);
 18242  transform_type,pair_type: type_test(c);
 18243  numeric_type: type_range(known)(independent);
 18244  known_op,unknown_op: test_known(c);
 18245  
 18246  @ @<Declare unary action procedures@>=
 18247  procedure test_known(@!c:quarterword);
 18248  label done;
 18249  var @!b:true_code..false_code; {is the current expression known?}
 18250  @!p,@!q:pointer; {locations in a big node}
 18251  begin b:=false_code;
 18252  case cur_type of
 18253  vacuous,boolean_type,string_type,pen_type,future_pen,path_type,picture_type,
 18254   known: b:=true_code;
 18255  transform_type,pair_type:begin p:=value(cur_exp); q:=p+big_node_size[cur_type];
 18256    repeat q:=q-2;
 18257    if type(q)<>known then goto done;
 18258    until q=p;
 18259    b:=true_code;
 18260  done:  end;
 18261  othercases do_nothing
 18262  endcases;
 18263  if c=known_op then flush_cur_exp(b)
 18264  else flush_cur_exp(true_code+false_code-b);
 18265  cur_type:=boolean_type;
 18266  end;
 18267  
 18268  @ @<Additional cases of unary operators@>=
 18269  cycle_op: begin if cur_type<>path_type then flush_cur_exp(false_code)
 18270    else if left_type(cur_exp)<>endpoint then flush_cur_exp(true_code)
 18271    else flush_cur_exp(false_code);
 18272    cur_type:=boolean_type;
 18273    end;
 18274  
 18275  @ @<Additional cases of unary operators@>=
 18276  make_pen_op: begin if cur_type=pair_type then pair_to_path;
 18277    if cur_type=path_type then cur_type:=future_pen
 18278    else bad_unary(make_pen_op);
 18279    end;
 18280  make_path_op: begin if cur_type=future_pen then materialize_pen;
 18281    if cur_type<>pen_type then bad_unary(make_path_op)
 18282    else  begin flush_cur_exp(make_path(cur_exp)); cur_type:=path_type;
 18283      end;
 18284    end;
 18285  total_weight_op: if cur_type<>picture_type then bad_unary(total_weight_op)
 18286    else flush_cur_exp(total_weight(cur_exp));
 18287  reverse: if cur_type=path_type then
 18288      begin p:=htap_ypoc(cur_exp);
 18289      if right_type(p)=endpoint then p:=link(p);
 18290      toss_knot_list(cur_exp); cur_exp:=p;
 18291      end
 18292    else if cur_type=pair_type then pair_to_path
 18293    else bad_unary(reverse);
 18294  
 18295  @ Finally, we have the operations that combine a capsule~|p|
 18296  with the current expression.
 18297  
 18298  @p @t\4@>@<Declare binary action procedures@>@;
 18299  procedure do_binary(@!p:pointer;@!c:quarterword);
 18300  label done,done1,exit;
 18301  var @!q,@!r,@!rr:pointer; {for list manipulation}
 18302  @!old_p,@!old_exp:pointer; {capsules to recycle}
 18303  @!v:integer; {for numeric manipulation}
 18304  begin check_arith;
 18305  if internal[tracing_commands]>two then
 18306    @<Trace the current binary operation@>;
 18307  @<Sidestep |independent| cases in capsule |p|@>;
 18308  @<Sidestep |independent| cases in the current expression@>;
 18309  case c of
 18310  plus,minus:@<Add or subtract the current expression from |p|@>;
 18311  @t\4@>@<Additional cases of binary operators@>@;
 18312  end; {there are no other cases}
 18313  recycle_value(p); free_node(p,value_node_size); {|return| to avoid this}
 18314  exit:check_arith; @<Recycle any sidestepped |independent| capsules@>;
 18315  end;
 18316  
 18317  @ @<Declare binary action...@>=
 18318  procedure bad_binary(@!p:pointer;@!c:quarterword);
 18319  begin disp_err(p,"");
 18320  exp_err("Not implemented: ");
 18321  @.Not implemented...@>
 18322  if c>=min_of then print_op(c);
 18323  print_known_or_unknown_type(type(p),p);
 18324  if c>=min_of then print("of")@+else print_op(c);
 18325  print_known_or_unknown_type(cur_type,cur_exp);@/
 18326  help3("I'm afraid I don't know how to apply that operation to that")@/
 18327    ("combination of types. Continue, and I'll return the second")@/
 18328    ("argument (see above) as the result of the operation.");
 18329  put_get_error;
 18330  end;
 18331  
 18332  @ @<Trace the current binary operation@>=
 18333  begin begin_diagnostic; print_nl("{(");
 18334  print_exp(p,0); {show the operand, but not verbosely}
 18335  print_char(")"); print_op(c); print_char("(");@/
 18336  print_exp(null,0); print(")}"); end_diagnostic(false);
 18337  end
 18338  
 18339  @ Several of the binary operations are potentially complicated by the
 18340  fact that |independent| values can sneak into capsules. For example,
 18341  we've seen an instance of this difficulty in the unary operation
 18342  of negation. In order to reduce the number of cases that need to be
 18343  handled, we first change the two operands (if necessary)
 18344  to rid them of |independent| components. The original operands are
 18345  put into capsules called |old_p| and |old_exp|, which will be
 18346  recycled after the binary operation has been safely carried out.
 18347  
 18348  @<Recycle any sidestepped |independent| capsules@>=
 18349  if old_p<>null then
 18350    begin recycle_value(old_p); free_node(old_p,value_node_size);
 18351    end;
 18352  if old_exp<>null then
 18353    begin recycle_value(old_exp); free_node(old_exp,value_node_size);
 18354    end
 18355  
 18356  @ A big node is considered to be ``tarnished'' if it contains at least one
 18357  independent component. We will define a simple function called `|tarnished|'
 18358  that returns |null| if and only if its argument is not tarnished.
 18359  
 18360  @<Sidestep |independent| cases in capsule |p|@>=
 18361  case type(p) of
 18362  transform_type,pair_type: old_p:=tarnished(p);
 18363  independent: old_p:=void;
 18364  othercases old_p:=null
 18365  endcases;
 18366  if old_p<>null then
 18367    begin q:=stash_cur_exp; old_p:=p; make_exp_copy(old_p);
 18368    p:=stash_cur_exp; unstash_cur_exp(q);
 18369    end;
 18370  
 18371  @ @<Sidestep |independent| cases in the current expression@>=
 18372  case cur_type of
 18373  transform_type,pair_type:old_exp:=tarnished(cur_exp);
 18374  independent:old_exp:=void;
 18375  othercases old_exp:=null
 18376  endcases;
 18377  if old_exp<>null then
 18378    begin old_exp:=cur_exp; make_exp_copy(old_exp);
 18379    end
 18380  
 18381  @ @<Declare binary action...@>=
 18382  function tarnished(@!p:pointer):pointer;
 18383  label exit;
 18384  var @!q:pointer; {beginning of the big node}
 18385  @!r:pointer; {current position in the big node}
 18386  begin q:=value(p); r:=q+big_node_size[type(p)];
 18387  repeat r:=r-2;
 18388  if type(r)=independent then
 18389    begin tarnished:=void; return;
 18390    end;
 18391  until r=q;
 18392  tarnished:=null;
 18393  exit:end;
 18394  
 18395  @ @<Add or subtract the current expression from |p|@>=
 18396  if (cur_type<pair_type)or(type(p)<pair_type) then
 18397    if (cur_type=picture_type)and(type(p)=picture_type) then
 18398      begin if c=minus then negate_edges(cur_exp);
 18399      cur_edges:=cur_exp; merge_edges(value(p));
 18400      end
 18401    else bad_binary(p,c)
 18402  else  if cur_type=pair_type then
 18403      if type(p)<>pair_type then bad_binary(p,c)
 18404      else  begin q:=value(p); r:=value(cur_exp);
 18405        add_or_subtract(x_part_loc(q),x_part_loc(r),c);
 18406        add_or_subtract(y_part_loc(q),y_part_loc(r),c);
 18407        end
 18408    else  if type(p)=pair_type then bad_binary(p,c)
 18409      else add_or_subtract(p,null,c)
 18410  
 18411  @ The first argument to |add_or_subtract| is the location of a value node
 18412  in a capsule or pair node that will soon be recycled. The second argument
 18413  is either a location within a pair or transform node of |cur_exp|,
 18414  or it is null (which means that |cur_exp| itself should be the second
 18415  argument).  The third argument is either |plus| or |minus|.
 18416  
 18417  The sum or difference of the numeric quantities will replace the second
 18418  operand.  Arithmetic overflow may go undetected; users aren't supposed to
 18419  be monkeying around with really big values.
 18420  @^overflow in arithmetic@>
 18421  
 18422  @<Declare binary action...@>=
 18423  @t\4@>@<Declare the procedure called |dep_finish|@>@;
 18424  procedure add_or_subtract(@!p,@!q:pointer;@!c:quarterword);
 18425  label done,exit;
 18426  var @!s,@!t:small_number; {operand types}
 18427  @!r:pointer; {list traverser}
 18428  @!v:integer; {second operand value}
 18429  begin if q=null then
 18430    begin t:=cur_type;
 18431    if t<dependent then v:=cur_exp@+else v:=dep_list(cur_exp);
 18432    end
 18433  else  begin t:=type(q);
 18434    if t<dependent then v:=value(q)@+else v:=dep_list(q);
 18435    end;
 18436  if t=known then
 18437    begin if c=minus then negate(v);
 18438    if type(p)=known then
 18439      begin v:=slow_add(value(p),v);
 18440      if q=null then cur_exp:=v@+else value(q):=v;
 18441      return;
 18442      end;
 18443    @<Add a known value to the constant term of |dep_list(p)|@>;
 18444    end
 18445  else  begin if c=minus then negate_dep_list(v);
 18446    @<Add operand |p| to the dependency list |v|@>;
 18447    end;
 18448  exit:end;
 18449  
 18450  @ @<Add a known value to the constant term of |dep_list(p)|@>=
 18451  r:=dep_list(p);
 18452  while info(r)<>null do r:=link(r);
 18453  value(r):=slow_add(value(r),v);
 18454  if q=null then
 18455    begin q:=get_node(value_node_size); cur_exp:=q; cur_type:=type(p);
 18456    name_type(q):=capsule;
 18457    end;
 18458  dep_list(q):=dep_list(p); type(q):=type(p);
 18459  prev_dep(q):=prev_dep(p); link(prev_dep(p)):=q;
 18460  type(p):=known; {this will keep the recycler from collecting non-garbage}
 18461  
 18462  @ We prefer |dependent| lists to |proto_dependent| ones, because it is
 18463  nice to retain the extra accuracy of |fraction| coefficients.
 18464  But we have to handle both kinds, and mixtures too.
 18465  
 18466  @<Add operand |p| to the dependency list |v|@>=
 18467  if type(p)=known then
 18468    @<Add the known |value(p)| to the constant term of |v|@>
 18469  else  begin s:=type(p); r:=dep_list(p);
 18470    if t=dependent then
 18471      begin if s=dependent then
 18472       if max_coef(r)+max_coef(v)<coef_bound then
 18473        begin v:=p_plus_q(v,r,dependent); goto done;
 18474        end; {|fix_needed| will necessarily be false}
 18475      t:=proto_dependent; v:=p_over_v(v,unity,dependent,proto_dependent);
 18476      end;
 18477    if s=proto_dependent then v:=p_plus_q(v,r,proto_dependent)
 18478    else v:=p_plus_fq(v,unity,r,proto_dependent,dependent);
 18479   done:  @<Output the answer, |v| (which might have become |known|)@>;
 18480    end
 18481  
 18482  @ @<Add the known |value(p)| to the constant term of |v|@>=
 18483  begin while info(v)<>null do v:=link(v);
 18484  value(v):=slow_add(value(p),value(v));
 18485  end
 18486  
 18487  @ @<Output the answer, |v| (which might have become |known|)@>=
 18488  if q<>null then dep_finish(v,q,t)
 18489  else  begin cur_type:=t; dep_finish(v,null,t);
 18490    end
 18491  
 18492  @ Here's the current situation: The dependency list |v| of type |t|
 18493  should either be put into the current expression (if |q=null|) or
 18494  into location |q| within a pair node (otherwise). The destination (|cur_exp|
 18495  or |q|) formerly held a dependency list with the same
 18496  final pointer as the list |v|.
 18497  
 18498  @<Declare the procedure called |dep_finish|@>=
 18499  procedure dep_finish(@!v,@!q:pointer;@!t:small_number);
 18500  var @!p:pointer; {the destination}
 18501  @!vv:scaled; {the value, if it is |known|}
 18502  begin if q=null then p:=cur_exp@+else p:=q;
 18503  dep_list(p):=v; type(p):=t;
 18504  if info(v)=null then
 18505    begin vv:=value(v);
 18506    if q=null then flush_cur_exp(vv)
 18507    else  begin recycle_value(p); type(q):=known; value(q):=vv;
 18508      end;
 18509    end
 18510  else if q=null then cur_type:=t;
 18511  if fix_needed then fix_dependencies;
 18512  end;
 18513  
 18514  @ Let's turn now to the six basic relations of comparison.
 18515  
 18516  @<Additional cases of binary operators@>=
 18517  less_than,less_or_equal,greater_than,greater_or_equal,equal_to,unequal_to:
 18518    begin@t@>@;
 18519    if (cur_type>pair_type)and(type(p)>pair_type) then
 18520      add_or_subtract(p,null,minus) {|cur_exp:=(p)-cur_exp|}
 18521    else if cur_type<>type(p) then
 18522      begin bad_binary(p,c); goto done;
 18523      end
 18524    else if cur_type=string_type then
 18525      flush_cur_exp(str_vs_str(value(p),cur_exp))
 18526    else if (cur_type=unknown_string)or(cur_type=unknown_boolean) then
 18527      @<Check if unknowns have been equated@>
 18528    else if (cur_type=pair_type)or(cur_type=transform_type) then
 18529      @<Reduce comparison of big nodes to comparison of scalars@>
 18530    else if cur_type=boolean_type then flush_cur_exp(cur_exp-value(p))
 18531    else  begin bad_binary(p,c); goto done;
 18532      end;
 18533    @<Compare the current expression with zero@>;
 18534  done:  end;
 18535  
 18536  @ @<Compare the current expression with zero@>=
 18537  if cur_type<>known then
 18538    begin if cur_type<known then
 18539      begin disp_err(p,"");
 18540      help1("The quantities shown above have not been equated.")@/
 18541      end
 18542    else  help2("Oh dear. I can't decide if the expression above is positive,")@/
 18543      ("negative, or zero. So this comparison test won't be `true'.");
 18544    exp_err("Unknown relation will be considered false");
 18545  @.Unknown relation...@>
 18546    put_get_flush_error(false_code);
 18547    end
 18548  else case c of
 18549    less_than: boolean_reset(cur_exp<0);
 18550    less_or_equal: boolean_reset(cur_exp<=0);
 18551    greater_than: boolean_reset(cur_exp>0);
 18552    greater_or_equal: boolean_reset(cur_exp>=0);
 18553    equal_to: boolean_reset(cur_exp=0);
 18554    unequal_to: boolean_reset(cur_exp<>0);
 18555    end; {there are no other cases}
 18556   cur_type:=boolean_type
 18557  
 18558  @ When two unknown strings are in the same ring, we know that they are
 18559  equal. Otherwise, we don't know whether they are equal or not, so we
 18560  make no change.
 18561  
 18562  @<Check if unknowns have been equated@>=
 18563  begin q:=value(cur_exp);
 18564  while (q<>cur_exp)and(q<>p) do q:=value(q);
 18565  if q=p then flush_cur_exp(0);
 18566  end
 18567  
 18568  @ @<Reduce comparison of big nodes to comparison of scalars@>=
 18569  begin q:=value(p); r:=value(cur_exp);
 18570  rr:=r+big_node_size[cur_type]-2;
 18571  loop@+  begin add_or_subtract(q,r,minus);
 18572    if type(r)<>known then goto done1;
 18573    if value(r)<>0 then goto done1;
 18574    if r=rr then goto done1;
 18575    q:=q+2; r:=r+2;
 18576    end;
 18577  done1:take_part(x_part+half(r-value(cur_exp)));
 18578  end
 18579  
 18580  @ Here we use the sneaky fact that |and_op-false_code=or_op-true_code|.
 18581  
 18582  @<Additional cases of binary operators@>=
 18583  and_op,or_op: if (type(p)<>boolean_type)or(cur_type<>boolean_type) then
 18584      bad_binary(p,c)
 18585    else if value(p)=c+false_code-and_op then cur_exp:=value(p);
 18586  
 18587  @ @<Additional cases of binary operators@>=
 18588  times: if (cur_type<pair_type)or(type(p)<pair_type) then bad_binary(p,times)
 18589    else if (cur_type=known)or(type(p)=known) then
 18590      @<Multiply when at least one operand is known@>
 18591    else if (nice_pair(p,type(p))and(cur_type>pair_type))
 18592        or(nice_pair(cur_exp,cur_type)and(type(p)>pair_type)) then
 18593      begin hard_times(p); return;
 18594      end
 18595    else bad_binary(p,times);
 18596  
 18597  @ @<Multiply when at least one operand is known@>=
 18598  begin if type(p)=known then
 18599    begin v:=value(p); free_node(p,value_node_size);
 18600    end
 18601  else  begin v:=cur_exp; unstash_cur_exp(p);
 18602    end;
 18603  if cur_type=known then cur_exp:=take_scaled(cur_exp,v)
 18604  else if cur_type=pair_type then
 18605    begin p:=value(cur_exp);
 18606    dep_mult(x_part_loc(p),v,true);
 18607    dep_mult(y_part_loc(p),v,true);
 18608    end
 18609  else dep_mult(null,v,true);
 18610  return;
 18611  end
 18612  
 18613  @ @<Declare binary action...@>=
 18614  procedure dep_mult(@!p:pointer;@!v:integer;@!v_is_scaled:boolean);
 18615  label exit;
 18616  var @!q:pointer; {the dependency list being multiplied by |v|}
 18617  @!s,@!t:small_number; {its type, before and after}
 18618  begin if p=null then q:=cur_exp
 18619  else if type(p)<>known then q:=p
 18620  else  begin if v_is_scaled then value(p):=take_scaled(value(p),v)
 18621    else value(p):=take_fraction(value(p),v);
 18622    return;
 18623    end;
 18624  t:=type(q); q:=dep_list(q); s:=t;
 18625  if t=dependent then if v_is_scaled then
 18626    if ab_vs_cd(max_coef(q),abs(v),coef_bound-1,unity)>=0 then t:=proto_dependent;
 18627  q:=p_times_v(q,v,s,t,v_is_scaled); dep_finish(q,p,t);
 18628  exit:end;
 18629  
 18630  @ Here is a routine that is similar to |times|; but it is invoked only
 18631  internally, when |v| is a |fraction| whose magnitude is at most~1,
 18632  and when |cur_type>=pair_type|.
 18633  
 18634  @p procedure frac_mult(@!n,@!d:scaled); {multiplies |cur_exp| by |n/d|}
 18635  var @!p:pointer; {a pair node}
 18636  @!old_exp:pointer; {a capsule to recycle}
 18637  @!v:fraction; {|n/d|}
 18638  begin if internal[tracing_commands]>two then
 18639    @<Trace the fraction multiplication@>;
 18640  case cur_type of
 18641  transform_type,pair_type:old_exp:=tarnished(cur_exp);
 18642  independent:old_exp:=void;
 18643  othercases old_exp:=null
 18644  endcases;
 18645  if old_exp<>null then
 18646    begin old_exp:=cur_exp; make_exp_copy(old_exp);
 18647    end;
 18648  v:=make_fraction(n,d);
 18649  if cur_type=known then cur_exp:=take_fraction(cur_exp,v)
 18650  else if cur_type=pair_type then
 18651    begin p:=value(cur_exp);
 18652    dep_mult(x_part_loc(p),v,false);
 18653    dep_mult(y_part_loc(p),v,false);
 18654    end
 18655  else dep_mult(null,v,false);
 18656  if old_exp<>null then
 18657    begin recycle_value(old_exp); free_node(old_exp,value_node_size);
 18658    end
 18659  end;
 18660  
 18661  @ @<Trace the fraction multiplication@>=
 18662  begin begin_diagnostic; print_nl("{("); print_scaled(n); print_char("/");
 18663  print_scaled(d); print(")*("); print_exp(null,0); print(")}");
 18664  end_diagnostic(false);
 18665  end
 18666  
 18667  @ The |hard_times| routine multiplies a nice pair by a dependency list.
 18668  
 18669  @<Declare binary action procedures@>=
 18670  procedure hard_times(@!p:pointer);
 18671  var @!q:pointer; {a copy of the dependent variable |p|}
 18672  @!r:pointer; {the big node for the nice pair}
 18673  @!u,@!v:scaled; {the known values of the nice pair}
 18674  begin if type(p)=pair_type then
 18675    begin q:=stash_cur_exp; unstash_cur_exp(p); p:=q;
 18676    end; {now |cur_type=pair_type|}
 18677  r:=value(cur_exp); u:=value(x_part_loc(r)); v:=value(y_part_loc(r));
 18678  @<Move the dependent variable |p| into both parts of the pair node |r|@>;
 18679  dep_mult(x_part_loc(r),u,true); dep_mult(y_part_loc(r),v,true);
 18680  end;
 18681  
 18682  @ @<Move the dependent variable |p|...@>=
 18683  type(y_part_loc(r)):=type(p);
 18684  new_dep(y_part_loc(r),copy_dep_list(dep_list(p)));@/
 18685  type(x_part_loc(r)):=type(p);
 18686  mem[value_loc(x_part_loc(r))]:=mem[value_loc(p)];
 18687  link(prev_dep(p)):=x_part_loc(r);
 18688  free_node(p,value_node_size)
 18689  
 18690  @ @<Additional cases of binary operators@>=
 18691  over: if (cur_type<>known)or(type(p)<pair_type) then bad_binary(p,over)
 18692    else  begin v:=cur_exp; unstash_cur_exp(p);
 18693      if v=0 then @<Squeal about division by zero@>
 18694      else  begin if cur_type=known then cur_exp:=make_scaled(cur_exp,v)
 18695        else if cur_type=pair_type then
 18696          begin p:=value(cur_exp);
 18697          dep_div(x_part_loc(p),v);
 18698          dep_div(y_part_loc(p),v);
 18699          end
 18700        else dep_div(null,v);
 18701        end;
 18702      return;
 18703      end;
 18704  
 18705  @ @<Declare binary action...@>=
 18706  procedure dep_div(@!p:pointer;@!v:scaled);
 18707  label exit;
 18708  var @!q:pointer; {the dependency list being divided by |v|}
 18709  @!s,@!t:small_number; {its type, before and after}
 18710  begin if p=null then q:=cur_exp
 18711  else if type(p)<>known then q:=p
 18712  else  begin value(p):=make_scaled(value(p),v); return;
 18713    end;
 18714  t:=type(q); q:=dep_list(q); s:=t;
 18715  if t=dependent then
 18716    if ab_vs_cd(max_coef(q),unity,coef_bound-1,abs(v))>=0 then t:=proto_dependent;
 18717  q:=p_over_v(q,v,s,t); dep_finish(q,p,t);
 18718  exit:end;
 18719  
 18720  @ @<Squeal about division by zero@>=
 18721  begin exp_err("Division by zero");
 18722  @.Division by zero@>
 18723  help2("You're trying to divide the quantity shown above the error")@/
 18724    ("message by zero. I'm going to divide it by one instead.");
 18725  put_get_error;
 18726  end
 18727  
 18728  @ @<Additional cases of binary operators@>=
 18729  pythag_add,pythag_sub: if (cur_type=known)and(type(p)=known) then
 18730      if c=pythag_add then cur_exp:=pyth_add(value(p),cur_exp)
 18731      else cur_exp:=pyth_sub(value(p),cur_exp)
 18732    else bad_binary(p,c);
 18733  
 18734  @ The next few sections of the program deal with affine transformations
 18735  of coordinate data.
 18736  
 18737  @<Additional cases of binary operators@>=
 18738  rotated_by,slanted_by,scaled_by,shifted_by,transformed_by,
 18739   x_scaled,y_scaled,z_scaled: @t@>@;@/
 18740    if (type(p)=path_type)or(type(p)=future_pen)or(type(p)=pen_type) then
 18741      begin path_trans(p,c); return;
 18742      end
 18743    else if (type(p)=pair_type)or(type(p)=transform_type) then big_trans(p,c)
 18744    else if type(p)=picture_type then
 18745      begin edges_trans(p,c); return;
 18746      end
 18747    else bad_binary(p,c);
 18748  
 18749  @ Let |c| be one of the eight transform operators. The procedure call
 18750  |set_up_trans(c)| first changes |cur_exp| to a transform that corresponds to
 18751  |c| and the original value of |cur_exp|. (In particular, |cur_exp| doesn't
 18752  change at all if |c=transformed_by|.)
 18753  
 18754  Then, if all components of the resulting transform are |known|, they are
 18755  moved to the global variables |txx|, |txy|, |tyx|, |tyy|, |tx|, |ty|;
 18756  and |cur_exp| is changed to the known value zero.
 18757  
 18758  @<Declare binary action...@>=
 18759  procedure set_up_trans(@!c:quarterword);
 18760  label done,exit;
 18761  var @!p,@!q,@!r:pointer; {list manipulation registers}
 18762  begin if (c<>transformed_by)or(cur_type<>transform_type) then
 18763    @<Put the current transform into |cur_exp|@>;
 18764  @<If the current transform is entirely known, stash it in global variables;
 18765    otherwise |return|@>;
 18766  exit:end;
 18767  
 18768  @ @<Glob...@>=
 18769  @!txx,@!txy,@!tyx,@!tyy,@!tx,@!ty:scaled; {current transform coefficients}
 18770  
 18771  @ @<Put the current transform...@>=
 18772  begin p:=stash_cur_exp; cur_exp:=id_transform; cur_type:=transform_type;
 18773  q:=value(cur_exp);
 18774  case c of
 18775  @<For each of the eight cases, change the relevant fields of |cur_exp|
 18776    and |goto done|;
 18777    but do nothing if capsule |p| doesn't have the appropriate type@>@;
 18778  end; {there are no other cases}
 18779  disp_err(p,"Improper transformation argument");
 18780  @.Improper transformation argument@>
 18781  help3("The expression shown above has the wrong type,")@/
 18782    ("so I can't transform anything using it.")@/
 18783    ("Proceed, and I'll omit the transformation.");
 18784  put_get_error;
 18785  done: recycle_value(p); free_node(p,value_node_size);
 18786  end
 18787  
 18788  @ @<If the current transform is entirely known, ...@>=
 18789  q:=value(cur_exp); r:=q+transform_node_size;
 18790  repeat r:=r-2;
 18791  if type(r)<>known then return;
 18792  until r=q;
 18793  txx:=value(xx_part_loc(q));
 18794  txy:=value(xy_part_loc(q));
 18795  tyx:=value(yx_part_loc(q));
 18796  tyy:=value(yy_part_loc(q));
 18797  tx:=value(x_part_loc(q));
 18798  ty:=value(y_part_loc(q));
 18799  flush_cur_exp(0)
 18800  
 18801  @ @<For each of the eight cases...@>=
 18802  rotated_by:if type(p)=known then
 18803    @<Install sines and cosines, then |goto done|@>;
 18804  slanted_by:if type(p)>pair_type then
 18805    begin install(xy_part_loc(q),p); goto done;
 18806    end;
 18807  scaled_by:if type(p)>pair_type then
 18808    begin install(xx_part_loc(q),p); install(yy_part_loc(q),p); goto done;
 18809    end;
 18810  shifted_by:if type(p)=pair_type then
 18811    begin r:=value(p); install(x_part_loc(q),x_part_loc(r));
 18812    install(y_part_loc(q),y_part_loc(r)); goto done;
 18813    end;
 18814  x_scaled:if type(p)>pair_type then
 18815    begin install(xx_part_loc(q),p); goto done;
 18816    end;
 18817  y_scaled:if type(p)>pair_type then
 18818    begin install(yy_part_loc(q),p); goto done;
 18819    end;
 18820  z_scaled:if type(p)=pair_type then
 18821    @<Install a complex multiplier, then |goto done|@>;
 18822  transformed_by:do_nothing;
 18823  
 18824  @ @<Install sines and cosines, then |goto done|@>=
 18825  begin n_sin_cos((value(p) mod three_sixty_units)*16);
 18826  value(xx_part_loc(q)):=round_fraction(n_cos);
 18827  value(yx_part_loc(q)):=round_fraction(n_sin);
 18828  value(xy_part_loc(q)):=-value(yx_part_loc(q));
 18829  value(yy_part_loc(q)):=value(xx_part_loc(q));
 18830  goto done;
 18831  end
 18832  
 18833  @ @<Install a complex multiplier, then |goto done|@>=
 18834  begin r:=value(p);
 18835  install(xx_part_loc(q),x_part_loc(r));
 18836  install(yy_part_loc(q),x_part_loc(r));
 18837  install(yx_part_loc(q),y_part_loc(r));
 18838  if type(y_part_loc(r))=known then negate(value(y_part_loc(r)))
 18839  else negate_dep_list(dep_list(y_part_loc(r)));
 18840  install(xy_part_loc(q),y_part_loc(r));
 18841  goto done;
 18842  end
 18843  
 18844  @ Procedure |set_up_known_trans| is like |set_up_trans|, but it
 18845  insists that the transformation be entirely known.
 18846  
 18847  @<Declare binary action...@>=
 18848  procedure set_up_known_trans(@!c:quarterword);
 18849  begin set_up_trans(c);
 18850  if cur_type<>known then
 18851    begin exp_err("Transform components aren't all known");
 18852  @.Transform components...@>
 18853    help3("I'm unable to apply a partially specified transformation")@/
 18854      ("except to a fully known pair or transform.")@/
 18855      ("Proceed, and I'll omit the transformation.");
 18856    put_get_flush_error(0);
 18857    txx:=unity; txy:=0; tyx:=0; tyy:=unity; tx:=0; ty:=0;
 18858    end;
 18859  end;
 18860  
 18861  @ Here's a procedure that applies the transform |txx..ty| to a pair of
 18862  coordinates in locations |p| and~|q|.
 18863  
 18864  @<Declare binary action...@>=
 18865  procedure trans(@!p,@!q:pointer);
 18866  var @!v:scaled; {the new |x| value}
 18867  begin v:=take_scaled(mem[p].sc,txx)+take_scaled(mem[q].sc,txy)+tx;
 18868  mem[q].sc:=take_scaled(mem[p].sc,tyx)+take_scaled(mem[q].sc,tyy)+ty;
 18869  mem[p].sc:=v;
 18870  end;
 18871  
 18872  @ The simplest transformation procedure applies a transform to all
 18873  coordinates of a path. The |null_pen| remains unchanged if it isn't
 18874  being shifted.
 18875  
 18876  @<Declare binary action...@>=
 18877  procedure path_trans(@!p:pointer;@!c:quarterword);
 18878  label exit;
 18879  var @!q:pointer; {list traverser}
 18880  begin set_up_known_trans(c); unstash_cur_exp(p);
 18881  if cur_type=pen_type then
 18882    begin if max_offset(cur_exp)=0 then if tx=0 then if ty=0 then return;
 18883    flush_cur_exp(make_path(cur_exp)); cur_type:=future_pen;
 18884    end;
 18885  q:=cur_exp;
 18886  repeat if left_type(q)<>endpoint then
 18887    trans(q+3,q+4); {that's |left_x| and |left_y|}
 18888  trans(q+1,q+2); {that's |x_coord| and |y_coord|}
 18889  if right_type(q)<>endpoint then
 18890    trans(q+5,q+6); {that's |right_x| and |right_y|}
 18891  q:=link(q);
 18892  until q=cur_exp;
 18893  exit:end;
 18894  
 18895  @ The next simplest transformation procedure applies to edges.
 18896  It is simple primarily because \MF\ doesn't allow very general
 18897  transformations to be made, and because the tricky subroutines
 18898  for edge transformation have already been written.
 18899  
 18900  @<Declare binary action...@>=
 18901  procedure edges_trans(@!p:pointer;@!c:quarterword);
 18902  label exit;
 18903  begin set_up_known_trans(c); unstash_cur_exp(p); cur_edges:=cur_exp;
 18904  if empty_edges(cur_edges) then return; {the empty set is easy to transform}
 18905  if txx=0 then if tyy=0 then
 18906   if txy mod unity=0 then if tyx mod unity=0 then
 18907    begin xy_swap_edges; txx:=txy; tyy:=tyx; txy:=0; tyx:=0;
 18908    if empty_edges(cur_edges) then return;
 18909    end;
 18910  if txy=0 then if tyx=0 then
 18911   if txx mod unity=0 then if tyy mod unity=0 then
 18912    @<Scale the edges, shift them, and |return|@>;
 18913  print_err("That transformation is too hard");
 18914  @.That transformation...@>
 18915  help3("I can apply complicated transformations to paths,")@/
 18916    ("but I can only do integer operations on pictures.")@/
 18917    ("Proceed, and I'll omit the transformation.");
 18918  put_get_error;
 18919  exit:end;
 18920  
 18921  @ @<Scale the edges, shift them, and |return|@>=
 18922  begin if (txx=0)or(tyy=0) then
 18923    begin toss_edges(cur_edges);
 18924    cur_exp:=get_node(edge_header_size); init_edges(cur_exp);
 18925    end
 18926  else  begin if txx<0 then
 18927      begin x_reflect_edges; txx:=-txx;
 18928      end;
 18929    if tyy<0 then
 18930      begin y_reflect_edges; tyy:=-tyy;
 18931      end;
 18932    if txx<>unity then x_scale_edges(txx div unity);
 18933    if tyy<>unity then y_scale_edges(tyy div unity);
 18934    @<Shift the edges by |(tx,ty)|, rounded@>;
 18935    end;
 18936  return;
 18937  end
 18938  
 18939  @ @<Shift the edges...@>=
 18940  tx:=round_unscaled(tx); ty:=round_unscaled(ty);
 18941  if (m_min(cur_edges)+tx<=0)or(m_max(cur_edges)+tx>=8192)or@|
 18942   (n_min(cur_edges)+ty<=0)or(n_max(cur_edges)+ty>=8191)or@|
 18943   (abs(tx)>=4096)or(abs(ty)>=4096) then
 18944    begin print_err("Too far to shift");
 18945  @.Too far to shift@>
 18946    help3("I can't shift the picture as requested---it would")@/
 18947      ("make some coordinates too large or too small.")@/
 18948      ("Proceed, and I'll omit the transformation.");
 18949    put_get_error;
 18950    end
 18951  else  begin if tx<>0 then
 18952      begin if not valid_range(m_offset(cur_edges)-tx) then fix_offset;
 18953      m_min(cur_edges):=m_min(cur_edges)+tx;
 18954      m_max(cur_edges):=m_max(cur_edges)+tx;
 18955      m_offset(cur_edges):=m_offset(cur_edges)-tx;
 18956      last_window_time(cur_edges):=0;
 18957      end;
 18958    if ty<>0 then
 18959      begin n_min(cur_edges):=n_min(cur_edges)+ty;
 18960      n_max(cur_edges):=n_max(cur_edges)+ty;
 18961      n_pos(cur_edges):=n_pos(cur_edges)+ty;
 18962      last_window_time(cur_edges):=0;
 18963      end;
 18964    end
 18965  
 18966  @ The hard cases of transformation occur when big nodes are involved,
 18967  and when some of their components are unknown.
 18968  
 18969  @<Declare binary action...@>=
 18970  @t\4@>@<Declare subroutines needed by |big_trans|@>@;
 18971  procedure big_trans(@!p:pointer;@!c:quarterword);
 18972  label exit;
 18973  var @!q,@!r,@!pp,@!qq:pointer; {list manipulation registers}
 18974  @!s:small_number; {size of a big node}
 18975  begin s:=big_node_size[type(p)]; q:=value(p); r:=q+s;
 18976  repeat r:=r-2;
 18977  if type(r)<>known then @<Transform an unknown big node and |return|@>;
 18978  until r=q;
 18979  @<Transform a known big node@>;
 18980  exit:end; {node |p| will now be recycled by |do_binary|}
 18981  
 18982  @ @<Transform an unknown big node and |return|@>=
 18983  begin set_up_known_trans(c); make_exp_copy(p); r:=value(cur_exp);
 18984  if cur_type=transform_type then
 18985    begin bilin1(yy_part_loc(r),tyy,xy_part_loc(q),tyx,0);
 18986    bilin1(yx_part_loc(r),tyy,xx_part_loc(q),tyx,0);
 18987    bilin1(xy_part_loc(r),txx,yy_part_loc(q),txy,0);
 18988    bilin1(xx_part_loc(r),txx,yx_part_loc(q),txy,0);
 18989    end;
 18990  bilin1(y_part_loc(r),tyy,x_part_loc(q),tyx,ty);
 18991  bilin1(x_part_loc(r),txx,y_part_loc(q),txy,tx);
 18992  return;
 18993  end
 18994  
 18995  @ Let |p| point to a two-word value field inside a big node of |cur_exp|,
 18996  and let |q| point to a another value field. The |bilin1| procedure
 18997  replaces |p| by $p\cdot t+q\cdot u+\delta$.
 18998  
 18999  @<Declare subroutines needed by |big_trans|@>=
 19000  procedure bilin1(@!p:pointer;@!t:scaled;@!q:pointer;@!u,@!delta:scaled);
 19001  var @!r:pointer; {list traverser}
 19002  begin if t<>unity then dep_mult(p,t,true);
 19003  if u<>0 then
 19004    if type(q)=known then delta:=delta+take_scaled(value(q),u)
 19005    else  begin @<Ensure that |type(p)=proto_dependent|@>;
 19006      dep_list(p):=p_plus_fq(dep_list(p),u,dep_list(q),proto_dependent,type(q));
 19007      end;
 19008  if type(p)=known then value(p):=value(p)+delta
 19009  else  begin r:=dep_list(p);
 19010    while info(r)<>null do r:=link(r);
 19011    delta:=value(r)+delta;
 19012    if r<>dep_list(p) then value(r):=delta
 19013    else  begin recycle_value(p); type(p):=known; value(p):=delta;
 19014      end;
 19015    end;
 19016  if fix_needed then fix_dependencies;
 19017  end;
 19018  
 19019  @ @<Ensure that |type(p)=proto_dependent|@>=
 19020  if type(p)<>proto_dependent then
 19021    begin if type(p)=known then new_dep(p,const_dependency(value(p)))
 19022    else dep_list(p):=p_times_v(dep_list(p),unity,dependent,proto_dependent,true);
 19023    type(p):=proto_dependent;
 19024    end
 19025  
 19026  @ @<Transform a known big node@>=
 19027  set_up_trans(c);
 19028  if cur_type=known then @<Transform known by known@>
 19029  else  begin pp:=stash_cur_exp; qq:=value(pp);
 19030    make_exp_copy(p); r:=value(cur_exp);
 19031    if cur_type=transform_type then
 19032      begin bilin2(yy_part_loc(r),yy_part_loc(qq),
 19033        value(xy_part_loc(q)),yx_part_loc(qq),null);
 19034      bilin2(yx_part_loc(r),yy_part_loc(qq),
 19035        value(xx_part_loc(q)),yx_part_loc(qq),null);
 19036      bilin2(xy_part_loc(r),xx_part_loc(qq),
 19037        value(yy_part_loc(q)),xy_part_loc(qq),null);
 19038      bilin2(xx_part_loc(r),xx_part_loc(qq),
 19039        value(yx_part_loc(q)),xy_part_loc(qq),null);
 19040      end;
 19041    bilin2(y_part_loc(r),yy_part_loc(qq),
 19042      value(x_part_loc(q)),yx_part_loc(qq),y_part_loc(qq));
 19043    bilin2(x_part_loc(r),xx_part_loc(qq),
 19044      value(y_part_loc(q)),xy_part_loc(qq),x_part_loc(qq));
 19045    recycle_value(pp); free_node(pp,value_node_size);
 19046    end;
 19047  
 19048  @ Let |p| be a |proto_dependent| value whose dependency list ends
 19049  at |dep_final|. The following procedure adds |v| times another
 19050  numeric quantity to~|p|.
 19051  
 19052  @<Declare subroutines needed by |big_trans|@>=
 19053  procedure add_mult_dep(@!p:pointer;@!v:scaled;@!r:pointer);
 19054  begin if type(r)=known then
 19055    value(dep_final):=value(dep_final)+take_scaled(value(r),v)
 19056  else  begin dep_list(p):=
 19057     p_plus_fq(dep_list(p),v,dep_list(r),proto_dependent,type(r));
 19058    if fix_needed then fix_dependencies;
 19059    end;
 19060  end;
 19061  
 19062  @ The |bilin2| procedure is something like |bilin1|, but with known
 19063  and unknown quantities reversed. Parameter |p| points to a value field
 19064  within the big node for |cur_exp|; and |type(p)=known|. Parameters
 19065  |t| and~|u| point to value fields elsewhere; so does parameter~|q|,
 19066  unless it is |null| (which stands for zero). Location~|p| will be
 19067  replaced by $p\cdot t+v\cdot u+q$.
 19068  
 19069  @<Declare subroutines needed by |big_trans|@>=
 19070  procedure bilin2(@!p,@!t:pointer;@!v:scaled;@!u,@!q:pointer);
 19071  var @!vv:scaled; {temporary storage for |value(p)|}
 19072  begin vv:=value(p); type(p):=proto_dependent;
 19073  new_dep(p,const_dependency(0)); {this sets |dep_final|}
 19074  if vv<>0 then add_mult_dep(p,vv,t); {|dep_final| doesn't change}
 19075  if v<>0 then add_mult_dep(p,v,u);
 19076  if q<>null then add_mult_dep(p,unity,q);
 19077  if dep_list(p)=dep_final then
 19078    begin vv:=value(dep_final); recycle_value(p);
 19079    type(p):=known; value(p):=vv;
 19080    end;
 19081  end;
 19082  
 19083  @ @<Transform known by known@>=
 19084  begin make_exp_copy(p); r:=value(cur_exp);
 19085  if cur_type=transform_type then
 19086    begin bilin3(yy_part_loc(r),tyy,value(xy_part_loc(q)),tyx,0);
 19087    bilin3(yx_part_loc(r),tyy,value(xx_part_loc(q)),tyx,0);
 19088    bilin3(xy_part_loc(r),txx,value(yy_part_loc(q)),txy,0);
 19089    bilin3(xx_part_loc(r),txx,value(yx_part_loc(q)),txy,0);
 19090    end;
 19091  bilin3(y_part_loc(r),tyy,value(x_part_loc(q)),tyx,ty);
 19092  bilin3(x_part_loc(r),txx,value(y_part_loc(q)),txy,tx);
 19093  end
 19094  
 19095  @ Finally, in |bilin3| everything is |known|.
 19096  
 19097  @<Declare subroutines needed by |big_trans|@>=
 19098  procedure bilin3(@!p:pointer;@!t,@!v,@!u,@!delta:scaled);
 19099  begin if t<>unity then delta:=delta+take_scaled(value(p),t)
 19100  else delta:=delta+value(p);
 19101  if u<>0 then value(p):=delta+take_scaled(v,u)
 19102  else value(p):=delta;
 19103  end;
 19104  
 19105  @ @<Additional cases of binary operators@>=
 19106  concatenate: if (cur_type=string_type)and(type(p)=string_type) then cat(p)
 19107    else bad_binary(p,concatenate);
 19108  substring_of: if nice_pair(p,type(p))and(cur_type=string_type) then
 19109      chop_string(value(p))
 19110    else bad_binary(p,substring_of);
 19111  subpath_of: begin if cur_type=pair_type then pair_to_path;
 19112    if nice_pair(p,type(p))and(cur_type=path_type) then
 19113      chop_path(value(p))
 19114    else bad_binary(p,subpath_of);
 19115    end;
 19116  
 19117  @ @<Declare binary action...@>=
 19118  procedure cat(@!p:pointer);
 19119  var @!a,@!b:str_number; {the strings being concatenated}
 19120  @!k:pool_pointer; {index into |str_pool|}
 19121  begin a:=value(p); b:=cur_exp; str_room(length(a)+length(b));
 19122  for k:=str_start[a] to str_start[a+1]-1 do append_char(so(str_pool[k]));
 19123  for k:=str_start[b] to str_start[b+1]-1 do append_char(so(str_pool[k]));
 19124  cur_exp:=make_string; delete_str_ref(b);
 19125  end;
 19126  
 19127  @ @<Declare binary action...@>=
 19128  procedure chop_string(@!p:pointer);
 19129  var @!a,@!b:integer; {start and stop points}
 19130  @!l:integer; {length of the original string}
 19131  @!k:integer; {runs from |a| to |b|}
 19132  @!s:str_number; {the original string}
 19133  @!reversed:boolean; {was |a>b|?}
 19134  begin a:=round_unscaled(value(x_part_loc(p)));
 19135  b:=round_unscaled(value(y_part_loc(p)));
 19136  if a<=b then reversed:=false
 19137  else  begin reversed:=true; k:=a; a:=b; b:=k;
 19138    end;
 19139  s:=cur_exp; l:=length(s);
 19140  if a<0 then
 19141    begin a:=0;
 19142    if b<0 then b:=0;
 19143    end;
 19144  if b>l then
 19145    begin b:=l;
 19146    if a>l then a:=l;
 19147    end;
 19148  str_room(b-a);
 19149  if reversed then
 19150    for k:=str_start[s]+b-1 downto str_start[s]+a do append_char(so(str_pool[k]))
 19151  else for k:=str_start[s]+a to str_start[s]+b-1 do append_char(so(str_pool[k]));
 19152  cur_exp:=make_string; delete_str_ref(s);
 19153  end;
 19154  
 19155  @ @<Declare binary action...@>=
 19156  procedure chop_path(@!p:pointer);
 19157  var @!q:pointer; {a knot in the original path}
 19158  @!pp,@!qq,@!rr,@!ss:pointer; {link variables for copies of path nodes}
 19159  @!a,@!b,@!k,@!l:scaled; {indices for chopping}
 19160  @!reversed:boolean; {was |a>b|?}
 19161  begin l:=path_length; a:=value(x_part_loc(p)); b:=value(y_part_loc(p));
 19162  if a<=b then reversed:=false
 19163  else  begin reversed:=true; k:=a; a:=b; b:=k;
 19164    end;
 19165  @<Dispense with the cases |a<0| and/or |b>l|@>;
 19166  q:=cur_exp;
 19167  while a>=unity do
 19168    begin q:=link(q); a:=a-unity; b:=b-unity;
 19169    end;
 19170  if b=a then @<Construct a path from |pp| to |qq| of length zero@>
 19171  else @<Construct a path from |pp| to |qq| of length $\lceil b\rceil$@>;
 19172  left_type(pp):=endpoint; right_type(qq):=endpoint; link(qq):=pp;
 19173  toss_knot_list(cur_exp);
 19174  if reversed then
 19175    begin cur_exp:=link(htap_ypoc(pp)); toss_knot_list(pp);
 19176    end
 19177  else cur_exp:=pp;
 19178  end;
 19179  
 19180  @ @<Dispense with the cases |a<0| and/or |b>l|@>=
 19181  if a<0 then
 19182    if left_type(cur_exp)=endpoint then
 19183      begin a:=0; if b<0 then b:=0;
 19184      end
 19185    else  repeat a:=a+l; b:=b+l;
 19186      until a>=0; {a cycle always has length |l>0|}
 19187  if b>l then if left_type(cur_exp)=endpoint then
 19188      begin b:=l; if a>l then a:=l;
 19189      end
 19190    else while a>=l do
 19191      begin a:=a-l; b:=b-l;
 19192      end
 19193  
 19194  @ @<Construct a path from |pp| to |qq| of length $\lceil b\rceil$@>=
 19195  begin pp:=copy_knot(q); qq:=pp;
 19196  repeat q:=link(q); rr:=qq; qq:=copy_knot(q); link(rr):=qq; b:=b-unity;
 19197  until b<=0;
 19198  if a>0 then
 19199    begin ss:=pp; pp:=link(pp);
 19200    split_cubic(ss,a*@'10000,x_coord(pp),y_coord(pp)); pp:=link(ss);
 19201    free_node(ss,knot_node_size);
 19202    if rr=ss then
 19203      begin b:=make_scaled(b,unity-a); rr:=pp;
 19204      end;
 19205    end;
 19206  if b<0 then
 19207    begin split_cubic(rr,(b+unity)*@'10000,x_coord(qq),y_coord(qq));
 19208    free_node(qq,knot_node_size);
 19209    qq:=link(rr);
 19210    end;
 19211  end
 19212  
 19213  @ @<Construct a path from |pp| to |qq| of length zero@>=
 19214  begin if a>0 then
 19215    begin qq:=link(q);
 19216    split_cubic(q,a*@'10000,x_coord(qq),y_coord(qq)); q:=link(q);
 19217    end;
 19218  pp:=copy_knot(q); qq:=pp;
 19219  end
 19220  
 19221  @ The |pair_value| routine changes the current expression to a
 19222  given ordered pair of values.
 19223  
 19224  @<Declare binary action...@>=
 19225  procedure pair_value(@!x,@!y:scaled);
 19226  var @!p:pointer; {a pair node}
 19227  begin p:=get_node(value_node_size); flush_cur_exp(p); cur_type:=pair_type;
 19228  type(p):=pair_type; name_type(p):=capsule; init_big_node(p);
 19229  p:=value(p);@/
 19230  type(x_part_loc(p)):=known; value(x_part_loc(p)):=x;@/
 19231  type(y_part_loc(p)):=known; value(y_part_loc(p)):=y;@/
 19232  end;
 19233  
 19234  @ @<Additional cases of binary operators@>=
 19235  point_of,precontrol_of,postcontrol_of: begin if cur_type=pair_type then
 19236       pair_to_path;
 19237    if (cur_type=path_type)and(type(p)=known) then
 19238      find_point(value(p),c)
 19239    else bad_binary(p,c);
 19240    end;
 19241  pen_offset_of: begin if cur_type=future_pen then materialize_pen;
 19242    if (cur_type=pen_type)and nice_pair(p,type(p)) then
 19243      set_up_offset(value(p))
 19244    else bad_binary(p,pen_offset_of);
 19245    end;
 19246  direction_time_of: begin if cur_type=pair_type then pair_to_path;
 19247    if (cur_type=path_type)and nice_pair(p,type(p)) then
 19248      set_up_direction_time(value(p))
 19249    else bad_binary(p,direction_time_of);
 19250    end;
 19251  
 19252  @ @<Declare binary action...@>=
 19253  procedure set_up_offset(@!p:pointer);
 19254  begin find_offset(value(x_part_loc(p)),value(y_part_loc(p)),cur_exp);
 19255  pair_value(cur_x,cur_y);
 19256  end;
 19257  @#
 19258  procedure set_up_direction_time(@!p:pointer);
 19259  begin flush_cur_exp(find_direction_time(value(x_part_loc(p)),
 19260    value(y_part_loc(p)),cur_exp));
 19261  end;
 19262  
 19263  @ @<Declare binary action...@>=
 19264  procedure find_point(@!v:scaled;@!c:quarterword);
 19265  var @!p:pointer; {the path}
 19266  @!n:scaled; {its length}
 19267  @!q:pointer; {successor of |p|}
 19268  begin p:=cur_exp;@/
 19269  if left_type(p)=endpoint then n:=-unity@+else n:=0;
 19270  repeat p:=link(p); n:=n+unity;
 19271  until p=cur_exp;
 19272  if n=0 then v:=0
 19273  else if v<0 then
 19274    if left_type(p)=endpoint then v:=0
 19275    else v:=n-1-((-v-1) mod n)
 19276  else if v>n then
 19277    if left_type(p)=endpoint then v:=n
 19278    else v:=v mod n;
 19279  p:=cur_exp;
 19280  while v>=unity do
 19281    begin p:=link(p); v:=v-unity;
 19282    end;
 19283  if v<>0 then @<Insert a fractional node by splitting the cubic@>;
 19284  @<Set the current expression to the desired path coordinates@>;
 19285  end;
 19286  
 19287  @ @<Insert a fractional node...@>=
 19288  begin q:=link(p); split_cubic(p,v*@'10000,x_coord(q),y_coord(q)); p:=link(p);
 19289  end
 19290  
 19291  @ @<Set the current expression to the desired path coordinates...@>=
 19292  case c of
 19293  point_of: pair_value(x_coord(p),y_coord(p));
 19294  precontrol_of: if left_type(p)=endpoint then pair_value(x_coord(p),y_coord(p))
 19295    else pair_value(left_x(p),left_y(p));
 19296  postcontrol_of: if right_type(p)=endpoint then pair_value(x_coord(p),y_coord(p))
 19297    else pair_value(right_x(p),right_y(p));
 19298  end {there are no other cases}
 19299  
 19300  @ @<Additional cases of bin...@>=
 19301  intersect: begin if type(p)=pair_type then
 19302      begin q:=stash_cur_exp; unstash_cur_exp(p);
 19303      pair_to_path; p:=stash_cur_exp; unstash_cur_exp(q);
 19304      end;
 19305    if cur_type=pair_type then pair_to_path;
 19306    if (cur_type=path_type)and(type(p)=path_type) then
 19307      begin path_intersection(value(p),cur_exp);
 19308      pair_value(cur_t,cur_tt);
 19309      end
 19310    else bad_binary(p,intersect);
 19311    end;
 19312  
 19313  @* \[43] Statements and commands.
 19314  The chief executive of \MF\ is the |do_statement| routine, which
 19315  contains the master switch that causes all the various pieces of \MF\
 19316  to do their things, in the right order.
 19317  
 19318  In a sense, this is the grand climax of the program: It applies all the
 19319  tools that we have worked so hard to construct. In another sense, this is
 19320  the messiest part of the program: It necessarily refers to other pieces
 19321  of code all over the place, so that a person can't fully understand what is
 19322  going on without paging back and forth to be reminded of conventions that
 19323  are defined elsewhere. We are now at the hub of the web.
 19324  
 19325  The structure of |do_statement| itself is quite simple.  The first token
 19326  of the statement is fetched using |get_x_next|.  If it can be the first
 19327  token of an expression, we look for an equation, an assignment, or a
 19328  title. Otherwise we use a \&{case} construction to branch at high speed to
 19329  the appropriate routine for various and sundry other types of commands,
 19330  each of which has an ``action procedure'' that does the necessary work.
 19331  
 19332  The program uses the fact that
 19333  $$\hbox{|min_primary_command=max_statement_command=type_name|}$$
 19334  to interpret a statement that starts with, e.g., `\&{string}',
 19335  as a type declaration rather than a boolean expression.
 19336  
 19337  @p @t\4@>@<Declare generic font output procedures@>@;
 19338  @t\4@>@<Declare action procedures for use by |do_statement|@>@;
 19339  procedure do_statement; {governs \MF's activities}
 19340  begin cur_type:=vacuous; get_x_next;
 19341  if cur_cmd>max_primary_command then @<Worry about bad statement@>
 19342  else if cur_cmd>max_statement_command then
 19343    @<Do an equation, assignment, title, or
 19344     `$\langle\,$expression$\,\rangle\,$\&{endgroup}'@>
 19345  else @<Do a statement that doesn't begin with an expression@>;
 19346  if cur_cmd<semicolon then
 19347    @<Flush unparsable junk that was found after the statement@>;
 19348  error_count:=0;
 19349  end;
 19350  
 19351  @ The only command codes |>max_primary_command| that can be present
 19352  at the beginning of a statement are |semicolon| and higher; these
 19353  occur when the statement is null.
 19354  
 19355  @<Worry about bad statement@>=
 19356  begin if cur_cmd<semicolon then
 19357    begin print_err("A statement can't begin with `");
 19358  @.A statement can't begin with x@>
 19359    print_cmd_mod(cur_cmd,cur_mod); print_char("'");
 19360    help5("I was looking for the beginning of a new statement.")@/
 19361      ("If you just proceed without changing anything, I'll ignore")@/
 19362      ("everything up to the next `;'. Please insert a semicolon")@/
 19363      ("now in front of anything that you don't want me to delete.")@/
 19364      ("(See Chapter 27 of The METAFONTbook for an example.)");@/
 19365  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 19366    back_error; get_x_next;
 19367    end;
 19368  end
 19369  
 19370  @ The help message printed here says that everything is flushed up to
 19371  a semicolon, but actually the commands |end_group| and |stop| will
 19372  also terminate a statement.
 19373  
 19374  @<Flush unparsable junk that was found after the statement@>=
 19375  begin print_err("Extra tokens will be flushed");
 19376  @.Extra tokens will be flushed@>
 19377  help6("I've just read as much of that statement as I could fathom,")@/
 19378  ("so a semicolon should have been next. It's very puzzling...")@/
 19379  ("but I'll try to get myself back together, by ignoring")@/
 19380  ("everything up to the next `;'. Please insert a semicolon")@/
 19381  ("now in front of anything that you don't want me to delete.")@/
 19382  ("(See Chapter 27 of The METAFONTbook for an example.)");@/
 19383  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 19384  back_error; scanner_status:=flushing;
 19385  repeat get_next;
 19386  @<Decrease the string reference count...@>;
 19387  until end_of_statement; {|cur_cmd=semicolon|, |end_group|, or |stop|}
 19388  scanner_status:=normal;
 19389  end
 19390  
 19391  @ If |do_statement| ends with |cur_cmd=end_group|, we should have
 19392  |cur_type=vacuous| unless the statement was simply an expression;
 19393  in the latter case, |cur_type| and |cur_exp| should represent that
 19394  expression.
 19395  
 19396  @<Do a statement that doesn't...@>=
 19397  begin if internal[tracing_commands]>0 then show_cur_cmd_mod;
 19398  case cur_cmd of
 19399  type_name:do_type_declaration;
 19400  macro_def:if cur_mod>var_def then make_op_def
 19401    else if cur_mod>end_def then scan_def;
 19402  @t\4@>@<Cases of |do_statement| that invoke particular commands@>@;
 19403  end; {there are no other cases}
 19404  cur_type:=vacuous;
 19405  end
 19406  
 19407  @ The most important statements begin with expressions.
 19408  
 19409  @<Do an equation, assignment, title, or...@>=
 19410  begin var_flag:=assignment; scan_expression;
 19411  if cur_cmd<end_group then
 19412    begin if cur_cmd=equals then do_equation
 19413    else if cur_cmd=assignment then do_assignment
 19414    else if cur_type=string_type then @<Do a title@>
 19415    else if cur_type<>vacuous then
 19416      begin exp_err("Isolated expression");
 19417  @.Isolated expression@>
 19418      help3("I couldn't find an `=' or `:=' after the")@/
 19419        ("expression that is shown above this error message,")@/
 19420        ("so I guess I'll just ignore it and carry on.");
 19421      put_get_error;
 19422      end;
 19423    flush_cur_exp(0); cur_type:=vacuous;
 19424    end;
 19425  end
 19426  
 19427  @ @<Do a title@>=
 19428  begin if internal[tracing_titles]>0 then
 19429    begin print_nl(""); slow_print(cur_exp); update_terminal;
 19430    end;
 19431  if internal[proofing]>0 then
 19432    @<Send the current expression as a title to the output file@>;
 19433  end
 19434  
 19435  @ Equations and assignments are performed by the pair of mutually recursive
 19436  @^recursion@>
 19437  routines |do_equation| and |do_assignment|. These routines are called when
 19438  |cur_cmd=equals| and when |cur_cmd=assignment|, respectively; the left-hand
 19439  side is in |cur_type| and |cur_exp|, while the right-hand side is yet
 19440  to be scanned. After the routines are finished, |cur_type| and |cur_exp|
 19441  will be equal to the right-hand side (which will normally be equal
 19442  to the left-hand side).
 19443  
 19444  @<Declare action procedures for use by |do_statement|@>=
 19445  @t\4@>@<Declare the procedure called |try_eq|@>@;
 19446  @t\4@>@<Declare the procedure called |make_eq|@>@;
 19447  procedure@?do_assignment; forward;@t\2@>@/
 19448  procedure do_equation;
 19449  var @!lhs:pointer; {capsule for the left-hand side}
 19450  @!p:pointer; {temporary register}
 19451  begin lhs:=stash_cur_exp; get_x_next; var_flag:=assignment; scan_expression;
 19452  if cur_cmd=equals then do_equation
 19453  else if cur_cmd=assignment then do_assignment;
 19454  if internal[tracing_commands]>two then @<Trace the current equation@>;
 19455  if cur_type=unknown_path then if type(lhs)=pair_type then
 19456    begin p:=stash_cur_exp; unstash_cur_exp(lhs); lhs:=p;
 19457    end; {in this case |make_eq| will change the pair to a path}
 19458  make_eq(lhs); {equate |lhs| to |(cur_type,cur_exp)|}
 19459  end;
 19460  
 19461  @ And |do_assignment| is similar to |do_equation|:
 19462  
 19463  @<Declare action procedures for use by |do_statement|@>=
 19464  procedure do_assignment;
 19465  var @!lhs:pointer; {token list for the left-hand side}
 19466  @!p:pointer; {where the left-hand value is stored}
 19467  @!q:pointer; {temporary capsule for the right-hand value}
 19468  begin if cur_type<>token_list then
 19469    begin exp_err("Improper `:=' will be changed to `='");
 19470  @.Improper `:='@>
 19471    help2("I didn't find a variable name at the left of the `:=',")@/
 19472      ("so I'm going to pretend that you said `=' instead.");@/
 19473    error; do_equation;
 19474    end
 19475  else  begin lhs:=cur_exp; cur_type:=vacuous;@/
 19476    get_x_next; var_flag:=assignment; scan_expression;
 19477    if cur_cmd=equals then do_equation
 19478    else if cur_cmd=assignment then do_assignment;
 19479    if internal[tracing_commands]>two then @<Trace the current assignment@>;
 19480    if info(lhs)>hash_end then
 19481      @<Assign the current expression to an internal variable@>
 19482    else @<Assign the current expression to the variable |lhs|@>;
 19483    flush_node_list(lhs);
 19484    end;
 19485  end;
 19486  
 19487  @ @<Trace the current equation@>=
 19488  begin begin_diagnostic; print_nl("{("); print_exp(lhs,0);
 19489  print(")=("); print_exp(null,0); print(")}"); end_diagnostic(false);
 19490  end
 19491  
 19492  @ @<Trace the current assignment@>=
 19493  begin begin_diagnostic; print_nl("{");
 19494  if info(lhs)>hash_end then slow_print(int_name[info(lhs)-(hash_end)])
 19495  else show_token_list(lhs,null,1000,0);
 19496  print(":="); print_exp(null,0); print_char("}"); end_diagnostic(false);
 19497  end
 19498  
 19499  @ @<Assign the current expression to an internal variable@>=
 19500  if cur_type=known then internal[info(lhs)-(hash_end)]:=cur_exp
 19501  else  begin exp_err("Internal quantity `");
 19502  @.Internal quantity...@>
 19503    slow_print(int_name[info(lhs)-(hash_end)]);
 19504    print("' must receive a known value");
 19505    help2("I can't set an internal quantity to anything but a known")@/
 19506      ("numeric value, so I'll have to ignore this assignment.");
 19507    put_get_error;
 19508    end
 19509  
 19510  @ @<Assign the current expression to the variable |lhs|@>=
 19511  begin p:=find_variable(lhs);
 19512  if p<>null then
 19513    begin q:=stash_cur_exp; cur_type:=und_type(p); recycle_value(p);
 19514    type(p):=cur_type; value(p):=null; make_exp_copy(p);
 19515    p:=stash_cur_exp; unstash_cur_exp(q); make_eq(p);
 19516    end
 19517  else  begin obliterated(lhs); put_get_error;
 19518    end;
 19519  end
 19520  
 19521  
 19522  @ And now we get to the nitty-gritty. The |make_eq| procedure is given
 19523  a pointer to a capsule that is to be equated to the current expression.
 19524  
 19525  @<Declare the procedure called |make_eq|@>=
 19526  procedure make_eq(@!lhs:pointer);
 19527  label restart,done, not_found;
 19528  var @!t:small_number; {type of the left-hand side}
 19529  @!v:integer; {value of the left-hand side}
 19530  @!p,@!q:pointer; {pointers inside of big nodes}
 19531  begin restart: t:=type(lhs);
 19532  if t<=pair_type then v:=value(lhs);
 19533  case t of
 19534  @t\4@>@<For each type |t|, make an equation and |goto done| unless |cur_type|
 19535    is incompatible with~|t|@>@;
 19536  end; {all cases have been listed}
 19537  @<Announce that the equation cannot be performed@>;
 19538  done:check_arith; recycle_value(lhs); free_node(lhs,value_node_size);
 19539  end;
 19540  
 19541  @ @<Announce that the equation cannot be performed@>=
 19542  disp_err(lhs,""); exp_err("Equation cannot be performed (");
 19543  @.Equation cannot be performed@>
 19544  if type(lhs)<=pair_type then print_type(type(lhs))@+else print("numeric");
 19545  print_char("=");
 19546  if cur_type<=pair_type then print_type(cur_type)@+else print("numeric");
 19547  print_char(")");@/
 19548  help2("I'm sorry, but I don't know how to make such things equal.")@/
 19549    ("(See the two expressions just above the error message.)");
 19550  put_get_error
 19551  
 19552  @ @<For each type |t|, make an equation and |goto done| unless...@>=
 19553  boolean_type,string_type,pen_type,path_type,picture_type:
 19554    if cur_type=t+unknown_tag then
 19555      begin nonlinear_eq(v,cur_exp,false); unstash_cur_exp(cur_exp); goto done;
 19556      end
 19557    else if cur_type=t then
 19558      @<Report redundant or inconsistent equation and |goto done|@>;
 19559  unknown_types:if cur_type=t-unknown_tag then
 19560      begin nonlinear_eq(cur_exp,lhs,true); goto done;
 19561      end
 19562    else if cur_type=t then
 19563      begin ring_merge(lhs,cur_exp); goto done;
 19564      end
 19565    else if cur_type=pair_type then if t=unknown_path then
 19566      begin pair_to_path; goto restart;
 19567      end;
 19568  transform_type,pair_type:if cur_type=t then
 19569      @<Do multiple equations and |goto done|@>;
 19570  known,dependent,proto_dependent,independent:if cur_type>=known then
 19571      begin try_eq(lhs,null); goto done;
 19572      end;
 19573  vacuous:do_nothing;
 19574  
 19575  @ @<Report redundant or inconsistent equation and |goto done|@>=
 19576  begin if cur_type<=string_type then
 19577    begin if cur_type=string_type then
 19578      begin if str_vs_str(v,cur_exp)<>0 then goto not_found;
 19579      end
 19580    else if v<>cur_exp then goto not_found;
 19581    @<Exclaim about a redundant equation@>; goto done;
 19582    end;
 19583  print_err("Redundant or inconsistent equation");
 19584  @.Redundant or inconsistent equation@>
 19585  help2("An equation between already-known quantities can't help.")@/
 19586    ("But don't worry; continue and I'll just ignore it.");
 19587  put_get_error; goto done;
 19588  not_found: print_err("Inconsistent equation");
 19589  @.Inconsistent equation@>
 19590  help2("The equation I just read contradicts what was said before.")@/
 19591    ("But don't worry; continue and I'll just ignore it.");
 19592  put_get_error; goto done;
 19593  end
 19594  
 19595  @ @<Do multiple equations and |goto done|@>=
 19596  begin p:=v+big_node_size[t]; q:=value(cur_exp)+big_node_size[t];
 19597  repeat p:=p-2; q:=q-2; try_eq(p,q);
 19598  until p=v;
 19599  goto done;
 19600  end
 19601  
 19602  @ The first argument to |try_eq| is the location of a value node
 19603  in a capsule that will soon be recycled. The second argument is
 19604  either a location within a pair or transform node pointed to by
 19605  |cur_exp|, or it is |null| (which means that |cur_exp| itself
 19606  serves as the second argument). The idea is to leave |cur_exp| unchanged,
 19607  but to equate the two operands.
 19608  
 19609  @<Declare the procedure called |try_eq|@>=
 19610  procedure try_eq(@!l,@!r:pointer);
 19611  label done,done1;
 19612  var @!p:pointer; {dependency list for right operand minus left operand}
 19613  @!t:known..independent; {the type of list |p|}
 19614  @!q:pointer; {the constant term of |p| is here}
 19615  @!pp:pointer; {dependency list for right operand}
 19616  @!tt:dependent..independent; {the type of list |pp|}
 19617  @!copied:boolean; {have we copied a list that ought to be recycled?}
 19618  begin @<Remove the left operand from its container, negate it, and
 19619    put it into dependency list~|p| with constant term~|q|@>;
 19620  @<Add the right operand to list |p|@>;
 19621  if info(p)=null then @<Deal with redundant or inconsistent equation@>
 19622  else  begin linear_eq(p,t);
 19623    if r=null then if cur_type<>known then if type(cur_exp)=known then
 19624      begin pp:=cur_exp; cur_exp:=value(cur_exp); cur_type:=known;
 19625      free_node(pp,value_node_size);
 19626      end;
 19627    end;
 19628  end;
 19629  
 19630  @ @<Remove the left operand from its container, negate it, and...@>=
 19631  t:=type(l);
 19632  if t=known then
 19633    begin t:=dependent; p:=const_dependency(-value(l)); q:=p;
 19634    end
 19635  else if t=independent then
 19636    begin t:=dependent; p:=single_dependency(l); negate(value(p));
 19637    q:=dep_final;
 19638    end
 19639  else  begin p:=dep_list(l); q:=p;
 19640    loop@+  begin negate(value(q));
 19641      if info(q)=null then goto done;
 19642      q:=link(q);
 19643      end;
 19644   done:  link(prev_dep(l)):=link(q); prev_dep(link(q)):=prev_dep(l);
 19645    type(l):=known;
 19646    end
 19647  
 19648  @ @<Deal with redundant or inconsistent equation@>=
 19649  begin if abs(value(p))>64 then {off by .001 or more}
 19650    begin print_err("Inconsistent equation");@/
 19651  @.Inconsistent equation@>
 19652    print(" (off by "); print_scaled(value(p)); print_char(")");
 19653    help2("The equation I just read contradicts what was said before.")@/
 19654      ("But don't worry; continue and I'll just ignore it.");
 19655    put_get_error;
 19656    end
 19657  else if r=null then @<Exclaim about a redundant equation@>;
 19658  free_node(p,dep_node_size);
 19659  end
 19660  
 19661  @ @<Add the right operand to list |p|@>=
 19662  if r=null then
 19663    if cur_type=known then
 19664      begin value(q):=value(q)+cur_exp; goto done1;
 19665      end
 19666    else  begin tt:=cur_type;
 19667      if tt=independent then pp:=single_dependency(cur_exp)
 19668      else pp:=dep_list(cur_exp);
 19669      end
 19670  else  if type(r)=known then
 19671      begin value(q):=value(q)+value(r); goto done1;
 19672      end
 19673    else  begin tt:=type(r);
 19674      if tt=independent then pp:=single_dependency(r)
 19675      else pp:=dep_list(r);
 19676      end;
 19677  if tt<>independent then copied:=false
 19678  else  begin copied:=true; tt:=dependent;
 19679    end;
 19680  @<Add dependency list |pp| of type |tt| to dependency list~|p| of type~|t|@>;
 19681  if copied then flush_node_list(pp);
 19682  done1:
 19683  
 19684  @ @<Add dependency list |pp| of type |tt| to dependency list~|p| of type~|t|@>=
 19685  watch_coefs:=false;
 19686  if t=tt then p:=p_plus_q(p,pp,t)
 19687  else if t=proto_dependent then
 19688    p:=p_plus_fq(p,unity,pp,proto_dependent,dependent)
 19689  else  begin q:=p;
 19690    while info(q)<>null do
 19691      begin value(q):=round_fraction(value(q)); q:=link(q);
 19692      end;
 19693    t:=proto_dependent; p:=p_plus_q(p,pp,t);
 19694    end;
 19695  watch_coefs:=true;
 19696  
 19697  @ Our next goal is to process type declarations. For this purpose it's
 19698  convenient to have a procedure that scans a $\langle\,$declared
 19699  variable$\,\rangle$ and returns the corresponding token list. After the
 19700  following procedure has acted, the token after the declared variable
 19701  will have been scanned, so it will appear in |cur_cmd|, |cur_mod|,
 19702  and~|cur_sym|.
 19703  
 19704  @<Declare the function called |scan_declared_variable|@>=
 19705  function scan_declared_variable:pointer;
 19706  label done;
 19707  var @!x:pointer; {hash address of the variable's root}
 19708  @!h,@!t:pointer; {head and tail of the token list to be returned}
 19709  @!l:pointer; {hash address of left bracket}
 19710  begin get_symbol; x:=cur_sym;
 19711  if cur_cmd<>tag_token then clear_symbol(x,false);
 19712  h:=get_avail; info(h):=x; t:=h;@/
 19713  loop@+  begin get_x_next;
 19714    if cur_sym=0 then goto done;
 19715    if cur_cmd<>tag_token then if cur_cmd<>internal_quantity then
 19716      if cur_cmd=left_bracket then @<Descend past a collective subscript@>
 19717      else goto done;
 19718    link(t):=get_avail; t:=link(t); info(t):=cur_sym;
 19719    end;
 19720  done: if eq_type(x) mod outer_tag<>tag_token then clear_symbol(x,false);
 19721  if equiv(x)=null then new_root(x);
 19722  scan_declared_variable:=h;
 19723  end;
 19724  
 19725  @ If the subscript isn't collective, we don't accept it as part of the
 19726  declared variable.
 19727  
 19728  @<Descend past a collective subscript@>=
 19729  begin l:=cur_sym; get_x_next;
 19730  if cur_cmd<>right_bracket then
 19731    begin back_input; cur_sym:=l; cur_cmd:=left_bracket; goto done;
 19732    end
 19733  else cur_sym:=collective_subscript;
 19734  end
 19735  
 19736  @ Type declarations are introduced by the following primitive operations.
 19737  
 19738  @<Put each...@>=
 19739  primitive("numeric",type_name,numeric_type);@/
 19740  @!@:numeric_}{\&{numeric} primitive@>
 19741  primitive("string",type_name,string_type);@/
 19742  @!@:string_}{\&{string} primitive@>
 19743  primitive("boolean",type_name,boolean_type);@/
 19744  @!@:boolean_}{\&{boolean} primitive@>
 19745  primitive("path",type_name,path_type);@/
 19746  @!@:path_}{\&{path} primitive@>
 19747  primitive("pen",type_name,pen_type);@/
 19748  @!@:pen_}{\&{pen} primitive@>
 19749  primitive("picture",type_name,picture_type);@/
 19750  @!@:picture_}{\&{picture} primitive@>
 19751  primitive("transform",type_name,transform_type);@/
 19752  @!@:transform_}{\&{transform} primitive@>
 19753  primitive("pair",type_name,pair_type);@/
 19754  @!@:pair_}{\&{pair} primitive@>
 19755  
 19756  @ @<Cases of |print_cmd...@>=
 19757  type_name: print_type(m);
 19758  
 19759  @ Now we are ready to handle type declarations, assuming that a
 19760  |type_name| has just been scanned.
 19761  
 19762  @<Declare action procedures for use by |do_statement|@>=
 19763  procedure do_type_declaration;
 19764  var @!t:small_number; {the type being declared}
 19765  @!p:pointer; {token list for a declared variable}
 19766  @!q:pointer; {value node for the variable}
 19767  begin if cur_mod>=transform_type then t:=cur_mod@+else t:=cur_mod+unknown_tag;
 19768  repeat p:=scan_declared_variable;
 19769  flush_variable(equiv(info(p)),link(p),false);@/
 19770  q:=find_variable(p);
 19771  if q<>null then
 19772    begin type(q):=t; value(q):=null;
 19773    end
 19774  else  begin print_err("Declared variable conflicts with previous vardef");
 19775  @.Declared variable conflicts...@>
 19776    help2("You can't use, e.g., `numeric foo[]' after `vardef foo'.")@/
 19777      ("Proceed, and I'll ignore the illegal redeclaration.");
 19778    put_get_error;
 19779    end;
 19780  flush_list(p);
 19781  if cur_cmd<comma then @<Flush spurious symbols after the declared variable@>;
 19782  until end_of_statement;
 19783  end;
 19784  
 19785  @ @<Flush spurious symbols after the declared variable@>=
 19786  begin print_err("Illegal suffix of declared variable will be flushed");
 19787  @.Illegal suffix...flushed@>
 19788  help5("Variables in declarations must consist entirely of")@/
 19789    ("names and collective subscripts, e.g., `x[]a'.")@/
 19790    ("Are you trying to use a reserved word in a variable name?")@/
 19791    ("I'm going to discard the junk I found here,")@/
 19792    ("up to the next comma or the end of the declaration.");
 19793  if cur_cmd=numeric_token then
 19794    help_line[2]:="Explicit subscripts like `x15a' aren't permitted.";
 19795  put_get_error; scanner_status:=flushing;
 19796  repeat get_next;
 19797  @<Decrease the string reference count...@>;
 19798  until cur_cmd>=comma; {either |end_of_statement| or |cur_cmd=comma|}
 19799  scanner_status:=normal;
 19800  end
 19801  
 19802  @ \MF's |main_control| procedure just calls |do_statement| repeatedly
 19803  until coming to the end of the user's program.
 19804  Each execution of |do_statement| concludes with
 19805  |cur_cmd=semicolon|, |end_group|, or |stop|.
 19806  
 19807  @p procedure main_control;
 19808  begin repeat do_statement;
 19809  if cur_cmd=end_group then
 19810    begin print_err("Extra `endgroup'");
 19811  @.Extra `endgroup'@>
 19812    help2("I'm not currently working on a `begingroup',")@/
 19813      ("so I had better not try to end anything.");
 19814    flush_error(0);
 19815    end;
 19816  until cur_cmd=stop;
 19817  end;
 19818  
 19819  @ @<Put each...@>=
 19820  primitive("end",stop,0);@/
 19821  @!@:end_}{\&{end} primitive@>
 19822  primitive("dump",stop,1);@/
 19823  @!@:dump_}{\&{dump} primitive@>
 19824  
 19825  @ @<Cases of |print_cmd...@>=
 19826  stop:if m=0 then print("end")@+else print("dump");
 19827  
 19828  @* \[44] Commands.
 19829  Let's turn now to statements that are classified as ``commands'' because
 19830  of their imperative nature. We'll begin with simple ones, so that it
 19831  will be clear how to hook command processing into the |do_statement| routine;
 19832  then we'll tackle the tougher commands.
 19833  
 19834  Here's one of the simplest:
 19835  
 19836  @<Cases of |do_statement|...@>=
 19837  random_seed: do_random_seed;
 19838  
 19839  @ @<Declare action procedures for use by |do_statement|@>=
 19840  procedure do_random_seed;
 19841  begin get_x_next;
 19842  if cur_cmd<>assignment then
 19843    begin missing_err(":=");
 19844  @.Missing `:='@>
 19845    help1("Always say `randomseed:=<numeric expression>'.");
 19846    back_error;
 19847    end;
 19848  get_x_next; scan_expression;
 19849  if cur_type<>known then
 19850    begin exp_err("Unknown value will be ignored");
 19851  @.Unknown value...ignored@>
 19852    help2("Your expression was too random for me to handle,")@/
 19853      ("so I won't change the random seed just now.");@/
 19854    put_get_flush_error(0);
 19855    end
 19856  else @<Initialize the random seed to |cur_exp|@>;
 19857  end;
 19858  
 19859  @ @<Initialize the random seed to |cur_exp|@>=
 19860  begin init_randoms(cur_exp);
 19861  if selector>=log_only then
 19862    begin old_setting:=selector; selector:=log_only;
 19863    print_nl("{randomseed:="); print_scaled(cur_exp); print_char("}");
 19864    print_nl(""); selector:=old_setting;
 19865    end;
 19866  end
 19867  
 19868  @ And here's another simple one (somewhat different in flavor):
 19869  
 19870  @<Cases of |do_statement|...@>=
 19871  mode_command: begin print_ln; interaction:=cur_mod;
 19872    @<Initialize the print |selector| based on |interaction|@>;
 19873    if log_opened then selector:=selector+2;
 19874    get_x_next;
 19875    end;
 19876  
 19877  @ @<Put each...@>=
 19878  primitive("batchmode",mode_command,batch_mode);
 19879  @!@:batch_mode_}{\&{batchmode} primitive@>
 19880  primitive("nonstopmode",mode_command,nonstop_mode);
 19881  @!@:nonstop_mode_}{\&{nonstopmode} primitive@>
 19882  primitive("scrollmode",mode_command,scroll_mode);
 19883  @!@:scroll_mode_}{\&{scrollmode} primitive@>
 19884  primitive("errorstopmode",mode_command,error_stop_mode);
 19885  @!@:error_stop_mode_}{\&{errorstopmode} primitive@>
 19886  
 19887  @ @<Cases of |print_cmd_mod|...@>=
 19888  mode_command: case m of
 19889    batch_mode: print("batchmode");
 19890    nonstop_mode: print("nonstopmode");
 19891    scroll_mode: print("scrollmode");
 19892    othercases print("errorstopmode")
 19893    endcases;
 19894  
 19895  @ The `\&{inner}' and `\&{outer}' commands are only slightly harder.
 19896  
 19897  @<Cases of |do_statement|...@>=
 19898  protection_command: do_protection;
 19899  
 19900  @ @<Put each...@>=
 19901  primitive("inner",protection_command,0);@/
 19902  @!@:inner_}{\&{inner} primitive@>
 19903  primitive("outer",protection_command,1);@/
 19904  @!@:outer_}{\&{outer} primitive@>
 19905  
 19906  @ @<Cases of |print_cmd...@>=
 19907  protection_command: if m=0 then print("inner")@+else print("outer");
 19908  
 19909  @ @<Declare action procedures for use by |do_statement|@>=
 19910  procedure do_protection;
 19911  var @!m:0..1; {0 to unprotect, 1 to protect}
 19912  @!t:halfword; {the |eq_type| before we change it}
 19913  begin m:=cur_mod;
 19914  repeat get_symbol; t:=eq_type(cur_sym);
 19915    if m=0 then
 19916      begin if t>=outer_tag then eq_type(cur_sym):=t-outer_tag;
 19917      end
 19918    else if t<outer_tag then eq_type(cur_sym):=t+outer_tag;
 19919    get_x_next;
 19920  until cur_cmd<>comma;
 19921  end;
 19922  
 19923  @ \MF\ never defines the tokens `\.(' and `\.)' to be primitives, but
 19924  plain \MF\ begins with the declaration `\&{delimiters} \.{()}'. Such a
 19925  declaration assigns the command code |left_delimiter| to `\.{(}' and
 19926  |right_delimiter| to `\.{)}'; the |equiv| of each delimiter is the
 19927  hash address of its mate.
 19928  
 19929  @<Cases of |do_statement|...@>=
 19930  delimiters: def_delims;
 19931  
 19932  @ @<Declare action procedures for use by |do_statement|@>=
 19933  procedure def_delims;
 19934  var l_delim,r_delim:pointer; {the new delimiter pair}
 19935  begin get_clear_symbol; l_delim:=cur_sym;@/
 19936  get_clear_symbol; r_delim:=cur_sym;@/
 19937  eq_type(l_delim):=left_delimiter; equiv(l_delim):=r_delim;@/
 19938  eq_type(r_delim):=right_delimiter; equiv(r_delim):=l_delim;@/
 19939  get_x_next;
 19940  end;
 19941  
 19942  @ Here is a procedure that is called when \MF\ has reached a point
 19943  where some right delimiter is mandatory.
 19944  
 19945  @<Declare the procedure called |check_delimiter|@>=
 19946  procedure check_delimiter(@!l_delim,@!r_delim:pointer);
 19947  label exit;
 19948  begin if cur_cmd=right_delimiter then if cur_mod=l_delim then return;
 19949  if cur_sym<>r_delim then
 19950    begin  missing_err(text(r_delim));@/
 19951  @.Missing `)'@>
 19952    help2("I found no right delimiter to match a left one. So I've")@/
 19953      ("put one in, behind the scenes; this may fix the problem.");
 19954    back_error;
 19955    end
 19956  else  begin print_err("The token `"); slow_print(text(r_delim));
 19957  @.The token...delimiter@>
 19958    print("' is no longer a right delimiter");
 19959    help3("Strange: This token has lost its former meaning!")@/
 19960      ("I'll read it as a right delimiter this time;")@/
 19961      ("but watch out, I'll probably miss it later.");
 19962    error;
 19963    end;
 19964  exit:end;
 19965  
 19966  @ The next four commands save or change the values associated with tokens.
 19967  
 19968  @<Cases of |do_statement|...@>=
 19969  save_command: repeat get_symbol; save_variable(cur_sym); get_x_next;
 19970    until cur_cmd<>comma;
 19971  interim_command: do_interim;
 19972  let_command: do_let;
 19973  new_internal: do_new_internal;
 19974  
 19975  @ @<Declare action procedures for use by |do_statement|@>=
 19976  procedure@?do_statement; forward;@t\2@>@/
 19977  procedure do_interim;
 19978  begin get_x_next;
 19979  if cur_cmd<>internal_quantity then
 19980    begin print_err("The token `");
 19981  @.The token...quantity@>
 19982    if cur_sym=0 then print("(%CAPSULE)")
 19983    else slow_print(text(cur_sym));
 19984    print("' isn't an internal quantity");
 19985    help1("Something like `tracingonline' should follow `interim'.");
 19986    back_error;
 19987    end
 19988  else  begin save_internal(cur_mod); back_input;
 19989    end;
 19990  do_statement;
 19991  end;
 19992  
 19993  @ The following procedure is careful not to undefine the left-hand symbol
 19994  too soon, lest commands like `{\tt let x=x}' have a surprising effect.
 19995  
 19996  @<Declare action procedures for use by |do_statement|@>=
 19997  procedure do_let;
 19998  var @!l:pointer; {hash location of the left-hand symbol}
 19999  begin get_symbol; l:=cur_sym; get_x_next;
 20000  if cur_cmd<>equals then if cur_cmd<>assignment then
 20001    begin missing_err("=");
 20002  @.Missing `='@>
 20003    help3("You should have said `let symbol = something'.")@/
 20004      ("But don't worry; I'll pretend that an equals sign")@/
 20005      ("was present. The next token I read will be `something'.");
 20006    back_error;
 20007    end;
 20008  get_symbol;
 20009  case cur_cmd of
 20010  defined_macro,secondary_primary_macro,tertiary_secondary_macro,
 20011   expression_tertiary_macro: add_mac_ref(cur_mod);
 20012  othercases do_nothing
 20013  endcases;@/
 20014  clear_symbol(l,false); eq_type(l):=cur_cmd;
 20015  if cur_cmd=tag_token then equiv(l):=null
 20016  else equiv(l):=cur_mod;
 20017  get_x_next;
 20018  end;
 20019  
 20020  @ @<Declare action procedures for use by |do_statement|@>=
 20021  procedure do_new_internal;
 20022  begin repeat if int_ptr=max_internal then
 20023    overflow("number of internals",max_internal);
 20024  @:METAFONT capacity exceeded number of int}{\quad number of internals@>
 20025  get_clear_symbol; incr(int_ptr);
 20026  eq_type(cur_sym):=internal_quantity; equiv(cur_sym):=int_ptr;
 20027  int_name[int_ptr]:=text(cur_sym); internal[int_ptr]:=0;
 20028  get_x_next;
 20029  until cur_cmd<>comma;
 20030  end;
 20031  
 20032  @ The various `\&{show}' commands are distinguished by modifier fields
 20033  in the usual way.
 20034  
 20035  @d show_token_code=0 {show the meaning of a single token}
 20036  @d show_stats_code=1 {show current memory and string usage}
 20037  @d show_code=2 {show a list of expressions}
 20038  @d show_var_code=3 {show a variable and its descendents}
 20039  @d show_dependencies_code=4 {show dependent variables in terms of independents}
 20040  
 20041  @<Put each...@>=
 20042  primitive("showtoken",show_command,show_token_code);@/
 20043  @!@:show_token_}{\&{showtoken} primitive@>
 20044  primitive("showstats",show_command,show_stats_code);@/
 20045  @!@:show_stats_}{\&{showstats} primitive@>
 20046  primitive("show",show_command,show_code);@/
 20047  @!@:show_}{\&{show} primitive@>
 20048  primitive("showvariable",show_command,show_var_code);@/
 20049  @!@:show_var_}{\&{showvariable} primitive@>
 20050  primitive("showdependencies",show_command,show_dependencies_code);@/
 20051  @!@:show_dependencies_}{\&{showdependencies} primitive@>
 20052  
 20053  @ @<Cases of |print_cmd...@>=
 20054  show_command: case m of
 20055    show_token_code:print("showtoken");
 20056    show_stats_code:print("showstats");
 20057    show_code:print("show");
 20058    show_var_code:print("showvariable");
 20059    othercases print("showdependencies")
 20060    endcases;
 20061  
 20062  @ @<Cases of |do_statement|...@>=
 20063  show_command:do_show_whatever;
 20064  
 20065  @ The value of |cur_mod| controls the |verbosity| in the |print_exp| routine:
 20066  If it's |show_code|, complicated structures are abbreviated, otherwise
 20067  they aren't.
 20068  
 20069  @<Declare action procedures for use by |do_statement|@>=
 20070  procedure do_show;
 20071  begin repeat get_x_next; scan_expression;
 20072  print_nl(">> ");
 20073  @.>>@>
 20074  print_exp(null,2); flush_cur_exp(0);
 20075  until cur_cmd<>comma;
 20076  end;
 20077  
 20078  @ @<Declare action procedures for use by |do_statement|@>=
 20079  procedure disp_token;
 20080  begin print_nl("> ");
 20081  @.>\relax@>
 20082  if cur_sym=0 then @<Show a numeric or string or capsule token@>
 20083  else  begin slow_print(text(cur_sym)); print_char("=");
 20084    if eq_type(cur_sym)>=outer_tag then print("(outer) ");
 20085    print_cmd_mod(cur_cmd,cur_mod);
 20086    if cur_cmd=defined_macro then
 20087      begin print_ln; show_macro(cur_mod,null,100000);
 20088      end; {this avoids recursion between |show_macro| and |print_cmd_mod|}
 20089  @^recursion@>
 20090    end;
 20091  end;
 20092  
 20093  @ @<Show a numeric or string or capsule token@>=
 20094  begin if cur_cmd=numeric_token then print_scaled(cur_mod)
 20095  else if cur_cmd=capsule_token then
 20096    begin g_pointer:=cur_mod; print_capsule;
 20097    end
 20098  else  begin print_char(""""); slow_print(cur_mod); print_char("""");
 20099    delete_str_ref(cur_mod);
 20100    end;
 20101  end
 20102  
 20103  @ The following cases of |print_cmd_mod| might arise in connection
 20104  with |disp_token|, although they don't necessarily correspond to
 20105  primitive tokens.
 20106  
 20107  @<Cases of |print_cmd_...@>=
 20108  left_delimiter,right_delimiter: begin if c=left_delimiter then print("lef")
 20109    else print("righ");
 20110    print("t delimiter that matches "); slow_print(text(m));
 20111    end;
 20112  tag_token:if m=null then print("tag")@+else print("variable");
 20113  defined_macro: print("macro:");
 20114  secondary_primary_macro,tertiary_secondary_macro,expression_tertiary_macro:
 20115    begin print_cmd_mod(macro_def,c); print("'d macro:");
 20116    print_ln; show_token_list(link(link(m)),null,1000,0);
 20117    end;
 20118  repeat_loop:print("[repeat the loop]");
 20119  internal_quantity:slow_print(int_name[m]);
 20120  
 20121  @ @<Declare action procedures for use by |do_statement|@>=
 20122  procedure do_show_token;
 20123  begin repeat get_next; disp_token;
 20124  get_x_next;
 20125  until cur_cmd<>comma;
 20126  end;
 20127  
 20128  @ @<Declare action procedures for use by |do_statement|@>=
 20129  procedure do_show_stats;
 20130  begin print_nl("Memory usage ");
 20131  @.Memory usage...@>
 20132  @!stat print_int(var_used); print_char("&"); print_int(dyn_used);
 20133  if false then@+tats@t@>@;@/
 20134  print("unknown");
 20135  print(" ("); print_int(hi_mem_min-lo_mem_max-1);
 20136  print(" still untouched)"); print_ln;
 20137  print_nl("String usage ");
 20138  print_int(str_ptr-init_str_ptr); print_char("&");
 20139  print_int(pool_ptr-init_pool_ptr);
 20140  print(" (");
 20141  print_int(max_strings-max_str_ptr); print_char("&");
 20142  print_int(pool_size-max_pool_ptr); print(" still untouched)"); print_ln;
 20143  get_x_next;
 20144  end;
 20145  
 20146  @ Here's a recursive procedure that gives an abbreviated account
 20147  of a variable, for use by |do_show_var|.
 20148  
 20149  @<Declare action procedures for use by |do_statement|@>=
 20150  procedure disp_var(@!p:pointer);
 20151  var @!q:pointer; {traverses attributes and subscripts}
 20152  @!n:0..max_print_line; {amount of macro text to show}
 20153  begin if type(p)=structured then @<Descend the structure@>
 20154  else if type(p)>=unsuffixed_macro then @<Display a variable macro@>
 20155  else if type(p)<>undefined then
 20156    begin print_nl(""); print_variable_name(p); print_char("=");
 20157    print_exp(p,0);
 20158    end;
 20159  end;
 20160  
 20161  @ @<Descend the structure@>=
 20162  begin q:=attr_head(p);
 20163  repeat disp_var(q); q:=link(q);
 20164  until q=end_attr;
 20165  q:=subscr_head(p);
 20166  while name_type(q)=subscr do
 20167    begin disp_var(q); q:=link(q);
 20168    end;
 20169  end
 20170  
 20171  @ @<Display a variable macro@>=
 20172  begin print_nl(""); print_variable_name(p);
 20173  if type(p)>unsuffixed_macro then print("@@#"); {|suffixed_macro|}
 20174  print("=macro:");
 20175  if file_offset>=max_print_line-20 then n:=5
 20176  else n:=max_print_line-file_offset-15;
 20177  show_macro(value(p),null,n);
 20178  end
 20179  
 20180  @ @<Declare action procedures for use by |do_statement|@>=
 20181  procedure do_show_var;
 20182  label done;
 20183  begin repeat get_next;
 20184  if cur_sym>0 then if cur_sym<=hash_end then
 20185   if cur_cmd=tag_token then if cur_mod<>null then
 20186    begin disp_var(cur_mod); goto done;
 20187    end;
 20188  disp_token;
 20189  done:get_x_next;
 20190  until cur_cmd<>comma;
 20191  end;
 20192  
 20193  @ @<Declare action procedures for use by |do_statement|@>=
 20194  procedure do_show_dependencies;
 20195  var @!p:pointer; {link that runs through all dependencies}
 20196  begin p:=link(dep_head);
 20197  while p<>dep_head do
 20198    begin if interesting(p) then
 20199      begin print_nl(""); print_variable_name(p);
 20200      if type(p)=dependent then print_char("=")
 20201      else print(" = "); {extra spaces imply proto-dependency}
 20202      print_dependency(dep_list(p),type(p));
 20203      end;
 20204    p:=dep_list(p);
 20205    while info(p)<>null do p:=link(p);
 20206    p:=link(p);
 20207    end;
 20208  get_x_next;
 20209  end;
 20210  
 20211  @ Finally we are ready for the procedure that governs all of the
 20212  show commands.
 20213  
 20214  @<Declare action procedures for use by |do_statement|@>=
 20215  procedure do_show_whatever;
 20216  begin if interaction=error_stop_mode then wake_up_terminal;
 20217  case cur_mod of
 20218  show_token_code:do_show_token;
 20219  show_stats_code:do_show_stats;
 20220  show_code:do_show;
 20221  show_var_code:do_show_var;
 20222  show_dependencies_code:do_show_dependencies;
 20223  end; {there are no other cases}
 20224  if internal[showstopping]>0 then
 20225    begin print_err("OK");
 20226  @.OK@>
 20227    if interaction<error_stop_mode then
 20228      begin help0; decr(error_count);
 20229      end
 20230    else help1("This isn't an error message; I'm just showing something.");
 20231    if cur_cmd=semicolon then error@+else put_get_error;
 20232    end;
 20233  end;
 20234  
 20235  @ The `\&{addto}' command needs the following additional primitives:
 20236  
 20237  @d drop_code=0 {command modifier for `\&{dropping}'}
 20238  @d keep_code=1 {command modifier for `\&{keeping}'}
 20239  
 20240  @<Put each...@>=
 20241  primitive("contour",thing_to_add,contour_code);@/
 20242  @!@:contour_}{\&{contour} primitive@>
 20243  primitive("doublepath",thing_to_add,double_path_code);@/
 20244  @!@:double_path_}{\&{doublepath} primitive@>
 20245  primitive("also",thing_to_add,also_code);@/
 20246  @!@:also_}{\&{also} primitive@>
 20247  primitive("withpen",with_option,pen_type);@/
 20248  @!@:with_pen_}{\&{withpen} primitive@>
 20249  primitive("withweight",with_option,known);@/
 20250  @!@:with_weight_}{\&{withweight} primitive@>
 20251  primitive("dropping",cull_op,drop_code);@/
 20252  @!@:dropping_}{\&{dropping} primitive@>
 20253  primitive("keeping",cull_op,keep_code);@/
 20254  @!@:keeping_}{\&{keeping} primitive@>
 20255  
 20256  @ @<Cases of |print_cmd...@>=
 20257  thing_to_add:if m=contour_code then print("contour")
 20258    else if m=double_path_code then print("doublepath")
 20259    else print("also");
 20260  with_option:if m=pen_type then print("withpen")
 20261    else print("withweight");
 20262  cull_op:if m=drop_code then print("dropping")
 20263    else print("keeping");
 20264  
 20265  @ @<Declare action procedures for use by |do_statement|@>=
 20266  function scan_with:boolean;
 20267  var @!t:small_number; {|known| or |pen_type|}
 20268  @!result:boolean; {the value to return}
 20269  begin t:=cur_mod; cur_type:=vacuous; get_x_next; scan_expression;
 20270  result:=false;
 20271  if cur_type<>t then @<Complain about improper type@>
 20272  else if cur_type=pen_type then result:=true
 20273  else @<Check the tentative weight@>;
 20274  scan_with:=result;
 20275  end;
 20276  
 20277  @ @<Complain about improper type@>=
 20278  begin exp_err("Improper type");
 20279  @.Improper type@>
 20280  help2("Next time say `withweight <known numeric expression>';")@/
 20281    ("I'll ignore the bad `with' clause and look for another.");
 20282  if t=pen_type then
 20283    help_line[1]:="Next time say `withpen <known pen expression>';";
 20284  put_get_flush_error(0);
 20285  end
 20286  
 20287  @ @<Check the tentative weight@>=
 20288  begin cur_exp:=round_unscaled(cur_exp);
 20289  if (abs(cur_exp)<4)and(cur_exp<>0) then result:=true
 20290  else  begin print_err("Weight must be -3, -2, -1, +1, +2, or +3");
 20291  @.Weight must be...@>
 20292    help1("I'll ignore the bad `with' clause and look for another.");
 20293    put_get_flush_error(0);
 20294    end;
 20295  end
 20296  
 20297  @ One of the things we need to do when we've parsed an \&{addto} or
 20298  similar command is set |cur_edges| to the header of a supposed \&{picture}
 20299  variable, given a token list for that variable.
 20300  
 20301  @<Declare action procedures for use by |do_statement|@>=
 20302  procedure find_edges_var(@!t:pointer);
 20303  var @!p:pointer;
 20304  begin p:=find_variable(t); cur_edges:=null;
 20305  if p=null then
 20306    begin obliterated(t); put_get_error;
 20307    end
 20308  else if type(p)<>picture_type then
 20309    begin print_err("Variable "); show_token_list(t,null,1000,0);
 20310  @.Variable x is the wrong type@>
 20311    print(" is the wrong type ("); print_type(type(p)); print_char(")");
 20312    help2("I was looking for a ""known"" picture variable.")@/
 20313      ("So I'll not change anything just now."); put_get_error;
 20314    end
 20315  else cur_edges:=value(p);
 20316  flush_node_list(t);
 20317  end;
 20318  
 20319  @ @<Cases of |do_statement|...@>=
 20320  add_to_command: do_add_to;
 20321  
 20322  @ @<Declare action procedures for use by |do_statement|@>=
 20323  procedure do_add_to;
 20324  label done, not_found;
 20325  var @!lhs,@!rhs:pointer; {variable on left, path on right}
 20326  @!w:integer; {tentative weight}
 20327  @!p:pointer; {list manipulation register}
 20328  @!q:pointer; {beginning of second half of doubled path}
 20329  @!add_to_type:double_path_code..also_code; {modifier of \&{addto}}
 20330  begin get_x_next; var_flag:=thing_to_add; scan_primary;
 20331  if cur_type<>token_list then
 20332    @<Abandon edges command because there's no variable@>
 20333  else  begin lhs:=cur_exp; add_to_type:=cur_mod;@/
 20334    cur_type:=vacuous; get_x_next; scan_expression;
 20335    if add_to_type=also_code then @<Augment some edges by others@>
 20336    else @<Get ready to fill a contour, and fill it@>;
 20337    end;
 20338  end;
 20339  
 20340  @ @<Abandon edges command because there's no variable@>=
 20341  begin exp_err("Not a suitable variable");
 20342  @.Not a suitable variable@>
 20343  help4("At this point I needed to see the name of a picture variable.")@/
 20344    ("(Or perhaps you have indeed presented me with one; I might")@/
 20345    ("have missed it, if it wasn't followed by the proper token.)")@/
 20346    ("So I'll not change anything just now.");
 20347  put_get_flush_error(0);
 20348  end
 20349  
 20350  @ @<Augment some edges by others@>=
 20351  begin find_edges_var(lhs);
 20352  if cur_edges=null then flush_cur_exp(0)
 20353  else if cur_type<>picture_type then
 20354    begin exp_err("Improper `addto'");
 20355  @.Improper `addto'@>
 20356    help2("This expression should have specified a known picture.")@/
 20357      ("So I'll not change anything just now."); put_get_flush_error(0);
 20358    end
 20359  else  begin merge_edges(cur_exp); flush_cur_exp(0);
 20360    end;
 20361  end
 20362  
 20363  @ @<Get ready to fill a contour...@>=
 20364  begin if cur_type=pair_type then pair_to_path;
 20365  if cur_type<>path_type then
 20366    begin exp_err("Improper `addto'");
 20367  @.Improper `addto'@>
 20368    help2("This expression should have been a known path.")@/
 20369      ("So I'll not change anything just now.");
 20370    put_get_flush_error(0); flush_token_list(lhs);
 20371    end
 20372  else  begin rhs:=cur_exp; w:=1; cur_pen:=null_pen;
 20373    while cur_cmd=with_option do
 20374      if scan_with then
 20375        if cur_type=known then w:=cur_exp
 20376        else @<Change the tentative pen@>;
 20377    @<Complete the contour filling operation@>;
 20378    delete_pen_ref(cur_pen);
 20379    end;
 20380  end
 20381  
 20382  @ We could say `|add_pen_ref(cur_pen)|; |flush_cur_exp(0)|' after changing
 20383  |cur_pen| here.  But that would have no effect, because the current expression
 20384  will not be flushed. Thus we save a bit of code (at the risk of being too
 20385  tricky).
 20386  
 20387  @<Change the tentative pen@>=
 20388  begin delete_pen_ref(cur_pen); cur_pen:=cur_exp;
 20389  end
 20390  
 20391  @ @<Complete the contour filling...@>=
 20392  find_edges_var(lhs);
 20393  if cur_edges=null then toss_knot_list(rhs)
 20394  else  begin lhs:=null; cur_path_type:=add_to_type;
 20395    if left_type(rhs)=endpoint then
 20396      if cur_path_type=double_path_code then @<Double the path@>
 20397      else @<Complain about non-cycle and |goto not_found|@>
 20398    else if cur_path_type=double_path_code then lhs:=htap_ypoc(rhs);
 20399    cur_wt:=w; rhs:=make_spec(rhs,max_offset(cur_pen),internal[tracing_specs]);
 20400    @<Check the turning number@>;
 20401    if max_offset(cur_pen)=0 then fill_spec(rhs)
 20402    else fill_envelope(rhs);
 20403    if lhs<>null then
 20404      begin rev_turns:=true;
 20405      lhs:=make_spec(lhs,max_offset(cur_pen),internal[tracing_specs]);
 20406      rev_turns:=false;
 20407      if max_offset(cur_pen)=0 then fill_spec(lhs)
 20408      else fill_envelope(lhs);
 20409      end;
 20410  not_found: end
 20411  
 20412  @ @<Double the path@>=
 20413  if link(rhs)=rhs then @<Make a trivial one-point path cycle@>
 20414  else  begin p:=htap_ypoc(rhs); q:=link(p);@/
 20415    right_x(path_tail):=right_x(q); right_y(path_tail):=right_y(q);
 20416    right_type(path_tail):=right_type(q);
 20417    link(path_tail):=link(q); free_node(q,knot_node_size);@/
 20418    right_x(p):=right_x(rhs); right_y(p):=right_y(rhs);
 20419    right_type(p):=right_type(rhs);
 20420    link(p):=link(rhs); free_node(rhs,knot_node_size);@/
 20421    rhs:=p;
 20422    end
 20423  
 20424  @ @<Make a trivial one-point path cycle@>=
 20425  begin right_x(rhs):=x_coord(rhs); right_y(rhs):=y_coord(rhs);
 20426  left_x(rhs):=x_coord(rhs); left_y(rhs):=y_coord(rhs);
 20427  left_type(rhs):=explicit; right_type(rhs):=explicit;
 20428  end
 20429  
 20430  @ @<Complain about non-cycle...@>=
 20431  begin print_err("Not a cycle");
 20432  @.Not a cycle@>
 20433  help2("That contour should have ended with `..cycle' or `&cycle'.")@/
 20434    ("So I'll not change anything just now."); put_get_error;
 20435  toss_knot_list(rhs); goto not_found;
 20436  end
 20437  
 20438  @ @<Check the turning number@>=
 20439  if turning_number<=0 then
 20440   if cur_path_type<>double_path_code then if internal[turning_check]>0 then
 20441    if (turning_number<0)and(link(cur_pen)=null) then negate(cur_wt)
 20442    else  begin if turning_number=0 then
 20443        if (internal[turning_check]<=unity)and(link(cur_pen)=null) then goto done
 20444        else print_strange("Strange path (turning number is zero)")
 20445  @.Strange path...@>
 20446      else print_strange("Backwards path (turning number is negative)");
 20447  @.Backwards path...@>
 20448      help3("The path doesn't have a counterclockwise orientation,")@/
 20449        ("so I'll probably have trouble drawing it.")@/
 20450        ("(See Chapter 27 of The METAFONTbook for more help.)");
 20451  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 20452      put_get_error;
 20453      end;
 20454  done:
 20455  
 20456  @ @<Cases of |do_statement|...@>=
 20457  ship_out_command: do_ship_out;
 20458  display_command: do_display;
 20459  open_window: do_open_window;
 20460  cull_command: do_cull;
 20461  
 20462  @ @<Declare action procedures for use by |do_statement|@>=
 20463  @t\4@>@<Declare the function called |tfm_check|@>@;
 20464  procedure do_ship_out;
 20465  label exit;
 20466  var @!c:integer; {the character code}
 20467  begin get_x_next; var_flag:=semicolon; scan_expression;
 20468  if cur_type<>token_list then
 20469    if cur_type=picture_type then cur_edges:=cur_exp
 20470    else  begin @<Abandon edges command because there's no variable@>;
 20471      return;
 20472      end
 20473  else  begin find_edges_var(cur_exp); cur_type:=vacuous;
 20474    end;
 20475  if cur_edges<>null then
 20476    begin c:=round_unscaled(internal[char_code]) mod 256;
 20477    if c<0 then c:=c+256;
 20478    @<Store the width information for character code~|c|@>;
 20479    if internal[proofing]>=0 then ship_out(c);
 20480    end;
 20481  flush_cur_exp(0);
 20482  exit:end;
 20483  
 20484  @ @<Declare action procedures for use by |do_statement|@>=
 20485  procedure do_display;
 20486  label not_found,common_ending,exit;
 20487  var @!e:pointer; {token list for a picture variable}
 20488  begin get_x_next; var_flag:=in_window; scan_primary;
 20489  if cur_type<>token_list then
 20490    @<Abandon edges command because there's no variable@>
 20491  else  begin e:=cur_exp; cur_type:=vacuous;
 20492    get_x_next; scan_expression;
 20493    if cur_type<>known then goto common_ending;
 20494    cur_exp:=round_unscaled(cur_exp);
 20495    if cur_exp<0 then goto not_found;
 20496    if cur_exp>15 then goto not_found;
 20497    if not window_open[cur_exp] then goto not_found;
 20498    find_edges_var(e);
 20499    if cur_edges<>null then disp_edges(cur_exp);
 20500    return;
 20501   not_found: cur_exp:=cur_exp*unity;
 20502   common_ending: exp_err("Bad window number");
 20503  @.Bad window number@>
 20504    help1("It should be the number of an open window.");
 20505    put_get_flush_error(0); flush_token_list(e);
 20506    end;
 20507  exit:end;
 20508  
 20509  @ The only thing difficult about `\&{openwindow}' is that the syntax
 20510  allows the user to go astray in many ways. The following subroutine
 20511  helps keep the necessary program reasonably short and sweet.
 20512  
 20513  @<Declare action procedures for use by |do_statement|@>=
 20514  function get_pair(@!c:command_code):boolean;
 20515  var @!p:pointer; {a pair of values that are known (we hope)}
 20516  @!b:boolean; {did we find such a pair?}
 20517  begin if cur_cmd<>c then get_pair:=false
 20518  else  begin get_x_next; scan_expression;
 20519    if nice_pair(cur_exp,cur_type) then
 20520      begin p:=value(cur_exp);
 20521      cur_x:=value(x_part_loc(p)); cur_y:=value(y_part_loc(p));
 20522      b:=true;
 20523      end
 20524    else b:=false;
 20525    flush_cur_exp(0); get_pair:=b;
 20526    end;
 20527  end;
 20528  
 20529  @ @<Declare action procedures for use by |do_statement|@>=
 20530  procedure do_open_window;
 20531  label not_found,exit;
 20532  var @!k:integer; {the window number in question}
 20533  @!r0,@!c0,@!r1,@!c1:scaled; {window coordinates}
 20534  begin get_x_next; scan_expression;
 20535  if cur_type<>known then goto not_found;
 20536  k:=round_unscaled(cur_exp);
 20537  if k<0 then goto not_found;
 20538  if k>15 then goto not_found;
 20539  if not get_pair(from_token) then goto not_found;
 20540  r0:=cur_x; c0:=cur_y;
 20541  if not get_pair(to_token) then goto not_found;
 20542  r1:=cur_x; c1:=cur_y;
 20543  if not get_pair(at_token) then goto not_found;
 20544  open_a_window(k,r0,c0,r1,c1,cur_x,cur_y); return;
 20545  not_found:print_err("Improper `openwindow'");
 20546  @.Improper `openwindow'@>
 20547  help2("Say `openwindow k from (r0,c0) to (r1,c1) at (x,y)',")@/
 20548    ("where all quantities are known and k is between 0 and 15.");
 20549  put_get_error;
 20550  exit:end;
 20551  
 20552  @ @<Declare action procedures for use by |do_statement|@>=
 20553  procedure do_cull;
 20554  label not_found,exit;
 20555  var @!e:pointer; {token list for a picture variable}
 20556  @!keeping:drop_code..keep_code; {modifier of |cull_op|}
 20557  @!w,@!w_in,@!w_out:integer; {culling weights}
 20558  begin w:=1;
 20559  get_x_next; var_flag:=cull_op; scan_primary;
 20560  if cur_type<>token_list then
 20561    @<Abandon edges command because there's no variable@>
 20562  else  begin e:=cur_exp; cur_type:=vacuous; keeping:=cur_mod;
 20563    if not get_pair(cull_op) then goto not_found;
 20564    while (cur_cmd=with_option)and(cur_mod=known) do
 20565      if scan_with then w:=cur_exp;
 20566    @<Set up the culling weights,
 20567      or |goto not_found| if the thresholds are bad@>;
 20568    find_edges_var(e);
 20569    if cur_edges<>null then
 20570      cull_edges(floor_unscaled(cur_x+unity-1),floor_unscaled(cur_y),w_out,w_in);
 20571    return;
 20572   not_found: print_err("Bad culling amounts");
 20573  @.Bad culling amounts@>
 20574    help1("Always cull by known amounts that exclude 0.");
 20575    put_get_error; flush_token_list(e);
 20576    end;
 20577  exit:end;
 20578  
 20579  @ @<Set up the culling weights, or |goto not_found| if the thresholds are bad@>=
 20580  if cur_x>cur_y then goto not_found;
 20581  if keeping=drop_code then
 20582    begin if (cur_x>0)or(cur_y<0) then goto not_found;
 20583    w_out:=w; w_in:=0;
 20584    end
 20585  else  begin if (cur_x<=0)and(cur_y>=0) then goto not_found;
 20586    w_out:=0; w_in:=w;
 20587    end
 20588  
 20589  @ The \&{everyjob} command simply assigns a nonzero value to the global variable
 20590  |start_sym|.
 20591  
 20592  @<Cases of |do_statement|...@>=
 20593  every_job_command: begin get_symbol; start_sym:=cur_sym; get_x_next;
 20594    end;
 20595  
 20596  @ @<Glob...@>=
 20597  @!start_sym:halfword; {a symbolic token to insert at beginning of job}
 20598  
 20599  @ @<Set init...@>=
 20600  start_sym:=0;
 20601  
 20602  @ Finally, we have only the ``message'' commands remaining.
 20603  
 20604  @d message_code=0
 20605  @d err_message_code=1
 20606  @d err_help_code=2
 20607  
 20608  @<Put each...@>=
 20609  primitive("message",message_command,message_code);@/
 20610  @!@:message_}{\&{message} primitive@>
 20611  primitive("errmessage",message_command,err_message_code);@/
 20612  @!@:err_message_}{\&{errmessage} primitive@>
 20613  primitive("errhelp",message_command,err_help_code);@/
 20614  @!@:err_help_}{\&{errhelp} primitive@>
 20615  
 20616  @ @<Cases of |print_cmd...@>=
 20617  message_command: if m<err_message_code then print("message")
 20618    else if m=err_message_code then print("errmessage")
 20619    else print("errhelp");
 20620  
 20621  @ @<Cases of |do_statement|...@>=
 20622  message_command: do_message;
 20623  
 20624  @ @<Declare action procedures for use by |do_statement|@>=
 20625  procedure do_message;
 20626  var @!m:message_code..err_help_code; {the type of message}
 20627  begin m:=cur_mod; get_x_next; scan_expression;
 20628  if cur_type<>string_type then
 20629    begin exp_err("Not a string");
 20630  @.Not a string@>
 20631    help1("A message should be a known string expression.");
 20632    put_get_error;
 20633    end
 20634  else  case m of
 20635    message_code:begin print_nl(""); slow_print(cur_exp);
 20636      end;
 20637    err_message_code:@<Print string |cur_exp| as an error message@>;
 20638    err_help_code:@<Save string |cur_exp| as the |err_help|@>;
 20639    end; {there are no other cases}
 20640  flush_cur_exp(0);
 20641  end;
 20642  
 20643  @ The global variable |err_help| is zero when the user has most recently
 20644  given an empty help string, or if none has ever been given.
 20645  
 20646  @<Save string |cur_exp| as the |err_help|@>=
 20647  begin if err_help<>0 then delete_str_ref(err_help);
 20648  if length(cur_exp)=0 then err_help:=0
 20649  else  begin err_help:=cur_exp; add_str_ref(err_help);
 20650    end;
 20651  end
 20652  
 20653  @ If \&{errmessage} occurs often in |scroll_mode|, without user-defined
 20654  \&{errhelp}, we don't want to give a long help message each time. So we
 20655  give a verbose explanation only once.
 20656  
 20657  @<Glob...@>=
 20658  @!long_help_seen:boolean; {has the long \&{errmessage} help been used?}
 20659  
 20660  @ @<Set init...@>=long_help_seen:=false;
 20661  
 20662  @ @<Print string |cur_exp| as an error message@>=
 20663  begin print_err(""); slow_print(cur_exp);
 20664  if err_help<>0 then use_err_help:=true
 20665  else if long_help_seen then help1("(That was another `errmessage'.)")
 20666  else  begin if interaction<error_stop_mode then long_help_seen:=true;
 20667    help4("This error message was generated by an `errmessage'")@/
 20668    ("command, so I can't give any explicit help.")@/
 20669    ("Pretend that you're Miss Marple: Examine all clues,")@/
 20670  @^Marple, Jane@>
 20671    ("and deduce the truth by inspired guesses.");
 20672    end;
 20673  put_get_error; use_err_help:=false;
 20674  end
 20675  
 20676  @* \[45] Font metric data.
 20677  \TeX\ gets its knowledge about fonts from font metric files, also called
 20678  \.{TFM} files; the `\.T' in `\.{TFM}' stands for \TeX,
 20679  but other programs know about them too. One of \MF's duties is to
 20680  write \.{TFM} files so that the user's fonts can readily be
 20681  applied to typesetting.
 20682  @:TFM files}{\.{TFM} files@>
 20683  @^font metric files@>
 20684  
 20685  The information in a \.{TFM} file appears in a sequence of 8-bit bytes.
 20686  Since the number of bytes is always a multiple of~4, we could
 20687  also regard the file as a sequence of 32-bit words, but \MF\ uses the
 20688  byte interpretation. The format of \.{TFM} files was designed by
 20689  Lyle Ramshaw in 1980. The intent is to convey a lot of different kinds
 20690  @^Ramshaw, Lyle Harold@>
 20691  of information in a compact but useful form.
 20692  
 20693  @<Glob...@>=
 20694  @!tfm_file:byte_file; {the font metric output goes here}
 20695  @!metric_file_name: str_number; {full name of the font metric file}
 20696  
 20697  @ The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit
 20698  integers that give the lengths of the various subsequent portions
 20699  of the file. These twelve integers are, in order:
 20700  $$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr
 20701  |lf|&length of the entire file, in words;\cr
 20702  |lh|&length of the header data, in words;\cr
 20703  |bc|&smallest character code in the font;\cr
 20704  |ec|&largest character code in the font;\cr
 20705  |nw|&number of words in the width table;\cr
 20706  |nh|&number of words in the height table;\cr
 20707  |nd|&number of words in the depth table;\cr
 20708  |ni|&number of words in the italic correction table;\cr
 20709  |nl|&number of words in the lig/kern table;\cr
 20710  |nk|&number of words in the kern table;\cr
 20711  |ne|&number of words in the extensible character table;\cr
 20712  |np|&number of font parameter words.\cr}}$$
 20713  They are all nonnegative and less than $2^{15}$. We must have |bc-1<=ec<=255|,
 20714  |ne<=256|, and
 20715  $$\hbox{|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
 20716  Note that a font may contain as many as 256 characters (if |bc=0| and |ec=255|),
 20717  and as few as 0 characters (if |bc=ec+1|).
 20718  
 20719  Incidentally, when two or more 8-bit bytes are combined to form an integer of
 20720  16 or more bits, the most significant bytes appear first in the file.
 20721  This is called BigEndian order.
 20722  @!@^BigEndian order@>
 20723  
 20724  @ The rest of the \.{TFM} file may be regarded as a sequence of ten data
 20725  arrays having the informal specification
 20726  $$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2}
 20727  \tabskip\centering
 20728  \halign to\displaywidth{\hfil\\{#}\tabskip=0pt&$\,:\,$\arr#\hfil
 20729   \tabskip\centering\cr
 20730  header&|[0..lh-1]@t\\{stuff}@>|\cr
 20731  char\_info&|[bc..ec]char_info_word|\cr
 20732  width&|[0..nw-1]fix_word|\cr
 20733  height&|[0..nh-1]fix_word|\cr
 20734  depth&|[0..nd-1]fix_word|\cr
 20735  italic&|[0..ni-1]fix_word|\cr
 20736  lig\_kern&|[0..nl-1]lig_kern_command|\cr
 20737  kern&|[0..nk-1]fix_word|\cr
 20738  exten&|[0..ne-1]extensible_recipe|\cr
 20739  param&|[1..np]fix_word|\cr}$$
 20740  The most important data type used here is a |@!fix_word|, which is
 20741  a 32-bit representation of a binary fraction. A |fix_word| is a signed
 20742  quantity, with the two's complement of the entire word used to represent
 20743  negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
 20744  binary point; thus, the largest |fix_word| value is $2048-2^{-20}$, and
 20745  the smallest is $-2048$. We will see below, however, that all but two of
 20746  the |fix_word| values must lie between $-16$ and $+16$.
 20747  
 20748  @ The first data array is a block of header information, which contains
 20749  general facts about the font. The header must contain at least two words,
 20750  |header[0]| and |header[1]|, whose meaning is explained below.  Additional
 20751  header information of use to other software routines might also be
 20752  included, and \MF\ will generate it if the \.{headerbyte} command occurs.
 20753  For example, 16 more words of header information are in use at the Xerox
 20754  Palo Alto Research Center; the first ten specify the character coding
 20755  scheme used (e.g., `\.{XEROX TEXT}' or `\.{TEX MATHSY}'), the next five
 20756  give the font family name (e.g., `\.{HELVETICA}' or `\.{CMSY}'), and the
 20757  last gives the ``face byte.''
 20758  
 20759  \yskip\hang|header[0]| is a 32-bit check sum that \MF\ will copy into
 20760  the \.{GF} output file. This helps ensure consistency between files,
 20761  since \TeX\ records the check sums from the \.{TFM}'s it reads, and these
 20762  should match the check sums on actual fonts that are used.  The actual
 20763  relation between this check sum and the rest of the \.{TFM} file is not
 20764  important; the check sum is simply an identification number with the
 20765  property that incompatible fonts almost always have distinct check sums.
 20766  @^check sum@>
 20767  
 20768  \yskip\hang|header[1]| is a |fix_word| containing the design size of the
 20769  font, in units of \TeX\ points. This number must be at least 1.0; it is
 20770  fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
 20771  font, i.e., a font that was designed to look best at a 10-point size,
 20772  whatever that really means. When a \TeX\ user asks for a font `\.{at}
 20773  $\delta$ \.{pt}', the effect is to override the design size and replace it
 20774  by $\delta$, and to multiply the $x$ and~$y$ coordinates of the points in
 20775  the font image by a factor of $\delta$ divided by the design size.  {\sl
 20776  All other dimensions in the\/ \.{TFM} file are |fix_word|\kern-1pt\
 20777  numbers in design-size units.} Thus, for example, the value of |param[6]|,
 20778  which defines the \.{em} unit, is often the |fix_word| value $2^{20}=1.0$,
 20779  since many fonts have a design size equal to one em.  The other dimensions
 20780  must be less than 16 design-size units in absolute value; thus,
 20781  |header[1]| and |param[1]| are the only |fix_word| entries in the whole
 20782  \.{TFM} file whose first byte might be something besides 0 or 255.
 20783  @^design size@>
 20784  
 20785  @ Next comes the |char_info| array, which contains one |@!char_info_word|
 20786  per character. Each word in this part of the file contains six fields
 20787  packed into four bytes as follows.
 20788  
 20789  \yskip\hang first byte: |@!width_index| (8 bits)\par
 20790  \hang second byte: |@!height_index| (4 bits) times 16, plus |@!depth_index|
 20791    (4~bits)\par
 20792  \hang third byte: |@!italic_index| (6 bits) times 4, plus |@!tag|
 20793    (2~bits)\par
 20794  \hang fourth byte: |@!remainder| (8 bits)\par
 20795  \yskip\noindent
 20796  The actual width of a character is \\{width}|[width_index]|, in design-size
 20797  units; this is a device for compressing information, since many characters
 20798  have the same width. Since it is quite common for many characters
 20799  to have the same height, depth, or italic correction, the \.{TFM} format
 20800  imposes a limit of 16 different heights, 16 different depths, and
 20801  64 different italic corrections.
 20802  
 20803  Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]=
 20804  \\{italic}[0]=0$ should always hold, so that an index of zero implies a
 20805  value of zero.  The |width_index| should never be zero unless the
 20806  character does not exist in the font, since a character is valid if and
 20807  only if it lies between |bc| and |ec| and has a nonzero |width_index|.
 20808  
 20809  @ The |tag| field in a |char_info_word| has four values that explain how to
 20810  interpret the |remainder| field.
 20811  
 20812  \def\hangg#1 {\hang\hbox{#1 }}
 20813  \yskip\hangg|tag=0| (|no_tag|) means that |remainder| is unused.\par
 20814  \hangg|tag=1| (|lig_tag|) means that this character has a ligature/kerning
 20815  program starting at location |remainder| in the |lig_kern| array.\par
 20816  \hangg|tag=2| (|list_tag|) means that this character is part of a chain of
 20817  characters of ascending sizes, and not the largest in the chain.  The
 20818  |remainder| field gives the character code of the next larger character.\par
 20819  \hangg|tag=3| (|ext_tag|) means that this character code represents an
 20820  extensible character, i.e., a character that is built up of smaller pieces
 20821  so that it can be made arbitrarily large. The pieces are specified in
 20822  |@!exten[remainder]|.\par
 20823  \yskip\noindent
 20824  Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
 20825  unless they are used in special circumstances in math formulas. For example,
 20826  \TeX's \.{\\sum} operation looks for a |list_tag|, and the \.{\\left}
 20827  operation looks for both |list_tag| and |ext_tag|.
 20828  
 20829  @d no_tag=0 {vanilla character}
 20830  @d lig_tag=1 {character has a ligature/kerning program}
 20831  @d list_tag=2 {character has a successor in a charlist}
 20832  @d ext_tag=3 {character is extensible}
 20833  
 20834  @ The |lig_kern| array contains instructions in a simple programming language
 20835  that explains what to do for special letter pairs. Each word in this array is a
 20836  |@!lig_kern_command| of four bytes.
 20837  
 20838  \yskip\hang first byte: |skip_byte|, indicates that this is the final program
 20839    step if the byte is 128 or more, otherwise the next step is obtained by
 20840    skipping this number of intervening steps.\par
 20841  \hang second byte: |next_char|, ``if |next_char| follows the current character,
 20842    then perform the operation and stop, otherwise continue.''\par
 20843  \hang third byte: |op_byte|, indicates a ligature step if less than~128,
 20844    a kern step otherwise.\par
 20845  \hang fourth byte: |remainder|.\par
 20846  \yskip\noindent
 20847  In a kern step, an
 20848  additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
 20849  between the current character and |next_char|. This amount is
 20850  often negative, so that the characters are brought closer together
 20851  by kerning; but it might be positive.
 20852  
 20853  There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
 20854  $0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
 20855  |remainder| is inserted between the current character and |next_char|;
 20856  then the current character is deleted if $b=0$, and |next_char| is
 20857  deleted if $c=0$; then we pass over $a$~characters to reach the next
 20858  current character (which may have a ligature/kerning program of its own).
 20859  
 20860  If the very first instruction of the |lig_kern| array has |skip_byte=255|,
 20861  the |next_char| byte is the so-called boundary character of this font;
 20862  the value of |next_char| need not lie between |bc| and~|ec|.
 20863  If the very last instruction of the |lig_kern| array has |skip_byte=255|,
 20864  there is a special ligature/kerning program for a boundary character at the
 20865  left, beginning at location |256*op_byte+remainder|.
 20866  The interpretation is that \TeX\ puts implicit boundary characters
 20867  before and after each consecutive string of characters from the same font.
 20868  These implicit characters do not appear in the output, but they can affect
 20869  ligatures and kerning.
 20870  
 20871  If the very first instruction of a character's |lig_kern| program has
 20872  |skip_byte>128|, the program actually begins in location
 20873  |256*op_byte+remainder|. This feature allows access to large |lig_kern|
 20874  arrays, because the first instruction must otherwise
 20875  appear in a location |<=255|.
 20876  
 20877  Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
 20878  the condition
 20879  $$\hbox{|256*op_byte+remainder<nl|.}$$
 20880  If such an instruction is encountered during
 20881  normal program execution, it denotes an unconditional halt; no ligature
 20882  or kerning command is performed.
 20883  
 20884  @d stop_flag=128+min_quarterword
 20885    {value indicating `\.{STOP}' in a lig/kern program}
 20886  @d kern_flag=128+min_quarterword {op code for a kern step}
 20887  @d skip_byte(#)==lig_kern[#].b0
 20888  @d next_char(#)==lig_kern[#].b1
 20889  @d op_byte(#)==lig_kern[#].b2
 20890  @d rem_byte(#)==lig_kern[#].b3
 20891  
 20892  @ Extensible characters are specified by an |@!extensible_recipe|, which
 20893  consists of four bytes called |@!top|, |@!mid|, |@!bot|, and |@!rep| (in this
 20894  order). These bytes are the character codes of individual pieces used to
 20895  build up a large symbol.  If |top|, |mid|, or |bot| are zero, they are not
 20896  present in the built-up result. For example, an extensible vertical line is
 20897  like an extensible bracket, except that the top and bottom pieces are missing.
 20898  
 20899  Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
 20900  if the piece isn't present. Then the extensible characters have the form
 20901  $TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
 20902  in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
 20903  The width of the extensible character is the width of $R$; and the
 20904  height-plus-depth is the sum of the individual height-plus-depths of the
 20905  components used, since the pieces are butted together in a vertical list.
 20906  
 20907  @d ext_top(#)==exten[#].b0 {|top| piece in a recipe}
 20908  @d ext_mid(#)==exten[#].b1 {|mid| piece in a recipe}
 20909  @d ext_bot(#)==exten[#].b2 {|bot| piece in a recipe}
 20910  @d ext_rep(#)==exten[#].b3 {|rep| piece in a recipe}
 20911  
 20912  @ The final portion of a \.{TFM} file is the |param| array, which is another
 20913  sequence of |fix_word| values.
 20914  
 20915  \yskip\hang|param[1]=slant| is the amount of italic slant, which is used
 20916  to help position accents. For example, |slant=.25| means that when you go
 20917  up one unit, you also go .25 units to the right. The |slant| is a pure
 20918  number; it is the only |fix_word| other than the design size itself that is
 20919  not scaled by the design size.
 20920  @^design size@>
 20921  
 20922  \hang|param[2]=space| is the normal spacing between words in text.
 20923  Note that character @'40 in the font need not have anything to do with
 20924  blank spaces.
 20925  
 20926  \hang|param[3]=space_stretch| is the amount of glue stretching between words.
 20927  
 20928  \hang|param[4]=space_shrink| is the amount of glue shrinking between words.
 20929  
 20930  \hang|param[5]=x_height| is the size of one ex in the font; it is also
 20931  the height of letters for which accents don't have to be raised or lowered.
 20932  
 20933  \hang|param[6]=quad| is the size of one em in the font.
 20934  
 20935  \hang|param[7]=extra_space| is the amount added to |param[2]| at the
 20936  ends of sentences.
 20937  
 20938  \yskip\noindent
 20939  If fewer than seven parameters are present, \TeX\ sets the missing parameters
 20940  to zero.
 20941  
 20942  @d slant_code=1
 20943  @d space_code=2
 20944  @d space_stretch_code=3
 20945  @d space_shrink_code=4
 20946  @d x_height_code=5
 20947  @d quad_code=6
 20948  @d extra_space_code=7
 20949  
 20950  @ So that is what \.{TFM} files hold. One of \MF's duties is to output such
 20951  information, and it does this all at once at the end of a job.
 20952  In order to prepare for such frenetic activity, it squirrels away the
 20953  necessary facts in various arrays as information becomes available.
 20954  
 20955  Character dimensions (\&{charwd}, \&{charht}, \&{chardp}, and \&{charic})
 20956  are stored respectively in |tfm_width|, |tfm_height|, |tfm_depth|, and
 20957  |tfm_ital_corr|. Other information about a character (e.g., about
 20958  its ligatures or successors) is accessible via the |char_tag| and
 20959  |char_remainder| arrays. Other information about the font as a whole
 20960  is kept in additional arrays called |header_byte|, |lig_kern|,
 20961  |kern|, |exten|, and |param|.
 20962  
 20963  @d undefined_label==lig_table_size {an undefined local label}
 20964  
 20965  @<Glob...@>=
 20966  @!bc,@!ec:eight_bits; {smallest and largest character codes shipped out}
 20967  @!tfm_width:array[eight_bits] of scaled; {\&{charwd} values}
 20968  @!tfm_height:array[eight_bits] of scaled; {\&{charht} values}
 20969  @!tfm_depth:array[eight_bits] of scaled; {\&{chardp} values}
 20970  @!tfm_ital_corr:array[eight_bits] of scaled; {\&{charic} values}
 20971  @!char_exists:array[eight_bits] of boolean; {has this code been shipped out?}
 20972  @!char_tag:array[eight_bits] of no_tag..ext_tag; {|remainder| category}
 20973  @!char_remainder:array[eight_bits] of 0..lig_table_size; {the |remainder| byte}
 20974  @!header_byte:array[1..header_size] of -1..255;
 20975    {bytes of the \.{TFM} header, or $-1$ if unset}
 20976  @!lig_kern:array[0..lig_table_size] of four_quarters; {the ligature/kern table}
 20977  @!nl:0..32767-256; {the number of ligature/kern steps so far}
 20978  @!kern:array[0..max_kerns] of scaled; {distinct kerning amounts}
 20979  @!nk:0..max_kerns; {the number of distinct kerns so far}
 20980  @!exten:array[eight_bits] of four_quarters; {extensible character recipes}
 20981  @!ne:0..256; {the number of extensible characters so far}
 20982  @!param:array[1..max_font_dimen] of scaled; {\&{fontdimen} parameters}
 20983  @!np:0..max_font_dimen; {the largest \&{fontdimen} parameter specified so far}
 20984  @!nw,@!nh,@!nd,@!ni:0..256; {sizes of \.{TFM} subtables}
 20985  @!skip_table:array[eight_bits] of 0..lig_table_size; {local label status}
 20986  @!lk_started:boolean; {has there been a lig/kern step in this command yet?}
 20987  @!bchar:integer; {right boundary character}
 20988  @!bch_label:0..lig_table_size; {left boundary starting location}
 20989  @!ll,@!lll:0..lig_table_size; {registers used for lig/kern processing}
 20990  @!label_loc:array[0..256] of -1..lig_table_size; {lig/kern starting addresses}
 20991  @!label_char:array[1..256] of eight_bits; {characters for |label_loc|}
 20992  @!label_ptr:0..256; {highest position occupied in |label_loc|}
 20993  
 20994  @ @<Set init...@>=
 20995  for k:=0 to 255 do
 20996    begin tfm_width[k]:=0; tfm_height[k]:=0; tfm_depth[k]:=0; tfm_ital_corr[k]:=0;
 20997    char_exists[k]:=false; char_tag[k]:=no_tag; char_remainder[k]:=0;
 20998    skip_table[k]:=undefined_label;
 20999    end;
 21000  for k:=1 to header_size do header_byte[k]:=-1;
 21001  bc:=255; ec:=0; nl:=0; nk:=0; ne:=0; np:=0;@/
 21002  internal[boundary_char]:=-unity;
 21003  bch_label:=undefined_label;@/
 21004  label_loc[0]:=-1; label_ptr:=0;
 21005  
 21006  @ @<Declare the function called |tfm_check|@>=
 21007  function tfm_check(@!m:small_number):scaled;
 21008  begin if abs(internal[m])>=fraction_half then
 21009    begin print_err("Enormous "); print(int_name[m]);
 21010  @.Enormous charwd...@>
 21011  @.Enormous chardp...@>
 21012  @.Enormous charht...@>
 21013  @.Enormous charic...@>
 21014  @.Enormous designsize...@>
 21015    print(" has been reduced");
 21016    help1("Font metric dimensions must be less than 2048pt.");
 21017    put_get_error;
 21018    if internal[m]>0 then tfm_check:=fraction_half-1
 21019    else tfm_check:=1-fraction_half;
 21020    end
 21021  else tfm_check:=internal[m];
 21022  end;
 21023  
 21024  @ @<Store the width information for character code~|c|@>=
 21025  if c<bc then bc:=c;
 21026  if c>ec then ec:=c;
 21027  char_exists[c]:=true;
 21028  gf_dx[c]:=internal[char_dx]; gf_dy[c]:=internal[char_dy];
 21029  tfm_width[c]:=tfm_check(char_wd);
 21030  tfm_height[c]:=tfm_check(char_ht);
 21031  tfm_depth[c]:=tfm_check(char_dp);
 21032  tfm_ital_corr[c]:=tfm_check(char_ic)
 21033  
 21034  @ Now let's consider \MF's special \.{TFM}-oriented commands.
 21035  
 21036  @<Cases of |do_statement|...@>=
 21037  tfm_command: do_tfm_command;
 21038  
 21039  @ @d char_list_code=0
 21040  @d lig_table_code=1
 21041  @d extensible_code=2
 21042  @d header_byte_code=3
 21043  @d font_dimen_code=4
 21044  
 21045  @<Put each...@>=
 21046  primitive("charlist",tfm_command,char_list_code);@/
 21047  @!@:char_list_}{\&{charlist} primitive@>
 21048  primitive("ligtable",tfm_command,lig_table_code);@/
 21049  @!@:lig_table_}{\&{ligtable} primitive@>
 21050  primitive("extensible",tfm_command,extensible_code);@/
 21051  @!@:extensible_}{\&{extensible} primitive@>
 21052  primitive("headerbyte",tfm_command,header_byte_code);@/
 21053  @!@:header_byte_}{\&{headerbyte} primitive@>
 21054  primitive("fontdimen",tfm_command,font_dimen_code);@/
 21055  @!@:font_dimen_}{\&{fontdimen} primitive@>
 21056  
 21057  @ @<Cases of |print_cmd...@>=
 21058  tfm_command: case m of
 21059    char_list_code:print("charlist");
 21060    lig_table_code:print("ligtable");
 21061    extensible_code:print("extensible");
 21062    header_byte_code:print("headerbyte");
 21063    othercases print("fontdimen")
 21064    endcases;
 21065  
 21066  @ @<Declare action procedures for use by |do_statement|@>=
 21067  function get_code:eight_bits; {scans a character code value}
 21068  label found;
 21069  var @!c:integer; {the code value found}
 21070  begin get_x_next; scan_expression;
 21071  if cur_type=known then
 21072    begin c:=round_unscaled(cur_exp);
 21073    if c>=0 then if c<256 then goto found;
 21074    end
 21075  else if cur_type=string_type then if length(cur_exp)=1 then
 21076    begin c:=so(str_pool[str_start[cur_exp]]); goto found;
 21077    end;
 21078  exp_err("Invalid code has been replaced by 0");
 21079  @.Invalid code...@>
 21080  help2("I was looking for a number between 0 and 255, or for a")@/
 21081    ("string of length 1. Didn't find it; will use 0 instead.");
 21082  put_get_flush_error(0); c:=0;
 21083  found: get_code:=c;
 21084  end;
 21085  
 21086  @ @<Declare action procedures for use by |do_statement|@>=
 21087  procedure set_tag(@!c:halfword;@!t:small_number;@!r:halfword);
 21088  begin if char_tag[c]=no_tag then
 21089    begin char_tag[c]:=t; char_remainder[c]:=r;
 21090    if t=lig_tag then
 21091      begin incr(label_ptr); label_loc[label_ptr]:=r; label_char[label_ptr]:=c;
 21092      end;
 21093    end
 21094  else @<Complain about a character tag conflict@>;
 21095  end;
 21096  
 21097  @ @<Complain about a character tag conflict@>=
 21098  begin print_err("Character ");
 21099  if (c>" ")and(c<127) then print(c)
 21100  else if c=256 then print("||")
 21101  else  begin print("code "); print_int(c);
 21102    end;
 21103  print(" is already ");
 21104  @.Character c is already...@>
 21105  case char_tag[c] of
 21106  lig_tag: print("in a ligtable");
 21107  list_tag: print("in a charlist");
 21108  ext_tag: print("extensible");
 21109  end; {there are no other cases}
 21110  help2("It's not legal to label a character more than once.")@/
 21111    ("So I'll not change anything just now.");
 21112  put_get_error; end
 21113  
 21114  @ @<Declare action procedures for use by |do_statement|@>=
 21115  procedure do_tfm_command;
 21116  label continue,done;
 21117  var @!c,@!cc:0..256; {character codes}
 21118  @!k:0..max_kerns; {index into the |kern| array}
 21119  @!j:integer; {index into |header_byte| or |param|}
 21120  begin case cur_mod of
 21121  char_list_code: begin c:=get_code;
 21122       {we will store a list of character successors}
 21123    while cur_cmd=colon do
 21124      begin cc:=get_code; set_tag(c,list_tag,cc); c:=cc;
 21125      end;
 21126    end;
 21127  lig_table_code: @<Store a list of ligature/kern steps@>;
 21128  extensible_code: @<Define an extensible recipe@>;
 21129  header_byte_code, font_dimen_code: begin c:=cur_mod; get_x_next;
 21130    scan_expression;
 21131    if (cur_type<>known)or(cur_exp<half_unit) then
 21132      begin exp_err("Improper location");
 21133  @.Improper location@>
 21134      help2("I was looking for a known, positive number.")@/
 21135        ("For safety's sake I'll ignore the present command.");
 21136      put_get_error;
 21137      end
 21138    else  begin j:=round_unscaled(cur_exp);
 21139      if cur_cmd<>colon then
 21140        begin missing_err(":");
 21141  @.Missing `:'@>
 21142        help1("A colon should follow a headerbyte or fontdimen location.");
 21143        back_error;
 21144        end;
 21145      if c=header_byte_code then @<Store a list of header bytes@>
 21146      else @<Store a list of font dimensions@>;
 21147      end;
 21148    end;
 21149  end; {there are no other cases}
 21150  end;
 21151  
 21152  @ @<Store a list of ligature/kern steps@>=
 21153  begin lk_started:=false;
 21154  continue: get_x_next;
 21155  if(cur_cmd=skip_to)and lk_started then
 21156   @<Process a |skip_to| command and |goto done|@>;
 21157  if cur_cmd=bchar_label then
 21158    begin c:=256; cur_cmd:=colon;@+end
 21159  else begin back_input; c:=get_code;@+end;
 21160  if(cur_cmd=colon)or(cur_cmd=double_colon)then
 21161    @<Record a label in a lig/kern subprogram and |goto continue|@>;
 21162  if cur_cmd=lig_kern_token then @<Compile a ligature/kern command@>
 21163  else  begin print_err("Illegal ligtable step");
 21164  @.Illegal ligtable step@>
 21165    help1("I was looking for `=:' or `kern' here.");
 21166    back_error; next_char(nl):=qi(0); op_byte(nl):=qi(0); rem_byte(nl):=qi(0);@/
 21167    skip_byte(nl):=stop_flag+1; {this specifies an unconditional stop}
 21168    end;
 21169  if nl=lig_table_size then overflow("ligtable size",lig_table_size);
 21170  @:METAFONT capacity exceeded ligtable size}{\quad ligtable size@>
 21171  incr(nl);
 21172  if cur_cmd=comma then goto continue;
 21173  if skip_byte(nl-1)<stop_flag then skip_byte(nl-1):=stop_flag;
 21174  done:end
 21175  
 21176  @ @<Put each...@>=
 21177  primitive("=:",lig_kern_token,0);
 21178  @!@:=:_}{\.{=:} primitive@>
 21179  primitive("=:|",lig_kern_token,1);
 21180  @!@:=:/_}{\.{=:\char'174} primitive@>
 21181  primitive("=:|>",lig_kern_token,5);
 21182  @!@:=:/>_}{\.{=:\char'174>} primitive@>
 21183  primitive("|=:",lig_kern_token,2);
 21184  @!@:=:/_}{\.{\char'174=:} primitive@>
 21185  primitive("|=:>",lig_kern_token,6);
 21186  @!@:=:/>_}{\.{\char'174=:>} primitive@>
 21187  primitive("|=:|",lig_kern_token,3);
 21188  @!@:=:/_}{\.{\char'174=:\char'174} primitive@>
 21189  primitive("|=:|>",lig_kern_token,7);
 21190  @!@:=:/>_}{\.{\char'174=:\char'174>} primitive@>
 21191  primitive("|=:|>>",lig_kern_token,11);
 21192  @!@:=:/>_}{\.{\char'174=:\char'174>>} primitive@>
 21193  primitive("kern",lig_kern_token,128);
 21194  @!@:kern_}{\&{kern} primitive@>
 21195  
 21196  @ @<Cases of |print_cmd...@>=
 21197  lig_kern_token: case m of
 21198  0:print("=:");
 21199  1:print("=:|");
 21200  2:print("|=:");
 21201  3:print("|=:|");
 21202  5:print("=:|>");
 21203  6:print("|=:>");
 21204  7:print("|=:|>");
 21205  11:print("|=:|>>");
 21206  othercases print("kern")
 21207  endcases;
 21208  
 21209  @ Local labels are implemented by maintaining the |skip_table| array,
 21210  where |skip_table[c]| is either |undefined_label| or the address of the
 21211  most recent lig/kern instruction that skips to local label~|c|. In the
 21212  latter case, the |skip_byte| in that instruction will (temporarily)
 21213  be zero if there were no prior skips to this label, or it will be the
 21214  distance to the prior skip.
 21215  
 21216  We may need to cancel skips that span more than 127 lig/kern steps.
 21217  
 21218  @d cancel_skips(#)==ll:=#;
 21219    repeat lll:=qo(skip_byte(ll)); skip_byte(ll):=stop_flag; ll:=ll-lll;
 21220    until lll=0
 21221  @d skip_error(#)==begin print_err("Too far to skip");
 21222  @.Too far to skip@>
 21223    help1("At most 127 lig/kern steps can separate skipto1 from 1::.");
 21224    error; cancel_skips(#);
 21225    end
 21226  
 21227  @<Process a |skip_to| command and |goto done|@>=
 21228  begin c:=get_code;
 21229  if nl-skip_table[c]>128 then
 21230    begin skip_error(skip_table[c]); skip_table[c]:=undefined_label;
 21231    end;
 21232  if skip_table[c]=undefined_label then skip_byte(nl-1):=qi(0)
 21233  else skip_byte(nl-1):=qi(nl-skip_table[c]-1);
 21234  skip_table[c]:=nl-1; goto done;
 21235  end
 21236  
 21237  @ @<Record a label in a lig/kern subprogram and |goto continue|@>=
 21238  begin if cur_cmd=colon then
 21239    if c=256 then bch_label:=nl
 21240    else set_tag(c,lig_tag,nl)
 21241  else if skip_table[c]<undefined_label then
 21242    begin ll:=skip_table[c]; skip_table[c]:=undefined_label;
 21243    repeat lll:=qo(skip_byte(ll));
 21244    if nl-ll>128 then
 21245      begin skip_error(ll); goto continue;
 21246      end;
 21247    skip_byte(ll):=qi(nl-ll-1); ll:=ll-lll;
 21248    until lll=0;
 21249    end;
 21250  goto continue;
 21251  end
 21252  
 21253  @ @<Compile a ligature/kern...@>=
 21254  begin next_char(nl):=qi(c); skip_byte(nl):=qi(0);
 21255  if cur_mod<128 then {ligature op}
 21256    begin op_byte(nl):=qi(cur_mod); rem_byte(nl):=qi(get_code);
 21257    end
 21258  else  begin get_x_next; scan_expression;
 21259    if cur_type<>known then
 21260      begin exp_err("Improper kern");
 21261  @.Improper kern@>
 21262      help2("The amount of kern should be a known numeric value.")@/
 21263        ("I'm zeroing this one. Proceed, with fingers crossed.");
 21264      put_get_flush_error(0);
 21265      end;
 21266    kern[nk]:=cur_exp;
 21267    k:=0;@+while kern[k]<>cur_exp do incr(k);
 21268    if k=nk then
 21269      begin if nk=max_kerns then overflow("kern",max_kerns);
 21270  @:METAFONT capacity exceeded kern}{\quad kern@>
 21271      incr(nk);
 21272      end;
 21273    op_byte(nl):=kern_flag+(k div 256);
 21274    rem_byte(nl):=qi((k mod 256));
 21275    end;
 21276  lk_started:=true;
 21277  end
 21278  
 21279  @ @d missing_extensible_punctuation(#)==
 21280    begin missing_err(#);
 21281  @.Missing `\char`\#'@>
 21282    help1("I'm processing `extensible c: t,m,b,r'."); back_error;
 21283    end
 21284  
 21285  @<Define an extensible recipe@>=
 21286  begin if ne=256 then overflow("extensible",256);
 21287  @:METAFONT capacity exceeded extensible}{\quad extensible@>
 21288  c:=get_code; set_tag(c,ext_tag,ne);
 21289  if cur_cmd<>colon then missing_extensible_punctuation(":");
 21290  ext_top(ne):=qi(get_code);
 21291  if cur_cmd<>comma then missing_extensible_punctuation(",");
 21292  ext_mid(ne):=qi(get_code);
 21293  if cur_cmd<>comma then missing_extensible_punctuation(",");
 21294  ext_bot(ne):=qi(get_code);
 21295  if cur_cmd<>comma then missing_extensible_punctuation(",");
 21296  ext_rep(ne):=qi(get_code);
 21297  incr(ne);
 21298  end
 21299  
 21300  @ @<Store a list of header bytes@>=
 21301  repeat if j>header_size then overflow("headerbyte",header_size);
 21302  @:METAFONT capacity exceeded headerbyte}{\quad headerbyte@>
 21303  header_byte[j]:=get_code; incr(j);
 21304  until cur_cmd<>comma
 21305  
 21306  @ @<Store a list of font dimensions@>=
 21307  repeat if j>max_font_dimen then overflow("fontdimen",max_font_dimen);
 21308  @:METAFONT capacity exceeded fontdimen}{\quad fontdimen@>
 21309  while j>np do
 21310    begin incr(np); param[np]:=0;
 21311    end;
 21312  get_x_next; scan_expression;
 21313  if cur_type<>known then
 21314    begin exp_err("Improper font parameter");
 21315  @.Improper font parameter@>
 21316    help1("I'm zeroing this one. Proceed, with fingers crossed.");
 21317    put_get_flush_error(0);
 21318    end;
 21319  param[j]:=cur_exp; incr(j);
 21320  until cur_cmd<>comma
 21321  
 21322  @ OK: We've stored all the data that is needed for the \.{TFM} file.
 21323  All that remains is to output it in the correct format.
 21324  
 21325  An interesting problem needs to be solved in this connection, because
 21326  the \.{TFM} format allows at most 256~widths, 16~heights, 16~depths,
 21327  and 64~italic corrections. If the data has more distinct values than
 21328  this, we want to meet the necessary restrictions by perturbing the
 21329  given values as little as possible.
 21330  
 21331  \MF\ solves this problem in two steps. First the values of a given
 21332  kind (widths, heights, depths, or italic corrections) are sorted;
 21333  then the list of sorted values is perturbed, if necessary.
 21334  
 21335  The sorting operation is facilitated by having a special node of
 21336  essentially infinite |value| at the end of the current list.
 21337  
 21338  @<Initialize table entries...@>=
 21339  value(inf_val):=fraction_four;
 21340  
 21341  @ Straight linear insertion is good enough for sorting, since the lists
 21342  are usually not terribly long. As we work on the data, the current list
 21343  will start at |link(temp_head)| and end at |inf_val|; the nodes in this
 21344  list will be in increasing order of their |value| fields.
 21345  
 21346  Given such a list, the |sort_in| function takes a value and returns a pointer
 21347  to where that value can be found in the list. The value is inserted in
 21348  the proper place, if necessary.
 21349  
 21350  At the time we need to do these operations, most of \MF's work has been
 21351  completed, so we will have plenty of memory to play with. The value nodes
 21352  that are allocated for sorting will never be returned to free storage.
 21353  
 21354  @d clear_the_list==link(temp_head):=inf_val
 21355  
 21356  @p function sort_in(@!v:scaled):pointer;
 21357  label found;
 21358  var @!p,@!q,@!r:pointer; {list manipulation registers}
 21359  begin p:=temp_head;
 21360  loop@+  begin q:=link(p);
 21361    if v<=value(q) then goto found;
 21362    p:=q;
 21363    end;
 21364  found: if v<value(q) then
 21365    begin r:=get_node(value_node_size); value(r):=v; link(r):=q; link(p):=r;
 21366    end;
 21367  sort_in:=link(p);
 21368  end;
 21369  
 21370  @ Now we come to the interesting part, where we reduce the list if necessary
 21371  until it has the required size. The |min_cover| routine is basic to this
 21372  process; it computes the minimum number~|m| such that the values of the
 21373  current sorted list can be covered by |m|~intervals of width~|d|. It
 21374  also sets the global value |perturbation| to the smallest value $d'>d$
 21375  such that the covering found by this algorithm would be different.
 21376  
 21377  In particular, |min_cover(0)| returns the number of distinct values in the
 21378  current list and sets |perturbation| to the minimum distance between
 21379  adjacent values.
 21380  
 21381  @p function min_cover(@!d:scaled):integer;
 21382  var @!p:pointer; {runs through the current list}
 21383  @!l:scaled; {the least element covered by the current interval}
 21384  @!m:integer; {lower bound on the size of the minimum cover}
 21385  begin m:=0; p:=link(temp_head); perturbation:=el_gordo;
 21386  while p<>inf_val do
 21387    begin incr(m); l:=value(p);
 21388    repeat p:=link(p);
 21389    until value(p)>l+d;
 21390    if value(p)-l<perturbation then perturbation:=value(p)-l;
 21391    end;
 21392  min_cover:=m;
 21393  end;
 21394  
 21395  @ @<Glob...@>=
 21396  @!perturbation:scaled; {quantity related to \.{TFM} rounding}
 21397  @!excess:integer; {the list is this much too long}
 21398  
 21399  @ The smallest |d| such that a given list can be covered with |m| intervals
 21400  is determined by the |threshold| routine, which is sort of an inverse
 21401  to |min_cover|. The idea is to increase the interval size rapidly until
 21402  finding the range, then to go sequentially until the exact borderline has
 21403  been discovered.
 21404  
 21405  @p function threshold(@!m:integer):scaled;
 21406  var @!d:scaled; {lower bound on the smallest interval size}
 21407  begin excess:=min_cover(0)-m;
 21408  if excess<=0 then threshold:=0
 21409  else  begin repeat d:=perturbation;
 21410    until min_cover(d+d)<=m;
 21411    while min_cover(d)>m do d:=perturbation;
 21412    threshold:=d;
 21413    end;
 21414  end;
 21415  
 21416  @ The |skimp| procedure reduces the current list to at most |m| entries,
 21417  by changing values if necessary. It also sets |info(p):=k| if |value(p)|
 21418  is the |k|th distinct value on the resulting list, and it sets
 21419  |perturbation| to the maximum amount by which a |value| field has
 21420  been changed. The size of the resulting list is returned as the
 21421  value of |skimp|.
 21422  
 21423  @p function skimp(@!m:integer):integer;
 21424  var @!d:scaled; {the size of intervals being coalesced}
 21425  @!p,@!q,@!r:pointer; {list manipulation registers}
 21426  @!l:scaled; {the least value in the current interval}
 21427  @!v:scaled; {a compromise value}
 21428  begin d:=threshold(m); perturbation:=0;
 21429  q:=temp_head; m:=0; p:=link(temp_head);
 21430  while p<>inf_val do
 21431    begin incr(m); l:=value(p); info(p):=m;
 21432    if value(link(p))<=l+d then
 21433      @<Replace an interval of values by its midpoint@>;
 21434    q:=p; p:=link(p);
 21435    end;
 21436  skimp:=m;
 21437  end;
 21438  
 21439  @ @<Replace an interval...@>=
 21440  begin repeat p:=link(p); info(p):=m;
 21441  decr(excess);@+if excess=0 then d:=0;
 21442  until value(link(p))>l+d;
 21443  v:=l+half(value(p)-l);
 21444  if value(p)-v>perturbation then perturbation:=value(p)-v;
 21445  r:=q;
 21446  repeat r:=link(r); value(r):=v;
 21447  until r=p;
 21448  link(q):=p; {remove duplicate values from the current list}
 21449  end
 21450  
 21451  @ A warning message is issued whenever something is perturbed by
 21452  more than 1/16\thinspace pt.
 21453  
 21454  @p procedure tfm_warning(@!m:small_number);
 21455  begin print_nl("(some "); print(int_name[m]);
 21456  @.some charwds...@>
 21457  @.some chardps...@>
 21458  @.some charhts...@>
 21459  @.some charics...@>
 21460  print(" values had to be adjusted by as much as ");
 21461  print_scaled(perturbation); print("pt)");
 21462  end;
 21463  
 21464  @ Here's an example of how we use these routines.
 21465  The width data needs to be perturbed only if there are 256 distinct
 21466  widths, but \MF\ must check for this case even though it is
 21467  highly unusual.
 21468  
 21469  An integer variable |k| will be defined when we use this code.
 21470  The |dimen_head| array will contain pointers to the sorted
 21471  lists of dimensions.
 21472  
 21473  @<Massage the \.{TFM} widths@>=
 21474  clear_the_list;
 21475  for k:=bc to ec do if char_exists[k] then
 21476    tfm_width[k]:=sort_in(tfm_width[k]);
 21477  nw:=skimp(255)+1; dimen_head[1]:=link(temp_head);
 21478  if perturbation>=@'10000 then tfm_warning(char_wd)
 21479  
 21480  @ @<Glob...@>=
 21481  @!dimen_head:array[1..4] of pointer; {lists of \.{TFM} dimensions}
 21482  
 21483  @ Heights, depths, and italic corrections are different from widths
 21484  not only because their list length is more severely restricted, but
 21485  also because zero values do not need to be put into the lists.
 21486  
 21487  @<Massage the \.{TFM} heights, depths, and italic corrections@>=
 21488  clear_the_list;
 21489  for k:=bc to ec do if char_exists[k] then
 21490    if tfm_height[k]=0 then tfm_height[k]:=zero_val
 21491    else tfm_height[k]:=sort_in(tfm_height[k]);
 21492  nh:=skimp(15)+1; dimen_head[2]:=link(temp_head);
 21493  if perturbation>=@'10000 then tfm_warning(char_ht);
 21494  clear_the_list;
 21495  for k:=bc to ec do if char_exists[k] then
 21496    if tfm_depth[k]=0 then tfm_depth[k]:=zero_val
 21497    else tfm_depth[k]:=sort_in(tfm_depth[k]);
 21498  nd:=skimp(15)+1; dimen_head[3]:=link(temp_head);
 21499  if perturbation>=@'10000 then tfm_warning(char_dp);
 21500  clear_the_list;
 21501  for k:=bc to ec do if char_exists[k] then
 21502    if tfm_ital_corr[k]=0 then tfm_ital_corr[k]:=zero_val
 21503    else tfm_ital_corr[k]:=sort_in(tfm_ital_corr[k]);
 21504  ni:=skimp(63)+1; dimen_head[4]:=link(temp_head);
 21505  if perturbation>=@'10000 then tfm_warning(char_ic)
 21506  
 21507  @ @<Initialize table entries...@>=
 21508  value(zero_val):=0; info(zero_val):=0;
 21509  
 21510  @ Bytes 5--8 of the header are set to the design size, unless the user has
 21511  some crazy reason for specifying them differently.
 21512  @^design size@>
 21513  
 21514  Error messages are not allowed at the time this procedure is called,
 21515  so a warning is printed instead.
 21516  
 21517  The value of |max_tfm_dimen| is calculated so that
 21518  $$\hbox{|make_scaled(16*max_tfm_dimen,internal[design_size])|}
 21519   < \\{three\_bytes}.$$
 21520  
 21521  @d three_bytes==@'100000000 {$2^{24}$}
 21522  
 21523  @p procedure fix_design_size;
 21524  var @!d:scaled; {the design size}
 21525  begin d:=internal[design_size];
 21526  if (d<unity)or(d>=fraction_half) then
 21527    begin if d<>0 then
 21528      print_nl("(illegal design size has been changed to 128pt)");
 21529  @.illegal design size...@>
 21530    d:=@'40000000; internal[design_size]:=d;
 21531    end;
 21532  if header_byte[5]<0 then if header_byte[6]<0 then
 21533    if header_byte[7]<0 then if header_byte[8]<0 then
 21534    begin header_byte[5]:=d div @'4000000;
 21535    header_byte[6]:=(d div 4096) mod 256;
 21536    header_byte[7]:=(d div 16) mod 256;
 21537    header_byte[8]:=(d mod 16)*16;
 21538    end;
 21539  max_tfm_dimen:=16*internal[design_size]-1-internal[design_size] div @'10000000;
 21540  if max_tfm_dimen>=fraction_half then max_tfm_dimen:=fraction_half-1;
 21541  end;
 21542  
 21543  @ The |dimen_out| procedure computes a |fix_word| relative to the
 21544  design size. If the data was out of range, it is corrected and the
 21545  global variable |tfm_changed| is increased by~one.
 21546  
 21547  @p function dimen_out(@!x:scaled):integer;
 21548  begin if abs(x)>max_tfm_dimen then
 21549    begin incr(tfm_changed);
 21550    if x>0 then x:=max_tfm_dimen@+else x:=-max_tfm_dimen;
 21551    end;
 21552  x:=make_scaled(x*16,internal[design_size]);
 21553  dimen_out:=x;
 21554  end;
 21555  
 21556  @ @<Glob...@>=
 21557  @!max_tfm_dimen:scaled; {bound on widths, heights, kerns, etc.}
 21558  @!tfm_changed:integer; {the number of data entries that were out of bounds}
 21559  
 21560  @ If the user has not specified any of the first four header bytes,
 21561  the |fix_check_sum| procedure replaces them by a ``check sum'' computed
 21562  from the |tfm_width| data relative to the design size.
 21563  @^check sum@>
 21564  
 21565  @p procedure fix_check_sum;
 21566  label exit;
 21567  var @!k:eight_bits; {runs through character codes}
 21568  @!b1,@!b2,@!b3,@!b4:eight_bits; {bytes of the check sum}
 21569  @!x:integer; {hash value used in check sum computation}
 21570  begin if header_byte[1]<0 then if header_byte[2]<0 then
 21571    if header_byte[3]<0 then if header_byte[4]<0 then
 21572    begin @<Compute a check sum in |(b1,b2,b3,b4)|@>;
 21573    header_byte[1]:=b1; header_byte[2]:=b2;
 21574    header_byte[3]:=b3; header_byte[4]:=b4; return;
 21575    end;
 21576  for k:=1 to 4 do if header_byte[k]<0 then header_byte[k]:=0;
 21577  exit:end;
 21578  
 21579  @ @<Compute a check sum in |(b1,b2,b3,b4)|@>=
 21580  b1:=bc; b2:=ec; b3:=bc; b4:=ec; tfm_changed:=0;
 21581  for k:=bc to ec do if char_exists[k] then
 21582    begin x:=dimen_out(value(tfm_width[k]))+(k+4)*@'20000000; {this is positive}
 21583    b1:=(b1+b1+x) mod 255;
 21584    b2:=(b2+b2+x) mod 253;
 21585    b3:=(b3+b3+x) mod 251;
 21586    b4:=(b4+b4+x) mod 247;
 21587    end
 21588  
 21589  @ Finally we're ready to actually write the \.{TFM} information.
 21590  Here are some utility routines for this purpose.
 21591  
 21592  @d tfm_out(#)==write(tfm_file,#) {output one byte to |tfm_file|}
 21593  
 21594  @p procedure tfm_two(@!x:integer); {output two bytes to |tfm_file|}
 21595  begin tfm_out(x div 256); tfm_out(x mod 256);
 21596  end;
 21597  @#
 21598  procedure tfm_four(@!x:integer); {output four bytes to |tfm_file|}
 21599  begin if x>=0 then tfm_out(x div three_bytes)
 21600  else  begin x:=x+@'10000000000; {use two's complement for negative values}
 21601    x:=x+@'10000000000;
 21602    tfm_out((x div three_bytes) + 128);
 21603    end;
 21604  x:=x mod three_bytes; tfm_out(x div unity);
 21605  x:=x mod unity; tfm_out(x div @'400);
 21606  tfm_out(x mod @'400);
 21607  end;
 21608  @#
 21609  procedure tfm_qqqq(@!x:four_quarters); {output four quarterwords to |tfm_file|}
 21610  begin tfm_out(qo(x.b0)); tfm_out(qo(x.b1)); tfm_out(qo(x.b2));
 21611  tfm_out(qo(x.b3));
 21612  end;
 21613  
 21614  @ @<Finish the \.{TFM} file@>=
 21615  if job_name=0 then open_log_file;
 21616  pack_job_name(".tfm");
 21617  while not b_open_out(tfm_file) do
 21618    prompt_file_name("file name for font metrics",".tfm");
 21619  metric_file_name:=b_make_name_string(tfm_file);
 21620  @<Output the subfile sizes and header bytes@>;
 21621  @<Output the character information bytes, then
 21622    output the dimensions themselves@>;
 21623  @<Output the ligature/kern program@>;
 21624  @<Output the extensible character recipes and the font metric parameters@>;
 21625  @!stat if internal[tracing_stats]>0 then
 21626    @<Log the subfile sizes of the \.{TFM} file@>;@;@+tats@/
 21627  print_nl("Font metrics written on "); slow_print(metric_file_name);
 21628  print_char(".");
 21629  @.Font metrics written...@>
 21630  b_close(tfm_file)
 21631  
 21632  @ Integer variables |lh|, |k|, and |lk_offset| will be defined when we use
 21633  this code.
 21634  
 21635  @<Output the subfile sizes and header bytes@>=
 21636  k:=header_size;
 21637  while header_byte[k]<0 do decr(k);
 21638  lh:=(k+3) div 4; {this is the number of header words}
 21639  if bc>ec then bc:=1; {if there are no characters, |ec=0| and |bc=1|}
 21640  @<Compute the ligature/kern program offset and implant the
 21641    left boundary label@>;
 21642  tfm_two(6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+lk_offset+nk+ne+np);
 21643    {this is the total number of file words that will be output}
 21644  tfm_two(lh); tfm_two(bc); tfm_two(ec); tfm_two(nw); tfm_two(nh);
 21645  tfm_two(nd); tfm_two(ni); tfm_two(nl+lk_offset); tfm_two(nk); tfm_two(ne);
 21646  tfm_two(np);
 21647  for k:=1 to 4*lh do
 21648    begin if header_byte[k]<0 then header_byte[k]:=0;
 21649    tfm_out(header_byte[k]);
 21650    end
 21651  
 21652  @ @<Output the character information bytes...@>=
 21653  for k:=bc to ec do
 21654    if not char_exists[k] then tfm_four(0)
 21655    else  begin tfm_out(info(tfm_width[k])); {the width index}
 21656      tfm_out((info(tfm_height[k]))*16+info(tfm_depth[k]));
 21657      tfm_out((info(tfm_ital_corr[k]))*4+char_tag[k]);
 21658      tfm_out(char_remainder[k]);
 21659      end;
 21660  tfm_changed:=0;
 21661  for k:=1 to 4 do
 21662    begin tfm_four(0); p:=dimen_head[k];
 21663    while p<>inf_val do
 21664      begin tfm_four(dimen_out(value(p))); p:=link(p);
 21665      end;
 21666    end
 21667  
 21668  @ We need to output special instructions at the beginning of the
 21669  |lig_kern| array in order to specify the right boundary character
 21670  and/or to handle starting addresses that exceed 255. The |label_loc|
 21671  and |label_char| arrays have been set up to record all the
 21672  starting addresses; we have $-1=|label_loc|[0]<|label_loc|[1]\le\cdots
 21673  \le|label_loc|[|label_ptr]|$.
 21674  
 21675  @<Compute the ligature/kern program offset...@>=
 21676  bchar:=round_unscaled(internal[boundary_char]);
 21677  if(bchar<0)or(bchar>255)then
 21678    begin bchar:=-1; lk_started:=false; lk_offset:=0;@+end
 21679  else begin lk_started:=true; lk_offset:=1;@+end;
 21680  @<Find the minimum |lk_offset| and adjust all remainders@>;
 21681  if bch_label<undefined_label then
 21682    begin skip_byte(nl):=qi(255); next_char(nl):=qi(0);
 21683    op_byte(nl):=qi(((bch_label+lk_offset)div 256));
 21684    rem_byte(nl):=qi(((bch_label+lk_offset)mod 256));
 21685    incr(nl); {possibly |nl=lig_table_size+1|}
 21686    end
 21687  
 21688  @ @<Find the minimum |lk_offset|...@>=
 21689  k:=label_ptr; {pointer to the largest unallocated label}
 21690  if label_loc[k]+lk_offset>255 then
 21691    begin lk_offset:=0; lk_started:=false; {location 0 can do double duty}
 21692    repeat char_remainder[label_char[k]]:=lk_offset;
 21693    while label_loc[k-1]=label_loc[k] do
 21694      begin decr(k); char_remainder[label_char[k]]:=lk_offset;
 21695      end;
 21696    incr(lk_offset); decr(k);
 21697    until lk_offset+label_loc[k]<256;
 21698      {N.B.: |lk_offset=256| satisfies this when |k=0|}
 21699    end;
 21700  if lk_offset>0 then
 21701    while k>0 do
 21702      begin char_remainder[label_char[k]]
 21703       :=char_remainder[label_char[k]]+lk_offset;
 21704      decr(k);
 21705      end
 21706  
 21707  @ @<Output the ligature/kern program@>=
 21708  for k:=0 to 255 do if skip_table[k]<undefined_label then
 21709    begin print_nl("(local label "); print_int(k); print(":: was missing)");
 21710  @.local label l:: was missing@>
 21711    cancel_skips(skip_table[k]);
 21712    end;
 21713  if lk_started then {|lk_offset=1| for the special |bchar|}
 21714    begin tfm_out(255); tfm_out(bchar); tfm_two(0);
 21715    end
 21716  else for k:=1 to lk_offset do {output the redirection specs}
 21717    begin ll:=label_loc[label_ptr];
 21718    if bchar<0 then
 21719      begin tfm_out(254); tfm_out(0);
 21720      end
 21721    else begin tfm_out(255); tfm_out(bchar);
 21722      end;
 21723    tfm_two(ll+lk_offset);
 21724    repeat decr(label_ptr);
 21725    until label_loc[label_ptr]<ll;
 21726    end;
 21727  for k:=0 to nl-1 do tfm_qqqq(lig_kern[k]);
 21728  for k:=0 to nk-1 do tfm_four(dimen_out(kern[k]))
 21729  
 21730  @ @<Output the extensible character recipes...@>=
 21731  for k:=0 to ne-1 do tfm_qqqq(exten[k]);
 21732  for k:=1 to np do
 21733    if k=1 then
 21734      if abs(param[1])<fraction_half then tfm_four(param[1]*16)
 21735      else  begin incr(tfm_changed);
 21736        if param[1]>0 then tfm_four(el_gordo)
 21737        else tfm_four(-el_gordo);
 21738        end
 21739    else tfm_four(dimen_out(param[k]));
 21740  if tfm_changed>0 then
 21741    begin if tfm_changed=1 then print_nl("(a font metric dimension")
 21742  @.a font metric dimension...@>
 21743    else  begin print_nl("("); print_int(tfm_changed);
 21744  @.font metric dimensions...@>
 21745      print(" font metric dimensions");
 21746      end;
 21747    print(" had to be decreased)");
 21748    end
 21749  
 21750  @ @<Log the subfile sizes of the \.{TFM} file@>=
 21751  begin wlog_ln(' ');
 21752  if bch_label<undefined_label then decr(nl);
 21753  wlog_ln('(You used ',nw:1,'w,',@| nh:1,'h,',@| nd:1,'d,',@| ni:1,'i,',@|
 21754   nl:1,'l,',@| nk:1,'k,',@| ne:1,'e,',@|
 21755   np:1,'p metric file positions');
 21756  wlog_ln('  out of ',@| '256w,16h,16d,64i,',@|
 21757   lig_table_size:1,'l,',max_kerns:1,'k,256e,',@|
 21758   max_font_dimen:1,'p)');
 21759  end
 21760  
 21761  @* \[46] Generic font file format.
 21762  The most important output produced by a typical run of \MF\ is the
 21763  ``generic font'' (\.{GF}) file that specifies the bit patterns of the
 21764  characters that have been drawn. The term {\sl generic\/} indicates that
 21765  this file format doesn't match the conventions of any name-brand manufacturer;
 21766  but it is easy to convert \.{GF} files to the special format required by
 21767  almost all digital phototypesetting equipment. There's a strong analogy
 21768  between the \.{DVI} files written by \TeX\ and the \.{GF} files written
 21769  by \MF; and, in fact, the file formats have a lot in common.
 21770  
 21771  A \.{GF} file is a stream of 8-bit bytes that may be
 21772  regarded as a series of commands in a machine-like language. The first
 21773  byte of each command is the operation code, and this code is followed by
 21774  zero or more bytes that provide parameters to the command. The parameters
 21775  themselves may consist of several consecutive bytes; for example, the
 21776  `|boc|' (beginning of character) command has six parameters, each of
 21777  which is four bytes long. Parameters are usually regarded as nonnegative
 21778  integers; but four-byte-long parameters can be either positive or
 21779  negative, hence they range in value from $-2^{31}$ to $2^{31}-1$.
 21780  As in \.{TFM} files, numbers that occupy
 21781  more than one byte position appear in BigEndian order,
 21782  and negative numbers appear in two's complement notation.
 21783  
 21784  A \.{GF} file consists of a ``preamble,'' followed by a sequence of one or
 21785  more ``characters,'' followed by a ``postamble.'' The preamble is simply a
 21786  |pre| command, with its parameters that introduce the file; this must come
 21787  first.  Each ``character'' consists of a |boc| command, followed by any
 21788  number of other commands that specify ``black'' pixels,
 21789  followed by an |eoc| command. The characters appear in the order that \MF\
 21790  generated them. If we ignore no-op commands (which are allowed between any
 21791  two commands in the file), each |eoc| command is immediately followed by a
 21792  |boc| command, or by a |post| command; in the latter case, there are no
 21793  more characters in the file, and the remaining bytes form the postamble.
 21794  Further details about the postamble will be explained later.
 21795  
 21796  Some parameters in \.{GF} commands are ``pointers.'' These are four-byte
 21797  quantities that give the location number of some other byte in the file;
 21798  the first file byte is number~0, then comes number~1, and so on.
 21799  
 21800  @ The \.{GF} format is intended to be both compact and easily interpreted
 21801  by a machine. Compactness is achieved by making most of the information
 21802  relative instead of absolute. When a \.{GF}-reading program reads the
 21803  commands for a character, it keeps track of two quantities: (a)~the current
 21804  column number,~|m|; and (b)~the current row number,~|n|.  These are 32-bit
 21805  signed integers, although most actual font formats produced from \.{GF}
 21806  files will need to curtail this vast range because of practical
 21807  limitations. (\MF\ output will never allow $\vert m\vert$ or $\vert
 21808  n\vert$ to get extremely large, but the \.{GF} format tries to be more general.)
 21809  
 21810  How do \.{GF}'s row and column numbers correspond to the conventions
 21811  of \TeX\ and \MF? Well, the ``reference point'' of a character, in \TeX's
 21812  view, is considered to be at the lower left corner of the pixel in row~0
 21813  and column~0. This point is the intersection of the baseline with the left
 21814  edge of the type; it corresponds to location $(0,0)$ in \MF\ programs.
 21815  Thus the pixel in \.{GF} row~0 and column~0 is \MF's unit square, comprising the
 21816  region of the plane whose coordinates both lie between 0 and~1. The
 21817  pixel in \.{GF} row~|n| and column~|m| consists of the points whose \MF\
 21818  coordinates |(x,y)| satisfy |m<=x<=m+1| and |n<=y<=n+1|.  Negative values of
 21819  |m| and~|x| correspond to columns of pixels {\sl left\/} of the reference
 21820  point; negative values of |n| and~|y| correspond to rows of pixels {\sl
 21821  below\/} the baseline.
 21822  
 21823  Besides |m| and |n|, there's also a third aspect of the current
 21824  state, namely the @!|paint_switch|, which is always either |black| or
 21825  |white|. Each \\{paint} command advances |m| by a specified amount~|d|,
 21826  and blackens the intervening pixels if |paint_switch=black|; then
 21827  the |paint_switch| changes to the opposite state. \.{GF}'s commands are
 21828  designed so that |m| will never decrease within a row, and |n| will never
 21829  increase within a character; hence there is no way to whiten a pixel that
 21830  has been blackened.
 21831  
 21832  @ Here is a list of all the commands that may appear in a \.{GF} file. Each
 21833  command is specified by its symbolic name (e.g., |boc|), its opcode byte
 21834  (e.g., 67), and its parameters (if any). The parameters are followed
 21835  by a bracketed number telling how many bytes they occupy; for example,
 21836  `|d[2]|' means that parameter |d| is two bytes long.
 21837  
 21838  \yskip\hang|paint_0| 0. This is a \\{paint} command with |d=0|; it does
 21839  nothing but change the |paint_switch| from \\{black} to \\{white} or vice~versa.
 21840  
 21841  \yskip\hang\\{paint\_1} through \\{paint\_63} (opcodes 1 to 63).
 21842  These are \\{paint} commands with |d=1| to~63, defined as follows: If
 21843  |paint_switch=black|, blacken |d|~pixels of the current row~|n|,
 21844  in columns |m| through |m+d-1| inclusive. Then, in any case,
 21845  complement the |paint_switch| and advance |m| by~|d|.
 21846  
 21847  \yskip\hang|paint1| 64 |d[1]|. This is a \\{paint} command with a specified
 21848  value of~|d|; \MF\ uses it to paint when |64<=d<256|.
 21849  
 21850  \yskip\hang|@!paint2| 65 |d[2]|. Same as |paint1|, but |d|~can be as high
 21851  as~65535.
 21852  
 21853  \yskip\hang|@!paint3| 66 |d[3]|. Same as |paint1|, but |d|~can be as high
 21854  as $2^{24}-1$. \MF\ never needs this command, and it is hard to imagine
 21855  anybody making practical use of it; surely a more compact encoding will be
 21856  desirable when characters can be this large. But the command is there,
 21857  anyway, just in case.
 21858  
 21859  \yskip\hang|boc| 67 |c[4]| |p[4]| |min_m[4]| |max_m[4]| |min_n[4]|
 21860  |max_n[4]|. Beginning of a character:  Here |c| is the character code, and
 21861  |p| points to the previous character beginning (if any) for characters having
 21862  this code number modulo 256.  (The pointer |p| is |-1| if there was no
 21863  prior character with an equivalent code.) The values of registers |m| and |n|
 21864  defined by the instructions that follow for this character must
 21865  satisfy |min_m<=m<=max_m| and |min_n<=n<=max_n|.  (The values of |max_m| and
 21866  |min_n| need not be the tightest bounds possible.)  When a \.{GF}-reading
 21867  program sees a |boc|, it can use |min_m|, |max_m|, |min_n|, and |max_n| to
 21868  initialize the bounds of an array. Then it sets |m:=min_m|, |n:=max_n|, and
 21869  |paint_switch:=white|.
 21870  
 21871  \yskip\hang|boc1| 68 |c[1]| |@!del_m[1]| |max_m[1]| |@!del_n[1]| |max_n[1]|.
 21872  Same as |boc|, but |p| is assumed to be~$-1$; also |del_m=max_m-min_m|
 21873  and |del_n=max_n-min_n| are given instead of |min_m| and |min_n|.
 21874  The one-byte parameters must be between 0 and 255, inclusive.
 21875  \ (This abbreviated |boc| saves 19~bytes per character, in common cases.)
 21876  
 21877  \yskip\hang|eoc| 69. End of character: All pixels blackened so far
 21878  constitute the pattern for this character. In particular, a completely
 21879  blank character might have |eoc| immediately following |boc|.
 21880  
 21881  \yskip\hang|skip0| 70. Decrease |n| by 1 and set |m:=min_m|,
 21882  |paint_switch:=white|. \ (This finishes one row and begins another,
 21883  ready to whiten the leftmost pixel in the new row.)
 21884  
 21885  \yskip\hang|skip1| 71 |d[1]|. Decrease |n| by |d+1|, set |m:=min_m|, and set
 21886  |paint_switch:=white|. This is a way to produce |d| all-white rows.
 21887  
 21888  \yskip\hang|@!skip2| 72 |d[2]|. Same as |skip1|, but |d| can be as large
 21889  as 65535.
 21890  
 21891  \yskip\hang|@!skip3| 73 |d[3]|. Same as |skip1|, but |d| can be as large
 21892  as $2^{24}-1$. \MF\ obviously never needs this command.
 21893  
 21894  \yskip\hang|new_row_0| 74. Decrease |n| by 1 and set |m:=min_m|,
 21895  |paint_switch:=black|. \ (This finishes one row and begins another,
 21896  ready to {\sl blacken\/} the leftmost pixel in the new row.)
 21897  
 21898  \yskip\hang|@!new_row_1| through |@!new_row_164| (opcodes 75 to 238). Same as
 21899  |new_row_0|, but with |m:=min_m+1| through |min_m+164|, respectively.
 21900  
 21901  \yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
 21902  general; it functions as a $(k+2)$-byte |no_op| unless special \.{GF}-reading
 21903  programs are being used. \MF\ generates \\{xxx} commands when encountering
 21904  a \&{special} string; this occurs in the \.{GF} file only between
 21905  characters, after the preamble, and before the postamble. However,
 21906  \\{xxx} commands might appear within characters,
 21907  in \.{GF} files generated by other
 21908  processors. It is recommended that |x| be a string having the form of a
 21909  keyword followed by possible parameters relevant to that keyword.
 21910  
 21911  \yskip\hang|@!xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
 21912  
 21913  \yskip\hang|xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<@t$2^{24}$@>|.
 21914  \MF\ uses this when sending a \&{special} string whose length exceeds~255.
 21915  
 21916  \yskip\hang|@!xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be
 21917  ridiculously large; |k| mustn't be negative.
 21918  
 21919  \yskip\hang|yyy| 243 |y[4]|. This command is undefined in general;
 21920  it functions as a 5-byte |no_op| unless special \.{GF}-reading programs
 21921  are being used. \MF\ puts |scaled| numbers into |yyy|'s, as a
 21922  result of \&{numspecial} commands; the intent is to provide numeric
 21923  parameters to \\{xxx} commands that immediately precede.
 21924  
 21925  \yskip\hang|@!no_op| 244. No operation, do nothing. Any number of |no_op|'s
 21926  may occur between \.{GF} commands, but a |no_op| cannot be inserted between
 21927  a command and its parameters or between two parameters.
 21928  
 21929  \yskip\hang|char_loc| 245 |c[1]| |dx[4]| |dy[4]| |w[4]| |p[4]|.
 21930  This command will appear only in the postamble, which will be explained shortly.
 21931  
 21932  \yskip\hang|@!char_loc0| 246 |c[1]| |@!dm[1]| |w[4]| |p[4]|.
 21933  Same as |char_loc|, except that |dy| is assumed to be zero, and the value
 21934  of~|dx| is taken to be |65536*dm|, where |0<=dm<256|.
 21935  
 21936  \yskip\hang|pre| 247 |i[1]| |k[1]| |x[k]|.
 21937  Beginning of the preamble; this must come at the very beginning of the
 21938  file. Parameter |i| is an identifying number for \.{GF} format, currently
 21939  131. The other information is merely commentary; it is not given
 21940  special interpretation like \\{xxx} commands are. (Note that \\{xxx}
 21941  commands may immediately follow the preamble, before the first |boc|.)
 21942  
 21943  \yskip\hang|post| 248. Beginning of the postamble, see below.
 21944  
 21945  \yskip\hang|post_post| 249. Ending of the postamble, see below.
 21946  
 21947  \yskip\noindent Commands 250--255 are undefined at the present time.
 21948  
 21949  @d gf_id_byte=131 {identifies the kind of \.{GF} files described here}
 21950  
 21951  @ \MF\ refers to the following opcodes explicitly.
 21952  
 21953  @d paint_0=0 {beginning of the \\{paint} commands}
 21954  @d paint1=64 {move right a given number of columns, then
 21955    black${}\swap{}$white}
 21956  @d boc=67 {beginning of a character}
 21957  @d boc1=68 {short form of |boc|}
 21958  @d eoc=69 {end of a character}
 21959  @d skip0=70 {skip no blank rows}
 21960  @d skip1=71 {skip over blank rows}
 21961  @d new_row_0=74 {move down one row and then right}
 21962  @d max_new_row=164 {the largest \\{new\_row} command is |new_row_164|}
 21963  @d xxx1=239 {for \&{special} strings}
 21964  @d xxx3=241 {for long \&{special} strings}
 21965  @d yyy=243 {for \&{numspecial} numbers}
 21966  @d char_loc=245 {character locators in the postamble}
 21967  @d pre=247 {preamble}
 21968  @d post=248 {postamble beginning}
 21969  @d post_post=249 {postamble ending}
 21970  
 21971  @ The last character in a \.{GF} file is followed by `|post|'; this command
 21972  introduces the postamble, which summarizes important facts that \MF\ has
 21973  accumulated. The postamble has the form
 21974  $$\vbox{\halign{\hbox{#\hfil}\cr
 21975    |post| |p[4]| |@!ds[4]| |@!cs[4]| |@!hppp[4]| |@!vppp[4]|
 21976     |@!min_m[4]| |@!max_m[4]| |@!min_n[4]| |@!max_n[4]|\cr
 21977    $\langle\,$character locators$\,\rangle$\cr
 21978    |post_post| |q[4]| |i[1]| 223's$[{\G}4]$\cr}}$$
 21979  Here |p| is a pointer to the byte following the final |eoc| in the file
 21980  (or to the byte following the preamble, if there are no characters);
 21981  it can be used to locate the beginning of \\{xxx} commands
 21982  that might have preceded the postamble. The |ds| and |cs| parameters
 21983  @^design size@> @^check sum@>
 21984  give the design size and check sum, respectively, which are exactly the
 21985  values put into the header of the \.{TFM} file that \MF\ produces (or
 21986  would produce) on this run. Parameters |hppp| and |vppp| are the ratios of
 21987  pixels per point, horizontally and vertically, expressed as |scaled| integers
 21988  (i.e., multiplied by $2^{16}$); they can be used to correlate the font
 21989  with specific device resolutions, magnifications, and ``at sizes.''  Then
 21990  come |min_m|, |max_m|, |min_n|, and |max_n|, which bound the values that
 21991  registers |m| and~|n| assume in all characters in this \.{GF} file.
 21992  (These bounds need not be the best possible; |max_m| and |min_n| may, on the
 21993  other hand, be tighter than the similar bounds in |boc| commands. For
 21994  example, some character may have |min_n=-100| in its |boc|, but it might
 21995  turn out that |n| never gets lower than |-50| in any character; then
 21996  |min_n| can have any value |<=-50|. If there are no characters in the file,
 21997  it's possible to have |min_m>max_m| and/or |min_n>max_n|.)
 21998  
 21999  @ Character locators are introduced by |char_loc| commands,
 22000  which specify a character residue~|c|, character escapements (|dx,dy|),
 22001  a character width~|w|, and a pointer~|p|
 22002  to the beginning of that character. (If two or more characters have the
 22003  same code~|c| modulo 256, only the last will be indicated; the others can be
 22004  located by following backpointers. Characters whose codes differ by a
 22005  multiple of 256 are assumed to share the same font metric information,
 22006  hence the \.{TFM} file contains only residues of character codes modulo~256.
 22007  This convention is intended for oriental languages, when there are many
 22008  character shapes but few distinct widths.)
 22009  @^oriental characters@>@^Chinese characters@>@^Japanese characters@>
 22010  
 22011  The character escapements (|dx,dy|) are the values of \MF's \&{chardx}
 22012  and \&{chardy} parameters; they are in units of |scaled| pixels;
 22013  i.e., |dx| is in horizontal pixel units times $2^{16}$, and |dy| is in
 22014  vertical pixel units times $2^{16}$.  This is the intended amount of
 22015  displacement after typesetting the character; for \.{DVI} files, |dy|
 22016  should be zero, but other document file formats allow nonzero vertical
 22017  escapement.
 22018  
 22019  The character width~|w| duplicates the information in the \.{TFM} file; it
 22020  is a |fix_word| value relative to the design size, and it should be
 22021  independent of magnification.
 22022  
 22023  The backpointer |p| points to the character's |boc|, or to the first of
 22024  a sequence of consecutive \\{xxx} or |yyy| or |no_op| commands that
 22025  immediately precede the |boc|, if such commands exist; such ``special''
 22026  commands essentially belong to the characters, while the special commands
 22027  after the final character belong to the postamble (i.e., to the font
 22028  as a whole). This convention about |p| applies also to the backpointers
 22029  in |boc| commands, even though it wasn't explained in the description
 22030  of~|boc|. @^backpointers@>
 22031  
 22032  Pointer |p| might be |-1| if the character exists in the \.{TFM} file
 22033  but not in the \.{GF} file. This unusual situation can arise in \MF\ output
 22034  if the user had |proofing<0| when the character was being shipped out,
 22035  but then made |proofing>=0| in order to get a \.{GF} file.
 22036  
 22037  @ The last part of the postamble, following the |post_post| byte that
 22038  signifies the end of the character locators, contains |q|, a pointer to the
 22039  |post| command that started the postamble.  An identification byte, |i|,
 22040  comes next; this currently equals~131, as in the preamble.
 22041  
 22042  The |i| byte is followed by four or more bytes that are all equal to
 22043  the decimal number 223 (i.e., @'337 in octal). \MF\ puts out four to seven of
 22044  these trailing bytes, until the total length of the file is a multiple of
 22045  four bytes, since this works out best on machines that pack four bytes per
 22046  word; but any number of 223's is allowed, as long as there are at least four
 22047  of them. In effect, 223 is a sort of signature that is added at the very end.
 22048  @^Fuchs, David Raymond@>
 22049  
 22050  This curious way to finish off a \.{GF} file makes it feasible for
 22051  \.{GF}-reading programs to find the postamble first, on most computers,
 22052  even though \MF\ wants to write the postamble last. Most operating
 22053  systems permit random access to individual words or bytes of a file, so
 22054  the \.{GF} reader can start at the end and skip backwards over the 223's
 22055  until finding the identification byte. Then it can back up four bytes, read
 22056  |q|, and move to byte |q| of the file. This byte should, of course,
 22057  contain the value 248 (|post|); now the postamble can be read, so the
 22058  \.{GF} reader can discover all the information needed for individual characters.
 22059  
 22060  Unfortunately, however, standard \PASCAL\ does not include the ability to
 22061  @^system dependencies@>
 22062  access a random position in a file, or even to determine the length of a file.
 22063  Almost all systems nowadays provide the necessary capabilities, so \.{GF}
 22064  format has been designed to work most efficiently with modern operating systems.
 22065  But if \.{GF} files have to be processed under the restrictions of standard
 22066  \PASCAL, one can simply read them from front to back. This will
 22067  be adequate for most applications. However, the postamble-first approach
 22068  would facilitate a program that merges two \.{GF} files, replacing data
 22069  from one that is overridden by corresponding data in the other.
 22070  
 22071  @* \[47] Shipping characters out.
 22072  The |ship_out| procedure, to be described below, is given a pointer to
 22073  an edge structure. Its mission is to describe the positive pixels
 22074  in \.{GF} form, outputting a ``character'' to |gf_file|.
 22075  
 22076  Several global variables hold information about the font file as a whole:\
 22077  |gf_min_m|, |gf_max_m|, |gf_min_n|, and |gf_max_n| are the minimum and
 22078  maximum \.{GF} coordinates output so far; |gf_prev_ptr| is the byte number
 22079  following the preamble or the last |eoc| command in the output;
 22080  |total_chars| is the total number of characters (i.e., |boc..eoc| segments)
 22081  shipped out.  There's also an array, |char_ptr|, containing the starting
 22082  positions of each character in the file, as required for the postamble. If
 22083  character code~|c| has not yet been output, |char_ptr[c]=-1|.
 22084  
 22085  @<Glob...@>=
 22086  @!gf_min_m,@!gf_max_m,@!gf_min_n,@!gf_max_n:integer; {bounding rectangle}
 22087  @!gf_prev_ptr:integer; {where the present/next character started/starts}
 22088  @!total_chars:integer; {the number of characters output so far}
 22089  @!char_ptr:array[eight_bits] of integer; {where individual characters started}
 22090  @!gf_dx,@!gf_dy:array[eight_bits] of integer; {device escapements}
 22091  
 22092  @ @<Set init...@>=
 22093  gf_prev_ptr:=0; total_chars:=0;
 22094  
 22095  @ The \.{GF} bytes are output to a buffer instead of being sent
 22096  byte-by-byte to |gf_file|, because this tends to save a lot of
 22097  subroutine-call overhead. \MF\ uses the same conventions for |gf_file|
 22098  as \TeX\ uses for its \\{dvi\_file}; hence if system-dependent
 22099  changes are needed, they should probably be the same for both programs.
 22100  
 22101  The output buffer is divided into two parts of equal size; the bytes found
 22102  in |gf_buf[0..half_buf-1]| constitute the first half, and those in
 22103  |gf_buf[half_buf..gf_buf_size-1]| constitute the second. The global
 22104  variable |gf_ptr| points to the position that will receive the next
 22105  output byte. When |gf_ptr| reaches |gf_limit|, which is always equal
 22106  to one of the two values |half_buf| or |gf_buf_size|, the half buffer that
 22107  is about to be invaded next is sent to the output and |gf_limit| is
 22108  changed to its other value. Thus, there is always at least a half buffer's
 22109  worth of information present, except at the very beginning of the job.
 22110  
 22111  Bytes of the \.{GF} file are numbered sequentially starting with 0;
 22112  the next byte to be generated will be number |gf_offset+gf_ptr|.
 22113  
 22114  @<Types...@>=
 22115  @!gf_index=0..gf_buf_size; {an index into the output buffer}
 22116  
 22117  @ Some systems may find it more efficient to make |gf_buf| a |packed|
 22118  array, since output of four bytes at once may be facilitated.
 22119  @^system dependencies@>
 22120  
 22121  @<Glob...@>=
 22122  @!gf_buf:array[gf_index] of eight_bits; {buffer for \.{GF} output}
 22123  @!half_buf:gf_index; {half of |gf_buf_size|}
 22124  @!gf_limit:gf_index; {end of the current half buffer}
 22125  @!gf_ptr:gf_index; {the next available buffer address}
 22126  @!gf_offset:integer; {|gf_buf_size| times the number of times the
 22127    output buffer has been fully emptied}
 22128  
 22129  @ Initially the buffer is all in one piece; we will output half of it only
 22130  after it first fills up.
 22131  
 22132  @<Set init...@>=
 22133  half_buf:=gf_buf_size div 2; gf_limit:=gf_buf_size; gf_ptr:=0;
 22134  gf_offset:=0;
 22135  
 22136  @ The actual output of |gf_buf[a..b]| to |gf_file| is performed by calling
 22137  |write_gf(a,b)|. It is safe to assume that |a| and |b+1| will both be
 22138  multiples of 4 when |write_gf(a,b)| is called; therefore it is possible on
 22139  many machines to use efficient methods to pack four bytes per word and to
 22140  output an array of words with one system call.
 22141  @^system dependencies@>
 22142  
 22143  @<Declare generic font output procedures@>=
 22144  procedure write_gf(@!a,@!b:gf_index);
 22145  var k:gf_index;
 22146  begin for k:=a to b do write(gf_file,gf_buf[k]);
 22147  end;
 22148  
 22149  @ To put a byte in the buffer without paying the cost of invoking a procedure
 22150  each time, we use the macro |gf_out|.
 22151  
 22152  @d gf_out(#)==@+begin gf_buf[gf_ptr]:=#; incr(gf_ptr);
 22153    if gf_ptr=gf_limit then gf_swap;
 22154    end
 22155  
 22156  @<Declare generic font output procedures@>=
 22157  procedure gf_swap; {outputs half of the buffer}
 22158  begin if gf_limit=gf_buf_size then
 22159    begin write_gf(0,half_buf-1); gf_limit:=half_buf;
 22160    gf_offset:=gf_offset+gf_buf_size; gf_ptr:=0;
 22161    end
 22162  else  begin write_gf(half_buf,gf_buf_size-1); gf_limit:=gf_buf_size;
 22163    end;
 22164  end;
 22165  
 22166  @ Here is how we clean out the buffer when \MF\ is all through; |gf_ptr|
 22167  will be a multiple of~4.
 22168  
 22169  @<Empty the last bytes out of |gf_buf|@>=
 22170  if gf_limit=half_buf then write_gf(half_buf,gf_buf_size-1);
 22171  if gf_ptr>0 then write_gf(0,gf_ptr-1)
 22172  
 22173  @ The |gf_four| procedure outputs four bytes in two's complement notation,
 22174  without risking arithmetic overflow.
 22175  
 22176  @<Declare generic font output procedures@>=
 22177  procedure gf_four(@!x:integer);
 22178  begin if x>=0 then gf_out(x div three_bytes)
 22179  else  begin x:=x+@'10000000000;
 22180    x:=x+@'10000000000;
 22181    gf_out((x div three_bytes) + 128);
 22182    end;
 22183  x:=x mod three_bytes; gf_out(x div unity);
 22184  x:=x mod unity; gf_out(x div @'400);
 22185  gf_out(x mod @'400);
 22186  end;
 22187  
 22188  @ Of course, it's even easier to output just two or three bytes.
 22189  
 22190  @<Declare generic font output procedures@>=
 22191  procedure gf_two(@!x:integer);
 22192  begin gf_out(x div @'400); gf_out(x mod @'400);
 22193  end;
 22194  @#
 22195  procedure gf_three(@!x:integer);
 22196  begin gf_out(x div unity); gf_out((x mod unity) div @'400);
 22197  gf_out(x mod @'400);
 22198  end;
 22199  
 22200  @ We need a simple routine to generate a \\{paint}
 22201  command of the appropriate type.
 22202  
 22203  @<Declare generic font output procedures@>=
 22204  procedure gf_paint(@!d:integer); {here |0<=d<65536|}
 22205  begin if d<64 then gf_out(paint_0+d)
 22206  else if d<256 then
 22207    begin gf_out(paint1); gf_out(d);
 22208    end
 22209  else  begin gf_out(paint1+1); gf_two(d);
 22210    end;
 22211  end;
 22212  
 22213  @ And |gf_string| outputs one or two strings. If the first string number
 22214  is nonzero, an \\{xxx} command is generated.
 22215  
 22216  @<Declare generic font output procedures@>=
 22217  procedure gf_string(@!s,@!t:str_number);
 22218  var @!k:pool_pointer;
 22219  @!l:integer; {length of the strings to output}
 22220  begin if s<>0 then
 22221    begin l:=length(s);
 22222    if t<>0 then l:=l+length(t);
 22223    if l<=255 then
 22224      begin gf_out(xxx1); gf_out(l);
 22225      end
 22226    else  begin gf_out(xxx3); gf_three(l);
 22227      end;
 22228    for k:=str_start[s] to str_start[s+1]-1 do gf_out(so(str_pool[k]));
 22229    end;
 22230  if t<>0 then for k:=str_start[t] to str_start[t+1]-1 do gf_out(so(str_pool[k]));
 22231  end;
 22232  
 22233  @ The choice between |boc| commands is handled by |gf_boc|.
 22234  
 22235  @d one_byte(#)== #>=0 then if #<256
 22236  
 22237  @<Declare generic font output procedures@>=
 22238  procedure gf_boc(@!min_m,@!max_m,@!min_n,@!max_n:integer);
 22239  label exit;
 22240  begin if min_m<gf_min_m then gf_min_m:=min_m;
 22241  if max_n>gf_max_n then gf_max_n:=max_n;
 22242  if boc_p=-1 then if one_byte(boc_c) then
 22243   if one_byte(max_m-min_m) then if one_byte(max_m) then
 22244    if one_byte(max_n-min_n) then if one_byte(max_n) then
 22245    begin gf_out(boc1); gf_out(boc_c);@/
 22246    gf_out(max_m-min_m); gf_out(max_m);
 22247    gf_out(max_n-min_n); gf_out(max_n); return;
 22248    end;
 22249  gf_out(boc); gf_four(boc_c); gf_four(boc_p);@/
 22250  gf_four(min_m); gf_four(max_m); gf_four(min_n); gf_four(max_n);
 22251  exit: end;
 22252  
 22253  @ Two of the parameters to |gf_boc| are global.
 22254  
 22255  @<Glob...@>=
 22256  @!boc_c,@!boc_p:integer; {parameters of the next |boc| command}
 22257  
 22258  @ Here is a routine that gets a \.{GF} file off to a good start.
 22259  
 22260  @d check_gf==@t@>@+if output_file_name=0 then init_gf
 22261  
 22262  @<Declare generic font output procedures@>=
 22263  procedure init_gf;
 22264  var @!k:eight_bits; {runs through all possible character codes}
 22265  @!t:integer; {the time of this run}
 22266  begin gf_min_m:=4096; gf_max_m:=-4096; gf_min_n:=4096; gf_max_n:=-4096;
 22267  for k:=0 to 255 do char_ptr[k]:=-1;
 22268  @<Determine the file extension, |gf_ext|@>;
 22269  set_output_file_name;
 22270  gf_out(pre); gf_out(gf_id_byte); {begin to output the preamble}
 22271  old_setting:=selector; selector:=new_string; print(" METAFONT output ");
 22272  print_int(round_unscaled(internal[year])); print_char(".");
 22273  print_dd(round_unscaled(internal[month])); print_char(".");
 22274  print_dd(round_unscaled(internal[day])); print_char(":");@/
 22275  t:=round_unscaled(internal[time]);
 22276  print_dd(t div 60); print_dd(t mod 60);@/
 22277  selector:=old_setting; gf_out(cur_length);
 22278  gf_string(0,make_string); decr(str_ptr);
 22279  pool_ptr:=str_start[str_ptr]; {flush that string from memory}
 22280  gf_prev_ptr:=gf_offset+gf_ptr;
 22281  end;
 22282  
 22283  @ @<Determine the file extension...@>=
 22284  if internal[hppp]<=0 then gf_ext:=".gf"
 22285  else  begin old_setting:=selector; selector:=new_string; print_char(".");
 22286    print_int(make_scaled(internal[hppp],59429463));
 22287      {$2^{32}/72.27\approx59429463.07$}
 22288    print("gf"); gf_ext:=make_string; selector:=old_setting;
 22289    end
 22290  
 22291  @ With those preliminaries out of the way, |ship_out| is not especially
 22292  difficult.
 22293  
 22294  @<Declare generic font output procedures@>=
 22295  procedure ship_out(@!c:eight_bits);
 22296  label done;
 22297  var @!f:integer; {current character extension}
 22298  @!prev_m,@!m,@!mm:integer; {previous and current pixel column numbers}
 22299  @!prev_n,@!n:integer; {previous and current pixel row numbers}
 22300  @!p,@!q:pointer; {for list traversal}
 22301  @!prev_w,@!w,@!ww:integer; {old and new weights}
 22302  @!d:integer; {data from edge-weight node}
 22303  @!delta:integer; {number of rows to skip}
 22304  @!cur_min_m:integer; {starting column, relative to the current offset}
 22305  @!x_off,@!y_off:integer; {offsets, rounded to integers}
 22306  begin check_gf; f:=round_unscaled(internal[char_ext]);@/
 22307  x_off:=round_unscaled(internal[x_offset]);
 22308  y_off:=round_unscaled(internal[y_offset]);
 22309  if term_offset>max_print_line-9 then print_ln
 22310  else if (term_offset>0)or(file_offset>0) then print_char(" ");
 22311  print_char("["); print_int(c);
 22312  if f<>0 then
 22313    begin print_char("."); print_int(f);
 22314    end;
 22315  update_terminal;
 22316  boc_c:=256*f+c; boc_p:=char_ptr[c]; char_ptr[c]:=gf_prev_ptr;@/
 22317  if internal[proofing]>0 then @<Send nonzero offsets to the output file@>;
 22318  @<Output the character represented in |cur_edges|@>;
 22319  gf_out(eoc); gf_prev_ptr:=gf_offset+gf_ptr; incr(total_chars);
 22320  print_char("]"); update_terminal; {progress report}
 22321  if internal[tracing_output]>0 then
 22322    print_edges(" (just shipped out)",true,x_off,y_off);
 22323  end;
 22324  
 22325  @ @<Send nonzero offsets to the output file@>=
 22326  begin if x_off<>0 then
 22327    begin gf_string("xoffset",0); gf_out(yyy); gf_four(x_off*unity);
 22328    end;
 22329  if y_off<>0 then
 22330    begin gf_string("yoffset",0); gf_out(yyy); gf_four(y_off*unity);
 22331    end;
 22332  end
 22333  
 22334  @ @<Output the character represented in |cur_edges|@>=
 22335  prev_n:=4096; p:=knil(cur_edges); n:=n_max(cur_edges)-zero_field;
 22336  while p<>cur_edges do
 22337    begin @<Output the pixels of edge row |p| to font row |n|@>;
 22338    p:=knil(p); decr(n);
 22339    end;
 22340  if prev_n=4096 then @<Finish off an entirely blank character@>
 22341  else if prev_n+y_off<gf_min_n then
 22342    gf_min_n:=prev_n+y_off
 22343  
 22344  @ @<Finish off an entirely blank...@>=
 22345  begin gf_boc(0,0,0,0);
 22346  if gf_max_m<0 then gf_max_m:=0;
 22347  if gf_min_n>0 then gf_min_n:=0;
 22348  end
 22349  
 22350  @ In this loop, |prev_w| represents the weight at column |prev_m|, which is
 22351  the most recent column reflected in the output so far; |w| represents the
 22352  weight at column~|m|, which is the most recent column in the edge data.
 22353  Several edges might cancel at the same column position, so we need to
 22354  look ahead to column~|mm| before actually outputting anything.
 22355  
 22356  @<Output the pixels of edge row |p| to font row |n|@>=
 22357  if unsorted(p)>void then sort_edges(p);
 22358  q:=sorted(p); w:=0; prev_m:=-fraction_one; {$|fraction_one|\approx\infty$}
 22359  ww:=0; prev_w:=0; m:=prev_m;
 22360  repeat if q=sentinel then mm:=fraction_one
 22361  else  begin d:=ho(info(q)); mm:=d div 8; ww:=ww+(d mod 8)-zero_w;
 22362    end;
 22363  if mm<>m then
 22364    begin if prev_w<=0 then
 22365      begin if w>0 then @<Start black at $(m,n)$@>;
 22366      end
 22367    else if w<=0 then @<Stop black at $(m,n)$@>;
 22368    m:=mm;
 22369    end;
 22370  w:=ww; q:=link(q);
 22371  until mm=fraction_one;
 22372  if w<>0 then {this should be impossible}
 22373    print_nl("(There's unbounded black in character shipped out!)");
 22374  @.There's unbounded black...@>
 22375  if prev_m-m_offset(cur_edges)+x_off>gf_max_m then
 22376    gf_max_m:=prev_m-m_offset(cur_edges)+x_off
 22377  
 22378  
 22379  @ @<Start black at $(m,n)$@>=
 22380  begin if prev_m=-fraction_one then @<Start a new row at $(m,n)$@>
 22381  else gf_paint(m-prev_m);
 22382  prev_m:=m; prev_w:=w;
 22383  end
 22384  
 22385  @ @<Stop black at $(m,n)$@>=
 22386  begin gf_paint(m-prev_m); prev_m:=m; prev_w:=w;
 22387  end
 22388  
 22389  @ @<Start a new row at $(m,n)$@>=
 22390  begin if prev_n=4096 then
 22391    begin gf_boc(m_min(cur_edges)+x_off-zero_field,
 22392      m_max(cur_edges)+x_off-zero_field,@|
 22393      n_min(cur_edges)+y_off-zero_field,n+y_off);
 22394    cur_min_m:=m_min(cur_edges)-zero_field+m_offset(cur_edges);
 22395    end
 22396  else if prev_n>n+1 then @<Skip down |prev_n-n| rows@>
 22397  else @<Skip to column $m$ in the next row and |goto done|, or skip zero rows@>;
 22398  gf_paint(m-cur_min_m); {skip to column $m$, painting white}
 22399  done:prev_n:=n;
 22400  end
 22401  
 22402  @ @<Skip to column $m$ in the next row...@>=
 22403  begin delta:=m-cur_min_m;
 22404  if delta>max_new_row then gf_out(skip0)
 22405  else  begin gf_out(new_row_0+delta); goto done;
 22406    end;
 22407  end
 22408  
 22409  @ @<Skip down...@>=
 22410  begin delta:=prev_n-n-1;
 22411  if delta<@'400 then
 22412    begin gf_out(skip1); gf_out(delta);
 22413    end
 22414  else  begin gf_out(skip1+1); gf_two(delta);
 22415    end;
 22416  end
 22417  
 22418  @ Now that we've finished |ship_out|, let's look at the other commands
 22419  by which a user can send things to the \.{GF} file.
 22420  
 22421  @<Cases of |do_statement|...@>=
 22422  special_command: do_special;
 22423  
 22424  @ @<Put each...@>=
 22425  primitive("special",special_command,string_type);@/
 22426  @!@:special_}{\&{special} primitive@>
 22427  primitive("numspecial",special_command,known);@/
 22428  @!@:num_special_}{\&{numspecial} primitive@>
 22429  
 22430  @ @<Declare action procedures for use by |do_statement|@>=
 22431  procedure do_special;
 22432  var @!m:small_number; {either |string_type| or |known|}
 22433  begin m:=cur_mod; get_x_next; scan_expression;
 22434  if internal[proofing]>=0 then
 22435    if cur_type<>m then @<Complain about improper special operation@>
 22436    else  begin check_gf;
 22437      if m=string_type then gf_string(cur_exp,0)
 22438      else  begin gf_out(yyy); gf_four(cur_exp);
 22439        end;
 22440      end;
 22441  flush_cur_exp(0);
 22442  end;
 22443  
 22444  @ @<Complain about improper special operation@>=
 22445  begin exp_err("Unsuitable expression");
 22446  @.Unsuitable expression@>
 22447  help1("The expression shown above has the wrong type to be output.");
 22448  put_get_error;
 22449  end
 22450  
 22451  @ @<Send the current expression as a title to the output file@>=
 22452  begin check_gf; gf_string("title ",cur_exp);
 22453  @.title@>
 22454  end
 22455  
 22456  @ @<Cases of |print_cmd...@>=
 22457  special_command:if m=known then print("numspecial")
 22458    else print("special");
 22459  
 22460  @ @<Determine if a character has been shipped out@>=
 22461  begin cur_exp:=round_unscaled(cur_exp) mod 256;
 22462  if cur_exp<0 then cur_exp:=cur_exp+256;
 22463  boolean_reset(char_exists[cur_exp]); cur_type:=boolean_type;
 22464  end
 22465  
 22466  @ At the end of the program we must finish things off by writing the postamble.
 22467  The \.{TFM} information should have been computed first.
 22468  
 22469  An integer variable |k| and a |scaled| variable |x| will be declared for
 22470  use by this routine.
 22471  
 22472  @<Finish the \.{GF} file@>=
 22473  begin gf_out(post); {beginning of the postamble}
 22474  gf_four(gf_prev_ptr); gf_prev_ptr:=gf_offset+gf_ptr-5; {|post| location}
 22475  gf_four(internal[design_size]*16);
 22476  for k:=1 to 4 do gf_out(header_byte[k]); {the check sum}
 22477  gf_four(internal[hppp]);
 22478  gf_four(internal[vppp]);@/
 22479  gf_four(gf_min_m); gf_four(gf_max_m);
 22480  gf_four(gf_min_n); gf_four(gf_max_n);
 22481  for k:=0 to 255 do if char_exists[k] then
 22482    begin x:=gf_dx[k] div unity;
 22483    if (gf_dy[k]=0)and(x>=0)and(x<256)and(gf_dx[k]=x*unity) then
 22484      begin gf_out(char_loc+1); gf_out(k); gf_out(x);
 22485      end
 22486    else  begin gf_out(char_loc); gf_out(k);
 22487      gf_four(gf_dx[k]); gf_four(gf_dy[k]);
 22488      end;
 22489    x:=value(tfm_width[k]);
 22490    if abs(x)>max_tfm_dimen then
 22491      if x>0 then x:=three_bytes-1@+else x:=1-three_bytes
 22492    else x:=make_scaled(x*16,internal[design_size]);
 22493    gf_four(x); gf_four(char_ptr[k]);
 22494    end;
 22495  gf_out(post_post); gf_four(gf_prev_ptr); gf_out(gf_id_byte);@/
 22496  k:=4+((gf_buf_size-gf_ptr) mod 4); {the number of 223's}
 22497  while k>0 do
 22498    begin gf_out(223); decr(k);
 22499    end;
 22500  @<Empty the last bytes out of |gf_buf|@>;
 22501  print_nl("Output written on "); slow_print(output_file_name);
 22502  @.Output written...@>
 22503  print(" ("); print_int(total_chars); print(" character");
 22504  if total_chars<>1 then print_char("s");
 22505  print(", "); print_int(gf_offset+gf_ptr); print(" bytes).");
 22506  b_close(gf_file);
 22507  end
 22508  
 22509  @* \[48] Dumping and undumping the tables.
 22510  After \.{INIMF} has seen a collection of macros, it
 22511  can write all the necessary information on an auxiliary file so
 22512  that production versions of \MF\ are able to initialize their
 22513  memory at high speed. The present section of the program takes
 22514  care of such output and input. We shall consider simultaneously
 22515  the processes of storing and restoring,
 22516  so that the inverse relation between them is clear.
 22517  @.INIMF@>
 22518  
 22519  The global variable |base_ident| is a string that is printed right
 22520  after the |banner| line when \MF\ is ready to start. For \.{INIMF} this
 22521  string says simply `\.{(INIMF)}'; for other versions of \MF\ it says,
 22522  for example, `\.{(preloaded base=plain 1984.2.29)}', showing the year,
 22523  month, and day that the base file was created. We have |base_ident=0|
 22524  before \MF's tables are loaded.
 22525  
 22526  @<Glob...@>=
 22527  @!base_ident:str_number;
 22528  
 22529  @ @<Set init...@>=
 22530  base_ident:=0;
 22531  
 22532  @ @<Initialize table entries...@>=
 22533  base_ident:=" (INIMF)";
 22534  
 22535  @ @<Declare act...@>=
 22536  @!init procedure store_base_file;
 22537  var @!k:integer; {all-purpose index}
 22538  @!p,@!q: pointer; {all-purpose pointers}
 22539  @!x: integer; {something to dump}
 22540  @!w: four_quarters; {four ASCII codes}
 22541  begin @<Create the |base_ident|, open the base file,
 22542    and inform the user that dumping has begun@>;
 22543  @<Dump constants for consistency check@>;
 22544  @<Dump the string pool@>;
 22545  @<Dump the dynamic memory@>;
 22546  @<Dump the table of equivalents and the hash table@>;
 22547  @<Dump a few more things and the closing check word@>;
 22548  @<Close the base file@>;
 22549  end;
 22550  tini
 22551  
 22552  @ Corresponding to the procedure that dumps a base file, we also have a function
 22553  that reads~one~in. The function returns |false| if the dumped base is
 22554  incompatible with the present \MF\ table sizes, etc.
 22555  
 22556  @d off_base=6666 {go here if the base file is unacceptable}
 22557  @d too_small(#)==begin wake_up_terminal;
 22558    wterm_ln('---! Must increase the ',#);
 22559  @.Must increase the x@>
 22560    goto off_base;
 22561    end
 22562  
 22563  @p @t\4@>@<Declare the function called |open_base_file|@>@;
 22564  function load_base_file:boolean;
 22565  label off_base,exit;
 22566  var @!k:integer; {all-purpose index}
 22567  @!p,@!q: pointer; {all-purpose pointers}
 22568  @!x: integer; {something undumped}
 22569  @!w: four_quarters; {four ASCII codes}
 22570  begin @<Undump constants for consistency check@>;
 22571  @<Undump the string pool@>;
 22572  @<Undump the dynamic memory@>;
 22573  @<Undump the table of equivalents and the hash table@>;
 22574  @<Undump a few more things and the closing check word@>;
 22575  load_base_file:=true; return; {it worked!}
 22576  off_base: wake_up_terminal;
 22577    wterm_ln('(Fatal base file error; I''m stymied)');
 22578  @.Fatal base file error@>
 22579  load_base_file:=false;
 22580  exit:end;
 22581  
 22582  @ Base files consist of |memory_word| items, and we use the following
 22583  macros to dump words of different types:
 22584  
 22585  @d dump_wd(#)==begin base_file^:=#; put(base_file);@+end
 22586  @d dump_int(#)==begin base_file^.int:=#; put(base_file);@+end
 22587  @d dump_hh(#)==begin base_file^.hh:=#; put(base_file);@+end
 22588  @d dump_qqqq(#)==begin base_file^.qqqq:=#; put(base_file);@+end
 22589  
 22590  @<Glob...@>=
 22591  @!base_file:word_file; {for input or output of base information}
 22592  
 22593  @ The inverse macros are slightly more complicated, since we need to check
 22594  the range of the values we are reading in. We say `|undump(a)(b)(x)|' to
 22595  read an integer value |x| that is supposed to be in the range |a<=x<=b|.
 22596  System error messages should be suppressed when undumping.
 22597  @^system dependencies@>
 22598  
 22599  @d undump_wd(#)==begin get(base_file); #:=base_file^;@+end
 22600  @d undump_int(#)==begin get(base_file); #:=base_file^.int;@+end
 22601  @d undump_hh(#)==begin get(base_file); #:=base_file^.hh;@+end
 22602  @d undump_qqqq(#)==begin get(base_file); #:=base_file^.qqqq;@+end
 22603  @d undump_end_end(#)==#:=x;@+end
 22604  @d undump_end(#)==(x>#) then goto off_base@+else undump_end_end
 22605  @d undump(#)==begin undump_int(x); if (x<#) or undump_end
 22606  @d undump_size_end_end(#)==too_small(#)@+else undump_end_end
 22607  @d undump_size_end(#)==if x># then undump_size_end_end
 22608  @d undump_size(#)==begin undump_int(x);
 22609    if x<# then goto off_base; undump_size_end
 22610  
 22611  @ The next few sections of the program should make it clear how we use the
 22612  dump/undump macros.
 22613  
 22614  @<Dump constants for consistency check@>=
 22615  dump_int(@$);@/
 22616  dump_int(mem_min);@/
 22617  dump_int(mem_top);@/
 22618  dump_int(hash_size);@/
 22619  dump_int(hash_prime);@/
 22620  dump_int(max_in_open)
 22621  
 22622  @ Sections of a \.{WEB} program that are ``commented out'' still contribute
 22623  strings to the string pool; therefore \.{INIMF} and \MF\ will have
 22624  the same strings. (And it is, of course, a good thing that they do.)
 22625  @.WEB@>
 22626  @^string pool@>
 22627  
 22628  @<Undump constants for consistency check@>=
 22629  x:=base_file^.int;
 22630  if x<>@$ then goto off_base; {check that strings are the same}
 22631  undump_int(x);
 22632  if x<>mem_min then goto off_base;
 22633  undump_int(x);
 22634  if x<>mem_top then goto off_base;
 22635  undump_int(x);
 22636  if x<>hash_size then goto off_base;
 22637  undump_int(x);
 22638  if x<>hash_prime then goto off_base;
 22639  undump_int(x);
 22640  if x<>max_in_open then goto off_base
 22641  
 22642  @ @d dump_four_ASCII==
 22643    w.b0:=qi(so(str_pool[k])); w.b1:=qi(so(str_pool[k+1]));
 22644    w.b2:=qi(so(str_pool[k+2])); w.b3:=qi(so(str_pool[k+3]));
 22645    dump_qqqq(w)
 22646  
 22647  @<Dump the string pool@>=
 22648  dump_int(pool_ptr);
 22649  dump_int(str_ptr);
 22650  for k:=0 to str_ptr do dump_int(str_start[k]);
 22651  k:=0;
 22652  while k+4<pool_ptr do
 22653    begin dump_four_ASCII; k:=k+4;
 22654    end;
 22655  k:=pool_ptr-4; dump_four_ASCII;
 22656  print_ln; print_int(str_ptr); print(" strings of total length ");
 22657  print_int(pool_ptr)
 22658  
 22659  @ @d undump_four_ASCII==
 22660    undump_qqqq(w);
 22661    str_pool[k]:=si(qo(w.b0)); str_pool[k+1]:=si(qo(w.b1));
 22662    str_pool[k+2]:=si(qo(w.b2)); str_pool[k+3]:=si(qo(w.b3))
 22663  
 22664  @<Undump the string pool@>=
 22665  undump_size(0)(pool_size)('string pool size')(pool_ptr);
 22666  undump_size(0)(max_strings)('max strings')(str_ptr);
 22667  for k:=0 to str_ptr do
 22668    begin undump(0)(pool_ptr)(str_start[k]); str_ref[k]:=max_str_ref;
 22669    end;
 22670  k:=0;
 22671  while k+4<pool_ptr do
 22672    begin undump_four_ASCII; k:=k+4;
 22673    end;
 22674  k:=pool_ptr-4; undump_four_ASCII;
 22675  init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr;
 22676  max_str_ptr:=str_ptr; max_pool_ptr:=pool_ptr
 22677  
 22678  @ By sorting the list of available spaces in the variable-size portion of
 22679  |mem|, we are usually able to get by without having to dump very much
 22680  of the dynamic memory.
 22681  
 22682  We recompute |var_used| and |dyn_used|, so that \.{INIMF} dumps valid
 22683  information even when it has not been gathering statistics.
 22684  
 22685  @<Dump the dynamic memory@>=
 22686  sort_avail; var_used:=0;
 22687  dump_int(lo_mem_max); dump_int(rover);
 22688  p:=mem_min; q:=rover; x:=0;
 22689  repeat for k:=p to q+1 do dump_wd(mem[k]);
 22690  x:=x+q+2-p; var_used:=var_used+q-p;
 22691  p:=q+node_size(q); q:=rlink(q);
 22692  until q=rover;
 22693  var_used:=var_used+lo_mem_max-p; dyn_used:=mem_end+1-hi_mem_min;@/
 22694  for k:=p to lo_mem_max do dump_wd(mem[k]);
 22695  x:=x+lo_mem_max+1-p;
 22696  dump_int(hi_mem_min); dump_int(avail);
 22697  for k:=hi_mem_min to mem_end do dump_wd(mem[k]);
 22698  x:=x+mem_end+1-hi_mem_min;
 22699  p:=avail;
 22700  while p<>null do
 22701    begin decr(dyn_used); p:=link(p);
 22702    end;
 22703  dump_int(var_used); dump_int(dyn_used);
 22704  print_ln; print_int(x);
 22705  print(" memory locations dumped; current usage is ");
 22706  print_int(var_used); print_char("&"); print_int(dyn_used)
 22707  
 22708  @ @<Undump the dynamic memory@>=
 22709  undump(lo_mem_stat_max+1000)(hi_mem_stat_min-1)(lo_mem_max);
 22710  undump(lo_mem_stat_max+1)(lo_mem_max)(rover);
 22711  p:=mem_min; q:=rover;
 22712  repeat for k:=p to q+1 do undump_wd(mem[k]);
 22713  p:=q+node_size(q);
 22714  if (p>lo_mem_max)or((q>=rlink(q))and(rlink(q)<>rover)) then goto off_base;
 22715  q:=rlink(q);
 22716  until q=rover;
 22717  for k:=p to lo_mem_max do undump_wd(mem[k]);
 22718  undump(lo_mem_max+1)(hi_mem_stat_min)(hi_mem_min);
 22719  undump(null)(mem_top)(avail); mem_end:=mem_top;
 22720  for k:=hi_mem_min to mem_end do undump_wd(mem[k]);
 22721  undump_int(var_used); undump_int(dyn_used)
 22722  
 22723  @ A different scheme is used to compress the hash table, since its lower region
 22724  is usually sparse. When |text(p)<>0| for |p<=hash_used|, we output three
 22725  words: |p|, |hash[p]|, and |eqtb[p]|. The hash table is, of course, densely
 22726  packed for |p>=hash_used|, so the remaining entries are output in~a~block.
 22727  
 22728  @<Dump the table of equivalents and the hash table@>=
 22729  dump_int(hash_used); st_count:=frozen_inaccessible-1-hash_used;
 22730  for p:=1 to hash_used do if text(p)<>0 then
 22731    begin dump_int(p); dump_hh(hash[p]); dump_hh(eqtb[p]); incr(st_count);
 22732    end;
 22733  for p:=hash_used+1 to hash_end do
 22734    begin dump_hh(hash[p]); dump_hh(eqtb[p]);
 22735    end;
 22736  dump_int(st_count);@/
 22737  print_ln; print_int(st_count); print(" symbolic tokens")
 22738  
 22739  @ @<Undump the table of equivalents and the hash table@>=
 22740  undump(1)(frozen_inaccessible)(hash_used); p:=0;
 22741  repeat undump(p+1)(hash_used)(p); undump_hh(hash[p]); undump_hh(eqtb[p]);
 22742  until p=hash_used;
 22743  for p:=hash_used+1 to hash_end do
 22744    begin undump_hh(hash[p]); undump_hh(eqtb[p]);
 22745    end;
 22746  undump_int(st_count)
 22747  
 22748  @ We have already printed a lot of statistics, so we set |tracing_stats:=0|
 22749  to prevent them from appearing again.
 22750  
 22751  @<Dump a few more things and the closing check word@>=
 22752  dump_int(int_ptr);
 22753  for k:=1 to int_ptr do
 22754    begin dump_int(internal[k]); dump_int(int_name[k]);
 22755    end;
 22756  dump_int(start_sym); dump_int(interaction); dump_int(base_ident);
 22757  dump_int(bg_loc); dump_int(eg_loc); dump_int(serial_no); dump_int(69069);
 22758  internal[tracing_stats]:=0
 22759  
 22760  @ @<Undump a few more things and the closing check word@>=
 22761  undump(max_given_internal)(max_internal)(int_ptr);
 22762  for k:=1 to int_ptr do
 22763    begin undump_int(internal[k]);
 22764    undump(0)(str_ptr)(int_name[k]);
 22765    end;
 22766  undump(0)(frozen_inaccessible)(start_sym);
 22767  undump(batch_mode)(error_stop_mode)(interaction);
 22768  undump(0)(str_ptr)(base_ident);
 22769  undump(1)(hash_end)(bg_loc);
 22770  undump(1)(hash_end)(eg_loc);
 22771  undump_int(serial_no);@/
 22772  undump_int(x);@+if (x<>69069)or eof(base_file) then goto off_base
 22773  
 22774  @ @<Create the |base_ident|...@>=
 22775  selector:=new_string;
 22776  print(" (preloaded base="); print(job_name); print_char(" ");
 22777  print_int(round_unscaled(internal[year])); print_char(".");
 22778  print_int(round_unscaled(internal[month])); print_char(".");
 22779  print_int(round_unscaled(internal[day])); print_char(")");
 22780  if interaction=batch_mode then selector:=log_only
 22781  else selector:=term_and_log;
 22782  str_room(1); base_ident:=make_string; str_ref[base_ident]:=max_str_ref;@/
 22783  pack_job_name(base_extension);
 22784  while not w_open_out(base_file) do
 22785   prompt_file_name("base file name",base_extension);
 22786  print_nl("Beginning to dump on file ");
 22787  @.Beginning to dump...@>
 22788  slow_print(w_make_name_string(base_file)); flush_string(str_ptr-1);
 22789  print_nl(""); slow_print(base_ident)
 22790  
 22791  @ @<Close the base file@>=
 22792  w_close(base_file)
 22793  
 22794  @* \[49] The main program.
 22795  This is it: the part of \MF\ that executes all those procedures we have
 22796  written.
 22797  
 22798  Well---almost. We haven't put the parsing subroutines into the
 22799  program yet; and we'd better leave space for a few more routines that may
 22800  have been forgotten.
 22801  
 22802  @p @<Declare the basic parsing subroutines@>@;
 22803  @<Declare miscellaneous procedures that were declared |forward|@>@;
 22804  @<Last-minute procedures@>
 22805  
 22806  @ We've noted that there are two versions of \MF84. One, called \.{INIMF},
 22807  @.INIMF@>
 22808  has to be run first; it initializes everything from scratch, without
 22809  reading a base file, and it has the capability of dumping a base file.
 22810  The other one is called `\.{VIRMF}'; it is a ``virgin'' program that needs
 22811  @.VIRMF@>
 22812  to input a base file in order to get started. \.{VIRMF} typically has
 22813  a bit more memory capacity than \.{INIMF}, because it does not need the
 22814  space consumed by the dumping/undumping routines and the numerous calls on
 22815  |primitive|, etc.
 22816  
 22817  The \.{VIRMF} program cannot read a base file instantaneously, of course;
 22818  the best implementations therefore allow for production versions of \MF\ that
 22819  not only avoid the loading routine for \PASCAL\ object code, they also have
 22820  a base file pre-loaded. This is impossible to do if we stick to standard
 22821  \PASCAL; but there is a simple way to fool many systems into avoiding the
 22822  initialization, as follows:\quad(1)~We declare a global integer variable
 22823  called |ready_already|. The probability is negligible that this
 22824  variable holds any particular value like 314159 when \.{VIRMF} is first
 22825  loaded.\quad(2)~After we have read in a base file and initialized
 22826  everything, we set |ready_already:=314159|.\quad(3)~Soon \.{VIRMF}
 22827  will print `\.*', waiting for more input; and at this point we
 22828  interrupt the program and save its core image in some form that the
 22829  operating system can reload speedily.\quad(4)~When that core image is
 22830  activated, the program starts again at the beginning; but now
 22831  |ready_already=314159| and all the other global variables have
 22832  their initial values too. The former chastity has vanished!
 22833  
 22834  In other words, if we allow ourselves to test the condition
 22835  |ready_already=314159|, before |ready_already| has been
 22836  assigned a value, we can avoid the lengthy initialization. Dirty tricks
 22837  rarely pay off so handsomely.
 22838  @^dirty \PASCAL@>
 22839  @^system dependencies@>
 22840  
 22841  On systems that allow such preloading, the standard program called \.{MF}
 22842  should be the one that has \.{plain} base preloaded, since that agrees
 22843  with {\sl The {\logos METAFONT\/}book}.  Other versions, e.g., \.{CMMF},
 22844  should also be provided for commonly used bases such as \.{cmbase}.
 22845  @:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
 22846  @.cmbase@>
 22847  @.plain@>
 22848  
 22849  @<Glob...@>=
 22850  @!ready_already:integer; {a sacrifice of purity for economy}
 22851  
 22852  @ Now this is really it: \MF\ starts and ends here.
 22853  
 22854  The initial test involving |ready_already| should be deleted if the
 22855  \PASCAL\ runtime system is smart enough to detect such a ``mistake.''
 22856  @^system dependencies@>
 22857  
 22858  @p begin @!{|start_here|}
 22859  history:=fatal_error_stop; {in case we quit during initialization}
 22860  t_open_out; {open the terminal for output}
 22861  if ready_already=314159 then goto start_of_MF;
 22862  @<Check the ``constant'' values...@>@;
 22863  if bad>0 then
 22864    begin wterm_ln('Ouch---my internal constants have been clobbered!',
 22865      '---case ',bad:1);
 22866  @.Ouch...clobbered@>
 22867    goto final_end;
 22868    end;
 22869  initialize; {set global variables to their starting values}
 22870  @!init if not get_strings_started then goto final_end;
 22871  init_tab; {initialize the tables}
 22872  init_prim; {call |primitive| for each primitive}
 22873  init_str_ptr:=str_ptr; init_pool_ptr:=pool_ptr;@/
 22874  max_str_ptr:=str_ptr; max_pool_ptr:=pool_ptr; fix_date_and_time;
 22875  tini@/
 22876  ready_already:=314159;
 22877  start_of_MF: @<Initialize the output routines@>;
 22878  @<Get the first line of input and prepare to start@>;
 22879  history:=spotless; {ready to go!}
 22880  if start_sym>0 then {insert the `\&{everyjob}' symbol}
 22881    begin cur_sym:=start_sym; back_input;
 22882    end;
 22883  main_control; {come to life}
 22884  final_cleanup; {prepare for death}
 22885  end_of_MF: close_files_and_terminate;
 22886  final_end: ready_already:=0;
 22887  end.
 22888  
 22889  @ Here we do whatever is needed to complete \MF's job gracefully on the
 22890  local operating system. The code here might come into play after a fatal
 22891  error; it must therefore consist entirely of ``safe'' operations that
 22892  cannot produce error messages. For example, it would be a mistake to call
 22893  |str_room| or |make_string| at this time, because a call on |overflow|
 22894  might lead to an infinite loop.
 22895  @^system dependencies@>
 22896  
 22897  If |final_cleanup| is bypassed, this program doesn't bother to close
 22898  the input files that may still be open.
 22899  
 22900  @<Last-minute...@>=
 22901  procedure close_files_and_terminate;
 22902  var @!k:integer; {all-purpose index}
 22903  @!lh:integer; {the length of the \.{TFM} header, in words}
 22904  @!lk_offset:0..256; {extra words inserted at beginning of |lig_kern| array}
 22905  @!p:pointer; {runs through a list of \.{TFM} dimensions}
 22906  @!x:scaled; {a |tfm_width| value being output to the \.{GF} file}
 22907  begin
 22908  @!stat if internal[tracing_stats]>0 then
 22909    @<Output statistics about this job@>;@;@+tats@/
 22910  wake_up_terminal; @<Finish the \.{TFM} and \.{GF} files@>;
 22911  if log_opened then
 22912    begin wlog_cr;
 22913    a_close(log_file); selector:=selector-2;
 22914    if selector=term_only then
 22915      begin print_nl("Transcript written on ");
 22916  @.Transcript written...@>
 22917      slow_print(log_name); print_char(".");
 22918      end;
 22919    end;
 22920  end;
 22921  
 22922  @ We want to finish the \.{GF} file if and only if it has already been started;
 22923  this will be true if and only if |gf_prev_ptr| is positive.
 22924  We want to produce a \.{TFM} file if and only if |fontmaking| is positive.
 22925  The \.{TFM} widths must be computed if there's a \.{GF} file, even if
 22926  there's going to be no \.{TFM}~file.
 22927  
 22928  We reclaim all of the variable-size memory at this point, so that
 22929  there is no chance of another memory overflow after the memory capacity
 22930  has already been exceeded.
 22931  
 22932  @<Finish the \.{TFM} and \.{GF} files@>=
 22933  if (gf_prev_ptr>0)or(internal[fontmaking]>0) then
 22934    begin @<Make the dynamic memory into one big available node@>;
 22935    @<Massage the \.{TFM} widths@>;
 22936    fix_design_size; fix_check_sum;
 22937    if internal[fontmaking]>0 then
 22938      begin @<Massage the \.{TFM} heights, depths, and italic corrections@>;
 22939      internal[fontmaking]:=0; {avoid loop in case of fatal error}
 22940      @<Finish the \.{TFM} file@>;
 22941      end;
 22942    if gf_prev_ptr>0 then @<Finish the \.{GF} file@>;
 22943    end
 22944  
 22945  @ @<Make the dynamic memory into one big available node@>=
 22946  rover:=lo_mem_stat_max+1; link(rover):=empty_flag; lo_mem_max:=hi_mem_min-1;
 22947  if lo_mem_max-rover>max_halfword then lo_mem_max:=max_halfword+rover;
 22948  node_size(rover):=lo_mem_max-rover; llink(rover):=rover; rlink(rover):=rover;
 22949  link(lo_mem_max):=null; info(lo_mem_max):=null
 22950  
 22951  @ The present section goes directly to the log file instead of using
 22952  |print| commands, because there's no need for these strings to take
 22953  up |str_pool| memory when a non-{\bf stat} version of \MF\ is being used.
 22954  
 22955  @<Output statistics...@>=
 22956  if log_opened then
 22957    begin wlog_ln(' ');
 22958    wlog_ln('Here is how much of METAFONT''s memory',' you used:');
 22959  @.Here is how much...@>
 22960    wlog(' ',max_str_ptr-init_str_ptr:1,' string');
 22961    if max_str_ptr<>init_str_ptr+1 then wlog('s');
 22962    wlog_ln(' out of ', max_strings-init_str_ptr:1);@/
 22963    wlog_ln(' ',max_pool_ptr-init_pool_ptr:1,' string characters out of ',
 22964      pool_size-init_pool_ptr:1);@/
 22965    wlog_ln(' ',lo_mem_max-mem_min+mem_end-hi_mem_min+2:1,@|
 22966      ' words of memory out of ',mem_end+1-mem_min:1);@/
 22967    wlog_ln(' ',st_count:1,' symbolic tokens out of ',
 22968      hash_size:1);@/
 22969    wlog_ln(' ',max_in_stack:1,'i,',@|
 22970      int_ptr:1,'n,',@|
 22971      max_rounding_ptr:1,'r,',@|
 22972      max_param_stack:1,'p,',@|
 22973      max_buf_stack+1:1,'b stack positions out of ',@|
 22974      stack_size:1,'i,',
 22975      max_internal:1,'n,',
 22976      max_wiggle:1,'r,',
 22977      param_size:1,'p,',
 22978      buf_size:1,'b');
 22979    end
 22980  
 22981  @ We get to the |final_cleanup| routine when \&{end} or \&{dump} has
 22982  been scanned.
 22983  
 22984  @<Last-minute...@>=
 22985  procedure final_cleanup;
 22986  label exit;
 22987  var c:small_number; {0 for \&{end}, 1 for \&{dump}}
 22988  begin c:=cur_mod;
 22989  if job_name=0 then open_log_file;
 22990  while input_ptr>0 do
 22991    if token_state then end_token_list@+else end_file_reading;
 22992  while loop_ptr<>null do stop_iteration;
 22993  while open_parens>0 do
 22994    begin print(" )"); decr(open_parens);
 22995    end;
 22996  while cond_ptr<>null do
 22997    begin print_nl("(end occurred when ");@/
 22998  @.end occurred...@>
 22999    print_cmd_mod(fi_or_else,cur_if);
 23000      {`\.{if}' or `\.{elseif}' or `\.{else}'}
 23001    if if_line<>0 then
 23002      begin print(" on line "); print_int(if_line);
 23003      end;
 23004    print(" was incomplete)");
 23005    if_line:=if_line_field(cond_ptr);
 23006    cur_if:=name_type(cond_ptr); loop_ptr:=cond_ptr;
 23007    cond_ptr:=link(cond_ptr); free_node(loop_ptr,if_node_size);
 23008    end;
 23009  if history<>spotless then
 23010   if ((history=warning_issued)or(interaction<error_stop_mode)) then
 23011    if selector=term_and_log then
 23012    begin selector:=term_only;
 23013    print_nl("(see the transcript file for additional information)");
 23014  @.see the transcript file...@>
 23015    selector:=term_and_log;
 23016    end;
 23017  if c=1 then
 23018    begin @!init store_base_file; return;@+tini@/
 23019    print_nl("(dump is performed only by INIMF)"); return;
 23020  @.dump...only by INIMF@>
 23021    end;
 23022  exit:end;
 23023  
 23024  @ @<Last-minute...@>=
 23025  @!init procedure init_prim; {initialize all the primitives}
 23026  begin
 23027  @<Put each...@>;
 23028  end;
 23029  @#
 23030  procedure init_tab; {initialize other tables}
 23031  var @!k:integer; {all-purpose index}
 23032  begin @<Initialize table entries (done by \.{INIMF} only)@>@;
 23033  end;
 23034  tini
 23035  
 23036  @ When we begin the following code, \MF's tables may still contain garbage;
 23037  the strings might not even be present. Thus we must proceed cautiously to get
 23038  bootstrapped in.
 23039  
 23040  But when we finish this part of the program, \MF\ is ready to call on the
 23041  |main_control| routine to do its work.
 23042  
 23043  @<Get the first line...@>=
 23044  begin @<Initialize the input routines@>;
 23045  if (base_ident=0)or(buffer[loc]="&") then
 23046    begin if base_ident<>0 then initialize; {erase preloaded base}
 23047    if not open_base_file then goto final_end;
 23048    if not load_base_file then
 23049      begin w_close(base_file); goto final_end;
 23050      end;
 23051    w_close(base_file);
 23052    while (loc<limit)and(buffer[loc]=" ") do incr(loc);
 23053    end;
 23054  buffer[limit]:="%";@/
 23055  fix_date_and_time; init_randoms(sys_time+sys_day*unity);@/
 23056  @<Initialize the print |selector|...@>;
 23057  if loc<limit then if buffer[loc]<>"\" then start_input; {\&{input} assumed}
 23058  end
 23059  
 23060  @* \[50] Debugging.
 23061  Once \MF\ is working, you should be able to diagnose most errors with
 23062  the \.{show} commands and other diagnostic features. But for the initial
 23063  stages of debugging, and for the revelation of really deep mysteries, you
 23064  can compile \MF\ with a few more aids, including the \PASCAL\ runtime
 23065  checks and its debugger. An additional routine called |debug_help|
 23066  will also come into play when you type `\.D' after an error message;
 23067  |debug_help| also occurs just before a fatal error causes \MF\ to succumb.
 23068  @^debugging@>
 23069  @^system dependencies@>
 23070  
 23071  The interface to |debug_help| is primitive, but it is good enough when used
 23072  with a \PASCAL\ debugger that allows you to set breakpoints and to read
 23073  variables and change their values. After getting the prompt `\.{debug \#}', you
 23074  type either a negative number (this exits |debug_help|), or zero (this
 23075  goes to a location where you can set a breakpoint, thereby entering into
 23076  dialog with the \PASCAL\ debugger), or a positive number |m| followed by
 23077  an argument |n|. The meaning of |m| and |n| will be clear from the
 23078  program below. (If |m=13|, there is an additional argument, |l|.)
 23079  @.debug \#@>
 23080  
 23081  @d breakpoint=888 {place where a breakpoint is desirable}
 23082  
 23083  @<Last-minute...@>=
 23084  @!debug procedure debug_help; {routine to display various things}
 23085  label breakpoint,exit;
 23086  var @!k,@!l,@!m,@!n:integer;
 23087  begin clear_terminal;
 23088    loop begin wake_up_terminal;
 23089    print_nl("debug # (-1 to exit):"); update_terminal;
 23090  @.debug \#@>
 23091    read(term_in,m);
 23092    if m<0 then return
 23093    else if m=0 then
 23094      begin goto breakpoint;@/ {go to every declared label at least once}
 23095      breakpoint: m:=0; @{'BREAKPOINT'@}@/
 23096      end
 23097    else  begin read(term_in,n);
 23098      case m of
 23099      @t\4@>@<Numbered cases for |debug_help|@>@;
 23100      othercases print("?")
 23101      endcases;
 23102      end;
 23103    end;
 23104  exit:end;
 23105  gubed
 23106  
 23107  @ @<Numbered cases...@>=
 23108  1: print_word(mem[n]); {display |mem[n]| in all forms}
 23109  2: print_int(info(n));
 23110  3: print_int(link(n));
 23111  4: begin print_int(eq_type(n)); print_char(":"); print_int(equiv(n));
 23112    end;
 23113  5: print_variable_name(n);
 23114  6: print_int(internal[n]);
 23115  7: do_show_dependencies;
 23116  9: show_token_list(n,null,100000,0);
 23117  10: slow_print(n);
 23118  11: check_mem(n>0); {check wellformedness; print new busy locations if |n>0|}
 23119  12: search_mem(n); {look for pointers to |n|}
 23120  13: begin read(term_in,l); print_cmd_mod(n,l);
 23121    end;
 23122  14: for k:=0 to n do print(buffer[k]);
 23123  15: panicking:=not panicking;
 23124  
 23125  @* \[51] System-dependent changes.
 23126  This section should be replaced, if necessary, by any special
 23127  modifications of the program
 23128  that are necessary to make \MF\ work at a particular installation.
 23129  It is usually best to design your change file so that all changes to
 23130  previous sections preserve the section numbering; then everybody's version
 23131  will be consistent with the published program. More extensive changes,
 23132  which introduce new sections, can be inserted here; then only the index
 23133  itself will get a new section number.
 23134  @^system dependencies@>
 23135  
 23136  @* \[52] Index.
 23137  Here is where you can find all uses of each identifier in the program,
 23138  with underlined entries pointing to where the identifier was defined.
 23139  If the identifier is only one letter long, however, you get to see only
 23140  the underlined entries. {\sl All references are to section numbers instead of
 23141  page numbers.}
 23142  
 23143  This index also lists error messages and other aspects of the program
 23144  that you might want to look up some day. For example, the entry
 23145  for ``system dependencies'' lists all sections that should receive
 23146  special attention from people who are installing \MF\ in a new
 23147  operating environment. A list of various things that can't happen appears
 23148  under ``this can't happen''.
 23149  Approximately 25 sections are listed under ``inner loop''; these account
 23150  for more than 60\pct! of \MF's running time, exclusive of input and output.