/* Copyright (c) 1995 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 VERIFYR GENERIC
(VERIFYR_all_graphic WHEN (GRAPHIC, GRAPHIC),
VERIFYR_all_graphic WHEN (GRAPHIC, *),
VERIFYR_all_graphic WHEN (GRAPHIC, GRAPHIC),
VERIFYR_all WHEN (*,*),
VERIFYR_sub_graphic WHEN (GRAPHIC, GRAPHIC,*),
VERIFYR_sub_graphic WHEN (GRAPHIC, *,*),
VERIFYR_sub_graphic WHEN (*, GRAPHIC, *),
VERIFYR_sub WHEN (*,*,*) );
/* Strategy for GRAPHIC arguments: The look-up table is large. To avoid initializing */
/* it on each call, it is initialized at compile time. On entry, a small number of table */
/* entries are set in preparation for the search. These entries are reset before exit, */
/* so that the table is already prepared for the next function reference. */
/* If these functions are called with a very long second argument, use the strategy of */
/* VERIFYR_sub. */
/* This function procedure searches the first string STRING for any characters that do */
/* not exist in second string SUB. If there are any such characters, the function returns */
/* the position of the right-most. */
VERIFYR_all:
PROCEDURE (STRING, SUB) OPTIONS (REORDER)
RETURNS (FIXED BINARY (31));
/* INCOMING: STRING = the string to be searched; */
/* SUB = contains characters to look for. */
DECLARE (STRING, SUB) CHARACTER (*);
DECLARE Table (0:255) BIT (1) STATIC ALIGNED;
DECLARE (J, K) FIXED BINARY (31);
IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */
RETURN (0);
IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */
RETURN (LENGTH(String));
IF LENGTH (SUB) = 1 THEN /* Looking for one character is fast. */
DO;
DO J = LENGTH (String) TO 1 BY -1;
IF SUBSTR(STRING, J, 1) ^= SUB THEN
RETURN (J);
END;
RETURN (0); /* Unsuccessful search. */
END;
/* SETS UP A LOOK-UP TABLE (which is independent of character set). */
Table = '1'B; /* All entries are TRUE. */
DO J = 1 TO LENGTH (Sub);
K = UNSPEC (SUBSTR (Sub, J, 1));
Table (K) = '0'B; /* Table(k) is FALSE for each character in SUB. */
END;
/* CONDUCT THE SEARCH (backwards). */
DO J = LENGTH (STRING) TO 1 BY -1;
K = UNSPEC (SUBSTR (STRING, J, 1));
IF Table(K) THEN /* TRUE when a SUB character does not match one */
RETURN (J); /* in STRING. */
END;
RETURN (0); /* Unsuccessful search. */
END VERIFYR_all;
/* This function procedure searches the first string STRING for any characters that do */
/* not exist in second string SUB. If there are any such characters, the function returns */
/* the position of the right-most. */
/* The search is performed from right to left, commencing from character position POSITION. */
VERIFYR_sub:
PROCEDURE (STRING, SUB, POSITION) OPTIONS (REORDER)
RETURNS (FIXED BINARY (31));
/* INCOMING: STRING = the string to be searched; */
/* SUB = contains characters 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 Table (0:255) BIT (1) STATIC ALIGNED;
DECLARE (J, K) FIXED BINARY (31);
IF (Position > LENGTH (String) ) | (Position < 0) THEN
DO;
SIGNAL STRINGRANGE;
RETURN (0);
END;
IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */
RETURN (0);
IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */
RETURN (Position);
IF LENGTH (SUB) = 1 THEN /* Looking for one character is fast. */
DO;
DO J = POSITION TO 1 BY -1;
IF SUBSTR(STRING, J, 1) ^= SUB THEN
RETURN (J);
END;
RETURN (0); /* Unsuccessful search. */
END;
/* SETS UP A LOOK-UP TABLE (which is independent of character set). */
Table = '1'B; /* All entries are TRUE. */
DO J = 1 TO LENGTH (Sub);
K = UNSPEC (SUBSTR (Sub, J, 1));
Table (K) = '0'B; /* Table(k) is FALSE for each character in SUB. */
END;
/* CONDUCT THE SEARCH (backwards). */
DO J = POSITION TO 1 BY -1;
K = UNSPEC (SUBSTR (STRING, J, 1));
IF Table(K) THEN /* TRUE when a SUB character does not match one */
RETURN (J); /* in STRING. */
END;
RETURN (0); /* Unsuccessful search. */
END VERIFYR_sub;
/* This function procedure searches the first string STRING for any graphic characters that */
/* do not exist in second string SUB. If there are any such characters, the function */
/* returns the position of the right-most. */
VERIFYR_all_graphic:
PROCEDURE (STRING, SUB) OPTIONS (REORDER)
RETURNS (FIXED BINARY (31));
/* INCOMING: STRING = the string to be searched; */
/* SUB = contains characters to look for. */
DECLARE (STRING, SUB) GRAPHIC (*);
DECLARE Table (0:65535) BIT (1) STATIC ALIGNED INITIAL ( (65536)(1)'1'B ),
Table_Set BIT(1) STATIC INITIAL ( '1'B);
DECLARE (J, K, L) FIXED BINARY (31);
IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */
RETURN (0);
IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */
RETURN (LENGTH(String));
IF LENGTH (SUB) = 1 THEN /* Looking for one character is fast. */
DO;
DO J = LENGTH (String) TO 1 BY -1;
IF SUBSTR(STRING, J, 1) ^= SUB THEN
RETURN (J);
END;
RETURN (0); /* Unsuccessful search. */
END;
/* SETS UP A LOOK-UP TABLE (which is independent of character set). */
IF ^Table_Set THEN
Table = '1'B; /* All entries are TRUE. */
Table_Set = '0'B;
DO L = 1 TO LENGTH (Sub);
K = UNSPEC (SUBSTR (Sub, L, 1));
Table (K) = '0'B; /* Table(k) is FALSE for each character in SUB. */
END;
/* CONDUCT THE SEARCH (backwards). */
DO J = LENGTH (STRING) TO 1 BY -1;
K = UNSPEC (SUBSTR (STRING, J, 1));
IF Table(K) THEN /* TRUE when a SUB character does not match one */
LEAVE; /* in STRING. */
END;
/* RESTORE THE TABLE */
DO L = 1 TO LENGTH (Sub);
K = UNSPEC (SUBSTR (Sub, L, 1));
Table (K) = '1'B; /* Table(k) is TRUE for each character in SUB. */
END;
Table_Set = '1'B;
RETURN (J);
END VERIFYR_all_graphic;
/* This function procedure searches the first string STRING for any graphic characters that */
/* do not exist in second string SUB. If there are any such characters, the function */
/* returns the position of the right-most. */
/* The search is performed from right to left, commencing from character position POSITION. */
VERIFYR_sub_graphic:
PROCEDURE (STRING, SUB, POSITION) OPTIONS (REORDER)
RETURNS (FIXED BINARY (31));
/* INCOMING: STRING = the string to be searched; */
/* SUB = contains characters 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 Table (0:65535) BIT (1) STATIC ALIGNED INITIAL ( (65536)(1)'1'B ),
Table_Set BIT (1) STATIC INITIAL ( '1'B );
DECLARE (J, K, L) FIXED BINARY (31);
IF (Position > LENGTH (String) ) | (Position < 0) THEN
DO;
SIGNAL STRINGRANGE;
RETURN (0);
END;
IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */
RETURN (0);
IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */
RETURN (Position);
IF LENGTH (SUB) = 1 THEN /* Looking for one character is fast. */
DO;
DO J = POSITION TO 1 BY -1;
IF SUBSTR(STRING, J, 1) ^= SUB THEN
RETURN (J);
END;
RETURN (0); /* Unsuccessful search. */
END;
/* SETS UP A LOOK-UP TABLE (which is independent of character set). */
IF ^Table_Set THEN
Table = '1'B; /* All entries are TRUE. */
Table_Set = '0'B;
DO L = 1 TO LENGTH (Sub);
K = UNSPEC (SUBSTR (Sub, L, 1));
Table (K) = '0'B; /* Table(k) is FALSE for each character in SUB. */
END;
/* CONDUCT THE SEARCH (backwards). */
DO J = POSITION TO 1 BY -1;
K = UNSPEC (SUBSTR (STRING, J, 1));
IF Table(K) THEN /* TRUE when a SUB character does not match one */
RETURN (J); /* in STRING. */
END;
DO L = 1 TO LENGTH (Sub);
K = UNSPEC (SUBSTR (Sub, L, 1));
Table (K) = '1'B; /* Table(k) is TRUE for each character in SUB. */
END;
Table_Set = '1'B;
RETURN (J);
END VERIFYR_sub_graphic;