NCEPLIBS-bufr 11.7.1
msgwrt.f
Go to the documentation of this file.
1C> @file
2C> @brief Finalize a BUFR message for output and write the message to
3C> a BUFR file.
4
5C> This subroutine performs final checks and updates on a BUFR message
6C> before writing it to a specified Fortran logical unit.
7C>
8C> <p>These final checks and updates include:
9C> - Standardizing the BUFR message, if requested via a previous call
10C> subroutine stdmsg()
11C> - Converting the BUFR message from edition 3 to edition 4, if
12C> requested via a previous call to subroutine pkvs01()
13C> - Storing any customized values into Section 0 or Section 1 of the
14C> BUFR message, if requested via one or more previous calls to
15C> subroutine pkvs01()
16C> - Storing a tank receipt time into Section 1 of the BUFR message,
17C> if requested via a previous call to subroutine strcpt()
18C> - For edition 3 BUFR messages, ensuring each section of the message
19C> contains an even number of bytes
20C> - Storing '7777' into the last four bytes of the BUFR message, and
21C> storing the final message length in Section 0
22C> - Appending zeroed-out bytes after the end of the BUFR message, up
23C> to the next machine word boundary
24C> - Encapsulating the BUFR message with IEEE Fortran control words,
25C> if requested via a previous call to subroutine setblock()
26C> - Storing a copy of the final message into internal arrays for
27C> possible later retrival via subroutine writsa()
28C>
29C> @author J. Woollen
30C> @date 1994-01-06
31C>
32C> @param[in] LUNIT -- integer: Fortran logical unit number for BUFR
33C> file
34C> @param[in] MESG -- integer(*): BUFR message
35C> @param[in] MGBYT -- integer: Size (in bytes) of BUFR message
36C>
37C> <b>Program history log:</b>
38C> | Date | Programmer | Comments |
39C> | -----|------------|----------|
40C> | 1994-01-06 | J. Woollen | Original author |
41C> | 1997-07-29 | J. Woollen | Modified to update the current BUFR version written in Section 0 from 2 to 3 |
42C> | 1998-07-08 | J. Woollen | Replaced call to Cray library routine ABORT with call to new internal routine bort() |
43C> | 1998-11-24 | J. Woollen | Modified to zero out the padding bytes written at the end of Section 4 |
44C> | 2000-09-19 | J. Woollen | Maximum message length increased from 10,000 to 20,000 bytes |
45C> | 2003-11-04 | J. Ator | Don't write to LUNIT if opened by openbf() using IO = 'NUL' |
46C> | 2003-11-04 | S. Bender | Added remarks and routine interdependencies |
47C> | 2003-11-04 | D. Keyser | Unified/portable for WRF; added documentation; outputs more complete diagnostic info when routine terminates abnormally |
48C> | 2005-11-29 | J. Ator | Use getlens(), iupbs01(), padmsg(), pkbs1() and nmwrd(); added logic to call pkbs1() and/or cnved4() when necessary |
49C> | 2009-03-23 | J. Ator | Use idxmsg() and errwrt(); add call to atrcpt(); allow standardizing even if data is compressed; work on local copy of input message |
50C> | 2012-09-15 | J. Woollen | Modified for C/I/O/BUFR interface; call new routine blocks() for file blocking and new C routine cwrbufr() to write BUFR message to disk file |
51C> | 2014-12-10 | J. Ator | Use modules instead of COMMON blocks |
52C> | 2019-05-09 | J. Ator | Added dimensions for MSGLEN and MSGTXT |
53C>
54 SUBROUTINE msgwrt(LUNIT,MESG,MGBYT)
55
56 USE modv_mxmsgl
57
58 USE moda_nulbfr
59 USE moda_bufrmg
60 USE moda_mgwa
61 USE moda_mgwb
62 USE moda_s01cm
63
64 COMMON /quiet / iprt
65 COMMON /msgstd/ csmf
66 COMMON /tnkrcp/ itryr,itrmo,itrdy,itrhr,itrmi,ctrt
67
68 CHARACTER*128 ERRSTR
69
70 CHARACTER*4 BUFR,SEVN
71 CHARACTER*1 CSMF
72 CHARACTER*1 CTRT
73 dimension mesg(*)
74 dimension iec0(2)
75
76 DATA bufr/'BUFR'/
77 DATA sevn/'7777'/
78
79C-----------------------------------------------------------------------
80C-----------------------------------------------------------------------
81
82C MAKE A LOCAL COPY OF THE INPUT MESSAGE FOR USE WITHIN THIS
83C SUBROUTINE, SINCE CALLS TO ANY OR ALL OF THE SUBROUTINES STNDRD,
84C CNVED4, PKBS1, ATRCPT, ETC. MAY END UP MODIFYING THE MESSAGE
85C BEFORE IT FINALLY GETS WRITTEN OUT TO LUNIT.
86
87 mbyt = mgbyt
88
89 iec0(1) = mesg(1)
90 iec0(2) = mesg(2)
91 ibit = 32
92 CALL pkb(mbyt,24,iec0,ibit)
93
94 DO ii = 1, nmwrd(iec0)
95 mgwa(ii) = mesg(ii)
96 ENDDO
97
98C OVERWRITE ANY VALUES WITHIN SECTION 0 OR SECTION 1 THAT WERE
99C REQUESTED VIA PREVIOUS CALLS TO BUFR ARCHIVE LIBRARY SUBROUTINE
100C PKVS01. IF A REQUEST WAS MADE TO CHANGE THE BUFR EDITION NUMBER
101C TO 4, THEN ACTUALLY CONVERT THE MESSAGE AS WELL.
102
103 IF(ns01v.GT.0) THEN
104 DO i=1,ns01v
105 IF(cmnem(i).EQ.'BEN') THEN
106 IF(ivmnem(i).EQ.4) THEN
107
108C INSTALL SECTION 0 BYTE COUNT FOR USE BY SUBROUTINE CNVED4.
109
110 ibit = 32
111 CALL pkb(mbyt,24,mgwa,ibit)
112
113 CALL cnved4(mgwa,mxmsgld4,mgwb)
114
115C COMPUTE MBYT FOR THE NEW EDITION 4 MESSAGE.
116
117 mbyt = iupbs01(mgwb,'LENM')
118
119C COPY THE MGWB ARRAY BACK INTO MGWA.
120
121 DO ii = 1, nmwrd(mgwb)
122 mgwa(ii) = mgwb(ii)
123 ENDDO
124 ENDIF
125 ELSE
126
127C OVERWRITE THE REQUESTED VALUE.
128
129 CALL pkbs1(ivmnem(i),mgwa,cmnem(i))
130 ENDIF
131 ENDDO
132 ENDIF
133
134C "STANDARDIZE" THE MESSAGE IF REQUESTED VIA COMMON /MSGSTD/.
135C HOWEVER, WE DO NOT WANT TO DO THIS IF THE MESSAGE CONTAINS BUFR
136C TABLE (DX) INFORMATION, IN WHICH CASE IT IS ALREADY "STANDARD".
137
138 IF ( ( csmf.EQ.'Y' ) .AND. ( idxmsg(mgwa).NE.1 ) ) THEN
139
140C INSTALL SECTION 0 BYTE COUNT AND SECTION 5 '7777' INTO THE
141C ORIGINAL MESSAGE. THIS IS NECESSARY BECAUSE SUBROUTINE STNDRD
142C REQUIRES A COMPLETE AND WELL-FORMED BUFR MESSAGE AS ITS INPUT.
143
144 ibit = 32
145 CALL pkb(mbyt,24,mgwa,ibit)
146 ibit = (mbyt-4)*8
147 CALL pkc(sevn,4,mgwa,ibit)
148
149 CALL stndrd(lunit,mgwa,mxmsgld4,mgwb)
150
151C COMPUTE MBYT FOR THE NEW "STANDARDIZED" MESSAGE.
152
153 mbyt = iupbs01(mgwb,'LENM')
154
155C COPY THE MGWB ARRAY BACK INTO MGWA.
156
157 DO ii = 1, nmwrd(mgwb)
158 mgwa(ii) = mgwb(ii)
159 ENDDO
160 ENDIF
161
162C APPEND THE TANK RECEIPT TIME TO SECTION 1 IF REQUESTED VIA
163C COMMON /TNKRCP/, UNLESS THE MESSAGE CONTAINS BUFR TABLE (DX)
164C INFORMATION.
165
166 IF ( ( ctrt.EQ.'Y' ) .AND. ( idxmsg(mgwa).NE.1 ) ) THEN
167
168C INSTALL SECTION 0 BYTE COUNT FOR USE BY SUBROUTINE ATRCPT.
169
170 ibit = 32
171 CALL pkb(mbyt,24,mgwa,ibit)
172
173 CALL atrcpt(mgwa,mxmsgld4,mgwb)
174
175C COMPUTE MBYT FOR THE REVISED MESSAGE.
176
177 mbyt = iupbs01(mgwb,'LENM')
178
179C COPY THE MGWB ARRAY BACK INTO MGWA.
180
181 DO ii = 1, nmwrd(mgwb)
182 mgwa(ii) = mgwb(ii)
183 ENDDO
184 ENDIF
185
186C GET THE SECTION LENGTHS.
187
188 CALL getlens(mgwa,4,len0,len1,len2,len3,len4,l5)
189
190C DEPENDING ON THE EDITION NUMBER OF THE MESSAGE, WE NEED TO ENSURE
191C THAT EACH SECTION WITHIN THE MESSAGE HAS AN EVEN NUMBER OF BYTES.
192
193 IF(iupbs01(mgwa,'BEN').LT.4) THEN
194 IF(mod(len1,2).NE.0) GOTO 901
195 IF(mod(len2,2).NE.0) GOTO 902
196 IF(mod(len3,2).NE.0) GOTO 903
197 IF(mod(len4,2).NE.0) THEN
198
199C PAD SECTION 4 WITH AN ADDITIONAL BYTE
200C THAT IS ZEROED OUT.
201
202 iad4 = len0+len1+len2+len3
203 iad5 = iad4+len4
204 ibit = iad4*8
205 len4 = len4+1
206 CALL pkb(len4,24,mgwa,ibit)
207 ibit = iad5*8
208 CALL pkb(0,8,mgwa,ibit)
209 mbyt = mbyt+1
210 ENDIF
211 ENDIF
212
213C WRITE SECTION 0 BYTE COUNT AND SECTION 5
214C ----------------------------------------
215
216 ibit = 0
217 CALL pkc(bufr, 4,mgwa,ibit)
218 CALL pkb(mbyt,24,mgwa,ibit)
219
220 kbit = (mbyt-4)*8
221 CALL pkc(sevn, 4,mgwa,kbit)
222
223C ZERO OUT THE EXTRA BYTES WHICH WILL BE WRITTEN
224C ----------------------------------------------
225
226C I.E. SINCE THE BUFR MESSAGE IS STORED WITHIN THE INTEGER ARRAY
227C MGWA(*) (RATHER THAN WITHIN A CHARACTER ARRAY), WE NEED TO MAKE
228C SURE THAT THE "7777" IS FOLLOWED BY ZEROED-OUT BYTES UP TO THE
229C BOUNDARY OF THE LAST MACHINE WORD THAT WILL BE WRITTEN OUT.
230
231 CALL padmsg(mgwa,mxmsgld4,npbyt)
232
233C WRITE THE MESSAGE PLUS PADDING TO A WORD BOUNDARY IF NULL(LUN) = 0
234C ------------------------------------------------------------------
235
236 mwrd = nmwrd(mgwa)
237 CALL status(lunit,lun,il,im)
238 IF(null(lun).EQ.0) THEN
239 CALL blocks(mgwa,mwrd)
240 CALL cwrbufr(lun,mgwa,mwrd)
241 ENDIF
242
243 IF(iprt.GE.2) THEN
244 CALL errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
245 WRITE ( unit=errstr, fmt='(A,I4,A,I7)')
246 . 'BUFRLIB: MSGWRT: LUNIT =', lunit, ', BYTES =', mbyt+npbyt
247 CALL errwrt(errstr)
248 CALL errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
249 CALL errwrt(' ')
250 ENDIF
251
252C SAVE A MEMORY COPY OF THIS MESSAGE, UNLESS IT'S A DX MESSAGE
253C ------------------------------------------------------------
254
255 IF(idxmsg(mgwa).NE.1) THEN
256
257C STORE A COPY OF THIS MESSAGE WITHIN MODULE BUFRMG,
258C FOR POSSIBLE LATER RETRIEVAL DURING A FUTURE CALL TO
259C SUBROUTINE WRITSA.
260
261 msglen(lun) = mwrd
262 DO i=1,msglen(lun)
263 msgtxt(i,lun) = mgwa(i)
264 ENDDO
265 ENDIF
266
267C EXITS
268C -----
269
270 RETURN
271901 CALL bort
272 . ('BUFRLIB: MSGWRT - LENGTH OF SECTION 1 IS NOT A MULTIPLE OF 2')
273902 CALL bort
274 . ('BUFRLIB: MSGWRT - LENGTH OF SECTION 2 IS NOT A MULTIPLE OF 2')
275903 CALL bort
276 . ('BUFRLIB: MSGWRT - LENGTH OF SECTION 3 IS NOT A MULTIPLE OF 2')
277 END
subroutine atrcpt(MSGIN, LMSGOT, MSGOT)
This subroutine reads an input message and outputs an equivalent BUFR message with a tank receipt tim...
Definition: atrcpt.f:35
subroutine blocks(MBAY, MWRD)
This subroutine encapsulates a BUFR message with IEEE Fortran control words as specified via the most...
Definition: blocks.f:46
subroutine bort(STR)
This subroutine calls subroutine errwrt() to log an error message, then calls subroutine bort_exit() ...
Definition: bort.f:23
subroutine cnved4(MSGIN, LMSGOT, MSGOT)
This subroutine reads an input BUFR message encoded using BUFR edition 3 and outputs an equivalent BU...
Definition: cnved4.f:37
void cwrbufr(f77int *nfile, f77int *bufr, f77int *nwrd)
This subroutine writes a BUFR message into a file that was previously opened for writing.
Definition: cread.c:173
subroutine errwrt(STR)
This subroutine allows the user to specify a custom location for the logging of error and diagnostic ...
Definition: errwrt.f:42
subroutine getlens(MBAY, LL, LEN0, LEN1, LEN2, LEN3, LEN4, LEN5)
This subroutine reads the lengths of all of the individual sections of a given BUFR message,...
Definition: getlens.f:40
function idxmsg(MESG)
This function determines whether a given BUFR message contains DX BUFR tables information that was ge...
Definition: idxmsg.f:24
function iupbs01(MBAY, S01MNEM)
This function returns a specified value from within Section 0 or Section 1 of a BUFR message.
Definition: iupbs01.f:74
subroutine msgwrt(LUNIT, MESG, MGBYT)
This subroutine performs final checks and updates on a BUFR message before writing it to a specified ...
Definition: msgwrt.f:55
This module declares and initializes the MXMSGL variable.
Definition: modv_MXMSGL.f:13
integer mxmsgld4
The value of mxmsgl divided by 4.
Definition: modv_MXMSGL.f:23
function nmwrd(MBAY)
GIVEN AN INTEGER ARRAY CONTAINING SECTION ZERO FROM A BUFR MESSAGE, THIS FUNCTION DETERMINES A COUNT ...
Definition: nmwrd.f:28
subroutine padmsg(MESG, LMESG, NPBYT)
THIS SUBROUTINE PADS A BUFR MESSAGE WITH ZEROED-OUT BYTES FROM THE END OF THE MESSAGE UP TO THE NEXT ...
Definition: padmsg.f:29
subroutine pkb(NVAL, NBITS, IBAY, IBIT)
This subroutine encodes an integer value within a specified number of bits of an integer array,...
Definition: pkb.f:39
subroutine pkbs1(IVAL, MBAY, S1MNEM)
This subroutines writes a specified value into a specified location within Section 1 of a BUFR messag...
Definition: pkbs1.f:58
subroutine pkc(CHR, NCHR, IBAY, IBIT)
This subroutine encodes a character string within a specified number of bits of an integer array,...
Definition: pkc.f:41
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 stndrd(LUNIT, MSGIN, LMSGOT, MSGOT)
This subroutine performs the same function as subroutine stdmsg(), except that it operates on a BUFR ...
Definition: stndrd.f:37