; RENAME.Z80 ; ; RENAME is used to change the name of one or more files. It permits ; ambiguous filenames and supports an Inspect mode that allows the user ; to confirm each rename before it is done. In addition, there is a ; Control mode which allows the user to manually specify the name for ; each file as it is presented to him. ; Vers equ 37 SubVers equ ' ' ; ; USAGE: ; ; RENAME {dir:}afn1=afn2{,{dir:}afn3=afn4{,...}} {{/}options} ; RENAME {dir:}afn2 afn1{,{dir:}afn4 afn3{,...}} {{/}options} ; RENAME {dir:}afn1{,{dir:}afn3{,...}} {{/}options} ; RENAME {dir:}afn{,{dir:}afn1=afn2{,{dir:}afn4 afn3{,...}}} {{/}options} ; ; The first form shows elements of the CP/M style (dir:newname=oldname). ; The second form shows elements of the MS-DOS style (dir:oldname newname). ; The third form adds the single-filespec (dir:oldname), which automatically ; invokes Control mode allowing the user to rename files individually. ; The forth form shows that all specification types can be intermixed on the ; command line. ; ; OPTIONS: ; ; I Inspect and approve each rename before it is done. ; ; S Include or exclude system files, depending on the ; configuration byte. ; ; E Erase an existing file with the same name without prompting. ; Without this option, RENAME prompts "Exists, Erase?". ; ; R Erase even an existing read-only file with the same name ; without prompting. Without this option, RENAME prompts ; "R/O, Erase?". ; ; Q Toggle current default quiet mode. Defaults to quiet flag, ; if it is on. Otherwise, defaults to configured quiet mode. ; ; HISTORY: ; ; Version 3.7 -- November 17, 1990 -- Howard Goldstein ; Fixed an obscure bug affecting Control mode. ; Version 3.6 -- November 12, 1990 -- Gene Pizzetta and Howard Goldstein ; RENAME's biggest fault was that it erased existing read-only ; files without notice. Now it prompts before erasing R/O files. ; An R option has been added to erase R/O files without prompting. ; A Q option has also been added to toggle the default quiet mode, ; which is controlled by the ZCPR3 quiet flag or a new quiet ; configuration byte. (In fact, all command line options, except ; I, can now be configured as the default mode with ZCNFG.) Since ; ZSDOS preserves file attributes automatically, RENAME pays no ; attention to the attributes unless the file is read-only or ; the DOS is ZRDOS or DRI's BDOS. This results in a significant ; speed-up under ZSDOS (and under Z3PLUS, which also preserves ; attributes). In no case, however, is the PUBLIC attribute (F2) ; preserved because it could be dangerous to do so. RENAME now ; displays the DU specification with each filename so you can be ; confident which directory it is working in. A few minor bugs ; have been swatted and the code has been streamlined. ; ; Version 3.5 -- July 1, 1990 -- Gene Pizzetta ; Changed filename display to "oldfile to newfile" instead of the ; strange "newfile from oldfile". Added configuration byte after ; ASCII string 'SYSFILES>' to chose whether to include system files ; by default (non-zero) or exclude them by default (0). S option ; now toggles the default meaning (it's current action is shown by ; the usage screen. Now filters high bit of filenames for terminals ; that display special characters that way. At the suggestion of ; Howard Goldstein, RENAME no longer signs on with its load address ; and version number; these are displayed only on the usage screen. ; Restored Q (quit) as a valid response to an rename or erase query, ; but ^C still works. Display has been made even more compact than ; last version. Many of these changes are to make the RENAME ; interface very similar to the RCP version. Sets program error ; flag to 10 if a matching filename is not found. If an invalid ; option is given, the program error flag is set to 19 and the ; error handler is invoked. ZEX input is suspended during execution ; of RENAME. The number of files renamed (up to 255) is placed in ; ZCPR3 register 0. Now obeys ZCPR3 quiet flag, except when in ; inspect or control mode, or when a prompt is necessary. Removed ; Wheel byte protection for E and S options. ; ; Version 3.4 -- March 31, 1990 -- Gene Pizzetta ; Modified for more compact display, usually a single line for each ; file renamed. ^C aborts at any prompt. ; ; Version 3.3A -- December 30, 1987 -- Bruce Morgen ; Strip high bit from EFCB program name characters. "E" and "S" ; options require Wheel byte set; help message reflects this. ; ; Version 3.3 -- December 19, 1987 -- Bruce Morgen ; Help message now reflects actual COM file name used, PPIP-style ; dual syntax implemented (as requested by Ken Taschner). This ; required some rather tricky parsing to support the single-filespec ; syntax "afn.typ [/]c", so while I was at it I made control mode ; mandatory and automatic for single-filespec elements and eliminated ; the C option letter altogether (as Rick says: "it only makes ; sense"...). In order support this single-filespec mode when such ; an element is the last (or only) one in a RENAME command line, the ; second file-spec in the last (or only) command is tested if the ; MS-DOS syntax is detected. If that second filespec starts with a ; "/" or includes only valid option letters (and no more characters ; than the number of valid option letters) it is assumed to be an ; option specifier rather than a rename-to filespec. Following ; Howard Goldstein's (LX17 & 18) lead, filespec-to-FCB parsing calls ; the Z33 CCP if it's available. A Z80, HD64180, NSC800 or (someday?) ; Z280 CPU now is required. ; ; Version 3.2 -- August 25, 1987 -- Jay Sage ; Changed to allow a leading slash before an option to make program ; consistent with a number of other Z programs (this was supposed to ; happen, but there was a bug in the code). Put data into a DSEG. ; Made header indicate load address. ; ; Version 3.1 -- April 12, 1987 -- Jay Sage ; Took idea of Rick Charnes and implemented it as an option so that ; one does not have to have two versions of the program. The option ; is 'E'. Also updated code to ZCPR33 type-3 environment to allow ; linking RENAME for execution in high memory if desired. ; ; Version 3.0a -- April 9, 1987 -- Rick Charnes ; I have modified this source code slightly so that if you try to ; rename FILE1 to FILE2 and FILE2 already exists, the program will ; NOT ask you if you are sure you want to delete FILE2. It just ; goes ahead and deletes the darn thing and renames FILE1. I had ; an application for it, studied and little and ... it works. Be ; careful, though. This is a special use program, and NOT for ; everyday use. I found an alias in which I needed it. ; ; Version 3.0 -- May 18, 1984 -- Richard Conn ; Version 2.0 -- January 16, 1983 -- Richard Conn ; Version 1.4 -- January 6, 1983 -- Richard Conn ; Version 1.3 -- December 7, 1982 -- Richard Conn ; Version 1.2 -- November 10, 1982 -- Richard Conn ; Version 1.1 -- October 26, 1981 -- Richard Conn ; RENAME.ASM. ; .request z3lib,syslib ; ext z3init,z33chk,z33fname,zfname,z3log,prtname,puter2,putreg ext inverror,getquiet,stopzex ext dirq,f$delete,f$rename,bbline,initfcb,bdos,retud,putud,getud ext phl4hc,phlfdc,eprint,epstr,cout,cin,caps,crlf,codend ; ; General equates ; CpmFcb equ 5Ch ; file control block CpmDma equ 80h ; input line buffer ESize equ 16 ; size of dir entry (from SYSLIB DIRQ routine) Z3Env equ 0FE00h ; environment address ; ; BDOS functions ; CpmVer equ 12 ; get CP/M version FSrchF equ 17 ; search first SetAtr equ 30 ; set file attributes DosVer equ 48 ; get extended DOS version ; ; ASCII characters ; CtrlC equ 03h ; ^C BEL equ 07h ; bell BS equ 08h ; backspace LF equ 0Ah ; linefeed CR equ 0Dh ; carriage return ; ; Type 3 header -- Code modified as suggested by Charles Irvine to function ; correctly with interrupts enabled. Program will abort with an error message ; when not loaded to the correct address (attempt to run it under CP/M or Z30). ; Entry: jr Start0 ; must use relative jump nop ; filler db 'Z3ENV',3 ; type-3 environment Z3EAdr: dw Z3Env ; filled in by Z33 dw Entry ; intended load address ; ; Configuration area . . . ; db 'RENAME' ; for ZCNFG db Vers/10+'0',Vers mod 10+'0' QtFlag: db 0 ; FFh=default to quiet mode SysFlg: db 80h ; 80h=exclude system files, C0h=include EraFlg: db 0 ; FFh=erase existing files without prompting ROFlag: db 0 ; FFh=erase R/O files without prompting ; Start0: ld hl,0 ; point to warmboot entry ld a,(hl) ; save the byte there di ; protect against interrupts ld (hl),0C9h ; replace warmboot with a return opcode rst 0 ; call address 0, pushing RETADDR ; ..onto stack RetAddr: ld (hl),a ; restore byte at 0 dec sp ; get stack pointer to point dec sp ; to the value of RETADDR pop hl ; get it into HL and restore stack ei ; we can allow interrupts again ld de,RetAddr ; this is where we should be xor a ; clear carry flag push hl ; save address again sbc hl,de ; subtract -- we should have 0 now pop hl ; restore value of RETADDR jr z,Start ; if addresses matched, begin real code ; ld de,NotZ33Msg-RetAddr ; offset to message add hl,de ex de,hl ; switch pointer to message into DE ld c,9 jp 0005h ; return via BDOS print string function NotZ33Msg: db 'Not Z33+$' ; abort message if not Z33-compatible ; ; Start of program . . . ; Start: ld (Stack),sp ; save stack call codend ld (CmdLne),hl ; setup command line buffer inc h ; buffer size ld (NTFcb),hl ; set temp FCB inc h ld (DirBuf),hl ; pointer to dir buffer ld sp,hl ; new stack pointer ld de,-100h+40 ; set 2nd FCB add hl,de ld (OFcb),hl ; ld hl,(Z3EAdr) ; point to ZCPR3 environment call z3init ; initialize environment call putud ; save current user/disk away call stopzex ; suspend ZEX input ; Initialize option flags ld hl,0 ; zero file count ld (FilCnt),hl ld de,OpIFlg ; point to inspect flag xor a ld (de),a ; no inspect mode inc de ld (de),a ; no control mode inc de ; point to quiet flag call getquiet ; is quiet flag set? rra ; make it FFh or 0 sbc a,a jr nz,SetQt ; (yes) ld a,(QtFlag) ; check configuration byte SetQt: ld (de),a ; ..and store in option flag inc de ld (de),a ; ..and second flag inc de ; point to remaining flags ld hl,SysFlg ; ..and move defaults ld bc,3 ldir ; ld a,(CpmFcb+1) ; get first character of filename cp ' ' ; no file spec? jr z,Usage cp '/' ; option caught? jp nz,RCont ld a,(CpmFcb+2) cp '/' ; help? jp nz,RCont ; (no) ; ; Print help information ; Usage: call eprint db 'RENAME Version ' db Vers/10+'0','.',(Vers mod 10)+'0',SubVers,' (loaded at ',0 ld hl,Entry call phl4hc call eprint db 'h)',CR,LF db 'Usage:',CR,LF db ' Old style: newname=oldname',CR,LF,' ',0 call prtname call eprint db ' {dir:}afn.aft=',0 call PrtOpt call eprint db ' New style: oldname newname',CR,LF,' ',0 call prtname call eprint db ' {dir:}afn.aft ',0 call PrtOpt call eprint db ' Interactive mode: oldname',CR,LF,' ',0 call prtname call eprint db ' {dir:}',0 call PrtOpt call eprint db ' Forms may be mixed in command line.',CR,LF db 'Options:',CR,LF db ' I Inspect mode (confirm each rename).',CR,LF db ' E ',0 ld a,(EraFlg) or a call nz,PrtNot call eprint db 'Erase existing',0 call PrtFWA call eprint db ' R ',0 ld a,(ROFlag) or a call nz,PrtNot call eprint db 'Erase even R/O',0 call PrtFWA call eprint db ' S ',0 ld a,(SysFlg) bit 6,a jr nz,Usage3 call eprint db 'In',0 jr Usage4 Usage3: call eprint db 'Ex',0 Usage4: call eprint db 'clude system files.',CR,LF db ' Q Toggle quiet mode o',0 ld a,(OpQFlg) or a jr nz,Usage5 call eprint db 'n.',0 jr Exit Usage5: call eprint db 'ff.',0 ; ; Return to operating system ; Exit: xor a ; zero the error code ErExit: call puter2 ; set program error flag ld b,a ; get error code to B or a jr z,NoEH cp 10 ; no files found? call nz,inverror ; (no, call error handler) NoEH: ld sp,(Stack) ; get old stack ret ; PrtNot: call eprint db 'Don''t ',0 ret PrtFWA: call eprint db ' files without asking.',CR,LF,0 ret PrtOpt: call eprint db 'afn.aft{,...} {{/}options}',CR,LF,0 ret ; ; Copy CpmDma buffer into temporary buffer ; RCont: ld de,(CmdLne) ; point to command line save buffer ld hl,CpmDma+1 ; point to CP/M DMA buffer push de ld bc,80h ; buffer size ldir ; copy into command line buffer ; ; Skip to filename string ; pop hl ld a,(CpmDma) ld c,a add hl,bc ld a,',' cpdr jr z,GComma CommaZ: ld hl,(CmdLne) jr NComma GComma: inc hl inc hl NComma: ld de,ArgTbl ld a,3 ld (de),a xor a call Argv jp nz,Usage inc de ld a,(de) cp 3 jr z,TriArg cp 2 jr nz,ChkQt ld hl,(Argum2) dec hl ld a,(hl) inc hl sub '=' jr z,ChkQt call OptAI jr nz,ChkQt dec hl ld (hl),a inc hl jr GetOpt TriArg: ld hl,(Argum3) ld a,(hl) ; ; Check for leading slash on option and skip it if so ; cp '/' ; option character? jr nz,GetOpt inc hl ; skip slash ; ; Process list of options ; GetOpt: ld a,(hl) ; get byte or a ; done? jr z,ChkQt inc hl ; point to next character ld de,GetOpt ; get return address push de ; push onto stack cp ' ' ; skip over spaces ret z cp 'E' ; erase old files? jr z,OptE cp 'R' ; erase R/O files? jr z,OptR cp 'I' ; inspect? jr z,OptI cp 'Q' ; quiet? jr z,OptQ cp 'S' ; system files? jr nz,InvOpt ; ; Set system files selection ; ld de,OpSFlg ; check default ld a,(de) xor 40h ; flip between 80h and C0h ld (de),a ret ; ; We have an invalid option ; InvOpt: call eprint db ' Invalid option.',0 pop de ; clean up stack ld a,19 jp ErExit ; ; Set inspect option ; OptI: ld a,0FFh ; inspect mode ld (OpIFlg),a ret ; ; Set auto erase option ; OptE: ld de,OpEFlg ; auto erase mode ld a,(de) cpl ld (de),a ret ; ; Set erase read-only option ; OptR: ld de,OpRFlg ; auto erase read-only ld a,(de) cpl ld (de),a ret ; ; Toggle quiet option ; OptQ: ld de,OpQFlg ; flip quiet mode ld a,(de) cpl ld (de),a inc de ld (de),a ret ; ; If inspect mode, turn off quiet mode. ; ChkQt: ld a,(OpIFlg) or a jr z,DSpec xor a ld (OpQFlg),a ; ; Extract disk, user, and filename information ; DSpec: ld hl,(CmdLne) ; point to first byte DSpec0: inc hl ; point to byte ld a,(hl) ; get byte cp ' ' ; space? jr z,DSpec0 jr DSpec2 ; ; Major re-entry point when file specs are separated by commas. ; HL points to first byte of next file spec ; DSpec1: ld a,(CtlFlg) ld b,a ld a,(OpQFlg) or b call z,crlf ; only if not quiet and not control mode jr z,DSpec2 ; ; The previous operation may have been in Control mode. If we are not ; also in Inspect mode, we need to set the Quiet mode flag to its original ; value. ; ld a,(OpIFlg) or a jr nz,DSpec2 ld a,(AQtFlg) ld (OpQFlg),a ; DSpec2: xor a ld (CtlFlg),a call getud ; reset user if necessary ld de,(NTFcb) ; point to FCB in DE call ParsIt ; extract filename to FCB, get disk and user ld (NxtChr),hl ; save pointer to delimiter which ended scan call z3log ; log into DU ; ; First name is now extracted -- extract possible second name ; ld de,(OFcb) ; point to FCB for 2nd name ld hl,(NTFcb) ; point to first name ld bc,16 ; copy 16 bytes ldir ld hl,(NxtChr) ; point to character which ended parse ld a,(hl) ; get it cp '=' ; assignment? jr z,GotEqu cp ' ' ; reverse assignment? jr z,GotEqu ld a,0FFh ; set for control mode ld (CtlFlg),a xor a ; ..and reset quiet flag ld (OpQFlg),a jr RenSet ; GotEqu: push af inc hl ; point to character after '=' or space ld de,(OFcb) ; point to temporary FCB call ParsIt ; extract filename into FCB, get disk and user ld (NxtChr),hl ; save pointer to delimiter which ended scan pop af cp '=' jr z,RenSet ld hl,(OFcb) ; swap pointers for MS-DOS "style" ld de,(NTFcb) ld (OFcb),de ld (NTFcb),hl ; ; Load directory and rename files ; RenSet: ld de,(OFcb) ; point to FCB ld hl,(DirBuf) ; point to end of code ld a,(OpSFlg) ; set flags call dirq ; load DIR, select files, pack, and alphabetize ; ; Rename DIR files; HL points to first file, BC=file count ; call RenamF ; ; Check for next file spec ; ld hl,(NxtChr) ; get pointer ld a,(hl) ; get delim inc hl ; point to next character cp ',' ; another file? jp z,DSpec1 ; continue processing ; ; Rename complete ; call PrtCnt ; print file count ld hl,(FilCnt) ; get count ld a,l ; check for none or h jp nz,Exit ld a,10 jp ErExit ; ; Rename selected files ; RenamF: ld a,b ; check for any files loaded or c ret z jr RenLp1 ; ; Print filename ; RenLp: ld a,(CtlFlg) ld d,a ld a,(OpQFlg) or d call z,crlf ; only if not quiet and not control mode RenLp1: push bc ; save entry count push hl ; save pointer to FCB ld hl,(NTFcb) ; copy new template into RenFcb ld de,RenFcb push de ld bc,16 ldir pop de pop hl ; get pointer push hl ; save pointer ld (hl),0 ; clear drive byte ld b,11 ; 11 bytes to FN and FT RenLp2: inc hl ; point to next character inc de ld a,(de) ; get character of new file cp '?' ; change '?' to old character jr nz,RenLp3 ld a,(hl) ; get old character and 7Fh ; mask old character ld (de),a ; store it away as new RenLp3: djnz RenLp2 ; count down ld a,(OpQFlg) ; check quiet mode or a jr nz,RenLp5 ; don't print anything ; RenLp4: pop hl ; point to old filename push hl call PrDU ; print DU and old filename ld a,(CtlFlg) ; check for control mode or a jr nz,RenLp5 ; don't print new name if control mode call eprint db ' to ',0 ld hl,RenFcb ; point to new filename call PrFn ; print new filename ; ; Check for control mode and perform control function if flag set ; RenLp5: ld a,(CtlFlg) ; get control mode flag or a ; NZ= yes jr nz,RenCtl ; ; Check for inspection and inspect if set ; ld a,(OpIFlg) ; get flag or a ; 0=no jr z,RenIt ; ; Prompt user for rename ; ld hl,MsgAsk ; rename question call AskIt1 jr z,RenIt ; (yes) ; ; Don't rename file ; RenNo: ld a,(CtlFlg) or a jp z,RenTst call eprint db ' Not Renamed',CR,LF,0 jp RenTst ; ; Control function -- allow user to rename as he desires ; RenCtl: call eprint db ' New Name (=Skip)? ',0 ld a,0FFh ; capitalize call bbline ; input line from user call crlf or a ; check for just carriage return jr nz,RCtrl0 jr RenNo ; proceed with next entry RCtrl0: ld de,RenFcb ; place into new name FCB call ParsIt ; just extract name ld bc,11 ; check for any wild characters RCtrl1: inc de ; point to next character ex de,hl ; in hl ld a,'?' ; can't be wild cpir jr nz,RenIt ; done -- perform rename ; WildEr: call eprint db bel,cr,lf,' No Wild Cards,',0 jr RenCtl ; ; Rename file; old name pointer on stack, new name in RenFcb ; Step 1 -- Determine if new name already exists ; RenIt: ld de,RenFcb ; point to new name call initfcb ld c,FSrchF ; does it already exist? call bdos ld b,a ; save location offset in B inc a ; exists? jr z,RenIt2 ; (no) ; ld a,(OpRFlg) ; unprompted read-only erase? or a jr nz,RenIt0 ; (yes, erase everything) ld a,(OpEFlg) ; unprompted erasing in effect? or a jr nz,DelOld ; (yep, if it's read-write) ld hl,MsgEra call AskIt jp nz,RenNo ; not yes, so assume no ld a,(CtlFlg) or a call nz,crlf ; ; check for R/O before doing anything on new filename, and prompt ; DelOld: ld a,b ; get back offset rrca rrca rrca add a,CpmDma+9 ld l,a ld h,0 bit 7,(hl) jr z,RenIt1 ; (no) ld hl,MsgRO call AskIt jp nz,RenNo ; not yes, so assume no RenIt0: ld hl,9 add hl,de ; point to T1 res 7,(hl) ; reset R/O bit ld c,SetAtr call bdos RenIt1: call f$delete ; delete file RenIt2: pop hl ; HL points to old name ; ; Check and clear R/O attribute on old filename ; push hl ; save pointer to old name ld de,(OFcb) ; copy old name push de ld bc,16 ldir pop de ; ld hl,9 ; point to T1 add hl,de ld a,(hl) and 80h ld (FAttr),a ; save attribute jr z,NotRO ; (not read-only) res 7,(hl) ld c,SetAtr ; make it read/write call bdos ; ; Do the rename ; NotRO: ld hl,RenFcb ; point to new name call f$rename ; rename file ; ; Restore R/O attribute, if necessary. Restore ALL attributes under ZRDOS. ; ld c,CpmVer ; get DOS version call bdos cp 30h jr nc,IsZS ; (must be CP/M 3) ld c,DosVer call bdos ld a,h or a jr z,IsZR ; (must be ZRDOS or DRI BDOS) IsZS: ld a,(FAttr) ; was old file read-only? or a jr z,NotRO2 ; (no) IsZR: pop de ; get pointer to old fcb push de ; ..and save it again inc de ; point to filename ld hl,RenFcb+1 ; point to new filename call RstAtr ; ..and restore attributes ld de,RenFcb ld c,SetAtr call nz,Bdos NotRO2: ld hl,(FilCnt) ; increment file count inc hl ld (FilCnt),hl ; ; Point to next entry ; RenTst: pop hl ; get pointer to directory entry ld de,ESize ; point to next entry add hl,de pop bc ; get count dec bc ; count down ld a,b ; check for zero or c jp nz,RenLp ret ; ; AskIt -- Prompts user. Pointer to prompt string in HL. ; AskIt: ld a,(OpQFlg) or a jr z,AskIt1 call crlf push hl ld hl,RenFcb call PrDU pop hl AskIt1: call epstr call cin ; get response call caps cp 'Y' jr z,AskIt2 cp 'Q' ; quit? jr z,Quit cp CtrlC ret nz ld a,'Q' Quit: or a AskIt2: call cout ret z call PrtCnt ; print count of files renamed and exit jp Exit ; MsgEra: db bel,' Exists, erase? N',BS,0 MsgRO: db bel,' R/O, erase? N',BS,0 MsgAsk: db ' Rename (Y/N/Q)? N',BS,0 ; ; AI (allegedly intelligent) routine to check for a string ; containing legal option letters ONLY. ; OptAI: ld a,(hl) sub '/' ; slash is explicit option delim jr nz,NoSlsh ; if not slash, do character check ld (hl),a ; if slash, null it out (A = 0) dec hl ld (hl),a ; null out leading space inc hl ; adjust pointer to options inc hl ret ; return with Z flag ; NoSlsh: ld d,h ; copy into DE ld e,l xor a ; search for terminating null ld bc,OptLen ; range for search cpir ; do short search jr z,MatAI ; found null, proceed ex de,hl ; otherwise too long for options ret ; return with NZ ; MatAI: push de dec de BLoop: inc de ld a,(de) or a jr z,DoneAI ; end of string, return with Z ld b,OptLen ld hl,OptLtr LLoop: cp (hl) jr z,BLoop inc hl djnz LLoop ; if B ticks down, a failure! dec b ; cheap NZ return ; DoneAI: pop hl ret ; OptLtr: db 'EIRSQ' OptLst: ds 0 OptLen equ OptLst-OptLtr ; ; SYSLIB Module Name: SARGV ; Author: Richard Conn ; SYSLIB Version Number: 3.6 ; Module Version Number: 1.1 ; public argv ; ARGV is a UNIX-style ARGC/ARGV string parser. It is passed ; a null-terminated string in HL and the address of a token pointer ; table in DE as follows: ; LXI H,STRING ; LXI D,ARGV$TABLE ; MVI A,0 ; do not mark token end ; CALL ARGV ; JNZ TOKEN$OVFL ; indicates more tokens than allowed ; ... ; ARGV$TABLE: ; DB maxent ; max number of entries permitted ; DS 1 ; number of entries stored by ARGV ; DS 2 ; pointer to token 1 ; DS 2 ; pointer to token 2 ; ... ; DS 2 ; pointer to token maxent ; Tokens are delimited by spaces and tabs. ; As well as '='. ; 27 Feb 86, jww ; Completed Joe's mod. by adding "=" to "SkSp:" as well as "SkNSp:" ; December 19, 1987, Bruce Morgen ; On input, if A=0, the end of each token is not marked with a null. ; If A<>0, a null is placed after the last byte of each token. ; If all went well, return with A=0 and Zero Flag set. If there ; are possibly more tokens than pointers, return with A=0FFH and NZ. ; Argv: push bc ; save regs push de push hl ld c,a ; save mark flag ex de,hl ld b,(hl) ; get max entry count push hl ; save address of max entry count inc hl ; point to token count inc hl ; point to first pointer ; ; On each loop, DE = address of next character in string and HL = address of ; next pointer buffer; B = number of pointer buffers remaining and C = ; mark flag (0 = no mark) ; Loop: call SkSp ; skip spaces and tabs in string pointed to by DE or a ; end of string? jr z,Done ld (hl),e ; store low inc hl ld (hl),d ; store high inc hl dec b ; count down jr z,Loop2 call SkNSp ; skip until end of token or a ; done? jr z,Done ld a,c ; get mark flag or a ; 0=no mark jr z,Loop1 xor a ; mark with null ld (de),a ; store null inc de ; point to next character Loop1: ld a,b ; check count or a jr nz,Loop ; continue on Loop2: call SkNSp ; skip over token call SkSp ; any tokens left? or a jr z,Done ; none if EOL or 0FFh ; make A = 0FFH to indicate more to come Done: pop hl ; get address of max token count push af ; save return flags ld a,(hl) ; get max token count sub b ; subtract counter inc hl ; point to return count ld (hl),a ; set return count pop af ; get return flag pop hl ; restore regs pop de pop bc ret ; ; Skip over space or tab characters ; SkSp: ld a,(de) ; get character and 7Fh ; mask inc de ; point to next cp ' ' ; continue if space jr z,SkSp cp 9 ; continue if tab jr z,SkSp cp '=' jr z,SkSp dec de ; point to character ret ; ; Skip over non-space and non-tab characters ; Added '=' so that A:=B: construct yields two arguments. v1.1 jww ; SkNSp: ld a,(de) ; get character and 7Fh ; mask ret z ; done if null cp ' ' ret z ; done if space cp 9 ret z ; done if tab cp '=' ret z ; new delimiter inc de ; point to next jr SkNSp ; ; End of ARGV inclusion ; ; Print count of files renamed ; PrtCnt: ld hl,(FilCnt) ; get count ld b,0 ; setting ZCPR3 register 0 ld a,l call putreg ld a,(AQtFlg) ; even in inspect and control modes or a ret nz ld a,(CtlFlg) or a call z,crlf ld a,h or l jr nz,PrtNbr call eprint db 'No',0 ; PrtNbr: call nz,phlfdc call eprint db ' File',0 ld a,h or a jr nz,PrtS ld a,l ; low one? cp 1 PrtS: ld a,'s' ; add 's' if more than one call nz,cout call eprint db ' Renamed',0 ret ; ; Print current DU ; PrDU: ld a,' ' call cout call retud ld a,b add a,'A' call cout push hl ; save pointer ld l,c ld h,0 call phlfdc pop hl ld a,':' call cout ; ; Print filename pointed to by HL ; PrFn: inc hl ; point to filename ld b,8 ; print name call PrtIt ld a,'.' ; decimal call cout ld b,3 ; print type ; PrtIt: ld a,(hl) ; get character and 07Fh ; reset high bit cp ' ' ; skip spaces call nz,cout inc hl ; point to next djnz PrtIt ; count down ret ; ; Parse filename -- use Z33 parser, if available ; ParsIt: call z33chk jr nz,Pars1 call z33fname push hl ld hl,15 add hl,de ld a,(hl) pop hl or a ret z call eprint db ' Invalid directory.',0 ld a,2 jp ErExit ; Pars1: xor a jp zfname ; ; Restore file attributes. Return with Z set if original name had no ; attributes set. Under CP/M 3 PUBLIC (F2) attribute is preserved and ; WHEEL (F8) attribute is always reset by the system. ; RstAtr: ld c,0 ; init attribute set flag call MovAtr ; F1 inc hl ; skip PUBLIC (F2) inc de call MovAtr ; DATESTAMP (F3) call MovAtr ; F4 inc hl ; skip F5, F6, and F7 inc hl inc hl inc de inc de inc de ld b,4 RALoop: call MovAtr ; WHEEL (F8), READ-ONLY (T1), SYSTEM (T2), djnz RALoop ; ..and ARCHIVE (T3) ret ; MovAtr: ld a,(de) ; byte from old name and 80h ; strip bits 0-6 or (hl) ; mask in byte from new name ld (hl),a ; ..and store in new name rla ; shift attribute bit thru carry rl c ; ..into C (attribute flag) inc hl ; point to next byte inc de ret ; ; Uninitialized buffers and data . . . ; DSEG ; ArgTbl: ds 1 ; maxent ds 1 ds 2 Argum2: ds 2 Argum3: ds 2 OpIFlg: ds 1 ; inspect flag (0=no, FFh=yes) CtlFlg: ds 1 ; control flag (0=no, FFh=yes) OpQFlg: ds 1 ; quiet flag (FFh=quiet) AQtFlg: ds 1 ; absolute quiet flag (even inspect mode) OpSFlg: ds 1 ; system flag (80h=exclude, C0h=include) OpEFlg: ds 1 ; unprompted erasure of existing file (0=no) OpRFlg: ds 1 ; unprompted read-only erasure (0=no) FAttr: ds 1 ; attribute flag of current file NxtChr: ds 2 ; pointer to next character in command line FilCnt: ds 2 ; count of number of files renamed RenFcb: ds 40 ; FCB for renaming OFcb: ds 2 ; FCB for old filename and old file template NTFcb: ds 2 ; FCB for new file template CmdLne: ds 2 ; pointer to command line buffer DirBuf: ds 2 ; pointer to directory buffer Stack: ds 2 ; old stack pointer ; end