NCEPLIBS-bufr  12.0.0
ufbstp.f
Go to the documentation of this file.
1 C> @file
2 C> @brief Read/write one or more data values from/to a data subset.
3 C>
4 C> @author J. Woollen @date 1994-01-06
5 
6 C> This subroutine reads or writes one or more data values from or to
7 C> the BUFR data subset that is currently open within the BUFRLIB
8 C> internal arrays. The direction of the data transfer is determined
9 C> by the context of ABS(LUNIN):
10 C> - If ABS(LUNIN) points to a file that was previously opened for
11 C> input using subroutine openbf(), then data values are read from
12 C> the current data subset.
13 C> - If ABS(LUNIN) points to a file that was previously opened for
14 C> output using subroutine openbf(), then data values are written to
15 C> the current data subset.
16 C>
17 C> This subroutine is specifically designed for use with Table B
18 C> mnemonics which are part of a fixed (i.e. non-delayed) replication
19 C> sequence, or for mnemonics which are replicated by being directly
20 C> listed more than once within an overall subset definition.
21 C> It is very similar to subroutine ufbrep(), but it differs in how it
22 C> processes the input mnemonic string STR. For more details, see
23 C> the discussion and example use case in [DX BUFR Tables](@ref ufbsubs).
24 C> See also subroutines ufbint() and ufbseq(), which can also be used
25 C> to read/write one or more data values from/to a data subset but are
26 C> also designed for different use cases as noted in
27 C> [DX BUFR Tables](@ref ufbsubs).
28 C>
29 C> It is the user's responsibility to ensure that USR is dimensioned
30 C> sufficiently large enough to accommodate the number of data values
31 C> that are to be read from or written to the data subset. Note also
32 C> that USR is an array of real*8 values; therefore, any data that are
33 C> to be written out as character (i.e. CCITT IA5) values in
34 C> BUFR must be converted from character into real*8 format within the
35 C> application program before calling this subroutine. Conversely,
36 C> when this subroutine is being used to read character values from a
37 C> data subset, the value that is returned will be in real*8 format
38 C> and must be converted back into character format by the application
39 C> program before it can be used as such. Alternatively, there are
40 C> different subroutines such as readlc() and writlc() which can be
41 C> used to read/write character data directly from/to a data subset
42 C> without the need to convert from/to real*8 format as an intermediate
43 C> step.
44 C>
45 C> Numeric (i.e. non-character) data values within USR are always in
46 C> the exact units specified for the corresponding mnemonic within the
47 C> relevant DX or master BUFR table, without any scale or reference
48 C> values applied. Specifically, this means that, when writing
49 C> data values into an output subset, the user only needs to store each
50 C> respective value into USR using the units specified within the table,
51 C> and the BUFRLIB software will take care of any necessary scaling or
52 C> referencing of the value before it is actually encoded into BUFR.
53 C> Conversely, when reading data values from an input subset, the
54 C> values returned in USR are already de-scaled and de-referenced and,
55 C> thus, are already in the exact units that were defined for the
56 C> corresponding mnemonics within the table.
57 C>
58 C> "Missing" values in USR are always denoted by a unique
59 C> placeholder value. This placeholder value is initially set
60 C> to a default value of 10E10_8, but it can be reset to
61 C> any substitute value of the user's choice via a separate
62 C> call to subroutine setbmiss(). In any case, and whenever this
63 C> subroutine is used to read data values from an input subset, any
64 C> returned value in USR can be easily checked for equivalence to the
65 C> current placeholder value via a call to function ibfms(), and a
66 C> positive result means that the value for the corresponding mnemonic
67 C> was encoded as "missing" in BUFR (i.e. all bits set to 1) within the
68 C> original data subset. Conversely, whenever this subroutine
69 C> is used to write data values to an output subset, the current
70 C> placeholder value can be obtained via a separate call to function
71 C> getbmiss(), and the resulting value can then be stored into the
72 C> USR array whereever the user desires a BUFR "missing" value (i.e.
73 C> all bits set to 1) to be encoded for the corresponding mnemonic
74 C> within the output subset.
75 C>
76 C> @remarks
77 C> - If LUNIN < 0, and if ABS(LUNIN) points to a file that is open
78 C> for output (writing BUFR), then the subroutine will treat the file
79 C> pointed to by ABS(LUNIN) as though it was open for input (reading
80 C> BUFR). This is a special capability for use by some applications
81 C> that need to read certain values back out from a BUFR file during
82 C> the same time that it is in the process of being written to.
83 C>
84 C> @param[in] LUNIN -- integer: Absolute value is Fortran logical
85 C> unit number for BUFR file
86 C> @param[in,out] USR -- real*8(*,*): Data values
87 C> - If ABS(LUNIN) was opened for input, then
88 C> USR is output from this subroutine and
89 C> contains data values that were read
90 C> from the current data subset.
91 C> - If ABS(LUNIN) was opened for output, then
92 C> USR is input to this subroutine and
93 C> contains data values that are to be
94 C> written to the current data subset.
95 C> @param[in] I1 -- integer: First dimension of USR as allocated
96 C> within the calling program
97 C> @param[in] I2 -- integer:
98 C> - If ABS(LUNIN) was opened for input, then I2
99 C> must be set equal to the second dimension
100 C> of USR as allocated within the calling program
101 C> - If ABS(LUNIN) was opened for output, then I2
102 C> must be set equal to the number of replications
103 C> of STR that are to be written to the data subset
104 C> @param[out] IRET -- integer: Number of replications of STR that were
105 C> read/written from/to the data subset
106 C> @param[in] STR -- character*(*): String of blank-separated
107 C> Table B mnemonics
108 C> in one-to-one correspondence with the number of data
109 C> values that will be read/written from/to the data
110 C> subset within the first dimension of USR (see
111 C> [DX BUFR Tables](@ref dfbftab) for further
112 C> information about Table B mnemonics)
113 C>
114 C> @author J. Woollen @date 1994-01-06
115  RECURSIVE SUBROUTINE ufbstp(LUNIN,USR,I1,I2,IRET,STR)
116 
117  USE modv_im8b
118  USE modv_bmiss
119 
120  USE moda_usrint
121  USE moda_msgcwd
122 
123  COMMON /quiet / iprt
124 
125  CHARACTER*(*) str
126  CHARACTER*128 bort_str1,bort_str2,errstr
127  real*8 usr(i1,i2)
128 
129  DATA ifirst1/0/,ifirst2/0/
130 
131  SAVE ifirst1, ifirst2
132 
133 C----------------------------------------------------------------------
134 C----------------------------------------------------------------------
135 
136 C CHECK FOR I8 INTEGERS
137 C ---------------------
138 
139  IF(im8b) THEN
140  im8b=.false.
141 
142  CALL x84(lunin,my_lunin,1)
143  CALL x84(i1,my_i1,1)
144  CALL x84(i2,my_i2,1)
145  CALL ufbstp(my_lunin,usr,my_i1,my_i2,iret,str)
146  CALL x48(iret,iret,1)
147 
148  im8b=.true.
149  RETURN
150  ENDIF
151 
152  iret = 0
153 
154 C CHECK THE FILE STATUS AND I-NODE
155 C --------------------------------
156 
157  lunit = abs(lunin)
158  CALL status(lunit,lun,il,im)
159  IF(il.EQ.0) GOTO 900
160  IF(im.EQ.0) GOTO 901
161  IF(inode(lun).NE.inv(1,lun)) GOTO 902
162 
163  io = min(max(0,il),1)
164  IF(lunin.NE.lunit) io = 0
165 
166  IF(i1.LE.0) THEN
167  IF(iprt.GE.0) THEN
168  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
169  errstr = .LE.'BUFRLIB: UFBSTP - 3rd ARG. (INPUT) IS 0, ' //
170  . 'SO RETURN WITH 5th ARG. (IRET) = 0; 6th ARG. (STR) ='
171  CALL errwrt(errstr)
172  CALL errwrt(str)
173  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
174  CALL errwrt(' ')
175  ENDIF
176  GOTO 100
177  ELSEIF(i2.LE.0) THEN
178  IF(iprt.EQ.-1) ifirst1 = 1
179  IF(io.EQ.0 .OR. ifirst1.EQ.0 .OR. iprt.GE.1) THEN
180  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
181  errstr = .LE.'BUFRLIB: UFBSTP - 4th ARG. (INPUT) IS 0, ' //
182  . 'SO RETURN WITH 5th ARG. (IRET) = 0; 6th ARG. (STR) ='
183  CALL errwrt(errstr)
184  CALL errwrt(str)
185  IF(iprt.EQ.0 .AND. io.EQ.1) THEN
186  errstr = 'Note: Only the first occurrence of this WARNING ' //
187  . 'message is printed, there may be more. To output all ' //
188  . 'such messages,'
189  CALL errwrt(errstr)
190  errstr = 'modify your application program to add ' //
191  . '"CALL OPENBF(0,''QUIET'',1)" prior to the first call ' //
192  . 'to a BUFRLIB routine.'
193  CALL errwrt(errstr)
194  ENDIF
195  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
196  CALL errwrt(' ')
197  ifirst1 = 1
198  ENDIF
199  GOTO 100
200  ENDIF
201 
202 C INITIALIZE USR ARRAY PRECEEDING AN INPUT OPERATION
203 C --------------------------------------------------
204 
205  IF(io.EQ.0) THEN
206  DO j=1,i2
207  DO i=1,i1
208  usr(i,j) = bmiss
209  ENDDO
210  ENDDO
211  ENDIF
212 
213 C PARSE OR RECALL THE INPUT STRING - READ/WRITE VALUES
214 C ----------------------------------------------------
215 
216  CALL string(str,lun,i1,io)
217 
218 C CALL THE MNEMONIC READER/WRITER
219 C -------------------------------
220 
221  CALL ufbsp(lun,usr,i1,i2,io,iret)
222 
223  IF(io.EQ.1 .AND. iret.NE.i2) GOTO 903
224 
225  IF(iret.EQ.0) THEN
226  IF(io.EQ.0) THEN
227  IF(iprt.GE.1) THEN
228  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
229  errstr = 'BUFRLIB: UFBSTP - NO SPECIFIED VALUES READ IN, ' //
230  . 'SO RETURN WITH 5th ARG. (IRET) = 0; 6th ARG. (STR) ='
231  CALL errwrt(errstr)
232  CALL errwrt(str)
233  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
234  CALL errwrt(' ')
235  ENDIF
236  ELSE
237  IF(iprt.EQ.-1) ifirst2 = 1
238  IF(ifirst2.EQ.0 .OR. iprt.GE.1) THEN
239  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
240  errstr = 'BUFRLIB: UFBSTP - NO SPECIFIED VALUES WRITTEN OUT, ' //
241  . 'SO RETURN WITH 5th ARG. (IRET) = 0; 6th ARG. (STR) ='
242  CALL errwrt(errstr)
243  CALL errwrt(str)
244  CALL errwrt('MAY NOT BE IN THE BUFR TABLE(?)')
245  IF(iprt.EQ.0) THEN
246  errstr = 'Note: Only the first occurrence of this WARNING ' //
247  . 'message is printed, there may be more. To output all ' //
248  . 'such messages,'
249  CALL errwrt(errstr)
250  errstr = 'modify your application program to add ' //
251  . '"CALL OPENBF(0,''QUIET'',1)" prior to the first call ' //
252  . 'to a BUFRLIB routine.'
253  CALL errwrt(errstr)
254  ENDIF
255  CALL errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
256  CALL errwrt(' ')
257  ifirst2 = 1
258  ENDIF
259  ENDIF
260  ENDIF
261 
262 C EXITS
263 C -----
264 
265 100 RETURN
266 900 CALL bort('BUFRLIB: UFBSTP - BUFR FILE IS CLOSED, IT MUST BE'//
267  . ' OPEN')
268 901 CALL bort('BUFRLIB: UFBSTP - A MESSAGE MUST BE OPEN IN BUFR '//
269  . 'FILE, NONE ARE')
270 902 CALL bort('BUFRLIB: UFBSTP - LOCATION OF INTERNAL TABLE FOR '//
271  . 'BUFR FILE DOES NOT AGREE WITH EXPECTED LOCATION IN INTERNAL '//
272  . 'SUBSET ARRAY')
273 903 WRITE(bort_str1,'("BUFRLIB: UFBSTP - MNEMONIC STRING READ IN IS'//
274  . ': ",A)') str
275  WRITE(bort_str2,'(18X,"THE NUMBER OF ''LEVELS'' ACTUALLY '//
276  . 'WRITTEN (",I3,") DOES NOT EQUAL THE NUMBER REQUESTED (",I3,")'//
277  . ' - INCOMPLETE WRITE")') iret,i2
278  CALL bort2(bort_str1,bort_str2)
279  END
subroutine bort2(STR1, STR2)
Log two error messages and abort application program.
Definition: bort2.f:18
subroutine bort(STR)
Log one error message and abort application program.
Definition: bort.f:18
subroutine errwrt(STR)
This subroutine allows the user to specify a custom location for the logging of error and diagnostic ...
Definition: errwrt.f:36
This module contains declarations for arrays used to store information about the current BUFR message...
integer, dimension(:), allocatable inode
Table A mnemonic for type of BUFR message.
This module contains declarations for arrays used to store data values and associated metadata for th...
integer, dimension(:,:), allocatable, target inv
Inventory pointer which links each data value to its corresponding node in the internal jump/link tab...
This module declares and initializes the BMISS variable.
Definition: modules_vars.F90:9
real *8, public bmiss
Current placeholder value to represent "missing" data when reading from or writing to BUFR files; thi...
This module declares and initializes the IM8B variable.
logical, public im8b
Status indicator to keep track of whether all future calls to BUFRLIB subroutines and functions from ...
recursive subroutine status(LUNIT, LUN, IL, IM)
Check whether a specified Fortran logical unit number is currently connected to the NCEPLIBS-bufr sof...
Definition: status.f:36
subroutine string(STR, LUN, I1, IO)
This subroutine checks to see if a user-specified character string is in the string cache (arrays in ...
Definition: string.f:28
subroutine ufbsp(LUN, USR, I1, I2, IO, IRET)
This subroutine writes or reads specified values to or from the current BUFR data subset within inter...
Definition: ufbsp.f:37
recursive subroutine ufbstp(LUNIN, USR, I1, I2, IRET, STR)
This subroutine reads or writes one or more data values from or to the BUFR data subset that is curre...
Definition: ufbstp.f:116
subroutine x48(IIN4, IOUT8, NVAL)
Encode one or more 4-byte integer values as 8-byte integer values.
Definition: x48.F:19
subroutine x84(IIN8, IOUT4, NVAL)
Encode one or more 8-byte integer values as 4-byte integer values.
Definition: x84.F:19