TeX change file for MVS. Copyright (C) 1984 by David Fuchs. All rights are reserved. @x @d banner=='This is TeX, Version 1.1' {printed when \TeX\ starts} @y @d banner=='This is TeX, MVS Version 1.1' {printed when -TeX- starts} @d ccat==@=^^@> @z @x procedure initialize; {this procedure gets things started properly} @y @ @# procedure initialize; {this procedure gets things started properly} @z @x @d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging} @d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging} @y @d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging} @d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging} @z @x @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== @d tats== @z @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==@{ @d tini==@} @z @x @d othercases == others: {default for cases not listed explicitly} @y @d othercases == otherwise {default for cases not listed explicitly} @z @x @!mem_max=30000; {greatest index in \TeX's internal |mem| array; must be strictly less than |max_halfword|} @!buf_size=500; {maximum number of characters simultaneously present in 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} @!max_in_open=6; {maximum number of input files and error insertions that 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} @!nest_size=40; {maximum number of semantic levels simultaneously active} @!max_strings=3000; {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 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} @!dvi_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='TeXformats:TEX.POOL '; {string of length |file_name_size|; tells where the string pool appears} @.TeXformats@> @y @!mem_max=60000; {greatest index in \TeX's internal |mem| array; must be strictly less than |max_halfword|} @!buf_size=500; {maximum number of characters simultaneously present in 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} @!max_in_open=6; {maximum number of input files and error insertions that 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=25000; {number of words of |font_info| for all fonts} @!param_size=60; {maximum number of simultaneous macro parameters} @!nest_size=40; {maximum number of semantic levels simultaneously active} @!max_strings=3000; {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 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} @!dvi_buf_size=4096; {size of the output buffer; must be a multiple of 8} @!len_byte_block=2048; {must be half of |dvi_buf_size|} @!len_word_block=256; {format file buffer length} @!file_name_size=40; {file names shouldn't be longer than this} @!pool_name='TEX.POOL '; {string of length |file_name_size|; tells where the string pool appears} @.TeXformats@> @z @x @d mem_base=0 {smallest index in the |mem| array; must not be less than |min_halfword|} @d hi_mem_base=13000 {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 hash_size=2100 {maximum number of control sequences; it should be at most 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|} @d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions} @^system dependencies@> @y @d mem_base=0 {smallest index in the |mem| array; must not be less than |min_halfword|} @d hi_mem_base=22000 {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 hash_size=2100 {maximum number of control sequences; it should be at most 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|} @d hyph_size=307 {another prime; the number of \.{\\hyphenation} exceptions} @^system dependencies@> @z @x @!ASCII_code=0..127; {seven-bit numbers} @y @!ASCII_code=packed 0..127; {seven-bit numbers} @z @x @d last_text_char=127 {ordinal number of the largest element of |text_char|} @y @d last_text_char=255 {ordinal number of the largest element of |text_char|} @z @x {ASCII codes 0 and |@'177| do not appear in text} @y {ASCII codes 0 and |@'177| do not appear in text} parmstring:=parms ccat str('C'); if parmstring(.1.)='W' then begin xchr(.@'134.):=chr(@"5F); {backslash} xchr(.@'173.):=chr(@"8B); {left curly} xchr(.@'175.):=chr(@"9B); {right curly} xchr(.@'140.):=chr(@"AF); {left single quote} xchr(.@'176.):=chr(@"9C); {tilde} end; @z @x for us to specify simple operations on word files before they are defined. @= @!eight_bits=0..255; {unsigned one-byte quantity} @!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 do a few simple things with them in this section before they are defined. @d alpha_file==@= text@> @= @!eight_bits=packed 0..255; {unsigned one-byte quantity} @z @x begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); @y begin okstatus; if dd_name='' then reset(f,'DDNAME='ccat dd_member) else pdsin(f,'DDNAME='ccat dd_name ccat ',MEMBER=' ccat dd_member); a_open_in:=status; @z @x begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); @y begin okstatus; if dd_name='' then rewrite(f,'DDNAME='ccat dd_member) else pdsout(f,'DDNAME='ccat dd_name ccat ',MEMBER=' ccat dd_member); a_open_out:=status; @z @x begin reset(f,name_of_file,'/O'); b_open_in:=reset_OK(f); @y begin okstatus; pdsin(f,'DDNAME='ccat dd_name ccat ',MEMBER=' ccat dd_member); b_open_in:=status; @z @x begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f); @y begin okstatus; rewrite(f,'DDNAME=DVIFILE'); b_open_out:=status; @z @x begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f); @y begin okstatus; reset(f,'DDNAME=FMTFILE'); w_open_in:=status; @z @x begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f); @y begin okstatus; rewrite(f,'DDNAME=FMTOUT'); w_open_out:=status; @z @x @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:30} 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 overflow("buffer size",buf_size); @:TeX capacity exceeded buffer size}{\quad buffer size@> 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 @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:30} 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 overflow("buffer size",buf_size); @:TeX capacity exceeded buffer size}{\quad buffer size@> 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; @z @x @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 @d t_open_in==reset(term_in,'INTERACTIVE') @d t_open_out==rewrite(term_out) {open the terminal for text output} @z @x @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 wake_up_terminal == do_nothing {cancel the user's cancellation of output} @y @d update_terminal == do_nothing @d clear_terminal == do_nothing @d wake_up_terminal == do_nothing @z @x name_of_file:=pool_name; {we needn't set |name_length|} @y name_of_file:=pool_name; {we needn't set |name_length|} dd_name:=''; dd_member:='POOL'; @z @x if not input_ln(term_in,true) then fatal_error("End of file on the terminal!"); @y write_ln(term_out); if not input_ln(term_in,true) then fatal_error("End of file on the terminal!"); @z @x interrupt:=0; OK_to_interrupt:=true; @y interrupt:=0; OK_to_interrupt:=true; @z @x @!glue_ratio=real; {one-word representation of a glue expansion factor} @y @!glue_ratio=shortreal; {are there any other reals in the program?} @z @x @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} @y @d qi(#)==# @d qo(#)==# @d hi(#)==# @d ho(#)==# @z @x @!quarterword = min_quarterword..max_quarterword; {1/4 of a word} @!halfword=min_halfword..max_halfword; {1/2 of a word} @!two_choices = 1..2; {used when there are two variants in a record} @!four_choices = 1..4; {used when there are four variants in a record} @y @!quarterword = packed min_quarterword..max_quarterword; {1/4 of a word} @!halfword=packed min_halfword..max_halfword; {1/2 of a word} @!two_choices=packed 1..2; {used when there are two variants in a record} @!four_choices=packed 1..4; {when there are four variants in a record} @z @x @!word_file = file of memory_word; @y @!word_block = packed array [0..len_word_block-1] of memory_word; @!word_file = packed file of word_block; @!byte_block = packed array [0..len_byte_block-1] of quarterword; @!byte_file = packed file of byte_block; @z @x FIX ME! if abs(mem[p+glue_offset].int)<@'4000000 then print("?.?") @y if false then print("?.?") @z @x @p procedure fix_date_and_time; begin time:=12*60; {minutes since midnight} day:=4; {fourth day of the month} month:=7; {seventh month of the year} year:=1776; {Anno Domini} end; @y @p procedure fix_date_and_time; var date,tod:alfa; hour, minute:integer; begin datetime(date,tod); readstr(str(date),month:3,day:3,year); year:=year+1900;{Bug next century} readstr(str(tod),hour:3,minute); time:=hour*60+minute; end; @z @x @d TEX_area=="TeXinputs:" @y @d TEX_area=="TeXinput:" @z @x @p procedure pack_file_name(@!n,@!a,@!e:str_number); var k:integer; {number of positions filled in |name_of_file|} @!c: ASCII_code; {character being packed} @!j:pool_pointer; {index into |str_pool|} begin k:=0; @y @p procedure pack_file_name(@!n,@!a,@!e:str_number); var k:integer; {number of positions filled in |name_of_file|} @!c: ASCII_code; {character being packed} @!j:pool_pointer; {index into |str_pool|} begin k:=0; dd_name:=''; dd_member:=''; for j:=str_start(.a.) to str_start(.a+1.)-2 do {no colon} dd_name:=dd_name ccat str(xchr(.str_pool(.j.).)); for j:=str_start(.n.) to str_start(.n+1.)-1 do dd_member:=dd_member ccat str(xchr(.str_pool(.j.).)); @z @x pack_job_name(".log"); @y cur_area:=""; cur_ext:=".log"; cur_name:="texput"; pack_cur_name; @z @x @ @= @y @ @= tfm_count:=0; @z %% fget==incr(tfm_count); if tfm_count=len_byte_block then new_tfm @x @d fget==get(tfm_file) @d fbyte==tfm_file^ @y @d fbyte==tfm_file@@[tfm_count] @z @x @ Some systems may find it more efficient to make |dvi_buf| a |packed| array, since output of four bytes at once may be facilitated. @^system dependencies@> @y @ We play a trick with variant records so that we can fill up the |dvi_buf| array byte by byte, but write it out in one swell foop. @^system dependencies@> @d dvi_buf==d_buffer.b {buffer for \.{DVI} output} @z @x @!dvi_buf:array[dvi_index] of eight_bits; {buffer for \.{DVI} output} @y @!d_buffer: packed record case boolean of false:(b:packed array [dvi_index] of eight_bits); true: (l:byte_block; r:byte_block); end; @z @x @ The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling |write_dvi(a,b)|. For best results, this procedure should be optimized to run as fast as possible on each particular system, since it is part of \TeX's inner loop. It is safe to assume that |a| and |b+1| will both be multiples of 4 when |write_dvi(a,b)| is called; therefore it is possible on many machines to use efficient methods to pack four bytes per word and to output an array of words with one system call. @^system dependencies@> @^inner loop@> @^defecation@> @p procedure write_dvi(@!a,@!b:dvi_index); var k:dvi_index; begin for k:=a to b do write(dvi_file,dvi_buf[k]); end; @y @ The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling |write| on the other variant of the |dvi_buf| record. Thus, we had better be sure things line up properly. many machines to use efficient methods to pack four bytes per word and to output an array of words with one system call. @^system dependencies@> @^inner loop@> @^defecation@> @= if dvi_buf_size<>2*len_byte_block then bad:=223; @z @x begin write_dvi(0,half_buf-1); dvi_limit:=half_buf; @y begin write(dvi_file,d_buffer.l); dvi_limit:=half_buf; @z @x else begin write_dvi(half_buf,dvi_buf_size-1); dvi_limit:=dvi_buf_size; @y else begin write(dvi_file,d_buffer.r); dvi_limit:=dvi_buf_size; @z @x if dvi_limit=half_buf then write_dvi(half_buf,dvi_buf_size-1); if dvi_ptr>0 then write_dvi(0,dvi_ptr-1) @y if dvi_limit=half_buf then write(dvi_file,d_buffer.r); for k:=dvi_ptr to dvi_buf_size do dvi_buf[k]:=223; {bug is |k| ok?} if dvi_ptr>0 then write(dvi_file,d_buffer.l); if dvi_ptr>half_buf then write(dvi_file,d_buffer.r); @z @x @@; @y @@; procedure now_Print_a_symbolic_description_of_the_new_break_node; begin @ end; procedure do_Print_a_symbolic_description_of_this_feasible_break; begin @; end; procedure Update_printed_node_for_symbolic_displays; begin @; end; @z @x exit: @!stat @@+tats@; @y exit: @!stat Update_printed_node_for_symbolic_displays @+tats@; @z @x @; @y now_Print_a_symbolic_description_of_the_new_break_node; @z @x @; @y do_Print_a_symbolic_description_of_this_feasible_break; @z @x @d dump_wd(#)==begin fmt_file^:=#; put(fmt_file);@+end @d dump_int(#)==begin fmt_file^.int:=#; put(fmt_file);@+end @d dump_hh(#)==begin fmt_file^.hh:=#; put(fmt_file);@+end @d dump_qqqq(#)==begin fmt_file^.qqqq:=#; put(fmt_file);@+end @= @y @d fmt_word==fmt_file@@[fmt_count] @d dump_wd(#)==begin fmt_word:=#; put_fmt;@+end @d dump_int(#)==begin fmt_word.int:=#; put_fmt;@+end @d dump_hh(#)==begin fmt_word.hh:=#; put_fmt;@+end @d dump_qqqq(#)==begin fmt_word.qqqq:=#; put_fmt;@+end @= @!fmt_count:integer; @z @x @d undump_wd(#)==begin get(fmt_file); #:=fmt_file^;@+end @d undump_int(#)==begin get(fmt_file); #:=fmt_file^.int;@+end @d undump_hh(#)==begin get(fmt_file); #:=fmt_file^.hh;@+end @d undump_qqqq(#)==begin get(fmt_file); #:=fmt_file^.qqqq;@+end @y @d undump_wd(#)==begin get_fmt; #:=fmt_word;@+end @d undump_int(#)==begin get_fmt; #:=fmt_word.int;@+end @d undump_hh(#)==begin get_fmt; #:=fmt_word.hh;@+end @d undump_qqqq(#)==begin get_fmt; #:=fmt_word.qqqq;@+end @z @x @= @y @= fmt_count:=0; @z; @x x:=fmt_file^.int; @y fmt_count:=0; x:=fmt_word.int; @z @x dump_int(interaction); dump_int(format_ident); dump_int(69069); @y dump_int(interaction); dump_int(format_ident); dump_int(69069); while fmt_count<>0 do dump_int(0); {flush out the buffer} @z @x wterm('Ouch---my internal constants have been', ' clobbered!---case ',bad:1); @y wterm('Ouch---my internal constants have been', ' clobbered!---case ',bad:1); ret_code(100+bad); @z @x final_end: ready_already:=0; @y ret_code(history*4); final_end: @z @x This section should be replaced, if necessary, by changes to the program that are necessary to make \TeX\ 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 @ @= @!tfm_count:integer; @!status: boolean; {did the last |reset| or |rewrite| succede?} @ @= procedure okstatus; begin status:=true; end; @\@=%INCLUDE ONERROR;@>@\ procedure onerror; begin {write_ln(term_out,'GOT ERROR ',FERROR:1);} if FERROR in [41,48] then begin status:=false;FACTION:=(..); end; if FERROR=30 then interrupt:=1; end; procedure fget; begin incr(tfm_count); if tfm_count=len_byte_block then begin get(tfm_file); tfm_count:=0; end; end; procedure put_fmt; begin incr(fmt_count); if fmt_count=len_word_block then begin put(fmt_file); fmt_count:=0; end; end; procedure get_fmt; begin incr(fmt_count); if fmt_count=len_word_block then begin get(fmt_file); fmt_count:=0; end; end; @ @= dd_name: string(256); dd_member: string(256); parmstring: string(256); @z