      program hw02_02

      implicit none

*     Program to read a paragraph and comoute the mean and rms about
*     the mean of the number of characters per word and the number of 
*     words per sentence.


      integer*4 lenline  ! function to return non-blank length of line
      integer*4 len_in    ! length of input line.
      integer*4 ierr     ! IOSTAT error variable for file open and read
      integer*4 num_char ! Number of characters in current word
      integer*4 num_word ! Number of words in while file
      integer*4 num_sent ! Number of sentences in file
      integer*4 num_word_insent ! Number of words in current sentence
      integer*4 sum_num_char ! Sum of total number of chacters
      integer*4 sum_num_word ! Sum of number of words
      integer*4 sum_num_char_sq ! Sum of number of characters squared
      integer*4 sum_num_word_sq ! Sun of number of words squared

      integer*4 j   ! Loop counter over characters in inline

      logical still_in_word ! set true for hypenated word to show we
                            ! are still in word on new line
      logical in_gap  ! Set true when space is found incase there are
                      ! more than one-space between words and when 
                      ! the end of sentence is found.

      real*4 mean_char, rms_char   ! Mean and RMS number of characters
                      ! per word
      real*4 mean_sent, rms_sent   ! Mean and RMS of words per sentence.

      character*128 infile  ! Input file name (read from runstring)
      character*256 inline  ! Line read from file.

****  Get file name
      call getarg(1,infile)
      if( lenline(infile).eq.0 ) then
          infile = 'Q2_text.txt'
      endif 

****  Now open the file
      open(50,file=infile,iostat=ierr,status='old')
      if( ierr.ne.0 ) then
          call report_error(ierr,
     .        'Opening file ' // infile(1:lenline(infile)))      
          stop 'HW2_2: Error opening input file name'
      endif

****  Now initialize the counters we will need
      num_char = 0
      num_word = 0
      num_sent = 0
      num_word_insent = 0
      sum_num_char = 0
      sum_num_word = 0
      sum_num_char_sq = 0
      sum_num_word_sq = 0
      still_in_word = .false.   ! Needed when word hypenated
      in_gap = .false.

****  Loop over the file, counting characeters and words
      do while ( ierr.eq.0 )
         read(50,'(a)',iostat=ierr) inline
         if( ierr.eq.0 ) then
            len_in = lenline(inline)

*           Scan the input line, counting as we go
            do j = 1,len_in
               if( (inline(j:j).ge.'a' .and. inline(j:j).le.'z') .or.
     .             (inline(j:j).ge.'A' .and. inline(j:j).le.'Z') ) then
*                 This just a regular letter
                  num_char = num_char + 1
                  in_gap = .false.
               elseif ( inline(j:j).eq.' ' .and. .not. in_gap ) then
*                 We have space and so a word has ended
                  num_word = num_word + 1
                  num_word_insent = num_word_insent + 1
                  sum_num_char = sum_num_char + num_char
                  sum_num_char_sq = sum_num_char_sq + num_char**2 
*                 Reset number of characters and that we are in gap
                  num_char = 0
                  in_gap = .true.
               elseif ( inline(j:j).eq.'.' .or. 
     .                  inline(j:j).eq.'?' ) then
*                 End of a word and so increment same as space
                  if( num_char.gt.0 ) then 
                     num_word = num_word + 1
                     num_word_insent = num_word_insent + 1
                     sum_num_char = sum_num_char + num_char
                     sum_num_char_sq = sum_num_char_sq + num_char**2 
*                    Reset number of characters and that we are in gap
                     num_char = 0
                  endif

*                 We are at the end of a sentence
                  num_sent = num_sent + 1
                  sum_num_word = sum_num_word + num_word_insent
                  sum_num_word_sq = sum_num_word_sq + num_word_insent**2
                  num_word_insent = 0
                  in_gap = .true.
               elseif (inline(j:j).eq.'-') then
*                 Hypenated word, so keep character count going
                  still_in_word = .true.
*              Ignore any other characeters (:, ;, numbers) 
               endif 
            end do
*           We have reached the end of the linw and normally this 
*           would mark the end of a word.  Increment counts and for
*           hypen
            if( .not. still_in_word ) then
               if( num_char.gt.0 ) then
                  num_word = num_word + 1
                  num_word_insent = num_word_insent + 1
                  sum_num_char = sum_num_char + num_char
                  sum_num_char_sq = sum_num_char_sq + num_char**2 
*                 Reset number of characters and that we are in gap
                  num_char = 0
               endif
            endif
            still_in_word = .false.
         endif
      enddo

*     Now finish up the calcuations
      mean_char = float(sum_num_char)/num_word
      if( num_word.gt.1 ) then 
          rms_char = sqrt((sum_num_char_sq - num_word*mean_char**2)/
     .                    (num_word-1))
      else
          rms_char = 0.0
      end if

      mean_sent = float(sum_num_word)/num_sent
      if( num_sent.gt.1 ) then
         rms_sent = sqrt((sum_num_word_sq - num_sent*mean_sent**2)/
     .                   (num_sent-1))
      else
         rms_sent = 0.0
      endif 

*     Ouptu the results
      write(*,220) infile(1:lenline(infile)),
     .             mean_char, rms_char, num_word,
     .             mean_sent, rms_sent, num_sent
220   format('12.010 HW02_02: In file ',a,' there are:',/,
     .       'Mean chacters per word  ',F5.2,' with RMS ',
     .        f5.2,' in ',i4,' words;',/,
     .       'Mean words per sentence ',F5.2,' with RMS ',
     .        F5.2,' in ',i4,' sentences',/)


      close(50)
      end


      subroutine report_error(ierr,mess)

      implicit none

*     Routine to report IOSTAT errors.  Initially developed
*     for 12.010 HW2 Problem 2.

* PASSED VARIABLES

      integer*4 ierr
      character*(*) mess

* LOCAL VARIABLES
* None
      
***** See if the IOSTAT error was non-zero
      if( ierr.ne.0 ) then
         write(*,120) ierr, mess
 120     format(/,'IOSTAT Error ',i4,' occurred ',a)
      end if

      return
      end
 
      integer*4 function lenline(in)

      implicit none

*     Returns length of used portion of string.  Originally
*     developed for HW2 Problem 2.  f90 has an intrisic called
*     len_trim(<string>) that performs the same function.

* PASSED VARIABLES
      
      character*(*) in   ! The string passed that we need to find
                          ! the last character of

* LOCAL VARIABLES
      integer*4 len_in    ! Declared length of in string
      integer*4 i         ! Counter used to work backwards through string

***** Get the declared length of string
      len_in = LEN(in)
      i = len_in
      do while ( i.gt.0 .and. in(i:i).eq.' ')
          i = i - 1
      end do

      lenline = i

      return
      end

