Is there XOR operator in Progress?
There is AND, OR and NOT, so, i can code "XOR" like this:
(a OR b) AND NOT (a AND b)
I just want to know if the operator exists (with another name).
Thanks.
Unfortunately, there is no such inbuilt operator in Progress.
You can implement it in the way you said.
There is no built-in XOR. But you might find this helpful:
/* _md5.i
RSA Data Security, Inc. MD5 Message-Digest Algorithm
Progress implementation courtesy Ultramain Systems, Inc.
12/20/00 Andrew Brooman
*/
&IF DEFINED ( BROOMAN_MD5_IMPLEMENTATION ) EQ 0 &THEN
&GLOBAL-DEFINE BROOMAN_MD5_IMPLEMENTATION
/* 12/20/00 Andrew Brooman
NOTES:
1) The MD5 algorithm is described at www.landfield.com/rfcs/rfc1321.html.
2) For ease of debugging, I have used the variable names from the algorithm
as described (e.g. M, A, B, C, D, X, Y, Z, FF, GG, HH, II) hence the
inconsistency with Progress naming conventions (e.g. cMessage).
3) A "word" in this algorithm is a long word (32 bits).
4) Progress INTEGERs are signed long words. Despite the signing,
AND, OR, XOR, NOT, Shift, Add seem to work fine. You will notice
use of negative numbers (e.g. initializing MD5 buffers A B C D) when
the high-order bit needs to be set.
MAX INT = +2147483647
MIN INT = -2147483648
MAX INT + 1 = MIN INT (overflows)
29 Aug 2006 Greg Higgins
Removed Functions to _md5.i
Added Preprocessor BROOMAN_MD5_IMPLEMENTATION
Added some ASSIGN statements
*/
/* bitwise logical operations on long words */
FUNCTION bitAND RETURNS INTEGER (INPUT X AS INTEGER, INPUT Y AS INTEGER):
DEFINE VARIABLE b1 AS INTEGER NO-UNDO.
DEFINE VARIABLE b2 AS INTEGER NO-UNDO.
DEFINE VARIABLE n AS INTEGER NO-UNDO.
DEFINE VARIABLE Z AS INTEGER NO-UNDO.
DO n = 1 TO 32:
ASSIGN
b1 = GET-BITS(X, n, 1)
b2 = GET-BITS(Y, n, 1)
.
IF b1 = 1 AND b2 = 1 THEN PUT-BITS(Z, n, 1) = 1.
END.
RETURN Z.
END FUNCTION.
FUNCTION bitNOT RETURNS INTEGER (INPUT X AS INTEGER):
DEFINE VARIABLE b AS INTEGER NO-UNDO.
DEFINE VARIABLE n AS INTEGER NO-UNDO.
DEFINE VARIABLE Z AS INTEGER NO-UNDO.
DO n = 1 TO 32:
b = GET-BITS(X, n, 1).
IF b = 0 THEN PUT-BITS(Z, n, 1) = 1.
END.
RETURN Z.
END FUNCTION.
FUNCTION bitOR RETURNS INTEGER (INPUT X AS INTEGER, INPUT Y AS INTEGER):
DEFINE VARIABLE b1 AS INTEGER NO-UNDO.
DEFINE VARIABLE b2 AS INTEGER NO-UNDO.
DEFINE VARIABLE n AS INTEGER NO-UNDO.
DEFINE VARIABLE Z AS INTEGER NO-UNDO.
DO n = 1 TO 32:
ASSIGN
b1 = GET-BITS(X, n, 1)
b2 = GET-BITS(Y, n, 1)
.
IF b1 = 1 OR b2 = 1 THEN PUT-BITS(Z, n, 1) = 1.
END.
RETURN Z.
END FUNCTION.
FUNCTION bitShift RETURNS INTEGER (INPUT X AS INTEGER, INPUT S AS INTEGER):
DEFINE VARIABLE Z AS INTEGER NO-UNDO.
ASSIGN
PUT-BITS(Z, 1, s) = GET-BITS(X, 33 - s, s)
PUT-BITS(Z, s + 1, 32 - s) = GET-BITS(X, 1, 32 - s)
.
RETURN Z.
END FUNCTION.
FUNCTION bitXOR RETURNS INTEGER (INPUT X AS INTEGER, INPUT Y AS INTEGER):
DEFINE VARIABLE b1 AS INTEGER NO-UNDO.
DEFINE VARIABLE b2 AS INTEGER NO-UNDO.
DEFINE VARIABLE n AS INTEGER NO-UNDO.
DEFINE VARIABLE Z AS INTEGER NO-UNDO.
DO n = 1 TO 32:
ASSIGN
b1 = GET-BITS(X, n, 1)
b2 = GET-BITS(Y, n, 1)
.
IF b1 + b2 = 1 THEN PUT-BITS(Z, n, 1) = 1.
END.
RETURN Z.
END FUNCTION.
/* function to convert integer to hex (starting with low order byte first) */
FUNCTION hexGet RETURNS CHARACTER (INPUT X AS INTEGER):
DEFINE VARIABLE b1 AS INTEGER NO-UNDO.
DEFINE VARIABLE b2 AS INTEGER NO-UNDO.
DEFINE VARIABLE n AS INTEGER NO-UNDO.
DEFINE VARIABLE h AS CHARACTER NO-UNDO INITIAL "0123456789abcdef".
DEFINE VARIABLE Z AS CHARACTER NO-UNDO.
DO n = 0 TO 3:
ASSIGN
b1 = GET-BITS(X, n * 8 + 5, 4)
b2 = GET-BITS(X, n * 8 + 1, 4)
.
Z = Z + SUBSTRING(h, b1 + 1, 1) + SUBSTRING(h, b2 + 1, 1).
END.
RETURN Z.
END FUNCTION.
/* MD5 operations */
FUNCTION F RETURNS INTEGER(INPUT X AS INTEGER, INPUT Y AS INTEGER,
INPUT Z AS INTEGER):
RETURN bitOR(bitAND(X,Y), bitAND(bitNOT(X),Z)).
END FUNCTION.
FUNCTION G RETURNS INTEGER(INPUT X AS INTEGER, INPUT Y AS INTEGER,
INPUT Z AS INTEGER):
RETURN bitOR(bitAND(X, Z), bitAND(Y, bitNOT(Z))).
END FUNCTION.
FUNCTION H RETURNS INTEGER(INPUT X AS INTEGER, INPUT Y AS INTEGER,
INPUT Z AS INTEGER):
RETURN bitXOR(bitXOR(X, Y), Z).
END FUNCTION.
FUNCTION I RETURNS INTEGER(INPUT X AS INTEGER, INPUT Y AS INTEGER,
INPUT Z AS INTEGER):
RETURN bitXOR(Y, bitOR(X, bitNOT(Z))).
END FUNCTION.
/* in the following operations, notice the values for X[k] and T[i]
are passed in rather than looked up--slight deviation from standard */
PROCEDURE Round1:
DEFINE INPUT-OUTPUT PARAMETER a AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER b AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER c AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER d AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Xk AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER s AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Ti AS INTEGER NO-UNDO.
a = b + bitShift(a + F(b, c, d) + Xk + Ti, s).
END PROCEDURE.
PROCEDURE Round2:
DEFINE INPUT-OUTPUT PARAMETER a AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER b AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER c AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER d AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Xk AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER s AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Ti AS INTEGER NO-UNDO.
a = b + bitShift(a + G(b, c, d) + Xk + Ti, s).
END PROCEDURE.
PROCEDURE Round3:
DEFINE INPUT-OUTPUT PARAMETER a AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER b AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER c AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER d AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Xk AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER s AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Ti AS INTEGER NO-UNDO.
a = b + bitShift(a + H(b, c, d) + Xk + Ti, s).
END PROCEDURE.
PROCEDURE Round4:
DEFINE INPUT-OUTPUT PARAMETER a AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER b AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER c AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER d AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Xk AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER s AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER Ti AS INTEGER NO-UNDO.
a = b + bitShift(a + I(b, c, d) + Xk + Ti, s).
END PROCEDURE.
/* main function to compute an MD5 digest */
FUNCTION MD5 RETURNS CHARACTER (INPUT cMessage AS CHARACTER):
DEFINE VARIABLE A AS INTEGER NO-UNDO.
DEFINE VARIABLE AA AS INTEGER NO-UNDO.
DEFINE VARIABLE B AS INTEGER NO-UNDO.
DEFINE VARIABLE BB AS INTEGER NO-UNDO.
DEFINE VARIABLE C AS INTEGER NO-UNDO.
DEFINE VARIABLE CC AS INTEGER NO-UNDO.
DEFINE VARIABLE D AS INTEGER NO-UNDO.
DEFINE VARIABLE DD AS INTEGER NO-UNDO.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE j AS INTEGER NO-UNDO.
DEFINE VARIABLE M AS MEMPTR NO-UNDO.
DEFINE VARIABLE N AS INTEGER NO-UNDO.
DEFINE VARIABLE X AS INTEGER NO-UNDO EXTENT 16.
DEFINE VARIABLE cDigest AS CHARACTER NO-UNDO.
DEFINE VARIABLE iLenOrig AS INTEGER NO-UNDO.
DEFINE VARIABLE iLenPadded AS INTEGER NO-UNDO.
DEFINE VARIABLE iPadding AS INTEGER NO-UNDO.
/* compute original message length */
iLenOrig = LENGTH(cMessage).
/* compute padded message length:
a) must be a multiple of 64 bytes
b) must have at least 9 bytes of padding
*/
iPadding = 64 - iLenOrig MOD 64.
IF iPadding < 9 THEN iPadding = iPadding + 64.
iLenPadded = iLenOrig + iPadding.
/* create MEMPTR to hold message since we need to manipulate bits,
bytes, and long words */
ASSIGN
SET-SIZE(M) = iLenPadded
SET-BYTE-ORDER(M) = 3 /* little-endian */
.
/* add padding */
ASSIGN
PUT-STRING(M, 1, iLenOrig) = cMessage
PUT-BYTE(M, iLenOrig + 1) = 128
PUT-LONG(M, iLenPadded - 7) = iLenOrig * 8
.
/* initialize MD registers */
ASSIGN
A = 1732584193
B = -271733879
C = -1732584194
D = 271733878
.
/* process message in N blocks of 16 words (64 bytes) */
N = iLenPadded / 64 - 1.
DO i = 0 TO N:
/* copy 16 words into working buffer X */
DO j = 0 TO 15:
X[j + 1] = GET-LONG(M, i * 64 + j * 4 + 1).
END.
/* store current MD5 registers */
ASSIGN
AA = A
BB = B
CC = C
DD = D
.
/* note: in the following rounds, minor changes were made:
a) X[k] is passed rather than k
b) T[i] is passed rather that i
c) because Progress has one based arrays, the subscript
for X[k] is one higher than the standard algorithm
*/
/* round 1 */
RUN Round1(INPUT-OUTPUT A, B, C, D, X[1], 7, -680876936).
RUN Round1(INPUT-OUTPUT D, A, B, C, X[2], 12, -389564586).
RUN Round1(INPUT-OUTPUT C, D, A, B, X[3], 17, 606105819).
RUN Round1(INPUT-OUTPUT B, C, D, A, X[4], 22, -1044525330).
RUN Round1(INPUT-OUTPUT A, B, C, D, X[5], 7, -176418897).
RUN Round1(INPUT-OUTPUT D, A, B, C, X[6], 12, 1200080426).
RUN Round1(INPUT-OUTPUT C, D, A, B, X[7], 17, -1473231341).
RUN Round1(INPUT-OUTPUT B, C, D, A, X[8], 22, -45705983).
RUN Round1(INPUT-OUTPUT A, B, C, D, X[9], 7, 1770035416).
RUN Round1(INPUT-OUTPUT D, A, B, C, X[10], 12, -1958414417).
RUN Round1(INPUT-OUTPUT C, D, A, B, X[11], 17, -42063).
RUN Round1(INPUT-OUTPUT B, C, D, A, X[12], 22, -1990404162).
RUN Round1(INPUT-OUTPUT A, B, C, D, X[13], 7, 1804603682).
RUN Round1(INPUT-OUTPUT D, A, B, C, X[14], 12, -40341101).
RUN Round1(INPUT-OUTPUT C, D, A, B, X[15], 17, -1502002290).
RUN Round1(INPUT-OUTPUT B, C, D, A, X[16], 22, 1236535329).
/* round 2 */
RUN Round2(INPUT-OUTPUT A, B, C, D, X[2], 5, -165796510).
RUN Round2(INPUT-OUTPUT D, A, B, C, X[7], 9, -1069501632).
RUN Round2(INPUT-OUTPUT C, D, A, B, X[12], 14, 643717713).
RUN Round2(INPUT-OUTPUT B, C, D, A, X[1], 20, -373897302).
RUN Round2(INPUT-OUTPUT A, B, C, D, X[6], 5, -701558691).
RUN Round2(INPUT-OUTPUT D, A, B, C, X[11], 9, 38016083).
RUN Round2(INPUT-OUTPUT C, D, A, B, X[16], 14, -660478335).
RUN Round2(INPUT-OUTPUT B, C, D, A, X[5], 20, -405537848).
RUN Round2(INPUT-OUTPUT A, B, C, D, X[10], 5, 568446438).
RUN Round2(INPUT-OUTPUT D, A, B, C, X[15], 9, -1019803690).
RUN Round2(INPUT-OUTPUT C, D, A, B, X[4], 14, -187363961).
RUN Round2(INPUT-OUTPUT B, C, D, A, X[9], 20, 1163531501).
RUN Round2(INPUT-OUTPUT A, B, C, D, X[14], 5, -1444681467).
RUN Round2(INPUT-OUTPUT D, A, B, C, X[3], 9, -51403784).
RUN Round2(INPUT-OUTPUT C, D, A, B, X[8], 14, 1735328473).
RUN Round2(INPUT-OUTPUT B, C, D, A, X[13], 20, -1926607734).
/* round 3 */
RUN Round3(INPUT-OUTPUT A, B, C, D, X[6], 4, -378558).
RUN Round3(INPUT-OUTPUT D, A, B, C, X[9], 11, -2022574463).
RUN Round3(INPUT-OUTPUT C, D, A, B, X[12], 16, 1839030562).
RUN Round3(INPUT-OUTPUT B, C, D, A, X[15], 23, -35309556).
RUN Round3(INPUT-OUTPUT A, B, C, D, X[2], 4, -1530992060).
RUN Round3(INPUT-OUTPUT D, A, B, C, X[5], 11, 1272893353).
RUN Round3(INPUT-OUTPUT C, D, A, B, X[8], 16, -155497632).
RUN Round3(INPUT-OUTPUT B, C, D, A, X[11], 23, -1094730640).
RUN Round3(INPUT-OUTPUT A, B, C, D, X[14], 4, 681279174).
RUN Round3(INPUT-OUTPUT D, A, B, C, X[1], 11, -358537222).
RUN Round3(INPUT-OUTPUT C, D, A, B, X[4], 16, -722521979).
RUN Round3(INPUT-OUTPUT B, C, D, A, X[7], 23, 76029189).
RUN Round3(INPUT-OUTPUT A, B, C, D, X[10], 4, -640364487).
RUN Round3(INPUT-OUTPUT D, A, B, C, X[13], 11, -421815835).
RUN Round3(INPUT-OUTPUT C, D, A, B, X[16], 16, 530742520).
RUN Round3(INPUT-OUTPUT B, C, D, A, X[3], 23, -995338651).
/* round 4 */
RUN Round4(INPUT-OUTPUT A, B, C, D, X[1], 6, -198630844).
RUN Round4(INPUT-OUTPUT D, A, B, C, X[8], 10, 1126891415).
RUN Round4(INPUT-OUTPUT C, D, A, B, X[15], 15, -1416354905).
RUN Round4(INPUT-OUTPUT B, C, D, A, X[6], 21, -57434055).
RUN Round4(INPUT-OUTPUT A, B, C, D, X[13], 6, 1700485571).
RUN Round4(INPUT-OUTPUT D, A, B, C, X[4], 10, -1894986606).
RUN Round4(INPUT-OUTPUT C, D, A, B, X[11], 15, -1051523).
RUN Round4(INPUT-OUTPUT B, C, D, A, X[2], 21, -2054922799).
RUN Round4(INPUT-OUTPUT A, B, C, D, X[9], 6, 1873313359).
RUN Round4(INPUT-OUTPUT D, A, B, C, X[16], 10, - 30611744).
RUN Round4(INPUT-OUTPUT C, D, A, B, X[7], 15, -1560198380).
RUN Round4(INPUT-OUTPUT B, C, D, A, X[14], 21, 1309151649).
RUN Round4(INPUT-OUTPUT A, B, C, D, X[5], 6, -145523070).
RUN Round4(INPUT-OUTPUT D, A, B, C, X[12], 10, -1120210379).
RUN Round4(INPUT-OUTPUT C, D, A, B, X[3], 15, 718787259).
RUN Round4(INPUT-OUTPUT B, C, D, A, X[10], 21, -343485551).
/* update MD5 registers */
ASSIGN
A = A + AA
B = B + BB
C = C + CC
D = D + DD
.
END.
/* convert MD5 registers to hex string from low-order A to high-order D */
cDigest = hexGet(A) + hexGet(B) + hexGet(C) + hexGet(D).
/* cleanup and return */
SET-SIZE(M) = 0.
RETURN cDigest.
END FUNCTION.
&ENDIF
/* End of _md5.i */