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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
|
include <tbset.h>
# tdump -- Program to dump a table.
# This differs from tprint in several ways: column names and row numbers
# are not printed, and all columns for a given row are printed (possibly on
# several lines) before moving on to the next row. Also, g format is used
# for floating-point numbers (%15.7g for real, %24.16g for double) regardless
# of the format specification for the column. This is to prevent loss of
# precision.
#
# Phil Hodge, 31-Jul-1987 Task created
# Phil Hodge, 11-Aug-1987 Modify d_gt_col_ptr for datatype=-n for char string.
# Phil Hodge, 30-Dec-1987 Use tctexp for column names.
# Phil Hodge, 7-Sep-1988 Change parameter name for table.
# Phil Hodge, 21-Dec-1988 Also print column descrip; use g format for data.
# Phil Hodge, 9-Mar-1989 Change type of dtype in tbhgnp from char to int.
# Phil Hodge, 9-Jul-1991 Rename parameter pagwidth to pwidth.
# Phil Hodge, 2-Apr-1993 Include short datatype in td_col_def.
# Phil Hodge, 2-Jun-1994 In td_col_ptr, include newline in warning message.
# Phil Hodge, 12-Dec-1994 Include array size in column definitions;
# increase SZ_DTYPE from 9 to 29;
# dump all elements if column is an array.
# Phil Hodge, 15-Dec-1994 Increase size of file names from SZ_FNAME to SZ_LINE.
# Phil Hodge, 13-Jan-1995 Change calling sequence of inquotes.
# Phil Hodge, 19-Jul-1995 Add tp to calling sequence of tl_dtype in td_col_def.
# Phil Hodge, 4-Apr-1996 In td_p_data, start each array at beginning of line;
# change formats for real & double to %13.7g, %22.16g.
# Phil Hodge, 5-Jun-1997 If keywords are to be printed, also print comments.
# Phil Hodge, 20-Jul-1998 Print '' instead of blank for null keywords.
# Phil Hodge, 22-Jul-1998 Left justify strings and boolean elements.
# Phil Hodge, 2-Nov-2000 Use pwidth < 1 to disable the test on page width.
# Phil Hodge, 15-May-2002 Use a specific format for int and short columns;
# this was needed because for x or o format the printed
# values could be misleading.
define SZ_FMT 16 # size of string containing print format
define FMT_REAL "%13.7g" # format for printing a real
define SPACE_REAL 13 # space required for printing a real
define FMT_DBL "%22.16g" # format for printing a double
define SPACE_DBL 22 # space required for printing a double
define FMT_INT "%11d" # format for printing an int
define SPACE_INT 11 # space required for printing an int
define FMT_SHORT "%5d" # format for printing a short
define SPACE_SHORT 5 # space required for printing a short
define MAX_RANGES (SZ_LINE/2) # max number of ranges of row numbers
define SZ_DTYPE 29 # size of string containing column data type
define SZ_LBUF 2 * SZ_LINE + 1
procedure tdump()
#--
pointer tp # pointer to input table descr
pointer cptr # scratch for array of column pointers
pointer tname # scratch for table name
pointer cname, pname, dname # scratch for names of output files
pointer upar # scratch for header keyword value
pointer comment # scratch for header keyword comment
pointer datatype # scr for array of data types of columns
pointer nelem # scr for array of array lengths of columns
pointer len_fmt # scr for array of lengths of print formats
pointer pformat # scratch for array of print formats
pointer columns # list of columns to be dumped
pointer r_str # string which gives ranges of row numbers
char keyword[SZ_KEYWORD] # buffer for user parameter keyword
char char_type # data type as a letter (t, b, i, r, d)
pointer sp # stack pointer
int fd # file descr for output user param, data
int n # loop index for user parameters
int dtype # data type (TY_CHAR, etc)
int npar # number of user parameters
int nrows, ncols # number of rows and columns in table
int nprint # number of columns to print (may be < ncols)
int pagewidth # page width
bool prcoldef # print column definitions?
bool prparam, prdata # print user parameters? data?
pointer tbtopn()
int open(), clgeti(), tbpsta()
begin
call smark (sp)
call salloc (tname, SZ_LINE, TY_CHAR)
call salloc (cname, SZ_LINE, TY_CHAR)
call salloc (pname, SZ_LINE, TY_CHAR)
call salloc (dname, SZ_LINE, TY_CHAR)
call clgstr ("table", Memc[tname], SZ_LINE)
# Get the names of the output files. If a name is null, don't
# write the corresponding portion of the table.
call clgstr ("cdfile", Memc[cname], SZ_LINE)
call clgstr ("pfile", Memc[pname], SZ_LINE)
call clgstr ("datafile", Memc[dname], SZ_LINE)
prcoldef = (Memc[cname] != EOS)
prparam = (Memc[pname] != EOS)
prdata = (Memc[dname] != EOS)
if (!prcoldef && !prparam && !prdata) {
call sfree (sp) # nothing to do
return
}
tp = tbtopn (Memc[tname], READ_ONLY, 0)
if (prcoldef || prdata) {
# If we are to print column definitions and/or data,
# allocate memory and get list of columns.
call salloc (columns, SZ_LINE, TY_CHAR)
call clgstr ("columns", Memc[columns], SZ_LINE)
ncols = tbpsta (tp, TBL_NCOLS)
# Allocate enough scratch space for printing all columns.
call salloc (cptr, ncols, TY_POINTER)
call salloc (len_fmt, ncols, TY_INT)
call salloc (datatype, ncols, TY_INT)
call salloc (nelem, ncols, TY_INT)
}
if (prcoldef) {
# Open the output file for the column definitions.
fd = open (Memc[cname], NEW_FILE, TEXT_FILE)
# Print column definitions.
call td_col_def (tp, fd, Memc[columns], Memi[cptr])
call close (fd) # column definitions have been written
}
if (prparam) {
# Print header parameters.
npar = tbpsta (tp, TBL_NPAR)
if (npar > 0) {
fd = open (Memc[pname], NEW_FILE, TEXT_FILE)
call salloc (upar, SZ_PARREC, TY_CHAR)
call salloc (comment, SZ_PARREC, TY_CHAR)
do n = 1, npar {
# Get the Nth user parameter, and print it.
call tbhgnp (tp, n, keyword, dtype, Memc[upar])
call tbhgcm (tp, keyword, Memc[comment], SZ_PARREC)
switch (dtype) {
case TY_REAL:
char_type = 'r'
case TY_INT:
char_type = 'i'
case TY_DOUBLE:
char_type = 'd'
case TY_BOOL:
char_type = 'b'
default:
char_type = 't'
}
if (keyword[1] == EOS) {
call fprintf (fd, "'' ")
} else {
call fprintf (fd, "%-8s")
call pargstr (keyword)
}
call fprintf (fd, " %c")
call pargc (char_type)
if (Memc[comment] == EOS) {
call fprintf (fd, " %s\n")
call pargstr (Memc[upar])
} else { # also print comment
if (char_type == 't') {
call fprintf (fd, " '%s'") # enclose text in quotes
call pargstr (Memc[upar])
} else {
call fprintf (fd, " %s") # no quotes needed
call pargstr (Memc[upar])
}
call fprintf (fd, " %s\n")
call pargstr (Memc[comment])
}
}
call close (fd) # header parameters have been written
}
}
if (prdata) {
# Print data portion of table.
nrows = tbpsta (tp, TBL_NROWS)
if ((nrows < 1) || (ncols < 1)) {
call eprintf ("table is empty\n")
call tbtclo (tp)
call sfree (sp)
return # nothing more to do
}
# Open the output file for the table data.
fd = open (Memc[dname], NEW_FILE, TEXT_FILE)
call salloc (r_str, SZ_LINE, TY_CHAR)
call clgstr ("rows", Memc[r_str], SZ_LINE)
pagewidth = clgeti ("pwidth")
if (IS_INDEF(pagewidth))
pagewidth = -1 # no limit on page width
# Get column pointers, formats, etc for all columns that are
# to be printed.
call td_col_ptr (tp, Memc[columns], pagewidth, Memi[cptr],
Memi[len_fmt], Memi[datatype], Memi[nelem], nprint)
if (nprint > 0) {
# Allocate scratch space for print format. (one char for EOS)
call salloc (pformat, (SZ_FMT+1)*nprint, TY_CHAR)
# Print the values in the table.
call td_p_data (tp, fd, Memi[cptr], Memc[r_str],
Memi[len_fmt], Memi[datatype], Memi[nelem],
Memc[pformat], pagewidth, nprint)
}
call close (fd) # data values have been printed
}
call tbtclo (tp)
call sfree (sp)
end
# td_col_def -- print column definitions
# This routine prints the column name, data type, print format, and units
# for all columns that were specified by the user.
procedure td_col_def (tp, fd, columns, cptr)
pointer tp # i: pointer to table descriptor
int fd # i: fd for output file
char columns[ARB] # i: list of columns to be dumped
pointer cptr[ARB] # o: array of pointers to column descriptors
#--
pointer sp
pointer cname, cunits, cfmt # pointers to scratch space for column info
char chartyp[SZ_DTYPE] # data type expressed as a string
int ncols # the total number of columns in the table
int nprint # number of columns to print
int dtype # data type of a column
int nelem # array length
int lenformat # (ignored)
int colnum # column number (ignored)
int k # loop index
int tbpsta()
begin
call smark (sp)
call salloc (cname, SZ_FNAME, TY_CHAR)
call salloc (cunits, SZ_FNAME, TY_CHAR)
call salloc (cfmt, SZ_COLFMT, TY_CHAR)
ncols = tbpsta (tp, TBL_NCOLS)
# Get column pointers for all columns that are to be dumped.
call tctexp (tp, columns, ncols, nprint, cptr)
# Do for each column that is to be printed.
do k = 1, nprint {
call tbcinf (cptr[k],
colnum, Memc[cname], Memc[cunits], Memc[cfmt],
dtype, nelem, lenformat)
# Enclose column name in quotes if it contains embedded
# or trailing blanks.
call inquotes (Memc[cname], Memc[cname], SZ_FNAME, YES)
call fprintf (fd, "%-16s") # but name can be longer
call pargstr (Memc[cname])
# Print data type. First convert integer data type code to a
# character string, and append info about array size if > 1.
call tl_dtype (tp, cptr[k], dtype, nelem, chartyp, SZ_DTYPE)
call fprintf (fd, " %-8s")
call pargstr (chartyp)
# Print the format for display.
call fprintf (fd, " %8s")
call pargstr (Memc[cfmt])
# Print column units. Ignore trailing blanks.
call inquotes (Memc[cunits], Memc[cunits], SZ_FNAME, NO)
call fprintf (fd, " %s")
call pargstr (Memc[cunits])
call fprintf (fd, "\n") # end of line for each column
}
call sfree (sp)
end
# td_col_ptr -- get column pointers
# This routine gets an array of pointers to the descriptors of those
# columns that are to be printed, plus other info.
procedure td_col_ptr (tp, columns, pagewidth,
cptr, len_fmt, datatype, nelem, nprint)
pointer tp # i: pointer to table descriptor
char columns[ARB] # i: list of columns to be dumped
int pagewidth # i: page width (to make sure it's wide enough)
pointer cptr[ARB] # o: array of pointers to column descriptors
int len_fmt[ARB] # o: length of print format for each column
int datatype[ARB] # o: data type for each column
int nelem[ARB] # o: array length of each column
int nprint # o: number of columns to print
#--
char colname[SZ_COLNAME] # column name for possible error message
int ncols # total number of columns in the table
int k # loop index
int tbpsta(), tbcigi()
begin
ncols = tbpsta (tp, TBL_NCOLS)
# Get column pointers for all columns that are to be dumped.
call tctexp (tp, columns, ncols, nprint, cptr)
# For each column that is to be printed, get the length of the print
# format, and if the column type is string then increase the length
# of the print format by two for possible enclosing quotes.
do k = 1, nprint {
datatype[k] = tbcigi (cptr[k], TBL_COL_DATATYPE)
nelem[k] = tbcigi (cptr[k], TBL_COL_LENDATA)
if (datatype[k] == TY_REAL)
len_fmt[k] = SPACE_REAL
else if (datatype[k] == TY_DOUBLE)
len_fmt[k] = SPACE_DBL
else if (datatype[k] == TY_INT)
len_fmt[k] = SPACE_INT
else if (datatype[k] == TY_SHORT)
len_fmt[k] = SPACE_SHORT
else
len_fmt[k] = tbcigi (cptr[k], TBL_COL_FMTLEN)
if (datatype[k] < 0) # char string column
len_fmt[k] = len_fmt[k] + 2
if (pagewidth > 0 && len_fmt[k] > pagewidth) {
call tbcigt (cptr[k], TBL_COL_NAME, colname, SZ_COLNAME)
call eprintf ("Page width is too small for column `%s'.\n")
call pargstr (colname)
}
}
end
# td_p_data -- print the contents of the table
# The data in the table are printed one row at a time.
procedure td_p_data (tp, fd, cptr, range_string,
len_fmt, datatype, nelem,
pformat, pagewidth, nprint)
pointer tp # i: pointer to table descriptor
int fd # i: fd for output file
pointer cptr[nprint] # i: array of pointers to column descriptors
char range_string[ARB] # i: string which gives ranges of row numbers
int datatype[nprint] # i: array of flags: true if column is a string
int nelem[ARB] # i: array length of each column
int len_fmt[nprint] # i: array of lengths of print formats
char pformat[SZ_FMT,nprint] # io: scratch space for print formats
int pagewidth # i: page width
int nprint # i: number of columns to print
#--
pointer sp
pointer lbuf # scratch space for line buffer
double dbuf # buffer for double-precision value
real rbuf # buffer for single-precision value
int ibuf # buffer for integer value
short sbuf # buffer for short value
int nrows # number of rows in the table
int rownum, k # loop indices for row, column
int j # loop index for array element
int line_len # current line length
int ranges[3,MAX_RANGES] # ranges of row numbers
int nvalues # returned by decode_ranges and ignored
int stat # returned by get_next_number
bool done # flag for terminating loop
int decode_ranges(), get_next_number()
int tbpsta(), tbagtr(), tbagtd(), tbagti(), tbagts(), tbagtt()
string MISSING "error reading data from table"
begin
nrows = tbpsta (tp, TBL_NROWS)
if (decode_ranges (range_string, ranges, MAX_RANGES, nvalues) != 0) {
call eprintf ("bad range of row numbers\n")
return
}
call smark (sp)
call salloc (lbuf, SZ_LBUF, TY_CHAR)
# This section gets the print format for each column. The
# format is just "%Ns" or "%-Ns".
do k = 1, nprint {
pformat[1,k] = '%'
if (datatype[k] < 0 || datatype[k] == TY_BOOL) {
call sprintf (pformat[2,k], SZ_FMT-1, "-%ds") # left justify
call pargi (len_fmt[k])
} else {
call sprintf (pformat[2,k], SZ_FMT-1, "%ds")
call pargi (len_fmt[k])
}
}
# This section prints the data.
rownum = 0 # initialize get_next_number
line_len = 0
done = false
while ( !done ) {
stat = get_next_number (ranges, rownum)
if ((stat == EOF) || (rownum > nrows)) {
done = true
} else {
# Print values in current row. The loop on k is for each
# column that is to be printed.
do k = 1, nprint {
# If the current column contains arrays, print each
# element, and start at the beginning of the line.
if (nelem[k] > 1 && line_len > 0) {
call fprintf (fd, "\n")
line_len = 0 # reset after newline
}
do j = 1, nelem[k] {
# If we have previously printed something on the
# current line, print either a space or newline,
# depending on how close we are to the end of the line.
if (line_len > 1) {
if (pagewidth > 0 &&
line_len + len_fmt[k] >= pagewidth) {
# need to start a new line
call fprintf (fd, "\n")
line_len = 0
} else {
# continue on current line
call fprintf (fd, " ")
line_len = line_len + 1
}
}
if (datatype[k] == TY_REAL) {
if (tbagtr (tp, cptr[k], rownum, rbuf, j, 1) < 1)
call error (1, MISSING)
call sprintf (Memc[lbuf], SZ_LBUF, FMT_REAL)
call pargr (rbuf)
} else if (datatype[k] == TY_DOUBLE) {
if (tbagtd (tp, cptr[k], rownum, dbuf, j, 1) < 1)
call error (1, MISSING)
call sprintf (Memc[lbuf], SZ_LBUF, FMT_DBL)
call pargd (dbuf)
} else if (datatype[k] == TY_INT) {
if (tbagti (tp, cptr[k], rownum, ibuf, j, 1) < 1)
call error (1, MISSING)
call sprintf (Memc[lbuf], SZ_LBUF, FMT_INT)
call pargi (ibuf)
} else if (datatype[k] == TY_SHORT) {
if (tbagts (tp, cptr[k], rownum, sbuf, j, 1) < 1)
call error (1, MISSING)
call sprintf (Memc[lbuf], SZ_LBUF, FMT_SHORT)
call pargs (sbuf)
} else {
if (tbagtt (tp, cptr[k], rownum,
Memc[lbuf], SZ_LBUF, j, 1) < 1)
call error (1, MISSING)
}
# If the value is a string, enclose in quotes if
# there are embedded blanks (ignore trailing blanks).
if (datatype[k] < 0)
call inquotes (Memc[lbuf], Memc[lbuf], SZ_LINE, NO)
call fprintf (fd, pformat[1,k])
call pargstr (Memc[lbuf])
# Add width of current column.
line_len = line_len + len_fmt[k]
}
}
call fprintf (fd, "\n") # end of current row
line_len = 0
}
}
call sfree (sp)
end
|