program sequentiel_indexe
  implicit none
  character(len=19), dimension(2), parameter :: f_index = &
        (/ "index_naissance.dat", "index_deces.dat    " /)
  character(len=80) :: musicien
  integer           :: lrecl

  ! Ouverture du fichier des musiciens en accès direct
  ! ainsi que des fichiers d'index.
  open ( unit=1,          file = f_index(1),                &
         status="old",    form="formatted", action="read" )
  open ( unit=2,          file = trim(f_index(2)),          &
         status="old",    form="formatted", action="read" )
  inquire( iolength=lrecl ) musicien
  open ( unit=3,          file="musiciens.bin",             &
         status="old",    form="unformatted",               &
         access="direct", action="read", recl=lrecl )

  call recherche_musicien

  close( unit=1 )
  close( unit=2 )
  close( unit=3 )
end program sequentiel_indexe

subroutine recherche_musicien
  implicit none
  integer, parameter :: EOF = -1
  character(len=50)  :: prompt_date, message
  character(len=4)   :: date_saisie, date_lue
  integer            :: unite_index

  do
    ! Type de date : naissance ou décès
    if ( choix_date() == EOF ) exit
    ! Lecture d'une date.
    if ( lecture_date() == EOF) exit 
    ! Recherche du ou des musiciens
    if ( .not. musicien_trouve() ) &
      print *,"Aucun musicien ne répond à la demande"
    print *
  end do

contains

  integer function choix_date()
    integer   ios_stdin, reponse
    character tabulation

    tabulation = achar(9)
    do
      print"(2a)",tabulation,'--------------------------------'
      print"(2a)",tabulation,'Choix du critère de recherche : '
      print"(2a)",tabulation,'- par date de naissance (1)'
      print"(2a)",tabulation,'- par date de décès     (2)'
      print"(2a)",tabulation,'- QUITTER               (3)'
      print"(2a)",tabulation,'--------------------------------'
      read(*, *, IOSTAT=ios_stdin) reponse
      if ( ios_stdin < 0 ) then
        choix_date = EOF
        return
      else if ( ios_stdin > 0 ) then
        print "(/,a,/)", "Erreur dans la saisie"
      else
        if ( reponse < 1 .or. reponse > 3 ) then
          print *,"Choix invalide."
        else
          exit
        end if
      end if
    end do

    select case (reponse)
      case(1) ! Recherche par date de naissance.
        prompt_date = "Entrer une date de naissance d'un musicien"
        message = "Liste des musiciens nés en"
      case(2) ! Recherche par date de décès.
        prompt_date = "Entrer une date de décès d'un musicien"
        message = "Liste des musiciens morts en"
      case(3) ! Quitter
        choix_date = EOF
        return
    end select
    unite_index = reponse
    rewind( unit=unite_index )
    choix_date = 0
  end function choix_date

  function lecture_date()
    integer lecture_date
    integer ios_stdin

    do
      print "(/,a)", trim(prompt_date)
      read(*, *, IOSTAT=ios_stdin) date_saisie
      if( ios_stdin < 0 ) then
        lecture_date = EOF
        return
      else if( ios_stdin > 0 ) then
        print "(/,a,/)", "Date erronée!"
      else
        message = trim(message)//" "//date_saisie
        exit
      end if
    end do
    lecture_date = 0
  end function lecture_date

  function musicien_trouve()
    logical musicien_trouve
    ! Déclarations locales
    character(len=80) :: musicien
    character(len=11) :: fmt = "(/,a,/,  a)"
    integer           :: i, taille_message, numrec

    taille_message = len_trim(message)
    
    write( fmt(8:9), "(i2)" ) taille_message
    print fmt, message, ("-",i=1,taille_message)

    musicien_trouve = .false.
    do
      read( unit=unite_index, fmt=*, END=1 ) date_lue, numrec
      if ( date_lue == date_saisie ) then
        ! On lit l'enregistrement correspondant.
        musicien_trouve = .true.
        read( unit=3, rec=numrec ) musicien
        print "(2a)"," - ", trim(musicien)
      end if
    end do
1   return
  end function musicien_trouve
end subroutine recherche_musicien

