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