DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: 2 T

⟦26cd0561d⟧ TextFile

    Length: 31481 (0x7af9)
    Types: TextFile
    Names: »25_to_29.diff«

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦this⟧ »./DVIware/lpr-viewers/crudetype/25_to_29.diff« 
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/lpr-viewers/crudetype/25_to_29.diff« 

TextFile

*** /src/tex/mytangle.web~	Mon Jan 30 07:25:04 1989
--- mytangle.web	Tue Mar  7 18:39:05 1989
***************
*** 8,21 ****
  % Version 1.7 introduced the new change file format (June, 1983).
  % Version 2.0 was released in July, 1983, with version 0.999 of TeX.
  % Version 2.5 was released in November, 1983, with version 1.0 of TeX.
  % RMD's attempts to improve error detection
  
  % Here is TeX material that gets inserted after \input webmac
  \def\hang{\hangindent 3em\indent\ignorespaces}
! \font\ninerm=amr9
! \let\mc=\ninerm % medium caps for names like PASCAL
! \def\PASCAL{{\mc PASCAL}}
! \def\pb{$\.|\ldots\.|$} % pascal brackets (|...|)
  \def\v{\.{\char'174}} % vertical (|) in typewriter font
  \mathchardef\BA="3224 % double arrow
  \def\({} % kludge for alphabetizing certain module names
--- 8,25 ----
  % Version 1.7 introduced the new change file format (June, 1983).
  % Version 2.0 was released in July, 1983, with version 0.999 of TeX.
  % Version 2.5 was released in November, 1983, with version 1.0 of TeX.
+ % Version 2.6 fixed a bug: force-line-break after a constant (August, 1984).
+ % Version 2.7 fixed the definition of check_sum_prime (May, 1985).
+ % Version 2.8 fixed a bug in change_buffer movement (August, 1985).
+ % Version 2.9 allows nonnumeric macros before their definition (December, 1988).
  % RMD's attempts to improve error detection
  
  % Here is TeX material that gets inserted after \input webmac
  \def\hang{\hangindent 3em\indent\ignorespaces}
! \font\ninerm=cmr9
! \let\mc=\ninerm % medium caps for names like SAIL
! \def\PASCAL{Pascal}
! \def\pb{$\.|\ldots\.|$} % Pascal brackets (|...|)
  \def\v{\.{\char'174}} % vertical (|) in typewriter font
  \mathchardef\BA="3224 % double arrow
  \def\({} % kludge for alphabetizing certain module names
***************
*** 27,37 ****
    \def\rheader{\mainfont Appendix E\hfil \contentspagenumber}
    \centerline{\titlefont The {\ttitlefont TANGLE} processor}
    \vskip 15pt
!   \centerline{(Version 2.5)}
    \vfill}
  \pageno=\contentspagenumber \advance\pageno by 1
! 
! @* Introduction.
  This program converts a \.{WEB} file to a \PASCAL\ file. It was written
  by D. E. Knuth in September, 1981; a somewhat similar {\mc SAIL} program had
  been developed in March, 1979. Since this program describes itself, a
--- 31,40 ----
    \def\rheader{\mainfont Appendix E\hfil \contentspagenumber}
    \centerline{\titlefont The {\ttitlefont TANGLE} processor}
    \vskip 15pt
!   \centerline{(Version 2.9)}
    \vfill}
  \pageno=\contentspagenumber \advance\pageno by 1
! \f

@* Introduction.
  This program converts a \.{WEB} file to a \PASCAL\ file. It was written
  by D. E. Knuth in September, 1981; a somewhat similar {\mc SAIL} program had
  been developed in March, 1979. Since this program describes itself, a
***************
*** 56,67 ****
  The ``banner line'' defined here should be changed whenever \.{TANGLE}
  is modified.
  
! @d banner=='This is TANGLE, Version 2.5'
  
  @ The program begins with a fairly normal header, made up of pieces that
  @^system dependencies@>
  will mostly be filled in later. The \.{WEB} input comes from files |web_file|
! and |change_file|, the \PASCAL\ output goes to file |pascal_file|,
  and the string pool output goes to file |pool|.
  
  If it is necessary to abort the job because of a fatal error, the program
--- 59,70 ----
  The ``banner line'' defined here should be changed whenever \.{TANGLE}
  is modified.
  
! @d banner=='This is TANGLE, Version 2.9'
  
  @ The program begins with a fairly normal header, made up of pieces that
  @^system dependencies@>
  will mostly be filled in later. The \.{WEB} input comes from files |web_file|
! and |change_file|, the \PASCAL\ output goes to file |Pascal_file|,
  and the string pool output goes to file |pool|.
  
  If it is necessary to abort the job because of a fatal error, the program
***************
*** 70,76 ****
  @d end_of_TANGLE = 9999 {go here to wrap it up}
  
  @p @t\4@>@<Compiler directives@>@/
! program TANGLE(@!web_file,@!change_file,@!pascal_file,@!pool);
  label end_of_TANGLE; {go here to finish}
  const @<Constants in the outer block@>@/
  type @<Types in the outer block@>@/
--- 73,79 ----
  @d end_of_TANGLE = 9999 {go here to wrap it up}
  
  @p @t\4@>@<Compiler directives@>@/
! program TANGLE(@!web_file,@!change_file,@!Pascal_file,@!pool);
  label end_of_TANGLE; {go here to finish}
  const @<Constants in the outer block@>@/
  type @<Types in the outer block@>@/
***************
*** 208,215 ****
  @<Glob...@>=@!history:spotless..fatal_message; {how bad was this run?}
  
  @ @<Set init...@>=history:=spotless;
! 
! @* The character set.
  One of the main goals in the design of \.{WEB} has been to make it readily
  portable between a wide variety of computers. Yet \.{WEB} by its very
  nature must use a greater variety of characters than most computer
--- 211,217 ----
  @<Glob...@>=@!history:spotless..fatal_message; {how bad was this run?}
  
  @ @<Set init...@>=history:=spotless;
! \f

@* The character set.
  One of the main goals in the design of \.{WEB} has been to make it readily
  portable between a wide variety of computers. Yet \.{WEB} by its very
  nature must use a greater variety of characters than most computer
***************
*** 480,487 ****
  init_xord( xord) ;
  for i:=first_text_char to last_text_char do xord[chr(i)]:=@'40;
  for i:=1 to @'176 do xord[xchr[i]]:=i;
! 
! @* Input and output.
  The input conventions of this program are intended to be very much like those
  of \TeX\ (except, of course, that they are much simpler, because much less
  needs to be done). Furthermore they are identical to those of \.{WEAVE}.
--- 482,488 ----
  init_xord( xord) ;
  for i:=first_text_char to last_text_char do xord[chr(i)]:=@'40;
  for i:=1 to @'176 do xord[xchr[i]]:=i;
! \f

@* Input and output.
  The input conventions of this program are intended to be very much like those
  of \TeX\ (except, of course, that they are much simpler, because much less
  needs to be done). Furthermore they are identical to those of \.{WEAVE}.
***************
*** 538,551 ****
  begin reset(web_file); reset(change_file);
  end;
  
! @ The main output goes to |pascal_file|, and string pool constants are
  written to the |pool| file.
  
  @<Globals...@>=
! @!pascal_file: text_file;
  @!pool: text_file;
  
! @ The following code opens |pascal_file| and |pool|.
  Since these files were listed in the program header, we assume that the
  \PASCAL\ runtime system has checked that suitable external file names have
  been given.
--- 539,552 ----
  begin reset(web_file); reset(change_file);
  end;
  
! @ The main output goes to |Pascal_file|, and string pool constants are
  written to the |pool| file.
  
  @<Globals...@>=
! @!Pascal_file: text_file;
  @!pool: text_file;
  
! @ The following code opens |Pascal_file| and |pool|.
  Since these files were listed in the program header, we assume that the
  \PASCAL\ runtime system has checked that suitable external file names have
  been given.
***************
*** 552,558 ****
  @^system dependencies@>
  
  @<Set init...@>=
! rewrite(pascal_file); rewrite(pool);
  
  @ Input goes into an array called |buffer|.
  
--- 553,559 ----
  @^system dependencies@>
  
  @<Set init...@>=
! rewrite(Pascal_file); rewrite(pool);
  
  @ Input goes into an array called |buffer|.
  
***************
*** 597,604 ****
      read_ln(f); limit:=final_limit; input_ln:=true;
    end;
  end;
! 
! @* Reporting errors to the user.
  The \.{TANGLE} processor operates in two phases: first it inputs the source
  file and stores a compressed representation of the program, then it produces
  the \PASCAL\ output from the compressed representation.
--- 598,604 ----
      read_ln(f); limit:=final_limit; input_ln:=true;
    end;
  end;
! \f

@* Reporting errors to the user.
  The \.{TANGLE} processor operates in two phases: first it inputs the source
  file and stores a compressed representation of the program, then it produces
  the \PASCAL\ output from the compressed representation.
***************
*** 704,711 ****
  @d overflow(#)==fatal_error('! Sorry, ',#,' capacity exceeded')
  @.Sorry, x capacity exceeded@>
  
! 
! @* Data structures.
  Most of the user's \PASCAL\ code is packed into seven- or eight-bit integers
  in two large arrays called |byte_mem| and |tok_mem|.
  The |byte_mem| array holds the names of identifiers, strings, and modules;
--- 704,710 ----
  @d overflow(#)==fatal_error('! Sorry, ',#,' capacity exceeded')
  @.Sorry, x capacity exceeded@>
  
! \f

@* Data structures.
  Most of the user's \PASCAL\ code is packed into seven- or eight-bit integers
  in two large arrays called |byte_mem| and |tok_mem|.
  The |byte_mem| array holds the names of identifiers, strings, and modules;
***************
*** 887,893 ****
  
  @ Here is a little procedure that prints the text of a given name.
  
! @* Searching for identifiers.
  The hash table described above is updated by the |id_lookup| procedure,
  which finds a given identifier and returns a pointer to its index in
  |byte_start|. If the identifier was not already present, it is inserted with
--- 886,900 ----
  
  @ Here is a little procedure that prints the text of a given name.
  
! @p procedure print_id(@!p:name_pointer); {print identifier or module name}
! var k:0..max_bytes; {index into |byte_mem|}
! @!w:0..ww-1; {segment of |byte_mem|}
! begin if p>=name_ptr then print('IMPOSSIBLE')
! else  begin w:=p mod ww;
!   for k:=byte_start[p] to byte_start[p+ww]-1 do print(xchr[byte_mem[w,k]]);
!   end;
! end;
! \f

@* Searching for identifiers.
  The hash table described above is updated by the |id_lookup| procedure,
  which finds a given identifier and returns a pointer to its index in
  |byte_start|. If the identifier was not already present, it is inserted with
***************
*** 1000,1006 ****
      ((p=name_ptr)and(t=normal)and(buffer[id_first]<>"""")) then
    @<Compute the secondary hash code |h| and put the first characters
    into the auxiliary array |chopped_id|@>;
! if p<>name_ptr then @<Give double-definition error and change |p| to type |t|@>
  else @<Enter a new identifier into the table at position |p|@>;
  end
  
--- 1007,1014 ----
      ((p=name_ptr)and(t=normal)and(buffer[id_first]<>"""")) then
    @<Compute the secondary hash code |h| and put the first characters
    into the auxiliary array |chopped_id|@>;
! if p<>name_ptr then
!   @<Give double-definition error, if necessary, and change |p| to type |t|@>
  else @<Enter a new identifier into the table at position |p|@>;
  end
  
***************
*** 1023,1040 ****
  chopped_id[s]:=0;
  end
  
! @ If a macro has appeared before it was defined, \.{TANGLE} will
  still work all right; after all, such behavior is typical of the replacement
  texts for modules, which act very much like macros. However, an undefined
  numeric macro
  may not be used on the right-hand side of another numeric macro definition,
! so \.{TANGLE} finds it simplest to make a blanket rule that macros should
  be defined before they are used. The following routine gives an error message
  and also fixes up any damage that may have been caused.
  
  @<Give double...@>= {now |p<>name_ptr| and |t<>normal|}
  begin if ilk[p]=normal then
!   begin err_print('! This identifier has already appeared');
  @.This identifier has already...@>
    @<Remove |p| from secondary hash table@>;
    end
--- 1031,1048 ----
  chopped_id[s]:=0;
  end
  
! @ If a nonnumeric macro has appeared before it was defined, \.{TANGLE} will
  still work all right; after all, such behavior is typical of the replacement
  texts for modules, which act very much like macros. However, an undefined
  numeric macro
  may not be used on the right-hand side of another numeric macro definition,
! so \.{TANGLE} finds it simplest to make a blanket rule that numeric macros should
  be defined before they are used. The following routine gives an error message
  and also fixes up any damage that may have been caused.
  
  @<Give double...@>= {now |p<>name_ptr| and |t<>normal|}
  begin if ilk[p]=normal then
!   begin if t=numeric then err_print('! This identifier has already appeared');
  @.This identifier has already...@>
    @<Remove |p| from secondary hash table@>;
    end
***************
*** 1107,1113 ****
  @ We compute the string pool check sum by working modulo a prime number
  that is large but not so large that overflow might occur.
  
! @d check_sum_prime==@'3777777671 {$2^{29}-73$}
  @^preprocessed strings@>
  
  @<Define and output a new string...@>=
--- 1115,1121 ----
  @ We compute the string pool check sum by working modulo a prime number
  that is large but not so large that overflow might occur.
  
! @d check_sum_prime==@'3777777667 {$2^{29}-73$}
  @^preprocessed strings@>
  
  @<Define and output a new string...@>=
***************
*** 1136,1143 ****
    write_ln(pool);
    end;
  end
! 
! @* Searching for module names.
  The |mod_lookup| procedure finds the module name |mod_text[1..l]| in the
  search tree, after inserting it if necessary, and returns a pointer to
  where it was found.
--- 1144,1150 ----
    write_ln(pool);
    end;
  end
! \f

@* Searching for module names.
  The |mod_lookup| procedure finds the module name |mod_text[1..l]| in the
  search tree, after inserting it if necessary, and returns a pointer to
  where it was found.
***************
*** 1238,1245 ****
  @.Ambiguous prefix@>
  prefix_lookup:=r; {the result will be 0 if there was no match}
  end;
! 
! @* Tokens.
  Replacement texts, which represent \PASCAL\ code in a compressed format,
  appear in |tok_mem| as mentioned above. The codes in
  these texts are called `tokens'; some tokens occupy two consecutive
--- 1245,1251 ----
  @.Ambiguous prefix@>
  prefix_lookup:=r; {the result will be 0 if there was no match}
  end;
! \f

@* Tokens.
  Replacement texts, which represent \PASCAL\ code in a compressed format,
  appear in |tok_mem| as mentioned above. The codes in
  these texts are called `tokens'; some tokens occupy two consecutive
***************
*** 1257,1263 ****
  The replacement text pointer for the first unnamed module
  appears in |text_link[0]|, and the most recent such pointer is |last_unnamed|.
  
! @d module_flag==max_texts {final |link| in module replacement texts}
  
  @<Glob...@>=
  @!last_unnamed:text_pointer; {most recent replacement text of unnamed module}
--- 1263,1269 ----
  The replacement text pointer for the first unnamed module
  appears in |text_link[0]|, and the most recent such pointer is |last_unnamed|.
  
! @d module_flag==max_texts {final |text_link| in module replacement texts}
  
  @<Glob...@>=
  @!last_unnamed:text_pointer; {most recent replacement text of unnamed module}
***************
*** 1392,1399 ****
  
  othercases print(xchr[a])
  endcases
! 
! @* Stacks for output.
  Let's make sure that our data structures contain enough information to
  produce the entire \PASCAL\ program as desired, by working next on the
  algorithms that actually do produce that program.
--- 1398,1404 ----
  
  othercases print(xchr[a])
  endcases
! \f

@* Stacks for output.
  Let's make sure that our data structures contain enough information to
  produce the entire \PASCAL\ program as desired, by working next on the
  algorithms that actually do produce that program.
***************
*** 1671,1678 ****
      end;
    end;
  done:
! 
! @* Producing the output.
  The |get_output| routine above handles most of the complexity of output
  generation, but there are two further considerations that have a nontrivial
  effect on \.{TANGLE}'s algorithms.
--- 1676,1682 ----
      end;
    end;
  done:
! \f

@* Producing the output.
  The |get_output| routine above handles most of the complexity of output
  generation, but there are two further considerations that have a nontrivial
  effect on \.{TANGLE}'s algorithms.
***************
*** 1809,1816 ****
  @!b:0..out_buf_size; {value of |break_ptr| upon entry}
  begin b:=break_ptr;
  if (semi_ptr<>0)and(out_ptr-semi_ptr<=line_length) then break_ptr:=semi_ptr;
! for k:=1 to break_ptr do write(pascal_file,xchr[out_buf[k-1]]);
! write_ln(pascal_file); incr(line);
  if line mod 100 = 0 then
    begin print('.');
    if line mod 500 = 0 then print(line:1);
--- 1813,1820 ----
  @!b:0..out_buf_size; {value of |break_ptr| upon entry}
  begin b:=break_ptr;
  if (semi_ptr<>0)and(out_ptr-semi_ptr<=line_length) then break_ptr:=semi_ptr;
! for k:=1 to break_ptr do write(Pascal_file,xchr[out_buf[k-1]]);
! write_ln(Pascal_file); incr(line);
  if line mod 100 = 0 then
    begin print('.');
    if line mod 500 = 0 then print(line:1);
***************
*** 2017,2024 ****
  else  begin app("("); app("-"); app_val(-v); app(")"); check_break;
    out_state:=misc;
    end
! 
! @* The big output switch.
  To complete the output process, we need a routine that takes the results
  of |get_output| and feeds them to |send_out|, |send_val|, or |send_sign|.
  This procedure `|send_the_output|' will be invoked just once, as follows:
--- 2021,2027 ----
  else  begin app("("); app("-"); app_val(-v); app(")"); check_break;
    out_state:=misc;
    end
! \f

@* The big output switch.
  To complete the output process, we need a routine that takes the results
  of |get_output| and feeds them to |send_out|, |send_val|, or |send_sign|.
  This procedure `|send_the_output|' will be invoked just once, as follows:
***************
*** 2273,2286 ****
    end;
  
  @ @<Force a line break@>=
! begin while out_ptr>0 do
    begin if out_ptr<=line_length then break_ptr:=out_ptr;
    flush_buffer;
    end;
  out_state:=misc;
  end
! 
! @* Introduction to the input phase.
  We have now seen that \.{TANGLE} will be able to output the full
  \PASCAL\ program, if we can only get that program into the byte memory in
  the proper format. The input process is something like the output process
--- 2276,2289 ----
    end;
  
  @ @<Force a line break@>=
! begin send_out(str,0); {normalize the buffer}
! while out_ptr>0 do
    begin if out_ptr<=line_length then break_ptr:=out_ptr;
    flush_buffer;
    end;
  out_state:=misc;
  end
! \f

@* Introduction to the input phase.
  We have now seen that \.{TANGLE} will be able to output the full
  \PASCAL\ program, if we can only get that program into the byte memory in
  the proper format. The input process is something like the output process
***************
*** 2385,2391 ****
  
  @ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
  begin change_limit:=limit;
! for k:=0 to limit do change_buffer[k]:=buffer[k];
  end
  
  @ The following procedure is used to see if the next change entry should
--- 2388,2394 ----
  
  @ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
  begin change_limit:=limit;
! if limit>0 then for k:=0 to limit-1 do change_buffer[k]:=buffer[k];
  end
  
  @ The following procedure is used to see if the next change entry should
***************
*** 2518,2524 ****
  @d control_text=@'203 {control code for `\.{@@t}', `\.{@@\^}', etc.}
  @d format=@'204 {control code for `\.{@@f}'}
  @d definition=@'205 {control code for `\.{@@d}'}
! @d begin_pascal=@'206 {control code for `\.{@@p}'}
  @d module_name=@'207 {control code for `\.{@@<}'}
  @d new_module=@'210 {control code for `\.{@@\ }' and `\.{@@*}'}
  
--- 2521,2527 ----
  @d control_text=@'203 {control code for `\.{@@t}', `\.{@@\^}', etc.}
  @d format=@'204 {control code for `\.{@@f}'}
  @d definition=@'205 {control code for `\.{@@d}'}
! @d begin_Pascal=@'206 {control code for `\.{@@p}'}
  @d module_name=@'207 {control code for `\.{@@<}'}
  @d new_module=@'210 {control code for `\.{@@\ }' and `\.{@@*}'}
  
***************
*** 2537,2543 ****
  "F","f": control_code:=format; {format definition}
  "{": control_code:=begin_comment; {begin-comment delimiter}
  "}": control_code:=end_comment; {end-comment delimiter}
! "P","p": control_code:=begin_pascal; {\PASCAL\ text in unnamed module}
  "T","t","^",".",":": control_code:=control_text; {control text to be ignored}
  "&": control_code:=join; {concatenate two tokens}
  "<": control_code:=module_name; {beginning of a module name}
--- 2540,2546 ----
  "F","f": control_code:=format; {format definition}
  "{": control_code:=begin_comment; {begin-comment delimiter}
  "}": control_code:=end_comment; {end-comment delimiter}
! "P","p": control_code:=begin_Pascal; {\PASCAL\ text in unnamed module}
  "T","t","^",".",":": control_code:=control_text; {control text to be ignored}
  "&": control_code:=join; {concatenate two tokens}
  "<": control_code:=module_name; {beginning of a module name}
***************
*** 2616,2623 ****
    begin if bal=0 then return;
    decr(bal);
    end
! 
! @* Inputting the next token.
  As stated above, \.{TANGLE}'s most interesting input procedure is the
  |get_next| routine that inputs the next token. However, the procedure
  isn't especially difficult.
--- 2619,2625 ----
    begin if bal=0 then return;
    decr(bal);
    end
! \f

@* Inputting the next token.
  As stated above, \.{TANGLE}'s most interesting input procedure is the
  |get_next| routine that inputs the next token. However, the procedure
  isn't especially difficult.
***************
*** 2818,2825 ****
    for j:=1 to 25 do print(xchr[mod_text[j]]);
    print('...'); mark_harmless;
    end
! 
! @* Scanning a numeric definition.
  When \.{TANGLE} looks at the \PASCAL\ text following the `\.=' of a numeric
  macro definition, it calls on the precedure |scan_numeric(p)|, where |p|
  points to the name that is to be defined. This procedure evaluates the
--- 2820,2826 ----
    for j:=1 to 25 do print(xchr[mod_text[j]]);
    print('...'); mark_harmless;
    end
! \f

@* Scanning a numeric definition.
  When \.{TANGLE} looks at the \PASCAL\ text following the `\.=' of a numeric
  macro definition, it calls on the precedure |scan_numeric(p)|, where |p|
  points to the name that is to be defined. This procedure evaluates the
***************
*** 2829,2835 ****
  terminated this definition.
  
  A definition ends with the control codes |definition|, |format|, |module_name|,
! |begin_pascal|, and |new_module|, all of which can be recognized
  by the fact that they are the largest values |get_next| can return.
  
  @d end_of_definition(#)==(#>=format)
--- 2830,2836 ----
  terminated this definition.
  
  A definition ends with the control codes |definition|, |format|, |module_name|,
! |begin_Pascal|, and |new_module|, all of which can be recognized
  by the fact that they are the largest values |get_next| can return.
  
  @d end_of_definition(#)==(#>=format)
***************
*** 2885,2891 ****
      end;
    "+": do_nothing;
    "-": next_sign:=-next_sign;
!   format, definition, module_name, begin_pascal, new_module: goto done;
    ";": err_print('! Omit semicolon in numeric definition');
  @.Omit semicolon in numeric def...@>
    othercases @<Signal error, flush rest of the definition@>
--- 2886,2892 ----
      end;
    "+": do_nothing;
    "-": next_sign:=-next_sign;
!   format, definition, module_name, begin_Pascal, new_module: goto done;
    ";": err_print('! Omit semicolon in numeric definition');
  @.Omit semicolon in numeric def...@>
    othercases @<Signal error, flush rest of the definition@>
***************
*** 2921,2928 ****
  val:=16*val+next_control-"0"; next_control:=get_next;
  until (next_control>"F")or(next_control<"0")or@|
    ((next_control>"9")and(next_control<"A"))
! 
! @* Scanning a macro definition.
  The rules for generating the replacement texts corresponding to simple
  macros, parametric macros, and \PASCAL\ texts of a module are almost
  identical, so a single procedure is used for all three cases. The
--- 2922,2928 ----
  val:=16*val+next_control-"0"; next_control:=get_next;
  until (next_control>"F")or(next_control<"0")or@|
    ((next_control>"9")and(next_control<"A"))
! \f

@* Scanning a macro definition.
  The rules for generating the replacement texts corresponding to simple
  macros, parametric macros, and \PASCAL\ texts of a module are almost
  identical, so a single procedure is used for all three cases. The
***************
*** 2999,3010 ****
      a:=cur_module mod @'400;
      end;
  verbatim: @<Copy verbatim string from the buffer to |tok_mem|@>;
! definition, format, begin_pascal: if t<>module_name then goto done
    else  begin err_print('! @@',xchr[buffer[loc-1]],
! @.\AT!p is ignored in PASCAL text@>
! @.\AT!d is ignored in PASCAL text@>
! @.\AT!f is ignored in PASCAL text@>
!       ' is ignored in PASCAL text: maybe @@  missing?');
          @.Missing \AT!  @>
        @<Show last checkpoint@>;
        goto continue;
--- 2999,3010 ----
      a:=cur_module mod @'400;
      end;
  verbatim: @<Copy verbatim string from the buffer to |tok_mem|@>;
! definition, format, begin_Pascal: if t<>module_name then goto done
    else  begin err_print('! @@',xchr[buffer[loc-1]],
! @.\AT!p is ignored in Pascal text@>
! @.\AT!d is ignored in Pascal text@>
! @.\AT!f is ignored in Pascal text@>
!       ' is ignored in Pascal text: maybe @@  missing?');
          @.Missing \AT!  @>
        @<Show last checkpoint@>;
        goto continue;
***************
*** 3060,3067 ****
  begin p:=id_lookup(t); scan_repl(t);@/
  equiv[p]:=cur_repl_text; text_link[cur_repl_text]:=0;
  end;
! 
! @* Scanning a module.
  The |scan_module| procedure starts when `\.{@@\ }' or `\.{@@*}' has been
  sensed in the input, and it proceeds until the end of that module.  It
  uses |module_count| to keep track of the current module number; with luck,
--- 3060,3066 ----
  begin p:=id_lookup(t); scan_repl(t);@/
  equiv[p]:=cur_repl_text; text_link[cur_repl_text]:=0;
  end;
! \f

@* Scanning a module.
  The |scan_module| procedure starts when `\.{@@\ }' or `\.{@@*}' has been
  sensed in the input, and it proceeds until the end of that module.  It
  uses |module_count| to keep track of the current module number; with luck,
***************
*** 3130,3136 ****
  
  @ @<Scan the \PASCAL...@>=
  case next_control of
! begin_pascal:p:=0;
  module_name: begin p:=cur_module;
    @<Check that |=| or |==| follows this module name, otherwise |return|@>;
    end;
--- 3129,3135 ----
  
  @ @<Scan the \PASCAL...@>=
  case next_control of
! begin_Pascal:p:=0;
  module_name: begin p:=cur_module;
    @<Check that |=| or |==| follows this module name, otherwise |return|@>;
    end;
***************
*** 3144,3151 ****
  repeat next_control:=get_next;
  until next_control<>"+"; {allow optional `\.{+=}'}
  if (next_control<>"=")and(next_control<>equivalence_sign) then
!   begin err_print('! PASCAL text flushed, = sign is missing');
! @.PASCAL text flushed...@>
    repeat next_control:=skip_ahead;
    until next_control=new_module;
    return;
--- 3143,3150 ----
  repeat next_control:=get_next;
  until next_control<>"+"; {allow optional `\.{+=}'}
  if (next_control<>"=")and(next_control<>equivalence_sign) then
!   begin err_print('! Pascal text flushed, = sign is missing');
! @.Pascal text flushed...@>
    repeat next_control:=skip_ahead;
    until next_control=new_module;
    return;
***************
*** 3165,3172 ****
    end;
  text_link[cur_repl_text]:=module_flag;
    {mark this replacement text as a nonmacro}
! 
! @* Debugging.
  The \PASCAL\ debugger with which \.{TANGLE} was developed allows breakpoints
  to be set, and variables can be read and changed, but procedures cannot be
  executed. Therefore a `|debug_help|' procedure has been inserted in the main
--- 3164,3170 ----
    end;
  text_link[cur_repl_text]:=module_flag;
    {mark this replacement text as a nonmacro}
! \f

@* Debugging.
  The \PASCAL\ debugger with which \.{TANGLE} was developed allows breakpoints
  to be set, and variables can be read and changed, but procedures cannot be
  executed. Therefore a `|debug_help|' procedure has been inserted in the main
***************
*** 3180,3186 ****
  discontinuing this when |ddt<=0|; thus you type $2n+1$ integers, ending
  with zero or a negative number. Then control either passes to the
  breakpoint, allowing you to look at and/or change variables (if you typed
! zero), or you exit the routine (if you typed a negative value).
  
  Another global variable, |debug_cycle|, can be used to skip silently
  past calls on |debug_help|. If you set |debug_cycle>1|, the program stops
--- 3178,3184 ----
  discontinuing this when |ddt<=0|; thus you type $2n+1$ integers, ending
  with zero or a negative number. Then control either passes to the
  breakpoint, allowing you to look at and/or change variables (if you typed
! zero), or to exit the routine (if you typed a negative value).
  
  Another global variable, |debug_cycle|, can be used to skip silently
  past calls on |debug_help|. If you set |debug_cycle>1|, the program stops
***************
*** 3234,3241 ****
    end;
  exit:end;
  gubed
! 
! @* The main program.
  We have defined plenty of procedures, and it is time to put the last
  pieces of the puzzle in place. Here is where \.{TANGLE} starts, and where
  it ends.
--- 3232,3238 ----
    end;
  exit:end;
  gubed
! \f

@* The main program.
  We have defined plenty of procedures, and it is time to put the last
  pieces of the puzzle in place. Here is where \.{TANGLE} starts, and where
  it ends.
***************
*** 3299,3306 ****
  error_message: print_nl('(Pardon me, but I think I spotted something wrong.)');
  fatal_message: print_nl('(That was a fatal error, my friend.)');
  end {there are no other cases}
! 
! @* Error detection.
  This section is an attempt to improve \.{TANGLE} by making it detect certain
  errors. Most of the additional code goes in here, so as not to disturb the
  module numbers of the rest of the program.
--- 3296,3302 ----
  error_message: print_nl('(Pardon me, but I think I spotted something wrong.)');
  fatal_message: print_nl('(That was a fatal error, my friend.)');
  end {there are no other cases}
! \f

@* Error detection.
  This section is an attempt to improve \.{TANGLE} by making it detect certain
  errors. Most of the additional code goes in here, so as not to disturb the
  module numbers of the rest of the program.
***************
*** 3434,3441 ****
      for c := first to last do
      xx[c] :=  invalid_code ;
    end;
! 
! @* System-dependent changes.
  This module should be replaced, if necessary, by changes to the program
  that are necessary to make \.{TANGLE} work at a particular installation.
  It is usually best to design your change file so that all changes to
--- 3430,3436 ----
      for c := first to last do
      xx[c] :=  invalid_code ;
    end;
! \f

@* System-dependent changes.
  This module should be replaced, if necessary, by changes to the program
  that are necessary to make \.{TANGLE} work at a particular installation.
  It is usually best to design your change file so that all changes to
***************
*** 3444,3451 ****
  which introduce new modules, can be inserted here; then only the index
  itself will get a new module number.
  @^system dependencies@>
! 
! @* Index.
  Here is a cross-reference table for the \.{TANGLE} processor.
  All modules in which an identifier is
  used are listed with that identifier, except that reserved words are
--- 3439,3445 ----
  which introduce new modules, can be inserted here; then only the index
  itself will get a new module number.
  @^system dependencies@>
! \f

@* Index.
  Here is a cross-reference table for the \.{TANGLE} processor.
  All modules in which an identifier is
  used are listed with that identifier, except that reserved words are