@@ -27,15 +27,7 @@ module fpm_source_parsing
27
27
implicit none
28
28
29
29
private
30
- public :: parse_f_source, parse_c_source
31
-
32
- character (15 ), parameter :: INTRINSIC_MODULE_NAMES(* ) = &
33
- [' iso_c_binding ' , &
34
- ' iso_fortran_env' , &
35
- ' ieee_arithmetic' , &
36
- ' ieee_exceptions' , &
37
- ' ieee_features ' , &
38
- ' omp_lib ' ]
30
+ public :: parse_f_source, parse_c_source, parse_use_statement
39
31
40
32
contains
41
33
@@ -77,7 +69,7 @@ function parse_f_source(f_filename,error) result(f_source)
77
69
type (srcfile_t) :: f_source
78
70
type (error_t), allocatable , intent (out ) :: error
79
71
80
- logical :: inside_module, inside_interface
72
+ logical :: inside_module, inside_interface, using, intrinsic_module
81
73
integer :: stat
82
74
integer :: fh, n_use, n_include, n_mod, n_parent, i, j, ic, pass
83
75
type (string_t), allocatable :: file_lines(:), file_lines_lower(:)
@@ -179,59 +171,24 @@ function parse_f_source(f_filename,error) result(f_source)
179
171
end if
180
172
181
173
! Process 'USE' statements
182
- if ( index ( file_lines_lower(i)% s,' use ' ) == 1 .or. &
183
- index (file_lines_lower(i) % s, ' use:: ' ) == 1 ) then
174
+ call parse_use_statement(f_filename,i, file_lines_lower(i)% s,using,intrinsic_module,mod_name,error)
175
+ if ( allocated (error)) return
184
176
185
- if (index (file_lines_lower(i) % s, ' :: ' ) > 0 ) then
177
+ if (using ) then
186
178
187
- temp_string = split_n(file_lines_lower(i)% s,delims= ' :' ,n= 2 ,stat= stat)
188
- if (stat /= 0 ) then
189
- call file_parse_error(error,f_filename, &
190
- ' unable to find used module name' ,i, &
191
- file_lines_lower(i)% s,index (file_lines_lower(i)% s,' ::' ))
192
- return
193
- end if
179
+ ! Not a valid module name?
180
+ if (.not. is_fortran_name(mod_name)) cycle
194
181
195
- mod_name = split_n(temp_string,delims= ' ,' ,n= 1 ,stat= stat)
196
- if (stat /= 0 ) then
197
- call file_parse_error(error,f_filename, &
198
- ' unable to find used module name' ,i, &
199
- file_lines_lower(i)% s)
200
- return
201
- end if
202
-
203
- else
204
-
205
- mod_name = split_n(file_lines_lower(i)% s,n= 2 ,delims= ' ,' ,stat= stat)
206
- if (stat /= 0 ) then
207
- call file_parse_error(error,f_filename, &
208
- ' unable to find used module name' ,i, &
209
- file_lines_lower(i)% s)
210
- return
211
- end if
212
-
213
- end if
214
-
215
- if (.not. is_fortran_name(mod_name)) then
216
- cycle
217
- end if
218
-
219
- if (any ([(index (mod_name,trim (INTRINSIC_MODULE_NAMES(j)))>0 , &
220
- j= 1 ,size (INTRINSIC_MODULE_NAMES))])) then
221
- cycle
222
- end if
182
+ ! Valid intrinsic module: not a dependency
183
+ if (intrinsic_module) cycle
223
184
224
185
n_use = n_use + 1
225
186
226
- if (pass == 2 ) then
227
-
228
- f_source% modules_used(n_use)% s = mod_name
229
-
230
- end if
187
+ if (pass == 2 ) f_source% modules_used(n_use)% s = mod_name
231
188
232
189
cycle
233
190
234
- end if
191
+ endif
235
192
236
193
! Process 'INCLUDE' statements
237
194
ic = index (file_lines_lower(i)% s,' include' )
@@ -655,5 +612,117 @@ function parse_sequence(string,t1,t2,t3,t4) result(found)
655
612
656
613
end function parse_sequence
657
614
615
+ ! USE [, intrinsic] :: module_name [, only: only_list]
616
+ ! USE [, non_intrinsic] :: module_name [, only: only_list]
617
+ subroutine parse_use_statement (f_filename ,i ,line ,use_stmt ,is_intrinsic ,module_name ,error )
618
+
619
+ ! > Current file name and line number (for error messaging)
620
+ character (* ), intent (in ) :: f_filename
621
+ integer , intent (in ) :: i
622
+
623
+ ! > The line being parsed. MUST BE preprocessed with trim(adjustl()
624
+ character (* ), intent (in ) :: line
625
+
626
+ ! > Does this line contain a `use` statement?
627
+ logical , intent (out ) :: use_stmt
628
+
629
+ ! > Is the module in this statement intrinsic?
630
+ logical , intent (out ) :: is_intrinsic
631
+
632
+ ! > used module name
633
+ character (:), allocatable , intent (out ) :: module_name
634
+
635
+ ! > Error handling
636
+ type (error_t), allocatable , intent (out ) :: error
637
+
638
+ character (15 ), parameter :: INTRINSIC_NAMES(* ) = &
639
+ [' iso_c_binding ' , &
640
+ ' iso_fortran_env' , &
641
+ ' ieee_arithmetic' , &
642
+ ' ieee_exceptions' , &
643
+ ' ieee_features ' , &
644
+ ' omp_lib ' ]
645
+
646
+ character (len= :), allocatable :: temp_string
647
+ integer :: colons,intr,nonintr,j,stat
648
+ logical :: has_intrinsic_name
649
+
650
+ use_stmt = .false.
651
+ is_intrinsic = .false.
652
+ if (len_trim (line)<= 0 ) return
653
+
654
+ ! Quick check that the line is preprocessed
655
+ if (line(1 :1 )==' ' ) then
656
+ call fatal_error(error,' internal_error: source file line is not trim(adjustl()) on input to parse_use_statement' )
657
+ return
658
+ end if
659
+
660
+ ! 'use' should be the first string in the adjustl line
661
+ use_stmt = index (line,' use ' )==1 .or. index (line,' use::' )==1 .or. index (line,' use,' )==1
662
+ if (.not. use_stmt) return
663
+ colons = index (line,' ::' )
664
+ nonintr = 0
665
+ intr = 0
666
+
667
+ have_colons: if (colons> 3 ) then
668
+
669
+ ! there may be an intrinsic/non-intrinsic spec
670
+ nonintr = index (line(1 :colons-1 ),' non_intrinsic' )
671
+ if (nonintr== 0 ) intr = index (line(1 :colons-1 ),' intrinsic' )
672
+
673
+
674
+ temp_string = split_n(line,delims= ' :' ,n= 2 ,stat= stat)
675
+ if (stat /= 0 ) then
676
+ call file_parse_error(error,f_filename, &
677
+ ' unable to find used module name' ,i, &
678
+ line,colons)
679
+ return
680
+ end if
681
+
682
+ module_name = split_n(temp_string,delims= ' ,' ,n= 1 ,stat= stat)
683
+ if (stat /= 0 ) then
684
+ call file_parse_error(error,f_filename, &
685
+ ' unable to find used module name' ,i, &
686
+ line)
687
+ return
688
+ end if
689
+
690
+ else
691
+
692
+ module_name = split_n(line,n= 2 ,delims= ' ,' ,stat= stat)
693
+ if (stat /= 0 ) then
694
+ call file_parse_error(error,f_filename, &
695
+ ' unable to find used module name' ,i, &
696
+ line)
697
+ return
698
+ end if
699
+
700
+ end if have_colons
701
+
702
+ ! If declared intrinsic, check that it is true
703
+ has_intrinsic_name = any ([(index (module_name,trim (INTRINSIC_NAMES(j)))>0 , &
704
+ j= 1 ,size (INTRINSIC_NAMES))])
705
+ if (intr> 0 .and. .not. has_intrinsic_name) then
706
+
707
+ ! An intrinsic module was not found. Its name could be in the next line,
708
+ ! in which case, we just skip this check. The compiler will do the job if the name is invalid.
709
+
710
+ ! Module name was not read: it's in the next line
711
+ if (index (module_name,' &' )<= 0 ) then
712
+ call file_parse_error(error,f_filename, &
713
+ ' module ' // module_name// ' is declared intrinsic but it is not ' ,i, &
714
+ line)
715
+ return
716
+ endif
717
+ endif
718
+
719
+ ! Should we treat this as an intrinsic module
720
+ is_intrinsic = nonintr== 0 .and. & ! not declared non-intrinsic
721
+ (intr> 0 .or. has_intrinsic_name)
722
+
723
+ end subroutine parse_use_statement
724
+
725
+
726
+
658
727
end module fpm_source_parsing
659
728
0 commit comments