subroutine blank_fill(oct,long)
  !---------------------------------------------------------------------
  ! @ private
  ! Blank the input string along its 'long' first chars. Work with
  ! integer*1 values instead of characters.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)  :: long       ! Length of string
  integer(kind=1), intent(out) :: oct(long)  ! String retrieved as a I*1 array
  ! Local
  integer(kind=4) :: i
  !
  do i=1,long
    oct(i) = ichar(' ')
  enddo
end subroutine blank_fill
!
subroutine ctodes(string,nc,addr)
  use gsys_interfaces, except_this=>ctodes
  use gildas_def
  !---------------------------------------------------------------------
  ! @ public
  ! Copy at address the value of 'string'. nc is the maximum length
  ! (number of bytes) of the string to copy.
  !---------------------------------------------------------------------
  character(len=*),             intent(in) :: string  !
  integer(kind=4),              intent(in) :: nc      !
  integer(kind=address_length), intent(in) :: addr    ! Address is not modified
  ! Local
  integer(kind=1) :: membyt(1)
  integer(kind=address_length) :: ipnt,jpnt,opnt
  integer(kind=4) :: length
  !
  jpnt = addr
  opnt = bytpnt(jpnt,membyt)
  ipnt = bytpnt(locstr(string),membyt)
  call blank_fill(membyt(opnt),nc)    ! Could be shortened
  length = min(nc,len(string))
  call bytoby(membyt(ipnt),membyt(opnt),length)
end subroutine ctodes
!
subroutine destoc(nc,addr,string)
  use gildas_def
  use gsys_interfaces, except_this=>destoc
  !---------------------------------------------------------------------
  ! @ public
  ! Copy in 'string' the value referenced at address 'addr'. nc
  ! is the maximum length (number of bytes) of the string to copy.
  !---------------------------------------------------------------------
  integer(kind=4),              intent(in)  :: nc      !
  integer(kind=address_length), intent(in)  :: addr    !
  character(len=*),             intent(out) :: string  !
  ! Local
  integer(kind=1) :: membyt(1)
  integer(kind=address_length) :: ipnt,jpnt,opnt
  integer(kind=4) :: length
  !
  string = ' '
  jpnt = addr
  ipnt = bytpnt(jpnt,membyt)
  opnt = bytpnt(locstr(string),membyt)
  length = min(nc,len(string))
  call bytoby(membyt(ipnt),membyt(opnt),length)
end subroutine destoc
!
function match_string(string,pattern)
  !---------------------------------------------------------------------
  ! @ public
  ! Basic function for regular expression matching. Only '*' is
  ! currently recognized as a special character.
  !  * : matches 0 or more characters
  ! By construction, tolerate contiguous stars e.g. 'AB***CD'. Matching
  ! is case-sensitive.
  !---------------------------------------------------------------------
  logical                      :: match_string  ! Return value
  character(len=*), intent(in) :: string        ! String to test
  character(len=*), intent(in) :: pattern       ! Pattern to match
  ! Local
  integer(kind=4) :: ppos,spos,p1,p2,s1
  logical :: start
  !
  ! Now extensive tests
  match_string = .false.
  p1 = 1
  s1 = 1
  start = .true.
  do while (.true.)
     !
     ! 1st return case: no more pattern to match
     if (pattern(p1:).eq.'')  return  ! Each piece has matched something
     !
     spos = index(pattern(p1:),'*')  ! Star position
     !
     if (spos.eq.0) then
       ! 2nd return case: no (more) stars
       p2 = len_trim(pattern)
       ppos = index(string(s1:),pattern(p1:p2),.true.)  ! Backward search
       if (ppos.eq.0) then
         match_string = .false.
       elseif (start) then
         match_string = string(s1:).eq.pattern(p1:p2)
       else
         ! Here end of strings must match
         match_string = (ppos+p2-p1).eq.len_trim(string(s1:))
       endif
       return
     !
     elseif (spos.eq.1) then
       ! Found a '*' at left position
       p1 = p1+1
       if (start) then
         start=.false.
         match_string = .true.  ! Revert the default on return
       endif
       cycle
     !
     else
       p2 = p1+spos-2
     endif
     !
     ! Pattern position
     ppos = index(string(s1:),pattern(p1:p2))
     !
     ! 3rd return case: no match
     if (ppos.eq.0) then
        match_string = .false.
        return
     endif
     !
     ! Special left boundary condition
     if (start .and. spos.gt.1) then
        match_string = ppos.eq.1
        if (.not.match_string)  return
     endif
     !
     ! Prepare next loop
     s1 = s1+ppos+p2-p1
     p1 = p1+spos
     if (start)  start=.false.
     !
  enddo
  !
end function match_string
