NCEPLIBS-bufr  12.3.0
jumplink.F90
Go to the documentation of this file.
1 
5 
22 subroutine makestab
23 
24  use modv_vars, only: bmiss, maxjl, nfiles, iprt
25 
26  use moda_usrint
27  use moda_stbfr
28  use moda_lushr
29  use moda_xtab
30  use moda_tababd
31  use moda_tables
32  use moda_nrv203
33  use moda_bitmaps
34 
35  implicit none
36 
37  integer lunit, lundx, lun, lum, n, itba, inc, newn, noda, node, inod, icmpdx, ishrdx
38 
39  character*128 bort_str, errstr
40  character*8 nemo
41 
42  logical expand
43 
44  ! Reset pointer table and string cache.
45 
46  ntab = 0
47  nnrv = 0
48  ntamc = 0
49  call strcln
50 
51  ! Figure out which units share tables.
52 
53  ! The lus array is static between calls to this subroutine, and it keeps track of which logical units share dictionary
54  ! table information:
55  ! if lus(i) = 0, then iolun(i) does not share dictionary table information with any other logical unit
56  ! if lus(i) > 0, then iolun(i) shares dictionary table information with logical unit iolun(lus(i))
57  ! if lus(i) < 0, then iolun(i) does not now, but at one point in the past, shared dictionary table information
58  ! with logical unit iolun(abs(lus(i)))
59 
60  ! The xtab array is non-static and is recomputed within the below loop during each call to this subroutine:
61  ! if xtab(i) = .true., then the dictionary table information has changed for iolun(i) since the last call to this subroutine
62  ! if xtab(i) = .false., then the dictionary table information has not changed for iolun(i) since the last call to this subroutine
63 
64  do lun=1,nfiles
65  xtab(lun) = .false.
66  if(iolun(lun)==0) then
67  ! Logical unit iolun(lun) is not defined to NCEPLIBS-bufr.
68  lus(lun) = 0
69  else if(mtab(1,lun)==0) then
70  ! New dictionary table information has been read for logical unit iolun(lun) since the last call to this subroutine.
71  xtab(lun) = .true.
72  if(lus(lun)/=0) then
73  if(iolun(abs(lus(lun)))==0) then
74  lus(lun) = 0
75  else if(lus(lun)>0) then
76  ! iolun(lun) was sharing table information with logical unit iolun(lus(lun)), so check whether the table information
77  ! has really changed. If not, then iolun(lun) just re-read a copy of the exact same table information as before,
78  ! and therefore it can continue to share with logical unit iolun(lus(lun)).
79  if(icmpdx(lus(lun),lun)==1) then
80  xtab(lun) = .false.
81  call cpbfdx(lus(lun),lun)
82  else
83  lus(lun) = (-1)*lus(lun)
84  endif
85  else if(icmpdx(abs(lus(lun)),lun)==1) then
86  ! iolun(lun) was not sharing table information with logical unit iolun(lus(lun)), but it did at one point in the past
87  ! and now once again has the same table information as that logical unit. Since the two units shared table
88  ! information at one point in the past, allow them to do so again.
89  xtab(lun) = .false.
90  lus(lun) = abs(lus(lun))
91  call cpbfdx(lus(lun),lun)
92  endif
93  endif
94  else if(lus(lun)>0) then
95  ! Logical unit iolun(lun) is sharing table information with logical unit iolun(lus(lun)), so make sure that the latter
96  ! unit is still defined to NCEPLIBS-bufr.
97  if(iolun(lus(lun))==0) then
98  lus(lun) = 0
99  else if( xtab(lus(lun)) .and. (icmpdx(lus(lun),lun)==0) ) then
100  ! The table information for logical unit iolun(lus(lun)) just changed (in midstream). If iolun(lun) is an output
101  ! file, then we will have to update it with the new table information later on in this subroutine. Otherwise,
102  ! iolun(lun) is an input file and is no longer sharing tables with iolun(lus(lun)).
103  if(iolun(lun)<0) lus(lun) = (-1)*lus(lun)
104  endif
105  else
106  ! Determine whether logical unit iolun(lun) is sharing table information with any other logical units.
107  lum = 1
108  do while ((lum<lun).and.(lus(lun)==0))
109  if(ishrdx(lum,lun)==1) then
110  lus(lun) = lum
111  else
112  lum = lum+1
113  endif
114  enddo
115  endif
116  enddo
117 
118  ! Initialize jump/link tables with subsets/sequences/elements.
119 
120  do lun=1,nfiles
121  if(iolun(lun)/=0 .and. ntba(lun)>0) then
122  ! Reset any existing inventory pointers.
123  if(iomsg(lun)/=0) then
124  if(lus(lun)<=0) then
125  inc = (ntab+1)-mtab(1,lun)
126  else
127  inc = mtab(1,lus(lun))-mtab(1,lun)
128  endif
129  do n=1,nval(lun)
130  inv(n,lun) = inv(n,lun)+inc
131  enddo
132  endif
133  if(lus(lun)<=0) then
134  ! The dictionary table information corresponding to logical unit iolun(lun) has not yet been written into the internal
135  ! jump/link table, so add it in now.
136  call chekstab(lun)
137  do itba=1,ntba(lun)
138  inod = ntab+1
139  nemo = taba(itba,lun)(4:11)
140  call tabsub(lun,nemo)
141  mtab(itba,lun) = inod
142  isc(inod) = ntab
143  enddo
144  else if( xtab(lus(lun)) .and. (icmpdx(lus(lun),lun)==0) ) then
145  ! Logical unit iolun(lun) is an output file that is sharing table information with logical unit iolun(lus(lun)) whose
146  ! table just changed (in midstream). Flush any existing data messages from iolun(lun), then update the table information
147  ! for this logical unit with the corresponding new table information from iolun(lus(lun)), then update iolun(lun) itself
148  ! with a copy of the new table information.
149  lunit = abs(iolun(lun))
150  if(iomsg(lun)/=0) call closmg(lunit)
151  call cpbfdx(lus(lun),lun)
152  lundx = abs(iolun(lus(lun)))
153  call wrdxtb(lundx,lunit)
154  endif
155  endif
156  enddo
157 
158  ! Store types and initial values and counts
159 
160  do node=1,ntab
161  if(typ(node)=='SUB') then
162  vali(node) = 0
163  knti(node) = 1
164  itp(node) = 0
165  elseif(typ(node)=='SEQ') then
166  vali(node) = 0
167  knti(node) = 1
168  itp(node) = 0
169  elseif(typ(node)=='RPC') then
170  vali(node) = 0
171  knti(node) = 0
172  itp(node) = 0
173  elseif(typ(node)=='RPS') then
174  vali(node) = 0
175  knti(node) = 0
176  itp(node) = 0
177  elseif(typ(node)=='REP') then
178  vali(node) = bmiss
179  knti(node) = irf(node)
180  itp(node) = 0
181  elseif(typ(node)=='DRS') then
182  vali(node) = 0
183  knti(node) = 1
184  itp(node) = 1
185  elseif(typ(node)=='DRP') then
186  vali(node) = 0
187  knti(node) = 1
188  itp(node) = 1
189  elseif(typ(node)=='DRB') then
190  vali(node) = 0
191  knti(node) = 0
192  itp(node) = 1
193  elseif(typ(node)=='NUM') then
194  vali(node) = bmiss
195  knti(node) = 1
196  itp(node) = 2
197  else ! typ(node)=='CHR'
198  vali(node) = bmiss
199  knti(node) = 1
200  itp(node) = 3
201  endif
202  enddo
203 
204  ! Set up expansion segments for type 'SUB', 'DRP', and 'DRS' nodes.
205 
206  newn = 0
207  knt(1:maxjl) = 0
208  do n=1,ntab
209  iseq(n,1) = 0
210  iseq(n,2) = 0
211  expand = typ(n)=='SUB' .or. typ(n)=='DRP' .or. typ(n)=='DRS' .or. typ(n)=='REP' .or. typ(n)=='DRB'
212  if(expand) then
213  iseq(n,1) = newn+1
214  noda = n
215  node = n+1
216  if(typ(noda)=='REP') then
217  knt(node) = knti(noda)
218  else
219  knt(node) = 1
220  endif
221  outer: do while (.true.)
222  newn = newn+1
223  if(newn>maxjl) then
224  write(bort_str,'("BUFRLIB: MAKESTAB - NUMBER OF JSEQ ENTRIES IN JUMP/LINK TABLE EXCEEDS THE LIMIT (",I6,")")') maxjl
225  call bort(bort_str)
226  endif
227  jseq(newn) = node
228  knt(node) = max(knti(node),knt(node))
229  inner: do while (.true.)
230  if(jump(node)*knt(node)>0) then
231  node = jump(node)
232  cycle outer
233  else if(link(node)>0) then
234  node = link(node)
235  cycle outer
236  else
237  node = jmpb(node)
238  if(node==noda) exit outer
239  if(node==0) then
240  write(bort_str,'("BUFRLIB: MAKESTAB - NODE IS ZERO, FAILED TO CIRCULATE (TAG IS ",A,")")') tag(n)
241  call bort(bort_str)
242  endif
243  knt(node) = max(knt(node)-1,0)
244  endif
245  enddo inner
246  enddo outer
247  iseq(n,2) = newn
248  endif
249  enddo
250 
251  ! Print the sequence tables
252 
253  if(iprt>=2) then
254  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
255  do n=1,ntab
256  write ( unit=errstr, fmt='(A,I5,2X,A10,A5,6I8)' ) &
257  'BUFRLIB: MAKESTAB ', n, tag(n), typ(n), jmpb(n), jump(n), link(n), ibt(n), irf(n), isc(n)
258  call errwrt(errstr)
259  enddo
260  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
261  call errwrt(' ')
262  endif
263 
264  return
265 end subroutine makestab
266 
273 subroutine chekstab(lun)
274 
275  use moda_tababd
276  use moda_nmikrp
277 
278  implicit none
279 
280  integer, intent(in) :: lun
281  integer itab, idn, iret, iscl, iref, ibit, nseq
282 
283  character*128 bort_str
284  character*24 unit
285  character*8 nemo
286  character*1 tab
287 
288  ! There must be entries in Tables A, B, and D
289 
290  if(ntba(lun)==0) call bort ('BUFRLIB: CHEKSTAB - EMPTY TABLE A IN INTERNAL BUFR TABLES')
291  if(ntbb(lun)==0) call bort ('BUFRLIB: CHEKSTAB - EMPTY TABLE B IN INTERNAL BUFR TABLES')
292  if(ntbd(lun)==0) call bort ('BUFRLIB: CHEKSTAB - EMPTY TABLE D IN INTERNAL BUFR TABLES')
293 
294  ! Make sure each Table A entry is defined as a sequence
295 
296  do itab=1,ntba(lun)
297  nemo = taba(itab,lun)(4:11)
298  call nemtab(lun,nemo,idn,tab,iret)
299  if(tab/='D') then
300  write(bort_str,'("BUFRLIB: CHEKSTAB - TABLE A ENTRY: ",A," NOT DEFINED AS A SEQUENCE")') nemo
301  call bort(bort_str)
302  endif
303  enddo
304 
305  ! Check Table B contents
306 
307  do itab=1,ntbb(lun)
308  call nemtbb(lun,itab,unit,iscl,iref,ibit)
309  enddo
310 
311  ! Check Table D contents
312 
313  do itab=1,ntbd(lun)
314  call nemtbd(lun,itab,nseq,nem(1,1),irp(1,1),krp(1,1))
315  enddo
316 
317  return
318 end subroutine chekstab
319 
327 subroutine tabsub(lun,nemo)
328 
329  use modv_vars, only: mxtamc, mxtco
330 
331  use moda_tables
332  use moda_nmikrp
333  use moda_nrv203
334  use moda_bitmaps
335  use moda_tabccc
336 
337  implicit none
338 
339  integer, intent(in) :: lun
340  integer jmp0(10), nodl(10), ntag(10,2), maxlim, node, idn, itab, nseq, limb, n, jj, iyyy, irep, iknt, jum0, iokoper
341 
342  character*128 bort_str
343  character*8, intent(in) :: nemo
344  character*8 nems
345  character*1 tab
346 
347  logical drop(10), ltamc
348 
349  data maxlim /10/
350 
351  ! Check the mnemonic
352 
353  ! Note that Table A mnemonics, in addition to being stored within internal BUFR Table A array taba(*,lun), are also stored as
354  ! Table D mnemonics within internal BUFR Table D array tabd(*,lun). So the following test is valid.
355 
356  call nemtab(lun,nemo,idn,tab,itab)
357  if(tab/='D') then
358  write(bort_str,'("BUFRLIB: TABSUB - SUBSET NODE NOT IN TABLE D (TAB=",A,") FOR INPUT MNEMONIC ",A)') tab,nemo
359  call bort(bort_str)
360  endif
361 
362  ! Store a subset node and jump/link the tree
363 
364  call inctab(nemo,'SUB',node)
365  jump(node) = node+1
366  jmpb(node) = 0
367  link(node) = 0
368  ibt(node) = 0
369  irf(node) = 0
370  isc(node) = 0
371 
372  call nemtbd(lun,itab,nseq,nem(1,1),irp(1,1),krp(1,1))
373  ntag(1,1) = 1
374  ntag(1,2) = nseq
375  jmp0(1) = node
376  nodl(1) = node
377  limb = 1
378 
379  icdw = 0
380  icsc = 0
381  icrv = 1
382  incw = 0
383 
384  ibtnrv = 0
385  ipfnrv = 0
386 
387  if(ntamc+1>mxtamc) call bort('BUFRLIB: TABSUB - MXTAMC OVERFLOW')
388  inodtamc(ntamc+1) = node
389  ntco(ntamc+1) = 0
390  ltamc = .false.
391 
392  ! The following loop resolves all entities in the subset by emulating recursion via explicit goto statements.
393 
394  11 do n=ntag(limb,1),ntag(limb,2)
395 
396  ntag(limb,1) = n+1
397  drop(limb) = n==ntag(limb,2)
398 
399  call nemtab(lun,nem(n,limb),idn,tab,itab)
400  nems = nem(n,limb)
401 
402  if(tab=='C') then
403  ! Special treatment for certain operator descriptors.
404  read(nems,'(3X,I3)') iyyy
405  if(itab==1) then
406  if(iyyy/=0) then
407  if(icdw/=0) then
408  write(bort_str,'("BUFRLIB: TABSUB - THERE ARE TWO SIMULTANEOUS '// &
409  'CHANGE DATA WIDTH OPERATIONS IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
410  call bort(bort_str)
411  endif
412  icdw = iyyy-128
413  else
414  icdw = 0
415  endif
416  elseif(itab==2) then
417  if(iyyy/=0) then
418  if(icsc/=0) then
419  write(bort_str,'("BUFRLIB: TABSUB - THERE ARE TWO SIMULTANEOUS '// &
420  'CHANGE DATA SCALE OPERATIONS IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
421  call bort(bort_str)
422  endif
423  icsc = iyyy-128
424  else
425  icsc = 0
426  endif
427  elseif(itab==3) then
428  if(iyyy==0) then
429  ! Stop applying new reference values to subset nodes. Instead, revert to the use of standard Table B values.
430  if(ipfnrv==0) then
431  write(bort_str,'("BUFRLIB: TABSUB - A 2-03-000 OPERATOR WAS '// &
432  'ENCOUNTERED WITHOUT ANY PRIOR 2-03-YYY OPERATOR FOR INPUT MNEMONIC ",A)') nemo
433  call bort(bort_str)
434  endif
435  do jj=ipfnrv,nnrv
436  ienrv(jj) = ntab
437  enddo
438  ipfnrv = 0
439  elseif(iyyy==255) then
440  ! End the definition of new reference values.
441  ibtnrv = 0
442  else
443  ! Begin the definition of new reference values.
444  if(ibtnrv/=0) then
445  write(bort_str,'("BUFRLIB: TABSUB - THERE ARE TWO SIMULTANEOUS '// &
446  'CHANGE REF VALUE OPERATIONS IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
447  call bort(bort_str)
448  endif
449  ibtnrv = iyyy
450  endif
451  elseif(itab==7) then
452  if(iyyy>0) then
453  if(icdw/=0) then
454  write(bort_str,'("BUFRLIB: TABSUB - THERE ARE TWO SIMULTANEOUS '// &
455  'CHANGE DATA WIDTH OPERATIONS IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
456  call bort(bort_str)
457  endif
458  if(icsc/=0) then
459  write(bort_str,'("BUFRLIB: TABSUB - THERE ARE TWO SIMULTANEOUS '// &
460  'CHANGE DATA SCALE OPERATIONS IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
461  call bort(bort_str)
462  endif
463  icdw = ((10*iyyy)+2)/3
464  icsc = iyyy
465  icrv = 10**iyyy
466  else
467  icsc = 0
468  icdw = 0
469  icrv = 1
470  endif
471  elseif(itab==8) then
472  incw = iyyy
473  elseif((itab>=21).and.(iokoper(nems)==1)) then
474  ! Save the location of this operator within the jump/link table, for possible later use.
475  if(.not.ltamc) then
476  ltamc = .true.
477  ntamc = ntamc+1
478  end if
479  if(ntco(ntamc)+1>mxtco) call bort('BUFRLIB: TABSUB - MXTCO OVERFLOW')
480  ntco(ntamc) = ntco(ntamc)+1
481  ctco(ntamc,ntco(ntamc)) = nems(1:6)
483  endif
484  else
485  nodl(limb) = ntab+1
486  irep = irp(n,limb)
487  iknt = krp(n,limb)
488  jum0 = jmp0(limb)
489  call tabent(lun,nems,tab,itab,irep,iknt,jum0)
490  endif
491 
492  if(tab=='D') then
493  ! Note here how a new tree "limb" is created (and is then immediately recursively resolved) whenever a Table D mnemonic
494  ! contains another Table D mnemonic as one of its children.
495  limb = limb+1
496  if(limb>maxlim) then
497  write(bort_str,'("BUFRLIB: TABSUB - THERE ARE TOO MANY NESTED '// &
498  'TABLE D SEQUENCES (TREES) WITHIN INPUT MNEMONIC ",A," - THE LIMIT IS",I4)') nemo,maxlim
499  call bort(bort_str)
500  endif
501  call nemtbd(lun,itab,nseq,nem(1,limb),irp(1,limb),krp(1,limb))
502  ntag(limb,1) = 1
503  ntag(limb,2) = nseq
504  jmp0(limb) = ntab
505  goto 11
506  elseif(drop(limb)) then
507  do while (.true.)
508  link(nodl(limb)) = 0
509  limb = limb-1
510  if(limb==0) then
511  if(icrv/=1) then
512  write(bort_str,'("BUFRLIB: TABSUB - A 2-07-YYY OPERATOR WAS '// &
513  'NOT CANCELLED IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
514  call bort(bort_str)
515  endif
516  if(icdw/=0) then
517  write(bort_str,'("BUFRLIB: TABSUB - A 2-01-YYY OPERATOR WAS '// &
518  'NOT CANCELLED IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
519  call bort(bort_str)
520  endif
521  if(icsc/=0) then
522  write(bort_str,'("BUFRLIB: TABSUB - A 2-02-YYY OPERATOR WAS '// &
523  'NOT CANCELLED IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
524  call bort(bort_str)
525  endif
526  if(incw/=0) then
527  write(bort_str,'("BUFRLIB: TABSUB - A 2-08-YYY OPERATOR WAS '// &
528  'NOT CANCELLED IN THE TREE BUILT FROM INPUT MNEMONIC ",A)') nemo
529  call bort(bort_str)
530  endif
531  if(ibtnrv/=0) then
532  write(bort_str,'("BUFRLIB: TABSUB - A 2-03-YYY OPERATOR WAS '// &
533  'APPLIED WITHOUT ANY SUBSEQUENT 2-03-255 OPERATOR FOR INPUT MNEMONIC ",A)') nemo
534  call bort(bort_str)
535  endif
536  if(ipfnrv/=0) then
537  ! One or more new reference values were defined for this subset, but there was no subsequent 2-03-000 operator,
538  ! so set all IENRV(*) values for this subset to point to the last element of the subset within the jump/link table.
539  ! Note that, if there had been a subsequent 2-03-000 operator, then these IENRV(*) values would have already been
540  ! properly set above.
541  do jj=ipfnrv,nnrv
542  ienrv(jj) = ntab
543  enddo
544  endif
545  return
546  endif
547  if(.not.drop(limb)) exit
548  enddo
549  link(nodl(limb)) = ntab+1
550  goto 11
551  elseif(tab/='C') then
552  link(nodl(limb)) = ntab+1
553  endif
554 
555  enddo
556 
557  write(bort_str,'("BUFRLIB: TABSUB - ENTITIES WERE NOT SUCCESSFULLY RESOLVED (BY EMULATING RESURSION) FOR SUBSET '// &
558  'DEFINED BY TBL A MNEM. ",A)') nemo
559  call bort(bort_str)
560 
561  return
562 end subroutine tabsub
563 
577 subroutine tabent(lun,nemo,tab,itab,irep,iknt,jum0)
578 
579  use modv_vars, only: mxnrv, typs, reps, lens
580 
581  use moda_tables
582  use moda_nrv203
583  use moda_tabccc
584 
585  implicit none
586 
587  integer, intent(in) :: lun, itab, irep, iknt, jum0
588  integer i, jm0, node, iscl, iref, ibit
589 
590  character*24 unit
591  character*10 rtag
592  character*8, intent(in) :: nemo
593  character, intent(in) :: tab
594  character*3 typt
595 
596  jm0 = jum0
597 
598  ! Make a jump/link table entry for a replicator
599 
600  if(irep/=0) then
601  rtag = reps(irep)//nemo
602  do i=1,10
603  if(rtag(i:i)==' ') then
604  rtag(i:i) = reps(irep+5)
605  call inctab(rtag,typs(irep),node)
606  jump(node) = node+1
607  jmpb(node) = jm0
608  link(node) = 0
609  ibt(node) = lens(irep)
610  irf(node) = 0
611  isc(node) = 0
612  if(irep==1) irf(node) = iknt
613  jm0 = node
614  exit
615  endif
616  enddo
617  endif
618 
619  ! Make a jump/link entry for an element or a sequence
620 
621  if(tab=='B') then
622  call nemtbb(lun,itab,unit,iscl,iref,ibit)
623  if(unit(1:5)=='CCITT') then
624  typt = 'CHR'
625  else
626  typt = 'NUM'
627  endif
628  call inctab(nemo,typt,node)
629  jump(node) = 0
630  jmpb(node) = jm0
631  link(node) = 0
632  ibt(node) = ibit
633  irf(node) = iref
634  isc(node) = iscl
635  if(unit(1:4)=='CODE') then
636  typt = 'COD'
637  elseif(unit(1:4)=='FLAG') then
638  typt = 'FLG'
639  endif
640  if( (typt=='NUM') .and. (ibtnrv/=0) ) then
641  ! This node contains a new (redefined) reference value.
642  if(nnrv+1>mxnrv) call bort('BUFRLIB: TABENT - MXNRV OVERFLOW')
643  nnrv = nnrv+1
644  tagnrv(nnrv) = nemo
645  inodnrv(nnrv) = node
646  isnrv(nnrv) = node+1
647  ibt(node) = ibtnrv
648  if(ipfnrv==0) ipfnrv = nnrv
649  elseif( (typt=='NUM') .and. (nemo(1:3)/='204') ) then
650  ibt(node) = ibt(node) + icdw
651  isc(node) = isc(node) + icsc
652  irf(node) = irf(node) * icrv
653  elseif( (typt=='CHR') .and. (incw>0) ) then
654  ibt(node) = incw * 8
655  endif
656  else ! tab=='D'
657  if(irep==0) then
658  typt = 'SEQ'
659  else
660  typt = typs(irep+5)
661  endif
662  call inctab(nemo,typt,node)
663  jump(node) = node+1
664  jmpb(node) = jm0
665  link(node) = 0
666  ibt(node) = 0
667  irf(node) = 0
668  isc(node) = 0
669  endif
670 
671  return
672 end subroutine tabent
673 
686 subroutine inctab(atag,atyp,node)
687 
688  use modv_vars, only: maxjl
689 
690  use moda_tables
691 
692  implicit none
693 
694  integer, intent(out) :: node
695 
696  character*(*), intent(in) :: atag, atyp
697  character*128 bort_str
698 
699  ntab = ntab+1
700  if(ntab>maxjl) then
701  write(bort_str,'("BUFRLIB: INCTAB - THE NUMBER OF JUMP/LINK TABLE ENTRIES EXCEEDS THE LIMIT, MAXJL (",I7,")")') maxjl
702  call bort(bort_str)
703  endif
704  tag(ntab) = atag
705  typ(ntab) = atyp
706  node = ntab
707 
708  return
709 end subroutine inctab
710 
731 integer function lstjpb(node,lun,jbtyp) result(iret)
732 
733  use moda_msgcwd
734  use moda_tables
735 
736  implicit none
737 
738  integer, intent(in) :: node, lun
739  integer nod
740 
741  character*(*), intent(in) :: jbtyp
742  character*128 bort_str
743 
744  if(node<inode(lun)) then
745  write(bort_str,'("BUFRLIB: LSTJPB - TABLE NODE (",I7,") IS OUT OF BOUNDS, < LOWER BOUNDS (",I7,")")') node,inode(lun)
746  call bort(bort_str)
747  endif
748  if(node>isc(inode(lun))) then
749  write(bort_str,'("BUFRLIB: LSTJPB - TABLE NODE (",I7,") IS OUT OF BOUNDS, > UPPER BOUNDS (",I7,")")') node,isc(inode(lun))
750  call bort(bort_str)
751  endif
752 
753  nod = node
754 
755  ! Find this or the previous node of type jbtyp
756 
757  do while (nod/=0)
758  if(typ(nod)==jbtyp) exit
759  nod = jmpb(nod)
760  enddo
761 
762  iret = nod
763 
764  return
765 end function lstjpb
766 
777 integer function ishrdx(lud,lun) result(iret)
778 
779  use moda_tababd
780 
781  implicit none
782 
783  integer, intent(in) :: lud, lun
784  integer ii
785 
786  ! Note that, for any file ID luX, the mtab(*,luX) array contains pointer indices into the internal jump/link table
787  ! for each of the Table A mnemonics that is currently defined for that luX value. Thus, if all of these indices are
788  ! identical for two different luX values, then the associated logical units are sharing table information.
789 
790  if ( ( ntba(lud) >= 1 ) .and. ( ntba(lud) == ntba(lun) ) ) then
791  ii = 1
792  iret = 1
793  do while ( ( ii <= ntba(lud) ) .and. ( iret == 1 ) )
794  if ( ( mtab(ii,lud) /= 0 ) .and. ( mtab(ii,lud) == mtab(ii,lun) ) ) then
795  ii = ii + 1
796  else
797  iret = 0
798  endif
799  enddo
800  else
801  iret = 0
802  endif
803 
804  return
805 end function ishrdx
806 
822 integer function icmpdx(lud,lun) result(iret)
823 
824  use moda_tababd
825 
826  implicit none
827 
828  integer, intent(in) :: lud, lun
829  integer ishrdx, i
830 
831  ! First, check whether the two units are actually sharing tables.
832  ! If so, then they obviously have the same table information.
833 
834  iret = ishrdx(lud,lun)
835  if ( iret == 1 ) return
836 
837  ! Otherwise, check whether the internal Table A, B and D entries are all identical between the two units.
838 
839  if ( ( ntba(lud) == 0 ) .or. ( ntba(lun) /= ntba(lud) ) ) return
840  do i = 1, ntba(lud)
841  if ( idna(i,lun,1) /= idna(i,lud,1) ) return
842  if ( idna(i,lun,2) /= idna(i,lud,2) ) return
843  if ( taba(i,lun) /= taba(i,lud) ) return
844  enddo
845 
846  if ( ( ntbb(lud) == 0 ) .or. ( ntbb(lun) /= ntbb(lud) ) ) return
847  do i = 1, ntbb(lud)
848  if ( idnb(i,lun) /= idnb(i,lud) ) return
849  if ( tabb(i,lun) /= tabb(i,lud) ) return
850  enddo
851 
852  if ( ( ntbd(lud) == 0 ) .or. ( ntbd(lun) /= ntbd(lud) ) ) return
853  do i = 1, ntbd(lud)
854  if ( idnd(i,lun) /= idnd(i,lud) ) return
855  if ( tabd(i,lun) /= tabd(i,lud) ) return
856  enddo
857 
858  iret = 1
859 
860  return
861 end function icmpdx
862 
888 subroutine drstpl(inod,lun,inv1,inv2,invn)
889 
890  use moda_tables
891 
892  implicit none
893 
894  integer, intent(in) :: inod, lun, inv1
895  integer, intent(inout) :: inv2
896  integer, intent(out) :: invn
897  integer node, invwin
898 
899  do while (.true.)
900  node = inod
901  do while (.true.)
902  node = jmpb(node)
903  if(node==0) return
904  if(typ(node)=='DRS' .or. typ(node)=='DRB') then
905  invn = invwin(node,lun,inv1,inv2)
906  if(invn>0) then
907  call usrtpl(lun,invn,1)
908  call newwin(lun,inv1,inv2)
909  invn = invwin(inod,lun,invn,inv2)
910  if(invn>0) return
911  exit
912  endif
913  endif
914  enddo
915  enddo
916 
917  return
918 end subroutine drstpl
919 
952 recursive subroutine nemspecs ( lunit, nemo, nnemo, nscl, nref, nbts, iret )
953 
954  use bufrlib
955 
956  use modv_vars, only: im8b
957 
958  use moda_usrint
959  use moda_msgcwd
960  use moda_tables
961  use moda_nrv203
962 
963  implicit none
964 
965  integer, intent(in) :: lunit, nnemo
966  integer, intent(out) :: nscl, nref, nbts, iret
967  integer my_lunit, my_nnemo, lun, il, im, nidx, ierfst, node, ltn, jj, lcn, bort_target_set
968 
969  character*(*), intent(in) :: nemo
970  character*10 cnemo
971  character*10 tagn
972 
973  ! Check for I8 integers.
974 
975  if(im8b) then
976  im8b=.false.
977  call x84(lunit,my_lunit,1)
978  call x84(nnemo,my_nnemo,1)
979  call nemspecs(my_lunit,nemo,my_nnemo,nscl,nref,nbts,iret)
980  call x48(nscl,nscl,1)
981  call x48(nref,nref,1)
982  call x48(nbts,nbts,1)
983  call x48(iret,iret,1)
984  im8b=.true.
985  return
986  endif
987 
988  ! If we're catching bort errors, set a target return location if one doesn't already exist.
989 
990  if (bort_target_set() == 1) then
991  call strsuc(nemo,cnemo,lcn)
992  call catch_bort_nemspecs_c(lunit,cnemo,lcn,nnemo,nscl,nref,nbts,iret)
993  call bort_target_unset
994  return
995  endif
996 
997  iret = -1
998 
999  ! Get lun from lunit.
1000 
1001  call status( lunit, lun, il, im )
1002  if ( il == 0 ) return
1003  if ( inode(lun) /= inv(1,lun) ) return
1004 
1005  ! Starting from the beginning of the subset, locate the (nnemo)th occurrence of nemo.
1006 
1007  call fstag( lun, nemo, nnemo, 1, nidx, ierfst )
1008  if ( ierfst /= 0 ) return
1009 
1010  ! Confirm that nemo is a Table B mnemonic.
1011 
1012  node = inv(nidx,lun)
1013  if ( ( typ(node) /= 'NUM' ) .and. ( typ(node) /= 'CHR' ) ) return
1014 
1015  ! Get the scale factor, reference value and bit width, including accounting for any Table C operators which may be in
1016  ! scope for this particular occurrence of nemo.
1017 
1018  iret = 0
1019 
1020  nscl = isc(node)
1021  nbts = ibt(node)
1022  nref = irf(node)
1023 
1024  if ( nnrv > 0 ) then
1025 
1026  ! There are nodes containing redefined reference values (from one or more 2-03-YYY operators) in the jump/link table,
1027  ! so we need to check if this node is one of them.
1028 
1029  tagn = ' '
1030  call strsuc( nemo, tagn, ltn )
1031  if ( ( ltn <= 0 ) .or. ( ltn > 8 ) ) return
1032 
1033  do jj = 1, nnrv
1034  if ( ( node /= inodnrv(jj) ) .and. ( tagn(1:8) == tagnrv(jj) ) .and. &
1035  ( node >= isnrv(jj) ) .and. ( node <= ienrv(jj) ) ) then
1036  nref = int(nrv(jj))
1037  return
1038  end if
1039  end do
1040 
1041  end if
1042 
1043  return
1044 end subroutine nemspecs
1045 
1065 subroutine fstag ( lun, utag, nutag, nin, nout, iret )
1066 
1067  use moda_usrint
1068  use moda_tables
1069 
1070  implicit none
1071 
1072  integer, intent(in) :: lun, nutag, nin
1073  integer, intent(out) :: nout, iret
1074  integer, parameter :: maxtg = 15
1075  integer ntg, istep, itagct
1076 
1077  character*(*), intent(in) :: utag
1078  character*10 tgs(maxtg)
1079 
1080  iret = -1
1081 
1082  ! Confirm that there's only one mnemonic in the input string.
1083 
1084  call parstr( utag, tgs, maxtg, ntg, ' ', .true. )
1085  if ( ntg /= 1 ) return
1086 
1087  ! Starting from nin, search either forward or backward for the (nutag)th occurrence of utag.
1088 
1089  if ( nutag == 0 ) return
1090  istep = isign( 1, nutag )
1091  itagct = 0
1092  nout = nin + istep
1093  do while ( ( nout >= 1 ) .and. ( nout <= nval(lun) ) )
1094  if ( tgs(1) == tag(inv(nout,lun)) ) then
1095  itagct = itagct + 1
1096  if ( itagct == iabs(nutag) ) then
1097  iret = 0
1098  return
1099  endif
1100  endif
1101  nout = nout + istep
1102  enddo
1103 
1104  return
1105 end subroutine fstag
1106 
1126 recursive subroutine gettagpr ( lunit, tagch, ntagch, tagpr, iret )
1127 
1128  use bufrlib
1129 
1130  use modv_vars, only: im8b
1131 
1132  use moda_usrint
1133  use moda_msgcwd
1134  use moda_tables
1135 
1136  implicit none
1137 
1138  integer, intent(in) :: lunit, ntagch
1139  integer, intent(out) :: iret
1140  integer my_lunit, my_ntagch, lun, il, im, nch, lch, ntpchr, ltp, bort_target_set
1141 
1142  character*(*), intent(in) :: tagch
1143  character*(*), intent(out) :: tagpr
1144  character*9 ctagch, ctagpr
1145 
1146  ! Check for I8 integers.
1147 
1148  if(im8b) then
1149  im8b=.false.
1150  call x84 ( lunit, my_lunit, 1 )
1151  call x84 ( ntagch, my_ntagch, 1 )
1152  call gettagpr ( my_lunit, tagch, my_ntagch, tagpr, iret )
1153  call x48 ( iret, iret, 1 )
1154  im8b=.true.
1155  return
1156  endif
1157 
1158  tagpr = ' '
1159 
1160  ! If we're catching bort errors, set a target return location if one doesn't already exist.
1161 
1162  if ( bort_target_set() == 1 ) then
1163  call strsuc( tagch, ctagch, lch )
1164  call catch_bort_gettagpr_c( lunit, ctagch, lch, ntagch, ctagpr, len(ctagpr), ntpchr, iret )
1165  ltp = min( len(tagpr), ntpchr )
1166  tagpr(1:ltp) = ctagpr(1:ltp)
1167  call bort_target_unset
1168  return
1169  endif
1170 
1171  iret = -1
1172 
1173  ! Get lun from lunit.
1174 
1175  call status( lunit, lun, il, im )
1176  if ( il == 0 ) return
1177  if ( inode(lun) /= inv(1,lun) ) return
1178 
1179  ! Get tagpr from the (ntagch)th occurrence of tagch.
1180 
1181  call fstag( lun, tagch, ntagch, 1, nch, iret )
1182  if ( iret /= 0 ) return
1183 
1184  tagpr = tag(jmpb(inv(nch,lun)))
1185 
1186  return
1187 end subroutine gettagpr
1188 
1205 integer function invtag(node,lun,inv1,inv2) result(iret)
1206 
1207  use modv_vars, only: iprt
1208 
1209  use moda_usrint
1210  use moda_tables
1211 
1212  implicit none
1213 
1214  integer, intent(in) :: node, lun, inv1, inv2
1215 
1216  character*10 tagn
1217 
1218  if(node/=0) then
1219  tagn = tag(node)
1220  ! Search between inv1 and inv2
1221  do iret=inv1,inv2
1222  if(tag(inv(iret,lun))==tagn) return
1223  enddo
1224  endif
1225 
1226  iret = 0
1227 
1228  if(iprt>=2) then
1229  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1230  call errwrt('BUFRLIB: INVTAG - RETURNING WITH A VALUE OF 0')
1231  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1232  call errwrt(' ')
1233  endif
1234 
1235  return
1236 end function invtag
1237 
1252 integer function invwin(node,lun,inv1,inv2) result(iret)
1253 
1254  use modv_vars, only: iprt
1255 
1256  use moda_usrint
1257 
1258  implicit none
1259 
1260  integer, intent(in) :: node, lun, inv1, inv2
1261  integer idx
1262 
1263  character*80 errstr
1264 
1265  iret = 0
1266  if(node/=0) then
1267  ! Search between inv1 and inv2
1268  do idx=inv1,inv2
1269  if(inv(idx,lun)==node) then
1270  iret = idx
1271  exit
1272  endif
1273  enddo
1274  endif
1275 
1276  if(iprt>=3) then
1277  write(errstr,'(a,3i8)') 'invwin i1,i2,in ', inv1, inv2, iret
1278  call errwrt(errstr)
1279  endif
1280 
1281  return
1282 end function invwin
1283 
1327 subroutine getwin(node,lun,iwin,jwin)
1328 
1329  use moda_usrint
1330 
1331  implicit none
1332 
1333  integer, intent(in) :: node, lun
1334  integer, intent(out) :: iwin, jwin
1335  integer irpc, lstjpb, invwin
1336 
1337  character*128 bort_str
1338 
1339  irpc = lstjpb(node,lun,'RPC')
1340 
1341  if(irpc==0) then
1342  iwin = invwin(node,lun,jwin,nval(lun))
1343  if(iwin==0 .and. jwin>1) return
1344  iwin = 1
1345  jwin = nval(lun)
1346  return
1347  else
1348  iwin = invwin(irpc,lun,jwin,nval(lun))
1349  if(iwin==0) return
1350  if(val(iwin,lun)==0.) then
1351  iwin = 0
1352  return
1353  endif
1354  endif
1355 
1356  jwin = invwin(irpc,lun,iwin+1,nval(lun))
1357  if(jwin==0) then
1358  write(bort_str,'("BUFRLIB: GETWIN - SEARCHED BETWEEN",I5," AND",I5,", MISSING BRACKET")') iwin+1, nval(lun)
1359  call bort(bort_str)
1360  endif
1361 
1362  return
1363 end subroutine getwin
1364 
1396 subroutine conwin(lun,inc1,inc2)
1397 
1398  use moda_usrint
1399 
1400  implicit none
1401 
1402  integer, intent(in) :: lun
1403  integer, intent(out) :: inc1, inc2
1404  integer nnod, ncon, nods, nodc, ivls, kons, nc, invcon
1405 
1406  common /usrstr/ nnod, ncon, nods(20), nodc(10), ivls(10), kons(10)
1407 
1408  if(ncon==0) then
1409  ! There are no condition nodes in the string
1410  inc1 = 1
1411  inc2 = nval(lun)
1412  return
1413  endif
1414 
1415  outer: do while (.true.)
1416  call getwin(nodc(1),lun,inc1,inc2)
1417  if(inc1>0) then
1418  do nc=1,ncon
1419  if(invcon(nc,lun,inc1,inc2)==0) cycle outer
1420  enddo
1421  endif
1422  exit
1423  enddo outer
1424 
1425  return
1426 end subroutine conwin
1427 
1454 integer function invcon(nc,lun,inv1,inv2) result(iret)
1455 
1456  use modv_vars, only: iprt
1457 
1458  use moda_usrint
1459 
1460  implicit none
1461 
1462  integer, intent(in) :: nc, lun, inv1, inv2
1463  integer nnod, ncon, nods, nodc, ivls, kons
1464 
1465  common /usrstr/ nnod, ncon, nods(20), nodc(10), ivls(10), kons(10)
1466 
1467  if(inv1>0 .and. inv1<=nval(lun) .and. inv2>0 .and. inv2<=nval(lun)) then
1468  do iret=inv1,inv2
1469  if(inv(iret,lun)==nodc(nc)) then
1470  if(kons(nc)==1 .and. val(iret,lun)==ivls(nc)) return
1471  if(kons(nc)==2 .and. val(iret,lun)/=ivls(nc)) return
1472  if(kons(nc)==3 .and. val(iret,lun)<ivls(nc)) return
1473  if(kons(nc)==4 .and. val(iret,lun)>ivls(nc)) return
1474  endif
1475  enddo
1476  endif
1477 
1478  iret = 0
1479  if(iprt>=2) then
1480  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1481  call errwrt('BUFRLIB: INVCON - RETURNING WITH A VALUE OF 0')
1482  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1483  call errwrt(' ')
1484  endif
1485 
1486  return
1487 end function invcon
1488 
1505 subroutine newwin(lun,iwin,jwin)
1506 
1507  use moda_usrint
1508 
1509  implicit none
1510 
1511  integer, intent(in) :: lun, iwin
1512  integer, intent(out) :: jwin
1513  integer node, lstjpb
1514 
1515  character*128 bort_str
1516 
1517  if(iwin==1) then
1518  ! This is a "SUB" (subset) node, so return jwin as pointing to the last value of the entire subset.
1519  jwin = nval(lun)
1520  return
1521  endif
1522 
1523  ! Confirm that iwin points to an "RPC" node and then compute jwin.
1524  node = inv(iwin,lun)
1525  if(lstjpb(node,lun,'RPC')/=node) then
1526  write(bort_str,'("BUFRLIB: NEWWIN - LSTJPB FOR NODE",I6,'// &
1527  '" (LSTJPB=",I5,") DOES NOT EQUAL VALUE OF NODE, NOT RPC (IWIN =",I8,")")') node, lstjpb(node,lun,'RPC'), iwin
1528  call bort(bort_str)
1529  endif
1530  jwin = iwin+nint(val(iwin,lun))
1531 
1532  return
1533 end subroutine newwin
1534 
1553 subroutine nxtwin(lun,iwin,jwin)
1554 
1555  use moda_usrint
1556 
1557  implicit none
1558 
1559  integer, intent(in) :: lun
1560  integer, intent(inout) :: iwin, jwin
1561  integer node, lstjpb
1562 
1563  character*128 bort_str
1564 
1565  if(jwin==nval(lun)) then
1566  iwin = 0
1567  return
1568  endif
1569 
1570  node = inv(iwin,lun)
1571  if(lstjpb(node,lun,'RPC')/=node) then
1572  write(bort_str,'("BUFRLIB: NXTWIN - LSTJPB FOR NODE",I6," '// &
1573  '(LSTJPB=",I5,") DOES NOT EQUAL VALUE OF NODE, NOT RPC (IWIN =",I8,")")') node, lstjpb(node,lun,'RPC'), iwin
1574  call bort(bort_str)
1575  endif
1576  if(val(jwin,lun)==0) then
1577  iwin = 0
1578  else
1579  iwin = jwin
1580  jwin = iwin+nint(val(iwin,lun))
1581  endif
1582 
1583  return
1584 end subroutine nxtwin
1585 
1603 integer function nvnwin(node,lun,inv1,inv2,invn,nmax) result(iret)
1604 
1605  use modv_vars, only: iprt
1606 
1607  use moda_usrint
1608 
1609  implicit none
1610 
1611  integer, intent(in) :: node, lun, inv1, inv2, nmax
1612  integer, intent(out) :: invn(*)
1613  integer i, n
1614 
1615  character*128 bort_str
1616 
1617  iret = 0
1618 
1619  if(node==0) then
1620  if(iprt>=1) then
1621  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1622  call errwrt('BUFRLIB: NVNWIN - NODE=0, IMMEDIATE RETURN')
1623  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1624  call errwrt(' ')
1625  endif
1626  return
1627  endif
1628 
1629  do i=1,nmax
1630  invn(i) = 1e9
1631  enddo
1632 
1633  ! Search between inv1 and inv2
1634 
1635  do n=inv1,inv2
1636  if(inv(n,lun)==node) then
1637  if(iret+1>nmax) then
1638  write(bort_str,'("BUFRLIB: NVNWIN - THE NUMBER OF EVENTS EXCEEDS THE LIMIT NMAX (",I5,")")') nmax
1639  call bort(bort_str)
1640  endif
1641  iret = iret+1
1642  invn(iret) = n
1643  endif
1644  enddo
1645 
1646  return
1647 end function nvnwin
recursive subroutine bort(str)
Log an error message, then either return to or abort the application program.
Definition: borts.F90:15
subroutine bort_target_unset
Clear any existing bort target.
Definition: borts.F90:180
integer function bort_target_set()
Sets a new bort target, if bort catching is enabled and such a target doesn't already exist.
Definition: borts.F90:160
subroutine cpbfdx(lud, lun)
Copy all of the DX BUFR table information from one unit to another within internal memory.
Definition: copydata.F90:714
subroutine nemtbb(lun, itab, unit, iscl, iref, ibit)
Get information about a Table B descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1275
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:838
subroutine nemtbd(lun, itab, nseq, nems, irps, knts)
Get information about a Table D descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1343
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 strsuc(str1, str2, lens)
Remove leading and trailing blanks from a character string.
Definition: misc.F90:199
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 bitmaps internally within a data subset definition.
integer, dimension(:,:), allocatable inodtco
Entries within jump/link table which contain Table C operators.
integer ntamc
Number of Table A mnemonics in jump/link table (up to a maximum of mxtamc) which contain at least one...
integer, dimension(:), allocatable inodtamc
Entries within jump/link table which contain Table A mnemonics.
character *6, dimension(:,:), allocatable ctco
Table C operators corresponding to inodtco.
integer, dimension(:), allocatable ntco
Number of Table C operators (with an XX value of 21 or greater) within the data subset definition of ...
Declare an array used by subroutine makestab() to keep track of which logical units share DX BUFR tab...
integer, dimension(:), allocatable lus
Tracking index for each file ID.
Declare arrays used to store information about the current BUFR message that is in the process of bei...
integer, dimension(:), allocatable inode
Table A mnemonic for type of BUFR message.
Declare arrays used by various subroutines to hold information about Table D sequences.
integer, dimension(:,:), allocatable krp
Replication counts corresponding to nem:
integer, dimension(:,:), allocatable irp
Replication indicators corresponding to nem:
character *8, dimension(:,:), allocatable nem
Child mnemonics within Table D sequences.
Declare arrays and variables for use with any 2-03-YYY (change reference value) operators present wit...
integer, dimension(:), allocatable ienrv
End of entry range in jump/link table, within which the corresponding new reference value in nrv will...
character *8, dimension(:), allocatable tagnrv
Table B mnemonic to which the corresponding new reference value in nrv applies.
integer, dimension(:), allocatable isnrv
Start of entry range in jump/link table, within which the corresponding new reference value in nrv wi...
integer nnrv
Number of entries in the jump/link table which contain new reference values (up to a maximum of mxnrv...
integer *8, dimension(:), allocatable nrv
New reference values corresponding to inodnrv.
integer ipfnrv
A number between 1 and nnrv, denoting the first entry within the module arrays which applies to the c...
integer, dimension(:), allocatable inodnrv
Entries within jump/link table which contain new reference values.
integer ibtnrv
Number of bits in Section 4 occupied by each new reference value for the current 2-03-YYY operator in...
Declare arrays used to store file and message status indicators for all logical units that have been ...
integer, dimension(:), allocatable iolun
File status indicators.
integer, dimension(:), allocatable iomsg
Message status indicator corresponding to iolun, denoting whether a BUFR message is currently open wi...
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.
Declare variables for use with certain Table C operators in the internal jump/link table.
integer icsc
Number by which to modify the scale of subsequent jump/link table mnemonics whose type indicator is "...
integer icdw
Number of bits by which to modify the data width of subsequent jump/link table mnemonics whose type i...
integer icrv
Factor by which to multiply the reference value of subsequent jump/link table mnemonics whose type in...
integer incw
New data width (in bytes) for subsequent jump/link table mnemonics whose type indicator is "CHR"; set...
Declare arrays and variables used to store the internal jump/link table.
integer, dimension(:), allocatable jseq
Temporary storage used in expanding sequences.
integer, dimension(:), allocatable irf
Reference values corresponding to tag and typ:
integer, dimension(:,:), allocatable iseq
Temporary storage used in expanding sequences.
integer, dimension(:), allocatable isc
Scale factors corresponding to tag and typ:
integer, dimension(:), allocatable ibt
Bit widths corresponding to tag and typ:
integer, dimension(:), allocatable knt
Temporary storage used in calculating delayed replication counts.
real *8, dimension(:), allocatable vali
Initialized data values corresponding to typ:
character *3, dimension(:), allocatable typ
Type indicators corresponding to tag:
integer, dimension(:), allocatable jmpb
Jump backward indices corresponding to tag and typ:
character *10, dimension(:), allocatable tag
Mnemonics in the jump/link table.
integer ntab
Number of entries in the jump/link table.
integer, dimension(:), allocatable jump
Jump forward indices corresponding to tag and typ:
integer, dimension(:), allocatable itp
Integer type values corresponding to typ:
integer, dimension(:), allocatable link
Link indices corresponding to tag, typ and jmpb:
integer, dimension(:), allocatable knti
Initialized replication counts corresponding to typ and jump:
Declare arrays used to store data values and associated metadata for the current BUFR data subset in ...
integer, dimension(:), allocatable nval
Number of data values in BUFR data subset.
real *8, dimension(:,:), allocatable, target val
Data values.
integer, dimension(:,:), allocatable, target inv
Inventory pointer which links each data value to its corresponding node in the internal jump/link tab...
Declare an array used to track, for each file ID, whether the DX BUFR table associated with the corre...
logical, dimension(:), allocatable xtab
Tracking index 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...
recursive subroutine closmg(lunin)
Close the BUFR message that is currently open for writing within internal arrays associated with logi...
subroutine usrtpl(lun, invn, nbmp)
Expand a subset template within internal arrays.
subroutine strcln
Reset the internal mnemonic string cache.
Definition: strings.F90:116
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