subroutine sic_alias(line,rglobal,error)
  use gildas_def
  use sic_interfaces, except_this=>sic_alias
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !   DEFINE ALIAS AliasName Variable [/GLOBAL]
  !
  !   Create an alias, that is another name for the same variable.
  !---------------------------------------------------------------------
  character(len=*) , intent(in)    :: line     !
  logical,           intent(in)    :: rglobal  !
  logical,           intent(inout) :: error    !
  ! Local
  character(len=varname_length) :: name
  character(len=128) :: chain
  integer :: n
  !
  ! Get the alias
  call sic_ch(line,0,2,name,n,.true.,error)
  if (error)  return
  !
  ! Get the target
  call sic_ch(line,0,3,chain,n,.true.,error)
  if (error) return
  !
  call sic_def_alias(name,chain,rglobal,error)
  if (error)  return
  !
end subroutine sic_alias
!
subroutine sic_def_alias(aliasname,targetname,global,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_def_alias
  use gildas_def
  use sic_structures
  use sic_dictionaries
  use sic_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public
  !
  ! An "alias" is a variable pointing towards an existing one
  ! It need a code under -5, and different from -999, and under the
  ! ReadOnly offset. Let say -6, and call it ALIAS_DEFINED
  !
  ! We have a list of "alias" as a separate table
  ! For each entry, this list contains
  !     - the variable number
  !     - the pointed variable number
  !
  ! In deleting a variable, one checks
  !     - whether it is an alias (code = ALIAS_DEFINED).
  !         - then deleted it from the list aliases
  !         - delete the variable number and name, but don't free memory
  !     - or not
  !         - then check if it has aliases in the alias list.
  !         - Delete all aliases first
  !         - delete variable only after...
  !
  ! Structure canNOT have aliases
  !
  ! A problem concerns aliases of Header variables... They must be deleted
  ! at the same time than the others. This is handled by having the pointee
  ! number being the variable number of the header. To do so, when defining
  ! an alias, we have to figure out if the variable it
  ! points to is an header/image...
  !
  ! Alias can points towards sub-arrays
  !
  ! Alias have the same level as there pointees.
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: aliasname   ! Alias name
  character(len=*), intent(in)    :: targetname  ! Target name
  logical,          intent(in)    :: global      ! Is the target global?
  logical,          intent(inout) :: error       ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='DEFINE'
  type(sic_identifier_t) :: aliasvar,targetvar,headvar
  integer :: level,in,jn,kn,ier,n
  type(sic_descriptor_t) :: desc
  type(sic_dimensions_t) :: spec
  logical :: lglobal,verbose
  !
  ! Modify here to support sub-array
  ! Parse name from dimensions...
  spec%do%strict   = .true.   ! Can not be an expression like A[1].eq.B[1]
  spec%do%range    = .true.   ! e.g. A[3:5] supported
  spec%do%subset   = .false.  ! e.g. A[2,] not supported
  spec%do%implicit = .false.  ! e.g. A[i] not allowed
  spec%do%twospec  = .true.   ! e.g. A[i][j:k] allowed
  verbose  = .true.
  call sic_parse_dim(targetname,targetvar,spec,verbose,error)
  if (error) return
  !
  lglobal = global
  if (lglobal) then
    level = 0
  else
    level = var_level
  endif
  targetvar%level = level
  !
  ! Find the variable
  ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,targetvar,jn)
  !
  ! Also check whether a Global variables fit when the request is Local
  if (ier.ne.1 .and. .not.lglobal) then
    level = 0
    targetvar%level = level
    lglobal = .true.
    ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,targetvar,jn)
  endif
  if (ier.ne.1) then
    call sic_message(seve%e,rname,  &
      'Pointee Variable '//trim(targetvar%name)//' does not exist')
    error = .true.
    return
  endif
  if (dicvar(jn)%desc%status.eq.alias_defined) then
    ! Forbidden, at least as long as the destruction of the target will
    ! not be able to destroy its aliases and aliases of aliases.
    call sic_message(seve%e,rname,'An alias can not point to another alias')
    error = .true.
    return
  endif
  !
  ! Alias can be a structure member under limited conditions
  if (sic_checkstruct(aliasname,lglobal).eq.0) then
    error = .true.
    return
  endif
  !
  ! It must be valid name
  call sic_validname(aliasname,error)
  if (error) then
    call sic_message(seve%e,rname,'Invalid variable name '//aliasname)
    return
  endif
  !
  ! It must not be already existing. Aliases have same level as Pointees.
  aliasvar%name = aliasname
  aliasvar%lname = len_trim(aliasname)
  aliasvar%level = level
  ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,aliasvar,kn)
  if (ier.eq.1) then
    call sic_message(seve%e,rname,  &
      'Variable '//trim(aliasname)//' already exists')
    error = .true.
    return
  endif
  !
  ! Insert it
  ier = sic_hasins(rname,maxvar,pfvar,pnvar,dicvar,aliasvar,in)
  if (ier.eq.0 .or. ier.eq.2) then
    error = .true.
    return
  endif
  !
  ! Set the back pointer. Aliases are always considered as user-defined (even
  ! if defined from program) because they can point either on user or program
  ! defined variables, and thus can be local "variables".
  if (lglobal) then
    var_g = var_g-1
    var_pointer (var_g) = in
  else
    var_n = var_n+1
    var_pointer (var_n) = in
  endif
  !
  ! Fill the descriptor
  ! Do not allow incarnation or transposition here
  call extract_descr(desc,dicvar(jn)%desc,spec%done,targetvar%name,.false.,0,error)
  if (error) return
  dicvar(in)%desc = desc
  dicvar(in)%desc%status = alias_defined
  !
  ! Add to the list of aliases
  nalias = nalias+1
  alias(nalias) = in
  !
  ! Check if pointee is part of an header
  n = index(dicvar(jn)%id%name,'%')
  if (n.ne.0) then
    n = n-1
    headvar%name = dicvar(jn)%id%name(1:n)
    headvar%lname = n
    headvar%level = level   ! As the Alias
    kn = jn
    ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,headvar,kn)
    if (dicvar(kn)%desc%status.gt.0) then    ! This is a header OR image
      jn = kn
    endif
  endif
  pointee(nalias) = jn
  targetvar%name = targetname
  call sic_upper(targetvar%name)
  targetvar%lname = len_trim(targetname)
  dicali(nalias) = targetvar
  !
#if defined(GAG_USE_PYTHON)
  call gpy_getvar(aliasvar%name,aliasvar%level)
#endif
  !
end subroutine sic_def_alias
!
subroutine zap_alias (in)
  use sic_interfaces, except_this=>zap_alias
  use sic_structures
  use sic_dictionaries
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Delete an Alias from the list of aliases
  !---------------------------------------------------------------------
  integer,intent(in) :: in          ! Alias number
  ! Local
  integer :: i,j
  !
  j = 0
  do i=1,nalias
    if (alias(i).eq.in) then
      j = i
      exit
    endif
  enddo
  if (j.eq.0) then
    call sic_message(seve%e,'SIC','lost alias ...')
    return
  endif
  !
  nalias = nalias-1
  do i=j,nalias
    alias(i) = alias(i+1)
    pointee(i) = pointee(i+1)
    dicali(i) = dicali(i+1)
  enddo
  alias(nalias+1) = 0
  pointee(nalias+1) = 0
  dicali(nalias+1)%name = ' '
  dicali(nalias+1)%lname = 0
  dicali(nalias+1)%level = 0
end subroutine zap_alias
!
subroutine del_alias (in,local)
  use sic_interfaces, except_this=>del_alias
  use gildas_def
  use sic_structures
  use sic_dictionaries
  !---------------------------------------------------------------------
  ! @ private
  ! Delete the aliases pointing (even partially) towards variable IN
  !---------------------------------------------------------------------
  integer, intent(in) :: in         ! Pointee number
  logical, intent(in) :: local      ! Local or Global status
  ! Local
  integer :: i,j
  logical :: error,user
  !
  error = .false.
  user = .true.  ! Aliases always considered as user-defined
  !
  i = 1
  do while (i.le.nalias)
    if (pointee(i).eq.in) then
      ! If this alias points on IN, delete it. This pushes down the list
      ! of aliases, so do not increment I
      j = alias(i)
#if defined(GAG_USE_PYTHON)
      ! The Jth element of DICALI is the alias target.
      ! The Jth element of DICVAR is the alias name.
      call gpy_delvar(dicvar(j)%id%name,dicvar(j)%id%level)
#endif
      call zap_alias(j)
      call sic_zapvariable(j,user,local,error)
    else
      ! Else, go to next name
      i = i+1
    endif
  enddo
end subroutine del_alias
