* * Check one or more ISINs specified as command line arguments * PROGRAM VALIDATE_ISIN IMPLICIT NONE CHARACTER*13 ISIN INTEGER I LOGICAL IS_ISIN DO I = 1, IARGC() CALL GETARG(I, ISIN) IF (IS_ISIN(ISIN)) THEN PRINT *, 'ISIN ''', ISIN, ''' is valid' ELSE PRINT *, 'ISIN ''', ISIN, ''' is invalid' ENDIF ENDDO STOP END * * Checks whether an ISIN is valid * LOGICAL FUNCTION IS_ISIN(ISIN) CHARACTER*13 ISIN INTEGER I INTEGER NEWSUM, OLDSUM INTEGER D1 INTEGER D2 LOGICAL MULTIPLY LOGICAL IS_DIGIT LOGICAL IS_UPPER IF (LEN_TRIM(ISIN) .NE. 12) THEN IS_ISIN = .FALSE. RETURN ENDIF IF (IS_DIGIT(ISIN(12:12)) .EQV. .FALSE.) THEN IS_ISIN = .FALSE. RETURN ENDIF NEWSUM = 0 MULTIPLY = .TRUE. DO I = 11, 1, -1 IF (I .EQ. 0 .OR. I .EQ. 1) THEN IF (IS_UPPER(ISIN(I:I))) THEN D1 = IACHAR(ISIN(I:I)) - IACHAR('A') + 10 ELSE IS_ISIN = .FALSE. RETURN ENDIF ELSE IF (IS_UPPER(ISIN(I:I))) THEN D1 = IACHAR(ISIN(I:I)) - IACHAR('A') + 10 ELSE IF (IS_DIGIT(ISIN(I:I))) THEN D1 = IACHAR(ISIN(I:I)) - IACHAR('0') ELSE IS_ISIN = .FALSE. RETURN ENDIF ENDIF IF (D1 .LT. 10) THEN IF (MULTIPLY) THEN D1 = D1 * 2 ENDIF MULTIPLY = .NOT. MULTIPLY ELSE D2 = D1 / 10 D1 = MOD(D1, 10) IF (MULTIPLY) THEN D1 = D1 * 2 ELSE D2 = D2 * 2 ENDIF NEWSUM = NEWSUM + MOD(D2, 10) + (D2 / 10) ENDIF NEWSUM = NEWSUM + MOD(D1, 10) + (D1 / 10) ENDDO NEWSUM = MOD(NEWSUM, 10) NEWSUM = 10 - NEWSUM NEWSUM = MOD(NEWSUM, 10) OLDSUM = IACHAR(ISIN(12:12)) - IACHAR('0') IF (OLDSUM .NE. NEWSUM) THEN IS_ISIN = .FALSE. RETURN ENDIF IS_ISIN = .TRUE. RETURN END * * Checks whether a character is a digit * LOGICAL FUNCTION IS_DIGIT(C) CHARACTER*1 C CHARACTER*10 DIGIT INTEGER INDX DIGIT = '0123456789' INDX = INDEX(DIGIT, C) IF (INDX .NE. 0) THEN IS_DIGIT = .TRUE. ELSE IS_DIGIT = .FALSE. ENDIF RETURN END * * Checks whether a character is an uppercase letter * LOGICAL FUNCTION IS_UPPER(C) CHARACTER*1 C CHARACTER*26 UPPER INTEGER INDX UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' INDX = INDEX(UPPER, C) IF (INDX .NE. 0) THEN IS_UPPER = .TRUE. ELSE IS_UPPER = .FALSE. ENDIF RETURN END