LCOV - code coverage report
Current view: top level - src/57_iopsp_parser - xmltools.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 37.0 % 414 153
Test Date: 2026-09-21 13:49:52 Functions: 29.3 % 41 12

            Line data    Source code
       1              : !
       2              : ! Copyright (C) 2020-2021 Quantum ESPRESSO group
       3              : ! This file is distributed under the terms of the
       4              : ! GNU General Public License. See the file `License'
       5              : ! in the root directory of the present distribution,
       6              : ! or http://www.gnu.org/copyleft/gpl.txt .
       7              : !
       8              : !--------------------------------------------------------
       9              : 
      10              : #if defined HAVE_CONFIG_H
      11              : #include "config.h"
      12              : #endif
      13              : 
      14              : #include "abi_common.h"
      15              : 
      16              : MODULE xmltools
      17              :   !--------------------------------------------------------
      18              :   !
      19              :   ! Poor-man set of tools for reading and writing xml files
      20              :   ! Similar to iotk but much simpler - Paolo Giannozzi, June 2020
      21              :   ! Limitations: too many to be listed in detail. Main ones:
      22              :   ! * works on a single opened file at the time. Exception:
      23              :   !   while a file is opened, one can open, R/W, close another file,
      24              :   !   but it is not possible to operate on both files at the same time
      25              :   ! * lines no more than 1024 characters long (see maxline parameter)
      26              :   ! * no more than 9 levels of tags (see maxlevel parameter)
      27              :   ! * length of tags no more than 80 characters (see maxlength parameter)
      28              :   ! * can read tags only in the correct order. If a tag is not found, the
      29              :   !   file is rewound. If "ierr" is present, a second attempt to find the
      30              :   !   tag is done starting from the top of the file - may work if the searched
      31              :   !   tag is found only above the current position, and nowhere else
      32              :   ! * only single values (e.g. no vectors) in attributes
      33              :   ! * attributes should not contain commas or strange characters
      34              :   ! * xml comments (<!-- ...  -->) or <![CDATA[ ... ]]> cannot be mixed
      35              :   !   with numerical fields
      36              :   !
      37              :   !USE upf_kinds, ONLY : dp
      38              :   use defs_basis
      39              :   IMPLICIT NONE
      40              :   !
      41              : #undef __debug
      42              :   !! define __debug to print information on opened and closed tags
      43              :   LOGICAL, PARAMETER :: one_line_tags=.true.
      44              :   !! if true, write tags with one value in a single line:
      45              :   !! <tag attr1="val1" ... >value</tag>
      46              :   !! otherwise, as in iotk:
      47              :   !! <tag attr1="val1" ... >
      48              :   !! value
      49              :   !! </tag>
      50              :   !! Only for single values; arrays are always written as in iotk
      51              :   !
      52              :   ! internal variables for reading and writing
      53              :   !
      54              :   INTEGER :: xmlunit
      55              :   INTEGER, PARAMETER :: maxline=1024
      56              :   CHARACTER(LEN=maxline) :: line
      57              :   INTEGER :: xmlsave = -1, nopen = 0
      58              :   INTEGER :: eot
      59              :   ! eot points to the end of tag in line just scanned
      60              :   INTEGER :: nattr
      61              :   CHARACTER(LEN=:), ALLOCATABLE :: attrlist
      62              :   !
      63              :   ! variables used to keep track of open tags
      64              :   !
      65              :   INTEGER :: nlevel = -1
      66              :   INTEGER, PARAMETER :: maxlength=80, maxlevel=9
      67              :   CHARACTER(LEN=maxlength), DIMENSION(0:maxlevel) :: open_tags
      68              :   !
      69              :   PRIVATE
      70              :   ! general subroutines
      71              :   PUBLIC :: xml_open_file, xml_closefile
      72              :   ! subroutines for writing
      73              :   PUBLIC :: add_attr
      74              :   PUBLIC :: xmlw_writetag, xmlw_opentag, xmlw_closetag
      75              :   ! subroutines for reading
      76              :   PUBLIC :: xmlr_readtag, xmlr_opentag, xmlr_closetag
      77              :   PUBLIC :: get_attr
      78              :   ! utility functions
      79              :   PUBLIC :: xml_protect, i2c, l2c, r2c
      80              :   !
      81              :   ! Error codes returned by xmlr_opentag / xml_readtag:
      82              :   !  -1   tag with no value (e.g. <tag attr="val"/>) found (no error)
      83              :   !   0   tag found and read (no error)
      84              :   !   1   tag not found
      85              :   !   2   error parsing file
      86              :   !   3   line too long
      87              :   !   4   too many levels of tags
      88              :   !
      89              :   ! Error codes returned by xmlw_opentag / xml_writetag:
      90              :   !   0     tag open and/or written (no error)
      91              :   !   1     cannot write to unit "xmlunit"
      92              :   !   2     tag name too long
      93              :   !   3     wrong number of values for attributes
      94              :   !   4     too many levels of tag
      95              :   !
      96              :   INTERFACE xmlr_readtag
      97              :      MODULE PROCEDURE readtag_c, readtag_r, readtag_l, readtag_i, &
      98              :           readtag_iv, readtag_rv, readtag_rm, readtag_rt, &
      99              :           readtag_zv, readtag_zm, readtag_zt
     100              :   END INTERFACE xmlr_readtag
     101              :   !
     102              :   ! IMPORTANT NOTICE: complex numbers, z=a+ib, are written as two reals:
     103              :   ! "a b", not in fortran free format as "(a,b)". Reason:
     104              :   ! make the file readable by non-fortran tools, e.g. python
     105              :   !
     106              :   INTERFACE xmlw_writetag
     107              :      MODULE PROCEDURE writetag_c, writetag_r, writetag_l, writetag_i, &
     108              :           writetag_iv, writetag_rv, writetag_rm, writetag_rt, &
     109              :           writetag_zv, writetag_zm, writetag_zt
     110              :   END INTERFACE xmlw_writetag
     111              :   !
     112              :   INTERFACE get_attr
     113              :      MODULE PROCEDURE get_i_attr, get_l_attr, get_r_attr, get_c_attr
     114              :   END INTERFACE get_attr
     115              : 
     116              :   INTERFACE add_attr
     117              :      MODULE PROCEDURE add_i_attr, add_l_attr, add_r_attr, add_c_attr
     118              :   END INTERFACE add_attr
     119              : 
     120              : CONTAINS
     121              : 
     122          805 :   SUBROUTINE get_i_attr ( attrname, attrval_i )
     123              :     !
     124              :     ! returns attrval_i=0 if not found or not readable
     125              :     !
     126              :     !IMPLICIT NONE
     127              :     CHARACTER(LEN=*), INTENT(IN) :: attrname
     128              :     INTEGER, INTENT(OUT) :: attrval_i
     129              :     !
     130              :     CHARACTER(LEN=80) :: attrval_c
     131              :     !
     132          805 :     CALL get_c_attr ( attrname, attrval_c )
     133          805 :     if ( len_trim(attrval_c) > 0 ) then
     134          719 :        READ (attrval_c,*, err=1) attrval_i
     135          719 :        return
     136              : 1      print '("Error reading attribute ",a,": expected integer, found ",a)', &
     137            0 :             trim(attrname), trim(attrval_c)
     138              :     end if
     139           86 :     attrval_i = 0
     140              :     !
     141              :   END SUBROUTINE get_i_attr
     142              :   !
     143          144 :   SUBROUTINE get_l_attr ( attrname, attrval_l )
     144              :     !
     145              :     ! returns attrval_l=.false. if not found or not readable
     146              :     !
     147              :     !IMPLICIT NONE
     148              :     CHARACTER(LEN=*), INTENT(IN) :: attrname
     149              :     LOGICAL, INTENT(OUT) :: attrval_l
     150              :     !
     151              :     CHARACTER(LEN=80) :: attrval_c
     152              :     !
     153          144 :     CALL get_c_attr ( attrname, attrval_c )
     154          144 :     if ( len_trim(attrval_c) > 0 ) then
     155          114 :        READ (attrval_c,*, err=1) attrval_l
     156          114 :        return
     157              : 1      print '("Error reading attribute ",a,": expected logical, found ",a)', &
     158            0 :             trim(attrname), trim(attrval_c)
     159              :     end if
     160           30 :     attrval_l = .false.
     161              :     !
     162              :   END SUBROUTINE get_l_attr
     163              :   !
     164          668 :   SUBROUTINE get_r_attr ( attrname, attrval_r )
     165              :     !
     166              :     ! returns attrval_r=0 if not found or not readable
     167              :     !
     168              :     !IMPLICIT NONE
     169              :     CHARACTER(LEN=*), INTENT(IN) :: attrname
     170              :     REAL(dp), INTENT(OUT) :: attrval_r
     171              :     !
     172              :     CHARACTER(LEN=80) :: attrval_c
     173              :     !
     174          668 :     CALL get_c_attr ( attrname, attrval_c )
     175          668 :     if ( len_trim(attrval_c) > 0 ) then
     176          363 :        READ (attrval_c,*, err=1) attrval_r
     177          363 :        return
     178              : 1      print '("Error reading attribute ",a,": expected real, found ",a)', &
     179            0 :             trim(attrname), trim(attrval_c)
     180              :     end if
     181          305 :     attrval_r = 0.0_dp
     182              :     !
     183              :   END SUBROUTINE get_r_attr
     184              :   !
     185         1932 :   SUBROUTINE get_c_attr ( attrname, attrval_c )
     186              :     !
     187              :     ! returns attrval_c='' if not found
     188              :     !
     189              :     !IMPLICIT NONE
     190              :     CHARACTER(LEN=*), INTENT(IN) :: attrname
     191              :     CHARACTER(LEN=*), INTENT(OUT) :: attrval_c
     192              :     !
     193              :     CHARACTER(LEN=1) :: quote
     194              :     INTEGER :: j0, j1
     195              :     LOGICAL :: found
     196              :     !
     197              :     ! search for attribute name in attrlist: attr1="val1" attr2="val2" ...
     198              :     !
     199         1932 :     attrval_c = ''
     200         3326 :     if ( .not. allocated(attrlist) ) return
     201         1852 :     if ( len_trim(attrlist) < 1 ) return
     202              :     !
     203              :     j0 = 1
     204        14098 :     do while ( j0 < len_trim(attrlist) )
     205              :        ! locate = and first quote
     206        13640 :        j1 = index ( attrlist(j0:), '=' )
     207        13640 :        quote = attrlist(j0+j1:j0+j1)
     208              :        ! next line: something is not right
     209        13640 :        if ( quote /= '"' .and. quote /= "'" ) return
     210              :        ! check if attribute found: need exact match
     211        13640 :        found =  ( trim(attrname) == adjustl(trim(attrlist(j0:j0+j1-2))) )
     212              :        ! locate next quote
     213        13640 :        j0 = j0+j1+1
     214        13640 :        j1 = index ( attrlist(j0:), quote )
     215        13640 :        if ( found) then
     216         1394 :           if ( j1 == 1 ) then
     217              :              ! two quotes, one after the other ("")
     218           16 :              attrval_c = ' '
     219              :           else
     220              :              ! get value between two quotes
     221         1378 :              attrval_c = adjustl(trim(attrlist(j0:j0+j1-2)))
     222              :           end if
     223         1394 :           return
     224              :        end if
     225        12246 :        j0 = j0+j1
     226              :     end do
     227              :     !
     228         1932 :   END SUBROUTINE get_c_attr
     229              :   !
     230            0 :   SUBROUTINE add_i_attr ( attrname, attrval_i )
     231              :     !
     232              :     !IMPLICIT NONE
     233              :     CHARACTER(LEN=*), INTENT(IN) :: attrname
     234              :     INTEGER, INTENT(IN) :: attrval_i
     235              :     !
     236            0 :     CALL add_c_attr ( attrname, i2c(attrval_i) )
     237              :     !
     238            0 :   END SUBROUTINE add_i_attr
     239              :   !
     240            0 :   SUBROUTINE add_l_attr ( attrname, attrval_l )
     241              :     !
     242              :     !IMPLICIT NONE
     243              :     CHARACTER(LEN=*), INTENT(IN) :: attrname
     244              :     LOGICAL, INTENT(IN) :: attrval_l
     245              :     !
     246            0 :     CALL add_c_attr ( attrname, l2c(attrval_l) )
     247              :     !
     248            0 :   END SUBROUTINE add_l_attr
     249              :   !
     250            0 :   SUBROUTINE add_r_attr ( attrname, attrval_r )
     251              :     !
     252              :     !IMPLICIT NONE
     253              :     CHARACTER(LEN=*), INTENT(IN) :: attrname
     254              :     REAL(dp), INTENT(IN) :: attrval_r
     255              :     !
     256            0 :     CALL add_c_attr ( attrname, r2c(attrval_r) )
     257              :     !
     258            0 :   END SUBROUTINE add_r_attr
     259              :   !
     260            0 :   SUBROUTINE add_c_attr ( attrname, attrval_c )
     261              :     !
     262              :     !IMPLICIT NONE
     263              :     CHARACTER(LEN=*), INTENT(IN) :: attrname, attrval_c
     264              :     !
     265            0 :     IF ( .NOT. ALLOCATED(attrlist) ) THEN
     266            0 :        attrlist = ' '//TRIM(attrname)//'="'//TRIM(attrval_c)//'"'
     267              :     ELSE
     268            0 :        attrlist = attrlist // ' ' // TRIM(attrname)//'="'//TRIM(attrval_c)//'"'
     269              :     END IF
     270              :     !
     271            0 :   END SUBROUTINE add_c_attr
     272              :   !
     273           16 :   FUNCTION xml_open_file ( filexml ) RESULT (iun)
     274              :     !
     275              :     ! returns on output the opened unit number if opened successfully
     276              :     ! returns -1 otherwise
     277              :     !
     278              :     CHARACTER(LEN=*), INTENT(in) :: filexml
     279              :     INTEGER :: iun, ios
     280              :     !
     281           16 :     IF ( nopen > 1 ) THEN
     282              :        print "('cannot open file ',a,': two xml files already opened')",&
     283            0 :                trim(filexml)
     284              :        iun = -1
     285            0 :        RETURN
     286              :     END IF
     287              :     OPEN ( NEWUNIT=iun, FILE=filexml, FORM='formatted', STATUS='unknown', &
     288           16 :          IOSTAT=ios)
     289           16 :     IF ( ios /= 0 ) iun = -1
     290           16 :     nopen = nopen + 1
     291           16 :     IF ( nopen > 1 ) xmlsave = xmlunit
     292           16 :     xmlunit = iun
     293           16 :     nlevel = 0
     294           16 :     open_tags(nlevel) = 'root'
     295           16 :     if ( allocated(attrlist) ) DEALLOCATE ( attrlist)
     296              : #if defined ( __debug )
     297              :     print "('file ',a,' opened with unit ',i5)",trim(filexml),iun
     298              : #endif
     299              :     !
     300           16 :   END FUNCTION xml_open_file
     301              :   !
     302           16 :   SUBROUTINE xml_closefile ( )
     303              :     !
     304           16 :     CLOSE ( UNIT=xmlunit, STATUS='keep' )
     305              : #if defined ( __debug )
     306              :     print "('unit ',i5,': file closed')", xmlunit
     307              : #endif
     308           16 :     xmlunit = xmlsave
     309           16 :     nopen = nopen - 1
     310           16 :     xmlsave = -1
     311           16 :     IF (nlevel > 0) print '("warning: file closed at level ",i1,&
     312            0 :             & " with tag ",A," open")', nlevel, trim(open_tags(nlevel))
     313           16 :     nlevel = 0
     314              :     !
     315           16 :   END SUBROUTINE xml_closefile
     316              :   !
     317            0 :   SUBROUTINE xmlw_opentag (name, ierr )
     318              :     ! On input:
     319              :     ! name      required, character: tag name
     320              :     ! On output: the tag is left open, ready for addition of data -
     321              :     !            the tag must be subsequently closed with close_xml_tag
     322              :     ! If ierr is present, the error code set in write_tag_and_attr is returned
     323              :     ! If ierr is absent,  the above error code is reprinted on output
     324              :     !
     325              :     CHARACTER(LEN=*), INTENT(IN) :: name
     326              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     327              :     !
     328              :     INTEGER :: ier_
     329              :     CHARACTER(LEN=1) :: tag_end='>'
     330              :     !
     331            0 :     ier_ = write_tag_and_attr (name)
     332              :     IF ( ier_ < 0 ) ier_ = 0
     333              :     ! complete tag, leaving it open for further data
     334            0 :     WRITE (xmlunit, "(A1)", ERR=100) tag_end
     335              :     ! exit here
     336            0 : 100 IF ( present(ierr) ) THEN
     337            0 :        ierr = ier_
     338            0 :     ELSE IF ( ier_ > 0 ) THEN
     339            0 :        print '("Fatal error ",i2," in xmlw_opentag!")', ier_
     340              :     END IF
     341              :     !
     342            0 :   END SUBROUTINE xmlw_opentag
     343              : 
     344            0 :   SUBROUTINE writetag_c (name, cval, ierr )
     345              :     ! On input, same as xmlw_opentag, plus:
     346              :     ! cval   character, value of the tag.
     347              :     ! If cval=' ' write <name  attr1="val1" attr2="val2" ... />
     348              :     ! If cval='?' write <?name attr1="val1" attr2="val2" ...?>
     349              :     ! otherwise,  write <name  attr1="val1" attr2="val2" ...>cval</name>
     350              :     !             (on a same line if one_line_tags=.true.)
     351              :     ! On output, same as xmlw_opentag
     352              :     !
     353              :     CHARACTER(LEN=*), INTENT(IN) :: name
     354              :     CHARACTER(LEN=*), INTENT(IN) :: cval
     355              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     356              :     !
     357              :     INTEGER :: ier_
     358              :     LOGICAL :: is_proc
     359              :     !
     360            0 :     is_proc = (LEN_TRIM(cval) == 1)
     361            0 :     IF ( is_proc ) is_proc = is_proc .AND. ( cval(1:1) == '?')
     362              :     IF (is_proc) THEN
     363            0 :        ier_ = write_tag_and_attr ( '?'//name )
     364              :     ELSE
     365            0 :        ier_ = write_tag_and_attr ( name )
     366              :     END IF
     367            0 :     IF ( ier_ > 0 ) GO TO 10
     368              :     !
     369              :     ! all is well: write tag value if any, close otherwise
     370              :     !
     371            0 :     IF ( LEN_TRIM(cval) == 0 ) THEN
     372              :        ! empty tag value: close here the tag
     373            0 :        CALL xmlw_closetag ( '' )
     374            0 :     ELSE IF ( is_proc ) THEN
     375              :        ! close "process" tag (e.g. <?xml ... ?>
     376            0 :        CALL xmlw_closetag ( '?' )
     377              :     ELSE
     378              :        ! write value (character)
     379              :        IF (one_line_tags) THEN
     380            0 :           WRITE (xmlunit, "('>',A)", ADVANCE='no') trim(cval)
     381              :        ELSE
     382              :           WRITE (xmlunit, "('>',/,A)") trim(cval)
     383              :        ENDIF
     384              :        ! close here the tag
     385            0 :        CALL xmlw_closetag ( name )
     386              :     END IF
     387              :     ! in case of exit error close the tag anyway
     388            0 : 10  IF ( ier_ /= 0 ) WRITE (xmlunit, "('>')", ERR=100)
     389            0 : 100 IF ( present(ierr) ) THEN
     390            0 :        ierr = ier_
     391            0 :     ELSE IF ( ier_ > 0 ) THEN
     392            0 :        print '("Fatal error ",i2," in xmlw_writetag!")', ier_
     393              :     END IF
     394              :     !
     395            0 :   END SUBROUTINE writetag_c
     396              :   !
     397            0 :   SUBROUTINE writetag_i (name, ival, ierr )
     398              :     !
     399              :     ! As writetag_c, for integer value
     400              :     !
     401              :     CHARACTER(LEN=*), INTENT(IN) :: name
     402              :     INTEGER, INTENT(IN)          :: ival
     403              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     404              :     !
     405            0 :     CALL writetag_c (name, i2c(ival), ierr )
     406              :     !
     407            0 :   END SUBROUTINE writetag_i
     408              :   !
     409            0 :   SUBROUTINE writetag_iv (name, ivec, ierr )
     410              :     !
     411              :     ! As writetag_c, for integer value
     412              :     !
     413              :     CHARACTER(LEN=*), INTENT(IN) :: name
     414              :     INTEGER, INTENT(IN)          :: ivec(:)
     415              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     416              :     !
     417            0 :     CALL xmlw_opentag (name, ierr )
     418            0 :     WRITE( xmlunit, '(4I18)') ivec
     419            0 :     CALL xmlw_closetag ( )
     420              :     !
     421            0 :   END SUBROUTINE writetag_iv
     422              :   !
     423            0 :   SUBROUTINE writetag_l (name, lval, ierr )
     424              :     !
     425              :     ! As writetag_c, for logical value
     426              :     !
     427              :     CHARACTER(LEN=*), INTENT(IN) :: name
     428              :     LOGICAL, INTENT(IN)          :: lval
     429              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     430              :     !
     431            0 :     CALL writetag_c (name, l2c(lval), ierr )
     432              :     !
     433            0 :   END SUBROUTINE writetag_l
     434              :   !
     435            0 :   SUBROUTINE writetag_r (name, rval, ierr )
     436              :     !
     437              :     ! As writetag_c, for real value
     438              :     !
     439              :     CHARACTER(LEN=*), INTENT(IN) :: name
     440              :     REAL(dp), INTENT(IN)         :: rval
     441              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     442              :     !
     443            0 :     CALL writetag_c (name, r2c(rval), ierr )
     444              :     !
     445            0 :   END SUBROUTINE writetag_r
     446              :   !
     447            0 :   SUBROUTINE writetag_rv (name, rvec, ierr )
     448              :     !
     449              :     ! As writetag_c, for a vector of real values
     450              :     !
     451              :     CHARACTER(LEN=*), INTENT(IN) :: name
     452              :     REAL(dp), INTENT(IN)         :: rvec(:)
     453              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     454              :     !
     455            0 :     CALL xmlw_opentag (name, ierr )
     456            0 :     WRITE( xmlunit, '(3es24.15)') rvec
     457            0 :     CALL xmlw_closetag ( )
     458              :     !
     459            0 :   END SUBROUTINE writetag_rv
     460              :   !
     461            0 :   SUBROUTINE writetag_rm (name, rmat, ierr )
     462              :     !
     463              :     ! As writetag_c, for a matrix of real values
     464              :     !
     465              :     CHARACTER(LEN=*), INTENT(IN) :: name
     466              :     REAL(dp), INTENT(IN)         :: rmat(:,:)
     467              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     468              :     !
     469            0 :     CALL xmlw_opentag (name, ierr )
     470            0 :     WRITE( xmlunit, '(3es24.15)') rmat
     471            0 :     CALL xmlw_closetag ( )
     472              :     !
     473            0 :   END SUBROUTINE writetag_rm
     474              :   !
     475            0 :   SUBROUTINE writetag_rt (name, rtens, ierr )
     476              :     !
     477              :     ! As writetag_c, for a 3-dim tensor of real values
     478              :     !
     479              :     CHARACTER(LEN=*), INTENT(IN) :: name
     480              :     REAL(dp), INTENT(IN)         :: rtens(:,:,:)
     481              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     482              :     !
     483            0 :     CALL xmlw_opentag (name, ierr )
     484            0 :     WRITE( xmlunit, '(3es24.15)') rtens
     485            0 :     CALL xmlw_closetag ( )
     486              :     !
     487            0 :   END SUBROUTINE writetag_rt
     488              :   !
     489            0 :   SUBROUTINE writetag_zv (name, zvec, ierr )
     490              :     !
     491              :     ! As writetag_c, for a vector of complex values
     492              :     !
     493              :     use, intrinsic :: iso_c_binding
     494              :     CHARACTER(LEN=*), INTENT(IN) :: name
     495              :     COMPLEX(dp), INTENT(IN), TARGET:: zvec(:)
     496              :     INTEGER, INTENT(OUT), OPTIONAL :: ierr
     497              :     !
     498              :     ! Casts a real pointer (rvec) to a complex array (zvec) via C pointer (!)
     499              :     ! in order to write complexes as two reals. Some compilers require that
     500              :     ! the argument of c_loc (zvec) is a pointer or has the "target" attribute
     501              :     !
     502              :     TYPE (c_ptr) :: cp
     503            0 :     REAL(dp), POINTER  :: rvec(:)
     504              :     INTEGER :: n, ndim
     505              :     !
     506            0 :     NULLIFY (rvec)
     507            0 :     cp = c_loc(zvec)
     508            0 :     CALL c_f_pointer (cp, rvec, shape(zvec)*[2])
     509            0 :     CALL xmlw_opentag (name, ierr )
     510            0 :     ndim = SIZE (zvec)
     511            0 :     DO n=1,2*ndim,2
     512            0 :        WRITE( xmlunit, *) rvec(n), rvec(n+1)
     513              :     END DO
     514            0 :     CALL xmlw_closetag ( )
     515              :     !
     516            0 :   END SUBROUTINE writetag_zv
     517              :   !
     518            0 :   SUBROUTINE writetag_zm (name, zmat, ierr )
     519              :     !
     520              :     ! As writetag_c for a matrix of complex values - see comments in writetag_zv
     521              :     !
     522              :     use, intrinsic :: iso_c_binding
     523              :     CHARACTER(LEN=*), INTENT(IN) :: name
     524              :     COMPLEX(dp), INTENT(IN), TARGET:: zmat(:,:)
     525              :     INTEGER, INTENT(OUT), OPTIONAL :: ierr
     526              :     !
     527              :     TYPE (c_ptr) :: cp
     528            0 :     REAL(dp), POINTER  :: rmat(:,:)
     529              :     !
     530            0 :     NULLIFY (rmat)
     531            0 :     cp = c_loc(zmat)
     532            0 :     CALL c_f_pointer (cp, rmat, shape(zmat)*[2,1])
     533              :     !
     534            0 :     CALL xmlw_opentag (name, ierr )
     535            0 :     WRITE( xmlunit, '(2es24.15)') rmat
     536            0 :     CALL xmlw_closetag ( )
     537              :     !
     538            0 :   END SUBROUTINE writetag_zm
     539              :   !
     540            0 :   SUBROUTINE writetag_zt (name, ztens, ierr )
     541              :     !
     542              :     ! As writetag_c for a matrix of complex values - see comments in writetag_zv
     543              :     !
     544              :     use, intrinsic :: iso_c_binding
     545              :     CHARACTER(LEN=*), INTENT(IN) :: name
     546              :     COMPLEX(dp), INTENT(IN), TARGET:: ztens(:,:,:)
     547              :     INTEGER, INTENT(OUT), OPTIONAL :: ierr
     548              :     !
     549              :     TYPE (c_ptr) :: cp
     550            0 :     REAL(dp), POINTER  :: rtens(:,:,:)
     551              :     !
     552            0 :     NULLIFY (rtens)
     553            0 :     cp = c_loc(ztens)
     554            0 :     CALL c_f_pointer (cp, rtens, shape(ztens)*[2,1,1])
     555              :     !
     556            0 :     CALL xmlw_opentag (name, ierr )
     557            0 :     WRITE( xmlunit, '(2es24.15)') rtens
     558            0 :     CALL xmlw_closetag ( )
     559              :     !
     560            0 :   END SUBROUTINE writetag_zt
     561              :   !
     562            0 :   FUNCTION write_tag_and_attr (name) RESULT (ierr)
     563              :     !
     564              :     CHARACTER(LEN=*), INTENT(IN) :: name
     565              :     INTEGER :: ierr
     566              :     ! See list of error codes in the header of this file
     567              :     !
     568              :     !LOGICAL :: have_list, have_vals
     569              :     INTEGER :: i !, la, lv, n1a,n2a, n1v, n2v
     570              :     !
     571            0 :     IF ( LEN_TRIM(name) > maxlength ) THEN
     572            0 :        ierr = 2
     573              :        RETURN
     574              :     END IF
     575              :     !
     576            0 :     IF ( nlevel+1 > maxlevel ) THEN
     577            0 :        ierr = 4
     578              :        RETURN
     579              :     END IF
     580            0 :     nlevel = nlevel+1
     581            0 :     open_tags(nlevel) = TRIM(name)
     582              :     !
     583              :     ! pretty (?) printing
     584              :     !
     585            0 :     ierr = 1
     586            0 :     DO i=2,nlevel
     587            0 :        WRITE (xmlunit, "('  ')", ADVANCE="no", ERR=10)
     588              :     END DO
     589            0 :     WRITE (xmlunit, "('<',A)", ADVANCE="no", ERR=10) trim(name)
     590              : #if defined ( __debug )
     591              :     print '("opened (write) level-",i1," tag ",A)', nlevel, trim(open_tags(nlevel))
     592              : #endif
     593              :     !
     594              :     ! attributes (if present)
     595              :     !
     596            0 :     ierr = 3
     597            0 :     if ( allocated (attrlist) ) then
     598            0 :        WRITE (xmlunit, "(A)", ADVANCE='no', ERR=10) attrlist
     599            0 :        deallocate (attrlist)
     600              :     end if
     601              :     ! normal exit here
     602              :     ierr = 0
     603              : 10  RETURN
     604              :     !
     605            0 :   END FUNCTION write_tag_and_attr
     606              :   !
     607            0 :   SUBROUTINE xmlw_closetag ( tag )
     608              :     ! tag   not present: close current open tag with </tag>
     609              :     ! empty tag present: close current open tag with />
     610              :     ! tag='?'   present: close current open tag with ?>
     611              :     ! otherwise,close specified tag with </tag>
     612              :     CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: tag
     613              :     INTEGER :: i
     614              :     !
     615            0 :     IF ( nlevel < 0 ) THEN
     616            0 :       print "('xmlw_closetag: severe error, closing tag that was never opened')"
     617            0 :       RETURN
     618              :     END IF
     619            0 :     IF ( .NOT.PRESENT(tag) ) THEN
     620            0 :        DO i=2,nlevel
     621            0 :           WRITE (xmlunit, '("  ")', ADVANCE='NO')
     622              :        END DO
     623            0 :        WRITE (xmlunit, '("</",A,">")') trim(open_tags(nlevel))
     624              : #if defined ( __debug )
     625              :     print '("closed (write) level-",i1," tag ",A)', nlevel, trim(open_tags(nlevel))
     626              : #endif
     627              :     ELSE
     628            0 :        i = len_trim(tag)
     629            0 :        IF ( i == 0 ) THEN
     630            0 :           WRITE (xmlunit, '("/>")')
     631              : #if defined ( __debug )
     632              :           print '("closed (write) level-",i1," tag ",A)', &
     633              :                nlevel, trim(open_tags(nlevel))
     634              : #endif
     635            0 :        ELSE IF ( i == 1 .AND. tag(1:1) == '?' ) THEN
     636            0 :           WRITE (xmlunit, '("?>")')
     637              : #if defined ( __debug )
     638              :           print '("closed (write) level-",i1," tag ",A)', nlevel, tag
     639              : #endif
     640              :        ELSE
     641            0 :           WRITE (xmlunit, '("</",A,">")') trim(tag)
     642              : #if defined ( __debug )
     643              :           print '("closed (write) level-",i1," tag ",A)', nlevel, tag
     644              : #endif
     645              :        END IF
     646              :     END IF
     647            0 :     nlevel = nlevel-1
     648              :     !
     649              :   END SUBROUTINE xmlw_closetag
     650              :   !
     651              :   !--------------------------------------------------------
     652            0 :   function xml_protect ( data_in ) result (data_out)
     653              :     !--------------------------------------------------------
     654              :     !
     655              :     ! poor-man escaping of a string so that it conforms to xml standard:
     656              :     ! replace & with @, < and > with *.
     657              :     ! To prevent problems with attributes, double quotes " are replaced
     658              :     ! with single quotes '. data_out is left-justified
     659              :     !
     660              :     character(len=*), intent(in) :: data_in
     661              :     character(len=:), allocatable :: data_out
     662              :     !character(len=1) :: c
     663              :     integer:: n, i
     664              :     !
     665            0 :     n = len_trim(adjustl(data_in))
     666              :     ! Alternative version with CDATA:
     667              :     ! allocate(character(len=n+12):: data_out)
     668              :     ! data_out = '<![CDATA['//trim(adjustl(data_in))//']]>'
     669            0 :     data_out = trim(adjustl(data_in))
     670            0 :     do i=1,n
     671            0 :        if ( data_out(i:i) == '&' ) data_out(i:i) = '@'
     672            0 :        if ( data_out(i:i) == '<' .or. data_out(i:i) == '>') data_out(i:i) = '*'
     673            0 :        if ( data_out(i:i) == '"' ) data_out(i:i) = "'"
     674              :     end do
     675              :     ! a more complete version should escape & as &amp;, < as &lt;
     676              :     ! (escaping > as &gt; , " as &quotes; , ' as &apo; is not strictly needed)
     677              :     ! BUT taking care not to escape &amp; into &amp;amp;
     678              : 
     679            0 :   end function xml_protect
     680              : 
     681              :   ! Poor-man conversion utilities from integer, logical, real to character
     682              :   ! To be used in conjunction with routines in module xmlw to write xml
     683              :   !
     684          261 :   function i2c (i) result (c)
     685              :     integer, intent(in) :: i
     686              :     character(len=:), allocatable :: c
     687              :     character(len=11) :: caux
     688              :     !
     689          261 :     write(caux,'(i11)') i
     690          261 :     c = trim(adjustl(caux))
     691              :     !
     692          261 :   end function i2c
     693              : 
     694            0 :   function l2c (l) result (c)
     695              :     logical, intent(in) :: l
     696              :     character(len=:), allocatable :: c
     697              :     !
     698            0 :     if (l) then
     699            0 :        c='true'
     700              :     else
     701            0 :        c='false'
     702              :     endif
     703              :     !
     704            0 :   end function l2c
     705              : 
     706            0 :   function r2c (f) result (c)
     707              :     real(dp), intent(in) :: f
     708              :     character(len=:), allocatable :: c
     709              :     character(len=30) :: caux
     710              :     !
     711              :     !integer :: n, m, i
     712              :     ! The format of real numbers can be vastly improved
     713              :     ! this is just the simplest solution
     714            0 :     write(caux,*) f
     715            0 :     c = trim(adjustl(caux))
     716              :     !
     717            0 :   end function r2c
     718              :   !
     719            0 :   SUBROUTINE readtag_i (name, ival, ierr )
     720              :     !
     721              :     ! As readtag_c, for integer value
     722              :     !
     723              :     CHARACTER(LEN=*), INTENT(IN) :: name
     724              :     INTEGER, INTENT(OUT)         :: ival
     725              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     726              :     CHARACTER(LEN=80) :: cval
     727              :     !
     728            0 :     CALL readtag_c (name, cval, ierr )
     729            0 :     if ( len_trim(cval) > 0 ) then
     730            0 :        READ (cval,*) ival
     731              :     else
     732            0 :        ival = 0
     733              :     end if
     734              :     !
     735            0 :   END SUBROUTINE readtag_i
     736              :   !
     737            0 :   SUBROUTINE readtag_iv (name, ivec, ierr)
     738              :     !
     739              :     ! As readtag_c, for a vector of integer values
     740              :     !
     741              :     CHARACTER(LEN=*), INTENT(IN) :: name
     742              :     INTEGER, INTENT(OUT)         :: ivec(:)
     743              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     744              :     INTEGER :: ier_
     745              :     !
     746            0 :     CALL xmlr_opentag (name, ier_)
     747            0 :     if ( ier_ == 0  ) then
     748            0 :        READ(xmlunit, *) ivec
     749            0 :        CALL xmlr_closetag ( )
     750              :     else
     751            0 :        ivec = 0.0_dp
     752              :     end if
     753            0 :     IF ( present (ierr) ) ierr = ier_
     754              :     !
     755            0 :   END SUBROUTINE readtag_iv
     756              :   !
     757            0 :   SUBROUTINE readtag_l (name, lval, ierr )
     758              :     !
     759              :     ! As readtag_c, for logical value
     760              :     !
     761              :     CHARACTER(LEN=*), INTENT(IN) :: name
     762              :     LOGICAL, INTENT(OUT)         :: lval
     763              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     764              :     CHARACTER(LEN=80) :: cval
     765              :     !
     766            0 :     CALL readtag_c (name, cval, ierr )
     767            0 :     if ( len_trim(cval) > 0 ) then
     768            0 :        READ (cval,*) lval
     769              :     else
     770            0 :        lval = .false.
     771              :     end if
     772              :     !
     773            0 :   END SUBROUTINE readtag_l
     774              :   !
     775            0 :   SUBROUTINE readtag_r (name, rval, ierr )
     776              :     !
     777              :     ! As readtag_c, for real value
     778              :     !
     779              :     CHARACTER(LEN=*), INTENT(IN) :: name
     780              :     REAL(dp), INTENT(OUT)         :: rval
     781              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     782              :     CHARACTER(LEN=80) :: cval
     783              :     !
     784            0 :     CALL readtag_c (name, cval, ierr )
     785            0 :     if ( len_trim(cval) > 0 ) then
     786            0 :        READ (cval,*) rval
     787              :     else
     788            0 :        rval = 0.0_dp
     789              :     end if
     790              :     !
     791            0 :   END SUBROUTINE readtag_r
     792              :   !
     793          283 :   SUBROUTINE readtag_rv (name, rvec, ierr)
     794              :     !
     795              :     ! As readtag_c, for a vector of real values
     796              :     !
     797              :     CHARACTER(LEN=*), INTENT(IN) :: name
     798              :     REAL(dp), INTENT(OUT)         :: rvec(:)
     799              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     800              :     INTEGER :: ier_
     801              :     !
     802          283 :     CALL xmlr_opentag (name, ier_)
     803          283 :     if ( ier_ == 0  ) then
     804          259 :        READ(xmlunit, *) rvec
     805          259 :        CALL xmlr_closetag ( )
     806              :     else
     807        34404 :        rvec = 0.0_dp
     808              :     end if
     809          283 :     IF ( present (ierr) ) ierr = ier_
     810              :     !
     811          283 :   END SUBROUTINE readtag_rv
     812              :   !
     813           16 :   SUBROUTINE readtag_rm (name, rmat, ierr)
     814              :     !
     815              :     ! As readtag_c, for a matrix of real values
     816              :     !
     817              :     CHARACTER(LEN=*), INTENT(IN) :: name
     818              :     REAL(dp), INTENT(OUT)         :: rmat(:,:)
     819              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     820              :     INTEGER :: ier_
     821              :     !
     822           16 :     CALL xmlr_opentag (name, ier_)
     823           16 :     if ( ier_ == 0  ) then
     824           16 :        READ(xmlunit, *) rmat
     825           16 :        CALL xmlr_closetag ( )
     826              :     else
     827            0 :        rmat = 0.0_dp
     828              :     end if
     829           16 :     IF ( present (ierr) ) ierr = ier_
     830              :     !
     831           16 :   END SUBROUTINE readtag_rm
     832              :   !
     833            0 :   SUBROUTINE readtag_rt (name, rtens, ierr)
     834              :     !
     835              :     ! As readtag_c, for a 3-dim tensor of real values
     836              :     !
     837              :     CHARACTER(LEN=*), INTENT(IN) :: name
     838              :     REAL(dp), INTENT(OUT)         :: rtens(:,:,:)
     839              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     840              :     INTEGER :: ier_
     841              :     !
     842            0 :     CALL xmlr_opentag (name, ier_)
     843            0 :     if ( ier_ == 0  ) then
     844            0 :        READ(xmlunit, *) rtens
     845            0 :        CALL xmlr_closetag ( )
     846              :     else
     847            0 :        rtens = 0.0_dp
     848              :     end if
     849            0 :     IF ( present (ierr) ) ierr = ier_
     850              :     !
     851            0 :   END SUBROUTINE readtag_rt
     852              :   !
     853            0 :   SUBROUTINE readtag_zv (name, zvec, ierr)
     854              :     !
     855              :     ! As readtag_c, for a vector of complex values - see comments in writetag_zv
     856              :     !
     857              :     use, intrinsic :: iso_c_binding
     858              :     CHARACTER(LEN=*), INTENT(IN) :: name
     859              :     COMPLEX(dp), INTENT(OUT), target     :: zvec(:)
     860              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     861              :     !
     862              :     TYPE (c_ptr) :: cp
     863            0 :     REAL(dp), POINTER  :: rvec(:)
     864              :     INTEGER :: ier_
     865              :     !
     866            0 :     CALL xmlr_opentag (name, ier_)
     867            0 :     if ( ier_ == 0  ) then
     868            0 :        NULLIFY (rvec)
     869            0 :        cp = c_loc(zvec)
     870            0 :        CALL c_f_pointer ( cp, rvec, shape(zvec)*[2])
     871            0 :        READ( xmlunit, *) rvec
     872            0 :        CALL xmlr_closetag ( )
     873              :     else
     874            0 :        zvec = 0.0_dp
     875              :     end if
     876            0 :     IF ( present (ierr) ) ierr = ier_
     877              :     !
     878            0 :   END SUBROUTINE readtag_zv
     879              :   !
     880            0 :   SUBROUTINE readtag_zm (name, zmat, ierr)
     881              :     !
     882              :     ! As readtag_c, for a matrix of complex values - see comments in writetag_zv
     883              :     !
     884              :     use, intrinsic :: iso_c_binding
     885              :     CHARACTER(LEN=*), INTENT(IN) :: name
     886              :     COMPLEX(dp), INTENT(OUT), target     :: zmat(:,:)
     887              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     888              :     TYPE (c_ptr) :: cp
     889            0 :     REAL(dp), POINTER  :: rmat(:,:)
     890              :     INTEGER :: ier_
     891              :     !
     892            0 :     CALL xmlr_opentag (name, ier_)
     893            0 :     if ( ier_ == 0  ) then
     894            0 :        NULLIFY (rmat)
     895            0 :        cp = c_loc(zmat)
     896            0 :        CALL c_f_pointer (cp, rmat, shape(zmat)*[2,1])
     897            0 :        READ(xmlunit, *) rmat
     898            0 :        CALL xmlr_closetag ( )
     899              :     else
     900            0 :        zmat = 0.0_dp
     901              :     end if
     902            0 :     IF ( present (ierr) ) ierr = ier_
     903              :     !
     904            0 :   END SUBROUTINE readtag_zm
     905              :     !
     906            0 :   SUBROUTINE readtag_zt (name, ztens, ierr)
     907              :     !
     908              :     ! As readtag_c, for a matrix of complex values - see comments in writetag_zv
     909              :     !
     910              :     use, intrinsic :: iso_c_binding
     911              :     CHARACTER(LEN=*), INTENT(IN) :: name
     912              :     COMPLEX(dp), INTENT(OUT), target     :: ztens(:,:,:)
     913              :     INTEGER, INTENT(OUT),OPTIONAL :: ierr
     914              :     TYPE (c_ptr) :: cp
     915            0 :     REAL(dp), POINTER  :: rtens(:,:,:)
     916              :     INTEGER :: ier_
     917              :     !
     918            0 :     CALL xmlr_opentag (name, ier_)
     919            0 :     if ( ier_ == 0  ) then
     920            0 :        NULLIFY (rtens)
     921            0 :        cp = c_loc(ztens)
     922            0 :        CALL c_f_pointer (cp, rtens, shape(ztens)*[2,1,1])
     923            0 :        READ(xmlunit, *) rtens
     924            0 :        CALL xmlr_closetag ( )
     925              :     else
     926            0 :        ztens = 0.0_dp
     927              :     end if
     928            0 :     IF ( present (ierr) ) ierr = ier_
     929              :     !
     930            0 :   END SUBROUTINE readtag_zt
     931              :     !
     932          106 :   subroutine readtag_c ( tag, cval, ierr)
     933              :     !
     934              :     !implicit none
     935              :     !
     936              :     character(len=*), intent(in) :: tag
     937              :     character(len=*), intent(out):: cval
     938              :     integer, intent(out), optional :: ierr
     939              :     !
     940              :     integer ::  i, j, lt !, ll
     941              :     character(len=1) :: endtag
     942              :     !
     943          106 :     call xmlr_opentag ( tag, ierr )
     944              :     !
     945          106 :     cval = ''
     946          106 :     if ( eot < 0 ) then
     947            0 :        if ( .not. present(ierr) ) then
     948            0 :           write(std_out,*) 'end of file reached, tag not found'
     949              :        else
     950            0 :           ierr = 1
     951              :        end if
     952          106 :        return
     953          106 :     else if ( eot == 0 ) then
     954              :        ! print *, 'tag found, no value to read on line'
     955              :        return
     956              :     else
     957              :        ! scan current line if there is something after the end of tag
     958              :        ! (variable "eot"); read a new line otherwise
     959            0 :        do while(.true.)
     960            0 :           if ( eot > len_trim(line) ) then
     961            0 :              read(xmlunit,'(a)', end=10) line
     962            0 :              j = 1
     963              :           else
     964              :              j = eot
     965              :           end if
     966              :           ! beginning of val at line(j:j): search for end tag
     967            0 :           i = index ( line(j:), '</'//trim(tag) )
     968            0 :           if ( i < 1 ) then
     969              :              ! </tag> not found on this line: read value and continue
     970            0 :              cval = trim(cval) // adjustl(trim(line(j:)))
     971              :           else
     972              :              ! possible end tag found
     973            0 :              lt = len_trim(tag)
     974            0 :              endtag = adjustl( line(j+i+1+lt:) )
     975            0 :              if ( endtag /= '>' ) then
     976            0 :                 if ( .not.present(ierr)) then
     977            0 :                    write(std_out,*) 'tag ',trim(tag),' not correctly closed'
     978              :                 else
     979            0 :                    ierr = 2
     980              :                 endif
     981              :              else
     982              :                 ! end of tag found, read value (if any) and exit
     983            0 :                 if ( i > 1 ) cval = trim(cval) // adjustl(trim(line(j:j+i-2)))
     984              :                 ! print *, 'value=',cval
     985              :              end if
     986              : #if defined ( __debug )
     987              :              print '("closed (read) level-",i1," tag ",A)', &
     988              :                      nlevel, trim(open_tags(nlevel))
     989              : #endif
     990            0 :              nlevel = nlevel -1
     991              :              !
     992            0 :              return
     993              :              !
     994              :           endif
     995              :           !
     996              :        end do
     997              :        !
     998              :     end if
     999              :     ! print *, 'tag </',trim(tag),'> not found'
    1000            0 : 10  if ( present(ierr) ) then
    1001            0 :        ierr = 1
    1002              :     else
    1003            0 :        write(std_out,*) 'end of file reached, tag </'//trim(tag)//'> not found'
    1004              :     end if
    1005              :     !
    1006          106 :   end subroutine readtag_c
    1007              :   !
    1008          491 :   subroutine xmlr_opentag ( tag, ierr)
    1009              :     !
    1010              :     !implicit none
    1011              :     !
    1012              :     character(len=*), intent(in) :: tag
    1013              :     integer, intent(out), optional :: ierr
    1014              :     ! See list of error codes in the header of this file
    1015              :     integer :: stat, ntry, ll, lt, i, j, j0
    1016              :     ! stat=-1: in comment (not actually used)
    1017              :     ! stat= 0: begin
    1018              :     ! stat= 1: tag found
    1019              :     !
    1020              :     character(len=1) :: quote
    1021              :     !
    1022          491 :     nattr=0
    1023          491 :     ntry =0
    1024          387 :     if ( allocated(attrlist) ) deallocate (attrlist)
    1025          491 :     lt = len_trim(tag)
    1026              :     !
    1027          557 :  1  ntry = ntry+1
    1028          557 :     stat=0
    1029          557 :     eot =-1
    1030              :     do while (.true.)
    1031       619182 :        read(xmlunit,'(a)', end=10) line
    1032       619076 :        ll = len_trim(line)
    1033       619076 :        if ( ll == maxline ) then
    1034            0 :           write(std_out,*)'xmlr_opentag: severe error, line too long'
    1035            0 :           if (present(ierr)) ierr = 3
    1036          451 :           return
    1037              :        end if
    1038              :        ! j is the current scan position
    1039              :        j = 1
    1040              :        ! j0 is the start of attributes and values
    1041              :        j0 = 1
    1042       644225 :        parse: do while ( j <= ll )
    1043              :           !
    1044              :           ! following case is never set and unnecessary:
    1045              :           !if ( stat ==-1 ) then
    1046              :           !   ! scanning a comment
    1047              :           !   i = index(line(j:),'-->')
    1048              :           !   if ( i == 0 ) then
    1049              :           !      ! no end of comment found on this line
    1050              :           !      exit parse
    1051              :           !   else
    1052              :           !      ! end of comment found
    1053              :           !      stat = 0
    1054              :           !      j = j+i+3
    1055              :           !   end if
    1056              :           !else if ( stat == 0 ) then
    1057      1260757 :           if ( stat == 0 ) then
    1058              :              !
    1059              :              ! searching for tag
    1060              :              !
    1061       616983 :              i = index( line(j:),'<'//trim(tag) )
    1062       616983 :              if ( i == 0 ) then
    1063              :                 ! no tag found on this line
    1064              :                 exit parse
    1065              :              else
    1066              :                 ! tag found? check what follows our would-be tag
    1067          451 :                 j = j+i+lt
    1068          451 :                 if ( j > ll ) then
    1069              :                    stat = 1
    1070              :                    ! <tag continues in next line
    1071              :                    exit parse
    1072              :                 else if ( line(j:j) == ' ' .or. line(j:j) == '>' &
    1073          264 :                                            .or. line(j:j+1)=='/>') then
    1074              :                    ! <tag or <tag> or <tag/> found
    1075          264 :                    stat = 1
    1076              :                 end if
    1077              :              end if
    1078              :              !
    1079              :           else if ( stat == 1 ) then
    1080              :              ! tag found, search for attributes if any or end of tag
    1081        25336 :              if (line(j:j) == ' ' ) then
    1082              :                 ! skip blanks: there is at least one if attributes are present
    1083         3577 :                 j = j+1
    1084              :                 ! save value of j into j0: beginning of an attribute
    1085         3577 :                 j0= j
    1086        21759 :              else if ( line(j:j+1) == '/>' ) then
    1087              :                 ! <tag ... /> found : return
    1088          106 :                 if (present(ierr)) ierr =-1
    1089              :                 ! eot = 0: tag with no value found
    1090          106 :                 eot = 0
    1091              :                 !
    1092          106 :                 return
    1093              :                 !
    1094        21653 :              else if ( line(j:j) == '>' ) then
    1095              :                 ! <tag ... > found
    1096              :                 ! eot points to the rest of the line
    1097          345 :                 eot = j+1
    1098          345 :                 if (present(ierr)) ierr = 0
    1099          345 :                 nlevel = nlevel+1
    1100          345 :                 IF ( nlevel > maxlevel ) THEN
    1101            0 :                    write(std_out,*) 'xmlr_opentag: severe error, too many levels'
    1102            0 :                    if (present(ierr)) ierr = 4
    1103              :                 else
    1104          345 :                    open_tags(nlevel) = trim(tag)
    1105              : #if defined ( __debug )
    1106              :                    print '("opened (read) level-",i1," tag ",A)',&
    1107              :                        nlevel, trim(open_tags(nlevel))
    1108              : #endif
    1109              :                 end if
    1110              :                 !
    1111          345 :                 return
    1112              :                 !
    1113        21308 :              else if ( line(j:j) == '=' ) then
    1114              :                 ! end of attribute located: save attribute (with final =)
    1115         2249 :                 nattr=nattr+1
    1116              :                 ! print *, 'attr=',line(j0:j-1)
    1117         2249 :                 if ( nattr == 1 ) then
    1118          397 :                    attrlist = line(j0:j)
    1119              :                 else
    1120         1852 :                    attrlist = attrlist//' '//line(j0:j)
    1121              :                 end if
    1122              :                 ! continue searching for attribute value
    1123              :                 j = j+1
    1124        19059 :              else if ( line(j:j) == '"' .or. line(j:j) =="'" ) then
    1125              :                 ! first occurrence of ' or " found, look for next
    1126         2249 :                 quote = line(j:j)
    1127         2249 :                 i = index(line(j+1:),quote)
    1128         2249 :                 if ( i < 1 ) then
    1129              :                    ! print *, 'Error: matching quote not found'
    1130              :                    go to 10
    1131              :                 else
    1132              :                    ! save attribute value (with quotes) and continue scanning
    1133              :                    ! print *, 'attrval=',line(j:j+i-2)
    1134         2249 :                    attrlist = attrlist//line(j:j+i)
    1135         2249 :                    j = j+i+1
    1136              :                 end if
    1137              :              else
    1138              :                 ! continue scanning until end of attribute
    1139              :                 j = j+1
    1140              :              endif
    1141              :              !
    1142              :           end if
    1143              :        end do parse
    1144              :        !
    1145              :     end do
    1146              :     !
    1147          106 : 10  if ( stat == 0 ) then
    1148          106 :        if ( present(ierr) ) then
    1149          106 :           ierr = 1
    1150              :           ! quick-and-dirty pseudo-fix to deal with tags not found:
    1151              :           ! rewind and try again - will work if the desired tag is
    1152              :           ! found above the current position (and nowhere else)
    1153          106 :           rewind(xmlunit)
    1154          106 :           if ( ntry == 1 ) go to 1
    1155              :        else
    1156            0 :           write(std_out,*) 'end of file reached, tag '//trim(tag)//' not found'
    1157              :        end if
    1158              :     else
    1159            0 :        write(std_out,*) 'xmlr_opentag: severe parsing error'
    1160            0 :        if ( present(ierr) ) ierr = 2
    1161              :     end if
    1162              :     !
    1163          491 :   end subroutine xmlr_opentag
    1164              :   !
    1165          345 :   subroutine xmlr_closetag ( tag, ierr)
    1166              :     !
    1167              :     !implicit none
    1168              :     !
    1169              :     character(len=*), intent(in), optional :: tag
    1170              :     integer, intent(out), optional :: ierr
    1171              :     ! 0: </tag> found
    1172              :     ! 1: </tag> not found
    1173              :     ! 2: error parsing file
    1174              :     !
    1175              :     integer :: stat, ll, lt, i, j
    1176              :     ! stat=-1: in comment (not actually used)
    1177              :     ! stat= 0: begin
    1178              :     ! stat= 1: end
    1179              :     !
    1180          345 :     if ( nlevel < 0 ) &
    1181            0 :          print '("xmlr_closetag: severe error, closing tag that was never opened")'
    1182              :     stat=0
    1183              : #if defined ( __debug )
    1184              :     if ( .not. present(tag) ) then
    1185              :        print '("closed (read) level-",i1," tag ",A)', &
    1186              :             nlevel, trim(open_tags(nlevel))
    1187              :     else
    1188              :        print '("closed (read) level-",i1," tag ",A)', nlevel, tag
    1189              :     end if
    1190              : #endif
    1191              :     do while (.true.)
    1192        24336 :        read(xmlunit,'(a)', end=10) line
    1193        24336 :        ll = len_trim(line)
    1194        24336 :        if ( ll == maxline ) then
    1195            0 :           write(std_out,*) 'Fatal error: line too long'
    1196            0 :           if (present(ierr)) ierr = 2
    1197            0 :           return
    1198              :        end if
    1199              :        ! j is the current scan position
    1200              :        j = 1
    1201        24681 :        parse: do while ( j <= ll )
    1202              :           !
    1203              :           ! following case is never set and unnecessary:
    1204              :           !if ( stat ==-1 ) then
    1205              :           ! scanning a comment
    1206              :           !   i = index(line(j:),'-->')
    1207              :           !   if ( i == 0 ) then
    1208              :           ! no end of comment found on this line
    1209              :           !      exit parse
    1210              :           !   else
    1211              :           ! end of comment found
    1212              :           !      stat = 0
    1213              :           !      j = j+i+3
    1214              :           !   end if
    1215              :           !else if ( stat == 0 ) then
    1216        48648 :           if ( stat == 0 ) then
    1217              :              !
    1218              :              ! searching for closing tag
    1219              :              !
    1220        24312 :              IF ( .NOT.PRESENT(tag) ) THEN
    1221        24312 :                 i = index( line(j:),'</'//trim(open_tags(nlevel)) )
    1222        24312 :                 lt= len_trim(open_tags(nlevel))
    1223              :              ELSE
    1224            0 :                 i = index( line(j:),'</'//trim(tag) )
    1225            0 :                 lt= len_trim(tag)
    1226              :              END IF
    1227        24312 :              if ( i == 0 ) then
    1228              :                 ! no tag found on this line
    1229              :                 exit parse
    1230              :              else
    1231              :                 ! tag found? check what follows our would-be tag
    1232          345 :                 j = j+i+1+lt
    1233          345 :                 if ( j > ll ) then
    1234              :                    stat = 1
    1235              :                    ! </tag continues in next line
    1236              :                    exit parse
    1237          345 :                 else if ( line(j:j) == ' ' .or. line(j:j) == '>') then
    1238              :                    ! </tag or </tag> found
    1239          345 :                    stat = 1
    1240              :                 end if
    1241              :              end if
    1242              :              !
    1243              :           else if ( stat == 1 ) then
    1244              :              !
    1245              :              ! </tag found, search for end of tag
    1246              :              !
    1247          345 :              if (line(j:j) == ' ' ) then
    1248              :                 ! skip blanks
    1249            0 :                 j = j+1
    1250          345 :              else if ( line(j:j) == '>' ) then
    1251              :                 ! </tag ... > found
    1252              :                 ! print *, '</tag> found'
    1253          345 :                 if ( present(ierr) ) ierr = 0
    1254              :                 !print '("closed")'
    1255          345 :                 nlevel = nlevel - 1
    1256              :                 !
    1257          345 :                 return
    1258              :                 !
    1259              :              endif
    1260              :              !
    1261              :           end if
    1262              :        end do parse
    1263              :        !
    1264              :     end do
    1265              :     !
    1266            0 : 10  write(std_out,*) 'end of file reached, closing tag not found'
    1267            0 :     if ( present(ierr) ) ierr = 1
    1268              :     !
    1269              :   end subroutine xmlr_closetag
    1270              : 
    1271         4101 : END MODULE xmltools
        

Generated by: LCOV version 2.3-1