subroutine sic_trap
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_trap
  use sic_interactions
  use gbl_message
  use gildas_def
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !
  !       Abort execution in non-interactive session after any error
  !---------------------------------------------------------------------
  if (inter_state) return
  call sic_message(seve%f,'PAUSE','Session is not interactive')
  call sysexi(fatale)
end subroutine sic_trap
!
subroutine break
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>break
  use gildas_def
  use sic_structures
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !
  !       Make a PAUSE
  !----------------------------------------------------------------------
  !
  ! Generate a traceback if in interactive mode
  if (nlire.ne.0) then
    if (mlire(nlire).eq.0) then
      call traceback
      return
    endif
  endif
  !
  ! Else pause
  nlire=nlire+1
  if (nlire.gt.maxlev) then
    call sic_message(seve%f,'PAUSE','Level depth too large')
    call sysexi(fatale)
  endif
  ! Set IF block first depth for this level
  if_depth (nlire) = if_current+1
  mlire(nlire)=0
end subroutine break
!
subroutine traceback
  use sic_interfaces, except_this=>traceback
  use sic_macros_interfaces
  use sic_structures
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !       Generate traceback information
  !---------------------------------------------------------------------
  ! Local
  character(len=*), parameter :: rname='ERROR'
  integer :: i,j,l
  character(len=message_length) :: mess
  !
  do i=nlire-1,2,-1
    l=mlire(i)
    if (l.eq.-1) then
      write(mess,100)
      call sic_message(seve%i,rname,mess)
    elseif (l.le.-2) then
      j = cloop
      do while(j.gt.0)
        write(mess,101) j,indice(j),jloo-firllo(j)
        call sic_message(seve%i,rname,mess)
        j = ploop(j)
      enddo
    elseif (l.eq.0) then
      write(mess,102)
      call sic_message(seve%i,rname,mess)
    else
      write(mess,103) trim(macnam(l)),jmac(l)
      call sic_message(seve%i,rname,mess)
    endif
  enddo
  !
100 format('Called by Program')
101 format('Called by Loop ',i2,' (#',1pg11.4,')',t65,'at line ',i4)
102 format('Called by Pause')
103 format('Called by ',a,1x,'at Line ',i4)
end subroutine traceback
!
subroutine erreur(error,line,nline,lect,err)
  use sic_interfaces, except_this=>erreur
  use sic_macros_interfaces
  use sic_interactions
  use sic_dictionaries
  use gbl_message
  use gbl_ansicodes
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   (Internal routine) Error handler
  !
  ! This routine traps all errors and take appropriate action:
  !  - Generate a PAUSE with traceback (Default)
  !  - or activate an error recovery command defined by the user in
  !    command "ON ERROR Command"
  !---------------------------------------------------------------------
  logical, intent(inout) :: error  ! Logical flag indicating if an error occured
  character(len=*) :: line         ! Command line to be executed     Output
  integer :: nline                 ! Length of line                  Output
  integer :: lect                  ! Level of execution              Input
  logical, intent(out)   :: err    !
  ! Local
  character(len=*), parameter :: rname='ERROR'
  integer :: l,i,lerr,ierr
  logical :: flag
  character(len=message_length) :: mess
  character(len=32) :: eprompt
  integer :: leprompt
  logical :: empty ! In Error Recovery Mode, empty lines reset the Error Prompt
  ! Data
  save flag
  data flag /.false./
  !
  ! Set SIC%ERROR, indicating if last command was a success or not.
  sicvar_error = error
  !
  ! Check wether one is already in error recovery mode (FLAG = .TRUE.)
  err = .false.
  ierr = var_level
  lerr = nerr(ierr)
  if (flag) then
    if (.not.error) then
      !
      ! Else end error recovery mode, since it has been completed successfully
      flag = .false.
      !
      ! ON ERROR QUIT : Stop after one recovery
    elseif (lerr.eq.e_quit) then
      ! print *,'E_QUIT on error '
      line = errcom(ierr)
      nline = 23
      flag = .false.
      error = .true.
      err = .true.
    elseif (lerr.eq.e_retu) then
      ! print *,'E_RETU on error '
      line = errcom(ierr)
      nline = 10
      flag = .false.
      error = .false.
      err = .true.
      !
      ! Avoid infinite loops by Pausing
    elseif (lerr.eq.e_pause) then  ! .AND. VAR_LEVEL.EQ.0) THEN
      line = errcom(ierr)
      nline = 9
      flag = .false.
      error = .true.
      err = .true.
    else
      error = .false.
      flag  = .false.
      write(mess,205)
      call sic_message(seve%i,rname,mess)
      call break
      call sic_trap
    endif
    return
  endif
  !
  ! Any other mode, Return if no error
  if (.not.error) return
  !
  ! Else, generate traceback if needed, and activate error recovery action
  !
  error = .false.
  call delcom  ! Delete pending command lines
  !
  ! NLIRE = 0 means subroutine mode of the SIC monitor
  !
  if (nlire.eq.0) then
    write(mess,204)
    call sic_message(seve%i,rname,mess)
    !
    ! Classical error recovery mode : PAUSE and EDIT if possible
    if (lerr.eq.e_pause) then
      call break
      call sic_trap
      if (edit_mode) then
        call bldprt(nlire)
        call edit_line(line,nline,gprompt,lgprompt)
        lect = 0
        err = .true.
      endif
    elseif (lerr.ne.e_cont) then
      !
      ! Set error recovery mode and define line to be executed
      flag = .true.
      line  = errcom(ierr)
      nline = lerr
      if (lerr.eq.e_quit) then
        nline = 23
      elseif (lerr.eq.e_retu) then
        nline = 10
      else
        nline = lerr
      endif
      err = .true.
    endif
    return
  endif
  !
  ! Any positive value of NLIRE means a level of execution
  !
  ! Signal where the error occured
  l=mlire(nlire)
  if (l.eq.-1) then
    write(mess,200)
    call sic_message(seve%i,rname,mess)
  elseif (l.le.-2) then
    i = cloop
    do while(i.gt.0)
      write(mess,201) i,indice(i),jloo-firllo(i)
      call sic_message(seve%i,rname,mess)
      i = ploop(i)
    enddo
  elseif (l.eq.0) then
    !
    ! No traceback if one was already in interactive mode, and no PAUSE either
    if (lerr.eq.e_pause) then
      call sic_trap
      if (edit_mode) then
        call bldprt(nlire)
        if (.not.history_old_behaviour(0)) then
          if (nlire.le.1) then
            line = ' '
            nline = 0
          endif
        endif
        ! Prompt in Reverse video
        eprompt = trim(c_reverse)//gprompt(1:lgprompt)//trim(c_clear)
        leprompt = len_trim(eprompt)
        empty = .true.
        call getcom(line,nline,l,eprompt,leprompt,err,empty)
        lect = 0
        ! Carry on the error, set the temporary one to .TRUE.
        error = err  
        err = .true.  
      endif
    elseif (lerr.ne.e_cont) then
      flag = .true.
      line  = errcom(ierr)
      nline = lerr
      if (lerr.eq.e_quit) then
        nline = 23
      elseif (lerr.eq.e_retu) then
        nline = 10
      else
        nline = lerr
      endif
      err = .true.
      ! Give feedback to user: we will execute a custom command which he
      ! might understand himself (e.g. "ON ERROR EXIT"...)
      call sic_message(seve%w,rname,'Error trapped on user request: ON ERROR '//line)
    endif
    return
  else
    if (macnam(nmacro).ne.' ') then
      write(mess,203) trim(macnam(nmacro)),jmac(l)
      call sic_message(seve%i,rname,mess)
    endif
  endif
  !
  ! Give the Traceback information
  call traceback
  !
  ! Default error handling PAUSE
  if (lerr.eq.e_pause) then
    call break
    call sic_trap
    if (edit_mode) then
      call bldprt(nlire)
      call edit_line(line,nline,gprompt,lgprompt)
      lect = 0
      err = .true.
    endif
  elseif (lerr.ne.e_cont) then
    !
    ! Set error recovery mode and define line to be executed
    flag = .true.
    line  = errcom(ierr)
    nline = lerr
    if (lerr.eq.e_quit) then
      nline = 23
    elseif (lerr.eq.e_retu) then
      nline = 10
    else
      nline = lerr
    endif
    err = .true.
  endif
  return
  !
200 format('Occured in Program')
201 format('Occured in Loop ',i2,' (#',1pg11.4,')',' at Line ',i4)
203 format('Occured in ',a,' at Line ',i4)
204 format('Occured in Execute mode')
205 format('Occured in Error recovery mode')
end subroutine erreur
!
subroutine sic_on(line,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_on
  !---------------------------------------------------------------------
  ! @ private
  !  Support routine for command
  !    ON Arg
  !  Disambiguise the first argument.
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line
  logical,          intent(inout) :: error
  ! Local
  character(len=*), parameter :: rname='ON'
  integer(kind=4), parameter :: nkey=1
  character(len=5), parameter :: keys(nkey) = (/ 'ERROR' /)
  integer(kind=4) :: nc,ikey
  character(len=6) :: argum,key
  !
  call sic_ke(line,0,1,argum,nc,.true.,error)
  if (error) return
  !
  call sic_ambigs(rname,argum,key,ikey,keys,nkey,error)
  if (error)  return
  !
  if (ikey.eq.1) then  ! ERROR
    call seterr(line,error)
    if (error)  return
  else
    call sic_message(seve%e,'ON',trim(key)//' is not implemented')
    error = .true.
    return
  endif
  !
end subroutine sic_on
!
subroutine seterr(line,error)
  use gildas_def
  use gbl_message
  use sic_structures
  use sic_dictionaries
  use sic_interfaces, except_this=>seterr
  !---------------------------------------------------------------------
  ! @ private
  !   Defines the error recovery action by command ON ERROR Command
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line
  logical,          intent(inout) :: error
  ! Local
  character(len=1), parameter :: backslash=char(92)
  character(len=12) :: keyword
  character(len=commandline_length) :: cerr
  integer(kind=4) :: nl,action
  !
  ! Retrieve and analyse the error command line
  if (.not.sic_present(0,2)) then
    ! Select default error recovery mode if no argument is given
    cerr = ' '
    nl = 1
    action = e_pause
    !
  else
    ! Otherwise switch to the alternate error recovery mode
    !
    if (sic_narg(0).eq.2) then
      ! Only a single argument after ON ERROR, can be a double-quoted string
      call sic_ch(line,0,2,cerr,nl,.true.,error)
      if (error)  return
    else
      ! Several arguments after ON ERROR
      cerr = line( sic_start(0,2) : sic_end(0,sic_narg(0)) )
      nl = len_trim(cerr)
    endif
    !
    ! Patch blank after @, if any
    call aroba(cerr,nl,error)
    if (error)  return
    !
    ! Resolve the command
    call sic_find (keyword,cerr,nl,error)
    if (error) return
    !
    ! Catch predefined cases (negative or null codes)
    if (cerr(1:nl).eq.'SIC'//backslash//'CONTINUE') then
      action = e_cont
    elseif (cerr(1:nl).eq.'SIC'//backslash//'QUIT') then
      action = e_quit
      write (cerr,'(A,I2)') 'SIC'//backslash//'RETURN ERROR FROM ',var_level
      nl = 23
    elseif (cerr(1:nl).eq.'SIC'//backslash//'PAUSE') then
      action = e_pause
    elseif (cerr(1:nl).eq.'SIC'//backslash//'RETURN') then
      action = e_retu
    else
      ! Default: any other command, positive code
      action = nl
    endif
  endif
  !
  errcom(var_level) = cerr(1:nl)
  nerr(var_level) = action
  !
end subroutine seterr
