NCEPLIBS-bufr  12.1.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
37 
38  implicit none
39 
40  integer, intent(in) :: lunmt1, lunmt2
41  integer my_lunmt1, my_lunmt2, lun1, lun2, lmtd
42 
43  character*(*), intent(in) :: cmtdir
44  character*240 mtdir
45 
46  common /mstinf/ lun1, lun2, lmtd, mtdir
47 
48  ! Check for I8 integers
49  if(im8b) then
50  im8b=.false.
51 
52  call x84 ( lunmt1, my_lunmt1, 1 )
53  call x84 ( lunmt2, my_lunmt2, 1 )
54  call mtinfo ( cmtdir, my_lunmt1, my_lunmt2 )
55 
56  im8b=.true.
57  return
58  endif
59 
60  call strsuc ( cmtdir, mtdir, lmtd )
61 
62  lun1 = lunmt1
63  lun2 = lunmt2
64 
65  return
66 end subroutine mtinfo
67 
86 subroutine mtfnam ( imt, imtv, iogce, imtvl, tbltyp, stdfil, locfil )
87 
88  implicit none
89 
90  integer, intent(in) :: imt, imtv, iogce, imtvl
91  integer iprt, lun1, lun2, lmtd, ltbt, isize
92 
93  character*(*), intent(in) :: tbltyp
94  character*(*), intent(out) :: stdfil, locfil
95 
96  character*16 tbltyp2
97  character*20 fmtf
98  character*240 mtdir
99  character*128 bort_str
100 
101  logical found
102 
103  common /quiet/ iprt
104  common /mstinf/ lun1, lun2, lmtd, mtdir
105 
106  call strsuc ( tbltyp, tbltyp2, ltbt )
107 
108  ! Determine the standard master table path/filename.
109 
110  if ( ( imt == 0 ) .and. ( imtv <= 13 ) ) then
111  ! For master table 0, version 13 is a superset of all earlier versions.
112  stdfil = mtdir(1:lmtd) // '/bufrtab.' // tbltyp2(1:ltbt) // '_STD_0_13'
113  else
114  write ( fmtf, '(A,I1,A,I1,A)' ) '(4A,I', isize(imt), ',A,I', isize(imtv), ')'
115  write ( stdfil, fmtf ) mtdir(1:lmtd), '/bufrtab.', tbltyp2(1:ltbt), '_STD_', imt, '_', imtv
116  endif
117  if ( iprt >= 2 ) then
118  call errwrt('Standard ' // tbltyp2(1:ltbt) // ':')
119  call errwrt(stdfil)
120  endif
121  inquire ( file = stdfil, exist = found )
122  if ( .not. found ) then
123  bort_str = 'BUFRLIB: MTFNAM - COULD NOT FIND STANDARD FILE:'
124  call bort2(bort_str, stdfil)
125  endif
126 
127  ! Now determine the local master table path/filename.
128 
129  ! Use the local table corresponding to the originating center and local table version number, if such a table exists.
130  ! Otherwise use the local table from NCEP.
131 
132  write ( fmtf, '(A,I1,A,I1,A,I1,A)' ) '(4A,I', isize(imt), ',A,I', isize(iogce), ',A,I', isize(imtvl), ')'
133  write ( locfil, fmtf ) mtdir(1:lmtd), '/bufrtab.', tbltyp2(1:ltbt), '_LOC_', imt, '_', iogce, '_', imtvl
134  if ( iprt >= 2 ) then
135  call errwrt('Local ' // tbltyp2(1:ltbt) // ':')
136  call errwrt(locfil)
137  endif
138  inquire ( file = locfil, exist = found )
139  if ( .not. found ) then
140  ! Use the local table from NCEP.
141  locfil = mtdir(1:lmtd) // '/bufrtab.' // tbltyp2(1:ltbt) // '_LOC_0_7_1'
142  if ( iprt >= 2 ) then
143  call errwrt('Local ' // tbltyp2(1:ltbt) // ' not found, so using:')
144  call errwrt(locfil)
145  endif
146  inquire ( file = locfil, exist = found )
147  if ( .not. found ) then
148  bort_str = 'BUFRLIB: MTFNAM - COULD NOT FIND LOCAL FILE:'
149  call bort2(bort_str, locfil)
150  endif
151  endif
152 
153  return
154 end subroutine mtfnam
155 
177 integer function ireadmt ( lun ) result ( iret )
178 
179  use bufrlib
180 
181  use modv_vars, only: maxnc, maxcd, mxmtbb, mxmtbd
182 
183  use moda_mstabs
184  use moda_bitbuf
185  use moda_rdmtb
186  use moda_sc3bfr
187  use moda_s3list
188  use moda_tablef
189 
190  implicit none
191 
192  integer, intent(in) :: lun
193  integer iprt, lun1, lun2, lmtd, lmt, lmtv, logce, lmtvl, imt, imtv, iogce, imtvl, ii, jj, idx, ncds3, ier, &
194  ibmt, ibmtv, ibogce, ibltv, idmt, idmtv, idogce, idltv, iupbs01, ifxy, istdesc
195 
196  character*(*), parameter :: bort_str1 = 'BUFRLIB: IREADMT - COULD NOT OPEN STANDARD FILE:'
197  character*(*), parameter :: bort_str2 = 'BUFRLIB: IREADMT - COULD NOT OPEN LOCAL FILE:'
198  character*275 stdfil,locfil
199  character*240 mtdir
200 
201  logical allstd
202 
203  common /quiet/ iprt
204  common /mstinf/ lun1, lun2, lmtd, mtdir
205 
206  ! Initializing the following value ensures that new master tables are read during the first call to this subroutine.
207 
208  data lmt /-99/
209 
210  save lmt, lmtv, logce, lmtvl
211 
212  iret = 0
213 
214  ! Unpack some Section 1 information from the message that was most recently read.
215 
216  imt = iupbs01( mbay(1,lun), 'BMT' )
217  imtv = iupbs01( mbay(1,lun), 'MTV' )
218  iogce = iupbs01( mbay(1,lun), 'OGCE' )
219  imtvl = iupbs01( mbay(1,lun), 'MTVL' )
220 
221  ! Compare the master table and master table version numbers from this message to those from the message that was
222  ! processed during the previous call to this subroutine.
223 
224  if ( ( imt /= lmt ) .or. ( ( imt /= 0 ) .and. ( imtv /= lmtv ) ) .or. &
225  ( ( imt == 0 ) .and. ( imtv /= lmtv ) .and. ( ( imtv > 13 ) .or. ( lmtv > 13 ) ) ) ) then
226  ! Either the master table number has changed
227  ! OR
228  ! The master table number hasn't changed, but it isn't 0, and the table version number has changed
229  ! OR
230  ! The master table number hasn't changed and is 0, but the table version number has changed, and at least one of the
231  ! table version numbers (i.e. the current or the previous) is greater than 13 (which is the last version that was a
232  ! superset of all earlier versions of master table 0!)
233 
234  ! In any of these cases, we need to read in new tables!
235  iret = 1
236 
237  else
238 
239  ! Unpack the list of Section 3 descriptors from the message and determine if any of them are local descriptors.
240  call upds3 ( mbay(1,lun), maxnc, cds3, ncds3 )
241  ii = 1
242  allstd = .true.
243  do while ( (allstd) .and. (ii<=ncds3) )
244  if ( istdesc(ifxy(cds3(ii))) == 0 ) then
245  allstd = .false.
246  else
247  ii = ii + 1
248  endif
249  enddo
250 
251  ! If there was at least one local (i.e. non-standard) descriptor, and if either the originating center or local table
252  ! version number are different than those from the message that was processed during the previous call to this subroutine,
253  ! then we need to read in new tables.
254  if ( ( .not. allstd ) .and. ( ( iogce /= logce ) .or. ( imtvl /= lmtvl ) ) ) iret = 1
255 
256  endif
257 
258  if ( iret == 0 ) return
259 
260  lmt = imt
261  lmtv = imtv
262  logce = iogce
263  lmtvl = imtvl
264 
265  if ( iprt >= 2 ) then
266  call errwrt(' ')
267  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
268  call errwrt('BUFRLIB: IREADMT - OPENING/READING MASTER TABLES')
269  endif
270 
271  if ( isc3(lun) /= 0 ) then
272 
273  ! Locate and open the master Table B files. There should be one file of standard descriptors and one file of local
274  ! descriptors.
275  call mtfnam ( imt, imtv, iogce, imtvl, 'TableB', stdfil, locfil )
276  open ( unit = lun1, file = stdfil, iostat = ier )
277  if ( ier /= 0 ) call bort2(bort_str1, stdfil)
278  open ( unit = lun2, file = locfil, iostat = ier )
279  if ( ier /= 0 ) call bort2(bort_str2, locfil)
280 
281  ! Read the master Table B files.
282  call rdmtbb ( lun1, lun2, mxmtbb, ibmt, ibmtv, ibogce, ibltv, nmtb, ibfxyn, cbscl, cbsref, cbbw, &
284 
285  ! Close the master Table B files.
286  close ( unit = lun1 )
287  close ( unit = lun2 )
288 
289  ! Locate and open the master Table D files. There should be one file of standard descriptors and one file of local
290  ! descriptors.
291  call mtfnam ( imt, imtv, iogce, imtvl, 'TableD', stdfil, locfil )
292  open ( unit = lun1, file = stdfil, iostat = ier )
293  if ( ier /= 0 ) call bort2(bort_str1, stdfil)
294  open ( unit = lun2, file = locfil, iostat = ier )
295  if ( ier /= 0 ) call bort2(bort_str2, locfil)
296 
297  ! Read the master Table D files.
298  call rdmtbd ( lun1, lun2, mxmtbd, maxcd, idmt, idmtv, idogce, idltv, nmtd, idfxyn, cdmnem, cmdscd, cdseq, &
299  ndelem, iefxyn, ceelem )
300  do ii = 1, nmtd
301  do jj = 1, ndelem(ii)
302  idx = icvidx_c( ii-1, jj-1, maxcd ) + 1
303  idefxy(idx) = iefxyn(ii,jj)
304  enddo
305  enddo
306 
307  ! Close the master Table D files.
308  close ( unit = lun1 )
309  close ( unit = lun2 )
310 
311  ! Copy master table B and D information into internal C arrays.
313  ndelem, idefxy, maxcd )
314  endif
315 
316  if ( cdmf == 'Y' ) then
317 
318  ! Locate and open the master code and flag table files. There should be one file corresponding to the standard Table B
319  ! descriptors, and one file corresponding to the local Table B descriptors.
320  call mtfnam ( imt, imtv, iogce, imtvl, 'CodeFlag', stdfil, locfil )
321  open ( unit = lun1, file = stdfil, iostat = ier )
322  if ( ier /= 0 ) call bort2(bort_str1, stdfil)
323  open ( unit = lun2, file = locfil, iostat = ier )
324  if ( ier /= 0 ) call bort2(bort_str2, locfil)
325 
326  ! Read the master code and flag table files.
327  call rdmtbf ( lun1, lun2 )
328 
329  ! Close the master code and flag table files.
330  close ( unit = lun1 )
331  close ( unit = lun2 )
332  endif
333 
334  if ( iprt >= 2 ) then
335  call errwrt('+++++++++++++++++++++++++++++++++++++++++++++++++')
336  call errwrt(' ')
337  endif
338 
339  return
340 end function ireadmt
341 
370 subroutine rdmtbb ( lunstb, lunltb, mxmtbb, imt, imtv, iogce, iltv, nmtbb, imfxyn, cmscl, cmsref, cmbw, &
371  cmunit, cmmnem, cmdsc, cmelem )
372 
373  implicit none
374 
375  integer, intent(in) :: lunstb, lunltb, mxmtbb
376  integer, intent(out) :: imt, imtv, iogce, iltv, nmtbb, imfxyn(*)
377  integer isfxyn, ilfxyn, iers, ierl
378 
379  character, intent(out) :: cmelem(120,*), cmunit(24,*), cmsref(12,*), cmmnem(8,*), cmscl(4,*), cmbw(4,*), cmdsc(*)*4
380  character*200 stline, ltline
381  character*128 bort_str
382  character*6 cmatch, adn30
383 
384  ! Read and parse the header lines of both files.
385 
386  call gettbh ( lunstb, lunltb, 'B', imt, imtv, iogce, iltv )
387 
388  ! Read through the remainder of both files, merging the contents into a unified set of master Table B arrays.
389 
390  nmtbb = 0
391  call getntbe ( lunstb, isfxyn, stline, iers )
392  call getntbe ( lunltb, ilfxyn, ltline, ierl )
393  do while ( ( iers == 0 ) .or. ( ierl == 0 ) )
394  if ( ( iers == 0 ) .and. ( ierl == 0 ) ) then
395  if ( isfxyn == ilfxyn ) then
396  cmatch = adn30( isfxyn, 6 )
397  write(bort_str,'("BUFRLIB: RDMTBB - STANDARD AND LOCAL '// &
398  'TABLE B FILES BOTH CONTAIN SAME FXY NUMBER: ",5A)') cmatch(1:1), '-', cmatch(2:3), '-', cmatch(4:6)
399  call bort(bort_str)
400  else if ( isfxyn < ilfxyn ) then
401  call sntbbe ( isfxyn, stline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
402  call getntbe ( lunstb, isfxyn, stline, iers )
403  else
404  call sntbbe ( ilfxyn, ltline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
405  call getntbe ( lunltb, ilfxyn, ltline, ierl )
406  endif
407  else if ( iers == 0 ) then
408  call sntbbe ( isfxyn, stline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
409  call getntbe ( lunstb, isfxyn, stline, iers )
410  else
411  call sntbbe ( ilfxyn, ltline, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
412  call getntbe ( lunltb, ilfxyn, ltline, ierl )
413  endif
414  enddo
415 
416  return
417 end subroutine rdmtbb
418 
448 subroutine rdmtbd ( lunstd, lunltd, mxmtbd, mxelem, imt, imtv, iogce, iltv, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, &
449  nmelem, iefxyn, ceelem )
450 
451  implicit none
452 
453  integer, intent(in) :: lunstd, lunltd, mxmtbd, mxelem
454  integer, intent(out) :: imt, imtv, iogce, iltv, nmtbd, imfxyn(*), nmelem(*), iefxyn(mxmtbd,mxelem)
455  integer isfxyn, ilfxyn, iers, ierl
456 
457  character, intent(out) :: cmseq(120,*), cmmnem(8,*), cmdsc(*)*4, ceelem(mxmtbd,mxelem)*120
458 
459  character*200 stline, ltline
460  character*128 bort_str
461  character*6 cmatch, adn30
462 
463  ! Read and parse the header lines of both files.
464 
465  call gettbh ( lunstd, lunltd, 'D', imt, imtv, iogce, iltv )
466 
467  ! Read through the remainder of both files, merging the contents into a unified set of master Table D arrays.
468 
469  nmtbd = 0
470  call getntbe ( lunstd, isfxyn, stline, iers )
471  call getntbe ( lunltd, ilfxyn, ltline, ierl )
472  do while ( ( iers == 0 ) .or. ( ierl == 0 ) )
473  if ( ( iers == 0 ) .and. ( ierl == 0 ) ) then
474  if ( isfxyn == ilfxyn ) then
475  cmatch = adn30( isfxyn, 6 )
476  write(bort_str,'("BUFRLIB: RDMTBD - STANDARD AND LOCAL '// &
477  'TABLE D FILES BOTH CONTAIN SAME FXY NUMBER: ",5A)') cmatch(1:1), '-', cmatch(2:3), '-', cmatch(4:6)
478  call bort(bort_str)
479  else if ( isfxyn < ilfxyn ) then
480  call sntbde ( lunstd, isfxyn, stline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
481  call getntbe ( lunstd, isfxyn, stline, iers )
482  else
483  call sntbde ( lunltd, ilfxyn, ltline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
484  call getntbe ( lunltd, ilfxyn, ltline, ierl )
485  endif
486  else if ( iers == 0 ) then
487  call sntbde ( lunstd, isfxyn, stline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
488  call getntbe ( lunstd, isfxyn, stline, iers )
489  else
490  call sntbde ( lunltd, ilfxyn, ltline, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
491  call getntbe ( lunltd, ilfxyn, ltline, ierl )
492  endif
493  enddo
494 
495  return
496 end subroutine rdmtbd
497 
507 subroutine rdmtbf ( lunstf, lunltf )
508 
509  use bufrlib
510 
511  implicit none
512 
513  integer, intent(in) :: lunstf, lunltf
514  integer imt, imtv, iogce, iltv, isfxyn, ilfxyn, iers, ierl
515 
516  character*160 stline, ltline
517  character*128 bort_str
518  character*6 cmatch, adn30
519 
520  ! Initialize the internal memory structure, including allocating space for it in case this hasn't already been done.
521 
522  call inittbf_c
523 
524  ! Read and parse the header lines of both files.
525 
526  call gettbh ( lunstf, lunltf, 'F', imt, imtv, iogce, iltv )
527 
528  ! Read through the remainder of both files, merging the contents into a unified internal memory structure.
529 
530  call getntbe ( lunstf, isfxyn, stline, iers )
531  call getntbe ( lunltf, ilfxyn, ltline, ierl )
532  do while ( ( iers == 0 ) .or. ( ierl == 0 ) )
533  if ( ( iers == 0 ) .and. ( ierl == 0 ) ) then
534  if ( isfxyn == ilfxyn ) then
535  cmatch = adn30( isfxyn, 6 )
536  write(bort_str,'("BUFRLIB: RDMTBF - STANDARD AND LOCAL '// &
537  'CODE/FLAG TABLE FILES BOTH CONTAIN SAME FXY NUMBER: ",5A)') cmatch(1:1), '-', cmatch(2:3), '-', cmatch(4:6)
538  call bort(bort_str)
539  else if ( isfxyn < ilfxyn ) then
540  call sntbfe ( lunstf, isfxyn )
541  call getntbe ( lunstf, isfxyn, stline, iers )
542  else
543  call sntbfe ( lunltf, ilfxyn )
544  call getntbe ( lunltf, ilfxyn, ltline, ierl )
545  endif
546  else if ( iers == 0 ) then
547  call sntbfe ( lunstf, isfxyn )
548  call getntbe ( lunstf, isfxyn, stline, iers )
549  else
550  call sntbfe ( lunltf, ilfxyn )
551  call getntbe ( lunltf, ilfxyn, ltline, ierl )
552  endif
553  enddo
554 
555  ! Sort the contents of the internal memory structure.
556 
557  call sorttbf_c
558 
559  return
560 end subroutine rdmtbf
561 
579 subroutine sntbbe ( ifxyn, line, mxmtbb, nmtbb, imfxyn, cmscl, cmsref, cmbw, cmunit, cmmnem, cmdsc, cmelem )
580 
581  implicit none
582 
583  integer, intent(in) :: ifxyn, mxmtbb
584  integer, intent(out) :: nmtbb, imfxyn(*)
585  integer ntag, ii, nemock
586 
587  character, intent(out) :: cmelem(120,*), cmunit(24,*), cmsref(12,*), cmmnem(8,*), cmscl(4,*), cmbw(4,*), cmdsc(*)*4
588  character*(*), intent(in) :: line
589  character*(*), parameter :: bort_str1_head = 'BUFRLIB: SNTBBE - TABLE B ENTRY FOR ELEMENT DESCRIPTOR: '
590  character*200 tags(10), wktag
591  character*128 bort_str1, bort_str2
592 
593  if ( nmtbb >= mxmtbb ) call bort('BUFRLIB: SNTBBE - OVERFLOW OF MERGED ARRAYS')
594  nmtbb = nmtbb + 1
595 
596  ! Store the FXY number. This is the element descriptor.
597 
598  imfxyn( nmtbb ) = ifxyn
599 
600  ! Parse the table entry.
601 
602  call parstr ( line, tags, 10, ntag, '|', .false. )
603  if ( ntag < 4 ) then
604  call sntbestr(bort_str1_head, ifxyn, bort_str1)
605  bort_str2 = ' HAS TOO FEW FIELDS'
606  call bort2(bort_str1, bort_str2)
607  endif
608 
609  ! Scale factor.
610 
611  tags(2) = adjustl( tags(2) )
612  if ( tags(2) == ' ' ) then
613  call sntbestr(bort_str1_head, ifxyn, bort_str1)
614  bort_str2 = ' HAS MISSING SCALE FACTOR'
615  call bort2(bort_str1, bort_str2)
616  endif
617  tags(2)(1:4) = adjustr( tags(2)(1:4) )
618  do ii = 1, 4
619  cmscl( ii, nmtbb ) = tags(2)(ii:ii)
620  enddo
621 
622  ! Reference value.
623 
624  tags(3) = adjustl( tags(3) )
625  if ( tags(3) == ' ' ) then
626  call sntbestr(bort_str1_head, ifxyn, bort_str1)
627  bort_str2 = ' HAS MISSING REFERENCE VALUE'
628  call bort2(bort_str1, bort_str2)
629  endif
630  tags(3)(1:12) = adjustr( tags(3)(1:12) )
631  do ii = 1, 12
632  cmsref( ii, nmtbb ) = tags(3)(ii:ii)
633  enddo
634 
635  ! Bit width.
636 
637  tags(4) = adjustl( tags(4) )
638  if ( tags(4) == ' ' ) then
639  call sntbestr(bort_str1_head, ifxyn, bort_str1)
640  bort_str2 = ' HAS MISSING BIT WIDTH'
641  call bort2(bort_str1, bort_str2)
642  endif
643  tags(4)(1:4) = adjustr( tags(4)(1:4) )
644  do ii = 1, 4
645  cmbw( ii, nmtbb ) = tags(4)(ii:ii)
646  end do
647 
648  ! Units. Note that this field is allowed to be blank.
649 
650  if ( ntag > 4 ) then
651  tags(5) = adjustl( tags(5) )
652  do ii = 1, 24
653  cmunit( ii, nmtbb ) = tags(5)(ii:ii)
654  enddo
655  else
656  do ii = 1, 24
657  cmunit( ii, nmtbb ) = ' '
658  enddo
659  endif
660 
661  ! Comment (additional) fields. Any of these fields may be blank.
662 
663  cmdsc( nmtbb ) = ' '
664  do ii = 1, 8
665  cmmnem( ii, nmtbb ) = ' '
666  enddo
667  do ii = 1, 120
668  cmelem( ii, nmtbb ) = ' '
669  enddo
670  if ( ntag > 5 ) then
671  wktag = tags(6)
672  call parstr ( wktag, tags, 10, ntag, ';', .false. )
673  if ( ntag > 0 ) then
674  ! The first additional field contains the mnemonic.
675  tags(1) = adjustl( tags(1) )
676  ! If there is a mnemonic, then make sure it's legal.
677  if ( ( tags(1) /= ' ' ) .and. ( nemock( tags(1) ) /= 0 ) ) then
678  call sntbestr(bort_str1_head, ifxyn, bort_str1)
679  bort_str2 = ' HAS ILLEGAL MNEMONIC'
680  call bort2(bort_str1, bort_str2)
681  endif
682  do ii = 1, 8
683  cmmnem( ii, nmtbb ) = tags(1)(ii:ii)
684  enddo
685  endif
686  if ( ntag > 1 ) then
687  ! The second additional field contains descriptor codes.
688  tags(2) = adjustl( tags(2) )
689  cmdsc( nmtbb ) = tags(2)(1:4)
690  endif
691  if ( ntag > 2 ) then
692  ! The third additional field contains the element name.
693  tags(3) = adjustl( tags(3) )
694  do ii = 1, 120
695  cmelem( ii, nmtbb ) = tags(3)(ii:ii)
696  enddo
697  endif
698  endif
699 
700  return
701 end subroutine sntbbe
702 
723 subroutine sntbde ( lunt, ifxyn, line, mxmtbd, mxelem, nmtbd, imfxyn, cmmnem, cmdsc, cmseq, nmelem, iefxyn, ceelem )
724 
725  implicit none
726 
727  integer, intent(in) :: lunt, ifxyn, mxmtbd, mxelem
728  integer, intent(out) :: nmtbd, imfxyn(*), nmelem(*), iefxyn(mxmtbd,mxelem)
729  integer ii, ipt, ntag, nelem, nemock, ifxy, igetfxy, igetntbl
730 
731  character*(*), intent(in) :: line
732  character*(*), parameter :: bort_str1_head = 'BUFRLIB: SNTBDE - TABLE D ENTRY FOR SEQUENCE DESCRIPTOR: '
733  character, intent(out) :: cmseq(120,*), cmmnem(8,*), cmdsc(*)*4, ceelem(mxmtbd,mxelem)*120
734  character*200 tags(10), cline
735  character*128 bort_str1, bort_str2
736  character*6 adsc
737 
738  logical done
739 
740  if ( nmtbd >= mxmtbd ) call bort('BUFRLIB: SNTBDE - OVERFLOW OF MERGED ARRAYS')
741  nmtbd = nmtbd + 1
742 
743  ! Store the FXY number. This is the sequence descriptor.
744 
745  imfxyn( nmtbd ) = ifxyn
746 
747  ! Is there any other information within the first line of the table entry? If so, it follows a "|" separator.
748 
749  do ii = 1, 8
750  cmmnem( ii, nmtbd ) = ' '
751  enddo
752  cmdsc( nmtbd ) = ' '
753  do ii = 1, 120
754  cmseq( ii, nmtbd ) = ' '
755  enddo
756  ipt = index( line, '|' )
757  if ( ipt /= 0 ) then
758  ! Parse the rest of the line. Any of the fields may be blank.
759  call parstr ( line(ipt+1:), tags, 10, ntag, ';', .false. )
760  if ( ntag > 0 ) then
761  ! The first additional field contains the mnemonic.
762  tags(1) = adjustl( tags(1) )
763  ! If there is a mnemonic, then make sure it's legal.
764  if ( ( tags(1) /= ' ' ) .and. ( nemock( tags(1) ) /= 0 ) ) then
765  call sntbestr(bort_str1_head, ifxyn, bort_str1)
766  bort_str2 = ' HAS ILLEGAL MNEMONIC'
767  call bort2(bort_str1, bort_str2)
768  endif
769  do ii = 1, 8
770  cmmnem( ii, nmtbd ) = tags(1)(ii:ii)
771  enddo
772  endif
773  if ( ntag > 1 ) then
774  ! The second additional field contains descriptor codes.
775  tags(2) = adjustl( tags(2) )
776  cmdsc( nmtbd ) = tags(2)(1:4)
777  endif
778  if ( ntag > 2 ) then
779  ! The third additional field contains the sequence name.
780  tags(3) = adjustl( tags(3) )
781  do ii = 1, 120
782  cmseq( ii, nmtbd ) = tags(3)(ii:ii)
783  enddO
784  endif
785  endif
786 
787  ! Now, read and parse all remaining lines from this table entry. Each line should contain an element descriptor for
788  ! the sequence represented by the current sequence descriptor.
789 
790  nelem = 0
791  done = .false.
792  do while ( .not. done )
793  if ( igetntbl( lunt, cline ) /= 0 ) then
794  call sntbestr(bort_str1_head, ifxyn, bort_str1)
795  bort_str2 = ' IS INCOMPLETE'
796  call bort2(bort_str1, bort_str2)
797  endif
798  call parstr ( cline, tags, 10, ntag, '|', .false. )
799  if ( ntag < 2 ) then
800  call sntbestr(bort_str1_head, ifxyn, bort_str1)
801  bort_str2 = ' HAS BAD ELEMENT CARD'
802  call bort2(bort_str1, bort_str2)
803  endif
804  ! The second field contains the FXY number for this element.
805  if ( igetfxy( tags(2), adsc ) /= 0 ) then
806  call sntbestr(bort_str1_head, ifxyn, bort_str1)
807  bort_str2 = ' HAS BAD OR MISSING ELEMENT FXY NUMBER'
808  call bort2(bort_str1, bort_str2)
809  endif
810  if ( nelem >= mxelem ) CALL bort('BUFRLIB: SNTBDE - OVERFLOW OF MERGED ARRAYS')
811  nelem = nelem + 1
812  iefxyn( nmtbd, nelem ) = ifxy( adsc )
813  ! The third field (if it exists) contains the element name.
814  if ( ntag > 2 ) then
815  tags(3) = adjustl( tags(3) )
816  ceelem( nmtbd, nelem ) = tags(3)(1:120)
817  else
818  ceelem( nmtbd, nelem ) = ' '
819  endif
820  ! Is this the last line for this table entry?
821  if ( index( tags(2), ' >' ) == 0 ) done = .true.
822  enddo
823  nmelem( nmtbd ) = nelem
824 
825  return
826 end subroutine sntbde
827 
835 subroutine sntbfe ( lunt, ifxyn )
836 
837  use bufrlib
838 
839  implicit none
840 
841  integer, intent(in) :: lunt, ifxyn
842  integer idfxy(10), idval(25), nidfxy, nidval, ntag, ii, jj, ival, ier, ipt, lt3, ifxy, igetfxy, igetntbl
843 
844  character*160 cline, tags(4), cdstr(2), adsc(10), cval(25)
845  character*(*), parameter :: bort_str1_head = 'BUFRLIB: SNTBFE - TABLE F ENTRY FOR ELEMENT DESCRIPTOR: '
846  character*128 bort_str1, bort_str2
847  character*6 cdsc
848 
849  logical done, lstnblk
850 
851  ! We already have the FXY number. Now we need to read and parse all of the remaining lines from the table entry for this
852  ! FXY number. The information for each individual code figure or bit number will then be stored as a separate entry within
853  ! the internal memory structure.
854 
855  done = .false.
856  nidfxy = 0
857  nidval = 0
858 
859  do while ( .not. done )
860 
861  if ( igetntbl( lunt, cline ) /= 0 ) then
862  call sntbestr(bort_str1_head, ifxyn, bort_str1)
863  bort_str2 = ' IS INCOMPLETE'
864  call bort2(bort_str1, bort_str2)
865  endif
866 
867  call parstr ( cline, tags, 4, ntag, '|', .false. )
868  if ( ( ntag < 2 ) .or. ( ntag > 3 ) ) then
869  call sntbestr(bort_str1_head, ifxyn, bort_str1)
870  bort_str2 = ' HAS BAD CARD'
871  call bort2(bort_str1, bort_str2)
872  endif
873 
874  if ( ntag == 2 ) then
875 
876  ! This line contains a list of dependencies.
877 
878  call parstr ( tags(2), cdstr, 2, ntag, '=', .false. )
879  if ( ntag /= 2 ) then
880  call sntbestr(bort_str1_head, ifxyn, bort_str1)
881  bort_str2 = ' HAS BAD DEPENDENCY CARD'
882  call bort2(bort_str1, bort_str2)
883  endif
884  ! Parse the list of FXY numbers.
885  call parstr ( cdstr(1), adsc, 10, nidfxy, ',', .false. )
886  if ( ( nidfxy == 0 ) .or. ( ( nidfxy == 1 ) .and. ( adsc(1) == ' ' ) ) ) then
887  call sntbestr(bort_str1_head, ifxyn, bort_str1)
888  bort_str2 = ' HAS BAD DEPENDENCY LIST (FXY)'
889  call bort2(bort_str1, bort_str2)
890  endif
891  do ii = 1, nidfxy
892  if ( igetfxy( adsc(ii), cdsc ) /= 0 ) then
893  call sntbestr(bort_str1_head, ifxyn, bort_str1)
894  bort_str2 = ' HAS BAD DEPENDENCY (FXY)'
895  call bort2(bort_str1, bort_str2)
896  endif
897  idfxy(ii) = ifxy( cdsc )
898  enddo
899  ! Parse the list of values.
900  call parstr ( cdstr(2), cval, 25, nidval, ',', .false. )
901  if ( ( nidval == 0 ) .or. ( ( nidval == 1 ) .and. ( cval(1) == ' ' ) ) ) then
902  call sntbestr(bort_str1_head, ifxyn, bort_str1)
903  bort_str2 = ' HAS BAD DEPENDENCY LIST (VAL)'
904  call bort2(bort_str1, bort_str2)
905  endif
906  do ii = 1, nidval
907  cval(ii) = adjustl( cval(ii) )
908  call strnum ( cval(ii), ival, ier )
909  if ( ier /= 0 ) then
910  call sntbestr(bort_str1_head, ifxyn, bort_str1)
911  bort_str2 = ' HAS BAD DEPENDENCY (VAL)'
912  call bort2(bort_str1, bort_str2)
913  endif
914  idval(ii) = ival
915  enddo
916 
917  else
918 
919  ! This line contains a value (code figure or bit number) and corresponding meaning.
920 
921  ipt = index( tags(2), ' >' )
922  if ( ipt == 0 ) then
923  ! This is the last line for this table entry.
924  done = .true.
925  else
926  tags(2)(ipt+1:ipt+1) = ' '
927  endif
928  tags(2) = adjustl( tags(2) )
929  call strnum ( tags(2), ival, ier )
930  ! Find the last non-blank character in the meaning string.
931  tags(3) = adjustl( tags(3) )
932  lt3 = len(tags(3))
933  lstnblk = .false.
934  do while ( ( lt3 > 0 ) .and. ( .not. lstnblk ) )
935  if ( tags(3)(lt3:lt3) /= ' ' ) then
936  lstnblk = .true.
937  else
938  lt3 = lt3 - 1
939  endif
940  enddo
941  ! Store the information for this value within the internal memory structure.
942  if ( ( nidfxy == 0 ) .and. ( nidval == 0 ) ) then
943  call strtbfe_c ( ifxyn, ival, tags(3), lt3, -1, -1 )
944  else
945  do ii = 1, nidfxy
946  do jj = 1, nidval
947  call strtbfe_c ( ifxyn, ival, tags(3), lt3, idfxy(ii), idval(jj) )
948  enddo
949  enddo
950  endif
951 
952  endif
953 
954  enddo
955 
956  return
957 end subroutine sntbfe
958 
966 subroutine sntbestr ( hestr, ifxyn, estr )
967 
968  implicit none
969 
970  character*(*), intent(in) :: hestr
971  character*(*), intent(out) :: estr
972  character*6 adn30, clemon
973 
974  integer, intent(in) :: ifxyn
975 
976  clemon = adn30( ifxyn, 6 )
977  estr = hestr // clemon(1:1) // '-' // clemon(2:3) // '-' // clemon(4:6)
978 
979  return
980 end subroutine sntbestr
981 
992 integer function igetntbl ( lunt, line ) result ( iret )
993 
994  implicit none
995 
996  integer, intent(in) :: lunt
997  integer ier
998 
999  character*(*), intent(out) :: line
1000 
1001  do while (.true.)
1002  read ( lunt, '(A)', iostat = ier ) line
1003  if ( ( ier /= 0 ) .or. ( line(1:3) == 'END' ) ) then
1004  iret = -1
1005  return
1006  endif
1007  if ( ( line /= ' ' ) .and. ( line(1:1) /= '#' ) ) then
1008  iret = 0
1009  return
1010  endif
1011  enddo
1012 
1013 end function igetntbl
1014 
1027 integer function igettdi ( iflag ) result ( iret )
1028 
1029  implicit none
1030 
1031  integer, intent(in) :: iflag
1032  integer, parameter :: idxmin = 62976 ! = ifxy('354000')
1033  integer, parameter :: idxmax = 63231 ! = ifxy('354255')
1034  integer idx
1035 
1036  save idx
1037 
1038  if ( iflag == 0 ) then
1039  ! Initialize the index to one less than the actual minimum value. That way, the next normal call will return the
1040  ! minimum value.
1041  idx = idxmin - 1
1042  iret = -1
1043  else
1044  idx = idx + 1
1045  if ( idx > idxmax ) call bort('BUFRLIB: IGETTDI - IDXMAX OVERFLOW')
1046  iret = idx
1047  endif
1048 
1049  return
1050 end function igettdi
1051 
1071 subroutine gettbh ( luns, lunl, tab, imt, imtv, iogce, iltv )
1072 
1073  implicit none
1074 
1075  integer, intent(in) :: luns, lunl
1076  integer, intent(out) :: imt, imtv, iogce, iltv
1077  integer ntag, imt2, iersn, igetntbl
1078 
1079  character, intent(in) :: tab
1080 
1081  character*128 bort_str
1082  character*(*), parameter :: bort_str_head = 'BUFRLIB: GETTBH - BAD OR MISSING HEADER WITHIN '
1083  character*40 header
1084  character*30 tags(5), label
1085  character*3 cftyp
1086  character*2 cttyp
1087 
1088  logical badlabel
1089 
1090  ! Statement function to check for bad header line label
1091  badlabel( label ) = ( ( index( label, cttyp ) == 0 ) .or. ( index( label, cftyp ) == 0 ) )
1092 
1093  cttyp = tab // ' '
1094 
1095  ! Read and parse the header line of the standard file.
1096 
1097  cftyp = 'STD'
1098  if ( igetntbl( luns, 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 < 3 ) .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), imt, iersn )
1108  call strnum ( tags(3), imtv, iersn )
1109 
1110  ! Read and parse the header line of the local file.
1111 
1112  cftyp = 'LOC'
1113  if ( igetntbl( lunl, header ) /= 0 ) then
1114  bort_str = bort_str_head // cftyp // ' TABLE ' // tab
1115  call bort(bort_str)
1116  endif
1117  call parstr ( header, tags, 5, ntag, '|', .false. )
1118  if ( ( ntag < 4 ) .or. ( badlabel( tags(1) ) ) ) then
1119  bort_str = bort_str_head // cftyp // ' TABLE ' // tab
1120  call bort(bort_str)
1121  endif
1122  call strnum ( tags(2), imt2, iersn )
1123  call strnum ( tags(3), iogce, iersn )
1124  call strnum ( tags(4), iltv, iersn )
1125 
1126  ! Verify that both files are for the same master table.
1127 
1128  if ( imt /= imt2 ) then
1129  write(bort_str,'("BUFRLIB: GETTBH - MASTER TABLE NUMBER MISMATCH BETWEEN STD AND LOC TABLE ",A)') tab
1130  call bort(bort_str)
1131  endif
1132 
1133  return
1134 end subroutine gettbh
1135 
1147 subroutine getntbe ( lunt, ifxyn, line, iret )
1148 
1149  implicit none
1150 
1151  integer, intent(in) :: lunt
1152  integer, intent(out) :: ifxyn, iret
1153  integer ntag, igetfxy, ifxy, igetntbl
1154 
1155  character*(*), intent(out) :: line
1156  character*128 bort_str1, bort_str2
1157  character*20 tags(4)
1158  character*6 adsc
1159 
1160  ! Get the first line of the next entry in the file.
1161 
1162  iret = igetntbl( lunt, line )
1163  if ( iret == 0 ) then
1164  ! The first field within this line should contain the FXY number.
1165  call parstr ( line(1:20), tags, 4, ntag, '|', .false. )
1166  if ( igetfxy( tags(1), adsc ) /= 0 ) then
1167  bort_str1 = 'BUFRLIB: GETNTBE - CARD BEGINNING WITH: ' // line(1:20)
1168  bort_str2 = ' HAS BAD OR MISSING FXY NUMBER'
1169  call bort2(bort_str1, bort_str2)
1170  endif
1171  ! Store the WMO bit-wise representation of the FXY number.
1172  ifxyn = ifxy( adsc )
1173  endif
1174 
1175  return
1176 end subroutine getntbe
1177 
1208 subroutine codflg(cf)
1209 
1210  use moda_tablef
1211 
1212  implicit none
1213 
1214  character, intent(in) :: cf
1215 
1216  character*128 bort_str
1217 
1218  call capit(cf)
1219  if(cf/='Y'.and. cf/='N') then
1220  write(bort_str,'("BUFRLIB: CODFLG - INPUT ARGUMENT IS ",A1,", IT MUST BE EITHER Y OR N")') cf
1221  call bort(bort_str)
1222  endif
1223  cdmf = cf
1224 
1225  return
1226 end subroutine codflg
1227 
1240 integer function nemock(nemo) result(iret)
1241 
1242  implicit none
1243 
1244  integer i, lnemo
1245 
1246  character*(*), intent(in) :: nemo
1247 
1248  ! Get the length of nemo
1249 
1250  lnemo = 0
1251  do i=len(nemo),1,-1
1252  if(nemo(i:i)/=' ') then
1253  lnemo = i
1254  exit
1255  endif
1256  enddo
1257  if(lnemo<1 .or. lnemo>8) then
1258  iret = -1
1259  return
1260  endif
1261 
1262  ! Scan nemo for allowable characters
1263 
1264  if ( verify(nemo(1:lnemo),'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.') == 0 ) then
1265  iret = 0
1266  else
1267  iret = -2
1268  endif
1269 
1270  return
1271 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:87
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:177
subroutine strsuc(str1, str2, lens)
Remove leading and trailing blanks from a character string.
Definition: misc.F90:220
subroutine capit(str)
Capitalize all of the alphabetic characters in a string.
Definition: misc.F90:355
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:829
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