NCEPLIBS-bufr  12.1.0
dxtable.F90
Go to the documentation of this file.
1 
5 
28 subroutine readdx(lunit,lun,lundx)
29 
30  implicit none
31 
32  integer, intent(in) :: lunit, lun, lundx
33  integer iprt, lud, ildx, imdx
34 
35  character*128 errstr
36 
37  common /quiet/ iprt
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 moda_mgwa
125 
126  implicit none
127 
128  integer, intent(in) :: lunit, lun
129  integer iprt, ict, ier, idxmsg, iupbs3
130 
131  character*128 errstr
132 
133  logical done
134 
135  common /quiet/ iprt
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
608 
609  use moda_tababd
610 
611  implicit none
612 
613  integer, intent(in) :: lun, ioi
614  integer ibct, ipd1, ipd2, ipd3, ipd4, ninib, ninid, n, i, iret, ifxy
615 
616  character*8 inib(6,5),inid(5)
617  character*6 adn30
618 
619  common /padesc/ ibct, ipd1, ipd2, ipd3, ipd4
620 
621  data inib /'------','BYTCNT ','BYTES ','+0','+0','16', &
622  '------','BITPAD ','NONE ','+0','+0','1 ', &
623  '031000','DRF1BIT ','NUMERIC','+0','+0','1 ', &
624  '031001','DRF8BIT ','NUMERIC','+0','+0','8 ', &
625  '031002','DRF16BIT','NUMERIC','+0','+0','16'/
626  data ninib /5/
627 
628  data inid /' ', &
629  'DRP16BIT', &
630  'DRP8BIT ', &
631  'DRPSTAK ', &
632  'DRP1BIT '/
633  data ninid /5/
634 
635  ! Clear out a table partition
636 
637  ntba(lun) = 0
638  do i=1,ntba(0)
639  taba(i,lun) = ' '
640  mtab(i,lun) = 0
641  enddo
642 
643  ntbb(lun) = 0
644  do i=1,ntbb(0)
645  tabb(i,lun) = ' '
646  enddo
647 
648  ntbd(lun) = 0
649  do i=1,ntbd(0)
650  tabd(i,lun) = ' '
651  call pktdd(i,lun,0,iret)
652  enddo
653 
654  if(ioi==0) return
655 
656  ! Initialize table with apriori Table B and D entries
657 
658  inib(1,1) = adn30(ibct,6)
659  inib(1,2) = adn30(ipd4,6)
660 
661  do i=1,ninib
662  ntbb(lun) = ntbb(lun)+1
663  idnb(i,lun) = ifxy(inib(1,i))
664  tabb(i,lun)( 1: 6) = inib(1,i)(1:6)
665  tabb(i,lun)( 7: 70) = inib(2,i)
666  tabb(i,lun)( 71: 94) = inib(3,i)
667  tabb(i,lun)( 95: 98) = inib(4,i)(1:4)
668  tabb(i,lun)( 99:109) = inib(5,i)
669  tabb(i,lun)(110:112) = inib(6,i)(1:3)
670  enddo
671 
672  do i=2,ninid
673  n = ntbd(lun)+1
674  idnd(n,lun) = idnr(i)
675  tabd(n,lun)(1: 6) = adn30(idnr(i),6)
676  tabd(n,lun)(7:70) = inid(i)
677  call pktdd(n,lun,idnr(1),iret)
678  call pktdd(n,lun,idnr(i+5),iret)
679  ntbd(lun) = n
680  enddo
681 
682  return
683 end subroutine dxinit
684 
696 subroutine dxmini(mbay,mbyt,mb4,mba,mbb,mbd)
697 
698  use modv_vars, only: mxmsgld4
699 
700  implicit none
701 
702  integer, intent(out) :: mbay(*), mbyt, mb4, mba, mbb, mbd
703  integer maxdx, idxv, nxstr, ldxa, ldxb, ldxd, ld30, mtyp, msbt, mbit, ih, id, im, iy, i, nsub, idxs, ldxs, &
704  nby0, nby1, nby2, nby3, nby4, nby5, iupm
705 
706  character*128 bort_str
707  character*56 dxstr
708 
709  common /dxtab/ maxdx, idxv, nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
710 
711  msbt = idxv
712 
713  ! Initialize the message
714 
715  mbit = 0
716  do i=1,mxmsgld4
717  mbay(i) = 0
718  enddo
719 
720  ! For DX table messages, the Section 1 date is simply zeroed out. Note that there is logic in function idxmsg()
721  ! which relies on this.
722  ih = 0
723  id = 0
724  im = 0
725  iy = 0
726 
727  mtyp = 11 ! DX table messages are always type 11, per WMO BUFR Table A
728  nsub = 1
729 
730  idxs = idxv+1
731  ldxs = nxstr(idxs)
732 
733  nby0 = 8
734  nby1 = 18
735  nby2 = 0
736  nby3 = 7 + nxstr(idxs) + 1
737  nby4 = 7
738  nby5 = 4
739  mbyt = nby0+nby1+nby2+nby3+nby4+nby5
740 
741  if(mod(nby3,2)/=0) call bort ('BUFRLIB: DXMINI - LENGTH OF SECTION 3 IS NOT A MULTIPLE OF 2')
742 
743  ! Section 0
744 
745  call pkc('BUFR' , 4 , mbay,mbit)
746  call pkb( mbyt , 24 , mbay,mbit)
747  call pkb( 3 , 8 , mbay,mbit)
748 
749  ! Section 1
750 
751  call pkb( nby1 , 24 , mbay,mbit)
752  call pkb( 0 , 8 , mbay,mbit)
753  call pkb( 3 , 8 , mbay,mbit)
754  call pkb( 7 , 8 , mbay,mbit)
755  call pkb( 0 , 8 , mbay,mbit)
756  call pkb( 0 , 8 , mbay,mbit)
757  call pkb( mtyp , 8 , mbay,mbit)
758  call pkb( msbt , 8 , mbay,mbit)
759  call pkb( 36 , 8 , mbay,mbit)
760  call pkb( idxv , 8 , mbay,mbit)
761  call pkb( iy , 8 , mbay,mbit)
762  call pkb( im , 8 , mbay,mbit)
763  call pkb( id , 8 , mbay,mbit)
764  call pkb( ih , 8 , mbay,mbit)
765  call pkb( 0 , 8 , mbay,mbit)
766  call pkb( 0 , 8 , mbay,mbit)
767 
768  ! Section 3
769 
770  call pkb( nby3 , 24 , mbay,mbit)
771  call pkb( 0 , 8 , mbay,mbit)
772  call pkb( 1 , 16 , mbay,mbit)
773  call pkb( 2**7 , 8 , mbay,mbit)
774  do i=1,ldxs
775  call pkb(iupm(dxstr(idxs)(i:i),8),8,mbay,mbit)
776  enddo
777  call pkb( 0 , 8 , mbay,mbit)
778 
779  ! Section 4
780 
781  mb4 = mbit/8+1
782  call pkb( nby4 , 24 , mbay,mbit)
783  call pkb( 0 , 8 , mbay,mbit)
784  mba = mbit/8+1
785  call pkb( 0 , 8 , mbay,mbit)
786  mbb = mbit/8+1
787  call pkb( 0 , 8 , mbay,mbit)
788  mbd = mbit/8+1
789  call pkb( 0 , 8 , mbay,mbit)
790 
791  if(mbit/8+nby5/=mbyt) then
792  write(bort_str,'("BUFRLIB: DXMINI - NUMBER OF BYTES STORED FOR '// &
793  'A MESSAGE (",I6,") IS NOT THE SAME AS FIRST CALCULATED, MBYT (",I6)') mbit/8+nby5,mbyt
794  call bort(bort_str)
795  endif
796 
797  return
798 end subroutine dxmini
799 
811 subroutine writdx(lunit,lun,lundx)
812 
813  implicit none
814 
815  integer, intent(in) :: lunit, lun, lundx
816 
817  character*128 bort_str
818 
819  ! The table must be coming from an input file
820 
821  if(lunit==lundx) then
822  write(bort_str,'("BUFRLIB: WRITDX - FILES CONTAINING BUFR DATA '// &
823  'AND DICTIONARY TABLE CANNOT BE THE SAME (HERE BOTH SHARE FORTRAN UNIT NUMBER ",I3,")")') lunit
824  call bort(bort_str)
825  endif
826 
827  ! Must first call readdx() to generate internal dictionary table arrays, before calling wrdxtb()
828 
829  call readdx(lunit,lun,lundx)
830  call wrdxtb(lunit,lunit)
831 
832  return
833 end subroutine writdx
834 
849 recursive subroutine wrdxtb(lundx,lunot)
850 
851  use modv_vars, only: im8b
852 
853  use moda_tababd
854  use moda_mgwa
855 
856  implicit none
857 
858  integer, intent(in) :: lundx, lunot
859  integer maxdx, idxv, nxstr, ldxa, ldxb, ldxd, ld30, my_lundx, my_lunot, ldx, lot, il, im, lda, ldb, ldd, l30, nseq, &
860  mbit, mbyt, mby4, mbya, mbyb, mbyd, i, j, jj, idn, lend, len0, len1, len2, l3, l4, l5, iupb, iupm
861 
862  common /dxtab/ maxdx, idxv, nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
863 
864  character*56 dxstr
865  character*6 adn30
866 
867  logical msgfull
868 
869  ! Check for I8 integers
870 
871  if(im8b) then
872  im8b=.false.
873 
874  call x84(lundx,my_lundx,1)
875  call x84(lunot,my_lunot,1)
876  call wrdxtb(my_lundx,my_lunot)
877 
878  im8b=.true.
879  return
880  endif
881 
882  ! Check file statuses
883 
884  call status(lunot,lot,il,im)
885  if(il==0) call bort('BUFRLIB: WRDXTB - OUTPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR OUTPUT')
886  if(il<0) call bort('BUFRLIB: WRDXTB - OUTPUT BUFR FILE IS OPEN FOR INPUT, IT MUST BE OPEN FOR OUTPUT')
887 
888  call status(lundx,ldx,il,im)
889  if(il==0) call bort('BUFRLIB: WRDXTB - DX TABLE FILE IS CLOSED, IT MUST BE OPEN')
890 
891  ! If files are different, copy internal table information from lundx to lunot
892 
893  if(lundx/=lunot) call cpbfdx(ldx,lot)
894 
895  ! Generate and write out BUFR dictionary messages to lunot
896 
897  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
898 
899  lda = ldxa(idxv+1)
900  ldb = ldxb(idxv+1)
901  ldd = ldxd(idxv+1)
902  l30 = ld30(idxv+1)
903 
904  ! Table A information
905 
906  do i=1,ntba(lot)
907  if(msgfull(mbyt,lda,maxdx).or.(iupb(mgwa,mbya,8)==255)) then
908  call msgwrt(lunot,mgwa,mbyt)
909  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
910  endif
911  mbit = 8*(mby4-1)
912  call pkb(iupb(mgwa,mby4,24)+lda,24,mgwa,mbit)
913  mbit = 8*(mbya-1)
914  call pkb(iupb(mgwa,mbya,8)+1,8,mgwa,mbit)
915  mbit = 8*(mbyb-1)
916  call pkc(taba(i,lot),lda,mgwa,mbit)
917  call pkb(0,8,mgwa,mbit)
918  call pkb(0,8,mgwa,mbit)
919  mbyt = mbyt+lda
920  mbyb = mbyb+lda
921  mbyd = mbyd+lda
922  enddo
923 
924  ! Table B information
925 
926  do i=1,ntbb(lot)
927  if(msgfull(mbyt,ldb,maxdx).or.(iupb(mgwa,mbyb,8)==255)) then
928  call msgwrt(lunot,mgwa,mbyt)
929  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
930  endif
931  mbit = 8*(mby4-1)
932  call pkb(iupb(mgwa,mby4,24)+ldb,24,mgwa,mbit)
933  mbit = 8*(mbyb-1)
934  call pkb(iupb(mgwa,mbyb,8)+1,8,mgwa,mbit)
935  mbit = 8*(mbyd-1)
936  call pkc(tabb(i,lot),ldb,mgwa,mbit)
937  call pkb(0,8,mgwa,mbit)
938  mbyt = mbyt+ldb
939  mbyd = mbyd+ldb
940  enddo
941 
942  ! Table D information
943 
944  do i=1,ntbd(lot)
945  nseq = iupm(tabd(i,lot)(ldd+1:ldd+1),8)
946  lend = ldd+1 + l30*nseq
947  if(msgfull(mbyt,lend,maxdx).or.(iupb(mgwa,mbyd,8)==255)) then
948  call msgwrt(lunot,mgwa,mbyt)
949  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
950  endif
951  mbit = 8*(mby4-1)
952  call pkb(iupb(mgwa,mby4,24)+lend,24,mgwa,mbit)
953  mbit = 8*(mbyd-1)
954  call pkb(iupb(mgwa,mbyd,8)+1,8,mgwa,mbit)
955  mbit = 8*(mbyt-4)
956  call pkc(tabd(i,lot),ldd,mgwa,mbit)
957  call pkb(nseq,8,mgwa,mbit)
958  do j=1,nseq
959  jj = ldd+2 + (j-1)*2
960  idn = iupm(tabd(i,lot)(jj:jj),16)
961  call pkc(adn30(idn,l30),l30,mgwa,mbit)
962  enddo
963  mbyt = mbyt+lend
964  enddo
965 
966  ! Write the unwritten (leftover) message.
967 
968  call msgwrt(lunot,mgwa,mbyt)
969 
970  ! Write out one additional (dummy) DX message containing zero subsets. This will serve as a delimiter for this set of
971  ! table messages within output unit lunot, just in case the next thing written to lunot ends up being another set of
972  ! table messages.
973 
974  call dxmini(mgwa,mbyt,mby4,mbya,mbyb,mbyd)
975  call getlens(mgwa,2,len0,len1,len2,l3,l4,l5)
976  mbit = (len0+len1+len2+4)*8
977  call pkb(0,16,mgwa,mbit)
978  call msgwrt(lunot,mgwa,mbyt)
979 
980  return
981 end subroutine wrdxtb
982 
989 subroutine stbfdx(lun,mesg)
990 
991  use modv_vars, only: maxcd
992 
993  use moda_tababd
994 
995  implicit none
996 
997  integer, intent(in) :: lun, mesg(*)
998  integer maxdx, idxv, nxstr, ldxa, ldxb, ldxd, ld30, ldxbd(10), ldxbe(10), ja, jb, idxs, i3, i, j, n, nd, ndd, idn, &
999  jbit, len0, len1, len2, len3, l4, l5, lda, ldb, ldd, ldbd, ldbe, l30, ia, la, ib, lb, id, ld, iret, &
1000  ifxy, iupb, iupbs01, igetntbi, idn30
1001 
1002  character*128 bort_str
1003  character*128 tabb1, tabb2
1004  character*56 dxstr
1005  character*55 cseq
1006  character*50 dxcmp
1007  character*24 unit
1008  character*8 nemo
1009  character*6 numb, cidn
1010 
1011  common /dxtab/ maxdx, idxv, nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
1012 
1013  data ldxbd /38, 70, 8*0/
1014  data ldxbe /42, 42, 8*0/
1015 
1016  ! Statement functions
1017  ja(i) = ia+1+lda*(i-1)
1018  jb(i) = ib+1+ldb*(i-1)
1019 
1020  ! Get some preliminary information from the message
1021 
1022  idxs = iupbs01(mesg,'MSBT')+1
1023  if(idxs>idxv+1) idxs = iupbs01(mesg,'MTVL')+1
1024  if(ldxa(idxs)==0 .or. ldxb(idxs)==0 .or. ldxd(idxs)==0) call bort('BUFRLIB: STBFDX - UNEXPECTED DICTIONARY '// &
1025  'MESSAGE SUBTYPE OR LOCAL VERSION NUMBER (E.G., L.V.N. HIGHER THAN KNOWN)')
1026 
1027  call getlens(mesg,3,len0,len1,len2,len3,l4,l5)
1028  i3 = len0+len1+len2
1029  dxcmp = ' '
1030  jbit = 8*(i3+7)
1031  call upc(dxcmp,nxstr(idxs),mesg,jbit,.false.)
1032  if(dxcmp/=dxstr(idxs)) call bort('BUFRLIB: STBFDX - UNEXPECTED DICTIONARY MESSAGE CONTENTS')
1033 
1034  ! Section 4 - read definitions for Tables A, B and D
1035 
1036  lda = ldxa(idxs)
1037  ldb = ldxb(idxs)
1038  ldd = ldxd(idxs)
1039  ldbd = ldxbd(idxs)
1040  ldbe = ldxbe(idxs)
1041  l30 = ld30(idxs)
1042 
1043  ia = i3+len3+5
1044  la = iupb(mesg,ia,8)
1045  ib = ja(la+1)
1046  lb = iupb(mesg,ib,8)
1047  id = jb(lb+1)
1048  ld = iupb(mesg,id,8)
1049 
1050  ! Table A
1051 
1052  do i=1,la
1053  n = igetntbi(lun,'A')
1054  jbit = 8*(ja(i)-1)
1055  call upc(taba(n,lun),lda,mesg,jbit,.true.)
1056  numb = ' '//taba(n,lun)(1:3)
1057  nemo = taba(n,lun)(4:11)
1058  cseq = taba(n,lun)(13:67)
1059  call stntbia(n,lun,numb,nemo,cseq)
1060  enddo
1061 
1062  ! Table B
1063 
1064  do i=1,lb
1065  n = igetntbi(lun,'B')
1066  jbit = 8*(jb(i)-1)
1067  call upc(tabb1,ldbd,mesg,jbit,.true.)
1068  jbit = 8*(jb(i)+ldbd-1)
1069  call upc(tabb2,ldbe,mesg,jbit,.true.)
1070  tabb(n,lun) = tabb1(1:ldxbd(idxv+1))//tabb2(1:ldxbe(idxv+1))
1071  numb = tabb(n,lun)(1:6)
1072  nemo = tabb(n,lun)(7:14)
1073  call nenubd(nemo,numb,lun)
1074  idnb(n,lun) = ifxy(numb)
1075  unit = tabb(n,lun)(71:94)
1076  call capit(unit)
1077  tabb(n,lun)(71:94) = unit
1078  ntbb(lun) = n
1079  enddo
1080 
1081  ! Table D
1082 
1083  do i=1,ld
1084  n = igetntbi(lun,'D')
1085  jbit = 8*id
1086  call upc(tabd(n,lun),ldd,mesg,jbit,.true.)
1087  numb = tabd(n,lun)(1:6)
1088  nemo = tabd(n,lun)(7:14)
1089  call nenubd(nemo,numb,lun)
1090  idnd(n,lun) = ifxy(numb)
1091  nd = iupb(mesg,id+ldd+1,8)
1092  if(nd>maxcd) then
1093  write(bort_str,'("BUFRLIB: STBFDX - NUMBER OF DESCRIPTORS IN '// &
1094  'TABLE D ENTRY ",A," IN BUFR TABLE (",I4,") EXCEEDS THE LIMIT (",I4,")")') nemo,nd,maxcd
1095  call bort(bort_str)
1096  endif
1097  do j=1,nd
1098  ndd = id+ldd+2 + (j-1)*l30
1099  jbit = 8*(ndd-1)
1100  call upc(cidn,l30,mesg,jbit,.true.)
1101  idn = idn30(cidn,l30)
1102  call pktdd(n,lun,idn,iret)
1103  if(iret<0) call bort('BUFRLIB: STBFDX - BAD RETURN FROM BUFRLIB ROUTINE PKTDD, SEE PREVIOUS WARNING MESSAGE')
1104  enddo
1105  id = id+ldd+1 + nd*l30
1106  if(iupb(mesg,id+1,8)==0) id = id+1
1107  ntbd(lun) = n
1108  enddo
1109 
1110  return
1111 end subroutine stbfdx
1112 
1122 integer function idxmsg( mesg ) result( iret )
1123 
1124  implicit none
1125 
1126  integer, intent(in) :: mesg(*)
1127  integer iupbs01
1128 
1129  ! Note that the following test relies upon logic within subroutine dxmini() which zeroes out the Section 1 date of
1130  ! all DX dictionary messages.
1131 
1132  if ( (iupbs01(mesg,'MTYP')==11) .and. &
1133  (iupbs01(mesg,'MNTH')==0) .and. (iupbs01(mesg,'DAYS')==0) .and. (iupbs01(mesg,'HOUR')==0) ) then
1134  iret = 1
1135  else
1136  iret = 0
1137  end if
1138 
1139  return
1140 end function idxmsg
1141 
1152 integer function igetntbi ( lun, ctb ) result(iret)
1153 
1154  use moda_tababd
1155 
1156  implicit none
1157 
1158  integer, intent(in) :: lun
1159  integer imax
1160 
1161  character, intent(in) :: ctb
1162  character*128 bort_str
1163 
1164  if ( ctb == 'A' ) then
1165  iret = ntba(lun) + 1
1166  imax = ntba(0)
1167  else if ( ctb == 'B' ) then
1168  iret = ntbb(lun) + 1
1169  imax = ntbb(0)
1170  else ! ctb == 'D'
1171  iret = ntbd(lun) + 1
1172  imax = ntbd(0)
1173  endif
1174  if ( iret > imax ) then
1175  write(bort_str,'("BUFRLIB: IGETNTBI - NUMBER OF INTERNAL TABLE",A1," ENTRIES EXCEEDS THE LIMIT (",I4,")")') ctb, imax
1176  call bort(bort_str)
1177  endif
1178 
1179  return
1180 end function igetntbi
1181 
1196 subroutine nemtbax(lun,nemo,mtyp,msbt,inod)
1197 
1198  use moda_tababd
1199 
1200  implicit none
1201 
1202  integer, intent(in) :: lun
1203  integer, intent(out) :: mtyp, msbt, inod
1204  integer i
1205 
1206  character*(*), intent(in) :: nemo
1207  character*128 bort_str
1208 
1209  inod = 0
1210 
1211  ! Look for nemo in Table A
1212 
1213  do i=1,ntba(lun)
1214  if(taba(i,lun)(4:11)==nemo) then
1215  mtyp = idna(i,lun,1)
1216  msbt = idna(i,lun,2)
1217  inod = mtab(i,lun)
1218  if(mtyp<0 .or. mtyp>255) then
1219  write(bort_str,'("BUFRLIB: NEMTBAX - INVALID MESSAGE TYPE (",I4,") RETURNED FOR MENMONIC ",A)') mtyp, nemo
1220  call bort(bort_str)
1221  endif
1222  if(msbt<0 .or. msbt>255) then
1223  write(bort_str,'("BUFRLIB: NEMTBAX - INVALID MESSAGE SUBTYPE (",I4,") RETURNED FOR MENMONIC ",A)') msbt, nemo
1224  call bort(bort_str)
1225  endif
1226  exit
1227  endif
1228  enddo
1229 
1230  return
1231 end subroutine nemtbax
1232 
1246 subroutine nemtba(lun,nemo,mtyp,msbt,inod)
1247 
1248  implicit none
1249 
1250  integer, intent(in) :: lun
1251  integer, intent(out) :: mtyp, msbt, inod
1252 
1253  character*(*), intent(in) :: nemo
1254  character*128 bort_str
1255 
1256  ! Look for nemo in Table A
1257 
1258  call nemtbax(lun,nemo,mtyp,msbt,inod)
1259  if(inod==0) then
1260  write(bort_str,'("BUFRLIB: NEMTBA - CAN''T FIND MNEMONIC ",A)') nemo
1261  call bort(bort_str)
1262  endif
1263 
1264  return
1265 end subroutine nemtba
1266 
1277 subroutine nemtbb(lun,itab,unit,iscl,iref,ibit)
1278 
1279  use moda_tababd
1280 
1281  implicit none
1282 
1283  integer, intent(in) :: lun, itab
1284  integer, intent(out) :: iscl, iref, ibit
1285  integer idn, ierns
1286 
1287  character*128 bort_str
1288  character*24, intent(out) :: unit
1289  character*8 nemo
1290 
1291  if(itab<=0 .or. itab>ntbb(lun)) then
1292  write(bort_str,'("BUFRLIB: NEMTBB - ITAB (",I7,") NOT FOUND IN TABLE B")') itab
1293  call bort(bort_str)
1294  endif
1295 
1296  ! Pull out Table B information
1297 
1298  idn = idnb(itab,lun)
1299  nemo = tabb(itab,lun)( 7:14)
1300  unit = tabb(itab,lun)(71:94)
1301  call strnum(tabb(itab,lun)( 95: 98),iscl,ierns)
1302  call strnum(tabb(itab,lun)( 99:109),iref,ierns)
1303  call strnum(tabb(itab,lun)(110:112),ibit,ierns)
1304 
1305  ! Check Table B contents
1306 
1307  if(unit(1:5)/='CCITT' .and. ibit>32) then
1308  write(bort_str,'("BUFRLIB: NEMTBB - BIT WIDTH FOR NON-CHARACTER TABLE B MNEMONIC ",A," (",I7,") IS > 32")') nemo,ibit
1309  call bort(bort_str)
1310  endif
1311  if(unit(1:5)=='CCITT' .and. mod(ibit,8)/=0) then
1312  write(bort_str,'("BUFRLIB: NEMTBB - BIT WIDTH FOR CHARACTER TABLE B MNEMONIC ",A," (",I7,") IS NOT A MULTIPLE OF 8")') &
1313  nemo,ibit
1314  call bort(bort_str)
1315  endif
1316 
1317  return
1318 end subroutine nemtbb
1319 
1345 subroutine nemtbd(lun,itab,nseq,nems,irps,knts)
1346 
1347  use modv_vars, only: maxcd
1348 
1349  use moda_tababd
1350 
1351  implicit none
1352 
1353  integer, intent(in) :: lun, itab
1354  integer, intent(out) :: nseq, irps(*), knts(*)
1355  integer i, j, ndsc, idsc, iret
1356 
1357  character*128 bort_str
1358  character*8, intent(out) :: nems(*)
1359  character*8 nemo, nemt, nemf
1360  character tab
1361 
1362  if(itab<=0 .or. itab>ntbd(lun)) then
1363  write(bort_str,'("BUFRLIB: NEMTBD - ITAB (",I7,") NOT FOUND IN TABLE D")') itab
1364  call bort(bort_str)
1365  endif
1366 
1367  ! Clear the return values
1368 
1369  nseq = 0
1370 
1371  do i=1,maxcd
1372  nems(i) = ' '
1373  irps(i) = 0
1374  knts(i) = 0
1375  enddo
1376 
1377  ! Parse the Table D entry
1378 
1379  nemo = tabd(itab,lun)(7:14)
1380  idsc = idnd(itab,lun)
1381  call uptdd(itab,lun,0,ndsc)
1382 
1383  ! Loop through each child mnemonic
1384 
1385  do j=1,ndsc
1386  if(nseq+1>maxcd) then
1387  write(bort_str,'("BUFRLIB: NEMTBD - THERE ARE MORE THAN '// &
1388  '(",I4,") DESCRIPTORS (THE LIMIT) IN TABLE D SEQUENCE MNEMONIC ",A)') maxcd, nemo
1389  call bort(bort_str)
1390  endif
1391  call uptdd(itab,lun,j,idsc)
1392  call numtab(lun,idsc,nemt,tab,iret)
1393  if(tab=='R') then
1394  if(iret<0) then
1395  ! Regular (i.e. non-delayed) replication
1396  irps(nseq+1) = 1
1397  knts(nseq+1) = abs(iret)
1398  elseif(iret>0) then
1399  ! Delayed replication
1400  irps(nseq+1) = iret
1401  endif
1402  elseif(tab=='F') then
1403  ! Replication factor
1404  irps(nseq+1) = iret
1405  elseif(tab=='D'.or.tab=='C') then
1406  nseq = nseq+1
1407  nems(nseq) = nemt
1408  elseif(tab=='B') then
1409  nseq = nseq+1
1410  if((nemt(1:1)=='.').and.(j<ndsc)) then
1411  ! This is a "following value" mnemonic
1412  call uptdd(itab,lun,j+1,idsc)
1413  call numtab(lun,idsc,nemf,tab,iret)
1414  call rsvfvm(nemt,nemf)
1415  endif
1416  nems(nseq) = nemt
1417  endif
1418  enddo
1419 
1420  return
1421 end subroutine nemtbd
1422 
1445 recursive subroutine nemdefs ( lunit, nemo, celem, cunit, iret )
1446 
1447  use modv_vars, only: im8b
1448 
1449  use moda_tababd
1450 
1451  implicit none
1452 
1453  integer, intent(in) :: lunit
1454  integer, intent(out) :: iret
1455  integer my_lunit, lun, il, im, idn, iloc, ls
1456 
1457  character*(*), intent(in) :: nemo
1458  character*(*), intent(out) :: celem, cunit
1459  character tab
1460 
1461  ! Check for I8 integers.
1462 
1463  if(im8b) then
1464  im8b=.false.
1465  call x84 ( lunit, my_lunit, 1 )
1466  call nemdefs ( my_lunit, nemo, celem, cunit, iret )
1467  call x48 ( iret, iret, 1 )
1468  im8b=.true.
1469  return
1470  endif
1471 
1472  iret = -1
1473 
1474  ! Get lun from lunit.
1475 
1476  call status( lunit, lun, il, im )
1477  if ( il == 0 ) return
1478 
1479  ! Find the requested mnemonic in the internal Table B arrays.
1480 
1481  call nemtab( lun, nemo, idn, tab, iloc )
1482  if ( ( iloc == 0 ) .or. ( tab /= 'B' ) ) return
1483 
1484  ! Get the element name and units of the requested mnemonic.
1485 
1486  celem = ' '
1487  ls = min(len(celem),55)
1488  celem(1:ls) = tabb(iloc,lun)(16:15+ls)
1489 
1490  cunit = ' '
1491  ls = min(len(cunit),24)
1492  cunit(1:ls) = tabb(iloc,lun)(71:70+ls)
1493 
1494  iret = 0
1495 
1496  return
1497 end subroutine nemdefs
1498 
1513 subroutine nenubd(nemo,numb,lun)
1514 
1515  use moda_tababd
1516 
1517  implicit none
1518 
1519  character, intent(in) :: nemo*8, numb*6
1520  character*128 bort_str
1521 
1522  integer, intent(in) :: lun
1523  integer n
1524 
1525  do n=1,ntbb(lun)
1526  if(numb==tabb(n,lun)(1:6)) then
1527  write(bort_str,'("BUFRLIB: NENUBD - TABLE B FXY VALUE (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') numb
1528  call bort(bort_str)
1529  endif
1530  if(nemo==tabb(n,lun)(7:14)) then
1531  write(bort_str,'("BUFRLIB: NENUBD - TABLE B MNEMONIC (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') nemo
1532  call bort(bort_str)
1533  endif
1534  enddo
1535 
1536  do n=1,ntbd(lun)
1537  if(numb==tabd(n,lun)(1:6)) then
1538  write(bort_str,'("BUFRLIB: NENUBD - TABLE D FXY VALUE (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') numb
1539  call bort(bort_str)
1540  endif
1541  if(nemo==tabd(n,lun)(7:14)) then
1542  write(bort_str,'("BUFRLIB: NENUBD - TABLE D MNEMONIC (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') nemo
1543  call bort(bort_str)
1544  endif
1545  enddo
1546 
1547  return
1548 end subroutine nenubd
1549 
1559 subroutine stntbia ( n, lun, numb, nemo, celsq )
1560 
1561  use moda_tababd
1562 
1563  implicit none
1564 
1565  integer, intent(in) :: n, lun
1566  integer i, mtyp, msbt
1567 
1568  character*(*), intent(in) :: numb, nemo, celsq
1569  character*128 bort_str
1570 
1571  ! Confirm that neither nemo nor numb has already been defined within the internal BUFR Table A for the given lun.
1572 
1573  do i=1,ntba(lun)
1574  if(numb(4:6)==taba(i,lun)(1:3)) then
1575  write(bort_str,'("BUFRLIB: STNTBIA - TABLE A FXY VALUE (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') numb
1576  call bort(bort_str)
1577  endif
1578  if(nemo(1:8)==taba(i,lun)(4:11)) then
1579  write(bort_str,'("BUFRLIB: STNTBIA - TABLE A MNEMONIC (",A,") HAS ALREADY BEEN DEFINED (DUPLICATE)")') nemo
1580  call bort(bort_str)
1581  endif
1582  enddo
1583 
1584  ! Store the values within the internal BUFR Table A.
1585 
1586  taba(n,lun)(1:3) = numb(4:6)
1587  taba(n,lun)(4:11) = nemo(1:8)
1588  taba(n,lun)(13:67) = celsq(1:55)
1589 
1590  ! Decode and store the message type and subtype.
1591 
1592  if ( verify( nemo(3:8), '1234567890' ) == 0 ) then
1593  ! Message type & subtype obtained directly from Table A mnemonic
1594  read ( nemo,'(2X,2I3)') mtyp, msbt
1595  idna(n,lun,1) = mtyp
1596  idna(n,lun,2) = msbt
1597  else
1598  ! Message type obtained from Y value of Table A seq. descriptor
1599  read ( numb(4:6),'(I3)') idna(n,lun,1)
1600  ! Message subtype hardwired to zero
1601  idna(n,lun,2) = 0
1602  endif
1603 
1604  ! Update the count of internal Table A entries.
1605 
1606  ntba(lun) = n
1607 
1608  return
1609 end subroutine stntbia
1610 
1620 subroutine stntbi ( n, lun, numb, nemo, celsq )
1621 
1622  use moda_tababd
1623 
1624  implicit none
1625 
1626  integer, intent(in) :: n, lun
1627  integer ifxy
1628 
1629  character*(*), intent(in) :: numb, nemo, celsq
1630 
1631  call nenubd ( nemo, numb, lun )
1632 
1633  if ( numb(1:1) == '0') then
1634  idnb(n,lun) = ifxy(numb)
1635  tabb(n,lun)(1:6) = numb(1:6)
1636  tabb(n,lun)(7:14) = nemo(1:8)
1637  tabb(n,lun)(16:70) = celsq(1:55)
1638  ntbb(lun) = n
1639  else ! numb(1:1) == '3'
1640  idnd(n,lun) = ifxy(numb)
1641  tabd(n,lun)(1:6) = numb(1:6)
1642  tabd(n,lun)(7:14) = nemo(1:8)
1643  tabd(n,lun)(16:70) = celsq(1:55)
1644  ntbd(lun) = n
1645  endif
1646 
1647  return
1648 end subroutine stntbi
1649 
1665 subroutine pktdd(id,lun,idn,iret)
1666 
1667  use modv_vars, only: maxcd
1668 
1669  use moda_tababd
1670 
1671  implicit none
1672 
1673  integer, intent(in) :: id, lun, idn
1674  integer, intent(out) :: iret
1675  integer maxdx, idxv, nxstr, ldxa, ldxb, ldxd, ld30, iprt, ldd, nd, idm, iupm
1676 
1677  character*128 errstr
1678  character*56 dxstr
1679 
1680  common /dxtab/ maxdx, idxv, nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
1681  common /quiet/ iprt
1682 
1683  ! ldd points to the byte within tabd(id,lun) which contains (in packed integer format) a count of the number of child
1684  ! mnemonics stored thus far for this parent mnemonic.
1685  ldd = ldxd(idxv+1)+1
1686 
1687  ! Zero the counter if idn is zero
1688  if(idn==0) then
1689  call ipkm(tabd(id,lun)(ldd:ldd),1,0)
1690  iret = 0
1691  return
1692  endif
1693 
1694  ! Update the stored descriptor count for this Table D entry. nd is the (unpacked) count of the number of child mnemonics
1695  ! stored thus far for this parent mnemonic.
1696  nd = iupm(tabd(id,lun)(ldd:ldd),8)
1697 
1698  if(nd<0 .or. nd==maxcd) then
1699  if(iprt>=0) then
1700  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1701  if(nd<0) then
1702  write ( unit=errstr, fmt='(A,I4,A)' ) 'BUFRLIB: PKTDD - BAD COUNTER VALUE (=', nd, ') - RETURN WITH IRET = -1'
1703  else
1704  write ( unit=errstr, fmt='(A,I4,A,A)' ) 'BUFRLIB: PKTDD - MAXIMUM NUMBER OF CHILD MNEMONICS (=', &
1705  maxcd, ') ALREADY STORED FOR THIS PARENT - RETURN WITH IRET = -1'
1706  endif
1707  call errwrt(errstr)
1708  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1709  call errwrt(' ')
1710  endif
1711  iret = -1
1712  return
1713  else
1714  nd = nd+1
1715  call ipkm(tabd(id,lun)(ldd:ldd),1,nd)
1716  iret = nd
1717  endif
1718 
1719  ! Pack and store the descriptor. idm points to the starting byte within tabd(id,lun) at which the idn value for this
1720  ! child mnemonic will be stored (as a packed integer of width = 2 bytes).
1721  idm = ldd+1 + (nd-1)*2
1722  call ipkm(tabd(id,lun)(idm:idm),2,idn)
1723 
1724  return
1725 end subroutine pktdd
1726 
1740 subroutine uptdd(id,lun,ient,iret)
1741 
1742  use moda_tababd
1743 
1744  implicit none
1745 
1746  integer, intent(in) :: id, lun, ient
1747  integer, intent(out) :: iret
1748  integer maxdx, idxv, nxstr, ldxa, ldxb, ldxd, ld30, ldd, ndsc, idsc, iupm
1749 
1750  character*128 bort_str
1751  character*56 dxstr
1752 
1753  common /dxtab/ maxdx, idxv, nxstr(10), ldxa(10), ldxb(10), ldxd(10), ld30(10), dxstr(10)
1754 
1755  ! Check if ient is in bounds
1756 
1757  ldd = ldxd(idxv+1)+1
1758  ndsc = iupm(tabd(id,lun)(ldd:ldd),8)
1759  if(ient==0) then
1760  iret = ndsc
1761  return
1762  elseif(ient<0 .or. ient>ndsc) then
1763  write(bort_str,'("BUFRLIB: UPTDD - VALUE OF THIRD ARGUMENT IENT (INPUT) IS OUT OF RANGE (IENT =",I4,")")') ient
1764  call bort(bort_str)
1765  endif
1766 
1767  ! Return the descriptor indicated by ient
1768 
1769  idsc = ldd+1 + (ient-1)*2
1770  iret = iupm(tabd(id,lun)(idsc:idsc),16)
1771 
1772  return
1773 end subroutine uptdd
1774 
1794 subroutine rsvfvm(nem1,nem2)
1795 
1796  implicit none
1797 
1798  character*8, intent(inout) :: nem1
1799  character*8, intent(in) :: nem2
1800 
1801  integer i, j
1802 
1803  do i=1,len(nem1)
1804  if(i==1) then
1805  ! Skip the initial ".", and initialize J.
1806  j = 1
1807  else
1808  if(nem1(i:i)=='.') then
1809  nem1(i:i) = nem2(j:j)
1810  j = j+1
1811  endif
1812  endif
1813  enddo
1814 
1815  return
1816 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:678
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:1278
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:697
subroutine nemtba(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1247
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:1795
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:850
subroutine nemtbax(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1197
subroutine nemtbd(lun, itab, nseq, nems, irps, knts)
Get information about a Table D descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1346
subroutine stntbi(n, lun, numb, nemo, celsq)
Store a new entry within internal BUFR Table B or D.
Definition: dxtable.F90:1621
subroutine pktdd(id, lun, idn, iret)
Store information about a child mnemonic within the internal BUFR Table D.
Definition: dxtable.F90:1666
subroutine stntbia(n, lun, numb, nemo, celsq)
Store a new entry within internal BUFR Table A.
Definition: dxtable.F90:1560
subroutine stbfdx(lun, mesg)
Copy a DX BUFR tables message into the internal memory arrays in module moda_tababd.
Definition: dxtable.F90:990
subroutine writdx(lunit, lun, lundx)
Write DX BUFR table (dictionary) messages to the beginning of an output BUFR file in lunit.
Definition: dxtable.F90:812
recursive subroutine nemdefs(lunit, nemo, celem, cunit, iret)
Get the element name and units associated with a Table B descriptor.
Definition: dxtable.F90:1446
integer function igetntbi(lun, ctb)
Get the next available index for storing an entry within a specified internal DX BUFR table.
Definition: dxtable.F90:1153
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:1514
integer function idxmsg(mesg)
Check whether a BUFR message contains DX BUFR tables information that was generated by the NCEPLIBS-b...
Definition: dxtable.F90:1123
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:1741
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:432
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:357
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:303
recursive subroutine strnum(str, num, iret)
Decode an integer from a character string.
Definition: misc.F90:177
subroutine capit(str)
Capitalize all of the alphabetic characters in a string.
Definition: misc.F90:355
Wrap C NCEPLIBS-bufr functions so they can be called from within the Fortran part of the library.
Definition: bufrlib.F90:11
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