Skip to content

Instantly share code, notes, and snippets.

@texdraft texdraft/texs.diff
Created Aug 13, 2019

Embed
What would you like to do?
diff oldtex.web tex.web
This file has been truncated, but you can view the full file.
2,4c2,3
< \def\glob{13} % this should be the section number of "<Globals...>"
< \def\gglob{20, 26} % this should be the next two sections of "<Globals...>"
< This is \TeX, a document compiler intended to produce high-quality typesetting.
---
> This is \TeX, a document compiler intended to produce typesetting of high
> quality.
9c8
< will be obtainable on a great variety of different computers.
---
> will be obtainable on a great variety of computers.
34c33
< the \TeX\ user's manual.
---
> {\sl The \TeX book}.
35a35
> @:TeXbook}{\sl The \TeX book@>
38c38
< of@@1977, when Michael@@F. Plass and Frank@@M. Liang designed and coded
---
> of~1977, when Michael~F. Plass and Frank~M. Liang designed and coded
43c43
< based on some specifications that the author had made in April of that year.
---
> based on some specifications that the author had made in May of that year.
54c54,55
< somewhat like the present ``web'' were developed by Luis Trabb@@Pardo and
---
> somewhat like the present ``web'' were developed by Luis Trabb~Pardo and
> @^Trabb Pardo, Luis Isidoro@>
56c57
< created by Ignacio@@A. Zabala in 1979 and 1980. The \TeX82 program, which
---
> created by Ignacio~A. Zabala in 1979 and 1980. The \TeX82 program, which
67c68,76
< has been substantially improved.
---
> has been substantially improved. After the appearance of ``Version 0'' in
> September 1982, this program benefited greatly from the comments of
> many other people, notably David~R. Fuchs and Howard~W. Trickey.
> A final revision in September 1989 extended the input character set to
> eight-bit codes and introduced the ability to hyphenate words from
> different languages, based on some ideas of Michael~J. Ferguson.
> @^Fuchs, David Raymond@>
> @^Trickey, Howard Wellington@>
> @^Ferguson, Michael John@>
69c78
< No doubt there still is plenty of room for enhancements, but the author
---
> No doubt there still is plenty of room for improvement, but the author
71c80
< and reliabil\-ity are to be its main virtues.
---
> and reliability are to be its main virtues.
79a89
> @^system dependencies@>
81c91,99
< @d banner=='This is TeX, Version -0.25' {printed when \TeX\ starts}
---
> If this program is changed, the resulting system should not be called
> `\TeX'; the official name `\TeX' by itself is reserved
> for software systems that are fully compatible with each other.
> A special test suite called the ``\.{TRIP} test'' is available for
> helping to determine whether a particular implementation deserves to be
> known as `\TeX' [cf.~Stanford Computer Science report CS1027,
> November 1984].
>
> @d banner=='This is TeX, Version 3.14159265' {printed when \TeX\ starts}
84d101
< \def\ph{{\mc PASCAL-H}}
87c104
< available to the author in 1982. The methods used here to work with
---
> available to the author in 1982. Constructions that apply to
89,90c106,107
< reader to see how to make an appropriate interface for other systems
< if necessary. (\ph\ is Charles Hedrick's mod\-ifi\-ca\-tion of a compiler
---
> reader see how to make an appropriate interface for other systems
> if necessary. (\ph\ is Charles Hedrick's modification of a compiler
98,99c115,120
< \PASCAL\ itself, so that most of the code can be mechanically translated
< into other high-level languages.)
---
> \PASCAL\ itself, so that most of the code can be translated mechanically
> into other high-level languages. For example, the `\&{with}' and `\\{new}'
> features are not used, nor are pointer types, set types, or enumerated
> scalar types; there are no `\&{var}' parameters, except in the case of files;
> there are no tag fields on variant records; there are no assignments
> |real:=integer|; no procedures are declared local to other procedures.)
110a132,136
> Incidentally, \PASCAL's standard |round| function can be problematical,
> because it disagrees with the IEEE floating-point standard.
> Many implementors have
> therefore chosen to substitute their own home-grown rounding procedure.
>
114,115c140,141
< For example, the portion of the program called `\X\glob:Globals in the outer
< block\X' here will be replaced by a sequence of variable declarations
---
> For example, the portion of the program called `\X\glob:Global
> variables\X' below will be replaced by a sequence of variable declarations
120c146
< sections \gglob, $\ldots$,'' also make it possible to look at the set of
---
> sections \gglob, \dots,'' also make it possible to look at the set of
126a153
> @:PASCAL H}{\ph@>
138c165
< var@?@<Globals in the outer block@>@/
---
> var @<Global variables@>@/
141,143c168,170
< var@?@<Local variables for initialization@>@/
< begin @<Initialize whatever \TeX\ might access@>@;
< end;@#
---
> var @<Local variables for initialization@>@/
> begin @<Initialize whatever \TeX\ might access@>@;
> end;@#
150c177
< comment `@!|start_here|'. If you want to skip down to the
---
> comment `|start_here|'. If you want to skip down to the
167c194
< {key control points}
---
> {key control points}
173,177c200,207
< delimited by the codewords `$|debug|\ldotsm|gubed|$', with apologies
< to people who wish to preserve the purity of English. Similarly, there
< is some conditional code delimited by `$|stat|\ldotsm|tats|$'
< that is intended only for use when statistics
< are to be kept about \TeX's memory usage.
---
> delimited by the codewords `$|debug|\ldots|gubed|$', with apologies
> to people who wish to preserve the purity of English.
>
> Similarly, there is some conditional code delimited by
> `$|stat|\ldots|tats|$' that is intended for use when statistics are to be
> kept about \TeX's memory usage. The |stat| $\ldots$ |tats| code also
> implements diagnostic information for \.{\\tracingparagraphs} and
> \.{\\tracingpages}.
180,181c210,211
< @d debug==@{ {change this to `$\\{debug}\eqv\null$' when debugging}
< @d gubed==@} {change this to `$\\{gubed}\eqv\null$' when debugging}
---
> @d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
> @d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
185,188c215,218
< @d stat==@{ {change this to `$\\{stat}\eqv\null$' when gathering
< usage statistics}
< @d tats==@} {change this to `$\\{tats}\eqv\null$' when gathering
< usage statistics}
---
> @d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering
> usage statistics}
> @d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering
> usage statistics}
193c223
< version called \.{INITEX}, which does the extra calculations need to
---
> version called \.{INITEX}, which does the extra calculations needed to
195c225
< initialize \TeX's internal tables; and (2)@@there is a shorter and faster
---
> initialize \TeX's internal tables; and (2)~there is a shorter and faster
198c228
< the codewords `$|init|\ldotsm|tini|$'.
---
> the codewords `$|init|\ldots|tini|$'.
200,201c230,231
< @d init== {change this to `$\\{init}\eqv\.{@@\{}$' in the production version}
< @d tini== {change this to `$\\{tini}\eqv\.{@@\}}$' in the production version}
---
> @d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
> @d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
207c237
< init @<Initialize table entries (done by \.{INITEX} only)@>@;@+tini
---
> @!init @<Initialize table entries (done by \.{INITEX} only)@>@;@+tini
210d239
< @^system dependencies@>
217c246,248
< @^Overflow in arithmetic@>
---
> @:PASCAL H}{\ph@>
> @^system dependencies@>
> @^overflow in arithmetic@>
221c252
< debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
---
> @!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
223c254
< @ This \TeX\ implementation conforms to the rules of the {\sl PASCAL User
---
> @ This \TeX\ implementation conforms to the rules of the {\sl Pascal User
234c265
< $$\vbox{\halign{\!#\hfil\cr
---
> $$\vbox{\halign{\ignorespaces#\hfil\cr
238c269
< |othercases| $\langle\,$code for |x≠1| and |x≠3|$\,\rangle$\cr
---
> |othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
243,248c274,279
< syntaxes like `\!|else|\unskip' or `\\{otherwise}' or `\\{otherwise}:',
< etc. The definitions of |othercases| and |endcases| should be changed to
< agree with local conventions. Note that no semicolon appears before
< |endcases| in this program, so the definition of |endcases| should include
< a semicolon if the compiler wants one. (Of course, if no default mechanism
< is available, the |case| statements of \TeX\ will have to be laboriously
---
> syntaxes like `\&{else}' or `\&{otherwise}' or `\\{otherwise}:', etc. The
> definitions of |othercases| and |endcases| should be changed to agree with
> local conventions. Note that no semicolon appears before |endcases| in
> this program, so the definition of |endcases| should include a semicolon
> if the compiler wants one. (Of course, if no default mechanism is
> available, the |case| statements of \TeX\ will have to be laboriously
250c281,282
< \PASCAL s have in fact done this, successfully but not happily!)
---
> \PASCAL s have, in fact, done this, successfully but not happily!)
> @:PASCAL H}{\ph@>
264,265c296,301
< @!mem_max=30000; {greatest index in \TeX's internal |mem| array,
< must be strictly less than |max_halfword|}
---
> @!mem_max=30000; {greatest index in \TeX's internal |mem| array;
> must be strictly less than |max_halfword|;
> must be equal to |mem_top| in \.{INITEX}, otherwise |>=mem_top|}
> @!mem_min=0; {smallest index in \TeX's internal |mem| array;
> must be |min_halfword| or more;
> must be equal to |mem_bot| in \.{INITEX}, otherwise |<=mem_bot|}
267,272c303,309
< current lines of open files; must not exceed |max_halfword|}
< @!error_line=64; {width of context lines on terminal error messages}
< @!half_error_line=32; {width of first lines of contexts in terminal
< error messages, should be between 30 and |error_line-15|}
< @!max_print_line=72; {width of longest text lines output, should be at least 60}
< @!stack_size=80; {maximum number of simultaneous input sources}
---
> current lines of open files and in control sequences between
> \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|}
> @!error_line=72; {width of context lines on terminal error messages}
> @!half_error_line=42; {width of first lines of contexts in terminal
> error messages; should be between 30 and |error_line-15|}
> @!max_print_line=79; {width of longest text lines output; should be at least 60}
> @!stack_size=200; {maximum number of simultaneous input sources}
274,278c311,315
< can be going on simultaneously}
< @!font_max=75; {maximum internal font number, must not exceed |max_quarterword|}
< @!bad_font_code=300; {user font codes must be less than this}
< @!font_mem_size=15000; {number of words of |font_info| for all fonts}
< @!param_size=30; {maximum number of simultaneous macro parameters}
---
> can be going on simultaneously}
> @!font_max=75; {maximum internal font number; must not exceed |max_quarterword|
> and must be at most |font_base+256|}
> @!font_mem_size=20000; {number of words of |font_info| for all fonts}
> @!param_size=60; {maximum number of simultaneous macro parameters}
282,292c319,330
< available for the user's control sequences and font names,
< after \TeX's own error messages are stored}
< @!pool_size=30000; {maximum number of characters in strings, including all
< error messages and help texts, and the names of all fonts and
< control sequences; must be at least 22000 more than |string_vacancies|}
< @!align_size=4; {maximum number of simultaneous alignments}
< @!save_size=300; {space for saving values outside of current group, must be
< at most |max_halfword|}
< @!trie_size=7000; {space for hyphenation patterns, should be larger for
< \.{INITEX} than it is in production versions of \TeX}
< @!dvi_buf_size=800; {size of the output buffer, must be a multiple of 8}
---
> available for the user's control sequences and font names,
> after \TeX's own error messages are stored}
> @!pool_size=32000; {maximum number of characters in strings, including all
> error messages and help texts, and the names of all fonts and
> control sequences; must exceed |string_vacancies| by the total
> length of \TeX's own strings, which is currently about 23000}
> @!save_size=600; {space for saving values outside of current group; must be
> at most |max_halfword|}
> @!trie_size=8000; {space for hyphenation patterns; should be larger for
> \.{INITEX} than it is in production versions of \TeX}
> @!trie_op_size=500; {space for ``opcodes'' in the hyphenation patterns}
> @!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8}
294,296c332,334
< @!pool_name='<TeX.sources>TEX.POOL ';
< {string of length |file_name_size|, tells where string pool appears}
< @^system dependencies@>
---
> @!pool_name='TeXformats:TEX.POOL ';
> {string of length |file_name_size|; tells where the string pool appears}
> @.TeXformats@>
309,314c347,353
< @d mem_base=0 {smallest index in the |mem| array, must not be less
< than |min_halfword|}
< @d hi_mem_base=12000 {smallest index in the single-word area of |mem|,
< must be substantially larger than |mem_base| and smaller than |mem_max|}
< @d font_base=0 {smallest internal font number, must not be less
< than |min_quarterword|}
---
> @d mem_bot=0 {smallest index in the |mem| array dumped by \.{INITEX};
> must not be less than |mem_min|}
> @d mem_top==30000 {largest index in the |mem| array dumped by \.{INITEX};
> must be substantially larger than |mem_bot|
> and not greater than |mem_max|}
> @d font_base=0 {smallest internal font number; must not be less
> than |min_quarterword|}
316,317c355,356
< about |(mem_max-hi_mem_base)/6|, but 2100 is already quite generous}
< @d hash_prime=1777 {a prime number equal to about 85\%\ of |hash_size|}
---
> about |(mem_max-mem_min)/10|}
> @d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
330,331c369,370
< @ Later on we will say `\!|if mem_max≥max_halfword then bad←10|', or
< something similar. (We can't do that until |max_halfword| has been defined.)
---
> @ Later on we will say `\ignorespaces|if mem_max>=max_halfword then bad:=14|',
> or something similar. (We can't do that until |max_halfword| has been defined.)
334,339c373,380
< bad←0;
< if (half_error_line<30)∨(half_error_line>error_line-15) then bad←1;
< if max_print_line<60 then bad←2;
< if dvi_buf_size mod 8≠0 then bad←3;
< if (hi_mem_base<mem_base+100)∨(hi_mem_base+100>mem_max) then bad←4;
< if hash_prime>hash_size then bad←5;
---
> bad:=0;
> if (half_error_line<30)or(half_error_line>error_line-15) then bad:=1;
> if max_print_line<60 then bad:=2;
> if dvi_buf_size mod 8<>0 then bad:=3;
> if mem_bot+1100>mem_top then bad:=4;
> if hash_prime>hash_size then bad:=5;
> if max_in_open>=128 then bad:=6;
> if mem_top<256+11 then bad:=7; {we will want |null_list>255|}
342,354c383,394
< occasional |goto| statements will be meaningful. We insert
< the label `|exit|:' just before the `\!|end|\unskip' of a procedure in
< which we have used the `|return|' statement defined below;
< the label `|restart|' is occasionally used at the very beginning of a
< procedure; and the label `|reswitch|' is occasionally used just prior to
< a |case| statement in which some cases change the conditions and we wish to
< branch to the newly applicable case.
< Loops that are set up with the |loop| construction defined below are
< commonly exited by going to `|done|' or to `|found|' or to `|not_found|',
< and they are sometimes repeated by going to `|continue|'.
< If two or more parts of a subroutine start differently but end up the same,
< the shared code may be gathered together at `|common_ending|'.
<
---
> occasional |goto| statements will be meaningful. We insert the label
> `|exit|' just before the `\ignorespaces|end|\unskip' of a procedure in
> which we have used the `|return|' statement defined below; the label
> `|restart|' is occasionally used at the very beginning of a procedure; and
> the label `|reswitch|' is occasionally used just prior to a |case|
> statement in which some cases change the conditions and we wish to branch
> to the newly applicable case. Loops that are set up with the |loop|
> construction defined below are commonly exited by going to `|done|' or to
> `|found|' or to `|not_found|', and they are sometimes repeated by going to
> `|continue|'. If two or more parts of a subroutine start differently but
> end up the same, the shared code may be gathered together at
> `|common_ending|'.
378,379c418,420
< @d incr(#) == #←#+1 {increase a variable by unity}
< @d decr(#) == #←#-1 {decrease a variable by unity}
---
> @d incr(#) == #:=#+1 {increase a variable by unity}
> @d decr(#) == #:=#-1 {decrease a variable by unity}
> @d negate(#) == #:=-# {change the sign of a variable}
381c422,423
< @f loop == xclause {\.{WEB}'s |xclause| acts like `\!|while true do|\unskip'}
---
> @f loop == xclause
> {\.{WEB}'s |xclause| acts like `\ignorespaces|while true do|\unskip'}
384a427,428
> @d empty=0 {symbolic name for a null constant}
>
386,388c430,432
< In order to make \TeX\ readily portable between a wide variety of
< computers, all of its input text is converted to an internal seven-bit
< code that is essentially standard ascii, the ``American Standard Code for
---
> In order to make \TeX\ readily portable to a wide variety of
> computers, all of its input text is converted to an internal eight-bit
> code that includes standard ASCII, the ``American Standard Code for
390c434
< character is read in. Conversely, characters are converted from ascii to
---
> character is read in. Conversely, characters are converted from ASCII to
392c436
< text file.
---
> text file.
396c440
< character `\.A' has ascii code $65=@'101$, and when \TeX\ typesets
---
> character `\.A' has ASCII code $65=@'101$, and when \TeX\ typesets
400c444
< \TeX's device-independent files is responsible for converting from ascii to
---
> \TeX's device-independent files is responsible for converting from ASCII to
402c446
< @^ascii code@>
---
> @^ASCII code@>
404c448
< \TeX's internal code is relevant also with respect to constants
---
> \TeX's internal code also defines the value of constants
406c450
< \.{\\chcode}, \.{\\mathcode}, \.{\\uccode}, \.{\\lccode}, and \.{\\delcode}
---
> \.{\\catcode}, \.{\\mathcode}, \.{\\uccode}, \.{\\lccode}, and \.{\\delcode}
409,410c453,454
< @ Characters of text that have been converted to \TeX's internal form
< are said to be of type |ascii_code|, which is a subrange of the integers.
---
> @ Characters of text that have been converted to \TeX's internal form
> are said to be of type |ASCII_code|, which is a subrange of the integers.
413c457
< @!ascii_code=0..127; {seven-bit numbers}
---
> @!ASCII_code=0..255; {eight-bit numbers}
416,418c460,462
< character sets were common, so it did not make provision for lower case
< letters. Nowadays, of course, we need to deal with both upper and lower case
< alphabets in a convenient way, especially in a program for typesetting;
---
> character sets were common, so it did not make provision for lowercase
> letters. Nowadays, of course, we need to deal with both capital and small
> letters in a convenient way, especially in a program for typesetting;
423c467
< with ascii codes @'40 through @'176; all of these characters are now
---
> with ASCII codes @'40 through @'176; all of these characters are now
435c479
< from |ascii_code| when they are input and output. We shall also assume
---
> from |ASCII_code| when they are input and output. We shall also assume
437c481
< |chr(last_text_char)|, in\-clu\-sive. The following definitions should be
---
> |chr(last_text_char)|, inclusive. The following definitions should be
443c487
< @d last_text_char=127 {ordinal number of the largest element of |text_char|}
---
> @d last_text_char=255 {ordinal number of the largest element of |text_char|}
446c490
< i:0..last_text_char;
---
> @!i:integer;
448c492
< @ The \TeX\ processor converts between ascii code and
---
> @ The \TeX\ processor converts between ASCII code and
452,462c496,509
< @<Globals...@>=
< @!xord: array [text_char] of ascii_code;
< {specifies conversion of input characters}
< @!xchr: array [ascii_code] of text_char;
< {specifies conversion of output characters}
<
< @ Since we are assuming that our \PASCAL\ system is able to read and write the
< visible characters of standard ascii (although not necessarily using the
< ascii codes to represent them), the following assignment statements initialize
< most of the |xchr| array properly, without needing any system-dependent
< changes.
---
> @<Glob...@>=
> @!xord: array [text_char] of ASCII_code;
> {specifies conversion of input characters}
> @!xchr: array [ASCII_code] of text_char;
> {specifies conversion of output characters}
>
> @ Since we are assuming that our \PASCAL\ system is able to read and
> write the visible characters of standard ASCII (although not
> necessarily using the ASCII codes to represent them), the following
> assignment statements initialize the standard part of the |xchr| array
> properly, without needing any system-dependent changes. On the other
> hand, it is possible to implement \TeX\ with less complete character
> sets, and in such cases it will be necessary to change something here.
> @^system dependencies@>
465,561c512,606
< xchr[@'40]←' ';
< xchr[@'41]←'!';
< xchr[@'42]←'"';
< xchr[@'43]←'#';
< xchr[@'44]←'$';
< xchr[@'45]←'%';
< xchr[@'46]←'&';
< xchr[@'47]←'''';@/
< xchr[@'50]←'(';
< xchr[@'51]←')';
< xchr[@'52]←'*';
< xchr[@'53]←'+';
< xchr[@'54]←',';
< xchr[@'55]←'-';
< xchr[@'56]←'.';
< xchr[@'57]←'/';@/
< xchr[@'60]←'0';
< xchr[@'61]←'1';
< xchr[@'62]←'2';
< xchr[@'63]←'3';
< xchr[@'64]←'4';
< xchr[@'65]←'5';
< xchr[@'66]←'6';
< xchr[@'67]←'7';@/
< xchr[@'70]←'8';
< xchr[@'71]←'9';
< xchr[@'72]←':';
< xchr[@'73]←';';
< xchr[@'74]←'<';
< xchr[@'75]←'=';
< xchr[@'76]←'>';
< xchr[@'77]←'?';@/
< xchr[@'100]←'@@';
< xchr[@'101]←'A';
< xchr[@'102]←'B';
< xchr[@'103]←'C';
< xchr[@'104]←'D';
< xchr[@'105]←'E';
< xchr[@'106]←'F';
< xchr[@'107]←'G';@/
< xchr[@'110]←'H';
< xchr[@'111]←'I';
< xchr[@'112]←'J';
< xchr[@'113]←'K';
< xchr[@'114]←'L';
< xchr[@'115]←'M';
< xchr[@'116]←'N';
< xchr[@'117]←'O';@/
< xchr[@'120]←'P';
< xchr[@'121]←'Q';
< xchr[@'122]←'R';
< xchr[@'123]←'S';
< xchr[@'124]←'T';
< xchr[@'125]←'U';
< xchr[@'126]←'V';
< xchr[@'127]←'W';@/
< xchr[@'130]←'X';
< xchr[@'131]←'Y';
< xchr[@'132]←'Z';
< xchr[@'133]←'[';
< xchr[@'134]←'\';
< xchr[@'135]←']';
< xchr[@'136]←'^';
< xchr[@'137]←'_';@/
< xchr[@'140]←'`';
< xchr[@'141]←'a';
< xchr[@'142]←'b';
< xchr[@'143]←'c';
< xchr[@'144]←'d';
< xchr[@'145]←'e';
< xchr[@'146]←'f';
< xchr[@'147]←'g';@/
< xchr[@'150]←'h';
< xchr[@'151]←'i';
< xchr[@'152]←'j';
< xchr[@'153]←'k';
< xchr[@'154]←'l';
< xchr[@'155]←'m';
< xchr[@'156]←'n';
< xchr[@'157]←'o';@/
< xchr[@'160]←'p';
< xchr[@'161]←'q';
< xchr[@'162]←'r';
< xchr[@'163]←'s';
< xchr[@'164]←'t';
< xchr[@'165]←'u';
< xchr[@'166]←'v';
< xchr[@'167]←'w';@/
< xchr[@'170]←'x';
< xchr[@'171]←'y';
< xchr[@'172]←'z';
< xchr[@'173]←'{';
< xchr[@'174]←'|';
< xchr[@'175]←'}';
< xchr[@'176]←'~';@/
< xchr[0]←' '; xchr[@'177]←' ';
< {ascii codes 0 and |@'177| do not appear in text}
---
> xchr[@'40]:=' ';
> xchr[@'41]:='!';
> xchr[@'42]:='"';
> xchr[@'43]:='#';
> xchr[@'44]:='$';
> xchr[@'45]:='%';
> xchr[@'46]:='&';
> xchr[@'47]:='''';@/
> xchr[@'50]:='(';
> xchr[@'51]:=')';
> xchr[@'52]:='*';
> xchr[@'53]:='+';
> xchr[@'54]:=',';
> xchr[@'55]:='-';
> xchr[@'56]:='.';
> xchr[@'57]:='/';@/
> xchr[@'60]:='0';
> xchr[@'61]:='1';
> xchr[@'62]:='2';
> xchr[@'63]:='3';
> xchr[@'64]:='4';
> xchr[@'65]:='5';
> xchr[@'66]:='6';
> xchr[@'67]:='7';@/
> xchr[@'70]:='8';
> xchr[@'71]:='9';
> xchr[@'72]:=':';
> xchr[@'73]:=';';
> xchr[@'74]:='<';
> xchr[@'75]:='=';
> xchr[@'76]:='>';
> xchr[@'77]:='?';@/
> xchr[@'100]:='@@';
> xchr[@'101]:='A';
> xchr[@'102]:='B';
> xchr[@'103]:='C';
> xchr[@'104]:='D';
> xchr[@'105]:='E';
> xchr[@'106]:='F';
> xchr[@'107]:='G';@/
> xchr[@'110]:='H';
> xchr[@'111]:='I';
> xchr[@'112]:='J';
> xchr[@'113]:='K';
> xchr[@'114]:='L';
> xchr[@'115]:='M';
> xchr[@'116]:='N';
> xchr[@'117]:='O';@/
> xchr[@'120]:='P';
> xchr[@'121]:='Q';
> xchr[@'122]:='R';
> xchr[@'123]:='S';
> xchr[@'124]:='T';
> xchr[@'125]:='U';
> xchr[@'126]:='V';
> xchr[@'127]:='W';@/
> xchr[@'130]:='X';
> xchr[@'131]:='Y';
> xchr[@'132]:='Z';
> xchr[@'133]:='[';
> xchr[@'134]:='\';
> xchr[@'135]:=']';
> xchr[@'136]:='^';
> xchr[@'137]:='_';@/
> xchr[@'140]:='`';
> xchr[@'141]:='a';
> xchr[@'142]:='b';
> xchr[@'143]:='c';
> xchr[@'144]:='d';
> xchr[@'145]:='e';
> xchr[@'146]:='f';
> xchr[@'147]:='g';@/
> xchr[@'150]:='h';
> xchr[@'151]:='i';
> xchr[@'152]:='j';
> xchr[@'153]:='k';
> xchr[@'154]:='l';
> xchr[@'155]:='m';
> xchr[@'156]:='n';
> xchr[@'157]:='o';@/
> xchr[@'160]:='p';
> xchr[@'161]:='q';
> xchr[@'162]:='r';
> xchr[@'163]:='s';
> xchr[@'164]:='t';
> xchr[@'165]:='u';
> xchr[@'166]:='v';
> xchr[@'167]:='w';@/
> xchr[@'170]:='x';
> xchr[@'171]:='y';
> xchr[@'172]:='z';
> xchr[@'173]:='{';
> xchr[@'174]:='|';
> xchr[@'175]:='}';
> xchr[@'176]:='~';@/
563c608
< @ Some of the ascii codes without visible characters have been given symbolic
---
> @ Some of the ASCII codes without visible characters have been given symbolic
566,568c611,613
< @d null_code=@'0 {ascii code that might disappear}
< @d carriage_return=@'15 {ascii code used at end of line}
< @d invalid_code=@'177 {ascii code that should not appear}
---
> @d null_code=@'0 {ASCII code that might disappear}
> @d carriage_return=@'15 {ASCII code used at end of line}
> @d invalid_code=@'177 {ASCII code that many systems prohibit in text files}
570c615
< @ The ascii code is ``standard'' only to a certain extent, since many
---
> @ The ASCII code is ``standard'' only to a certain extent, since many
572c617
< to more than 94 printing characters. Appendix@@C of the \TeX\ manual
---
> to more than 94 printing characters. Appendix~C of {\sl The \TeX book\/}
574a620
> @:TeXbook}{\sl The \TeX book@>
577c623
< on a garden-variety \PASCAL\ for which only standard ascii
---
> on a garden-variety \PASCAL\ for which only standard ASCII
579c625
< what codes are specified in |xchr[1..@'37]|, but the safest policy is to
---
> what codes are specified in |xchr[0..@'37]|, but the safest policy is to
584,588c630
< like `\.\NE' instead of `\.{\\ne}'. At MIT, for example, it would be more
< appropriate to substitute the code
< $$\hbox{|for i←1 to @'37 do xchr[i]←chr(i);|}$$
< \TeX's character set is essentially the same as MIT's, even with respect to
< characters less than@@@'40. People with extended character sets can
---
> like `\.^^Z' instead of `\.{\\ne}'. People with extended character sets can
590,596c632,638
< characters the users of \TeX\ are allowed to have in their input files,
< provided that unsuitable characters do not correspond to the special
< codes like |carriage_return| that are listed above. It is best
< to make the codes correspond to the intended interpretations as shown
< in Appendix@@C whenever possible; but this is not necessary. For example,
< in countries with an alphabet of more than 26 letters, it is usually best
< to map the additional letters into codes less than@@@'40.
---
> characters the users of \TeX\ are allowed to have in their input files.
> It is best to make the codes correspond to the intended interpretations as
> shown in Appendix~C whenever possible; but this is not necessary. For
> example, in countries with an alphabet of more than 26 letters, it is
> usually best to map the additional letters into codes less than~@'40.
> To get the most ``permissive'' character set, change |' '| on the
> right of these assignment statements to |chr(i)|.
601c643,644
< for i←1 to @'37 do xchr[i]←' ';
---
> for i:=0 to @'37 do xchr[i]:=' ';
> for i:=@'177 to @'377 do xchr[i]:=' ';
606c649
< |j| or more; hence, standard ascii code numbers will be used instead of
---
> |j| or more; hence, standard ASCII code numbers will be used instead of
610,611c653,656
< for i←first_text_char to last_text_char do xord[chr(i)]←invalid_code;
< for i←1 to @'176 do xord[xchr[i]]←i;
---
> for i:=first_text_char to last_text_char do xord[chr(i)]:=invalid_code;
> for i:=@'200 to @'377 do xord[xchr[i]]:=i;
> for i:=0 to @'176 do xord[xchr[i]]:=i;
>
616c661
< that input and output are not a part of ``real'' programming. Well, it is true
---
> that input and output are not part of ``real'' programming. Well, it is true
621,622c666,667
< two choices: whether to attack I/O now and get it over with, or to postpone
< it until near the end. Neither prospect is very attractive, so let's
---
> two choices, either to attack I/O now and get it over with, or to postpone
> I/O until near the end. Neither prospect is very attractive, so let's
625,627c670,672
< The basic operations we need to do are (1)@@inputting and outputting of
< text, to or from a file or the user's terminal; (2)@@inputting and
< outputting of eight-bit bytes, to or from a file; (3)@@instructing the
---
> The basic operations we need to do are (1)~inputting and outputting of
> text, to or from a file or the user's terminal; (2)~inputting and
> outputting of eight-bit bytes, to or from a file; (3)~instructing the
629c674
< output from a specified file; (4)@@testing whether the end of an input
---
> output from a specified file; (4)~testing whether the end of an input
632c677
< Note that \TeX\ needs to deal with only two kinds of files.
---
> \TeX\ needs to deal with two kinds of files.
641,644c686,689
< \TeX\ actually makes use also of a third kind of file, called a |word_file|,
< when dumping and reloading format information for its own initialization.
< We shall define a word file later; but it will be possible for us to
< do a few simple things with them in this section before they are defined.
---
> The program actually makes use also of a third kind of file, called a
> |word_file|, when dumping and reloading base information for its own
> initialization. We shall define a word file later; but it will be possible
> for us to specify simple operations on word files before they are defined.
664,667c709,712
< @!name_of_file:packed array[1..file_name_size] of char;
< {on some systems this may be a \&{record} variable}
< @!name_length:0..file_name_size; {this many characters are actually
< relevant in |name_of_file| (the rest are blank)}
---
> @!name_of_file:packed array[1..file_name_size] of char;@;@/
> {on some systems this may be a \&{record} variable}
> @!name_length:0..file_name_size;@/{this many characters are actually
> relevant in |name_of_file| (the rest are blank)}
669,670c714,715
< @ The \ph\ compiler with which the present version of \TeX\ was pre\-pared has
< extended the rules of \PASCAL\ in a very convenient way. To open file@@|f|,
---
> @ The \ph\ compiler with which the present version of \TeX\ was prepared has
> extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
672,677c717,722
< $$\vbox{\halign{#\hfil\qquadⓧ#\hfil\cr
< |reset(f,@t\\{name}@>,'/O')|ⓧfor input;\cr
< |rewrite(f,@t\\{name}@>,'/O')|ⓧfor output.\cr}}$$
< The `\\{name}' parameter, which is of type `\!|packed
< array[@t\<\\{any}>@>] of text_char|', stands for the name of
< the external file that is being opened for input or output.
---
> $$\vbox{\halign{#\hfil\qquad&#\hfil\cr
> |reset(f,@t\\{name}@>,'/O')|&for input;\cr
> |rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
> The `\\{name}' parameter, which is of type `{\bf packed array
> $[\langle\\{any}\rangle]$ of \\{char}}', stands for the name of
> the external file that is being opened for input or output.
683,685c728,730
< (e.g., it might already be in use), we will have |eof(f)=true| after an
< unsuccessful |reset|, and |eof(f)=false| after an unsuccessful |rewrite|.
< This allows \TeX\ to undertake appropriate corrective action.
---
> (e.g., someone may already be trying to write the same file), we will have
> |@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows
> \TeX\ to undertake appropriate corrective action.
686a732
> @^system dependencies@>
688,690c734,735
< We can now implement the file-opening procedures in the following simple way,
< where the functions return |false| if no file identified by |name_of_file|
< could be opened:
---
> \TeX's file-opening procedures return |false| if no file identified by
> |name_of_file| could be opened.
691a737,738
> @d reset_OK(#)==erstat(#)=0
> @d rewrite_OK(#)==erstat(#)=0
694,695c741,742
< {open a text file for input}
< begin reset(f,name_of_file,'/O'); a_open_in←not eof(f);
---
> {open a text file for input}
> begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f);
699,700c746,747
< {open a text file for output}
< begin rewrite(f,name_of_file,'/O'); a_open_out←eof(f);
---
> {open a text file for output}
> begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f);
704,705c751,752
< {open a binary file for input}
< begin reset(f,name_of_file,'/O'); b_open_in←not eof(f);
---
> {open a binary file for input}
> begin reset(f,name_of_file,'/O'); b_open_in:=reset_OK(f);
709,710c756,757
< {open a binary file for output}
< begin rewrite(f,name_of_file,'/O'); b_open_out←eof(f);
---
> {open a binary file for output}
> begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f);
714,715c761,762
< {open a word file for input}
< begin reset(f,name_of_file,'/O'); w_open_in←not eof(f);
---
> {open a word file for input}
> begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f);
719,720c766,767
< {open a word file for output}
< begin rewrite(f,name_of_file,'/O'); w_open_out←eof(f);
---
> {open a word file for output}
> begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f);
723a771
> @:PASCAL H}{\ph@>
729a778,780
> These procedures should not generate error messages if a file is
> being closed before it has been successfully opened.
>
744c795
< binary@@I/O. Text output is also easy to do with standard \PASCAL\ routines.
---
> binary~I/O. Text output is also easy to do with standard \PASCAL\ routines.
746,747c797,798
< of the necessary translation to |ascii_code| values, and because
< \TeX's conventions should be efficient and they should
---
> of the necessary translation to |ASCII_code| values.
> \TeX's conventions should be efficient, and they should
753c804
< now, it suffices for us to know that |buffer| is an array of |ascii_code|
---
> now, it suffices for us to know that |buffer| is an array of |ASCII_code|
758c809
< @!buffer:array[0..buf_size] of ascii_code; {lines of characters being read}
---
> @!buffer:array[0..buf_size] of ASCII_code; {lines of characters being read}
764,769c815,822
< field into available positions of the buffer array and returns the value |true|,
< unless the file has already been entirely read, in which case it returns
< |false| (and does nothing else). The |ascii_code| numbers that represent
< the next line of the file are input into |buffer[first]|, |buffer[first+1]|,
< $\ldotss$, |buffer[last-1]|; and the global variable |last| is set equal
< to |first| plus the length of the line.
---
> file into available positions of the buffer array and returns the value
> |true|, unless the file has already been entirely read, in which case it
> returns |false| and sets |last:=first|. In general, the |ASCII_code|
> numbers that represent the next line of the file are input into
> |buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the
> global variable |last| is set equal to |first| plus the length of the
> line. Trailing blanks are removed from the line; thus, either |last=first|
> (in which case the line was entirely blank) or |buffer[last-1]<>" "|.
772c825
< would make |last≥buf_size|; this is done so that other parts of \TeX\
---
> would make |last>=buf_size|; this is done so that other parts of \TeX\
775,776c828,829
< |first<buf_size| will always hold, so there is always room for an ``empty''
< line.
---
> |first<buf_size| will always hold, so that there is always room for an
> ``empty'' line.
782,786c835,844
< This procedure does a |get| before looking at the first character of the
< line, and it does not do a |get| when it reaches the end of the line.
< Therefore it can be used to acquire input from the user's terminal as well
< as from ordinary text files. Other parts of \TeX\ take care of inputting
< the first line of a file, so that the first character is not lost.
---
> If the |bypass_eoln| parameter is |true|, |input_ln| will do a |get|
> before looking at the first character of the line; this skips over
> an |eoln| that was in |f^|. The procedure does not do a |get| when it
> reaches the end of the line; therefore it can be used to acquire input
> from the user's terminal as well as from ordinary text files.
>
> Standard \PASCAL\ says that a file should have |eoln| immediately
> before |eof|, but \TeX\ needs only a weaker restriction: If |eof|
> occurs in the middle of a line, the system function |eoln| should return
> a |true| result (even though |f^| will be undefined).
796,810c854,872
< @p function input_ln(var f:alpha_file):boolean; {inputs the next line
< or returns |false|}
< begin get(f); {input the first character of the line into |f^|}
< if eof(f) then input_ln←false
< else begin last←first; {cf.\ Matthew 19:30}
< while not eoln(f) do
< begin if last≥max_buf_stack then
< begin max_buf_stack←last+1;
< if max_buf_stack=buf_size then
< overflow("buffer size",buf_size);
< end;
< buffer[last]←xord[f^]; get(f); incr(last);
< end;
< input_ln←true;
< end;
---
> @p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean;
> {inputs the next line or returns |false|}
> var last_nonblank:0..buf_size; {|last| with trailing blanks removed}
> begin if bypass_eoln then if not eof(f) then get(f);
> {input the first character of the line into |f^|}
> last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
> if eof(f) then input_ln:=false
> else begin last_nonblank:=first;
> while not eoln(f) do
> begin if last>=max_buf_stack then
> begin max_buf_stack:=last+1;
> if max_buf_stack=buf_size then
> @<Report overflow of the input buffer, and abort@>;
> end;
> buffer[last]:=xord[f^]; get(f); incr(last);
> if buffer[last-1]<>" " then last_nonblank:=last;
> end;
> last:=last_nonblank; input_ln:=true;
> end;
823c885,887
< @ Here is how to open the terminal files in \ph:
---
> @ Here is how to open the terminal files
> in \ph. The `\.{/I}' switch suppresses the first |get|.
> @:PASCAL H}{\ph@>
826c890
< @d t_open_in==reset(term_in,'TTY:','/O') {open the terminal for text input}
---
> @d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
830c894,895
< happens on the user's terminal, and two procedures are used for this
---
> happens on the user's terminal, and three system-dependent
> procedures are used for this
834c899
< The other, |clear_terminal|, is called when we wish to cancel any
---
> The second, |clear_terminal|, is called when we wish to cancel any
836,837c901,905
< issue an unexpected error message). The following macros show how these
< two operations can be specified in \ph:
---
> 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@>
841a910
> @d wake_up_terminal == do_nothing {cancel the user's cancellation of output}
844,845c913,914
< the user's terminal. This line is special because it is read before we
< have opened the error transcript file; there is sort of a ``chicken and
---
> the user's terminal. This line is different because it is read before we
> have opened the transcript file; there is sort of a ``chicken and
848c917
< the transcript file will be named `\.{paper.err}'; but if no \.{\\input}
---
> the transcript file will be named `\.{paper.log}'; but if no \.{\\input}
850c919
< file will acquire its default name `\.{texput.err}'. (The transcript file
---
> file will acquire its default name `\.{texput.log}'. (The transcript file
852a922
> @.texput@>
862,863c932,951
< @ Different systems have different ways to get started, but regardless of
< what conventions are adopted the routine that initializes the terminal
---
> The first line is special also because it may be read before \TeX\ has
> input a format 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|\unskip, the
> @^system dependencies@>
> statement `|goto final_end|' should be replaced by something that
> quietly terminates the program.)
>
> @<Report overflow of the input buffer, and abort@>=
> if format_ident=0 then
> begin write_ln(term_out,'Buffer size exceeded!'); goto final_end;
> @.Buffer size exceeded@>
> end
> else begin cur_input.loc_field:=first; cur_input.limit_field:=last-1;
> overflow("buffer size",buf_size);
> @:TeX capacity exceeded buffer size}{\quad buffer size@>
> end
>
> @ Different systems have different ways to get started. But regardless of
> what conventions are adopted, the routine that initializes the terminal
867,868c955,956
< terminal. (The file |term_out| will already be open for output to the
< terminal.)
---
> terminal. (The file |term_out| will already be open for output to the
> terminal.)
871,873c959,961
< considered the first line of terminal input. Otherwise the
< user should be prompted with `\.{**}', and the first line of input
< should be whatever is typed in response.
---
> considered the first line of terminal input. Otherwise the
> user should be prompted with `\.{**}', and the first line of input
> should be whatever is typed in response.
876,877c964,965
< command line, should appear in locations 0 to |last-1| of the
< |buffer| array.
---
> command line, should appear in locations |first| to |last-1| of the
> |buffer| array.
880,881c968,969
< character that \TeX\ reads next is in |buffer[loc]|. This
< character should not be blank, and we should have |loc<last|.
---
> character to be read next by \TeX\ is in |buffer[loc]|. This
> character should not be blank, and we should have |loc<last|.
884,886c972,974
< before a non-blank line comes in. The prompt is `\.\#' instead of the
< later `\.*' because the meaning is slightly different: `\\input' need
< not be typed immediately after `\.\#'.)
---
> before a non-blank line comes in. The prompt is `\.{**}' instead of the
> later `\.*' because the meaning is slightly different: `\.{\\input}' need
> not be typed immediately after~`\.{**}'.)
891c979
< with\-out retrieving a possible command line.
---
> without retrieving a possible command line.
899,913c987,1002
< loop@+begin write(term_out,'**'); update_terminal;
< if not input_ln(term_in) then {this shouldn't happen}
< begin write_ln(term_out);
< write(term_out,'! End of file on the terminal... why?');
< @.End of file on the terminal...@>
< init_terminal←false; return;
< end;
< loc←first;
< while (loc<last)∧(buffer[loc]=" ") do incr(loc);
< if loc<last then
< begin init_terminal←true;
< return; {return unless the line was all blank}
< end;
< write_ln(term_out,'Please type the name of your input file.');
< end;
---
> loop@+begin wake_up_terminal; write(term_out,'**'); update_terminal;
> @.**@>
> if not input_ln(term_in,true) then {this shouldn't happen}
> begin write_ln(term_out);
> write(term_out,'! End of file on the terminal... why?');
> @.End of file on the terminal@>
> init_terminal:=false; return;
> end;
> loc:=first;
> while (loc<last)and(buffer[loc]=" ") do incr(loc);
> if loc<last then
> begin init_terminal:=true;
> return; {return unless the line was all blank}
> end;
> write_ln(term_out,'Please type the name of your input file.');
> end;
914a1004
>
917c1007
< of seven-bit characters. Since \PASCAL\ does not have a well-developed string
---
> of eight-bit characters. Since \PASCAL\ does not have a well-developed string
922c1012
< The array |str_pool| contains all of the (seven-bit) ascii codes in all
---
> The array |str_pool| contains all of the (eight-bit) ASCII codes in all
925,926c1015,1016
< string number |s| comprises the characters |str_pool[j]| for
< |str_start[s]≤j<str_start[s+1]|. Additional integer variables
---
> string number |s| comprises the characters |str_pool[j]| for
> |str_start[s]<=j<str_start[s+1]|. Additional integer variables
932,933c1022,1023
< String numbers 0 to 127 are reserved for strings that correspond to single
< ascii characters. This is in accordance with the conventions of \.{WEB},
---
> String numbers 0 to 255 are reserved for strings that correspond to single
> ASCII characters. This is in accordance with the conventions of \.{WEB},
935c1025
< which converts single-character strings into the ascii code number of the
---
> which converts single-character strings into the ASCII code number of the
939,941c1029,1031
< ascii code for a period, while \.{WEB} will convert a string like \.{"hello"}
< into some integer greater than@@127. String number 46 will presumably be the
< single character `\..'; but some ascii codes have no standard visible
---
> ASCII code for a period, while \.{WEB} will convert a string like \.{"hello"}
> into some integer greater than~255. String number 46 will presumably be the
> single character `\..'; but some ASCII codes have no standard visible
943,944c1033,1044
< ascii character, so the first 128 strings are used to specify exactly what
< should be printed for each of the 128 possibilities.
---
> ASCII character, so the first 256 strings are used to specify exactly what
> should be printed for each of the 256 possibilities.
>
> Elements of the |str_pool| array must be ASCII codes that can actually
> be printed; i.e., they must have an |xchr| equivalent in the local
> character set. (This restriction applies only to preloaded strings,
> not to those generated dynamically by the user.)
>
> Some \PASCAL\ compilers won't pack integers into a single byte unless the
> integers lie in the range |-128..127|. To accommodate such systems
> we access the string pool only via macros that can easily be redefined.
> @^system dependencies@>
946,948c1046,1047
< Elements of the |str_pool| array must be ascii codes that can actually be
< printed; i.e., they must have an |xchr| equivalent in the local
< character set.
---
> @d si(#) == # {convert from |ASCII_code| to |packed_ASCII_code|}
> @d so(#) == # {convert from |packed_ASCII_code| to |ASCII_code|}
952a1052
> @!packed_ASCII_code = 0..255; {elements of |str_pool| array}
954,955c1054,1055
< @ @<Globals...@>=
< @!str_pool:packed array[pool_pointer] of ascii_code; {the characters}
---
> @ @<Glob...@>=
> @!str_pool:packed array[pool_pointer] of packed_ASCII_code; {the characters}
958c1058,1060
< @!str_ptr : str_number; {start of the current string being created}
---
> @!str_ptr : str_number; {number of the current string being created}
> @!init_pool_ptr : pool_pointer; {the starting value of |pool_ptr|}
> @!init_str_ptr : str_number; {the starting value of |str_ptr|}
961c1063
< macros instead of using \PASCAL\ procedures, because many of the
---
> macros instead of \PASCAL\ procedures, because many of the
968c1070
< in string number \#}
---
> in string number \#}
975c1077
< The macro called |append_char|, defined here, does not check to see if the
---
> The |append_char| macro, defined here, does not check to see if the
984,985c1086,1087
< @d append_char(#) == {put |ascii_code| \#\ at the end of |str_pool|}
< begin str_pool[pool_ptr]←#; incr(pool_ptr);
---
> @d append_char(#) == {put |ASCII_code| \# at the end of |str_pool|}
> begin str_pool[pool_ptr]:=si(#); incr(pool_ptr);
988,990c1090,1094
< @d str_room(#) == begin if pool_ptr+# > pool_size then
< overflow("pool size",pool_size);
< end
---
> @d str_room(#) == {make sure that the pool hasn't overflowed}
> begin if pool_ptr+# > pool_size then
> overflow("pool size",pool_size-init_pool_ptr);
> @:TeX capacity exceeded pool size}{\quad pool size@>
> end
999,1001c1103,1106
< overflow("number of strings",max_strings);
< incr(str_ptr); str_start[str_ptr]←pool_ptr;
< make_string←str_ptr-1;
---
> overflow("number of strings",max_strings-init_str_ptr);
> @:TeX capacity exceeded number of strings}{\quad number of strings@>
> incr(str_ptr); str_start[str_ptr]:=pool_ptr;
> make_string:=str_ptr-1;
1006,1007c1111,1112
< @d flush_string==begin decr(str_ptr); pool_ptr←str_start[str_ptr];
< end
---
> @d flush_string==begin decr(str_ptr); pool_ptr:=str_start[str_ptr];
> end
1011a1117,1118
> Empirical tests indicate that |str_eq_buf| is used in such a way that
> it tends to return |true| about 80 percent of the time.
1014c1121
< {test equality of strings}
---
> {test equality of strings}
1018c1125
< begin j←str_start[s]; result←false;
---
> begin j:=str_start[s];
1020,1024c1127,1133
< begin if str_pool[j]≠buffer[k] then goto not_found;
< incr(j); incr(k);
< end;
< result←true;
< not_found: str_eq_buf←result;
---
> begin if so(str_pool[j])<>buffer[k] then
> begin result:=false; goto not_found;
> end;
> incr(j); incr(k);
> end;
> result:=true;
> not_found: str_eq_buf:=result;
1031c1140
< {test equality of strings}
---
> {test equality of strings}
1035,1037c1144,1146
< begin result←false;
< if length(s)≠length(t) then goto not_found;
< j←str_start[s]; k←str_start[t];
---
> begin result:=false;
> if length(s)<>length(t) then goto not_found;
> j:=str_start[s]; k:=str_start[t];
1039,1043c1148,1152
< begin if str_pool[j]≠str_pool[k] then goto not_found;
< incr(j); incr(k);
< end;
< result←true;
< not_found: str_eq_str←result;
---
> begin if str_pool[j]<>str_pool[k] then goto not_found;
> incr(j); incr(k);
> end;
> result:=true;
> not_found: str_eq_str:=result;
1052,1053c1161,1162
< @p init function init_strings:boolean; {initializes the string pool, but
< returns |false| if something goes wrong}
---
> @p @!init function get_strings_started:boolean; {initializes the string pool,
> but returns |false| if something goes wrong}
1055c1164
< var k,@!l:0..127; {small indices or counters}
---
> var k,@!l:0..255; {small indices or counters}
1059,1061c1168,1170
< @!c:boolean; {check sum has checked}
< begin pool_ptr←0; str_ptr←0;
< @<Make the first 128 strings@>;
---
> @!c:boolean; {check sum has been checked}
> begin pool_ptr:=0; str_ptr:=0; str_start[0]:=0;
> @<Make the first 256 strings@>;
1063c1172
< or give an error message and return |false|@>;
---
> or give an error message and return |false|@>;
1067,1079c1176,1190
< @ @<Make the first 128...@>=
< for k←0 to 127 do
< begin if (k<" ")∧(@<Character |k| cannot be printed@>) then
< begin append_char("^"); append_char("^");
< append_char(k+@'100);
< end
< else if k=127 then
< begin append_char("^"); append_char("^");
< append_char("?");
< end
< else append_char(k);
< g←make_string;
< end
---
> @ @d app_lc_hex(#)==l:=#;
> if l<10 then append_char(l+"0")@+else append_char(l-10+"a")
>
> @<Make the first 256...@>=
> for k:=0 to 255 do
> begin if (@<Character |k| cannot be printed@>) then
> begin append_char("^"); append_char("^");
> if k<@'100 then append_char(k+@'100)
> else if k<@'200 then append_char(k-@'100)
> else begin app_lc_hex(k div 16); app_lc_hex(k mod 16);
> end;
> end
> else append_char(k);
> g:=make_string;
> end
1081c1192
< @ The first 128 strings will contain 95 standard ascii characters, and the
---
> @ The first 128 strings will contain 95 standard ASCII characters, and the
1084c1195
< an extended character set, where for example |xchr[@'32]=@t\.{\'\NE\'}@>|,
---
> an extended character set, where for example |xchr[@'32]=@t\.{\'^^Z\'}@>|,
1092,1096c1203,1215
< The boolean expression defined here should be |true| unless \TeX\ internal code
< number@@$k$ corresponds to a non-troublesome visible symbol in the local
< char\-ac\-ter set, given that |k<@'40|.
< At MIT, for example, the appropriate formula would be
< `|k in [0,@'10..@'12,@'14,@'15,@'33]|'.
---
> Unprintable characters of codes 128--255 are, similarly, rendered
> \.{\^\^80}--\.{\^\^ff}.
>
> The boolean expression defined here should be |true| unless \TeX\
> internal code number~|k| corresponds to a non-troublesome visible
> symbol in the local character set. An appropriate formula for the
> extended character set recommended in {\sl The \TeX book\/} would, for
> example, be `|k in [0,@'10..@'12,@'14,@'15,@'33,@'177..@'377]|'.
> If character |k| cannot be printed, and |k<@'200|, then character |k+@'100| or
> |k-@'100| must be printable; moreover, ASCII codes |[@'41..@'46,
> @'60..@'71, @'136, @'141..@'146, @'160..@'171]| must be printable.
> Thus, at least 81 printable characters are needed.
> @:TeXbook}{\sl The \TeX book@>
1101c1220
< true
---
> (k<" ")or(k>"~")
1104c1223
< de\-scription that you are now reading, it outputs the \PASCAL\ program
---
> description that you are now reading, it outputs the \PASCAL\ program
1112c1231,1232
< @!pool_file:alpha_file; {the string-pool file output by \.{TANGLE}}
---
> @!init @!pool_file:alpha_file; {the string-pool file output by \.{TANGLE}}
> tini
1114,1115c1234,1236
< @ @d bad_pool(#)==begin write_ln(term_out,#); init_strings←false; return;
< end
---
> @ @d bad_pool(#)==begin wake_up_terminal; write_ln(term_out,#);
> a_close(pool_file); get_strings_started:=false; return;
> end
1117c1238
< name_of_file←pool_name; {we needn't set |name_length|}
---
> name_of_file:=pool_name; {we needn't set |name_length|}
1119,1125c1240,1246
< begin c←false;
< repeat @<Read one string, but return |false| if the
< string memory space is getting too tight for comfort@>;
< until c;
< init_strings←true;
< end
< else bad_pool('! I can''t read TEX.POOL.')
---
> begin c:=false;
> repeat @<Read one string, but return |false| if the
> string memory space is getting too tight for comfort@>;
> until c;
> a_close(pool_file); get_strings_started:=true;
> end
> else bad_pool('! I can''t read TEX.POOL.')
1133,1135c1254,1256
< else begin if (xord[m]<"0")∨(xord[m]>"9")∨@|
< (xord[n]<"0")∨(xord[n]>"9") then
< bad_pool('! TEX.POOL line doesn''t begin with two digits.');
---
> else begin if (xord[m]<"0")or(xord[m]>"9")or@|
> (xord[n]<"0")or(xord[n]>"9") then
> bad_pool('! TEX.POOL line doesn''t begin with two digits.');
1137,1139c1258,1260
< l←xord[m]*10+xord[n]-"0"*11; {compute the length}
< if pool_ptr+l+string_vacancies>pool_size then
< bad_pool('! You have to increase POOLSIZE.');
---
> l:=xord[m]*10+xord[n]-"0"*11; {compute the length}
> if pool_ptr+l+string_vacancies>pool_size then
> bad_pool('! You have to increase POOLSIZE.');
1141,1147c1262,1267
< for k←1 to l do
< begin if eoln(pool_file) then bad_pool('! TEX.POOL line too short.');
< @.TEX.POOL line too short@>
< read(pool_file,m); append_char(xord[m]);
< end;
< read_ln(pool_file); g←make_string;
< end;
---
> for k:=1 to l do
> begin if eoln(pool_file) then m:=' '@+else read(pool_file,m);
> append_char(xord[m]);
> end;
> read_ln(pool_file); g:=make_string;
> end;
1150c1270
< @ The \.{WEB} operation \.{\at\$} denotes the value that should be at the
---
> @ The \.{WEB} operation \.{@@\$} denotes the value that should be at the
1156,1158c1276,1278
< begin a←0; k←1;
< loop@+ begin if (xord[n]<"0")∨(xord[n]>"9") then
< bad_pool('! TEX.POOL check sum doesn''t have nine digits.');
---
> begin a:=0; k:=1;
> loop@+ begin if (xord[n]<"0")or(xord[n]>"9") then
> bad_pool('! TEX.POOL check sum doesn''t have nine digits.');
1160,1164c1280,1284
< a←10*a+xord[n]-"0";
< if k=9 then goto done;
< incr(k); read(pool_file,n);
< end;
< done: if a≠@$ then bad_pool('! TEX.POOL doesn''t match; TANGLE me again.');
---
> a:=10*a+xord[n]-"0";
> if k=9 then goto done;
> incr(k); read(pool_file,n);
> end;
> done: if a<>@$ then bad_pool('! TEX.POOL doesn''t match; TANGLE me again.');
1166c1286
< c←true;
---
> c:=true;
1167a1288
>
1169c1290
< Messages that are sent to a user's terminal and to the error-transcript file
---
> Messages that are sent to a user's terminal and to the transcript-log file
1176,1177c1297,1298
< \hang |term_and_err|, the normal setting, prints on the terminal and on the
< error-transcript file.
---
> \hang |term_and_log|, the normal setting, prints on the terminal and on the
> transcript file.
1179c1300
< \hang |err_only|, prints only on the error-transcript file.
---
> \hang |log_only|, prints only on the transcript file.
1184c1305
< before the error-transcript file is open.
---
> before the transcript file is open.
1186,1188c1307,1309
< \hang |pseudo|, puts output into a cyclic buffer that is used
< by the |show_context| routine; see that routine for the
< reasoning behind this curious mode.
---
> \hang |pseudo|, puts output into a cyclic buffer that is used
> by the |show_context| routine; when we get to that routine we shall discuss
> the reasoning behind this curious mode.
1191c1312
< string pool.
---
> string pool.
1193c1314
< \hang 0 to 15, prints on one of the sixteen files for \.{\\send} output.
---
> \hang 0 to 15, prints on one of the sixteen files for \.{\\write} output.
1196c1317
< \noindent The symbolic names `|term_and_err|', etc., have been assigned
---
> \noindent The symbolic names `|term_and_log|', etc., have been assigned
1198c1319
< |no_print+2=err_only|, |term_only+2=err_only+1=term_and_err|.
---
> |no_print+2=log_only|, |term_only+2=log_only+1=term_and_log|.
1200,1205c1321,1327
< Two additional global variables, |tally| and |offset|, record
< the number of characters that have been printed since they were most
< recently cleared to zero. We use |tally| to record the length of
< (possibly very long) stretches of printing; |offset|, on the other
< hand, keeps track of how many characters have appeared so far on the current
< line of text output.
---
> Three additional global variables, |tally| and |term_offset| and
> |file_offset|, record the number of characters that have been printed
> since they were most recently cleared to zero. We use |tally| to record
> the length of (possibly very long) stretches of printing; |term_offset|
> and |file_offset|, on the other hand, keep track of how many characters
> have appeared so far on the current line that has been output to the
> terminal or to the transcript file, respectively.
1209,1210c1331,1332
< @d err_only=18 {printing is destined for the transcript file only}
< @d term_and_err=19 {normal |selector| setting}
---
> @d log_only=18 {printing is destined for the transcript file only}
> @d term_and_log=19 {normal |selector| setting}
1215,1216c1337,1338
< @<Globals...@>=
< @!err_file : alpha_file; {transcript of \TeX\ session}
---
> @<Glob...@>=
> @!log_file : alpha_file; {transcript of \TeX\ session}
1218c1340
< @!dig : array[0..22] of 0..9; {digits in a number being output}
---
> @!dig : array[0..22] of 0..15; {digits in a number being output}
1220,1222c1342,1347
< @!offset : 0..max_print_line; {the number of characters on the current line}
< @!trick_buf:array[0..error_line] of ascii_code; {circular buffer for
< pseudoprinting}
---
> @!term_offset : 0..max_print_line;
> {the number of characters on the current terminal line}
> @!file_offset : 0..max_print_line;
> {the number of characters on the current file line}
> @!trick_buf:array[0..error_line] of ASCII_code; {circular buffer for
> pseudoprinting}
1227c1352,1365
< selector←term_only; tally←0; offset←0;
---
> selector:=term_only; tally:=0; term_offset:=0; file_offset:=0;
>
> @ Macro abbreviations for output to the terminal and to the log file are
> defined here for convenience. Some systems need special conventions
> for terminal output, and it is possible to adhere to those conventions
> by changing |wterm|, |wterm_ln|, and |wterm_cr| in this section.
> @^system dependencies@>
>
> @d wterm(#)==write(term_out,#)
> @d wterm_ln(#)==write_ln(term_out,#)
> @d wterm_cr==write_ln(term_out)
> @d wlog(#)==write(log_file,#)
> @d wlog_ln(#)==write_ln(log_file,#)
> @d wlog_cr==write_ln(log_file)
1233d1370
< label exit;
1235,1241c1372,1380
< term_and_err: begin write_ln(term_out); write_ln(err_file);
< end;
< err_only: write_ln(err_file);
< term_only: write_ln(term_out);
< no_print: do_nothing;
< pseudo,new_string: return;
< othercases write_ln(send_file[selector])
---
> term_and_log: begin wterm_cr; wlog_cr;
> term_offset:=0; file_offset:=0;
> end;
> log_only: begin wlog_cr; file_offset:=0;
> end;
> term_only: begin wterm_cr; term_offset:=0;
> end;
> no_print,pseudo,new_string: do_nothing;
> othercases write_ln(write_file[selector])
1243,1244c1382
< offset←0; {|tally| is not affected}
< exit:end;
---
> end; {|tally| is not affected}
1250,1251d1387
< @d preserve_offset=90 {go here when |offset| is not to be changed}
<
1253,1258c1389,1410
< procedure print_char(@!c:ascii_code); {prints a single character}
< label preserve_offset;
< begin case selector of
< term_and_err: begin write(term_out,xchr[c]); write(err_file,xchr[c]); end;
< err_only: write(err_file,xchr[c]);
< term_only: write(term_out,xchr[c]);
---
> procedure print_char(@!s:ASCII_code); {prints a single character}
> label exit;
> begin if @<Character |s| is the current new-line character@> then
> if selector<pseudo then
> begin print_ln; return;
> end;
> case selector of
> term_and_log: begin wterm(xchr[s]); wlog(xchr[s]);
> incr(term_offset); incr(file_offset);
> if term_offset=max_print_line then
> begin wterm_cr; term_offset:=0;
> end;
> if file_offset=max_print_line then
> begin wlog_cr; file_offset:=0;
> end;
> end;
> log_only: begin wlog(xchr[s]); incr(file_offset);
> if file_offset=max_print_line then print_ln;
> end;
> term_only: begin wterm(xchr[s]); incr(term_offset);
> if term_offset=max_print_line then print_ln;
> end;
1260,1268c1412,1415
< pseudo: begin if tally<trick_count then
< trick_buf[tally mod error_line]←c;
< goto preserve_offset;
< end;
< new_string: begin if pool_ptr<pool_size then append_char(c);
< goto preserve_offset; {drop characters if the string space is full}
< end;
< othercases begin write(send_file[selector],xchr[c]); goto preserve_offset;
< end
---
> pseudo: if tally<trick_count then trick_buf[tally mod error_line]:=s;
> new_string: begin if pool_ptr<pool_size then append_char(s);
> end; {we drop characters if the string space is full}
> othercases write(write_file[selector],xchr[s])
1270,1273c1417,1418
< incr(offset);
< if offset=max_print_line then print_ln;
< preserve_offset:incr(tally);
< end;
---
> incr(tally);
> exit:end;
1276c1421
< the single standard ascii character \.c, we could call |print("c")|, since
---
> the single standard ASCII character \.c, we could call |print("c")|, since
1279c1424,1426
< routine when it knows that this is safe.
---
> routine when it knows that this is safe. (The present implementation
> assumes that it is always safe to print a visible ASCII character.)
> @^system dependencies@>
1282a1430
> label exit;
1284,1285c1432,1452
< begin if (s<0)∨(s≥str_ptr) then s←0; {this can't happen}
< j←str_start[s];
---
> @!nl:integer; {new-line character to restore}
> begin if s>=str_ptr then s:="???" {this can't happen}
> @.???@>
> else if s<256 then
> if s<0 then s:="???" {can't happen}
> else begin if selector>pseudo then
> begin print_char(s); return; {internal strings are not expanded}
> end;
> if (@<Character |s| is the current new-line character@>) then
> if selector<pseudo then
> begin print_ln; return;
> end;
> nl:=new_line_char; new_line_char:=-1;
> {temporarily disable new-line character}
> j:=str_start[s];
> while j<str_start[s+1] do
> begin print_char(so(str_pool[j])); incr(j);
> end;
> new_line_char:=nl; return;
> end;
> j:=str_start[s];
1287,1288c1454,1470
< begin print_char(str_pool[j]); incr(j);
< end;
---
> begin print_char(so(str_pool[j])); incr(j);
> end;
> exit:end;
>
> @ Control sequence names, file names, and strings constructed with
> \.{\\string} might contain |ASCII_code| values that can't
> be printed using |print_char|. Therefore we use |slow_print| for them:
>
> @<Basic print...@>=
> procedure slow_print(@!s:integer); {prints string |s|}
> var j:pool_pointer; {current character code position}
> begin if (s>=str_ptr) or (s<256) then print(s)
> else begin j:=str_start[s];
> while j<str_start[s+1] do
> begin print(so(str_pool[j])); incr(j);
> end;
> end;
1292c1474
< the version number and format package. The |offset| variable is temporarily
---
> the version number and format package. The |term_offset| variable is temporarily
1298,1301c1480,1484
< write(term_out,banner);
< if format_ident=0 then write_ln(term_out,' (no format preloaded)')
< else begin print(format_ident); print_ln;
< end;
---
> wterm(banner);
> if format_ident=0 then wterm_ln(' (no format preloaded)')
> else begin slow_print(format_ident); print_ln;
> end;
> update_terminal;
1308c1491,1492
< begin if offset>0 then print_ln;
---
> begin if ((term_offset>0)and(odd(selector)))or@|
> ((file_offset>0)and(selector>=log_only)) then print_ln;
1313c1497
< a backslash.
---
> the user's escape character (which is usually a backslash).
1317c1501,1504
< begin print_char("\"); print(s);
---
> var c:integer; {the escape character code}
> begin @<Set variable |c| to the current escape character@>;
> if c>=0 then if c<256 then print(c);
> slow_print(s);
1320c1507
< @ An array of digits is printed by |print_digs|.
---
> @ An array of digits in the range |0..15| is printed by |print_the_digs|.
1323c1510,1511
< procedure print_digs(@!k:eight_bits); {prints |dig[k-1]|$\ldotsm$|dig[0]|}
---
> procedure print_the_digs(@!k:eight_bits);
> {prints |dig[k-1]|$\,\ldots\,$|dig[0]|}
1325,1326c1513,1516
< begin decr(k); print_char("0"+dig[k]);
< end;
---
> begin decr(k);
> if dig[k]<10 then print_char("0"+dig[k])
> else print_char("A"-10+dig[k]);
> end;
1337,1339c1527,1529
< var k:0..20; {index to current digit; we assume that $|n|<10^{20}$}
< @!m:nonnegative_integer; {used to negate |n| in possibly dangerous cases}
< begin k←0;
---
> var k:0..23; {index to current digit; we assume that $|n|<10^{23}$}
> @!m:integer; {used to negate |n| in possibly dangerous cases}
> begin k:=0;
1341,1349c1531,1539
< begin print_char("-");
< if n>-100000000 then n←-n
< else begin m←-1-n; n←m div 10; m←(m mod 10)+1; k←1;
< if m<10 then dig[0]←m
< else begin dig[0]←0; n←n+1;
< end;
< end;
< end;
< repeat dig[k]←n mod 10; n←n div 10; incr(k);
---
> begin print_char("-");
> if n>-100000000 then negate(n)
> else begin m:=-1-n; n:=m div 10; m:=(m mod 10)+1; k:=1;
> if m<10 then dig[0]:=m
> else begin dig[0]:=0; incr(n);
> end;
> end;
> end;
> repeat dig[k]:=n mod 10; n:=n div 10; incr(k);
1351c1541
< print_digs(k);
---
> print_the_digs(k);
1354c1544,1545
< @ Octal printing of nonnegative integers is accomplished by |print_octal|.
---
> @ Here is a trivial procedure to print two digits; it is usually called with
> a parameter in the range |0<=n<=99|.
1356,1361c1547,1549
< @p procedure print_octal(@!n:integer); {prints a positive integer in octal form}
< var k:0..22; {index to current digit; we assume that $0\L n<8^{22}$}
< begin k←0; print_char("'");
< repeat dig[k]←n mod 8; n←n div 8; incr(k);
< until n=0;
< print_digs(k);
---
> @p procedure print_two(@!n:integer); {prints two least significant digits}
> begin n:=abs(n) mod 100; print_char("0"+(n div 10));
> print_char("0"+(n mod 10));
1364,1365c1552
< @ In certain situations, \TeX\ prints either a standard visible ascii
< character or its octal ascii code.
---
> @ Hexadecimal printing of nonnegative integers is accomplished by |print_hex|.
1367,1371c1554,1560
< @p procedure print_ascii(@!c:integer); {prints a character or its code}
< begin if (c>" ") and (c≤"~") then print_char(c)
< else begin if c<0 then print_char("-");
< print_octal(abs(c)); print_char(" ");
< end;
---
> @p procedure print_hex(@!n:integer);
> {prints a positive integer in hexadecimal form}
> var k:0..22; {index to current digit; we assume that $0\L n<16^{22}$}
> begin k:=0; print_char("""");
> repeat dig[k]:=n mod 16; n:=n div 16; incr(k);
> until n=0;
> print_the_digs(k);
1374,1377c1563,1572
< @ Roman numerals are produced by the |print_roman_int| routine, whose
< argument should be a positive integer. Readers who like puzzles might enjoy
< trying to figure out how this tricky code works; therefore no explanation
< will be given.
---
> @ Old versions of \TeX\ needed a procedure called |print_ASCII| whose function
> is now subsumed by |print|. We retain the old name here as a possible aid to
> future software arch\ae ologists.
>
> @d print_ASCII == print
>
> @ Roman numerals are produced by the |print_roman_int| routine. Readers
> who like puzzles might enjoy trying to figure out how this tricky code
> works; therefore no explanation will be given. Notice that 1990 yields
> \.{mcmxc}, not \.{mxm}.
1379c1574
< @p procedure print_roman_int(@!n:nonnegative_integer);
---
> @p procedure print_roman_int(@!n:integer);
1383,1397c1578,1592
< begin j←str_start["m2d5c2l5x2v5i"]; v←1000;
< loop@+ begin while n≥v do
< begin print_char(str_pool[j]); n←n-v;
< end;
< if n=0 then return;
< k←j+2; u←v div (str_pool[k-1]-"0");
< if str_pool[k-1]="2" then
< begin k←k+2; u←u div (str_pool[k-1]-"0");
< end;
< if n+u≥v then
< begin print_char(str_pool[k]); n←n+u;
< end
< else begin j←j+2; v←v div (str_pool[j-1]-"0");
< end;
< end;
---
> begin j:=str_start["m2d5c2l5x2v5i"]; v:=1000;
> loop@+ begin while n>=v do
> begin print_char(so(str_pool[j])); n:=n-v;
> end;
> if n<=0 then return; {nonpositive input produces no output}
> k:=j+2; u:=v div (so(str_pool[k-1])-"0");
> if str_pool[k-1]=si("2") then
> begin k:=k+2; u:=u div (so(str_pool[k-1])-"0");
> end;
> if n+u>=v then
> begin print_char(so(str_pool[k])); n:=n+u;
> end
> else begin j:=j+2; v:=v div (so(str_pool[j-1])-"0");
> end;
> end;
1405c1600
< begin j←str_start[str_ptr];
---
> begin j:=str_start[str_ptr];
1407,1408c1602,1603
< begin print_char(str_pool[j]); incr(j);
< end;
---
> begin print_char(so(str_pool[j])); incr(j);
> end;
1412c1607
< assuming that the |selector| setting is either |term_only| or |term_and_err|.
---
> assuming that the |selector| setting is either |term_only| or |term_and_log|.
1418,1419c1613,1614
< @d prompt_input(#)==begin print(#); term_input;
< end {prints a string and gets a line of input}
---
> @d prompt_input(#)==begin wake_up_terminal; print(#); term_input;
> end {prints a string and gets a line of input}
1423,1425c1618,1621
< begin update_terminal; {Now the user sees the prompt for sure}
< if not input_ln(term_in) then fatal_error("! End of file on the terminal");
< @.End of file on the terminal...@>
---
> begin update_terminal; {now the user sees the prompt for sure}
> if not input_ln(term_in,true) then fatal_error("End of file on the terminal!");
> @.End of file on the terminal@>
> term_offset:=0; {the user's line ended with \<\rm return>}
1427,1428c1623,1624
< if last≠first then for k←first to last-1 do print(buffer[k]);
< print_ln; incr(selector); {restore previous status, with |offset=0|}
---
> if last<>first then for k:=first to last-1 do print(buffer[k]);
> print_ln; incr(selector); {restore previous status}
1429a1626
>
1433c1630
< |print_nl("! Something anomalous has been detected");|\cr
---
> |print_err("Something anomalous has been detected");|\cr
1440c1637
< official error message that was printed. (Outside of the U.S.A., the help
---
> official error message that was printed. (Outside the U.S.A., the help
1444a1642,1643
> The |print_err| procedure supplies a `\.!' before the official message,
> and makes sure that the terminal is awake if a stop is going to occur.
1457a1657,1659
> @d print_err(#)==begin if interaction=error_stop_mode then wake_up_terminal;
> print_nl("! "); print(#);
> end
1462c1664
< @ @<Set init...@>=interaction←error_stop_mode;
---
> @ @<Set init...@>=interaction:=error_stop_mode;
1469c1671
< and |err_file| not yet open);
---
> and |log_file| not yet open);
1471c1673
< \hang|term_only| (when |interaction>batch_mode| and |err_file| not yet open);
---
> \hang|term_only| (when |interaction>batch_mode| and |log_file| not yet open);
1473c1675
< \hang|err_only| (when |interaction=batch_mode| and |err_file| is open);
---
> \hang|log_only| (when |interaction=batch_mode| and |log_file| is open);
1475c1677
< \hang|term_and_err| (when |interaction>batch_mode| and |err_file| is open).
---
> \hang|term_and_log| (when |interaction>batch_mode| and |log_file| is open).
1478c1680
< if interaction=batch_mode then selector←no_print@+else selector←term_only
---
> if interaction=batch_mode then selector:=no_print@+else selector:=term_only
1482a1685
> A similar interlock is provided by |set_box_allowed|.
1485,1486c1688,1690
< The global variable |spotless| is set to false when the first error
< has been detected.
---
> The global variable |history| records the worst level of error that
> has been detected. It has four possible values: |spotless|, |warning_issued|,
> |error_message_issued|, and |fatal_error_stop|.
1492a1697,1701
> @d spotless=0 {|history| value when nothing has been amiss yet}
> @d warning_issued=1 {|history| value when |begin_diagnostic| has been called}
> @d error_message_issued=2 {|history| value when |error| has been called}
> @d fatal_error_stop=3 {|history| value when termination was premature}
>
1495c1704,1705
< @!spotless:boolean; {has the source input been clean so far?}
---
> @!set_box_allowed:boolean; {is it safe to do a \.{\\setbox} assignment?}
> @!history:spotless..fatal_error_stop; {has the source input been clean so far?}
1497c1707
< last paragraph ended}
---
> last paragraph ended}
1499,1500c1709,1714
< @ @<Set init...@>=
< deletions_allowed←true; spotless←true; error_count←0;
---
> @ The value of |history| is initially |fatal_error_stop|, but it will
> be changed to |spotless| if \TeX\ survives the initialization process.
>
> @<Set init...@>=
> deletions_allowed:=true; set_box_allowed:=true;
> error_count:=0; {|history| is initialized elsewhere}
1508c1722
< when |get_token| is being used to delete a token, or if some fatal error
---
> when |get_token| is being used to delete a token, and/or if some fatal error
1511c1725
< is never more than one level deep.
---
> is never more than two levels deep.
1513a1728
> procedure@?normalize_selector; forward;@t\2@>@/
1517a1733
> procedure@?open_log_file; forward;@t\2@>@/
1520c1736,1738
< @t\4@>@;@+debug@+procedure@?debug_help; forward;@;@+gubed
---
> procedure@?give_err_help; forward;@t\2@>@/
> @t\4\hskip-\fontdimen2\font@>@;@+@!debug@+procedure@?debug_help;
> forward;@;@+gubed
1524c1742
< in reverse order, i.e., with |help_line[0]| last.
---
> in reverse order, i.e., with |help_line[0]| appearing last.
1526,1538c1744,1756
< @d hlp1(#)==help_line[0]←#;@+end
< @d hlp2(#)==help_line[1]←#; hlp1
< @d hlp3(#)==help_line[2]←#; hlp2
< @d hlp4(#)==help_line[3]←#; hlp3
< @d hlp5(#)==help_line[4]←#; hlp4
< @d hlp6(#)==help_line[5]←#; hlp5
< @d help0==help_ptr←0 {sometimes there might be no help}
< @d help1==@+begin help_ptr←1; hlp1 {use this with one help line}
< @d help2==@+begin help_ptr←2; hlp2 {use this with two help lines}
< @d help3==@+begin help_ptr←3; hlp3 {use this with three help lines}
< @d help4==@+begin help_ptr←4; hlp4 {use this with four help lines}
< @d help5==@+begin help_ptr←5; hlp5 {use this with five help lines}
< @d help6==@+begin help_ptr←6; hlp6 {use this with six help lines}
---
> @d hlp1(#)==help_line[0]:=#;@+end
> @d hlp2(#)==help_line[1]:=#; hlp1
> @d hlp3(#)==help_line[2]:=#; hlp2
> @d hlp4(#)==help_line[3]:=#; hlp3
> @d hlp5(#)==help_line[4]:=#; hlp4
> @d hlp6(#)==help_line[5]:=#; hlp5
> @d help0==help_ptr:=0 {sometimes there might be no help}
> @d help1==@+begin help_ptr:=1; hlp1 {use this with one help line}
> @d help2==@+begin help_ptr:=2; hlp2 {use this with two help lines}
> @d help3==@+begin help_ptr:=3; hlp3 {use this with three help lines}
> @d help4==@+begin help_ptr:=4; hlp4 {use this with four help lines}
> @d help5==@+begin help_ptr:=5; hlp5 {use this with five help lines}
> @d help6==@+begin help_ptr:=6; hlp6 {use this with six help lines}
1542a1761,1764
> @!use_err_help:boolean; {should the |err_help| list be shown?}
>
> @ @<Set init...@>=
> help_ptr:=0; use_err_help:=false;
1544,1545c1766,1767
< @ The |quit| procedure just cuts across all active procedure levels and jumps
< out to |end_of_TEX|. This is the only nonlocal |@!goto| statement in the
---
> @ The |jump_out| procedure just cuts across all active procedure levels and
> goes to |end_of_TEX|. This is the only nontrivial |@!goto| statement in the
1550,1551c1772,1774
< In such cases the body of |quit| should simply be `|close_files_and_terminate|;'
< followed by a call on some system procedure that quietly terminates the program.
---
> In such cases the body of |jump_out| should simply be
> `|close_files_and_terminate|;\thinspace' followed by a call on some system
> procedure that quietly terminates the program.
1554c1777
< procedure quit;
---
> procedure jump_out;
1562,1565c1785,1790
< label continue, exit;
< var c:ascii_code; {what the user types}
< @!s1,@!s2,@!s3:integer; {used to save global variables when deleting tokens}
< begin print_char("."); show_context;
---
> label continue,exit;
> var c:ASCII_code; {what the user types}
> @!s1,@!s2,@!s3,@!s4:integer;
> {used to save global variables when deleting tokens}
> begin if history<error_message_issued then history:=error_message_issued;
> print_char("."); show_context;
1569c1794
< begin print_nl("(That makes 100 errors; please try again.)");
---
> begin print_nl("(That makes 100 errors; please try again.)");
1571,1572c1796,1797
< quit;
< end;
---
> history:=fatal_error_stop; jump_out;
> end;
1578,1582c1803,1808
< if last=first then return;
< c←buffer[first];
< if c≥"a" then c←c+"A"-"a"; {convert to upper case}
< @<Interpret code |c| and |return| if done@>;
< end
---
> @.?\relax@>
> if last=first then return;
> c:=buffer[first];
> if c>="a" then c:=c+"A"-"a"; {convert to uppercase}
> @<Interpret code |c| and |return| if done@>;
> end
1587,1591c1813,1815
< wizardry, so it is not standard in \TeX\ and not included here except
< as a recommendation. (The name of the file to edit, if an `\.E' option is
< added, is |input_stack[base_ptr].name_field|, provided that |base_ptr>0|;
< the value of |base_ptr| has been set by |show_context|.
< No input files are open when |base_ptr=0|.)
---
> wizardry, so the present implementation simply types out the name of the
> file that should be
> edited and the relevant line number.
1594,1595c1818,1819
< There is a secret `\.D' option available when the debugging routines have
< not been commented out.
---
> There is a secret `\.D' option available when the debugging routines haven't
> been commented~out.
1600,1603c1824,1834
< "1","2","3","4","5","6","7","8","9": if deletions_allowed then
< @<Delete |c-"0"| tokens, |goto continue|@>;
< @t\4\4@>@;@+debug "D": begin debug_help; goto continue;@+end;@+gubed@/
< "H": @<Print the help information, |goto continue|@>;
---
> "0","1","2","3","4","5","6","7","8","9": if deletions_allowed then
> @<Delete \(c)|c-"0"| tokens and |goto continue|@>;
> @t\4\4@>@;@+@!debug "D": begin debug_help; goto continue;@+end;@+gubed@/
> "E": if base_ptr>0 then
> begin print_nl("You want to edit file ");
> @.You want to edit file x@>
> slow_print(input_stack[base_ptr].name_field);
> print(" at line "); print_int(line);
> interaction:=scroll_mode; jump_out;
> end;
> "H": @<Print the help information and |goto continue|@>;
1606,1610c1837,1838
< "X":begin prompt_input("Type X again to exit:");
< if (last>first)∧((buffer[first]="x")∨(buffer[first]="X")) then
< begin interaction←scroll_mode; quit;
< end;
< end;
---
> "X":begin interaction:=scroll_mode; jump_out;
> end;
1615,1620c1843,1845
< @ The `\.E' option in the following menu
< should be taken out of braces if it is implemented.
< @^system dependencies@>
<
< @<Print the menu...@>=
< print("Type <return> to proceed, S to scroll future error messages,");@/
---
> @ @<Print the menu...@>=
> begin print("Type <return> to proceed, S to scroll future error messages,");@/
> @.Type <return> to proceed...@>
1622,1623c1847,1848
< print_nl("I to insert something, ");@/
< @{@,@,@+if base_ptr>0 then print("E to edit your file,");@;@+@}@/
---
> print_nl("I to insert something, ");
> if base_ptr>0 then print("E to edit your file,");
1625,1626c1850,1852
< print_nl("1 or ... or 9 to ignore the next 1 to 9 tokens of input,");
< print_nl("H for help, X to quit.")
---
> print_nl("1 or ... or 9 to ignore the next 1 to 9 tokens of input,");
> print_nl("H for help, X to quit.");
> end
1634,1636c1860,1868
< begin error_count←0; interaction←batch_mode+c-"Q";
< if c="Q" then decr(selector);
< print_ln; return;
---
> begin error_count:=0; interaction:=batch_mode+c-"Q";
> print("OK, entering ");
> case c of
> "Q":begin print_esc("batchmode"); decr(selector);
> end;
> "R":print_esc("nonstopmode");
> "S":print_esc("scrollmode");
> end; {there are no other cases}
> print("..."); print_ln; update_terminal; return;
1639,1642c1871,1874
< @ When the following code is executed, the material inserted by the user
< may appear in |buffer[(first+1)..(last-1)]|; otherwise another prompt
< will be given. In order to fully understand this part of the program,
< you need to be familiar with \TeX's input stacks.
---
> @ When the following code is executed, |buffer[(first+1)..(last-1)]| may
> contain the material inserted by the user; otherwise another prompt will
> be given. In order to understand this part of the program fully, you need
> to be familiar with \TeX's input stacks.
1646c1878
< {now |state←mid_line|, so an initial blank space will count as a blank}
---
> {now |state=mid_line|, so an initial blank space will count as a blank}
1648,1653c1880,1886
< begin loc←first+1; buffer[first]←" ";
< end
< else begin prompt_input("**"); loc←first;
< end;
< first←last;
< cur_input.limit_field←last-1; {no |carriage_return| ends this line}
---
> begin loc:=first+1; buffer[first]:=" ";
> end
> else begin prompt_input("insert>"); loc:=first;
> @.insert>@>
> end;
> first:=last;
> cur_input.limit_field:=last-1; {no |end_line_char| ends this line}
1659,1663c1892,1897
< @<Delete |c-"0"| tokens...@>=
< begin s1←cur_tok; s2←cur_cmd; s3←cur_chr; OK_to_interrupt←false;
< if (last>first+1) and (buffer[first+1]≥"0")∧(buffer[first+1]≤"9") then
< c←c*10+buffer[first+1]-"0"*11
< else c←c-"0";
---
> @<Delete \(c)|c-"0"| tokens...@>=
> begin s1:=cur_tok; s2:=cur_cmd; s3:=cur_chr; s4:=align_state;
> align_state:=1000000; OK_to_interrupt:=false;
> if (last>first+1) and (buffer[first+1]>="0")and(buffer[first+1]<="9") then
> c:=c*10+buffer[first+1]-"0"*11
> else c:=c-"0";
1665,1668c1899,1902
< begin get_token; {one-level recursive call of |error| is possible}
< decr(c);
< end;
< cur_tok←s1; cur_cmd←s2; cur_chr←s3; OK_to_interrupt←true;
---
> begin get_token; {one-level recursive call of |error| is possible}
> decr(c);
> end;
> cur_tok:=s1; cur_cmd:=s2; cur_chr:=s3; align_state:=s4; OK_to_interrupt:=true;
1675,1679c1909,1917
< begin if help_ptr=0 then
< help2("Sorry, I don't know how to help in this situation.")@/
< ("Maybe you should try asking a human?");
< repeat decr(help_ptr); print(help_line[help_ptr]); print_ln;
< until help_ptr=0;
---
> begin if use_err_help then
> begin give_err_help; use_err_help:=false;
> end
> else begin if help_ptr=0 then
> help2("Sorry, I don't know how to help in this situation.")@/
> @t\kern1em@>("Maybe you should try asking a human?");
> repeat decr(help_ptr); print(help_line[help_ptr]); print_ln;
> until help_ptr=0;
> end;
1681,1683c1919,1921
< ("Maybe you should try asking a human?")@/
< ("An error might have occurred before I noticed any problems.")@/
< ("``If all else fails, read the instructions.''");
---
> ("Maybe you should try asking a human?")@/
> ("An error might have occurred before I noticed any problems.")@/
> ("``If all else fails, read the instructions.''");@/
1689,1691c1927,1932
< while help_ptr>0 do
< begin decr(help_ptr); print_nl(help_line[help_ptr]);
< end;
---
> if use_err_help then
> begin print_ln; give_err_help;
> end
> else while help_ptr>0 do
> begin decr(help_ptr); print_nl(help_line[help_ptr]);
> end;
1693c1934
< if interaction>batch_mode then incr(selector); {enable terminal output}
---
> if interaction>batch_mode then incr(selector); {re-enable terminal output}
1702a1944,1954
> @ In anomalous cases, the print selector might be in an unknown state;
> the following subroutine is called to fix things just enough to keep
> running a bit longer.
>
> @p procedure normalize_selector;
> begin if log_opened then selector:=term_and_log
> else selector:=term_only;
> if job_name=0 then open_log_file;
> if interaction=batch_mode then decr(selector);
> end;
>
1706,1708c1958,1962
< interaction←scroll_mode; {no more interaction}
< error; quit; {irrecoverable error}
< end
---
> interaction:=scroll_mode; {no more interaction}
> if log_opened then error;
> @!debug if interaction>batch_mode then debug_help;@+gubed@;@/
> history:=fatal_error_stop; jump_out; {irrecoverable error}
> end
1712c1966,1967
< begin print_nl("! Emergency stop"); help1(s); succumb;
---
> begin normalize_selector;@/
> print_err("Emergency stop"); help1(s); succumb;
1720,1722c1975,1978
< begin print_nl("! TeX capacity exceeded, sorry [");
< @.TeX capacity exceeded...@>
< print(s); print_char("="); print_int(n); print_char("]");
---
> begin normalize_selector;
> print_err("TeX capacity exceeded, sorry [");
> @.TeX capacity exceeded ...@>
> print(s); print_char("="); print_int(n); print_char("]");
1724c1980
< ("you can ask a wizard to enlarge me.");
---
> ("you can ask a wizard to enlarge me.");
1728,1730c1984,1989
< @ The program might sometime run completely amok and print out the
< following message, which is really intended for the \TeX\ maintenance
< person instead of the user.
---
> @ The program might sometime run completely amok, at which point there is
> no choice but to stop. If no previous error has been detected, that's bad
> news; a message is printed that is really intended for the \TeX\
> maintenance person instead of the user (unless the user has been
> particularly diabolical). The index entries for `this can't happen' may
> help to pinpoint the problem.
1735,1737c1994,1997
< {consistency check violated; |s| tells where}
< begin if spotless then
< begin print_nl("! This can't happen ("); print(s); print_char(")");
---
> {consistency check violated; |s| tells where}
> begin normalize_selector;
> if history<error_message_issued then
> begin print_err("This can't happen ("); print(s); print_char(")");
1739,1741c1999,2001
< help1("I'm broken. Please show this to someone who can fix can fix");
< end
< else begin print_nl("! I can't go on meeting you like this");
---
> help1("I'm broken. Please show this to someone who can fix can fix");
> end
> else begin print_err("I can't go on meeting you like this");
1743,1745c2003,2005
< help2("One of your earlier faux pas has wounded me deeply,")@/
< ("so I'm barely conscious. Please fix it and try again.");
< end;
---
> help2("One of your faux pas seems to have wounded me deeply...")@/
> ("in fact, I'm barely conscious. Please fix it and try again.");
> end;
1757,1758c2017,2018
< @d check_interrupt==begin if interrupt≠0 then pause_for_instructions;
< end
---
> @d check_interrupt==begin if interrupt<>0 then pause_for_instructions;
> end
1761c2021
< @!interrupt:integer; {should \TeX\ pause for instruction?}
---
> @!interrupt:integer; {should \TeX\ pause for instructions?}
1765c2025
< interrupt←0; OK_to_interrupt←true;
---
> interrupt:=0; OK_to_interrupt:=true;
1767,1768c2027,2028
< @ When an interrupt has been detected, the program comes goes into its
< highest interaction level and lets the user have the full flexibility of
---
> @ When an interrupt has been detected, the program goes into its
> highest interaction level and lets the user have nearly the full flexibility of
1774,1777c2034,2037
< begin interaction←error_stop_mode;
< if (selector=err_only)∨(selector=no_print) then
< incr(selector);
< print_nl("! Interruption");
---
> begin interaction:=error_stop_mode;
> if (selector=log_only)or(selector=no_print) then
> incr(selector);
> print_err("Interruption");
1779,1784c2039,2044
< help3("You rang?")@/
< ("Try to insert some instructions for me (e.g.,`I\showlists'),")@/
< ("unless you just want to quit by typing `X'.");
< deletions_allowed←false; error; deletions_allowed←true;
< interrupt←0;
< end;
---
> help3("You rang?")@/
> ("Try to insert some instructions for me (e.g.,`I\showlists'),")@/
> ("unless you just want to quit by typing `X'.");
> deletions_allowed:=false; error; deletions_allowed:=true;
> interrupt:=0;
> end;
1785a2046
>
1802c2063,2066
< numerator. These are harmless; see |div| in the index.)
---
> numerator. These are harmless; see |div| in the index. Also if the user
> sets the \.{\\time} or the \.{\\year} to a negative value, some diagnostic
> information will involve negative-numerator division. The same remarks
> apply for |mod| as well as for |div|.)
1808,1809c2072,2073
< begin if odd(x) then half←(x+1) div 2
< else half←x @!div 2;
---
> begin if odd(x) then half:=(x+1) div 2
> else half:=x @!div 2;
1824,1825c2088,2089
< @ The following function is used to create a scaled integer from a decimal
< fraction $(.d↓0d↓1\ldotsm d↓{k-1})$, where |0≤k≤16|. The digit $d↓i$ is
---
> @ The following function is used to create a scaled integer from a given decimal
> fraction $(.d_0d_1\ldots d_{k-1})$, where |0<=k<=17|. The digit $d_i$ is
1829c2093
< {converts a decimal fraction}
---
> {converts a decimal fraction}
1831c2095
< begin a←0;
---
> begin a:=0;
1833,1835c2097,2099
< begin decr(k); a←(a+dig[k]*two) div 10;
< end;
< round_decimals←(a+1) div 2;
---
> begin decr(k); a:=(a+dig[k]*two) div 10;
> end;
> round_decimals:=(a+1) div 2;
1841,1844c2105,2112
< be reproduced exactly. [{\sl Proof:\/} If round$(x)=\lfloor
< x+{1\over2}\rfloor$ and if $\alpha<1$, it is not difficult to verify that
< round$(\alpha\,\hbox{round}( \alpha^{-1}n))=n$ for all integers $n$. In
< our case $\alpha=2^{16}/10^5$.]
---
> be reproduced exactly; the ``simplest'' such decimal number is output,
> but there is always at least one digit following the decimal point.
>
> The invariant relation in the \&{repeat} loop is that a sequence of
> decimal digits yet to be printed will yield the original number if and only if
> they form a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$.
> We can stop if and only if $f=0$ satisfies this condition; the loop will
> terminate before $s$ can possibly become zero.
1847,1848c2115,2116
< digits}
< var k:0..4; {index to current digit of the fraction part}
---
> digits}
> var delta:scaled; {amount of allowable inaccuracy}
1850,1851c2118,2119
< begin print_char("-"); s←-s; {print the sign, if negative}
< end;
---
> begin print_char("-"); negate(s); {print the sign, if negative}
> end;
1853,1854d2120
< s←((s mod unity) * 3125 + 1024) div 2048;
< {now |0≤s<100000| is the fraction part}
1856,1857c2122,2125
< repeat print_char("0"+(s div 10000)); s←10*(s mod 10000);
< until s=0;
---
> s:=10*(s mod unity)+5; delta:=10;
> repeat if delta>unity then s:=s+@'100000-50000; {round the last digit}
> print_char("0"+(s div unity)); s:=10*(s mod unity); delta:=delta*10;
> until s<=delta;
1871c2139
< @^Overflow in arithmetic@>
---
> @^overflow in arithmetic@>
1873c2141
< few dozen tests of the form `\!|if x≥@'10000000000 then
---
> few dozen tests of the form `\ignorespaces|if x>=@'10000000000 then
1890c2158,2159
< and@@|y| are |scaled| and |n| is an integer.
---
> and~|y| are |scaled| and |n| is an integer. We will also use it to
> multiply integers.
1892c2161,2164
< @p function nx_plus_y(@!n:integer;@!x,@!y:scaled):scaled;
---
> @d nx_plus_y(#)==mult_and_add(#,@'7777777777)
> @d mult_integers(#)==mult_and_add(#,0,@'17777777777)
>
> @p function mult_and_add(@!n:integer;@!x,@!y,@!max_answer:scaled):scaled;
1894,1900c2166,2172
< begin x←-x; n←-n;
< end;
< if n=0 then nx_plus_y←y
< else if ((x≤(@'7777777777-y) div n)∧(-x≤(@'7777777777+y) div n)) then
< nx_plus_y←n*x+y
< else begin arith_error←true; nx_plus_y←0;
< end;
---
> begin negate(x); negate(n);
> end;
> if n=0 then mult_and_add:=y
> else if ((x<=(max_answer-y) div n)and(-x<=(max_answer+y) div n)) then
> mult_and_add:=n*x+y
> else begin arith_error:=true; mult_and_add:=0;
> end;
1906,1907c2178,2179
< var negate:boolean; {should |remainder| be negated?}
< begin negate←false;
---
> var negative:boolean; {should |remainder| be negated?}
> begin negative:=false;
1909,1920c2181,2192
< begin arith_error←true; x_over_n←0; remainder←x;
< end
< else begin if n<0 then
< begin x←-x; n←-n; negate←true;
< end;
< if x≥0 then
< begin x_over_n←x div n; remainder←x mod n;
< end
< else begin x_over_n←-((-x) div n); remainder←-((-x) mod n);
< end;
< end;
< if negate then remainder←-remainder;
---
> begin arith_error:=true; x_over_n:=0; remainder:=x;
> end
> else begin if n<0 then
> begin negate(x); negate(n); negative:=true;
> end;
> if x>=0 then
> begin x_over_n:=x div n; remainder:=x mod n;
> end
> else begin x_over_n:=-((-x) div n); remainder:=-((-x) mod n);
> end;
> end;
> if negative then negate(remainder);
1924,1926c2196,2198
< where |n| and |d| are nonnegative integers |≤@t$2^{16}$@>| and |d| is
< positive. It would be too dangerous to multiply by@@|n| and then divide
< by@@|d|, in separate operations, since overflow might well occur; and it
---
> where |n| and |d| are nonnegative integers |<=@t$2^{16}$@>| and |d| is
> positive. It would be too dangerous to multiply by~|n| and then divide
> by~|d|, in separate operations, since overflow might well occur; and it
1931c2203
< var positive:boolean; {was |x≥0|?}
---
> var positive:boolean; {was |x>=0|?}
1933,1940c2205,2212
< begin if x≥0 then positive←true
< else begin x←-x; positive←false;
< end;
< t←(x mod @'100000)*n;
< u←(x div @'100000)*n+(t div @'100000);
< v←(u mod d)*@'100000 + (t mod @'100000);
< if u div d≥@'100000 then arith_error←true
< else u←@'100000*(u div d) + (v div d);
---
> begin if x>=0 then positive:=true
> else begin negate(x); positive:=false;
> end;
> t:=(x mod @'100000)*n;
> u:=(x div @'100000)*n+(t div @'100000);
> v:=(u mod d)*@'100000 + (t mod @'100000);
> if u div d>=@'100000 then arith_error:=true
> else u:=@'100000*(u div d) + (v div d);
1942,1945c2214,2217
< begin xn_over_d←u; remainder←v mod d;
< end
< else begin xn_over_d←-u; remainder←-(v mod d);
< end;
---
> begin xn_over_d:=u; remainder:=v mod d;
> end
> else begin xn_over_d:=-u; remainder:=-(v mod d);
> end;
1949,1950c2221,2222
< total@@|t| is supposed to be made from amounts that sum to@@|s|. According
< to the \TeX\ manual, the badness of this situation is $100(t/s)^3$;
---
> total~|t| is supposed to be made from amounts that sum to~|s|. According
> to {\sl The \TeX book}, the badness of this situation is $100(t/s)^3$;
1953a2226
> @:TeXbook}{\sl The \TeX book@>
1961,1962c2234,2235
< It is not difficult to prove that $$\hbox{|badness(t+1,s)≥badness(t,s)
< ≥badness(t,s+1)|}$$. The badness function defined here is capable of
---
> It is not difficult to prove that $$\hbox{|badness(t+1,s)>=badness(t,s)
> >=badness(t,s+1)|}.$$ The badness function defined here is capable of
1967c2240
< @p function badness(@!t,@!s:scaled):halfword; {compute badness, given |t≥0|}
---
> @p function badness(@!t,@!s:scaled):halfword; {compute badness, given |t>=0|}
1969,1977c2242,2250
< 100\cdot2^{18}$}
< begin if t=0 then badness←0
< else if s≤0 then badness←inf_bad
< else begin if t≤7230584 then r←(t*297) div s {$297^3=99.94\times2^{18}$}
< else if s≥1663497 then r←t div (s div 297)
< else r←t;
< if r>1290 then badness←inf_bad {$1290^3<2^{31}<1291^3$}
< else badness←(r*r*r+@'400000) div @'1000000;
< end; {that was $r^3/2^{18}$, rounded to the nearest integer}
---
> 100\cdot2^{18}$}
> begin if t=0 then badness:=0
> else if s<=0 then badness:=inf_bad
> else begin if t<=7230584 then r:=(t*297) div s {$297^3=99.94\times2^{18}$}
> else if s>=1663497 then r:=t div (s div 297)
> else r:=t;
> if r>1290 then badness:=inf_bad {$1290^3<2^{31}<1291^3$}
> else badness:=(r*r*r+@'400000) div @'1000000;
> end; {that was $r^3/2^{18}$, rounded to the nearest integer}
1987c2260
< An unsigned glue ratio should take the same amount of memory as an
---
> A glue ratio should take the same amount of memory as an
1990c2263
< |short_real| in some implementations of \PASCAL. Alter\-natively,
---
> |short_real| in some implementations of \PASCAL. Alternatively,
1992c2265,2266
< arithmetic; see {\sl TUGboat \bf3} (1982), 10--27.
---
> arithmetic; see {\sl TUGboat \bf3},1 (March 1982), 10--27. (But the
> routines cited there must be modified to allow negative glue ratios.)
1994a2269,2274
> @d set_glue_ratio_zero(#) == #:=0.0 {store the representation of zero ratio}
> @d set_glue_ratio_one(#) == #:=1.0 {store the representation of unit ratio}
> @d float(#) == # {convert from |glue_ratio| to type |real|}
> @d unfloat(#) == # {convert from |real| to type |glue_ratio|}
> @d float_constant(#) == #.0 {convert |integer| constant to |real|}
>
1996a2277
>
2000c2281
< possibly scaled, or an (unsigned) |glue_ratio|, or a small number of
---
> possibly scaled, or a (signed) |glue_ratio|, or a small number of
2012c2293
< field)\cr
---
> field)\cr
2014c2295
< &\qquad\qquad\qquad(four quarterword fields)\cr}}$$
---
> &\qquad\qquad\qquad(four quarterword fields)\cr}}$$
2039c2320
< so it makes rather general assumptions. If integers having the subrange
---
> so it makes few assumptions. If integers having the subrange
2057,2064c2338,2350
< if (min_quarterword>0)∨(max_quarterword<127) then bad←11;
< if (min_halfword>0)∨(max_halfword<32767) then bad←12;
< if (min_quarterword<min_halfword)∨@|
< (max_quarterword>max_halfword) then bad←13;
< if (mem_base<min_halfword)∨(mem_max≥max_halfword) then bad←14;
< if (font_base<min_quarterword)∨(font_max>max_quarterword) then bad←15;
< if (save_size>max_halfword)∨(max_strings>max_halfword) then bad←16;
< if (buf_size>max_halfword) then bad←17;
---
> init if (mem_min<>mem_bot)or(mem_max<>mem_top) then bad:=10;@+tini@;@/
> if (mem_min>mem_bot)or(mem_max<mem_top) then bad:=10;
> if (min_quarterword>0)or(max_quarterword<127) then bad:=11;
> if (min_halfword>0)or(max_halfword<32767) then bad:=12;
> if (min_quarterword<min_halfword)or@|
> (max_quarterword>max_halfword) then bad:=13;
> if (mem_min<min_halfword)or(mem_max>=max_halfword)or@|
> (mem_bot-mem_min>max_halfword+1) then bad:=14;
> if (font_base<min_quarterword)or(font_max>max_quarterword) then bad:=15;
> if font_max>font_base+256 then bad:=16;
> if (save_size>max_halfword)or(max_strings>max_halfword) then bad:=17;
> if buf_size>max_halfword then bad:=18;
> if max_quarterword-min_quarterword<255 then bad:=19;
2074c2360
< @^inner loop@>
---
> @^inner loop@>@^system dependencies@>
2076,2079c2362,2369
< @d qi(#)==(#+min_quarterword)
< {to put an |eight_bits| item into a quarterword}
< @d qo(#)==(#-min_quarterword)
< {to take an |eight_bits| item out of a quarterword}
---
> @d qi(#)==#+min_quarterword
> {to put an |eight_bits| item into a quarterword}
> @d qo(#)==#-min_quarterword
> {to take an |eight_bits| item out of a quarterword}
> @d hi(#)==#+min_halfword
> {to put a sixteen-bit item into a halfword}
> @d ho(#)==#-min_halfword
> {to take a sixteen-bit item from a halfword}
2092,2096c2382,2386
< @!rh:halfword;
< case two_choices of
< 1: (@!lh:halfword);
< 2: (@!b0:quarterword; @!b1:quarterword);
< end;
---
> @!rh:halfword;
> case two_choices of
> 1: (@!lh:halfword);
> 2: (@!b0:quarterword; @!b1:quarterword);
> end;
2098,2109c2388,2399
< @!b0:quarterword;
< @!b1:quarterword;
< @!b2:quarterword;
< @!b3:quarterword;
< end;
< @!memory_word = packed record@;@/
< case four_choices of
< 1: (@!int:integer);
< 2: (@!gr:glue_ratio);
< 3: (@!hh:two_halves);
< 4: (@!qqqq:four_quarters);
< end;
---
> @!b0:quarterword;
> @!b1:quarterword;
> @!b2:quarterword;
> @!b3:quarterword;
> end;
> @!memory_word = record@;@/
> case four_choices of
> 1: (@!int:integer);
> 2: (@!gr:glue_ratio);
> 3: (@!hh:two_halves);
> 4: (@!qqqq:four_quarters);
> end;
2116c2406,2407
< @p debug procedure print_memory_word(@!w:memory_word); {prints |w| in all ways}
---
> @p @!debug procedure print_word(@!w:memory_word);
> {prints |w| in all ways}
2119c2410,2411
< print_scaled(round(unity*w.gr)); print_ln;@/
---
> print_scaled(round(unity*float(w.gr))); print_ln;@/
> @^real multiplication@>
2125a2418
>
2127c2420
< The \TeX\ system does nearly all of its own mem\-ory allocation, so that it
---
> The \TeX\ system does nearly all of its own memory allocation, so that it
2135c2428
< called |eqtb| that will be explained below. A pointer variable might
---
> called |eqtb| that will be explained later. A pointer variable might
2138c2431
< value represents a null pointer.
---
> value represents a null pointer. \TeX\ does not assume that |mem[null]| exists.
2146,2147c2439,2442
< @ The |mem| array is divided once and for all into two regions that are
< allocated separately. Locations less than |hi_mem_base| are used for storing
---
> @ The |mem| array is divided into two regions that are allocated separately,
> but the dividing line between these two regions is not fixed; they grow
> together until finding their ``natural'' size in a particular job.
> Locations less than or equal to |lo_mem_max| are used for storing
2151,2162c2446,2466
< appears in the allocated nodes: the program is responsible for knowing the
< relevant size when a node is freed. The remaining region of |mem| is
< allocated in single words using a conventional \.{AVAIL} stack.
<
< Incidentally, it would be feasible to construct implementations of \TeX\ that
< are based on 16-bit words instead of 32-bit words, for machines having
< comparatively small memories. In such cases it would be desirable to have
< two parallel arrays for the upper part of memory, called say \\{mem\_link}|[p]|
< and \\{mem\_info}|[p]|,
< since the single-word region in the present implementation
< consists entirely of |memory_word| items of type |two_halves|.
< @^small computers@>
---
> appears in the allocated nodes; the program is responsible for knowing the
> relevant size when a node is freed. Locations greater than or equal to
> |hi_mem_min| are used for storing one-word records; a conventional
> \.{AVAIL} stack is used for allocation in this region.
>
> Locations of |mem| between |mem_bot| and |mem_top| may be dumped as part
> of preloaded format files, by the \.{INITEX} preprocessor.
> @.INITEX@>
> Production versions of \TeX\ may extend the memory at both ends in order to
> provide more space; locations between |mem_min| and |mem_bot| are always
> used for variable-size nodes, and locations between |mem_top| and |mem_max|
> are always used for single-word nodes.
>
> The key pointers that govern |mem| allocation have a prescribed order:
> $$\advance\thickmuskip-2mu
> \hbox{|null<=mem_min<=mem_bot<lo_mem_max<
> hi_mem_min<mem_top<=mem_end<=mem_max|.}$$
>
> Empirical tests show that the present implementation of \TeX\ tends to
> spend about 9\pct! of its running time allocating nodes, and about 6\pct!
> deallocating them after their use.
2164,2165c2468,2471
< @<Globals...@>=
< @!mem : array[mem_base..mem_max] of memory_word; {the big dynamic storage area}
---
> @<Glob...@>=
> @!mem : array[mem_min..mem_max] of memory_word; {the big dynamic storage area}
> @!lo_mem_max : pointer; {the largest location of variable-size memory in use}
> @!hi_mem_min : pointer; {the smallest location of one-word memory in use}
2169c2475
< maximum memory usage. When code between the delimiters |stat| $\ldots$
---
> maximum memory usage. When code between the delimiters |@!stat| $\ldots$
2171,2172c2477
< report these statistics whenever a page is output and |tracing_stats| is
< nonzero.
---
> report these statistics when |tracing_stats| is sufficiently large.
2174c2479
< @<Globals...@>=
---
> @<Glob...@>=
2176d2480
< @!max_var_used : integer; {how much memory was in use}
2181c2485
< occur between |hi_mem_base| and |mem_end|, inclusive, are of type
---
> occur between |hi_mem_min| and |mem_end|, inclusive, are of type
2191c2495
< @<Globals...@>=
---
> @<Glob...@>=
2195c2499
< @ If one-word memory is exhausted, it might mean that the user has forgotten
---
> @ If memory is exhausted, it might mean that the user has forgotten
2203a2508,2513
> @^inner loop@>
>
> If the available-space list is empty, i.e., if |avail=null|,
> we try first to increase |mem_end|. If that cannot be done, i.e., if
> |mem_end=mem_max|, we try to decrease |hi_mem_min|. If that cannot be
> done, i.e., if |hi_mem_min=lo_mem_max+1|, we have to quit.
2207,2208c2517,2518
< begin p←avail; {get top location in the |avail| stack}
< if p≠null then avail←link(avail) {and pop it off}
---
> begin p:=avail; {get top location in the |avail| stack}
> if p<>null then avail:=link(avail) {and pop it off}
2210,2217c2520,2532
< begin incr(mem_end); p←mem_end;
< end
< else begin runaway; {if memory is exhausted, display possible runaway text}
< overflow("memory size",mem_max-mem_base); {quit; all one-word nodes are busy}
< end;
< link(p)←null; {provide an oft-desired initialization of the new node}
< stat incr(dyn_used);@+tats@;{maintain statistics}
< get_avail←p;
---
> begin incr(mem_end); p:=mem_end;
> end
> else begin decr(hi_mem_min); p:=hi_mem_min;
> if hi_mem_min<=lo_mem_max then
> begin runaway; {if memory is exhausted, display possible runaway text}
> overflow("main memory size",mem_max+1-mem_min);
> {quit; all one-word nodes are busy}
> @:TeX capacity exceeded main memory size}{\quad main memory size@>
> end;
> end;
> link(p):=null; {provide an oft-desired initialization of the new node}
> @!stat incr(dyn_used);@+tats@;{maintain statistics}
> get_avail:=p;
2225,2227c2540,2555
< begin link(#)←avail; avail←#;
< stat decr(dyn_used);@+tats@/
< end
---
> begin link(#):=avail; avail:=#;
> @!stat decr(dyn_used);@+tats@/
> end
>
> @ There's also a |fast_get_avail| routine, which saves the procedure-call
> overhead at the expense of extra programming. This routine is used in
> the places that would otherwise account for the most calls of |get_avail|.
> @^inner loop@>
>
> @d fast_get_avail(#)==@t@>@;@/
> begin #:=avail; {avoid |get_avail| if possible, to save time}
> if #=null then #:=get_avail
> else begin avail:=link(#); link(#):=null;
> @!stat incr(dyn_used);@+tats@/
> end;
> end
2230a2559
> @^inner loop@>
2233,2237c2562,2569
< available}
< var q:pointer; {the successor of node |p|}
< begin while p≠null do
< begin q←link(p); free_avail(p); p←q;
< end;
---
> available}
> var @!q,@!r:pointer; {list traversers}
> begin if p<>null then
> begin r:=p;
> repeat q:=r; r:=link(r); @!stat decr(dyn_used);@+tats@/
> until r=null; {now |q| is the last node on the list}
> link(q):=avail; avail:=p;
> end;
2252a2585,2587
> (We require |mem_max<max_halfword| because terrible things can happen
> when |max_halfword| appears in the |link| field of a nonempty node.)
>
2259c2594
< @<Globals...@>=
---
> @<Glob...@>=
2263c2598
< of size@@|s|, which must be 2@@or more. The |link| field of the first word
---
> of size~|s|, which must be 2~or more. The |link| field of the first word
2270,2271c2605,2606
< @p function get_node(@!s:integer):pointer; {variable-size node liberation}
< label found,exit;
---
> @p function get_node(@!s:integer):pointer; {variable-size node allocation}
> label found,exit,restart;
2275c2610,2611
< begin p←rover; {start at some free node in the ring}
---
> @!t:integer; {temporary register}
> begin restart: p:=rover; {start at some free node in the ring}
2277,2278c2613,2615
< and |goto found| if allocation was possible@>;
< p←rlink(p); {move to the next node in the ring}
---
> and |goto found| if allocation was possible@>;
> @^inner loop@>
> p:=rlink(p); {move to the next node in the ring}
2281,2286c2618,2626
< begin get_node←max_halfword; return;
< end;
< overflow("var size",hi_mem_base-mem_base); {sorry, nothing satisfactory is left}
< found: link(r)←null; {this node is now nonempty}
< stat var_used←var_used+s; {maintain usage statistics}
< if var_used>max_var_used then max_var_used←var_used;
---
> begin get_node:=max_halfword; return;
> end;
> if lo_mem_max+2<hi_mem_min then if lo_mem_max+2<=mem_bot+max_halfword then
> @<Grow more variable-size memory and |goto restart|@>;
> overflow("main memory size",mem_max+1-mem_min);
> {sorry, nothing satisfactory is left}
> @:TeX capacity exceeded main memory size}{\quad main memory size@>
> found: link(r):=null; {this node is now nonempty}
> @!stat var_used:=var_used+s; {maintain usage statistics}
2288c2628
< get_node←r;
---
> get_node:=r;
2291,2292c2631,2666
< @ The following operations remove an empty node from the doubly-linked
< list, knowing that it is not the only item in the list.
---
> @ The lower part of |mem| grows by 1000 words at a time, unless
> we are very close to going under. When it grows, we simply link
> a new node into the available-space list. This method of controlled
> growth helps to keep the |mem| usage consecutive when \TeX\ is
> implemented on ``virtual memory'' systems.
> @^virtual memory@>
>
> @<Grow more variable-size memory and |goto restart|@>=
> begin if hi_mem_min-lo_mem_max>=1998 then t:=lo_mem_max+1000
> else t:=lo_mem_max+1+(hi_mem_min-lo_mem_max) div 2;
> {|lo_mem_max+2<=t<hi_mem_min|}
> p:=llink(rover); q:=lo_mem_max; rlink(p):=q; llink(rover):=q;@/
> if t>mem_bot+max_halfword then t:=mem_bot+max_halfword;
> rlink(q):=rover; llink(q):=p; link(q):=empty_flag; node_size(q):=t-lo_mem_max;@/
> lo_mem_max:=t; link(lo_mem_max):=null; info(lo_mem_max):=null;
> rover:=q; goto restart;
> end
>
> @ Empirical tests show that the routine in this section performs a
> node-merging operation about 0.75 times per allocation, on the average,
> after which it finds that |r>p+1| about 95\pct! of the time.
>
> @<Try to allocate...@>=
> q:=p+node_size(p); {find the physical successor}
> @^inner loop@>
> while is_empty(q) do {merge node |p| with node |q|}
> begin t:=rlink(q);
> if q=rover then rover:=t;
> llink(t):=llink(q); rlink(llink(q)):=t;@/
> q:=q+node_size(q);
> end;
> r:=q-s;
> if r>p+1 then @<Allocate from the top of node |p| and |goto found|@>;
> if r=p then if rlink(p)<>p then
> @<Allocate entire node |p| and |goto found|@>;
> node_size(p):=q-p {reset the size in case it grew}
2294,2312c2668,2671
< @d remove_node(#) ==@;
< if #=rover then rover←rlink(#);
< llink(rlink(#))←llink(#);
< rlink(llink(#))←rlink(#)
<
< @ @<Try to allocate...@>=
< q←p+node_size(p); {find the physical successor}
< while is_empty(q) do {merge |p| with |q|}
< begin remove_node(q); q←q+node_size(q);
< end;
< r←q-s;
< if r>p+1 then @<Allocate from top of node |p| and |goto found|@>;
< if (r=p) and ((rlink(p)≠rover) or (llink(p)≠rover)) then
< @<Allocate entire node |p| and |goto found|@>;
< node_size(p)←q-p {reset the size in case it grew}
<
< @ @<Allocate from top...@>=
< begin node_size(p)←r-p; {store the remaining size}
< rover←p; {start searching here next time}
---
> @ @<Allocate from the top...@>=
> begin node_size(p):=r-p; {store the remaining size}
> @^inner loop@>
> rover:=p; {start searching here next time}
2316,2318c2675,2679
< @ @<Allocate entire...@>=
< begin remove_node(p); {delete node |p| from the ring}
< rover←rlink(p); {let |rover| rove around}
---
> @ Here we delete node |p| from the ring, and let |rover| rove around.
>
> @<Allocate entire...@>=
> begin rover:=rlink(p); t:=llink(p);
> llink(rover):=t; rlink(t):=rover;
2324a2686
> @^inner loop@>
2327c2689
< liberation}
---
> liberation}
2329,2335c2691,2694
< begin if @<Node |p| isn't in the variable-size |mem|@> then
< confusion("freenode");
< @:confusion free_node}{\quad freenode@>
< node_size(p)←s; link(p)←empty_flag;
< q←llink(rover); llink(p)←q; rlink(p)←rover; {set both links}
< llink(rover)←p; rlink(q)←p; {insert |p| into the ring}
< stat var_used←var_used-s;@+tats@;{maintain statistics}
---
> begin node_size(p):=s; link(p):=empty_flag;
> q:=llink(rover); llink(p):=q; rlink(p):=rover; {set both links}
> llink(rover):=p; rlink(q):=p; {insert |p| into the ring}
> @!stat var_used:=var_used-s;@+tats@;{maintain statistics}
2343,2344c2702,2703
< @p init procedure sort_avail; {sorts the available variable-size nodes
< by location}
---
> @p @!init procedure sort_avail; {sorts the available variable-size nodes
> by location}
2347,2355c2706,2714
< begin p←get_node(@'10000000000); {merge adjacent free areas}
< p←rlink(rover); rlink(rover)←max_halfword; old_rover←rover;
< while p≠old_rover do @<Sort |p| into the list starting at |rover|
< and advance |p| to |rlink(p)|@>;
< p←rover;
< while rlink(p)≠max_halfword do
< begin llink(rlink(p))←p; p←rlink(p);
< end;
< rlink(p)←rover; llink(rover)←p;
---
> begin p:=get_node(@'10000000000); {merge adjacent free areas}
> p:=rlink(rover); rlink(rover):=max_halfword; old_rover:=rover;
> while p<>old_rover do @<Sort \(p)|p| into the list starting at |rover|
> and advance |p| to |rlink(p)|@>;
> p:=rover;
> while rlink(p)<>max_halfword do
> begin llink(rlink(p)):=p; p:=rlink(p);
> end;
> rlink(p):=rover; llink(rover):=p;
2359c2718,2719
< @ The following |while| loop terminates, since the list that starts at
---
> @ The following |while| loop is guaranteed to
> terminate, since the list that starts at
2362c2722
< @<Sort |p|...@>=
---
> @<Sort \(p)|p|...@>=
2364,2369c2724,2730
< begin q←p; p←rlink(q); rlink(q)←rover; rover←q;
< end
< else begin q←rover;
< while rlink(q)<p do q←rlink(q);
< r←rlink(p); rlink(p)←rlink(q); rlink(q)←p; p←r;
< end
---
> begin q:=p; p:=rlink(q); rlink(q):=rover; rover:=q;
> end
> else begin q:=rover;
> while rlink(q)<p do q:=rlink(q);
> r:=rlink(p); rlink(p):=rlink(q); rlink(q):=p; p:=r;
> end
>
2390c2751
< two words, and they appear in |mem| locations less than |hi_mem_base|.
---
> two words, and they appear in |mem| locations less than |hi_mem_min|.
2398,2400c2759,2761
< and most fonts will stick to characters less than 128 (since higher codes
< are accessed outside of math mode only via ligatures and the \.{\\char}
< operator).
---
> and most fonts will stick to characters whose codes are
> less than 128 (since higher codes
> are more difficult to access on most keyboards).
2407,2410c2768,2770
< entries: The first of these would identify the font and the character
< dimensions, and it would also link to the second, where the full halfword
< |info| field would address the desired character. Such an extension of
< \TeX\ would not be difficult; further details are left to the reader.
---
> entries: The first of these has |font=font_base|, and its |link| points
> to the second;
> the second identifies the font and the character dimensions.
2412c2772,2776
< the same box dimensions.
---
> the same box dimensions. The |character| field of the first |char_node|
> is a ``\\{charext}'' that distinguishes between graphic symbols whose
> dimensions are identical for typesetting purposes. (See the \MF\ manual.)
> Such an extension of \TeX\ would not be difficult; further details are
> left to the reader.
2419,2420c2783,2784
< @d is_char_node(#) == (#>hi_mem_base)
< {does the argument point to a |char_node|?}
---
> @d is_char_node(#) == (#>=hi_mem_min)
> {does the argument point to a |char_node|?}
2458c2822,2824
< @d glue_set(#) == mem[#+6].gr {a word of type |glue_ratio| for glue setting}
---
> @d glue_offset = 6 {position of |glue_set| in a box node}
> @d glue_set(#) == mem[#+glue_offset].gr
> {a word of type |glue_ratio| for glue setting}
2462,2463c2828,2829
< The |subtype| field is set to |min_quarterword|, since that is the |span_count|
< value that is desired in case this |hlist_node| is changed to an |unset_node|.
---
> The |subtype| field is set to |min_quarterword|, since that's the desired
> |span_count| value if this |hlist_node| is changed to an |unset_node|.
2467,2471c2833,2837
< begin p←get_node(box_node_size); type(p)←hlist_node;
< subtype(p)←min_quarterword;
< width(p)←0; depth(p)←0; height(p)←0; shift_amount(p)←0; list_ptr(p)←null;
< glue_sign(p)←normal; glue_order(p)←normal; glue_set(p)←0.0;
< new_null_box←p;
---
> begin p:=get_node(box_node_size); type(p):=hlist_node;
> subtype(p):=min_quarterword;
> width(p):=0; depth(p):=0; height(p):=0; shift_amount(p):=0; list_ptr(p):=null;
> glue_sign(p):=normal; glue_order(p):=normal; set_glue_ratio_zero(glue_set(p));
> new_null_box:=p;
2475c2841
< was made from a vertical list.
---
> contains a vertical list.
2484c2850
< an hlist; the |height| and |depth| are never running in a vlist.
---
> an hlist; the |height| and |depth| are never running in a~vlist.
2497,2500c2863,2866
< begin p←get_node(rule_node_size); type(p)←rule_node;
< subtype(p)←0; {the |subtype| is not used}
< width(p)←null_flag; depth(p)←null_flag; height(p)←null_flag;
< new_rule←p;
---
> begin p:=get_node(rule_node_size); type(p):=rule_node;
> subtype(p):=0; {the |subtype| is not used}
> width(p):=null_flag; depth(p):=null_flag; height(p):=null_flag;
> new_rule:=p;
2506c2872
< The |width| field of an |ins_node| is slightly misnamed; it actually holds
---
> The |height| field of an |ins_node| is slightly misnamed; it actually holds
2508,2510c2874,2879
< There is one more field, the |ins_ptr|, which points to the beginning of
< the vlist for the insertion. In the present implementation, |ins_ptr|
< occupies a full word, although half a word would be enough.
---
> The |depth| field holds the |split_max_depth| to be used in case this
> insertion is split, and the |split_top_ptr| points to the corresponding
> |split_top_skip|. The |float_cost| field holds the |floating_penalty| that
> will be used if this insertion floats to a subsequent page after a
> split insertion of the same class. There is one more field, the
> |ins_ptr|, which points to the beginning of the vlist for the insertion.
2513,2514c2882,2885
< @d ins_node_size=3 {number of words to allocate for an insertion}
< @d ins_ptr(#)==mem[#+2].int {the vertical list to be inserted}
---
> @d ins_node_size=5 {number of words to allocate for an insertion}
> @d float_cost(#)==mem[#+1].int {the |floating_penalty| to be used}
> @d ins_ptr(#)==info(#+4) {the vertical list to be inserted}
> @d split_top_ptr(#)==link(#+4) {the |split_top_skip| to be used}
2517,2518c2888,2889
< of a token list that contains the user's \.{\\mark} text. Like the |ins_ptr|
< field, this one occupies a full word instead of a halfword just because
---
> of a token list that contains the user's \.{\\mark} text.
> This field occupies a full word instead of a halfword, because
2526,2529c2897,2901
< @ An |adjust_node|, which occurs only in horizontal lists, specifies
< material that will be moved out into the surrounding vertical list;
< i.e., it is used to implement \TeX's `\.{\\vadjust}' operation.
< The |adjust_ptr| field points to the vlist containing this material.
---
> @ An |adjust_node|, which occurs only in horizontal lists,
> specifies material that will be moved out into the surrounding
> vertical list; i.e., it is used to implement \TeX's `\.{\\vadjust}'
> operation. The |adjust_ptr| field points to the vlist containing this
> material.
2534,2540c2906,2918
< @ A |ligature_node|, which occurs only in horizontal lists, specifies a
< composite character that was formed from two or more actual characters.
< The second word of the node, which is called the |lig_char| word, contains
< |font| and |character| fields just as in a |char_node|. The characters
< that generated the ligature have not been forgotten, since they are needed
< for diagnostic messages and for hyphenation; the |lig_ptr| field points to
< a linked list of character nodes for those characters.
---
> @ A |ligature_node|, which occurs only in horizontal lists, specifies
> a character that was fabricated from the interaction of two or more
> actual characters. The second word of the node, which is called the
> |lig_char| word, contains |font| and |character| fields just as in a
> |char_node|. The characters that generated the ligature have not been
> forgotten, since they are needed for diagnostic messages and for
> hyphenation; the |lig_ptr| field points to a linked list of character
> nodes for all original characters that have been deleted. (This list
> might be empty if the characters that generated the ligature were
> retained in other nodes.)
>
> The |subtype| field is 0, plus 2 and/or 1 if the original source of the
> ligature included implicit left and/or right boundaries.
2547c2925,2928
< contents of the |font|, |character|, and |lig_ptr| fields.
---
> contents of the |font|, |character|, and |lig_ptr| fields. We also have
> a |new_lig_item| function, which returns a two-word node having a given
> |character| field. Such nodes are used for temporary processing as ligatures
> are being created.
2551,2554c2932,2940
< begin p←get_node(small_node_size); type(p)←ligature_node;
< subtype(p)←0; {the |subtype| is not used}
< font(lig_char(p))←f; character(lig_char(p))←c; lig_ptr(p)←q;
< new_ligature←p;
---
> begin p:=get_node(small_node_size); type(p):=ligature_node;
> font(lig_char(p)):=f; character(lig_char(p)):=c; lig_ptr(p):=q;
> subtype(p):=0; new_ligature:=p;
> end;
> @#
> function new_lig_item(@!c:quarterword):pointer;
> var p:pointer; {the new node}
> begin p:=get_node(small_node_size); character(p):=c; lig_ptr(p):=null;
> new_lig_item:=p;
2565c2951
< lists that consist entirely of character, kern, and ligature nodes.
---
> lists that consist entirely of character, kern, box, rule, and ligature nodes.
2581,2583c2967,2969
< begin p←get_node(small_node_size); type(p)←disc_node;
< replace_count(p)←0; pre_break(p)←null; post_break(p)←null;
< new_disc←p;
---
> begin p:=get_node(small_node_size); type(p):=disc_node;
> replace_count(p):=0; pre_break(p):=null; post_break(p):=null;
> new_disc:=p;
2592c2978
< things by adding code to these extension modules. For example, there
---
> things by adding code at the end of the program. For example, there
2598c2984
< `\.{\\send}' and `\.{\\xsend}' as if they were extensions, in order to
---
> `\.{\\write}' and `\.{\\special}' as if they were extensions, in order to
2615,2616c3001,3002
< begin p←get_node(small_node_size); type(p)←math_node;
< subtype(p)←s; width(p)←w; new_math←p;
---
> begin p:=get_node(small_node_size); type(p):=math_node;
> subtype(p):=s; width(p):=w; new_math:=p;
2623,2624c3009,3010
< |type| of the previous node is |math_node| or less. Furthermore, a
< node is discarded after a break if its type is |math_node| or more.
---
> |type| of the previous node is less than |math_node|. Furthermore, a
> node is discarded after a break if its type is |math_node| or~more.
2626c3012
< @d precedes_break(#)==(type(#)≤math_node)
---
> @d precedes_break(#)==(type(#)<math_node)
2647c3033
< will be the same as the parameter number, plus one.
---
> will be the same as the parameter number, plus~one.
2654c3040
<
---
>
2656,2657c3042,3043
< @d mu_glue=98 {|subtype| for mskip glue}
< @d cond_math_glue=99 {special |subtype| to suppress glue in the next node}
---
> @d cond_math_glue=98 {special |subtype| to suppress glue in the next node}
> @d mu_glue=99 {|subtype| for math glue}
2691a3078,3079
> The reference count in the copy is |null|, because there is assumed
> to be exactly one reference to the new specification.
2695,2698c3083,3086
< begin q←get_node(glue_spec_size);@/
< mem[q]←mem[p]; glue_ref_count(q)←null;@/
< width(q)←width(p); stretch(q)←stretch(p); shrink(q)←shrink(p);
< new_spec←q;
---
> begin q:=get_node(glue_spec_size);@/
> mem[q]:=mem[p]; glue_ref_count(q):=null;@/
> width(q):=width(p); stretch(q):=stretch(p); shrink(q):=shrink(p);
> new_spec:=q;
2701,2703c3089,3092
< @ And here's a function that creates a glue node for a given parameter;
< for example, |new_param_glue(disp_skip_code)| returns a pointer to a glue
< node for the current \.{\\dispskip}.
---
> @ And here's a function that creates a glue node for a given parameter
> identified by its code number; for example,
> |new_param_glue(line_skip_code)| returns a pointer to a glue node for the
> current \.{\\lineskip}.
2708,2712c3097,3101
< begin p←get_node(small_node_size); type(p)←glue_node; subtype(p)←n+1;
< leader_ptr(p)←null;@/
< q←@<Current |mem| equivalent of glue parameter number |n|@>@t@>;
< glue_ptr(p)←q; incr(glue_ref_count(q));
< new_param_glue←p;
---
> begin p:=get_node(small_node_size); type(p):=glue_node; subtype(p):=n+1;
> leader_ptr(p):=null;@/
> q:=@<Current |mem| equivalent of glue parameter number |n|@>@t@>;
> glue_ptr(p):=q; incr(glue_ref_count(q));
> new_param_glue:=p;
2720,2722c3109,3111
< begin p←get_node(small_node_size); type(p)←glue_node; subtype(p)←normal;
< leader_ptr(p)←null; glue_ptr(p)←q; incr(glue_ref_count(q));
< new_glue←p;
---
> begin p:=get_node(small_node_size); type(p):=glue_node; subtype(p):=normal;
> leader_ptr(p):=null; glue_ptr(p):=q; incr(glue_ref_count(q));
> new_glue:=p;
2725c3114
< @ Still another subroutine is needed: this one is sort of a combination
---
> @ Still another subroutine is needed: This one is sort of a combination
2734,2736c3123,3125
< begin temp_ptr←new_spec(@<Current |mem| equivalent of glue parameter...@>);
< p←new_glue(temp_ptr); glue_ref_count(temp_ptr)←null; subtype(p)←n+1;
< new_skip_param←p;
---
> begin temp_ptr:=new_spec(@<Current |mem| equivalent of glue parameter...@>);
> p:=new_glue(temp_ptr); glue_ref_count(temp_ptr):=null; subtype(p):=n+1;
> new_skip_param:=p;