home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-28 | 50.1 KB | 1,410 lines |
- % mf.ch for C compilation with web2c, derived from various other change
- % files: INITEX.CH for Berkeley Unix TeX 1.1 (by Howard Trickey and
- % Pavel Curtis), by Paul Richards. web2c modifications by Tim Morgan,
- % et al.
- %
- % Modification history:
- % (more recent changes in ChangeLog)
- % Revision 2.0 90/3/27 20:20:00 ken
- % To version 2.0.
- % Revision 1.9 90/1/20 09:05:32 karl
- % To version 1.9.
- % Revision 1.8 89/11/30 09:08:16 karl
- % To version 1.8 (8-bit).
- % Revision 1.7 88/12/27 15:02:24 mackay
- % Cosmetic upgrade for version 1.7
- % Revision 1.6 88/12/11 15:59:15 morgan
- % Brought up to MF version 1.6
- % Revision 1.5 88/03/02 13:25:44 morgan
- % More C changes
- % Revision 1.4 87/12/09 12:50:00 hesse
- % Changes for C version
- % Revision 1.3 87/03/07 21:15:21 mackay
- % Minor changes found on archive version on SCORE
- % Revision 1.2 86/09/29 21:46:43 mackay
- % Made no-debug the default, and changed version number
- % to correspond with improved mf.web file
- % (Got rid of debug code to avoid bug in range check
- % code of VAX4.3 BSD and SUN3 version 3.1 Os pc interpreter)
- % Revision 1.0 86/01/31 15:46:08 richards
- % Released for MF 1.0;
- % Incorporates: New binary I/O library, separate optimized
- % arithmetic for takefraction/makefraction, new graphics interface.
-
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [0] WEAVE: print changes only.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- \def\botofcontents{\vskip 0pt plus 1fil minus 1.5in}
- @y
- \def\botofcontents{\vskip 0pt plus 1fil minus 1.5in}
- \let\maybe=\iffalse
- \def\title{\MF\ changes for C}
- \def\glob{13}\def\gglob{20, 25} % these are defined in module 1
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [1.2] banner
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d banner=='This is METAFONT, Version 2.71' {printed when \MF\ starts}
- @y
- @d banner=='This is METAFONT, Version 2.71' {more is printed later}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [1.7] Convert `debug..gubed' and `stat..tats' into #ifdefs.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
- @d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
- @f debug==begin
- @f gubed==end
- @#
- @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}
- @y
- @d stat==ifdef('STAT')
- @d tats==endif('STAT')
- @d debug==ifdef('DEBUG')
- @d gubed==endif('DEBUG')
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [1.8] Same, for `init..tini'.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
- @d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
- @y
- @d init==ifdef('INIMF')
- @d tini==endif('INIMF')
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Get rid of compiler directives.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @<Compiler directives@>=
- @{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead}
- @!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
- @y
- @<Compiler directives@>=
- @{No compiler directives for C.@}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [1.11] Compile-time constants. Although we only change a few of
- % these, listing them all makes the patch file for a big Metafont simpler.
- % 16K for BSD I/O; file_name_size is set from the system constant.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @<Constants...@>=
- @!mem_max=30000; {greatest index in \MF's internal |mem| array;
- must be strictly less than |max_halfword|;
- must be equal to |mem_top| in \.{INIMF}, otherwise |>=mem_top|}
- @!max_internal=100; {maximum number of internal quantities}
- @!buf_size=500; {maximum number of characters simultaneously present in
- current lines of open files; 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}
- @!screen_width=768; {number of pixels in each row of screen display}
- @!screen_depth=1024; {number of pixels in each column of screen display}
- @!stack_size=30; {maximum number of simultaneous input sources}
- @!max_strings=2000; {maximum number of strings; must not exceed |max_halfword|}
- @!string_vacancies=8000; {the minimum number of characters that should be
- available for the user's identifier names and strings,
- after \MF's own error messages are stored}
- @!pool_size=32000; {maximum number of characters in strings, including all
- error messages and help texts, and the names of all identifiers;
- must exceed |string_vacancies| by the total
- length of \MF's own strings, which is currently about 22000}
- @!move_size=5000; {space for storing moves in a single octant}
- @!max_wiggle=300; {number of autorounded points per cycle}
- @!gf_buf_size=800; {size of the output buffer, must be a multiple of 8}
- @!file_name_size=40; {file names shouldn't be longer than this}
- @!pool_name='MFbases:MF.POOL ';
- {string of length |file_name_size|; tells where the string pool appears}
- @.MFbases@>
- @!path_size=300; {maximum number of knots between breakpoints of a path}
- @!bistack_size=785; {size of stack for bisection algorithms;
- should probably be left at this value}
- @!header_size=100; {maximum number of \.{TFM} header words, times~4}
- @!lig_table_size=5000; {maximum number of ligature/kern steps, must be
- at least 255 and at most 32510}
- @!max_kerns=500; {maximum number of distinct kern amounts}
- @!max_font_dimen=50; {maximum number of \&{fontdimen} parameters}
- @y
- @d file_name_size == PATH_MAX
-
- @<Constants...@>=
- @!mem_max=262140; {greatest index in \MF's internal |mem| array;
- must be strictly less than |max_halfword|;
- must be equal to |mem_top| in \.{INIMF}, otherwise |>=mem_top|}
- @!max_internal=300; {maximum number of internal quantities}
- @!buf_size=3000; {maximum number of characters simultaneously present in
- current lines of open files; must not exceed |max_halfword|}
- @!error_line=79; {width of context lines on terminal error messages}
- @!half_error_line=50; {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}
- @!screen_width=1664; {number of pixels in each row of screen display}
- @!screen_depth=1200; {number of pixels in each column of screen display}
- @!stack_size=300; {maximum number of simultaneous input sources}
- @!max_strings=7500; {maximum number of strings; must not exceed |max_halfword|}
- @!string_vacancies=74000; {the minimum number of characters that should be
- available for the user's identifier names and strings,
- after \MF's own error messages are stored}
- @!pool_size=100000; {maximum number of characters in strings, including all
- error messages and help texts, and the names of all identifiers;
- must exceed |string_vacancies| by the total
- length of \MF's own strings, which is currently about 22000}
- @!move_size=20000; {space for storing moves in a single octant}
- @!max_wiggle=1000; {number of autorounded points per cycle}
- @!gf_buf_size=16384; {size of the output buffer, must be a multiple of 8}
- @!pool_name='mf.pool';
- {string of length |file_name_size|; tells where the string pool appears}
- @!path_size=1000; {maximum number of knots between breakpoints of a path}
- @!bistack_size=1500; {size of stack for bisection algorithms;
- should probably be left at this value}
- @!header_size=100; {maximum number of \.{TFM} header words, times~4}
- @!lig_table_size=15000; {maximum number of ligature/kern steps, must be
- at least 255 and at most 32510}
- @!max_kerns=2500; {maximum number of distinct kern amounts}
- @!max_font_dimen=50; {maximum number of \&{fontdimen} parameters}
- @!mem_top=262140; {largest index in the |mem| array dumped by \.{INIMF};
- must be substantially larger than |mem_min|
- and not greater than |mem_max|}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [1.12] Sensitive compile-time constants. mem_top is made into a
- % #define, so it is easier to change for the trap test.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d mem_min=0 {smallest index in the |mem| array, must not be less
- than |min_halfword|}
- @d mem_top==30000 {largest index in the |mem| array dumped by \.{INIMF};
- must be substantially larger than |mem_min|
- and not greater than |mem_max|}
- @d hash_size=2100 {maximum number of symbolic tokens,
- must be less than |max_halfword-3*param_size|}
- @d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
- @d max_in_open=6 {maximum number of input files and error insertions that
- can be going on simultaneously}
- @d param_size=150 {maximum number of simultaneous macro parameters}
- @y
- @d mem_min=0 {smallest index in the |mem| array, must not be less
- than |min_halfword|}
- @d hash_size=9500 {maximum number of symbolic tokens,
- must be less than |max_halfword-3*param_size|}
- @d hash_prime=7919 {a prime number equal to about 85\pct! of |hash_size|}
- @d max_in_open=15 {maximum number of input files and error insertions that
- can be going on simultaneously}
- @d param_size=150 {maximum number of simultaneous macro parameters}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Use C macros for `incr' and `decr'.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d incr(#) == #:=#+1 {increase a variable by unity}
- @d decr(#) == #:=#-1 {decrease a variable by unity}
- @y
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] The text_char type is used as an array index into xord. The
- % default type `char' produces signed integers, which are bad array
- % indices in C.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- @x
- @d text_char == char {the data type of characters in text files}
- @y
- @d text_char == ASCII_code {the data type of characters in text files}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [1.22] Allow any character as input.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @^character set dependencies@>
- @^system dependencies@>
-
- @<Set init...@>=
- for i:=0 to @'37 do xchr[i]:=' ';
- for i:=@'177 to @'377 do xchr[i]:=' ';
- @y
- @^character set dependencies@>
- @^system dependencies@>
-
- @d tab = @'11 { ASCII horizontal tab }
- @d form_feed = @'14 { ASCII form feed }
-
- @<Set init...@>=
- for i:=0 to @'37 do xchr[i]:=chr(i);
- for i:=@'177 to @'377 do xchr[i]:=chr(i);
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [3.25] Remove file types we don't need.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- The program actually makes use also of a third kind of file, called a
- |word_file|, when dumping and reloading base information for its own
- initialization. We shall define a word file later; but it will be possible
- for us to specify simple operations on word files before they are defined.
-
- @y
- I/O in C is done using standard I/O. We will define the path numbers
- in an include file for C which are used in searching for files to be
- read. We'll define all the file types in C also.
- @z
-
- @x
- @!alpha_file=packed file of text_char; {files that contain textual data}
- @!byte_file=packed file of eight_bits; {files that contain binary data}
- @y
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [3.27] Do file opening in C.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ The \ph\ compiler with which the present version of \MF\ was prepared has
- extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
- we can write
- $$\vbox{\halign{#\hfil\qquad\hfil\cr
- |reset(f,@t\\{name}@>,'/O')|&for input;\cr
- |rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
- The `\\{name}' parameter, which is of type `\ignorespaces|packed
- array[@t\<\\{any}>@>] of text_char|', stands for the name of
- the external file that is being opened for input or output.
- Blank spaces that might appear in \\{name} are ignored.
-
- The `\.{/O}' parameter tells the operating system not to issue its own
- error messages if something goes wrong. If a file of the specified name
- cannot be found, or if such a file cannot be opened for some other reason
- (e.g., someone may already be trying to write the same file), we will have
- |@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows
- \MF\ to undertake appropriate corrective action.
- @:PASCAL H}{\ph@>
- @^system dependencies@>
-
- \MF's file-opening procedures return |false| if no file identified by
- |name_of_file| could be opened.
-
- @d reset_OK(#)==erstat(#)=0
- @d rewrite_OK(#)==erstat(#)=0
-
- @p function a_open_in(var @!f:alpha_file):boolean;
- {open a text file for input}
- begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f);
- end;
- @#
- function a_open_out(var @!f:alpha_file):boolean;
- {open a text file for output}
- begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f);
- end;
- @#
- function b_open_out(var @!f:byte_file):boolean;
- {open a binary file for output}
- begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f);
- end;
- @#
- function w_open_in(var @!f:word_file):boolean;
- {open a word file for input}
- begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f);
- end;
- @#
- function w_open_out(var @!f:word_file):boolean;
- {open a word file for output}
- begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f);
- end;
- @y
- @ All of the file opening functions are defined in C.
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [3.28] Do file closing in C.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ Files can be closed with the \ph\ routine `|close(f)|', which
- @^system dependencies@>
- should be used when all input or output with respect to |f| has been completed.
- This makes |f| available to be opened again, if desired; and if |f| was used for
- output, the |close| operation makes the corresponding external file appear
- on the user's area, ready to be read.
-
- @p procedure a_close(var @!f:alpha_file); {close a text file}
- begin close(f);
- end;
- @#
- procedure b_close(var @!f:byte_file); {close a binary file}
- begin close(f);
- end;
- @#
- procedure w_close(var @!f:word_file); {close a word file}
- begin close(f);
- end;
- @y
- @ And all the file closing routines as well.
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [3.30] Do `input_ln' in C.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- Standard \PASCAL\ says that a file should have |eoln| immediately
- before |eof|, but \MF\ needs only a weaker restriction: If |eof|
- occurs in the middle of a line, the system function |eoln| should return
- a |true| result (even though |f^| will be undefined).
-
- @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;
- end;
- @y
- We define |input_ln| in C, for efficiency.
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] `term_in' and `term_out' are standard input and output.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @<Glob...@>=
- @!term_in:alpha_file; {the terminal as an input file}
- @!term_out:alpha_file; {the terminal as an output file}
- @y
- @d term_in==stdin {the terminal as an input file}
- @d term_out==stdout {the terminal as an output file}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [3.32] We don't need to open the terminal files.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ Here is how to open the terminal files
- in \ph. The `\.{/I}' switch suppresses the first |get|.
- @^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}
- @y
- @ Here is how to open the terminal files. |t_open_out| does nothing.
- |t_open_in|, on the other hand, does the work of ``rescanning,'' or getting
- any command line arguments the user has provided. It's defined in C.
-
- @d t_open_out == {output already open for text output}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [3.33] Flushing output.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- these operations can be specified in \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}
- @y
- these operations can be specified with {\mc UNIX}. |update_terminal|
- does an |fflush| (via the macro |flush|). |clear_terminal| is redefined
- to do nothing, since the user should control the terminal.
- @^system dependencies@>
-
- @d update_terminal == flush (term_out)
- @d clear_terminal == do_nothing
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [3.36] Reading the command line.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ The following program does the required initialization
- without retrieving a possible command line.
- It should be clear how to modify this routine to deal with command lines,
- if the system permits them.
- @^system dependencies@>
-
- @p function init_terminal:boolean; {gets the terminal input started}
- label exit;
- begin t_open_in;
- 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;
- exit:end;
- @y
- @ The following program does the required initialization.
- Iff anything has been specified on the command line, then |t_open_in|
- will return with |last > first|.
- @^system dependencies@>
-
- @p
- function init_terminal:boolean; {gets the terminal input started}
- label exit;
- begin
- t_open_in;
- if last > first then begin
- loc := first;
- while (loc < last) and (buffer[loc]=' ') do
- incr(loc);
- if loc < last then begin
- init_terminal := true;
- goto exit;
- end;
- end;
- loop@+begin
- wake_up_terminal; write(term_out, '**'); update_terminal;
- @.**@>
- if not input_ln(term_in,true) then begin {this shouldn't happen}
- 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;
- exit:
- end;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [4.51] Open the pool file using a path, and can't do string
- % assignments directly. (`strcpy' and `strlen' work here because
- % `pool_name' is a constant string, and thus ends in a null and doesn't
- % start with a space.)
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- name_of_file:=pool_name; {we needn't set |name_length|}
- if a_open_in(pool_file) then
- @y
- vstrcpy (name_of_file+1, pool_name); {copy the string}
- name_of_file[0] := ' ';
- name_of_file[strlen (pool_name) + 1] := ' ';
- name_length := strlen (pool_name);
- if a_open_in (pool_file, MF_POOL_PATH) then
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [4.51,52,53] Make `TEX.POOL' lowercase in messages, and change how
- % it's read.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- else bad_pool('! I can''t read MF.POOL.')
- @y
- else bad_pool('! I can''t read mf.pool.')
- @z
-
- @x
- begin if eof(pool_file) then bad_pool('! MF.POOL has no check sum.');
- @.MF.POOL has no check sum@>
- read(pool_file,m,n); {read two digits of string length}
- @y
- begin if eof(pool_file) then bad_pool('! mf.pool has no check sum.');
- @.MF.POOL has no check sum@>
- read(pool_file,m); read(pool_file,n); {read two digits of string length}
- @z
-
- @x
- bad_pool('! MF.POOL line doesn''t begin with two digits.');
- @y
- bad_pool('! mf.pool line doesn''t begin with two digits.');
- @z
-
- @x
- bad_pool('! MF.POOL check sum doesn''t have nine digits.');
- @y
- bad_pool('! mf.pool check sum doesn''t have nine digits.');
- @z
-
- @x
- done: if a<>@$ then bad_pool('! MF.POOL doesn''t match; TANGLE me again.');
- @y
- done: if a<>@$ then bad_pool('! mf.pool doesn''t match; tangle me again.');
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Print rest of banner, eliminate the misleading message ``(no base
- % preloaded)''.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- wterm(banner);
- if base_ident=0 then wterm_ln(' (no base preloaded)')
- else begin slow_print(base_ident); print_ln;
- end;
- @y
- wterm (banner);
- wterm (version_string);
- if base_ident>0 then slow_print(base_ident); print_ln;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Eliminate non-local goto.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @<Error hand...@>=
- procedure jump_out;
- begin goto end_of_MF;
- end;
- @y
- @d do_final_end==begin
- update_terminal;
- ready_already:=0;
- if (history <> spotless) and (history <> warning_issued) then
- uexit(1)
- else
- uexit(0);
- end
- @<Error hand...@>=
- procedure jump_out;
- begin
- close_files_and_terminate;
- do_final_end;
- end;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [6.79] Handle the switch-to-editor option.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- line ready to be edited. But such an extension requires some system
- wizardry, so the present implementation simply types out the name of the
- file that should be
- edited and the relevant line number.
- @^system dependencies@>
-
- There is a secret `\.D' option available when the debugging routines haven't
- been commented~out.
- @^debugging@>
- @y
- line ready to be edited.
- We do this by calling the external procedure |call_edit| with a pointer to
- the filename, its length, and the line number.
- However, here we just set up the variables that will be used as arguments,
- since we don't want to do the switch-to-editor until after \MF\ has closed
- its files.
- @^system dependencies@>
-
- There is a secret `\.D' option available when the debugging routines have
- not been commented out.
- @^debugging@>
- @d edit_file==input_stack[file_ptr]
- @z
- @x
- "E": if file_ptr>0 then
- begin print_nl("You want to edit file ");
- @.You want to edit file x@>
- slow_print(input_stack[file_ptr].name_field);
- print(" at line "); print_int(line);@/
- interaction:=scroll_mode; jump_out;
- @y
- "E": if file_ptr>0 then
- begin
- edit_name_start:=str_start[edit_file.name_field];
- edit_name_length:=str_start[edit_file.name_field+1] -
- str_start[edit_file.name_field];
- edit_line:=line;
- jump_out;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [9.153] Make it easy to build a bigger Metafont. (Nothing is changed
- % in the basic version.)
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d min_quarterword=0 {smallest allowable value in a |quarterword|}
- @d max_quarterword=255 {largest allowable value in a |quarterword|}
- @d min_halfword==0 {smallest allowable value in a |halfword|}
- @d max_halfword==65535 {largest allowable value in a |halfword|}
- @y
- @d min_quarterword=0 {smallest allowable value in a |quarterword|}
- @d max_quarterword=255 {largest allowable value in a |quarterword|}
- @d min_halfword==0 {smallest allowable value in a |halfword|}
- @d max_halfword==262143 {largest allowable value in a |halfword|}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Efficiency.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ The operation of subtracting |min_halfword| occurs rather frequently in
- \MF, so it is convenient to abbreviate this operation by using the macro
- |ho| defined here. \MF\ will run faster with respect to compilers that
- don't optimize the expression `|x-0|', if this macro is simplified in the
- obvious way when |min_halfword=0|. Similarly, |qi| and |qo| are used for
- input to and output from quarterwords.
- @^system dependencies@>
-
- @d ho(#)==#-min_halfword
- {to take a sixteen-bit item from a halfword}
- @d qo(#)==#-min_quarterword {to read eight bits from a quarterword}
- @d qi(#)==#+min_quarterword {to store eight bits in a quarterword}
-
- @y
- @ The operation of subtracting |min_halfword| occurs rather frequently in
- \MF, so it is convenient to abbreviate this operation by using the macro
- |ho| defined here. \MF\ will run faster with respect to compilers that
- don't optimize the expression `|x-0|', if this macro is simplified in the
- obvious way when |min_halfword=0|. Similarly, |qi| and |qo| are used for
- input to and output from quarterwords.
- So they have been simplified here in the obvious way.
- @^system dependencies@>
-
- @d ho(#)==#
- @d qo(#)==#
- @d qi(#)==#
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] We've put the memory structure into the include file `texmf.h',
- % since it's too hard to translate automatically. Also, remove the
- % `word_file' type.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @!two_halves = packed record@;@/
- @!rh:halfword;
- case two_choices of
- 1: (@!lh:halfword);
- 2: (@!b0:quarterword; @!b1:quarterword);
- end;
- @!four_quarters = packed record@;@/
- @!b0:quarterword;
- @!b1:quarterword;
- @!b2:quarterword;
- @!b3:quarterword;
- end;
- @!memory_word = record@;@/
- case three_choices of
- 1: (@!int:integer);
- 2: (@!hh:two_halves);
- 3: (@!qqqq:four_quarters);
- end;
- @!word_file = file of memory_word;
- @y
- @=#include "texmfmem.h";@>
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Fix an unsigned/signed problem in getnode.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- if r>p+1 then @<Allocate from the top of node |p| and |goto found|@>;
- @y
- if r>toint(p+1) then @<Allocate from the top of node |p| and |goto found|@>;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [11.178] Change the word `free' so that it doesn't conflict with the
- % standard C library routine of the same name.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- been included. (You may want to decrease the size of |mem| while you
- @^debugging@>
- are debugging.)
- @y
- been included. (You may want to decrease the size of |mem| while you
- @^debugging@>
- are debugging.)
-
- @d free==free_arr
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Eliminate two unsigned comparisons to zero.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- repeat if (p>=lo_mem_max)or(p<mem_min) then clobbered:=true
- else if (rlink(p)>=lo_mem_max)or(rlink(p)<mem_min) then clobbered:=true
- @y
- repeat if (p>=lo_mem_max) then clobbered:=true
- else if (rlink(p)>=lo_mem_max) then clobbered:=true
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [12.194] Do `fix_date_and_time' in C.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ The following procedure, which is called just before \MF\ initializes its
- input and output, establishes the initial values of the date and time.
- @^system dependencies@>
- Since standard \PASCAL\ cannot provide such information, something special
- is needed. The program here simply specifies July 4, 1776, at noon; but
- users probably want a better approximation to the truth.
-
- Note that the values are |scaled| integers. Hence \MF\ can no longer
- be used after the year 32767.
-
- @p procedure fix_date_and_time;
- begin internal[time]:=12*60*unity; {minutes since midnight}
- internal[day]:=4*unity; {fourth day of the month}
- internal[month]:=7*unity; {seventh month of the year}
- internal[year]:=1776*unity; {Anno Domini}
- end;
- @y
- @ The following procedure, which is called just before \MF\ initializes its
- input and output, establishes the initial values of the date and time.
- It is calls an externally defined |date_and_time|, even though it could
- be done from Pascal.
- The external procedure also sets up interrupt catching.
- @^system dependencies@>
-
- Note that the values are |scaled| integers. Hence \MF\ can no longer
- be used after the year 32767.
-
- @p procedure fix_date_and_time;
- begin
- date_and_time(internal[time],internal[day],internal[month],internal[year]);
- internal[time] := internal[time] * unity;
- internal[day] := internal[day] * unity;
- internal[month] := internal[month] * unity;
- internal[year] := internal[year] * unity;
- end;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [12.199] Allow <tab> and <form feed> as input.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- for k:=0 to " "-1 do char_class[k]:=invalid_class;
- for k:=127 to 255 do char_class[k]:=invalid_class;
- @y
- for k:=0 to " "-1 do char_class[k]:=invalid_class;
- for k:=127 to 255 do char_class[k]:=invalid_class;
- char_class[tab]:=space_class;
- char_class[form_feed]:=space_class;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [\approx 329] |valid_range| uses |abs|, which we have defined as a C
- % macro. Some C preprocessors cannot expand the giant argument here.
- % So we add a temporary.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @p procedure edge_prep(@!ml,@!mr,@!nl,@!nr:integer);
- var @!delta:halfword; {amount of change}
- @y
- @p procedure edge_prep(@!ml,@!mr,@!nl,@!nr:integer);
- var @!delta:halfword; {amount of change}
- temp:integer;
- @z
-
- @x
- if not valid_range(m_min(cur_edges)+m_offset(cur_edges)-zero_field) or@|
- not valid_range(m_max(cur_edges)+m_offset(cur_edges)-zero_field) then
- @y
- temp := m_offset (cur_edges) - zero_field;
- if not valid_range (m_min (cur_edges) + temp)
- or not valid_range (m_max (cur_edges) + temp)
- then
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [\approx 530] |make_fraction| and |take_fraction| are defined as C
- % macros, to make the parameters work right. Their expansions are too
- % long for some preprocessors, just as in the previous change.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- alpha:=take_fraction(take_fraction(major_axis,
- make_fraction(gamma,beta)),n_cos)@|
- -take_fraction(take_fraction(minor_axis,
- make_fraction(delta,beta)),n_sin);
- alpha:=(alpha+half_unit) div unity;
- gamma:=pyth_add(take_fraction(major_axis,n_cos),
- take_fraction(minor_axis,n_sin));
- @y
- alpha := make_fraction (gamma, beta);
- alpha := take_fraction (major_axis, alpha);
- alpha := take_fraction (alpha, n_cos);
- alpha := (alpha+half_unit) div unity;
- gamma := take_fraction (minor_axis, n_sin);
- gamma := pyth_add (take_fraction (major_axis, n_cos), gamma);
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [27.564] The window functions are defined externally, in C.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @p function init_screen:boolean;
- begin init_screen:=false;
- end;
- @#
- procedure update_screen; {will be called only if |init_screen| returns |true|}
- begin @!init wlog_ln('Calling UPDATESCREEN');@+tini {for testing only}
- end;
- @y
- {These functions/procedures are defined externally in C.}
- @z
-
- @x
- @p procedure blank_rectangle(@!left_col,@!right_col:screen_col;
- @!top_row,@!bot_row:screen_row);
- var @!r:screen_row;
- @!c:screen_col;
- begin @{@+for r:=top_row to bot_row-1 do
- for c:=left_col to right_col-1 do
- screen_pixel[r,c]:=white;@+@}@/
- @!init wlog_cr; {this will be done only after |init_screen=true|}
- wlog_ln('Calling BLANKRECTANGLE(',left_col:1,',',
- right_col:1,',',top_row:1,',',bot_row:1,')');@+tini
- end;
- @y
- {Same thing}
- @z
-
- @x
- @p procedure paint_row(@!r:screen_row;@!b:pixel_color;var @!a:trans_spec;
- @!n:screen_col);
- var @!k:screen_col; {an index into |a|}
- @!c:screen_col; {an index into |screen_pixel|}
- begin @{ k:=0; c:=a[0];
- repeat incr(k);
- repeat screen_pixel[r,c]:=b; incr(c);
- until c=a[k];
- b:=black-b; {$|black|\swap|white|$}
- until k=n;@+@}@/
- @!init wlog('Calling PAINTROW(',r:1,',',b:1,';');
- {this is done only after |init_screen=true|}
- for k:=0 to n do
- begin wlog(a[k]:1); if k<>n then wlog(',');
- end;
- wlog_ln(')');@+tini
- end;
- @y
- {Same thing}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.765] Area and extension rules.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ The file names we shall deal with for illustrative purposes have the
- following structure: If the name contains `\.>' or `\.:', the file area
- consists of all characters up to and including the final such character;
- otherwise the file area is null. If the remaining file name contains
- `\..', the file extension consists of all such characters from the first
- remaining `\..' to the end, otherwise the file extension is null.
- @^system dependencies@>
-
- We can scan such file names easily by using two global variables that keep track
- of the occurrences of area and extension delimiters:
-
- @<Glob...@>=
- @!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any}
- @!ext_delimiter:pool_pointer; {the relevant `\..', if any}
- @y
- @ The file names we shall deal with for illustrative purposes have the
- following structure: If the name contains `\./', the file area
- consists of all characters up to and including the final such character;
- otherwise the file area is null. If the remaining file name contains
- `\..', the file extension consists of all such characters from the first
- remaining `\..' to the end, otherwise the file extension is null.
- @^system dependencies@>
-
- We can scan such file names easily by using two global variables that keep
- track of the occurrences of area and extension delimiters:
-
- @<Glob...@>=
- @!area_delimiter:pool_pointer; {the most recent `\./', if any}
- @!ext_delimiter:pool_pointer; {the most recent `\..', if any}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.766] MF area directories.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d MF_area=="MFinputs:"
- @.MFinputs@>
- @y
- In C, the default paths are specified in a separate
- file, \.{site.h}. The file opening procedures do path searching
- based either on those default paths, or on paths given by the user
- in environment variables.
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.768] more_name
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- begin if c=" " then more_name:=false
- else begin if (c=">")or(c=":") then
- @y
- begin if (c=" ")or(c=tab) then more_name:=false
- else begin if (c="/") then
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.771] In pack_file_name, leave room for the extra null we append at
- % the end of a filename in make_c_string.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- if k<=file_name_size then name_length:=k@+else name_length:=file_name_size;
- @y
- if k<file_name_size then name_length:=k@+else name_length:=file_name_size-1;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.772] The default base.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d base_default_length=18 {length of the |MF_base_default| string}
- @d base_area_length=8 {length of its area part}
- @d base_ext_length=5 {length of its `\.{.base}' part}
- @y
- In C, we don't give the area part, instead depending
- on the path searching that will happen during file opening. Also, the
- length will be set in the main program.
-
- @d base_area_length=0 {length of its area part}
- @d base_ext_length=5 {length of its `\.{.base}' part}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.773] Where `plain.base' is.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @!MF_base_default:packed array[1..base_default_length] of char;
-
- @ @<Set init...@>=
- MF_base_default:='MFbases:plain.base';
- @y
- @!base_default_length: integer;
- @!MF_base_default: c_char_pointer;
-
- @ We set the name of the default format file and the length of that name
- in C, instead of Pascal, since we want them to depend on the name of the
- program.
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.775] Change to pack_buffered_name as with pack_file_name.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- if k<=file_name_size then name_length:=k@+else name_length:=file_name_size;
- @y
- if k<file_name_size then name_length:=k@+else name_length:=file_name_size-1;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.776] Base file opening: only try once, with path searching.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- pack_buffered_name(0,loc,j-1); {try first without the system file area}
- if w_open_in(base_file) then goto found;
- pack_buffered_name(base_area_length,loc,j-1);
- {now try the system base file area}
- if w_open_in(base_file) then goto found;
- @y
- pack_buffered_name(0,loc,j-1);
- if w_open_in(base_file) then goto found;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % (still [38.776]) Replace `PLAIN' in error messages with `default'.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- wterm_ln('Sorry, I can''t find that base;',' will try PLAIN.');
- @y
- wterm_ln('Sorry, I can''t find that base;',' will try the default.');
- @z
- @x
- wterm_ln('I can''t find the PLAIN base file!');
- @.I can't find PLAIN...@>
- @y
- wterm_ln('I can''t find the default base file!');
- @.I can't find default base...@>
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.778] Make scan_file_name ignore leading tabs as well as spaces.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @p procedure scan_file_name;
- label done;
- begin begin_name;
- while buffer[loc]=" " do incr(loc);
- @y
- @p procedure scan_file_name;
- label done;
- begin begin_name;
- while (buffer[loc]=" ")or(buffer[loc]=tab) do incr(loc);
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.782] `logname' is declared in <unistd.h> on some systems.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- `\.{.base}' and `\.{.tfm}' in the names of \MF's output files.
- @y
- `\.{.base}' and `\.{.tfm}' in the names of \MF's output files.
-
- @d log_name == texmf_log_name
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.783] <Scan file name...> needs similar leading tab treatment.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @ @<Scan file name in the buffer@>=
- begin begin_name; k:=first;
- while (buffer[k]=" ")and(k<last) do incr(k);
- @y
- @ @<Scan file name in the buffer@>=
- begin begin_name; k:=first;
- while ((buffer[k]=" ")or(buffer[k]=tab))and(k<last) do incr(k);
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Adjust for C string conventions.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @!months:packed array [1..36] of char; {abbreviations of month names}
- @y
- @!months:c_char_pointer;
- @z
-
- @x
- begin wlog(banner);
- slow_print(base_ident); print(" ");
- print_int(round_unscaled(internal[day])); print_char(" ");
- months:='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
- @y
- begin wlog(banner);
- wlog (version_string);
- slow_print(base_ident); print(" ");
- print_int(round_unscaled(internal[day])); print_char(" ");
- months := ' JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';
- @z
-
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.789] a_open_in of input file needs path specifier; also, try to
- % open the file with and without the `.mf'.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- if cur_ext="" then cur_ext:=".mf";
- pack_cur_name;
- loop@+ begin begin_file_reading; {set up |cur_file| and new level of input}
- if a_open_in(cur_file) then goto done;
- if cur_area="" then
- begin pack_file_name(cur_name,MF_area,cur_ext);
- if a_open_in(cur_file) then goto done;
- end;
- @y
- pack_cur_name;
- loop@+begin
- begin_file_reading; {set up |cur_file| and new level of input}
- {See comments in \.{tex.ch}.}
- if (cur_ext <> ".mf") and (name_length + 4 < file_name_size)
- and (not extension_irrelevant_p (name_of_file, 'mf'))
- then begin
- name_of_file[name_length + 1] := ".";
- name_of_file[name_length + 2] := "m";
- name_of_file[name_length + 3] := "f";
- name_length := name_length + 3;
- end;
- if a_open_in (cur_file, MF_INPUT_PATH) then goto done;
-
- {Try without |".mf"|.}
- if cur_ext = ".mf" then cur_ext := "";
- pack_cur_name;
- if a_open_in (cur_file, MF_INPUT_PATH) then goto done;
-
- {Couldn't find the file. Put |".mf"| back into the filename if we
- removed it, and then invoke an external program. If it succeeds, try
- opening the file once more.}
- if cur_ext = "" then begin
- cur_ext := ".mf";
- pack_cur_name;
- end;
- if make_tex_mf then begin
- if a_open_in (cur_file, MF_INPUT_PATH) then goto done;
- end;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [38.789] Get rid of return of filename to string pool.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- if name=str_ptr-1 then {we can conserve string pool space now}
- begin flush_string(name); name:=cur_name;
- end;
- @y
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??.???] another C casting problem
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- if (m_min(cur_edges)+tx<=0)or(m_max(cur_edges)+tx>=8192)or@|
- (n_min(cur_edges)+ty<=0)or(n_max(cur_edges)+ty>=8191)or@|
- @y
- if (toint(m_min(cur_edges))+tx<=0)or(m_max(cur_edges)+tx>=8192)or@|
- (toint(n_min(cur_edges))+ty<=0)or(n_max(cur_edges)+ty>=8191)or@|
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] `threshold' is both a function and a variable, and broken C
- % compilers (e.g., many versions of pcc), get confused by that. Since
- % the function is used much less often than the variable, we'll change
- % the function name.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @p function threshold(@!m:integer):scaled;
- var @!d:scaled; {lower bound on the smallest interval size}
- begin excess:=min_cover(0)-m;
- if excess<=0 then threshold:=0
- else begin repeat d:=perturbation;
- until min_cover(d+d)<=m;
- while min_cover(d)>m do d:=perturbation;
- threshold:=d;
- @y
- @p function threshold_fn(@!m:integer):scaled;
- var @!d:scaled; {lower bound on the smallest interval size}
- begin excess:=min_cover(0)-m;
- if excess<=0 then threshold_fn:=0
- else begin repeat d:=perturbation;
- until min_cover(d+d)<=m;
- while min_cover(d)>m do d:=perturbation;
- threshold_fn:=d;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Change the call to the threshold function.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- begin d:=threshold(m); perturbation:=0;
- @y
- begin d:=threshold_fn(m); perturbation:=0;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [45.1128] Writing the tfm file.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d tfm_out(#)==write(tfm_file,#) {output one byte to |tfm_file|}
-
- @p procedure tfm_two(@!x:integer); {output two bytes to |tfm_file|}
- begin tfm_out(x div 256); tfm_out(x mod 256);
- end;
- @#
- procedure tfm_four(@!x:integer); {output four bytes to |tfm_file|}
- begin if x>=0 then tfm_out(x div three_bytes)
- else begin x:=x+@'10000000000; {use two's complement for negative values}
- x:=x+@'10000000000;
- tfm_out((x div three_bytes) + 128);
- end;
- x:=x mod three_bytes; tfm_out(x div unity);
- x:=x mod unity; tfm_out(x div @'400);
- tfm_out(x mod @'400);
- end;
- @#
- procedure tfm_qqqq(@!x:four_quarters); {output four quarterwords to |tfm_file|}
- begin tfm_out(qo(x.b0)); tfm_out(qo(x.b1)); tfm_out(qo(x.b2));
- tfm_out(qo(x.b3));
- end;
- @y
- Under {\mc UNIX}, we are using the binary input and output routines.
- Hence, we redefine all the {\mc TFM} input and output in terms of those
- routines.
-
- @d tfm_out(#) == b_write_byte(tfm_file, #)
- @d tfm_two(#) == b_write_2_bytes(tfm_file, #)
- @d tfm_four(#) == b_write_4_bytes(tfm_file, #)
-
- @p procedure tfm_qqqq(@!x:four_quarters); {output four quarterwords to |tfm_file|}
- begin tfm_out(qo(x.b0)); tfm_out(qo(x.b1)); tfm_out(qo(x.b2));
- tfm_out(qo(x.b3));
- end;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [47.1148] write_gf
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @<Declare generic font output procedures@>=
- procedure write_gf(@!a,@!b:gf_index);
- var k:gf_index;
- begin for k:=a to b do write(gf_file,gf_buf[k]);
- end;
- @y
- In C, we use a macro to call |fwrite| or |write| directly, writing all
- the bytes to be written in one shot. Much better even than writing four
- bytes at a time.
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] init_gf: C needs k to be 0..256 instead of 0..255.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- procedure init_gf;
- var @!k:eight_bits; {runs through all possible character codes}
- @y
- procedure init_gf;
- var @!k:0..256; {runs through all possible character codes}
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Fix signed/unsigned comparison problem in C.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- if prev_m-m_offset(cur_edges)+x_off>gf_max_m then
- gf_max_m:=prev_m-m_offset(cur_edges)+x_off
- @y
- if prev_m-toint(m_offset(cur_edges))+x_off>gf_max_m then
- gf_max_m:=prev_m-m_offset(cur_edges)+x_off
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Reading and writing of `base_file'.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- @d dump_wd(#)==begin base_file^:=#; put(base_file);@+end
- @d dump_int(#)==begin base_file^.int:=#; put(base_file);@+end
- @d dump_hh(#)==begin base_file^.hh:=#; put(base_file);@+end
- @d dump_qqqq(#)==begin base_file^.qqqq:=#; put(base_file);@+end
- @y
- @z
-
- @x
- @d undump_wd(#)==begin get(base_file); #:=base_file^;@+end
- @d undump_int(#)==begin get(base_file); #:=base_file^.int;@+end
- @d undump_hh(#)==begin get(base_file); #:=base_file^.hh;@+end
- @d undump_qqqq(#)==begin get(base_file); #:=base_file^.qqqq;@+end
- @y
- @z
-
- @x
- x:=base_file^.int;
- @y
- undump_int(x);
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] `eof' here means `have we previously encountered the
- % end-of-file', not `are we at the end of the file'.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- undump_int(x);@+if (x<>69069)or eof(base_file) then goto off_base
- @y
- undump_int(x);@+if (x<>69069)or feof(base_file) then goto off_base
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [??] Eliminate possibly wrong word `preloaded' from base_idents.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- print(" (preloaded base="); print(job_name); print_char(" ");
- @y
- print(" (base="); print(job_name); print_char(" ");
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [49.1197] `uexit' argument depends on `history', procedureize the main
- % programs, and add call to set_paths.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- t_open_out; {open the terminal for output}
- @y
- t_open_out; {open the terminal for output}
- set_paths (MF_BASE_PATH_BIT + MF_INPUT_PATH_BIT + MF_POOL_PATH_BIT);
- @z
-
- @x
- end_of_MF: close_files_and_terminate;
- final_end: ready_already:=0;
- @y
- close_files_and_terminate;
- final_end: do_final_end;
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [49.1198] Print new line before termination; switch to editor if
- % necessary.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- slow_print(log_name); print_char(".");
- end;
- end;
- @y
- slow_print(log_name); print_char(".");
- end;
- end;
- print_ln;
- if (edit_name_start<>0) and (interaction>batch_mode) then
- call_edit(str_pool,edit_name_start,edit_name_length,edit_line);
- @z
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % [51.1207,1208] Add editor-switch variable to globals.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- @x
- This section should be replaced, if necessary, by any special
- modifications of the program
- that are necessary to make \MF\ work at a particular installation.
- It is usually best to design your change file so that all changes to
- previous sections preserve the section numbering; then everybody's version
- will be consistent with the published program. More extensive changes,
- which introduce new sections, can be inserted here; then only the index
- itself will get a new section number.
- @^system dependencies@>
- @y
- Here are the variables used to hold ``switch-to-editor'' information.
- @^system dependencies@>
-
- @<Global...@>=
- @!edit_name_start: pool_pointer;
- @!edit_name_length,@!edit_line: integer;
-
- @ The |edit_name_start| will be set to point into |str_pool| somewhere after
- its beginning if \MF\ is supposed to switch to an editor on exit.
-
- @<Set init...@>=
- edit_name_start:=0;
- @z
-