GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
MODULE strings_mod |
||
2 |
|||
3 |
IMPLICIT NONE |
||
4 |
|||
5 |
PRIVATE |
||
6 |
PUBLIC :: maxlen, init_printout, msg, fmsg, get_in, lunout, prt_level |
||
7 |
PUBLIC :: strLower, strHead, strStack, strCount, strReduce, strClean, strIdx |
||
8 |
PUBLIC :: strUpper, strTail, strStackm, strParse, strReplace, strFind, find, cat |
||
9 |
PUBLIC :: dispTable, dispOutliers, dispNameList |
||
10 |
PUBLIC :: is_numeric, bool2str, int2str, real2str, dble2str |
||
11 |
PUBLIC :: reduceExpr, str2bool, str2int, str2real, str2dble |
||
12 |
PUBLIC :: addQuotes, checkList, removeComment, test |
||
13 |
|||
14 |
INTERFACE get_in; MODULE PROCEDURE getin_s, getin_i, getin_r, getin_l; END INTERFACE get_in |
||
15 |
INTERFACE msg; MODULE PROCEDURE msg_1, msg_m; END INTERFACE msg |
||
16 |
INTERFACE fmsg; MODULE PROCEDURE fmsg_1, fmsg_m; END INTERFACE fmsg |
||
17 |
INTERFACE strHead; MODULE PROCEDURE strHead_1, strHead_m; END INTERFACE strHead |
||
18 |
INTERFACE strTail; MODULE PROCEDURE strTail_1, strTail_m; END INTERFACE strTail |
||
19 |
INTERFACE strClean; MODULE PROCEDURE strClean_1, strClean_m; END INTERFACE strClean |
||
20 |
INTERFACE strReduce; MODULE PROCEDURE strReduce_1, strReduce_2; END INTERFACE strReduce |
||
21 |
INTERFACE strIdx; MODULE PROCEDURE strIdx_1, strIdx_m; END INTERFACE strIdx |
||
22 |
INTERFACE strCount; MODULE PROCEDURE strCount_m1, strCount_11, strCount_1m; END INTERFACE strCount |
||
23 |
INTERFACE strReplace; MODULE PROCEDURE strReplace_1, strReplace_m; END INTERFACE strReplace |
||
24 |
INTERFACE cat; MODULE PROCEDURE horzcat_s1, horzcat_i1, horzcat_r1, & |
||
25 |
! horzcat_d1, horzcat_dm, |
||
26 |
horzcat_sm, horzcat_im, horzcat_rm; END INTERFACE cat |
||
27 |
INTERFACE find; MODULE PROCEDURE strFind, find_int, find_boo; END INTERFACE find |
||
28 |
INTERFACE dispOutliers; MODULE PROCEDURE dispOutliers_1, dispOutliers_2; END INTERFACE dispOutliers |
||
29 |
INTERFACE reduceExpr; MODULE PROCEDURE reduceExpr_1, reduceExpr_m; END INTERFACE reduceExpr |
||
30 |
INTERFACE addQuotes; MODULE PROCEDURE addQuotes_1, addQuotes_m; END INTERFACE addQuotes |
||
31 |
|||
32 |
INTEGER, PARAMETER :: maxlen = 256 !--- Standard maximum length for strings |
||
33 |
INTEGER, SAVE :: lunout = 6 !--- Printing unit (default: 6, ie. on screen) |
||
34 |
INTEGER, SAVE :: prt_level = 1 !--- Printing level (default: 1, ie. print all) |
||
35 |
|||
36 |
CONTAINS |
||
37 |
|||
38 |
!============================================================================================================================== |
||
39 |
379 |
LOGICAL FUNCTION test(lcond, lout) RESULT(lerr) |
|
40 |
LOGICAL, INTENT(IN) :: lcond |
||
41 |
LOGICAL, INTENT(OUT) :: lout |
||
42 |
379 |
lerr = lcond; lout = lcond |
|
43 |
379 |
END FUNCTION test |
|
44 |
!============================================================================================================================== |
||
45 |
|||
46 |
|||
47 |
!============================================================================================================================== |
||
48 |
SUBROUTINE init_printout(lunout_, prt_level_) |
||
49 |
INTEGER, INTENT(IN) :: lunout_, prt_level_ |
||
50 |
lunout = lunout_ |
||
51 |
prt_level = prt_level_ |
||
52 |
END SUBROUTINE init_printout |
||
53 |
!============================================================================================================================== |
||
54 |
|||
55 |
|||
56 |
!============================================================================================================================== |
||
57 |
!=== Same as getin ; additional last argument: the default value. |
||
58 |
!============================================================================================================================== |
||
59 |
SUBROUTINE getin_s(nam, val, def) |
||
60 |
USE ioipsl_getincom, ONLY: getin |
||
61 |
CHARACTER(LEN=*), INTENT(IN) :: nam |
||
62 |
CHARACTER(LEN=*), INTENT(INOUT) :: val |
||
63 |
CHARACTER(LEN=*), INTENT(IN) :: def |
||
64 |
val = def; CALL getin(nam, val) |
||
65 |
IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(val) |
||
66 |
END SUBROUTINE getin_s |
||
67 |
!============================================================================================================================== |
||
68 |
SUBROUTINE getin_i(nam, val, def) |
||
69 |
USE ioipsl_getincom, ONLY: getin |
||
70 |
CHARACTER(LEN=*), INTENT(IN) :: nam |
||
71 |
INTEGER, INTENT(INOUT) :: val |
||
72 |
INTEGER, INTENT(IN) :: def |
||
73 |
val = def; CALL getin(nam, val) |
||
74 |
IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(int2str(val)) |
||
75 |
END SUBROUTINE getin_i |
||
76 |
!============================================================================================================================== |
||
77 |
SUBROUTINE getin_r(nam, val, def) |
||
78 |
USE ioipsl_getincom, ONLY: getin |
||
79 |
CHARACTER(LEN=*), INTENT(IN) :: nam |
||
80 |
REAL, INTENT(INOUT) :: val |
||
81 |
REAL, INTENT(IN) :: def |
||
82 |
val = def; CALL getin(nam, val) |
||
83 |
IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(real2str(val)) |
||
84 |
END SUBROUTINE getin_r |
||
85 |
!============================================================================================================================== |
||
86 |
SUBROUTINE getin_l(nam, val, def) |
||
87 |
USE ioipsl_getincom, ONLY: getin |
||
88 |
CHARACTER(LEN=*), INTENT(IN) :: nam |
||
89 |
LOGICAL, INTENT(INOUT) :: val |
||
90 |
LOGICAL, INTENT(IN) :: def |
||
91 |
val = def; CALL getin(nam, val) |
||
92 |
IF(val.NEQV.def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(bool2str(val)) |
||
93 |
END SUBROUTINE getin_l |
||
94 |
!============================================================================================================================== |
||
95 |
|||
96 |
|||
97 |
!============================================================================================================================== |
||
98 |
!=== Display one or several messages, one each line, starting with the current routine name "modname". |
||
99 |
!============================================================================================================================== |
||
100 |
3588 |
SUBROUTINE msg_1(str, modname, ll, unit) |
|
101 |
!--- Display a simple message "str". Optional parameters: |
||
102 |
! * "modname": module name, displayed in front of the message (with ": " separator) if present. |
||
103 |
! * "ll": message trigger ; message is displayed only if ll==.TRUE. |
||
104 |
! * "unit": write unit (by default: "lunout") |
||
105 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
106 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname |
||
107 |
LOGICAL, OPTIONAL, INTENT(IN) :: ll |
||
108 |
INTEGER, OPTIONAL, INTENT(IN) :: unit |
||
109 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
110 |
CHARACTER(LEN=maxlen) :: subn |
||
111 |
INTEGER :: unt |
||
112 |
✓✓ | 3588 |
subn = ''; IF(PRESENT(modname)) subn = modname |
113 |
✓✓✓✓ |
3588 |
IF(PRESENT(ll)) THEN; IF(.NOT.ll) RETURN; END IF |
114 |
✓✓ | 62 |
unt = lunout; IF(PRESENT(unit)) unt = unit |
115 |
✗✓ | 62 |
IF(subn == '') WRITE(unt,'(a)') str !--- Simple message |
116 |
✓✗ | 62 |
IF(subn /= '') WRITE(unt,'(a)') TRIM(subn)//': '//str !--- Routine name provided |
117 |
✓✗ | 3588 |
END SUBROUTINE msg_1 |
118 |
!============================================================================================================================== |
||
119 |
SUBROUTINE msg_m(str, modname, ll, unit, nmax) |
||
120 |
!--- Same as msg_1 with multiple strings that are stacked (separator: coma) on up to "nmax" full lines. |
||
121 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
122 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname |
||
123 |
LOGICAL, OPTIONAL, INTENT(IN) :: ll |
||
124 |
INTEGER, OPTIONAL, INTENT(IN) :: unit |
||
125 |
INTEGER, OPTIONAL, INTENT(IN) :: nmax |
||
126 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
127 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:) |
||
128 |
CHARACTER(LEN=maxlen) :: subn |
||
129 |
INTEGER :: unt, nmx, k |
||
130 |
LOGICAL :: l |
||
131 |
subn = ''; IF(PRESENT(modname)) subn = modname |
||
132 |
l = .TRUE.; IF(PRESENT(ll)) l = ll |
||
133 |
unt = lunout; IF(PRESENT(unit)) unt = unit |
||
134 |
nmx = 128; IF(PRESENT(nmax)) nmx = nmax |
||
135 |
s = strStackm(str, ', ', nmx) |
||
136 |
DO k=1,SIZE(s); CALL msg_1(s(k), subn, l, unt); END DO |
||
137 |
END SUBROUTINE msg_m |
||
138 |
!============================================================================================================================== |
||
139 |
66 |
LOGICAL FUNCTION fmsg_1(str, modname, ll, unit) RESULT(l) |
|
140 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
141 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname |
||
142 |
LOGICAL, OPTIONAL, INTENT(IN) :: ll |
||
143 |
INTEGER, OPTIONAL, INTENT(IN) :: unit |
||
144 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
145 |
CHARACTER(LEN=maxlen) :: subn |
||
146 |
INTEGER :: unt |
||
147 |
✓✓ | 55 |
subn = ''; IF(PRESENT(modname)) subn = modname |
148 |
✓✗ | 66 |
l = .TRUE.; IF(PRESENT(ll)) l = ll |
149 |
✗✓ | 66 |
unt = lunout; IF(PRESENT(unit)) unt = unit |
150 |
66 |
CALL msg_1(str, subn, l, unt) |
|
151 |
✓✓ | 66 |
END FUNCTION fmsg_1 |
152 |
!============================================================================================================================== |
||
153 |
LOGICAL FUNCTION fmsg_m(str, modname, ll, unit, nmax) RESULT(l) |
||
154 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
155 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname |
||
156 |
LOGICAL, OPTIONAL, INTENT(IN) :: ll |
||
157 |
INTEGER, OPTIONAL, INTENT(IN) :: unit |
||
158 |
INTEGER, OPTIONAL, INTENT(IN) :: nmax |
||
159 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
160 |
CHARACTER(LEN=maxlen) :: subn |
||
161 |
INTEGER :: unt, nmx |
||
162 |
subn = ''; IF(PRESENT(modname)) subn = modname |
||
163 |
l = .TRUE.; IF(PRESENT(ll)) l = ll |
||
164 |
unt = lunout; IF(PRESENT(unit)) unt = unit |
||
165 |
nmx = 128; IF(PRESENT(nmax)) nmx = nmax |
||
166 |
CALL msg_m(str, subn, l, unt, nmx) |
||
167 |
END FUNCTION fmsg_m |
||
168 |
!============================================================================================================================== |
||
169 |
|||
170 |
|||
171 |
!============================================================================================================================== |
||
172 |
!=== Lower/upper case conversion function. ==================================================================================== |
||
173 |
!============================================================================================================================== |
||
174 |
ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strLower(str) RESULT(out) |
||
175 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
176 |
INTEGER :: k |
||
177 |
out = str |
||
178 |
DO k=1,LEN_TRIM(str) |
||
179 |
IF(str(k:k)>='A' .AND. str(k:k)<='Z') out(k:k)=ACHAR(IACHAR(str(k:k))+32) |
||
180 |
END DO |
||
181 |
END FUNCTION strLower |
||
182 |
!============================================================================================================================== |
||
183 |
ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strUpper(str) RESULT(out) |
||
184 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
185 |
INTEGER :: k |
||
186 |
out = str |
||
187 |
DO k=1,LEN_TRIM(str) |
||
188 |
IF(str(k:k)>='a' .AND. str(k:k)<='z') out(k:k)=ACHAR(IACHAR(str(k:k))-32) |
||
189 |
END DO |
||
190 |
END FUNCTION strUpper |
||
191 |
!============================================================================================================================== |
||
192 |
|||
193 |
|||
194 |
!============================================================================================================================== |
||
195 |
!=== Extract the substring in front of the first (last if lBackward==TRUE) occurrence of "sep" in "str" ================ |
||
196 |
!=== Examples for str='a_b_c' and sep='_' and the bash command with the same effect: ================ |
||
197 |
!=== * strHead(..,.FALSE.) = 'a' ${str%%$sep*} ================ |
||
198 |
!=== * strHead(..,.TRUE.) = 'a_b' ${str%$sep*} ================ |
||
199 |
!============================================================================================================================== |
||
200 |
14 |
CHARACTER(LEN=maxlen) FUNCTION strHead_1(str, sep, lBackward) RESULT(out) |
|
201 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
202 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep |
||
203 |
LOGICAL, OPTIONAL, INTENT(IN) :: lBackward |
||
204 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
205 |
14 |
IF(PRESENT(sep)) THEN |
|
206 |
✓✗✓✗ |
14 |
IF( PRESENT(lBackWard)) out = str(1:INDEX(str,sep,lBackWard)-1) |
207 |
✗✓✗✗ |
14 |
IF(.NOT.PRESENT(lBackWard)) out = str(1:INDEX(str,sep)-1) |
208 |
ELSE |
||
209 |
IF( PRESENT(lBackWard)) out = str(1:INDEX(str,'/',lBackWard)-1) |
||
210 |
IF(.NOT.PRESENT(lBackWard)) out = str(1:INDEX(str,'/')-1) |
||
211 |
END IF |
||
212 |
✓✓✗✓ |
14 |
IF(out == '') out = str |
213 |
✓✗ | 14 |
END FUNCTION strHead_1 |
214 |
!============================================================================================================================== |
||
215 |
FUNCTION strHead_m(str, sep, lBackward) RESULT(out) |
||
216 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) |
||
217 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
218 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep |
||
219 |
LOGICAL, OPTIONAL, INTENT(IN) :: lBackward |
||
220 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
221 |
INTEGER :: k |
||
222 |
IF(PRESENT(sep)) THEN |
||
223 |
IF( PRESENT(lBackWard)) out = [(strHead_1(str(k), sep, lBackWard), k=1, SIZE(str))] |
||
224 |
IF(.NOT.PRESENT(lBackWard)) out = [(strHead_1(str(k), sep), k=1, SIZE(str))] |
||
225 |
ELSE |
||
226 |
IF( PRESENT(lBackWard)) out = [(strHead_1(str(k), '/', lBackWard), k=1, SIZE(str))] |
||
227 |
IF(.NOT.PRESENT(lBackWard)) out = [(strHead_1(str(k), '/'), k=1, SIZE(str))] |
||
228 |
END IF |
||
229 |
END FUNCTION strHead_m |
||
230 |
!============================================================================================================================== |
||
231 |
!=== Extract the substring following the first (last if lBackward==TRUE) occurrence of "sep" in "str" ================ |
||
232 |
!=== Examples for str='a_b_c' and sep='_' and the bash command with the same effect: ================ |
||
233 |
!=== * strTail(str, '_', .FALSE.) = 'b_c' ${str#*$sep} ================ |
||
234 |
!=== * strTail(str, '_', .TRUE.) = 'c' ${str##*$sep} ================ |
||
235 |
!============================================================================================================================== |
||
236 |
7 |
CHARACTER(LEN=maxlen) FUNCTION strTail_1(str, sep, lBackWard) RESULT(out) |
|
237 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
238 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep |
||
239 |
LOGICAL, OPTIONAL, INTENT(IN) :: lBackWard |
||
240 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
241 |
7 |
IF(PRESENT(sep)) THEN |
|
242 |
✗✓✗✗ |
7 |
IF( PRESENT(lBackWard)) out = str(INDEX(str,sep,lBackWard)+LEN(sep):LEN_TRIM(str)) |
243 |
✓✗✓✗ |
7 |
IF(.NOT.PRESENT(lBackWard)) out = str(INDEX(str,sep) +LEN(sep):LEN_TRIM(str)) |
244 |
ELSE |
||
245 |
IF( PRESENT(lBackWard)) out = str(INDEX(str,'/',lBackWard)+1:LEN_TRIM(str)) |
||
246 |
IF(.NOT.PRESENT(lBackWard)) out = str(INDEX(str,'/') +1:LEN_TRIM(str)) |
||
247 |
END IF |
||
248 |
✗✓✗✗ |
7 |
IF(out == '') out = str |
249 |
✓✗ | 7 |
END FUNCTION strTail_1 |
250 |
!============================================================================================================================== |
||
251 |
FUNCTION strTail_m(str, sep, lBackWard) RESULT(out) |
||
252 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) |
||
253 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
254 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep |
||
255 |
LOGICAL, OPTIONAL, INTENT(IN) :: lBackWard |
||
256 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
257 |
INTEGER :: k |
||
258 |
IF(PRESENT(sep)) THEN |
||
259 |
IF( PRESENT(lBackWard)) out = [(strTail_1(str(k), sep, lBackWard), k=1, SIZE(str))] |
||
260 |
IF(.NOT.PRESENT(lBackWard)) out = [(strTail_1(str(k), sep), k=1, SIZE(str))] |
||
261 |
ELSE |
||
262 |
IF( PRESENT(lBackWard)) out = [(strTail_1(str(k), '/', lBackWard), k=1, SIZE(str))] |
||
263 |
IF(.NOT.PRESENT(lBackWard)) out = [(strTail_1(str(k), '/'), k=1, SIZE(str))] |
||
264 |
END IF |
||
265 |
END FUNCTION strTail_m |
||
266 |
!============================================================================================================================== |
||
267 |
|||
268 |
|||
269 |
!============================================================================================================================== |
||
270 |
!=== Concatenates the strings "str(:)" with separator "sep" into a single string using a separator (',' by default). ========== |
||
271 |
!============================================================================================================================== |
||
272 |
✗✓✗✗ ✗✗ |
11 |
FUNCTION strStack(str, sep, mask) RESULT(out) |
273 |
CHARACTER(LEN=:), ALLOCATABLE :: out |
||
274 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
275 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep |
||
276 |
LOGICAL, OPTIONAL, INTENT(IN) :: mask(:) |
||
277 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
278 |
CHARACTER(LEN=:), ALLOCATABLE :: s |
||
279 |
INTEGER :: is, i0 |
||
280 |
✓✓ | 11 |
IF(SIZE(str) == 0) THEN; out = ''; RETURN; END IF |
281 |
✗✓✗✓ ✗✗✗✗ ✗✗ |
1 |
ALLOCATE(s, SOURCE=', '); IF(PRESENT(sep)) s=sep |
282 |
✗✓✗✗ |
1 |
IF(PRESENT(mask)) THEN |
283 |
IF(ALL(.NOT.mask)) THEN; out = ''; RETURN; END IF |
||
284 |
i0 = 0; DO WHILE(.NOT.mask(i0+1)); i0 = i0+1; END DO |
||
285 |
out = str(i0); DO is=i0+1,SIZE(str, DIM=1); IF(.NOT.mask(is)) CYCLE; out = TRIM(out)//s//TRIM(str(is)); END DO |
||
286 |
ELSE |
||
287 |
✓✗✗✗ ✓✗✓✓ ✓✗✓✗ ✓✗✗✓ ✓✗✓✗ ✓✗ |
6 |
out = str(1); DO is=2,SIZE(str, DIM=1); out = TRIM(out)//s//TRIM(str(is)); END DO |
288 |
END IF |
||
289 |
✗✓✗✗ ✓✗ |
22 |
END FUNCTION strStack |
290 |
!============================================================================================================================== |
||
291 |
!=== Concatenate the strings "str(:)" with separator "sep" into one or several lines of "nmax" characters max (for display) === |
||
292 |
!============================================================================================================================== |
||
293 |
FUNCTION strStackm(str, sep, nmax) RESULT(out) |
||
294 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) |
||
295 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
296 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep |
||
297 |
INTEGER, OPTIONAL, INTENT(IN) :: nmax |
||
298 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
299 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: t(:) |
||
300 |
CHARACTER(LEN=maxlen) :: sp |
||
301 |
INTEGER :: is, ns, no, mx, n |
||
302 |
IF(SIZE(str) == 0) THEN; out = ['']; RETURN; END IF |
||
303 |
sp =', '; IF(PRESENT(sep )) sp = sep |
||
304 |
ns = 2 ; IF(PRESENT(sep )) ns = LEN(sep) |
||
305 |
mx = 256; IF(PRESENT(nmax)) mx = nmax |
||
306 |
no = 1; out = [''] |
||
307 |
DO is = 1, SIZE(str) |
||
308 |
n = LEN_TRIM(str(is)); IF(out(no)/='') n = n+ns+LEN_TRIM(out(no)) !--- Line length after "str(is)" inclusion |
||
309 |
IF(out(no) == '') THEN |
||
310 |
out(no) = str(is) !--- Empty new line: set to "str(is)" |
||
311 |
ELSE IF(n <= mx) THEN |
||
312 |
out(no) = TRIM(out(no))//sp(1:ns)//TRIM(str(is)) !--- Append "str(is)" to the current line |
||
313 |
ELSE |
||
314 |
ALLOCATE(t(no+1)); t(1:no) = out; no=no+1; t(no) = str(is) !--- Full line: "str(si)" put in next line |
||
315 |
CALL MOVE_ALLOC(FROM=t, TO=out) |
||
316 |
END IF |
||
317 |
END DO |
||
318 |
END FUNCTION strStackm |
||
319 |
!============================================================================================================================== |
||
320 |
|||
321 |
|||
322 |
!============================================================================================================================== |
||
323 |
!=== String cleaning: replace tabulation by spaces, remove NULL characters and comments. ====================================== |
||
324 |
!============================================================================================================================== |
||
325 |
SUBROUTINE strClean_1(str) |
||
326 |
CHARACTER(LEN=*), INTENT(INOUT) :: str |
||
327 |
INTEGER :: k, n, m |
||
328 |
n = LEN(str) |
||
329 |
DO k = n, 1, -1 |
||
330 |
m = IACHAR(str(k:k)) |
||
331 |
IF(m==9) str(k:k) = ' ' !--- Replace the tabulations with spaces |
||
332 |
IF(m==0) str(k:n) = str(k+1:n)//' ' !--- Remove the NULL characters |
||
333 |
END DO |
||
334 |
m = INDEX(str,'!')-1; IF(m==-1) m = LEN_TRIM(str) !--- Remove end of line comment |
||
335 |
str = ADJUSTL(str(1:m)) |
||
336 |
END SUBROUTINE strClean_1 |
||
337 |
!============================================================================================================================== |
||
338 |
✗✓ | 1 |
SUBROUTINE strClean_m(str) |
339 |
CHARACTER(LEN=*), INTENT(INOUT) :: str(:) |
||
340 |
INTEGER :: k |
||
341 |
✗✓ | 1 |
DO k = 1, SIZE(str); CALL strClean_1(str(k)); END DO |
342 |
1 |
END SUBROUTINE strClean_m |
|
343 |
!============================================================================================================================== |
||
344 |
|||
345 |
|||
346 |
!============================================================================================================================== |
||
347 |
!=== strReduce_1(str1) : Remove duplicated elements of str1. =========================================================== |
||
348 |
!=== strReduce_2(str1,str2): Append str1 with new elements of str2. =========================================================== |
||
349 |
!============================================================================================================================== |
||
350 |
1 |
SUBROUTINE strReduce_1(str, nb) |
|
351 |
CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: str(:) |
||
352 |
INTEGER, OPTIONAL, INTENT(OUT) :: nb |
||
353 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
354 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: s1(:) |
||
355 |
INTEGER :: k, n, n1 |
||
356 |
1 |
IF(PRESENT(nb)) nb = 0 |
|
357 |
1 |
CALL MOVE_ALLOC(FROM=str, TO=s1); CALL strClean(s1) |
|
358 |
1 |
n1 = SIZE(s1, DIM=1) !--- Total nb. of elements in "s1" |
|
359 |
✗✓✗✓ ✗✗✗✗ ✗✓✗✗ |
1 |
n = COUNT( [( ALL(s1(1:k-1)/=s1(k)), k=1, n1 )] ) !--- Nb of unique elements in "s1" |
360 |
✓✗✓✗ ✗✓✗✓ ✗✓✗✓ |
2 |
ALLOCATE(str(n)) |
361 |
✓✗ | 2 |
IF(n==0) RETURN |
362 |
str(1) = s1(1) |
||
363 |
n=1; DO k=2,n1; IF(ANY(s1(1:k-1)==s1(k))) CYCLE; n=n+1; str(n)=s1(k); END DO |
||
364 |
IF(PRESENT(nb)) nb=n |
||
365 |
✓✗✓✗ ✗✗ |
3 |
END SUBROUTINE strReduce_1 |
366 |
!============================================================================================================================== |
||
367 |
SUBROUTINE strReduce_2(str1, str2) |
||
368 |
CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: str1(:) |
||
369 |
CHARACTER(LEN=*), INTENT(IN) :: str2(:) |
||
370 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
371 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: s1(:), s2(:) |
||
372 |
INTEGER :: k |
||
373 |
IF(SIZE(str2)==0) RETURN |
||
374 |
s2 = str2; CALL strClean(s2) |
||
375 |
IF(.NOT.ALLOCATED(s2)) RETURN |
||
376 |
IF(SIZE(s2) == 0) THEN; DEALLOCATE(s2); RETURN; END IF |
||
377 |
IF(.NOT.ALLOCATED(str1)) THEN |
||
378 |
str1 = s2 |
||
379 |
ELSE IF(SIZE(str1)==0) THEN |
||
380 |
str1 = s2 |
||
381 |
ELSE |
||
382 |
s1 = str1; CALL strClean(s1) |
||
383 |
str1 = [s1, PACK(s2, MASK= [( ALL(s1(:) /= s2(k)), k=1, SIZE(s2) )] ) ] |
||
384 |
END IF |
||
385 |
END SUBROUTINE strReduce_2 |
||
386 |
!============================================================================================================================== |
||
387 |
|||
388 |
|||
389 |
!============================================================================================================================== |
||
390 |
!=== GET THE INDEX OF THE FIRST APPEARANCE IN THE STRING VECTOR "str(:)" OF THE STRING(s) "s[(:)]" ============================ |
||
391 |
!=== OPTIONALY: GET THE NUMBER OF FOUND ELEMENTS "n". NB: UNFOUND => INDEX=0 ============================ |
||
392 |
!============================================================================================================================== |
||
393 |
✗✓ | 405 |
INTEGER FUNCTION strIdx_1(str, s) RESULT(out) |
394 |
CHARACTER(LEN=*), INTENT(IN) :: str(:), s |
||
395 |
✓✓✓✓ |
1622 |
DO out = 1, SIZE(str); IF(str(out) == s) EXIT; END DO |
396 |
✓✓✗✓ |
405 |
IF(out == 1+SIZE(str) .OR. SIZE(str)==0) out = 0 |
397 |
405 |
END FUNCTION strIdx_1 |
|
398 |
!============================================================================================================================== |
||
399 |
✗✓✗✓ |
3 |
FUNCTION strIdx_m(str, s, n) RESULT(out) |
400 |
CHARACTER(LEN=*), INTENT(IN) :: str(:), s(:) |
||
401 |
INTEGER, OPTIONAL, INTENT(OUT) :: n |
||
402 |
INTEGER, ALLOCATABLE :: out(:) |
||
403 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
404 |
INTEGER :: k |
||
405 |
✗✓✓✓ ✓✗✓✓ ✗✓✗✗ ✗✓✓✗ ✗✗✓✓ |
39 |
out = [(strIdx_1(str(:), s(k)), k=1, SIZE(s))] |
406 |
✗✓✗✗ ✗✗ |
3 |
IF(PRESENT(n)) n = COUNT(out(:)/=0) |
407 |
3 |
END FUNCTION strIdx_m |
|
408 |
!============================================================================================================================== |
||
409 |
|||
410 |
|||
411 |
!============================================================================================================================== |
||
412 |
!=== GET THE INDEX LIST OF THE ELEMENTS OF "str(:)" EQUAL TO "s" AND OPTIONALY, ITS LENGTH "n" ================================ |
||
413 |
!============================================================================================================================== |
||
414 |
✗✓ | 5 |
FUNCTION strFind(str, s, n) RESULT(out) |
415 |
CHARACTER(LEN=*), INTENT(IN) :: str(:), s |
||
416 |
INTEGER, OPTIONAL, INTENT(OUT) :: n |
||
417 |
INTEGER, ALLOCATABLE :: out(:) |
||
418 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
419 |
INTEGER :: k |
||
420 |
✗✓✓✓ ✓✗✓✓ ✓✗✓✓ ✗✓ |
80 |
out = PACK( [(k, k=1, SIZE(str(:), DIM=1))], MASK = str(:) == s ) |
421 |
✓✗ | 5 |
IF(PRESENT(n)) n = SIZE(out(:), DIM=1) |
422 |
5 |
END FUNCTION strFind |
|
423 |
!============================================================================================================================== |
||
424 |
FUNCTION find_int(i,j,n) RESULT(out) |
||
425 |
INTEGER, INTENT(IN) :: i(:), j |
||
426 |
INTEGER, OPTIONAL, INTENT(OUT) :: n |
||
427 |
INTEGER, ALLOCATABLE :: out(:) |
||
428 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
429 |
INTEGER :: k |
||
430 |
out = PACK( [(k, k=1, SIZE(i(:), DIM=1))], MASK = i(:) == j ) |
||
431 |
IF(PRESENT(n)) n = SIZE(out(:), DIM=1) |
||
432 |
END FUNCTION find_int |
||
433 |
!============================================================================================================================== |
||
434 |
FUNCTION find_boo(l,n) RESULT(out) |
||
435 |
LOGICAL, INTENT(IN) :: l(:) |
||
436 |
INTEGER, OPTIONAL, INTENT(OUT) :: n |
||
437 |
INTEGER, ALLOCATABLE :: out(:) |
||
438 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
439 |
INTEGER :: k |
||
440 |
out = PACK( [(k, k=1, SIZE(l(:), DIM=1))], MASK = l(:) ) |
||
441 |
IF(PRESENT(n)) n = SIZE(out(:), DIM=1) |
||
442 |
END FUNCTION find_boo |
||
443 |
!============================================================================================================================== |
||
444 |
|||
445 |
|||
446 |
!============================================================================================================================== |
||
447 |
!=== GET THE INDEX IN "rawList" OF THE 1ST APPEARANCE OF ONE OF THE "del(:)" SEPARATORS (0 IF NONE OF THEM ARE PRESENT) |
||
448 |
!=== IF lSc == .TRUE.: * SKIP HEAD SIGNS OR EXPONENTS SIGNS THAT SHOULD NOT BE CONFUSED WITH SEPARATORS |
||
449 |
!=== * THEN TEST WHETHER THE STRING FROM START TO THE FOUND SEPARATOR IS A CORRECTLY FORMATTED NUMBER |
||
450 |
!============================================================================================================================== |
||
451 |
✗✓ | 11 |
LOGICAL FUNCTION strIdx_prv(rawList, del, ibeg, idx, idel, lSc) RESULT(lerr) |
452 |
CHARACTER(LEN=*), INTENT(IN) :: rawList !--- String in which delimiters have to be identified |
||
453 |
CHARACTER(LEN=*), INTENT(IN) :: del(:) !--- List of delimiters |
||
454 |
INTEGER, INTENT(IN) :: ibeg !--- Start index |
||
455 |
INTEGER, INTENT(OUT) :: idx !--- Index of the first identified delimiter in "rawList" |
||
456 |
INTEGER, INTENT(OUT) :: idel !--- Index of the identified delimiter (0 if idx==0) |
||
457 |
LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Care about nbs with front sign or in scient. notation |
||
458 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
459 |
INTEGER :: idx0 !--- Used to display an identified non-numeric string |
||
460 |
lerr = .FALSE. |
||
461 |
11 |
idx = strIdx1(rawList, del, ibeg, idel) !--- idx/=0: del(idel) is at position "idx" in "rawList" |
|
462 |
✓✗ | 11 |
IF(.NOT.PRESENT(lSc)) RETURN !--- No need to check exceptions for numbers => finished |
463 |
✗✓ | 11 |
IF(.NOT. lSc ) RETURN !--- No need to check exceptions for numbers => finished |
464 |
|||
465 |
!=== No delimiter found: the whole string must be a valid number |
||
466 |
IF(idx == 0) THEN !--- No element of "del" in "rawList" |
||
467 |
lerr = .NOT.is_numeric(rawList(ibeg:LEN_TRIM(rawList))) !--- String must be a number |
||
468 |
IF(lerr) idx = LEN_TRIM(rawList); RETURN !--- Set idx so that rawList(ibeg:idx-1) = whole string |
||
469 |
END IF |
||
470 |
|||
471 |
IF(test(idx == 1 .AND. INDEX('+-',del(idel)) /= 0, lerr)) RETURN !--- The front delimiter is different from +/-: error |
||
472 |
IF( idx /= 1 .AND. is_numeric(rawList(ibeg:idx-1))) RETURN !--- The input string head is a valid number |
||
473 |
|||
474 |
!=== The string part in front of the 1st delimiter is not a valid number: search for next delimiter index "idx" |
||
475 |
idx0 = idx ; idx = strIdx1(rawList, del, idx+1, idel) !--- Keep start index because idx is recycled |
||
476 |
IF(idx == 0) THEN |
||
477 |
lerr = .NOT.is_numeric(rawList(ibeg:LEN_TRIM(rawList))) !--- No other delimiter: whole string must be a valid numb |
||
478 |
IF(lerr) idx = idx0; RETURN |
||
479 |
END IF |
||
480 |
lerr = .NOT.is_numeric(rawList(ibeg:idx-1)) |
||
481 |
|||
482 |
CONTAINS |
||
483 |
|||
484 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
485 |
✗✓ | 11 |
INTEGER FUNCTION strIdx1(str, del, ib, id) RESULT(i) |
486 |
!--- Get the index of the first appereance of one of the delimiters "del(:)" in "str" starting from position "ib". |
||
487 |
!--- "id" is the index in "del(:)" of the first delimiter found. |
||
488 |
IMPLICIT NONE |
||
489 |
CHARACTER(LEN=*), INTENT(IN) :: str, del(:) |
||
490 |
INTEGER, INTENT(IN) :: ib |
||
491 |
INTEGER, INTENT(OUT) :: id |
||
492 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
493 |
✓✓✓✗ |
43 |
DO i = ib, LEN_TRIM(str); id = strIdx(del, str(i:i)); IF(id /= 0) EXIT; END DO |
494 |
✓✗ | 11 |
IF(i > LEN_TRIM(str)) THEN; i = 0; id = 0; END IF |
495 |
11 |
END FUNCTION strIdx1 |
|
496 |
|||
497 |
END FUNCTION strIdx_prv |
||
498 |
!============================================================================================================================== |
||
499 |
|||
500 |
|||
501 |
!============================================================================================================================== |
||
502 |
!=== Count the number of elements separated by "delimiter" in list "rawList". ================================================= |
||
503 |
!============================================================================================================================== |
||
504 |
10 |
LOGICAL FUNCTION strCount_11(rawList, delimiter, nb, lSc) RESULT(lerr) |
|
505 |
CHARACTER(LEN=*), INTENT(IN) :: rawList |
||
506 |
CHARACTER(LEN=*), INTENT(IN) :: delimiter |
||
507 |
INTEGER, INTENT(OUT) :: nb |
||
508 |
LOGICAL, OPTIONAL, INTENT(IN) :: lSc |
||
509 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
510 |
LOGICAL :: ll |
||
511 |
ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc |
||
512 |
✓✗✓✓ ✗✓ |
30 |
lerr = strCount_1m(rawList, [delimiter], nb, ll) |
513 |
✗✓ | 10 |
END FUNCTION strCount_11 |
514 |
!============================================================================================================================== |
||
515 |
2 |
LOGICAL FUNCTION strCount_m1(rawList, delimiter, nb, lSc) RESULT(lerr) |
|
516 |
CHARACTER(LEN=*), INTENT(IN) :: rawList(:) |
||
517 |
CHARACTER(LEN=*), INTENT(IN) :: delimiter |
||
518 |
INTEGER, ALLOCATABLE, INTENT(OUT) :: nb(:) |
||
519 |
LOGICAL, OPTIONAL, INTENT(IN) :: lSc |
||
520 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
521 |
LOGICAL :: ll |
||
522 |
INTEGER :: id |
||
523 |
✗✓✗✗ ✗✗ |
1 |
ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc .AND. INDEX('+-', delimiter) /= 0 |
524 |
lerr = .TRUE. |
||
525 |
✓✗✗✓ ✗✓ |
1 |
ALLOCATE(nb(SIZE(rawList))) |
526 |
✓✓ | 2 |
DO id = 1, SIZE(rawList) |
527 |
✓✗✓✓ ✗✓✓✗ ✓✗ |
5 |
lerr = lerr .AND. strCount_1m(rawList(id), [delimiter], nb(id), ll) |
528 |
END DO |
||
529 |
✗✓ | 1 |
END FUNCTION strCount_m1 |
530 |
!============================================================================================================================== |
||
531 |
22 |
LOGICAL FUNCTION strCount_1m(rawList, delimiter, nb, lSc) RESULT(lerr) |
|
532 |
CHARACTER(LEN=*), INTENT(IN) :: rawList |
||
533 |
CHARACTER(LEN=*), INTENT(IN) :: delimiter(:) |
||
534 |
INTEGER, INTENT(OUT) :: nb |
||
535 |
LOGICAL, OPTIONAL, INTENT(IN) :: lSc |
||
536 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
537 |
INTEGER :: ib, ie, jd, nr |
||
538 |
LOGICAL :: ll |
||
539 |
CHARACTER(LEN=1024) :: r |
||
540 |
11 |
lerr = .FALSE. |
|
541 |
✓✗ | 11 |
ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc |
542 |
✓✗ | 11 |
r = TRIM(ADJUSTL(rawList)) |
543 |
✗✓ | 11 |
nr = LEN_TRIM(r); IF(nr == 0) RETURN |
544 |
11 |
nb = 1; ib = 1 |
|
545 |
DO |
||
546 |
11 |
lerr = strIdx_prv(r, delimiter, ib, ie, jd, ll) |
|
547 |
✗✓✗✓ |
11 |
IF(fmsg('"'//TRIM(r(ib:ie-1))//'" is not numeric', ll=lerr)) RETURN |
548 |
✗✓✗✗ |
11 |
IF(ie == 0 .OR. jd == 0) EXIT |
549 |
ib = ie + LEN(delimiter(jd)) |
||
550 |
DO WHILE(r(ib:ib) == ' ' .AND. ib < nr); ib = ib + 1; END DO !--- Skip spaces before next chain |
||
551 |
nb = nb + 1 |
||
552 |
END DO |
||
553 |
✗✓ | 22 |
END FUNCTION strCount_1m |
554 |
!============================================================================================================================== |
||
555 |
|||
556 |
|||
557 |
!============================================================================================================================== |
||
558 |
!=== Purpose: Parse "delimiter"-separated list "rawList" into the pair keys(:), vals(:). ==================================== |
||
559 |
!=== Corresponding "vals" remains empty if the element does not contain "=" sign. ==================================== |
||
560 |
!============================================================================================================================== |
||
561 |
20 |
LOGICAL FUNCTION strParse(rawList, delimiter, keys, n, vals) RESULT(lerr) |
|
562 |
CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter |
||
563 |
CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: keys(:) |
||
564 |
INTEGER, OPTIONAL, INTENT(OUT) :: n |
||
565 |
CHARACTER(LEN=maxlen), ALLOCATABLE, OPTIONAL, INTENT(OUT) :: vals(:) |
||
566 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
567 |
CHARACTER(LEN=1024) :: r |
||
568 |
INTEGER :: nr, nk |
||
569 |
lerr = .FALSE. |
||
570 |
✓✓ | 20 |
r = TRIM(ADJUSTL(rawList)) |
571 |
✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗ |
20 |
nr = LEN_TRIM(r); IF(nr == 0) THEN; keys = ['']; RETURN; END IF |
572 |
20 |
CALL strParse_prv(nk) !--- COUNT THE ELEMENTS |
|
573 |
✓✗✗✓ ✗✓ |
20 |
ALLOCATE(keys(nk)) |
574 |
✓✓ | 20 |
IF(PRESENT(vals)) THEN |
575 |
✗✓✗✓ |
6 |
ALLOCATE(vals(nk)); CALL strParse_prv(nk, keys, vals) !--- PARSE THE KEYS |
576 |
ELSE |
||
577 |
14 |
CALL strParse_prv(nk, keys) !--- PARSE THE KEYS |
|
578 |
END IF |
||
579 |
✓✓ | 60 |
IF(PRESENT(n)) n = nk |
580 |
|||
581 |
CONTAINS |
||
582 |
|||
583 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
584 |
✓✓✓✗ ✗✓✓✓ ✓✗✗✓ |
40 |
SUBROUTINE strParse_prv(nkeys, keys, vals) |
585 |
!--- * Get the number of elements after parsing ("nkeys" only is present) |
||
586 |
!--- * Parse the <key>=<val> pairs and store result in "keys" and "vals" (already allocated) |
||
587 |
IMPLICIT NONE |
||
588 |
INTEGER, INTENT(OUT) :: nkeys |
||
589 |
CHARACTER(LEN=maxlen), OPTIONAL, INTENT(OUT) :: keys(:) |
||
590 |
CHARACTER(LEN=maxlen), OPTIONAL, INTENT(OUT) :: vals(:) |
||
591 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
592 |
INTEGER :: ib, ie |
||
593 |
40 |
nkeys = 1; ib = 1 |
|
594 |
28 |
DO |
|
595 |
68 |
ie = INDEX(rawList(ib:nr), delimiter)+ib-1 !--- Determine the next separator start index |
|
596 |
✓✓ | 68 |
IF(ie == ib-1) EXIT |
597 |
✓✓✓✗ ✓✗ |
28 |
IF(PRESENT(keys)) keys(nkeys) = r(ib:ie-1) !--- Get the ikth key |
598 |
✓✓✓✗ |
28 |
IF(PRESENT(vals)) CALL parseKeys(keys(nkeys), vals(nkeys)) !--- Parse the ikth <key>=<val> pair |
599 |
28 |
ib = ie + LEN(delimiter) |
|
600 |
✓✓✓✗ |
200 |
DO WHILE(r(ib:ib) == ' ' .AND. ib < nr); ib = ib + 1; END DO !--- Skip spaces before next chain |
601 |
28 |
nkeys = nkeys+1 |
|
602 |
END DO |
||
603 |
✓✓✓✗ ✓✗ |
40 |
IF(PRESENT(keys)) keys(nkeys) = r(ib:nr) !--- Get the last key |
604 |
✓✓✓✗ |
40 |
IF(PRESENT(vals)) CALL parseKeys(keys(nkeys), vals(nkeys)) !--- Parse the last <key>=<val> pair |
605 |
40 |
END SUBROUTINE strParse_prv |
|
606 |
|||
607 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
608 |
20 |
SUBROUTINE parseKeys(key, val) |
|
609 |
CHARACTER(LEN=*), INTENT(INOUT) :: key |
||
610 |
CHARACTER(LEN=*), INTENT(OUT) :: val |
||
611 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
612 |
INTEGER :: ix |
||
613 |
20 |
ix = INDEX(key, '='); IF(ix == 0) RETURN !--- First "=" index in "key" |
|
614 |
✓✗✓✗ |
14 |
val = ADJUSTL(key(ix+1:LEN_TRIM(key))) |
615 |
✓✗✓✗ |
14 |
key = ADJUSTL(key(1:ix-1)) |
616 |
✓✓ | 20 |
END SUBROUTINE parseKeys |
617 |
|||
618 |
END FUNCTION strParse |
||
619 |
!============================================================================================================================== |
||
620 |
LOGICAL FUNCTION strParse_m(rawList, delimiter, keys, n, vals, lSc, id) RESULT(lerr) |
||
621 |
CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter(:) |
||
622 |
CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: keys(:) !--- Parsed keys vector |
||
623 |
INTEGER, OPTIONAL, INTENT(OUT) :: n !--- Length of the parsed vector |
||
624 |
CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:) !--- Values for <name>=<value> keys |
||
625 |
LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Take care about numbers in scientific notation |
||
626 |
INTEGER, OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:) !--- Indexes of the separators in "delimiter(:)" vector |
||
627 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
628 |
CHARACTER(LEN=1024) :: r |
||
629 |
INTEGER :: nr, ik, nk, ib, ie, jd |
||
630 |
LOGICAL :: ll |
||
631 |
ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc |
||
632 |
IF(test(fmsg("Couldn't parse list: non-numerical strings were found", ll=strCount_1m(rawList, delimiter, nk, ll)),lerr)) RETURN |
||
633 |
|||
634 |
!--- FEW ALLOCATIONS |
||
635 |
ALLOCATE(keys(nk)) |
||
636 |
IF(PRESENT(vals)) ALLOCATE(vals(nk)) |
||
637 |
IF(PRESENT(id)) ALLOCATE(id(nk-1)) |
||
638 |
IF(PRESENT(n)) n = nk |
||
639 |
|||
640 |
!--- PARSING |
||
641 |
r = TRIM(ADJUSTL(rawList)) |
||
642 |
nr = LEN_TRIM(r); IF(nr == 0) RETURN |
||
643 |
ib = 1 |
||
644 |
DO ik = 1, nk-1 |
||
645 |
IF(test(fmsg('Non-numeric values found', ll=strIdx_prv(r, delimiter, ib, ie, jd, ll)),lerr)) RETURN |
||
646 |
keys(ik) = r(ib:ie-1) |
||
647 |
IF(PRESENT(vals)) CALL parseKeys(keys(ik), vals(ik)) !--- Parse a <key>=<val> pair |
||
648 |
IF(PRESENT(id )) id(ik) = jd !--- Index in "delimiter(:)" of the "ik"th delimiter |
||
649 |
ib = ie + LEN_TRIM( delimiter(jd) ) !--- Length of the current delimiter |
||
650 |
DO WHILE(r(ib:ib) == ' ' .AND. ib < nr); ib = ib + 1; END DO !--- Skip spaces before next chain |
||
651 |
END DO |
||
652 |
keys(nk) = r(ib:nr) |
||
653 |
IF(PRESENT(vals)) CALL parseKeys(keys(nk), vals(nk)) !--- Parse a <key>=<val> pair |
||
654 |
|||
655 |
CONTAINS |
||
656 |
|||
657 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
658 |
SUBROUTINE parseKeys(key, val) |
||
659 |
CHARACTER(LEN=*), INTENT(INOUT) :: key |
||
660 |
CHARACTER(LEN=*), INTENT(OUT) :: val |
||
661 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
662 |
INTEGER :: ix |
||
663 |
ix = INDEX(key, '='); IF(ix == 0) RETURN !--- First "=" index in "key" |
||
664 |
val = ADJUSTL(key(ix+1:LEN_TRIM(key))) |
||
665 |
key = ADJUSTL(key(1:ix-1)) |
||
666 |
END SUBROUTINE parseKeys |
||
667 |
|||
668 |
END FUNCTION strParse_m |
||
669 |
!============================================================================================================================== |
||
670 |
|||
671 |
|||
672 |
!============================================================================================================================== |
||
673 |
!=== String substitution: replace "key" by "val" each time it appears in "str". |
||
674 |
!============================================================================================================================== |
||
675 |
SUBROUTINE strReplace_1(str, key, val, lsurr) |
||
676 |
CHARACTER(LEN=*), INTENT(INOUT) :: str !--- Main string |
||
677 |
CHARACTER(LEN=*), INTENT(IN) :: key, val !--- "key" will be replaced by "val" |
||
678 |
LOGICAL, OPTIONAL, INTENT(IN) :: lsurr !--- TRUE => key must be surrounded by special characters to be substituted |
||
679 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
680 |
INTEGER :: i0, ix, nk, ns |
||
681 |
LOGICAL :: lsur, lb, le |
||
682 |
lsur = .FALSE.; IF(PRESENT(lsurr)) lsur = lsurr |
||
683 |
nk = LEN_TRIM(key) |
||
684 |
i0 = 1 |
||
685 |
DO |
||
686 |
ns = LEN_TRIM(str) |
||
687 |
ix = INDEX(str(i0:ns), TRIM(key)) !--- First appearance index of "key" in "s", starting from index "i0" |
||
688 |
IF(ix == 0) EXIT |
||
689 |
ix = ix + i0 -1 |
||
690 |
IF(lsur) THEN !--- Key must be surrounded by special characters |
||
691 |
!--- lb=.TRUE.: key is at the very beginning of "str" or located after a special character |
||
692 |
lb = ix ==1; IF(.NOT.lb) lb = INDEX('+-*/()^', str(ix-1 :ix-1 ))/=0 |
||
693 |
!--- le=.TRUE.: key is at the very end of "str" or located before a special character |
||
694 |
le = ix+nk-1==ns; IF(.NOT.le) le = INDEX('+-*/()^', str(ix+nk:ix+nk))/=0 |
||
695 |
IF(.NOT.(lb.AND.le)) THEN; i0 = i0 + nk; CYCLE; END IF |
||
696 |
END IF |
||
697 |
str = str(1:ix-1)//TRIM(val)//str(ix+nk:ns) |
||
698 |
END DO |
||
699 |
END SUBROUTINE strReplace_1 |
||
700 |
!============================================================================================================================== |
||
701 |
SUBROUTINE strReplace_m(str, key, val, lsurr) |
||
702 |
CHARACTER(LEN=*), INTENT(INOUT) :: str(:) !--- Main strings vector |
||
703 |
CHARACTER(LEN=*), INTENT(IN) :: key, val !--- "key" will be replaced by "val" |
||
704 |
LOGICAL, OPTIONAL, INTENT(IN) :: lsurr !--- TRUE => key must be surrounded by special characters to be substituted |
||
705 |
INTEGER :: k |
||
706 |
LOGICAL :: ll |
||
707 |
ll=.FALSE.; IF(PRESENT(lsurr)) ll=lsurr |
||
708 |
DO k=1, SIZE(str); CALL strReplace_1(str(k),key,val,ll); END DO |
||
709 |
END SUBROUTINE strReplace_m |
||
710 |
!============================================================================================================================== |
||
711 |
|||
712 |
|||
713 |
!============================================================================================================================== |
||
714 |
!=== Contatenate horizontally scalars/vectors of strings/integers/reals into a vector/array =================================== |
||
715 |
!============================================================================================================================== |
||
716 |
FUNCTION horzcat_s1(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) |
||
717 |
CHARACTER(LEN=*), TARGET, INTENT(IN) :: s0 |
||
718 |
CHARACTER(LEN=*), OPTIONAL, TARGET, INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9 |
||
719 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) |
||
720 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
721 |
CHARACTER(LEN=maxlen), POINTER :: s |
||
722 |
LOGICAL :: lv(10) |
||
723 |
INTEGER :: iv |
||
724 |
lv = [ .TRUE. , PRESENT(s1), PRESENT(s2), PRESENT(s3), PRESENT(s4) , & |
||
725 |
PRESENT(s5), PRESENT(s6), PRESENT(s7), PRESENT(s8), PRESENT(s9) ] |
||
726 |
ALLOCATE(out(COUNT(lv))) |
||
727 |
DO iv=1, COUNT(lv) |
||
728 |
SELECT CASE(iv) |
||
729 |
CASE(1); s=> s0; CASE(2); s=> s1; CASE(3); s=> s2; CASE(4); s=> s3; CASE(5); s=> s4 |
||
730 |
CASE(6); s=> s5; CASE(7); s=> s6; CASE(8); s=> s7; CASE(9); s=> s8; CASE(10);s=> s9 |
||
731 |
END SELECT |
||
732 |
out(iv) = s |
||
733 |
END DO |
||
734 |
END FUNCTION horzcat_s1 |
||
735 |
!============================================================================================================================== |
||
736 |
✓✗✓✗ ✗✓✓✓ ✓✗✗✓ ✓✓✓✗ ✗✓✓✓ ✓✗✗✓ ✓✓✓✗ ✗✓✓✓ ✓✗✗✓ ✓✓✓✗ ✗✓✓✓ ✓✗✗✓ ✗✓✗✗ ✗✗✗✓ |
4 |
FUNCTION horzcat_sm(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) |
737 |
CHARACTER(LEN=*), TARGET, DIMENSION(:), INTENT(IN) :: s0 |
||
738 |
CHARACTER(LEN=*), OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9 |
||
739 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:,:) |
||
740 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
741 |
CHARACTER(LEN=maxlen), POINTER :: s(:) |
||
742 |
LOGICAL :: lv(10) |
||
743 |
INTEGER :: nrow, ncol, iv, n |
||
744 |
lv = [ .TRUE. , PRESENT(s1), PRESENT(s2), PRESENT(s3), PRESENT(s4) , & |
||
745 |
✓✗✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✗✓✗✗ ✓✓ |
63 |
PRESENT(s5), PRESENT(s6), PRESENT(s7), PRESENT(s8), PRESENT(s9) ] |
746 |
✓✓✓✓ |
44 |
nrow = SIZE(s0); ncol=COUNT(lv) |
747 |
✓✗✓✗ ✗✓✗✓ ✗✓ |
8 |
ALLOCATE(out(nrow, ncol)) |
748 |
✓✓ | 25 |
DO iv=1, ncol |
749 |
4 |
SELECT CASE(iv) |
|
750 |
14 |
CASE(1); s=> s0; CASE(2); s=> s1; CASE(3); s=> s2; CASE(4); s=> s3; CASE(5); s=> s4 |
|
751 |
✓✓✓✓ ✓✓✓✓ ✓✗✗ |
21 |
CASE(6); s=> s5; CASE(7); s=> s6; CASE(8); s=> s7; CASE(9); s=> s8; CASE(10);s=> s9 |
752 |
END SELECT |
||
753 |
21 |
n = SIZE(s, DIM=1) |
|
754 |
✗✓ | 21 |
IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF |
755 |
✓✓ | 130 |
out(:,iv) = s(:) |
756 |
END DO |
||
757 |
4 |
END FUNCTION horzcat_sm |
|
758 |
!============================================================================================================================== |
||
759 |
FUNCTION horzcat_i1(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) |
||
760 |
INTEGER, TARGET, INTENT(IN) :: i0 |
||
761 |
INTEGER, OPTIONAL, TARGET, INTENT(IN) :: i1, i2, i3, i4, i5, i6, i7, i8, i9 |
||
762 |
INTEGER, ALLOCATABLE :: out(:) |
||
763 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
764 |
INTEGER, POINTER :: i |
||
765 |
LOGICAL :: lv(10) |
||
766 |
INTEGER :: iv |
||
767 |
lv = [ .TRUE. , PRESENT(i1), PRESENT(i2), PRESENT(i3), PRESENT(i4) , & |
||
768 |
PRESENT(i5), PRESENT(i6), PRESENT(i7), PRESENT(i8), PRESENT(i9) ] |
||
769 |
ALLOCATE(out(COUNT(lv))) |
||
770 |
DO iv=1, COUNT(lv) |
||
771 |
SELECT CASE(iv) |
||
772 |
CASE(1); i=> i0; CASE(2); i=> i1; CASE(3); i=> i2; CASE(4); i=> i3; CASE(5); i=> i4 |
||
773 |
CASE(6); i=> i5; CASE(7); i=> i6; CASE(8); i=> i7; CASE(9); i=> i8; CASE(10);i=> i9 |
||
774 |
END SELECT |
||
775 |
out(iv) = i |
||
776 |
END DO |
||
777 |
END FUNCTION horzcat_i1 |
||
778 |
!============================================================================================================================== |
||
779 |
✓✗✓✗ ✗✓✓✗ ✓✗✗✓ ✓✓✓✗ ✗✓✓✓ ✓✗✗✓ ✓✓✓✗ ✗✓✓✓ ✓✗✗✓ ✓✓✓✗ ✗✓✓✓ ✓✗✗✓ ✓✓✓✗ ✗✓✗✓ |
4 |
FUNCTION horzcat_im(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) |
780 |
INTEGER, TARGET, DIMENSION(:), INTENT(IN) :: i0 |
||
781 |
INTEGER, OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: i1, i2, i3, i4, i5, i6, i7, i8, i9 |
||
782 |
INTEGER, ALLOCATABLE :: out(:,:) |
||
783 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
784 |
INTEGER, POINTER :: i(:) |
||
785 |
LOGICAL :: lv(10) |
||
786 |
INTEGER :: nrow, ncol, iv, n |
||
787 |
lv = [ .TRUE. , PRESENT(i1), PRESENT(i2), PRESENT(i3), PRESENT(i4) , & |
||
788 |
✓✗✗✓ ✓✗✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓✗✓ ✓✓ |
59 |
PRESENT(i5), PRESENT(i6), PRESENT(i7), PRESENT(i8), PRESENT(i9) ] |
789 |
✓✓✓✓ |
44 |
nrow = SIZE(i0); ncol=COUNT(lv) |
790 |
✓✗✗✓ ✗✓ |
4 |
ALLOCATE(out(nrow, ncol)) |
791 |
✓✓ | 29 |
DO iv=1, ncol |
792 |
4 |
SELECT CASE(iv) |
|
793 |
16 |
CASE(1); i=> i0; CASE(2); i=> i1; CASE(3); i=> i2; CASE(4); i=> i3; CASE(5); i=> i4 |
|
794 |
✓✓✓✓ ✓✓✓✓ ✓✓✗ |
25 |
CASE(6); i=> i5; CASE(7); i=> i6; CASE(8); i=> i7; CASE(9); i=> i8; CASE(10);i=> i9 |
795 |
END SELECT |
||
796 |
25 |
n = SIZE(i, DIM=1) |
|
797 |
✗✓ | 25 |
IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF |
798 |
✓✓ | 154 |
out(:,iv) = i(:) |
799 |
END DO |
||
800 |
4 |
END FUNCTION horzcat_im |
|
801 |
!============================================================================================================================== |
||
802 |
FUNCTION horzcat_r1(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) |
||
803 |
REAL, TARGET, INTENT(IN) :: r0 |
||
804 |
REAL, OPTIONAL, TARGET, INTENT(IN) :: r1, r2, r3, r4, r5, r6, r7, r8, r9 |
||
805 |
REAL, ALLOCATABLE :: out(:) |
||
806 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
807 |
REAL, POINTER :: r |
||
808 |
LOGICAL :: lv(10) |
||
809 |
INTEGER :: iv |
||
810 |
lv = [ .TRUE. , PRESENT(r1), PRESENT(r2), PRESENT(r3), PRESENT(r4) , & |
||
811 |
PRESENT(r5), PRESENT(r6), PRESENT(r7), PRESENT(r8), PRESENT(r9) ] |
||
812 |
ALLOCATE(out(COUNT(lv))) |
||
813 |
DO iv=1, COUNT(lv) |
||
814 |
SELECT CASE(iv) |
||
815 |
CASE(1); r=> r0; CASE(2); r=> r1; CASE(3); r=> r2; CASE(4); r=> r3; CASE(5); r=> r4 |
||
816 |
CASE(6); r=> r5; CASE(7); r=> r6; CASE(8); r=> r7; CASE(9); r=> r8; CASE(10);r=> r9 |
||
817 |
END SELECT |
||
818 |
out(iv) = r |
||
819 |
END DO |
||
820 |
END FUNCTION horzcat_r1 |
||
821 |
!============================================================================================================================== |
||
822 |
FUNCTION horzcat_rm(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) |
||
823 |
REAL, TARGET, DIMENSION(:), INTENT(IN) :: r0 |
||
824 |
REAL, OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: r1, r2, r3, r4, r5, r6, r7, r8, r9 |
||
825 |
REAL, ALLOCATABLE :: out(:,:) |
||
826 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
827 |
REAL, POINTER :: r(:) |
||
828 |
LOGICAL :: lv(10) |
||
829 |
INTEGER :: nrow, ncol, iv, n |
||
830 |
lv = [ .TRUE. , PRESENT(r1), PRESENT(r2), PRESENT(r3), PRESENT(r4) , & |
||
831 |
PRESENT(r5), PRESENT(r6), PRESENT(r7), PRESENT(r8), PRESENT(r9) ] |
||
832 |
nrow = SIZE(r0); ncol=COUNT(lv) |
||
833 |
ALLOCATE(out(nrow, ncol)) |
||
834 |
DO iv=1, ncol |
||
835 |
SELECT CASE(iv) |
||
836 |
CASE(1); r=> r0; CASE(2); r=> r1; CASE(3); r=> r2; CASE(4); r=> r3; CASE(5); r=> r4 |
||
837 |
CASE(6); r=> r5; CASE(7); r=> r6; CASE(8); r=> r7; CASE(9); r=> r8; CASE(10);r=> r9 |
||
838 |
END SELECT |
||
839 |
n = SIZE(r, DIM=1) |
||
840 |
IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF |
||
841 |
out(:,iv) = r(:) |
||
842 |
END DO |
||
843 |
END FUNCTION horzcat_rm |
||
844 |
!============================================================================================================================== |
||
845 |
FUNCTION horzcat_d1(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) |
||
846 |
DOUBLE PRECISION, TARGET, INTENT(IN) :: d0 |
||
847 |
DOUBLE PRECISION, OPTIONAL, TARGET, INTENT(IN) :: d1, d2, d3, d4, d5, d6, d7, d8, d9 |
||
848 |
DOUBLE PRECISION, ALLOCATABLE :: out(:) |
||
849 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
850 |
DOUBLE PRECISION, POINTER :: d |
||
851 |
LOGICAL :: lv(10) |
||
852 |
INTEGER :: iv |
||
853 |
lv = [ .TRUE. , PRESENT(d1), PRESENT(d2), PRESENT(d3), PRESENT(d4) , & |
||
854 |
PRESENT(d5), PRESENT(d6), PRESENT(d7), PRESENT(d8), PRESENT(d9) ] |
||
855 |
ALLOCATE(out(COUNT(lv))) |
||
856 |
DO iv=1, COUNT(lv) |
||
857 |
SELECT CASE(iv) |
||
858 |
CASE(1); d=> d0; CASE(2); d=> d1; CASE(3); d=> d2; CASE(4); d=> d3; CASE(5); d=> d4 |
||
859 |
CASE(6); d=> d5; CASE(7); d=> d6; CASE(8); d=> d7; CASE(9); d=> d8; CASE(10);d=> d9 |
||
860 |
END SELECT |
||
861 |
out(iv) = d |
||
862 |
END DO |
||
863 |
END FUNCTION horzcat_d1 |
||
864 |
!============================================================================================================================== |
||
865 |
FUNCTION horzcat_dm(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) |
||
866 |
DOUBLE PRECISION, TARGET, DIMENSION(:), INTENT(IN) :: d0 |
||
867 |
DOUBLE PRECISION, OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: d1, d2, d3, d4, d5, d6, d7, d8, d9 |
||
868 |
DOUBLE PRECISION, ALLOCATABLE :: out(:,:) |
||
869 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
870 |
DOUBLE PRECISION, POINTER :: d(:) |
||
871 |
LOGICAL :: lv(10) |
||
872 |
INTEGER :: nrow, ncol, iv, n |
||
873 |
lv = [ .TRUE. , PRESENT(d1), PRESENT(d2), PRESENT(d3), PRESENT(d4) , & |
||
874 |
PRESENT(d5), PRESENT(d6), PRESENT(d7), PRESENT(d8), PRESENT(d9) ] |
||
875 |
nrow = SIZE(d0); ncol=COUNT(lv) |
||
876 |
ALLOCATE(out(nrow, ncol)) |
||
877 |
DO iv=1, ncol |
||
878 |
SELECT CASE(iv) |
||
879 |
CASE(1); d=> d0; CASE(2); d=> d1; CASE(3); d=> d2; CASE(4); d=> d3; CASE(5); d=> d4 |
||
880 |
CASE(6); d=> d5; CASE(7); d=> d6; CASE(8); d=> d7; CASE(9); d=> d8; CASE(10);d=> d9 |
||
881 |
END SELECT |
||
882 |
n = SIZE(d, DIM=1) |
||
883 |
IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF |
||
884 |
out(:,iv) = d(:) |
||
885 |
END DO |
||
886 |
END FUNCTION horzcat_dm |
||
887 |
!============================================================================================================================== |
||
888 |
|||
889 |
|||
890 |
!============================================================================================================================== |
||
891 |
!--- Display a clean table composed of successive vectors of same length. |
||
892 |
!=== The profile "p" describe in which order to pick up the columns from "s", "i" and "r" for display. |
||
893 |
!=== * nRowMax lines are displayed (default: all lines) |
||
894 |
!=== * nColMax characters (default: as long as needed) are displayed at most on a line. If the effective total length is |
||
895 |
!=== higher, several partial tables are displayed ; the nHead (default: 1) first columns are included in each sub-table. |
||
896 |
!============================================================================================================================== |
||
897 |
✓✗✗✓ ✓✗✓✗ ✗✓✗✓ ✗✗✗✗ ✗✓ |
4 |
LOGICAL FUNCTION dispTable(p, titles, s, i, r, rFmt, nRowMax, nColMax, nHead, unit, sub) RESULT(lerr) |
898 |
CHARACTER(LEN=*), INTENT(IN) :: p !--- DISPLAY MAP: s/i/r |
||
899 |
CHARACTER(LEN=*), INTENT(IN) :: titles(:) !--- TITLES (ONE EACH COLUMN) |
||
900 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: s(:,:) !--- STRINGS |
||
901 |
INTEGER, OPTIONAL, INTENT(IN) :: i(:,:) !--- INTEGERS |
||
902 |
REAL, OPTIONAL, INTENT(IN) :: r(:,:) !--- REALS |
||
903 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: rFmt !--- Format for reals |
||
904 |
INTEGER, OPTIONAL, INTENT(IN) :: nRowMax !--- Display at most "nRowMax" rows |
||
905 |
INTEGER, OPTIONAL, INTENT(IN) :: nColMax !--- Display at most "nColMax" characters each line |
||
906 |
INTEGER, OPTIONAL, INTENT(IN) :: nHead !--- Head columns repeated for multiple tables display |
||
907 |
INTEGER, OPTIONAL, INTENT(IN) :: unit !--- Output unit (default: screen) |
||
908 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sub !--- Subroutine name |
||
909 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
910 |
CHARACTER(LEN=2048) :: row |
||
911 |
CHARACTER(LEN=maxlen) :: rFm, el, subn |
||
912 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: d(:,:) |
||
913 |
CHARACTER(LEN=1) :: s1, sp |
||
914 |
INTEGER :: is, ii, ir, it, k, nmx, unt, ic, np |
||
915 |
INTEGER :: ns, ni, nr, nt, l, ncol, nHd, ib, l0 |
||
916 |
INTEGER, ALLOCATABLE :: n(:), ncmx(:) |
||
917 |
INTEGER, PARAMETER :: nm=1 !--- Space between values & columns |
||
918 |
LOGICAL :: ls, li, lr |
||
919 |
✓✗✓✓ |
4 |
subn = ''; IF(PRESENT(sub)) subn = sub |
920 |
✗✓✗✗ |
4 |
rFm = '*'; IF(PRESENT(rFmt)) rFm = rFmt !--- Specified format for reals |
921 |
✗✓ | 4 |
unt = lunout; IF(PRESENT(unit)) unt = unit !--- Specified output unit |
922 |
4 |
np = LEN_TRIM(p); ns = 0; ni = 0; nr = 0; ncol = 0 |
|
923 |
✓✗✗✓ ✓✗✗✓ ✗✓✗✗ |
4 |
ls = PRESENT(s); li = PRESENT(i); lr = PRESENT(r) |
924 |
✗✓✗✗ |
4 |
lerr = .FALSE.; IF(.NOT.ANY([ls,li,lr])) RETURN !--- Nothing to do |
925 |
sp = '|' !--- Separator |
||
926 |
|||
927 |
!--- CHECK ARGUMENTS COHERENCE |
||
928 |
✗✓ | 4 |
lerr = np /= SIZE(titles); IF(fmsg('display map "p" length and titles list mismatch', subn, lerr)) RETURN |
929 |
✓✗ | 4 |
IF(ls) THEN |
930 |
✗✓✓✓ ✓✓✓✓ |
96 |
ns = SIZE(s, 1); ncol = ncol + SIZE(s, 2); lerr = COUNT([(p(ic:ic)=='s', ic=1, np)]) /= SIZE(s, 2) |
931 |
END IF |
||
932 |
✓✗ | 4 |
IF(li) THEN |
933 |
✗✓✓✓ ✓✓✓✓ |
96 |
ni = SIZE(i, 1); ncol = ncol + SIZE(i, 2); lerr = COUNT([(p(ic:ic)=='i', ic=1, np)]) /= SIZE(i, 2) |
934 |
END IF |
||
935 |
✗✓ | 4 |
IF(lr) THEN |
936 |
nr = SIZE(r, 1); ncol = ncol + SIZE(r, 2); lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, 2) |
||
937 |
END IF |
||
938 |
✗✓ | 4 |
IF(fmsg('display map "p" length and arguments number mismatch', subn, lerr)) RETURN |
939 |
✗✓ | 4 |
lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', subn, lerr)) RETURN |
940 |
✓✗✓✗ ✗✓ |
8 |
lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', subn, lerr)) RETURN |
941 |
✗✓✗✗ ✗✓ |
8 |
lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg( 'string and real arguments lengths mismatch', subn, lerr)) RETURN |
942 |
✗✓✗✗ ✗✓ |
8 |
lerr = li.AND.lr.AND.ni/=nr; IF(fmsg( 'integer and real arguments lengths mismatch', subn, lerr)) RETURN |
943 |
✗✓ | 4 |
nmx = MAX(ns,ni,nr)+1; IF(PRESENT(nRowMax)) nmx = MIN(nmx,nRowMax+1) |
944 |
|||
945 |
!--- Allocate the assembled quantities array |
||
946 |
✓✗✓✗ ✗✓✗✓ ✓✗✗✓ |
8 |
ALLOCATE(d(nmx,ncol), n(ncol)) |
947 |
|||
948 |
!--- Assemble the vectors into a strings array in the order indicated by "pattern" |
||
949 |
is = 1; ii = 1; ir = 1 |
||
950 |
✓✓ | 50 |
DO ic = 1, ncol |
951 |
✓✗ | 46 |
d(1,ic) = TRIM(titles(ic)) |
952 |
4 |
SELECT CASE(p(ic:ic)) |
|
953 |
✓✓✗✓ |
126 |
CASE('s'); d(2:nmx,ic) = s(:,is) ; is = is + 1 |
954 |
✓✓ | 150 |
CASE('i'); d(2:nmx,ic) = int2str(i(:,ii) ); ii = ii + 1 |
955 |
✓✓✗✗ ✗✗ |
46 |
CASE('r'); d(2:nmx,ic) = real2str(r(:,ir),rFm); ir = ir + 1 |
956 |
END SELECT |
||
957 |
END DO |
||
958 |
✓✓✓✓ |
326 |
CALL cleanZeros(d) |
959 |
✓✓ | 50 |
DO ic = 1, ncol |
960 |
✓✓ | 326 |
n(ic)=0; DO ir=1, nmx; n(ic)=MAX(n(ic), LEN_TRIM(d(ir,ic))); END DO |
961 |
END DO |
||
962 |
✓✓ | 50 |
n(:) = n(:) + 2*nm |
963 |
|||
964 |
!--- Build the vector of max column index in case the rows are too long (table must be displayed in multiple parts) |
||
965 |
✓✗ | 4 |
nHd = 1; IF(PRESENT(nHead)) nHd = nHead |
966 |
✗✓ | 4 |
IF(.NOT.PRESENT(nColMax)) THEN |
967 |
nt = 1; ncmx = [ncol] |
||
968 |
ELSE |
||
969 |
✓✓ | 12 |
nt = 1; l0 = SUM(n(1:nHd)+1)+1 |
970 |
✓✗ | 4 |
IF(PRESENT(sub)) l0=l0+LEN_TRIM(subn)+1 |
971 |
!--- Count the number of table parts |
||
972 |
✓✓✗✓ |
42 |
l = l0; DO ic = nHd+1, ncol; l = l+n(ic)+1; IF(l>=nColMax) THEN; nt = nt+1; l = l0+n(ic)+1; END IF; END DO |
973 |
!--- Get the index of the last column for each table part |
||
974 |
✓✗✗✓ |
4 |
ALLOCATE(ncmx(nt)); k = 1 |
975 |
✓✓✗✓ |
42 |
l = l0; DO ic = nHd+1, ncol; l = l+n(ic)+1; IF(l>=nColMax) THEN; ncmx(k) = ic-1; l = l0+n(ic)+1; k = k+1; END IF; END DO |
976 |
4 |
ncmx(nt) = ncol |
|
977 |
END IF |
||
978 |
|||
979 |
!--- Display the strings array as a table |
||
980 |
✓✓ | 8 |
DO it = 1, nt |
981 |
✓✓ | 28 |
DO ir = 1, nmx; row = '' |
982 |
✓✓ | 72 |
DO ic = 1, nHd; el = d(ir,ic) |
983 |
48 |
s1 = sp |
|
984 |
✗✓✓✓ ✓✗ |
174 |
row = TRIM(row)//REPEAT(' ',nm)//TRIM(el)//REPEAT(' ',n(ic)-LEN_TRIM(el)-nm)//s1 |
985 |
END DO |
||
986 |
✗✓ | 24 |
ib = nHd+1; IF(it>1) ib = ncmx(it-1)+1 |
987 |
✓✓ | 252 |
DO ic = ib, ncmx(it); el = d(ir,ic) |
988 |
228 |
s1 = sp |
|
989 |
✗✓✓✓ ✓✗ |
1100 |
row = TRIM(row)//REPEAT(' ',nm)//TRIM(el)//REPEAT(' ',n(ic)-LEN_TRIM(el)-nm)//s1 |
990 |
END DO |
||
991 |
24 |
nr = LEN_TRIM(row)-1 !--- Final separator removed |
|
992 |
24 |
CALL msg(row(1:nr), subn, unit=unt) |
|
993 |
✓✓ | 24 |
IF(ir /= 1) CYCLE !--- Titles only are underlined |
994 |
✓✓✗✓ ✓✓✓✗ |
54 |
row=''; DO ic=1,nHd; row=TRIM(row)//REPEAT('-',n(ic))//'+'; END DO |
995 |
✓✓✗✓ ✓✓✓✗ |
320 |
DO ic = ib,ncmx(it); row=TRIM(row)//REPEAT('-',n(ic))//'+'; END DO |
996 |
28 |
CALL msg(row(1:LEN_TRIM(row)-1), subn, unit=unt) |
|
997 |
END DO |
||
998 |
8 |
CALL msg('', subn, unit=unt) |
|
999 |
END DO |
||
1000 |
|||
1001 |
✓✗✓✗ ✓✗✓✗ |
8 |
END FUNCTION dispTable |
1002 |
!============================================================================================================================== |
||
1003 |
|||
1004 |
!============================================================================================================================== |
||
1005 |
LOGICAL FUNCTION dispNamelist(unt, p, titles, s, i, r, rFmt, llast) RESULT(lerr) |
||
1006 |
INTEGER, INTENT(IN) :: unt !--- Output unit |
||
1007 |
CHARACTER(LEN=*), INTENT(IN) :: p !--- DISPLAY MAP: s/i/r |
||
1008 |
CHARACTER(LEN=*), INTENT(IN) :: titles(:) !--- TITLES (ONE EACH COLUMN) |
||
1009 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: s(:,:) !--- STRINGS |
||
1010 |
INTEGER, OPTIONAL, INTENT(IN) :: i(:,:) !--- INTEGERS |
||
1011 |
REAL, OPTIONAL, INTENT(IN) :: r(:,:) !--- REALS |
||
1012 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: rFmt !--- Format for reals |
||
1013 |
LOGICAL, OPTIONAL, INTENT(IN) :: llast !--- Last variable: no final ',' |
||
1014 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1015 |
CHARACTER(LEN=maxlen) :: rFm, el |
||
1016 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: d(:,:) |
||
1017 |
CHARACTER(LEN=:), ALLOCATABLE :: sp, row |
||
1018 |
INTEGER :: is, ii, ir, nrow, ic |
||
1019 |
INTEGER :: ns, ni, nr, ncol, np |
||
1020 |
INTEGER, ALLOCATABLE :: n(:) |
||
1021 |
LOGICAL :: ls, li, lr, la |
||
1022 |
rFm = '*'; IF(PRESENT(rFmt)) rFm = rFmt !--- Specified format for reals |
||
1023 |
ls = PRESENT(s); li = PRESENT(i); lr = PRESENT(r) |
||
1024 |
lerr = .FALSE.; IF(.NOT.ANY([ls,li,lr])) RETURN !--- Nothing to do |
||
1025 |
la = .FALSE.; IF(PRESENT(llast)) la = llast |
||
1026 |
|||
1027 |
!--- CHECK ARGUMENTS COHERENCE |
||
1028 |
ns = 0; ni = 0; nr = 0; np = LEN_TRIM(p); ncol = 0 |
||
1029 |
IF(ls) THEN; ns = SIZE(s, DIM=1); ncol = ncol + SIZE(s, DIM=2) |
||
1030 |
lerr = COUNT([(p(ic:ic)=='s', ic=1, np)]) /= SIZE(s, DIM=2) |
||
1031 |
END IF |
||
1032 |
IF(li) THEN; ni = SIZE(i, DIM=1); ncol = ncol + SIZE(i, DIM=2) |
||
1033 |
lerr = COUNT([(p(ic:ic)=='i', ic=1, np)]) /= SIZE(i, DIM=2) |
||
1034 |
END IF |
||
1035 |
IF(lr) THEN; nr = SIZE(r, DIM=1); ncol = ncol + SIZE(r, DIM=2) |
||
1036 |
lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, DIM=2) |
||
1037 |
END IF |
||
1038 |
IF(fmsg('display map "p" length and arguments number mismatch', ll=lerr)) RETURN |
||
1039 |
lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', ll=lerr)) RETURN |
||
1040 |
lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', ll=lerr)) RETURN |
||
1041 |
lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg( 'string and real arguments lengths mismatch', ll=lerr)) RETURN |
||
1042 |
lerr = li.AND.lr.AND.ni/=nr; IF(fmsg( 'integer and real arguments lengths mismatch', ll=lerr)) RETURN |
||
1043 |
|||
1044 |
!--- Allocate the assembled quantities array |
||
1045 |
nrow = MAX(ns,ni,nr)+1 |
||
1046 |
ALLOCATE(d(nrow,ncol), n(ncol)) |
||
1047 |
|||
1048 |
!--- Assemble the vectors into a strings array in the order indicated by "pattern" |
||
1049 |
is = 1; ii = 1; ir = 1 |
||
1050 |
DO ic = 1, ncol |
||
1051 |
d(1,ic) = TRIM(titles(ic)) |
||
1052 |
SELECT CASE(p(ic:ic)) |
||
1053 |
CASE('s'); d(2:nrow,ic) = s(:,is) ; is = is + 1 |
||
1054 |
CASE('i'); d(2:nrow,ic) = int2str(i(:,ii) ); ii = ii + 1 |
||
1055 |
CASE('r'); d(2:nrow,ic) = real2str(r(:,ir),rFm); ir = ir + 1 |
||
1056 |
END SELECT |
||
1057 |
END DO |
||
1058 |
CALL cleanZeros(d) |
||
1059 |
DO ic = 1, ncol |
||
1060 |
n(ic) = 0; DO ir=1, nrow; n(ic)=MAX(n(ic), LEN_TRIM(d(ir,ic))); END DO |
||
1061 |
IF(needQuotes(d(2,ic)) .AND. ic/=1) n(ic) = n(ic) + 2 !--- For quotes, using second line only |
||
1062 |
END DO |
||
1063 |
|||
1064 |
!--- Display the strings array as a table |
||
1065 |
DO ir = 1, nrow |
||
1066 |
row = ''; sp = ' '; IF(TRIM(d(ir,1)) /= '') sp = ' = ' |
||
1067 |
DO ic = 1, ncol |
||
1068 |
el = d(ir,ic); IF(ic /= 1) el = addQuotes_1(el) |
||
1069 |
row = row//TRIM(el)//REPEAT(' ',n(ic)-LEN_TRIM(el))//sp |
||
1070 |
sp = ' '; IF(ic /= ncol-1) CYCLE |
||
1071 |
IF(TRIM(d(MIN(ir+1,nrow),1)) /= '' .AND. (ir /= nrow .OR. .NOT.la)) sp = ' , ' |
||
1072 |
END DO |
||
1073 |
WRITE(unt,'(a)')TRIM(row) |
||
1074 |
END DO |
||
1075 |
|||
1076 |
!--- End of section |
||
1077 |
IF(la) THEN |
||
1078 |
WRITE(unt,'(a)')'/' |
||
1079 |
WRITE(unt,'(a)') |
||
1080 |
END IF |
||
1081 |
|||
1082 |
END FUNCTION dispNameList |
||
1083 |
!============================================================================================================================== |
||
1084 |
|||
1085 |
|||
1086 |
!============================================================================================================================== |
||
1087 |
LOGICAL FUNCTION dispOutliers_1(ll, a, n, err_msg, nam, subn, nRowmax, nColMax, nHead, unit) RESULT(lerr) |
||
1088 |
! Display outliers list in tables |
||
1089 |
! If "nam" is supplied, it means the last index is for tracers => one table each tracer for rank > 2. |
||
1090 |
LOGICAL, INTENT(IN) :: ll(:) !--- Linearized mask of outliers |
||
1091 |
REAL, INTENT(IN) :: a(:) !--- Linearized array of values |
||
1092 |
INTEGER, INTENT(IN) :: n(:) !--- Profile before linearization |
||
1093 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: err_msg, nam(:), subn !--- Error message, variables and calling subroutine names |
||
1094 |
INTEGER, OPTIONAL, INTENT(IN) :: nRowMax !--- Maximum number of lines to display (default: all) |
||
1095 |
INTEGER, OPTIONAL, INTENT(IN) :: nColMax !--- Maximum number of characters per line (default: 2048) |
||
1096 |
INTEGER, OPTIONAL, INTENT(IN) :: nHead !--- Number of front columns to duplicate (default: 1) |
||
1097 |
INTEGER, OPTIONAL, INTENT(IN) :: unit !--- Output unit (def: lunout) |
||
1098 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1099 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:) |
||
1100 |
LOGICAL, ALLOCATABLE :: m(:) |
||
1101 |
INTEGER, ALLOCATABLE :: ki(:), kj(:) |
||
1102 |
INTEGER :: i, j, k, rk, rk1, ib, ie, itr, nm, unt, nRmx, nCmx, nHd, nv |
||
1103 |
CHARACTER(LEN=maxlen) :: mes, sub, fm='(f12.9)', v, s |
||
1104 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: vnm(:) |
||
1105 |
|||
1106 |
lerr = ANY(ll); IF(.NOT.lerr) RETURN !--- No outliers -> finished |
||
1107 |
|||
1108 |
mes = 'outliers found'; IF(PRESENT(err_msg)) mes = err_msg !--- Error message |
||
1109 |
vnm = ['a']; IF(PRESENT(nam )) vnm = nam !--- Variables names |
||
1110 |
sub = 'dispOutliers'; IF(PRESENT(subn)) sub = subn !--- Calling subroutine name |
||
1111 |
nRmx= SIZE(a); IF(PRESENT(nRowMax)) nRmx=MIN(nRmx,nRowMax)!-- Maximum number of lines to print |
||
1112 |
nCmx= 2048; IF(PRESENT(nColMax)) nCmx=MIN(nCmx,nColMax)!-- Maximum number of characters each line |
||
1113 |
nHd = 1; IF(PRESENT(nHead)) nHd = nHead !--- Number of front columns to duplicate |
||
1114 |
unt = lunout; IF(PRESENT(unit)) unt = unit !--- Unit to print messages |
||
1115 |
|||
1116 |
rk = SIZE(n); nv = SIZE(vnm) |
||
1117 |
IF(test(fmsg('SIZE(nam) /= 1 and /= last "n" element', sub, nv /= 1 .AND. nv /= n(rk), unt),lerr)) RETURN |
||
1118 |
IF(test(fmsg('ll" and "a" sizes mismatch', sub, SIZE(a) /= SIZE(ll), unt),lerr)) RETURN |
||
1119 |
IF(test(fmsg('profile "n" does not match "a" and "ll', sub, SIZE(a) /= PRODUCT(n), unt),lerr)) RETURN |
||
1120 |
CALL msg(mes, sub, unit=unt) |
||
1121 |
|||
1122 |
!--- SCALAR CASE: single value to display |
||
1123 |
IF(rk==1.AND.n(1)==1) THEN |
||
1124 |
IF(ll(1)) WRITE(unt,'(a," = ",f12.9)')TRIM(nam(1)),a(1); RETURN |
||
1125 |
END IF |
||
1126 |
|||
1127 |
rk1 = rk; IF(nv==1) rk1 = rk-1 !--- Rank of each displayed table |
||
1128 |
SELECT CASE(rk1) !--- Indices list |
||
1129 |
CASE(1,2); ki = [ (i,i=1,n(1)) ] |
||
1130 |
CASE(3); ki = [((i,i=1,n(1)),j=1,n(2))]; kj = [((j,i=1,n(1)),j=1,n(2))] |
||
1131 |
CASE DEFAULT; WRITE(unt,*)'Sorry: routine "dispOutliers" is limited to rank 3'; RETURN |
||
1132 |
END SELECT |
||
1133 |
|||
1134 |
!--- VECTOR CASE: table " name | value " (known names) / ) / " i | a(i) " (unknown names) |
||
1135 |
IF(rk==1) THEN |
||
1136 |
ALLOCATE(ttl(2)); ttl(2) = TRIM(vnm(1))//'(i)'; ttl(1) = 'i' |
||
1137 |
IF(nv == 1) lerr = dispTable('sr', ttl, s=cat(PACK(nam,ll)), r=cat(PACK(a,ll)), & |
||
1138 |
rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub) |
||
1139 |
IF(nv /= 1) lerr = dispTable('ir', ['name ','value'], i=cat(PACK(ki,m)), r=cat(PACK(a,ll)), & |
||
1140 |
rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub) |
||
1141 |
CALL msg("can't display outliers table", sub, lerr, unt) |
||
1142 |
RETURN |
||
1143 |
END IF |
||
1144 |
|||
1145 |
!--- OTHER CASES: one table for each tracer (last index) |
||
1146 |
ttl = [(ACHAR(k), k = 105, 104+rk)] !--- Titles list ('i', 'j', 'k'...) |
||
1147 |
s = strStack( ttl(1:rk-1) ) !--- Tracer name dummy indexes: (i, j, k, ... |
||
1148 |
|||
1149 |
DO itr=1,n(rk) |
||
1150 |
nm = PRODUCT(n(1:rk-1)) !--- number of elements per tracer |
||
1151 |
ie = itr*nm; ib = ie-nm+1; m=ll(ib:ie) !--- section bounds for tracer "itr" ; outlayers mask |
||
1152 |
IF(.NOT.ANY(m)) CYCLE !--- no outlayers for tracer "itr" |
||
1153 |
v = TRIM(vnm(MIN(itr,SIZE(vnm))))//'('//TRIM(s) !--- "<name>(" |
||
1154 |
IF(nv == 1) ttl(rk) = TRIM(v)//','//int2str(itr)//')' !--- "<name>(i,j,itr)" (single name) |
||
1155 |
IF(nv /= 1) ttl(rk) = TRIM(v)//')' !--- "<nam(itr)>(i,j)" (one name each table/itr index) |
||
1156 |
IF(rk==2) lerr = dispTable('ir', ttl, i=cat(PACK(ki,m)), r=cat(PACK(a(ib:ie),m)), & |
||
1157 |
rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub) |
||
1158 |
IF(rk==3) lerr = dispTable('iir', ttl, i=cat(PACK(ki,m),PACK(kj,m)), r=cat(PACK(a(ib:ie),m)), & |
||
1159 |
rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub) |
||
1160 |
CALL msg("can't display outliers table", sub, lerr, unt) |
||
1161 |
IF(lerr) RETURN |
||
1162 |
END DO |
||
1163 |
END FUNCTION dispOutliers_1 |
||
1164 |
!============================================================================================================================== |
||
1165 |
LOGICAL FUNCTION dispOutliers_2(ll, a, n, err_msg, nam, subn, nRowMax, nColMax, nHead, unit) RESULT(lerr) |
||
1166 |
! Display outliers list in tables |
||
1167 |
! If "nam" is supplied and, it means the last index is for tracers => one table each tracer for rank > 2. |
||
1168 |
LOGICAL, INTENT(IN) :: ll(:) !--- Linearized mask of outliers |
||
1169 |
REAL, INTENT(IN) :: a(:,:) !--- Linearized arrays of values stacked along 2nd dim. |
||
1170 |
INTEGER, INTENT(IN) :: n(:) !--- Profile before linearization |
||
1171 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: err_msg, nam(:), subn !--- Error message, variables and calling subroutine names |
||
1172 |
INTEGER, OPTIONAL, INTENT(IN) :: nRowMax !--- Maximum number of lines to display (default: all) |
||
1173 |
INTEGER, OPTIONAL, INTENT(IN) :: nColMax !--- Maximum number of characters per line (default: 2048) |
||
1174 |
INTEGER, OPTIONAL, INTENT(IN) :: nHead !--- Number of front columns to duplicate (default: 1) |
||
1175 |
INTEGER, OPTIONAL, INTENT(IN) :: unit !--- Output unit (def: lunout) |
||
1176 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1177 |
CHARACTER(LEN=maxlen) :: mes, sub, fm='(f12.9)', prf |
||
1178 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), vnm(:) |
||
1179 |
INTEGER, ALLOCATABLE :: ki(:), kj(:), kl(:) |
||
1180 |
INTEGER :: i, j, k, rk, nv, unt, nRmx, nCmx, nHd |
||
1181 |
REAL, ALLOCATABLE :: val(:,:) |
||
1182 |
|||
1183 |
lerr = ANY(ll); IF(.NOT.lerr) RETURN !--- No outliers -> finished |
||
1184 |
rk = SIZE(n); nv = SIZE(a,2) |
||
1185 |
mes = 'outliers found'; IF(PRESENT(err_msg)) mes = err_msg !--- Error message |
||
1186 |
vnm = [(ACHAR(k+96),k=1,nv)]; IF(PRESENT(nam )) vnm = nam !--- Variables names |
||
1187 |
sub = 'dispOutliers'; IF(PRESENT(subn)) sub = subn !--- Calling subroutine name |
||
1188 |
nRmx= SIZE(a); IF(PRESENT(nRowMax)) nRmx=MIN(nRmx,nRowMax)!-- Maximum number of lines to print |
||
1189 |
nCmx= 2048; IF(PRESENT(nColMax)) nCmx=MIN(nCmx,nColMax)!-- Maximum number of characters each line |
||
1190 |
nHd = 1; IF(PRESENT(nHead)) nHd = nHead !--- Number of front columns to duplicate |
||
1191 |
unt = lunout; IF(PRESENT(unit)) unt = unit !--- Unit to print messages |
||
1192 |
lerr= SIZE(vnm) /= nv; IF(fmsg('SIZE(nam) /= SIZE(a,2)', sub, lerr, unt)) RETURN |
||
1193 |
lerr= SIZE(a,1) /= SIZE(ll); IF(fmsg('"ll" and "a" sizes mismatch', sub, lerr, unt)) RETURN |
||
1194 |
lerr= SIZE(a,1) /= PRODUCT(n); IF(fmsg('profile "n" does not match "a" and "ll"', sub, lerr, unt)) RETURN |
||
1195 |
|||
1196 |
SELECT CASE(rk) !--- Indices list |
||
1197 |
CASE(0); IF(ll(1)) THEN; WRITE(unt,'(a,", ",a," = ",2f12.9)')TRIM(vnm(1)),TRIM(vnm(2)),a(1,1),a(1,2); RETURN; END IF |
||
1198 |
CASE(1); ki = [ (i,i=1,n(1)) ] |
||
1199 |
CASE(2); ki = [ ((i,i=1,n(1)),j=1,n(2))]; kj = [ ((j,i=1,n(1)),j=1,n(2))] |
||
1200 |
CASE(3); ki = [(((i,i=1,n(1)),j=1,n(2)),k=1,n(3))]; kj = [(((j,i=1,n(1)),j=1,n(2)),k=1,n(3))] |
||
1201 |
kl = [(((k,i=1,n(1)),j=1,n(2)),k=1,n(3))] |
||
1202 |
CASE DEFAULT; WRITE(unt,*)'Sorry: routine "dispOutliers_2" is limited to rank 3'; RETURN |
||
1203 |
END SELECT |
||
1204 |
|||
1205 |
ttl = [(ACHAR(k), k = 105, 104+rk), vnm] !--- Titles list ('i', 'j', 'k'...'var1', 'var2', ...) |
||
1206 |
prf = REPEAT('i',rk)//REPEAT('r',nv) !--- Profile |
||
1207 |
ALLOCATE(val(COUNT(ll),nv)); DO k=1, nv; val(:,k) = PACK(a(:,k),ll); END DO |
||
1208 |
IF(rk == 1) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll)), r = val, & |
||
1209 |
rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub) |
||
1210 |
IF(rk == 2) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll)), r = val, & |
||
1211 |
rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub) |
||
1212 |
IF(rk == 3) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll),PACK(kl,ll)), r = val, & |
||
1213 |
rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub) |
||
1214 |
CALL msg("can't display outliers table", sub, lerr, unt) |
||
1215 |
END FUNCTION dispOutliers_2 |
||
1216 |
!============================================================================================================================== |
||
1217 |
|||
1218 |
|||
1219 |
!============================================================================================================================== |
||
1220 |
!=== Reduce an algebrical expression (basic operations and parenthesis) to a single number (string format) ==================== |
||
1221 |
!============================================================================================================================== |
||
1222 |
LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(lerr) |
||
1223 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
1224 |
CHARACTER(LEN=maxlen), INTENT(OUT) :: val |
||
1225 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1226 |
CHARACTER(LEN=maxlen) :: v |
||
1227 |
CHARACTER(LEN=1024) :: s, vv |
||
1228 |
CHARACTER(LEN=1024), ALLOCATABLE :: vl(:) |
||
1229 |
INTEGER, ALLOCATABLE :: ip(:) |
||
1230 |
INTEGER :: nl, nn, i, j, im, ix |
||
1231 |
LOGICAL :: ll |
||
1232 |
s = str |
||
1233 |
|||
1234 |
!--- Check wether the parenthesis are correctly formed |
||
1235 |
ll = strCount(s,'(',nl) |
||
1236 |
ll = strCount(s,')',nn) |
||
1237 |
lerr = nl /= nn |
||
1238 |
IF(fmsg('Mismatching number of opening and closing parenthesis: '//TRIM(s), ll=lerr)) RETURN |
||
1239 |
nl = 2*nl-1 |
||
1240 |
|||
1241 |
!--- Build vectors ; vl: parenthesis-separated elements ; ip: parenthesis types (1: opening, 2: closing) |
||
1242 |
ALLOCATE(ip(nl-1),vl(nl)) |
||
1243 |
j = 1; im = 1 |
||
1244 |
DO i = 1, LEN_TRIM(str) |
||
1245 |
ix = INDEX('()', str(i:i)) |
||
1246 |
IF(ix == 0) CYCLE |
||
1247 |
ip(j) = ix |
||
1248 |
vl(j) = str(im:i-1) |
||
1249 |
j = j + 1; im = i + 1 |
||
1250 |
END DO |
||
1251 |
vl(j) = str(im:LEN_TRIM(str)) |
||
1252 |
|||
1253 |
!--- Search for each opening/closing parenthesis pair |
||
1254 |
DO WHILE(nl > 1) |
||
1255 |
i = 1; DO WHILE(ip(i) /= 1 .OR. ip(i+1) /= 2); i = i + 1; END DO !IF(i > SIZE(ip)+1) EXIT;END DO |
||
1256 |
IF(test(reduceExpr_basic(vl(i+1), v), lerr)) RETURN |
||
1257 |
v = TRIM(vl(i))//TRIM(v); IF(i+2<=nl) v=TRIM(v)//TRIM(vl(i+2)) |
||
1258 |
vv = v//REPEAT(' ',768) |
||
1259 |
IF(i == 1) THEN; ip = ip(3:nl-1); vl = [ vv, vl(4 :nl)] |
||
1260 |
ELSE IF(i == nl-1) THEN; ip = ip(1:nl-2); vl = [vl(1:nl-3), vv ] |
||
1261 |
ELSE; ip = [ip(1: i-1), ip(i+2:nl-1)]; vl = [vl(1: i-1), vv, vl(i+3:nl)]; END IF |
||
1262 |
nl = SIZE(vl) |
||
1263 |
END DO |
||
1264 |
lerr = reduceExpr_basic(vl(1), val) |
||
1265 |
END FUNCTION reduceExpr_1 |
||
1266 |
|||
1267 |
|||
1268 |
!============================================================================================================================== |
||
1269 |
!=== Reduce a simple algebrical expression (basic operations, no parenthesis) to a single number (string format) ============== |
||
1270 |
!============================================================================================================================== |
||
1271 |
LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(lerr) |
||
1272 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
1273 |
CHARACTER(LEN=*), INTENT(OUT) :: val |
||
1274 |
DOUBLE PRECISION, ALLOCATABLE :: vl(:) |
||
1275 |
INTEGER, ALLOCATABLE :: id(:) |
||
1276 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: ky(:) |
||
1277 |
CHARACTER(LEN=1), ALLOCATABLE :: op(:) |
||
1278 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1279 |
CHARACTER(LEN=1024) :: s |
||
1280 |
DOUBLE PRECISION :: v, vm, vp |
||
1281 |
INTEGER :: i, ni, io |
||
1282 |
lerr = .FALSE. |
||
1283 |
IF(is_numeric(str)) THEN; val=TRIM(str); RETURN; END IF |
||
1284 |
op = ['^','/','*','+','-'] !--- List of recognized operations |
||
1285 |
s = str |
||
1286 |
IF(test(strParse_m(s, op, ky, lSc=.TRUE., id = id), lerr)) RETURN !--- Parse the values |
||
1287 |
vl = str2dble(ky) !--- Conversion to doubles |
||
1288 |
lerr = ANY(vl >= HUGE(1.d0)) |
||
1289 |
IF(fmsg('Some values are non-numeric in: '//TRIM(s), ll=lerr)) RETURN !--- Non-numerical values found |
||
1290 |
DO io = 1, SIZE(op) !--- Loop on known operators (order matters !) |
||
1291 |
DO i = SIZE(id), 1, -1 !--- Loop on found operators |
||
1292 |
ni = SIZE(id) |
||
1293 |
IF(id(i) /= io) CYCLE !--- Current found operator is not op(io) |
||
1294 |
vm = vl(i); vp = vl(i+1) !--- Couple of values used for current operation |
||
1295 |
SELECT CASE(op(io)) !--- Perform operation on the two values |
||
1296 |
CASE('^'); v = vm**vp |
||
1297 |
CASE('/'); v = vm/vp |
||
1298 |
CASE('*'); v = vm*vp |
||
1299 |
CASE('+'); v = vm+vp |
||
1300 |
CASE('-'); v = vm-vp |
||
1301 |
END SELECT |
||
1302 |
IF(i == ni) THEN; vl = [vl(1:ni-1), v]; ELSE; vl = [vl(1:i-1), v, vl(i+2:ni+1)]; END IF |
||
1303 |
IF(i == ni) THEN; id = id(1:ni-1); ELSE; id = [id(1:i-1), id(i+1:ni )]; END IF |
||
1304 |
END DO |
||
1305 |
END DO |
||
1306 |
val = dble2str(vl(1)) |
||
1307 |
|||
1308 |
END FUNCTION reduceExpr_basic |
||
1309 |
!============================================================================================================================== |
||
1310 |
|||
1311 |
!============================================================================================================================== |
||
1312 |
FUNCTION reduceExpr_m(str, val) RESULT(lerr) |
||
1313 |
LOGICAL, ALLOCATABLE :: lerr(:) |
||
1314 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
1315 |
CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) |
||
1316 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1317 |
INTEGER :: i |
||
1318 |
ALLOCATE(lerr(SIZE(str)),val(SIZE(str))) |
||
1319 |
lerr(:) = [(reduceExpr_1(str(i), val(i)), i=1, SIZE(str))] |
||
1320 |
END FUNCTION reduceExpr_m |
||
1321 |
!============================================================================================================================== |
||
1322 |
|||
1323 |
|||
1324 |
!============================================================================================================================== |
||
1325 |
!=== Check whether a string is a number or not ================================================================================ |
||
1326 |
!============================================================================================================================== |
||
1327 |
276 |
ELEMENTAL LOGICAL FUNCTION is_numeric(str) RESULT(out) |
|
1328 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
1329 |
REAL :: x |
||
1330 |
INTEGER :: e |
||
1331 |
CHARACTER(LEN=12) :: fmt |
||
1332 |
✓✗ | 276 |
IF(TRIM(str) == '') THEN; out = .FALSE.; RETURN; END IF |
1333 |
276 |
WRITE(fmt,'("(f",i0,".0)")') LEN_TRIM(str) |
|
1334 |
276 |
READ(str,fmt,IOSTAT=e) x |
|
1335 |
✓✓✗✓ |
276 |
out = e==0 .AND. INDEX('Ee',str(LEN_TRIM(str):LEN_TRIM(str)))==0 |
1336 |
END FUNCTION is_numeric |
||
1337 |
!============================================================================================================================== |
||
1338 |
|||
1339 |
|||
1340 |
!============================================================================================================================== |
||
1341 |
!=== Convert a string into a logical/integer integer or an integer/real into a string ========================================= |
||
1342 |
!============================================================================================================================== |
||
1343 |
ELEMENTAL LOGICAL FUNCTION str2bool(str) RESULT(out) |
||
1344 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
1345 |
INTEGER :: ierr |
||
1346 |
READ(str,*,IOSTAT=ierr) out |
||
1347 |
IF(ierr==0) RETURN |
||
1348 |
out = ANY(['t ','true ','.true.','y ','yes ']==strLower(str)) |
||
1349 |
END FUNCTION str2bool |
||
1350 |
!============================================================================================================================== |
||
1351 |
20 |
ELEMENTAL INTEGER FUNCTION str2int(str) RESULT(out) |
|
1352 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
1353 |
INTEGER :: ierr |
||
1354 |
20 |
READ(str,*,IOSTAT=ierr) out |
|
1355 |
✗✓ | 20 |
IF(ierr/=0) out = -HUGE(1) |
1356 |
20 |
END FUNCTION str2int |
|
1357 |
!============================================================================================================================== |
||
1358 |
ELEMENTAL REAL FUNCTION str2real(str) RESULT(out) |
||
1359 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
1360 |
INTEGER :: ierr |
||
1361 |
READ(str,*,IOSTAT=ierr) out |
||
1362 |
IF(ierr/=0) out = -HUGE(1.) |
||
1363 |
END FUNCTION str2real |
||
1364 |
!============================================================================================================================== |
||
1365 |
ELEMENTAL DOUBLE PRECISION FUNCTION str2dble(str) RESULT(out) |
||
1366 |
CHARACTER(LEN=*), INTENT(IN) :: str |
||
1367 |
INTEGER :: ierr |
||
1368 |
READ(str,*,IOSTAT=ierr) out |
||
1369 |
IF(ierr/=0) out = -HUGE(1.d0) |
||
1370 |
END FUNCTION str2dble |
||
1371 |
!============================================================================================================================== |
||
1372 |
15 |
ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION bool2str(b) RESULT(out) |
|
1373 |
LOGICAL, INTENT(IN) :: b |
||
1374 |
15 |
WRITE(out,*)b |
|
1375 |
15 |
out = ADJUSTL(out) |
|
1376 |
15 |
END FUNCTION bool2str |
|
1377 |
!============================================================================================================================== |
||
1378 |
1913 |
ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION int2str(i, nDigits) RESULT(out) |
|
1379 |
INTEGER, INTENT(IN) :: i |
||
1380 |
INTEGER, OPTIONAL, INTENT(IN) :: nDigits |
||
1381 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1382 |
1913 |
WRITE(out,*)i |
|
1383 |
1913 |
out = ADJUSTL(out) |
|
1384 |
✓✓ | 1913 |
IF(.NOT.PRESENT(nDigits)) RETURN |
1385 |
✓✗✓✓ |
1188 |
IF(nDigits > LEN_TRIM(out)) out = REPEAT('0', nDigits - LEN_TRIM(out))//TRIM(out) |
1386 |
END FUNCTION int2str |
||
1387 |
!============================================================================================================================== |
||
1388 |
5 |
ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION real2str(r,fmt) RESULT(out) |
|
1389 |
REAL, INTENT(IN) :: r |
||
1390 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt |
||
1391 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1392 |
✗✓ | 5 |
IF( PRESENT(fmt)) WRITE(out,fmt)r |
1393 |
✓✗ | 5 |
IF(.NOT.PRESENT(fmt)) WRITE(out, * )r |
1394 |
5 |
out = ADJUSTL(out) |
|
1395 |
5 |
END FUNCTION real2str |
|
1396 |
!============================================================================================================================== |
||
1397 |
ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION dble2str(d,fmt) RESULT(out) |
||
1398 |
DOUBLE PRECISION, INTENT(IN) :: d |
||
1399 |
CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt |
||
1400 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1401 |
IF( PRESENT(fmt)) WRITE(out,fmt)d |
||
1402 |
IF(.NOT.PRESENT(fmt)) WRITE(out, * )d |
||
1403 |
out = ADJUSTL(out) |
||
1404 |
END FUNCTION dble2str |
||
1405 |
!============================================================================================================================== |
||
1406 |
276 |
ELEMENTAL SUBROUTINE cleanZeros(s) |
|
1407 |
CHARACTER(LEN=*), INTENT(INOUT) :: s |
||
1408 |
INTEGER :: ls, ix, i |
||
1409 |
276 |
IF(is_numeric(s)) THEN |
|
1410 |
125 |
ls = LEN_TRIM(s) |
|
1411 |
125 |
ix = MAX(INDEX(s,'E'),INDEX(s,'e'),INDEX(s,'D'),INDEX(s,'d')) |
|
1412 |
✓✗ | 125 |
IF(ix == 0) THEN |
1413 |
✓✓✓✓ ✓✗✓✗ |
225 |
DO ix = ls,1,-1; IF(s(ix:ix) /= '0') EXIT; END DO; s=s(1:ix+1) |
1414 |
ELSE IF(INDEX(s,'.')/=0) THEN |
||
1415 |
i = ix-1; DO WHILE(s(i:i) == '0'); i = i-1; END DO; s=s(1:i)//s(ix:ls) |
||
1416 |
END IF |
||
1417 |
END IF |
||
1418 |
✓✓ | 276 |
END SUBROUTINE cleanZeros |
1419 |
!============================================================================================================================== |
||
1420 |
|||
1421 |
|||
1422 |
!============================================================================================================================== |
||
1423 |
FUNCTION addQuotes_1(s) RESULT(out) |
||
1424 |
CHARACTER(LEN=*), INTENT(IN) :: s |
||
1425 |
CHARACTER(LEN=:), ALLOCATABLE :: out |
||
1426 |
IF(needQuotes(s)) THEN; out = "'"//TRIM(s)//"'"; ELSE; out = s; END IF |
||
1427 |
END FUNCTION addQuotes_1 |
||
1428 |
!============================================================================================================================== |
||
1429 |
FUNCTION addQuotes_m(s) RESULT(out) |
||
1430 |
CHARACTER(LEN=*), INTENT(IN) :: s(:) |
||
1431 |
CHARACTER(LEN=:), ALLOCATABLE :: out(:) |
||
1432 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1433 |
INTEGER :: k, n |
||
1434 |
n = MAXVAL(LEN_TRIM(s), MASK=.TRUE.) |
||
1435 |
ALLOCATE(CHARACTER(LEN=n) :: out(SIZE(s))) |
||
1436 |
DO k=1,SIZE(s) |
||
1437 |
IF(needQuotes(s(k))) THEN; out(k) = "'"//TRIM(s(k))//"'"; ELSE; out(k) = s(k); END IF |
||
1438 |
END DO |
||
1439 |
END FUNCTION addQuotes_m |
||
1440 |
!============================================================================================================================== |
||
1441 |
ELEMENTAL LOGICAL FUNCTION needQuotes(s) RESULT(out) |
||
1442 |
CHARACTER(LEN=*), INTENT(IN) :: s |
||
1443 |
CHARACTER(LEN=1) :: b, e |
||
1444 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1445 |
out = .TRUE.; IF(TRIM(s) == '') RETURN |
||
1446 |
b = s(1:1); e = s(MAX(1,LEN_TRIM(s)):MAX(1,LEN_TRIM(s))) |
||
1447 |
out = .NOT.is_numeric(s) .AND. (b /= "'" .OR. e /= "'") .AND. ( b /= '"' .OR. e /= '"') |
||
1448 |
END FUNCTION needQuotes |
||
1449 |
!============================================================================================================================== |
||
1450 |
|||
1451 |
|||
1452 |
!============================================================================================================================== |
||
1453 |
!=== DISPLAY "<message>: the following <items> are <reason>" FOLLOWED BY THE LIST OF <str> FOR WHICH <lerr>==T. =============== |
||
1454 |
!============================================================================================================================== |
||
1455 |
✗✓✗✓ |
4 |
LOGICAL FUNCTION checkList(str, lerr, message, items, reason, nmax) RESULT(out) |
1456 |
! Purpose: Messages in case a list contains wrong elements (indicated by lerr boolean vector). |
||
1457 |
! Note: Return value "out" is .TRUE. if there are errors (ie at least one element of "lerr" is TRUE). |
||
1458 |
CHARACTER(LEN=*), INTENT(IN) :: str(:) |
||
1459 |
LOGICAL, INTENT(IN) :: lerr(:) |
||
1460 |
CHARACTER(LEN=*), INTENT(IN) :: message, items, reason |
||
1461 |
INTEGER, OPTIONAL, INTENT(IN) :: nmax |
||
1462 |
!------------------------------------------------------------------------------------------------------------------------------ |
||
1463 |
CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:) |
||
1464 |
INTEGER :: i, nmx |
||
1465 |
✗✓ | 4 |
nmx = 256; IF(PRESENT(nmax)) nmx=nmax |
1466 |
✓✓✓✗ ✗✓ |
20 |
out = ANY(lerr); IF(.NOT.out) RETURN |
1467 |
CALL msg(TRIM(message)//': the following '//TRIM(items)//' are '//TRIM(reason)//':') |
||
1468 |
s = strStackm(PACK(str, MASK=lerr), ', ',nmx) |
||
1469 |
DO i=1,SIZE(s,DIM=1); CALL msg(s(i)); END DO |
||
1470 |
✗✓ | 4 |
END FUNCTION checkList |
1471 |
!============================================================================================================================== |
||
1472 |
|||
1473 |
|||
1474 |
!============================================================================================================================== |
||
1475 |
!=== Remove comment in line "str", ie all the characters from the first "#" sign found in "str". ============================== |
||
1476 |
!============================================================================================================================== |
||
1477 |
8 |
SUBROUTINE removeComment(str) |
|
1478 |
CHARACTER(LEN=*), INTENT(INOUT) :: str |
||
1479 |
INTEGER :: ix |
||
1480 |
ix = INDEX(str,'# '); IF(ix /= 0) str = str(1:ix-1)//REPEAT(' ',LEN(str)-ix+1) |
||
1481 |
✗✓ | 8 |
END SUBROUTINE removeComment |
1482 |
!============================================================================================================================== |
||
1483 |
|||
1484 |
|||
1485 |
END MODULE strings_mod |
Generated by: GCOVR (Version 4.2) |