NCEPLIBS-bufr  12.2.0
All Data Structures Namespaces Files Functions Variables Macros Pages
dxtable.F90
Go to the documentation of this file.
1 
5 
28 subroutine readdx(lunit,lun,lundx)
29 
30  use modv_vars, only: iprt
31 
32  implicit none
33 
34  integer, intent(in) :: lunit, lun, lundx
35  integer lud, ildx, imdx
36 
37  character*128 errstr
38 
39  ! Get the status of unit lundx
40 
41  call status(lundx,lud,ildx,imdx)
42 
43  ! Read a dictionary table from the indicated source
44 
45  if (lunit==lundx) then
46  ! Source is input BUFR file in lunit
47  if(iprt>=2) then
48  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
49  write ( unit=errstr, fmt='(A,A,I3,A)' ) 'BUFRLIB: READDX - READING BUFR DICTIONARY TABLE FROM ', &
50  'INPUT BUFR FILE IN UNIT ', lundx, ' INTO INTERNAL ARRAYS'
51  call errwrt(errstr)
52  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
53  call errwrt(' ')
54  endif
55  rewind lunit
56  call rdbfdx(lunit,lun)
57  elseif(ildx==-1) then
58  ! Source is input BUFR file in lundx; BUFR file in lunit may be input or output
59  if(iprt>=2) then
60  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
61  write ( unit=errstr, fmt='(A,A,I3,A,A,I3)' ) 'BUFRLIB: READDX - COPYING BUFR DCTY TBL FROM INTERNAL ', &
62  'ARRAYS ASSOC. W/ INPUT UNIT ', lundx, ' TO THOSE ASSOC. W/ UNIT ', lunit
63  call errwrt(errstr)
64  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
65  call errwrt(' ')
66  endif
67  call cpbfdx(lud,lun)
68  call makestab
69  elseif(ildx==1) then
70  ! Source is output BUFR file in lundx; BUFR file in lunit may be input or output
71  if(iprt>=2) then
72  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
73  write ( unit=errstr, fmt='(A,A,I3,A,A,I3)' ) 'BUFRLIB: READDX - COPYING BUFR DCTY TBL FROM INTERNAL ', &
74  'ARRAYS ASSOC. W/ OUTPUT UNIT ', lundx, ' TO THOSE ASSOC. W/ UNIT ', lunit
75  call errwrt(errstr)
76  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
77  call errwrt(' ')
78  endif
79  call cpbfdx(lud,lun)
80  call makestab
81  elseif(ildx==0) then
82  ! Source is user-supplied character table in lundx; BUFR file in lunit may be input or output
83  if(iprt>=2) then
84  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
85  write ( unit=errstr, fmt='(A,A,I3,A)' ) 'BUFRLIB: READDX - READING BUFR DICTIONARY TABLE FROM ', &
86  'USER-SUPPLIED TEXT FILE IN UNIT ', lundx, ' INTO INTERNAL ARRAYS'
87  call errwrt(errstr)
88  call errwrt('++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++')
89  call errwrt(' ')
90  endif
91  rewind lundx
92  call rdusdx(lundx,lun)
93  else
94  call bort('BUFRLIB: READDX - CANNOT DETERMINE SOURCE OF INPUT DICTIONARY TABLE')
95  endif
96 
97  return
98 end subroutine readdx
99 
120 subroutine rdbfdx(lunit,lun)
121 
122  use bufrlib
123 
124  use modv_vars, only: iprt
125 
126  use moda_mgwa
127 
128  implicit none
129 
130  integer, intent(in) :: lunit, lun
131  integer ict, ier, idxmsg, iupbs3
132 
133  character*128 errstr
134 
135  logical done
136 
137  call dxinit(lun,0)
138 
139  ict = 0
140  done = .false.
141 
142  ! Read a complete dictionary table from lunit, as a set of one or more DX dictionary messages.
143 
144  do while ( .not. done )
145  call rdmsgw ( lunit, mgwa, ier )
146  if ( ier == -1 ) then
147  ! Don't abort for an end-of-file condition, since it may be possible for a file to end with dictionary messages.
148  ! Instead, backspace the file pointer and let the calling routine diagnose the end-of-file condition and deal with
149  ! it as it sees fit.
150  call backbufr_c(lun)
151  done = .true.
152  else if ( ier == -2 ) then
153  call bort('BUFRLIB: RDBFDX - ERROR READING A BUFR DICTIONARY MESSAGE')
154  else if ( idxmsg(mgwa) /= 1 ) then
155  ! This is a non-DX dictionary message. Assume we've reached the end of the dictionary table, and backspace lunit
156  ! so that the next read (e.g. in the calling routine) will get this same message.
157  call backbufr_c(lun)
158  done = .true.
159  else if ( iupbs3(mgwa,'NSUB') == 0 ) then
160  ! This is a DX dictionary message, but it doesn't contain any actual dictionary information. Assume we've reached
161  ! the end of the dictionary table.
162  done = .true.
163  else
164  ! Store this message into module @ref moda_tababd.
165  ict = ict + 1
166  call stbfdx(lun,mgwa)
167  endif
168  enddo
169 
170  if ( iprt >= 2 ) then
171  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
172  write ( unit=errstr, fmt='(A,I3,A)' ) 'BUFRLIB: RDBFDX - STORED NEW DX TABLE CONSISTING OF (', ict, ') MESSAGES;'
173  call errwrt(errstr)
174  errstr = 'WILL APPLY THIS TABLE TO ALL SUBSEQUENT DATA IN FILE UNTIL NEXT DX TABLE IS FOUND'
175  call errwrt(errstr)
176  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
177  call errwrt(' ')
178  endif
179 
180  call makestab
181 
182  return
183 end subroutine rdbfdx
184 
196 subroutine rdusdx(lundx,lun)
197 
198  use moda_tababd
199 
200  implicit none
201 
202  integer, intent(in) :: lundx, lun
203  integer ios, iret, n, numbck, nemock, igetntbi
204 
205  character*128 bort_str1
206  character*156 bort_str2
207  character*80 card
208  character*8 nemo
209  character*6 numb, nmb2
210 
211  ! Initialize the dictionary table control word partition arrays with apriori Table B and D entries
212 
213  call dxinit(lun,1)
214  rewind lundx
215 
216  ! Read user cards until there are no more
217 
218  do while (.true.)
219 
220  read(lundx, '(A80)', iostat = ios) card
221  if (ios/=0) then
222  call makestab
223  return
224  endif
225 
226  if(card(1: 1)== '*') cycle ! comment line
227  if(card(3:10)=='--------') cycle ! separation line
228  if(card(3:10)==' ') cycle ! blank line
229  if(card(3:10)=='MNEMONIC') cycle ! header line
230  if(card(3:10)=='TABLE D') cycle ! header line
231  if(card(3:10)=='TABLE B') cycle ! header line
232 
233  if(card(12:12)=='|' .and. card(21:21)=='|') then
234 
235  ! Parse a descriptor definition card
236  nemo = card(3:10) ! nemo is the (up to) 8-character mnemonic
237  iret=nemock(nemo)
238  if(iret==-2) then
239  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
240  write(bort_str2,'(18X,"MNEMONIC ",A," IN USER DICTIONARY HAS INVALID CHARACTERS")') nemo
241  call bort2(bort_str1,bort_str2)
242  endif
243  numb = card(14:19) ! numb is the 6-character FXY value corresponding to nemo
244  nmb2 = numb
245  if(nmb2(1:1)=='A') nmb2(1:1) = '3'
246  iret=numbck(nmb2)
247  if(iret==-1) then
248  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
249  write(bort_str2,'(18X,"DESCRIPTOR NUMBER ",A," IN USER '// &
250  'DICTIONARY HAS AN INVALID FIRST CHARACTER (F VALUE) - MUST BE A, 0 OR 3")') numb
251  call bort2(bort_str1,bort_str2)
252  endif
253  if(iret==-2) then
254  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
255  write(bort_str2,'(18X,"DESCRIPTOR NUMBER ",A," IN USER '// &
256  'DICTIONARY HAS NON-NUMERIC VALUES IN CHARACTERS 2-6 (X AND Y VALUES)")') numb
257  call bort2(bort_str1,bort_str2)
258  endif
259  if(iret==-3) then
260  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
261  write(bort_str2,'(18X,"DESCRIPTOR NUMBER ",A," IN USER '// &
262  'DICTIONARY HAS INVALID NUMBER IN CHARACTERS 2-3 (X VALUE) - MUST BE BETWEEN 00 AND 63")') numb
263  call bort2(bort_str1,bort_str2)
264  endif
265  if(iret==-4) then
266  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
267  write(bort_str2,'(18X,"DESCRIPTOR NUMBER ",A," IN USER '// &
268  'DICTIONARY HAS INVALID NUMBER IN CHARACTERS 4-6 (Y VALUE) - MUST BE BETWEEN 000 AND 255")') numb
269  call bort2(bort_str1,bort_str2)
270  endif
271 
272  if(numb(1:1)=='A') then
273  ! Table A descriptor found
274  n = igetntbi( lun, 'A' )
275  call stntbia ( n, lun, numb, nemo, card(23:) )
276  if ( idna(n,lun,1) == 11 ) then
277  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
278  write(bort_str2,'(18X,"USER-DEFINED MESSAGE TYPE ""011"" IS RESERVED FOR DICTIONARY MESSAGES")')
279  call bort2(bort_str1,bort_str2)
280  endif
281  ! Replace "A" with "3" so Table D descriptor will be found in card as well (see below).
282  numb(1:1) = '3'
283  endif
284 
285  if(numb(1:1)=='0') then
286  ! Table B descriptor found
287  call stntbi ( igetntbi(lun,'B'), lun, numb, nemo, card(23:) )
288  cycle
289  endif
290 
291  if(numb(1:1)=='3') then
292  ! Table D descriptor found
293  call stntbi ( igetntbi(lun,'D'), lun, numb, nemo, card(23:) )
294  cycle
295  endif
296 
297  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
298  write(bort_str2,'(18X,"DESCRIPTOR NUMBER ",A," IN USER '// &
299  'DICTIONARY HAS AN INVALID FIRST CHARACTER (F VALUE) - MUST BE A, 0 OR 3")') numb
300  call bort2(bort_str1,bort_str2)
301 
302  endif
303 
304  if(card(12:12)=='|' .and. card(19:19)/='|') then
305  ! Parse a sequence definition card
306  call seqsdx(card,lun)
307  cycle
308  endif
309 
310  if(card(12:12)=='|' .and. card(19:19)=='|') then
311  ! Parse an element definition card
312  call elemdx(card,lun)
313  cycle
314  endif
315 
316  ! Can't figure out what kind of card it is
317  write(bort_str1,'("BUFRLIB: RDUSDX - CARD READ IN IS: ",A)') card
318  write(bort_str2,'(18X,"THIS CARD HAS A BAD FORMAT - IT IS NOT RECOGNIZED BY THIS SUBROUTINE")')
319  call bort2(bort_str1,bort_str2)
320  enddo
321 
322 end subroutine rdusdx
323 
332 subroutine seqsdx(card,lun)
333 
334  use modv_vars, only: reps, idnr
335 
336  implicit none
337 
338  integer, intent(in) :: lun
339  integer maxtgs, maxtag, ntag, idn, jdn, iseq, irep, i, j, n, itab, iret, ier, numr, nemock
340 
341  character*128 bort_str1, bort_str2
342  character*80 seqs
343  character*80, intent(in) :: card
344  character*12 atag, tags(250)
345  character*8 nemo, nema, nemb
346  character*6 adn30, clemon
347  character tab
348 
349  data maxtgs /250/
350  data maxtag /12/
351 
352  ! Find the sequence tag in Table D and parse the sequence string
353 
354  nemo = card( 3:10)
355  seqs = card(14:78)
356 
357  ! Note that an entry for this mnemonic should already exist within the internal BUFR Table D array tabd(*,LUN); this entry
358  ! should have been created by subroutine rdusdx() when the mnemonic and its associated FXY value and description were
359  ! initially defined within a card read from the "Descriptor Definition" section at the top of the user-supplied DX BUFR
360  ! table in character format. Now, we need to retrieve the positional index for that entry within tabd(*,lun) so that we
361  ! can access the entry and then add the decoded sequence information to it.
362 
363  call nemtab(lun,nemo,idn,tab,iseq)
364  if(tab/='D') then
365  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
366  write(bort_str2,'(18X,"MNEMONIC ",A," IS NOT A TABLE D ENTRY (UNDEFINED, TAB=",A,")")') nemo,tab
367  call bort2(bort_str1,bort_str2)
368  endif
369  call parstr(seqs,tags,maxtgs,ntag,' ',.true.)
370  if(ntag==0) then
371  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
372  write(bort_str2,'(18X,"TABLE D SEQUENCE (PARENT) MNEMONIC ",A," DOES NOT CONTAIN ANY CHILD MNEMONICS")') nemo
373  call bort2(bort_str1,bort_str2)
374  endif
375 
376  do n=1,ntag
377  atag = tags(n)
378  irep = 0
379 
380  ! Check for a replicator
381 
382  outer: do i=1,5
383  if(atag(1:1)==reps(i)) then
384  ! Note that reps(*), which contains all of the symbols used to denote all of the various replication schemes that
385  ! are possible within a user-supplied BUFR dictionary table in character format, was previously defined within
386  ! subroutine bfrini().
387  do j=2,maxtag
388  if(atag(j:j)==reps(i+5)) then
389  ! Note that subroutine strnum() will return numr = 0 if the string passed to it contains all blanks
390  ! (as *should* be the case whenever i = 2 '(' ')', 3 '{' '}', 4 '[' ']', or 5 '<' '>').
391  ! However, when i = 1 '"' '"', then subroutine strnum() will return numr = (the number of replications for
392  ! the mnemonic using F=1 "regular" (i.e. non-delayed) replication).
393  call strnum(atag(j+1:maxtag),numr,ier)
394  if(i==1 .and. numr<=0) then
395  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
396  write(bort_str2,'(9X,"TBL D MNEM. ",A," CONTAINS REG. REPL. '// &
397  'CHILD MNEM. ",A," W/ INVALID # OF REPLICATIONS (",I3,") AFTER 2ND QUOTE")') nemo,tags(n),numr
398  call bort2(bort_str1,bort_str2)
399  endif
400  if(i==1 .and. numr>255) then
401  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
402  write(bort_str2,'(18X,"TBL D MNEM. ",A," CONTAINS REG. REPL. '// &
403  'CHILD MNEM. ",A," W/ # OF REPLICATIONS (",I3,") > LIMIT OF 255")') nemo,tags(n),numr
404  call bort2(bort_str1,bort_str2)
405  endif
406  if(i/=1 .and. numr/=0) then
407  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
408  write(bort_str2,'(18X,"TBL D MNEM. ",A," CONTAINS DELAYED REPL. '// &
409  'CHILD MNEM. ",A," W/ # OF REPL. (",I3,") SPECIFIED - A NO-NO")') nemo,tags(n),numr
410  call bort2(bort_str1,bort_str2)
411  endif
412  atag = atag(2:j-1)
413  irep = i
414  exit outer
415  endif
416  enddo
417  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
418  write(bort_str2,'(18X,"TABLE D SEQUENCE (PARENT) MNEMONIC ",A,'// &
419  '" CONTAINS A BADLY FORMED CHILD MNEMONIC ",A)') nemo,tags(n)
420  call bort2(bort_str1,bort_str2)
421  endif
422  enddo outer
423 
424  ! Check for a valid tag
425 
426  iret=nemock(atag)
427  if(iret==-1) then
428  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
429  write(bort_str2,'(18X,"TABLE D (PARENT) MNEMONIC ",A," CONTAINS'// &
430  ' A CHILD MNEMONIC ",A," NOT BETWEEN 1 & 8 CHARACTERS")') nemo,tags(n)
431  call bort2(bort_str1,bort_str2)
432  endif
433  if(iret==-2) then
434  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
435  write(bort_str2,'(18X,"TABLE D (PARENT) MNEMONIC ",A," CONTAINS'// &
436  ' A CHILD MNEMONIC ",A," WITH INVALID CHARACTERS")') nemo,tags(n)
437  call bort2(bort_str1,bort_str2)
438  endif
439  call nemtab(lun,atag,idn,tab,iret)
440  if(iret>0) then
441  ! Note that the next code line checks that we are not trying to replicate a Table B mnemonic (which is currently not
442  ! allowed). The logic works because, for replicated mnemonics, irep = i = (the index within reps(*) of the symbol
443  ! associated with the type of replication in question (e.g. "{, "<", etc.))
444  if(tab=='B' .and. irep/=0) then
445  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
446  write(bort_str2,'(18X,"TABLE D (PARENT) MNEMONIC ",A," CONTAINS'// &
447  ' A REPLICATED CHILD TABLE B MNEMONIC ",A," - A NO-NO")') nemo,tags(n)
448  call bort2(bort_str1,bort_str2)
449  endif
450  if(atag(1:1)=='.') then
451  ! This mnemonic is a "following value" mnemonic (i.e. it relates to the mnemonic that immediately follows it within
452  ! the user-supplied character-format BUFR dictionary table sequence), so confirm that it contains, as a substring,
453  ! this mnemonic that immediately follows it.
454  if(n==ntag) then
455  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
456  write(bort_str2,'(18X,"TBL D (PARENT) MNEM. ",A," CONTAINS A '// &
457  '''FOLLOWING VALUE'' MNEMONIC WHICH IS LAST IN THE STRING")') nemo
458  call bort2(bort_str1,bort_str2)
459  endif
460  nemb = tags(n+1)(1:8)
461  call numtab(lun,idn,nema,tab,itab)
462  call nemtab(lun,nemb,jdn,tab,iret)
463  call rsvfvm(nema,nemb)
464  if(nema/=atag) then
465  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
466  write(bort_str2,'(18X,"TBL D (PARENT) MNEM. ",A," CONTAINS AN '// &
467  'INVALID ''FOLLOWING VALUE'' MNEMONIC ",A,"(SHOULD BE ",A,")")') nemo,tags(n),nema
468  call bort2(bort_str1,bort_str2)
469  endif
470  if(tab/='B') then
471  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
472  write(bort_str2,'(18X,"TBL D (PARENT) MNEM. ",A,", THE MNEM. ",'// &
473  'A," FOLLOWING A ''FOLLOWING VALUE'' MNEM. IS NOT A TBL B ENTRY")') nemo,nemb
474  call bort2(bort_str1,bort_str2)
475  endif
476  endif
477  else
478  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
479  write(bort_str2,'(18X,"TABLE D SEQUENCE (PARENT) MNEMONIC ",A,'// &
480  '" CONTAINS A CHILD MNEMONIC ",A," NOT FOUND IN ANY TABLE")') nemo,tags(n)
481  call bort2(bort_str1,bort_str2)
482  endif
483 
484  ! Write the descriptor string into the tabd array, but first look for a replication descriptor
485  if(irep>0) call pktdd(iseq,lun,idnr(irep)+numr,iret)
486  if(iret<0) then
487  clemon = adn30(idnr(irep)+numr,6)
488  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
489  write(bort_str2,'(9X,"TBL D (PARENT) MNEM. ",A," - BAD RETURN '// &
490  'FROM PKTDD TRYING TO STORE REPL. DESC. ",A,", SEE PREV. WARNING MSG")') nemo,clemon
491  call bort2(bort_str1,bort_str2)
492  endif
493  call pktdd(iseq,lun,idn,iret)
494  if(iret<0) then
495  write(bort_str1,'("BUFRLIB: SEQSDX - CARD READ IN IS: ",A)') card
496  write(bort_str2,'(9X,"TBL D (PARENT) MNEM. ",A," - BAD RETURN '// &
497  'FROM PKTDD TRYING TO STORE CHILD MNEM. ",A,", SEE PREV. WARNING MSG")') nemo,tags(n)
498  call bort2(bort_str1,bort_str2)
499  endif
500 
501  enddo
502 
503  return
504 end subroutine seqsdx
505 
515 subroutine elemdx(card,lun)
516 
517  use moda_tababd
518 
519  implicit none
520 
521  integer, intent(in) :: lun
522  integer idsn, iele, iret
523 
524  character*128 bort_str1, bort_str2
525  character*80, intent(in) :: card
526  character*24 unit
527  character*11 refr, refr_orig
528  character*8 nemo
529  character*4 scal, scal_orig
530  character*3 bitw, bitw_orig
531  character sign, tab
532 
533  ! Capture the various elements characteristics
534 
535  nemo = card( 3:10)
536  scal = card(14:17)
537  refr = card(21:31)
538  bitw = card(35:37)
539  unit = card(41:64)
540  ! Make sure the units are all capitalized
541  call capit(unit)
542 
543  ! Find the element tag in Table B. Note that an entry for this mnemonic should already exist within the internal
544  ! BUFR Table B array tabb(*,lun). We now need to retrieve the positional index for that entry within tabb(*,lun)
545  ! so that we can access the entry and then add the scale factor, reference value, bit width, and units to it.
546 
547  call nemtab(lun,nemo,idsn,tab,iele)
548  if(tab/='B') then
549  write(bort_str1,'("BUFRLIB: ELEMDX - CARD READ IN IS: ",A)') card
550  write(bort_str2,'(18X,"MNEMONIC ",A," IS NOT A TABLE B ENTRY (UNDEFINED, TAB=",A,")")') nemo,tab
551  call bort2(bort_str1,bort_str2)
552  endif
553 
554  ! Left justify and store characteristics
555 
556  unit = adjustl(unit)
557  if(unit==' ') then
558  write(bort_str1,'("BUFRLIB: ELEMDX - CARD READ IN IS: ",A)') card
559  write(bort_str2,'(18X,"UNITS FIELD IS EMPTY")')
560  call bort2(bort_str1,bort_str2)
561  endif
562  tabb(iele,lun)(71:94) = unit
563 
564  scal_orig=scal
565  call jstnum(scal,sign,iret)
566  if(iret/=0) then
567  write(bort_str1,'("BUFRLIB: ELEMDX - CARD READ IN IS: ",A)') card
568  write(bort_str2,'(18X,"PARSED SCALE VALUE (=",A,") IS NOT NUMERIC")') scal_orig
569  call bort2(bort_str1,bort_str2)
570  endif
571  tabb(iele,lun)(95:95) = sign
572  tabb(iele,lun)(96:98) = scal(1:3)
573 
574  refr_orig=refr
575  call jstnum(refr,sign,iret)
576  if(iret/=0) then
577  write(bort_str1,'("BUFRLIB: ELEMDX - CARD READ IN IS: ",A)') card
578  write(bort_str2,'(18X,"PARSED REFERENCE VALUE (=",A,") IS NOT NUMERIC")') refr_orig
579  call bort2(bort_str1,bort_str2)
580  endif
581  tabb(iele,lun)( 99: 99) = sign
582  tabb(iele,lun)(100:109) = refr(1:10)
583 
584  bitw_orig=bitw
585  call jstnum(bitw,sign,iret)
586  if(iret/=0 .or. sign=='-') then
587  write(bort_str1,'("BUFRLIB: ELEMDX - CARD READ IN IS: ",A)') card
588  write(bort_str2,'(18X,"PARSED BIT WIDTH VALUE (=",A,") IS NOT NUMERIC")') bitw_orig
589  call bort2(bort_str1,bort_str2)
590  endif
591  tabb(iele,lun)(110:112) = bitw
592 
593  return
594 end subroutine elemdx
595 
605 subroutine dxinit(lun,ioi)
606 
607  use modv_vars, only: idnr, fxy_fbit, fxy_sbyct, fxy_drf16, fxy_drf8, fxy_drf1
608 
609  use moda_tababd
610 
611  implicit none
612 
613  integer, intent(in) :: lun, ioi
614  integer ninib, ninid, n, i, iret, ifxy
615 
616  character*8 inib(6,5),inid(5)
617  character*6 adn30
618 
619  data inib / '------','BYTCNT ','BYTES ','+0','+0','16', &
620  '------','BITPAD ','NONE ','+0','+0','1 ', &
621  fxy_drf1,'DRF1BIT ','NUMERIC','+0','+0','1 ', &
622  fxy_drf8,'DRF8BIT ','NUMERIC','+0','+0','8 ', &
623  fxy_drf16,'DRF16BIT','NUMERIC','+0','+0','16'/
624  data ninib /5/
625 
626  data inid /' ', &
627  'DRP16BIT', &
628  'DRP8BIT ', &
629  'DRPSTAK ', &
630  'DRP1BIT '/
631  data ninid /5/
632 
633  ! Clear out a table partition
634 
635  ntba(lun) = 0
636  do i=1,ntba(0)
637  taba(i,lun) = ' '
638  mtab(i,lun) = 0
639  enddo
640 
641  ntbb(lun) = 0
642  tabb(1:ntbb(0),lun) = ' '
643 
644  ntbd(lun) = 0
645  do i=1,ntbd(0)
646  tabd(i,lun) = ' '
647  call pktdd(i,lun,0,iret)
648  enddo
649 
650  if(ioi==0) return
651 
652  ! Initialize table with apriori Table B and D entries
653 
654  inib(1,1) = fxy_sbyct
655  inib(1,2) = fxy_fbit
656 
657  do i=1,ninib
658  ntbb(lun) = ntbb(lun)+1
659  idnb(i,lun) = ifxy(inib(1,i))
660  tabb(i,lun)( 1: 6) = inib(1,i)(1:6)
661  tabb(i,lun)( 7: 70) = inib(2,i)
662  tabb(i,lun)( 71: 94) = inib(3,i)
663  tabb(i,lun)( 95: 98) = inib(4,i)(1:4)
664  tabb(i,lun)( 99:109) = inib(5,i)
665  tabb(i,lun)(110:112) = inib(6,i)(1:3)
666  enddo
667 
668  do i=2,ninid
669  n = ntbd(lun)+1
670  idnd(n,lun) = idnr(i)
671  tabd(n,lun)(1: 6) = adn30(idnr(i),6)
672  tabd(n,lun)(7:70) = inid(i)
673  call pktdd(n,lun,idnr(1),iret)
674  call pktdd(n,lun,idnr(i+5),iret)
675  ntbd(lun) = n
676  enddo
677 
678  return
679 end subroutine dxinit
680 
692 subroutine dxmini(mbay,mbyt,mb4,mba,mbb,mbd)
693 
694  use modv_vars, only: mxmsgld4, mtv, nby0, nby1, nby2, nby5, bmostr, idxv
695 
696  implicit none
697 
698  integer, intent(out) :: mbay(*), mbyt, mb4, mba, mbb, mbd
699  integer nxstr, ldxa, ldxb, ldxd, ld30, mtyp, msbt, mbit, ih, id, im, iy, i, nsub, idxs, ldxs, &
700  len3, nby4, iupm
701 
702  character*128 bort_str
703  character*56 dxstr
704 
705  common /dxtab/ nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
706 
707  msbt = idxv
708 
709  ! Initialize the message
710 
711  mbit = 0
712  mbay(1:mxmsgld4) = 0
713 
714  ! For DX table messages, the Section 1 date is simply zeroed out. Note that there is logic in function idxmsg()
715  ! which relies on this.
716  ih = 0
717  id = 0
718  im = 0
719  iy = 0
720 
721  mtyp = 11 ! DX table messages are always type 11, per WMO BUFR Table A
722  nsub = 1
723 
724  idxs = idxv+1
725  ldxs = nxstr(idxs)
726 
727  len3 = 7 + nxstr(idxs) + 1
728  nby4 = 7
729  mbyt = nby0+nby1+nby2+len3+nby4+nby5
730 
731  if(mod(len3,2)/=0) call bort ('BUFRLIB: DXMINI - LENGTH OF SECTION 3 IS NOT A MULTIPLE OF 2')
732 
733  ! Section 0
734 
735  call pkc(bmostr , 4 , mbay,mbit)
736  call pkb( mbyt , 24 , mbay,mbit)
737  call pkb( 3 , 8 , mbay,mbit)
738 
739  ! Section 1
740 
741  call pkb( nby1 , 24 , mbay,mbit)
742  call pkb( 0 , 8 , mbay,mbit)
743  call pkb( 3 , 8 , mbay,mbit)
744  call pkb( 7 , 8 , mbay,mbit)
745  call pkb( 0 , 8 , mbay,mbit)
746  call pkb( 0 , 8 , mbay,mbit)
747  call pkb( mtyp , 8 , mbay,mbit)
748  call pkb( msbt , 8 , mbay,mbit)
749  call pkb( mtv , 8 , mbay,mbit)
750  call pkb( idxv , 8 , mbay,mbit)
751  call pkb( iy , 8 , mbay,mbit)
752  call pkb( im , 8 , mbay,mbit)
753  call pkb( id , 8 , mbay,mbit)
754  call pkb( ih , 8 , mbay,mbit)
755  call pkb( 0 , 8 , mbay,mbit)
756  call pkb( 0 , 8 , mbay,mbit)
757 
758  ! Section 3
759 
760  call pkb( len3 , 24 , mbay,mbit)
761  call pkb( 0 , 8 , mbay,mbit)
762  call pkb( 1 , 16 , mbay,mbit)
763  call pkb( 2**7 , 8 , mbay,mbit)
764  do i=1,ldxs
765  call pkb(iupm(dxstr(idxs)(i:i),8),8,mbay,mbit)
766  enddo
767  call pkb( 0 , 8 , mbay,mbit)
768 
769  ! Section 4
770 
771  mb4 = mbit/8+1
772  call pkb( nby4 , 24 , mbay,mbit)
773  call pkb( 0 , 8 , mbay,mbit)
774  mba = mbit/8+1
775  call pkb( 0 , 8 , mbay,mbit)
776  mbb = mbit/8+1
777  call pkb( 0 , 8 , mbay,mbit)
778  mbd = mbit/8+1
779  call pkb( 0 , 8 , mbay,mbit)
780 
781  if(mbit/8+nby5/=mbyt) then
782  write(bort_str,'("BUFRLIB: DXMINI - NUMBER OF BYTES STORED FOR '// &
783  'A MESSAGE (",I6,") IS NOT THE SAME AS FIRST CALCULATED, MBYT (",I6)') mbit/8+nby5,mbyt
784  call bort(bort_str)
785  endif
786 
787  return
788 end subroutine dxmini
789 
801 subroutine writdx(lunit,lun,lundx)
802 
803  implicit none
804 
805  integer, intent(in) :: lunit, lun, lundx
806 
807  character*128 bort_str
808 
809  ! The table must be coming from an input file
810 
811  if(lunit==lundx) then
812  write(bort_str,'("BUFRLIB: WRITDX - FILES CONTAINING BUFR DATA '// &
813  'AND DICTIONARY TABLE CANNOT BE THE SAME (HERE BOTH SHARE FORTRAN UNIT NUMBER ",I3,")")') lunit
814  call bort(bort_str)
815  endif
816 
817  ! Must first call readdx() to generate internal dictionary table arrays, before calling wrdxtb()
818 
819  call readdx(lunit,lun,lundx)
820  call wrdxtb(lunit,lunit)
821 
822  return
823 end subroutine writdx
824 
839 recursive subroutine wrdxtb(lundx,lunot)
840 
841  use modv_vars, only: im8b, idxv
842 
843  use moda_tababd
844  use moda_mgwa
845  use moda_bitbuf, only: maxbyt
846 
847  implicit none
848 
849  integer, intent(in) :: lundx, lunot
850  integer nxstr, ldxa, ldxb, ldxd, ld30, my_lundx, my_lunot, ldx, lot, il, im, lda, ldb, ldd, l30, nseq, &
851  mbit, mbyt, mby4, mbya, mbyb, mbyd, i, j, jj, idn, lend, len0, len1, len2, l3, l4, l5, iupb, iupm
852 
853  common /dxtab/ nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
854 
855  character*56 dxstr
856  character*6 adn30
857 
858  logical msgfull
859 
860  ! Check for I8 integers
861 
862  if(im8b) then
863  im8b=.false.
864 
865  call x84(lundx,my_lundx,1)
866  call x84(lunot,my_lunot,1)
867  call wrdxtb(my_lundx,my_lunot)
868 
869  im8b=.true.
870  return
871  endif
872 
873  ! Check file statuses
874 
875  call status(lunot,lot,il,im)
876  if(il==0) call bort('BUFRLIB: WRDXTB - OUTPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR OUTPUT')
877  if(il<0) call bort('BUFRLIB: WRDXTB - OUTPUT BUFR FILE IS OPEN FOR INPUT, IT MUST BE OPEN FOR OUTPUT')
878 
879  call status(lundx,ldx,il,im)
880  if(il==0) call bort('BUFRLIB: WRDXTB - DX TABLE FILE IS CLOSED, IT MUST BE OPEN')
881 
882  ! If files are different, copy internal table information from lundx to lunot
883 
884  if(lundx/=lunot) call cpbfdx(ldx,lot)
885 
886  ! Generate and write out BUFR dictionary messages to lunot
887 
888  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
889 
890  lda = ldxa(idxv+1)
891  ldb = ldxb(idxv+1)
892  ldd = ldxd(idxv+1)
893  l30 = ld30(idxv+1)
894 
895  ! Table A information
896 
897  do i=1,ntba(lot)
898  if(msgfull(mbyt,lda,maxbyt).or.(iupb(mgwa,mbya,8)==255)) then
899  call msgwrt(lunot,mgwa,mbyt)
900  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
901  endif
902  mbit = 8*(mby4-1)
903  call pkb(iupb(mgwa,mby4,24)+lda,24,mgwa,mbit)
904  mbit = 8*(mbya-1)
905  call pkb(iupb(mgwa,mbya,8)+1,8,mgwa,mbit)
906  mbit = 8*(mbyb-1)
907  call pkc(taba(i,lot),lda,mgwa,mbit)
908  call pkb(0,8,mgwa,mbit)
909  call pkb(0,8,mgwa,mbit)
910  mbyt = mbyt+lda
911  mbyb = mbyb+lda
912  mbyd = mbyd+lda
913  enddo
914 
915  ! Table B information
916 
917  do i=1,ntbb(lot)
918  if(msgfull(mbyt,ldb,maxbyt).or.(iupb(mgwa,mbyb,8)==255)) then
919  call msgwrt(lunot,mgwa,mbyt)
920  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
921  endif
922  mbit = 8*(mby4-1)
923  call pkb(iupb(mgwa,mby4,24)+ldb,24,mgwa,mbit)
924  mbit = 8*(mbyb-1)
925  call pkb(iupb(mgwa,mbyb,8)+1,8,mgwa,mbit)
926  mbit = 8*(mbyd-1)
927  call pkc(tabb(i,lot),ldb,mgwa,mbit)
928  call pkb(0,8,mgwa,mbit)
929  mbyt = mbyt+ldb
930  mbyd = mbyd+ldb
931  enddo
932 
933  ! Table D information
934 
935  do i=1,ntbd(lot)
936  nseq = iupm(tabd(i,lot)(ldd+1:ldd+1),8)
937  lend = ldd+1 + l30*nseq
938  if(msgfull(mbyt,lend,maxbyt).or.(iupb(mgwa,mbyd,8)==255)) then
939  call msgwrt(lunot,mgwa,mbyt)
940  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
941  endif
942  mbit = 8*(mby4-1)
943  call pkb(iupb(mgwa,mby4,24)+lend,24,mgwa,mbit)
944  mbit = 8*(mbyd-1)
945  call pkb(iupb(mgwa,mbyd,8)+1,8,mgwa,mbit)
946  mbit = 8*(mbyt-4)
947  call pkc(tabd(i,lot),ldd,mgwa,mbit)
948  call pkb(nseq,8,mgwa,mbit)
949  do j=1,nseq
950  jj = ldd+2 + (j-1)*2
951  idn = iupm(tabd(i,lot)(jj:jj),16)
952  call pkc(adn30(idn,l30),l30,mgwa,mbit)
953  enddo
954  mbyt = mbyt+lend
955  enddo
956 
957  ! Write the unwritten (leftover) message.
958 
959  call msgwrt(lunot,mgwa,mbyt)
960 
961  ! Write out one additional (dummy) DX message containing zero subsets. This will serve as a delimiter for this set of
962  ! table messages within output unit lunot, just in case the next thing written to lunot ends up being another set of
963  ! table messages.
964 
965  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
966  call getlens(mgwa,2,len0,len1,len2,l3,l4,l5)
967  mbit = (len0+len1+len2+4)*8
968  call pkb(0,16,mgwa,mbit)
969  call msgwrt(lunot,mgwa,mbyt)
970 
971  return
972 end subroutine wrdxtb
973 
980 subroutine stbfdx(lun,mesg)
981 
982  use modv_vars, only: maxcd, idxv
983 
984  use moda_tababd
985 
986  implicit none
987 
988  integer, intent(in) :: lun, mesg(*)
989  integer nxstr, ldxa, ldxb, ldxd, ld30, ldxbd(10), ldxbe(10), ja, jb, idxs, i3, i, j, n, nd, ndd, idn, &
990  jbit, len0, len1, len2, len3, l4, l5, lda, ldb, ldd, ldbd, ldbe, l30, ia, la, ib, lb, id, ld, iret, &
991  ifxy, iupb, iupbs01, igetntbi, idn30
992 
993  character*128 bort_str
994  character*128 tabb1, tabb2
995  character*56 dxstr
996  character*55 cseq
997  character*50 dxcmp
998  character*24 unit
999  character*8 nemo
1000  character*6 numb, cidn
1001 
1002  common /dxtab/ nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
1003 
1004  data ldxbd /38, 70, 8*0/
1005  data ldxbe /42, 42, 8*0/
1006 
1007  ! Statement functions
1008  ja(i) = ia+1+lda*(i-1)
1009  jb(i) = ib+1+ldb*(i-1)
1010 
1011  ! Get some preliminary information from the message
1012 
1013  idxs = iupbs01(mesg,'MSBT')+1
1014  if(idxs>idxv+1) idxs = iupbs01(mesg,'MTVL')+1
1015  if(ldxa(idxs)==0 .or. ldxb(idxs)==0 .or. ldxd(idxs)==0) call bort('BUFRLIB: STBFDX - UNEXPECTED DICTIONARY '// &
1016  'MESSAGE SUBTYPE OR LOCAL VERSION NUMBER (E.G., L.V.N. HIGHER THAN KNOWN)')
1017 
1018  call getlens(mesg,3,len0,len1,len2,len3,l4,l5)
1019  i3 = len0+len1+len2
1020  dxcmp = ' '
1021  jbit = 8*(i3+7)
1022  call upc(dxcmp,nxstr(idxs),mesg,jbit,.false.)
1023  if(dxcmp/=dxstr(idxs)) call bort('BUFRLIB: STBFDX - UNEXPECTED DICTIONARY MESSAGE CONTENTS')
1024 
1025  ! Section 4 - read definitions for Tables A, B and D
1026 
1027  lda = ldxa(idxs)
1028  ldb = ldxb(idxs)
1029  ldd = ldxd(idxs)
1030  ldbd = ldxbd(idxs)
1031  ldbe = ldxbe(idxs)
1032  l30 = ld30(idxs)
1033 
1034  ia = i3+len3+5
1035  la = iupb(mesg,ia,8)
1036  ib = ja(la+1)
1037  lb = iupb(mesg,ib,8)
1038  id = jb(lb+1)
1039  ld = iupb(mesg,id,8)
1040 
1041  ! Table A
1042 
1043  do i=1,la
1044  n = igetntbi(lun,'A')
1045  jbit = 8*(ja(i)-1)
1046  call upc(taba(n,lun),lda,mesg,jbit,.true.)
1047  numb = ' '//taba(n,lun)(1:3)
1048  nemo = taba(n,lun)(4:11)
1049  cseq = taba(n,lun)(13:67)
1050  call stntbia(n,lun,numb,nemo,cseq)
1051  enddo
1052 
1053  ! Table B
1054 
1055  do i=1,lb
1056  n = igetntbi(lun,'B')
1057  jbit = 8*(jb(i)-1)
1058  call upc(tabb1,ldbd,mesg,jbit,.true.)
1059  jbit = 8*(jb(i)+ldbd-1)
1060  call upc(tabb2,ldbe,mesg,jbit,.true.)
1061  tabb(n,lun) = tabb1(1:ldxbd(idxv+1))//tabb2(1:ldxbe(idxv+1))
1062  numb = tabb(n,lun)(1:6)
1063  nemo = tabb(n,lun)(7:14)
1064  call nenubd(nemo,numb,lun)
1065  idnb(n,lun) = ifxy(numb)
1066  unit = tabb(n,lun)(71:94)
1067  call capit(unit)
1068  tabb(n,lun)(71:94) = unit
1069  ntbb(lun) = n
1070  enddo
1071 
1072  ! Table D
1073 
1074  do i=1,ld
1075  n = igetntbi(lun,'D')
1076  jbit = 8*id
1077  call upc(tabd(n,lun),ldd,mesg,jbit,.true.)
1078  numb = tabd(n,lun)(1:6)
1079  nemo = tabd(n,lun)(7:14)
1080  call nenubd(nemo,numb,lun)
1081  idnd(n,lun) = ifxy(numb)
1082  nd = iupb(mesg,id+ldd+1,8)
1083  if(nd>maxcd) then
1084  write(bort_str,'("BUFRLIB: STBFDX - NUMBER OF DESCRIPTORS IN '// &
1085  'TABLE D ENTRY ",A," IN BUFR TABLE (",I4,") EXCEEDS THE LIMIT (",I4,")")') nemo,nd,maxcd
1086  call bort(bort_str)
1087  endif
1088  do j=1,nd
1089  ndd = id+ldd+2 + (j-1)*l30
1090  jbit = 8*(ndd-1)
1091  call upc(cidn,l30,mesg,jbit,.true.)
1092  idn = idn30(cidn,l30)
1093  call pktdd(n,lun,idn,iret)
1094  if(iret<0) call bort('BUFRLIB: STBFDX - BAD RETURN FROM BUFRLIB ROUTINE PKTDD, SEE PREVIOUS WARNING MESSAGE')
1095  enddo
1096  id = id+ldd+1 + nd*l30
1097  if(iupb(mesg,id+1,8)==0) id = id+1
1098  ntbd(lun) = n
1099  enddo
1100 
1101  return
1102 end subroutine stbfdx
1103 
1113 integer function idxmsg( mesg ) result( iret )
1114 
1115  implicit none
1116 
1117  integer, intent(in) :: mesg(*)
1118  integer iupbs01
1119 
1120  ! Note that the following test relies upon logic within subroutine dxmini() which zeroes out the Section 1 date of
1121  ! all DX dictionary messages.
1122 
1123  if ( (iupbs01(mesg,'MTYP')==11) .and. &
1124  (iupbs01(mesg,'MNTH')==0) .and. (iupbs01(mesg,'DAYS')==0) .and. (iupbs01(mesg,'HOUR')==0) ) then
1125  iret = 1
1126  else
1127  iret = 0
1128  end if
1129 
1130  return
1131 end function idxmsg
1132 
1143 integer function igetntbi ( lun, ctb ) result(iret)
1144 
1145  use moda_tababd
1146 
1147  implicit none
1148 
1149  integer, intent(in) :: lun
1150  integer imax
1151 
1152  character, intent(in) :: ctb
1153  character*128 bort_str
1154 
1155  if ( ctb == 'A' ) then
1156  iret = ntba(lun) + 1
1157  imax = ntba(0)
1158  else if ( ctb == 'B' ) then
1159  iret = ntbb(lun) + 1
1160  imax = ntbb(0)
1161  else ! ctb == 'D'
1162  iret = ntbd(lun) + 1
1163  imax = ntbd(0)
1164  endif
1165  if ( iret > imax ) then
1166  write(bort_str,'("BUFRLIB: IGETNTBI - NUMBER OF INTERNAL TABLE",A1," ENTRIES EXCEEDS THE LIMIT (",I4,")")') ctb, imax
1167  call bort(bort_str)
1168  endif
1169 
1170  return
1171 end function igetntbi
1172 
1187 subroutine nemtbax(lun,nemo,mtyp,msbt,inod)
1188 
1189  use moda_tababd
1190 
1191  implicit none
1192 
1193  integer, intent(in) :: lun
1194  integer, intent(out) :: mtyp, msbt, inod
1195  integer i
1196 
1197  character*(*), intent(in) :: nemo
1198  character*128 bort_str
1199 
1200  inod = 0
1201 
1202  ! Look for nemo in Table A
1203 
1204  do i=1,ntba(lun)
1205  if(taba(i,lun)(4:11)==nemo) then
1206  mtyp = idna(i,lun,1)
1207  msbt = idna(i,lun,2)
1208  inod = mtab(i,lun)
1209  if(mtyp<0 .or. mtyp>255) then
1210  write(bort_str,'("BUFRLIB: NEMTBAX - INVALID MESSAGE TYPE (",I4,") RETURNED FOR MENMONIC ",A)') mtyp, nemo
1211  call bort(bort_str)
1212  endif
1213  if(msbt<0 .or. msbt>255) then
1214  write(bort_str,'("BUFRLIB: NEMTBAX - INVALID MESSAGE SUBTYPE (",I4,") RETURNED FOR MENMONIC ",A)') msbt, nemo
1215  call bort(bort_str)
1216  endif
1217  exit
1218  endif
1219  enddo
1220 
1221  return
1222 end subroutine nemtbax
1223 
1237 subroutine nemtba(lun,nemo,mtyp,msbt,inod)
1238 
1239  implicit none
1240 
1241  integer, intent(in) :: lun
1242  integer, intent(out) :: mtyp, msbt, inod
1243 
1244  character*(*), intent(in) :: nemo
1245  character*128 bort_str
1246 
1247  ! Look for nemo in Table A
1248 
1249  call nemtbax(lun,nemo,mtyp,msbt,inod)
1250  if(inod==0) then
1251  write(bort_str,'("BUFRLIB: NEMTBA - CAN''T FIND MNEMONIC ",A)') nemo
1252  call bort(bort_str)
1253  endif
1254 
1255  return
1256 end subroutine nemtba
1257 
1268 subroutine nemtbb(lun,itab,unit,iscl,iref,ibit)
1269 
1270  use moda_tababd
1271 
1272  implicit none
1273 
1274  integer, intent(in) :: lun, itab
1275  integer, intent(out) :: iscl, iref, ibit
1276  integer idn, ierns
1277 
1278  character*128 bort_str
1279  character*24, intent(out) :: unit
1280  character*8 nemo
1281 
1282  if(itab<=0 .or. itab>ntbb(lun)) then
1283  write(bort_str,'("BUFRLIB: NEMTBB - ITAB (",I7,") NOT FOUND IN TABLE B")') itab
1284  call bort(bort_str)
1285  endif
1286 
1287  ! Pull out Table B information
1288 
1289  idn = idnb(itab,lun)
1290  nemo = tabb(itab,lun)( 7:14)
1291  unit = tabb(itab,lun)(71:94)
1292  call strnum(tabb(itab,lun)( 95: 98),iscl,ierns)
1293  call strnum(tabb(itab,lun)( 99:109),iref,ierns)
1294  call strnum(tabb(itab,lun)(110:112),ibit,ierns)
1295 
1296  ! Check Table B contents
1297 
1298  if(unit(1:5)/='CCITT' .and. ibit>32) then
1299  write(bort_str,'("BUFRLIB: NEMTBB - BIT WIDTH FOR NON-CHARACTER TABLE B MNEMONIC ",A," (",I7,") IS > 32")') nemo,ibit
1300  call bort(bort_str)
1301  endif
1302  if(unit(1:5)=='CCITT' .and. mod(ibit,8)/=0) then
1303  write(bort_str,'("BUFRLIB: NEMTBB - BIT WIDTH FOR CHARACTER TABLE B MNEMONIC ",A," (",I7,") IS NOT A MULTIPLE OF 8")') &
1304  nemo,ibit
1305  call bort(bort_str)
1306  endif
1307 
1308  return
1309 end subroutine nemtbb
1310 
1336 subroutine nemtbd(lun,itab,nseq,nems,irps,knts)
1337 
1338  use modv_vars, only: maxcd
1339 
1340  use moda_tababd
1341 
1342  implicit none
1343 
1344  integer, intent(in) :: lun, itab
1345  integer, intent(out) :: nseq, irps(*), knts(*)
1346  integer i, j, ndsc, idsc, iret
1347 
1348  character*128 bort_str
1349  character*8, intent(out) :: nems(*)
1350  character*8 nemo, nemt, nemf
1351  character tab
1352 
1353  if(itab<=0 .or. itab>ntbd(lun)) then
1354  write(bort_str,'("BUFRLIB: NEMTBD - ITAB (",I7,") NOT FOUND IN TABLE D")') itab
1355  call bort(bort_str)
1356  endif
1357 
1358  ! Clear the return values
1359 
1360  nseq = 0
1361 
1362  do i=1,maxcd
1363  nems(i) = ' '
1364  irps(i) = 0
1365  knts(i) = 0
1366  enddo
1367 
1368  ! Parse the Table D entry
1369 
1370  nemo = tabd(itab,lun)(7:14)
1371  idsc = idnd(itab,lun)
1372  call uptdd(itab,lun,0,ndsc)
1373 
1374  ! Loop through each child mnemonic
1375 
1376  do j=1,ndsc
1377  if(nseq+1>maxcd) then
1378  write(bort_str,'("BUFRLIB: NEMTBD - THERE ARE MORE THAN '// &
1379  '(",I4,") DESCRIPTORS (THE LIMIT) IN TABLE D SEQUENCE MNEMONIC ",A)') maxcd, nemo
1380  call bort(bort_str)
1381  endif
1382  call uptdd(itab,lun,j,idsc)
1383  call numtab(lun,idsc,nemt,tab,iret)
1384  if(tab=='R') then
1385  if(iret<0) then
1386  ! Regular (i.e. non-delayed) replication
1387  irps(nseq+1) = 1
1388  knts(nseq+1) = abs(iret)
1389  elseif(iret>0) then
1390  ! Delayed replication
1391  irps(nseq+1) = iret
1392  endif
1393  elseif(tab=='F') then
1394  ! Replication factor
1395  irps(nseq+1) = iret
1396  elseif(tab=='D'.or.tab=='C') then
1397  nseq = nseq+1
1398  nems(nseq) = nemt
1399  elseif(tab=='B') then
1400  nseq = nseq+1
1401  if((nemt(1:1)=='.').and.(j<ndsc)) then
1402  ! This is a "following value" mnemonic
1403  call uptdd(itab,lun,j+1,idsc)
1404  call numtab(lun,idsc,nemf,tab,iret)
1405  call rsvfvm(nemt,nemf)
1406  endif
1407  nems(nseq) = nemt
1408  endif
1409  enddo
1410 
1411  return
1412 end subroutine nemtbd
1413 
1436 recursive subroutine nemdefs ( lunit, nemo, celem, cunit, iret )
1437 
1438  use modv_vars, only: im8b
1439 
1440  use moda_tababd
1441 
1442  implicit none
1443 
1444  integer, intent(in) :: lunit
1445  integer, intent(out) :: iret
1446  integer my_lunit, lun, il, im, idn, iloc, ls
1447 
1448  character*(*), intent(in) :: nemo
1449  character*(*), intent(out) :: celem, cunit
1450  character tab
1451 
1452  ! Check for I8 integers.
1453 
1454  if(im8b) then
1455  im8b=.false.
1456  call x84 ( lunit, my_lunit, 1 )
1457  call nemdefs ( my_lunit, nemo, celem, cunit, iret )
1458  call x48 ( iret, iret, 1 )
1459  im8b=.true.
1460  return
1461  endif
1462 
1463  iret = -1
1464 
1465  ! Get lun from lunit.
1466 
1467  call status( lunit, lun, il, im )
1468  if ( il == 0 ) return
1469 
1470  ! Find the requested mnemonic in the internal Table B arrays.
1471 
1472  call nemtab( lun, nemo, idn, tab, iloc )
1473  if ( ( iloc == 0 ) .or. ( tab /= 'B' ) ) return
1474 
1475  ! Get the element name and units of the requested mnemonic.
1476 
1477  celem = ' '
1478  ls = min(len(celem),55)
1479  celem(1:ls) = tabb(iloc,lun)(16:15+ls)
1480 
1481  cunit = ' '
1482  ls = min(len(cunit),24)
1483  cunit(1:ls) = tabb(iloc,lun)(71:70+ls)
1484 
1485  iret = 0
1486 
1487  return
1488 end subroutine nemdefs
1489 
1504 subroutine nenubd(nemo,numb,lun)
1505 
1506  use moda_tababd
1507 
1508  implicit none
1509 
1510  character, intent(in) :: nemo*8, numb*6
1511  character*128 bort_str
1512 
1513  integer, intent(in) :: lun
1514  integer n
1515 
1516  do n=1,ntbb(lun)
1517  if(numb==tabb(n,lun)(1:6)) then
1518  write(bort_str,'("BUFRLIB: NENUBD - TABLE B FXY VALUE (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') numb
1519  call bort(bort_str)
1520  endif
1521  if(nemo==tabb(n,lun)(7:14)) then
1522  write(bort_str,'("BUFRLIB: NENUBD - TABLE B MNEMONIC (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') nemo
1523  call bort(bort_str)
1524  endif
1525  enddo
1526 
1527  do n=1,ntbd(lun)
1528  if(numb==tabd(n,lun)(1:6)) then
1529  write(bort_str,'("BUFRLIB: NENUBD - TABLE D FXY VALUE (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') numb
1530  call bort(bort_str)
1531  endif
1532  if(nemo==tabd(n,lun)(7:14)) then
1533  write(bort_str,'("BUFRLIB: NENUBD - TABLE D MNEMONIC (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') nemo
1534  call bort(bort_str)
1535  endif
1536  enddo
1537 
1538  return
1539 end subroutine nenubd
1540 
1550 subroutine stntbia ( n, lun, numb, nemo, celsq )
1551 
1552  use moda_tababd
1553 
1554  implicit none
1555 
1556  integer, intent(in) :: n, lun
1557  integer i, mtyp, msbt
1558 
1559  character*(*), intent(in) :: numb, nemo, celsq
1560  character*128 bort_str
1561 
1562  ! Confirm that neither nemo nor numb has already been defined within the internal BUFR Table A for the given lun.
1563 
1564  do i=1,ntba(lun)
1565  if(numb(4:6)==taba(i,lun)(1:3)) then
1566  write(bort_str,'("BUFRLIB: STNTBIA - TABLE A FXY VALUE (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') numb
1567  call bort(bort_str)
1568  endif
1569  if(nemo(1:8)==taba(i,lun)(4:11)) then
1570  write(bort_str,'("BUFRLIB: STNTBIA - TABLE A MNEMONIC (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') nemo
1571  call bort(bort_str)
1572  endif
1573  enddo
1574 
1575  ! Store the values within the internal BUFR Table A.
1576 
1577  taba(n,lun)(1:3) = numb(4:6)
1578  taba(n,lun)(4:11) = nemo(1:8)
1579  taba(n,lun)(13:67) = celsq(1:55)
1580 
1581  ! Decode and store the message type and subtype.
1582 
1583  if ( verify( nemo(3:8), '1234567890' ) == 0 ) then
1584  ! Message type & subtype obtained directly from Table A mnemonic
1585  read ( nemo,'(2X,2I3)') mtyp, msbt
1586  idna(n,lun,1) = mtyp
1587  idna(n,lun,2) = msbt
1588  else
1589  ! Message type obtained from Y value of Table A seq. descriptor
1590  read ( numb(4:6),'(I3)') idna(n,lun,1)
1591  ! Message subtype hardwired to zero
1592  idna(n,lun,2) = 0
1593  endif
1594 
1595  ! Update the count of internal Table A entries.
1596 
1597  ntba(lun) = n
1598 
1599  return
1600 end subroutine stntbia
1601 
1611 subroutine stntbi ( n, lun, numb, nemo, celsq )
1612 
1613  use moda_tababd
1614 
1615  implicit none
1616 
1617  integer, intent(in) :: n, lun
1618  integer ifxy
1619 
1620  character*(*), intent(in) :: numb, nemo, celsq
1621 
1622  call nenubd ( nemo, numb, lun )
1623 
1624  if ( numb(1:1) == '0') then
1625  idnb(n,lun) = ifxy(numb)
1626  tabb(n,lun)(1:6) = numb(1:6)
1627  tabb(n,lun)(7:14) = nemo(1:8)
1628  tabb(n,lun)(16:70) = celsq(1:55)
1629  ntbb(lun) = n
1630  else ! numb(1:1) == '3'
1631  idnd(n,lun) = ifxy(numb)
1632  tabd(n,lun)(1:6) = numb(1:6)
1633  tabd(n,lun)(7:14) = nemo(1:8)
1634  tabd(n,lun)(16:70) = celsq(1:55)
1635  ntbd(lun) = n
1636  endif
1637 
1638  return
1639 end subroutine stntbi
1640 
1656 subroutine pktdd(id,lun,idn,iret)
1657 
1658  use modv_vars, only: maxcd, iprt, idxv
1659 
1660  use moda_tababd
1661 
1662  implicit none
1663 
1664  integer, intent(in) :: id, lun, idn
1665  integer, intent(out) :: iret
1666  integer nxstr, ldxa, ldxb, ldxd, ld30, ldd, nd, idm, iupm
1667 
1668  character*128 errstr
1669  character*56 dxstr
1670 
1671  common /dxtab/ nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
1672 
1673  ! ldd points to the byte within tabd(id,lun) which contains (in packed integer format) a count of the number of child
1674  ! mnemonics stored thus far for this parent mnemonic.
1675  ldd = ldxd(idxv+1)+1
1676 
1677  ! Zero the counter if idn is zero
1678  if(idn==0) then
1679  call ipkm(tabd(id,lun)(ldd:ldd),1,0)
1680  iret = 0
1681  return
1682  endif
1683 
1684  ! Update the stored descriptor count for this Table D entry. nd is the (unpacked) count of the number of child mnemonics
1685  ! stored thus far for this parent mnemonic.
1686  nd = iupm(tabd(id,lun)(ldd:ldd),8)
1687 
1688  if(nd<0 .or. nd==maxcd) then
1689  if(iprt>=0) then
1690  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1691  if(nd<0) then
1692  write ( unit=errstr, fmt='(A,I4,A)' ) 'BUFRLIB: PKTDD - BAD COUNTER VALUE (=', nd, ') - RETURN WITH IRET = -1'
1693  else
1694  write ( unit=errstr, fmt='(A,I4,A,A)' ) 'BUFRLIB: PKTDD - MAXIMUM NUMBER OF CHILD MNEMONICS (=', &
1695  maxcd, ') ALREADY STORED FOR THIS PARENT - RETURN WITH IRET = -1'
1696  endif
1697  call errwrt(errstr)
1698  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1699  call errwrt(' ')
1700  endif
1701  iret = -1
1702  return
1703  else
1704  nd = nd+1
1705  call ipkm(tabd(id,lun)(ldd:ldd),1,nd)
1706  iret = nd
1707  endif
1708 
1709  ! Pack and store the descriptor. idm points to the starting byte within tabd(id,lun) at which the idn value for this
1710  ! child mnemonic will be stored (as a packed integer of width = 2 bytes).
1711  idm = ldd+1 + (nd-1)*2
1712  call ipkm(tabd(id,lun)(idm:idm),2,idn)
1713 
1714  return
1715 end subroutine pktdd
1716 
1730 subroutine uptdd(id,lun,ient,iret)
1731 
1732  use modv_vars, only: idxv
1733 
1734  use moda_tababd
1735 
1736  implicit none
1737 
1738  integer, intent(in) :: id, lun, ient
1739  integer, intent(out) :: iret
1740  integer nxstr, ldxa, ldxb, ldxd, ld30, ldd, ndsc, idsc, iupm
1741 
1742  character*128 bort_str
1743  character*56 dxstr
1744 
1745  common /dxtab/ nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
1746 
1747  ! Check if ient is in bounds
1748 
1749  ldd = ldxd(idxv+1)+1
1750  ndsc = iupm(tabd(id,lun)(ldd:ldd),8)
1751  if(ient==0) then
1752  iret = ndsc
1753  return
1754  elseif(ient<0 .or. ient>ndsc) then
1755  write(bort_str,'("BUFRLIB: UPTDD - VALUE OF THIRD ARGUMENT IENT (INPUT) IS OUT OF RANGE (IENT =",I4,")")') ient
1756  call bort(bort_str)
1757  endif
1758 
1759  ! Return the descriptor indicated by ient
1760 
1761  idsc = ldd+1 + (ient-1)*2
1762  iret = iupm(tabd(id,lun)(idsc:idsc),16)
1763 
1764  return
1765 end subroutine uptdd
1766 
1786 subroutine rsvfvm(nem1,nem2)
1787 
1788  implicit none
1789 
1790  character*8, intent(inout) :: nem1
1791  character*8, intent(in) :: nem2
1792 
1793  integer i, j
1794 
1795  do i=1,len(nem1)
1796  if(i==1) then
1797  ! Skip the initial ".", and initialize J.
1798  j = 1
1799  else
1800  if(nem1(i:i)=='.') then
1801  nem1(i:i) = nem2(j:j)
1802  j = j+1
1803  endif
1804  endif
1805  enddo
1806 
1807  return
1808 end subroutine rsvfvm
subroutine bort(str)
Log an error message, then abort the application program.
Definition: borts.F90:15
subroutine bort2(str1, str2)
Log two error messages, then abort the application program.
Definition: borts.F90:39
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
recursive integer function iupm(cbay, nbits)
Decode an integer value from within a specified number of bits of a character string,...
Definition: cidecode.F90:265
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
recursive subroutine ipkm(cbay, nbyt, n)
Encode an integer value within a specified number of bytes of a character string, up to a maximum of ...
Definition: ciencode.F90:194
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 cpbfdx(lud, lun)
Copy all of the DX BUFR table information from one unit to another within internal memory.
Definition: copydata.F90:676
subroutine elemdx(card, lun)
Decode the scale factor, reference value, bit width and units (i.e., the "elements") from a Table B m...
Definition: dxtable.F90:516
subroutine nemtbb(lun, itab, unit, iscl, iref, ibit)
Get information about a Table B descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1269
subroutine dxmini(mbay, mbyt, mb4, mba, mbb, mbd)
Initialize a DX BUFR tables (dictionary) message, writing all the preliminary information into Sectio...
Definition: dxtable.F90:693
subroutine nemtba(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1238
subroutine rdusdx(lundx, lun)
Read and parse a file containing a user-supplied DX BUFR table in character format,...
Definition: dxtable.F90:197
subroutine rsvfvm(nem1, nem2)
Process a "following value" mnemonic.
Definition: dxtable.F90:1787
subroutine seqsdx(card, lun)
Decode the Table D sequence information from a mnemonic definition card that was previously read from...
Definition: dxtable.F90:333
recursive subroutine wrdxtb(lundx, lunot)
Generate one or more BUFR messages from the DX BUFR tables information associated with a given BUFR f...
Definition: dxtable.F90:840
subroutine nemtbax(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1188
subroutine nemtbd(lun, itab, nseq, nems, irps, knts)
Get information about a Table D descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1337
subroutine stntbi(n, lun, numb, nemo, celsq)
Store a new entry within internal BUFR Table B or D.
Definition: dxtable.F90:1612
subroutine pktdd(id, lun, idn, iret)
Store information about a child mnemonic within the internal BUFR Table D.
Definition: dxtable.F90:1657
subroutine stntbia(n, lun, numb, nemo, celsq)
Store a new entry within internal BUFR Table A.
Definition: dxtable.F90:1551
subroutine stbfdx(lun, mesg)
Copy a DX BUFR tables message into the internal memory arrays in module moda_tababd.
Definition: dxtable.F90:981
subroutine writdx(lunit, lun, lundx)
Write DX BUFR table (dictionary) messages to the beginning of an output BUFR file in lunit.
Definition: dxtable.F90:802
recursive subroutine nemdefs(lunit, nemo, celem, cunit, iret)
Get the element name and units associated with a Table B descriptor.
Definition: dxtable.F90:1437
integer function igetntbi(lun, ctb)
Get the next available index for storing an entry within a specified internal DX BUFR table.
Definition: dxtable.F90:1144
subroutine readdx(lunit, lun, lundx)
Initialize modules moda_tababd and moda_msgcwd with DX BUFR (dictionary) tables.
Definition: dxtable.F90:29
subroutine dxinit(lun, ioi)
Clear out the internal arrays (in module moda_tababd) holding the DX BUFR table, then optionally init...
Definition: dxtable.F90:606
subroutine nenubd(nemo, numb, lun)
Confirm that a mnemonic and FXY value haven't already been defined.
Definition: dxtable.F90:1505
integer function idxmsg(mesg)
Check whether a BUFR message contains DX BUFR tables information that was generated by the NCEPLIBS-b...
Definition: dxtable.F90:1114
subroutine uptdd(id, lun, ient, iret)
Get the WMO bit-wise representation of the FXY value corresponding to a child mnemonic in a Table D s...
Definition: dxtable.F90:1731
subroutine rdbfdx(lunit, lun)
Beginning at the current file pointer location within lunit, read a complete DX BUFR table into inter...
Definition: dxtable.F90:121
subroutine errwrt(str)
Specify a custom location for the logging of error and diagnostic messages generated by the NCEPLIBS-...
Definition: errwrt.F90:32
subroutine nemtab(lun, nemo, idn, tab, iret)
Get information about a descriptor, based on a mnemonic.
Definition: fxy.F90:434
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
subroutine jstnum(str, sign, iret)
Left-justify a character string containing an encoded integer, by removing all leading blanks and any...
Definition: misc.F90:282
recursive subroutine strnum(str, num, iret)
Decode an integer from a character string.
Definition: misc.F90:156
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 arrays and variables used to store BUFR messages internally for multiple file IDs.
integer maxbyt
Maximum length of an output BUFR message.
Declare an array used by various subroutines and functions to hold a temporary working copy of a BUFR...
integer, dimension(:), allocatable mgwa
Temporary working copy of BUFR message.
Declare arrays and variables used to store DX BUFR tables internally for multiple file IDs.
integer, dimension(:), allocatable ntba
Number of Table A entries for each file ID (up to a maximum of maxtba, whose value is stored in array...
character *600, dimension(:,:), allocatable tabd
Table D entries for each file ID.
character *128, dimension(:,:), allocatable taba
Table A entries for each file ID.
integer, dimension(:,:), allocatable mtab
Entries within jump/link table corresponding to taba.
integer, dimension(:,:,:), allocatable idna
Message types (in array element 1) and subtypes (in array element 2) corresponding to taba.
integer, dimension(:), allocatable ntbd
Number of Table D entries for each file ID (up to a maximum of maxtbd, whose value is stored in array...
integer, dimension(:), allocatable ntbb
Number of Table B entries for each file ID (up to a maximum of maxtbb, whose value is stored in array...
integer, dimension(:,:), allocatable idnd
WMO bit-wise representations of the FXY values corresponding to tabd.
integer, dimension(:,:), allocatable idnb
WMO bit-wise representations of the FXY values corresponding to tabb.
character *128, dimension(:,:), allocatable tabb
Table B entries for each file ID.
recursive subroutine status(lunit, lun, il, im)
Check whether a specified Fortran logical unit number is currently connected to the NCEPLIBS-bufr sof...
logical function msgfull(msiz, itoadd, mxsiz)
Check whether the current data subset in the internal arrays will fit within the current BUFR message...
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.
subroutine rdmsgw(lunit, mesg, iret)
Read the next BUFR message from logical unit lunit as an array of integer words.
subroutine msgwrt(lunit, mesg, mgbyt)
Perform final checks and updates on a BUFR message before writing it to a specified Fortran logical u...
recursive integer function iupbs01(mbay, s01mnem)
Read a specified value from within Section 0 or Section 1 of a BUFR message.
Definition: s013vals.F90:247
subroutine parstr(str, tags, mtag, ntag, sep, limit80)
Parse a string containing one or more substrings into an array of substrings.
Definition: strings.F90:473
subroutine x48(iin4, iout8, nval)
Encode one or more 4-byte integer values as 8-byte integer values.
Definition: x4884.F90:18
subroutine x84(iin8, iout4, nval)
Encode one or more 8-byte integer values as 4-byte integer values.
Definition: x4884.F90:65