subroutine sic_delvariable (var,user,error)
  use gildas_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_delvariable
  use sic_structures
  use sic_dictionaries
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public-mandatory (as calls with named arguments are used)
  !   Delete Variable VAR (any kind)
  !   If variable does not exist and request comes from user, an error
  ! is raised. If variable does not exist and request comes from
  ! program, no error is raised.
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: var    ! Name of variable
  logical,          intent(in) :: user   ! User (TRUE) or Program request
  logical                      :: error  ! Return error code               Output
  ! Local
  character(len=*), parameter :: rname='DELETE'
  type(sic_identifier_t) :: varfound
  integer :: in,ier
  integer(kind=4) :: status
  logical :: local,luser,found
  character(len=message_length) :: mess
  !
  ! Locate the variable at current level
  varfound%name = var
  call sic_upper(varfound%name)
  varfound%lname = len_trim(var)
  varfound%level = var_level
  ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,varfound,in)
  if (ier.ne.1) then
    ! Local variable not found: check for a global one if possible
    if (var_level.eq.0) then
      ! We are already at global level
      found = .false.
    else
      varfound%level = 0
      ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,varfound,in)
      found = ier.eq.1
      local = .false.       ! Found a Global variable
    endif
  else
    found = .true.
    local = var_level.ne.0  ! Found a Local variable if level non zero
  endif
  if (.not.found) then
    if (user) then
      error = .true.
      call sic_message(seve%e,rname,'No such variable '//var)
    endif
    return
  endif
  !
  ! Delete variable according to its Status
  ! First delete the possible associated python SicVar instance
#if defined(GAG_USE_PYTHON)
  call gpy_delvar(varfound%name,varfound%level)
#endif
  !
  ! Second free the associated memory (or variables if it is a structure) after
  ! flushing to disk if needed
  luser = user
  status = dicvar(in)%desc%status
  !
  if (status.eq.alias_defined) then  ! It is an alias, just delete it from the list
    call zap_alias(in)
    luser = .true.  ! Aliases always considered as user-defined (see symetric
                    ! comment in sic_def_alias)
    !
  elseif (status.eq.user_defined) then ! Interactively defined by user
    call del_alias(in,local)  ! Delete its aliases
    if (dicvar(in)%desc%type.eq.0) then    ! User-def structure...
      call sic_delstructure(varfound,user,error)
      if (error)  call sic_message(seve%f,rname,'Error deleting structure '//  &
      var)
    else
      call free_vm(dicvar(in)%desc%size,dicvar(in)%desc%addr)
    endif
    !
  elseif (status.gt.0) then   ! Image variable mapped on a GIO slot, unmap
    call del_alias(in,local)  ! Delete the aliases
    call sic_delstructure(varfound,user,error)
    if (.not.dicvar(in)%desc%readonly) then    ! A writeable image/header
      ! Warn if Nvisi is lower than visibility axis
      if (gdf_check_nvisi(status,mess).lt.0)  call sic_message(seve%w,rname,mess)
      call gdf_flih (status,.false.,error)
    endif
    call gio_fris (status,error)
    !
  elseif (status.eq.program_defined) then
    if (user) then
      call sic_message(seve%e,rname,'Program defined variable '//trim(var)//' is protected')
      error = .true.
      return
    endif
    if (associated(dicvar(in)%desc%head)) then
      ! Variable provides a header and it is not mapped on a GIO slot
      call sic_delstructure(varfound,user,error)
      error = .false.               ! Make sure in this case no error
    endif
    if (dicvar(in)%desc%type.eq.0) then    ! Program-def structure...
      call sic_delstructure(varfound,user,error)
      if (error)  call sic_message(seve%f,rname,'Error deleting structure '//  &
      var)
    endif
    !
  elseif (status.eq.scratch_operand  .or.  &  ! Should not happen...
          status.eq.free_operand     .or.  &
          status.eq.readonly_operand .or.  &
          status.eq.interm_operand   .or.  &
          status.eq.empty_operand) then      ! Not an image variable
    call sic_message(seve%e,rname,'Unexpected variable status on delete')
    write(mess,*) status,in,var
    call sic_message(seve%e,rname,mess)
    error = .true.
    return
    !
  else                         ! Code not in list...
    call sic_message(seve%e,rname,'Unknown variable status code on delete')
    write(mess,*) status,in
    call sic_message(seve%e,rname,mess)
    error = .true.
    return
  endif
  !
  ! Now delete the variable from the list
  call sic_zapvariable(in,luser,local,error)
  if (error) return
  !
end subroutine sic_delvariable
!
subroutine sic_zapvariable(in,user,local,error)
  use sic_interfaces, except_this=>sic_zapvariable
  use sic_structures
  use sic_dictionaries
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !  Delete Variable number IN from variable list
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: in     ! Variable number
  logical,         intent(in)    :: user   ! Is variable User defined?
  logical,         intent(in)    :: local  ! Is variable Local or Global
  logical,         intent(inout) :: error  ! Logical error flag
  ! Local
  integer(kind=4) :: ier,i,ivar,ntot
  !
  dicvar(in)%desc%status = empty_operand
  ier = sic_hasdel(maxvar,pfvar,pnvar,dicvar,dicvar(in)%id)
  if (ier.ne.1) then
    call sic_message(seve%e,'VARIABLE','No such variable '//trim(dicvar(in)%id%name))
    error = .true.
    return
  endif
  if (.not.user) return
  !
  ! Locate the back pointer
  if (local) then
    do i=1,var_n
      if (var_pointer(i).eq.in) then
        ivar = i
        goto 80
      endif
    enddo
  else
    do i=var_g,maxvar
      if (var_pointer(i).eq.in) then
        ivar = i
        goto 80
      endif
    enddo
  endif
  call sic_message(seve%e,'VARIABLE','Internal error, no back pointer')
  error =.true.
  return
  !
  ! Decrement the back pointers from this one
80 continue
  if (local) then
    ntot = ivar+1
    do i=ntot,var_n
      var_pointer(i-1) = var_pointer(i)
    enddo
    var_pointer(var_n) = 0
    var_n = var_n-1
  else
    ntot = ivar-1
    do i=ntot,var_g,-1
      var_pointer(i+1) = var_pointer(i)
    enddo
    var_pointer(var_g) = 0
    var_g = var_g+1
  endif
end subroutine sic_zapvariable
!
subroutine sic_delstructure(structvar,user,error)
  use gildas_def
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_delstructure
  use sic_structures
  use sic_dictionaries
  use sic_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Delete a Structure and all its members. It assumes the variable is a
  ! structure, not a header.
  ! This routine is called when input variable is already checked as a TRUE
  ! structure.
  !---------------------------------------------------------------------
  type(sic_identifier_t), intent(in)    :: structvar  ! Structure name to delete
  logical,                intent(in)    :: user       ! User or Program request
  logical,                intent(inout) :: error      ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='DELETE'
  integer(kind=4) :: nvar,nn,ivar,list(maxvar),ik,status
  character(len=varname_length) :: sname,varname
  integer :: structlev,varlev
  logical :: local,luser
  character(len=message_length) :: mess
  !
  ! Determine the variable level
  structlev = structvar%level  ! NOT the current level VAR_LEVEL, since it
  local = structlev.ne.0       ! may be asked to delete a Global structure
  !
  ! Build the prefix of all the structure members
  sname = structvar%name         ! Say, MYOLD
  nn = len_trim(sname)
  if (sname(nn:nn).ne.'%') then
    nn = nn+1
    sname(nn:nn) = '%'           ! MYOLD%
  endif
  !
  ! Delete everything left under MYOLD%
  call gag_haslis(maxvar,pfvar,pnvar,list,nvar)
  do ivar=1,nvar
    ik = list(ivar)
    !
    ! Jump to next variable if name is not correct
    varname=dicvar(ik)%id%name
    if (index(varname,sname(:nn)).ne.1)  cycle  ! ivar
    !
    ! Jump to next variable if level is not correct
    varlev=dicvar(ik)%id%level
    if (varlev.ne.structlev)  cycle  ! ivar
    !
    ! Skip the current structure itself, it will be zapped by the calling routine
    if (varname.eq.sname)  cycle  ! ivar
    !
    ! Ok, found an attribute, delete it
    !
    ! Cannot use the simple SIC_HASDEL
    !   IER=SIC_HASDEL(MAXVAR,PFVAR,PNVAR,DICVAR,FOUND)
    ! because it does not reset VAR_N properly...
    !
    ! Instead, one should use SIC_ZAPVARIABLE, but
    !   - take care of not deleting space of program defined variable  S.Guilloteau
    !   - deleting space of the other                                  G.Duvert
    !   - only if it has not been deleted before                       S.Guilloteau
    !   - and only if that variable is not a Structure itself          S.Guilloteau
    !
    status = dicvar(ik)%desc%status
    luser = user .and. status.ne.program_defined
    ! This part mostly duplicated from sic_delvariable!
    if (status.eq.alias_defined) then  ! It is an alias, just delete it from the list
      call zap_alias(ik)
      luser = .true.  ! Aliases always considered as user-defined (see symetric
                      ! comment in sic_def_alias)
      !
    elseif (luser) then          ! Interactively defined by user
      if (status.eq.empty_operand) then
        ! Has already been deleted (should not happen?)
        continue
        !
      elseif (status.eq.user_defined) then
        ! Interactively defined by user
        call del_alias(ik,local)  ! Delete its aliases
        if (dicvar(ik)%desc%type.ne.0) then  ! Not a structure
          ! print *,'Zapping ',ik,dicvar(ik)%desc%status,program_defined,  &
          !  dicvar(ik)%desc%type,dicvar(ik)%desc%size,dicvar(ik)%desc%addr
          call free_vm(dicvar(ik)%desc%size,dicvar(ik)%desc%addr)
        endif
        !
      elseif (status.gt.0) then
        ! Image variable, unmap
        call del_alias(ik,local)      ! Delete the aliases
        if (.not.dicvar(ik)%desc%readonly) then ! A writeable image/header
          ! Warn if Nvisi is lower than visibility axis
          if (gdf_check_nvisi(status,mess).lt.0)  call sic_message(seve%w,rname,mess)
          call gdf_flih (status,.false.,error)
        endif
        call gio_fris (status,error)
        !
      endif
    endif
    !
    ! Now delete the variable from the list
    call sic_zapvariable(ik,luser,local,error)
    if (error) then
      call sic_message(seve%e,rname,'Error ZAP in sic_delstructure for '//varname)
    endif
    !
  enddo
  !
end subroutine sic_delstructure
!
subroutine erase_variables
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>erase_variables
  use sic_structures
  use sic_dictionaries
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !       Delete and reset to zero all local variables at level
  !       VAR_LEVEL, and decrement VAR_LEVEL
  !---------------------------------------------------------------------
  ! Local
  character(len=*), parameter :: rname='VARIABLE'
  integer(kind=4) :: i,in,ier,status
  logical :: error,user
  character(len=message_length) :: mess
  !
  !!Print *,'Start makeERASE_VARIABLES'
  user = .true.
  error = .false.
  !
  ! Loop BACKWARDS to delete structure items BEFORE the structure,
  ! and also to delete aliases BEFORE their pointees.
  do i=var_n,var_macro(var_level)+1,-1
    in = var_pointer (i)
    if (in.ne.0) status = dicvar(in)%desc%status
    !!Print *,'Treating ',in,status,dicvar(in)%id%name, alias_defined
    !
    if (in.eq.0) then
      ! This could happen if a STRUCTURE was deleted before its components
      call sic_message(seve%e,rname,'Lost variable in ERASE_VARIABLES')
      !
    elseif (status.eq.alias_defined) then
      !!Print *,'Found an ALIAS_DEFINED at ',in
      call zap_alias(in)    ! In this case, calls to del_alias become useless
      ! or
      ! cycle               ! Aliases will be deleted when deleting the pointee
      !                       by the calls to del_alias
    elseif (status.eq.user_defined) then  ! Interactively defined by user
      ! call del_alias(in,.true.)  ! Delete the aliases. No need! Because
      !   we are rewinding the events, all aliases should have been
      !   deleted before the pointees.
      if (dicvar(in)%desc%type.eq.0) then  ! User-def structure...
        call sic_delstructure(dicvar(in)%id,user,error)
        if (error)  call sic_message(seve%f,rname,'Error deleting '//  &
                    'structure '//dicvar(in)%id%name)
      else
        call free_vm (dicvar(in)%desc%size,dicvar(in)%desc%addr)
      endif
      !
    elseif (status.gt.0) then  ! Image or Header variable mapped on a GIO slot, unmap
      ! call del_alias(in,.true.)  ! Delete the aliases. No need! Because
      !   we are rewinding the events, all aliases should have been
      !   deleted before the pointees.
      call sic_delstructure(dicvar(in)%id,user,error)
      if (.not.dicvar(in)%desc%readonly) then
        ! Warn if Nvisi is lower than visibility axis
        if (gdf_check_nvisi(dicvar(in)%desc%status,mess).lt.0)  call sic_message(seve%w,rname,mess)
       call gdf_flih (dicvar(in)%desc%status,.false.,error)
      endif
      call gio_fris (dicvar(in)%desc%status,error)
      !
    elseif (status.eq.program_defined) then
      call sic_message(seve%e,rname,'Program defined variables are global')
      write(mess,*) status,dicvar(in)%id%name,in
      call sic_message(seve%e,rname,mess)
      error = .true.
    elseif (status.eq.empty_operand) then
      continue
    elseif (status.eq.scratch_operand  .or.  &  ! Should not happen...
            status.eq.free_operand     .or.  &
            status.eq.readonly_operand .or.  &
            status.eq.interm_operand) then
      call sic_message(seve%e,rname,'Unexpected variable status on delete')
      write(mess,*) status,dicvar(in)%id%name,in
      call sic_message(seve%e,rname,mess)
      error = .true.
    else                       ! Code not in list...
      call sic_message(seve%e,rname,'Unknown variable status code '//  &
      'on return')
      write(mess,*) status
      call sic_message(seve%e,rname,mess)
      error = .true.
    endif
    dicvar(in)%desc%status = empty_operand
#if defined(GAG_USE_PYTHON)
    call gpy_delvar(dicvar(in)%id%name,dicvar(in)%id%level)
#endif
    ier = sic_hasdel(maxvar,pfvar,pnvar,dicvar,dicvar(in)%id)
  enddo
  var_n = var_macro(var_level)
  var_level = var_level-1
  !!Print *,'Finished ERASE_VARIABLES'
end subroutine erase_variables
!
subroutine del_ima_var
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>del_ima_var
  use sic_structures
  use sic_dictionaries
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !       Delete all image variables. This is called upon Program exit to
  !       ensure updating (when the mapping mechanism cannot be used).
  !---------------------------------------------------------------------
  ! Local
  character(len=*), parameter :: rname='VARIABLE'
  integer :: i,in,status
  logical :: error,user
  character(len=message_length) :: mess
  !
  user = .false.               ! This is a Program Request !
  !
  ! Go FORWARD to delete structure items before the structure header
  do i=var_g,maxvar
    error = .false.    ! Reset error
    in = var_pointer (i)
    status = dicvar(in)%desc%status
    !!Print *,'DEL_IMA_VAR ',in, status, TRIM(DICVAR(IN)%id%name),DICVAR(IN)%id%LEVEL
    if (status.eq.user_defined) then   ! Interactively defined by user
      if (dicvar(in)%desc%type.eq.0) then  ! User-def structure...
        call sic_delstructure(dicvar(in)%id,user,error)
        if (error)  call sic_message(seve%f,rname,'Error deleting '//  &
                    'structure '//dicvar(in)%id%name)
      else
        call free_vm (dicvar(in)%desc%size,dicvar(in)%desc%addr)
      endif
    elseif (status.gt.0) then  ! Image variable, unmap
      call sic_delstructure(dicvar(in)%id,user,error)
      if (.not.dicvar(in)%desc%readonly) then      ! Means it is not readonly: Flush header
        ! Warn if Nvisi is lower than visibility axis
        if (gdf_check_nvisi(dicvar(in)%desc%status,mess).lt.0)  call sic_message(seve%w,rname,mess)
        call gdf_flih (dicvar(in)%desc%status,.false.,error)
      endif
      call gio_fris (dicvar(in)%desc%status,error)  ! Free image slot and do all writing if needed...
      if (error)  call sic_message(seve%f,rname,'Error deleting '//  &
                  'image '//dicvar(in)%id%name)
    elseif (status.eq.program_defined) then
      !call sic_message(seve%w,rname,'Program defined variable '//  &
      !  trim(dicvar(in)%id%name)//' is global')
      !error = .true.
      continue
    elseif (status.eq.empty_operand .or. status.eq.alias_defined) then
      continue
    elseif (status.eq.scratch_operand  .or.  &  ! Should not happen...
            status.eq.free_operand     .or.  &
            status.eq.readonly_operand .or.  &
            status.eq.empty_operand) then
      call sic_message(seve%e,rname,'Unexpected variable status on delete')
      write(mess,*) status,in,trim(dicvar(in)%id%name),' at level ',dicvar(in)%id%level
      call sic_message(seve%e,rname,mess)
      error = .true.
    else                       ! Code not in list...
      call sic_message(seve%e,rname,'Unknown variable status code on exit')
      write(mess,*) status
      call sic_message(seve%e,rname,mess)
      error = .true.
    endif
    dicvar(in)%desc%status = empty_operand
  enddo
end subroutine del_ima_var
!
subroutine sic_free_variable
  use sic_interfaces, except_this=>sic_free_variable
  use sic_dictionaries
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Release the variable structure list at exit time
  !---------------------------------------------------------------------
  character(len=*), parameter :: rname='FREE_VARIABLE'
  integer :: ier
  !
  ! Deallocate variable arrays
  deallocate(dicvar,pnvar,var_pointer,alias,dicali,pointee,stat=ier)
  if (ier.ne.0) then
     call sic_message(seve%e,rname,'Dictionary deallocation error')
  endif
  !
end subroutine sic_free_variable
