subroutine get_resu (form,dimr,noper,ioper,operand,iresul,error)
  use sic_interfaces, except_this=>get_resu
  use gildas_def
  use sic_dependencies_interfaces
  use sic_expressions
  use sic_dictionaries
  use sic_types
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ private
  !  Get a new pointer to descriptor of result.
  !---------------------------------------------------------------------
  integer :: form                           ! Format of result (R4, R8, L)
  integer(kind=size_length) :: dimr         ! Dimension of result
  integer :: noper                          ! Number of operands
  integer :: ioper(noper)                   ! Pointer to operand descriptors
  type(sic_descriptor_t) :: operand(0:maxoper)  ! List of operands
  integer :: iresul                         ! Pointer to result descriptor
  logical :: error                          ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='MTH'
  integer :: i,ier
  integer(kind=size_length) :: size
  !
  error = .false.
  size = dimr
  if (form.eq.fmt_r8 .or. form.eq.fmt_i8) size=2*size
  !
  ! In final result if possible
  if (operand(0)%type.eq.form .and. operand(0)%size.eq.size) then
    if (operand(0)%status.eq.free_operand) then
      iresul = 0
      operand(0)%status = interm_operand
      return
    endif
    !
    ! Then among operands (of this operation) that point to the final result
    do i=1,noper
      if (operand(ioper(i))%status.eq.interm_operand) then
        iresul = ioper(i)
        return
      endif
    enddo
  endif
  !
  ! Then among the other operands of this operation.
  do i=1,noper
    if (operand(ioper(i))%status.eq.scratch_operand .and.  &
        size.eq.operand(ioper(i))%size) then
      iresul = ioper(i)
      return
    endif
  enddo
  !
  ! Then among remaining free operands
  do i=1,maxoper
    if (operand(i)%status.eq.free_operand .and. size.eq.operand(i)%size) then
      iresul = i
      operand(i)%status = scratch_operand
      return
    endif
  enddo
  ! Allocate memory if nothing else works
  do i=1,maxoper
    if (operand(i)%status.eq.empty_operand) then
      ier = sic_getvm (size,operand(i)%addr)
      if (ier.ne.1) then
        call sic_message(seve%e,rname,'Memory allocation failure')
        error = .true.
        return
      endif
      operand(i)%type = form
      operand(i)%readonly = .false.
      operand(i)%ndim = 1
      operand(i)%dims(1) = dimr
      operand(i)%size = size
      operand(i)%status = scratch_operand
      iresul = i
      return
    endif
  enddo
  !
  ! Else apologize
  call sic_message(seve%e,rname,'Too many operands')
  error = .true.
end subroutine get_resu
!
subroutine free_oper (form,dimr,noper,ioper,operand,iresul,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>free_oper
  use gildas_def
  use sic_expressions
  use sic_dictionaries
  use sic_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Free useless operands and move pointers to current result.
  !---------------------------------------------------------------------
  integer :: form                           ! Format of result (R4, R8, L)
  integer(kind=size_length) :: dimr         ! Dimension of result
  integer :: noper                          ! Number of operands
  integer :: ioper(noper)                   ! Pointer to operand descriptors
  type(sic_descriptor_t) :: operand(0:maxoper)  ! List of operands
  integer :: iresul                         ! Pointer to result descriptor
  logical :: error                          ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='FREE_OPER'
  integer :: i
  character(len=message_length) :: mess
  !
  do i=1,noper
    if (operand(ioper(i))%status.eq.scratch_operand) then
      if (ioper(i).ne.iresul) then
        operand(ioper(i))%status = free_operand
        ! write (6,*) 'Freed operand ',IOPER(I)
      endif
    elseif (operand(ioper(i))%status.eq.empty_operand) then
      write (mess,*) 'Operand ',ioper(i),'was EMPTY'
      call sic_message(seve%u,rname,mess)
      write (mess,*) 'Operand ',ioper(i),'was READ'
      call sic_message(seve%u,rname,mess)
      ! Used result array a intermediate storage, nothing wrong with that
    elseif (operand(ioper(i))%status.eq.interm_operand) then
      continue
      ! Static operand, do nothing for this one
    elseif (operand(ioper(i))%status.eq.user_defined     .or.  &
            operand(ioper(i))%status.eq.readonly_operand .or.  &
            operand(ioper(i))%status.eq.program_defined) then
      continue
    else
      write (mess,*) 'Unknown operand status',operand(ioper(i))%status, &
        ' for ',ioper(i)
      call sic_message(seve%u,rname,mess)
    endif
  enddo
  !
  ! Assign result : Free IOPER(2) descriptor and
  ! move result descriptor in IOPER(2). Could be optimised
  ! by transmitting back pointers, or at least pushing
  ! the descriptor to an EMPTY place to avoid wasting memory.
  !
  operand(iresul)%type = form
  operand(iresul)%readonly = .false.
  if (ioper(1).ne.iresul) then
    if ( operand(ioper(1))%status.eq.free_operand ) then
      call free_vm (operand(ioper(1))%size,operand(ioper(1))%addr)
      ! write(6,*) 'Deleted FREE operand ',IOPER(1)
      ! Should never happen given the above code...
    elseif (operand(ioper(1))%status.eq.scratch_operand) then
      call free_vm (operand(ioper(1))%size,operand(ioper(1))%addr)
      write(mess,*) 'Deleted SCRATCH operand ',ioper(1)
      call sic_message(seve%u,rname,mess)
    endif
    operand(ioper(1)) = operand(iresul)
    if (iresul.ne.0) then
      operand(iresul)%type = 0
      operand(iresul)%readonly = .false.
      operand(iresul)%addr = 0
      operand(iresul)%ndim = 0
      operand(iresul)%dims(:) = 0
      operand(iresul)%size = 0
      operand(iresul)%status = empty_operand
    endif
  endif
  ! write(6,*) 'Called FREE_OPER'
end subroutine free_oper
