* JMP SUBSTRINGSX * *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=* * * * SUBSTRING ROUTINE LIBRARY * * * * AUTHOR: NATHAN RIGGS * * CONTACT: NATHAN.RIGGS@ * * OUTLOOK.COM * * * * VERSION: 0.1.2 * * DATE: 30-OCT-2018 * * ASSEMBLER: MERLIN 8 PRO * * * * LICENSE: APACHE 2.0, WHERE * * APPLICABLE. CODE INSPIRED * * BY THE WORKS OF OTHERS MAY * * FALL UNDER A DIFFERENT * * LICENSE (NOTED IN ROUTINE). * * * * THIS IS A LIBRARY FOR USING * * SUBSTRING OPERATIONS. THIS * * IS SEPARATE FROM THE MAIN * * STRINGS LIBRARY BY VIRTUE OF * * DEALING WITH FULL MEMORY * * ERRORS IN THE ASSEMBLER. * * YEEEEE. * * * *------------------------------* * * * LIST OF ROUTINES * * * * SUBPOS : FIND POS OF SUBSTR * * SUBCOPY : COPY SUBSTRING * * SUBDEL : DELETE SUBSTRING * * SUBINS : INSERT SUBSTRING * * * *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-* * *``````````````````````````````* * SUBPOS :: SUBSTRING POSITION * *- -* * FIND THE POSITION OF A SUB- * * STRING WITHIN ANOTHER STRING * *- -* * CLOBBERS: * * * * FLAGS: ????---- REG: AXYM * *- -* * CYCLES: ??? * * SIZE: * *- -* * USAGE: * * * * LDA #>STR ; STRING ADDR * * PHA * * LDA #SUB ; SUBSTR ADDR * * PHA * * LDA #STR ; SOURCE STRING * * PHA * * LDA #SUB ; SUBSTRING ADDR * * PHA * * LDA # SLEN THEN ** COUNT = SLEN - SINDEX + 1 * LDA :SINDEX CLC ADC :SCNT BCS :RECALC TAX ; BR IF INDEX + COUNT > 255 DEX CPX :S1LEN BCC :CNT10K ; BR IF IND + CNT - 1 < S1LEN BEQ :CNT10K ; OR EQUAL * ** THE CALLER ASKED FOR TOO MANY CHARS SO ** JUST RETURN EVERYTHING BETWEEN INDEX AND ** END OF STRING. SO CNT = S1LEN - INDEX + 1 * :RECALC LDA :S1LEN ; RECALCULATE COUNT SEC SBC :SINDEX STA :SCNT INC :SCNT ; CNT = S1LEN - IND + 1 LDA #$0FF STA :SCERR ; INDICATE TRUNCATION * ** CHECK IF COUNT IS <= THE MAXIMUM LENGTH ** OF THE DEST STRING. IF NOT, THEN SET COUNT TO ** MAX LENGTH. ** IF COUNT > MAXLEN THEN ** COUNT = MAXLEN * :CNT10K LDA :SCNT CMP :MLEN ; IF CNT > M SUBSTR LEN ? BCC :CNT20K ; BR IF CNT < MAXLEN BEQ :CNT20K ; BR IF CNT = MAXLEN LDA :MLEN STA :SCNT ; ELSE CNT = MAXLEN LDA #$0FF STA :SCERR ; INDICATE DEST STR OVERFLOW * ** EVERYTHING IS SET UP SO MOVE THE ** SUBSTRING TO THE DESTINATION STRING * :CNT20K LDX :SCNT ; REG X WILL BE COUNTER BEQ :EREXIT ; ERR IF 0 LDA #1 ; START WITH 1ST CHAR IN DEST STA :S2LEN ; RUNNING DEST INDEX ; __SINDEX IS SRC INDEX :MVLP LDY :SINDEX LDA (ADDR1),Y ; GET NEXT SRC CHAR LDY :S2LEN STA (ADDR2),Y ; MOVE NEXT CHAR TO DEST INC :SINDEX ; INC SRC INDEX INC :S2LEN ; INC DEST INDEX DEX ; DECREMENT COUNTER BNE :MVLP ; CONT UNTIL CNT = 0 DEC :S2LEN ; SUBSTR LEN=FINAL DEST IND-1 LDA :SCERR ; CHECK FOR ANY ERRORS BNE :EREXIT ; BR IF STR TRUNCATED OR OVERFLOW * ** GOOD EXIT * :OKEXIT CLC BCC :EXIT * ** ERROR EXIT * :EREXIT SEC * ** STORE LENGTH BYTE IN FRONT OF SUBSTR * :EXIT LDA :S2LEN LDY #0 STA (ADDR2),Y RTS * ** DATA * :S1LEN DS 1 :S2LEN DS 1 :MLEN DS 1 :SCNT DS 1 :SINDEX DS 1 :SCERR DS 1 * *``````````````````````````````* * SUBDEL :: DELETE SUBSTRING * *- -* * DELETE A SUBSTRING FROM A * * STRING. * *- -* * CLOBBERS: * * * * FLAGS: ????---- REG: AXYM * *- -* * CYCLES: ??? * * SIZE: * *- -* * USAGE: * * * * LDA #>STR ; STRING ADDRESS * * PHA * * LDA # 255 STA :SIDX ; SAVE INDEX + COUNT AS ; THE SOURCE INDEX TAX ; X = INDEX + COUNT DEX CPX :S1LEN BCC :CNTOK ; BR IF IND + CNT - 1 ; < __S1LEN ; ELSE JUST TRUNC STRING BEQ :TRUNC ; TRUNC BUT NO ERROR-- ; EXACTLY ENOUGH CHARS LDA #$0FF STA :SCERR ; INDICATE ERROR - NOT ; ENOUGH CHARS TO DELETE * ** TRUNCATE THE STRING - NO COMPACTING NECESSARY * :TRUNC LDX :SINDEX ; STRING LENGTH = ; START INDEX - 1 DEX STX :S1LEN LDA :SCERR BEQ :OKEXIT BNE :ERREXIT * ** DELETE THE SUBSTRING BY COMPACTING ** MOVE ALL CHARS ABOVE THE DELETED AREA DOWN * :CNTOK * ** CALCULATE NUMBER OF CHARS TO MOVE ** (SLEN - SIDX + 1) * LDA :S1LEN ; GET STR LENGTH SEC SBC :SIDX ; SUBTRACT START INDEX TAX INX BEQ :OKEXIT ; ADD 1 TO INCLUDE LAST ; CHAR; BR IF CNT = 0 :MVLP LDY :SIDX LDA (ADDR1),Y ; GET NEXT CHAR LDY :SINDEX STA (ADDR1),Y ;MOVE IT DOWN INC :SINDEX INC :SIDX ; INC DEST, SRC INDEXES DEX BNE :MVLP ; CONT UNTIL CNT = 0 LDX :SINDEX DEX ; START LENGTH = FINAL ; DEST INDEX -1 STX :S1LEN * ** GOOD EXIT * :OKEXIT CLC BCC :EXIT :ERREXIT SEC * :EXIT LDA :S1LEN LDY #0 STA (ADDR1),Y ; SET LENGTH OF STRING RTS * ** DATA * :S1LEN DS 1 :SCNT DS 1 :SINDEX DS 1 :SIDX DS 1 :SCERR DS 1 * *``````````````````````````````* * SUBINS :: INSERT SUBSTRING * *- -* * INSERT A SUBSTRING INTO * * ANOTHER STRING. * *- -* * CLOBBERS: * * * * FLAGS: ????---- REG: AXYM * *- -* * CYCLES: ??? * * SIZE: * *- -* * USAGE: * * * * LDA #STR ; STRING TO INS TO * * PHA * * LDA #SUB ; SUBSTRING TO INS * * PHA * * LDA # 255 CMP :MLEN ; BCC :IDXLEN ; BR IF S1+S2 LEN < MAX LENGTH BEQ :IDXLEN ; BR IF EQUAL * ** SUBSTRING DOES NOT FIT, SO TRUNCATE IT * :TRUNC LDA :MLEN ; SUBSTR LEN = MLEN - STR LEN SEC SBC :S1LEN BCC :EREXIT BEQ :EREXIT ; ERR IF MLEN < STR LEN OR 0 ; (ORIGINAL STRING WAS TOO LONG) STA :S2LEN LDA #$0FF STA :SCERR ; INDICATE SUBSTR WAS TRUNCATED * ** CHECK THAT INDEX IS WITHIN STRING. IF NOT, CONCAT ** SUBSTR ONTO THE END OF THE STRING. * :IDXLEN LDA :S1LEN CMP :SINDEX ; BCS :LENOK ; BR IF INDEX WITHIN STR LDX :S1LEN ; ELSE CONCAT SUB AT END OF STR INX STX :SINDEX ; START RIGHT AFTER END OF STR LDA #$0FF STA :SCERR ; INDICATE ERR IN INSERT LDA :S1LEN CLC ADC :S2LEN STA :S1LEN ; ADD LENGTHS TOGETHER JMP :MVESUB ; PERFORM MOVE, NOTHING ELSE TODO * ** OPEN UP A SPACE IN THE SOURCE STRING FOR THE ** SUBSTRING BY MOVING THE CHARACTERS FROM THE END ** OF THE SOURCE STRING DOWN TO INDEX, UP BY ** THE SIZE OF THE STRING. * :LENOK * ** CALC NUMBER OF CHARS TO MOVE ** COUNT = STR LEN - START INDEX + 1 * LDA :S1LEN SEC SBC :SINDEX TAX INX ; X= NUM OF CHARS TO MOV * ** SET THE SOURCE INDEX AND CALC DEST INDEX * LDA :S1LEN STA :SIDX ; SRC ENDS AT ORIG STR END CLC ADC :S2LEN STA :SBIDX ; DEST ENDS FURTHER BY SUB LEN STA :S1LEN ; SET NEW LENGTH TO THIS ALSO * :OPNLP LDY :SIDX LDA (ADDR1),Y LDY :SBIDX STA (ADDR1),Y ; MOVE IT UP IN MEM DEC :SIDX DEC :SBIDX ; DE DEST IDX, COUNTER DEX BNE :OPNLP ; CONT UNTIL COUNTER = 0 * ** MOVE THE SUBSTR INTO THE OPEN AREA * :MVESUB LDA #1 STA :SIDX ; START AT ONE IN THE SUBSTR ; START AT INDEX IN THE STRING LDX :S2LEN ; X = NUM OF CHARS TO MOVE * :MVELP LDY :SIDX LDA (ADDR2),Y ; GET NEXT CHAR LDY :SINDEX STA (ADDR1),Y INC :SIDX ; INC SUBSTR INDEX INC :SINDEX ; INC STR INDEX DEX ; DEC COUNTER BNE :MVELP ; CONT UNTIL COUNTER = 0 LDA :SCERR ; GET ERROR FLAG BNE :EREXIT ; BR IF SUBSTR WAS TRUNCED * :OKEXIT CLC BCC :EXIT :EREXIT SEC ; ERROR EXIT :EXIT LDA :S1LEN LDY #0 STA (ADDR1),Y RTS * ** DATA * :S1LEN DS 1 :S2LEN DS 1 :SUBLEN DS 1 :MLEN DS 1 :SINDEX DS 1 :SIDX DS 1 :SBIDX DS 1 :SCERR DS 1 * SUBSTRINGSX *