/* Copyright (c) 1996 by R. A. Vowels, from "Introduction to PL/I, Algorithms, and */ /* Structured Programming". Permission is given to reproduce and to use these procedures */ /* as part of a program, and to include them as part of a larger work to be sold for profit. */ /* However, the user is not permitted to sell the procedures separately. Provided always */ /* that these procedures and this copyright notice are reproduced in full. */ DECLARE INDEXR GENERIC (INDEXR_all_graphic WHEN (GRAPHIC, GRAPHIC), INDEXR_all_graphic WHEN (GRAPHIC, *), INDEXR_all_graphic WHEN (*, GRAPHIC), INDEXR_sub_graphic WHEN (GRAPHIC, GRAPHIC, *), INDEXR_sub_graphic WHEN (GRAPHIC, *, *), INDEXR_sub_graphic WHEN (*, GRAPHIC, *), INDEXR_all WHEN (*, *), INDEXR_sub WHEN (*, *, *) ); /* This function searches the first string STRING, to ascertain whether the second string */ /* SUB exists within it. If it does, the function returns the position of the right-most */ /* character that matches. The search commences from right to left. */ INDEXR_all: PROCEDURE (STRING, SUB) OPTIONS (REORDER) RETURNS (FIXED BINARY (31) ); /* INCOMING: STRING = the string to be searched; */ /* SUB = contains the string to look for; */ DECLARE (STRING, SUB) CHARACTER (*); DECLARE (LENGTH, SUBSTR) BUILTIN; DECLARE CK CHARACTER (1); DECLARE K FIXED BINARY (31); DECLARE (LP, LS) FIXED BINARY (31); LP = LENGTH (Sub); LS = LENGTH (String); IF (LP = 0) | (LS = 0) THEN /* There's nothing to search. */ RETURN (0); CK = SUBSTR (Sub, 1, 1); IF LP = 1 THEN /* A seacrh for 1 character is faster. */ DO; DO K = LS TO 1 BY -1; IF SUBSTR (String, K, 1) = CK THEN RETURN (K); END; RETURN (0); END; DO K = LS-LP+1 TO 1 BY -1; DO K = K TO 1 BY -1 WHILE (CK ^= SUBSTR (String, K, 1) ); END; /* A fast inner loop to look for a starting character. */ IF K > 0 THEN IF SUBSTR (String, K, LP) = Sub THEN RETURN (K); /* We had a match at position K. */ END; RETURN (0); /* No luck at all. Go back empty-handed. */ END INDEXR_all; /* This function searches the first string STRING, to ascertain whether the second string */ /* SUB exists within it. If it does, the function returns the position of the right-most */ /* character that matches. The search commences from position Position, from right */ /* to left. */ /* Note that the value of Position must be such that the string SUB will fit within */ /* STRING. If it does not, the search will commence from position */ /* LENGTH(String) - LENGTH(Sub) + 1, that is, with SUB right-adjusted alongside STRING. */ INDEXR_sub: PROCEDURE (String, Sub, Position) OPTIONS (REORDER) RETURNS (FIXED BINARY (31) ); /* INCOMING: STRING = the string to be searched; */ /* SUB = contains the string to look for; */ /* POSITION = where to start the search (measured from the left-hand end of */ /* STRING). */ DECLARE (STRING, SUB) CHARACTER (*); DECLARE Position FIXED BINARY (31); DECLARE (LENGTH, SUBSTR, MIN) BUILTIN; DECLARE CK CHARACTER (1); DECLARE K FIXED BINARY (31); DECLARE (LP, LS) FIXED BINARY (31); LP = LENGTH (Sub); LS = LENGTH (String); IF (Position > LS) | (Position < 0) THEN DO; SIGNAL STRINGRANGE; RETURN (0); END; IF (LP = 0) | (LS = 0) THEN /* There's nothing to search. */ RETURN (0); CK = SUBSTR (Sub, 1, 1); IF LP = 1 THEN /* A seacrh for 1 character is faster. */ DO; DO K = Position TO 1 BY -1; IF SUBSTR (String, K, 1) = CK THEN RETURN (K); END; RETURN (0); END; DO K = MIN(LS-LP+1, Position-LP+1) TO 1 BY -1; DO K = K TO 1 BY -1 WHILE (CK ^= SUBSTR (String, K, 1) ); END; /* A fast inner loop to look for a starting character. */ IF K > 0 THEN IF SUBSTR (String, K, LP) = Sub THEN RETURN (K); /* We had a match at position K. */ END; RETURN (0); /* No luck at all. Go back empty-handed. */ END INDEXR_sub; /* This function searches the first string STRING, to ascertain whether the second string */ /* SUB exists within it. If it does, the function returns the position of the right-most */ /* character that matches. The search commences from right to left. */ INDEXR_all_graphic: PROCEDURE (STRING, SUB) OPTIONS (REORDER) RETURNS (FIXED BINARY (31) ); /* INCOMING: STRING = the string to be searched; */ /* SUB = contains the string to look for; */ DECLARE (STRING, SUB) GRAPHIC (*); DECLARE (LENGTH, SUBSTR) BUILTIN; DECLARE CK GRAPHIC (1); DECLARE K FIXED BINARY (31); DECLARE (LP, LS) FIXED BINARY (31); LP = LENGTH (Sub); LS = LENGTH (String); IF (LP = 0) | (LS = 0) THEN /* There's nothing to search. */ RETURN (0); CK = SUBSTR (Sub, 1, 1); IF LP = 1 THEN /* A seacrh for 1 character is faster. */ DO; DO K = LS TO 1 BY -1; IF SUBSTR (String, K, 1) = CK THEN RETURN (K); END; RETURN (0); END; DO K = LS-LP+1 TO 1 BY -1; DO K = K TO 1 BY -1 WHILE (CK ^= SUBSTR (String, K, 1) ); END; /* A fast inner loop to look for a starting character. */ IF K > 0 THEN IF SUBSTR (String, K, LP) = Sub THEN RETURN (K); /* We had a match at position K. */ END; RETURN (0); /* No luck at all. Go back empty-handed. */ END INDEXR_all_graphic; /* This function searches the first string STRING, to ascertain whether the second string */ /* SUB exists within it. If it does, the function returns the position of the right-most */ /* character that matches. The search commences from position Position, from right */ /* to left. */ /* Note that the value of Position must be such that the string SUB will fit within */ /* STRING. If it does not, the search will commence from position */ /* LENGTH(String) - LENGTH(Sub) + 1, that is, with SUB right-adjusted alongside STRING. */ INDEXR_sub_graphic: PROCEDURE (String, Sub, Position) OPTIONS (REORDER) RETURNS (FIXED BINARY (31) ); /* INCOMING: STRING = the string to be searched; */ /* SUB = contains the string to look for; */ /* POSITION = where to start the search (measured from the left-hand end of */ /* STRING). */ DECLARE (STRING, SUB) GRAPHIC (*); DECLARE Position FIXED BINARY (31); DECLARE (LENGTH, SUBSTR, MIN) BUILTIN; DECLARE CK GRAPHIC (1); DECLARE K FIXED BINARY (31); DECLARE (LP, LS) FIXED BINARY (31); LP = LENGTH (Sub); LS = LENGTH (String); IF (Position > LS) | (Position < 0) THEN DO; SIGNAL STRINGRANGE; RETURN (0); END; IF (LP = 0) | (LS = 0) THEN /* There's nothing to search. */ RETURN (0); CK = SUBSTR (Sub, 1, 1); IF LP = 1 THEN /* A seacrh for 1 character is faster. */ DO; DO K = Position TO 1 BY -1; IF SUBSTR (String, K, 1) = CK THEN RETURN (K); END; RETURN (0); END; DO K = MIN(LS-LP+1, Position-LP+1) TO 1 BY -1; DO K = K TO 1 BY -1 WHILE (CK ^= SUBSTR (String, K, 1) ); END; /* A fast inner loop to look for a starting character. */ IF K > 0 THEN IF SUBSTR (String, K, LP) = Sub THEN RETURN (K); /* We had a match at position K. */ END; RETURN (0); /* No luck at all. Go back empty-handed. */ END INDEXR_sub_graphic;