0.6.2-dev0
FORCES
FORtran lib for Comp. Env. Sys.
Loading...
Searching...
No Matches
mo_nml.f90
Go to the documentation of this file.
1!> \file mo_nml.f90
2!> \brief \copybrief mo_nml
3!> \details \copydetails mo_nml
4
5!> \brief Deal with namelist files.
6!> \details This module provides routines to open, close and position namelist files.
7!! - Adapted from Echam5, (C) MPI-MET, Hamburg, Germany
8!> \author L. Kornblueh, MPI, March 2001, original source
9!> \changelog
10!! - Jan 2011, Matthias Cuntz
11!! - compatible with gfortran <= version 4.3
12!! - all integer(i4)
13!! - quiet
14!! - Jan 2013, Matthias Cuntz
15!! - close_nml with unit, open_nml quiet=.true. default position_nml swap first and status
16!> \authors Matthias Cuntz
17!> \date Jan 2011
18!> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
19!! FORCES is released under the LGPLv3+ license \license_note
20MODULE mo_nml
21
22 USE mo_kind, ONLY : i4
23 USE mo_string_utils, ONLY : tolower
25
26 IMPLICIT NONE
27
28 PRIVATE
29
30 PUBLIC :: open_nml ! open namelist file
31 PUBLIC :: close_nml ! close namelist file
32 PUBLIC :: position_nml ! position namelist file
33 PUBLIC :: nunitnml ! namelist unit
34 PUBLIC :: positioned, missing, length_error, read_error ! return values from position_nml
35
36 ! return values in optinal status of function 'position_nml'
37 !> Information: file pointer set to namelist group
38 INTEGER(i4), PARAMETER :: positioned = 0
39 !> Error: namelist group is missing
40 INTEGER(i4), PARAMETER :: missing = 1
41 !> Error: namelist group name too long
42 INTEGER(i4), PARAMETER :: length_error = 2
43 !> Error occured during read of namelist file
44 INTEGER(i4), PARAMETER :: read_error = 3
45
46 !> default namelist unit
47 INTEGER, SAVE :: nunitnml = -1
48
49 ! ------------------------------------------------------------------
50
51CONTAINS
52
53 ! ------------------------------------------------------------------
54
55 !> \brief Open a namelist file.
56
57 !> \details Open a namelist file.
58 !!
59 !! \b Example
60 !!
61 !! \code{.f90}
62 !! call open_nml('namelist.txt',nnml)
63 !! \endcode
64 !! See also example in test directory
65
66 !> \param[in] "character(len=*) :: file" namelist filename
67 !> \param[in] "integer :: unit" namelist unit
68 !> \param[in] "logical, optional :: quiet" Be verbose or not (default: .true.)\n
69 !! .true.: no messages\n
70 !! .false.: write out messages
71
72 !> \author Matthias Cuntz
73 !> \date Dec 2011
74 !! - modified from Echam5, (C) MPI-MET, Hamburg, Germany
75 !> \date Jan 2013
76 !! - quiet=.true. default
77 !> \author Luis Samaniego
78 !> \date Nov 2013
79 !! - comparison statements == -> .eq., etc
80
81 SUBROUTINE open_nml(file, unit, quiet)
82
83 IMPLICIT NONE
84
85 CHARACTER(len = *), INTENT(IN) :: file
86 INTEGER, INTENT(IN) :: unit
87 LOGICAL, INTENT(IN), OPTIONAL :: quiet
88 INTEGER :: istat
89 LOGICAL :: iquiet
90
91 iquiet = .false.
92 if (present(quiet)) iquiet = quiet
93
94 nunitnml = unit
95 if (.not. iquiet) CALL message(' This is namelist ', trim(file))
96 OPEN (nunitnml, file = file, iostat = istat, status = 'old', action = 'read', delim = 'apostrophe')
97
98 IF (istat .ne. 0) THEN
99 CALL error_message('OPEN_NML: Could not open namelist file ', trim(file))
100 END IF
101
102 END SUBROUTINE open_nml
103
104 ! ------------------------------------------------------------------
105
106 !> \brief Close a namelist file.
107
108 !> \details Close a namelist file.
109 !!
110 !! \b Example
111 !!
112 !! \code{.f90}
113 !! call close_nml()
114 !! ! or
115 !! call close_nml(unml)
116 !! \endcode
117 !! See also example in test directory
118
119 !> \param[in] "integer, optional :: unit" namelist unit
120
121 !> \note
122 !! open_nml remembers the namelist unit in the public, save variable nunitnml.\n
123 !! close_nml uses nunitnml if unit is not given.
124
125 !> \author Matthias Cuntz
126 !> \date Dec 2011
127 !! - modified from Echam5, (C) MPI-MET, Hamburg, Germany
128 !> \date Jan 2013
129 !! - unit
130 SUBROUTINE close_nml(unit)
131
132 IMPLICIT NONE
133
134 INTEGER, INTENT(IN), OPTIONAL :: unit
135
136 INTEGER :: istat, nnml
137
138 nnml = nunitnml
139 if (present(unit)) nnml = unit
140
141 IF (nnml .lt. 0) CALL error_message('CLOSE_NML: No namelist file opened.')
142
143 CLOSE(nnml, iostat = istat)
144
145 IF (istat .ne. 0) CALL error_message('CLOSE_NML: Could not close namelist file.')
146
147 if (.not. present(unit)) nunitnml = -1
148
149 END SUBROUTINE close_nml
150
151 ! ------------------------------------------------------------------
152
153 !> \brief Position a namlist file.
154
155 !> \details Position namelist file pointer for reading a new namelist next.\n
156 !! It positions the namelist file at the correct place for reading\n
157 !! namelist /name/ (case independent).
158 !!
159 !! \b Example
160 !!
161 !! \code{.f90}
162 !! call position_nml('myname',nnml)
163 !! \endcode
164
165 !> \param[in] "character(len=*) :: name" namelist name (case independent)
166 !> \param[in] "integer, optional :: unit" namelist unit (default: nunitnml)
167 !> \param[in] "logical, optional :: first" start search at beginning,
168 !! i.e. rewind the namelist first (default: .true.)\n
169 !! .true.: rewind\n
170 !! .false.: continue search from current file pointer
171 !> \param[out] "integer(i4), optional :: status" Set on output to either of\n
172 !! POSITIONED (0) - correct\n
173 !! MISSING (1) - name not found\n
174 !! LENGTH_ERROR (2) - namelist length longer then 256 characters\n
175 !! READ_ERROR (3) - error while reading namelist file
176
177 !> \author Matthias Cuntz
178 !> \date Dec 2011
179 !! - modified from Echam5, (C) MPI-MET, Hamburg, Germany
180 !> \date Jan 2013
181 !! - swap first and status in call list
182 SUBROUTINE position_nml(name, unit, status, first)
183
184 IMPLICIT NONE
185
186 CHARACTER(len = *), INTENT(in) :: name ! namelist group name
187 INTEGER, INTENT(in), OPTIONAL :: unit ! file unit number
188 INTEGER(i4), INTENT(out), OPTIONAL :: status ! error return value
189 LOGICAL, INTENT(in), OPTIONAL :: first ! default: true
190
191 CHARACTER(len = 256) :: yline ! line read
192 CHARACTER(len = 256) :: test ! uppercase namelist group name
193 INTEGER(i4) :: stat ! local copy of status variable
194 INTEGER :: ios ! status variable from read operation
195 LOGICAL :: lrew ! local copy of rewind flag
196 INTEGER(i4) :: iunit ! local copy of unit number
197 INTEGER(i4) :: len_name ! length of requested namelist group name
198 CHARACTER :: ytest ! character to test for delimiter
199 CHARACTER(len = 12) :: code ! error code printed
200 INTEGER(i4) :: ind ! index from index routine
201 INTEGER(i4) :: indc ! index of comment character (!)
202
203 lrew = .true.
204 IF (PRESENT(first)) lrew = first
205 iunit = nunitnml
206 IF (PRESENT(unit)) iunit = unit
207 stat = missing
208 code = 'MISSING'
209
210 len_name = len_trim(name)
211
212 IF (len_name .gt. len(test)) THEN
213 stat = length_error
214 code = 'LENGTH_ERROR'
215 END IF
216
217 !test = '&'//tolower(name)
218 write(test, '(A,A)') '&', tolower(name)
219
220 ! Reposition file at beginning:
221 IF (lrew) rewind(iunit)
222
223 ! Search start of namelist
224 DO
225 IF (stat .ne. missing) EXIT
226
227 yline = ' '
228
229 READ (iunit, *, iostat = ios) yline
230 IF (ios .lt. 0) THEN
231 EXIT ! MISSING
232 ELSE IF (ios .gt. 0) THEN
233 stat = read_error
234 code = 'READ_ERROR'
235 EXIT
236 END IF
237
238 yline = tolower(yline)
239
240 ind = index(yline, trim(test))
241
242 IF (ind .eq. 0) cycle
243
244 indc = index(yline, '!')
245
246 IF (indc .gt. 0 .AND. indc .lt. ind) cycle
247
248 ! test for delimiter
249 ytest = yline(ind + len_name + 1 : ind + len_name + 1)
250
251 IF ((lge(ytest, '0') .AND. lle(ytest, '9')) .OR. &
252 (lge(ytest, 'a') .AND. lle(ytest, 'z')) .OR. &
253 ytest .eq. '_' .OR. &
254 (lge(ytest, 'A') .AND. lle(ytest, 'Z'))) THEN
255 cycle
256 ELSE
257 stat = positioned
258 backspace(iunit)
259 EXIT
260 END IF
261 END DO
262
263 IF (PRESENT(status)) status = stat
264 SELECT CASE (stat)
265 CASE (positioned)
266 RETURN
267 CASE (missing)
268 IF (PRESENT(status)) RETURN
269 END SELECT
270
271 ! Error if it reaches here
272 CALL error_message('POSITION_NML: namelist /', trim(name) , '/ ', trim(code))
273
274 END SUBROUTINE position_nml
275
276END MODULE mo_nml
Define number representations.
Definition mo_kind.F90:17
integer, parameter i4
4 Byte Integer Kind
Definition mo_kind.F90:40
Write out concatenated strings.
subroutine, public error_message(t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15, t16, uni, advance, show, raise, reset_format)
Write out an error message to stderr and call stop 1.
subroutine, public message(t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15, t16, uni, advance, show, reset_format)
Write out an error message to stdout.
Deal with namelist files.
Definition mo_nml.f90:20
integer, save, public nunitnml
default namelist unit
Definition mo_nml.f90:47
subroutine, public position_nml(name, unit, status, first)
Position a namlist file.
Definition mo_nml.f90:183
integer(i4), parameter, public positioned
Information: file pointer set to namelist group.
Definition mo_nml.f90:38
integer(i4), parameter, public missing
Error: namelist group is missing.
Definition mo_nml.f90:40
subroutine, public close_nml(unit)
Close a namelist file.
Definition mo_nml.f90:131
subroutine, public open_nml(file, unit, quiet)
Open a namelist file.
Definition mo_nml.f90:82
integer(i4), parameter, public read_error
Error occured during read of namelist file.
Definition mo_nml.f90:44
integer(i4), parameter, public length_error
Error: namelist group name too long.
Definition mo_nml.f90:42
String utilities.
character(len=len_trim(upper)) function, public tolower(upper)
Convert to lower case.