Skip to content

Commit 66cdbf5

Browse files
author
Damian Rouson
authored
Merge pull request #686 from sourceryinstitute/fix-#638-check-compiler-version
Fix #683 check compiler version
2 parents 9900f82 + 7008ea7 commit 66cdbf5

File tree

1 file changed

+107
-14
lines changed

1 file changed

+107
-14
lines changed

prerequisites/acceptable_compiler.f90

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,114 @@
3333
! POSSIBILITY OF SUCH DAMAGE.
3434

3535
program main
36+
!! input: acceptable compiler version the form major.minor.patch
37+
!! output:
38+
!! .true. if compiler version >= acceptable version
39+
!! .false. otherwise
3640
use iso_fortran_env, only : compiler_version
3741
implicit none
38-
integer, parameter :: first_argument=1
42+
43+
integer, parameter :: first_argument=1, max_version_length=len('999.999.999')
3944
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+
53146
end program

0 commit comments

Comments
 (0)