go_file.F90 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. !###############################################################################
  2. !
  3. #define IF_ERROR_RETURN(action) if (status/=0) then; write (gol,'("in ",a)') rname; call goErr; action; return; end if
  4. !
  5. !###############################################################################
  6. module GO_File
  7. implicit none
  8. ! --- in/out -------------------
  9. private
  10. public :: goGetFU
  11. public :: TTextFile
  12. public :: Init, Done
  13. public :: ReadLine, RewindFile
  14. ! --- const ---------------------------------
  15. character(len=*), parameter :: mname = 'GO_File'
  16. ! --- types -------------------------------------
  17. type TTextFile
  18. character(len=80) :: name
  19. ! file unit:
  20. integer :: fu
  21. ! comment ?
  22. logical :: commented
  23. character(len=1) :: comment
  24. end type TTextFile
  25. ! --- interfaces -------------------------------------
  26. interface Init
  27. module procedure file_Init
  28. end interface
  29. interface Done
  30. module procedure file_Done
  31. end interface
  32. contains
  33. ! ==============================================================
  34. ! ===
  35. ! === file units
  36. ! ===
  37. ! ==============================================================
  38. ! Returns the first free available file unit number.
  39. subroutine goGetFU( fu, status )
  40. use GO_FU , only : goStdIn, goStdOut, goStdErr
  41. use GO_FU , only : goFuRange
  42. use GO_Print, only : gol, goErr
  43. ! --- in/out --------------------------
  44. integer, intent(out) :: fu
  45. integer, intent(out) :: status
  46. ! --- const ---------------------------
  47. character(len=*), parameter :: rname = mname//'/goGetFU'
  48. ! --- local --------------------------
  49. integer :: i
  50. character(len=256) :: fname
  51. logical :: opened
  52. ! --- local ---------------------------
  53. ! start with lowest possible unit:
  54. fu = goFuRange(1) - 1
  55. ! loop until unopned unit is found:
  56. do
  57. ! try next file unit:
  58. fu = fu + 1
  59. ! too large ?
  60. if ( fu > goFuRange(2) ) then
  61. write (gol,'("unable to select free file unit within allowed range ...")'); call goErr
  62. write (gol,'("close some files or increase goFuRange in module GO_FU")'); call goErr
  63. write (gol,'("current goFuRange : ",i6," .. ",i6)') goFuRange; call goErr
  64. write (gol,'("open files:")')
  65. do i = goFuRange(1), goFuRange(2)
  66. inquire( unit=i, name=fname )
  67. write (gol,'(i6," : ",a)') i, trim(fname); call goErr
  68. end do
  69. write (gol,'("in ",a)') rname; call goErr; status=1; return
  70. end if
  71. ! skip ?
  72. if ( fu==goStdIn ) cycle
  73. if ( fu==goStdOut ) cycle
  74. if ( fu==goStdErr ) cycle
  75. ! free available unit ? then ok
  76. inquire( unit=fu, opened=opened )
  77. if ( .not. opened ) exit
  78. end do
  79. ! ok
  80. status = 0
  81. end subroutine goGetFU
  82. ! ==============================================================
  83. ! ===
  84. ! === text file
  85. ! ===
  86. ! ==============================================================
  87. !
  88. ! call Init( file, filename, iostat, [,status='unknown'|'old'|'new'] [,comment='\%'] )
  89. !
  90. ! Replaces the intrinsic 'open' command, but uses a
  91. ! a structure of type TTextFile instead of a file unit number. \\
  92. ! Arguments passed are the same as for 'open'.\\
  93. ! In addition, a text file can be opened as a commented
  94. ! text file; with the 'ReadLine' command one is able to read
  95. ! lines from the file while skipping the lines starting
  96. ! with the specified comment.
  97. !
  98. subroutine file_Init( file, filename, iostat, status, comment )
  99. use GO_Print, only : gol, goPr, goErr
  100. ! --- in/out ------------------------
  101. type(TTextFile), intent(out) :: file
  102. character(len=*), intent(in) :: filename
  103. integer, intent(out) :: iostat
  104. character(len=*), intent(in), optional :: status
  105. character(len=1), intent(in), optional :: comment
  106. ! --- const ---------------------------
  107. character(len=*), parameter :: rname = mname//'/file_Init'
  108. ! --- local ----------------------------
  109. logical :: exist
  110. character(len=10) :: statusX
  111. ! --- begin ----------------------------
  112. ! file exist ?
  113. inquire( file=trim(filename), exist=exist )
  114. if ( .not. exist ) then
  115. write (gol,'("commented text file not found:")'); call goErr
  116. write (gol,'(" file name : ",a)') trim(filename); call goErr
  117. write (gol,'("in ",a)') rname; call goErr; iostat=1; return
  118. end if
  119. ! check file status : 'old', 'new', 'unknown'
  120. if (present(status)) then
  121. statusX = status
  122. else
  123. statusX = 'unknown'
  124. end if
  125. ! store filename:
  126. file%name = filename
  127. ! select free file unit:
  128. Call goGetFU( file%fu, iostat )
  129. if (iostat/=0) then; write (gol,'("in ",a)') rname; call goErr; iostat=1; return; end if
  130. ! open file:
  131. open( unit=file%fu, file=trim(filename), iostat=iostat, &
  132. status=statusX, form='formatted' )
  133. if ( iostat /= 0 ) then
  134. write (gol,'("from file open :")'); call goErr
  135. write (gol,'(" file name : ",a)') trim(filename); call goErr
  136. write (gol,'("in ",a)') rname; call goErr; iostat=1; return
  137. end if
  138. ! check on comment lines ?
  139. if ( present(comment) ) then
  140. file%commented = .true.
  141. file%comment = comment
  142. else
  143. file%commented = .false.
  144. file%comment = 'x'
  145. end if
  146. ! ok
  147. iostat = 0
  148. end subroutine file_Init
  149. ! ***
  150. !
  151. ! call Done( file )
  152. !
  153. subroutine file_Done( file, status )
  154. use GO_Print, only : gol, goPr, goErr
  155. ! --- in/out -----------------
  156. type(TTextFile), intent(inout) :: file
  157. integer, intent(out) :: status
  158. ! --- const ----------------------
  159. character(len=*), parameter :: rname = mname//'/file_Done'
  160. ! --- begin ------------------------
  161. ! close file:
  162. close( unit=file%fu, iostat=status )
  163. if ( status /= 0 ) then
  164. write (gol,'("from closing file:")'); call goErr
  165. write (gol,'(" ",a)') trim(file%name); call goErr
  166. write (gol,'("in ",a)') rname; call goErr; status=1; return
  167. end if
  168. ! ok
  169. status = 0
  170. end subroutine file_Done
  171. ! ***
  172. !
  173. ! call ReadLine( file, s )
  174. !
  175. ! Reads the next line from a commented text file,
  176. ! but skips all lines starting with the 'comment'
  177. ! specified with the 'Init' command.
  178. ! Empty lines are skipped too.
  179. !
  180. subroutine ReadLine( file, s, status )
  181. use GO_Print, only : gol, goPr, goErr
  182. ! --- in/out -------------------------
  183. type(TTextFile), intent(inout) :: file
  184. character(len=*), intent(out) :: s
  185. integer, intent(out) :: status
  186. ! --- const --------------------------
  187. character(len=*), parameter :: rname = mname//'/ReadLine'
  188. ! --- local --------------------------
  189. character(len=10) :: fmt
  190. ! --- begin --------------------------
  191. ! format (a100) etc:
  192. write (fmt,'("(a",i6.6,")")') len(s)
  193. ! loop until:
  194. ! o uncommented line has been read in s
  195. ! o eof is reached
  196. do
  197. ! read next line:
  198. read (file%fu,fmt,iostat=status) s
  199. if ( status < 0 ) then ! eof
  200. s = ''
  201. status=-1; return
  202. else if ( status > 0 ) then
  203. write (gol,'("reading line from file:")'); call goErr
  204. write (gol,'(" ",a)') trim(file%name); call goErr
  205. write (gol,'("in ",a)') rname; call goErr; status=1; return
  206. end if
  207. ! remove leading space:
  208. s = adjustl( s )
  209. ! empty ?
  210. if ( len_trim(s) == 0 ) cycle
  211. ! check for comment ?
  212. if ( file%commented .and. (scan(s,file%comment)==1) ) cycle
  213. ! s filled; leave loop
  214. exit
  215. end do
  216. ! ok
  217. status = 0
  218. end subroutine ReadLine
  219. subroutine RewindFile( file, status)
  220. use GO_Print, only : gol, goPr, goErr
  221. ! --- in/out -------------------------
  222. type(TTextFile), intent(inout) :: file
  223. integer, intent(out) :: status
  224. ! --- const --------------------------
  225. character(len=*), parameter :: rname = mname//'/RewindFile'
  226. ! --- local --------------------------
  227. ! --- begin --------------------------
  228. rewind(unit = file%fu, iostat = status)
  229. if (status /= 0 ) then
  230. write (gol,'("Rewind operation failed")') ; call goErr
  231. write (gol,*) 'On file: ',trim(file%name) ; call goErr
  232. write (gol,*) 'Unit : ',file%fu ; call goErr
  233. write (gol,'("in ",a)') rname; call goErr; status=1; return
  234. endif
  235. status = 0
  236. end subroutine RewindFile
  237. end module GO_File
  238. ! ###########################################################################
  239. ! ###
  240. ! ### test program
  241. ! ###
  242. ! ###########################################################################
  243. !
  244. ! ---[test.rc]--------------------------------------
  245. ! !
  246. ! ! abcdefg
  247. ! ! 2
  248. !
  249. ! 0000000001111111111222222222233333333334
  250. ! 1234567890123456789012345678901234567890
  251. !
  252. ! aaa : kasfjasfjsla;kfja;ls
  253. !
  254. ! ! xxxxxxxxxx
  255. !
  256. ! bbb : 123
  257. ! --------------------------------------------------
  258. !
  259. !program test_go_file
  260. !
  261. ! use go_file
  262. !
  263. ! type(TTextFile) :: file
  264. ! character(len=25) :: s
  265. ! integer :: status
  266. !
  267. ! call Init( file, 'test.rc', status )
  268. ! if (status/=0) stop 'error'
  269. !
  270. ! do
  271. !
  272. ! call ReadLine( file, s, status )
  273. ! if (status<0) then
  274. ! print *, 'xxx eof'
  275. ! exit
  276. ! else if ( status == 0 ) then
  277. ! print *, 'xxx "'//trim(s)//'"'
  278. ! else
  279. ! print *, 'xxx error'
  280. ! exit
  281. ! end if
  282. !
  283. ! end do
  284. !
  285. ! call Done( file, status )
  286. ! if (status/=0) stop 'error'
  287. !
  288. !
  289. !end program test_go_file
  290. !