; ****** LOOKUP.ASM ******* ; ; by Jim Schenkel (415) 928-4445 - reads a data file and tries to match ; match an input string ; ; 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 TYPEF EQU 2 ; Type character to console PRINTF EQU 9 ; Print string terminated by '$' RDBUFF EQU 10 ; Read console buffer OPENF EQU 15 ; Open file READF EQU 20 ; Sequential read DMAF EQU 26 ; Set DMA CR EQU 0DH ; Carriage return LF EQU 0AH ; Line feed TAB EQU 9 ; Tab character ; File name must be exactly 11 bytes (FILENAME.TYP) - placed here so it ; can be easily changed to default to your favorite program. FILNAM: DEFB 'MAST LST' ; Name of default file ; Initialize local stack START: LD HL,0 ; Clear HL ADD HL,SP ; Add in old stack LD (OLDSP),HL ; Save it LD SP,STACK ; Set up new stack CALL CLEAR ; Clear screen ; Check for command line file name LD A,(FCB+1) ; Get first character CP ' ' ; If it's not a space JR NZ,OPEN ; Then use that name LD DE,HOWDY ; Sign on CALL PRINT ; Move the default file name into the FCB LD HL,FILNAM ; Point to file name LD DE,FCB+1 ; Point to FCB filename LD BC,11 ; Counter LDIR ; Move it ; Open the file OPEN: LD DE,FCB ; Point to FCB LD C,OPENF ; Open the file CALL BDOS LD DE,NOFILE ; Error message INC A ; FF-->0 if no file JP Z,ERROR ; So bail out ; Calculate the top of memory LD HL,(0006) ; Get BDOS location LD DE,900H ; 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 give CALL 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,MX ; Point to input buffer LD C,RDBUFF ; Read a buffer CALL BDOS LD A,(MX+1) ; Get string length OR A ; Test for zero JR NZ,CONT LD DE,CRLF JR ERROR ; 0 = aborted ; Convert to upper-case CONT: LD BC,(MX) ; Get CX in B LD HL,STRING ; Point to string UP: LD A,(HL) ; Get a character CP 'a' ; Check for lower case JR C,NOLO ; Jump if ok SUB 20H ; Else convert to lower LD (HL),A ; And store it NOLO: INC HL ; Bump pointer DJNZ UP ; And loop ; Search for the string SEARCH: LD HL,BUFFER ; Point to buffer LD BC,(BUFLEN) ; Counter for 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 BUFLEN counter LD BC,(MX) ; Get CX 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 LD A,(HL) ; Get another character CP 1AH ; End of file? JR Z,GETSTR ; Then get another string CP CR ; End of record? JR NZ,NEXTCH ; No, get another character JR LOOK ; Yes, so go look some more ; Wrap it up and bail out ERROR: CALL PRINT ; Print message LD HL,(OLDSP) ; Get old stack pointer LD SP,HL ; Put it in place RET ; Return to CCP ;----------------------------------------------------------------------- ; subroutines ; Clear the screen CLEAR: LD E,26 ; Clear screen character ; 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,80 ; Counter for 128 bytes 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 ; Messages CRLF DEFB CR,LF,'$' HOWDY: DEFB CR,LF,TAB,'*** SELECT STRING TO FIND ***',CR,LF,LF,'$' NOFILE: DEFB CR,LF,'++ Cannot find the data file ++',CR,LF,'$' OVRFLW: DEFB CR,LF,LF,'++ File is longer than available space, ' DEFB 'excess is unavailable ++',CR,LF,'$' PROMPT: DEFB CR,LF,LF,'==>','$' ; Storage DEFS 64 ; Stack area STACK EQU $ ; Reserved OLDSP: 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 - MX, CX and string must be in this order MX: DEFB 80H ; Max length of search string CX: DEFB 0 ; Reserved for actual length STRING: DEFS 80H ; Space for search string ORG ($+255)/256*256 BUFFER EQU $ ; Begin data buffer here END