Skip to content

Commit 552826b

Browse files
committed
fix pathlib
1 parent 02fd41b commit 552826b

File tree

8 files changed

+166
-55
lines changed

8 files changed

+166
-55
lines changed

character/str2int.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
program str2int
1+
program str2int_demo
22
!! very simple demo of string to integer
33
implicit none
44

@@ -7,7 +7,7 @@ program str2int
77

88
x = '42'
99
m = str2int(x)
10-
if (x/=42) error stop
10+
if (m/=42) error stop
1111

1212
contains
1313

io/CMakeLists.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,20 @@ add_test(NAME io:ReadOnly COMMAND readonly)
3232
add_executable(null devnull.f90)
3333
add_test(NAME io:nullfile COMMAND null)
3434

35-
add_library(pathlib OBJECT pathlib.F90)
35+
add_library(pathlib OBJECT pathlib.f90)
3636
add_executable(test_pathlib test_pathlib.f90)
3737
target_link_libraries(test_pathlib pathlib)
3838
add_test(NAME io:pathlib COMMAND $<TARGET_FILE:test_pathlib>)
39+
if(WIN32)
40+
target_sources(pathlib PRIVATE pathlib_windows.f90)
41+
else()
42+
target_sources(pathlib PRIVATE pathlib_unix.f90)
43+
endif()
44+
if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
45+
target_sources(pathlib PRIVATE path_exists_intel.f90)
46+
else()
47+
target_sources(pathlib PRIVATE path_exists.f90)
48+
endif()
3949

4050

4151
include(CheckCSourceRuns)

io/meson.build

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ if not(os == 'windows' and fc.get_id() == 'pgi')
2222
timeout: 10, suite: 'io')
2323
endif
2424

25-
pathlib = library('pathlib', 'pathlib.F90')
25+
pathlib_src = os == 'windows' ? files('pathlib_windows.f90') : files('pathlib_unix.f90')
26+
pathlib_src += ['intel', 'intel-cl'].contains(fc.get_id()) ? files('path_exists_intel.f90') : files('path_exists.f90')
27+
28+
pathlib = library('pathlib',
29+
sources: ['pathlib.f90', pathlib_src])
2630
test_pathlib = executable('test_pathlib',
2731
sources: 'test_pathlib.f90',
2832
link_with: pathlib)

io/path_exists.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
submodule (pathlib) path_exists
2+
!! this is for non-Intel compilers
3+
implicit none
4+
5+
contains
6+
7+
module procedure assert_directory_exists
8+
!! throw error if directory does not exist
9+
!! this accomodates non-Fortran 2018 error stop with variable character
10+
11+
logical :: exists
12+
13+
inquire(file=path, exist=exists)
14+
15+
if (exists) return
16+
17+
write(stderr,*) path // ' directory does not exist'
18+
error stop
19+
20+
end procedure assert_directory_exists
21+
22+
end submodule path_exists

io/path_exists_intel.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
submodule (pathlib) path_exists
2+
!! Intel compilers require non-standard inquire(directory=)
3+
implicit none
4+
5+
contains
6+
7+
module procedure assert_directory_exists
8+
!! throw error if directory does not exist
9+
!! this accomodates non-Fortran 2018 error stop with variable character
10+
11+
logical :: exists
12+
13+
inquire(directory=path, exist=exists)
14+
15+
if (exists) return
16+
17+
write(stderr,*) path // ' directory does not exist'
18+
error stop
19+
20+
end procedure assert_directory_exists
21+
22+
end submodule path_exists

io/pathlib.F90 renamed to io/pathlib.f90

Lines changed: 43 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,56 +4,50 @@ module pathlib
44

55
implicit none
66
private
7-
public :: mkdir, copyfile, expanduser, home
7+
public :: mkdir, copyfile, expanduser, home, get_suffix, filesep_swap, assert_directory_exists, assert_file_exists
8+
9+
interface ! pathlib_{unix,windows}.f90
10+
module integer function copyfile(source, dest) result(istat)
11+
character(*), intent(in) :: source, dest
12+
end function copyfile
13+
14+
module integer function mkdir(path) result(istat)
15+
character(*), intent(in) :: path
16+
end function mkdir
17+
end interface
18+
19+
interface ! path_exists*.f90
20+
module subroutine assert_directory_exists(path)
21+
character(*), intent(in) :: path
22+
end subroutine assert_directory_exists
23+
end interface
824

925
contains
1026

11-
integer function copyfile(source, dest) result(istat)
12-
!! overwrites existing file in destination
13-
character(*), intent(in) :: source, dest
14-
character(len(source)) :: src
15-
character(len(dest)) :: dst
16-
logical :: exists
17-
integer :: icstat
18-
19-
#if defined(_WIN32)
20-
!! https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy
21-
character(*), parameter :: CMD='copy /y '
22-
src = filesep_swap(source)
23-
dst = filesep_swap(dest)
24-
#else
25-
character(*), parameter :: CMD='cp -r '
26-
src = source
27-
dst = dest
28-
#endif
29-
30-
call execute_command_line(CMD//src//' '//dst, exitstat=istat, cmdstat=icstat)
31-
if (istat == 0 .and. icstat /= 0) istat = icstat
32-
if (istat /= 0) write(stderr,*) 'ERROR: '//CMD//src//' '//dst
27+
pure function get_suffix(filename)
28+
character(*), intent(in) :: filename
29+
character(:), allocatable :: get_suffix
30+
31+
get_suffix = filename(index(filename, '.', back=.true.) : len(filename))
32+
33+
end function get_suffix
3334

34-
end function copyfile
3535

36+
subroutine assert_file_exists(path)
37+
!! throw error if file does not exist
38+
!! this accomodates non-Fortran 2018 error stop with variable character
3639

37-
integer function mkdir(path) result(istat)
38-
!! create a directory, with parents if needed
3940
character(*), intent(in) :: path
40-
character(len(path)) :: p
41-
integer :: icstat
42-
43-
#if defined(_WIN32)
44-
!! https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/md
45-
character(*), parameter :: CMD='mkdir '
46-
p = filesep_swap(path)
47-
#else
48-
character(*), parameter :: CMD='mkdir -p '
49-
p = path
50-
#endif
51-
52-
call execute_command_line(CMD // p, exitstat=istat, cmdstat=icstat)
53-
if (istat == 0 .and. icstat /= 0) istat = icstat
54-
if (istat /= 0) write(stderr,*) 'ERROR: '//CMD//p
41+
logical :: exists
5542

56-
end function mkdir
43+
inquire(file=path, exist=exists)
44+
45+
if (exists) return
46+
47+
write(stderr,'(A)') 'ERROR: file does not exist ' // path
48+
error stop
49+
50+
end subroutine assert_file_exists
5751

5852

5953
function filesep_swap(path) result(swapped)
@@ -105,20 +99,18 @@ end function expanduser
10599

106100
function home()
107101
!! https://en.wikipedia.org/wiki/Home_directory#Default_home_directory_per_operating_system
108-
character(:), allocatable :: home, var
102+
character(:), allocatable :: home
109103
character(256) :: buf
110104
integer :: L, istat
111105

112-
#if defined(_WIN32)
113-
var = "USERPROFILE"
114-
#else
115-
var = "HOME"
116-
#endif
106+
call get_environment_variable("HOME", buf, length=L, status=istat)
107+
if (L==0 .or. istat /= 0) then
108+
call get_environment_variable("USERPROFILE", buf, length=L, status=istat)
109+
endif
117110

118-
call get_environment_variable(var, buf, length=L, status=istat)
119111
if (L==0 .or. istat /= 0) then
120-
write(stderr,*) 'ERROR: could not determine home directory from env var ',var
121-
if (istat==1) write(stderr,*) 'env var ',var,' does not exist.'
112+
write(stderr,*) 'ERROR: could not determine home directory from env variable'
113+
if (istat==1) write(stderr,*) 'env variable does not exist.'
122114
home = ""
123115
else
124116
home = trim(buf) // '/'

io/pathlib_unix.f90

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
submodule (pathlib) pathlib_unix
2+
3+
implicit none
4+
5+
contains
6+
7+
module procedure copyfile
8+
9+
integer :: icstat
10+
!! https://linux.die.net/man/1/cp
11+
character(*), parameter :: CMD='cp -rf '
12+
13+
call execute_command_line(CMD // source // ' ' // dest, exitstat=istat, cmdstat=icstat)
14+
if (istat == 0 .and. icstat /= 0) istat = icstat
15+
16+
end procedure copyfile
17+
18+
19+
module procedure mkdir
20+
!! create a directory, with parents if needed
21+
integer :: icstat
22+
23+
character(*), parameter :: CMD='mkdir -p '
24+
25+
call execute_command_line(CMD // path, exitstat=istat, cmdstat=icstat)
26+
if (istat == 0 .and. icstat /= 0) istat = icstat
27+
28+
end procedure mkdir
29+
30+
end submodule pathlib_unix

io/pathlib_windows.f90

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
submodule (pathlib) pathlib_windows
2+
3+
implicit none
4+
5+
contains
6+
7+
module procedure copyfile
8+
9+
integer :: icstat
10+
!! https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy
11+
character(*), parameter :: CMD='copy /y '
12+
13+
call execute_command_line(CMD // filesep_swap(source) // ' ' // filesep_swap(dest), exitstat=istat, cmdstat=icstat)
14+
if (istat == 0 .and. icstat /= 0) istat = icstat
15+
16+
end procedure copyfile
17+
18+
19+
module procedure mkdir
20+
!! create a directory, with parents if needed
21+
integer :: icstat
22+
!! https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/md
23+
character(*), parameter :: CMD='mkdir '
24+
25+
call execute_command_line(CMD // filesep_swap(path), exitstat=istat, cmdstat=icstat)
26+
if (istat == 0 .and. icstat /= 0) istat = icstat
27+
28+
end procedure mkdir
29+
30+
31+
end submodule pathlib_windows

0 commit comments

Comments
 (0)