home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / id2id.lbr / ID2ID.PZS / ID2ID.PAS
Encoding:
Pascal/Delphi Source File  |  1986-12-28  |  25.0 KB  |  667 lines

  1. PROGRAM id2id(source, target, idpairs, output);
  2. (* ####################################################### *)
  3. (* ID2ID - Rename identifiers in PASCAL, C, ASSY  or SPL   *)
  4. (*         programs.  Optional up/downshift.               *)
  5. (*                                                         *)
  6. (* W A R N I N G - This system is case sensitive for id's. *)
  7. (* IN addition, if listed on uppercase only printers,      *)
  8. (* note that many characters are lower case.  In general,  *)
  9. (* identifiers are lowercase and reserved words are in     *)
  10. (* upper case. Braces may map into brackets on UC printers *)
  11. (*                                                         *)
  12. (* James F. Miner  79/06/01                                *)
  13. (*  Social Sciences Research Facilities Center.            *)
  14. (* Andy Mickel     79/06/28                                *)
  15. (*  University Computer Center,   (612) 376-7290           *)
  16. (* University of Minnesota,                                *)
  17. (* Minneapolis, Minn. 55455 USA   Copyright (c) 1979       *)
  18. (* C.B. Falconer      79/12/04    (203) 281-1438           *)
  19. (*  680 Hartfort Tpk., Hamden, Conn. 06517                 *)
  20. (*    for SPL source and generally adapted to HP3000       *)
  21. (*                                                         *)
  22. (*  (Based on an earlier version by John T. Easton and     *)
  23. (*   James F. Miner, 76/11/29, as modified by Andy         *)
  24. (*   Mickel and Rick L. Marcus, 78/12/08)                  *)
  25. (*                                                         *)
  26. (* THE NAMES AND ORGANIZATIONS GIVEN MUST NOT BE DELETED   *)
  27. (* IN ANY USE OF THIS PROGRAM                              *)
  28. (*                                                         *)
  29. (* See Pascal News #15 for external documentation          *)
  30. (*                                                         *)
  31. (*         Internal documentation                          *)
  32. (* ID2ID reads a file of IDPAIRS and builds an AVL-        *)
  33. (* balanced binary tree of identifiers while checking for  *)
  34. (* duplicates.  It then reads the SOURCE program and edits *)
  35. (* it to TARGET file by substituting identifiers found in  *)
  36. (* the tree.  A final check is made for new identifiers    *)
  37. (* which were already seen in the SOURCE, and REPORT may   *)
  38. (* be generated.                                           *)
  39. (*                                                         *)
  40. (* Outline of modifications by C.B.F.                      *)
  41. (* The IDPAIRS file may contain option settings, starting  *)
  42. (* at the left of the line, of the form                    *)
  43. (*   $OPTION   where OPTION may be:                        *)
  44. (*       "FLIP", "SPL", "ASM", "C", "UPSHIFT", "DOWNSHIFT" *)
  45. (* This controls the comment and string delimiters used.   *)
  46. (* FLIP allows the action to be reversed, i.e. replace new *)
  47. (* by old, and undo the revision.                          *)
  48. (*                                                         *)
  49. (* NOTE that, to preserve original line numbers, TARGET    *)
  50. (* file should generally be a variable ascii file on the   *)
  51. (* HP3000 system.  This will allow the editor to recover   *)
  52. (* and reformat the file records as desired.  Lines        *)
  53. (* beginining with "E" or "e" in column 1 may confuse the  *)
  54. (* system when using front numbered files, and lines with  *)
  55. (* alphabetical characters in the last column will also    *)
  56. (* cause confusion when using rear-numbered files.         *)
  57. (*                                                         *)
  58. (* The revised system allows for the use of indentation    *)
  59. (* codes in the source file, where an indentation code is  *)
  60. (* the ascii DLE character, followed by chr(ord(' ')+n)    *)
  61. (* where n is the number of spaces desired.                *)
  62. (*                                                         *)
  63. (* Other languages may usually be handled by suitable      *)
  64. (* chars. for string delimiters and for "fillers".  The    *)
  65. (* cases added are for 8080 and similar assembly language  *)
  66. (* (almost Intel specs), C and SPL (an ALGOL like language *)
  67. (* for the HP3000).                                        *)
  68. (*                                                         *)
  69. (* 1.7 - option $ASM8080 changed to $ASM. (this parameter  *)
  70. (*       handles 8080, Z80, 8086 source).  Added options   *)
  71. (*       $C, $DOWNSHIFT.  $ASM, $C allow for ' or " string *)
  72. (*       delimiters.  86/2/21 cbf                          *)
  73. (* 1.6 - added linenumber for unclosed string error        *)
  74. (*       normal input operation, check source exists 84/4  *)
  75. (* 1.5 - added option "UPSHIFT", Feb. 1982                 *)
  76. (* ####################################################### *)
  77.  
  78.   (* =================== *)
  79.  
  80.   CONST
  81.     signon      = 'ID2ID (source, target, idpairs, output) Ver. 1.7 ';
  82.     maxlength   = 25;
  83.     blanks      = '                         ';
  84.     (* must be maxlength long *)
  85.     debug       = false;         (* enable symbol dumps *)
  86.     growthflag  = false;         (* enable dump on growth *)
  87.  
  88.   (* =================== *)
  89.  
  90.   TYPE
  91.     idlength    = 1..maxlength;
  92.     string      = RECORD
  93.       name        : PACKED ARRAY[idlength] OF char;
  94.       length      : 0..maxlength;  (* 0 allows for empty string *)
  95.       END;
  96.  
  97.     chtype      = (digit, letter, under, lparen, lbrace, 
  98.                    indent, ltsy, semi, slash, prime, quote,
  99.                    blank, special, other);
  100.     (* so <= under is allowable in id's *)
  101.  
  102.     balance     = (lefthigh, even, ritehigh);
  103.     nodeptr     = ^node;
  104.     node        = RECORD
  105.       id          : string;
  106.       left, right : nodeptr;
  107.       bal         : balance;
  108.       idisnew     : boolean;
  109.       CASE idisold: boolean OF
  110.   true:  (newptr      : nodeptr);
  111.   false: (seeninsource : boolean);
  112.       END;  (* node RECORD *)
  113.  
  114.   (* ================== *)
  115.  
  116.   VAR
  117.     idtable     : nodeptr;       (* symbol table *)
  118.  
  119.     idpairs,
  120.     source,
  121.     target      : text;
  122.  
  123.     downshift,
  124.     upshift,                     (* input text *)
  125.     fatal       : boolean;       (* abort on fatal errors *)
  126.  
  127.     depth       : integer;       (* monitor table depth *)
  128.  
  129.     (* string delimiters for language *)
  130.     delim1,                      (* usually single quote *)
  131.     delim2      : char;          (* usually double quote *)
  132.     language    : (pascal, spl, asm8080, c);  (* available languages *)
  133.  
  134.     dle         : char;          (* signals indentation codes *)
  135.     underch     : char;          (* filler character in ids *)
  136.  
  137.     upshiftwd   : string;
  138.     downshftwd  : string;
  139.     splwd       : string;
  140.     asm8080wd   : string;
  141.     cwd         : string;
  142.     flipwd      : string;
  143.     cmntwd      : string;
  144.     cmntwdl     : string;      (* in lower case *)
  145.  
  146.   (* 1-----------------1 *)
  147.  
  148.   PROCEDURE initialize;
  149.  
  150.     BEGIN (* initialize *)
  151.     depth := 0; dle := chr(16);  (* data link escape *)
  152.     underch := '_';
  153.     delim1 := ''''; delim2 := '"';  (* default pascal strings *)
  154.     language := pascal;
  155.     splwd.name       := 'SPL                      ';
  156.     asm8080wd.name   := 'ASM                      ';
  157.     cwd.name         := 'C                        ';
  158.     flipwd.name      := 'FLIP                     ';
  159.     cmntwd.name      := 'COMMENT                  ';
  160.     cmntwdl.name     := 'comment                  ';
  161.     upshiftwd.name   := 'UPSHIFT                  ';
  162.     downshftwd.name  := 'DOWNSHIFT                ';
  163.     (*                 1234567890123456789012345' *)
  164.     splwd.length := 3; upshiftwd.length := 7;
  165.     asm8080wd.length := 3; flipwd.length := 4;
  166.     cmntwd.length := 7; cmntwdl.length := 7;
  167.     downshftwd.length := 9; cwd.length := 1;
  168.     (* names padded to maxlength with blanks *)
  169.     (* options must be in upper case *)
  170.     writeln(signon);
  171.     fatal := false; (* no fatal error yet *)
  172.     upshift := false; downshift := false; 
  173.     END; (* initialize *)
  174.  
  175.   (* 1-----------------1 *)
  176.  
  177.   PROCEDURE dumptable(base : nodeptr);
  178.  
  179.     (* 2-----------------2 *)
  180.  
  181.     PROCEDURE writecontent(item : nodeptr);
  182.  
  183.       BEGIN (* writecontent *)
  184.       IF debug THEN
  185.         WITH item^ DO BEGIN
  186.           write(output, ' ' : 2 * depth, ord(bal) - 1 : 2,
  187.                         ' ', id.name : id.length);
  188.           IF idisnew THEN write(' *NEW* ');
  189.           IF idisold THEN BEGIN
  190.             write(' *OLD* --> ');
  191.             IF newptr <> item THEN WITH newptr^.id DO BEGIN
  192.               write(name : length); END
  193.             ELSE write(' itself!!'); END;
  194.           END; (* WITH item^ *)
  195.         writeln;
  196.       END; (* writecontent *)
  197.  
  198.     (* 2-----------------2 *)
  199.  
  200.     BEGIN  (* dumptable *)
  201.     IF debug THEN
  202.       IF base <> NIL THEN BEGIN
  203.         depth := succ(depth);
  204.         dumptable(base^.left);
  205.         writecontent(base);
  206.         dumptable(base^.right);
  207.         depth := pred(depth); END; (* base <> NIL *)
  208.     END; (* dumptable *)
  209.  
  210.   (* 1-----------------1 *)
  211.  
  212.   FUNCTION chclass(ch : char) : chtype;
  213.   (* May be incorrect for non-ASCII character sets,  *)
  214.   (* however all these dependencies are collected    *)
  215.   (* here, and a set of char is not required         *)
  216.  
  217.     BEGIN (* chclass *)
  218.     IF (ch >= 'A') AND (ch <= 'Z') THEN chclass := letter
  219.     ELSE IF (ch >= 'a') AND (ch <= 'z') THEN chclass := letter
  220.     ELSE IF (ch >= '0') AND (ch <= '9') THEN chclass := digit
  221.     ELSE IF ch = delim1 THEN chclass := prime
  222.     ELSE IF ch = delim2 THEN chclass := quote
  223.     ELSE IF ch = '(' THEN chclass := lparen
  224.     ELSE IF ch = '{' THEN chclass := lbrace
  225.     ELSE IF ch = '/' THEN chclass := slash
  226.     ELSE IF ch = ' ' THEN chclass := blank
  227.     ELSE IF ch = underch THEN chclass := under
  228.     ELSE IF ch = '<' THEN chclass := ltsy (* allow for SPL comments *)
  229.     ELSE IF ch = ';' THEN chclass := semi (* for 8080 comments *)
  230.     ELSE IF ch = dle THEN chclass := indent (* multi-blanks *)
  231.     ELSE IF (ch = '@') OR (ch = '.') THEN BEGIN
  232.       IF language = ASM8080 THEN chclass := letter
  233.       ELSE chclass := other END
  234.     ELSE chclass := other;
  235.     END; (* chclass *)
  236.  
  237.   (* 1-----------------1 *)
  238.  
  239.   PROCEDURE readid(VAR infile : text; VAR ident : string);
  240.  
  241.     CONST
  242.       ucnvt = -32; (* ord('A') - ord('a') *)
  243.  
  244.     VAR
  245.       ch    : char;
  246.  
  247.     BEGIN (* readid *)
  248.     WITH ident DO BEGIN
  249.       name := blanks; length := 0;
  250.       REPEAT
  251.         length := succ(length); read(infile, ch);
  252.         IF upshift THEN
  253.           IF ch IN ['a'..'z'] THEN name[length] := chr(ord(ch) + ucnvt)
  254.           ELSE name[length] := ch
  255.         ELSE IF downshift THEN
  256.           IF ch IN ['A'..'Z'] THEN name[length] := chr(ord(ch) - ucnvt)
  257.           ELSE name[length] := ch
  258.         ELSE name[length] := ch;
  259.       UNTIL eoln(infile) OR
  260.             (chclass(infile^) > under) OR
  261.             (length = maxlength);
  262.       END; (* WITH ident *)
  263.     END; (* readid *)
  264.  
  265.   (* 1---------------1 *)
  266.  
  267.   PROCEDURE readidpairsandcreatesymboltable;
  268.  
  269.     LABEL 97, 98; (* for fatal errors *)
  270.  
  271.     TYPE
  272.       idkind      = (oldkind, newkind);
  273.  
  274.     VAR
  275.       xtraid,
  276.       oldid,
  277.       newid       : string;
  278.       link        : nodeptr;     (* remember newid pointer *)
  279.       linenum     : integer;
  280.       flipflag,                  (* to reverse action of idpairs *)
  281.       incrhgt     : boolean;
  282.  
  283.     (* 2---------------2 *)
  284.  
  285.     PROCEDURE error;
  286.  
  287.       BEGIN (* error *)
  288.       writeln('on line number ' : 29, linenum : 1,
  289.             ' of "idpairs" file.');
  290.       END; (* error *)
  291.  
  292.     (* 2---------------2 *)
  293.  
  294.     PROCEDURE enter(VAR identifier : string; kind : idkind;
  295.                     VAR p : nodeptr; VAR higher : boolean);
  296.  
  297.       (* ################################################# *)
  298.       (* enter uses an avl-balanced tree search algorithm  *)
  299.       (* by Miklaus Wirth.  See section 4.4.7 in           *)
  300.       (* "ALGORITHMS+DATA STRUCTURES = PROGRAMS"           *)
  301.       (* ################################################# *)
  302.  
  303.       LABEL 99; (* for fatal error exit *)
  304.  
  305.       VAR
  306.         p1, p2      : nodeptr;
  307.  
  308.       BEGIN (* enter *)
  309.       IF p = NIL THEN BEGIN (* id not found in tree, insert it *)
  310.         new(p); higher := true;
  311.         WITH p^ DO BEGIN
  312.           id := identifier;
  313.           idisnew := kind = newkind;
  314.           idisold := kind = oldkind;
  315.           left := NIL; right := NIL; bal := even;
  316.           IF idisnew THEN BEGIN
  317.             link := p; seeninsource := false; END
  318.           ELSE newptr := link; END;
  319.         END
  320.       ELSE IF identifier.name < p^.id.name THEN BEGIN
  321.         enter(identifier, kind, p^.left, higher);
  322.         IF fatal THEN GOTO 99;
  323.         IF higher THEN  (* left branch has grown higher *)
  324.           CASE p^.bal OF
  325.   ritehigh: BEGIN
  326.             p^.bal := even; higher := false;
  327.             END;
  328.       even: p^.bal := lefthigh;
  329.   lefthigh: BEGIN                (* rebalance *)
  330.             p1 := p^.left;
  331.             IF p1^.bal = lefthigh THEN BEGIN (* single ll rotation *)
  332.               p^.left := p1^.right; p1^.right := p;
  333.               p^.bal := even; p := p1; END
  334.             ELSE BEGIN          (* double lr rotation *)
  335.               p2 := p1^.right; p1^.right := p2^.left;
  336.               p2^.left := p1; p^.left := p2^.right;
  337.               p2^.right := p;
  338.               IF p2^.bal = lefthigh THEN p^.bal := ritehigh
  339.               ELSE p^.bal := even;
  340.               IF p2^.bal = ritehigh THEN p1^.bal := lefthigh
  341.               ELSE p1^.bal := even;
  342.               p := p2; END; (* double lr rotation *)
  343.             p^.bal := even; higher := false; END;
  344.           END; (* case *)
  345.         END (* identifier.name < p^.id.name *)
  346.       ELSE IF identifier.name > p^.id.name THEN BEGIN
  347.         enter(identifier, kind, p^.right, higher);
  348.         IF fatal THEN GOTO 99;
  349.         IF higher THEN  (* right branch has grown *)
  350.           CASE p^.bal OF
  351.   lefthigh: BEGIN
  352.             p^.bal := even; higher := false;
  353.             END;
  354.       even: p^.bal := ritehigh;
  355.   ritehigh: BEGIN                (* rebalance *)
  356.             p1 := p^.right;
  357.             IF p1^.bal = ritehigh THEN BEGIN (* single rr rotation *)
  358.               p^.right := p1^.left; p1^.left := p;
  359.               p^.bal := even; p := p1; END
  360.             ELSE BEGIN          (* double rl rotation *)
  361.               p2 := p1^.left; p1^.left := p2^.right;
  362.               p2^.right := p1; p^.right := p2^.left;
  363.               p2^.left := p;
  364.               IF p2^.bal = ritehigh THEN p^.bal := lefthigh
  365.               ELSE p^.bal := even;
  366.               IF p2^.bal = lefthigh THEN p1^.bal := ritehigh
  367.               ELSE p1^.bal := even;
  368.               p := p2; END;
  369.             p^.bal := even; higher := false; END;
  370.           END; (* case *)
  371.         END (* identifier.name > p^.id.name *)
  372.       ELSE BEGIN                (* identifier is already in tree *)
  373.         higher := false;
  374.         WITH p^ DO  BEGIN
  375.           IF idisold THEN
  376.             IF kind = oldkind THEN BEGIN (* duplicate oldid's *)
  377.               writeln('*** duplicate OLDID encountered: ',
  378.                       identifier.name);
  379.               error; fatal := true; GOTO 99; END
  380.             ELSE BEGIN
  381.               idisnew := true; link := p; END
  382.           ELSE IF kind = newkind THEN BEGIN
  383.             writeln('--- warning+  ', identifier.name,
  384.                   ' has also appeared as another newid');
  385.             error; link := p; END
  386.           ELSE BEGIN
  387.             idisold := true; newptr := link; END
  388.           END; (* WITH *)
  389.         END; (* identifier already in tree *)
  390.   99: END; (* enter *)
  391.  
  392.     (* 2---------------2 *)
  393.  
  394.     PROCEDURE truncate(VAR ident : string);
  395.  
  396.       BEGIN (* truncate *)
  397.       writeln('---WARNING: truncation for identifier, ',
  398.             ident.name);
  399.       writeln('Extra chapacters ignored.' : 39);
  400.       error;
  401.       REPEAT
  402.         get(idpairs);
  403.       UNTIL chclass(idpairs^) > under;
  404.       END; (* truncate *)
  405.  
  406.     (* 2---------------2 *)
  407.  
  408.     BEGIN (* readidpairsandcreatesymboltable *)
  409.     IF exists(idpairs) THEN BEGIN
  410.       idtable := NIL; linenum := 1;
  411.       incrhgt := false; flipflag := false;
  412.       WHILE NOT eof(idpairs) DO BEGIN
  413.         WHILE (idpairs^ = ' ') AND NOT eoln(idpairs) DO get(idpairs);
  414.         IF chclass(idpairs^) = letter THEN BEGIN
  415.           readid(idpairs, oldid);
  416.           IF chclass(idpairs^) <= under THEN truncate(oldid);
  417.           WHILE NOT eoln(idpairs)
  418.                 AND (  (idpairs^=' ')
  419.                     OR (idpairs^=',') ) DO get(idpairs);
  420.           IF chclass(idpairs^) = letter THEN BEGIN
  421.             readid(idpairs, newid);
  422.             IF chclass(idpairs^) <= under THEN truncate(newid);
  423.             IF flipflag THEN xtraid := oldid
  424.             ELSE xtraid := newid;
  425.             enter(xtraid, newkind, idtable, incrhgt);
  426.             IF fatal THEN GOTO 98; (* fatal error exit *)
  427.             IF debug THEN
  428.               IF growthflag THEN BEGIN
  429.                 writeln;
  430.                 writeln('Entering ',xtraid.name:xtraid.length);
  431.                 dumptable(idtable); END;
  432.             IF flipflag THEN xtraid := newid ELSE xtraid := oldid;
  433.             enter(xtraid, oldkind, idtable, incrhgt);
  434.             IF fatal THEN GOTO 98;  (* fatal error exit *)
  435.             IF debug THEN
  436.               IF growthflag THEN BEGIN
  437.                 writeln;
  438.                 writeln('Entering ', xtraid.name : xtraid.length);
  439.                 dumptable(idtable); END;
  440.             END
  441.           ELSE BEGIN
  442.             writeln('---WARNING: malformed idpair'); error; END;
  443.           END   (* chclass=letter *)
  444.         ELSE IF idpairs^ = '$' THEN BEGIN (* possible option control *)
  445.           get(idpairs);
  446.           IF chclass(idpairs^) = letter THEN BEGIN
  447.             readid(idpairs, newid);
  448.             IF newid = splwd THEN BEGIN (* set spl options *)
  449.               IF language <> pascal THEN GOTO 97; (* one change only *)
  450.               underch := ''''; delim1 := '"'; delim2 := '"';
  451.               language := spl; END
  452.             ELSE IF newid = asm8080wd THEN BEGIN
  453.               (* 8080 assembly options *)
  454.               IF language <> pascal THEN GOTO 97; (* one change only *)
  455.               delim2 := '"'; language := asm8080; END
  456.             ELSE IF newid = cwd THEN BEGIN (* c language options *)
  457.               IF language <> pascal THEN GOTO 97; (* one change only *)
  458.               delim2 := '"'; language := c; END
  459.             ELSE IF (newid = flipwd) AND NOT flipflag THEN
  460.               flipflag := true
  461.             ELSE IF (newid = upshiftwd) AND NOT downshift THEN
  462.               upshift := true
  463.             ELSE IF (newid = downshftwd) AND NOT upshift THEN
  464.               downshift := true
  465.             ELSE GOTO 97; (* bad option is fatal *) END (* letter *)
  466.           ELSE BEGIN (* option error *)
  467. 97:         writeln('*** Fatal error, bad option');
  468.             error; fatal := true; GOTO 98; END;
  469.           END (* option control *)
  470.         ELSE BEGIN
  471.           writeln('---WARNING: malformed idpair'); error; END;
  472.         readln(idpairs); linenum := succ(linenum);  END;
  473.       END; (* idpairs exists *)
  474. 98: END; (* readidpairsandcreatesymboltable *)
  475.  
  476.   (* 1---------------1 *)
  477.  
  478.   PROCEDURE editsourcetotarget;
  479.  
  480.     LABEL 1, 2;
  481.  
  482.     VAR
  483.       sourceid    : string;
  484.       lineno      : integer;
  485.  
  486.     (* 2---------------2 *)
  487.  
  488.     PROCEDURE substitute(VAR identifier : string; p : nodeptr);
  489.  
  490.       (* 3---------------3 *)
  491.  
  492.       PROCEDURE writesourceid;
  493.  
  494.         BEGIN (* writesourceid *)
  495.         WITH sourceid DO write(target, name: length);
  496.         WHILE chclass(source^) <= under DO BEGIN
  497.           write(target, source^); get(source); END;
  498.         END; (* writesourceid *)
  499.  
  500.       (* 3---------------3 *)
  501.  
  502.       BEGIN (* substitute *)
  503.       IF p = NIL THEN (* identifier not in tree, echo *)
  504.         writesourceid
  505.       ELSE IF identifier.name > p^.id.name THEN
  506.         substitute(identifier, p^.right)
  507.       ELSE IF identifier.name < p^.id.name THEN
  508.         substitute(identifier, p^.left)
  509.       ELSE WITH p^ DO            (* found *)
  510.         IF idisold THEN BEGIN
  511.           WITH newptr^.id DO  write(target, name: length);
  512.           WHILE chclass(source^) <= under DO get(source); END
  513.         ELSE BEGIN
  514.           seeninsource := true; writesourceid; END;
  515.       END; (* substitute *)
  516.  
  517.     (* 2---------------2 *)
  518.  
  519.     PROCEDURE skipstring(delim : char);
  520.  
  521.       BEGIN (* skipstring *)
  522.       REPEAT
  523.         write(target, source^); get(source);
  524.       UNTIL (source^ = delim) OR eoln(source);
  525.       IF eoln(source) THEN
  526.         writeln('---WARNING: Unclosed string in source program line ',
  527.                  lineno : 1);
  528.       END; (* skipstring *)
  529.  
  530.     (* 2---------------2 *)
  531.  
  532.     PROCEDURE absorbcomment(ender : char); (* ?* ... *? *)
  533.  
  534.       BEGIN (* absorbcomment *)
  535.       write(target, source^); get(source);
  536.       IF source^ = '*' THEN BEGIN (* comment *)
  537.         REPEAT
  538.           write(target, source^); get(source);
  539.           WHILE source^ <> '*' DO BEGIN
  540.             IF eoln(source) THEN writeln(target)
  541.             ELSE write(target, source^);
  542.             get(source); END;
  543.           write(target, source^); get(source);
  544.         UNTIL source^ = ender;
  545.         write(target, source^); get(source); END;
  546.       END; (* absorbcomment *)
  547.  
  548.     (* 2---------------2 *)
  549.  
  550.     BEGIN (* editsourcetotarget *)
  551.     reset(source); rewrite(target); lineno := 0;
  552.     WHILE NOT eof(source) DO BEGIN
  553.       lineno := succ(lineno);
  554.       WHILE NOT eoln(source) DO
  555.         CASE chclass(source^) OF
  556.   letter,
  557.   under:  BEGIN
  558.           readid(source, sourceid);
  559.           IF language = spl THEN
  560.             IF (sourceid = cmntwd) OR (sourceid = cmntwdl) THEN BEGIN
  561.               write(target,sourceid.name : sourceid.length);
  562.               REPEAT
  563.                 IF eoln(source) THEN writeln(target)
  564.                 ELSE write(target,source^);
  565.                 get(source);
  566.               UNTIL source^ = ';'; END
  567.             ELSE substitute(sourceid, idtable)
  568.           ELSE substitute(sourceid, idtable) END;
  569.    digit: REPEAT
  570.             write(target, source^); get(source);
  571.           UNTIL (chclass(source^) <> digit)
  572.                  AND (source^ <> '.')
  573.                  AND (source^ <> 'E')
  574.                  AND (source^ <> 'e');
  575.    quote: BEGIN
  576.           skipstring(delim2);
  577.           IF eoln(source) THEN GOTO 2;
  578.           write(target, source^); get(source);
  579.           END;
  580.    prime: BEGIN
  581.           skipstring(delim1);
  582.           IF eoln(source) THEN GOTO 2;
  583.           write(target, source^); get(source);
  584.           END;
  585.   lbrace: BEGIN                (* stdcomment *)
  586.           IF language <> pascal THEN GOTO 1;
  587.           REPEAT
  588.             IF eoln(source) THEN writeln(target)
  589.             ELSE write(target, source^);
  590.             get(source);
  591.           UNTIL source^ = '}';
  592.           write(target, source^); get(source);
  593.           END;
  594.    slash: BEGIN
  595.           IF language <> c THEN GOTO 1;
  596.           absorbcomment('/');
  597.           END;
  598.   lparen: BEGIN
  599.           IF language <> pascal THEN GOTO 1;
  600.           absorbcomment(')');
  601.           END;
  602.     ltsy: BEGIN (* spl comment *)
  603.           IF language <> spl THEN GOTO 1;
  604.           write(target, source^); get(source);
  605.           IF source^ = '<' THEN BEGIN (* comment *)
  606.             REPEAT
  607.               write(target, source^); get(source);
  608.               WHILE source^ <> '>' DO BEGIN
  609.                 IF eoln(source) THEN writeln(target)
  610.                 ELSE write(target, source^);
  611.                 get(source); END;
  612.               write(target, source^); get(source);
  613.             UNTIL source^ = '>';
  614.             write(target, source^); get(source); END;
  615.           END;
  616.     semi: BEGIN
  617.           IF language <> asm8080 THEN GOTO 1;
  618.           REPEAT    (* absorb 8080 source comment line *)
  619.             write(target, source^); get(source);
  620.           UNTIL eoln(source);
  621.           END;
  622.   indent: BEGIN (* special indentation code *)
  623.           write(target, dle); get(source);
  624.           IF NOT eoln(source) AND (source^ >= ' ') THEN BEGIN
  625.             write(target, source^); get(source); END;
  626.           END;
  627.   other, 
  628.   blank,
  629.   special:
  630.   1:      BEGIN
  631.           write(target, source^); get(source);
  632.           END;
  633.         END; (* case, while not eoln *)
  634.   2:  readln(source); writeln(target); END; (* while not eof *)
  635.     END; (* editsourcetotarget *)
  636.  
  637.   (* 1---------------1 *)
  638.  
  639.   PROCEDURE checkseeninsource(p : nodeptr);
  640.  
  641.     BEGIN (* checkseeninsource *)
  642.     IF p <> NIL THEN
  643.       WITH p^ DO BEGIN
  644.       checkseeninsource(left);
  645.       IF idisnew AND NOT idisold THEN
  646.         IF seeninsource THEN BEGIN
  647.           writeln('---WARNING: ', id.name : id.length,
  648.                 ' was specified as a new identifier ');
  649.           writeln(' and was also seen in the source'); END;
  650.       checkseeninsource(right) END
  651.     END; (* checkseeninsource *)
  652.  
  653.   (* 1---------------1 *)
  654.  
  655.   BEGIN (* id2id *)
  656.   initialize;
  657.   readidpairsandcreatesymboltable;
  658.   IF NOT fatal THEN BEGIN
  659.     IF debug THEN BEGIN
  660.       writeln; writeln;
  661.       writeln(' SYMBOL TABLE CONTENTS');
  662.       dumptable(idtable);
  663.       writeln; END; (* IF display *)
  664.     editsourcetotarget;
  665.     checkseeninsource(idtable); END;
  666.   END. (* id2id *)
  667. 4░