NCEPLIBS-bufr  12.3.0
mastertable.F90
Go to the documentation of this file.
1 
5 
34 recursive subroutine mtinfo ( cmtdir, lunmt1, lunmt2 )
35 
36  use modv_vars, only: im8b, lun1, lun2, mtdir, lmtd
37 
38  implicit none
39 
40  integer, intent(in) :: lunmt1, lunmt2
41  integer my_lunmt1, my_lunmt2
42 
43  character*(*), intent(in) :: cmtdir
44 
45  ! Check for I8 integers
46  if(im8b) then
47  im8b=.false.
48  call x84 ( lunmt1, my_lunmt1, 1 )
49  call x84 ( lunmt2, my_lunmt2, 1 )
50  call mtinfo ( cmtdir, my_lunmt1, my_lunmt2 )
51  im8b=.true.
52  return
53  endif
54 
55  call strsuc ( cmtdir, mtdir, lmtd )
56 
57  lun1 = lunmt1
58  lun2 = lunmt2
59 
60  return
61 end subroutine mtinfo
62 
81 subroutine mtfnam ( imt, imtv, iogce, imtvl, tbltyp, stdfil, locfil )
82 
83  use modv_vars, only: iprt, mtdir, lmtd
84 
85  implicit none
86 
87  integer, intent(in) :: imt, imtv, iogce, imtvl
88  integer ltbt, isize
89 
90  character*(*), intent(in) :: tbltyp
91  character*(*), intent(out) :: stdfil, locfil
92 
93  character*16 tbltyp2
94  character*20 fmtf
95  character*128 bort_str
96 
97  logical found
98 
99  call strsuc ( tbltyp, tbltyp2, ltbt )
100 
101  ! Determine the standard master table path/filename.
102 
103  if ( ( imt == 0 ) .and. ( imtv <= 13 ) ) then
104  ! For master table 0, version 13 is a superset of all earlier versions.
105  stdfil = mtdir(1:lmtd) // '/bufrtab.' // tbltyp2(1:ltbt) // '_STD_0_13'
106  else
107  write ( fmtf, '(A,I1,A,I1,A)' ) '(4A,I', isize(imt), ',A,I', isize(imtv), ')'
108  write ( stdfil, fmtf ) mtdir(1:lmtd), '/bufrtab.', tbltyp2(1:ltbt), '_STD_', imt, '_', imtv
109  endif
110  if ( iprt >= 2 ) then
111  call errwrt('Standard ' // tbltyp2(1:ltbt) // ':')
112  call errwrt(stdfil)
113  endif
114  inquire ( file = stdfil, exist = found )
115  if ( .not. found ) then
116  bort_str = 'BUFRLIB: MTFNAM - COULD NOT FIND STANDARD FILE:'
117  call bort2(bort_str, stdfil)
118  endif
119 
120  ! Now determine the local master table path/filename.
121 
122  ! Use the local table corresponding to the originating center and local table version number, if such a table exists.
123  ! Otherwise use the local table from NCEP.
124 
125  write ( fmtf, '(A,I1,A,I1,A,I1,A)' ) '(4A,I', isize(imt), ',A,I', isize(iogce), ',A,I', isize(imtvl), ')'
126  write ( locfil, fmtf ) mtdir(1:lmtd), '/bufrtab.', tbltyp2(1:ltbt), '_LOC_', imt, '_', iogce, '_', imtvl
127  if ( iprt >= 2 ) then
128  call errwrt('Local ' // tbltyp2(1:ltbt) // ':')
129  call errwrt(locfil)
130  endif
131  inquire ( file = locfil, exist = found )
132  if ( .not. found ) then
133  ! Use the local table from NCEP.
134  locfil = mtdir(1:lmtd) // '/bufrtab.' // tbltyp2(1:ltbt) // '_LOC_0_7_1'
135  if ( iprt >= 2 ) then
136  call errwrt('Local ' // tbltyp2(1:ltbt) // ' not found, so using:')
137  call errwrt(locfil)
138  endif
139  inquire ( file = locfil, exist = found )
140  if ( .not. found ) then
141  bort_str = 'BUFRLIB: MTFNAM - COULD NOT FIND LOCAL FILE:'
142  call bort2(bort_str, locfil)
143  endif
144  endif
145 
146  return
147 end subroutine mtfnam
148 
168 integer function ireadmt ( lun ) result ( iret )
169 
170  use bufrlib
171 
172  use modv_vars, only: maxnc, maxcd, mxmtbb, mxmtbd, iprt, lun1, lun2, lmt, lmtv, logce, lmtvl
173 
174  use moda_mstabs
175  use moda_bitbuf
176  use moda_rdmtb
177  use moda_sc3bfr
178  use moda_s3list
179  use moda_tablef
180 
181  implicit none
182 
183  integer, intent(in) :: lun
184  integer imt, imtv, iogce, imtvl, ii, jj, idx, ncds3, ier, ibmt, ibmtv, ibogce, ibltv, idmt, idmtv, idogce, idltv, &
186 
187  character*(*), parameter :: bort_str1 = 'BUFRLIB: IREADMT - COULD NOT OPEN STANDARD FILE:'
188  character*(*), parameter :: bort_str2 = 'BUFRLIB: IREADMT - COULD NOT OPEN LOCAL FILE:'
189  character*275 stdfil,locfil
190 
191  logical allstd
192 
193  ! Initializing the following value ensures that new master tables are read during the first call to this subroutine.
194 
195  iret = 0
196 
197  ! Unpack some Section 1 information from the message that was most recently read.
198 
199  imt = iupbs01( mbay(1,lun), 'BMT' )
200  imtv = iupbs01( mbay(1,lun), 'MTV' )
201  iogce = iupbs01( mbay(1,lun), 'OGCE' )
202  imtvl = iupbs01( mbay(1,lun), 'MTVL' )
203 
204  ! Compare the master table and master table version numbers from this message to those from the message that was
205  ! processed during the previous call to this subroutine.
206 
207  if ( ( imt /= lmt ) .or. ( ( imt /= 0 ) .and. ( imtv /= lmtv ) ) .or. &
208  ( ( imt == 0 ) .and. ( imtv /= lmtv ) .and. ( ( imtv > 13 ) .or. ( lmtv > 13 ) ) ) ) then
209  ! Either the master table number has changed
210  ! OR
211  ! The master table number hasn't changed, but it isn't 0, and the table version number has changed
212  ! OR
213  ! The master table number hasn't changed and is 0, but the table version number has changed, and at least one of the
214  ! table version numbers (i.e. the current or the previous) is greater than 13 (which is the last version that was a
215  ! superset of all earlier versions of master table 0!)
216 
217  ! In any of these cases, we need to read in new tables!
218  iret = 1
219 
220  else
221 
222  ! Unpack the list of Section 3 descriptors from the message and determine if any of them are local descriptors.
223  call upds3 ( mbay(1,lun), maxnc, cds3, ncds3 )
224  ii = 1
225  allstd = .true.
226  do while ( (allstd) .and. (ii<=ncds3) )
227  if ( istdesc(ifxy(cds3(ii))) == 0 ) then
228  allstd = .false.
229  else
230  ii = ii + 1
231  endif
232  enddo
233 
234  ! If there was at least one local (i.e. non-standard) descriptor, and if either the originating center or local table
235  ! version number are different than those from the message that was processed during the previous call to this subroutine,
236  ! then we need to read in new tables.
237  if ( ( .not. allstd ) .and. ( ( iogce /= logce ) .or. ( imtvl /= lmtvl ) ) ) iret = 1
238 
239  endif
240 
241  if ( iret == 0 ) return
242 
243  lmt = imt
244  lmtv = imtv
245  logce = iogce
246  lmtvl = imtvl
247 
248  if ( iprt >= 2 ) then
249  call errwrt(' ')
250  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
251  call errwrt('BUFRLIB: IREADMT - OPENING/READING MASTER TABLES')
252  endif
253 
254  if ( isc3(lun) /= 0 ) then
255 
256  ! Locate and open the master Table B files. There should be one file of standard descriptors and one file of local
257  ! descriptors.
258  call mtfnam ( imt, imtv, iogce, imtvl, 'TableB', stdfil, locfil )
259  open ( unit = lun1, file = stdfil, iostat = ier )
260  if ( ier /= 0 ) call bort2(bort_str1, stdfil)
261  open ( unit = lun2, file = locfil, iostat = ier )
262  if ( ier /= 0 ) call bort2(bort_str2, locfil)
263 
264  ! Read the master Table B files.
265  call rdmtbb ( lun1, lun2, mxmtbb, ibmt, ibmtv, ibogce, ibltv, nmtb, ibfxyn, cbscl, cbsref, cbbw, &
267 
268  ! Close the master Table B files.
269  close ( unit = lun1 )
270  close ( unit = lun2 )
271 
272  ! Locate and open the master Table D files. There should be one file of standard descriptors and one file of local
273  ! descriptors.
274  call mtfnam ( imt, imtv, iogce, imtvl, 'TableD', stdfil, locfil )
275  open ( unit = lun1, file = stdfil, iostat = ier )
276  if ( ier /= 0 ) call bort2(bort_str1, stdfil)
277  open ( unit = lun2, file = locfil, iostat = ier )
278  if ( ier /= 0 ) call bort2(bort_str2, locfil)
279 
280  ! Read the master Table D files.
281  call rdmtbd ( lun1, lun2, mxmtbd, maxcd, idmt, idmtv, idogce, idltv, nmtd, idfxyn, cdmnem, cmdscd, cdseq, &
282  ndelem, iefxyn, ceelem )
283  do ii = 1, nmtd
284  do jj = 1, ndelem(ii)
285  idx = icvidx_c( ii-1, jj-1, maxcd ) + 1
286  idefxy(idx) = iefxyn(ii,jj)
287  enddo
288  enddo
289 
290  ! Close the master Table D files.
291  close ( unit = lun1 )
292  close ( unit = lun2 )
293 
294  ! Copy master table B and D information into internal C arrays.
296  ndelem, idefxy, maxcd )
297  endif
298 
299  if ( cdmf == 'Y' ) then
300 
301  ! Locate and open the master code and flag table files. There should be one file corresponding to the standard Table B
302  ! descriptors, and one file corresponding to the local Table B descriptors.
303  call mtfnam ( imt, imtv, iogce, imtvl, 'CodeFlag', stdfil, locfil )
304  open ( unit = lun1, file = stdfil, iostat = ier )
305  if ( ier /= 0 ) call bort2(bort_str1, stdfil)
306  open ( unit = lun2, file = locfil, iostat = ier )
307  if ( ier /= 0 ) call bort2(bort_str2, locfil)
308 
309  ! Read the master code and flag table files.
310  call rdmtbf ( lun1, lun2 )
311 
312  ! Close the master code and flag table files.
313  close ( unit = lun1 )
314  close ( unit = lun2 )
315  endif
316 
317  if ( iprt >= 2 ) then
318  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
319  call errwrt(' ')
320  endif
321 
322  return
323 end function ireadmt
324 
353 subroutine rdmtbb ( lunstb, lunltb, mxmtbb, imt, imtv, iogce, iltv, nmtbb, imfxyn, cmscl, cmsref, cmbw, &
354  cmunit, cmmnem, cmdsc, cmelem )
355 
356  implicit none
357 
358  integer, intent(in) :: lunstb, lunltb, mxmtbb
359  integer, intent(out) :: imt, imtv, iogce, iltv, nmtbb, imfxyn(*)
360  integer isfxyn, ilfxyn, iers, ierl
361 
362  character, intent(out) :: cmelem(120,*), cmunit(24,*), cmsref(12,*), cmmnem(8,*), cmscl(4,*), cmbw(4,*), cmdsc(*)*4
363  character*200 stline, ltline
364  character*128 bort_str
365  character*6 cmatch, adn30
366 
367  ! Read and parse the header lines of both files.
368 
369  call gettbh ( lunstb, lunltb, 'B', imt, imtv, iogce, iltv )
370 
371  ! Read through the remainder of both files, merging the contents into a unified set of master Table B arrays.
372 
373  nmtbb = 0
374  call getntbe ( lunstb, isfxyn, stline, iers )
375  call getntbe ( lunltb, ilfxyn, ltline, ierl )
376  do while ( ( iers == 0 ) .or. ( ierl == 0 ) )
377  if ( ( iers == 0 ) .and. ( ierl == 0 ) ) then
378  if ( isfxyn == ilfxyn ) then
379  cmatch = adn30( isfxyn, 6 )
380  write(bort_str,'("BUFRLIB: RDMTBB - STANDARD AND LOCAL '// &
381  'TABLE B FILES BOTH CONTAIN SAME FXY NUMBER: ",5A)') cmatch(1:1), '-', cmatch(2:3), '-', cmatch(4:6)
382  call bort(bort_str)
383  else if ( isfxyn < ilfxyn ) then
384  call sntbbe ( isfxyn, stline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
385  call getntbe ( lunstb, isfxyn, stline, iers )
386  else
387  call sntbbe ( ilfxyn, ltline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
388  call getntbe ( lunltb, ilfxyn, ltline, ierl )
389  endif
390  else if ( iers == 0 ) then
391  call sntbbe ( isfxyn, stline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
392  call getntbe ( lunstb, isfxyn, stline, iers )
393  else
394  call sntbbe ( ilfxyn, ltline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
395  call getntbe ( lunltb, ilfxyn, ltline, ierl )
396  endif
397  enddo
398 
399  return
400 end subroutine rdmtbb
401 
431 subroutine rdmtbd ( lunstd, lunltd, mxmtbd, mxelem, imt, imtv, iogce, iltv, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, &
432  nmelem, iefxyn, ceelem )
433 
434  implicit none
435 
436  integer, intent(in) :: lunstd, lunltd, mxmtbd, mxelem
437  integer, intent(out) :: imt, imtv, iogce, iltv, nmtbd, imfxyn(*), nmelem(*), iefxyn(mxmtbd,mxelem)
438  integer isfxyn, ilfxyn, iers, ierl
439 
440  character, intent(out) :: cmseq(120,*), cmmnem(8,*), cmdsc(*)*4, ceelem(mxmtbd,mxelem)*120
441 
442  character*200 stline, ltline
443  character*128 bort_str
444  character*6 cmatch, adn30
445 
446  ! Read and parse the header lines of both files.
447 
448  call gettbh ( lunstd, lunltd, 'D', imt, imtv, iogce, iltv )
449 
450  ! Read through the remainder of both files, merging the contents into a unified set of master Table D arrays.
451 
452  nmtbd = 0
453  call getntbe ( lunstd, isfxyn, stline, iers )
454  call getntbe ( lunltd, ilfxyn, ltline, ierl )
455  do while ( ( iers == 0 ) .or. ( ierl == 0 ) )
456  if ( ( iers == 0 ) .and. ( ierl == 0 ) ) then
457  if ( isfxyn == ilfxyn ) then
458  cmatch = adn30( isfxyn, 6 )
459  write(bort_str,'("BUFRLIB: RDMTBD - STANDARD AND LOCAL '// &
460  'TABLE D FILES BOTH CONTAIN SAME FXY NUMBER: ",5A)') cmatch(1:1), '-', cmatch(2:3), '-', cmatch(4:6)
461  call bort(bort_str)
462  else if ( isfxyn < ilfxyn ) then
463  call sntbde ( lunstd, isfxyn, stline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
464  call getntbe ( lunstd, isfxyn, stline, iers )
465  else
466  call sntbde ( lunltd, ilfxyn, ltline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
467  call getntbe ( lunltd, ilfxyn, ltline, ierl )
468  endif
469  else if ( iers == 0 ) then
470  call sntbde ( lunstd, isfxyn, stline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
471  call getntbe ( lunstd, isfxyn, stline, iers )
472  else
473  call sntbde ( lunltd, ilfxyn, ltline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
474  call getntbe ( lunltd, ilfxyn, ltline, ierl )
475  endif
476  enddo
477 
478  return
479 end subroutine rdmtbd
480 
490 subroutine rdmtbf ( lunstf, lunltf )
491 
492  use bufrlib
493 
494  implicit none
495 
496  integer, intent(in) :: lunstf, lunltf
497  integer imt, imtv, iogce, iltv, isfxyn, ilfxyn, iers, ierl
498 
499  character*160 stline, ltline
500  character*128 bort_str
501  character*6 cmatch, adn30
502 
503  ! Initialize the internal memory structure, including allocating space for it in case this hasn't already been done.
504 
505  call inittbf_c
506 
507  ! Read and parse the header lines of both files.
508 
509  call gettbh ( lunstf, lunltf, 'F', imt, imtv, iogce, iltv )
510 
511  ! Read through the remainder of both files, merging the contents into a unified internal memory structure.
512 
513  call getntbe ( lunstf, isfxyn, stline, iers )
514  call getntbe ( lunltf, ilfxyn, ltline, ierl )
515  do while ( ( iers == 0 ) .or. ( ierl == 0 ) )
516  if ( ( iers == 0 ) .and. ( ierl == 0 ) ) then
517  if ( isfxyn == ilfxyn ) then
518  cmatch = adn30( isfxyn, 6 )
519  write(bort_str,'("BUFRLIB: RDMTBF - STANDARD AND LOCAL '// &
520  'CODE/FLAG TABLE FILES BOTH CONTAIN SAME FXY NUMBER: ",5A)') cmatch(1:1), '-', cmatch(2:3), '-', cmatch(4:6)
521  call bort(bort_str)
522  else if ( isfxyn < ilfxyn ) then
523  call sntbfe ( lunstf, isfxyn )
524  call getntbe ( lunstf, isfxyn, stline, iers )
525  else
526  call sntbfe ( lunltf, ilfxyn )
527  call getntbe ( lunltf, ilfxyn, ltline, ierl )
528  endif
529  else if ( iers == 0 ) then
530  call sntbfe ( lunstf, isfxyn )
531  call getntbe ( lunstf, isfxyn, stline, iers )
532  else
533  call sntbfe ( lunltf, ilfxyn )
534  call getntbe ( lunltf, ilfxyn, ltline, ierl )
535  endif
536  enddo
537 
538  ! Sort the contents of the internal memory structure.
539 
540  call sorttbf_c
541 
542  return
543 end subroutine rdmtbf
544 
562 subroutine sntbbe ( ifxyn, line, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
563 
564  implicit none
565 
566  integer, intent(in) :: ifxyn, mxmtbb
567  integer, intent(inout) :: nmtbb
568  integer, intent(out) :: imfxyn(*)
569  integer ntag, ii, nemock
570 
571  character, intent(out) :: cmelem(120,*), cmunit(24,*), cmsref(12,*), cmmnem(8,*), cmscl(4,*), cmbw(4,*), cmdsc(*)*4
572  character*(*), intent(in) :: line
573  character*(*), parameter :: bort_str1_head = 'BUFRLIB: SNTBBE - TABLE B ENTRY FOR ELEMENT DESCRIPTOR: '
574  character*200 tags(10), wktag
575  character*128 bort_str1, bort_str2
576 
577  if ( nmtbb >= mxmtbb ) call bort('BUFRLIB: SNTBBE - OVERFLOW OF MERGED ARRAYS')
578  nmtbb = nmtbb + 1
579 
580  ! Store the FXY number. This is the element descriptor.
581 
582  imfxyn( nmtbb ) = ifxyn
583 
584  ! Parse the table entry.
585 
586  call parstr ( line, tags, 10, ntag, '|', .false. )
587  if ( ntag < 4 ) then
588  call sntbestr(bort_str1_head, ifxyn, bort_str1)
589  bort_str2 = ' HAS TOO FEW FIELDS'
590  call bort2(bort_str1, bort_str2)
591  endif
592 
593  ! Scale factor.
594 
595  tags(2) = adjustl( tags(2) )
596  if ( tags(2) == ' ' ) then
597  call sntbestr(bort_str1_head, ifxyn, bort_str1)
598  bort_str2 = ' HAS MISSING SCALE FACTOR'
599  call bort2(bort_str1, bort_str2)
600  endif
601  tags(2)(1:4) = adjustr( tags(2)(1:4) )
602  do ii = 1, 4
603  cmscl( ii, nmtbb ) = tags(2)(ii:ii)
604  enddo
605 
606  ! Reference value.
607 
608  tags(3) = adjustl( tags(3) )
609  if ( tags(3) == ' ' ) then
610  call sntbestr(bort_str1_head, ifxyn, bort_str1)
611  bort_str2 = ' HAS MISSING REFERENCE VALUE'
612  call bort2(bort_str1, bort_str2)
613  endif
614  tags(3)(1:12) = adjustr( tags(3)(1:12) )
615  do ii = 1, 12
616  cmsref( ii, nmtbb ) = tags(3)(ii:ii)
617  enddo
618 
619  ! Bit width.
620 
621  tags(4) = adjustl( tags(4) )
622  if ( tags(4) == ' ' ) then
623  call sntbestr(bort_str1_head, ifxyn, bort_str1)
624  bort_str2 = ' HAS MISSING BIT WIDTH'
625  call bort2(bort_str1, bort_str2)
626  endif
627  tags(4)(1:4) = adjustr( tags(4)(1:4) )
628  do ii = 1, 4
629  cmbw( ii, nmtbb ) = tags(4)(ii:ii)
630  end do
631 
632  ! Units. Note that this field is allowed to be blank.
633 
634  if ( ntag > 4 ) then
635  tags(5) = adjustl( tags(5) )
636  do ii = 1, 24
637  cmunit( ii, nmtbb ) = tags(5)(ii:ii)
638  enddo
639  else
640  do ii = 1, 24
641  cmunit( ii, nmtbb ) = ' '
642  enddo
643  endif
644 
645  ! Comment (additional) fields. Any of these fields may be blank.
646 
647  cmdsc( nmtbb ) = ' '
648  do ii = 1, 8
649  cmmnem( ii, nmtbb ) = ' '
650  enddo
651  do ii = 1, 120
652  cmelem( ii, nmtbb ) = ' '
653  enddo
654  if ( ntag > 5 ) then
655  wktag = tags(6)
656  call parstr ( wktag, tags, 10, ntag, ';', .false. )
657  if ( ntag > 0 ) then
658  ! The first additional field contains the mnemonic.
659  tags(1) = adjustl( tags(1) )
660  ! If there is a mnemonic, then make sure it's legal.
661  if ( ( tags(1) /= ' ' ) .and. ( nemock( tags(1) ) /= 0 ) ) then
662  call sntbestr(bort_str1_head, ifxyn, bort_str1)
663  bort_str2 = ' HAS ILLEGAL MNEMONIC'
664  call bort2(bort_str1, bort_str2)
665  endif
666  do ii = 1, 8
667  cmmnem( ii, nmtbb ) = tags(1)(ii:ii)
668  enddo
669  endif
670  if ( ntag > 1 ) then
671  ! The second additional field contains descriptor codes.
672  tags(2) = adjustl( tags(2) )
673  cmdsc( nmtbb ) = tags(2)(1:4)
674  endif
675  if ( ntag > 2 ) then
676  ! The third additional field contains the element name.
677  tags(3) = adjustl( tags(3) )
678  do ii = 1, 120
679  cmelem( ii, nmtbb ) = tags(3)(ii:ii)
680  enddo
681  endif
682  endif
683 
684  return
685 end subroutine sntbbe
686 
707 subroutine sntbde ( lunt, ifxyn, line, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
708 
709  implicit none
710 
711  integer, intent(in) :: lunt, ifxyn, mxmtbd, mxelem
712  integer, intent(inout) :: nmtbd
713  integer, intent(out) :: imfxyn(*), nmelem(*), iefxyn(mxmtbd,mxelem)
714  integer ii, ipt, ntag, nelem, nemock, ifxy, igetfxy, igetntbl
715 
716  character*(*), intent(in) :: line
717  character*(*), parameter :: bort_str1_head = 'BUFRLIB: SNTBDE - TABLE D ENTRY FOR SEQUENCE DESCRIPTOR: '
718  character, intent(out) :: cmseq(120,*), cmmnem(8,*), cmdsc(*)*4, ceelem(mxmtbd,mxelem)*120
719  character*200 tags(10), cline
720  character*128 bort_str1, bort_str2
721  character*6 adsc
722 
723  logical done
724 
725  if ( nmtbd >= mxmtbd ) call bort('BUFRLIB: SNTBDE - OVERFLOW OF MERGED ARRAYS')
726  nmtbd = nmtbd + 1
727 
728  ! Store the FXY number. This is the sequence descriptor.
729 
730  imfxyn( nmtbd ) = ifxyn
731 
732  ! Is there any other information within the first line of the table entry? If so, it follows a "|" separator.
733 
734  do ii = 1, 8
735  cmmnem( ii, nmtbd ) = ' '
736  enddo
737  cmdsc( nmtbd ) = ' '
738  do ii = 1, 120
739  cmseq( ii, nmtbd ) = ' '
740  enddo
741  ipt = index( line, '|' )
742  if ( ipt /= 0 ) then
743  ! Parse the rest of the line. Any of the fields may be blank.
744  call parstr ( line(ipt+1:), tags, 10, ntag, ';', .false. )
745  if ( ntag > 0 ) then
746  ! The first additional field contains the mnemonic.
747  tags(1) = adjustl( tags(1) )
748  ! If there is a mnemonic, then make sure it's legal.
749  if ( ( tags(1) /= ' ' ) .and. ( nemock( tags(1) ) /= 0 ) ) then
750  call sntbestr(bort_str1_head, ifxyn, bort_str1)
751  bort_str2 = ' HAS ILLEGAL MNEMONIC'
752  call bort2(bort_str1, bort_str2)
753  endif
754  do ii = 1, 8
755  cmmnem( ii, nmtbd ) = tags(1)(ii:ii)
756  enddo
757  endif
758  if ( ntag > 1 ) then
759  ! The second additional field contains descriptor codes.
760  tags(2) = adjustl( tags(2) )
761  cmdsc( nmtbd ) = tags(2)(1:4)
762  endif
763  if ( ntag > 2 ) then
764  ! The third additional field contains the sequence name.
765  tags(3) = adjustl( tags(3) )
766  do ii = 1, 120
767  cmseq( ii, nmtbd ) = tags(3)(ii:ii)
768  enddO
769  endif
770  endif
771 
772  ! Now, read and parse all remaining lines from this table entry. Each line should contain an element descriptor for
773  ! the sequence represented by the current sequence descriptor.
774 
775  nelem = 0
776  done = .false.
777  do while ( .not. done )
778  if ( igetntbl( lunt, cline ) /= 0 ) then
779  call sntbestr(bort_str1_head, ifxyn, bort_str1)
780  bort_str2 = ' IS INCOMPLETE'
781  call bort2(bort_str1, bort_str2)
782  endif
783  call parstr ( cline, tags, 10, ntag, '|', .false. )
784  if ( ntag < 2 ) then
785  call sntbestr(bort_str1_head, ifxyn, bort_str1)
786  bort_str2 = ' HAS BAD ELEMENT CARD'
787  call bort2(bort_str1, bort_str2)
788  endif
789  ! The second field contains the FXY number for this element.
790  if ( igetfxy( tags(2), adsc ) /= 0 ) then
791  call sntbestr(bort_str1_head, ifxyn, bort_str1)
792  bort_str2 = ' HAS BAD OR MISSING ELEMENT FXY NUMBER'
793  call bort2(bort_str1, bort_str2)
794  endif
795  if ( nelem >= mxelem ) CALL bort('BUFRLIB: SNTBDE - OVERFLOW OF MERGED ARRAYS')
796  nelem = nelem + 1
797  iefxyn( nmtbd, nelem ) = ifxy( adsc )
798  ! The third field (if it exists) contains the element name.
799  if ( ntag > 2 ) then
800  tags(3) = adjustl( tags(3) )
801  ceelem( nmtbd, nelem ) = tags(3)(1:120)
802  else
803  ceelem( nmtbd, nelem ) = ' '
804  endif
805  ! Is this the last line for this table entry?
806  if ( index( tags(2), ' >' ) == 0 ) done = .true.
807  enddo
808  nmelem( nmtbd ) = nelem
809 
810  return
811 end subroutine sntbde
812 
820 subroutine sntbfe ( lunt, ifxyn )
821 
822  use bufrlib
823 
824  implicit none
825 
826  integer, intent(in) :: lunt, ifxyn
827  integer idfxy(10), idval(25), nidfxy, nidval, ntag, ii, jj, ival, ier, ipt, lt3, ifxy, igetfxy, igetntbl
828 
829  character*160 cline, tags(4), cdstr(2), adsc(10), cval(25)
830  character*(*), parameter :: bort_str1_head = 'BUFRLIB: SNTBFE - TABLE F ENTRY FOR ELEMENT DESCRIPTOR: '
831  character*128 bort_str1, bort_str2
832  character*6 cdsc
833 
834  logical done, lstnblk
835 
836  ! We already have the FXY number. Now we need to read and parse all of the remaining lines from the table entry for this
837  ! FXY number. The information for each individual code figure or bit number will then be stored as a separate entry within
838  ! the internal memory structure.
839 
840  done = .false.
841  nidfxy = 0
842  nidval = 0
843 
844  do while ( .not. done )
845 
846  if ( igetntbl( lunt, cline ) /= 0 ) then
847  call sntbestr(bort_str1_head, ifxyn, bort_str1)
848  bort_str2 = ' IS INCOMPLETE'
849  call bort2(bort_str1, bort_str2)
850  endif
851 
852  call parstr ( cline, tags, 4, ntag, '|', .false. )
853  if ( ( ntag < 2 ) .or. ( ntag > 3 ) ) then
854  call sntbestr(bort_str1_head, ifxyn, bort_str1)
855  bort_str2 = ' HAS BAD CARD'
856  call bort2(bort_str1, bort_str2)
857  endif
858 
859  if ( ntag == 2 ) then
860 
861  ! This line contains a list of dependencies.
862 
863  call parstr ( tags(2), cdstr, 2, ntag, '=', .false. )
864  if ( ntag /= 2 ) then
865  call sntbestr(bort_str1_head, ifxyn, bort_str1)
866  bort_str2 = ' HAS BAD DEPENDENCY CARD'
867  call bort2(bort_str1, bort_str2)
868  endif
869  ! Parse the list of FXY numbers.
870  call parstr ( cdstr(1), adsc, 10, nidfxy, ',', .false. )
871  if ( ( nidfxy == 0 ) .or. ( ( nidfxy == 1 ) .and. ( adsc(1) == ' ' ) ) ) then
872  call sntbestr(bort_str1_head, ifxyn, bort_str1)
873  bort_str2 = ' HAS BAD DEPENDENCY LIST (FXY)'
874  call bort2(bort_str1, bort_str2)
875  endif
876  do ii = 1, nidfxy
877  if ( igetfxy( adsc(ii), cdsc ) /= 0 ) then
878  call sntbestr(bort_str1_head, ifxyn, bort_str1)
879  bort_str2 = ' HAS BAD DEPENDENCY (FXY)'
880  call bort2(bort_str1, bort_str2)
881  endif
882  idfxy(ii) = ifxy( cdsc )
883  enddo
884  ! Parse the list of values.
885  call parstr ( cdstr(2), cval, 25, nidval, ',', .false. )
886  if ( ( nidval == 0 ) .or. ( ( nidval == 1 ) .and. ( cval(1) == ' ' ) ) ) then
887  call sntbestr(bort_str1_head, ifxyn, bort_str1)
888  bort_str2 = ' HAS BAD DEPENDENCY LIST (VAL)'
889  call bort2(bort_str1, bort_str2)
890  endif
891  do ii = 1, nidval
892  cval(ii) = adjustl( cval(ii) )
893  call strnum ( cval(ii), ival, ier )
894  if ( ier /= 0 ) then
895  call sntbestr(bort_str1_head, ifxyn, bort_str1)
896  bort_str2 = ' HAS BAD DEPENDENCY (VAL)'
897  call bort2(bort_str1, bort_str2)
898  endif
899  idval(ii) = ival
900  enddo
901 
902  else
903 
904  ! This line contains a value (code figure or bit number) and corresponding meaning.
905 
906  ipt = index( tags(2), ' >' )
907  if ( ipt == 0 ) then
908  ! This is the last line for this table entry.
909  done = .true.
910  else
911  tags(2)(ipt+1:ipt+1) = ' '
912  endif
913  tags(2) = adjustl( tags(2) )
914  call strnum ( tags(2), ival, ier )
915  ! Find the last non-blank character in the meaning string.
916  tags(3) = adjustl( tags(3) )
917  lt3 = len(tags(3))
918  lstnblk = .false.
919  do while ( ( lt3 > 0 ) .and. ( .not. lstnblk ) )
920  if ( tags(3)(lt3:lt3) /= ' ' ) then
921  lstnblk = .true.
922  else
923  lt3 = lt3 - 1
924  endif
925  enddo
926  ! Store the information for this value within the internal memory structure.
927  if ( ( nidfxy == 0 ) .and. ( nidval == 0 ) ) then
928  call strtbfe_c ( ifxyn, ival, tags(3), lt3, -1, -1 )
929  else
930  do ii = 1, nidfxy
931  do jj = 1, nidval
932  call strtbfe_c ( ifxyn, ival, tags(3), lt3, idfxy(ii), idval(jj) )
933  enddo
934  enddo
935  endif
936 
937  endif
938 
939  enddo
940 
941  return
942 end subroutine sntbfe
943 
951 subroutine sntbestr ( hestr, ifxyn, estr )
952 
953  implicit none
954 
955  character*(*), intent(in) :: hestr
956  character*(*), intent(out) :: estr
957  character*6 adn30, clemon
958 
959  integer, intent(in) :: ifxyn
960 
961  clemon = adn30( ifxyn, 6 )
962  estr = hestr // clemon(1:1) // '-' // clemon(2:3) // '-' // clemon(4:6)
963 
964  return
965 end subroutine sntbestr
966 
977 integer function igetntbl ( lunt, line ) result ( iret )
978 
979  implicit none
980 
981  integer, intent(in) :: lunt
982  integer ier
983 
984  character*(*), intent(out) :: line
985 
986  do while (.true.)
987  read ( lunt, '(A)', iostat = ier ) line
988  if ( ( ier /= 0 ) .or. ( line(1:3) == 'END' ) ) then
989  iret = -1
990  return
991  endif
992  if ( ( line /= ' ' ) .and. ( line(1:1) /= '#' ) ) then
993  iret = 0
994  return
995  endif
996  enddo
997 
998 end function igetntbl
999 
1012 integer function igettdi ( iflag ) result ( iret )
1013 
1014  implicit none
1015 
1016  integer, intent(in) :: iflag
1017  integer, parameter :: idxmin = 62976 ! = ifxy('354000')
1018  integer, parameter :: idxmax = 63231 ! = ifxy('354255')
1019  integer idx
1020 
1021  save idx
1022 
1023  if ( iflag == 0 ) then
1024  ! Initialize the index to one less than the actual minimum value. That way, the next normal call will return the
1025  ! minimum value.
1026  idx = idxmin - 1
1027  iret = -1
1028  else
1029  idx = idx + 1
1030  if ( idx > idxmax ) call bort('BUFRLIB: IGETTDI - IDXMAX OVERFLOW')
1031  iret = idx
1032  endif
1033 
1034  return
1035 end function igettdi
1036 
1056 subroutine gettbh ( luns, lunl, tab, imt, imtv, iogce, iltv )
1057 
1058  implicit none
1059 
1060  integer, intent(in) :: luns, lunl
1061  integer, intent(out) :: imt, imtv, iogce, iltv
1062  integer ntag, imt2, iersn, igetntbl
1063 
1064  character, intent(in) :: tab
1065 
1066  character*128 bort_str
1067  character*(*), parameter :: bort_str_head = 'BUFRLIB: GETTBH - BAD OR MISSING HEADER WITHIN '
1068  character*40 header
1069  character*30 tags(5), label
1070  character*3 cftyp
1071  character*2 cttyp
1072 
1073  logical badlabel
1074 
1075  ! Statement function to check for bad header line label
1076  badlabel( label ) = ( ( index( label, cttyp ) == 0 ) .or. ( index( label, cftyp ) == 0 ) )
1077 
1078  cttyp = tab // ' '
1079 
1080  ! Read and parse the header line of the standard file.
1081 
1082  cftyp = 'STD'
1083  if ( igetntbl( luns, header ) /= 0 ) then
1084  bort_str = bort_str_head // cftyp // ' TABLE ' // tab
1085  call bort(bort_str)
1086  endif
1087  call parstr ( header, tags, 5, ntag, '|', .false. )
1088  if ( ( ntag < 3 ) .or. ( badlabel( tags(1) ) ) ) then
1089  bort_str = bort_str_head // cftyp // ' TABLE ' // tab
1090  call bort(bort_str)
1091  endif
1092  call strnum ( tags(2), imt, iersn )
1093  call strnum ( tags(3), imtv, iersn )
1094 
1095  ! Read and parse the header line of the local file.
1096 
1097  cftyp = 'LOC'
1098  if ( igetntbl( lunl, header ) /= 0 ) then
1099  bort_str = bort_str_head // cftyp // ' TABLE ' // tab
1100  call bort(bort_str)
1101  endif
1102  call parstr ( header, tags, 5, ntag, '|', .false. )
1103  if ( ( ntag < 4 ) .or. ( badlabel( tags(1) ) ) ) then
1104  bort_str = bort_str_head // cftyp // ' TABLE ' // tab
1105  call bort(bort_str)
1106  endif
1107  call strnum ( tags(2), imt2, iersn )
1108  call strnum ( tags(3), iogce, iersn )
1109  call strnum ( tags(4), iltv, iersn )
1110 
1111  ! Verify that both files are for the same master table.
1112 
1113  if ( imt /= imt2 ) then
1114  write(bort_str,'("BUFRLIB: GETTBH - MASTER TABLE NUMBER MISMATCH BETWEEN STD AND LOC TABLE ",A)') tab
1115  call bort(bort_str)
1116  endif
1117 
1118  return
1119 end subroutine gettbh
1120 
1132 subroutine getntbe ( lunt, ifxyn, line, iret )
1133 
1134  implicit none
1135 
1136  integer, intent(in) :: lunt
1137  integer, intent(out) :: ifxyn, iret
1138  integer ntag, igetfxy, ifxy, igetntbl
1139 
1140  character*(*), intent(out) :: line
1141  character*128 bort_str1, bort_str2
1142  character*20 tags(4)
1143  character*6 adsc
1144 
1145  ! Get the first line of the next entry in the file.
1146 
1147  iret = igetntbl( lunt, line )
1148  if ( iret == 0 ) then
1149  ! The first field within this line should contain the FXY number.
1150  call parstr ( line(1:20), tags, 4, ntag, '|', .false. )
1151  if ( igetfxy( tags(1), adsc ) /= 0 ) then
1152  bort_str1 = 'BUFRLIB: GETNTBE - CARD BEGINNING WITH: ' // line(1:20)
1153  bort_str2 = ' HAS BAD OR MISSING FXY NUMBER'
1154  call bort2(bort_str1, bort_str2)
1155  endif
1156  ! Store the WMO bit-wise representation of the FXY number.
1157  ifxyn = ifxy( adsc )
1158  endif
1159 
1160  return
1161 end subroutine getntbe
1162 
1193 recursive subroutine codflg(cf)
1194 
1195  use bufrlib
1196 
1197  use moda_tablef
1198 
1199  implicit none
1200 
1201  integer bort_target_set
1202 
1203  character, intent(in) :: cf
1204 
1205  character*128 bort_str
1206  character my_cf
1207 
1208  ! If we're catching bort errors, set a target return location if one doesn't already exist.
1209 
1210  if (bort_target_set() == 1) then
1211  call catch_bort_codflg_c(cf)
1212  call bort_target_unset
1213  return
1214  endif
1215 
1216  my_cf = cf
1217  call capit(my_cf)
1218  if(my_cf /= 'Y' .and. my_cf /= 'N') then
1219  write(bort_str,'("BUFRLIB: CODFLG - INPUT ARGUMENT IS ",A1,", IT MUST BE EITHER Y, y, N OR n")') cf
1220  call bort(bort_str)
1221  endif
1222  cdmf = my_cf
1223 
1224  return
1225 end subroutine codflg
1226 
1239 integer function nemock(nemo) result(iret)
1240 
1241  implicit none
1242 
1243  integer i, lnemo
1244 
1245  character*(*), intent(in) :: nemo
1246 
1247  ! Get the length of nemo
1248 
1249  lnemo = 0
1250  do i=len(nemo),1,-1
1251  if(nemo(i:i)/=' ') then
1252  lnemo = i
1253  exit
1254  endif
1255  enddo
1256  if(lnemo<1 .or. lnemo>8) then
1257  iret = -1
1258  return
1259  endif
1260 
1261  ! Scan nemo for allowable characters
1262 
1263  if ( verify(nemo(1:lnemo),'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.') == 0 ) then
1264  iret = 0
1265  else
1266  iret = -2
1267  endif
1268 
1269  return
1270 end function nemock
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
recursive subroutine bort2(str1, str2)
Log two error messages, then either return to or abort the application program.
Definition: borts.F90:48
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 errwrt(str)
Specify a custom location for the logging of error and diagnostic messages generated by the NCEPLIBS-...
Definition: errwrt.F90:32
integer function ifxy(adsc)
Convert an FXY value from its 6 character representation to its WMO bit-wise representation.
Definition: fxy.F90:152
subroutine sntbde(lunt, ifxyn, line, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem)
Store the first line of an entry that was previously read from an ASCII master Table D file into a se...
recursive subroutine codflg(cf)
Specify whether or not code and flag table information should be included during all future reads of ...
subroutine sntbfe(lunt, ifxyn)
Read an entire entry from a previously-opened ASCII master Code/Flag table file, then store the infor...
subroutine sntbestr(hestr, ifxyn, estr)
Generate an error-reporting string containing an FXY number.
subroutine rdmtbd(lunstd, lunltd, mxmtbd, mxelem, imt, imtv, iogce, iltv, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem)
Read master Table D information from two separate ASCII files (one standard and one local) and then m...
subroutine mtfnam(imt, imtv, iogce, imtvl, tbltyp, stdfil, locfil)
Based on the input arguments, determine the names of the corresponding standard and local master tabl...
Definition: mastertable.F90:82
integer function nemock(nemo)
Check a mnemonic for validity.
subroutine sntbbe(ifxyn, line, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem)
Store an entry that was previously read from an ASCII master Table B file into a set of merged Fortra...
subroutine getntbe(lunt, ifxyn, line, iret)
Read the first line of the next entry from the specified ASCII master table B, table D or table F (Co...
integer function igettdi(iflag)
Depending on the value of the input flag, either return the next usable scratch Table D index for the...
subroutine rdmtbb(lunstb, lunltb, mxmtbb, imt, imtv, iogce, iltv, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem)
Read master Table B information from two separate ASCII files (one standard and one local) and then m...
integer function igetntbl(lunt, line)
Read the next line from an ASCII master table B, table D or Code/Flag table file, ignoring any blank ...
subroutine gettbh(luns, lunl, tab, imt, imtv, iogce, iltv)
Read the header lines from two separate ASCII files (one standard and one local) containing master ta...
recursive subroutine mtinfo(cmtdir, lunmt1, lunmt2)
Specify the directory location and Fortran logical unit numbers to be used when reading master BUFR t...
Definition: mastertable.F90:35
subroutine rdmtbf(lunstf, lunltf)
Read master Code/Flag table information from two separate ASCII files (one standard and one local) an...
integer function ireadmt(lun)
Check the most recent BUFR message that was read via a call to one of the message-reading subroutines...
recursive subroutine strnum(str, num, iret)
Decode an integer from a character string.
Definition: misc.F90:156
subroutine strsuc(str1, str2, lens)
Remove leading and trailing blanks from a character string.
Definition: misc.F90:199
subroutine capit(str)
Capitalize all of the alphabetic characters in a string.
Definition: misc.F90:334
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.
Declare arrays and variables used to store master Table B and Table D entries within internal memory.
integer, dimension(:), allocatable idfxyn
WMO bit-wise representations of FXY numbers for master Table D.
character, dimension(:,:), allocatable cbunit
Units corresponding to ibfxyn.
integer nmtb
Number of master Table B entries (up to a maximum of mxmtbb).
character, dimension(:,:), allocatable cbbw
Bit widths corresponding to ibfxyn.
character, dimension(:,:), allocatable cdseq
Sequence names corresponding to idfxyn.
character, dimension(:,:), allocatable cbmnem
Mnemonics corresponding to ibfxyn.
integer, dimension(:), allocatable ndelem
Numbers of child descriptors corresponding to idfxyn.
character, dimension(:,:), allocatable cbelem
Element names corresponding to ibfxyn.
character, dimension(:,:), allocatable cbscl
Scale factors corresponding to ibfxyn.
character, dimension(:,:), allocatable cdmnem
Mnemonics corresponding to idfxyn.
character, dimension(:,:), allocatable cbsref
Reference values corresponding to ibfxyn.
integer nmtd
Number of master Table D entries (up to a maximum of mxmtbd).
integer, dimension(:), allocatable idefxy
WMO bit-wise representations of child descriptors corresponding to idfxyn.
integer, dimension(:), allocatable ibfxyn
WMO bit-wise representations of FXY numbers for master Table B.
Declare arrays and variables used to store master Table B and Table D entries within internal memory.
character *120, dimension(:,:), allocatable ceelem
Element names corresponding to iefxyn.
character *4, dimension(:), allocatable cmdscb
Descriptor codes for Table B elements.
integer, dimension(:,:), allocatable iefxyn
WMO bit-wise representations of child descriptors of Table D sequences.
character *4, dimension(:), allocatable cmdscd
Descriptor codes for Table D sequences.
Declare arrays used by various subroutines and functions to hold a temporary working copy of a Sectio...
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 ...
integer, dimension(:), allocatable isc3
Section 3 switch for each file ID:
Declare a variable used to indicate whether master code and flag tables should be read.
character cdmf
Flag indicating whether to include code and flag table information during reads of master BUFR tables...
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
recursive subroutine upds3(mbay, lcds3, cds3, nds3)
Read the sequence of data descriptors contained within Section 3 of a BUFR message.
Definition: s013vals.F90:850
integer function istdesc(idn)
Given the WMO bit-wise representation of an FXY value for a descriptor, check whether the descriptor ...
Definition: standard.F90:317
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 x84(iin8, iout4, nval)
Encode one or more 8-byte integer values as 4-byte integer values.
Definition: x4884.F90:65