home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
commercial-software
/
programming
/
Z80TOOLS.ZIP
/
DISK1.ZIP
/
MODULES.ANT
< prev
next >
Wrap
Text File
|
1998-07-30
|
48KB
|
1,973 lines
name 'CHKOPS'
; CHKOPS: save command tail, check count of operands and
; check for "?" in first operand. Parameters are:
; reg B = min tokens allowed
; reg C = max tokens allowed
; DE-> usage message ending in $
; returns count of command tokens in reg. A.
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
maclib environ
dseg
usage dw 0 ; save ->message
cseg
public CHKOPS
entersub
CHKOPS:
push h ; save caller's HL
xchg
shld usage ; save ->message
savetail ; A = count of tokens
push psw ; ..save for exit
cmp b ; count :: min
jc quit ; (less than min)
ora a ; were there zero operands?
jz exit ; (yes, must be right number)
dcr a ; reduce count to force carry
cmp c ; ..on comparison to max
jnc quit ; (count > max)
mvi a,1 ; get DE->first token
tailtokn @A
xchg ; make that HL->token
mov a,m
cpi '?' ; does it start with "?"
jnz exit ; (nope)
inx h
mov a,m ; is it maybe "?xxx" or
ora a ; ..is it exactly ?,null
jnz exit ; (was "?xx...")
quit: lhld usage
xchg ; DE->abort-message
abort ,@D
exit: pop psw ; A = count of tokens
lhld usage ; restore
xchg ; ..caller's DE
pop h ; ..and HL
ret
end
rt ,@D
exit: pop psw ; A = count of tokens
lhld usage ; restor name 'OPENIN'
;
; OPENIN(operand-number,filedef) -- assign the specified command
; operand to the filedef and open it. Abort with one of three
; messages if problems arise:
;
; FRUMMAGE is not a valid filespec.
; FRUMMAGE is ambiguous; an explicit name is needed.
; FRUMMAGE is empty or does not exist.
;
; A = operand number to assign
; DE->filedef to use
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
maclib environ
dseg
is: strconst ' is '
inval: strconst 'not a valid filespec'
ambig: strconst 'ambiguous; an explicit name is needed'
empty: strconst 'empty or does not exist'
dotdol: strconst '.$'
msg: strspace 64
cseg
entersub
public OPENIN
OPENIN:
push psw
push b
push d
push h
xchg ; save ->file in HL
tailtokn @A ; DE->operand
xchg ; ok, HL->operand, DE->file
fassign @D,@H
lxi b,inval ; (set up for invalid)
jz error ; oops, not a valid filespec
cpi '?' ; was it ambiguous?
lxi b,ambig ; (prepare in case it was)
jz error ; (yes)
freset @D ; try to open it
lxi b,empty ; (but assume we can't)
jz error ; (we couldn't)
pop h
pop d
pop b
pop psw
ret
; Something went wrong, and BC->the details of why. Build
; an abort message and quit.
error:
; copy the operand to the message field first
lxi d,msg
strcopy @Dupdate,@Hupdate
; add the word " is "
lxi h,is
strappnd @Dupdate,@Hupdate
; then add the specific explanation
mov h,b ! mov l,c
strappnd @Dupdate,@Hupdate
; finish up with a period and a dollar sign
lxi h,dotdol
strappnd @Dupdate,@Hupdate
; that does it -- byebye
lxi d,msg
abort ,@D
end
and a dol name 'OPENUT'
;===============================================================
;
; OPENUT module
;
; Function OPENIN( A=operand number, DE->filedef)
; Acquire the given operand string and assign it to the filedef,
; then open the file for input. If problems, abort with one of
; three messages:
;
; FRUMMAGE is not a valid filespec.
; FRUMMAGE is ambiguous; an explicit name is needed.
; FRUMMAGE is empty or does not exist.
;
; Function OPENOU( A=operand, DE->filedef, BC->default filedef)
; As for OPENIN, but allows a default filedef, opens for output
; with frewrite and hence doesn't care if file is empty.
;
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
maclib environ
dseg
is: strconst ' is '
inval: strconst 'not a valid filespec'
ambig: strconst 'ambiguous; an explicit name is needed'
empty: strconst 'empty or does not exist'
dotdol: strconst '.$'
msg: strspace 64
cseg
entersub
public OPENIN
OPENIN:
push psw
push b
push d
push h
lxi b,0 ; no default filedef for input
call Assign ; assign & check the operand
freset @D ; try to open it
lxi b,empty ; (but assume we can't)
cz Error ; (we couldn't)
pop h
pop d
pop b
pop psw
ret
public OPENOU
OPENOU:
push psw
push b
push d
push h
call Assign ; try the assignment
frewrite @D ; and open for output
pop h
pop d
pop b
pop psw
ret
; Internal subroutine Assign(A=op#, DE->file, BC->dflt) --
; Attempt the assign of operand to file with default and
; abort if necessary.
Assign:
push d ; save ->file
tailtokn @A ; get DE->operand string
xchg ; and move to HL
pop d ; recover DE->file
fassign @D,@H,@B
lxi b,inval ; (set up for invalid)
cz Error ; oops, not a valid filespec
cpi '?' ; was it ambiguous?
lxi b,ambig ; (prepare in case it was)
cz Error ; (yes)
ret ; assigned ok...
; Internal subroutine Error(BC->submessage, HL->operand)
; Not really a subroutine because it always aborts and never
; returns -- construct an abort message including the operand
; string and abort the program.
Error:
; copy the operand to the message field first
lxi d,msg
strcopy @Dupdate,@Hupdate
; add the word " is "
lxi h,is
strappnd @Dupdate,@Hupdate
; then add the specific explanation
mov h,b ! mov l,c
strappnd @Dupdate,@Hupdate
; finish up with a period and a dollar sign
lxi h,dotdol
strappnd @Dupdate,@Hupdate
; that does it -- byebye
lxi d,msg
abort ,@D
end
and a dollar sign
lxi h,dotdol
name 'ANTINP'
;===============================================================
; copyin(DE=r): record r has been allocated to the current file
; and the AntSeq file is not at end of file. Read its next
; 128-byte record and write it to the anthology data file.
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
maclib environ
entersub
dseg
buffer: ds 128 ; buffer for data I/O
cseg
public ANTINP
ANTINP:
push psw
push b
push d
push h
push d ; save record number again
lxi d,AntSeq
lxi h,buffer
lxi b,128
fgetblok @D,@H,@B
lxi d,AntDat
pop h ; HL=record number
frecseek @D,@H ; seek to data record
lxi h,buffer
lxi b,128
fputblok @D,@H,@B
pop h
pop d
pop b
pop psw
ret
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
antname.ANX
AntDirY ds FcrLen ; directory copy name 'ANTOUT'
;===============================================================
; copyout(DE=r): record r is the next in sequence for the
; current output file. Read it from the data file and write it
; to the output file. If the seek operation returns Z true,
; meaning "seek to unwritten data," abort -- we're confused.
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
maclib environ
entersub
dseg
buffer: ds 128 ; buffer for data I/O
msgIC3: db 'Integrity check #3.$'
cseg
public ANTOUT
ANTOUT:
push psw
push b
push d
push h
xchg ; HL=record number
lxi d,AntDat
frecseek @D,@H
abort z,msgIC3
lxi h,buffer
lxi b,128
fgetblok @D,@H,@B
lxi d,AntSeq
lxi b,128
fputblok @D,@H,@B
pop h
pop d
pop b
pop psw
ret
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
antna name 'ANTFIN'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; find(DE->string): returns HL->FS entry or HL=zero
maclib environ
public ANTFIN
ANTFIN:
push psw
push b
lhld TopF
FINloop:
lxi b,FSlen
ora a ; clear carry
dsbc b ; HL->next lower FS entry
lbcd BotF ; is HL now lower than lowest?
dsbc b ; (carry is still clear)
jrc FINfail ; (yes, we tried them all)
dad b ; no, restore HL
strcmp @D,@H ; is this the wanted entry?
jrz FINhit ; (yes, stop)
jmp FINloop
FINfail: lxi h,0 ; return HL=0 for failure
FINhit: ; return HL->FS entry for success
pop b
pop psw
ret
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file i name 'ANTFRE'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; free(HL->FS entry): Find all record slots now owned by this
; file and disown them by putting -1 in each. Check that the
; number found agree with the size field, aborting if it does
; not.
;
; The marked slots are not added to Frecs at this time. They
; will be made officially free (zero) during the next Commit.
maclib environ
entersub
dseg
msgIC2: db 'Integrity check #2.$'
cseg
public ANTFRE
ANTFRE:
push psw
push b
push d
push h
lbcd TopR ; BC holds TopR for end-check
xchg ; DE contains ->FS as comparand
lxi h,0 ; count of found records...
push h ; ..is kept on top of stack
lhld Base ; HL scans array R
FREloop:
ora a
dsbc b ; TopR = HL?
jnc FREdone ; (yes, done)
dad b ; no, restore HL
mov a,m ! inx h ; A = low byte, HL->2nd byte
cmp e
jnz FREmiss ; (low-byte mismatch)
mov a,m
sub d ; (leave A=0 if equal)
jnz FREmiss ; (high-byte mismatch)
dcr a ; A = FFh
dcx h
mov m,a ; 1st byte = FF
inx h ; HL->2nd byte again
mov m,a ; record slot = -1 (FFFF)
xthl
inx h ; increment count of freed slots
xthl
FREmiss: inx h ; HL->next slot
jmp FREloop
; All in-use slots of R have been scanned. Those that were
; owned by the indicated file have been set to -1, and the count
; of such slots is on the stack. Make sure it's the same as the
; size field of the FS entry, and set that size to zero.
FREdone:
lxi h,FSsize
dad d ; HL-> size field
pop d ; DE=count
mov a,e
cmp m
jrnz FREugh
mvi m,0 ; zero low byte
inx h
mov a,d
cmp m
jrnz FREugh
mvi m,0 ; ..and high byte
pop h
pop d
pop b
pop psw
ret
FREugh: abort ,msgIC2
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
antname.ANX
AntDi name 'ANTADD'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; add(DE->string): returns HL->new FS entry initialized with
; the filename string -- or, if there are no free entries,
; aborts with "Directory space is full."
maclib environ
entersub
dseg
NoDir: db 'Directory space is full.$'
cseg
public ANTADD
ANTADD:
push psw
push b
lhld TopF
ADDloop:
lxi b,FSlen
ora a
dsbc b ; HL->next lower FS entry
push h ; (save that)
lbcd BotF
dsbc b ; off the bottom now?
pop h ; (recover ->next entry)
jrc ADDnew ; (yes, allocate a new name)
mov a,m ! ora a ; no, does HL->free entry (null)?
jrz ADDold ; (yes, reuse old name)
jmp ADDloop ; no, try another
; All allocated FS entries are in use. HL=BotF-16, which will
; do for a new entry provided it doesn't overlap TopR.
ADDnew:
lbcd TopR
push h
ora a
dsbc b ; compare HL vs. TopR
pop h
abort c,NoDir ; ..and quit if overlap.
shld BotF ; set the new BotF, extending array
mvi m,0 ; make new entry null
; HL->an available FS entry (contains a null string). Copy
; DE->string into it...
ADDold:
xchg ; append wants DE->target, HL->source
strappnd @D,@H
xchg ; recover HL->array entry
; ...and set its size word to zero
push h
lxi b,FSsize
dad b ; HL->size field
xra a
mov m,a ! inx h ; zero it
mov m,a
pop h
; Whatever we did, there is now one more active file entry.
lbcd AlFiles
inx b
sbcd AlFiles
pop b
pop psw
ret
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common name 'ANTND'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; nextdat(HL->FS entry, DE=last record number):
; Return the next record number after DE which is owned by
; HL->file. The caller is expected to know whether there IS a
; next record or not, so if there is not, we abort with an
; integrity check 1.
;
; We receive and return DE as an integer record number "r" from
; 1 to (TopR-Base)/2. Internally we deal with addresses of
; record slots, Base+2*r.
;
; Record numbers are origin-1 while the array is really origin-0
; so the slot indexed by DE on entry is Base+2*(DE-1). But we
; want to start with the NEXT slot, so we begin at Base+2*DE.
maclib environ
entersub
dseg
msgIC1: db 'Integrity check #1.$'
cseg
public ANTND
ANTND:
push psw
push b
push h ; save FS pointer
lhld Base
dad d ; Base + 2*DE gives...
dad d ; ...HL->next record slot
pop d ; DE=FS pointer to compare
lbcd TopR ; BC=limit address for checking
NDloop:
ora a
dsbc b ; has HL got up to TopR?
abort nc,msgIC1; (if so, somebody goofed)
dad b ; no, restore HL
mov a,m ! inx h
cmp e ; compare low bytes
mov a,m ; and set up for high ones
jnz NDmiss
cmp d
jz NDhit
NDmiss: inx h
jmp NDloop
; HL->2nd byte of the next record slot that names DE->FS entry.
; Convert HL into a record number as (HL-Base)/2 + 1.
NDhit:
dcx h ; back to 1st byte of word
lbcd Base
ora a
dsbc b ; (carry now clear, HL was >= BC)
rarr h ; 0 >> H >> carry
rarr l ; carry >> L >> carry
inx h ; make origin-1
xchg ; DE=record #, HL->FS entry
pop b
pop psw
ret
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
an name 'ANTNF'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; nextfree(HL->FS entry, DE=record number):
; Return the record number of the next FREE record slot after
; DE, and allocate it to HL=file address. If no free (zero)
; entries are found before TopR, create one by sliding TopR
; up, aborting if that overlaps BotF.
;
; See notes on index arithmetic in ANTND.
maclib environ
entersub
dseg
NoDat: db 'Data space is full.$'
cseg
public ANTNF
ANTNF:
push psw
push b
push h ; save FS pointer
lhld Base
dad d
dad d ; HL->next record slot
pop d ; DE=FS pointer to compare
lbcd TopR ; BC=limit of ever-used records
NFloop:
ora a
dsbc b ; has HL got up to TopR?
jnc NFnew ; (yes, make a new one)
dad b ; no, restore HL
mov a,m ! inx h
ora m ; is this slot zero?
jz NFold ; (yes, use it)
inx h ; no, step over it
jmp NFloop ; ..and continue
; BC=HL=TopR, and no zero entries were seen. If TopR+2 < BotF,
; increment TopR and use this slot. Otherwise abort.
NFnew:
inx b ! inx b ; new TopR, maybe
lhld BotF
dsbc b ; new TopR > BotF? (equal is ok)
abort c,NoDat ; (yes, array R is full)
sbcd TopR ; no, ok, store new TopR
mov h,b ! mov l,c ; and set up HL
dcx h ; ..to point to 2nd byte of slot
jmp NFboth
; We found a record entry that was previously used but is now
; free. We will use it, so decrement Frecs.
NFold:
lbcd Frecs
dcx b
sbcd Frecs
; HL->2nd byte of a record slot that is available. Store DE
; into it to claim ownership. Then convert the address into
; a record number: 1+(HL-Base)/2
NFboth:
mov m,d
dcx h
mov m,e
lbcd Base
ora a
dsbc b
rarr h
rarr l
inx h
xchg ; DE=record #, HL->FS entry
pop b
pop psw
ret
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; e name 'ANTSET'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; Setup(DE->usage message):
; Get the first command operand and use it to set up all three
; anthology filedefs in the common area with drivecode, filename
; and password, and their appropriate filetypes.
;
; If there is no first operand, or if it starts with "?," abort
; with the given usage message. Other messages:
;
; FRUMMAGE is not a valid anthology filespec
; FRUMMAGE is ambiguous; anthology spec must be explicit
maclib environ
entersub
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
; Reopen the common definition and assemble into it the filedefs
; of the anthology files.
common /ANTCOM/
org AntDat ; assemble filedefs into common
filedef 2048
org AntDirX
filedef 1024
org AntDirY
filedef 1024
org AntSeq
filedef 1024
dseg
tokens ds 1 ; save token-count for exit
usage ds 2 ; save ->usage message
string strspace 80 ; space to build abort-message
Ant: strconst 'ANT'
Anx: strconst 'ANX'
Any: strconst 'ANY'
inval:
strconst ' is not a valid anthology filespec.$'
ambig:
strconst ' is ambiguous; anthology spec must be explicit.$'
cseg
public ANTSET
ANTSET:
push b
push d
push h
xchg
shld usage
savetail
sta tokens
ora a ; any tokens at all?
jnz SET1 ; (yes, continue)
abusage: ; come here if token 1 is "?"
lhld usage
xchg
abort ,@D
SET1: mvi a,1
tailtokn @A
ldax d
cpi '?' ; a plea for help?
jrz abusage ; (yes, abort w/ usage msg)
; The first token is present and is not a question mark. Test
; it by assigning it to one file.
xchg ; HL->token 1
lxi d,AntDat
fassign @D,@H ; assign D:filename.typ;pass
lxi d,inval
jz abspec ; (bad filespec)
lxi d,ambig
cpi '?'
jz abspec ; (ambiguous spec)
; The first-token filespec is a valid one at least for the
; general case. Assign it to the other two files as well.
lxi d,AntDirX
fassign @D,@H
lxi d,AntDirY
fassign @D,@H
; Now force all three to have their correct filetypes, over-
; riding any filetype the user may have given.
typeonly equ 00100b ; no pass, do type, no name, no drive
lxi d,AntDat
lxi h,Ant
fassign @D,@H,,typeonly
lxi d,AntDirX
lxi h,Anx
fassign @D,@H,,typeonly
lxi d,AntDirY
lxi h,Any
fassign @D,@H,,typeonly
; That's that, the filedefs are ready to open.
lda Tokens
pop h
pop d
pop b
ret
; common routine to abort with a message composed of HL->string
; followed by DE->string.
abspec:
push d
lxi d,string
strcopy @D,@H
pop h
strappnd @D,@H
lxi d,string
abort ,@D
followed by DE->string.
abspec:
push d
lxi d,string
strcopy @ name 'ANTOPE'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; ANTOPEn: Open all three anthology files with freset. All must
; have some data in them (even a new, empty anthology has one
; data record and one record in each directory) -- so abort if
; they don't. (Note that the use of a device-name, e.g.
; "antdir con:," will result in this error because we append
; a filetype. The filespec "con:.anx" is a (nonexistent) disk
; file by toolkit rules.)
maclib environ
entersub
dseg
string: strspace 64 ; space for message
empty:
strconst ' is empty or nonexistent.$'
cseg
public ANTOPE
ANTOPE:
push psw
push b
push d
push h
lxi d,AntDat
freset @D
jz abempty
lxi d,AntDirX
freset @D
jz abempty
lxi d,AntDirY
freset @D
jz abempty
pop h
pop b
pop d
pop psw
ret
abempty:
lxi h,string
fgetspec @D,@H ; filespec to string area
xchg
lxi h,empty
strappnd @D,@H
abort ,@D
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
antname.ANX
A name 'ANTLOA'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; module ANTLOA
;
; Load a directory from disk into storage. Assumes that ANTPRE
; has done its work of assigning filespecs and opening files.
;
; In contrast to ANTSAV, this module does only the most gross
; validity checks. That is so that, if a directory is only
; slightly damaged, files can still be extracted from it. Any
; inconsistencies in the R and FS arrays will be trapped if
; and when ANTSAV is called to update the directory.
;
; Since ANTSAV writes a directory in two distinct parts (which
; may have overlapped in storage but are separate on disk) we
; must read it back in two distinct parts. However, we can
; read it from low to high in two simple block-reads.
;
; messages
; abort "Integrity check #9" invalid SizeX or SpanX
; history:
; initial code 8/1/84
;===============================================================
maclib environ
entersub
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R (128-multiple)
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS (ditto)
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
dseg
msgIC9 db 'Integrity check #9.$'
screen: msgfile
load1 strconst 'Loading directory...'
load2 strconst 'done'
cseg
public ANTLOA
ANTLOA:
push psw
push b
push d
push h
fputstr screen,load1
; fgetblok(ANX,significant numbers)
; if (SizeR+SizeF > SizeDir) then abort(#9)
lxi d,AntDirX
lxi b,AntHdrLen
lxi h,AntHdr
fgetblok @D,@H,@B
lhld SizeR
xchg
lhld SizeF
dad d
lxi b,SizeDir
ora a
dsbc b
jnc IC9 ; must be a garbage file
; Base := DSalloc(SizeDir)
; TopR := Base+SizeR
; TopF := Base+SizeDir
; BotF := TopF-SizeF
dslow @B
shld Base
xchg ; save Base in DE
lhld SizeR
dad d ; HL = Base+SizeR
shld TopR
mov h,b ! mov l,c
dad d ; HL = Base+SizeDir
shld TopF
xchg
lhld SizeF
xchg ; HL=TopF, DE=SizeF
ora a
dsbc d ; HL=TopF-SizeF
shld BotF
; seek(ANX,record #2)
; amount := SpanR*128
; start := Base
; getblock(ANX,start,amount)
; amount := SpanF*128
; start := TopF-SpanF*128
; getblock(ANX,start,amount)
lxi d,AntDirX
lxi h,2
frecseek @D,@H
lda SpanR ; both spans must be <256
ora a
rar ; 0 >> A >> carry
mov b,a
mvi a,0
rar ; carry >> A
mov c,a ; BC = SpanR*128
push b ; (save for integrity check)
lhld Base
; n.b. fgetblok handles the case of length=0 ok
fgetblok @D,@H,@B
pop h ; HL=count we asked for
ora a ; BC=count we got
dsbc b ; they better be the same,
jnz IC9 ; ..or something is very wrong
lda spanF
ora a
rar
mov b,a
mvi a,0
rar
mov c,a ; BC=count of bytes to get
push b ; (save)
ora a
lhld TopF
dsbc b ; HL->where it goes
fgetblok @D,@H,@B
pop h ; count we asked for
ora a
dsbc b ; ..versus what we got
jnz IC9
; for j := 1 to MaxR do
; if (R[r] <> 0) then {should be filepointer}
; R[r] := TopF - R[r]
; endif
; end for
; This loop's purpose is to convert file-pointers from relative
; back to absolute addresses. In it we could validity-check
; the pointers. But any corruption that makes a pointer
; invalid must lead to integrity check #1 or #3 during ANTGET
; or #2 during ANTERA or #4, #5, or #6 during the next ANTSAV,
; so why gild the lily?
lhld Base
Ldloop:
lbcd TopR
ora a
dsbc b
jnc Lddone
dad b
mov c,m ! inx h
mov b,m ; BC=R[r], HL->2nd byte of it
mov a,b ! ora c
jrz Ldstep ; R[r]=0=free slot
xchg
lhld TopF
dsbc b
xchg ; DE = TopF - R[r]
mov m,d ! dcx h
mov m,e ! inx h
Ldstep: inx h
jmp Ldloop
Lddone:
fputline screen,load2
pop h
pop d
pop b
pop psw
ret
IC9: abort ,msgIC9
end
: inx h
jmp Ldloop
Lddone:
fputline screen,load2
pop h
pop d
pop b
pop psw
ret
name 'ANTSAV'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
; module ANTSAV
;
; Contains the logic needed to commit the anthology directory
; to disk, including validation of its consistency and writing
; it in such a way that a crash for disk-full will leave the
; original directory unaltered.
;
; messages
; abort "Integrity check #4" record owned by non-file
; abort "Integrity check #5" Frecs <> free records
; abort "Integrity check #6" file size incorrect
; abort "Integrity check #7" AlFiles <> in-use files
; abort "Integrity check #8" error in size arithmetic
;
; History:
; initial code 8/1/84
;===============================================================
maclib environ
entersub
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R (128-multiple)
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS (ditto)
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
dseg
msgIC4 db 'Integrity check #4.$'
msgIC5 db 'Integrity check #5.$'
msgIC6 db 'Integrity check #6.$'
msgIC7 db 'Integrity check #7.$'
msgIC8 db 'Integrity check #8.$'
screen: msgfile
save1 strconst 'Saving directory...'
save2 strconst 'done'
cseg
public ANTSAV
ANTSAV:
push psw
push b
push d
push h
fputstr screen,save1
call commit
call update
fputline screen,save2
pop psw
pop b
pop d
pop h
ret
;===============================================================
; Commit: sweep over the array R, doing these things:
;
; 1. convert conditional-free records (-1) to free (0)
; and add them to the Frecs count of free records.
;
; 2. count the free records and verify Frecs.
;
; 3. verify that un-free (nonzero) records contain valid
; file-pointers -- multiples of 16 and in the correct
; range -- which point to active files.
;
; 4. tally the records owned by each file in a temporary
; word in the file's FS entry.
;
; 5. convert record file-pointers to relative form.
;
; Then sweep over the array FS, doing these things:
;
; 1. count active (non-null) entries and verify AlFiles.
;
; 2. verify that each file's tally of records agrees with
; its size, and clean up the temporary count.
;
; Afterward the directory is known to be self-consistent and is
; in condition to be written to disk.
;
; We need one word per file to tally the records that point to
; each file. The FS entry is laid out this way:
;
; F I L E N A M E . T Y P 00 xx SS SS
;
; where SS SS is the size-word and xx is unused. Since xx will
; always be preceded by 00 ending the string, or by an unused
; byte, we keep the tally in the "00 xx" bytes. On the last
; sweep we replace it with "00 00" to restore the terminal null
; to any full-length string.
Commit:
; for j := 1 to MaxF do
; T[j] := 0
; end for
lhld TopF
lxi d,-4
dad d ; HL->"T" field in top entry
lxi d,-17 ; DE = decrement value
lbcd BotF ; BC = bottom limit for check
xra a ; A = constant zero
C1loop:
ora a
dsbc b ; while HL > BC
jrc C1loopz
dad b ; (restore HL)
mov m,a
inx h
mov m,a ; T := 0000
dad d ; HL->next lower entry's "T"
jmp C1loop
C1loopz:
; nfr := 0
; for j := 1 to MaxR do
; if (R[j] = -1) then {conditional free}
; R[j] := 0
; Frecs := Frecs+1
; nfr := nfr + 1
; else if (R[j] = 0) then {actually free}
; nfr := nfr + 1
; else {not free}
; f := R[j]
; if (f is valid) and (F[f] is active) then
; R[j] := TopF - f
; T[f] := T[f]+1
; else
; abort("Integrity Check #4")
; endif
; endif
; end for
; if (nfr <> Frecs) then abort("Integrity check #5")
dseg
nfr ds 2
cseg
lxi h,0
shld nfr
lhld Base
C2loop:
lbcd TopR ; while HL < TopR
ora a
dsbc b
jnc C2loopz
dad b
mov e,m
inx h
mov d,m ; DE = R[j]
mov a,d ! ora e
jz C2free ; case of R[j]=0 is easy to spot
inx d ; if DE+1 = 0, we have R[j]=-1
mov a,d ! ora e
dcx d ; assuming not, restore DE
jnz C2inuse
dcx h
mov m,a ; (A now is 00)
inx h
mov m,a ; now R[j] = 0
lbcd Frecs
inx b
sbcd Frecs ; count the now-free slot
C2free: lbcd nfr
inx b
sbcd nfr ; count the free slot
inx h ; HL->next slot
jmp C2loop ; continue loop from here
C2inuse:
push d ; save contents of R[j] = f
push h ; save ->2nd byte of R[j]
; that pointer f should be => BotF
lhld BotF
dcx h ; f should be > HL = BotF-1
ora a
dsbc d ; HL = (BotF-1) - f
jnc IC4
; ..and less than TopF
lhld TopF
ora a
dsbc d ; HL=TopF - f
jc IC4
jz IC4
; ..and a multiple of 16
mov a,l
ani 0fh
jnz IC4
; R[j]=f is a valid pointer to an entry of FS and HL=TopF-f
xchg ; DE=TopF - f
pop h ; HL->2nd byte of R[j]
mov m,d
dcx h
mov m,e ; R[j] := TopF - f
inx h ! inx h ; HL->next slot
xthl ; HL->FS[f], ->next slot on stack
mov a,m ; is F[f] active?
ora a ; (not null string if so)
jz IC4
lxi d,FSsize-2
dad d ; HL->T[f]
inr m ; increment low byte
jnz C2pop ; (no overflow to 2nd byte)
inx h
inr m ; (propogate to 2nd byte)
C2pop: pop h ; HL->next record slot
jmp C2loop
; one of the checks on the value of R[j] failed.
IC4: abort ,msgIC4
C2loopz:
lhld nfr
xchg
lhld Frecs
ora a
dsbc d
abort nz,msgIC5
dseg
naf equ nfr ; reuse the scratch word
cseg
; naf := 0
; for j := 1 to MaxF do
; if (F[j] is not null) then
; naf := naf + 1
; if (T[j] <> S[j]) then
; abort("Integrity check #6")
; endif
; end for
; if (naf <> AlFiles) then abort("Integrity check #7")
lxi h,0
shld naf
lhld BotF ; just for variety, go from low to hi
C3loop:
lbcd TopF
ora a ; while BC > HL
dsbc b
jnc C3loopz
dad b
mov a,m ; does HL->non-null string?
ora a
jnz C3inuse ; (yes)
lxi d,FSlen
dad d ; no, advance to next
jmp C3loop ; ..and iterate
C3inuse:
lded naf
inx d
sded naf ; count active file
lxi d,FSsize-2
dad d ; HL->T[j]
xra a
mov e,m
mov m,a ; pick it up and zero it
inx h
mov d,m
mov m,a
inx h ; HL->S[j], DE=T[j]
mov c,m
inx h
mov b,m ; BC = S[j]
inx h ; ..and HL->next entry
xchg
dsbc b ; compare S[j] :: T[j]
xchg
jz C3loop
abort ,msgIC6
C3loopz:
lhld naf
xchg
lhld AlFiles
ora a
dsbc d
rz
abort ,msgIC7
;===============================================================
; update: the directory has been modified in storage, and Commit
; has validated it and made file-addresses relocatable. Now we
; write it to disk updating the files .ANX and .ANY. We write
; from last record to first so that, if CP/M aborts us for a
; full disk, it will do so before we change the existing files.
dseg
recno ds 2
cseg
update:
; SizeR := TopR-Base
; if (SizeR < 0) then abort("Integrity check #8")
; SpanR := (SizeR+127)/128
;
; SizeF := TopF-BotF
; if (SizeF < 0) then abort("Integrity check #8")
; SpanF := (SizeF+127)/128
; { number of records in directory is also recno of
; the last record, which will be the first written}
; recno := SpanR + SpanF + 1
lhld Base
xchg
lhld TopR
ora a
dsbc d ; HL = TopR-Base
jm IC8 ; (oops)
shld SizeR
lxi b,127
dad b ; HL = SizeR+127
dad h ; ..shifted left once
mov l,h
mvi h,0 ; ..shifted right 8 times
shld SpanR
lhld BotF
xchg
lhld TopF
ora a
dsbc d ; HL = TopF-BotF
jm IC8 ; (oops)
shld SizeF
dad b ; ...+127
dad h ; ..shift left
mov l,h
mvi h,0 ; ..and right by 8
shld SpanF
xchg
lhld SpanR
dad d ; HL = SpanF+SpanR
inx h ; ..+1
shld recno ; record number to write first/next
; j := SpanF
; ptr := TopF
; while ( j > 0 ) do
; ptr := ptr-128
; seek(ANX,recno)
; putblock(ANX,ptr,128)
; seek(ANY,recno)
; putblock(ANY,ptr,128)
; recno := recno-1
; j := j-1
; end while
lda SpanF ; has to be less than 256
mov b,a ; ..so carry loop count in B
lhld TopF ; set HL=byte above 1st record
ora a ; any records in this segment?
cnz WRloop ; ..if so, write B records from HL down
; j := SpanR
; ptr := Base+(SpanR*128)
; while ( j > 0 ) do
; {same loop as above}
; end while
lda SpanR
mov b,a
ora a ; clear carry
rar ; 0 >> A >> carry
mov d,a ; high 7 bits to D
mvi a,0
rar ; carry >> A
mov e,a ; DE = SpanR * 128
lhld Base
dad d ; HL = Base+(SpanR*128)
mov a,b ; now, are there any records?
ora a
cnz WRloop ; ..if so, write them
; frewind(ANX)
; putblock(ANX,significant numbers)
; fclose(ANX)
; frewind(ANY)
; putblock(ANY,significant numbers)
; fclose(ANY)
; fclose(ANT)
lxi h,AntHdr
lxi b,AntHdrLen
lxi d,AntDirX
frewind @D
fputblok @D,@H,@B
fclose @D
lxi d,AntDirY
frewind @D
fputblok @D,@H,@B
fclose @D
lxi d,AntDat
fclose @D
ret
; somehow, TopR is less than Base or TopF is less than BotF
IC8: abort ,msgIC8
; the identical bodies of the above two loops, factored out
WRloop:
lxi d,-128
dad d ; HL->next lower record to write
lxi d,AntDirX
push h ; (save ptr)
lhld recno
frecseek @D,@H
pop h
fputblok @D,@H,128
lxi d,AntDirY
push h
lhld recno
dcx h ; (insert recno := recno-1)
shld recno
inx h
frecseek @D,@H
pop h
fputblok @D,@H,128
djnz WRloop
ret
end
name 'ANTMRK'
; Copyright (C) 1985 M&T Publishing Co. all rights reserved
;===============================================================
;
; module ANTMRK
;
; This module provides essential services to ANTGET, ANTDIR,
; and ANTERA. The ANTMRK routine takes an operand token,
; assigns it to AntSeq, and marks every file in the directory
; that matches that (possibly ambiguous) filespec.
;
; The ANTNMK (nextmark) returns the next marked directory entry
; following the one it is passed.
;
; messages (aborts)
; FRUMMAGE is not a valid filespec
; Integrity check #10 (improper use of ANTNMK)
;
; History
; initial code 8/4/84
;===============================================================
maclib environ
common /ANTCOM/
; This common area definition is included in all, or most
; anthology programs. It defines the directory in storage.
; The filedefs are assembled in module ANTSUP.
AntHdr equ $ ; following words precede directory
SizeR ds 2 ; size of array R (128-multiple)
SpanR ds 2 ; # of 128-byte records over R
SizeF ds 2 ; size of array FS (ditto)
SpanF ds 2 ; # of 128-byte records over FS
AlFiles ds 2 ; count of allocated files
Frecs ds 2 ; count of free records
AntHdrLen equ $-AntHdr ; bytes written at head of file
Base ds 2 ; ->base of dir. (array R)
TopR ds 2 ; ->low free byte
BotF ds 2 ; ->bottom byte of FS
TopF ds 2 ; ->byte after directory
SizeDir equ 16384 ; in-core size of directory
FSsize equ 14 ; offset to size in FS entry
FSlen equ 16 ; size of an FS entry
AntDat ds FcrLen ; data file antname.ANT
AntDirX ds FcrLen ; directory copy antname.ANX
AntDirY ds FcrLen ; directory copy antname.ANY
AntSeq ds FcrLen ; sequential file in/out
cseg ; end of common
dseg
ngspec: db ' is not a valid filespec.$'
IC10: db 'Integrity check #10.$'
msg strspace 50
cseg
entersub
;===============================================================
; mark(DE->operand) returns HL=count
;
; Assign the operand to AntSeq; then extract its filename.typ
; string. Compare to every directory entry and mark the ones
; that match. The mark is to set the high bit in the first byte
; of the filename (cleared in ANTNMK).
public ANTMRK
ANTMRK:
push psw
push b
push d
xchg
lxi d,AntSeq
fassign @D,@H
jnz okspec
lxi d,msg
strcopy @D,@Hupdate
lxi h,ngspec
strappnd @D,@Hupdate
abort ,@D
okspec:
lxi h,msg ; string-space for filename.typ
fgetspec @D,@H,0110b ; name, type not drive or pass
lhld TopF ; work our way down from old to new
lxi b,0 ; BC counts matches
AMloop:
lxi d,-FSlen
dad d ; HL->next file down
lded BotF
ora a
dsbc d ; or is it off the end?
jc AMloopz ; (yes, done)
dad d ; no, restore HL
lxi d,msg ; DE->comparand
call compare
jnz AMloop
mov a,m
ori 80h ; mark the file
mov m,a
inx b ; count match
jmp AMloop
AMloopz:
mov h,b ! mov l,c
pop d
pop b
pop psw
ret
; Compare DE->"XYZ???.???" versus HL->filename string in F.
; The rule is, "?" matches anything except dot and null. When
; we find a "?" versus a dot or null, we skip over the ?s
; to a non-?.
Compare:
push d
push h
mov a,m ! ora a ; a null directory entry matches nothing
jnz Comp2 ; (HL->live entry)
inr a ; ..and this is null, set Z false
jmp Compdone
Comp2: ldax d ! ora a ; a null comparand matches everything
jz Compdone
Comploop:
ldax d ; compare current bytes
cmp m
jnz CompNE ; not equal, check for "?"
; current bytes equal, are we at end of both strings?
ora a
jz Compdone ; yes, end with a match
; current bytes are considered equal but are not at the end.
; step to next bytes and try again.
CompStep:
inx d
inx h
jmp Comploop
; current bytes are not equal. If the comparand byte isn't
; a "?" we have a definite mismatch.
CompNE:
cpi '?'
jnz Compdone
; The comparand is "?" -- if the compared byte is neither a dot
; nor the null at the end, consider them equal.
mov a,m
ora a
jz Compdelim
cpi '.'
jnz CompStep
; We have "?..." versus a delimiter. Step over the ?s to a
; non-? and go back to compare it to the delimiter.
Compdelim:
inx d
ldax d
cpi '?'
jrz Compdelim
jmp Comploop
; The comparison is over and the Z flag reflects the result.
Compdone:
pop h
pop d
ret
;===============================================================
; nextmark(HL->F[f]) returns HL->F[f]. Scan down the directory
; for the next marked entry, clear its mark, and return its
; address. We should not be called when there is no next mark.
public ANTNMK
ANTNMK:
push psw
push d
NMloop:
lxi d,-FSlen
dad d ; HL->next file back
lded BotF
ora a
dsbc d ; is there one?
abort c,IC10 ; (there better be)
dad d ; yes, restore HL
mov a,m ! ora a ; is this one marked?
jp NMloop ; (no)
ani 7Fh ; yes, clear the mark
mov m,a
pop d
pop psw
ret
end
! ora a ; is this one marked?
jp NMloop ; (no)