home *** CD-ROM | disk | FTP | other *** search
- {$LINESIZE:132}
- {$PAGESIZE:57}
- {$LIST+}
- {$symtab+}
- {$WARN-}
- {$DEBUG+}
- {$LINE+}
- {$ENTRY+}
- {$INDEXCK-}
- {$RANGECK-}
- {$INITCK-}
- {$INDEXCK-}
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ +}
- {+ PROGRAM TITLE: Cross Reference Generator +}
- {+ +}
- {+ WRITTEN BY: Peter Grogono +}
- {+ DATE WRITTEN: ? +}
- {+ +}
- {+ SUMMARY: +}
- {+ +}
- {+ 1. Output Files: +}
- {+ default is to disk files: +}
- {+ a. output file = file name + '.XRF' +}
- {+ all identifiers and their line # +}
- {+ b. output file = file name + '.PRN' +}
- {+ the file with all lines numbered +}
- {+ 2. LISTING Device: +}
- {+ Output may be to either the console or +}
- {+ the printer but NOT both. +}
- {+ +}
- {+ MODIFICATION RECORD: +}
- {+ 12-AUG-80 -modified for Pascal/Z v3.0 +}
- {+ -by Raymond E. Penley +}
- {+ 16-AUG-80 -added function ConnectFiles +}
- {+ 17-AUG-80 -added GetL, ReadC, ReadWord +}
- {+ 22-AUG-80 -selective use of control-c +}
- {+ +}
- {+ +}
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- PROGRAM XREFG2;
- { Cross Reference Generator }
- (*%P-,F-,M- [symbolic I/O OFF,
- floating point checking OFF,
- integer mult & div checking OFF] *)
- CONST
- alfa_length = 8;
- BLANKS = ' ';
- dflt_str_len = 255;
- entrygap = 0; { # of blank lines between line numbers}
- fid_len = 14; { Max length CP/M file names }
- heading = 'Cross-Reference Listing';
- headingsize = 3; {number of lines for heading}
- LLmax = dflt_str_len;
- {} MaxOnLine = 10;
- Maxlines = MAXINT; {longest document permitted}
- MaxWordlen = alfa_length;{longest word read without truncation}
- Maxlinelen = 80; {length of output line}
- MaxOnPage = 60; {size of output page}
- numbergap = 2; {number of gaps between line numbers}
- {} NumKeys = 46; {number of Pascal reseve words}
- {Read your Pascal manuals on this one!}
- {} NumKeysP1 = NumKeys + 1;
- {} NumberWidth = 6;
- space = ' ';
- TYPE
- {} ALFA = PACKED ARRAY[1..alfa_length] OF CHAR;
- {} { BYTE = 0..255; }
- {} CHARNAME = (lletter, uletter, digit, blank, quote, atab,
- EndOfLine, FileMark, otherchar );
- {} CHARINFO = RECORD
- name : charname;
- valu : CHAR
- END;
- COUNTER = 1..Maxlines;
- {} dfltstr = string (dflt_str_len) ;
- FID = string (fid_len) ;
- lineindex = 1..Maxlinelen;
- {} pageindex = BYTE;
- Wordindex = 1..MaxWordlen;
- Queuepointer = ^Queueitem;
- Queueitem = RECORD
- linenumber : counter;
- NextInQueue: Queuepointer
- END;
- EntryType = RECORD
- Wordvalue : alfa;
- FirstInQueue,
- lastinQueue: Queuepointer
- END;
- treepointer = ^node;
- node = RECORD
- entry : EntryType;
- left,
- right : treepointer
- END;
- SZ0 = string(1);
- SZ255 = string(255);
- VAR
- bell : CHAR;
- blankindex : BYTE;
- currchar, { Current operative character }
- nextchar : charinfo; { Look-ahead character }
- fatal_error : BOOLEAN;
- FILE_ID, { CP/M file name }
- PRN_ID, { basic file name + '.PRN' }
- New_ID : string(14) ; { basic file name + '.XRF' }
- fbuffer :STRING(255); { Format buffer - before final Print }
- FIN : TEXT;
- flushing : (KNOT, DBL, STD, LIT);
- form_feed : CHAR;
- Key : ARRAY[1..NumKeysP1] OF alfa;
- letters : SET OF CHAR;
- LISTING : BOOLEAN;
- Look : char; { Character read in from File }
- {}{OUTPUT : TEXT; } { Listing device -console or printer }
- tab : CHAR;
- wordcount : INTEGER; { total # of words in file }
- WordTree : treepointer;
- xeof, { EOF status AFTER a read }
- xeoln : BOOLEAN; { EOLN status after a read }
- GAP : char ;
- (*%C- [Control-C OFF]***********************************************)
- FUNCTION length(VAR x: STRING): INTEGER;
- VAR
- Y: INTEGER;
- Z: CHAR;
- BEGIN
- Z := X [0] ;
- Y := ORD(Z) ;
- LENGTH := Y ;
- END; {LENGTH}
- PROCEDURE koncat(VAR X: STRING; VAR Y: CHAR);
- VAR LL : INTEGER;
- BEGIN
- ll := ORD(X[0]);
- ll := ll + 1 ;
- X[ll} := Y ;
- END; {KONCAT}
- PROCEDURE setlength(VAR x: STRING; y: INTEGER);
- VAR
- UL : INTEGER; CY, CL : CHAR;
- begin
- UL := UPPER(X); CL := chr(ul); cy := CHR(Y);
- IF Y > ul THEN X [0] := CL;
- ELSE X[0] := CY ;
- END; {SETLENGTH}
- FUNCTION index(VAR x: STRING; VAR y char): byte ; EXTERNAL;
- { PROCEDURE PAGE(VAR fx: TEXT);
- BEGIN
- WRITE(fx, form_feed);
- END; }
- PROCEDURE CLEAR{output};
- VAR
- ix : 1..24;
- BEGIN
- FOR ix:=1 TO 24 DO WRITELN;
- END;
- PROCEDURE BuildTree(VAR tree: treepointer);
- VAR
- CurrentWord : alfa;
- Currentline: INTEGER;
- FOUT: TEXT; { local output file }
- PROCEDURE Entertree(VAR subtree: treepointer;
- Word : alfa;
- line :counter);
- VAR
- nextitem : Queuepointer;
- BEGIN
- IF subtree=nil THEN
- BEGIN {create a new entry}
- NEW(subtree);
- WITH subtree^ DO BEGIN
- left := nil;
- right := nil;
- WITH entry DO BEGIN
- Wordvalue := Word;
- NEW(FirstInQueue);
- LastinQueue := FirstInQueue;
- WITH FirstInQueue^ DO BEGIN
- linenumber := line;
- NextInQueue := nil;
- END;{WITH FirstInQueue}
- END;{WITH entry}
- END;{WITH subtree}
- END {create a new entry}
- ELSE {append a list item}
- WITH subtree^, entry DO
- IF Word=Wordvalue THEN
- BEGIN
- IF lastinQueue^.linenumber <> line THEN
- BEGIN
- NEW(nextitem);
- WITH Nextitem^ DO BEGIN
- linenumber := line;
- NextInQueue := nil;
- END;{WITH}
- lastinQueue^.NextInQueue := Nextitem;
- lastinQueue := nextitem;
- END;
- END
- ELSE
- IF Word < Wordvalue THEN
- Entertree(left,Word,line)
- ELSE
- Entertree(right,Word,line);
- END;{Entertree}
- Procedure ReadC({updating} VAR nextchar : charinfo;
- {returning}VAR currchar : charinfo );
- { revised 4 Jan 80, rep }
- { Defined the chars "^", "$", and "_" as lowercase letters }
- BEGIN {+++ File status module. +++
- Stores file status "AFTER" a read.
- NOTE this play on words - after one char is
- actually "PRIOR TO" the next character }
- xeof := EOF(FIN);
- {+++ read BYTE module +++}
- IF NOT xeof THEN
- xeoln := EOLN(FIN) ;
- IF NOT xeof THEN
- READ(FIN, Look);
- {+++ current operative character module +++}
- currchar := nextchar;
- {+++ Classify the character just read +++}
- WITH nextchar DO BEGIN{ Look-ahead character name module }
- IF xeof THEN
- name := FileMark
- ELSE IF xeoln THEN
- name := EndOfLine
- ELSE IF Look IN ['^', '$', '_', 'a'..'z'] THEN {lower case plus}
- name := lletter
- ELSE IF Look IN ['A'..'Z'] THEN {upper case}
- name := uletter
- ELSE IF Look IN ['0'..'9'] THEN {digit}
- name := digit
- ELSE IF Look = '''' THEN
- name := quote
- ELSE IF Look = TAB THEN
- name := atab
- ELSE IF Look = space THEN
- name := blank
- ELSE
- name := otherchar;
- CASE name of{ store character value module }
- EndOfLine,
- FileMark: Valu := space;
- OTHERWISE valu := look;
- END{ case name of };
- End{ Look-ahead character name module };
- END; {of ReadC}
- PROCEDURE GetL( VAR fbuffer : string );
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ Get a line of text into users buffer. +}
- {+ Flushes comment lines: +}
- {+ Flushes lines of Literals: 'this is it' +}
- {+ Ignores special characters & tabs: +}
- {+ Recognizes End of File and End of Line. +}
- {+ +}
- {+GLOBAL +}
- {+ flushing : (KNOT, DBL, STD, LIT); +}
- {+ fbuffer = dfltstr +}
- {+ LLmax = 0..Max Line length; +}
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- VAR
- state : (scanning, terminal, overflow);
- BEGIN { GetL }
- setlength(fbuffer,0);
- fatal_error := FALSE;
- state := scanning;
- REPEAT
- ReadC(nextchar, currchar);
- {} WRITE(FOUT, currchar.valu);
- {} IF listing THEN
- WRITE( {OUTPUT,} currchar.valu);
- IF (length(fbuffer) >= LLmax) THEN{ exceeded length of buffer }
- BEGIN{ reset EOLN }
- fatal_error := TRUE;
- state := overflow;
- setlength(fbuffer,0);
- WRITE(bell);
- WRITELN('EXCEEDED LENGTH OF INPUT BUFFER');
- END
- ELSE
- BEGIN
- IF (currchar.name IN [FileMark,EndOfLine]) THEN
- state:=terminal{ END of line or END of file };
- CASE flushing of
- KNOT:
- CASE currchar.name of
- lletter, uletter, digit, blank:
- BEGIN{ store }
- KONCAT(FBUFFER,CURRCHAR.VALU) ;
- END;
- atab, quote, otherchar:
- BEGIN{ Flush comments -convert
- tabs & other chars to spaces }
- IF (currchar.valu='(') and (nextchar.valu='*')
- THEN flushing := DBL
- ELSE IF (currchar.valu='{') THEN
- flushing := STD
- ELSE IF currchar.name=quote THEN
- flushing := LIT;
- { convert to a space }
- koncat(fbuffer,GAP);
- END;
- otherwise { END of line -or- file mark }
- KONCAT(fbuffer,currchar.valu)
- END{ case currchar name of };
- DBL: { scanning for a closing - double comment }
- IF (currchar.valu ='*') and (nextchar.valu =')')
- THEN flushing := KNOT;
- STD: { scanning for a closing curley }
- IF currchar.valu = '}' THEN
- flushing := KNOT;
- LIT: { scanning for a closing quote }
- IF currchar.name = quote THEN
- flushing := KNOT
- END{ flushing case }
- END{ ELSE }
- UNTIL (state<>scanning);
- END; {of GetL}
- PROCEDURE ReadWord;
- {++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ +}
- {+ Analyze the Line into "words" +}
- {+ +}
- {++++++++++++++++++++++++++++++++++++++++++++++++}
- LABEL 1;
- CONST
- TOP = NumKeys + 1;
- VAR
- ix, {temp indexer}
- idlen, {length of the word}
- Cpos : BYTE; { Current Position pointer }
- BEGIN{ ReadWord }
- Cpos := 1; { start at the beginning of a line }
- WHILE Cpos < length(fbuffer) DO
- BEGIN {Cpos<length(fbuffer)}
- WHILE (Cpos < length(fbuffer)) AND (fbuffer[Cpos]=space) DO
- Cpos:=Cpos + 1; {--- skip spaces ---}
- idlen := 0;
- WHILE (Cpos < length(fbuffer)) AND (fbuffer[Cpos ] <> space) DO
- BEGIN{ accept only non-spaces }
- IF idlen < MaxWordlen THEN
- BEGIN
- idlen := idlen + 1;
- CurrentWord[idlen] := fbuffer[Cpos];
- END;
- Cpos := Cpos +1;
- END{ WHILE };
- {} IF idlen=0 THEN {no word was found} GOTO 1;
- IF idlen >= blankindex THEN
- blankindex := idlen
- ELSE
- REPEAT
- CurrentWord[blankindex] := space;
- blankindex := blankindex - 1;
- UNTIL blankindex=idlen;
- WordCount := WordCount + 1;
- {++++++++++++++++++++++++++++++++++}
- {+ linear search with sentinel +}
- {++++++++++++++++++++++++++++++++++}
- Key[TOP] := CurrentWord;
- ix := 0;
- REPEAT
- ix := ix + 1;
- UNTIL Key[ix] = CurrentWord;
- {++++++++++++++++++++++++++++++++++}
- {} IF ix=TOP THEN {CurrentWord is not a reserve word, so}
- EnterTree(tree,CurrentWord,Currentline);
- 1:{Here is no word <length of word=0>};
- END; {WHILE Cpos<length(fbuffer)}
- END; {of Readword}
- BEGIN{BuildTree}
- {}ASSIGN(FOUT,PRN_ID); REWRITE(FOUT);
- PAGE(FOUT);
- Currentline := 0;
- nextchar.name := blank; { Initialize next char to a space }
- nextchar.valu := space;
- ReadC({update} nextchar, { Initialize current char to space }
- {returning} currchar); { First char from file in nextchar }
- WHILE ((currchar.name<>filemark) AND (NOT fatal_error)) DO
- BEGIN
- Currentline := Currentline + 1;
- WRITE(FOUT, Currentline:6,': ');
- IF listing THEN WRITE({OUTPUT,} Currentline:6,': ');
- GetL(fbuffer) { attempt to read the first line };
- WRITELN(FOUT);
- IF listing THEN WRITELN{output};
- ReadWord; {Analyze the Text into single 'words' }
- END; {While}
- PAGE(FOUT);
- CLOSE(FOUT) ;
- END; {of BuildTree}{CLOSE(PRN_ID);}
- PROCEDURE PrintTree(tree: treepointer);
- {
- GLOBAL
- MaxOnLine = max line references per line
- NumberWidth = field for each number
- }
- VAR
- XOUT: TEXT; { local output file }
- pageposition: pageindex;
- PROCEDURE PrintEntry(subtree: treepointer;
- VAR position: pageindex);
- VAR ix: Wordindex;
- itemcount : 0..Maxlinelen;
- itemptr : Queuepointer;
- PROCEDURE PrintLine(VAR Currentposition: pageindex;
- newlines: pageindex);
- VAR
- linecounter: pageindex;
- BEGIN
- {} IF (Currentposition + newlines) < MaxOnPage THEN
- BEGIN
- {} FOR linecounter:=1 TO newlines DO WRITELN(XOUT);
- {} IF listing THEN
- FOR linecounter:=1 TO newlines DO WRITELN{OUTPUT};
- Currentposition := Currentposition + newlines;
- END
- ELSE
- BEGIN
- {} PAGE(XOUT);
- {} WRITELN(XOUT,heading);
- {} FOR linecounter := 1 TO headingsize - 1 DO
- WRITELN(XOUT);
- {} IF listing THEN
- BEGIN
- CLEAR{OUTPUT}; {PAGE(OUTPUT);}
- WRITELN({OUTPUT,} heading);
- FOR linecounter := 1 TO headingsize - 1 DO
- WRITELN{OUTPUT};
- END;
- Currentposition := headingsize + 1;
- END
- END;{PrintLine}
- BEGIN{PrintEntry}
- IF subtree<>nil THEN
- WITH subtree^ DO BEGIN
- PrintEntry(left,position);
- PrintLine(position,entrygap + 1);
- WITH entry DO BEGIN
- {} FOR ix:=1 TO MaxWordlen DO
- WRITE(XOUT, WordValue[ix]);
- {} IF listing THEN
- FOR ix:=1 TO MaxWordlen DO
- WRITE({OUTPUT,} WordValue[ix]);
- itemcount := 0;
- itemptr := FirstInQueue;
- WHILE itemptr <> nil DO
- BEGIN
- itemcount := itemcount + 1;
- IF itemcount > MaxOnLine THEN
- BEGIN
- PrintLine(position,1);
- {} WRITE(XOUT, space:MaxWordlen);
- {} IF listing THEN
- WRITE({OUTPUT,} space:MaxWordlen);
- itemcount := 1;
- END;
- {} WRITE(XOUT, itemptr^.linenumber: numberwidth);
- {} IF listing THEN
- WRITE({OUTPUT,}itemptr^.linenumber: numberwidth);
- itemptr := itemptr^.NextInQueue;
- END;{WHILE}
- END; {WITH entry}
- PrintEntry(right,position);
- END; {WITH subtree^}
- END; {PrintEntry}
- BEGIN{PrintTree}
- READFN(input,xout);
- Rewrite(Xout) ;
- PAGE(XOUT);
- PagePosition := MaxOnPage;
- PrintEntry(tree,PagePosition);
- PAGE(XOUT);
- END; {of PrintTree}{CLOSE(New_ID);}
- (*%C+ [Control-C ON]*******************************)
- FUNCTION ConnectFiles: boolean;
- TYPE
- Linebuffer = string(80);
- VAR
- ix,jx,
- Cmllen : BYTE;
- Cmlline : LINEBUFFER ;
- BEGIN{ ConnectFiles }
- fatal_error := FALSE;
- ConnectFiles := TRUE;
- WRITELN('Enter Complete Filenames ') ;
- WRITELN ;
- WRITELN('Input File:');
- READLN(FILE_ID);
- WRITELN('Cross-Reference output:');
- READLN(NEW_ID);
- WRITELN('Printed output:');
- READLN(PRN_ID);
- WRITELN;
- ASSIGN(FIN,FILE_ID);
- RESET(FIN);
- IF EOF(FIN) THEN
- BEGIN
- WRITE(BELL);
- WRITELN('FILE NOT FOUND !!!!!!');
- fatal_error := TRUE;
- ConnectFiles := FALSE;
- END
- ELSE
- writeln(FILE_ID,PRN_ID,NEW_ID);
- END{ of ConnectFiles };
- (*%C- [control-c OFF]***********************************)
- PROCEDURE Initialize;
- VAR
- Ch: CHAR;
- con_wanted,
- tty_wanted : BOOLEAN;
- BEGIN
- bell := CHR(7); GAP := ' ' ;
- IF ConnectFiles THEN
- BEGIN
- letters := ['A'..'Z','a'..'z'];
- Key[ 1] := 'AND ';
- Key[ 2] := 'ARRAY ';
- Key[ 3] := 'BEGIN ';
- Key[ 4] := 'BOOLEAN '; {+++ NOT A RESERVE WORD +++}
- Key[ 5] := 'CASE ';
- Key[ 6] := 'CHAR '; {+++ NOT A RESERVE WORD +++}
- Key[ 7] := 'CONST ';
- Key[ 8] := 'DIV ';
- Key[ 9] := 'DOWNTO ';
- Key[10] := 'DO ';
- Key[11] := 'ELSE ';
- Key[12] := 'END ';
- Key[13] := 'EXIT '; {+++ NOT a Pascal reserve word +++}
- Key[14] := 'FILE ';
- Key[15] := 'FOR ';
- Key[16] := 'FUNCTION';
- Key[17] := 'GOTO ';
- Key[18] := 'IF ';
- Key[19] := 'IN ';
- Key[20] := 'INPUT '; {+++ NOT A RESERVE WORD +++}
- Key[21] := 'INTEGER '; {+++ NOT A RESERVE WORD +++}
- Key[22] := 'LABEL ';
- Key[23] := 'MOD ';
- Key[24] := 'NIL ';
- Key[25] := 'NOT ';
- Key[26] := 'OF ';
- Key[27] := 'OR ';
- Key[28] := 'OUTPUT '; {+++ NOT A RESERVE WORD +++}
- Key[29] := 'PACKED ';
- Key[30] := 'PROCEDUR';
- Key[31] := 'PROGRAM ';
- Key[32] := 'REAL '; {+++ NOT A RESERVE WORD +++}
- Key[33] := 'RECORD ';
- Key[34] := 'REPEAT ';
- Key[35] := 'SET ';
- Key[36] := 'STRING '; {+++ NOT a Pascal reserve word +++}
- Key[37] := 'TEXT '; {+++ NOT A RESERVE WORD +++}
- Key[38] := 'THEN ';
- Key[39] := 'TO ';
- Key[40] := 'TYPE ';
- Key[41] := 'UNTIL ';
- Key[42] := 'VAR ';
- Key[43] := 'WHILE ';
- Key[44] := 'WITH ';
- Key[45] := 'WRITE '; {+++ NOT A RESERVE WORD +++}
- Key[46] := 'WRITELN '; {+++ NOT A RESERVE WORD +++}
- blankindex := alfa_length;
- tab := CHR(9); { ASCII Tab character }
- form_feed := CHR(12); gap := CHR(32);
- flushing := KNOT{ flushing };
- WRITELN;
- WRITELN('Output Device:');
- WRITE( ' CONSOLE ->');
- READLN(Ch);
- con_wanted := ( (Ch='Y') OR (Ch='y') );
- WRITE( ' PRINTER ->');
- READLN(Ch);
- tty_wanted := ( (Ch='Y') OR (Ch='y') );
- If tty_wanted THEN
- con_wanted := FALSE;
- IF NOT (con_wanted OR tty_wanted) THEN
- LISTING := FALSE
- ELSE
- BEGIN
- LISTING := TRUE;
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- IF con_wanted THEN REWRITE('CON:', OUTPUT);
- IF tty_wanted THEN REWRITE('LST:', OUTPUT);
- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- END;
- WRITELN;
- END; {IF ConnectFiles}
- END; {of Initialize}
- BEGIN { Cross Reference }
- CLEAR{output};
- WRITELN(' ':22, 'CROSS REFERENCE GENERATOR');
- WRITELN;WRITELN;WRITELN;WRITELN;
- Initialize;
- IF NOT fatal_error THEN
- BEGIN
- WordTree := NIL; {Make the Tree empty}
- writeln('Pass 1 [Listing] Begins ...');BuildTree(WordTree);
- writeln('Pass 2 [Cross-Ref] Begins ...');PrintTree(WordTree);
- END;
- {}WRITELN;
- END. { Cross Reference }