|
33 | 33 | ! POSSIBILITY OF SUCH DAMAGE.
|
34 | 34 |
|
35 | 35 | program main
|
| 36 | + !! input: acceptable compiler version the form major.minor.patch |
| 37 | + !! output: |
| 38 | + !! .true. if compiler version >= acceptable version |
| 39 | + !! .false. otherwise |
36 | 40 | use iso_fortran_env, only : compiler_version
|
37 | 41 | implicit none
|
38 |
| - integer, parameter :: first_argument=1 |
| 42 | + |
| 43 | + integer, parameter :: first_argument=1, max_version_length=len('999.999.999') |
39 | 44 | integer stat
|
40 |
| - character(len=9) version_number |
41 |
| - call get_command_argument(first_argument,version_number,status=stat) |
42 |
| - select case(stat) |
43 |
| - case(-1) |
44 |
| - error stop "acceptable_compiler.f90: insufficient string length in attempt to read command argument" |
45 |
| - case(0) |
46 |
| - ! successful command argument read |
47 |
| - case(1:) |
48 |
| - error stop "acceptable_compiler.f90: no version-number supplied" |
49 |
| - case default |
50 |
| - error stop "invalid status" |
51 |
| - end select |
52 |
| - print *,(compiler_version() >= "GCC version "//adjustl(trim(version_number))//" ") |
| 45 | + character(len=max_version_length) acceptable_version |
| 46 | + |
| 47 | + call get_command_argument(first_argument,acceptable_version,status=stat) |
| 48 | + call validate_command_line( stat ) |
| 49 | + |
| 50 | + associate( compiler_version=> compiler_version() ) |
| 51 | + associate(major_version=>major(compiler_version), acceptable_major=>major(acceptable_version)) |
| 52 | + if ( major_version > acceptable_major ) then |
| 53 | + print *,.true. |
| 54 | + else if ( major_version == acceptable_major ) then |
| 55 | + associate(minor_version=>minor(compiler_version), acceptable_minor=>minor(acceptable_version)) |
| 56 | + if ( minor_version > acceptable_minor ) then |
| 57 | + print *,.true. |
| 58 | + else if ( minor_version == acceptable_minor ) then |
| 59 | + associate(patch_version=>patch(compiler_version), acceptable_patch=>patch(acceptable_version)) |
| 60 | + if ( patch_version >= acceptable_patch ) then |
| 61 | + print *,.true. |
| 62 | + else |
| 63 | + print *,.false. |
| 64 | + end if |
| 65 | + end associate |
| 66 | + else |
| 67 | + print *,.false. |
| 68 | + end if |
| 69 | + end associate |
| 70 | + else |
| 71 | + print *,.false. |
| 72 | + end if |
| 73 | + end associate |
| 74 | + end associate |
| 75 | + |
| 76 | +contains |
| 77 | + |
| 78 | + subroutine validate_command_line( command_line_status ) |
| 79 | + integer, intent(in) :: command_line_status |
| 80 | + select case(command_line_status) |
| 81 | + case(-1) |
| 82 | + error stop "acceptable_compiler.f90: insufficient string length in attempt to read command argument" |
| 83 | + case(0) |
| 84 | + ! successful command argument read |
| 85 | + case(1:) |
| 86 | + error stop "acceptable_compiler.f90: no version-number supplied" |
| 87 | + case default |
| 88 | + error stop "invalid status" |
| 89 | + end select |
| 90 | + end subroutine |
| 91 | + |
| 92 | + pure function major(version_string) result(major_value) |
| 93 | + character(len=*), intent(in) :: version_string |
| 94 | + integer major_value |
| 95 | + character(len=:), allocatable :: leading_digits |
| 96 | + |
| 97 | + associate( first_dot => scan(version_string, '.') ) |
| 98 | + associate( first_digit => scan( version_string(1:first_dot-1), '0123456789' ) ) |
| 99 | + leading_digits = version_string( first_digit : first_dot-1 ) |
| 100 | + read(leading_digits,*) major_value |
| 101 | + end associate |
| 102 | + end associate |
| 103 | + |
| 104 | + end function |
| 105 | + |
| 106 | + pure function minor(version_string) result(minor_value) |
| 107 | + character(len=*), intent(in) :: version_string |
| 108 | + integer minor_value |
| 109 | + character(len=:), allocatable :: middle_digits |
| 110 | + |
| 111 | + associate( first_dot => scan(version_string, '.') ) |
| 112 | + associate( second_dot => first_dot + scan(version_string(first_dot+1:), '.') ) |
| 113 | + middle_digits = version_string( first_dot+1 : second_dot-1 ) |
| 114 | + read(middle_digits,*) minor_value |
| 115 | + end associate |
| 116 | + end associate |
| 117 | + |
| 118 | + end function |
| 119 | + |
| 120 | + pure function patch(version_string) result(patch_value) |
| 121 | + character(len=*), intent(in) :: version_string |
| 122 | + integer patch_value |
| 123 | + character(len=:), allocatable :: trailing_digits |
| 124 | + |
| 125 | + associate( first_dot => scan(version_string, '.') ) |
| 126 | + associate( second_dot => first_dot + scan(version_string(first_dot+1:), '.') ) |
| 127 | + associate( first_non_digit=> second_dot + first_printable_non_digit(version_string(second_dot+1:)) ) |
| 128 | + trailing_digits = version_string( second_dot+1 : first_non_digit-1 ) |
| 129 | + read(trailing_digits,*) patch_value |
| 130 | + end associate |
| 131 | + end associate |
| 132 | + end associate |
| 133 | + |
| 134 | + end function |
| 135 | + |
| 136 | + pure function first_printable_non_digit( string ) result(location) |
| 137 | + character(len=*), intent(in) :: string |
| 138 | + integer i, location |
| 139 | + integer, parameter :: ASCII_non_digit(*)=[(i,i=32,47),(i,i=58,126)] |
| 140 | + character(len=1), parameter :: non_digit(*)=[( char(ASCII_non_digit(i)) , i=1, size(ASCII_non_digit) )] |
| 141 | + character(len=size(non_digit)) non_digit_string |
| 142 | + write(non_digit_string,'(85a)') non_digit |
| 143 | + location = scan(string,non_digit_string) |
| 144 | + end function |
| 145 | + |
53 | 146 | end program
|
0 commit comments