summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mf.web
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2008-04-22 23:55:39 +0000
committerKarl Berry <karl@freefriends.org>2008-04-22 23:55:39 +0000
commit84fe7abdb90ee91379d256986b51ebc59f65eb87 (patch)
tree5ae9f62a2875eea941c06982a456440bfbf3ad81 /Build/source/texk/web2c/mf.web
parent227ddc990601089b65fc3b3ca07220d09c1d116e (diff)
mf 2.718281 from knuth
git-svn-id: svn://tug.org/texlive/trunk@7607 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/mf.web')
-rw-r--r--Build/source/texk/web2c/mf.web253
1 files changed, 135 insertions, 118 deletions
diff --git a/Build/source/texk/web2c/mf.web b/Build/source/texk/web2c/mf.web
index 3854d7c2638..13c4b85f498 100644
--- a/Build/source/texk/web2c/mf.web
+++ b/Build/source/texk/web2c/mf.web
@@ -24,6 +24,7 @@
% Version 2.718 fixed bug in <Choose a dependent...> (March 1995).
% Version 2.7182 fixed bugs related to "<unprintable char>" (August 1996).
% Version 2.71828 suppressed autorounding in dangerous cases (June 2003).
+% Version 2.718281 was a general cleanup with minor fixes (February 2008).
% A reward of $327.68 will be paid to the first finder of any remaining bug.
@@ -153,7 +154,7 @@ helping to determine whether an implementation deserves to be
known as `\MF\kern.5pt' [cf.~Stanford Computer Science report CS1095,
January 1986].
-@d banner=='This is METAFONT, Version 2.71828' {printed when \MF\ starts}
+@d banner=='This is METAFONT, Version 2.718281' {printed when \MF\ starts}
@ Different \PASCAL s have slightly different conventions, and the present
@!@:PASCAL H}{\ph@>
@@ -203,6 +204,7 @@ portions of the program heading.
Actually the heading shown here is not quite normal: The |program| line
does not mention any |output| file, because \ph\ would ask the \MF\ user
to specify a file name if |output| were specified here.
+@:PASCAL H}{\ph@>
@^system dependencies@>
@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:}
@@ -291,6 +293,7 @@ directives shown below specify full checking and inclusion of the \PASCAL\
debugger when \MF\ is being debugged, but they cause range checking and other
redundant code to be eliminated when the production system is being generated.
Arithmetic overflow will be detected in all cases.
+@:PASCAL H}{\ph@>
@^system dependencies@>
@^Overflow in arithmetic@>
@@ -326,6 +329,7 @@ if the compiler wants one. (Of course, if no default mechanism is
available, the |case| statements of \MF\ will have to be laboriously
extended by listing all remaining cases. People who are stuck with such
\PASCAL s have, in fact, done this, successfully but not happily!)
+@:PASCAL H}{\ph@>
@d othercases == others: {default for cases not listed explicitly}
@d endcases == @+end {follows the default case in an extended |case| statement}
@@ -784,6 +788,7 @@ begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f);
end;
@ Files can be closed with the \ph\ routine `|close(f)|', which
+@:PASCAL H}{\ph@>
@^system dependencies@>
should be used when all input or output with respect to |f| has been completed.
This makes |f| available to be opened again, if desired; and if |f| was used for
@@ -889,10 +894,12 @@ is considered an output file the file variable is |term_out|.
@ Here is how to open the terminal files
in \ph. The `\.{/I}' switch suppresses the first |get|.
+@:PASCAL H}{\ph@>
@^system dependencies@>
@d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
-@d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output}
+@d t_open_out==rewrite(term_out,'TTY:','/O')
+ {open the terminal for text output}
@ Sometimes it is necessary to synchronize the input/output mixture that
happens on the user's terminal, and three system-dependent
@@ -906,6 +913,7 @@ issue an unexpected error message). The third, |wake_up_terminal|,
is supposed to revive the terminal if the user has disabled it by
some instruction to the operating system. The following macros show how
these operations can be specified in \ph:
+@:PASCAL H}{\ph@>
@^system dependencies@>
@d update_terminal == break(term_out) {empty the terminal output buffer}
@@ -934,7 +942,7 @@ consist of the remainder of the command line, after the part that invoked \MF.
The first line is special also because it may be read before \MF\ has
input a base file. In such cases, normal error messages cannot yet
be given. The following code uses concepts that will be explained later.
-(If the \PASCAL\ compiler does not support non-local |@!goto|, the
+(If the \PASCAL\ compiler does not support non-local |@!goto|\unskip, the
@^system dependencies@>
statement `|goto final_end|' should be replaced by something that
quietly terminates the program.)
@@ -1043,6 +1051,7 @@ not to those generated dynamically by the user.)
Some \PASCAL\ compilers won't pack integers into a single byte unless the
integers lie in the range |-128..127|. To accommodate such systems
we access the string pool only via macros that can easily be redefined.
+@^system dependencies@>
@d si(#) == # {convert from |ASCII_code| to |packed_ASCII_code|}
@d so(#) == # {convert from |packed_ASCII_code| to |ASCII_code|}
@@ -1252,7 +1261,8 @@ The boolean expression defined here should be |true| unless \MF\ internal
code number~|k| corresponds to a non-troublesome visible symbol in the
local character set.
If character |k| cannot be printed, and |k<@'200|, then character |k+@'100| or
-|k-@'100| must be printable; moreover, ASCII codes |[@'60..@'71, @'141..@'146]|
+|k-@'100| must be printable; moreover, ASCII codes
+|[@'60..@'71, @'136, @'141..@'146]|
must be printable.
@^character set dependencies@>
@^system dependencies@>
@@ -2042,6 +2052,7 @@ as efficient as possible.
desirable to avoid producing multiple error messages in case of arithmetic
overflow. So the routines below set the global variable |arith_error| to |true|
instead of reporting errors directly to the user.
+@^overflow in arithmetic@>
@<Glob...@>=
@!arith_error:boolean; {has arithmetic overflow occurred recently?}
@@ -2275,7 +2286,7 @@ var @!p:integer; {the fraction so far}
@!negative:boolean; {should the result be negated?}
@!n:integer; {additional multiple of $q$}
@!be_careful:integer; {disables certain compiler optimizations}
-begin @<Reduce to the case that |f>=0| and |q>0|@>;
+begin @<Reduce to the case that |f>=0| and |q>=0|@>;
if f<fraction_one then n:=0
else begin n:=f div fraction_one; f:=f mod fraction_one;
if q<=el_gordo div n then n:=n*q
@@ -2292,7 +2303,7 @@ if negative then take_fraction:=-(n+p)
else take_fraction:=n+p;
end;
-@ @<Reduce to the case that |f>=0| and |q>0|@>=
+@ @<Reduce to the case that |f>=0| and |q>=0|@>=
if f>=0 then negative:=false
else begin negate(f); negative:=true;
end;
@@ -2331,7 +2342,7 @@ var @!p:integer; {the fraction so far}
@!negative:boolean; {should the result be negated?}
@!n:integer; {additional multiple of $q$}
@!be_careful:integer; {disables certain compiler optimizations}
-begin @<Reduce to the case that |f>=0| and |q>0|@>;
+begin @<Reduce to the case that |f>=0| and |q>=0|@>;
if f<unity then n:=0
else begin n:=f div unity; f:=f mod unity;
if q<=el_gordo div n then n:=n*q
@@ -3238,7 +3249,7 @@ relevant size when a node is freed. Locations greater than or equal to
\.{AVAIL} stack is used for allocation in this region.
Locations of |mem| between |mem_min| and |mem_top| may be dumped as part
-of preloaded format files, by the \.{INIMF} preprocessor.
+of preloaded base files, by the \.{INIMF} preprocessor.
@.INIMF@>
Production versions of \MF\ may extend the memory at the top end in order to
provide more space; these locations, between |mem_top| and |mem_max|,
@@ -3514,7 +3525,6 @@ appear in locations |hi_mem_stat_min| through |mem_top|, inclusive.
when \MF\ is initializing itself the slow way.
@<Initialize table entries (done by \.{INIMF} only)@>=
-@^data structure assumptions@>
rover:=lo_mem_stat_max+1; {initialize the dynamic memory}
link(rover):=empty_flag;
node_size(rover):=1000; {which is a 1000-word available node}
@@ -3714,7 +3724,7 @@ and error-recovery methods of this program.
At any rate, here is the list, for future reference.
@d if_test=1 {conditional text (\&{if})}
-@d fi_or_else=2 {delimiters for conditionals (\&{elseif}, \&{else}, \&{fi}}
+@d fi_or_else=2 {delimiters for conditionals (\&{elseif}, \&{else}, \&{fi})}
@d input=3 {input a source file (\&{input}, \&{endinput})}
@d iteration=4 {iterate (\&{for}, \&{forsuffixes}, \&{forever}, \&{endfor})}
@d repeat_loop=5 {special command substituted for \&{endfor}}
@@ -3743,7 +3753,7 @@ At any rate, here is the list, for future reference.
@d delimiters=27 {define a pair of delimiters (\&{delimiters})}
@d open_window=28 {define a window on the screen (\&{openwindow})}
@d special_command=29 {output special info (\&{special}, \&{numspecial})}
-@d type_name=30 {declare a type (\&{numeric}, \&{pair}, etc.}
+@d type_name=30 {declare a type (\&{numeric}, \&{pair}, etc.)}
@d max_statement_command=type_name
@d min_primary_command=type_name
@d left_delimiter=31 {the left delimiter of a matching pair}
@@ -3802,7 +3812,7 @@ At any rate, here is the list, for future reference.
@d step_token=74 {the operator `\&{step}'}
@d until_token=75 {the operator `\&{until}'}
@d lig_kern_token=76
- {the operators `\&{kern}' and `\.{=:}' and `\.{=:\char'174}, etc.}
+ {the operators `\&{kern}' and `\.{=:}' and `\.{=:\char'174}', etc.}
@d assignment=77 {the operator `\.{:=}'}
@d skip_to=78 {the operation `\&{skipto}'}
@d bchar_label=79 {the operator `\.{\char'174\char'174:}'}
@@ -4074,7 +4084,7 @@ fuss with. Every such parameter has an identifying code number, defined here.
@d tracing_stats=12 {show memory usage at end of job}
@d tracing_online=13 {show long diagnostics on terminal and in the log file}
@d year=14 {the current year (e.g., 1984)}
-@d month=15 {the current month (e.g, 3 $\equiv$ March)}
+@d month=15 {the current month (e.g., 3 $\equiv$ March)}
@d day=16 {the current day of the month}
@d time=17 {the number of minutes past midnight when this job started}
@d char_code=18 {the number of the next character to be output}
@@ -4926,9 +4936,8 @@ present, we shall refer to the |info| field of this special node as the
@^reference counts@>
The next node or nodes after the reference count serve to describe the
-formal parameters. They either contain a code word that specifies all
-of the parameters, or they contain zero or more parameter tokens followed
-by the code `|general_macro|'.
+formal parameters. They consist of zero or more parameter tokens followed
+by a code for the type of macro.
@d ref_count==info {reference count preceding a macro definition or pen header}
@d add_mac_ref(#)==incr(ref_count(#)) {make a new reference to a macro list}
@@ -4982,7 +4991,7 @@ exit:end;
The variables of \MF\ programs can be simple, like `\.x', or they can
combine the structural properties of arrays and records, like `\.{x20a.b}'.
A \MF\ user assigns a type to a variable like \.{x20a.b} by saying, for
-example, `\.{boolean} \.{x20a.b}'. It's time for us to study how such
+example, `\.{boolean} \.{x[]a.b}'. It's time for us to study how such
things are represented inside of the computer.
Each variable value occupies two consecutive words, either in a two-word
@@ -5027,7 +5036,8 @@ final attribute node links to the constant |end_attr|, whose |attr_loc|
field is greater than any legal hash address. The |attr_head| in the
parent points to a node whose |name_type| is |structured_root|; this
node represents the null attribute, i.e., the variable that is relevant
-when no attributes are attached to the parent. The |attr_head| node is either
+when no attributes are attached to the parent. The |attr_head| node
+has the fields of either
a value node, a subscript node, or an attribute node, depending on what
the parent would be if it were not structured; but the subscript and
attribute fields are ignored, so it effectively contains only the data of
@@ -5066,9 +5076,10 @@ a pencil to draw a diagram.) The lone variable `\.x' is represented by
to an attribute node representing `\.{x[]}'. Thus |name_type(q1)=attr|,
|attr_loc(q1)=collective_subscript=0|, |parent(q1)=p|,
|type(q1)=structured|, |attr_head(q1)=qq|, and |subscr_head(q1)=qq1|;
-|qq| is a value node with |type(qq)=numeric_type| (assuming that \.{x5} is
-numeric, because |qq| represents `\.{x[]}' with no further attributes),
-|name_type(qq)=structured_root|, and
+|qq| is a three-word ``attribute-as-value'' node with |type(qq)=numeric_type|
+(assuming that \.{x5} is numeric, because |qq| represents `\.{x[]}'
+with no further attributes), |name_type(qq)=structured_root|,
+|attr_loc(qq)=0|, |parent(qq)=p|, and
|link(qq)=qq1|. (Now pay attention to the next part.) Node |qq1| is
an attribute node representing `\.{x[][]}', which has never yet
occurred; its |type| field is |undefined|, and its |value| field is
@@ -5085,8 +5096,10 @@ Furthermore |subscript(r1)=20.0|, |name_type(r1)=subscr|,
|type(r1)=structured|, |attr_head(r1)=qqq|, |subscr_head(r1)=qqq1|,
and we finish things off with three more nodes
|qqq|, |qqq1|, and |qqq2| hung onto~|r1|. (Perhaps you should start again
-with a larger sheet of paper.) The value of variable \.{x20b}
-appears in node~|qqq2|, as you can well imagine.
+with a larger sheet of paper.) The value of variable `\.{x20b}'
+appears in node~|qqq2=link(qqq1)|, as you can well imagine.
+Similarly, the value of `\.{x.a}' appears in node |q2=link(q1)|, where
+|attr_loc(q2)=h(a)| and |parent(q2)=p|.
If the example in the previous paragraph doesn't make things crystal
clear, a glance at some of the simpler subroutines below will reveal how
@@ -5523,7 +5536,7 @@ defined_macro,secondary_primary_macro,tertiary_secondary_macro,
tag_token:if q<>null then
if saving then name_type(q):=saved_root
else begin flush_below_variable(q); free_node(q,value_node_size);
- end;
+ end;@;
othercases do_nothing
endcases;@/
eqtb[p]:=eqtb[frozen_undefined];
@@ -5549,7 +5562,7 @@ until the most recent such entry has been removed.
\smallskip\hang
|info(p)=q|, where |1<=q<=hash_end|, means that |mem[p+1]| holds the former
contents of |eqtb[q]|. Such save stack entries are generated by \&{save}
-commands or suitable \&{interim} commands.
+commands.
\smallskip\hang
|info(p)=hash_end+q|, where |q>0|, means that |value(p)| is a |scaled|
@@ -5699,7 +5712,7 @@ the knot, and to \\{left} fields instead of \\{right} fields.
Non-|explicit| control points will be chosen based on ``tension'' parameters
in the |left_tension| and |right_tension| fields. The
`\&{atleast}' option is represented by negative tension values.
-@!@:at_least_}{\&{atleast} primitive@>
+@:at_least_}{\&{atleast} primitive@>
For example, the \MF\ path specification
$$\.{z0..z1..tension atleast 1..\{curl 2\}z2..z3\{-1,-2\}..tension
@@ -5826,9 +5839,6 @@ if (left_type(p)<>explicit)and(left_type(p)<>open) then
@ A curl of 1 is shown explicitly, so that the user sees clearly that
\MF's default curl is present.
-The code here uses the fact that |left_curl==left_given| and
-|right_curl==right_given|.
-
@<Print information for a curve that begins |curl|...@>=
begin if left_type(p)=open then print("??"); {can't happen}
@.??@>
@@ -6079,7 +6089,7 @@ have been given for $0<k<n$, and it will be convenient to introduce
equations of the same form for $k=0$ and $k=n$, where
$$A_0=B_0=C_n=D_n=0.$$
If $\theta_0$ is supposed to have a given value $E_0$, we simply
-define $C_0=0$, $D_0=0$, and $R_0=E_0$. Otherwise a curl
+define $C_0=1$, $D_0=0$, and $R_0=E_0$. Otherwise a curl
parameter, $\gamma_0$, has been specified at~$z_0$; this means
that the mock curvature at $z_0$ should be $\gamma_0$ times the
mock curvature at $z_1$; i.e.,
@@ -6499,7 +6509,6 @@ end;
$\\{ss}\L\sin\theta\,/\sin(\theta+\phi)$ are to be enforced if $\sin\theta$,
$\sin\phi$, and $\sin(\theta+\phi)$ all have the same sign. Otherwise
there is no ``bounding triangle.''
-@!@:at_least_}{\&{atleast} primitive@>
@<Decrease the velocities, if necessary...@>=
if((st>=0)and(sf>=0))or((st<=0)and(sf<=0)) then
@@ -6599,7 +6608,7 @@ for the two subintervals after bisection are respectively
$(Z_1^{(1)},Z_1^{(2)},\ldots,Z_1^{(n)})$ and
$(Z_1^{(n)},Z_2^{(n-1)},\ldots,Z_n^{(1)})$.
And the values of $z_0$ appropriate for the bisected interval are $z'_0=z_0$
-and $z''_0=z_0+(Z_1+Z_2+\cdots+Z_n)/2^{l+1}$.
+and $z''_0=z_0+(Z'_1+Z'_2+\cdots+Z'_n)/2^{l+1}$.
Step $2'$ involves division by~2, which introduces computational errors
of at most $1\over2$ at each step; thus after $l$~levels of bisection the
@@ -6792,7 +6801,7 @@ upset the symmetry. We can restore much of the lost symmetry by adding
@ One further possibility needs to be mentioned: The algorithm
will be applied only to cubic polynomials $B(x_0,x_1,x_2,x_3;t)$ that
are nondecreasing as $t$~varies from 0 to~1; this condition turns
-out to hold if and only if $x_0\L x_1$, $x_2\L x_3$, and either
+out to hold if and only if $x_0\L x_1$ and $x_2\L x_3$, and either
$x_1\L x_2$ or $(x_1-x_2)^2\L(x_1-x_0)(x_3-x_2)$. If bisection were
carried out with perfect accuracy, these relations would remain
invariant. But rounding errors can creep in, hence the bisection
@@ -6801,7 +6810,7 @@ initial conditions. This leads to the potential danger that $m$ or~$n$
could become negative in the algorithm described above.
For example, if we start with $(x_1-x_0,x_2-x_1,x_3-x_2)=
-(X_1,X_2,X_3)=(7,-16,58)$, the corresponding polynomial is
+(X_1,X_2,X_3)=(7,-16,39)$, the corresponding polynomial is
monotonic, because $16^2<7\cdot39$. But the bisection algorithm
produces the left descendant $(7,-5,3)$, which is nonmonotonic;
its right descendant is~$(0,-1,3)$.
@@ -6828,10 +6837,10 @@ In either case the condition $\lfloor\xt_3\rfloor-\lfloor\xt_0\rfloor>0$
implies that $\xt_3-\xt_0>1-2\epsilon$, hence $x_3-x_0>1-4\epsilon$.
But it can be shown that if $B(x_0,x_1,x_2,x_3;t)$ is a monotonic
cubic, then $B(x_0,x_1,x_2,x_3;{1\over2})$ is always between
-$.14[x_0,x_3]$ and $.86[x_0,x_3]$; and it is impossible for $\bar x$
+$.06[x_0,x_3]$ and $.94[x_0,x_3]$; and it is impossible for $\bar x$
to be within~$\epsilon$ of such a number. Contradiction!
-(The constant .14 is actually $(7-\sqrt{28}\,)/12$; the worst case
-occurs for polynomials like $B(0,28-4\sqrt{28},14-5\sqrt{28},42;t)$.)
+(The constant .06 is actually $(2-\sqrt3\,)/4$; the worst case
+occurs for polynomials like $B(0,2-\sqrt3,1-\sqrt3,3;t)$.)
@ OK, now that a long theoretical preamble has justified the
bisection-and-doubling algorithm, we are ready to proceed with
@@ -7121,7 +7130,7 @@ unsorted list whenever the corresponding row has been displayed.
@<Initialize table entries...@>=
info(sentinel):=max_halfword; {|link(sentinel)=null|}
-@ The rows themselves are represented by row-header nodes that
+@ The rows themselves are represented by row header nodes that
contain four link fields. Two of these four, |sorted| and |unsorted|,
point to the first items of the edge-weight lists just mentioned.
The other two, |link| and |knil|, point to the headers of the two
@@ -8308,7 +8317,7 @@ end;
@ @<Glob...@>=
@!cur_x,@!cur_y:scaled;
- {outputs of |rotate|, |unrotate|, and a few other routines}
+ {outputs of |skew|, |unskew|, and a few other routines}
@ The conversion to skewed and rotated coordinates takes place in
stages, and at one point in the transformation we will have negated the
@@ -8539,6 +8548,7 @@ print_err(s);
end;
@ If the segment numbers on the cycle are $t_1$, $t_2$, \dots, $t_m$,
+and if |m<=max_quarterword|,
we have $t_{k-1}\L t_k$ except for at most one value of~$k$. If there are
no exceptions, $f$ will point to $t_1$; otherwise it will point to the
exceptional~$t_k$.
@@ -8651,7 +8661,7 @@ applied to a double path.
here will propagate to all descendants of cubics that are split into
subintervals. These numbers must be nonzero, but otherwise they are
present merely for diagnostic purposes. The cubic from |p| to~|q|
-that represents ``time interval'' |(t-1)..t| usually has |right_type(q)=t|,
+that represents ``time interval'' |(t-1)..t| usually has |left_type(q)=t|,
except when |t| is too large to be stored in a quarterword.
@d procrustes(#)==@+if abs(#)>=dmax then
@@ -9144,7 +9154,8 @@ end
vertical, and diagonal tangents occur at places that will produce appropriate
images after the curve is digitized.
-The first job is to fix things so that |x(t)| is an integer multiple of the
+The first job is to fix things so that |x(t)| plus the horizontal pen offset
+is an integer multiple of the
current ``granularity'' when the derivative $x'(t)$ crosses through zero.
The given cyclic path contains regions where $x'(t)\G0$ and regions
where $x'(t)\L0$. The |quadrant_subdivide| routine is called into action
@@ -9163,8 +9174,8 @@ complications can arise that might make the task more difficult. In the
first place, autorounding is inappropriate at cusps where $x'$ jumps
discontinuously past zero without ever being zero. In the second place,
the current pen might be unsymmetric in such a way that $x$ coordinates
-should round differently when $x'$ becomes positive than when it becomes
-negative. These considerations imply that round$(x_0)$ might be greater
+should round differently in different parts of the curve.
+These considerations imply that round$(x_0)$ might be greater
than round$(x_1)$, even though $x_0\L x_1$; in such cases we do not want
to carry out the linear transformation. Furthermore, it's possible to have
round$(x_1)-\hbox{round} (x_0)$ positive but much greater than $x_1-x_0$;
@@ -9315,18 +9326,11 @@ if odd(right_type(p))<>odd(right_type(q)) then
|x|~coordinate of the current pen's west edge is
$$\hbox{|y_coord(link(cur_pen+seventh_octant))|},$$
and that there are similar ways to address other important offsets.
-An ``|east_west_edge|'' is computed as a compromise between east and
-west, for use in doublepaths, in case the two edges have conflicting
-tendencies.
@d north_edge(#)==y_coord(link(#+fourth_octant))
@d south_edge(#)==y_coord(link(#+first_octant))
@d east_edge(#)==y_coord(link(#+second_octant))
@d west_edge(#)==y_coord(link(#+seventh_octant))
-@d north_south_edge(#)==mem[#+10].int {compromise between north and south}
-@d east_west_edge(#)==mem[#+11].int {compromise between east and west}
-@d NE_SW_edge(#)==mem[#+12].int {compromise between northeast and southwest}
-@d NW_SE_edge(#)==mem[#+13].int {compromise between northwest and southeast}
@<Compute before-and-after |x| values based on the current pen@>=
begin if cur_pen=null_pen then pen_edge:=0
@@ -9804,7 +9808,7 @@ truncated biased path $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor
\bigr)$ and information about the initial and final endpoints. If the
unrounded and unbiased
path begins at $(x_0,y_0)$ and ends at $(x_1,y_1)$, it's possible to
-prove (by induction on the length of truncated biased path) that the
+prove (by induction on the length of the truncated biased path) that the
rounded unbiased path is obtained by the following construction:
\yskip\textindent{1)} Start at $\bigl(\round(x_0),\round(y_0)\bigr)$.
@@ -10023,23 +10027,23 @@ $$w_0\;w_1\;w_2\;w_2\;=\;(0,-1)\;(3,-1)\;(6,1)\;(6,1).$$
With skewed coordinates $(u-v,v)$ instead of $(u,v)$ we obtain the list
$$w_0\;w_1\;w_2\;w_2\;\mapsto\;(1,-1)\;(4,-1)\;(5,1)\;(5,1),$$
which is what actually appears in the data structure. In the second
-octant there's only one offset; we list it three times (with coordinates
+octant there's only one offset; we list it twice (with coordinates
interchanged, so as to make the second octant look like the first),
and skew those coordinates, obtaining
$$\tabskip\centering
\halign to\hsize{$\hfil#\;\mapsto\;{}$\tabskip=0pt&
$#\hfil$&\quad in the #\hfil\tabskip\centering\cr
-w_2\;w_2\;w_2&(-5,6)\;(-5,6)\;(-5,6)\cr
+w_2\;w_2&(-5,6)\;(-5,6)\cr
\noalign{\vskip\belowdisplayskip
\vbox{\noindent\strut as the list of transformed and skewed offsets to use
-when curves that travel in the second octant. Similarly, we will have\strut}
+when curves travel in the second octant. Similarly, we will have\strut}
\vskip\abovedisplayskip}
-w_2\;w_2\;w_2&(7,-6)\;(7,-6)\;(7,-6)&third;\cr
+w_2\;w_2&(7,-6)\;(7,-6)&third;\cr
w_2\;w_2\;w_3\;w_3&(-7,1)\;(-7,1)\;(-3,2)\;(-3,2)&fourth;\cr
-w_3\;w_3\;w_3&(3,-2)\;(3,-2)\;(3,-2)&fifth;\cr
-w_3\;w_3\;w_0\;w_0&(-3,1)\;(-3,1)\;(1,0)\;(1,0)&sixth;\cr
-w_0\;w_0\;w_0&(1,0)\;(1,0)\;(1,0)&seventh;\cr
-w_0\;w_0\;w_0&(-1,1)\;(-1,1)\;(-1,1)&eighth.\cr}$$
+w_3\;w_3&(1,-2)\;(1,-2)&fifth;\cr
+w_3\;w_3\;w_0\;w_0&(-1,1)\;(-1,1)\;(1,0)\;(1,0)&sixth;\cr
+w_0\;w_0&(1,0)\;(1,0)&seventh;\cr
+w_0\;w_0&(-1,1)\;(-1,1)&eighth.\cr}$$
Notice that $w_1$ is considered here to be internal to the first octant;
it's not part of the eighth. We could equally well have taken $w_0$ out
of the first octant list and put it into the eighth; then the first octant
@@ -10071,8 +10075,9 @@ where $(u_k,v_k)$ is the representation of $w_k$ after it has been rotated
into a first-octant disguise.
@ The top-level data structure of a pen polygon is a 10-word node containing
-a reference count followed by pointers to the eight pen lists, followed
+a reference count followed by pointers to the eight offset lists, followed
by an indication of the pen's range of values.
+@^reference counts@>
If |p|~points to such a node, and if the
offset list for, say, the fourth octant has entries $w_0$, $w_1$, \dots,
@@ -10095,7 +10100,7 @@ The tenth word of a pen header node contains the maximum absolute value of
an $x$ or $y$ coordinate among all of the unskewed pen offsets.
The |link| field of a pen header node should be |null| if and only if
-the pen has no offsets.
+the pen is a single point.
@d pen_node_size=10
@d coord_node_size=3
@@ -10140,6 +10145,7 @@ end
predeclared for error recovery. It doesn't need a proper
reference count, because the |toss_pen| procedure below
will never delete it from memory.
+@^reference counts@>
@<Initialize table entries...@>=
ref_count(null_pen):=null; link(null_pen):=null;@/
@@ -10435,7 +10441,7 @@ and~|q| should be associated with the |k|th offset when |right_type(p)=k|.
List |c| is actually part of a cycle spec, so it terminates at the
first node whose |right_type| is |endpoint|. The cubics all have
-monotone-nondecreasing $x'(t)$ and $y'(t)$.
+monotone-nondecreasing $x(t)$ and $y(t)$.
@p @t\4@>@<Declare subroutines needed by |offset_prep|@>@;
procedure offset_prep(@!c,@!h:pointer);
@@ -10491,8 +10497,8 @@ end;
of these, the $k$th pen slope is defined by the formula
$$s_k={v\k-v_k\over u\k-u_k},\qquad\hbox{for $0<k<n$}.$$
In odd-numbered octants, the numerator and denominator of this fraction
-will be positive; in even-numbered octants they will both be negative.
-Furthermore we always have $0=s_0<s_1<\cdots<s_n=\infty$. The goal of
+will be nonnegative; in even-numbered octants they will both be nonpositive.
+Furthermore we always have $0=s_0\le s_1\le\cdots\le s_n=\infty$. The goal of
|offset_prep| is to find an offset index~|k| to associate with
each cubic, such that the slope $s(t)$ of the cubic satisfies
$$s_{k-1}\le s(t)\le s_k\qquad\hbox{for $0\le t\le 1$.}\eqno(*)$$
@@ -10598,7 +10604,7 @@ exit:end;
@ @<Compute test coefficients |(t0,t1,t2)| for $s(t)$ versus...@>=
du:=x_coord(ww)-x_coord(w); dv:=y_coord(ww)-y_coord(w);
-if abs(du)>=abs(dv) then {$s_{k\pm1}\le1$}
+if abs(du)>=abs(dv) then {$s_{k-1}\le1$ or $s_k\le1$}
begin s:=make_fraction(dv,du);
t0:=take_fraction(x0,s)-y0;
t1:=take_fraction(x1,s)-y1;
@@ -10611,8 +10617,8 @@ else begin s:=make_fraction(du,dv);
end
@ The curve has crossed $s_k$ or $s_{k-1}$; its initial segment satisfies
-$(*)$, and it might cross again and return towards $s_k$, yielding another
-solution of $(*)$.
+$(*)$, and it might cross again and return towards $s_{k-1}$ or $s_k$,
+respectively, yielding another solution of $(*)$.
@<Split the cubic at $t$, and split off another...@>=
begin split_for_offset(p,t); right_type(p):=k; p:=link(p);@/
@@ -10791,7 +10797,7 @@ begin print_nl("@@ Octant "); print(octant_dir[octant]);
print(" ("); print_int(info(h)); print(" offset");
if info(h)<>1 then print_char("s");
print("), from ");
-print_two_true(x_coord(p)+x_coord(w),y_coord(p)+y_coord(w));
+print_two_true(x_coord(p)+x_coord(w),y_coord(p)+y_coord(w));@/
ww:=link(h);@+if right_transition(q)=diagonal then ww:=knil(ww);
print(" to ");
print_two_true(x_coord(q)+x_coord(ww),y_coord(q)+y_coord(ww));
@@ -10925,6 +10931,7 @@ end
@ @<Insert the new envelope moves in the pixel data@>=
debug if (m<>mm1)or(move_ptr<>n1-n0) then confusion("1");@+gubed@;@/
+@:this can't happen /}{\quad 1@>
move[0]:=d0+env_move[0]-mm0;
for n:=1 to move_ptr do
move[n]:=env_move[n]-env_move[n-1]+1;
@@ -11039,6 +11046,7 @@ finishing-up process is slightly different in the dual case.
@<Insert the new envelope moves dually in the pixel data@>=
debug if (m<>mm1)or(move_ptr<>n1-n0) then confusion("2");@+gubed@;@/
+@:this can't happen /}{\quad 2@>
move[0]:=d0+env_move[1]-mm0;
for n:=1 to move_ptr do
move[n]:=env_move[n+1]-env_move[n]+1;
@@ -11228,7 +11236,7 @@ discarded during the course of the algorithm.
The contents of |right_u(p)| and |left_v(q)| are integer multiples
of |half_unit|, just like the coordinate fields. Hence, for example,
-the point $\bigl($|x_coord(p)-left_v(q),y_coord(p)+right_u(q)|$\bigr)$
+the point $\bigl($|x_coord(p)-left_v(q),y_coord(p)+right_u(p)|$\bigr)$
also belongs to class number |right_class(p)|. This point is one
step closer to the vertex in node~|q|; it equals that vertex
if and only if |left_length(q)=1|.
@@ -11304,7 +11312,7 @@ if (major_axis=minor_axis)or(theta mod ninety_deg=0) then
begin beta:=major_axis; gamma:=minor_axis;
n_sin:=fraction_one; n_cos:=0; {|n_sin| and |n_cos| are used later}
end
- else begin beta:=minor_axis; gamma:=major_axis;
+ else begin beta:=minor_axis; gamma:=major_axis; theta:=0;
end; {|n_sin| and |n_cos| aren't needed in this case}
end
else begin symmetric:=false;
@@ -11528,7 +11536,7 @@ else begin y:=make_fraction(y,abs(x));
end
@ Since we're interested in the tangent directions, we work with the
-derivative $${\textstyle1\over3}B'(x_0,x_1,x_2,x_3;t)=
+derivative $${1\over3}B'(x_0,x_1,x_2,x_3;t)=
B(x_1-x_0,x_2-x_1,x_3-x_2;t)$$ instead of
$B(x_0,x_1,x_2,x_3;t)$ itself. The derived coefficients are also scaled up
in order to achieve better accuracy.
@@ -11697,7 +11705,7 @@ overlap if and only if $u\submin\L x\submax$ and
$x\submin\L u\submax$. Letting
$$U\submin=\min(0,U_1,U_1+U_2,U_1+U_2+U_3),\;
U\submax=\max(0,U_1,U_1+U_2,U_1+U_2+U_3),$$
-we have $u\submin=2^lu_0+U\submin$, etc.; the condition for overlap
+we have $2^lu\submin=2^lu_0+U\submin$, etc.; the condition for overlap
reduces to
$$X\submin-U\submax\L 2^l(u_0-x_0)\L X\submax-U\submin.$$
Thus we want to maintain the quantity $2^l(u_0-x_0)$; similarly,
@@ -11901,13 +11909,14 @@ split |cubic_intersection| up into two procedures.
@<Glob...@>=
@!delx,@!dely:integer; {the components of $\Delta=2^l(w_0-z_0)$}
-@!tol:integer; {bound on the uncertainly in the overlap test}
+@!tol:integer; {bound on the uncertainty in the overlap test}
@!uv,@!xy:0..bistack_size; {pointers to the current packets of interest}
@!three_l:integer; {|tol_step| times the bisection level}
@!appr_t,@!appr_tt:integer; {best approximations known to the answers}
@ We shall assume that the coordinates are sufficiently non-extreme that
integer overflow will not occur.
+@^overflow in arithmetic@>
@<Initialize for intersections at level zero@>=
q:=link(p); qq:=link(pp); bisect_ptr:=int_packets;@/
@@ -11958,8 +11967,8 @@ not_found: if odd(cur_tt) then
+stack_3(u_packet(uv));
dely:=dely+stack_1(v_packet(uv))+stack_2(v_packet(uv))
+stack_3(v_packet(uv));
- uv:=uv+int_packets; {switch from |l_packet| to |r_packet|}
- decr(cur_tt); xy:=xy-int_packets; {switch from |r_packet| to |l_packet|}
+ uv:=uv+int_packets; {switch from |l_packets| to |r_packets|}
+ decr(cur_tt); xy:=xy-int_packets; {switch from |r_packets| to |l_packets|}
delx:=delx+stack_1(x_packet(xy))+stack_2(x_packet(xy))
+stack_3(x_packet(xy));
dely:=dely+stack_1(y_packet(xy))+stack_2(y_packet(xy))
@@ -11970,7 +11979,7 @@ else begin incr(cur_tt); tol:=tol+three_l;
-stack_3(x_packet(xy));
dely:=dely-stack_1(y_packet(xy))-stack_2(y_packet(xy))
-stack_3(y_packet(xy));
- xy:=xy+int_packets; {switch from |l_packet| to |r_packet|}
+ xy:=xy+int_packets; {switch from |l_packets| to |r_packets|}
end
@ @<Descend to the previous level...@>=
@@ -12462,7 +12471,10 @@ independent variables it depends on is reverting to |undefined|.
@d s_scale=64 {the serial numbers are multiplied by this factor}
@d new_indep(#)== {create a new independent variable}
- begin type(#):=independent; serial_no:=serial_no+s_scale;
+ begin if serial_no>el_gordo-s_scale then
+ overflow("independent variables",serial_no div s_scale);
+@:METAFONT capacity exceeded independent variables}{\quad independent variables@>
+ type(#):=independent; serial_no:=serial_no+s_scale;
value(#):=serial_no;
end
@@ -14005,8 +14017,8 @@ fin_numeric_token:@<Pack the numeric and fraction parts of a numeric token
found: cur_sym:=id_lookup(k,loc-k);
end
-@ We go to |restart| instead of to |switch|, because |state| might equal
-|token_list| after the error has been dealt with
+@ We go to |restart| instead of to |switch|, because we might enter
+|token_state| after the error has been dealt with
(cf.\ |clear_for_error_prompt|).
@<Decry the invalid...@>=
@@ -14253,7 +14265,7 @@ it makes sense to have most of the work done by a single subroutine. That
subroutine is called |scan_toks|.
The first parameter to |scan_toks| is the command code that will
-terminate scanning (either |macro_def|, |loop_repeat|, or |iteration|).
+terminate scanning (either |macro_def| or |iteration|).
The second parameter, |subst_list|, points to a (possibly empty) list
of two-word nodes whose |info| and |value| fields specify symbol tokens
@@ -14909,7 +14921,7 @@ if (cur_cmd<>right_delimiter)or(cur_mod<>l_delim) then
back_error;
end
-@ A \&{suffix} or \&{text} parameter will be have been scanned as
+@ A \&{suffix} or \&{text} parameter will have been scanned as
a token list pointed to by |cur_exp|, in which case we will have
|cur_type=token_list|.
@@ -15512,7 +15524,7 @@ of three system-dependent
procedures called |begin_name|, |more_name|, and |end_name|. In
essence, if the user-specified characters of the file name are $c_1\ldots c_n$,
the system-independent driver program does the operations
-$$|begin_name|;\,|more_name|(c_1);\,\ldots\,;|more_name|(c_n);
+$$|begin_name|;\,|more_name|(c_1);\,\ldots\,;\,|more_name|(c_n);
\,|end_name|.$$
These three procedures communicate with each other via global variables.
Afterwards the file name will appear in the string pool as three strings
@@ -16021,8 +16033,8 @@ or |false_code|.
\smallskip\hang
|cur_type=unknown_boolean| means that |cur_exp| points to a capsule
-node that is in the ring of variables equivalent
-to at least one undefined boolean variable.
+node that is in
+a ring of equivalent booleans whose value has not yet been defined.
\smallskip\hang
|cur_type=string_type| means that |cur_exp| is a string number (i.e., an
@@ -16031,8 +16043,8 @@ includes this particular reference.
\smallskip\hang
|cur_type=unknown_string| means that |cur_exp| points to a capsule
-node that is in the ring of variables equivalent
-to at least one undefined string variable.
+node that is in
+a ring of equivalent strings whose value has not yet been defined.
\smallskip\hang
|cur_type=pen_type| means that |cur_exp| points to a pen header node. This
@@ -16041,8 +16053,8 @@ reference.
\smallskip\hang
|cur_type=unknown_pen| means that |cur_exp| points to a capsule
-node that is in the ring of variables equivalent
-to at least one undefined pen variable.
+node that is in
+a ring of equivalent pens whose value has not yet been defined.
\smallskip\hang
|cur_type=future_pen| means that |cur_exp| points to a knot list that
@@ -16057,8 +16069,8 @@ the path will have been chosen.
\smallskip\hang
|cur_type=unknown_path| means that |cur_exp| points to a capsule
-node that is in the ring of variables equivalent
-to at least one undefined path variable.
+node that is in
+a ring of equivalent paths whose value has not yet been defined.
\smallskip\hang
|cur_type=picture_type| means that |cur_exp| points to an edges header node.
@@ -16066,8 +16078,8 @@ Nobody else points to this particular set of edges.
\smallskip\hang
|cur_type=unknown_picture| means that |cur_exp| points to a capsule
-node that is in the ring of variables equivalent
-to at least one undefined picture variable.
+node that is in
+a ring of equivalent pictures whose value has not yet been defined.
\smallskip\hang
|cur_type=transform_type| means that |cur_exp| points to a |transform_type|
@@ -16102,8 +16114,7 @@ example, in the expression
\smallskip\hang
|cur_type=token_list| means that |cur_exp| points to a linked list of
-tokens. This case arises only on the left-hand side of an assignment
-(`\.{:=}') operation, under very special circumstances.
+tokens.
\smallskip\noindent
The possible settings of |cur_type| have been listed here in increasing
@@ -16113,9 +16124,9 @@ are allowed. Conversely, \MF\ has no variables of type |vacuous| or
|token_list|.
@ Capsules are two-word nodes that have a similar meaning
-to |cur_type| and |cur_exp|. Such nodes have |name_type=capsule|
-and |link<=void|; and their |type| field is one of the possibilities for
-|cur_type| listed above.
+to |cur_type| and |cur_exp|. Such nodes have |name_type=capsule|,
+and their |type| field is one of the possibilities for |cur_type| listed above.
+Also |link<=void| in capsules that aren't part of a token list.
The |value| field of a capsule is, in most cases, the value that
corresponds to its |type|, as |cur_exp| corresponds to |cur_type|.
@@ -16200,6 +16211,7 @@ output. If it is~0, dependency lists will be abbreviated to
`\.{linearform}' unless they consist of a single term. If it is greater
than~1, complicated structures (pens, pictures, and paths) will be displayed
in full.
+@.linearform@>
@<Declare subroutines for printing expressions@>=
@t\4@>@<Declare the procedure called |print_dp|@>@;
@@ -16274,6 +16286,7 @@ var @!q:pointer; {the node following |p|}
begin q:=link(p);
if (info(q)=null) or (verbosity>0) then print_dependency(p,t)
else print("linearform");
+@.linearform@>
end;
@ The displayed name of a variable in a ring will not be a capsule unless
@@ -16377,7 +16390,7 @@ something depends on it. In the latter case, a dependent variable whose
coefficient of dependence is maximal will take its place.
The relevant algorithm is due to Ignacio~A. Zabala, who implemented it
as part of his Ph.D. thesis (Stanford University, December 1982).
-@^Zabala Salelles, Ignacio Andres@>
+@^Zabala Salelles, Ignacio Andr\'es@>
For example, suppose that variable $x$ is being recycled, and that the
only variables depending on~$x$ are $y=2x+a$ and $z=x+b$. In this case
@@ -16594,7 +16607,7 @@ procedure scan_primary;
label restart, done, done1, done2;
var @!p,@!q,@!r:pointer; {for list manipulation}
@!c:quarterword; {a primitive operation code}
-@!my_var_flag:0..max_command_code; {initial value of |my_var_flag|}
+@!my_var_flag:0..max_command_code; {initial value of |var_flag|}
@!l_delim,@!r_delim:pointer; {hash addresses of a delimiter pair}
@<Other local variables for |scan_primary|@>@;
begin my_var_flag:=var_flag; var_flag:=0;
@@ -17046,7 +17059,7 @@ numeric_type:begin new_indep(p); goto restart;
end;
independent: begin q:=single_dependency(p);
if q=dep_final then
- begin cur_type:=known; cur_exp:=0; free_node(q,value_node_size);
+ begin cur_type:=known; cur_exp:=0; free_node(q,dep_node_size);
end
else begin cur_type:=dependent; encapsulate(q);
end;
@@ -17092,7 +17105,7 @@ begin if type(q)=known then
else if type(q)=independent then
begin p:=single_dependency(q);
if p=dep_final then
- begin type(r):=known; value(r):=0; free_node(p,value_node_size);
+ begin type(r):=known; value(r):=0; free_node(p,dep_node_size);
end
else begin type(r):=dependent; new_dep(r,p);
end;
@@ -17541,9 +17554,9 @@ cur_y:=cur_exp; cur_x:=x;
end
@ At this point |right_type(q)| is usually |open|, but it may have been
-set to some other value by a previous splicing operation. We must maintain
-the value of |right_type(q)| in unusual cases such as
-`\.{..z1\{z2\}\&\{z3\}z1\{0,0\}..}'.
+set to some other value by a previous operation. We must maintain
+the value of |right_type(q)| in cases such as
+`\.{..\{curl2\}z\{0,0\}..}'.
@<Put the pre-join...@>=
begin t:=scan_direction;
@@ -18390,6 +18403,7 @@ argument). The third argument is either |plus| or |minus|.
The sum or difference of the numeric quantities will replace the second
operand. Arithmetic overflow may go undetected; users aren't supposed to
be monkeying around with really big values.
+@^overflow in arithmetic@>
@<Declare binary action...@>=
@t\4@>@<Declare the procedure called |dep_finish|@>@;
@@ -19430,7 +19444,7 @@ if cur_type=unknown_path then if type(lhs)=pair_type then
make_eq(lhs); {equate |lhs| to |(cur_type,cur_exp)|}
end;
-@ And |do_assignment| is similar to |do_expression|:
+@ And |do_assignment| is similar to |do_equation|:
@<Declare action procedures for use by |do_statement|@>=
procedure do_assignment;
@@ -19524,7 +19538,7 @@ put_get_error
@ @<For each type |t|, make an equation and |goto done| unless...@>=
boolean_type,string_type,pen_type,path_type,picture_type:
if cur_type=t+unknown_tag then
- begin nonlinear_eq(v,cur_exp,false); goto done;
+ begin nonlinear_eq(v,cur_exp,false); unstash_cur_exp(cur_exp); goto done;
end
else if cur_type=t then
@<Report redundant or inconsistent equation and |goto done|@>;
@@ -19689,7 +19703,7 @@ loop@+ begin get_x_next;
else goto done;
link(t):=get_avail; t:=link(t); info(t):=cur_sym;
end;
-done: if eq_type(x)<>tag_token then clear_symbol(x,false);
+done: if eq_type(x) mod outer_tag<>tag_token then clear_symbol(x,false);
if equiv(x)=null then new_root(x);
scan_declared_variable:=h;
end;
@@ -20073,7 +20087,7 @@ else begin print_char(""""); slow_print(cur_mod); print_char("""");
end
@ The following cases of |print_cmd_mod| might arise in connection
-with |disp_token|, although they don't correspond to any
+with |disp_token|, although they don't necessarily correspond to
primitive tokens.
@<Cases of |print_cmd_...@>=
@@ -20752,6 +20766,7 @@ since many fonts have a design size equal to one em. The other dimensions
must be less than 16 design-size units in absolute value; thus,
|header[1]| and |param[1]| are the only |fix_word| entries in the whole
\.{TFM} file whose first byte might be something besides 0 or 255.
+@^design size@>
@ Next comes the |char_info| array, which contains one |@!char_info_word|
per character. Each word in this part of the file contains six fields
@@ -20888,6 +20903,7 @@ to help position accents. For example, |slant=.25| means that when you go
up one unit, you also go .25 units to the right. The |slant| is a pure
number; it is the only |fix_word| other than the design size itself that is
not scaled by the design size.
+@^design size@>
\hang|param[2]=space| is the normal spacing between words in text.
Note that character @'40 in the font need not have anything to do with
@@ -21196,7 +21212,7 @@ We may need to cancel skips that span more than 127 lig/kern steps.
@<Process a |skip_to| command and |goto done|@>=
begin c:=get_code;
-if nl-skip_table[c]>128 then {|skip_table[c]<<nl<=undefined_label|}
+if nl-skip_table[c]>128 then
begin skip_error(skip_table[c]); skip_table[c]:=undefined_label;
end;
if skip_table[c]=undefined_label then skip_byte(nl-1):=qi(0)
@@ -21479,6 +21495,7 @@ value(zero_val):=0; info(zero_val):=0;
@ Bytes 5--8 of the header are set to the design size, unless the user has
some crazy reason for specifying them differently.
+@^design size@>
Error messages are not allowed at the time this procedure is called,
so a warning is printed instead.
@@ -21505,7 +21522,7 @@ if header_byte[5]<0 then if header_byte[6]<0 then
header_byte[7]:=(d div 16) mod 256;
header_byte[8]:=(d mod 16)*16;
end;
-max_tfm_dimen:=16*internal[design_size]-internal[design_size] div @'10000000;
+max_tfm_dimen:=16*internal[design_size]-1-internal[design_size] div @'10000000;
if max_tfm_dimen>=fraction_half then max_tfm_dimen:=fraction_half-1;
end;
@@ -21516,9 +21533,9 @@ global variable |tfm_changed| is increased by~one.
@p function dimen_out(@!x:scaled):integer;
begin if abs(x)>max_tfm_dimen then
begin incr(tfm_changed);
- if x>0 then x:=three_bytes-1@+else x:=1-three_bytes;
- end
-else x:=make_scaled(x*16,internal[design_size]);
+ if x>0 then x:=max_tfm_dimen@+else x:=-max_tfm_dimen;
+ end;
+x:=make_scaled(x*16,internal[design_size]);
dimen_out:=x;
end;
@@ -22039,7 +22056,7 @@ from one that is overridden by corresponding data in the other.
@* \[47] Shipping characters out.
The |ship_out| procedure, to be described below, is given a pointer to
-an edge structure. Its mission is to describe the the positive pixels
+an edge structure. Its mission is to describe the positive pixels
in \.{GF} form, outputting a ``character'' to |gf_file|.
Several global variables hold information about the font file as a whole:\
@@ -22244,7 +22261,7 @@ print_dd(round_unscaled(internal[day])); print_char(":");@/
t:=round_unscaled(internal[time]);
print_dd(t div 60); print_dd(t mod 60);@/
selector:=old_setting; gf_out(cur_length);
-str_start[str_ptr+1]:=pool_ptr; gf_string(0,str_ptr);
+gf_string(0,make_string); decr(str_ptr);
pool_ptr:=str_start[str_ptr]; {flush that string from memory}
gf_prev_ptr:=gf_offset+gf_ptr;
end;
@@ -22487,7 +22504,7 @@ so that the inverse relation between them is clear.
The global variable |base_ident| is a string that is printed right
after the |banner| line when \MF\ is ready to start. For \.{INIMF} this
string says simply `\.{(INIMF)}'; for other versions of \MF\ it says,
-for example, `\.{(preloaded base=plain 84.2.29)}', showing the year,
+for example, `\.{(preloaded base=plain 1984.2.29)}', showing the year,
month, and day that the base file was created. We have |base_ident=0|
before \MF's tables are loaded.
@@ -22806,8 +22823,8 @@ rarely pay off so handsomely.
On systems that allow such preloading, the standard program called \.{MF}
should be the one that has \.{plain} base preloaded, since that agrees
-with {\sl The {\logos METAFONT\/}book}. Other versions, e.g., \.{cmbase},
-should also be provided for commonly used bases.
+with {\sl The {\logos METAFONT\/}book}. Other versions, e.g., \.{CMMF},
+should also be provided for commonly used bases such as \.{cmbase}.
@:METAFONTbook}{\sl The {\logos METAFONT\/}book@>
@.cmbase@>
@.plain@>