home *** CD-ROM | disk | FTP | other *** search
- ;
- ; IF -- conditionally execute or skip commands witthin a submit file
- ;
- ; Written by Marc C. Brooks 1/4/83
- ;
- ; based on David Kirkland's version of SKIPIF as of 6/12/83
- ;
- ; Usage:
- ;
- ; IF A[mbig] fn true if fn is ambigous
- ; IF E[xists] fn true if file fn exists
- ; IF M[issing] fn true if file fn does not exist
- ; IF N[ull] (fn) true if the fn is missing
- ; IF Z[ero] fn true if file fn is zero length or does not exist
- ;
- ; If the condition is true, all commands up to the next ELSE or
- ; ENDIF statement are executed. If an ELSE is encountered before
- ; the ENDIF statement is reached, commands are skipped until the
- ; ENDIF is found. If the condition is false, commands are skipped
- ; until the matching ELSE or ENDIF is found. Command execution then
- ; resumes. IF-ELSE-ENDIF groups may be nested to any depth.
- ;
- ; Only the first character of the first keyword (the A of Ambig or
- ; whatever) is checked. If an invalid keyword is entered, all
- ; commands between the IF and its matching ENDIF will be skipped
- ; (after a suitable error message.)
- ;
- cpm equ 0000h
- tpa equ 0100h
- ccpoff equ 0806h ; offset from (bdos+1) to bottom of ccp
- bdos equ 0005h
- fcb1 equ 005ch ;the first fcb prepared by the CCP
- name1 equ fcb1+1 ; start of the filename of fcb1 (AEMN or Z)
- fcb2 equ 006ch
- name2 equ fcb2+1
- fcb2CUR equ fcb2+32 ; current record for fcb2
- ;
- drive equ 'A' ; the drive with the $$$.SUB file
- bell equ 07h ; an ASCII bell character
- ; BDOS codes used
- ;
- PrtStr equ 9 ; Print a string to console (terminated by $)
- Open equ 15 ; Open a file
- Close equ 16 ; Close a file
- Srch1st equ 17 ; Search for the first occurence of a file
- Erase equ 19 ; Erase a file
- Read equ 20 ; Read a sequential record from a file
- SetDma equ 26 ; Set the dma buffer address
- ;
- org tpa
- ;
- ; First set the Stack, Dma address and check for a $$$.SUB file
- ;
- lhld bdos+1 ; get the address of the BDOS
- lxi d,-ccpoff ; and add the CCP offset
- dad d ; set the stack below the CCP
- sphl
-
- mvi c,SetDma ; set the dma address to the buffer following
- lxi d,dmabuf ; the variables.
- call bdos
-
- mvi c,Open ; open $$$.SUB
- lxi d,subfile
- call bdos
- inr a ; check to see if the $$$.SUB exists
- jz explain ; if not, explain the syntax and return
- ;
- ; Everything is fine so execute the command the caller actually asked for
- ;
- lda name1 ; first character of the AMBIG or EXISTS or ..
-
- cpi 'N' ; Null?
- jz null
-
- lda name2 ; check the to see if the user gave
- cpi 020h ; a filespec as the second argument
- jnz process
-
- mvi c,PrtStr ; fn is null, bitch to user and skip both the
- lxi d,FnNulMsg ; IF and ELSE clauses
- call bdos
- jmp skipboth
-
- process lda name1 ; okay, we have a filespec, branch to command
- cpi 'A' ; Ambig?
- jz ambig
- cpi 'E' ; Exists?
- jz exists
- cpi 'M' ; Missing?
- jz missing
- cpi 'Z' ; Zero?
- jz zero
-
- mvi c,PrtStr ; no match so print error message
- lxi d,BadOptMsg
- call bdos
-
- jmp skipboth ; skip both IF anf ELSE clauses
-
- ; ambig - do the IF clause if the 2nd argument is ambiguous
- ambig mvi b,11 ; 11 characters in filename & filetype
- lxi h,name2 ; bypass the drive code
-
- scanlp mov a,m ; scan for '?' in parsed fcb
- cpi '?'
- jz cpm ; fn is ambiguous, return to CP/M
- inx h
- dcr b ; done ?
- jnz scanlp ; no, loop back for next char
-
- jmp false ; no '?', so false
-
- ; exists - do the IF clause if the file exists
- exists call search
- jnz cpm ; file found, return to CP/M
- jmp false
-
- ; missing - do the IF clause if the file does not exist
- missing call search
- jnz false
- jmp cpm ; file not found, return to CP/M
-
- ; null - do the IF clause if the second parameter is missing
- null lda name2 ; Check the second FCB to see if the user
- cpi 020h ; gave a filespec as the second arg
- jnz false
- jmp cpm ; fn is not present, return to CP/M
-
- ; zero - do the IF clause if the 2nd argument is a zero length file
- zero call search ; does the file exist?
- jz cpm ; nope, zero long then so return to CP/M
-
- mvi c,Open ; yes, lets open it
- lxi d,fcb2
- call bdos
-
- xra a ; zero the current record byte
- sta fcb2CUR
- mvi c,Read ; now try to read one record (will fail if
- lxi d,fcb2 ; the file is zero length)
- call bdos
- ora a
- jz false ; read was OK, so not zero length
- jmp cpm ; read failed, return to CP/M
-
- ; search - search for the first (possibly) ambiguous file to match fcb
- search mvi c,Srch1st
- lxi d,fcb2
- call bdos
- inr a ; adjust the flags
- ret
-
- ; skipboth - tell the user and skip both clauses of the IF
- skipboth mvi c,PrtStr ; tell the user that both the IF and the
- lxi d,SkipMsg ; ELSE clauses are being skipped
- call bdos
-
- mvi c,Open ; open $$$.SUB
- lxi d,subfile
- call bdos
-
- call skipend ; skip line till the ENDIF is encountered
-
- mvi c,Close ; close the $$$.SUB to rewrite the modified fcb
- lxi d,subfile
- call bdos
-
- jmp cpm ; return to CPM
-
- ; false - skip all command up to and including the ELSE, then return
- false mvi c,Open ; open $$$.SUB
- lxi d,subfile
- call bdos
-
- call skipelse ; skip lines till ELSE or ENDIF
-
- mvi c,Close ; close the $$$.SUB to rewrite the modified fcb
- lxi d,subfile
- call bdos
-
- jmp cpm ; return to CP/M to execute else clause
-
- ; skipend - skip lines in the $$$.SUB file till an ENDIF is found
- skipend call nxtline ; get the next line from the $$$.SUB file
-
- lxi d,EndLit ; point to the ENDIF literal
- call compstr ; and compare
- jnz skipend ; not equal, loop till it is
- ret ; equal, return to caller
-
- ; skipelse - skip lines in the $$$.SUB file till an ELSE or ENDIF is found
- skipelse call nxtline ; get the next line from the $$$.SUB file
-
- lxi d,ElseLit ; point to the ELSE literal
- call compstr ; now compare the record just read to if equal
- rz ; yes, return to caller
-
- lxi d,EndLit ; point to the ENDIF literal
- call compstr ; and compare
- jnz skipelse ; not equal, loop till found
- ret ; equal, return to caller
-
- ; nxtline - get the next line from the $$$.SUB file (with recursion stuff)
- nxtline call nxtcmd ; get the next command line from the $$$.SUB
-
- lxi d,IfLit ; is it an IF statement?
- call compstr
- rnz ; nope, okay, return the line to caller
-
- call skipend ; yes, skip both clauses of this nested IF
- jmp nxtline ; and now get the next command line
-
- ; nxtcmd - get the command line from the $$$.SUB file and chop it off the file
- nxtcmd lda subCNT ; get the current record count for $$$.SUB
- dcr a ; decrement by one
- sta subREC ; and set the current record
- mvi c,Read ; read the next command
- lxi d,subfile
- call bdos
- inr a
- jz killsub ; if error, kill $$$.SUB and exit
-
- lxi h,dmabuf ; load the address of the command buffer
- mov e,m ; get the byte count
- mvi d,0
- dad d
- inx h
- mvi m,0 ; and terminate the command with a zero
-
- lxi h,subs2 ; zero the S2 byte of the fcb to force the
- mvi m,0 ; BDOS to rewrite it
- inx h ; now point to the record count byte
- mov a,m ; and see if it is a zero
- ora a
- jz erasub ; yes, erase the $$$.SUB and return to CP/M
- dcr m ; no, decrement the record count and return
- ret
-
- ; compstr - compare the command just read to the literal point to by DE
- compstr lxi h,dmabuf+1 ; get the address of the command and
- ; skip the leading whitespace
-
- skipblk mov a,m ; end of command string ?
- ora a
- jz nomatch ; yes, signal no match
-
- cpi 021h ; is it whitespace ?
- jnc complp ; no, start comparing
- inx h ; yes, next character
- jmp skipblk
-
- nomatch ori 0ffh ; clear the zero flag to signal no match
- ret ; and return to caller
-
- complp ldax d
- ora a ; end of the comparison string ?
- rz ; yes, they must match
- mov c,a
- mov a,m ; not eos, get next byte
- cpi 061h ; is 'a' <= a <= 'z' ?
- jc compit
- cpi 07ah
- jnc compit
- ani 05fh ; yes, fold to upper case
- compit cmp c ; match ?
- rnz ; no , return non zero
- inx h
- inx d
- jmp complp
-
- ; killsub - kill the submit file and return to CP/M
- killsub mvi c,PrtStr
- lxi d,TermMsg ; tell the user
- call bdos
-
- erasub mvi c,Erase ; now kill the $$$.SUB file
- lxi d,subfile
- call bdos
-
- jmp cpm ; return to CP/M
-
- ; explain - give the syntax and an operational synopsis since the user
- ; involked IF with no $$$.SUB file present (i.e. from console)
- explain mvi c,PrtStr
- lxi d,HelpMsg
- call bdos
-
- jmp cpm ; return to CP/M
- ;
- ;
- IfLit db 'IF',0
- ;
- ElseLit db 'ELSE',0
- ;
- EndLit db 'ENDIF',0
- ;
- ;
- ;
- TermMsg db bell,bell,bell,'ERROR - Submit procedure terminated'
- db 13,10,'$'
- ;
- FnNulMsg db bell,bell,bell,'A filespec must be given with this command'
- db 13,10,'$'
- ;
- BadOptMsg db bell,bell,bell,'That is not a legal option (A,E,M,N or Z)'
- db 13,10,'$'
- ;
- SkipMsg db bell,bell,bell,'ERROR - Skipping both IF and ELSE clauses'
- db 13,10,'$'
- ;
- HelpMsg db bell,13,10,'IF and its companion programs (ELSE, ENDIF and GOTO) are',13,10
- db 'used within submit files to allow conditional execution of',13,10
- db 'commands. See IF.DOC for examples.',13,10
- db 13,10
- db 'Usage: IF A[mbig] fn true if fn is ambigous',13,10
- db ' IF E[xists] fn true if file fn exists',13,10
- db ' IF M[issing] fn true if file fn does not exist',13,10
- db ' IF N[ull] (fn) true if the fn is missing',13,10
- db ' IF Z[ero] fn true if file fn is zero length or',13,10
- db ' does not exist',13,10
- db 13,10
- db 'If the condition is true, all commands up to the next ELSE or',13,10
- db 'ENDIF statement are executed. If an ELSE is encountered before',13,10
- db 'the ENDIF statement is reached, commands are skipped until the',13,10
- db 'ENDIF is found. If the condition is false, commands are skipped',13,10
- db 'until the matching ELSE or ENDIF is found. Command execution',13,10
- db 'then resumes. IF-ELSE-ENDIF groups may be nested to any depth.',13,10
- db 13,10
- db 'Only the first character of the first keyword (the A of Ambig or',13,10
- db 'whatever) is checked.',13,10
- db '$'
- ;
- ;
- subfile db drive+1-'A' ; drive for the $$$.SUB file
- db '$$$ SUB' ; and the parsed name
- db 0,0 ; and extent and S1 bytes
- subs2 ds 1 ; and the S2 byte (0'ed to cause BDOS rewrite)
- subCNT ds 1 ; and the record count
- ds 16 ; room for the allocation map
- subREC ds 1 ; room for the current record number
- ds 3 ; and finally, room for the random rec num
- ;
- dmabuf ds 128 ; the dma buffer for all operations
- ;
- end