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

  1. {********************************************************
  2. **
  3. **  EDIT #5 - 12 July 1980
  4. **
  5. **  PROGRAM TITLE:    Concordance
  6. **
  7. **  WRITTEN BY:        Raymond E. Penley
  8. **  DATE WRITTEN:    26 January 1980
  9. **
  10. **  WRITTEN FOR:    Personal pleasure
  11. **            Donated to Pascal/Z users Gp
  12. **
  13. **  PROGRAM SUMMARY:
  14. **
  15. **    Examine a piece of text and produce a list,
  16. **    in alphabetical order, of all the distinct
  17. **    words which appear in the text.
  18. **
  19. **  INPUT AND OUTPUT FILES:
  20. **
  21. **    INPUT FILE: DRIVE: BASIC FILE NAME . EXTENSION
  22. **    OUT FILE:   DRIVE: BASIC FILE NAME . CCD
  23. **
  24.         *************            }
  25. PROGRAM CONCORDANCE;
  26.  
  27. label    9;{abort}
  28. const
  29.   alfa_len     = 16;     { length of words }
  30.   c4         = MAXINT;{ max line number }
  31.   Clearcode    = 26;     { clear screen    }
  32.   default    = 255;
  33.   dflt_str_len    = default;
  34.   LLmax     = default;{ max line length }
  35.   LLmin     = 72;    { Min line length }
  36.   space     = ' ';
  37.   StrMax     = 255;
  38.  
  39. type
  40.   alfa        = STRING alfa_len;
  41.   byte        = 0..255;
  42.   charname = (lletter, uletter, digit, blank, quote, atab,
  43.           EndOfLine, FileMark, otherchar );
  44.   charinfo = RECORD
  45.         name : charname;
  46.         valu : char
  47.          END;
  48.   dfltstr    = STRING default;{ default length for all strings }
  49.   ItemRecords  = record
  50.            item  :alfa;
  51.            Next  :^ItemRecords
  52.          end;
  53.   ItemPointers = ^ItemRecords;
  54.   str0        = string 0;
  55.   str255    = string StrMax;
  56.  
  57. var
  58.   Look       : char;    { Character read in from File }
  59.   cline       : integer;    { current line number }
  60.   currchar,        { Current operative character }
  61.   nextchar : CharInfo;    { Look-ahead character }
  62.   CON_wanted,
  63.   DEBUG,
  64.   error_flag: BOOLEAN;
  65.   Fbuffer  : dfltstr;    { Format buffer - before final Print }
  66.   flushing : (KNOT, DBL, STD, LIT);
  67.   ID       : alfa;    { Identifier storage }
  68.   idlen       : byte;    { Identifier Length }
  69.   ListHead  :ItemPointers;
  70.   tab       : char;
  71.   TextFile,        { Input file }
  72.   Work_File: TEXT;    { Output file }
  73.   wordcount: integer;    { total # of words in file }
  74.   xeof,            { EOF status AFTER a read }
  75.   xeoln    : boolean;    { EOLN status after a read }
  76.  
  77. Function length(x: str255): integer; external;
  78. Procedure setlength(var x: str0; y: integer); external;
  79. Function index(x,y: str255): integer; external;
  80.  
  81. PROCEDURE Error( enumb : byte);
  82. begin
  83.   CASE enumb of
  84.     0:    writeln('Fatal error!');
  85.     1:    writeln('Exceeded buffer limits on read');
  86.     2:    {-reserved-};
  87.     3:    writeln('File not found');
  88.     4:    {-reserved-}
  89.    end{ of case };
  90.   error_flag := true
  91. end;
  92.  
  93. PROCEDURE InsertItem( Newitem  :alfa);
  94. {*
  95. **    From the book - PASCAL An Introduction
  96. **    to Methodical Programming
  97. **    Authors:
  98. **    W. Findlay and D.A. Watt
  99.         ******            }
  100. VAR    entry,
  101.     PriorEntry,
  102.     Newentry     :ItemPointers;
  103.     found        :boolean;
  104.  
  105.    Procedure INSERTWORD;
  106.    begin{ CREATE the New entry and Insert it in position }
  107.      New(Newentry);
  108.      Newentry^.item := Newitem;
  109.      Newentry^.Next := entry;
  110.      If entry = ListHead then
  111.        ListHead := Newentry
  112.      Else
  113.        PriorEntry^.Next := Newentry;
  114.    end{-of InsertWord-};
  115.  
  116. begin
  117.   { FIND the position where the New item will be Inserted }
  118.   entry := ListHead;
  119.   found := false;
  120.   While NOT found AND (entry <> NIL) do
  121.     WITH entry^ DO
  122.       If (item < Newitem) then
  123.     begin
  124.     PriorEntry := entry;
  125.     entry := Next
  126.     end
  127.       Else
  128.     found := true;
  129.   If found then{-Crate a new entry in the list If necessary-}
  130.     begin
  131.     If (entry^.item <> Newitem) then InsertWord{ at position `entry` }
  132.     end
  133.   Else
  134.     InsertWord{ at end of list }
  135. end{-of InsertItem-};
  136.  
  137. PROCEDURE WriteItems;
  138. CONST      Sail = '***   INDEX   ***';
  139. var      entry  :ItemPointers;
  140. begin
  141.   Writeln(Work_File, Sail);
  142.   If CON_wanted then writeln(Sail);
  143.   entry := ListHead;
  144.   While entry <> NIL DO
  145.     WITH entry^ DO
  146.       begin
  147.       Writeln(Work_File, item);
  148.       If CON_wanted then writeln(item);
  149.       entry := Next
  150.       end
  151. end{--of WriteItems-};
  152.  
  153. Procedure ReadC(var nextchar : charinfo;
  154.         var currchar : charinfo );
  155. { revised 4 Jan 80, rep }
  156. begin{ Terminator status module.
  157.    Stores terminator status "AFTER" a read.
  158.    NOTE this play on words - after one char is
  159.    actually "PRIOR TO" the next character        }
  160.   xeoln := EOLN(textfile);
  161.   xeof  := EOF(textfile);
  162. { read byte module }
  163.   If NOT xeof then
  164.         READ(Textfile, Look);
  165. { current operative character module }
  166.   currchar := nextchar;
  167.   With NextChar do begin{ Look-ahead character name module }
  168.     If xeof then
  169.       name := FileMark
  170.     Else If xeoln then
  171.        name := EndOfLine
  172.     Else If LooK IN ['a'..'z'] then { lower case }
  173.        name := lletter
  174.     Else If LooK IN ['A'..'Z'] then { upper case }
  175.        name := uletter
  176.     Else If LooK IN ['0'..'9'] then { digit }
  177.        name := digit
  178.     Else If LooK = '''' then
  179.        name := quote
  180.     Else If LooK = TAB then
  181.        name := atab
  182.     Else If LooK = space then
  183.        name := blank
  184.     Else name := otherchar;
  185.     CASE name of{ store character value module }
  186.     EndOfLine,
  187.     FileMark:    Valu := space;
  188.     Else:        Valu := LooK
  189.     end{ case name of };
  190.   End{ Look-ahead character name module };
  191. end{ ReadC };
  192.  
  193. PROCEDURE GetL( var Fbuffer : dfltstr );
  194. {        *****
  195.     Get a line of text into users buffer.
  196.     Flushes comment lines:
  197.     Flushes lines of Literals:  'this is it'
  198.     Ignores special characters & tabs:
  199.     Recognizes End of File and End of Line.
  200. GLOBAL
  201.     flushing : (KNOT, DBL, STD, LIT);
  202.     Fbuffer = dfltstr
  203.     LLmax   = 0..Max Line length;
  204.         *****                }
  205. var    state : (scanning, terminal, overflow);
  206. begin { GetL }
  207.    setlength(fbuffer,0);
  208.    error_flag := false;
  209.    state := scanning;
  210.   REPEAT
  211.     ReadC(Nextchar, Currchar);
  212.     If (length(fbuffer) >= LLmax) then{ exceeded length of buffer }
  213.       begin{ reset EOLN }
  214.     state := overflow;
  215.     READLN(fbuffer);{ reset EOLN }
  216.     error(1)
  217.       end
  218.     Else
  219.       begin
  220.     If (currchar.name IN [FileMark,EndOfLine]) then
  221.           state:=terminal{ end of line or end of file };
  222.     CASE flushing of
  223.         KNOT:
  224.         CASE currchar.name of
  225.         lletter, uletter, digit, blank:
  226.             begin{ store }
  227.             append(fbuffer,currchar.valu);
  228.             end;
  229.         atab, quote, otherchar:
  230.             begin{     Flush comments    -convert
  231.                      tabs & other chars to spaces }
  232.             If (currchar.valu='(') and (nextchar.valu='*')
  233.               then flushing := DBL
  234.             Else If (currchar.valu='{') then 
  235.                flushing := STD
  236.             Else If currchar.name=quote then
  237.                flushing := LIT;
  238.             { convert to a space }
  239.             append(fbuffer,space);
  240.             end;
  241.         else:    { end of line -or- file mark }
  242.             append(fbuffer,currchar.valu)
  243.         end{ case currchar name of };
  244.         DBL:  { scanning for a closing  - double comment }
  245.         If (currchar.valu ='*') and (nextchar.valu =')')
  246.           then flushing := KNOT;
  247.         STD:  { scanning for a closing curley  }
  248.           If currchar.valu = '}' then
  249.               flushing := KNOT;
  250.         LIT:  { scanning for a closing quote }
  251.           If currchar.name = quote then
  252.             flushing := KNOT
  253.         end{ flushing case }
  254.       end{ Else }
  255.   UNTIL (state<>scanning);
  256. end{-of GetL-};
  257.  
  258. PROCEDURE ReadWord;
  259. {     Analyze the Line into "words"        }
  260. const    space = ' ';
  261. var    Cpos : byte; { Current Position pointer }
  262. begin{ ReadWord }
  263.  Cpos := 1; { start at the beginning of a line }
  264.  While (Cpos < length(fbuffer)) Do
  265.   begin
  266.    { skip spaces }
  267.    while (Cpos < length(Fbuffer)) AND (fbuffer[Cpos]=space) Do Cpos:=Cpos+1;
  268.    Setlength(ID,0);{ start with a null array }
  269.    while (Cpos < length(fbuffer)) AND (fbuffer[Cpos ] <> space) Do
  270.     begin{ accept only non-spaces }
  271.      If (length(ID)<alfa_len) then append(ID,fbuffer[ Cpos ]);
  272.      Cpos := Cpos +1;
  273.     end{ while };
  274.    while (length(ID)<alfa_len) Do append(ID,space);
  275. {}If DEBUG then writeln('   ',ID);
  276.    InsertItem(ID);
  277.    WordCount := WordCount + 1;
  278.  end;
  279. end{-of ReadWord-};
  280.  
  281. Procedure SKIP(n : byte);
  282. var    i : byte;
  283. begin    For i:=1 to N do writeln
  284. end;
  285.  
  286. Function ConnectFiles: boolean;
  287. const    dflt_extension = '.CCD';
  288.     fid_len    = 14;    { Max length CP/M file names }
  289. type    FID    = string fid_len;
  290. var    File_ID,
  291.     New_ID  : FID;
  292.     ix,jx    : byte;
  293.  
  294.     Procedure PAD(var ID: fid; required: byte);
  295.     const    space = ' ';
  296.     begin
  297.       while (length(ID)<required) Do append(ID,space);
  298.     end;
  299.  
  300. begin{-GETID-}
  301.   ConnectFiles := true;
  302.   Setlength(File_ID,0);
  303.   writeln;
  304.   write('Enter <Drive:><File name>  ');
  305.   readln(File_ID);
  306.   If (length(File_ID)>fid_len) then
  307.     setlength(File_ID,fid_len)
  308.   Else
  309.     PAD(File_ID, fid_len);
  310.   RESET(File_ID, TextFile);
  311.   If EOF(TextFile) then{ ABORT }
  312.     begin
  313.       error(3);
  314.       ConnectFiles := false;
  315.     end
  316.   Else
  317.     begin
  318.     ix := index(File_ID,'.'); { search for an extension }
  319.     jx := index(File_ID,' '); { search for the first space }
  320.     If (ix=0) then{ no extension was specified }
  321.       Setlength(File_ID,jx-1)
  322.     Else
  323.       Setlength(File_ID,ix-1);
  324.     Setlength(New_ID,0);
  325.     append(New_ID, File_ID);
  326.     append(New_ID, dflt_extension);
  327.     PAD(New_ID, fid_len);
  328.     REWRITE(New_ID, Work_File);
  329.     end;
  330. End{ of ConnectFiles };
  331.  
  332. Procedure Initialize;
  333. var    ch: char;
  334. begin
  335.   ListHead := NIL;  { MAKE the LIST EMPTY }
  336.   cline    := 0; { current line counter }
  337.   wordcount := 0;
  338.   idlen := 0;
  339.   tab    := chr(9);  { ASCII Tab character }
  340.   flushing := KNOT{ flushing };
  341. {-INITIALIZE look-ahead char-}
  342.   nextchar.name := blank;
  343.   nextchar.valu := space;
  344.  
  345.   writeln;
  346.   WRITE('DEBUG?');READ(Ch);
  347.   DEBUG := ((Ch='Y') or (Ch='y'));
  348.   writeln;
  349.   WRITE('Output to Console?');READ(Ch);
  350.   CON_wanted := ((Ch='Y') or (Ch='y'));
  351. end;
  352.  
  353. PROCEDURE Clear(code : byte);
  354. {    device dependent routine    }
  355. begin   WRITELN( CHR(code) )
  356. end;
  357.  
  358. Procedure Sign_On;
  359. begin
  360.   Clear(clearcode);
  361.   writeln;
  362.   writeln(' ':20,'***   C O N C O R D A N C E   ***');
  363.   SKIP(4);
  364. end;
  365.  
  366. Begin{ main body of Concordance }
  367.   Sign_On;
  368.   If NOT ConnectFiles then {ABORT} goto 9;
  369.   Initialize;
  370.   SKIP(4);
  371.   cline:= cline +1;
  372.   GetL(Fbuffer) { attempt to read the first line };
  373.   while ((currchar.name<>filemark) AND (NOT error_flag)) do
  374.     begin
  375. {}    If DEBUG then writeln('line',cline:5,'  ',fbuffer);
  376.       ReadWord{Analyze the Text into single 'words' };
  377.       If cline=c4 then cline:=0;
  378.       cline := cline +1;
  379.       GetL(Fbuffer) { attempt to read another line of text };
  380.     end{ while };
  381.   Clear(clearcode);
  382.   WriteItems;    { Write all the Items in order }
  383.   writeln;
  384.   writeln(' ':18, '***   SUMMARY   ***');
  385.   writeln('Total # lines =',cline -1);
  386.   writeln('Total # words =', wordcount);
  387.   writeln;
  388. 9:{ABORT};
  389. end{ of ConCordance }.
  390.