LCOV - code coverage report
Current view: top level - src/input - input_keyword_types.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 45.8 % 382 175
Test Date: 2025-12-04 06:27:48 Functions: 50.0 % 10 5

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief represents keywords in an input
      10              : !> \par History
      11              : !>      06.2004 created, based on Joost cp_keywords proposal [fawzi]
      12              : !> \author fawzi
      13              : ! **************************************************************************************************
      14              : MODULE input_keyword_types
      15              :    USE cp_units,                        ONLY: cp_unit_create,&
      16              :                                               cp_unit_desc,&
      17              :                                               cp_unit_desc_length,&
      18              :                                               cp_unit_release,&
      19              :                                               cp_unit_type
      20              :    USE input_enumeration_types,         ONLY: enum_create,&
      21              :                                               enum_release,&
      22              :                                               enum_retain,&
      23              :                                               enumeration_type
      24              :    USE input_val_types,                 ONLY: &
      25              :         char_t, enum_t, integer_t, lchar_t, logical_t, no_t, real_t, val_create, val_release, &
      26              :         val_retain, val_type, val_write, val_write_internal
      27              :    USE kinds,                           ONLY: default_string_length,&
      28              :                                               dp
      29              :    USE print_messages,                  ONLY: print_message
      30              :    USE reference_manager,               ONLY: get_citation_key
      31              :    USE string_utilities,                ONLY: a2s,&
      32              :                                               compress,&
      33              :                                               substitute_special_xml_tokens,&
      34              :                                               typo_match,&
      35              :                                               uppercase
      36              : #include "../base/base_uses.f90"
      37              : 
      38              :    IMPLICIT NONE
      39              :    PRIVATE
      40              : 
      41              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      42              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'input_keyword_types'
      43              : 
      44              :    INTEGER, PARAMETER, PUBLIC :: usage_string_length = default_string_length*2
      45              : 
      46              :    PUBLIC :: keyword_p_type, keyword_type, keyword_create, keyword_retain, &
      47              :              keyword_release, keyword_get, keyword_describe, &
      48              :              write_keyword_xml, keyword_typo_match
      49              : 
      50              : ! **************************************************************************************************
      51              : !> \brief represent a pointer to a keyword (to make arrays of pointers)
      52              : !> \param keyword the pointer to the keyword
      53              : !> \author fawzi
      54              : ! **************************************************************************************************
      55              :    TYPE keyword_p_type
      56              :       TYPE(keyword_type), POINTER :: keyword => NULL()
      57              :    END TYPE keyword_p_type
      58              : 
      59              : ! **************************************************************************************************
      60              : !> \brief represent a keyword in the input
      61              : !> \param names the names of the current keyword (at least one should be
      62              : !>        present) for example "MAXSCF"
      63              : !> \param location is where in the source code (file and line) the keyword is created
      64              : !> \param usage how to use it "MAXSCF 10"
      65              : !> \param description what does it do: "MAXSCF : determines the maximum
      66              : !>        number of steps in an SCF run"
      67              : !> \param deprecation_notice show this warning that the keyword is deprecated
      68              : !> \param citations references to literature associated with this keyword
      69              : !> \param type_of_var the type of keyword (controls how it is parsed)
      70              : !>        it can be one of: no_parse_t,logical_t, integer_t, real_t,
      71              : !>        char_t
      72              : !> \param n_var number of values that should be parsed (-1=unknown)
      73              : !> \param repeats if the keyword can be present more than once in the
      74              : !>        section
      75              : !> \param removed to trigger a CPABORT when encountered while parsing the input
      76              : !> \param enum enumeration that defines the mapping between integers and
      77              : !>        strings
      78              : !> \param unit the default unit this keyword is read in (to automatically
      79              : !>        convert to the internal cp2k units during parsing)
      80              : !> \param default_value the default value for the keyword
      81              : !> \param lone_keyword_value value to be used in presence of the keyword
      82              : !>        without any parameter
      83              : !> \note
      84              : !>      I have expressely avoided a format string for the type of keywords:
      85              : !>      they should easily map to basic types of fortran, if you need more
      86              : !>      information use a subsection. [fawzi]
      87              : !> \author Joost & fawzi
      88              : ! **************************************************************************************************
      89              :    TYPE keyword_type
      90              :       INTEGER :: ref_count = 0
      91              :       CHARACTER(LEN=default_string_length), DIMENSION(:), POINTER :: names => NULL()
      92              :       CHARACTER(LEN=usage_string_length) :: location = ""
      93              :       CHARACTER(LEN=usage_string_length) :: usage = ""
      94              :       CHARACTER, DIMENSION(:), POINTER :: description => null()
      95              :       CHARACTER(LEN=:), ALLOCATABLE :: deprecation_notice
      96              :       INTEGER, POINTER, DIMENSION(:) :: citations => NULL()
      97              :       INTEGER :: type_of_var = 0, n_var = 0
      98              :       LOGICAL :: repeats = .FALSE., removed = .FALSE.
      99              :       TYPE(enumeration_type), POINTER :: enum => NULL()
     100              :       TYPE(cp_unit_type), POINTER :: unit => NULL()
     101              :       TYPE(val_type), POINTER :: default_value => NULL()
     102              :       TYPE(val_type), POINTER :: lone_keyword_value => NULL()
     103              :    END TYPE keyword_type
     104              : 
     105              : CONTAINS
     106              : 
     107              : ! **************************************************************************************************
     108              : !> \brief creates a keyword object
     109              : !> \param keyword the keyword object to be created
     110              : !> \param location from where in the source code keyword_create() is called
     111              : !> \param name the name of the keyword
     112              : !> \param description ...
     113              : !> \param usage ...
     114              : !> \param type_of_var ...
     115              : !> \param n_var ...
     116              : !> \param repeats ...
     117              : !> \param variants ...
     118              : !> \param default_val ...
     119              : !> \param default_l_val ...
     120              : !> \param default_r_val ...
     121              : !> \param default_lc_val ...
     122              : !> \param default_c_val ...
     123              : !> \param default_i_val ...
     124              : !> \param default_l_vals ...
     125              : !> \param default_r_vals ...
     126              : !> \param default_c_vals ...
     127              : !> \param default_i_vals ...
     128              : !> \param lone_keyword_val ...
     129              : !> \param lone_keyword_l_val ...
     130              : !> \param lone_keyword_r_val ...
     131              : !> \param lone_keyword_c_val ...
     132              : !> \param lone_keyword_i_val ...
     133              : !> \param lone_keyword_l_vals ...
     134              : !> \param lone_keyword_r_vals ...
     135              : !> \param lone_keyword_c_vals ...
     136              : !> \param lone_keyword_i_vals ...
     137              : !> \param enum_c_vals ...
     138              : !> \param enum_i_vals ...
     139              : !> \param enum ...
     140              : !> \param enum_strict ...
     141              : !> \param enum_desc ...
     142              : !> \param unit_str ...
     143              : !> \param citations ...
     144              : !> \param deprecation_notice ...
     145              : !> \param removed ...
     146              : !> \author fawzi
     147              : ! **************************************************************************************************
     148    706880064 :    SUBROUTINE keyword_create(keyword, location, name, description, usage, type_of_var, &
     149     11572124 :                              n_var, repeats, variants, default_val, &
     150              :                              default_l_val, default_r_val, default_lc_val, default_c_val, default_i_val, &
     151    706880064 :                              default_l_vals, default_r_vals, default_c_vals, default_i_vals, &
     152              :                              lone_keyword_val, lone_keyword_l_val, lone_keyword_r_val, lone_keyword_c_val, &
     153   1413760128 :                              lone_keyword_i_val, lone_keyword_l_vals, lone_keyword_r_vals, &
     154   2120640192 :                              lone_keyword_c_vals, lone_keyword_i_vals, enum_c_vals, enum_i_vals, &
     155   1413760128 :                              enum, enum_strict, enum_desc, unit_str, citations, deprecation_notice, removed)
     156              :       TYPE(keyword_type), POINTER                        :: keyword
     157              :       CHARACTER(len=*), INTENT(in)                       :: location, name, description
     158              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: usage
     159              :       INTEGER, INTENT(in), OPTIONAL                      :: type_of_var, n_var
     160              :       LOGICAL, INTENT(in), OPTIONAL                      :: repeats
     161              :       CHARACTER(len=*), DIMENSION(:), INTENT(in), &
     162              :          OPTIONAL                                        :: variants
     163              :       TYPE(val_type), OPTIONAL, POINTER                  :: default_val
     164              :       LOGICAL, INTENT(in), OPTIONAL                      :: default_l_val
     165              :       REAL(KIND=DP), INTENT(in), OPTIONAL                :: default_r_val
     166              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: default_lc_val, default_c_val
     167              :       INTEGER, INTENT(in), OPTIONAL                      :: default_i_val
     168              :       LOGICAL, DIMENSION(:), INTENT(in), OPTIONAL        :: default_l_vals
     169              :       REAL(KIND=DP), DIMENSION(:), INTENT(in), OPTIONAL  :: default_r_vals
     170              :       CHARACTER(len=*), DIMENSION(:), INTENT(in), &
     171              :          OPTIONAL                                        :: default_c_vals
     172              :       INTEGER, DIMENSION(:), INTENT(in), OPTIONAL        :: default_i_vals
     173              :       TYPE(val_type), OPTIONAL, POINTER                  :: lone_keyword_val
     174              :       LOGICAL, INTENT(in), OPTIONAL                      :: lone_keyword_l_val
     175              :       REAL(KIND=DP), INTENT(in), OPTIONAL                :: lone_keyword_r_val
     176              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: lone_keyword_c_val
     177              :       INTEGER, INTENT(in), OPTIONAL                      :: lone_keyword_i_val
     178              :       LOGICAL, DIMENSION(:), INTENT(in), OPTIONAL        :: lone_keyword_l_vals
     179              :       REAL(KIND=DP), DIMENSION(:), INTENT(in), OPTIONAL  :: lone_keyword_r_vals
     180              :       CHARACTER(len=*), DIMENSION(:), INTENT(in), &
     181              :          OPTIONAL                                        :: lone_keyword_c_vals
     182              :       INTEGER, DIMENSION(:), INTENT(in), OPTIONAL        :: lone_keyword_i_vals
     183              :       CHARACTER(len=*), DIMENSION(:), INTENT(in), &
     184              :          OPTIONAL                                        :: enum_c_vals
     185              :       INTEGER, DIMENSION(:), INTENT(in), OPTIONAL        :: enum_i_vals
     186              :       TYPE(enumeration_type), OPTIONAL, POINTER          :: enum
     187              :       LOGICAL, INTENT(in), OPTIONAL                      :: enum_strict
     188              :       CHARACTER(len=*), DIMENSION(:), INTENT(in), &
     189              :          OPTIONAL                                        :: enum_desc
     190              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: unit_str
     191              :       INTEGER, DIMENSION(:), INTENT(in), OPTIONAL        :: citations
     192              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: deprecation_notice
     193              :       LOGICAL, INTENT(in), OPTIONAL                      :: removed
     194              : 
     195              :       CHARACTER(LEN=default_string_length)               :: tmp_string
     196              :       INTEGER                                            :: i, n
     197              :       LOGICAL                                            :: check
     198              : 
     199    706880064 :       CPASSERT(.NOT. ASSOCIATED(keyword))
     200    706880064 :       ALLOCATE (keyword)
     201    706880064 :       keyword%ref_count = 1
     202              :       NULLIFY (keyword%unit)
     203    706880064 :       keyword%location = location
     204    706880064 :       keyword%removed = .FALSE.
     205              : 
     206    706880064 :       CPASSERT(LEN_TRIM(name) > 0)
     207              : 
     208    706880064 :       IF (PRESENT(variants)) THEN
     209     34716372 :          ALLOCATE (keyword%names(SIZE(variants) + 1))
     210     11572124 :          keyword%names(1) = name
     211     27039832 :          DO i = 1, SIZE(variants)
     212     15467708 :             CPASSERT(LEN_TRIM(variants(i)) > 0)
     213     27039832 :             keyword%names(i + 1) = variants(i)
     214              :          END DO
     215              :       ELSE
     216    695307940 :          ALLOCATE (keyword%names(1))
     217    695307940 :          keyword%names(1) = name
     218              :       END IF
     219   1429227836 :       DO i = 1, SIZE(keyword%names)
     220   1429227836 :          CALL uppercase(keyword%names(i))
     221              :       END DO
     222              : 
     223    706880064 :       IF (PRESENT(usage)) THEN
     224    233345825 :          CPASSERT(LEN_TRIM(usage) <= LEN(keyword%usage))
     225    233345825 :          keyword%usage = usage
     226              :          ! Check that the usage string starts with one of the keyword names.
     227    233345825 :          IF (keyword%names(1) /= "_SECTION_PARAMETERS_" .AND. keyword%names(1) /= "_DEFAULT_KEYWORD_") THEN
     228    223054244 :             tmp_string = usage
     229    223054244 :             CALL uppercase(tmp_string)
     230    223054244 :             check = .FALSE.
     231    457301571 :             DO i = 1, SIZE(keyword%names)
     232    458315239 :                check = check .OR. (INDEX(tmp_string, TRIM(keyword%names(i))) == 1)
     233              :             END DO
     234    223054244 :             IF (.NOT. check) THEN
     235            0 :                CPABORT("Usage string must start with one of the keyword name.")
     236              :             END IF
     237              :          END IF
     238              :       ELSE
     239    473534239 :          keyword%usage = ""
     240              :       END IF
     241              : 
     242    706880064 :       n = LEN_TRIM(description)
     243   2120298424 :       ALLOCATE (keyword%description(n))
     244  33656585023 :       DO i = 1, n
     245  33656585023 :          keyword%description(i) = description(i:i)
     246              :       END DO
     247              : 
     248    706880064 :       IF (PRESENT(citations)) THEN
     249      3207300 :          ALLOCATE (keyword%citations(SIZE(citations, 1)))
     250      3078891 :          keyword%citations = citations
     251              :       ELSE
     252    705810964 :          NULLIFY (keyword%citations)
     253              :       END IF
     254              : 
     255    706880064 :       keyword%repeats = .FALSE.
     256    706880064 :       IF (PRESENT(repeats)) keyword%repeats = repeats
     257              : 
     258    706880064 :       NULLIFY (keyword%enum)
     259    706880064 :       IF (PRESENT(enum)) THEN
     260            0 :          keyword%enum => enum
     261            0 :          IF (ASSOCIATED(enum)) CALL enum_retain(enum)
     262              :       END IF
     263    706880064 :       IF (PRESENT(enum_i_vals)) THEN
     264     24296493 :          CPASSERT(PRESENT(enum_c_vals))
     265     24296493 :          CPASSERT(.NOT. ASSOCIATED(keyword%enum))
     266              :          CALL enum_create(keyword%enum, c_vals=enum_c_vals, i_vals=enum_i_vals, &
     267     33265503 :                           desc=enum_desc, strict=enum_strict)
     268              :       ELSE
     269    682583571 :          CPASSERT(.NOT. PRESENT(enum_c_vals))
     270              :       END IF
     271              : 
     272    706880064 :       NULLIFY (keyword%default_value, keyword%lone_keyword_value)
     273    706880064 :       IF (PRESENT(default_val)) THEN
     274              :          IF (PRESENT(default_l_val) .OR. PRESENT(default_l_vals) .OR. &
     275              :              PRESENT(default_i_val) .OR. PRESENT(default_i_vals) .OR. &
     276              :              PRESENT(default_r_val) .OR. PRESENT(default_r_vals) .OR. &
     277            0 :              PRESENT(default_c_val) .OR. PRESENT(default_c_vals)) &
     278            0 :             CPABORT("you should pass either default_val or a default value, not both")
     279            0 :          keyword%default_value => default_val
     280            0 :          IF (ASSOCIATED(default_val%enum)) THEN
     281            0 :             IF (ASSOCIATED(keyword%enum)) THEN
     282            0 :                CPASSERT(ASSOCIATED(keyword%enum, default_val%enum))
     283              :             ELSE
     284            0 :                keyword%enum => default_val%enum
     285            0 :                CALL enum_retain(keyword%enum)
     286              :             END IF
     287              :          ELSE
     288            0 :             CPASSERT(.NOT. ASSOCIATED(keyword%enum))
     289              :          END IF
     290            0 :          CALL val_retain(default_val)
     291              :       END IF
     292    706880064 :       IF (.NOT. ASSOCIATED(keyword%default_value)) THEN
     293              :          CALL val_create(keyword%default_value, l_val=default_l_val, &
     294              :                          l_vals=default_l_vals, i_val=default_i_val, i_vals=default_i_vals, &
     295              :                          r_val=default_r_val, r_vals=default_r_vals, c_val=default_c_val, &
     296   4934457716 :                          c_vals=default_c_vals, lc_val=default_lc_val, enum=keyword%enum)
     297              :       END IF
     298              : 
     299    706880064 :       keyword%type_of_var = keyword%default_value%type_of_var
     300    706880064 :       IF (keyword%default_value%type_of_var == no_t) THEN
     301     15912281 :          CALL val_release(keyword%default_value)
     302              :       END IF
     303              : 
     304    706880064 :       IF (keyword%type_of_var == no_t) THEN
     305     15912281 :          IF (PRESENT(type_of_var)) THEN
     306     15912281 :             keyword%type_of_var = type_of_var
     307              :          ELSE
     308              :             CALL cp_abort(__LOCATION__, &
     309              :                           "keyword "//TRIM(keyword%names(1))// &
     310            0 :                           " assumed undefined type by default")
     311              :          END IF
     312    690967783 :       ELSE IF (PRESENT(type_of_var)) THEN
     313     13370658 :          IF (keyword%type_of_var /= type_of_var) &
     314              :             CALL cp_abort(__LOCATION__, &
     315              :                           "keyword "//TRIM(keyword%names(1))// &
     316            0 :                           " has a type different from the type of the default_value")
     317     13370658 :          keyword%type_of_var = type_of_var
     318              :       END IF
     319              : 
     320    706880064 :       IF (keyword%type_of_var == no_t) THEN
     321            0 :          CALL val_create(keyword%default_value)
     322              :       END IF
     323              : 
     324    706880064 :       IF (PRESENT(lone_keyword_val)) THEN
     325              :          IF (PRESENT(lone_keyword_l_val) .OR. PRESENT(lone_keyword_l_vals) .OR. &
     326              :              PRESENT(lone_keyword_i_val) .OR. PRESENT(lone_keyword_i_vals) .OR. &
     327              :              PRESENT(lone_keyword_r_val) .OR. PRESENT(lone_keyword_r_vals) .OR. &
     328            0 :              PRESENT(lone_keyword_c_val) .OR. PRESENT(lone_keyword_c_vals)) &
     329              :             CALL cp_abort(__LOCATION__, &
     330            0 :                           "you should pass either lone_keyword_val or a lone_keyword value, not both")
     331            0 :          keyword%lone_keyword_value => lone_keyword_val
     332            0 :          CALL val_retain(lone_keyword_val)
     333            0 :          IF (ASSOCIATED(lone_keyword_val%enum)) THEN
     334            0 :             IF (ASSOCIATED(keyword%enum)) THEN
     335            0 :                IF (.NOT. ASSOCIATED(keyword%enum, lone_keyword_val%enum)) &
     336            0 :                   CPABORT("keyword%enum/=lone_keyword_val%enum")
     337              :             ELSE
     338            0 :                IF (ASSOCIATED(keyword%lone_keyword_value)) THEN
     339            0 :                   CPABORT(".NOT. ASSOCIATED(keyword%lone_keyword_value)")
     340              :                END IF
     341            0 :                keyword%enum => lone_keyword_val%enum
     342            0 :                CALL enum_retain(keyword%enum)
     343              :             END IF
     344              :          ELSE
     345            0 :             CPASSERT(.NOT. ASSOCIATED(keyword%enum))
     346              :          END IF
     347              :       END IF
     348    706880064 :       IF (.NOT. ASSOCIATED(keyword%lone_keyword_value)) THEN
     349              :          CALL val_create(keyword%lone_keyword_value, l_val=lone_keyword_l_val, &
     350              :                          l_vals=lone_keyword_l_vals, i_val=lone_keyword_i_val, i_vals=lone_keyword_i_vals, &
     351              :                          r_val=lone_keyword_r_val, r_vals=lone_keyword_r_vals, c_val=lone_keyword_c_val, &
     352   4241159676 :                          c_vals=lone_keyword_c_vals, enum=keyword%enum)
     353              :       END IF
     354    706880064 :       IF (ASSOCIATED(keyword%lone_keyword_value)) THEN
     355    706880064 :          IF (keyword%lone_keyword_value%type_of_var == no_t) THEN
     356    609375597 :             CALL val_release(keyword%lone_keyword_value)
     357              :          ELSE
     358     97504467 :             IF (keyword%lone_keyword_value%type_of_var /= keyword%type_of_var) &
     359            0 :                CPABORT("lone_keyword_value type incompatible with keyword type")
     360              :             ! lc_val cannot have lone_keyword_value!
     361     97504467 :             IF (keyword%type_of_var == enum_t) THEN
     362      6981246 :                IF (keyword%enum%strict) THEN
     363      6981246 :                   check = .FALSE.
     364     55807180 :                   DO i = 1, SIZE(keyword%enum%i_vals)
     365     84681569 :                      check = check .OR. (keyword%default_value%i_val(1) == keyword%enum%i_vals(i))
     366              :                   END DO
     367      6981246 :                   IF (.NOT. check) &
     368            0 :                      CPABORT("default value not in enumeration : "//keyword%names(1))
     369              :                END IF
     370              :             END IF
     371              :          END IF
     372              :       END IF
     373              : 
     374    706880064 :       keyword%n_var = 1
     375    706880064 :       IF (ASSOCIATED(keyword%default_value)) THEN
     376    783016520 :          SELECT CASE (keyword%default_value%type_of_var)
     377              :          CASE (logical_t)
     378     92048737 :             keyword%n_var = SIZE(keyword%default_value%l_val)
     379              :          CASE (integer_t)
     380    151882735 :             keyword%n_var = SIZE(keyword%default_value%i_val)
     381              :          CASE (enum_t)
     382     24210983 :             IF (keyword%enum%strict) THEN
     383     24210983 :                check = .FALSE.
     384    135666579 :                DO i = 1, SIZE(keyword%enum%i_vals)
     385    173535783 :                   check = check .OR. (keyword%default_value%i_val(1) == keyword%enum%i_vals(i))
     386              :                END DO
     387     24210983 :                IF (.NOT. check) &
     388            0 :                   CPABORT("default value not in enumeration : "//keyword%names(1))
     389              :             END IF
     390     24210983 :             keyword%n_var = SIZE(keyword%default_value%i_val)
     391              :          CASE (real_t)
     392    412637319 :             keyword%n_var = SIZE(keyword%default_value%r_val)
     393              :          CASE (char_t)
     394      2458681 :             keyword%n_var = SIZE(keyword%default_value%c_val)
     395              :          CASE (lchar_t)
     396      7729328 :             keyword%n_var = 1
     397              :          CASE (no_t)
     398            0 :             keyword%n_var = 0
     399              :          CASE default
     400    690967783 :             CPABORT("")
     401              :          END SELECT
     402              :       END IF
     403    706880064 :       IF (PRESENT(n_var)) keyword%n_var = n_var
     404    706880064 :       IF (keyword%type_of_var == lchar_t .AND. keyword%n_var /= 1) &
     405            0 :          CPABORT("arrays of lchar_t not supported : "//keyword%names(1))
     406              : 
     407    706880064 :       IF (PRESENT(unit_str)) THEN
     408    323847150 :          ALLOCATE (keyword%unit)
     409     12953886 :          CALL cp_unit_create(keyword%unit, unit_str)
     410              :       END IF
     411              : 
     412    706880064 :       IF (PRESENT(deprecation_notice)) THEN
     413       105660 :          keyword%deprecation_notice = TRIM(deprecation_notice)
     414              :       END IF
     415              : 
     416    706880064 :       IF (PRESENT(removed)) THEN
     417        37136 :          keyword%removed = removed
     418              :       END IF
     419    706880064 :    END SUBROUTINE keyword_create
     420              : 
     421              : ! **************************************************************************************************
     422              : !> \brief retains the given keyword (see doc/ReferenceCounting.html)
     423              : !> \param keyword the keyword to retain
     424              : !> \author fawzi
     425              : ! **************************************************************************************************
     426    706880064 :    SUBROUTINE keyword_retain(keyword)
     427              :       TYPE(keyword_type), POINTER                        :: keyword
     428              : 
     429    706880064 :       CPASSERT(ASSOCIATED(keyword))
     430    706880064 :       CPASSERT(keyword%ref_count > 0)
     431    706880064 :       keyword%ref_count = keyword%ref_count + 1
     432    706880064 :    END SUBROUTINE keyword_retain
     433              : 
     434              : ! **************************************************************************************************
     435              : !> \brief releases the given keyword (see doc/ReferenceCounting.html)
     436              : !> \param keyword the keyword to release
     437              : !> \author fawzi
     438              : ! **************************************************************************************************
     439   1816697349 :    SUBROUTINE keyword_release(keyword)
     440              :       TYPE(keyword_type), POINTER                        :: keyword
     441              : 
     442   1816697349 :       IF (ASSOCIATED(keyword)) THEN
     443   1413760128 :          CPASSERT(keyword%ref_count > 0)
     444   1413760128 :          keyword%ref_count = keyword%ref_count - 1
     445   1413760128 :          IF (keyword%ref_count == 0) THEN
     446    706880064 :             DEALLOCATE (keyword%names)
     447    706880064 :             DEALLOCATE (keyword%description)
     448    706880064 :             CALL val_release(keyword%default_value)
     449    706880064 :             CALL val_release(keyword%lone_keyword_value)
     450    706880064 :             CALL enum_release(keyword%enum)
     451    706880064 :             IF (ASSOCIATED(keyword%unit)) THEN
     452     12953886 :                CALL cp_unit_release(keyword%unit)
     453     12953886 :                DEALLOCATE (keyword%unit)
     454              :             END IF
     455    706880064 :             IF (ASSOCIATED(keyword%citations)) THEN
     456      1069100 :                DEALLOCATE (keyword%citations)
     457              :             END IF
     458    706880064 :             DEALLOCATE (keyword)
     459              :          END IF
     460              :       END IF
     461   1816697349 :       NULLIFY (keyword)
     462   1816697349 :    END SUBROUTINE keyword_release
     463              : 
     464              : ! **************************************************************************************************
     465              : !> \brief ...
     466              : !> \param keyword ...
     467              : !> \param names ...
     468              : !> \param usage ...
     469              : !> \param description ...
     470              : !> \param type_of_var ...
     471              : !> \param n_var ...
     472              : !> \param default_value ...
     473              : !> \param lone_keyword_value ...
     474              : !> \param repeats ...
     475              : !> \param enum ...
     476              : !> \param citations ...
     477              : !> \author fawzi
     478              : ! **************************************************************************************************
     479        50724 :    SUBROUTINE keyword_get(keyword, names, usage, description, type_of_var, n_var, &
     480              :                           default_value, lone_keyword_value, repeats, enum, citations)
     481              :       TYPE(keyword_type), POINTER                        :: keyword
     482              :       CHARACTER(len=default_string_length), &
     483              :          DIMENSION(:), OPTIONAL, POINTER                 :: names
     484              :       CHARACTER(len=*), INTENT(out), OPTIONAL            :: usage, description
     485              :       INTEGER, INTENT(out), OPTIONAL                     :: type_of_var, n_var
     486              :       TYPE(val_type), OPTIONAL, POINTER                  :: default_value, lone_keyword_value
     487              :       LOGICAL, INTENT(out), OPTIONAL                     :: repeats
     488              :       TYPE(enumeration_type), OPTIONAL, POINTER          :: enum
     489              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: citations
     490              : 
     491            0 :       CPASSERT(ASSOCIATED(keyword))
     492        50724 :       CPASSERT(keyword%ref_count > 0)
     493        50724 :       IF (PRESENT(names)) names => keyword%names
     494        50724 :       IF (PRESENT(usage)) usage = keyword%usage
     495        50724 :       IF (PRESENT(description)) description = a2s(keyword%description)
     496        50724 :       IF (PRESENT(type_of_var)) type_of_var = keyword%type_of_var
     497        50724 :       IF (PRESENT(n_var)) n_var = keyword%n_var
     498        50724 :       IF (PRESENT(repeats)) repeats = keyword%repeats
     499        50724 :       IF (PRESENT(default_value)) default_value => keyword%default_value
     500        50724 :       IF (PRESENT(lone_keyword_value)) lone_keyword_value => keyword%lone_keyword_value
     501        50724 :       IF (PRESENT(enum)) enum => keyword%enum
     502        50724 :       IF (PRESENT(citations)) citations => keyword%citations
     503        50724 :    END SUBROUTINE keyword_get
     504              : 
     505              : ! **************************************************************************************************
     506              : !> \brief writes out a description of the keyword
     507              : !> \param keyword the keyword to describe
     508              : !> \param unit_nr the unit to write to
     509              : !> \param level the description level (0 no description, 1 name
     510              : !>        2: +usage, 3: +variants+description+default_value+repeats
     511              : !>        4: +type_of_var)
     512              : !> \author fawzi
     513              : ! **************************************************************************************************
     514           19 :    SUBROUTINE keyword_describe(keyword, unit_nr, level)
     515              :       TYPE(keyword_type), POINTER                        :: keyword
     516              :       INTEGER, INTENT(in)                                :: unit_nr, level
     517              : 
     518              :       CHARACTER(len=cp_unit_desc_length)                 :: c_string
     519              :       INTEGER                                            :: i, l
     520              : 
     521           19 :       CPASSERT(ASSOCIATED(keyword))
     522           19 :       CPASSERT(keyword%ref_count > 0)
     523           19 :       IF (level > 0 .AND. (unit_nr > 0)) THEN
     524           19 :          WRITE (unit_nr, "(a,a,a)") "                           ---", &
     525           38 :             TRIM(keyword%names(1)), "---"
     526           19 :          IF (level > 1) THEN
     527           19 :             WRITE (unit_nr, "(a,a)") "usage         : ", TRIM(keyword%usage)
     528              :          END IF
     529           19 :          IF (level > 2) THEN
     530           19 :             WRITE (unit_nr, "(a)") "description   : "
     531           19 :             CALL print_message(TRIM(a2s(keyword%description)), unit_nr, 0, 0, 0)
     532           19 :             IF (level > 3) THEN
     533            0 :                SELECT CASE (keyword%type_of_var)
     534              :                CASE (logical_t)
     535            0 :                   IF (keyword%n_var == -1) THEN
     536            0 :                      WRITE (unit_nr, "('  A list of logicals is expected')")
     537            0 :                   ELSE IF (keyword%n_var == 1) THEN
     538            0 :                      WRITE (unit_nr, "('  A logical is expected')")
     539              :                   ELSE
     540            0 :                      WRITE (unit_nr, "(i6,'  logicals are expected')") keyword%n_var
     541              :                   END IF
     542            0 :                   WRITE (unit_nr, "('  (T,TRUE,YES,ON) and (F,FALSE,NO,OFF) are synonyms')")
     543              :                CASE (integer_t)
     544            0 :                   IF (keyword%n_var == -1) THEN
     545            0 :                      WRITE (unit_nr, "('  A list of integers is expected')")
     546            0 :                   ELSE IF (keyword%n_var == 1) THEN
     547            0 :                      WRITE (unit_nr, "('  An integer is expected')")
     548              :                   ELSE
     549            0 :                      WRITE (unit_nr, "(i6,' integers are expected')") keyword%n_var
     550              :                   END IF
     551              :                CASE (real_t)
     552            0 :                   IF (keyword%n_var == -1) THEN
     553            0 :                      WRITE (unit_nr, "('  A list of reals is expected')")
     554            0 :                   ELSE IF (keyword%n_var == 1) THEN
     555            0 :                      WRITE (unit_nr, "('  A real is expected')")
     556              :                   ELSE
     557            0 :                      WRITE (unit_nr, "(i6,' reals are expected')") keyword%n_var
     558              :                   END IF
     559            0 :                   IF (ASSOCIATED(keyword%unit)) THEN
     560            0 :                      c_string = cp_unit_desc(keyword%unit, accept_undefined=.TRUE.)
     561              :                      WRITE (unit_nr, "('the default unit of measure is ',a)") &
     562            0 :                         TRIM(c_string)
     563              :                   END IF
     564              :                CASE (char_t)
     565            0 :                   IF (keyword%n_var == -1) THEN
     566            0 :                      WRITE (unit_nr, "('  A list of words is expected')")
     567            0 :                   ELSE IF (keyword%n_var == 1) THEN
     568            0 :                      WRITE (unit_nr, "('  A word is expected')")
     569              :                   ELSE
     570            0 :                      WRITE (unit_nr, "(i6,' words are expected')") keyword%n_var
     571              :                   END IF
     572              :                CASE (lchar_t)
     573            0 :                   WRITE (unit_nr, "('  A string is expected')")
     574              :                CASE (enum_t)
     575            0 :                   IF (keyword%n_var == -1) THEN
     576            0 :                      WRITE (unit_nr, "('  A list of keywords is expected')")
     577            0 :                   ELSE IF (keyword%n_var == 1) THEN
     578            0 :                      WRITE (unit_nr, "('  A keyword is expected')")
     579              :                   ELSE
     580            0 :                      WRITE (unit_nr, "(i6,' keywords are expected')") keyword%n_var
     581              :                   END IF
     582              :                CASE (no_t)
     583            0 :                   WRITE (unit_nr, "('  Non-standard type.')")
     584              :                CASE default
     585            0 :                   CPABORT("")
     586              :                END SELECT
     587              :             END IF
     588           19 :             IF (keyword%type_of_var == enum_t) THEN
     589            2 :                IF (level > 3) THEN
     590            0 :                   WRITE (unit_nr, "('  valid keywords:')")
     591            0 :                   DO i = 1, SIZE(keyword%enum%c_vals)
     592            0 :                      c_string = keyword%enum%c_vals(i)
     593            0 :                      IF (LEN_TRIM(a2s(keyword%enum%desc(i)%chars)) > 0) THEN
     594              :                         WRITE (unit_nr, "('  - ',a,' : ',a,'.')") &
     595            0 :                            TRIM(c_string), TRIM(a2s(keyword%enum%desc(i)%chars))
     596              :                      ELSE
     597            0 :                         WRITE (unit_nr, "('  - ',a)") TRIM(c_string)
     598              :                      END IF
     599              :                   END DO
     600              :                ELSE
     601            2 :                   WRITE (unit_nr, "('  valid keywords:')", advance='NO')
     602            2 :                   l = 17
     603           18 :                   DO i = 1, SIZE(keyword%enum%c_vals)
     604           16 :                      c_string = keyword%enum%c_vals(i)
     605           16 :                      IF (l + LEN_TRIM(c_string) > 72 .AND. l > 14) THEN
     606            0 :                         WRITE (unit_nr, "(/,'    ')", advance='NO')
     607            0 :                         l = 4
     608              :                      END IF
     609           16 :                      WRITE (unit_nr, "(' ',a)", advance='NO') TRIM(c_string)
     610           18 :                      l = LEN_TRIM(c_string) + 3
     611              :                   END DO
     612            2 :                   WRITE (unit_nr, "()")
     613              :                END IF
     614            2 :                IF (.NOT. keyword%enum%strict) THEN
     615            0 :                   WRITE (unit_nr, "('     other integer values are also accepted.')")
     616              :                END IF
     617              :             END IF
     618           19 :             IF (ASSOCIATED(keyword%default_value) .AND. keyword%type_of_var /= no_t) THEN
     619           17 :                WRITE (unit_nr, "('default_value : ')", advance="NO")
     620           17 :                CALL val_write(keyword%default_value, unit_nr=unit_nr)
     621              :             END IF
     622           19 :             IF (ASSOCIATED(keyword%lone_keyword_value) .AND. keyword%type_of_var /= no_t) THEN
     623            3 :                WRITE (unit_nr, "('lone_keyword  : ')", advance="NO")
     624            3 :                CALL val_write(keyword%lone_keyword_value, unit_nr=unit_nr)
     625              :             END IF
     626           19 :             IF (keyword%repeats) THEN
     627            0 :                WRITE (unit_nr, "(' and it can be repeated more than once')", advance="NO")
     628              :             END IF
     629           19 :             WRITE (unit_nr, "()")
     630           19 :             IF (SIZE(keyword%names) > 1) THEN
     631            1 :                WRITE (unit_nr, "(a)", advance="NO") "variants    : "
     632            3 :                DO i = 2, SIZE(keyword%names)
     633            3 :                   WRITE (unit_nr, "(a,' ')", advance="NO") keyword%names(i)
     634              :                END DO
     635            1 :                WRITE (unit_nr, "()")
     636              :             END IF
     637              :          END IF
     638              :       END IF
     639           19 :    END SUBROUTINE keyword_describe
     640              : 
     641              : ! **************************************************************************************************
     642              : !> \brief Prints a description of a keyword in XML format
     643              : !> \param keyword The keyword to describe
     644              : !> \param level ...
     645              : !> \param unit_number Number of the output unit
     646              : !> \author Matthias Krack
     647              : ! **************************************************************************************************
     648            0 :    SUBROUTINE write_keyword_xml(keyword, level, unit_number)
     649              : 
     650              :       TYPE(keyword_type), POINTER                        :: keyword
     651              :       INTEGER, INTENT(IN)                                :: level, unit_number
     652              : 
     653              :       CHARACTER(LEN=1000)                                :: string
     654              :       CHARACTER(LEN=3)                                   :: removed, repeats
     655              :       CHARACTER(LEN=8)                                   :: short_string
     656              :       INTEGER                                            :: i, l0, l1, l2, l3, l4
     657              : 
     658            0 :       CPASSERT(ASSOCIATED(keyword))
     659            0 :       CPASSERT(keyword%ref_count > 0)
     660              : 
     661              :       ! Indentation for current level, next level, etc.
     662              : 
     663            0 :       l0 = level
     664            0 :       l1 = level + 1
     665            0 :       l2 = level + 2
     666            0 :       l3 = level + 3
     667            0 :       l4 = level + 4
     668              : 
     669            0 :       IF (keyword%repeats) THEN
     670            0 :          repeats = "yes"
     671              :       ELSE
     672            0 :          repeats = "no "
     673              :       END IF
     674              : 
     675            0 :       IF (keyword%removed) THEN
     676            0 :          removed = "yes"
     677              :       ELSE
     678            0 :          removed = "no "
     679              :       END IF
     680              : 
     681              :       ! Write (special) keyword element
     682              : 
     683            0 :       IF (keyword%names(1) == "_SECTION_PARAMETERS_") THEN
     684            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     685              :             REPEAT(" ", l0)//"<SECTION_PARAMETERS repeats="""//TRIM(repeats)// &
     686            0 :             """ removed="""//TRIM(removed)//""">", &
     687            0 :             REPEAT(" ", l1)//"<NAME type=""default"">SECTION_PARAMETERS</NAME>"
     688            0 :       ELSE IF (keyword%names(1) == "_DEFAULT_KEYWORD_") THEN
     689            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     690            0 :             REPEAT(" ", l0)//"<DEFAULT_KEYWORD repeats="""//TRIM(repeats)//""">", &
     691            0 :             REPEAT(" ", l1)//"<NAME type=""default"">DEFAULT_KEYWORD</NAME>"
     692              :       ELSE
     693            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     694              :             REPEAT(" ", l0)//"<KEYWORD repeats="""//TRIM(repeats)// &
     695            0 :             """ removed="""//TRIM(removed)//""">", &
     696              :             REPEAT(" ", l1)//"<NAME type=""default"">"// &
     697            0 :             TRIM(keyword%names(1))//"</NAME>"
     698              :       END IF
     699              : 
     700            0 :       DO i = 2, SIZE(keyword%names)
     701            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     702              :             REPEAT(" ", l1)//"<NAME type=""alias"">"// &
     703            0 :             TRIM(keyword%names(i))//"</NAME>"
     704              :       END DO
     705              : 
     706            0 :       SELECT CASE (keyword%type_of_var)
     707              :       CASE (logical_t)
     708            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     709            0 :             REPEAT(" ", l1)//"<DATA_TYPE kind=""logical"">"
     710              :       CASE (integer_t)
     711            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     712            0 :             REPEAT(" ", l1)//"<DATA_TYPE kind=""integer"">"
     713              :       CASE (real_t)
     714            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     715            0 :             REPEAT(" ", l1)//"<DATA_TYPE kind=""real"">"
     716              :       CASE (char_t)
     717            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     718            0 :             REPEAT(" ", l1)//"<DATA_TYPE kind=""word"">"
     719              :       CASE (lchar_t)
     720            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     721            0 :             REPEAT(" ", l1)//"<DATA_TYPE kind=""string"">"
     722              :       CASE (enum_t)
     723            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     724            0 :             REPEAT(" ", l1)//"<DATA_TYPE kind=""keyword"">"
     725            0 :          IF (keyword%enum%strict) THEN
     726            0 :             WRITE (UNIT=unit_number, FMT="(A)") &
     727            0 :                REPEAT(" ", l2)//"<ENUMERATION strict=""yes"">"
     728              :          ELSE
     729            0 :             WRITE (UNIT=unit_number, FMT="(A)") &
     730            0 :                REPEAT(" ", l2)//"<ENUMERATION strict=""no"">"
     731              :          END IF
     732            0 :          DO i = 1, SIZE(keyword%enum%c_vals)
     733            0 :             WRITE (UNIT=unit_number, FMT="(A)") &
     734            0 :                REPEAT(" ", l3)//"<ITEM>", &
     735              :                REPEAT(" ", l4)//"<NAME>"// &
     736            0 :                TRIM(ADJUSTL(substitute_special_xml_tokens(keyword%enum%c_vals(i))))//"</NAME>", &
     737              :                REPEAT(" ", l4)//"<DESCRIPTION>"// &
     738              :                TRIM(ADJUSTL(substitute_special_xml_tokens(a2s(keyword%enum%desc(i)%chars)))) &
     739            0 :                //"</DESCRIPTION>", REPEAT(" ", l3)//"</ITEM>"
     740              :          END DO
     741            0 :          WRITE (UNIT=unit_number, FMT="(A)") REPEAT(" ", l2)//"</ENUMERATION>"
     742              :       CASE (no_t)
     743            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     744            0 :             REPEAT(" ", l1)//"<DATA_TYPE kind=""non-standard type"">"
     745              :       CASE DEFAULT
     746            0 :          CPABORT("")
     747              :       END SELECT
     748              : 
     749            0 :       short_string = ""
     750            0 :       WRITE (UNIT=short_string, FMT="(I8)") keyword%n_var
     751            0 :       WRITE (UNIT=unit_number, FMT="(A)") &
     752            0 :          REPEAT(" ", l2)//"<N_VAR>"//TRIM(ADJUSTL(short_string))//"</N_VAR>", &
     753            0 :          REPEAT(" ", l1)//"</DATA_TYPE>"
     754              : 
     755              :       WRITE (UNIT=unit_number, FMT="(A)") REPEAT(" ", l1)//"<USAGE>"// &
     756              :          TRIM(substitute_special_xml_tokens(keyword%usage)) &
     757            0 :          //"</USAGE>"
     758              : 
     759              :       WRITE (UNIT=unit_number, FMT="(A)") REPEAT(" ", l1)//"<DESCRIPTION>"// &
     760              :          TRIM(substitute_special_xml_tokens(a2s(keyword%description))) &
     761            0 :          //"</DESCRIPTION>"
     762              : 
     763            0 :       IF (ALLOCATED(keyword%deprecation_notice)) &
     764              :          WRITE (UNIT=unit_number, FMT="(A)") REPEAT(" ", l1)//"<DEPRECATION_NOTICE>"// &
     765              :          TRIM(substitute_special_xml_tokens(keyword%deprecation_notice)) &
     766            0 :          //"</DEPRECATION_NOTICE>"
     767              : 
     768            0 :       IF (ASSOCIATED(keyword%default_value) .AND. &
     769              :           (keyword%type_of_var /= no_t)) THEN
     770            0 :          IF (ASSOCIATED(keyword%unit)) THEN
     771              :             CALL val_write_internal(val=keyword%default_value, &
     772              :                                     string=string, &
     773            0 :                                     unit=keyword%unit)
     774              :          ELSE
     775              :             CALL val_write_internal(val=keyword%default_value, &
     776            0 :                                     string=string)
     777              :          END IF
     778            0 :          CALL compress(string)
     779              :          WRITE (UNIT=unit_number, FMT="(A)") &
     780              :             REPEAT(" ", l1)//"<DEFAULT_VALUE>"// &
     781            0 :             TRIM(ADJUSTL(substitute_special_xml_tokens(string)))//"</DEFAULT_VALUE>"
     782              :       END IF
     783              : 
     784            0 :       IF (ASSOCIATED(keyword%unit)) THEN
     785            0 :          string = cp_unit_desc(keyword%unit, accept_undefined=.TRUE.)
     786              :          WRITE (UNIT=unit_number, FMT="(A)") &
     787              :             REPEAT(" ", l1)//"<DEFAULT_UNIT>"// &
     788            0 :             TRIM(ADJUSTL(string))//"</DEFAULT_UNIT>"
     789              :       END IF
     790              : 
     791            0 :       IF (ASSOCIATED(keyword%lone_keyword_value) .AND. &
     792              :           (keyword%type_of_var /= no_t)) THEN
     793              :          CALL val_write_internal(val=keyword%lone_keyword_value, &
     794            0 :                                  string=string)
     795              :          WRITE (UNIT=unit_number, FMT="(A)") &
     796              :             REPEAT(" ", l1)//"<LONE_KEYWORD_VALUE>"// &
     797            0 :             TRIM(ADJUSTL(substitute_special_xml_tokens(string)))//"</LONE_KEYWORD_VALUE>"
     798              :       END IF
     799              : 
     800            0 :       IF (ASSOCIATED(keyword%citations)) THEN
     801            0 :          DO i = 1, SIZE(keyword%citations, 1)
     802            0 :             short_string = ""
     803            0 :             WRITE (UNIT=short_string, FMT="(I8)") keyword%citations(i)
     804              :             WRITE (UNIT=unit_number, FMT="(A)") &
     805            0 :                REPEAT(" ", l1)//"<REFERENCE>", &
     806            0 :                REPEAT(" ", l2)//"<NAME>"//TRIM(get_citation_key(keyword%citations(i)))//"</NAME>", &
     807            0 :                REPEAT(" ", l2)//"<NUMBER>"//TRIM(ADJUSTL(short_string))//"</NUMBER>", &
     808            0 :                REPEAT(" ", l1)//"</REFERENCE>"
     809              :          END DO
     810              :       END IF
     811              : 
     812              :       WRITE (UNIT=unit_number, FMT="(A)") &
     813            0 :          REPEAT(" ", l1)//"<LOCATION>"//TRIM(keyword%location)//"</LOCATION>"
     814              : 
     815              :       ! Close (special) keyword section
     816              : 
     817            0 :       IF (keyword%names(1) == "_SECTION_PARAMETERS_") THEN
     818            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     819            0 :             REPEAT(" ", l0)//"</SECTION_PARAMETERS>"
     820            0 :       ELSE IF (keyword%names(1) == "_DEFAULT_KEYWORD_") THEN
     821            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     822            0 :             REPEAT(" ", l0)//"</DEFAULT_KEYWORD>"
     823              :       ELSE
     824            0 :          WRITE (UNIT=unit_number, FMT="(A)") &
     825            0 :             REPEAT(" ", l0)//"</KEYWORD>"
     826              :       END IF
     827              : 
     828            0 :    END SUBROUTINE write_keyword_xml
     829              : 
     830              : ! **************************************************************************************************
     831              : !> \brief ...
     832              : !> \param keyword ...
     833              : !> \param unknown_string ...
     834              : !> \param location_string ...
     835              : !> \param matching_rank ...
     836              : !> \param matching_string ...
     837              : !> \param bonus ...
     838              : ! **************************************************************************************************
     839            0 :    SUBROUTINE keyword_typo_match(keyword, unknown_string, location_string, matching_rank, matching_string, bonus)
     840              : 
     841              :       TYPE(keyword_type), POINTER                        :: keyword
     842              :       CHARACTER(LEN=*)                                   :: unknown_string, location_string
     843              :       INTEGER, DIMENSION(:), INTENT(INOUT)               :: matching_rank
     844              :       CHARACTER(LEN=*), DIMENSION(:), INTENT(INOUT)      :: matching_string
     845              :       INTEGER, INTENT(IN)                                :: bonus
     846              : 
     847            0 :       CHARACTER(LEN=LEN(matching_string(1)))             :: line
     848              :       INTEGER                                            :: i, imatch, imax, irank, j, k
     849              : 
     850            0 :       CPASSERT(ASSOCIATED(keyword))
     851            0 :       CPASSERT(keyword%ref_count > 0)
     852              : 
     853            0 :       DO i = 1, SIZE(keyword%names)
     854            0 :          imatch = typo_match(TRIM(keyword%names(i)), TRIM(unknown_string))
     855            0 :          IF (imatch > 0) THEN
     856            0 :             imatch = imatch + bonus
     857            0 :             WRITE (line, '(T2,A)') " keyword "//TRIM(keyword%names(i))//" in section "//TRIM(location_string)
     858            0 :             imax = SIZE(matching_rank, 1)
     859            0 :             irank = imax + 1
     860            0 :             DO k = imax, 1, -1
     861            0 :                IF (imatch > matching_rank(k)) irank = k
     862              :             END DO
     863            0 :             IF (irank <= imax) THEN
     864            0 :                matching_rank(irank + 1:imax) = matching_rank(irank:imax - 1)
     865            0 :                matching_string(irank + 1:imax) = matching_string(irank:imax - 1)
     866            0 :                matching_rank(irank) = imatch
     867            0 :                matching_string(irank) = line
     868              :             END IF
     869              :          END IF
     870              : 
     871            0 :          IF (keyword%type_of_var == enum_t) THEN
     872            0 :             DO j = 1, SIZE(keyword%enum%c_vals)
     873            0 :                imatch = typo_match(TRIM(keyword%enum%c_vals(j)), TRIM(unknown_string))
     874            0 :                IF (imatch > 0) THEN
     875            0 :                   imatch = imatch + bonus
     876              :                   WRITE (line, '(T2,A)') " enum "//TRIM(keyword%enum%c_vals(j))// &
     877              :                      " in section "//TRIM(location_string)// &
     878            0 :                      " for keyword "//TRIM(keyword%names(i))
     879            0 :                   imax = SIZE(matching_rank, 1)
     880            0 :                   irank = imax + 1
     881            0 :                   DO k = imax, 1, -1
     882            0 :                      IF (imatch > matching_rank(k)) irank = k
     883              :                   END DO
     884            0 :                   IF (irank <= imax) THEN
     885            0 :                      matching_rank(irank + 1:imax) = matching_rank(irank:imax - 1)
     886            0 :                      matching_string(irank + 1:imax) = matching_string(irank:imax - 1)
     887            0 :                      matching_rank(irank) = imatch
     888            0 :                      matching_string(irank) = line
     889              :                   END IF
     890              :                END IF
     891              :             END DO
     892              :          END IF
     893              :       END DO
     894              : 
     895            0 :    END SUBROUTINE keyword_typo_match
     896              : 
     897            0 : END MODULE input_keyword_types
        

Generated by: LCOV version 2.0-1