Index: /trunk/psLib/psLib.kdevses
===================================================================
--- /trunk/psLib/psLib.kdevses	(revision 3024)
+++ /trunk/psLib/psLib.kdevses	(revision 3025)
@@ -4,26 +4,26 @@
  <DocsAndViews NumberOfDocuments="8" >
   <Doc0 NumberOfViews="1" URL="file:/home/desonia/psLib/test/fileUtils/tst_psFits.c" >
-   <View0 line="22" Type="Source" />
+   <View0 Type="Source" />
   </Doc0>
   <Doc1 NumberOfViews="1" URL="file:/home/desonia/psLib/src/fileUtils/psFits.h" >
-   <View0 line="166" Type="Source" />
+   <View0 Type="Source" />
   </Doc1>
   <Doc2 NumberOfViews="1" URL="file:/home/desonia/psLib/src/fileUtils/psFits.c" >
-   <View0 line="257" Type="Source" />
+   <View0 Type="Source" />
   </Doc2>
   <Doc3 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImage.h" >
-   <View0 line="0" Type="Source" />
+   <View0 Type="Source" />
   </Doc3>
   <Doc4 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImageIO.c" >
-   <View0 line="20" Type="Source" />
+   <View0 Type="Source" />
   </Doc4>
   <Doc5 NumberOfViews="1" URL="file:/home/desonia/psLib/src/fileUtils/psFileUtilsErrors.dat" >
-   <View0 line="20" Type="Source" />
+   <View0 Type="Source" />
   </Doc5>
   <Doc6 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImageErrors.dat" >
-   <View0 line="57" Type="Source" />
+   <View0 Type="Source" />
   </Doc6>
   <Doc7 NumberOfViews="1" URL="file:/home/desonia/psLib/src/sysUtils/psLogMsg.h" >
-   <View0 line="0" Type="Source" />
+   <View0 line="36" Type="Source" />
   </Doc7>
  </DocsAndViews>
Index: /trunk/psLib/src/astronomy/psMetadata.c
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.c	(revision 3024)
+++ /trunk/psLib/src/astronomy/psMetadata.c	(revision 3025)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.48 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-13 23:27:06 $
+*  @version $Revision: 1.49 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:20 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -495,4 +495,5 @@
 psMetadataLookupNumTYPE(F64)
 psMetadataLookupNumTYPE(S32)
+psMetadataLookupNumTYPE(Bool)
 
 psMetadataItem* psMetadataGet(psMetadata *md, psS32 where)
Index: /trunk/psLib/src/astronomy/psMetadata.h
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.h	(revision 3024)
+++ /trunk/psLib/src/astronomy/psMetadata.h	(revision 3025)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-13 21:09:39 $
+*  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:20 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -240,4 +240,18 @@
 );
 
+/** Find an item in the metadata collection based on key name and return its boolean value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not found, zero is
+ *  returned.
+ *
+ * @return psBool : Value of metadata item.
+ */
+psBool psMetadataLookupBool(
+    psMetadata *md,            ///< Metadata collection to lookup metadata item.
+    const char *key,           ///< Name of metadata key.
+    psBool *status              ///< Status of lookup.
+);
+
 /** Find an item in the metadata collection based on key name and return its integer value.
  *
Index: /trunk/psLib/src/collections/psMetadata.c
===================================================================
--- /trunk/psLib/src/collections/psMetadata.c	(revision 3024)
+++ /trunk/psLib/src/collections/psMetadata.c	(revision 3025)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.48 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-13 23:27:06 $
+*  @version $Revision: 1.49 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:20 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -495,4 +495,5 @@
 psMetadataLookupNumTYPE(F64)
 psMetadataLookupNumTYPE(S32)
+psMetadataLookupNumTYPE(Bool)
 
 psMetadataItem* psMetadataGet(psMetadata *md, psS32 where)
Index: /trunk/psLib/src/collections/psMetadata.h
===================================================================
--- /trunk/psLib/src/collections/psMetadata.h	(revision 3024)
+++ /trunk/psLib/src/collections/psMetadata.h	(revision 3025)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-13 21:09:39 $
+*  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:20 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -240,4 +240,18 @@
 );
 
+/** Find an item in the metadata collection based on key name and return its boolean value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not found, zero is
+ *  returned.
+ *
+ * @return psBool : Value of metadata item.
+ */
+psBool psMetadataLookupBool(
+    psMetadata *md,            ///< Metadata collection to lookup metadata item.
+    const char *key,           ///< Name of metadata key.
+    psBool *status              ///< Status of lookup.
+);
+
 /** Find an item in the metadata collection based on key name and return its integer value.
  *
Index: /trunk/psLib/src/collections/psVector.h
===================================================================
--- /trunk/psLib/src/collections/psVector.h	(revision 3024)
+++ /trunk/psLib/src/collections/psVector.h	(revision 3025)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-10-27 00:57:31 $
+ *  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-17 20:58:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -37,4 +37,5 @@
 
     union {
+        psBool B;               ///< Boolean data.
         psU8* U8;               ///< Unsigned 8-bit integer data.
         psU16* U16;             ///< Unsigned 16-bit integer data.
@@ -63,5 +64,5 @@
 /** Allocate a vector.
  *
- *  Uses psLib memory allocation functions to create a vector collection of 
+ *  Uses psLib memory allocation functions to create a vector collection of
  *  data as defined by the psType type.
  *
@@ -75,6 +76,6 @@
 /** Reallocate a vector.
  *
- *  Uses psLib memory allocation functions to reallocate a vector collection 
- *  of data. The vector is reallocated according to the psType type member 
+ *  Uses psLib memory allocation functions to reallocate a vector collection
+ *  of data. The vector is reallocated according to the psType type member
  *  contained within the vector.
  *
@@ -89,6 +90,6 @@
 /** Recycle a vector.
  *
- *  Uses psLib memory allocation functions to reallocate a vector collection 
- *  of data. The vector is reallocated according to the psElemType type 
+ *  Uses psLib memory allocation functions to reallocate a vector collection
+ *  of data. The vector is reallocated according to the psElemType type
  *  parameter.
  *
@@ -107,5 +108,5 @@
 /** Copy a vector, converting types.
  *
- *  Performs a deep copy of the elements of one psVector to a new psVector, 
+ *  Performs a deep copy of the elements of one psVector to a new psVector,
  *  converting numeric types to a specified type.
  *
@@ -133,6 +134,6 @@
 /** Creates an array of indices based on sort ordered of array.
  *
- *  Sorts a vector and creates an integer array holding indices of 
- *  sorted float values based on pre-sort index positions.  
+ *  Sorts a vector and creates an integer array holding indices of
+ *  sorted float values based on pre-sort index positions.
  *
  *  @return  psVector*     vector of the indices of sort.
Index: /trunk/psLib/src/dataIO/psFileUtilsErrors.dat
===================================================================
--- /trunk/psLib/src/dataIO/psFileUtilsErrors.dat	(revision 3024)
+++ /trunk/psLib/src/dataIO/psFileUtilsErrors.dat	(revision 3025)
@@ -34,5 +34,5 @@
 psFits_NOT_IMAGE_TYPE                  Current FITS HDU type must be an image.
 psFits_NOT_TABLE_TYPE                  Current FITS HDU type must be a table.
-psFits_TABLE_FIRSTROW_NULL             Can't create a table without the first row, where table column information is derived.
+psFits_TABLE_EMPTY                     Can't create a table without any rows.
 psFits_CFITSIO_ERROR                   CFITSIO error: %s
 psFits_METATYPE_INVALID                Specified FITS metadata type, %c, is not supported.
Index: /trunk/psLib/src/dataIO/psFileUtilsErrors.h
===================================================================
--- /trunk/psLib/src/dataIO/psFileUtilsErrors.h	(revision 3024)
+++ /trunk/psLib/src/dataIO/psFileUtilsErrors.h	(revision 3025)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-01-13 01:54:25 $
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-17 20:58:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -56,5 +56,5 @@
 #define PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE "Current FITS HDU type must be an image."
 #define PS_ERRORTEXT_psFits_NOT_TABLE_TYPE "Current FITS HDU type must be a table."
-#define PS_ERRORTEXT_psFits_TABLE_FIRSTROW_NULL "Can't create a table without the first row, where table column information is derived."
+#define PS_ERRORTEXT_psFits_TABLE_EMPTY "Can't create a table without any rows."
 #define PS_ERRORTEXT_psFits_CFITSIO_ERROR "CFITSIO error: %s"
 #define PS_ERRORTEXT_psFits_METATYPE_INVALID "Specified FITS metadata type, %c, is not supported."
Index: /trunk/psLib/src/dataIO/psFits.c
===================================================================
--- /trunk/psLib/src/dataIO/psFits.c	(revision 3024)
+++ /trunk/psLib/src/dataIO/psFits.c	(revision 3025)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-01-14 19:40:33 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-17 20:58:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -165,14 +165,14 @@
     switch (type) {
     case PS_TYPE_BOOL:
-        *fitsType = "1L";
+        *fitsType = psStringCopy("1L");
         break;
     case PS_TYPE_S32:
-        *fitsType = "1J";
+        *fitsType = psStringCopy("1J");
         break;
     case PS_TYPE_F32:
-        *fitsType = "1E";
+        *fitsType = psStringCopy("1E");
         break;
     case PS_TYPE_F64:
-        *fitsType = "1D";
+        *fitsType = psStringCopy("1D");
         break;
         // XXX: Handle other types, e.g., Vectors, etc.
@@ -1028,5 +1028,5 @@
 
     // the row parameter in the proper range?
-    if (row < 1 || row > numRows) {
+    if (row < 0 || row >= numRows) {
         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
                 PS_ERRORTEXT_psFits_ROW_INVALID,
@@ -1056,7 +1056,7 @@
         if (status == 0) {
 
-            #define READ_TABLE_ROW_CASE(FITSTYPE, TYPE) \
+            #define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE) \
         case FITSTYPE: { \
-                ps##TYPE value; \
+                NATIVETYPE value; \
                 int anynul = 0; \
                 fits_read_col(fits->p_fd, FITSTYPE, col,row+1, \
@@ -1064,16 +1064,30 @@
                 if (anynul == 0) { \
                     psMetadataAdd(data,PS_LIST_TAIL, name, \
-                                  PS_TYPE_S32, PS_META_PRIMITIVE, \
-                                  "", value); \
+                                  PS_TYPE_##TYPE, PS_META_PRIMITIVE, \
+                                  "", (ps##TYPE)value); \
                 } \
-            } \
-            break;
+                break; \
+            }
 
             switch (typecode) {
             case TBYTE:
             case TSHORT:
-                READ_TABLE_ROW_CASE(TLONG, S32)
-                READ_TABLE_ROW_CASE(TFLOAT, F32)
-                READ_TABLE_ROW_CASE(TDOUBLE, F64)
+            case TLONGLONG:
+                READ_TABLE_ROW_CASE(TLONG, long, S32)
+                READ_TABLE_ROW_CASE(TFLOAT, float, F32)
+                READ_TABLE_ROW_CASE(TDOUBLE, double, F64)
+                READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL);
+            case TSTRING: {
+                    char* value;
+                    int anynul = 0;
+                    fits_read_col(fits->p_fd, TSTRING, col,row+1,
+                                  1, 1, NULL, &value, &anynul, &status);
+                    if (anynul == 0) {
+                        psMetadataAdd(data,PS_LIST_TAIL, name,
+                                      PS_TYPE_PTR, PS_META_STR,
+                                      "", value);
+                    }
+                    break;
+                }
             default:
                 psTrace("psFits.psFitsReadTableRow", 2,
@@ -1266,7 +1280,5 @@
     // get the size of the FITS table
     long numRows = 0;
-    int numCols = 0;
     fits_get_num_rows(fits->p_fd, &numRows, &status);
-    fits_get_num_cols(fits->p_fd, &numCols, &status);
     if ( status != 0) {
         char fitsErr[MAX_STRING_LENGTH];
@@ -1278,5 +1290,5 @@
     }
 
-    psArray* table = psArrayAlloc(numCols);
+    psArray* table = psArrayAlloc(numRows);
 
     for (int row = 0; row < numRows; row++) {
@@ -1293,4 +1305,5 @@
 {
     int status = 0;
+    psMetadataItem* item;
 
     if (fits == NULL) {
@@ -1307,11 +1320,16 @@
 
     int rows = table->n;
+    if (rows < 1) {
+        // no table data, what can I do?
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                PS_ERRORTEXT_psFits_TABLE_EMPTY);
+        return false;
+    }
 
     // find all the columns needed
-    psArray* columns = psArrayAlloc(16);
+    psArray* columns = psArrayAlloc(((psMetadata*)table->data[0])->list->size);
     columns->n=0;
 
     // find the unique items in the array of metadata 'rows'
-    psMetadataItem* item;
     for (int row=0; row < rows; row++) {
         psMetadata* rowMeta = table->data[row];
@@ -1329,5 +1347,5 @@
                     }
                     if (! found) {
-                        psArrayAdd(columns, columns->nalloc, item);
+                        psArrayAdd(columns, columns->nalloc, psMemIncrRefCounter(item));
                     }
                 }
@@ -1347,5 +1365,5 @@
     for (int n=0; n < columns->n; n++) {
         char* fitsType;
-        columnNames->data[n] = ((psMetadataItem*)columns->data[n])->name;
+        columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name);
         if ( ! convertPsTypeToBinaryTForm(((psMetadataItem*)columns->data[n])->pType,
                                           &fitsType)) {
@@ -1366,12 +1384,11 @@
                     &status);
 
+    psFree(columnNames);
+    psFree(columnTypes);
+
     // fill in the table elements with data
     for (int n = 0; n < columns->n; n++) {
         int row;
         item = columns->data[n];
-        psArray* columnItems = psArrayAlloc(table->n);
-        for (row = 0; row < table->n; row++) {
-            columnItems->data[row] = psMetadataLookup(table->data[row],item->name);
-        }
 
         if (item->type == PS_META_PRIMITIVE) {
@@ -1380,8 +1397,9 @@
             case PS_TYPE_S32:
                 for (row = 0; row < table->n; row++) {
-                    col->data.S32[row] = item->data.S32;
+                    col->data.S32[row] = psMetadataLookupS32(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_int(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1392,8 +1410,9 @@
             case PS_TYPE_F32:
                 for (row = 0; row < table->n; row++) {
-                    col->data.F32[row] = item->data.F32;
+                    col->data.F32[row] = psMetadataLookupF32(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_flt(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1402,10 +1421,11 @@
                                    &status);
                 break;
-            case PS_TYPE_S64:
+            case PS_TYPE_F64:
                 for (row = 0; row < table->n; row++) {
-                    col->data.F64[row] = item->data.F64;
+                    col->data.F64[row] = psMetadataLookupF64(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_dbl(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1414,14 +1434,22 @@
                                    &status);
                 break;
+            case PS_TYPE_BOOL:
+                for (row = 0; row < table->n; row++) {
+                    col->data.S8[row] = psMetadataLookupBool(
+                                            table->data[row],item->name,NULL);
+                }
+                fits_write_col_log(fits->p_fd,
+                                   n+1, // column number
+                                   1, // firstrow
+                                   1, // firstelem
+                                   table->n, // nelements
+                                   col->data.S8,
+                                   &status);
+                break;
             default:
                 // XXX: error message
-                psFree(col);
-                psFree(columnItems);
-                psFree(columnNames);
-                psFree(columnTypes);
-                psFree(columns);
-                return false;
+                break;
             }
-
+            psFree(col);
         } else if (item->type == PS_META_STR) {
             psArray* col = psArrayAlloc(table->n);
@@ -1436,6 +1464,9 @@
                                (char**)col->data,
                                &status);
-        }
-    }
+            psFree(col);
+        }
+    }
+
+    psFree(columns);
 
     return true;
Index: /trunk/psLib/src/fileUtils/psFileUtilsErrors.dat
===================================================================
--- /trunk/psLib/src/fileUtils/psFileUtilsErrors.dat	(revision 3024)
+++ /trunk/psLib/src/fileUtils/psFileUtilsErrors.dat	(revision 3025)
@@ -34,5 +34,5 @@
 psFits_NOT_IMAGE_TYPE                  Current FITS HDU type must be an image.
 psFits_NOT_TABLE_TYPE                  Current FITS HDU type must be a table.
-psFits_TABLE_FIRSTROW_NULL             Can't create a table without the first row, where table column information is derived.
+psFits_TABLE_EMPTY                     Can't create a table without any rows.
 psFits_CFITSIO_ERROR                   CFITSIO error: %s
 psFits_METATYPE_INVALID                Specified FITS metadata type, %c, is not supported.
Index: /trunk/psLib/src/fileUtils/psFileUtilsErrors.h
===================================================================
--- /trunk/psLib/src/fileUtils/psFileUtilsErrors.h	(revision 3024)
+++ /trunk/psLib/src/fileUtils/psFileUtilsErrors.h	(revision 3025)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-01-13 01:54:25 $
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-17 20:58:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -56,5 +56,5 @@
 #define PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE "Current FITS HDU type must be an image."
 #define PS_ERRORTEXT_psFits_NOT_TABLE_TYPE "Current FITS HDU type must be a table."
-#define PS_ERRORTEXT_psFits_TABLE_FIRSTROW_NULL "Can't create a table without the first row, where table column information is derived."
+#define PS_ERRORTEXT_psFits_TABLE_EMPTY "Can't create a table without any rows."
 #define PS_ERRORTEXT_psFits_CFITSIO_ERROR "CFITSIO error: %s"
 #define PS_ERRORTEXT_psFits_METATYPE_INVALID "Specified FITS metadata type, %c, is not supported."
Index: /trunk/psLib/src/fileUtils/psFits.c
===================================================================
--- /trunk/psLib/src/fileUtils/psFits.c	(revision 3024)
+++ /trunk/psLib/src/fileUtils/psFits.c	(revision 3025)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-01-14 19:40:33 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-17 20:58:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -165,14 +165,14 @@
     switch (type) {
     case PS_TYPE_BOOL:
-        *fitsType = "1L";
+        *fitsType = psStringCopy("1L");
         break;
     case PS_TYPE_S32:
-        *fitsType = "1J";
+        *fitsType = psStringCopy("1J");
         break;
     case PS_TYPE_F32:
-        *fitsType = "1E";
+        *fitsType = psStringCopy("1E");
         break;
     case PS_TYPE_F64:
-        *fitsType = "1D";
+        *fitsType = psStringCopy("1D");
         break;
         // XXX: Handle other types, e.g., Vectors, etc.
@@ -1028,5 +1028,5 @@
 
     // the row parameter in the proper range?
-    if (row < 1 || row > numRows) {
+    if (row < 0 || row >= numRows) {
         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
                 PS_ERRORTEXT_psFits_ROW_INVALID,
@@ -1056,7 +1056,7 @@
         if (status == 0) {
 
-            #define READ_TABLE_ROW_CASE(FITSTYPE, TYPE) \
+            #define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE) \
         case FITSTYPE: { \
-                ps##TYPE value; \
+                NATIVETYPE value; \
                 int anynul = 0; \
                 fits_read_col(fits->p_fd, FITSTYPE, col,row+1, \
@@ -1064,16 +1064,30 @@
                 if (anynul == 0) { \
                     psMetadataAdd(data,PS_LIST_TAIL, name, \
-                                  PS_TYPE_S32, PS_META_PRIMITIVE, \
-                                  "", value); \
+                                  PS_TYPE_##TYPE, PS_META_PRIMITIVE, \
+                                  "", (ps##TYPE)value); \
                 } \
-            } \
-            break;
+                break; \
+            }
 
             switch (typecode) {
             case TBYTE:
             case TSHORT:
-                READ_TABLE_ROW_CASE(TLONG, S32)
-                READ_TABLE_ROW_CASE(TFLOAT, F32)
-                READ_TABLE_ROW_CASE(TDOUBLE, F64)
+            case TLONGLONG:
+                READ_TABLE_ROW_CASE(TLONG, long, S32)
+                READ_TABLE_ROW_CASE(TFLOAT, float, F32)
+                READ_TABLE_ROW_CASE(TDOUBLE, double, F64)
+                READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL);
+            case TSTRING: {
+                    char* value;
+                    int anynul = 0;
+                    fits_read_col(fits->p_fd, TSTRING, col,row+1,
+                                  1, 1, NULL, &value, &anynul, &status);
+                    if (anynul == 0) {
+                        psMetadataAdd(data,PS_LIST_TAIL, name,
+                                      PS_TYPE_PTR, PS_META_STR,
+                                      "", value);
+                    }
+                    break;
+                }
             default:
                 psTrace("psFits.psFitsReadTableRow", 2,
@@ -1266,7 +1280,5 @@
     // get the size of the FITS table
     long numRows = 0;
-    int numCols = 0;
     fits_get_num_rows(fits->p_fd, &numRows, &status);
-    fits_get_num_cols(fits->p_fd, &numCols, &status);
     if ( status != 0) {
         char fitsErr[MAX_STRING_LENGTH];
@@ -1278,5 +1290,5 @@
     }
 
-    psArray* table = psArrayAlloc(numCols);
+    psArray* table = psArrayAlloc(numRows);
 
     for (int row = 0; row < numRows; row++) {
@@ -1293,4 +1305,5 @@
 {
     int status = 0;
+    psMetadataItem* item;
 
     if (fits == NULL) {
@@ -1307,11 +1320,16 @@
 
     int rows = table->n;
+    if (rows < 1) {
+        // no table data, what can I do?
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                PS_ERRORTEXT_psFits_TABLE_EMPTY);
+        return false;
+    }
 
     // find all the columns needed
-    psArray* columns = psArrayAlloc(16);
+    psArray* columns = psArrayAlloc(((psMetadata*)table->data[0])->list->size);
     columns->n=0;
 
     // find the unique items in the array of metadata 'rows'
-    psMetadataItem* item;
     for (int row=0; row < rows; row++) {
         psMetadata* rowMeta = table->data[row];
@@ -1329,5 +1347,5 @@
                     }
                     if (! found) {
-                        psArrayAdd(columns, columns->nalloc, item);
+                        psArrayAdd(columns, columns->nalloc, psMemIncrRefCounter(item));
                     }
                 }
@@ -1347,5 +1365,5 @@
     for (int n=0; n < columns->n; n++) {
         char* fitsType;
-        columnNames->data[n] = ((psMetadataItem*)columns->data[n])->name;
+        columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name);
         if ( ! convertPsTypeToBinaryTForm(((psMetadataItem*)columns->data[n])->pType,
                                           &fitsType)) {
@@ -1366,12 +1384,11 @@
                     &status);
 
+    psFree(columnNames);
+    psFree(columnTypes);
+
     // fill in the table elements with data
     for (int n = 0; n < columns->n; n++) {
         int row;
         item = columns->data[n];
-        psArray* columnItems = psArrayAlloc(table->n);
-        for (row = 0; row < table->n; row++) {
-            columnItems->data[row] = psMetadataLookup(table->data[row],item->name);
-        }
 
         if (item->type == PS_META_PRIMITIVE) {
@@ -1380,8 +1397,9 @@
             case PS_TYPE_S32:
                 for (row = 0; row < table->n; row++) {
-                    col->data.S32[row] = item->data.S32;
+                    col->data.S32[row] = psMetadataLookupS32(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_int(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1392,8 +1410,9 @@
             case PS_TYPE_F32:
                 for (row = 0; row < table->n; row++) {
-                    col->data.F32[row] = item->data.F32;
+                    col->data.F32[row] = psMetadataLookupF32(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_flt(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1402,10 +1421,11 @@
                                    &status);
                 break;
-            case PS_TYPE_S64:
+            case PS_TYPE_F64:
                 for (row = 0; row < table->n; row++) {
-                    col->data.F64[row] = item->data.F64;
+                    col->data.F64[row] = psMetadataLookupF64(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_dbl(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1414,14 +1434,22 @@
                                    &status);
                 break;
+            case PS_TYPE_BOOL:
+                for (row = 0; row < table->n; row++) {
+                    col->data.S8[row] = psMetadataLookupBool(
+                                            table->data[row],item->name,NULL);
+                }
+                fits_write_col_log(fits->p_fd,
+                                   n+1, // column number
+                                   1, // firstrow
+                                   1, // firstelem
+                                   table->n, // nelements
+                                   col->data.S8,
+                                   &status);
+                break;
             default:
                 // XXX: error message
-                psFree(col);
-                psFree(columnItems);
-                psFree(columnNames);
-                psFree(columnTypes);
-                psFree(columns);
-                return false;
+                break;
             }
-
+            psFree(col);
         } else if (item->type == PS_META_STR) {
             psArray* col = psArrayAlloc(table->n);
@@ -1436,6 +1464,9 @@
                                (char**)col->data,
                                &status);
-        }
-    }
+            psFree(col);
+        }
+    }
+
+    psFree(columns);
 
     return true;
Index: /trunk/psLib/src/fits/psFits.c
===================================================================
--- /trunk/psLib/src/fits/psFits.c	(revision 3024)
+++ /trunk/psLib/src/fits/psFits.c	(revision 3025)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-01-14 19:40:33 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-17 20:58:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -165,14 +165,14 @@
     switch (type) {
     case PS_TYPE_BOOL:
-        *fitsType = "1L";
+        *fitsType = psStringCopy("1L");
         break;
     case PS_TYPE_S32:
-        *fitsType = "1J";
+        *fitsType = psStringCopy("1J");
         break;
     case PS_TYPE_F32:
-        *fitsType = "1E";
+        *fitsType = psStringCopy("1E");
         break;
     case PS_TYPE_F64:
-        *fitsType = "1D";
+        *fitsType = psStringCopy("1D");
         break;
         // XXX: Handle other types, e.g., Vectors, etc.
@@ -1028,5 +1028,5 @@
 
     // the row parameter in the proper range?
-    if (row < 1 || row > numRows) {
+    if (row < 0 || row >= numRows) {
         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
                 PS_ERRORTEXT_psFits_ROW_INVALID,
@@ -1056,7 +1056,7 @@
         if (status == 0) {
 
-            #define READ_TABLE_ROW_CASE(FITSTYPE, TYPE) \
+            #define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE) \
         case FITSTYPE: { \
-                ps##TYPE value; \
+                NATIVETYPE value; \
                 int anynul = 0; \
                 fits_read_col(fits->p_fd, FITSTYPE, col,row+1, \
@@ -1064,16 +1064,30 @@
                 if (anynul == 0) { \
                     psMetadataAdd(data,PS_LIST_TAIL, name, \
-                                  PS_TYPE_S32, PS_META_PRIMITIVE, \
-                                  "", value); \
+                                  PS_TYPE_##TYPE, PS_META_PRIMITIVE, \
+                                  "", (ps##TYPE)value); \
                 } \
-            } \
-            break;
+                break; \
+            }
 
             switch (typecode) {
             case TBYTE:
             case TSHORT:
-                READ_TABLE_ROW_CASE(TLONG, S32)
-                READ_TABLE_ROW_CASE(TFLOAT, F32)
-                READ_TABLE_ROW_CASE(TDOUBLE, F64)
+            case TLONGLONG:
+                READ_TABLE_ROW_CASE(TLONG, long, S32)
+                READ_TABLE_ROW_CASE(TFLOAT, float, F32)
+                READ_TABLE_ROW_CASE(TDOUBLE, double, F64)
+                READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL);
+            case TSTRING: {
+                    char* value;
+                    int anynul = 0;
+                    fits_read_col(fits->p_fd, TSTRING, col,row+1,
+                                  1, 1, NULL, &value, &anynul, &status);
+                    if (anynul == 0) {
+                        psMetadataAdd(data,PS_LIST_TAIL, name,
+                                      PS_TYPE_PTR, PS_META_STR,
+                                      "", value);
+                    }
+                    break;
+                }
             default:
                 psTrace("psFits.psFitsReadTableRow", 2,
@@ -1266,7 +1280,5 @@
     // get the size of the FITS table
     long numRows = 0;
-    int numCols = 0;
     fits_get_num_rows(fits->p_fd, &numRows, &status);
-    fits_get_num_cols(fits->p_fd, &numCols, &status);
     if ( status != 0) {
         char fitsErr[MAX_STRING_LENGTH];
@@ -1278,5 +1290,5 @@
     }
 
-    psArray* table = psArrayAlloc(numCols);
+    psArray* table = psArrayAlloc(numRows);
 
     for (int row = 0; row < numRows; row++) {
@@ -1293,4 +1305,5 @@
 {
     int status = 0;
+    psMetadataItem* item;
 
     if (fits == NULL) {
@@ -1307,11 +1320,16 @@
 
     int rows = table->n;
+    if (rows < 1) {
+        // no table data, what can I do?
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                PS_ERRORTEXT_psFits_TABLE_EMPTY);
+        return false;
+    }
 
     // find all the columns needed
-    psArray* columns = psArrayAlloc(16);
+    psArray* columns = psArrayAlloc(((psMetadata*)table->data[0])->list->size);
     columns->n=0;
 
     // find the unique items in the array of metadata 'rows'
-    psMetadataItem* item;
     for (int row=0; row < rows; row++) {
         psMetadata* rowMeta = table->data[row];
@@ -1329,5 +1347,5 @@
                     }
                     if (! found) {
-                        psArrayAdd(columns, columns->nalloc, item);
+                        psArrayAdd(columns, columns->nalloc, psMemIncrRefCounter(item));
                     }
                 }
@@ -1347,5 +1365,5 @@
     for (int n=0; n < columns->n; n++) {
         char* fitsType;
-        columnNames->data[n] = ((psMetadataItem*)columns->data[n])->name;
+        columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name);
         if ( ! convertPsTypeToBinaryTForm(((psMetadataItem*)columns->data[n])->pType,
                                           &fitsType)) {
@@ -1366,12 +1384,11 @@
                     &status);
 
+    psFree(columnNames);
+    psFree(columnTypes);
+
     // fill in the table elements with data
     for (int n = 0; n < columns->n; n++) {
         int row;
         item = columns->data[n];
-        psArray* columnItems = psArrayAlloc(table->n);
-        for (row = 0; row < table->n; row++) {
-            columnItems->data[row] = psMetadataLookup(table->data[row],item->name);
-        }
 
         if (item->type == PS_META_PRIMITIVE) {
@@ -1380,8 +1397,9 @@
             case PS_TYPE_S32:
                 for (row = 0; row < table->n; row++) {
-                    col->data.S32[row] = item->data.S32;
+                    col->data.S32[row] = psMetadataLookupS32(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_int(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1392,8 +1410,9 @@
             case PS_TYPE_F32:
                 for (row = 0; row < table->n; row++) {
-                    col->data.F32[row] = item->data.F32;
+                    col->data.F32[row] = psMetadataLookupF32(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_flt(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1402,10 +1421,11 @@
                                    &status);
                 break;
-            case PS_TYPE_S64:
+            case PS_TYPE_F64:
                 for (row = 0; row < table->n; row++) {
-                    col->data.F64[row] = item->data.F64;
+                    col->data.F64[row] = psMetadataLookupF64(
+                                             table->data[row],item->name,NULL);
                 }
                 fits_write_col_dbl(fits->p_fd,
-                                   n, // column number
+                                   n+1, // column number
                                    1, // firstrow
                                    1, // firstelem
@@ -1414,14 +1434,22 @@
                                    &status);
                 break;
+            case PS_TYPE_BOOL:
+                for (row = 0; row < table->n; row++) {
+                    col->data.S8[row] = psMetadataLookupBool(
+                                            table->data[row],item->name,NULL);
+                }
+                fits_write_col_log(fits->p_fd,
+                                   n+1, // column number
+                                   1, // firstrow
+                                   1, // firstelem
+                                   table->n, // nelements
+                                   col->data.S8,
+                                   &status);
+                break;
             default:
                 // XXX: error message
-                psFree(col);
-                psFree(columnItems);
-                psFree(columnNames);
-                psFree(columnTypes);
-                psFree(columns);
-                return false;
+                break;
             }
-
+            psFree(col);
         } else if (item->type == PS_META_STR) {
             psArray* col = psArrayAlloc(table->n);
@@ -1436,6 +1464,9 @@
                                (char**)col->data,
                                &status);
-        }
-    }
+            psFree(col);
+        }
+    }
+
+    psFree(columns);
 
     return true;
Index: /trunk/psLib/src/mathtypes/psVector.h
===================================================================
--- /trunk/psLib/src/mathtypes/psVector.h	(revision 3024)
+++ /trunk/psLib/src/mathtypes/psVector.h	(revision 3025)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-10-27 00:57:31 $
+ *  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-17 20:58:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -37,4 +37,5 @@
 
     union {
+        psBool B;               ///< Boolean data.
         psU8* U8;               ///< Unsigned 8-bit integer data.
         psU16* U16;             ///< Unsigned 16-bit integer data.
@@ -63,5 +64,5 @@
 /** Allocate a vector.
  *
- *  Uses psLib memory allocation functions to create a vector collection of 
+ *  Uses psLib memory allocation functions to create a vector collection of
  *  data as defined by the psType type.
  *
@@ -75,6 +76,6 @@
 /** Reallocate a vector.
  *
- *  Uses psLib memory allocation functions to reallocate a vector collection 
- *  of data. The vector is reallocated according to the psType type member 
+ *  Uses psLib memory allocation functions to reallocate a vector collection
+ *  of data. The vector is reallocated according to the psType type member
  *  contained within the vector.
  *
@@ -89,6 +90,6 @@
 /** Recycle a vector.
  *
- *  Uses psLib memory allocation functions to reallocate a vector collection 
- *  of data. The vector is reallocated according to the psElemType type 
+ *  Uses psLib memory allocation functions to reallocate a vector collection
+ *  of data. The vector is reallocated according to the psElemType type
  *  parameter.
  *
@@ -107,5 +108,5 @@
 /** Copy a vector, converting types.
  *
- *  Performs a deep copy of the elements of one psVector to a new psVector, 
+ *  Performs a deep copy of the elements of one psVector to a new psVector,
  *  converting numeric types to a specified type.
  *
@@ -133,6 +134,6 @@
 /** Creates an array of indices based on sort ordered of array.
  *
- *  Sorts a vector and creates an integer array holding indices of 
- *  sorted float values based on pre-sort index positions.  
+ *  Sorts a vector and creates an integer array holding indices of
+ *  sorted float values based on pre-sort index positions.
  *
  *  @return  psVector*     vector of the indices of sort.
Index: /trunk/psLib/src/sys/psType.h
===================================================================
--- /trunk/psLib/src/sys/psType.h	(revision 3024)
+++ /trunk/psLib/src/sys/psType.h	(revision 3025)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-12-21 00:37:51 $
+*  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:21 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -78,5 +78,5 @@
 
 typedef psU8 psMaskType;               ///< the C datatype for a mask image
-
+typedef psBool psBOOL;                 ///< allow psBOOL to be used instead of psBool (for macros)
 
 #define PS_MIN_S8        INT8_MIN      /**< minimum valid psS8 value */
Index: /trunk/psLib/src/sysUtils/psType.h
===================================================================
--- /trunk/psLib/src/sysUtils/psType.h	(revision 3024)
+++ /trunk/psLib/src/sysUtils/psType.h	(revision 3025)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-12-21 00:37:51 $
+*  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:21 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -78,5 +78,5 @@
 
 typedef psU8 psMaskType;               ///< the C datatype for a mask image
-
+typedef psBool psBOOL;                 ///< allow psBOOL to be used instead of psBool (for macros)
 
 #define PS_MIN_S8        INT8_MIN      /**< minimum valid psS8 value */
Index: /trunk/psLib/src/types/psMetadata.c
===================================================================
--- /trunk/psLib/src/types/psMetadata.c	(revision 3024)
+++ /trunk/psLib/src/types/psMetadata.c	(revision 3025)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.48 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-13 23:27:06 $
+*  @version $Revision: 1.49 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:20 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -495,4 +495,5 @@
 psMetadataLookupNumTYPE(F64)
 psMetadataLookupNumTYPE(S32)
+psMetadataLookupNumTYPE(Bool)
 
 psMetadataItem* psMetadataGet(psMetadata *md, psS32 where)
Index: /trunk/psLib/src/types/psMetadata.h
===================================================================
--- /trunk/psLib/src/types/psMetadata.h	(revision 3024)
+++ /trunk/psLib/src/types/psMetadata.h	(revision 3025)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-13 21:09:39 $
+*  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:20 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -240,4 +240,18 @@
 );
 
+/** Find an item in the metadata collection based on key name and return its boolean value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not found, zero is
+ *  returned.
+ *
+ * @return psBool : Value of metadata item.
+ */
+psBool psMetadataLookupBool(
+    psMetadata *md,            ///< Metadata collection to lookup metadata item.
+    const char *key,           ///< Name of metadata key.
+    psBool *status              ///< Status of lookup.
+);
+
 /** Find an item in the metadata collection based on key name and return its integer value.
  *
Index: /trunk/psLib/test/dataIO/tst_psFits.c
===================================================================
--- /trunk/psLib/test/dataIO/tst_psFits.c	(revision 3024)
+++ /trunk/psLib/test/dataIO/tst_psFits.c	(revision 3025)
@@ -6,6 +6,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-14 19:21:55 $
+*  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:22 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -19,5 +19,8 @@
 
 static bool makeMulti(void);  // implicitly tests psFitsSetExtName
+static bool makeTable(void);
 const char* multiFilename = "multi.fits";
+const char* tableFilename = "table.fits";
+const int tableNumRows = 10;
 
 static psS32 tst_psFitsAlloc( void );
@@ -26,4 +29,5 @@
 static psS32 tst_psFitsReadHeader( void );
 static psS32 tst_psFitsReadHeaderSet( void );
+static psS32 tst_psFitsReadTable( void );
 
 testDescription tests[] = {
@@ -35,5 +39,6 @@
                               {tst_psFitsMoveExtNum, 803, "psFitsGetSize", 0, true},
                               {tst_psFitsReadHeader, 804, "psFitsReadHeader", 0, false},
-                              {tst_psFitsReadHeaderSet, 0, "psFitsReadHeaderSet", 0, false},
+                              {tst_psFitsReadHeaderSet,805, "psFitsReadHeaderSet", 0, false},
+                              {tst_psFitsReadTable,809, "psFitsReadTable", 0, false},
                               {NULL}
                           };
@@ -110,4 +115,62 @@
 }
 
+bool makeTable(void)
+{
+
+    if (access(tableFilename, F_OK) != 0) {
+        psFits* fitsFile = psFitsAlloc(tableFilename);
+
+        if (fitsFile == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not create 'table' FITS file.");
+            return false;
+        }
+
+        // make the PHU an image (per FITS standard, it must be)
+        psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+        if (! psFitsWriteImage(fitsFile,NULL,image,1) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not write PHU image.");
+            return false;
+        }
+
+        psFree(image);
+
+        // build a table structure
+        psArray* table = psArrayAlloc(tableNumRows);
+        table->n = 0;
+        for (int row = 0; row < tableNumRows; row++) {
+            psMetadata* header = psMetadataAlloc();
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                          PS_TYPE_S32, PS_META_PRIMITIVE,
+                          "psS32 Item", (psS32)row);
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                          PS_TYPE_F32, PS_META_PRIMITIVE,
+                          "psF32 Item", (float)(1.0f/(float)(1+row)));
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                          PS_TYPE_F64, PS_META_PRIMITIVE,
+                          "psF64 Item", (double)(1.0/(double)(1+row)));
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                          PS_TYPE_BOOL, PS_META_PRIMITIVE,
+                          "psBool Item",
+                          (row%2 == 0));
+
+            psArrayAdd(table,0,header);
+        }
+
+        psFitsWriteTable(fitsFile, NULL, table, "table-1");
+
+        psFree(table);
+        psFree(fitsFile);
+    }
+
+    return true;
+}
+
 psS32 tst_psFitsAlloc( void )
 {
@@ -176,4 +239,10 @@
     psFits* fits = psFitsAlloc(multiFilename);
 
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
     int numHDUs = psFitsGetSize(fits);
 
@@ -290,4 +359,10 @@
 
     psFits* fits = psFitsAlloc(multiFilename);
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
 
     int numHDUs = psFitsGetSize(fits);
@@ -489,4 +564,10 @@
     psFits* fits = psFitsAlloc(multiFilename);
 
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
     int numHDUs = psFitsGetSize(fits);
 
@@ -594,4 +675,10 @@
     psFits* fits = psFitsAlloc(multiFilename);
 
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
     int numHDUs = psFitsGetSize(fits);
 
@@ -701,2 +788,87 @@
     return 0;
 }
+
+static psS32 tst_psFitsReadTable( void )
+{
+
+
+    if (! makeTable() ) {
+        return 1;
+    }
+
+    psFits* fits = psFitsAlloc(tableFilename);
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
+    psFitsMoveExtNum(fits,1,false);
+
+    psArray* table = psFitsReadTable(fits);
+
+    if (table == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTable returned NULL unexpectedly.");
+        return 2;
+    }
+
+    if (table->n != tableNumRows) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Expected %d rows, but read %d.",
+                tableNumRows, table->n);
+        return 3;
+    }
+
+
+    for (int row = 0; row < table->n; row++) {
+        psMetadata* rowData = table->data[row];
+
+        psS32 intItem = psMetadataLookupS32(rowData, "MYINT",NULL);
+        psF32 fltItem = psMetadataLookupF32(rowData, "MYFLT",NULL);
+        psF64 dblItem = psMetadataLookupF64(rowData, "MYDBL",NULL);
+        psBool boolItem = psMetadataLookupBool(rowData, "MYBOOL",NULL);
+
+        if (intItem != row) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psS32 metadata item from file.  Got %d vs %d",
+                    intItem, row);
+            return 20;
+        }
+
+        if (fabsf(fltItem - 1.0f/(float)(1+row)) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF32 metadata item from file.  Got %f vs %f",
+                    fltItem,1.0f/(float)(1+row));
+            return 21;
+        }
+
+        if (abs(dblItem - 1.0/(double)(1+row)) > DBL_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF64 metadata item from file.  Got %g vs %g",
+                    dblItem, 1.0/(double)(1+row));
+            return 22;
+        }
+
+        if (boolItem != (row%2 == 0)) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psBool metadata item from file.");
+            return 23;
+        }
+
+    }
+
+    psFree(table);
+    psFree(fits);
+
+    psArray* nullTest = psFitsReadTable(NULL);
+
+    if (nullTest != NULL || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psFitsReadTable returned non-NULL when given NULL.");
+        return 30;
+    }
+
+    return 0;
+}
Index: /trunk/psLib/test/dataIO/verified/tst_psFits.stderr
===================================================================
--- /trunk/psLib/test/dataIO/verified/tst_psFits.stderr	(revision 3024)
+++ /trunk/psLib/test/dataIO/verified/tst_psFits.stderr	(revision 3025)
@@ -91,2 +91,13 @@
 ---> TESTPOINT PASSED (psImage{psFitsReadHeaderSet} | tst_psFits.c)
 
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFits.c                                               *
+*            TestPoint: psImage{psFitsReadTable}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|E|psFitsReadTable (psFits.c:<LINENO>)
+    The input psFits object can not NULL.
+
+---> TESTPOINT PASSED (psImage{psFitsReadTable} | tst_psFits.c)
+
Index: /trunk/psLib/test/fileUtils/tst_psFits.c
===================================================================
--- /trunk/psLib/test/fileUtils/tst_psFits.c	(revision 3024)
+++ /trunk/psLib/test/fileUtils/tst_psFits.c	(revision 3025)
@@ -6,6 +6,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-01-14 19:21:55 $
+*  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-01-17 20:58:22 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -19,5 +19,8 @@
 
 static bool makeMulti(void);  // implicitly tests psFitsSetExtName
+static bool makeTable(void);
 const char* multiFilename = "multi.fits";
+const char* tableFilename = "table.fits";
+const int tableNumRows = 10;
 
 static psS32 tst_psFitsAlloc( void );
@@ -26,4 +29,5 @@
 static psS32 tst_psFitsReadHeader( void );
 static psS32 tst_psFitsReadHeaderSet( void );
+static psS32 tst_psFitsReadTable( void );
 
 testDescription tests[] = {
@@ -35,5 +39,6 @@
                               {tst_psFitsMoveExtNum, 803, "psFitsGetSize", 0, true},
                               {tst_psFitsReadHeader, 804, "psFitsReadHeader", 0, false},
-                              {tst_psFitsReadHeaderSet, 0, "psFitsReadHeaderSet", 0, false},
+                              {tst_psFitsReadHeaderSet,805, "psFitsReadHeaderSet", 0, false},
+                              {tst_psFitsReadTable,809, "psFitsReadTable", 0, false},
                               {NULL}
                           };
@@ -110,4 +115,62 @@
 }
 
+bool makeTable(void)
+{
+
+    if (access(tableFilename, F_OK) != 0) {
+        psFits* fitsFile = psFitsAlloc(tableFilename);
+
+        if (fitsFile == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not create 'table' FITS file.");
+            return false;
+        }
+
+        // make the PHU an image (per FITS standard, it must be)
+        psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+        if (! psFitsWriteImage(fitsFile,NULL,image,1) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not write PHU image.");
+            return false;
+        }
+
+        psFree(image);
+
+        // build a table structure
+        psArray* table = psArrayAlloc(tableNumRows);
+        table->n = 0;
+        for (int row = 0; row < tableNumRows; row++) {
+            psMetadata* header = psMetadataAlloc();
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                          PS_TYPE_S32, PS_META_PRIMITIVE,
+                          "psS32 Item", (psS32)row);
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                          PS_TYPE_F32, PS_META_PRIMITIVE,
+                          "psF32 Item", (float)(1.0f/(float)(1+row)));
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                          PS_TYPE_F64, PS_META_PRIMITIVE,
+                          "psF64 Item", (double)(1.0/(double)(1+row)));
+
+            psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                          PS_TYPE_BOOL, PS_META_PRIMITIVE,
+                          "psBool Item",
+                          (row%2 == 0));
+
+            psArrayAdd(table,0,header);
+        }
+
+        psFitsWriteTable(fitsFile, NULL, table, "table-1");
+
+        psFree(table);
+        psFree(fitsFile);
+    }
+
+    return true;
+}
+
 psS32 tst_psFitsAlloc( void )
 {
@@ -176,4 +239,10 @@
     psFits* fits = psFitsAlloc(multiFilename);
 
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
     int numHDUs = psFitsGetSize(fits);
 
@@ -290,4 +359,10 @@
 
     psFits* fits = psFitsAlloc(multiFilename);
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
 
     int numHDUs = psFitsGetSize(fits);
@@ -489,4 +564,10 @@
     psFits* fits = psFitsAlloc(multiFilename);
 
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
     int numHDUs = psFitsGetSize(fits);
 
@@ -594,4 +675,10 @@
     psFits* fits = psFitsAlloc(multiFilename);
 
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
     int numHDUs = psFitsGetSize(fits);
 
@@ -701,2 +788,87 @@
     return 0;
 }
+
+static psS32 tst_psFitsReadTable( void )
+{
+
+
+    if (! makeTable() ) {
+        return 1;
+    }
+
+    psFits* fits = psFitsAlloc(tableFilename);
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsAlloc returned NULL on existing file.");
+        return 1;
+    }
+
+    psFitsMoveExtNum(fits,1,false);
+
+    psArray* table = psFitsReadTable(fits);
+
+    if (table == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTable returned NULL unexpectedly.");
+        return 2;
+    }
+
+    if (table->n != tableNumRows) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Expected %d rows, but read %d.",
+                tableNumRows, table->n);
+        return 3;
+    }
+
+
+    for (int row = 0; row < table->n; row++) {
+        psMetadata* rowData = table->data[row];
+
+        psS32 intItem = psMetadataLookupS32(rowData, "MYINT",NULL);
+        psF32 fltItem = psMetadataLookupF32(rowData, "MYFLT",NULL);
+        psF64 dblItem = psMetadataLookupF64(rowData, "MYDBL",NULL);
+        psBool boolItem = psMetadataLookupBool(rowData, "MYBOOL",NULL);
+
+        if (intItem != row) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psS32 metadata item from file.  Got %d vs %d",
+                    intItem, row);
+            return 20;
+        }
+
+        if (fabsf(fltItem - 1.0f/(float)(1+row)) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF32 metadata item from file.  Got %f vs %f",
+                    fltItem,1.0f/(float)(1+row));
+            return 21;
+        }
+
+        if (abs(dblItem - 1.0/(double)(1+row)) > DBL_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF64 metadata item from file.  Got %g vs %g",
+                    dblItem, 1.0/(double)(1+row));
+            return 22;
+        }
+
+        if (boolItem != (row%2 == 0)) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psBool metadata item from file.");
+            return 23;
+        }
+
+    }
+
+    psFree(table);
+    psFree(fits);
+
+    psArray* nullTest = psFitsReadTable(NULL);
+
+    if (nullTest != NULL || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psFitsReadTable returned non-NULL when given NULL.");
+        return 30;
+    }
+
+    return 0;
+}
Index: /trunk/psLib/test/fileUtils/verified/tst_psFits.stderr
===================================================================
--- /trunk/psLib/test/fileUtils/verified/tst_psFits.stderr	(revision 3024)
+++ /trunk/psLib/test/fileUtils/verified/tst_psFits.stderr	(revision 3025)
@@ -91,2 +91,13 @@
 ---> TESTPOINT PASSED (psImage{psFitsReadHeaderSet} | tst_psFits.c)
 
+/***************************** TESTPOINT ******************************************\
+*             TestFile: tst_psFits.c                                               *
+*            TestPoint: psImage{psFitsReadTable}                                   *
+*             TestType: Positive                                                   *
+\**********************************************************************************/
+
+<DATE><TIME>|<HOST>|E|psFitsReadTable (psFits.c:<LINENO>)
+    The input psFits object can not NULL.
+
+---> TESTPOINT PASSED (psImage{psFitsReadTable} | tst_psFits.c)
+
