From: Brian McLaughlin
Subject: Code for reverse INSTR
The code below is a reverse INSTR implementation. Instead of the first
instance of a sub-string, it finds the last instance. This can be
helpful
when you are parsing the filename from a pathname, based on the last
instance of the "\" delimiter. I am releasing the code to the public
domain.
$LIB ALL OFF
DECLARE FUNCTION GETSTRLOC& (BYVAL Handle%) 'REQUIRED for use of
RINSTR%
DECLARE FUNCTION RINSTR% (Main$, SearchFor$)
'Demo code -----------------------------------------
Main$ = "12345678901234567890"
Search$ = "90"
PRINT RINSTR%(Main$, Search$)
END ' ----------------------------------------------
'========================================
FUNCTION RInstr% (Main$, SearchFor$)
'========================================
' Written by Brian McLaughlin. Released into the public domain.
' This FUNCTION is a reverse implementation of INSTR. You pass it the
' string to be searched in Main$, and the string to search for in
' SearchFor$.
'
' RInstr% then searches for the last occurence of SearchFor$ within
Main$.
' If it finds SearchFor$, it returns the position of the first
character
' of the final occurence of SearchFor$, as a an offset from the first
' char of Main$. For example, if Main$ were identical to SearchFor$,
' RInstr% would return 1.
'
' RInstr% returns a zero if:
' 1) Main$ is null, or
' 2) SearchFor$ is null, or
' 3) SearchFor$ is longer than Main$, or
' 4) SearchFor$ was not found within Main$
'--------------------------------------------------------------------------
LOCAL Position%
Position% = 0 ' assume failure
ASM Push SI
ASM Push DI
ASM Push DS
ASM Les BX, SearchFor$
ASM Mov AX, ES:[BX]
ASM Push AX
ASM Call GETSTRLOC ; puts SearchFor$ address in DX:AX, length in
CX
ASM Jcxz ReturnZero ; we can't search for a null$
ASM Push DX ; save them all
ASM Push AX
ASM Push CX
ASM Les BX, Main$
ASM Mov AX, ES:[BX]
ASM Push AX
ASM Call GETSTRLOC ; puts Main$ address in DX:AX, length in CX
ASM Mov ES, DX
ASM Mov DI, AX ; ES:DI = points to first byte of Main$
ASM Pop DX ; DX = length of SearchFor$
ASM Pop SI
ASM Pop DS ; DS:SI points to first byte of SearchFor$
ASM Jcxz ReturnZero ; we can't search if main$ is a null$
ASM Add DI, CX ; points ES:DI one byte past end of Main$
ASM Sub DI, DX ; points ES:DI at last "possible" byte of
Main$
ASM Mov AL, Byte Ptr [SI] ; AL = value of first char of Search$
ASM Sub CX, DX
ASM Js ReturnZero ; if CX < 0 then SearchFor$ longer than Main$
ASM Inc CX ; adjust CX to get proper number of bytes to
scan
ScanStr:
ASM Std ; set direction flag for backward scan
ASM Repne Scasb ; scan for a match to AL at ES:DI
ASM Jnz ReturnZero ; zero flag cleared if no match found
ASM Push SI ; save the necessary registers before
ASM Push DI ; they're destroyed by Cmpsb, and note that
ASM Push CX ; ES:DI points one byte prior to matching char
ASM Cld ; now we'll search forward again
ASM Mov CX, DX ; for the length of Search$
ASM Inc DI ; but first, re-point ES:DI at matching char
ASM Repe Cmpsb ; do the comparison
ASM Pop CX ; restore earlier loop counter
Continued with next message...
*** QwkNews (tm) v2.1
* [TN71] Toast House Import
--- GEcho 1.20/Pro
---------------
* Origin: Toast House Remote (1:100/561)
|