libsim Versione 7.2.6
char_utilities.F90
1! Copyright (C) 2010 ARPA-SIM <urpsim@smr.arpa.emr.it>
2! authors:
3! Davide Cesari <dcesari@arpa.emr.it>
4! Paolo Patruno <ppatruno@arpa.emr.it>
5
6! This program is free software; you can redistribute it and/or
7! modify it under the terms of the GNU General Public License as
8! published by the Free Software Foundation; either version 2 of
9! the License, or (at your option) any later version.
10
11! This program is distributed in the hope that it will be useful,
12! but WITHOUT ANY WARRANTY; without even the implied warranty of
13! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14! GNU General Public License for more details.
15
16! You should have received a copy of the GNU General Public License
17! along with this program. If not, see <http://www.gnu.org/licenses/>.
18!> \brief Utilities for CHARACTER variables.
19!!
20!! This module is a collection of all-purpose utilities connected to
21!! the use of CHARACTER variables, and text handling in general.
22!!
23!! \ingroup base
24#include "config.h"
25MODULE char_utilities
26USE kinds
28USE io_units
29IMPLICIT NONE
30
31CHARACTER(len=*),PARAMETER :: LOWER_CASE = 'abcdefghijklmnopqrstuvwxyz'
32CHARACTER(len=*),PARAMETER :: UPPER_CASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
33
34!> Set of functions that return a CHARACTER representation of the
35!! input variable. The return value is of type \a CHARACTER with a
36!! predefined length depending on the type of the input. The functions
37!! use a default format suitable to reasonably represent the input
38!! variable, or a user-defined format provided with the optional
39!! variable \a form. The \a miss optional value, if provided,
40!! replaces the output representation in case the input is missing
41!! according to the definitions in \a missing_values module. The
42!! length of the \a miss parameter should not exceed the length of the
43!! maximum representable value of the provided type, otherwise it may
44!! be truncated. For numerical types, the return value may be quite
45!! long, in order to take into account all possible cases, so it is
46!! suggested to trim the result with the intrinsic function \a TRIM()
47!! before using it. Be warned that no check is performed on the
48!! optional format \a form, so a runtime error may occur if it is
49!! syntactically wrong or not suitable to the data type provided. The
50!! functions are \a ELEMENTAL, so they can be applied to arrays of any
51!! shape.
52!!
53!! \param in (any type of INTEGER, REAL or CHARACTER) value to be represented as CHARACTER
54!! \param miss CHARACTER(len=*),INTENT(in),OPTIONAL optional character replacement for missing value
55!! \param form CHARACTER(len=*),INTENT(in),OPTIONAL optional format
56!!
57!! Example of use:
58!! \code
59!! USE char_utilities
60!! INTEGER :: j
61!! ...
62!! WRITE(*,*)'The value provided, '//TRIM(to_char(j))//', is too large'
63!! ...
64!! \endcode
65INTERFACE to_char
66 MODULE PROCEDURE int_to_char, byte_to_char, &
67 real_to_char, double_to_char, logical_to_char, &
68 char_to_char, char_to_char_miss
69END INTERFACE
70
71
72!> Set of functions that return a trimmed CHARACTER representation of the
73!! input variable. The functions are analogous to \a to_char but they
74!! return a representation of the input in a CHARACTER with a variable
75!! length, which needs not to be trimmed before use. The optional
76!! format here is not accepted and these functions are not \a
77!! ELEMENTAL so they work only on scalar arguments.
78!!
79!! \param in (any type of INTEGER, REAL or CHARACTER) value to be represented as CHARACTER
80!! \param miss CHARACTER(len=*),INTENT(in),OPTIONAL optional character replacement for missing value
81!!
82!! Example of use:
83!! \code
84!! USE char_utilities
85!! INTEGER :: j
86!! ...
87!! WRITE(*,*)'The value provided, '//t2c(j)//', is too large'
88!! ...
89!! \endcode
90INTERFACE t2c
91 MODULE PROCEDURE trim_int_to_char, trim_int_to_char_miss, &
92 trim_byte_to_char, trim_byte_to_char_miss, &
93 trim_real_to_char, trim_real_to_char_miss, &
94 trim_double_to_char, trim_double_to_char_miss, trim_logical_to_char, &
95 trim_char_to_char, trim_char_to_char_miss
96END INTERFACE
97
98
99!> Class that allows splitting a long line into shorter lines of equal
100!! length at the occurrence of a specific character (typically a blank
101!! space). All the members of the class are \a PRIVATE, thus all the
102!! operations are performed through its methods.
103TYPE line_split
104 PRIVATE
105 INTEGER :: align_type, ncols, nlines
106 INTEGER, POINTER :: word_start(:), word_end(:)
107 CHARACTER(len=1), POINTER :: paragraph(:,:)
108END TYPE line_split
109
110!> Destructor for the \a line_split class.
111!! It cleanly destroys a \a line_split object, deallocating all the
112!! dynamically allocated space.
113!!
114!! \param this (TYPE(line_split)) object to be destroyed
115INTERFACE delete
116 MODULE PROCEDURE line_split_delete
117END INTERFACE
118
119
120!> Tries to match the given string with the pattern
121!! Result:
122!! .true. if the entire string matches the pattern, .false.
123!! otherwise
124!! Note:
125!! Trailing blanks are ignored
126!!
127!! provides a string matching method known as glob matching: it is used
128!! for instance under UNIX, Linux and DOS to select files whose names
129!! match a certain pattern - strings like "*.f90" describe all file
130!! swhose names end in ".f90".
131!!
132!! The method implemented in the module is somewhat simplified than the
133!! full glob matching possible under UNIX: it does not support
134!! character classes.
135!!
136!! Glob patterns are intended to match the entire string. In this
137!! implementation, however, trailing blanks in both the string and the
138!! pattern are ignored, so that it is a bit easier to use in Fortran.
139!!
140!! The module supports both "*" and "?" as wild cards, where "*" means
141!! any sequence of characters, including zero and "?" means a single
142!! character. If you need to match the characters "*" or "?", then
143!! precede them with a backslash ("\"). If you need to match a
144!! backslash, you will need to use two:
145!!
146!!
147!! match = string_match( "c:\somedir" "c:\\*" )
148!!
149!! will return .true., while:
150!!
151!! match = string_match( "c:\somedir" "c:\*" )
152!!
153!! will not match, as the backslash "escapes" the asterisk, which then becomes an ordinary character.
154!!
155!! BUGS
156!!
157!! The matching algorithm is not flawless:
158!!
159!! * Patterns like "e* *" may fail, because trailing blanks are
160!! removed. The string "e " ought to match this pattern, but
161!! because only the substring "e" will be considered, the
162!! trailing blank that is necessary for matching between the two
163!! asterisks is removed from the matching process.
164!!
165!! The test program contains a case that should fail on this, but it does not, oddly enough.
166!!
167!! * Patterns like "b*ba" fail on a string like "babababa" because
168!! the algorithm finds an early match (the substring at 3:4) for
169!! the last literal substring "ba" in the pattern. It should
170!! instead skip over that substring and search for the substring
171!! 7:8.
172!!
173!! There are two ways to deal with this:
174!!
175!! o Insert an extra character at the end, which does not occur anywhere in the pattern.
176!!
177!! o If the match fails, continue at a point after the position of the literal substring where matching failed.
178!!
179!! The second is probably the way to go, but it may be a bit slower.
180INTERFACE match
181 MODULE PROCEDURE string_match, string_match_v
182END INTERFACE
183
184
185!> Class to print a progress bar on the screen.
186!! This class prints a progress bar on the screen, which can be
187!! updated by the calling program. At the moment the progress can only
188!! be displayed in percent (0-100) of the min-max progress interval,
189!! with a predefined format. The progress interval also defaults to
190!! 0-100 but it can be changed by the user after instantiating the
191!! object, but before updating it.
192TYPE progress_line
193 DOUBLE PRECISION :: min=0.0d0 !< minimum value of the progress interval
194 DOUBLE PRECISION :: max=100.0d0 !< minimum value of the progress interval
195 DOUBLE PRECISION,PRIVATE :: curr=0.0d0
196 CHARACTER(len=512),PRIVATE :: form='(''|'',I3.0,''%|'',A,''|'',10X,''|'')'
197 CHARACTER(len=1),PRIVATE :: done='='
198 CHARACTER(len=1),PRIVATE :: todo='-'
199 INTEGER,PRIVATE :: barloc=8
200 INTEGER,PRIVATE :: spin=0
201 CONTAINS
202 PROCEDURE :: update => progress_line_update_d, progress_line_update_i
203 PROCEDURE :: alldone => progress_line_alldone
204END TYPE progress_line
205
206CHARACTER(len=4),PARAMETER :: progress_line_spin='-\|/'
207
208PRIVATE
209PUBLIC line_split
210PUBLIC to_char, t2c, c2i, c2r, c2d, delete, match, &
211 fchar_to_cstr, fchar_to_cstr_alloc, cstr_to_fchar, uppercase, lowercase, &
212 align_center, l_nblnk, f_nblnk, word_split, &
213 line_split_new, line_split_get_nlines, line_split_get_line, &
214 suffixname, default_columns, wash_char, &
215 print_status_line, done_status_line, progress_line
216
217CONTAINS
218
219! Version with integer argument, please use the generic \a to_char
220! rather than this function directly.
221ELEMENTAL FUNCTION int_to_char(in, miss, form) RESULT(char)
222INTEGER,INTENT(in) :: in ! value to be represented as CHARACTER
223CHARACTER(len=*),INTENT(in),OPTIONAL :: miss ! replacement for missing value
224CHARACTER(len=*),INTENT(in),OPTIONAL :: form ! optional format
225CHARACTER(len=11) :: char
226
227IF (PRESENT(miss)) THEN
228 IF (.NOT.c_e(in)) THEN
229 char = miss
230 ELSE
231 IF (PRESENT(form)) THEN
232 WRITE(char,form)in
233 ELSE
234 WRITE(char,'(I0)')in
235 ENDIF
236 ENDIF
237ELSE
238 IF (PRESENT(form)) THEN
239 WRITE(char,form)in
240 ELSE
241 WRITE(char,'(I0)')in
242 ENDIF
243ENDIF
244
245END FUNCTION int_to_char
246
247
248FUNCTION trim_int_to_char(in) RESULT(char)
249INTEGER,INTENT(in) :: in ! value to be represented as CHARACTER
250CHARACTER(len=LEN_TRIM(to_char(in))) :: char
251
252char = to_char(in)
254END FUNCTION trim_int_to_char
255
256
257FUNCTION trim_int_to_char_miss(in, miss) RESULT(char)
258INTEGER,INTENT(in) :: in ! value to be represented as CHARACTER
259CHARACTER(len=*),INTENT(in) :: miss ! replacement for missing value
260CHARACTER(len=LEN_TRIM(to_char(in,miss=miss))) :: char
261
262char = to_char(in, miss=miss)
263
264END FUNCTION trim_int_to_char_miss
265
266
267! Version with 1-byte integer argument, please use the generic \a to_char
268! rather than this function directly.
269ELEMENTAL FUNCTION byte_to_char(in, miss, form) RESULT(char)
270INTEGER(kind=int_b),INTENT(in) :: in ! value to be represented as CHARACTER
271CHARACTER(len=*),INTENT(in),OPTIONAL :: miss ! replacement for missing value
272CHARACTER(len=*),INTENT(in),OPTIONAL :: form ! optional format
273CHARACTER(len=11) :: char
274
275IF (PRESENT(miss)) THEN
276 IF (.NOT.c_e(in)) THEN
277 char = miss
278 ELSE
279 IF (PRESENT(form)) THEN
280 WRITE(char,form)in
281 ELSE
282 WRITE(char,'(I0)')in
283 ENDIF
284 ENDIF
285ELSE
286 IF (PRESENT(form)) THEN
287 WRITE(char,form)in
288 ELSE
289 WRITE(char,'(I0)')in
290 ENDIF
291ENDIF
292
293END FUNCTION byte_to_char
294
295
296FUNCTION trim_byte_to_char(in) RESULT(char)
297INTEGER(kind=int_b),INTENT(in) :: in ! value to be represented as CHARACTER
298CHARACTER(len=LEN_TRIM(to_char(in))) :: char
299
300char = to_char(in)
301
302END FUNCTION trim_byte_to_char
304
305FUNCTION trim_byte_to_char_miss(in,miss) RESULT(char)
306INTEGER(kind=int_b),INTENT(in) :: in ! value to be represented as CHARACTER
307CHARACTER(len=*),INTENT(in) :: miss ! replacement for missing value
308CHARACTER(len=LEN_TRIM(to_char(in,miss=miss))) :: char
309
310char = to_char(in, miss=miss)
311
312END FUNCTION trim_byte_to_char_miss
313
314
315! Version with character argument, please use the generic \a to_char
316! rather than this function directly. It is almost useless, just
317! provided for completeness.
318ELEMENTAL FUNCTION char_to_char(in) RESULT(char)
319CHARACTER(len=*),INTENT(in) :: in ! value to be represented as CHARACTER
320CHARACTER(len=LEN(in)) :: char
321
322char = in
323
324END FUNCTION char_to_char
325
326
327ELEMENTAL FUNCTION char_to_char_miss(in, miss) RESULT(char)
328CHARACTER(len=*),INTENT(in) :: in ! value to be represented as CHARACTER
329CHARACTER(len=*),INTENT(in) :: miss ! replacement for missing value
330CHARACTER(len=MAX(LEN(in),LEN(miss))) :: char
331
332IF (c_e(in)) THEN
333 char = in
334ELSE
335 char = miss
336ENDIF
337
338END FUNCTION char_to_char_miss
339
340
341FUNCTION trim_char_to_char(in) result(char)
342CHARACTER(len=*),INTENT(in) :: in ! value to be represented as CHARACTER
343CHARACTER(len=LEN_TRIM(in)) :: char
344
345char = trim(in)
346
347END FUNCTION trim_char_to_char
348
349
350FUNCTION trim_char_to_char_miss(in, miss) RESULT(char)
351CHARACTER(len=*),INTENT(in) :: in ! value to be represented as CHARACTER
352CHARACTER(len=*),INTENT(in) :: miss ! replacement for missing valu
353CHARACTER(len=LEN_TRIM(char_to_char_miss(in,miss))) :: char
354
355char = char_to_char_miss(in, miss)
356
357END FUNCTION trim_char_to_char_miss
358
359
360! Version with single precision real argument, please use the generic
361! \a to_char rather than this function directly.
362ELEMENTAL FUNCTION real_to_char(in, miss, form) RESULT(char)
363REAL,INTENT(in) :: in ! value to be represented as CHARACTER
364CHARACTER(len=*),INTENT(in),OPTIONAL :: miss ! replacement for missing value
365CHARACTER(len=*),INTENT(in),OPTIONAL :: form ! optional format
366CHARACTER(len=15) :: char
367
368CHARACTER(len=15) :: tmpchar
369
370IF (PRESENT(miss)) THEN
371 IF (.NOT.c_e(in)) THEN
372 char = miss
373 ELSE
374 IF (PRESENT(form)) THEN
375 WRITE(char,form)in
376 ELSE
377 WRITE(tmpchar,'(G15.9)') in
378 char = adjustl(tmpchar)
379 ENDIF
380 ENDIF
381ELSE
382 IF (PRESENT(form)) THEN
383 WRITE(char,form)in
384 ELSE
385 WRITE(tmpchar,'(G15.9)') in
386 char = adjustl(tmpchar)
387 ENDIF
388ENDIF
389
390END FUNCTION real_to_char
392
393FUNCTION trim_real_to_char(in) RESULT(char)
394REAL,INTENT(in) :: in ! value to be represented as CHARACTER
395CHARACTER(len=LEN_TRIM(to_char(in))) :: char
396
397char = real_to_char(in)
398
399END FUNCTION trim_real_to_char
400
401
402FUNCTION trim_real_to_char_miss(in, miss) RESULT(char)
403REAL,INTENT(in) :: in ! value to be represented as CHARACTER
404CHARACTER(len=*),INTENT(in) :: miss ! replacement for missing value
405CHARACTER(len=LEN_TRIM(to_char(in,miss=miss))) :: char
406
407char = real_to_char(in, miss=miss)
408
409END FUNCTION trim_real_to_char_miss
410
411
412! Version with double precision real argument, please use the generic
413! \a to_char rather than this function directly.
414ELEMENTAL FUNCTION double_to_char(in, miss, form) RESULT(char)
415DOUBLE PRECISION,INTENT(in) :: in ! value to be represented as CHARACTER
416CHARACTER(len=*),INTENT(in),OPTIONAL :: miss ! replacement for missing value
417CHARACTER(len=*),INTENT(in),OPTIONAL :: form ! optional format
418CHARACTER(len=24) :: char
419
420CHARACTER(len=24) :: tmpchar
421
422IF (PRESENT(miss)) THEN
423 IF (.NOT.c_e(in)) THEN
424 char = miss
425 ELSE
426 IF (PRESENT(form)) THEN
427 WRITE(char,form)in
428 ELSE
429 WRITE(tmpchar,'(G24.17)') in
430 char = adjustl(tmpchar)
431 ENDIF
432 ENDIF
433ELSE
434 IF (PRESENT(form)) THEN
435 WRITE(char,form)in
436 ELSE
437 WRITE(tmpchar,'(G24.17)') in
438 char = adjustl(tmpchar)
439 ENDIF
440ENDIF
441
442END FUNCTION double_to_char
443
444
445FUNCTION trim_double_to_char(in) RESULT(char)
446DOUBLE PRECISION,INTENT(in) :: in ! value to be represented as CHARACTER
447CHARACTER(len=LEN_TRIM(to_char(in))) :: char
448
449char=double_to_char(in)
450
451END FUNCTION trim_double_to_char
452
453
454FUNCTION trim_double_to_char_miss(in, miss) RESULT(char)
455DOUBLE PRECISION,INTENT(in) :: in ! value to be represented as CHARACTER
456CHARACTER(len=*),INTENT(in) :: miss ! replacement for missing value
457CHARACTER(len=LEN_TRIM(to_char(in,miss=miss))) :: char
458
459char=double_to_char(in, miss=miss)
460
461END FUNCTION trim_double_to_char_miss
462
463
464! Version with logical argument, please use the generic \a to_char
465! rather than this function directly.
466ELEMENTAL FUNCTION logical_to_char(in, form) RESULT(char)
467LOGICAL,INTENT(in) :: in ! value to be represented as CHARACTER
468CHARACTER(len=*),INTENT(in),OPTIONAL :: form ! optional format
469CHARACTER(len=1) :: char
470
471IF (PRESENT(form)) THEN
472 WRITE(char,form) in
473ELSE
474 WRITE(char,'(L1)') in
475ENDIF
476
477END FUNCTION logical_to_char
478
479
480ELEMENTAL FUNCTION trim_logical_to_char(in) RESULT(char)
481LOGICAL,INTENT(in) :: in ! value to be represented as CHARACTER
482
483CHARACTER(len=1) :: char
484
485WRITE(char,'(L1)') in
486
487END FUNCTION trim_logical_to_char
488
489
490!> Convert a character string to an integer value if possible.
491!! It is \a ELEMENTAL so it works with arrays of any shape. It returns
492!! missing value if the input cannot be converted or is empty or
493!! missing.
494ELEMENTAL FUNCTION c2i(string) RESULT(num)
495CHARACTER(len=*),INTENT(in) :: string !< string to be represented as \a INTEGER
496INTEGER :: num
497
498INTEGER :: lier
499
500IF (.NOT.c_e(string)) THEN
501 num = imiss
502ELSE IF (len_trim(string) == 0) THEN
503 num = imiss
504ELSE
505 READ(string, '(I32)', iostat=lier)num
506 IF (lier /= 0) THEN
507 num = imiss
508 ENDIF
509ENDIF
510
511END FUNCTION c2i
512
513
514!> Convert a character string to a real value if possible.
515!! It is \a ELEMENTAL so it works with arrays of any shape. It returns
516!! missing value if the input cannot be converted or is empty or
517!! missing.
518ELEMENTAL FUNCTION c2r(string) RESULT(num)
519CHARACTER(len=*),INTENT(in) :: string !< string to be represented as \a REAL
520REAL :: num
521
522INTEGER :: lier
523
524IF (.NOT.c_e(string)) THEN
525 num = rmiss
526ELSE IF (len_trim(string) == 0) THEN
527 num = rmiss
528ELSE
529 READ(string, '(F32.0)', iostat=lier)num
530 IF (lier /= 0) THEN
531 num = rmiss
532 ENDIF
533ENDIF
534
535END FUNCTION c2r
536
537
538!> Convert a character string to a double value if possible.
539!! It is \a ELEMENTAL so it works with arrays of any shape. It returns
540!! missing value if the input cannot be converted or is empty or
541!! missing.
542ELEMENTAL FUNCTION c2d(string) RESULT(num)
543CHARACTER(len=*),INTENT(in) :: string !< string to be represented as \a DOUBLE \a PRECISION
544DOUBLE PRECISION :: num
545
546INTEGER :: lier
547
548IF (.NOT.c_e(string)) THEN
549 num = rmiss
550ELSE IF (len_trim(string) == 0) THEN
551 num = rmiss
552ELSE
553 READ(string, '(F32.0)', iostat=lier)num
554 IF (lier /= 0) THEN
555 num = rmiss
556 ENDIF
557ENDIF
558
559END FUNCTION c2d
560
561
562!> Converts a \a CHARACTER variable into a string which can be
563!! directly passed to a C function requiring a null-terminated \a
564!! const \a char* (input) argument. If the result is going to be
565!! stored into an array, this has to be dimensioned with a suitable
566!! size (\a LEN(fchar) \a + \a 1 ).
567FUNCTION fchar_to_cstr(fchar) RESULT(cstr)
568CHARACTER(len=*), INTENT(in) :: fchar !< variable to be converted
569INTEGER(kind=int_b) :: cstr(len(fchar)+1)
570
571cstr(1:len(fchar)) = transfer(fchar, cstr, len(fchar))
572cstr(len(fchar)+1) = 0 ! zero-terminate
573
574END FUNCTION fchar_to_cstr
575
576
577!> Converts a \a CHARACTER variable into a string which can be
578!! directly passed to a C function requiring a null-terminated \a
579!! char* (input/output) argument. The result is stored into \a pcstr
580!! which is allocated within the subroutine and has to be deallocated
581!! by the calling procedure.
582SUBROUTINE fchar_to_cstr_alloc(fchar, pcstr)
583CHARACTER(len=*), INTENT(in) :: fchar !< variable to be converted
584INTEGER(kind=int_b), POINTER :: pcstr(:) !< pointer to a 1-d byte array which will be allocated and, on output, will contain the null-terminated string
585
586ALLOCATE(pcstr(len(fchar)+1))
587pcstr(1:len(fchar)) = transfer(fchar, pcstr, len(fchar))
588pcstr(len(fchar)+1) = 0 ! zero-terminate
589
590END SUBROUTINE fchar_to_cstr_alloc
591
592
593!> Converts a null-terminated C-style string into a Fortran \a CHARACTER
594!! variable of the same length, the null termination character is
595!! removed.
596FUNCTION cstr_to_fchar(cstr) RESULT(fchar)
597INTEGER(kind=int_b), INTENT(in) :: cstr(:) !< variable to be converted
598CHARACTER(len=SIZE(cstr)-1) :: fchar
599
600INTEGER :: i
601
602!l = MIN(LEN(char), SIZE(cstr)-1)
603fchar = transfer(cstr(1:SIZE(cstr)-1), fchar)
604DO i = 1, SIZE(cstr)-1
605 IF (fchar(i:i) == char(0)) THEN ! truncate if the null terminator is found before
606 fchar(i:) = ' '
607 EXIT
608 ENDIF
609ENDDO
610
611END FUNCTION cstr_to_fchar
612
613
614!> Convert a \a CHARACTER variable to uppercase.
615FUNCTION uppercase ( Input_String ) RESULT ( Output_String )
616CHARACTER( * ), INTENT( IN ) :: input_string !< variable to be converted
617CHARACTER( LEN( Input_String ) ) :: output_string
618 ! -- Local variables
619INTEGER :: i, n
620
621 ! -- Copy input string
622output_string = input_string
623 ! -- Loop over string elements
624DO i = 1, len( output_string )
625 ! -- Find location of letter in lower case constant string
626 n = index( lower_case, output_string( i:i ) )
627 ! -- If current substring is a lower case letter, make it upper case
628 IF ( n /= 0 ) output_string( i:i ) = upper_case( n:n )
629END DO
630END FUNCTION uppercase
631
632
633!> Convert a \a CHARACTER variable to lowercase.
634FUNCTION lowercase ( Input_String ) RESULT ( Output_String )
635 ! -- Argument and result
636CHARACTER( * ), INTENT( IN ) :: input_string !< variable to be converted
637CHARACTER( LEN( Input_String ) ) :: output_string
638 ! -- Local variables
639INTEGER :: i, n
640
641 ! -- Copy input string
642output_string = input_string
643 ! -- Loop over string elements
644DO i = 1, len( output_string )
645 ! -- Find location of letter in upper case constant string
646 n = index( upper_case, output_string( i:i ) )
647 ! -- If current substring is an upper case letter, make it lower case
648 IF ( n /= 0 ) output_string( i:i ) = lower_case( n:n )
649END DO
650END FUNCTION lowercase
651
652
653!> Returns \a input_string centered, i.e.\ with an equal number of
654!! leading and trailing blanks (±1 if they are odd). The needed
655!! number of leading/trailing blanks is added or removed at the
656!! beginning and/or at the end in order to keep the length of the
657!! resulting string equal to the input length.
658ELEMENTAL FUNCTION align_center(input_string) RESULT(aligned)
659CHARACTER(len=*), INTENT(in) :: input_string !< string to be aligned
660
661CHARACTER(len=LEN(input_string)) :: aligned
662
663INTEGER :: n1, n2
664
665n1 = f_nblnk(input_string)
666n2 = len(input_string)-l_nblnk(input_string)+1
667
668aligned = ''
669aligned((n1+n2)/2:) = input_string(n1:)
670
671END FUNCTION align_center
672
673
674!> Return the index of last character in \a input_string which is not
675!! a blank space. If the string is zero-length or contains only blank
676!! spaces, zero is returned. It is named l_nblnk and not lnblnk in
677!! order to avoid conflict with a nondefault intrinsic Fortran
678!! function with the same name, available on some compilers.
679ELEMENTAL FUNCTION l_nblnk(input_string, blnk) RESULT(nblnk)
680CHARACTER(len=*), INTENT(in) :: input_string !< string to be scanned
681CHARACTER(len=1), INTENT(in), OPTIONAL :: blnk !< optional blank character, if not provided, a blank space is assumed
683CHARACTER(len=1) :: lblnk
684INTEGER :: nblnk
685
686IF (PRESENT(blnk)) THEN
687 lblnk = blnk
688ELSE
689 lblnk = ' '
690ENDIF
691
692DO nblnk = len(input_string), 1, -1
693 IF (input_string(nblnk:nblnk) /= lblnk) RETURN
694ENDDO
695
696END FUNCTION l_nblnk
697
698
699!> Return the index of first character in \a input_string which is not
700!! a blank space. If the string is zero-length or contains only blank
701!! spaces, \a LEN(input_string)+1 is returned.
702ELEMENTAL FUNCTION f_nblnk(input_string, blnk) RESULT(nblnk)
703CHARACTER(len=*), INTENT(in) :: input_string !< string to be scanned
704CHARACTER(len=1), INTENT(in), OPTIONAL :: blnk !< optional blank character, if not provided, a blank space is assumed
705
706CHARACTER(len=1) :: lblnk
707INTEGER :: nblnk
708
709IF (PRESENT(blnk)) THEN
710 lblnk = blnk
711ELSE
712 lblnk = ' '
713ENDIF
714
715DO nblnk = 1, len(input_string)
716 IF (input_string(nblnk:nblnk) /= lblnk) RETURN
717ENDDO
718
719END FUNCTION f_nblnk
720
721
722!> Split a line into words at a predefined character (default blank).
723!! Returns the number of words in \a input_string. If pointers \a
724!! word_start and \a word_end are provided, they are allocated with \a
725!! nword elements and set to the indices of initial and final
726!! character of every word in \a input_string. Groups of contiguous
727!! separation characters are treated as a single separator character.
728FUNCTION word_split(input_string, word_start, word_end, sep) RESULT(nword)
729CHARACTER(len=*), INTENT(in) :: input_string !< string to be scanned
730INTEGER, POINTER, OPTIONAL :: word_start(:) !< indices of first character of each word in \a input_string, allocated here, must be deallocated by the user
731INTEGER, POINTER, OPTIONAL :: word_end(:) !< indices of last character of each word in \a input_string, allocated here, must be deallocated by the user
732CHARACTER(len=1), OPTIONAL :: sep !< optional word separator character, if not provided, a blank space is assumed
733
734INTEGER :: nword
735
736INTEGER :: ls, le
737INTEGER, POINTER :: lsv(:), lev(:)
738CHARACTER(len=1) :: lsep
739
740IF (PRESENT(sep)) THEN
741 lsep = sep
742ELSE
743 lsep = ' '
744ENDIF
745
746nword = 0
747le = 0
748DO WHILE(.true.)
749 ls = f_nblnk(input_string(le+1:), lsep) + le ! search next nonblank
750 IF (ls > len(input_string)) EXIT ! end of words
751 le = index(input_string(ls:), lsep)
752 IF (le == 0) THEN
753 le = len(input_string)
754 ELSE
755 le = le + ls - 2
756 ENDIF
757 nword = nword + 1
758ENDDO
759
760IF (.NOT.PRESENT(word_start) .AND. .NOT.PRESENT(word_end)) RETURN
761
762ALLOCATE(lsv(nword), lev(nword))
763nword = 0
764le = 0
765DO WHILE(.true.)
766 ls = f_nblnk(input_string(le+1:), lsep) + le ! search next nonblank
767 IF (ls > len(input_string)) EXIT ! end of words
768 le = index(input_string(ls:), lsep)
769 IF (le == 0) THEN
770 le = len(input_string)
771 ELSE
772 le = le + ls - 2
773 ENDIF
774 nword = nword + 1
775 lsv(nword) = ls
776 lev(nword) = le
777ENDDO
778
779IF (PRESENT(word_start)) THEN
780 word_start => lsv
781ELSE
782 DEALLOCATE(lsv)
783ENDIF
784IF (PRESENT(word_end)) THEN
785 word_end => lev
786ELSE
787 DEALLOCATE(lev)
788ENDIF
789
790END FUNCTION word_split
791
792
793!> Constructor for the \a line_split class. It creates a new object
794!! allowing to split a line of text into multiple lines of predefined
795!! length at blank spaces. If a line can't be splitted because a word
796!! is longer than the line, it is truncated.
797FUNCTION line_split_new(line, ncols) RESULT(this)
798CHARACTER(len=*), INTENT(in) :: line !< line to be splitted
799INTEGER, INTENT(in), OPTIONAL :: ncols !< maximum number of columns on every line, if not provided a suitable default is used
800
801TYPE(line_split) :: this
802
803INTEGER :: nw, nwords, nlines, columns_in_line, words_in_line, ncols_next_word
804
805IF (PRESENT(ncols)) THEN
806 this%ncols = ncols
807ELSE
808 this%ncols = default_columns()
809ENDIF
810! split the input line
811nwords = word_split(line, this%word_start, this%word_end)
812! count the lines required to accomodate the input line in a paragraph
813nlines = 0
814nw = 0
815DO WHILE(nw < nwords)
816 columns_in_line = 0
817 words_in_line = 0
818 DO WHILE(nw < nwords)
819 nw = nw + 1
820 ncols_next_word = this%word_end(nw) - this%word_start(nw) + 1
821 IF (words_in_line > 0) ncols_next_word = ncols_next_word + 1 ! previous space
822 IF (columns_in_line + ncols_next_word <= this%ncols .OR. &
823 words_in_line == 0) THEN ! accept the word
824 columns_in_line = columns_in_line + ncols_next_word
825 words_in_line = words_in_line + 1
826 ELSE ! refuse the word
827 nw = nw - 1
828 EXIT
829 ENDIF
830 ENDDO
831 nlines = nlines + 1
832ENDDO
833
834!IF (nlines == 0)
835ALLOCATE(this%paragraph(this%ncols, nlines))
836this%paragraph = ' '
837! repeat filling the paragraph
838nlines = 0
839nw = 0
840DO WHILE(nw < nwords)
841 columns_in_line = 0
842 words_in_line = 0
843 DO WHILE(nw < nwords)
844 nw = nw + 1
845 ncols_next_word = this%word_end(nw) - this%word_start(nw) + 1
846 IF (words_in_line > 0) ncols_next_word = ncols_next_word + 1 ! previous space
847 IF (columns_in_line + ncols_next_word <= this%ncols .OR. &
848 words_in_line == 0) THEN ! accept the word
849 columns_in_line = columns_in_line + ncols_next_word
850! now fill the paragraph
851 IF (columns_in_line <= this%ncols) THEN ! non truncated line
852 IF (words_in_line > 0) THEN ! previous space
853 this%paragraph(columns_in_line-ncols_next_word+1:columns_in_line,nlines+1) = &
854 transfer(' '//line(this%word_start(nw):this%word_end(nw)), this%paragraph)
855 ELSE ! no previous space
856 this%paragraph(columns_in_line-ncols_next_word+1:columns_in_line,nlines+1) = &
857 transfer(line(this%word_start(nw):this%word_end(nw)), this%paragraph)
858 ENDIF
859 ELSE ! truncated line (word longer than line)
860 this%paragraph(1:this%ncols,nlines+1) = &
861 transfer(line(this%word_start(nw):this%word_start(nw)+this%ncols-1), this%paragraph)
862 ENDIF
863 words_in_line = words_in_line + 1
864 ELSE ! refuse the word
865 nw = nw - 1
866 EXIT
867 ENDIF
868 ENDDO
869 nlines = nlines + 1
870ENDDO
871
872END FUNCTION line_split_new
873
874
875! Cleanly destroy a \a line_split object, deallocating all the
876! dynamically allocated space. Use the generic name \a delete rather
877! than this specfoc subroutine.
878SUBROUTINE line_split_delete(this)
879TYPE(line_split), INTENT(inout) :: this ! object to be destroyed
880
881IF (ASSOCIATED(this%paragraph)) DEALLOCATE(this%paragraph)
882IF (ASSOCIATED(this%word_start)) DEALLOCATE(this%word_start)
883IF (ASSOCIATED(this%word_end)) DEALLOCATE(this%word_end)
884
885END SUBROUTINE line_split_delete
886
887
888!> Return the number of lines over which the input line was splitted.
889FUNCTION line_split_get_nlines(this) RESULT(nlines)
890TYPE(line_split), INTENT(in) :: this !< object initialised with the line to be splitted
891
892INTEGER :: nlines
893
894IF (ASSOCIATED(this%paragraph)) THEN
895 nlines = SIZE(this%paragraph, 2)
896ELSE
897 nlines = 0
898ENDIF
899
900END FUNCTION line_split_get_nlines
901
902
903!> Return the \a nline-th line obtained after splitting. If \a nline
904!! is out of range, a missing value is returned. The line is always
905!! left-aligned and it is padded with trailing blanks up to the
906!! requested line length.
907FUNCTION line_split_get_line(this, nline) RESULT(line)
908TYPE(line_split), INTENT(in) :: this !< object initialised with the line to be splitted
909INTEGER, INTENT(in) :: nline !< index of the line to be returned
910
911CHARACTER(len=SIZE(this%paragraph, 1)) :: line
912IF (nline > 0 .AND. nline <= SIZE(this%paragraph, 2)) THEN
913 line = transfer(this%paragraph(:,nline), line)
914ELSE
915 line = cmiss
916ENDIF
917
918END FUNCTION line_split_get_line
919
920
921!> Return the number of columns in the terminal, if available it is
922!! taken from the \a COLUMNS environment variable (it may be necessary
923!! to execute \c export \c COLUMNS before running the program, in
924!! order for this to work), otherwise it is set to 80. A positive
925!! value is returned in any case
926FUNCTION default_columns() RESULT(cols)
927INTEGER :: cols
928
929INTEGER, PARAMETER :: defaultcols = 80 ! default of the defaults
930INTEGER, PARAMETER :: maxcols = 256 ! maximum value
931CHARACTER(len=10) :: ccols
932
933cols = defaultcols
934CALL getenv('COLUMNS', ccols)
935IF (ccols == '') RETURN
936
937READ(ccols, '(I10)', err=100) cols
938cols = min(cols, maxcols)
939IF (cols <= 0) cols = defaultcols
940RETURN
941
942100 cols = defaultcols ! error in reading the value
943
944END FUNCTION default_columns
945
946
947!> Return the suffix of a filename.
948FUNCTION suffixname ( Input_String ) RESULT ( Output_String )
949! -- Argument and result
950CHARACTER( * ), INTENT( IN ) :: input_string !< string to be interpreted as a filename
951CHARACTER( LEN( Input_String ) ) :: output_string
952! -- Local variables
953INTEGER :: i
954
955output_string=""
956i = index(input_string,".",back=.true.)
957if (i > 0 .and. i < len(input_string)) output_string= input_string(i+1:)
958
959END FUNCTION suffixname
960
961
962!> Remove the requested characters from a string.
963!! This function returns a string cleaned from unwanted characters,
964!! either by removing "bad" characters (argument \a badchar) or by
965!! keeping only "good" characters (argument \a goodchar). If neither
966!! \a badchar nor \a goodchar are provided, it keeps only alphabetic
967!! ASCII characters.
968ELEMENTAL FUNCTION wash_char(in, goodchar, badchar) RESULT(char)
969CHARACTER(len=*),INTENT(in) :: in !< string to be cleaned
970CHARACTER(len=*),INTENT(in),OPTIONAL :: badchar !< optional set of "bad" characters
971CHARACTER(len=*),INTENT(in),OPTIONAL :: goodchar !< optional set of "good" characters
972integer,allocatable :: igoodchar(:)
973integer,allocatable :: ibadchar(:)
974
975CHARACTER(len=len(in)) :: char,charr,charrr
976INTEGER :: i,ia,nchar
977
978char=""
979charr=""
980charrr=""
981
982if (present(goodchar)) then
983
984allocate(igoodchar(len(goodchar)))
986 do i =1, len(goodchar)
987 igoodchar=ichar(goodchar(i:i))
988 end do
989
990 nchar=0
991 do i=1,len(in)
992 ia = ichar(in(i:i))
993 if (any(ia == igoodchar))then
994 nchar=nchar+1
995 charrr(nchar:nchar)=achar(ia)
996 end if
997 end do
998
999deallocate(igoodchar)
1000
1001else
1002
1003 charrr=in
1004
1005end if
1006
1007
1008
1009if (present(badchar)) then
1010
1011allocate(ibadchar(len(badchar)))
1012
1013 do i =1, len(badchar)
1014 ibadchar=ichar(badchar(i:i))
1015 end do
1016
1017 nchar=0
1018 do i=1,len(charrr)
1019 ia = ichar(charrr(i:i))
1020 if (.not. any(ia == ibadchar))then
1021 nchar=nchar+1
1022 charr(nchar:nchar)=achar(ia)
1023 end if
1024 end do
1025
1026deallocate(ibadchar)
1027
1028else
1029
1030 charr=charrr
1031
1032end if
1033
1034
1035if (.not. present(goodchar) .and. .not. present(badchar)) then
1036
1037 nchar=0
1038 do i=1,len(charr)
1039 ia = ichar(charr(i:i))
1040 if ((ia >= 65 .and. ia <= 90) .or. &
1041 (ia >= 97 .and. ia <= 122))then
1042 nchar=nchar+1
1043 char(nchar:nchar)=achar(ia)
1044 end if
1045 end do
1046
1047else
1048
1049 char=charr
1050
1051end if
1052
1053
1054END FUNCTION wash_char
1055
1056
1057! derived by http://sourceforge.net/projects/flibs
1058!
1059! globmatch.f90 --
1060! Match strings according to (simplified) glob patterns
1061!
1062! The pattern matching is limited to literals, * and ?
1063! (character classes are not supported). A backslash escapes
1064! any character.
1065!
1066! $Id: globmatch.f90,v 1.5 2006/03/26 19:03:53 arjenmarkus Exp $
1067!!$Copyright (c) 2008, Arjen Markus
1068!!$
1069!!$All rights reserved.
1070!!$
1071!!$Redistribution and use in source and binary forms, with or without modification,
1072!!$are permitted provided that the following conditions are met:
1073!!$
1074!!$Redistributions of source code must retain the above copyright notice,
1075!!$this list of conditions and the following disclaimer.
1076!!$Redistributions in binary form must reproduce the above copyright notice,
1077!!$this list of conditions and the following disclaimer in the documentation
1078!!$and/or other materials provided with the distribution.
1079!!$Neither the name of the author nor the names of the contributors
1080!!$may be used to endorse or promote products derived from this software
1081!!$without specific prior written permission.
1082!!$THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1083!!$"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1084!!$THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1085!!$ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
1086!!$FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1087!!$DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1088!!$SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1089!!$CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
1090!!$OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1091!!$OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1092!
1093
1094!> Tries to match the given string with the pattern (array version).
1095!! Returns \a .TRUE. if the entire string matches the pattern, \a
1096!! .FALSE. otherwise. Note: trailing blanks are ignored.
1097function string_match_v( string, pattern ) result(match)
1098character(len=*), intent(in) :: string(:) !< string to be examined
1099character(len=*), intent(in) :: pattern !< glob pattern to be used for the matching
1100logical :: match(size(string))
1101
1102integer :: i
1103
1104do i =1,size(string)
1105 match(i)=string_match(string(i),pattern)
1106end do
1107
1108end function string_match_v
1109
1110
1111!> Tries to match the given string with the pattern.
1112!! Returns \a .TRUE. if the entire string matches the pattern, \a
1113!! .FALSE. otherwise. Note: trailing blanks are ignored.
1114recursive function string_match( string, pattern ) result(match)
1115 character(len=*), intent(in) :: string !< String to be examined
1116 character(len=*), intent(in) :: pattern !< Glob pattern to be used for the matching
1117 logical :: match
1118
1119! '\\' without -fbackslash generates a warning on gfortran, '\'
1120! crashes doxygen, so we choose '\\' and -fbackslash in configure.ac
1121 character(len=1), parameter :: backslash = '\\'
1122 character(len=1), parameter :: star = '*'
1123 character(len=1), parameter :: question = '?'
1124
1125 character(len=len(pattern)) :: literal
1126 integer :: ptrim
1127 integer :: p
1128 integer :: k
1129 integer :: ll
1130 integer :: method
1131 integer :: start
1132 integer :: strim
1133
1134 match = .false.
1135 method = 0
1136 ptrim = len_trim( pattern )
1137 strim = len_trim( string )
1138 p = 1
1139 ll = 0
1140 start = 1
1141
1142 !
1143 ! Split off a piece of the pattern
1144 !
1145 do while ( p <= ptrim )
1146 select case ( pattern(p:p) )
1147 case( star )
1148 if ( ll .ne. 0 ) exit
1149 method = 1
1150 case( question )
1151 if ( ll .ne. 0 ) exit
1152 method = 2
1153 start = start + 1
1154 case( backslash )
1155 p = p + 1
1156 ll = ll + 1
1157 literal(ll:ll) = pattern(p:p)
1158 case default
1159 ll = ll + 1
1160 literal(ll:ll) = pattern(p:p)
1161 end select
1162
1163 p = p + 1
1164 enddo
1165
1166 !
1167 ! Now look for the literal string (if any!)
1168 !
1169 if ( method == 0 ) then
1170 !
1171 ! We are at the end of the pattern, and of the string?
1172 !
1173 if ( strim == 0 .and. ptrim == 0 ) then
1174 match = .true.
1175 else
1176 !
1177 ! The string matches a literal part?
1178 !
1179 if ( ll > 0 ) then
1180 if ( string(start:min(strim,start+ll-1)) == literal(1:ll) ) then
1181 start = start + ll
1182 match = string_match( string(start:), pattern(p:) )
1183 endif
1184 endif
1185 endif
1186 endif
1187
1188 if ( method == 1 ) then
1189 !
1190 ! Scan the whole of the remaining string ...
1191 !
1192 if ( ll == 0 ) then
1193 match = .true.
1194 else
1195 do while ( start <= strim )
1196 k = index( string(start:), literal(1:ll) )
1197 if ( k > 0 ) then
1198 start = start + k + ll - 1
1199 match = string_match( string(start:), pattern(p:) )
1200 if ( match ) then
1201 exit
1202 endif
1203 endif
1204
1205 start = start + 1
1206 enddo
1207 endif
1208 endif
1209
1210 if ( method == 2 .and. ll > 0 ) then
1211 !
1212 ! Scan the whole of the remaining string ...
1213 !
1214 if ( string(start:min(strim,start+ll-1)) == literal(1:ll) ) then
1215 match = string_match( string(start+ll:), pattern(p:) )
1216 endif
1217 endif
1218 return
1219end function string_match
1220
1221
1222SUBROUTINE print_status_line(line)
1223CHARACTER(len=*),INTENT(in) :: line
1224CHARACTER(len=1),PARAMETER :: cr=char(13)
1225WRITE(stdout_unit,'(2A)',advance='no')cr,trim(line)
1226FLUSH(unit=6) ! probably useless with gfortran, required with Intel fortran
1227END SUBROUTINE print_status_line
1228
1229SUBROUTINE done_status_line()
1230WRITE(stdout_unit,'()')
1231END SUBROUTINE done_status_line
1232
1233
1234!> Update a progress line with a new value.
1235!! This subroutine updates the progress line object with a new double
1236!! precision value \a val. Values outside the range \a this%min, \a
1237!! this%max are truncated. If \a val is equal or greter maximum the
1238!! progress bar is closed so that a new line can be printed. When a
1239!! progress_line object reaches its maximum it can no more be updated
1240!! and/or closed. Use the interface method \a update rather than this
1241!! subroutine directly.
1242SUBROUTINE progress_line_update_d(this, val)
1243CLASS(progress_line),INTENT(inout) :: this !< progress_line object to be updated
1244DOUBLE PRECISION,INTENT(in) :: val !< new value
1245
1246INTEGER :: vint, i
1247CHARACTER(len=512) :: line
1248
1249IF (this%curr >= this%max) RETURN ! line is already closed, do nothing
1250
1251this%curr = max(this%min, min(this%max, val))
1252this%spin = mod(this%spin+1, 4)
1253line = ''
1254
1255vint = nint((this%curr-this%min)/(this%max-this%min)*100.d0)
1256WRITE(line,this%form)vint, &
1257 progress_line_spin(this%spin+1:this%spin+1)
1258vint = vint/10
1259
1260DO i = 1, vint
1261 line(this%barloc+i:this%barloc+i) = this%done
1262ENDDO
1263DO i = vint+1, 10
1264 line(this%barloc+i:this%barloc+i) = this%todo
1265ENDDO
1266CALL print_status_line(line)
1267IF (this%curr >= this%max) CALL done_status_line()
1268
1269END SUBROUTINE progress_line_update_d
1270
1271
1272!> Update a progress line with a new value.
1273!! This subroutine is equivalent to \a progress_line_update_d but it
1274!! accepts an inteer value \a val. Use the interface method \a update
1275!! rather than this subroutine directly.
1276SUBROUTINE progress_line_update_i(this, val)
1277CLASS(progress_line),INTENT(inout) :: this !< progress_line object to be updated
1278INTEGER,INTENT(in) :: val !< new value
1279
1280CALL progress_line_update_d(this, dble(val))
1281
1282END SUBROUTINE progress_line_update_i
1283
1284!> Close artificially the progress_line object.
1285!! This subroutine forces the progress_line object to be closed
1286!! regardless of the value reached by the progress counter. It does
1287!! not need to be called if the \a update method has already been
1288!! called with the maximum progress value.
1289SUBROUTINE progress_line_alldone(this)
1290CLASS(progress_line),INTENT(inout) :: this
1291CALL progress_line_update_d(this, this%max)
1292END SUBROUTINE progress_line_alldone
1293
1294
1295END MODULE char_utilities
Destructor for the line_split class.
Tries to match the given string with the pattern Result: .true.
Set of functions that return a trimmed CHARACTER representation of the input variable.
Set of functions that return a CHARACTER representation of the input variable.
Index method.
Function to check whether a value is missing or not.
Utilities for CHARACTER variables.
Definition of constants to be used for declaring variables of a desired type.
Definition kinds.F90:245
Definitions of constants and functions for working with missing values.
Class that allows splitting a long line into shorter lines of equal length at the occurrence of a spe...
Class to print a progress bar on the screen.

Generated with Doxygen.