home *** CD-ROM | disk | FTP | other *** search
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ +}
- {+ 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;
-
- S$0 = string 0;
- S$255 = 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 : FID; { basic file name + '.XRF' }
- fbuffer : dfltstr; { 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 }
-
- (*$C- [Control-C OFF]***********************************************)
-
- FUNCTION length(x: S$255): INTEGER; EXTERNAL;
- PROCEDURE setlength(VAR x: S$0; y: INTEGER); EXTERNAL;
- FUNCTION index(x,y: S$255): INTEGER; 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 }
- xeoln := EOLN(FIN);
- xeof := EOF(FIN);
- {+++ read BYTE module +++}
- 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;
- ELSE: Valu := Look
- END{ case name of };
- End{ Look-ahead character name module };
- END; {of ReadC}
-
- PROCEDURE GetL( VAR fbuffer : dfltstr );
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ 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 }
- append(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 }
- append(fbuffer,space);
- END;
- else: { END of line -or- file mark }
- append(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}
- {}REWRITE(PRN_ID, 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);
- END; {of BuildTree}{CLOSE(PRN_ID);}
-
-
- PROCEDURE PrintTree(tree: treepointer);
- {
- GLOBAL
- MaxOnLine = max line references per line
- NumberWidth = field for each number
- }
- VAR
- FOUT: 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(FOUT);
- {} IF listing THEN
- FOR linecounter:=1 TO newlines DO WRITELN{OUTPUT};
- Currentposition := Currentposition + newlines;
- END
- ELSE
- BEGIN
- {} PAGE(FOUT);
- {} WRITELN(FOUT,heading);
- {} FOR linecounter := 1 TO headingsize - 1 DO
- WRITELN(FOUT);
- {} 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(FOUT, 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(FOUT, space:MaxWordlen);
- {} IF listing THEN
- WRITE({OUTPUT,} space:MaxWordlen);
- itemcount := 1;
- END;
- {} WRITE(FOUT, 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}
- {}REWRITE(New_ID, FOUT);
- PAGE(FOUT);
- PagePosition := MaxOnPage;
- PrintEntry(tree,PagePosition);
- PAGE(FOUT);
- END; {of PrintTree}{CLOSE(New_ID);}
-
- (*$C+ [Control-C ON]*******************************)
-
- FUNCTION ConnectFiles: boolean;
- TYPE
- Linebuffer = string 80;
- VAR
- ix,jx,
- Cmllen : BYTE;
- Cmlline : Linebuffer;
-
- PROCEDURE GCML( VAR line : linebuffer;
- VAR len : BYTE );
- {++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ READ the system command line. +}
- {+ THIS MUST be the very first read in the +}
- {+ entire program! +}
- {++++++++++++++++++++++++++++++++++++++++++++++++}
- CONST input = 0; { !!!! PASCAL/Z !!! }
- BEGIN
- setlength(line,0);
- len := 0;
- IF NOT EOLN(input) THEN
- BEGIN
- READLN(line);
- len := length(line);
- END;
- END; {of GCML}
-
- PROCEDURE PAD(VAR this_ID: fid; required: BYTE);
- BEGIN
- WHILE (length(this_ID)<required) DO
- append(this_ID,space);
- END;
-
- BEGIN{ ConnectFiles }
- fatal_error := FALSE;
- ConnectFiles := TRUE;
- GCML(Cmlline, Cmllen);
- IF (Cmllen=0) THEN { no file name from the console }
- BEGIN
- setlength(FILE_ID,0);
- WRITELN;
- WRITE('Enter <Drive:> FILE name - ');
- READLN(FILE_ID);
- END
- ELSE
- FILE_ID := Cmlline;
- IF (length(FILE_ID)>fid_len) THEN
- setlength(FILE_ID,fid_len);
- PAD(FILE_ID, fid_len);
- RESET(FILE_ID, FIN);
- IF EOF(FIN) THEN{ ABORT }
- BEGIN
- WRITE(bell);
- WRITELN('FILE NOT FOUND');
- fatal_error := TRUE;
- ConnectFiles := FALSE;
- END
- ELSE
- BEGIN
- ix := index(FILE_ID,'.'); { search for an extension }
- jx := index(FILE_ID,' '); { search for the first space }
- IF (ix=0) THEN{ no extension was specified }
- setlength(FILE_ID,jx-1)
- ELSE
- setlength(FILE_ID,ix-1);
-
- setlength(New_ID,0); { New_ID := CONCAT(FILE_ID, '.XRF'); }
- append(New_ID, FILE_ID);
- append(New_ID, '.XRF');
- PAD(New_ID, fid_len);
-
- setlength(PRN_ID,0); { PRN_ID := CONCAT(FILE_ID, '.PRN'); }
- append(PRN_ID, FILE_ID);
- append(PRN_ID, '.PRN');
- PAD(PRN_ID, fid_len);
-
- END;
- END{ of ConnectFiles };
-
- (*$C- [control-c OFF]***********************************)
-
- PROCEDURE Initialize;
- VAR
- Ch: CHAR;
- con_wanted,
- tty_wanted : BOOLEAN;
- BEGIN
- bell := CHR(7);
- 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);
- 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}
- BuildTree(WordTree);
- PrintTree(WordTree);
- END;
- {}WRITELN;
- END. { Cross Reference }
-