subroutine sic_lower(c)
  !---------------------------------------------------------------------
  ! @ public
  !  Converts a character string to lowercase.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: c  ! Character string
  ! Local
  integer(kind=4) :: i,ic
  do i=1,len(c)
    if (c(i:i).ge.'A' .and. c(i:i).le.'Z') then
      ic = ichar(c(i:i))+ichar('a')-ichar('A')
      c(i:i)=char(ic)
    endif
  enddo
end subroutine sic_lower
!
subroutine sic_upper(c)
  !---------------------------------------------------------------------
  ! @ public
  !  Converts a character string to uppercase.
  !  Slow if called frequently to convert a single character.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: c  ! Character string
  ! Local
  integer(kind=4) :: i,ic
  !
  do i=1,len(c)
    if (c(i:i).ge.'a' .and. c(i:i).le.'z') then
      ic=ichar(c(i:i))+ichar('A')-ichar('a')
      c(i:i)=char(ic)
    endif
  enddo
end subroutine sic_upper
!
function lenc(c)
  !---------------------------------------------------------------------
  ! @ public
  !  Returns the location of the last non-blank character in a string.
  !---------------------------------------------------------------------
  integer(kind=4) :: lenc  ! Function value on return
  character(len=*), intent(in) :: c  ! Character string
  ! Local
  integer(kind=4) :: i
  !
  do i=len(c),1,-1
    if (ichar(c(i:i)).gt.32) then
      lenc = i
      return
    endif
  enddo
  lenc = 0
end function lenc
!
subroutine sic_blanc(c,n)
  !---------------------------------------------------------------------
  ! @ public
  !   Reduce the character string C to the standard SIC internal syntax.
  !   Suppress all unecessary separators.
  !   Character strings "abcd... " are not modified.
  !   Convert to upper case all characters.
  !   Ignores and destroys comments.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: c  ! Character string to be formatted
  integer(kind=4),  intent(inout) :: n  ! Length of C
  ! Local
  integer(kind=4) :: i,nl
  logical :: lo,li,chaine,some
  integer(kind=4), parameter :: tab=9
  !
  if (n.eq.0) return
  !
  li = .false.
  lo = .true.
  chaine = .false.
  some = .false.
  nl = n
  n = 0
  i = 1
  !
  do while (i.le.nl)
    !
    ! Skip character strings
    if (c(i:i).eq.'"') then
      chaine=.not.chaine
    endif
    if (chaine) goto 30
    !
    ! Suppress redondant separators
    li=.false.
    if (c(i:i).ne.' ' .and. c(i:i).ne.char(tab)) goto 20
    ! Space separator
    li=.true.
    ! Not the first one
    if (lo)  goto 100
    ! First one
    c(i:i) = ' '
    goto 30
    !
    ! Skip comment area
20  continue
    if (c(i:i).eq.'!') then
      some=.true.
      exit  ! while loop
    endif
    !
    ! Reset input character string
30  n=n+1
    if (i.ne.n) c(n:n) = c(i:i)
    if (i.gt.n) c(i:i) = ' '
100 lo=li
    !
    ! End of loop
    i = i+1
  enddo
  !
  ! Remove trailing separators if any
  if (n.ne.0) then
    if (c(n:n).eq.' ') n=n-1
  endif
  ! Clean up end of line
  if (n.lt.nl) c(n+1:) = ' '
  if (some) n=max(n,1)
end subroutine sic_blanc
!
subroutine sic_next(line,par,lpar,npar,dotab)
  !---------------------------------------------------------------------
  ! @ public
  !  Returns the next "word" of the command line. Words are separated
  ! by blanks, but also optionally by tabulations.
  !---------------------------------------------------------------------
  character(len=*),  intent(in)    :: line   ! Line to be analysed
  character(len=*),  intent(out)   :: par    ! Next word found
  integer(kind=4),   intent(out)   :: lpar   ! Length of word found
  integer(kind=4),   intent(inout) :: npar   ! Start point for analysis, updated for subsequent call
  logical, optional, intent(in)    :: dotab  ! Take also tabulations as separator?
  ! Local
  character(len=1), parameter :: space=' '
  character(len=1), parameter :: tabul=char(9)
  logical :: lw1, lw2, chaine,checktab
  integer(kind=4) :: l1,j,l2
  !
  if (present(dotab)) then
    checktab = dotab
  else
    checktab = .false.
  endif
  chaine = .false.
  lw1 = .false.
  lw2 = .true.
  l1 = 0
  do j = 1,len(line)
    !
    ! Character strings
    if (line(j:j).eq.'"') then
      if (.not.chaine) then
        l1 = j
        chaine = .true.
        goto 10
      endif
      l2 = j
      goto 20
    endif
    if (chaine) goto 10
    !
    ! Usual delimiters
    lw1 = line(j:j).eq.space .or. (checktab.and.line(j:j).eq.tabul)
    if (.not.lw1.and.lw2) then
      l1 = j
    elseif (lw1.and..not.lw2) then
      l2 = j-1
      goto 20
    endif
10  lw2 = lw1
  enddo
  l2 = j-1
  !
20 continue
  if (l1.gt.0) then
    lpar = l2 - l1 + 1
    npar = npar + lpar + 1
    if (.not.chaine) then
      par = line(l1:l2)
    else
      lpar = lpar-2
      par = line(l1+1:l2-1)
    endif
  else
    lpar = 0
  endif
end subroutine sic_next
!
subroutine sic_noir(cin,np)
  !---------------------------------------------------------------------
  ! @ public
  !  Reduce all separators to one.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: cin  ! Character string
  integer(kind=4),  intent(out)   :: np   ! Length of string
  ! Local
  integer(kind=4), parameter :: tab=9
  integer(kind=4) :: n,ni,i
  logical :: lo,li
  !
  ! Reduit les Separateurs
  lo = .false.
  ni = len_trim(cin)
  n  = 0
  do i=1,ni
    li=.true.
    if (cin(i:i).ne.' ' .and. cin(i:i).ne.char(9)) then
      n = n+1
      cin(n:n) = cin(i:i)
    else
      !
      ! C'est un blanc
      li=.false.
      if (lo) then
        ! C'est le premier
        n = n+1
        cin(n:n) = ' '
      endif
    endif
    lo = li
  enddo
  cin(n+1:) = ' '
  np = n
end subroutine sic_noir
!
subroutine sic_black(cin,np)
  !---------------------------------------------------------------------
  ! @ public
  !   Suppress all separators
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: cin  ! Character string
  integer(kind=4),  intent(out)   :: np   ! Length of string
  ! Local
  integer(kind=4), parameter :: tab=9
  integer(kind=4) :: n,ni,i
  !
  ! Reduit les Separateurs
  n  = 0
  ni = len_trim(cin)
  do i=1,ni
    if (cin(i:i).ne.' ' .and. cin(i:i).ne.char(9)) then
      n = n+1
      cin(n:n) = cin(i:i)
    endif
  enddo
  if (n.lt.ni) cin(n+1:) = ' '
  np = n
end subroutine sic_black
!
subroutine sic_upcase(c,n)
  !---------------------------------------------------------------------
  ! @ public
  !   Reduce the character string C to the standard SIC internal syntax.
  !   Suppress all unecessary separators.
  !   Character strings "abcd... " are not modified.
  !   Convert to upper case all characters.
  !   Ignores and destroys comments.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: c  ! Character string to be formatted
  integer(kind=4),  intent(inout) :: n  ! Length of string
  ! Local
  integer(kind=4) :: i,nl,ic
  logical :: lo,li,chaine,some
  integer(kind=4), parameter :: tab=9
  !
  if (n.eq.0) return
  !
  lo = .true.
  chaine = .false.
  some = .false.
  nl = n
  n = 0
  i = 1
  li = .false.
  !
  do while (i.le.nl)
    !
    ! Skip character strings
    if (c(i:i).eq.'"') then
      chaine=.not.chaine
    endif
    if (chaine) goto 30
    !
    ! Convert to upper case
    if (c(i:i).ge.'a' .and. c(i:i).le.'z') then
      ic = ichar(c(i:i))-ichar('a')+ichar('A')
      c(i:i)=char(ic)
    endif
    !
    ! Suppress redondant separators
    li=.false.
    if (c(i:i).ne.' ' .and. c(i:i).ne.char(tab)) goto 20
    ! Space separator
    li=.true.
    ! Not the first one
    if (lo)  goto 100
    ! First one
    c(i:i) = ' '
    goto 30
    !
    ! Skip comment area
20  continue
    if (c(i:i).eq.'!') then
      some=.true.
      exit  ! while loop
    endif
    !
    ! Reset input character string
30  n=n+1
    if (i.ne.n) c(n:n) = c(i:i)
    if (i.gt.n) c(i:i) = ' '
100 lo=li
    !
    ! End of loop
    i = i+1
  enddo
  !
  ! Remove trailing separators if any
  if (n.ne.0) then
    if (c(n:n).eq.' ') n=n-1
  endif
  ! Clean up end of line
  if (n.lt.nl) c(n+1:) = ' '
  if (some) n=max(n,1)
end subroutine sic_upcase
!
subroutine sic_separ(separ,line,par,lpar,npar)
  !---------------------------------------------------------------------
  ! @ public
  !  Returns the next "word" of the command line
  !---------------------------------------------------------------------
  character(len=1), intent(in)    :: separ  !
  character(len=*), intent(in)    :: line   !
  character(len=*), intent(out)   :: par    !
  integer(kind=4),  intent(out)   :: lpar   !
  integer(kind=4),  intent(inout) :: npar   !
  ! Local
  logical :: lw1, lw2, list_directed
  character(len=1) :: chaine, lsepar, csepar
  integer(kind=4) :: l1,j,l2,lj, ll
  !
  if (ichar(separ).eq.0) then
    list_directed = .true.
    lsepar = ' '
    chaine = ' '
    csepar = ','
  else
    list_directed = .false.
    lsepar = separ
  endif
  !
  lw1 = .false.
  lw2 = .true.
  l1 = 0
  l2 = -1
  lj = len_trim(line)
  !
  if (list_directed) then
    !!Print *,line(:lj)//'!'
    !
    do j = 1,lj
      !
      ! Character strings if needed...
      if (chaine.ne.' ') then
        ! We are in a string, is it the closing key ?
        if (line(j:j).eq.chaine) then
          l2 = j
          exit
        endif
        lw2 = lw1
        cycle
      else
        ! Is it an opening key
        if (line(j:j).eq.'"') then
          l1 = j
          chaine = '"'
          lw2 = lw1
          cycle
        else if (line(j:j).eq."'") then
          l1 = j
          chaine = "'"
          lw2 = lw1
          cycle
        endif
      endif
      !
      ! Termination delimiter
      if (line(j:j).eq.csepar) then
        l2 = j-1
        exit
      endif
      !
      ! Usual delimiters
      lw1 = line(j:j).eq.lsepar
      if (.not.lw1.and.lw2) then
        l1 = j
      elseif (lw1.and..not.lw2) then
        l2 = j-1
        exit
      endif
      lw2 = lw1
    enddo
    !
    if (l2.eq.-1) l2 = lj
    !
    if (l1.gt.0) then
      if (chaine.eq.' ') then
        lpar = l2 - l1 + 1
        par = line(l1:l2)
      else
        lpar = l2 - l1 - 1
        par = line(l1+1:l2-1)
      endif
      !
      ! Skip things until next non-delimiter
      do j=l2+1,lj
        !!Print *,l2,j,line(1:j)//'!'
        if (line(j:j).eq.csepar) then
          npar = npar+j
          exit
        else if (line(j:j).ne." ") then
          npar = npar+j-1
          exit
        endif
      enddo
      !!Print *,'NPAR final ',npar
   else
      lpar = 0
    endif
    !
  else
    !
    do j = 1,lj
      !
      ! Usual simple delimiters, no strings...
      lw1 = line(j:j).eq.lsepar
      if (.not.lw1.and.lw2) then
        l1 = j
      elseif (lw1.and..not.lw2) then
        l2 = j-1
        exit
      endif
      lw2 = lw1
    enddo
    if (l2.eq.-1) l2 = lj
    !
    if (l1.gt.0) then
      lpar = l2 - l1 + 1
      npar = npar + lpar + 1
      par = line(l1:l2)
    else
      lpar = 0
    endif
  endif
end subroutine sic_separ
