subroutine exec_task (buffer)
  use gildas_def
  use gbl_message
  use sic_interfaces, except_this=>exec_task
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  character(len=*) :: buffer        !
  ! Local
  character(len=*), parameter :: rname='TASK'
  character(len=commandline_length) :: line
  character(len=12) :: lang
  character(len=12) :: comm
  logical :: error
  integer :: icode,ocode
  !
  line = buffer
  icode = code_exec
  goto 10
  !
entry play_task(buffer)
  line = buffer
  icode = code_play
  goto 10
  !
entry enter_task
  icode = code_enter
  goto 10
  !
10 continue
  !
  error = .false.
  do while(.true.)
    call sic_run (line,lang,comm,error,icode,ocode)
    if (ocode.ne.code_next) return
    if (lang.eq.'TASK') then
      call run_task(line,comm,error)
    elseif (lang.eq.'SIC') then
      call run_sic(line,comm,error)
    else
      call sic_message(seve%e,rname,'Language invalid in this context '//lang)
      error = .true.
    endif
    icode = code_run
  enddo
end subroutine exec_task
!
subroutine run_task (line,comm,error)
  use sic_interfaces, except_this=>run_task
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private-mandatory (because symbol is used elsewhere)
  ! Dispatch the command line
  ! Arguments :
  ! LINE  C*(*) Command line      Input/Output
  ! COMM  C*(*) Command       Input
  !---------------------------------------------------------------------
  character(len=*)              :: line   !
  character(len=*)              :: comm   !
  logical,          intent(out) :: error  ! Logical error flag
  !
  call sic_message(seve%c,'TASK',line)
  !
  error = .false.
  if (comm.eq.'GO') then
    tabort = .false.
    if (x_window) then
      call xgag_go(line,tabort)
      call xgag_wait
      call xgag_end(1,tabort)
      call end_dialog
    endif
  elseif (comm.eq.'CHARACTER') then
    call tchars (line,error)
  elseif (comm.eq.'FILE') then
    call tfiles (line,error)
  elseif (comm.eq.'REAL') then
    call treals (line,error)
  elseif (comm.eq.'INTEGER') then
    call tintes (line,error)
  elseif (comm.eq.'LOGICAL') then
    call tlogis (line,error)
  elseif (comm.eq.'VALUES') then
    call tvalue (line,error)
  elseif (comm.eq.'WRITE') then
    call twrite (line,error)
  elseif (comm.eq.'HELP') then
    call thelp (line,error)
  elseif (comm.eq.'MORE') then
    call tmore (line,error)
  else
    call sic_message(seve%e,'TASK','No code for '//comm)
    error = .true.
  endif
end subroutine run_task
!
function err_task (dummy)
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  logical :: err_task               !
  logical :: dummy                  !
  err_task = .false.
end function err_task
!
subroutine load_task
  use sic_interfaces, except_this=>load_task
  use gildas_def
  use sic_interactions
  use gbl_message
  use sic_dependencies_interfaces
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  ! Local
  character(len=*), parameter :: vers='3.0    10-Apr-2016   S.Guilloteau'
  character(len=4) :: cccc
  integer :: ier
  ! Language
  integer, parameter :: mtask=19
  character(len=12) :: vocab(mtask)
  ! Does order matter ?
  data vocab /                                        &
    '#GO',                                            &
    ' HELP',                                          &
    ' WRITE',                                         &
    ' LOGICAL',                                       &
    ' INTEGER',   '/RANGE','/INDEX','/CHOICE',        &
    ' REAL',      '/RANGE','/SEXAGESIMAL','/CHOICE',  &
    ' CHARACTER', '/CHOICE',                          &
    ' FILE',      '/OLD','/NEW',                      &
    ' MORE',     ' VALUES' /
  !
  call sic_begin('TASK','GAG_HELP_TASK',-mtask,vocab,vers,run_task,err_task)
  ier = sic_getlun (tlun)
  if (mod(ier,2).eq.0) then
    call sic_message(seve%f,'TASK','Error allocating unit for parameter file')
    call sysexi (fatale)
  endif
  ! Retrieves the default extension for tasks names on the current system
  call executable_extension(cccc)
  ! Add a leading point if extension is not nil.
  if (cccc.ne.' ') then
    taskext = '.'//cccc
  else
    taskext = ' '
  endif
end subroutine load_task
!
subroutine exit_task(error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>exit_task
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  !  Clean the TASK-related components
  !---------------------------------------------------------------------
  logical, intent(inout) :: error  ! Logical error flag
  !
  call sic_frelun(tlun)
  !
end subroutine exit_task
!
subroutine treals (line,error)
  use sic_dependencies_interfaces
  use gildas_def
  use sic_interactions
  use sic_interfaces, except_this=>treals
  use sic_types
  use gbl_format
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! GILDAS  Support routine for command
  ! TASK\REAL "Prompt text" Name = [Value]
  !
  ! Define a parameter of specified type (Real, Integer, Logical,
  ! Character, or File) name, and assign it a value if specified.
  ! Otherwise, prompt with the text for a value.
  !---------------------------------------------------------------------
  character(len=*)                :: line   !
  logical,          intent(inout) :: error  !
  ! Local
  character(len=*), parameter :: rname='TASK'
  integer :: nline,iarg,ntype,nc,ndim,i,j,np,iopt,istat
  integer(kind=index_length) :: dim(1)
  integer :: status,ier,jopt
  character(len=12) :: comm
  character(len=12) :: ctype
  character(len=32) :: name,cname
  character(len=4) :: equal
  character(len=80) :: invite
  logical :: translate,found
  integer :: lt,nk,type
  character(len=commandline_length) :: chain
  character(len=filename_length) :: expr,string
  character(len=64) :: variab
  real(8) :: r8
  type(sic_descriptor_t) :: descr
  integer(kind=address_length) :: ipnt
  integer(kind=1) :: membyt(1)
  !
  ntype = 1
  translate = .false.  ! Not used in this context
  ctype = 'REAL'
  iopt = 0
  if (sic_present(1,0)) then   ! /RANGE
    jopt = 1
  else
    jopt = 0
  endif
  if (sic_present(2,0)) then
    if (jopt.eq.1) goto 99
    jopt=2                     ! /SEXAGESIMAL
  endif
  if (sic_present(3,0)) then
    if (jopt.gt.0) goto 99
    jopt=3                     ! /CHOICE
  endif
  goto 10
  !
entry tintes (line,error)
  ntype = 2
  translate = .false.  ! Not used in this context
  ctype = 'INTEGER'
  iopt = 0
  if (sic_present(1,0)) then   ! /RANGE
    jopt = 1
  else
    jopt = 0
  endif
  if (sic_present(2,0)) then
    if (jopt.eq.1) goto 99
    jopt=2                     ! /INDEX
  endif
  if (sic_present(3,0)) then
    if (jopt.gt.0) goto 99
    jopt=3                     ! /CHOICE
  endif
  goto 10
  !
entry tlogis (line,error)
  ntype = 3
  translate = .false.  ! Not used in this context
  ctype = 'LOGICAL'
  iopt = 0
  jopt = 0
  goto 10
  !
entry tchars (line,error)
  ntype = 4
  translate = .false.
  ctype = 'CHARACTER'
  iopt = 0
  if (sic_present(1,0)) then   ! /CHOICE
    jopt = 1
  else
    jopt = 0
  endif
  goto 10
  !
entry tvalue (line,error)
  ntype = 5  ! Write a string
  translate = .false.
  ctype = 'VALUES'
  iopt = 0
  jopt = 0
  goto 10
  !
entry tfiles (line,error)
  ! Similar to characters, but logical names are translated.
  istat= 0
  ntype = 4
  translate = .true.
  ctype = 'FILE'
  jopt = 0
  ! OLD files
  iopt = 0
  if (sic_present(1,0)) then
    if (.not.sic_present(0,2)) iopt = 1
    istat = -1
    ! NEW files
  elseif (sic_present(2,0)) then
    if (.not.sic_present(0,2)) iopt = 2
    istat = +1
  else
    istat = 0
  endif
  goto 10
  !
  ! Get parameter name
10 if (npar.ge.mpar) goto 97
  call sic_ke (line,iopt,2,name,nc,.true.,error)
  if (error) return
  cname = name
  i = index(name,'[')
  if (i.ne.0) then
    if (ntype.eq.5) then
      call sic_message(seve%e,rname,'VALUES cannot have dimensions '//name)
      error = .true.
      return
    endif
    !
    j = index(name,']')
    !
    ! the following line forces a correct read with the I20 edit descriptor on IBM
    ! (the variable-length format is not apparently in the f77 norm)
    name(j:) = ','
    read (name(i+1:),*,iostat=ier) ndim
    if (ier.ne.0) then
      call sic_get_inte(name(i+1:j-1),ndim,error)
      if (error) goto 98
    endif
    ndim = ndim-1
    dim(1) = ndim+1
    ! then we clean the line
    name(i:) = ' '
  else
    ndim = 0
  endif
  npar  = npar+1
  tname(npar) = name
  ttype(npar) = ntype+10*ndim
!!  if (ntype.eq.5) ttype(npar) = 4 ! VALUES string
  !
  ! Define a SIC variable of specified type
  if (ntype.eq.1) then
    nreal = nreal + ndim + 1
    if (nreal.gt.mreal) goto 97
    tnumb(npar) = nreal
    if (ndim.ne.0) then
      call sic_def_dble (name,treal(nreal-ndim),1,dim,.false.,error)
    else
      call sic_def_dble (name,treal(nreal),0,dim,.false.,error)
    endif
  elseif (ntype.eq.2) then
    ninte = ninte + ndim + 1
    if (ninte.gt.minte) goto 97
    tnumb(npar) = ninte
    if (ndim.ne.0) then
      call sic_def_long (name,tinte(ninte-ndim),1,dim,.false.,error)
    else
      call sic_def_long (name,tinte(ninte),0,dim,.false.,error)
    endif
  elseif (ntype.eq.3) then
    nlogi = nlogi + ndim + 1
    if (nlogi.gt.mlogi) goto 97
    tnumb(npar) = nlogi
    if (ndim.eq.0) then
      call sic_def_logi (name,tlogi(nlogi),.false.,error)
    endif
  else
    nchar = nchar + ndim + 1
    if (nchar.gt.mchar) goto 97
    tnumb(npar) = nchar
    if (ndim.eq.0) then
      call sic_def_char (name,tchar(nchar),.false.,error)
    else
      call sic_def_charn (name,tchar(nchar-ndim),1,dim,.false.,error)
    endif
  endif
  if (error) then
    npar = npar-1
    return
  endif
  !
  ! Check for = sign and ignore it
  iarg = 3
  if (sic_present(iopt,iarg)) then
    equal = line(sic_start(iopt,iarg):sic_end(iopt,iarg))
    if (equal.eq.'=') iarg = iarg+1
  endif
  !
  ! Get prompt
  call sic_ch (line,iopt,1,invite,nc,.true.,error)
  if (error) goto 96
  tprom(npar) = invite(1:nc)
  !
  ! Check for X-Window mode
  if (x_window) then
    !
    np = sic_start(iopt,iarg)
    if (np.eq.0) then
      chain = 'LET '//name//'/PROMPT "'//invite(1:nc)//'"'
    else
      nk = sic_end(iopt,sic_narg(iopt))+1
      nk = max(np,nk)
      chain = 'LET '//trim(name)//' '//line(np:nk)//'/PROMPT "'//  &
      invite(1:nc)//'"'
    endif
    nc = len_trim(chain)
    !     Treat peculiar options:
    if (ctype.eq.'REAL') then
      if (jopt.eq.1) then
        chain(nc+1:)  = " /RANGE "
        nc=nc+8
        !     Look for /RANGE option for integer
        np = sic_start(1,1)
        nk = sic_end(1,sic_narg(1))+1
        chain(nc+1:)  = line(np:nk)
        nc = len_trim(chain)
      elseif (jopt.eq.2) then
        chain(nc+1:)  = " /SEXAGESIMAL "
        nc=nc+14
      elseif (jopt.eq.3) then
        chain(nc+1:)  = " /CHOICE "
        nc=nc+9
        !     Look for /CHOICE option for real
        np = sic_start(3,1)
        nk = sic_end(3,sic_narg(3))+1
        chain(nc+1:)  = line(np:nk)
        nc = len_trim(chain)
      endif
    elseif (ctype.eq.'INTEGER') then
      if (jopt.eq.1) then
        chain(nc+1:)  = " /RANGE "
        nc=nc+8
        !     Look for /RANGE option for integer
        np = sic_start(1,1)
        nk = sic_end(1,sic_narg(1))+1
        chain(nc+1:)  = line(np:nk)
        nc = len_trim(chain)
      elseif (jopt.eq.2) then
        chain(nc+1:)  = " /INDEX "
        nc=nc+8
        !     Look for /INDEX option for integer
        np = sic_start(2,1)
        nk = sic_end(2,sic_narg(2))+1
        chain(nc+1:)  = line(np:nk)
        nc = len_trim(chain)
      elseif (jopt.eq.3) then
        chain(nc+1:)  = " /CHOICE "
        nc=nc+9
        !     Look for /CHOICE option for integer
        np = sic_start(3,1)
        nk = sic_end(3,sic_narg(3))+1
        chain(nc+1:)  = line(np:nk)
        nc = len_trim(chain)
      endif
    elseif (ctype.eq.'CHARACTER') then
      !     Look for /CHOICE option for character strings
      if (jopt.eq.1) then
        np = sic_start(1,0)-1
        nk = sic_end(1,sic_narg(1))+1
        chain(nc+1:)  = line(np:nk)
        nc = len_trim(chain)
      endif
    elseif (ctype.eq.'FILE') then    !Automatically add the browser
      chain(nc+1:)  = " /FILE "
      nc=nc+7
    elseif (ctype.eq.'VALUES') then
      chain(nc+1:)  = " /NOQUOTE "
      nc=nc+10
    endif
    !
    call sic_blanc    (chain,nc)
    call sic_analyse  (comm,chain,nc,error)
    call xgag_variable(chain,nc,error)
    return
  endif
  !
  ! Check array argument IARG
  found = .false.
  if (ndim.ne.0 .and. sic_narg(iopt).eq.iarg) then
    call sic_ch (line,iopt,iarg,variab,nc,.true.,error)
    call sic_descriptor(variab,descr,found)    ! Checked
    if (found) then
      if (descr%dims(1).ne.ndim+1) found = .false.
    endif
    if (found) then
      type = descr%type
      ipnt = bytpnt(descr%addr,membyt)
      if (type.eq.fmt_r4) then
        if (ntype.eq.1) then
          call r4tor8(membyt(ipnt),treal(nreal-ndim),ndim+1)
        else
          found = .false.
        endif
      elseif (type.eq.fmt_r8) then
        if (ntype.eq.1) then
          call r8tor8(membyt(ipnt),treal(nreal-ndim),ndim+1)
        else
          found = .false.
        endif
      elseif (type.eq.fmt_i4) then
        if (ntype.eq.2) then
          call i4toi8(membyt(ipnt),tinte(ninte-ndim),ndim+1)
        elseif (ntype.eq.1) then
          call i4tor8(membyt(ipnt),treal(nreal-ndim),ndim+1)
        else
          found = .false.
        endif
      elseif (type.eq.fmt_i8) then
        if (ntype.eq.2) then
          call i8toi8(membyt(ipnt),tinte(ninte-ndim),ndim+1)
        elseif (ntype.eq.1) then
          call i8tor8(membyt(ipnt),treal(nreal-ndim),ndim+1)
        else
          found = .false.
        endif
      elseif (type.eq.fmt_l) then
        if (ntype.eq.3) then
          call l4tol4(membyt(ipnt),tlogi(nlogi-ndim),ndim+1)
        else
          found = .false.
        endif
      else
        found = .false.
      endif
    endif
  endif
  if (found) return
  !
  ! If not enough arguments, prompt for text
  if (.not.sic_present(iopt,iarg+ndim)) then
    write (*,'(A)') invite(1:nc)
    nline = len_trim(line)+1
20  call sic_wprn (ctype//cname//' = ',line(nline+1:),nc)
    if (nc.eq.0) goto 96
    !
    ! Check for help
    if (line(nline+1:nline+nc).eq.'?') then
      call tkeys(tprog,tname(npar))
      goto 20
    endif
    nline = min(nline+nc,len(line))
    call sic_blanc (line,nline)
    call sic_analyse (comm,line,nline,error)
    if (error) goto 96
  endif
  !
  ! Now assign the value
  if (ntype.eq.5) then  ! Values
    lt = 1
    string = ' '
    expr = ' '
    do i=iarg,sic_narg(iopt) !!,ndim
    !
    ! Get the string
      nc = 0
      error = .false.
      call sic_ch (line,iopt,i,expr,nc,.true.,error)
      ! the evaluate the expression
      r8 = 0.0
      call sic_math_dble (expr,nc,r8,error)
      if (error) goto 96
      call sic_dble_to_string(r8,string)
      !
      ! Add to argument string
      tchar(nchar)(lt:) = string
      lt = len_trim(tchar(nchar))+2
    enddo
    !
  else if (ntype.eq.4) then
    do i=0,ndim
      call sic_ch (line,iopt,iarg+i,tchar(nchar+i-ndim),nc,.true.,error)
      if (error) goto 96
      if (translate) status = parse_file(tchar(nchar+i-ndim),istat)
    enddo
  elseif (ntype.eq.3) then
    do i=0,ndim
      call sic_l4 (line,iopt,iarg+i,tlogi(nlogi+i-ndim),.true.,error)
      if (error) goto 96
    enddo
  elseif (ntype.eq.2) then
    do i=0,ndim
      call sic_i8 (line,iopt,iarg+i,tinte(ninte+i-ndim),.true.,error)
      if (error) goto 96
    enddo
  else
    do i=0,ndim
      call sic_r8 (line,iopt,iarg+i,treal(nreal+i-ndim),.true.,error)
      if (error) goto 96
    enddo
  endif
  return
  !
96 continue
  call sic_delvariable(tname(npar),.false.,error)
  npar = npar-1
  error = .true.
  return
99 call sic_message(seve%e,rname,'Incompatible options')
  error = .true.
  return
97 call sic_message(seve%e,rname,'Too many parameters')
  error = .true.
  return
98 call sic_message(seve%e,rname,'Invalid dimension '//name(i+1:j+1))
  error = .true.
  return
end subroutine treals
!
subroutine twrite(line,error)
  use sic_interfaces, except_this=>twrite
  use sic_interactions
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! GILDAS  Support routine for command
  ! TASK\WRITE Parameter
  !---------------------------------------------------------------------
  character(len=*)                :: line   !
  logical,          intent(inout) :: error  !
  ! Local
  integer :: i,j,ndim,ntype,nc
  character(len=16) :: name
  !
  call sic_ke (line,0,1,name,nc,.true.,error)
  if (error) return
  do i=1,npar
    if (name.eq.tname(i)) then
      ndim =ttype(i)/10
      ntype=ttype(i)-10*ndim
      write(tlun,'(A)') name
      if (ntype.eq.5) then
        write(tlun,'(A)') ( tchar(j)(1:len_trim(tchar(j))), j=tnumb(i)-ndim,tnumb(i) )
      else if (ntype.ge.4) then
        write(tlun,'(A)') ( tchar(j)(1:len_trim(tchar(j))), j=tnumb(i)-ndim,tnumb(i) )
      elseif (ntype.eq.3) then
        write(tlun,*)     ( tlogi(j),       j=tnumb(i)-ndim,tnumb(i) )
      elseif (ntype.eq.2) then
        write(tlun,*)     ( tinte(j),       j=tnumb(i)-ndim,tnumb(i) )
      else
        write(tlun,*)     ( treal(j),       j=tnumb(i)-ndim,tnumb(i) )
      endif
      return
    endif
  enddo
  call sic_message(seve%e,'TASK','Undefined parameter '//name)
  error = .true.
end subroutine twrite
!
subroutine tmore(line,error)
  use sic_interfaces, except_this=>tmore
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  character(len=*) :: line          !
  logical :: error                  !
  ! Local
  character(len=1), parameter :: backslash=char(92)
  integer :: nt
  character(len=12) :: bouton,comm
  character(len=24) :: option
  character(len=64) :: texte
  !
  error = .false.
  !
  if (x_window) then
    bouton = 'Go'//char(0)
    comm = 'TASK'//backslash//'GO'//char(0)
    call sic_ch (line,0,1,texte,nt,.true.,error)
    if (error) return
    option = 'Parameters ...'//char(0)
    call xgag_more (bouton,comm,texte,option)
  endif
end subroutine tmore
!
subroutine thelp(line,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>thelp
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command:
  !   TASK\HELP  [TaskName [VarName]]
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  !
  ! Local
  character(len=80) :: tname,vname
  integer(kind=4) :: nc
  !
  ! Parse task name
  tname = ' '
  call sic_ch (line,0,1,tname,nc,.false.,error)
  if (error) return
  !
  ! Parse variable name
  vname = ' '
  call sic_ch (line,0,2,vname,nc,.false.,error)
  if (error) return
  !
  call help_run(tname,vname,1,error)
  if (error)  return
  !
end subroutine thelp
