! FNDSTR - Search all files for FIRST OCCURANCE of string
!
!=======================================================================!
!       NOTE:   This program is provided for non-profit use only.       !
!               It is the property of Digital Solutions, Inc., and      !
!               is not for resale.                                      !
!=======================================================================!
!
!               Jonathan A. Craigue
!               Digital Solutions, Inc.
!               6424 East Tanque Verde, Ste. C
!               Tucson, Az.  85701
!               (602) 886-8472
!
!
!
! To use this program:
!
!       - create a direct.lst file using then command DIR=<fspec>/D/K
!       - RUN FNDSTR
!       - enter up to 5 strings to search for
!       - you may specify:
!               . how many lines into a file the program should read
!                       to look for a match
!               . whether or not to go on to the next file as soon as
!                       any matches are found
!               . wildcard characters using * ( will match any number
!                       of arbitrary characters on the line being searched-
!                       e.g. 'open*#1*input' will match:
!                       open      #1,"data.dat", input
!                       open #11,"def.lst",input
!                   or you may search for literal *'s
!               . fold all search and input lines into upper case or perform
!                       an exact comparison
!
!
map1 fline,f            ! first line for file being searched
map1 iline,s,254
map1 ifile,s,40
map1 ss(5),s,80         ! array for str's to search for
map1 maxs,f             ! # search strings input into ss(5)
map1 aq$,s,80           ! work str
map1 i,f                !
map1 lc,f               !
map1 found,f            !
map1 sss,s,80           ! work string (holds pattern remaining)
map1 w'str,s,254        ! work string (holds line remaining to be searched)
map1 a1,s,80            ! work string (holds current search string)

map1 maxlines,f         ! max lines to search - 0=all
map1 wild,s,1           ! does * in search string mean wild card?
map1 stp,s,1            ! stop if any matches found - goto next file
map1 uc,s,1             ! fold search & input strings to ucase?

map1 pos,f
map1 cnt,f              ! # matches this file
map1 gtot,f
!------------------ vars from spool.fil for header:, print'line:
map1 dt,b,2
map1 xref'co,s,30,"Digital Solutions, Inc."
map1 page'ttl,s,100,"Search for strings"
map1 page$,s,10
map1 pg'cnt,f
map1 frst'sw,b,1
map1 page'head,s,100
map1 dline,s,132
map1 pline,s,132
map1 line'count,f
map1 tdate,s,8
map1 prog$,s,20
map1 ttime,s,20
       ? tab(-1,0);"FNDSTR - search files in DIRECT.LST for strings (use dir=<fspec>/d)";

       call DATIM
       prog$="FNDSTR"
       open #2,"fndstr.lst",output
       open #1,"direct.lst",input
       call GET'SS
IFILE'LOOP:
       input line #1 ifile
       xcall strip,ifile
       fline=1
       if eof(1)=1 then goto ALL'DONE
       if instr(1,ifile," ")<>0 then &
               ? tab(-1,0);"Please create direct.lst using the /d option on DIR !" :&
               end
       call SEARCH'FILE
       goto IFILE'LOOP
ALL'DONE:
       ? tab(23,1);tab(-1,10);tab(-1,21);"*** ALL DONE ***";tab(-1,22);tab(23,27);" - ";
       if stp<>"Y" then &
               ? "  All files: ";str(gtot); &
       else &
               if gtot<>0 then &
                       ? "Occurances found ! "; &
               else &
                       ? "None found";
       ? "  - See FNDSTR.LST"
       ? tab(-1,28);
end
!--------
GET'SS:
       ?
       ?
       ? "Please input strings to find:"
       for i=1 to 5
               ? tab(i+4,1);i using "##";
               ? ".";
       next i
       ? tab(11,1);"Search how many lines into file (cr=all) ? ";
       ? tab(12,1);"Stop after 1st occurrence ? (cr=no) : ";
       ? tab(13,1);"Interpret * as wild card ? (cr=yes) ";
       ? tab(14,1);"Fold everything to ucase ? (cr=yes) ";

       for i=1 to 5
               ? tab(i+4,5);
               input line ss(i)
               if ss(i)="" then maxs=i-1 : i=5
       next i

       ? tab(11,1);"Search how many lines into file (cr=all) ? ";
       input line maxlines
       if maxlines=0 then ? tab(11,45);tab(-1,9);"ALL"

       ? tab(12,1);"Stop after 1st occurrence ? (cr=no) : ";
       input line stp
       stp=ucs(stp)
       if stp="" then stp="N"
       ? tab(12,39);tab(-1,9);
       if stp="N" then ? "No" else ? "Yes"

       ? tab(13,1);"&
Interpret * as wild card ? (cr=yes) ";
       input line wild
       wild=ucs(wild)
       if wild="" then wild="Y"
       ? tab(13,37);tab(-1,9);
       if wild="Y" then ? "Yes" else ? "No"


       ? tab(14,1);"Fold everything to ucase ? (cr=yes) ";
       input line uc
       uc=ucs(uc)
       if uc="" then uc="Y"
       ? tab(14,37);tab(-1,9);
       if uc="Y" then ? "Yes" else ? "No"

       ? tab(23,1);"Any change? ";
       input line aq$
       if ucs(aq$)="Y" then goto GET'SS
       ? tab(23,1);tab(-1,10);
       ? tab(-1,29);
       for i=1 to 5
               if uc="Y" then ss(i)=ucs(ss(i))
               ? tab(i+4,1);tab(-1,9);i using "##";
               ? ".";ss(i);
       next i

       call HEADER
return
!---------
SEARCH'FILE:
       open #11,ifile,input
       ? tab(16,1);tab(-1,11);"Searching ";ifile;tab(-1,12);
       lc=1
SLOOP:
       input line #11 iline
       if uc="Y" then iline=ucs(iline)
       if eof(11)=1 then goto E'SLOOP
       if lc>maxlines and maxlines<>0 then goto E'SLOOP
       call SEARCH'LINE
       if found=1 and stp="Y" then goto E'SLOOP
       lc=lc+1
       goto SLOOP

E'SLOOP:
       close #11
       ? tab(16,1);tab(-1,9);
       ? tab(17,1);tab(-1,16);ifile;tab(17,27);" - ";
       gtot=gtot+cnt
       if stp<>"Y" then &
               ? "This file ";str(cnt);"  All files: ";str(gtot) &
       else &
               if cnt<>0 then &
                       ? "Found" &
               else &
                       ? "Not found"
       ? tab(23,1);tab(-1,10);
       cnt=0
return
!---------------
SEARCH'LINE:
       found=0
       if wild="Y" then goto SEARCH'WILD
       for i=1 to maxs
               if instr(1,ucs(iline),ucs(ss(i)))=0 then goto NI
               pline=iline
               call PRINT'LINE
               found=1
               cnt=cnt+1
               if stp="Y" then i=maxs
NI:
       next i
return

!--------------
SEARCH'WILD:
       for i=1 to maxs
               sss=ss(i)
               found=0
               w'str=iline
               call MATCH
               if found=1 then &
                       pline=iline :&
                       call PRINT'LINE :&
                       cnt=cnt+1 :&
                       if stp="Y" then i=maxs
       next i
return
!-------------
MATCH:
       pos=instr(1,sss,"*")
       if pos=0 then &
               a1=sss :&
               sss="" &
       else &
               if pos<>1 then &
                       a1=sss[1,pos-1] :&
                       sss=sss[pos+1,len(sss)] &
               else &
                       a1=sss[2,len(sss)] :&
                       sss=""

       pos=instr(1,w'str,a1)
       if pos=0 then &
               found=0 :&
               goto E'MATCH

       if pos<>1 then &
               w'str=w'str[pos+len(a1)-1,len(w'str)] &
       else &
               w'str=w'str[1+len(a1),len(w'str)]

       if len(sss)=0 then found=1 : goto E'MATCH
       goto MATCH
E'MATCH:
return
!------------
HEADER:
       if frst'sw # 0 pline[1;1] = chr(12) : ? #2 pline
       frst'sw = 1
       pline[1,20] = "Date: " + tdate
       pg'cnt = pg'cnt + 1 : page$ = pg'cnt using "###"
       pline[108;10] = "Page " + page$
       xcall strip, page'ttl
       pline[40-int(len(page'ttl)/2);len(page'ttl)] = page'ttl
       ? #2 pline
       pline[108;12] = "Prgm: " + prog$
       pline[1;20]="Time: " + ttime
       xcall strip, xref'co
       pline[40-int(len(xref'co)/2);len(xref'co)] = xref'co
       ? #2 pline
       pline = dline
       ? #2 pline
       if page'head=""  then goto NO''P''HEAD
       xcall strip, page'head
       if len(page'head)<40 then &
               pline[40-int(len(page'head)/2);len(page'head)] = page'head &
       else &
               pline=page'head
       ? #2 pline
NO''P''HEAD:
       line'count = 0
return
!-----------
PRINT'LINE:
       aq$=space(20)
       if fline=1 then aq$[1,20]=ifile
       fline=0
       ? #2 aq$;"|";pline
       line'count=line'count+1
       pline=""
       if line'count>60 then call HEADER
return
!---------
DATIM:
       dt=1
       xcall odtim,w'str,0,0,dt
       tdate=w'str[1,10]
       ttime=w'str[11,len(w'str)]
return
!----------