amiga-e/amigae33a/E_v3.3a/Src/Src/Pd/findf.e

245 lines
4.4 KiB
Plaintext

/*
findf
A very fast case-sensitive grep-style search program using
async i/o and the Boyer-Moore search algorithm.
Usage - same as 'c:search' for the commands implemented.
Michael Zucchi 1994
*/
MODULE 'dos/dos', 'dos/dosasl',
'locale',
'tools/async'
DEF skip[256]:ARRAY OF CHAR, -> skip array
line[1024]:ARRAY OF CHAR, -> input buffer
buffer[1024]:ARRAY OF CHAR, -> for case-sensitive searches
m, -> length of string
string:PTR TO CHAR, -> string to match
uppertable[256]:ARRAY OF CHAR,-> lower->upper conversion table
quiet, nonum, quick, ncase -> settings
PROC main()
DEF args:PTR TO LONG, rdargs, p:PTR TO LONG, an:PTR TO anchorpath,go,
fib:PTR TO fileinfoblock, loc, i
args:=[0,0,0,0,0,0,0];
IF rdargs:=ReadArgs('FROM/M,SEARCH/A,ALL/S,NONUM/S,QUIET/S,QUICK/S,CASE/S', args, 0)
string:=args[1];
nonum:=args[3];
quiet:=args[4];
quick:=args[5];
ncase:=args[6]=0;
IF ncase
IF localebase:=OpenLibrary('locale.library', 0)
IF loc:=OpenLocale(0);
FOR i:=0 TO 255 DO uppertable[i]:=ConvToUpper(loc, i);
CloseLocale(loc);
ELSE
FOR i:=0 TO 255 DO uppertable[i]:=IF i>="a" AND i<="z" THEN i-32 ELSE i
ENDIF
ELSE
FOR i:=0 TO 255 DO uppertable[i]:=IF i>="a" AND i<="z" THEN i-32 ELSE i
ENDIF
CloseLibrary(localebase);
MOVE.L uppertable,A0
MOVE.L string,A1
MOVEQ #0,D0
mn_up: MOVE.B (A1),D0
MOVE.B 0(A0,D0.W),(A1)+
BNE.S mn_up
ENDIF
initskip();
IF an:=New(SIZEOF anchorpath + 256)
an.strlen:=255
an.breakbits:=SIGBREAKF_CTRL_C;
fib:=an.info
p:=args[0];
go:=0
WHILE p[] AND (go=0)
go:=MatchFirst(p[], an);
WHILE go=0
IF (fib.direntrytype) <0
go:=scanfile(an+SIZEOF anchorpath);
ELSE
IF args[2]
IF (an.flags AND APF_DIRCHANGED)=0 THEN an.flags:=an.flags OR APF_DODIR
ENDIF
ENDIF
IF go=0 THEN go:=MatchNext(an);
ENDWHILE
p++
ENDWHILE
IF quick THEN WriteF('\e[M');
Dispose(an);
ENDIF
FreeArgs(rdargs);
ELSE
WriteF('FindF, Michael Zucchi 1994.\nERROR: bad args\n'+
' FROM/M files/patterns to search\n'+
' SEARCH/A text to search for\n'+
' ALL/S recursively scan subdirectories\n'+
' NONUM/S do not output line numbers\n'+
' QUIET/S do not output matched lines\n'+
' QUICK/S faster file-scan display\n'+
' CASE/S do a case-sensitive search\n');
ENDIF
ENDPROC
/*
search a single file, by filename, line at a time
*/
PROC scanfile(name)
DEF number, file, found=0,go=0
IF quick
WriteF('\s\e[K\b', name);
ELSE
IF quiet=0 THEN WriteF('\s\n', name);
ENDIF
number:=1;
IF (file:=as_Open(name, MODE_OLDFILE, 3, 10240))
WHILE as_FGetS(file, line, 1023) AND (go=0)
IF testmatch()
IF quiet
IF found=0 THEN WriteF('\s\n', name);
JUMP close
ELSEIF nonum
-> IF quick AND found=0 THEN WriteF('\n');
WriteF('\s', line);
ELSE
-> IF quick AND found=0 THEN WriteF('\n');
WriteF('\d[6] \s', number, line);
ENDIF
found:=1
ENDIF
number++
go:=CheckSignal(SIGBREAKF_CTRL_C)
ENDWHILE
close:
as_Close(file);
ENDIF
ENDPROC go
/*
Initialise the skip table for a given search string
*/
PROC initskip()
DEF i
m:=StrLen(string);
-> initialise skip table for all characters
FOR i:=0 TO 255
skip[i]:=m+1;
ENDFOR
-> set skip table for characters in the string
FOR i:=0 TO m-1
skip[string[i]]:=m-i;
ENDFOR
ENDPROC
/*
Looks for a match in a given line
*/
PROC testmatch()
IF m<1 THEN RETURN
MOVEM.L A4-A5,-(A7)
MOVE.L m,D7
SUBQ.L #1,D7
TST.L ncase
BEQ.S tm_case
-> non case-sensitive
MOVE.L line,A3
MOVE.L buffer,A0
LEA 1(A0,D7.L),A2
MOVE.L uppertable,A1
MOVEQ #0,D0
tp_up: MOVE.B (A3)+,D0
MOVE.B 0(A1,D0.W),(A0)+
BNE.S tp_up
BRA.S tp_match
-> case sensitive
tm_case:
MOVE.L line,A0
LEA 1(A0,D7.L),A2 -> a[i]
tm_scan:
TST.B (A0)+ -> <hack> find end of string
BNE.S tm_scan
tp_match:
MOVE.L string,A1
MOVE.L A1,A5
LEA 1(A1,D7.L),A1 -> p[j]
MOVE.L skip,A4
MOVE.L D7,D3
ADDQ.L #2,D3
MOVEQ #0,D1
tm_loop0:
MOVE.L D7,D2
MOVE.L A1,A3
tm_loop:
MOVE.B -(A2),D1
CMP.B -(A3),D1
BEQ.S tm_matchchar
MOVE.L A5,D0
SUB.L A3,D0 -> -j
ADD.L D3,D0 -> M-j+1
MOVE.B 0(A4,D1.W),D1 -> skip[character]
CMP.L D0,D1
BLT.S tm_add0
ADD.L D1,A2
tm_ok: CMPA.L A0,A2
BLT.S tm_loop0
MOVEQ #0,D0
BRA.S tm_exit
tm_add0:
ADD.L D0,A2
BRA.S tm_ok
tm_matchchar:
DBF D2,tm_loop
MOVEQ #-1,D0
tm_exit:
MOVEM.L (A7)+,A4-A5
ENDPROC D0