; ;************************************************************************** ; 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: February 14, 1989 ; ;-------------------------------------------------------------------------- ; ; Modifications: ; ; Author: Dave Ramsey Date: May 8, 1989 ; ; Purpose of Mod: Correct several small bugs and to implement correct ; DU: processing for the input and output files. ; (Thanks, Howard!) ; ; Author: Dave Ramsey Date: May 12, 1989 ; ; Purpose of Mod: Relinked with correct start address (0100h instead ; of 0103h). ; ; ; 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 13 ;defines current version of GF 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,pa2hc,fi0$open,f0$get,fo0$open,f0$put ext fi0$close,fo0$close,caps,z3init,argv,pstr,cout ext crlf,eval16,zprsfn,z3log ; ; main: jp start db 'Z3ENV' ;this is a z3 util db 1 ;external environment descriptor 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 ld sp,hl ;set new stack ; ; check for help request ; ld a,(05Ch+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 ld a,0ffh ;*DO* 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 hl,(arg1) ;pointer to arg1 ld de,infcb ;pointer to input FCB xor a call zprsfn ;parse input arg into a useful FCB ld de,infcb call z3log ld de,infcb call fi0$open ;open file in infcb for input jr 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 hl,(arg2) ld de,outfcb xor a call zprsfn ld de,outfcb call z3log ld de,outfcb call fo0$open ;open file in outfcb for output jr 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 ld de,infcb call z3log 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: push af ; save input byte ld de,outfcb call z3log pop af ; restore input byte call f0$put ; put next byte in output file jr loop ;endwhile ; finish: ld de,outfcb call z3log call fo0$close ;close output file fini1: ld de,infcb call z3log 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 */ ; else if *charptr == '\' then ; ++charptr ; if *charptr == '\' then ; temp = *charptr ; else ; temp = eval16(charptr) ; 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... ret z ;let caller use '^' char... 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 not '~' then check for hex sequences inc hl ld a,(hl) cp a,'~' ;trap `~~` sequence and let caller use ret z ;the `~` char... add a,020h ;add 32 to make it lowercase contr3: cp a,'\' ;'\' is the hex trigger ret nz ;is it's not '\' it's just a plain char inc hl ld a,(hl) cp a,'\' ret z ;trap '\\' and let caller use a '\' char call eval16 ;convert it to a binary byte value 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 ' A \ signals a hexadecimal string.',CR,LF db ' i.e. \0D or ^M is a carriage return and ~M is an "m"',CR,LF db ' To use a trigger char, simply type it twice - ',CR,LF db ' i.e. \\ or ^^ or ~~ will do the trick.',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 arg1 ds 2 ;pointer to arg1 - the input filename arg2 ds 2 ;pointer to arg2 - the output filename arg3 ds 2 ;pointer to arg3 - the character to change arg4 ds 2 ;pointer to arg4 - the target character ; infcb ds 36 outfcb ds 36 end