aboutsummaryrefslogtreecommitdiff
path: root/pkg/utilities/nttools/tprint
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/utilities/nttools/tprint')
-rw-r--r--pkg/utilities/nttools/tprint/mkpkg15
-rw-r--r--pkg/utilities/nttools/tprint/notes40
-rw-r--r--pkg/utilities/nttools/tprint/tdump.x486
-rw-r--r--pkg/utilities/nttools/tprint/tprhtml.x592
-rw-r--r--pkg/utilities/nttools/tprint/tprint.h5
-rw-r--r--pkg/utilities/nttools/tprint/tprint.x535
-rw-r--r--pkg/utilities/nttools/tprint/tprlatex.x579
-rw-r--r--pkg/utilities/nttools/tprint/tprplain.x530
8 files changed, 2782 insertions, 0 deletions
diff --git a/pkg/utilities/nttools/tprint/mkpkg b/pkg/utilities/nttools/tprint/mkpkg
new file mode 100644
index 00000000..8134ff5b
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/mkpkg
@@ -0,0 +1,15 @@
+# Update tprint and tdump in the ttools package library.
+# Author: HODGE, 2-FEB-1988
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ tdump.x <tbset.h>
+ tprint.x <time.h> <finfo.h> <tbset.h>
+ tprhtml.x <tbset.h> tprint.h
+ tprplain.x <tbset.h> tprint.h
+ tprlatex.x <tbset.h> tprint.h
+ ;
diff --git a/pkg/utilities/nttools/tprint/notes b/pkg/utilities/nttools/tprint/notes
new file mode 100644
index 00000000..2e6f9ff0
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/notes
@@ -0,0 +1,40 @@
+ Structure chart for tprint: 1988 Jan 21
+
+tprint:
+ (tbtopn)
+ tpr_fm_date:
+ (finfo)
+ tpr_param_pr:
+ (tbhgnp)
+ tpr_data_pr:
+ (tctexp)
+ tpr_plain_pr:
+ (decode_ranges)
+ get_page:
+ (tbcigi)
+ tpr_pfmt:
+ (tbcigt)
+ tpr_cnames_pr:
+ (tbcigt)
+ (get_next_number)
+ prt_row
+ (tbcigi)
+ (tbegt[])
+ tpr_latex_pr:
+ (decode_ranges)
+ tpr_pfmt:
+ (tbcigt)
+ tpr_beg_doc
+ tpr_def
+ tpr_begin_tbl
+ tpr_cnames_pr_l:
+ tpr_w_colsep
+ (tbcigt)
+ (get_next_number)
+ tpr_end_tbl
+ prt_row_l:
+ tpr_w_colsep
+ (tbcigi)
+ (tbegt[])
+ tpr_end_doc
+ (tbtclo)
diff --git a/pkg/utilities/nttools/tprint/tdump.x b/pkg/utilities/nttools/tprint/tdump.x
new file mode 100644
index 00000000..54658d58
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/tdump.x
@@ -0,0 +1,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
diff --git a/pkg/utilities/nttools/tprint/tprhtml.x b/pkg/utilities/nttools/tprint/tprhtml.x
new file mode 100644
index 00000000..6aecd26a
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/tprhtml.x
@@ -0,0 +1,592 @@
+include <ctype.h> # for IS_WHITE
+include <tbset.h>
+include "tprint.h"
+
+define ALIGN_LEFT -1
+define ALIGN_CENTER 0 # currently not used
+define ALIGN_RIGHT 1
+
+# This file contains subroutines for printing header keywords and/or
+# table data in html table format.
+# The high-level subroutines are:
+#
+# tpr_html_begin
+# tpr_html_end
+# tpr_html_param print header keywords
+# tpr_html_pr print table data
+#
+# Phil Hodge, 9-Aug-1999 Subroutine created
+
+procedure tpr_html_begin()
+
+begin
+ call printf ("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n")
+ call printf ("<HTML>\n")
+end
+
+procedure tpr_html_end()
+
+begin
+ call printf ("</HTML>\n")
+end
+
+# tpr_html_pr -- print contents of table
+# This version prints the table data in html format.
+
+procedure tpr_html_pr (tp, colptr, ncp, s_cp, lgroup,
+ range_string, pagelength,
+ showrow, orig_row, showhdr, showunits)
+
+pointer tp # i: pointer to table descriptor
+pointer colptr[ncp] # i: array of pointers to column descriptors
+int ncp # i: number of columns to print
+pointer s_cp # i: pointer to column to control spacing
+int lgroup # i: print blank line after this many lines
+char range_string[ARB] # i: string which gives ranges of row numbers
+int pagelength # i: number of data lines before printing header
+bool showrow # i: true if row number is to be printed
+bool orig_row # i: show row number from underlying table?
+bool showhdr # i: print column names, etc?
+bool showunits # i: print column units?
+#--
+pointer sp
+pointer buf # for a table entry; also for table info
+pointer nelem # array length for each column
+pointer align # array of flags for column alignment
+int max_nelem # maximum of array lengths
+bool has_arrays # true if any column contains arrays
+bool has_scalars # true if not all columns contain arrays
+char rowspan[SZ_FNAME] # string possibly containing ROWSPAN=max_nelem
+int nspan # alternate ROWSPAN=nspan, if extra spacing
+int linenum # number of lines of data printed
+int tmp_linenum # temporary value for linenum
+int line_on_page # number of data lines printed on current page
+int nrows # number of rows in table
+int rownum # row number
+int row # row number to be printed
+int cn # loop index for column number
+int element # loop index for element within array
+int ranges[3,MAX_RANGES] # ranges of row numbers
+int nvalues # returned by decode_ranges and ignored
+int stat # returned by get_next_number
+int s_flag # YES if we should add a line for spacing
+int s_nelem # array size of s_cp column, or one
+bool done # flag for terminating while loop on rows
+int decode_ranges(), get_next_number()
+int tbpsta(), tbcigi(), tbagtt()
+errchk tbsirow
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+ call salloc (nelem, ncp, TY_INT)
+ call salloc (align, ncp, TY_INT)
+
+ # Get info for each column.
+ max_nelem = 1 # initial values
+ if (showrow)
+ has_scalars = true # row number is a scalar
+ else
+ has_scalars = false
+
+ if (s_cp == NULL)
+ s_nelem = 1
+ else
+ s_nelem = tbcigi (s_cp, TBL_COL_LENDATA)
+
+ do cn = 1, ncp {
+
+ # array length
+ Memi[nelem+cn-1] = tbcigi (colptr[cn], TBL_COL_LENDATA)
+ if (Memi[nelem+cn-1] > max_nelem)
+ max_nelem = Memi[nelem+cn-1]
+ if (Memi[nelem+cn-1] == 1)
+ has_scalars = true
+
+ # left or right alignment, depending on print format
+ call tbcigt (colptr[cn], TBL_COL_FMT, Memc[buf], SZ_LINE)
+ if (Memc[buf+1] == '-') # e.g. %-12s
+ Memi[align+cn-1] = ALIGN_LEFT
+ else
+ Memi[align+cn-1] = ALIGN_RIGHT
+ }
+ if (max_nelem > 1) {
+ has_arrays = true
+ nspan = max_nelem # initial value
+ if (lgroup > 1) {
+ nspan = nspan + max_nelem / (lgroup - 1)
+ if (max_nelem / (lgroup - 1) * (lgroup - 1) == max_nelem)
+ nspan = nspan - 1 # one entire line will be blank
+ }
+ call sprintf (rowspan, SZ_FNAME, "ROWSPAN=%d")
+ call pargi (nspan)
+ } else {
+ has_arrays = false
+ rowspan[1] = EOS
+ }
+
+ call tbtnam (tp, Memc[buf], SZ_LINE)
+
+ call printf ("\n")
+ call printf ("<HEAD><TITLE>tprint of %s</TITLE></HEAD>\n")
+ call pargstr (Memc[buf])
+ call printf ("<BODY>\n")
+ call printf ("\n")
+
+ call printf ("<TABLE BORDER=2>\n")
+ call printf ("<CAPTION ALIGN=TOP>\n")
+ call printf ("<B>Table data: %s</B>\n")
+ call pargstr (Memc[buf])
+ call printf ("</CAPTION>\n")
+ call printf ("\n")
+
+ nrows = tbpsta (tp, TBL_NROWS)
+
+ if (showhdr) {
+ call tpr_h_header (tp, colptr, ncp, showrow, showunits,
+ Memc[buf], SZ_LINE)
+ }
+
+ if (decode_ranges (range_string, ranges, MAX_RANGES, nvalues) != OK)
+ call error (1, "bad range of row numbers")
+
+ # Print each row that is to be printed.
+ linenum = 0 # initialize line counters
+ line_on_page = 0
+ rownum = 0 # initialize get_next_number
+ stat = get_next_number (ranges, rownum) # get first row number
+ done = (stat == EOF) || (rownum > nrows)
+
+ while ( !done ) {
+
+ # If we need to insert extra lines for spacing within a column
+ # that contains arrays, find out the total number of lines
+ # we'll need to print. Then set ROWSPAN to this new value.
+ if (s_nelem > 1) {
+ # Count the total number of elements we'll span.
+ nspan = max_nelem # initial value
+ tmp_linenum = linenum
+ do element = 1, max_nelem {
+ call tpr_h_space (tp, s_cp, s_nelem, lgroup,
+ rownum, element, max_nelem, tmp_linenum, nspan)
+ tmp_linenum = tmp_linenum + 1
+ }
+ # Overwrite original value of rowspan string.
+ call sprintf (rowspan, SZ_FNAME, "ROWSPAN=%d")
+ call pargi (nspan)
+ }
+
+ # If all columns contain arrays, print a blank line.
+ if (!has_scalars && rownum > 1)
+ call tpr_h_blank_line (ncp, showrow)
+
+ # Loop over the number of elements in the longest array.
+ do element = 1, max_nelem {
+
+ # Check whether we should print a blank line.
+ # (Set pagelength to zero for this call; in tpr_space,
+ # blocking into groups of lines is reset at the top of
+ # each page, but we don't do that with html output.)
+ call tpr_space (tp, s_cp, lgroup,
+ rownum, element, max_nelem, 0, linenum, s_flag)
+
+ if (s_flag == YES) {
+ # Print a blank line.
+ if (has_arrays && element > 1) {
+ # Print a blank field for each array column.
+ call printf (" <TR>\n")
+ do cn = 1, ncp {
+ if (Memi[nelem+cn-1] > 1)
+ call printf (" <TD>&nbsp;</TD>\n")
+ }
+ call printf (" </TR>\n")
+ } else {
+ call tpr_h_blank_line (ncp, showrow)
+ }
+ linenum = linenum + 1
+ line_on_page = line_on_page + 1
+ }
+
+ # Print column names again, if appropriate.
+ if (showhdr && element == 1 && pagelength > 0) {
+ if (line_on_page >= pagelength) {
+ call tpr_h_header (tp, colptr, ncp, showrow, showunits,
+ Memc[buf], SZ_LINE)
+ line_on_page = 0
+ }
+ }
+
+ call printf (" <TR>\n")
+
+ if (element == 1 && showrow) {
+ if (orig_row)
+ call tbsirow (tp, rownum, row)
+ else
+ row = rownum
+ if (has_arrays) {
+ call printf (" <TD ALIGN=RIGHT %s>%d</TD>\n")
+ call pargstr (rowspan)
+ call pargi (row)
+ } else {
+ call printf (" <TD ALIGN=RIGHT>%d</TD>\n")
+ call pargi (row)
+ }
+ }
+
+ # Print each column.
+ do cn = 1, ncp {
+
+ # Does the current column contain arrays?
+ if (Memi[nelem+cn-1] > 1) {
+
+ if (element <= Memi[nelem+cn-1]) {
+ if (tbagtt (tp, colptr[cn], rownum,
+ Memc[buf], SZ_LINE, element, 1) < 1)
+ call error (1, "can't read array element")
+ call tpr_cell (Memc[buf], Memi[align+cn-1],
+ false, "")
+ } else {
+ call printf (" <TD>&nbsp;</TD>\n")
+ }
+
+ } else if (element == 1) {
+
+ call tbegtt (tp, colptr[cn], rownum,
+ Memc[buf], SZ_LINE)
+ if (has_arrays) {
+ call tpr_cell (Memc[buf], Memi[align+cn-1],
+ true, rowspan)
+ } else {
+ call tpr_cell (Memc[buf], Memi[align+cn-1],
+ false, "")
+ }
+ }
+ }
+
+ call printf (" </TR>\n")
+ linenum = linenum + 1
+ line_on_page = line_on_page + 1
+ }
+
+ stat = get_next_number (ranges, rownum)
+ done = (stat == EOF) || (rownum > nrows)
+ }
+
+ # Print column names at the end of the document, if appropriate.
+ if (showhdr && pagelength > 0) {
+ if (line_on_page >= pagelength) {
+ call tpr_h_header (tp, colptr, ncp, showrow, showunits,
+ Memc[buf], SZ_LINE)
+ }
+ }
+
+ call printf ("</TABLE>\n")
+ call printf ("</BODY>\n")
+ call flush (STDOUT)
+
+ call sfree (sp)
+end
+
+procedure tpr_h_blank_line (ncp, showrow)
+
+int ncp # i: number of columns to print
+bool showrow # i: true if we also print row numbers
+#--
+int nspan # number of columns to span
+
+begin
+ if (showrow)
+ nspan = ncp + 1
+ else
+ nspan = ncp
+
+ call printf (" <TR>\n")
+ call printf (" <TD COLSPAN=%d>&nbsp;</TD>\n")
+ call pargi (nspan)
+ call printf (" </TR>\n")
+end
+
+# This is a simplified version of tpr_space which just increments the count
+# of the number of elements to be spanned in a ROWSPAN tag.
+#
+# We can't just call tpr_space to do this, because each time it examines
+# a row, it saves the current value as 'previous'. We need this routine
+# in order to have a separate 'previous' variable.
+#
+# We don't need to increment linenum if nspan is incremented, because we
+# only use this routine for spacing in arrays, and it's the element number
+# that we care about for that case.
+
+procedure tpr_h_space (tp, s_cp, s_nelem, lgroup,
+ rownum, element, max_nelem, linenum, nspan)
+
+pointer tp # i: pointer to table descriptor
+pointer s_cp # i: pointer to column to control spacing
+int s_nelem # i: array size of s_cp column
+int lgroup # i: print blank after this many lines
+int rownum # i: number of current row
+int element # i: array element number
+int max_nelem # i: max value for element
+int linenum # i: number of lines that have been printed
+int nspan # io: incremented if we should increment ROWSPAN
+#--
+pointer sp
+pointer current # scratch for value of column in current row
+int lpage # number of line we would print
+int s_flag # YES if we would print a line for spacing
+char previous[SZ_LINE] # value of column in previous row
+bool do_compare # true if we should compare column values
+bool strne()
+int junk, tbagtt()
+errchk tbegtt, tbagtt
+
+begin
+ s_flag = NO # may be changed later
+
+ # linenum is the number of lines that have already been printed.
+ # lpage is the current line number.
+ lpage = linenum + 1
+
+ # If this is the first line, get the current value of the column
+ # and save it as "previous". That's all.
+ if (lpage == 1) {
+ junk = tbagtt (tp, s_cp, rownum, previous, SZ_LINE, element, 1)
+ return
+ }
+
+ # Have we printed a group of lines? If so, set the flag to indicate
+ # that we should print a blank line.
+ if (lgroup > 1) {
+ if (max_nelem > 1) {
+ if (lpage > 1) {
+ if (lgroup == 2)
+ s_flag = YES
+ else if (mod (element, lgroup-1) == 1)
+ s_flag = YES
+ }
+ } else if (mod (lpage, lgroup) == 0) {
+ s_flag = YES
+ }
+ }
+
+ # Check the value in the column.
+ if (element <= s_nelem) {
+ if (s_flag == YES) {
+ # Since we already know we need to print a space, we don't
+ # have to compare current and previous values, but we still
+ # must save current value as "previous".
+ junk = tbagtt (tp, s_cp, rownum, previous, SZ_LINE,
+ element, 1)
+ } else {
+ # Get current value, and compare it with previous value.
+ call smark (sp)
+ call salloc (current, SZ_LINE, TY_CHAR)
+ do_compare = true # may be reset
+ junk = tbagtt (tp, s_cp, rownum, Memc[current], SZ_LINE,
+ element, 1)
+ if (do_compare && strne (Memc[current], previous)) {
+ # Set flag; save current value as previous value.
+ s_flag = YES
+ call strcpy (Memc[current], previous, SZ_LINE)
+ }
+ call sfree (sp)
+ }
+ }
+
+ # If we should print a line before the first element of an array,
+ # we'll print a full line, rather than adding one to ROWSPAN; this
+ # is why we include the test on element.
+ if (s_flag == YES && element > 1)
+ nspan = nspan + 1
+end
+
+# This routine trims trailing blanks from the input buffer (in-place),
+# and it sets ip to the index of the first non-blank character. If
+# the entire field is blank, the string "&nbsp;" is assigned to the
+# input buffer.
+
+procedure tpr_deblank (buf, ip)
+
+char buf[ARB] # io: input string (trailing blanks will be truncted)
+int ip # o: first non-blank character in buf
+#--
+int strlen()
+
+begin
+ ip = strlen (buf)
+ while (ip >= 1 && IS_WHITE(buf[ip])) { # trim trailing blanks
+ buf[ip] = EOS
+ ip = ip - 1
+ }
+ ip = 1
+ while (IS_WHITE(buf[ip])) # trim leading blanks
+ ip = ip + 1
+ if (buf[ip] == EOS) {
+ call strcpy ("&nbsp;", buf, SZ_LINE)
+ ip = 1
+ }
+end
+
+# This routine prints one table element.
+
+procedure tpr_cell (buf, align, print_rowspan, rowspan)
+
+char buf[ARB] # io: input string (trailing blanks will be truncted)
+int align # i: ALIGN_LEFT or ALIGN_RIGHT
+bool print_rowspan # i: true --> print rowspan string
+char rowspan[ARB] # i: ROWSPAN=<n>
+#--
+int ip # first non-blank character in buf
+
+begin
+ call tpr_deblank (buf, ip)
+
+ if (print_rowspan) {
+
+ if (align == ALIGN_LEFT) {
+ call printf (" <TD ALIGN=LEFT %s>%s</TD>\n")
+ call pargstr (rowspan)
+ call pargstr (buf[ip])
+ } else {
+ call printf (" <TD ALIGN=RIGHT %s>%s</TD>\n")
+ call pargstr (rowspan)
+ call pargstr (buf[ip])
+ }
+
+ } else {
+
+ if (align == ALIGN_LEFT) {
+ call printf (" <TD ALIGN=LEFT>%s</TD>\n")
+ call pargstr (buf[ip])
+ } else {
+ call printf (" <TD ALIGN=RIGHT>%s</TD>\n")
+ call pargstr (buf[ip])
+ }
+ }
+end
+
+procedure tpr_h_header (tp, colptr, ncp, showrow, showunits, buf, maxch)
+
+pointer tp # i: pointer to table descriptor
+pointer colptr[ncp] # i: array of pointers to column descriptors
+int ncp # i: number of columns to print
+bool showrow # i: true if row number is to be printed
+bool showunits # i: print column units?
+char buf[ARB] # o: scratch space
+int maxch # i: size of buf
+#--
+int cn # loop index for column number
+
+begin
+ call printf (" <TR>\n")
+
+ if (showrow)
+ call printf (" <TH ALIGN=RIGHT>(row)</TH>\n")
+
+ do cn = 1, ncp {
+ call tbcigt (colptr[cn], TBL_COL_NAME, buf, SZ_LINE)
+ call printf (" <TH>%s</TH>\n")
+ call pargstr (buf)
+ }
+ call printf (" </TR>\n")
+
+ if (showunits) {
+ call printf (" <TR>\n")
+ if (showrow)
+ call printf (" <TH>&nbsp;</TH>\n")
+ do cn = 1, ncp {
+ call tbcigt (colptr[cn], TBL_COL_UNITS, buf, SZ_LINE)
+ if (buf[1] == EOS) {
+ call printf (" <TH>&nbsp;</TH>\n")
+ } else {
+ call printf (" <TH>%s</TH>\n")
+ call pargstr (buf)
+ }
+ }
+ call printf (" </TR>\n")
+ }
+end
+
+# This routine prints all the header keywords for a table.
+
+procedure tpr_html_param (tp)
+
+pointer tp # i: pointer to table descriptor
+#--
+pointer sp
+pointer buf # for a keyword value
+pointer comment # keyword comment
+int npar # number of header parameters
+char keyword[SZ_KEYWORD] # keyword name
+int n # loop index for keyword number
+int dtype # returned by tbhgnp and ignored
+int tbpsta()
+
+begin
+ npar = tbpsta (tp, TBL_NPAR)
+ if (npar <= 0)
+ return
+
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+ call salloc (comment, SZ_FNAME, TY_CHAR)
+
+ call tbtnam (tp, Memc[buf], SZ_LINE)
+
+ call printf ("\n")
+ call printf ("<HEAD><TITLE>tprint of %s</TITLE></HEAD>\n")
+ call pargstr (Memc[buf])
+ call printf ("<BODY>\n")
+ call printf ("\n")
+
+ call printf ("<TABLE BORDER=2>\n")
+ call printf ("<CAPTION ALIGN=TOP>\n")
+ call printf ("<B>Table keywords: %s</B>\n")
+ call pargstr (Memc[buf])
+ call printf ("</CAPTION>\n")
+ call printf ("\n")
+
+ call printf (" <TR>\n")
+ call printf (" <TH>keyword</TH>\n")
+ call printf (" <TH>value</TH>\n")
+ call printf (" <TH>comment</TH>\n")
+ call printf (" </TR>\n")
+
+ do n = 1, npar {
+
+ call printf (" <TR>\n")
+
+ # Get the Nth header parameter and comment.
+ call tbhgnp (tp, n, keyword, dtype, Memc[buf])
+ call tbhgcm (tp, keyword, Memc[comment], SZ_FNAME)
+
+ if (keyword[1] == EOS) {
+ call printf (" <TD>&nbsp;</TD>\n")
+ } else {
+ call printf (" <TD>%s</TD>\n")
+ call pargstr (keyword)
+ }
+
+ if (Memc[buf] == EOS) {
+ call printf (" <TD>&nbsp;</TD>\n")
+ } else {
+ call printf (" <TD>%s</TD>\n")
+ call pargstr (Memc[buf])
+ }
+
+ if (Memc[comment] == EOS) {
+ call printf (" <TD>&nbsp;</TD>\n")
+ } else {
+ call printf (" <TD>%s</TD>\n")
+ call pargstr (Memc[comment])
+ }
+
+ call printf (" </TR>\n")
+ }
+
+ call printf ("</TABLE>\n")
+ call printf ("</BODY>\n")
+ call flush (STDOUT)
+
+ call sfree (sp)
+end
diff --git a/pkg/utilities/nttools/tprint/tprint.h b/pkg/utilities/nttools/tprint/tprint.h
new file mode 100644
index 00000000..d0781b1c
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/tprint.h
@@ -0,0 +1,5 @@
+define MAXCOLS 52 # maximum number of columns per page
+define SZ_FMT 17 # size of string containing print format
+define MAX_RANGES (SZ_LINE/2) # max number of ranges of row numbers
+define SHORT_STRING 11 # size of short text strings
+define SZ_ROW_HDR 5 # size of header for row number: "# row"
diff --git a/pkg/utilities/nttools/tprint/tprint.x b/pkg/utilities/nttools/tprint/tprint.x
new file mode 100644
index 00000000..65c2d09d
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/tprint.x
@@ -0,0 +1,535 @@
+include <time.h> # defines SZ_TIME for datestr
+include <error.h> # defines EA_WARN
+include <finfo.h> # used by tpr_fm_date
+include <fset.h> # used to check whether output is redirected
+include <tbset.h>
+include "tprint.h"
+
+# tprint -- Program to print tables.
+#
+# Phil Hodge, 31-Jul-1987 Task created
+# Phil Hodge, 11-Aug-1987 Delete call to tbtext.
+# Phil Hodge, 28-Aug-1987 Write date that table was last modified.
+# Phil Hodge, 12-Oct-1987 Include LaTeX/TeX option.
+# Phil Hodge, 30-Dec-1987 Filename template; tctexp for column names.
+# Phil Hodge, 12-Feb-1988 Include option to align columns if format is small.
+# Phil Hodge, 30-Mar-1988 Page width = ttyncols; get sp_col & lgroup.
+# Phil Hodge, 7-Sep-1988 Change parameter name for table.
+# Phil Hodge, 10-May-1991 Use clpopns instead of clpopnu.
+# Phil Hodge, 26-Mar-1992 Remove call to tbtext; use tbtnam instead.
+# Phil Hodge, 28-Oct-1992 Set align=false if showhdr=false.
+# Phil Hodge, 5-Jul-1993 Include option to print column units.
+# Phil Hodge, 3-Feb-1994 Set showunits to false for a text table.
+# Phil Hodge, 15-Dec-1994 Increase size of table name from SZ_FNAME to SZ_LINE.
+# Phil Hodge, 16-Feb-1995 In tpr_param_pr, print "#" before header lines.
+# Phil Hodge, 6-Mar-1995 In tpr_param_pr, print comment for header parameter.
+# Phil Hodge, 23-Jun-1995 In tpr_fm_date, get file name using tbparse.
+# Phil Hodge, 3-Oct-1995 Replace clgfil calls with tbn... .
+# Phil Hodge, 9-Apr-1996 Error check tbtopn and tpr_data_pr;
+# call error if number of columns to print is zero (i.e. if no
+# column was found); flush STDOUT.
+# Phil Hodge, 5-Jun-1997 Use single instead of double quotes for keyword
+# text value, if there's an associated comment.
+# Phil Hodge, 26-Mar-1998 Add orig_row to par file, to show row number in
+# underlying table in case a row selector was used.
+# Phil Hodge, 7-Jun-1999 Allow showunits to be true for a text table;
+# this overrides the change made on 3-Feb-1994;
+# if input is redirected, set input to STDIN without getting cl param.
+# Phil Hodge, 9-Aug-1999 Add option = html; modify tpr_space to handle
+# arrays and to just set a flag, rather than actually printing the space.
+# Phil Hodge, 3-Jul-2000 In tpr_param_pr, delete leading blanks from the
+# value and comment.
+# Phil Hodge, 15-Jul-2009 In tpr_fm_date, remove ttype from the call to
+# tbparse.
+
+procedure tprint()
+
+pointer tp # pointer to input table descr
+pointer sp # stack pointer
+pointer tname # scratch for table name
+pointer columns # scratch for list of column names
+pointer range_string # string which gives ranges of row numbers
+pointer tlist # for list of input table names
+int pagewidth # max number of char in line length
+int pagelength # number of data lines (excl header) per page
+int lgroup # number of lines to group together on output
+bool prparam, prdata # print header parameters? data?
+bool showrow # show row number on output?
+bool orig_row # show row number from underlying table?
+bool showhdr # show table name, column names, etc on output?
+bool showunits # show column units on output?
+bool align # override print fmt to align col & name?
+char prt_option[SHORT_STRING] # "plain", "latex", "tex"
+char sp_cname[SZ_COLNAME] # name of column to control spacing
+bool first_table # false ==> print line to separate tables
+int clgeti(), fstati(), envgeti()
+bool clgetb()
+pointer tbnopenp(), tbnopen()
+int tbnget()
+pointer tbtopn()
+
+begin
+ call smark (sp)
+ call salloc (tname, SZ_LINE, TY_CHAR)
+ call salloc (columns, SZ_LINE, TY_CHAR)
+
+ if (fstati (STDIN, F_REDIR) == YES)
+ tlist = tbnopen ("STDIN")
+ else
+ tlist = tbnopenp ("table")
+
+ # Find out which portions of the table the user wants to print.
+ prparam = clgetb ("prparam")
+ prdata = clgetb ("prdata")
+ if (!prparam && !prdata) {
+ call sfree (sp)
+ return
+ }
+
+ if (prdata) {
+ # Get parameters relevant to printing data portion of table.
+
+ call salloc (range_string, SZ_LINE, TY_CHAR)
+
+ # Get page width from ttyncols unless output is redirected.
+ if (fstati (STDOUT, F_REDIR) == YES)
+ pagewidth = clgeti ("pwidth")
+ else
+ pagewidth = envgeti ("ttyncols")
+ pagelength = clgeti ("plength")
+ showrow = clgetb ("showrow")
+ orig_row = clgetb ("orig_row")
+ call clgstr ("columns", Memc[columns], SZ_LINE)
+ call clgstr ("rows", Memc[range_string], SZ_LINE)
+ align = clgetb ("align")
+
+ call clgstr ("sp_col", sp_cname, SZ_COLNAME)
+ lgroup = clgeti ("lgroup") + 1 # add one for the space
+ }
+
+ call clgstr ("option", prt_option, SHORT_STRING)
+ showhdr = clgetb ("showhdr")
+ if (showhdr) {
+ showunits = clgetb ("showunits")
+ } else {
+ # There's no need to align columns with their names if the names
+ # are not printed.
+ align = false
+ showunits = false
+ }
+
+ if (prt_option[1] == 'h') # HTML
+ call tpr_html_begin()
+
+ # Loop over all table names in the file name template.
+ first_table = true
+ while (tbnget (tlist, Memc[tname], SZ_LINE) != EOF) {
+
+ if ( ! first_table ) {
+ call printf ("\n") # blank line between tables
+ call flush (STDOUT)
+ }
+ first_table = false
+
+ # Open the table.
+ iferr {
+ tp = tbtopn (Memc[tname], READ_ONLY, 0)
+ } then {
+ call erract (EA_WARN)
+ next
+ }
+
+ # Get the full table name (for use by tpr_fm_date),
+ call tbtnam (tp, Memc[tname], SZ_LINE)
+
+ # Print the name of the table and the date that the table was
+ # last modified.
+ if (showhdr)
+ call tpr_fm_date (Memc[tname], prt_option)
+
+ if (prparam) # print header parameters
+ call tpr_param_pr (tp, prt_option, prdata)
+
+ if (prdata) { # print data portion of table
+ iferr {
+ call tpr_data_pr (tp, pagewidth, pagelength,
+ showrow, orig_row, showhdr, showunits,
+ align, sp_cname, lgroup,
+ Memc[columns], Memc[range_string], prt_option)
+ } then {
+ call tbtclo (tp)
+ call erract (EA_WARN)
+ next
+ }
+ }
+
+ call tbtclo (tp)
+ }
+ if (prt_option[1] == 'h') # HTML
+ call tpr_html_end()
+
+ call tbnclose (tlist)
+ call sfree (sp)
+end
+
+
+
+# tpr_fm_date -- Get date of file
+# This procedure gets the date that a table was last modified and writes
+# the table name and date to STDOUT.
+
+procedure tpr_fm_date (tablename, prt_option)
+
+char tablename[ARB] # i: name of table
+char prt_option[ARB] # i: "plain", "latex", or "tex"
+#--
+pointer sp
+pointer filename # name of table without brackets
+pointer cdfname # returned by tbparse and ignored
+int hdu # ignored
+long ostruct[LEN_FINFO] # contains info about file
+long mtime
+char datestr[SZ_TIME] # date that table was last modified
+char percent # the % character
+int junk, tbparse()
+int finfo()
+
+begin
+ if (prt_option[1] == 'h') # HTML
+ return
+
+ call smark (sp)
+ call salloc (filename, SZ_FNAME, TY_CHAR)
+ call salloc (cdfname, SZ_FNAME, TY_CHAR)
+
+ # Get file name from table name.
+ junk = tbparse (tablename, Memc[filename],
+ Memc[cdfname], SZ_FNAME, hdu)
+
+ percent = '%'
+
+ if (finfo (Memc[filename], ostruct) != ERR) {
+ mtime = FI_MTIME(ostruct)
+ call cnvtime (mtime, datestr, SZ_TIME)
+
+ if (prt_option[1] == 'p') { # plain print
+ call printf ("# Table %s %s\n")
+ call pargstr (tablename)
+ call pargstr (datestr)
+ } else { # LaTeX or TeX
+ call printf ("%c")
+ call pargc (percent) # comment
+ call printf (" Table %s %s\n")
+ call pargstr (tablename)
+ call pargstr (datestr)
+ }
+ call printf ("\n")
+ }
+ call flush (STDOUT)
+
+ call sfree (sp)
+end
+
+
+
+# tpr_param_pr -- Print header parameters
+# This procedure prints the header parameters on STDOUT.
+#
+# Phil Hodge, 5-Oct-1987 Subroutine created
+# Phil Hodge, 30-Dec-1987 If latex or tex, print % prefix.
+# Phil hodge, 9-Mar-1989 Change type of dtype in tbhgnp from char to int.
+
+procedure tpr_param_pr (tp, prt_option, prdata)
+
+pointer tp # i: pointer to table descriptor
+char prt_option[ARB] # i: "plain", "latex", or "tex"
+bool prdata # i: print data? (not here, though)
+#--
+pointer sp
+pointer value # scratch for value of parameter (string)
+pointer comment # scratch for comment for parameter
+int dtype # data type (TY_CHAR, etc)
+int npar # number of header parameters
+int n # loop index for parameter number
+int ipp, ipc # offsets for skipping leading blanks
+char keyword[SZ_KEYWORD] # buffer for header parameter keyword
+char percent # the % character
+int tbpsta()
+
+begin
+ if (prt_option[1] == 'h') { # HTML
+ call tpr_html_param (tp)
+ return
+ }
+
+ percent = '%'
+ npar = tbpsta (tp, TBL_NPAR)
+ if (npar > 0) {
+ call smark (sp)
+ call salloc (value, SZ_PARREC, TY_CHAR)
+ call salloc (comment, SZ_PARREC, TY_CHAR)
+ do n = 1, npar {
+
+ # Get the Nth header parameter and comment.
+ call tbhgnp (tp, n, keyword, dtype, Memc[value])
+ call tbhgcm (tp, keyword, Memc[comment], SZ_PARREC)
+ ipp = 0
+ while (Memc[value+ipp] == ' ')
+ ipp = ipp + 1
+ ipc = 0
+ while (Memc[comment+ipc] == ' ')
+ ipc = ipc + 1
+
+ if (prt_option[1] != 'p') { # LaTeX or TeX, not plain
+ call printf ("%c")
+ call pargc (percent) # comment
+ } else if (prdata) { # plain output, with data
+ call printf ("#K ") # comment
+ }
+
+ # Print the keyword and value, and possibly a comment.
+ if (Memc[comment+ipc] == EOS) { # no comment to print
+
+ call printf ("%-8s %s\n")
+ call pargstr (keyword)
+ call pargstr (Memc[value+ipp])
+
+ } else if (dtype == TY_CHAR) {
+
+ # Enclose value in quotes to distinguish from comment.
+ call printf ("%-8s '%s' %s\n")
+ call pargstr (keyword)
+ call pargstr (Memc[value+ipp])
+ call pargstr (Memc[comment+ipc])
+
+ } else {
+
+ # Numeric; no quotes needed.
+ call printf ("%-8s %s %s\n")
+ call pargstr (keyword)
+ call pargstr (Memc[value+ipp])
+ call pargstr (Memc[comment+ipc])
+ }
+ }
+ call sfree (sp)
+ call printf ("\n")
+ }
+ call flush (STDOUT)
+end
+
+
+
+# tpr_data_pr -- Print table data
+# This procedure prints the data portion of a table on STDOUT.
+#
+# Phil Hodge, 5-Oct-1987 Subroutine created
+# Phil Hodge, 12-Feb-1988 Include option to align columns if format is small.
+# Phil Hodge, 30-Mar-1988 Get column to control spacing of printout.
+
+procedure tpr_data_pr (tp, pagewidth, pagelength,
+ showrow, orig_row, showhdr, showunits,
+ align, sp_cname, lgroup,
+ columns, range_string, prt_option)
+
+pointer tp # i: pointer to table descriptor
+int pagewidth # i: page width
+int pagelength # i: number of lines of table per page
+bool showrow # i: print row number?
+bool orig_row # i: show row number from underlying table?
+bool showhdr # i: print column names, etc?
+bool showunits # i: print column units?
+bool align # i: override print fmt to align col & name?
+char sp_cname[SZ_COLNAME] # i: column to control spacing
+int lgroup # i: print blank line after this many lines
+char columns[ARB] # i: list of names of columns to be printed
+char range_string[ARB] # i: range of row numbers to print
+char prt_option[ARB] # i: "plain", "latex", or "tex"
+#--
+pointer sp
+pointer cptr # scratch for array of column pointers
+pointer s_cp # pointer to column to control spacing
+int nrows, ncols # number of rows and columns in table
+int ncp # number of columns to print (may be < ncols)
+int k # loop index
+int tbpsta()
+
+begin
+ nrows = tbpsta (tp, TBL_NROWS)
+ ncols = tbpsta (tp, TBL_NCOLS)
+
+ if ((nrows < 1) || (ncols < 1)) {
+ call eprintf ("table is empty\n")
+ return # nothing more to do
+ }
+
+ # Allocate enough space for storing a descriptor for each column.
+ call smark (sp)
+ call salloc (cptr, ncols, TY_POINTER)
+
+ # Get column pointers for all columns that are to be printed.
+ call tctexp (tp, columns, ncols, ncp, Memi[cptr])
+
+ # Check whether there is a column to control spacing.
+ k = 1
+ while ((sp_cname[k] == ' ' || sp_cname[k] == '\t') &&
+ (sp_cname[k] != EOS) && (k <= SZ_COLNAME))
+ k = k + 1
+ if (sp_cname[k] != EOS) {
+ call tbcfnd1 (tp, sp_cname[k], s_cp)
+ if (s_cp == NULL) {
+ call eprintf ("WARNING: column `%s' for spacing not found\n")
+ call pargstr (sp_cname)
+ }
+ } else {
+ s_cp = NULL
+ }
+
+ if (ncp > 0) {
+ # Print the values in the table.
+ if (prt_option[1] == 'p') { # plain printing
+ call tpr_plain_pr (tp, Memi[cptr], ncp, s_cp, lgroup,
+ range_string, pagewidth, pagelength,
+ showrow, orig_row, showhdr, showunits, align)
+ } else if (prt_option[1] == 'h') { # html table
+ call tpr_html_pr (tp, Memi[cptr], ncp, s_cp, lgroup,
+ range_string, pagelength,
+ showrow, orig_row, showhdr, showunits)
+ } else { # LaTeX or TeX
+ call tpr_latex_pr (tp, Memi[cptr], ncp, s_cp, lgroup,
+ range_string, pagewidth, pagelength,
+ showrow, orig_row, showhdr, showunits, prt_option)
+ }
+ call flush (STDOUT)
+ } else {
+ call error (1, "column not found")
+ }
+ call sfree (sp)
+end
+
+
+
+# tpr_space -- print line separator
+# Check whether we should print a blank line (or other line separator) if
+# the value in the designated column has changed since the last call to
+# this routine or if a group of lgroup lines has been printed.
+# The groups of lines are counted starting at the beginning of each
+# page; this makes a difference if lgroup does not divide pagelength.
+# If any column being printed contains arrays, then lgroup is applied
+# to element number, not to line number.
+#
+# If lgroup is one then it will be ignored; if s_cp is NULL then
+# the column values will be ignored.
+# When linenum is zero, the "previous" column value is initialized
+# with the current value.
+
+procedure tpr_space (tp, s_cp, lgroup,
+ rownum, element, max_nelem, pagelength, linenum, s_flag)
+
+pointer tp # i: pointer to table descriptor
+pointer s_cp # i: pointer to column to control spacing
+int lgroup # i: print blank after this many lines
+int rownum # i: number of current row
+int element # i: array element number
+int max_nelem # i: max value for element
+int pagelength # i: number of data lines per page
+int linenum # i: number of lines that have been printed
+int s_flag # o: YES if we should print a line for spacing
+#--
+pointer sp
+pointer current # scratch for value of column in current row
+int lpage # number of lines already printed on this page
+char previous[SZ_LINE] # value of column in previous row
+bool do_compare # true if we should compare column values
+bool strne()
+int nelem, tbcigi(), junk, tbagtt()
+errchk tbegtt, tbagtt
+
+begin
+ s_flag = NO # may be changed later
+
+ if (lgroup <= 1 && s_cp == NULL)
+ return
+
+ if (pagelength > 0)
+ lpage = mod (linenum, pagelength) + 1
+ else
+ lpage = linenum + 1
+
+ if (s_cp != NULL)
+ nelem = tbcigi (s_cp, TBL_COL_LENDATA)
+ else
+ nelem = 1
+
+ # If we're at the beginning of a page, get the current value
+ # of the column and save it as "previous". That's all.
+ if (lpage == 1) {
+ if (s_cp != NULL) {
+ if (nelem > 1) {
+ if (element <= nelem) {
+ junk = tbagtt (tp, s_cp, rownum, previous, SZ_LINE,
+ element, 1)
+ }
+ } else {
+ call tbegtt (tp, s_cp, rownum, previous, SZ_LINE)
+ }
+ }
+ return
+ }
+
+ # Have we printed a group of lines? If so, set the flag to indicate
+ # that we should print a blank line.
+ # If we're printing arrays, apply lgroup to the array elements instead
+ # of to the rows, but in this case also print a space between each row
+ # (i.e. when element is one), except at the top of a page.
+ # Note: The value of lgroup is one more than the parameter value,
+ # so that it can be used with mod on linenum, because linenum gets
+ # incremented when a blank line is printed. But here we want to use
+ # lgroup with element, which doesn't get incremented. That's why
+ # we subtract one from lgroup in "mod (element, lgroup-1)".
+ if (lgroup > 1) {
+ if (max_nelem > 1) {
+ if (lpage > 1) {
+ if (lgroup == 2)
+ s_flag = YES
+ else if (mod (element, lgroup-1) == 1)
+ s_flag = YES
+ }
+ } else if (mod (lpage, lgroup) == 0) {
+ s_flag = YES
+ }
+ }
+
+ # Check the value in the column.
+ if (s_cp != NULL) {
+ if (s_flag == YES) {
+ # If we already know we need to print a space, we don't have
+ # to compare current and previous values, but we still must
+ # save current value as "previous".
+ if (nelem > 1 && element <= nelem) {
+ junk = tbagtt (tp, s_cp, rownum, previous, SZ_LINE,
+ element, 1)
+ } else if (element == 1) {
+ call tbegtt (tp, s_cp, rownum, previous, SZ_LINE)
+ } # else we already have the value
+ } else {
+ # Get current value, and compare it with previous value.
+ call smark (sp)
+ call salloc (current, SZ_LINE, TY_CHAR)
+ do_compare = true # may be reset
+ if (nelem > 1 && element <= nelem) {
+ junk = tbagtt (tp, s_cp, rownum, Memc[current], SZ_LINE,
+ element, 1)
+ } else if (element == 1) {
+ call tbegtt (tp, s_cp, rownum, Memc[current], SZ_LINE)
+ } else {
+ do_compare = false
+ }
+ if (do_compare && strne (Memc[current], previous)) {
+ # Set flag; save current value as previous value.
+ s_flag = YES
+ call strcpy (Memc[current], previous, SZ_LINE)
+ }
+ call sfree (sp)
+ }
+ }
+end
diff --git a/pkg/utilities/nttools/tprint/tprlatex.x b/pkg/utilities/nttools/tprint/tprlatex.x
new file mode 100644
index 00000000..2875caa8
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/tprlatex.x
@@ -0,0 +1,579 @@
+include <tbset.h>
+include "tprint.h"
+
+# tpr_latex_pr -- print contents of table
+# This version prints the table data in a form suitable for input to
+# TeX or LaTeX. The corresponding procedure that prints in plain text
+# format is tpr_plain_pr.
+#
+# Phil Hodge, 7-Oct-1987 Subroutine created
+# Phil Hodge, 12-Feb-1988 Call tpr_pfmt_l instead of tpr_pfmt
+# Phil Hodge, 30-Mar-1988 Use a column to control spacing of printout.
+# Phil Hodge, 6-Jan-1989 tpr_break_l for new page, also after tpr_cnames_pr.
+# Phil Hodge, 2-Apr-1993 In prt_row_l, include short datatype.
+# Phil Hodge, 5-Jul-1993 Include option to print column units.
+# Phil Hodge, 26-Mar-1998 Add orig_row to calling sequence, use in prt_row_l;
+# in tpr_break_l, the calling sequence of tpr_end_tbl
+# had an extra argument.
+# Phil Hodge, 9-Aug-1999 Change the calling sequence of tpr_space.
+
+procedure tpr_latex_pr (tp, colptr, ncp, s_cp, lgroup,
+ range_string, pagewidth, pagelength,
+ showrow, orig_row, showhdr, showunits, prt_option)
+
+pointer tp # i: pointer to table descriptor
+pointer colptr[ncp] # i: array of pointers to column descriptors
+int ncp # i: number of columns to print
+pointer s_cp # i: pointer to column to control spacing
+int lgroup # i: print a blank line after this many lines
+char range_string[ARB] # i: string which gives ranges of row numbers
+int pagewidth # i: page width
+int pagelength # i: number of data lines per page
+bool showrow # i: true if row number is to be printed
+bool orig_row # i: show row number from underlying table?
+bool showhdr # i: print column names, etc?
+bool showunits # i: print column units?
+char prt_option[ARB] # i: "latex" or "tex"
+#--
+pointer sp
+pointer data_fmt # print formats for column data values
+pointer j_flag # left or right justification
+char rn_fmt[SZ_FMT] # format for printing row numbers
+char rn_name[SZ_ROW_HDR] # row number header: "(row)"
+char percent # a percent sign (comment for TeX)
+int nrows # total number of rows in table
+int element # loop index for array element number
+int max_nelem # max number of elements
+int rn_width # width needed for printing row number
+int lenfmt[MAXCOLS] # lengths of print fmt for cols on current page
+int rownum # row number
+int linenum # number of lines of data printed
+int ranges[3,MAX_RANGES] # ranges of row numbers
+int nvalues # returned by decode_ranges and ignored
+int stat # returned by get_next_number
+int k # loop index
+int s_flag # YES if we should add a line for spacing
+bool done # flag for terminating while loop on rows
+int decode_ranges(), get_next_number(), tbpsta(), tbcigi()
+
+begin
+ percent = '%'
+
+ # Allocate space for format strings for printing column names
+ # and values.
+ call smark (sp)
+ call salloc (data_fmt, (SZ_FMT+1)*ncp, TY_CHAR)
+ call salloc (j_flag, ncp, TY_INT)
+
+ if (ncp > MAXCOLS) {
+ call eprintf ("maximum number of columns is %d\n")
+ call pargi (MAXCOLS)
+ call error (1, "")
+ }
+
+ nrows = tbpsta (tp, TBL_NROWS)
+
+ if (decode_ranges (range_string, ranges, MAX_RANGES, nvalues) != OK)
+ call error (1, "bad range of row numbers")
+
+ # These three values (rn_name, rn_fmt, rn_width) must be consistent.
+ call strcpy ("(row)", rn_name, SHORT_STRING)
+ call strcpy ("%5d", rn_fmt, SZ_FMT)
+ if (showrow)
+ rn_width = SZ_ROW_HDR # space for printing row number
+ else
+ rn_width = 0
+
+ # Get length of print format for each column.
+ do k = 1, ncp
+ lenfmt[k] = tbcigi (colptr[k], TBL_COL_FMTLEN)
+
+ # Fill array of print formats for column names and for data.
+ call tpr_pfmt_l (colptr, lenfmt, Memc[data_fmt],
+ Memi[j_flag], ncp)
+
+ if (showhdr) {
+ # Print the \begin{document} string.
+ call tpr_beg_doc (prt_option)
+
+ # Print the default \def or \newcommand for column separators
+ # and \eol, and print the begin-table string and column names.
+ call tpr_def (prt_option, ncp, showrow)
+ call tpr_begin_tbl (prt_option, Memi[j_flag], ncp, showrow)
+ call tpr_cnames_pr_l (colptr, ncp, showrow, showunits, rn_name)
+ }
+
+ # Print each row that is to be printed.
+ linenum = 0 # initialize line counter
+ rownum = 0 # initialize get_next_number
+ stat = get_next_number (ranges, rownum) # get first row number
+ done = (stat == EOF) || (rownum > nrows)
+
+ element = 1 # not used yet
+ max_nelem = 1
+
+ while ( !done ) {
+
+ # Print a page break if appropriate.
+ call tpr_break_l (linenum, pagelength, showhdr, showunits,
+ prt_option, Memi[j_flag],
+ colptr, ncp, showrow, rn_name)
+
+ # Print a blank line if the column value has changed or if
+ # a group of lgroup lines have been printed.
+ call tpr_space (tp, s_cp, lgroup,
+ rownum, element, max_nelem, pagelength, linenum, s_flag)
+ if (s_flag == YES) {
+ call printf ("\\extline\n")
+ linenum = linenum + 1
+ # Check whether we should also print a page break.
+ call tpr_break_l (linenum, pagelength, showhdr, showunits,
+ prt_option, Memi[j_flag],
+ colptr, ncp, showrow, rn_name)
+ }
+
+ # Print % as row separator (for readability); print current row.
+ call printf ("%c\n")
+ call pargc (percent)
+ call prt_row_l (tp, colptr, Memc[data_fmt], ncp, rownum,
+ lenfmt, pagewidth, showrow, orig_row, rn_fmt, rn_width)
+ linenum = linenum + 1
+ stat = get_next_number (ranges, rownum)
+ done = (stat == EOF) || (rownum > nrows)
+ }
+
+ if (showhdr) {
+ # Print end-table string.
+ call tpr_end_tbl (prt_option)
+ }
+ if (showhdr)
+ # Write \end{document} string.
+ call tpr_end_doc (prt_option)
+
+ call sfree (sp)
+end
+
+# tpr_break_l -- print a page break
+# This routine prints the "end table" and "begin table" strings, if
+# appropriate. If pagelength is zero we're not printing page breaks
+# anyway, and if linenum is zero we've already printed the header, so
+# nothing is done. Otherwise, if linenum is zero mod pagelength
+# print a page break, and if showhdr print the column names.
+
+procedure tpr_break_l (linenum, pagelength, showhdr, showunits,
+ prt_option, just_flag,
+ colptr, ncp, showrow, rn_name)
+
+int linenum # io: number of lines of data printed
+int pagelength # i: number of data lines per page
+bool showhdr # i: print column names?
+bool showunits # i: print column units?
+char prt_option[ARB] # i: "latex" or "tex"
+int just_flag[ARB] # i: -1, 0, +1 for left, center, right just.
+pointer colptr[ARB] # i: array of column pointers
+int ncp # i: number of columns to print
+bool showrow # i: print row number?
+char rn_name[ARB] # i: column header for row number
+#--
+
+begin
+ if (pagelength > 0) {
+ if (linenum > 0) {
+ if (mod (linenum, pagelength) == 0) {
+ # Print end table, begin table, and column names.
+ call tpr_end_tbl (prt_option)
+ call tpr_begin_tbl (prt_option, just_flag, ncp,
+ showrow)
+ if (showhdr)
+ call tpr_cnames_pr_l (colptr, ncp,
+ showrow, showunits, rn_name)
+ }
+ }
+ }
+end
+
+
+# tpr_pfmt_l -- Get print formats
+# This procedure fills an array with print formats for printing the
+# column values. An array of flags specifying whether each column is
+# to be left or right justified is also returned.
+
+procedure tpr_pfmt_l (colptr, lenfmt, data_fmt, just_flag, ncp)
+
+pointer colptr[ncp] # i: array of column pointers
+int lenfmt[ncp] # i: array of lengths of print formats
+char data_fmt[SZ_FMT,ncp] # o: array of print formats for data
+int just_flag[ncp] # o: -1 or +1 for left, right justification
+int ncp # i: number of columns to print
+#--
+int cn # loop index for column number
+
+begin
+ do cn = 1, ncp { # do for each column to print
+
+ call tbcigt (colptr[cn], TBL_COL_FMT, data_fmt[1,cn], SZ_FMT)
+ if (data_fmt[2,cn] == '-')
+ just_flag[cn] = -1 # left justification
+ else
+ just_flag[cn] = 1 # right justification
+ }
+end
+
+
+
+# tpr_beg_doc -- Print begin-document strings
+# This procedure prints strings for LaTeX or for TeX that begin
+# a document. (Nothing is written for TeX.)
+
+procedure tpr_beg_doc (prt_option)
+
+char prt_option[ARB] # i: "latex" or "tex"
+
+begin
+ if (prt_option[1] == 'l') { # LaTeX
+ call printf ("\\documentstyle{article}\n")
+ call printf ("\\begin{document}\n")
+ }
+end
+
+
+
+# tpr_end_doc -- Print end-document strings
+# This procedure prints strings for LaTeX or for TeX that end
+# a document.
+
+procedure tpr_end_doc (prt_option)
+
+char prt_option[ARB] # i: "latex" or "tex"
+
+begin
+ if (prt_option[1] == 'l') # LaTeX
+ call printf ("\\end{document}\n")
+ else if (prt_option[1] == 't') # TeX
+ call printf ("\\end\n")
+end
+
+
+# tpr_def -- Print newcommand strings
+# This procedure prints strings for LaTeX or for TeX that define
+# macros for column separators and for the end-of-line string.
+#
+# Phil Hodge, 1-Apr-88 \extline added
+
+procedure tpr_def (prt_option, ncp, showrow)
+
+char prt_option[ARB] # i: "latex" or "tex"
+int ncp # i: number of columns to print
+bool showrow # i: print row number?
+#--
+int k # loop index
+char new_cmd[SHORT_STRING] # "\newcommand" or "\def"
+char n_str[SHORT_STRING] # "{\null}"
+char latex_eol[SHORT_STRING] # "\eol{\\}"
+char tex_eol[SHORT_STRING] # "\eol{\cr}"
+
+begin
+ if (prt_option[1] == 'l') # LaTeX
+ call strcpy ("\\newcommand", new_cmd, SHORT_STRING)
+ else if (prt_option[1] == 't') # TeX
+ call strcpy ("\\def", new_cmd, SHORT_STRING)
+ call strcpy ("{\\null}", n_str, SHORT_STRING)
+ call strcpy ("\\eol{\\\\}", latex_eol, SHORT_STRING)
+ call strcpy ("\\eol{\\cr}", tex_eol, SHORT_STRING)
+
+ if (showrow)
+ k = 0
+ else
+ k = 1
+
+ # Define either \colzero or \cola, depending on showrow.
+ call printf ("%s")
+ call pargstr (new_cmd)
+ call tpr_w_colsep (k)
+ call printf ("%s\n")
+ call pargstr (n_str)
+
+ # Define the rest of the column-separators, if any.
+ k = k + 1
+ while (k <= ncp) {
+ call printf ("%s")
+ call pargstr (new_cmd)
+ call tpr_w_colsep (k)
+ call printf ("{&}\n")
+ k = k + 1
+ }
+
+ # Define \eol.
+ call printf ("%s")
+ call pargstr (new_cmd)
+ if (prt_option[1] == 'l') { # LaTeX
+ call printf ("%s\n")
+ call pargstr (latex_eol)
+ } else if (prt_option[1] == 't') { # TeX
+ call printf ("%s\n")
+ call pargstr (tex_eol)
+ }
+
+ # Define \extline for writing blank lines.
+ call printf ("%s\\extline{")
+ call pargstr (new_cmd)
+ do k = 1, ncp-1
+ call printf ("&")
+ if (showrow)
+ call printf ("&")
+ call printf ("\\eol}\n")
+
+ call printf ("\n")
+end
+
+
+
+# tpr_begin_tbl -- Print begin-table string
+# This procedure prints a begin-table string for LaTeX or for TeX.
+
+procedure tpr_begin_tbl (prt_option, just_flag, ncp, showrow)
+
+char prt_option[ARB] # i: "latex" or "tex"
+int just_flag[ARB] # i: -1, 0, +1 for left, center, right just.
+int ncp # i: number of columns to print
+bool showrow # i: print row number?
+#--
+int k # loop index
+char tex_cr[SHORT_STRING] # "\cr"
+
+begin
+ if (prt_option[1] == 'l') { # LaTeX
+
+ call printf ("\\begin{tabular}{")
+ if (showrow)
+ call printf ("r") # right justify row number
+ do k = 1, ncp {
+ if (just_flag[k] == -1)
+ call printf ("l") # left justify
+ else if (just_flag[k] == 1)
+ call printf ("r") # right justify
+ else
+ call printf ("c") # center
+ }
+ call printf ("}\n")
+
+ } else if (prt_option[1] == 't') { # TeX
+
+ call strcpy ("\\cr", tex_cr, SHORT_STRING)
+
+ if (showrow) {
+ call printf ("\\halign{\\hfil#") # row number
+ call printf ("\n&\\quad")
+ } else {
+ call printf ("\\halign{")
+ }
+
+ # First column.
+ if (just_flag[1] == -1)
+ call printf ("#\\hfil") # left
+ else if (just_flag[1] == 1)
+ call printf ("\\hfil#") # right
+ else
+ call printf ("\\hfil#\\hfil") # center
+
+ do k = 2, ncp {
+ if (just_flag[k] == -1)
+ call printf ("\n&\\quad#\\hfil")
+ else if (just_flag[k] == 1)
+ call printf ("\n&\\quad\\hfil#")
+ else
+ call printf ("\n&\\quad\\hfil#\\hfil")
+ }
+ call printf ("%s\n\n") # can't use \eol here
+ call pargstr (tex_cr)
+ }
+end
+
+
+# tpr_end_tbl -- Print end-table string
+# This procedure prints an end-table string for LaTeX (or TeX).
+
+procedure tpr_end_tbl (prt_option)
+
+char prt_option[ARB] # i: "latex" or "tex"
+#--
+
+begin
+ if (prt_option[1] == 'l') # LaTeX
+ call printf ("\\end{tabular}\n\n")
+ else if (prt_option[1] == 't') # TeX
+ call printf ("}\n\n")
+end
+
+
+
+# tpr_cnames_pr_l -- Print column names
+# This procedure prints the column names followed by a blank line.
+# (TeX or LaTeX only)
+
+procedure tpr_cnames_pr_l (colptr, ncp, showrow, showunits, rn_name)
+
+pointer colptr[ncp] # i: array of column pointers
+int ncp # i: number of columns on current page
+bool showrow # i: true if row number is to be printed
+bool showunits # i: print column units?
+char rn_name[ARB] # i: column header for row number
+#--
+int cn # loop index for column number
+char colname[SZ_COLNAME] # column name
+char colunits[SZ_COLUNITS] # column units
+
+begin
+ if (showrow) {
+ call tpr_w_colsep (0)
+ call printf (rn_name)
+ }
+ do cn = 1, ncp { # do for each column on page
+ call tpr_w_colsep (cn)
+ call tbcigt (colptr[cn], TBL_COL_NAME, colname, SZ_COLNAME)
+ call printf ("%s") # trim extra blanks
+ call pargstr (colname)
+ }
+ call printf ("\\eol\n")
+
+ # Also print column units?
+ if (showunits) {
+ if (showrow) {
+ call tpr_w_colsep (0)
+ }
+ do cn = 1, ncp {
+ call tpr_w_colsep (cn)
+ call tbcigt (colptr[cn], TBL_COL_UNITS, colunits, SZ_COLUNITS)
+ call printf ("%s")
+ call pargstr (colunits)
+ }
+ call printf ("\\eol\n")
+ }
+ call printf ("\\extline\n")
+end
+
+
+# prt_row_l -- print a row
+# This procedure prints the contents of one row. This LaTeX (or TeX)
+# version differs from the plain-print version in the following ways:
+# character-string values are printed using %s so that extra blanks
+# will not be printed, the column-separators may differ from one column
+# to the next, and an end-of-line string is printed.
+
+procedure prt_row_l (tp, colptr, data_fmt, ncp, rownum,
+ lenfmt, pagewidth, showrow, orig_row, rn_fmt, rn_width)
+
+pointer tp # i: pointer to table descriptor
+pointer colptr[ncp] # i: array of pointers to column descriptors
+char data_fmt[SZ_FMT,ncp] # i: print format for each column
+int ncp # i: number of columns on current page
+int rownum # i: row number
+int lenfmt[ncp] # i: array of lengths of print formats
+int pagewidth # i: page width
+bool showrow # i: print row number?
+bool orig_row # i: show row number from underlying table?
+char rn_fmt[ARB] # i: format for printing row number
+int rn_width # i: space for printing row number
+#--
+pointer sp
+pointer cbuf # scratch for character-string buffer
+double dbuf # buffer for double-precision elements
+real rbuf # buffer for single-precision elements
+int ibuf # buffer for integer elements
+short sbuf
+bool bbuf # buffer for boolean elements
+int cn # loop index for column number
+int datatype # data type of column
+int lentotal # for determining when to print \n
+int colsep_width # space needed to print column-separator string
+int underlying_row # row number in underlying table
+int tbcigi()
+errchk tbsirow
+
+begin
+ call smark (sp)
+ call salloc (cbuf, SZ_LINE, TY_CHAR)
+
+ colsep_width = 6 # e.g. "\cola "
+
+ if (showrow) {
+ call tpr_w_colsep (0)
+ if (orig_row) {
+ call tbsirow (tp, rownum, underlying_row)
+ call printf (rn_fmt)
+ call pargi (underlying_row)
+ } else {
+ call printf (rn_fmt)
+ call pargi (rownum) # write row number
+ }
+ lentotal = colsep_width + rn_width
+ } else {
+ lentotal = 0
+ }
+
+ do cn = 1, ncp {
+
+ if (lentotal + lenfmt[cn] > pagewidth) {
+ call printf ("\n")
+ lentotal = 0
+ }
+ call tpr_w_colsep (cn) # write column-separator string
+
+ datatype = tbcigi (colptr[cn], TBL_COL_DATATYPE)
+ switch (datatype) {
+ case (TY_REAL):
+ call tbegtr (tp, colptr[cn], rownum, rbuf)
+ call printf (data_fmt[1,cn])
+ call pargr (rbuf)
+ case (TY_DOUBLE):
+ call tbegtd (tp, colptr[cn], rownum, dbuf)
+ call printf (data_fmt[1,cn])
+ call pargd (dbuf)
+ case (TY_INT):
+ call tbegti (tp, colptr[cn], rownum, ibuf)
+ call printf (data_fmt[1,cn])
+ call pargi (ibuf)
+ case (TY_SHORT):
+ call tbegts (tp, colptr[cn], rownum, sbuf)
+ call printf (data_fmt[1,cn])
+ call pargs (sbuf)
+ case (TY_BOOL):
+ call tbegtb (tp, colptr[cn], rownum, bbuf)
+ call printf (data_fmt[1,cn])
+ call pargb (bbuf)
+ default:
+ if (datatype < 0 || datatype == TY_CHAR) {
+ call tbegtt (tp, colptr[cn], rownum, Memc[cbuf], SZ_LINE)
+ call printf ("%s") # trim blanks
+ call pargstr (Memc[cbuf])
+ } else {
+ call error (1, "bad data type; table corrupted?")
+ }
+ }
+ lentotal = lentotal + colsep_width + lenfmt[cn]
+ }
+ call printf ("\\eol\n")
+
+ call sfree (sp)
+end
+
+
+# tpr_w_colsep -- Write column-separator string
+# This procedure writes a string of the form "\cola ", "\colb ", etc
+# for n = 1, 2, etc. The case n = 0 gives "\colzero " which is used
+# for the row number column.
+
+procedure tpr_w_colsep (n)
+
+int n # i: column number or zero
+#--
+string alphabet "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+begin
+ if (n <= 0) {
+ call printf ("\\colzero ")
+ } else {
+ call printf ("\\col%c ")
+ call pargc (alphabet[n])
+ }
+end
diff --git a/pkg/utilities/nttools/tprint/tprplain.x b/pkg/utilities/nttools/tprint/tprplain.x
new file mode 100644
index 00000000..c40217d7
--- /dev/null
+++ b/pkg/utilities/nttools/tprint/tprplain.x
@@ -0,0 +1,530 @@
+include <ctype.h> # for IS_WHITE
+include <tbset.h>
+include "tprint.h"
+
+# tpr_plain_pr -- print contents of table
+# This version simply prints the table data. The corresponding procedure
+# that prints in TeX/LaTeX format is tpr_latex_pr.
+# It may be that all the columns that are to be printed will not fit
+# on one page, in which case they are printed in sections: all the rows
+# are printed for the first set of columns, then all the rows for the next
+# set, etc.
+#
+# Phil Hodge, 5-Oct-1987 Subroutine created
+# Phil Hodge, 7-Oct-1987 prt_row: use different buffer for each data type.
+# Phil Hodge, 12-Feb-1988 Include option to align columns with header
+# Phil Hodge, 30-Mar-1988 Use a column to control spacing of printout.
+# Phil Hodge, 6-Jan-1989 Call tpr_break for new page, also after tpr_cnames_pr
+# Phil Hodge, 2-Apr-1993 In prt_row, include short datatype.
+# Phil Hodge, 5-Jul-1993 Include option to print column units.
+# Phil Hodge, 16-Feb-1995 Print "#" before header lines to comment them out.
+# Phil Hodge, 26-Mar-1998 Add orig_row to calling sequence, use in prt_row;
+# remove showrow from calling sequences of
+# tpr_break and tpr_cnames_pr.
+# Phil Hodge, 18-Jan-1999 Get boolean as string, to preserve indef values.
+# Phil Hodge, 30-Mar-1999 Delete declaration of bbuf from prt_row.
+# Phil Hodge, 9-Aug-1999 Print all array elements;
+# move code for printing blank lines into prt_row;
+# change the calling sequence of tpr_space;
+# delete data_fmt and subroutine tpr_g_fmt.
+# Phil Hodge, 3-Jul-2000 In tpr_pfmt, use "%-s" format for the last column
+# on a page, if the column should be left justified.
+# Phil Hodge, 2-Nov-2000 Remove the restriction that no more than MAXCOLS
+# columns can be printed on one page.
+
+procedure tpr_plain_pr (tp, cptr, nprint, s_cp, lgroup,
+ range_string, pagewidth, pagelength,
+ showrow, orig_row, showhdr, showunits, align)
+
+pointer tp # i: pointer to table descriptor
+pointer cptr[nprint] # i: array of pointers to column descriptors
+int nprint # i: number of columns to print
+pointer s_cp # i: pointer to column to control spacing
+int lgroup # i: print blank line after this many lines
+char range_string[ARB] # i: string which gives ranges of row numbers
+int pagewidth # i: page width
+int pagelength # i: number of data lines per page
+bool showrow # i: true if row number is to be printed
+bool orig_row # i: show row number from underlying table?
+bool showhdr # i: print column names?
+bool showunits # i: print column units?
+bool align # i: override print fmt to align col & name?
+#--
+pointer sp
+pointer colptr # ptr to descriptors for columns on current page
+pointer lenfmt # ptr to lengths of print fmt for cols on page
+pointer cn_fmt # formats for printing column values
+char rn_fmt[SZ_FMT] # format for printing row numbers
+char rn_name[SZ_ROW_HDR] # row number header: "# row"
+char rn_units[SZ_ROW_HDR] # "# " printed in the line for units
+char percent # '%'
+int nrows # total number of rows in table
+int rn_width # width needed for printing row number
+int lcp # column number of leftmost column on page
+int ncp # number of columns on current page
+int rownum # row number
+int linenum # number of lines of data printed
+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 while loop on rows
+int decode_ranges(), get_next_number(), tbpsta()
+
+begin
+ # Allocate space for format strings for printing column names and
+ # values. Allocate arrays for pointers to column descriptors and
+ # the ascii width of each column. Allow enough space to print all
+ # columns on one page.
+ call smark (sp)
+ call salloc (cn_fmt, (SZ_FMT+1)*nprint, TY_CHAR)
+ call salloc (colptr, nprint, TY_POINTER)
+ call salloc (lenfmt, nprint, TY_POINTER)
+
+ nrows = tbpsta (tp, TBL_NROWS)
+
+ if (decode_ranges (range_string, ranges, MAX_RANGES, nvalues) != OK)
+ call error (1, "bad range of row numbers")
+
+ # rn_name, rn_units, rn_fmt and rn_width must be consistent.
+ if (showrow) {
+ # These two strings are printed above the row number
+ # in the line for column names and in the line for column units.
+ call strcpy ("# row", rn_name, SZ_ROW_HDR)
+ call strcpy ("# ", rn_units, SZ_ROW_HDR)
+ rn_width = SZ_ROW_HDR # space for printing row number
+ } else if (showhdr) {
+ call strcpy ("#", rn_name, SZ_ROW_HDR)
+ call strcpy ("#", rn_units, SZ_ROW_HDR)
+ rn_width = 1 # space for "#"
+ } else {
+ rn_name[1] = EOS # no header printed
+ rn_units[1] = EOS
+ rn_width = 0
+ }
+ percent = '%'
+ call sprintf (rn_fmt, SZ_FMT, "%c%dd") # --> %5d
+ call pargc (percent)
+ call pargi (SZ_ROW_HDR)
+
+ lcp = 1 # initialize
+ while (lcp <= nprint) { # do for each page
+
+ # Get column pointers for current page
+ call get_page (tp, cptr, lcp, nprint, pagewidth-rn_width,
+ align, showunits, Memi[colptr], Memi[lenfmt], ncp)
+
+ # Fill array of print formats.
+ call tpr_pfmt (Memi[colptr], Memi[lenfmt], align, Memc[cn_fmt], ncp)
+
+ # Print a form feed if this is not the first page and the user
+ # has requested page breaks.
+ if (lcp > 1) {
+ if (pagelength > 0)
+ call printf ("\f\n")
+ else
+ call printf ("\n")
+ }
+ # Print column names.
+ if (showhdr)
+ call tpr_cnames_pr (Memi[colptr], Memc[cn_fmt], ncp,
+ showunits, rn_name, rn_units)
+
+ # Print each row that is to be printed.
+ linenum = 0 # initialize line counter
+ rownum = 0 # initialize get_next_number
+ stat = get_next_number (ranges, rownum) # get first row number
+ done = (stat == EOF) || (rownum > nrows)
+
+ while ( !done ) {
+
+ # Print values in current row.
+ call prt_row (tp, Memi[colptr], Memc[cn_fmt], ncp,
+ linenum, pagelength, s_cp, lgroup,
+ rn_fmt, rn_name, rn_units,
+ rownum, showrow, orig_row, showhdr, showunits)
+
+ # Get next row number.
+ stat = get_next_number (ranges, rownum)
+ done = (stat == EOF) || (rownum > nrows)
+ }
+
+ lcp = lcp + ncp # next set of columns to be printed
+ }
+ call sfree (sp)
+end
+
+# tpr_break -- print a page break
+# This routine prints a form feed ('\f') if appropriate. If pagelength
+# is zero we're not printing page breaks anyway, and if linenum is zero
+# we've already printed the header, so nothing is done. Otherwise,
+# if linenum is zero mod pagelength print a page break, and if showhdr
+# print the header.
+
+procedure tpr_break (linenum, pagelength, showhdr, showunits,
+ colptr, cn_fmt, ncp, rn_name, rn_units)
+
+int linenum # io: number of lines of data printed
+int pagelength # i: number of data lines per page
+bool showhdr # i: print column names?
+bool showunits # i: also print column units?
+pointer colptr[ARB] # i: array of column pointers
+char cn_fmt[SZ_FMT,ARB] # i: array of print formats
+int ncp # i: number of columns on current page
+char rn_name[ARB] # i: column header for row number
+char rn_units[ARB] # i: printed below rn_name
+#--
+
+begin
+ if (pagelength > 0) {
+ if (linenum > 0) {
+ if (mod (linenum, pagelength) == 0) {
+ call printf ("\f\n")
+ if (showhdr) # print column names
+ call tpr_cnames_pr (colptr, cn_fmt, ncp,
+ showunits, rn_name, rn_units)
+ }
+ }
+ }
+end
+
+
+# get_page -- get columns for page
+# This procedure determines which columns will fit on the current page.
+# Each column is assumed to begin with a column separator which is a
+# single space.
+
+procedure get_page (tp, cptr, lcp, nprint, pagewidth, align,
+ showunits, colptr, lenfmt, ncp)
+
+pointer tp # i: pointer to table descriptor
+pointer cptr[nprint] # i: array of pointers to all column descr
+int lcp # i: column number of leftmost column on page
+int nprint # i: number of columns to print
+int pagewidth # i: page width available for writing
+bool align # i: override print fmt to align col & name?
+bool showunits # i: also print column units?
+pointer colptr[ARB] # o: pointers for columns on current page
+int lenfmt[ARB] # o: length of print format for each col
+int ncp # o: number of columns on current page
+#--
+char colname[SZ_COLNAME] # column name for error message
+int lentotal # sum of lenfmt plus a space for each column
+int nextc # column counter
+int tpr_lenfmt()
+
+begin
+ # Assume we can print at least one column, truncated if necessary.
+ ncp = 1
+ colptr[1] = cptr[lcp]
+ # Get width for printing column.
+ lenfmt[1] = tpr_lenfmt (colptr[1], align, showunits)
+ if (lenfmt[1] > pagewidth-1) {
+ call tbcigt (colptr[1], TBL_COL_NAME, colname, SZ_COLNAME)
+ call eprintf ("caution: column %s will be truncated\n")
+ call pargstr (colname)
+ lenfmt[1] = pagewidth-1
+ }
+
+ lentotal = lenfmt[1] + 1 # add one for leading space
+
+ # The loop continuation conditions are:
+ # the columns fit on the page,
+ # there are still columns that have not been included.
+ while (lentotal < pagewidth && lcp+ncp-1 < nprint) {
+ nextc = ncp + 1
+ colptr[nextc] = cptr[lcp+nextc-1]
+ # get lenfmt
+ lenfmt[nextc] = tpr_lenfmt (colptr[nextc], align, showunits)
+ lentotal = lentotal + lenfmt[nextc] + 1 # one for leading space
+ if (lentotal <= pagewidth)
+ ncp = nextc # = ncp + 1
+ }
+end
+
+
+
+# tpr_lenfmt -- get length of print format
+# This function returns the length of the print format for a column.
+# If align is true then the column name will be gotten, and the length
+# of the print format that is returned will be at least as large as
+# the length of the column name. The length will also be at least five,
+# since that is the length of the word INDEF.
+
+int procedure tpr_lenfmt (cptr, align, showunits)
+
+pointer cptr # i: pointer to column descriptor
+bool align # i: true ==> may increase length of print fmt
+bool showunits # i: also print column units?
+#--
+char colname[SZ_COLNAME] # name of column
+char colunits[SZ_COLUNITS] # column units
+int lenfmt # length of print format
+int len_name # length of column name
+int len_units # length of column units
+int tbcigi(), strlen()
+
+begin
+ lenfmt = tbcigi (cptr, TBL_COL_FMTLEN)
+
+ if ( align ) {
+
+ call tbcigt (cptr, TBL_COL_NAME, colname, SZ_COLNAME)
+ len_name = strlen (colname)
+
+ # Length >= length of column name or the word "INDEF".
+ lenfmt = max (lenfmt, len_name, 5)
+
+ if (showunits) {
+ call tbcigt (cptr, TBL_COL_UNITS, colunits, SZ_COLUNITS)
+ len_units = strlen (colunits)
+ lenfmt = max (lenfmt, len_units)
+ }
+ }
+ return (lenfmt)
+end
+
+
+
+# tpr_pfmt -- Get print formats
+# This procedure fills an array with print formats of the form %ws.
+# These can be used for printing the column names, units and data values.
+
+procedure tpr_pfmt (colptr, lenfmt, align, cn_fmt, ncp)
+
+pointer colptr[ncp] # i: array of column pointers
+int lenfmt[ncp] # i: array of lengths of print formats
+bool align # i: override print fmt to align col & name?
+char cn_fmt[SZ_FMT,ncp] # o: array of print formats
+int ncp # i: number of columns on current page
+#--
+char fmt[SZ_COLFMT] # unmodified print format as gotten from table
+int cn # loop index for column number
+
+begin
+ do cn = 1, ncp { # do for each column on page
+
+ # Get print format for current column.
+ call tbcigt (colptr[cn], TBL_COL_FMT, fmt, SZ_COLFMT)
+
+ cn_fmt[1,cn] = '%'
+ if (fmt[2] == '-') { # left justification
+ if (cn == ncp) {
+ call sprintf (cn_fmt[2,cn], SZ_FMT-1, "-s")
+ } else {
+ call sprintf (cn_fmt[2,cn], SZ_FMT-1, "-%ds")
+ call pargi (lenfmt[cn])
+ }
+ } else { # right justification
+ call sprintf (cn_fmt[2,cn], SZ_FMT-1, "%ds")
+ call pargi (lenfmt[cn])
+ }
+ }
+end
+
+
+# tpr_cnames_pr -- Print column names
+# This procedure prints the column names and units and an extra blank line.
+# A comment character ("#") is printed at the beginning of the line; this
+# is new as of 1995 Feb 16.
+
+procedure tpr_cnames_pr (colptr, cn_fmt, ncp,
+ showunits, rn_name, rn_units)
+
+pointer colptr[ncp] # i: array of column pointers
+char cn_fmt[SZ_FMT,ncp] # i: array of print formats
+int ncp # i: number of columns on current page
+bool showunits # i: also print column units?
+char rn_name[ARB] # i: column header for row number
+char rn_units[ARB] # i: printed below rn_name
+#--
+char colname[SZ_COLNAME] # column name
+char colunits[SZ_COLUNITS] # column units
+int cn # loop index for column number
+
+begin
+ call printf (rn_name) # "# row" or "#"
+
+ do cn = 1, ncp { # do for each column on page
+ call printf (" ")
+ call tbcigt (colptr[cn], TBL_COL_NAME, colname, SZ_COLNAME)
+ call printf (cn_fmt[1,cn])
+ call pargstr (colname)
+ }
+ call printf ("\n")
+
+ # Also print column units?
+ if (showunits) {
+ call printf (rn_units) # "# " or "#"
+ do cn = 1, ncp {
+ call printf (" ")
+ call tbcigt (colptr[cn], TBL_COL_UNITS, colunits, SZ_COLUNITS)
+ call printf (cn_fmt[1,cn])
+ call pargstr (colunits)
+ }
+ call printf ("\n")
+ }
+
+ call printf ("\n")
+end
+
+
+# prt_row -- print a row
+# This procedure prints the contents of one row.
+
+procedure prt_row (tp, colptr, cn_fmt, ncp,
+ linenum, pagelength, s_cp, lgroup,
+ rn_fmt, rn_name, rn_units,
+ rownum, showrow, orig_row, showhdr, showunits)
+
+pointer tp # i: pointer to table descriptor
+pointer colptr[ncp] # i: array of pointers to column descriptors
+char cn_fmt[SZ_FMT,ncp] # i: array of print formats
+int ncp # i: number of columns on current page
+int linenum # io: number of lines of data printed
+int pagelength # i: number of data lines per page
+pointer s_cp # i: pointer to column to control spacing
+int lgroup # i: print blank line after this many lines
+char rn_fmt[ARB] # i: format for printing row number
+char rn_name[ARB] # i: row number header: "# row"
+char rn_units[ARB] # i: "# " printed in the line for units
+int rownum # i: row number
+bool showrow # i: print row number?
+bool orig_row # i: show row number from underlying table?
+bool showhdr # i: was a header printed?
+bool showunits # i: print column units?
+#--
+pointer sp
+pointer cbuf # scratch for character-string buffer
+pointer nelem # array length for each column
+int max_nelem # maximum of array lengths
+bool has_arrays # true if any column contains arrays
+bool has_scalars # true if not all columns contain arrays
+int cn # loop index for column number
+int element # loop index for array element number
+int underlying_row # row number in underlying table
+int ip # first non-blank character in cbuf
+int s_flag # YES if we should print a line for spacing
+int tbcigi(), tbagtt()
+errchk tbsirow
+
+begin
+ call smark (sp)
+ call salloc (cbuf, SZ_LINE, TY_CHAR)
+ call salloc (nelem, ncp, TY_INT)
+
+ # Get the array length for each column.
+ max_nelem = 1 # initial values
+ if (showrow)
+ has_scalars = true # row number is a scalar
+ else
+ has_scalars = false
+
+ do cn = 1, ncp {
+ Memi[nelem+cn-1] = tbcigi (colptr[cn], TBL_COL_LENDATA)
+ if (Memi[nelem+cn-1] > max_nelem)
+ max_nelem = Memi[nelem+cn-1]
+ if (Memi[nelem+cn-1] == 1)
+ has_scalars = true
+ }
+ has_arrays = (max_nelem > 1)
+
+ # If all columns contain arrays, print a blank line as a separator.
+ if (!has_scalars && rownum > 1)
+ call printf ("\n")
+
+ # Loop over the number of elements in the longest array.
+ do element = 1, max_nelem {
+
+ # Print a page break if appropriate.
+ call tpr_break (linenum, pagelength, showhdr, showunits,
+ colptr, cn_fmt, ncp, rn_name, rn_units)
+
+ # Print a blank line if the value in the column has changed
+ # or if a group of lgroup lines has been printed.
+ call tpr_space (tp, s_cp, lgroup,
+ rownum, element, max_nelem, pagelength, linenum, s_flag)
+ if (s_flag == YES) {
+ call printf ("\n")
+ linenum = linenum + 1
+ # Check whether we should also print a page break.
+ call tpr_break (linenum, pagelength, showhdr, showunits,
+ colptr, cn_fmt, ncp, rn_name, rn_units)
+ }
+
+ if (showrow) {
+ if (element == 1) {
+ if (orig_row) {
+ call tbsirow (tp, rownum, underlying_row)
+ call printf (rn_fmt)
+ call pargi (underlying_row)
+ } else {
+ call printf (rn_fmt)
+ call pargi (rownum)
+ }
+ } else {
+ call printf (" ") # SZ_ROW_HDR blanks
+ }
+ } else if (showhdr) {
+ # Corresponds to the "#" at the beginning of header lines.
+ call printf (" ")
+ }
+
+ do cn = 1, ncp {
+
+ # Even if no row number is printed, start with a space.
+ call printf (" ") # space between columns
+
+ # Does the current column contain arrays?
+ if (Memi[nelem+cn-1] > 1) {
+
+ if (element <= Memi[nelem+cn-1]) {
+ if (tbagtt (tp, colptr[cn], rownum,
+ Memc[cbuf], SZ_LINE, element, 1) < 1)
+ call error (1, "can't read array element")
+ call tpr_noblank (Memc[cbuf], ip)
+ } else {
+ Memc[cbuf] = EOS
+ ip = 1
+ }
+ call printf (cn_fmt[1,cn])
+ call pargstr (Memc[cbuf+ip-1])
+
+ } else if (element == 1) {
+
+ # This is a scalar column.
+ call tbegtt (tp, colptr[cn], rownum, Memc[cbuf], SZ_LINE)
+ call tpr_noblank (Memc[cbuf], ip)
+ call printf (cn_fmt[1,cn])
+ call pargstr (Memc[cbuf+ip-1])
+
+ } else {
+
+ # Print a blank field for a scalar column to match array
+ # element > 1 for array column(s).
+ call printf (cn_fmt[1,cn])
+ call pargstr ("")
+ }
+ }
+ call printf ("\n")
+ linenum = linenum + 1
+ }
+ call sfree (sp)
+end
+
+procedure tpr_noblank (buf, ip)
+
+char buf[ARB] # io: input string (trailing blanks will be truncted)
+int ip # o: first non-blank character in buf
+#--
+int strlen()
+
+begin
+ ip = strlen (buf)
+ while (ip >= 1 && IS_WHITE(buf[ip])) { # trim trailing blanks
+ buf[ip] = EOS
+ ip = ip - 1
+ }
+ ip = 1
+ while (IS_WHITE(buf[ip])) # trim leading blanks
+ ip = ip + 1
+end