NCEPLIBS-bufr  12.3.0
standard.F90
Go to the documentation of this file.
1 
5 
35 recursive subroutine stdmsg(cf)
36 
37  use bufrlib
38 
39  use moda_msgstd
40 
41  implicit none
42 
43  integer bort_target_set
44 
45  character, intent(in) :: cf
46  character*128 bort_str
47  character my_cf
48 
49  ! If we're catching bort errors, set a target return location if one doesn't already exist.
50 
51  if (bort_target_set() == 1) then
52  call catch_bort_stdmsg_c(cf)
54  return
55  endif
56 
57  my_cf = cf
58  call capit(my_cf)
59  if(my_cf /= 'Y' .and. my_cf /= 'N') then
60  write(bort_str,'("BUFRLIB: STDMSG - INPUT ARGUMENT IS ",A1,", IT MUST BE EITHER Y, y, N OR n")') cf
61  call bort(bort_str)
62  endif
63  csmf = my_cf
64 
65  return
66 end subroutine stdmsg
67 
86 recursive subroutine stndrd(lunit,msgin,lmsgot,msgot)
87 
88  use bufrlib
89 
90  use modv_vars, only: im8b, nbytw, nby5, bmcstr
91 
92  use moda_s3list
93 
94  implicit none
95 
96  integer, intent(in) :: msgin(*), lunit, lmsgot
97  integer, intent(out) :: msgot(*)
98  integer my_lunit, my_lmsgot, lun, il, im, len0, len1, len2, len3, len4, len5
99  integer iad3, iad4, lenn, lenm, iupbs01, iupbs3, iupb, mxbyto, lbyto, ii, isub, itab, mtyp, msbt, inod
100  integer istdesc, ncd, iben, ibit, jbit, kbit, mbit, nad4, lsub, nsub, islen, kval, nval, i, k, l, n, bort_target_set
101 
102  character*128 bort_str
103  character*8 subset
104  character*4 s5str
105  character*1 tab
106  character*(*), parameter :: bort_arrayoverflow = &
107  'BUFRLIB: STNDRD - OVERFLOW OF OUTPUT (STANDARD) MESSAGE ARRAY; TRY A LARGER DIMENSION FOR THIS ARRAY'
108 
109  logical found
110 
111  ! Check for I8 integers.
112 
113  if(im8b) then
114  im8b=.false.
115  call x84(lunit,my_lunit,1)
116  call x84(lmsgot,my_lmsgot,1)
117  call stndrd(my_lunit,msgin,my_lmsgot*2,msgot)
118  im8b=.true.
119  return
120  endif
121 
122  ! If we're catching bort errors, set a target return location if one doesn't already exist.
123 
124  if (bort_target_set() == 1) then
125  call catch_bort_stndrd_c(lunit,msgin,lmsgot,msgot)
126  call bort_target_unset
127  return
128  endif
129 
130  ! lunit must point to an open BUFR file.
131 
132  call status(lunit,lun,il,im)
133  if(il==0) call bort('BUFRLIB: STNDRD - BUFR FILE IS CLOSED, IT MUST BE OPEN')
134 
135  ! Identify the section lengths and addresses in msgin.
136 
137  call getlens(msgin,5,len0,len1,len2,len3,len4,len5)
138 
139  iad3 = len0+len1+len2
140  iad4 = iad3+len3
141 
142  lenn = len0+len1+len2+len3+len4+len5
143 
144  lenm = iupbs01(msgin,'LENM')
145 
146  if(lenn/=lenm) then
147  write(bort_str,'("BUFRLIB: STNDRD - INPUT MESSAGE LENGTH FROM SECTION 0",I6," DOES NOT EQUAL SUM OF ALL INDIVIDUAL '// &
148  'SECTION LENGTHS (",I6,")")') lenm,lenn
149  call bort(bort_str)
150  endif
151 
152  mbit = (lenn-4)*8
153  call upc(s5str,nby5,msgin,mbit,.true.)
154  if(s5str/=bmcstr) then
155  write(bort_str,'("BUFRLIB: STNDRD - INPUT MESSAGE DOES NOT END WITH ""7777"" (ENDS WITH ",A)') s5str
156  call bort(bort_str)
157  endif
158 
159  ! Copy Sections 0 through part of Section 3 into msgot.
160 
161  mxbyto = (lmsgot*nbytw) - 8
162 
163  lbyto = iad3+7
164  if(lbyto>mxbyto) call bort(bort_arrayoverflow)
165  call mvb(msgin,1,msgot,1,lbyto)
166 
167  ! Rewrite new Section 3 in a standard form. First, locate the top-level Table A descriptor.
168 
169  found = .false.
170  ii = 10
171  do while ((.not.found).and.(ii>=8))
172  isub = iupb(msgin,iad3+ii,16)
173  call numtab(lun,isub,subset,tab,itab)
174  if((itab/=0).and.(tab=='D')) then
175  call nemtbax(lun,subset,mtyp,msbt,inod)
176  if(inod/=0) found = .true.
177  endif
178  ii = ii - 2
179  enddo
180  if(.not.found) call bort('BUFRLIB: STNDRD - TABLE A SUBSET DESCRIPTOR NOT FOUND')
181 
182  if (istdesc(isub)==0) then
183  ! isub is a non-standard Table A descriptor and needs to be expanded into an equivalent standard sequence
184  call restd_c(lun,isub,ncd,ids3)
185  else
186  ! isub is already a standard descriptor, so just copy it "as is" into the new Section 3 (i.e. no expansion is necessary)
187  ncd = 1
188  ids3(ncd) = isub
189  endif
190 
191  ! Use the edition number to determine the length of the new Section 3.
192 
193  len3 = 7+(ncd*2)
194  iben = iupbs01(msgin,'BEN')
195  if(iben<4) then
196  len3 = len3+1
197  endif
198  lbyto = lbyto + len3 - 7
199  if(lbyto>mxbyto) call bort(bort_arrayoverflow)
200 
201  ! Store the descriptors into the new Section 3.
202 
203  ibit = (iad3+7)*8
204  do n=1,ncd
205  call pkb(ids3(n),16,msgot,ibit)
206  enddo
207 
208  ! Depending on the edition number, pad out the new Section 3 with an additional zeroed-out byte to ensure an even byte count.
209 
210  if(iben<4) then
211  call pkb(0,8,msgot,ibit)
212  endif
213 
214  ! Store the length of the new Section 3.
215 
216  ibit = iad3*8
217  call pkb(len3,24,msgot,ibit)
218 
219  ! Now the tricky part - new Section 4.
220 
221  if(iupbs3(msgin,'ICMP')==1) then
222 
223  ! The data in Section 4 is compressed and is therefore already standardized, so copy it "as is" into the new Section 4.
224 
225  if((lbyto+len4+4)>mxbyto) call bort(bort_arrayoverflow)
226 
227  call mvb(msgin,iad4+1,msgot,lbyto+1,len4)
228  jbit = (lbyto+len4)*8
229 
230  else
231 
232  nad4 = iad3+len3
233 
234  ibit = (iad4+4)*8
235  jbit = (nad4+4)*8
236 
237  lbyto = lbyto + 4
238 
239  ! Copy the subsets, minus the byte counters and bit pads, into the new Section 4.
240 
241  nsub = iupbs3(msgin,'NSUB')
242 
243  subset_copy: do i=1,nsub
244  call upb(lsub,16,msgin,ibit)
245  if(nsub>1) then
246  ! Use the byte counter to copy this subset.
247  islen = lsub-2
248  else
249  ! This is the only subset in the message, and it could possibly be an overlarge (> 65530 bytes) subset, in
250  ! which case we can't rely on the value stored in the byte counter. Either way, we don't really need it.
251  islen = iad4+len4-(ibit/8)
252  endif
253  do l=1,islen
254  call upb(nval,8,msgin,ibit)
255  lbyto = lbyto + 1
256  if(lbyto>mxbyto) call bort(bort_arrayoverflow)
257  call pkb(nval,8,msgot,jbit)
258  enddo
259  do k=1,8
260  kbit = ibit-k-8
261  call upb(kval,8,msgin,kbit)
262  if(kval==k) then
263  jbit = jbit-k-8
264  cycle subset_copy
265  endif
266  enddo
267  call bort('BUFRLIB: STNDRD - BIT MISMATCH COPYING SECTION 4 FROM INPUT TO OUTPUT (STANDARD) MESSAGE')
268  enddo subset_copy
269 
270  ! From this point on, we will need (at most) 6 more bytes of space within msgot in order to be able to store the entire
271  ! standardized message (i.e. we will need (at most) 2 more zeroed-out bytes in Section 4, plus the 4 bytes '7777' in
272  ! Section 5), so do a final msgot overflow check now.
273 
274  if(lbyto+6>mxbyto) call bort(bort_arrayoverflow)
275 
276  ! Pad the new Section 4 with zeroes up to the next whole byte boundary.
277 
278  do while(.not.(mod(jbit,8)==0))
279  call pkb(0,1,msgot,jbit)
280  enddo
281 
282  ! Depending on the edition number, we may need to further pad the new Section 4 with an additional zeroed-out byte in
283  ! order to ensure that the padding is up to an even byte boundary.
284 
285  if( (iben<4) .and. (mod(jbit/8,2)/=0) ) then
286  call pkb(0,8,msgot,jbit)
287  endif
288 
289  ibit = nad4*8
290  len4 = jbit/8 - nad4
291  call pkb(len4,24,msgot,ibit)
292  call pkb(0,8,msgot,ibit)
293  endif
294 
295  ! Finish the new message with an updated section 0 byte count.
296 
297  ibit = 32
298  lenn = len0+len1+len2+len3+len4+len5
299  call pkb(lenn,24,msgot,ibit)
300 
301  call pkc(bmcstr,nby5,msgot,jbit)
302 
303  return
304 end subroutine stndrd
305 
316 integer function istdesc( idn ) result( iret )
317 
318  implicit none
319 
320  integer, intent(in) :: idn
321  integer if, ix, iy, iokoper
322 
323  character*6 adsc, adn30
324 
325  adsc = adn30( idn, 6 )
326 
327  read(adsc,'(I1,I2,I3)') if,ix,iy
328  if ( if == 1 ) then
329  ! adsc is a replication descriptor and therefore standard by default
330  iret = 1
331  else if ( if == 2 ) then
332  ! adsc is an operator descriptor
333  iret = iokoper( adsc )
334  else if ( ( ix < 48 ) .and. ( iy < 192 ) ) then
335  iret = 1
336  else
337  iret = 0
338  end if
339 
340  return
341 end function istdesc
recursive subroutine bort(str)
Log an error message, then either return to or abort the application program.
Definition: borts.F90:15
subroutine bort_target_unset
Clear any existing bort target.
Definition: borts.F90:180
integer function bort_target_set()
Sets a new bort target, if bort catching is enabled and such a target doesn't already exist.
Definition: borts.F90:160
subroutine upb(nval, nbits, ibay, ibit)
Decode an integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:202
recursive integer function iupb(mbay, nbyt, nbit)
Decode an integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:226
subroutine upc(chr, nchr, ibay, ibit, cnvnull)
Decode a character string from within a specified number of bytes of an integer array,...
Definition: cidecode.F90:26
subroutine pkc(chr, nchr, ibay, ibit)
Encode a character string within a specified number of bytes of an integer array, starting at the bit...
Definition: ciencode.F90:25
subroutine pkb(nval, nbits, ibay, ibit)
Encode an integer value within a specified number of bits of an integer array, starting at the bit im...
Definition: ciencode.F90:140
subroutine mvb(ib1, nb1, ib2, nb2, nbm)
Copy a specified number of bytes from one packed binary array to another.
Definition: copydata.F90:767
subroutine nemtbax(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1194
subroutine numtab(lun, idn, nemo, tab, iret)
Get information about a descriptor, based on the WMO bit-wise representation of an FXY value.
Definition: fxy.F90:359
character *(*) function adn30(idn, ldn)
Convert an FXY value from its WMO bit-wise representation to a character string of length 5 or 6.
Definition: fxy.F90:18
integer function iokoper(nemo)
Check whether a specified mnemonic is a Table C operator supported by the NCEPLIBS-bufr software.
Definition: misc.F90:486
subroutine capit(str)
Capitalize all of the alphabetic characters in a string.
Definition: misc.F90:334
Wrap C NCEPLIBS-bufr functions so they can be called from within the Fortran part of the library.
Definition: bufrlib.F90:11
Declare a variable used to indicate whether output BUFR messages should be standardized.
character csmf
Flag indicating whether BUFR output messages are to be standardized; this variable is initialized to ...
Declare arrays used by various subroutines and functions to hold a temporary working copy of a Sectio...
integer, dimension(:), allocatable ids3
Temporary working copy of Section 3 descriptor list in integer form.
recursive subroutine status(lunit, lun, il, im)
Check whether a specified Fortran logical unit number is currently connected to the NCEPLIBS-bufr sof...
recursive subroutine getlens(mbay, ll, len0, len1, len2, len3, len4, len5)
Read the section lengths of a BUFR message, up to a specified point in the message.
recursive integer function iupbs01(mbay, s01mnem)
Read a specified value from within Section 0 or Section 1 of a BUFR message.
Definition: s013vals.F90:245
recursive integer function iupbs3(mbay, s3mnem)
Read a specified value from within Section 3 of a BUFR message.
Definition: s013vals.F90:344
recursive subroutine stndrd(lunit, msgin, lmsgot, msgot)
Standardize a BUFR message.
Definition: standard.F90:87
recursive subroutine stdmsg(cf)
Specify whether BUFR messages output by future calls to message-writing subroutines and subset-writin...
Definition: standard.F90:36
integer function istdesc(idn)
Given the WMO bit-wise representation of an FXY value for a descriptor, check whether the descriptor ...
Definition: standard.F90:317
subroutine x84(iin8, iout4, nval)
Encode one or more 8-byte integer values as 4-byte integer values.
Definition: x4884.F90:65