diff --git a/src/parser/lib/fileread.f b/src/parser/lib/fileread.f deleted file mode 100644 index 2930e52..0000000 --- a/src/parser/lib/fileread.f +++ /dev/null @@ -1,148 +0,0 @@ - module fileread_mod - contains -!------------------------------------------------------------------- - - subroutine get_datfile(datnam,dnlen) - implicit none -! Get name of input data file DATNAM either from the program's first -! command line argument or ask the user. - - integer dnlen - character(len=dnlen) datnam - - integer argcount - - argcount=iargc() - if (argcount.gt.0) then - call getarg(1,datnam) - else - write(6,'(A)') 'Specify input file:' - read(*,*) datnam - endif - - if (len_trim(datnam).eq.dnlen) then - write(6,'(A)') 'ERROR: TRUNCATED FILENAME' - write(6,'(A)') '"' // datnam // '"' - endif - - end subroutine get_datfile - -!------------------------------------------------------------------- - - subroutine internalize_datfile(datnam,infile,linenum,llen, - > maxlines,dnlen) - use strings_mod,only:write_oneline,int2string - implicit none - -! Read input file located at DATNAM, skipping comments and blank lines. - integer dnlen,llen,maxlines - integer linenum - character(len=dnlen) datnam - character(len=llen) infile(maxlines) - - character(len=llen) line - - !character*16 int2string - - integer j - - !Fabian - character(len=llen) fmt,fmt2 - integer,parameter :: std_out = 6 - integer,parameter :: funit = 10 - write(fmt,'(A)') 'Reading file ''' // trim(datnam) // ''' ...' - call write_oneline(fmt,std_out) - - open(unit=funit,file=datnam) - linenum=0 - do j=1,maxlines - !read(funit,fmt='(A)',end=20) line ! works only for ifort, not for gfortran or mpif90 - write(fmt2,'("(A",I3,")")') llen !Fabian - read(funit,fmt=fmt2,end=20) line !Fabian - if (line(1:3).eq.'---') then - write(fmt,'(A)') 'EOF-mark "---" found at line' - > // trim(int2string(j)) - call write_oneline(fmt,std_out) - exit - endif - call internalize_line(linenum,infile,line,llen,maxlines) - enddo - 20 close(funit) - - if (j.ge.maxlines) then - write(6,'(A)') 'ERROR: FILE LENGTH EXCEEDING MAXLINES.' - stop 1 - endif - - write(fmt,'(A)') 'File read successfully (' - > // trim(int2string(linenum)) // ' lines).' - call write_oneline(fmt,std_out) - - end subroutine internalize_datfile - -!------------------------------------------------------------------- - - subroutine internalize_line(linenum,infile,line,llen,maxlines) - use strings_mod,only: strip_string,upcase - implicit none -! Parse a single line of input. Ignore comments ("!..") and blank -! lines, and turn all input to uppercase. -! -! infile: data file's internalized form -! line: single verbatim line read from physical file -! linenum: current number of non-commentlines read -! increased by 1 if read line is not a comment -! llen: maximum character length of a single line -! maxlines: maximum number of lines in infile - - integer llen,maxlines - integer linenum - character(len=llen) infile(maxlines) - character(len=llen) line - - character(len=llen) strip - integer line_pos,text_end - - integer j - - line_pos=linenum+1 - -! ignore empty lines - if (len_trim(line).eq.0) then - return - endif - -! strip needless whitespace - call strip_string(line,strip,llen) - -! determine EOL -! ignore comments - text_end=0 - do j=1,len_trim(strip) - if (strip(j:j).eq.'!') then - exit - endif - text_end=text_end+1 - enddo - - if (text_end.eq.llen) then - write(6,'(A,I6)') 'WARNING: POTENTIALLY TRUNCATED LINE:' - write(6,'(A)') '"' // strip(1:60) // '"...' - endif - -! skip if line is a comment - if (text_end.eq.0) then - return - endif - - infile(line_pos)=' ' - -! turn string to uppercase and write to infile, ignoring comments - call upcase(strip,infile(line_pos),text_end) - -! increment line number - linenum=linenum+1 - - end subroutine internalize_line - - end module diff --git a/src/parser/lib/fileread.f90 b/src/parser/lib/fileread.f90 index fec4fdb..62ebd56 100644 --- a/src/parser/lib/fileread.f90 +++ b/src/parser/lib/fileread.f90 @@ -1,180 +1,202 @@ module fileread_mod - contains - !------------------------------------------------------------------- + use strings_mod, only: int2string, strip_string, upcase, write_oneline + implicit none +contains +!------------------------------------------------------------------- + subroutine get_datfile(datnam) + implicit none +! Get name of input data file DATNAM either from the program's first +! command line argument or ask the user. + integer, parameter :: dnlen = 1000 + character(len=dnlen) :: tmp + character(len=:), allocatable, intent(out) :: datnam + integer argcount + argcount = iargc() + if (argcount .gt. 0) then + call getarg(1, tmp) + datnam = trim(tmp) + else + write (6, '(A)') 'Specify input file:' + read (*, *) tmp + datnam = trim(tmp) + end if - subroutine get_datfile(datnam,dnlen) - implicit none - ! Get name of input data file DATNAM either from the program's first - ! command line argument or ask the user. + if (len_trim(tmp) .eq. dnlen) then + write (6, '(A)') 'ERROR: TRUNCATED FILENAME' + write (6, '(A)') '"'//tmp//'"' + end if + end subroutine get_datfile +!------------------------------------------------------------------- + recursive subroutine internalize_datfile(datnam, infile, linenum, llen) + implicit none +! Read input file located at DATNAM, skipping comments and blank lines. + integer, intent(in) :: llen!, maxlines + integer, intent(inout) :: linenum + character(len=:), allocatable, intent(in):: datnam + character(len=llen), allocatable, intent(inout) :: infile(:) - integer dnlen - character(len=dnlen) datnam + ! local variables + character(len=llen) line + character(len=32) datfmt + integer j, unit + integer, parameter :: line_increase = 10000 + character(len=llen) fmt + integer, parameter :: std_out = 6 - integer argcount + datfmt = '(750A)' + write (datfmt, '(1A,i0,2A)') "(", llen, "A)" - argcount=iargc() - if (argcount.gt.0) then - call getarg(1,datnam) - else - write(6,'(A)') 'Specify input file:' - read(*,*) datnam - endif + write (fmt, '(A)') 'Reading file '''//trim(datnam)//''' ...' + call write_oneline(fmt, std_out) - if (len_trim(datnam).eq.dnlen) then - write(6,'(A)') 'ERROR: TRUNCATED FILENAME' - write(6,'(A)') '"' // datnam // '"' - endif + if (file_exists(datnam)) then + open (newunit=unit, file=datnam) + else + write(*,*) 'file: ', datnam + error stop 'specified inputfile does not exist' + end if - end subroutine get_datfile + if (allocated(infile)) deallocate (infile) + allocate (character(len=llen) :: infile(line_increase)) + linenum = 0 + j = 0 + do + j = j + 1 + read (unit, fmt=datfmt, end=20) line - !------------------------------------------------------------------- + if (line(1:3) .eq. '---') then + write (fmt, '(A)') 'EOF-mark "---" found at line'& + &//trim(int2string(j)) + call write_oneline(fmt, std_out) + exit + end if - recursive subroutine internalize_datfile(datnam,infile,linenum,llen, & - maxlines,dnlen) - use strings_mod,only:write_oneline,int2string - implicit none + ! increase infile if needed + if (linenum + 1 >= size(infile, 1)) call increase_infile(infile,line_increase, llen) + call internalize_line(linenum, infile, line, llen) + end do +20 close (unit) - ! Read input file located at DATNAM, skipping comments and blank lines. - integer dnlen,llen,maxlines - integer linenum - character(len=dnlen) datnam - character(len=llen) infile(maxlines) +! decrease size of infile to actual linenum + call shrink_infile(infile,linenum,llen) - character(len=llen) line + write (6, '(A)') 'File:'//datnam//' read successfully ('& + &//trim(int2string(linenum))//' lines).' + end subroutine internalize_datfile +!------------------------------------------------------------------- + recursive subroutine internalize_line(linenum, infile, line, llen) + implicit none +! Parse a single line of input. Ignore comments ("!..") and blank +! lines, and turn all input to uppercase. +! +! infile: data file's internalized form +! line: single verbatim line read from physical file +! linenum: current number of non-commentlines read +! increased by 1 if read line is not a comment +! llen: maximum character length of a single line + integer llen + integer linenum + character(len=llen), allocatable :: infile(:) + character(len=llen) line - !character*16 int2string + character(len=llen) strip + integer line_pos, text_end - integer j + integer j - !Fabian - character(len=llen) fmt,fmt2 - integer,parameter :: std_out = 6 - integer,parameter :: funit = 10 - write(fmt,'(A)') 'Reading file ''' // trim(datnam) // ''' ...' - call write_oneline(fmt,std_out) + ! ignore empty lines + if (len_trim(line) .eq. 0) then + return + end if - open(unit=funit,file=datnam) - linenum=0 - do j=1,maxlines - !read(funit,fmt='(A)',end=20) line ! works only for ifort, not for gfortran or mpif90 - write(fmt2,'("(A",I3,")")') llen !Fabian - read(funit,fmt=fmt2,end=20) line !Fabian - if (line(1:3).eq.'---') then - write(fmt,'(A)') 'EOF-mark "---" found at line' & - // trim(int2string(j)) - call write_oneline(fmt,std_out) - exit - endif - call internalize_line(linenum,infile,line,llen,maxlines,dnlen) - enddo - 20 close(funit) + ! strip needless whitespace + call strip_string(line, strip, llen) - if (j.ge.maxlines) then - write(6,'(A)') 'ERROR: FILE LENGTH EXCEEDING MAXLINES.' - stop 1 - endif + ! determine EOL + ! ignore comments + text_end = 0 + do j = 1, len_trim(strip) + if (strip(j:j) .eq. '!') then + exit + end if + text_end = text_end + 1 + end do - write(fmt,'(A)') 'File read successfully (' & - // trim(int2string(linenum)) // ' lines).' - call write_oneline(fmt,std_out) + if (text_end .eq. llen) then + write (6, '(A,I6)') 'WARNING: POTENTIALLY TRUNCATED LINE:' + write (6, '(A)') '"'//strip(1:60)//'"...' + end if - end subroutine internalize_datfile + ! skip if line is a comment + if (text_end .eq. 0) then + return + end if - !------------------------------------------------------------------- + ! insert include files "@filename" + if (strip(1:1) == '@') then + block + character(len=llen), allocatable :: tmp_infile(:) + character(len=:), allocatable :: tmp_name + integer :: tmp_linenum - recursive subroutine internalize_line(linenum,infile,line,llen,maxlines,dnlen) - use strings_mod,only: strip_string,upcase - implicit none - ! Parse a single line of input. Ignore comments ("!..") and blank - ! lines, and turn all input to uppercase. - ! - ! infile: data file's internalized form - ! line: single verbatim line read from physical file - ! linenum: current number of non-commentlines read - ! increased by 1 if read line is not a comment - ! llen: maximum character length of a single line - ! maxlines: maximum number of lines in infile + tmp_name = trim(strip(2:)) + call internalize_datfile(tmp_name, tmp_infile, tmp_linenum, llen) + call shrink_infile(infile, linenum, llen) ! decrease size of infile to actual linenum + call append_infile(infile, tmp_infile, llen) + linenum = size(infile, 1) + end block + return + end if - integer llen,maxlines - integer linenum - integer dnlen - character(len=llen) infile(maxlines) - character(len=llen) line + line_pos = linenum + 1 + infile(line_pos) = ' ' - character(len=llen) strip - integer line_pos,text_end +! turn string to uppercase and write to infile, ignoring comments + call upcase(strip, infile(line_pos), text_end) - integer j +! increment line number + linenum = linenum + 1 + end subroutine internalize_line - line_pos=linenum+1 +! append 1D array by a another 1D array + subroutine append_infile(array1, array2, llen) + integer, intent(in) :: llen + character(len=llen), dimension(:), intent(inout), allocatable :: array1 + character(len=llen), dimension(:), intent(in), allocatable :: array2 + character(len=llen), dimension(:), allocatable :: tmp + integer :: s_in, s_out + s_in = size(array1, 1) + s_out = s_in + size(array2, 1) + allocate (tmp(s_out)) + tmp(1:s_in) = array1(:) + tmp(s_in + 1:) = array2(:) + call move_alloc(tmp, array1) + end subroutine append_infile - ! ignore empty lines - if (len_trim(line).eq.0) then - return - endif + subroutine shrink_infile(infile,linenum,llen) + integer,intent(in) :: linenum, llen + character(len=llen),dimension(:),allocatable,intent(inout) :: infile + character(len=llen),dimension(:),allocatable :: tmp_file + allocate(character(len=llen) :: tmp_file(1:linenum)) + tmp_file(1:linenum) = infile(1:linenum) + call move_alloc(tmp_file, infile) + end subroutine shrink_infile - ! strip needless whitespace - call strip_string(line,strip,llen) + subroutine increase_infile(infile, line_increase, llen) + integer,intent(in) :: llen, line_increase + character(len=llen), dimension(:),intent(inout),allocatable :: infile + character(len=llen), dimension(:),allocatable :: tmp_file + integer :: linenum + linenum = size(infile,1) + allocate (character(len=llen) :: tmp_file(linenum + line_increase)) + tmp_file(1:linenum) = infile(1:linenum) + call move_alloc(tmp_file, infile) + end subroutine increase_infile - ! determine EOL - ! ignore comments - text_end=0 - do j=1,len_trim(strip) - if (strip(j:j).eq.'!') then - exit - endif - text_end=text_end+1 - enddo + function file_exists(filename) result(res) + character(len=*), intent(in) :: filename + logical :: res + inquire (file=trim(filename), exist=res) + end function file_exists - if (text_end.eq.llen) then - write(6,'(A,I6)') 'WARNING: POTENTIALLY TRUNCATED LINE:' - write(6,'(A)') '"' // strip(1:60) // '"...' - endif - - ! skip if line is a comment - if (text_end.eq.0) then - return - endif - - ! insert included file - if (strip(1:1) .eq. '@') then - block - character(len=llen),allocatable:: tmp_file(:) - character(len=:),allocatable:: tmp_name - integer:: tmp_linenum - - tmp_name = trim(strip(2:)) - call internalize_datfile(tmp_name,tmp_file,tmp_linenum,llen,maxlines,dnlen) - call append_infile(infile,tmp_file,llen) - end block - - - - endif - - infile(line_pos)=' ' - - ! turn string to uppercase and write to infile, ignoring comments - call upcase(strip,infile(line_pos),text_end) - - ! increment line number - linenum=linenum+1 - - end subroutine internalize_line - - - subroutine append_infile(array1, array2, llen) - integer, intent(in) :: llen - character(len=llen), dimension(:), intent(inout), allocatable :: array1 - character(len=llen), dimension(:), intent(in), allocatable :: array2 - character(len=llen), dimension(:), allocatable :: tmp - integer :: s_in, s_out - s_in = size(array1, 1) - s_out = s_in + size(array2, 1) - allocate (tmp(s_out)) - tmp(1:s_in) = array1(:) - tmp(s_in + 1:) = array2(:) - call move_alloc(tmp, array1) - end subroutine append_infile - -end module +end module fileread_mod diff --git a/src/parser/lib/keyread.f b/src/parser/lib/keyread.f index 47c8a17..2a651a2 100644 --- a/src/parser/lib/keyread.f +++ b/src/parser/lib/keyread.f @@ -127,6 +127,7 @@ call long_realkey(infile,inpos,key_end, > ddat,dstart,readlen,llen,maxdat,linenum) else if (intype.eq.4) then + datlen=maxdat-cstart+1 call long_strkey(infile,inpos,key_end, > cdat,cstart,readlen,llen,maxdat,linenum,clen) else if (intype.eq.5) then @@ -173,7 +174,7 @@ dstart=dstart+inlen else if (intype.eq.4) then datpos(2,j)=cstart - dstart=cstart+inlen + cstart=cstart+inlen else if (intype.eq.5) then ! remember where you last found the key in infile datpos(2,j)=inpos diff --git a/src/parser/lib/long_keyread.f b/src/parser/lib/long_keyread.f index afab713..1010d5d 100644 --- a/src/parser/lib/long_keyread.f +++ b/src/parser/lib/long_keyread.f @@ -452,8 +452,8 @@ !--------------------------------------------------------------------------- - subroutine long_strline(inline,linelen,line_start, - > cdat,cpos,datlen,readlen,clen, + subroutine long_strline(inline,linelen,line_start,cdat, + > cpos,datlen,readlen,clen, > continued,broken,strpos) use strings_mod,only:iswhitespace, downcase implicit none diff --git a/src/parser/lib/strings.f b/src/parser/lib/strings.f index da09710..9884e50 100644 --- a/src/parser/lib/strings.f +++ b/src/parser/lib/strings.f @@ -499,7 +499,51 @@ C..... Addition of the first if-loop #ifdef mpi_version endif #endif - end subroutine write_oneline + Pure Function to_upper (str) Result (string) + + ! ============================== + ! Changes a string to upper case + ! ============================== + Implicit None + Character(*), Intent(In) :: str + Character(LEN(str)) :: string + + Integer :: ic, i + + Character(26), Parameter :: cap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + Character(26), Parameter :: low = 'abcdefghijklmnopqrstuvwxyz' + + ! Capitalize each letter if it is lowecase + string = str + do i = 1, LEN_TRIM(str) + ic = INDEX(low, str(i:i)) + if (ic > 0) string(i:i) = cap(ic:ic) + end do + + End Function to_upper + + Pure Function to_lower (str) Result (string) + + ! ============================== + ! Changes a string to upper case + ! ============================== + Implicit None + Character(*), Intent(In) :: str + Character(LEN(str)) :: string + + Integer :: ic, i + + Character(26), Parameter :: cap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + Character(26), Parameter :: low = 'abcdefghijklmnopqrstuvwxyz' + + ! Capitalize each letter if it is lowecase + string = str + do i = 1, LEN_TRIM(str) + ic = INDEX(cap, str(i:i)) + if (ic > 0) string(i:i) = low(ic:ic) + end do + + End Function to_lower end module diff --git a/src/parser/parser.f b/src/parser/parser.f index 6ffeeb3..2137fac 100644 --- a/src/parser/parser.f +++ b/src/parser/parser.f @@ -43,7 +43,7 @@ ! weighting parameters ! Declare INTERNAL variables - character(len=dnlen) :: datname, dbgdatname !< name of the input File + character(len=:),allocatable :: datname, dbgdatname !< name of the input File character(len=llen), dimension(:), allocatable :: infile !< internalized array of capitalized input file without comments, blanklines integer linenum !< linenumber in infile double precision gspread @@ -91,9 +91,12 @@ ! Read input file !############################################################ - call get_datfile(datname,dnlen) + !call get_datfile(datname,dnlen) + call get_datfile(datname) + !call internalize_datfile + !> (datname,infile,linenum,llen,maxlines,dnlen) call internalize_datfile - > (datname,infile,linenum,llen,maxlines,dnlen) + > (datname,infile,linenum,llen) dbgdatname='.internal_input' #ifndef mpi_version write(6,'(A)') 'Writing internalized version of input to ''' @@ -503,6 +506,7 @@ ndata(j)=idat(datIdx(j,key_id)) enddo numdatpt=sum(ndata(1:sets)) + write(6,*) 'THE TOTAL NUMBER OF POINTS:', numdatpt else write(*,*)'WARNING: NO NPOINTS CARD GIVEN' endif