home *** CD-ROM | disk | FTP | other *** search
- ; Change.asm
- ; A find and replace utility for text files.
- ; Format: CHANGE filespec findstring replacestring
- ; The strings have to be in quotes or decimal ASCII
- ; Multiple codes in a string are separated by commas
- ; e.g. CHANGE MYFILE 27,"-1" "*"
-
-
- CODE SEGMENT ;*************************
- ASSUME CS:CODE,DS:CODE ;* *
- ORG 100H ;* REMEMBER TO EXE2BIN *
- ;* *
- START: JMP BEGINNING ;*************************
-
-
- ; DATA AREA
- ; ---------
- FILE_START DW ?
- FIND_CNT DW 0
- REPLACE_CNT DW 0
- CHANGE_FLAG DB 0
-
- SYNTAX_MSG DB 'Syntax error$'
- NOT_FOUND$ DB 'File not found$'
- TOO_BIG$ DB 'File too big$'
- CHANGE$ DB 'Not Changed$'
- DB "Copyright 1986 Ziff-Davis Publishing Co.",1Ah
- DB "Programmed by Michael J. Mefford",1Ah
-
- ; CODE AREA
- ; ---------
-
- ;-------------------------------------------------------;
- ; First we will parse the filename and the two strings. ;
- ;-------------------------------------------------------;
-
- BEGINNING: MOV SI,80H ;Point to parameters.
- MOV DX,OFFSET SYNTAX_MSG ;Point to syntax message.
- CLD ;Move in forward direction.
- CALL SPACE ;Parse leading spaces.
- MOV FILE_START,SI ;We now point to filename.
-
- FILE_BYTE: CMP BYTE PTR [SI],13 ;Is it a carriage return?
- JZ EXIT ;If yes, exit with syntax error.
- CMP BYTE PTR [SI],32 ;Is it a space?
- JZ ASCIIZ ;If yes, end of filename
- INC SI ; else, point to next byte
- JMP SHORT FILE_BYTE ; and check it.
- ASCIIZ: MOV BYTE PTR [SI],0 ;Make filename into ASCIIZ.
-
- CALL SPACE ;Parse the spaces.
- XOR CX,CX ;Set string counter to zero.
- MOV DI,OFFSET FIND$ ;Point to find string storage.
- FIND_BYTE: CALL STRING ;Get string.
- CMP BYTE PTR [SI],32 ;Are we now pointing to space?
- JZ REPLACE ;If yes, done here.
- CMP BYTE PTR [SI],13 ;Is it a carriage return?
- JZ EXIT ;If yes, it's a syntax error
- INC SI ; else point to next byte
- JMP SHORT FIND_BYTE ; and get rest of string.
-
- REPLACE: CALL SPACE ;Parse spaces.
- MOV FIND_CNT,CX ;Save count of find string bytes.
- XOR CX,CX ;Reset counter to zero.
- MOV DI,OFFSET REPLACE$ ;Point to replace string storage.
- REPLACE_BYTE: CALL STRING ;Get string.
- CMP BYTE PTR [SI],32 ;Are we now pointing to space?
- JZ OPEN_FILE ;If yes, we are done here.
- CMP BYTE PTR [SI],13 ;Are we now pointing to CR?
- JZ OPEN_FILE ;If yes, we are done here
- INC SI ; else, point to next byte
- JMP SHORT REPLACE_BYTE ; and get rest of string.
-
- ;------------------------------------------;
- ; The exit is placed in the middle of code ;
- ; so it can be reached by short jumps. ;
- ;------------------------------------------;
-
- EXIT: MOV AH,9 ;Display message
- INT 21H
- INT 20H ; and terminate.
-
- ;-----------------------------------------------------------;
- ; We are ready to open the file and read it into the buffer ;
- ; offset 20,000 bytes from the start. We will then move the ;
- ; bytes to the start of buffer, trading any match of find ;
- ; string with replacement string. ;
- ;-----------------------------------------------------------;
-
- OPEN_FILE: MOV REPLACE_CNT,CX ;Save count of replace bytes.
- MOV DX,FILE_START ;Point to ASCIIZ filename
- MOV AX,3D00H ; and open file for reading.
- INT 21H
- MOV DX,OFFSET NOT_FOUND$ ;If not found
- JC EXIT ; display message and exit.
-
- READ_FILE: MOV BX,AX ;File handle into BX
- MOV DX,OFFSET BUFFER+20000 ;Point buffer
- MOV CX,40000 ;Attempt to read 40,000 bytes.
- MOV AH,3FH
- INT 21H
- MOV DX,OFFSET TOO_BIG$ ;Point to error message.
- CMP AX,40000 ;Did we read 40,000 bytes?
- JZ EXIT ;If yes, file too big; exit
- PUSH AX ; else, save count of bytes
- MOV AH,3EH ; and close the file.
- INT 21H
-
- COMPARE: POP DX ;Retrieve byte count.
- MOV AX,FIND_CNT ;Retrieve find string length.
- CMP DX,AX ;Is find string bigger than file?
- JGE OK ;If no, it's OK
- MOV DX,OFFSET CHANGE$ ; else exit with no change.
- JMP SHORT EXIT
-
- OK: MOV BX,OFFSET BUFFER+20000 ;Point to start of file
- MOV AX,OFFSET BUFFER ; and start of storage.
- NEXT_COMP: MOV SI,OFFSET FIND$ ; point to find string
- MOV DI,BX ; point to match attempt
- MOV CX,FIND_CNT ; get find string length
- REP CMPSB ; and compare.
- MOV DI,AX ;Point storage area.
- JZ MATCH ;If match, store replace string
- MOV SI,BX ; else store
- MOVSB ; old byte
- INC AX ; point to next storage spot
- INC BX ; start of next byte to compare
- DEC DX ; decrement file byte count
- JMP SHORT LOOP ; and check if end of file.
-
- MATCH: OR CHANGE_FLAG,1 ;Indicate that we found a match.
- MOV SI,OFFSET REPLACE$ ;Point to replacement string.
- MOV CX,REPLACE_CNT ;Get length.
- ADD AX,CX ; point to next storage spot
- ADD BX,FIND_CNT ; start of next byte to compare
- SUB DX,FIND_CNT ; subtract from file byte count
- REP MOVSB ; and store the string.
-
- LOOP: CMP DX,FIND_CNT ;Is find string bigger than
- JGE NEXT_COMP ; balance of file? If no, next
- MOV CX,DX ; compare else, transfer the
- ADD AX,CX ; balance of file to write
- MOV SI,BX ; storage area.
- REP MOVSB
-
- ;-----------------------------------------;
- ; We are ready to write the file to disk. ;
- ;-----------------------------------------;
-
- WRITE: PUSH AX ;Save length of new file.
- MOV DX,FILE_START ; point to ASCIIZ filename.
- XOR CX,CX ; normal attribute
- MOV AH,3CH ; and create new file.
- INT 21H
- POP CX ;Retrieve file length
- SUB CX,OFFSET BUFFER ;It's in offset form; correct it.
- MOV BX,AX ;File handle into BX
- MOV DX,OFFSET BUFFER ; point to storage buffer
- MOV AH,40H ; and write the file.
- INT 21H
- MOV AH,3EH ;Close file.
- INT 21H
- MOV DX,OFFSET CHANGE$ ;Point to "Not Changed"
- CMP CHANGE_FLAG,0 ;Did we find a match?
- JZ NOT_CHANGED ;If no, display as is
- ADD DX,4 ; else bump pointer to "Changed"
- NOT_CHANGED: JMP EXIT ; and we are done.
-
- ;---------------------------------------------;
- ; This subroutine will get the quoted string ;
- ; or convert the decimal ASCII to hexadecimal ;
- ; and store in the appropriate storage area. ;
- ;---------------------------------------------;
-
- STRING: CMP BYTE PTR [SI],'"' ;Is it quotes?
- JNZ NUMBER ;If no, must be number
- INC SI ; else, point to first string
- NEXT_STRING: LODSB ; byte and retrieve.
- CMP AL,13 ;Is it carriage return?
- JZ ERROR ;If yes, syntax error; exit.
- CMP AL,'"' ;Is it quotes?
- JNZ STORE ;If no, store the byte
- CALL DELIMITER ; else, see if delimiter
- JNC STORE ; and store the quote if part
- RET ; of string else, we are done.
-
- STORE: STOSB ;Store the byte
- INC CX ; increment byte count
- JMP SHORT NEXT_STRING ; and get next string byte
-
- NUMBER: XOR BL,BL ;Zero into hex counter.
- GET_NUMBER: CALL DELIMITER ;Is it a delimiter?
- JNC LOAD_NUMBER ;If no, get next decimal number
- MOV AL,BL ; get hex byte
- STOSB ; and store
- INC CX ; increment byte count
- RET ; and we are done
-
- LOAD_NUMBER: LODSB ;Get the decimal number
- CMP AL,'0' ;Is it between 0 and 9?
- JB ERROR ;If no, syntax error
- CMP AL,'9'
- JA ERROR
- SUB AL,30H ; else, convert to hex
- MOV BH,AL ; and save
- MOV AL,10 ; multiply by ten
- MUL BL ; to shift place left
- MOV BL,AL
- ADD BL,BH ; add new number
- JMP SHORT GET_NUMBER ; and get next decimal number.
- ERROR: JMP EXIT ;In lieu of range of short jump.
-
- ;--------------------------------;
- ; This subroutine will parse ;
- ; leading and delimiting spaces. ;
- ;--------------------------------;
-
- SPACE: INC SI ;Point to next byte
- CMP BYTE PTR [SI],32 ;Is it space?
- JZ SPACE ;If no, get next byte
- RET ; else, return.
-
- ;----------------------------;
- ; This subroutine will check ;
- ; for delimiter characters. ;
- ;----------------------------;
-
- DELIMITER: CLC ;Assume not delimiter.
- CMP BYTE PTR [SI],32 ;Is it space
- JZ SET_CARRY
- CMP BYTE PTR [SI],13 ; or carriage return
- JZ SET_CARRY
- CMP BYTE PTR [SI],',' ; or comma?
- JNZ RETURN ;If no, return else, indicate
- SET_CARRY: STC ; by setting carry flag
- RETURN: RET ; and return.
-
- ;-------------------------------------------------------------;
- ; Storage buffers for findstring, replacestring and file at ;
- ; end of code to make basic data listing appreciably shorter. ;
- ;-------------------------------------------------------------;
-
- FIND$:
- ORG OFFSET FIND$+128
- REPLACE$:
- ORG OFFSET REPLACE$+128
- BUFFER:
-
- CODE ENDS
- END START
-