.TITLE STEXCH .IDENT /V02/ .ENABLE LC ; ; This subroutine changes all or some occurrences within an ASCII string ; of one substring for another, extending or truncating (and padding with ; nulls) the strin if the substrings are of different length ; ; Author: V01 16-Mar-79 Mark Woolfson ; V02 29-Jan-80 Phil Stephensen-Payne ; ; Calling Sequence: ; ; This subroutine is called via the standard FORTRAN calling sequence as:- ; ; CALL STEXCH(SUB1,SLEN1,SUB2,SLEN2,STR,LEN,REPCNT [,STATUS]) ; or ; STATUS = STEXCH(SUB1,SLEN1,SUB2,SLEN2,STR,LEN,REPCNT) ; ; Where:- ; SUB1 = Address of substring to be replaced ; LEN1 = Length of substring to be replaced ; SUB2 = Address of substring to replace SUB1 with ; LEN2 = Length of substring to replace SUB1 with ; STR = Address of string for replacement to be done in ; LEN = Length of string for replacement to be done in ; REPCNT = Number of occurrences to be replaced (0=all) ; STATUS = Optional error reply ; ; Errors Returned: ; ; STATUS = 0 if the operation was successful ; = -1 if a parameter error was detected ; ; External References: ; ; This module calls the subroutines STFIND and PRMCHK ; ; SRCLEN: .WORD 0 ;LENGTH OF SEARCH STRING REPLEN: .WORD 0 ; Length of replacement DESLEN: .WORD 0 ;LENGTH OF STRING TO BE SEARCHED LOCADR: .WORD 0 ;RETURN POSITION ; PARAM: .WORD 5 ;NUMBER PARAMS FOR STFIND ROUTINE SRCADD: .WORD 0 ; .WORD SRCLEN ; DESTIN: .WORD 0 ;ADDRESS OF STRING TO BE SEARCHED .WORD DESLEN ;LENGTH OF STRING TO BE SEACHED .WORD LOCADR ; ; REPADD: .WORD 0 ; Address of replacement string STRADD: .WORD 0 ;CURRENT ADDRESS IN DEST STRING STRLEN: .WORD 0 ;CURRENT LENGTH OF DEST STRING ; STEXCH:: MOV #8.,R0 ;SET UP NUMBER OF PARAMS CALL PRMCHK ;CHECK ON PARAMETERS BCS 10$ ; If CS parameter error - exit at once TST (R5)+ ; Remove number of parameters MOV (R5)+,SRCADD ; Get address of search string MOVB @(R5)+,SRCLEN ; Get length of search string MOV (R5)+,REPADD ; Get address of replacement string MOVB @(R5)+,REPLEN ; Get length of replacement string MOV (R5)+,STRADD ; Get address of source string MOVB @(R5)+,STRLEN ; Get length of source string MOVB @(R5)+,R4 ; Get replacement count BIC #177400,R4 ; Clear any sign extension ; ;FIND NEXT OCCURANCE OF THE TO-BE-REPLACED STRING ; 2$: CLR R0 ; Clear R0 for success CMPB STRLEN, SRCLEN ;TEST STR LEN >= SEARCH STR LEN BLT 10$ ;QUIT IF NOT MOV STRADD, DESTIN ;GET ADDRESS OF STRING MOV STRLEN, DESLEN ;GET LENGTH OF STRING MOV R5, -(SP) ;SAVE OUR PARAM POINTER MOV #PARAM, R5 ;SET UP STFIND'S PARAM POINTER JSR PC, STFIND ;CALL STFIND ROUTINE MOV (SP)+, R5 ;RESTORE OUR PARAM POINTER CLR R0 ; Clear R0 just in case DEC LOCADR ;DID WE FIND ONE? BLT 10$ ;... NO, SO QUIT ; ;HAVING FOUND A TO-BE-REPLACED STRING, LET'S DISCOVER HOW TO REPLACE IT ; MOV STRLEN, R3 ;GET REMAINING STR LENGTH SUB LOCADR, R3 ;SUB OFFSET OF TO-BE-REPLACED STRING SUB SRCLEN, R3 ;SUB LENGTH OF " " MOV R3, R0 ;TO GIVE NEW LENGTH OF REMAINING STRING CMP SRCLEN,REPLEN ;COMP TO-BE-REPLACED LEN WITH REPLACING LENGTH BEQ 5$ ;... =, SO JUST OVERWRITE BLT 4$ ;... <, SO EXPAND STRING ; ;TO-BE-REPLACED > REPLACED, SO SHORTEN STRING ; MOV STRADD, R1 ;GET START ADDR OF STRING ADD LOCADR, R1 ;GET ADDR OF START OF TO-BE-REPLACED STR MOV R1, R2 ; ADD SRCLEN, R1 ;END OF TO-BE-REPLACED (OLD) STRING ADD REPLEN, R2 ;END OF REPLACING (NEW) STRING TST R3 ; Anything to move BEQ 60$ ; If eq no - skip move 6$: MOVB (R1)+, (R2)+ ;MOVE STRING UP BYTE BY BYTE SOB R3, 6$ ;TEST FOR END ; 60$: MOV SRCLEN, R3 ;CALC DIFFERENCE IN STRING LENGTH SUB REPLEN, R3 ; 7$: CLRB (R2)+ ;PAD STRING OUT WITH NULLS SOB R3, 7$ ;TEST FOR END OF FILL BR 5$ ;GO MOVE IN NEW STRING ; ;TO-BE-REPLACED < REPLACING, SO EXTEND STRING ; 4$: MOV STRADD, R1 ; ADD STRLEN, R1 ;GET ADDR OF OLD END OF STR MOV R1, R2 ; ADD REPLEN, R2 ; SUB SRCLEN, R2 ;GET ADDR OF NEW END OF STRING TST R3 ; Anythin to shift? BLE 5$ ; If LE no - exit 9$: MOVB -(R1), -(R2) ;MOVE STRING DOWN BYTE BY BYTE SOB R3, 9$ ;TEST FOR END OF MOVE ; ;OK, STRING IN RIGHT PLACE FOR NEW STRING TO BE COPIED IN, SO LET'S DO SO ; 5$: MOV STRADD, R1 ; ADD LOCADR, R1 ;GET ADDR OF START OF COPY TO AREA MOV REPADD, R2 ;GET ADDR OF NEW STRING MOV REPLEN, R3 ;GET LENGTH OF NEW STRING BEQ 3$ ;NOTHING TO MOVE 8$: MOVB (R2)+, (R1)+ ;COPY IN NEW STRING SOB R3, 8$ ;TEST FOR END OF COPY ; ;NOW SET UP INFO ON REMAINING STRING AND TEST FOR END OF EXCH ; 3$: MOV R0, STRLEN ;LENGTH OF REMAINING STRING MOV R1, STRADD ;ADDRESS OF REMAINING STRING TST R4 ;TEST IF REPLACING ALL OCCURANCES BEQ 2$ ;...YES. SO FIND NEXT DEC R4 ;... NO, SO TEST IF WE'VE DONE ENOUGH BGT 2$ ; ... NO, SO FIND NEXT OCCURANCE CLR R0 ; Show success ; 10$: RETURN ;QUIT .END