; ;********************************************************************** ; GF is a generalized file filter program for ZCPR systems. ; ; Purpose: GF allows the user to change any single character from an ; input file to any other character in the resulting an output ; file. ; ; Author: Dave Ramsey Date: December 12, 1988 ; ; Assembler Used: SLR's Z80ASM ; ;********************************************************************** ; ;PDL for Filter follows: ; ;Begin FILTER ; Get ptr to cmd line ; Parse cmd line ; If number args = 4 then ; open input file (arg[1]) ; if open error then ; abort with message "can't open input file" arg[1] ; endif ; open output file (arg[2]) ; target = control(arg[3]) ; replacement = control(arg[4]) ; while not eof(input file) do ; inchar = getnextchar(input file) ; if inchar = target then ; inchar = replacement ; endif ; putnextchar(output file) ; end while ; else ; show help ; endif ;end FILTER ; ; ;********************************************************************** ; VERSION equ 10 ;defines current version of GF FCB0 equ 5Ch FCB1 equ 6Ch BDOSEV equ 0005h ;BDOS entry vector BOOTEV equ 0000h ;system warm start entry vector CR equ 0Dh ;carriage return = ASCII char 13 LF equ 0Ah ;line feed = ASCII char 10 TBUFF equ 080h ; ; ext print,fi0$open,f0$get,fo1$open,f1$put,fi0$close,fo1$close ext caps,z3init,argv,pstr,cout,crlf ; ; main: jp start db 'Z3ENV' z3eadr ds 2 ; start: ld hl,z3eadr call z3init ;initialize Z3 environment ; ; setup program stack here... ; ld hl,0 add hl,sp ;save current sp ld (oldsp),hl ld hl,BDOSEV+1 ;get BDOS address... ld a,h sub a,8 ;our stack = BDOS - 2K (to save CCP) ld h,a ;set page address of stack xor a ld l,a ;put on a page boundary ; ; check for help request ; ld a,(FCB0+1) cp a,'/' jr z,help cp a,' ' jr nz,start2 help: ld hl,usage call pstr jp fini2 ; ; parse the command tail... ; start2: ld de,argtbl ld hl,TBUFF+1 ;cmd tail is in TBUFF xor a ;do not NULL terminate args call argv jr z,start3 ;if parsing error occurred, show help ld hl,parserr call pstr jp fini2 start3: ld a,(argtbl+1) cp a,4 jr z,openin ;if wrong # of args, show help ld hl,argcount call pstr jp fini2 ; ; open input file specified in arg #1 ; openin: ld de,FCB0 call fi0$open ;open file in infcb for input jp z,openout ;if ok, goto start call print ;else print error msg and abort db 'Input file not found.',0 jp fini2 ; ; open output file specified in arg #2 ; openout: ld de,FCB1 call fo1$open ;open file in outfcb for output jp z,getargs call print db 'Unable to open specified output file.',0 jp fini1 getargs: ; ; here we would set values from cmd line for target and replacement ; chars... ; ld hl,(arg3) ;point at 3rd cmd line arg ld a,(hl) call control ;convert search arg ld (oldchar),a ;save converted char ; ld hl,(arg4) ;point at 4th cmd line arg ld a,(hl) call control ;convert replacement arg ld (newchar),a ;save converted char loop: ;while not eof do call f0$get ; get next input byte jp nz,finish ; if not zero, error - process error ld hl,oldchar cp a,(hl) ; input byte = search char? jr nz,loop2 ; if no, continue processing ld a,(newchar) ; else replace with new char ; loop2: call f1$put ; put next byte in output file jr loop ;endwhile ; finish: call fo1$close ;close output file fini1: call fi0$close ;close input file fini2: ld hl,(oldsp) ;get old stack pointer ld sp,hl ;restore BDOS stack pointer ret ;return to CCP ; ;**************************************************************** ; ; CONTROL routine: returns the cmd line arg pointed to by HL ; as a character in A. Converts cmd line string ^c to the ; equivalent control character. ; ;Begin CONTROL ; temp = charptr passed in from caller ; if *charptr == '^' then ; ++charptr ; convert to uppercase(*charptr) ; if *charptr == `^` then ; temp = *charptr ; else ; temp = *charptr - 64 /* convert to control */ ; endif ; else if *charptr == '~' then ; ++charptr ; if *charptr == '~' then ; temp = *charptr ; else ; temp = *charptr + 32 /* convert to lowercase */ ; endif ; return temp ;end CONTROL ; ;**************************************************************** ; control: ld a,(hl) ;get initial arg cp a,'^' ;is it control trigger? jr nz,contr2 ;if not, check for lowercase flag inc hl ld a,(hl) ;else get next byte in arg cp a,'^' ;trap '^^' sequence... jr z,contr3 ;let caller use '^' char... call caps ;else capitalize it, and then sub a,040h ;subtract 64 to get ASCII ctrl code ret ; ; check here for lowercase trigger... contr2: cp a,'~' ;`~` is our lowercase flag jr nz,contr3 ;if it's not `~` it's just a plain char inc hl ld a,(hl) cp a,'~' ;trap `~~` sequence and let caller use jr z,contr3 ;the `~` char... add a,020h ;add 32 to make it lowercase contr3: ret ;return from control char conversion ; ; data areas: ; usage: db 'GF, Version ',VERSION/10+'0','.',VERSION MOD 10+'0' db ' - A Generalized Filter.',CR,LF db 'Syntax:',CR,LF db ' GF du:fn1 du:fn2 oldch newch',CR,LF db ' Where:',CR,LF db ' du:fn1 is the input file spec;',CR,LF db ' du:fn2 is the output file spec;',CR,LF db ' oldchar is the search character; and',CR,LF db ' newchar is the replacement character.',CR,LF, db ' A ^ character before either oldchar or newchar',CR,LF db ' tells GF to convert it to a control character.',CR,LF db ' A ~ character before either oldchar or newchar',CR,LF db ' tells GF to convert it to lowercase.',CR,LF db ' i.e. ^M is a carriage return and ~M is an "m"',CR,LF,LF,0 ; parserr db 'Parsing error!',CR,LF,0 argcount db 'Incorrect number of arguments!',CR,LF,0 ; oldsp ds 2 oldchar ds 1 newchar ds 1 argtbl db 4 ;max number of args expected ds 1 ;number of args actually found ds 2 ;pointer to arg1 ds 2 ;pointer to arg2 arg3 ds 2 ;pointer to arg3 arg4 ds 2 ;pointer to arg4 ; end