NCEPLIBS-bufr  12.3.0
memmsgs.F90
Go to the documentation of this file.
1 
5 
38 recursive subroutine ufbmem(lunit,inew,iret,iunit)
39 
40  use bufrlib
41 
42  use modv_vars, only: im8b, maxmem, maxmsg, iprt
43 
44  use moda_mgwa
45  use moda_msgmem
46 
47  implicit none
48 
49  integer, intent(in) :: lunit, inew
50  integer, intent(out) :: iret, iunit
51  integer my_lunit, my_inew, iflg, itim, lun, il, im, itemp, ier, nmsg, lmem, i, mlast0, idxmsg, nmwrd, bort_target_set
52 
53  character*128 bort_str, errstr
54 
55  ! Check for I8 integers
56 
57  if(im8b) then
58  im8b=.false.
59  call x84(lunit,my_lunit,1)
60  call x84(inew,my_inew,1)
61  call ufbmem(my_lunit,my_inew,iret,iunit)
62  call x48(iret,iret,1)
63  call x48(iunit,iunit,1)
64  im8b=.true.
65  return
66  endif
67 
68  ! If we're catching bort errors, set a target return location if one doesn't already exist.
69 
70  if (bort_target_set() == 1) then
71  call catch_bort_ufbmem_c(lunit,inew,iret,iunit)
73  return
74  endif
75 
76  ! Try to open BUFR file and set to initialize or concatenate
77 
78  call openbf(lunit,'IN',lunit)
79 
80  if(inew==0) then
81  msgp(0) = 0
82  munit = 0
83  mlast = 0
84  ndxts = 0
85  ldxts = 0
86  ndxm = 0
87  ldxm = 0
88  endif
89 
90  nmsg = msgp(0)
91  iret = 0
92  iflg = 0
93  itim = 0
94 
95  ! Copy any BUFR dictionary table messages from the beginning of lunit into @ref moda_msgmem for possible later use.
96  ! Note that such a table (if one exists) is already now in scope due to the prior call to subroutine openbf(), which
97  ! in turn would have automatically called subroutines readdx(), rdbfdx() and makestab() for this table.
98 
99  itemp = ndxts
100  call status(lunit,lun,il,im)
101  call cewind_c(lun)
102  call cpdxmm(lunit)
103 
104  ! If a table was indeed present at the beginning of the file, then set the flag to indicate that this table is now in scope.
105 
106  if ((itemp+1)==ndxts) ldxts = ndxts
107 
108  ! Transfer messages from file to memory and set message pointers
109 
110  do while (.true.)
111  call rdmsgw(lunit,mgwa,ier)
112  if(ier==-1) exit
113  if(ier==-2) then
114  write(bort_str,'("BUFRLIB: UFBMEM - ERROR READING MESSAGE NUMBER",I5," INTO MEMORY FROM UNIT",I3)') nmsg+1,lunit
115  call bort(bort_str)
116  endif
117 
118  if(idxmsg(mgwa)==1) then
119  ! New "embedded" BUFR dictionary table messages have been found in this file. Copy them into @ref moda_msgmem
120  ! for later use.
121  call backbufr_c(lun) ! Backspace lunit
122  call cpdxmm(lunit)
123  cycle
124  endif
125 
126  nmsg = nmsg+1
127  if(nmsg>maxmsg) iflg = 1
128  lmem = nmwrd(mgwa)
129  if(lmem+mlast>maxmem) iflg = 2
130 
131  if(iflg==0) then
132  iret = iret+1
133  do i=1,lmem
134  msgs(mlast+i) = mgwa(i)
135  enddo
136  msgp(0) = nmsg
137  msgp(nmsg) = mlast+1
138  else
139  if(itim==0) then
140  mlast0 = mlast
141  itim=1
142  endif
143  endif
144  mlast = mlast+lmem
145  enddo
146 
147  if(iflg==1) then
148  ! Emergency room treatment for maxmsg array overflow
149  if(iprt>=0) then
150  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
151  write ( unit=errstr, fmt='(A,A,I8,A)' ) 'BUFRLIB: UFBMEM - THE NO. OF MESSAGES REQUIRED TO STORE ', &
152  'ALL MESSAGES INTERNALLY EXCEEDS MAXIMUM (', maxmsg, ') - INCOMPLETE READ'
153  call errwrt(errstr)
154  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEM STORED ', msgp(0), ' MESSAGES OUT OF ', nmsg, '<<<'
155  call errwrt(errstr)
156  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEM STORED ', mlast0, ' BYTES OUT OF ', mlast, '<<<'
157  call errwrt(errstr)
158  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
159  call errwrt(' ')
160  endif
161  mlast=mlast0
162  endif
163 
164  if(iflg==2) then
165  ! Emergency room treatment for maxmem array overflow
166  if(iprt>=0) then
167  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
168  write ( unit=errstr, fmt='(A,A,I8,A)' ) 'BUFRLIB: UFBMEM - THE NO. OF BYTES REQUIRED TO STORE ', &
169  'ALL MESSAGES INTERNALLY EXCEEDS MAXIMUM (', maxmem, ') - INCOMPLETE READ'
170  call errwrt(errstr)
171  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEM STORED ', mlast0, ' BYTES OUT OF ', mlast, '<<<'
172  call errwrt(errstr)
173  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEM STORED ', msgp(0), ' MESSAGES OUT OF ', nmsg, '<<<'
174  call errwrt(errstr)
175  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
176  call errwrt(' ')
177  endif
178  mlast=mlast0
179  endif
180 
181  if(iret==0) then
182  call closbf(lunit)
183  else
184  if(munit/=0) call closbf(lunit)
185  if(munit==0) munit = lunit
186  endif
187  iunit = munit
188 
189  return
190 end subroutine ufbmem
191 
220 recursive subroutine ufbmex(lunit,lundx,inew,iret,mesg)
221 
222  use bufrlib
223 
224  use modv_vars, only: im8b, maxmem, maxmsg, iprt
225 
226  use moda_mgwa
227  use moda_msgmem
228 
229  implicit none
230 
231  character*128 bort_str, errstr
232 
233  integer, intent(in) :: lunit, lundx, inew
234  integer, intent(out) :: mesg(*), iret
235  integer my_lunit, my_lundx, my_inew, nmesg, iflg, itim, ier, nmsg, lmem, i, mlast0, iupbs01, nmwrd, bort_target_set
236 
237  ! Check for I8 integers
238 
239  if(im8b) then
240  im8b=.false.
241  call x84(lunit,my_lunit,1)
242  call x84(lundx,my_lundx,1)
243  call x84(inew,my_inew,1)
244  if (my_inew==0) then
245  nmesg = 0
246  else
247  nmesg = msgp(0)
248  call x84(mesg(1),mesg(1),nmesg)
249  endif
250  call ufbmex(my_lunit,my_lundx,my_inew,iret,mesg(1))
251  call x48(mesg(1),mesg(1),nmesg+iret)
252  call x48(iret,iret,1)
253  im8b=.true.
254  return
255  endif
256 
257  ! If we're catching bort errors, set a target return location if one doesn't already exist.
258 
259  if (bort_target_set() == 1) then
260  call catch_bort_ufbmex_c(lunit,lundx,inew,iret,mesg)
261  call bort_target_unset
262  return
263  endif
264 
265  ! Try to open BUFR file and set to initialize or concatenate
266 
267  call openbf(lunit,'IN',lundx)
268 
269  if(inew==0) then
270  msgp(0) = 0
271  munit = 0
272  mlast = 0
273  ndxts = 0
274  ldxts = 0
275  ndxm = 0
276  ldxm = 0
277  endif
278 
279  nmsg = msgp(0)
280  iret = 0
281  iflg = 0
282  itim = 0
283 
284  ! Set some flags so that subsequent calls to the message reading routines will know there is a BUFR table in scope.
285 
286  ndxts = 1
287  ldxts = 1
288  ipmsgs(1) = 1
289 
290  ! Transfer messages from file to memory and set message pointers.
291 
292  do while (.true.)
293  call rdmsgw(lunit,mgwa,ier)
294  if(ier==-1) exit
295  if(ier==-2) then
296  write(bort_str,'("BUFRLIB: UFBMEX - ERROR READING MESSAGE NUMBER",I5," INTO MEMORY FROM UNIT",I3)') nmsg+1,lunit
297  call bort(bort_str)
298  endif
299 
300  nmsg = nmsg+1
301  mesg(nmsg) = iupbs01(mgwa,'MTYP')
302  if(nmsg>maxmsg) iflg = 1
303  lmem = nmwrd(mgwa)
304  if(lmem+mlast>maxmem) iflg = 2
305 
306  if(iflg==0) then
307  iret = iret+1
308  do i=1,lmem
309  msgs(mlast+i) = mgwa(i)
310  enddo
311  msgp(0) = nmsg
312  msgp(nmsg) = mlast+1
313  else
314  if(itim==0) then
315  mlast0 = mlast
316  itim=1
317  endif
318  endif
319  mlast = mlast+lmem
320  enddo
321 
322  if(iflg==1) then
323  ! Emergency room treatment for maxmsg array overflow
324  if(iprt>=0) then
325  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
326  write ( unit=errstr, fmt='(A,A,I8,A)' ) 'BUFRLIB: UFBMEX - THE NO. OF MESSAGES REQUIRED TO STORE ', &
327  'ALL MESSAGES INTERNALLY EXCEEDS MAXIMUM (', maxmsg, ') - INCOMPLETE READ'
328  call errwrt(errstr)
329  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEX STORED ', msgp(0), ' MESSAGES OUT OF ', nmsg, '<<<'
330  call errwrt(errstr)
331  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEX STORED ', mlast0, ' BYTES OUT OF ', mlast, '<<<'
332  call errwrt(errstr)
333  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
334  call errwrt(' ')
335  endif
336  mlast=mlast0
337  endif
338 
339  if(iflg==2) then
340  ! Emergency room treatment for maxmem array overflow
341  if(iprt>=0) then
342  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
343  write ( unit=errstr, fmt='(A,A,I8,A)' ) 'BUFRLIB: UFBMEX - THE NO. OF BYTES REQUIRED TO STORE ', &
344  'ALL MESSAGES INTERNALLY EXCEEDS MAXIMUM (', maxmem, ') - INCOMPLETE READ'
345  call errwrt(errstr)
346  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEX STORED ', mlast0, ' BYTES OUT OF ', mlast, '<<<'
347  call errwrt(errstr)
348  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBMEX STORED ', msgp(0), ' MESSAGES OUT OF ', nmsg, '<<<'
349  call errwrt(errstr)
350  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
351  call errwrt(' ')
352  endif
353  mlast=mlast0
354  endif
355 
356  if(iret==0) then
357  call closbf(lunit)
358  else
359  if(munit/=0) call closbf(lunit)
360  if(munit==0) munit = lunit
361  endif
362 
363  return
364 end subroutine ufbmex
365 
391 recursive subroutine readmm(imsg,subset,jdate,iret)
392 
393  use modv_vars, only: im8b
394 
395  implicit none
396 
397  integer, intent(inout) :: imsg
398  integer, intent(out) :: jdate, iret
399 
400  character*8, intent(out) :: subset
401 
402  ! Check for I8 integers.
403 
404  if(im8b) then
405  im8b=.false.
406  call x84(imsg,imsg,1)
407  call readmm(imsg,subset,jdate,iret)
408  call x48(imsg,imsg,1)
409  call x48(jdate,jdate,1)
410  call x48(iret,iret,1)
411  im8b=.true.
412  return
413  endif
414 
415  call rdmemm(imsg,subset,jdate,iret)
416 
417  imsg = imsg+1
418 
419  return
420 end subroutine readmm
421 
441 recursive integer function ireadmm(imsg,subset,idate) result(iret)
442 
443  use modv_vars, only: im8b
444 
445  implicit none
446 
447  integer, intent(inout) :: imsg
448  integer, intent(out) :: idate
449 
450  character*8, intent(out) :: subset
451 
452  ! Check for I8 integers.
453 
454  if(im8b) then
455  im8b=.false.
456  call x84(imsg,imsg,1)
457  iret=ireadmm(imsg,subset,idate)
458  call x48(imsg,imsg,1)
459  call x48(idate,idate,1)
460  im8b=.true.
461  return
462  endif
463 
464  call readmm(imsg,subset,idate,iret)
465 
466  return
467 end function ireadmm
468 
492 recursive subroutine rdmemm(imsg,subset,jdate,iret)
493 
494  use bufrlib
495 
496  use modv_vars, only: im8b, iprt
497 
498  use moda_msgcwd
499  use moda_bitbuf
500  use moda_mgwa
501  use moda_msgmem
502 
503  implicit none
504 
505  integer, intent(in) :: imsg
506  integer, intent(out) :: jdate, iret
507  integer my_imsg, lun, il, im, ii, jj, kk, nwrd, iptr, lptr, ier, bort_target_set
508 
509  character*128 bort_str, errstr
510  character*8, intent(out) :: subset
511  character*9 csubset
512 
513  logical known
514 
515  ! Check for I8 integers
516 
517  if(im8b) then
518  im8b=.false.
519  call x84(imsg,my_imsg,1)
520  call rdmemm(my_imsg,subset,jdate,iret)
521  call x48(jdate,jdate,1)
522  call x48(iret,iret,1)
523  im8b=.true.
524  return
525  endif
526 
527  ! If we're catching bort errors, set a target return location if one doesn't already exist.
528 
529  if (bort_target_set() == 1) then
530  call catch_bort_rdmemm_c(imsg,csubset,jdate,len(csubset),iret)
531  subset(1:8) = csubset(1:8)
532  call bort_target_unset
533  return
534  endif
535 
536  ! Check the message request and file status
537 
538  call status(munit,lun,il,im)
539  call wtstat(munit,lun,il,1)
540  iret = 0
541 
542  if(imsg==0 .or.imsg>msgp(0)) then
543  call wtstat(munit,lun,il,0)
544  if(iprt>=1) then
545  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
546  if(imsg==0) then
547  errstr = 'BUFRLIB: RDMEMM - REQUESTED MEMORY MESSAGE NUMBER {FIRST (INPUT) ARGUMENT} IS 0, RETURN WITH IRET = -1'
548  else
549  write ( unit=errstr, fmt='(A,I6,A,I6,A)' ) 'BUFRLIB: RDMEMM - REQ. MEMORY MESSAGE #', imsg, &
550  ' {= 1ST (INPUT) ARG.} > # OF MESSAGES IN MEMORY (', msgp(0), '), RETURN WITH IRET = -1'
551  endif
552  call errwrt(errstr)
553  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
554  call errwrt(' ')
555  endif
556  iret = -1
557  return
558  endif
559 
560  ! Determine which table applies to this message.
561 
562  known = .false.
563  jj = ndxts
564  do while ((.not.known).and.(jj>=1))
565  if (ipmsgs(jj)<=imsg) then
566  known = .true.
567  else
568  jj = jj - 1
569  endif
570  enddo
571  if (.not.known) then
572  write(bort_str,'("BUFRLIB: RDMEMM - UNKNOWN DX TABLE FOR REQUESTED MESSAGE #",I5)') imsg
573  call bort(bort_str)
574  endif
575 
576  ! Is this table the one that is currently in scope?
577 
578  if (jj/=ldxts) then
579 
580  ! No, so reset the software to use the proper table.
581 
582  if(iprt>=2) then
583  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++')
584  write ( unit=errstr, fmt='(A,I3,A,I3,A,I6)' ) 'BUFRLIB: RDMEMM - RESETTING TO USE DX TABLE #', jj, &
585  ' INSTEAD OF DX TABLE #', ldxts, ' FOR REQUESTED MESSAGE #', imsg
586  call errwrt(errstr)
587  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++')
588  call errwrt(' ')
589  endif
590  call dxinit(lun,0)
591 
592  ! Store each of the DX dictionary messages which constitute this table.
593 
594  do ii = ifdxts(jj), (ifdxts(jj)+icdxts(jj)-1)
595  if (ii==ndxm) then
596  nwrd = ldxm - ipdxm(ii) + 1
597  else
598  nwrd = ipdxm(ii+1) - ipdxm(ii)
599  endif
600  do kk = 1, nwrd
601  mgwa(kk) = mdx(ipdxm(ii)+kk-1)
602  enddo
603  call stbfdx(lun,mgwa)
604  enddo
605 
606  ! Rebuild the internal jump/link table.
607 
608  call makestab
609  ldxts = jj
610  endif
611 
612  ! Read memory message number imsg into a message buffer.
613 
614  iptr = msgp(imsg)
615  if(imsg<msgp(0)) lptr = msgp(imsg+1)-iptr
616  if(imsg==msgp(0)) lptr = mlast-iptr+1
617  iptr = iptr-1
618 
619  do ii=1,lptr
620  mbay(ii,lun) = msgs(iptr+ii)
621  enddo
622 
623  ! Parse the message section contents.
624 
625  call cktaba(lun,subset,jdate,ier)
626  nmsg(lun) = imsg
627 
628  return
629 end subroutine rdmemm
630 
648 recursive subroutine rdmems(isub,iret)
649 
650  use bufrlib
651 
652  use modv_vars, only: im8b, iprt
653 
654  use moda_msgcwd
655  use moda_unptyp
656  use moda_bitbuf
657  use moda_msgmem
658 
659  implicit none
660 
661  integer, intent(in) :: isub
662  integer, intent(out) :: iret
663  integer my_isub, lun, il, im, mbym, nbyt, i, iupb, bort_target_set
664 
665  character*128 bort_str, errstr
666 
667  ! Check for I8 integers
668 
669  if(im8b) then
670  im8b=.false.
671  call x84(isub,my_isub,1)
672  call rdmems(my_isub,iret)
673  call x48(iret,iret,1)
674  im8b=.true.
675  return
676  endif
677 
678  ! If we're catching bort errors, set a target return location if one doesn't already exist.
679 
680  if (bort_target_set() == 1) then
681  call catch_bort_rdmems_c(isub,iret)
682  call bort_target_unset
683  return
684  endif
685 
686  ! Check the message request and file status
687 
688  call status(munit,lun,il,im)
689  if(im==0) call bort('BUFRLIB: RDMEMS - A MEMORY MESSAGE MUST BE OPEN IN INPUT BUFR FILE, NONE ARE')
690  if(nsub(lun)/=0) then
691  write(bort_str,'("BUFRLIB: RDMEMS - UPON ENTRY, SUBSET POINTER IN MEMORY MESSAGE IS NOT AT BEGINNING (",I3," '// &
692  'SUBSETS HAVE BEEN READ, SHOULD BE 0)")') nsub(lun)
693  call bort(bort_str)
694  endif
695 
696  if(isub>msub(lun)) then
697  if(iprt>=0) then
698  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
699  write ( unit=errstr, fmt='(A,I5,A,A,I5,A)' ) 'BUFRLIB: RDMEMS - REQ. SUBSET #', isub, ' (= 1st INPUT ', &
700  'ARG.) > # OF SUBSETS IN MEMORY MESSAGE (', msub(lun), ')'
701  call errwrt(errstr)
702  call errwrt('RETURN WITH IRET = -1')
703  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
704  call errwrt(' ')
705  endif
706  iret = -1
707  return
708  endif
709 
710  mbym = mbyt(lun)
711  nbyt = 0
712 
713  ! Position to subset number isub in memory message
714 
715  if(msgunp(lun)==0) then
716  nsub(lun) = isub-1
717  do i=1,isub-1
718  mbyt(lun) = mbyt(lun) + iupb(mbay(1,lun),mbyt(lun)+1,16)
719  enddo
720  elseif(msgunp(lun)==1) then
721  ! message with "standard" Section 3
722  do i=1,isub-1
723  call readsb(munit,iret)
724  enddo
725  else
726  ! compressed message
727  nsub(lun) = isub-1
728  endif
729 
730  ! Now read subset number isub from memory message
731 
732  call readsb(munit,iret)
733  if(iret/=0) call bort('BUFRLIB: RDMEMS - CALL TO ROUTINE READSB RETURNED WITH IRET = -1 (EITHER MEMORY MESSAGE '// &
734  'NOT OPEN OR ALL SUBSETS IN MESSAGE READ')
735 
736  ! Reset subset pointer back to zero (beginning of message) and return
737 
738  mbyt(lun) = mbym
739  nsub(lun) = 0
740 
741  return
742 end subroutine rdmems
743 
749 subroutine cpdxmm( lunit )
750 
751  use bufrlib
752 
753  use modv_vars, only: mxdxts, iprt
754 
755  use moda_mgwa
756  use moda_msgmem
757 
758  implicit none
759 
760  integer, intent(in) :: lunit
761  integer ict, lun, il, im, ier, j, lmem, idxmsg, iupbs3, nmwrd
762 
763  character*128 errstr
764 
765  logical done
766 
767  if ( ndxts >= mxdxts ) call bort('BUFRLIB: CPDXMM - MXDXTS OVERFLOW')
768 
769  ict = 0
770  done = .false.
771  call status(lunit,lun,il,im)
772 
773  ! Read a complete dictionary table from lunit, as a set of one or more DX dictionary messages.
774 
775  do while ( .not. done )
776  call rdmsgw ( lunit, mgwa, ier )
777  if ( ier == -2 ) call bort('BUFRLIB: CPDXMM - UNEXPECTED READ ERROR')
778  if ( ier == -1 ) then
779 
780  ! Don't abort for an end-of-file condition, since it may be possible for a file to end with dictionary messages.
781  ! Instead, backspace the file pointer and let the calling routine diagnose the end-of-file condition and deal with
782  ! it as it sees fit.
783 
784  call backbufr_c(lun)
785  done = .true.
786  else if ( idxmsg(mgwa) /= 1 ) then
787 
788  ! This is a non-DX dictionary message. Assume we've reached the end of the dictionary table, and backspace lunit so
789  ! that the next read (e.g. in the calling routine) will get this same message.
790 
791  call backbufr_c(lun)
792  done = .true.
793  else if ( iupbs3(mgwa,'nsub') == 0 ) then
794 
795  ! This is a DX dictionary message, but it doesn't contain any actual dictionary information. Assume we've reached the
796  ! end of the dictionary table.
797 
798  done = .true.
799  else
800 
801  ! Store this message into @ref moda_msgmem.
802 
803  ict = ict + 1
804  if ( ( ndxm + ict ) > mxdxm ) call bort('BUFRLIB: CPDXMM - MXDXM OVERFLOW')
805  ipdxm(ndxm+ict) = ldxm + 1
806  lmem = nmwrd(mgwa)
807  if ( ( ldxm + lmem ) > mxdxw ) call bort('BUFRLIB: CPDXMM - MXDXW OVERFLOW')
808  do j = 1, lmem
809  mdx(ldxm+j) = mgwa(j)
810  enddo
811  ldxm = ldxm + lmem
812  endif
813  enddo
814 
815  ! Update the table information within @ref moda_msgmem.
816 
817  if ( ict > 0 ) then
818  ifdxts(ndxts+1) = ndxm + 1
819  icdxts(ndxts+1) = ict
820  ipmsgs(ndxts+1) = msgp(0) + 1
821  ndxm = ndxm + ict
822  ndxts = ndxts + 1
823  if ( iprt >= 2 ) then
824  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++')
825  write ( unit=errstr, fmt='(A,I3,A,I3,A)') 'BUFRLIB: CPDXMM - STORED NEW DX TABLE #', ndxts, &
826  ' CONSISTING OF ', ict, ' MESSAGES'
827  call errwrt(errstr)
828  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++')
829  call errwrt(' ')
830  endif
831  endif
832 
833  return
834 end subroutine cpdxmm
835 
857 recursive subroutine ufbmms(imsg,isub,subset,jdate)
858 
859  use bufrlib
860 
861  use modv_vars, only: im8b
862 
863  use moda_msgcwd
864  use moda_msgmem
865 
866  implicit none
867 
868  integer, intent(in) :: imsg, isub
869  integer, intent(out) :: jdate
870  integer my_imsg, my_isub, lun, il, im, iret, bort_target_set
871 
872  character*8, intent(out) :: subset
873  character*128 bort_str
874  character*9 csubset
875 
876  ! Check for I8 integers
877 
878  if(im8b) then
879  im8b=.false.
880  call x84(imsg,my_imsg,1)
881  call x84(isub,my_isub,1)
882  call ufbmms(my_imsg,my_isub,subset,jdate)
883  call x48(jdate,jdate,1)
884  im8b=.true.
885  return
886  endif
887 
888  ! If we're catching bort errors, set a target return location if one doesn't already exist.
889 
890  if (bort_target_set() == 1) then
891  call catch_bort_ufbmms_c(imsg,isub,csubset,jdate,len(csubset))
892  subset(1:8) = csubset(1:8)
893  call bort_target_unset
894  return
895  endif
896 
897  ! Read subset #isub from memory message #imsg
898 
899  call rdmemm(imsg,subset,jdate,iret)
900  if(iret<0) then
901  if(imsg>0) then
902  write(bort_str,'("BUFRLIB: UFBMMS - REQUESTED MEMORY MESSAGE NUMBER TO READ IN (",I5,") EXCEEDS THE NUMBER OF '// &
903  'MESSAGES IN MEMORY (",I5,")")') imsg,msgp(0)
904  else
905  write(bort_str,'("BUFRLIB: UFBMMS - REQUESTED MEMORY MESSAGE NUMBER TO READ IN IS ZERO - THIS IS NOT VALID")')
906  endif
907  call bort(bort_str)
908  endif
909  call rdmems(isub,iret)
910  if(iret/=0) then
911  call status(munit,lun,il,im)
912  write(bort_str,'("BUFRLIB: UFBMMS - REQ. SUBSET NUMBER TO READ IN (",I3,") EXCEEDS THE NUMBER OF SUBSETS (",I3,") '// &
913  'IN THE REG. MEMORY MESSAGE (",I5,")")') isub,msub(lun),imsg
914  call bort(bort_str)
915  endif
916 
917  return
918 end subroutine ufbmms
919 
937 recursive subroutine ufbmns(irep,subset,idate)
938 
939  use bufrlib
940 
941  use modv_vars, only: im8b
942 
943  use moda_msgmem
944 
945  implicit none
946 
947  integer, intent(in) :: irep
948  integer, intent(out) :: idate
949  integer my_irep, imsg, jrep, iret, ireadmm, nmsub, bort_target_set
950 
951  character*8, intent(out) :: subset
952  character*128 bort_str
953  character*9 csubset
954 
955  ! Check for I8 integers
956 
957  if(im8b) then
958  im8b=.false.
959  call x84(irep,my_irep,1)
960  call ufbmns(my_irep,subset,idate)
961  call x48(idate,idate,1)
962  im8b=.true.
963  return
964  endif
965 
966  ! If we're catching bort errors, set a target return location if one doesn't already exist.
967 
968  if (bort_target_set() == 1) then
969  call catch_bort_ufbmns_c(irep,csubset,idate,len(csubset))
970  subset(1:8) = csubset(1:8)
971  call bort_target_unset
972  return
973  endif
974 
975  jrep = 0
976  imsg = 1
977 
978  ! Read subset #irep
979 
980  do while(ireadmm(imsg,subset,idate)==0)
981  if(jrep+nmsub(munit)>=irep) then
982  call rdmems(irep-jrep,iret)
983  return
984  endif
985  jrep = jrep+nmsub(munit)
986  enddo
987 
988  write(bort_str,'("BUFRLIB: UFBMNS - REQ. SUBSET NO. TO READ IN (",I5,") EXCEEDS TOTAL NO. OF SUBSETS IN THE COLLECTION '// &
989  'OF MEMORY MESSAGES (",I5,")")') irep,jrep
990  call bort(bort_str)
991 end subroutine ufbmns
992 
1012 recursive subroutine ufbrms(imsg,isub,usr,i1,i2,iret,str)
1013 
1014  use bufrlib
1015 
1016  use modv_vars, only: im8b, iprt
1017 
1018  use moda_msgcwd
1019  use moda_msgmem
1020 
1021  implicit none
1022 
1023  integer, intent(in) :: imsg, isub, i1, i2
1024  integer, intent(out) :: iret
1025  integer my_imsg, my_isub, my_i1, my_i2, jdate, lun, il, im, lcstr, bort_target_set
1026 
1027  real*8, intent(out) :: usr(i1,i2)
1028 
1029  character*(*), intent(in) :: str
1030  character*128 bort_str, errstr
1031  character*90 cstr
1032  character*8 subset
1033 
1034  ! Check for I8 integers
1035 
1036  if(im8b) then
1037  im8b=.false.
1038  call x84(imsg,my_imsg,1)
1039  call x84(isub,my_isub,1)
1040  call x84(i1,my_i1,1)
1041  call x84(i2,my_i2,1)
1042  call ufbrms(my_imsg,my_isub,usr,my_i1,my_i2,iret,str)
1043  call x48(iret,iret,1)
1044  im8b=.true.
1045  return
1046  endif
1047 
1048  ! If we're catching bort errors, set a target return location if one doesn't already exist.
1049  if (bort_target_set() == 1) then
1050  call strsuc(str,cstr,lcstr)
1051  call catch_bort_ufbrms_c(imsg,isub,usr,i1,i2,iret,cstr,lcstr)
1052  call bort_target_unset
1053  return
1054  endif
1055 
1056  iret = 0
1057  if(i1<=0) then
1058  if(iprt>=0) then
1059  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1060  errstr = .LE.'BUFRLIB: UFBRMS - 4th ARG. (INPUT) IS 0, SO RETURN WITH 6th ARG. (IRET) = 0; 7th ARG. (STR) ='
1061  call errwrt(errstr)
1062  call errwrt(str)
1063  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1064  call errwrt(' ')
1065  endif
1066  return
1067  elseif(i2<=0) then
1068  if(iprt>=0) then
1069  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1070  errstr = .LE.'BUFRLIB: UFBRMS - 5th ARG. (INPUT) IS 0, SO RETURN WITH 6th ARG. (IRET) = 0; 7th ARG. (STR) ='
1071  call errwrt(errstr)
1072  call errwrt(str)
1073  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1074  call errwrt(' ')
1075  endif
1076  return
1077  endif
1078 
1079  ! Read requested values from subset #isub within memory message #imsg
1080 
1081  call rdmemm(imsg,subset,jdate,iret)
1082  if(iret<0) then
1083  if(imsg>0) then
1084  write(bort_str,'("BUFRLIB: UFBRMS - REQUESTED MEMORY MESSAGE NUMBER TO READ IN (",I5,") EXCEEDS THE NUMBER OF '// &
1085  'MESSAGES IN MEMORY (",I5,")")') imsg,msgp(0)
1086  else
1087  write(bort_str,'("BUFRLIB: UFBRMS - REQUESTED MEMORY MESSAGE NUMBER TO READ IN IS ZERO - THIS IS NOT VALID")')
1088  endif
1089  call bort(bort_str)
1090  endif
1091  call rdmems(isub,iret)
1092  if(iret/=0) then
1093  call status(munit,lun,il,im)
1094  write(bort_str,'("BUFRLIB: UFBRMS - REQ. SUBSET NUMBER TO READ IN (",I3,") EXCEEDS THE NUMBER OF SUBSETS (",I3,") '// &
1095  'IN THE REG. MEMORY MESSAGE (",I5,")")') isub,msub(lun),imsg
1096  call bort(bort_str)
1097  endif
1098 
1099  call ufbint(munit,usr,i1,i2,iret,str)
1100 
1101  return
1102 end subroutine ufbrms
1103 
1145 recursive subroutine ufbtam(tab,i1,i2,iret,str)
1146 
1147  use bufrlib
1148 
1149  use modv_vars, only: im8b, bmiss, iprt
1150 
1151  use moda_usrint
1152  use moda_msgcwd
1153  use moda_bitbuf
1154  use moda_msgmem
1155  use moda_tables
1156 
1157  implicit none
1158 
1159  character*(*), intent(in) :: str
1160  character*128 bort_str, errstr
1161  character*90 cstr
1162  character*10 tgs(100)
1163  character*8 subset, cval
1164 
1165  integer*8 mps, ival
1166  integer, intent(in) :: i1, i2
1167  integer, intent(out) :: iret
1168  integer maxtg, nnod, ncon, nods, nodc, ivls, kons, my_i1, my_i2, i, irec, isub, itbl, lun, il, im, jdate, mret, &
1169  kbit, mbit, nbit, n, node, imsg, kmsg, nrep, ntg, nbyt, nbmp, nmsub, lcstr, bort_target_set
1170 
1171  real*8, intent(out) :: tab(i1,i2)
1172  real*8 rval, ups
1173 
1174  common /usrstr/ nnod,ncon,nods(20),nodc(10),ivls(10),kons(10)
1175 
1176  equivalence(cval,rval)
1177 
1178  data maxtg /100/
1179 
1180  ! Statement function
1181  mps(node) = 2_8**(ibt(node))-1
1182 
1183  ! Check for I8 integers
1184 
1185  if(im8b) then
1186  im8b=.false.
1187  call x84(i1,my_i1,1)
1188  call x84(i2,my_i2,1)
1189  call ufbtam(tab,my_i1,my_i2,iret,str)
1190  call x48(iret,iret,1)
1191  im8b=.true.
1192  return
1193  endif
1194 
1195  ! If we're catching bort errors, set a target return location if one doesn't already exist.
1196  if (bort_target_set() == 1) then
1197  call strsuc(str,cstr,lcstr)
1198  call catch_bort_ufbtam_c(tab,i1,i2,iret,cstr,lcstr)
1199  call bort_target_unset
1200  return
1201  endif
1202 
1203  iret = 0
1204 
1205  if(msgp(0)==0) return
1206 
1207  tab(1:i1,1:i2) = bmiss
1208 
1209  ! Check for special tags in string
1210 
1211  call parstr(str,tgs,maxtg,ntg,' ',.true.)
1212  irec = 0
1213  isub = 0
1214  itbl = 0
1215  do i=1,ntg
1216  if(tgs(i)=='IREC') irec = i
1217  if(tgs(i)=='ISUB') isub = i
1218  if(tgs(i)=='ITBL') itbl = i
1219  enddo
1220 
1221  call status(munit,lun,il,im)
1222 
1223  ! Cycle through all of the memory messages in the internal arrays
1224 
1225  outer: do imsg=1,msgp(0)
1226  call rdmemm(imsg,subset,jdate,mret)
1227  if(mret<0) then
1228  write(bort_str,'("BUFRLIB: UFBTAM - HIT END-OF-FILE READING MESSAGE NUMBER",I5," IN INTERNAL MEMORY")') imsg
1229  call bort(bort_str)
1230  endif
1231 
1232  call string(str,lun,i1,0)
1233  if(irec>0) nods(irec) = 0
1234  if(isub>0) nods(isub) = 0
1235  if(itbl>0) nods(itbl) = 0
1236 
1237  ! Process all the subsets in the memory message
1238 
1239  do while (nsub(lun)<msub(lun))
1240  if(iret+1>i2) then
1241  ! Emergency room treatment for array overflow
1242  call rdmemm(0,subset,jdate,mret)
1243  nrep = 0
1244  do kmsg=1,msgp(0)
1245  call rdmemm(kmsg,subset,jdate,mret)
1246  if(mret<0) then
1247  write(bort_str,'("BUFRLIB: UFBTAM - HIT END-OF-FILE READING MESSAGE NUMBER",I5," IN INTERNAL MEMORY")') kmsg
1248  call bort(bort_str)
1249  endif
1250  nrep = nrep+nmsub(munit)
1251  enddo
1252  if(iprt>=0) then
1253  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1254  write ( unit=errstr, fmt='(A,A,I8,A,A)' ) 'BUFRLIB: UFBTAM - THE NO. OF DATA SUBSETS IN MEMORY ', &
1255  .GT.'IS LIMIT OF ', i2, ' IN THE 3RD ARG. (INPUT) - INCOMPLETE READ'
1256  call errwrt(errstr)
1257  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBTAM STORED ', iret, ' REPORTS OUT OF ', nrep, '<<<'
1258  call errwrt(errstr)
1259  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1260  call errwrt(' ')
1261  endif
1262  exit outer
1263  endif
1264 
1265  iret = iret+1
1266 
1267  do i=1,nnod
1268  nods(i) = abs(nods(i))
1269  enddo
1270 
1271  call usrtpl(lun,1,1)
1272  mbit = mbyt(lun)*8+16
1273  nbit = 0
1274  n = 1
1275 
1276  inner: do while(n+1<=nval(lun))
1277  n = n+1
1278  node = inv(n,lun)
1279  mbit = mbit+nbit
1280  nbit = ibt(node)
1281  if(itp(node)==1) then
1282  call upb8(ival,nbit,mbit,mbay(1,lun))
1283  nbmp=int(ival)
1284  call usrtpl(lun,n,nbmp)
1285  endif
1286  do i=1,nnod
1287  if(nods(i)==node) then
1288  if(itp(node)==1) then
1289  call upb8(ival,nbit,mbit,mbay(1,lun))
1290  tab(i,iret) = ival
1291  elseif(itp(node)==2) then
1292  call upb8(ival,nbit,mbit,mbay(1,lun))
1293  if(ival<mps(node)) tab(i,iret) = ups(ival,node)
1294  elseif(itp(node)==3) then
1295  cval = ' '
1296  kbit = mbit
1297  call upc(cval,nbit/8,mbay(1,lun),kbit,.true.)
1298  tab(i,iret) = rval
1299  endif
1300  nods(i) = -nods(i)
1301  cycle inner
1302  endif
1303  enddo
1304  do i=1,nnod
1305  if(nods(i)>0) cycle inner
1306  enddo
1307  enddo inner
1308 
1309  ! Update the subset pointers before next read
1310 
1311  ibit = mbyt(lun)*8
1312  call upb(nbyt,16,mbay(1,lun),ibit)
1313  mbyt(lun) = mbyt(lun) + nbyt
1314  nsub(lun) = nsub(lun) + 1
1315  if(irec>0) tab(irec,iret) = nmsg(lun)
1316  if(isub>0) tab(isub,iret) = nsub(lun)
1317  if(itbl>0) tab(itbl,iret) = ldxts
1318  enddo
1319 
1320  enddo outer
1321 
1322  ! Reset the memory file
1323  call rdmemm(0,subset,jdate,mret)
1324 
1325  return
1326 end subroutine ufbtam
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 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
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 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 stbfdx(lun, mesg)
Copy a DX BUFR tables message into the internal memory arrays in module moda_tababd.
Definition: dxtable.F90:987
subroutine dxinit(lun, ioi)
Clear out the internal arrays (in module moda_tababd) holding the DX BUFR table, then optionally init...
Definition: dxtable.F90:604
integer function idxmsg(mesg)
Check whether a BUFR message contains DX BUFR tables information that was generated by the NCEPLIBS-b...
Definition: dxtable.F90:1120
subroutine errwrt(str)
Specify a custom location for the logging of error and diagnostic messages generated by the NCEPLIBS-...
Definition: errwrt.F90:32
recursive subroutine rdmems(isub, iret)
Read a specified data subset from the BUFR message that was most recently read via a call to subrouti...
Definition: memmsgs.F90:649
subroutine cpdxmm(lunit)
Read an entire DX BUFR table from a specified file into internal memory arrays.
Definition: memmsgs.F90:750
recursive subroutine rdmemm(imsg, subset, jdate, iret)
Read a specified BUFR message from internal arrays in memory, so that it is now in scope for processi...
Definition: memmsgs.F90:493
recursive subroutine ufbmem(lunit, inew, iret, iunit)
Connect a new file to the NCEPLIBS-bufr software for input operations, then read the entire file cont...
Definition: memmsgs.F90:39
recursive subroutine readmm(imsg, subset, jdate, iret)
Read a specified BUFR message from internal arrays in memory, so that it is now in scope for processi...
Definition: memmsgs.F90:392
recursive subroutine ufbmex(lunit, lundx, inew, iret, mesg)
Connect a new file to the NCEPLIBS-bufr software for input operations, then read the entire file cont...
Definition: memmsgs.F90:221
recursive subroutine ufbmns(irep, subset, idate)
Read a specified data subset from internal arrays in memory, so that it is now in scope for processin...
Definition: memmsgs.F90:938
recursive subroutine ufbrms(imsg, isub, usr, i1, i2, iret, str)
Read one or more data values from a data subset in internal arrays.
Definition: memmsgs.F90:1013
recursive subroutine ufbtam(tab, i1, i2, iret, str)
Read through every data subset in internal arrays and return one or more specified data values from e...
Definition: memmsgs.F90:1146
recursive subroutine ufbmms(imsg, isub, subset, jdate)
Read a specified data subset from internal arrays.
Definition: memmsgs.F90:858
recursive integer function ireadmm(imsg, subset, idate)
Call subroutine readmm() and pass back its return code as the function value.
Definition: memmsgs.F90:442
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 BUFR messages internally for multiple file IDs.
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.
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 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 the contents of one or more BUFR files within internal mem...
integer, dimension(:), allocatable msgp
Pointers to the beginning of each message within msgs (up to a maximum of maxmsg, and where array ele...
integer, dimension(:), allocatable ipmsgs
Pointers to first message within msgs for which each DX BUFR table applies.
integer, dimension(:), allocatable msgs
BUFR messages read from one or more BUFR files.
integer, dimension(:), allocatable icdxts
Number of consecutive messages within mdx which constitute each DX BUFR table, beginning with the cor...
integer mxdxm
Maximum number of DX BUFR table messages that can be stored within mdx.
integer, dimension(:), allocatable ifdxts
Pointers to the beginning of each DX BUFR table within mdx.
integer munit
Fortran logical unit number for use in accessing contents of BUFR files within internal memory.
integer ndxm
Number of DX BUFR table messages stored within mdx (up to a maximum of mxdxm).
integer ldxm
Number of array elements filled within mdx (up to a maximum of mxdxw).
integer mlast
Number of array elements filled within msgs (up to a maximum of maxmem).
integer ldxts
Number of DX BUFR table that is currently in scope, depending on which BUFR message within msgs is cu...
integer ndxts
Number of DX BUFR tables represented by the messages within mdx (up to a maximum of mxdxts).
integer, dimension(:), allocatable mdx
DX BUFR table messages read from one or more BUFR files, for use in decoding the messages in msgs.
integer mxdxw
Maximum number of entries that can be stored within mdx.
integer, dimension(:), allocatable ipdxm
Pointers to the beginning of each message within mdx.
Declare arrays and variables used to store the internal jump/link table.
integer, dimension(:), allocatable ibt
Bit widths corresponding to tag and typ:
integer, dimension(:), allocatable itp
Integer type values corresponding to typ:
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 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.
integer, dimension(:,:), allocatable, target inv
Inventory pointer which links each data value to its corresponding node in the internal jump/link tab...
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...
subroutine wtstat(lunit, lun, il, im)
Update file status in library internals.
recursive integer function nmsub(lunit)
Get the total number of data subsets available within the BUFR message that was most recently opened ...
integer function nmwrd(mbay)
Given an integer array containing Section 0 from a BUFR message, determine the array size (in integer...
subroutine rdmsgw(lunit, mesg, iret)
Read the next BUFR message from logical unit lunit as an array of integer words.
subroutine usrtpl(lun, invn, nbmp)
Expand a subset template within internal arrays.
recursive subroutine readsb(lunit, iret)
Read the next data subset from a BUFR message.
Definition: readwritesb.F90:32
recursive subroutine ufbint(lunin, usr, i1, i2, iret, str)
Read or write one or more data values from or to a data subset.
subroutine cktaba(lun, subset, jdate, iret)
Get the Table A mnemonic from Sections 1 and 3 of a BUFR message.
Definition: s013vals.F90:1332
recursive integer function iupbs01(mbay, s01mnem)
Read a specified value from within Section 0 or Section 1 of a BUFR message.
Definition: s013vals.F90:245
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 string(str, lun, i1, io)
Check whether a string is in the internal mnemonic string cache.
Definition: strings.F90:25
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