1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
!># Interface to TOML processing library
!>
!> This module acts as a proxy to the `toml-f` public Fortran API and allows
!> to selectively expose components from the library to `fpm`.
!> The interaction with `toml-f` data types outside of this module should be
!> limited to tables, arrays and key-lists, most of the necessary interactions
!> are implemented in the building interface with the `get_value` and `set_value`
!> procedures.
!>
!> This module allows to implement features necessary for `fpm`, which are
!> not yet available in upstream `toml-f`.
!>
!> For more details on the library used see the
!> [TOML-Fortran](https://toml-f.github.io/toml-f) developer pages.
module fpm_toml
use fpm_error, only : error_t, fatal_error, file_not_found_error
use fpm_strings, only : string_t
use tomlf, only : toml_table, toml_array, toml_key, toml_stat, get_value, &
& set_value, toml_parse, toml_error, new_table, add_table, add_array, &
& toml_serializer, len
implicit none
private
public :: read_package_file
public :: toml_table, toml_array, toml_key, toml_stat, get_value, set_value
public :: new_table, add_table, add_array, len
public :: toml_error, toml_serializer, toml_parse
interface get_value
module procedure :: get_child_value_string_list
end interface get_value
contains
!> Process the configuration file to a TOML data structure
subroutine read_package_file(table, manifest, error)
!> TOML data structure
type(toml_table), allocatable, intent(out) :: table
!> Name of the package configuration file
character(len=*), intent(in) :: manifest
!> Error status of the operation
type(error_t), allocatable, intent(out) :: error
type(toml_error), allocatable :: parse_error
integer :: unit
logical :: exist
inquire(file=manifest, exist=exist)
if (.not.exist) then
call file_not_found_error(error, manifest)
return
end if
open(file=manifest, newunit=unit)
call toml_parse(table, unit, parse_error)
close(unit)
if (allocated(parse_error)) then
allocate(error)
call move_alloc(parse_error%message, error%message)
return
end if
end subroutine read_package_file
subroutine get_child_value_string_list(table, key, list, error)
!> Instance of the TOML data structure
type(toml_table), intent(inout) :: table
!> Key to read from
character(len=*), intent(in) :: key
!> List of strings to read
type(string_t), allocatable, intent(out) :: list(:)
!> Error handling
type(error_t), allocatable, intent(out) :: error
integer :: stat, ilist, nlist
type(toml_array), pointer :: children
character(len=:), allocatable :: str
call get_value(table, key, children, requested=.false.)
if (associated(children)) then
nlist = len(children)
allocate(list(nlist))
do ilist = 1, nlist
call get_value(children, ilist, str, stat=stat)
if (stat /= toml_stat%success) then
call fatal_error(error, "Entry in "//key//" field cannot be read")
exit
end if
call move_alloc(str, list(ilist)%s)
end do
if (allocated(error)) return
else
call get_value(table, key, str, stat=stat)
if (stat /= toml_stat%success) then
call fatal_error(error, "Entry in "//key//" field cannot be read")
return
end if
if (allocated(str)) then
allocate(list(1))
call move_alloc(str, list(1)%s)
end if
end if
end subroutine get_child_value_string_list
end module fpm_toml
|