/* 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;