! Program Example from "Essential Fortran 90 & 95" by Loren P. Meissner
! Copyright 1996. Copying for sale requires permission from the author.
! Otherwise, distribution is permitted if these three lines are included.

  module H03M
    implicit none
    public :: Fill, Search, Update, Insert, Print_It
    integer, parameter, public :: ARRAY_SIZE = 21, NAME_LENGTH = 20
    type, private :: List_Type
      character (len = NAME_LENGTH), dimension(ARRAY_SIZE) :: List
      integer :: List_Length
    end type List_Type
    integer, private :: K  ! K is an ACID variable
    type (List_Type), save, private :: X = List_Type( (/ ("", K = 1, ARRAY_SIZE) /), 0 )
  contains

    subroutine Fill( Data )
      character(len = *), dimension(:), intent(in) :: Data
  ! start subroutine Fill
      X % List(: size( Data)) = Data
      X % List_Length = size( Data )
      return
    end subroutine Fill

    subroutine Search( Search_Key, Exit_Code, Location )
      character (len = *), intent(in) :: Search_Key
      character (len = *), intent(out) :: Exit_Code
      integer, intent(out) :: Location
      integer :: Loop
  ! start subroutine Search
      do Loop = 1, X % List_Length
        Location = Loop
        if (X % List(Loop) == Search_Key) then
          Exit_Code = "FOUND"
          return
        else if (X % List(Loop) > Search_Key) then
          Exit_Code = "NOT FOUND"
          return
        else
          ! Continue searching
        end if
      end do
      Exit_Code = "NOT FOUND"
      return
    end subroutine Search

    subroutine Update( Search_Key, Location )
      character (len = *), intent(in) :: Search_Key
      integer, intent(in) :: Location
  ! start subroutine Update
      write (unit = *, fmt = *) " Found:  ", Search_Key, " at: ", Location
      return
    end subroutine Update

    subroutine Insert( Search_Key, Location )
    character (len = *), intent(in) :: Search_Key
    integer, intent(in) :: Location
  ! start subroutine Insert
      write (unit = *, fmt = *) " Insert: ", Search_Key, " at: ", Location
      X % List(Location + 1: X % List_Length + 1) = X % List(Location: X % List_Length)
      X % List_Length = X % List_Length + 1
      X % List(Location) = Search_Key
      return
    end subroutine Insert

    subroutine Print_It( )
      integer :: I
  ! start subroutine Print_It
      do I = 1, X % List_Length
        write (unit = *, fmt = *) I, " ", X % List(I)
      end do
      return
    end subroutine Print_It

  end module H03M
