      program survey
!
!     Distribute error in closed surveying travese.  In a
!     closed surveying traverse of N legs, the sum of the N
!     interior angles MUST equal 180(N-2) degrees.  If not,
!     the difference is attributed to measuring error.  The
!     difference is distributed equally among the N angles
!     in the form of an adjustment.
!
!     An example of a closed surveying traverse is a building
!     perimeter or property line.  Here, the surveyor begins
!     at some point on the line and measures the interior angle
!     the current "leg" makes with the last.  Some measurement
!     error is present each time the surveyor uses the transit.
!     This program "distributes" that error equally along the
!     traverse.
!
      type mark
           real                 :: angle
           type (mark), pointer :: next_mark
      end  type mark

      type ( mark ), pointer    :: begin
      type ( mark ), pointer    :: temp
      type ( mark ), pointer    :: traverse

      real                      :: adjustment      = 0.0
      real                      :: angle_input
      integer                   :: legs            = 0
      logical                   :: need_adjustment = .false.
      real                      :: total_angles    = 0.0
!
!     Initialize the beginning point of the traverse and
!     clear the link to the next mark.
      allocate ( begin )
      traverse => begin
      nullify ( traverse%next_mark )
!
!     Read interior angles.
      print *, " "
      print *, "Enter angles (0 to finish) ..."
      do
100      continue
         read ( *,*,err=100,end=200 ) angle_input
         if ( angle_input .le. 0.0 ) then
              exit
         else if ( angle_input .ge. 180.0 ) then
              print *, "Angles must be less than 180 degrees!"
              go to 100
         end if
!
!        Store the angle just read, allocate memory for the
!        next measurement, and point to that newly allocated
!        memory.
         traverse%angle = angle_input
         allocate ( traverse%next_mark )
         traverse => traverse%next_mark
!
!        Keep a count of the number of angles.
         legs = legs + 1
      end do
!
!     Clear the pointer at the end of the list.
200   continue
      nullify ( traverse%next_mark )
!
!     Advise the user that all angles have been read.
      print *, " "
      print *, "All", legs, "angles have been read ..."
!
!     Bail-out if there are less than three angles.
      if ( legs .lt. 3 ) then
           print *, " "
           print *, "ERROR! Fewer than 3 angles read!"
           go to 600
      end if
!
!     Add up the angles.
      traverse => begin
      do
         total_angles = total_angles + traverse%angle
         traverse => traverse%next_mark
         if ( .not. associated ( traverse%next_mark ) ) exit
      end do
!
!     Compute the measurement error.
      adjustment = ( ( ( legs - 2 ) * 180 ) - total_angles ) / legs
      print *, " "
      print *, "Measurement adjustment is", adjustment, "degrees."
      if ( abs ( adjustment ) .gt. 0.0 ) need_adjustment = .true.
!
!     Adjust each entry.
      print *, " "
      traverse => begin
      i = 0
      do
         i = i + 1
         write ( *,300,advance="NO" ) i, traverse%angle
300      format ( ' ', 'Angle ', i2.2, ' is ', f10.5 )
         if ( need_adjustment ) then
              traverse%angle = traverse%angle + adjustment
              write ( *,400,advance="NO" ) traverse%angle
400           format ( ' adjusted to ', f10.5 )
         end if
         write ( *,500 )
500      format ( ' degrees.' )
         traverse => traverse%next_mark
         if ( .not. associated ( traverse%next_mark ) ) exit
      end do
!
!     Deallocate the linked list.
      traverse => begin
      do
         temp => traverse%next_mark
         deallocate ( traverse )
         if ( .not. associated ( temp%next_mark ) ) exit
         traverse => temp
      end do
      nullify ( begin )
      nullify ( temp  )
!
!     End of program.
600   continue
      print *, " "
      end program survey
