subroutine define_symbol (line,nline,error)
  use sic_dependencies_interfaces
  use sic_structures
  use sic_dictionaries
  use sic_interfaces, except_this=>define_symbol
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Support routine for command
  !       SYMBOL [ABBREV] ["ANYTHING you want"] [/INQUIRE ["Question"]]
  !       Defines, list or delete an abbreviation
  ! Arguments :
  !       LINE    C*(*)   Command line defining the abbreviation
  !---------------------------------------------------------------------
  character(len=*)       :: line   !
  integer                :: nline  !
  logical, intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='SYMBOL'
  character(len=40) :: question
  character(len=16) :: argum
  character(len=translation_length) :: symb
  character(len=symbol_length) :: name
  integer :: list(maxsym),i,lt,in,nc,ier
  character(len=symbol_length+translation_length+7) :: mess  ! Matches format 100 below
  !
  ! Check if one is listing the Symbol table
  if (.not.sic_present(0,1)) then
    if (symbols%pf(27).eq.0) then
      call sic_message(seve%r,rname,'Table is empty')
    else
      call gag_hassort(maxsym,symbols%pf,symbols%pn,symbols%name,list,in)
      call sic_message(seve%r,rname,'Table contains : ')
      do i=1,in
        write(mess,100) symbols%name(list(i)),  &
                        symbols%trans(list(i))(1:symbols%ltrans(list(i)))
        call sic_message(seve%r,rname,mess)
      enddo
    endif
    return
  endif
  !
  ! Find the symbol and truncate to symbol_length characters, exclude quotes
  call sic_ch (line,0,1,argum,nc,.true.,error)
  if (error) return
  call sic_upper(argum)
  name = argum
  if (nc.gt.symbol_length)  &
    call sic_message(seve%w,rname,'Symbol truncated to '//name)
  !
  ! Check if symbol is to be listed
  if (.not.sic_present(0,2).and..not.sic_present(1,0)) then
    ier = gag_hasfin(maxsym,symbols%pf,symbols%pn,symbols%name,name,in)
    if (mod(ier,2).ne.0) then
      write(mess,100) name,  &
                      symbols%trans(in)(1:symbols%ltrans(in))
      call sic_message(seve%r,rname,mess)
    else
      call sic_message(seve%w,rname,'Undefined symbol '//name)
    endif
    return
  endif
  !
  ! Create a new symbol definition
  if (sic_present(0,3)) then
    call sic_message(seve%e,rname,"Trailing arguments in assignment: "//line)
    error = .true.
    return
  endif
  !
  ! Check if enquiry needed
  if (sic_present(1,0)) then
    question = name//'Translation ?'
    call sic_ch (line,1,1,question,nc,.false.,error)
    if (error) return
    call sic_wprn(question(1:nc),symb,lt)
    if (lt.eq.0) return
  else
    !
    ! Define abbreviation
    call sic_ch (line,0,2,symb,lt,.true.,error)
    if (error) return
  endif
  !
  ! Insert or replace in symbol dictionnary
  call sic_setsymbol (name,symb(1:lt),error)
  return
  !
100 format("'",a,"'",' = "',a,'"')
end subroutine define_symbol
!
subroutine replace_usercom(user,command,line,nline,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>replace_usercom
  use sic_types
  !---------------------------------------------------------------------
  ! @ private
  !   Identifies and translate the user command from the input command
  ! line
  !---------------------------------------------------------------------
  type(sic_language_t), intent(in)    :: user     ! The user language
  character(len=*),     intent(inout) :: command  ! The user command to translate
  character(len=*),     intent(inout) :: line     ! Line to be translated (updated)
  integer(kind=4),      intent(inout) :: nline    ! Line length (updated)
  logical,              intent(inout) :: error    ! Logical error flag
  ! Local
  integer(kind=4) :: ier,in,lt,ls,pos
  !
  ier = gag_hasfin(user%usym%msym,user%usym%pf,user%usym%pn,user%usym%name,  &
    command,in)
  if (ier.ne.1) then
    call sic_message(seve%e,'SIC','User command not understood')
    error = .true.
    return
  endif
  ! Length of translation
  lt = user%usym%ltrans(in)
  !
  ! Length of symbol:
  !       USER      \     COMMAND
  ls = user%lname + 1 + len_trim(command)
  !
  ! Position in line
  pos = 1
  !
  call replace_symlog(line,ls,user%usym%trans(in),lt,pos,nline,error)
  if (error) return
  !
end subroutine replace_usercom
!
subroutine replace_symbol(line,nline,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>replace_symbol
  use sic_dictionaries
  !---------------------------------------------------------------------
  ! @ private
  !  Identifies and translate all the SIC symbols from the input
  ! command line
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line   ! Line to be translated (updated)
  integer(kind=4),  intent(inout) :: nline  ! Line length (updated)
  logical,          intent(out)   :: error  ! Logical error flag
  ! Local
  logical :: symb
  character(len=symbol_length) :: name
  integer :: pos,next,lsymb,ltrans,in,ier
  !
  ! If no symbol, return
  error = .false.
  if (symbols%pf(27).eq.0) return
  !
  ! POS   Pointer of current position in LINE
  ! NEXT  Relative position of next word separator
  !       The absolute position of next word separator is POS+NEXT
  !       The length of pseudo-symbol is also NEXT
  !
  ! First word
  symb = .false.
  pos  = 1
  next = index(line(pos+1:),' ')
  !
  ! Set name to be translated
  name = line(pos:next)
  next = next-1
  !
  ! All other words
  do
    lsymb = next+1
    ier = gag_hasfin(maxsym,symbols%pf,symbols%pn,symbols%name,name,in)
    if (ier.eq.1) then
      ltrans = symbols%ltrans(in)
      call replace_symlog(line,lsymb,symbols%trans(in),ltrans,pos,nline,error)
      if (error) return
      symb = .true.
    endif
    !
    ! Search for beginning of next symbol.
    next=index(line(pos+1:),"'")
    ! Nothing left
    if (next.eq.0) then
      if (symb) call sic_blanc(line,nline)
      return
    endif
    !
    ! Find next WORD separator
30  pos = pos+next
    next = index(line(pos+1:),"'")
    ! Nothing left
    if (next.eq.0) then
      if (symb) call sic_blanc(line,nline)
      return
    endif
    if (index(line(pos+1:),' ').lt.next) goto 30
    !
    ! Valid symbol look for translation
    name = line(pos+1:pos+next-1)
    call sic_upper(name)
  enddo
end subroutine replace_symbol
!
subroutine replace_logical(line,nline,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>replace_logical
  !---------------------------------------------------------------------
  ! @ private
  ! SIC Internal Routine
  !     Replace logical names between Back Quotes by their translation
  !---------------------------------------------------------------------
  character(len=*)       :: line   !
  integer                :: nline  !
  logical, intent(inout) :: error  !
  ! Local
  integer :: i,ier,istart,iend,lenlog,lentrans
  character(len=512) :: lognam, inpnam
  character(len=1) :: bquot,dquot
  logical :: string
  ! Data
  data bquot/'`'/, dquot/'"'/
  !
  string = .false.
  istart = 0
  iend = 0
  !
  i = 1
  do while (i.le.nline)
    if (line(i:i).eq.dquot) then
      string = .not.string
    elseif  (.not.string) then
      if (line(i:i).eq.bquot) then
        if (istart.ne.0) then
          iend = i
          lenlog = iend-istart+1
          ! This line does not recursively translate logical names
          ier = sic_getlog(line(istart+1:iend-1),lognam)
          if (ier.eq.0) then
            ! These 2 lines will do the recursive translation
            inpnam = line(istart+1:iend-1)
            call sic_parse_file(inpnam,"","",lognam)
            !
            lentrans = len_trim(lognam)
            call replace_symlog(line,lenlog,lognam,lentrans,istart,nline,error)
            i = istart
            istart = 0
          endif
        else
          istart = i
        endif
      endif
    endif
    i = i+1
  enddo
end subroutine replace_logical
!
subroutine replace_symlog(line,lsymb,trans,ltrans,pos,nline,error)
  use gbl_message
  use sic_interfaces, except_this=>replace_symlog
  !---------------------------------------------------------------------
  ! @ private
  ! Replace a Symbol or Logical name by its translation.
  ! Note that the surrounding quotes (for Symbols) or backquotes (for
  ! logical names) are striped off.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: line    ! Command line
  integer(kind=4),  intent(in)    :: lsymb   ! Length of symbol
  character(len=*), intent(in)    :: trans   ! Translation
  integer(kind=4),  intent(in)    :: ltrans  ! Length of translation
  integer(kind=4),  intent(inout) :: pos     ! Curent position in line
  integer(kind=4),  intent(inout) :: nline   ! Length of line
  logical,          intent(inout) :: error   !
  ! Local
  integer(kind=4) :: i
  !
  if (nline+ltrans-lsymb .ge. len(line)) then
    call sic_message(seve%e,'SYMLOG','String too long, translation failed')
    error=.true.
    return
  endif
  !
  if (ltrans.lt.lsymb) then
    ! Shift the trailing characters to the left
    do i=pos+lsymb,nline
      line(i+ltrans-lsymb:i+ltrans-lsymb) = line(i:i)
    enddo
    line(nline+ltrans-lsymb+1:nline) = ' '
  elseif (ltrans.gt.lsymb) then
    ! Shift the trailing characters to the right
    do i=nline,pos+lsymb,-1
      line(i+ltrans-lsymb:i+ltrans-lsymb) = line(i:i)
    enddo
  endif
  ! Then replace symbol in-place
  line(pos:pos+ltrans-1) = trans(1:ltrans)
  nline = nline+ltrans-lsymb
  ! Move the cursor at the end of the translation. We could also move
  ! the cursor at the start of the translation to enable recursion,
  ! with proper adaptation of the callers.
  pos = pos+ltrans-1
  !
end subroutine replace_symlog
