LCOV - code coverage report
Current view: top level - src/input - cp_parser_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b1c14e6) Lines: 446 532 83.8 %
Date: 2022-07-02 11:36:49 Functions: 21 22 95.5 %

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

Generated by: LCOV version 1.15