; ---------------------------------------------------------- ; Reassembly of FIND.COM, which was originally extracted ; from the CBBS(R) package available from Ward Christensen ; and Randy Suess. However, considerable rearrangement has ; taken place, most notably the following: ; results in a screen of information ; the search pattern may be a regular expression ; label+line number as an alternative to line number ; instance count reported, both per file and globally ; .COM files are automatically excluded ; squeezed files do not deter the search ; To achieve compatibility with MicroShell the vertical bar ; was replaced by exclamation point; all syntactic elements ; are defined by EQU's and may be redefined. LABEL!PATTERN ; is checked for balanced parentheses and non-null arguments ; to forestall the most common failure modes. Had MicroShell ; not been available, an option to direct the output to some ; disk file would probably have been included. ; ; FYNDE.ASM Copyright (C) 1982 ; Universidad Autonoma de Puebla ; ; [Harold V. McIntosh, 20 December 1982 (SIG/M 165.10)] ; [1 July 1984 - scan squeezed files] ; [4 July 1984 - no false matches w/null lines] ; ---------------------------------------------------------- HT equ 09H ;horizontal tab LF equ 0AH ;line feed CR equ 0DH ;carriage return KZ equ 1AH ;^Z ; Delimiters for the command line LSQ equ '[' ;begin alternative list RSQ equ ']' ;end alternative list LBR equ '{' ;begin iterated expression RBR equ '}' ;end iterated expression ORR equ '!' ;separate alternatives ; Representatives of characters or classes. TAB equ '_' ;substitute for tab QUE equ '?' ;represent any byte ALF equ '@' ;represent any alphanumeric ; CP/M and other locations and parameters cfcb equ 005CH ;CP/M's file control block cblk equ 007CH ;CP/M's block counter csiz equ 0080H ;CP/M's record size cbuf equ 0080H ;CP/M's record buffer ksiz equ 26 ;sector capacity of IN buffer isiz equ ksiz*128 hsiz equ 256 ;max characters in Huffman code ; ------------ org 100H ; ------------ X0100: lxi sp,stak lda cfcb+1 ;file name cpi ' ' jnz X0143 lxi h,M1 ferm: call mssg ;message to console jmp 0000 X0143: lxi h,M2 call mssg ;message to console mvi c,12 lxi d,cfcb ;CP/M's file control block lxi h,file call miuc ;block move xra a sta enth lxi h,cbuf ;CP/M's record buffer mov e,m mov c,e mov d,a xchg inx d dad d mov m,a xchg X0152: inx h dcr c mov a,m ora a jz X029C cpi ' ' jnz X0152 inx h call bala ;check balance of [], {}. call nula ;check for null alternatives lxi d,patt ;command line pattern call muve mvi c,4 lxi d,lzer lxi h,dtot call miuc ;block move lxi h,0000 shld lapo lxi h,patt ;command line pattern shld papo call next ora a jz scan shld papo lxi h,patt shld lapo ; Scan the directory for file names. scan: mvi c,26 ;(1A) set DMA address lxi d,cbuf ;CP/M's record buffer call 0005 ; - B D O S - mvi c,17 ;(11) search once lxi d,file call 0005 ; - B D O S - lxi h,enth inr m mov c,m fnth: inr a jz done ;we're all done dcr c jz this push b mvi c,18 ;(12) search again lxi d,file call 0005 ; - B D O S - pop b jmp fnth ; We're all done. done: lxi h,dtot jmp ferm ;final (error) message ; A prospective file has been located this: dcr a ani 03 add a add a add a add a add a adi 81H mov e,a mvi d,00 mvi c,12 lxi h,cfcb+1 ;CP/M's file control block call miuc ;block move lxi h,cfcb+9 ;CP/M's file control block call dcom ;disregard .COM files jz scan lxi h,cfcb+9 ;CP/M's file control block call dcmd ;disregard .CMD files jz scan ; Open the file, check for squeezing. mvi c,15 ;(0F) open file lxi d,cfcb ;CP/M's FCB call 0005 ; - B I O S - inr a jz 0000 ;quit [without message] xra a sta cblk ;block pointer sta dens ;z/nz=un/squeezed sta mult ;repeat factor lxi h,0000 shld ictr ;input counter lxi h,cfcb+10 ;CP/M's file control block mov a,m cpi 'Q' jnz nsqz call gbyt ;fetch one byte cpi 076H jnz nsqz call gbyt ;fetch one byte cpi 0FFH jnz nsqz lxi h,dens ;z/nz=un/squeezed mvi m,0FFH call rwor ;fetch word ; unsqueezed file name lxi b,200CH ;twelve spaces lxi h,uzfn ;unsqueezed file's name call fiuc ;block fill mvi b,8 lxi d,uzfn ;unsqueezed file's name luup: call gbyt ;fetch one byte ora a jz luut cpi '.' jz luuw stax d inx d dcr b jnz luup luuz: call gbyt ora a jz luut cpi '.' jnz luuz luuw: mvi b,3 lxi d,uzfn+8 stax d inx d luur: call gbyt ora a jz luut stax d inx d dcr b jnz luur luus: call gbyt ora a jnz luus luut: lxi h,uzfn+9 call dcom ;disregard .COM files jz scan lxi h,uzfn+9 call dcmd ;disregard .CMD files jz scan ; load code directory ldic: call rwor ;fetch word lxi b,hsiz mov a,c sub l mov a,b sbb h jnc ldii lxi h,M8 ;'code table won't fit' call mssg jmp scan ldii: dad h dad h mov c,l mov b,h lxi d,code ;code table ldij: call gbyt ;fetch one byte stax d inx d dcx b mov a,c ora b jnz ldij lxi h,roco ;rotation count mvi m,1 nsqz: mvi c,4 lxi d,lzer lxi h,lnum ;'line number' call miuc ;block move mvi c,4 lxi d,lzer lxi h,ftot ;'file total' call miuc ;block move mvi c,8 lxi d,cfcb+1 ;file name lxi h,fnam ;'file name' call miuc ;block move mvi c,3 lxi d,0065H ;extension lxi h,fext ;'file extension' call miuc ;block move lxi h,fhed call mssg ;message to console lda dens ora a jz sixs lxi h,hesq ;'[original]' call mssg sixs: lxi b,2006H ;six spaces lxi h,llbl call fiuc ;block fill X01C8: lxi h,lnum+3 ;increment l.c. call inco ;increment line counter lxi h,lbuf ;line buffer mvi b,0FFH X01E0: inr b jm X01FD push b push h call inch ;char from big bffr to line bffr pop h pop b mov m,a inx h cpi KZ jnz X01E8 lxi h,ftot call mssg ;message to console jmp scan X01E8: cpi LF jnz X01E0 jmp X0202 X01FD: mvi m,CR inx h mvi m,LF inx h ; Check console for termination request. If one ; is present, clear it out before leaving. X0202: mvi m,00 ;guarantee right hand fence mvi c,11 ;(0B) console status call 0005 ; - B I O S - ora a jz culi mvi c,1 ;(01) read console call 0005 ; - B D O S - cpi 03H ;^C jnz skpf lxi h,M4 ;"search terminated" jmp ferm ;final (error) message skpf: lxi h,M5 ;"remainder of file skipped" call mssg ;message to console jmp scan ; Scan the current line. ; First see if it is labelled. culi: lhld lapo mov a,h ora l jz X0217 ;no label requested xchg lxi h,lbuf call chek jnz X0217 ;label not found push h lxi b,2006H ;six spaces lxi h,llbl call fiuc ;block fill pop h lxi d,llbl+5 mvi c,6 didl: dcx h mov a,m cpi HT ;ignore tabs in text jz didl cpi ' ' ;quit at head of line jc dido stax d dcx d dcr c jnz didl dido: mvi c,4 lxi d,lzer lxi h,lnum call miuc ;block move ; Now look for the pattern X0217: lxi h,lbuf ;line buffer X021A: xchg lhld papo ;pattern pointer xchg push h call chek pop h jz X0263 mov a,m cpi CR jz X01C8 ;increment l.c. at X026A inx h jmp X021A ; Pattern matches, so type label & line containing it X0263: lxi h,llbl ;line label call mssg ;message to console lxi h,lbuf ;line buffer call mssg ;message to console lxi h,ftot+3 call inco lxi h,dtot+3 call inco jmp X01C8 ;increment l.c. at X026A ; Increment ASCII counter at (HL-3). inco: mov a,m ori 30H inr a mov m,a cpi ':' rnz mvi m,'0' dcx h jmp inco ; Memory to console mssg: mov e,m inx h push h mvi c,2 ;(02) write console call 0005 ; - B I O S - pop h mov a,m ora a jnz mssg ;message to console ret X029C: lxi h,M3 ;"bad pattern" call ferm ;final (error) message ; decode next character dnch: lxi h,code ;code table dncr: call rbit jnc dncs inx h inx h dncs: mov e,m inx h mov d,m mov a,d cpi 0FEH jz dnct ora a jp dncu mov a,e cma stc cmc ret dnct: stc ret ; Calculate +4*. dncu: lxi h,code ;code table dad d dad d dad d dad d jmp dncr ; read one bit at a time rbit: push h lxi h,roco ;rotation count dcr m jnz rbiu mvi m,8 call gbyt ;fetch one byte sta roby ;rotating byte rbiu: lda roby ;rotating byte rar sta roby ;rotating byte pop h ret ; read one word rwor: call gbyt ;fetch one byte push psw call gbyt ;fetch one byte pop h mov l,h mov h,a ret ; Fetch the next byte. The input buffer will be refreshed if it ; is necessary. For normal files, one byte will be extracted from ; the input buffer; for squeezed files, one byte will be decoded ; from the incoming bit stream and subtracted from the checksum. inch: lda dens ;z/nz = un/squeezed ora a jz gbyt ;fetch one byte lda mult ;repeat factor ora a jz gusq dcr a sta mult ;repeat factor lda lach ;last character read ret gusq: call dnch jnc guss mvi a,1AH ret guss: cpi 090H jz gusu sta lach ;last character read ret gusu: call dnch ora a jnz gusv mvi a,090H ret gusv: dcr a dcr a sta mult ;repeat factor lda lach ;last character read ret ; unsqueezed (normal) text gbyt: lhld ictr ;input counter mov a,h ora l cz indi ;disk to IN area lhld ictr ;input counter dcx h shld ictr ;input counter lhld iptr ;input pointer mov a,m inx h shld iptr ;input pointer ret indi: mvi b,ksiz lxi h,isiz shld ictr ;input counter lxi h,ibuf ;input buffer shld iptr ;input pointer indd: mvi m,KZ push h push b xchg mvi c,26 ;(1A) set DMA address call 0005 ; - B D O S - lxi d,cfcb ;CP/M's file control block mvi c,20 ;(14) read one record call 0005 ; - B D O S - pop b pop h ora a rnz dcr b rz lxi d,csiz ;CP/M's record size dad d jmp indd ; Disregard .COM files dcom: mov a,m cpi 'C' rnz inx h mov a,m cpi 'O' rnz inx h mov a,m cpi 'M' rnz lxi h,M6 ;".COM file disregarded" call mssg ;message to console xra a ret ; Disregard .CMD files dcmd: mov a,m cpi 'C' rnz inx h mov a,m cpi 'M' rnz inx h mov a,m cpi 'D' rnz lxi h,M7 ;".CMD file disregarded" call mssg ;message to console xra a ret ; Advance to next alternative nexx: mov e,m inx h mov d,m xchg next: mov a,m ora a rz inx h call enda rz call begb jz nexx jmp next ; Block fill with C B's starting at (HL). fiuc: mov m,b inx h dcr c jnz fiuc ;block fill ret ; Block move of C bytes from (DE) to (HL). miuc: ldax d mov m,a inx d inx h dcr c jnz miuc ;block move ret ; Move and semi-compile the command line. muve: mov a,m cpi TAB jnz munt mvi a,HT munt: stax d inx h inx d cpi RBR jz murb cpi RSQ jz murb cpi LBR jz mulb cpi LSQ jz mulb must: dcr c jnz muve ret murb: xthl mov m,e inx h mov m,d pop h jmp must mulb: push d inx d inx d jmp must ; Check balance of []'s and {}'s. bala: push h push b lxi b,0101H balb: mov a,m inx h cpi LSQ jnz balc inr b jmp balb balc: cpi RSQ jnz bald dcr b jz balx jmp balb bald: cpi LBR jnz bale inr c jmp balb bale: cpi RBR jnz balf dcr c jz balx jmp balb balf: ora a jnz balb mov a,c cpi 01 jnz balx mov a,b cpi 01 pop b pop h rz balx: lxi h,M3 ;"bad pattern" jmp ferm ;final (error) message ; Check for termination of alternative. enda: cpi ORR rz endb: cpi RSQ rz cpi RBR rz ora a ret ; Check for beginning of alternative. bega: cpi ORR rz begb: cpi LSQ rz cpi LBR ret ; Check for null alternative. nula: push h call nulb pop h ret nulb: mov a,m inx h ora a rz call bega jnz nulb mov a,m call enda jnz nulb jmp balx ; Check for given expression. chek: ldax d inx d call enda rz mov b,a mov a,m cpi CR jz chno mov a,b cpi LBR jz chlb cpi LSQ jz chsq mov c,m inx h cpi QUE jz chek cpi ALF jz chal cmp c jz chek mov b,a mov a,c cpi 'a' jc chno cpi '{' jnc chno ani 05FH cmp b jz chek chno: ori 0FFH ret ; Check alphanumeric. chal: mov a,c cpi '0' jc chno cpi ':' jc chek cpi 'A' jc chno cpi '[' jc chek cpi 'a' jc chno cpi '{' jc chek jmp chno ; Check list of alternatives. chsq: mov c,l mov b,h lhld sqxx push h lhld sqaa push h lhld sqzz push h mov l,c mov h,b shld sqxx xchg mov e,m inx h mov d,m inx h shld sqaa xchg shld sqzz chaa: lhld sqxx call chek jz chff chbb: lhld sqaa ;fail so find next alternative chcc: call next cpi RSQ jz chdd ;no more alternatives, so fail cpi ORR jnz chcc shld sqaa xchg jmp chaa ;try next alternative chdd: lhld sqxx ori 0FFH chee: mov c,l mov b,h pop h shld sqzz pop h shld sqaa pop h shld sqxx mov l,c mov h,b ret chff: xchg ;good alternative, try rest lhld sqzz xchg call chek jz chee jmp chbb ; Check iterative pattern. chlb: mov c,l mov b,h lhld text push h lhld texx push h lhld rest push h lhld rept push h lhld repp push h mov l,c mov h,b shld text shld texx xchg mov e,m inx h mov d,m inx h shld rept shld repp xchg shld rest chlc: lhld rest xchg lhld text call chek ;check rest jz chzz chii: lhld rept ;rest failed xchg lhld text ;keep same text call chek ;try out the repeater jnz choo shld text ;repeater worked, record progress lhld repp ;start alternatives over again shld rept jmp chlc choo: lhld rept ;repeater failed, try next chxx: call next cpi RBR jz chyy ;this was the last, quit cpi ORR jnz chxx shld rept jmp chii chyy: lhld texx ori 00 ;emphasize the RBR chzz: mov c,l mov b,h pop h shld repp pop h shld rept pop h shld rest pop h shld texx pop h shld text mov l,c mov h,b ret M1: db 'The command line',CR,LF db ' FYNDE D:FILE.EXT EXPRESSION',CR,LF db 'will search through all instances of FILE.EXT',CR,LF db '(which may be an ambiguous reference) on disk D',CR,LF db 'to find lines containing EXPRESSION. Such lines',CR,LF db 'will be presented on the console preceded by a',CR,LF db 'line number, and classified by file. EXPRESSION',CR,LF db 'may have the form LABEL!PATTERN or simply the',CR,LF db 'form PATTERN. Both may contain:',CR,LF db ' [p1!p2!...!pn] alternative strings',CR,LF db ' {p1!p2!...!pn} repeated alternatives',CR,LF db ' ? any single character',CR,LF db ' @ for any alphanumeric: a-z, A-Z, 0-9',CR,LF db ' _ in place of horizontal tab',CR,LF db 'When a label is present, lines will be numbered',CR,LF db 'relative to the label. Example: X{?}:![call!ret]',CR,LF db 'will list calls and returns relative to labels',CR,LF db 'like X0100: or X33:. LABEL begins in column 1,',CR,LF db 'PATTERN can begin in any column. Squeezed files',CR,LF db 'will be searched as well as unsqueezed ones. Use',CR,LF db '^C to quit, any other key skips rest of file.',CR,LF db 00 M2: db 'FYNDE.COM 04/01/84 ICUAP',CR,LF,00 M3: db '-- Bad Pattern --',00 M4: db CR,LF,'-- Search Terminated --',00 M5: db ' -- Remainder of File Skipped --',CR,LF,00 M6: db '.COM file disregarded.',CR,LF,00 M7: db '.CMD file disregarded.',CR,LF,00 M8: db ' -- Code Table Won''t Fit --',CR,LF,00 enth: ds 1 file: db 'DFilenameEXT',00 ds 19 sqxx: ds 2 sqaa: ds 2 sqzz: ds 2 text: ds 2 texx: ds 2 rest: ds 2 rept: ds 2 repp: ds 2 ds 100 ;stack area stak: ds 2 ;initialize stack pointer lapo: ds 2 ;label pointer papo: ds 2 ;pattern pointer hesq: db '[original] : ' uzfn: db 'original.xxx' ;unsqueezed file's name db CR,LF,00 fhed: db '------> File ' fnam: db 'xxxxxxxx.' ;filename fext: db 'xxx',CR,LF,00 ;file extension llbl: db ' +' lnum: db ' ',00 lzer: db ' 0' ftot: db ' lines found',CR,LF,00 dtot: db ' instances in the entire disk',CR,LF,00 db 00 ;fence for line buffer lbuf: ds 85H ;line buffer dens: ds 1 ;z/nz = un/squeezed roby: ds 1 ;rotating byte roco: ds 1 ;rotation count mult: ds 1 ;repeat factor lach: ds 1 ;last character read ictr: ds 2 ;input counter iptr: ds 2 ;input pointer ibuf: ds isiz ;input buffer patt: ds 256 ;command line pattern code: ds 4*csiz ;Huffman code table fini: ds 0 end