!
      module mk_hvols
!
! Enable history mss path file name expansion, e.g.:
! "/FOSTER/file1","to","/FOSTER/file5","by","1" becomes
! "/FOSTER/file1","/FOSTER/file2",...,"/FOSTER/file5" 
! See function mkhvols. This is called from input.
!
      contains
!-----------------------------------------------------------------------
      logical function isdigit(s)
      implicit none
      character(len=1),intent(in) :: s
      character(len=1) :: digits(10)=
     +  (/'0','1','2','3','4','5','6','7','8','9'/)
      integer :: i
      isdigit = .false.
      do i=1,10
        if (s==digits(i)) then
          isdigit = .true.
          exit
        endif
      enddo
      end function isdigit
!-----------------------------------------------------------------------
      function ndollars(s)
      character(len=*),intent(in) :: s
      integer :: i
      ndollars = 0
      do i=1,len(s)
        if (s(i:i)=='$') ndollars = ndollars+1 
      enddo
      end function ndollars
!-----------------------------------------------------------------------
      integer function decode_int(str,sout)
      implicit none
!
! Return integer decoded from digits in string str.
! Only use digits from end of str. Also return string
! sout, with integers
!
      character(len=*),intent(in) :: str
      character(len=*),intent(out) :: sout
      character(len=len(str)) :: snum,s
      character(len=8) :: format
      integer :: i,ipos,slen
!
      decode_int = -1
      s = adjustl(str)
      slen = len_trim(s)
      if (slen>9999) then
        write(6,"('>>> decode_int: string too long:',
     +    ' slen=',i10)") slen 
        return
      endif
      ipos = 0
      snum = ' '
      sout = trim(s)
      do i=slen,1,-1
        if (.not.isdigit(s(i:i))) then
          if (ipos > 0) then
            exit
          else
            cycle
          endif
        endif
        ipos = ipos+1
        snum(slen-ipos+1:slen-ipos+1) = s(i:i)
        sout(i:i) = '$'
      enddo
      if (ipos==0) return
      snum = adjustl(snum)
      write(format,"('(i',i4,')')") len_trim(snum)
!     read(trim(snum),format,err=100) decode_int ! ibm does not like this
      read(snum,format,err=100) decode_int
      return
 100  write(6,"('>>> decode_int: error making integer from ',
     +  'string: ',a)") trim(snum)
      decode_int = -1
      end function decode_int
!-----------------------------------------------------------------------
      subroutine encode_str(str,num,ndigits)
      implicit none
!
! Given str containing n characters '$', return
! same string, but with the '$' replaced by num.
!
      character(len=*),intent(inout) :: str
      character(len=len(str)) :: newstr
      integer,intent(in) :: num,ndigits
      integer :: i,ipos,ndollar
      character(len=16) :: format,numstr
!
      if (ndigits<=0) return
      write(format,"('(i',i4,'.',i4,')')") ndigits,ndigits
      format = trim(adjustl(format))
      ipos = index(str,'$')
      ndollar = ndollars(str)
      write(numstr,format,err=100) num
      call replace_substr(str,str(ipos:ipos+ndollar-1),numstr,newstr)
      str = newstr
      return
 100  write(6,"('>>> encode_str: error writing integer ',
     +  'num=',i12,' to string.')") num
      return
      end subroutine encode_str
!-----------------------------------------------------------------------
      subroutine replace_substr(s,subold,subnew,sout)
      character(len=*),intent(in) :: s,subold,subnew
      character(len=*),intent(out) :: sout
      integer :: i,ii,ipos,lonsubnew,lensubold,lens
!
! Init sout to input s:
      sout = s
!
! Get position of first char of subold in s:
      ipos = index(s,subold)
      if (ipos <= 0) then
        write(6,"('>>> WARNING replace_substr: could not find subold ',
     |    a,' in string ',a)") trim(subold),trim(s)
        return
      endif
!
! Check subnew:
      lensubnew = len_trim(subnew)
      if (lensubnew <= 0) then
        write(6,"('>>> WARNING replace_substr: zero length subnew.')")
        return
      endif
!
! Check if enough space in sout:
      lensubold = len_trim(subold)
      lens = len_trim(s)
      if (lens-lensubold+lensubnew > len(sout)) then
        write(6,"('>>> WARNING replace_substr: sout not long enough:',
     |    ' lens-lensubold+lensubnew=',i4,' len(sout)=',i4)")
     |    lens-lensubold+lensubnew,len(sout)
        return
      endif
!
! Replace subold with subnew in sout:
      sout(ipos:ipos+lensubnew-1) = trim(subnew)
!
! Complete sout with remainder of s:
      ii = ipos+lensubnew
      do i=ipos+lensubold,lens
        sout(ii:ii) = s(i:i)  
        ii = ii+1
      enddo
      end subroutine replace_substr
!-----------------------------------------------------------------------
      integer function mkhvols(vols_in,vols_out,mxout)
      implicit none
!
! Given array of strings vols_in as mss paths, return 
!   list of vols_out, which are same as vols_in unless
!   vols_in(2) = 'to', in which case vols_in is, e.g.:
!   "vol5","to","vol10","by","n". In this case expand
!   to "vol5","vol6",...,"vol10" (use decode_int)
! Return number of defined elements in vols_out
!
! Args:
      character(len=*),intent(in) :: vols_in(:)
      integer,intent(in) :: mxout
      character(len=*),intent(out) :: vols_out(mxout)
!
! Locals:
      character(len=240) :: vol_first,vol_last,template_first,
     +  template_last,template_dum
      integer :: nvin,i,n_first,n_last,n_delta,ipos0,ipos1,
     |  ndol_first,ndigits,ndig
!
! Check input sizes:
      mkhvols = 0
      nvin = size(vols_in)
      if (nvin > mxout) then
        write(6,"('>>> mkhvols: too many volume inputs =',
     +    i3,' (must be <= mxout=',i3)") nvin,mxout
        nvin = mxout
      elseif (nvin<=0) then
        write(6,"('>>> mkhvols: need vols_in')")
        return
      endif
      vols_out = ' '
      if (nvin==1) then
        vols_out(1) = vols_in(1)
        return
      endif
!
! No expansion -> just echo non-blank elements of vols_in to vols_out:
!
      if (trim(vols_in(2))/='to'.and.trim(vols_in(2))/='TO') then
        do i=1,nvin
          if (len_trim(vols_in(i)) > 0) then
            mkhvols = mkhvols+1
            vols_out(mkhvols) = vols_in(i)
          endif  
        enddo
        return
      endif
!
! Do expansion of "vols1","to","vols2","by","n"
!
      write(6,"('Doing expansion of mss histvol paths:')")
      write(6,"(a,' ',a,' ',a,' ',a,' ',a)")
     +  trim(vols_in(1)),trim(vols_in(2)),trim(vols_in(3)),
     +  trim(vols_in(4)),trim(vols_in(5))
!
      if (trim(vols_in(4))/='by'.and.trim(vols_in(4))/='BY') then
        write(6,"('>>> mkhvols: if 2nd vols is ""',a,'"" then ',
     +    '4th vol must be ""by"" or ""BY""')") trim(vols_in(2))
        return
      endif
!
! vol_first is first volume, n_first is number from first volume:
      vol_first = vols_in(1)
      vol_first = trim(vol_first)
      n_first = decode_int(vol_first,template_first)
      if (n_first==-1) then
        write(6,"('>>> mkhvols: could not get number from ',
     +    'first volume: vols_in(1)=',a)") vols_in(1)
        return
      endif
      ndol_first = ndollars(template_first)
!
! vol_last is last volume, n_last is number from last volume:
      vol_last  = vols_in(3)
      vol_last = trim(vol_last)
      n_last = decode_int(vol_last,template_last)
      if (n_last==-1) then
        write(6,"('>>> mkhvols: could not get number from ',
     +    'last volume: vols_in(3)=',a)") vols_in(3)
        return
      endif
!
! n_delta is delta integer between volumes:
      n_delta = decode_int(vols_in(5),template_dum)
      if (n_delta==-1) then
        write(6,"('>>> mkhvols: could not get delta from ',
     +    'vols_in(5)=',a)") vols_in(5)
        return 
      endif
!
! Check delta:
      if (n_first > n_last) then
        write(6,"('>>> mkhvols: n_first must be <= n_last:',
     +    ' n_first=',i5,' n_last=',i5)") n_first,n_last
        return
      endif 
      if (n_delta > n_last-n_first) then
        write(6,"('>>> mkhvols: n_delta must be <= n_last-n_first:',
     +    ' n_delta=',i5,' n_first=',i5,' n_last=',i5)")
     +    n_delta,n_first,n_last
      endif
!
! Warn if first template /= last template (i.e., root names are
! different, not including number of dollars). (Not fatal -- will 
! use 1st template in this case)
!
      ipos0 = index(template_first,'$')
      ipos1 = index(template_last,'$')
      if (template_first(1:ipos0-1)/=template_last(1:ipos1-1)) then
        write(6,"('>>> WARNING mkhvols: root names of first and ',
     +    'last mss files are different:',/'  template_first=',a,
     +    ' template_last=',a,'  (will use first)')")
     +    trim(template_first),trim(template_last) 
      endif
      ndigits = ndol_first
!
! Loop from number in first vol to number in last vol, by delta,
! building vols_out w/ encode_str.
!
      do i=n_first,n_last,n_delta
        ndig = int(log10(real(i)))+1	! number of digits in i
        if (ndig > ndigits) ndigits = ndigits+(ndig-ndigits)
        if (mkhvols+1 > mxout) then
          write(6,"('>>> WARNING mkhvols: too many vols -- ',
     +      'stopping at mxhvols=',i3)") mkhvols
          exit
        endif
        mkhvols = mkhvols+1
        vols_out(mkhvols) = template_first
        call encode_str(vols_out(mkhvols),i,ndigits)

!       write(6,"('mkhvols: i=',i3,' ndigits=',i2,' mkhvols=',i3,
!    |    ' template=',a,' vols_out=',a)") i,ndigits,mkhvols,
!    |    trim(template_first),trim(vols_out(mkhvols))

      enddo
!     call shutdown('mkhvols')
      end function mkhvols
      end module mk_hvols
