module gsys_interfaces_public
  interface
    subroutine sic_ambigs(prog,line,comm,ncom,vocab,nv,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Resolves command abbreviations and check for ambiguities
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: prog       ! Message prefix
      character(len=*), intent(in)    :: line       ! Abbreviation to be analysed
      character(len=*), intent(out)   :: comm       ! Command found
      integer(kind=4),  intent(out)   :: ncom       ! Command number
      integer(kind=4),  intent(in)    :: nv         ! List of commands
      character(len=*), intent(in)    :: vocab(nv)  ! Number of command
      logical,          intent(inout) :: error      ! Logical error flag
    end subroutine sic_ambigs
  end interface
  !
  interface
    subroutine sic_ambigs_sub(prog,line,comm,ncom,vocab,nv,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Still to be renamed
      ! Same as 'sic_ambigs' but:
      !  - do not recognize "?" which can be used to list all the
      !    possible values,
      !  - do not raise an error if no known keyword is found.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: prog       ! Message prefix
      character(len=*), intent(in)    :: line       ! Abbreviation to be analysed
      character(len=*), intent(out)   :: comm       ! Command found
      integer(kind=4),  intent(out)   :: ncom       ! Command number
      integer(kind=4),  intent(in)    :: nv         ! List of commands
      character(len=*), intent(in)    :: vocab(nv)  ! Number of command
      logical,          intent(inout) :: error      ! Logical error flag
    end subroutine sic_ambigs_sub
  end interface
  !
  interface
    subroutine sic_ambigs_list(caller,sever,message,vocab,ikeys,first,last)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Display an ambiguity list
      !---------------------------------------------------------------------
      character(len=*), intent(in)                   :: caller    ! Calling routine name
      integer(kind=4),  intent(in)                   :: sever     ! Severity of header message
      character(len=*), intent(in)                   :: message   ! Header message before list
      character(len=*), intent(in)                   :: vocab(:)  ! List of keywords
      integer(kind=4),  intent(in), optional, target :: ikeys(:)  ! Restrict to these keys?
      integer(kind=4),  intent(in), optional         :: first     ! Truncate start of string?
      integer(kind=4),  intent(in), optional         :: last      ! Truncate or force to this length?
    end subroutine sic_ambigs_list
  end interface
  !
  interface gag_infini
    subroutine gag_infini4(anum,string,ndg)
      !---------------------------------------------------------------------
      ! @ public-generic gag_infini
      ! Format Invalid Numbers (single precision version)
      !---------------------------------------------------------------------
      real(kind=4),     intent(in)  :: anum    ! Number
      character(len=*), intent(out) :: string  ! Representation
      integer(kind=4),  intent(out) :: ndg     ! Length of string
    end subroutine gag_infini4
    subroutine gag_infini8(anum,string,ndg)
      !---------------------------------------------------------------------
      ! @ public-generic gag_infini
      ! Format Invalid Numbers (double precision version)
      !---------------------------------------------------------------------
      real(kind=8),     intent(in)  :: anum    ! Number
      character(len=*), intent(out) :: string  ! Representation
      integer(kind=4),  intent(out) :: ndg     ! Length of string
    end subroutine gag_infini8
  end interface gag_infini
  !
  interface gag_notanum
    subroutine gag_notanum4(notanum)
      !---------------------------------------------------------------------
      ! @ public-generic gag_notanum
      ! Return the value of NaN (R*4 version)]
      !  An IEEE signaling NaN is represented by any bit pattern
      !    between X'7F80 0001' and X'7FBF FFFF', or
      !    between X'FF80 0001' and X'FFBF FFFF'.
      !  An IEEE quiet NaN is represented by any bit pattern
      !    between X'7FC0 0000' and X'7FFF FFFF', or
      !    between X'FFC0 0000' and X'FFFF FFFF'.
      !---------------------------------------------------------------------
      real(kind=4), intent(out) :: notanum  ! NaN value
    end subroutine gag_notanum4
    subroutine gag_notanum8(notanum)
      !---------------------------------------------------------------------
      ! @ public-generic gag_notanum
      ! Return the value of NaN (R*8 version)
      !  An IEEE signaling NaN is represented by any bit pattern
      !    between X'7FF00000 00000001' and X'7FF7FFFF FFFFFFFF', or
      !    between X'FFF00000 00000001' and X'FFF7FFFF FFFFFFFF'.
      !  An IEEE quiet NaN is represented by any bit pattern
      !    between X'7FF80000 00000000' and X'7FFFFFFF FFFFFFFF', or
      !    between X'FFF80000 00000000' and X'FFFFFFFF FFFFFFFF'.
      !---------------------------------------------------------------------
      real(kind=8), intent(out) :: notanum  ! NaN value
    end subroutine gag_notanum8
  end interface gag_notanum
  !
  interface
    function sic_ctrlc()
      use gsys_variables
      !---------------------------------------------------------------------
      ! @ public
      ! Return .TRUE. if ^C has been pressed, and restore CONTROLC flag to
      ! .FALSE.
      !---------------------------------------------------------------------
      logical :: sic_ctrlc  ! Function value on return
    end function sic_ctrlc
  end interface
  !
  interface
    function sic_ctrlc_status()
      use gsys_variables
      !---------------------------------------------------------------------
      ! @ public
      ! Return .TRUE. if ^C has been pressed but do *not* restore CONTROLC
      ! flag to .FALSE.
      !---------------------------------------------------------------------
      logical :: sic_ctrlc_status  ! Function value on return
    end function sic_ctrlc_status
  end interface
  !
  interface
    subroutine gag_fromdate(date,idate,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Converts the date '01-JAN-1984' in internal code
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: date   ! String date
      integer(kind=4),  intent(out)   :: idate  ! Internal coded date value
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine gag_fromdate
  end interface
  !
  interface
    subroutine gag_todate(idate,date,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Converts the internal code to formatted date
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in)    :: idate  ! Internal coded date value
      character(len=*), intent(out)   :: date   ! String date
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine gag_todate
  end interface
  !
  interface
    subroutine gag_fromyyyymmdd(string,dobs,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Decode a string date in the format "YYYYMMDD" into a gag date
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: string  !
      integer(kind=4),  intent(out)   :: dobs    !
      logical,          intent(inout) :: error   !
    end subroutine gag_fromyyyymmdd
  end interface
  !
  interface
    subroutine gag_toyyyymmdd(dobs,string,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Encode a gag date to a string date in the format "YYYYMMDD"
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in)    :: dobs    !
      character(len=*), intent(out)   :: string  !
      logical,          intent(inout) :: error   !
    end subroutine gag_toyyyymmdd
  end interface
  !
  interface
    subroutine gag_isodate(date,idate,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !   Converts the ISO #8601 date '1996-10-14T10:34:55.345' in internal
      ! code.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: date   ! String date
      integer(kind=4),  intent(out)   :: idate  ! Internal coded date value
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine gag_isodate
  end interface
  !
  interface
    subroutine gag_toisodate(idate,date,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Converts the internal code to ISO formatted date
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in)    :: idate  ! Internal coded date value
      character(len=*), intent(out)   :: date   ! String date
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine gag_toisodate
  end interface
  !
  interface
    subroutine isodate_to_gagdate(date,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Converts an ISO date representation to a GAG (DD-Monthname-YY) date
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: date   ! String date
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine isodate_to_gagdate
  end interface
  !
  interface
    subroutine gagdate_to_isodate(date,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Converts an ISO date representation to a GAG (DD-Monthname-YY) date
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: date   ! String date
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine gagdate_to_isodate
  end interface
  !
  interface
    subroutine gag_datj(id,im,iy,jour)
      !---------------------------------------------------------------------
      ! @ public
      !   Convert a date (id/im/iy) in number of days till the 01/01/1984
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: id    ! Day number
      integer(kind=4), intent(in)  :: im    ! Month number
      integer(kind=4), intent(in)  :: iy    ! Year number
      integer(kind=4), intent(out) :: jour  ! Elapsed day count
    end subroutine gag_datj
  end interface
  !
  interface
    subroutine gag_jdat(jour,id,im,iy)
      !---------------------------------------------------------------------
      ! @ public
      ! Reverse conversion
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: jour  ! Elapsed day count
      integer(kind=4), intent(out) :: id    ! Day number
      integer(kind=4), intent(out) :: im    ! Month number
      integer(kind=4), intent(out) :: iy    ! Year number
    end subroutine gag_jdat
  end interface
  !
  interface
    subroutine gag_isodate2mjd(timestring,mjd,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Convert an ISO #8601 date string of the form:
      !   2015-01-09T08:58:19.230000
      ! into a Modified Julian Date value.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: timestring
      real(kind=8),     intent(out)   :: mjd
      logical,          intent(inout) :: error
    end subroutine gag_isodate2mjd
  end interface
  !
  interface
    subroutine gag_mjd2isodate(mjd,timestring,error)
      use phys_const
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Convert a Modified Julian Date value to an ISO #8601 date string
      ! of the form:
      !   2015-01-09T08:58:19.230000
      !   123456789 123456789 123456
      !---------------------------------------------------------------------
      real(kind=8),     intent(in)    :: mjd
      character(len=*), intent(out)   :: timestring
      logical,          intent(inout) :: error
    end subroutine gag_mjd2isodate
  end interface
  !
  interface
    subroutine gag_gagut2mjd(date,ut,mjd,error)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public
      !  Convert a GAG_DATE + UT into a MJD date
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: date   ! [gag]
      real(kind=8),    intent(in)    :: ut     ! [rad] Day starts at 0 radians
      real(kind=8),    intent(out)   :: mjd    !
      logical,         intent(inout) :: error  !
    end subroutine gag_gagut2mjd
  end interface
  !
  interface
    subroutine gag_mjd2gagut(mjd,date,ut,error)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public
      !  Convert a MJD date into GAG_DATE + UT
      !---------------------------------------------------------------------
      real(kind=8),    intent(in)    :: mjd
      integer(kind=4), intent(out)   :: date
      real(kind=8),    intent(out)   :: ut
      logical,         intent(inout) :: error
    end subroutine gag_mjd2gagut
  end interface
  !
  interface
    subroutine sic_date(datetime)
      !---------------------------------------------------------------------
      ! @ public
      !  Return the current date-time in Gildas format
      !     DD-MMM-YYYY hh:mm:ss.ss
      !     123456789 123456789 123
      ! Use 23 character strings for full date-time, or shorter strings
      ! for truncated values.
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: datetime
    end subroutine sic_date
  end interface
  !
  interface
    subroutine sic_isodate(datetime)
      !---------------------------------------------------------------------
      ! @ public
      !  Return the current date-time in ISO #8601:
      !     1996-10-14T10:34:55.345
      !     123456789 123456789 123
      ! Use 23 character strings for full date-time, or shorter strings
      ! for truncated values.
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: datetime
    end subroutine sic_isodate
  end interface
  !
  interface
    subroutine sic_gagdate(gagdate)
      !---------------------------------------------------------------------
      ! @ public
      !  Return the current UTC date in GAG_DATE format
      !---------------------------------------------------------------------
      integer(kind=4), intent(out) :: gagdate
    end subroutine sic_gagdate
  end interface
  !
  interface
    subroutine sic_decode(chain,value,ndiv,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !   Decode a sexagesimal character string into angle value in radians.
      ! Formats can be:
      !       61.5000000      or      161
      !       61:30.0000      or      161:40
      !       61:45:50.9      or      161:40:50
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: chain  ! Character string
      real(kind=8),     intent(out)   :: value  ! Value of angle
      integer(kind=4),  intent(in)    :: ndiv   ! 360/24
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine sic_decode
  end interface
  !
  interface
    subroutine sic_lower(c)
      !---------------------------------------------------------------------
      ! @ public
      !  Converts a character string to lowercase.
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: c  ! Character string
    end subroutine sic_lower
  end interface
  !
  interface
    subroutine sic_upper(c)
      !---------------------------------------------------------------------
      ! @ public
      !  Converts a character string to uppercase.
      !  Slow if called frequently to convert a single character.
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: c  ! Character string
    end subroutine sic_upper
  end interface
  !
  interface
    function lenc(c)
      !---------------------------------------------------------------------
      ! @ public
      !  Returns the location of the last non-blank character in a string.
      !---------------------------------------------------------------------
      integer(kind=4) :: lenc  ! Function value on return
      character(len=*), intent(in) :: c  ! Character string
    end function lenc
  end interface
  !
  interface
    subroutine sic_blanc(c,n)
      !---------------------------------------------------------------------
      ! @ public
      !   Reduce the character string C to the standard SIC internal syntax.
      !   Suppress all unecessary separators.
      !   Character strings "abcd... " are not modified.
      !   Convert to upper case all characters.
      !   Ignores and destroys comments.
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: c  ! Character string to be formatted
      integer(kind=4),  intent(inout) :: n  ! Length of C
    end subroutine sic_blanc
  end interface
  !
  interface
    subroutine sic_next(line,par,lpar,npar,dotab)
      !---------------------------------------------------------------------
      ! @ public
      !  Returns the next "word" of the command line. Words are separated
      ! by blanks, but also optionally by tabulations.
      !---------------------------------------------------------------------
      character(len=*),  intent(in)    :: line   ! Line to be analysed
      character(len=*),  intent(out)   :: par    ! Next word found
      integer(kind=4),   intent(out)   :: lpar   ! Length of word found
      integer(kind=4),   intent(inout) :: npar   ! Start point for analysis, updated for subsequent call
      logical, optional, intent(in)    :: dotab  ! Take also tabulations as separator?
    end subroutine sic_next
  end interface
  !
  interface
    subroutine sic_noir(cin,np)
      !---------------------------------------------------------------------
      ! @ public
      !  Reduce all separators to one.
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: cin  ! Character string
      integer(kind=4),  intent(out)   :: np   ! Length of string
    end subroutine sic_noir
  end interface
  !
  interface
    subroutine sic_black(cin,np)
      !---------------------------------------------------------------------
      ! @ public
      !   Suppress all separators
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: cin  ! Character string
      integer(kind=4),  intent(out)   :: np   ! Length of string
    end subroutine sic_black
  end interface
  !
  interface
    subroutine sic_upcase(c,n)
      !---------------------------------------------------------------------
      ! @ public
      !   Reduce the character string C to the standard SIC internal syntax.
      !   Suppress all unecessary separators.
      !   Character strings "abcd... " are not modified.
      !   Convert to upper case all characters.
      !   Ignores and destroys comments.
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: c  ! Character string to be formatted
      integer(kind=4),  intent(inout) :: n  ! Length of string
    end subroutine sic_upcase
  end interface
  !
  interface
    subroutine sic_separ(separ,line,par,lpar,npar)
      !---------------------------------------------------------------------
      ! @ public
      !  Returns the next "word" of the command line
      !---------------------------------------------------------------------
      character(len=1), intent(in)    :: separ  !
      character(len=*), intent(in)    :: line   !
      character(len=*), intent(out)   :: par    !
      integer(kind=4),  intent(out)   :: lpar   !
      integer(kind=4),  intent(inout) :: npar   !
    end subroutine sic_separ
  end interface
  !
  interface
    subroutine gagout (mess)
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      character(len=*), intent(in) :: mess  !
    end subroutine gagout
  end interface
  !
  interface
    function sic_get_arg_count()
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_get_arg_count  !  Function value on return
    end function sic_get_arg_count
  end interface
  !
  interface
    subroutine sic_get_arg(n,arg)
      !---------------------------------------------------------------------
      ! @ public
      !   This machine dependent function retrieves the Nth argument of
      ! command line.
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in)  :: n    ! Argument index
      character(len=*), intent(out) :: arg  ! Argument value
    end subroutine sic_get_arg
  end interface
  !
  interface
    subroutine gmessage_init(logname,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Initialization routine for gmessage facility:
      !  - close previously opened message file (useful to change the file
      !    during a session)
      !  - open the (new) message file
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: logname
      logical,          intent(inout) :: error
    end subroutine gmessage_init
  end interface
  !
  interface
    subroutine gmessage_parse_and_set(inid,infilter,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Alter the message filters for input package. Inputs are:
      ! 1) The package id,
      ! 2) The alteration rule, as used in SIC command line, e.g. "s-dtu",
      !    "l=fewri", ...
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in)    :: inid      ! Package id
      character(len=*), intent(in)    :: infilter  ! Filter rule
      logical,          intent(inout) :: error     ! Error flag
    end subroutine gmessage_parse_and_set
  end interface
  !
  interface
    subroutine gmessage_parse_and_set_all(infilter,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Updates all filters for all packages (excluding "Global" ones),
      ! given the input alteration rule
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: infilter  ! Filter rule
      logical,          intent(inout) :: error     ! Error flag
    end subroutine gmessage_parse_and_set_all
  end interface
  !
  interface
    subroutine gmessage_print_active(sev,error)
      use gpack_def
      !---------------------------------------------------------------------
      ! @ public
      ! Prints all filters for all ACTIVE packages (i.e. "Global" or "per
      ! package")
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: sev    ! Severity used to write output
      logical,         intent(inout) :: error  ! Error flag
    end subroutine gmessage_print_active
  end interface
  !
  interface
    subroutine gmessage_print_all(sev,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Prints filters for all packages (excluding "Global" ones)
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: sev    ! Severity used to write output
      logical,         intent(inout) :: error  ! Error flag
    end subroutine gmessage_print_all
  end interface
  !
  interface
    subroutine gmessage_print_id(id,sev,error)
      use gpack_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Prints filters for the input package. Input is the package id.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: id     ! Package id
      integer(kind=4), intent(in)    :: sev    ! Severity used to write output
      logical,         intent(inout) :: error  ! Error flag
    end subroutine gmessage_print_id
  end interface
  !
  interface
    subroutine gmessage_print(packname,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Prints filters for the input package. Input is the package name.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: packname  ! Package name
      logical,          intent(inout) :: error     ! Error flag
    end subroutine gmessage_print
  end interface
  !
  interface
    subroutine gmessage_translate(seve_leve,seve_code,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Translate a message severity letter into its corresponding integer
      ! code, as a call to gmessage_write needs.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: seve_leve  ! Input severity letter
      integer(kind=4),  intent(out)   :: seve_code  ! Translated code
      logical,          intent(inout) :: error      ! Error flag
    end subroutine gmessage_translate
  end interface
  !
  interface
    subroutine gmessage_log_append(flag)
      !---------------------------------------------------------------------
      ! @ public
      ! Message file will be appended if already existing. Must be called
      ! before opening the message file.
      !---------------------------------------------------------------------
      logical, intent(in) :: flag
    end subroutine gmessage_log_append
  end interface
  !
  interface
    subroutine gmessage_close(error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Closes message file and reset its logical unit for a clean handling
      ! of very last messages. Do not produce an error if no message file
      ! is opened.
      !---------------------------------------------------------------------
      logical, intent(inout) :: error    ! Error flag
    end subroutine gmessage_close
  end interface
  !
  interface
    subroutine gmessage_write(id,mkind,procname,message)
      use gpack_def
      use gbl_message
      use gbl_ansicodes
      !---------------------------------------------------------------------
      ! @ public
      ! Output procname and message, with severity kind "mkind", according
      ! to current messaging filters of input package.
      !  - input id is the identifier given to the package when it
      !    registered, or the one from another package if current package
      !    wants to appear as an other into the message file (e.g. 'gio'
      !    messages appear as 'sic' messages in message file).
      !  - mkind is an integer which should be set with the severity
      !    structure provided by gbl_message module.
      !  Although this routine is public, you should call it only once (with
      !  the 4 arguments) in your <packname>-message routine, and then call
      !  everywhere in your package your <packname>-message routine with
      !  3 arguments. Your package id should be known only in the
      ! <packname>-message routine.
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in) :: id        ! Package id
      integer(kind=4),  intent(in) :: mkind     ! Message kind
      character(len=*), intent(in) :: procname  ! Name of calling procedure
      character(len=*), intent(in) :: message   ! Message string
    end subroutine gmessage_write
  end interface
  !
  interface
    subroutine gmessage_write_in_mesfile(id,mkind,procname,message)
      use gpack_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public TEMPORARY FOR CLIC ONLY (SB, 02-jun-2008)
      ! Rewrite of gmessage_write. It writes to mesfile only and ignores
      ! filters.
      !---------------------------------------------------------------------
      ! Output procname and message, with severity kind "mkind", according
      ! to current messaging filters of input package.
      !  - input id is the identifier given to the package when it
      !    registered, or the one from another package if current package
      !    wants to appear as an other into the message file (e.g. 'gio'
      !    messages appear as 'sic' messages in message file).
      !  - mkind is an integer which should be set with the severity
      !    structure provided by gbl_message module.
      !  Although this routine is public, you should call it only once (with
      !  the 4 arguments) in your <packname>-message routine, and then call
      !  everywhere in your package your <packname>-message routine with
      !  3 arguments. Your package id should be known only in the
      ! <packname>-message routine.
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in) :: id        ! Package id
      integer(kind=4),  intent(in) :: mkind     ! Message kind
      character(len=*), intent(in) :: procname  ! Name of calling procedure
      character(len=*), intent(in) :: message   ! Message string
    end subroutine gmessage_write_in_mesfile
  end interface
  !
  interface
    subroutine gag_message(mkind,procname,message)
      use gpack_def
      !---------------------------------------------------------------------
      ! @ public (obsolete)
      ! Outputs procname and message, with severity kind "mkind", according
      ! to current GLOBAL messaging filters. mkind is an integer which
      ! should be set with the severity structure provided by gbl_message
      ! module.
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in) :: mkind     ! Message kind
      character(len=*), intent(in) :: procname  ! Name of calling procedure
      character(len=*), intent(in) :: message   ! Message string
    end subroutine gag_message
  end interface
  !
  interface
    subroutine gmessage_use_gbl_rules(flag)
      !---------------------------------------------------------------------
      ! @ public
      ! Activates or deactivates use of global messaging filters instead of
      ! local (per package) ones.
      !---------------------------------------------------------------------
      logical, intent(in) :: flag  ! Activate if .true.
    end subroutine gmessage_use_gbl_rules
  end interface
  !
  interface
    subroutine gmessage_log_date(flag)
      !---------------------------------------------------------------------
      ! @ public
      ! Activates or deactivates printing date-time in message file.
      !---------------------------------------------------------------------
      logical, intent(in) :: flag  ! Activate if .true.
    end subroutine gmessage_log_date
  end interface
  !
  interface
    subroutine gmessage_quiet
      !---------------------------------------------------------------------
      ! @ public
      ! Ensure almost-quiet messaging mode to Screen.
      ! This is done by setting Global onscreen filter to FE------, and
      ! using Global filters.
      !---------------------------------------------------------------------
      !
    end subroutine gmessage_quiet
  end interface
  !
  interface
    subroutine gmessage_standard
      !---------------------------------------------------------------------
      ! @ public
      ! Restore normal verbosity.
      ! This is done by stopping using Global filters.
      !---------------------------------------------------------------------
      !
    end subroutine gmessage_standard
  end interface
  !
  interface
    subroutine gmessage_verbose
      !---------------------------------------------------------------------
      ! @ public
      ! Provide a maximal verbose messaging mode for Screen and Message
      ! file.
      ! This is done by turning on all the kind of messages, to both Screen
      ! and Message file.
      !---------------------------------------------------------------------
      !
    end subroutine gmessage_verbose
  end interface
  !
  interface
    subroutine gmessage_debug_swap
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Provide a maximal verbose messaging mode for Screen and Message
      ! file.
      ! This is done by turning on all the kind of messages, to both Screen
      ! and Message file.
      !---------------------------------------------------------------------
      ! Local
    end subroutine gmessage_debug_swap
  end interface
  !
  interface
    subroutine gmessage_print_colors(error)
      !---------------------------------------------------------------------
      ! @ public
      ! Show the current status of message colors
      !---------------------------------------------------------------------
      logical, intent(inout) :: error
    end subroutine gmessage_print_colors
  end interface
  !
  interface
    subroutine gmessage_colors_swap(flag)
      !---------------------------------------------------------------------
      ! @ public
      ! Enable or disable the message coloring
      !---------------------------------------------------------------------
      logical, intent(in) :: flag
    end subroutine gmessage_colors_swap
  end interface
  !
  interface
    subroutine gmessage_colors_parse(argum,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Parse argument for changing a message kind color
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: argum
      logical,          intent(inout) :: error
    end subroutine gmessage_colors_parse
  end interface
  !
  interface
    function gpack_get_count()
      !---------------------------------------------------------------------
      ! @ public
      ! Return number of registered packages
      !---------------------------------------------------------------------
      integer(kind=4) :: gpack_get_count
    end function gpack_get_count
  end interface
  !
  interface
    function gpack_get_info(ipack)
      use gpack_def
      !---------------------------------------------------------------------
      ! @ public
      ! Return package information structure
      !---------------------------------------------------------------------
      type(gpack_info_t) :: gpack_get_info
      integer(kind=4), intent(in) :: ipack
    end function gpack_get_info
  end interface
  !
  interface
    function gpack_get_id(gpack_name,present,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Private function to get the package id from the package name
      !---------------------------------------------------------------------
      integer(kind=4)  :: gpack_get_id ! Returned package id
      character(len=*), intent(in)    :: gpack_name   ! Package name
      logical,          intent(in)    :: present      ! Must the package be already registered?
      logical,          intent(inout) :: error        ! Error flag
    end function gpack_get_id
  end interface
  !
  interface
    subroutine gpack_resolve(packname,found,error)
      use gbl_message
      use gpack_def
      !---------------------------------------------------------------------
      ! @ public
      ! Resolve packname string ambiguities
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: packname  ! Package name
      logical,          intent(out)   :: found     ! Found package?
      logical,          intent(inout) :: error     ! Error flag
    end subroutine gpack_resolve
  end interface
  !
  interface
    function gpack_is_registered(gpack_name)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Check registration status of a package
      !---------------------------------------------------------------------
      logical                      :: gpack_is_registered  ! Package registration status
      character(len=*), intent(in) :: gpack_name           ! Package name
    end function gpack_is_registered
  end interface
  !
  interface
    function gpack_build(pack_set,already_registered,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Builds a package and its dependencies, returns package registration
      ! id
      !---------------------------------------------------------------------
      integer(kind=4) :: gpack_build
      external               :: pack_set
      logical, intent(out)   :: already_registered
      logical, intent(inout) :: error
    end function gpack_build
  end interface
  !
  interface
    subroutine gsys_message_set_id(id)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Alter library id into input id. Should be called by the library
      ! which wants to share its id with the current one.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in) :: id
    end subroutine gsys_message_set_id
  end interface
  !
  interface
    function sic_ramlog(chain,trans)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Decode a Sic logical as a RAM space, computed in MiB. 3 syntaxes
      ! are allowed:
      !
      ! No unit: default MiB
      !   SPACE_GILDAS  256    ! [MiB] Absolute value
      !
      ! Explicit unit:
      !   SPACE_GILDAS  256MB  ! Supported units: TB GB MB kB TiB GiB MiB kiB
      !
      ! Percent of total RAM:
      !   SPACE_GILDAS  50%    ! [  ] Relative value in fraction of the total
      !                              RAM size
      !
      ! The value can be integer or floating point. The unit or percent can
      ! be separated from the value by 0 or more blanks.
      !
      ! Function value on return is:
      !    0 if found and translated               ('trans' modified in return)
      !    1 if not found                          ('trans' not modified in return)
      !    2 if found but error during translation ('trans' not modified in return)
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_ramlog  ! Function value on return
      character(len=*), intent(in)    :: chain  ! Logical name (e.g. 'SPACE_GILDAS')
      real(kind=4),     intent(inout) :: trans  ! Output value
    end function sic_ramlog
  end interface
  !
  interface
    function sic_setlog(name,trans)
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_setlog
      character(len=*), intent(in) :: name   !
      character(len=*), intent(in) :: trans  !
    end function sic_setlog
  end interface
  !
  interface
    function dictname(dtype,file)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !
      ! This system dependent routine returns the full names (including
      ! path) of the (internal) logical name definition files.
      ! Known dictionary types as input are 'GLOBAL', 'LOCAL', or 'USER'.
      ! Any other kind raises an error.
      !
      ! This version for Unix.
      !---------------------------------------------------------------------
      integer(kind=4) :: dictname             !
      character(len=*), intent(in)  :: dtype  ! Dictionary type
      character(len=*), intent(out) :: file   ! Associated file
    end function dictname
  end interface
  !
  interface
    subroutine gag_separ(ins,ous,dis)
      !---------------------------------------------------------------------
      ! @ public
      !     Returns the characters used as Separators in path names.
      !     This allows multi-OS support where the directory names are separated
      !     by either / (Unix), \ (Windows), or : (MAC-OS)
      !---------------------------------------------------------------------
      character(len=1), intent(out) :: ins         !
      character(len=1), intent(out) :: ous         !
      character(len=1), intent(out) :: dis         !
    end subroutine gag_separ
  end interface
  !
  interface
    subroutine gag_release(ostring)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !   Return a string with the release name, date, system, and branch.
      ! Read the string in GAG_VERSION symbol, and optionally replace the
      ! release date by the calling executable date if in HEAD version.
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: ostring  ! Output string
    end subroutine gag_release
  end interface
  !
  interface sic_getlog
    function sic_getlog_i4(chain,trans)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic sic_getlog
      !  Translate a logical value. Function value on return is:
      !    0 if found and translated               ('trans' modified in return)
      !    1 if not found                          ('trans' not modified in return)
      !    2 if found but error during translation ('trans' not modified in return)
      ! ---
      !  I*4 version
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlog_i4  ! Function value on return
      character(len=*), intent(in)    :: chain  ! Logical name (e.g. 'SPACE_GILDAS')
      integer(kind=4),  intent(inout) :: trans  ! Output value
    end function sic_getlog_i4
    function sic_getlog_i8(chain,trans)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic sic_getlog
      !  Translate a logical value. Function value on return is:
      !    0 if found and translated               ('trans' modified in return)
      !    1 if not found                          ('trans' not modified in return)
      !    2 if found but error during translation ('trans' not modified in return)
      ! ---
      !  I*8 version
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlog_i8  ! Function value on return
      character(len=*), intent(in)    :: chain  ! Logical name (e.g. 'SPACE_GILDAS')
      integer(kind=8),  intent(inout) :: trans  ! Output value
    end function sic_getlog_i8
    function sic_getlog_r4(chain,trans)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic sic_getlog
      !  Translate a logical value. Function value on return is:
      !    0 if found and translated               ('trans' modified in return)
      !    1 if not found                          ('trans' not modified in return)
      !    2 if found but error during translation ('trans' not modified in return)
      ! ---
      !  R*4 version
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlog_r4  ! Function value on return
      character(len=*), intent(in)    :: chain  ! Logical name (e.g. 'SPACE_GILDAS')
      real(kind=4),     intent(inout) :: trans  ! Output value
    end function sic_getlog_r4
    function sic_getlog_r8(chain,trans)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic sic_getlog
      !  Translate a logical value. Function value on return is:
      !    0 if found and translated               ('trans' modified in return)
      !    1 if not found                          ('trans' not modified in return)
      !    2 if found but error during translation ('trans' not modified in return)
      ! ---
      !  R*8 version
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlog_r8  ! Function value on return
      character(len=*), intent(in)    :: chain  ! Logical name (e.g. 'SPACE_GILDAS')
      real(kind=8),     intent(inout) :: trans  ! Output value
    end function sic_getlog_r8
    function sic_getlog_l(chain,trans)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic sic_getlog
      !  Translate a logical value. Function value on return is:
      !    0 if found and translated               ('trans' modified in return)
      !    1 if not found                          ('trans' not modified in return)
      !    2 if found but error during translation ('trans' not modified in return)
      ! ---
      !  Logical (boolean) version. Supported keywords are (case-
      ! insensitive): YES, Y, NO, N
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlog_l  ! Function value on return
      character(len=*), intent(in)    :: chain  ! Logical name (e.g. 'SPACE_GILDAS')
      logical,          intent(inout) :: trans  ! Output value
    end function sic_getlog_l
    function sic_getlog_ch(name,trans)
      !---------------------------------------------------------------------
      ! @ public-generic sic_getlog
      !  Translate a logical value. Function value on return is:
      !    0 if found and translated ('trans' modified in return)
      !    1 if not found            ('trans' not modified in return)
      ! ---
      !  C*(*) version
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlog_ch  ! Function value on return
      character(len=*), intent(in)    :: name   ! Logical name
      character(len=*), intent(inout) :: trans  ! Output value
    end function sic_getlog_ch
    function sic_getlog_inplace(name)
      !---------------------------------------------------------------------
      ! @ public-generic sic_getlog
      !  Translate a logical value. Function value on return is:
      !    0 if found and translated ('name' modified in return)
      !    1 if not found            ('name' not modified in return)
      !  OBSOLESCENT, USE 2 ARGUMENTS INSTEAD  !!!
      ! ---
      !  C*(*) version, obsolescent calling sequence which replaces the
      ! value in place.
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlog_inplace
      character(len=*), intent(inout) :: name  ! Output value
    end function sic_getlog_inplace
  end interface sic_getlog
  !
  interface
    function gag_hasins(mdim,pf,pn,dict,name,in)
      !---------------------------------------------------------------------
      ! @ public
      !  *** This version for dictionaries as character string arrays ***
      !       Insert a new name or replace an existing name
      !       in a dictionnary using a hashing structure
      !       and a list of pointers.
      !
      !       GAG_HASINS      0       E  Invalid name
      !                       1       S  Successfully inserted
      !                       2       E  Too many names
      !                       3       S  Successfully replaced
      !
      !       PF      I(0:27) PF(J) Address of first name beginning
      !                       with CHAR(J-ICHAR('A')) in dictionnary.
      !                       PF(26) is the address of the first
      !                       available place.                        Input/Output
      !                       PF(27) is the number of symbols
      !       PN      I(MDIM) Address of next name with same first
      !                       letter. If PN(J)=0, no more such name.  Input/Output
      !---------------------------------------------------------------------
      integer(kind=4) :: gag_hasins  ! Function value on return
      integer(kind=4),  intent(in)    :: mdim        ! Size of dictionnary
      integer(kind=4),  intent(inout) :: pf(0:27)    !
      integer(kind=4),  intent(inout) :: pn(mdim)    !
      character(len=*), intent(inout) :: dict(mdim)  ! Dictionnary array of size MDIM
      character(len=*), intent(inout) :: name        ! Name to be inserted
      integer(kind=4),  intent(out)   :: in          ! Address of this name
    end function gag_hasins
  end interface
  !
  interface
    subroutine gag_hasini(mdim,pf,pn)
      !---------------------------------------------------------------------
      ! @ public
      ! SIC   Internal routine
      !  *** This version for all kind of dictionaries ***
      !       Initialise a hashing structure for a possible dictionnary.
      ! Arguments :
      !       MDIM    I       Size of dictionnary
      !       PF      I(0:27) PF(J) Address of first name beginning
      !                       with CHAR(J-ICHAR('A')) in dictionnary.
      !                       PF(26) is the address of the first
      !                       available place.
      !                       PF(27) the number of symbol
      !       PN      I(MDIM) Address of next name with same first
      !                       letter. If PN(J)=0, no more such name.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: mdim      !
      integer(kind=4), intent(out) :: pf(0:27)  !
      integer(kind=4), intent(out) :: pn(mdim)  !
    end subroutine gag_hasini
  end interface
  !
  interface
    function gag_hasdel(mdim,pf,pn,dict,name)
      !---------------------------------------------------------------------
      ! @ public
      !  *** This version for dictionaries as character string arrays ***
      !       Delete a name in a dictionnary using a hashing structure
      !       and a list of pointers.
      !
      !       GAG_HASDEL      1       Name deleted
      !                       3       Name does not exist
      !
      !       PF      I(0:27) PF(J) Address of first name beginning
      !                       with CHAR(J-ICHAR('A')) in dictionnary.
      !                       PF(26) is the address of the first
      !                       available place.                        Input/Output
      !                       PF(27) is the number of symbols
      !       PN      I(MDIM) Address of next name with same first
      !                       letter. If PN(J)=0, no more such name.  Input/Output
      !---------------------------------------------------------------------
      integer(kind=4) :: gag_hasdel  ! Function value on return
      integer(kind=4),  intent(in)    :: mdim        ! Size of dictionnary
      integer(kind=4),  intent(inout) :: pf(0:27)    !
      integer(kind=4),  intent(inout) :: pn(mdim)    !
      character(len=*), intent(in)    :: dict(mdim)  ! Dictionnary array of size MDIM
      character(len=*), intent(inout) :: name        ! Name to be deleted
    end function gag_hasdel
  end interface
  !
  interface
    function gag_hasfin(mdim,pf,pn,dict,name,in)
      !---------------------------------------------------------------------
      ! @ public
      !  *** This version for dictionaries as character string arrays ***
      !       Find a name in a dictionnary using a hashing structure
      !       and a list of pointers.
      !
      !       GAG_HASFIN      0       No such name
      !                       1       Name found
      !       PF      I(0:27) PF(J) Address of first name beginning
      !                       with CHAR(J-ICHAR('A')) in dictionnary.
      !                       PF(26) is the address of the first
      !                       available place.                        Input
      !       PN      I(MDIM) Address of next name with same first
      !                       letter. If PN(J)=0, no more such name.  Input
      !---------------------------------------------------------------------
      integer(kind=4) :: gag_hasfin  ! Function value on return
      integer(kind=4),  intent(in)    :: mdim        ! Size of dictionnary
      integer(kind=4),  intent(in)    :: pf(0:27)    !
      integer(kind=4),  intent(in)    :: pn(mdim)    !
      character(len=*), intent(in)    :: dict(mdim)  ! Dictionnary array of size MDIM
      character(len=*), intent(inout) :: name        ! Name to be found
      integer(kind=4),  intent(out)   :: in          ! Address of this name
    end function gag_hasfin
  end interface
  !
  interface
    subroutine gag_haslis(mdim,pf,pn,list,leng)
      !---------------------------------------------------------------------
      ! @ public
      !  *** This version for all kind of dictionaries ***
      !
      !  List a dictionnary using a hashing structure and a list of pointers.
      ! This routine just builds the list of pointers to current entries.
      !
      ! THERE IS NO WARRANTY THE OUTPUT LIST IS SORTED ALPHABETICALLY.
      ! Actually with the current hashing method, the output list is sorted
      ! by first letter only. Use subroutine gag_hassort for a fully sorted
      ! list.
      !
      !   PF(0:27)   PF(0:25) Address of first name beginning with
      !                       CHAR(J-ICHAR('A')) in dictionnary.
      !              PF(26)   is the address of the first available place.
      !              PF(27)   the number of symbols
      !   PN(MDIM)            Address of next name with same first letter.
      !                       If PN(J)=0, no more such name.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)  :: mdim        ! Size of dictionnary
      integer(kind=4), intent(in)  :: pf(0:27)    !
      integer(kind=4), intent(in)  :: pn(mdim)    !
      integer(kind=4), intent(out) :: list(mdim)  ! List of entries in dictionnary
      integer(kind=4), intent(out) :: leng        ! Current number of entries
    end subroutine gag_haslis
  end interface
  !
  interface
    function sic_open(unit,file,status,readonly)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! This machine dependent function opens a formatted file, and returns an
      ! error code. This Unix version simulates version numbers by renaming
      ! any existing file to a ~appended name.
      !
      ! Possible statuses are:
      !  - NEW: rename previous version with ~ appended (GILDAS special
      !         feature) and create a new file (only write mode makes sense)
      !  - REPLACE: overwrite an OLD file (if any) and create a new file
      !         (only write mode makes sense)
      !  - APPEND: open an OLD file in read-write mode (always), ready for
      !         writing at end of file.
      !  - OLD: reopen an old file in read-only or read-write mode (as
      !         desired)
      !  - other Fortran standard keywords
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_open  ! Return value
      integer(kind=4),  intent(in) :: unit      ! Fortran logical unit
      character(len=*), intent(in) :: file      ! File name
      character(len=*), intent(in) :: status    ! File status ('NEW', or 'OLD', or...)
      logical,          intent(in) :: readonly  ! Open as write protected?
    end function sic_open
  end interface
  !
  interface
    function sic_flush(unit)
      !---------------------------------------------------------------------
      ! @ public
      ! This function flushes file buffer onto disk, and returns an error
      ! code.
      !---------------------------------------------------------------------
      integer(kind=4)             :: sic_flush  ! Flush status (0=success)
      integer(kind=4), intent(in) :: unit       ! Logical unit
    end function sic_flush
  end interface
  !
  interface
    function sic_close(unit)
      !---------------------------------------------------------------------
      ! @ public
      ! This function closes a formatted file, and returns an error code.
      ! Following the Fortran norm, default closing STATUS:
      ! - is DELETE if unit has been opened with STATUS=SCRATCH,
      ! - is KEEP if unit has been opened with any other STATUS.
      ! Use unit=0 to close all units.
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_close  ! Close status (0=success)
      integer(kind=4), intent(in) :: unit  ! Logical unit to close
    end function sic_close
  end interface
  !
  interface
    subroutine sic_frelun(unit)
      !---------------------------------------------------------------------
      ! @ public
      ! This machine dependent function frees a Fortran logical unit obtained
      ! through a call to SIC_GETLUN. Error on close can not be retrieved,
      ! use GAG_FRELUN to do so.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in) :: unit  ! Fortran logical unit to close
    end subroutine sic_frelun
  end interface
  !
  interface
    function sic_getlun(unit)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! This machine dependent function returns a free Fortran logical unit in
      ! UNIT. The function value is an error code. For safe operation, all
      ! logical units used by the program should be obtained through calls to
      ! SIC_GETLUN. This portable version reserves all units between STALUN+1
      ! and STALUN+MAXLUN, which may interfere with the calling program. Safer
      ! equivalents can usually be obtained through system calls.
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_getlun  ! Function value on return
      integer(kind=4), intent(out) :: unit  ! Unit obtained on return
    end function sic_getlun
  end interface
  !
  interface
    function gag_frelun(unit)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! This machine dependent function frees a Fortran logical unit obtained
      ! through a call to SIC_GETLUN. The function value is an error code.
      !---------------------------------------------------------------------
      integer(kind=4) :: gag_frelun  ! Function value on return
      integer(kind=4), intent(in) :: unit  ! Logical unit to close
    end function gag_frelun
  end interface
  !
  interface
    function gag_stalun(unit)
      !---------------------------------------------------------------------
      ! @ public
      ! Stat input lun (or all if lun=0) and print out status of lun(s)
      !---------------------------------------------------------------------
      integer(kind=4) :: gag_stalun  ! Function value on return
      integer(kind=4), intent(in) :: unit  ! Unit to stat
    end function gag_stalun
  end interface
  !
  interface
    function sic_purge(file,keep)
      !---------------------------------------------------------------------
      ! @ public
      ! This machine dependent function deletes all versions of a file except
      ! for the KEEP last ones, KEEP=0 being a supported case. The function
      ! value is an error code. This dummy version does nothing and should be
      ! replaced by an EMACS-like behaviour (using numbered backup files).
      !---------------------------------------------------------------------
      integer(kind=4) :: sic_purge  ! Return value
      character(len=*), intent(in) :: file       ! File name
      integer(kind=4),  intent(in) :: keep       ! Number of versions that should be kept
    end function sic_purge
  end interface
  !
  interface
    subroutine sic_resolve_log(chain)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      ! Resolve logical variables recursively
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: chain  !
    end subroutine sic_resolve_log
  end interface
  !
  interface
    subroutine sic_parse_file(name,dir,ext,file)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      ! Adds the directory DIR and extension EXT if necessary to the file
      ! name NAME to form FILE. In addition, logical name are translated to
      ! obtain the intrinsic "physical" names.
      !
      ! For UNIX purposes: (a logical name is somestring finished with ":")
      !      a) converts "\" to "/"
      !      b) converts ~ to $HOME
      !
      ! if first character is "!" or "/"
      !     1) TRANSLATES LOGICAL NAMES
      !     2) Does not add extension
      !     3) is respectful of upper/lowercases
      ! if not :
      !     1) converts to lowercase
      !     2) TRANSLATES LOGICAL NAMES
      !     3) Does add extension, in lowercase
      !---------------------------------------------------------------------
      character(len=*), intent(in)  :: name  ! File name
      character(len=*), intent(in)  :: dir   ! Default directory
      character(len=*), intent(in)  :: ext   ! Default extension
      character(len=*), intent(out) :: file  ! Fully extended file name
    end subroutine sic_parse_file
  end interface
  !
  interface
    subroutine sic_parsef(name,file,dir,ext)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Same as SIC_PARSE_FILE +
      !  at return, NAME is the file named stripped from directory and
      !  extension
      ! ---
      !  Obsolete: use SIC_PARSE_FILE and/or SIC_PARSE_NAME instead
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: name  ! File name
      character(len=*), intent(out)   :: file  ! Fully extended file name
      character(len=*), intent(in)    :: dir   ! Default directory
      character(len=*), intent(in)    :: ext   ! Default extension
    end subroutine sic_parsef
  end interface
  !
  interface
    function sic_query_file (name,path,ext,file)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      ! Same as sic_findfile but avoid modifying input 'name'
      !---------------------------------------------------------------------
      logical :: sic_query_file              ! Function value on return
      character(len=*), intent(in)  :: name  ! File name
      character(len=*), intent(in)  :: path  ! Search path
      character(len=*), intent(in)  :: ext   ! Default extension
      character(len=*), intent(out) :: file  ! Fully extended file name
    end function sic_query_file
  end interface
  !
  interface
    function sic_findfile(name,file,path,ext)
      !---------------------------------------------------------------------
      ! @ public
      !  Search on the path PATH and with extension EXT if necessary the
      ! file name NAME to find FILE. At return, NAME is the file named
      ! stripped from these extensions. In addition, logical name are
      ! translated to obtain the intrinsic "physical" names.
      !---------------------------------------------------------------------
      logical :: sic_findfile                  ! Function value on return
      character(len=*), intent(inout) :: name  ! File name
      character(len=*), intent(out)   :: file  ! Fully extended file name
      character(len=*), intent(in)    :: path  ! Search Path
      character(len=*), intent(in)    :: ext   ! Default extension
    end function sic_findfile
  end interface
  !
  interface
    subroutine sic_parse_name(iname,ofile,oext,odir)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      !  Split an input file name as:
      !  - its basename (no extension),
      !  - its extension,
      !  - its dirname.
      ! Sic logicals are resolved in the the input file name before parsing
      !---------------------------------------------------------------------
      character(len=*), intent(in)            :: iname
      character(len=*), intent(out)           :: ofile
      character(len=*), intent(out), optional :: oext
      character(len=*), intent(out), optional :: odir
    end subroutine sic_parse_name
  end interface
  !
  interface
    subroutine gag_iostat (msg,ier)
      !---------------------------------------------------------------------
      ! @ public
      ! Return system message corresponding to IO error code IER
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: msg  ! Returned message
      integer(kind=4),  intent(in)  :: ier  ! 32-bit system message code
    end subroutine gag_iostat
  end interface
  !
  interface
    function failed_allocate(rname,array,ier,error)
      use gbl_message
      !-------------------------------------------------------------------
      ! @ public
      ! Check allocation status and display a message if error
      !-------------------------------------------------------------------
      logical :: failed_allocate  ! Function value on return
      character(len=*), intent(in)    :: rname  ! Calling routine name
      character(len=*), intent(in)    :: array  ! Name of allocated array
      integer(kind=4),  intent(in)    :: ier    ! Allocation status
      logical,          intent(inout) :: error  ! Logical error flag
    end function failed_allocate
  end interface
  !
  interface putios
    subroutine putios_write (name,ier)
      !---------------------------------------------------------------------
      ! @ public-generic putios
      ! Print system message corresponding to IO error code IER
      ! ---
      ! This version writes directly the message to STDOUT
      !---------------------------------------------------------------------
      character(len=*), intent(in) :: name  ! Facility name
      integer(kind=4),  intent(in) :: ier   ! 32-bit system message code
    end subroutine putios_write
    subroutine putios_message (mseve,procname,ier)
      !---------------------------------------------------------------------
      ! @ public-generic putios
      ! Print system message corresponding to IO error code IER
      ! ---
      ! This version creates a standard message
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in) :: mseve     ! Message severity
      character(len=*), intent(in) :: procname  ! Name of calling procedure
      integer(kind=4),  intent(in) :: ier       ! 32-bit system message code
    end subroutine putios_message
  end interface putios
  !
  interface
    subroutine sexag(ch,rr8,ndiv)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public (obsolescent since 19-mar-2015, use rad2sexa instead)
      !  Writes an angle in sexagesimal notation. The number of characters
      ! updated are limited to 13.
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: ch    ! Formatted string
      real(kind=8),     intent(in)  :: rr8   ! Angle in radians
      integer(kind=4),  intent(in)  :: ndiv  ! Number of divisions per turn (24/360)
    end subroutine sexag
  end interface
  !
  interface
    subroutine deg2sexa(d8,ndiv,ch,ndig,left)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public
      !  Write an angle (degrees) in sexagesimal notation.
      !---------------------------------------------------------------------
      real(kind=8),     intent(in)           :: d8    ! [Deg] Angle
      integer(kind=4),  intent(in)           :: ndiv  ! [   ] Number of div. per turn (24/360)
      character(len=*), intent(out)          :: ch    ! [   ] Formatted string
      integer(kind=4),  intent(in), optional :: ndig  ! [   ] Number of digits desired
      logical,          intent(in), optional :: left  ! [   ] Left justify the output string?
    end subroutine deg2sexa
  end interface
  !
  interface
    subroutine rad2sexa(rr8,ndiv,ch,ndig,left)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public
      !  Write an angle (radians) in sexagesimal notation.
      !  The number of digits in the fractional part is controled by 'ndig'.
      ! If absent, the string will be filled with as many digits as
      ! possible, for example if you want a 3 digits fractional part, use
      !  -DDD:MM:SS.SSS = 14 characters (360 divisions per turn)
      !  -HH:MM:SS.SSS = 13 characters (24 divisions per turn)
      !---------------------------------------------------------------------
      real(kind=8),     intent(in)           :: rr8   ! [Rad] Angle
      integer(kind=4),  intent(in)           :: ndiv  ! [   ] Number of div. per turn (24/360)
      character(len=*), intent(out)          :: ch    ! [   ] Formatted string
      integer(kind=4),  intent(in), optional :: ndig  ! [   ] Number of digits desired
      logical,          intent(in), optional :: left  ! [   ] Left justify the output string?
    end subroutine rad2sexa
  end interface
  !
  interface
    subroutine deg2dms(r8,d,m,s)
      !---------------------------------------------------------------------
      ! @ public
      !  Split a floating point value in degreee-minute-seconds numerical
      ! values. No assumption on the input value unit.
      !---------------------------------------------------------------------
      real(kind=8),    intent(in)  :: r8
      integer(kind=4), intent(out) :: d
      integer(kind=4), intent(out) :: m
      real(kind=8),    intent(out) :: s
    end subroutine deg2dms
  end interface
  !
  interface
    subroutine ctodes(string,nc,addr)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      ! Copy at address the value of 'string'. nc is the maximum length
      ! (number of bytes) of the string to copy.
      !---------------------------------------------------------------------
      character(len=*),             intent(in) :: string  !
      integer(kind=4),              intent(in) :: nc      !
      integer(kind=address_length), intent(in) :: addr    ! Address is not modified
    end subroutine ctodes
  end interface
  !
  interface
    subroutine destoc(nc,addr,string)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      ! Copy in 'string' the value referenced at address 'addr'. nc
      ! is the maximum length (number of bytes) of the string to copy.
      !---------------------------------------------------------------------
      integer(kind=4),              intent(in)  :: nc      !
      integer(kind=address_length), intent(in)  :: addr    !
      character(len=*),             intent(out) :: string  !
    end subroutine destoc
  end interface
  !
  interface
    function match_string(string,pattern)
      !---------------------------------------------------------------------
      ! @ public
      ! Basic function for regular expression matching. Only '*' is
      ! currently recognized as a special character.
      !  * : matches 0 or more characters
      ! By construction, tolerate contiguous stars e.g. 'AB***CD'. Matching
      ! is case-sensitive.
      !---------------------------------------------------------------------
      logical                      :: match_string  ! Return value
      character(len=*), intent(in) :: string        ! String to test
      character(len=*), intent(in) :: pattern       ! Pattern to match
    end function match_string
  end interface
  !
  interface
    subroutine sic_terminal(name)
      !---------------------------------------------------------------------
      ! @ public
      !  Returns the name of the terminal.
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: name  ! Terminal name
    end subroutine sic_terminal
  end interface
  !
  interface
    subroutine sysexi(code)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !---------------------------------------------------------------------
      integer(kind=4), intent(in) :: code  ! Input terminating code
    end subroutine sysexi
  end interface
  !
  interface
    subroutine gag_os(os)
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: os  !
    end subroutine gag_os
  end interface
  !
  interface
    subroutine gag_mkdir(dir,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      character(len=*), intent(in)  :: dir    !
      logical,          intent(out) :: error  !
    end subroutine gag_mkdir
  end interface
  !
  interface
    subroutine gag_directory_num(dirstring,num,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Return the number of standard files in a directory. Nice to be
      ! called before 'gag_directory' so that the filename(:) array can be
      ! allocated to an appropriate size.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: dirstring  !
      integer(kind=4),  intent(out)   :: num        ! Number of standard files
      logical,          intent(inout) :: error      ! Logical error flag
    end subroutine gag_directory_num
  end interface
  !
  interface
    subroutine gag_directory(dirstring,filestring,filename,nfile,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !   Return the actual files that match a given string (with *'s)
      ! inside a given directory (no *'s). Note that nothing forbids the
      ! file pattern to ask for subdirectories (e.g. */foo*.dat). The short
      ! filenames are returned (without directory path).
      !   In return, the list of files is stored in an array provided by the
      ! caller. This array MUST be allocatable. The subroutine will
      ! reallocate it to the appropriate size.
      !---------------------------------------------------------------------
      character(len=*), intent(in)               :: dirstring    ! input directory
      character(len=*), intent(in)               :: filestring   ! input file string
      character(len=*), intent(out), allocatable :: filename(:)  ! char array filled in
      integer(kind=4),  intent(out)              :: nfile        ! number of files
      logical,          intent(inout)            :: error        !
    end subroutine gag_directory
  end interface
  !
  interface
    subroutine sic_username(name)
      !---------------------------------------------------------------------
      ! @ public
      ! Return user name from:
      ! 1) $USER environment variable, else
      ! 2) $LOGNAME environment variable, else
      ! 3) use string "Gildas"
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: name  ! Output string
    end subroutine sic_username
  end interface
  !
  interface
    subroutine sic_hostname(node)
      !---------------------------------------------------------------------
      ! @ public
      ! Return host name from:
      ! 1) $HOST environment variable, else
      ! 2) $HOSTNAME environment variable, else
      ! 3) non-standard subroutine HOSTNM (standard alternative could be
      !    execute_command_line("hostname",node), else
      ! 4) blank string
      !---------------------------------------------------------------------
      character(len=*), intent(out) :: node  ! Output string
    end subroutine sic_hostname
  end interface
  !
  interface
    subroutine sic_setdir(direc,nc,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! SIC   Machine specific routine that changes and/or returns the
      !       default directory.
      !---------------------------------------------------------------------
      character(len=*), intent(inout) :: direc  ! Name of default directory
      integer(kind=4),  intent(inout) :: nc     ! Length of directory name
      logical,          intent(inout) :: error  ! Error flag
    end subroutine sic_setdir
  end interface
  !
  interface
    subroutine gag_cpu(arg)
      !---------------------------------------------------------------------
      ! @ public
      ! All compilers are assumed to be Fortran 1995 compatible now
      !---------------------------------------------------------------------
      real(kind=4), intent(out) :: arg  !
    end subroutine gag_cpu
  end interface
  !
  interface
    subroutine gag_delete(fich)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      character(len=*), intent(in) :: fich  !
    end subroutine gag_delete
  end interface
  !
  interface
    function gag_which(name,dirlist,full)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      !   Find which file is invoked, given its name. Input name may
      ! include:
      !   - an absolute path,
      !   - a relative path,
      !   - only the file name, in which case it is searched in the
      !     input list of directories (might be an environment variable).
      !     This list is ignored in the 2 above cases.
      ! Output is a valid path to the file from current working directory.
      ! It is legal to search for a file which does not exist. The (or a)
      ! full path will be built, but the function value will be false on
      ! return.
      !   This function does the same as 'which' system command if input
      ! name is searched in '$PATH'
      !---------------------------------------------------------------------
      logical :: gag_which                      ! .true. on return if found
      character(len=*), intent(in)  :: name     ! File name to search
      character(len=*), intent(in)  :: dirlist  ! List of directories to search in (optional)
      character(len=*), intent(out) :: full     ! Return the path in this variable
    end function gag_which
  end interface
  !
  interface
    function gag_mtime(file,nanosec)
      !---------------------------------------------------------------------
      ! @ public
      ! Return the last modification time in nanoseconds since 01-jan-1970
      ! The file can be a regular file or a directory. If file is a symlink,
      ! evaluation is made on its target.
      ! Max value is 2**63-1 ns = (2**63-1)/1e9/86400/365 = 292 years
      !---------------------------------------------------------------------
      integer(kind=4) :: gag_mtime  ! Function value on return (0 for success)
      character(len=*), intent(in)  :: file     ! File name
      integer(kind=8),  intent(out) :: nanosec  !
    end function gag_mtime
  end interface
  !
  interface
    function gag_time(nanosec)
      !---------------------------------------------------------------------
      ! @ public
      ! Return the current time in nanoseconds since 01-jan-1970
      ! Max value is 2**63-1 ns = (2**63-1)/1e9/86400/365 = 292 years
      !---------------------------------------------------------------------
      integer(kind=4) :: gag_time  ! Function value on return (0 for success)
      integer(kind=8), intent(out) :: nanosec  !
    end function gag_time
  end interface
  !
  interface
    subroutine gag_filmodif(file,modif,error)
      use gbl_message
      use gsys_types
      !---------------------------------------------------------------------
      ! @ public
      !  (re)compute the 'modified' structure and evaluate if the file
      ! was 'probably' modified since last evaluation. The file can be
      ! a regular file or a directory. If file is a symlink, evaluation is
      ! made on its target.
      !   NB: modif%modified is NOT modified if there is an ambiguity.
      ! It is up to the caller to set it to its best default according to
      ! the context.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: file   ! File name
      type(mfile_t),    intent(inout) :: modif  !
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine gag_filmodif
  end interface
  !
  interface
    subroutine gag_fillines(file,doblank,nlines,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Count the number of lines in a FORMATTED file. More precisely, it
      ! counts the number of carriage returns (same as Linux shell "wc -l").
      ! Be careful of missing carriage return at the end of your files.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: file     !
      logical,          intent(in)    :: doblank  ! Ignore blank lines?
      integer(kind=4),  intent(out)   :: nlines   !
      logical,          intent(inout) :: error    !
    end subroutine gag_fillines
  end interface
  !
  interface
    function gag_filsame(file1,file2)
      !---------------------------------------------------------------------
      ! @ public
      ! Check if 2 files are identical or not.
      ! This is based by comparing the devices hosting the files and the
      ! inodes on the devices.
      !---------------------------------------------------------------------
      logical :: gag_filsame
      character(len=*), intent(in) :: file1,file2
    end function gag_filsame
  end interface
  !
  interface
    function gag_memsize_format(nbytes) result(result)
      !---------------------------------------------------------------------
      ! @ public
      ! Format a memory size in a human readable form, with appropriate
      ! units.
      !---------------------------------------------------------------------
      character(len=8)            :: result
      integer(kind=8), intent(in) :: nbytes ! [Bytes]
    end function gag_memsize_format
  end interface
  !
  interface
    subroutine gag_cputime_init(time)
      use gsys_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(cputime_t), intent(inout) :: time  !
    end subroutine gag_cputime_init
  end interface
  !
  interface
    subroutine gag_cputime_get(time)
      use gsys_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(cputime_t), intent(inout) :: time  !
    end subroutine gag_cputime_get
  end interface
  !
  interface
    subroutine gtime_current(time)
      use gbl_message
      use gsys_types
      !---------------------------------------------------------------------
      ! @ public
      ! Display the timing statistics and projections
      !---------------------------------------------------------------------
      type(time_t), intent(inout) :: time
    end subroutine gtime_current
  end interface
  !
  interface gtime_init
    subroutine gtime_init4(time,nloop,error)
      use gsys_types
      !---------------------------------------------------------------------
      ! @ public-generic gtime_init
      ! Init the timing structure (INTEGER*4 nloop)
      !---------------------------------------------------------------------
      type(time_t),    intent(out)   :: time
      integer(kind=4), intent(in)    :: nloop
      logical,         intent(inout) :: error
    end subroutine gtime_init4
    subroutine gtime_init8(time,nloop,error)
      use gbl_message
      use gsys_types
      !---------------------------------------------------------------------
      ! @ public-generic gtime_init
      ! Init the timing structure (INTEGER*8 nloop)
      !---------------------------------------------------------------------
      type(time_t),    intent(out)   :: time
      integer(kind=8), intent(in)    :: nloop
      logical,         intent(inout) :: error
    end subroutine gtime_init8
  end interface gtime_init
  !
end module gsys_interfaces_public
