subroutine compare_comm(line,error)
  use gkernel_interfaces
  use gkernel_types
  use gbl_message
  use imager_interfaces, only : map_message
  !-------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER
  !   Support for command COMPARE Left Right [/DIRECTORY <top]  
  !   and COMPARE ? or COMPARE ??
  !!
  !-------------------------------------------------------------------
  character(len=*), intent(inout) :: line    !! Command line
  logical, intent(inout) :: error            !! Error flag
  !
  ! Constants
  integer, parameter :: o_dir=1
  character(len=*), parameter :: rname='COMPARE'
  integer, parameter :: mvoc=4
  character(len=8) :: argum, vocab(mvoc), key
  data vocab /'LEFT','RIGHT','JOINT','EACH'/
  !
  ! Local
  type(sic_descriptor_t) :: ldesc, rdesc
  character(len=256) :: chain
  character(len=64), save :: cleft, cright
  character(len=4) :: trail
  integer :: i, n, narg, ikey
  logical, save :: todo=.true.
  logical, save :: is2d=.false.
  logical :: found, do_insert
  !
  ! Code
  do_insert = (sic_lire().eq.0)
  narg = sic_narg(0)
  trail = ' '
  if (narg.eq.1) then
    call sic_ch(line,0,1,chain,i,.true.,error)
    if (error) return
    if ((chain.eq.'?').or.(chain.eq.'??')) then
      call exec_program('@ i_compare '//chain)
      return
    else
      call sic_ke(line,0,1,argum,n,.true.,error)
      call sic_ambigs (rname,argum,key,ikey,vocab,mvoc,error)
      if (error) return
      trail(2:3) = key(1:2)
    endif
  endif
  !
  if ((narg.gt.1).or.todo) then
    todo = .true.
    if (narg.gt.2) then
      call sic_ke(line,0,3,argum,n,.true.,error)
      call sic_ambigs (rname,argum,key,ikey,vocab,mvoc,error)
      if (error) return
      trail(2:3) = key(1:2)
    endif
    ! Define CMP_LEFT or CMP_RIGHT if any argument is a File
    ! or dataset imported in Cube
    call compare_comm_args(line,cleft,cright,error)
    if (error) return
    !
    call sic_descriptor(cleft,ldesc,found)
    if ((ldesc%ndim.eq.3).and.(ldesc%dims(3).eq.1)) ldesc%ndim = 2
    call sic_descriptor(cright,rdesc,found)
    if ((rdesc%ndim.eq.3).and.(rdesc%dims(3).eq.1)) rdesc%ndim = 2
    !
    if ( (ldesc%ndim.eq.2).and.(rdesc%ndim.eq.2) ) then
      is2d = .true.
    else 
      is2d = .false.
    endif
    if (sic_varexist('CMP%FIRST')) call exec_program('LET CMP%FIRST YES')
    !!Print *,'Is 2D ? ',is2d,' Left ',ldesc%dims(1:ldesc%ndim),' Right ',rdesc%dims(1:rdesc%ndim)
    !
  endif
  !
  todo = .false.
  call get_topdir(line,o_dir)
  call exec_program('@ p_clear')
  !
  if (is2d) then  
    call exec_program('@ p_compare_map '//trim(cleft)//' '//trim(cright)//trail)
  else
    call exec_program('@ p_compare_sub '//trim(cleft)//' '//trim(cright)//trail)
  endif
  !
  if (do_insert) call sic_insert_log(line)
end subroutine compare_comm
!
subroutine compare_comm_args(line,cleft,cright,error)
  use gkernel_interfaces
  use gkernel_types
  use gbl_message
  use imager_interfaces, only : map_message
  !-------------------------------------------------------------------
  ! @ private
  !*
  ! IMAGER -- Support for command COMPARE Left Right [/DIRECTORY <top]
  !   and COMPARE ? or COMPARE ??
  !!
  !-------------------------------------------------------------------
  character(len=*), intent(inout) :: line    !! Command line
  character(len=*), intent(out) :: cleft     !! Left variable name
  character(len=*), intent(out) :: cright    !! Right variable name
  logical, intent(out) :: error              !! Error flag
  !
  ! Constants
  integer, parameter :: o_dir=1
  character(len=*), parameter :: rname='COMPARE'
  !
  ! Local ---
  character(len=filename_length) :: leftfile, rightfile
  integer :: n, ileft, iright
  type(gildas), save :: hleft, hright
  !
  ! Code ----
  call sic_ch(line,0,1,leftfile,n,.true.,error)
  if (error) return
  cleft = 'CMP_LEFT'
  call sub_load_var(rname,line,leftfile,cleft,ileft,error)
  if (error) return
  !
  call sic_ch(line,0,2,rightfile,n,.true.,error)
  if (error) return
  cright = 'CMP_RIGHT'
  call sub_load_var(rname,line,rightfile,cright,iright,error)
  if (error) return
  !
  if (ileft.eq.2) call read_and_map(cleft,hleft,leftfile,error)
  if (iright.eq.2) call read_and_map(cright,hright,rightfile,error)
end subroutine compare_comm_args
!
subroutine read_and_map(name,head,file,error)
  use gkernel_types
  use gbl_message
  use gkernel_interfaces
  use imager_interfaces, only : map_message
  !*
  ! IMAGER -- Utility routine 
  !   Read a data cube and define an associated SIC variable
  !!
  character(len=*), intent(in) :: name      !! SIC Variable name
  character(len=*), intent(inout) :: file   !! Data file
  type(gildas), intent(inout) :: head       !! Data cube header
  logical, intent(out) :: error             !! Logical error flag
  !
  character(len=*), parameter :: rname='COMPARE'
  logical :: err
  integer :: ier
  !
  err = .false.
  error = .false.
  ier = 0
  if (associated(head%r3d)) deallocate(head%r3d,stat=ier)
  if (ier.ne.0) call map_message(seve%w,rname,'Deallocation error')
  call gildas_null(head)
  call gdf_read_gildas(head, file,' ', error, data=.false.)
  if (error) return
  !
  if (product(head%gil%dim(4:)).gt.1) then
    call map_message(seve%e,rname,'Only Maps and Cubes supported')
    call gdf_close_image(head,err)
    error = .true.
    return
  endif
  !
  allocate(head%r3d(head%gil%dim(1),head%gil%dim(2),   &
   &        head%gil%dim(3)),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%w,rname,'Data Allocation error')
    call gdf_close_image(head,err)
    error = .true.
    return
  endif
  call gdf_read_data(head,head%r3d,error)
  call gdf_close_image(head,err)
  if (error) return
  if (product(head%gil%dim(3:)).le.1) head%gil%ndim = 2
  call sic_mapgildas (name,head,error,head%r3d)
  !  
end subroutine read_and_map
!
subroutine sub_load_var(comm,line,arg,varname,iscode,error)
  use gkernel_interfaces
  use gkernel_types
  use gbl_message
  use clean_default
  use imager_interfaces, only : map_message
  !-------------------------------------------------------------------
  ! @ private
  !* 
  ! IMAGER -- Support for (implicit) LOAD command
  !
  !     "Load"  ?|File.ext|InVAR|CubeName|CubeNumber (as) OutVAR
  !
  !   Support for command COMPARE, VIEW, SHOW, etc...
  !!
  !-------------------------------------------------------------------
  character(len=*), intent(in) :: comm       !! Caller
  character(len=*), intent(inout) :: line    !! Command line
  character(len=*), intent(inout) :: arg     !! Argument
  character(len=*), intent(inout) :: varname !! Desired / Returned name
  integer, intent(out) :: iscode             !! 0-4
  logical, intent(out) :: error              !! Error flag
  !
  ! Constants 
  integer, parameter :: is_help=0
  integer, parameter :: is_varname=1
  integer, parameter :: is_filename=2
  integer, parameter :: is_cubename=3
  integer, parameter :: is_cubeid=4
  character(len=*), parameter :: rname='LOAD'
  character(len=8) :: name(4)
  data name /'VARIABLE','FILE','CUBENAME','CUBEID'/
  !
  ! Local ---
  character(len=filename_length) :: chain
  character(len=filename_length) :: file
  character(len=32) :: argu
  integer :: n,na,ier,nline,lc
  !
  logical :: found
  !
  ! Code ----
  error = .false.
  iscode = is_help
  if (arg.eq.'?'.or.arg.eq.'??') return
  !
  chain = arg
  n = len_trim(chain)
  !
  if (index(chain,'.').ne.0) then
    !
    ! Discard the default image
    if (sic_varexist(varname)) call sic_delvariable(varname,.false.,error)
    found = sic_findfile(chain,file,' ',' ')
    if (.not.found) then
      call map_message(seve%e,rname,'No such file '//trim(file))
      error = .true.
      return
    else
      iscode = is_filename
      arg = file        ! Return the file name
    endif
  else if (chain(n:n).eq.':') then
    iscode = is_cubename
    file = '@ cube_load '//chain(1:n-1)//' '//trim(varname)
  else
    call sic_upper(chain)
    lc = len_trim(chain)
    if (chain(lc:lc).eq.'%') then
      ! A structure, with possibly %DATA array variable
      if (sic_varexist(chain(lc-1:lc-1))) then
        varname = chain
        iscode = -1
        Print *,chain(1:lc)//'%DATAs exists'
      endif
    else if (sic_varexist(chain)) then
      iscode = is_varname
      varname = chain
    else
      read(chain,*,iostat=ier) na
      if ((ier.eq.0).and.(na.gt.0)) then
        ! This is a positive integer, possibly a Cube index
        write(file,'(A,I0,1X,A)') '@ cube_load +',na,trim(varname)
        iscode = is_cubeid
      else
        error = .false.
      endif
    endif
  endif
  !
  select case (iscode)
  case (0)
    call map_message(seve%e,comm,'No such Buffer or SIC variable ' &
    & //trim(arg))
    error =.true.
  case (is_cubename,is_cubeid)
    call exec_program(file)
    ! Reset the command line pointers
    nline = len_trim(line)
    argu = comm
    call sic_analyse(argu,line,nline,error) ! Reset command line pointers
    error = ImagerError
  end select
  if (error) return
  call map_message(seve%i,comm,'Loading '//trim(arg)//' as a '//name(iscode)//' '//trim(varname))
end subroutine sub_load_var
