NCEPLIBS-bufr  12.0.1
makestab.f
Go to the documentation of this file.
1 C> @file
2 C> @brief Build the internal jump/link table.
3 C>
4 C> @author J. Woollen @date 1994-01-06
5 
6 C> This subroutine constructs the internal jump/link table within
7 C> module tables, using all of the internal BUFR table array information
8 C> from module @ref moda_tababd for all of the internal I/O streams that are
9 C> currently defined to the library in module @ref moda_stbfr.
10 C>
11 C> The entire jump/link table will always be completely reconstructed
12 C> from scratch, even if some of the information within the internal
13 C> BUFR table arrays already existed there at the time of the previous
14 C> call to this subroutine, because there may have been other events
15 C> that have taken place since the previous call to this subroutine and
16 C> which haven't yet been reflected within the internal jump/link table.
17 C> For example, an I/O stream may have recently been unlinked from the
18 C> library via an internal call to subroutine closbf(), or the DX BUFR
19 C> tables associated with an I/O stream may have changed.
20 C>
21 C> @author J. Woollen @date 1994-01-06
22 
23  SUBROUTINE makestab
24 
25  USE modv_bmiss
26  USE modv_maxjl
27  USE modv_nfiles
28 
29  USE moda_usrint
30  USE moda_stbfr
31  USE moda_lushr
32  USE moda_xtab
33  USE moda_tababd
34  USE moda_tables
35  USE moda_nrv203
36  USE moda_bitmaps
37 
38  COMMON /quiet/ iprt
39 
40  CHARACTER*128 BORT_STR,ERRSTR
41  CHARACTER*8 NEMO
42  LOGICAL EXPAND
43 
44 C-----------------------------------------------------------------------
45 C-----------------------------------------------------------------------
46 
47 C RESET POINTER TABLE AND STRING CACHE
48 C ------------------------------------
49 
50  ntab = 0
51  nnrv = 0
52  ntamc = 0
53  CALL strcln
54 
55 C FIGURE OUT WHICH UNITS SHARE TABLES
56 C -----------------------------------
57 
58 C The LUS array is static between calls to this subroutine, and it
59 C keeps track of which logical units share dictionary table
60 C information:
61 C if LUS(I) = 0, then IOLUN(I) does not share dictionary table
62 C information with any other logical unit
63 C if LUS(I) > 0, then IOLUN(I) shares dictionary table
64 C information with logical unit IOLUN(LUS(I))
65 C if LUS(I) < 0, then IOLUN(I) does not now, but at one point in
66 C the past, shared dictionary table information
67 C with logical unit IOLUN(ABS(LUS(I)))
68 
69 C The XTAB array is non-static and is recomputed within the below
70 C loop during each call to this subroutine:
71 C if XTAB(I) = .TRUE., then the dictionary table information
72 C has changed for IOLUN(I) since the last
73 C call to this subroutine
74 C if XTAB(I) = .FALSE., then the dictionary table information
75 C has not changed for IOLUN(I) since the
76 C last call to this subroutine
77 
78  DO lun=1,nfiles
79  xtab(lun) = .false.
80  IF(iolun(lun).EQ.0) THEN
81 
82 C Logical unit IOLUN(LUN) is not defined to the BUFRLIB.
83 
84  lus(lun) = 0
85  ELSE IF(mtab(1,lun).EQ.0) THEN
86 
87 C New dictionary table information has been read for logical
88 C unit IOLUN(LUN) since the last call to this subroutine.
89 
90  xtab(lun) = .true.
91  IF(lus(lun).NE.0) THEN
92  IF(iolun(abs(lus(lun))).EQ.0) THEN
93  lus(lun) = 0
94  ELSE IF(lus(lun).GT.0) THEN
95 
96 C IOLUN(LUN) was sharing table information with logical
97 C unit IOLUN(LUS(LUN)), so check whether the table
98 C information has really changed. If not, then IOLUN(LUN)
99 C just re-read a copy of the exact same table information
100 C as before, and therefore it can continue to share with
101 C logical unit IOLUN(LUS(LUN)).
102 
103  IF(icmpdx(lus(lun),lun).EQ.1) THEN
104  xtab(lun) = .false.
105  CALL cpbfdx(lus(lun),lun)
106  ELSE
107  lus(lun) = (-1)*lus(lun)
108  ENDIF
109  ELSE IF(icmpdx(abs(lus(lun)),lun).EQ.1) THEN
110 
111 C IOLUN(LUN) was not sharing table information with logical
112 C unit IOLUN(LUS(LUN)), but it did at one point in the past
113 C and now once again has the same table information as that
114 C logical unit. Since the two units shared table
115 C information at one point in the past, allow them to do
116 C so again.
117 
118  xtab(lun) = .false.
119  lus(lun) = abs(lus(lun))
120  CALL cpbfdx(lus(lun),lun)
121  ENDIF
122  ENDIF
123  ELSE IF(lus(lun).GT.0) THEN
124 
125 C Logical unit IOLUN(LUN) is sharing table information with
126 C logical unit IOLUN(LUS(LUN)), so make sure that the latter
127 C unit is still defined to the BUFRLIB.
128 
129  IF(iolun(lus(lun)).EQ.0) THEN
130  lus(lun) = 0
131  ELSE IF( xtab(lus(lun)) .AND.
132  + (icmpdx(lus(lun),lun).EQ.0) ) THEN
133 
134 C The table information for logical unit IOLUN(LUS(LUN))
135 C just changed (in midstream). If IOLUN(LUN) is an output
136 C file, then we will have to update it with the new table
137 C information later on in this subroutine. Otherwise,
138 C IOLUN(LUN) is an input file and is no longer sharing
139 C tables with IOLUN(LUS(LUN)).
140 
141  IF(iolun(lun).LT.0) lus(lun) = (-1)*lus(lun)
142  ENDIF
143  ELSE
144 
145 C Determine whether logical unit IOLUN(LUN) is sharing table
146 C information with any other logical units.
147 
148  lum = 1
149  DO WHILE ((lum.LT.lun).AND.(lus(lun).EQ.0))
150  IF(ishrdx(lum,lun).EQ.1) THEN
151  lus(lun) = lum
152  ELSE
153  lum = lum+1
154  ENDIF
155  ENDDO
156  ENDIF
157  ENDDO
158 
159 C INITIALIZE JUMP/LINK TABLES WITH SUBSETS/SEQUENCES/ELEMENTS
160 C -----------------------------------------------------------
161 
162  DO lun=1,nfiles
163 
164  IF(iolun(lun).NE.0 .AND. ntba(lun).GT.0) THEN
165 
166 C Reset any existing inventory pointers.
167 
168  IF(iomsg(lun).NE.0) THEN
169  IF(lus(lun).LE.0) THEN
170  inc = (ntab+1)-mtab(1,lun)
171  ELSE
172  inc = mtab(1,lus(lun))-mtab(1,lun)
173  ENDIF
174  DO n=1,nval(lun)
175  inv(n,lun) = inv(n,lun)+inc
176  ENDDO
177  ENDIF
178 
179  IF(lus(lun).LE.0) THEN
180 
181 C The dictionary table information corresponding to logical
182 C unit IOLUN(LUN) has not yet been written into the internal
183 C jump/link table, so add it in now.
184 
185  CALL chekstab(lun)
186  DO itba=1,ntba(lun)
187  inod = ntab+1
188  nemo = taba(itba,lun)(4:11)
189  CALL tabsub(lun,nemo)
190  mtab(itba,lun) = inod
191  isc(inod) = ntab
192  ENDDO
193  ELSE IF( xtab(lus(lun)) .AND.
194  + (icmpdx(lus(lun),lun).EQ.0) ) THEN
195 
196 C Logical unit IOLUN(LUN) is an output file that is sharing
197 C table information with logical unit IOLUN(LUS(LUN)) whose
198 C table just changed (in midstream). Flush any existing data
199 C messages from IOLUN(LUN), then update the table information
200 C for this logical unit with the corresponding new table
201 C information from IOLUN(LUS(LUN)), then update IOLUN(LUN)
202 C itself with a copy of the new table information.
203 
204  lunit = abs(iolun(lun))
205  IF(iomsg(lun).NE.0) CALL closmg(lunit)
206  CALL cpbfdx(lus(lun),lun)
207  lundx = abs(iolun(lus(lun)))
208  CALL wrdxtb(lundx,lunit)
209  ENDIF
210 
211  ENDIF
212 
213  ENDDO
214 
215 C STORE TYPES AND INITIAL VALUES AND COUNTS
216 C -----------------------------------------
217 
218  DO node=1,ntab
219  IF(typ(node).EQ.'SUB') THEN
220  vali(node) = 0
221  knti(node) = 1
222  itp(node) = 0
223  ELSEIF(typ(node).EQ.'SEQ') THEN
224  vali(node) = 0
225  knti(node) = 1
226  itp(node) = 0
227  ELSEIF(typ(node).EQ.'RPC') THEN
228  vali(node) = 0
229  knti(node) = 0
230  itp(node) = 0
231  ELSEIF(typ(node).EQ.'RPS') THEN
232  vali(node) = 0
233  knti(node) = 0
234  itp(node) = 0
235  ELSEIF(typ(node).EQ.'REP') THEN
236  vali(node) = bmiss
237  knti(node) = irf(node)
238  itp(node) = 0
239  ELSEIF(typ(node).EQ.'DRS') THEN
240  vali(node) = 0
241  knti(node) = 1
242  itp(node) = 1
243  ELSEIF(typ(node).EQ.'DRP') THEN
244  vali(node) = 0
245  knti(node) = 1
246  itp(node) = 1
247  ELSEIF(typ(node).EQ.'DRB') THEN
248  vali(node) = 0
249  knti(node) = 0
250  itp(node) = 1
251  ELSEIF(typ(node).EQ.'NUM') THEN
252  vali(node) = bmiss
253  knti(node) = 1
254  itp(node) = 2
255  ELSEIF(typ(node).EQ.'CHR') THEN
256  vali(node) = bmiss
257  knti(node) = 1
258  itp(node) = 3
259  ELSE
260  GOTO 901
261  ENDIF
262  ENDDO
263 
264 C SET UP EXPANSION SEGMENTS FOR TYPE 'SUB', 'DRP', AND 'DRS' NODES
265 C ----------------------------------------------------------------
266 
267  newn = 0
268 
269  DO n=1,ntab
270  iseq(n,1) = 0
271  iseq(n,2) = 0
272  expand = typ(n).EQ.'SUB' .OR. typ(n).EQ.'DRP' .OR. typ(n).EQ.'DRS'
273  . .OR. typ(n).EQ.'REP' .OR. typ(n).EQ.'DRB'
274  IF(expand) THEN
275  iseq(n,1) = newn+1
276  noda = n
277  node = n+1
278  DO k=1,maxjl
279  knt(k) = 0
280  ENDDO
281  IF(typ(noda).EQ.'REP') knt(node) = knti(noda)
282  IF(typ(noda).NE.'REP') knt(node) = 1
283 
284 1 newn = newn+1
285  IF(newn.GT.maxjl) GOTO 902
286  jseq(newn) = node
287  knt(node) = max(knti(node),knt(node))
288 2 IF(jump(node)*knt(node).GT.0) THEN
289  node = jump(node)
290  GOTO 1
291  ELSE IF(link(node).GT.0) THEN
292  node = link(node)
293  GOTO 1
294  ELSE
295  node = jmpb(node)
296  IF(node.EQ.noda) GOTO 3
297  IF(node.EQ.0 ) GOTO 903
298  knt(node) = max(knt(node)-1,0)
299  GOTO 2
300  ENDIF
301 3 iseq(n,2) = newn
302  ENDIF
303  ENDDO
304 
305 C PRINT THE SEQUENCE TABLES
306 C ------------------------
307 
308  IF(iprt.GE.2) THEN
309  CALL errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
310  DO i=1,ntab
311  WRITE ( unit=errstr, fmt='(A,I5,2X,A10,A5,6I8)' )
312  . 'BUFRLIB: MAKESTAB ', i, tag(i), typ(i), jmpb(i), jump(i),
313  . link(i), ibt(i), irf(i), isc(i)
314  CALL errwrt(errstr)
315  ENDDO
316  CALL errwrt('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
317  CALL errwrt(' ')
318  ENDIF
319 
320 C EXITS
321 C -----
322 
323  RETURN
324 901 WRITE(bort_str,'("BUFRLIB: MAKESTAB - UNKNOWN TYPE ",A)')typ(node)
325  CALL bort(bort_str)
326 902 WRITE(bort_str,'("BUFRLIB: MAKESTAB - NUMBER OF JSEQ ENTRIES IN'//
327  . ' JUMP/LINK TABLE EXCEEDS THE LIMIT (",I6,")")') maxjl
328  CALL bort(bort_str)
329 903 WRITE(bort_str,'("BUFRLIB: MAKESTAB - NODE IS ZERO, FAILED TO '//
330  . 'CIRCULATE (TAG IS ",A,")")') tag(n)
331  CALL bort(bort_str)
332  END
subroutine bort(STR)
Log one error message and abort application program.
Definition: bort.f:18
subroutine chekstab(LUN)
This subroutine checks that an internal BUFR table representation is self-consistent and fully define...
Definition: chekstab.f:16
recursive subroutine closmg(LUNIN)
This subroutine closes the BUFR message that is currently open for writing within internal arrays ass...
Definition: closmg.f:26
subroutine cpbfdx(LUD, LUN)
This subroutine copies all of the DX BUFR table information from one unit to another within internal ...
Definition: cpbfdx.f:17
subroutine errwrt(STR)
This subroutine allows the user to specify a custom location for the logging of error and diagnostic ...
Definition: errwrt.f:36
integer function icmpdx(LUD, LUN)
This function determines whether the full set of associated DX BUFR Table information is identical be...
Definition: icmpdx.f:28
integer function ishrdx(LUD, LUN)
This function determines whether the same DX BUFR Table is being shared between two Fortran logical u...
Definition: ishrdx.f:24
subroutine makestab
This subroutine constructs the internal jump/link table within module tables, using all of the intern...
Definition: makestab.f:24
This module contains array and variable declarations used to store bitmaps internally within a data s...
integer ntamc
Number of Table A mnemonics in jump/link table (up to a maximum of MXTAMC) which contain at least one...
This module contains a declaration for an array used by subroutine makestab() to keep track of which ...
integer, dimension(:), allocatable lus
Tracking index for each I/O internal stream index.
This module contains array and variable declarations for use with any 2-03-YYY (change reference valu...
integer nnrv
Number of entries in the jump/link table which contain new reference values (up to a maximum of MXNRV...
This module contains array declarations used to store file and message status indicators for all logi...
integer, dimension(:), allocatable iolun
File status indicators.
integer, dimension(:), allocatable iomsg
Message status indicator corresponding to iolun, denoting whether a BUFR message is currently open wi...
This module contains array and variable declarations used to store DX BUFR tables internally for mult...
integer, dimension(:), allocatable ntba
Number of Table A entries for each internal I/O stream (up to a maximum of MAXTBA,...
character *128, dimension(:,:), allocatable taba
Table A entries for each internal I/O stream.
integer, dimension(:,:), allocatable mtab
Entries within jump/link table corresponding to taba.
This module contains array and variable declarations used to store the internal jump/link table.
integer, dimension(:), allocatable jseq
Temporary storage used in expanding sequences.
integer, dimension(:), allocatable irf
Reference values corresponding to tag and typ:
integer, dimension(:,:), allocatable iseq
Temporary storage used in expanding sequences.
integer, dimension(:), allocatable isc
Scale factors corresponding to tag and typ:
integer, dimension(:), allocatable ibt
Bit widths corresponding to tag and typ:
integer, dimension(:), allocatable knt
Temporary storage used in calculating delayed replication counts.
real *8, dimension(:), allocatable vali
Initialized data values corresponding to typ:
character *3, dimension(:), allocatable typ
Type indicators corresponding to tag:
integer, dimension(:), allocatable jmpb
Jump backward indices corresponding to tag and typ:
character *10, dimension(:), allocatable tag
Mnemonics in the jump/link table.
integer ntab
Number of entries in the jump/link table.
integer, dimension(:), allocatable jump
Jump forward indices corresponding to tag and typ:
integer, dimension(:), allocatable itp
Integer type values corresponding to typ:
integer, dimension(:), allocatable link
Link indices corresponding to tag, typ and jmpb:
integer, dimension(:), allocatable knti
Initialized replication counts corresponding to typ and jump:
This module contains declarations for arrays used to store data values and associated metadata for th...
integer, dimension(:), allocatable nval
Number of data values in BUFR data subset.
integer, dimension(:,:), allocatable, target inv
Inventory pointer which links each data value to its corresponding node in the internal jump/link tab...
This module contains an array declaration used to track, for each I/O stream index,...
logical, dimension(:), allocatable xtab
Tracking index for each internal I/O stream index.
This module declares and initializes the BMISS variable.
Definition: modules_vars.F90:9
real *8, public bmiss
Current placeholder value to represent "missing" data when reading from or writing to BUFR files; thi...
This module declares and initializes the MAXJL variable.
integer maxjl
Maximum number of entries in the internal jump/link table.
This module declares and initializes the NFILES variable.
integer, public nfiles
Maximum number of BUFR files that can be connected to the BUFRLIB software (for reading or writing) a...
subroutine strcln
This subroutine resets the internal mnemonic string cache.
Definition: strcln.f:13
subroutine tabsub(LUN, NEMO)
This subroutine builds the entire jump/link tree (including recursively resolving all "child" mnemoni...
Definition: tabsub.f:15
recursive subroutine wrdxtb(LUNDX, LUNOT)
This subroutine generates one or more BUFR messages from the DX BUFR tables information associated wi...
Definition: wrdxtb.f:26