! integer function fixnamelist(lu) ! ! This routine reads the user namelist read (after rmcomments has ! stripped comments and added quotes to cfields if necessary), ! and checks for attempts to read string values into integer or array ! keywords (e.g., flons='zm', etc). When these are found, they are ! replaced by appropriate flags of the keyword type for later processing. ! ! This is called only if running on an IBM/AIX platform. This is because ! IBM does not allow reading a string value into an integer or real. ! (SGI does allow this, so fixnamelist is not necessary). ! ! This routine reads from lu, and returns a logical unit attached to the ! fixed namelist file. ! use proc,only: zmflag,mtimeflag,hmf2flag implicit none ! ! Args: integer,intent(in) :: lu ! ! Local: logical :: isopen,found integer :: i,ii,ios,nline,len character(len=10000) :: rdline,line,line0,keyword character(len=8) :: zmflag_str,mtimeflag_str,hmf2_str ! ! External: character(len=120),external :: strcompress integer,external :: nextlu ! if (lu <= 0) then write(6,"('>>> fixnamelist: bad input lu=',i5)") lu fixnamelist = -1 return endif inquire(unit=lu,opened=isopen) if (.not.isopen) then open(unit=lu,iostat=ios) if (ios /= 0) then write(6,"('>>> WARNING fixnamelist: error opening input', | ' file with unit lu=',i2,' ios=',i5)") lu,ios fixnamelist = -1 return endif endif fixnamelist = nextlu() rewind lu write(zmflag_str,"(f8.0)") zmflag zmflag_str = trim(adjustl(zmflag_str)) keyword = ' ' nline = 0 ! ! Read each line from users namelist input file: read_loop: do rdline = ' ' ! ! Read a line and increment nline: read(lu,"(a)",iostat=ios) rdline if (ios > 0) then write(6,"('>>> fixnamelist: error reading from input', | ' unit lu=',i3,' at rdline ',i5)") lu,nline return endif if (ios < 0) exit read_loop ! eof nline = nline+1 line0 = rdline ! ! Parse keyword as string before '=' in current line. If '=' is ! missing, assume keyword is blank (a keyword=value pair has not ! yet been encountered) or this is a continuation line and previous ! keyword is used. ! i = index(line0,'=') if (i > 1) keyword = line0(1:i-1) keyword = strcompress(keyword) ! write(6,"('fixnamelist: nline=',i3,' keyword=$',a,'$')") ! | nline,trim(keyword) ! ! Check for short form of mtimes, e.g. mtimes = 10,0,0,'to',11,0,0,'by',60 ! Replace 'to' and 'by' with mtimeflag for sub chmtimes (util.F). if (trim(keyword)=='mtimes'.or.trim(keyword)=='mtimes_cntr')then found = .false. if ((index(line0,'''to''')>0.or.index(line0,'''TO''')>0).and. | (index(line0,'''by''')>0.or.index(line0,'''BY''')>0)) | found = .true. write(mtimeflag_str,"(i8)") mtimeflag call replace_substring(trim(line0),'''to''',mtimeflag_str, | line) ; line0 = line call replace_substring(trim(line0),'''TO''',mtimeflag_str, | line) ; line0 = line call replace_substring(trim(line0),'''by''',mtimeflag_str, | line) ; line0 = line call replace_substring(trim(line0),'''BY''',mtimeflag_str, | line) if (found) | write(6,"('fixnamelist: Replaced namelist input line:', | /,' ',a,/,'with: ',/,' ',a)") trim(adjustl(rdline)), | trim(adjustl(line)) ! ! Check for fmnmxint. Add quotes around min,max,int values, and ! change name to cmnmxint: elseif (trim(keyword)=='fmnmxint') then call addquotes(line0,line) ; line0 = line call replace_substring(line0,'fmnmxint','cmnmxint',line) write(6,"('fixnamelist: Replaced namelist input line:', | /,' ',a,/,'with: ',/,' ',a)") trim(adjustl(rdline)), | trim(adjustl(line)) ! ! Check for fscale, and treat like fmnmxint above, except change name ! to cscale: elseif (trim(keyword)=='fscale') then call addquotes(line0,line) ; line0 = line call replace_substring(line0,'fscale','cscale',line) write(6,"('fixnamelist: Replaced namelist input line:', | /,' ',a,/,'with: ',/,' ',a)") trim(adjustl(rdline)), | trim(adjustl(line)) ! ! Check for hmf2 heights in xyut_zpht: elseif (trim(keyword)=='xyut_zpht') then found = .false. if (index(line0,'''hmf2''') > 0) found = .true. if (found) then write(hmf2_str,"(f8.0)") hmf2flag hmf2_str = trim(adjustl(hmf2_str)) call replace_substring(trim(line0),'''hmf2''',hmf2_str,line) write(6,"('fixnamelist: Replaced namelist input line:', | /,' ',a,/,'with: ',/,' ',a)") trim(adjustl(rdline)), | trim(adjustl(line)) else line = line0 endif elseif (trim(keyword)=='fmap_zpht') then found = .false. if (index(line0,'''hmf2''') > 0) found = .true. if (found) then write(hmf2_str,"(f8.0)") hmf2flag hmf2_str = trim(adjustl(hmf2_str)) call replace_substring(trim(line0),'''hmf2''',hmf2_str,line) write(6,"('fixnamelist: Replaced namelist input line:', | /,' ',a,/,'with: ',/,' ',a)") trim(adjustl(rdline)), | trim(adjustl(line)) else line = line0 endif ! ! Check for 'zm' in inputs requiring selected longitudes and replace ! with zmflag. Also check for 'sltxxx'. Sub checkslt will replace the ! slt string with sltflag+slt for sub chlons (input.F). ! elseif (trim(keyword)=='xylocs' .or. | trim(keyword)=='utvert_locs' .or. | trim(keyword)=='utlat_zphtlon'.or. | trim(keyword)=='xyut_locs' .or. | trim(keyword)=='flons' ) then found = .false. if (index(line0,'''zm''') > 0) found = .true. call replace_substring(trim(line0),'''zm''',zmflag_str,line) line0 = line if (index(line0,'''ZM''') > 0) found = .true. call replace_substring(trim(line0),'''ZM''',zmflag_str,line) line0 = line if (index(line0,'''slt') > 0.or.index(line0,'''SLT') > 0.or. | index(line0,'''lt') > 0.or.index(line0,'''LT') > 0) | found = .true. call checkslt(trim(line0),line) if (found) | write(6,"('fixnamelist: Replaced namelist input line:', | /,' ',a,/,'with: ',/,' ',a)") trim(adjustl(rdline)), | trim(adjustl(line)) ! ! Check for old style end cards and replace with slash: elseif (index(line0,'&end' ) > 0 .or. | index(line0,'&end_sut') > 0 .or. | index(line0,'&end_mut') > 0) then if (index(line0,'&end') > 0) | call replace_substring(trim(line0),'&end','/',line) if (index(line0,'&end_sut') > 0) | call replace_substring(trim(line0),'&end_sut','/',line) if (index(line0,'&end_mut') > 0) | call replace_substring(trim(line0),'&end_mut','/',line) write(6,"('fixnamelist: Replaced namelist input line:', | /,' ',a,/,'with: ',/,' ',a)") trim(adjustl(rdline)), | trim(adjustl(line)) ! ! No change needed: else line = line0 endif ! write(6,"(a)") trim(line) write(fixnamelist,"(a)") trim(line) enddo read_loop rewind fixnamelist ! stop 'fixnamelist' end function fixnamelist !----------------------------------------------------------------------- character(len=*) function strcompress(str) ! ! Move all leading and imbedded blanks in str to the end. New string ! is the return value of the function, input str is unchanged. ! implicit none character(len=*),intent(in) :: str character(len=len(str)) :: strtemp integer :: i,ii,leng ! strtemp = ' ' ii = 0 do i=1,len(str) if (str(i:i)/=' ') then ii = ii+1 strtemp(ii:ii) = str(i:i) endif enddo strcompress = strtemp end function strcompress !----------------------------------------------------------------------- recursive subroutine replace_substring(str_in,substr_old, | substr_new,str_out) ! ! Replace any and all occurences of substr_old in str_in with substr_new, ! returning result in str_out. This is recursive. Any blanks in str_in ! are moved to the end, but str_in is otherwise unchanged. ! implicit none ! ! Args: character(len=*),intent(inout) :: str_in character(len=*),intent(in) :: substr_old,substr_new character(len=*),intent(out) :: str_out ! ! Local: integer :: i,ii,loc,leng,len_subold,len_subnew,len_strin, | len_strout,len_strtail character(len=len(str_out)) :: strtemp,strtail character(len=len(str_in)) :: strtempin logical :: found ! write(6,"('enter replace_substring: substr_old=',a)") substr_old ! ! Return if substr_old not found in str_in: str_out = str_in ! init found = .false. loc = index(str_in,substr_old) if (loc <= 0) return found = .true. ! ! Compress input string (i.e., move leading and imbedded blanks to the end): strtempin = ' ' ii = 0 do i=1,len(str_in) if (str_in(i:i)/=' ') then ii = ii+1 strtempin(ii:ii) = str_in(i:i) endif enddo str_in = strtempin str_out = str_in ! init loc = index(str_in,substr_old) ! ! Set lengths: len_subold = len(substr_old) len_subnew = len(substr_new) len_strin = len(str_in) len_strout = len(str_out) ! ! write(6,"(/,'replace_substring: found substr_old ',a,' in ', ! | ' str_in = ',/,' ',a)") substr_old,trim(str_in) ! write(6,"(' loc = ',i3,' substr_old = ',a,' len_subold=', ! | i3,' substr_new = ',a)") loc,substr_old,len_subold,substr_new ! ! First replace substr_old with blanks and compress: ! (cannot use function strcompress because length of str_out is not ! known, so explicit interface for strcompress is not accepted) ! str_out(loc:loc+len_subold-1) = ' ' strtemp = ' ' ii = 0 do i=1,len(str_out) if (str_out(i:i)/=' ') then ii = ii+1 strtemp(ii:ii) = str_out(i:i) endif enddo str_out = strtemp ! write(6,"('replace_substring: str_out minus substr_old = ',a)") ! | trim(str_out) ! write(6,"('str_in=',/,' ',a)") trim(str_in) ! ! Save tail of input string: strtail = ' ' leng = len_strin-(loc+len_subold)+1 strtail(1:leng) = str_in(loc+len_subold:len_strin) ! write(6,"('leng=',i3,' loc=',i3,' len_subold=',i3,' len_strin=', ! | i3,' str_in=',/,' ',a)") ! | leng,loc,len_subold,len_strin,trim(str_in) ! write(6,"('replace_substring: strtail=',a)") trim(strtail) len_strtail = len_trim(strtail) ! ! Insert new substring: str_out(loc:loc+len_subnew-1) = substr_new ! ! Replace tail: str_out(loc+len_subnew:loc+len_subnew+len_strtail-1) = | trim(strtail) ! ! Finally, compress output string: strtemp = ' ' ii = 0 do i=1,len(str_out) if (str_out(i:i)/=' ') then ii = ii+1 strtemp(ii:ii) = str_out(i:i) endif enddo str_out = strtemp str_in = str_out ! write(6,"('replace_substring returning: str_out = ',a, ! | ' substr_old=',a,/)") trim(str_out),trim(substr_old) call replace_substring(str_in,substr_old,substr_new,str_out) end subroutine replace_substring !----------------------------------------------------------------------- subroutine addquotes(str_in,str_out) ! ! Args: character(len=*),intent(in) :: str_in character(len=*),intent(out) :: str_out ! ! Local: integer :: i,ii,len_strin,len_strtemp0,last character(len=len(str_in)+80) :: strtemp0,strtemp1 ! str_out = ' ' ! init ! ! Compress str_in, save in strtemp0: len_strin = len(str_in) strtemp0 = ' ' ii = 0 do i=1,len_strin if (str_in(i:i)/=' ') then ii = ii+1 strtemp0(ii:ii) = str_in(i:i) endif enddo last = len_trim(strtemp0) ! write(6,"('addquotes: str_in=',/,' ',a)") trim(str_in) ! write(6,"('addquotes: last=',i3,' strtemp0(last)=',a,' strtemp0=', ! | /,' ',a)") last,strtemp0(last:last),trim(strtemp0) ! ! Add quotes after each comma (unless comma is last char in the line): strtemp1 = ' ' ii = 0 do i=1,len_trim(strtemp0) if (strtemp0(i:i)==','.and.i < last) then ii = ii+1 ; strtemp1(ii:ii) = ',' if (strtemp0(i+1:i+1) /= '''') then ii = ii+1 ; strtemp1(ii:ii) = '''' endif else ii = ii+1 strtemp1(ii:ii) = strtemp0(i:i) endif if (i==last.and.strtemp0(i:i)/=',') then ii = ii+1 ; strtemp1(ii:ii) = '''' endif enddo ! write(6,"('addquotes: strtemp1=',/,' ',a)") trim(strtemp1) ! ! Add quotes before each comma: strtemp0 = strtemp1 strtemp1 = ' ' ii = 0 do i=1,len_trim(strtemp0) if (strtemp0(i+1:i+1)==',') then ii = ii+1 ; strtemp1(ii:ii) = strtemp0(i:i) if (strtemp0(i:i) /= '''') then ii = ii+1 ; strtemp1(ii:ii) = '''' endif else ii = ii+1 ; strtemp1(ii:ii) = strtemp0(i:i) endif enddo ! write(6,"('addquotes: strtemp1=',/,' ',a)") trim(strtemp1) if (len_trim(strtemp1) > len_strin) then write(6,"('>>> WARNING addquotes: len_trim(strtemp1) > ', | 'len_strin: len_trim(strtemp1)=',i4,' len_strin=',i4)") | len_trim(strtemp1),len_strin write(6,"('Try shortening the following input string:')") write(6,"(a)") trim(str_in) stop 'addquotes' endif str_out = trim(strtemp1) end subroutine addquotes !----------------------------------------------------------------------- recursive subroutine checkslt(str_in,str_out) use proc,only: sltflag implicit none ! ! Args: character(len=*),intent(inout) :: str_in character(len=*),intent(out) :: str_out ! ! Local: integer :: loc,loc0,loc1,loc2,loc3,len_strin character(len=8) :: sltstr character(len=32) :: subsltstr character(len=len(str_in)) :: cpy_strin real :: slt ! ! Check for the string 'slt (leading quote only) loc0 = index(str_in,'''slt') loc1 = index(str_in,'''SLT') loc2 = index(str_in,'''lt') loc3 = index(str_in,'''LT') if (loc0==0.and.loc1==0.and.loc2==0.and.loc3==0) return cpy_strin = str_in if (loc1 > 0) call replace_substring(cpy_strin,'''SLT','''slt', | str_in) if (loc3 > 0) call replace_substring(cpy_strin,'''LT','''slt', | str_in) loc0 = index(str_in,'''slt') ! write(6,"(/,'checkslt: found slt at index ',i3)") loc0 ! ! Find 2nd quote after slt: len_strin = len(str_in) loc1 = index(str_in(loc0+1:len_strin),'''') if (loc1 == 0) then write(6,"('>>> checkslt: could not find closing quote to ', | 'slt in the following namelist input line:')") write(6,"(a)") trim(str_in) stop 'checkslt' endif loc1 = loc1+loc0 ! write(6,"('checkslt: found closing quote at index ',i3)") ! | loc1 ! ! Read the requested local time: read(str_in(loc0+4:loc1-1),"(f5.2)") slt ! write(6,"('checkslt: slt=',f5.2)") slt slt = slt+sltflag ! see function isslt in util.F write(sltstr,"(f8.2)") slt sltstr = trim(adjustl(sltstr)) ! write(6,"('checkslt: slt+sltflag=',f8.2,' sltstr=',a)") ! | slt,sltstr ! ! Replace with slt: subsltstr = str_in(loc0:loc1) ! write(6,"('checkslt: subsltstr=',a)") trim(subsltstr) ! write(6,"('checkslt before replace_substring: str_in=',/,a, ! | ' ')") trim(str_in) call replace_substring(str_in,trim(subsltstr),sltstr,str_out) ! write(6,"('checkslt done: str_out=',/,' ',a)") ! | trim(str_out) ! ! Continue the check until 'slt string is not found: str_in = str_out call checkslt(str_in,str_out) end subroutine checkslt