; REVFN.MAC ; Vers equ 11 ; version number SubVers equ ' ' ; modification level ; ; Reverses the case of a filename. For ZCPR3 only. ; ; USAGE: ; ; REVFN {dir:}fn.ft {{/}options} ; ; If no DU or DIR specification is given, the current drive/user is assumed. ; ; OPTIONS: ; ; Q Toggles quiet mode. Quiet mode is set by the ZCPR3 quiet ; flag or by a configuration byte (non-zero defaults to ; quiet mode). Option Q toggles the current mode. ; ; R Toggles query for renaming of read-only files. Normally ; REVFN asks before renaming read-only files. This default ; can be changed by a configuration byte to rename files ; without asking. The R option will toggle the current ; default to non-default operation. ; ; Version 1.1 -- October 8, 1990 -- Gene Pizzetta ; Corrected bug that required slash for options. Now handles ; filenames beginning with slash properly, if preceded by a ; DU spec. ; ; Version 1.0 -- September 23, 1990 -- Gene Pizzetta ; Initial release. ; ; Gene Pizzetta ; 481 Revere Street ; Revere, MA 02151 ; ; Newton Centre Z-Node: (617) 965-7259 ; GEnie: E.PIZZETTA ; Voice: (617) 284-0891 ; ; Developed with SLRMAC and SLRNK+: ; slrmac revfn/m ; slrnkp revfn/n,/v,/a:100,/j,revfn,vlib/s,z3lib/s,syslib/s,/e ; ; System addresses . . . ; Bdos equ 05h CpmFcb equ 5Ch AltFcb equ 6Ch CpmDma equ 80h TPA equ 100h ; ; ASCII characters . . . ; BEL equ 07h ; bell BS equ 08h ; backspace TAB equ 09h ; tab LF equ 0Ah ; linefeed CR equ 0Dh ; carriage return ; MACLIB Z80 ; ; Following routines are from VLIB, Z3LIB, and SYSLIB ; ext f$exist,f$rename,initfcb,gfa,sfa,capin ext retud,logud,epstr,pfn2,cout,pafdc,phl4hc ext z3vinit,stndout,stndend,getquiet,gzmtop,prtname ext puter2,inverror,zsyschk ; public pstr ; ; TYP3HDR.MAC, Version 1.1 -- Extended Intel Mnemonics ; This code has been modified as suggested by Charles Irvine so that ; it will function correctly with interrupts enabled. ; Extended Intel mnemonics by Gene Pizzetta, April 30, 1989. ; Entry: jr Start0 ; must use relative jump db 0 ; filler db 'Z3ENV',3 ; type-3 environment Z3EAdr: dw 0FE00h ; filled in by Z33 dw Entry ; intended load address ; ; Configuration area . . . ; db 'REVFN' ; filename for ZCNFG CFG file db Vers/10+'0',Vers mod 10+'0',' ' QtFlag: db 0 ; non-zero defaults to quiet mode ROFlag: db 0 ; non-zero renames R/O without asking ; Start0: lxi h,0 ; point to warmboot entry mov a,m ; save the byte there di ; protect against interrupts mvi m,0C9h ; replace warmboot with a return opcode rst 0 ; call address 0, pushing RetAddr onto stack RetAddr: mov m,a ; restore byte at 0 dcx sp ; get stack pointer to point dcx sp ; ..to the value of RetAddr pop h ; get it into HL and restore stack ei ; we can allow interrupts again lxi d,RetAddr ; this is where we should be xra a ; clear carry flag push h ; save address again dsbc de ; subtract -- we should have 0 now pop h ; restore value of RetAddr jz Start ; if addresses matched, begin real code ; lxi d,NotZ33Msg-RetAddr ; offset to message dad d xchg ; switch pointer to message into DE mvi c,9 jmp 0005h ; return via BDOS print string function ; NotZ33Msg: db 'Not Z33+$' ; abort message if not Z33-compatible ; ; Messages . . . ; MsgUse: db 'REVFN Version ' db Vers/10+'0','.',Vers mod 10+'0',SubVers db ' (loaded at ',0 MsgUs1: db 'h)',CR,LF db 'Reverses the case of a filename.',CR,LF db 'Usage:',CR,LF,' ',0 MsgUs2: db ' {dir:}fn.ft {{/}options}',CR,LF db 'A filename is required.',CR,LF db 'Options:',CR,LF db ' Q toggle quiet mode ',0 MsgUs3: db CR,LF,' R ',0 MsgUs4: db 'rename read-only files without asking',0 MsgDon: db 'don''t ',0 MsgUon: db 'on',0 MsgUof: db 'off',0 MsgRd: db ' Renaming ',0 MsgWrt: db ' to ',0 MsgFNF: db ' not found.',0 MsgFEx: db ' exists.',0 MsgRO: db BEL,' Read-Only, Rename? No',BS,BS,0 MsgYes: db 'Yes',CR,LF,0 MsgAmb: db ' No ambiguous filenames.',0 MsgDir: db ' Invalid directory.',0 MsgBdO: db ' Invalid option.',0 ; Start: lhld Z3EAdr ; set up environment call zsyschk ; is this a Z-system? rnz ; (nope) call z3vinit sspd OldStk ; save old stack pointer call gzmtop ; get top of memory sphl ; ..and set up new stack ; call getquiet ; is ZCPR quiet flag set? jrnz SetZQt ; (yes) lda QtFlag ; no, get quiet config byte SetZQt: sta OpQFlg ; ..and store in Q option flag lxi h,CpmDma ; see if there's a tail mov a,m ora a jz Usage ; (no) ; GtTail: call GetOpt ; get options lxi h,CpmFcb+1 ; get input filename from fcb mov a,m cpi ' ' ; is there a filename? jz Usage ; (nope) cpi '/' ; is it an option list? jrnz GtTl1 lda CpmFcb ; do we have a drive spec? ora a jrnz GtTl1 ; (yes, it must be a filename) jmp Usage ; no input file, give usage ; GtTl1: lxi b,11 ; check for ambiguity mvi a,'?' ccir jrnz GtIFl mvi a,8 ; set error code lxi h,MsgAmb ; it's ambiguous jmp ErExit ; GtIFl: lxi h,CpmFcb+1 lxi d,InpFcb+1 ; point to input FCB lxi b,11 ldir ; move filename ; GtIUsr: lda CpmFcb+15 ; check for valid directory ora a jnz InvDir ; (nope) lda CpmFcb ; get driv (A=1) ora a ; is there one? jrnz GtIUs1 ; (yes) call retud ; no, get default disk mov a,b inr a ; make A=1 GtIUs1: dcr a ; make A=0 sta InDrv ; ..and store it lda CpmFcb+13 ; get user sta InUsr ; ..and store it ; call InDU ; set drive/user lxi d,InpFcb call initfcb call f$exist jrnz FilFnd call RevFn call f$exist jrnz FilFnd mvi a,' ' call cout lda InDrv mov b,a lda InUsr mov c,a inx d call PrtFn mvi a,10 ; set error code lxi h,MsgFNF ; file not found jmp ErExit ; FilFnd: call gfa ; check attributes sta AttFlg ; store them bit 0,a ; read-only? jrz SkpQry ; (no) lda OpRFlg ; option R? ora a jrnz SkpQry ; (yes, skip query) lxi h,MsgRO ; say it's read-only call epstr call capin ; get response cpi 'Y' jnz Finish lxi h,MsgYes ; send Yes, CR, LF call epstr lxi d,InpFcb SkpQry: xra a ; reset attributes call sfa lxi h,InpFcb+1 ; move old name to new name lxi d,OutFcb+1 lxi b,11 ldir lxi d,OutFcb call RevFn ; reverse case of new name call initfcb call f$exist ; does new filename exist? jrz RenFil ; (no, rename it) mvi a,' ' call cout lda InDrv mov b,a lda InUsr mov c,a inx d call PrtFn mvi a,4 ; set error code lxi h,MsgFEx ; new file exists jmp ErExit RenFil: lda OpQFlg ; quiet option? ora a jrnz NoPrt1 ; (yes, don't print anything) lxi h,MsgRd ; print the file we're reading call epstr lda InDrv mov b,a lda InUsr mov c,a lxi d,InpFcb+1 call PrtFn lxi h,MsgWrt ; ..and the file we're writing call epstr lda InDrv mov b,a lda InUsr mov c,a lxi d,OutFcb+1 call PrtFn ; NoPrt1: lxi d,InpFcb ; point to old name lxi h,OutFcb ; point to new name call f$rename ; ..and rename file lda AttFlg ; check attributes ora a jrz Finish ; (none) lxi d,OutFcb call sfa ; set them ; Finish: xra a ; reset error flag ErExit: ora a ; error? cnz epstr ; (yes, print message) Exit: call puter2 ; set error code mov b,a ; put error code in B ora a ; do we have one? cnz inverror ; (yes, call error handler) lspd OldStk ; restore old stack pointer ret ; ..and return to CCP ; InvDir: mvi a,2 ; invalid directory lxi h,MsgDir jr ErExit ; ; Subroutines . . . ; ; PrtFn -- Prints drive/user and filename on console ; PrtFn: call stndout mov a,b ; get drive adi 'A' ; make it printable call cout ; ..and print it mov a,c ; get user call pafdc ; ..and print it mvi a,':' call cout call pfn2 ; print filename call stndend ret ; ; EatSpc -- gobbles up spaces and tabs ; EatSpc: mov a,m ora a rz inx h cpi ' ' ; is it a space? jrz EatSpc ; (yes) cpi TAB ; is it a tab? jrz EatSpc ; (yes) dcx h ret ; ; InDU -- sets default drive and user for input file ; InDU: lda InUsr mov c,a lda InDrv mov b,a call logud ret ; ; GetOpt -- checks command tail for user supplied options and sets ; appropriate option flags. ; GetOpt: lda ROFlag ; initialize R option sta OpRFlg lxi h,CpmDma ; point to command tail mov a,m ; anything there? ora a rz ; (no) inx h call EatSpc cpi '/' jz IsSlsh FnLp: inx h ; move past filename mov a,m ora a rz ; (end of tail) cpi ' ' jrz GetOp1 cpi TAB jrz GetOp1 jr FnLp ; GetOp1: call EatSpc ora a rz ; (end of tail) cpi '/' ; is it a slash? jrnz GotOpt ; (no, get options) ; IsSlsh: inx h ; move past slash GotOpt: mov a,m ; get option inx h ora a rz ; (end of tail) cpi ' ' ; space? jrz GotOpt ; (skip it) cpi '/' ; usage request? jrz Usage ; (yes) cpi 'Q' ; quiet flag? jrz OptQ ; (yes) cpi 'R' ; rename read-only files? jrz OptR ; (yes) mvi a,19 ; set invalid option error lxi h,MsgBdO jmp ErExit ; ; Option setting routines ; Usage: lxi h,MsgUse call epstr lxi h,Entry call phl4hc lxi h,MsgUs1 call epstr call prtname lxi h,MsgUs2 call epstr lda OpQFlg ; check quiet mode ora a lxi h,MsgUof cnz epstr lxi h,MsgUon cz epstr lxi h,MsgUs3 call epstr lxi h,MsgDon lda ROFlag ora a cnz epstr lxi h,MsgUs4 call epstr jmp Finish ; OptQ: lda OpQFlg ; get Q flag rar ; get low bit into carry sbb a ; set all 8 bits according to carry cma ; flip sta OpQFlg ; zero it jmp GotOpt ; OptR: lda OpRFlg ; get R flag rar sbb a cma sta OpRFlg ; set it jmp GotOpt ; ; RevFn -- reverses case of a filename ; Entry: D=address of fcb ; Affected: AF,HL ; RevFn: push d ; move pointer to HL pop h inx h ; move pointer to filename mvi b,11 RevFn1: mov a,m ; get character call RevCas ; reverse it mov m,a ; put it back inx h ; advance pointer djnz RevFn1 ret ; ; RevCas -- reverses case of alpha character, preserving high bit ; Entry: A = character ; Exit: A = reversed character ; RevCas: push psw ; save character ani 7Fh ; reset high bit cpi ' ' ; is it control char? jm IsCtrl ; (yes) cpi 7Fh ; or DEL? jrz IsCtrl ; (yes) cpi 'A' ; number or symbol? jm Back ; (yes, skip it) cpi '[' ; is it uppercase? jp NotUpp ; (no) pop psw ; get back character adi 32 ; change uppercase to lowercase ret ; NotUpp: cpi 'a' ; less than 'a' jm Back ; (yes, skip it) cpi '{' ; is it lowercase? jp Back ; (no, skip it) pop psw ; get back character sui 32 ; change lowercase to uppercase ret ; IsCtrl: pop psw ; adjust stack mvi a,'$' ; change control char to '$' ret ; Back: pop psw ; adjust stack ret ; ; PSTR -- forces ZSYSCHK to use EPSTR ; pstr: jmp epstr ; DSEG ; ; Uninitialized storage . . . ; AttFlg: ds 1 ; file attributes flag OpRFlg: ds 1 ; rename read-only flag OpQFlg: ds 1 ; current quiet mode flag InDrv: ds 1 ; input file drive InUsr: ds 1 ; input file user OldStk: ds 2 ; old stack pointer InpFcb: ds 36 ; input file fcb OutFcb: ds 36 ; output file fcb ; end