123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- !###############################################################################
- !
- #define IF_ERROR_RETURN(action) if (status/=0) then; write (gol,'("in ",a)') rname; call goErr; action; return; end if
- !
- !###############################################################################
- module GO_File
- implicit none
- ! --- in/out -------------------
- private
- public :: goGetFU
- public :: TTextFile
- public :: Init, Done
- public :: ReadLine, RewindFile
- ! --- const ---------------------------------
-
- character(len=*), parameter :: mname = 'GO_File'
- ! --- types -------------------------------------
- type TTextFile
- character(len=80) :: name
- ! file unit:
- integer :: fu
- ! comment ?
- logical :: commented
- character(len=1) :: comment
- end type TTextFile
- ! --- interfaces -------------------------------------
- interface Init
- module procedure file_Init
- end interface
-
- interface Done
- module procedure file_Done
- end interface
-
- contains
- ! ==============================================================
- ! ===
- ! === file units
- ! ===
- ! ==============================================================
- ! Returns the first free available file unit number.
- subroutine goGetFU( fu, status )
-
- use GO_FU , only : goStdIn, goStdOut, goStdErr
- use GO_FU , only : goFuRange
- use GO_Print, only : gol, goErr
- ! --- in/out --------------------------
- integer, intent(out) :: fu
- integer, intent(out) :: status
- ! --- const ---------------------------
-
- character(len=*), parameter :: rname = mname//'/goGetFU'
-
- ! --- local --------------------------
- integer :: i
- character(len=256) :: fname
- logical :: opened
- ! --- local ---------------------------
-
- ! start with lowest possible unit:
- fu = goFuRange(1) - 1
-
- ! loop until unopned unit is found:
- do
- ! try next file unit:
- fu = fu + 1
- ! too large ?
- if ( fu > goFuRange(2) ) then
- write (gol,'("unable to select free file unit within allowed range ...")'); call goErr
- write (gol,'("close some files or increase goFuRange in module GO_FU")'); call goErr
- write (gol,'("current goFuRange : ",i6," .. ",i6)') goFuRange; call goErr
- write (gol,'("open files:")')
- do i = goFuRange(1), goFuRange(2)
- inquire( unit=i, name=fname )
- write (gol,'(i6," : ",a)') i, trim(fname); call goErr
- end do
- write (gol,'("in ",a)') rname; call goErr; status=1; return
- end if
-
- ! skip ?
- if ( fu==goStdIn ) cycle
- if ( fu==goStdOut ) cycle
- if ( fu==goStdErr ) cycle
- ! free available unit ? then ok
- inquire( unit=fu, opened=opened )
- if ( .not. opened ) exit
-
- end do
- ! ok
- status = 0
- end subroutine goGetFU
- ! ==============================================================
- ! ===
- ! === text file
- ! ===
- ! ==============================================================
- !
- ! call Init( file, filename, iostat, [,status='unknown'|'old'|'new'] [,comment='\%'] )
- !
- ! Replaces the intrinsic 'open' command, but uses a
- ! a structure of type TTextFile instead of a file unit number. \\
- ! Arguments passed are the same as for 'open'.\\
- ! In addition, a text file can be opened as a commented
- ! text file; with the 'ReadLine' command one is able to read
- ! lines from the file while skipping the lines starting
- ! with the specified comment.
- !
- subroutine file_Init( file, filename, iostat, status, comment )
- use GO_Print, only : gol, goPr, goErr
- ! --- in/out ------------------------
- type(TTextFile), intent(out) :: file
- character(len=*), intent(in) :: filename
- integer, intent(out) :: iostat
-
- character(len=*), intent(in), optional :: status
- character(len=1), intent(in), optional :: comment
- ! --- const ---------------------------
-
- character(len=*), parameter :: rname = mname//'/file_Init'
-
- ! --- local ----------------------------
- logical :: exist
- character(len=10) :: statusX
- ! --- begin ----------------------------
- ! file exist ?
- inquire( file=trim(filename), exist=exist )
- if ( .not. exist ) then
- write (gol,'("commented text file not found:")'); call goErr
- write (gol,'(" file name : ",a)') trim(filename); call goErr
- write (gol,'("in ",a)') rname; call goErr; iostat=1; return
- end if
- ! check file status : 'old', 'new', 'unknown'
- if (present(status)) then
- statusX = status
- else
- statusX = 'unknown'
- end if
- ! store filename:
- file%name = filename
- ! select free file unit:
- Call goGetFU( file%fu, iostat )
- if (iostat/=0) then; write (gol,'("in ",a)') rname; call goErr; iostat=1; return; end if
- ! open file:
- open( unit=file%fu, file=trim(filename), iostat=iostat, &
- status=statusX, form='formatted' )
- if ( iostat /= 0 ) then
- write (gol,'("from file open :")'); call goErr
- write (gol,'(" file name : ",a)') trim(filename); call goErr
- write (gol,'("in ",a)') rname; call goErr; iostat=1; return
- end if
-
- ! check on comment lines ?
- if ( present(comment) ) then
- file%commented = .true.
- file%comment = comment
- else
- file%commented = .false.
- file%comment = 'x'
- end if
- ! ok
- iostat = 0
- end subroutine file_Init
- ! ***
- !
- ! call Done( file )
- !
- subroutine file_Done( file, status )
- use GO_Print, only : gol, goPr, goErr
- ! --- in/out -----------------
- type(TTextFile), intent(inout) :: file
- integer, intent(out) :: status
- ! --- const ----------------------
-
- character(len=*), parameter :: rname = mname//'/file_Done'
-
- ! --- begin ------------------------
- ! close file:
- close( unit=file%fu, iostat=status )
- if ( status /= 0 ) then
- write (gol,'("from closing file:")'); call goErr
- write (gol,'(" ",a)') trim(file%name); call goErr
- write (gol,'("in ",a)') rname; call goErr; status=1; return
- end if
-
- ! ok
- status = 0
- end subroutine file_Done
- ! ***
- !
- ! call ReadLine( file, s )
- !
- ! Reads the next line from a commented text file,
- ! but skips all lines starting with the 'comment'
- ! specified with the 'Init' command.
- ! Empty lines are skipped too.
- !
- subroutine ReadLine( file, s, status )
- use GO_Print, only : gol, goPr, goErr
- ! --- in/out -------------------------
- type(TTextFile), intent(inout) :: file
- character(len=*), intent(out) :: s
- integer, intent(out) :: status
- ! --- const --------------------------
-
- character(len=*), parameter :: rname = mname//'/ReadLine'
-
- ! --- local --------------------------
- character(len=10) :: fmt
- ! --- begin --------------------------
- ! format (a100) etc:
- write (fmt,'("(a",i6.6,")")') len(s)
- ! loop until:
- ! o uncommented line has been read in s
- ! o eof is reached
- do
-
- ! read next line:
- read (file%fu,fmt,iostat=status) s
- if ( status < 0 ) then ! eof
- s = ''
- status=-1; return
- else if ( status > 0 ) then
- write (gol,'("reading line from file:")'); call goErr
- write (gol,'(" ",a)') trim(file%name); call goErr
- write (gol,'("in ",a)') rname; call goErr; status=1; return
- end if
- ! remove leading space:
- s = adjustl( s )
- ! empty ?
- if ( len_trim(s) == 0 ) cycle
- ! check for comment ?
- if ( file%commented .and. (scan(s,file%comment)==1) ) cycle
-
- ! s filled; leave loop
- exit
-
- end do
-
- ! ok
- status = 0
- end subroutine ReadLine
- subroutine RewindFile( file, status)
- use GO_Print, only : gol, goPr, goErr
- ! --- in/out -------------------------
- type(TTextFile), intent(inout) :: file
- integer, intent(out) :: status
- ! --- const --------------------------
-
- character(len=*), parameter :: rname = mname//'/RewindFile'
-
- ! --- local --------------------------
- ! --- begin --------------------------
- rewind(unit = file%fu, iostat = status)
- if (status /= 0 ) then
- write (gol,'("Rewind operation failed")') ; call goErr
- write (gol,*) 'On file: ',trim(file%name) ; call goErr
- write (gol,*) 'Unit : ',file%fu ; call goErr
- write (gol,'("in ",a)') rname; call goErr; status=1; return
- endif
- status = 0
- end subroutine RewindFile
- end module GO_File
- ! ###########################################################################
- ! ###
- ! ### test program
- ! ###
- ! ###########################################################################
- !
- ! ---[test.rc]--------------------------------------
- ! !
- ! ! abcdefg
- ! ! 2
- !
- ! 0000000001111111111222222222233333333334
- ! 1234567890123456789012345678901234567890
- !
- ! aaa : kasfjasfjsla;kfja;ls
- !
- ! ! xxxxxxxxxx
- !
- ! bbb : 123
- ! --------------------------------------------------
- !
- !program test_go_file
- !
- ! use go_file
- !
- ! type(TTextFile) :: file
- ! character(len=25) :: s
- ! integer :: status
- !
- ! call Init( file, 'test.rc', status )
- ! if (status/=0) stop 'error'
- !
- ! do
- !
- ! call ReadLine( file, s, status )
- ! if (status<0) then
- ! print *, 'xxx eof'
- ! exit
- ! else if ( status == 0 ) then
- ! print *, 'xxx "'//trim(s)//'"'
- ! else
- ! print *, 'xxx error'
- ! exit
- ! end if
- !
- ! end do
- !
- ! call Done( file, status )
- ! if (status/=0) stop 'error'
- !
- !
- !end program test_go_file
- !
|