aboutsummaryrefslogtreecommitdiff
path: root/noao/digiphot/ptools/pconvert
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /noao/digiphot/ptools/pconvert
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'noao/digiphot/ptools/pconvert')
-rw-r--r--noao/digiphot/ptools/pconvert/mkpkg14
-rw-r--r--noao/digiphot/ptools/pconvert/ptconvert.x236
-rw-r--r--noao/digiphot/ptools/pconvert/ptdeftable.x375
-rw-r--r--noao/digiphot/ptools/pconvert/ptstrwrd.x51
-rw-r--r--noao/digiphot/ptools/pconvert/t_pconvert.x53
5 files changed, 729 insertions, 0 deletions
diff --git a/noao/digiphot/ptools/pconvert/mkpkg b/noao/digiphot/ptools/pconvert/mkpkg
new file mode 100644
index 00000000..362576cb
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/mkpkg
@@ -0,0 +1,14 @@
+# PCONVERT task
+
+$checkout libpkg.a ".."
+$update libpkg.a
+$checkin libpkg.a ".."
+$exit
+
+libpkg.a:
+ ptconvert.x <error.h> <evexpr.h> \
+ <tbset.h> ../../lib/ptkeysdef.h
+ ptdeftable.x ../../lib/ptkeysdef.h <tbset.h> <ctype.h>
+ ptstrwrd.x
+ t_pconvert.x <fset.h>
+ ;
diff --git a/noao/digiphot/ptools/pconvert/ptconvert.x b/noao/digiphot/ptools/pconvert/ptconvert.x
new file mode 100644
index 00000000..8ac97ac8
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/ptconvert.x
@@ -0,0 +1,236 @@
+include <error.h>
+include <evexpr.h>
+include <tbset.h>
+include "../../lib/ptkeysdef.h"
+
+# PT_APCONVERT -- Procedure to select records from a text file in pseudo list
+# format.
+
+procedure pt_convert (fd, td, fields, expr, append)
+
+int fd # text file descriptor
+int td # table file descriptor
+char fields[ARB] # fields to be output
+char expr[ARB] # boolean expression to be evaluated
+int append # append to an existing table
+
+bool oexpr
+int nchars, nunique, uunique, funique, ncontinue, recptr, rownum
+int ntotkeys, first_rec, printall, table_defined
+pointer sp, line, colpoints, key, o
+
+bool streq()
+extern pt_getop ()
+int getline(), strncmp(), tbpsta(), pt_deftable(), pt_apptable()
+pointer evexpr(), locpr()
+real asumi()
+
+begin
+
+ # Allocate temporary working space.
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Initialize the keys structure.
+ call pt_kyinit (key)
+
+ # Initialize the counters.
+ nunique = 0
+ uunique = 0
+ funique = 0
+
+ # Initalize the record reading code.
+ table_defined = NO
+ first_rec = YES
+ recptr = 1
+ ncontinue = 0
+
+ # Initialize the expression evaluator.
+ o = NULL
+ if (streq (expr, "yes")) {
+ oexpr = true
+ printall = YES
+ } else {
+ oexpr = false
+ printall = NO
+ }
+
+ # Initialize the pointer for writing rows.
+ if (append == YES)
+ rownum = tbpsta (td, TBL_NROWS)
+ else
+ rownum = 0
+
+ # Loop over the text file records.
+ nchars = getline (fd, Memc[line])
+ while (nchars != EOF) {
+
+ # Determine the type of record.
+ if (Memc[line] == KY_CHAR_POUND) {
+ if (strncmp (Memc[line], KY_CHAR_KEYWORD, KY_LEN_STR) == 0) {
+ call pt_kyadd (key, Memc[line], nchars)
+ } else if (strncmp (Memc[line], KY_CHAR_NAME,
+ KY_LEN_STR) == 0) {
+ nunique = nunique + 1
+ call pt_kname (key, Memc[line], nchars, nunique)
+ } else if (strncmp (Memc[line], KY_CHAR_UNITS,
+ KY_LEN_STR) == 0) {
+ uunique = uunique + 1
+ call pt_knunits (key, Memc[line], nchars, uunique)
+ } else if (strncmp (Memc[line], KY_CHAR_FORMAT,
+ KY_LEN_STR) == 0) {
+ funique = funique + 1
+ call pt_knformats (key, Memc[line], nchars, funique)
+ }
+
+ } else if (Memc[line] == KY_CHAR_NEWLINE) {
+ # skip blank lines
+
+ } else {
+
+ # Construct the table record.
+ call pt_mkrec (key, Memc[line], nchars, first_rec, recptr,
+ ncontinue)
+
+ # Construct output record when there is no continuation char.
+ if (Memc[line+nchars-2] != KY_CHAR_CONT) {
+
+ # Construct the output table if not defined.
+ if (table_defined == NO) {
+
+ # Compute the maximum number of keys.
+ ntotkeys = nint (asumi (Memi[KY_NELEMS(key)],
+ KY_NKEYS(key)))
+
+ # Allocate space for the column pointers.
+ call salloc (colpoints, ntotkeys, TY_INT)
+
+ # Initialize the table.
+ if (append == NO) {
+ if (pt_deftable (td, key, fields,
+ Memi[colpoints]) <= 0)
+ break
+ } else if (append == YES) {
+ if (pt_apptable (td, key, fields,
+ Memi[colpoints]) <= 0)
+ break
+ }
+
+ table_defined = YES
+ }
+
+ # Evaluate the expression.
+ iferr {
+ if (printall == NO) {
+ call pt_apset (key)
+ o = evexpr (expr, locpr (pt_getop), 0)
+ if (O_TYPE(o) != TY_BOOL)
+ call error (0, "Expression must be a boolean")
+ oexpr = O_VALB(o)
+ }
+ } then {
+ call erract (EA_WARN)
+ call xev_freeop (o)
+ call mfree (o, TY_STRUCT)
+ break
+ }
+
+ # Construct the output record.
+ if (oexpr) {
+ rownum = rownum + 1
+ call pt_putrec (td, Memi[colpoints], key, rownum)
+ }
+
+ # Get ready for next record.
+ ncontinue = 0
+ recptr = 1
+ first_rec = NO
+ if (o != NULL) {
+ call xev_freeop (o)
+ call mfree (o, TY_STRUCT)
+ }
+ }
+ }
+
+ # Read the next line.
+ nchars = getline (fd, Memc[line])
+ }
+
+ # Free the keys structure.
+ call pt_kyfree (key)
+ call sfree (sp)
+end
+
+
+# PT_PUTREC -- Add a row to the table.
+
+procedure pt_putrec (td, colpoints, key, rownum)
+
+pointer td # table descriptor
+pointer colpoints[ARB] # pointers for columns
+pointer key # key structure
+int rownum # row number
+
+int i, index, elem, kip, maxch, n, nk, ncols
+int number, datatype, lendata, lenfmt, ival
+pointer sp, colname, colunits, colfmt, str
+real rval
+bool streq()
+int ctor(), ctoi()
+
+begin
+ call smark (sp)
+ call salloc (colname, SZ_COLNAME+1, TY_CHAR)
+ call salloc (colunits, SZ_PARREC+1, TY_CHAR)
+ call salloc (colfmt, SZ_PARREC+1, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # For each selected field move into the table
+ ncols = 0
+ do i = 1, KY_NSELECT(key) {
+
+ # Get the pointer to the desired value.
+ index = Memi[KY_SELECT(key)+i-1]
+ elem = Memi[KY_ELEM_SELECT(key)+i-1]
+ maxch = Memi[KY_LEN_SELECT(key)+i-1]
+ kip = Memi[KY_PTRS(key)+index-1] + (elem - 1) * maxch
+
+ # Trim leading and trailing whitespace from the value and
+ # copy value to output buffer.
+
+ for (n = 0; Memc[kip] == ' '; n = n + 1)
+ kip = kip + 1
+ for (nk = 0; Memc[kip+nk] != ' ' && n <= maxch; nk = nk + 1)
+ n = n + 1
+ call strcpy (Memc[kip], Memc[str], nk)
+
+ # Find info about this column.
+ ncols = ncols + 1
+ call tbcinf (colpoints[ncols], number, Memc[colname],
+ Memc[colunits], Memc[colfmt], datatype, lendata, lenfmt)
+
+ # Move the selected value into the column.
+ kip = 1
+ switch (datatype) {
+ case TY_INT:
+ if (ctoi (Memc[str], kip, ival) <= 0)
+ call tbrpti (td, colpoints[ncols], INDEFI, 1, rownum)
+ else
+ call tbrpti (td, colpoints[ncols], ival, 1, rownum)
+ case TY_REAL:
+ if (ctor (Memc[str], kip, rval) <= 0)
+ call tbrptr (td, colpoints[ncols], INDEFR, 1, rownum)
+ else
+ call tbrptr (td, colpoints[ncols], rval, 1, rownum)
+ case TY_BOOL:
+ if (streq ("yes", Memc[str]))
+ call tbrptb (td, colpoints[ncols], true, 1, rownum)
+ else
+ call tbrptb (td, colpoints[ncols], false, 1, rownum)
+ default:
+ call tbrptt (td, colpoints[ncols], Memc[str], nk, 1, rownum)
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/digiphot/ptools/pconvert/ptdeftable.x b/noao/digiphot/ptools/pconvert/ptdeftable.x
new file mode 100644
index 00000000..86fb2c35
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/ptdeftable.x
@@ -0,0 +1,375 @@
+#include <ctype.h>
+include <tbset.h>
+include "../../lib/ptkeysdef.h"
+
+# PT_DEFTABLE -- Set up and create the table for the conversion of
+# the APPHOT text file.
+
+int procedure pt_deftable (td, key, fields, columns)
+
+pointer td # output table descriptor
+pointer key # key structure
+char fields[ARB] # fields to be output to the table
+int columns[ARB] # pointer to array of column pointers
+
+int ncols
+int pt_defcols()
+
+begin
+ # Define the table columns.
+ ncols = pt_defcols (td, key, fields, columns)
+ if (ncols <= 0)
+ return (0)
+
+ # Define the table header.
+ call pt_defheader (td, key)
+
+ return (ncols)
+end
+
+
+# PT_DEFHEADER -- Define the header structure.
+
+procedure pt_defheader (td, key)
+
+pointer td # table descriptor
+pointer key # pointer to the keys structure
+
+int i, index, type, len, ival, ip
+pointer sp, kname, value, ptr
+real rval
+bool streq()
+int pt_strwrd(), pt_kstati(), ctoi(), ctor()
+
+begin
+ call smark (sp)
+ call salloc (kname, SZ_KEYWORD, TY_CHAR)
+ call salloc (value, KY_SZPAR, TY_CHAR)
+
+ # Define the columns determining datatype from the format string.
+ do i = 1, KY_NPKEYS(key) {
+
+ index = pt_strwrd (i, Memc[kname], SZ_KEYWORD, Memc[KY_WORDS(key)])
+ if (index <= 0)
+ next
+
+ ptr = Memi[KY_PTRS(key)+index-1]
+ len = pt_kstati (key, Memc[kname], KY_LENGTH)
+ call strcpy (Memc[ptr], Memc[value], len)
+ type = pt_kstati (key, Memc[kname], KY_DATATYPE)
+
+ switch (type) {
+ case TY_INT:
+ ip = 1
+ if (ctoi (Memc[value], ip, ival) <= 0)
+ call tbhadi (td, Memc[kname], INDEFI)
+ else
+ call tbhadi (td, Memc[kname], ival)
+ case TY_REAL:
+ ip = 1
+ if (ctor (Memc[value], ip, rval) <= 0)
+ call tbhadr (td, Memc[kname], INDEFR)
+ else
+ call tbhadr (td, Memc[kname], rval)
+ case TY_BOOL:
+ if (streq ("yes", Memc[value]))
+ call tbhadb (td, Memc[kname], true)
+ else
+ call tbhadb (td, Memc[kname], false)
+ default:
+ call tbhadt (td, Memc[kname], Memc[value])
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# PT_DEFCOLS -- Define the data columns to be output.
+
+int procedure pt_defcols (td, key, fields, columns)
+
+pointer td # table Descriptor
+pointer key # key structure
+char fields[ARB] # fields selected
+pointer columns[ARB] # array of pointers for columns
+
+int max_nkeys, index, ncols, element, nelems, type, len
+pointer sp, kname, aranges, ranges, rangeset, colname, colunits, colformat
+pointer list
+
+int pt_gnfn(), strdic(), pt_ranges(), get_next_number()
+int decode_ranges(), pt_kstati()
+pointer pt_ofnl()
+real asumi()
+errchk tbcdef()
+
+begin
+ # Allocate working space.
+
+ call smark (sp)
+ call salloc (kname, KY_SZPAR, TY_CHAR)
+ call salloc (aranges, SZ_FNAME, TY_CHAR)
+ call salloc (ranges, SZ_FNAME, TY_CHAR)
+ call salloc (rangeset, 3 * KY_MAXNRANGES, TY_INT)
+
+ call salloc (colname, SZ_COLNAME, TY_CHAR)
+ call salloc (colunits, SZ_COLUNITS, TY_CHAR)
+ call salloc (colformat, SZ_COLFMT, TY_CHAR)
+
+ # Initialize the select buffers. The select keyword, format
+ # and units string buffers are not necessary in this application.
+
+ max_nkeys = nint (asumi (Memi[KY_NELEMS(key)], KY_NKEYS(key)))
+ if (KY_SELECT(key) != NULL)
+ call mfree (KY_SELECT(key), TY_INT)
+ call malloc (KY_SELECT(key), max_nkeys, TY_INT)
+ if (KY_ELEM_SELECT(key) != NULL)
+ call mfree (KY_ELEM_SELECT(key), TY_INT)
+ call malloc (KY_ELEM_SELECT(key), max_nkeys, TY_INT)
+ if (KY_LEN_SELECT(key) != NULL)
+ call mfree (KY_LEN_SELECT(key), TY_INT)
+ call malloc (KY_LEN_SELECT(key), max_nkeys, TY_INT)
+
+ # Initialize the number of columns.
+ ncols = 0
+
+ # Open the list of fields.
+ list = pt_ofnl (key, fields)
+
+ # Loop over the fields.
+ while (pt_gnfn (list, Memc[kname], Memc[aranges], KY_SZPAR) != EOF) {
+
+ # Find location of the field in the keyword dictionary and
+ # expand the ranges string if it is defined.
+ index = strdic (Memc[kname], Memc[kname], KY_SZPAR,
+ Memc[KY_WORDS(key)])
+ if (pt_ranges (Memc[aranges], Memc[ranges], element, SZ_LINE) ==
+ ERR)
+ call error (0, "Cannot decode DAOPHOT range string")
+
+ # The field was not found.
+ if (index == 0) {
+ next
+
+ # Reject keyword fields.
+ } else if (index <= KY_NPKEYS (key)) {
+ next
+
+ # The field is single valued.
+ } else if (Memi[KY_NELEMS(key)+index-1] == 1) {
+
+ # Enter the pointers into the select buffer.
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = 1
+ len = pt_kstati (key, Memc[kname], KY_LENGTH)
+ Memi[KY_LEN_SELECT(key)+ncols] = len
+ ncols = ncols + 1
+
+ # Get the column name, the units and the formats.
+ call strcpy (Memc[kname], Memc[colname], SZ_COLNAME)
+ call pt_kstats (key, Memc[kname], KY_UNITSTR, Memc[colunits],
+ SZ_COLUNITS)
+ call pt_kstats (key, Memc[kname], KY_FMTSTR, Memc[colformat],
+ SZ_COLFMT)
+
+ # Create the column determining the datatype from the
+ # format string.
+ type = pt_kstati (key, Memc[kname], KY_DATATYPE)
+ if (type != TY_CHAR)
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], type, 1, 1)
+ else
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], -len, 1, 1)
+
+ # The field is multi-valued.
+ } else {
+
+ if (Memc[ranges] == EOS) {
+ call sprintf (Memc[ranges], SZ_FNAME, "1-%d")
+ call pargi (Memi[KY_NELEMS(key)+index-1])
+ }
+ if (decode_ranges (Memc[ranges], Memi[rangeset], KY_MAXNRANGES,
+ nelems) == ERR)
+ call error (0, "Cannot decode ranges string")
+
+ nelems = 0
+ while (get_next_number (Memi[rangeset], nelems) != EOF) {
+ if (nelems < 1 || nelems > Memi[KY_NELEMS(key)+index-1])
+ break
+
+ len = pt_kstati (key, Memc[kname], KY_LENGTH)
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = nelems
+ Memi[KY_LEN_SELECT(key)+ncols] = len
+ ncols = ncols + 1
+
+ # Get the column name, units and format.
+ call sprintf (Memc[colname], SZ_COLNAME, "%s[%d]")
+ call pargstr (Memc[kname])
+ call pargi (nelems)
+ call pt_kstats (key, Memc[kname], KY_UNITSTR,
+ Memc[colunits], SZ_COLUNITS)
+ call pt_kstats (key, Memc[kname], KY_FMTSTR,
+ Memc[colformat], SZ_COLFMT)
+
+ # Create the column determining the datatype from the
+ # format string.
+ type = pt_kstati (key, Memc[kname], KY_DATATYPE)
+ if (type != TY_CHAR)
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], type, 1, 1)
+ else
+ call tbcdef (td, columns[ncols], Memc[colname],
+ Memc[colunits], Memc[colformat], -len, 1, 1)
+ }
+ }
+ }
+
+ # Create the table.
+ call tbpset (td, TBL_MAXPAR, KY_NPKEYS(key))
+ call tbtcre (td)
+
+ # Free the space
+ call pt_cfnl (list)
+ call sfree (sp)
+
+ # Reallocate select buffer space
+ KY_NSELECT(key) = ncols
+ call realloc (KY_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_ELEM_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_LEN_SELECT(key), KY_NSELECT(key), TY_INT)
+
+ return (ncols)
+end
+
+
+# PT_APPTABLE -- Find the array of column pointers for appending to an
+# existing ST table.
+
+int procedure pt_apptable (td, key, fields, columns)
+
+pointer td # the table descriptor
+pointer key # key structure
+char fields[ARB] # string containing fields to include in table
+pointer columns[ARB] # Array of pointers for columns
+
+int max_nkeys, index, ncols, element, nelems
+pointer list, sp, kname, aranges, ranges, rangeset, colname
+int pt_gnfn(), strdic(), pt_ranges(), get_next_number(), decode_ranges()
+int pt_kstati()
+pointer pt_ofnl()
+real asumi()
+
+begin
+ # Allocate buffer space.
+ call smark (sp)
+ call salloc (kname, KY_SZPAR, TY_CHAR)
+ call salloc (aranges, SZ_FNAME, TY_CHAR)
+ call salloc (ranges, SZ_FNAME, TY_CHAR)
+ call salloc (rangeset, 3 * KY_MAXNRANGES, TY_INT)
+ call salloc (colname, SZ_COLNAME, TY_CHAR)
+
+ # Initialize the select buffers. The select keyword, format
+ # and units string buffers are not necessary in this application.
+
+ max_nkeys = nint (asumi (Memi[KY_NELEMS(key)], KY_NKEYS(key)))
+ max_nkeys = nint (asumi (Memi[KY_NELEMS(key)], KY_NKEYS(key)))
+ if (KY_SELECT(key) != NULL)
+ call mfree (KY_SELECT(key), TY_INT)
+ call malloc (KY_SELECT(key), max_nkeys, TY_INT)
+ if (KY_ELEM_SELECT(key) != NULL)
+ call mfree (KY_ELEM_SELECT(key), TY_INT)
+ call malloc (KY_ELEM_SELECT(key), max_nkeys, TY_INT)
+ if (KY_LEN_SELECT(key) != NULL)
+ call mfree (KY_LEN_SELECT(key), TY_INT)
+ call malloc (KY_LEN_SELECT(key), max_nkeys, TY_INT)
+
+ # Initialize the number of columns.
+ ncols = 0
+
+ # Initialize the list of fields.
+ ncols = 0
+ list = pt_ofnl (key, fields)
+
+ # Loop over the fields.
+ while (pt_gnfn (list, Memc[kname], Memc[aranges], KY_SZPAR) != EOF) {
+
+ # Find the column.
+ index = strdic (Memc[kname], Memc[kname], KY_SZPAR,
+ Memc[KY_WORDS(key)])
+ if (pt_ranges (Memc[aranges], Memc[ranges], element,
+ SZ_LINE) == ERR)
+ call error (0, "Cannot decode DAOPHOT range string")
+
+ # Skip if the column does exist in the text database.
+ if (index == 0)
+ next
+
+ # Skip the header keywords.
+ else if (index <= KY_NPKEYS (key))
+ next
+
+ # Convert single-valued elements.
+ else if (Memi[KY_NELEMS(key)+index-1] == 1) {
+
+ call strcpy (Memc[kname], Memc[colname], SZ_COLNAME)
+ call tbcfnd (td, Memc[colname], columns[ncols+1], 1)
+ if (columns[ncols+1] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (Memc[colname])
+ } else {
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = 1
+ Memi[KY_LEN_SELECT(key)+ncols] = pt_kstati (key,
+ Memc[kname], KY_LENGTH)
+ ncols = ncols + 1
+ }
+
+ # Convert multivalued elements.
+ } else {
+
+ if (Memc[ranges] == EOS) {
+ call sprintf (Memc[ranges], SZ_FNAME, "1-%d")
+ call pargi (Memi[KY_NELEMS(key)+index-1])
+ }
+ if (decode_ranges (Memc[ranges], Memi[rangeset], KY_MAXNRANGES,
+ nelems) == ERR)
+ call error (0, "Cannot decode ranges string")
+
+ nelems = 0
+ while (get_next_number (Memi[rangeset], nelems) != EOF) {
+ if (nelems < 1 || nelems > Memi[KY_NELEMS(key)+index-1])
+ break
+ call sprintf (Memc[colname], SZ_COLNAME, "%s[%d]")
+ call pargstr (Memc[kname])
+ call pargi (nelems)
+ call tbcfnd (td, Memc[colname], columns[ncols+1], 1)
+ if (columns[ncols+1] == NULL) {
+ call eprintf ("Column %s not found\n")
+ call pargstr (Memc[colname])
+ } else {
+ Memi[KY_SELECT(key)+ncols] = index
+ Memi[KY_ELEM_SELECT(key)+ncols] = nelems
+ Memi[KY_LEN_SELECT(key)+ncols] = pt_kstati (key,
+ Memc[kname], KY_LENGTH)
+ ncols = ncols + 1
+ }
+
+ }
+ }
+ }
+
+ # Free the space
+ call pt_cfnl (list)
+ call sfree (sp)
+
+ # Reallocate select buffer space
+ KY_NSELECT(key) = ncols
+ call realloc (KY_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_ELEM_SELECT(key), KY_NSELECT(key), TY_INT)
+ call realloc (KY_LEN_SELECT(key), KY_NSELECT(key), TY_INT)
+
+ return (ncols)
+end
diff --git a/noao/digiphot/ptools/pconvert/ptstrwrd.x b/noao/digiphot/ptools/pconvert/ptstrwrd.x
new file mode 100644
index 00000000..31a9974b
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/ptstrwrd.x
@@ -0,0 +1,51 @@
+# PT_STRWRD -- Search a dictionary string for a given string index number.
+# This is the opposite function of strdic(), that returns the index for
+# given string. The entries in the dictionary string are separated by
+# a delimiter character which is the first character of the dictionary
+# string. The index of the string found is returned as the function value.
+# Otherwise, if there is no string for that index, a zero is returned.
+
+int procedure pt_strwrd (index, outstr, maxch, dict)
+
+int index # String index
+char outstr[ARB] # Output string as found in dictionary
+int maxch # Maximum length of output string
+char dict[ARB] # Dictionary string
+
+int i, len, start, count
+
+int strlen()
+
+begin
+ # Clear output string
+ outstr[1] = EOS
+
+ # Return if the dictionary is not long enough
+ if (dict[1] == EOS)
+ return (0)
+
+ # Initialize counters
+ count = 1
+ len = strlen (dict)
+
+ # Search the dictionary string. This loop only terminates
+ # successfully if the index is found. Otherwise the procedure
+ # returns with and error condition.
+ for (start = 2; count < index; start = start + 1) {
+ if (dict[start] == dict[1])
+ count = count + 1
+ if (start == len)
+ return (0)
+ }
+
+ # Extract the output string from the dictionary
+ for (i = start; dict[i] != EOS && dict[i] != dict[1]; i = i + 1) {
+ if (i - start + 1 > maxch)
+ break
+ outstr[i - start + 1] = dict[i]
+ }
+ outstr[i - start + 1] = EOS
+
+ # Return index for output string
+ return (count)
+end
diff --git a/noao/digiphot/ptools/pconvert/t_pconvert.x b/noao/digiphot/ptools/pconvert/t_pconvert.x
new file mode 100644
index 00000000..fafcbf5f
--- /dev/null
+++ b/noao/digiphot/ptools/pconvert/t_pconvert.x
@@ -0,0 +1,53 @@
+include <fset.h>
+
+# T_PCONVERT -- Procedure to convert the records within a text file into
+# an STSDAS Table.
+
+procedure t_pconvert ()
+
+pointer text # pointer to name of text file
+pointer fields # pointer list of fields
+pointer table # pointer to STSDAS table
+pointer expr # Pointer to boolean expression
+int append # open file in append mode
+
+int fd, td
+pointer sp
+bool clgetb()
+int open(), btoi(), fstati(), tbtopn()
+
+begin
+
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (text, SZ_LINE, TY_CHAR)
+ call salloc (fields, SZ_LINE, TY_CHAR)
+ call salloc (table, SZ_LINE, TY_CHAR)
+ call salloc (expr, SZ_LINE, TY_CHAR)
+
+ # Get the parameters.
+ call clgstr ("textfile", Memc[text], SZ_LINE)
+ call clgstr ("table", Memc[table], SZ_LINE)
+ call clgstr ("fields", Memc[fields], SZ_LINE)
+ call strupr (Memc[fields])
+ call clgstr ("expr", Memc[expr], SZ_LINE)
+ append = btoi (clgetb ("append"))
+
+ # Open the table.
+ fd = open (Memc[text], READ_ONLY, TEXT_FILE)
+ if (append == YES)
+ td = tbtopn (Memc[table], READ_WRITE, 0)
+ else
+ td = tbtopn (Memc[table], NEW_FILE, 0)
+
+ # Select records.
+ call pt_convert (fd, td, Memc[fields], Memc[expr], append)
+
+ # Close up.
+ call close (fd)
+ call tbtclo (td)
+ call sfree (sp)
+end