subroutine sic_desc (line,iopt,iarg,desc,default,present,error)
  use sic_interfaces, except_this=>sic_desc
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   External routine
  !       Retrieves the IARG-th argument of the IOPT-th option
  !       and returns a SIC descriptor pointing to the appropriate
  !       variable.
  !
  ! Arguments:
  !       LINE    C*(*)   Command line                    Input
  !       IOPT    I       Option number (0=command)       Input
  !       IARG    I       Argument number (0=command)     Input
  !       PRESENT L       Must the argument be present ?  Input
  !---------------------------------------------------------------------
  character(len=*)                      :: line     !
  integer                               :: iopt     !
  integer                               :: iarg     !
  type(sic_descriptor_t), intent(out)   :: desc     ! Descriptor
  type(sic_descriptor_t), intent(in)    :: default  ! Default descriptor
  logical                               :: present  !
  logical,                intent(inout) :: error    ! Error return
  !
  call sic_desc_inca (line,iopt,iarg,desc,default,present,error,1)
end subroutine sic_desc
!
subroutine sic_inca (line,iopt,iarg,desc,default,present,error)
  use sic_interfaces, except_this=>sic_inca
  use sic_types
  !---------------------------------------------------------------------
  ! @ public
  !       Retrieves the IARG-th argument of the IOPT-th option
  !       and returns a SIC incarnation of the result.
  !
  ! Arguments:
  !       LINE    C*(*)   Command line                    Input
  !       IOPT    I       Option number (0=command)       Input
  !       IARG    I       Argument number (0=command)     Input
  !       PRESENT L       Must the argument be present ?  Input
  !---------------------------------------------------------------------
  character(len=*)                      :: line     !
  integer                               :: iopt     !
  integer                               :: iarg     !
  type(sic_descriptor_t), intent(out)   :: desc     ! Descriptor
  type(sic_descriptor_t), intent(in)    :: default  ! Default descriptor
  logical                               :: present  !
  logical,                intent(inout) :: error    ! Error return
  !
  call sic_desc_inca (line,iopt,iarg,desc,default,present,error,2)
end subroutine sic_inca
!
subroutine sic_desc_inca (line,iopt,iarg,desc,default,present,error,code)
  use gildas_def
  use gbl_message
  use gbl_format
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_desc_inca
  use sic_structures
  use sic_dictionaries
  use sic_interactions
  use sic_expressions
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   External routine
  !       Retrieves the IARG-th argument of the IOPT-th option
  !       and returns a SIC descriptor pointing to the appropriate
  !       variable.
  !
  ! Arguments:
  !       LINE    C*(*)   Command line                    Input
  !       IOPT    I       Option number (0=command)       Input
  !       IARG    I       Argument number (0=command)     Input
  !       PRESENT L       Must the argument be present ?  Input
  !       ERROR   L       Error return
  !       CODE    I       1 <=> Descriptor,  2 <=> Incarnation Input
  ! (5-mar-1985)
  !---------------------------------------------------------------------
  character(len=*) :: line                    !
  integer :: iopt                             !
  integer :: iarg                             !
  type(sic_descriptor_t), intent(out) :: desc     ! Descriptor
  type(sic_descriptor_t), intent(in)  :: default  ! Default descriptor
  logical :: present                          !
  logical :: error                            !
  integer :: code                             !
  ! Local
  character(len=*), parameter :: rname='DECODE'
  type(sic_descriptor_t) :: tmp
  integer :: argtyp,ifirst,ilast,parg,thetyp
  logical :: found,l
  real(kind=4) :: r4
  real(kind=8) :: r8
  integer(kind=4) :: i4
  integer(kind=8) :: i8
  character(len=1) :: quote
  character(len=1024) :: argum,var
  character(len=message_length) :: mess
  ! Data
  data quote /"'"/
  !
  ! Get default descriptor
  desc = default
  argtyp = default%type
  !
  if (argtyp.lt.0) then
    thetyp = 2
  else
    thetyp = 0
  endif
  !
  ! Check if argument is present
  error = .true.
  if (iopt.gt.maxopt .or. iopt.lt.0 .or. iarg.lt.0) then
    write(mess,104) iopt,iarg
    call sic_message(seve%e,rname,mess)
    return
  endif
  if (locstr(line).ne.ccomm%aline) then
    call sic_message(seve%e,rname,'You have overwritten the command line pointers.')
    call sic_message(seve%e,rname,'The following command line can not be parsed anymore:')
    call sic_message(seve%e,rname,line)
    call sic_message(seve%e,rname,'because the command '//trim(ccomm%command)//  &
      ' was executed in the meantime.')
    return
  endif
  if (iarg.le.ccomm%narg(iopt)) then
    parg = ccomm%popt(iopt)+iarg
    if (parg.gt.mword) then
      write(mess,104) iopt,iarg
      call sic_message(seve%e,rname,mess)
      return
    endif
    ifirst = ccomm%ibeg(parg)
    ilast  = ccomm%iend(parg)
  else
    if (present) then
      if (iopt.eq.0) then
        write(mess,101) iarg,trim(ccomm%lang),char(92),vocab(ccomm%icom)(2:)
      else
        write(mess,102) iarg,vocab(ccomm%icom+iopt)(2:)
      endif
      call sic_message(seve%e,rname,mess)
      return
    endif
    error = .false.
    return
  endif
  error = .false.
  !
  ! If *, return the default
  if (line(ifirst:ilast).eq.'*') return
  !
  ! Undefined type: check argument type and return automatic incarnation
  if (argtyp.eq.0) then
    ! Only valid for Incarnation
    if (code.eq.1) then
      call sic_message(seve%e,rname,'Programming error ')
      call sic_message(seve%e,rname,'Undefined variable type in call to '//  &
      'SIC_DESC')
      error = .true.
      return
    endif
    !
    ! Character string
    if (line(ifirst:ifirst).eq.'"') then
      call sic_expand(argum,line,ifirst,ilast,parg,error)
      if (error) return
      next_st = next_st+1
      argu_st(next_st) = argum(1:parg)
      desc%type = parg
      desc%readonly = .false.
      desc%addr = locstr(argu_st(next_st))
      desc%ndim = 0
      desc%size = (desc%type+3)/4
      !
      ! Implicit formatting
    elseif  (line(ifirst:ifirst).eq.quote) then
      call sic_expand(argum,line,ifirst,ilast,parg,error)
      if (error) return
      next_st = next_st+1
      argu_st(next_st) = argum(1:parg)
      desc%type = parg
      desc%readonly = .false.
      desc%addr = locstr(argu_st(next_st))
      desc%ndim = 0
      desc%size = (desc%type+3)/4
      !
      ! Variable or expression
    else
      var = line(ifirst:ilast)
      parg = ilast-ifirst+1
      call sic_upcase (var,parg)
      ! call sic_descriptor (var,desc,found)  ! Under check, this is not obvious
      call sic_materialize (var,desc,found)    ! most likely allow transposition ?
      !
      ! Variable
      if (found) then
        return
      else
        !
        ! Scalar expression
        if (sicprecis.eq.fmt_r8) then
          call sic_math_dble (var,ilast-ifirst+1,r8,error)
          if (error) return
          next_arg = next_arg + 1
          desc%type = fmt_r8
          desc%readonly = .false.
          argu_r8(next_arg) = r8
          desc%addr = locwrd(argu_r8(next_arg))
          desc%size = 2
          !
        elseif (sicprecis.eq.fmt_r4) then
          call sic_math_real (var,ilast-ifirst+1,r4,error)
          if (error) return
          next_arg = next_arg + 1
          desc%type = fmt_r4
          desc%readonly = .false.
          argu_r4(next_arg) = r4
          desc%addr = locwrd(argu_r4(next_arg))
          desc%size = 1
          !
        elseif (sicprecis.eq.fmt_i8) then
          call sic_math_long (var,ilast-ifirst+1,i8,error)
          if (error) return
          next_arg = next_arg + 1
          desc%type = fmt_i8
          desc%readonly = .false.
          argu_i8(next_arg) = i8
          desc%addr = locwrd(argu_i8(next_arg))
          desc%size = 2
          !
        else
          call sic_message(seve%e,rname,'Internal error: unsupported precision')
          error = .true.
          return
        endif
        desc%ndim = 0            ! Scalar
        desc%dims(:) = 0
        desc%status = program_defined
      endif
    endif
    !
    ! Logical arrays or scalar
  elseif  (argtyp.eq.fmt_l) then
    if (line(ifirst:ifirst).eq.'"') then
      !
      ! "..." is a Character String
      call sic_message(seve%e,rname,'Argument mismatch')
      error = .true.
      return
    elseif  (line(ifirst:ifirst).eq.quote) then
      !
      ! '...' is a scalar expression
      ifirst = ifirst+1
      ilast = ilast-1
      var = line(ifirst:ilast)
      parg = ilast-ifirst+1
      call sic_upcase (var,parg)
      call sic_math_logi (var,parg,l,error)
      if (error) return
      next_arg = next_arg + 1
      argu_l4(next_arg) = l
      desc%type = argtyp
      desc%readonly = .false.
      desc%addr = locwrd(argu_l4(next_arg))
      desc%ndim = 0              ! Scalar
      desc%dims(:) = 0
      desc%size = 1
      desc%status = program_defined
    else
      !
      ! Try a logical variable
      var = line(ifirst:ilast)
      parg = ilast-ifirst+1
      call sic_upcase (var,parg)
      ! call sic_descriptor (var,desc,found)  ! Under check, this is not obvious
      call sic_materialize (var,desc,found)    ! most likely allow transposition ?
      if (found) then
        if (desc%type.ne.fmt_l) then
          call sic_message(seve%e,rname,'Variable type mismatch')
          error = .true.
          return
        endif
      else
        !
        ! Try a logical expression (scalar)
        call sic_math_logi (var,parg,l,error)
        if (error) return
        next_arg = next_arg + 1
        argu_l4(next_arg) = l
        desc%type = argtyp
        desc%readonly = .false.
        desc%addr = locwrd(argu_l4(next_arg))
        desc%ndim = 0            ! Scalar
        desc%dims(:) = 0
        desc%size = 1
        desc%status = program_defined
      endif
    endif
    ! Real arrays or scalar
  elseif  (argtyp.lt.0) then
    if (line(ifirst:ifirst).eq.'"') then
      !
      ! "..." is a Character String
      call sic_message(seve%e,rname,'Argument mismatch')
      error = .true.
      return
    elseif  (line(ifirst:ifirst).eq.quote) then
      !
      ! '...' is a scalar expression
      ifirst = ifirst+1
      ilast = ilast-1
      desc%type = argtyp
      desc%readonly = .false.
      if (desc%type.eq.fmt_r8) then
        call sic_math_dble (line(ifirst:ilast),ilast-ifirst+1,r8,error)
        if (error) return
        next_arg = next_arg + 1
        argu_r8(next_arg) = r8
        desc%addr = locwrd(argu_r8(next_arg))
        desc%size = 2
      elseif (desc%type.eq.fmt_r4) then
        call sic_math_real (line(ifirst:ilast),ilast-ifirst+1,r4,error)
        if (error) return
        next_arg = next_arg + 1
        argu_r4(next_arg) = r4
        desc%addr = locwrd(argu_r4(next_arg))
        desc%size = 1
      elseif (desc%type.eq.fmt_i4) then
        call sic_math_inte (line(ifirst:ilast),ilast-ifirst+1,i4,error)
        if (error) return
        next_arg = next_arg + 1
        argu_i4(next_arg) = i4
        desc%addr = locwrd(argu_i4(next_arg))
        desc%size = 1
      elseif (desc%type.eq.fmt_i8) then
        call sic_math_long (line(ifirst:ilast),ilast-ifirst+1,i8,error)
        if (error) return
        next_arg = next_arg + 1
        argu_i8(next_arg) = i8
        desc%addr = locwrd(argu_i8(next_arg))
        desc%size = 2
      else
        call sic_message(seve%e,rname,'Argument type mismatch')
        error = .true.
        return
      endif
      desc%ndim = 0              ! Scalar
      desc%dims(:) = 0
      desc%status = program_defined
    else
      var = line(ifirst:ilast)
      ! call sic_descriptor (var,tmp,found)  ! Under check, this is not obvious
      call sic_materialize (var,tmp,found) ! most likely allow transposition ?
      !
      ! Variable
      if (found) then
        ! Check variable type for CODE = 1
        if (code.eq.1) then
          if (tmp%type.ne.argtyp) then
            call sic_message(seve%e,rname,'Variable type mismatch')
            error = .true.
            return
          else
            desc = tmp
          endif
        else
          ! Else incarnate
          call sic_incarnate(argtyp,tmp,desc,error)
          ! And free temporary variable (if any, due to transposition) if incarnation differ
          if (tmp%type.ne.argtyp) call sic_volatile(tmp)
          if (error) then
            call sic_message(seve%e,rname,'Variable type mismatch')
            return
          endif
        endif
      elseif  (code.ne.1) then
        !
        ! Scalar expression, valid only for Incarnation
        desc%type = argtyp
        desc%readonly = .false.
        if (argtyp.eq.fmt_r8) then
          call sic_math_dble (line(ifirst:ilast),ilast-ifirst+1,r8,error)
          if (error) return
          next_arg = next_arg + 1
          argu_r8(next_arg) = r8
          desc%addr = locwrd(argu_r8(next_arg))
          desc%size = 2
        elseif (argtyp.eq.fmt_r4) then
          call sic_math_real (line(ifirst:ilast),ilast-ifirst+1,r4,error)
          if (error) return
          next_arg = next_arg + 1
          argu_r4(next_arg) = r4
          desc%addr = locwrd(argu_r4(next_arg))
          desc%size = 1
        elseif (argtyp.eq.fmt_i4) then
          call sic_math_inte (line(ifirst:ilast),ilast-ifirst+1,i4,error)
          if (error) return
          next_arg = next_arg + 1
          argu_i4(next_arg) = i4
          desc%addr = locwrd(argu_i4(next_arg))
          desc%size = 1
        elseif (argtyp.eq.fmt_i8) then
          call sic_math_long (line(ifirst:ilast),ilast-ifirst+1,i8,error)
          if (error) return
          next_arg = next_arg + 1
          argu_i8(next_arg) = i8
          desc%addr = locwrd(argu_i8(next_arg))
          desc%size = 2
        else
          call sic_message(seve%e,rname,'Argument type mismatch')
          error = .true.
          return
        endif
        desc%ndim = 0            ! Scalar
        desc%dims(:) = 0
        desc%status = program_defined
      else
        ! Cannot return a descriptor for an expression
        call sic_message(seve%e,rname,'No such variable '//var(1:10)//'...')
        error = .true.
      endif
    endif
    !
    ! Characters
  else
    !
    ! Characters with no expand ("As Is")
    if (line(ifirst:ifirst).eq.'"') then
      !            CALL SIC_SHAPE(ARGUM,LINE,IFIRST,ILAST,PARG,ERROR)
      if (code.eq.1) then
        var = line(ifirst:ilast)
        call sic_message(seve%e,rname,'No such variable '//var(1:16)//'...')
        error = .true.
        return
      else
        call sic_expand(argum,line,ifirst,ilast,parg,error)
        if (error) return
        next_st = next_st+1
        argu_st(next_st) = argum(1:parg)
        desc%type = parg
        desc%readonly = .false.
        desc%addr = locstr(argu_st(next_st))
        desc%ndim = 0
        desc%size = (desc%type+3)/4
      endif
      !
      ! Implicit formatting ('...')
    elseif  (line(ifirst:ifirst).eq.quote) then
      if (code.eq.1) then
        var = line(ifirst:ilast)
        call sic_message(seve%e,rname,'No such variable '//var(1:16)//'...')
        error = .true.
        return
      else
        call sic_expand(argum,line,ifirst,ilast,parg,error)
        if (error) return
        next_st = next_st+1
        argu_st(next_st) = argum(1:parg)
        desc%type = parg
        desc%readonly = .false.
        desc%addr = locstr(argu_st(next_st))
        desc%ndim = 0
        desc%size = (desc%type+3)/4
      endif
      !
      ! Else, must be a character variable
    else
      var = line(ifirst:ilast)
      parg = ilast-ifirst+1
      call sic_descriptor (var,desc,found) ! Checked: do not transpose
      if (found) then
        if (desc%type.le.0) then
          call sic_message(seve%e,rname,'Argument type mismatch')
          error = .true.
          return
        endif
      else
        call sic_message(seve%e,rname,'No such variable '//var(1:16)//'...')
        error = .true.
        return
      endif
    endif
  endif
  !
101 format('Missing argument number ',i3,' of Command ',a,a,a)
102 format('Missing argument number ',i3,' of Option ',a)
104 format('Option ',i3,' or argument ',i3,' out of bounds')
end subroutine sic_desc_inca
