home *** CD-ROM | disk | FTP | other *** search
-
-
- ; ----------------------------------------------------------
- ; 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:
- ; - <no file name> results in a screen of information
- ; - the search pattern may be a regular expression
- ; - instance count reported, both per file and globally
- ; 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. PATTERN!SKELETON
- ; 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. STUTE.ASN was
- ; derived from STUTE.ASM by applying Sorcim's TRANS86, then
- ; cleaning up the resulting code by hand. The code can be
- ; assembled by Sorcim's ACT86, which uses a different style
- ; than the Intel assembler. STUTE differs from FIND in that
- ; the patterns found are replaced by a constant rather than
- ; just being locatse, and that a new disk file is created
- ; to hold the modified text. The extension of each original
- ; file is changed to .BAK.
- ;
- ; STUTE.ASN Copyright (C) 1983
- ; Universidad Autonoma de Puebla
- ;
- ; [Harold V. McIntosh, 16 November 1983]
- ; ----------------------------------------------------------
-
- 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
-
- ; CPM locations and parameters
-
- BDOS: equ 224 ;CP/M interrupt to BDOS
-
- TFCB equ 005CH ;CP/M's file control block
- CBLK equ 007CH ;CP/M's block counter
- TSIZ equ 0080H ;CP/M's record size
- TBUF equ 0080H ;CP/M's record buffer
- KSIZ equ 26 ;sector capacity of IN buffer
- ISIZ equ KSIZ*128
- OSIZ equ 128
-
- ; -------------
- org 0100H
- ; -------------
-
- BEGN: cmpb TFCB+1,#' ' ;file name
- jnz X0143
- ld bx,#TUTO ;tutorial message
- jmp GBYE
-
- X0143: ld bx,#LOGO ;identification line
- call MSSG
-
- ld ah,#12
- ld dx,#TFCB ;CP/M's FCB
- ld bx,#FILE ;generic filename
- call MIUC
-
- ld al,FILE ;generic filename
- sto al,KFIL ;backup file (.BAK)
- sto al,IFIL ;input file (.EXT)
- sto al,OFIL ;output file (.$$$)
- sto al,UFIL ;active output (.$$$)
- stob #0,ENTH
-
- ld bx,#TBUF ;CP/M's record buffer
- ld dl,[bx]
- mov cl,dl
- ld dh,#0
- xchg bx,dx
- inc dx
- add bx,dx
- stob #0,[bx] ;mark end of console line
- xchg bx,dx ;take up beginning of line
- X0152: inc bx
- dec cl
- cmpb [bx],#0
- jnz GPAT
- jmp BADP ;message: 'Bad Pattern'
- GPAT: cmpb [bx],#' '
- jnz X0152 ;pass over file name
- inc bx
- call BALA ;check balance of [], {}.
- call NULA ;check for null alternatives
- ld dx,#PATT ;command line pattern
- call MUVE
- xchg bx,dx
- dec bx
- sto bx,SKND ;skeleton end
-
- ld ah,#4
- ld dx,#LZER ;counter initializer
- ld bx,#DTOT ;'Disk Total'
- call MIUC
-
- ld bx,#PATT ;command line pattern
- sto bx,PAPO ;pattern pointer
- call NEXT
- sto bx,SKPO ;skeleton pointer
-
- ; Scan the directory for file names. A list is made of files
- ; which will be scanned, both because of a quirk in CP/M's
- ; "search again" and to avoid a future encounter with a file
- ; which has already been processed and given the old name.
- ; Likewise, .BAK and .$$$ files are excluded from analysis.
-
- PREP: sto #1,DCTR ;directory counter
- sto #DIRY,DPTR ;#directory extract,directory pointer
-
- ld cl,#26 ;(1A) set DMA address
- ld dx,#TBUF ;CP/M's record buffer
- int BDOS ; - B D O S -
-
- ld cl,#17 ;(11) search once
- ld dx,#FILE ;generic filename
- int BDOS ; - B D O S -
-
- ; Find the Nth file which fits the file description.
-
- FNTH: cmp al,#0FFH ;FF=search failed
- jz SCAN ;all relevant files located
- and al,#03 ;isolate quad
- ld ah,#32
- mulb ah
- ld bx,#0081H
- add bx,ax
- cmpb [bx+8],#'B'
- jnz NBAK
- cmpb [bx+9],#'A'
- jnz NBAK
- cmpb [bx+10],#'K'
- jz OMIT
- NBAK: cmpb [bx+8],#'$'
- jnz NDOL
- cmpb [bx+9],#'$'
- jnz NDOL
- cmpb [bx+10],#'$'
- jz OMIT
- NDOL: ld ah,#12
- mov dx,bx
- ld bx,DPTR ;directory pointer
- call MIUC
- sto bx,DPTR ;directory pointer
- incb DCTR ;directory counter
-
- OMIT: ld cl,#18 ;(12) search again
- ld dx,#FILE ;generic filename
- int BDOS ; - B D O S -
-
- jmp FNTH
-
- ; We're all done.
-
- DONE: ld bx,#DTOT ;'Disk Total'
- GBYE: call MSSG
- EXIT: ld dl,#00
- ld cl,#00
- int BDOS
-
- ; Now we are ready to scan the prospective files.
-
- SCAN: sto #DIRY,DPTR
- SCAM: decb DCTR
- jz DONE
- push DPTR
- add DPTR,#12
-
- ld ah,#8
- pop dx
- push dx
- ld bx,#KFIL+1 ;backup file (.BAK)
- call MIUC
-
- ld ah,#11
- pop dx
- push dx
- ld bx,#IFIL+1 ;input file (.EXT)
- call MIUC
-
- ld ah,#8
- pop dx
- push dx
- ld bx,#OFIL+1 ;output file (.$$$)
- call MIUC
-
- ld ah,#8
- pop dx
- push dx
- ld bx,#UFIL+1 ;active output (.$$$)
- call MIUC
-
- ld ah,#12
- pop dx
- ld bx,#TFCB+1 ;CP/M's file control block
- call MIUC
-
- ld cl,#19 ;(13) delete file
- ld dx,#KFIL ;backup file (.BAK)
- int BDOS ; - B D O S -
-
- ld cl,#19 ;(13) delete file
- ld dx,#OFIL ;output file (.$$$)
- int BDOS ; - B D O S -
-
- ld cl,#22 ;(16) create file
- ld dx,#UFIL ;active output (.$$$)
- int BDOS ; - B D O S -
- stob #0,UREC
-
- ld cl,#15 ;(0F) open file
- ld dx,#TFCB ;CP/M's FCB
- int BDOS ; - B D O S -
- inc al
- jnz STAY
- jmp EXIT ;quit [without message]
- STAY: stob #0,CBLK ;block pointer
-
- ld ah,#4
- ld dx,#LZER ;counter initializer
- ld bx,#LNUM ;'line number'
- call MIUC
-
- ld ah,#4
- ld dx,#LZER ;counter initializer
- ld bx,#FTOT ;'file total'
- call MIUC
-
- ld ah,#8
- ld dx,#TFCB+1 ;file name
- ld bx,#FNAM ;'file name'
- call MIUC
-
- ld ah,#3
- ld dx,#0065H ;extension
- ld bx,#FEXT ;'file extension'
- call MIUC
-
- ld bx,#FHED ;"File" header
- call MSSG ;message to console
-
- X01C2: sto #0000,ICTR ;input file counter
- sto #TSIZ,OCTR
- sto #UBUF,OPTR
- LOOP: ld bx,#LNUM+3 ;increment l.c.
- call INCO ;increment line counter
- ld bx,#LBUF ;line buffer
- ld ch,#0FFH
- MORL: inc ch
- js CRLF ;force a line after 80H columns
- push cx
- push bx
- call INCH ;char from big bffr to line bffr
- pop bx
- pop cx
- sto al,[bx]
- inc bx
- cmp al,#KZ
- jnz X01E8
- ld bx,#FTOT
- call MSSG
-
- ; Close out last, incomplete record.
-
- LARE: cmp OCTR,#0000
- jz CLOF
- ld al,#KZ
- call OUCH
- jmp LARE
-
- CLOF: ld cl,#21 ;(15) write one record
- ld dx,#UFIL ;active output (.$$$)
- int BDOS ; - B D O S -
-
- ld cl,#16 ;(10) close file
- ld dx,#UFIL ;active output (.$$$)
- int BDOS ; - B D O S -
-
- ld cl,#23 ;(17) rename file
- ld dx,#IFIL ;input file (.EXT)
- int BDOS ; - B D O S -
-
- ld cl,#23 ;(17) rename file
- ld dx,#OFIL ;output file (.$$$)
- int BDOS ; - B D O S -
-
- jmp SCAM
-
- X01E8: cmp al,#LF
- jnz MORL ;line not finished
- jmp IRRQ
-
- CRLF: stob #CR,[bx]
- inc bx
- stob #LF,[bx]
- inc bx
-
- ; Check console for termination request. If one
- ; is present, clear it out before leaving.
-
- IRRQ: stob #00,[bx] ;guarantee right hand fence
- ld cl,#11 ;(0B) console status
- int BDOS ; - B D O S -
- or al,al
- jz CULI
- ld cl,#1 ;(01) read console
- int BDOS ; - B D O S -
- ld bx,#M4 ;"search terminated"
- jmp GBYE
-
- ; Scan the current line.
-
- CULI: ld bx,#LBUF ;line buffer
- sto bx,ALFA ;begin good segment
- sto bx,BETA ;end good segment
- NEXB: ld dx,PAPO ;pattern pointer
- ld bx,BETA ;end good segment
- cmpb [bx],#CR
- jz NULI
- call CHEK
- jnz FAIL
- push dx
- push bx
- ld bx,#LNUM ;'line number'
- call MSSG
- ld bx,#LBUF
- call MSSG
- ld bx,#FTOT+3
- call INCO
- ld bx,#DTOT+3 ;'Disk Total'
- call INCO
- ld dx,BETA ;end good segment
- ld bx,ALFA ;begin good segment
- call OULI
- ld dx,SKND ;skeleton end
- ld bx,SKPO ;skeleton pointer
- call OULI
- pop bx
- sto bx,ALFA ;begin good segment
- dec bx
- sto bx,BETA ;end good segment
- pop dx
- FAIL: inc BETA ;end good segment
- jmp NEXB ;move scan up one byte
-
- NULI: ld dx,BETA ;end good segment
- inc dx
- inc dx
- ld bx,ALFA ;begin good segment
- call OULI
- jmp LOOP ;go for another line
-
- ; Increment ASCII counter at (HL-3).
-
- INCC: stob #'0',[bx]
- dec bx
- orb [bx],#30H
- INCO: incb [bx]
- cmpb [bx],#':'
- jz INCC
- ret
-
- ; Memory to console
-
- MSSG: ld dl,[bx]
- inc bx
- push bx
- ld cl,#2 ;(02) write console
- int BDOS ; - B D O S -
- pop bx
- cmpb [bx],#0
- jnz MSSG
- ret
-
- ; Read a character from the input buffer; if and when
- ; the buffer is empty, more sectors are brought in from
- ; the disk until an end-of-file is reached.
-
- INCH: cmp ICTR,#0000 ;input file counter
- jnz INCI
- call INDI ;disk to IN area
- INCI: dec ICTR ;input file counter
- ld bx,IPTR ;input file pointer
- ld al,[bx]
- cmp al,#KZ
- jz INCR
- inc IPTR ;input file pointer
- INCR: ret
-
- ; Bring in reinforcements from the disk.
-
- INDI: ld ch,#KSIZ
- sto #ISIZ,ICTR ;input file counter
- ld bx,#IBUF ;input file buffer
- sto bx,IPTR ;input file pointer
- INDD: stob #KZ,[bx]
- push bx
- push cx
-
- xchg bx,dx
- ld cl,#26 ;(1A) set DMA address
- int BDOS ; - B D O S -
-
- ld dx,#TFCB ;CP/M's file control block
- ld cl,#20 ;(14) read one record
- int BDOS ; - B D O S -
-
- pop cx
- pop bx
- or al,al
- jnz INDR
- dec ch
- jz INDR
- add bx,#TSIZ ;CP/M's record size
- jmp INDD
- INDR: ret
-
- ; Send a "line" [(HL) to (DE)] to out file
-
- OULJ: ld al,[bx]
- call OUCH
- inc bx
- OULI: cmp bx,dx
- jnz OULJ
- ret
-
- ; Send one character to the output file, conserve BC, HL
-
- OUCH: push dx
- push bx
- push ax
- cmp OCTR,#0000
- jnz OUCI
- call OUDI ;OUT area to disk
- OUCI: dec OCTR
- pop ax
- ld bx,OPTR
- sto al,[bx]
- inc OPTR
- pop bx
- pop dx
- ret
-
- ; Flush the buffer when it is full, make ready for next.
-
- OUDI: sto #OSIZ,OCTR
- sto #UBUF,OPTR
-
- ld cl,#26 ;(1A) set DMA address
- ld dx,#UBUF
- int BDOS ; - B D O S -
-
- ld cl,#21 ;(15) write one record
- ld dx,#UFIL ;active output (.$$$)
- int BDOS ; - B D O S -
-
- cmp al,#0
- jz OUDR
- ld bx,#M5
- jmp GBYE
- OUDR: ret
-
- ; Advance to next alternative
-
- NEXX: ld bx,[bx]
- NEXT: ld al,[bx]
- or al,al
- jz NEXR
- inc bx
- call ENDA
- jz NEXR
- call BEGB
- jz NEXX
- jmp NEXT
- NEXR: ret
-
- ; Move by Increment Until Count.
-
- MIUC: xchg bx,dx
- ld al,[bx]
- xchg bx,dx
- sto al,[bx]
- inc dx
- inc bx
- dec ah
- jnz MIUC
- ret
-
- ; Move and semi-compile the command line.
-
- MUVE: ld al,[bx]
- cmp al,#TAB
- jnz MUNT
- ld al,#HT
- MUNT: xchg bx,dx
- sto al,[bx]
- xchg bx,dx
- inc bx
- inc dx
- cmp al,#RBR
- jz MURB
- cmp al,#RSQ
- jz MURB
- cmp al,#LBR
- jz MULB
- cmp al,#LSQ
- jz MULB
- MUST: dec cl
- jnz MUVE
- ret
-
- MURB: mov ax,bx
- pop bx
- sto dx,[bx]
- mov bx,ax
- jmp MUST
-
- MULB: push dx
- inc dx
- inc dx
- jmp MUST
-
- ; Check balance of []'s and {}'s.
-
- BALA: push bx
- push cx
- ld cx,#0101H
- BALB: ld al,[bx]
- inc bx
- cmp al,#LSQ
- jnz BALC
- inc ch
- jmp BALB
- BALC: cmp al,#RSQ
- jnz BALD
- dec ch
- jz BADP
- jmp BALB
- BALD: cmp al,#LBR
- jnz BALE
- inc cl
- jmp BALB
- BALE: cmp al,#RBR
- jnz BALF
- dec cl
- jz BADP
- jmp BALB
- BALF: or al,al
- jnz BALB
- cmp cl,#01
- jnz BADP
- cmp ch,#01
- pop cx
- pop bx
- jnz BADP
- ret
-
- BADP: ld bx,#M3 ;"bad pattern"
- jmp GBYE
-
-
- ; Check for termination of alternative.
-
- ENDA: cmp al,#ORR
- jz ENDC
- cmp al,#RSQ
- jz ENDC
- cmp al,#RBR
- jz ENDC
- or al,al
- ENDC: ret
-
- ; Check for beginning of alternative.
-
- BEGA: cmp al,#ORR
- jz BEGC
- BEGB: cmp al,#LSQ
- jz BEGC
- cmp al,#LBR
- BEGC: ret
-
- ; Check for null alternative.
-
- NULA: push bx
- call NULC
- pop bx
- NULB: ret
- NULC: ld al,[bx]
- inc bx
- or al,al
- jz NULB
- call BEGA
- jnz NULC
- ld al,[bx]
- call ENDA
- jnz NULC
- jmp BADP
-
- ; Check for given expression.
-
- CHEK: ld ah,[bx]
- xchg bx,dx
- ld al,[bx]
- xchg bx,dx
- inc dx
- call ENDA
- jz CHNR
- cmp ah,#CR
- jz CHNO
- cmp al,#LBR
- jnz CHEL
- jmp CHLB
- CHEL: cmp al,#LSQ
- jz CHSQ
- ld cl,[bx]
- inc bx
- cmp al,#QUE
- jz CHEK
- cmp al,#ALF
- jz CHAL
- cmp al,ah
- jz CHEK
- cmp ah,#'a'
- jc CHNO
- cmp ah,#'{'
- jnc CHNO
- and ah,#05FH
- cmp al,ah
- jz CHEK
- CHNO: or al,#0FFH
- CHNR: ret
-
- ; Check alphanumeric.
-
- CHAL: mov al,cl
- cmp al,#'0'
- jc CHNO
- cmp al,#':'
- jc CHEK
- cmp al,#'A'
- jc CHNO
- cmp al,#'['
- jc CHEK
- cmp al,#'a'
- jc CHNO
- cmp al,#'{'
- jc CHEK
- jmp CHNO
-
- ; Check list of alternatives.
-
- CHSQ: push SQXX
- push SQAA
- push SQZZ
- sto bx,SQXX
- xchg bx,dx
- ld dx,[bx]
- inc bx
- inc bx
- sto bx,SQAA
- sto dx,SQZZ
- CHAA: ld bx,SQXX
- call CHEK
- jz CHFF
- CHBB: ld bx,SQAA ;fail so find next alternative
- CHCC: call NEXT
- cmp al,#RSQ
- jz CHDD ;no more alternatives, so fail
- cmp al,#ORR
- jnz CHCC
- sto bx,SQAA
- xchg bx,dx
- jmp CHAA ;try next alternative
- CHDD: ld bx,SQXX
- or al,#0FFH
- CHEE: pop SQZZ
- pop SQAA
- pop SQXX
- ret
- CHFF: ld dx,SQZZ ;good alternative, try rest
- call CHEK
- jz CHEE
- jmp CHBB
-
- ; Check iterative pattern.
-
- CHLB: push TEXT
- push TEXX
- push REST
- push REPT
- push REPP
- sto bx,TEXT
- sto bx,TEXX
- xchg bx,dx
- ld dx,[bx]
- inc bx
- inc bx
- sto bx,REPT
- sto bx,REPP
- sto dx,REST
- CHLC: ld dx,REST
- ld bx,TEXT
- call CHEK ;check rest
- jz CHZZ
- CHII: ld dx,REPT ;rest failed
- ld bx,TEXT ;keep same text
- call CHEK ;try out the repeater
- jnz CHOO
- sto bx,TEXT ;repeater worked, record progress
- ld bx,REPP ;start alternatives over again
- sto bx,REPT
- jmp CHLC
- CHOO: ld bx,REPT ;repeater failed, try next
- CHXX: call NEXT
- cmp al,#RBR
- jz CHYY ;this was the last, quit
- cmp al,#ORR
- jnz CHXX
- sto bx,REPT
- jmp CHII
- CHYY: ld bx,TEXX
- or al,#00 ;emphasize the RBR
- CHZZ: pop REPP
- pop REPT
- pop REST
- pop TEXX
- pop TEXT
- ret
-
- TUTO: db 'The command line',CR,LF
- db ' STUTE D:FILE.EXT PATTERN!SKELETON',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 PATTERN. Such lines will',CR,LF
- db 'be shown on the console preceded by a line number,',CR,LF
- db 'classified by file. Whenever the regular expression',CR,LF
- db 'PATTERN is found, it will be replaced by the constant',CR,LF
- db 'SKELETON. The PATTERN 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 'A general PATTERN must be used with extreme caution',CR,LF
- db 'because the same constant will replace it, whatever',CR,LF
- db 'its form. The PATTERN may not involve more than one',CR,LF
- db 'single line, but more than one instance of the PATTERN',CR,LF
- db 'may occupy the same line.',CR,LF
- db 00
-
- LOGO: db 'STUTE.CMD 16/NOV/83 ICUAP',CR,LF,00
-
- M3: db '-- Bad Pattern --',00
-
- M4: db CR,LF,'-- Substitution Terminated --',00
-
- M5: db CR,LF,'-- Disk or Directory Full --',00
-
- ; The following file control segments are arranged in just
- ; the form shown so that they will be properly paired for
- ; the renaming which has to be done after closing each file.
-
- ENTH: ds 1
- FILE: db 'DFilenameEXT',00,00,00,00 ;generic filename
- ds 16
- OFIL: db 'DFilename$$$',00,00,00,00 ;output file (.$$$)
- IFIL: db 'DFilenameEXT',00,00,00,00 ;input file (.EXT)
- KFIL: db 'DFilenameBAK',00,00,00,00 ;backup file (.BAK)
- UFIL: db 'Dfilename$$$',00,00,00,00 ;active output (.$$$)
- ds 16
- UREC: ds 1
- UBUF: ds 80H
- OPTR: ds 2
- OCTR: ds 2
-
- ; All the relevant files are located and noted before any
- ; substitutions are made, to avoid a newly created file
- ; being placed in the dictionary, being encountered again
- ; later on and then being processed a second time. The worst
- ; case would be to have to use all 64 files (minus one, for
- ; elbow room) in the directory, but that's not likely.
-
- DCTR: ds 1 ;directory counter
- DPTR: ds 2 ;directory pointer
- DIRY: ds 1024 ;directory of file names, if needed
-
- ; Temporary storage for the regular expression parser.
-
- SQXX: ds 2
- SQAA: ds 2
- SQZZ: ds 2
- TEXT: ds 2
- TEXX: ds 2
- REST: ds 2
- REPT: ds 2
- REPP: ds 2
-
- ; Scan pointers, buffers, headings and labels.
-
- ALFA: ds 2 ;begin good segment
- BETA: ds 2 ;end good segment
-
- PATT: ds 256 ;command line pattern
- PAPO: ds 2 ;pattern pointer
- SKPO: ds 2 ;skeleton pointer
- SKND: ds 2 ;skeleton end
- FHED: db '----> File ' ;"File" header
- FNAM: db 'xxxxxxxx.' ;filename
- FEXT: db 'xxx',CR,LF,00 ;file extension
- LNUM: db ' 0 ',00 ;'line number'
- LZER: db ' 0' ;counter initializer
- FTOT: db ' 0 substitutions made',CR,LF,00
- DTOT: db ' 0 instances in the entire disk',CR,LF,00
- db 00 ;fence for line buffer
- LBUF: ds 85H ;line buffer
- ICTR: ds 2 ;input file counter
- IPTR: ds 2 ;input file pointer
- IBUF: ds ISIZ ;input file buffer
- FINI: ds 0
-
- end
-