aboutsummaryrefslogtreecommitdiff
path: root/pkg/xtools/catquery
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /pkg/xtools/catquery
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/xtools/catquery')
-rw-r--r--pkg/xtools/catquery/cq.h100
-rw-r--r--pkg/xtools/catquery/cqdb.x442
-rw-r--r--pkg/xtools/catquery/cqdef.h133
-rw-r--r--pkg/xtools/catquery/cqdtype.x53
-rw-r--r--pkg/xtools/catquery/cqget.x225
-rw-r--r--pkg/xtools/catquery/cqgfields.x483
-rw-r--r--pkg/xtools/catquery/cqgqpars.x99
-rw-r--r--pkg/xtools/catquery/cqgrecords.x83
-rw-r--r--pkg/xtools/catquery/cqiminfo.x220
-rw-r--r--pkg/xtools/catquery/cqimquery.x931
-rw-r--r--pkg/xtools/catquery/cqistat.x161
-rw-r--r--pkg/xtools/catquery/cqlocate.x40
-rw-r--r--pkg/xtools/catquery/cqmap.x112
-rw-r--r--pkg/xtools/catquery/cqnqpars.x18
-rw-r--r--pkg/xtools/catquery/cqquery.x998
-rw-r--r--pkg/xtools/catquery/cqrinfo.x390
-rw-r--r--pkg/xtools/catquery/cqrstat.x171
-rw-r--r--pkg/xtools/catquery/cqsetcat.x293
-rw-r--r--pkg/xtools/catquery/cqsqpars.x135
-rw-r--r--pkg/xtools/catquery/cqstat.x74
-rw-r--r--pkg/xtools/catquery/cqwrdstr.x56
-rw-r--r--pkg/xtools/catquery/doc/README322
-rw-r--r--pkg/xtools/catquery/doc/catalogs.hlp233
-rw-r--r--pkg/xtools/catquery/doc/catquery.hd56
-rw-r--r--pkg/xtools/catquery/doc/catquery.hlp322
-rw-r--r--pkg/xtools/catquery/doc/catquery.men28
-rw-r--r--pkg/xtools/catquery/doc/ccsystems.hlp134
-rw-r--r--pkg/xtools/catquery/doc/cqfimquery.hlp39
-rw-r--r--pkg/xtools/catquery/doc/cqfinfo.hlp85
-rw-r--r--pkg/xtools/catquery/doc/cqfinfon.hlp79
-rw-r--r--pkg/xtools/catquery/doc/cqfquery.hlp78
-rw-r--r--pkg/xtools/catquery/doc/cqget.hlp130
-rw-r--r--pkg/xtools/catquery/doc/cqgnrecord.hlp61
-rw-r--r--pkg/xtools/catquery/doc/cqgqpar.hlp72
-rw-r--r--pkg/xtools/catquery/doc/cqgqparn.hlp73
-rw-r--r--pkg/xtools/catquery/doc/cqgrecord.hlp46
-rw-r--r--pkg/xtools/catquery/doc/cqgvalc.hlp42
-rw-r--r--pkg/xtools/catquery/doc/cqgvald.hlp40
-rw-r--r--pkg/xtools/catquery/doc/cqgvali.hlp40
-rw-r--r--pkg/xtools/catquery/doc/cqgvall.hlp40
-rw-r--r--pkg/xtools/catquery/doc/cqgvalr.hlp40
-rw-r--r--pkg/xtools/catquery/doc/cqgvals.hlp41
-rw-r--r--pkg/xtools/catquery/doc/cqhinfo.hlp39
-rw-r--r--pkg/xtools/catquery/doc/cqhinfon.hlp47
-rw-r--r--pkg/xtools/catquery/doc/cqimclose.hlp24
-rw-r--r--pkg/xtools/catquery/doc/cqimquery.hlp44
-rw-r--r--pkg/xtools/catquery/doc/cqistati.hlp49
-rw-r--r--pkg/xtools/catquery/doc/cqistats.hlp56
-rw-r--r--pkg/xtools/catquery/doc/cqistatt.hlp55
-rw-r--r--pkg/xtools/catquery/doc/cqkinfo.hlp65
-rw-r--r--pkg/xtools/catquery/doc/cqkinfon.hlp73
-rw-r--r--pkg/xtools/catquery/doc/cqlocate.hlp35
-rw-r--r--pkg/xtools/catquery/doc/cqlocaten.hlp47
-rw-r--r--pkg/xtools/catquery/doc/cqmap.hlp33
-rw-r--r--pkg/xtools/catquery/doc/cqnqpars.hlp32
-rw-r--r--pkg/xtools/catquery/doc/cqquery.hlp35
-rw-r--r--pkg/xtools/catquery/doc/cqrclose.hlp24
-rw-r--r--pkg/xtools/catquery/doc/cqrstati.hlp53
-rw-r--r--pkg/xtools/catquery/doc/cqrstats.hlp54
-rw-r--r--pkg/xtools/catquery/doc/cqrstatt.hlp56
-rw-r--r--pkg/xtools/catquery/doc/cqsetcat.hlp35
-rw-r--r--pkg/xtools/catquery/doc/cqsetcatn.hlp35
-rw-r--r--pkg/xtools/catquery/doc/cqsqpar.hlp39
-rw-r--r--pkg/xtools/catquery/doc/cqsqparn.hlp39
-rw-r--r--pkg/xtools/catquery/doc/cqstati.hlp61
-rw-r--r--pkg/xtools/catquery/doc/cqstats.hlp48
-rw-r--r--pkg/xtools/catquery/doc/cqstatt.hlp45
-rw-r--r--pkg/xtools/catquery/doc/cqunmap.hlp26
-rw-r--r--pkg/xtools/catquery/doc/cqwinfo.hlp65
-rw-r--r--pkg/xtools/catquery/doc/cqwinfon.hlp75
-rw-r--r--pkg/xtools/catquery/doc/surveys.hlp197
-rw-r--r--pkg/xtools/catquery/mkpkg32
72 files changed, 8736 insertions, 0 deletions
diff --git a/pkg/xtools/catquery/cq.h b/pkg/xtools/catquery/cq.h
new file mode 100644
index 00000000..9d9f801f
--- /dev/null
+++ b/pkg/xtools/catquery/cq.h
@@ -0,0 +1,100 @@
+# Public definitions file for the catalog query interface.
+
+# The catalog access interface parameter definitions
+
+define CQNRECS 1 # the number of records in the catalog database
+define CQSZRECLIST 2 # the length of the record name list in chars
+define CQRECLIST 3 # the record name @list
+define CQCATDB 4 # the catalog database file name
+define CQCATNO 5 # the current catalog record number
+define CQCATNAME 6 # the current catalog name
+
+# The max size of a query parameter name, value, units, and formats string.
+
+define CQ_SZ_QPNAME 19
+define CQ_SZ_QPVALUE 79
+define CQ_SZ_QPUNITS 19
+define CQ_SZ_QPFMTS 11
+
+# The maximum number of fields or columns in the result.
+
+define CQ_MAX_NFIELDS 100
+
+# The catalog access results parameter definitions
+
+define CQRCATDB 1 # the catalog database file
+define CQRCATNAME 2 # the catalog name
+define CQRADDRESS 3 # the address
+define CQRQUERY 4 # the query
+define CQRNQPARS 5 # the number of query parameters
+define CQRQPNAMES 6 # the query parameter names
+define CQRQPVALUES 7 # the query parameter values
+define CQRQPUNITS 8 # the query parameter units
+
+define CQRTYPE 9 # the results format (currently stext or btext)
+define CQRECSIZE 10 # the record length in characters (default = 0)
+define CQRHSKIP 11 # the number of header lines to skip (default = 0)
+define CQRTSKIP 12 # the number of trailing lines to skip (default = 0)
+define CQRTRIML 13 # the number of leading characters to trim
+define CQRTRIMR 14 # the number of trailing characters to trim
+
+define CQRNRECS 15 # The number of records in the results
+define CQNHEADER 16 # The number of header keywords in the results
+define CQNFIELDS 17 # The number of record fields in the results
+define CQRECPTR 18 # the current record pointer
+
+# The surveys access results parameter definitions
+
+define CQIMCATDB 1
+define CQIMCATNAME 2
+define CQIMADDRESS 3
+define CQIMQUERY 4
+define CQINQPARS 5
+define CQIQPNAMES 6
+define CQIQPVALUES 7
+define CQIQPUNITS 8
+define CQIMNAME 9
+define CQIMTYPE 10
+define CQWCS 11
+define CQNWCS 12
+define CQNIMPARS 13
+
+
+# The max size of a field name, value, units, and formats string.
+
+define CQ_SZ_FNAME 19
+define CQ_SZ_FVALUE 79
+define CQ_SZ_FUNITS 19
+define CQ_SZ_FFMTS 11
+
+
+# Define the default input catalog file types
+
+define CQ_RTYPESTR "|stext|btext|"
+
+define CQ_STEXT 1 # Simple text (free format fields)
+ # Newline delimited records
+ # Whitespace delimited fields
+ # No embedded whitespace unless in ""
+ # Skip nlines header
+ # Skip nchars at beginning / end of record
+ # Skip nlines trailer
+
+
+define CQ_BTEXT 2 # Blocked text (fixed format fields)
+ # Fixed size newline delimited records
+ # Offset and size delimited fields
+ # Embedded whitespace permitted
+ # Skip nlines header
+ # Skip nchars at beginning / end of record
+ # Skip nlines trailer
+
+
+define CQ_ITYPESTR "|fits|"
+define CQ_FITS 1
+
+
+define CQ_WTYPESTR "|fits|dss|none|"
+define CQ_WFITS 1
+define CQ_WDSS 2
+define CQ_WNONE 3
diff --git a/pkg/xtools/catquery/cqdb.x b/pkg/xtools/catquery/cqdb.x
new file mode 100644
index 00000000..13434ca4
--- /dev/null
+++ b/pkg/xtools/catquery/cqdb.x
@@ -0,0 +1,442 @@
+include <ctype.h>
+include "cqdef.h"
+include "cq.h"
+
+# These are the catalog configuration file access routines used by the
+# catalog access interface. These routines should not normally be called
+# directly from the applications program.
+
+
+# CQ_DGETI -- Get an integer field from the database record.
+
+int procedure cq_dgeti (cq, record, field)
+
+pointer cq #I The catalog database descriptor
+int record #I The catalog record index
+char field[ARB] #I The record field
+
+int ival #O Field value
+char name[SZ_LINE]
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "The catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (ival)
+ if (nscan() == 2)
+ return (ival)
+ else
+ call error (0, "Error reading catalog integer field value")
+ }
+ }
+
+ call error (0, "Catalog record field not found")
+end
+
+
+# CQ_DGETR -- Get a real field from the catalog database record.
+
+real procedure cq_dgetr (cq, record, field)
+
+pointer cq #I The catalog database descriptor
+int record #I The catalog database record index
+char field[ARB] #I The catalog record field
+
+real rval
+char name[SZ_LINE]
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "The catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargr (rval)
+ if (nscan() == 2)
+ return (rval)
+ else
+ call error (0, "Error reading real catalog field value")
+ }
+ }
+
+ call error (0, "Catalog record field not found")
+end
+
+
+# CQ_DGETD -- Get a double precision field from a record.
+
+double procedure cq_dgetd (cq, record, field)
+
+pointer cq #I The catalog database descriptor
+int record #I The catalog database index
+char field[ARB] #I The catalog database field
+
+double dval
+char name[SZ_LINE]
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "The catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargd (dval)
+ if (nscan() == 2)
+ return (dval)
+ else
+ call error (0, "Error reading double catalog field value")
+ }
+ }
+
+ call error (0, "Catalog record field not found")
+end
+
+
+# CQ_DGWRD -- Get a string field from the database file.
+
+procedure cq_dgwrd (cq, record, field, str, maxchar)
+
+pointer cq #I The catalog access descriptor
+int record #I The catalog record index
+char field[ARB] #I The field name
+char str[maxchar] #O The output string value
+int maxchar #I The maximum characters for string
+
+char name[SZ_LINE]
+int i, fscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "Catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargwrd (str, maxchar)
+ for (i=1; IS_WHITE(str[i]); i=i+1)
+ ;
+ if (i > 1)
+ call strcpy (str[i], str, maxchar)
+ return
+ }
+ }
+
+ call error (0, "Catalog record field not found")
+end
+
+
+# CQ_DGSTR -- Get a string field from the database file.
+
+procedure cq_dgstr (cq, record, field, str, maxchar)
+
+pointer cq #I The catalog access descriptor
+int record #I The catalog record index
+char field[ARB] #I The field name
+char str[maxchar] #O The output string value
+int maxchar #I The maximum characters for string
+
+char name[SZ_LINE]
+int i, fscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "Catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargstr (str, maxchar)
+ for (i=1; IS_WHITE(str[i]); i=i+1)
+ ;
+ if (i > 1)
+ call strcpy (str[i], str, maxchar)
+ return
+ }
+ }
+
+ call error (0, "Catalog record field not found")
+end
+
+
+# CQ_DGAI -- Get an integer array field from a record.
+
+procedure cq_dgai (cq, record, field, array, len_array, npts)
+
+pointer cq #I The database catalog record
+int record #I The database record index
+char field[ARB] #I The database field
+int array[len_array] #O The output array values
+int len_array #I The length of array
+int npts #O The number of points in the array
+
+char name[SZ_LINE]
+int i
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "The catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (npts)
+ if (nscan() != 2)
+ call error (0, "Error reading size of integer array")
+
+ npts = min (npts, len_array)
+ for (i = 1; i <= npts; i = i + 1) {
+ if (fscan (CQ_FD(cq)) == EOF)
+ call error (0, "The integer array is truncated")
+
+ call gargi (array[i])
+ if (nscan() != 1)
+ call error (0, "Error decoding integer array")
+ }
+ return
+ }
+ }
+
+ call error (0, "The catalog record field not found")
+end
+
+
+# CQ_DGAR -- Get a real array field from a record.
+
+procedure cq_dgar (cq, record, field, array, len_array, npts)
+
+pointer cq #I The database catalog record
+int record #I The database record index
+char field[ARB] #I The database field
+real array[len_array] #O The output array values
+int len_array #I The length of array
+int npts #O The number of points in the array
+
+char name[SZ_LINE]
+int i
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "The catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (npts)
+ if (nscan() != 2)
+ call error (0, "Error reading real array size value")
+
+ npts = min (npts, len_array)
+ for (i = 1; i <= npts; i = i + 1) {
+ if (fscan (CQ_FD(cq)) == EOF)
+ call error (0, "The real array is truncated")
+
+ call gargr (array[i])
+ if (nscan() != 1)
+ call error (0, "Error reading real array")
+ }
+ return
+ }
+ }
+
+ call error (0, "The catalog record field not found")
+end
+
+
+# CQ_DGAD -- Get a double array field from a catalog.
+
+procedure cq_dgad (cq, record, field, array, len_array, npts)
+
+pointer cq #I The catalog database descriptor
+int record #I The catalog record index
+char field[ARB] #I The database field
+double array[len_array] #O The array values
+int len_array #I The length of array
+int npts #O The number of points in the array
+
+char name[SZ_LINE]
+int i
+
+int fscan(), nscan()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "The catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (npts)
+ if (nscan() != 2)
+ call error (0, "Error the double array size")
+
+ npts = min (npts, len_array)
+ for (i = 1; i <= npts; i = i + 1) {
+ if (fscan (CQ_FD(cq)) == EOF)
+ call error (0, "The double array is truncated")
+
+ call gargd (array[i])
+ if (nscan() != 1)
+ call error (0, "Error reading the double array")
+ }
+ return
+ }
+ }
+
+ call error (0, "Catalog record field not found")
+end
+
+
+# CQ_DGATXT -- Get newline delimited text from a database file.
+
+procedure cq_dgatxt (cq, record, field, str, maxchar, nlines)
+
+pointer cq #I The catalog access descriptor
+int record #I The catalog record index
+char field[ARB] #I The field name
+char str[maxchar] #O The output string value
+int maxchar #I The maximum characters for string
+int nlines #I the number of text lines
+
+char name[SZ_LINE]
+int i, op
+int fscan(), nscan(), gstrcpy()
+bool streq()
+
+begin
+ if ((record < 1) || (record > CQ_NRECS(cq)))
+ call error (0, "Catalog record is out of bounds")
+
+ call seek (CQ_FD(cq), CQ_OFFSET(cq, record))
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (name, SZ_LINE)
+
+ if (streq (name, "begin"))
+ break
+ else if (streq (name, field)) {
+ call gargi (nlines)
+ if (nscan() != 2)
+ call error (0, "Error text array length")
+ op = 1
+ do i = 1, nlines {
+ if (fscan (CQ_FD(cq)) == EOF)
+ call error (0, "The text array is truncated")
+ call gargstr (name, SZ_LINE)
+ op = op + gstrcpy (name, str[op], maxchar - op +1)
+ if (op > maxchar)
+ break
+ str[op] = '\n'
+ op = op + 1
+ str[op] = EOS
+ }
+
+ return
+ }
+ }
+
+ call error (0, "Catalog record field not found")
+end
+
+
+## DTPTIME -- Put a time string with a comment
+#
+#procedure dtptime (dt)
+#
+#pointer dt # DTTEXT pointer
+#
+#char timestr[SZ_TIME]
+#long time, clktime()
+#
+#begin
+# time = clktime (0)
+# call cnvtime (time, timestr, SZ_TIME)
+# call fprintf (DT(dt), "# %s\n")
+# call pargstr (timestr)
+#end
+#
+#
+## DTPUT -- Print to database.
+#
+#procedure dtput (dt, format)
+#
+#pointer dt # DTTEXT pointer
+#char format[ARB] # String format
+#
+#begin
+# call fprintf (DT(dt), format)
+#end
+
+# CQ_DSCAN -- Scan database.
+
+int procedure cq_dscan (cq)
+
+pointer cq # The catalog database descriptor.
+
+int fscan()
+
+begin
+ return (fscan (CQ_FD(cq)))
+end
diff --git a/pkg/xtools/catquery/cqdef.h b/pkg/xtools/catquery/cqdef.h
new file mode 100644
index 00000000..6337bd9f
--- /dev/null
+++ b/pkg/xtools/catquery/cqdef.h
@@ -0,0 +1,133 @@
+# Private definitions file for the catalog query interface.
+
+
+# Miscellaneous definitions mostly concerning buffer sizes.
+
+#define CQ_SZ_LINE SZ_LINE # The text storage size in chars
+define CQ_SZFNAME (1+SZ_FNAME) / 2 # The file name storage size in structs
+define CQ_SZLINE (1+SZ_LINE) / 2 # The text storage size in structs
+define CQ_ALLOC 20 # The record allocation block size
+
+define USE_URLGET TRUE
+
+
+# The catalog record map descriptor (borrowed from dttext interface).
+
+define CQ_LEN (8 + 2 * CQ_SZFNAME)
+
+define CQ_FD Memi[$1] # The database FIO channel
+define CQ_MODE Memi[$1+1] # The database access mode
+define CQ_NRECS Memi[$1+2] # The number of records
+define CQ_MAP Memi[$1+3] # The pointer to record names
+define CQ_NAMES Memi[$1+4] # The pointer to name indices
+define CQ_OFFSETS Memi[$1+5] # The pointer to record offsets
+define CQ_CATNO Memi[$1+6] # The current catalog number
+define CQ_CAT Memi[$1+7] # The current catalog descriptor
+define CQ_CATDB Memc[P2C($1+8)] # The database file name
+define CQ_CATNAME Memc[P2C($1+8+CQ_SZFNAME)]# The current catalog name
+
+define CQ_NAMEI Memi[CQ_NAMES($1)+$2-1]
+define CQ_NAME Memc[CQ_MAP($1)+CQ_NAMEI($1,$2)]
+define CQ_OFFSET Meml[CQ_OFFSETS($1)+$2-1]
+
+
+# The current catalog desciptor.
+
+define CQ_LEN_CC (15 + 2 * CQ_SZLINE)
+define QOFFSET P2C($1+15+$2*CQ_SZLINE)
+
+define CQ_NQPARS Memi[$1] # The no of query params
+define CQ_PQPNAMES Memi[$1+1] # The query param names ptr
+define CQ_PQPDVALUES Memi[$1+2] # The query param defaults ptr
+define CQ_PQPVALUES Memi[$1+3] # The query param values ptr
+define CQ_PQPUNITS Memi[$1+4] # The query param units ptr
+define CQ_PQPFMTS Memi[$1+5] # The query param format ptr
+define CQ_HFMT Memi[$1+6] # The header format
+define CQ_ADDRESS Memc[QOFFSET($1,0)] # The catalog address
+define CQ_QUERY Memc[QOFFSET($1,1)] # The network query
+
+# The catalog results descriptor.
+
+define CQ_LEN_RES (30+2*CQ_SZFNAME+2*CQ_SZLINE)
+define ROFFSET P2C($1+30+$2*CQ_SZFNAME+$3*CQ_SZLINE)
+
+define CQ_RNQPARS Memi[$1] # The number of query params
+define CQ_RQPNAMES Memi[$1+1] # The query param names ptr
+define CQ_RQPVALUES Memi[$1+2] # The query param values ptr
+define CQ_RQPUNITS Memi[$1+3] # The query param units ptr
+
+define CQ_RTYPE Memi[$1+4] # The results data format
+define CQ_RECSIZE Memi[$1+5] # The results record size
+define CQ_RHSKIP Memi[$1+6] # The number of header records to skip
+define CQ_RTRIML Memi[$1+7] # The beginning of record trim
+define CQ_RTRIMR Memi[$1+8] # The end of record trim
+define CQ_RTSKIP Memi[$1+9] # The number of trailer records to skip
+
+define CQ_NHEADER Memi[$1+10] # The number of header keywords
+define CQ_HKNAMES Memi[$1+11] # The results keyword names
+define CQ_HKVALUES Memi[$1+12] # The result keyword values
+
+define CQ_NFIELDS Memi[$1+13] # The number of record fields
+define CQ_FNAMES Memi[$1+14] # The record field names
+define CQ_FTYPES Memi[$1+15] # The record field data types ptr
+define CQ_FOFFSETS Memi[$1+16] # The record field offsets ptr
+define CQ_FSIZES Memi[$1+17] # The record field sizes ptr
+define CQ_FUNITS Memi[$1+18] # The record field units
+define CQ_FFMTS Memi[$1+19] # The record field formats
+
+define CQ_RFD Memi[$1+20] # The results file descriptor
+define CQ_RBUF Memi[$1+21] # The results data descriptor
+define CQ_RNRECS Memi[$1+22] # The number of results records
+define CQ_RINDEX Memi[$1+23] # The results record index pointer
+
+define CQ_RECPTR Memi[$1+24] # The current record
+define CQ_FNFIELDS Memi[$1+25] # The number of fields in current record
+define CQ_FINDICES Memi[$1+26] # The current record indices pointer
+
+define CQ_RCATDB Memc[ROFFSET($1,0,0)] # The catalog database name
+define CQ_RCATNAME Memc[ROFFSET($1,1,0)] # The catalog name
+
+define CQ_RADDRESS Memc[ROFFSET($1,2,0)] # Query address
+define CQ_RQUERY Memc[ROFFSET($1,2,1)] # Query string
+
+# The image survey descriptor. May need to extend this structure as more
+# experience with different image formats is obtained. May not need wcs and
+# keyword default value strings ...
+
+define CQ_LEN_IM (30+3*CQ_SZFNAME+2*CQ_SZLINE)
+define IOFFSET P2C($1+30+$2*CQ_SZFNAME+$3*CQ_SZLINE)
+
+define CQ_INQPARS Memi[$1] # The number of query params
+define CQ_IQPNAMES Memi[$1+1] # The query param names ptr
+define CQ_IQPVALUES Memi[$1+2] # The query param values ptr
+define CQ_IQPUNITS Memi[$1+3] # The query param units ptr
+define CQ_IMTYPE Memi[$1+4] # The image data format
+
+define CQ_WCS Memi[$1+10] # The image wcs type
+define CQ_NWCS Memi[$1+11] # The number of wcs keywords
+define CQ_WPNAMES Memi[$1+12] # The wcs parameter names
+define CQ_WKNAMES Memi[$1+13] # The wcs keyword names
+define CQ_WKDVALUES Memi[$1+14] # The wcs keyword default values
+define CQ_WKVALUES Memi[$1+15] # The wcs keyword values
+define CQ_WKTYPES Memi[$1+16] # The wcs keyword data types
+define CQ_WKUNITS Memi[$1+17] # The wcs keyword value units
+
+define CQ_NIMPARS Memi[$1+19] # The number of header keywords
+define CQ_IPNAMES Memi[$1+20] # The results keyword names
+define CQ_IKNAMES Memi[$1+21] # The result keyword values
+define CQ_IKDVALUES Memi[$1+22] # The result keyword values
+define CQ_IKVALUES Memi[$1+23] # The result keyword values
+define CQ_IKTYPES Memi[$1+24] # The result keyword values
+define CQ_IKUNITS Memi[$1+25] # The result keyword values
+
+define CQ_IMCATDB Memc[IOFFSET($1,0,0)] # The survey database name
+define CQ_IMCATNAME Memc[IOFFSET($1,1,0)] # The survey name
+define CQ_IMNAME Memc[IOFFSET($1,2,0)] # The image name
+
+define CQ_IMADDRESS Memc[IOFFSET($1,3,0)] # Query address
+define CQ_IMQUERY Memc[IOFFSET($1,3,1)] # Query string
+
+
+define CQ_HFMTSTR "|none|http|"
+define CQ_HNONE 1
+define CQ_HHTTP 2
diff --git a/pkg/xtools/catquery/cqdtype.x b/pkg/xtools/catquery/cqdtype.x
new file mode 100644
index 00000000..e0088590
--- /dev/null
+++ b/pkg/xtools/catquery/cqdtype.x
@@ -0,0 +1,53 @@
+# CQ_DTYPE -- Decode the field data type.
+
+define NTYPES 6
+
+# CQ_DTYPE -- Given a single character data type from the set [csilrd] return
+# the appropriate integer type,
+
+int procedure cq_dtype (c)
+
+char c
+
+int type_codes[NTYPES], i
+string types "csilrd"
+int stridx()
+data type_codes /TY_CHAR, TY_SHORT, TY_INT, TY_LONG, TY_REAL, TY_DOUBLE/
+begin
+ i = stridx (c, types)
+ if (i == 0)
+ return (TY_CHAR)
+ else
+ return (type_codes[stridx(c,types)])
+end
+
+# CQ_ITYPE -- Given an integer code from the set TY_CHAR, TY_SHORT, TY_INT,
+# TY_LONG, TY_REAL, and TY_DOUBLE return the appropriate character code
+# from the set [csilrd].
+
+char procedure cq_itype (itype)
+
+int itype #I the integer data type
+
+char c
+
+begin
+ switch (itype) {
+ case TY_CHAR:
+ c = 'c'
+ case TY_SHORT:
+ c = 's'
+ case TY_INT:
+ c = 'i'
+ case TY_LONG:
+ c = 'l'
+ case TY_REAL:
+ c = 'r'
+ case TY_DOUBLE:
+ c = 'd'
+ default:
+ c = 'c'
+ }
+
+ return (c)
+end
diff --git a/pkg/xtools/catquery/cqget.x b/pkg/xtools/catquery/cqget.x
new file mode 100644
index 00000000..ea259bb5
--- /dev/null
+++ b/pkg/xtools/catquery/cqget.x
@@ -0,0 +1,225 @@
+include "cqdef.h"
+include "cq.h"
+
+# These routines fetch fields from the catalog configuation by field name.
+# They can be used by the calling program to read quantities of interest
+# directly from the configuration file. In most applications it should
+# not be necessary to use these routines as the main interface routines
+# provide most of the desired functionality, but they are included for
+# completeness.
+
+# CQ_FGETI -- Fetch an integer field from the current catalog.
+
+int procedure cq_fgeti (cq, field)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+
+int ival
+int cq_dgeti()
+errchk cq_dgeti()
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ ival = cq_dgeti (cq, CQ_CATNO(cq), field)
+
+ return (ival)
+end
+
+
+# CQ_FGETR -- Fetch a real field from the current catalog.
+
+real procedure cq_fgetr (cq, field)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+
+real rval
+real cq_dgetr()
+errchk cq_dgetr()
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ rval = cq_dgetr (cq, CQ_CATNO(cq), field)
+
+ return (rval)
+end
+
+
+# CQ_FGETD -- Fetch a double precision field from the current catalog.
+
+double procedure cq_fgetd (cq, field)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+
+double dval
+double cq_dgetd()
+errchk cq_dgetd()
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ dval = cq_dgetd (cq, CQ_CATNO(cq), field)
+
+ return (dval)
+end
+
+
+# CQ_FGAI -- Get an array valued integer parameter.
+
+int procedure cq_fgai (cq, field, array, max_len)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+int array[ARB] #O the output array
+int max_len #I the maximum length of the array
+
+int npts
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ call cq_dgai (cq, CQ_CATNO(cq), field, array, max_len, npts)
+
+ return (npts)
+end
+
+
+# CQ_FGAR -- Get an array valued real parameter.
+
+int procedure cq_fgar (cq, field, array, max_len)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+real array[ARB] #O the output array
+int max_len #I the maximum length of the array
+
+int npts
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ call cq_dgar (cq, CQ_CATNO(cq), field, array, max_len, npts)
+
+ return (npts)
+end
+
+
+# CQ_FGAD -- Get an array valued double parameter.
+
+int procedure cq_fgad (cq, field, array, max_len)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+double array[ARB] #O the output array
+int max_len #I the maximum length of the array
+
+int npts
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ call cq_dgad (cq, CQ_CATNO(cq), field, array, max_len, npts)
+
+ return (npts)
+end
+
+
+# CQ_FGWRD -- Fetch a single word field from the current catalog.
+
+procedure cq_fgwrd (cq, field, str, maxch)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+char str[ARB] #O the output string
+int maxch #I the maximum number of characters
+
+errchk cq_dgwrd()
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ call cq_dgwrd (cq, CQ_CATNO(cq), field, str, maxch)
+end
+
+
+# CQ_FGSTR -- Fetch a string field from the current catalog.
+
+procedure cq_fgstr (cq, field, str, maxch)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+char str[ARB] #O the output string
+int maxch #I the maximum number of characters
+
+errchk cq_dgwrd()
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ call cq_dgstr (cq, CQ_CATNO(cq), field, str, maxch)
+end
+
+
+# CQ_FGTEXT -- Fetch a multi-line text field from the current catalog.
+
+int procedure cq_fgtext (cq, field, str, maxch)
+
+pointer cq #I the catalog descriptor
+char field[ARB] #I the field name
+char str[ARB] #O the output string
+int maxch #I the maximum number of characters
+
+int nlines
+errchk cq_dgatxt()
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ call error (0, "The current catalog is undefined")
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ call error (0, "The current catalog is undefined")
+
+ call cq_dgatxt (cq, CQ_CATNO(cq), field, str, maxch, nlines)
+
+ return (nlines)
+end
+
+
+# CQ_SCAN -- Scan the database at the current position.
+
+int procedure cq_scan (cq)
+
+pointer cq # The catalog database descriptor.
+
+int fscan()
+
+begin
+ return (fscan (CQ_FD(cq)))
+end
diff --git a/pkg/xtools/catquery/cqgfields.x b/pkg/xtools/catquery/cqgfields.x
new file mode 100644
index 00000000..23b94221
--- /dev/null
+++ b/pkg/xtools/catquery/cqgfields.x
@@ -0,0 +1,483 @@
+include <ctype.h>
+include "cqdef.h"
+include "cq.h"
+
+# CQ_SETRECORD -- Set the the current record. What action this procedure takes
+# depends on the input data type. In the case of text files this task
+# sets the current record pointer and figures where in the record each
+# column begins. For blocked text files the foffsets determine where each
+# record begins.
+
+int procedure cq_setrecord (res, recptr)
+
+pointer res #I the results descriptor
+int recptr #U the current record pointer
+
+pointer buf
+
+begin
+ # The record is outside the record data range.
+ if (recptr <= 0) {
+ CQ_RECPTR(res) = 0
+ CQ_FNFIELDS(res) = 0
+ call aclri (Memi[CQ_FINDICES(res)], CQ_MAX_NFIELDS + 1)
+ return (BOF)
+ }
+ if (recptr > CQ_RNRECS(res))
+ return (EOF)
+
+ CQ_RECPTR(res) = recptr
+ switch (CQ_RTYPE(res)) {
+ case CQ_STEXT:
+ buf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ call cq_find_fields (Memc[buf], Memi[CQ_FINDICES(res)],
+ CQ_MAX_NFIELDS, CQ_FNFIELDS(res))
+ case CQ_BTEXT:
+ ;
+ default:
+ }
+
+ return (recptr)
+end
+
+
+# CQ_GVALC -- Fetch a record field as a string value.
+
+int procedure cq_gvalc (res, recptr, field, str, maxch)
+
+pointer res #I the results descriptor
+int recptr #I the current record pointer
+char field[ARB] #I the record field name.
+char str[ARB] #O the output string parameter
+int maxch #I the maximum number of characters
+
+pointer fbuf
+int fnum, fip, fsize
+int cq_fnumber(), cq_setrecord()
+
+begin
+ # The record is outside the record data range.
+ str[1] = EOS
+ if (recptr <= 0 || recptr > CQ_RNRECS(res))
+ return (0)
+
+ # Find the field number.
+ fnum = cq_fnumber (res, field)
+ if (fnum <= 0)
+ return (0)
+
+ # Set the current record if necessary.
+ if (recptr != CQ_RECPTR(res)) {
+ if (cq_setrecord (res, recptr) != recptr)
+ return (0)
+ }
+
+ # Extract the requested field as a string. If the data is in binary
+ # internally this will require formatting a string. If the data is
+ # text this requires extracting the appropriate piece of text.
+
+ switch (CQ_RTYPE(res)) {
+
+ case CQ_STEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fnum = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fip = Memi[CQ_FINDICES(res)+fnum-1]
+ fsize = min (maxch, Memi[CQ_FINDICES(res)+fnum] -
+ Memi[CQ_FINDICES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], str, fsize)
+
+ case CQ_BTEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fip = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fsize = min (maxch, Memi[CQ_FSIZES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], str, fsize)
+
+ default:
+ fsize = 0
+
+ }
+
+ return (fsize)
+end
+
+
+# CQ_GVALD -- Return a double precision field value
+
+int procedure cq_gvald (res, recptr, field, dval)
+
+pointer res #I the results descriptor
+int recptr #I the current record pointer
+char field[ARB] #I the record field name.
+double dval #O the output double value
+
+pointer fbuf, sp, line
+int fnum, fip, fsize, nchars
+int cq_fnumber(), ctod(), cq_setrecord()
+
+begin
+ dval = INDEFD
+
+ # The record is outside the record data range.
+ if (recptr <= 0 || recptr > CQ_RNRECS(res))
+ return (0)
+
+ # Find the field number.
+ fnum = cq_fnumber (res, field)
+ if (fnum <= 0)
+ return (0)
+
+ # Set the current record if necessary.
+ if (recptr != CQ_RECPTR(res)) {
+ if (cq_setrecord (res, recptr) != recptr)
+ return (0)
+ }
+
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Extract the requested field as a double precision value. If the data
+ # is in binary internally this may imply a type conversion. If the data
+ # is text this requires decoding the string value.
+
+ switch (CQ_RTYPE(res)) {
+
+ case CQ_STEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fnum = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fip = Memi[CQ_FINDICES(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FINDICES(res)+fnum] -
+ Memi[CQ_FINDICES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctod (Memc[line], fip, dval)
+
+ case CQ_BTEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fip = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FSIZES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctod (Memc[line], fip, dval)
+
+ default:
+ nchars = 0
+
+ }
+
+ call sfree (sp)
+
+ return (nchars)
+end
+
+
+# CQ_GVALR -- Return a real precision field value.
+
+int procedure cq_gvalr (res, recptr, field, rval)
+
+pointer res #I the results descriptor
+int recptr #I the current record pointer
+char field[ARB] #I the record field name.
+real rval #O the output real value
+
+pointer fbuf, sp, line
+int fnum, fip, fsize, nchars
+int cq_fnumber(), ctor(), cq_setrecord()
+
+begin
+ rval = INDEFR
+
+ # The record is outside the record data range.
+ if (recptr <= 0 || recptr > CQ_RNRECS(res))
+ return (0)
+
+ # Find the field number.
+ fnum = cq_fnumber (res, field)
+ if (fnum <= 0)
+ return (0)
+
+ # Set the current record if necessary.
+ if (recptr != CQ_RECPTR(res)) {
+ if (cq_setrecord (res, recptr) != recptr)
+ return (0)
+ }
+
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Extract the requested field as a double precision value. If the data
+ # is in binary internally this may imply a type conversion. If the data
+ # is text this requires decoding the string value.
+
+ switch (CQ_RTYPE(res)) {
+
+ case CQ_STEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fnum = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fip = Memi[CQ_FINDICES(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FINDICES(res)+fnum] -
+ Memi[CQ_FINDICES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctor (Memc[line], fip, rval)
+
+ case CQ_BTEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fip = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FSIZES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctor (Memc[line], fip, rval)
+
+ default:
+ nchars = 0
+
+ }
+
+ call sfree (sp)
+
+ return (nchars)
+end
+
+
+# CQ_GVALL -- Return a long integer field value.
+
+int procedure cq_gvall (res, recptr, field, lval)
+
+pointer res #I the results descriptor
+int recptr #I the current record pointer
+char field[ARB] #I the record field name.
+long lval #I the output long value
+
+pointer fbuf, sp, line
+int fnum, fip, fsize, nchars
+int cq_fnumber(), ctol(), cq_setrecord()
+
+begin
+ lval = INDEFL
+
+ # The record is outside the record data range.
+ if (recptr <= 0 || recptr > CQ_RNRECS(res))
+ return (0)
+
+ # Find the field number.
+ fnum = cq_fnumber (res, field)
+ if (fnum <= 0)
+ return (0)
+
+ # Set the current record if necessary.
+ if (recptr != CQ_RECPTR(res)) {
+ if (cq_setrecord (res, recptr) != recptr)
+ return(0)
+ }
+
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Extract the requested field as a double precision value. If the data
+ # is in binary internally this may imply a type conversion. If the data
+ # is text this requires decoding the string value.
+
+ switch (CQ_RTYPE(res)) {
+
+ case CQ_STEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fnum = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fip = Memi[CQ_FINDICES(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FINDICES(res)+fnum] -
+ Memi[CQ_FINDICES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctol (Memc[line], fip, lval)
+
+ case CQ_BTEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fip = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FSIZES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctol (Memc[line], fip, lval)
+
+ default:
+ nchars = 0
+
+ }
+
+ call sfree (sp)
+
+ return (nchars)
+end
+
+
+# CQ_GVALI -- Return an integer field value
+
+int procedure cq_gvali (res, recptr, field, ival)
+
+pointer res #I the results descriptor
+int recptr #I the current record pointer
+char field[ARB] #I the record field name.
+int ival #I the output int value
+
+pointer fbuf, sp, line
+int fnum, fip, fsize, nchars
+int cq_fnumber(), ctoi(), cq_setrecord()
+
+begin
+ ival = INDEFI
+
+ # The record is outside the record data range.
+ if (recptr <= 0 || recptr > CQ_RNRECS(res))
+ return (0)
+
+ # Find the field number.
+ fnum = cq_fnumber (res, field)
+ if (fnum <= 0)
+ return (0)
+
+ # Set the current record if necessary.
+ if (recptr != CQ_RECPTR(res)) {
+ if (cq_setrecord (res, recptr) != recptr)
+ return (0)
+ }
+
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Extract the requested field as a double precision value. If the data
+ # is in binary internally this may imply a type conversion. If the data
+ # is text this requires decoding the string value.
+
+ switch (CQ_RTYPE(res)) {
+
+ case CQ_STEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fnum = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fip = Memi[CQ_FINDICES(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FINDICES(res)+fnum] -
+ Memi[CQ_FINDICES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctoi (Memc[line], fip, ival)
+
+ case CQ_BTEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fip = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FSIZES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctoi (Memc[line], fip, ival)
+
+ default:
+ nchars = 0
+ }
+
+ call sfree (sp)
+
+ return (nchars)
+end
+
+
+# CQ_GVALS -- Return a short integer field value
+
+int procedure cq_gvals (res, recptr, field, sval)
+
+pointer res #I the results descriptor
+int recptr #I the current record pointer
+char field[ARB] #I the record field name.
+short sval #O the output short value
+
+pointer fbuf, sp, line
+int fnum, fip, fsize, nchars, ival
+int cq_fnumber(), ctoi(), cq_setrecord()
+
+begin
+ sval = INDEFS
+
+ # The record is outside the record data range.
+ if (recptr <= 0 || recptr > CQ_RNRECS(res))
+ return (0)
+
+ # Find the field number.
+ fnum = cq_fnumber (res, field)
+ if (fnum <= 0)
+ return (0)
+
+ # Set the current record if necessary.
+ if (recptr != CQ_RECPTR(res)) {
+ if (cq_setrecord (res, recptr) != recptr)
+ return (0)
+ }
+
+ call smark (sp)
+ call salloc (line, SZ_LINE, TY_CHAR)
+
+ # Extract the requested field as a double precision value. If the data
+ # is in binary internally this may imply a type conversion. If the data
+ # is text this requires decoding the string value.
+
+ switch (CQ_RTYPE(res)) {
+
+ case CQ_STEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fnum = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fip = Memi[CQ_FINDICES(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FINDICES(res)+fnum] -
+ Memi[CQ_FINDICES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctoi (Memc[line], fip, ival)
+ if (nchars > 0)
+ sval = ival
+
+ case CQ_BTEXT:
+ fbuf = CQ_RBUF(res) + Memi[CQ_RINDEX(res)+recptr-1] - 1
+ fip = Memi[CQ_FOFFSETS(res)+fnum-1]
+ fsize = min (SZ_LINE, Memi[CQ_FSIZES(res)+fnum-1])
+ call strcpy (Memc[fbuf+fip-1], Memc[line], fsize)
+ fip = 1
+ nchars = ctoi (Memc[line], fip, ival)
+ if (nchars > 0)
+ sval = ival
+
+ default:
+ nchars = 0
+
+ }
+
+ call sfree (sp)
+
+ return (nchars)
+end
+
+
+# CQ_FIND_FIELDS -- This procedure finds the starting column for each field
+# in the input line. These column numbers are returned in the array
+# field_pos; the number of fields is also returned.
+
+procedure cq_find_fields (linebuf, field_pos, max_fields, nfields)
+
+char linebuf[ARB] #I the input buffer
+int field_pos[max_fields] #O the output field positions
+int max_fields #I the maximum number of fields
+int nfields #O the computed number of fields
+
+bool in_field
+int ip, field_num
+
+begin
+ field_num = 1
+ field_pos[1] = 1
+ in_field = false
+
+ for (ip=1; linebuf[ip] != '\n' && linebuf[ip] != EOS; ip=ip+1) {
+ if (! IS_WHITE(linebuf[ip]))
+ in_field = true
+ else if (in_field) {
+ in_field = false
+ field_num = field_num + 1
+ field_pos[field_num] = ip
+ }
+ }
+
+ field_pos[field_num+1] = ip
+ nfields = field_num
+end
diff --git a/pkg/xtools/catquery/cqgqpars.x b/pkg/xtools/catquery/cqgqpars.x
new file mode 100644
index 00000000..627dd053
--- /dev/null
+++ b/pkg/xtools/catquery/cqgqpars.x
@@ -0,0 +1,99 @@
+include "cqdef.h"
+
+
+# CQ_GQPAR -- Get the default value, units, and format for a query parameter
+# by name.
+
+int procedure cq_gqpar (cq, name, pname, max_name, value, max_val, units,
+ max_units, format, max_format)
+
+pointer cq #I the catalog descriptor
+char name[ARB] #I the input query parameter name
+char pname[ARB] #I the output query parameter name
+int max_name #I the max size of the parameter name
+char value[ARB] #O the default value size
+int max_val #I the max size of the parameter value
+char units[ARB] #O the units string
+int max_units #I the max size of the parameter units
+char format[ARB] #O the format string
+int max_format #I the max size of the parameter format
+
+pointer cc
+int parno
+int strdic(), cq_wrdstr()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (0)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (0)
+ cc = CQ_CAT(cq)
+
+ parno = strdic (name, pname, max_name, Memc[CQ_PQPNAMES(cc)])
+ if (parno <= 0)
+ return (0)
+
+ parno = cq_wrdstr (parno, value, max_val, Memc[CQ_PQPDVALUES(cc)])
+ if (parno <= 0)
+ return (0)
+
+ parno = cq_wrdstr (parno, units, max_units, Memc[CQ_PQPUNITS(cc)])
+ if (parno <= 0)
+ return (0)
+
+ parno = cq_wrdstr (parno, format, max_format, Memc[CQ_PQPFMTS(cc)])
+ if (parno <= 0)
+ return (0)
+
+ return (parno)
+end
+
+
+# CQ_GQPARN -- Get the default value, units, and format for a query parameter
+# by number.
+
+int procedure cq_gqparn (cq, parno, pname, max_name, value, max_val, units,
+ max_units, format, max_format)
+
+pointer cq #I the catalog descriptor
+int parno #I the parameter number
+char pname[ARB] #I the output query parameter name
+int max_name #I the max size of the parameter name
+char value[ARB] #O the default value size
+int max_val #I the max size of the parameter value
+char units[ARB] #O the units string
+int max_units #I the max size of the parameter units
+char format[ARB] #O the format string
+int max_format #I the max size of the parameter format
+
+pointer cc
+int pnum
+int cq_wrdstr()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (0)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (0)
+ cc = CQ_CAT(cq)
+
+ pnum = cq_wrdstr (parno, pname, max_name, Memc[CQ_PQPNAMES(cc)])
+ if (pnum <= 0)
+ return (0)
+
+ pnum = cq_wrdstr (parno, value, max_val, Memc[CQ_PQPDVALUES(cc)])
+ if (pnum <= 0)
+ return (0)
+
+ pnum = cq_wrdstr (parno, units, max_units, Memc[CQ_PQPUNITS(cc)])
+ if (pnum <= 0)
+ return (0)
+
+ pnum = cq_wrdstr (parno, format, max_format, Memc[CQ_PQPFMTS(cc)])
+ if (pnum <= 0)
+ return (0)
+
+ return (pnum)
+end
diff --git a/pkg/xtools/catquery/cqgrecords.x b/pkg/xtools/catquery/cqgrecords.x
new file mode 100644
index 00000000..f7debe94
--- /dev/null
+++ b/pkg/xtools/catquery/cqgrecords.x
@@ -0,0 +1,83 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_GNRECORD -- Get next record from the results descriptor.
+
+int procedure cq_gnrecord (res, buf, maxch, recptr)
+
+pointer res #I the results descriptor
+char buf[ARB] #O the output record buffer
+int maxch #I the maximum buffer size
+int recptr #U the current record pointer
+
+int nchars
+int getline()
+
+begin
+ # The record is outside the record data range.
+ if (recptr < 0)
+ return (BOF)
+ if (recptr >= CQ_RNRECS(res))
+ return (EOF)
+
+ # Use file mechanism to extract record. Could also use buffer pointer
+ # and offsets
+
+ switch (CQ_RTYPE(res)) {
+
+ # Don't worry about maxch at the moment. Just assume that the
+ # buffer is at least SZ_LINE long. Can use recsize to return
+ # a buffer, SZ_LINE is the default. May need to use getlline
+ # in future.
+
+ case CQ_STEXT, CQ_BTEXT:
+ call seek (CQ_RFD(res), Meml[CQ_RINDEX(res)+recptr])
+ nchars = getline (CQ_RFD(res), buf)
+ recptr = recptr + 1
+ return (nchars)
+
+ default:
+ return (EOF)
+ }
+end
+
+
+# CQ_GRECORD -- Get a specified record from the results descriptor.
+
+int procedure cq_grecord (res, buf, maxch, recptr)
+
+pointer res #I the results descriptor
+char buf[ARB] #O the output record buffer
+int maxch #I the maximum buffer size
+int recptr #I the record to be extracted
+
+int nchars
+int getline()
+
+begin
+ # Check for out-of-bounds record requests.
+ if (recptr < 1)
+ return (BOF)
+ if (recptr > CQ_RNRECS(res))
+ return (EOF)
+
+ # Use file mechanism to extract record. Could also use buffer pointer
+ # and offsets
+
+ switch (CQ_RTYPE(res)) {
+
+ # Don't worry about maxch at the moment. Just assume that the
+ # buffer is at least SZ_LINE long. Can use recsize to return
+ # a buffer, SZ_LINE is the default. May need to use getlline
+ # in future.
+
+ case CQ_STEXT, CQ_BTEXT:
+ call seek (CQ_RFD(res), Meml[CQ_RINDEX(res)+recptr-1])
+ nchars = getline (CQ_RFD(res), buf)
+ return (nchars)
+
+ default:
+ return (EOF)
+ }
+end
diff --git a/pkg/xtools/catquery/cqiminfo.x b/pkg/xtools/catquery/cqiminfo.x
new file mode 100644
index 00000000..898d1ed2
--- /dev/null
+++ b/pkg/xtools/catquery/cqiminfo.x
@@ -0,0 +1,220 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_WINFO -- Get the WCS field description by field name.
+
+int procedure cq_winfo (res, wfield, wkname, sz_wkname, wkvalue, sz_wkvalue,
+ wktype, wkunits, sz_wkunits)
+
+pointer res #I the results descriptor
+char wfield[ARB] #I the field name
+char wkname[ARB] #O the output keyword name
+int sz_wkname #I the maximum size of the keyword name string
+char wkvalue[ARB] #O the current value string
+int sz_wkvalue #I the maximum size of the current value string
+int wktype #O the output field datatype
+char wkunits[ARB] #O the outpit field units string
+int sz_wkunits #I the maximum size of the units string
+
+pointer sp, fname
+int fieldno
+int strdic(), cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NWCS(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (wfield, Memc[fname], CQ_SZ_FNAME,
+ Memc[CQ_WPNAMES(res)])
+ if (fieldno <= 0) {
+ call sfree (sp)
+ return (0)
+ }
+
+ # Get the field keyword name.
+ if (cq_wrdstr (fieldno, wkname, sz_wkname, Memc[CQ_WKNAMES(res)]) <= 0)
+ wkname[1] = EOS
+
+ # Get the field keyword value.
+ if (cq_wrdstr (fieldno, wkvalue, sz_wkvalue,
+ Memc[CQ_WKVALUES(res)]) <= 0)
+ wkvalue[1] = EOS
+
+ # Get the field type.
+ wktype = Memi[CQ_WKTYPES(res)+fieldno-1]
+
+ # Get the field units.
+ if (cq_wrdstr (fieldno, wkunits, sz_wkunits,
+ Memc[CQ_WKUNITS(res)]) <= 0)
+ wkunits[1] = EOS
+
+ call sfree (sp)
+
+ return (fieldno)
+end
+
+
+# CQ_WINFON -- Get the WCS field description by field number.
+
+int procedure cq_winfon (res, fieldno, wfield, sz_wfield, wkname, sz_wkname,
+ wkvalue, sz_wkvalue, wktype, wkunits, sz_wkunits)
+
+pointer res #I the results descriptor
+int fieldno #I the input field number
+char wfield[ARB] #O the field name
+int sz_wfield #I the maximum size of the field string
+char wkname[ARB] #O the output keyword name
+int sz_wkname #I the maximum size of the keyword name string
+char wkvalue[ARB] #O the current value string
+int sz_wkvalue #I the maximum size of the current value string
+int wktype #O the output field datatype
+char wkunits[ARB] #O the outpit field units string
+int sz_wkunits #I the maximum size of the units string
+
+int cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NWCS(res) <= 0)
+ return (0)
+ if (fieldno <= 0 || fieldno > CQ_NWCS(res))
+ return (0)
+
+ # Get the field name.
+ if (cq_wrdstr (fieldno, wfield, sz_wfield, Memc[CQ_WPNAMES(res)]) <= 0)
+ return (0)
+
+ # Get the field keyword name.
+ if (cq_wrdstr (fieldno, wkname, sz_wkname, Memc[CQ_WKNAMES(res)]) <= 0)
+ wkname[1] = EOS
+
+ # Get the field keyword value.
+ if (cq_wrdstr (fieldno, wkvalue, sz_wkvalue,
+ Memc[CQ_WKVALUES(res)]) <= 0)
+ wkvalue[1] = EOS
+
+ # Get the field type.
+ wktype = Memi[CQ_WKTYPES(res)+fieldno-1]
+
+ # Get the field units.
+ if (cq_wrdstr (fieldno, wkunits, sz_wkunits,
+ Memc[CQ_WKUNITS(res)]) <= 0)
+ wkunits[1] = EOS
+
+ return (fieldno)
+end
+
+
+# CQ_KINFO -- Get the keyword field description by field name.
+
+int procedure cq_kinfo (res, kfield, ikname, sz_ikname, ikvalue, sz_ikvalue,
+ iktype, ikunits, sz_ikunits)
+
+pointer res #I the results descriptor
+char kfield[ARB] #I the field name
+char ikname[ARB] #O the output keyword name
+int sz_ikname #I the maximum size of the keyword name string
+char ikvalue[ARB] #O the current value string
+int sz_ikvalue #I the maximum size of the current value string
+int iktype #O the output field datatype
+char ikunits[ARB] #O the outpit field units string
+int sz_ikunits #I the maximum size of the units string
+
+pointer sp, fname
+int fieldno
+int strdic(), cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NIMPARS(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (kfield, Memc[fname], CQ_SZ_FNAME,
+ Memc[CQ_IPNAMES(res)])
+ if (fieldno <= 0) {
+ call sfree (sp)
+ return (0)
+ }
+
+ # Get the field keyword name.
+ if (cq_wrdstr (fieldno, ikname, sz_ikname, Memc[CQ_IKNAMES(res)]) <= 0)
+ ikname[1] = EOS
+
+ # Get the field keyword value.
+ if (cq_wrdstr (fieldno, ikvalue, sz_ikvalue,
+ Memc[CQ_IKVALUES(res)]) <= 0)
+ ikvalue[1] = EOS
+
+ # Get the field type.
+ iktype = Memi[CQ_IKTYPES(res)+fieldno-1]
+
+ # Get the field units.
+ if (cq_wrdstr (fieldno, ikunits, sz_ikunits,
+ Memc[CQ_IKUNITS(res)]) <= 0)
+ ikunits[1] = EOS
+
+ call sfree (sp)
+
+ return (fieldno)
+end
+
+
+# CQ_KINFON -- Get the image keyword field description by field number.
+
+int procedure cq_kinfon (res, fieldno, kfield, sz_kfield, ikname, sz_ikname,
+ ikvalue, sz_ikvalue, iktype, ikunits, sz_ikunits)
+
+pointer res #I the results descriptor
+int fieldno #I the input field number
+char kfield[ARB] #O the field name
+int sz_kfield #I the maximum size of the field string
+char ikname[ARB] #O the output keyword name
+int sz_ikname #I the maximum size of the keyword name string
+char ikvalue[ARB] #O the current value string
+int sz_ikvalue #I the maximum size of the current value string
+int iktype #O the output field datatype
+char ikunits[ARB] #O the outpit field units string
+int sz_ikunits #I the maximum size of the units string
+
+int cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NIMPARS(res) <= 0)
+ return (0)
+ if (fieldno <= 0 || fieldno > CQ_NIMPARS(res))
+ return (0)
+
+ # Get the field name.
+ if (cq_wrdstr (fieldno, kfield, sz_kfield, Memc[CQ_IPNAMES(res)]) <= 0)
+ return (0)
+
+ # Get the field keyword name.
+ if (cq_wrdstr (fieldno, ikname, sz_ikname, Memc[CQ_IKNAMES(res)]) <= 0)
+ ikname[1] = EOS
+
+ # Get the field keyword value.
+ if (cq_wrdstr (fieldno, ikvalue, sz_ikvalue, Memc[CQ_IKVALUES(res)]) <=
+ 0)
+ ikvalue[1] = EOS
+
+ # Get the field type.
+ iktype = Memi[CQ_IKTYPES(res)+fieldno-1]
+
+ # Get the field units.
+ if (cq_wrdstr (fieldno, ikunits, sz_ikunits, Memc[CQ_IKUNITS(res)]) <=
+ 0)
+ ikunits[1] = EOS
+
+ return (fieldno)
+end
diff --git a/pkg/xtools/catquery/cqimquery.x b/pkg/xtools/catquery/cqimquery.x
new file mode 100644
index 00000000..28a2957c
--- /dev/null
+++ b/pkg/xtools/catquery/cqimquery.x
@@ -0,0 +1,931 @@
+include <fset.h>
+include <ctype.h>
+include "cqdef.h"
+include "cq.h"
+
+
+define DEF_SZ_INBUF 32768 # the maximum network transfer buffer size
+
+
+# CQ_FIMQUERY -- Send a dummy image query on an existing image. The immage
+# may be any supported IRAF images.
+
+pointer procedure cq_fimquery (cq, imname)
+
+pointer cq #I the catalog database descriptor
+char imname[ARB] #I the input image name
+
+pointer res
+int cc
+pointer cq_firinit()
+int imaccess()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+ cc = CQ_CAT(cq)
+
+ # Open the network connection.
+ if (imaccess (imname, READ_WRITE) != YES)
+ return (NULL)
+
+ # Initialize the image results structure.
+ res = cq_firinit (cq)
+
+ # Return the results pointer.
+ return (res)
+end
+
+
+# CQ_IMQUERY -- Send an image survey query and return the image as a file.
+# Currently only FITS files are supported. The calling program is responsible
+# for generating an IRAF compatible image name. If the file already exists
+# no file is created but a valid results descriptor is still created.
+
+pointer procedure cq_imquery (cq, imname)
+
+pointer cq #I the catalog database descriptor
+char imname[ARB] #I the image name
+
+pointer res, inbuf
+char url[SZ_PATHNAME], addr[SZ_LINE], query[SZ_LINE], buf[SZ_LINE]
+int cc, fd, outfd, nchars, ip, op
+bool done
+pointer cq_irinit()
+int ndopen(), strlen(), open(), read(), getline(), url_get()
+errchk ndopen(), awriteb(), open(), read(), getline()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+ cc = CQ_CAT(cq)
+
+
+ if (USE_URLGET) {
+ # Initialize the image results structure.
+ res = cq_irinit (cq)
+
+ call strcpy (CQ_ADDRESS(cc), buf, SZ_LINE)
+ for (ip=1; buf[ip] != ':'; ip=ip+1) ; # skip 'inet:'
+ ip = ip + 1
+ for ( ; buf[ip] != ':'; ip=ip+1) ; # skip '80:'
+ ip = ip + 1
+ for (op=1; buf[ip] != ':'; ip=ip+1) {
+ addr[op] = buf[ip]
+ op = op + 1
+ }
+ addr[op] = EOS
+
+ call strcpy (CQ_IMQUERY(res), buf, SZ_LINE)
+ for (op=1; !IS_WHITE(buf[op+4]); op=op+1)
+ query[op] = buf[op+4]
+ query[op] = EOS
+
+ call sprintf (url, SZ_LINE, "http://%s%s")
+ call pargstr (addr)
+ call pargstr (query)
+
+ iferr {
+ call malloc (inbuf, DEF_SZ_INBUF, TY_CHAR)
+ if (url_get (url, imname, inbuf) < 0)
+ call error (0, "Cannot access url")
+ call mfree (inbuf, TY_CHAR)
+ } then {
+ if (res != NULL)
+ call cq_imclose (res)
+ return (NULL)
+ }
+
+ return (res)
+ }
+
+
+ # Open the network connection.
+ iferr (fd = ndopen (CQ_ADDRESS(cc), READ_WRITE))
+ return (NULL)
+
+ # Initialize the image results structure.
+ res = cq_irinit (cq)
+
+ # Formulate the query.
+ iferr {
+ switch (CQ_IMTYPE(res)) {
+ case CQ_FITS:
+ nchars = strlen (CQ_IMQUERY(res))
+ call write (fd, CQ_IMQUERY(res), nchars)
+ default:
+ nchars = strlen (CQ_IMQUERY(res))
+ call write (fd, CQ_IMQUERY(res), nchars)
+ }
+ call flush (fd)
+ call fseti (fd, F_CANCEL, OK)
+ } then {
+ if (fd != NULL)
+ call close (fd)
+ if (res != NULL)
+ call cq_imclose (res)
+ return (NULL)
+ }
+
+ # Open the output file.
+ outfd = NULL
+ iferr {
+ # Open the output file. Worry about legal image names at a
+ # higher level.
+ switch (CQ_IMTYPE(res)) {
+ case CQ_FITS:
+ outfd = open (imname, NEW_FILE, TEXT_FILE)
+ default:
+ outfd = open (imname, NEW_FILE, TEXT_FILE)
+ }
+ } then {
+ if (fd != NULL)
+ call close (fd)
+ if (res != NULL)
+ call cq_imclose (res)
+ return (NULL)
+ }
+
+ # Send the query and get back the results.
+ inbuf = NULL
+ iferr {
+
+ # Allocate the maximum buffer size.
+ call malloc (inbuf, DEF_SZ_INBUF, TY_CHAR)
+
+ # Skip a fixed number of bytes. Dangerous unless the header
+ # is always the same size.
+ switch (CQ_HFMT(cc)) {
+ case CQ_HNONE:
+ ;
+ case CQ_HHTTP:
+ repeat {
+ nchars = getline (fd, Memc[inbuf])
+ if (nchars <= 0)
+ break
+ Memc[inbuf+nchars] = EOS
+ } until ((Memc[inbuf] == '\r' && Memc[inbuf+1] == '\n') ||
+ (Memc[inbuf] == '\n'))
+ default:
+ ;
+ }
+
+ # Get the data.
+ repeat {
+ nchars = read (fd, Memc[inbuf], DEF_SZ_INBUF)
+ if (nchars > 0) {
+ Memc[inbuf+nchars] = EOS
+ call write (outfd, Memc[inbuf], nchars)
+ done = false
+ } else {
+ done = true
+ }
+ } until (done)
+
+ # Cleanup.
+ call mfree (inbuf, TY_CHAR)
+ inbuf = NULL
+ call flush (outfd)
+ call close (outfd)
+ outfd = NULL
+ call close (fd)
+ fd = NULL
+
+ } then {
+ if (inbuf != NULL)
+ call mfree (inbuf, TY_CHAR)
+ if (outfd != NULL) {
+ call close (outfd)
+ call delete (imname)
+ }
+ if (fd != NULL)
+ call close (fd)
+ if (res != NULL)
+ call cq_imclose (res)
+ return (NULL)
+ }
+
+ # Return the results pointer.
+ return (res)
+end
+
+
+# CQ_IMCLOSE -- Close the results structure,
+
+procedure cq_imclose (res)
+
+pointer res #U the results descriptor.
+
+begin
+ call cq_irfree (res)
+end
+
+
+# CQ_FIRINIT -- Initialize an image results descriptor.
+
+pointer procedure cq_firinit (cq)
+
+pointer cq #I the catalog descriptor
+
+pointer cc, res
+pointer sp, value, wpname, wkname, wkdvalue, wkvalue, wkunits
+int i, ncount, sz1, sz2, sz3, sz4, sz5, op1, op2, op3, op4, op5
+char ftype
+int cq_dgeti(), strdic(), cq_dscan(), nscan()
+int gstrcpy(), cq_dtype()
+errchk cq_dgwrd(), cq_dgeti(), cq_dscan()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+ cc = CQ_CAT(cq)
+
+ # Allocate the results structure.
+ call calloc (res, CQ_LEN_IM, TY_STRUCT)
+
+ # Format the query.
+ call smark (sp)
+ call salloc (value, CQ_SZ_QPVALUE, TY_CHAR)
+ call salloc (wpname, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (wkname, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (wkdvalue, CQ_SZ_QPVALUE, TY_CHAR)
+ call salloc (wkvalue, CQ_SZ_QPVALUE, TY_CHAR)
+ call salloc (wkunits, CQ_SZ_QPUNITS, TY_CHAR)
+
+ # Save the survey informaton and query in the results structure.
+ call strcpy (CQ_CATDB(cq), CQ_IMCATDB(res), SZ_FNAME)
+ call strcpy (CQ_CATNAME(cq), CQ_IMCATNAME(res), SZ_FNAME)
+ call strcpy ("", CQ_IMADDRESS(res), SZ_LINE)
+ call strcpy ("", CQ_IMQUERY(res), SZ_LINE)
+
+ # Copy the query parameters to the results descriptor.
+ CQ_INQPARS(res) = 0
+ CQ_IQPNAMES(res) = NULL
+ CQ_IQPVALUES(res) = NULL
+ CQ_IQPUNITS(res) = NULL
+
+ # Get the input image data type.
+ iferr {
+ call cq_dgwrd (cq, CQ_CATNO(cq), "type", Memc[value],
+ CQ_SZ_QPVALUE)
+ } then {
+ Memc[value] = EOS
+ CQ_IMTYPE(res) = CQ_FITS
+ } else {
+ CQ_IMTYPE(res) = strdic (Memc[value], Memc[value], CQ_SZ_QPVALUE,
+ CQ_ITYPESTR)
+ }
+
+ # Get the input image data type.
+ iferr {
+ call cq_dgwrd (cq, CQ_CATNO(cq), "wcs", Memc[value],
+ CQ_SZ_QPVALUE)
+ } then {
+ CQ_IMTYPE(res) = CQ_WNONE
+ } else {
+ CQ_WCS(res) = strdic (Memc[value], Memc[value], CQ_SZ_QPVALUE,
+ CQ_WTYPESTR)
+ }
+
+ # Get the number of wcs parameters.
+ iferr (CQ_NWCS(res) = cq_dgeti (cq, CQ_CATNO(cq), "nwcs"))
+ CQ_NWCS(res) = 0
+
+ # Allocate space for the wcs parameters.
+ call calloc (CQ_WPNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKDVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKTYPES(res), CQ_NWCS(res), TY_INT)
+ call calloc (CQ_WKUNITS(res), SZ_LINE, TY_CHAR)
+
+ # Get the wcs parameters.
+ ncount = 0
+ if (CQ_NWCS(res) > 0) {
+
+ # Initialize the header parameter keywords and values.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ sz3 = SZ_LINE; op3 = 2
+ sz4 = SZ_LINE; op4 = 2
+ sz5 = SZ_LINE; op5 = 2
+ call strcpy ("|", Memc[CQ_WPNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_WKNAMES(res)], sz2)
+ call strcpy ("|", Memc[CQ_WKDVALUES(res)], sz3)
+ call strcpy ("|", Memc[CQ_WKVALUES(res)], sz4)
+ call strcpy ("|", Memc[CQ_WKUNITS(res)], sz5)
+
+ do i = 1, CQ_NWCS(res) {
+
+ # Get the wcs parameter name, keyword, default value,
+ # data type and units value.
+ if (cq_dscan (cq) == EOF)
+ break
+ call gargwrd (Memc[wpname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkdvalue], CQ_SZ_QPVALUE)
+ call gargc (ftype)
+ call gargwrd (Memc[wkunits], CQ_SZ_QPUNITS)
+ if (nscan() != 5)
+ break
+
+ # Add the parameter name to the list.
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_WPNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[wpname], Memc[CQ_WPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_WPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ # Add the keyword name to the list.
+ if ((sz2 - op2 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_WKNAMES(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[wkname], Memc[CQ_WKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_WKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+
+ # Add the default keyword value to the list.
+ if ((sz3 - op3 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz3 = sz3 + SZ_LINE
+ call realloc (CQ_WKDVALUES(res), sz3, TY_CHAR)
+ }
+ op3 = op3 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_WKDVALUES(res)+op3-1], sz3 - op3 + 1)
+ op3 = op3 + gstrcpy ("|", Memc[CQ_WKDVALUES(res)+op3-1],
+ sz3 - op3 + 1)
+
+ # Add the keyword value to the list.
+ if ((sz4 - op4 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz4 = sz4 + SZ_LINE
+ call realloc (CQ_WKVALUES(res), sz4, TY_CHAR)
+ }
+ op4 = op4 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_WKVALUES(res)+op4-1], sz4 - op4 + 1)
+ op4 = op4 + gstrcpy ("|", Memc[CQ_WKVALUES(res)+op4-1],
+ sz4 - op4 + 1)
+
+ # Compute the data type.
+ Memi[CQ_WKTYPES(res)+i-1] = cq_dtype (ftype)
+
+ # Add the default keyword value to the list.
+ if ((sz5 - op5 + 1) < (CQ_SZ_QPUNITS + 1)) {
+ sz5 = sz5 + SZ_LINE
+ call realloc (CQ_WKUNITS(res), sz5, TY_CHAR)
+ }
+ op5 = op5 + gstrcpy (Memc[wkunits],
+ Memc[CQ_WKUNITS(res)+op5-1], sz5 - op5 + 1)
+ op5 = op5 + gstrcpy ("|", Memc[CQ_WKUNITS(res)+op5-1],
+ sz5 - op5 + 1)
+
+ ncount = ncount + 1
+ }
+ }
+
+ # Resize the wcs parameter arrays.
+ if (ncount != CQ_NWCS(res)) {
+ CQ_NWCS(res) = 0
+ call realloc (CQ_WPNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_WKNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_WKDVALUES(res), 1, TY_CHAR)
+ call realloc (CQ_WKVALUES(res), 1, TY_CHAR)
+ call mfree (CQ_WKTYPES(res), TY_INT)
+ CQ_WKTYPES(res) = NULL
+ call realloc (CQ_WKUNITS(res), 1, TY_CHAR)
+ } else {
+ call realloc (CQ_WPNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_WKNAMES(res), op2, TY_CHAR)
+ call realloc (CQ_WKDVALUES(res), op3, TY_CHAR)
+ call realloc (CQ_WKVALUES(res), op4, TY_CHAR)
+ call realloc (CQ_WKUNITS(res), op5, TY_CHAR)
+ Memc[CQ_WPNAMES(res)+op1] = EOS
+ Memc[CQ_WKNAMES(res)+op2] = EOS
+ Memc[CQ_WKDVALUES(res)+op3] = EOS
+ Memc[CQ_WKVALUES(res)+op4] = EOS
+ Memc[CQ_WKUNITS(res)+op5] = EOS
+ }
+
+ # Get the number of keyword parameters.
+ iferr (CQ_NIMPARS(res) = cq_dgeti (cq, CQ_CATNO(cq), "nkeys"))
+ CQ_NIMPARS(res) = 0
+
+ # Allocate space for the keyword parameters.
+ call calloc (CQ_IPNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKDVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKTYPES(res), CQ_NIMPARS(res), TY_INT)
+ call calloc (CQ_IKUNITS(res), SZ_LINE, TY_CHAR)
+
+ # Get the keyword parameters.
+ ncount = 0
+ if (CQ_NIMPARS(res) > 0) {
+
+ # Initialize the header parameter keywords and values.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ sz3 = SZ_LINE; op3 = 2
+ sz4 = SZ_LINE; op4 = 2
+ sz5 = SZ_LINE; op5 = 2
+ call strcpy ("|", Memc[CQ_IPNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_IKNAMES(res)], sz2)
+ call strcpy ("|", Memc[CQ_IKDVALUES(res)], sz3)
+ call strcpy ("|", Memc[CQ_IKVALUES(res)], sz4)
+ call strcpy ("|", Memc[CQ_IKUNITS(res)], sz5)
+
+ do i = 1, CQ_NIMPARS(res) {
+
+ # Get the wcs parameter name, keyword, default value,
+ # data type and units value.
+ if (cq_dscan (cq) == EOF)
+ break
+ call gargwrd (Memc[wpname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkdvalue], CQ_SZ_QPVALUE)
+ call gargc (ftype)
+ call gargwrd (Memc[wkunits], CQ_SZ_QPUNITS)
+ if (nscan() != 5)
+ break
+
+ # Add the parameter name to the list.
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_IPNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[wpname], Memc[CQ_IPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_IPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ # Add the keyword name to the list.
+ if ((sz2 - op2 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_IKNAMES(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[wkname], Memc[CQ_IKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_IKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+
+ # Add the default keyword value to the list.
+ if ((sz3 - op3 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz3 = sz3 + SZ_LINE
+ call realloc (CQ_IKDVALUES(res), sz3, TY_CHAR)
+ }
+ op3 = op3 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_IKDVALUES(res)+op3-1], sz3 - op3 + 1)
+ op3 = op3 + gstrcpy ("|", Memc[CQ_IKDVALUES(res)+op3-1],
+ sz3 - op3 + 1)
+
+ # Add the keyword value to the list.
+ if ((sz4 - op4 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz4 = sz4 + SZ_LINE
+ call realloc (CQ_IKVALUES(res), sz4, TY_CHAR)
+ }
+ op4 = op4 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_IKVALUES(res)+op4-1], sz4 - op4 + 1)
+ op4 = op4 + gstrcpy ("|", Memc[CQ_IKVALUES(res)+op4-1],
+ sz4 - op4 + 1)
+
+ # Compute the data type.
+ Memi[CQ_IKTYPES(res)+i-1] = cq_dtype (ftype)
+
+ # Add the default keyword value to the list.
+ if ((sz5 - op5 + 1) < (CQ_SZ_QPUNITS + 1)) {
+ sz5 = sz5 + SZ_LINE
+ call realloc (CQ_IKUNITS(res), sz5, TY_CHAR)
+ }
+ op5 = op5 + gstrcpy (Memc[wkunits],
+ Memc[CQ_IKUNITS(res)+op5-1], sz5 - op5 + 1)
+ op5 = op5 + gstrcpy ("|", Memc[CQ_IKUNITS(res)+op5-1],
+ sz5 - op5 + 1)
+
+ ncount = ncount + 1
+
+ }
+ }
+
+ # Resize the wcs parameter arrays.
+ if (ncount != CQ_NIMPARS(res)) {
+ CQ_NIMPARS(res) = 0
+ call realloc (CQ_IPNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_IKNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_IKDVALUES(res), 1, TY_CHAR)
+ call realloc (CQ_IKVALUES(res), 1, TY_CHAR)
+ call mfree (CQ_IKTYPES(res), TY_INT)
+ CQ_IKTYPES(res) = NULL
+ call realloc (CQ_IKUNITS(res), 1, TY_CHAR)
+ } else {
+ call realloc (CQ_IPNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_IKNAMES(res), op2, TY_CHAR)
+ call realloc (CQ_IKDVALUES(res), op3, TY_CHAR)
+ call realloc (CQ_IKVALUES(res), op4, TY_CHAR)
+ call realloc (CQ_IKUNITS(res), op5, TY_CHAR)
+ Memc[CQ_IPNAMES(res)+op1] = EOS
+ Memc[CQ_IKNAMES(res)+op2] = EOS
+ Memc[CQ_IKDVALUES(res)+op3] = EOS
+ Memc[CQ_IKVALUES(res)+op4] = EOS
+ Memc[CQ_IKUNITS(res)+op5] = EOS
+ }
+
+ call sfree (sp)
+
+ return (res)
+end
+
+
+# CQ_IRINIT -- Initialize an image results descriptor.
+
+pointer procedure cq_irinit (cq)
+
+pointer cq #I the catalog descriptor
+
+pointer cc, res
+pointer sp, query, value, wpname, wkname, wkdvalue, wkvalue, wkunits
+int i, fsize, ncount, sz1, sz2, sz3, sz4, sz5, op1, op2, op3, op4, op5
+char ftype
+int cq_wrdstr(), cq_dgeti(), strlen(), strdic(), cq_dscan(), nscan()
+int gstrcpy(), cq_dtype()
+errchk cq_dgwrd(), cq_dgeti(), cq_dscan()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+ cc = CQ_CAT(cq)
+
+ # Allocate the results structure.
+ call calloc (res, CQ_LEN_IM, TY_STRUCT)
+
+ # Format the query.
+ call smark (sp)
+ call salloc (query, SZ_LINE, TY_CHAR)
+ call salloc (value, CQ_SZ_QPVALUE, TY_CHAR)
+ call sprintf (Memc[query], SZ_LINE, CQ_QUERY(cc))
+ do i = 1, CQ_NQPARS(cc) {
+ if (cq_wrdstr (i, Memc[value], CQ_SZ_QPVALUE,
+ Memc[CQ_PQPVALUES(cc)]) <= 0)
+ next
+ call pargstr (Memc[value])
+ }
+
+ # Save the survey informaton and query in the results structure.
+ call strcpy (CQ_CATDB(cq), CQ_IMCATDB(res), SZ_FNAME)
+ call strcpy (CQ_CATNAME(cq), CQ_IMCATNAME(res), SZ_FNAME)
+ call strcpy (CQ_ADDRESS(cc), CQ_IMADDRESS(res), SZ_LINE)
+ call strcpy (Memc[query], CQ_IMQUERY(res), SZ_LINE)
+
+ # Copy the query parameters to the results descriptor.
+ CQ_INQPARS(res) = CQ_NQPARS(cc)
+ fsize = strlen (Memc[CQ_PQPNAMES(cc)])
+ call malloc (CQ_IQPNAMES(res), fsize, TY_CHAR)
+ call strcpy (Memc[CQ_PQPNAMES(cc)], Memc[CQ_IQPNAMES(res)], fsize)
+ fsize = strlen (Memc[CQ_PQPVALUES(cc)])
+ call malloc (CQ_IQPVALUES(res), fsize, TY_CHAR)
+ call strcpy (Memc[CQ_PQPVALUES(cc)], Memc[CQ_IQPVALUES(res)], fsize)
+ fsize = strlen (Memc[CQ_PQPUNITS(cc)])
+ call malloc (CQ_IQPUNITS(res), fsize, TY_CHAR)
+ call strcpy (Memc[CQ_PQPUNITS(cc)], Memc[CQ_IQPUNITS(res)], fsize)
+
+ # Get the input image data type.
+ iferr {
+ call cq_dgwrd (cq, CQ_CATNO(cq), "type", Memc[value],
+ CQ_SZ_QPVALUE)
+ } then {
+ Memc[value] = EOS
+ CQ_IMTYPE(res) = CQ_FITS
+ } else {
+ CQ_IMTYPE(res) = strdic (Memc[value], Memc[value], CQ_SZ_QPVALUE,
+ CQ_ITYPESTR)
+ }
+
+ call salloc (wpname, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (wkname, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (wkdvalue, CQ_SZ_QPVALUE, TY_CHAR)
+ call salloc (wkvalue, CQ_SZ_QPVALUE, TY_CHAR)
+ call salloc (wkunits, CQ_SZ_QPUNITS, TY_CHAR)
+
+ # Get the input image data type.
+ iferr {
+ call cq_dgwrd (cq, CQ_CATNO(cq), "wcs", Memc[value],
+ CQ_SZ_QPVALUE)
+ } then {
+ CQ_IMTYPE(res) = CQ_WNONE
+ } else {
+ CQ_WCS(res) = strdic (Memc[value], Memc[value], CQ_SZ_QPVALUE,
+ CQ_WTYPESTR)
+ }
+
+ # Get the number of wcs parameters.
+ iferr (CQ_NWCS(res) = cq_dgeti (cq, CQ_CATNO(cq), "nwcs"))
+ CQ_NWCS(res) = 0
+
+ # Allocate space for the wcs parameters.
+ call calloc (CQ_WPNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKDVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_WKTYPES(res), CQ_NWCS(res), TY_INT)
+ call calloc (CQ_WKUNITS(res), SZ_LINE, TY_CHAR)
+
+ # Get the wcs parameters.
+ ncount = 0
+ if (CQ_NWCS(res) > 0) {
+
+ # Initialize the header parameter keywords and values.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ sz3 = SZ_LINE; op3 = 2
+ sz4 = SZ_LINE; op4 = 2
+ sz5 = SZ_LINE; op5 = 2
+ call strcpy ("|", Memc[CQ_WPNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_WKNAMES(res)], sz2)
+ call strcpy ("|", Memc[CQ_WKDVALUES(res)], sz3)
+ call strcpy ("|", Memc[CQ_WKVALUES(res)], sz4)
+ call strcpy ("|", Memc[CQ_WKUNITS(res)], sz5)
+
+
+ do i = 1, CQ_NWCS(res) {
+
+ # Get the wcs parameter name, keyword, default value,
+ # data type and units value.
+ if (cq_dscan (cq) == EOF)
+ break
+ call gargwrd (Memc[wpname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkdvalue], CQ_SZ_QPVALUE)
+ call gargc (ftype)
+ call gargwrd (Memc[wkunits], CQ_SZ_QPUNITS)
+ if (nscan() != 5)
+ break
+
+ # Add the parameter name to the list.
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_WPNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[wpname], Memc[CQ_WPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_WPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ # Add the keyword name to the list.
+ if ((sz2 - op2 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_WKNAMES(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[wkname], Memc[CQ_WKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_WKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+
+ # Add the default keyword value to the list.
+ if ((sz3 - op3 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz3 = sz3 + SZ_LINE
+ call realloc (CQ_WKDVALUES(res), sz3, TY_CHAR)
+ }
+ op3 = op3 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_WKDVALUES(res)+op3-1], sz3 - op3 + 1)
+ op3 = op3 + gstrcpy ("|", Memc[CQ_WKDVALUES(res)+op3-1],
+ sz3 - op3 + 1)
+
+ # Add the keyword value to the list.
+ if ((sz4 - op4 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz4 = sz4 + SZ_LINE
+ call realloc (CQ_WKVALUES(res), sz4, TY_CHAR)
+ }
+ op4 = op4 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_WKVALUES(res)+op4-1], sz4 - op4 + 1)
+ op4 = op4 + gstrcpy ("|", Memc[CQ_WKVALUES(res)+op4-1],
+ sz4 - op4 + 1)
+
+ # Compute the data type.
+ Memi[CQ_WKTYPES(res)+i-1] = cq_dtype (ftype)
+
+ # Add the default keyword value to the list.
+ if ((sz5 - op5 + 1) < (CQ_SZ_QPUNITS + 1)) {
+ sz5 = sz5 + SZ_LINE
+ call realloc (CQ_WKUNITS(res), sz5, TY_CHAR)
+ }
+ op5 = op5 + gstrcpy (Memc[wkunits],
+ Memc[CQ_WKUNITS(res)+op5-1], sz5 - op5 + 1)
+ op5 = op5 + gstrcpy ("|", Memc[CQ_WKUNITS(res)+op5-1],
+ sz5 - op5 + 1)
+
+ ncount = ncount + 1
+ }
+ }
+
+ # Resize the wcs parameter arrays.
+ if (ncount != CQ_NWCS(res)) {
+ CQ_NWCS(res) = 0
+ call realloc (CQ_WPNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_WKNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_WKDVALUES(res), 1, TY_CHAR)
+ call realloc (CQ_WKVALUES(res), 1, TY_CHAR)
+ call mfree (CQ_WKTYPES(res), TY_INT)
+ CQ_WKTYPES(res) = NULL
+ call realloc (CQ_WKUNITS(res), 1, TY_CHAR)
+ } else {
+ call realloc (CQ_WPNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_WKNAMES(res), op2, TY_CHAR)
+ call realloc (CQ_WKDVALUES(res), op3, TY_CHAR)
+ call realloc (CQ_WKVALUES(res), op4, TY_CHAR)
+ call realloc (CQ_WKUNITS(res), op5, TY_CHAR)
+ Memc[CQ_WPNAMES(res)+op1] = EOS
+ Memc[CQ_WKNAMES(res)+op2] = EOS
+ Memc[CQ_WKDVALUES(res)+op3] = EOS
+ Memc[CQ_WKVALUES(res)+op4] = EOS
+ Memc[CQ_WKUNITS(res)+op5] = EOS
+ }
+
+ # Get the number of keyword parameters.
+ iferr (CQ_NIMPARS(res) = cq_dgeti (cq, CQ_CATNO(cq), "nkeys"))
+ CQ_NIMPARS(res) = 0
+
+ # Allocate space for the keyword parameters.
+ call calloc (CQ_IPNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKDVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKVALUES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_IKTYPES(res), CQ_NIMPARS(res), TY_INT)
+ call calloc (CQ_IKUNITS(res), SZ_LINE, TY_CHAR)
+
+ # Get the keyword parameters.
+ ncount = 0
+ if (CQ_NIMPARS(res) > 0) {
+
+ # Initialize the header parameter keywords and values.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ sz3 = SZ_LINE; op3 = 2
+ sz4 = SZ_LINE; op4 = 2
+ sz5 = SZ_LINE; op5 = 2
+ call strcpy ("|", Memc[CQ_IPNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_IKNAMES(res)], sz2)
+ call strcpy ("|", Memc[CQ_IKDVALUES(res)], sz3)
+ call strcpy ("|", Memc[CQ_IKVALUES(res)], sz4)
+ call strcpy ("|", Memc[CQ_IKUNITS(res)], sz5)
+
+ do i = 1, CQ_NIMPARS(res) {
+
+ # Get the wcs parameter name, keyword, default value,
+ # data type and units value.
+ if (cq_dscan (cq) == EOF)
+ break
+ call gargwrd (Memc[wpname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[wkdvalue], CQ_SZ_QPVALUE)
+ call gargc (ftype)
+ call gargwrd (Memc[wkunits], CQ_SZ_QPUNITS)
+ if (nscan() != 5)
+ break
+
+ # Add the parameter name to the list.
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_IPNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[wpname], Memc[CQ_IPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_IPNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ # Add the keyword name to the list.
+ if ((sz2 - op2 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_IKNAMES(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[wkname], Memc[CQ_IKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_IKNAMES(res)+op2-1],
+ sz2 - op2 + 1)
+
+ # Add the default keyword value to the list.
+ if ((sz3 - op3 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz3 = sz3 + SZ_LINE
+ call realloc (CQ_IKDVALUES(res), sz3, TY_CHAR)
+ }
+ op3 = op3 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_IKDVALUES(res)+op3-1], sz3 - op3 + 1)
+ op3 = op3 + gstrcpy ("|", Memc[CQ_IKDVALUES(res)+op3-1],
+ sz3 - op3 + 1)
+
+ # Add the keyword value to the list.
+ if ((sz4 - op4 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz4 = sz4 + SZ_LINE
+ call realloc (CQ_IKVALUES(res), sz4, TY_CHAR)
+ }
+ op4 = op4 + gstrcpy (Memc[wkdvalue],
+ Memc[CQ_IKVALUES(res)+op4-1], sz4 - op4 + 1)
+ op4 = op4 + gstrcpy ("|", Memc[CQ_IKVALUES(res)+op4-1],
+ sz4 - op4 + 1)
+
+ # Compute the data type.
+ Memi[CQ_IKTYPES(res)+i-1] = cq_dtype (ftype)
+
+ # Add the default keyword value to the list.
+ if ((sz5 - op5 + 1) < (CQ_SZ_QPUNITS + 1)) {
+ sz5 = sz5 + SZ_LINE
+ call realloc (CQ_IKUNITS(res), sz5, TY_CHAR)
+ }
+ op5 = op5 + gstrcpy (Memc[wkunits],
+ Memc[CQ_IKUNITS(res)+op5-1], sz5 - op5 + 1)
+ op5 = op5 + gstrcpy ("|", Memc[CQ_IKUNITS(res)+op5-1],
+ sz5 - op5 + 1)
+
+ ncount = ncount + 1
+
+ }
+ }
+
+ # Resize the wcs parameter arrays.
+ if (ncount != CQ_NIMPARS(res)) {
+ CQ_NIMPARS(res) = 0
+ call realloc (CQ_IPNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_IKNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_IKDVALUES(res), 1, TY_CHAR)
+ call realloc (CQ_IKVALUES(res), 1, TY_CHAR)
+ call mfree (CQ_IKTYPES(res), TY_INT)
+ CQ_IKTYPES(res) = NULL
+ call realloc (CQ_IKUNITS(res), 1, TY_CHAR)
+ } else {
+ call realloc (CQ_IPNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_IKNAMES(res), op2, TY_CHAR)
+ call realloc (CQ_IKDVALUES(res), op3, TY_CHAR)
+ call realloc (CQ_IKVALUES(res), op4, TY_CHAR)
+ call realloc (CQ_IKUNITS(res), op5, TY_CHAR)
+ Memc[CQ_IPNAMES(res)+op1] = EOS
+ Memc[CQ_IKNAMES(res)+op2] = EOS
+ Memc[CQ_IKDVALUES(res)+op3] = EOS
+ Memc[CQ_IKVALUES(res)+op4] = EOS
+ Memc[CQ_IKUNITS(res)+op5] = EOS
+ }
+
+ call sfree (sp)
+
+ return (res)
+end
+
+
+# CQ_IRFREE -- Free the image results structure.
+
+procedure cq_irfree (res)
+
+pointer res #U the results descriptor.
+
+begin
+ # Free the query parameter names, values, and units.
+ if (CQ_IQPNAMES(res) != NULL)
+ call mfree (CQ_IQPNAMES(res), TY_CHAR)
+ if (CQ_IQPVALUES(res) != NULL)
+ call mfree (CQ_IQPVALUES(res), TY_CHAR)
+ if (CQ_IQPUNITS(res) != NULL)
+ call mfree (CQ_IQPUNITS(res), TY_CHAR)
+
+ # Free the wcs parameters.
+ if (CQ_WPNAMES(res) != NULL)
+ call mfree (CQ_WPNAMES(res), TY_CHAR)
+ if (CQ_WKNAMES(res) != NULL)
+ call mfree (CQ_WKNAMES(res), TY_CHAR)
+ if (CQ_WKDVALUES(res) != NULL)
+ call mfree (CQ_WKDVALUES(res), TY_CHAR)
+ if (CQ_WKVALUES(res) != NULL)
+ call mfree (CQ_WKVALUES(res), TY_CHAR)
+ if (CQ_WKTYPES(res) != NULL)
+ call mfree (CQ_WKTYPES(res), TY_INT)
+ if (CQ_WKUNITS(res) != NULL)
+ call mfree (CQ_WKUNITS(res), TY_CHAR)
+
+ # Free the image keyword parameters.
+ if (CQ_IPNAMES(res) != NULL)
+ call mfree (CQ_IPNAMES(res), TY_CHAR)
+ if (CQ_IKNAMES(res) != NULL)
+ call mfree (CQ_IKNAMES(res), TY_CHAR)
+ if (CQ_IKDVALUES(res) != NULL)
+ call mfree (CQ_IKDVALUES(res), TY_CHAR)
+ if (CQ_IKVALUES(res) != NULL)
+ call mfree (CQ_IKVALUES(res), TY_CHAR)
+ if (CQ_IKTYPES(res) != NULL)
+ call mfree (CQ_IKTYPES(res), TY_INT)
+ if (CQ_IKUNITS(res) != NULL)
+ call mfree (CQ_IKUNITS(res), TY_CHAR)
+
+ if (res != NULL)
+ call mfree (res, TY_STRUCT)
+end
diff --git a/pkg/xtools/catquery/cqistat.x b/pkg/xtools/catquery/cqistat.x
new file mode 100644
index 00000000..0ae35527
--- /dev/null
+++ b/pkg/xtools/catquery/cqistat.x
@@ -0,0 +1,161 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_ISTATI -- Get an integer image results parameter.
+
+int procedure cq_istati (res, param)
+
+pointer res #I pointer to the results descriptor
+int param #I the integer parameter to be retrieved
+
+begin
+ switch (param) {
+ case CQINQPARS:
+ return (CQ_INQPARS(res))
+ case CQIMTYPE:
+ return (CQ_IMTYPE(res))
+ case CQWCS:
+ return (CQ_WCS(res))
+ case CQNWCS:
+ return (CQ_NWCS(res))
+ case CQNIMPARS:
+ return (CQ_NIMPARS(res))
+ default:
+ call error (0, "Error fetching integer image results parameter")
+ }
+end
+
+
+# CQ_ISTATR -- Get a real image results parameter.
+
+real procedure cq_istatr (res, param)
+
+pointer res #I pointer to the image results descriptor
+int param #I the real image parameter to be retrieved
+
+begin
+ switch (param) {
+ default:
+ call error (0, "Error fetching real results parameter")
+ }
+end
+
+
+# CQ_ISTATD -- Get a double precision image results parameter.
+
+double procedure cq_istatd (res, param)
+
+pointer res #I pointer to the image results descriptor
+int param #I the double parameter to be retrieved
+
+begin
+ switch (param) {
+ default:
+ call error (0, "Error fetching double results parameter")
+ }
+end
+
+
+# CQ_ISTATS -- Get a string image results parameter.
+
+procedure cq_istats (res, param, str, maxch)
+
+pointer res #I pointer to the results descriptor
+int param #I the string parameter to be retrieved
+char str[ARB] #O the output string parameter
+int maxch #I the maximum size of the string parameter
+
+begin
+ switch (param) {
+ case CQIQPNAMES:
+ call strcpy (Memc[CQ_IQPNAMES(res)], str, maxch)
+ case CQIQPVALUES:
+ call strcpy (Memc[CQ_IQPVALUES(res)], str, maxch)
+ case CQIQPUNITS:
+ call strcpy (Memc[CQ_IQPUNITS(res)], str, maxch)
+ case CQIMCATDB:
+ call strcpy (CQ_IMCATDB(res), str, maxch)
+ case CQIMCATNAME:
+ call strcpy (CQ_IMCATNAME(res), str, maxch)
+ case CQIMADDRESS:
+ call strcpy (CQ_IMADDRESS(res), str, maxch)
+ case CQIMQUERY:
+ call strcpy (CQ_IMQUERY(res), str, maxch)
+ case CQIMNAME:
+ call strcpy (CQ_IMNAME(res), str, maxch)
+ default:
+ call error (0, "Error fetching string results parameter")
+ }
+end
+
+
+# CQ_ISTATT -- Get a text list results parameter. A text list is a
+# string with items separated from each other by newlines.
+
+int procedure cq_istatt (res, param, str, maxch)
+
+pointer res #I pointer to the results descriptor
+int param #I the list parameter to be retrieved
+char str[ARB] #O the output string parameter
+int maxch #I the maximum size of the string parameter
+
+pointer sp, tstr
+int i, fd
+int stropen(), cq_wrdstr()
+
+begin
+ switch (param) {
+
+ case CQIQPNAMES:
+ call smark (sp)
+ call salloc (tstr, CQ_SZ_QPNAME, TY_CHAR)
+ fd = stropen (str, maxch, NEW_FILE)
+ str[1] = EOS
+ do i = 1, CQ_INQPARS(res) {
+ if (cq_wrdstr (i, Memc[tstr], CQ_SZ_QPNAME,
+ Memc[CQ_IQPNAMES(res)]) > 0) {
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[tstr])
+ }
+ }
+ call close (fd)
+ call sfree (sp)
+ return (CQ_INQPARS(res))
+
+ case CQIQPVALUES:
+ call smark (sp)
+ call salloc (tstr, CQ_SZ_QPVALUE, TY_CHAR)
+ fd = stropen (str, maxch, NEW_FILE)
+ str[1] = EOS
+ do i = 1, CQ_INQPARS(res) {
+ if (cq_wrdstr (i, Memc[tstr], CQ_SZ_QPVALUE,
+ Memc[CQ_IQPVALUES(res)]) > 0) {
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[tstr])
+ }
+ }
+ call close (fd)
+ call sfree (sp)
+ return (CQ_INQPARS(res))
+
+ case CQIQPUNITS:
+ call smark (sp)
+ call salloc (tstr, CQ_SZ_QPUNITS, TY_CHAR)
+ fd = stropen (str, maxch, NEW_FILE)
+ str[1] = EOS
+ do i = 1, CQ_INQPARS(res) {
+ if (cq_wrdstr (i, Memc[tstr], CQ_SZ_QPUNITS,
+ Memc[CQ_IQPUNITS(res)]) > 0) {
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[tstr])
+ }
+ }
+ call close (fd)
+ call sfree (sp)
+ return (CQ_INQPARS(res))
+
+ default:
+ call error (0, "Error fetching list image results parameter")
+ }
+end
diff --git a/pkg/xtools/catquery/cqlocate.x b/pkg/xtools/catquery/cqlocate.x
new file mode 100644
index 00000000..7070f8c0
--- /dev/null
+++ b/pkg/xtools/catquery/cqlocate.x
@@ -0,0 +1,40 @@
+include "cqdef.h"
+
+# CQ_LOCATE -- Locate a catalog by name. Return 0 if the catalog is not found.
+
+int procedure cq_locate (cq, name)
+
+pointer cq #I the catalog descriptor
+char name[ARB] #I the catalog name
+
+int i
+bool streq()
+
+begin
+ do i = 1, CQ_NRECS(cq) {
+ if (streq (name, CQ_NAME(cq, i)))
+ return (i)
+ }
+
+ return (0)
+end
+
+
+# CQ_LOCATEN -- Locate a catalog by number and retrieve its name. Return 0 if
+# the catalog is not found.
+
+int procedure cq_locaten (cq, catno, name, maxch)
+
+pointer cq #I the catalog descriptor
+int catno #I the catalog sequence record number
+char name[ARB] #O the output catalog name
+int maxch #I the maximum size of the catalog name
+
+begin
+ if (catno > 0 && catno <= CQ_NRECS(cq)) {
+ call strcpy (CQ_NAME(cq, catno), name, maxch)
+ return (catno)
+ }
+
+ return (0)
+end
diff --git a/pkg/xtools/catquery/cqmap.x b/pkg/xtools/catquery/cqmap.x
new file mode 100644
index 00000000..75ad4c2f
--- /dev/null
+++ b/pkg/xtools/catquery/cqmap.x
@@ -0,0 +1,112 @@
+include <ctype.h>
+include "cqdef.h"
+
+# CQ_MAP -- Map a catalog database.
+
+pointer procedure cq_map (database, mode)
+
+char database[ARB] #I The database file
+int mode #I The database file access mode
+
+int i, nrec, cq_alloc1, cq_alloc2
+pointer cq, str
+
+long note()
+int open(), fscan(), strlen()
+bool streq()
+errchk open()
+
+begin
+ if (mode != READ_ONLY && mode != NEW_FILE && mode != APPEND)
+ return (NULL)
+
+ iferr (i = open (database, mode, TEXT_FILE))
+ return (NULL)
+
+ call calloc (cq, CQ_LEN, TY_STRUCT)
+ call strcpy (database, CQ_CATDB(cq), SZ_FNAME)
+ CQ_FD(cq) = i
+
+ if (mode != READ_ONLY)
+ return (cq)
+
+ cq_alloc1 = CQ_ALLOC
+ cq_alloc2 = CQ_ALLOC * SZ_LINE
+ call malloc (CQ_OFFSETS(cq), cq_alloc1, TY_LONG)
+ call malloc (CQ_NAMES(cq), cq_alloc1, TY_INT)
+ call malloc (CQ_MAP(cq), cq_alloc2, TY_CHAR)
+ call malloc (str, SZ_LINE, TY_CHAR)
+
+ nrec = 1
+ CQ_NRECS(cq) = 0
+ CQ_NAMEI(cq, nrec) = 0
+
+ while (fscan (CQ_FD(cq)) != EOF) {
+ call gargwrd (CQ_NAME(cq, nrec), SZ_LINE)
+
+ if (streq (CQ_NAME(cq, nrec), "begin")) {
+ call gargstr (Memc[str], SZ_LINE)
+ for (i=str; IS_WHITE(Memc[i]); i=i+1)
+ ;
+ call strcpy (Memc[i], CQ_NAME(cq,nrec), SZ_LINE)
+
+ for (i = 1; i < nrec; i = i + 1)
+ if (streq (CQ_NAME(cq, i), CQ_NAME(cq, nrec)))
+ break
+
+ if (i < nrec)
+ CQ_OFFSET(cq, i) = note (CQ_FD(cq))
+ else {
+ CQ_NRECS(cq) = nrec
+ CQ_OFFSET(cq, nrec) = note (CQ_FD(cq))
+ CQ_NAMEI(cq, nrec+1) = CQ_NAMEI(cq, nrec) +
+ strlen (CQ_NAME(cq, nrec)) + 1
+ nrec = nrec + 1
+ }
+
+ if (nrec == cq_alloc1) {
+ cq_alloc1 = cq_alloc1 + CQ_ALLOC
+ call realloc (CQ_OFFSETS(cq), cq_alloc1, TY_LONG)
+ call realloc (CQ_NAMES(cq), cq_alloc1, TY_INT)
+ }
+ if (CQ_NAMEI(cq, nrec) + SZ_LINE >= cq_alloc2) {
+ cq_alloc2 = cq_alloc2 + CQ_ALLOC * SZ_LINE
+ call realloc (CQ_MAP(cq), cq_alloc2, TY_CHAR)
+ }
+ }
+ }
+
+ call realloc (CQ_MAP(cq), CQ_NAMEI(cq, nrec), TY_CHAR)
+ call realloc (CQ_OFFSETS(cq), CQ_NRECS(cq), TY_LONG)
+ call realloc (CQ_NAMES(cq), CQ_NRECS(cq), TY_INT)
+ call mfree (str, TY_CHAR)
+
+ return (cq)
+end
+
+
+# CQ_UNMAP -- Close the database.
+
+procedure cq_unmap (cq)
+
+pointer cq #U The database file descriptor
+
+begin
+ if (cq == NULL)
+ return
+
+ # Free the current catalog structure.
+ call cq_ccfree (cq)
+
+ # Close the catalog database file.
+ if (CQ_FD(cq) != NULL)
+ call close (CQ_FD(cq))
+
+ # Free the record mapping arrays.
+ call mfree (CQ_MAP(cq), TY_CHAR)
+ call mfree (CQ_OFFSETS(cq), TY_LONG)
+ call mfree (CQ_NAMES(cq), TY_INT)
+
+ # Free the structure.
+ call mfree (cq, TY_STRUCT)
+end
diff --git a/pkg/xtools/catquery/cqnqpars.x b/pkg/xtools/catquery/cqnqpars.x
new file mode 100644
index 00000000..d7769925
--- /dev/null
+++ b/pkg/xtools/catquery/cqnqpars.x
@@ -0,0 +1,18 @@
+include "cqdef.h"
+
+
+# CQ_NQPARS -- Return the number of query parameters. Do we really need
+# a special routine ?
+
+int procedure cq_nqpars (cq)
+
+pointer cq #I the catalog descriptor
+
+begin
+ if (CQ_CAT(cq) == NULL)
+ return (0)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (0)
+
+ return (CQ_NQPARS(CQ_CAT(cq)))
+end
diff --git a/pkg/xtools/catquery/cqquery.x b/pkg/xtools/catquery/cqquery.x
new file mode 100644
index 00000000..1806484c
--- /dev/null
+++ b/pkg/xtools/catquery/cqquery.x
@@ -0,0 +1,998 @@
+include <fset.h>
+include <ctype.h>
+include "cqdef.h"
+include "cq.h"
+
+
+define DEF_SZ_INBUF 32768 # the maximum network transfer buffer size
+define DEF_SZ_INDEX 1000 # the record index length increment
+
+# CQ_QUERY -- Send a query and return the data.
+
+pointer procedure cq_query (cq)
+
+pointer cq #I the catalog database descriptor
+
+pointer cc, res, inbuf, line, sp, spfname
+char url[SZ_PATHNAME], addr[SZ_LINE], query[SZ_LINE], buf[SZ_LINE]
+int j, fd, nchars, nlines, nrecs, szindex, ip, op
+bool done
+long note()
+pointer cq_rinit()
+int ndopen(), strlen(), read(), open(), getline(), fstati(), url_get()
+errchk ndopen(), fprintf(), areadb(), awriteb(), open(), read()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+ cc = CQ_CAT(cq)
+
+
+ if (0<1&& USE_URLGET) {
+ # Initialize the image results structure.
+ res = cq_rinit (cq)
+
+ call strcpy (CQ_ADDRESS(cc), buf, SZ_LINE)
+ for (ip=1; buf[ip] != ':'; ip=ip+1) ; # skip 'inet:'
+ ip = ip + 1
+ for ( ; buf[ip] != ':'; ip=ip+1) ; # skip '80:'
+ ip = ip + 1
+ for (op=1; buf[ip] != ':'; ip=ip+1) {
+ addr[op] = buf[ip]
+ op = op + 1
+ }
+ addr[op] = EOS
+
+ call strcpy (CQ_RQUERY(res), buf, SZ_LINE)
+ for (op=1; !IS_WHITE(buf[op+4]); op=op+1)
+ query[op] = buf[op+4]
+ query[op] = EOS
+
+ call sprintf (url, SZ_LINE, "http://%s%s")
+ call pargstr (addr)
+ call pargstr (query)
+
+ iferr {
+ call smark (sp)
+ call salloc (spfname, SZ_FNAME, TY_CHAR)
+
+ call malloc (inbuf, DEF_SZ_INBUF, TY_CHAR)
+
+ # Open the output spool file.
+ call mktemp ("query", Memc[spfname], SZ_FNAME)
+
+ if (url_get (url, Memc[spfname], inbuf) < 0)
+ call error (0, "Cannot access url")
+
+ fd = open (Memc[spfname], READ_ONLY, TEXT_FILE)
+ CQ_RFD(res) = open (Memc[spfname], READ_WRITE, SPOOL_FILE)
+ repeat {
+ call aclrc (Memc[inbuf], DEF_SZ_INBUF)
+ nchars = read (fd, Memc[inbuf], DEF_SZ_INBUF)
+ if (nchars > 0) {
+ Memc[inbuf+nchars] = EOS
+ call write (CQ_RFD(res), Memc[inbuf], nchars)
+ done = false
+ } else
+ done = true
+ } until (done)
+ call flush (CQ_RFD(res))
+ call close (fd)
+
+ CQ_RBUF(res) = fstati (CQ_RFD(res), F_BUFPTR)
+ call seek (CQ_RFD(res), BOF)
+
+ call mfree (inbuf, TY_CHAR)
+ call sfree (sp)
+
+ } then {
+ if (res != NULL)
+ call cq_rfree (res)
+ return (NULL)
+ }
+
+ } else {
+
+ # Open the network connection.
+ iferr (fd = ndopen (CQ_ADDRESS(cc), READ_WRITE))
+ return (NULL)
+
+ # Initialize the results structure.
+ res = cq_rinit (cq)
+
+ # Send the query and get back the results.
+ iferr {
+
+ call smark (sp)
+
+ # Formulate the query.
+ switch (CQ_RTYPE(res)) {
+ case CQ_STEXT, CQ_BTEXT:
+ call fprintf (fd, "%s")
+ call pargstr (CQ_RQUERY(res))
+ default:
+ nchars = strlen (CQ_RQUERY(res))
+ call write (fd, CQ_RQUERY(res), nchars)
+ }
+ call flush (fd)
+
+ # Open the output spool file.
+ call salloc (spfname, SZ_FNAME, TY_CHAR)
+ call mktemp ("query", Memc[spfname], SZ_FNAME)
+ CQ_RFD(res) = open (Memc[spfname], READ_WRITE, SPOOL_FILE)
+ call sfree (sp)
+
+ # Get the data.
+ call malloc (inbuf, DEF_SZ_INBUF, TY_CHAR)
+ call fseti (fd, F_CANCEL, OK)
+
+ switch (CQ_HFMT(cc)) {
+ case CQ_HNONE:
+ ;
+ case CQ_HHTTP:
+ repeat {
+ nchars = getline (fd, Memc[inbuf])
+ if (nchars <= 0)
+ break
+ Memc[inbuf+nchars] = EOS
+ } until ((Memc[inbuf] == '\r' && Memc[inbuf+1] == '\n') ||
+ (Memc[inbuf] == '\n'))
+ default:
+ ;
+ }
+
+ repeat {
+ nchars = read (fd, Memc[inbuf], DEF_SZ_INBUF)
+ if (nchars > 0) {
+ Memc[inbuf+nchars] = EOS
+ call write (CQ_RFD(res), Memc[inbuf], nchars)
+ done = false
+ } else {
+ done = true
+ }
+ } until (done)
+
+ # Cleanup.
+ call flush (CQ_RFD(res))
+ call mfree (inbuf, TY_CHAR)
+ CQ_RBUF(res) = fstati (CQ_RFD(res), F_BUFPTR)
+ call seek (CQ_RFD(res), BOF)
+ call close (fd)
+
+ } then {
+ call cq_rfree (res)
+ call close (fd)
+ return (NULL)
+ }
+
+ }
+
+ # Construct the record index.
+ CQ_RNRECS(res) = 0
+ switch (CQ_RTYPE(res)) {
+ case CQ_STEXT, CQ_BTEXT:
+
+ # Initialize.
+ nlines = 0
+ nrecs = 0
+
+ # Iniitialize the index array.
+ szindex = DEF_SZ_INDEX
+ call malloc (line, SZ_LINE, TY_CHAR)
+ call calloc (CQ_RINDEX(res), szindex, TY_LONG)
+
+ # Create the index array.
+ repeat {
+ Meml[CQ_RINDEX(res)+nrecs] = note (CQ_RFD(res))
+ nchars = getline (CQ_RFD(res), Memc[line])
+ if (nchars == EOF)
+ break
+ nlines = nlines + 1
+ if (nlines <= CQ_RHSKIP(res))
+ next
+ if (Memc[line] == '\n')
+ next
+ #if (CQ_RECSIZE(res) > 0 && nchars != CQ_RECSIZE(res))
+ if (CQ_RECSIZE(res) > 0 && nchars > CQ_RECSIZE(res))
+ Meml[CQ_RINDEX(res)+nrecs] = EOF
+ else if (CQ_RTRIML(res) > 0 || CQ_RTRIMR(res) > 0) {
+ inbuf = CQ_RBUF(res) + Meml[CQ_RINDEX(res)+nrecs] - 1
+ do j = 1, min (CQ_RTRIML(res), nchars)
+ Memc[inbuf+j-1] = ' '
+ do j = nchars - CQ_RTRIMR(res), nchars - 1
+ Memc[inbuf+j-1] = ' '
+ }
+ nrecs = nrecs + 1
+ if (nrecs >= szindex) {
+ szindex = szindex + DEF_SZ_INDEX
+ call realloc (CQ_RINDEX(res), szindex, TY_LONG)
+ call aclrl (Meml[CQ_RINDEX(res)+szindex-DEF_SZ_INDEX],
+ DEF_SZ_INDEX)
+ }
+ }
+ call mfree (line, TY_CHAR)
+ CQ_RNRECS(res) = nrecs
+
+ # Remove the incorrectly sized and trailing records.
+ nrecs = 0
+ do j = 0, CQ_RNRECS(res) - CQ_RTSKIP(res) - 1 {
+ if (Meml[CQ_RINDEX(res)+j] == EOF)
+ next
+ Meml[CQ_RINDEX(res)+nrecs] = Meml[CQ_RINDEX(res)+j]
+ nrecs = nrecs + 1
+ }
+ CQ_RNRECS(res) = nrecs
+
+ # Resize the index array.
+ call realloc (CQ_RINDEX(res), max (1, CQ_RNRECS(res) + 1), TY_LONG)
+
+ default:
+ ;
+ }
+
+ # Return the results pointer.
+ return (res)
+end
+
+
+# CQ_FQUERY -- Treat a catalog file file as thought it were the results
+# of a query. The catalog file file name and file description are passed
+# to the routine as arguments.
+
+pointer procedure cq_fquery (cq, catfile, catfmt)
+
+pointer cq #I the catalog database descriptor
+char catfile[ARB] #I the input catalog file
+char catfmt[ARB] #I the input catalog description
+
+pointer res, inbuf, line, sp, spfname
+int j, fd, nchars, nlines, nrecs, szindex
+bool done
+pointer cq_frinit()
+long note()
+int access(), open(), read(), fstati(), getline()
+errchk open(), read()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+
+ # Check to see if the catalog file exists.
+ if (access (catfile, 0, 0) == NO)
+ return (NULL)
+
+ # Check to see if the fmt string is defined.
+ if (catfmt[1] == EOS)
+ return (NULL)
+
+ # Open the catalog file.
+ if (access (catfile, READ_ONLY, TEXT_FILE) == YES) {
+ iferr (fd = open (catfile, READ_ONLY, TEXT_FILE))
+ return (NULL)
+ } else {
+ iferr (fd = open (catfile, READ_ONLY, BINARY_FILE))
+ return (NULL)
+ }
+
+ # Initialize the results structure using the file description.
+ res = cq_frinit (cq, catfmt)
+ if (res == NULL)
+ return (NULL)
+
+ # Read in the results.
+ iferr {
+
+ # Open the output spool file.
+ call smark (sp)
+ call salloc (spfname, SZ_FNAME, TY_CHAR)
+ call mktemp ("query", Memc[spfname], SZ_FNAME)
+ #CQ_RFD(res) = open ("dev$null", READ_WRITE, SPOOL_FILE)
+ CQ_RFD(res) = open (Memc[spfname], READ_WRITE, SPOOL_FILE)
+ call sfree (sp)
+
+ # Get the data.
+ call malloc (inbuf, DEF_SZ_INBUF, TY_CHAR)
+ repeat {
+ nchars = read (fd, Memc[inbuf], DEF_SZ_INBUF)
+ if (nchars > 0) {
+ Memc[inbuf+nchars] = EOS
+ call write (CQ_RFD(res), Memc[inbuf], nchars)
+ done = false
+ } else {
+ done = true
+ }
+ } until (done)
+
+ # Cleanup.
+ call flush (CQ_RFD(res))
+ call mfree (inbuf, TY_CHAR)
+ CQ_RBUF(res) = fstati (CQ_RFD(res), F_BUFPTR)
+ call close (fd)
+
+ } then {
+ call cq_rfree (res)
+ call close (fd)
+ return (NULL)
+ }
+
+ # Construct the record index.
+ CQ_RNRECS(res) = 0
+ switch (CQ_RTYPE(res)) {
+ case CQ_STEXT, CQ_BTEXT:
+
+ # Initialize.
+ nlines = 0
+ nrecs = 0
+
+ # Iniitialize the index array.
+ szindex = DEF_SZ_INDEX
+ call malloc (line, SZ_LINE, TY_CHAR)
+ call calloc (CQ_RINDEX(res), szindex, TY_LONG)
+
+ # Create the index array.
+ call seek (CQ_RFD(res), BOF)
+ repeat {
+ Meml[CQ_RINDEX(res)+nrecs] = note (CQ_RFD(res))
+ nchars = getline (CQ_RFD(res), Memc[line])
+ if (nchars == EOF)
+ break
+ nlines = nlines + 1
+ if (nlines <= CQ_RHSKIP(res))
+ next
+ if (Memc[line] == '\n')
+ next
+ if (Memc[line] == '#')
+ next
+ #if (CQ_RECSIZE(res) > 0 && nchars != CQ_RECSIZE(res))
+ if (CQ_RECSIZE(res) > 0 && nchars > CQ_RECSIZE(res))
+ Meml[CQ_RINDEX(res)+nrecs] = EOF
+ else if (CQ_RTRIML(res) > 0 || CQ_RTRIMR(res) > 0) {
+ inbuf = CQ_RBUF(res) + Meml[CQ_RINDEX(res)+nrecs] - 1
+ do j = 1, min (CQ_RTRIML(res), nchars)
+ Memc[inbuf+j-1] = ' '
+ do j = nchars - CQ_RTRIMR(res), nchars - 1
+ Memc[inbuf+j-1] = ' '
+ }
+ nrecs = nrecs + 1
+ if (nrecs >= szindex) {
+ szindex = szindex + DEF_SZ_INDEX
+ call realloc (CQ_RINDEX(res), szindex, TY_LONG)
+ call aclrl (Meml[CQ_RINDEX(res)+szindex-DEF_SZ_INDEX],
+ DEF_SZ_INDEX)
+ }
+ }
+ call mfree (line, TY_CHAR)
+ CQ_RNRECS(res) = nrecs
+
+ # Check for and reject short records and trim trailing records.
+ nrecs = 0
+ do j = 0, CQ_RNRECS(res) - CQ_RTSKIP(res) - 1 {
+ if (Meml[CQ_RINDEX(res)+j] == EOF)
+ next
+ Meml[CQ_RINDEX(res)+nrecs] = Meml[CQ_RINDEX(res)+j]
+ nrecs = nrecs + 1
+ }
+ CQ_RNRECS(res) = nrecs
+
+ # Trim the trailing records.
+ call realloc (CQ_RINDEX(res), max (1, CQ_RNRECS(res) + 1), TY_LONG)
+
+ default:
+ ;
+ }
+
+ return (res)
+end
+
+
+# CQ_RCLOSE -- Close the results structure,
+
+procedure cq_rclose (res)
+
+pointer res #U the results descriptor.
+
+begin
+ call cq_rfree (res)
+end
+
+
+# CQ_RINIT -- Initialize a results descriptor.
+
+pointer procedure cq_rinit (cq)
+
+pointer cq #I the catalog descriptor
+
+pointer cc, res, sp, query, value, kname, fname, funits, ffmt
+int i, ncount, sz1, sz2, sz3, op1, op2, op3, foffset, fsize
+char ftype
+int cq_wrdstr(), strdic(), cq_dgeti(), cq_dscan(), nscan()
+int cq_dtype(), strlen(), gstrcpy()
+errchk cq_dgwrd(), cq_dgeti(), cq_dscan()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+ cc = CQ_CAT(cq)
+
+ # Allocate the results structure.
+ call calloc (res, CQ_LEN_RES, TY_STRUCT)
+
+ # Format the query.
+ call smark (sp)
+ call salloc (query, SZ_LINE, TY_CHAR)
+ call salloc (value, CQ_SZ_QPVALUE, TY_CHAR)
+ call sprintf (Memc[query], SZ_LINE, CQ_QUERY(cc))
+ do i = 1, CQ_NQPARS(cc) {
+ if (cq_wrdstr (i, Memc[value], CQ_SZ_QPVALUE,
+ Memc[CQ_PQPVALUES(cc)]) <= 0)
+ next
+ call pargstr (Memc[value])
+ }
+
+ # Save the catalog informaton and query in the results structure.
+ call strcpy (CQ_CATDB(cq), CQ_RCATDB(res), SZ_FNAME)
+ call strcpy (CQ_CATNAME(cq), CQ_RCATNAME(res), SZ_FNAME)
+ call strcpy (CQ_ADDRESS(cc), CQ_RADDRESS(res), SZ_LINE)
+ call strcpy (Memc[query], CQ_RQUERY(res), SZ_LINE)
+
+ # Copy the query parameters to the results descriptor.
+ CQ_RNQPARS(res) = CQ_NQPARS(cc)
+ fsize = strlen (Memc[CQ_PQPNAMES(cc)])
+ call malloc (CQ_RQPNAMES(res), fsize, TY_CHAR)
+ call strcpy (Memc[CQ_PQPNAMES(cc)], Memc[CQ_RQPNAMES(res)], fsize)
+ fsize = strlen (Memc[CQ_PQPVALUES(cc)])
+ call malloc (CQ_RQPVALUES(res), fsize, TY_CHAR)
+ call strcpy (Memc[CQ_PQPVALUES(cc)], Memc[CQ_RQPVALUES(res)], fsize)
+ fsize = strlen (Memc[CQ_PQPUNITS(cc)])
+ call malloc (CQ_RQPUNITS(res), fsize, TY_CHAR)
+ call strcpy (Memc[CQ_PQPUNITS(cc)], Memc[CQ_RQPUNITS(res)], fsize)
+
+ # Get the input data type.
+ iferr {
+ call cq_dgwrd (cq, CQ_CATNO(cq), "type", Memc[value],
+ CQ_SZ_QPVALUE)
+ } then {
+ Memc[value] = EOS
+ CQ_RTYPE(res) = CQ_STEXT
+ } else {
+ CQ_RTYPE(res) = strdic (Memc[value], Memc[value], CQ_SZ_QPVALUE,
+ CQ_RTYPESTR)
+ }
+
+ # Get the number of leading and trailing records to be skipped.
+ iferr (CQ_RHSKIP(res) = cq_dgeti (cq, CQ_CATNO(cq), "hskip"))
+ CQ_RHSKIP(res) = 0
+ iferr (CQ_RTSKIP(res) = cq_dgeti (cq, CQ_CATNO(cq), "tskip"))
+ CQ_RTSKIP(res) = 0
+
+ # Get the record size and trimming parameters.
+ iferr (CQ_RECSIZE(res) = cq_dgeti (cq, CQ_CATNO(cq), "recsize"))
+ CQ_RECSIZE(res) = 0
+ iferr (CQ_RTRIML(res) = cq_dgeti (cq, CQ_CATNO(cq), "triml"))
+ CQ_RTRIML(res) = 0
+ iferr (CQ_RTRIMR(res) = cq_dgeti (cq, CQ_CATNO(cq), "trimr"))
+ CQ_RTRIMR(res) = 0
+
+ iferr (CQ_NHEADER(res) = cq_dgeti (cq, CQ_CATNO(cq), "nheader"))
+ CQ_NHEADER(res) = 0
+
+ # Get the header parameters.
+ call calloc (CQ_HKNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_HKVALUES(res), SZ_LINE, TY_CHAR)
+ ncount = 0
+ if (CQ_NHEADER(res) > 0) {
+
+ # Initialize the header parameter keywords and values.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ call strcpy ("|", Memc[CQ_HKNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_HKVALUES(res)], sz2)
+
+ call salloc (kname, CQ_SZ_FNAME, TY_CHAR)
+ do i = 1, CQ_NHEADER(res) {
+
+ # Get the keyword and value.
+ if (cq_dscan (cq) == EOF)
+ break
+ call gargwrd (Memc[kname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[query], SZ_LINE)
+ if (nscan() != 2)
+ break
+
+ # Add the keyword name to the list.
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_HKNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[kname], Memc[CQ_HKNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_HKNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ # Add the keyword value to the list.
+ if ((sz2 - op2 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_HKVALUES(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[query], Memc[CQ_HKVALUES(res)+op2-1],
+ sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_HKVALUES(res)+op2-1],
+ sz2 - op2 + 1)
+
+ ncount = ncount + 1
+ }
+ }
+
+ # Resize the header keyword and value arrays.
+ if (ncount != CQ_NHEADER(res)) {
+ CQ_NHEADER(res) = 0
+ call realloc (CQ_HKNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_HKVALUES(res), 1, TY_CHAR)
+ Memc[CQ_HKNAMES(res)] = EOS
+ Memc[CQ_HKVALUES(res)] = EOS
+ } else {
+ call realloc (CQ_HKNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_HKVALUES(res), op2, TY_CHAR)
+ Memc[CQ_HKNAMES(res)+op1] = EOS
+ Memc[CQ_HKVALUES(res)+op2] = EOS
+ }
+
+ iferr (CQ_NFIELDS(res) = cq_dgeti (cq, CQ_CATNO(cq), "nfields"))
+ CQ_NFIELDS(res) = 0
+
+ # Allocate the field description arrays.
+ call calloc (CQ_FNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_FOFFSETS(res), CQ_NFIELDS(res), TY_INT)
+ call calloc (CQ_FSIZES(res), CQ_NFIELDS(res), TY_INT)
+ call calloc (CQ_FTYPES(res), CQ_NFIELDS(res), TY_INT)
+ call calloc (CQ_FUNITS(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_FFMTS(res), SZ_LINE, TY_CHAR)
+
+ # Get the field decoding parameters.
+ ncount = 0
+ if (CQ_NFIELDS(res) > 0) {
+
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+ call salloc (funits, CQ_SZ_FUNITS, TY_CHAR)
+ call salloc (ffmt, CQ_SZ_FFMTS, TY_CHAR)
+
+ # Initialize the name, units, and format string dictionaries.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ sz3 = SZ_LINE; op3 = 2
+ call strcpy ("|", Memc[CQ_FNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_FUNITS(res)], sz2)
+ call strcpy ("|", Memc[CQ_FFMTS(res)], sz3)
+
+ do i =1, CQ_NFIELDS(res) {
+
+ # Get the field description.
+ if (cq_dscan (cq) == EOF)
+ break
+ call gargwrd (Memc[fname], CQ_SZ_FNAME)
+ call gargi (foffset)
+ call gargi (fsize)
+ call gargc (ftype)
+ call gargwrd (Memc[funits], CQ_SZ_FUNITS)
+ call gargwrd (Memc[ffmt], CQ_SZ_FFMTS)
+ if (nscan() != 6)
+ break
+
+ # Add the field name to the field name dictionary.
+ if ((sz1 - op1 + 1) < (CQ_SZ_FNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_FNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[fname], Memc[CQ_FNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_FNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ # Set the field offset, size, and type.
+ Memi[CQ_FOFFSETS(res)+i-1] = foffset
+ Memi[CQ_FTYPES(res)+i-1] = cq_dtype (ftype)
+ Memi[CQ_FSIZES(res)+i-1] = fsize
+
+ # Add the field units to the field units dictionary.
+ if ((sz2 - op2 + 1) < (CQ_SZ_FUNITS + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_FUNITS(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[funits], Memc[CQ_FUNITS(res)+op2-1],
+ sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_FUNITS(res)+op2-1],
+ sz2 - op2 + 1)
+
+ # Add the field format to the field format dictionary.
+ if ((sz3 - op3 + 1) < (CQ_SZ_FFMTS + 1)) {
+ sz3 = sz3 + SZ_LINE
+ call realloc (CQ_FFMTS(res), sz3, TY_CHAR)
+ }
+ op3 = op3 + gstrcpy (Memc[ffmt], Memc[CQ_FFMTS(res)+op3-1],
+ sz3 - op3 + 1)
+ op3 = op3 + gstrcpy ("|", Memc[CQ_FFMTS(res)+op3-1],
+ sz3 - op3 + 1)
+
+ ncount = ncount + 1
+ }
+ }
+
+ # Adjust the field description size.
+ if (ncount != CQ_NFIELDS(res)) {
+ CQ_NFIELDS(res) = 0
+ call realloc (CQ_FNAMES(res), 1, TY_CHAR)
+ Memc[CQ_FNAMES(res)] = EOS
+ call mfree (CQ_FOFFSETS(res), TY_INT); CQ_FOFFSETS(res) = NULL
+ call mfree (CQ_FSIZES(res), TY_INT); CQ_FSIZES(res) = NULL
+ call mfree (CQ_FTYPES(res), TY_INT); CQ_FTYPES(res) = NULL
+ call realloc (CQ_FUNITS(res), 1, TY_CHAR)
+ Memc[CQ_FUNITS(res)] = EOS
+ call realloc (CQ_FFMTS(res), 1, TY_CHAR)
+ Memc[CQ_FFMTS(res)] = EOS
+ } else {
+ call realloc (CQ_FNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_FUNITS(res), op2, TY_CHAR)
+ call realloc (CQ_FFMTS(res), op3, TY_CHAR)
+ Memc[CQ_FNAMES(res)+op1] = EOS
+ Memc[CQ_FUNITS(res)+op2] = EOS
+ Memc[CQ_FFMTS(res)+op3] = EOS
+ }
+
+ # Allocate space for the simple text field indices array.
+ call calloc (CQ_FINDICES(res), CQ_MAX_NFIELDS + 1, TY_INT)
+
+ # Initilize the records descriptor.
+ CQ_RFD(res) = NULL
+
+ call sfree (sp)
+
+ return (res)
+end
+
+
+# Temporary definitions to get stuff working. Move into header file at some
+# point ?
+
+define DIC_FNAMES "|type|hskip|tskip|recsize|triml|trimr|nheader|nfields|"
+define DIC_TYPE 1
+define DIC_HSKIP 2
+define DIC_TSKIP 3
+define DIC_RECORD 4
+define DIC_TRIML 5
+define DIC_TRIMR 6
+define DIC_NHEADER 7
+define DIC_NFIELDS 8
+
+# CQ_FRINIT -- Initialize a results descriptor from a file description.
+
+pointer procedure cq_frinit (cq, catfmt)
+
+pointer cq #I Initialize the results structure.
+char catfmt[ARB] #I the catalog format desciption
+
+pointer res, sp, fname, funits, ffmt, fvalue
+int i, ncount, sz1, sz2, sz3, op1, op2, op3, fd, foffset, fsize
+int fscan(), nscan(), strdic(), strlen(), cq_dtype(), gstrcpy()
+char ftype
+int stropen()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (NULL)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (NULL)
+
+ # Allocate the structure.
+ call calloc (res, CQ_LEN_RES, TY_STRUCT)
+
+ # Format the catalog information, the address, query, and query
+ # parameters.
+ call strcpy (CQ_CATDB(cq), CQ_RCATDB(res), SZ_LINE)
+ call strcpy (CQ_CATNAME(cq), CQ_RCATNAME(res), SZ_LINE)
+ call strcpy ("", CQ_RADDRESS(res), SZ_LINE)
+ call strcpy ("", CQ_RQUERY(res), SZ_LINE)
+ CQ_RNQPARS(res) = 0
+ call malloc (CQ_RQPNAMES(res), 1, TY_CHAR)
+ call malloc (CQ_RQPVALUES(res), 1, TY_CHAR)
+ call malloc (CQ_RQPUNITS(res), 1, TY_CHAR)
+ Memc[CQ_RQPNAMES(res)] = EOS
+ Memc[CQ_RQPVALUES(res)] = EOS
+ Memc[CQ_RQPUNITS(res)] = EOS
+
+ # Set default file formats.
+ CQ_RTYPE(res) = CQ_STEXT
+ CQ_RHSKIP(res) = 0
+ CQ_RTSKIP(res) = 0
+ CQ_RECSIZE(res) = 0
+ CQ_RTRIML(res) = 0
+ CQ_RTRIMR(res) = 0
+ CQ_NFIELDS(res) = 0
+
+ call smark(sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+ call salloc (funits, CQ_SZ_FUNITS, TY_CHAR)
+ call salloc (ffmt, CQ_SZ_FFMTS, TY_CHAR)
+ call salloc (fvalue, SZ_LINE, TY_CHAR)
+
+ # Read in the defined file formats.
+ fd = stropen (catfmt, strlen (catfmt), READ_ONLY)
+ while (fscan (fd) != EOF) {
+
+ # Get the field name.
+ call gargwrd (Memc[fname], CQ_SZ_FNAME)
+ if (nscan () < 1 || Memc[fname] == EOS)
+ next
+ i = strdic (Memc[fname], Memc[fname], CQ_SZ_FNAME, DIC_FNAMES)
+
+ # Decode the field.
+ switch (i) {
+
+ case DIC_TYPE:
+ call gargwrd (Memc[fname], CQ_SZ_FNAME)
+ if (nscan () < 2 || Memc[fname] == EOS)
+ CQ_RTYPE(res) = CQ_STEXT
+ else
+ CQ_RTYPE(res) = strdic (Memc[fname], Memc[fname],
+ CQ_SZ_FNAME, CQ_RTYPESTR)
+
+ case DIC_HSKIP:
+ call gargi (CQ_RHSKIP(res))
+ if (nscan() < 2)
+ CQ_RHSKIP(res) = 0
+
+ case DIC_TSKIP:
+ call gargi (CQ_RTSKIP(res))
+ if (nscan() < 2)
+ CQ_RTSKIP(res) = 0
+
+ case DIC_RECORD:
+ call gargi (CQ_RECSIZE(res))
+ if (nscan() < 2)
+ CQ_RECSIZE(res) = 0
+
+ case DIC_TRIML:
+ call gargi (CQ_RTRIML(res))
+ if (nscan() < 2)
+ CQ_RTRIML(res) = 0
+
+ case DIC_TRIMR:
+ call gargi (CQ_RTRIMR(res))
+ if (nscan() < 2)
+ CQ_RTRIMR(res) = 0
+
+ case DIC_NHEADER:
+ call gargi (CQ_NHEADER(res))
+ if (nscan() < 2)
+ CQ_NHEADER(res) = 0
+
+ call calloc (CQ_HKNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_HKVALUES(res), SZ_LINE, TY_CHAR)
+
+ ncount = 0
+ if (CQ_NHEADER(res) > 0) {
+
+ # Initialize the header name and value dictionaries.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ call strcpy ("|", Memc[CQ_HKNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_HKVALUES(res)], sz2)
+
+ do i = 1, CQ_NHEADER(res) {
+
+ # Get the keyword name and value.
+ if (fscan (fd) == EOF)
+ break
+ call gargwrd (Memc[fname], CQ_SZ_QPNAME)
+ call gargwrd (Memc[fvalue], SZ_LINE)
+ if (nscan() != 2)
+ break
+
+ # Add the keyword name to the keyword dictionary.
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_HKNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[fname], Memc[CQ_HKNAMES(res)+
+ op1-1], sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_HKNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ # Add the keyword value to the keyword value dictionary.
+ if ((sz2 - op2 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_HKVALUES(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[fvalue],
+ Memc[CQ_HKVALUES(res)+ op2-1], sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_HKVALUES(res)+op2-1],
+ sz2 - op2 + 1)
+
+ ncount = ncount + 1
+ }
+ }
+
+ # Addjust the keyword dictionary sizes.
+ if (ncount != CQ_NHEADER(res)) {
+ CQ_NHEADER(res) = 0
+ call realloc (CQ_HKNAMES(res), 1, TY_CHAR)
+ call realloc (CQ_HKVALUES(res), 1, TY_CHAR)
+ Memc[CQ_HKNAMES(res)] = EOS
+ Memc[CQ_HKVALUES(res)] = EOS
+ } else {
+ call realloc (CQ_HKNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_HKVALUES(res), op2, TY_CHAR)
+ Memc[CQ_HKNAMES(res)+op1] = EOS
+ Memc[CQ_HKVALUES(res)+op2] = EOS
+ }
+
+ case DIC_NFIELDS:
+ call gargi (CQ_NFIELDS(res))
+ if (nscan() < 2)
+ CQ_NFIELDS(res) = 0
+
+ # Allocate space for the field descriptors.
+ call calloc (CQ_FNAMES(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_FOFFSETS(res), CQ_NFIELDS(res), TY_INT)
+ call calloc (CQ_FSIZES(res), CQ_NFIELDS(res), TY_INT)
+ call calloc (CQ_FTYPES(res), CQ_NFIELDS(res), TY_INT)
+ call calloc (CQ_FUNITS(res), SZ_LINE, TY_CHAR)
+ call calloc (CQ_FFMTS(res), SZ_LINE, TY_CHAR)
+
+ ncount = 0
+ if (CQ_NFIELDS(res) > 0) {
+
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ sz3 = SZ_LINE; op3 = 2
+ call strcpy ("|", Memc[CQ_FNAMES(res)], sz1)
+ call strcpy ("|", Memc[CQ_FUNITS(res)], sz2)
+ call strcpy ("|", Memc[CQ_FFMTS(res)], sz3)
+
+ do i = 1, CQ_NFIELDS(res) {
+
+ # Get the field description.
+ if (fscan (fd) == EOF)
+ break
+ call gargwrd (Memc[fname], CQ_SZ_FNAME)
+ call gargi (foffset)
+ call gargi (fsize)
+ call gargc (ftype)
+ call gargwrd (Memc[funits], CQ_SZ_FUNITS)
+ call gargwrd (Memc[ffmt], CQ_SZ_FFMTS)
+ if (nscan() != 6)
+ break
+
+ # Add the field name to the field name dictionary.
+ if ((sz1 - op1 + 1) < (CQ_SZ_FNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_FNAMES(res), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[fname], Memc[CQ_FNAMES(res)+
+ op1-1], sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_FNAMES(res)+op1-1],
+ sz1 - op1 + 1)
+
+ Memi[CQ_FOFFSETS(res)+i-1] = foffset
+ Memi[CQ_FTYPES(res)+i-1] = cq_dtype (ftype)
+ Memi[CQ_FSIZES(res)+i-1] = fsize
+
+ # Add the field units to the field units dictionary.
+ if ((sz2 - op2 + 1) < (CQ_SZ_FUNITS + 1)) {
+ sz2 = sz2 + SZ_LINE
+ call realloc (CQ_FUNITS(res), sz2, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[funits],
+ Memc[CQ_FUNITS(res)+ op2-1], sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_FUNITS(res)+op2-1],
+ sz2 - op2 + 1)
+
+ # Add the field format to the field formats dictionary.
+ if ((sz3 - op3 + 1) < (CQ_SZ_FFMTS + 1)) {
+ sz3 = sz3 + SZ_LINE
+ call realloc (CQ_FFMTS(res), sz3, TY_CHAR)
+ }
+ op3 = op3 + gstrcpy (Memc[ffmt],
+ Memc[CQ_FFMTS(res)+ op3 -1], sz3 - op3 + 1)
+ op3 = op3 + gstrcpy ("|", Memc[CQ_FFMTS(res)+op3-1],
+ sz3 - op3 + 1)
+
+ ncount = ncount + 1
+ }
+ }
+ if (ncount != CQ_NFIELDS(res)) {
+ CQ_NFIELDS(res) = 0
+ call realloc (CQ_FNAMES(res), 1, TY_CHAR)
+ Memc[CQ_FNAMES(res]) = EOS
+ call mfree (CQ_FOFFSETS(res), TY_INT)
+ CQ_FOFFSETS(res) = NULL
+ call mfree (CQ_FSIZES(res), TY_INT)
+ CQ_FSIZES(res) = NULL
+ call mfree (CQ_FTYPES(res), TY_INT)
+ CQ_FTYPES(res) = NULL
+ call realloc (CQ_FUNITS(res), 1, TY_CHAR)
+ Memc[CQ_FUNITS(res)] = EOS
+ call realloc (CQ_FFMTS(res), 1, TY_CHAR)
+ Memc[CQ_FFMTS(res)] = EOS
+ } else {
+ call realloc (CQ_FNAMES(res), op1, TY_CHAR)
+ call realloc (CQ_FUNITS(res), op2, TY_CHAR)
+ call realloc (CQ_FFMTS(res), op3, TY_CHAR)
+ Memc[CQ_FNAMES(res]+op1) = EOS
+ Memc[CQ_FUNITS(res)+op2] = EOS
+ Memc[CQ_FFMTS(res)+op3] = EOS
+ }
+ default:
+ ;
+ }
+ }
+ call close (fd)
+ call sfree (sp)
+
+ # Allocate space for the field indices array.
+ call calloc (CQ_FINDICES(res), CQ_MAX_NFIELDS + 1, TY_INT)
+
+ # Initilize the records descriptor.
+ CQ_RFD(res) = NULL
+
+ return (res)
+end
+
+
+# CQ_RFREE -- Free the results structure.
+
+procedure cq_rfree (res)
+
+pointer res #U the results descriptor.
+
+begin
+ # Free the query parameter names, values, and units.
+ if (CQ_RQPNAMES(res) != NULL)
+ call mfree (CQ_RQPNAMES(res), TY_CHAR)
+ if (CQ_RQPVALUES(res) != NULL)
+ call mfree (CQ_RQPVALUES(res), TY_CHAR)
+ if (CQ_RQPUNITS(res) != NULL)
+ call mfree (CQ_RQPUNITS(res), TY_CHAR)
+
+ # Free the header names and values.
+ if (CQ_HKNAMES(res) != NULL)
+ call mfree (CQ_HKNAMES(res), TY_CHAR)
+ if (CQ_HKVALUES(res) != NULL)
+ call mfree (CQ_HKVALUES(res), TY_CHAR)
+
+ # Free the field offsets, sizes, and types.
+ if (CQ_FNAMES(res) != NULL)
+ call mfree (CQ_FNAMES(res), TY_CHAR)
+ if (CQ_FOFFSETS(res) != NULL)
+ call mfree (CQ_FOFFSETS(res), TY_INT)
+ if (CQ_FSIZES(res) != NULL)
+ call mfree (CQ_FSIZES(res), TY_INT)
+ if (CQ_FTYPES(res) != NULL)
+ call mfree (CQ_FTYPES(res), TY_INT)
+ if (CQ_FUNITS(res) != NULL)
+ call mfree (CQ_FUNITS(res), TY_CHAR)
+ if (CQ_FFMTS(res) != NULL)
+ call mfree (CQ_FFMTS(res), TY_CHAR)
+
+ # Free the record description.
+ if (CQ_FINDICES(res) != NULL)
+ call mfree (CQ_FINDICES(res), TY_INT)
+
+ # Free the record buffer.
+ if (CQ_RINDEX(res) != NULL)
+ call mfree (CQ_RINDEX(res), TY_LONG)
+ if (CQ_RFD(res) != NULL)
+ call close (CQ_RFD(res))
+
+ if (res != NULL)
+ call mfree (res, TY_STRUCT)
+end
diff --git a/pkg/xtools/catquery/cqrinfo.x b/pkg/xtools/catquery/cqrinfo.x
new file mode 100644
index 00000000..f61dc949
--- /dev/null
+++ b/pkg/xtools/catquery/cqrinfo.x
@@ -0,0 +1,390 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_HINFO -- Get the header keyword value by keyword name.
+
+int procedure cq_hinfo (res, hkname, hkvalue, sz_hkvalue)
+
+pointer res #I the results descriptor
+char hkname[ARB] #I the header keyword name
+char hkvalue[ARB] #O the header keyword value
+int sz_hkvalue #I the maximum size of the keyword value
+
+pointer sp, kname
+int kwno
+int strdic(), cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NHEADER(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (kname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ kwno = strdic (hkname, Memc[kname], CQ_SZ_FNAME, Memc[CQ_HKNAMES(res)])
+ if (kwno <= 0) {
+ call sfree (sp)
+ return (0)
+ }
+
+ # Retrieve the keyword value.
+ if (cq_wrdstr (kwno, hkvalue, sz_hkvalue, Memc[CQ_HKVALUES(res)]) <= 0)
+ hkvalue[1] = EOS
+
+ call sfree (sp)
+
+ return (kwno)
+end
+
+
+# CQ_HINFON -- Get the header keyword name and value using the keyword number.
+
+int procedure cq_hinfon (res, kwno, hkname, sz_hkname, hkvalue, sz_hkvalue)
+
+pointer res #I the results descriptor
+int kwno #I the keyword number
+char hkname[ARB] #O the header keyword name
+int sz_hkname #I the maximum size of the keyword name
+char hkvalue[ARB] #O the header keyword value
+int sz_hkvalue #I the maximum size of the keyword value
+
+int cq_wrdstr()
+
+begin
+ # Return if there are no keywords.
+ if (CQ_NHEADER(res) <= 0)
+ return (0)
+
+ # Return if the keyword is out of bounds.
+ if (kwno < 1 || kwno > CQ_NHEADER(res))
+ return (0)
+
+ # Retrieve the keyword value.
+ if (cq_wrdstr (kwno, hkname, sz_hkname, Memc[CQ_HKNAMES(res)]) <= 0)
+ hkname[1] = EOS
+
+ # Retrieve the keyword value.
+ if (cq_wrdstr (kwno, hkvalue, sz_hkvalue, Memc[CQ_HKVALUES(res)]) <= 0)
+ hkvalue[1] = EOS
+
+ return (kwno)
+end
+
+
+# CQ_FINFO -- Get the field description by field name.
+
+int procedure cq_finfo (res, field, foffset, fsize, ftype, units, sz_units,
+ fmts, sz_fmts)
+
+pointer res #I the results descriptor
+char field[ARB] #I the field name
+int foffset #O the output field offset
+int fsize #O the output field size
+int ftype #O the output field datatype
+char units[ARB] #O the outpit field units string
+int sz_units #I the maximum size of the units string
+char fmts[ARB] #O the outpit field formats string
+int sz_fmts #I the maximum size of the formats string
+
+pointer sp, fname
+int fieldno
+int strdic(), cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (field, Memc[fname], CQ_SZ_FNAME, Memc[CQ_FNAMES(res)])
+ if (fieldno <= 0) {
+ call sfree (sp)
+ return (0)
+ }
+
+ # Get the field offset, size, and type.
+ foffset = Memi[CQ_FOFFSETS(res)+fieldno-1]
+ fsize = Memi[CQ_FSIZES(res)+fieldno-1]
+ ftype = Memi[CQ_FTYPES(res)+fieldno-1]
+
+ # Get the field units and format.
+ if (cq_wrdstr (fieldno, units, sz_units, Memc[CQ_FUNITS(res)]) <= 0)
+ units[1] = EOS
+ if (cq_wrdstr (fieldno, fmts, sz_fmts, Memc[CQ_FFMTS(res)]) <= 0)
+ fmts[1] = EOS
+
+ call sfree (sp)
+
+ return (fieldno)
+end
+
+
+# CQ_FNUMBER -- Get the field number given the field name.
+
+int procedure cq_fnumber (res, field)
+
+pointer res #I the results descriptor
+char field[ARB] #I the field name
+
+pointer sp, fname
+int fieldno
+int strdic()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (field, Memc[fname], CQ_SZ_FNAME, Memc[CQ_FNAMES(res)])
+
+ call sfree (sp)
+ return (fieldno)
+end
+
+
+# CQ_FOFFSET -- Get the field offset given the field name.
+
+int procedure cq_foffset (res, field)
+
+pointer res #I the results descriptor
+char field[ARB] #I the field name
+
+pointer sp, fname
+int fieldno
+int strdic()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (field, Memc[fname], CQ_SZ_FNAME, Memc[CQ_FNAMES(res)])
+
+ call sfree (sp)
+
+ if (fieldno <= 0)
+ return (0)
+ else
+ return (Memi[CQ_FOFFSETS(res)+fieldno-1])
+end
+
+
+# CQ_FSIZE -- Get the field offset given the field name.
+
+int procedure cq_fsize (res, field)
+
+pointer res #I the results descriptor
+char field[ARB] #I the field name
+
+pointer sp, fname
+int fieldno
+int strdic()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (field, Memc[fname], CQ_SZ_FNAME, Memc[CQ_FNAMES(res)])
+
+ call sfree (sp)
+
+ if (fieldno <= 0)
+ return (0)
+ else
+ return (Memi[CQ_FSIZES(res)+fieldno-1])
+end
+
+
+# CQ_FTYPE -- Get the field type given the field name.
+
+int procedure cq_ftype (res, field)
+
+pointer res #I the results descriptor
+char field[ARB] #I the field name
+
+pointer sp, fname
+int fieldno
+int strdic()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0)
+ return (0)
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (field, Memc[fname], CQ_SZ_FNAME, Memc[CQ_FNAMES(res)])
+
+ call sfree (sp)
+
+ if (fieldno <= 0)
+ return (0)
+ else
+ return (Memi[CQ_FTYPES(res)+fieldno-1])
+end
+
+
+# CQ_FUNITS -- Get the field units given the field name.
+
+procedure cq_funits (res, field, units, sz_units)
+
+pointer res #I the results descriptor
+char field[ARB] #I the field name
+char units[ARB] #O the output units string
+int sz_units #I the maximum size of the units string
+
+pointer sp, fname
+int fieldno
+int strdic(), cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0) {
+ units[1] = EOS
+ return
+ }
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (field, Memc[fname], CQ_SZ_FNAME, Memc[CQ_FNAMES(res)])
+
+ # Get the units string.
+ if (fieldno > 0) {
+ if (cq_wrdstr (fieldno, units, sz_units, Memc[CQ_FUNITS(res)]) <= 0)
+ units[1] = EOS
+ } else
+ units[1] = EOS
+
+ call sfree (sp)
+end
+
+
+# CQ_FFMTS -- Get the field format given the field name.
+
+procedure cq_ffmts (res, field, format, sz_format)
+
+pointer res #I the results descriptor
+char field[ARB] #I the field name
+char format[ARB] #O the output format string
+int sz_format #I the maximum size of the format string
+
+pointer sp, fname
+int fieldno
+int strdic(), cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0) {
+ format[1] = EOS
+ return
+ }
+
+ call smark (sp)
+ call salloc (fname, CQ_SZ_FNAME, TY_CHAR)
+
+ # Find the requested field.
+ fieldno = strdic (field, Memc[fname], CQ_SZ_FNAME, Memc[CQ_FNAMES(res)])
+
+ # Get the units string.
+ if (fieldno > 0) {
+ if (cq_wrdstr (fieldno, format, sz_format,
+ Memc[CQ_FFMTS(res)]) <= 0)
+ format[1] = EOS
+ } else
+ format[1] = EOS
+
+ call sfree (sp)
+end
+
+
+# CQ_FINFON -- Get the field description by field number.
+
+int procedure cq_finfon (res, fieldno, fname, sz_fname, foffset, fsize, ftype,
+ units, sz_units, fmts, sz_fmts)
+
+pointer res #I the results descriptor
+int fieldno #I the input field number
+char fname[ARB] #O the field name
+int sz_fname #I the maximum field name size
+int foffset #O the output field offset
+int fsize #O the output field size
+int ftype #O the output field datatype
+char units[ARB] #O the outpit field units string
+int sz_units #I the maximum size of the units string
+char fmts[ARB] #O the outpit field formats string
+int sz_fmts #I the maximum size of the formats string
+
+int cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0)
+ return (0)
+ if (fieldno <= 0 || fieldno > CQ_NFIELDS(res))
+ return (0)
+
+ # Get the field name.
+ if (cq_wrdstr (fieldno, fname, sz_fname, Memc[CQ_FNAMES(res)]) <= 0)
+ return (0)
+
+ # Set the field offset, size, and type.
+ foffset = Memi[CQ_FOFFSETS(res)+fieldno-1]
+ fsize = Memi[CQ_FSIZES(res)+fieldno-1]
+ ftype = Memi[CQ_FTYPES(res)+fieldno-1]
+
+ if (cq_wrdstr (fieldno, units, sz_units, Memc[CQ_FUNITS(res)]) <= 0)
+ units[1] = EOS
+ if (cq_wrdstr (fieldno, fmts, sz_fmts, Memc[CQ_FFMTS(res)]) <= 0)
+ fmts[1] = EOS
+
+ return (fieldno)
+end
+
+
+# CQ_FNAME -- Get the field name given the field number.
+
+int procedure cq_fname (res, fieldno, fname, sz_fname)
+
+pointer res #I the results descriptor
+int fieldno #I the input field number
+char fname[ARB] #O the field name
+int sz_fname #I the maximum field name size
+
+int cq_wrdstr()
+
+begin
+ # Return if there are no fields.
+ if (CQ_NFIELDS(res) <= 0)
+ return (0)
+ if (fieldno <= 0 || fieldno > CQ_NFIELDS(res))
+ return (0)
+
+ # Get the field name.
+ if (cq_wrdstr (fieldno, fname, sz_fname, Memc[CQ_FNAMES(res)]) <= 0)
+ return (0)
+
+ return (fieldno)
+end
diff --git a/pkg/xtools/catquery/cqrstat.x b/pkg/xtools/catquery/cqrstat.x
new file mode 100644
index 00000000..60319e77
--- /dev/null
+++ b/pkg/xtools/catquery/cqrstat.x
@@ -0,0 +1,171 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_RSTATI -- Get an integer results parameter.
+
+int procedure cq_rstati (res, param)
+
+pointer res #I pointer to the results descriptor
+int param #I the integer parameter to be retrieved
+
+begin
+ switch (param) {
+ case CQRNQPARS:
+ return (CQ_RNQPARS(res))
+ case CQRTYPE:
+ return (CQ_RTYPE(res))
+ case CQRNRECS:
+ return (CQ_RNRECS(res))
+ case CQRECSIZE:
+ return (CQ_RECSIZE(res))
+ case CQRHSKIP:
+ return (CQ_RHSKIP(res))
+ case CQRTSKIP:
+ return (CQ_RTSKIP(res))
+ case CQRTRIML:
+ return (CQ_RTRIML(res))
+ case CQRTRIMR:
+ return (CQ_RTRIMR(res))
+ case CQNHEADER:
+ return (CQ_NHEADER(res))
+ case CQNFIELDS:
+ return (CQ_NFIELDS(res))
+ case CQRECPTR:
+ return (CQ_RECPTR(res))
+ default:
+ call error (0, "Error fetching integer results parameter")
+ }
+end
+
+
+# CQ_RSTATR -- Get a real results parameter.
+
+real procedure cq_rstatr (res, param)
+
+pointer res #I pointer to the results descriptor
+int param #I the real parameter to be retrieved
+
+begin
+ switch (param) {
+ default:
+ call error (0, "Error fetching real results parameter")
+ }
+end
+
+
+# CQ_RSTATD -- Get a double precision results parameter.
+
+double procedure cq_rstatd (res, param)
+
+pointer res #I pointer to the results descriptor
+int param #I the double parameter to be retrieved
+
+begin
+ switch (param) {
+ default:
+ call error (0, "Error fetching double results parameter")
+ }
+end
+
+
+# CQ_RSTATS -- Get a string results parameter.
+
+procedure cq_rstats (res, param, str, maxch)
+
+pointer res #I pointer to the results descriptor
+int param #I the string parameter to be retrieved
+char str[ARB] #O the output string parameter
+int maxch #I the maximum size of the string parameter
+
+begin
+ switch (param) {
+ case CQRCATDB:
+ call strcpy (CQ_RCATDB(res), str, maxch)
+ case CQRCATNAME:
+ call strcpy (CQ_RCATNAME(res), str, maxch)
+ case CQRADDRESS:
+ call strcpy (CQ_RADDRESS(res), str, maxch)
+ case CQRQUERY:
+ call strcpy (CQ_RQUERY(res), str, maxch)
+ case CQRQPNAMES:
+ call strcpy (Memc[CQ_RQPNAMES(res)], str, maxch)
+ case CQRQPVALUES:
+ call strcpy (Memc[CQ_RQPVALUES(res)], str, maxch)
+ case CQRQPUNITS:
+ call strcpy (Memc[CQ_RQPUNITS(res)], str, maxch)
+ default:
+ call error (0, "Error fetching string results parameter")
+ }
+end
+
+
+# CQ_RSTATT -- Get a text list results parameter. A text list is a
+# string with items separated from each other by newlines.
+
+int procedure cq_rstatt (res, param, str, maxch)
+
+pointer res #I pointer to the results descriptor
+int param #I the list parameter to be retrieved
+char str[ARB] #O the output string parameter
+int maxch #I the maximum size of the string parameter
+
+pointer sp, tstr
+int i, fd
+int stropen(), cq_wrdstr()
+
+begin
+ switch (param) {
+
+ case CQRQPNAMES:
+ call smark (sp)
+ call salloc (tstr, CQ_SZ_QPNAME, TY_CHAR)
+ fd = stropen (str, maxch, NEW_FILE)
+ str[1] = EOS
+ do i = 1, CQ_RNQPARS(res) {
+ if (cq_wrdstr (i, Memc[tstr], CQ_SZ_QPNAME,
+ Memc[CQ_RQPNAMES(res)]) > 0) {
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[tstr])
+ }
+ }
+ call close (fd)
+ call sfree (sp)
+ return (CQ_RNQPARS(res))
+
+ case CQRQPVALUES:
+ call smark (sp)
+ call salloc (tstr, CQ_SZ_QPVALUE, TY_CHAR)
+ fd = stropen (str, maxch, NEW_FILE)
+ str[1] = EOS
+ do i = 1, CQ_RNQPARS(res) {
+ if (cq_wrdstr (i, Memc[tstr], CQ_SZ_QPVALUE,
+ Memc[CQ_RQPVALUES(res)]) > 0) {
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[tstr])
+ }
+ }
+ call close (fd)
+ call sfree (sp)
+ return (CQ_RNQPARS(res))
+
+ case CQRQPUNITS:
+ call smark (sp)
+ call salloc (tstr, CQ_SZ_QPUNITS, TY_CHAR)
+ fd = stropen (str, maxch, NEW_FILE)
+ str[1] = EOS
+ do i = 1, CQ_RNQPARS(res) {
+ if (cq_wrdstr (i, Memc[tstr], CQ_SZ_QPUNITS,
+ Memc[CQ_RQPUNITS(res)]) > 0) {
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[tstr])
+ }
+ }
+ call close (fd)
+ call sfree (sp)
+ return (CQ_RNQPARS(res))
+
+ default:
+ call error (0, "Error fetching list results parameter")
+ }
+end
diff --git a/pkg/xtools/catquery/cqsetcat.x b/pkg/xtools/catquery/cqsetcat.x
new file mode 100644
index 00000000..f64ae4c3
--- /dev/null
+++ b/pkg/xtools/catquery/cqsetcat.x
@@ -0,0 +1,293 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_SETCAT -- Set the current catalog by name.
+
+int procedure cq_setcat (cq, name)
+
+pointer cq #I the catalog descriptor
+char name[ARB] #I the catalog name
+
+int i, catno
+int cq_ccrquery()
+bool streq()
+
+begin
+ catno = 0
+ do i = 1, CQ_NRECS(cq) {
+ if (streq (name, CQ_NAME(cq, i)))
+ catno = i
+ }
+ if (catno == 0)
+ return (0)
+
+ # Free the previous current catalog descriptor if any.
+ call cq_ccfree (cq)
+
+ # Allocate the new descriptor.
+ call cq_ccinit (cq, catno)
+
+ # Get the new catalog parameters.
+ if (cq_ccrquery (cq) == ERR) {
+ call cq_ccfree (cq)
+ return (0)
+ }
+
+ return (catno)
+end
+
+
+# CQ_SETCATN -- Set the current catalog by number.
+
+int procedure cq_setcatn (cq, catno)
+
+pointer cq #I the catalog descriptor
+int catno #I the catalog number
+
+int cq_ccrquery()
+
+begin
+ if (catno < 1 || catno > CQ_NRECS(cq))
+ return (0)
+
+ # Free the previous current catalog descriptor if any.
+ call cq_ccfree (cq)
+
+ # Allocate the new descriptor.
+ call cq_ccinit (cq, catno)
+
+ # Get the new catalog parameters.
+ if (cq_ccrquery (cq) == ERR) {
+ call cq_ccfree (cq)
+ return (0)
+ }
+
+ return (catno)
+end
+
+
+# CQ_CCINIT -- Initialize the current catalog descriptor.
+
+procedure cq_ccinit (cq, catno)
+
+pointer cq #I the catalog database descriptor
+int catno #I the current catalog number
+
+pointer cc
+
+begin
+ if (catno < 1 || catno > CQ_NRECS(cq))
+ return
+ CQ_CATNO(cq) = catno
+ call strcpy (CQ_NAME(cq, catno), CQ_CATNAME(cq), SZ_FNAME)
+
+ call calloc (CQ_CAT(cq), CQ_LEN_CC, TY_STRUCT)
+ cc = CQ_CAT(cq)
+
+ CQ_NQPARS(cc) = 0
+ CQ_HFMT(cc) = CQ_HNONE
+
+ call calloc (CQ_PQPNAMES(cc), SZ_LINE, TY_CHAR)
+ call calloc (CQ_PQPDVALUES(cc), SZ_LINE, TY_CHAR)
+ call calloc (CQ_PQPVALUES(cc), SZ_LINE, TY_CHAR)
+ call calloc (CQ_PQPUNITS(cc), SZ_LINE, TY_CHAR)
+ call calloc (CQ_PQPFMTS(cc), SZ_LINE, TY_CHAR)
+
+ Memc[CQ_PQPNAMES(cc)] = EOS
+ Memc[CQ_PQPDVALUES(cc)] = EOS
+ Memc[CQ_PQPVALUES(cc)] = EOS
+ Memc[CQ_PQPUNITS(cc)] = EOS
+ Memc[CQ_PQPFMTS(cc)] = EOS
+
+ CQ_ADDRESS(cc) = EOS
+ CQ_QUERY(cc) = EOS
+
+end
+
+
+# CQ_CCRQUERY -- Read in the query related parameters from the catalog
+# database. May need to encode the field names at some point.
+
+int procedure cq_ccrquery (cq)
+
+pointer cq #I the catalog database descriptor
+
+pointer cc, sp, str
+int i, catno, nqpars, npars, sz1, sz2, sz3, sz4, sz5
+int op1, op2, op3, op4, op5
+int cq_dgeti(), cq_dscan(), nscan(), gstrcpy(), strdic()
+errchk cq_dgwrd(), cq_dgeti(), cq_dscan()
+
+begin
+ # If the current catalog is not defined then return.
+ if (CQ_CAT(cq) == NULL)
+ return (ERR)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (ERR)
+ cc = CQ_CAT(cq)
+ catno = CQ_CATNO(cq)
+
+ call smark (sp)
+ call salloc (str, 4 * (SZ_LINE + 1), TY_CHAR)
+
+ iferr {
+
+ # Get the catalog address and query string.
+ call cq_dgwrd (cq, catno, "address", CQ_ADDRESS(cc), SZ_LINE)
+ call cq_dgstr (cq, catno, "query", CQ_QUERY(cc), SZ_LINE)
+
+ # Get the protocol.
+ call cq_dgwrd (cq, catno, "protocol", Memc[str], SZ_LINE)
+ CQ_HFMT(cc) = strdic (Memc[str], Memc[str], SZ_LINE,
+ CQ_HFMTSTR)
+ if (CQ_HFMT(cc) <= 0)
+ CQ_HFMT(cc) = CQ_HNONE
+
+ # Determine the number of query parameters and position the
+ # file to the correct place.
+ nqpars = cq_dgeti (cq, catno, "nquery")
+
+ } then {
+
+ # Reinitialize and return.
+ CQ_ADDRESS(cc) = EOS
+ CQ_QUERY(cc) = EOS
+ call sfree (sp)
+ return (ERR)
+ }
+
+
+ # Open the query parameter string dictionaries.
+ sz1 = SZ_LINE; op1 = 2
+ sz2 = SZ_LINE; op2 = 2
+ sz3 = SZ_LINE; op3 = 2
+ sz4 = SZ_LINE; op4 = 2
+ sz5 = SZ_LINE; op5 = 2
+ call strcpy ("|", Memc[CQ_PQPNAMES(cc)], sz1)
+ call strcpy ("|", Memc[CQ_PQPDVALUES(cc)], sz2)
+ call strcpy ("|", Memc[CQ_PQPVALUES(cc)], sz3)
+ call strcpy ("|", Memc[CQ_PQPUNITS(cc)], sz4)
+ call strcpy ("|", Memc[CQ_PQPFMTS(cc)], sz5)
+
+ # Scan the query parameter list.
+ npars = 0
+ for (i = 1; i <= nqpars; i = i + 1) {
+ if (cq_dscan (cq) == EOF)
+ break
+
+ # Get the query parameter fields.
+ call gargwrd (Memc[str], SZ_LINE)
+ call gargwrd (Memc[str+SZ_LINE+1], SZ_LINE)
+ call gargwrd (Memc[str+2*(SZ_LINE+1)], SZ_LINE)
+ call gargwrd (Memc[str+3*(SZ_LINE+1)], SZ_LINE)
+ if (nscan() != 4)
+ break
+
+ # Get the query parameter name.
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPNAME + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (CQ_PQPNAMES(cc), sz1, TY_CHAR)
+ }
+ op1 = op1 + gstrcpy (Memc[str], Memc[CQ_PQPNAMES(cc)+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[CQ_PQPNAMES(cc)+op1-1],
+ sz1 - op1 + 1)
+
+ # Get the default query parameter value and initialize the
+ # user query parameter string.
+ if ((sz2 - op2 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz2 = sz2 + SZ_LINE
+ sz3 = sz3 + SZ_LINE
+ call realloc (CQ_PQPDVALUES(cc), sz2, TY_CHAR)
+ call realloc (CQ_PQPVALUES(cc), sz3, TY_CHAR)
+ }
+ op2 = op2 + gstrcpy (Memc[str+SZ_LINE+1],
+ Memc[CQ_PQPDVALUES(cc)+op2-1], sz2 - op2 + 1)
+ op2 = op2 + gstrcpy ("|", Memc[CQ_PQPDVALUES(cc)+op2-1],
+ sz2 - op2 + 1)
+ op3 = op3 + gstrcpy (Memc[str+SZ_LINE+1],
+ Memc[CQ_PQPVALUES(cc)+op3-1], sz3 - op3 + 1)
+ op3 = op3 + gstrcpy ("|", Memc[CQ_PQPVALUES(cc)+op3-1],
+ sz3 - op3 + 1)
+
+ # Get the query parameter units.
+ if ((sz4 - op4 + 1) < (CQ_SZ_QPUNITS + 1)) {
+ sz4 = sz4 + SZ_LINE
+ call realloc (CQ_PQPUNITS(cc), sz4, TY_CHAR)
+ }
+ op4 = op4 + gstrcpy (Memc[str+2*(SZ_LINE+1)],
+ Memc[CQ_PQPUNITS(cc)+op4-1], sz4 - op4 + 1)
+ op4 = op4 + gstrcpy ("|", Memc[CQ_PQPUNITS(cc)+op4-1],
+ sz4 - op4 + 1)
+
+ # Get the query parameter formats.
+ if ((sz5 - op5 + 1) < (CQ_SZ_QPFMTS + 1)) {
+ sz5 = sz5 + SZ_LINE
+ call realloc (CQ_PQPFMTS(cc), sz5, TY_CHAR)
+ }
+ op5 = op5 + gstrcpy (Memc[str+3*(SZ_LINE+1)],
+ Memc[CQ_PQPFMTS(cc)+op5-1], sz5 - op5 + 1)
+ op5 = op5 + gstrcpy ("|", Memc[CQ_PQPFMTS(cc)+op5-1],
+ sz5 - op5 + 1)
+
+ npars = npars + 1
+ }
+
+ # Return the appropriate status.
+ call sfree (sp)
+ if (npars != nqpars) {
+ CQ_NQPARS(cc) = 0
+ call realloc (CQ_PQPNAMES(cc), SZ_LINE, TY_CHAR)
+ call realloc (CQ_PQPDVALUES(cc), SZ_LINE, TY_CHAR)
+ call realloc (CQ_PQPVALUES(cc), SZ_LINE, TY_CHAR)
+ call realloc (CQ_PQPUNITS(cc), SZ_LINE, TY_CHAR)
+ call realloc (CQ_PQPFMTS(cc), SZ_LINE, TY_CHAR)
+ Memc[CQ_PQPNAMES(cc)] = EOS
+ Memc[CQ_PQPDVALUES(cc)] = EOS
+ Memc[CQ_PQPVALUES(cc)] = EOS
+ Memc[CQ_PQPUNITS(cc)] = EOS
+ Memc[CQ_PQPFMTS(cc)] = EOS
+ CQ_ADDRESS(cc) = EOS
+ CQ_QUERY(cc) = EOS
+ return (ERR)
+ } else {
+ CQ_NQPARS(cc) = npars
+ call realloc (CQ_PQPNAMES(cc), op1, TY_CHAR)
+ call realloc (CQ_PQPDVALUES(cc), op2, TY_CHAR)
+ call realloc (CQ_PQPVALUES(cc), op3, TY_CHAR)
+ call realloc (CQ_PQPUNITS(cc), op4, TY_CHAR)
+ call realloc (CQ_PQPFMTS(cc), op5, TY_CHAR)
+ Memc[CQ_PQPNAMES(cc)+op1] = EOS
+ Memc[CQ_PQPDVALUES(cc)+op2] = EOS
+ Memc[CQ_PQPVALUES(cc)+op3] = EOS
+ Memc[CQ_PQPUNITS(cc)+op4] = EOS
+ Memc[CQ_PQPFMTS(cc)+op5] = EOS
+ return (OK)
+ }
+end
+
+
+# CQ_CCFREE - Free the current catalog descriptor
+
+procedure cq_ccfree (cq)
+
+pointer cq #I the catalog database descriptor
+
+pointer cc
+
+begin
+ CQ_CATNAME(cq) = EOS
+ CQ_CATNO(cq) = 0
+
+ if (CQ_CAT(cq) != NULL) {
+ cc = CQ_CAT(cq)
+ call mfree (CQ_PQPNAMES(cc), TY_CHAR)
+ call mfree (CQ_PQPDVALUES(cc), TY_CHAR)
+ call mfree (CQ_PQPVALUES(cc), TY_CHAR)
+ call mfree (CQ_PQPUNITS(cc), TY_CHAR)
+ call mfree (CQ_PQPFMTS(cc), TY_CHAR)
+ call mfree (CQ_CAT(cq), TY_STRUCT)
+ }
+ CQ_CAT(cq) = NULL
+end
diff --git a/pkg/xtools/catquery/cqsqpars.x b/pkg/xtools/catquery/cqsqpars.x
new file mode 100644
index 00000000..e2ab9c3c
--- /dev/null
+++ b/pkg/xtools/catquery/cqsqpars.x
@@ -0,0 +1,135 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_SQPAR -- Set the value of a query parameter by name.
+
+int procedure cq_sqpar (cq, name, valuestr)
+
+pointer cq #I the catalog descriptor
+char name[ARB] #I the input query parameter name
+char valuestr[ARB] #I the parameter value string
+
+pointer cc, sp, pname, tmpdic, pvalue
+int i, parno, sz1, op1
+int strdic(), strlen(), cq_wrdstr(), gstrcpy()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (0)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (0)
+ cc = CQ_CAT(cq)
+
+
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (pname, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (pvalue, CQ_SZ_QPVALUE, TY_CHAR)
+
+ # Locate the parameter.
+ parno = strdic (name, Memc[pname], CQ_SZ_QPNAME, Memc[CQ_PQPNAMES(cc)])
+ if (parno <= 0) {
+ call sfree (sp)
+ return (0)
+ }
+
+ # Initalize the temporary string.
+ sz1 = strlen (Memc[CQ_PQPVALUES(cc)]) + CQ_SZ_QPVALUE
+ call malloc (tmpdic, sz1, TY_CHAR)
+ call strcpy ("|", Memc[tmpdic], sz1)
+ op1 = 2
+
+
+ # Reformat the values string.
+ do i = 1, CQ_NQPARS(cc) {
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (tmpdic, sz1, TY_CHAR)
+ }
+ if (i == parno) {
+ op1 = op1 + gstrcpy (valuestr, Memc[tmpdic+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[tmpdic+op1-1], sz1 - op1 + 1)
+ } else if (cq_wrdstr (i, Memc[pvalue], CQ_SZ_QPNAME,
+ Memc[CQ_PQPVALUES(cc)]) > 0) {
+ op1 = op1 + gstrcpy (Memc[pvalue], Memc[tmpdic+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[tmpdic+op1-1], sz1 - op1 + 1)
+ }
+ }
+
+ # Update the values string. Leave as temp length for now.
+ call realloc (CQ_PQPVALUES(cc), op1 - 1, TY_CHAR)
+ call strcpy (Memc[tmpdic], Memc[CQ_PQPVALUES(cc)], op1 - 1)
+
+ call mfree (tmpdic, TY_CHAR)
+ call sfree (sp)
+
+ return (parno)
+end
+
+
+# CQ_SQPARN -- Set the value of a query parameter by number.
+
+int procedure cq_sqparn (cq, parno, valuestr)
+
+pointer cq #I the catalog descriptor
+int parno #I the query parameter number
+char valuestr[ARB] #I the parameter value string
+
+pointer cc, sp, pname, tmpdic, pvalue
+int i, sz1, op1
+int strlen(), cq_wrdstr(), gstrcpy()
+
+begin
+ # Check that the current catalog is defined.
+ if (CQ_CAT(cq) == NULL)
+ return (0)
+ if (CQ_CATNO(cq) < 1 || CQ_CATNO(cq) > CQ_NRECS(cq))
+ return (0)
+ cc = CQ_CAT(cq)
+
+ if (parno < 1 || parno > CQ_NQPARS(cc))
+ return (0)
+
+ # Get some working space.
+ call smark (sp)
+ call salloc (pname, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (pvalue, CQ_SZ_QPVALUE, TY_CHAR)
+
+ # Initialize the new dictionary.
+ sz1 = strlen (Memc[CQ_PQPVALUES(cc)]) + CQ_SZ_QPVALUE
+ call calloc (tmpdic, sz1, TY_CHAR)
+ call strcpy ("|", Memc[tmpdic], sz1)
+ op1 = 2
+
+ # Reformat the values string.
+ do i = 1, CQ_NQPARS(cc) {
+ if ((sz1 - op1 + 1) < (CQ_SZ_QPVALUE + 1)) {
+ sz1 = sz1 + SZ_LINE
+ call realloc (tmpdic, sz1, TY_CHAR)
+ }
+ if (i == parno) {
+ op1 = op1 + gstrcpy (valuestr, Memc[tmpdic+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[tmpdic+op1-1], sz1 - op1 + 1)
+ } else if (cq_wrdstr (i, Memc[pvalue], CQ_SZ_QPNAME,
+ Memc[CQ_PQPVALUES(cc)]) > 0) {
+ op1 = op1 + gstrcpy (Memc[pvalue], Memc[tmpdic+op1-1],
+ sz1 - op1 + 1)
+ op1 = op1 + gstrcpy ("|", Memc[tmpdic+op1-1], sz1 - op1 + 1)
+ }
+ }
+
+ # Update the values string.
+ call realloc (CQ_PQPVALUES(cc), op1, TY_CHAR)
+ call strcpy (Memc[tmpdic], Memc[CQ_PQPVALUES(cc)], op1 - 1)
+
+ # Free memory.
+ call mfree (tmpdic, TY_CHAR)
+ call sfree (sp)
+
+ return (parno)
+end
diff --git a/pkg/xtools/catquery/cqstat.x b/pkg/xtools/catquery/cqstat.x
new file mode 100644
index 00000000..152022a9
--- /dev/null
+++ b/pkg/xtools/catquery/cqstat.x
@@ -0,0 +1,74 @@
+include "cqdef.h"
+include "cq.h"
+
+
+# CQ_STATI -- Get an integer catalog database parameter.
+
+int procedure cq_stati (cq, param)
+
+pointer cq #I pointer to the catalog query structure.
+int param #I the integer parameter to be retrieved
+
+begin
+ switch (param) {
+ case CQNRECS:
+ return (CQ_NRECS(cq))
+ case CQSZRECLIST:
+ return (CQ_NAMEI(cq, CQ_NRECS(cq) + 1))
+ case CQCATNO:
+ return (CQ_CATNO(cq))
+ default:
+ call error (0, "Error fetching integer catalog database parameter")
+ }
+end
+
+
+
+# CQ_STATS -- Get a string catalog database parameter.
+
+procedure cq_stats (cq, param, str, maxch)
+
+pointer cq #I pointer to the catalog query structure.
+int param #I the string parameter to be retrieved
+char str[ARB] #O the output string parameter
+int maxch #I the maximum size of the string parameter
+
+begin
+ switch (param) {
+ case CQCATDB:
+ call strcpy (CQ_CATDB(cq), str, maxch)
+ case CQCATNAME:
+ call strcpy (CQ_CATNAME(cq), str, maxch)
+ default:
+ call error (0, "Error fetching string catalog database parameter")
+ }
+end
+
+
+# CQ_STATT -- Get a text list catalog database parameter. A text list is a
+# string with items separated from each other by newlines.
+
+int procedure cq_statt (cq, param, str, maxch)
+
+pointer cq #I pointer to the catalog query structure.
+int param #I the list parameter to be retrieved
+char str[ARB] #O the output string parameter
+int maxch #I the maximum size of the string parameter
+
+int i, fd
+int stropen()
+
+begin
+ switch (param) {
+ case CQRECLIST:
+ fd = stropen (str, maxch, NEW_FILE)
+ do i = 1, CQ_NRECS(cq) {
+ call fprintf (fd, "%s\n")
+ call pargstr (CQ_NAME(cq, i))
+ }
+ call strclose (fd)
+ return (CQ_NRECS(cq))
+ default:
+ call error (0, "Error fetching list catalog database parameter")
+ }
+end
diff --git a/pkg/xtools/catquery/cqwrdstr.x b/pkg/xtools/catquery/cqwrdstr.x
new file mode 100644
index 00000000..bfdf1088
--- /dev/null
+++ b/pkg/xtools/catquery/cqwrdstr.x
@@ -0,0 +1,56 @@
+
+# CQ_WRDSTR -- 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 cq_wrdstr (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)
+
+ # Return if the index is less than or equal to zero.
+ if (index <= 0)
+ 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/pkg/xtools/catquery/doc/README b/pkg/xtools/catquery/doc/README
new file mode 100644
index 00000000..f17920ab
--- /dev/null
+++ b/pkg/xtools/catquery/doc/README
@@ -0,0 +1,322 @@
+ CATQUERY: The Catalog and Survey Access Routines
+
+1. Introduction
+
+ The catquery package provides a set of routines for local and remote
+catalog and image survey server access. The supported catalogs and image
+surveys are described in records stored in a catalog and image survey
+configuration file respectively. The catalog and image survey records
+specify the network address, the query format, and the output format for
+each supported catalog or image display server. More detailed information
+about catalogs and image survey access and configuration files can be
+found by typing "help catalogs" and "help surveys".
+
+ The results of each catalog query are stored in memory in an IRAF spool
+file. Calling programs can access the catalog results sequentially or randomly
+by record number. Individual fields in each record can be decoded into
+floating point, integer, or string values.
+
+The results of each image survey query are written to an image file on disk,
+currently a fits image file. IRAF image i/o routines can be used to access
+the image. There must be enough space availale on the disk to receive the
+image.
+
+
+2. The Interface Routines
+
+The package prefix is cq. The interface routines are listed below.
+
+ cq = cq_map (file, mode)
+ ival = cq_stati (cq, param)
+ cq_stats (cq, param, str, maxch)
+ nlines = cq_statt (cq, param, text, maxch)
+
+ catno = cq_locate (cq, name)
+ catno = cq_locaten (cq, catno, catname, maxch)
+ catno = cq_setcat (cq, name)
+ catno = cq_setcatn (cq, catno)
+
+ [ird]val = cq_fget[ird] (cq, name)
+ nelems = cq_fga[ird] (cq, name, array[ird], max_nelems)
+ cq_fgstr (cq, name, str, maxch)
+ cq_fgwrd (cq, name, wrd, maxch)
+ nlines = cq_fgtext (cq, name, text, maxch)
+ stat = cq_scan (cq)
+
+ nqpars = cq_nqpars (cq)
+ qparno = cq_gqpar (cq, name, qpname, max_qpname, qpvalue,
+ max_qpvalue, qpunits, max_qpunits, qpformat,
+ max_qpformat)
+ qparno = cq_gqparn (cq, qparno, qpname, max_qpname, qpvalue,
+ max_qpvalue, qpunits, max_qpunits, qpformat, max_qpformat)
+ qparno = cq_sqpar (cq, name, valuestr)
+ qparno = cq_sqparn (cq, qparno, valuestr)
+
+ res = cq_query (cq)
+ res = cq_fquery (cq, catfile, cathdr)
+ ival = cq_rstati (res, param)
+ cq_rstats (res, param, str, maxch)
+ nlines = cq_rstatt (res, param, text, maxch)
+ hparno = cq_hinfo (res, name, hpvalue, max_hpvalue)
+ hparno = cq_hinfon (res, hparno, hpname, max_hpname, hpvalue,
+ max_hpvalue)
+ nchars = cq_grecord (res, buffer, maxch, recno)
+ nchars = cq_gnrecord (res, buffer, maxch, nextrec)
+ fieldno = cq_finfo (res, name, foffset, fsize, ftype, funits,
+ max_funits, formats, max_formats)
+ fieldno = cq_finfon (res, fieldno, fname, max_fname, foffset, fsize,
+ ftype, funits, max_funits, formats, max_formats)
+ cq_rclose (res)
+ nchars = cq_gval[silrd] (res, name, [silrd]val)
+ nchars = cq_gvalc (res, name, str, maxch)
+
+ imres = cq_imquery (cq, imname)
+ imres = cq_fimquery (cq, imname)
+ ival = cq_istati (imres, param)
+ cq_istats (imres, param, str, maxch)
+ nlines = cq_istatt (imres, param, text, maxch)
+ wparno = cq_winfo (imres, name, wkname, max_wkname, wvalue,
+ max_wvalue, wtype, wunits, max_wunits)
+ wparno = cq_winfon (imres, wparno, wpname, max_wpnane, wkname,
+ max_wkname, wvalue, max_wvalue, wtype, wunits, max_wunits)
+ kparno = cq_kinfo (imres, name, skname, max_skname, svalue,
+ max_svalue, stype, sunits, max_sunits)
+ kparno = cq_kinfon (imres, kparno, spname, max_spname, skname,
+ max_skname, svalue, max_svalue, stype, sunits, max_sunits)
+ cq_imclose (imres)
+
+ cq_unmap (cq)
+
+
+3. Notes
+
+ An "include <pkg/cq.h>" statement must appear in the calling program to
+make the catquery pacakge parameter definitions visible to the calling program.
+
+ A "-lxtools" must be included in the calling program link line to link in
+the catquery routines.
+
+ The catalog and image surveys configuration files are mapped and unmapped
+with the routines cq_map and cq_unmap.
+
+ Before making a query the calling program must set the current catalog
+or image survey with the cq_setcat or cq_setcatn routines, and format
+and set the query parameters with the cq_gqpar, cq_gqparn, and cq_sqparn
+routines.
+
+ Remote and locate catalog queries are made with the cq_query routine.
+The routines cq_rstat[ist] are used to retrieve the catalog results parameters.
+Header parameter values and field descriptions can be retrieved with
+the cq_hinfo / cq_hinfon and cq_finfo / cq_finfon routines respectively.
+Catalog records can be accessed sequentially or randomly with the cq_gnrecord
+and cq_grecord routines. The cq_gval[csilrd] routines can be used to decode
+the record fields into floating point, integer, or string values. The
+cq_fquery routine is used to make a catalog file emulate the results of a
+catalog query. Cq_rclose frees the catalog results descriptor.
+
+ Remote and locate image survey queries are made with the cq_imquery routine.
+The routines cq_istat[ist] are used to retrieve the survey results parameters.
+The standard wcs and image parameter descriptions can be retrieved with the
+the cq_winfo / cq_winfon and cq_kinfo / cq_kinfon routines respectively. The
+cq_fimquery routine is used to make an existing image emulate the results of
+an image survey query. Cq_imclose frees the survey results descriptor.
+
+4. Examples
+
+Example 1: Query a catalog and dump the results to a catalog file.
+
+ include <cq.h>
+
+ ....
+
+ ra = clgetd ("ra")
+ dec = clgetd ("dec")
+ width = clgetd ("width")
+
+ ....
+
+ # Open the catalog configuration file.
+ cq = cq_map ("astromz$lib/catdb.dat", READ_ONLY)
+ if (cq == NULL)
+ ...
+
+ # Set the catalog.
+ catno = cq_setcat (cq, "noao@usno2")
+ if (catno == 0)
+ ...
+
+ # Set the query parameters. Assume the input input units match the
+ # the expected units. The input size is a width so divide by two
+ # if the query expects a radius.
+ nqpars = cq_nqpars (cq)
+ do i = 1, nqpars {
+ parno = cq_gqparn (cq, i, qpname, CQ_SZ_QPNAME, qpvalue,
+ CQ_SZ_QPVALUE, qpunits, CQ_SZ_QPUNITS, qpformats
+ CQ_SZ_QPFORMATS)
+ if (parno != i)
+ next
+ if (streq (qpname, "ra")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (ra)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "dec")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (dec)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "radius")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width / 2.0d0)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "width")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "xwidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "ywidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ }
+ }
+
+ # Make the query.
+ res = cq_query (cq)
+ if (res == NULL)
+ ...
+
+ # Write the results to a file.
+ recptr = 0
+ while (cq_gnrecord (res, buffer, SZ_LINE, rectpr) != EOF) {
+ call fprintf (outfd, "%s")
+ call pargstr (buffer)
+ }
+
+ # Close the query.
+ call cq_rclose (res)
+
+ # Close the database.
+ call cq_unmap (cq)
+
+
+Example 2: Repeat the previous example but only output records for
+ which magnitude values <= 16.0.
+
+ include <cq.h>
+
+ ...
+
+ res = cq_query (cq)
+ if (res == NULL)
+ ...
+
+ nrec = cq_rstati (res, CQNRECS)
+ do i = 1, nrecs {
+ nchars = cq_gvalr (res, i, "mag1", mag)
+ if (nchars <= 0)
+ next
+ if (mag > 16.0)
+ next
+ nchars = cq_grecord (res, buffer, SZ_LINE, i)
+ if (nchars <= 0)
+ next
+ call fprintf (outfd, "%s")
+ call pargstr (buffer)
+ }
+
+ call cq_rclose (res)
+
+ ...
+
+
+Example 3: Make an image survey query and dump the results to a fits file.
+
+ include <cq.h>
+
+ ....
+
+ ra = clgetd ("ra")
+ dec = clgetd ("dec")
+ width = clgetd ("width")
+
+ ....
+
+ # Open the catalog configuration file.
+ cq = cq_map ("astromz$lib/imdb.dat", READ_ONLY)
+ if (cq == NULL)
+ ...
+
+ # Set the catalog.
+ catno = cq_setcat (cq, "dss1@cadc")
+ if (catno == 0)
+ ...
+
+ # Set the query parameters. Assume the input input units match the
+ # the expected units.
+ nqpars = cq_nqpars (cq)
+ do i = 1, nqpars {
+ parno = cq_gqparn (cq, i, qpname, CQ_SZ_QPNAME, qpvalue, CQ_SZ_QPVALUE,
+ qpunits, CQ_SZ_QPUNITS, qpformats, CQ_SZ_QPFORMATS)
+ if (parno != i)
+ next
+ if (streq (qpname, "ra")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (ra)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "dec")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (dec)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "width")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "xwidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "ywidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ }
+ }
+
+ # Make the query.
+ imres = cq_imquery (cq, "outimage.fits")
+ if (imres == NULL)
+ ...
+
+ # Free the results structure
+ call cq_imclose (imres)
+
+ # Unmap the database
+ call cq_unmap (cq)
+
+
+
+Example 4: Repeat the previous example but convert the dss wcs to a fits wcs.
+At_mkdss is a routine which converts a dss wcs to a fits wcs
+
+ ...
+
+ # Make the query.
+ imres = cq_imquery (cq, "outimage.fits")
+ if (imres == NULL)
+ ...
+
+ wcstype = cq_istati (imres, CQWCS)
+ if (wcstype == CQWDSS) {
+ im = immap ("outimage.fits", READ_WRITE, 0)
+ stat = at_mkdss (im, true, false)
+ if (stat == ERR)
+ ...
+ call imunmap (im)
+ }
+
+ # Free the results structure
+ call cq_imclose (imres)
+
+ ...
diff --git a/pkg/xtools/catquery/doc/catalogs.hlp b/pkg/xtools/catquery/doc/catalogs.hlp
new file mode 100644
index 00000000..4109f810
--- /dev/null
+++ b/pkg/xtools/catquery/doc/catalogs.hlp
@@ -0,0 +1,233 @@
+.help catalogs Mar00 astromz
+.ih
+NAME
+catalogs -- describe the catalog configuration file
+.ih
+USAGE
+help catalogs
+.ih
+CATALOGS
+
+A catalog is a large set of tabular data records from which smaller
+tabular data sets can be extracted by issuing a catalog server query. Catalogs
+may be installed locally or accessed remotely. Installing a catalog involves
+creating a record in the catalog configuration file which specifies the
+catalog network address, the catalog query format, and the catalog query
+output format. In the following sections the configuration file is
+described in the context of accessing astrometric catalogs.
+
+.ih
+THE CATALOG CONFIGURATION FILE
+
+A record in the catalog configuration file specifies the network address,
+the query format, and the output format of each supported catalog server.
+Catalog server records names have the form "catalog@site",
+e.g. "usno2@noao". Adding support for a new catalog server or responding
+to changes in the behavior of an already supported server requires either adding
+a new record to the configuration file or changing an existing record in
+the configuration file. It does not require changing the catalog
+access code.
+
+The catalog server network address tells the catalog access code where
+and how to connect to the network. Each network address has the syntax
+"domain:port:address:flags" e.g. "inet:80:www.noao.edu:text".
+
+The query format specifies the form of the query server string, and the
+names, default values, units, and format of the query parameters. A set of
+query parameter names are reserved for accessing astrometric catalogs
+including "ra", "dec", "radius", "hwidth", "width", "rawidth", "decwidth",
+rahwidth, and dechwidth. The names of these parameters are not part of the
+catalog access API. Other types of catalogs may have different reserved
+query parameter names. The user replaces the default query values with user
+query parameter values before making the query.
+
+The server query output format specifies the form of the expected server output:
+including the data stream type, the record size, and the name, location,
+size, data type, units and format of each field in the record. A set of
+standard field names is reserved for accessing the output of astrometric
+catalog servers including "id", "ra", "dec", and "mag[1-n]". These standard
+field names are not part of the catalog access API. Other catalog
+types may have a different set of standard field names in the future.
+
+.ih
+SAMPLE CATALOG RECORD
+
+The following two examples illustrate typical catalog configuration file
+records. Note that both records can be used to access the same catalog
+data. The first example accesses the catalog as simple text, the latter
+as blocked text.
+
+.nf
+Example 1: Accessing the catalog as simple text.
+
+begin susno2@noao
+address inet:80:www.noao.edu:text
+query GET /cgi-bin/usno/usnoextract?search=yes&ra=%-s&dec=%-s&width=%-s HTTP/1.0
+\n\n
+nquery 4
+ ra 00:00:00.00 hours %0.2h
+ dec 00:00:00.0 degrees %0.1h
+ radius 5.0 minutes %0.1f
+ qsystem J2000.0 INDEF %s
+type stext
+ hskip 10
+ tskip 6
+ recsize 0
+ triml 0
+ trimr 4
+nheader 1
+ csystem J2000.0
+nfields 4
+ ra 1 0 d hours %12.3h
+ dec 2 0 d degrees %12.2h
+ mag1 3 0 r INDEF %4.1f
+ mag2 4 0 r INDEF %4.1f
+.fi
+
+.nf
+Example 2: Accessing the catalog as blocked text.
+
+begin busno2@noao
+address inet:80:www.noao.edu:text
+query GET /cgi-bin/usno/usnoextract?search=yes&ra=%-s&dec=%-s&width=%-s HTTP/1.0
+\n\n
+nquery 4
+ ra 00:00:00.00 hours %0.2h
+ dec 00:00:00.0 degrees %0.1h
+ radius 5.0 minutes %0.1f
+ qsystem J2000.0 INDEF %s
+type btext
+ hskip 10
+ tskip 6
+ recsize 44
+ triml 0
+ trimr 4
+nheader 1
+ csystem J2000.0
+nfields 4
+ ra 1 13 d hours %12.3h
+ dec 14 14 d degrees %12.2h
+ mag1 28 6 r INDEF %4.1f
+ mag2 34 6 r INDEF %4.1f
+.fi
+
+The beginning of a new catalog record is indicated by a line of the form
+\fI"begin catname"\fR where catname is a unique name of the form
+\fI"catalog@site"\fR. If there is more than one record with the same
+name, the last record is the one that is read. The same catalog server
+may be accessed in more than one way by creating multiple records.
+For example if the catalog server supports an optional magnitude selection
+feature, then in one record this feature can be enabled and in another it
+can be disabled.
+
+The \fIaddress\fR, \fIquery\fR and \fInquery\fR keywords are required and
+define the network address, query command, format and query parameters for
+the catalog.
+
+The \fIaddress\fR keyword "domain", "port", and "flags" fields are almost
+always "inet", "80", and "text" respectively, so in most cases the only
+address keyword field that has to be filled in is the address
+field "www.noao.edu" in this case.
+
+The \fIquery\fR keyword defines the query command whose form is server
+dependent. The query parameter values are encoded via the %-s formatting
+strings. The calling program must encode the user query parameter values
+into a set a strings which then replace the -%s format statement in the
+query string.
+
+The number of query parameters is defined by the \fInquery\fR keyword. The
+number of query parameters must be greater than or equal to the number of "-%s"
+strings in the query keyword value. The name, default value, units,
+and format of each query parameter are listed below the nquery keyword,
+one query parameter description per line. The query parameters should
+be defined in the catalog configuration file in the same order that they
+appear in the query keyword value. Alert readers will notice that in
+the examples above the number of query parameters is 4 but there are only
+3 "%-s" strings in the query keyword value. In these examples the qsystem
+query parameter, which defines the coordinate system of the ra and dec query
+parameter values is fixed at J2000. For some servers this parameter may
+be a true query parameter, i.e. the server may accept coordinates in
+B1950 or J2000 or some other coordinate system.
+
+For astrometric catalogs the reserved query parameter names "ra", "dec", and
+"qysystem" should be used to define the extraction region center and its
+coordinate system, and one or more of "radius", "width", "xwidth", and
+"ywidth" should be used to define the extraction region size. The units
+of "ra" should be "hours", "degrees", or "radians", the units of dec
+should be "degrees" or "radians", and units of the size query parameter
+should be "degrees" or "minutes". The qsystem parameter value may be
+any one of the supported celestial coordinate systems. The most common
+qsystem values are "icrs", "J2000", or "B1950". The query parameter
+formats are used to convert numerical values supplied by the calling
+program to string values that can be passed to the query string.
+It should be emphasized that the reserved query parameter names and units
+are conventions that are adopted to simplify writing the configuration
+file and astrometric applications. They are not part of the catalog
+access API itself.
+
+The \fItype\fR keyword defines the form of the query output. The current options
+are "stext" for simple text and "btext" for blocked text. Simple text
+contains newline delimited records with whitespace delimited fields.
+Blocked text contains newline delimited records and fixed position and size
+fields. If the type keyword is missing "stext" is assumed.
+
+The \fIrecsize\fR keyword is the length of the record in characters including
+the newline character. If the record size is variable recsize should be set
+t0 0. If undefined the recsize keyword defaults to 0 for variable record
+size.
+
+The \fIhskip\fR, \fItskip\fR, \fIltrim\fR, and \fItrim\fR define the number
+of leading and trailing records in the query output to sky, and the
+number of leading and trailing characters in each record to trim, i.e.
+replace with blanks. If absent these keywords default to zero.
+
+The \fInheader\fR keyword defines the number of header keywords. Header
+keyword values are global quantities which apply to the catalog server
+output as a whole. There may be 0 or many header keywords.
+
+For most astrometry catalog the most important and often only header keyword
+is \fIcsystem\fR which defines the coordinate system of the query output
+coordinates, i.e. if csystem is "J2000" then the coordinates of objects
+extracted from the catalog are in "J2000".
+
+The \fInfields\fR keyword defines the number of fields in the query output
+records. The name, offset, size, datatype, units, and format of each field
+follow, one field description per line. For simple text files the offset
+is field or column number and the size is 0 meaning undefined. For blocked
+text files the offset is the 1-indexed position of the first character (which
+may be blank) in the field and size is the field size in characters where
+the field size includes trailing blanks. Using a blocked text description may
+be required for dealing with fields containing embedded blanks. The type
+defines the preferred data type of a field. In the examples above the ra and
+dec are assigned double precision data types. This means that for precision
+reasons the calling program should but is not required to read these
+quantities into double precision variables. The units information is
+used to perform any required coordinate conversions, and the format information
+is used in cases where the calling program must decode a field, perform
+some numerical operation on it, and reencode it with the original precision.
+
+For astrometric catalogs the reserved standard field names "id", "ra", "dec",
+"mag#" etc should be used to define the standard field names. The current
+standard field name list is \fIid\fR, \fIra\fR, \fIdec\fR, \fRera\fR,
+\fIedec\fR, \fIpmra\fR, \fIpmdec\fR, \fIepmra\fR, \fIepmdec\fR,
+\fIcatsystem\fR, \fIequinox\fR, \fIepoch\fR, \fIpx\fR, \fIrv\fR, \fIepx\fR,
+\fIerv\fR, \fImag\fR, \fIcolor\fR, \fIemag\fR, \fIecolor\fR, \fIxp\fR,
+\fIyp\fR, \fIxc\fR, \fIyc\fR, \fIexc\fR, \fIeyc\fR, \fIimag\fR, and \fIeimag\fR.
+At a minimum an astrometric catalog must contain the "ra" and "dec" fields.
+The units of the ra field must be "hours", "degrees", or "radians"
+and the units of the "dec" field must be "degrees" or "radians". The
+other standard fields are optional and define quantities like: proper
+motions in ra and dec, the coordinate system, equinox, and epoch
+of observation, parallax, radial velocity, magnitude and color information,
+and predicted image pixel coordinates. The definitions and default units
+for all these quantities are defined more fully in the help for the
+astrometry package. It should be emphasized that the reserved field names
+and units names are conventions that are adopted to simplify writing the
+configuration file and astrometric applications. They are not part of
+the catalog access API itself.
+
+
+.ih
+SEE ALSO
+surveys
+.endhelp
diff --git a/pkg/xtools/catquery/doc/catquery.hd b/pkg/xtools/catquery/doc/catquery.hd
new file mode 100644
index 00000000..1ae79114
--- /dev/null
+++ b/pkg/xtools/catquery/doc/catquery.hd
@@ -0,0 +1,56 @@
+# Help directory for the CATQUERY library
+
+$doc = "./"
+$source = "../"
+
+cqmap hlp=doc$cqmap.hlp, src=source$cqmap.x
+cqstati hlp=doc$cqstati.hlp, src=source$cqstat.x
+cqstats hlp=doc$cqstats.hlp, src=source$cqstat.x
+cqstatt hlp=doc$cqstatt.hlp, src=source$cqstat.x
+cqlocate hlp=doc$cqlocate.hlp, src=source$cqlocate.x
+cqlocaten hlp=doc$cqlocaten.hlp, src=source$cqlocate.x
+cqsetcat hlp=doc$cqsetcat.hlp, src=source$cqsetcat.x
+cqsetcatn hlp=doc$cqsetcatn.hlp, src=source$cqsetcat.x
+cqget hlp=doc$cqget.hlp, src=source$cqget.x
+
+cqnqpars hlp=doc$cqnqpars.hlp, src=source$cqnqpars.x
+cqgqpar hlp=doc$cqgqpar.hlp, src=source$cqgqpar.x
+cqgqparn hlp=doc$cqgqparn.hlp, src=source$cqgqpar.x
+cqsqpar hlp=doc$cqsqpar.hlp, src=source$cqsqpar.x
+cqsqparn hlp=doc$cqsqparn.hlp, src=source$cqsqpar.x
+
+cqquery hlp=doc$cqquery.hlp, src=source$cqquery.x
+cqfquery hlp=doc$cqfquery.hlp, src=source$cqquery.x
+cqrstati hlp=doc$cqrstati.hlp, src=source$cqrstat.x
+cqrstats hlp=doc$cqrstats.hlp, src=source$cqrstat.x
+cqrstatt hlp=doc$cqrstatt.hlp, src=source$cqrstat.x
+cqhinfo hlp=doc$cqhinfo.hlp, src=source$cqrinfo.x
+cqhinfon hlp=doc$cqhinfon.hlp, src=source$cqrinfo.x
+cqfinfo hlp=doc$cqfinfo.hlp, src=source$cqrinfo.x
+cqfinfon hlp=doc$cqfinfon.hlp, src=source$cqrinfo.x
+cqgrecord hlp=doc$cqgrecord.hlp, src=source$cqrecords.x
+cqgnrecord hlp=doc$cqgnrecord.hlp, src=source$cqrecords.x
+cqgvalc hlp=doc$cqgvalc.hlp, src=source$cqgfields.x
+cqgvals hlp=doc$cqgvals.hlp, src=source$cqgfields.x
+cqgvali hlp=doc$cqgvali.hlp, src=source$cqgfields.x
+cqgvall hlp=doc$cqgvall.hlp, src=source$cqgfields.x
+cqgvalr hlp=doc$cqgvalr.hlp, src=source$cqgfields.x
+cqgvald hlp=doc$cqgvald.hlp, src=source$cqgfields.x
+cqrclose hlp=doc$cqrclose.hlp, src=source$cqquery.x
+
+cqimquery hlp=doc$cqimquery.hlp, src=source$cqimquery.x
+cqfimquery hlp=doc$cqfimquery.hlp, src=source$cqimquery.x
+cqistati hlp=doc$cqistati.hlp, src=source$cqistat.x
+cqistats hlp=doc$cqistats.hlp, src=source$cqistat.x
+cqistatt hlp=doc$cqistatt.hlp, src=source$cqistat.x
+cqwinfo hlp=doc$cqwinfo.hlp, src=source$cqiminfo.x
+cqwinfon hlp=doc$cqwinfon.hlp, src=source$cqiminfo.x
+cqkinfo hlp=doc$cqkinfo.hlp, src=source$cqiminfo.x
+cqkinfon hlp=doc$cqkinfon.hlp, src=source$cqiminfo.x
+cqimclose hlp=doc$cqimclose.hlp, src=source$cqimquery.x
+
+cqunmap hlp=doc$cqunmap.hlp, src=source$cqmap.x
+
+ccsystems hlp=doc$ccsystems.hlp
+catalogs hlp=doc$catalogs.hlp
+surveys hlp=doc$surveys.hlp
diff --git a/pkg/xtools/catquery/doc/catquery.hlp b/pkg/xtools/catquery/doc/catquery.hlp
new file mode 100644
index 00000000..3521c62c
--- /dev/null
+++ b/pkg/xtools/catquery/doc/catquery.hlp
@@ -0,0 +1,322 @@
+.help catquery Aug01 xtools
+.ih
+NAME
+catquery -- catalog access package
+.ih
+SYNOPSIS
+
+.nf
+ cq = cq_map (file, mode)
+ ival = cq_stati (cq, param)
+ cq_stats (cq, param, str, maxch)
+ nlines = cq_statt (cq, param, text, maxch)
+
+ catno = cq_locate (cq, name)
+ catno = cq_locaten (cq, catno, catname, maxch)
+ catno = cq_setcat (cq, name)
+ catno = cq_setcatn (cq, catno)
+
+ [ird]val = cq_fget[ird] (cq, name)
+ nelems = cq_fga[ird] (cq, name, array[ird], max_nelems)
+ cq_fgstr (cq, name, str, maxch)
+ cq_fgwrd (cq, name, wrd, maxch)
+ nlines = cq_fgtext (cq, name, text, maxch)
+ stat = cq_scan (cq)
+
+ nqpars = cq_nqpars (cq)
+ qparno = cq_gqpar (cq, name, qpname, max_qpname, qpvalue,
+ max_qpvalue, qpunits, max_qpunits, qpformat,
+ max_qpformat)
+ qparno = cq_gqparn (cq, qparno, qpname, max_qpname, qpvalue,
+ max_qpvalue, qpunits, max_qpunits, qpformat, max_qpformat)
+ qparno = cq_sqpar (cq, name, valuestr)
+ qparno = cq_sqparn (cq, qparno, valuestr)
+
+ res = cq_query (cq)
+ res = cq_fquery (cq, catfile, cathdr)
+ ival = cq_rstati (res, param)
+ cq_rstats (res, param, str, maxch)
+ nlines = cq_rstatt (res, param, text, maxch)
+ hparno = cq_hinfo (res, name, hpvalue, max_hpvalue)
+ hparno = cq_hinfon (res, hparno, hpname, max_hpname, hpvalue,
+ max_hpvalue)
+ nchars = cq_grecord (res, buffer, maxch, recno)
+ nchars = cq_gnrecord (res, buffer, maxch, nextrec)
+ fieldno = cq_finfo (res, name, foffset, fsize, ftype, funits,
+ max_funits, formats, max_formats)
+ fieldno = cq_finfon (res, fieldno, fname, max_fname, foffset, fsize,
+ ftype, funits, max_funits, formats, max_formats)
+ cq_rclose (res)
+ nchars = cq_gval[silrd] (res, name, [silrd]val)
+ nchars = cq_gvalc (res, name, str, maxch)
+
+ imres = cq_imquery (cq, imname)
+ imres = cq_fimquery (cq, imname)
+ ival = cq_istati (imres, param)
+ cq_istats (imres, param, str, maxch)
+ nlines = cq_istatt (imres, param, text, maxch)
+ wparno = cq_winfo (imres, name, wkname, max_wkname, wvalue,
+ max_wvalue, wtype, wunits, max_wunits)
+ wparno = cq_winfon (imres, wparno, wpname, max_wpnane, wkname,
+ max_wkname, wvalue, max_wvalue, wtype, wunits, max_wunits)
+ kparno = cq_kinfo (imres, name, skname, max_skname, svalue,
+ max_svalue, stype, sunits, max_sunits)
+ kparno = cq_kinfon (imres, kparno, spname, max_spname, skname,
+ max_skname, svalue, max_svalue, stype, sunits, max_sunits)
+ cq_imclose (imres)
+
+ cq_unmap (cq)
+.fi
+.ih
+DESCRIPTION
+The catquery package provides a set of routines for local and remote
+catalog and image survey server access. The supported catalogs and image
+surveys are described in records stored in a catalog and image survey
+configuration file respectively. The catalog and image survey records
+specify the network address, the query format, and the output format for
+each supported catalog or image display server. More detailed information
+about catalogs and image survey access and configuration files can be
+found by typing "help catalogs" and "help surveys".
+
+The results of each catalog query are stored in memory in an IRAF spool file.
+Calling programs can access the catalog results sequentially or randomly
+by record number. Individual fields in each record can be decoded into
+floating point, integer, or string values.
+
+The results of each image survey query are written to an image file on disk,
+currently a fits image file. IRAF image i/o routines can be used to access
+the image. There must be enough space availale on the disk to receive the
+image.
+
+.ih
+NOTES
+
+The catquery package definitions file is cq.h.
+
+The catalog and image surveys configuration files are mapped and unmapped
+with the routines cq_map and cq_unmap.
+
+Before making a query the calling program must set the current catalog
+or image survey with the cq_setcat or cq_setcatn routines, and format
+and set the query parameters with the cq_gqpar, cq_gqparn, and cq_sqparn
+routines.
+
+Remote and locate catalog queries are made with the cq_query routine.
+The routines cq_rstat[ist] are used to retrieve the catalog results parameters.
+Header parameter values and field descriptions can be retrieved with
+the cq_hinfo, cq_hinfon, cq_finfo, and cq_finfon routines. Catalog records
+can be accessed sequentially or randomly with the cq_gnrecord and
+cq_grecord routines. The cq_gval[csilrd] routines can be used to decode
+the record fields into floating point, integer, or string values.
+The cq_fquery routine is used to make a catalog file emulate
+the results of a catalog query. Cq_rclose frees the catalog results descriptor.
+
+Remote and locate image survey queries are made with the cq_imquery routine.
+The routines cq_istat[ist] are used to retrieve the survey results parameters.
+The standard wcs and image parameter descriptions can be retrieved with the
+the cq_winfo, cq_winfon, cq_kinfo, and cq_kinfon routines. The cq_fimquery
+routine is used to make an existing image emulate the results of an image
+survey query. Cq_imclose frees the survey results descriptor.
+
+.ih
+EXAMPLES
+.nf
+Example 1: Query a catalog and dump the results to a catalog file.
+
+ include <cq.h>
+
+ ....
+
+ ra = clgetd ("ra")
+ dec = clgetd ("dec")
+ width = clgetd ("width")
+
+ ....
+
+ # Open the catalog configuration file.
+ cq = cq_map ("astromz$lib/catdb.dat", READ_ONLY)
+ if (cq == NULL)
+ ...
+
+ # Set the catalog.
+ catno = cq_setcat (cq, "noao@usno2")
+ if (catno == 0)
+ ...
+
+ # Set the query parameters. Assume the input units match the
+ # the expected units. The input size is a width so divide by two
+ # if the query expects a radius.
+ nqpars = cq_nqpars (cq)
+ do i = 1, nqpars {
+ parno = cq_gqparn (cq, i, qpname, CQ_SZ_QPNAME, qpvalue,
+ CQ_SZ_QPVALUE, qpunits, CQ_SZ_QPUNITS, qpformats
+ CQ_SZ_QPFORMATS)
+ if (parno != i)
+ next
+ if (streq (qpname, "ra")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (ra)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "dec")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (dec)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "radius")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width / 2.0d0)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "width")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "xwidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "ywidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ }
+ }
+
+ # Make the query.
+ res = cq_query (cq)
+ if (res == NULL)
+ ...
+
+ # Write the results to a file.
+ recptr = 0
+ while (cq_gnrecord (res, buffer, SZ_LINE, rectpr) != EOF) {
+ call fprintf (outfd, "%s")
+ call pargstr (buffer)
+ }
+
+ # Close the query.
+ call cq_rclose (res)
+
+ # Close the database.
+ call cq_unmap (cq)
+
+
+Example 2: Repeat the previous example but only output records for
+ which magnitude values <= 16.0.
+
+ include <cq.h>
+
+ ...
+
+ res = cq_query (cq)
+ if (res == NULL)
+ ...
+
+ nrec = cq_rstati (res, CQNRECS)
+ do i = 1, nrecs {
+ nchars = cq_gvalr (res, i, "mag1", mag)
+ if (nchars <= 0)
+ next
+ if (mag > 16.0)
+ next
+ nchars = cq_grecord (res, buffer, SZ_LINE, i)
+ if (nchars <= 0)
+ next
+ call fprintf (outfd, "%s")
+ call pargstr (buffer)
+ }
+
+ call cq_rclose (res)
+
+ ...
+
+
+Example 3: Make an image survey query and dump the results to a fits file.
+
+ include <cq.h>
+
+ ....
+
+ ra = clgetd ("ra")
+ dec = clgetd ("dec")
+ width = clgetd ("width")
+
+ ....
+
+ # Open the catalog configuration file.
+ cq = cq_map ("astromz$lib/imdb.dat", READ_ONLY)
+ if (cq == NULL)
+ ...
+
+ # Set the catalog.
+ catno = cq_setcat (cq, "dss1@cadc")
+ if (catno == 0)
+ ...
+
+ # Set the query parameters. Assume the input units match the
+ # the expected units.
+ nqpars = cq_nqpars (cq)
+ do i = 1, nqpars {
+ parno = cq_gqparn (cq, i, qpname, CQ_SZ_QPNAME, qpvalue, CQ_SZ_QPVALUE,
+ qpunits, CQ_SZ_QPUNITS, qpformats, CQ_SZ_QPFORMATS)
+ if (parno != i)
+ next
+ if (streq (qpname, "ra")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (ra)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "dec")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (dec)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "width")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "xwidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ } else if (streq (qpname, "ywidth")) {
+ call sprintf (qpvalue, CQ_SZ_QPVALUE, qpformats)
+ call pargd (width)
+ parno = cq_sqpars (cq, qpname, qpvalue)
+ }
+ }
+
+ # Make the query.
+ imres = cq_imquery (cq, "outimage.fits")
+ if (imres == NULL)
+ ...
+
+ # Free the results structure
+ call cq_imclose (imres)
+
+ # Unmap the database
+ call cq_unmap (cq)
+
+
+
+Example 4: Repeat the previous example but convert the dss wcs to a fits wcs.
+ At_mkdss is a routine which converts a dss wcs to a fits wcs
+
+ ...
+
+ # Make the query.
+ imres = cq_imquery (cq, "outimage.fits")
+ if (imres == NULL)
+ ...
+
+ wcstype = cq_istati (imres, CQWCS)
+ if (wcstype == CQWDSS) {
+ im = immap ("outimage.fits", READ_WRITE, 0)
+ stat = at_mkdss (im, true, false)
+ if (stat == ERR)
+ ...
+ call imunmap (im)
+ }
+
+ # Free the results structure
+ call cq_imclose (imres)
+
+ ...
+.fi
+.endhelp
diff --git a/pkg/xtools/catquery/doc/catquery.men b/pkg/xtools/catquery/doc/catquery.men
new file mode 100644
index 00000000..ace43e7c
--- /dev/null
+++ b/pkg/xtools/catquery/doc/catquery.men
@@ -0,0 +1,28 @@
+ cqmap - Map the catalog / survey configuration file
+ cqstat[ist] - Get an integer, string, or text catalog / survey parameter
+ cqlocate[n] - Locate a catalog / survey by name or number
+ cqsetcat[n] - Set the current catalog / survey by name or number
+ cqget - Read catalog / survey configuration file keywords directly
+
+ cqnqpars - Get the number of query parameters
+ cqgqpar[n] - Get query parameter info by name or number
+ cqsqpar[n] - Set query parameter value by name or number
+
+ cqquery - Query a catalog and return the results
+ cqfquery - Query a catalog file and return the results
+ cqrstat[ist] - Get catalog results integer, string, or text parameter
+ cqhinfo[n] - Get catalog results header value by name or number
+ cqgrecord - Get catalog results record
+ cqgnrecord - Get next catalog results record
+ cqfinfo[n] - Get catalog results field info by name or number
+cqgval[csilrd] - Get field value from record
+ cqrclose - Close the catalog results
+
+ cqimquery - Query an image survey and return the results
+ cqfimquery - Query an image file and return the results
+ cqistat[ist] - Get survey results integer, string, or text parameter
+ cqwinfo[n] - Get survey results wcs parameter info by name or number
+ cqkinfo[n] - Get survey results image parameter info by name or number
+ cqimclose - Close the survey results
+
+ cqunmap - Unmap the configuration file
diff --git a/pkg/xtools/catquery/doc/ccsystems.hlp b/pkg/xtools/catquery/doc/ccsystems.hlp
new file mode 100644
index 00000000..3c1235a6
--- /dev/null
+++ b/pkg/xtools/catquery/doc/ccsystems.hlp
@@ -0,0 +1,134 @@
+.help ccsystems Mar00 catquery
+.ih
+NAME
+ccsystems -- list and describe the supported sky coordinate systems
+.ih
+USAGE
+help ccsystems
+
+.ih
+SKY COORDINATE SYSTEMS
+
+The sky package supports the equatorial ("fk4", "fk4-noe", "fk5", "icrs"),
+ecliptic, galactic, and supergalactic celestial coordinate systems. In most
+cases and unless otherwise noted users can input their coordinates in
+any one of these systems as long as they specify the coordinate system
+correctly.
+
+Considerable flexibility is permitted in how the coordinate systems are
+specified, e.g. J2000.0, j2000.0, 2000.0, fk5, fk5 J2000, and fk5 2000.0
+all specify the mean place post-IAU 1976 or FK5 system. Missing equinox and
+epoch fields assume reasonable defaults. In most cases the
+systems of most interest to users are "icrs", "j2000", and "b1950"
+which stand for the ICRS J2000.0, FK5 J2000.0 and FK4 B1950.0 celestial
+coordinate systems respectively. The full set of options are listed below:
+
+.ls equinox [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system if equinox is a
+Julian epoch, e.g. J2000.0 or 2000.0, or the equatorial mean place
+pre-IAU 1976 system (FK4) if equinox is a Besselian epoch, e.g. B1950.0
+or 1950.0. Julian equinoxes are prefixed by a J or j, Besselian equinoxes
+by a B or b. Equinoxes without the J / j or B / b prefix are treated as
+Besselian epochs if they are < 1984.0, Julian epochs if they are >= 1984.0.
+Epoch is the epoch of the observation and may be a Julian
+epoch, a Besselian epoch, or a Julian date. Julian epochs
+are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to the epoch type of
+equinox if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls icrs [equinox] [epoch]
+The International Celestial Reference System where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk5 [equinox] [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system where equinox is a
+Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0. Epoch
+is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls noefk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system but without the E-terms
+where equinox is a Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day. If undefined epoch defaults to equinox.
+.le
+.ls apparent epoch
+The equatorial geocentric apparent place post-IAU 1976 system where
+epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date.
+.le
+.ls ecliptic epoch
+The ecliptic coordinate system where epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch values < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day.
+.le
+.ls galactic [epoch]
+The IAU 1958 galactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+.ls supergalactic [epoch]
+The deVaucouleurs supergalactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+
+Fields enclosed in [] are optional with the defaults as described. The epoch
+field for the "icrs" , "fk5", "galactic", and "supergalactic" coordinate
+systems is only used if the input coordinates are in the equatorial fk4,
+noefk4, fk5, or icrs systems and proper motions are used to transform from
+coordinate system to another.
+
+.ih
+SEE ALSO
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqfimquery.hlp b/pkg/xtools/catquery/doc/cqfimquery.hlp
new file mode 100644
index 00000000..d344c7ee
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqfimquery.hlp
@@ -0,0 +1,39 @@
+.help cqfimquery Mar00 "Catquery Package"
+.ih
+NAME
+cqfimquery -- return the results of an image file query
+.ih
+SYNOPSIS
+
+imres = cq_fimquery (cq, imname)
+
+.nf
+pointer cq # the configuration file descriptor
+char imname # the input image file name
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls imname
+The file name of the image being queried.
+.le
+.ih
+DESCRIPTION
+Cq_fimquery queries an existing image and returns a results descriptor.
+Cq_fimquery is a pointer procedure which returns the results descriptor
+as its function value. NULL is returned if an error occurs in the query
+or the image does not exist.
+
+Cq_fimquery is used to make an image emulate the results of an image
+survey query.
+.ih
+NOTES
+Cq_setcat with the image survey name set to the reserved record name
+"imname@noao" must be called before any image survey query is made.
+
+.ih
+SEE ALSO
+cqimquery, cqimclose
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqfinfo.hlp b/pkg/xtools/catquery/doc/cqfinfo.hlp
new file mode 100644
index 00000000..b3bce18a
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqfinfo.hlp
@@ -0,0 +1,85 @@
+.help cqfinfo Mar00 "Catquery Package"
+.ih
+NAME
+cqfinfo -- get the requested description by name
+.ih
+SYNOPSIS
+
+fieldno = cq_finfo (res, name, fname, max_fname, foffset, fsize, ftype, funits,
+ max_funits, format, max_format)
+
+.nf
+pointer res # the results descriptor
+char name # the input field name
+char fname # the returned field name
+int max_fname # the maximum size of the field name
+int foffset # the returned field offset
+int fsize # the returned field size
+int ftype # the returned field type
+char funits # the returned field units
+int max_funits # the maximum size of the field units
+char format # the returned field format
+int max_format # the maximum size of the field format
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls name
+The name of the requested field.
+.le
+.ls fname
+The returned field name.
+.le
+.ls max_fname
+The maximum size of the returned field name.
+.le
+.ls foffset
+The returned field offset. Foffset is the field or column number if the
+results are in simple text format, or the one-indexed field offset in chars
+if the results are in blocked text format.
+.le
+.ls fsize
+The returned field size. Fsize is zero if the results are in simple text format,
+the field width in characters if the results are in blocked file format.
+.le
+.ls ftype
+The returned field data type. The options are TY_DOUBLE, TY_REAL, TY_LONG,
+TY_INT, TY_SHORT, and TY_CHAR.
+.le
+.ls funits
+The returned field units.
+.le
+.ls max_funits
+The maximum size of the returned field units.
+.le
+.ls format
+The returned field format.
+.le
+.ls max_format
+The maximum size of the returned field format.
+.le
+.ih
+DESCRIPTION
+Cq_finfo returns the name, offset, size, data type, units, and format of
+the requested field. Cq_finfo is an integer function which returns
+the field number of the requested field as its function value.
+
+.ih
+NOTES
+
+Related routines of interest are:
+
+.nf
+fieldno = cq_fnumber (res, fname)
+foffset = cq_foffset (res, fname)
+ fsize = cq_fsize (res, fname)
+ ftype = cq_ftype (res, fname)
+ call cq_funits (res, fname, units, max_units)
+ call cq_ffmts (res, fname, format, max_format)
+.fi
+.ih
+SEE ALSO
+cqfinfon
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqfinfon.hlp b/pkg/xtools/catquery/doc/cqfinfon.hlp
new file mode 100644
index 00000000..62f07dfd
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqfinfon.hlp
@@ -0,0 +1,79 @@
+.help cqfinfon Mar00 "Catquery Package"
+.ih
+NAME
+cqfinfon -- get the catalog results field description by number
+.ih
+SYNOPSIS
+
+fieldno = cq_finfon (res, fieldno, fname, max_fname, foffset, fsize, ftype,
+ funits, max_funits, format, max_format)
+
+.nf
+pointer res # the results descriptor
+int fieldno # the sequence number of the field to be returned
+char fname # the returned field name
+int max_fname # the maximum size of the returned field name
+int foffset # the field offset
+int fsize # the field size
+int ftype # the field data type
+char funits # the field units
+int max_funits # the maximum size of the returned field units
+char format # the field format
+int max_format # the maximum size of the returned field format
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls fieldno
+The sequence number of the field for which information is to be returned.
+.le
+.ls fname
+The returned field name.
+.le
+.ls max_fname
+The maximum size of the returned field name.
+.le
+.ls foffset
+The field offset. Foffset is the field or column number if the
+results are in simple text format, or the one-indexed field offset in chars
+if the results are in blocked text format.
+.le
+.ls fsize
+The field size. Fsize is zero if the results are in simple text file format,
+the field width in characters if results are in blocked file format.
+.le
+.ls ftype
+The field data type. The options are TY_DOUBLE, TY_REAL, TY_LONG, TY_INT,
+TY_SHORT, and TY_CHAR.
+.le
+.ls units
+The returned field units string.
+.le
+.ls max_units
+The maximum size of the returned field units string.
+.le
+.ls format
+The returned field format string.
+.le
+.ls max_format
+The maximum size of the returned field format string.
+.le
+.ih
+DESCRIPTION
+Cq_finfon returns the name, offset, size, data type, units, and format of
+the requested field. Cq_finfon is an integer function which returns
+the field number of the requested field as its function value.
+
+.ih
+NOTES
+Related routines of interest are:
+
+.nf
+call cq_fname (res, fieldno, name, max_name)
+.fi
+.ih
+SEE ALSO
+cqfinfo
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqfquery.hlp b/pkg/xtools/catquery/doc/cqfquery.hlp
new file mode 100644
index 00000000..32f2d5b0
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqfquery.hlp
@@ -0,0 +1,78 @@
+.help cqfquery Mar00 "Catquery Package"
+.ih
+NAME
+cqfquery -- query a catalog file and return the results
+.ih
+SYNOPSIS
+
+res = cq_fquery (cq, catfile, hdrtxt)
+
+.nf
+pointer cq # the configuration file descriptor
+char catfile # the catalog file name
+char hdrtext # the catalog file header text
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls catfile
+The catalog file name.
+.le
+.ls hdrtext
+Text describing the format of the catalog file.
+.le
+.ih
+DESCRIPTION
+Cq_fquery is a pointer function which returns the results descriptor as its
+function value. NULL is returned if an error occurs in the catalog file query.
+
+Cq_fquery is used to make a catalog file emulate the results of
+a catalog query. The calling program must supply the catalog format
+description. A sample catalog file and catalog description are shown below.
+.ih
+NOTES
+Cq_setcat with the catalog name set to the reserved record name "filename@noao"
+must be called before any catalog file query is made.
+
+A sample catalog file is shown below.
+
+.nf
+ 00:00:01.443 -0:06:57.52 13.5 15.2
+ 00:00:01.574 -0:05:33.26 16.1 18.0
+ 00:00:01.904 -0:09:48.51 18.2 19.6
+ 00:00:02.529 -0:04:21.53 13.4 14.4
+ 00:00:04.154 -0:01:56.32 17.1 18.3
+ 00:00:04.438 -0:05:00.03 11.4 13.5
+ 00:00:04.697 -0:03:24.59 16.9 17.7
+ 00:00:05.989 -0:02:46.36 15.1 17.6
+ 00:00:07.118 -0:09:03.53 19.1 19.8
+ 00:00:07.260 -0:06:47.95 17.0 17.7
+ 00:00:07.314 -0:00:22.35 15.3 16.8
+.fi
+
+The accompanying catalog file header is shown below.
+
+.nf
+type stext
+nheader 1
+ csystem J2000
+nfields 4
+ ra 1 0 d hours %12.3h
+ dec 2 0 d degrees %12.2h
+ mag1 3 0 r INDEF %4.1f
+ mag2 4 0 r INDEF %4.1f
+.fi
+
+The catalog header specifies the type of file, "stext" for simple text in
+this example, the number of header parameters, the number of fields in each
+record, and the individual field descriptions.
+
+More information about the catalog header shown here can be found by typing
+"help catalogs".
+
+.ih
+SEE ALSO
+cqquery, cqrclose
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqget.hlp b/pkg/xtools/catquery/doc/cqget.hlp
new file mode 100644
index 00000000..0229cdc1
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqget.hlp
@@ -0,0 +1,130 @@
+.help cqget Mar00 "Catquery Package"
+.ih
+NAME
+cqget -- read configuration file keywords directly
+.ih
+SYNOPSIS
+
+.nf
+ [ird]val = cq_fget[ird](cq, fname)
+ nelems = cq_fga[ird](cq, fname, [ird]array, max_nelems)
+ call cq_fgwrd (cq, fname, wrd, maxch)
+ call cq_fgstr (cq, fname, str, maxch)
+ nlines = cq_fgtext (cq, fname, text, maxch)
+ stat = cq_scan (cq)
+
+pointer cq # the configuration file descriptor
+char fname # the field or keyword to be located
+int iarray # the returned integer array
+int rarray # the returned real array
+int darray # the returned double array
+int max_nelems # the maximum size of the returned array
+char wrd # the keyword word value to be read
+char str # the keyword string value to be read
+char text # the keyword text value to be read
+int maxch # the maximum size of the word, string, text value
+.fi
+.ih
+SYNOPSIS
+.ls cq
+The configuration file descriptor.
+.le
+.ls fname
+The name of the field or keyword to be read.
+.le
+.ls [ird]array
+The integer, real, or double array returned by a call to cq_fga[ird].
+.le
+.ls max_nelems
+The maximum number of elements in the array returned by a call to
+cq_fga[ird].
+.le
+.ls wrd, str, text
+The word, string, or text value returned by a call to cq_fgwrd, cq_fgstr, or
+cq_fgtext.
+.le
+.ls maxch
+The maximum number of characters in the word, string, or text returned
+by cq_fgwrd, cq_fgstr, cq_fgtext.
+.le
+.ih
+DESCRIPTION
+
+Cq_fgval[ird] is an integer, real, or double function which returns the
+integer, real, or double value of the requested field or keyword as its
+function value.
+
+Cq_fga[ird] returns an integer, real, or double array for the requested
+field. Cq_fga[ird] is an integer function which returns the number of elements
+in the retrieved array as its function value.
+
+Cq_fg[wrd/str/text] returns the next word, the entire string, or the
+number of lines in the requested keyword. Cq_fgtext is an integer function
+which returns the number of lines in the returned text as its functions
+value.
+
+.ih
+NOTES
+The cqget routines are used to read keywords or fields in the current catalog
+or survey directly. The routines cq_setcat or cq_setcatn must be called before
+the cqget routines can be used.
+
+The cqget routines must be error checked to avoid task termination.
+.ih
+EXAMPLES
+
+Sample catalog configuration file record.
+
+.nf
+begin usno2@noao
+address inet:80:www.noao.edu:text
+query GET /cgi-bin/usno/usnoextract?search=yes&ra=%-s&dec=%-s&width=%-s HTTP/1.0
+\n\n
+nquery 4
+ ra 00:00:00.00 hours %0.2h
+ dec 00:00:00.0 degrees %0.1h
+ radius 5.0 minutes %0.1f
+ qsystem J2000.0 INDEF %s
+type stext
+ hskip 10
+ tskip 6
+ recsize 44
+ triml 0
+ trimr 4
+nheader 1
+ csystem J2000.0
+nfields 4
+ ra 1 0 d hours %12.3h
+ dec 2 0 d degrees %12.2h
+ mag1 3 0 r INDEF %4.1f
+ mag2 4 0 r INDEF %4.1f
+.fi
+
+Example 1: To fetch the query field which includes embedded blanks use cq_fgstr.
+
+.nf
+call cq_fgstr (cq, "query", buffer, SZ_LINE)
+.fi
+
+Example 2: To fetch the type field use cq_fgwrd.
+
+.nf
+call cq_fgwrd (cq, "type", buffer, SZ_LINE)
+.fi
+
+Example 3: To determine the number of query parameters.
+
+.nf
+nquery = cq_fgeti (cq, "nquery")
+.fi
+
+Example4: To return a text array which follows a numerically valued parameter.
+
+.nf
+nquery = cq_fgeti (cq, "nquery")
+nlines = cq_fgtext (cq, "nquery", buffer, nquery * SZ_LINE)
+.fi
+
+.ih
+SEE ALSO
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgnrecord.hlp b/pkg/xtools/catquery/doc/cqgnrecord.hlp
new file mode 100644
index 00000000..6fd9ab53
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgnrecord.hlp
@@ -0,0 +1,61 @@
+.help cqgnrecord Mar00 "Catquery Package"
+.ih
+NAME
+cqgnrecord -- get the next record from the catalog results
+.ih
+SYNOPSIS
+
+stat = cq_gnrecord (res, buf, maxch, nextrec)
+
+.nf
+pointer res # the results descriptor
+char buf # the output record buffer
+int maxch # the maximum size of the output record buffer
+int recno # the next available record number
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls buf
+The buffer containing the returned record.
+.le
+.ls maxch
+The maximum size of the output buffer.
+.le
+.ls recptr
+The next available record number. Recptr is updated after each call.
+.le
+.ih
+DESCRIPTION
+Cq_gnrecord returns the requested record. Cq_grecord is an integer function
+which returns BOF, the number of characters in the record, or EOF as
+its function value.
+
+.ih
+NOTES
+In most cases allocating a buffer size that is SZ_LINE chars long
+will be adequate to hold the output record. If the integer results parameter
+CQRECSIZE is defined, i.e. non-zero, then an output buffer CQRECSIZE chars
+long can be allocated.
+
+.ih
+EXAMPLES
+
+pointer cq_query()
+int cq_gnrecord()
+
+...
+
+res = cq_query (cq)
+recno = 0
+while (cq_gnrecord (res, record, SZ_LINE, recno) != EOF) {
+ call printf ("%s")
+ call pargstr (record)
+}
+call cq_rclose (res)
+.ih
+SEE ALSO
+cqgrecord
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgqpar.hlp b/pkg/xtools/catquery/doc/cqgqpar.hlp
new file mode 100644
index 00000000..72b14809
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgqpar.hlp
@@ -0,0 +1,72 @@
+.help cqgqpar Mar00 "Catquery Package"
+.ih
+NAME
+cqgqpar -- get a query parameter description by name
+.ih
+SYNOPSIS
+
+parno = cq_gqpar (cq, pname, qpname, max_qpname, qpvalue, max_qpvalue, qpunits,
+ max_qpunits, qpformat, max_qpformat)
+
+.nf
+pointer cq # the configuration file descriptor
+char pname # the name of the requested query parameter
+char qpname # the returned query parameter name
+int max_qpname # the maximum size of the returned parameter name
+char qpvalue # the returned query parameter value
+int max_qpvalue # the maximum size of the returned parameter value
+char qpunits # the returned query parameter units
+int max_qpunits # the maximum size of the returned parameter units
+char qpformat # the returned query parameter format
+int max_qpformat # the maximum size of the returned parameter format
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls pname
+The name of the requested query parameter.
+.le
+.ls qpname
+The returned query parameter name.
+.le
+.ls max_qpname
+The maximum size of the returned query parameter name.
+.le
+.ls qpvalue
+The returned query parameter value.
+.le
+.ls max_qpvalue
+The maximum size of the returned query parameter value.
+.le
+.ls qpunits
+The returned query parameter units.
+.le
+.ls max_qpunits
+The maximum size of the returned query parameter units.
+.le
+.ls qpformat
+The returned query parameter format.
+.le
+.ls max_qpformat
+The maximum size of the returned query parameter format.
+.le
+.ih
+DESCRIPTION
+Cq_gqpar returns the name, value, units, and format of the requested query
+parameter. Cq_gpar is an integer function which returns the sequence number
+of the query parameter as its function value. Zero is returned if the requested
+query parameter is not found.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before a query parameter
+request can be made.
+
+The defined constants CQ_SZ_QPNAME, CQ_SZ_QPVALUE, CQ_SZ_QPUNITS, and
+CQ_SZ_QPFMTS in the cq.h file can be used to assign values to the
+max_qpname, max_qpvalue, max_qpunits, and max_qpformat paramters.
+.ih
+SEE ALSO
+cqnqpars, cqgqparn, cqsqpar, cqsqparn
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgqparn.hlp b/pkg/xtools/catquery/doc/cqgqparn.hlp
new file mode 100644
index 00000000..10155fe7
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgqparn.hlp
@@ -0,0 +1,73 @@
+.help cqgqparn Mar00 "Catquery Package"
+.ih
+NAME
+cqgqparn -- get the query parameter description by sequence number
+.ih
+SYNOPSIS
+
+parno = cq_gqparn (cq, parno, qpname, max_qpname, qpvalue, max_qpvalue, qpunits,
+ max_qpunits, qpformat, max_qpformat)
+
+.nf
+pointer cq # the configuration file descriptor
+int parno # the query parameter sequence number
+char qpname # the returned query parameter name
+int max_qpname # the maximum size of the returned parameter name
+char qpvalue # the returned query parameter value
+int max_qpvalue # the maximum size of the returned parameter value
+char qpunits # the returned query parameter units
+int max_qpunits # the maximum size of the returned parameter units
+char qpformat # the returned query parameter format
+int max_qpformat # the maximum size of the returned parameter format
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls parno
+The query parameter sequence number.
+.le
+.ls qpname
+The returned query parameter name.
+.le
+.ls max_qpname
+The maximum size of the returned query parameter name.
+.le
+.ls qpvalue
+The returned query parameter value.
+.le
+.ls max_qpvalue
+The maximum size of the returned query parameter value.
+.le
+.ls qpunits
+The returned query parameter units.
+.le
+.ls max_qpunits
+The maximum size of the returned query parameter units.
+.le
+.ls qpformat
+The returned query parameter format.
+.le
+.ls max_qpformat
+The maximum size of the returned query parameter format.
+.le
+.ih
+DESCRIPTION
+Cq_gqparn returns the name, value, units, and format of the requested query
+parameter by number. Cq_gparn is an integer function which returns the
+sequence number of the query parameter as its function value. Zero is
+returned if the requested query parameter is not found.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before a query parameter
+request can be made.
+
+The defined constants CQ_SZ_QPNAME, CQ_SZ_QPVALUE, CQ_SZ_QPUNITS, and
+CQ_SZ_QPFMTS in the cq.h file can be used to assign values to the
+max_qpname, max_qpvalue, max_qpunits, and max_qpformat paramters.
+
+.ih
+SEE ALSO
+cqnqpars, cqgqpar, cqsqpar, cqsqparn
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgrecord.hlp b/pkg/xtools/catquery/doc/cqgrecord.hlp
new file mode 100644
index 00000000..732f43f5
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgrecord.hlp
@@ -0,0 +1,46 @@
+.help cqgrecord Mar00 "Catquery Package"
+.ih
+NAME
+cqgrecord -- get a record from the catalog results
+.ih
+SYNOPSIS
+
+stat = cq_grecord (res, buf, maxch, recno)
+
+.nf
+pointer res # the results descriptor
+char buf # the output buffer
+int maxch # the maximum size of the output buffer
+int recno # the record to be fetched
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls buf
+The buffer containing the returned record.
+.le
+.ls maxch
+The maximum size of the output buffer.
+.le
+.ls recptr
+The sequence number of the record to be fetched. Recptr should be set to
+to initialize sequential reading of all the catalog results.
+.le
+.ih
+DESCRIPTION
+Cq_grecord returns the requested record. Cq_grecord is an integer function
+which returns BOF, the number of characters in the record, or EOF as
+its function value.
+.ih
+NOTES
+In most cases allocating a buffer size that is SZ_LINE chars long
+will be adequate to hold the output record. If the integer results parameter
+CQRECSIZE is defined, i.e. non-zero, then an output buffer CQRECSIZE chars
+long can be allocated.
+
+.ih
+SEE ALSO
+cqgnrecord
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgvalc.hlp b/pkg/xtools/catquery/doc/cqgvalc.hlp
new file mode 100644
index 00000000..a6313556
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgvalc.hlp
@@ -0,0 +1,42 @@
+.help cqgvalc Mar00 "Catquery Package"
+.ih
+NAME
+cqgvalc -- get a catalog results field as a string value
+.ih
+SYNOPSIS
+nchars = cq_gvalc (res, recno, fname, str, maxch)
+
+.nf
+pointer res # the results descriptor
+int recno # the record number
+char fname # the field name
+char str # the returned string value
+int maxch # the maximum size of the returned string value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls recno
+The record number.
+.le
+.ls fname
+The field name.
+.le
+.ls str
+Array containing returned string value.
+.le
+.ls maxch
+The maximum size in characters of the returned string value.
+.le
+.ih
+DESCRIPTION
+Cq_gvalc returns the requested field value as a string. Cq_gvalc is an
+integer function which returns the number of decoded characters as its
+function value. Zero is returned if the field could not be decoded.
+
+.ih
+SEE ALSO
+cqgval[silrd]
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgvald.hlp b/pkg/xtools/catquery/doc/cqgvald.hlp
new file mode 100644
index 00000000..245371cb
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgvald.hlp
@@ -0,0 +1,40 @@
+.help cqgvald Mar00 "Catquery Package"
+.ih
+NAME
+cqgvald -- get a catalog results field as a double precision value
+.ih
+SYNOPSIS
+
+nchars = cq_gvald (res, recno, fname, dval)
+
+.nf
+pointer res # the results descriptor
+int recno # the record number
+char fname # the field name
+double dval # the returned field value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls recno
+The record number.
+.le
+.ls fname
+The field name.
+.le
+.ls dval
+The returned double precision value.
+.le
+.ih
+DESCRIPTION
+Cq_gvald returns the requested field as a double precision value.
+Cq_gvald is an integer function which returns the number of characters
+that were successfully decoded as its function value. Zero is returned
+if the requested field could not be decoded.
+
+.ih
+SEE ALSO
+cqgval[csilr]
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgvali.hlp b/pkg/xtools/catquery/doc/cqgvali.hlp
new file mode 100644
index 00000000..8d5d3606
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgvali.hlp
@@ -0,0 +1,40 @@
+.help cqgvali Mar00 "Catquery Package"
+.ih
+NAME
+cqgvali -- get a catalog results field as an integer
+.ih
+SYNOPSIS
+
+nchars = cq_gvali (res, recno, fname, ival)
+
+.nf
+pointer res # the results descriptor
+int recno # the record number
+char fname # the field name
+int ival # the returned field value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls recno
+The record number.
+.le
+.ls fname
+The field name.
+.le
+.ls ival
+The returned integer value.
+.le
+.ih
+DESCRIPTION
+Cq_gvali returns the requested field as an integer value.
+Cq_gvali is an integer function which returns the number of characters
+that were successfully decoded as its function value. Zero is returned
+if the requested field could not be decoded.
+
+.ih
+SEE ALSO
+cqgval[cslrd]
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgvall.hlp b/pkg/xtools/catquery/doc/cqgvall.hlp
new file mode 100644
index 00000000..0571850f
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgvall.hlp
@@ -0,0 +1,40 @@
+.help cqgvall Mar00 "Catquery Package"
+.ih
+NAME
+cqgvall -- get the catalog results field as a long integer value
+.ih
+SYNOPSIS
+
+nchars = cq_gvall (res, recno, fname, lval)
+
+.nf
+pointer res # the results descriptor
+int recno # the record number
+char fname # the field name
+long lval # the returned field value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls recno
+The record number.
+.le
+.ls fname
+The field name.
+.le
+.ls lval
+The returned long integer value.
+.le
+.ih
+DESCRIPTION
+Cq_gvall returns the requested field as a long integer value.
+Cq_gvall is an integer function which returns the number of characters
+that were successfully decoded as its function value. Zero is returned
+if the requested field could not be decoded.
+
+.ih
+SEE ALSO
+cqgval[csird]
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgvalr.hlp b/pkg/xtools/catquery/doc/cqgvalr.hlp
new file mode 100644
index 00000000..f7229841
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgvalr.hlp
@@ -0,0 +1,40 @@
+.help cqgvalr Mar00 "Catquery Package"
+.ih
+NAME
+cqgvalr -- get the catalog results field as a real value
+.ih
+SYNOPSIS
+
+nchars = cq_gvalr (res, recno, fname, rval)
+
+.nf
+pointer res # the results descriptor
+int recno # the record number
+char fname # the field name
+real rval # the returned field value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls recno
+The record number.
+.le
+.ls fname
+The field name.
+.le
+.ls rval
+The returned real value.
+.le
+.ih
+DESCRIPTION
+Cq_gvalr returns the requested field as a real value.
+Cq_gvalr is an integer function which returns the number of characters
+that were successfully decoded as its function value. Zero is returned
+if the requested field could not be decoded.
+
+.ih
+SEE ALSO
+cqgval[csild]
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqgvals.hlp b/pkg/xtools/catquery/doc/cqgvals.hlp
new file mode 100644
index 00000000..90f39544
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqgvals.hlp
@@ -0,0 +1,41 @@
+.help cqgvals Mar00 "Catquery Package"
+.ih
+NAME
+cqgvals -- get the catalog results field as a short integer
+.ih
+SYNOPSIS
+include <cq.h>
+
+nchars = cq_gvals (res, recno, fname, sval)
+
+.nf
+pointer res # the results descriptor
+int recno # the record number
+char fname # the field name
+short sval # the returned field value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls recno
+The record number.
+.le
+.ls fname
+The field name.
+.le
+.ls sval
+The returned short integer value.
+.le
+.ih
+DESCRIPTION
+Cq_gvals returns the requested field as a short integer value.
+Cq_gvals is an integer function which returns the number of characters
+that were successfully decoded as its function value. Zero is returned
+if the requested field could not be decoded.
+
+.ih
+SEE ALSO
+cqgval[cilrd]
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqhinfo.hlp b/pkg/xtools/catquery/doc/cqhinfo.hlp
new file mode 100644
index 00000000..62db280c
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqhinfo.hlp
@@ -0,0 +1,39 @@
+.help cqhinfo Mar00 "Catquery Package"
+.ih
+NAME
+cqhinfo -- get catalog results header parameter value by name
+.ih
+SYNOPSIS
+
+hparno = cq_hinfo (res, hname, hvalue, max_hvalue)
+
+.nf
+pointer res # the results descriptor
+char hname # the results header parameter name
+char hvalue # the returned header parameter value
+int max_hvalue # the maximum size of the header parameter value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls hname
+The name of the results header parameter for which the value is to be returned.
+.le
+.ls hvalue
+The returned results header parameter value.
+.le
+.ls max_hvalue
+The maximum size of the returned results header parameter value.
+.le
+.ih
+DESCRIPTION
+Cq_hinfo returns the value of the requested header parameter. Cq_hinfo is
+an integer function which returns the header parameter sequence number
+as its function value. Zero is returned if the header parameter
+cannot be found.
+.ih
+SEE ALSO
+cqhinfon
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqhinfon.hlp b/pkg/xtools/catquery/doc/cqhinfon.hlp
new file mode 100644
index 00000000..2654ce50
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqhinfon.hlp
@@ -0,0 +1,47 @@
+.help cqhinfon Mar00 "Catquery Package"
+.ih
+NAME
+cqhinfon -- get a catalog results header parameter value by number
+.ih
+SYNOPSIS
+
+hparno = cq_hinfon (res, hparno, hname, max_hname, hvalue, max_hvalue)
+
+.nf
+pointer res # the results descriptor
+int hparno # the results header parameter sequence number
+char hname # the returned results header parameter name
+int max_hname # the maximum size of the header parameter name
+char hvalue # the returned header parameter value
+int max_hvalue # the maximum size of the header parameter value
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls hparno
+The requested results header parameter sequence number.
+.le
+.ls hname
+The returned name of the results header parameter.
+.le
+.ls max_hname
+The maximum size of the results header parameter name.
+.le
+.ls hvalue
+The returned results header parameter value.
+.le
+.ls max_hvalue
+The maximum size of the results header parameter value.
+.le
+.ih
+DESCRIPTION
+Cq_hinfon returns the name and value of the requested results header
+parameter. Cq_hinfon is an integer function which returns the
+sequence number of the requested parameter as its function value.
+Zero is returned if the results header parameter is not found.
+.ih
+SEE ALSO
+cqhinfo
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqimclose.hlp b/pkg/xtools/catquery/doc/cqimclose.hlp
new file mode 100644
index 00000000..4c3d105b
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqimclose.hlp
@@ -0,0 +1,24 @@
+.help cqimclose Mar00 "Catquery Package"
+.ih
+NAME
+cqimclose -- free the survey results descriptor
+.ih
+SYNOPSIS
+
+call cq_imclose (imres)
+
+.nf
+pointer imres # the results descriptor
+.fi
+.ih
+ARGUMENTS
+.ls imres
+The survey results descriptor.
+.le
+.ih
+DESCRIPTION
+Cq_imclose frees the survey results descriptor.
+.ih
+SEE ALSO
+cqimquery, cqfimquery
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqimquery.hlp b/pkg/xtools/catquery/doc/cqimquery.hlp
new file mode 100644
index 00000000..12e71506
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqimquery.hlp
@@ -0,0 +1,44 @@
+.help cqimquery Mar00 "Catquery Package"
+.ih
+NAME
+cqimquery -- query the image survey and return the results
+.ih
+SYNOPSIS
+
+imres = cq_imquery (cq, imname)
+
+.nf
+pointer cq # the configuration file descriptor
+pointer imname # the name of the output image file
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls imname
+The name of the output image file. At the output image produced by an
+image survey query must be a single FITS image. The image name
+should include the suffix ".fits" in order to make the image
+visible to IRAF image i/o.
+.le
+.ih
+DESCRIPTION
+Cq_imquery queries the image survey, creates an output image file, and
+returns the survey results descriptor. Cq_imquery is a pointer function
+which returns the survey results descriptor as its function value.
+Null is returned if an error occurs in the survey query.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before any catalog or image
+survey query can be made.
+
+Cq_nqpars and either cq_gqpar or cq_gqparn must be called to determine
+the number of query parameters and get each query parameter description.
+
+Cq_sqpar or cq_sqparn must be called to replace the default query parameter
+values with the calling program values.
+.ih
+SEE ALSO
+cqfimquery, cqimclose
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqistati.hlp b/pkg/xtools/catquery/doc/cqistati.hlp
new file mode 100644
index 00000000..beeec2c9
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqistati.hlp
@@ -0,0 +1,49 @@
+.help cqistati Mar00 "Catquery Package"
+.ih
+NAME
+cqistati -- get an image survey results integer parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+ival = cq_istati (imres, parameter)
+
+.nf
+pointer imres # the survey results descriptor
+int parameter # the parameter to be returned
+.fi
+.ih
+ARGUMENTS
+.ls imres
+The survey results descriptor.
+.le
+.ls parameter
+The survey parameter to be returned. The currently supported survey
+parameters defined in cq.h are:
+.nf
+CQINQPARS # the number of query params used to produce results
+CQIMTYPE # the image results type, CQFITS
+CQIMRECSIZE # the image record size, 0 if undefined
+CQIMHSKIP # the number of leading bytes to skip, 0 if undefined
+CQIMHREAD # the number of leading dummy reads, 0 if undefined
+CQWCS # the image wcs status, CQ_WFITS or CQ_WDSS or CQ_WNONE
+CQNWCS # the number of wcs parameters, 0 if none defined
+CQNIMPARS # the number of image parameters, 0 if none defined
+.fi
+.le
+.ih
+DESCRIPTION
+Cq_istati returns the values of image survey results integer parameters.
+Cq_istati is an integer function which returns the value of the requested
+parameter as its function value.
+
+.ih
+NOTES
+More information about the image survey results parameters and their
+relationship to the parent image survey is available by typing
+"help surveys".
+
+.ih
+SEE ALSO
+cq_istats, cq_istatt
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqistats.hlp b/pkg/xtools/catquery/doc/cqistats.hlp
new file mode 100644
index 00000000..700717f0
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqistats.hlp
@@ -0,0 +1,56 @@
+.help cqistats Mar00 "Catquery Package"
+.ih
+NAME
+cqistats -- get an image survey results string parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+call cq_istats (imres, parameter, str, maxch)
+
+.nf
+pointer imres # the image survey results descriptor
+int parameter # the parameter to be returned
+char str # the returned string parameter value
+int maxch # the maximum size of the string parameter
+.fi
+.ih
+ARGUMENTS
+.ls res
+The image survey results descriptor.
+.le
+.ls parameter
+The image survey results parameter to be returned. The currently supported
+image survey parameters defined in cq.h are:
+
+.nf
+CQIMCATDB # the name of the parent configuration file
+CQIMCATNAME # the name of the parent image survey
+CQIMADDRESS # the network address used to produce the results
+CQIMQUERY # the query used to produce the results
+CQIMNAME # the output image name
+CQIQPNAMES # the results query parameter dictionary
+CQIQPVALUES # the results query parameter values dictionary
+CQIQPUNITS # the results query parameter units dictionary
+.fi
+.le
+.ls str
+Array containing returned string parameter value.
+.le
+.ls maxch
+The maximum size in characters of the returned string value.
+.le
+.ih
+DESCRIPTION
+Cq_istats returns the values of image survey results string parameters.
+
+.ih
+NOTES
+More information about the image survey results parameters and their
+relationship to the parent image survey is available by typing
+"help surveys".
+
+.ih
+SEE ALSO
+cq_istati, cq_istatt
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqistatt.hlp b/pkg/xtools/catquery/doc/cqistatt.hlp
new file mode 100644
index 00000000..0af9fb4a
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqistatt.hlp
@@ -0,0 +1,55 @@
+.help cqistatt Mar00 "Catquery Package"
+.ih
+NAME
+cqistatt -- get an image survey results text parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+nlines = cq_istatt (imres, parameter, text, maxch)
+
+.nf
+pointer imres # the survey results descriptor
+int parameter # the parameter to be returned
+char text # the returned text parameter value
+int maxch # the maximum size of the returned text parameter
+.fi
+.ih
+ARGUMENTS
+.ls imres
+The results descriptor.
+.le
+.ls parameter
+The image survey parameter to be returned. The currently supported text
+image survey results text parameters defined in cq.h are:
+.nf
+CQIQPNAMES # the list of survey results query parameter names
+CQIQPVALUES # the list of survey results query parameter values
+CQIQPUNITS # the list of survey results query parameter units
+.fi
+.le
+.ls text
+String containing returned text parameter value. Text parameters differ
+from string parameters only in that they contain embedded newline
+characters.
+.le
+.ls maxch
+The maximum size in characters of the returned text value.
+.le
+.ih
+DESCRIPTION
+Cq_istatt returns the values of catalog results string parameters.
+
+The buffer size for the returned text parameters can be estimated by getting
+the value of the integer parameter CQRNQPARS, and multiplying it by the maximum
+buffer sizes CQ_SZ_QPNAME, CQ_SZ_QPVALUE, CQ_SZ_QPUNITS respectively.
+
+.ih
+NOTES
+More information about the survey results parameters and their relationship
+to the parent image survey is available by typing "help surveys".
+
+.ih
+SEE ALSO
+cq_istati, cq_istats
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqkinfo.hlp b/pkg/xtools/catquery/doc/cqkinfo.hlp
new file mode 100644
index 00000000..30d869a8
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqkinfo.hlp
@@ -0,0 +1,65 @@
+.help cqkinfo Mar00 "Catquery Package"
+.ih
+NAME
+cqkinfo -- get the results standard image parameter description by name
+.ih
+SYNOPSIS
+
+ipno = cq_kinfo (imres, pname, pkname, max_pkname, pkvalue, max_pkvalue,
+ pktype, pkunits, max_pkunits)
+
+.nf
+pointer imres # the survey results descriptor
+char pname # the image parameter name
+char pkname # the default image keyword name (INDEF if undefined)
+int max_pkname # the maximum size of the keyword name
+char pkvalue # the default parameter value (INDEF if undefined)
+int max_pkvalue # the maximum size of the parameter value
+int pktype # the parameter data type
+char pkunits # the parameter units (INDEF if undefined)
+int max_wpunits # the maximum size of the parameter units
+.fi
+.ih
+ARGUMENTS
+.ls imres
+The image results descriptor.
+.le
+.ls pname
+The name of the image parameter for which the description is to be returned.
+.le
+.ls pkname
+The returned image parameter keyword name. Pkname is "INDEF" if undefined.
+.le
+.ls max_pkname
+The maximum size of the returned image parameter keyword name.
+.le
+.ls pkvalue
+The returned image parameter value. Pkvalue is "INDEF" if undefined.
+.le
+.ls max_pkvalue
+The maximum size of the returned image parameter value.
+.le
+.ls pktype
+The image parameter data type. The options are TY_DOUBLE, TY_REAL, TY_LONG,
+TY_INT, TY_SHORT, and TY_CHAR.
+.le
+.ls pkunits
+The returned image parameter units. Pkunits is "INDEF" if undefined.
+.le
+.ls max_pkunits
+The maximum size of the returned image parameter units.
+.le
+.ih
+DESCRIPTION
+Cq_kinfo returns the keyword name, default value, data type, and units
+of the requested standard image parameter. Cq_kinfo is an integer function
+which returns the sequence number of the standard image parameter as its
+function value. Zero is returned if the standard image parameter is not found.
+.ih
+NOTES
+For more information about the standard image parameters and their relationship
+to the image surveys configuration file type "help surveys".
+.ih
+SEE ALSO
+cqkinfon
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqkinfon.hlp b/pkg/xtools/catquery/doc/cqkinfon.hlp
new file mode 100644
index 00000000..e57f0d47
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqkinfon.hlp
@@ -0,0 +1,73 @@
+.help cqkinfon Mar00 "Catquery Package"
+.ih
+NAME
+cqkinfon -- get the results standard image parameter description by number
+.ih
+SYNOPSIS
+
+ipno = cq_kinfo (imres, ipno, pname, max_pname, pkname, max_pkname, pkvalue,
+ max_pkvalue, pktype, pkunits, max_pkunits)
+
+.nf
+pointer imres # the survey results descriptor
+int ipno # the image parameter sequence number
+char pname # the image parameter name
+int max_pname # the maximum size of the parameter name
+char pkname # the default image keyword name (INDEF if undefined)
+int max_pkname # the maximum size of the keyword name
+char pkvalue # the default parameter value (INDEF if undefined)
+int max_pkvalue # the maximum size of the parameter value
+int pktype # the parameter data type
+char pkunits # the parameter units (INDEF if undefined)
+int max_wpunits # the maximum size of the parameter units
+.fi
+.ih
+ARGUMENTS
+.ls imres
+The image results descriptor.
+.le
+.ls ipno
+The sequence number of the requested parameter.
+.le
+.ls pname
+The returned image parameter name.
+.le
+.ls max_pname
+The maximum size of the returned parameter name.
+.le
+.ls pkname
+The returned image parameter keyword name. Pkname is "INDEF" if undefined.
+.le
+.ls max_pkname
+The maximum size of the returned image parameter keyword name.
+.le
+.ls pkvalue
+The returned image parameter value. Pkvalue is "INDEF" if undefined.
+.le
+.ls max_pkvalue
+The maximum size of the returned image parameter value.
+.le
+.ls pktype
+The image parameter data type. The options are TY_DOUBLE, TY_REAL, TY_LONG,
+TY_INT, TY_SHORT, and TY_CHAR.
+.le
+.ls pkunits
+The returned image parameter units. Pkunits is "INDEF" if undefined.
+.le
+.ls max_pkunits
+The maximum size of the returned image parameter units.
+.le
+.ih
+DESCRIPTION
+Cq_kinfon returns the keyword name, default value, data type, and units
+of the requested standard image parameter. Cq_kinfon is an integer function
+which returns the sequence number of the standard image parameter as its
+function value. Zero is returned if the standard image parameter is not found.
+.ih
+NOTES
+For more information about the standard image parameters and their relationship
+to the image surveys configuration file type "help surveys".
+.ih
+SEE ALSO
+cqkinfo
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqlocate.hlp b/pkg/xtools/catquery/doc/cqlocate.hlp
new file mode 100644
index 00000000..12f7cbc0
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqlocate.hlp
@@ -0,0 +1,35 @@
+.help cqlocate Mar00 "Catquery Package"
+.ih
+NAME
+cqlocate -- locate a catalog / survey record by name
+.ih
+SYNOPSIS
+
+catno = cq_locate (cq, catname)
+
+.nf
+pointer cq # the configuration file descriptor
+char catname # the name of the catalog / survey record to be located
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls catname
+The name of the catalog / survey record to be located.
+.le
+.ih
+DESCRIPTION
+Cq_locate locates a catalog / survey record in the configuration file by
+name. Cq_locate is an integer function which returns the catalog / survey
+record sequence number as its function value. Zero is returned if the catalog
+record is not located.
+.ih
+Cq_locate is used to determine whether the requested record exists. It does
+not set the current catalog / survey. This must be done with a call to
+cq_setcat or cq_setcatn.
+.ih
+SEE ALSO
+cqlocaten, cqsetcat, cqsetcatn
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqlocaten.hlp b/pkg/xtools/catquery/doc/cqlocaten.hlp
new file mode 100644
index 00000000..ca7011b0
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqlocaten.hlp
@@ -0,0 +1,47 @@
+.help cqlocaten Mar00 "Catquery Package"
+.ih
+NAME
+cqlocaten -- locate a catalog / survey record by number
+.ih
+SYNOPSIS
+
+catno = cq_locaten (cq, catno, catname, maxch)
+
+.nf
+pointer cq # the configuration file descriptor
+int catno # the number of the catalog / survey to be located
+char catname # the name of the located catalog
+int maxch # the maximum size of the name of the located catalog
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls catno
+The sequence number of the catalog / survey record to be located.
+.le
+.ls catname
+The name of the located catalog.
+.le
+.ls maxch
+The maximum size of the name of the located catalog.
+.le
+.ih
+DESCRIPTION
+Cq_locaten locates a catalog / survey record in the configuration file by
+sequence number. Cq_locaten is an integer function which returns the catalog
+/ survey record sequence number as its function value. Zero is returned
+if the catalog record is not located. Cq_locaten also returns the name of the
+located catalog in the array catname.
+
+.ih
+NOTES
+Cq_locaten is used to determine whether the requested record exists. It does
+not set the current catalog / survey. This must be done with a call to
+cq_setcat or cq_setcatn.
+
+.ih
+SEE ALSO
+cqlocate, cqsetcat, cqsetcatn
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqmap.hlp b/pkg/xtools/catquery/doc/cqmap.hlp
new file mode 100644
index 00000000..1c87530d
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqmap.hlp
@@ -0,0 +1,33 @@
+.help cqmap Mar00 "Catquery Package"
+.ih
+NAME
+cq_map -- map the catalog / survey configuration file
+.ih
+SYNOPSIS
+cq = cq_map (file, mode)
+
+.nf
+char file # the catalog / survey configuration file
+int mode # the file access mode
+.fi
+.ih
+ARGUMENTS
+.ls file
+The name of the catalog / survey configuration file.
+.le
+.ls mode
+The configuration file access mode. At present only READ_ONLY is supported.
+.le
+.ih
+DESCRIPTION
+Cq_map maps the record structure of the catalog / survey configuration file.
+Cq_map is a pointer function which returns the configuration file descriptor
+to the calling program.
+.ih
+NOTES
+Cq_map returns a NULL configuration file descriptor if an error occurs in
+the mapping process.
+.ih
+SEE ALSO
+cqunmap
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqnqpars.hlp b/pkg/xtools/catquery/doc/cqnqpars.hlp
new file mode 100644
index 00000000..63ac4ca8
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqnqpars.hlp
@@ -0,0 +1,32 @@
+.help cqnqpars Mar00 "Catquery Package"
+.ih
+NAME
+cqnqpars -- Get the number of query parameters
+.ih
+SYNOPSIS
+
+nqpars = cq_nqpars (cq)
+
+.nf
+pointer cq # the configuration file descriptor
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ih
+DESCRIPTION
+Cq_nqpars returns the number of expected catalog / survey query parameters.
+Cq_nqpars is an integer function which returns the number of expected
+catalog / survey parameters as its function value. The number of query
+parameters may be zero if the query is non-programmable. Not all query
+parameters are programmable.
+.ih
+NOTES
+The routines cq_setcat or cq_setcatn must be called before the number of
+query parameters can be requested.
+.ih
+SEE ALSO
+cqgqpar, cqgqparn, cqsqpar, cqsqparn
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqquery.hlp b/pkg/xtools/catquery/doc/cqquery.hlp
new file mode 100644
index 00000000..797cd72c
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqquery.hlp
@@ -0,0 +1,35 @@
+.help cqquery Mar00 "Catquery Package"
+.ih
+NAME
+cqquery -- query a catalog and return the results
+.ih
+SYNOPSIS
+
+res = cq_query (cq)
+
+.nf
+pointer cq # the configuration file descriptor
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ih
+DESCRIPTION
+Cq_query is a pointer function which returns the catalog results descriptor
+as its function value. NULL is returned if an error occurs in the catalog
+query.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before any catalog query can be made.
+
+Cq_nqpars and either cq_gqpar or cq_gqparn must be called to determine the
+number of query parameters and get each query parameter description.
+
+Cq_sqpar or cq_sqparn must be called to replace the default query parameter
+values with the calling program values.
+.ih
+SEE ALSO
+cqfquery, cqrclose
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqrclose.hlp b/pkg/xtools/catquery/doc/cqrclose.hlp
new file mode 100644
index 00000000..98dfb4b5
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqrclose.hlp
@@ -0,0 +1,24 @@
+.help cqrclose Mar00 "Catquery Package"
+.ih
+NAME
+cqrclose -- free the catalog results descriptor
+.ih
+SYNOPSIS
+
+call cq_rclose (res)
+
+.nf
+pointer res # the results descriptor
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ih
+DESCRIPTION
+Cq_rclose frees the results descriptor.
+.ih
+SEE ALSO
+cqquery, cqfquery
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqrstati.hlp b/pkg/xtools/catquery/doc/cqrstati.hlp
new file mode 100644
index 00000000..943a5218
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqrstati.hlp
@@ -0,0 +1,53 @@
+.help cqrstati Mar00 "Catquery Package"
+.ih
+NAME
+cqrstati -- get a catalog results integer parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+ival = cq_rstati (res, parameter)
+
+.nf
+pointer res # the results descriptor
+int parameter # the parameter to be returned
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls parameter
+The catalog results parameter to be returned. The currently supported
+catalog results parameters defined in cq.h are:
+.nf
+CQRNQPARS # the number of query params used to produce results
+CQRTYPE # the data type of the results, CQSTEXT or CQBTEXT
+CQRNRECS # the number of records in the results
+CQRECSIZE # the record size, 0 if undefined
+CQRHSKIP # the number of header records to skip, 0 if undefined
+CQRTSKIP # the number of trailer records to skip, 0 if undefined
+CQRTRIML # the number of leading chars to skip, 0 if undefined
+CQRTRIMR # the number of trailing chars to skip, 0 if undefined
+CQNHEADER # the number of header keyword value pairs, 0 if none defined
+CQNFIELDS # the number of fields in a record
+CQRECPTR # the current record number, BOF or number or EOF
+.fi
+.le
+.ih
+DESCRIPTION
+
+Cq_rstati returns the values of catalog results integer parameters.
+Cq_rstati is an integer function which returns the value of the requested
+parameter as its function value.
+
+.ih
+NOTES
+
+More information about the catalog results parameters and their relationship
+to the parent catalog is available by typing "help catalogs".
+
+.ih
+SEE ALSO
+cqrstats, cqrstatt
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqrstats.hlp b/pkg/xtools/catquery/doc/cqrstats.hlp
new file mode 100644
index 00000000..45487dfd
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqrstats.hlp
@@ -0,0 +1,54 @@
+.help cqrstats Mar00 "Catquery Package"
+.ih
+NAME
+cqsrtats -- get a catalog results string parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+call cq_rstats (res, parameter, str, maxch)
+
+.nf
+pointer res # the results descriptor
+int parameter # the parameter to be returned
+char str # the returned string parameter
+int maxch # the maximum size of the returned string parameter
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls parameter
+The catalog results parameter to be returned. The currently supported
+catalog results parameters defined in cq.h are:
+
+.nf
+CQRCATDB # the name of the parent configuration file
+CQRCATNAME # the name of the parent catalog
+CQRADDRESS # the network address used to produce the results
+CQRQUERY # the network query used to produce the results
+CQRQPNAMES # the results query parameter dictionary
+CQRQPVALUES # the results query parameter values dictionary
+CQRQPUNITS # the results query parameter units dictionary
+.fi
+.le
+.ls str
+Array containing returned string parameter value.
+.le
+.ls maxch
+The maximum size in characters of the returned string parameter value.
+.le
+.ih
+DESCRIPTION
+Cq_rstats returns the values of catalog results string parameters.
+
+.ih
+NOTES
+More information about the catalog results parameters and their relationship
+to the parent catalog is available by typing "help catalogs".
+
+.ih
+SEE ALSO
+cqrstati, cqrstatt
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqrstatt.hlp b/pkg/xtools/catquery/doc/cqrstatt.hlp
new file mode 100644
index 00000000..cbb13c44
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqrstatt.hlp
@@ -0,0 +1,56 @@
+.help cqrstatt Mar00 "Catquery Package"
+.ih
+NAME
+cqrstatt -- get a catalog results text parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+nlines = cq_rstatt (res, parameter, text, maxch)
+
+.nf
+pointer res # the results descriptor
+int parameter # the parameter to be returned
+char text # the returned text parameter value
+int maxch # the maximum size of the returned text parameter
+.fi
+.ih
+ARGUMENTS
+.ls res
+The results descriptor.
+.le
+.ls parameter
+The catalog results parameter to be returned. The currently supported
+catalog results text parameters defined in cq.h are:
+
+.nf
+CQRQPNAMES # the list of catalog results query parameter names
+CQRQPVALUES # the list of catalog results query parameter values
+CQRQPUNITS # the list of catalog results query parameter units
+.fi
+.le
+.ls text
+String containing returned text parameter value. Text parameters differ
+from string parameters only in that they contain embedded newline
+characters.
+.le
+.ls maxch
+The maximum size in characters of the returned text value.
+.le
+.ih
+DESCRIPTION
+Cq_rstatt returns the values of catalog results string parameters.
+
+The buffer size for the returned text parameters can be estimated by getting
+the value of the integer parameter CQRNQPARS, and multiplying it by the maximum
+ buffer sizes CQ_SZ_QPNAME, CQ_SZ_QPVALUE, CQ_SZ_QPUNITS respectively.
+
+.ih
+NOTES
+More information about the catalog results parameters and their relationship
+to the parent catalog is available by typing "help catalogs".
+
+.ih
+SEE ALSO
+cq_rstati, cq_rstats
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqsetcat.hlp b/pkg/xtools/catquery/doc/cqsetcat.hlp
new file mode 100644
index 00000000..1a6a4f62
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqsetcat.hlp
@@ -0,0 +1,35 @@
+.help cqsetcat Mar00 "Catquery Package"
+.ih
+NAME
+cqsetcat -- set the current catalog / survey by name
+.ih
+SYNOPSIS
+
+catno = cq_setcat (cq, catname)
+
+.nf
+pointer cq # the configuration file descriptor
+char catname # the name of the catalog to be set
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls catname
+The name of the catalog / survey to be set.
+.le
+.ih
+DESCRIPTION
+Cq_setcat sets the current catalog. Cq_setcat is an integer function
+which returns the sequence number of the requested catalog / survey as
+its function value. Zero is returned if the requested catalog / survey
+cannot be set.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before any catalog or survey query can
+be made.
+.ih
+SEE ALSO
+cqlocate, cqlocaten, cqsetcatn
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqsetcatn.hlp b/pkg/xtools/catquery/doc/cqsetcatn.hlp
new file mode 100644
index 00000000..dac93a00
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqsetcatn.hlp
@@ -0,0 +1,35 @@
+.help cqsetcatn Mar00 "Catquery Package"
+.ih
+NAME
+cqsetcatn -- set the current catalog / survey by number
+.ih
+SYNOPSIS
+
+catno = cq_setcatn (cq, catno)
+
+.nf
+pointer cq # the configuration file descriptor
+int catno # the sequence number of the catalog / survey to be set
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls catno
+The sequence number of the catalog / survey to be set.
+.le
+.ih
+DESCRIPTION
+Cq_setcatn sets the current catalog / survey by number. Cq_setcatn is an
+integer function which returns the catalog / survey
+record sequence number as its function value. Zero is returned if the catalog
+record is not set.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before any catalog or image
+survey query can be made.
+.ih
+SEE ALSO
+cqlocate, cqlocaten, cqsetcat
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqsqpar.hlp b/pkg/xtools/catquery/doc/cqsqpar.hlp
new file mode 100644
index 00000000..57a86255
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqsqpar.hlp
@@ -0,0 +1,39 @@
+.help cqsqpar Mar00 "Catquery Package"
+.ih
+NAME
+cqsqpar -- set the value of a query parameter by name
+.ih
+SYNOPSIS
+
+parno = cq_sqpar (cq, pname, value)
+
+.nf
+pointer cq # the configuration file descriptor
+char pname # the query parameter name
+char value # the query parameter value
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls pname
+The name of the query parameter to be set.
+.le
+.ls value
+The new query parameter value.
+.le
+.ih
+DESCRIPTION
+Cq_sqpar sets the value of the named query parameter. Qq_sqpar is an integer
+function which returns the sequence number of the requested parameter
+as its function value. Zero is returned if the requested query parameter
+is not found.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before a query parameter value
+can be changed.
+.ih
+SEE ALSO
+cqnqpars, cqgpar, cqgqparn, cqsqparn
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqsqparn.hlp b/pkg/xtools/catquery/doc/cqsqparn.hlp
new file mode 100644
index 00000000..f0cc92fc
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqsqparn.hlp
@@ -0,0 +1,39 @@
+.help cqsqparn Mar00 "Catquery Package"
+.ih
+NAME
+cqsqparn -- set the value of a query parameter by number
+.ih
+SYNOPSIS
+
+parno = cq_sqparn (cq, parno, value)
+
+.nf
+pointer cq # the configuration file descriptor
+int parno # the sequence number of the query parameter
+char value # the query parameter value
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls parno
+The sequence number of the query parameter to be set.
+.le
+.ls value
+The new query parameter value.
+.le
+.ih
+DESCRIPTION
+Cq_sqpar sets the value of the named query parameter. Qq_sqpar is an integer
+function which returns the sequence number of the requested parameter
+as its function value. Zero is returned if the requested query parameter
+is not found.
+.ih
+NOTES
+Cq_setcat or cq_setcatn must be called before a query parameter value
+can be changed.
+.ih
+SEE ALSO
+cqnqpars, cqgqpar, cqgparn, cqsqpar
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqstati.hlp b/pkg/xtools/catquery/doc/cqstati.hlp
new file mode 100644
index 00000000..15fe1d9e
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqstati.hlp
@@ -0,0 +1,61 @@
+.help cqstati Mar00 "Catquery Package"
+.ih
+NAME
+cqstati -- get a catalog / survey integer parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+ival = cq_stati (cq, parameter)
+
+.nf
+pointer cq # the configuration file descriptor
+int parameter # the parameter to be returned
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration file descriptor.
+.le
+.ls parameter
+The parameter to be returned. The currently supported parameters defined
+in cq.h are:
+.nf
+ CQNRECS # the number of catalog / survey file records
+ CQSZRECLIST # the length of the record name list in chars
+ CQCATNO # the current catalog number
+.fi
+.le
+.ih
+DESCRIPTION
+Cq_stati returns the values of catalog / survey integer parameters.
+Cq_stati is an integer function which returns the value of the requested
+parameter as its function value.
+
+.ih
+NOTES
+The current catalog number CQCATNO is 0 if the current catalog has not been set
+by a call to cq_setcat or cq_setcatn.
+
+The length of the record list CQSZRECLIST can be used to preallocate the buffer
+required to fetch the text parameter CQRECLIST.
+
+.ih
+EXAMPLES
+.nf
+ include <cq.h>
+
+ int cq_stati()
+
+ ....
+
+ sz_buf = cq_stati (cq, CQSZRECLIST)
+ call malloc (buf, sz_buf, TY_CHAR)
+ nlines = cq_statt (cq, CQRECLIST, Memc[buf], sz_buf)
+
+ ...
+.fi
+.ih
+SEE ALSO
+cq_stats, cq_statt
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqstats.hlp b/pkg/xtools/catquery/doc/cqstats.hlp
new file mode 100644
index 00000000..1aabc590
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqstats.hlp
@@ -0,0 +1,48 @@
+.help cqstats Mar00 "Catquery Package"
+.ih
+NAME
+cqstats -- get a catalog / survey string parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+call cq_stats (cq, parameter, str, maxch)
+
+.nf
+pointer cq # the configuration file descriptor
+int parameter # the parameter to be returned
+char str # the returned string parameter value
+int maxch # the maximum size of the returned string parameter
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The catalog / survey configuration file descriptor.
+.le
+.ls parameter
+The parameter to be returned. The string parameters defined
+in cq.h are:
+.nf
+ CQCATDB # the name of the configuration file
+ CQCATNAME # the name of the current catalog
+.fi
+.le
+.ls str
+Array containing returned string parameter.
+.le
+.ls maxch
+The maximum size of the returned string parameter.
+.le
+.ih
+DESCRIPTION
+Cq_stats returns the requested catalog / survey string parameters.
+
+.ih
+NOTES
+The current catalog name CQCATNAME is "" if the current catalog has not been
+set by a call to cq_setcat or cq_setcatn.
+
+.ih
+SEE ALSO
+cq_stati, cq_statt
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqstatt.hlp b/pkg/xtools/catquery/doc/cqstatt.hlp
new file mode 100644
index 00000000..082f5757
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqstatt.hlp
@@ -0,0 +1,45 @@
+.help cqstatt Mar00 "Catquery Package"
+.ih
+NAME
+cqstatt -- get a catalog / survey text parameter
+.ih
+SYNOPSIS
+include <cq.h>
+
+nlines = cq_statt (cq, parameter, text, maxch)
+
+.nf
+pointer cq # the configuration file descriptor
+int parameter # the parameter to be returned
+char text # the returned text parameter value
+int maxch # the maximum size of the returned text parameter
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The configuration catalog / survey file descriptor.
+.le
+.ls parameter
+The parameter to be returned. The text parameters defined in cq.h are:
+.nf
+define CQRECLIST # the catalog configuration file record list
+.fi
+.le
+.ls text
+The returned text parameter value. Text parameters differ
+from string parameters only in that they may contain embedded newline
+characters.
+.le
+.ls maxch
+The maximum size in characters of the returned text.
+.le
+.ih
+DESCRIPTION
+Cq_statt returns the requested catalog / survey text parameters.
+Cq_statt is an integer function which returns the numbers of lines in the
+requested parameter value as its function value.
+
+.ih
+SEE ALSO
+cq_stati, cq_stats
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqunmap.hlp b/pkg/xtools/catquery/doc/cqunmap.hlp
new file mode 100644
index 00000000..e33128cf
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqunmap.hlp
@@ -0,0 +1,26 @@
+.help cqunmap Mar00 "Catquery Package"
+.ih
+NAME
+cq_unmap -- unmap the catalog / survey configuration file
+.ih
+SYNOPSIS
+call cq_unmap (cq)
+
+.nf
+pointer cq # the configuration file descriptor
+.fi
+.ih
+ARGUMENTS
+.ls cq
+The catalog / survey configuration file descriptor.
+.le
+.ih
+DESCRIPTION
+Unmap the configuration file.
+.ih
+NOTES
+Cq_unmap should be called when catalog / survey access is terminated.
+.ih
+SEE ALSO
+cqmap
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqwinfo.hlp b/pkg/xtools/catquery/doc/cqwinfo.hlp
new file mode 100644
index 00000000..9bdc7edf
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqwinfo.hlp
@@ -0,0 +1,65 @@
+.help cqwinfo Mar00 "Catquery Package"
+.ih
+NAME
+cqwinfo -- get the results wcs parameter description by name
+.ih
+SYNOPSIS
+
+wcsno = cq_winfo (imres, wname, wkname, max_wkname, wkvalue, max_wkvalue,
+ wktype, wkunits, max_wkunits)
+
+.nf
+pointer imres # the survey results descriptor
+char wname # the wcs parameter name
+char wkname # the default wcs keyword name (INDEF if undefined)
+int max_wkname # the maximum size of the returned keyword name
+char wkvalue # the default wcs parameter value (INDEF if undefined)
+int max_wkvalue # the maximum size of the parameter value
+int wktype # the wcs parameter data type
+char wkunits # the wcs parameter units (INDEF if undefined)
+int max_wkunits # the maximum size of the returned wcs parameter units
+.fi
+.ih
+ARGUMENTS
+.ls imres
+The image results descriptor.
+.le
+.ls wname
+The name of the wcs parameter for which the description is to be returned.
+.le
+.ls wkname
+The returned wcs parameter keyword name. Wkname is "INDEF" if undefined.
+.le
+.ls max_wkname
+The maximum size of the returned wcs parameter keyword name.
+.le
+.ls wkvalue
+The returned wcs parameter value. Wkvalue is "INDEF" if undefined.
+.le
+.ls max_wkvalue
+The maximum size of the returned wcs parameter value.
+.le
+.ls wktype
+The wcs parameter data type. The options are TY_DOUBLE, TY_REAL, TY_LONG,
+TY_INT, TY_SHORT, and TY_CHAR.
+.le
+.ls wkunits
+The returned wcs parameter units. Wkunits is "INDEF" if undefined.
+.le
+.ls max_wkunits
+The maximum size of the returned wcs parameter units.
+.le
+.ih
+DESCRIPTION
+Cq_winfo returns the keyword name, default value, data type, and units
+of the requested wcs parameter. Cq_winfo is an integer function
+which returns the sequence number of the wcs parameter as its function
+value. Zero is returned if the wcs parameter is not found.
+.ih
+NOTES
+For more information about the wcs parameters and their relationship
+to the image surveys configuration file type "help surveys".
+.ih
+SEE ALSO
+cqwinfon
+.endhelp
diff --git a/pkg/xtools/catquery/doc/cqwinfon.hlp b/pkg/xtools/catquery/doc/cqwinfon.hlp
new file mode 100644
index 00000000..04fab301
--- /dev/null
+++ b/pkg/xtools/catquery/doc/cqwinfon.hlp
@@ -0,0 +1,75 @@
+.help cqwinfon Mar00 "Catquery Package"
+.ih
+NAME
+cqwinfon -- get the results wcs description by number
+.ih
+SYNOPSIS
+
+wcsno = cq_winfo (imres, wcsno, wname, max_wname, wkname, max_wkname, wkvalue,
+ max_wkvalue, wktype, wkunits, max_wkunits)
+
+.nf
+pointer imres # the image results descriptor
+int wcsno # the wcs parameter sequence number
+char wname # the wcs parameter name
+int max_wname # the maximum size of the wcs parameter name
+char wkname # the default wcs keyword name (INDEF if undefined)
+int max_wkname # the maximum size of the keyword name
+char wkvalue # the default wcs keyword value (INDEF if undefined)
+int max_wkvalue # the maximum size of the parameter value
+int wktype # the wcs parameter data type
+char wkunits # the wcs parameter units (INDEF if undefined)
+int max_wkunits # the maximum size of the wcs parameter units
+.fi
+.ih
+ARGUMENTS
+.ls imres
+The image results descriptor.
+.le
+.ls wcsno
+The sequence number of the wcs parameter to be returned.
+.le
+.ls wname
+The returned wcs parameter name.
+.le
+.ls max_wname
+The maximum size of the returned wcs parameter name.
+.le
+.ls wkname
+The returned wcs parameter keyword name.
+.le
+.ls max_wkname
+The maximum size of the returned wcs parameter keyword name.
+.le
+.ls wkvalue
+The returned wcs parameter value.
+.le
+.ls max_wkvalue
+The maximum size of the returned wcs parameter value.
+.le
+.ls wktype
+The returned wcs parameter type. The options are TY_DOUBLE, TY_REAL, TY_LONG,
+TY_INT, TY_SHORT, and TY_CHAR.
+.le
+.ls wkunits
+The returned wcs parameter units.
+.le
+.ls max_wkunits
+The maximum size of the returned wcs parameter units.
+.le
+.ih
+DESCRIPTION
+Cq_winfon returns the parameter name, keyword name, default value, data type,
+and units of the requested wcs parameter. Cq_winfon is an integer function
+which returns the sequence number of the wcs parameter as its function
+value. Zero is returned if the wcs parameter is not found.
+
+.ih
+NOTES
+For more information about the wcs parameters and their relationship
+to the image surveys configuration file type "help surveys".
+
+.ih
+SEE ALSO
+cqwinfo
+.endhelp
diff --git a/pkg/xtools/catquery/doc/surveys.hlp b/pkg/xtools/catquery/doc/surveys.hlp
new file mode 100644
index 00000000..bfc50e69
--- /dev/null
+++ b/pkg/xtools/catquery/doc/surveys.hlp
@@ -0,0 +1,197 @@
+.help surveys Mar00 catquery
+.ih
+NAME
+surveys -- describe the image survey configuration file
+.ih
+USAGE
+help surveys
+.ih
+IMAGE SURVEYS
+
+An image survey contains image data for a large region of the sky from which
+image data for small regions of the sky can be extracted.
+Image surveys may be installed locally or accessed remotely. Each
+supported survey must have a record in the image survey configuration file,
+which define the image survey network address, the image survey query format,
+and the image survey query output format.
+
+.ih
+THE IMAGE SURVEY CONFIGURATION FILE
+
+A record in the image survey configuration file specifies the network address,
+the query format, and the output image format for each supported image server.
+Each image server is accessed via a record name of the form
+"survey@server", e.g. "dss2@cadc". Adding support for a new image survey
+server or responding to changes in the behavior of an existing image survey
+server requires either adding a new record to the configuration file or
+changing an existing record. No modification to the survey access
+code should be required.
+
+The server network address tells the image survey access code where and how to
+connect to the network. Each network address has the syntax
+"domain:port:address:flags" e.g. "inet:80:www.noao.edu:text".
+
+The query format specifies the form of the query server string, and the
+names, default values, units, and format of the query parameters. A set of
+standard query parameter names are reserved for accessing image surveys
+including "ra", "dec", "radius", "width", "xwidth", and "ywidth".
+
+The server output format specifies the format of the expected server output:
+including the image type, the world coordinate system type, and the
+standard keyword set. At present the only supported image type is FITS,
+the only supported world coordinate system types are FITS and DSS,
+and the standard keyword set includes keyword that are required or
+useful for astrometric analysis tasks.
+
+.ih
+SAMPLE IMAGE SURVEY RECORD
+
+The following example illustrates the main features of a typical image survey
+configuration file record.
+
+.nf
+begin dss1@cadc
+address inet:80:cadcwww.hia.nrc.ca:binary
+query GET /cadcbin/dss-server?ra=%-s&dec=%-s&mime-type=application/x-fits&x=%-s
+&y=%-s HTTP/1.0\n\n
+nquery 5
+ ra 00:00:00.00 hours %0.2h
+ dec +00:00:00.0 degrees %0.1h
+ xwidth 10.0 minutes %0.1f
+ ywidth 10.0 minutes %0.1f
+ qsystem J2000.0 INDEF %s
+type fits
+wcs dss
+nwcs 10
+ wxref INDEF INDEF d pixels
+ wyref INDEF INDEF d pixels
+ wxmag INDEF 1.701 d arcsec/pixel
+ wymag INDEF 1.701 d arcsec/pixel
+ wxrot INDEF 180.0 d degrees
+ wyrot INDEF 0.0 d degrees
+ wraref OBJCTRA INDEF d hms
+ wdecref OBJCTDEC INDEF d dms
+ wproj INDEF tan c INDEF
+ wsystem INDEF J2000 c INDEF
+nkeys 13
+ observat INDEF Palomar c INDEF
+ esitelng INDEF +116:51:46.80 d degrees
+ esitelat INDEF +33:21:21.6 d degrees
+ esitealt INDEF 1706 r meters
+ esitetz INDEF 8 r INDEF
+ emjdobs INDEF INDEF d INDEF
+ edatamin INDEF INDEF r ADU
+ edatamax INDEF INDEF r ADU
+ gain INDEF INDEF r e-/ADU
+ erdnoise INDEF INDEF r e-
+ ewavlen INDEF INDEF r angstroms
+ etemp INDEF INDEF r degrees
+ epress INDEF INDEF r mbars
+.fi
+
+The beginning of a new image survey record is indicated by a line
+of the form \fI"begin surveyname"\fR where surveyname is a unique name of the
+form \fI"survey@server"\fR. Any number of unique names can access the same
+image survey. If more than one record with the same name exists in the
+configuration file the last record is the one read. Multiple entries for
+the same catalog can be used to define a different query format or different
+output type. For example if an image server supports more than one output
+formats then two records with two different queries can be defined,
+one which outputs one format, and another which outputs a different one.
+
+The \fIaddress\fR, \fIquery\fR and \fInquery\fR keywords are required, and
+define the network address, query command format and query parameters for
+the image survey.
+
+The \fIaddress\fR keyword "domain", "port", and "flags" fields are almost
+always "inet", "80", and "binary" respectively for image surveys, so
+the only field that has to be defined is the address field
+":cadcwww.hia.nrc.ca" in this case.
+
+The \fIquery\fR keyword defines the query command whose form is server
+dependent. The query parameter values are encoded via the %-s formatting
+strings. The calling program must encode the user query parameter values
+into a set a strings which then replace the -%s format statement in the
+query string.
+
+The number of query parameters is defined by the \fInquery\fR parameter. The
+number of query parameters must be greater than or equal to the number of "-%s"
+strings in the query keyword value. The name, default value, units,
+and format of each query parameter are listed below the nquery keyword
+one query parameter description per line. The query parameters should be
+defined in the configuration file in the same order that they appear
+in the query keyword value. Alert readers will notice that in the example above
+the number of query parameters is 5 but there are only 4 "%-s" strings
+in the query keyword value. In this example the qsystem query parameter which
+defined the coordinate system of the ra and dec query parameter values is
+fixed at J2000. For some servers this parameter may be a true query parameter,
+i.e. the server may accept coordinates in B1950 or J2000 or some other
+coordinate system.
+
+For "astrometric" image surveys the reserved query parameter names "ra", "dec",
+and "qsystem" should be used to define the extraction region center and its
+coordinate system, and one or more of "radius", "width", "xwidth", and
+"ywidth" should be used to define the extraction region size. The units
+of "ra" should be "hours", "degrees", or "radians", the units of dec
+should be "degrees" or "radians", and units of the size query parameter
+should be "degrees" or "minutes". The qsystem parameter value may be
+any one of the supported celestial coordinate systems. The most common
+qsystem values are "icrs", "J2000", or "B1950". The query parameter
+formats are used to convert numerical values supplied by the calling
+program to string values that can be passed to the query string.
+It should be emphasized that the reserved query parameter names and units
+are conventions that are adopted to simplify writing the configuration
+file and astrometric applications. They are not part of the image survey
+access API itself.
+
+The \fItype\fR keyword defines the format of the output image data. At
+present only FITS data is supported.
+
+The \fIwcs\fR keyword defines the wcs status of the image. The options
+are "fits" for an image which contains a valid FITS wcs, "dss" for an image
+which contains a valid DSS wcs, and "none" for an image contains no
+standard wcs information.
+
+The \fInwcs\fR keyword defines the number of following wcs parameters. Each
+wcs parameter definition consists of a standard keyword name, the actual
+keyword name or INDEF if no keyword exists, the default keyword value or
+INDEF is there is no default value, the data type which must be one of
+d(double), r(real), (i)integer, or c(character), and the units which may
+be INDEF if they are undefined.
+
+The reserved standard wcs keyword names \fIwxref\fR,
+\fIwyref\fR, \fIwxmag\fR, \fIwymag\fR, \fIwxref\fR, \fIwyref\fR, \fIwraref\fR,
+\fIwdecref\fR, \fIwproj\fR, and \fIwsystem\fR, should be used to define the
+pixel reference coordinates, the pixel scale in "/ pixel, the coordinate
+system rotation and skew in degrees, the reference coordinates in some celestial
+coordinate system, the image projection, and the celestial coordinate system.
+The units of wraref may be "hours", "degrees" or "radians" and the units
+of wdecref may be "hours" and "degrees". At present the units for the
+remaining wcs keywords should be regarded as fixed. It should be emphasized
+that the reserved standard wcs parameter names and units are conventions that
+are adopted to simplify writing the configuration file and astrometric image
+applications. They are not part of the image survey access API itself.
+
+The \fInkeys\fR keyword defines the number of following standard keyword
+parameters. Each parameter definition consists of a standard keyword name,
+the actual keyword name or INDEF is no keyword exists, the default value
+or INDEF is there is no default value, the data type which must be one of
+d(double), r(real), (i)integer, or c(character), and the parameter units
+which may be INDEF if they are undefined.
+
+The reserved standard keyword names \fIobservat\fR,
+\fIesitelng\fR, \fIesitelat\fR, \fIesitelat\fR, and \fIesitetz\fR should be
+used to define the site, \fIemjdobs\fR, \fIewavelen\fR, \fIetemp\fR,
+and \fIepress\fR to define the time and physical conditions of the observation,
+ and \fIedatamin\fR, \fIedatamax\fR, \fIegain\fR, and \fIerdnoise\fR
+to define the detector parameters. At present the units of all these
+parameters should be regarded as fixed.
+It should be emphasized that the reserved standard header parameter names and
+units are conventions that are adopted to simplify writing the configuration
+file and astrometric image applications. They are not part of the image survey
+access API itself.
+
+.ih
+SEE ALSO
+ccsystems, catalogs
+.endhelp
diff --git a/pkg/xtools/catquery/mkpkg b/pkg/xtools/catquery/mkpkg
new file mode 100644
index 00000000..91f0b557
--- /dev/null
+++ b/pkg/xtools/catquery/mkpkg
@@ -0,0 +1,32 @@
+# Catalog and survey access tools subdirectory
+
+$checkout libxtools.a lib$
+$update libxtools.a
+$checkin libxtools.a lib$
+$exit
+
+libxtools.a:
+ cqmap.x <ctype.h> "cqdef.h"
+ cqstat.x "cqdef.h" "cq.h"
+ cqlocate.x "cqdef.h"
+
+ cqsetcat.x "cqdef.h" "cq.h"
+ cqnqpars.x "cqdef.h"
+ cqgqpars.x "cqdef.h"
+ cqsqpars.x "cqdef.h" "cq.h"
+
+ cqquery.x <fset.h> "cqdef.h" "cq.h"
+ cqrstat.x "cqdef.h" "cq.h"
+ cqrinfo.x "cqdef.h" "cq.h"
+ cqgrecords.x "cqdef.h" "cq.h"
+ cqgfields.x <ctype.h> "cqdef.h" "cq.h"
+
+ cqimquery.x <fset.h> "cqdef.h" "cq.h"
+ cqistat.x "cqdef.h" "cq.h"
+ cqiminfo.x "cqdef.h" "cq.h"
+
+ cqget.x "cqdef.h" "cq.h"
+ cqdb.x <ctype.h> "cqdef.h" "cq.h"
+ cqwrdstr.x
+ cqdtype.x
+ ;