RosettaCodeData/Task/IBAN/DBL/iban.dbl
2023-07-01 13:44:08 -04:00

156 lines
4.6 KiB
Text

;
; Validate IBAN for DBL version 4 by Dario B.
;
; Compile with "dbl -r" to reinitialize all data each time
; the module (main or subroutine) is entered.
;
RECORD
J, D5
ISVALID, D1
IBAN, A35,'GB82 WEST 1234 5698 7654 32'
, A35,'GB82 TEST 1234 5698 7654 32'
, A35,'GR16 0110 1250 0000 0001 2300 695'
, A35,'GB29 NWBK 6016 1331 9268 19'
, A35,'SA03 8000 0000 6080 1016 7519'
, A35,'CH93 0076 2011 6238 5295 7'
, A35,'IL62 0108 0000 0009 9999 999'
, A35,'US12 3456 7890 0987 6543 210'
, A35,'GR16 0110 1250 0000 0001 2300 695X'
PROC
;-------------------------------------------------------------------------------
XCALL FLAGS (0007000000,1) ;Suppress STOP message
OPEN (1,O,'TT:') ;Open video
FOR J=1 UNTIL 9
DO BEGIN
XCALL CHECK_IBAN (IBAN(J),ISVALID)
IF (ISVALID.EQ.1)
THEN DISPLAY (1,IBAN(J),' is valid',10)
ELSE DISPLAY (1,IBAN(J),' is not valid',10)
END
CLOSE 1
END
;===============================================================================
; CHECK AND VALIDATE IBAN SUBROUTINE
;===============================================================================
SUBROUTINE CHECK_IBAN
IBAN, A ;IBAN code
ISVALID, D ;0=is not valid 1=is valid
RECORD
K, D5
J, D5
D2, D2
D3, D3
D9, D9
A9, A9
IBANC, A35
IINT, A80
PARTS, D2
MOD, D5
.DEFINE NC,75 ;numbers of ISO / LEN in table
ISOCK, [NC]A4,'AD24','AE23','AL28','AT20','AZ28','BA20','BE16','BG22','BH22','BR29',
&'BY28','CH21','CR22','CY28','CZ24','DE22','DK18','DO28','EE20','ES24',
&'FI18','FO18','FR27','GB22','GE22','GI23','GL18','GR27','GT28','HR21',
&'HU28','IE22','IL23','IQ23','IS26','IT27','JO30','KW30','KZ20','LB28',
&'LC32','LI21','LT20','LU20','LV21','MC27','MD24','ME22','MK19','MR27',
&'MT31','MU30','NL18','NO15','PK24','PL28','PS29','PT25','QA29','RO24',
&'RS22','SA24','SC31','SE24','SI19','SK24','SM27','ST25','SV28','TL23',
&'TN24','TR26','UA29','VG24','XK20'
PROC
;-------------------------------------------------------------------------------
CLEAR IBANC,IINT ;Not required when compiled with dbl -r
;Remove blanks
K=
FOR J=1 UNTIL %TRIM(IBAN) DO IF (IBAN(J:1).NE.' ')
BEGIN
INCR K
IBANC(K:1)=IBAN(J:1)
END
;Check ISO code and len
UPCASE IBANC
FOR J=1 UNTIL NC DO IF (IBANC(1:2).EQ.ISOCK[J](1:2)) EXITLOOP
IF (J.GT.NC)
BEGIN
;ISO not found in table, returns ISVALID=0
ISVALID=
XRETURN
END
D2=ISOCK[J](3:2)
IF (%TRIM(IBANC).NE.D2)
BEGIN
;wrong len returns ISVALID=0
ISVALID=
XRETURN
END
; Now, do this
; IBAN: GB82WEST12345698765432
; Rearrange: WEST12345698765432GB82
; Convert to integer: 3214282912345698765432161182
; Compute remainder: 3214282912345698765432161182 mod 97 = 1
;Move the first four characters to the end
IBANC(%TRIM(IBANC)+1:4)=IBANC(1:4)
IBANC=IBANC(5,$LEN(IBANC))
;Convert A to 10, B to 11 ... Z
K=1
FOR J=1 UNTIL %TRIM(IBANC)
DO BEGIN
IF (IBANC(J:1).GE.'A'.AND.IBANC(J:1).LE.'Z')
THEN BEGIN
XCALL DECML (IBANC(J:1),D3)
IINT(K:2)=D3-55,'XX'
K=K+2
END
ELSE BEGIN
IINT(K:1)=IBANC(J:1)
INCR K
END
END
;Calculate the mod 97 of large number.
;Implements a stepwise check for mod 97 in chunks of 9 at the first time,
;then in chunks of seven prepended by the last mod 97 operation converted
;to a string
PARTS=1+(%TRIM(IINT)-9)/7
IF ((PARTS-1)*7.LT.%TRIM(IINT)-9) INCR PARTS
FOR J=1 UNTIL PARTS
DO BEGIN
IF (J.EQ.1) THEN A9=IINT(1:9)
ELSE BEGIN
A9(1:2)=MOD,'XX'
A9(3:7)=IINT(10+(J-2)*7:7)
END
D9=A9
MOD=D9-(D9/97)*97
END
IF (MOD.EQ.1) ISVALID=1
ELSE ISVALID=
XRETURN
END