LCOV - code coverage report
Current view: top level - src/input - cp_parser_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:62906da) Lines: 84.2 % 532 448
Test Date: 2026-10-24 01:17:15 Functions: 95.5 % 22 21

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Utility routines to read data from files.
      10              : !>      Kept as close as possible to the old parser because
      11              : !>        1. string handling is a weak point of fortran compilers, and it is
      12              : !>           easy to write correct things that do not work
      13              : !>        2. conversion of old code
      14              : !> \par History
      15              : !>      22.11.1999 first version of the old parser (called qs_parser)
      16              : !>                 Matthias Krack
      17              : !>      06.2004 removed module variables, cp_parser_type, new module [fawzi]
      18              : !> \author Fawzi Mohamed, Matthias Krack
      19              : ! **************************************************************************************************
      20              : MODULE cp_parser_methods
      21              : 
      22              :    USE cp_log_handling,                 ONLY: cp_to_string
      23              :    USE cp_parser_buffer_types,          ONLY: copy_buffer_type,&
      24              :                                               finalize_sub_buffer,&
      25              :                                               initialize_sub_buffer
      26              :    USE cp_parser_ilist_methods,         ONLY: ilist_reset,&
      27              :                                               ilist_setup,&
      28              :                                               ilist_update
      29              :    USE cp_parser_inpp_methods,          ONLY: inpp_end_include,&
      30              :                                               inpp_expand_variables,&
      31              :                                               inpp_process_directive
      32              :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      33              :                                               parser_reset
      34              :    USE kinds,                           ONLY: default_path_length,&
      35              :                                               default_string_length,&
      36              :                                               dp,&
      37              :                                               int_8,&
      38              :                                               max_line_length
      39              :    USE mathconstants,                   ONLY: radians
      40              :    USE message_passing,                 ONLY: mp_para_env_type
      41              :    USE string_utilities,                ONLY: is_whitespace,&
      42              :                                               uppercase
      43              : #include "../base/base_uses.f90"
      44              : 
      45              :    IMPLICIT NONE
      46              :    PRIVATE
      47              : 
      48              :    PUBLIC :: parser_test_next_token, parser_get_object, parser_location, &
      49              :              parser_search_string, parser_get_next_line, parser_skip_space, &
      50              :              parser_read_line, read_float_object, read_integer_object
      51              : 
      52              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_parser_methods'
      53              : 
      54              :    INTERFACE parser_get_object
      55              :       MODULE PROCEDURE parser_get_integer, &
      56              :          parser_get_logical, &
      57              :          parser_get_real, &
      58              :          parser_get_string
      59              :    END INTERFACE
      60              : 
      61              : CONTAINS
      62              : 
      63              : ! **************************************************************************************************
      64              : !> \brief return a description of the part of the file actually parsed
      65              : !> \param parser the parser
      66              : !> \return ...
      67              : !> \author fawzi
      68              : ! **************************************************************************************************
      69            0 :    FUNCTION parser_location(parser) RESULT(res)
      70              : 
      71              :       TYPE(cp_parser_type), INTENT(IN)                   :: parser
      72              :       CHARACTER&
      73              :          (len=default_path_length+default_string_length) :: res
      74              : 
      75              :       res = ", File: '"//TRIM(parser%input_file_name)//"', Line: "// &
      76              :             TRIM(ADJUSTL(cp_to_string(parser%input_line_number)))// &
      77            0 :             ", Column: "//TRIM(ADJUSTL(cp_to_string(parser%icol)))
      78            0 :       IF (parser%icol == -1) THEN
      79            0 :          res(LEN_TRIM(res):) = " (EOF)"
      80            0 :       ELSE IF (MAX(1, parser%icol1) <= parser%icol2) THEN
      81              :          res(LEN_TRIM(res):) = ", Chunk: <"// &
      82            0 :                                parser%input_line(MAX(1, parser%icol1):parser%icol2)//">"
      83              :       END IF
      84              : 
      85            0 :    END FUNCTION parser_location
      86              : 
      87              : ! **************************************************************************************************
      88              : !> \brief   store the present status of the parser
      89              : !> \param parser ...
      90              : !> \date    08.2008
      91              : !> \author  Teodoro Laino [tlaino] - University of Zurich
      92              : ! **************************************************************************************************
      93      4788442 :    SUBROUTINE parser_store_status(parser)
      94              : 
      95              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
      96              : 
      97      4788442 :       CPASSERT(ASSOCIATED(parser%status))
      98      4788442 :       parser%status%in_use = .TRUE.
      99      4788442 :       parser%status%old_input_line = parser%input_line
     100      4788442 :       parser%status%old_input_line_number = parser%input_line_number
     101      4788442 :       parser%status%old_icol = parser%icol
     102      4788442 :       parser%status%old_icol1 = parser%icol1
     103      4788442 :       parser%status%old_icol2 = parser%icol2
     104              :       ! Store buffer info
     105      4788442 :       CALL copy_buffer_type(parser%buffer, parser%status%buffer)
     106              : 
     107      4788442 :    END SUBROUTINE parser_store_status
     108              : 
     109              : ! **************************************************************************************************
     110              : !> \brief   retrieve the original status of the parser
     111              : !> \param parser ...
     112              : !> \date    08.2008
     113              : !> \author  Teodoro Laino [tlaino] - University of Zurich
     114              : ! **************************************************************************************************
     115      4788442 :    SUBROUTINE parser_retrieve_status(parser)
     116              : 
     117              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     118              : 
     119              :       ! Always store the new buffer (if it is really newly read)
     120      4788442 :       IF (parser%buffer%buffer_id /= parser%status%buffer%buffer_id) THEN
     121           38 :          CALL initialize_sub_buffer(parser%buffer%sub_buffer, parser%buffer)
     122              :       END IF
     123      4788442 :       parser%status%in_use = .FALSE.
     124      4788442 :       parser%input_line = parser%status%old_input_line
     125      4788442 :       parser%input_line_number = parser%status%old_input_line_number
     126      4788442 :       parser%icol = parser%status%old_icol
     127      4788442 :       parser%icol1 = parser%status%old_icol1
     128      4788442 :       parser%icol2 = parser%status%old_icol2
     129              : 
     130              :       ! Retrieve buffer info
     131      4788442 :       CALL copy_buffer_type(parser%status%buffer, parser%buffer)
     132              : 
     133      4788442 :    END SUBROUTINE parser_retrieve_status
     134              : 
     135              : ! **************************************************************************************************
     136              : !> \brief   Read the next line from a logical unit "unit" (I/O node only).
     137              : !>          Skip (nline-1) lines and skip also all comment lines.
     138              : !> \param parser ...
     139              : !> \param nline ...
     140              : !> \param at_end ...
     141              : !> \date    22.11.1999
     142              : !> \author  Matthias Krack (MK)
     143              : !> \version 1.0
     144              : !> \note 08.2008 [tlaino] - Teodoro Laino UZH : updated for buffer
     145              : ! **************************************************************************************************
     146     46727489 :    SUBROUTINE parser_read_line(parser, nline, at_end)
     147              : 
     148              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     149              :       INTEGER, INTENT(IN)                                :: nline
     150              :       LOGICAL, INTENT(out), OPTIONAL                     :: at_end
     151              : 
     152              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'parser_read_line'
     153              : 
     154              :       INTEGER                                            :: handle, iline, istat
     155              : 
     156     46727489 :       CALL timeset(routineN, handle)
     157              : 
     158     46727489 :       IF (PRESENT(at_end)) at_end = .FALSE.
     159              : 
     160     93437517 :       DO iline = 1, nline
     161              :          ! Try to read the next line from the buffer
     162     46733289 :          CALL parser_get_line_from_buffer(parser, istat)
     163              : 
     164              :          ! Handle (persisting) read errors
     165     93437517 :          IF (istat /= 0) THEN
     166        23261 :             IF (istat < 0) THEN ! EOF/EOR is negative other errors positive
     167        23261 :                IF (PRESENT(at_end)) THEN
     168        23261 :                   at_end = .TRUE.
     169              :                ELSE
     170            0 :                   CPABORT("Unexpected EOF"//TRIM(parser_location(parser)))
     171              :                END IF
     172        23261 :                parser%icol = -1
     173        23261 :                parser%icol1 = 0
     174        23261 :                parser%icol2 = -1
     175              :             ELSE
     176              :                CALL cp_abort(__LOCATION__, &
     177              :                              "An I/O error occurred (IOSTAT = "// &
     178              :                              TRIM(ADJUSTL(cp_to_string(istat)))//")"// &
     179            0 :                              TRIM(parser_location(parser)))
     180              :             END IF
     181        23261 :             CALL timestop(handle)
     182        23261 :             RETURN
     183              :          END IF
     184              :       END DO
     185              : 
     186              :       ! Reset column pointer, if a new line was read
     187     46704228 :       IF (nline > 0) parser%icol = 0
     188              : 
     189     46704228 :       CALL timestop(handle)
     190              :    END SUBROUTINE parser_read_line
     191              : 
     192              : ! **************************************************************************************************
     193              : !> \brief   Retrieving lines from buffer
     194              : !> \param parser ...
     195              : !> \param istat ...
     196              : !> \date    08.2008
     197              : !> \author  Teodoro Laino [tlaino] - University of Zurich
     198              : ! **************************************************************************************************
     199     46733289 :    SUBROUTINE parser_get_line_from_buffer(parser, istat)
     200              : 
     201              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     202              :       INTEGER, INTENT(OUT)                               :: istat
     203              : 
     204     46733289 :       istat = 0
     205              :       ! Check buffer
     206     46733289 :       IF (parser%buffer%present_line_number == parser%buffer%size) THEN
     207        98431 :          IF (ASSOCIATED(parser%buffer%sub_buffer)) THEN
     208              :             ! If the sub_buffer is initialized let's restore its buffer
     209           38 :             CALL finalize_sub_buffer(parser%buffer%sub_buffer, parser%buffer)
     210              :          ELSE
     211              :             ! Rebuffer input file if required
     212        98393 :             CALL parser_read_line_low(parser)
     213              :          END IF
     214              :       END IF
     215     46733289 :       parser%buffer%present_line_number = parser%buffer%present_line_number + 1
     216     46733289 :       parser%input_line_number = parser%buffer%input_line_numbers(parser%buffer%present_line_number)
     217     46733289 :       parser%input_line = parser%buffer%input_lines(parser%buffer%present_line_number)
     218     46733289 :       IF ((parser%buffer%istat /= 0) .AND. &
     219              :           (parser%buffer%last_line_number == parser%buffer%present_line_number)) THEN
     220        23261 :          istat = parser%buffer%istat
     221              :       END IF
     222              : 
     223     46733289 :    END SUBROUTINE parser_get_line_from_buffer
     224              : 
     225              : ! **************************************************************************************************
     226              : !> \brief   Low level reading subroutine with buffering
     227              : !> \param parser ...
     228              : !> \date    08.2008
     229              : !> \author  Teodoro Laino [tlaino] - University of Zurich
     230              : ! **************************************************************************************************
     231        98393 :    SUBROUTINE parser_read_line_low(parser)
     232              : 
     233              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     234              : 
     235              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'parser_read_line_low'
     236              : 
     237              :       INTEGER                                            :: handle, iline, imark, islen, istat, &
     238              :                                                             last_buffered_line_number
     239              :       LOGICAL                                            :: non_white_found, &
     240              :                                                             this_line_is_white_or_comment
     241              : 
     242        98393 :       CALL timeset(routineN, handle)
     243              : 
     244     98491393 :       parser%buffer%input_lines = ""
     245        98393 :       IF (parser%para_env%is_source()) THEN
     246        51266 :          iline = 0
     247        51266 :          istat = 0
     248        51266 :          parser%buffer%buffer_id = parser%buffer%buffer_id + 1
     249        51266 :          parser%buffer%present_line_number = 0
     250        51266 :          parser%buffer%last_line_number = parser%buffer%size
     251        51266 :          last_buffered_line_number = parser%buffer%input_line_numbers(parser%buffer%size)
     252     37070904 :          DO WHILE (iline /= parser%buffer%size)
     253              :             ! Increment counters by 1
     254     37041388 :             iline = iline + 1
     255     37041388 :             last_buffered_line_number = last_buffered_line_number + 1
     256              : 
     257              :             ! Try to read the next line from file
     258     37041388 :             parser%buffer%input_line_numbers(iline) = last_buffered_line_number
     259     37041388 :             READ (UNIT=parser%input_unit, FMT="(A)", IOSTAT=istat) parser%buffer%input_lines(iline)
     260              : 
     261              :             ! Pre-processing steps:
     262              :             ! 1. Expand variables 2. Process directives and read next line.
     263              :             ! On read failure try to go back from included file to previous i/o-stream.
     264     37041388 :             IF (istat == 0) THEN
     265     37019043 :                islen = LEN_TRIM(parser%buffer%input_lines(iline))
     266     37019043 :                this_line_is_white_or_comment = is_comment_line(parser, parser%buffer%input_lines(iline))
     267     37019043 :                IF (.NOT. this_line_is_white_or_comment .AND. parser%apply_preprocessing) THEN
     268     30883842 :                   imark = INDEX(parser%buffer%input_lines(iline) (1:islen), "$")
     269     30883842 :                   IF (imark /= 0) THEN
     270              :                      CALL inpp_expand_variables(parser%inpp, parser%buffer%input_lines(iline), &
     271         6338 :                                                 parser%input_file_name, parser%buffer%input_line_numbers(iline))
     272         6338 :                      islen = LEN_TRIM(parser%buffer%input_lines(iline))
     273              :                   END IF
     274     30883842 :                   imark = INDEX(parser%buffer%input_lines(iline) (1:islen), "@")
     275     30883842 :                   IF (imark /= 0) THEN
     276              :                      CALL inpp_process_directive(parser%inpp, parser%buffer%input_lines(iline), &
     277              :                                                  parser%input_file_name, parser%buffer%input_line_numbers(iline), &
     278        10591 :                                                  parser%input_unit)
     279        10591 :                      islen = LEN_TRIM(parser%buffer%input_lines(iline))
     280              :                      ! Handle index and cycle
     281        10591 :                      last_buffered_line_number = 0
     282        10591 :                      iline = iline - 1
     283        10591 :                      CYCLE
     284              :                   END IF
     285              : 
     286              :                   ! after preprocessor parsing could the line be empty again
     287     30873251 :                   this_line_is_white_or_comment = is_comment_line(parser, parser%buffer%input_lines(iline))
     288              :                END IF
     289        22345 :             ELSE IF (istat < 0) THEN ! handle EOF
     290        22345 :                IF (parser%inpp%io_stack_level > 0) THEN
     291              :                   ! We were reading from an included file. Go back one level.
     292              :                   CALL inpp_end_include(parser%inpp, parser%input_file_name, &
     293          595 :                                         parser%buffer%input_line_numbers(iline), parser%input_unit)
     294              :                   ! Handle index and cycle
     295          595 :                   last_buffered_line_number = parser%buffer%input_line_numbers(iline)
     296          595 :                   iline = iline - 1
     297          595 :                   CYCLE
     298              :                END IF
     299              :             END IF
     300              : 
     301              :             ! Saving persisting read errors
     302     37030202 :             IF (istat /= 0) THEN
     303        21750 :                parser%buffer%istat = istat
     304        21750 :                parser%buffer%last_line_number = iline
     305     19125188 :                parser%buffer%input_line_numbers(iline:) = 0
     306     19125188 :                parser%buffer%input_lines(iline:) = ""
     307              :                EXIT
     308              :             END IF
     309              : 
     310              :             ! Pre-processing and error checking done. Ready for parsing.
     311     37008452 :             IF (.NOT. parser%parse_white_lines) THEN
     312     36786558 :                non_white_found = .NOT. this_line_is_white_or_comment
     313              :             ELSE
     314              :                non_white_found = .TRUE.
     315              :             END IF
     316     37037968 :             IF (.NOT. non_white_found) THEN
     317      4845890 :                iline = iline - 1
     318      4845890 :                last_buffered_line_number = last_buffered_line_number - 1
     319              :             END IF
     320              :          END DO
     321              :       END IF
     322              :       ! Broadcast buffer informations
     323        98393 :       CALL broadcast_input_information(parser)
     324              : 
     325        98393 :       CALL timestop(handle)
     326              : 
     327        98393 :    END SUBROUTINE parser_read_line_low
     328              : 
     329              : ! **************************************************************************************************
     330              : !> \brief   Broadcast the input information.
     331              : !> \param parser ...
     332              : !> \date    02.03.2001
     333              : !> \author  Matthias Krack (MK)
     334              : !> \note 08.2008 [tlaino] - Teodoro Laino UZH : updated for buffer
     335              : ! **************************************************************************************************
     336        98393 :    SUBROUTINE broadcast_input_information(parser)
     337              : 
     338              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     339              : 
     340              :       CHARACTER(len=*), PARAMETER :: routineN = 'broadcast_input_information'
     341              : 
     342              :       INTEGER                                            :: handle
     343              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     344              : 
     345        98393 :       CALL timeset(routineN, handle)
     346              : 
     347        98393 :       para_env => parser%para_env
     348        98393 :       IF (para_env%num_pe > 1) THEN
     349        94304 :          CALL para_env%bcast(parser%buffer%buffer_id)
     350        94304 :          CALL para_env%bcast(parser%buffer%present_line_number)
     351        94304 :          CALL para_env%bcast(parser%buffer%last_line_number)
     352        94304 :          CALL para_env%bcast(parser%buffer%istat)
     353    188702304 :          CALL para_env%bcast(parser%buffer%input_line_numbers)
     354    188702304 :          CALL para_env%bcast(parser%buffer%input_lines)
     355              :       END IF
     356              : 
     357        98393 :       CALL timestop(handle)
     358              : 
     359        98393 :    END SUBROUTINE broadcast_input_information
     360              : 
     361              : ! **************************************************************************************************
     362              : !> \brief returns .true. if the line is a comment line or an empty line
     363              : !> \param parser ...
     364              : !> \param line ...
     365              : !> \return ...
     366              : !> \par History
     367              : !>      03.2009 [tlaino] - Teodoro Laino
     368              : ! **************************************************************************************************
     369     67892294 :    ELEMENTAL FUNCTION is_comment_line(parser, line) RESULT(resval)
     370              : 
     371              :       TYPE(cp_parser_type), INTENT(IN)                   :: parser
     372              :       CHARACTER(LEN=*), INTENT(IN)                       :: line
     373              :       LOGICAL                                            :: resval
     374              : 
     375              :       CHARACTER(LEN=1)                                   :: thischar
     376              :       INTEGER                                            :: icol
     377              : 
     378     67892294 :       resval = .TRUE.
     379   1237136053 :       DO icol = 1, LEN(line)
     380   1236828055 :          thischar = line(icol:icol)
     381   1237136053 :          IF (.NOT. is_whitespace(thischar)) THEN
     382     67584296 :             IF (.NOT. is_comment(parser, thischar)) resval = .FALSE.
     383              :             EXIT
     384              :          END IF
     385              :       END DO
     386              : 
     387     67892294 :    END FUNCTION is_comment_line
     388              : 
     389              : ! **************************************************************************************************
     390              : !> \brief returns .true. if the character passed is a comment character
     391              : !> \param parser ...
     392              : !> \param testchar ...
     393              : !> \return ...
     394              : !> \par History
     395              : !>      02.2008 created, AK
     396              : !> \author AK
     397              : ! **************************************************************************************************
     398    133459116 :    ELEMENTAL FUNCTION is_comment(parser, testchar) RESULT(resval)
     399              : 
     400              :       TYPE(cp_parser_type), INTENT(IN)                   :: parser
     401              :       CHARACTER(LEN=1), INTENT(IN)                       :: testchar
     402              :       LOGICAL                                            :: resval
     403              : 
     404    133459116 :       resval = .FALSE.
     405              :       ! We are in a private function, and parser has been tested before...
     406    391832697 :       IF (ANY(parser%comment_character == testchar)) resval = .TRUE.
     407              : 
     408    133459116 :    END FUNCTION is_comment
     409              : 
     410              : ! **************************************************************************************************
     411              : !> \brief   Read the next input line and broadcast the input information.
     412              : !>          Skip (nline-1) lines and skip also all comment lines.
     413              : !> \param parser ...
     414              : !> \param nline ...
     415              : !> \param at_end ...
     416              : !> \date    22.11.1999
     417              : !> \author  Matthias Krack (MK)
     418              : !> \version 1.0
     419              : ! **************************************************************************************************
     420     51635655 :    SUBROUTINE parser_get_next_line(parser, nline, at_end)
     421              : 
     422              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     423              :       INTEGER, INTENT(IN)                                :: nline
     424              :       LOGICAL, INTENT(out), OPTIONAL                     :: at_end
     425              : 
     426              :       LOGICAL                                            :: my_at_end
     427              : 
     428     51635655 :       IF (nline > 0) THEN
     429     46231137 :          CALL parser_read_line(parser, nline, at_end=my_at_end)
     430     46231137 :          IF (PRESENT(at_end)) THEN
     431     45315730 :             at_end = my_at_end
     432              :          ELSE
     433       915407 :             IF (my_at_end) THEN
     434            0 :                CPABORT("Unexpected EOF"//TRIM(parser_location(parser)))
     435              :             END IF
     436              :          END IF
     437      5404518 :       ELSE IF (PRESENT(at_end)) THEN
     438      5404236 :          at_end = .FALSE.
     439              :       END IF
     440              : 
     441     51635655 :    END SUBROUTINE parser_get_next_line
     442              : 
     443              : ! **************************************************************************************************
     444              : !> \brief   Skips the whitespaces
     445              : !> \param parser ...
     446              : !> \date    02.03.2001
     447              : !> \author  Matthias Krack (MK)
     448              : !> \version 1.0
     449              : ! **************************************************************************************************
     450        24897 :    SUBROUTINE parser_skip_space(parser)
     451              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     452              : 
     453              :       INTEGER                                            :: i
     454              :       LOGICAL                                            :: at_end
     455              : 
     456              :       ! Variable input string length (automatic search)
     457              : 
     458              :       ! Check for EOF
     459        24897 :       IF (parser%icol == -1) THEN
     460            0 :          parser%icol1 = 1
     461            0 :          parser%icol2 = -1
     462            0 :          RETURN
     463              :       END IF
     464              : 
     465              :       ! Search for the beginning of the next input string
     466              :       outer_loop: DO
     467              : 
     468              :          ! Increment the column counter
     469        25591 :          parser%icol = parser%icol + 1
     470              : 
     471              :          ! Quick return, if the end of line is found
     472        25591 :          IF ((parser%icol > LEN_TRIM(parser%input_line)) .OR. &
     473              :              is_comment(parser, parser%input_line(parser%icol:parser%icol))) THEN
     474           76 :             parser%icol1 = 1
     475           76 :             parser%icol2 = -1
     476           76 :             RETURN
     477              :          END IF
     478              : 
     479              :          ! Ignore all white space
     480        25515 :          IF (.NOT. is_whitespace(parser%input_line(parser%icol:parser%icol))) THEN
     481              :             ! Check for input line continuation
     482        24821 :             IF (parser%input_line(parser%icol:parser%icol) == parser%continuation_character) THEN
     483            0 :                inner_loop: DO i = parser%icol + 1, LEN_TRIM(parser%input_line)
     484            0 :                   IF (is_whitespace(parser%input_line(i:i))) CYCLE inner_loop
     485            0 :                   IF (is_comment(parser, parser%input_line(i:i))) THEN
     486              :                      EXIT inner_loop
     487              :                   ELSE
     488            0 :                      parser%icol1 = i
     489            0 :                      parser%icol2 = LEN_TRIM(parser%input_line)
     490              :                      CALL cp_abort(__LOCATION__, &
     491              :                                    "Found a non-blank token which is not a comment after the line continuation character '"// &
     492            0 :                                    parser%continuation_character//"'"//TRIM(parser_location(parser)))
     493              :                   END IF
     494              :                END DO inner_loop
     495            0 :                CALL parser_get_next_line(parser, 1, at_end=at_end)
     496            0 :                IF (at_end) THEN
     497              :                   CALL cp_abort(__LOCATION__, &
     498              :                                 "Unexpected end of file (EOF) found after line continuation"// &
     499            0 :                                 TRIM(parser_location(parser)))
     500              :                END IF
     501            0 :                parser%icol = 0
     502            0 :                CYCLE outer_loop
     503              :             ELSE
     504        24821 :                parser%icol = parser%icol - 1
     505        24821 :                parser%icol1 = parser%icol
     506        24821 :                parser%icol2 = parser%icol
     507        24821 :                RETURN
     508              :             END IF
     509              :          END IF
     510              : 
     511              :       END DO outer_loop
     512              : 
     513              :    END SUBROUTINE parser_skip_space
     514              : 
     515              : ! **************************************************************************************************
     516              : !> \brief   Get the next input string from the input line.
     517              : !> \param parser ...
     518              : !> \param string_length ...
     519              : !> \date    19.02.2001
     520              : !> \author  Matthias Krack (MK)
     521              : !> \version 1.0
     522              : !> \notes   -) this function MUST be private in this module!
     523              : ! **************************************************************************************************
     524     11670830 :    SUBROUTINE parser_next_token(parser, string_length)
     525              : 
     526              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     527              :       INTEGER, INTENT(IN), OPTIONAL                      :: string_length
     528              : 
     529              :       CHARACTER(LEN=1)                                   :: token
     530              :       INTEGER                                            :: i, len_trim_inputline, length
     531              :       LOGICAL                                            :: at_end
     532              : 
     533     11670830 :       IF (PRESENT(string_length)) THEN
     534       302567 :          IF (string_length > max_line_length) THEN
     535            0 :             CPABORT("string length > max_line_length")
     536              :          ELSE
     537              :             length = string_length
     538              :          END IF
     539              :       ELSE
     540              :          length = 0
     541              :       END IF
     542              : 
     543              :       ! Precompute trimmed line length
     544     11670830 :       len_trim_inputline = LEN_TRIM(parser%input_line)
     545              : 
     546     11670830 :       IF (length > 0) THEN
     547              : 
     548              :          ! Read input string of fixed length (single line)
     549              : 
     550              :          ! Check for EOF
     551       302567 :          IF (parser%icol == -1) THEN
     552            0 :             CPABORT("Unexpectetly reached EOF"//TRIM(parser_location(parser)))
     553              :          END IF
     554              : 
     555       302567 :          length = MIN(len_trim_inputline - parser%icol1 + 1, length)
     556       302567 :          parser%icol1 = parser%icol + 1
     557       302567 :          parser%icol2 = parser%icol + length
     558       302567 :          i = INDEX(parser%input_line(parser%icol1:parser%icol2), parser%quote_character)
     559       302567 :          IF (i > 0) parser%icol2 = parser%icol + i
     560       302567 :          parser%icol = parser%icol2
     561              : 
     562              :       ELSE
     563              : 
     564              :          ! Variable input string length (automatic multi-line search)
     565              : 
     566              :          ! Check for EOF
     567     11368263 :          IF (parser%icol == -1) THEN
     568            0 :             parser%icol1 = 1
     569            0 :             parser%icol2 = -1
     570      1697194 :             RETURN
     571              :          END IF
     572              : 
     573              :          ! Search for the beginning of the next input string
     574              :          outer_loop1: DO
     575              : 
     576              :             ! Increment the column counter
     577     34232463 :             parser%icol = parser%icol + 1
     578              : 
     579              :             ! Quick return, if the end of line is found
     580     34232463 :             IF (parser%icol > len_trim_inputline) THEN
     581      1651604 :                parser%icol1 = 1
     582      1651604 :                parser%icol2 = -1
     583      1651604 :                RETURN
     584              :             END IF
     585              : 
     586     32580859 :             token = parser%input_line(parser%icol:parser%icol)
     587              : 
     588     32580859 :             IF (is_whitespace(token)) THEN
     589              :                ! Ignore white space
     590              :                CYCLE outer_loop1
     591      9835907 :             ELSE IF (is_comment(parser, token)) THEN
     592        34578 :                parser%icol1 = 1
     593        34578 :                parser%icol2 = -1
     594        34578 :                parser%first_separator = .TRUE.
     595        34578 :                RETURN
     596      9801329 :             ELSE IF (token == parser%quote_character) THEN
     597              :                ! Read quoted string
     598        11012 :                parser%icol1 = parser%icol + 1
     599        11012 :                parser%icol2 = parser%icol + INDEX(parser%input_line(parser%icol1:), parser%quote_character)
     600        11012 :                IF (parser%icol2 == parser%icol) THEN
     601            0 :                   parser%icol1 = parser%icol
     602            0 :                   parser%icol2 = parser%icol
     603              :                   CALL cp_abort(__LOCATION__, &
     604            0 :                                 "Unmatched quotation mark found"//TRIM(parser_location(parser)))
     605              :                ELSE
     606        11012 :                   parser%icol = parser%icol2
     607        11012 :                   parser%icol2 = parser%icol2 - 1
     608        11012 :                   parser%first_separator = .TRUE.
     609        11012 :                   RETURN
     610              :                END IF
     611      9790317 :             ELSE IF (token == parser%continuation_character) THEN
     612              :                ! Check for input line continuation
     613       118784 :                inner_loop1: DO i = parser%icol + 1, len_trim_inputline
     614       118784 :                   IF (is_whitespace(parser%input_line(i:i))) THEN
     615              :                      CYCLE inner_loop1
     616            0 :                   ELSE IF (is_comment(parser, parser%input_line(i:i))) THEN
     617              :                      EXIT inner_loop1
     618              :                   ELSE
     619            0 :                      parser%icol1 = i
     620            0 :                      parser%icol2 = len_trim_inputline
     621              :                      CALL cp_abort(__LOCATION__, &
     622              :                                    "Found a non-blank token which is not a comment after the line continuation character '"// &
     623            0 :                                    parser%continuation_character//"'"//TRIM(parser_location(parser)))
     624              :                   END IF
     625              :                END DO inner_loop1
     626       118784 :                CALL parser_get_next_line(parser, 1, at_end=at_end)
     627       118784 :                IF (at_end) THEN
     628              :                   CALL cp_abort(__LOCATION__, &
     629            0 :                                 "Unexpected end of file (EOF) found after line continuation"//TRIM(parser_location(parser)))
     630              :                END IF
     631       118784 :                len_trim_inputline = LEN_TRIM(parser%input_line)
     632       118784 :                CYCLE outer_loop1
     633      9671533 :             ELSE IF (INDEX(parser%separators, token) > 0) THEN
     634          464 :                IF (parser%first_separator) THEN
     635          464 :                   parser%first_separator = .FALSE.
     636          464 :                   CYCLE outer_loop1
     637              :                ELSE
     638            0 :                   parser%icol1 = parser%icol
     639            0 :                   parser%icol2 = parser%icol
     640              :                   CALL cp_abort(__LOCATION__, &
     641              :                                 "Unexpected separator token '"//token// &
     642            0 :                                 "' found"//TRIM(parser_location(parser)))
     643              :                END IF
     644              :             ELSE
     645      9671069 :                parser%icol1 = parser%icol
     646      9671069 :                parser%first_separator = .TRUE.
     647      9671069 :                EXIT outer_loop1
     648              :             END IF
     649              : 
     650              :          END DO outer_loop1
     651              : 
     652              :          ! Search for the end of the next input string
     653              :          outer_loop2: DO
     654     65098013 :             parser%icol = parser%icol + 1
     655     65098013 :             IF (parser%icol > len_trim_inputline) EXIT outer_loop2
     656     62601513 :             token = parser%input_line(parser%icol:parser%icol)
     657     62601513 :             IF (is_whitespace(token) .OR. is_comment(parser, token) .OR. &
     658      9084713 :                 (token == parser%continuation_character)) THEN
     659              :                EXIT outer_loop2
     660     56013300 :             ELSE IF (INDEX(parser%separators, token) > 0) THEN
     661       586356 :                parser%first_separator = .FALSE.
     662       586356 :                EXIT outer_loop2
     663              :             END IF
     664              :          END DO outer_loop2
     665              : 
     666      9671069 :          parser%icol2 = parser%icol - 1
     667              : 
     668      9671069 :          IF (parser%input_line(parser%icol:parser%icol) == &
     669           14 :              parser%continuation_character) parser%icol = parser%icol2
     670              : 
     671              :       END IF
     672              : 
     673              :    END SUBROUTINE parser_next_token
     674              : 
     675              : ! **************************************************************************************************
     676              : !> \brief   Test next input object.
     677              : !>           -  test_result : "EOL": End of line
     678              : !>           -  test_result : "EOS": End of section
     679              : !>           -  test_result : "FLT": Floating point number
     680              : !>           -  test_result : "INT": Integer number
     681              : !>           -  test_result : "STR": String
     682              : !> \param parser ...
     683              : !> \param string_length ...
     684              : !> \return ...
     685              : !> \date    23.11.1999
     686              : !> \author  Matthias Krack (MK)
     687              : !> \note - 08.2008 [tlaino] - Teodoro Laino UZH : updated for buffer
     688              : !>          - Major rewrite to parse also (multiple) products of integer or
     689              : !>            floating point numbers (23.11.2012,MK)
     690              : ! **************************************************************************************************
     691      4788442 :    FUNCTION parser_test_next_token(parser, string_length) RESULT(test_result)
     692              : 
     693              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     694              :       INTEGER, INTENT(IN), OPTIONAL                      :: string_length
     695              :       CHARACTER(LEN=3)                                   :: test_result
     696              : 
     697              :       CHARACTER(LEN=max_line_length)                     :: error_message, string
     698              :       INTEGER                                            :: iz, n
     699              :       LOGICAL                                            :: ilist_in_use
     700              :       REAL(KIND=dp)                                      :: fz
     701              : 
     702      4788442 :       test_result = ""
     703              : 
     704              :       ! Store current status
     705      4788442 :       CALL parser_store_status(parser)
     706              : 
     707              :       ! Handle possible list of integers
     708      4788442 :       ilist_in_use = parser%ilist%in_use .AND. (parser%ilist%ipresent < parser%ilist%iend)
     709              :       IF (ilist_in_use) THEN
     710        14794 :          test_result = "INT"
     711        14794 :          CALL parser_retrieve_status(parser)
     712      3878493 :          RETURN
     713              :       END IF
     714              : 
     715              :       ! Otherwise continue normally
     716      4773648 :       IF (PRESENT(string_length)) THEN
     717            0 :          CALL parser_next_token(parser, string_length=string_length)
     718              :       ELSE
     719      4773648 :          CALL parser_next_token(parser)
     720              :       END IF
     721              : 
     722              :       ! End of line
     723      4773648 :       IF (parser%icol1 > parser%icol2) THEN
     724      1686206 :          test_result = "EOL"
     725      1686206 :          CALL parser_retrieve_status(parser)
     726      1686206 :          RETURN
     727              :       END IF
     728              : 
     729      3087442 :       string = parser%input_line(parser%icol1:parser%icol2)
     730      3087442 :       n = LEN_TRIM(string)
     731              : 
     732      3087442 :       IF (n == 0) THEN
     733            0 :          test_result = "STR"
     734            0 :          CALL parser_retrieve_status(parser)
     735            0 :          RETURN
     736              :       END IF
     737              : 
     738              :       ! Check for end section string
     739      3087442 :       IF (string(1:n) == parser%end_section) THEN
     740            0 :          test_result = "EOS"
     741            0 :          CALL parser_retrieve_status(parser)
     742            0 :          RETURN
     743              :       END IF
     744              : 
     745              :       ! Check for integer object
     746      3087442 :       error_message = ""
     747      3087442 :       CALL read_integer_object(string(1:n), iz, error_message)
     748      3087442 :       IF (LEN_TRIM(error_message) == 0) THEN
     749      1322488 :          test_result = "INT"
     750      1322488 :          CALL parser_retrieve_status(parser)
     751      1322488 :          RETURN
     752              :       END IF
     753              : 
     754              :       ! Check for floating point object
     755      1764954 :       error_message = ""
     756      1764954 :       CALL read_float_object(string(1:n), fz, error_message)
     757      1764954 :       IF (LEN_TRIM(error_message) == 0) THEN
     758       855005 :          test_result = "FLT"
     759       855005 :          CALL parser_retrieve_status(parser)
     760       855005 :          RETURN
     761              :       END IF
     762              : 
     763       909949 :       test_result = "STR"
     764       909949 :       CALL parser_retrieve_status(parser)
     765              : 
     766              :    END FUNCTION parser_test_next_token
     767              : 
     768              : ! **************************************************************************************************
     769              : !> \brief   Search a string pattern in a file defined by its logical unit
     770              : !>          number "unit". A case sensitive search is performed, if
     771              : !>          ignore_case is .FALSE..
     772              : !>          begin_line: give back the parser at the beginning of the line
     773              : !>          matching the search
     774              : !> \param parser ...
     775              : !> \param string ...
     776              : !> \param ignore_case ...
     777              : !> \param found ...
     778              : !> \param line ...
     779              : !> \param begin_line ...
     780              : !> \param search_from_begin_of_file ...
     781              : !> \date    05.10.1999
     782              : !> \author  MK
     783              : !> \note 08.2008 [tlaino] - Teodoro Laino UZH : updated for buffer
     784              : ! **************************************************************************************************
     785       161491 :    SUBROUTINE parser_search_string(parser, string, ignore_case, found, line, begin_line, &
     786              :                                    search_from_begin_of_file)
     787              : 
     788              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     789              :       CHARACTER(LEN=*), INTENT(IN)                       :: string
     790              :       LOGICAL, INTENT(IN)                                :: ignore_case
     791              :       LOGICAL, INTENT(OUT)                               :: found
     792              :       CHARACTER(LEN=*), INTENT(OUT), OPTIONAL            :: line
     793              :       LOGICAL, INTENT(IN), OPTIONAL                      :: begin_line, search_from_begin_of_file
     794              : 
     795       161491 :       CHARACTER(LEN=LEN(string))                         :: pattern
     796              :       CHARACTER(LEN=max_line_length+1)                   :: current_line
     797              :       INTEGER                                            :: ipattern
     798              :       LOGICAL                                            :: at_end, begin, do_reset
     799              : 
     800       161491 :       found = .FALSE.
     801       161491 :       begin = .FALSE.
     802       161491 :       do_reset = .FALSE.
     803        67076 :       IF (PRESENT(begin_line)) begin = begin_line
     804       161491 :       IF (PRESENT(search_from_begin_of_file)) do_reset = search_from_begin_of_file
     805       161491 :       IF (PRESENT(line)) line = ""
     806              : 
     807              :       ! Search for string pattern
     808       161491 :       pattern = string
     809       161491 :       IF (ignore_case) CALL uppercase(pattern)
     810       161491 :       IF (do_reset) CALL parser_reset(parser)
     811              :       DO
     812              :          ! This call is buffered.. so should not represent any bottleneck
     813     42271557 :          CALL parser_get_next_line(parser, 1, at_end=at_end)
     814              : 
     815              :          ! Exit loop, if the end of file is reached
     816     42271557 :          IF (at_end) EXIT
     817              : 
     818              :          ! Check the current line for string pattern
     819     42262167 :          current_line = parser%input_line
     820     42262167 :          IF (ignore_case) CALL uppercase(current_line)
     821     42262167 :          ipattern = INDEX(current_line, TRIM(pattern))
     822              : 
     823     42271557 :          IF (ipattern > 0) THEN
     824       152101 :             found = .TRUE.
     825       152101 :             parser%icol = ipattern - 1
     826       152101 :             IF (PRESENT(line)) THEN
     827        93030 :                IF (LEN(line) < LEN_TRIM(parser%input_line)) THEN
     828              :                   CALL cp_warn(__LOCATION__, &
     829              :                                "The returned input line has more than "// &
     830              :                                TRIM(ADJUSTL(cp_to_string(LEN(line))))// &
     831              :                                " characters and is therefore too long to fit in the "// &
     832              :                                "specified variable"// &
     833            0 :                                TRIM(parser_location(parser)))
     834              :                END IF
     835              :             END IF
     836              :             EXIT
     837              :          END IF
     838              : 
     839              :       END DO
     840              : 
     841       161491 :       IF (found) THEN
     842       152101 :          IF (begin) parser%icol = 0
     843              :       END IF
     844              : 
     845       161491 :       IF (found) THEN
     846       152101 :          IF (PRESENT(line)) line = parser%input_line
     847       152101 :          IF (.NOT. begin) CALL parser_next_token(parser)
     848              :       END IF
     849              : 
     850       161491 :    END SUBROUTINE parser_search_string
     851              : 
     852              : ! **************************************************************************************************
     853              : !> \brief   Check, if the string object contains an object of type integer.
     854              : !> \param string ...
     855              : !> \return ...
     856              : !> \date    22.11.1999
     857              : !> \author  Matthias Krack (MK)
     858              : !> \version 1.0
     859              : !> \note - Introducing the possibility to parse a range of integers INT1..INT2
     860              : !>            Teodoro Laino [tlaino] - University of Zurich - 08.2008
     861              : !>          - Parse also a product of integer numbers (23.11.2012,MK)
     862              : ! **************************************************************************************************
     863      1833656 :    ELEMENTAL FUNCTION integer_object(string) RESULT(contains_integer_object)
     864              : 
     865              :       CHARACTER(LEN=*), INTENT(IN)                       :: string
     866              :       LOGICAL                                            :: contains_integer_object
     867              : 
     868              :       INTEGER                                            :: i, idots, istar, n
     869              : 
     870      1833656 :       contains_integer_object = .TRUE.
     871      1833656 :       n = LEN_TRIM(string)
     872              : 
     873      1833656 :       IF (n == 0) THEN
     874      1833656 :          contains_integer_object = .FALSE.
     875              :          RETURN
     876              :       END IF
     877              : 
     878      1833656 :       idots = INDEX(string(1:n), "..")
     879      1833656 :       istar = INDEX(string(1:n), "*")
     880              : 
     881      1833656 :       IF (idots /= 0) THEN
     882              :          contains_integer_object = is_integer(string(1:idots - 1)) .AND. &
     883        15456 :                                    is_integer(string(idots + 2:n))
     884      1818200 :       ELSE IF (istar /= 0) THEN
     885              :          i = 1
     886          224 :          DO WHILE (istar /= 0)
     887          114 :             IF (.NOT. is_integer(string(i:i + istar - 2))) THEN
     888      1833656 :                contains_integer_object = .FALSE.
     889              :                RETURN
     890              :             END IF
     891          114 :             i = i + istar
     892          224 :             istar = INDEX(string(i:n), "*")
     893              :          END DO
     894          110 :          contains_integer_object = is_integer(string(i:n))
     895              :       ELSE
     896      1818090 :          contains_integer_object = is_integer(string(1:n))
     897              :       END IF
     898              : 
     899              :    END FUNCTION integer_object
     900              : 
     901              : ! **************************************************************************************************
     902              : !> \brief ...
     903              : !> \param string ...
     904              : !> \return ...
     905              : ! **************************************************************************************************
     906      1849226 :    ELEMENTAL FUNCTION is_integer(string) RESULT(check)
     907              : 
     908              :       CHARACTER(LEN=*), INTENT(IN)                       :: string
     909              :       LOGICAL                                            :: check
     910              : 
     911              :       INTEGER                                            :: i, n
     912              : 
     913      1849226 :       check = .TRUE.
     914      1849226 :       n = LEN_TRIM(string)
     915              : 
     916      1849226 :       IF (n == 0) THEN
     917      1849226 :          check = .FALSE.
     918              :          RETURN
     919              :       END IF
     920              : 
     921      1849226 :       IF ((INDEX("+-", string(1:1)) > 0) .AND. (n == 1)) THEN
     922      1849226 :          check = .FALSE.
     923              :          RETURN
     924              :       END IF
     925              : 
     926      1849226 :       IF (INDEX("+-0123456789", string(1:1)) == 0) THEN
     927      1849226 :          check = .FALSE.
     928              :          RETURN
     929              :       END IF
     930              : 
     931      5156678 :       DO i = 2, n
     932      5156678 :          IF (INDEX("0123456789", string(i:i)) == 0) THEN
     933      1849226 :             check = .FALSE.
     934              :             RETURN
     935              :          END IF
     936              :       END DO
     937              : 
     938              :    END FUNCTION is_integer
     939              : 
     940              : ! **************************************************************************************************
     941              : !> \brief   Read an integer number.
     942              : !> \param parser ...
     943              : !> \param object ...
     944              : !> \param newline ...
     945              : !> \param skip_lines ...
     946              : !> \param string_length ...
     947              : !> \param at_end ...
     948              : !> \date    22.11.1999
     949              : !> \author  Matthias Krack (MK)
     950              : !> \version 1.0
     951              : ! **************************************************************************************************
     952      3667312 :    SUBROUTINE parser_get_integer(parser, object, newline, skip_lines, &
     953              :                                  string_length, at_end)
     954              : 
     955              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     956              :       INTEGER, INTENT(OUT)                               :: object
     957              :       LOGICAL, INTENT(IN), OPTIONAL                      :: newline
     958              :       INTEGER, INTENT(IN), OPTIONAL                      :: skip_lines, string_length
     959              :       LOGICAL, INTENT(out), OPTIONAL                     :: at_end
     960              : 
     961              :       CHARACTER(LEN=max_line_length)                     :: error_message
     962              :       INTEGER                                            :: nline
     963              :       LOGICAL                                            :: my_at_end
     964              : 
     965      1833656 :       IF (PRESENT(skip_lines)) THEN
     966            0 :          nline = skip_lines
     967              :       ELSE
     968      1833656 :          nline = 0
     969              :       END IF
     970              : 
     971      1833656 :       IF (PRESENT(newline)) THEN
     972        65709 :          IF (newline) nline = nline + 1
     973              :       END IF
     974              : 
     975      1833656 :       CALL parser_get_next_line(parser, nline, at_end=my_at_end)
     976      1833656 :       IF (PRESENT(at_end)) THEN
     977            0 :          at_end = my_at_end
     978            0 :          IF (my_at_end) RETURN
     979      1833656 :       ELSE IF (my_at_end) THEN
     980            0 :          CPABORT("Unexpected EOF"//TRIM(parser_location(parser)))
     981              :       END IF
     982              : 
     983      1833656 :       IF (parser%ilist%in_use) THEN
     984        14802 :          CALL ilist_update(parser%ilist)
     985              :       ELSE
     986      1818854 :          IF (PRESENT(string_length)) THEN
     987            0 :             CALL parser_next_token(parser, string_length=string_length)
     988              :          ELSE
     989      1818854 :             CALL parser_next_token(parser)
     990              :          END IF
     991      1818854 :          IF (parser%icol1 > parser%icol2) THEN
     992            0 :             parser%icol1 = parser%icol
     993            0 :             parser%icol2 = parser%icol
     994              :             CALL cp_abort(__LOCATION__, &
     995              :                           "An integer type object was expected, found end of line"// &
     996            0 :                           TRIM(parser_location(parser)))
     997              :          END IF
     998              :          ! Checks for possible lists of integers
     999      1818854 :          IF (INDEX(parser%input_line(parser%icol1:parser%icol2), "..") /= 0) THEN
    1000          654 :             CALL ilist_setup(parser%ilist, parser%input_line(parser%icol1:parser%icol2))
    1001              :          END IF
    1002              :       END IF
    1003              : 
    1004      1833656 :       IF (integer_object(TRIM(ADJUSTL(parser%input_line(parser%icol1:parser%icol2))))) THEN
    1005      1833656 :          IF (parser%ilist%in_use) THEN
    1006        15456 :             object = parser%ilist%ipresent
    1007        15456 :             CALL ilist_reset(parser%ilist)
    1008              :          ELSE
    1009      1818200 :             CALL read_integer_object(parser%input_line(parser%icol1:parser%icol2), object, error_message)
    1010      1818200 :             IF (LEN_TRIM(error_message) > 0) THEN
    1011            0 :                CPABORT(TRIM(error_message)//TRIM(parser_location(parser)))
    1012              :             END IF
    1013              :          END IF
    1014              :       ELSE
    1015              :          CALL cp_abort(__LOCATION__, &
    1016              :                        "An integer type object was expected, found <"// &
    1017              :                        parser%input_line(parser%icol1:parser%icol2)//">"// &
    1018            0 :                        TRIM(parser_location(parser)))
    1019              :       END IF
    1020              : 
    1021              :    END SUBROUTINE parser_get_integer
    1022              : 
    1023              : ! **************************************************************************************************
    1024              : !> \brief   Read a string representing logical object.
    1025              : !> \param parser ...
    1026              : !> \param object ...
    1027              : !> \param newline ...
    1028              : !> \param skip_lines ...
    1029              : !> \param string_length ...
    1030              : !> \param at_end ...
    1031              : !> \date    01.04.2003
    1032              : !> \par History
    1033              : !>      - New version (08.07.2003,MK)
    1034              : !> \author  FM
    1035              : !> \version 1.0
    1036              : ! **************************************************************************************************
    1037        52204 :    SUBROUTINE parser_get_logical(parser, object, newline, skip_lines, &
    1038              :                                  string_length, at_end)
    1039              : 
    1040              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1041              :       LOGICAL, INTENT(OUT)                               :: object
    1042              :       LOGICAL, INTENT(IN), OPTIONAL                      :: newline
    1043              :       INTEGER, INTENT(IN), OPTIONAL                      :: skip_lines, string_length
    1044              :       LOGICAL, INTENT(out), OPTIONAL                     :: at_end
    1045              : 
    1046              :       CHARACTER(LEN=max_line_length)                     :: input_string
    1047              :       INTEGER                                            :: input_string_length, nline
    1048              :       LOGICAL                                            :: my_at_end
    1049              : 
    1050        26102 :       CPASSERT(.NOT. parser%ilist%in_use)
    1051        26102 :       IF (PRESENT(skip_lines)) THEN
    1052            0 :          nline = skip_lines
    1053              :       ELSE
    1054        26102 :          nline = 0
    1055              :       END IF
    1056              : 
    1057        26102 :       IF (PRESENT(newline)) THEN
    1058            0 :          IF (newline) nline = nline + 1
    1059              :       END IF
    1060              : 
    1061        26102 :       CALL parser_get_next_line(parser, nline, at_end=my_at_end)
    1062        26102 :       IF (PRESENT(at_end)) THEN
    1063            0 :          at_end = my_at_end
    1064            0 :          IF (my_at_end) RETURN
    1065        26102 :       ELSE IF (my_at_end) THEN
    1066            0 :          CPABORT("Unexpected EOF"//TRIM(parser_location(parser)))
    1067              :       END IF
    1068              : 
    1069        26102 :       IF (PRESENT(string_length)) THEN
    1070            0 :          CALL parser_next_token(parser, string_length=string_length)
    1071              :       ELSE
    1072        26102 :          CALL parser_next_token(parser)
    1073              :       END IF
    1074              : 
    1075        26102 :       input_string_length = parser%icol2 - parser%icol1 + 1
    1076              : 
    1077        26102 :       IF (input_string_length == 0) THEN
    1078            0 :          parser%icol1 = parser%icol
    1079            0 :          parser%icol2 = parser%icol
    1080              :          CALL cp_abort(__LOCATION__, &
    1081              :                        "A string representing a logical object was expected, found end of line"// &
    1082            0 :                        TRIM(parser_location(parser)))
    1083              :       ELSE
    1084        26102 :          input_string = ""
    1085        26102 :          input_string(:input_string_length) = parser%input_line(parser%icol1:parser%icol2)
    1086              :       END IF
    1087        26102 :       CALL uppercase(input_string)
    1088              : 
    1089        35389 :       SELECT CASE (TRIM(input_string))
    1090              :       CASE ("0", "F", ".F.", "FALSE", ".FALSE.", "N", "NO", "OFF")
    1091         9287 :          object = .FALSE.
    1092              :       CASE ("1", "T", ".T.", "TRUE", ".TRUE.", "Y", "YES", "ON")
    1093        16815 :          object = .TRUE.
    1094              :       CASE DEFAULT
    1095              :          CALL cp_abort(__LOCATION__, &
    1096              :                        "A string representing a logical object was expected, found <"// &
    1097        26102 :                        TRIM(input_string)//">"//TRIM(parser_location(parser)))
    1098              :       END SELECT
    1099              : 
    1100              :    END SUBROUTINE parser_get_logical
    1101              : 
    1102              : ! **************************************************************************************************
    1103              : !> \brief   Read a floating point number.
    1104              : !> \param parser ...
    1105              : !> \param object ...
    1106              : !> \param newline ...
    1107              : !> \param skip_lines ...
    1108              : !> \param string_length ...
    1109              : !> \param at_end ...
    1110              : !> \date    22.11.1999
    1111              : !> \author  Matthias Krack (MK)
    1112              : !> \version 1.0
    1113              : ! **************************************************************************************************
    1114      3172448 :    SUBROUTINE parser_get_real(parser, object, newline, skip_lines, string_length, &
    1115              :                               at_end)
    1116              : 
    1117              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1118              :       REAL(KIND=dp), INTENT(OUT)                         :: object
    1119              :       LOGICAL, INTENT(IN), OPTIONAL                      :: newline
    1120              :       INTEGER, INTENT(IN), OPTIONAL                      :: skip_lines, string_length
    1121              :       LOGICAL, INTENT(out), OPTIONAL                     :: at_end
    1122              : 
    1123              :       CHARACTER(LEN=max_line_length)                     :: error_message
    1124              :       INTEGER                                            :: nline
    1125              :       LOGICAL                                            :: my_at_end
    1126              : 
    1127      1586224 :       CPASSERT(.NOT. parser%ilist%in_use)
    1128              : 
    1129      1586224 :       IF (PRESENT(skip_lines)) THEN
    1130            0 :          nline = skip_lines
    1131              :       ELSE
    1132      1586224 :          nline = 0
    1133              :       END IF
    1134              : 
    1135      1586224 :       IF (PRESENT(newline)) THEN
    1136       108750 :          IF (newline) nline = nline + 1
    1137              :       END IF
    1138              : 
    1139      1586224 :       CALL parser_get_next_line(parser, nline, at_end=my_at_end)
    1140      1586224 :       IF (PRESENT(at_end)) THEN
    1141            0 :          at_end = my_at_end
    1142            0 :          IF (my_at_end) RETURN
    1143      1586224 :       ELSE IF (my_at_end) THEN
    1144            0 :          CPABORT("Unexpected EOF"//TRIM(parser_location(parser)))
    1145              :       END IF
    1146              : 
    1147      1586224 :       IF (PRESENT(string_length)) THEN
    1148            0 :          CALL parser_next_token(parser, string_length=string_length)
    1149              :       ELSE
    1150      1586224 :          CALL parser_next_token(parser)
    1151              :       END IF
    1152              : 
    1153      1586224 :       IF (parser%icol1 > parser%icol2) THEN
    1154            0 :          parser%icol1 = parser%icol
    1155            0 :          parser%icol2 = parser%icol
    1156              :          CALL cp_abort(__LOCATION__, &
    1157              :                        "A floating point type object was expected, found end of the line"// &
    1158            0 :                        TRIM(parser_location(parser)))
    1159              :       END IF
    1160              : 
    1161              :       ! Possibility to have real numbers described in the input as division between two numbers
    1162      1586224 :       CALL read_float_object(parser%input_line(parser%icol1:parser%icol2), object, error_message)
    1163      1586224 :       IF (LEN_TRIM(error_message) > 0) THEN
    1164            0 :          CPABORT(TRIM(error_message)//TRIM(parser_location(parser)))
    1165              :       END IF
    1166              : 
    1167              :    END SUBROUTINE parser_get_real
    1168              : 
    1169              : ! **************************************************************************************************
    1170              : !> \brief   Read a string.
    1171              : !> \param parser ...
    1172              : !> \param object ...
    1173              : !> \param lower_to_upper ...
    1174              : !> \param newline ...
    1175              : !> \param skip_lines ...
    1176              : !> \param string_length ...
    1177              : !> \param at_end ...
    1178              : !> \param allow_empty Accept explicitly quoted empty strings (missing tokens still fail).
    1179              : !> \date    22.11.1999
    1180              : !> \author  Matthias Krack (MK)
    1181              : !> \version 1.0
    1182              : ! **************************************************************************************************
    1183      6769204 :    SUBROUTINE parser_get_string(parser, object, lower_to_upper, newline, skip_lines, &
    1184              :                                 string_length, at_end, allow_empty)
    1185              : 
    1186              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1187              :       CHARACTER(LEN=*), INTENT(OUT)                      :: object
    1188              :       LOGICAL, INTENT(IN), OPTIONAL                      :: lower_to_upper, newline
    1189              :       INTEGER, INTENT(IN), OPTIONAL                      :: skip_lines, string_length
    1190              :       LOGICAL, INTENT(out), OPTIONAL                     :: at_end
    1191              :       LOGICAL, INTENT(IN), OPTIONAL                      :: allow_empty
    1192              : 
    1193              :       INTEGER                                            :: input_string_length, nline
    1194              :       LOGICAL                                            :: my_at_end
    1195              : 
    1196      3384602 :       object = ""
    1197      3384602 :       CPASSERT(.NOT. parser%ilist%in_use)
    1198      3384602 :       IF (PRESENT(skip_lines)) THEN
    1199            0 :          nline = skip_lines
    1200              :       ELSE
    1201      3384602 :          nline = 0
    1202              :       END IF
    1203              : 
    1204      3384602 :       IF (PRESENT(newline)) THEN
    1205      1512310 :          IF (newline) nline = nline + 1
    1206              :       END IF
    1207              : 
    1208      3384602 :       CALL parser_get_next_line(parser, nline, at_end=my_at_end)
    1209      3384602 :       IF (PRESENT(at_end)) THEN
    1210      1250185 :          at_end = my_at_end
    1211      1250191 :          IF (my_at_end) RETURN
    1212      2134417 :       ELSE IF (my_at_end) THEN
    1213              :          CALL cp_abort(__LOCATION__, &
    1214            0 :                        "Unexpected EOF"//TRIM(parser_location(parser)))
    1215              :       END IF
    1216              : 
    1217      3372645 :       IF (PRESENT(string_length)) THEN
    1218       302567 :          CALL parser_next_token(parser, string_length=string_length)
    1219              :       ELSE
    1220      3070078 :          CALL parser_next_token(parser)
    1221              :       END IF
    1222              : 
    1223      3372645 :       input_string_length = parser%icol2 - parser%icol1 + 1
    1224              : 
    1225              :       ! An explicitly quoted empty string is distinct from a missing token.
    1226      3372645 :       IF (input_string_length == 0 .AND. PRESENT(allow_empty)) THEN
    1227            6 :          IF (allow_empty) RETURN
    1228              :       END IF
    1229      3372639 :       IF (input_string_length <= 0) THEN
    1230              :          CALL cp_abort(__LOCATION__, &
    1231              :                        "A string type object was expected, found end of line"// &
    1232            0 :                        TRIM(parser_location(parser)))
    1233      3372639 :       ELSE IF (input_string_length > LEN(object)) THEN
    1234              :          CALL cp_abort(__LOCATION__, &
    1235              :                        "The input string <"//parser%input_line(parser%icol1:parser%icol2)// &
    1236              :                        "> has more than "//cp_to_string(LEN(object))// &
    1237              :                        " characters and is therefore too long to fit in the "// &
    1238            0 :                        "specified variable"//TRIM(parser_location(parser)))
    1239            0 :          object = parser%input_line(parser%icol1:parser%icol1 + LEN(object) - 1)
    1240              :       ELSE
    1241      3372639 :          object(:input_string_length) = parser%input_line(parser%icol1:parser%icol2)
    1242              :       END IF
    1243              : 
    1244              :       ! Convert lowercase to uppercase, if requested
    1245      3372639 :       IF (PRESENT(lower_to_upper)) THEN
    1246      1662151 :          IF (lower_to_upper) CALL uppercase(object)
    1247              :       END IF
    1248              : 
    1249      3384602 :    END SUBROUTINE parser_get_string
    1250              : 
    1251              : ! **************************************************************************************************
    1252              : !> \brief   Returns a floating point number read from a string including
    1253              : !>          fraction like z1/z2.
    1254              : !> \param string ...
    1255              : !> \param object ...
    1256              : !> \param error_message ...
    1257              : !> \date    11.01.2011 (MK)
    1258              : !> \par History
    1259              : !>      - Add simple function parsing (17.05.2023, MK)
    1260              : !> \author  Matthias Krack
    1261              : !> \version 2.0
    1262              : !> \note - Parse also multiple products and fractions of floating point numbers (23.11.2012,MK)
    1263              : ! **************************************************************************************************
    1264      4026652 :    ELEMENTAL SUBROUTINE read_float_object(string, object, error_message)
    1265              : 
    1266              :       CHARACTER(LEN=*), INTENT(IN)                       :: string
    1267              :       REAL(KIND=dp), INTENT(OUT)                         :: object
    1268              :       CHARACTER(LEN=*), INTENT(OUT)                      :: error_message
    1269              : 
    1270              :       INTEGER, PARAMETER                                 :: maxlen = 5
    1271              : 
    1272              :       CHARACTER(LEN=maxlen)                              :: func
    1273              :       INTEGER                                            :: i, ileft, iop, iright, is, islash, &
    1274              :                                                             istar, istat, n
    1275              :       LOGICAL                                            :: parsing_done
    1276              :       REAL(KIND=dp)                                      :: fsign, z
    1277              : 
    1278      4026652 :       error_message = ""
    1279      4026652 :       func = ""
    1280              : 
    1281      4026652 :       i = 1
    1282      4026652 :       iop = 0
    1283      4026652 :       n = LEN_TRIM(string)
    1284              : 
    1285      4026652 :       parsing_done = .FALSE.
    1286              : 
    1287      7148557 :       DO WHILE (.NOT. parsing_done)
    1288      4031854 :          i = i + iop
    1289      4031854 :          islash = INDEX(string(i:n), "/")
    1290      4031854 :          istar = INDEX(string(i:n), "*")
    1291      4031854 :          IF ((islash == 0) .AND. (istar == 0)) THEN
    1292              :             ! Last factor found: read it and then exit the loop
    1293      4013908 :             iop = n - i + 2
    1294      4013908 :             parsing_done = .TRUE.
    1295        17946 :          ELSE IF ((islash > 0) .AND. (istar > 0)) THEN
    1296         6296 :             iop = MIN(islash, istar)
    1297        11650 :          ELSE IF (islash > 0) THEN
    1298              :             iop = islash
    1299         4634 :          ELSE IF (istar > 0) THEN
    1300         4634 :             iop = istar
    1301              :          END IF
    1302      4031854 :          ileft = INDEX(string(i:MIN(n, i + maxlen + 1)), "(")
    1303      4031854 :          IF (ileft > 0) THEN
    1304              :             ! Check for sign
    1305          342 :             is = ICHAR(string(i:i))
    1306           12 :             SELECT CASE (is)
    1307              :             CASE (43)
    1308           12 :                fsign = 1.0_dp
    1309           12 :                func = string(i + 1:i + ileft - 2)
    1310              :             CASE (45)
    1311           22 :                fsign = -1.0_dp
    1312           22 :                func = string(i + 1:i + ileft - 2)
    1313              :             CASE DEFAULT
    1314          308 :                fsign = 1.0_dp
    1315          342 :                func = string(i:i + ileft - 2)
    1316              :             END SELECT
    1317          342 :             iright = INDEX(string(i:n), ")")
    1318          342 :             READ (UNIT=string(i + ileft:i + iright - 2), FMT=*, IOSTAT=istat) z
    1319          342 :             IF (istat /= 0) THEN
    1320              :                error_message = "A floating point type object as argument for function <"// &
    1321              :                                TRIM(func)//"> is expected, found <"// &
    1322          240 :                                string(i + ileft:i + iright - 2)//">"
    1323       909949 :                RETURN
    1324              :             END IF
    1325            8 :             SELECT CASE (func)
    1326              :             CASE ("COS")
    1327            8 :                z = fsign*COS(z*radians)
    1328              :             CASE ("EXP")
    1329            4 :                z = fsign*EXP(z)
    1330              :             CASE ("LOG")
    1331            4 :                z = fsign*LOG(z)
    1332              :             CASE ("LOG10")
    1333            4 :                z = fsign*LOG10(z)
    1334              :             CASE ("SIN")
    1335            6 :                z = fsign*SIN(z*radians)
    1336              :             CASE ("SQRT")
    1337            4 :                z = fsign*SQRT(z)
    1338              :             CASE ("TAN")
    1339            4 :                z = fsign*TAN(z*radians)
    1340              :             CASE DEFAULT
    1341           68 :                error_message = "Unknown function <"//TRIM(func)//"> found"
    1342          102 :                RETURN
    1343              :             END SELECT
    1344              :          ELSE
    1345      4031512 :             READ (UNIT=string(i:i + iop - 2), FMT=*, IOSTAT=istat) z
    1346      4031512 :             IF (istat /= 0) THEN
    1347              :                error_message = "A floating point type object was expected, found <"// &
    1348       909641 :                                string(i:i + iop - 2)//">"
    1349       909641 :                RETURN
    1350              :             END IF
    1351              :          END IF
    1352      6238608 :          IF (i == 1) THEN
    1353      3120001 :             object = z
    1354         1904 :          ELSE IF (string(i - 1:i - 1) == "*") THEN
    1355          152 :             object = object*z
    1356              :          ELSE
    1357         1752 :             IF (z == 0.0_dp) THEN
    1358              :                error_message = "Division by zero found <"// &
    1359            0 :                                string(i:i + iop - 2)//">"
    1360            0 :                RETURN
    1361              :             ELSE
    1362         1752 :                object = object/z
    1363              :             END IF
    1364              :          END IF
    1365              :       END DO
    1366              : 
    1367      4026652 :    END SUBROUTINE read_float_object
    1368              : 
    1369              : ! **************************************************************************************************
    1370              : !> \brief   Returns an integer number read from a string including products of
    1371              : !>          integer numbers like iz1*iz2*iz3
    1372              : !> \param string ...
    1373              : !> \param object ...
    1374              : !> \param error_message ...
    1375              : !> \date    23.11.2012 (MK)
    1376              : !> \author  Matthias Krack
    1377              : !> \version 1.0
    1378              : !> \note - Parse also (multiple) products of integer numbers (23.11.2012,MK)
    1379              : ! **************************************************************************************************
    1380      4960685 :    ELEMENTAL SUBROUTINE read_integer_object(string, object, error_message)
    1381              : 
    1382              :       CHARACTER(LEN=*), INTENT(IN)                       :: string
    1383              :       INTEGER, INTENT(OUT)                               :: object
    1384              :       CHARACTER(LEN=*), INTENT(OUT)                      :: error_message
    1385              : 
    1386              :       CHARACTER(LEN=20)                                  :: fmtstr
    1387              :       INTEGER                                            :: i, iop, istat, n
    1388              :       INTEGER(KIND=int_8)                                :: iz8, object8
    1389              :       LOGICAL                                            :: parsing_done
    1390              : 
    1391      4960685 :       error_message = ""
    1392              : 
    1393      4960685 :       i = 1
    1394      4960685 :       iop = 0
    1395      4960685 :       n = LEN_TRIM(string)
    1396              : 
    1397      4960685 :       parsing_done = .FALSE.
    1398              : 
    1399      8115038 :       DO WHILE (.NOT. parsing_done)
    1400      4964037 :          i = i + iop
    1401              :          ! note that INDEX always starts counting from 1 if found. Thus iop
    1402              :          ! will give the length of the integer number plus 1
    1403      4964037 :          iop = INDEX(string(i:n), "*")
    1404      4964037 :          IF (iop == 0) THEN
    1405              :             ! Last factor found: read it and then exit the loop
    1406              :             ! note that iop will always be the length of one integer plus 1
    1407              :             ! and we still need to calculate it here as it is need for fmtstr
    1408              :             ! below to determine integer format length
    1409      4952957 :             iop = n - i + 2
    1410      4952957 :             parsing_done = .TRUE.
    1411              :          END IF
    1412      4964037 :          istat = 1
    1413      4964037 :          IF (iop - 1 > 0) THEN
    1414              :             ! need an explicit fmtstr here. With 'FMT=*' compilers from intel and pgi will also
    1415              :             ! read float numbers as integers, without setting istat non-zero, i.e. string="0.3", istat=0, iz8=0
    1416              :             ! this leads to wrong CP2K results (e.g. parsing force fields).
    1417      4964033 :             WRITE (fmtstr, FMT='(A,I0,A)') '(I', iop - 1, ')'
    1418      4964033 :             READ (UNIT=string(i:i + iop - 2), FMT=fmtstr, IOSTAT=istat) iz8
    1419              :          END IF
    1420      4964037 :          IF (istat /= 0) THEN
    1421              :             error_message = "An integer type object was expected, found <"// &
    1422      1809684 :                             string(i:i + iop - 2)//">"
    1423      1809684 :             RETURN
    1424              :          END IF
    1425      3154353 :          IF (i == 1) THEN
    1426      3154089 :             object8 = iz8
    1427              :          ELSE
    1428          264 :             object8 = object8*iz8
    1429              :          END IF
    1430      6305354 :          IF (ABS(object8) > HUGE(0)) THEN
    1431              :             error_message = "The specified integer number <"//string(i:i + iop - 2)// &
    1432            0 :                             "> exceeds the allowed range of a 32-bit integer number."
    1433            0 :             RETURN
    1434              :          END IF
    1435              :       END DO
    1436              : 
    1437      3151001 :       object = INT(object8)
    1438              : 
    1439      4960685 :    END SUBROUTINE read_integer_object
    1440              : 
    1441              : END MODULE cp_parser_methods
        

Generated by: LCOV version 2.0-1