!-----------------------------------------------------------------------
! Miscellaneous system dependent routines. Some are written in Fortran
! (module sysfor.for), others in C (module sysc.c)
!-----------------------------------------------------------------------
subroutine sic_terminal(name)
  !---------------------------------------------------------------------
  ! @ public
  !  Returns the name of the terminal.
  !---------------------------------------------------------------------
  character(len=*), intent(out) :: name  ! Terminal name
  name = '/dev/tty'
  !  Alternate code (calls ctermid through a buffer C routine)
  !
  !       INTEGER BUFSIZ
  !       PARAMETER (BUFSIZ=80)   ! Should be long enough for a physical name...
  !       INTEGER(KIND=1) BUFFER(BUFSIZ)
  !       INTEGER I
  !*
  !       CALL TERMC(BUFFER)      ! Calls ctermid
  !       DO I=1,MIN(LEN(NAME),BUFSIZ)
  !           NAME(I:I) = CHAR(BUFFER(I))
  !       ENDDO
end subroutine sic_terminal
!
subroutine sysexi(code)
  use gsys_interfaces, except_this=>sysexi
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !---------------------------------------------------------------------
  integer(kind=4), intent(in) :: code  ! Input terminating code
  ! Local
  character(len=message_length) :: mess
  !
#if defined(FORTRAN2003)
  logical :: error
#endif
  !
  if (mod(code,2).eq.0) then
    write (mess,100) code
    call gsys_message(seve%f,'SYSTEM',mess)
#if defined(FORTRAN2003)
    ! Flush the message file, this can help after a crash...
    error = .false.
    call gmessage_flush(error)
    ! Flush the STDOUT, this can help after a task crash...
    call flush(6)
#endif
    !
    call gag_crash
  endif
  stop ' '
100 format ('Exit code ',i12,' from call to SYSEXI')
end subroutine sysexi
!
subroutine gag_os(os)
  !---------------------------------------------------------------------
  ! @ public
  !---------------------------------------------------------------------
  character(len=*), intent(out) :: os  !
#if defined(WIN32)
  os = 'WIN32'
#else
  os = 'LINUX'
#endif
end subroutine gag_os
!
subroutine gag_mkdir(dir,error)
  use gsys_interfaces, except_this=>gag_mkdir
  use gildas_def
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: dir    !
  logical,          intent(out) :: error  !
  ! Local
  character(len=*), parameter :: rname='GAG_MKDIR'
  ! Local
  integer(kind=4) :: ier
  character(len=filename_length) :: chain,dire
  !
  dire = dir
  ier = sic_getlog(dire)
#ifdef MINGW
  chain = 'mkdir '//dire
#else
  chain = 'mkdir -p '//dire
#endif
  ier = gag_system(chain)
  if (ier.ne.0) then
    call gsys_message(seve%e,rname,'Could not create directory '//dire)
    error = .true.
  else
    error = .false.
  endif
end subroutine gag_mkdir
!
subroutine gag_directory_num(dirstring,num,error)
  use gbl_message
  use gsys_interfaces, except_this=>gag_directory_num
  !---------------------------------------------------------------------
  ! @ 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
  ! Local
  character(len=*), parameter :: rname='GAG_DIRECTORY_NUM'
  character(len=filename_length) :: dstring
  integer(kind=4) :: ier
  !
  call sic_resolve_env(dirstring,dstring)  ! Resolve ~ and other environment vars
  call sic_resolve_log(dstring)            ! Resolve sic logicals
  !
  if (gag_inquire(dstring,len_trim(dstring)).ne.0) then
    num = 0
    call gsys_message(seve%e,rname,'No such directory '//dstring)
    error = .true.
    return
  endif
  !
  ier = gag_directory_num_C(dstring,num)
  if (ier.ne.0) then
    call gsys_message(seve%e,rname,'Error counting files in '//dirstring)
    error = .true.
    return
  endif
  !
end subroutine gag_directory_num
!
subroutine gag_directory(dirstring,filestring,filename,nfile,error)
  use gildas_def
  use gbl_message
  use gsys_interfaces, except_this=>gag_directory
  !---------------------------------------------------------------------
  ! @ 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        !
  ! Local
  character(len=*), parameter :: rname='GAG_DIRECTORY'
  integer(kind=4) :: lun,ier,ic,ld
  character(len=filename_length) :: com,tmp,tmpname,dstring
  character(len=1) :: insep,ousep,cdir
  logical :: doalloc
#if defined(WIN32)
  integer(kind=4) :: i, nbrack, nclose, idot, nt
  character(len=filename_length) :: tmpstring
  character(len=4) :: addstring
  character(len=32) :: extension
#endif
  !
  ier = 0
  nfile = 0
  ld = lenc(dirstring)
  dstring = dirstring(1:ld)
  ! add directory separator if needed
  call gag_separ(insep,ousep,cdir)
  !
  ! If a directory is specified,check that it exists
  if (ld.gt.0) then
    if (gag_isdir(dstring(1:ld)).ne.0) then
      call gsys_message(seve%w,rname,'No such directory '//dstring(1:ld))
      return
    else if(dstring(ld:ld).ne.cdir) then
      ld = ld+1
      dstring(ld:ld)=cdir
    endif
  endif
  !
  tmp = 'files.dat'
  call sic_parsef(tmp,tmpname,'GAG_SCRATCH:','.dat')
#if defined(WIN32)
  tmpstring = filestring
  nbrack =  index(tmpstring,'[')
  if (nbrack.ne.0) then
    nclose = index(tmpstring,']')
    addstring = tmpstring(nbrack+1:nclose-1)
    !
    ! Supported syntax is ONLY [a-b], no more
    if (len_trim(addstring).ne.3.or.addstring(2:2).ne.'-' &
      & .or.ichar(addstring(1:1)).gt.ichar(addstring(3:3))) then
      call gsys_message(seve%e,rname,'Invalid syntax '//tmpstring(nbrack:nclose))
      nfile = -1
    else
      tmpstring(nbrack:) = addstring(1:1)//filestring(nclose+1:)
      if (ld.eq.0) then
        com = 'dir /B /O:N '//trim(tmpstring)//' > '//tmpname
      else
        com = 'dir /B /O:N '//trim(dstring)//trim(tmpstring)//' > '//tmpname
      endif
      ier = gag_system(com)
      do i = ichar(addstring(1:1))+1, ichar(addstring(3:3))
        tmpstring(nbrack:) = char(i)//filestring(nclose+1:)
        if (ld.eq.0) then
          com = 'dir /B /O:N '//trim(tmpstring)//' >> '//tmpname
        else
          com = 'dir /B /O:N '//trim(dstring)//trim(tmpstring)//' >> '//tmpname
        endif
        ier = gag_system(com)
      enddo
    endif
  else
    if (ld.eq.0) then
      com = 'dir /B /O:N '//trim(filestring)//' > '//tmpname
    else
      com = 'dir /B /O:N '//trim(dstring)//trim(filestring)//' > '//tmpname
    endif
    ier = gag_system(com)
  endif
  !
  ! Check if any wildcard beyond the extension separator
  nt = len_trim(filestring)
  idot = 0
  do i= nt,1,-1
    if (filestring(i:i).eq.'*') then
      exit
    else if (filestring(i:i).eq.'.') then
      extension = filestring(i:nt)
      idot = nt-i+1
    endif
  enddo
#else
  if (len_trim(filestring).eq.0) then
    ! Empty file pattern: list everything, but avoid "-d" which lists "."
    ! (current directory) if current directory is empty.
    if (ld.eq.0) then
      com = ' 2>/dev/null ls -t1  > '//tmpname
    else
      com = ' 2>/dev/null cd '//trim(dstring)//'; 2>/dev/null ls -t1 '//  &
      trim(filestring)//' > '//tmpname
    endif
  else
    if (ld.eq.0) then
      com = ' 2>/dev/null ls -t1 -d '//trim(filestring)//' > '//tmpname
    else
      com = ' 2>/dev/null cd '//trim(dstring)//'; 2>/dev/null ls -t1 -d '//  &
      trim(filestring)//' > '//tmpname
    endif
  endif
  ier = gag_system(com)
#endif
  ! Can not trap this error: 'ls' raises an error if 0 files are found...
  ! if (ier.ne.0) then
  !   call gsys_message(seve%e,rname,'Could not list directory')
  !   error = .true.
  !   return
  ! endif
  !
  ! Number of files found?
  call gag_fillines(tmpname,.false.,nfile,error)
  if (error)  return
  doalloc = .false.
  if (allocated(filename)) then
    if (size(filename).ne.nfile) then
      deallocate(filename)
      doalloc = .true.
    endif
  else
    doalloc = .true.
  endif
  if (doalloc) then
    allocate(filename(nfile),stat=ier)
    if (failed_allocate('SIC','file list',ier,error))  return
  endif
  !
  ier = sic_getlun(lun)
  if (ier.ne.1) then
    call gag_filrm(tmpname)
    return
  endif
  ier = sic_open (lun,tmpname,'OLD',.true.)
  if (ier.ne.0) then
    call gsys_message(seve%e,rname,'Cannot open '//tmpname)
    call putios('E-'//trim(rname)//', ',ier)
    call gag_filrm(tmpname)
    nfile = -1
    return
  endif
  !
  nfile = 0
  do
    read(lun,'(a)',end=100) com
    tmp = com
    ic = lenc(tmp)
#if defined(WIN32)
    !
    ! Special case for Windows because of the UGLY BUG of 8.3 short names
    !  Windows will consider short names in the search process. The
    !  problem is that the extension is purely truncated to 3 characters
    !  in such a search, so a search of  toto*.lmv would also return the
    !  toto*.lmv-clean files for example. The result is just next to be
    !  unpredictable when you have a mixture of files with and without
    !  short names, which can happen because the creation of 8.3 names
    !  is a dynamical attribute of the file system, but not their use !...
    !  Without this patch, on a directory containing (among other things)
    !     date.f90    date.f90-1
    !    sic find date.f90   would return only date.f90
    !  but
    !    sic find *.f90     would return both files.
    !  Exercice: try to figure out why given the above rules...
    !  Hints: there several possible solutions
    if (idot.ne.0) then
      if (tmp(ic-idot+1:ic).ne.extension(1:idot)) ic = 0
    endif
    !
#endif
    if (ic.ne.0) then
      nfile = nfile+1
      filename(nfile) = tmp(1:ic)
    endif
  enddo
100 close(lun)
  call gag_filrm(tmpname)
  call sic_frelun(lun)
end subroutine gag_directory
!
subroutine sic_username(name)
  use gsys_interfaces, except_this=>sic_username
  !---------------------------------------------------------------------
  ! @ 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
  !
  name = ' '
  call sic_getenv('USER',name)                       ! $USER
  if (name.eq.' ') call sic_getenv('LOGNAME',name)   ! $LOGNAME
  if (name.eq.' ') name = 'Gildas'                   ! Default...
end subroutine sic_username
!
subroutine sic_hostname(node)
  use gsys_interfaces, except_this=>sic_hostname
  !---------------------------------------------------------------------
  ! @ 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
  !
  node = ' '
  call sic_getenv('HOST',node)                       ! $HOST
  if (node.eq.' ') call sic_getenv('HOSTNAME',node)  ! $HOSTNAME
#if defined(GAG_USE_UNDERSCORE)
  ! Disabled if no underscore as ifort can not find its own subroutine
  ! in this case...
  if (node.eq.' ') call hostnm(node)
#endif
end subroutine sic_hostname
!
subroutine sic_setdir(direc,nc,error)
  use gsys_interfaces, except_this=>sic_setdir
  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
  ! Local
  character(len=filename_length) :: diro
  integer(kind=4) :: ier
  character(len=1), parameter :: backslash=char(92)
  !
  ! Get input name (if any)
  if (nc.gt.0) then
    call sic_parse_file(direc(1:nc),'','',diro)
    nc = len_trim(diro)
    if (diro(nc:nc).eq.'/' .or. diro(nc:nc).eq.backslash) nc = nc-1
    !
    ! Check if directory exists
    if (gag_inquire(diro,nc).ne.0) then
      call gsys_message(seve%e,'SETDIR','No such directory '//diro)
      diro = ''
      error = .true.
      ! Do not return, we still have to return the current working directory.
    endif
  else
    diro = ''
  endif
  !
  ! Set a new directory if non-null, and get current working directory
  ier = set_dir(diro)
  !
  if (ier.ne.0) then
    ! Error when changing it
    error = .true.
    call putmsg('E-SETDIR,  ',ier)
    !
    ! Get cwd anyhow
    diro = ''
    ier = set_dir(diro)
  endif
  !
  ! Return cwd
  direc = diro
  nc = len_trim(diro)
end subroutine sic_setdir
!
subroutine gag_cpu(arg)
  !---------------------------------------------------------------------
  ! @ public
  ! All compilers are assumed to be Fortran 1995 compatible now
  !---------------------------------------------------------------------
  real(kind=4), intent(out) :: arg  !
  call cpu_time(arg)
end subroutine gag_cpu
!
subroutine gag_delete(fich)
  use gildas_def
  use gbl_message
  use gsys_interfaces, except_this=>gag_delete
  !---------------------------------------------------------------------
  ! @ public
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: fich  !
  ! Local
  integer(kind=4) :: ier
  character(len=filename_length) :: chain
  !
#if defined(WIN32)
  chain = 'DEL '//fich
#else
  chain = 'rm -f '//fich
#endif
  ier = gag_system(chain)
  if (ier.ne.0)  &
    call gsys_message(seve%e,'DELETE','Could not delete file '//fich)
end subroutine gag_delete
!
function gag_which(name,dirlist,full)
  use gildas_def
  use gsys_interfaces, except_this=>gag_which
  !---------------------------------------------------------------------
  ! @ 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
  ! Local
  character(len=path_length) :: path,path2
  character(len=1) :: insep,ousep,disep
  integer(kind=4) :: i,j,pl,pl2
  logical :: error
  !
  call gag_separ(insep,ousep,disep)
  !
  full = name
  gag_which = .false.
  error = .false.
  !
  ! Name may already have an absolute path
#ifdef WIN32
  if (name(2:3).eq.':\') then
#else
  if (name(1:1).eq.disep) then
#endif
    gag_which = (gag_inquire (full,lenc(full)).eq.0)
    return
  !
  ! Name may have a relative path
  elseif (index(name,disep).gt.1 .or. dirlist.eq.'') then
    path = ' '
    pl = 0
    call sic_setdir(path,pl,error)
    if (error) return
    full = path(1:pl)//disep//name
    gag_which = (gag_inquire (full,lenc(full)).eq.0)
    return
  !
  ! Else, scan through the input directory list / environment variable
  else
    call sic_resolve_env(dirlist,path)
#ifndef WIN32
    ! Replace ":" ";", recognized by SIC_QUERY_FILE as separator
    i = index(path,':')
    do while (i.ne.0)
      path(i:i) = ';'
      i = index(path,':')
    enddo
#endif
    ! Add a directory separator at the end of each directory
    ! (this is needed by SIC_QUERY_FILE)
    pl = lenc(path)
    path2 = ''
    pl2 = 0
    j = 1
    do i=1,pl
      if (path(i:i).eq.';') then
        path2 = path2(:pl2)//path(j:i-1)//disep
        pl2 = lenc(path2)
        j = i
      endif
    enddo
    path2 = path2(:pl2)//path(j:pl)//disep
    !
    gag_which = sic_query_file(name,path2,'',full)
    !
  endif
end function gag_which
!
function gag_mtime(file,nanosec)
  use gsys_interfaces, except_this=>gag_mtime
  !---------------------------------------------------------------------
  ! @ 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.
  !---------------------------------------------------------------------
  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  !
  ! Local
  integer(kind=8), parameter :: sec2nano=1000000000_8
  integer(kind=4) :: sec,nsec
  !
  gag_mtime = gag_mtime_c(file,sec,nsec)
  if (gag_mtime.ne.0) then
    nanosec = 0
    return
  endif
  !
  nanosec = sec2nano*sec+nsec
  !
end function gag_mtime
!
function gag_time(nanosec)
  use gsys_interfaces, except_this=>gag_time
  !---------------------------------------------------------------------
  ! @ public
  ! Return the current time in nanoseconds since 01-jan-1970
  !---------------------------------------------------------------------
  integer(kind=4) :: gag_time  ! Function value on return (0 for success)
  integer(kind=8), intent(out) :: nanosec  !
  ! Local
  integer(kind=8), parameter :: sec2nano=1000000000_8
  integer(kind=4) :: sec,nsec
  !
  gag_time = gag_time_c(sec,nsec)
  if (gag_time.ne.0) then
    nanosec = 0
    return
  endif
  !
  nanosec = sec2nano*sec+nsec
  !
end function gag_time
!
subroutine gag_filmodif(file,modif,error)
  use gbl_message
  use gsys_types
  use gsys_interfaces, except_this=>gag_filmodif
  !---------------------------------------------------------------------
  ! @ 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
  ! Local
  character(len=*), parameter :: rname='TIME'
  integer(kind=8), parameter :: granularity=1000000000_8  ! File system granularity (ns)
  integer(kind=4) :: ier
  integer(kind=8) :: time
  !
  if (file.ne.modif%file) then
    ! Not the same file, e.g. at first call
    modif%file = file
    ier = gag_mtime(file,modif%mtime)
    if (ier.ne.0)  goto 101
    ier = gag_time(modif%ptime)
    if (ier.ne.0)  goto 102
    ! modif%modif = unchanged, let caller decide e.g. at first call
    return
  endif
  !
  ! Same file name, has it been modified?
  ier = gag_mtime(file,time)
  if (ier.ne.0)  goto 101
  if (time.ne.modif%mtime) then
    ! File has been modified (in the past or in the the future, this may
    ! happen on NFS file systems)
    ! Note: use .NE. instead of .LT., so that change of directories
    ! with same filename may be handled to first order
    modif%mtime = time
    ier = gag_time(modif%ptime)
    if (ier.ne.0)  goto 102
    modif%modif = .true.
    return
  endif
  !
  ! Same modification time. Modified? May be, may be not... Compare last
  ! read time
  ier = gag_time(time)
  if (ier.ne.0)  goto 102
  if (time-modif%ptime.lt.0) then
    ! Last call was in the past? Should never happen
    call gsys_message(seve%e,rname,  &
      'Internal error: last evaluation in the future!')
    error = .true.
    return
  elseif (time-modif%ptime.le.granularity) then
    ! If there was a modification, this is below the file system
    ! granularity. Ambiguous, change nothing, let the caller decide
    continue
  else
    ! Much more time has elapsed, for sure file has not changed
    modif%modif = .false.
  endif
  ! Do NOT update the proved 'ptime'! Else if called at high rate, the test
  ! above will be perpetually ambiguous.
  return
  !
101 continue  ! Error 1
  call gsys_message(seve%e,rname,  &
    'Error getting modification time for file '//file)
  error = .true.
  return
102 continue  ! Error 2
  call gsys_message(seve%e,rname,'Error getting current time')
  error = .true.
  return
end subroutine gag_filmodif
!
subroutine gag_fillines(file,doblank,nlines,error)
  use gbl_message
  use gsys_interfaces, except_this=>gag_fillines
  !---------------------------------------------------------------------
  ! @ 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    !
  ! Local
  character(len=*), parameter :: rname='LINES'
  integer(kind=4) :: ier,lun,nl
  character(len=8196) :: local_line
  !
  nlines = 0
  !
  ! Open file
  ier = sic_getlun(lun)
  if (mod(ier,2).eq.0) then
    error = .true.
    return
  endif
  ier = sic_open(lun,file,'OLD',.true.)
  if (ier.ne.0) then
    call gsys_message(seve%e,rname,'Error opening '//file)
    call putios('E-ACCEPT,  ',ier)
    error = .true.
    goto 10
  endif
  !
  ! Read file
  if (doblank)  then
    ! Ignore blank and comment lines
    do
      read(lun,'(A)',iostat=ier)  local_line
      if (ier.ne.0) exit  ! <0: EOF, >0: Error
      ! Same as ACCEPT:
      if (local_line(1:1).eq.'!')  cycle  ! Ignore comments
      nl = len_trim(local_line)
      call sic_blanc(local_line,nl)  ! Suppress everything after a '!'
      if (nl.eq.0)  cycle            ! Ignore empty lines after SIC_BLANC
      nlines = nlines+1
    enddo
    !
  else
    ! Count everything
    do
      read(lun,'(A)',iostat=ier)
      if (ier.ne.0) exit  ! <0: EOF, >0: Error
      nlines = nlines+1
    enddo
  endif
  !
  if (ier.gt.0) then  ! Error
    call gsys_message(seve%e,rname,'Error counting lines')
    call putios('E-LINES,  ',ier)
    error = .true.
    return
  endif
  !
10 continue
  ! Close file
  ier = sic_close(lun)
  call sic_frelun(lun)
  !
end subroutine gag_fillines
!
function gag_filsame(file1,file2)
  use gsys_interfaces, except_this=>gag_filsame
  !---------------------------------------------------------------------
  ! @ 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
  gag_filsame = gag_filsame_c(file1,file2).eq.1
end function gag_filsame
