! $Id$
!
! Earth System Modeling Framework
! Copyright (c) 2002-2025, University Corporation for Atmospheric Research,
! Massachusetts Institute of Technology, Geophysical Fluid Dynamics
! Laboratory, University of Michigan, National Centers for Environmental
! Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
! NASA Goddard Space Flight Center.
! Licensed under the University of Illinois-NCSA License.
!
#define ESMF_FILENAME "ESMF_IOUtil.F90"
!
! ESMF IOUtil Module
!
! (all lines between the !BOP and !EOP markers will be included in the
! automated document processing.)
!------------------------------------------------------------------------------
! one blank line for protex processing - in case all routines here are
! marked internal (BOPI/EOPI), the output file will still have contents.
!BOP
!EOP
!------------------------------------------------------------------------------
! module definition
module ESMF_IOUtilMod
!BOPI
! !MODULE: ESMF_UtilIOUtilMod - Fortran I/O utility routines
!
! !DESCRIPTION:
!
! Fortran I/O-specific utility routines
!
! See the ESMF Developers Guide document for more details.
!
!------------------------------------------------------------------------------
! !USES:
! can not use ESMF_LogErrMod because it would cause a module circularity
use ESMF_UtilTypesMod
#include "ESMF.h"
implicit none
!
! !PRIVATE TYPES:
private
!------------------------------------------------------------------------------
!
! !DESCRIPTION:
!
! !PUBLIC MEMBER SUBROUTINES:
!
public ESMF_UtilIOUnitFlush
public ESMF_UtilIOUnitGet
public ESMF_UtilIOUnitInit
!==============================================================================
!
! MODULE SCOPE DATA
!
!==============================================================================
! Standard I/O Units
! (F2003 TODO: Eventually, for compilers which support the F2003
! ISO_FORTRAN_ENV intrinsic module, these should access the constants
! 'input_unit', 'output_unit', and 'error_unit'.)
integer, parameter, public :: ESMF_UtilIOStdin = 5
integer, parameter, public :: ESMF_UtilIOStdout = 6
#ifdef sysHP_UX
! Special setting for HP_UX
integer, parameter, public :: ESMF_UtilIOStderr = 7
#else
! Generic setting for UNIX other than HP-UX
integer, parameter, public :: ESMF_UtilIOStderr = 0
#endif
! Unit number range for ESMF internal use.
integer, private :: ESMF_UtilIOUnitLower = ESMF_LOG_FORT_UNIT_NUMBER
integer, private :: ESMF_UtilIOUnitUpper = ESMF_LOG_UPPER
!------------------------------------------------------------------------------
! leave the following line as-is; it will insert the cvs ident string
! into the object file for tracking purposes.
character(*), parameter, private :: version = &
'$Id$'
!------------------------------------------------------------------------------
contains
!-------------------------------------------------------------------------
#undef ESMF_METHOD
#define ESMF_METHOD "ESMF_UtilIOUnitFlush"
!BOP
! !IROUTINE: ESMF_UtilIOUnitFlush - Flush output on a unit number
!
! !INTERFACE:
subroutine ESMF_UtilIOUnitFlush(unit, keywordEnforcer, rc)
!
! !PARAMETERS:
integer, intent(in) :: unit
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
integer, intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Call the system-dependent routine to force output on a specific
! Fortran unit number.
!
! The arguments are:
! \begin{description}
! \item[unit]
! A Fortran I/O unit number. If the unit is not connected to a file,
! no flushing occurs.
! \item[{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!EOP
integer :: localrc
integer :: localstat
logical :: connected
inquire (unit=unit, opened=connected)
if (.not. connected) then
if (present (rc)) then
rc = ESMF_SUCCESS
end if
return
end if
! By default, use the F2003 FLUSH statement. For older compilers,
! use a macro defined in the configuration-specific ESMF_Conf.inc
! include file. This is needed because the name of the flush routine
! and exact number of its arguements vary between implementations.
#if !defined (ESMF_IOFlushMacro)
flush (unit, iostat=localstat)
! Convert Fortran iostat to ESMF rc
localrc = merge (ESMF_SUCCESS, ESMF_FAILURE, localstat == 0)
#else
! Preset localrc in advance, since some library versions of FLUSH do
! not support a status argument for detecting errors.
localstat = 0
ESMF_IOFlushMacro(unit, localstat)
! Convert status return to ESMF rc
localrc = merge (ESMF_SUCCESS, ESMF_FAILURE, localstat == 0)
#endif
if (present(rc)) then
rc = localrc
end if
end subroutine ESMF_UtilIOUnitFlush
!-------------------------------------------------------------------------
#undef ESMF_METHOD
#define ESMF_METHOD "ESMF_UtilIOUnitGet"
!BOP
! !IROUTINE: ESMF_UtilIOUnitGet - Scan for a free I/O unit number
!
! !INTERFACE:
subroutine ESMF_UtilIOUnitGet(unit, keywordEnforcer, rc)
!
! !ARGUMENTS:
integer, intent(out) :: unit
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
integer, intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Scan for, and return, a free Fortran I/O unit number.
! By default, the range of unit numbers returned is between 50 and 99
! (parameters {\tt ESMF\_LOG\_FORTRAN\_UNIT\_NUMBER} and {\tt ESMF\_LOG\_UPPER}
! respectively.) When integrating ESMF into an application where these values
! conflict with other usages, the range of values may be moved by setting the
! optional {\tt IOUnitLower} and {\tt IOUnitUpper} arguments in the initial
! {\tt ESMF\_Initialize()} call with values in a safe, alternate, range.
!
! The Fortran unit number which is returned is not reserved in any way.
! Successive calls without intervening {\tt OPEN} or {\tt CLOSE} statements
! (or other means of connecting to units), might not return a unique unit
! number. It is recommended that an {\tt OPEN} statement immediately follow
! the call to {\tt ESMF\_IOUnitGet()} to activate the unit.
!
! The arguments are:
! \begin{description}
! \item[unit]
! A Fortran I/O unit number.
! \item[{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!EOP
integer :: i
integer :: localstat
logical :: inuse
if (present(rc)) rc = ESMF_FAILURE
do, i=ESMF_UtilIOUnitLower, ESMF_UtilIOUnitUpper
inquire (unit=i, opened=inuse, iostat=localstat)
if (.not. inuse .and. localstat == 0) exit
end do
if (i <= ESMF_UtilIOUnitUpper) then
unit = i
if (present (rc)) rc = ESMF_SUCCESS
else
unit = -1
end if
end subroutine ESMF_UtilIOUnitGet
!-------------------------------------------------------------------------
#undef ESMF_METHOD
#define ESMF_METHOD "ESMF_UtilIOUnitInit"
!BOPI
! !IROUTINE: ESMF_UtilIOUnitInit - Initialize ESMF Fortran I/O unit number range
!
! !INTERFACE:
subroutine ESMF_UtilIOUnitInit(lower, upper, rc)
!
! !ARGUMENTS:
integer, intent(in), optional :: lower
integer, intent(in), optional :: upper
integer, intent(out), optional :: rc
!
! !DESCRIPTION:
! Initialize non-default range for Fortran I/O unit numbers used
! within ESMF.
!
! The arguments are:
! \begin{description}
! \item[{[lower]}]
! A lower bound for Fortran unit numbers.
! \item[{[upper]}]
! A upper bound for Fortran unit numbers.
! \item[{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOPI
if (present(rc)) rc = ESMF_FAILURE
! Sanity checks
if (present (lower)) then
if (lower < 0) return
end if
if (present (upper)) then
if (upper < 0) return
end if
if (present (lower) .and. .not. present (upper)) then
if (lower > ESMF_UtilIOUnitUpper) return
end if
if (present (upper) .and. .not. present (lower)) then
if (upper < ESMF_UtilIOUnitLower) return
end if
if (present (upper) .and. present (lower)) then
if (upper < lower) return
end if
!
if (present (lower)) then
ESMF_UtilIOUnitLower = lower
end if
if (present (upper)) then
ESMF_UtilIOUnitUpper = upper
end if
if (present (rc)) rc = ESMF_SUCCESS
end subroutine ESMF_UtilIOUnitInit
!------------------------------------------------------------------------------
end module ESMF_IOUtilMod