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