aboutsummaryrefslogtreecommitdiff
path: root/pkg/utilities/nttools/tprint/tdump.x
blob: 54658d58e063e31a2eb9e9ec6b016f119c9c6155 (plain) (blame)
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