/* 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. */ /* Revised 12 October 2001. */ DECLARE TALLY GENERIC (TALLY_graphic WHEN (GRAPHIC, GRAPHIC), TALLY_graphic WHEN (GRAPHIC, *), TALLY_graphic WHEN (*, GRAPHIC), TALLY_char WHEN (CHARACTER, CHARACTER), TALLY_char WHEN (CHARACTER, *), TALLY_char WHEN (*, CHARACTER), TALLY_bit WHEN (BIT, BIT), TALLY_char WHEN (*, *) ); /* This function procedure counts the number of times that string SUB occurs in string STRING. */ TALLY_char: PROCEDURE (STRING, SUB) OPTIONS (REORDER) RETURNS (FIXED BINARY (31)); /* INCOMING: STRING = the character string to be searched; */ /* SUB = the character string for which we are searching. */ DECLARE (STRING, SUB) CHARACTER (*); DECLARE (TOTAL, POSITION) FIXED BINARY (31); IF (LENGTH (STRING) = 0) | (LENGTH (SUB) = 0) THEN RETURN (0); TOTAL = 0; POSITION = 1; DO WHILE (POSITION <= LENGTH (STRING) ); POSITION = INDEX (STRING, SUB, POSITION) + 1; IF POSITION = 1 THEN LEAVE; TOTAL = TOTAL + 1; END; RETURN (TOTAL); END TALLY_char; /* This function procedure counts the number of times that string SUB occurs in string STRING. */ TALLY_graphic: PROCEDURE (STRING, SUB) OPTIONS (REORDER) RETURNS (FIXED BINARY (31)); /* INCOMING: STRING = the character string to be searched; */ /* SUB = the character string for which we are searching. */ DECLARE (STRING, SUB) GRAPHIC (*); DECLARE (TOTAL, POSITION) FIXED BINARY (31); IF (LENGTH (STRING) = 0) | (LENGTH (SUB) = 0) THEN RETURN (0); TOTAL = 0; POSITION = 1; DO WHILE (POSITION <= LENGTH (STRING) ); POSITION = INDEX (STRING, SUB, POSITION) + 1; IF POSITION = 1 THEN LEAVE; TOTAL = TOTAL + 1; END; RETURN (TOTAL); END TALLY_graphic; /* This function procedure counts the number of times that bit string SUB occurs in bit */ /* string STRING. */ TALLY_bit: PROCEDURE (STRING, SUB) OPTIONS (REORDER) RETURNS (FIXED BINARY (31)); /* INCOMING: STRING = the bit string to be searched; */ /* SUB = the bit string for which we are searching. */ DECLARE (STRING, SUB) BIT (*) ALIGNED; DECLARE (TOTAL, POSITION, J) FIXED BINARY (31); /* A look-up table for converting bit patterns to number of bits. */ /* The look-up is 8 bits wide. */ DECLARE TABLE (0:255) FIXED BINARY (7) STATIC INITIAL ( 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 ); DECLARE LIMIT FIXED BINARY (31); DECLARE B8 BIT(8) ALIGNED; IF (LENGTH (STRING) = 0) | (LENGTH (SUB) = 0) THEN RETURN (0); IF LENGTH (SUB) = 1 THEN /* This case amounts to counting 0 or 1 bits. */ DO; IF SUB = '1'B THEN /* Fast count, 8-bits at a time. */ DO; TOTAL = 0; Limit = DIVIDE(LENGTH (STRING), 8, 15, 0)*8; DO J = 1 TO Limit BY 8; B8 = SUBSTR(STRING, J, 8); (NOFIXEDOVERFLOW): TOTAL = TOTAL + TABLE(B8); END; /* The last few bits are counted one-at-a-time. */ DO J = Limit+1 TO LENGTH (STRING); IF SUBSTR (STRING, J, 1) = SUB THEN TOTAL = TOTAL + 1; END; RETURN (TOTAL); END; TOTAL = 0; DO J = 1 TO LENGTH (STRING); IF SUBSTR (STRING, J, 1) = SUB THEN TOTAL = TOTAL + 1; END; RETURN (TOTAL); END; TOTAL = 0; POSITION = 1; DO WHILE (POSITION <= LENGTH (STRING) ); POSITION = INDEX (STRING, SUB, POSITION) + 1; IF POSITION = 1 THEN LEAVE; TOTAL = TOTAL + 1; END; RETURN (TOTAL); END TALLY_bit;