!===============================================================================
! SVN $Id: shr_string_mod.F90 18548 2009-09-26 23:55:51Z tcraig $
! SVN $URL: https://svn-ccsm-models.cgd.ucar.edu/csm_share/branch_tags/cesm1_0_rel_tags/cesm1_0_rel01_share3_100616/shr/shr_string_mod.F90 $
!===============================================================================
!===============================================================================
!BOP ===========================================================================
!
! !MODULE: shr_string_mod -- string and list methods
!
! !DESCRIPTION:
! General string and specific list method. A list is a single string
! that is delimited by a character forming multiple fields, ie,
! character(len=*) :: mylist = "t:s:u1:v1:u2:v2:taux:tauy"
! The delimiter is called listDel in this module, is default ":",
! but can be set by a call to shr_string_listSetDel.
!
! !REVISION HISTORY:
! 2005-Apr-28 - T. Craig - first version
!
! !INTERFACE: ------------------------------------------------------------------
module shr_string_mod 19,6
! !USES:
use shr_kind_mod
! F90 kinds
use shr_sys_mod
! shared system calls
use shr_cal_mod
! shared calendar
use shr_timer_mod
, only : shr_timer_get, shr_timer_start, shr_timer_stop
use shr_log_mod
, only : s_loglev => shr_log_Level
use shr_log_mod
, only : s_logunit => shr_log_Unit
implicit none
private
! !PUBLIC TYPES:
! no public types
! !PUBLIC MEMBER FUNCTIONS:
public :: shr_string_countChar ! Count number of char in string, fn
public :: shr_string_toUpper ! Convert string to upper-case
public :: shr_string_toLower ! Convert string to lower-case
public :: shr_string_getParentDir ! For a pathname get the parent directory name
public :: shr_string_lastIndex ! Index of last substr in str
public :: shr_string_endIndex ! Index of end of substr in str
public :: shr_string_leftAlign ! remove leading white space
public :: shr_string_alphanum ! remove all non alpha-numeric characters
public :: shr_string_betweenTags ! get the substring between the two tags
public :: shr_string_parseCFtunit ! parse CF time units
public :: shr_string_clean ! Set string to all white space
public :: shr_string_listIsValid ! test for a valid "list"
public :: shr_string_listGetNum ! Get number of fields in list, fn
public :: shr_string_listGetIndex ! Get index of field
public :: shr_string_listGetIndexF ! function version of listGetIndex
public :: shr_string_listGetName ! get k-th field name
public :: shr_string_listIntersect ! get intersection of two field lists
public :: shr_string_listUnion ! get union of two field lists
public :: shr_string_listMerge ! merge two lists to form third
public :: shr_string_listAppend ! append list at end of another
public :: shr_string_listPrepend ! prepend list in front of another
public :: shr_string_listSetDel ! Set field delimeter in lists
public :: shr_string_listGetDel ! Get field delimeter in lists
public :: shr_string_setAbort ! set local abort flag
public :: shr_string_setDebug ! set local debug flag
! !PUBLIC DATA MEMBERS:
! no public data members
!EOP
character(len=1) ,save :: listDel = ":" ! note single exec implications
character(len=2) ,save :: listDel2 = "::" ! note single exec implications
logical ,save :: doabort = .true.
integer(SHR_KIND_IN),save :: debug = 0
!===============================================================================
contains
!===============================================================================
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_countChar -- Count number of occurances of a character
!
! !DESCRIPTION:
! count number of occurances of a single character in a string
! \newline
! n = shr\_string\_countChar(string,character)
!
! !REVISION HISTORY:
! 2005-Feb-28 - First version from dshr_bundle
!
! !INTERFACE: ------------------------------------------------------------------
integer function shr_string_countChar(str,char,rc) 1,3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: str ! string to search
character(1) ,intent(in) :: char ! char to search for
integer(SHR_KIND_IN),intent(out),optional :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: count ! counts occurances of char
integer(SHR_KIND_IN) :: n ! generic index
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_countChar) "
character(*),parameter :: F00 = "('(shr_string_countChar) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
count = 0
do n = 1, len_trim(str)
if (str(n:n) == char) count = count + 1
end do
shr_string_countChar = count
if (present(rc)) rc = 0
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_countChar
!===============================================================================
!BOP ===========================================================================
! !IROUTINE: shr_string_toUpper -- Convert string to upper case
!
! !DESCRIPTION:
! Convert the input string to upper-case.
! Use achar and iachar intrinsics to ensure use of ascii collating sequence.
!
! !REVISION HISTORY:
! 2005-Dec-20 - Move CAM version over to shared code.
!
! !INTERFACE: ------------------------------------------------------------------
function shr_string_toUpper(str) 6,4
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(len=*), intent(in) :: str ! String to convert to upper case
character(len=len(str)) :: shr_string_toUpper
!----- local -----
integer(SHR_KIND_IN) :: i ! Index
integer(SHR_KIND_IN) :: aseq ! ascii collating sequence
integer(SHR_KIND_IN) :: LowerToUpper ! integer to convert case
character(len=1) :: ctmp ! Character temporary
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_toUpper) "
character(*),parameter :: F00 = "('(shr_string_toUpper) ',4a)"
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
LowerToUpper = iachar("A") - iachar("a")
do i = 1, len(str)
ctmp = str(i:i)
aseq = iachar(ctmp)
if ( aseq >= iachar("a") .and. aseq <= iachar("z") ) &
ctmp = achar(aseq + LowertoUpper)
shr_string_toUpper
(i:i) = ctmp
end do
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_toUpper
!===============================================================================
!BOP ===========================================================================
! !IROUTINE: shr_string_toLower -- Convert string to lower case
!
! !DESCRIPTION:
! Convert the input string to lower-case.
! Use achar and iachar intrinsics to ensure use of ascii collating sequence.
!
! !REVISION HISTORY:
! 2006-Apr-20 - Creation
!
! !INTERFACE: ------------------------------------------------------------------
function shr_string_toLower(str) 1,4
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(len=*), intent(in) :: str ! String to convert to lower case
character(len=len(str)) :: shr_string_toLower
!----- local -----
integer(SHR_KIND_IN) :: i ! Index
integer(SHR_KIND_IN) :: aseq ! ascii collating sequence
integer(SHR_KIND_IN) :: UpperToLower ! integer to convert case
character(len=1) :: ctmp ! Character temporary
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_toLower) "
character(*),parameter :: F00 = "('(shr_string_toLower) ',4a)"
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
UpperToLower = iachar("a") - iachar("A")
do i = 1, len(str)
ctmp = str(i:i)
aseq = iachar(ctmp)
if ( aseq >= iachar("A") .and. aseq <= iachar("Z") ) &
ctmp = achar(aseq + UpperToLower)
shr_string_toLower
(i:i) = ctmp
end do
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_toLower
!===============================================================================
!BOP ===========================================================================
! !IROUTINE: shr_string_getParentDir -- For pathname get the parent directory name
!
! !DESCRIPTION:
! Get the parent directory name for a pathname.
!
! !REVISION HISTORY:
! 2006-May-09 - Creation
!
! !INTERFACE: ------------------------------------------------------------------
function shr_string_getParentDir(str),3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(len=*), intent(in) :: str ! String to convert to lower case
character(len=len(str)) :: shr_string_getParentDir
!----- local -----
integer(SHR_KIND_IN) :: i ! Index
integer(SHR_KIND_IN) :: nlen ! Length of string
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_getParentDir) "
character(*),parameter :: F00 = "('(shr_string_getParentDir) ',4a)"
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
nlen = len_trim(str)
if ( str(nlen:nlen) == "/" ) nlen = nlen - 1
i = index( str(1:nlen), "/", back=.true. )
if ( i == 0 )then
shr_string_getParentDir = str
else
shr_string_getParentDir = str(1:i-1)
end if
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_getParentDir
!===============================================================================
!BOP ===========================================================================
!
!
! !IROUTINE: shr_string_lastIndex -- Get index of last substr within string
!
! !DESCRIPTION:
! Get index of last substr within string
! \newline
! n = shr\_string\_lastIndex(string,substring)
!
! !REVISION HISTORY:
! 2005-Feb-28 - First version from dshr_domain
!
! !INTERFACE: ------------------------------------------------------------------
integer function shr_string_lastIndex(string,substr,rc) 7,3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: string ! string to search
character(*) ,intent(in) :: substr ! sub-string to search for
integer(SHR_KIND_IN),intent(out),optional :: rc ! return code
!EOP
!--- local ---
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_lastIndex) "
character(*),parameter :: F00 = "('(shr_string_lastIndex) ',4a)"
!-------------------------------------------------------------------------------
! Note:
! - "new" F90 back option to index function makes this home-grown solution obsolete
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
shr_string_lastIndex = index(string,substr,.true.)
if (present(rc)) rc = 0
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_lastIndex
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_endIndex -- Get the ending index of substr within string
!
! !DESCRIPTION:
! Get the ending index of substr within string
! \newline
! n = shr\_string\_endIndex(string,substring)
!
! !REVISION HISTORY:
! 2005-May-10 - B. Kauffman, first version.
!
! !INTERFACE: ------------------------------------------------------------------
integer function shr_string_endIndex(string,substr,rc) 1,3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: string ! string to search
character(*) ,intent(in) :: substr ! sub-string to search for
integer(SHR_KIND_IN),intent(out),optional :: rc ! return code
!EOP
!--- local ---
integer(SHR_KIND_IN) :: i ! generic index
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_endIndex) "
character(*),parameter :: F00 = "('(shr_string_endIndex) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! * returns zero if substring not found, uses len_trim() intrinsic
! * very similar to: i = index(str,substr,back=.true.)
! * do we need this function?
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
i = index(trim(string),trim(substr))
if ( i == 0 ) then
shr_string_endIndex = 0 ! substr is not in string
else
shr_string_endIndex = i + len_trim(substr) - 1
end if
! -------------------------------------------------------------------
! i = index(trim(string),trim(substr),back=.true.)
! if (i == len(string)+1) i = 0
! shr_string_endIndex = i
! -------------------------------------------------------------------
if (present(rc)) rc = 0
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_endIndex
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_leftAlign -- remove leading white space
!
! !DESCRIPTION:
! Remove leading white space
! \newline
! call shr\_string\_leftAlign(string)
!
! !REVISION HISTORY:
! 2005-Apr-28 - B. Kauffman - First version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_leftAlign(str,rc) 22,3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(inout) :: str
integer(SHR_KIND_IN),intent(out) ,optional :: rc ! return code
!EOP
!----- local ----
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_leftAlign) "
character(*),parameter :: F00 = "('(shr_string_leftAlign) ',4a)"
!-------------------------------------------------------------------------------
! note:
! * ?? this routine isn't needed, use the intrisic adjustL instead ??
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
! -------------------------------------------------------------------
! --- I used this until I discovered the intrinsic function below - BK
! do while (len_trim(str) > 0 )
! if (str(1:1) /= ' ') exit
! str = str(2:len_trim(str))
! end do
! rCode = 0
! !! (len_trim(str) == 0 ) rCode = 1 ! ?? appropriate ??
! -------------------------------------------------------------------
str = adjustL(str)
if (present(rc)) rc = 0
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_leftAlign
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_alphanum -- remove non alpha numeric characters
!
! !DESCRIPTION:
! Remove all non alpha numeric characters from string
! \newline
! call shr\_string\_alphanum(string)
!
! !REVISION HISTORY:
! 2005-Aug-01 - T. Craig - First version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_alphanum(str,rc),3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(inout) :: str
integer(SHR_KIND_IN),intent(out) ,optional :: rc ! return code
!EOP
!----- local ----
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: n,icnt ! counters
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_alphaNum) "
character(*),parameter :: F00 = "('(shr_string_alphaNum) ',4a)"
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
icnt = 0
do n=1,len_trim(str)
if ((str(n:n) >= 'a' .and. str(n:n) <= 'z') .or. &
(str(n:n) >= 'A' .and. str(n:n) <= 'Z') .or. &
(str(n:n) >= '0' .and. str(n:n) <= '9')) then
icnt = icnt + 1
str(icnt:icnt) = str(n:n)
endif
enddo
do n=icnt+1,len(str)
str(n:n) = ' '
enddo
if (present(rc)) rc = 0
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_alphanum
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_betweenTags -- Get the substring between the two tags.
!
! !DESCRIPTION:
! Get the substring found between the start and end tags.
! \newline
! call shr\_string\_betweenTags(string,startTag,endTag,substring,rc)
!
! !REVISION HISTORY:
! 2005-May-11 - B. Kauffman, first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_betweenTags(string,startTag,endTag,substr,rc),4
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: string ! string to search
character(*) ,intent(in) :: startTag ! start tag
character(*) ,intent(in) :: endTag ! end tag
character(*) ,intent(out) :: substr ! sub-string between tags
integer(SHR_KIND_IN),intent(out),optional :: rc ! retrun code
!EOP
!--- local ---
integer(SHR_KIND_IN) :: iStart ! substring start index
integer(SHR_KIND_IN) :: iEnd ! substring end index
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_betweenTags) "
character(*),parameter :: F00 = "('(shr_string_betweenTags) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! * assumes the leading/trailing white space is not part of start & end tags
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
iStart = shr_string_endIndex
(string,trim(adjustL(startTag))) ! end of start tag
iEnd = index(string,trim(adjustL(endTag ))) ! start of end tag
rCode = 0
substr = ""
if (iStart < 1) then
if (s_loglev > 0) then
write(s_logunit,F00) "ERROR: can't find start tag in string"
write(s_logunit,F00) "ERROR: start tag = ",trim(startTag)
write(s_logunit,F00) "ERROR: string = ",trim(string)
endif
rCode = 1
else if (iEnd < 1) then
if (s_loglev > 0) then
write(s_logunit,F00) "ERROR: can't find end tag in string"
write(s_logunit,F00) "ERROR: end tag = ",trim( endTag)
write(s_logunit,F00) "ERROR: string = ",trim(string)
endif
rCode = 2
else if ( iEnd <= iStart) then
if (s_loglev > 0) then
write(s_logunit,F00) "ERROR: start tag not before end tag"
write(s_logunit,F00) "ERROR: start tag = ",trim(startTag)
write(s_logunit,F00) "ERROR: end tag = ",trim( endTag)
write(s_logunit,F00) "ERROR: string = ",trim(string)
endif
rCode = 3
else if ( iStart+1 == iEnd ) then
substr = ""
if (s_loglev > 0) write(s_logunit,F00) "WARNING: zero-length substring found in ",trim(string)
else
substr = string(iStart+1:iEnd-1)
if (len_trim(substr) == 0 .and. s_loglev > 0) &
& write(s_logunit,F00) "WARNING: white-space substring found in ",trim(string)
end if
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_betweenTags
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_parseCFtunit -- Parse CF time unit
!
! !DESCRIPTION:
! Parse CF time unit into a delta string name and a base time in yyyymmdd
! and seconds (nearest integer actually).
! \newline
! call shr\_string\_parseCFtunit(string,substring)
! \newline
! Input string is like "days since 0001-06-15 15:20:45.5 -6:00"
! - recognizes "days", "hours", "minutes", "seconds"
! - must have at least yyyy-mm-dd, hh:mm:ss.s is optional
! - expects a "since" in the string
! - ignores time zone part
!
! !REVISION HISTORY:
! 2005-May-15 - T. Craig - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_parseCFtunit(string,unit,bdate,bsec,rc) 2,19
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: string ! string to search
character(*) ,intent(out) :: unit ! delta time unit
integer(SHR_KIND_IN),intent(out) :: bdate ! base date yyyymmdd
real(SHR_KIND_R8) ,intent(out) :: bsec ! base seconds
integer(SHR_KIND_IN),intent(out),optional :: rc ! return code
!EOP
!--- local ---
integer(SHR_KIND_IN) :: i,i1,i2 ! generic index
character(SHR_KIND_CL) :: tbase ! baseline time
character(SHR_KIND_CL) :: lstr ! local string
integer(SHR_KIND_IN) :: yr,mo,da,hr,min ! time stuff
real(SHR_KIND_R8) :: sec ! time stuff
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_parseCFtunit) "
character(*),parameter :: F00 = "('(shr_string_parseCFtunit) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! o assume length of CF-1.0 time attribute char string < SHR_KIND_CL
! This is a reasonable assumption.
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
unit = 'none'
bdate = 0
bsec = 0.0_SHR_KIND_R8
i = shr_string_lastIndex
(string,'days ')
if (i > 0) unit = 'days'
i = shr_string_lastIndex
(string,'hours ')
if (i > 0) unit = 'hours'
i = shr_string_lastIndex
(string,'minutes ')
if (i > 0) unit = 'minutes'
i = shr_string_lastIndex
(string,'seconds ')
if (i > 0) unit = 'seconds'
if (trim(unit) == 'none') then
write(s_logunit,F00) ' ERROR time unit unknown'
call shr_string_abort
(subName//' time unit unknown')
endif
i = shr_string_lastIndex
(string,' since ')
if (i < 1) then
write(s_logunit,F00) ' ERROR since does not appear in unit attribute for time '
call shr_string_abort
(subName//' no since in attr name')
endif
tbase = trim(string(i+6:))
call shr_string_leftAlign
(tbase)
if (debug > 0 .and. s_logunit > 0) then
write(s_logunit,*) trim(subName)//' '//'unit '//trim(unit)
write(s_logunit,*) trim(subName)//' '//'tbase '//trim(tbase)
endif
yr=0; mo=0; da=0; hr=0; min=0; sec=0
i1 = 1
i2 = index(tbase,'-') - 1
lstr = tbase(i1:i2)
read(lstr,*,ERR=200,END=200) yr
tbase = tbase(i2+2:)
call shr_string_leftAlign
(tbase)
i2 = index(tbase,'-') - 1
lstr = tbase(i1:i2)
read(lstr,*,ERR=200,END=200) mo
tbase = tbase(i2+2:)
call shr_string_leftAlign
(tbase)
i2 = index(tbase,' ') - 1
lstr = tbase(i1:i2)
read(lstr,*,ERR=200,END=200) da
tbase = tbase(i2+2:)
call shr_string_leftAlign
(tbase)
i2 = index(tbase,':') - 1
lstr = tbase(i1:i2)
read(lstr,*,ERR=200,END=100) hr
tbase = tbase(i2+2:)
call shr_string_leftAlign
(tbase)
i2 = index(tbase,':') - 1
lstr = tbase(i1:i2)
read(lstr,*,ERR=200,END=100) min
tbase = tbase(i2+2:)
call shr_string_leftAlign
(tbase)
i2 = index(tbase,' ') - 1
lstr = tbase(i1:i2)
read(lstr,*,ERR=200,END=100) sec
100 continue
if (debug > 0 .and. s_loglev > 0) write(s_logunit,*) trim(subName),'ymdhms:',yr,mo,da,hr,min,sec
call shr_cal_ymd2date
(yr,mo,da,bdate)
bsec = real(hr*3600 + min*60,SHR_KIND_R8) + sec
if (present(rc)) rc = 0
if (debug>1) call shr_timer_stop
(t01)
return
200 continue
write(s_logunit,F00) 'ERROR 200 on char num read '
call shr_string_abort
(subName//' ERROR on char num read')
if (debug>1) call shr_timer_stop
(t01)
return
end subroutine shr_string_parseCFtunit
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_clean -- Clean a string, set it to "blank"
!
! !DESCRIPTION:
! Clean a string, set it to blank
! \newline
! call shr\_string\_clean(string,rc)
!
! !REVISION HISTORY:
! 2005-May-05 - T. Craig
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_clean(string,rc) 7,3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(inout) :: string ! list/string
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: n ! counter
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_clean) "
character(*),parameter :: F00 = "('(shr_string_clean) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
string = ' '
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_clean
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listIsValid -- determine whether string is a valid list
!
! !DESCRIPTION:
! Determine whether string is a valid list
! \newline
! logical_var = shr\_string\_listIsValid(list,rc)
!
! !REVISION HISTORY:
! 2005-May-05 - B. Kauffman
!
! !INTERFACE: ------------------------------------------------------------------
logical function shr_string_listIsValid(list,rc),3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: list ! list/string
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer (SHR_KIND_IN) :: nChar ! lenth of list
integer (SHR_KIND_IN) :: rCode ! return code
integer (SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listIsValid) "
character(*),parameter :: F00 = "('(shr_string_listIsValid) ',4a)"
!-------------------------------------------------------------------------------
! check that the list conforms to the list format
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
shr_string_listIsValid = .true.
nChar = len_trim(list)
if (nChar < 1) then ! list is an empty string
rCode = 1
else if ( list(1:1) == listDel ) then ! first char is delimiter
rCode = 2
else if (list(nChar:nChar) == listDel ) then ! last char is delimiter
rCode = 3
else if (index(trim(list)," " ) > 0) then ! white-space in a field name
rCode = 4
else if (index(trim(list),listDel2) > 0) then ! found zero length field
rCode = 5
end if
if (rCode /= 0) then
shr_string_listIsValid = .false.
if (s_loglev > 0) write(s_logunit,F00) "WARNING: invalid list = ",trim(list)
endif
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_listIsValid
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listGetName -- Get name of k-th field in list
!
! !DESCRIPTION:
! Get name of k-th field in list
! \newline
! call shr\_string\_listGetName(list,k,name,rc)
!
! !REVISION HISTORY:
! 2005-May-05 - B. Kauffman
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listGetName(list,k,name,rc) 15,6
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: list ! list/string
integer(SHR_KIND_IN) ,intent(in) :: k ! index of field
character(*) ,intent(out) :: name ! k-th name in list
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: i,j,n ! generic indecies
integer(SHR_KIND_IN) :: kFlds ! number of fields in list
integer(SHR_KIND_IN) :: i0,i1 ! name = list(i0:i1)
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listGetName) "
character(*),parameter :: F00 = "('(shr_string_listGetName) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
!--- check that this is a valid list ---
if (.not. shr_string_listIsValid(list,rCode) ) then
write(s_logunit,F00) "ERROR: invalid list = ",trim(list)
call shr_string_abort
(subName//" ERROR: invalid list = "//trim(list))
end if
!--- check that this is a valid index ---
kFlds = shr_string_listGetNum
(list)
if (k<1 .or. kFlds<k) then
write(s_logunit,*) subName,"ERROR: invalid index = ",k
write(s_logunit,*) subName,"ERROR: list = ",trim(list)
call shr_string_abort
(subName//" ERROR: invalid index")
end if
!--- start with whole list, then remove fields before and after desired field ---
i0 = 1
i1 = len_trim(list)
!--- remove field names before desired field ---
do n=2,k
i = index(list(i0:i1),listDel)
i0 = i0 + i
end do
!--- remove field names after desired field ---
if ( k < kFlds ) then
i = index(list(i0:i1),listDel)
i1 = i0 + i - 2
end if
!--- copy result into output variable ---
name = list(i0:i1)//" "
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listGetName
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listIntersect -- Get intersection of two field lists
!
! !DESCRIPTION:
! Get intersection of two fields lists, write into third list
! \newline
! call shr\_string\_listIntersect(list1,list2,listout)
!
! !REVISION HISTORY:
! 2005-May-05 - T. Craig
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listIntersect(list1,list2,listout,rc) 1,8
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: list1 ! list/string
character(*) ,intent(in) :: list2 ! list/string
character(*) ,intent(out) :: listout ! list/string
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: nf,n1,n2 ! counters
character(SHR_KIND_CS) :: name ! field name
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listIntersect) "
character(*),parameter :: F00 = "('(shr_string_listIntersect) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
nf = shr_string_listGetNum
(list1)
call shr_string_clean
(listout)
do n1 = 1,nf
call shr_string_listGetName
(list1,n1,name,rCode)
n2 = shr_string_listGetIndexF
(list2,name)
if (n2 > 0) then
call shr_string_listAppend
(listout,name)
endif
enddo
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listIntersect
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listUnion -- Get union of two field lists
!
! !DESCRIPTION:
! Get union of two fields lists, write into third list
! \newline
! call shr\_string\_listUnion(list1,list2,listout)
!
! !REVISION HISTORY:
! 2005-May-05 - T. Craig
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listUnion(list1,list2,listout,rc),12
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: list1 ! list/string
character(*) ,intent(in) :: list2 ! list/string
character(*) ,intent(out) :: listout ! list/string
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: nf,n1,n2 ! counters
character(SHR_KIND_CS) :: name ! field name
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listUnion) "
character(*),parameter :: F00 = "('(shr_string_listUnion) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
call shr_string_clean
(listout)
nf = shr_string_listGetNum
(list1)
do n1 = 1,nf
call shr_string_listGetName
(list1,n1,name,rCode)
n2 = shr_string_listGetIndexF
(listout,name)
if (n2 < 1) then
call shr_string_listAppend
(listout,name)
endif
enddo
nf = shr_string_listGetNum
(list2)
do n1 = 1,nf
call shr_string_listGetName
(list2,n1,name,rCode)
n2 = shr_string_listGetIndexF
(listout,name)
if (n2 < 1) then
call shr_string_listAppend
(listout,name)
endif
enddo
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listUnion
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listMerge -- Merge lists two list to third
!
! !DESCRIPTION:
! Merge two list to third
! \newline
! call shr\_string\_listMerge(list1,list2,listout)
! call shr\_string\_listMerge(list1,list2,list1)
!
! !REVISION HISTORY:
! 2005-May-05 - T. Craig
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listMerge(list1,list2,listout,rc),10
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: list1 ! list/string
character(*) ,intent(in) :: list2 ! list/string
character(*) ,intent(out) :: listout ! list/string
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
character(SHR_KIND_CX) :: l1,l2 ! local char strings
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listMerge) "
character(*),parameter :: F00 = "('(shr_string_listMerge) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! - no input or output string should be longer than SHR_KIND_CX
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
!--- make sure temp strings are large enough ---
if ( (len(l1) < len_trim(list1)) .or. (len(l2) < len_trim(list2))) then
call shr_string_abort
(subName//'ERROR: temp string not large enough')
end if
call shr_string_clean
(l1)
call shr_string_clean
(l2)
call shr_string_clean
(listout)
l1 = trim(list1)
l2 = trim(list2)
call shr_string_leftAlign
(l1,rCode)
call shr_string_leftAlign
(l2,rCode)
if (len_trim(l1)+len_trim(l2)+1 > len(listout)) &
call shr_string_abort
(subName//'ERROR: output list string not large enough')
if (len_trim(l1) == 0) then
listout = trim(l2)
else
listout = trim(l1)//":"//trim(l2)
endif
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listMerge
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listAppend -- Append one list to another
!
! !DESCRIPTION:
! Append one list to another
! \newline
! call shr\_string\_listAppend(list,listadd)
!
! !REVISION HISTORY:
! 2005-May-05 - T. Craig
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listAppend(list,listadd,rc) 4,7
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(inout) :: list ! list/string
character(*) ,intent(in) :: listadd ! list/string
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
character(SHR_KIND_CX) :: l1 ! local string
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listAppend) "
character(*),parameter :: F00 = "('(shr_string_listAppend) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! - no input or output string should be longer than SHR_KIND_CX
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
!--- make sure temp string is large enough ---
if (len(l1) < len_trim(listAdd)) then
call shr_string_abort
(subName//'ERROR: temp string not large enough')
end if
call shr_string_clean
(l1)
l1 = trim(listadd)
call shr_string_leftAlign
(l1,rCode)
if (len_trim(list)+len_trim(l1)+1 > len(list)) &
call shr_string_abort
(subName//'ERROR: output list string not large enough')
if (len_trim(list) == 0) then
list = trim(l1)
else
list = trim(list)//":"//trim(l1)
endif
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listAppend
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listPrepend -- Prepend one list to another
!
! !DESCRIPTION:
! Prepend one list to another
! \newline
! call shr\_string\_listPrepend(listadd,list)
! \newline
! results in listadd:list
!
! !REVISION HISTORY:
! 2005-May-05 - T. Craig
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listPrepend(listadd,list,rc),8
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: listadd ! list/string
character(*) ,intent(inout) :: list ! list/string
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
character(SHR_KIND_CX) :: l1 ! local string
integer(SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listPrepend) "
character(*),parameter :: F00 = "('(shr_string_listPrepend) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! - no input or output string should be longer than SHR_KIND_CX
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
rCode = 0
!--- make sure temp string is large enough ---
if (len(l1) < len_trim(listAdd)) then
call shr_string_abort
(subName//'ERROR: temp string not large enough')
end if
call shr_string_clean
(l1)
l1 = trim(listadd)
call shr_string_leftAlign
(l1,rCode)
call shr_string_leftAlign
(list,rCode)
if (len_trim(list)+len_trim(l1)+1 > len(list)) &
call shr_string_abort
(subName//'ERROR: output list string not large enough')
if (len_trim(l1) == 0) then
list = trim(list)
else
list = trim(l1)//":"//trim(list)
endif
if (present(rc)) rc = rCode
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listPrepend
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listGetIndexF -- Get index of field in string
!
! !DESCRIPTION:
! Get index of field in string
! \newline
! k = shr\_string\_listGetIndex(str,"taux")
!
! !REVISION HISTORY:
! 2005-Feb-28 - B. Kauffman and J. Schramm - first version
!
! !INTERFACE: ------------------------------------------------------------------
integer function shr_string_listGetIndexF(string,fldStr) 448,4
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*),intent(in) :: string ! string
character(*),intent(in) :: fldStr ! name of field
!EOP
!----- local -----
integer(SHR_KIND_IN) :: k ! local index variable
integer(SHR_KIND_IN) :: rc ! error code
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listGetIndexF) "
character(*),parameter :: F00 = "('(shr_string_listGetIndexF) ',4a)"
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
call shr_string_listGetIndex
(string,fldStr,k,print=.false.,rc=rc)
shr_string_listGetIndexF = k
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_listGetIndexF
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listGetIndex -- Get index of field in string
!
! !DESCRIPTION:
! Get index of field in string
! \newline
! call shr\_string\_listGetIndex(str,"taux",k,rc)
!
! !REVISION HISTORY:
! 2005-Feb-28 - B. Kauffman and J. Schramm - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listGetIndex(string,fldStr,kFld,print,rc) 1,5
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: string ! string
character(*) ,intent(in) :: fldStr ! name of field
integer(SHR_KIND_IN),intent(out) :: kFld ! index of field
logical ,intent(in) ,optional :: print ! print switch
integer(SHR_KIND_IN),intent(out),optional :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: n ! index for colon position
integer(SHR_KIND_IN) :: k ! index for field name position
integer(SHR_KIND_IN) :: nFields ! number of fields in a string
integer(SHR_KIND_IN) :: i0,i1 ! fldStr == string(i0,i1) ??
integer(SHR_KIND_IN) :: j0,j1 ! fldStr == string(j0,j1) ??
logical :: found ! T => field found in fieldNames
logical :: lprint ! local print flag
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listGetIndex) "
character(*),parameter :: F00 = "('(shr_string_listGetIndex) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! - searching from both ends of the list at the same time seems to be 20% faster
! but I'm not sure why (B. Kauffman, Feb 2007)
! - I commented out sanity check to a little gain speed (B. Kauffman, Mar 2007)
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
if (present(rc)) rc = 0
lprint = .false.
if (present(print)) lprint = print
!--- confirm proper size of input data ---
if (len_trim(fldStr) < 1) then
if (lprint) write(s_logunit,F00) "ERROR: input field name has 0 length"
call shr_string_abort
(subName//"invalid field name")
end if
!--- search for field name in string's list of fields ---
found = .false.
kFld = 0
i0 = 1 ! ?? fldStr == string(i0:i1) ??
i1 = -1
j0 = -1 ! ?? fldStr == string(j0:j1) ??
j1 = len_trim(string)
nFields = shr_string_listGetNum
(string)
do k = 1,nFields
!--------------------------------------------------------
! search from end of list to end of list
!--------------------------------------------------------
!--- get end index of of field number k ---
n = index(string(i0:len_trim(string)),listDel)
if (n > 0) then
i1 = i0 + n - 2 ! *not* the last field name in fieldNames
else
i1 = len_trim(string) ! this is the last field name in fieldNames
endif
!--- sanity check ---
! if ((k <nFields .and. n<1) .or. (k==nFields .and. n>0)) then
! call shr_string_abort(subName//"ERROR: wrong string%nf ?")
! end if
!--- is it a match? ---
if (trim(fldStr) == string(i0:i1)) then
found = .true.
kFld = k
exit
endif
i0 = i1 + 2 ! start index for next iteration
!--------------------------------------------------------
! search from end of list to start of list
!--------------------------------------------------------
!--- get start index of field number (nFields + 1 - k ) ---
n = index(string(1:j1),listDel,back=.true.)
j0 = n + 1 ! n==0 => the first field name in fieldNames
!--- sanity check ---
! if ((k <nFields .and. n<1) .or. (k==nFields .and. n>0)) then
! call shr_string_abort(subName//"ERROR: wrong string%nf ?")
! end if
!--- is it a match? ---
if (trim(fldStr) == string(j0:j1)) then
found = .true.
kFld = nFields + 1 - k
exit
endif
j1 = j0 - 2 ! end index for next iteration
!--------------------------------------------------------
! exit if all field names have been checked
!--------------------------------------------------------
if (2*k >= nFields) exit
end do
!--- not finding a field is not a fatal error ---
if (.not. found) then
kFld = 0
if (lprint .and. s_loglev > 0) write(s_logunit,F00) "FYI: field ",trim(fldStr)," not found in list ",trim(string)
if (present(rc)) rc = 1
end if
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listGetIndex
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listGetNum -- get number of fields in a string list
!
! !DESCRIPTION:
! return number of fields in string list
!
! !REVISION HISTORY:
! 2005-Apr-28 - T. Craig - First version
!
! !INTERFACE: ------------------------------------------------------------------
integer function shr_string_listGetNum(str) 23,4
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*),intent(in) :: str ! string to search
!EOP
!----- local -----
integer(SHR_KIND_IN) :: count ! counts occurances of char
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!----- formats -----
character(*),parameter :: subName = "(shr_string_listGetNum) "
character(*),parameter :: F00 = "('(shr_string_listGetNum) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
shr_string_listGetNum = 0
if (len_trim(str) > 0) then
count = shr_string_countChar
(str,listDel)
shr_string_listGetNum = count + 1
endif
if (debug>1) call shr_timer_stop
(t01)
end function shr_string_listGetNum
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listSetDel -- Set list delimeter character
!
! !DESCRIPTION:
! Set field delimeter character in lists
! \newline
! call shr\_string\_listSetDel(":")
!
! !REVISION HISTORY:
! 2005-Apr-30 - T. Craig - first prototype
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listSetDel(cflag),3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(len=1),intent(in) :: cflag
!EOP
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!--- formats ---
character(*),parameter :: subName = "(shr_string_listSetDel) "
character(*),parameter :: F00 = "('(shr_string_listSetDel) ',a) "
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
if (debug > 0 .and. s_loglev > 0) write(s_logunit,F00) 'changing listDel from '//trim(listDel)//' to '//trim(cflag)
listDel = trim(cflag)
listDel2 = listDel//listDel
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listSetDel
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_listGetDel -- Get list delimeter character
!
! !DESCRIPTION:
! Get field delimeter character in lists
! \newline
! call shr\_string\_listGetDel(del)
!
! !REVISION HISTORY:
! 2005-May-15 - T. Craig - first prototype
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_listGetDel(del),3
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*),intent(out) :: del
!EOP
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!--- formats ---
character(*),parameter :: subName = "(shr_string_listGetDel) "
character(*),parameter :: F00 = "('(shr_string_listGetDel) ',a) "
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
del = trim(listDel)
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_listGetDel
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_setAbort -- Set local shr_string abort flag
!
! !DESCRIPTION:
! Set local shr_string abort flag, true = abort, false = print and continue
! \newline
! call shr\_string\_setAbort(.false.)
!
! !REVISION HISTORY:
! 2005-Apr-30 - T. Craig - first prototype
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_setAbort(flag),3
implicit none
! !INPUT/OUTPUT PARAMETERS:
logical,intent(in) :: flag
!EOP
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!--- formats ---
character(*),parameter :: subName = "(shr_string_setAbort) "
character(*),parameter :: F00 = "('(shr_string_setAbort) ',a) "
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
if (debug > 0 .and. s_loglev > 0) then
if (flag) then
write(s_logunit,F00) 'setting abort to true'
else
write(s_logunit,F00) 'setting abort to false'
endif
endif
doabort = flag
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_setAbort
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_string_setDebug -- Set local shr_string debug level
!
! !DESCRIPTION:
! Set local shr_string debug level, 0 = production
! \newline
! call shr\_string\_setDebug(2)
!
! !REVISION HISTORY:
! 2005-Apr-30 - T. Craig - first prototype
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_string_setDebug(iFlag),3
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer(SHR_KIND_IN),intent(in) :: iFlag ! requested debug level
!EOP
!--- local ---
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!--- formats ---
character(*),parameter :: subName = "(shr_string_setDebug) "
character(*),parameter :: F00 = "('(shr_string_setDebug) ',a) "
character(*),parameter :: F01 = "('(shr_string_setDebug) ',a,i3,a,i3) "
!-------------------------------------------------------------------------------
! NTOE: write statement can be expensive if called many times.
!-------------------------------------------------------------------------------
if (iFlag>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (iFlag>1) call shr_timer_start
(t01)
! if (s_loglev > 0) write(s_logunit,F01) 'changing debug level from ',debug,' to ',iflag
debug = iFlag
if (iFlag>1) call shr_timer_stop
(t01)
end subroutine shr_string_setDebug
!===============================================================================
!===============================================================================
subroutine shr_string_abort(string) 12,4
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*),optional,intent(in) :: string
!EOP
integer(SHR_KIND_IN) :: t01 = 0 ! timer
!--- local ---
character(SHR_KIND_CX) :: lstring
character(*),parameter :: subName = "(shr_string_abort)"
character(*),parameter :: F00 = "('(shr_string_abort) ',a)"
!-------------------------------------------------------------------------------
! NOTE:
! - no input or output string should be longer than SHR_KIND_CX
!-------------------------------------------------------------------------------
if (debug>1 .and. t01<1) call shr_timer_get
(t01,subName)
if (debug>1) call shr_timer_start
(t01)
lstring = ''
if (present(string)) lstring = string
if (doabort) then
call shr_sys_abort
(trim(lstring))
else
write(s_logunit,F00) ' no abort:'//trim(lstring)
endif
if (debug>1) call shr_timer_stop
(t01)
end subroutine shr_string_abort
!===============================================================================
!===============================================================================
end module shr_string_mod