'===========================================================================
' Subject: REVERSE INSTR                      Date: 01-06-98 (14:43)       
'  Author: Don Schullian                      Code: PB                     
'  Origin: d83@ath.forthnet.gr              Packet: PB.ABC
'===========================================================================
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' REVERSE INSTR
'   by Don Schullian
'   for PowerBASIC v3.5+
'
' Like INSTR but searches backwards through the target string
'
' P% if the value is > 0 then the starting mid$ position in Target$
' T$ the target string
' S$ the string being searched for
'
' RETURNS the MID$ position of S$ in T$ or ZERO if S$ was not
'   or could not possibly be found
'
' NOTE: as the string parameters are being sent BYVAL the function
'       can be greatly speeded up by using SEG but then the incoming
'       strings MUST conform to the variable type declared. If you
'       require many searches on long strings then it would be
'       advisable to (re)create another version using SEG for that
'       string variable type.
'
' POINT OF INTEREST:
'       This function, as seen here, comes within a few ticks of
'       the ASM version found in my library Nutz 'n Boltz
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
DECLARE FUNCTION fRINSTR%(BYVAL P%,BYVAL T$,BYVAL S$)
DIM P AS INTEGER
DIM S AS STRING
DIM T AS STRING

CLS

T$ = "This is a test"
S$ = "is"
P% = 0
PRINT T$
DO
  P% = fRINSTR%( P%, T$, S$ )
  IF P% = 0 THEN EXIT LOOP
  LOCATE , P%
  PRINT S$
  DECR P%
LOOP

FUNCTION fRINSTR( BYVAL P    AS INTEGER, _
                  BYVAL Txt  AS STRING , _
                  BYVAL Srch AS STRING   ) LOCAL PUBLIC AS INTEGER

  DIM Slen  AS LOCAL INTEGER                    ' length of Srch$
  DIM S_ptr AS LOCAL BYTE PTR                   ' char pointer to Srch$
  DIM Tlen  AS LOCAL INTEGER                    ' length of Txt$
  DIM T_ptr AS LOCAL BYTE PTR                   ' char pointer to Txt$
  DIM X     AS LOCAL INTEGER                    ' main Txt$ loop counter
  DIM Y     AS LOCAL INTEGER                    ' main Srch$ loop counter
  DIM Z     AS LOCAL INTEGER                    ' temp Txt offset
                                                '
  Slen% = LEN(Srch$)                            ' get the length of Srch$
  IF Slen% = 0   THEN EXIT FUNCTION             ' nothing to search for
  Tlen% = LEN(Txt$) - Slen%                     ' length of Txt$ - Srch$
  IF Tlen% < 1   THEN EXIT FUNCTION             ' no possibility
  IF P% > Tlen% THEN EXIT FUNCTION              ' no possibility
  IF P% > 0 THEN Tlen% = P%                     ' set mid$ starting point
                                                '
  DECR Slen%                                    ' Zero based for pointers
  DECR Tlen%                                    ' << ditto >>
  T_ptr = STRPTR32( Txt$  )                     ' set pointers
  S_ptr = STRPTR32( Srch$ )                     '
                                                '
  FOR X% = Tlen% TO 0 STEP -1                   ' start search
    IF @S_ptr[0] <> @T_ptr[X%] THEN ITERATE     ' if 1st Srch$ not a match
    IF Slen% = 0 THEN EXIT FOR                  ' if only 1 char search
    Z% = X%                                     ' offset in Txt$
    FOR Y% = 1 TO Slen%                         ' confirm all chars
      INCR Z%                                   '  next pos in Txt$
      IF @S_ptr[Y%] <> @T_ptr[Z%] THEN EXIT FOR '  not equal - exit early
    NEXT                                        '
    IF Y% > Slen% THEN EXIT FOR                 ' WE HAVE A WINNER!
  NEXT                                          '
                                                '
  FUNCTION = ( X% + 1 )                         ' RETURN position
                                                '
END FUNCTION                                    '
