NCEPLIBS-bufr  12.3.0
openclosebf.F90
Go to the documentation of this file.
1 
5 
15 recursive subroutine fortran_open(filename, lunit, format, position, iret)
16 
17  use modv_vars, only: im8b
18 
19  implicit none
20  character*(*), intent(in) :: filename, format, position
21  integer, intent(in) :: lunit
22  integer, intent(out) :: iret
23  integer my_lunit
24 
25  ! check for i8 integers
26 
27  if(im8b) then
28  im8b=.false.
29  call x84(lunit,my_lunit,1)
30  call fortran_open(filename,my_lunit,format,position,iret)
31  call x48(iret,iret,1)
32  im8b=.true.
33  return
34  endif
35 
36  open(lunit, file=trim(filename), form=trim(format), position=trim(position), iostat=iret)
37  return
38 end subroutine fortran_open
39 
46 recursive subroutine fortran_close(lunit, iret)
47 
48  use modv_vars, only: im8b
49 
50  implicit none
51  integer, intent(in) :: lunit
52  integer, intent(out) :: iret
53  integer my_lunit
54 
55  ! check for i8 integers
56 
57  if(im8b) then
58  im8b=.false.
59  call x84(lunit,my_lunit,1)
60  call fortran_close(my_lunit,iret)
61  call x48(iret,iret,1)
62  im8b=.true.
63  return
64  endif
65 
66  close(lunit, iostat=iret)
67  return
68 end subroutine fortran_close
69 
163 recursive subroutine openbf(lunit,io,lundx)
164 
165  use bufrlib
166 
167  use modv_vars, only: im8b, ifopbf, nfiles, iprt
168 
169  use moda_msgcwd
170  use moda_stbfr
171  use moda_sc3bfr
172  use moda_lushr
173  use moda_nulbfr
174  use moda_stcode
175 
176  implicit none
177 
178  integer, intent(in) :: lunit, lundx
179  integer my_lunit, my_lundx, iprtprv, lun, il, im, lcio, bort_target_set
180 
181  character*(*), intent(in) :: io
182  character*255 filename, fileacc
183  character*128 bort_str, errstr
184  character*28 cprint(0:4)
185  character*6 cio
186 
187  data cprint/ &
188  ' (only aborts) ', &
189  ' (limited -default) ', &
190  ' (all warnings) ', &
191  ' (all warnings+infos) ', &
192  ' (all warnings+infos+debugs)'/
193 
194  ! Check for i8 integers
195 
196  if(im8b) then
197  im8b=.false.
198  call x84(lunit,my_lunit,1)
199  call x84(lundx,my_lundx,1)
200  call openbf(my_lunit,io,my_lundx)
201  im8b=.true.
202  return
203  endif
204 
205  ! If we're catching bort errors, set a target return location if one doesn't already exist.
206 
207  if (bort_target_set() == 1) then
208  call strsuc(io,cio,lcio)
209  call catch_bort_openbf_c(lunit,cio,lundx,lcio)
210  call bort_target_unset
211  return
212  endif
213 
214  if(io=='QUIET') then
215  ! Override previous iprt value
216  iprtprv = iprt
217  iprt = lundx
218  if(iprt<-1) iprt = -1
219  if(iprt>3) iprt = 3
220  if(iprt>=0) then
221  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
222  write ( unit=errstr, fmt='(A,I3,A,A,I3,A)' ) 'BUFRLIB: OPENBF - DEGREE OF MESSAGE PRINT INDICATOR CHNGED FROM', &
223  iprtprv,cprint(iprtprv+1),' TO',iprt,cprint(iprt+1)
224  call errwrt(errstr)
225  call errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
226  call errwrt(' ')
227  endif
228  endif
229 
230  if(ifopbf==0) then
231  ! This is the first call to this subroutine, so take care of some initial housekeeping tasks.
232  ! Note that arallocf and arallocc_c must be called before calling bfrini.
233 
234  ! Allocate internal arrays.
235  call arallocf
236  call arallocc_c
237 
238  ! Initialize some global variables.
239  call bfrini
240 
241  ifopbf = 1
242  endif
243  if( (io=='FIRST') .or. (io=='QUIET') ) return
244 
245  ! See if a file can be opened
246 
247  call status(lunit,lun,il,im)
248  if(lun==0) then
249  write(bort_str,'("BUFRLIB: OPENBF - THERE ARE ALREADY",I3," BUFR FILES OPENED, CANNOT OPEN FILE CONNECTED TO UNIT",I4)') &
250  nfiles,lunit
251  call bort(bort_str)
252  endif
253  if(il/=0) then
254  write(bort_str,'("BUFRLIB: OPENBF - THE FILE CONNECTED TO UNIT",I5," IS ALREADY OPEN")') lunit
255  call bort(bort_str)
256  endif
257  null(lun) = 0
258  isc3(lun) = 0
259  iscodes(lun) = 0
260  lus(lun) = 0
261 
262  ! Use inquire to obtain the filename associated with unit lunit
263 
264  if (io/='NUL' .and. io/='INUL') then
265  inquire(lunit,access=fileacc)
266  if(fileacc=='UNDEFINED') open(lunit)
267  inquire(lunit,name=filename)
268  filename=trim(filename)//char(0)
269  endif
270 
271  nmsg(lun) = 0
272  nsub(lun) = 0
273  msub(lun) = 0
274  inode(lun) = 0
275  idate(lun) = 0
276 
277  ! Decide how to open the file and setup the dictionary
278 
279  if(io=='IN') then
280  call openrb_c(lun,filename)
281  call wtstat(lunit,lun,-1,0)
282  call readdx(lunit,lun,lundx)
283  else if(io=='INUL') then
284  call wtstat(lunit,lun,-1,0)
285  if(lunit/=lundx) call readdx(lunit,lun,lundx)
286  null(lun) = 1
287  else if(io=='NUL') then
288  call wtstat(lunit,lun,1,0)
289  if(lunit/=lundx) call readdx(lunit,lun,lundx)
290  null(lun) = 1
291  else if(io=='INX') then
292  call openrb_c(lun,filename)
293  call wtstat(lunit,lun,-1,0)
294  null(lun) = 1
295  else if(io=='OUX') then
296  call openwb_c(lun,filename)
297  call wtstat(lunit,lun,1,0)
298  else if(io=='SEC3') then
299  call openrb_c(lun,filename)
300  call wtstat(lunit,lun,-1,0)
301  isc3(lun) = 1
302  else if(io=='OUT') then
303  call openwb_c(lun,filename)
304  call wtstat(lunit,lun,1,0)
305  call writdx(lunit,lun,lundx)
306  else if(io=='NODX') then
307  call openwb_c(lun,filename)
308  call wtstat(lunit,lun,1,0)
309  call readdx(lunit,lun,lundx)
310  else if(io=='APN' .or. io=='APX') then
311  call openab_c(lun,filename)
312  call wtstat(lunit,lun,1,0)
313  if(lunit/=lundx) call readdx(lunit,lun,lundx)
314  call posapx(lunit)
315  else
316  call bort('BUFRLIB: OPENBF - ILLEGAL SECOND (INPUT) ARGUMENT')
317  endif
318 
319  return
320 end subroutine openbf
321 
334 recursive subroutine closbf(lunit)
335 
336  use bufrlib
337 
338  use modv_vars, only: im8b
339 
340  use moda_nulbfr
341 
342  implicit none
343 
344  character*128 errstr
345 
346  integer, intent(in) :: lunit
347  integer my_lunit, lun, il, im, bort_target_set
348 
349  ! Check for i8 integers
350 
351  if(im8b) then
352  im8b=.false.
353  call x84(lunit,my_lunit,1)
354  call closbf(my_lunit)
355  im8b=.true.
356  return
357  endif
358 
359  ! If we're catching bort errors, set a target return location if one doesn't already exist.
360 
361  if (bort_target_set() == 1) then
362  call catch_bort_closbf_c(lunit)
363  call bort_target_unset
364  return
365  endif
366 
367  if ( .not. allocated(null) ) then
368  call errwrt('++++++++++++++++++++WARNING++++++++++++++++++++++')
369  errstr = 'BUFRLIB: CLOSBF WAS CALLED WITHOUT HAVING PREVIOUSLY CALLED OPENBF'
370  call errwrt(errstr)
371  call errwrt('++++++++++++++++++++WARNING++++++++++++++++++++++')
372  return
373  endif
374 
375  call status(lunit,lun,il,im)
376  if(il>0 .and. im/=0) call closmg(lunit)
377  if(il/=0 .and. null(lun)==0) call closfb_c(lun)
378  call wtstat(lunit,lun,0,0)
379 
380  ! Close Fortran unit if null(lun) = 0
381 
382  if(null(lun)==0) close(lunit)
383 
384  return
385 end subroutine closbf
386 
408 recursive subroutine status(lunit,lun,il,im)
409 
410  use bufrlib
411 
412  use modv_vars, only: im8b, nfiles
413 
414  use moda_stbfr
415 
416  implicit none
417 
418  integer, intent(in) :: lunit
419  integer, intent(out) :: lun, il, im
420  integer my_lunit, i, bort_target_set
421 
422  character*128 bort_str, errstr
423 
424  ! Check for I8 integers
425 
426  if(im8b) then
427  im8b=.false.
428  call x84(lunit,my_lunit,1)
429  call status(my_lunit,lun,il,im)
430  call x48(lun,lun,1)
431  call x48(il,il,1)
432  call x48(im,im,1)
433  im8b=.true.
434  return
435  endif
436 
437  ! If we're catching bort errors, set a target return location if one doesn't already exist.
438 
439  if (bort_target_set() == 1) then
440  call catch_bort_status_c(lunit,lun,il,im)
441  call bort_target_unset
442  return
443  endif
444 
445  if(lunit<=0 .or. lunit>99) then
446  write(bort_str,'("BUFRLIB: STATUS - INPUT UNIT NUMBER (",I3,") OUTSIDE LEGAL RANGE OF 1-99")') lunit
447  call bort(bort_str)
448  endif
449 
450  ! Clear the status indicators
451 
452  lun = 0
453  il = 0
454  im = 0
455 
456  ! See if the unit is already connected to the library
457 
458  if ( .not. allocated(iolun) ) then
459  call errwrt('++++++++++++++++++++WARNING++++++++++++++++++++++')
460  errstr = 'BUFRLIB: STATUS WAS CALLED WITHOUT HAVING PREVIOUSLY CALLED OPENBF'
461  call errwrt(errstr)
462  call errwrt('++++++++++++++++++++WARNING++++++++++++++++++++++')
463  return
464  endif
465 
466  do i=1,nfiles
467  if(abs(iolun(i))==lunit) lun = i
468  enddo
469 
470  ! If not, try to define it so as to connect it to the library
471 
472  if(lun==0) then
473  do i=1,nfiles
474  if(iolun(i)==0) then
475  ! File space is available, return with lun > 0, il and im remain 0
476  lun = i
477  return
478  endif
479  enddo
480  ! File space is NOT available, return with lun, il and im all 0
481  return
482  endif
483 
484  ! If the unit was already connected to the library prior to this call, then return statuses
485 
486  il = sign(1,iolun(lun))
487  im = iomsg(lun)
488 
489  return
490 end subroutine status
491 
519 subroutine wtstat(lunit,lun,il,im)
520 
521  use moda_stbfr
522 
523  implicit none
524 
525  integer, intent(in) :: lunit, lun, il, im
526 
527  character*128 bort_str
528 
529  ! Check on the arguments
530 
531  if(lunit<=0) then
532  write(bort_str,'("BUFRLIB: WTSTAT - INVALID UNIT NUMBER PASSED INTO FIRST ARGUMENT (INPUT) (=",I3,")")') lunit
533  call bort(bort_str)
534  endif
535  if(lun<=0) then
536  write(bort_str,'("BUFRLIB: WTSTAT - INVALID FILE ID PASSED INTO SECOND ARGUMENT (INPUT) (=",I3,")")') lun
537  call bort(bort_str)
538  endif
539  if(il<-1 .or. il>1) then
540  write(bort_str,'("BUFRLIB: WTSTAT - INVALID LOGICAL UNIT STATUS INDICATOR PASSED INTO THIRD ARGUMENT '// &
541  '(INPUT) (=",I4,")")') il
542  call bort(bort_str)
543  endif
544  if(im< 0 .or. im>1) then
545  write(bort_str,'("BUFRLIB: WTSTAT - INVALID BUFR MESSAGE STATUS INDICATOR PASSED INTO FOURTH ARGUMENT '// &
546  '(INPUT) (=",I4,")")') im
547  call bort(bort_str)
548  endif
549 
550  ! Check on lunit-lun combination
551 
552  if(abs(iolun(lun))/=lunit .and. (iolun(lun)/=0)) then
553  write(bort_str,'("BUFRLIB: WTSTAT - ATTEMPTING TO REDEFINE EXISTING FILE UNIT (LOGICAL UNIT '// &
554  'NUMBER ",I3,")")') iolun(lun)
555  call bort(bort_str)
556  endif
557 
558  ! Reset the file statuses
559 
560  if(il/=0) then
561  iolun(lun) = sign(lunit,il)
562  iomsg(lun) = im
563  else
564  iolun(lun) = 0
565  iomsg(lun) = 0
566  endif
567 
568  return
569 end subroutine wtstat
570 
596 recursive subroutine ufbcnt(lunit,kmsg,ksub)
597 
598  use bufrlib
599 
600  use modv_vars, only: im8b
601 
602  use moda_msgcwd
603 
604  implicit none
605 
606  integer, intent(in) :: lunit
607  integer, intent(out) :: kmsg, ksub
608  integer my_lunit, lun, il, im, bort_target_set
609 
610  ! Check for I8 integers
611 
612  if(im8b) then
613  im8b=.false.
614  call x84(lunit,my_lunit,1)
615  call ufbcnt(my_lunit,kmsg,ksub)
616  call x48(kmsg,kmsg,1)
617  call x48(ksub,ksub,1)
618  im8b=.true.
619  return
620  endif
621 
622  ! If we're catching bort errors, set a target return location if one doesn't already exist.
623 
624  if (bort_target_set() == 1) then
625  call catch_bort_ufbcnt_c(lunit, kmsg, ksub)
626  call bort_target_unset
627  return
628  endif
629 
630  ! Check the file status - return the message and subset counters
631 
632  call status(lunit,lun,il,im)
633  if(il==0) call bort('BUFRLIB: UFBCNT - BUFR FILE IS CLOSED, IT MUST BE OPEN FOR EITHER INPUT OR OUTPUT')
634  kmsg = nmsg(lun)
635  ksub = nsub(lun)
636 
637  return
638 end subroutine ufbcnt
639 
651 subroutine posapx(lunxx)
652 
653  use bufrlib
654 
655  use moda_mgwa
656 
657  implicit none
658 
659  integer, intent(in) :: lunxx
660  integer lunit, lun, il, im, ier, idxmsg
661 
662  lunit = abs(lunxx)
663 
664  call status(lunit,lun,il,im)
665  if(il==0) call bort('BUFRLIB: POSAPX - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR OUTPUT')
666  if(il<0) call bort('BUFRLIB: POSAPX - INPUT BUFR FILE IS OPEN FOR INPUT, IT MUST BE OPEN FOR OUTPUT')
667 
668  ! Try to read to the end of the file
669 
670  do while (.true.)
671  call rdmsgw(lunit,mgwa,ier)
672  if(ier<0) return
673  if(idxmsg(mgwa)==1) then
674  ! This is an internal dictionary message that was generated by the NCEPLIBS-bufr software. Backspace the file pointer
675  ! and then read and store all such dictionary messages (they should be stored consecutively!) and reset the internal tables.
676  call backbufr_c(lun)
677  call rdbfdx(lunit,lun)
678  endif
679  enddo
680 
681 end subroutine posapx
682 
714 subroutine rewnbf(lunit,isr)
715 
716  use bufrlib
717 
718  use moda_msgcwd
719  use moda_bitbuf
720  use moda_bufrsr
721 
722  implicit none
723 
724  integer, intent(in) :: lunit, isr
725  integer lun, il, im, i, kdate, ier
726 
727  character*128 bort_str
728  character*8 subset
729 
730  ! Try to trap bad call problems
731  if(isr==0) then
732  call status(lunit,lun,il,im)
733  if(jsr(lun)/=0) then
734  write(bort_str,'("BUFRLIB: REWNBF - ATTEMPING TO SAVE '// &
735  'PARAMETERS FOR FILE FOR WHICH THEY HAVE ALREADY BEEN SAVED (AND NOT YET RESTORED) (UNIT",I3,")")') lunit
736  call bort(bort_str)
737  endif
738  if(il==0) then
739  write(bort_str,'("BUFRLIB: REWNBF - ATTEMPING TO SAVE '// &
740  'PARAMETERS FOR BUFR FILE WHICH IS NOT OPENED FOR EITHER INPUT OR OUTPUT) (UNIT",I3,")")') lunit
741  call bort(bort_str)
742  endif
743  elseif(isr==1) then
744  if(junn==0) then
745  write(bort_str,'("BUFRLIB: REWNBF - ATTEMPING TO RESTORE '// &
746  'PARAMETERS TO BUFR FILE WHICH WERE NEVER SAVED (UNIT",I3,")")') lunit
747  call bort(bort_str)
748  endif
749  if(jsr(junn)/=1) then
750  write(bort_str,'("BUFRLIB: REWNBF - ATTEMPING TO RESTORE '// &
751  'PARAMETERS TO BUFR FILE WHICH WERE NEVER SAVED (UNIT",I3,")")') lunit
752  call bort(bort_str)
753  endif
754  lun = junn
755  else
756  write(bort_str,'("BUFRLIB: REWNBF - SAVE/RESTORE SWITCH (INPUT '// &
757  'ARGUMENT ISR) IS NOT ZERO OR ONE (HERE =",I4,") (UNIT",I3,")")') isr, lunit
758  call bort(bort_str)
759  endif
760 
761  if(isr==0) then
762  ! Store the existing file parameters
763  jmsg = nmsg(lun)
764  jsub = nsub(lun)
765  if ( il > 0 ) then
766  ! The file is open for writing
767  jbit = ibit
768  jbyt = mbyt(lun)
769  do i=1,jbyt
770  jbay(i) = mbay(i,lun)
771  enddo
772  endif
773  junn = lun
774  jill = il
775  jimm = im
776  ! Reset the file for reading
777  call wtstat(lunit,lun,-1,0)
778  endif
779 
780  ! Rewind the file
781  call cewind_c(lun)
782 
783  if(isr==1) then
784  ! Restore the previous file parameters. Note that we already restored the previous value of lun earlier in this routine.
785 
786  ! Reset nmsg(lun) to 0, so that the below calls to readmg() will internally restore nmsg(lun) to the correct value.
787  nmsg(lun) = 0
788 
789  ! Note that the below calls to readmg() are valid even if the file was previously open for writing, because we haven't yet
790  ! called wtstat() to restore the file to its previous I/O status. So until then we can still read from it as though it
791  ! was an input file.
792  do i=1,jmsg
793  call readmg(lunit,subset,kdate,ier)
794  if(ier<0) then
795  write(bort_str,'("BUFRLIB: REWNBF - HIT END OF FILE BEFORE '// &
796  'REPOSITIONING BUFR FILE IN UNIT",I3," TO ORIGINAL MESSAGE NO.",I5)') lunit, jmsg
797  call bort(bort_str)
798  endif
799  enddo
800 
801  if ( jill < 0 ) then
802  ! The file was previously open for reading
803  do i=1,jsub
804  call readsb(lunit,ier)
805  enddo
806  else
807  ! The file was previously open for writing
808  do i=1,jbyt
809  mbay(i,lun) = jbay(i)
810  enddo
811  nsub(lun) = jsub
812  mbyt(lun) = jbyt
813  ibit = jbit
814  endif
815 
816  ! Now restore the file to its previous I/O status
817  il = jill
818  im = jimm
819  call wtstat(lunit,lun,il,im)
820  endif
821 
822  ! Toggle the stack status indicator
823  jsr(lun) = mod(jsr(lun)+1,2)
824 
825  return
826 end subroutine rewnbf
827 
895 
896 recursive subroutine ufbtab(lunin,tab,i1,i2,iret,str)
897 
898  use bufrlib
899 
900  use modv_vars, only: part, im8b, bmiss, iac, iprt
901 
902  use moda_usrint
903  use moda_msgcwd
904  use moda_unptyp
905  use moda_bitbuf
906  use moda_tables
907 
908  implicit none
909 
910  integer*8 ival, lref, ninc, mps, lps
911  integer, intent(in) :: lunin, i1, i2
912  integer, intent(inout) :: iret
913  integer, parameter :: maxtg = 100
914  integer nnod, ncon, nods, nodc, ivls, kons, my_lunin, my_i1, my_i2, lunit, lun, il, im, irec, isub, i, n, ntg, &
915  jdate, jbit, kbit, lbit, mbit, nbit, nibit, nbyt, nsb, node, nbmp, nrep, lret, linc, iac_prev, ityp, &
917 
918  character*(*), intent(in) :: str
919  character*128 errstr
920  character*90 cstr
921  character*40 cref
922  character*10 tgs(maxtg)
923  character*8 subset, cval
924 
925  logical :: openit, overflow, just_count, need_node, need_newmsg
926 
927  real*8, intent(out) :: tab(i1,i2)
928  real*8 rval, ups
929 
930  common /usrstr/ nnod, ncon, nods(20), nodc(10), ivls(10), kons(10)
931 
932  save lun, openit
933 
934  equivalence(cval,rval)
935 
936  ! Statement functions
937  mps(node) = 2_8**(ibt(node))-1
938  lps(lbit) = max(2_8**(lbit)-1,1)
939 
940  ! Check for I8 integers
941  if(im8b) then
942  im8b=.false.
943  call x84(lunin,my_lunin,1)
944  call x84(i1,my_i1,1)
945  call x84(i2,my_i2,1)
946  call ufbtab(my_lunin,tab,my_i1,my_i2,iret,str)
947  call x48(iret,iret,1)
948  im8b=.true.
949  return
950  endif
951 
952  ! If we're catching bort errors, set a target return location if one doesn't already exist.
953  if (bort_target_set() == 1) then
954  call strsuc(str,cstr,lcstr)
955  call catch_bort_ufbtab_c(lunin,tab,i1,i2,iret,cstr,lcstr)
956  call bort_target_unset
957  return
958  endif
959 
960  ! Set counters to zero
961  irec = 0
962  isub = 0
963 
964  ! Initialize all of the output array values to the current value for "missing"
965  tab(1:i1,1:i2) = bmiss
966 
967  iac_prev = iac
968  iac = 1
969 
970  lunit = abs(lunin)
971  just_count = lunin<lunit
972  if (.not. just_count) then
973  ! Check for special tags in string
974  call parstr(str,tgs,maxtg,ntg,' ',.true.)
975  do i=1,ntg
976  if(tgs(i)=='IREC') irec = i
977  if(tgs(i)=='ISUB') isub = i
978  enddo
979  endif
980 
981  overflow = .false.
982 
983  if(part.and.iret<0) then
984  ! The previous call to this subroutine only partially read through the file, so resume reading from
985  ! the point where it previously left off.
986  need_newmsg = .false.
987  iret = 0
988  else
989  ! Make sure subroutine openbf() has been called at least once before trying to call subroutine status();
990  ! otherwise, status() might try to access array space that hasn't yet been dynamically allocated.
991  call openbf(0,'FIRST',0)
992  call status(lunit,lun,il,im)
993  openit = il==0
994  if(openit) then
995  ! Open BUFR file connected to unit lunit if it isn't already open
996  call openbf(lunit,'INX',lunit)
997  else
998  ! If BUFR file already opened, save position and rewind to first data message
999  call rewnbf(lunit,0)
1000  endif
1001  need_newmsg = .true.
1002  iret = 0
1003  ! Check for count subset only option
1004  if(just_count) then
1005  do while(ireadmg(-lunit,subset,jdate)>=0)
1006  iret = iret+nmsub(lunit)
1007  enddo
1008  endif
1009  endif
1010 
1011  outer: do while (.not. just_count)
1012 
1013  if(need_newmsg) then
1014  ! Read the next message from the file
1015  if(ireadmg(-lunit,subset,jdate)<0) exit
1016  call string(str,lun,i1,0)
1017  if(irec>0) nods(irec) = 0
1018  if(isub>0) nods(isub) = 0
1019  else
1020  need_newmsg=.true.
1021  endif
1022 
1023  if(msgunp(lun)/=2) then
1024  ! The message is uncompressed
1025 
1026  inner1: do while (.true.)
1027  ! Get the next subset from the message
1028  if(nsub(lun)==msub(lun)) cycle outer
1029  if(iret+1>i2) then
1030  if(part) then
1031  iret=-iret
1032  return
1033  else
1034  overflow = .true.
1035  exit outer
1036  endif
1037  endif
1038  iret = iret+1
1039  do i=1,nnod
1040  nods(i) = abs(nods(i))
1041  enddo
1042  if(msgunp(lun)==0) then
1043  mbit = mbyt(lun)*8 + 16
1044  else
1045  mbit = mbyt(lun)
1046  endif
1047  nbit = 0
1048  n = 1
1049  call usrtpl(lun,n,n)
1050  inner2: do while (.true.)
1051  ! Cycle through each node of the subset to look for the requested values
1052  if(n+1<=nval(lun)) then
1053  n = n+1
1054  node = inv(n,lun)
1055  mbit = mbit+nbit
1056  nbit = ibt(node)
1057  if(itp(node)==1) then
1058  call upb8(ival,nbit,mbit,mbay(1,lun))
1059  nbmp=int(ival)
1060  call usrtpl(lun,n,nbmp)
1061  endif
1062  do i=1,nnod
1063  if(nods(i)==node) then
1064  if(itp(node)==1) then
1065  call upb8(ival,nbit,mbit,mbay(1,lun))
1066  tab(i,iret) = ival
1067  elseif(itp(node)==2) then
1068  call upb8(ival,nbit,mbit,mbay(1,lun))
1069  if(ival<mps(node)) tab(i,iret) = ups(ival,node)
1070  elseif(itp(node)==3) then
1071  cval = ' '
1072  kbit = mbit
1073  call upc(cval,nbit/8,mbay(1,lun),kbit,.true.)
1074  tab(i,iret) = rval
1075  endif
1076  nods(i) = -nods(i)
1077  cycle inner2
1078  endif
1079  enddo
1080  do i=1,nnod
1081  if(nods(i)>0) cycle inner2
1082  enddo
1083  endif
1084  exit
1085  enddo inner2
1086  ! Update the subset pointers
1087  if(msgunp(lun)==0) then
1088  ibit = mbyt(lun)*8
1089  call upb(nbyt,16,mbay(1,lun),ibit)
1090  mbyt(lun) = mbyt(lun) + nbyt
1091  else
1092  mbyt(lun) = mbit
1093  endif
1094  nsub(lun) = nsub(lun) + 1
1095  if(irec>0) tab(irec,iret) = nmsg(lun)
1096  if(isub>0) tab(isub,iret) = nsub(lun)
1097  enddo inner1
1098 
1099  else
1100  ! The message is compressed
1101 
1102  if(iret+msub(lun)>i2) then
1103  if(part) then
1104  iret=-iret
1105  return
1106  else
1107  overflow = .true.
1108  exit outer
1109  endif
1110  endif
1111  if(irec>0.or.isub>0) then
1112  do nsb=1,msub(lun)
1113  if(irec>0) tab(irec,iret+nsb) = nmsg(lun)
1114  if(isub>0) tab(isub,iret+nsb) = nsb
1115  enddo
1116  endif
1117  call usrtpl(lun,1,1)
1118  ibit = mbyt(lun)
1119  n = 0
1120  inner3: do while ( n < nval(lun) )
1121  ! Cycle through each node of each subset to look for the requested values
1122  n = n+1
1123  node = inv(n,lun)
1124  nbit = ibt(node)
1125  ityp = itp(node)
1126  if(n==1) then
1127  ! Reset the node indices
1128  do i=1,nnod
1129  nods(i) = abs(nods(i))
1130  enddo
1131  else
1132  ! Are we still looking for more values?
1133  need_node = .false.
1134  do i=1,nnod
1135  if(nods(i)>0) then
1136  need_node = .true.
1137  exit
1138  endif
1139  enddo
1140  if(.not. need_node) exit inner3
1141  endif
1142  if(ityp==1 .or. ityp==2) then
1143  call up8(lref,nbit,mbay(1,lun),ibit)
1144  call upb(linc,6,mbay(1,lun),ibit)
1145  nibit = ibit + linc*msub(lun)
1146  elseif(ityp==3) then
1147  cref=' '
1148  call upc(cref,nbit/8,mbay(1,lun),ibit,.true.)
1149  call upb(linc,6,mbay(1,lun),ibit)
1150  nibit = ibit + 8*linc*msub(lun)
1151  else
1152  cycle
1153  endif
1154  if(ityp==1) then
1155  ! This is a delayed replication node
1156  jbit = ibit + linc
1157  call up8(ninc,linc,mbay(1,lun),jbit)
1158  ival = lref+ninc
1159  call usrtpl(lun,n,int(ival))
1160  cycle
1161  endif
1162  do i=1,nnod
1163  if(node==nods(i)) then
1164  ! This is one of the requested values, so store the corresponding value from each subset in the message
1165  nods(i) = -nods(i)
1166  lret = iret
1167  if(ityp==1 .or. ityp==2) then
1168  do nsb=1,msub(lun)
1169  jbit = ibit + linc*(nsb-1)
1170  call up8(ninc,linc,mbay(1,lun),jbit)
1171  ival = lref+ninc
1172  lret = lret+1
1173  if(ninc<lps(linc)) tab(i,lret) = ups(ival,node)
1174  enddo
1175  elseif(ityp==3) then
1176  do nsb=1,msub(lun)
1177  if(linc==0) then
1178  cval = cref(1:8)
1179  else
1180  jbit = ibit + linc*(nsb-1)*8
1181  cval = ' '
1182  call upc(cval,linc,mbay(1,lun),jbit,.true.)
1183  endif
1184  lret = lret+1
1185  tab(i,lret) = rval
1186  enddo
1187  else
1188  call bort('UFBTAB - INVALID ELEMENT TYPE SPECIFIED')
1189  endif
1190  endif
1191  enddo
1192  ibit = nibit
1193  enddo inner3
1194  iret = iret+msub(lun)
1195 
1196  endif
1197 
1198  enddo outer
1199 
1200  if(overflow) then
1201  nrep = iret
1202  do while(ireadsb(lunit)==0)
1203  nrep = nrep+1
1204  enddo
1205  do while(ireadmg(-lunit,subset,jdate)>=0)
1206  nrep = nrep+nmsub(lunit)
1207  enddo
1208  if(iprt>=0) then
1209  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1210  write ( unit=errstr, fmt='(A,A,I8,A)' ) 'BUFRLIB: UFBTAB - THE NO. OF DATA SUBSETS IN THE BUFR FILE ', &
1211  .GT.'IS LIMIT OF ', i2, ' IN THE 4TH ARG. (INPUT) - INCOMPLETE READ'
1212  call errwrt(errstr)
1213  write ( unit=errstr, fmt='(A,I8,A,I8,A)' ) '>>>UFBTAB STORED ', iret, ' REPORTS OUT OF ', nrep, '<<<'
1214  call errwrt(errstr)
1215  call errwrt('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
1216  call errwrt(' ')
1217  endif
1218  endif
1219 
1220  if(openit) then
1221  ! Close BUFR file if it was opened here
1222  call closbf(lunit)
1223  else
1224  ! Restore BUFR file to its previous status and position
1225  call rewnbf(lunit,1)
1226  endif
1227 
1228  iac = iac_prev
1229 
1230  return
1231 end subroutine ufbtab
1232 
1258 subroutine setpart ( xpart )
1259 
1260  use modv_vars, only: part
1261 
1262  implicit none
1263 
1264  logical, intent(in) :: xpart
1265 
1266  part = xpart
1267 
1268  return
1269 end subroutine setpart
1270 
subroutine arallocf
Dynamically allocate Fortran language arrays.
Definition: arallocf.F90:19
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
subroutine up8(nval, nbits, ibay, ibit)
Decode an 8-byte integer value from within a specified number of bits of an integer array,...
Definition: cidecode.F90:128
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 writdx(lunit, lun, lundx)
Write DX BUFR table (dictionary) messages to the beginning of an output BUFR file in lunit.
Definition: dxtable.F90:800
subroutine readdx(lunit, lun, lundx)
Initialize modules moda_tababd and moda_msgcwd with DX BUFR (dictionary) tables.
Definition: dxtable.F90:29
subroutine rdbfdx(lunit, lun)
Beginning at the current file pointer location within lunit, read a complete DX BUFR table into inter...
Definition: dxtable.F90:121
subroutine errwrt(str)
Specify a custom location for the logging of error and diagnostic messages generated by the NCEPLIBS-...
Definition: errwrt.F90:32
subroutine strsuc(str1, str2, lens)
Remove leading and trailing blanks from a character string.
Definition: misc.F90:199
subroutine bfrini
Initialize numerous global variables and arrays within internal modules and common blocks throughout ...
Definition: misc.F90:16
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 arrays and variables needed to store the current position within a BUFR file.
integer jill
File status indicator of BUFR file.
integer jimm
Message status indicator of BUFR file.
integer, dimension(:), allocatable jsr
Indicator of stack status when entering subroutine rewnbf().
integer jmsg
Sequential number of BUFR message, counting from the beginning of the file.
integer jbit
Bit pointer within BUFR message.
integer jsub
Sequential number of BUFR data subset, counting from the beginning of the current BUFR message.
integer junn
File ID of BUFR file.
integer jbyt
Length (in bytes) of BUFR message.
integer, dimension(:), allocatable jbay
BUFR message.
Declare an array used by subroutine makestab() to keep track of which logical units share DX BUFR tab...
integer, dimension(:), allocatable lus
Tracking index for each file ID.
Declare 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 an array used to store a switch for each file ID, indicating whether any BUFR messages should...
integer, dimension(:), allocatable null
Output switch for each file ID:
Declare an array used to store a switch for each file ID, indicating whether BUFR messages read from ...
integer, dimension(:), allocatable isc3
Section 3 switch for each file ID:
Declare arrays used to store file and message status indicators for all logical units that have been ...
integer, dimension(:), allocatable iolun
File status indicators.
integer, dimension(:), allocatable iomsg
Message status indicator corresponding to iolun, denoting whether a BUFR message is currently open wi...
Declare 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 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.
subroutine rewnbf(lunit, isr)
Store or restore parameters associated with a BUFR file.
recursive subroutine fortran_open(filename, lunit, format, position, iret)
Open a Fortran file on the local system.
Definition: openclosebf.F90:16
recursive subroutine openbf(lunit, io, lundx)
Connect a new file to the NCEPLIBS-bufr software for input or output operations, or initialize the li...
subroutine setpart(xpart)
Specify whether future calls to subroutine ufbtab() should attempt to return full or partial results.
recursive subroutine fortran_close(lunit, iret)
Close a Fortran file on the local system.
Definition: openclosebf.F90:47
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...
subroutine wtstat(lunit, lun, il, im)
Update file status in library internals.
recursive subroutine ufbtab(lunin, tab, i1, i2, iret, str)
Read through every data subset in a BUFR file and return one or more specified data values from each ...
subroutine posapx(lunxx)
Position an output BUFR file for appending.
recursive subroutine closmg(lunin)
Close the BUFR message that is currently open for writing within internal arrays associated with logi...
recursive integer function nmsub(lunit)
Get the total number of data subsets available within the BUFR message that was most recently opened ...
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 rdmsgw(lunit, mesg, iret)
Read the next BUFR message from logical unit lunit as an array of integer words.
recursive integer function ireadmg(lunit, subset, idate)
Call subroutine readmg() and pass back its return code as the function value.
subroutine usrtpl(lun, invn, nbmp)
Expand a subset template within internal arrays.
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 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