!Utility to search text of file(s) for keystring.

! MDP Feb/1984.
!JHB hacked it Sep 1984. Commented out stats, added
!option to display text centred with newlines replaced by '_' and tidied up a bit
!JHB at it again Oct 84 - added output file option
!JHB at it again May 85 - added "suppress output" option

%own %string (255) Wild File     = "",
{{                 In file       = "",
                   Key = ""
%own %byteinteger  disflag       = 0

%include "inc:util.imp"
%include "inc:fs.imp"
%include "inc:fsutil.imp"

%begin
   %string (31) %array File Names (1 : 110)
   %integer Number of Files = 0
   %string (63) This File, A, B, Base File Name, Directory, Line, outfile
   %integer Ptr 1, Ptr 2, Index, outstream
   %integer Number Found = 0, Flag = 0
   %integer CPU 0 = 0, CPU 1 = 0, CPU 2 = 0, Call = 0

   %routine Load Directory (%string (7) Directory)

      %string (127) Line

      %on 0,1,2,3,4,5,6,7,8,9,10 %start
         -> End Load
      %finish

      Directory = Directory . ":" %if Directory # ""
      Open Input (1, Directory."Directory");   Select Input (1)

      Number of Files = 0
      %cycle
         Read Line (Line)
         Number of Files = Number of Files + 1
         File Names (Number of Files) = Line
      %repeat

 End Load:
      %if Number of Files = 0 %start
         Printline("SEARCH : Can't load directory - ".Event_Message)
         %stop
      %finish
      Close Input
      Select Input (0)
   %end

   %predicate Match String (%integer Source, Pattern, Length)

      %label False, Case Ok

{ Call = Call + 1
      %true %if Length = 0

      *Move.L Source,  A0
      *Move.L Pattern, A1
      *Move.L Length,  D0

   Compare:
      *Move.B (A0)+, D1
      *Cmp.B  #'A', D1
      *Blt    Case Ok
      *Cmp.B  #'Z', D1
      *Bgt    Case Ok
      *Or.B   #' ', D1
   Case Ok:
      *Move.B (A1)+, D2
      *Cmp.B  D1,D2
      *Bne    False
      *Subq   #1, D0
      *Bne    Compare
!      *DBne   D0, Compare

!      Number Found = Number Found + 1
      %true
   False:
      %false
   %end

   %routine Display String (%integer %name Index,
                            %integer Start, Finish,
                            %string (31) File Name)

      %own %string (31) Last File = ""
      %integer Sym, From, To, Count

      %if Last File # File Name %start
         New Line
         Printline("*** ".File Name." :***********************************")
         New Line
         Last File = File Name
      %finish

      %if disflag = 0 %start 
         !Display the line containing the text. Woe betide if it's long.

         From = Index
         From = From - 1 %while From > Start  %and Byte Integer (From) # Nl
         From = From + 1 %if from # start

         To = Index
         To   = To   + 1 %while To   < Finish %and Byte Integer ( To ) # Nl

         %if to - from > 79 %start ;!Very long line
            from = index - 39 %if index - 39 > from
            to = from + 80 %if from + 80 < to
         %finish

         Index = To

      %elseif disflag=1
         from = index - 39; to = index + 39
         index = to

      %else ;!Suppress printing
         %return

      %finish

      from = start %if from < start; to = finish %if to > finish
      %for sym = from, 1, to-1 %cycle
         %if ' ' <= byteinteger(sym) <= 16_7e %then printsymbol(byteinteger(sym)) %else %c
         printsymbol('_')
      %repeat
      newline
   %end

   %routine  Search File (%string (31) Directory, File)

      %integer File Start, Len, File End
      %integer Sym, Upper, Index
      %integer F Start

      File = Directory .":". File %if Directory # ""
      Connect File (File, 0, File Start, Len)

!      CPU 2 = CPU Time
      File End = File Start + Len - 1
      Upper = File End - length(key) + 1
      Index = File Start

      %while Index < Upper %cycle
         %if Match String (Index, addr(key)+1, length(key)) %start
            Display String (Index, File Start, File End, File)
            %exit %if disflag=2
         %else
            Index = Index + 1
         %finish
      %repeat
!      CPU 2 = CPU Time - CPU 2
       heapput(file start)
   %end

   %on 3,4,9 %start
      -> Deleted file %if Flag = 1
      newline
      %Stop
   %finish

   outfile = ":"; wild file = "*.*"

{{ define param ("IN", infile, 0)
   Define Param ("Wildfile", Wild File, 0)
   Define Param ("Searchstring", Key, pam nodefault)
   Define enum Param ("Line,Centred,None", disflag, 0)
   define param("Output", outfile, pam newgroup)
   Process Parameters (CLI Param)

   Base File Name = Wild File
{{ open input(1, infile) %if infile # ""
{{ Prompt ("File:   ")
{{ Read Line (Base File Name) %while Base File Name = ""
{{ Prompt ("String: ")
{{ Read Line (Key) %while Key = ""
{{ close input %if infile # ""

   !Ditch quotes if he quoted it and map to lower case
   Key = Sub String (Key, 2, Length (Key)) %if Charno (Key, 1) = '"'
   length(Key) = length(Key) - 1 %if charno(key, length(key)) = '"'
   %if length(key) = 0 %then printstring("SEARCH: *** Null search string supplied ***
") %and %stop
   to lower(key)

   !Haul in USER:DIRECTORY special file
   Directory = "" %unless Base File Name -> Directory .(":"). Base File Name
   Load Directory (Directory)

   Ptr 1 = 1; Ptr 2 = 1
   %while Ptr 1 <= Number of Files %cycle
      This File = File Names (Ptr 1)
      %if Matches (This File, Base File Name) %start
         %if Base File Name = "*" %start
            Ptr 1 = Ptr 1 + 1 %and %continue %if This File -> A .("."). B
         %finish
         File Names (Ptr 2) = This File
         Ptr 2 = Ptr 2 + 1
      %finish
      Ptr 1 = Ptr 1 + 1
   %repeat

   Number of Files = Ptr 2 - 1
   %if Number of Files = 0 %start
      Printline("No files matched file specification.")
      %stop
   %finish

!!?   close output
   %if outfile="" %or outfile= ":" %then outstream=0 %elsestart
      printline("Recording output in ".outfile)
      outstream=2
      open output(2, outfile); selectoutput(2)
   %finish

   Index = 1
   CPU 0 = CPU Time
   %while Index <=Number of Files %cycle
      Flag = 1
      Search File (Directory, File Names (Index))
Deleted File:
      Flag = 0
      CPU 1 = CPU 1 + CPU 2
      Index = Index + 1
   %repeat

   New Line
close output %and selectoutput(0) %if outstream#0
%end %of %program
