1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
Design of 3-D table insertion task
----------------------------------
Author: I. Busko
Revision history:
12/16/96 - First version.
01/15/97 - Revised after design review.
01/20/97 - Matches version 1.0 of code.
Revision content:
01/20/97: (i) internal flow control of TICOPY routine; (ii) the two main
data structures now store "regular" column pointers (in the
tbtable sense) instead of column pointers in the tcs_ sense;
(iii) inclusion of a template table.
1. Specifications / requirements:
This task will perform the inverse operation performed by task txtable.
It will insert (in the tainsert task sense) one or more 2-D tables into
rows of a 3-D table. Alternatively, it will create a 3-D table from the
2-D input tables. Each column in the input 2-D table is inserted as an
array into a single cell at the specified row in the output table.
Additional scalar columns, stored in the headers of the input table by
txtable, will also be processed. Row/column selectors in the input table
names will be supported.
This design proposes a first, non-sophisticated version of the task. The
emphasis is on simplicity rather than providing support for all possible
situations. For instance, what to do if the size of a given column in one
of the input tables is larger than the corresponding array size in an
existing output table ? Throw away the extra elements ? Resize output table ?
But what rules to follow in order to fill back the now resized arrays ? This
design will solve problems like these by resorting to the simplest (from the
code viewpoint) solution (in this case, just ignore the extra elements).
If the output table does not exist, the first input table in the list
will define both the column information for the output table, as well as
its maximum array size. Columns in the input and output table will be
matched by column name. If a given column in an input table does not exist
in a previously existing output table, it will be ignored.
From design review: an existing table can be used as a template when creating
a new 3-D output table. If no template is supplied, the first table in the
input list becomes the template.
Because the selector mechanism does not work with scalars stored in the
input tables' headers by task txtable, these scalars, if existent, will
be always inserted in the output table, provided column names match.
An error results when:
- an array is found in a cell in any of the input tables,
- datatypes in input and output columns do not agree.
The task will be named "titable" following a former proposal for naming
the 3-D table utilities.
2. Language:
SPP, to allow the use of the generic datatype compiling facility, and to
reuse significant amounts of code already developed for txtable, tximage
and tainsert.
3. Task parameters:
Name Type What
input file list/template list of 2D table names with optional
row/column bracket selectors.
output file name 3-D table name with no row/column selectors
(modified in place or created from scratch).
template file name 3-D template table with column selectors
row int row in output table where to begin insertion.
4. Data structures:
The main data structures are two pointer-type column descriptor arrays.
One array is associated with the output table, and the other array is
associated with the current input table.
The output table array is sized to store column information from both the
actual columnar data in the input tables, as well as any scalar data
stored in the input table headers by the txtable task. If the output table
already exists, it will define the array size and contents completely.
If it is being created by the task, the first input table in the list will
define the size and content of the output descriptor array. Thus if other
tables in the input list have additional columns (both physical or in the
form of header-stored scalars), these additional columns will be ignored.
5. Code structure:
The listing below shows only the most important subroutines; lower-level
functions such as decoding header keywords are not explicited.
The first section deals with creating the main column descriptor array
for the output table. If the table does not exist, column information
must be read from the input table columns themselves AND from eventual
scalar columns stored in the header by txtable.
The second section scans the input list and performs the actual insertion
operation. Again, a separate piece of code exists for the cases where a
physical column exists in the input table, or an header-stored scalar
instead. The innermost loop takes care of reading only the selected rows
from the input table.
- Read task parameters (clget).
- Alloc work memory (malloc, calloc).
- Strip output name from eventual bracket selectors (rdselect).
- Open input list (imtopen).
- If output table already exists (access).
**> Procedure TIUPDATE:
- Open output table (tbtopn).
- Create array of column pointers from output table (malloc, tcs_open).
- Get column pointers from tcs structure.
**> End TIUPDATE.
- Else
**> Procedure TINEW:
- If template table is not valid:
- Get first table name from input list (imtgetim).
- End if.
- Check if it is a table (whatfile). Exit if not.
- Break name into bracketed selectors (rdselect).
- Open template table (tbtopn).
- Get its total (selected and unselected) number of rows (tbpsta).
- Scalars in input table are signaled by TCTOTAL keyword in input table
header. Look for it (tbhfkr) and increase number of output columns.
- Create array of column pointers from input column selector and TCTOTAL
info (malloc, tcs_open).
- If no columns were matched, and no TCTOTAL keyword was found, exit.
- Open output table (no STDOUT allowed) (tbtopn).
**> Procedure TISETC:
- Loop over input column pointer array, if it exists.
- Copy column information from input to output (tbcinf, tbcdef),
setting the output array size to be the input number of rows
in the case of a 2-D template, or keeping it the same size
in the case of a 3-D template.
- End loop.
- Loop over all possible keyword sets (from 1 to TCTOTAL).
- Look for TCD_xxx keyword (tbhfkr).
- If found:
- Decode TCD keyword into column data (name, datatype, format)
- Create scalar column in output table's column array (tbcdef).
- End if.
- End loop.
**> End TISETC:
- Create output table (tbtcre).
- Close input table (tbtclo).
- Rewind input list (imtrew).
**> End TINEW:
- End if.
- Initialize row counter with "row" parameter value (clgeti). Set flag if row
parameter is negative or INDEF.
**> Procedure TINSERT:
- Loop over input list (imtlen).
- Get table name (imtgetim).
- Check if it is a table (whatfile). Skip and warn user if not.
- Break name into bracketed selectors (rdselect).
- Open input table (tbtopn).
- Look for ORIG_ROW keyword (tbhfkr). If found, and if "row" parameter
is negative or INDEF, supersede row counter with keyword value.
- Find how many rows were requested by row selector (trsopen, trseval,
trsclose).
- Create array of column pointers from column selector (malloc,tcs_open).
**> Procedure TICOPY:
- Loop over output table column pointers.
- Get column info from output table (tbcinf)
- Choose the minimum in between this array size and the number
of rows selected from input table (tbalen).
- If there are matched columns, loop over input table column
pointers.
- Get column info from input table (tcs_column, tbcinf)
- If column names match:
- If data types do not match, abort.
**> Procedure TICC:
- If character-type, get string size.
given by the minimum size computed above (malloc).
**> Procedure TIROWS (generic data type):
- Alloc buffer of appropriate type and with size
- Copy selected rows from input table into buffer
(trsopen, trseval, tbcgt, trsclose).
- Copy buffer into designated row/column (tbapt).
- If output exists and array is larger than buffer:
- Set remaining elements to INDEF.
- End if.
**> End TIROWS.
**> End TICC.
- Else (no match), look for scalar data in input header:
- Look for TCTOTAL keyword (tbhfkr). If found:
- Loop over all possible keyword sets (from 1 to
TCTOTAL).
- Look for TCD_xxx keyword (tbhfkr).
- Decode TCD keyword to extract column name.
- If column name from header matches with output
column name:
**> Procedure TICH (generic datatype):
- Look for TCV_xxx keyword (tbhfkr). If found:
- Read value.
- Write scalar data (tbcpt).
- Else
- Warn user that input table header is
corrupted.
- End if.
**> End TICH.
- End if.
- End loop.
- End if.
- End if (Notice that a no-match case, both from columns and
header scalars, is not an error since the output or
template table may have columns that do not exist
among the selected columns in the input table).
- End loop.
- End loop.
**> End TICOPY.
- Free input table's array of column pointers (tcs_close, mfree).
- Close input table (tbtclo).
- Bump output row counter.
- End loop.
**> End TINSERT:
- Free output table's array of column pointers (tcs_close, mfree).
- Close output table (tbtclo).
- Close input list (imtclose).
- Free work memory (mfree).
|