aboutsummaryrefslogtreecommitdiff
path: root/pkg/tbtables/tbzwrt.x
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tbtables/tbzwrt.x')
-rw-r--r--pkg/tbtables/tbzwrt.x257
1 files changed, 257 insertions, 0 deletions
diff --git a/pkg/tbtables/tbzwrt.x b/pkg/tbtables/tbzwrt.x
new file mode 100644
index 00000000..dcb19da4
--- /dev/null
+++ b/pkg/tbtables/tbzwrt.x
@@ -0,0 +1,257 @@
+include <ctype.h>
+include <tbset.h>
+include "tbtables.h"
+include "tbltext.h"
+
+define COLWIDTH 10 # width for holding print format for a column
+
+# tbzwrt -- write data values to a text file
+# The table data are written from memory to a temporary file, the original
+# text table is deleted, and then the temp file is renamed to the name
+# of the original text table. The file is closed by this routine, and
+# TB_FILE(tp) is set to NULL. If the output file is STDOUT or STDERR,
+# however, the data are just written to that fd.
+# A string will be enclosed in quotes if the string contains a blank or tab
+# or if it begins with a number or plus or minus. The latter is necessary
+# in case the table rows are reordered, putting this string in the first
+# row, because without quotes it would appear to be a numeric column.
+#
+# If no change has been made to the table, this routine returns without
+# doing anything.
+#
+# Phil Hodge, 25-Mar-1992 Subroutine created.
+# Phil Hodge, 20-Jul-1992 Don't quote string just because it begins with digit.
+# Phil Hodge, 25-Nov-1994 Don't quote if only leading or trailing blanks.
+# Phil Hodge, 2-Dec-1994 Include test on pform longer than SZ_OBUF.
+# Phil Hodge, 3-Apr-1995 Check TB_MODIFIED.
+# Phil Hodge, 2-Jan-1996 Quote blank strings; write INDEFI for undefined int.
+# Phil Hodge, 14-Apr-1998 Use COL_FMT directly, instead of calling tbcftg.
+# Phil Hodge, 12-Apr-1999 Check for STDERR, in addition to STDOUT.
+# Phil Hodge, 21-Apr-1999 Print each column one at a time, rather than
+# using one fprintf with all the print formats concatenated;
+# this is to avoid the line length limit imposed by SZ_OBUF.
+# Phil Hodge, 15-Jun-1999 Modify for table with explicit column definitions.
+
+procedure tbzwrt (tp)
+
+pointer tp # i: pointer to table descriptor
+#--
+pointer sp
+pointer temp # scratch for name of temporary table
+pointer cbuf # buffer for output string
+pointer colname # for comparing column name with "c<n>"
+pointer cp # pointer to column descriptor
+int fd # fd for temporary table
+int key # loop index for keyword number
+int row_1 # row number minus one
+int ncols # number of columns
+int colnum # column number
+int lenstr # length of a string table element
+int ip # offset for extracting a string in Memc
+int i # loop index
+int istart, iend # limits on i when looking for embedded blanks
+bool to_stdout # is output file STDOUT?
+bool quote # whitespace in string? then enclose in quotes
+char blank # ' ', as an argument to stridx
+int stridx()
+int strlen(), open()
+bool streq()
+
+begin
+ if (!TB_MODIFIED(tp))
+ return
+
+ blank = ' '
+
+ call smark (sp)
+ call salloc (temp, SZ_FNAME, TY_CHAR)
+ call salloc (cbuf, SZ_LINE, TY_CHAR)
+
+ ncols = TB_NCOLS(tp)
+
+ # If the output file is STDOUT or STDERR, we just write to it.
+ if (streq (TB_NAME(tp), "STDOUT")) {
+ to_stdout = true
+ fd = STDOUT
+ } else if (streq (TB_NAME(tp), "STDERR")) {
+ to_stdout = true
+ fd = STDERR
+ } else {
+ to_stdout = false
+ # Create temporary table (text file).
+ call mktemp ("tmp$texttbl", Memc[temp], SZ_FNAME)
+ fd = open (Memc[temp], NEW_FILE, TEXT_FILE)
+ }
+
+ # Check whether the table has been "converted" from simple format
+ # to explicit, by setting a column name or units. If any column
+ # name differs from "c<N>" (case insensitive; any N, not just the
+ # current column number), or if units have been specified for any
+ # column, the table subtype will be reset to explicit column def.
+ if (TB_SUBTYPE(tp) != TBL_SUBTYPE_EXPLICIT) {
+ call salloc (colname, SZ_COLNAME, TY_CHAR)
+ do colnum = 1, TB_NCOLS(tp) {
+ cp = TB_COLINFO(tp,colnum)
+ if (COL_UNITS(cp) != EOS) {
+ TB_SUBTYPE(tp) = TBL_SUBTYPE_EXPLICIT
+ break
+ }
+ call strcpy (COL_NAME(cp), Memc[colname], SZ_COLNAME)
+ call strlwr (Memc[colname])
+ if (Memc[colname] != 'c') {
+ TB_SUBTYPE(tp) = TBL_SUBTYPE_EXPLICIT
+ break
+ } else if (Memc[colname+1] == EOS || Memc[colname+1] == '0') {
+ # A column name for a simple text table is never just "c"
+ # without a number, and the number never begins with "0".
+ TB_SUBTYPE(tp) = TBL_SUBTYPE_EXPLICIT
+ break
+ } else {
+ do i = 2, SZ_COLNAME {
+ if (Memc[colname+i-1] == EOS)
+ break
+ if (!IS_DIGIT(Memc[colname+i-1])) {
+ TB_SUBTYPE(tp) = TBL_SUBTYPE_EXPLICIT
+ break
+ }
+ }
+ }
+ }
+ }
+
+ # If the table has explicit column definitions, write them.
+ if (TB_SUBTYPE(tp) == TBL_SUBTYPE_EXPLICIT) {
+
+ do colnum = 1, TB_NCOLS(tp) {
+
+ cp = TB_COLINFO(tp,colnum)
+
+ call fprintf (fd, "#c ")
+
+ quote = (stridx (blank, COL_NAME(cp)) > 0)
+ if (quote) {
+ call fprintf (fd, "\"%s\"")
+ } else {
+ call fprintf (fd, "%s")
+ }
+ call pargstr (COL_NAME(cp))
+
+ if (COL_DTYPE(cp) == TBL_TY_DOUBLE) {
+ call fprintf (fd, " d")
+ } else if (COL_DTYPE(cp) == TBL_TY_INT) {
+ call fprintf (fd, " i")
+ } else if (COL_DTYPE(cp) < 0) {
+ call fprintf (fd, " ch*%d")
+ call pargi (-COL_DTYPE(cp))
+ } else {
+ call fprintf (fd, " ch*1024")
+ }
+
+ call fprintf (fd, " %s")
+ call pargstr (COL_FMT(cp))
+
+ quote = (stridx (blank, COL_UNITS(cp)) > 0)
+ if (quote) {
+ call fprintf (fd, " \"%s\"")
+ } else {
+ call fprintf (fd, " %s")
+ }
+ call pargstr (COL_UNITS(cp))
+ call fprintf (fd, "\n")
+ }
+ }
+
+ # If there are keywords, write them.
+ if (TB_KEYLIST_PTR(tp) != NULL) {
+ do key = 1, TB_NPAR(tp) {
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[TB_KEYWORD(tp,key)])
+ }
+ }
+
+ # Write the comment buffer to the output file.
+ if (TB_COMMENT(tp) != NULL) {
+ if (Memc[TB_COMMENT(tp)] != EOS)
+ call putline (fd, Memc[TB_COMMENT(tp)])
+ }
+
+ # Print each row to the file.
+ do row_1 = 0, TB_NROWS(tp) - 1 { # zero indexed
+
+ # Print each column in the current row.
+ do colnum = 1, ncols {
+
+ cp = TB_COLINFO(tp,colnum)
+
+ if (colnum > 1) # separator between columns
+ call fprintf (fd, " ")
+
+ call fprintf (fd, COL_FMT(cp)) # use this format
+
+ # Now call the appropriate parg routine.
+ if (COL_DTYPE(cp) == TY_DOUBLE) {
+
+ call pargd (Memd[COL_OFFSET(cp) + row_1])
+
+ } else if (COL_DTYPE(cp) == TY_INT) {
+
+ if (IS_INDEFI (Memi[COL_OFFSET(cp) + row_1]))
+ call pargstr ("INDEFI")
+ else
+ call pargi (Memi[COL_OFFSET(cp) + row_1])
+
+ } else { # string
+
+ lenstr = -COL_DTYPE(cp) + 1 # one for EOS
+ ip = row_1 * lenstr # offset to element
+
+ # Check for embedded whitespace.
+ quote = false # initial value
+
+ # istart and iend are zero indexed
+ istart = 0
+ while (IS_WHITE(Memc[COL_OFFSET(cp)+ip+istart]))
+ istart = istart + 1 # skip leading blanks
+ iend = strlen (Memc[COL_OFFSET(cp)+ip]) - 1
+ if (istart > iend)
+ quote = true # null or all blank
+ while (iend > istart &&
+ IS_WHITE(Memc[COL_OFFSET(cp)+ip+iend])) {
+ iend = iend - 1 # skip trailing blanks
+ }
+
+ do i = istart, iend { # zero indexed
+ if (IS_WHITE(Memc[COL_OFFSET(cp)+ip+i])) {
+ quote = true
+ break
+ }
+ }
+
+ if (quote) {
+ Memc[cbuf] = '"'
+ Memc[cbuf+1] = EOS
+ call strcat (Memc[COL_OFFSET(cp)+ip], Memc[cbuf],
+ SZ_LINE)
+ call strcat ("\"", Memc[cbuf], SZ_LINE)
+ call pargstr (Memc[cbuf])
+ } else {
+ call pargstr (Memc[COL_OFFSET(cp)+ip])
+ }
+ }
+ }
+ call fprintf (fd, "\n")
+ }
+
+ call close (fd)
+
+ if (!to_stdout) {
+ # Close and delete the original text table, and rename the
+ # new (temporary) file back to the name of the original.
+ call close (TB_FILE(tp))
+ call delete (TB_NAME(tp))
+ call rename (Memc[temp], TB_NAME(tp))
+ }
+ TB_FILE(tp) = NULL # to indicate that it's closed
+
+ call sfree (sp)
+end