|
1 | 1 | !># Store compiler commands in a `compile_commands.json` table
|
2 | 2 | module fpm_compile_commands
|
3 |
| - use fpm_toml, only: serializable_t, set_string, set_list, get_value, get_list, toml_table, add_table |
| 3 | + use fpm_toml, only: serializable_t, set_string, set_value, set_list, get_value, get_list, toml_table, add_table, toml_array, add_array, toml_stat |
| 4 | + use jonquil, only: json_serialize, json_ser_config |
4 | 5 | use fpm_strings, only: string_t, operator(==)
|
5 | 6 | use fpm_error, only: error_t, syntax_error, fatal_error
|
6 | 7 | use fpm_os, only: get_current_directory
|
@@ -34,6 +35,7 @@ module fpm_compile_commands
|
34 | 35 | !> Operation
|
35 | 36 | procedure :: destroy => cct_destroy
|
36 | 37 | procedure :: register => cct_register
|
| 38 | + procedure :: write => cct_write |
37 | 39 |
|
38 | 40 | !> Serialization interface
|
39 | 41 | procedure :: serializable_is_same => cct_is_same
|
@@ -110,47 +112,117 @@ logical function compile_command_is_same(this,that)
|
110 | 112 | compile_command_is_same = .true.
|
111 | 113 |
|
112 | 114 | end function compile_command_is_same
|
113 |
| - |
114 |
| - !> Dump compile_command_table_t to toml table |
115 |
| - subroutine cct_dump_toml(self, table, error) |
116 |
| - |
| 115 | + |
| 116 | + !> Dump compile_command_table_t to a toml array |
| 117 | + subroutine cct_dump_array(self, array, error) |
117 | 118 | !> Instance of the serializable object
|
118 | 119 | class(compile_command_table_t), intent(inout) :: self
|
119 | 120 |
|
120 | 121 | !> Data structure
|
121 |
| - type(toml_table), intent(inout) :: table |
| 122 | + type(toml_array), intent(inout) :: array |
122 | 123 |
|
123 | 124 | !> Error handling
|
124 |
| - type(error_t), allocatable, intent(out) :: error |
| 125 | + type(error_t), allocatable, intent(out) :: error |
125 | 126 |
|
126 |
| - integer :: ii |
127 |
| - type(toml_table), pointer :: ptr |
128 |
| - character(64) :: name |
| 127 | + integer :: ii, stat |
| 128 | + type(toml_table), pointer :: item |
129 | 129 |
|
130 | 130 | if (.not.allocated(self%command)) return
|
131 | 131 |
|
132 | 132 | do ii = 1, size(self%command)
|
133 | 133 | associate (cmd => self%command(ii))
|
134 | 134 |
|
135 | 135 | ! Set node for this command
|
136 |
| - write(name,1) ii |
137 |
| - call add_table(table, trim(name), ptr) |
138 |
| - if (.not. associated(ptr)) then |
139 |
| - call fatal_error(error, "compile_command_table_t cannot create entry for "//trim(name)) |
| 136 | + call add_table(array, item, stat) |
| 137 | + if (stat /= toml_stat%success) then |
| 138 | + call fatal_error(error, "Cannot store entry in compile_command_table_t array") |
140 | 139 | return
|
141 |
| - end if |
142 |
| - |
143 |
| - ! Dump node |
144 |
| - call cmd%dump_to_toml(ptr, error) |
| 140 | + end if |
| 141 | + call cmd%dump_to_toml(item, error) |
145 | 142 | if (allocated(error)) return
|
146 |
| - |
| 143 | + |
147 | 144 | endassociate
|
148 |
| - end do |
| 145 | + end do |
| 146 | + |
| 147 | + end subroutine cct_dump_array |
149 | 148 |
|
150 |
| - 1 format('compile_command_',i0) |
| 149 | + !> Dump compile_command_table_t to toml table |
| 150 | + subroutine cct_dump_toml(self, table, error) |
| 151 | + |
| 152 | + !> Instance of the serializable object |
| 153 | + class(compile_command_table_t), intent(inout) :: self |
| 154 | + |
| 155 | + !> Data structure |
| 156 | + type(toml_table), intent(inout) :: table |
| 157 | + |
| 158 | + !> Error handling |
| 159 | + type(error_t), allocatable, intent(out) :: error |
| 160 | + |
| 161 | + integer :: stat, ii |
| 162 | + type(toml_array), pointer :: array |
| 163 | + |
| 164 | + if (.not.allocated(self%command)) return |
| 165 | + |
| 166 | + ! Create array |
| 167 | + call add_array(table, 'compile_commands', array, stat=stat) |
| 168 | + if (stat/=toml_stat%success .or. .not.associated(array)) then |
| 169 | + call fatal_error(error,"compile_command_table_t cannot create entry") |
| 170 | + return |
| 171 | + end if |
| 172 | + |
| 173 | + ! Dump to it |
| 174 | + call cct_dump_array(self, array, error) |
151 | 175 |
|
152 | 176 | end subroutine cct_dump_toml
|
153 | 177 |
|
| 178 | + !> Write compile_commands.json file. Because Jonquil does not support non-named arrays, |
| 179 | + !> create a custom json here. |
| 180 | + subroutine cct_write(self, filename, error) |
| 181 | + |
| 182 | + !> Instance of the serializable object |
| 183 | + class(compile_command_table_t), intent(inout) :: self |
| 184 | + |
| 185 | + !> The file name |
| 186 | + character(*), intent(in) :: filename |
| 187 | + |
| 188 | + !> Error handling |
| 189 | + type(error_t), allocatable, intent(out) :: error |
| 190 | + |
| 191 | + type(toml_array) :: array |
| 192 | + type(json_ser_config) :: cfg |
| 193 | + integer :: stat, lun |
| 194 | + |
| 195 | + ! Init array |
| 196 | + array = toml_array() |
| 197 | + |
| 198 | + ! Dump information to the array |
| 199 | + call cct_dump_array(self, array, error) |
| 200 | + if (allocated(error)) return |
| 201 | + |
| 202 | + ! Open file and write to it |
| 203 | + open(newunit=lun,file=filename,form='formatted',action='write',status='replace',iostat=stat) |
| 204 | + if (stat/=0) then |
| 205 | + call fatal_error(error, 'cannot open file '//filename//' for writing') |
| 206 | + return |
| 207 | + end if |
| 208 | + |
| 209 | + ! Ensure the array has no key |
| 210 | + if (allocated(array%key)) deallocate(array%key) |
| 211 | + |
| 212 | + cfg%indent = repeat(' ',4) |
| 213 | + write (lun, '(A)', iostat=stat, err=1) '{' |
| 214 | + write (lun, '(A)', iostat=stat, err=1) json_serialize(array, cfg) |
| 215 | + write (lun, '(A)', iostat=stat, err=1) '}' |
| 216 | + |
| 217 | + close(lun,iostat=stat) |
| 218 | + |
| 219 | + 1 if (stat/=0) then |
| 220 | + call fatal_error(error, 'cannot close file '//filename//' after writing') |
| 221 | + return |
| 222 | + end if |
| 223 | + |
| 224 | + end subroutine cct_write |
| 225 | + |
154 | 226 | !> Cleanup a compile command table
|
155 | 227 | elemental subroutine cct_destroy(self)
|
156 | 228 |
|
|
0 commit comments