32bit Checksum in PROGRESS 4GL

  This code is an example how to manipulate character strings in PROGRESS 4GL on a bit level. This code below has been used in one real enterprise internal messaging system to ensure messages' integrity, when passing them between the number of PROGRESS Application Servers. This bit manipulation, in fact, is only an emulation of the bit logic, but sometimes it is more resonable, than calling an external C language code (or using HLC), specifically when you need reliable transactions to be performed. Now you can see the code below and wonder, how to use arrays of logical variables to perform the 'bit logic'.

/* checksum.p
*/
PROCEDURE checksum.

/* [LT]
 * Paskirtis:
 *	Skaičiuoja CHAR eilutės 32-bitų kontrolinę sumą ir formuoja
 *	PROGRESS INT tipo rezultatą. Kadangi INT tipas yra 'signed 
 *	long' - rezultatas gali būti ir neigiamas, priklausomai nuo 
 *	32-ojo bito. Kontrolinės sumos skaičiavimas C kalbos priemonėmis 
 *	mažiau patrauklus, kadangi reikia iškvietinėti išorinę programą 
 *	(panaudojant INPUT-OUTPUT THROUGH).
 *
 *  Pašaliniai efektai:
 *      Grąžina checksum kintamojo reikšmę (32-bit checksum).
 */

/* [EN]
 * Synopsis:
 *	Calculates 32-bit checksum of CHAR string. The result is stored 
 *	into variable of INT type. PROGRESS's INT type is a 32-bit signed
 *	long integer, so the result may be either negative or positive, 
 *	depending on 32'th bit. This module is an attempt not to write 
 *	an external C program, which would be called using 
 *	INPUT-OUTPUT THROUGH.
 *
 * Returns:
 *	32-bit chaecksum, stored in variable of INT type.
 *
 *
 * Author:
 *	Vladas Saulis (PRODATA) - 1997.
 */

/* Input string, for which we calculate checksum */
DEF INPUT PARAM buf AS CHAR. 

/* The resulted checksum */
DEF OUTPUT PARAM checksum AS INT. 

DEF VAR c4sum AS INT.
DEF VAR csbits AS LOG EXTENT 32.
DEF VAR c4bits AS LOG EXTENT 32.
DEF VAR bignum AS INT.

DEF VAR buflen AS INT.

DEF VAR k AS INT.
DEF VAR j AS INT.

DEF VAR nbytes AS INT INIT 0.

/* For the sake of sanity */
DO k = 1 TO 32:  /* Apnuliname visus bitus */
        csbits[k] = false.
        END.

buflen = LENGTH(buf).
IF buflen = 0 THEN RETURN.

nbytes = nbytes + buflen.
DO j = 1 TO buflen BY 4:
    /* Imame kiekvieną ketvirtuką pranesimo baitų 
       ir formuojame is jų long INT.
       Take every four bytes from the string 
       and form a long INT from it. 
    */

    c4sum = 256 * 256 * 256 *
      (IF j > buflen THEN 0 ELSE asc(SUBSTRING(buf, j, 1))).
    c4sum = c4sum + 256 * 256 * 
      (IF (j + 1) > buflen THEN 0 ELSE asc(SUBSTRING(buf, j + 1, 1))).
    c4sum = c4sum + 256 *
      (IF (j + 2) > buflen THEN 0 ELSE asc(SUBSTRING(buf, j + 2, 1))).
    c4sum = c4sum + 
      (IF (j + 3) > buflen THEN 0 ELSE asc(SUBSTRING(buf, j + 3, 1))).

    bignum = 256 * 256 * 256 * 64.
                
    /* Skaidome long INT i bitus 
     * Split long INT to bits
     */
    IF c4sum < 0 THEN c4bits[1] = true.
    DO k = 2 TO 32:
        IF c4sum < bignum THEN c4bits[k] = false.
        ELSE DO:
            c4sum = c4sum - bignum.
            c4bits[k] = true.
            END.
        bignum = bignum / 2.
        END.

    DO k = 1 TO 32:  /* XOR operation */
       csbits[k] = IF csbits[k] = c4bits[k] THEN true ELSE false.
       END.

    END. /* DO j = 1... */

/* formuojame long INT is bitų
 * Form a long INT from the bits
 */
bignum = 1.
checksum = 0.

DO k = 32 TO 1 BY -1:
    IF csbits[k] THEN checksum = checksum + bignum.
    bignum = 2 * bignum.
    END.

END. /* PROC checksum */

  You can freely use this code in any of your projects, however the reference to the author in your code is mandatory.



-->