subroutine gridder (line,error)
  use gildas_def
  use gbl_format
  use gbl_message
  use sic_types
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>gridder
  use greg_kernel
  use greg_rg
  use greg_xyz
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !  RANDOM_MAP Grid_descriptor[S]
  !  1    [/BLANKING Bval]
  !  2    [/NEIGHBOURS N]
  !  3    [/TRIANGLES]
  !  4    [/EXTRAPOLATE]
  !  5    [/VARIABLE]
  !  6    [/SKIP [TRIANGULATION] [INTERPOLATION]]
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   !
  logical,          intent(inout) :: error  ! Logical error flag
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='RANDOM_MAP'
  integer(kind=4), parameter :: optblan=1  ! /BLANKING
  integer(kind=4), parameter :: optneig=2  ! /NEIGHBOURS
  integer(kind=4), parameter :: opttria=3  ! /TRIANGLES
  integer(kind=4), parameter :: optextr=4  ! /EXTRAPOLATE
  integer(kind=4), parameter :: optvari=5  ! /VARIABLE
  integer(kind=4), parameter :: optskip=6  ! /SKIP
  integer(kind=4) :: igrad,ncp,mrand,nc,ier,iarg,iskip
  integer(kind=size_length) :: nmin,nmax
  real(kind=4) :: xdmin,xdmax,ydmin,ydmax,blank
  logical :: done,logran(7)
  character(len=80) :: chain
  character(len=20) :: argum,key
  !
  integer(kind=address_length) :: ipx,ipy,ipz
  integer(kind=address_length) :: my_addr_x,my_addr_y,my_addr_z
  integer(kind=4) :: my_nxy,form
  type(sic_descriptor_t), save :: xinca,yinca,zinca
  type(sic_descriptor_t) :: xdesc,ydesc,zdesc
  character(len=varname_length) :: var
  logical :: found,donex,donez
  real(kind=8) :: rxref,rxval,rxinc,ryref,ryval,ryinc
  integer(kind=4) :: nrx,nry
  integer(kind=size_length) :: ndp
  !
  real(kind=4), allocatable, save :: xd(:)
  real(kind=4), allocatable, save :: yd(:)
  real(kind=4), allocatable, save :: zd(:)
  real(kind=4), allocatable, save :: wk(:)
  integer(kind=4), allocatable, save :: iwk(:)
  !
  save xdmin,xdmax,ydmin,ydmax,blank
  save igrad,ncp,ndp
  ! Save
  save logran,mrand
  save ipx,ipy,ipz
  ! Data
  character(len=20), parameter :: rgmap='RGMAP'
  integer(kind=4), parameter :: nskip=2
  character(len=*), parameter :: skip(nskip) = (/ 'TRIANGULATION','INTERPOLATION' /)
  data mrand/0/,logran/7*.false./,igrad/40/,ncp/4/
  !
  ! RANDOM /VARIABLE VarX VarY VarZ
  if (sic_present(optvari,0)) then
    if (sic_narg(optvari).ne.3) then
      chain = '/VARIABLE option requires 3 arguments'
      call greg_message(seve%e,rname,chain)
      error = .true.
      return
    endif
    !
    call sic_ch (line,optvari,1,var,nc,.true.,error)
    found = .true.
    call sic_materialize(var,xdesc,found)
    if (.not.found) then
      chain = 'Unknown variable '//var
      call greg_message(seve%e,rname,chain)
      error = .true.
      return
    endif
    call sic_ch (line,optvari,2,var,nc,.true.,error)
    found = .true.
    call sic_materialize(var,ydesc,found)
    if (.not.found) then
      error = .true.
      chain = 'Unknown variable '//var
      call greg_message(seve%e,rname,chain)
      call sic_volatile(xdesc)   ! It may have been transposed...
      return
    endif
    call sic_ch (line,optvari,3,var,nc,.true.,error)
    found = .true.
    call sic_materialize(var,zdesc,found)
    if (.not.found) then
      error = .true.
      chain = 'Unknown variable '//var
      call greg_message(seve%e,rname,chain)
      call sic_volatile(xdesc)   ! It may have been transposed...
      call sic_volatile(ydesc)   ! It may have been transposed...
      return
    endif
    !
    form = fmt_r8
    call sic_incarnate(form,xdesc,xinca,error)
    call sic_incarnate(form,ydesc,yinca,error)
    call sic_incarnate(form,zdesc,zinca,error)
    !
    if (yinca%size.ne.xinca%size .or. xinca%size.ne.zinca%size) then
      call greg_message(seve%w,rname,'Arrays have different sizes')
    endif
    if (sic_notsamedesc(xdesc,xinca)) call sic_volatile(xdesc)
    if (sic_notsamedesc(ydesc,yinca)) call sic_volatile(ydesc)
    if (sic_notsamedesc(zdesc,zinca)) call sic_volatile(zdesc)
    !
    my_nxy = xinca%size/2
    my_addr_x = xinca%addr
    my_addr_y = yinca%addr
    my_addr_z = zinca%addr
  else
    my_nxy = nxy
    my_addr_x = locwrd(column_x)
    my_addr_y = locwrd(column_y)
    my_addr_z = locwrd(column_z)
  endif
  !
  ! Optimizations (/SKIP). See HELP RANDOM_MAP for details.
  donex = .false.
  donez = .false.
  do iarg=1,sic_narg(optskip)
    call sic_ke(line,optskip,iarg,argum,nc,.true.,error)
    if (error)  return
    call sic_ambigs(rname,argum,key,iskip,skip,nskip,error)
    if (error)  return
    select case (iskip)
    case (1)  ! TRIANGULATION
      donex = .true.
    case (2)  ! INTERPOLATION
      donez = .true.
    end select
  enddo
  !
  ! First copy the X, Y, Z arrays if not already done
  done = donex.and.donez
  if (.not.done .or. ndp.eq.0) then
    !
    ! Check arguments
    if (.not.sic_present(0,1)) then
      call greg_message(seve%e,rname,'Argument(s) required')
      error = .true.
      return
    endif
    if (my_nxy.le.4) then
      call greg_message(seve%e,rname,'Too few data points')
      error = .true.
      return
    endif
    !
    ! Compute Blanking value
    if (eblank.ge.0.) then
      blank = cblank
      call sic_r4 (line,optblan,1,blank,.false.,error)
      if (error) return
    else
      call sic_r4 (line,optblan,1,blank,.true.,error)
      if (error) then
        call greg_message(seve%e,rname,'No blanking value')
        return
      endif
    endif
    write(chain,'(A,1PG13.6)') 'Using blanking value ',blank
    call greg_message(seve%i,rname,chain)
    if (my_nxy.gt.mrand) then
      if (allocated(xd)) then
        deallocate(xd,yd,zd,wk,iwk)
        donex = .false.
        donez = .false.
      endif
      ! NB: size of working buffers is inherited from older code but
      ! is completely obscur! Have to understand how gridran works...
      allocate(xd(my_nxy),yd(my_nxy),zd(my_nxy),  &
               wk(13*my_nxy),iwk(35*my_nxy),stat=ier)
      if (failed_allocate(rname,'XD, YD, ZD, WK, IWK buffers',ier,error))  return
      mrand = my_nxy
    endif
    !
    ipx = gag_pointer(my_addr_x,memory)
    ipy = gag_pointer(my_addr_y,memory)
    ipz = gag_pointer(my_addr_z,memory)
    !
    if (.not.donex) then
      call us8_to_int(memory(ipx),memory(ipy),xd,yd,my_nxy)
      logran(2) = .false.      ! Loaded
      logran(3) = .false.      ! Repeat
    endif
    if (.not.donez) then
      if (my_addr_z.eq.0) then
        call greg_message(seve%e,rname,'No Z data loaded')
        error = .true.
        return
      endif
      call r8tor4(memory(ipz),zd,my_nxy)
      logran(2) = .false.  ! Must reload the values
    endif
    ndp = my_nxy
  endif
  !
  ! Define optional actions
  logran(1) = sic_present(optextr,0)  ! Extrapolate
  logran(6) = .false.                 ! Extrema
  if (sic_present(optneig,0)) then    ! /NEIGHBOURS
    ncp = 4
    call sic_i4 (line,optneig,1,ncp,.false.,error)
    if (error) return
    ncp = min(max(2,ncp),8)
    logran(2) = .false.
    logran(3) = .false.
  else
    ncp = 4
  endif
  logran(5) = sic_present(opttria,0) ! /TRIANGLES
  logran(7) = .false.                ! /VALUES suppressed
  !
  ! Just plot additional values of existing data
  if (logran(2) .and. .not.sic_present(0,1)) then
    ! logran(2) = .true. => Reload not needed
    ! sic_present(0,1) = .false. => No argument i.e. grid not redefined
    call gridset(ncp,blank,logran)
    call gridran(xd,yd,zd,int(ndp,kind=4),wk,iwk,rg%data,drawg,relog,gwrite,error)
    return
  endif
  !
  ! Set the data structure
  call sic_ke (line,0,1,argum,nc,.true.,error)
  if (error) return
  if (argum(1:nc).eq.rgmap(1:nc)) then
    if (rg%status.eq.code_pointer_null) then
      call greg_message(seve%e,rname,'No reference map')
      error = .true.
      return
    endif
    rxinc = rg%xinc*gux
    ryinc = rg%yinc*guy
    rxref = rg%xref
    ryref = rg%yref
    rxval = gx1 + (rg%xval-gux1)*gux
    ryval = gy1 + (rg%yval-guy1)*guy
    logran(2) = .false.
    nrx = rg%nx
    nry = rg%ny
  else
    call sic_i4 (line,0,1,igrad,.true.,error)
    if (error) return
    if (igrad.lt.2) then
      call greg_message(seve%e,rname,'Too few grid points in X or Y')
      error = .true.
      return
    endif
    if (nrx.ne.igrad) logran(2) = .false.
    nrx = igrad
    igrad = nrx
    call sic_i4 (line,0,2,igrad,.false.,error)
    if (error) return
    if (igrad.lt.2) then
      call greg_message(seve%e,rname,'Too few grid points in X or Y')
      error = .true.
      return
    endif
    if (nry.ne.igrad) logran(2) = .false.
    nry = igrad
    call gr4_minmax (ndp,xd,0.0,-1.0,xdmin,xdmax,nmin,nmax)
    call gr4_minmax (ndp,yd,0.0,-1.0,ydmin,ydmax,nmin,nmax)
    rxinc = (xdmax-xdmin)/nrx
    ryinc = (ydmax-ydmin)/nry
    rxref = 0.5d0
    ryref = 0.5d0
    rxval = xdmin
    ryval = ydmin
  endif
  call gridini(nrx,rxref,rxval,rxinc,nry,ryref,ryval,ryinc)
  !
  ! Load Virtual memory for interpolated grid
  if (.not.logran(2)) then
    call reallocate_rgdata(nrx,nry,error)
    if (error)  return
  endif
  !
  ! CALL CONRAN(XD,YD,ZD,NDP,WK,IWK,SARRAY,ERROR)
  !
  call gridset(ncp,blank,logran)
  call gridran(xd,yd,zd,int(ndp,kind=4),wk,iwk,rg%data,drawg,relog,gwrite,error)
  ! Check error code, and abort if set
  if (error) return
  !
  ! Everything OK
  logran(2) = .true.           ! Loaded
  logran(3) = .true.           ! Repeat
  !
  if (axis_xlog) then
    rg%xval = lux + (rxval - gx1)/gux
    call greg_message(seve%w,rname,'X Logarithmic scale converted to linear')
    call greg_message(seve%w,rname,'Use LIMITS /RGDATA to process map')
  else
    rg%xval = gux1 + (rxval - gx1)/gux
  endif
  rg%xref = rxref
  rg%xinc = rxinc/gux
  if (axis_ylog) then
    rg%yval = luy + (ryval - gy1)/guy
    call greg_message(seve%w,rname,'Y Logarithmic scale converted to linear')
    call greg_message(seve%w,rname,'Use LIMITS /RGDATA to process map')
  else
    rg%yval = guy1 + (ryval - gy1)/guy
  endif
  rg%yref = ryref
  rg%yinc = ryinc/guy
end subroutine gridder
!
subroutine drawg(x,y)
  use greg_interfaces, except_this=>drawg
  !---------------------------------------------------------------------
  ! @ private-mandatory (because symbol is used elsewhere)
  !---------------------------------------------------------------------
  real :: x                         !
  real :: y                         !
  call gdraw(y,x)
end subroutine drawg
!
subroutine relog(x,y)
  use greg_interfaces, except_this=>relog
  !---------------------------------------------------------------------
  ! @ private-mandatory (because symbol is used elsewhere)
  !---------------------------------------------------------------------
  real :: x                         !
  real :: y                         !
  call grelocate(y,x)
end subroutine relog
