%INSTR

Search for a substring within a string

WSupported on Windows
USupported on Unix
VSupported on OpenVMS
NSupported in Synergy .NET
position = %INSTR(start, string, substring[, position2])

or

xcall INSTR(start, string, substring, position2)

Return value

position

The starting position of the first occurrence of substring within string. (n)

If any of the following conditions are true, the result is 0:

If substring is null but string is not, the result is 1. If position2 is specified, the result is also returned in that variable.

Arguments

start

The position in the string at which the search will begin. (n)

string

The string in which to search for the substring. (a)

substring

The substring for which to search. (a)

position2

(optional) A variable in which to return the starting position of the first occurrence of substring. If INSTR can’t find an exact match of the substring value or matches one of the other conditions described by position, position2 is returned with a value of 0 to indicate that the search failed. (n)

Discussion

Searching from left to right, %INSTR searches for substring in string from start through the end of the string. The length of substring must be less than or equal to the length of string.

To search from right to left and find the last occurrence of the substring, use %RVSTR.

The position returned is relative to the beginning of string.

Examples

This function checks if the entered state abbreviation is in the western part of the United States.

function chk_state 
    a_state     ,a 
record 
    western     ,a*,    "AZ|CA|CO|ID|MT|NM|NV|OR|UT|WA|WY" 
 
proc 
     freturn %instr(1, western, a_state) 
endfunction

In the example below, assume your data division looks like this:

record
    codes       ,a30,   "help.add.sub.mul.div"
    loc         ,d3
    target      ,a3,    "sub"

The following subroutine returns a loc value of 7, because the first d appears at character position 7 in the string stored in the codes variable.

xcall instr(4, codes, "d", loc)

The subroutine below assigns the value 8 to loc, because when the search begins at the eighth character stored in codes, the first d appears at character position 8. This result differs from the preceding XCALL, because the starting position value causes the search to begin after the d in character position 7.

xcall instr(8, codes, "d", loc)

The following subroutine searches codes for the first occurrence of sub, beginning at character position 1. Loc is set to 10.

xcall instr(1, codes, target, loc)

The example below uses one field for all of the error messages, rather than a separate field or array entry for each message. This saves data space, because the field is the exact size of the error message, with no filler. The processing method uses delimiters that make it easy to add, delete, or change error messages.

subroutine error_msg
    err_code            ,a      ;Error code, including colon
.define TTY             ,1      ;Terminal channel
.define FILEOF          ,1      ;End-of-file error #
.define ROW             ,12     ;Row # to display error message
record err_msg                  ;Capitalized word is err_code
                        ,a*,    "Opener:Could not open file\"
  &                             "FLESIZ:File full\"
  &                             "DUPKEY:Duplicate key exists\"
  &                             "KEYSIZ:Incorrect key size\"
  &                             "NOTFOUND:Record not found\"
  &                             "LOCKED:Record locked--try again\"
  &                             "ILLRECNBR:Invalid record number\"
  &                             "WRONG:Invalid error code\"
  &                             "CNTLC:Internal error--call developer!\"
record msg_buffer
    ret_msg             ,a22,   "Press <CR> to Continue"
    input               ,a1             ;Dummy input variable
    start_pos           ,d4             ;Start position of error message
    end_pos             ,d4             ;End position of error message
    len                 ,d2             ;Length of error message
record window
    width               ,d2             ;Width of error msg display
    col                 ,d2             ;Column position of error msg
proc
    onerror (FILEOF)done, exit          ;Look for valid error code
    xcall instr(1, err_msg, err_code, start_pos)
    len = %size(err_code)
    if (start_pos .eq. 0) 
      begin
        len = 6                         ;Length of "WRONG:"
        xcall instr(1, err_msg, "WRONG:", start_pos)
      end
    xcall instr(start_pos + len, err_msg, '\', end_pos)
    decr end_pos                        ;Back up to end of msg
    start_pos = start_pos + len
    width = end_pos - start_pos + 1 ;Error msg width
    col = %rnd(40.0 - width/2.0)

    display(TTY, $scr_pos(ROW, col), 
  &         err_msg(start_pos, end_pos),
  &         $scr_pos(ROW + 1, 28), ret_msg)
    reads(TTY, input, done)             ;Wait for user response
done,                                   ;Error displayed
    offerror
    xreturn

exit,                           ;If anything unexpected happens, stop program
    offerror
    xcall exit_sys              ;External wrap up
    stop
endsubroutine