!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Specific Fortran routines and module used for Python binding support.
! These routines are not Python-specific and could be made public (and
! moved) at some point.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!  Always compile this file, with or without Python. This ensures that
! the interface files are the same in both configuration. We had
! problem with the previous scheme (this file was not compiled if
! Python was disabled) when compiling the same sources for different
! configurations.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine gmaster_set_ismaster(ismaster)
  use sic_python
  !---------------------------------------------------------------------
  ! @ private
  ! Python binding private routine.
  ! Set the Gildas programs master status
  !---------------------------------------------------------------------
  logical, intent(in) :: ismaster  !
  !
  gildas_ismaster = ismaster
  !
end subroutine gmaster_set_ismaster
!
function gmaster_get_ismaster()
  use sic_python
  !---------------------------------------------------------------------
  ! @ private
  ! Python binding private routine.
  ! Get the Gildas programs master status
  !---------------------------------------------------------------------
  integer :: gmaster_get_ismaster  ! Function value on return
  !
  if (gildas_ismaster) then
    gmaster_get_ismaster = 1
  else
    gmaster_get_ismaster = 0
  endif
  !
end function gmaster_get_ismaster
!
#if defined(GAG_USE_PYTHON)
!
subroutine gmaster_build_sic(flag)
  use sic_interfaces, except_this=>gmaster_build_sic
  !---------------------------------------------------------------------
  ! @private
  ! Python binding private routine.
  ! Initialize Gildas with SIC as slave
  !---------------------------------------------------------------------
  integer :: flag           ! Error flag
  ! Local
  logical :: error
  !
  flag = 0
  error = .false.
  !
  call sense_inter_state  ! Define some usefull globals
  call gmaster_set_hide_gui
  call gmaster_set_hide_welcome
  call gmaster_build(sic_pack_set,error)
  !
  if (error) flag = 1
  !
end subroutine gmaster_build_sic
!
function sic_verify()
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  ! Return the SIC%VERIFY status
  !---------------------------------------------------------------------
  logical :: sic_verify  ! Function value on return
  !
  sic_verify = lverif
  !
end function sic_verify
!
function sic_varlevel()
  use sic_dictionaries
  !---------------------------------------------------------------------
  ! @ public (for Python port)
  ! Retrieve current execution level
  !---------------------------------------------------------------------
  integer :: sic_varlevel  ! Function value on return
  !
  sic_varlevel = var_level
  !
end function sic_varlevel
!
function sic_dictsize()
  use sic_dictionaries
  !---------------------------------------------------------------------
  ! @ public (for Python port)
  ! Retrieve size of SIC hashing list (dictionary)
  !---------------------------------------------------------------------
  integer :: sic_dictsize  ! Function value on return
  !
  sic_dictsize = pfvar(27)
  !
end function sic_dictsize
!
subroutine sic_typecodes(fmt_r4_out,fmt_r8_out,fmt_i4_out,fmt_i8_out,  &
  fmt_l_out,fmt_by_out,fmt_c4_out)
  use gbl_format
  !---------------------------------------------------------------------
  ! @ public (for Python port)
  ! Retrieve SIC type codes
  !---------------------------------------------------------------------
  integer, intent(out) :: fmt_r4_out  !
  integer, intent(out) :: fmt_r8_out  !
  integer, intent(out) :: fmt_i4_out  !
  integer, intent(out) :: fmt_i8_out  !
  integer, intent(out) :: fmt_l_out   !
  integer, intent(out) :: fmt_by_out  !
  integer, intent(out) :: fmt_c4_out  !
  !
  fmt_r4_out = FMT_R4
  fmt_r8_out = FMT_R8
  fmt_i4_out = FMT_I4
  fmt_i8_out = FMT_I8
  fmt_l_out  = FMT_L
  fmt_by_out = FMT_BY
  fmt_c4_out = FMT_C4
  !
end subroutine sic_typecodes
!
subroutine sic_descptr(varname,level,address)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_descptr
  use gildas_def
  use sic_structures
  use sic_dictionaries
  use sic_types
  !---------------------------------------------------------------------
  ! @ public (for Python port)
  ! Gives back descriptor memory address, given the SIC name.
  ! It is called once or twice, but only at variable initialization.
  ! Return address = -1 means that variable was not found (can be an
  ! error or not depending on the caller).
  !---------------------------------------------------------------------
  character(len=*),             intent(in)  :: varname  !
  integer,                      intent(in)  :: level    !
  integer(kind=address_length), intent(out) :: address  !
  ! Local
  type(sic_identifier_t) :: var
  integer :: ier, in
  integer(kind=address_length) :: descr(6+sic_maxdims)
  save  descr  ! Because C code will reaccess its values later on
  !
  if (varname.eq.' ')  return
  !
  var%name = varname
  var%lname = len_trim(varname)
  var%level = level
  ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,var,in)
  if (ier.ne.1) then
     address = -1
     return
  endif
  !
  ! Fill my local descriptor. Unefficient?
  descr(1) = dicvar(in)%desc%type
  descr(2) = dicvar(in)%desc%addr
  descr(3) = dicvar(in)%desc%size
  descr(4) = dicvar(in)%desc%status
  if (dicvar(in)%desc%readonly) then
    descr(5) = 1
  else
    descr(5) = 0
  endif
  descr(6) = dicvar(in)%desc%ndim
  descr(7:6+sic_maxdims) = dicvar(in)%desc%dims(1:sic_maxdims)
  !
  ! And return the address of my local (but saved) descriptor
  address = locwrd(descr)
  !
end subroutine sic_descptr
!
subroutine sic_getname(varnum,varname,namelength,varlevel)
  use sic_dependencies_interfaces
  use gildas_def
  use sic_structures
  use sic_dictionaries
  !---------------------------------------------------------------------
  ! @ public (for Python port)
  ! Retrieve variable name from its number in dictionary
  !---------------------------------------------------------------------
  integer,                       intent(in)  :: varnum      !
  character(len=varname_length), intent(out) :: varname     !
  integer,                       intent(out) :: namelength  !
  integer,                       intent(out) :: varlevel    !
  ! Local
  integer :: list(maxvar),in,ik
  !
  call gag_haslis(maxvar,pfvar,pnvar,list,in)
  ik         = list(varnum)
  varname    = dicvar(ik)%id%name
  namelength = len_trim(varname)
  varlevel   = dicvar(ik)%id%level
  !
end subroutine sic_getname
!
subroutine sic_run_python(line,reentrant,error)
  use gildas_def
  use gbl_message
  use sic_interfaces, except_this=>sic_run_python
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  !  Support routine for command
  !   SIC\PYTHON
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line       ! Input command line
  logical,          intent(in)    :: reentrant  ! Allow (re)entrant call to Python prompt
  logical,          intent(inout) :: error      ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='PYTHON'
  integer(kind=4), parameter :: code_next=0  ! See module 'sic_interpreter'
  character(len=132) :: comarg
  integer(kind=4), parameter :: margs=20  ! Maximum number of arguments (Python command line)
  integer(kind=4) :: nc,largs(margs),nargs,iarg,ier
  character(len=filename_length) :: fich
  character(len=filename_length) :: args(margs)  ! Each arg is at most a file name (Python command line)
  logical :: found
  !
  if (sic_present(0,1)) then
    ! One or more arguments have been passed
    call sic_ch(line,0,1,comarg,nc,.true.,error)
    if (error)  return
    if (comarg(nc-2:nc).eq.'.py') then
      ! 1st argument ends with '.py'
      call find_procedure(comarg,fich,found)
      if (found) then
        ! Store filename and args in 'COMARG'
        call sic_ch(line,0,1,args(1),largs(1),.true.,error)
        nargs = min(margs,sic_narg(0))
        do iarg=2,nargs
          call sic_st(line,0,iarg,args(iarg),largs(iarg),.true.,error)
          if (error)  exit  ! Exit loop
        enddo
        call gpy_execfile(fich,len_trim(fich),args,largs,len(args(1)),nargs,ier)
        if (ier.ne.0) error = .true.
      else
        call sic_message(seve%e,rname,'No such file '//comarg(1:nc))
        error = .true.
        return
      endif
    else
      ! Arguments are a command
      comarg = line(ccomm%ibeg(2):ccomm%iend(ccomm%nword))
      nc = len_trim(comarg)
      call gpy_exec(comarg,nc,ier)
      if (ier.ne.0) error = .true.
    endif
    !
  elseif (reentrant) then
    ! No argument passed
    call gpy_interact()
    !
  else
    call sic_message(seve%e,'PYTHON',  &
      'Entering Python prompt is invalid in this context')
    error = .true.
    return
  endif
  !
end subroutine sic_run_python
#else
subroutine sic_run_python(line,reentrant,error)
  use gbl_message
  use sic_interfaces, except_this=>sic_run_python
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line       ! Input command line
  logical,          intent(in)    :: reentrant  ! Allow (re)entrant call to Python prompt
  logical,          intent(inout) :: error      ! Logical error flag
  ! Local
  integer(kind=4), parameter :: code_next=0  ! See module 'sic_interpreter'
  !
  call sic_message(seve%e,'PYTHON','SIC not compiled with Python binding')
  error = .true. ! Test 
!  error = .false.  ! Not sure why...
end subroutine sic_run_python
#endif
