|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: 2 T
Length: 31481 (0x7af9) Types: TextFile Names: »25_to_29.diff«
└─⟦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«
*** /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