Formatted output conversion (similar to C sprintf).
Format a string like C sprintf(3). Note that the implementation is quite different from C sprintf(3).
104
106 implicit none
107 character(*), intent(out) :: unit
108 character(*), intent(in) :: fmt
109 integer, intent(in), optional :: i(:), n(:)
110 real(SP), intent(in), optional :: r(:)
111 real(DP), intent(in), optional :: d(:)
112 logical, intent(in), optional :: L(:)
113 character(*), intent(in), optional :: c1, c2, c3
114 character(*), intent(in), optional :: ca(:)
115
116
117 integer :: ni, nr, nd, nl, nc, na, nn
118 integer :: ucur
119 integer :: endp
120 integer :: cur
121 integer :: ptr
122 integer :: exp_ptr
123 integer :: minus_ptr
124 integer :: repeat
125 integer :: m
126 integer :: stat
127 character(80) :: cbuf
128 character(80) :: exp_buf
129 character(80) :: ibuf
130 integer :: len_ibuf
131 integer :: figs_ibuf
132 logical :: int_zero_fill
133 integer :: int_figs
134 continue
135 ni = 0; nr = 0; nd = 0; nl = 0; nc = 0; na = 0; nn = 0
136 unit = ""
137 ucur = 0
138 endp = 0
139 int_figs = 0
140 int_zero_fill = .false.
141 mainloop: do
142 cur = endp + 1
143 if (cur > len(fmt)) exit mainloop
144
145
146
147 endp = cur - 1 + scan(fmt(cur: ), '%')
148 if (endp > cur) then
149 call append(unit, ucur, fmt(cur:endp-1), stat)
150 if (stat /= 0) exit mainloop
151 else if (endp == cur - 1) then
152 call append(unit, ucur, fmt(cur: ), stat)
153 exit mainloop
154 endif
155
156
157
158 cur = endp + 1
159 endp = cur - 1 + scan(fmt(cur: ), 'DdOoXxFfRrBbYySsCcAa%')
160 if (endp < cur) then
161 call append(unit, ucur, fmt(cur-1: ), stat)
162 exit mainloop
163 endif
164 cbuf = fmt(cur:endp-1)
165
166
167
168 if (cbuf(1:1) == '*') then
169 nn = nn + 1
170 if (nn > size(n)) then
171 repeat = 1
172 else
173 repeat = n(nn)
174 endif
175 ibuf = cbuf(2:)
176 else
177 repeat = 1
178 ibuf = cbuf
179
180
181
182
183
184
185 endif
186
187
188
189
190
191 if (scan(ibuf(1:1),'1234567890') > 0) then
192 if (ibuf(1:1) == '0') then
193 int_zero_fill = .true.
194 else
195 int_zero_fill = .false.
196 end if
197 read(unit=ibuf, fmt="(i80)") int_figs
198 else
199 int_figs = 0
200 int_zero_fill = .false.
201 endif
202 percentrepeat: do m = 1, repeat
203 if (m > 1) then
204 call append(unit, ucur,
", ", stat)
205 if (stat /= 0) exit mainloop
206 endif
207 select case(fmt(endp:endp))
208 case('d', 'D')
209 if (.not. present(i)) cycle mainloop
210 ni = ni + 1; if (ni > size(i)) cycle mainloop
211 write(ibuf, "(i20)") i(ni)
212 len_ibuf = len(trim(adjustl(ibuf)))
213 figs_ibuf = verify(ibuf, ' ')
214 cbuf = ' '
215 if (int_figs > len_ibuf) then
216 minus_ptr = scan(ibuf, '-')
217 if (int_zero_fill) then
218 if (minus_ptr /= 0) then
219 len_ibuf = len_ibuf - 1
220 figs_ibuf = figs_ibuf + 1
221 cbuf(1:int_figs-len_ibuf) = '-0000000000000000000'
222 else
223 cbuf(1:int_figs-len_ibuf) = '00000000000000000000'
224 end if
225 end if
226 cbuf(int_figs-len_ibuf+1:) = ibuf(figs_ibuf:20)
227 else
228 cbuf = ibuf(figs_ibuf:20)
229 end if
230 call append(unit, ucur, trim(cbuf), stat)
231 if (stat /= 0) exit mainloop
232 case('o', 'O')
233 if (.not. present(i)) cycle mainloop
234 ni = ni + 1; if (ni > size(i)) cycle mainloop
235 write(cbuf, "(o20)") i(ni)
236 call append(unit, ucur, trim(adjustl(cbuf)), stat)
237 if (stat /= 0) exit mainloop
238 case('x', 'X')
239 if (.not. present(i)) cycle mainloop
240 ni = ni + 1; if (ni > size(i)) cycle mainloop
241 write(cbuf, "(z20)") i(ni)
242 call append(unit, ucur, trim(adjustl(cbuf)), stat)
243 if (stat /= 0) exit mainloop
244 case('f', 'F')
245 if (.not. present(d)) cycle mainloop
246 nd = nd + 1; if (nd > size(d)) cycle mainloop
247 write(cbuf, "(f80.40)") d(nd)
248 cbuf = adjustl(cbuf)
249 exp_ptr = verify(cbuf, ' 1234567890-+.', back=.true.)
250 exp_buf = ' '
251 if (exp_ptr > 0) then
252 exp_buf = cbuf(exp_ptr: )
253 cbuf(exp_ptr: ) = " "
254 end if
255 ptr = verify(cbuf, " 0", back=.true.)
256 if (ptr > 0) cbuf(ptr+1: ) = " "
257 cbuf = trim(cbuf) // trim(exp_buf)
258 call append(unit, ucur, trim(adjustl(cbuf)), stat)
259 if (stat /= 0) exit mainloop
260 case('r', 'R')
261 if (.not. present(r)) cycle mainloop
262 nr = nr + 1 ; if (nr > size(r)) cycle mainloop
263 write(cbuf, "(f80.40)") r(nr)
264 cbuf = adjustl(cbuf)
265 exp_ptr = verify(cbuf, ' 1234567890-+.', back=.true.)
266 exp_buf = ' '
267 if (exp_ptr > 0) then
268 exp_buf = cbuf(exp_ptr: )
269 cbuf(exp_ptr: ) = " "
270 end if
271 ptr = verify(cbuf, " 0", back=.true.)
272 if (ptr > 0) cbuf(ptr+1: ) = " "
273 cbuf = trim(cbuf) // trim(exp_buf)
274 call append(unit, ucur, trim(adjustl(cbuf)), stat)
275 if (stat /= 0) exit mainloop
276 case('b', 'B')
277 if (.not. present(l)) cycle mainloop
278 nl = nl + 1; if (nl > size(l)) cycle mainloop
279 write(cbuf, "(L1)") l(nl)
280 call append(unit, ucur, trim(adjustl(cbuf)), stat)
281 if (stat /= 0) exit mainloop
282 case('y', 'Y')
283 if (.not. present(l)) cycle mainloop
284 nl = nl + 1; if (nl > size(l)) cycle mainloop
285 if (l(nl)) then
286 call append(unit, ucur,
"yes", stat)
287 if (stat /= 0) exit mainloop
288 else
289 call append(unit, ucur,
"no", stat)
290 if (stat /= 0) exit mainloop
291 endif
292 case('c', 'C')
293 nc = nc + 1
294 if (nc == 1) then
295 if (.not. present(c1)) cycle percentrepeat
296 call append(unit, ucur, c1, stat)
297 if (stat /= 0) exit mainloop
298 else if (nc == 2) then
299 if (.not. present(c2)) cycle percentrepeat
300 call append(unit, ucur, c2, stat)
301 if (stat /= 0) exit mainloop
302 else if (nc == 3) then
303 if (.not. present(c3)) cycle percentrepeat
304 call append(unit, ucur, c3, stat)
305 if (stat /= 0) exit mainloop
306 endif
307 case('a', 'A')
308 if (.not. present(ca)) cycle mainloop
309 na = na + 1; if (na > size(ca)) cycle mainloop
310 call append(unit, ucur, trim(adjustl(ca(na))), stat)
311 if (stat /= 0) exit mainloop
312 case('%')
313 call append(unit, ucur,
'%', stat)
314 if (stat /= 0) exit mainloop
315 end select
316 enddo percentrepeat
317 enddo mainloop
318 return
319contains
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 subroutine append(unitx, ucur, val, stat)
336 character(*), intent(inout):: unitx
337 integer, intent(inout):: ucur
338 character(*), intent(in) :: val
339 integer, intent(out) :: stat
340 integer :: wrsz
341 continue
342
343 if (ucur >= len(unitx)) then
344 stat = 2
345
346 else
347
348 wrsz = min(len(val), len(unitx) - ucur)
349 unitx(1+ucur: wrsz+ucur) = val(1: wrsz)
350 ucur = ucur + wrsz
351 stat = 0
352 if (wrsz < len(val)) stat = 1
353 endif
355
subroutine append(unitx, ucur, val, stat)
Provides kind type parameter values.
integer, parameter, public dp
Double Precision Real number
integer, parameter, public sp
Single Precision Real number.