; ****** LOOKUP.ASM ******* ; ; by Jim Schenkel (415) 928-4445 - reads a data file and tries to match ; match an input string ; ; rev. 7/10/87 - Ernest F. Barnhart, N8DVE for AB17 RCP/M ; ; 1. Modified to only load program specified file name, ; so it can be used on drive A0: of RCP/M to fast ; search a specific file. Suggest .COM program be ; named to identify specific purpose, such as OFFLINE ; to search off line disk catalog. ASCII file to search ; may be on any drive specified in program WITH SAME ; USER AREA. ; 2. Program had been previously converted to .Z80 code. ; Some code has been further streamlined. ; 3. Added PAUSE, RESTART, and ABORT features. ; 4. The program sign on, prompt, drive, file name and ; maximum search string length can also be easily ; patched by looking for in code labels, allowing ; program program development for other specific ; searches. ; 5. Other minor code changes. ; ; rev. 8/15/86 - Paul Foote, to protect CCP and start buffer on even page ; rev. 9/1/82 - Jim Schenkel .Z80 ; Needed for M80 assembler, else ignore ASEG ; Needed for M80 assembler, else ignore ORG 100H ; CP/M operating system JP START BDOS EQU 0005H ; DOS entry point FCB EQU 005CH ; File control block RDCON EQU 01H ; Read console TYPEF EQU 02H ; Type character to console PRINTF EQU 09H ; Print string terminated by '$' RDBUFF EQU 0AH ; Read console buffer CONSTT EQU 0BH ; Console status OPENF EQU 0FH ; Open file READF EQU 14H ; Sequential read DMAF EQU 1AH ; Set DMA CR EQU 0DH ; Carriage return LF EQU 0AH ; Line feed BELL EQU 07H ; Bell EOF EQU 1AH ; EOF PAUSE EQU 'S'-40H ; Pause character RESTRT EQU 'R'-40H ; Restart Character ABORT EQU 'C'-40H ; Abort character ; Drive and file name of exactly 11 characters must be placed here. ; User area must the same as .COM is on. DEFB 'MAXLEN>' MAXLEN EQU 08H ; The search string maximum length DEFB 'DRVFILE>' FILNAM: DEFB 0,'MAST LST' ; Drive (Current=0, A=1, B=2, etc.) & file name START: LD (OLDSTK),SP ; Save Stack LD SP,STACK ; New stack LD DE,SIGNON ; Sign on CALL PRINT ; Move the default file name into the FCB LD HL,FILNAM ; Point to file name LD DE,FCB ; Point to FCB filename LD BC,12 ; Counter LDIR ; Move it ; Open the file LD DE,FCB ; Point to FCB LD C,OPENF ; Open the file CALL BDOS INC A ; FF-->0 if no file LD DE,NOFILE ; Error message JP Z,EXIT ; So bail out ; Calculate the top of memory LD HL,(0006) ; Get BDOS location LD DE,0C00H ; Leave enough room SBC HL,DE ; To avoid trouble LD (TOP),HL ; Store upper bound ; Initialize the pointer to the DMA LD DE,BUFFER ; Point to data area LD (BDMA),DE ; Store current pointer LD C,DMAF ; Set the DMA CALL BDOS XOR A ; Zero A LD (FCB+32),A ; Clear CR in DMA ; Read data into memory READ: LD DE,FCB ; Get record LD C,READF CALL BDOS OR A ; Zero if read ok JR NZ,BUFSIZ ; Else entire file was read ; Increment the buffer pointer LD HL,(BDMA) ; Get the current pointer LD DE,80H ; Add 128 bytes ADD HL,DE ; As offset LD (BDMA),HL ; Store new pointer PUSH HL ; Save pointer LD DE,(TOP) ; Get upper bound SBC HL,DE ; Subtract from pointer JR C,XBF ; DE>HL, so proceed LD DE,OVRFLW ; HL>DE, so CALL PRINT ; Print message and JR BUFSIZ ; Don't read any more XBF: POP DE ; Pick up pointer in DE LD C,DMAF ; Update the DMA CALL BDOS JR READ ; Do it again ; Calculate size of data buffer BUFSIZ: LD HL,(BDMA) ; Get last DMA LD DE,80H ; Add another block ADD HL,DE ; To get to end of buffer LD DE,BUFFER ; Get start of buffer OR A ; Clear carry SBC HL,DE ; Subtract start from end LD (BUFLEN),HL ; Store buffer length ; Get the input string GETSTR: CALL CLSTR ; Clear the search string LD DE,PROMPT ; Ready the prompt LD C,PRINTF ; Print it CALL BDOS LD DE,SERSTR ; Point to search string buffer LD C,RDBUFF ; Read a buffer CALL BDOS LD E,LF ; Prepare to CALL PRCHR ; Print LD A,(ACTLEN) ; Get search string actual length OR A ; Test for zero JR NZ,CONT LD DE,CRLF JR EXIT ; 0 = aborted ; Convert to upper-case CONT: LD BC,(SERSTR) ; Get search string actual length in B LD HL,STRING ; Point to string UP: LD A,(HL) ; Get a character CP '@' ; Greater than '@'? JP M,NOALFA ; If negative then not alpha CP '{' ; Less than or equal '{'? JP P,NOALFA ; If positive then not alpha AND 5FH ; Convert to upper case NOALFA: LD (HL),A ; And store it INC HL ; Bump pointer DJNZ UP ; And loop ; Search for the string LD HL,BUFFER ; Point to buffer LD BC,(BUFLEN) ; Counter for buffer length LOOK: LD DE,STRING ; Point to search string LD A,(DE) ; Get first character CPIR ; Look for a match JR Z,GOT1 ; Found a match JP PO,GETSTR ; Counter has reached zero ; So ask for another string JR LOOK ; Do entire buffer ; Found match for first character, check the rest of the search string GOT1: PUSH BC ; Save buffer length counter LD BC,(SERSTR) ; Get search string actual length in B DEC B ; Allow for first character JR Z,SHOW ; Print if only 1 GOT2: INC DE ; Bump pointer to string LD A,(DE) ; Get a character CP '?' ; Wild card? JR Z,WILD ; Yes, so ignore match CP (HL) ; Does it match? JR NZ,NOPE ; No, try again WILD: INC HL ; Bump pointer to buffer DJNZ GOT2 ; Loop for all characters JR SHOW ; All characters match NOPE: POP BC ; Restore BUFLEN counter JR LOOK ; And keep looking ; Print the record and update the data pointer and counter to the end of ; the record SHOW: POP BC ; Restore BUFLEN counter SHOW1: DEC HL ; Back up a character PUSH HL ; Save pointer to buffer LD DE,BUFFER ; Beginning of buffer OR A ; Clear the carry SBC HL,DE ; Are we at the beginning? POP HL ; (restore the pointer) JR Z,NEXTCH ; Yes, so print 1st record INC BC ; Else increment counter LD A,(HL) ; What's that character? CP CR ; Is it a carriage return? JR NZ,SHOW1 ; No, so go back further NEXTCH: LD E,A ; Ready to print character CALL PRCHR ; Start printing the record INC HL ; Byte by byte DEC BC ; Keeping track of length LD A,B ; If bc goes to zero OR C ; Then at the end of the data buffer JR Z,LOOK ; If EOR then look at next record LD A,(HL) ; Else get another character CP EOF ; End of file? JP Z,GETSTR ; If EOF then get another string CP CR ; End of record? JR NZ,NEXTCH ; If not EOR then get another character CALL CHECK ; ELse record printed, check if okay to proceed CP ABORT ; Abort? JR NZ,NOSTOP ; If not aborted then do not stop LD DE,ABRT ; Else load abort message JR EXIT ; And exit NOSTOP: CP RESTRT ; Restart? JP Z,GETSTR ; If restarted then get new string JR LOOK ; Else go look some more ; Wrap it up and bail out EXIT: CALL PRINT ; Print message LD SP,(OLDSTK) ; Put it in place RET ; Return to CCP ;----------------------------------------------------------------------- ; subroutines ; Print a character PRCHR: PUSH AF ; Save everything PUSH BC PUSH DE PUSH HL LD C,TYPEF ; Type character function CALL BDOS ; Do it, then POP HL ; Restore everything POP DE POP BC POP AF RET ; Clear the input string CLSTR: LD B,MAXLEN ; Counter for maximum string length LD HL,STRING ; Point to string storage XOR A ; Clear a CLR2: LD (HL),A ; Zero a byte INC HL ; Bump pointer DJNZ CLR2 ; And loop RET ; Print a string terminated by '$' PRINT: PUSH AF ; Save the registers PUSH BC PUSH DE PUSH HL LD C,PRINTF ; Print function CALL BDOS POP HL ; Restore the registers POP DE POP BC POP AF RET ; Check if okay to proceed CHECK: PUSH HL ; Save registers PUSH DE PUSH BC LD C,CONSTT ; Get console status CALL BDOS OR A ; 0 = Key not pressed JR Z,CHKFIN ; If key not pressed then check finished LD C,RDCON ; Key pressed, read console CALL BDOS CP PAUSE ; Pause? JR NZ,CHKFIN ; If not pause then check finished LD C,RDCON ; Paused, read console CALL BDOS CHKFIN: POP BC ; Recall registers POP DE POP HL RET ; Messages CRLF: DEFB CR,LF,'$' DEFB 'SIGNON>' SIGNON: DEFB CR,LF DEFB '[ AB17 Off-Line Disc-Catalog File-Search Utility ]' DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,CR,LF DEFB '[ ^C to Cease, Any Key to Resume, ^S to Stop Scroll ]',CR,LF DEFB '[ Wild card chars as ''?'' ONLY (and not as 1st char) ]','$' DEFB 'PROMPT>' PROMPT: DEFB CR,LF,LF,'Enter a search string or file name => ',0,BELL,'$' NOFILE: DEFB CR,LF,LF,'++ Cannot find the data file! ++',CR,LF,BELL,'$' OVRFLW: DEFB CR,LF,LF,'++ Warning - Partial file loaded! ++',BELL,'$' ABRT: DEFB CR,LF,LF,'++ Search aborted! ++',CR,LF,BELL,'$' ; Storage DEFS 40H ; Stack area STACK EQU $ ; Reserved OLDSTK: DEFW 0 ; Old stack pointer TOP: DEFW 0 ; Top of memory BUFLEN: DEFW 0 ; Length of data buffer BDMA: DEFW 0 ; Current DMA pointer ; Read buffer - SERSTR, ACTLEN and STRING must be in this order SERSTR: DEFB MAXLEN ; Max length of search string ACTLEN: DEFB 0 ; Reserved for actual length STRING: DEFS MAXLEN ; Space for search string ORG ($+255)/256*256 BUFFER EQU $ ; Begin data buffer here END