; ; Program: IF ; Author: Richard Conn ; Modified By: Charles McManis ; Version: 1.2 ; Date: 11 Feb 85 ; Previous Versions: 1.1 (22 Apr 84) ; version equ 12 ; ; IF is intended to be invoked from the IF routine in an FCP. ; This program implements the IF conditional tests and sets the next level ; of IF to be TRUE or FALSE. ; ; Modified on 02/11/85 to accept ambiguous file names and match them. This ; allows aliases to add file extensions if they are needed, for instance ; if there is an alias LDIR that gets a directory of an .LBR file, it ; previously had to be defined as an example : ; ; ; ; Equates for Key Values ; z3env SET 0f400h ;address of ZCPR3 environment noise equ 0 ;set to 1 for noisey (message) operation negchar equ '~' ;negation prefix char bdos equ 5 fcb1 equ 5ch fcb2 equ 6ch tbuff equ 80h cr equ 0dh lf equ 0ah bel equ 07h ; ; External Z3LIB and SYSLIB Routines ; ext z3init,strtzex,stopzex,geter1,getreg,ift,iff,getenv ext eval10,print,capine,codend,sksp,sknsp,zfname,cout ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3init ;initialize the ZCPR3 Environment jmp ifstart ; ; Condition Table ; condtab: db 'T ' ;TRUE dw ifctrue db 'F ' ;FALSE dw ifcfalse db 'EM' ;file empty dw ifcempty db 'ER' ;error message dw ifcerror db 'EX' ;file exists dw ifcex db 'IN' ;user input dw ifcinput db 'NU' ;null argument dw ifcnull db 'TC' ;Z3TCAP Entry Loaded dw ifctcap db 'WH' ;Wheel Byte dw ifcwheel db 0 ; ; FCP Extension Command: IF ; ifstart: ; ; Advance to Next Line if Noisey ; IF NOISE mvi a,lf call cout ENDIF ;NOISE ; ; Test for Equal Sign in Line and Process FCB1=FCB2 form if so ; lxi h,tbuff+1 ;pt to buffer ifteq: mov a,m ;look for = inx h ;pt to next ora a ;done if EOL jz ifck0 cpi '=' ;equal? jnz ifteq lxi h,fcb1+1 ;= found, so compare FCB1 and FCB2 lxi d,fcb2+1 mvi b,11 ;11 chars ifteq1: ldax d ;compare ; ** Such a small change really. cpi '?' ; see if an AFN was specified jz okchar ; always match a ? mov c,a ; save it in C temporarily mov a,m ; get the other character cpi '?' ; see if it is a ? jz okchar ; if so accept it as a match cmp c ; ** This allows IF $1=* and IF $1=*.?q? etc ; cmp m ; this guy is no longer needed. jnz ifcf ;FALSE if no match okchar: inx h ;advance inx d dcr b ;count down jnz ifteq1 jmp ifct ;TRUE if match ; ; Test Condition in FCB1 and file name in FCB2 ; Execute condition processing routine ; ifck0: lxi d,fcb1+1 ;pt to first char in FCB1 ldax d ;get it cpi '/' ;help? jz ifhelp cpi ' ' ;also help jz ifhelp sta negflag ;set negate flag cpi negchar ;is it a negate? jnz ifck1 inx d ;pt to char after negchar ifck1: call regtest ;test for register value jnz runreg call condtest ;test of condition match jnz runcond ;process condition IF NOISE call print db ' No IF Condition Given',0 ret ELSE ;NOT NOISE mvi a,bel jmp cout ENDIF ;NOISE ; ; Print Help Message ; ifhelp: IF NOT NOISE mvi a,lf ;leading new line call cout ENDIF ;NOT NOISE call print db 'IF, Version ' db (version/10)+'0','.',(version mod 10)+'0' db ' - Conditional Test' db cr,lf,'Syntax:' db cr,lf,' IF condition arguments -or- IF ~condition arguments' db cr,lf,'where a leading "~" negates the effect of the ' db 'IF Condition' db cr,lf,'Possible IF Conditions are:' db cr,lf,' T Always TRUE' db cr,lf,' F Always FALSE' db cr,lf,' EMPTY T if Files are Empty' db cr,lf,' ERROR T if Error Flag Set' db cr,lf,' EXIST T if Files Exist' db cr,lf,' INPUT T if User Hits T, Y, CR, or SP' db cr,lf,' NULL arg T if No Arg Follows' db cr,lf,' TCAP T if ZCPR3 TCAP Available' db cr,lf,' WHEEL T if Wheel Byte Set' db cr,lf,' reg value T if Register reg = value' db cr,lf,' fcb1=fcb2 T if the Two FCB values are =' db cr,lf,'Only first 2 letters of keywords are required' db cr,lf,'The leading "~" is effective with all conditions except' db ' fcb1=fcb2' db 0 ret ; ; Process register - register value is in A ; runreg: push psw ;save value call getnum ;extract value in FCB2 as a number pop psw ;get value cmp b ;compare against extracted value jz ifctrue ;TRUE if match jmp ifcfalse ;FALSE if non-match ; ; Process conditional test - address of conditional routine is in HL ; runcond: pchl ;"call" routine pted to by HL ; ; Condition: NULL (2nd file name) ; ifcnull: lda fcb2+1 ;get first char of 2nd file name cpi ' ' ;space = null jz ifctrue jmp ifcfalse ; ; Condition: TCAP ; ifctcap: call getenv ;get ptr to ZCPR3 environment descriptor lxi d,80h ;pt to TCAP entry dad d mov a,m ;get first char cpi ' '+1 ;space or less = none jc ifcfalse jmp ifctrue ; ; Condition: WHEEL ; ifcwheel: call getenv ;get ptr to ZCPR3 environment descriptor lxi d,29h ;pt to Wheel Byte address dad d mov a,m ;get low inx h mov h,m ;get high mov l,a ;put low mov a,m ;get Wheel Byte ora a ;0=not wheel jz ifcfalse jmp ifctrue ; ; Condition: TRUE ; IFCTRUE enables an active IF ; Condition: FALSE ; IFCFALSE enables an inactive IF ; ifctrue: call negtest ;test for negate jz ifcf ;make IF FALSE ifct: IF NOISE call print db ' IF T',0 ENDIF ;NOISE call ift ;make IF TRUE rnz jmp ifovfl ifcfalse: call negtest ;test for negate jz ifct ;make IF TRUE ifcf: IF NOISE call print db ' IF F',0 ENDIF ;NOISE call iff ;make IF FALSE rnz ifovfl: IF NOISE call print db ' IF Overflow',0 ret ELSE ;NOT NOISE mvi a,bel jmp cout ENDIF ;NOISE ; ; Condition: INPUT (from user) ; ifcinput: IF NOT NOISE mvi a,lf ;new line call cout ENDIF ;NOT NOISE call stopzex ;suspend ZEX input call print db ' IF True? ',0 call capine call strtzex ;resume ZEX input cpi 'T' ;true? jz ifctrue cpi 'Y' ;yes? jz ifctrue cpi cr ;new line? jz ifctrue cpi ' ' ;space? jz ifctrue jmp ifcfalse ; ; Condition: EXIST filename.typ ; List of Files Permitted ; ifcex: call skip2 ;skip to 2nd token jz ifctrue ;declare TRUE if none ; ; Extract Next File ; ifcex1: lxi d,fcb1 ;pt to FCB call zfname ;convert text push h ;save ptr to next char ; ; Log Into to DU and Search for File ; call tlog ;log into DU lxi d,fcb1 ;pt to fcb mvi c,17 ;search for first call bdos inr a ;set zero if error ; ; Abort as FALSE if File Not Found ; pop h ;get ptr to next char jz ifcfalse ; ; Advance to Next File, if Any ; mov a,m ;more to follow? inx h cpi ',' jz ifcex1 ; ; All Files Exist if No More Files ; jmp ifctrue ;all found, so TRUE ; ; Condition: EMPTY filename.typ ; ifcempty: call skip2 ;skip to 2nd token jz ifctrue ;TRUE if none ; ; Select Next File ; ifcem1: lxi d,fcb1 ;pt to FCB1 call zfname ;convert push h ;save ptr to next ; ; Log into DU and Try to Open File ; call tlog ;log into FCB1's DU lxi d,fcb1 ;pt to fcb1 mvi c,15 ;open file push d ;save fcb ptr call bdos pop d inr a ;not found? ; ; File is Empty if Not Found ; jz ifemt ; ; Try to Read one Record from File ; mvi c,20 ;try to read a record call bdos ora a ;0=OK ; ; File is Empty if Can't Read Record ; jnz ifemt ;NZ if no read pop h ;file not empty ; ; File Exists and Contains Something ; jmp ifcfalse ;so EMPTY condition is FALSE ; ; File is Empty - Advance ; ifemt: pop h ;pt to next char mov a,m ;get next char inx h cpi ',' ;more to come? jz ifcem1 ; ; Done and True if No More Files - All are Empty ; jmp ifctrue ;all empty, so TRUE ; ; Condition: ERROR ; ifcerror: call geter1 ;get error byte jz ifctrue jmp ifcfalse ; ; **** Support Routines **** ; ; ; Save TBUFF and skip to 2nd token ; skip2: lxi d,tbuff+1 ;pt to first char call codend ;pt to free area skip2a: ldax d ;get next char mov d ora a ;done? jnz skip2a call codend ;skip over spaces call sksp call sknsp ;skip over 1st token call sksp ;skip over spaces mov a,m ;get 1st char of 2nd token ora a ;return with Z if none ret ; ; Convert chars in FCB2 into a number in B ; getnum: lxi h,fcb2+1 ;pt to first char call eval10 ;evaluate mov b,a ;value in B ret ; ; Log into DU in FCB1 ; tlog: lda fcb1 ;get disk ora a ;current? jnz tlog1 mvi c,25 ;get disk call bdos inr a ;increment for following decrement tlog1: dcr a ;A=0 mov e,a ;disk in E mvi c,14 call bdos lda fcb1+13 ;pt to user mov e,a mvi c,32 ;set user jmp bdos ; ; Test of Negate Flag = negchar ; negtest: lda negflag ;get flag cpi negchar ;test for No ret ; ; Test FCB1 against a single digit (0-9) ; Return with register value in A and NZ if so ; regtest: ldax d ;get digit sui '0' jc zret ;Z flag for no digit cpi 10 ;range? jnc zret ;Z flag for no digit mov b,a ;register number in B call getreg ;get register value mov b,a ;save value xra a ;set NZ dcr a mov a,b ;get register value ret zret: xra a ;set Z ret ; ; Test FCB1 against condition table (must have 2-char entries) ; Return with routine address in HL if match and NZ flag ; condtest: lxi h,condtab ;pt to table condt1: mov a,m ;end of table? ora a rz ldax d ;get char mov b,m ;get other char in B inx h ;pt to next inx d cmp b ;compare entries jnz condt2 ldax d ;get 2nd char cmp m ;compare jnz condt2 inx h ;pt to address mov a,m ;get address in HL inx h mov h,m mov l,a ;HL = address xra a ;set NZ for OK dcr a ret condt2: lxi b,3 ;pt to next entry dad b ; ... 1 byte for text + 2 bytes for address dcx d ;pt to 1st char of condition jmp condt1 ; ; Buffers ; negflag: ds 1 ;negation flag end