home *** CD-ROM | disk | FTP | other *** search
- {********************************************************
- **
- ** EDIT #5 - 12 July 1980
- **
- ** PROGRAM TITLE: Concordance
- **
- ** WRITTEN BY: Raymond E. Penley
- ** DATE WRITTEN: 26 January 1980
- **
- ** WRITTEN FOR: Personal pleasure
- ** Donated to Pascal/Z users Gp
- **
- ** PROGRAM SUMMARY:
- **
- ** Examine a piece of text and produce a list,
- ** in alphabetical order, of all the distinct
- ** words which appear in the text.
- **
- ** INPUT AND OUTPUT FILES:
- **
- ** INPUT FILE: DRIVE: BASIC FILE NAME . EXTENSION
- ** OUT FILE: DRIVE: BASIC FILE NAME . CCD
- **
- ************* }
- PROGRAM CONCORDANCE;
-
- label 9;{abort}
- const
- alfa_len = 16; { length of words }
- c4 = MAXINT;{ max line number }
- Clearcode = 26; { clear screen }
- default = 255;
- dflt_str_len = default;
- LLmax = default;{ max line length }
- LLmin = 72; { Min line length }
- space = ' ';
- StrMax = 255;
-
- type
- alfa = STRING alfa_len;
- byte = 0..255;
- charname = (lletter, uletter, digit, blank, quote, atab,
- EndOfLine, FileMark, otherchar );
- charinfo = RECORD
- name : charname;
- valu : char
- END;
- dfltstr = STRING default;{ default length for all strings }
- ItemRecords = record
- item :alfa;
- Next :^ItemRecords
- end;
- ItemPointers = ^ItemRecords;
- str0 = string 0;
- str255 = string StrMax;
-
- var
- Look : char; { Character read in from File }
- cline : integer; { current line number }
- currchar, { Current operative character }
- nextchar : CharInfo; { Look-ahead character }
- CON_wanted,
- DEBUG,
- error_flag: BOOLEAN;
- Fbuffer : dfltstr; { Format buffer - before final Print }
- flushing : (KNOT, DBL, STD, LIT);
- ID : alfa; { Identifier storage }
- idlen : byte; { Identifier Length }
- ListHead :ItemPointers;
- tab : char;
- TextFile, { Input file }
- Work_File: TEXT; { Output file }
- wordcount: integer; { total # of words in file }
- xeof, { EOF status AFTER a read }
- xeoln : boolean; { EOLN status after a read }
-
- Function length(x: str255): integer; external;
- Procedure setlength(var x: str0; y: integer); external;
- Function index(x,y: str255): integer; external;
-
- PROCEDURE Error( enumb : byte);
- begin
- CASE enumb of
- 0: writeln('Fatal error!');
- 1: writeln('Exceeded buffer limits on read');
- 2: {-reserved-};
- 3: writeln('File not found');
- 4: {-reserved-}
- end{ of case };
- error_flag := true
- end;
-
- PROCEDURE InsertItem( Newitem :alfa);
- {*
- ** From the book - PASCAL An Introduction
- ** to Methodical Programming
- ** Authors:
- ** W. Findlay and D.A. Watt
- ****** }
- VAR entry,
- PriorEntry,
- Newentry :ItemPointers;
- found :boolean;
-
- Procedure INSERTWORD;
- begin{ CREATE the New entry and Insert it in position }
- New(Newentry);
- Newentry^.item := Newitem;
- Newentry^.Next := entry;
- If entry = ListHead then
- ListHead := Newentry
- Else
- PriorEntry^.Next := Newentry;
- end{-of InsertWord-};
-
- begin
- { FIND the position where the New item will be Inserted }
- entry := ListHead;
- found := false;
- While NOT found AND (entry <> NIL) do
- WITH entry^ DO
- If (item < Newitem) then
- begin
- PriorEntry := entry;
- entry := Next
- end
- Else
- found := true;
- If found then{-Crate a new entry in the list If necessary-}
- begin
- If (entry^.item <> Newitem) then InsertWord{ at position `entry` }
- end
- Else
- InsertWord{ at end of list }
- end{-of InsertItem-};
-
- PROCEDURE WriteItems;
- CONST Sail = '*** INDEX ***';
- var entry :ItemPointers;
- begin
- Writeln(Work_File, Sail);
- If CON_wanted then writeln(Sail);
- entry := ListHead;
- While entry <> NIL DO
- WITH entry^ DO
- begin
- Writeln(Work_File, item);
- If CON_wanted then writeln(item);
- entry := Next
- end
- end{--of WriteItems-};
-
- Procedure ReadC(var nextchar : charinfo;
- var currchar : charinfo );
- { revised 4 Jan 80, rep }
- begin{ Terminator status module.
- Stores terminator status "AFTER" a read.
- NOTE this play on words - after one char is
- actually "PRIOR TO" the next character }
- xeoln := EOLN(textfile);
- xeof := EOF(textfile);
- { read byte module }
- If NOT xeof then
- READ(Textfile, Look);
- { current operative character module }
- currchar := nextchar;
- 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 }
- 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{ 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);
- error_flag := false;
- state := scanning;
- REPEAT
- ReadC(Nextchar, Currchar);
- If (length(fbuffer) >= LLmax) then{ exceeded length of buffer }
- begin{ reset EOLN }
- state := overflow;
- READLN(fbuffer);{ reset EOLN }
- error(1)
- 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" }
- const space = ' ';
- var Cpos : byte; { Current Position pointer }
- begin{ ReadWord }
- Cpos := 1; { start at the beginning of a line }
- While (Cpos < length(fbuffer)) Do
- begin
- { skip spaces }
- while (Cpos < length(Fbuffer)) AND (fbuffer[Cpos]=space) Do Cpos:=Cpos+1;
- Setlength(ID,0);{ start with a null array }
- while (Cpos < length(fbuffer)) AND (fbuffer[Cpos ] <> space) Do
- begin{ accept only non-spaces }
- If (length(ID)<alfa_len) then append(ID,fbuffer[ Cpos ]);
- Cpos := Cpos +1;
- end{ while };
- while (length(ID)<alfa_len) Do append(ID,space);
- {}If DEBUG then writeln(' ',ID);
- InsertItem(ID);
- WordCount := WordCount + 1;
- end;
- end{-of ReadWord-};
-
- Procedure SKIP(n : byte);
- var i : byte;
- begin For i:=1 to N do writeln
- end;
-
- Function ConnectFiles: boolean;
- const dflt_extension = '.CCD';
- fid_len = 14; { Max length CP/M file names }
- type FID = string fid_len;
- var File_ID,
- New_ID : FID;
- ix,jx : byte;
-
- Procedure PAD(var ID: fid; required: byte);
- const space = ' ';
- begin
- while (length(ID)<required) Do append(ID,space);
- end;
-
- begin{-GETID-}
- ConnectFiles := true;
- Setlength(File_ID,0);
- writeln;
- write('Enter <Drive:><File name> ');
- readln(File_ID);
- If (length(File_ID)>fid_len) then
- setlength(File_ID,fid_len)
- Else
- PAD(File_ID, fid_len);
- RESET(File_ID, TextFile);
- If EOF(TextFile) then{ ABORT }
- begin
- error(3);
- 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);
- append(New_ID, File_ID);
- append(New_ID, dflt_extension);
- PAD(New_ID, fid_len);
- REWRITE(New_ID, Work_File);
- end;
- End{ of ConnectFiles };
-
- Procedure Initialize;
- var ch: char;
- begin
- ListHead := NIL; { MAKE the LIST EMPTY }
- cline := 0; { current line counter }
- wordcount := 0;
- idlen := 0;
- tab := chr(9); { ASCII Tab character }
- flushing := KNOT{ flushing };
- {-INITIALIZE look-ahead char-}
- nextchar.name := blank;
- nextchar.valu := space;
-
- writeln;
- WRITE('DEBUG?');READ(Ch);
- DEBUG := ((Ch='Y') or (Ch='y'));
- writeln;
- WRITE('Output to Console?');READ(Ch);
- CON_wanted := ((Ch='Y') or (Ch='y'));
- end;
-
- PROCEDURE Clear(code : byte);
- { device dependent routine }
- begin WRITELN( CHR(code) )
- end;
-
- Procedure Sign_On;
- begin
- Clear(clearcode);
- writeln;
- writeln(' ':20,'*** C O N C O R D A N C E ***');
- SKIP(4);
- end;
-
- Begin{ main body of Concordance }
- Sign_On;
- If NOT ConnectFiles then {ABORT} goto 9;
- Initialize;
- SKIP(4);
- cline:= cline +1;
- GetL(Fbuffer) { attempt to read the first line };
- while ((currchar.name<>filemark) AND (NOT error_flag)) do
- begin
- {} If DEBUG then writeln('line',cline:5,' ',fbuffer);
- ReadWord{Analyze the Text into single 'words' };
- If cline=c4 then cline:=0;
- cline := cline +1;
- GetL(Fbuffer) { attempt to read another line of text };
- end{ while };
- Clear(clearcode);
- WriteItems; { Write all the Items in order }
- writeln;
- writeln(' ':18, '*** SUMMARY ***');
- writeln('Total # lines =',cline -1);
- writeln('Total # words =', wordcount);
- writeln;
- 9:{ABORT};
- end{ of ConCordance }.
-