home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol022 / xrefg2.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  17.8 KB  |  646 lines

  1. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  2. {+                            +}
  3. {+  PROGRAM TITLE:    Cross Reference Generator    +}
  4. {+                            +}
  5. {+  WRITTEN BY:        Peter Grogono            +}
  6. {+  DATE WRITTEN:    ?                +}
  7. {+                            +}
  8. {+  SUMMARY:                        +}
  9. {+                            +}
  10. {+    1. Output Files:                +}
  11. {+       default is to disk files:            +}
  12. {+       a. output file = file name + '.XRF'        +}
  13. {+          all identifiers and their line #        +}
  14. {+       b. output file = file name + '.PRN'        +}
  15. {+          the file with all lines numbered        +}
  16. {+    2. LISTING Device:                +}
  17. {+       Output may be to either the console or    +}
  18. {+       the printer but NOT both.            +}
  19. {+                            +}
  20. {+  MODIFICATION RECORD:                +}
  21. {+    12-AUG-80    -modified for Pascal/Z v3.0    +}
  22. {+            -by Raymond E. Penley        +}
  23. {+    16-AUG-80    -added function ConnectFiles    +}
  24. {+    17-AUG-80    -added GetL, ReadC, ReadWord    +}
  25. {+      22-AUG-80    -selective use of control-c    +}
  26. {+                            +}
  27. {+                            +}
  28. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  29. PROGRAM XREFG2;
  30. { Cross Reference Generator }
  31. (*$P-,F-,M- [symbolic I/O OFF,
  32.          floating point checking OFF,
  33.          integer mult & div checking OFF]        *)
  34. CONST
  35.     alfa_length    =    8;
  36.     BLANKS        = '        ';
  37.     dflt_str_len    = 255;
  38.     entrygap    =    0;   { # of blank lines between line numbers}
  39.     fid_len        =   14;   { Max length CP/M file names }
  40.     heading        = 'Cross-Reference Listing';
  41.     headingsize    =    3;   {number of lines for heading}
  42.     LLmax        = dflt_str_len;
  43. {}    MaxOnLine    =   10;
  44.     Maxlines    = MAXINT; {longest document permitted}
  45.     MaxWordlen    = alfa_length;{longest word read without truncation}
  46.     Maxlinelen    =   80;   {length of output line}
  47.     MaxOnPage    =   60;   {size of output page}
  48.     numbergap    =    2;   {number of gaps between line numbers}
  49. {}    NumKeys        =   46;   {number of Pascal reseve words}
  50.                   {Read your Pascal manuals on this one!}
  51. {}    NumKeysP1    = NumKeys + 1;
  52. {}    NumberWidth    =    6;
  53.     space        =  ' ';
  54.  
  55. TYPE
  56. {}    ALFA    = PACKED ARRAY[1..alfa_length] OF CHAR;
  57. {}    BYTE    = 0..255;
  58. {}    CHARNAME = (lletter, uletter, digit, blank, quote, atab,
  59.               EndOfLine, FileMark, otherchar );
  60. {}    CHARINFO = RECORD
  61.              name : charname;
  62.              valu : CHAR
  63.            END;
  64.     COUNTER    = 1..Maxlines;
  65. {}    dfltstr    = string dflt_str_len;
  66.     FID    = string fid_len;
  67.     lineindex = 1..Maxlinelen;
  68. {}    pageindex = BYTE;
  69.     Wordindex = 1..MaxWordlen;
  70.     Queuepointer = ^Queueitem;
  71.     Queueitem = RECORD
  72.             linenumber : counter;
  73.             NextInQueue: Queuepointer
  74.             END;
  75.     EntryType = RECORD
  76.             Wordvalue : alfa;
  77.             FirstInQueue,
  78.             lastinQueue: Queuepointer
  79.              END;
  80.     treepointer = ^node;
  81.     node = RECORD
  82.          entry : EntryType;
  83.          left,
  84.          right : treepointer
  85.            END;
  86.  
  87.     S$0    = string 0;
  88.     S$255    = string 255;
  89.  
  90. VAR
  91.   bell        : CHAR;
  92.   blankindex    : BYTE;
  93.   currchar,            { Current operative character }
  94.   nextchar     : charinfo;    { Look-ahead character }
  95.   fatal_error    : BOOLEAN;
  96.   FILE_ID,            { CP/M file name }
  97.   PRN_ID,            { basic file name + '.PRN' }
  98.   New_ID      : FID;        { basic file name + '.XRF' }
  99.   fbuffer      : dfltstr;    { Format buffer - before final Print }
  100.   FIN        : TEXT;
  101.   flushing     : (KNOT, DBL, STD, LIT);
  102.   form_feed    : CHAR;
  103.   Key        : ARRAY[1..NumKeysP1] OF alfa;
  104.   letters     : SET OF CHAR;
  105.   LISTING    : BOOLEAN;
  106.   Look           : char;    { Character read in from File }
  107. {}{OUTPUT    : TEXT;  }    { Listing device -console or printer }
  108.   tab           : CHAR;
  109.   wordcount    : INTEGER;    { total # of words in file }
  110.   WordTree     : treepointer;
  111.   xeof,            { EOF status AFTER a read }
  112.   xeoln        : BOOLEAN;    { EOLN status after a read }
  113.  
  114. (*$C- [Control-C OFF]***********************************************)
  115.  
  116. FUNCTION length(x: S$255): INTEGER; EXTERNAL;
  117. PROCEDURE setlength(VAR x: S$0; y: INTEGER); EXTERNAL;
  118. FUNCTION index(x,y: S$255): INTEGER; EXTERNAL;
  119.  
  120. PROCEDURE PAGE(VAR fx: TEXT);
  121. BEGIN
  122.   WRITE(fx, form_feed);
  123. END;
  124.  
  125. PROCEDURE CLEAR{output};
  126. VAR
  127.   ix : 1..24;
  128. BEGIN
  129.   FOR ix:=1 TO 24 DO WRITELN;
  130. END;
  131.  
  132.  
  133.  
  134. PROCEDURE BuildTree(VAR tree: treepointer);
  135. VAR
  136.   CurrentWord : alfa;
  137.   Currentline: INTEGER;
  138.   FOUT: TEXT; { local output file }
  139.  
  140.  
  141.    PROCEDURE Entertree(VAR subtree: treepointer;
  142.                Word   : alfa;
  143.                line   :counter);
  144.    VAR
  145.      nextitem : Queuepointer;
  146.    BEGIN
  147.      IF subtree=nil THEN
  148.        BEGIN {create a new entry}
  149.      NEW(subtree);
  150.      WITH subtree^ DO BEGIN
  151.        left := nil;
  152.        right := nil;
  153.        WITH entry DO BEGIN
  154.          Wordvalue := Word;
  155.          NEW(FirstInQueue);
  156.          LastinQueue := FirstInQueue;
  157.          WITH FirstInQueue^ DO BEGIN
  158.         linenumber := line;
  159.         NextInQueue := nil;
  160.          END;{WITH FirstInQueue}
  161.        END;{WITH entry}
  162.      END;{WITH subtree}
  163.        END {create a new entry}
  164.      ELSE {append a list item}
  165.        WITH subtree^, entry DO
  166.      IF Word=Wordvalue THEN
  167.        BEGIN
  168.          IF lastinQueue^.linenumber <> line THEN
  169.         BEGIN
  170.           NEW(nextitem);
  171.           WITH Nextitem^ DO BEGIN
  172.             linenumber := line;
  173.             NextInQueue := nil;
  174.           END;{WITH}
  175.           lastinQueue^.NextInQueue := Nextitem;
  176.           lastinQueue := nextitem;
  177.         END;
  178.        END
  179.      ELSE
  180.        IF Word < Wordvalue THEN
  181.          Entertree(left,Word,line)
  182.        ELSE
  183.          Entertree(right,Word,line);
  184.    END;{Entertree}
  185.  
  186. Procedure ReadC({updating} VAR nextchar : charinfo;
  187.         {returning}VAR currchar : charinfo );
  188. { revised 4 Jan 80, rep }
  189. { Defined the chars "^", "$", and "_" as lowercase letters }
  190. BEGIN    {+++ File status module. +++
  191.    Stores file status "AFTER" a read.
  192.    NOTE this play on words - after one char is
  193.    actually "PRIOR TO" the next character        }
  194.   xeoln := EOLN(FIN);
  195.   xeof  := EOF(FIN);
  196.     {+++ read BYTE module +++}
  197.   IF NOT xeof THEN
  198.         READ(FIN, Look);
  199.     {+++ current operative character module +++}
  200.   currchar := nextchar;
  201.     {+++ Classify the character just read +++}
  202.   WITH nextchar DO BEGIN{ Look-ahead character name module }
  203.     IF xeof THEN
  204.     name := FileMark
  205.     ELSE IF xeoln THEN
  206.     name := EndOfLine
  207.     ELSE IF Look IN ['^', '$', '_', 'a'..'z'] THEN {lower case plus}
  208.     name := lletter
  209.     ELSE IF Look IN ['A'..'Z'] THEN {upper case}
  210.     name := uletter
  211.     ELSE IF Look IN ['0'..'9'] THEN {digit}
  212.     name := digit
  213.     ELSE IF Look = '''' THEN
  214.     name := quote
  215.     ELSE IF Look = TAB THEN
  216.     name := atab
  217.     ELSE IF Look = space THEN
  218.     name := blank
  219.     ELSE
  220.     name := otherchar;
  221.     CASE name of{ store character value module }
  222.     EndOfLine,
  223.     FileMark:    Valu := space;
  224.     ELSE:        Valu := Look
  225.     END{ case name of };
  226.   End{ Look-ahead character name module };
  227. END; {of ReadC}
  228.  
  229. PROCEDURE GetL( VAR fbuffer : dfltstr );
  230. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  231. {+    Get a line of text into users buffer.        +}
  232. {+    Flushes comment lines:                +}
  233. {+    Flushes lines of Literals:  'this is it'    +}
  234. {+    Ignores special characters & tabs:        +}
  235. {+    Recognizes End of File and End of Line.        +}
  236. {+                            +}
  237. {+GLOBAL                        +}
  238. {+    flushing : (KNOT, DBL, STD, LIT);        +}
  239. {+    fbuffer = dfltstr                +}
  240. {+    LLmax   = 0..Max Line length;            +}
  241. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  242. VAR
  243.   state : (scanning, terminal, overflow);
  244. BEGIN { GetL }
  245.    setlength(fbuffer,0);
  246.    fatal_error := FALSE;
  247.    state := scanning;
  248.   REPEAT
  249.     ReadC(nextchar, currchar);
  250. {}  WRITE(FOUT, currchar.valu);
  251. {}  IF listing THEN
  252.        WRITE( {OUTPUT,} currchar.valu);
  253.     IF (length(fbuffer) >= LLmax) THEN{ exceeded length of buffer }
  254.       BEGIN{ reset EOLN }
  255.     fatal_error := TRUE;
  256.     state := overflow;
  257.     setlength(fbuffer,0);
  258.     WRITE(bell);
  259.     WRITELN('EXCEEDED LENGTH OF INPUT BUFFER');
  260.       END
  261.     ELSE
  262.       BEGIN
  263.     IF (currchar.name IN [FileMark,EndOfLine]) THEN
  264.           state:=terminal{ END of line or END of file };
  265.     CASE flushing of
  266.         KNOT:
  267.         CASE currchar.name of
  268.         lletter, uletter, digit, blank:
  269.             BEGIN{ store }
  270.             append(fbuffer,currchar.valu);
  271.             END;
  272.         atab, quote, otherchar:
  273.             BEGIN{     Flush comments    -convert
  274.                      tabs & other chars to spaces }
  275.             IF (currchar.valu='(') and (nextchar.valu='*')
  276.               THEN flushing := DBL
  277.             ELSE IF (currchar.valu='{') THEN 
  278.                flushing := STD
  279.             ELSE IF currchar.name=quote THEN
  280.                flushing := LIT;
  281.             { convert to a space }
  282.             append(fbuffer,space);
  283.             END;
  284.         else:    { END of line -or- file mark }
  285.             append(fbuffer,currchar.valu)
  286.         END{ case currchar name of };
  287.         DBL:  { scanning for a closing  - double comment }
  288.         IF (currchar.valu ='*') and (nextchar.valu =')')
  289.           THEN flushing := KNOT;
  290.         STD:  { scanning for a closing curley  }
  291.           IF currchar.valu = '}' THEN
  292.               flushing := KNOT;
  293.         LIT:  { scanning for a closing quote }
  294.           IF currchar.name = quote THEN
  295.             flushing := KNOT
  296.         END{ flushing case }
  297.       END{ ELSE }
  298.   UNTIL (state<>scanning);
  299. END; {of GetL}
  300.  
  301. PROCEDURE ReadWord;
  302. {++++++++++++++++++++++++++++++++++++++++++++++++}
  303. {+                        +}
  304. {+     Analyze the Line into "words"        +}
  305. {+                        +}
  306. {++++++++++++++++++++++++++++++++++++++++++++++++}
  307. LABEL    1;
  308. CONST
  309.   TOP = NumKeys    + 1;
  310. VAR
  311.   ix,        {temp indexer}
  312.   idlen,    {length of the word}
  313.   Cpos : BYTE; { Current Position pointer }
  314.  
  315. BEGIN{ ReadWord }
  316.   Cpos := 1; { start at the beginning of a line }
  317.   WHILE Cpos < length(fbuffer) DO
  318.     BEGIN {Cpos<length(fbuffer)}
  319.       WHILE (Cpos < length(fbuffer)) AND (fbuffer[Cpos]=space) DO
  320.     Cpos:=Cpos + 1;       {--- skip spaces ---}
  321.  
  322.       idlen := 0;
  323.       WHILE (Cpos < length(fbuffer)) AND (fbuffer[Cpos ] <> space) DO
  324.     BEGIN{ accept only non-spaces }
  325.       IF idlen < MaxWordlen THEN
  326.         BEGIN
  327.           idlen := idlen + 1;
  328.           CurrentWord[idlen] := fbuffer[Cpos];
  329.         END;
  330.       Cpos := Cpos +1;
  331.     END{ WHILE };
  332. {}    IF idlen=0 THEN {no word was found} GOTO 1;
  333.  
  334.       IF idlen >= blankindex THEN
  335.     blankindex := idlen
  336.       ELSE
  337.     REPEAT
  338.       CurrentWord[blankindex] := space;
  339.       blankindex := blankindex - 1;
  340.     UNTIL blankindex=idlen;
  341.       WordCount := WordCount + 1;
  342.       {++++++++++++++++++++++++++++++++++}
  343.       {+   linear search with sentinel    +}
  344.       {++++++++++++++++++++++++++++++++++}
  345.       Key[TOP] := CurrentWord;
  346.       ix := 0;
  347.       REPEAT
  348.         ix := ix + 1;
  349.       UNTIL Key[ix] = CurrentWord;
  350.       {++++++++++++++++++++++++++++++++++}
  351. {}    IF ix=TOP THEN {CurrentWord is not a reserve word, so}
  352.      EnterTree(tree,CurrentWord,Currentline);
  353.       1:{Here is no word <length of word=0>};
  354.     END; {WHILE Cpos<length(fbuffer)}
  355. END; {of Readword}
  356.  
  357. BEGIN{BuildTree}
  358. {}REWRITE(PRN_ID, FOUT);
  359.   PAGE(FOUT);
  360.   Currentline := 0;
  361.   nextchar.name := blank;    { Initialize next char to a space }
  362.   nextchar.valu := space;
  363.   ReadC({update}    nextchar,    { Initialize current char to space }
  364.     {returning} currchar);    { First char from file in nextchar }
  365.   WHILE ((currchar.name<>filemark) AND (NOT fatal_error)) DO
  366.     BEGIN
  367.       Currentline := Currentline + 1;
  368.       WRITE(FOUT, Currentline:6,': ');
  369.       IF listing THEN WRITE({OUTPUT,} Currentline:6,': ');
  370.       GetL(fbuffer) { attempt to read the first line };
  371.       WRITELN(FOUT);
  372.       IF listing THEN WRITELN{output};
  373.       ReadWord; {Analyze the Text into single 'words' }
  374.     END; {While}
  375.   PAGE(FOUT);
  376. END; {of BuildTree}{CLOSE(PRN_ID);}
  377.  
  378.  
  379. PROCEDURE PrintTree(tree: treepointer);
  380. {
  381. GLOBAL
  382.     MaxOnLine   = max line references per line
  383.     NumberWidth = field for each number
  384. }
  385. VAR
  386.   FOUT: TEXT; { local output file }
  387.   pageposition: pageindex;
  388.  
  389.    PROCEDURE PrintEntry(subtree: treepointer;
  390.             VAR position: pageindex);
  391.    VAR    ix: Wordindex;
  392.     itemcount : 0..Maxlinelen;
  393.     itemptr : Queuepointer;
  394.  
  395.     PROCEDURE PrintLine(VAR Currentposition: pageindex;
  396.                     newlines: pageindex);
  397.     VAR
  398.       linecounter: pageindex;
  399.     BEGIN
  400. {}      IF (Currentposition + newlines) < MaxOnPage THEN
  401.         BEGIN
  402. {}        FOR linecounter:=1 TO newlines DO WRITELN(FOUT);
  403. {}        IF listing THEN
  404.           FOR linecounter:=1 TO newlines DO WRITELN{OUTPUT};
  405.         Currentposition := Currentposition + newlines;
  406.         END
  407.       ELSE
  408.         BEGIN
  409. {}          PAGE(FOUT);
  410. {}          WRITELN(FOUT,heading);
  411. {}          FOR linecounter := 1 TO headingsize - 1 DO
  412.          WRITELN(FOUT);
  413. {}          IF listing THEN
  414.         BEGIN
  415.           CLEAR{OUTPUT}; {PAGE(OUTPUT);}
  416.           WRITELN({OUTPUT,} heading);
  417.           FOR linecounter := 1 TO headingsize - 1 DO
  418.              WRITELN{OUTPUT};
  419.         END;
  420.           Currentposition := headingsize + 1;
  421.         END
  422.     END;{PrintLine}
  423.  
  424.    BEGIN{PrintEntry}
  425.      IF subtree<>nil THEN
  426.     WITH subtree^ DO BEGIN
  427.       PrintEntry(left,position);
  428.       PrintLine(position,entrygap + 1);
  429.       WITH entry DO BEGIN
  430. {}        FOR ix:=1 TO MaxWordlen DO
  431.           WRITE(FOUT, WordValue[ix]);
  432. {}        IF listing THEN
  433.            FOR ix:=1 TO MaxWordlen DO
  434.           WRITE({OUTPUT,} WordValue[ix]);
  435.         itemcount := 0;
  436.         itemptr := FirstInQueue;
  437.         WHILE itemptr <> nil DO
  438.           BEGIN
  439.         itemcount := itemcount + 1;
  440.         IF itemcount > MaxOnLine THEN
  441.           BEGIN
  442.             PrintLine(position,1);
  443. {}            WRITE(FOUT, space:MaxWordlen);
  444. {}            IF listing THEN 
  445.                WRITE({OUTPUT,} space:MaxWordlen);
  446.             itemcount := 1;
  447.           END;
  448. {}        WRITE(FOUT, itemptr^.linenumber: numberwidth);
  449. {}        IF listing THEN
  450.            WRITE({OUTPUT,}itemptr^.linenumber: numberwidth);
  451.         itemptr := itemptr^.NextInQueue;
  452.           END;{WHILE}
  453.       END; {WITH entry}
  454.       PrintEntry(right,position);
  455.     END; {WITH subtree^}
  456.    END; {PrintEntry}
  457.  
  458. BEGIN{PrintTree}
  459. {}REWRITE(New_ID, FOUT);
  460.   PAGE(FOUT);
  461.   PagePosition := MaxOnPage;
  462.   PrintEntry(tree,PagePosition);
  463.   PAGE(FOUT);
  464. END; {of PrintTree}{CLOSE(New_ID);}
  465.  
  466. (*$C+ [Control-C ON]*******************************)
  467.  
  468. FUNCTION ConnectFiles: boolean;
  469. TYPE
  470.   Linebuffer = string 80;
  471. VAR
  472.   ix,jx,
  473.   Cmllen  : BYTE;
  474.   Cmlline : Linebuffer;
  475.  
  476.     PROCEDURE GCML( VAR line : linebuffer;
  477.             VAR len  : BYTE  );
  478.     {++++++++++++++++++++++++++++++++++++++++++++++++}
  479.     {+ READ the system command line.        +}
  480.     {+ THIS MUST be the very first read in the    +}
  481.     {+ entire program!                +}
  482.     {++++++++++++++++++++++++++++++++++++++++++++++++}
  483.     CONST    input = 0;    { !!!!  PASCAL/Z   !!! }
  484.     BEGIN
  485.       setlength(line,0);
  486.       len := 0;
  487.       IF NOT EOLN(input) THEN
  488.         BEGIN
  489.           READLN(line);
  490.           len := length(line);
  491.         END;
  492.     END; {of GCML}
  493.  
  494.     PROCEDURE PAD(VAR this_ID: fid; required: BYTE);
  495.     BEGIN
  496.       WHILE (length(this_ID)<required) DO
  497.         append(this_ID,space);
  498.     END;
  499.  
  500. BEGIN{ ConnectFiles }
  501.   fatal_error := FALSE;
  502.   ConnectFiles := TRUE;
  503.   GCML(Cmlline, Cmllen);
  504.   IF (Cmllen=0) THEN { no file name from the console }
  505.     BEGIN
  506.       setlength(FILE_ID,0);
  507.       WRITELN;
  508.       WRITE('Enter <Drive:> FILE name - ');
  509.       READLN(FILE_ID);
  510.     END
  511.   ELSE
  512.       FILE_ID := Cmlline;
  513.   IF (length(FILE_ID)>fid_len) THEN
  514.         setlength(FILE_ID,fid_len);
  515.   PAD(FILE_ID, fid_len);
  516.   RESET(FILE_ID, FIN);
  517.   IF EOF(FIN) THEN{ ABORT }
  518.     BEGIN
  519.       WRITE(bell);
  520.       WRITELN('FILE NOT FOUND');
  521.       fatal_error := TRUE;
  522.       ConnectFiles := FALSE;
  523.     END
  524.   ELSE
  525.     BEGIN
  526.       ix := index(FILE_ID,'.'); { search for an extension }
  527.       jx := index(FILE_ID,' '); { search for the first space }
  528.       IF (ix=0) THEN{ no extension was specified }
  529.         setlength(FILE_ID,jx-1)
  530.       ELSE
  531.         setlength(FILE_ID,ix-1);
  532.  
  533.     setlength(New_ID,0);    { New_ID := CONCAT(FILE_ID, '.XRF'); }
  534.     append(New_ID, FILE_ID);
  535.     append(New_ID, '.XRF');
  536.     PAD(New_ID, fid_len);
  537.  
  538.     setlength(PRN_ID,0);    { PRN_ID := CONCAT(FILE_ID, '.PRN'); }
  539.     append(PRN_ID, FILE_ID);
  540.     append(PRN_ID, '.PRN');
  541.     PAD(PRN_ID, fid_len);
  542.  
  543.     END;
  544. END{ of ConnectFiles };
  545.  
  546. (*$C- [control-c OFF]***********************************)
  547.  
  548. PROCEDURE Initialize;
  549. VAR
  550.   Ch: CHAR;
  551.   con_wanted,
  552.   tty_wanted : BOOLEAN;
  553. BEGIN
  554.   bell := CHR(7);
  555.   IF ConnectFiles THEN
  556.     BEGIN
  557.       letters := ['A'..'Z','a'..'z'];
  558.     Key[ 1] := 'AND     ';
  559.     Key[ 2] := 'ARRAY   ';
  560.     Key[ 3] := 'BEGIN   ';
  561.     Key[ 4] := 'BOOLEAN '; {+++ NOT A RESERVE WORD +++}
  562.     Key[ 5] := 'CASE    ';
  563.     Key[ 6] := 'CHAR    '; {+++ NOT A RESERVE WORD +++}
  564.     Key[ 7] := 'CONST   ';
  565.     Key[ 8] := 'DIV     ';
  566.     Key[ 9] := 'DOWNTO  ';
  567.     Key[10] := 'DO      ';
  568.     Key[11] := 'ELSE    ';
  569.     Key[12] := 'END     ';
  570.     Key[13] := 'EXIT    ';    {+++ NOT a Pascal reserve word +++}
  571.     Key[14] := 'FILE    ';
  572.     Key[15] := 'FOR     ';
  573.     Key[16] := 'FUNCTION';
  574.     Key[17] := 'GOTO    ';
  575.     Key[18] := 'IF      ';
  576.     Key[19] := 'IN      ';
  577.     Key[20] := 'INPUT   '; {+++ NOT A RESERVE WORD +++}
  578.     Key[21] := 'INTEGER '; {+++ NOT A RESERVE WORD +++}
  579.     Key[22] := 'LABEL   ';
  580.     Key[23] := 'MOD     ';
  581.     Key[24] := 'NIL     ';
  582.     Key[25] := 'NOT     ';
  583.     Key[26] := 'OF      ';
  584.     Key[27] := 'OR      ';
  585.     Key[28] := 'OUTPUT  '; {+++ NOT A RESERVE WORD +++}
  586.     Key[29] := 'PACKED  ';
  587.     Key[30] := 'PROCEDUR';
  588.     Key[31] := 'PROGRAM ';
  589.     Key[32] := 'REAL    '; {+++ NOT A RESERVE WORD +++}
  590.     Key[33] := 'RECORD  ';
  591.     Key[34] := 'REPEAT  ';
  592.     Key[35] := 'SET     ';
  593.     Key[36] := 'STRING  ';    {+++ NOT a Pascal reserve word +++}
  594.     Key[37] := 'TEXT    '; {+++ NOT A RESERVE WORD +++}
  595.     Key[38] := 'THEN    ';
  596.     Key[39] := 'TO      ';
  597.     Key[40] := 'TYPE    ';
  598.     Key[41] := 'UNTIL   ';
  599.     Key[42] := 'VAR     ';
  600.     Key[43] := 'WHILE   ';
  601.     Key[44] := 'WITH    ';
  602.     Key[45] := 'WRITE   '; {+++ NOT A RESERVE WORD +++}
  603.     Key[46] := 'WRITELN '; {+++ NOT A RESERVE WORD +++}
  604.  
  605.     blankindex := alfa_length;
  606.     tab    := CHR(9);  { ASCII Tab character }
  607.     form_feed := CHR(12);
  608.     flushing := KNOT{ flushing };
  609.     WRITELN;
  610.     WRITELN('Output Device:');
  611.     WRITE(  '  CONSOLE ->');
  612.     READLN(Ch);
  613.     con_wanted := ( (Ch='Y') OR (Ch='y') );
  614.     WRITE(  '  PRINTER ->');
  615.     READLN(Ch);
  616.     tty_wanted := ( (Ch='Y') OR (Ch='y') );
  617.     If tty_wanted THEN
  618.        con_wanted := FALSE;
  619.     IF NOT (con_wanted OR tty_wanted) THEN
  620.       LISTING := FALSE
  621.     ELSE
  622.       BEGIN
  623.         LISTING := TRUE;
  624. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  625.         IF con_wanted THEN REWRITE('CON:', OUTPUT);
  626.         IF tty_wanted THEN REWRITE('LST:', OUTPUT);
  627. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  628.       END;
  629.     WRITELN;
  630.     END; {IF ConnectFiles}
  631. END; {of Initialize}
  632.  
  633. BEGIN { Cross Reference }
  634.   CLEAR{output};
  635.   WRITELN(' ':22, 'CROSS REFERENCE GENERATOR');
  636.   WRITELN;WRITELN;WRITELN;WRITELN;
  637.   Initialize;
  638.   IF NOT fatal_error THEN
  639.     BEGIN
  640.       WordTree := NIL;        {Make the Tree empty}
  641.       BuildTree(WordTree);
  642.       PrintTree(WordTree);
  643.     END;
  644. {}WRITELN;
  645. END. { Cross Reference }
  646.