1
0
Fork 0
qterm/source/CF.Z

859 lines
19 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; cf.z - creeping featurism (i.e. file operations in chat scripts)
; plus stuff to look after numbers in chat scripts
.incl "c:vars"
; stest - compare two strings !% = .s1.s2. `label jump if equal
; !% _ .s1.s2. `label jump if equal case insens.
; !% # .s1.s2. `label jump if not equal
.extern stest
stest: xor a
ld (casefl),a
call areabp
cp '#'
jr z,ckseq ; '#' for inequality
xor '='
jr z,ckseq ; '=' for equality
ld (casefl),a ; set case flag true
xor '_' ^ '=' ; '_' for equality case insensitive
ret nz
ckseq: or a ; z equality, nz inequality
push af ; save test value
call incbyp ; step up to strings
push hl
ld hl,work2
ld de,work2 + 1
ld bc,255
ld (hl),b
ldir ; clear space where strings will live
pop hl
or a
jr z,testzz
ld de,work2 + 1
ld b,2
seqslp: push bc
call scanst ; scan a string
inc de
pop bc
jr c,testzz ; exit if end of input
djnz seqslp ; otherwise loop till both read
inc hl ; skip trailing terminator
push hl ; save input pointer
ld hl,work2 + 1
ld de,work2 + 42 ; get the two strings
csl: ld b,0x7f
call cmptst ; check a characters
jr nz,phltz ; different, so finish test operation
ld a,(hl)
or a ; end of string?
jr z,phltz ; yes - finish test this way too
inc hl
inc de ; next chars .....
jr csl
; the !~ creeping featurism entry
.extern cf
cf:
call areabu ; what's wanted?
inc hl
cp '-'
jr z,cf_era ; '-' erases
cp '='
jr z,cf_ren
cp '+'
jr z,cf_copy ; '+' copies
cp 'Y'
jr z,cf_filq ; 'Y' file query: jump if file exists
xor 'N'
ret nz ; 'N' file query: jump if file doesn't exist
; fall into file query routine
; file query: check see if a file exists or not, and then jump to a label if
; it does.
cf_filq:
or a ; z for 'N', nz for 'Y'
push af
call scnfcb ; get a fcb
ld de,fcb
ld c,open ; try to open it - note that this will also
; work with wildcards
push hl
call usrbds ; open
inc a
phltz: pop hl
testzz: jr z,nofil ; not there - do test one way round
pop af ; 'Y' / 'N' result back
ret z ; 'N' and file exists => no skip
jr dskp1 ; 'Y' and file => skip
nofil: pop af ; no file .....
ret nz ; 'Y' and no file => no skip
dskp1: jp doskip ; go skip to the new line
; rename: du: is taken from the first name - a1:x = b7:y will rename a1:y
cf_ren: call gettwo
ret c ; exit on an error
ld hl,(auxfcb)
ld (fcb),hl ; xfer drive / user info
ld de,fcb
ld c,open
call usrbds ; open
inc a
ret z ; not there - exit
ld a,(fcb + 10)
add a,a
ret c ; if it's R/O stop now
ld de,auxfcb
ld c,open
call usrbds ; open
inc a
ret nz ; replacement _IS_ there - so exit
ld hl,auxfcb + 1
ld de,fcb + 17
ld bc,16
ldir ; shift stuff for rename
ld de,fcb
ld c,rename
jp usrbds ; go do it
; erase subroutine: no wildcards, single file erase
cf_era: call scnfcb
ret z ; no wildcards allowed
ld de,fcb
ld c,open
call usrbds ; open the file
ld a,(fcb + 10)
add a,a
ret c ; if it's R/O stop now
ld de,fcb
ld c,erase
jp usrbds ; otherwise erase it
; copy file routine
cf_copy:
call gettwo ; get two fcb's - one to fcb, one to auxfcb
ret c ; exit on an error
ld de,fcb
ld c,open
call usrbds ; open file1
inc a
ret z ; not there: exit
ld de,auxfcb
ld c,open
call usrbds ; open file2
inc a
ret nz ; is there: exit
ld de,auxfcb
ld c,create
call usrbds ; create file2
inc a
ret z ; create failed: exit
ld de,xbuff
ld c,setdma
call bdos ; set dma address
cplp: ld de,fcb
ld c,read
call usrbds ; read a sector
or a
jr nz,copied ; all done
ld de,auxfcb
ld c,write
call usrbds ; write it back
or a
jr z,cplp ; exit if write failed
copied: ld de,auxfcb
ld c,close
jp usrbds ; close output file
; parse two filenames, separated by an '=' sign
gettwo: call scnfcb ; get one
scf
ret z ; exit w/ carry if wildcards
call byp
cp '=' ; need an '='
scf
ret nz ; not there: exit
push hl
call xferax ; shift it to auxfcb
pop hl
inc hl
call scnfcb ; get a second
scf
ret z ; exit with carry on an error
or a
ret ; else clear carry for OK
; !@ evaluation subroutine
.extern eval
eval:
call areabu ; set to read the string
sub 'A' ; get the variable number
cp 26
jr nc,eerr0 ; not legal, exit now
call ivar
push de ; save it's address
inc hl
call scan ; scan a term
jr c,eerr1 ; no good - exit
push af ; save the value
call byp
cp '-'
jr z,opok
xor '+' ; check the operator
jr nz,eerr2
opok: push af ; save the operator (zero for '+', nz for '-')
inc hl
call scan ; get a second term
jr nc,s2ok ; all OK, go set the variable
pop de
eerr2: pop de
eerr1: pop de ; clean up the stack
eerr0: call ilprt
db 'Bad expression: \0'
call dim ; tell the user
ld hl,0x80
call prtslp
jp crlf ; and return
s2ok: ld l,a ; second term to l
pop bc ; operator to b
pop af ; first term to a
dec b
inc b ; zero => '+'
jr z,addem ; go do it
sub l
sub l ; setup for subtraction
addem: add a,l ; do the addition
pop hl ; restore variable address
ld (hl),a ; save result
ret
; !# test routine: compare variables with other variables or numbers
.extern test
test:
call areabu
sub 'A' ; get the variable
cp 26
jr nc,eerr0 ; exit on an error
call ivar
ld a,(de) ; get te value
push af ; save it
call incbyp ; get the operator
cp '<'
jr z,cmpok
cp '>'
jr z,cmpok
cp '#'
jr z,cmpok
xor '='
jr nz,eerr1 ; exit if it's no good
cmpok: push af ; save the operator
inc hl
call scan ; get the term
jr c,eerr2 ; something wrong, exit
ld e,a ; term to e
pop af ; restore the operator
or a
jr nz,nocpe ; z => '=' => equality
pop af
cp e ; test for equality
ret nz ; exit if no good
jr doskip ; go do the goto
; this is here for jr length reasons
cplt: pop af
cp e ; compare
skipnc: ret nc ; if it failed exit now
; jump to a line number
doskip: call scnnum ; get the number to go to
pop hl ; get return address back
pop de ; get the next line
dec a ; save it away (needs to be -1)
push af ; save the new line away
jp (hl) ; jump to return address
nocpe: cp '#' ; '#' => inequality
jr nz,nocpne
pop af ; restore variable value
cp e
ret z ; exit if test failed
jr doskip ; else do the goto
nocpne: cp '>'
jr nz,cplt ; '>' => greater than
pop af ; var to a
ld d,a ; and to d
ld a,e ; term to e
cp d ; and compare
jr skipnc ; go check the result
; initch - do odd bits and pieces of setup for chat operation
.extern initch
initch: ld a,1
ld (opentr),a ; clear number of open tries
.extern clrvar
clrvar:
ld a,'A'
ld (_check_),a
ld hl,vars ; nuke all variables to zero
ld de,vars + 1
ld bc,26 + 9 + 26 ; 26 numbers, plus 35 strings 0 - 9 & a - z
ld (hl),b ; start with a zero from b
ldir
dec b ; b comes out of the ldir w/ zero: dec to -1
ld (hl),b ; -1 byte to end strings
ld bc,512 - 9 - 27
ldir ; fill remaining space with -1's
ret
ivar: push hl ; save hl
ld l,a
ld h,0 ; offset in a to hl
ld de,vars
add hl,de ; index into table
ex de,hl ; swap to de
pop hl ; restore hl
ret
scan: call byp
or 0x20
sub 'a' ; was it a letter?
cp 26
jr nc,scnnum ; no, go see about a number
inc hl ; step over it
call ivar ; index into array
ld a,(de) ; get the value
ret ; and return - carry cleared by ivar
scnnum: ld e,0
call byp ; find the number
snlp: ld a,(hl) ; get char back
sub '0'
cp 10 ; number?
ccf
ret c ; return if not
ld d,a ; save in d
ld a,e
add a,a
add a,a
add a,e
add a,a ; a = e * 10
add a,d ; + d
ld e,a
inc hl
ld a,(hl) ; next letter
cp '-'
jr z,rete
cp '+'
jr z,rete ; + and - are legal delimiters
or ' '
xor ' ' ; so are ' ' and null
rete: ld a,e ; get value from e
jr nz,snlp
ret ; return, carry clear from compare
; mattog - handle !& toggles: 'm' & 'l' for matches, 'o' for modem output echo
.extern mattog
mattog: call areabu ; get command letter and upper case it
cp 'O'
ld c,op_bit ; 'O' - do output bit
jr z,dotog
cp 'L'
ld c,lf_bit ; 'L' - do looking for message bit
jr z,dotog
cp 'M' ; 'M' - do match bit
ret nz
ld c,mat_bit
dotog: call incbyp ; now look for a char to say what to do
ld hl,mode ; point hl at mode byte
or a
jr z,xorit ; nothing: toggle the bit
cp '0'
jr nz,clrit ; not '0': clear the bit to enable
ld a,(hl)
or c ; otherwise set it
jr smret
clrit: ld a,c
cpl ; toggle bit in c
and (hl) ; clear the bit in questin
jr smret
xorit: ld a,(hl)
xor c ; flip the bit
smret: ld (hl),a ; save and we're done
ret
; messag - process a !> printout
.extern messag
messag: call areabp ; point at first non-white
ld de,packet ; somewhere to put it
push de
ld bc,128 << 8 ; 128 chars max, and eoln is the delimiter
call parst ; crunch up the string
pop hl
jp prtslp ; and dump it out
; fileio - process !( r/w commands to read / write variables from the file
.extern fileio
fileio:
call areabu ; get R or W
cp 'R'
jr z,setrd
cp 'W'
ret nz
ld a,34 ; write random
db 0x11 ; ld de,XXXX - kills ld a below
setrd: ld a,33 ; read random
ld (hibit),a ; save it away for later
call incbyp
or 0x20
sub 'a'
cp 26
ret nc ; check valid string name
push af ; save string index
call incbyp
sub '0' ; number zero to nine for file record
ld hl,lbrs ; get /QTERM.LBR as a filename
push af
call scnfcb ; parse into 0x5b
pop af
ld hl,['T' << 8] + 'S'
ld (0x65),hl ; convert extent from LBR to STR
ld hl,(chtusr)
inc h
ld (0x5b),hl ; set drive / user
ld hl,0x68 ; point hl / de at nulls
ld de,0x69
ld bc,0xff - 0x68 ; clear to end of name
ldir
ld (0x7d),a ; save record number now
ld de,0x5b
ld c,15
call usrbds ; open it
pop de
inc a
ret z ; exit if no good
ld a,d
add a,9
call fparam ; point at string
ld de,0x80
push de ; save string address to read from
push hl ; save string address in table
push de ; and read address again
ld b,d
ld c,0x7f
ldir ; shift the string
pop de ; address to de
ld c,26
call bdos ; set dma
ld bc,(hibit) ; r/w BDOS opcode to c
ld de,0x5b
push de
call usrbds ; do the operation
pop de
ld c,16
call usrbds ; close the file
pop hl
jr repstr ; replace string in table
; sinput - handle two cases of input processing for !<
.extern sinput
sinput: call areabp ; get the command character
ld d,a ; command char to d
call incbyp ; get variable / string letter
call ucsa ; upper case it
sub 'A'
cp 26 ; is it valid?
ret nc ; nope
ld e,a ; letter code to e
ld a,d ; command char back from d
xor '-'
jr z,strin ; '-' for string input
xor '.' ^ '-'
ret nz ; '.' for hot key input
ld d,a ; make code in e fill de
push de ; save
call kbdin ; go get a character
pop de
ld hl,vars
add hl,de ; index into variables
ld (hl),a ; save the letter
ret
strin: ld d,e
push de
ld de,work2 ; point at input area
ld a,40
ld (de),a ; 40 chars maximum
ld c,10
call bdos ; go get them
call crlf ; throw a new line just for the hell of it
ld hl,work2 + 1
ld e,(hl) ; get the length
inc hl ; point at real text
pop af
push hl
ld d,0 ; extend length to de
add hl,de ; point at end of string
ld (hl),d ; add a null terminating byte
savstr: add a,9 ; get string index to a
call fparam ; point at string
repstr: call kilstr ; kill it
xor a
pop de
jp insstr ; and replace it
; now starts the middle of the "read string variable from modem" code - this
; is kinda cut to shreds for jr length reasons - we enter at the bottom and
; leave via savstr above
; the very end - we've read the string, now it's time to save it
gotit: inc de ; point back to start
push de ; save this point for later
ld h,d
ld l,e ; copy to hl
kcclp: ld a,(hl) ; get a char
and 0x7f ; nuke bit 7
ld (de),a ; save it
inc hl ; bump read ptr
or a
jr z,hsav ; exit on a null
cp ' '
jr c,kcclp ; ditch control chars
cp 0x7f
jr z,kcclp ; and deletes
inc de ; otherwise step up to allow saved character
jr kcclp
hsav: ld a,(hibit) ; get string number
jr savstr ; go and save it
; now the loop to find the start
stlp: call redsch ; check a character
jr z,wasec ; check for end character
ld a,(de) ; no - we'll want to save original char back
wasec: ld c,a ; save char to save
push hl
ld h,l ; load start char into h
call chksch ; did we find it?
pop hl
ld a,c
ld (de),a ; drop terminator in
jr z,gotit ; yes - go save it away
djnz stlp ; count chars
ret ; return when we run out chars
; ![ ^ a c1c2
;
; After ![ - and ![ : and normal lines have left text in w2 (a la stufw2),
; parse a string starting with c1 (but not including it), and ending with c2
; (again not including it) - save in string a. If c1 (or c2) are a null
; then the string becomes any whitespace delimited string: whitespace is
; taken as ' ', tab, cr, lf. Note also that all control characters are
; thrown away.
ipstr: call ucsahl
sub 'A' ; convert .....
cp 26 ; and test string index
ret nc
ld (hibit),a ; save it
call incbyp ; step up to delimiter chars
push hl
ld hl,work2 + 257
ld de,packet
ld bc,66
ldir
pop hl
ld de,pack + 1 ; save them in pack
ld b,2 ; two, null terminates
xor a
ld (de),a ; preload chars with two nulls
dec de
ld (de),a
call parst ; crunch up the string
ld hl,(pack) ; load delimiters from where parst put them
ld bc,64 << 8 ; max of 64 chars to look at / c == 0
ld de,packet + 65 ; point de at saved text
; now loop looking for the end
endlp: call redsch ; check a character
jr nz,noend ; check for end character
inc c ; flag we saw an end char
ld (de),a ; add a zero to terminate
jr cntend ; jump to count
noend: dec c
inc c
jr nz,stlp ; we've seen an end - go do it
cntend: djnz endlp ; count chars
ret ; return when we run out chars
; handle ![ multiple choice thingies from the modem
.extern multi
multi:
call areabp ; what's wanted?
ld c,a ; save the second character
call incbyp ; strip spaces
xor a
ld (casefl),a
ld a,c
cp '^'
jr z,ipstr
cp ':'
jp z,silnce
cp '-' ; '-' input ......
jr z,minput
xor '+' ; '+' for 8 bit string compare
jr z,str8b
cp '=' ^ '+' ; '=' for 7 bit
jr z,str7b
cp '_' ^ '+' ; '_' for 7 bit and case insensitive
ret nz ; oops - don't grok it.
ld (casefl),a ; set case flag
str7b: ld a,0x7f ; set 7 bit flag
db 0x06 ; makes the next byte the operand of a ld b,xx
str8b: dec a ; really ld a,0xff since a == 0:
; set all 8 bits
push af ; save comparison mask
ld de,packet ; somewhere to put match string
ld bc,[40 << 8] + ' ' ; 40 chars max, space is the delimiter
call parst ; crunch up the string
pop bc ; comparison mask back to b
ret c ; oops - bad string
push hl
ld hl,work2 + 322 ; point at stuff we read ..... (don't ask why
mclp: dec hl ; it's there :-)
ld a,(hl) ; end of string yet?
or a
pop de ; keep stack safe
ret z ; end of string: exit
push de ; save word back on stack
ld de,packet
call cmptst ; do we have a match??
jr nz,mclp ; skip if no good
push hl
cmplp: ld a,(de)
or a ; end of string we're searching for?
jr nz,mtchmo ; yes - we got a hit
pop hl
pop hl ; get string pointer back to hl
doskp1: jp doskip
mtchmo: call cmptst
jr nz,mchbad ; oops - didn't match, so exit now
inc hl
inc de
jr cmplp ; and back for more
mchbad: pop hl ; restore pointer
jr mclp ; and back for more
minput: call scnnum ; get a time
or a
jr nz,timok
ld a,15 ; none given, default to 15 seconds
timok: push af
push hl
ld hl,work2
ld de,work2 + 1
ld bc,512
ld (hl),c
ldir ; clear space where strings will live
pop hl
call byp
or a
jr z,nostr ; no strings, all done
ld de,work2 + 1
ld b,4
sslp: push bc
call scanst ; scan a string
inc de
pop bc
jr c,nostr ; exit if end of input
djnz sslp ; otherwise loop till 4 read
nostr: ld hl,work2 + 1
call finstr ; get address of it's end
ld (work2 + 240),hl ; and save it
ld hl,work2 + 42
call finstr
ld (work2 + 242),hl ; and for string 2
ld hl,work2 + 83
call finstr
ld (work2 + 244),hl ; and 3
ld hl,work2 + 124
call finstr
ld (work2 + 246),hl ; and 4
pop af ; get time back
ld c,a ; save it
second: dec c
ret z ; all out of time - exit
ld de,600
call setspd ; set the speed
qrtrms: ld b,96 ; hang loose a while
qmslp: djnz qmslp
push hl
push bc
call procch
jr c,nochar
call stufw2 ; save the char
inc de
ld hl,(work2 + 240)
call chkbak ; did we get string1
jr z,gotone ; exit if so
ld hl,(work2 + 242)
call chkbak ; string 2?
jr z,gotone ; exit if so
ld hl,(work2 + 244)
call chkbak ; string 3
jr z,gotone ; exit if so
ld hl,(work2 + 246)
call chkbak ; and lastly check string 4
jr z,gotone
nochar: pop bc
pop hl
dec hl ; count down second timer
ld a,h
or l
jr nz,qrtrms
jr second ; loop back
gotone: pop bc
pop hl
ret
.extern stufw2
stufw2: ld hl,work2 + 258
ld de,work2 + 257
ld bc,64
ldir
ld (de),a ; save the character
ret
.extern clerw2
clerw2: ld hl,work2 + 256
ld de,work2 + 257
ld bc,70
ld (hl),b
ldir
ret
finstr: ld a,(hl)
or a
ret z
inc hl
jr finstr
chkbak: dec hl
ld a,(hl)
inc hl
or a
jr nz,isastr
inc a
ret
isastr: push de
cklp: dec de
dec hl
ld a,(hl)
or a
jr z,pdret
ld a,(de)
xor (hl)
and 0x7f
jr z,cklp
pdret: pop de
ret
cmptst: ld a,(casefl)
or a ; case insensitive?
push af ; save z flag
ld a,(de)
jr z,noucs1 ; nope - use the character as is
and 0x7f
call ucsa ; force upper case
noucs1: ld c,a
pop af ; get z flag back for case insensitive
ld a,(hl)
jr z,noucs2
and 0x7f
call ucsa ; mask and force upper case
noucs2: xor c ; get in the rest of it
and b ; mask as necessary
ret
silnce: call scnnum ; get a time
or a
jr nz,stimok
ld a,15 ; none given, default to 15 seconds
stimok: call clerw2
ld b,a
inc b
setsil: ld c,b
xsecnd: dec c
ret z
push bc
ld de,600
call setspd ; set the speed
xrtrms: ld b,96 ; hang loose a while
xmslp: djnz xmslp
push hl
call procch
pop hl
jr c,xnchar
call stufw2
pop bc
jr setsil
xnchar: dec hl ; cound down second
ld a,h
or l
jr nz,xrtrms
pop bc
jr xsecnd ; loop back
; read a char, and see if it matches the delimiter in c
redsch: dec de
chksch: ld a,(de)
and 0x7f ; nuke parity
inc h
dec h ; is h zero?
jr nz,nowsp ; no - don't do white space check
call iswa ; is it white space?
scf
ccf ; clear carry
ret nz ; return nz if not (no match)
xor a ; clear a so 'cp h' below forces zero
nowsp: xor h ; see if char matches delimiter
ret
.dseg
.extern mode
mode: db lf_bit
.useg
casefl: ds 1 ; case insensitive string match?
.extern vars
vars: ds 26 ; space for 'a' through 'z'
.extern strngs
strngs: ds 512 ; space for 35 strings
.extern _check_
_check_:
ds 1 ; check space