home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
sigm
/
vol165
/
stute.asm
< prev
next >
Wrap
Assembly Source File
|
1984-07-08
|
14KB
|
928 lines
; ----------------------------------------------------------
; 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. 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. STUTE.ASM
; differs from FIND in that the patterns found are replaced
; by a constant rather than just being located.
;
; STUTE.ASM Copyright (C) 1983
; Universidad Autonoma de Puebla
;
; [Harold V. McIntosh, 28 February 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
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
osiz equ 128
; -------------
org 0100H
; -------------
begn: lxi h,0000
dad sp
shld stak
lxi sp,stak
lda cfcb+1 ;file name
cpi ' '
jnz X0143
lxi h,tuto ;tutorial message
call mssg
jmp gbye
X0143: lxi h,logo ;identification line
call mssg
mvi c,12
lxi d,cfcb ;CP/M's FCB
lxi h,file ;generic filename
call miuc
lda file ;generic filename
sta kfil ;backup file (.BAK)
sta ifil ;input file (.EXT)
sta ofil ;output file (.$$$)
sta ufil ;active output (.$$$)
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
xchg
dcx h
shld sund
mvi c,4
lxi d,lzer
lxi h,dtot
call miuc
lxi h,patt ;command line pattern
shld papo
call next
shld supo ;substitute pointer
; Scan the directory for file names.
prep: xra a
inr a
sta dctr ;directory counter
lxi h,diry ;directory extract
shld dptr ;directory pointer
push h
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 ;generic filename
call 0005 ; - B D O S -
fnth: pop h
inr a
jz scan ;all relevant files located
push h
dcr a
ani 03
add a
add a
add a
add a
add a
adi 81H
mov e,a
mvi d,00
lxi h,8
dad d
push h
mov a,m
cpi 'B'
jnz nbak
inx h
mov a,m
cpi 'A'
jnz nbak
inx h
mov a,m
cpi 'K'
pop h
jz omit
jmp nbac
nbak: pop h
nbac: mvi a,'$'
cmp m
jnz ndol
inx h
cmp m
jnz ndol
inx h
cmp m
jz omit
ndol: mvi c,12
pop h
call miuc
push h
lxi h,dctr ;directory counter
inr m
omit: mvi c,18 ;(12) search again
lxi d,file ;generic filename
call 0005 ; - B D O S -
jmp fnth
; We're all done.
done: lxi h,dtot
call mssg
gbye: lhld stak
sphl
ret
; A prospective file has been located
scan: lxi h,dctr
dcr m
jz done
lhld dptr
xchg
lxi h,12
dad d
shld dptr
push d
mvi c,8
pop d
push d
lxi h,kfil+1 ;backup file (.BAK)
call miuc
mvi c,11
pop d
push d
lxi h,ifil+1 ;input file (.EXT)
call miuc
mvi c,8
pop d
push d
lxi h,ofil+1 ;output file (.$$$)
call miuc
mvi c,8
pop d
push d
lxi h,ufil+1 ;active output (.$$$)
call miuc
mvi c,12
pop d
lxi h,cfcb+1 ;CP/M's file control block
call miuc
mvi c,19 ;(13) delete file
lxi d,kfil ;backup file (.BAK)
call 0005 ; - B D O S -
mvi c,19 ;(13) delete file
lxi d,ofil ;output file (.$$$)
call 0005 ; - B D O S -
mvi c,22 ;(16) create file
lxi d,ufil ;active output (.$$$)
call 0005 ; - B D O S -
mvi a,00
sta urec
mvi c,15 ;(0F) open file
lxi d,cfcb ;CP/M's FCB
call 0005 ; - B D O S -
inr a
jz gbye ;quit [without message]
xra a
sta cblk ;block pointer
mvi c,4
lxi d,lzer
lxi h,lnum ;'line number'
call miuc
mvi c,4
lxi d,lzer
lxi h,ftot ;'file total'
call miuc
mvi c,8
lxi d,cfcb+1 ;file name
lxi h,fnam ;'file name'
call miuc
mvi c,3
lxi d,0065H ;extension
lxi h,fext ;'file extension'
call miuc
lxi h,fhed
call mssg ;message to console
lxi b,2006H ;six spaces
lxi h,llbl
call fiuc ;fill until count
X01C2: lxi h,0000
shld ictr
lxi h,0080H
shld octr
lxi h,ubuf
shld optr
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
; Close out last, incomplete record.
lare: lhld octr
mov a,h
ora l
jz clof
mvi a,1AH
call ouch
jmp lare
clof: mvi c,21 ;(15) write one record
lxi d,ufil ;active output (.$$$)
call 0005 ; - B D O S -
mvi c,16 ;(10) close file
lxi d,ufil ;active output (.$$$)
call 0005 ; - B D O S -
mvi c,23 ;(17) rename file
lxi d,ifil ;input file (.EXT)
call 0005 ; - B D O S -
mvi c,23 ;(17) rename file
lxi d,ofil ;output file (.$$$)
call 0005 ; - B D O S -
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 D O S -
ora a
jz culi
mvi c,1 ;(01) read console
call 0005 ; - B D O S -
lxi h,M4 ;"search terminated"
call mssg
jmp gbye
; Scan the current line.
culi: lxi h,lbuf ;line buffer
shld alfa
shld beta
X021A: lhld papo ;substitute pointer
xchg
lhld beta
mov a,m
cpi CR
jz nuli
call chek
jnz fail
push d
push h
lxi h,llbl
call mssg
lxi h,lbuf
call mssg
lxi h,ftot+3
call inco
lxi h,dtot+3
call inco
lhld beta
xchg
lhld alfa
call ouli
lhld sund
xchg
lhld supo
call ouli
pop h
shld alfa
dcx h
shld beta
pop d
fail: lhld beta
inx h
shld beta
jmp X021A
nuli: lhld beta
inx h
inx h
xchg
lhld alfa
call ouli
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 D O S -
pop h
mov a,m
ora a
jnz mssg
ret
X029C: lxi h,M3 ;"bad pattern"
call mssg
jmp gbye
inch: lhld ictr
mov a,h
ora l
cz indi ;disk to IN area
lhld ictr
dcx h
shld ictr
lhld iptr
mov a,m
cpi KZ
rz
inx h
shld iptr
ret
indi: mvi b,ksiz
lxi h,isiz
shld ictr
lxi h,ibuf
shld iptr
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
; Send a "line" [(HL) to (DE)] to out file
ouli: mov a,e
sub l
mov c,a
mov a,d
sbb h
mov b,a
oulj: mov a,b
ora c
rz
mov a,m
call ouch
dcx b
inx h
jmp oulj
; Send one character to the output file, conserve BC, HL
ouch: push b
push h
push psw
lhld octr
mov a,h
ora l
cz oudi ;OUT area to disk
lhld octr
dcx h
shld octr
pop psw
lhld optr
mov m,a
inx h
shld optr
pop h
pop b
ret
oudi: lxi h,osiz
shld octr
lxi h,ubuf
shld optr
xchg
mvi c,26 ;(1A) set DMA address
call 0005 ; - B D O S -
lxi d,ufil ;active output (.$$$)
mvi c,21 ;(15) write one record
call 0005 ; - B D O S -
ora 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
; Fill (with B) until count (C).
fiuc: mov m,b
inx h
dcr c
jnz fiuc
ret
miuc: ldax d
mov m,a
inx d
inx h
dcr c
jnz miuc
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"
call mssg
jmp gbye ;PDL unbalanced but doesn't matter
; 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
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.COM 28/FEB/83 ICUAP',CR,LF,00
M3: db '-- Bad Pattern --',00
M4: db CR,LF,'-- Substitution Terminated --',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.
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
alfa: ds 2
beta: ds 2
patt: ds 256 ;command line pattern
ds 100 ;stack area
stak: ds 2 ;initialize stack pointer
papo: ds 2 ;pattern pointer
supo: ds 2 ;substitute pointer
sund: ds 2
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
ictr: ds 2
iptr: ds 2
ibuf: ds isiz
fini: ds 0
end