subroutine getcom(ligne,nl,lire,invite,np,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>getcom
  use sic_macros_interfaces
  use sic_structures
  use sic_interactions
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !       Gets a Command Line for the Interpretor
  ! Arguments
  !       LIGNE   Command line read               Output
  !       NL      Length of line                  Output
  !       LIRE    Input pointer                   Input
  !       INVITE  Prompt                          Input
  !       NP      Length of prompt                Input
  !       ERROR   Logical error flag              Output
  !---------------------------------------------------------------------
  character(len=*) :: ligne         !
  integer :: nl                     !
  integer :: lire                   !
  character(len=*) :: invite        !
  integer :: np                     !
  logical :: error                  !
  ! Local
  character(len=*), parameter :: rname='GETCOM'
  logical :: suite,fopened
  integer(kind=4) :: n,nl2,ier
  character(len=message_length) :: mess
  character(len=128) :: fname
  ! Patch to read commands like HELP; SAY "toto";
  integer :: k
  logical :: string
  ! Data
  character(len=commandline_length), save :: pending  ! Pending line
  integer(kind=4), save :: npend  ! Length of 'pending' line
  logical, save :: several  ! Is there a pending line?
  data several /.false./
  !
  ! Reset line first
  suite = .false.
  nl    = 0
  ligne = ' '
  !
  ! CHeck if multiple lines
  !D    Print *,'TEST GETCOM ',Several
  if (several) then
    ligne = pending(1:npend)
    nl = npend
    !D  Print *,'TEST GETCOM Several ',ligne(1:nl)
    goto 100
  endif
  !
  ! Reads it from the Terminal
  if (lire.eq.0) then
10  continue
    if (edit_mode.and.inter_state) then
      if (suite)then
        np=np+1
        invite(np-2:np)='-? '
        call read_line(ligne(nl+1:),n,invite,np)
        invite(np-2:np)='>  '
        np=np-1
      else
        call read_line(ligne(nl+1:),n,invite,np)
      endif
      if (n.lt.0) goto 150
    else
      if (inter_state) then
        if (suite)then
          np=np+1
          invite(np-2:np)='-? '
          write(6,101) invite(1:np)
          invite(np-2:np)='>  '
          np=np-1
        else
          write(6,101) invite(1:np)
        endif
      endif
      read (5,'(A)',err=10,end=150) ligne(nl+1:)
      n = len_trim(ligne(nl+1:))
    endif
    !
    ! Trap CTRL-C typed at prompt
    call ctrlc_check(error)
    if (n.eq.0) then
      ! Empty command => optimized loop: do not go back to SIC
      goto 10
    endif
    if (n.ge.len(ligne(nl+1:))) goto 200
    ! SYSTEM call or SIC call?
    nl2 = nl+n
    if (sic_format_system_token(ligne,nl2)) then
      nl = nl2
      return
    else
      call sblanc(ligne(nl+1:),n,suite,ier)
      if (ier.ne.1) goto 201
    endif
    !
    ! Handles Continuation Lines
    nl= nl+n
    if (nl.eq.0 .or. suite) goto 10
    goto 100
  endif
  !
  ! Reads in the Loop
  if (lire.le.-2) then
    call getlin (ligne,nl,jloo,iloo,nloo,loolen,loobuf)
    if (nl.eq.0) goto 150
    if (lverif.and.(nl.ne.0).and..not.sic_quiet) then
      call sic_echo (invite,np,ligne,nl)
    endif
    goto 100
  endif
  !
  ! Command from program
  if (lire.eq.-1) then
    call sic_message(seve%e,'SIC','Internal logic error LIRE = -1')
    error = .true.
    return
  endif
  !
  ! Reads in a Macro
30 continue
  read (lunmac(lire),'(A)',iostat=ier) ligne(nl+1:)
  if (ier.ne.0) goto 202
  jmac(lire)=jmac(lire)+1
  n = len_trim(ligne(nl+1:))
  if (n.eq.0) goto 30
  if (jmac(lire).eq.1)  call sic_format_shebang(ligne(nl+1:),n)  ! First line only
  call sblanc(ligne(nl+1:),n,suite,ier)
  if (ier.ne.1) goto 201
  !
  ! Handles Continuation Lines
  nl= nl+n
  if (nl.eq.0) goto 30
  if (suite) goto 30
  !
  if (.not.proced) then
    call sic_macros_replace_args(ligne,nl,lire,error)
    if (error) return
  endif
  if (lverif.and.(nl.ne.0).and..not.sic_quiet) then
    call sic_echo (invite,np,ligne,nl)
  endif
  !
100 continue
  string = .false.
  do k=1,nl
    if (ligne(k:k).eq.'"') then
      string = .not.string
    elseif (.not.string) then
      if (ligne(k:k).eq.';') then
        ! print *,'TEST GETCOM found ',k
        if (k.lt.nl) then
          pending = ligne(k+1:nl)
          npend = nl-k
          several = .true.
          ligne(k:nl) = ' '
          nl = len_trim(ligne)     ! was K-1
          if (nl.gt.0) then
            call sblanc(pending(1:),npend,suite,ier)
            if (ier.ne.1) goto 201
            call aroba(ligne,nl,error)
          else
            ligne = pending(1:npend)
            nl = npend
            several = .false.
            call aroba(ligne,nl,error)
          endif
          !D    print *,'TEST Returning SEVERAL commands: ',several
          !D    print *,'TEST '//trim(ligne)
          !D    print *,'TEST '//trim(pending)
          return
        else
          nl=k-1
          if (nl.gt.0) then
            ligne(nl+1:) = ' '
          else
            ligne = 'C'
            nl = 1
          endif
          nl = len_trim(ligne)     ! was not there
        endif
      endif
    endif
  enddo
  several = .false.
  ! End patch
  !
  ! If the first character is an @, add a blank after it if necessary.
  call aroba(ligne,nl,error)
  if (.not.error) return
  !
200 call sic_message(seve%e,rname,'Line too long, buffer overflow')
  error=.true.
  return
201 nl = nl+n
  error = .true.
  return
  !
202 continue
  if (ier.ne.-1) then
    ! Everything else but EOF (-1) is an error
    inquire(unit=lunmac(lire),opened=fopened,name=fname)
    if (fopened) then
      write(mess,'(A,I0,3A)') 'Read error on macro file, unit ',lunmac(lire),' (opened on file ',trim(fname),')'
    else
      write(mess,'(A,I0,A)') 'Read error on macro file, unit ',lunmac(lire),' (closed)'
    endif
    call sic_message(seve%e,rname,mess)
    call putios('E-GETCOM,  ',ier)
    error = .true.
  endif
150 return
  !
entry putcom(ligne,nl,error)
  !---------------------------------------------------------------------
  ! Patch for multiple command lines
  ! Reprocess the input line to search for multiple lines in it.
  !---------------------------------------------------------------------
  if (several) then
    ! Beware!!! There is already a pending line in the stack. Brute
    ! force: readd it to the input line
    ligne = ligne(1:nl)//'; '//pending(1:npend)
    nl = nl+2+npend
  endif
  goto 100
  !
entry delcom
  !---------------------------------------------------------------------
  !  Delete pending command line. Useful when e.g. an error occurs
  ! when executing one command in the sequence:
  !  valid1; invalid2; valid3
  !---------------------------------------------------------------------
  several = .false.
  pending = ''
  npend = 0
  !
101 format(a,$)
  !
contains
  !
  subroutine sic_format_shebang(line,nline)
    !----------------------------------------------------------------------
    ! Detect shebang line and transform it into a comment line. By design
    ! shebang can only appear in the 2 first characters of the first line
    ! of a macro.
    !----------------------------------------------------------------------
    character(len=*), intent(inout) :: line
    integer(kind=4),  intent(in)    :: nline
    if (nline.ge.2 .and. line(1:2).eq.'#!')  line(1:2) = '!!'
  end subroutine sic_format_shebang
end subroutine getcom
!
subroutine getlin(ligne,nc,j,i,next,m,buf)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>getlin
  use gildas_def
  !---------------------------------------------------------------------
  ! @ private
  !  Retrieves a command line from an internal buffer
  !---------------------------------------------------------------------
  character(len=*),             intent(out)   :: ligne   ! Command line retrieved
  integer(kind=4),              intent(out)   :: nc      ! Length of line
  integer(kind=4),              intent(inout) :: j       ! Current buffer command number
  integer(kind=4),              intent(in)    :: i       ! First buffer command number
  integer(kind=4),              intent(inout) :: next    ! Pointer in buffer
  integer(kind=4),              intent(in)    :: m       ! Number of commands in buffer
  integer(kind=address_length), intent(in)    :: buf(*)  ! Internal buffer
  ! Local
  integer(kind=address_length) :: addr
  integer(kind=4) :: last
  !
  nc = 0
10 j = j + 1
  if (j.gt.m) return
  last = next
  next = next + (buf(next)+3)/4 + 3
  if (j.le.i) goto 10
  !
  nc = buf(last)
  addr = buf(last+1)
  call destoc(nc,addr,ligne)
  ligne(nc+1:) = ' '
end subroutine getlin
!
subroutine aroba (line,nl,error)
  use sic_interfaces, except_this=>aroba
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !
  !       Adds a blank space after an @ if the @ is the first char in LINE
  !       and is not already followed by a blank.
  !
  !       LINE    Command line to be modified     Updated
  !       NL      Length of line                  Updated
  !       ERROR   Logical error flag              Output
  !---------------------------------------------------------------------
  character(len=*) :: line          !
  integer :: nl                     !
  logical :: error                  !
  ! Local
  integer :: i
  !
  if (line(1:1).eq.'@') then
    if (line(2:2).eq.' ') then
      return
    else
      if (nl.ge.len(line)) then
        error=.true.           ! Line too long
      else
        !              line = '@ '//line(2:)
        do i=nl,2,-1
          line(i+1:i+1) = line(i:i)
        enddo
        line(2:2) = ' '
        nl=nl+1
      endif
    endif
  endif
end subroutine aroba
!
subroutine sic_echo (invite,np,line,nl)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sic_echo
  use sic_interactions
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Internal routine
  !       Echo the command to the terminal in VERIFY mode
  ! Arguments
  !       INVITE  C*(*)   Prompt text
  !       NP      I       Length of prompt
  !       LINE    C*(*)   Command line including prompt
  !       NL      I       Length of LINE
  !---------------------------------------------------------------------
  character(len=*) :: invite        !
  integer :: np                     !
  character(len=*) :: line          !
  integer :: nl                     !
  ! Local
  integer :: n1,n2,tt_width,n
  character(len=4) :: ans
  integer, parameter :: mp=50       ! Prompt length...
  !
  tt_width = sic_ttyncol()
  n1 = 1
  n2 = tt_width-1-np
  if (n2.ge.nl) then
    if (sic_stepin.gt.0) then
      if (nl+np.lt.mp) then
        call sic_wprn(invite(1:np)//line(1:mp)//' ? ',ans,n)
      else
        write(6,1000) invite(1:np),line(1:nl)
        call sic_wprn(' ? ',ans,n)
      endif
    else
      write(6,1000) invite(1:np),line(1:nl)
    endif
    return
  else
    write(6,1000) invite(1:np),line(1:n2)
  endif
  !
10 n1 = n2+1
  n2 = n2+tt_width-1
  if (n2.ge.nl) then
    if (sic_stepin.gt.0) then
      if (nl-n1+1.lt.mp) then
        call sic_wprn(line(n1:mp+n1-1)//' ? ',ans,n)
      else
        write(6,1000) line(n1:nl)
        call sic_wprn(' ? ',ans,n)
      endif
    else
      write(6,1000) line(n1:nl)
    endif
    return
  endif
  write(6,1000) line(n1:n2),'-'
  goto 10
  !
1000 format(20(a))
end subroutine sic_echo
