NCEPLIBS-bufr  12.1.0
s013vals.F90
Go to the documentation of this file.
1 
5 
47 recursive subroutine gets1loc(s1mnem,iben,isbyt,iwid,iret)
48 
49  use modv_vars, only: im8b
50 
51  implicit none
52 
53  character*(*), intent(in) :: s1mnem
54 
55  integer, intent(in) :: iben
56  integer, intent(out) :: isbyt, iwid, iret
57  integer my_iben
58 
59  ! Check for I8 integers.
60 
61  if(im8b) then
62  im8b=.false.
63 
64  call x84(iben,my_iben,1)
65  call gets1loc(s1mnem,my_iben,isbyt,iwid,iret)
66  call x48(isbyt,isbyt,1)
67  call x48(iwid,iwid,1)
68  call x48(iret,iret,1)
69 
70  im8b=.true.
71  return
72  endif
73 
74  iret = 0
75  iwid = 8
76 
77  if(s1mnem=='LEN1') then
78  isbyt = 1
79  iwid = 24
80  else if(s1mnem=='BMT') then
81  isbyt = 4
82  else if(s1mnem=='OGCE') then
83  if(iben==3) then
84  isbyt = 6
85  else
86  ! Note that this location is actually the same for both edition 2 and edition 4 of BUFR
87  isbyt = 5
88  iwid = 16
89  endif
90  else if(s1mnem=='GSES') then
91  if(iben==3) then
92  isbyt = 5
93  else if(iben==4) then
94  isbyt = 7
95  iwid = 16
96  else
97  iret = -1
98  endif
99  else if(s1mnem=='USN') then
100  if(iben==4) then
101  isbyt = 9
102  else
103  isbyt = 7
104  endif
105  else if(s1mnem=='ISC2') then
106  iwid = 1
107  if(iben==4) then
108  isbyt = 10
109  else
110  isbyt = 8
111  endif
112  else if(s1mnem=='MTYP') then
113  if(iben==4) then
114  isbyt = 11
115  else
116  isbyt = 9
117  endif
118  else if(s1mnem=='MSBTI') then
119  if(iben==4) then
120  isbyt = 12
121  else
122  iret = -1
123  endif
124  else if(s1mnem=='MSBT') then
125  if(iben==4) then
126  isbyt = 13
127  else
128  isbyt = 10
129  endif
130  else if(s1mnem=='MTV') then
131  if(iben==4) then
132  isbyt = 14
133  else
134  isbyt = 11
135  endif
136  else if(s1mnem=='MTVL') then
137  if(iben==4) then
138  isbyt = 15
139  else
140  isbyt = 12
141  endif
142  else if(s1mnem=='YEAR') then
143  if(iben==4) then
144  isbyt = 16
145  iwid = 16
146  else
147  iret = -1
148  endif
149  else if(s1mnem=='YCEN') then
150  if(iben<4) then
151  isbyt = 13
152  else
153  iret = -1
154  endif
155  else if(s1mnem=='CENT') then
156  if(iben<4) then
157  isbyt = 18
158  else
159  iret = -1
160  endif
161  else if(s1mnem=='MNTH') then
162  if(iben==4) then
163  isbyt = 18
164  else
165  isbyt = 14
166  endif
167  else if(s1mnem=='DAYS') then
168  if(iben==4) then
169  isbyt = 19
170  else
171  isbyt = 15
172  endif
173  else if(s1mnem=='HOUR') then
174  if(iben==4) then
175  isbyt = 20
176  else
177  isbyt = 16
178  endif
179  else if(s1mnem=='MINU') then
180  if(iben==4) then
181  isbyt = 21
182  else
183  isbyt = 17
184  endif
185  else if(s1mnem=='SECO') then
186  if(iben==4) then
187  isbyt = 22
188  else
189  iret = -1
190  endif
191  else
192  iret = -1
193  endif
194 
195  return
196 end subroutine gets1loc
197 
246 recursive integer function iupbs01(mbay,s01mnem) result(iret)
247 
248  use modv_vars, only: im8b
249 
250  implicit none
251 
252  character*(*), intent(in) :: s01mnem
253 
254  integer, intent(in) :: mbay(*)
255  integer ival, iupb, i4dy, len0, iben, isbyt, iwid, iretgs, iyoc, icen
256 
257  logical ok4cent
258 
259  ! This statement function checks whether its input value contains a valid century value.
260  ok4cent(ival) = ((ival>=19).and.(ival<=21))
261 
262  ! Check for I8 integers.
263 
264  if(im8b) then
265  im8b=.false.
266 
267  iret = iupbs01(mbay,s01mnem)
268 
269  im8b=.true.
270  return
271  endif
272 
273  ! Handle some simple requests that do not depend on the BUFR edition number.
274 
275  if(s01mnem=='LENM') then
276  iret = iupb(mbay,5,24)
277  return
278  endif
279 
280  len0 = 8
281  if(s01mnem=='LEN0') then
282  iret = len0
283  return
284  endif
285 
286  ! Get the BUFR edition number.
287 
288  iben = iupb(mbay,8,8)
289  if(s01mnem=='BEN') then
290  iret = iben
291  return
292  endif
293 
294  ! Use the BUFR edition number to handle any other requests.
295 
296  call gets1loc(s01mnem,iben,isbyt,iwid,iretgs)
297  if(iretgs==0) then
298  iret = iupb(mbay,len0+isbyt,iwid)
299  if(s01mnem=='CENT') then
300 
301  ! Test whether the returned value was a valid century value.
302 
303  if(.not.ok4cent(iret)) iret = -1
304  endif
305  else if( (s01mnem=='YEAR') .and. (iben<4) ) then
306 
307  ! Calculate the 4-digit year.
308 
309  iyoc = iupb(mbay,21,8)
310  icen = iupb(mbay,26,8)
311 
312  ! Does icen contain a valid century value?
313 
314  if(ok4cent(icen)) then
315  ! YES, so use it to calculate the 4-digit year. Note that, by international convention, the year 2000 was the 100th
316  ! year of the 20th century, and the year 2001 was the 1st year of the 21st century
317  iret = (icen-1)*100 + iyoc
318  else
319  ! NO, so use a windowing technique to determine the 4-digit year from the year of the century.
320  iret = i4dy(mod(iyoc,100)*1000000)/10**6
321  endif
322  else
323  iret = -1
324  endif
325 
326  return
327 end function iupbs01
328 
348 recursive integer function iupbs3(mbay,s3mnem) result(iret)
349 
350  use modv_vars, only: im8b
351 
352  implicit none
353 
354  character*(*), intent(in) :: s3mnem
355 
356  integer, intent(in) :: mbay(*)
357  integer len0, len1, len2, len3, l4, l5, ipt, ival, imask, iupb
358 
359  ! Check for I8 integers.
360 
361  if(im8b) then
362  im8b=.false.
363 
364  iret = iupbs3(mbay,s3mnem)
365 
366  im8b=.true.
367  return
368  endif
369 
370  ! Skip to the beginning of Section 3.
371 
372  call getlens(mbay,3,len0,len1,len2,len3,l4,l5)
373  ipt = len0 + len1 + len2
374 
375  ! Unpack the requested value.
376 
377  if(s3mnem=='NSUB') then
378  iret = iupb(mbay,ipt+5,16)
379  else if( (s3mnem=='IOBS') .or. (s3mnem=='ICMP') ) then
380  ival = iupb(mbay,ipt+7,8)
381  if(s3mnem=='IOBS') then
382  imask = 128
383  else
384  imask = 64
385  endif
386  iret = min(1,iand(ival,imask))
387  else
388  iret = -1
389  endif
390 
391  return
392 end function iupbs3
393 
442 recursive integer function iupvs01(lunit,s01mnem) result(iret)
443 
444  use modv_vars, only: im8b
445 
446  use moda_bitbuf
447 
448  implicit none
449 
450  character*(*), intent(in) :: s01mnem
451 
452  integer, intent(in) :: lunit
453  integer my_lunit, lun, ilst, imst, iupbs01
454 
455  ! Check for I8 integers
456 
457  if(im8b) then
458  im8b=.false.
459 
460  call x84(lunit,my_lunit,1)
461  iret=iupvs01(my_lunit,s01mnem)
462 
463  im8b=.true.
464  return
465  endif
466 
467  iret = -1
468 
469  ! Check the file status
470 
471  call status(lunit,lun,ilst,imst)
472  if(ilst==0) call bort('BUFRLIB: IUPVS01 - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR INPUT')
473  if(ilst>0) call bort('BUFRLIB: IUPVS01 - INPUT BUFR FILE IS OPEN FOR OUTPUT, IT MUST BE OPEN FOR INPUT')
474  if(imst==0) call bort('BUFRLIB: IUPVS01 - A MESSAGE MUST BE OPEN IN INPUT BUFR FILE, NONE ARE')
475 
476  ! Unpack the requested value
477 
478  iret = iupbs01(mbay(1,lun),s01mnem)
479 
480  return
481 end function iupvs01
482 
520 recursive subroutine pkbs1(ival,mbay,s1mnem)
521 
522  use modv_vars, only: im8b
523 
524  implicit none
525 
526  character*(*), intent(in) :: s1mnem
527 
528  integer, intent(in) :: ival
529  integer, intent(inout) :: mbay(*)
530  integer my_ival, iben, isbyt, iwid, iret, iupbs01, ibit
531 
532  character*128 bort_str
533 
534  ! Check for I8 integers.
535 
536  if (im8b) then
537  im8b = .false.
538 
539  call x84(ival,my_ival,1)
540  call pkbs1(my_ival,mbay,s1mnem)
541 
542  im8b = .true.
543  return
544  end if
545 
546  iben = iupbs01(mbay,'BEN')
547 
548  ! Determine where to store the value.
549 
550  call gets1loc(s1mnem,iben,isbyt,iwid,iret)
551  if ( (iret==0) .and. &
552  ( (s1mnem=='USN') .or. (s1mnem=='BMT') .or. (s1mnem=='OGCE') .or. (s1mnem=='GSES') .or. (s1mnem=='MTYP') .or. &
553  (s1mnem=='MSBTI') .or. (s1mnem=='MSBT') .or. (s1mnem=='MTV') .or. (s1mnem=='MTVL') .or. (s1mnem=='YCEN') .or.&
554  (s1mnem=='CENT') .or. (s1mnem=='YEAR') .or. (s1mnem=='MNTH') .or. (s1mnem=='DAYS') .or. (s1mnem=='HOUR') .or.&
555  (s1mnem=='MINU') .or. (s1mnem=='SECO') ) ) then
556  ! Store the value.
557  ibit = (iupbs01(mbay,'LEN0')+isbyt-1)*8
558  call pkb(ival,iwid,mbay,ibit)
559  else
560  write(bort_str,'("BUFRLIB: PKBS1 - CANNOT OVERWRITE LOCATION CORRESPONDING TO MNEMONIC (",A,") WITHIN BUFR EDITION '// &
561  '(",I1,")")') s1mnem, iben
562  call bort(bort_str)
563  endif
564 
565  return
566 end subroutine pkbs1
567 
618 recursive subroutine pkvs01(s01mnem,ival)
619 
620  use modv_vars, only: im8b, mxs01v
621 
622  use moda_s01cm
623 
624  implicit none
625 
626  character*(*), intent(in) :: s01mnem
627 
628  integer, intent(in) :: ival
629  integer my_ival, i
630 
631  character*128 bort_str
632 
633  ! check for i8 integers
634 
635  if(im8b) then
636  im8b=.false.
637 
638  call x84(ival,my_ival,1)
639  call pkvs01(s01mnem,my_ival)
640 
641  im8b=.true.
642  return
643  endif
644 
645  ! Confirm that the arrays needed by this subroutine have already been allocated (and if not, go ahead and allocate them now),
646  ! since it's possible for this subroutine to be called before the first call to subroutine openbf().
647 
648  if ( ( .not. allocated(cmnem) ) .or. ( .not. allocated(ivmnem) ) ) then
649  call openbf(0,'FIRST',0)
650  endif
651 
652  ! If an ival has already been assigned for this particular s01mnem, then overwrite that entry in module @ref moda_s01cm
653  ! using the new ival.
654 
655  if(ns01v>0) then
656  do i=1,ns01v
657  if(s01mnem==cmnem(i)) then
658  ivmnem(i) = ival
659  return
660  endif
661  enddo
662  endif
663 
664  ! Otherwise, use the next available unused entry in module @ref moda_s01cm.
665 
666  if(ns01v>=mxs01v) then
667  write(bort_str,'("BUFRLIB: PKVS01 - CANNOT OVERWRITE MORE THAN ",I2," DIFFERENT LOCATIONS WITHIN SECTION 0 '// &
668  'OR SECTION 1")') mxs01v
669  call bort(bort_str)
670  endif
671 
672  ns01v = ns01v + 1
673  cmnem(ns01v) = s01mnem
674  ivmnem(ns01v) = ival
675 
676  return
677 end subroutine pkvs01
678 
685 subroutine reads3 ( lun )
686 
687  use bufrlib
688 
689  use modv_vars, only: maxnc, mxcnem
690 
691  use moda_sc3bfr
692  use moda_bitbuf
693  use moda_dscach
694  use moda_s3list
695 
696  implicit none
697 
698  integer, intent(in) :: lun
699  integer iprt, irepct, ireadmt, igettdi, itmp, ncds3, ii, jj, ifxy, igetntbi, n, idn
700 
701  character*6 numb, adn30
702  character*55 cseq
703  character*128 errstr
704 
705  logical incach
706 
707  common /quiet/ iprt
708 
709  save irepct
710 
711  ! Check whether the appropriate BUFR master table information has already been read into internal memory for this message.
712 
713  if ( ireadmt( lun ) == 1 ) then
714  ! NO (i.e. we just had to read in new master table information for this message), so reset some corresponding values in
715  ! other parts of the library.
716  call dxinit ( lun, 0 )
717  itmp = igettdi( 0 )
718  irepct = 0
719  ncnem = 0
720  endif
721 
722  ! Unpack the list of Section 3 descriptors from the message.
723 
724  call upds3 ( mbay(1,lun), maxnc, cds3, ncds3 )
725  do ii = 1, ncds3
726  ids3(ii) = ifxy( cds3(ii) )
727  enddo
728 
729  ! Is the list of Section 3 descriptors already in the cache?
730 
731  ! The cache is a performance-enhancing device which saves time when the same descriptor sequences are encountered over and
732  ! over within the calling program. Time is saved because the below calls to subroutines stseq_c() and makestab() are
733  ! bypassed whenever a list is already in the cache.
734 
735  incach = .false.
736  if ( ncnem > 0 ) then
737  ii = 1
738  do while ( (.not.incach) .and. (ii<=ncnem) )
739  if ( ncds3 == ndc(ii) ) then
740  jj = 1
741  incach = .true.
742  do while ( (incach) .and. (jj<=ncds3) )
743  if ( ids3(jj) == idcach(ii,jj) ) then
744  jj = jj + 1
745  else
746  incach = .false.
747  endif
748  enddo
749  if (incach) then
750 
751  ! The list is already in the cache, so store the corresponding Table A mnemonic into module @ref moda_sc3bfr and return.
752 
753  if ( iprt >= 2 ) then
754  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
755  errstr = 'BUFRLIB: READS3 - RE-USED CACHE LIST FOR ' // cnem(ii)
756  call errwrt(errstr)
757  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
758  call errwrt(' ')
759  endif
760  tamnem(lun) = cnem(ii)
761  return
762  endif
763  endif
764  ii = ii + 1
765  enddo
766  endif
767 
768  ! Get the next available index within the internal Table A.
769 
770  n = igetntbi( lun, 'A' )
771 
772  ! Generate a Table A mnemonic and sequence description.
773 
774  write ( tamnem(lun), '(A5,I3.3)') 'MSTTB', n
775  cseq = 'TABLE A MNEMONIC ' // tamnem(lun)
776 
777  ! Store the Table A mnemonic and sequence into the cache.
778 
779  ncnem = ncnem + 1
780  if ( ncnem > mxcnem ) call bort('BUFRLIB: READS3 - MXCNEM OVERFLOW')
781  cnem(ncnem) = tamnem(lun)
782  ndc(ncnem) = ncds3
783  do jj = 1, ncds3
784  idcach(ncnem,jj) = ids3(jj)
785  enddo
786  if ( iprt >= 2 ) then
787  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
788  errstr = 'BUFRLIB: READS3 - STORED CACHE LIST FOR ' // cnem(ncnem)
789  call errwrt(errstr)
790  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
791  call errwrt(' ')
792  endif
793 
794  ! Get an FXY value to use with this Table A mnemonic.
795 
796  idn = igettdi( lun )
797  numb = adn30( idn, 6 )
798 
799  ! Store all of the information for this mnemonic within the internal Table A.
800 
801  call stntbia ( n, lun, numb, tamnem(lun), cseq )
802 
803  ! Store all of the information for this sequence within the internal Tables B and D.
804 
805  call stseq_c ( lun, irepct, idn, tamnem(lun), cseq, ids3, ncds3 )
806 
807  ! Update the jump/link table.
808 
809  call makestab
810 
811  return
812 end subroutine reads3
813 
828 recursive subroutine upds3(mbay,lcds3,cds3,nds3)
829 
830  use modv_vars, only: im8b
831 
832  implicit none
833 
834  integer, intent(in) :: mbay(*), lcds3
835  integer, intent(out) :: nds3
836  integer my_lcds3, len0, len1, len2, len3, l4, l5, ipt, jj, iupb
837 
838  character*6, intent(out) :: cds3(*)
839  character*6 adn30
840 
841  ! Check for I8 integers.
842 
843  if(im8b) then
844  im8b=.false.
845 
846  call x84(lcds3,my_lcds3,1)
847  call upds3(mbay,my_lcds3,cds3,nds3)
848  call x48(nds3,nds3,1)
849 
850  im8b=.true.
851  return
852  endif
853 
854  ! Skip to the beginning of Section 3.
855 
856  call getlens(mbay,3,len0,len1,len2,len3,l4,l5)
857  ipt = len0 + len1 + len2
858 
859  ! Unpack the Section 3 descriptors.
860 
861  nds3 = 0
862  do jj = 8,(len3-1),2
863  nds3 = nds3 + 1
864  if(nds3>lcds3) call bort('BUFRLIB: UPDS3 - OVERFLOW OF OUTPUT DESCRIPTOR ARRAY; TRY A LARGER DIMENSION FOR THIS ARRAY')
865  cds3(nds3) = adn30(iupb(mbay,ipt+jj,16),6)
866  enddo
867 
868  return
869 end subroutine upds3
870 
888 recursive subroutine datelen(len)
889 
890  use modv_vars, only: im8b, lendat
891 
892  implicit none
893 
894  integer, intent(in) :: len
895  integer my_len
896 
897  character*128 bort_str
898 
899  ! Check for I8 integers
900 
901  if(im8b) then
902  im8b=.false.
903 
904  call x84(len,my_len,1)
905  call datelen(my_len)
906 
907  im8b=.true.
908  return
909  endif
910 
911  if(len/=8 .and. len/=10) then
912  write(bort_str,'("BUFRLIB: DATELEN - INPUT ARGUMENT IS",I4," - IT MUST BE EITHER 8 OR 10")') len
913  call bort(bort_str)
914  endif
915  lendat = len
916 
917  return
918 end subroutine datelen
919 
936 recursive subroutine datebf(lunit,mear,mmon,mday,mour,idate)
937 
938  use modv_vars, only: im8b
939 
940  use moda_mgwa
941 
942  implicit none
943 
944  integer, intent(in) :: lunit
945  integer, intent(out) :: mear, mmon, mday, mour, idate
946  integer my_lunit, iprt, lun, jl, jm, ier, idx, idxmsg, igetdate
947 
948  character*128 errstr
949 
950  common /quiet/ iprt
951 
952  ! Check for I8 integers
953 
954  if(im8b) then
955  im8b=.false.
956 
957  call x84(lunit,my_lunit,1)
958  call datebf(my_lunit,mear,mmon,mday,mour,idate)
959  call x48(mear,mear,1)
960  call x48(mmon,mmon,1)
961  call x48(mday,mday,1)
962  call x48(mour,mour,1)
963  call x48(idate,idate,1)
964 
965  im8b=.true.
966  return
967  endif
968 
969  ! Initialization, in case openbf() hasn't been called yet.
970 
971  if ( .not. allocated(mgwa) ) call openbf(lunit,'FIRST',lunit)
972 
973  ! See if the file is already open to the library (a no-no!).
974 
975  call status(lunit,lun,jl,jm)
976  if(jl/=0) call bort ('BUFRLIB: DATEBF - INPUT BUFR FILE IS OPEN, IT MUST BE CLOSED')
977 
978  ! Read to the first data message and pick out the date.
979 
980  call openbf(lunit,'INX',lunit)
981  idx = 1
982  do while (idx==1)
983  call rdmsgw(lunit,mgwa,ier)
984  if(ier<0) then
985  if (iprt>=1) then
986  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
987  errstr = 'BUFRLIB: DATEBF - SECTION 1 DATE COULD NOT BE LOCATED - RETURN WITH IDATE = -1'
988  call errwrt(errstr)
989  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
990  call errwrt(' ')
991  endif
992  idate = -1
993  call closbf(lunit)
994  return
995  endif
996  idx = idxmsg(mgwa)
997  end do
998  idate = igetdate(mgwa,mear,mmon,mday,mour)
999  call closbf(lunit)
1000 
1001  return
1002 end subroutine datebf
1003 
1021 recursive integer function igetdate(mbay,iyr,imo,idy,ihr) result(iret)
1022 
1023  use modv_vars, only: im8b, lendat
1024 
1025  implicit none
1026 
1027  integer, intent(in) :: mbay(*)
1028  integer, intent(out) :: iyr, imo, idy, ihr
1029  integer iupbs01
1030 
1031  ! Check for I8 integers.
1032 
1033  if(im8b) then
1034  im8b=.false.
1035 
1036  iret=igetdate(mbay,iyr,imo,idy,ihr)
1037  call x48(iyr,iyr,1)
1038  call x48(imo,imo,1)
1039  call x48(idy,idy,1)
1040  call x48(ihr,ihr,1)
1041 
1042  im8b=.true.
1043  return
1044  endif
1045 
1046  iyr = iupbs01(mbay,'YEAR')
1047  imo = iupbs01(mbay,'MNTH')
1048  idy = iupbs01(mbay,'DAYS')
1049  ihr = iupbs01(mbay,'HOUR')
1050  if(lendat/=10) iyr = mod(iyr,100)
1051  iret = (iyr*1000000) + (imo*10000) + (idy*100) + ihr
1052 
1053  return
1054 end function igetdate
1055 
1069 recursive integer function i4dy(idate) result(iret)
1070 
1071  use modv_vars, only: im8b
1072 
1073  implicit none
1074 
1075  integer, intent(in) :: idate
1076  integer my_idate, iy
1077 
1078  ! Check for I8 integers.
1079 
1080  if(im8b) then
1081  im8b=.false.
1082 
1083  call x84(idate,my_idate,1)
1084  iret=i4dy(my_idate)
1085 
1086  im8b=.true.
1087  return
1088  endif
1089 
1090  if(idate<10**8) then
1091  iy = idate/10**6
1092  if(iy>40) then
1093  iret = idate + 19*100000000
1094  else
1095  iret = idate + 20*100000000
1096  endif
1097  else
1098  iret = idate
1099  endif
1100 
1101  return
1102 end function i4dy
1103 
1135 recursive subroutine dumpbf(lunit,jdate,jdump)
1136 
1137  use modv_vars, only: im8b
1138 
1139  use moda_mgwa
1140 
1141  implicit none
1142 
1143  integer, intent(in) :: lunit
1144  integer, intent(out) :: jdate(*), jdump(*)
1145  integer my_lunit, lun, jl, jm, iprt, ier, ii, igetdate, idxmsg, iupbs3, iupbs01
1146 
1147  character*128 errstr
1148 
1149  common /quiet/ iprt
1150 
1151  ! Check for I8 integers
1152 
1153  if(im8b) then
1154  im8b=.false.
1155 
1156  call x84(lunit,my_lunit,1)
1157  call dumpbf(my_lunit,jdate,jdump)
1158  call x48(jdate(1),jdate(1),5)
1159  call x48(jdump(1),jdump(1),5)
1160 
1161  im8b=.true.
1162  return
1163  endif
1164 
1165  do ii=1,5
1166  jdate(ii) = -1
1167  jdump(ii) = -1
1168  enddo
1169 
1170  ! See if the file is already open to the library (a no-no!).
1171 
1172  call status(lunit,lun,jl,jm)
1173  if(jl/=0) call bort('BUFRLIB: DUMPBF - INPUT BUFR FILE IS OPEN, IT MUST BE CLOSED')
1174  call openbf(lunit,'INX',lunit)
1175 
1176  do while (.true.)
1177  call rdmsgw(lunit,mgwa,ier)
1178  if(ier/=0) exit
1179  if(idxmsg(mgwa)==1) cycle ! Skip past any dictionary messages
1180 
1181  ! The dump center YY,MM,DD,HH,MM should be in this message, which is the first message containing zero subsets
1182  if(iupbs3(mgwa,'NSUB')/=0) exit
1183  ii = igetdate(mgwa,jdate(1),jdate(2),jdate(3),jdate(4))
1184  jdate(5) = iupbs01(mgwa,'MINU')
1185 
1186  ! The dump clock YY,MM,DD,HH,MM should be in the next message, which is the second message containing zero subsets
1187  call rdmsgw(lunit,mgwa,ier)
1188  if(ier/=0) exit
1189  if(iupbs3(mgwa,'NSUB')/=0) exit
1190  ii = igetdate(mgwa,jdump(1),jdump(2),jdump(3),jdump(4))
1191  jdump(5) = iupbs01(mgwa,'MINU')
1192 
1193  call closbf(lunit)
1194  return
1195  enddo
1196 
1197  if (iprt>=1 .and. (jdate(1)==-1.or.jdump(1)==-1)) then
1198  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1199  if(jdate(1)==-1) then
1200  errstr = 'BUFRLIB: DUMPBF - FIRST EMPTY BUFR MESSAGE SECTION 1 DATE COULD NOT BE LOCATED - RETURN WITH JDATE = 5*-1'
1201  call errwrt(errstr)
1202  endif
1203  if(jdump(1)==-1) then
1204  errstr = 'BUFRLIB: DUMPBF - SECOND EMPTY BUFR MESSAGE SECTION 1 DATE COULD NOT BE LOCATED - RETURN WITH JDUMP = 5*-1'
1205  call errwrt(errstr)
1206  endif
1207  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1208  call errwrt(' ')
1209  endif
1210 
1211  return
1212 end subroutine dumpbf
1213 
1223 recursive subroutine minimg(lunit,mini)
1224 
1225  use modv_vars, only: im8b
1226 
1227  use moda_bitbuf
1228 
1229  implicit none
1230 
1231  integer, intent(in) :: lunit, mini
1232  integer my_lunit, my_mini, lun, il, im
1233 
1234  ! Check for I8 integers.
1235 
1236  if(im8b) then
1237  im8b=.false.
1238 
1239  call x84(lunit,my_lunit,1)
1240  call x84(mini,my_mini,1)
1241  call minimg(my_lunit,my_mini)
1242 
1243  im8b=.true.
1244  return
1245  endif
1246 
1247  call status(lunit,lun,il,im)
1248  if(il==0) call bort('BUFRLIB: MINIMG - OUTPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR OUTPUT')
1249  if(il<0) call bort('BUFRLIB: MINIMG - OUTPUT BUFR FILE IS OPEN FOR INPUT, IT MUST BE OPEN FOR OUTPUT')
1250  if(im==0) call bort('BUFRLIB: MINIMG - A MESSAGE MUST BE OPEN IN OUTPUT BUFR FILE, NONE ARE')
1251 
1252  call pkbs1(mini,mbay(1,lun),'MINU')
1253 
1254  return
1255 end subroutine minimg
1256 
1271 subroutine cktaba(lun,subset,jdate,iret)
1272 
1273  use moda_msgcwd
1274  use moda_sc3bfr
1275  use moda_unptyp
1276  use moda_bitbuf
1277 
1278  implicit none
1279 
1280  integer, intent(in) :: lun
1281  integer, intent(out) :: jdate, iret
1282  integer, parameter :: ncpfx = 3
1283  integer ibct, ipd1, ipd2, ipd3, ipd4, iprt, mtyp, msbt, mty1, msb1, isub, ksub, len0, len1, len2, len3, l4, l5, lundx, ii, &
1284  itab, inod, iad3, iad4, iyr, imo, idy, ihr, iupb, iupbs01, iupbs3, i4dy, igetdate
1285 
1286  character*128 bort_str, errstr
1287  character*8, intent(out) :: subset
1288  character*2, parameter :: cpfx(ncpfx) = (/'NC','FR','FN'/)
1289  character tab
1290 
1291  logical trybt
1292 
1293  common /padesc/ ibct, ipd1, ipd2, ipd3, ipd4
1294  common /quiet/ iprt
1295 
1296  iret = 0
1297 
1298  trybt = .true.
1299 
1300  ! Get the message type, subtype, and date from Section 1
1301 
1302  mtyp = iupbs01(mbay(1,lun),'MTYP')
1303  msbt = iupbs01(mbay(1,lun),'MSBT')
1304  jdate = igetdate(mbay(1,lun),iyr,imo,idy,ihr)
1305 
1306  if(mtyp==11) then
1307  ! This is a BUFR table (dictionary) message
1308  iret = 11
1309  ! There's no need to proceed any further unless Section 3 is being used for decoding
1310  if(isc3(lun)==0) then
1311  subset = " "
1312  return
1313  endif
1314  endif
1315 
1316  ! Get the first and second descriptors from Section 3
1317 
1318  call getlens(mbay(1,lun),3,len0,len1,len2,len3,l4,l5)
1319  iad3 = len0+len1+len2
1320  ksub = iupb(mbay(1,lun),iad3+8,16)
1321  isub = iupb(mbay(1,lun),iad3+10,16)
1322 
1323  ! Locate Section 4
1324 
1325  iad4 = iad3+len3
1326 
1327  ! Now, try to get the Table A mnemonic
1328 
1329  outer: do while (.true.)
1330 
1331  if(isc3(lun)/=0) then
1332  ! Section 3 is being used for decoding
1333  subset = tamnem(lun)
1334  call nemtbax(lun,subset,mty1,msb1,inod)
1335  if(inod>0) then
1336  mbyt(lun) = 8*(iad4+4)
1337  msgunp(lun) = 1
1338  exit outer
1339  endif
1340  endif
1341 
1342  inner: do while (.true.)
1343 
1344  call numtab(lun,isub,subset,tab,itab)
1345  call nemtbax(lun,subset,mty1,msb1,inod)
1346  if(inod>0) then
1347  ! The second descriptor in Section 3 corresponds to the Table A mnemonic, so the message contains non-standard
1348  ! NCEP extensions
1349  mbyt(lun) = (iad4+4)
1350  msgunp(lun) = 0
1351  exit outer
1352  endif
1353 
1354  call numtab(lun,ksub,subset,tab,itab)
1355  call nemtbax(lun,subset,mty1,msb1,inod)
1356  if(inod>0) then
1357  ! The first descriptor in Section 3 corresponds to the Table A mnemonic, so the message is WMO-standard
1358  mbyt(lun) = 8*(iad4+4)
1359  msgunp(lun) = 1
1360  exit outer
1361  endif
1362 
1363  ! OK, still no luck, so try "NCtttsss" (where ttt=mtyp and sss=msbt) as the Table A mnemonic, and if that doesn't work
1364  ! then also try "FRtttsss" AND "FNtttsss"
1365  ii=1
1366  do while(ii<=ncpfx)
1367  write(subset,'(A2,2I3.3)') cpfx(ii),mtyp,msbt
1368  call nemtbax(lun,subset,mty1,msb1,inod)
1369  if(inod>0) then
1370  if(ksub==ibct) then
1371  mbyt(lun) = (iad4+4)
1372  msgunp(lun) = 0
1373  else
1374  mbyt(lun) = 8*(iad4+4)
1375  msgunp(lun) = 1
1376  endif
1377  exit outer
1378  endif
1379  ii=ii+1
1380  enddo
1381 
1382  if(trybt) then
1383  ! Make one last desperate attempt by checking whether the application program contains an in-line version of
1384  ! subroutine openbt() to override the default version in the library
1385  trybt = .false.
1386  if(iprt>=1) then
1387  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1388  errstr = 'BUFRLIB: CKTABA - LAST RESORT, CHECK FOR EXTERNAL BUFR TABLE VIA CALL TO IN-LINE OPENBT'
1389  call errwrt(errstr)
1390  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
1391  call errwrt(' ')
1392  endif
1393  call openbt(lundx,mtyp)
1394  if(lundx>0) then
1395  ! There was an in-line replacement for the default library version of openbt(), so read DX table information from
1396  ! the specified logical unit and look for the Table A mnemonic there
1397  call rdusdx(lundx,lun)
1398  cycle inner
1399  endif
1400  endif
1401 
1402  ! Give up and report the bad news
1403  if(iprt>=0) then
1404  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1405  errstr = 'BUFRLIB: CKTABA - UNRECOGNIZED TABLE A MESSAGE TYPE (' // subset // ') - RETURN WITH IRET = -1'
1406  call errwrt(errstr)
1407  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1408  call errwrt(' ')
1409  endif
1410  iret = -1
1411  return
1412 
1413  enddo inner
1414 
1415  enddo outer
1416 
1417  ! Confirm the validity of the message type and subtype, and also check for compression
1418 
1419  if(isc3(lun)==0) then
1420  if(mtyp/=mty1) then
1421  write(bort_str,'("BUFRLIB: CKTABA - MESSAGE TYPE MISMATCH (SUBSET=",A8,", MTYP=",I3,", MTY1=",I3)') subset,mtyp,mty1
1422  call bort(bort_str)
1423  endif
1424  if( msbt/=msb1 .and. ( verify(subset(3:8),'1234567890') == 0 ) ) then
1425  write(bort_str,'("BUFRLIB: CKTABA - MESSAGE SUBTYPE MISMATCH (SUBSET=",A8,", MSBT=",I3,", MSB1=",I3)') subset,msbt,msb1
1426  call bort(bort_str)
1427  endif
1428  endif
1429  if(iupbs3(mbay(1,lun),'ICMP')>0) msgunp(lun) = 2
1430 
1431  ! Update values in @ref moda_msgcwd
1432 
1433  idate(lun) = i4dy(jdate)
1434  inode(lun) = inod
1435  msub(lun) = iupbs3(mbay(1,lun),'NSUB')
1436  nsub(lun) = 0
1437  if(iret/=11) nmsg(lun) = nmsg(lun)+1
1438 
1439  return
1440 end subroutine cktaba
1441 
1481 recursive subroutine mesgbc(lunin,mesgtyp,icomp)
1482 
1483  use modv_vars, only: im8b
1484 
1485  use moda_bitbuf
1486  use moda_mgwa
1487 
1488  implicit none
1489 
1490  integer, intent(in) :: lunin
1491  integer, intent(out) :: mesgtyp, icomp
1492  integer my_lunin, lunit, irec, ier, i, lun, il, im, iupbs01, iupbs3, idxmsg
1493 
1494  ! Check for I8 integers
1495 
1496  if(im8b) then
1497  im8b=.false.
1498  call x84(lunin,my_lunin,1)
1499  call mesgbc(my_lunin,mesgtyp,icomp)
1500  call x48(mesgtyp,mesgtyp,1)
1501  call x48(icomp,icomp,1)
1502  im8b=.true.
1503  return
1504  endif
1505 
1506  mesgtyp = -256
1507 
1508  lunit = abs(lunin)
1509 
1510  if(lunit==lunin) then
1511  ! Open the file, read past any DX BUFR tables and "dummy" messages, and return the first message type found
1512  irec = 0
1513  call openbf(lunit,'INX',lunit)
1514  do while (.true.)
1515  call rdmsgw(lunit,mgwa,ier)
1516  if(ier==-1) then
1517  if(irec==0) then
1518  mesgtyp = -256
1519  icomp = -3
1520  else
1521  if(mesgtyp>=0) mesgtyp = -mesgtyp
1522  icomp = -2
1523  endif
1524  call closbf(lunit)
1525  return
1526  endif
1527  irec = irec + 1
1528  mesgtyp = iupbs01(mgwa,'MTYP')
1529  if( (idxmsg(mgwa)/=1) .and. (iupbs3(mgwa,'NSUB')/=0) ) exit
1530  enddo
1531  call closbf(lunit)
1532  else
1533  ! Return message type for message currently stored in memory
1534  call status(lunit,lun,il,im)
1535  do i=1,12
1536  mgwa(i) = mbay(i,lun)
1537  enddo
1538  mesgtyp = iupbs01(mgwa,'MTYP')
1539  end if
1540 
1541  ! Set the compression switch
1542  icomp = iupbs3(mgwa,'ICMP')
1543 
1544  return
1545 end subroutine mesgbc
1546 
1570 recursive subroutine mesgbf(lunit,mesgtyp)
1571 
1572  use modv_vars, only: im8b
1573 
1574  use moda_mgwa
1575 
1576  implicit none
1577 
1578  integer, intent(in) :: lunit
1579  integer, intent(out) :: mesgtyp
1580  integer my_lunit, ier, iupbs01, idxmsg
1581 
1582  ! Check for I8 integers
1583 
1584  if(im8b) then
1585  im8b=.false.
1586  call x84(lunit,my_lunit,1)
1587  call mesgbf(my_lunit,mesgtyp)
1588  call x48(mesgtyp,mesgtyp,1)
1589  im8b=.true.
1590  return
1591  endif
1592 
1593  mesgtyp = -1
1594 
1595  call openbf(lunit,'INX',lunit)
1596 
1597  do while (.true.)
1598  call rdmsgw(lunit,mgwa,ier)
1599  if(ier==0) then
1600  mesgtyp = iupbs01(mgwa,'MTYP')
1601  if(idxmsg(mgwa)/=1) exit
1602  endif
1603  enddo
1604 
1605  call closbf(lunit)
1606 
1607  return
1608 end subroutine mesgbf
subroutine bort(str)
Log an error message, then abort the application program.
Definition: borts.F90:15
recursive integer function iupb(mbay, nbyt, nbit)
Decode an integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:226
subroutine 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 rdusdx(lundx, lun)
Read and parse a file containing a user-supplied DX BUFR table in character format,...
Definition: dxtable.F90:197
subroutine nemtbax(lun, nemo, mtyp, msbt, inod)
Get information about a Table A descriptor from the internal DX BUFR tables.
Definition: dxtable.F90:1197
subroutine stntbia(n, lun, numb, nemo, celsq)
Store a new entry within internal BUFR Table A.
Definition: dxtable.F90:1560
subroutine dxinit(lun, ioi)
Clear out the internal arrays (in module moda_tababd) holding the DX BUFR table, then optionally init...
Definition: dxtable.F90:606
integer function idxmsg(mesg)
Check whether a BUFR message contains DX BUFR tables information that was generated by the NCEPLIBS-b...
Definition: dxtable.F90:1123
subroutine errwrt(str)
Specify a custom location for the logging of error and diagnostic messages generated by the NCEPLIBS-...
Definition: errwrt.F90:32
subroutine numtab(lun, idn, nemo, tab, iret)
Get information about a descriptor, based on the WMO bit-wise representation of an FXY value.
Definition: fxy.F90:357
character *(*) function adn30(idn, ldn)
Convert an FXY value from its WMO bit-wise representation to a character string of length 5 or 6.
Definition: fxy.F90:18
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 mbay
Current BUFR message for each file ID.
integer, dimension(:), allocatable mbyt
Length (in bytes) of current BUFR message for each file ID.
Declare arrays and variables for the internal Table A mnemonic cache that is used for Section 3 decod...
character *8, dimension(:), allocatable cnem
Table A mnemonics.
integer ncnem
Number of entries in the internal Table A mnemonic cache (up to a maximum of mxcnem).
integer, dimension(:,:), allocatable idcach
WMO bit-wise representations of the child descriptors for the corresponding Table A mnemonic in cnem.
integer, dimension(:), allocatable ndc
Number of child descriptors for the corresponding Table A mnemonic in cnem.
Declare an array used by various subroutines and functions to hold a temporary working copy of a BUFR...
integer, dimension(:), allocatable mgwa
Temporary working copy of BUFR message.
Declare arrays 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 arrays and variables used to store custom values for certain mnemonics within Sections 0 and ...
integer, dimension(:), allocatable ivmnem
Custom values for use within Sections 0 and 1 of all future output BUFR messages written to all Fortr...
integer ns01v
Number of custom values stored.
character *8, dimension(:), allocatable cmnem
Section 0 and 1 mnemonics corresponding to ivmnem.
Declare arrays used by various subroutines and functions to hold a temporary working copy of a Sectio...
integer, dimension(:), allocatable ids3
Temporary working copy of Section 3 descriptor list in integer form.
character *6, dimension(:), allocatable cds3
Temporary working copy of Section 3 descriptor list in character form.
Declare an array used to store a switch for each file ID, indicating whether BUFR messages read from ...
character *8, dimension(:), allocatable tamnem
Table A mnemonic most recently read from each file ID, if isc3 = 1 for that stream.
integer, dimension(:), allocatable isc3
Section 3 switch for each file ID:
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:
recursive subroutine openbt(lundx, mtyp)
Specify a DX BUFR table of last resort, in case subroutine cktaba() is unable to locate a DX BUFR tab...
Definition: openbt.F90:31
recursive subroutine closbf(lunit)
Close the connection between logical unit lunit and the NCEPLIBS-bufr software.
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 status(lunit, lun, il, im)
Check whether a specified Fortran logical unit number is currently connected to the NCEPLIBS-bufr sof...
recursive subroutine getlens(mbay, ll, len0, len1, len2, len3, len4, len5)
Read the section lengths of a BUFR message, up to a specified point in the message.
subroutine rdmsgw(lunit, mesg, iret)
Read the next BUFR message from logical unit lunit as an array of integer words.
subroutine cktaba(lun, subset, jdate, iret)
Get the Table A mnemonic from Sections 1 and 3 of a BUFR message.
Definition: s013vals.F90:1272
recursive integer function iupbs01(mbay, s01mnem)
Read a specified value from within Section 0 or Section 1 of a BUFR message.
Definition: s013vals.F90:247
recursive subroutine datebf(lunit, mear, mmon, mday, mour, idate)
Get the Section 1 date-time from the first data message of a BUFR file, bypassing any messages at the...
Definition: s013vals.F90:937
recursive integer function iupvs01(lunit, s01mnem)
Read a specified value from within Section 0 or 1 of a BUFR message.
Definition: s013vals.F90:443
recursive subroutine pkbs1(ival, mbay, s1mnem)
Write a specified value into a specified location within Section 1 of a BUFR message,...
Definition: s013vals.F90:521
recursive integer function iupbs3(mbay, s3mnem)
Read a specified value from within Section 3 of a BUFR message.
Definition: s013vals.F90:349
recursive subroutine minimg(lunit, mini)
Write a minutes value into Section 1 of the BUFR message that was most recently opened for writing vi...
Definition: s013vals.F90:1224
recursive subroutine upds3(mbay, lcds3, cds3, nds3)
Read the sequence of data descriptors contained within Section 3 of a BUFR message.
Definition: s013vals.F90:829
recursive subroutine mesgbf(lunit, mesgtyp)
Read through a BUFR file (starting from the beginning of the file) and return the message type (from ...
Definition: s013vals.F90:1571
recursive subroutine gets1loc(s1mnem, iben, isbyt, iwid, iret)
Get the location of a specified value within Section 1 of a BUFR message.
Definition: s013vals.F90:48
recursive subroutine datelen(len)
Specify the format of Section 1 date-time values that will be output by future calls to any of the NC...
Definition: s013vals.F90:889
recursive subroutine dumpbf(lunit, jdate, jdump)
Read the Section 1 date-time from the first two "dummy" messages of an NCEP dump file.
Definition: s013vals.F90:1136
recursive subroutine mesgbc(lunin, mesgtyp, icomp)
Return the message type (from Section 1) and message compression indicator (from Section 3) of a BUFR...
Definition: s013vals.F90:1482
recursive subroutine pkvs01(s01mnem, ival)
Specify a value to be written into a specified location within Section 0 or Section 1 of all BUFR mes...
Definition: s013vals.F90:619
subroutine reads3(lun)
Read the Section 3 descriptors from the BUFR message in mbay(1,lun), then use the BUFR master tables ...
Definition: s013vals.F90:686
recursive integer function i4dy(idate)
Convert a date-time with a 2-digit year (YYMMDDHH) to a date-time with a 4-digit year (YYYYMMDDHH) us...
Definition: s013vals.F90:1070
recursive integer function igetdate(mbay, iyr, imo, idy, ihr)
Get the date-time from within Section 1 of a BUFR message.
Definition: s013vals.F90:1022
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