subroutine sic_let_auto (var,dble,error)
  use sic_interfaces, except_this=>sic_let_auto
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   External routine
  !       Attributes a value to an already defined variable of numeric type.
  !       No data type checking for this entry. Only Global
  !       variables are affected by this entry, since it is
  !       called by program only.
  !---------------------------------------------------------------------
  character(len=*)                :: var    !
  real*8                          :: dble   !
  logical,          intent(inout) :: error  !
  ! Local
  real*4 :: value
  integer*4 :: inte
  integer*8 :: long
  logical :: logi
  character(len=1) :: string
  integer :: fmt
  !
  fmt = 0
  call sic_let_var(var,value,dble,inte,long,logi,string,fmt,error)
end subroutine sic_let_auto
!
subroutine sic_let_real (var,value,error)
  use sic_interfaces, except_this=>sic_let_real
  use gbl_format
  !---------------------------------------------------------------------
  ! @ public
  !  Attributes a value to an already defined variable.
  !  No data type checking for this entry. Only Global variables are
  ! affected by this entry, since it is called by program only.
  !---------------------------------------------------------------------
  character(len=*)                :: var    !
  real*4                          :: value  !
  logical,          intent(inout) :: error  !
  ! Local
  real*8 :: dble
  integer*4 :: inte
  integer*8 :: long
  logical :: logi
  character(len=1) :: string
  integer :: fmt
  !
  fmt = fmt_r4
  call sic_let_var(var,value,dble,inte,long,logi,string,fmt,error)
end subroutine sic_let_real
!
subroutine sic_let_dble (var,dble,error)
  use sic_interfaces, except_this=>sic_let_dble
  use gbl_format
  !---------------------------------------------------------------------
  ! @ public
  !  Attributes a value to an already defined variable.
  !  No data type checking for this entry. Only Global variables are
  ! affected by this entry, since it is called by program only.
  !---------------------------------------------------------------------
  character(len=*)                :: var    !
  real*8                          :: dble   !
  logical,          intent(inout) :: error  !
  ! Local
  real*4 :: value
  integer*4 :: inte
  integer*8 :: long
  logical :: logi
  integer :: fmt
  character(len=1) :: string
  !
  fmt = fmt_r8
  call sic_let_var(var,value,dble,inte,long,logi,string,fmt,error)
end subroutine sic_let_dble
!
subroutine sic_let_inte (var,inte,error)
  use sic_interfaces, except_this=>sic_let_inte
  use gbl_format
  !---------------------------------------------------------------------
  ! @ public
  !  Attributes a value to an already defined variable.
  !  No data type checking for this entry. Only Global variables are
  ! affected by this entry, since it is called by program only.
  !---------------------------------------------------------------------
  character(len=*)                :: var    !
  integer*4                       :: inte   !
  logical,          intent(inout) :: error  !
  ! Local
  real*4 :: value
  real*8 :: dble
  logical :: logi
  integer*8 :: long
  integer :: fmt
  character(len=1) :: string
  !
  fmt = fmt_i4
  call sic_let_var(var,value,dble,inte,long,logi,string,fmt,error)
end subroutine sic_let_inte
!
subroutine sic_let_long (var,long,error)
  use sic_interfaces, except_this=>sic_let_long
  use gbl_format
  !---------------------------------------------------------------------
  ! @ public
  !  Attributes a value to an already defined variable.
  !  No data type checking for this entry. Only Global variables are
  ! affected by this entry, since it is called by program only.
  !---------------------------------------------------------------------
  character(len=*)                :: var    !
  integer*8                       :: long   !
  logical,          intent(inout) :: error  !
  ! Local
  real*4 :: value
  real*8 :: dble
  logical :: logi
  integer*4 :: inte
  integer :: fmt
  character(len=1) :: string
  !
  fmt = fmt_i8
  call sic_let_var(var,value,dble,inte,long,logi,string,fmt,error)
end subroutine sic_let_long
!
subroutine sic_let_logi (var,logi,error)
  use sic_interfaces, except_this=>sic_let_logi
  use gbl_format
  !---------------------------------------------------------------------
  ! @ public
  !  Attributes a value to an already defined variable.
  !  No data type checking for this entry. Only Global variables are
  ! affected by this entry, since it is called by program only.
  !---------------------------------------------------------------------
  character(len=*)                :: var    !
  logical                         :: logi   !
  logical,          intent(inout) :: error  !
  ! Local
  real*4 :: value
  real*8 :: dble
  integer*4 :: inte
  integer*8 :: long
  integer :: fmt
  character(len=1) :: string
  !
  fmt = fmt_l
  call sic_let_var(var,value,dble,inte,long,logi,string,fmt,error)
end subroutine sic_let_logi
!
subroutine sic_let_char (var,string,error)
  use sic_interfaces, except_this=>sic_let_char
  !---------------------------------------------------------------------
  ! @ public
  !  Attributes a value to an already defined variable.
  !  No data type checking for this entry. Only Global variables are
  ! affected by this entry, since it is called by program only.
  !---------------------------------------------------------------------
  character(len=*)                :: var     !
  character(len=*)                :: string  !
  logical,          intent(inout) :: error   !
  ! Local
  real*4 :: value
  real*8 :: dble
  integer*4 :: inte
  integer*8 :: long
  logical :: logi
  integer :: fmt
  !
  fmt = 1
  call sic_let_var(var,value,dble,inte,long,logi,string,fmt,error)
end subroutine sic_let_char
!
subroutine sic_let_var(namein,value,dble,inte,long,logi,string,fmt,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_let_var
  use gildas_def
  use sic_structures
  use sic_dictionaries
  use sic_types
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !       Attributes a value to an already defined variable.
  !       No data type checking for this entry. Only Global
  !       variables are affected by this entry, since it is
  !       called by program only.
  !
  !     Uses the appropriate input variable according to FMT
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: namein  !
  real(kind=4),     intent(in)  :: value   !
  real(kind=8),     intent(in)  :: dble    !
  integer(kind=4),  intent(in)  :: inte    !
  integer(kind=8),  intent(in)  :: long    !
  logical,          intent(in)  :: logi    !
  character(len=*), intent(in)  :: string  !
  integer(kind=4),  intent(in)  :: fmt     !
  logical,          intent(out) :: error   !
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='LET'
  type(sic_identifier_t) :: var
  integer :: in,ier,atype
  type(sic_descriptor_t) :: desc
  integer(kind=address_length) :: ipnt
  logical :: verbose
  type(sic_dimensions_t) :: spec
  character(len=message_length) :: mess
  real*4 :: lvalue
  integer*4 :: linte
  integer*8 :: llong
  !
  ! Parse name from dimensions...
  spec%do%strict   = .true.   ! 'namein' must refer to a valid specifier, not e.g. an expression
  spec%do%range    = .true.   ! e.g. A[3:5] allowed
  spec%do%subset   = .true.   ! e.g. A[2,] allowed
  spec%do%implicit = .false.  ! e.g. A[i] forbidden
  spec%do%twospec  = .true.   ! e.g. A[i][j:k] allowed
  verbose  = .true.
  error    = .false.
  call sic_parse_dim(namein,var,spec,verbose,error)
  if (error) return
  !
  ! Only Global here
  var%level = 0
  ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,var,in)
  if (ier.ne.1) then
    call sic_message(seve%e,rname,'No such variable '//namein)
    error =.true.
    return
  endif
  !
  ! Do not allow incarnation or transposition here
  call extract_descr(desc,dicvar(in)%desc,spec%done,var%name,.false.,0,error)
  if (error) return
  !
  atype = desc%type
  !
  if (desc%readonly) then
    call sic_message(seve%e,rname,'Readonly variables cannot be modified')
    error = .true.
    return
  elseif (desc%status.eq.scratch_operand) then
    call sic_message(seve%e,rname,'Trying to store in a scratch variable')
    error = .true.
    return
  elseif (atype.eq.0) then
    if (fmt.le.0) then
      call sic_message(seve%e,rname,'Header or Structure cannot be '//  &
      'assigned as a whole')
      error = .true.
      return
    endif
  elseif (atype.gt.0) then
    if (fmt.le.0) then
      write(mess,1001) 'Variable type does not match declaration ',fmt,atype,  &
      namein
      call sic_message(seve%e,rname,mess)
      error = .true.
      return
    endif
    call ctodes(string,desc%type,desc%addr)
  elseif (desc%ndim.ne.0) then
    call sic_message(seve%e,rname,'Cannot assign arrays')
    error = .true.
  elseif (fmt.eq.0) then
    ! Automatic: convert from the input real*8 value
    ipnt = bytpnt(desc%addr,membyt)
    if (atype.eq.fmt_i4) then
      linte = nint(dble)
      call i4toi4(linte,membyt(ipnt),1)
    elseif (atype.eq.fmt_r4) then
      lvalue = dble
      call r4tor4(lvalue,membyt(ipnt),1)
    elseif (atype.eq.fmt_r8) then
      call r8tor8(dble,membyt(ipnt),1)
    elseif (atype.eq.fmt_i8) then
      llong = nint(dble,kind=8)
      call i8toi8(llong,membyt(ipnt),1)
    else
      write(mess,1001) 'Variable type does not match declaration ',fmt,atype,  &
      namein
      call sic_message(seve%e,rname,mess)
      error = .true.
      return
    endif
    !
  elseif (fmt.ne.atype) then
    write(mess,1001) 'Variable type does not match declaration',fmt,atype,namein
    call sic_message(seve%e,rname,mess)
    error = .true.
  else
    ipnt = bytpnt(desc%addr,membyt)
    if (atype.eq.fmt_l) then
      call l4tol4(logi,membyt(ipnt),1)
    elseif (atype.eq.fmt_i4) then
      call i4toi4(inte,membyt(ipnt),1)
    elseif (atype.eq.fmt_r4) then
      call r4tor4(value,membyt(ipnt),1)
    elseif (atype.eq.fmt_r8) then
      call r8tor8(dble,membyt(ipnt),1)
    elseif (atype.eq.fmt_i8) then
      call i8toi8(long,membyt(ipnt),1)
    endif
  endif
  !
1001 format(a,i4,i4,a)
end subroutine sic_let_var
!
subroutine sic_def_real_addr (symb,rel,ndim,dim,readonly,error)
  use gildas_def
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Define a REAL Sic variable
  !  Does the real job. Do not call directly (use the generic interface
  !  'sic_def_real' instead), except for memory(ip) targets.
  ! Warning! Dimensions must be integers of kind index_length, i.e.
  ! explicit integer values can not be used.
  !---------------------------------------------------------------------
  character(len=*),            intent(in)    :: symb       ! Variable name
  real(kind=4),                intent(in)    :: rel        ! First element of target
  integer(kind=4),             intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),  intent(in)    :: dim(ndim)  ! Dimensions
  logical,                     intent(in)    :: readonly   ! Read only?
  logical,                     intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vaddr = locwrd (rel)
  vtype = fmt_r4
  vlev = 0
  size = 1
  do i = 1,ndim
    size = size*dim(i)
  enddo
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_real_addr
!
subroutine sic_def_dble_addr(symb,dble,ndim,dim,readonly,error)
  use gildas_def
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Define a DOUBLE Sic variable
  !  Does the real job. Do not call directly (use the generic interface
  !  'sic_def_dble' instead), except for memory(ip) targets.
  ! Warning! Dimensions must be integers of kind index_length, i.e.
  ! explicit integer values can not be used.
  !---------------------------------------------------------------------
  character(len=*),            intent(in)    :: symb       ! Variable name
  real(kind=8),                intent(in)    :: dble       ! First element of target
  integer(kind=4),             intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),  intent(in)    :: dim(ndim)  ! Dimensions
  logical,                     intent(in)    :: readonly   ! Read only?
  logical,                     intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vaddr = locwrd(dble)
  vtype = fmt_r8
  vlev = 0
  size = 2
  do i = 1,ndim
    size = size*dim(i)
  enddo
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_dble_addr
!
subroutine sic_def_inte_addr(symb,inte,ndim,dim,readonly,error)
  use gildas_def
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Define an INTEGER Sic variable
  !  Does the real job. Do not call directly (use the generic interface
  !  'sic_def_inte' instead), except for memory(ip) targets.
  ! Warning! Dimensions must be integers of kind index_length, i.e.
  ! explicit integer values can not be used.
  !---------------------------------------------------------------------
  character(len=*),            intent(in)    :: symb       ! Variable name
  integer(kind=4),             intent(in)    :: inte       ! First element of target
  integer(kind=4),             intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),  intent(in)    :: dim(ndim)  ! Dimensions
  logical,                     intent(in)    :: readonly   ! Read only?
  logical,                     intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vaddr = locwrd(inte)
  vtype = fmt_i4
  vlev = 0
  size = 1
  do i = 1,ndim
    size = size*dim(i)
  enddo
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_inte_addr
!
subroutine sic_def_long_addr(symb,long,ndim,dim,readonly,error)
  use gildas_def
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Define a LONG Sic variable
  !  Does the real job. Do not call directly (use the generic interface
  !  'sic_def_long' instead), except for memory(ip) targets.
  ! Warning! Dimensions must be integers of kind index_length, i.e.
  ! explicit integer values can not be used.
  !---------------------------------------------------------------------
  character(len=*),            intent(in)    :: symb       ! Variable name
  integer(kind=8),             intent(in)    :: long       ! First element of target
  integer(kind=4),             intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),  intent(in)    :: dim(ndim)  ! Dimensions
  logical,                     intent(in)    :: readonly   ! Read only?
  logical,                     intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vaddr = locwrd(long)
  vtype = fmt_i8
  vlev = 0
  size = 2
  do i = 1,ndim
    size = size*dim(i)
  enddo
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_long_addr
!
subroutine sic_def_cplx_addr (symb,cplx,ndim,dim,readonly,error)
  use gildas_def
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Define a COMPLEX Sic variable
  !  Does the real job. Do not call directly (use the generic interface
  !  'sic_def_cplx' instead), except for memory(ip) targets.
  ! Warning! Dimensions must be integers of kind index_length, i.e.
  ! explicit integer values can not be used.
  !---------------------------------------------------------------------
  character(len=*),            intent(in)    :: symb       ! Variable name
  complex(kind=4),             intent(in)    :: cplx       ! First element of target
  integer(kind=4),             intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),  intent(in)    :: dim(ndim)  ! Dimensions
  logical,                     intent(in)    :: readonly   ! Read only?
  logical,                     intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vaddr = locwrd (cplx)
  vtype = fmt_c4
  vlev = 0
  size = 2
  do i = 1,ndim
    size = size*dim(i)
  enddo
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_cplx_addr
!
subroutine sic_def_logi (symb,logi,readonly,error)
  use gildas_def
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_def_logi
  !---------------------------------------------------------------------
  ! @ public
  !  Define a LOGICAL scalar Sic variable
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: symb      ! Variable name
  logical,          intent(in)    :: logi      ! Target scalar
  logical,          intent(in)    :: readonly  ! Read only?
  logical,          intent(inout) :: error     ! Logical error flag
  ! Local
  integer :: vtype,ndim,vlev
  integer(kind=index_length) :: jdim(sic_maxdims)
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vaddr = locwrd(logi)
  vtype = fmt_l
  vlev = 0
  size = 1
  ndim = 0
  call sic_def_avar(symb,vaddr,vtype,size,ndim,jdim,readonly,vlev,error)
end subroutine sic_def_logi
!
subroutine sic_def_login_addr(symb,logi,ndim,dim,readonly,error)
  use gildas_def
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Define a LOGICAL array Sic variable
  !  Does the real job. Do not call directly (use the generic interface
  !  'sic_def_login' instead), except for memory(ip) targets.
  ! Warning! Dimensions must be integers of kind index_length, i.e.
  ! explicit integer values can not be used.
  !---------------------------------------------------------------------
  character(len=*),            intent(in)    :: symb       ! Variable name
  logical,                     intent(in)    :: logi       ! First element of target
  integer(kind=4),             intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),  intent(in)    :: dim(ndim)  ! Dimensions
  logical,                     intent(in)    :: readonly   ! Read only?
  logical,                     intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vaddr = locwrd(logi)
  vtype = fmt_l
  vlev = 0
  size = 1
  do i = 1,ndim
    size = size*dim(i)
  enddo
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_login_addr
!
subroutine sic_def_char(symb,chain,readonly,error)
  use gildas_def
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_def_char
  !---------------------------------------------------------------------
  ! @ public
  !  Define a CHARACTER scalar Sic variable
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: symb      ! Variable name
  character(len=*), intent(in)    :: chain     ! Target scalar string
  logical,          intent(in)    :: readonly  ! Read only?
  logical,          intent(inout) :: error     ! Logical error flag
  ! Local
  integer :: vtype,ndim,vlev
  integer(kind=index_length) :: jdim(sic_maxdims)
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vtype = len(chain)
  if (vtype.le.0) then
    call sic_message(seve%e,'SIC','Character string '//trim(symb)//' has zero-length')
    error = .true.
    return
  endif
  vaddr = locstr(chain)
  vlev = 0
  size = (vtype+3)/4
  ndim = 0
  call sic_def_avar(symb,vaddr,vtype,size,ndim,jdim,readonly,vlev,error)
end subroutine sic_def_char
!
subroutine sic_def_strn(symb,string,ns,readonly,error)
  use gildas_def
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch - on purpose -)
  ! Define a CHARACTER scalar SIC variable.
  ! The input 'string' variable can be of any kind, so the string
  ! length is passed in a complementary argument. Added for HEADERCHAR
  ! (at least).
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: symb       ! Variable name
  integer(kind=1),  intent(in)    :: string(*)  ! Target object
  integer(kind=4),  intent(in)    :: ns         ! String length
  logical,          intent(in)    :: readonly   ! Read only?
  logical,          intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,ndim,vlev
  integer(kind=index_length) :: jdim(sic_maxdims)
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vtype = ns
  if (vtype.le.0) then
    call sic_message(seve%e,'SIC','Character string '//trim(symb)//' has zero-length')
    error = .true.
    return
  endif
  vaddr = locwrd(string)
  vlev = 0
  size = (vtype+3)/4
  ndim = 0
  call sic_def_avar(symb,vaddr,vtype,size,ndim,jdim,readonly,vlev,error)
end subroutine sic_def_strn
!
subroutine sic_def_charn_addr(symb,chain,ndim,dim,readonly,error)
  use gildas_def
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Define a CHARACTER array Sic variable
  !  Does the real job. Do not call directly (use the generic interface
  !  'sic_def_charn' instead), except for memory(ip) targets.
  ! Warning! Dimensions must be integers of kind index_length, i.e.
  ! explicit integer values can not be used.
  !---------------------------------------------------------------------
  character(len=*),            intent(in)    :: symb       ! Variable name
  character(len=*),            intent(in)    :: chain      ! First element of target
  integer(kind=4),             intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),  intent(in)    :: dim(ndim)  ! Dimensions
  logical,                     intent(in)    :: readonly   ! Read only?
  logical,                     intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  integer(kind=address_length) :: vaddr
  !
  vtype = len(chain)
  if (vtype.le.0) then
    call sic_message(seve%e,'SIC','Character string '//trim(symb)//' has zero-length')
    error = .true.
    return
  endif
  vaddr = locstr(chain)
  vlev = 0
  size = vtype
  do i = 1,ndim
    size = size*dim(i)
  enddo
  size = (size+3)/4  ! Convert to words
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_charn_addr
!
subroutine sic_def_charpnt(symb,vaddr,vsize,ndim,dim,readonly,error)
  use gildas_def
  use gbl_message
  use sic_interfaces, except_this=>sic_def_charpnt
  !---------------------------------------------------------------------
  ! @ public
  !  Define a CHARACTER array Sic variable
  !---------------------------------------------------------------------
  character(len=*),             intent(in)    :: symb       ! Variable name
  integer(kind=address_length), intent(in)    :: vaddr      ! Target address
  integer(kind=4),              intent(in)    :: vsize      ! Size of each string
  integer(kind=4),              intent(in)    :: ndim       ! Number of dimensions
  integer(kind=index_length),   intent(in)    :: dim(ndim)  ! Dimensions
  logical,                      intent(in)    :: readonly   ! Read only?
  logical,                      intent(inout) :: error      ! Logical error flag
  ! Local
  integer :: vtype,i,vlev
  integer(kind=size_length) :: size
  !
  vtype = vsize
  if (vtype.le.0) then
    call sic_message(seve%e,'SIC','Character string '//trim(symb)//' has zero-length')
    error = .true.
    return
  endif
  vlev = 0
  size = vtype
  do i = 1,ndim
    size = size*dim(i)
  enddo
  size = (size+3)/4  ! Convert to words
  call sic_def_avar(symb,vaddr,vtype,size,ndim,dim,readonly,vlev,error)
end subroutine sic_def_charpnt
!
subroutine sic_def_avar(symb,vaddr,vtype,size,ndim,jdim,readonly,lev,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_def_avar
  use gildas_def
  use sic_structures
  use sic_dictionaries
  use sic_interactions
  use sic_types
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ private
  ! Defines Sic variables by program or user
  !---------------------------------------------------------------------
  character(len=*),             intent(in)  :: symb        ! Variable name
  integer(kind=address_length), intent(in)  :: vaddr       ! Variable address
  integer(kind=4),              intent(in)  :: vtype       ! Variable type
  integer(kind=size_length),    intent(in)  :: size        ! Variable size (4-bytes words)
  integer(kind=4),              intent(in)  :: ndim        ! Number of dimensions
  integer(kind=index_length),   intent(in)  :: jdim(ndim)  ! Dimensions
  logical,                      intent(in)  :: readonly    ! ReadOnly flag
  integer(kind=4),              intent(in)  :: lev         ! Variable level
  logical,                      intent(out) :: error       ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='VARIABLE'
  type(sic_identifier_t) :: var
  integer(kind=4) :: ls,in,i,ier
  !
  ! Check if SIC is loaded
  if (.not.loaded) then
    call sic_message(seve%e,rname,'SIC is not loaded')
    error = .true.
    return
  endif
  !
  ! NEVER CHECK THAT HERE! Does not work on 16 bit macs!
  !* Check "odd" address for non-character data
#ifndef CYGWIN
  if (mod(vaddr,4_address_length).ne.0.and.vtype.lt.0) then
    call sic_message(seve%e,rname,  &
      'Address of '//trim(symb)//' is not multiple of 4')
    error = .true.
    return
  endif
#endif
  !
  ! Find the symbol and truncate, exclude quotes
  ls = len_trim(symb)
  if (ls.gt.varname_length) then
    call sic_message(seve%e,rname,'Variable name too long '//symb)
    error = .true.
    return
  endif
  var%name = symb
  var%lname = ls
  call sic_upper(var%name)
  var%level = lev
  !
  ! Check if it already exists
  ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,var,in)
  if (ier.eq.1) then
    call sic_message(seve%e,rname,'Variable '//trim(symb)//  &
    ' already exists')
    error = .true.
    return
  endif
  !
  ! Insert in symbol dictionnary
  ier = sic_hasins(rname,maxvar,pfvar,pnvar,dicvar,var,in)
  if (ier.eq.0 .or. ier.eq.2) then
    error = .true.
    return
  endif
  !
  error = .false.
  !
  dicvar(in)%desc%addr = vaddr
  dicvar(in)%desc%type = vtype
  dicvar(in)%desc%readonly = readonly
  dicvar(in)%desc%ndim = ndim
  do i = 1,ndim
    dicvar(in)%desc%dims(i) = jdim(i)
  enddo
  do i = ndim+1,sic_maxdims
    dicvar(in)%desc%dims(i) = 1
  enddo
  dicvar(in)%desc%size = size
  dicvar(in)%desc%status = program_defined
  !
#if defined(GAG_USE_PYTHON)
  call gpy_getvar(var%name,var%level)
#endif
  !
end subroutine sic_def_avar
!
subroutine i4_type(n,arr)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: n    !
  integer*4 :: arr(n)               !
  ! Local
  integer :: i,m,j
  !
  m = n/6
  do i=1,6*m,6
    write(6,100) (arr(j),j=i,i+5)
    if (sic_ctrlc()) return
  enddo
  if (6*m.ne.n) write(6,100) (arr(j),j=6*m+1,n)
100 format(6(1x,i12))
end subroutine i4_type
!
subroutine i8_type(n,arr)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: n    !
  integer*8 :: arr(n)               !
  ! Local
  integer :: i,j,m
  m = n/3
  do i=1,3*m,3
    write(6,100) (arr(j),j=i,i+2)
    if (sic_ctrlc()) return
  enddo
  if (3*m.ne.n) write(6,100) (arr(j),j=3*m+1,n)
100 format (3(1x,i21))
end subroutine i8_type
!
subroutine r4_type(n,arr)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: n    !
  real :: arr(n)                    !
  ! Local
  integer :: i,j,m
  !
  m = n/5
  do i=1,5*m,5
    write(6,100) (arr(j),j=i,i+4)
    if (sic_ctrlc()) return
  enddo
  if (5*m.ne.n) write(6,100) (arr(j),j=5*m+1,n)
100 format (5(1x,1pg14.7))
end subroutine r4_type
!
subroutine r8_type(n,arr)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: n    !
  real*8 :: arr(n)                  !
  ! Local
  integer :: i,j,m
  m = n/3
  do i=1,3*m,3
    write(6,100) (arr(j),j=i,i+2)
    if (sic_ctrlc()) return
  enddo
  if (3*m.ne.n) write(6,100) (arr(j),j=3*m+1,n)
100 format (3(1x,1pg25.18))
end subroutine r8_type
!
subroutine c4_type(n,arr)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: n    !
  real*4 :: arr(*)                  !
  ! Local
  integer :: i,j,m
  m = n/2
  do i=1,4*m,4
    write(6,100) (arr(j),j=i,i+3)
    if (sic_ctrlc()) return
  enddo
  if (2*m.ne.n) write(6,100) (arr(j),j=4*m+1,2*n)
100 format (2(1x,'(',1pg15.7,',',1pg15.7,')'))
end subroutine c4_type
!
subroutine l_type(n,arr)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: n    !
  logical :: arr(n)                 !
  ! Local
  integer :: i,j,m
  m = n/24
  do i=1,24*m,24
    write(6,100) (arr(j),j=i,i+23)
    if (sic_ctrlc()) return
  enddo
  if (24*m.ne.n) write(6,100) (arr(j),j=24*m+1,n)
100 format (24(1x,l1))
end subroutine l_type
!
subroutine ch_type(n,arr,l)
  use gildas_def
  use sic_dependencies_interfaces
  use sic_interfaces
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: n       ! Number of elements
  character(len=*),          intent(in) :: arr(n)  !
  integer(kind=4),           intent(in) :: l       ! String length
  ! Local
  character(len=*), parameter :: blank =  &
    '                                                                '
  integer(kind=4) :: nperline,nblank,i,j,m,tt_width
  !
  tt_width = sic_ttyncol()
  nperline = max(1,tt_width/(l+1))  ! l+1: at least 1 blank between each value
  nblank = max(1,(tt_width-l*nperline)/nperline)
  m = n/nperline
  do i=1,nperline*m,nperline
    write(6,100) (arr(j)(1:l)//blank(1:nblank),j=i,i+nperline-1)
    if (sic_ctrlc()) return
  enddo
  if (nperline*m.ne.n)  &
    write(6,100) (arr(j)(1:l)//blank(1:nblank),j=nperline*m+1,n)
100 format (40A)
end subroutine ch_type
!
subroutine hex_type(n,arr)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !  Print the input byte-array as hexadecimal strings.
  !---------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: n       ! Number of elements
  integer(kind=1),           intent(in) :: arr(n)  !
  ! Local
  integer(kind=size_length) :: i,m,j
  integer(kind=4), parameter :: nperline=32 ! Number of bytes per line
  !
  m = n/nperline
  do i=1,nperline*m,nperline
    write(6,100) (arr(j),j=i,i+nperline-1)
    if (sic_ctrlc()) return
  enddo
  if (nperline*m.ne.n) write(6,100) (arr(j),j=nperline*m+1,n)
100 format(8(4(Z2.2),1X))  ! Gather by group of 4-bytes
end subroutine hex_type
!
! subroutine i4_type_to_string(n,arr,string)
!   use sic_interfaces
!   integer :: n                      !
!   integer :: arr(n)                 !
!   character(len=*) :: string        !
!   ! Local
!   integer :: i,nc
!   !
!   nc = 1
!   do i = 1, n
!     call sic_dble_to_string(arr(i),string(nc:))
!     nc = nc + len_trim(string(nc:))+ 1
!   enddo
! end subroutine i4_type_to_string
!
! subroutine r4_type_to_string(n,arr,string)
!   use sic_interfaces
!   integer :: n                      !
!   real :: arr(n)                    !
!   character(len=*) :: string        !
!   ! Local
!   integer :: i,nc
!   !
!   nc = 1
!   do i = 1, n
!     call sic_dble_to_string(arr(i),string(nc:))
!     nc = nc + len_trim(string(nc:))+ 1
!   enddo
! end subroutine r4_type_to_string
!
! subroutine r8_type_to_string(n,arr,string)
!   use sic_interfaces
!   integer :: n                      !
!   real*8 :: arr(n)                  !
!   character(len=*) :: string        !
!   ! Local
!   integer :: i,nc
!   !
!   nc = 1
!   do i = 1, n
!     call sic_dble_to_string(arr(i),string(nc:))
!     nc = nc + len_trim(string(nc:))+ 1
!   enddo
! end subroutine r8_type_to_string
!
! subroutine c4_type_to_string(n,arr,string)
!   use sic_interfaces
!   !---------------------------------------------------------------------
!   !
!   !---------------------------------------------------------------------
!   integer :: n                      !
!   real*4 :: arr(*)                  !
!   character(len=*) :: string        !
!   ! Local
!   integer :: i,nc
!   !
!   nc = 1
!   do i = 1, 2*n, 2
!     string(nc:nc) = '('
!     nc = nc+1
!     !
!     call sic_dble_to_string(arr(i),string(nc:))
!     nc = nc+len_trim(string(nc:))
!     !
!     string(nc:nc) = ','
!     nc = nc+1
!     !
!     call sic_dble_to_string(arr(i),string(nc:))
!     nc = nc+len_trim(string(nc:))
!     !
!     string(nc:nc) = ')'
!     nc = nc+2
!   enddo
!   !
! end subroutine c4_type_to_string
!
subroutine l_type_to_string(n,arr,string)
  use sic_interfaces
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer :: n                      !
  logical :: arr(n)                 !
  character(len=*) :: string        !
  ! Local
  integer :: i,nc
  !
  nc = 1
  do i = 1, n
    call sic_logi_to_string(arr(i),string(nc:))
    nc = nc + len_trim(string(nc:))+ 1
  enddo
end subroutine l_type_to_string
!
subroutine sic_validname(name,error)
  use sic_interfaces, except_this=>sic_validname
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC  Internal Routine
  !     Check if a variable name is valid
  !---------------------------------------------------------------------
  character(len=*) :: name          !
  logical :: error                  !
  ! Local
  integer :: i,n,ic
  character(len=1) :: c
  !
  error = .false.
  n = len_trim(name)
  do i=1,n
    if (name(i:i).eq.'$') then
      if (i.ne.n) then
        call sic_message(seve%w,'SIC','$ is only valid as last char '//  &
        name(1:n))
        !  error = .true. ! For the time being
      endif
    elseif  (name(i:i).eq.'_') then
      continue
    elseif  (name(i:i).eq.'%') then
      continue
    elseif  (name(i:i).ge.'a' .and. name(i:i).le.'z') then
      ic=ichar(name(i:i))+ichar('A')-ichar('a')
      name(i:i)=char(ic)
    elseif  (name(i:i).ge.'A' .and. name(i:i).le.'Z') then
      continue
    elseif  (name(i:i).ge.'0' .and. name(i:i).le.'9') then
      continue
    else
      c= name(i:i)
      call sic_message(seve%e,'SIC',c//' is not a valid character')
      error = .true.
    endif
  enddo
  if (error) then
    call sic_message(seve%e,'SIC_VALID','Invalid variable '//name(1:n))
  endif
end subroutine sic_validname
