This file is part of web2w. Copyright 2017 Martin Ruckert web2w is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. web2w is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with web2w. If not, see . Martin Ruckert, Hochschule Muenchen, Lothstrasse 64, 80336 Muenchen --- hint.w 2017-07-28 10:40:38.023223082 +0200 +++ tex.w 2017-07-28 10:43:49.801661332 +0200 @@ -73,11 +73,6 @@ \def\(#1){} % this is used to make section names sort themselves better \def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@> -\outer\def\N#1. \[#2]#3.{\MN#1.\vfil\eject % begin starred section - \def\rhead{PART #2:\uppercase{#3}} % define running headline - \message{*\modno} % progress report - \edef\next{\write\cont{\Z{\?#2]#3}{\modno}{\the\pageno}}}\next - \ifon\startsection{\bf\ignorespaces#3.\quad}\ignorespaces} \let\?=\relax % we want to be able to \write a \? \def\title{\TeX82} @@ -90,6 +85,22 @@ \def\glob{13} % this should be the section number of "" \def\gglob{20, 26} % this should be the next two sections of "" +\def\.#1{\leavevmode\hbox{\tentex % typewriter type for strings + \let\\=\BS % backslash in a string + \let\'=\RQ % right quote in a string + \let\`=\LQ % left quote in a string + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + \let\~=\TL % tilde in a string + \let\ =\SP % space in a string + \let\_=\UL % underline in a string + \let\&=\AM % ampersand in a string + #1\kern.05em}} +\def\^{\ifmmode\mathchar"222 \else\char`^ \fi} % pointer or hat +\def\LQ{{\tt\char'22}} % left quote in a string +\def\RQ{{\tt\char'23}} % right quote in a string +\def\dotdot{\mathrel{.\,.}} % double dot, used only in math mode +@s dotdot TeX @* Introduction. This is \TeX, a document compiler intended to produce typesetting of high quality. @@ -188,7 +199,7 @@ known as `\TeX' [cf.~Stanford Computer Science report CS1027, November 1984]. -@d banner "This is TeX, Version 3.14159265" /*printed when \TeX\ starts*/ +@d banner "This is TeX, Version 3.14159265 (HINT)" /*printed when \TeX\ starts*/ @ Different \PASCAL s have slightly different conventions, and the present @!@:PASCAL H}{\ph@> @@ -318,12 +329,33 @@ @^system dependencies@> @^overflow in arithmetic@> +@s int8_t int +@s uint8_t int +@s uint16_t int +@s halfword int +@s in TeX +@s line normal +@s to do + @= -/*@&$C-,A+,D-*/ /*no range check, catch arithmetic overflow, no debug overhead*/ -#ifdef @!DEBUG -/*@&$C+,D+*/ +#include +#include +#include +#include +#include +#include + +#define odd(X) ((X)&1) +#define chr(X) ((unsigned char)(X)) +#define ord(X) ((int)(X)) + +#if __SIZEOF_FLOAT__==4 +typedef float float32_t; +#else +#error float type must have size 4 #endif - /*but turn everything on when debugging*/ + +@h @ This \TeX\ implementation conforms to the rules of the {\sl Pascal User @:PASCAL}{\PASCAL@> @@ -757,7 +789,7 @@ @^system dependencies@> @= -uint8_t @!name_of_file0[file_name_size], *const @!name_of_file = @!name_of_file0-1;@;@/ +uint8_t @!name_of_file0[file_name_size+1]={0}, *const @!name_of_file = @!name_of_file0-1;@;@/ /*on some systems this may be a \&{record} variable*/ uint8_t @!name_length;@/ /*this many characters are actually relevant in |name_of_file| (the rest are blank)*/ @@ -790,32 +822,32 @@ @p bool a_open_in(alpha_file *f) /*open a text file for input*/ -{@+reset((*f), name_of_file,"/O");return reset_OK((*f)); +{@+reset((*f), name_of_file,"r");return reset_OK((*f)); } @# bool a_open_out(alpha_file *f) /*open a text file for output*/ -{@+rewrite((*f), name_of_file,"/O");return rewrite_OK((*f)); +{@+rewrite((*f), name_of_file,"w");return rewrite_OK((*f)); } @# bool b_open_in(byte_file *f) /*open a binary file for input*/ -{@+reset((*f), name_of_file,"/O");return reset_OK((*f)); +{@+reset((*f), name_of_file,"rb");return reset_OK((*f)); } @# bool b_open_out(byte_file *f) /*open a binary file for output*/ -{@+rewrite((*f), name_of_file,"/O");return rewrite_OK((*f)); +{@+rewrite((*f), name_of_file,"wb");return rewrite_OK((*f)); } @# bool w_open_in(word_file *f) /*open a word file for input*/ -{@+reset((*f), name_of_file,"/O");return reset_OK((*f)); +{@+reset((*f), name_of_file,"rb");return reset_OK((*f)); } @# bool w_open_out(word_file *f) /*open a word file for output*/ -{@+rewrite((*f), name_of_file,"/O");return rewrite_OK((*f)); +{@+rewrite((*f), name_of_file,"wb");return rewrite_OK((*f)); } @ Files can be closed with the \ph\ routine `|close(f)|', which @@ -938,8 +970,8 @@ @:PASCAL H}{\ph@> @^system dependencies@> -@d t_open_in reset(term_in,"TTY:","/O/I") /*open the terminal for text input*/ -@d t_open_out rewrite(term_out,"TTY:","/O") /*open the terminal for text output*/ +@d t_open_in term_in.f=stdin /*open the terminal for text input*/ +@d t_open_out term_out.f=stdout /*open the terminal for text output*/ @ Sometimes it is necessary to synchronize the input/output mixture that happens on the user's terminal, and three system-dependent @@ -956,8 +988,8 @@ @:PASCAL H}{\ph@> @^system dependencies@> -@d update_terminal break(term_out) /*empty the terminal output buffer*/ -@d clear_terminal break_in(term_in, true) /*clear the terminal input buffer*/ +@d update_terminal fflush(term_out.f) /*empty the terminal output buffer*/ +@d clear_terminal fflush(term_in.f) /*clear the terminal input buffer*/ @d wake_up_terminal do_nothing /*cancel the user's cancellation of output*/ @ We need a special routine to read the first line of \TeX\ input from @@ -1103,10 +1135,11 @@ typedef uint8_t packed_ASCII_code; /*elements of |str_pool| array*/ @ @= -packed_ASCII_code @!str_pool[pool_size+1]; /*the characters*/ -pool_pointer @!str_start[max_strings+1]; /*the starting pointers*/ -pool_pointer @!pool_ptr; /*first unused position in |str_pool|*/ -str_number @!str_ptr; /*number of the current string being created*/ +@@; +packed_ASCII_code @!str_pool[pool_size+1]= @<|str_pool| initialization@>; /*the characters*/ +pool_pointer @!str_start[max_strings+1]= {@<|str_start| initialization@>}; /*the starting pointers*/ +pool_pointer @!pool_ptr=@<|pool_ptr| initialization@>; /*first unused position in |str_pool|*/ +str_number @!str_ptr=@<|str_ptr| initialization@>; /*number of the current string being created*/ pool_pointer @!init_pool_ptr; /*the starting value of |pool_ptr|*/ str_number @!init_str_ptr; /*the starting value of |str_ptr|*/ @@ -1231,11 +1264,11 @@ @= for (k=0; k<=255; k++) - {@+if ((@)) - {@+append_char('^');append_char('^'); + { if (@[@@]) + { append_char('^');append_char('^'); if (k < 0100) append_char(k+0100)@; else if (k < 0200) append_char(k-0100)@; - else{@+app_lc_hex(k/16);app_lc_hex(k%16); + else{ app_lc_hex(k/16);app_lc_hex(k%16); } } else append_char(k); @@ -1289,7 +1322,7 @@ a_close(&pool_file);return false; } @= -name_of_file=pool_name; /*we needn't set |name_length|*/ +{@+int k;@+for(k=1; k<=file_name_size;k++)name_of_file[k]=pool_name[k-1];@+} /*we needn't set |name_length|*/ if (a_open_in(&pool_file)) {@+c=false; @/do@+{@= {@+if (eof(pool_file)) bad_pool("! TEX.POOL has no check sum."); @.TEX.POOL has no check sum@> -read(pool_file, m, n); /*read two digits of string length*/ +read(pool_file, m);@+read(pool_file, n); /*read two digits of string length*/ if (m== '*' ) @@; else{@+if ((xord[m] < '0')||(xord[m] > '9')||@| (xord[n] < '0')||(xord[n] > '9')) @@ -1411,12 +1444,30 @@ by changing |wterm|, |wterm_ln|, and |wterm_cr| in this section. @^system dependencies@> -@d wterm(X) write(term_out, X) -@d wterm_ln(...) write_ln(term_out,__VA_ARGS__) -@d wterm_cr write_ln(term_out) -@d wlog(...) write(log_file,__VA_ARGS__) -@d wlog_ln(...) write_ln(log_file,__VA_ARGS__) -@d wlog_cr write_ln(log_file) +@= +#define put(file) @[fwrite(&((file).d),sizeof((file).d),1,(file).f)@] +#define get(file) @[fread(&((file).d),sizeof((file).d),1,(file).f)@] + +#define reset(file,name,mode) @[((file).f=fopen((char *)(name)+1,mode),\ + (file).f!=NULL?get(file):0)@] +#define rewrite(file,name,mode) @[((file).f=fopen((char *)(name)+1,mode))@] +#define close(file) @[fclose((file).f)@] +#define eof(file) @[feof((file).f)@] +#define eoln(file) @[((file).d=='\n'||eof(file))@] +#define erstat(file) @[((file).f==NULL?-1:ferror((file).f))@] + +#define read(file,x) @[((x)=(file).d,get(file))@] +#define read_ln(file) @[do get(file); while (!eoln(file))@] + +#define write(file, format,...) @[fprintf(file.f,format,## __VA_ARGS__)@] +#define write_ln(file,...) @[write(file,__VA_ARGS__"\n")@] + +#define wterm(format,...) @[write(term_out,format, ## __VA_ARGS__)@] +#define wterm_ln(format,...) @[wterm(format "\n", ## __VA_ARGS__)@] +#define wterm_cr @[write(term_out,"\n")@] +#define wlog(format, ...) @[write(log_file,format, ## __VA_ARGS__)@] +#define wlog_ln(format, ...) @[wlog(format "\n", ## __VA_ARGS__)@] +#define wlog_cr @[write(log_file,"\n")@] @ To end a line of text output, we call |print_ln|. @@ -1447,7 +1498,7 @@ {@+print_ln();return; } switch (selector) { -case term_and_log: {@+wterm(xchr[s]);wlog(xchr[s]); +case term_and_log: {@+wterm("%c",xchr[s]);wlog("%c",xchr[s]); incr(term_offset);incr(file_offset); if (term_offset==max_print_line) {@+wterm_cr;term_offset=0; @@ -1456,17 +1507,17 @@ {@+wlog_cr;file_offset=0; } } @+break; -case log_only: {@+wlog(xchr[s]);incr(file_offset); +case log_only: {@+wlog("%c",xchr[s]);incr(file_offset); if (file_offset==max_print_line) print_ln(); } @+break; -case term_only: {@+wterm(xchr[s]);incr(term_offset); +case term_only: {@+wterm("%c",xchr[s]);incr(term_offset); if (term_offset==max_print_line) print_ln(); } @+break; case no_print: do_nothing;@+break; case pseudo: if (tally < trick_count) trick_buf[tally%error_line]=s;@+break; case new_string: {@+if (pool_ptr < pool_size) append_char(s); } @+break; /*we drop characters if the string space is full*/ -default:write(write_file[selector], xchr[s]); +default:write(write_file[selector],"%c", xchr[s]); } @/ incr(tally); } @@ -1509,6 +1560,10 @@ } } +void print_str(char *s) /* the simple version */ +{while (*s!=0) print_char(*s++);@+ +} + @ 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: @@ -1531,7 +1586,7 @@ character positions. @= -wterm(banner); +wterm("%s",banner); if (format_ident==0) wterm_ln(" (no format preloaded)"); else{@+slow_print(format_ident);print_ln(); } @@ -1541,10 +1596,10 @@ string appears at the beginning of a new line. @= -void print_nl(str_number @!s) /*prints string |s| at beginning of line*/ +void print_nl(char *@!s) /*prints string |s| at beginning of line*/ {@+if (((term_offset > 0)&&(odd(selector)))||@| ((file_offset > 0)&&(selector >= log_only))) print_ln(); -print(s); +print_str(s); } @ The procedure |print_esc| prints a string that is preceded by @@ -1681,10 +1736,10 @@ @* Reporting errors. When something anomalous is detected, \TeX\ typically does something like this: $$\vbox{\halign{#\hfil\cr -|print_err(@[@<|"Something anomalous has been detected"|@>@]);|\cr -|help3(@[@<|"This is the first line of my offer to help."|@>@])|\cr -|(@[@<|"This is the second line. I'm trying to"|@>@])|\cr -|(@[@<|"explain the best way for you to proceed."|@>@]);|\cr +|print_err("Something anomalous has been detected");|\cr +|help3("This is the first line of my offer to help.")|\cr +|("This is the second line. I'm trying to")|\cr +|("explain the best way for you to proceed.");|\cr |error;|\cr}}$$ A two-line help message would be given using |help2|, etc.; these informal helps should use simple vocabulary that complements the words used in the @@ -1788,10 +1843,10 @@ void close_files_and_terminate(void);@/ void clear_for_error_prompt(void);@/ void give_err_help(void);@/ -@t\4\hskip-\fontdimen2\font@>@; #ifdef @!DEBUG -@+void debug_help(void) - ;@; +void debug_help(void); +#else +#define debug_help() do_nothing #endif @ Individual lines of help are recorded in the array |help_line|, which @@ -1813,7 +1868,7 @@ @d help6 @+{@+help_ptr=6;hlp6 /*use this with six help lines*/ @= -str_number @!help_line[6]; /*helps for the next |error|*/ +char *@!help_line[6]; /*helps for the next |error|*/ uint8_t @!help_ptr; /*the number of help lines present*/ bool @!use_err_help; /*should the |err_help| list be shown?*/ @@ -1832,7 +1887,7 @@ @= void jump_out(void) -{@+goto end_of_TEX; +{@+ close_files_and_terminate(); exit(0); } @ Here now is the general |error| routine. @@ -1972,7 +2027,7 @@ else{@+if (help_ptr==0) help2("Sorry, I don't know how to help in this situation.")@/ @t\kern1em@>("Maybe you should try asking a human?"); - @/do@+{decr(help_ptr);print(help_line[help_ptr]);print_ln(); + @/do@+{decr(help_ptr);print_str(help_line[help_ptr]);print_ln(); }@+ while (!(help_ptr==0)); } help4("Sorry, I already gave what help I could...")@/ @@ -2017,16 +2072,12 @@ @d succumb {@+if (interaction==error_stop_mode) interaction=scroll_mode; /*no more interaction*/ if (log_opened) error(); - -#ifdef @!DEBUG -if (interaction > batch_mode) debug_help(); -#endif -@;@/ + if (interaction > batch_mode) debug_help(); history=fatal_error_stop;jump_out(); /*irrecoverable error*/ } @= -void fatal_error(str_number @!s) /*prints |s|, and that's it*/ +void fatal_error(char *@!s) /*prints |s|, and that's it*/ {@+normalize_selector();@/ print_err("Emergency stop");help1(s);succumb; @.Emergency stop@> @@ -2035,11 +2086,11 @@ @ Here is the most dreaded error message. @= -void overflow(str_number @!s, int @!n) /*stop due to finiteness*/ +void overflow(char *@!s, int @!n) /*stop due to finiteness*/ {@+normalize_selector(); print_err("TeX capacity exceeded, sorry ["); @.TeX capacity exceeded ...@> -print(s);print_char('=');print_int(n);print_char(']'); +print_str(s);print_char('=');print_int(n);print_char(']'); help2("If you really absolutely need more capacity,")@/ ("you can ask a wizard to enlarge me."); succumb; @@ -2202,7 +2253,7 @@ The present implementation of \TeX\ does not check for overflow when @^overflow in arithmetic@> dimensions are added or subtracted. This could be done by inserting a -few dozen tests of the form `\ignorespaces|if (x >= 010000000000) +few dozen tests of the form `\ignorespaces|if (x >= 010000000000)@/ @t\\{report\_overflow}@>|', but the chance of overflow is so remote that such tests do not seem worthwhile. @@ -2332,12 +2383,12 @@ @d set_glue_ratio_zero(X) X=0.0 /*store the representation of zero ratio*/ @d set_glue_ratio_one(X) X=1.0 /*store the representation of unit ratio*/ -@d float(X) X /*convert from |glue_ratio| to type |double|*/ -@d unfloat(X) X /*convert from |double| to type |glue_ratio|*/ -@d float_constant(X) X.0 /*convert |int| constant to |double|*/ +@d float(X) ((double)(X)) /*convert from |glue_ratio| to type |double|*/ +@d unfloat(X) ((glue_ratio)(X)) /*convert from |double| to type |glue_ratio|*/ +@d float_constant(X) ((double)(X)) /*convert |int| constant to |double|*/ @= -typedef double glue_ratio; /*one-word representation of a glue expansion factor*/ +typedef float32_t @!glue_ratio; /*one-word representation of a glue expansion factor*/ @* Packed data. In order to make efficient use of storage space, \TeX\ bases its major data @@ -2500,6 +2551,7 @@ value represents a null pointer. \TeX\ does not assume that |mem[null]| exists. @d pointer halfword /*a flag or a location in |mem| or |eqtb|*/ +@s pointer int @d null min_halfword /*the null pointer*/ @= @@ -2549,7 +2601,14 @@ @= int @!var_used, @!dyn_used; /*how much memory is in use*/ - +#ifdef @!DEBUG +#define incr_dyn_used @[incr(dyn_used)@] +#define decr_dyn_used @[decr(dyn_used)@] +#else +#define incr_dyn_used +#define decr_dyn_used +#endif + @ Let's consider the one-word memory region first, since it's the simplest. The pointer variable |mem_end| holds the highest-numbered location of |mem| that has ever been used. The free locations of |mem| that @@ -2599,10 +2658,7 @@ } } link(p)=null; /*provide an oft-desired initialization of the new node*/ -#ifdef @!STAT -incr(dyn_used); -#endif -@; /*maintain statistics*/ +incr_dyn_used; /*maintain statistics*/ return p; } @@ -2612,10 +2668,7 @@ @d free_avail(X) /*single-word node liberation*/ {@+link(X)=avail;avail=X; - -#ifdef @!STAT -decr(dyn_used); -#endif + decr_dyn_used; } @ There's also a |fast_get_avail| routine, which saves the procedure-call @@ -2627,10 +2680,7 @@ {@+X=avail; /*avoid |get_avail| if possible, to save time*/ if (X==null) X=get_avail(); else{@+avail=link(X);link(X)=null; - -#ifdef @!STAT -incr(dyn_used); -#endif + incr_dyn_used; } } @@ -2644,9 +2694,7 @@ if (p!=null) {@+r=p; @/do@+{q=r;r=link(r); -#ifdef @!STAT -decr(dyn_used); -#endif + decr_dyn_used; }@+ while (!(r==null)); /*now |q| is the last node on the list*/ link(q)=avail;avail=p; } @@ -8168,7 +8216,7 @@ else pstack[n]=link(temp_head); incr(n); if (tracing_macros > 0) - {@+begin_diagnostic();print_nl(match_chr);print_int(n); + {@+begin_diagnostic();print_nl("");print(match_chr);print_int(n); print_str("<-");show_token_list(pstack[n-1], null, 1000); end_diagnostic(false); } @@ -9997,10 +10045,7 @@ |TEX_font_area|. These system area names will, of course, vary from place to place. @^system dependencies@> - -@d TEX_area TEX_area @.TeXinputs@> -@d TEX_font_area TEX_font_area @.TeXfonts@> @ Here now is the first of the system-dependent routines for file name scanning. @@ -10076,7 +10121,7 @@ for (j=str_start[n]; j<=str_start[n+1]-1; j++) append_to_name(so(str_pool[j])); for (j=str_start[e]; j<=str_start[e+1]-1; j++) append_to_name(so(str_pool[j])); if (k <= file_name_size) name_length=k;@+else name_length=file_name_size; -for (k=name_length+1; k<=file_name_size; k++) name_of_file[k]= ' ' ; +name_of_file[name_length+1]=0; } @ A messier routine is also needed, since format file names must be scanned @@ -10088,13 +10133,10 @@ @d format_default_length 20 /*length of the |TEX_format_default| string*/ @d format_area_length 11 /*length of its area part*/ @d format_ext_length 4 /*length of its `\.{.fmt}' part*/ -@d format_extension format_extension /*the extension, as a \.{WEB} constant*/ +@d format_extension_str ".fmt" /*the extension, as a \.{WEB} constant*/ @= -uint8_t @!TEX_format_default0[format_default_length], *const @!TEX_format_default = @!TEX_format_default0-1; - -@ @= -TEX_format_default="TeXformats:plain.fmt"; +ASCII_code @!TEX_format_default[1+format_default_length+1]=" TeXformats/plain.fmt"; @.TeXformats@> @.plain@> @^system dependencies@> @@ -10125,7 +10167,7 @@ for (j=format_default_length-format_ext_length+1; j<=format_default_length; j++) append_to_name(xord[TEX_format_default[j]]); if (k <= file_name_size) name_length=k;@+else name_length=file_name_size; -for (k=name_length+1; k<=file_name_size; k++) name_of_file[k]= ' ' ; +name_of_file[name_length+1]=0; } @ Here is the only place we use |pack_buffered_name|. This part of the program @@ -10149,7 +10191,7 @@ /*now try the system format file area*/ if (w_open_in(&fmt_file)) goto found; wake_up_terminal; - wterm_ln("Sorry, I can't find that format;"," will try PLAIN."); + wterm_ln("Sorry, I can't find that format; will try PLAIN."); @.Sorry, I can't find...@> update_terminal; } @@ -10255,17 +10297,17 @@ variables |cur_name|, |cur_area|, |cur_ext|, and |name_of_file| are ready for another attempt at file opening. -@p void prompt_file_name(str_number @!s, str_number @!e) +@p void prompt_file_name(char *@!s, str_number @!e) {@+ uint16_t k; /*index into |buffer|*/ if (interaction==scroll_mode) wake_up_terminal; -if (s==@[@<|"input file name"|@>@]) print_err("I can't find file `")@; +if (strcmp(s,"input file name")==0) print_err("I can't find file `")@; @.I can't find file x@> else print_err("I can't write on file `"); @.I can't write on file x@> print_file_name(cur_name, cur_area, cur_ext);print_str("'."); if (e==@[@<|".tex"|@>@]) show_context(); -print_nl("Please type another ");print(s); +print_nl("Please type another ");print_str(s); @.Please type...@> if (interaction < scroll_mode) fatal_error("*** (job aborted, file error in nonstop mode)"); @@ -10286,9 +10328,10 @@ } @ Here's an example of how these conventions are used. Whenever it is time to -ship out a box of stuff, we shall use the macro |ensure_dvi_open|. +ship out a box of stuff, we shall use |@|. -@d ensure_dvi_open if (output_file_name==0) +@= +if (output_file_name==0) {@+if (job_name==0) open_log_file(); pack_job_name(@[@<|".dvi"|@>@]); while (!b_open_out(&dvi_file)) @@ -10296,7 +10339,7 @@ output_file_name=b_make_name_string(&dvi_file); } -@= +@ @= byte_file @!dvi_file; /*the device-independent output goes here*/ str_number @!output_file_name; /*full name of the output file*/ str_number @!log_name; /*full name of the log file*/ @@ -10310,7 +10353,7 @@ {@+uint8_t old_setting; /*previous |selector| setting*/ int @!k; /*index into |months| and |buffer|*/ uint16_t @!l; /*end of first input line*/ -uint8_t @!months0[36], *const @!months = @!months0-1; /*abbreviations of month names*/ +@!ASCII_code @!months[]=" JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; /*abbreviations of month names*/ old_setting=selector; if (job_name==0) job_name=@[@<|"texput"|@>@]; @.texput@> @@ -10349,11 +10392,10 @@ } @ @= -{@+wlog(banner); +{@+wlog("%s",banner); slow_print(format_ident);print_str(" "); print_int(day);print_char(' '); -months="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; -for (k=3*month-2; k<=3*month; k++) wlog(months[k]); +for (k=3*month-2; k<=3*month; k++) wlog("%c",months[k]); print_char(' ');print_int(year);print_char(' '); print_two(time/60);print_char(':');print_two(time%60); } @@ -10453,7 +10495,8 @@ @ The rest of the \.{TFM} file may be regarded as a sequence of ten data arrays having the informal specification $$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2} -\vbox{\halign{\hfil\\{#}&$\,:\,$\arr#\hfil\cr +\def\PB#1{\arr#1} +\vbox{\halign{\hfil\\{#}&$\,:\,$#\hfil\cr header&|[0 dotdot lh-1]@t\\{stuff}@>|\cr char\_info&|[bc dotdot ec]char_info_word|\cr width&|[0 dotdot nw-1]fix_word|\cr @@ -11913,7 +11956,7 @@ @p void write_dvi(dvi_index @!a, dvi_index @!b) {@+int k; -for (k=a; k<=b; k++) write(dvi_file, dvi_buf[k]); +for (k=a; k<=b; k++) write(dvi_file, "%c", dvi_buf[k]); } @ To put a byte in the buffer without paying the cost of invoking a procedure @@ -12279,7 +12322,7 @@ @ @= dvi_h=0;dvi_v=0;cur_h=h_offset;dvi_f=null_font; -ensure_dvi_open; +@; if (total_pages==0) {@+dvi_out(pre);dvi_out(id_byte); /*output the preamble*/ @^preamble of \.{DVI} file@> @@ -13135,10 +13178,11 @@ computed by the normal rules; if it exceeds this limit, the reference point is simply moved down until the limiting depth is attained. -@d vpack(...) vpackage(__VA_ARGS__, max_dimen) /*special case of unconstrained depth*/ - @p - pointer vpackage(pointer @!p, scaled @!h, small_number @!m, scaled @!l) +#define vpack(...) @[vpackage(__VA_ARGS__, max_dimen)@] + /*special case of unconstrained depth*/ + +pointer vpackage(pointer @!p, scaled @!h, small_number @!m, scaled @!l) {@+ pointer r; /*the box node that will be returned*/ scaled @!w, @!d, @!x; /*width, depth, and natural height*/ @@ -15023,9 +15067,9 @@ the program would not have been so strange. @:PASCAL}{\PASCAL@> -@d math_spacing @;@/ +@d math_spacing_str @;@/ @t\hskip-35pt@> -math_spacing +"math_spacing" @t$ \hskip-35pt$@> @= @@ -16337,7 +16381,7 @@ should no longer be active; then |goto continue| if a line from |r| to |cur_p| is infeasible, otherwise record a new feasible break@>; } -end: +end: ; #ifdef @!STAT @; #endif @@ -16358,7 +16402,9 @@ halfword @!b; /*badness of test line*/ int @!d; /*demerits of test line*/ bool @!artificial_demerits; /*has |d| been forced to zero?*/ +#ifdef @!STAT pointer @!save_link; /*temporarily holds value of |link(cur_p)|*/ +#endif scaled @!shortfall; /*used in badness calculations*/ @ @= @@ -17790,7 +17836,7 @@ ligature and a |lig_ptr| field that points to a |char_node| or is |null|. We have $$|cur_r|=\cases{|character(lig_stack)|,&if |lig_stack > null|;\cr - |qi(hu[j+1])|,&if |lig_stack==null| and |j < n|;\cr + \hbox{|qi(hu[j+1])|},&if |lig_stack==null| and |j < n|;\cr bchar,&if |lig_stack==null| and |j==n|.\cr}$$ @= @@ -23733,7 +23779,7 @@ incompatible with the present \TeX\ table sizes, etc. @d too_small(X) {@+wake_up_terminal; - wterm_ln("---! Must increase the ", X); + wterm_ln("---! Must increase the %s", X); @.Must increase the x@> goto bad_fmt; } @@ -24246,14 +24292,13 @@ if (ready_already==314159) goto start_of_TEX; @@; if (bad > 0) - {@+wterm_ln("Ouch---my internal constants have been clobbered!", - "---case ", bad: 1); + {@+wterm_ln("Ouch---my internal constants have been clobbered!" + "---case %d", bad); @.Ouch...clobbered@> exit(0); } initialize(); /*set global variables to their starting values*/ #ifdef @!INIT -if (!get_strings_started()) exit(0); init_prim(); /*call |primitive| for each primitive*/ init_str_ptr=str_ptr;init_pool_ptr=pool_ptr;fix_date_and_time(); #endif @@ -24263,7 +24308,7 @@ history=spotless; /*ready to go!*/ main_control(); /*come to life*/ final_cleanup(); /*prepare for death*/ -end_of_TEX: close_files_and_terminate(); +close_files_and_terminate(); ready_already=0; return 0; } @@ -24305,34 +24350,33 @@ @= if (log_opened) - {@+wlog_ln( ' ' ); - wlog_ln("Here is how much of TeX's memory"," you used:"); + {@+wlog_ln(" "); + wlog_ln("Here is how much of TeX's memory you used:"); @.Here is how much...@> - wlog( ' ' , str_ptr-init_str_ptr: 1," string"); - if (str_ptr!=init_str_ptr+1) wlog( 's' ); - wlog_ln(" out of ", max_strings-init_str_ptr: 1);@/ - wlog_ln( ' ' , pool_ptr-init_pool_ptr: 1," string characters out of ", - pool_size-init_pool_ptr: 1);@/ - wlog_ln( ' ' , lo_mem_max-mem_min+mem_end-hi_mem_min+2: 1,@| - " words of memory out of ", mem_end+1-mem_min: 1);@/ - wlog_ln( ' ' , cs_count: 1," multiletter control sequences out of ", - hash_size: 1);@/ - wlog( ' ' , fmem_ptr: 1," words of font info for ", - font_ptr-font_base: 1," font"); - if (font_ptr!=font_base+1) wlog( 's' ); - wlog_ln(", out of ", font_mem_size: 1," for ", font_max-font_base: 1);@/ - wlog( ' ' , hyph_count: 1," hyphenation exception"); - if (hyph_count!=1) wlog( 's' ); - wlog_ln(" out of ", hyph_size: 1);@/ - wlog_ln( ' ' , max_in_stack: 1,"i,", max_nest_stack: 1,"n,",@| - max_param_stack: 1,"p,",@| - max_buf_stack+1: 1,"b,",@| - max_save_stack+6: 1,"s stack positions out of ",@| - stack_size: 1,"i,", - nest_size: 1,"n,", - param_size: 1,"p,", - buf_size: 1,"b,", - save_size: 1, 's' ); + wlog(" %d string", str_ptr-init_str_ptr); + if (str_ptr!=init_str_ptr+1) wlog( "s" ); + wlog_ln( " out of %d", max_strings-init_str_ptr);@/ + wlog_ln( " %d string characters out of %d", pool_ptr-init_pool_ptr, + pool_size-init_pool_ptr);@/ + wlog_ln(" %d words of memory out of %d", lo_mem_max-mem_min+mem_end-hi_mem_min+2,@| + mem_end+1-mem_min);@/ + wlog_ln(" %d multiletter control sequences out of %d", cs_count, hash_size);@/ + wlog(" %d words of font info for %d font", fmem_ptr, font_ptr-font_base); + if (font_ptr!=font_base+1) wlog("s"); + wlog_ln( ", out of %d for %d", font_mem_size, font_max-font_base);@/ + wlog(" %d hyphenation exception", hyph_count); + if (hyph_count!=1) wlog("s"); + wlog_ln( " out of %d", hyph_size);@/ + wlog_ln(" %di,%dn,%dp,%db,%ds stack positions out of %di,%dn,%dp,%db,%ds", + max_in_stack, max_nest_stack,@| + max_param_stack,@| + max_buf_stack+1,@| + max_save_stack+6,@| + stack_size, + nest_size, + param_size, + buf_size, + save_size ); } @ We get to the |final_cleanup| routine when \.{\\end} or \.{\\dump} has @@ -24452,13 +24496,13 @@ loop{@+wake_up_terminal; print_nl("debug # (-1 to exit):");update_terminal; @.debug \#@> - read(term_in, m); - if (m < 0) return; + if (fscanf(term_in.f," %d",&m)<1 || + m < 0) return; else if (m==0) {@+goto breakpoint; /*go to every label at least once*/ breakpoint: m=0;/*'BREAKPOINT'*/ } - else{@+read(term_in, n); + else{@+fscanf(term_in.f," %d",&n); switch (m) { @t\4@>@@; default:print_str("?"); @@ -24484,7 +24528,7 @@ case 10: slow_print(n);@+break; case 11: check_mem(n > 0);@+break; /*check wellformedness; print new busy locations if |n > 0|*/ case 12: search_mem(n);@+break; /*look for pointers to |n|*/ -case 13: {@+read(term_in, l);print_cmd_chr(n, l); +case 13: {@+fscanf(term_in.f," %d",&l);print_cmd_chr(n, l); } @+break; case 14: for (k=0; k<=n; k++) print(buffer[k]);@+break; case 15: {@+font_in_short_display=null_font;short_display(n); @@ -24619,8 +24663,8 @@ @ @= @t\4@>@@; void do_extension(void) -{@+int i, @!j, @!k; /*all-purpose integers*/ -pointer @!p, @!q, @!r; /*all-purpose pointers*/ +{@+int @!k; /*all-purpose integer*/ +pointer @!p; /*all-purpose pointer*/ switch (cur_chr) { case open_node: @@;@+break; case write_node: @@;@+break; @@ -24957,22 +25001,6 @@ itself will get a new section number. @^system dependencies@> -@* Index. -Here is where you can find all uses of each identifier in the program, -with underlined entries pointing to where the identifier was defined. -If the identifier is only one letter long, however, you get to see only -the underlined entries. {\sl All references are to section numbers instead of -page numbers.} - -This index also lists error messages and other aspects of the program -that you might want to look up some day. For example, the entry -for ``system dependencies'' lists all sections that should receive -special attention from people who are installing \TeX\ in a new -operating environment. A list of various things that can't happen appears -under ``this can't happen''. Approximately 40 sections are listed under -``inner loop''; these account for about 60\pct! of \TeX's running time, -exclusive of input and output. - @ Appendix: Replacement of the string pool file. @d str_0_255 "^^@@^^A^^B^^C^^D^^E^^F^^G^^H^^I^^J^^K^^L^^M^^N^^O"@/ "^^P^^Q^^R^^S^^T^^U^^V^^W^^X^^Y^^Z^^[^^\\^^]^^^^^_"@/ @@ -25757,10 +25785,10 @@ @d str_505 "else" @<|"else"|@>=@+505 @ -@d str_506 "TeXinputs:" +@d str_506 "TeXinputs/" @d TEX_area 506 @ -@d str_507 "TeXfonts:" +@d str_507 "TeXfonts/" @d TEX_font_area 507 @ @d str_508 ".fmt" @@ -26827,3 +26855,19 @@ @ @<|pool_ptr| initialization@>= str_start_668 @ @<|str_ptr| initialization@>= 668 + +@* Index. +Here is where you can find all uses of each identifier in the program, +with underlined entries pointing to where the identifier was defined. +If the identifier is only one letter long, however, you get to see only +the underlined entries. {\sl All references are to section numbers instead of +page numbers.} + +This index also lists error messages and other aspects of the program +that you might want to look up some day. For example, the entry +for ``system dependencies'' lists all sections that should receive +special attention from people who are installing \TeX\ in a new +operating environment. A list of various things that can't happen appears +under ``this can't happen''. Approximately 40 sections are listed under +``inner loop''; these account for about 60\pct! of \TeX's running time, +exclusive of input and output.