61 use iso_fortran_env,
only : iostat_end
70 implicit none;
private
75 integer,
parameter,
private :: INCLUDE_TYPE_SYSTEM = 1
76 integer,
parameter,
private :: INCLUDE_TYPE_LOCAL = 2
78 integer,
parameter,
private :: MAX_PATH_LEN = 256
80 integer,
parameter,
private :: MAX_PATH_LEN = 4096
89 subroutine read_unit(iunit, ounit, macros, from_include)
92 integer,
intent(in) :: iunit
93 integer,
intent(in) :: ounit
94 type(macro),
allocatable,
intent(inout) :: macros(:)
95 logical,
intent(in) :: from_include
117 type(
context),
intent(in) :: ctx
118 integer,
intent(in) :: ounit
120 type(
macro),
allocatable,
intent(inout) :: macros(:)
121 character(*),
intent(in) :: token
123 character(:),
allocatable :: include_file
124 character(:),
allocatable :: dir, ifile
125 character(:),
allocatable :: sys_paths(:)
126 integer :: i, iunit, ierr, pos
127 integer :: include_type
134 include_file =
trim(adjustl(ctx%content(pos:)))
137 if (include_file(1:1) ==
'"')
then
138 include_type = include_type_local
139 include_file = include_file(2:
index(include_file(2:),
'"'))
140 else if (include_file(1:1) ==
'<')
then
141 include_type = include_type_system
142 include_file = include_file(2:
index(include_file(2:),
'>'))
146 message=
'Malformed #include directive', &
147 label=
label_type(
'Filepath should either be delimited by "<...>" or "..."',
index(ctx%content, include_file),
len(include_file)), &
148 source=
trim(ctx%path)), &
149 ctx%content, ctx%line))
156 inquire(file=ifile, exist=exists)
162 message=
'File not found', &
163 label=
label_type(
'Cannot find include file ' //
trim(include_file),
index(ctx%content, include_file),
len(include_file)), &
164 source=
trim(ctx%path)), &
165 ctx%content, ctx%line))
173 ifile =
join(dir, include_file)
174 if (include_type == include_type_local)
then
175 ifile =
join(dir, include_file)
176 inquire(file=ifile, exist=exists)
183 if (.not. exists .and.
allocated(
global%includedir))
then
184 do i = 1,
size(
global%includedir)
185 ifile =
join(
global%includedir(i), include_file)
186 inquire(file=ifile, exist=exists)
195 if (.not. exists)
then
197 character(:),
allocatable :: ipaths(:)
200 do i = 1,
size(ipaths)
201 ifile =
join(ipaths(i), include_file)
202 inquire(file=ifile, exist=exists)
211 if (.not. exists)
then
212 ifile =
join(
cwd(), include_file)
213 inquire(file=ifile, exist=exists)
220 if (.not. exists)
then
222 message=
'File not found', &
223 label=
label_type(
'Cannot find include file ' //
trim(include_file),
index(ctx%content, include_file),
len(include_file)), &
224 source=
trim(ctx%path)), &
225 ctx%content, ctx%line))
231 open(newunit=iunit, file=include_file, status=
'old', action=
'read', iostat=ierr)
234 message=
'File not found', &
235 label=
label_type(
'Cannot open include file ' //
trim(include_file),
index(ctx%content, include_file),
len(include_file)), &
236 source=
trim(ctx%path)), &
237 ctx%content, ctx%line))
241 call preprocess(iunit, ounit, macros, .true.)
252 character(:),
allocatable :: paths(:)
254 character(:),
allocatable :: path_env, tmp(:)
255 integer :: lpath, i, n_paths, start_pos, end_pos, count
256 character(len=1) :: path_sep
265 call get_environment_variable(
'INCLUDE', length=lpath)
267 allocate(
character(len=0) :: paths(0)); return
271 allocate(
character(len=lpath) :: path_env)
272 call get_environment_variable(
'INCLUDE',
value=path_env)
276 do i = 1, len(path_env)
277 if (path_env(i:i) == path_sep) n_paths = n_paths + 1
281 allocate(
character(len=MAX_PATH_LEN) :: tmp(n_paths))
286 do i = 1, len(path_env) + 1
287 if (i > len(path_env) .or. path_env(i:i) == path_sep)
then
288 if (i > len(path_env))
then
294 if (end_pos >= start_pos)
then
296 tmp(count) = trim(adjustl(path_env(start_pos:end_pos)))
304 allocate(
character(len=MAX_PATH_LEN) :: paths(count))
305 paths(:) = tmp(1:count)
307 allocate(
character(len=0) :: paths(0))
type(global_settings), public global
The single global instance used throughout fpx Initialized automatically with sensible defaults value...
recursive subroutine, public handle_include(ctx, ounit, preprocess, macros, token)
Process a include directive encountered during preprocessing Resolves the include file name (quoted o...
character(:) function, dimension(:), allocatable get_system_paths()
Get system include paths from PATH environment variable Returns an array of directory paths found in ...
logical, public verbose
Master switch for verbose diagnostic output Default value is .false. (quiet mode)....
pure logical function is_rooted(filepath)
Returns .true. if the path is rooted (starts with a separator) or is absolute. A rooted path begins w...
pure character(:) function, allocatable dirpath(filepath)
Returns the directory part of a path (everything before the last separator).
character(:) function, allocatable cwd()
Returns the current working directory as a deferred-length character string. Returns empty string on ...
pure character(len_trim(str)) function, public lowercase(str)
Convert string to lower case (respects contents of quotes).
Abstract interface for the main preprocessing routine (used for recursion) Allows handle_include to r...
Interface to render diagnostic messages and labels.
Generic interface for joining two path components Supports all combinations of character and string a...
Return the length of a string.
Return the trimmed string.
Source location and content snapshot for precise diagnostics Instances of this type are created for e...
Definition of diagnostic message.
Represents text as a sequence of ASCII code units. The derived type wraps an allocatable character ar...
Derived type representing a single preprocessor macro Extends string with macro-specific fields: rep...