subroutine feuille_cherche(dir,nom,segm,found)
  use gtv_interfaces, except_this=>feuille_cherche
  use gtv_buffers
  use gtv_tree
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Recherche une feuille donnee en argument, dans un macrosegment
  ! repere par 'dir'. Rend found a vrai si la feuille existe, a faux
  ! sinon.
  !---------------------------------------------------------------------
  type(gt_directory)            :: dir    ! Starting directory
  character(len=*), intent(in)  :: nom    ! Name to search for
  type(gt_segment), pointer     :: segm   ! Segment found, if any
  logical,          intent(out) :: found  ! Found it?
  ! Local
  integer :: l1,l2,i1
  !
  found = .false.
  l1 = len_trim(nom)
  i1 = index(nom,'*')  ! enable pseudo-wildcarding. The idea is to enable
                       ! the existence of one '*' in the segment name, and
                       ! check against it.
  segm => dir%leaf_first
  do while (associated(segm))
    l2 = len_trim(segm%head%gen%name)
    !
    if (i1.eq.0) then
      if (segm%head%gen%name.eq.nom) found = .true.
    elseif (i1.eq.1) then
      if (l2-l1+i1+1.ge.1) then
        if (segm%head%gen%name(l2-l1+i1+1:l2).eq.nom(i1+1:l1))  found = .true.
      endif
    else
      if (l2-l1+i1+1.ge.1) then
        if ( segm%head%gen%name(l2-l1+i1+1:l2).eq.nom(i1+1:l1) .and.  &
             segm%head%gen%name(1:i1-1)       .eq.nom(1:i1-1) )  found = .true.
      endif
    endif
    !
    if (found)  exit
    !
    segm => segm%nextseg
  enddo
  !
end subroutine feuille_cherche
!
subroutine fils_cherche(dir,nom,trouve,found)
  use gtv_interfaces, except_this=>fils_cherche
  use gtv_buffers
  use gtv_tree
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Recherche un fils donnee en argument, dans un macrosegment repere
  ! par 'dir'. Rend l'adresse de ce fils dans 'trouve'. Rend found a
  ! vrai si le fils existe, a faux sinon
  !---------------------------------------------------------------------
  type(gt_directory)              :: dir     ! Starting directory
  character(len=*),   intent(in)  :: nom     ! Name to search for
  type(gt_directory), pointer     :: trouve  ! Found address
  logical,            intent(out) :: found   ! Found it?
  ! Local
  type(gt_directory), pointer :: workdir
  !
  found = .false.
  workdir => dir%son_first
  !
  do while (associated(workdir))
    if (workdir%gen%name.eq.nom) then
      trouve => workdir
      found = .true.
      return
    endif
    workdir => workdir%brother
  enddo
  !
end subroutine fils_cherche
!
subroutine ret_pere(dir,trouve,error)
  use gtv_interfaces, except_this=>ret_pere
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Partant de la directorie reperee par 'dir', on remonte jusqu'a son
  ! pere repere par 'trouve'. error est mis a True si on cherche a
  ! remonter au dela de root.
  !---------------------------------------------------------------------
  type(gt_directory)          :: dir     ! Starting directory
  type(gt_directory), pointer :: trouve  ! Found address
  logical,      intent(inout) :: error   ! Logical error flag
  !
  trouve => dir%father
  error = .not.associated(dir%father)  ! i.e. 'dir' is root
  !
end subroutine ret_pere
!
subroutine decode_chemin(chemin,init,dir,isdir,segm,found)
  use gtv_buffers
  use gtv_interfaces, except_this=>decode_chemin
  use gtv_tree
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Partant d'une directorie reperee par 'init', on cherche a
  ! atteindre un segment ou un macro segment specifie par chemin
  ! (relatif). Si le chemin est absolu, 'init' est ignore et on
  ! cherche depuis la racine.
  ! On peut aussi lire le directory courant et renvoyer son adresse si
  ! son nom correspond a chemin. Si on y arrive alors, le but est
  ! specifie par 'dir' et found est true; sinon found est false.
  ! isdir = .true. si le dernier element lu est un macrosegment, .false.
  ! sinon.
  !---------------------------------------------------------------------
  character(len=*),   intent(in)  :: chemin  ! Input path
  type(gt_directory), pointer     :: init    ! Directory to search from
  type(gt_directory), pointer     :: dir     ! Directory of the target
  logical,            intent(out) :: isdir   ! Target is a directory
  type(gt_segment),   pointer     :: segm    ! Pointer to the segment target, if not a directory
  logical,            intent(out) :: found   ! Target was found
  ! Local
  integer :: ptr_deb,ptr_fin
  logical :: absolute,last,error
  type(gt_directory), pointer :: dep
  !
  error = .false.
  !
  ! 1) Cas particulier 1: Chemin vaut < tout seul.
  if (chemin.eq.dir_root) then
    dir => root
    isdir = .true.
    segm => null()
    found = .true.
    return
  endif
  !
  ! 2) Cas particulier 2: le grand-pere
  if (chemin.eq.dir_top) then
    dir => init%ancestor
    isdir = .true.
    segm => null()
    found = .true.
    return
  endif
  !
  absolute = chemin(1:1).eq.dir_sep
  dir => null()
  found = .false.
  segm => null()
  isdir = .false.
  !
  ! 3) Path starts with "<": it is absolute. We start from root, and 'init'
  ! is ignored
  if (absolute) then
    last = .false.
    ptr_deb = 2
    dep => root
    call next_nom(chemin(ptr_deb:),ptr_deb,ptr_fin,last)
    call fils_cherche(root,chemin(ptr_deb:ptr_fin),dir,found)
    do while (.not.last .and. found)
      dep => dir
      !
      ! Get next name
      ptr_deb = ptr_fin+2
      call next_nom(chemin(ptr_deb:),ptr_deb,ptr_fin,last)
      !
      ! Handle ".."
      if (chemin(ptr_deb:ptr_fin).eq.dir_up) then
        call ret_pere(dep,dir,error)
        if (error) then
          found = .false.
          return
        endif
      else
        call fils_cherche(dep,chemin(ptr_deb:ptr_fin),dir,found)
      endif
      !
    enddo
    !
    ! Il s'agit maintenant de tester si le dernier nom contenu dans le
    ! chemin est un segment ou un macrosegment
    if (.not.found .and. .not.last)  return
    if (last) then
      ! Est ce un segment ?
      call feuille_cherche(dep,chemin(ptr_deb:),segm,found)
      if (found)  then
        isdir = .false.
        return
      endif
      !
      ! Est ce un macro segment ? (Il n'a pas ete teste dans le do while,
      ! puisque c'etait le dernier et que donc next_nom a rendu last = .true.)
      call fils_cherche(dep,chemin(ptr_deb:),dir,found)
      if (found)  isdir = .true.
      return
    endif
  endif  ! Fin du chemin absolu.
  !
  ! 4) Cas general
  dep => init
  ptr_deb = 1
  call next_nom(chemin(ptr_deb:),ptr_deb,ptr_fin,last)
  do while (.not.last)
    if (chemin(ptr_deb:ptr_fin).eq.dir_up) then
      call ret_pere(dep,dir,error)
      if (error) then
        found = .false.
        return
      endif
      dep => dir
    else
      call fils_cherche(dep,chemin(ptr_deb:ptr_fin),dir,found)
      dep => dir
      if (.not.found) return
    endif
    ptr_deb = ptr_fin + 2
    call next_nom(chemin(ptr_deb:),ptr_deb,ptr_fin,last)
  enddo
  !
  ! On est sorti avec last = .true.
  ! Il reste a traiter le dernier morceau de chemin
  ! Il peut s'agir de .. : dans ce cas, appel de ret_pere
  if (chemin(ptr_deb:ptr_fin).eq.dir_up) then
    call ret_pere(dep,dir,error)
    if (error)  then
      isdir = .false.
      found = .false.
    else
      isdir = .true.
      found = .true.
    endif
    return
  endif
  !
  ! Est ce un segment ?
  call feuille_cherche(dep,chemin(ptr_deb:ptr_fin),segm,found)
  if (found) then
    dir => dep
    isdir = .false.
    return
  endif
  !
  ! Est ce un macro segment ? (Il n'a pas ete teste dans le do while, puisque
  ! c'etait le dernier et que donc next_nom a rendu last = .true.
  found = .false.
  call fils_cherche(dep,chemin(ptr_deb:ptr_fin),dir,found)
  if (found) then
    isdir = .true.
    return
  endif
  !
end subroutine decode_chemin
!
subroutine next_nom(nom,ptr_deb,ptr_fin,last)
  use gtv_interfaces, except_this=>next_nom
  use gtv_tree
  !---------------------------------------------------------------------
  ! @ private
  ! Rend dans ptr l'indice de fin d'un nom lu entre deux separateurs <
  ! last est vrai si c'est le dernier nom de la chaine de caracteres
  ! ATTENTION
  ! ptr_deb et ptr_fin sont des pointeurs dans la chaine d'ORIGINE
  ! (Chaine d'origine transmise par nom(ptr_deb:)
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: nom      ! String to parse
  integer,          intent(in)  :: ptr_deb  ! Offset to add to the returned index
  integer,          intent(out) :: ptr_fin  ! Index of the end of next name
  logical,          intent(out) :: last     ! No more name after this
  ! Local
  integer :: indice
  !
  indice = index(nom,dir_sep)
  if (indice .eq. 0) then
    last = .true.
    ptr_fin = ptr_deb + len_trim(nom)-1
    return
  endif
  !
  ptr_fin = ptr_deb-1 + indice-1
  last = .false.
  ! Cas particulier du chemin se terminant par <
  if (indice .eq. len_trim(nom)) last = .true.
  !
end subroutine next_nom
!
subroutine cree_chemin_dir(start,chemin,lch)
  use gtv_interfaces, except_this=>cree_chemin_dir
  use gtv_buffers
  use gtv_tree
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Return the absolute path from root '<' to directory given by 'start'
  !---------------------------------------------------------------------
  type(gt_directory)            :: start   ! Directory to be resolved
  character(len=*), intent(out) :: chemin  ! Output name (full path)
  integer,          intent(out) :: lch     ! Length of output
  ! Local
  type(gt_directory), pointer :: dir
  !
  if (.not.associated(start%father)) then
    chemin = dir_root
    lch = len_trim(dir_root)
    return
  endif
  !
  chemin = start%gen%name
  dir => start%father
  do while (associated(dir%father))
    chemin = trim(dir%gen%name)//dir_sep//chemin
    dir => dir%father
  enddo
  chemin = dir_root//chemin
  !
  lch = len_trim(chemin)
  !
end subroutine cree_chemin_dir
!
subroutine cree_chemin_seg(segm,chemin,lch)
  use gtv_interfaces, except_this=>cree_chemin_seg
  use gtv_tree
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !   Return the absolute path from root '<' to the segment given by
  ! 'segm'.
  !---------------------------------------------------------------------
  type(gt_segment)              :: segm    ! Pointer to segment
  character(len=*), intent(out) :: chemin  ! Output name (full path)
  integer,          intent(out) :: lch     ! Length of output
  !
  ! Path
  call cree_chemin_dir(segm%father,chemin,lch)
  !
  ! Add the segment name
  chemin = trim(chemin)//dir_sep//segm%head%gen%name
  lch = len_trim(chemin)
  !
end subroutine cree_chemin_seg
!
subroutine get_nomgrandpere(nom)
  use gtv_buffers
  use gtv_interfaces, except_this=>get_nomgrandpere
  use gtv_tree
  use gtv_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Return the name of the 'grandpere' branch from current directory.
  !---------------------------------------------------------------------
  character(len=*), intent(out) :: nom  ! Returned name
  !
  nom = cw_directory%ancestor%gen%name
  !
end subroutine get_nomgrandpere
