Index: trunk/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 39297)
+++ trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 39328)
@@ -8,4 +8,6 @@
 void read_vectors_cleanup ();
 int read_table_sizes (Header *header);
+int read_table_fields (Header *header, int isCompressed, int VERBOSE);
+void list_extnames (void);
 
 int datafile (int argc, char **argv) {
@@ -87,4 +89,17 @@
     gprint (GP_ERR, "       for time, values are human-readable date/time strings YYYY/MM/DD,hh:mm:ss\n");
     gprint (GP_ERR, "       the resulting vector is a float based on the TIMEFORMAT, TIMEREF values\n");
+
+    gprint (GP_ERR, "     -fits options:\n");
+    gprint (GP_ERR, "       -transpose : read rows as columns and vice-versa\n");
+
+    gprint (GP_ERR, "       -keyword (FIELD) : use FIELD to identify the extension (default: EXTNAME)\n");
+    gprint (GP_ERR, "       -pad-if-short : allow reading of broken files by padding missing data\n");
+    gprint (GP_ERR, "       -sizes : return a list of table size information ($table:Nx, $table:Ny, $table:$Nfields)  \n");
+    gprint (GP_ERR, "       -list-fields : return a list of table columns ($tfields:0 to $tfields:n) (use -v to see the list)\n");
+    gprint (GP_ERR, "       -extnum (N) : use the number to find the Nth extension (ignore EXTNAME)\n");
+    gprint (GP_ERR, "       -range (start) (Nrows) : read the specified portion of the file\n");
+    gprint (GP_ERR, "        -v : verbose \n");
+    gprint (GP_ERR, "        -char-vectors : char fields will be saved as vectors NAME:0 -- NAME:n for n characters \n");
+
     return (FALSE);
   }
@@ -393,4 +408,10 @@
   }
 
+  int listFields = FALSE;
+  if ((N = get_argument (argc, argv, "-list-fields"))) {
+    remove_argument (N, &argc, argv);
+    listFields = TRUE;
+  }
+
   int Nextend = -1;
   if ((N = get_argument (argc, argv, "-extnum"))) {
@@ -432,10 +453,22 @@
   // }
 
-  if ((argc < 2) && !getSizes) ESCAPE ("USAGE: read -fits extension [-extnum] [-keyword key] name name ...\n");
-  if ((argc != 1) && getSizes) ESCAPE ("USAGE: read -sizes -fits extension [-extnum] (does not read data values)\n");
+  int listExtnames = FALSE;
+  if (!strcmp(extname, "-list")) {
+    listExtnames = TRUE;
+  }
+
+  if ((argc < 2) && !getSizes && !listFields && !listExtnames) ESCAPE ("USAGE: read -fits extension [-extnum] [-keyword key] name name ...\n");
+  if ((argc != 1) && getSizes)   ESCAPE ("USAGE: read -sizes -fits extension [-extnum] (does not read data values)\n");
+  if ((argc != 1) && listFields) ESCAPE ("USAGE: read -list-fields -fits extension [-extnum] (does not read data values)\n");
+  if ((argc != 1) && listExtnames) ESCAPE ("USAGE: read -list-fields -fits extension [-extnum] (does not read data values)\n");
 
   if (f == NULL) ESCAPE ("file not found\n");
   fseeko (f, 0LL, SEEK_SET);
   table.header = &header;
+
+  if (listExtnames) {
+    list_extnames ();
+    return TRUE;
+  }
 
   /**** find the appropriate extension and read header (if extname is a number, use count) ****/
@@ -491,4 +524,10 @@
   if (getSizes && !IsCompressed) {
     read_table_sizes (&header);
+    if (CCDKeyword != NULL) free (CCDKeyword); 
+    gfits_free_header (&header); 
+    return TRUE;
+  }
+  if (listFields) {
+    read_table_fields (&header, IsCompressed, VERBOSE);
     if (CCDKeyword != NULL) free (CCDKeyword); 
     gfits_free_header (&header); 
@@ -676,2 +715,126 @@
 }
 
+// read -fits foo -sizes -- Nx, Ny, Nfields -> $table:Nx, $table:Ny, $table:$Nfields
+// read -fits foo -fields 
+
+int read_table_fields (Header *header, int isCompressed, int VERBOSE) {
+  
+  int i, Nfields;
+  char field[32], varname[32], type[80], comment[80], format[80], unit[80], null[80], nval[80];
+
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+
+  set_int_variable ("table:Nx", header->Naxis[0]);
+  set_int_variable ("table:Ny", header->Naxis[1]);
+  set_int_variable ("table:Nfields", Nfields);
+  set_int_variable ("tfields:n", Nfields);
+
+  for (i = 1; i <= Nfields; i++) {
+    memset (field,   0, 32);
+    memset (type,    0, 80);
+    memset (comment, 0, 80);
+    memset (format,  0, 80);
+    memset (unit,    0, 80);
+    memset (null,    0, 80);
+    memset (nval,    0, 80);
+
+    snprintf (field, 32, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, type);
+    
+    snprintf (varname, 32, "tfields:%d", i - 1);
+    set_str_variable (varname, type);
+
+    gfits_scan_alt (header, field, "%C", 1, comment);
+
+    if (!isCompressed) {
+      snprintf (field, 32, "TFORM%d", i);
+    } else {
+      snprintf (field, 32, "ZFORM%d", i);
+    }
+    gfits_scan (header, field, "%s", 1, format);
+
+    snprintf (field, 32, "TUNIT%d", i);
+    gfits_scan (header, field, "%s", 1, unit);
+    snprintf (field, 32, "TNULL%d", i);
+    if (!gfits_scan (header, field, "%s", 1, null)) strcpy (null, "none");
+    snprintf (field, 32, "TNVAL%d", i);
+    if (!gfits_scan (header, field, "%s", 1, nval)) strcpy (nval, "none");
+
+    if (VERBOSE) gprint (GP_LOG, "%-18s %-18s %-6s %-8s %-8s %-32s\n", type, unit, format, null, nval, comment); 
+  }
+
+
+  return TRUE;
+}
+
+void list_extnames (void) {
+
+  off_t Nbytes, Nelem;
+  int i, Naxis, Ncomp, extend, status;
+  char extname[82], exttype[82], axisname[32];
+  Header header;
+
+  fseeko (f, 0, SEEK_SET);
+
+  gprint (GP_LOG, "%-30s %-15s NAXIS NAXIS(i)...\n", "extname", "datatype"); 
+
+  Ncomp = 0;
+  while (gfits_fread_header (f, &header)) {
+    /* extract the EXTNAME for this component (set to PHU for 0th component) */
+    status = gfits_scan (&header, "EXTNAME", "%s", 1, extname);
+    if (!status) {
+      if (Ncomp == 0) {
+	strcpy (extname, "PHU");
+      } else {
+	strcpy (extname, "UNKNOWN");
+      }
+    }
+    gprint (GP_LOG, "%-30s ", extname);
+
+    /* extract the datatype for this component (IMAGE for 0th component) */
+    if (Ncomp == 0) {
+      strcpy (exttype, "IMAGE");
+    } else {
+      status = gfits_scan (&header, "XTENSION", "%s", 1, exttype);
+      if (!status) {
+	strcpy (exttype, "UNKNOWN");
+      }
+    }
+    gprint (GP_LOG, "%-15s ", exttype);
+
+    /* extract the rank of the component */
+    status = gfits_scan (&header, "NAXIS",  "%d", 1, &Naxis);
+    if (!status) {
+      gprint (GP_ERR, "component %d is missing Naxis!\n", Ncomp);
+      Ncomp ++;
+      continue;
+    }
+    gprint (GP_LOG, " %4d", Naxis);
+
+    /* extract the individual axes */
+    for (i = 0; i < Naxis; i++) {
+      sprintf (axisname, "NAXIS%d", i+1);
+      status = gfits_scan (&header, axisname,  OFF_T_FMT, 1,  &Nelem);
+      if (!status) {
+	gprint (GP_ERR, "missing %s\n", axisname);
+      }
+      gprint (GP_LOG, " "OFF_T_FMT,  Nelem);
+    }
+    gprint (GP_LOG, "\n");
+
+    /* are extensions identified? (we will scan for them anyway) */
+    if (Ncomp == 0) {
+      extend = FALSE;
+      gfits_scan_alt (&header, "EXTEND", "%t", 1, &extend);
+      if (!extend) {
+	gprint (GP_ERR, "no extensions listed in file\n");
+      }
+    }
+
+    Nbytes = gfits_data_size (&header);
+    fseeko (f, Nbytes, SEEK_CUR);
+
+    Ncomp ++;
+  }
+  return;
+}
