/*REXX*/
/*---CRC32 - DOS/Win/Wine - PCREXX/Regina/OOREXX/BREXX/Reginald/ --------------------------------- 20191130 ------------------------------------*/
/* CRC32  (32 bit Cyclic Redundancy Check)  checksum  for a string - ISO 3309                                                                   */
/* Not for SPF4/5 REXX as very CPU Intensive.                                                                                                   */
/* Shows that REXX can indeed use very large strings (over 4,000 characters long) and do very accurate math operations.                         */
/*----------------------------------------------------------------------------------------------------------------------------------------------*/
  parse version name level date1 date2 date3; parse source TOS ZED                                       ;/*Det REXX Info*/
  IF TRANSLATE(LEFT(TOS,3)) == "WIN" THEN SL = 1;ELSE SL = 0                                             ;/*Det Win or Nix*/
NUMERIC DIGITS 20                                                                                        ;/*Set # Significant Digits*/
S.1 = "The quick brown fox jumps over the lazy dog"                                                      ;/*Build Strings*/
S.2 = "Generate CRC32 Checksum For Byte Array Example"
S.3 = "NSA Rocks in Wyoming!!!!!"
S.4 = "This is a really long string because sometimes they just are and sometimes you need to compute the crc of a really really long string"
S.5 = "";DO 17; S.5 = S.5||TRANSLATE(S.1||S.2||S.3||S.4);END
S.6 = S.5||"1234567890!@#$%^&*()_+=-qwertyuiop{}}|[]\QWERTYUIOPasdfghjkl:ASDFGHJKL;zxcvbnm<>?ZXCVBNM,./"
IF SL = 1 THEN 'CLS';ELSE 'CLEAR'                                                                        ;/*Send CMD to OS*/
DO CNT = 1 TO 6                                                                                          ;/*Loop thru test strings*/
  X = S.CNT; CS = CRC32(X)                                                                               ;/*Calculate CRC*/
  SAY COPIES("-",79);                                                                                    ;/*Disp Separator*/
  SAY LENGTH(X)" Bytes - HEX CRC = "CS" - DEC CRC ="||X2D(CS)                                            ;/*Disp CRC Hex/Dec*/
  SAY X                                                                                                  ;/*Disp String*/
END
EXIT
/*----------------------------------------------------------------------------------------------------------------------------------------------*/
CRC32: PROCEDURE; PARSE ARG E,S                                                                          ;/*Calc HEX CRC for String E*/
  NUMERIC DIGITS 20
  C= 'edb88320'x                                                                                         ;/*Build 8 bit  indexed table*/
  F= 'ffFFffFF'x                                                                                         ;/*User CRC*/
  DO I = 0  FOR 256
     Z= D2C(I)                                                                                           ;/*One byte at a time*/
     R= RIGHT(Z,4,'0'x)                                                                                  ;/*Insure R is 32 bits*/
     DO J=0  FOR 8;                                                                                      ;/*Handle each rightmost byte bit*/
        RB = X2B(C2X(R))                                                                                 ;/*Handle each bit of rightmost 8 bits*/
        R = X2C(B2X(0 || LEFT(RB,31)))                                                                   ;/*Shift it right (unsigned) 1 bit*/
        IF RIGHT(RB,1) THEN R = BITXOR(R,C)                                                              ;/*Bin bit for XOR grunt work*/
     END
     E.Z = R                                                                                             ;/*Assign to 8 bit index table*/
  END                                                                                                    ;
  S=BITXOR(WORD(S '0000000'x, 1), F)                                                                     ;/*Utilize the user's CRC or a default*/
  DO K=1 FOR LENGTH(E)                                                                                   ;/*Start number crunching input data*/
     Q= BITXOR(RIGHT(S,1),SUBSTR(E,K,1) )
     S= BITXOR('0'x || LEFT(S,3),E.Q)
  END
  T = BITXOR(S,F)
RETURN C2X(T)                                                                                            ;/*Return CRC in HEX*/