NCEPLIBS-bufr  12.3.0
readwritesb.F90
Go to the documentation of this file.
1 
5 
31 recursive subroutine readsb(lunit,iret)
32 
33  use bufrlib
34 
35  use modv_vars, only: im8b
36 
37  use moda_msgcwd
38  use moda_unptyp
39  use moda_bitbuf
40  use moda_bitmaps
41  use moda_stcode
42 
43  implicit none
44 
45  integer, intent(in) :: lunit
46  integer, intent(out) :: iret
47  integer my_lunit, lun, il, im, ier, nbyt, bort_target_set
48 
49  ! Check for I8 integers
50 
51  if(im8b) then
52  im8b=.false.
53  call x84(lunit,my_lunit,1)
54  call readsb(my_lunit,iret)
55  call x48(iret,iret,1)
56  im8b=.true.
57  return
58  endif
59 
60  ! If we're catching bort errors, set a target return location if one doesn't already exist.
61 
62  if (bort_target_set() == 1) then
63  call catch_bort_readsb_c(lunit,iret)
65  return
66  endif
67 
68  iret = -1
69 
70  ! Check the file status
71 
72  call status(lunit,lun,il,im)
73  if(il==0) call bort('BUFRLIB: READSB - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR INPUT')
74  if(il>0) call bort('BUFRLIB: READSB - INPUT BUFR FILE IS OPEN FOR OUTPUT, IT MUST BE OPEN FOR INPUT')
75  if(im==0) return
76 
77  ! See if there is another subset in the message
78 
79  if(nsub(lun)==msub(lun)) return
80  nsub(lun) = nsub(lun) + 1
81 
82  ! Read the next subset and reset the pointers
83 
84  nbtm = 0
85  lstnod = 0
86  lstnodct = 0
87  iscodes(lun) = 0
88  linbtm = .false.
89 
90  if(msgunp(lun)==0) then
91  ibit = mbyt(lun)*8
92  call upb(nbyt,16,mbay(1,lun),ibit)
93  call rdtree(lun,ier)
94  if(ier/=0) return
95  mbyt(lun) = mbyt(lun) + nbyt
96  elseif(msgunp(lun)==1) then
97  ! message with "standard" Section 3
98  ibit = mbyt(lun)
99  call rdtree(lun,ier)
100  if(ier/=0) return
101  mbyt(lun) = ibit
102  else
103  ! compressed message
104  call rdcmps(lun)
105  if (iscodes(lun) /= 0) return
106  endif
107 
108  iret = 0
109 
110  return
111 end subroutine readsb
112 
124 recursive integer function ireadsb(lunit) result(iret)
125 
126  use modv_vars, only: im8b
127 
128  implicit none
129 
130  integer, intent(in) :: lunit
131  integer my_lunit
132 
133  ! Check for I8 integers.
134 
135  if(im8b) then
136  im8b=.false.
137  call x84(lunit,my_lunit,1)
138  iret=ireadsb(my_lunit)
139  im8b=.true.
140  return
141  endif
142 
143  call readsb(lunit,iret)
144 
145  return
146 end function ireadsb
147 
173 recursive subroutine readns(lunit,subset,jdate,iret)
174 
175  use bufrlib
176 
177  use modv_vars, only: im8b, lendat
178 
179  use moda_msgcwd
180  use moda_tables
181 
182  implicit none
183 
184  integer, intent(in) :: lunit
185  integer, intent(out) :: jdate, iret
186  integer my_lunit, lun, il, im, bort_target_set
187 
188  character*8, intent(out) :: subset
189  character*9 csubset
190 
191  ! Check for I8 integers
192 
193  if(im8b) then
194  im8b=.false.
195  call x84(lunit,my_lunit,1)
196  call readns(my_lunit,subset,jdate,iret)
197  call x48(jdate,jdate,1)
198  call x48(iret,iret,1)
199  im8b=.true.
200  return
201  endif
202 
203  ! If we're catching bort errors, set a target return location if one doesn't already exist.
204 
205  if (bort_target_set() == 1) then
206  call catch_bort_readns_c(lunit,csubset,jdate,len(csubset),iret)
207  subset(1:8) = csubset(1:8)
208  call bort_target_unset
209  return
210  endif
211 
212  ! Refresh the subset and jdate parameters
213 
214  call status(lunit,lun,il,im)
215  if(il==0) call bort('BUFRLIB: READNS - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR INPUT')
216  if(il>0) call bort('BUFRLIB: READNS - INPUT BUFR FILE IS OPEN FOR OUTPUT, IT MUST BE OPEN FOR INPUT')
217  if(inode(lun)==0) then
218  subset = ' '
219  else
220  subset = tag(inode(lun))(1:8)
221  endif
222  jdate = idate(lun)
223  if (lendat/=10) jdate = mod(jdate,10**8)
224 
225  ! Read the next subset in the BUFR file
226 
227  do while (.true.)
228  call readsb(lunit,iret)
229  if (iret==0) exit
230  call readmg(lunit,subset,jdate,iret)
231  if (iret/=0) exit
232  enddo
233 
234  return
235 end subroutine readns
236 
255 recursive integer function ireadns(lunit,subset,idate) result(iret)
256 
257  use modv_vars, only: im8b
258 
259  implicit none
260 
261  integer, intent(in) :: lunit
262  integer, intent(out) :: idate
263  integer my_lunit
264 
265  character*8, intent(out) :: subset
266 
267  ! Check for I8 integers.
268 
269  if(im8b) then
270  im8b=.false.
271  call x84(lunit,my_lunit,1)
272  iret=ireadns(my_lunit,subset,idate)
273  call x48(idate,idate,1)
274  im8b=.true.
275  return
276  endif
277 
278  call readns(lunit,subset,idate,iret)
279 
280  return
281 end function ireadns
282 
317 recursive subroutine writsb(lunit)
318 
319  use bufrlib
320 
321  use modv_vars, only: im8b
322 
323  use moda_msgcmp
324 
325  implicit none
326 
327  integer, intent(in) :: lunit
328  integer my_lunit, lun, il, im, bort_target_set
329 
330  ! Check for I8 integers
331 
332  if(im8b) then
333  im8b=.false.
334  call x84(lunit,my_lunit,1)
335  call writsb(my_lunit)
336  im8b=.true.
337  return
338  endif
339 
340  ! If we're catching bort errors, set a target return location if one doesn't already exist.
341 
342  if (bort_target_set() == 1) then
343  call catch_bort_writsb_c(lunit)
344  call bort_target_unset
345  return
346  endif
347 
348  ! Check the file status
349 
350  call status(lunit,lun,il,im)
351  if(il==0) call bort('BUFRLIB: WRITSB - OUTPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR OUTPUT')
352  if(il<0) call bort('BUFRLIB: WRITSB - OUTPUT BUFR FILE IS OPEN FOR INPUT, IT MUST BE OPEN FOR OUTPUT')
353  if(im==0) call bort('BUFRLIB: WRITSB - A MESSAGE MUST BE OPEN IN OUTPUT BUFR FILE, NONE ARE')
354 
355  ! Pack up the subset and put it into the message
356 
357  call wrtree(lun)
358  if( ccmf=='Y' ) then
359  call wrcmps(lunit)
360  else
361  call msgupd(lunit,lun)
362  endif
363 
364  return
365 end subroutine writsb
366 
445 recursive subroutine writsa(lunxx,lmsgt,msgt,msgl)
446 
447  use bufrlib
448 
449  use modv_vars, only: im8b
450 
451  use moda_bufrmg
452  use moda_msgcmp
453 
454  implicit none
455 
456  integer, intent(in) :: lunxx, lmsgt
457  integer, intent(out) :: msgt(*), msgl
458  integer my_lunxx, my_lmsgt, lunit, lun, il, im, n, bort_target_set
459 
460  ! Check for I8 integers
461 
462  if(im8b) then
463  im8b=.false.
464  call x84(lunxx,my_lunxx,1)
465  call x84(lmsgt,my_lmsgt,1)
466  call writsa(my_lunxx, my_lmsgt*2, msgt, msgl)
467  msgl = msgl/2
468  call x48(msgl,msgl,1)
469  im8b=.true.
470  return
471  endif
472 
473  ! If we're catching bort errors, set a target return location if one doesn't already exist.
474 
475  if (bort_target_set() == 1) then
476  call catch_bort_writsa_c(lunxx,lmsgt,msgt,msgl)
477  call bort_target_unset
478  return
479  endif
480 
481  lunit = abs(lunxx)
482 
483  ! Check the file status
484 
485  call status(lunit,lun,il,im)
486  if(il==0) call bort('BUFRLIB: WRITSA - OUTPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR OUTPUT')
487  if(il<0) call bort('BUFRLIB: WRITSA - OUTPUT BUFR FILE IS OPEN FOR INPUT, IT MUST BE OPEN FOR OUTPUT')
488  if(im==0) call bort('BUFRLIB: WRITSA - A MESSAGE MUST BE OPEN IN OUTPUT BUFR FILE, NONE ARE')
489 
490  ! If lunxx < 0, force memory msg to be written (w/o any current subset)
491 
492  if(lunxx<0) call closmg(lunit)
493 
494  ! Is there a completed BUFR message to be returned?
495 
496  if(msglen(lun)>0) then
497  if(msglen(lun)>lmsgt) call bort('BUFRLIB: WRITSA - OVERFLOW OF OUTPUT BUFR MESSAGE ARRAY; TRY A LARGER '// &
498  'DIMENSION FOR THIS ARRAY')
499  msgl = msglen(lun)
500  do n=1,msgl
501  msgt(n) = msgtxt(n,lun)
502  enddo
503  msglen(lun) = 0
504  else
505  msgl = 0
506  endif
507 
508  if(lunxx<0) return
509 
510  ! Pack up the subset and put it into the message
511 
512  call wrtree(lun)
513  if( ccmf=='Y' ) then
514  call wrcmps(lunit)
515  else
516  call msgupd(lunit,lun)
517  endif
518 
519  ! If the just-completed call to wrcmps() or msgupd() for this subset caused a message to be flushed to abs(lunxx), then
520  ! attempt to retrieve and return that message now. Otherwise, we run the risk that the next call to openmb() or openmg()
521  ! might cause another message to be flushed, and thus overwrite the current message within array msgtxt before we
522  ! had the chance to retrieve it during the next call to writsa().
523 
524  ! Also note that, in rare instances (e.g. if the byte count of the most recent subset is > 65530), we could end up with
525  ! two BUFR messages available to be returned from this one call to writsa(). If sufficient space is available in the
526  ! msgt array, then go ahead and return both messages now.
527 
528  if( (msglen(lun)>0) .and. (msgl+msglen(lun)<=lmsgt) ) then
529  do n = 1,msglen(lun)
530  msgt(msgl+n) = msgtxt(n,lun)
531  enddo
532  msgl = msgl+msglen(lun)
533  msglen(lun) = 0
534  endif
535 
536  return
537 end subroutine writsa
538 
566 recursive subroutine rdmgsb(lunit,imsg,isub)
567 
568  use bufrlib
569 
570  use modv_vars, only: im8b
571 
572  use moda_msgcwd
573  use moda_bitbuf
574 
575  implicit none
576 
577  integer, intent(in) :: lunit, imsg, isub
578  integer my_lunit, my_imsg, my_isub, lun, il, im, i, jdate, iret, bort_target_set
579 
580  character*128 bort_str
581  character*8 subset
582 
583  ! Check for I8 integers
584 
585  if(im8b) then
586  im8b=.false.
587  call x84(lunit,my_lunit,1)
588  call x84(imsg,my_imsg,1)
589  call x84(isub,my_isub,1)
590  call rdmgsb(my_lunit,my_imsg,my_isub)
591  im8b=.true.
592  return
593  endif
594 
595  ! If we're catching bort errors, set a target return location if one doesn't already exist.
596 
597  if (bort_target_set() == 1) then
598  call catch_bort_rdmgsb_c(lunit,imsg,isub)
599  call bort_target_unset
600  return
601  endif
602 
603  ! Open the file and skip to message #imsg
604 
605  call openbf(lunit,'IN',lunit)
606  call status(lunit,lun,il,im)
607 
608  ! Note that we need to use subroutine readmg() to actually read in all of the messages (including the
609  ! first (imsg-1) messages!), just in case there are any embedded dictionary messages in the file.
610 
611  do i=1,imsg
612  call readmg(lunit,subset,jdate,iret)
613  if(iret<0) then
614  write(bort_str,'("BUFRLIB: RDMGSB - HIT END OF FILE BEFORE READING REQUESTED MESSAGE NO.",I5," IN '//&
615  'BUFR FILE CONNECTED TO UNIT",I4)') imsg,lunit
616  call bort(bort_str)
617  endif
618  enddo
619 
620  ! Position at subset #isub
621 
622  do i=1,isub
623  call readsb(lunit,iret)
624  if(iret<0) then
625  write(bort_str,'("BUFRLIB: RDMGSB - ALL SUBSETS READ BEFORE READING REQ. SUBSET NO.",I3," IN '// &
626  'REQ. MSG NO.",I5," IN BUFR FILE CONNECTED TO UNIT",I4)') isub,imsg,lunit
627  call bort(bort_str)
628  endif
629  enddo
630 
631  return
632 end subroutine rdmgsb
633 
651 subroutine msgupd(lunit,lun)
652 
653  use modv_vars, only: iprt, nby0, nby1, nby2, nby3
654 
655  use moda_msgcwd
656  use moda_bitbuf
657  use moda_h4wlc
658 
659  implicit none
660 
661  integer, intent(in) :: lunit, lun
662  integer ibyt, lbyt, lbit, nbyt, ii, iupb
663 
664  logical msgfull
665 
666  character*128 errstr
667 
668  ! Pad the subset buffer
669 
670  call pad(ibay,ibit,ibyt,8)
671 
672  ! Check whether the new subset should be written into the currently open message
673 
674  if(msgfull(mbyt(lun),ibyt,maxbyt) .or. ((ibyt>65530).and.(nsub(lun)>0))) then
675  ! No it should not, either because it doesn't fit
676  ! OR
677  ! It has byte count > 65530 (sufficiently close to the upper limit for the 16 bit byte counter placed at the beginning
678  ! of each subset), and the current message has at least one subset in it
679  !
680  ! In either of these cases, we need to write out the current message and then create a new one to hold the current subset
681  call msgwrt(lunit,mbay(1,lun),mbyt(lun))
682  call msgini(lun)
683  endif
684 
685  if(msgfull(mbyt(lun),ibyt,maxbyt)) then
686  ! This is an overlarge subset that won't fit in any message given the current value of maxbyt, so discard the subset
687  ! and exit gracefully.
688  if(iprt>=0) then
689  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
690  write ( unit=errstr, fmt='(A,A,I7,A)') 'BUFRLIB: MSGUPD - SUBSET LONGER THAN ANY POSSIBLE MESSAGE ', &
691  '{MAXIMUM MESSAGE LENGTH = ', maxbyt, '}'
692  call errwrt(errstr)
693  call errwrt('>>>>>>>OVERLARGE SUBSET DISCARDED FROM FILE<<<<<<<<')
694  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
695  call errwrt(' ')
696  endif
697  call usrtpl(lun,1,1)
698  return
699  endif
700 
701  ! Set a byte count and transfer the subset buffer into the message
702 
703  lbit = 0
704  call pkb(ibyt,16,ibay,lbit)
705 
706  ! Note that we want to append the data for this subset to the end of Section 4, but the value in mbyt(lun) already includes
707  ! the length of Section 5 (i.e. 4 bytes). Therefore, we need to begin writing at the point 3 bytes prior to the byte
708  ! currently pointed to by mbyt(lun).
709 
710  call mvb(ibay,1,mbay(1,lun),mbyt(lun)-3,ibyt)
711 
712  ! Update the subset and byte counters
713 
714  mbyt(lun) = mbyt(lun) + ibyt
715  nsub(lun) = nsub(lun) + 1
716 
717  lbit = (nby0+nby1+nby2+4)*8
718  call pkb(nsub(lun),16,mbay(1,lun),lbit)
719 
720  lbyt = nby0+nby1+nby2+nby3
721  nbyt = iupb(mbay(1,lun),lbyt+1,24)
722  lbit = lbyt*8
723  call pkb(nbyt+ibyt,24,mbay(1,lun),lbit)
724 
725  ! If any long character strings are being held internally for storage into this subset, store them now
726 
727  if(nh4wlc>0) then
728  do ii = 1, nh4wlc
729  call writlc(luh4wlc(ii),chh4wlc(ii),sth4wlc(ii))
730  enddo
731  nh4wlc = 0
732  endif
733 
734  ! If the subset byte count is > 65530, then give it its own one-subset message (cannot have any other subsets in this
735  ! message because their beginning would be beyond the upper limit of 65535 in the 16-bit byte counter, meaning they
736  ! could not be located!)
737 
738  if(ibyt>65530) then
739  if(iprt>=1) then
740  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
741  write ( unit=errstr, fmt='(A,I7,A,A)') 'BUFRLIB: MSGUPD - SUBSET HAS BYTE COUNT = ',ibyt,' > UPPER LIMIT OF 65535'
742  call errwrt(errstr)
743  call errwrt('>>>>>>>WILL BE WRITTEN INTO ITS OWN MESSAGE<<<<<<<<')
744  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
745  call errwrt(' ')
746  endif
747  call msgwrt(lunit,mbay(1,lun),mbyt(lun))
748  call msgini(lun)
749  endif
750 
751  ! Reset the user arrays
752 
753  call usrtpl(lun,1,1)
754 
755  return
756 end subroutine msgupd
757 
787 subroutine pad(ibay,ibit,ibyt,ipadb)
788 
789  implicit none
790 
791  integer, intent(inout) :: ibay(*), ibit
792  integer, intent(in) :: ipadb
793  integer, intent(out) :: ibyt
794  integer ipad
795 
796  character*128 bort_str
797 
798  ! Pad the subset to an ipadb bit boundary
799 
800  ipad = ipadb - mod(ibit+8,ipadb)
801  ! First pack the # of bits being padded (this is a delayed replication factor)
802  call pkb(ipad,8,ibay,ibit)
803  ! Now pad with zeroes to the byte boundary
804  call pkb(0,ipad,ibay,ibit)
805  ibyt = ibit/8
806 
807  if(mod(ibit,8)/=0) then
808  write(bort_str,'("BUFRLIB: PAD - THE NUMBER OF BITS IN A PACKED'// &
809  ' SUBSET AFTER PADDING (",I8,") IS NOT A MULTIPLE OF 8")') ibit
810  call bort(bort_str)
811  endif
812 
813  return
814 end subroutine pad
815 
841 recursive integer function lcmgdf(lunit,subset) result(iret)
842 
843  use bufrlib
844 
845  use modv_vars, only: im8b
846 
847  use moda_tables
848 
849  implicit none
850 
851  integer, intent(in) :: lunit
852  integer my_lunit, lun, il, im, mtyp, msbt, inod, nte, i, lcs, bort_target_set
853 
854  character*8, intent(in) :: subset
855  character*9 csubset
856 
857  ! Check for I8 integers.
858 
859  if(im8b) then
860  im8b=.false.
861  call x84(lunit,my_lunit,1)
862  iret=lcmgdf(my_lunit,subset)
863  im8b=.true.
864  return
865  endif
866 
867  ! If we're catching bort errors, set a target return location if one doesn't already exist.
868 
869  if (bort_target_set() == 1) then
870  call strsuc(subset,csubset,lcs)
871  call catch_bort_lcmgdf_c(lunit,csubset,lcs,iret)
872  call bort_target_unset
873  return
874  endif
875 
876  iret = 0
877 
878  ! Get lun from lunit.
879 
880  call status(lunit,lun,il,im)
881  if (il==0) call bort('BUFRLIB: LCMGDF - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN')
882 
883  ! Confirm that subset is defined for this logical unit.
884 
885  call nemtba(lun,subset,mtyp,msbt,inod)
886 
887  ! Check if there's a long character string in the definition.
888 
889  nte = isc(inod)-inod
890 
891  do i = 1, nte
892  if ( (typ(inod+i)=='CHR') .and. (ibt(inod+i)>64) ) then
893  iret = 1
894  return
895  endif
896  enddo
897 
898  iret = 0
899 
900  return
901 end function lcmgdf
902 
927 recursive subroutine ufbpos(lunit,irec,isub,subset,jdate)
928 
929  use bufrlib
930 
931  use modv_vars, only: im8b
932 
933  use moda_msgcwd
934  use moda_bitbuf
935 
936  implicit none
937 
938  integer, intent(in) :: lunit, irec, isub
939  integer, intent(out) :: jdate
940  integer my_lunit, my_irec, my_isub, lun, il, im, jrec, jsub, iret, bort_target_set
941 
942  character*128 bort_str
943  character*9 csubset
944  character*8, intent(out) :: subset
945 
946  ! Check for I8 integers
947 
948  if(im8b) then
949  im8b=.false.
950  call x84(lunit,my_lunit,1)
951  call x84(irec,my_irec,1)
952  call x84(isub,my_isub,1)
953  call ufbpos(my_lunit,my_irec,my_isub,subset,jdate)
954  call x48(jdate,jdate,1)
955  im8b=.true.
956  return
957  endif
958 
959  ! If we're catching bort errors, set a target return location if one doesn't already exist.
960 
961  if (bort_target_set() == 1) then
962  call catch_bort_ufbpos_c(lunit,irec,isub,csubset,jdate,len(csubset))
963  subset(1:8) = csubset(1:8)
964  call bort_target_unset
965  return
966  endif
967 
968  ! Make sure a file is open for input
969 
970  call status(lunit,lun,il,im)
971  if(il==0) call bort('BUFRLIB: UFBPOS - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR INPUT')
972  if(il>0) call bort('BUFRLIB: UFBPOS - INPUT BUFR FILE IS OPEN FOR OUTPUT, IT MUST BE OPEN FOR INPUT')
973 
974  if(irec<=0) then
975  write(bort_str,'("BUFRLIB: UFBPOS - REQUESTED MESSAGE NUMBER TO READ IN (",I5,") IS NOT VALID")') irec
976  call bort(bort_str)
977  endif
978  if(isub<=0) then
979  write(bort_str,'("BUFRLIB: UFBPOS - REQUESTED SUBSET NUMBER TO READ IN (",I5,") IS NOT VALID")') isub
980  call bort(bort_str)
981  endif
982 
983  ! See where pointers are currently located
984 
985  call ufbcnt(lunit,jrec,jsub)
986 
987  ! Rewind file if requested pointers are behind current pointers
988 
989  if(irec<jrec .or. (irec==jrec.and.isub<jsub)) then
990  call cewind_c(lun)
991  nmsg(lun) = 0
992  nsub(lun) = 0
993  call ufbcnt(lunit,jrec,jsub)
994  endif
995 
996  ! Read subset #isub from message #irec from file
997 
998  do while (irec>jrec)
999  call readmg(lunit,subset,jdate,iret)
1000  if(iret<0) then
1001  write(bort_str,'("BUFRLIB: UFBPOS - REQUESTED MESSAGE NUMBER '// &
1002  'TO READ IN (",I5,") EXCEEDS THE NUMBER OF MESSAGES IN THE FILE (",I5,")")') irec, jrec
1003  call bort(bort_str)
1004  endif
1005  call ufbcnt(lunit,jrec,jsub)
1006  enddo
1007 
1008  do while (isub>jsub)
1009  call readsb(lunit,iret)
1010  if(iret/=0) then
1011  write(bort_str,'("BUFRLIB: UFBPOS - REQ. SUBSET NUMBER TO READ'// &
1012  ' IN (",I5,") EXCEEDS THE NUMBER OF SUBSETS (",I5,") IN THE REQ. MESSAGE (",I5,")")') isub, jsub, irec
1013  call bort(bort_str)
1014  endif
1015  call ufbcnt(lunit,jrec,jsub)
1016  enddo
1017 
1018  return
1019 end subroutine ufbpos
1020 
1032 subroutine rdtree(lun,iret)
1033 
1034  use modv_vars, only: bmiss
1035 
1036  use moda_usrint
1037  use moda_usrbit
1038  use moda_ival
1039  use moda_bitbuf
1040  use moda_tables
1041 
1042  implicit none
1043 
1044  integer, intent(in) :: lun
1045  integer, intent(out) :: iret
1046  integer ier, n, node, kbit, nbt, icbfms, igetrfel
1047 
1048  character*8 cval
1049 
1050  real*8 rval, ups
1051 
1052  equivalence(cval,rval)
1053 
1054  iret = 0
1055 
1056  ! Cycle through a subset setting up the template
1057 
1058  mbit(1) = ibit
1059  nbit(1) = 0
1060  call rcstpl(lun,ier)
1061  if(ier/=0) then
1062  iret = -1
1063  return
1064  endif
1065 
1066  ! Loop through each element of the subset, unpacking each value and then converting it to the proper type
1067 
1068  do n=1,nval(lun)
1069  call upb8(ival(n),nbit(n),mbit(n),mbay(1,lun))
1070  node = inv(n,lun)
1071  if(itp(node)==1) then
1072  ! The unpacked value is a delayed descriptor replication factor.
1073  val(n,lun) = ival(n)
1074  elseif(itp(node)==2) then
1075  ! The unpacked value is a real.
1076  nrfelm(n,lun) = igetrfel(n,lun)
1077  if (ival(n)<2_8**ibt(node)-1) then
1078  val(n,lun) = ups(ival(n),node)
1079  else
1080  val(n,lun) = bmiss
1081  endif
1082  elseif(itp(node)==3) then
1083  ! The value is a character string, so unpack it using an equivalenced real*8 value. Note that a maximum of 8 characters
1084  ! will be unpacked here, so a separate subsequent call to subroutine readlc() will be needed to fully unpack any string
1085  ! longer than 8 characters.
1086  cval = ' '
1087  kbit = mbit(n)
1088  nbt = min(8,nbit(n)/8)
1089  call upc(cval,nbt,mbay(1,lun),kbit,.true.)
1090  if (nbit(n)<=64 .and. icbfms(cval,nbt)/=0) then
1091  val(n,lun) = bmiss
1092  else
1093  val(n,lun) = rval
1094  endif
1095  endif
1096  enddo
1097 
1098  ibit = nbit(nval(lun))+mbit(nval(lun))
1099 
1100  return
1101 end subroutine rdtree
1102 
1111 subroutine wrtree(lun)
1112 
1113  use moda_usrint
1114  use moda_ival
1115  use moda_ufbcpl
1116  use moda_bitbuf
1117  use moda_tables
1118 
1119  implicit none
1120 
1121  integer, intent(in) :: lun
1122  integer*8 ipks
1123  integer n, node, nbit, ncr, numchr, jj, ibfms, igetrfel, imrkopr
1124 
1125  character*120 lstr
1126  character*8 cval
1127 
1128  real*8 rval
1129 
1130  equivalence(cval,rval)
1131 
1132  ! Convert user numbers into scaled integers
1133 
1134  do n=1,nval(lun)
1135  node = inv(n,lun)
1136  nrfelm(n,lun) = igetrfel(n,lun)
1137  if(itp(node)==1) then
1138  ival(n) = nint(val(n,lun))
1139  elseif(typ(node)=='NUM') then
1140  if( (ibfms(val(n,lun))==1) .or. (val(n,lun)/=val(n,lun)) ) then
1141  ! The user number is either "missing" or NaN.
1142  ival(n) = -1
1143  else
1144  ival(n) = ipks(val(n,lun),node)
1145  endif
1146  call strbtm(n,lun,int(ival(n)))
1147  endif
1148  enddo
1149 
1150  ! Pack the user array into the subset buffer
1151 
1152  ibit = 16
1153 
1154  do n=1,nval(lun)
1155  node = inv(n,lun)
1156  if(itp(node)<3) then
1157  ! The value to be packed is numeric.
1158  if ( imrkopr(tag(node)) == 1 ) then
1159  nbit = ibt(inv(nrfelm(n,lun),lun))
1160  else
1161  nbit = ibt(node)
1162  endif
1163  call pkb8(ival(n),nbit,ibay,ibit)
1164  else
1165  ! The value to be packed is a character string.
1166  ncr=ibt(node)/8
1167  if ( ncr>8 .and. luncpy(lun)/=0 ) then
1168  ! The string is longer than 8 characters and there was a preceeding call to ufbcpy() involving this output unit,
1169  ! so read the long string with readlc() and then write it into the output buffer using pkc().
1170  call readlc(luncpy(lun),lstr,tag(node))
1171  call pkc(lstr,ncr,ibay,ibit)
1172  else
1173  rval = val(n,lun)
1174  if(ibfms(rval)/=0) then
1175  ! The value is "missing", so set all bits to 1 before packing the field as a character string.
1176  numchr = min(ncr,len(lstr))
1177  do jj = 1, numchr
1178  call ipkm(lstr(jj:jj),1,255)
1179  enddo
1180  call pkc(lstr,numchr,ibay,ibit)
1181  else
1182  ! The value is not "missing", so pack the equivalenced character string. Note that a maximum of 8 characters
1183  ! will be packed here, so a separate subsequent call to subroutine writlc() will be needed to fully encode any
1184  ! string longer than 8 characters.
1185  call pkc(cval,ncr,ibay,ibit)
1186  endif
1187  endif
1188  endif
1189  enddo
1190 
1191  ! Reset ufbcpy() file pointer
1192 
1193  luncpy(lun)=0
1194 
1195  return
1196 end subroutine wrtree
1197 
1210 subroutine rcstpl(lun,iret)
1211 
1212  use modv_vars, only: maxjl, maxss, maxrcr, iprt
1213 
1214  use moda_usrint
1215  use moda_usrbit
1216  use moda_msgcwd
1217  use moda_bitbuf
1218  use moda_tables
1219  use moda_usrtmp
1220 
1221  implicit none
1222 
1223  character*128 bort_str
1224 
1225  integer, intent(in) :: lun
1226  integer, intent(out) :: iret
1227  integer nbmp(2,maxrcr), newn(2,maxrcr), knx(maxrcr), nodi, node, mbmp, nr, i, j, n, nn, n1, n2, new, ivob, igetrfel
1228 
1229  iret = 0
1230 
1231  ! Set the initial values for the template
1232 
1233  inv(1,lun) = inode(lun)
1234  val(1,lun) = 0
1235  nbmp(1,1) = 1
1236  nbmp(2,1) = 1
1237  nodi = inode(lun)
1238  node = inode(lun)
1239  mbmp = 1
1240  nval(lun) = 1
1241  nr = 0
1242  knx(1:maxrcr) = 0
1243 
1244  outer: do while (.true.)
1245 
1246  ! Set up the parameters for a level of recursion
1247 
1248  nr = nr+1
1249  if(nr>maxrcr) then
1250  write(bort_str,'("BUFRLIB: RCSTPL - THE NUMBER OF RECURSION LEVELS EXCEEDS THE LIMIT (",I3,")")') maxrcr
1251  call bort(bort_str)
1252  endif
1253  nbmp(1,nr) = 1
1254  nbmp(2,nr) = mbmp
1255 
1256  n1 = iseq(node,1)
1257  n2 = iseq(node,2)
1258  if(n1==0) then
1259  write(bort_str,'("BUFRLIB: RCSTPL - UNSET EXPANSION SEGMENT ",A)') tag(nodi)
1260  call bort(bort_str)
1261  endif
1262  if(n2-n1+1>maxjl) then
1263  if(iprt>=0) then
1264  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1265  call errwrt('BUFRLIB: RCSTPL - MAXJL OVERFLOW; SUBSET SKIPPED')
1266  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1267  endif
1268  iret = -1
1269  return
1270  endif
1271  newn(1,nr) = 1
1272  newn(2,nr) = n2-n1+1
1273 
1274  do n=1,newn(2,nr)
1275  nn = jseq(n+n1-1)
1276  iutmp(n,nr) = nn
1277  vutmp(n,nr) = vali(nn)
1278  enddo
1279 
1280  do while (.true.)
1281 
1282  ! Store nodes at some recursion level
1283 
1284  do i=nbmp(1,nr),nbmp(2,nr)
1285  if(knx(nr)==0) knx(nr) = nval(lun)
1286  if(i>nbmp(1,nr)) newn(1,nr) = 1
1287  do j=newn(1,nr),newn(2,nr)
1288  if(nval(lun)+1>maxss) then
1289  if(iprt>=0) then
1290  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1291  call errwrt('BUFRLIB: RCSTPL - MAXSS OVERFLOW; SUBSET SKIPPED')
1292  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1293  endif
1294  iret = -1
1295  return
1296  endif
1297  nval(lun) = nval(lun)+1
1298  node = iutmp(j,nr)
1299  ! inv is positional index in internal jump/link table for packed subset element nval(lun) in mbay
1300  inv(nval(lun),lun) = node
1301  ! mbit is the bit in mbay pointing to where the packed subset element nval(lun) begins
1302  mbit(nval(lun)) = mbit(nval(lun)-1)+nbit(nval(lun)-1)
1303  ! nbit is the number of bits in mbay occupied by packed subset element nval(lun)
1304  nrfelm(nval(lun),lun) = igetrfel(nval(lun),lun)
1305  nbit(nval(lun)) = ibt(node)
1306  if(nbit(nval(lun))==1) then
1307  ! Check whether this is a bitmap entry
1308  call upbb(ivob,nbit(nval(lun)),mbit(nval(lun)),mbay(1,lun))
1309  call strbtm(nval(lun),lun,ivob)
1310  endif
1311  ! Actual unpacked subset values are initialized here
1312  val(nval(lun),lun) = vutmp(j,nr)
1313  if(itp(node)==1) then
1314  call upbb(mbmp,nbit(nval(lun)),mbit(nval(lun)),mbay(1,lun))
1315  newn(1,nr) = j+1
1316  nbmp(1,nr) = i
1317  cycle outer
1318  endif
1319  enddo
1320  new = nval(lun)-knx(nr)
1321  val(knx(nr)+1,lun) = val(knx(nr)+1,lun) + new
1322  knx(nr) = 0
1323  enddo
1324 
1325  ! Check if we need to continue one recursion level back
1326 
1327  if(nr-1 == 0) exit outer
1328  nr = nr-1
1329  enddo
1330 
1331  enddo outer
1332 
1333  return
1334 end subroutine rcstpl
1335 
1346 subroutine usrtpl(lun,invn,nbmp)
1347 
1348  use modv_vars, only: maxjl, maxss, iprt
1349 
1350  use moda_usrint
1351  use moda_msgcwd
1352  use moda_tables
1353  use moda_ivttmp
1354  use moda_stcode
1355 
1356  implicit none
1357 
1358  integer, intent(in) :: lun, invn, nbmp
1359  integer i, j, ival, jval, n, n1, n2, nodi, node, newn, invr, knvn
1360 
1361  character*128 bort_str, errstr
1362 
1363  logical drp, drs, drb, drx
1364 
1365  if(iprt>=2) then
1366  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1367  write ( unit=errstr, fmt='(A,I3,A,I7,A,I5,A,A10)' ) &
1368  'BUFRLIB: USRTPL - LUN:INVN:NBMP:TAG(INODE(LUN)) = ', lun, ':', invn, ':', nbmp, ':', tag(inode(lun))
1369  call errwrt(errstr)
1370  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1371  call errwrt(' ')
1372  endif
1373 
1374  if(nbmp<=0) then
1375  if(iprt>=1) then
1376  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1377  call errwrt(.LE.'BUFRLIB: USRTPL - NBMP 0 - IMMEDIATE RETURN')
1378  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1379  call errwrt(' ')
1380  endif
1381  return
1382  endif
1383 
1384  drp = .false.
1385  drs = .false.
1386  drx = .false.
1387 
1388  ! Set up a node expansion
1389 
1390  if(invn==1) then
1391  ! The node is a Table A mnemonic
1392  nodi = inode(lun)
1393  inv(1,lun) = nodi
1394  nval(lun) = 1
1395  if(nbmp/=1) then
1396  write(bort_str,'("BUFRLIB: USRTPL - THIRD ARGUMENT (INPUT) = ",'// &
1397  'I4,", MUST BE 1 WHEN SECOND ARGUMENT (INPUT) IS 1 (SUBSET NODE) (",A,")")') nbmp, tag(nodi)
1398  call bort(bort_str)
1399  endif
1400  elseif(invn>0 .and. invn<=nval(lun)) then
1401  ! The node is (hopefully) a delayed replication factor
1402  nodi = inv(invn,lun)
1403  drp = typ(nodi) == 'DRP'
1404  drs = typ(nodi) == 'DRS'
1405  drb = typ(nodi) == 'DRB'
1406  drx = drp .or. drs .or. drb
1407  ival = nint(val(invn,lun))
1408  jval = 2**ibt(nodi)-1
1409  val(invn,lun) = ival+nbmp
1410  if(drb.and.nbmp/=1) then
1411  write(bort_str,'("BUFRLIB: USRTPL - THIRD ARGUMENT (INPUT) = ",'// &
1412  'I4,", MUST BE 1 WHEN NODE IS DRB (1-BIT DELAYED REPL. FACTOR) (",A,")")') nbmp, tag(nodi)
1413  call bort(bort_str)
1414  endif
1415  if(.not.drx) then
1416  write(bort_str,'("BUFRLIB: USRTPL - NODE IS OF TYPE ",A," - IT '// &
1417  'MUST BE EITHER A SUBSET OR DELAYED REPL. FACTOR (",A,")")') typ(nodi), tag(nodi)
1418  call bort(bort_str)
1419  endif
1420  if(ival<0) then
1421  write(bort_str,'("BUFRLIB: USRTPL - REPLICATION FACTOR IS NEGATIVE (=",I5,") (",A,")")') ival, tag(nodi)
1422  call bort(bort_str)
1423  endif
1424  if(ival+nbmp>jval) then
1425  write(bort_str,'("BUFRLIB: USRTPL - REPLICATION FACTOR OVERFLOW (EXCEEDS MAXIMUM OF",I6," (",A,")")') jval, tag(nodi)
1426  call errwrt(bort_str)
1427  iscodes(lun) = 1
1428  return
1429  endif
1430  else
1431  write(bort_str,'("BUFRLIB: USRTPL - INVENTORY INDEX {FIRST '// &
1432  'ARGUMENT (INPUT)} OUT OF BOUNDS (=",I5,", RANGE IS 1 TO",I6,") ")') invn, nval(lun)
1433  call bort(bort_str)
1434  endif
1435 
1436  ! Recall a pre-fab node expansion segment
1437 
1438  newn = 0
1439  n1 = iseq(nodi,1)
1440  n2 = iseq(nodi,2)
1441 
1442  if(n1==0) then
1443  write(bort_str,'("BUFRLIB: USRTPL - UNSET EXPANSION SEGMENT (",A,")")') tag(nodi)
1444  call bort(bort_str)
1445  endif
1446  if(n2-n1+1>maxjl) then
1447  write(bort_str,'("BUFRLIB: USRTPL - TEMPLATE ARRAY OVERFLOW, EXCEEDS THE LIMIT (",I6,") (",A,")")') maxjl, tag(nodi)
1448  call bort(bort_str)
1449  endif
1450 
1451  do n=n1,n2
1452  newn = newn+1
1453  itmp(newn) = jseq(n)
1454  vtmp(newn) = vali(jseq(n))
1455  enddo
1456 
1457  ! Move old nodes and store new ones
1458 
1459  if(nval(lun)+newn*nbmp>maxss) then
1460  write(bort_str,'("BUFRLIB: USRTPL - INVENTORY OVERFLOW (",I6,"), EXCEEDS THE LIMIT (",I6,") (",A,")")') &
1461  nval(lun)+newn*nbmp, maxss, tag(nodi)
1462  call bort(bort_str)
1463  endif
1464 
1465  do j=nval(lun),invn+1,-1
1466  inv(j+newn*nbmp,lun) = inv(j,lun)
1467  val(j+newn*nbmp,lun) = val(j,lun)
1468  enddo
1469 
1470  if(drp.or.drs) vtmp(1) = newn
1471  knvn = invn
1472 
1473  do i=1,nbmp
1474  do j=1,newn
1475  knvn = knvn+1
1476  inv(knvn,lun) = itmp(j)
1477  val(knvn,lun) = vtmp(j)
1478  enddo
1479  enddo
1480 
1481  ! Reset pointers and counters
1482 
1483  nval(lun) = nval(lun) + newn*nbmp
1484 
1485  if(iprt>=2) then
1486  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1487  write ( unit=errstr, fmt='(A,A,A10,2(A,I5),A,I7)' ) 'BUFRLIB: USRTPL - TAG(INV(INVN,LUN)):NEWN:NBMP:', &
1488  'NVAL(LUN) = ', tag(inv(invn,lun)), ':', newn, ':', nbmp, ':', nval(lun)
1489  call errwrt(errstr)
1490  do i=1,newn
1491  write ( unit=errstr, fmt='(2(A,I5),A,A10)' ) 'For I = ', i, ', ITMP(I) = ', itmp(i), ', TAG(ITMP(I)) = ', tag(itmp(i))
1492  call errwrt(errstr)
1493  enddo
1494  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1495  call errwrt(' ')
1496  endif
1497 
1498  if(drx) then
1499  node = nodi
1500  invr = invn
1501  outer: do while (.true.)
1502  node = jmpb(node)
1503  if(node<=0) exit
1504  if(itp(node)==0) then
1505  do invr=invr-1,1,-1
1506  if(inv(invr,lun)==node) then
1507  val(invr,lun) = val(invr,lun)+newn*nbmp
1508  cycle outer
1509  endif
1510  enddo
1511  write(bort_str,'("BUFRLIB: USRTPL - BAD BACKUP STRATEGY (",A,")")') tag(nodi)
1512  call bort(bort_str)
1513  else
1514  cycle
1515  endif
1516  enddo outer
1517  endif
1518 
1519  return
1520 end subroutine usrtpl
1521 
1535 recursive subroutine invmrg(lubfi,lubfj)
1536 
1537  use bufrlib
1538 
1539  use modv_vars, only: im8b
1540 
1541  use moda_usrint
1542  use moda_tables
1543  use moda_mrgcom
1544 
1545  implicit none
1546 
1547  integer, intent(in) :: lubfi, lubfj
1548  integer my_lubfi, my_lubfj, luni, il, im, lunj, jl, jm, is, js, node, nodj, ityp, iwrds, jwrds, &
1549  n, ioff, nwords, ibfms, bort_target_set
1550 
1551  character*128 bort_str
1552 
1553  logical herei, herej, missi, missj, samei
1554 
1555  ! Check for I8 integers
1556 
1557  if(im8b) then
1558  im8b=.false.
1559  call x84(lubfi,my_lubfi,1)
1560  call x84(lubfj,my_lubfj,1)
1561  call invmrg(my_lubfi,my_lubfj)
1562  im8b=.true.
1563  return
1564  endif
1565 
1566  ! If we're catching bort errors, set a target return location if one doesn't already exist.
1567 
1568  if (bort_target_set() == 1) then
1569  call catch_bort_invmrg_c(lubfi,lubfj)
1570  call bort_target_unset
1571  return
1572  endif
1573 
1574  is = 1
1575  js = 1
1576 
1577  ! Get the unit pointers
1578 
1579  call status(lubfi,luni,il,im)
1580  call status(lubfj,lunj,jl,jm)
1581 
1582  ! Step through the buffers comparing the inventory and merging data
1583 
1584  do while(is<=nval(luni))
1585  ! Confirm we're at the same node in each buffer
1586  node = inv(is,luni)
1587  nodj = inv(js,lunj)
1588  if(node/=nodj) then
1589  write(bort_str,'("BUFRLIB: INVMRG - NODE FROM INPUT BUFR FILE '// &
1590  '(",I7,") DOES NOT EQUAL NODE FROM OUTPUT BUFR FILE (",I7,"), TABULAR MISMATCH")') node, nodj
1591  call bort(bort_str)
1592  endif
1593 
1594  ityp = itp(node)
1595  if(ityp==1) then
1596  ! Do an entire sequence replacement
1597  if(typ(node)=='DRB') then
1598  ioff = 0
1599  else
1600  ioff = 1
1601  endif
1602  iwrds = nwords(is,luni)+ioff
1603  jwrds = nwords(js,lunj)+ioff
1604  if(iwrds>ioff .and. jwrds==ioff) then
1605  do n=nval(lunj),js+1,-1
1606  inv(n+iwrds-jwrds,lunj) = inv(n,lunj)
1607  val(n+iwrds-jwrds,lunj) = val(n,lunj)
1608  enddo
1609  do n=0,iwrds
1610  inv(js+n,lunj) = inv(is+n,luni)
1611  val(js+n,lunj) = val(is+n,luni)
1612  enddo
1613  nval(lunj) = nval(lunj)+iwrds-jwrds
1614  jwrds = iwrds
1615  nrpl = nrpl+1
1616  endif
1617  is = is+iwrds
1618  js = js+jwrds
1619  elseif((ityp==2).or.(ityp==3)) then
1620  ! Fill missing values
1621  herei = ibfms(val(is,luni))==0
1622  herej = ibfms(val(js,lunj))==0
1623  missi = .not.(herei)
1624  missj = .not.(herej)
1625  samei = val(is,luni)==val(js,lunj)
1626  if(herei.and.missj) then
1627  val(js,lunj) = val(is,luni)
1628  nmrg = nmrg+1
1629  elseif(herei.and.herej.and..not.samei) then
1630  namb = namb+1
1631  endif
1632  endif
1633 
1634  ! Bump the counters and go check the next pair
1635  is = is + 1
1636  js = js + 1
1637  enddo
1638 
1639  ntot = ntot+1
1640 
1641  return
1642 end subroutine invmrg
1643 
1652 integer function nwords(n,lun) result(iret)
1653 
1654  use moda_usrint
1655 
1656  implicit none
1657 
1658  integer, intent(in) :: n, lun
1659  integer k
1660 
1661  iret = 0
1662 
1663  do k=1,nint(val(n,lun))
1664  iret = iret + nint(val(iret+n+1,lun))
1665  enddo
1666 
1667  return
1668 end function nwords
subroutine strbtm(n, lun, ival)
Store internal information in module moda_bitmaps if the input element is part of a bitmap.
Definition: bitmaps.F90:20
recursive subroutine bort(str)
Log an error message, then either return to or abort the application program.
Definition: borts.F90:15
subroutine bort_target_unset
Clear any existing bort target.
Definition: borts.F90:180
integer function bort_target_set()
Sets a new bort target, if bort catching is enabled and such a target doesn't already exist.
Definition: borts.F90:160
subroutine upb(nval, nbits, ibay, ibit)
Decode an integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:202
subroutine upbb(nval, nbits, ibit, ibay)
Decode an integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:154
subroutine upb8(nval, nbits, ibit, ibay)
Decode an 8-byte integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:80
real *8 function ups(ival, node)
Unpack a real*8 value from an integer by applying the proper scale and reference values.
Definition: cidecode.F90:332
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 pkb8(nval, nbits, ibay, ibit)
Encode an 8-byte integer value within a specified number of bits of an integer array,...
Definition: ciencode.F90:97
subroutine rdcmps(lun)
Read the next compressed BUFR data subset into internal arrays.
Definition: compress.F90:122
subroutine wrcmps(lunix)
Write a compressed BUFR data subset.
Definition: compress.F90:396
subroutine mvb(ib1, nb1, ib2, nb2, nbm)
Copy a specified number of bytes from one packed binary array to another.
Definition: copydata.F90:767
subroutine nemtba(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1244
subroutine errwrt(str)
Specify a custom location for the logging of error and diagnostic messages generated by the NCEPLIBS-...
Definition: errwrt.F90:32
subroutine strsuc(str1, str2, lens)
Remove leading and trailing blanks from a character string.
Definition: misc.F90:199
integer function ibfms(r8val)
Check whether a real*8 data value returned from a previous call to any of the NCEPLIBS-bufr values-re...
Definition: missing.F90:25
Wrap C NCEPLIBS-bufr functions so they can be called from within the Fortran part of the library.
Definition: bufrlib.F90:11
Declare arrays and variables used to store BUFR messages internally for multiple file IDs.
integer, dimension(:), allocatable ibay
Current data subset.
integer ibit
Bit pointer within ibay.
integer, dimension(:,:), allocatable mbay
Current BUFR message for each file ID.
integer, dimension(:), allocatable mbyt
Length (in bytes) of current BUFR message for each file ID.
integer maxbyt
Maximum length of an output BUFR message.
Declare arrays and variables used to store bitmaps internally within a data subset definition.
integer lstnod
Most recent jump/link table entry that was processed by function igetrfel() and whose corresponding v...
integer nbtm
Number of stored bitmaps for the current data subset (up to a maximum of mxbtm).
integer lstnodct
Current count of consecutive occurrences of lstnod.
logical linbtm
Set to .true.
Declare arrays used to store, for each output file ID, a copy of the BUFR message that was most recen...
integer, dimension(:), allocatable msglen
Length (in integers) of BUFR message most recently written to each output file ID.
integer, dimension(:,:), allocatable msgtxt
BUFR message most recently written to each output file ID.
Declare arrays and variables needed to store long character strings (greater than 8 bytes) via subrou...
integer nh4wlc
Number of long character strings being stored.
character *14, dimension(:), allocatable sth4wlc
Table B mnemonics associated with long character strings.
integer, dimension(:), allocatable luh4wlc
File ID for associated output file.
character *120, dimension(:), allocatable chh4wlc
Long character strings.
Declare an array used to pack or unpack all of the values of a BUFR data subset.
integer *8, dimension(:), allocatable ival
BUFR data subset values.
Declare arrays which provide working space in several subprograms (usrtpl() and ufbcup()) which manip...
real *8, dimension(:), allocatable vtmp
val array elements for new sections of a growing subset buffer.
integer, dimension(:), allocatable itmp
inv array elements for new sections of a growing subset buffer.
Declare variables for use when merging parts of different data subsets.
integer nmrg
Number of merges.
integer ntot
Total number of calls to subroutine invmrg().
integer namb
Number of potential merges that weren't made because of ambiguities.
integer nrpl
Number of expansions of Table D mnemonics using short (1-bit) delayed replication.
Declare a variable used to indicate whether output BUFR messages should be compressed.
character ccmf
Flag indicating whether BUFR output messages are to be compressed; this variable is initialized to a ...
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.
integer, dimension(:), allocatable idate
Section 1 date-time of message.
integer, dimension(:), allocatable nmsg
Current message pointer within logical unit.
integer, dimension(:), allocatable msub
Total number of data subsets in message.
integer, dimension(:), allocatable nsub
Current subset pointer within message.
Declare an array used to store a status code for each file ID if an error or other abnormal result oc...
integer, dimension(:), allocatable iscodes
Abnormal status codes.
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 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:
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, dimension(:), allocatable itp
Integer type values corresponding to typ:
Declare an array used to store, for each file ID, the logical unit number corresponding to a separate...
integer, dimension(:), allocatable luncpy
Logical unit numbers used to copy long character strings between BUFR data subsets.
Declare an array used to store, for each file ID from which a BUFR message is currently being read as...
integer, dimension(:), allocatable msgunp
Flag indicating how to unpack data subsets from BUFR message:
Declare arrays for internal storage of pointers to BUFR data subset values.
integer, dimension(:), allocatable nbit
Length (in bits) of each packed data value in data subset.
integer, dimension(:), allocatable mbit
Pointer in data subset to first bit of each packed data value.
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...
integer, dimension(:,:), allocatable nrfelm
Referenced data value, for data values which refer to a previous data value in the BUFR data subset v...
Declare arrays used in subroutine rcstpl() to store subset segments that are being copied from a subs...
integer, dimension(:,:), allocatable iutmp
inv array elements for new sections of a growing subset buffer.
real *8, dimension(:,:), allocatable vutmp
val array elements for new sections of a growing subset buffer.
recursive subroutine openbf(lunit, io, lundx)
Connect a new file to the NCEPLIBS-bufr software for input or output operations, or initialize the li...
recursive subroutine ufbcnt(lunit, kmsg, ksub)
Get the current location of the file pointer within a BUFR file, in terms of a message number countin...
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...
recursive subroutine readmg(lunxx, subset, jdate, iret)
Read the next BUFR message from logical unit abs(lunxx) into internal arrays.
Definition: readwritemg.F90:44
subroutine msgini(lun)
Initialize, within the internal arrays, a new uncompressed BUFR message for output.
subroutine msgwrt(lunit, mesg, mgbyt)
Perform final checks and updates on a BUFR message before writing it to a specified Fortran logical u...
recursive subroutine ufbpos(lunit, irec, isub, subset, jdate)
Jump forwards or backwards to a specified data subset within a BUFR file.
subroutine pad(ibay, ibit, ibyt, ipadb)
Pad a BUFR data subset with zeroed-out bits up to the next byte boundary.
subroutine rdtree(lun, iret)
Read the next uncompressed BUFR data subset into internal arrays.
subroutine wrtree(lun)
Pack a BUFR data subset.
subroutine msgupd(lunit, lun)
Write an uncompressed BUFR data subset.
subroutine usrtpl(lun, invn, nbmp)
Expand a subset template within internal arrays.
recursive subroutine writsa(lunxx, lmsgt, msgt, msgl)
Write a complete data subset into a BUFR message, and return each completed message within a memory a...
recursive integer function ireadns(lunit, subset, idate)
Call subroutine readns() and pass back its return code as the function value.
integer function nwords(n, lun)
Compute the length of a specified delayed replication sequence within a data subset.
recursive subroutine writsb(lunit)
Write a complete data subset into a BUFR message, for eventual output to logical unit lunit.
recursive subroutine invmrg(lubfi, lubfj)
Merge parts of data subsets which have duplicate space and time coordinates but different or unique o...
recursive integer function ireadsb(lunit)
Call subroutine readsb() and pass back its return code as the function value.
recursive subroutine readsb(lunit, iret)
Read the next data subset from a BUFR message.
Definition: readwritesb.F90:32
subroutine rcstpl(lun, iret)
Initialize a subset template within internal arrays.
recursive integer function lcmgdf(lunit, subset)
Check whether the subset definition for a given message type contains any long character strings (gre...
recursive subroutine rdmgsb(lunit, imsg, isub)
Read a specified data subset from a BUFR file.
recursive subroutine readns(lunit, subset, jdate, iret)
Read the next data subset from a BUFR file.
recursive subroutine readlc(lunit, chr, str)
Read a long character string (greater than 8 bytes) from a data subset.
recursive subroutine writlc(lunit, chr, str)
Write a long character string (greater than 8 bytes) to a data subset.
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