NCEPLIBS-bufr 11.7.1
openbf.f
Go to the documentation of this file.
1C> @file
2C> @brief Connect a new system file to the BUFRLIB software for
3C> reading or writing BUFR messages.
4
5C> This subroutine connects a new file to the BUFRLIB software for
6C> input or output operations.
7C>
8C> @authors J. Woollen
9C> @authors J. Ator
10C> @authors D. Keyser
11C> @date 1994-01-06
12C>
13C> @param[in] LUNIT -- integer: Fortran logical unit number for BUFR
14C> file (unless IO is set to 'FIRST' or 'QUIET', in
15C> which case this is a dummy argument)
16C> @param[in] IO -- character*(*): flag indicating how LUNIT is to be
17C> used by the software:
18C> - 'IN' = input operations with table processing
19C> - 'INX' = input operations w/o table processing
20C> - 'OUX' = output operations w/o table processing
21C> - 'OUT' = output operations with table processing
22C> - 'SEC3' = same as 'IN', except use Section 3 of input
23C> messages for decoding rather than DX BUFR
24C> table information from LUNDX; in this case
25C> LUNDX is ignored, and user must provide
26C> appropriate [master BUFR tables](@ref dfbfmstab)
27C> within the directory specified by a subsequent
28C> call to subroutine mtinfo()
29C> - 'NODX' = same as 'OUT', except don't write DX BUFR
30C> table messages to LUNIT
31C> - 'APN' = same as 'NODX', except begin writing at end
32C> of file ("append")
33C> - 'APX' = same as 'APN', except backspace before
34C> appending
35C> - 'NUL' = same as 'OUT', except don't write any
36C> messages whatsoever to LUNIT (e.g. when
37C> subroutine writsa() is to be used)
38C> - 'INUL' = same as 'IN', except don't read any
39C> messages whatsoever from LUNIT (e.g. when
40C> subroutine readerme() is to be used)
41C> - 'QUIET' = LUNIT is ignored; this is an indicator
42C> that the value for IPRT in COMMON block
43C> /QUIET/ is being reset to the value in
44C> LUNDX
45C> - 'FIRST' = LUNIT and LUNDX are ignored; this is an
46C> indicator to initialize the BUFRLIB
47C> software, in case this subroutine was
48C> never previously called
49C> @param[in] LUNDX -- integer:
50C> - If IO is not set to 'FIRST' or 'QUIET' =
51C> Fortran logical unit number
52C> containing DX BUFR table information to be used in
53C> reading/writing from/to LUNIT (depending on the case).
54C> This value may be set equal to LUNIT if DX BUFR table
55C> information is already embedded in LUNIT.
56C> - If IO is set to 'QUIET' = indicator for degree of
57C> printout:
58C> - -1 = no printout except for ABORT messages
59C> - 0 = limited printout (default)
60C> - 1 = all warning messages are printed out
61C> - 2 = all warning and informational messages are
62C> printed out
63C>
64C> <p>The logical unit numbers LUNIT and LUNDX must already be associated
65C> with actual filenames on the local system, typically via a Fortran "OPEN"
66C> statement. Multiple logical units can be connected to the BUFRLIB software
67C> at any one time.
68C>
69C> <p>The argument IO is a character string describing how the file connected to
70C> LUNIT will be used, e.g. 'IN' is used to access an existing file of BUFR
71C> messages for input (i.e. reading/decoding BUFR), and 'OUT' is used to access
72C> a new file for output (i.e. writing/encoding BUFR). An option 'APX' is also
73C> available which behaves like 'OUT', except that output is then appended to
74C> an existing BUFR file rather than creating a new one from scratch, and there
75C> are also some additional options 'NUL' and 'NODX' which can likewise be used
76C> instead of 'OUT' for some very special cases as needed. There's also an
77C> option 'SEC3' which can be used in place of 'IN' for certain cases when the
78C> user is attempting to read BUFR messages whose content and descriptor layout
79C> are unknown in advance. However, all of these additional options are
80C> basically just variations of 'IN' or 'OUT', again depending on whether the
81C> intent is to read or write BUFR messages from the file connected to LUNIT.
82C> The only exceptions are when IO = 'FIRST' or 'QUIET'. When IO = 'FIRST',
83C> the subroutine simply checks whether it has already been called from within
84C> the application program and, if not, goes ahead and initializes the library
85C> without actually connecting any files in LUNIT or LUNDX.
86C> Alternatively, when IO = 'QUIET', the subroutine simply sets or resets the
87C> internal print verbosity switch to the value of input argument LUNDX,
88C> overriding its previous value and/or its internal default value of 0.
89C>
90C> <p>The third and final call argument LUNDX identifies the logical unit which
91C> contains the definition of the DX BUFR tables to be associated with unit
92C> LUNIT. Except when IO = 'SEC3', every BUFR file that is linked to the BUFRLIB
93C> software must have a DX BUFR tables file associated with it, and these tables
94C> may be defined within a separate ASCII text file
95C> (see [Description and Format of DX BUFR Tables](@ref dfbftab) for more info.)
96C> or, in the case of an existing BUFR file, may be embedded within the first few
97C> BUFR messages of the file itself, and in which case the user can denote this
98C> to the subroutine by setting LUNDX to the same value as LUBFR.
99C>
100C> @remarks
101C> - When an existing BUFR file is accessed for input (i.e. reading/decoding BUFR),
102C> the associated DX BUFR tables defined by LUNDX are stored internally within
103C> the BUFRLIB software and are referenced during all subsequent processing of
104C> the file. Likewise, when a file is accessed for output (i.e. writing/encoding
105C> BUFR), the associated DX BUFR tables are still stored internally for subsequent
106C> reference; however, the output file itself is also initialized by writing the
107C> BUFR table information (as one or more BUFR messages) to the beginning of the
108C> file, except when IO = 'NODX', and in which case the writing of these
109C> additional messages is suppressed.
110C> - As noted above, 'SEC3' is the only value of IO (other than 'QUIET') where it's
111C> not necessary to provide pre-defined DX BUFR tables via LUNDX. Instead, this
112C> option instructs the BUFRLIB software to unpack the data description section
113C> (Section 3) from each BUFR message it reads and then decode the contents
114C> accordingly. In this case, it's necessary to provide a set of BUFR master
115C> tables containing listings of all possible BUFR descriptors
116C> (see [Description and Format of master BUFR Tables](@ref dfbfmstab) for more
117C> info.), but otherwise no prior knowledge is required of the contents of the
118C> messages to be decoded.
119C>
120C> <b>Program history log:</b>
121C> | Date | Programmer | Comments |
122C> | -----|------------|----------|
123C> | 1994-01-06 | J. Woollen | Original author |
124C> | 1998-07-08 | J. Woollen | Replaced call to Cray library routine ABORT with call to new internal routine bort() |
125C> | 1999-11-18 | J. Woollen | The number of BUFR files which can be opened at one time increased from 10 to 32 |
126C> | 2003-11-04 | J. Ator | Added IO='NUL' option to prevent later writing to BUFR file in LUNIT; added documentation |
127C> | 2003-11-04 | S. Bender | Added remarks and routine interdependencies |
128C> | 2003-11-04 | D. Keyser | Unified/portable for WRF; added documentation; outputs more complete diagnostic info when routine terminates abnormally |
129C> | 2004-08-18 | J. Ator | Added SAVE for IFIRST flag and IO="NODX" option |
130C> | 2005-11-29 | J. Ator | Added COMMON /MSGFMT/ and ichkstr() call |
131C> | 2009-03-23 | J. Ator | Added IO='SEC3' option; removed call to posapn; clarified comments; use errwrt() |
132C> | 2010-05-11 | J. Ator | Added COMMON /STCODE/ |
133C> | 2012-06-18 | J. Ator | Added IO='INUL' option |
134C> | 2012-09-15 | J. Woollen | Modified for C/I/O/BUFR interface; use INQUIRE to obtain filename; use openrb(), openwb() and openab(); add IO types 'INX' and 'FIRST' |
135C> | 2014-11-07 | J. Ator | Allow dynamic allocation of certain arrays |
136C> | 2015-03-03 | J. Ator | Use MODA_IFOPBF instead of IFIRST |
137C>
138 SUBROUTINE openbf(LUNIT,IO,LUNDX)
139
140 USE modv_ifopbf
141 USE modv_nfiles
142
143 USE moda_msgcwd
144 USE moda_stbfr
145 USE moda_sc3bfr
146 USE moda_lushr
147 USE moda_nulbfr
148 USE moda_stcode
149
150 COMMON /quiet / iprt
151
152 CHARACTER*(*) IO
153 CHARACTER*255 FILENAME,FILEACC
154 CHARACTER*128 BORT_STR,ERRSTR
155 CHARACTER*28 CPRINT(0:3)
156 CHARACTER*1 BSTR(4)
157
158 DATA cprint/
159 . ' (only ABORTs) ',
160 . ' (limited - default) ',
161 . ' (all warnings) ',
162 . ' (all warning+informational)'/
163
164C-----------------------------------------------------------------------
165C-----------------------------------------------------------------------
166
167C If this is the first call to this subroutine, initialize
168C IPRT in /QUIET/ as 0 (limited printout - except for abort
169C messages)
170
171 IF(ifopbf.EQ.0) iprt = 0
172
173 IF(io.EQ.'QUIET') THEN
174c .... override previous IPRT value (printout indicator)
175 IF(lundx.LT.-1) lundx = -1
176 IF(lundx.GT. 2) lundx = 2
177 IF(lundx.GE.0) THEN
178 CALL errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
179 WRITE ( unit=errstr, fmt='(A,I3,A,A,I3,A)' )
180 . 'BUFRLIB: OPENBF - DEGREE OF MESSAGE PRINT INDICATOR '//
181 . 'CHNGED FROM',iprt,cprint(iprt+1),' TO',lundx,cprint(lundx+1)
182 CALL errwrt(errstr)
183 CALL errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
184 CALL errwrt(' ')
185 ENDIF
186 iprt = lundx
187 ENDIF
188
189 IF(ifopbf.EQ.0) THEN
190
191C This is the first call to this subroutine, so take care of some
192C initial housekeeping tasks. Note that ARALLOCF, ARALLOCC, and
193C WRDLEN must all be called prior to calling BFRINI.
194
195C Allocate any arrays which are being dynamically sized.
196 CALL arallocf
197 CALL arallocc
198
199C Figure out some important information about the local machine.
200 CALL wrdlen
201
202C Initialize some global variables.
203 CALL bfrini
204
205 ifopbf = 1
206 ENDIF
207
208 IF(io.EQ.'FIRST') GOTO 100
209 IF(io.EQ.'QUIET') GOTO 100
210
211C SEE IF A FILE CAN BE OPENED
212C ---------------------------
213
214 CALL status(lunit,lun,il,im)
215 IF(lun.EQ.0) GOTO 900
216 IF(il .NE.0) GOTO 901
217 null(lun) = 0
218 isc3(lun) = 0
219 iscodes(lun) = 0
220 lus(lun) = 0
221
222C USE INQUIRE TO OBTAIN THE FILENAME ASSOCIATED WITH UNIT LUNIT
223C -------------------------------------------------------------
224
225 IF (io.NE.'NUL' .AND. io.NE.'INUL') THEN
226 INQUIRE(lunit,access=fileacc)
227 IF(fileacc=='UNDEFINED') OPEN(lunit)
228 INQUIRE(lunit,name=filename)
229 filename=trim(filename)//char(0)
230 ENDIF
231
232C SET INITIAL OPEN DEFAULTS (CLEAR OUT A MSG CONTROL WORD PARTITION)
233C ------------------------------------------------------------------
234
235 nmsg(lun) = 0
236 nsub(lun) = 0
237 msub(lun) = 0
238 inode(lun) = 0
239 idate(lun) = 0
240
241C DECIDE HOW TO OPEN THE FILE AND SETUP THE DICTIONARY
242C ----------------------------------------------------
243
244 IF(io.EQ.'IN') THEN
245 CALL openrb(lun,filename)
246 CALL wtstat(lunit,lun,-1,0)
247 CALL readdx(lunit,lun,lundx)
248 ELSE IF(io.EQ.'INUL') THEN
249 CALL wtstat(lunit,lun,-1,0)
250 IF(lunit.NE.lundx) CALL readdx(lunit,lun,lundx)
251 null(lun) = 1
252 ELSE IF(io.EQ.'NUL') THEN
253 CALL wtstat(lunit,lun, 1,0)
254 IF(lunit.NE.lundx) CALL readdx(lunit,lun,lundx)
255 null(lun) = 1
256 ELSE IF(io.EQ.'INX') THEN
257 CALL openrb(lun,filename)
258 CALL wtstat(lunit,lun,-1,0)
259 null(lun) = 1
260 ELSE IF(io.EQ.'OUX') THEN
261 CALL openwb(lun,filename)
262 CALL wtstat(lunit,lun, 1,0)
263 ELSE IF(io.EQ.'SEC3') THEN
264 CALL openrb(lun,filename)
265 CALL wtstat(lunit,lun,-1,0)
266 isc3(lun) = 1
267 ELSE IF(io.EQ.'OUT') THEN
268 CALL openwb(lun,filename)
269 CALL wtstat(lunit,lun, 1,0)
270 CALL writdx(lunit,lun,lundx)
271 ELSE IF(io.EQ.'NODX') THEN
272 CALL openwb(lun,filename)
273 CALL wtstat(lunit,lun, 1,0)
274 CALL readdx(lunit,lun,lundx)
275 ELSE IF(io.EQ.'APN' .OR. io.EQ.'APX') THEN
276 CALL openab(lun,filename)
277 CALL wtstat(lunit,lun, 1,0)
278 IF(lunit.NE.lundx) CALL readdx(lunit,lun,lundx)
279 CALL posapx(lunit)
280 ELSE
281 GOTO 904
282 ENDIF
283
284 GOTO 100
285
286C FILE OPENED FOR INPUT IS EMPTY - LET READMG OR READERME GIVE
287C THE BAD NEWS LATER
288
289200 rewind lunit
290 IF(iprt.GE.0) THEN
291 CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
292 WRITE ( unit=errstr, fmt='(A,I3,A)' )
293 . 'BUFRLIB: OPENBF - INPUT BUFR FILE IN UNIT ', lunit,
294 . ' IS EMPTY'
295 CALL errwrt(errstr)
296 CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
297 CALL errwrt(' ')
298 ENDIF
299 CALL wtstat(lunit,lun,-1,0)
300
301C INITIALIZE THE DICTIONARY TABLE PARTITION
302C -----------------------------------------
303
304 CALL dxinit(lun,0)
305
306C EXITS
307C -----
308
309100 RETURN
310900 WRITE(bort_str,'("BUFRLIB: OPENBF - THERE ARE ALREADY",I3,'//
311 . '" BUFR FILES OPENED, CANNOT OPEN FILE CONNECTED TO UNIT",I4)')
312 . nfiles,lunit
313 CALL bort(bort_str)
314901 WRITE(bort_str,'("BUFRLIB: OPENBF - THE FILE CONNECTED TO UNIT"'//
315 . ',I5," IS ALREADY OPEN")') lunit
316 CALL bort(bort_str)
317904 CALL bort('BUFRLIB: OPENBF - SECOND (INPUT) ARGUMENT MUST BE'//
318 . ' "IN", "OUT", "NODX", "NUL", "APN", "APX", "SEC3"'//
319 . ' OR "QUIET"')
320 END
void arallocc(void)
This subroutine is called internally during the first call to subroutine openbf() from an application...
Definition: arallocc.c:36
subroutine arallocf
This subroutine is called internally during the first call to subroutine openbf() from an application...
Definition: arallocf.f:36
subroutine bfrini
This subroutine initializes numerous global variables and arrays within internal modules and COMMON b...
Definition: bfrini.f90:38
subroutine bort(STR)
This subroutine calls subroutine errwrt() to log an error message, then calls subroutine bort_exit() ...
Definition: bort.f:23
void openrb(f77int *nfile, char *ufile)
This subroutine opens a new system file for reading BUFR messages.
Definition: cread.c:34
void openwb(f77int *nfile, char *ufile)
This subroutine opens a new system file for writing BUFR messages.
Definition: cread.c:51
void openab(f77int *nfile, char *ufile)
This subroutine opens a new system file for appending BUFR messages.
Definition: cread.c:68
subroutine dxinit(LUN, IOI)
THIS SUBROUTINE INITIALIZES THE INTERNAL ARRAYS (IN MODULE TABABD) HOLDING THE DICTIONARY TABLE.
Definition: dxinit.f:41
subroutine errwrt(STR)
This subroutine allows the user to specify a custom location for the logging of error and diagnostic ...
Definition: errwrt.f:42
This module declares and initializes the IFOPBF variable.
Definition: modv_IFOPBF.f90:9
integer, public ifopbf
Status indicator to keep track of whether subroutine openbf() has already been called:
Definition: modv_IFOPBF.f90:16
This module declares and initializes the NFILES variable.
Definition: modv_NFILES.f90:12
integer, public nfiles
Maximum number of BUFR files that can be connected to the BUFRLIB software (for reading or writing) a...
Definition: modv_NFILES.f90:17
subroutine openbf(LUNIT, IO, LUNDX)
This subroutine connects a new file to the BUFRLIB software for input or output operations.
Definition: openbf.f:139
subroutine posapx(LUNXX)
THIS SUBROUTINE READS TO THE END OF THE FILE POINTED TO BY ABS(LUNXX) AND POSITIONS IT FOR APPENDING.
Definition: posapx.f:50
subroutine readdx(LUNIT, LUN, LUNDX)
THIS SUBROUTINE GENERATES INTERNAL ARRAYS CONTAINING BUFR DICTIONARY TABLES WHICH ARE NEEDED TO READ,...
Definition: readdx.f:55
subroutine status(LUNIT, LUN, IL, IM)
This subroutine checks whether a specified Fortran logical unit number is currently connected to the ...
Definition: status.f:56
subroutine wrdlen
This subroutine figures out some important information about the local machine on which the BUFRLIB s...
Definition: wrdlen.F:36
subroutine writdx(LUNIT, LUN, LUNDX)
THIS SUBROUTINE WRITES BUFR TABLE (DICTIONARY) MESSAGES TO THE BEGINNING OF AN OUTPUT BUFR FILE IN LU...
Definition: writdx.f:51
subroutine wtstat(LUNIT, LUN, IL, IM)
This subroutine can be used to connect or disconnect a specified Fortran logical unit number to/from ...
Definition: wtstat.f:53