!-----------------------------------------------------------------------
! Support module for CFITSIO interactions. Use module 'cfitsio_api'
! in your programs.
!-----------------------------------------------------------------------
module cfitsio_parameters
  !
  integer(kind=4), parameter :: code_cfitsio_readonly=0
  !
  integer(kind=4), parameter :: code_cfitsio_any_hdu=-1
  integer(kind=4), parameter :: code_cfitsio_image_hdu=0
  integer(kind=4), parameter :: code_cfitsio_ascii_tbl=1
  integer(kind=4), parameter :: code_cfitsio_binary_tbl=2
  !
  integer(kind=4), parameter :: code_cfitsio_error_missingkey=202
  !
end module cfitsio_parameters
!
module cfitsio_interfaces
  !
  interface
    subroutine ftvers(version)
    !-------------------------------------------------------------------
    !  Return the current version number of the fitsio library. The
    ! version number will be incremented with each new release of
    ! CFITSIO.
    !-------------------------------------------------------------------
    real(kind=4), intent(out) :: version
    end subroutine ftvers
    !
    subroutine ftopen(iunit,name,rwmode,block,status)
    !-------------------------------------------------------------------
    ! Open an existing FITS file with readonly or read/write access
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran I/O unit number
    character(len=*), intent(in)    :: name    ! Name of file to be opened
    integer(kind=4)                 :: rwmode  ! File access mode: 0 = readonly; else = read and write
    integer(kind=4),  intent(out)   :: block   ! Returned record length blocking factor
    integer(kind=4),  intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftopen
    !
    subroutine ftinit(iunit,filename,blocksize,status)
    !-------------------------------------------------------------------
    ! Close a FITS file that was previously opened with ftopen or ftinit
    !------------------------------------------ -------------------------
    integer(kind=4),  intent(in)    :: iunit      ! Fortran I/O unit number
    character(len=*), intent(in)    :: filename   ! Name of file to be initialized
    integer(kind=4),  intent(in)    :: blocksize  ! Block size (ignored?)
    integer(kind=4),  intent(inout) :: status     ! Returned error status (0=ok)
    end subroutine ftinit
    !
    subroutine ftclos(iunit,status)
    !-------------------------------------------------------------------
    ! Close a FITS file that was previously opened with ftopen or ftinit
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit   ! Fortran I/O unit number
    integer(kind=4), intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftclos
    !
    subroutine ftrprt(stream,status)
    !-------------------------------------------------------------------
    ! Display the error status message and flush the error stack
    !-------------------------------------------------------------------
    character(len=*), intent(in) :: stream  ! 'STDOUT' or 'STDERR'
    integer(kind=4),  intent(in) :: status  ! Error status
    end subroutine ftrprt
    !
    subroutine ftcmsg
    !-------------------------------------------------------------------
    ! Clear the error message stack
    !-------------------------------------------------------------------
    end subroutine ftcmsg
    !
    subroutine ftgerr(status,errtext)
    !-------------------------------------------------------------------
    !  Return the descriptive text string corresponding to a FITSIO
    ! error status code. The 30-character length string contains a brief
    ! description of the cause of the error.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)  :: status
    character(len=*), intent(out) :: errtext
    end subroutine ftgerr
    !
    subroutine ftflus(iunit,status)
    !-------------------------------------------------------------------
    ! Flush internal buffers of data to the output FITS file previously
    ! opened with ftopen or ftinit.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit   ! Fortran I/O unit number
    integer(kind=4), intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftflus
    !
    subroutine ftphps(iunit,bitpix,naxis,naxes,status)
    !-------------------------------------------------------------------
    ! Put the primary header or IMAGE extension keywords into the CHU.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit         ! Fortran I/O unit number
    integer(kind=4), intent(in)    :: bitpix        ! Number of bits per value
    integer(kind=4), intent(in)    :: naxis         ! Number of dimensions
    integer(kind=4), intent(in)    :: naxes(naxis)  ! Dimensions
    integer(kind=4), intent(inout) :: status        ! Returned error status (0=ok)
    end subroutine ftphps
    !
    subroutine ftthdu(iunit,nhdu,status)
    !-------------------------------------------------------------------
    ! Return the total number of HDUs in the FITS file. The CHDU
    ! remains unchanged.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit   ! Fortran I/O unit number
    integer(kind=4), intent(out)   :: nhdu    !
    integer(kind=4), intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftthdu
    !
    subroutine ftgkyd(iunit,keywrd,dval,comm,status)
    !-------------------------------------------------------------------
    ! Read a double precision value and comment string from a header
    ! record
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran I/O unit number
    character(len=*), intent(in)    :: keywrd  ! Keyword name
    real(kind=8),     intent(out)   :: dval    ! Output keyword value
    character(len=*), intent(out)   :: comm    ! Output keyword comment
    integer(kind=4),  intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftgkyd
    !
    subroutine ftgkyj(iunit,keywrd,intval,comm,status)
    !-------------------------------------------------------------------
    ! Read an integer value and the comment string from a header record
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran I/O unit number
    character(len=*), intent(in)    :: keywrd  ! Keyword name
    integer(kind=4),  intent(out)   :: intval  ! Output keyword value
    character(len=*), intent(out)   :: comm    ! Output keyword comment
    integer(kind=4),  intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftgkyj
    !
    subroutine ftgkyl(iunit,keywrd,logval,comm,status)
    !-------------------------------------------------------------------
    ! Read a logical value and the comment string from a header record
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran I/O unit number
    character(len=*), intent(in)    :: keywrd  ! Keyword name
    logical,          intent(out)   :: logval  ! Output keyword value
    character(len=*), intent(out)   :: comm    ! Output keyword comment
    integer(kind=4),  intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftgkyl
    !
    subroutine ftgkys(iunit,keywrd,strval,comm,status)
    !-------------------------------------------------------------------
    ! Read a character string value and comment string from a header
    ! record
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran I/O unit number
    character(len=*), intent(in)    :: keywrd  ! Keyword name
    character(len=*), intent(out)   :: strval  ! Output keyword value
    character(len=*), intent(out)   :: comm    ! Output keyword comment
    integer(kind=4),  intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftgkys
    !
    subroutine ftmahd(iunit,extno,xtend,status)
    !-------------------------------------------------------------------
    ! Move to Absolute Header Data unit
    ! Move the i/o pointer to the specified HDU and initialize all the
    ! common block parameters which describe the extension
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit   ! Fortran I/O unit number
    integer(kind=4), intent(in)    :: extno   ! Number of the extension to point to
    integer(kind=4), intent(out)   :: xtend   ! Returned type of extension
    integer(kind=4), intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftmahd
    !
    subroutine ftmnhd(iunit,hdutype,extname,extver,status)
    !-------------------------------------------------------------------
    ! Move to the (first) HDU which has the specified extension type and
    ! EXTNAME (or HDUNAME) and EXTVER keyword values. The hdutype
    ! parameter may have a value of IMAGE_HDU (0), ASCII_TBL (1),
    ! BINARY_TBL (2), or ANY_HDU (-1) where ANY_HDU means that only the
    ! extname and extver values will be used to locate the correct
    ! extension. If the input value of extver is 0 then the EXTVER
    ! keyword is ignored and the first HDU with a matching EXTNAME (or
    ! HDUNAME) keyword will be found. If no matching HDU is found in the
    ! file then the current HDU will remain unchanged and a status =
    ! BAD_HDU_NUM (301) will be returned.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit    ! Fortran I/O unit number
    integer(kind=4),  intent(in)    :: hdutype  !
    character(len=*), intent(in)    :: extname  !
    integer(kind=4),  intent(in)    :: extver   !
    integer(kind=4),  intent(inout) :: status   ! Returned error status (0=ok)
    end subroutine ftmnhd
    !
    subroutine ftgcno(iunit,casesn,templt,colnum,status)
    !-------------------------------------------------------------------
    ! Determine the column number corresponding to an input column name.
    ! This supports the * and ? wild cards in the input template.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran i/o unit number
    logical,          intent(in)    :: casesn  ! .true. if an exact case match of the names is required
    character(len=*), intent(in)    :: templt  ! Name of column as specified in a TTYPE keyword
    integer(kind=4),  intent(out)   :: colnum  ! Number of the column (first column = 1, a value of 0 is returned if the column is not found)
    integer(kind=4),  intent(inout) :: status  ! Returned error status
    end subroutine ftgcno
    !
    subroutine ftgcfe(iunit,colnum,frow,felem,nelem,array,flgval,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of R*4 values from a specified column of the table.
    ! Any undefined pixels will be have the corresponding value of FLGVAL
    ! set equal to .true., and ANYNUL will be set equal to .true. if any
    ! pixels are undefined.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit      ! Fortran i/o unit number
    integer(kind=4), intent(in)    :: colnum     ! Number of the column to read
    integer(kind=4), intent(in)    :: frow       ! First row to read
    integer(kind=4), intent(in)    :: felem      ! First element within the row to read
    integer(kind=4), intent(in)    :: nelem      ! Number of elements to read
    real(kind=4),    intent(out)   :: array(*)   ! Returned array of data values that was read from FITS file
    logical,         intent(out)   :: flgval(*)  ! Set to .true. if corresponding element undefined
    logical,         intent(inout) :: anynul     ! Set to .true. if any of the returned values are undefined
    integer(kind=4), intent(inout) :: status     ! Returned error status
    end subroutine ftgcfe
    !
    subroutine ftgcfd(iunit,colnum,frow,felem,nelem,array,flgval,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of R*8 values from a specified column of the table.
    ! Any undefined pixels will be have the corresponding value of FLGVAL
    ! set equal to .true., and ANYNUL will be set equal to .true. if any
    ! pixels are undefined.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit      ! Fortran i/o unit number
    integer(kind=4), intent(in)    :: colnum     ! Number of the column to read
    integer(kind=4), intent(in)    :: frow       ! First row to read
    integer(kind=4), intent(in)    :: felem      ! First element within the row to read
    integer(kind=4), intent(in)    :: nelem      ! Number of elements to read
    real(kind=8),    intent(out)   :: array(*)   ! Returned array of data values that was read from FITS file
    logical,         intent(out)   :: flgval(*)  ! Set to .true. if corresponding element undefined
    logical,         intent(inout) :: anynul     ! Set to .true. if any of the returned values are undefined
    integer(kind=4), intent(inout) :: status     ! Returned error status
    end subroutine ftgcfd
    !
    subroutine ftgcfj(iunit,colnum,frow,felem,nelem,array,flgval,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of I*4 values from a specified column of the table.
    ! Any undefined pixels will be have the corresponding value of FLGVAL
    ! set equal to .true., and ANYNUL will be set equal to .true. if any
    ! pixels are undefined.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit      ! Fortran i/o unit number
    integer(kind=4), intent(in)    :: colnum     ! Number of the column to read
    integer(kind=4), intent(in)    :: frow       ! First row to read
    integer(kind=4), intent(in)    :: felem      ! First element within the row to read
    integer(kind=4), intent(in)    :: nelem      ! Number of elements to read
    integer(kind=4), intent(out)   :: array(*)   ! Returned array of data values that was read from FITS file
    logical,         intent(out)   :: flgval(*)  ! Set to .true. if corresponding element undefined
    logical,         intent(inout) :: anynul     ! Set to .true. if any of the returned values are undefined
    integer(kind=4), intent(inout) :: status     ! Returned error status
    end subroutine ftgcfj
    !
    subroutine ftgcfs(iunit,colnum,frow,felem,nelem,array,flgval,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of character strings from a specified column of the table.
    ! Any undefined pixels will be have the corresponding value of FLGVAL
    ! set equal to .true., and ANYNUL will be set equal to .true. if any
    ! pixels are undefined.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit      ! Fortran i/o unit number
    integer(kind=4),  intent(in)    :: colnum     ! Number of the column to read
    integer(kind=4),  intent(in)    :: frow       ! First row to read
    integer(kind=4),  intent(in)    :: felem      ! First element within the row to read
    integer(kind=4),  intent(in)    :: nelem      ! Number of elements to read
    character(len=*), intent(out)   :: array(*)   ! Returned array of data values that was read from FITS file
    logical,          intent(out)   :: flgval(*)  ! Set to .true. if corresponding element undefined
    logical,          intent(inout) :: anynul     ! Set to .true. if any of the returned values are undefined
    integer(kind=4),  intent(inout) :: status     ! Returned error status
    end subroutine ftgcfs
    !
    subroutine ftgcfl(iunit,colnum,frow,felem,nelem,array,flgval,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of logical values from a specified column of the table.
    ! Any undefined pixels will be have the corresponding value of FLGVAL
    ! set equal to .true., and ANYNUL will be set equal to .true. if any
    ! pixels are undefined.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit      ! Fortran i/o unit number
    integer(kind=4), intent(in)    :: colnum     ! Number of the column to read
    integer(kind=4), intent(in)    :: frow       ! First row to read
    integer(kind=4), intent(in)    :: felem      ! First element within the row to read
    integer(kind=4), intent(in)    :: nelem      ! Number of elements to read
    logical,         intent(out)   :: array(*)   ! Returned array of data values that was read from FITS file
    logical,         intent(out)   :: flgval(*)  ! Set to .true. if corresponding element undefined
    logical,         intent(inout) :: anynul     ! Set to .true. if any of the returned values are undefined
    integer(kind=4), intent(inout) :: status     ! Returned error status
    end subroutine ftgcfl
    !
    subroutine ftgcvd(iunit,colnum,frow,felem,nelem,nulval,array,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of real*8 values from a specified column of the table.
    ! Any undefined pixels will be set equal to the value of NULVAL,
    ! unless NULVAL=0, in which case no checks for undefined pixels will
    ! be made.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit     ! Fortran i/o unit number
    integer(kind=4), intent(in)    :: colnum    ! Number of the column to read
    integer(kind=4), intent(in)    :: frow      ! First row to read
    integer(kind=4), intent(in)    :: felem     ! First element within the row to read
    integer(kind=4), intent(in)    :: nelem     ! Number of elements to read
    real(kind=8),    intent(in)    :: nulval    ! Value that undefined pixels will be set to
    real(kind=8),    intent(out)   :: array(*)  ! Returned array of data values that was read from FITS file
    logical,         intent(inout) :: anynul    ! Set to .true. if any of the returned values are undefined
    integer(kind=4), intent(inout) :: status    ! Returned error status
    end subroutine ftgcvd
    !
    subroutine ftgcve(iunit,colnum,frow,felem,nelem,nulval,array,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of real*4 values from a specified column of the table.
    ! Any undefined pixels will be set equal to the value of NULVAL,
    ! unless NULVAL=0, in which case no checks for undefined pixels will
    ! be made.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit     ! Fortran i/o unit number
    integer(kind=4), intent(in)    :: colnum    ! Number of the column to read
    integer(kind=4), intent(in)    :: frow      ! First row to read
    integer(kind=4), intent(in)    :: felem     ! First element within the row to read
    integer(kind=4), intent(in)    :: nelem     ! Number of elements to read
    real(kind=4),    intent(in)    :: nulval    ! Value that undefined pixels will be set to
    real(kind=4),    intent(out)   :: array(*)  ! Returned array of data values that was read from FITS file
    logical,         intent(inout) :: anynul    ! Set to .true. if any of the returned values are undefined
    integer(kind=4), intent(inout) :: status    ! Returned error status
    end subroutine ftgcve
    !
    subroutine ftgcvj(iunit,colnum,frow,felem,nelem,nulval,array,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of integer*4 values from a specified column of the table.
    ! Any undefined pixels will be set equal to the value of NULVAL,
    ! unless NULVAL=0, in which case no checks for undefined pixels will
    ! be made.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit     ! Fortran i/o unit number
    integer(kind=4), intent(in)    :: colnum    ! Number of the column to read
    integer(kind=4), intent(in)    :: frow      ! First row to read
    integer(kind=4), intent(in)    :: felem     ! First element within the row to read
    integer(kind=4), intent(in)    :: nelem     ! Number of elements to read
    integer(kind=4), intent(in)    :: nulval    ! Value that undefined pixels will be set to
    integer(kind=4), intent(out)   :: array(*)  ! Returned array of data values that was read from FITS file
    logical,         intent(inout) :: anynul    ! Set to .true. if any of the returned values are undefined
    integer(kind=4), intent(inout) :: status    ! Returned error status
    end subroutine ftgcvj
    !
    subroutine ftgcvs(iunit,colnum,frow,felem,nelem,nulval,array,anynul,status)
    !-------------------------------------------------------------------
    ! Read an array of character strings from a specified column of the table.
    ! Any undefined pixels will be set equal to the value of NULVAL,
    ! unless NULVAL=0, in which case no checks for undefined pixels will
    ! be made.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit     ! Fortran i/o unit number
    integer(kind=4),  intent(in)    :: colnum    ! Number of the column to read
    integer(kind=4),  intent(in)    :: frow      ! First row to read
    integer(kind=4),  intent(in)    :: felem     ! First element within the row to read
    integer(kind=4),  intent(in)    :: nelem     ! Number of elements to read
    character(len=*), intent(in)    :: nulval    ! Value that undefined pixels will be set to
    character(len=*), intent(out)   :: array(*)  ! Returned array of data values that was read from FITS file
    logical,          intent(inout) :: anynul    ! Set to .true. if any of the returned values are undefined
    integer(kind=4),  intent(inout) :: status    ! Returned error status
    end subroutine ftgcvs
    !
    subroutine ftgcl(iunit,colnum,frow,felem,nelem,array,status)
    !-------------------------------------------------------------------
    ! Read an array of logical values from a specified column of the table.
    ! Any undefined pixels will be set equal to the value of NULVAL,
    ! unless NULVAL=0, in which case no checks for undefined pixels will
    ! be made.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit     ! Fortran i/o unit number
    integer(kind=4),  intent(in)    :: colnum    ! Number of the column to read
    integer(kind=4),  intent(in)    :: frow      ! First row to read
    integer(kind=4),  intent(in)    :: felem     ! First element within the row to read
    integer(kind=4),  intent(in)    :: nelem     ! Number of elements to read
    logical,          intent(out)   :: array(*)  ! Returned array of data values that was read from FITS file
    integer(kind=4),  intent(inout) :: status    ! Returned error status
    end subroutine ftgcl
    !
    subroutine ftghps(iunit,keysexist,key_no,status)
    !-------------------------------------------------------------------
    ! Return the number of keywords in the header and the current
    ! position in the header. This returns the number of the keyword
    ! record that will be read next (or one greater than the position of
    ! the last keyword that was read or written). A value of 1 is
    ! returned if the pointer is positioned at the beginning of the
    ! header.
    !-------------------------------------------------------------------
    integer(kind=4), intent(in)    :: iunit      ! Fortran I/O unit number
    integer(kind=4), intent(out)   :: keysexist  ! Number of available keys
    integer(kind=4), intent(out)   :: key_no     ! Next key to read
    integer(kind=4), intent(inout) :: status     ! Returned error status
    end subroutine ftghps
    !
    subroutine ftgkyn(iunit,key_no,keyword,value,comment,status)
    !-------------------------------------------------------------------
    ! Get the name, value (as a string), and comment of the nth keyword
    ! in CHU. This routine also checks that the returned keyword name
    ! (KEYWORD) contains only legal ASCII characters. Call FTGREC and
    ! FTPSVC to bypass this error check.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit    ! Fortran I/O unit number
    integer(kind=4),  intent(in)    :: key_no   ! The key number
    character(len=*), intent(out)   :: keyword  !
    character(len=*), intent(out)   :: value    !
    character(len=*), intent(out)   :: comment  !
    integer(kind=4),  intent(inout) :: status   ! Returned error status
    end subroutine ftgkyn
    !
    subroutine ftukys(iunit,keywrd,strval,comm,status)
    !-------------------------------------------------------------------
    ! Update the value and comment fields of a keyword in the CHU.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran I/O unit number
    character(len=*), intent(in)    :: keywrd  ! Keyword name
    character(len=*), intent(in)    :: strval  ! Keyword value
    character(len=*), intent(in)    :: comm    ! Keyword comment
    integer(kind=4),  intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftukys
    !
    subroutine ftukyj(iunit,keywrd,intval,comm,status)
    !-------------------------------------------------------------------
    ! Update the value and comment fields of a keyword in the CHU.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit   ! Fortran I/O unit number
    character(len=*), intent(in)    :: keywrd  ! Keyword name
    integer(kind=4),  intent(in)    :: intval  ! Keyword value
    character(len=*), intent(in)    :: comm    ! Keyword comment
    integer(kind=4),  intent(inout) :: status  ! Returned error status (0=ok)
    end subroutine ftukyj
    !
    subroutine ftgsfe(iunit,group,naxis,naxes,fpixels,lpixels,incs, &
                      array,flagvals,anyf,status)
    !-------------------------------------------------------------------
    ! Get an arbitrary data subsection from the data array. Any
    ! Undefined pixels in the array will have the corresponding
    ! 'flagvals' element set equal to .TRUE.
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit        ! Fortran I/O unit number
    integer(kind=4),  intent(in)    :: group        !
    integer(kind=4),  intent(in)    :: naxis        ! Number of axes
    integer(kind=4),  intent(in)    :: naxes(*)     ! Axes length
    integer(kind=4),  intent(in)    :: fpixels(*)   ! BLC
    integer(kind=4),  intent(in)    :: lpixels(*)   ! TRC
    integer(kind=4),  intent(in)    :: incs(*)      ! Step in each dimension
    real(kind=4),     intent(out)   :: array(*)     ! Data array to read
    logical,          intent(out)   :: flagvals(*)  ! NULL flag for each value
    logical,          intent(out)   :: anyf         ! At least one NULL value?
    integer(kind=4),  intent(inout) :: status     ! Returned error status (0=ok)
    end subroutine ftgsfe
    !
    subroutine ftppre(iunit,group,fpixel,nelements,values,status)
    !-------------------------------------------------------------------
    ! Put elements into the data array
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit      ! Fortran I/O unit number
    integer(kind=4),  intent(in)    :: group      !
    integer(kind=4),  intent(in)    :: fpixel     ! Position within the 1-D array of the first pixel to write
    integer(kind=4),  intent(in)    :: nelements  ! Number of elements to write
    real(kind=4),     intent(in)    :: values(*)  ! Data array to write
    integer(kind=4),  intent(inout) :: status     ! Returned error status (0=ok)
    end subroutine ftppre
    !
    subroutine ftpsse(iunit,group,naxis,naxes,fpixels,lpixels,array,status)
    !-------------------------------------------------------------------
    ! Put an arbitrary data subsection into the data array
    !-------------------------------------------------------------------
    integer(kind=4),  intent(in)    :: iunit      ! Fortran I/O unit number
    integer(kind=4),  intent(in)    :: group      !
    integer(kind=4),  intent(in)    :: naxis      ! Number of axes
    integer(kind=4),  intent(in)    :: naxes(*)   ! Axes length
    integer(kind=4),  intent(in)    :: fpixels(*) ! BLC
    integer(kind=4),  intent(in)    :: lpixels(*) ! TRC
    real(kind=4),     intent(in)    :: array(*)   ! Data array to write
    integer(kind=4),  intent(inout) :: status     ! Returned error status (0=ok)
    end subroutine ftpsse
    !
  end interface
  !
end module cfitsio_interfaces
!
module cfitsio_api
  use cfitsio_parameters
  use cfitsio_interfaces
  !
contains
  subroutine cfitsio_errormsg(status,msg)
  !---------------------------------------------------------------------
  ! Convert a CFITSIO error status into an error message
  !---------------------------------------------------------------------
  integer(kind=4),  intent(in) :: status
  character(len=*), intent(out) :: msg
  !
  select case (status)
  case (0)
    msg = 'OK, no error'
  case (101)
    msg = 'Input and output files are the same'
  case (103)
    msg = 'Tried to open too many FITS files at once'
  case (104)
    msg = 'Could not open the named file'
  case (105)
    msg = 'Could not create the named file'
  case (106)
    msg = 'Error writing to FITS file'
  case (107)
    msg = 'Tried to move past end of file'
  case (108)
    msg = 'Error reading from FITS file'
  case (110)
    msg = 'Could not close the file'
  case (111)
    msg = 'Array dimensions exceed internal limit'
  case (112)
    msg = 'Cannot write to readonly file'
  case (113)
    msg = 'Could not allocate memory'
  case (114)
    msg = 'Invalid fitsfile pointer'
  case (115)
    msg = 'NULL input pointer to routine'
  case (116)
    msg = 'Error seeking position in file'
  !
  case (121)
    msg = 'Invalid URL prefix on file name'
  case (122)
    msg = 'Tried to register too many IO drivers'
  case (123)
    msg = 'Driver initialization failed'
  case (124)
    msg = 'Matching driver is not registered'
  case (125)
    msg = 'Failed to parse input file URL'
  !
  case (151)
    msg = 'Bad argument in shared memory driver'
  case (152)
    msg = 'Null pointer passed as an argument'
  case (153)
    msg = 'No more free shared memory handles'
  case (154)
    msg = 'Shared memory driver is not initialized'
  case (155)
    msg = 'IPC error returned by a system call'
  case (156)
    msg = 'No memory in shared memory driver'
  case (157)
    msg = 'Resource deadlock would occur'
  case (158)
    msg = 'Attempt to open/create lock file failed'
  case (159)
    msg = 'Shared memory block cannot be resized at the moment'
  !
  case (201)
    msg = 'Header already contains keywords'
  case (202)
    msg = 'Keyword not found in header'
  case (203)
    msg = 'Keyword record number is out of bounds'
  case (204)
    msg = 'Keyword value field is blank'
  case (205)
    msg = 'String is missing the closing quote'
  case (207)
    msg = 'Illegal character in keyword name or card'
  case (208)
    msg = 'Required keywords out of order'
  case (209)
    msg = 'Keyword value is not a positive integer'
  case (210)
    msg = 'Couldn''t find END keyword'
  case (211)
    msg = 'Illegal BITPIX keyword value'
  case (212)
    msg = 'Illegal NAXIS keyword value'
  case (213)
    msg = 'Illegal NAXISn keyword value'
  case (214)
    msg = 'Illegal PCOUNT keyword value'
  case (215)
    msg = 'Illegal GCOUNT keyword value'
  case (216)
    msg = 'Illegal TFIELDS keyword value'
  case (217)
    msg = 'Negative table row size'
  case (218)
    msg = 'Negative number of rows in table'
  case (219)
    msg = 'Column with this name not found in table'
  case (220)
    msg = 'Illegal value of SIMPLE keyword'
  case (221)
    msg = 'Primary array doesn''t start with SIMPLE'
  case (222)
    msg = 'Second keyword not BITPIX'
  case (223)
    msg = 'Third keyword not NAXIS'
  case (224)
    msg = 'Couldn''t find all the NAXISn keywords'
  case (225)
    msg = 'HDU doesn''t start with XTENSION keyword'
  case (226)
    msg = 'The CHDU is not an ASCII table extension'
  case (227)
    msg = 'The CHDU is not a binary table extension'
  case (228)
    msg = 'Couldn''t find PCOUNT keyword'
  case (229)
    msg = 'Couldn''t find GCOUNT keyword'
  case (230)
    msg = 'Couldn''t find TFIELDS keyword'
  case (231)
    msg = 'Couldn''t find TBCOLn keyword'
  case (232)
    msg = 'Couldn''t find TFORMn keyword'
  case (233)
    msg = 'The CHDU is not an IMAGE extension'
  case (234)
    msg = 'TBCOLn keyword value < 0 or > rowlength'
  case (235)
    msg = 'The CHDU is not a table'
  case (236)
    msg = 'Column is too wide to fit in table'
  case (237)
    msg = 'More than 1 column name matches template'
  case (241)
    msg = 'Sum of column widths not = NAXIS1'
  case (251)
    msg = 'Unrecognizable FITS extension type'
  case (252)
    msg = 'Unknown record; 1st keyword not SIMPLE or XTENSION'
  case (253)
    msg = 'END keyword is not blank'
  case (254)
    msg = 'Header fill area contains non-blank chars'
  case (255)
    msg = 'Illegal data fill bytes (not zero or blank)'
  case (261)
    msg = 'Illegal TFORM format code'
  case (262)
    msg = 'Unrecognizable TFORM datatype code'
  case (263)
    msg = 'Illegal TDIMn keyword value'
  case (264)
    msg = 'Invalid BINTABLE heap pointer is out of range'
  !
  case (301)
    msg = 'HDU number < 1 or > MAXHDU'
  case (302)
    msg = 'Column number < 1 or > tfields'
  case (304)
    msg = 'Tried to move to negative byte location in file'
  case (306)
    msg = 'Tried to read or write negative number of bytes'
  case (307)
    msg = 'Illegal starting row number in table'
  case (308)
    msg = 'Illegal starting element number in vector'
  case (309)
    msg = 'This is not an ASCII string column'
  case (310)
    msg = 'This is not a logical datatype column'
  case (311)
    msg = 'ASCII table column has wrong format'
  case (312)
    msg = 'Binary table column has wrong format'
  case (314)
    msg = 'Null value has not been defined'
  case (317)
    msg = 'This is not a variable length column'
  case (320)
    msg = 'Illegal number of dimensions in array'
  case (321)
    msg = 'First pixel number greater than last pixel'
  case (322)
    msg = 'Illegal BSCALE or TSCALn keyword = 0'
  case (323)
    msg = 'Illegal axis length < 1'
  !
  case (340:350)
    msg = 'Grouping function error'
  !
  case (360)
    msg = 'Malloc failed'
  case (361)
    msg = 'Read error from file'
  case (362)
    msg = 'Null pointer passed as an argument. Passing null pointer as a name of template file raises this error'
  case (363)
    msg = 'Line read seems to be empty (used internally)'
  case (364)
    msg = 'Cannot unread more then 1 line (or single line twice)'
  case (365)
    msg = 'Too deep include file nesting (infinite loop, template includes itself ?)'
  case (366)
    msg = 'Fopen() failed, cannot open template file'
  case (367)
    msg = 'End of file encountered and not expected'
  case (368)
    msg = 'Bad arguments passed. Usually means internal parser error. Should not happen'
  case (369)
    msg = 'Token not expected here'
  !
  case (401)
    msg = 'Bad int to formatted string conversion'
  case (402)
    msg = 'Bad float to formatted string conversion'
  case (403)
    msg = 'Can''t interpret keyword value as integer'
  case (404)
    msg = 'Can''t interpret keyword value as logical'
  case (405)
    msg = 'Can''t interpret keyword value as float'
  case (406)
    msg = 'Can''t interpret keyword value as double'
  case (407)
    msg = 'Bad formatted string to int conversion'
  case (408)
    msg = 'Bad formatted string to float conversion'
  case (409)
    msg = 'Bad formatted string to double conversion'
  case (410)
    msg = 'Illegal datatype code value'
  case (411)
    msg = 'Bad number of decimal places specified'
  case (412)
    msg = 'Overflow during datatype conversion'
  case (413)
    msg = 'Error compressing image'
  case (414)
    msg = 'Error uncompressing image'
  !
  case (420)
    msg = 'Error in date or time conversion'
  !
  case (431)
    msg = 'Syntax error in parser expression'
  case (432)
    msg = 'Expression did not evaluate to desired type'
  case (433)
    msg = 'Vector result too large to return in array'
  case (434)
    msg = 'Data parser failed not sent an out column'
  case (435)
    msg = 'Bad data encounter while parsing column'
  case (436)
    msg = 'Output file not of proper type'
  !
  case (501)
    msg = 'Celestial angle too large for projection'
  case (502)
    msg = 'Bad celestial coordinate or pixel value'
  case (503)
    msg = 'Error in celestial coordinate calculation'
  case (504)
    msg = 'Unsupported type of celestial projection'
  case (505)
    msg = 'Celestial coordinate keywords not found'
  case (506)
    msg = 'Approximate wcs keyword values were returned'
  !
  case default
    msg = 'Unknown error status'
  end select
  !
  end subroutine cfitsio_errormsg
end module cfitsio_api
