Index: /branches/eam_branches/ipp-20110505/Ohana/src/libohana/include/ohana.h
===================================================================
--- /branches/eam_branches/ipp-20110505/Ohana/src/libohana/include/ohana.h	(revision 31597)
+++ /branches/eam_branches/ipp-20110505/Ohana/src/libohana/include/ohana.h	(revision 31598)
@@ -235,4 +235,5 @@
 int     scan_line              PROTO((FILE *f, char *line)); 
 int     dparse                 PROTO((double *X, int NX, char *line));
+int     dparse_csv             PROTO((double *X, int NX, char *line));
 int     fparse                 PROTO((float *X, int NX, char *line));
 int     get_argument           PROTO((int argc, char **argv, char *arg));
Index: /branches/eam_branches/ipp-20110505/Ohana/src/libohana/src/string.c
===================================================================
--- /branches/eam_branches/ipp-20110505/Ohana/src/libohana/src/string.c	(revision 31597)
+++ /branches/eam_branches/ipp-20110505/Ohana/src/libohana/src/string.c	(revision 31598)
@@ -153,4 +153,18 @@
 }
 
+// advance to the next word, separated by commas:
+// AA,BB,CC : go from AA to BB to CC to 0
+// AA,,CC : go from AA to , to CC to 0
+// ,,, : go from , to , to , to 0
+
+char *_parse_nextword_csv (char *string) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; (*string != 0) && (*string != ','); string++);
+  if (*string == ',') string ++;
+  return (string);
+}
+
 int dparse (double *X, int NX, char *line) {
 
@@ -162,4 +176,25 @@
   for (i = 0; i < NX - 1; i++)
     word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word) return (FALSE);
+  if (word[0] == '-') return (-1);
+  return (1);
+}
+
+int dparse_csv (double *X, int NX, char *line) {
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword_csv (word);
+  
+  if (word[0] == ',') {
+      *X = NAN;
+      return 1;
+  }
 
   *X = strtod (word, &ptr);
Index: /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 31597)
+++ /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 31598)
@@ -2,5 +2,5 @@
 
 FILE *f = (FILE *) NULL;
-char filename[256];
+char filename[1024];
 
 int datafile (int argc, char **argv) {
@@ -23,5 +23,5 @@
 int read_vectors (int argc, char **argv) {
   
-  int i, j, Nskip, Nvec, *col, done, status;
+  int i, j, Nskip, Nvec, *col, done, status, IsCSV;
   int Nbytes, nbytes, Nstart, NELEM, N, nread;
   char *colstr, *c0, *c1, *buffer, *extname;
@@ -47,4 +47,10 @@
   }
 
+  IsCSV = FALSE;
+  if ((N = get_argument (argc, argv, "-csv"))) {
+    remove_argument (N, &argc, argv);
+    IsCSV = TRUE;
+  }
+
   if ((argc < 3) || !(argc % 2)) {
     gprint (GP_ERR, "USAGE: read name N name N ...\n");
@@ -58,4 +64,9 @@
   }
   fseeko (f, 0LL, SEEK_SET);
+
+//  if (IsCSV) {
+//    status = read_vectors_csv (argc, argv, Nskip, f);
+//    return status;
+//  }
 
   Nvec = (argc - 1) / 2;
@@ -122,5 +133,9 @@
       if ((*c0 != '#') && (*c0 != '!')) {
 	for (i = 0; (i < Nvec) && status; i++) {
-	  status = dparse (&value, col[i], c0);
+	  if (IsCSV) {
+	    status = dparse_csv (&value, col[i], c0);
+	  } else {
+	    status = dparse (&value, col[i], c0);
+	  }
 	  vec[i][0].elements.Flt[N] = value;
 	  if (!status) vec[i][0].elements.Flt[N] = NAN;
@@ -341,2 +356,104 @@
   return (TRUE);
 }
+
+# if (0)
+int read_vectors_csv (int argc, char **argv, int Nskip, FILE *f) {
+  
+  int i, j, Nvec, *col, done, status;
+  int Nbytes, nbytes, Nstart, NELEM, N, nread;
+  char *colstr, *c0, *c1, *buffer, *extname;
+  double value;
+  Vector **vec;
+
+  Nvec = (argc - 1) / 2;
+  ALLOCATE (vec, Vector *, Nvec);
+  ALLOCATE (col, int, Nvec);
+
+  for (i = 0; i < Nvec; i++) {
+    if ((vec[i] = SelectVector (argv[2*i + 1], ANYVECTOR, TRUE)) == NULL) {
+      gprint (GP_ERR, "USAGE: read name N name N ...\n");
+      free (vec);
+      free (col);
+      return (FALSE);    
+    }
+    // XXX we could allow flags (eg, N.i) to specify INT vs FLT types vectors...
+    colstr = argv[2*i+2];
+    for (j = 0; j < strlen (colstr); j++) {
+      if (!isdigit(colstr[j])) {
+	gprint (GP_ERR, "USAGE: read name N name N ...\n");
+	free (vec);
+	free (col);
+	return (FALSE);    
+      }
+    }
+    col[i] = atof (colstr);
+  }
+
+  // currently, all read vectors are forced to be type FLT
+  NELEM = 1000;
+  for (i = 0; i < Nvec; i++) {
+    ResetVector (vec[i], OPIHI_FLT, NELEM);
+  }
+  
+  ALLOCATE (buffer, char, 0x10001);
+  bzero (buffer, 0x10001);
+  for (i = 0; i < Nskip; i++) {
+    scan_line (f, buffer);
+  }
+
+  Nstart = 0;
+  N = 0;
+  done = FALSE;
+  while (!done) {
+    Nbytes = 0x10000 - Nstart;
+    bzero (&buffer[Nstart], Nbytes);
+    nread = fread (&buffer[Nstart], 1, Nbytes, f);
+    if (ferror (f)) {
+      perror ("error reading data file");
+      break;
+    }
+    if (nread == 0) break;
+    nbytes = nread + Nstart;
+    
+    status = TRUE;
+    c0 = buffer; 
+    while (status) {
+      c1 = strchr (c0, '\n');
+      if (c1 == (char *) NULL) {
+	Nstart = strlen (c0);
+	memmove (buffer, c0, Nstart);
+	status = FALSE;
+      } else {
+	*c1 = 0;
+      }      
+      if ((*c0 != '#') && (*c0 != '!')) {
+	for (i = 0; (i < Nvec) && status; i++) {
+	  status = dparse_csv (&value, col[i], c0);
+	  vec[i][0].elements.Flt[N] = value;
+	  if (!status) vec[i][0].elements.Flt[N] = NAN;
+	}
+	if (status) N++;
+      }
+      c0 = c1 + 1;
+      if (N == NELEM) {
+	NELEM += 1000;
+	for (i = 0; i < Nvec; i++) {
+	  REALLOCATE (vec[i][0].elements.Flt, opihi_flt, NELEM);
+	}
+      }
+	
+    }
+  }
+  for (i = 0; i < Nvec; i++) {
+    REALLOCATE (vec[i][0].elements.Flt, opihi_flt, MAX (N,1));
+    vec[i][0].Nelements = N;
+  }
+  
+  free (vec);
+  free (col);
+  free (buffer);
+  return (TRUE);
+
+}
+
+# endif
Index: /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/test/csv.dat
===================================================================
--- /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/test/csv.dat	(revision 31598)
+++ /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/test/csv.dat	(revision 31598)
@@ -0,0 +1,3 @@
+word,1,5,10
+foo,2,4,8
+sam,3,3,6
Index: /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/test/csv1.dat
===================================================================
--- /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/test/csv1.dat	(revision 31598)
+++ /branches/eam_branches/ipp-20110505/Ohana/src/opihi/cmd.data/test/csv1.dat	(revision 31598)
@@ -0,0 +1,3 @@
+word,1,5,10
+foo,,4,8
+sam,3,,6
