; UNJUST.MAC ; Vers equ 12 ; version number SubVers equ ' ' ; modification level ; ; Replaces multiple white-space characters in text files with a single ; space. For ZCPR3 only. ; ; USAGE: ; ; UNJUST {dir:}infile {dir:}{outfile} {{/}options} ; ; If no outfile name is given, it will have the same name as the infile. ; If a file exists with the same name as the outfile, it will be renamed ; to filetype BAK. ; ; UNJUST replaces strings of hard and soft spaces and tabs with a single ; hard space (20h), except two hard spaces are enforced after periods, ; question marks, and exclamation points. Leading and trailing spaces ; on a line are eliminated completely. Blocks of text delimited by a ; special tag character (^P) will be copied without changes. ; ; OPTIONS: ; ; T Leaves a single trailing space (except two spaces after ; a period, question mark, or exclamation point) at the ; end of lines that have existing trailing spaces. ; ; 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. ; ; For more information, see accompanying documentation file. ; ; Version 1.2 -- November 23, 1990 -- Gene Pizzetta ; Increased size of input buffer and made several other changes to ; speed up processing. Now removes trailing spaces on a line. ; T option allows leaving a single trailing space on lines where ; trailing spaces already exist (for ZDE compatibility). Also ; enforces two spaces after a question mark and exclamation point. ; Now properly handles files that do not end with a ^Z. Corrected ; bug that caused to sectors of ^Z's to be added to a file if it ; ended exactly on a sector boundary. Implemented several suggestions ; from Howard Goldstein to improve the code. ; ; Version 1.1 -- October 5, 1990 -- Gene Pizzetta ; Corrected bugs that caused unpredictable destination for outfile if ; no filespec was given and a jump to the wrong error routine if the ; input file was not found. Now checks for sufficient TPA space. ; Several other code optimizations, mostly at the suggestion of ; Howard Goldstein. (Thanks, Howard.) ; ; Version 1.0 -- September 22, 1990 -- Gene Pizzetta ; Initial release. ; ; Gene Pizzetta ; 481 Revere Street ; Revere, MA 02151 ; ; Newton Centre Z-Node: (617) 965-7259 ; Ladera Z-Node Central: (213) 670-9465 ; GEnie: E.PIZZETTA ; Voice: (617) 284-0891 ; ; System addresses . . . ; Bdos equ 05h CpmFcb equ 5Ch AltFcb equ 6Ch CpmDma equ 80h TPA equ 100h ; ; ASCII characters . . . ; CtrlC equ 03h ; ^C TAB equ 09h ; tab LF equ 0Ah ; linefeed CR equ 0Dh ; carriage return SCR equ 08Dh ; soft carriage return SSpace equ 0A0h ; soft space Dot equ 2Eh ; period HDot equ 0AEh ; period with high bit set CpmEof equ 1Ah ; CP/M end-of-file character (^Z) ; ; The following buffer sizes are in sectors (records) of 128 bytes. ; They may be set to any number of sectors up to a maximum of 256 (32K). ; Of course, you can't have two buffers of 32K if you plan to have ; UNJUST and your operating system in memory at the same time. ; InSiz equ 128 ; input buffer in sectors (128=16K) OutSiz equ 128 ; output buffer in sectors (128=16K) ; ; Following routines are from ZSLIB, VLIB, Z3LIB, and SYSLIB ; .request zslib,vlib,z3lib,syslib ; ext getstp,setstp ext stndout,stndend ext z3vinit,zsyschk,getquiet,gzmtop,prtname,puter2,inverror ext f$exist,f$open,f$make,f$rename,f$delete,f$close,f$read ext f$write,initfcb,setdma,codend,retud,logud,condin,cout ext epstr,pfn2,pafdc,phlfdc ; public pstr ; jp Start ; db 'Z3ENV' db 1 Z3EAdr: dw 0FE00h ; address of environment descriptor ; ; Configuration . . . ; dw 0 ; filler db 'UNJUST' ; for ZCNFG db Vers/10+'0',Vers mod 10+'0' QtFlag: db 0 ; FFh=default to quiet mode TSFlag: db 0 ; FFh=preserve trailing spaces TagChr: db 'P'-'@' ; tag for protected blocks ; ; Messages . . . ; MsgUse: db 'UNJUST Version ' db Vers/10+'0','.',Vers mod 10+'0',SubVers,CR,LF db 'Removes multiple white-space characters.',CR,LF db 'Usage:',CR,LF,' ',0 MsgUs1: db ' {dir:}infile {dir:}{outfile} {{/}options}',CR,LF db 'An input filename is required.',CR,LF db 'Text delimited by tag character (',0 MsgUs2: db ') is not changed.',CR,LF db 'Options:',CR,LF db ' T ',0 MsgUs3: db 'Preserve trailing spaces.',CR,LF db ' Q Toggle quiet mode o',0 MsgUon: db 'n.',0 MsgUof: db 'ff.',0 MsgDnt: db 'Don''t ',0 MsgRd: db ' Unjustifying ',0 MsgWrt: db ' to ',0 MsgDot: db ' .. ',0 MsgNSr: db ' No source file.',0 MsgFNF: db ' File not found.',0 MsgWEr: db ' Disk full!',0 MsgNSp: db ' No directory space.',0 MsgCEr: db ' Close error.',0 MsgAmb: db ' Ambiguous filename.',0 MsgDir: db ' Invalid directory.',0 MsgBdO: db ' Invalid option.',0 MsgMem: db ' Insufficient memory.',0 MsgAbt: db ' Aborted.',0 MsgDne: db ' spaces removed.',0 ; Start: ld hl,(Z3EAdr) ; set up environment call zsyschk ; is this a Z-system? ret nz ; (nope) call z3vinit ld (OldStk),sp ; save old stack pointer call gzmtop ; get top of memory ld sp,hl ; ..and set up new stack push hl ; save top of memory ; call codend ; set buffer addresses ld (InBuf),hl ld de,128*InSiz add hl,de ld (OutBuf),hl ld de,128 ; add stack size and safety buffer add hl,de ex de,hl ; put in DE pop hl ; recover top of memory in HL or a sbc hl,de ; determine memory size ld a,h ; put number of pages in A cp OutSiz/2 ; compare to buffer size jr nc,Start1 ; (TPA okay) ld a,12 ; set error code ld hl,MsgMem ; insufficient memory jp ErExit ; Start1: call getquiet ; is ZCPR quiet flag set? rra ; make it 0 or FF sbc a,a jr nz,Start2 ; (yes) ld a,(QtFlag) ; no, get quiet config byte Start2: ld (OpQFlg),a ; ..and store in Q option flag ld a,(TSFlag) ; move trailing space flag to option flag ld (OpTFlg),a ld hl,0 ; clear space character counter ld (SpcCnt),hl ld hl,CpmDma ; see if there's a tail ld a,(hl) or a jp z,Usage ; (no) call GetOpt ; get options ; Check for input file specification ld a,(FSFlag) ; any filespec? or a jp z,Usage ; (nope) ld a,(CpmFcb+1) ; check input filename cp ' ' ; is there one? jp nz,Start3 ; (yep) ld hl,MsgNSr ; source file required ld a,8 ; set error code jp ErExit ; Start3: ld hl,CpmFcb+1 ; check for ambiguous name call ChkAmb MovInp: ld hl,CpmFcb+1 ; move filename to input fcb ld de,InFcb+1 ld bc,11 ldir ld a,(CpmFcb+15) ; check for valid directory or a jp nz,InvDir ; (nope) ld a,(CpmFcb) ; get drive (A=1) or a ; is there one? call z,GetDft ; (no, get default) dec a ; make A=0 ld b,a ; put drive in B ld a,(CpmFcb+13) ; get user ld c,a ; put user in C ld (InUsr),bc ; store user and drive ; Check for output file specification ld a,(FSFlag) dec a jr z,MovOut ; (no output filespec) ld a,(AltFcb+1) cp ' ' ; do we have an output filename? jr z,MovOut ; (no) ld hl,AltFcb+1 ; check for ambiguous name call ChkAmb ld hl,AltFcb+1 ; okay, move filename jr MovFn ; MovOut: ld hl,CpmFcb+1 ; move input filename to output fcb MovFn: ld de,OutFcb+1 ld bc,11 ldir ld a,(AltFcb+15) ; check for valid directory or a jp nz,InvDir ; (nope) ld a,(AltFcb) ; get drive (A=1) or a ; is there one? call z,GetDft ; (no, get default) dec a ; make A=0 ld b,a ; put drive in B ld a,(AltFcb+13) ; get user ld c,a ; put user in C ld (OutUsr),bc ; store user and drive ld hl,OutFcb+1 ; save real output filename ld de,OutFn+1 ld bc,11 ldir ld hl,TmpTyp ; make filetype $$$ ld de,OutFcb+9 ld bc,3 ldir ; ld a,(OpQFlg) ; quiet option? or a ld hl,MsgRd ; print the file we're reading call z,epstr ld bc,(InUsr) ; B=drive, C=user ld de,InFcb+1 call z,PrtFn call OpnInp ; open input file call GetIni ; initialize GetC ; ld a,(OpQFlg) ; quiet option? or a ld hl,MsgWrt ; ..and the file we're writing call z,epstr ld bc,(OutUsr) ; B=drive, C=user ld de,OutFn+1 call z,PrtFn call OpnOut ; open output file call PutIni ; initialize PutC ; ld a,(OpQFlg) ; quiet? or a ld hl,MsgDot call z,epstr ; call RdLoop ; read and write files call ClsInp ; close input file call WrLast ; close output file call DatStp ; get date stamp, if any ; ld hl,BakTyp ; move BAK filetype to FCB ld de,OutFcb+9 ld bc,3 ldir ld de,OutFcb ; point to existing BAK name call initfcb call f$delete ; blind erase any existing BAK file ld de,OutFn ; point to old xxx name ld hl,OutFcb ; point to new BAK name call f$rename ; ..and blind rename any existing file ld hl,TmpTyp ; rename temporary $$$ file ld de,OutFcb+9 ; ..to output filename ld bc,3 ldir ld hl,OutFn ; point to new xxx name ld de,OutFcb ; point to old $$$ name call f$rename ; Finish: ld a,(OpQFlg) ; quiet option? or a ld a,0 ; reset error flag jr nz,Exit ; (yes) ld hl,(SpcCnt) ; get skipped space count call phlfdc ld hl,MsgDne ErExit: call epstr ; print message Exit: call puter2 ; set error code ld b,a ; put error code in B or a ; do we have one? call nz,inverror ; (yes, call error handler) ld sp,(OldStk) ; restore old stack pointer ret ; ..and return to CCP ; UAbort: cp CtrlC ; control-C? ret nz ; (nope, continue) ld a,4 ld hl,MsgAbt Abort: push af ; save error code call OutDU ld de,OutFcb call f$close ; close output file call f$delete ; erase it pop af ; restore error code jr ErExit ; InvDir: ld a,2 ; invalid directory ld hl,MsgDir jr ErExit ; ; Subroutines . . . ; ; OpnInp -- open input file ; OpnInp: ld de,InFcb call initfcb call InDU ; set drive/user for input call f$open ret z ; (all okay) ld a,10 ; set error flag ld hl,MsgFNF ; file not found jr ErExit ; ; OpnOut -- open output file ; OpnOut: ld de,OutFcb call initfcb ; initialize FCB call OutDU call f$make ; create and open file cp 0FFh ret nz ; (okay) ld a,11 ; set error flag ld hl,MsgNSp ; no directory space jp ErExit ; ; RdLoop -- reads and writes until end of file ; RdLoop: call SkpSp1 ; drop any leading space characters ret z ; (end of file) RdLp1: cp ' ' ; is it a space? jr z,IsSpc cp LF ; line feed? jr z,IsLF cp Dot ; period? jr z,IsDot cp TAB ; tab? jr z,IsSpc cp SSpace ; soft space? jr z,IsSpc cp HDot ; high-bit period? jr z,IsDot cp '?' ; question mark? jr z,IsDot cp '?'+80h ; high-bit question mark? jr z,IsDot cp '!' ; exclamation point? jr z,IsDot cp '!'+80h ; high-bit exclamation point? jr z,IsDot ld hl,TagChr ; protected area? cp (hl) jr z,IsTag call PutC ; output character jr c,WrtErr ; (disk full) RdLp2: call GetC ret z jr RdLp1 ; ; IsSpc -- Insert one space and ignore the rest ; IsSpc: call SkpSpc ret z call PutSpc jr RdLp1 ; ; IsLF -- We have the end of the line, so we skip leading spaces on ; next line. ; IsLF: call PutC ; send the line feed jr c,WrtErr call SkpSp1 ; skip any following space chars ret z jr RdLp1 ; ; IsDot -- We have a period, question mark, or exclamation point, so ; we need two spaces after it (unless there is no existing space). ; IsDot: call PutC ; send the period jr c,WrtErr call GetC ; does white-space follow? ret z ; (end of file) cp ' ' ; space? jr z,IsDot1 cp TAB ; tab? jr z,IsDot1 cp SSpace ; soft space? jr z,IsDot1 jr RdLp1 ; no, continue ; IsDot1: call SkpSpc ret z call PutSpc call PutSpc jr RdLp1 ; ; IsTag -- We have a protected area. We merely put and get characters ; until we find another tag character. ; IsTag: ld hl,TagChr ; point to tag character IsTag1: call GetC ; get next character ret z ; (end of file) cp (hl) ; another tag character? jr z,RdLp2 ; (yes, no more skipping) call PutC ; send character jr c,WrtErr ; (disk full) jr IsTag1 ; ..and loop ; ; PutSpc -- puts a space, unless at end of line and option T is zero. ; PutSpc: push af ; save character cp CR ; carriage return? call z,PutChk ; check option T flag jr z,PutSp1 ; (no space) cp SCR ; soft carriage return? call z,PutChk jr z,PutSp1 ld a,' ' ; insert space call PutC jr c,WrtErr ; (disk full) ld hl,(SpcCnt) ; decrement space count dec hl ld (SpcCnt),hl PutSp1: pop af ret ; PutChk: ld hl,OpTFlg dec (hl) inc (hl) ret ; WrtErr: ld a,11 ; set error flag ld hl,MsgWEr ; no disk space jp Abort ; ; SkpSpc -- skips past hard and soft spaces and tabs. Returns next ; non-space character in A. ; SkpSpc: ld hl,(SpcCnt) ; if we enter here, we've already inc hl ; ..dropped a white-space character ld (SpcCnt),hl SkpSp1: call GetC ; if here, no white-space yet ret z ; (end of file) cp ' ' jr z,SkpSpc cp SSpace jr z,SkpSpc cp TAB jr z,SkpSpc ret ; ; ClsInp -- close input file ; ClsInp: call InDU ; close input file ld de,InFcb call f$close ret z ; (okay) ld a,4 ; set error flag ld hl,MsgCEr ; close error jp Abort ; ; GetDft -- gets default drive and user ; GetDft: call retud ; C=user, B=drive (A=0) ld a,b ; A=drive (A=0) inc a ; A=drive (A=1) ret ; ; PrtFn -- Prints drive/user and filename on console ; PrtFn: call stndout ld a,b ; get drive add a,'A' ; make it printable call cout ; ..and print it ld a,c ; get user call pafdc ; ..and print it ld a,':' call cout call pfn2 ; print filename call stndend ret ; ; EatSpc -- gobbles up spaces and tabs ; EatSpc: ld a,(hl) or a ret z inc hl cp ' ' ; is it a space? jr z,EatSpc ; (yes) cp TAB ; is it a tab? jr z,EatSpc ; (yes) dec hl ret ; ; OutDU -- sets default drive and user for output file ; OutDU: push bc ld bc,(OutUsr) ; B=drive, C=user call logud pop bc ret ; ; InDU -- sets default drive and user for input file ; InDU: push bc ld bc,(InUsr) ; B=drive, C=user call logud pop bc ret ; ; GetC -- returns character from file. Assumes file has been ; successfully opened and GetIni has been called. Returns character ; or ^Z (end-of-file) in A. Zero set (Z) on end of file. ; Affected: AF ; GetC: push bc push de push hl ld a,(GetCnt) ; get counter cp 128 ; done with buffer? jr nc,GetC1 ; (yes, get next sector) GetChr: ld hl,(GetPtr) ; point to current DMA buffer ld e,a ; move counter to DE ld d,0 add hl,de ; ..and add it to HL inc a ; increment counter ld (GetCnt),a ld a,(hl) ; get next character cp CpmEof GetEof: pop hl pop de pop bc ret ; GetC1: call condin call nz,UAbort ; (check for abort) ld a,(GetMax) ld d,a ld a,(GetSec) ; get sector count cp d ; end of buffer? jr z,GetC2 ; (yes, we need to read more) inc a ; increment sector count ld (GetSec),a ; ..and store it ld hl,(GetPtr) ; get current sector pointer ld de,128 ; ..add 128 to it add hl,de ld (GetPtr),hl ; ..and store it xor a jr GetChr ; GetC2: ld a,(GetFlg) ; check end-of-file flag cp CpmEof jr z,GetEof ; (end of file) call InDU call ReadF ld hl,(InBuf) ld (GetPtr),hl xor a ld (GetSec),a jr GetChr ; ; GetIni -- must be called before first call to GetC. ; GetIni: ld hl,0 ; initialize flags ld (GetMax),hl ld (GetFlg),hl ; and GetSec ld a,128 ld (GetCnt),a ld hl,(InBuf) ; initialize pointer ld (GetPtr),hl ret ; ; ReadF -- read disk into input buffer ; ReadF: ld a,InSiz ld b,a dec a ld (GetMax),a ld hl,(InBuf) ReadF2: call RdSec jr nz,ReadF3 ld de,128 add hl,de djnz ReadF2 ret ; ReadF3: inc b ; we didn't read that last sector ld a,CpmEof ld (GetFlg),a ld a,InSiz ; store number of sectors read sub b ld (GetMax),a ret ; RdSec: call setdma ; set DMA address ld de,InFcb ; ..and read sector call f$read ret ; ; PutC -- Writes character to file. Assumes file has been successfully ; opened and PutIni has been called. Expects character in A. Returns ; carry set (C) on error (disk or directory full). ; Affected: Flags. ; PutC: push bc push de push hl ld c,a ; save character in C ld a,(PutCnt) ; get counter cp 128 ; buffer full? jr nc,PutC1 PutChr: ld hl,(PutPtr) ; point to current DMA buffer ld e,a ; move counter to DE ld d,0 add hl,de ; ..and add it to HL ld (hl),c ; write character inc a ; increment counter ld (PutCnt),a sub a ; clear carry PutEnd: ld a,c ; recover character pop hl pop de pop bc ret ; PutC1: ld a,(PutSec) ; get sector count inc a ; increment it cp OutSiz ; end of buffer? jr z,PutC2 ; (yes, we need to write it) ld (PutSec),a ; store new sector count ld hl,(PutPtr) ; get current sector pointer ld de,128 ; ..add 128 to it add hl,de ld (PutPtr),hl ; ..and store it xor a ; make A = 0 jr PutChr ; PutC2: call OutDU call WrtF ; write buffer to disk jr nz,PutErr ; (disk full) ld hl,(OutBuf) ; reset buffer pointer ld (PutPtr),hl xor a ; reset sector counter ld (PutSec),a jr PutChr ; PutErr: scf ; set carry jr PutEnd ; ; PutIni -- must be called before first call to PutC. ; PutIni: ld hl,0 ; initialize counters ld (PutCnt),hl ; and PutSec ld hl,(OutBuf) ; initialize buffer pointer ld (PutPtr),hl ret ; ; WrtF -- write output buffer to disk ; WrtF: ld a,(PutSec) ; get buffer sector count ld b,a ; put it in B inc b ld hl,(OutBuf) ; point to beginning of buffer WrtF2: call WrtSec ; write the sector ret nz ; (write error) ld de,128 ; increment DMA address add hl,de djnz WrtF2 ret ; WrtSec: call setdma ; set DMA address ld de,OutFcb ; ..and write sector call f$write ret ; ; WrLast -- writes remaining buffer contents and closes output file. ; WrLast: ld a,CpmEof ; put end-of-file character call PutC jp c,WrtErr ld hl,PutCnt ; point to current sector count ld a,128 sub (hl) jr z,WrLst1 ; (at end of sector) ld b,a ld a,CpmEof ; fill rest of sector with ^Z FillZ: call PutC jp c,WrtErr djnz FillZ WrLst1: ld de,(OutBuf) ; get beginning buffer address to DE ld hl,PutPtr ; HL -> buffer pointer ld a,e ; is pointer at zero? cp (hl) jr nz,WrLst2 ; (no) ld a,d inc hl cp (hl) jr nz,WrLst2 ; (no) ld a,(PutCnt) ; is counter at zero? or a jr nz,WrLst2 ; (no) jr ClsOut ; nothing to write, so close it ; WrLst2: call OutDU call WrtF ; write what's left jp nz,WrtErr ; (disk full, abort) ; ClsOut: call OutDU ; close output file ld de,OutFcb call f$close ret z ; (okay) ld a,4 ; set error flag ld hl,MsgCEr ; close error jp Abort ; ; GetOpt -- checks command tail for user supplied options and sets ; appropriate option flags. Also sets FSFlag to number of filespecs ; found. ; GetOpt: xor a ; initialize FSFlag ld (FSFlag),a ld hl,CpmDma ; point to command tail ld a,(hl) ; anything there? or a ret z ; (no) inc hl call EatSpc cp '/' jr z,IsSlsh ld a,(FSFlag) ; increment number of filespecs inc a ld (FSFlag),a FnLp1: inc hl ; move past first filename ld a,(hl) or a ret z ; (end of tail) cp ' ' jr z,GetOp1 cp TAB jr nz,FnLp1 ; GetOp1: call EatSpc or a ret z ; (end of tail) cp '/' ; is it a slash? jr z,IsSlsh ; (yes) ld a,(FSFlag) ; increment number of filespecs inc a ld (FSFlag),a FnLp2: inc hl ; move past second filename ld a,(hl) or a ret z ; (end of tail) cp ' ' jr z,GetOp2 cp TAB jr z,GetOp2 jr FnLp2 ; GetOp2: call EatSpc or a ret z ; (end of tail) cp '/' ; a slash? jr nz,GotOpt ; (no, get options) IsSlsh: inc hl ; move past slash GotOpt: ld a,(hl) ; get option inc hl or a ret z ; (end of tail) cp ' ' ; space? jr z,GotOpt ; (skip it) cp '/' ; usage request? jr z,Usage cp 'Q' ; quiet flag? jr z,OptQ cp 'T' ; trailing spaces? jr z,OptT ld a,19 ; set invalid option error ld hl,MsgBdO jp ErExit ; ; Option setting routines ; OptQ: ld a,(OpQFlg) ; get Q flag cpl ; flip it ld (OpQFlg),a ; store it jr GotOpt ; OptT: ld a,(OpTFlg) cpl ld (OpTFlg),a jr GotOpt ; Usage: ld hl,MsgUse call epstr call prtname ld hl,MsgUs1 call epstr ld a,(TagChr) ; get tag character cp ' ' ; control character? jr nc,Usage1 ; (no) ld b,a ; save control character tag in B ld a,'^' call cout ; if control, print caret ld a,b ; get back tag character add a,'@' Usage1: call cout ; ..and print it ld hl,MsgUs2 call epstr ld a,(OpTFlg) ld hl,MsgDnt or a call nz,epstr ld hl,MsgUs3 call epstr ld a,(OpQFlg) ; check quiet mode or a ld a,0 ; reset error flag ld hl,MsgUof jp nz,ErExit Usage2: ld hl,MsgUon jp ErExit ; ; DatStp -- Get create stamp from original file, if available, and ; transfer it to new file. ; DatStp: call InDU ; setup for input file ld de,InFcb ld hl,CpmDma ; point to DMA buffer call getstp ; get ZSDOS file stamp ret nz ; (error) ld a,(CpmDma+1) ; check for create date or a jr nz,DatSt1 ; (we've got a create date) ld a,(CpmDma+11) ; none, so check for modify date or a ret z ; (no date stamp) ld hl,CpmDma+10 ; point to modify date jr DatSt2 DatSt1: ld hl,CpmDma ; point to create date DatSt2: ld de,StpTmp ; move date to storage ld bc,5 ldir call OutDU ; setup for output file ld de,OutFcb ld hl,CpmDma ; point to DMA buffer call getstp ; get file stamp ret nz ; (error) ld hl,StpTmp ld de,CpmDma ; move old create stamp to date string ld bc,5 ldir ld de,OutFcb ; setup for file stamping ld hl,CpmDma call setstp ; set file stamp ret ; ; ChkAmb -- checks for ambiguous filename. Expects address of filename ; in HL. ; ChkAmb: ld bc,11 ld a,'?' cpir ret nz ; (no question marks) ld a,8 ; ambiguous filename ld hl,MsgAmb jp ErExit ; ; PSTR -- forces ZSYSCHK to use EPSTR ; pstr: jp epstr ; ; Data storage . . . ; BakTyp: db 'BAK' ; for BAK file TmpTyp: db '$$$' ; for temporary filename ; DSEG ; ; Uninitialized storage . . . ; OutFn: ds 12 ; save original output filename here InFcb: ds 36 ; input file fcb OutFcb: ds 36 ; output file fcb StpTmp: ds 5 ; temporary create date storage SpcCnt: ds 2 ; number of spaces removed OpQFlg: ds 1 ; FFh=quiet mode OpTFlg: ds 1 ; FFh=preserve trailing space FSFlag: ds 1 ; number of filespecs (set by GetOpt) GetMax: ds 1 ; number of sectors read into input buffer GetFlg: ds 1 ; GetC end-of-file flag GetSec: ds 1 ; GetC sector counter GetCnt: ds 1 ; GetC counter GetPtr: ds 2 ; GetC pointer PutCnt: ds 1 ; PutC counter PutSec: ds 1 ; PutC sector counter PutPtr: ds 2 ; PutC pointer InUsr: ds 1 ; input file user InDrv: ds 1 ; input file drive OutUsr: ds 1 ; output file user OutDrv: ds 1 ; output file drive DftUsr: ds 1 ; default user area DftDrv: ds 1 ; default drive OldStk: ds 2 ; old stack pointer InBuf: ds 2 ; input buffer address OutBuf: ds 2 ; output buffer address ; end