changeset 4944:44046bbaa52c

[project @ 2004-08-31 05:30:46 by jwe]
author jwe
date Tue, 31 Aug 2004 05:30:47 +0000
parents 1a499d0c58f5
children 4bd917f8a4a7
files liboctave/CNDArray.h liboctave/ChangeLog liboctave/boolNDArray.h liboctave/byte-swap.h liboctave/chNDArray.h liboctave/dMatrix.cc liboctave/dMatrix.h liboctave/dNDArray.h liboctave/data-conv.cc liboctave/data-conv.h src/ChangeLog src/file-io.cc src/ls-mat4.cc src/ls-mat5.cc src/ls-oct-binary.cc src/oct-stream.cc src/oct-stream.h src/ov-base-int.cc src/ov-base.cc src/ov-base.h src/ov-bool-mat.cc src/ov-bool.cc src/ov-cell.cc src/ov-complex.cc src/ov-complex.h src/ov-cx-mat.cc src/ov-cx-mat.h src/ov-intx.h src/ov-list.cc src/ov-range.cc src/ov-re-mat.cc src/ov-re-mat.h src/ov-scalar.cc src/ov-scalar.h src/ov-str-mat.cc src/ov-str-mat.h src/ov-struct.cc src/ov.cc src/ov.h
diffstat 39 files changed, 1452 insertions(+), 863 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/CNDArray.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/CNDArray.h	Tue Aug 31 05:30:47 2004 +0000
@@ -33,9 +33,6 @@
 #include "mx-defs.h"
 #include "mx-op-defs.h"
 
-#include "data-conv.h"
-#include "mach-info.h"
-
 class
 ComplexNDArray : public MArrayN<Complex>
 {
--- a/liboctave/ChangeLog	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/ChangeLog	Tue Aug 31 05:30:47 2004 +0000
@@ -1,3 +1,23 @@
+2004-08-31  John W. Eaton  <jwe@octave.org>
+
+	* data-conv.h (oct_data_conv::data_type): Include sized types.
+	Explicitly number enum elements.
+
+	* data-conv.cc (oct_data_conv::string_to_data_type (const
+	std::string&, int&, oct_data_conv::data_type&,
+	oct_data_conv::data_type&)): New function.
+	(oct_data_conv::string_to_data_type (const std::string&, int&,
+	oct_data_conv::data_type&)): New function.
+	(oct_data_conv::data_type_as_string): New function.
+
+	* dMatrix.cc (read_int, do_read, Matrix::read): Delete.
+	(write_int, do_write, Matrix::write): Delete.
+	* dMatrix.h (Matrix::read, Matrix::write): Delete decls.
+
+	* byte-swap.h: Use template functions and specialization.
+	Change all uses.
+	(swap_2_bytes, swap_4_bytes, swap_8_bytes): Delete.
+
 2004-08-30  John W. Eaton  <jwe@octave.org>
 
 	* oct-inttypes.h (octave_int_fit_to_range): Use template
--- a/liboctave/boolNDArray.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/boolNDArray.h	Tue Aug 31 05:30:47 2004 +0000
@@ -33,9 +33,6 @@
 #include "mx-defs.h"
 #include "mx-op-defs.h"
 
-#include "data-conv.h"
-#include "mach-info.h"
-
 #include "boolMatrix.h"
 
 class
--- a/liboctave/byte-swap.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/byte-swap.h	Tue Aug 31 05:30:47 2004 +0000
@@ -36,68 +36,62 @@
   t[j] = tmp;
 }
 
-static inline void
-swap_2_bytes (volatile void *ptr)
+template <int n>
+void
+swap_bytes (volatile void *ptr)
 {
-  volatile char *t = static_cast<volatile char *> (ptr);
+  for (size_t i = 0; i < n/2; i++)
+    swap_bytes (ptr, i, n-1-i);
+}
 
-  swap_bytes (t, 0, 1);
+template <>
+inline void
+swap_bytes <1> (volatile void *)
+{
+}
+
+template <>
+inline void
+swap_bytes <2> (volatile void *ptr)
+{
+  swap_bytes (ptr, 0, 1);
 }
 
-static inline void
-swap_4_bytes (volatile void *ptr)
+template <>
+inline void
+swap_bytes <4> (volatile void *ptr)
 {
-  volatile char *t = static_cast<volatile char *> (ptr);
-
-  swap_bytes (t, 0, 3);
-  swap_bytes (t, 1, 2);
+  swap_bytes (ptr, 0, 3);
+  swap_bytes (ptr, 1, 2);
 }
 
-static inline void
-swap_8_bytes (volatile void *ptr)
+template <>
+inline void
+swap_bytes <8> (volatile void *ptr)
 {
-  volatile char *t = static_cast<volatile char *> (ptr);
-
-  swap_bytes (t, 0, 7);
-  swap_bytes (t, 1, 6);
-  swap_bytes (t, 2, 5);
-  swap_bytes (t, 3, 4);
+  swap_bytes (ptr, 0, 7);
+  swap_bytes (ptr, 1, 6);
+  swap_bytes (ptr, 2, 5);
+  swap_bytes (ptr, 3, 4);
 }
 
-static inline void
-swap_2_bytes (volatile void *ptr, int len)
+template <int n>
+void
+swap_bytes (volatile void *ptr, int len)
 {
   volatile char *t = static_cast<volatile char *> (ptr);
 
   for (int i = 0; i < len; i++)
     {
-      swap_2_bytes (t);
-      t += 2;
+      swap_bytes<n> (t);
+      t += n;
     }
 }
 
-static inline void
-swap_4_bytes (volatile void *ptr, int len)
+template <>
+inline void
+swap_bytes<1> (volatile void *, int)
 {
-  volatile char *t = static_cast<volatile char *> (ptr);
-
-  for (int i = 0; i < len; i++)
-    {
-      swap_4_bytes (t);
-      t += 4;
-    }
-}
-
-static inline void
-swap_8_bytes (volatile void *ptr, int len)
-{
-  volatile char *t = static_cast<volatile char *> (ptr);
-
-  for (int i = 0; i < len; i++)
-    {
-      swap_8_bytes (t);
-      t += 8;
-    }
 }
 
 #endif
--- a/liboctave/chNDArray.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/chNDArray.h	Tue Aug 31 05:30:47 2004 +0000
@@ -33,9 +33,6 @@
 #include "mx-defs.h"
 #include "mx-op-defs.h"
 
-#include "data-conv.h"
-#include "mach-info.h"
-
 class
 charNDArray : public MArrayN<char>
 {
--- a/liboctave/dMatrix.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/dMatrix.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -2500,497 +2500,6 @@
   return is;
 }
 
-template <class T>
-void
-read_int (std::istream& is, bool swap_bytes, T& val)
-{
-  is.read (X_CAST (char *, &val), sizeof (T));
-
-  int t = sizeof (T);
-
-  if (swap_bytes && t > 1)
-    {
-      switch (t)
-	{
-	case 2:
-	  swap_2_bytes (X_CAST (char *, &val));
-	  break;
-
-	case 4:
-	  swap_4_bytes (X_CAST (char *, &val));
-	  break;
-
-	case 8:
-	  swap_8_bytes (X_CAST (char *, &val));
-	  break;
-
-	default:
-	  (*current_liboctave_error_handler)
-	    ("read_int: unrecognized data format!");
-	}
-    }
-}
-
-template void read_int (std::istream&, bool, char&);
-template void read_int (std::istream&, bool, signed char&);
-template void read_int (std::istream&, bool, unsigned char&);
-template void read_int (std::istream&, bool, short&);
-template void read_int (std::istream&, bool, unsigned short&);
-template void read_int (std::istream&, bool, int&);
-template void read_int (std::istream&, bool, unsigned int&);
-template void read_int (std::istream&, bool, long&);
-template void read_int (std::istream&, bool, unsigned long&);
-
-static inline bool
-do_read (std::istream& is, oct_data_conv::data_type dt, 
-	 oct_mach_info::float_format flt_fmt, bool swap_bytes,
-	 bool do_float_conversion, double& val)
-{
-  bool retval = true;
-
-  switch (dt)
-    {
-    case oct_data_conv::dt_char:
-      {
-	char tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_schar:
-      {
-	signed char tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_uchar:
-      {
-	unsigned char tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_short:
-      {
-	short tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_ushort:
-      {
-	unsigned short tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_int:
-      {
-	int tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_uint:
-      {
-	unsigned int tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_long:
-      {
-	long tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_ulong:
-      {
-	unsigned long tmp;
-	read_int (is, swap_bytes, tmp);
-	val = tmp;
-      }
-      break;
-
-    case oct_data_conv::dt_float:
-      {
-	float f;
-
-	is.read (X_CAST (char *, &f), sizeof (float));
-
-	if (do_float_conversion)
-	  do_float_format_conversion (&f, 1, flt_fmt);
-
-	val = f;
-      }
-      break;
-
-    case oct_data_conv::dt_double:
-      {
-	is.read (X_CAST (char *, &val), sizeof (double));
-
-	if (do_float_conversion)
-	  do_double_format_conversion (&val, 1, flt_fmt);
-      }
-      break;
-
-    default:
-      retval = false;
-      (*current_liboctave_error_handler)
-	("read: invalid type specification");
-      break;
-    }
-
-  return retval;
-}
-
-int
-Matrix::read (std::istream& is, int nr, int nc,
-	      oct_data_conv::data_type dt, int skip,
-	      oct_mach_info::float_format flt_fmt)
-{
-  if (nr == 0 || nc == 0)
-    {
-      if (nr >= 0 && nc >= 0)
-	resize (nr, nc);
-      else
-	resize (0, 0);
-
-      return 0;
-    }
-
-  int retval = -1;
-
-  bool ok = true;
-
-  int count = 0;
-
-  double *dat = 0;
-  int max_size = 0;
-
-  int final_nr = 0;
-  int final_nc = 0;
-
-  if (nr > 0)
-    {
-      if (nc > 0)
-	{
-	  resize (nr, nc, 0.0);
-	  dat = fortran_vec ();
-	  max_size = nr * nc;
-	}
-      else
-	{
-	  resize (nr, 32, 0.0);
-	  dat = fortran_vec ();
-	  max_size = nr * 32;
-	}
-    }
-  else
-    {
-      resize (32, 1, 0.0);
-      dat = fortran_vec ();
-      max_size = 32;
-    }
-
-  oct_mach_info::float_format native_flt_fmt
-    = oct_mach_info::float_format ();
-
-  bool do_float_conversion = (flt_fmt != native_flt_fmt);
-
-  // XXX FIXME XXX -- byte order for Cray?
-
-  bool swap_bytes = false;
-
-  if (oct_mach_info::words_big_endian ())
-    swap_bytes = (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
-		 || flt_fmt == oct_mach_info::flt_fmt_vax_g
-		 || flt_fmt == oct_mach_info::flt_fmt_vax_g);
-  else
-    swap_bytes = (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
-
-  for (;;)
-    {
-      // XXX FIXME XXX -- maybe there should be a special case for
-      // skip == 0.
-
-      if (is)
-	{
-	  if (nr > 0 && nc > 0 && count == max_size)
-	    {
-	      final_nr = nr;
-	      final_nc = nc;
-
-	      break;
-	    }
-
-	  double tmp = 0.0;
-
-	  ok = do_read (is, dt, flt_fmt, swap_bytes, do_float_conversion, tmp);
-
-	  if (ok)
-	    {
-	      if (is)
-		{
-		  if (count == max_size)
-		    {
-		      max_size *= 2;
-
-		      if (nr > 0)
-			resize (nr, max_size / nr, 0.0);
-		      else
-			resize (max_size, 1, 0.0);
-
-		      dat = fortran_vec ();
-		    }
-
-		  dat[count++] = tmp;
-		}
-
-	      if (skip != 0)
-		is.seekg (skip, std::ios::cur);
-
-	      if (is.eof ())
-		{
-		  if (nr > 0)
-		    {
-		      if (count > nr)
-			{
-			  final_nr = nr;
-			  final_nc = (count - 1) / nr + 1;
-			}
-		      else
-			{
-			  final_nr = count;
-			  final_nc = 1;
-			}
-		    }
-		  else
-		    {
-		      final_nr = count;
-		      final_nc = 1;
-		    }
-
-		  break;
-		}
-	    }
-	  else
-	    {
-	      ok = false;
-	      break;
-	    }
-	}
-      else
-	{
-	  ok = false;
-	  break;
-	}
-    }
-
-  if (ok)
-    {
-      resize (final_nr, final_nc, 0.0);
-
-      retval = count;
-    }
-
-  return retval;
-}
-
-template <class T>
-void
-write_int (std::ostream& os, bool swap_bytes, T val)
-{
-  int t = sizeof (T);
-
-  if (swap_bytes && t > 1)
-    {
-      switch (t)
-	{
-	case 2:
-	  swap_2_bytes (X_CAST (char *, &val));
-	  break;
-
-	case 4:
-	  swap_4_bytes (X_CAST (char *, &val));
-	  break;
-
-	case 8:
-	  swap_8_bytes (X_CAST (char *, &val));
-	  break;
-
-	default:
-	  (*current_liboctave_error_handler)
-	    ("write_int: unrecognized data format!");
-	}
-    }
-
-  os.write (X_CAST (char *, &val), sizeof (T));
-}
-
-template void write_int (std::ostream&, bool, char);
-template void write_int (std::ostream&, bool, signed char);
-template void write_int (std::ostream&, bool, unsigned char);
-template void write_int (std::ostream&, bool, short);
-template void write_int (std::ostream&, bool, unsigned short);
-template void write_int (std::ostream&, bool, int);
-template void write_int (std::ostream&, bool, unsigned int);
-template void write_int (std::ostream&, bool, long);
-template void write_int (std::ostream&, bool, unsigned long);
-
-static inline bool
-do_write (std::ostream& os, double d, oct_data_conv::data_type dt,
-	  oct_mach_info::float_format flt_fmt, bool swap_bytes,
-	  bool do_float_conversion)
-{
-  bool retval = true;
-
-  switch (dt)
-    {
-    case oct_data_conv::dt_char:
-      write_int (os, swap_bytes, X_CAST (char, d));
-      break;
-
-    case oct_data_conv::dt_schar:
-      write_int (os, swap_bytes, X_CAST (signed char, d));
-      break;
-
-    case oct_data_conv::dt_uchar:
-      write_int (os, swap_bytes, X_CAST (unsigned char, d));
-      break;
-
-    case oct_data_conv::dt_short:
-      write_int (os, swap_bytes, X_CAST (short, d));
-      break;
-
-    case oct_data_conv::dt_ushort:
-      write_int (os, swap_bytes, X_CAST (unsigned short, d));
-      break;
-
-    case oct_data_conv::dt_int:
-      write_int (os, swap_bytes, X_CAST (int, d));
-      break;
-
-    case oct_data_conv::dt_uint:
-      write_int (os, swap_bytes, X_CAST (unsigned int, d));
-      break;
-
-    case oct_data_conv::dt_long:
-      write_int (os, swap_bytes, X_CAST (long, d));
-      break;
-
-    case oct_data_conv::dt_ulong:
-      write_int (os, swap_bytes, X_CAST (unsigned long, d));
-      break;
-
-    case oct_data_conv::dt_float:
-      {
-	float f = d;
-
-	if (do_float_conversion)
-	  do_float_format_conversion (&f, 1, flt_fmt);
-
-	os.write (X_CAST (char *, &f), sizeof (float));
-      }
-      break;
-
-    case oct_data_conv::dt_double:
-      {
-	if (do_float_conversion)
-	  do_double_format_conversion (&d, 1, flt_fmt);
-
-	os.write (X_CAST (char *, &d), sizeof (double));
-      }
-      break;
-
-    default:
-      retval = false;
-      (*current_liboctave_error_handler)
-	("write: invalid type specification");
-      break;
-    }
-
-  return retval;
-}
-
-int
-Matrix::write (std::ostream& os, oct_data_conv::data_type dt, int skip,
-	       oct_mach_info::float_format flt_fmt)
-{
-  int retval = -1;
-
-  bool ok = true;
-
-  int count = 0;
-
-  const double *d = data ();
-
-  int n = length ();
-
-  oct_mach_info::float_format native_flt_fmt
-    = oct_mach_info::float_format ();
-
-  bool do_float_conversion = (flt_fmt != native_flt_fmt);
-
-  // XXX FIXME XXX -- byte order for Cray?
-
-  bool swap_bytes = false;
-
-  if (oct_mach_info::words_big_endian ())
-    swap_bytes = (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
-		 || flt_fmt == oct_mach_info::flt_fmt_vax_g
-		 || flt_fmt == oct_mach_info::flt_fmt_vax_g);
-  else
-    swap_bytes = (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
-
-  for (int i = 0; i < n; i++)
-    {
-      if (os)
-	{
-	  if (skip != 0)
-	    os.seekp (skip, std::ios::cur);
-
-	  if (os)
-	    {
-	      ok = do_write (os, d[i], dt, flt_fmt, swap_bytes,
-			     do_float_conversion);
-
-	      if (os && ok)
-		count++;
-	      else
-		break;
-	    }
-	  else
-	    {
-	      ok = false;
-	      break;
-	    }
-	}
-      else
-	{
-	  ok = false;
-	  break;
-	}
-    }
-
-  if (ok)
-    retval = count;
-
-  return retval;
-}
-
-
-
 Matrix
 Givens (double x, double y)
 {
--- a/liboctave/dMatrix.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/dMatrix.h	Tue Aug 31 05:30:47 2004 +0000
@@ -33,9 +33,6 @@
 #include "mx-defs.h"
 #include "mx-op-defs.h"
 
-#include "data-conv.h"
-#include "mach-info.h"
-
 class
 Matrix : public MArray2<double>
 {
@@ -230,12 +227,6 @@
   friend std::ostream& operator << (std::ostream& os, const Matrix& a);
   friend std::istream& operator >> (std::istream& is, Matrix& a);
 
-  int read (std::istream& is, int nr, int nc, oct_data_conv::data_type dt,
-	    int skip, oct_mach_info::float_format flt_fmt);
-
-  int write (std::ostream& os, oct_data_conv::data_type dt, int skip,
-	     oct_mach_info::float_format flt_fmt);
-
   static double resize_fill_value (void) { return 0; }
 
 private:
--- a/liboctave/dNDArray.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/dNDArray.h	Tue Aug 31 05:30:47 2004 +0000
@@ -34,9 +34,6 @@
 #include "mx-defs.h"
 #include "mx-op-defs.h"
 
-#include "data-conv.h"
-#include "mach-info.h"
-
 class
 NDArray : public MArrayN<double>
 {
--- a/liboctave/data-conv.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/data-conv.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -32,6 +32,26 @@
 #include "data-conv.h"
 #include "lo-error.h"
 
+#if defined HAVE_LONG_LONG_INT
+#define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
+  do \
+    { \
+      int sz = BITS / CHAR_BIT; \
+      if (sizeof (TQ char) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## char; \
+      else if (sizeof (TQ short) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## short; \
+      else if (sizeof (TQ int) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## int; \
+      else if (sizeof (TQ long) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## long; \
+      else if (sizeof (TQ long long) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## longlong; \
+      else \
+        VAL = oct_data_conv::dt_unknown; \
+    } \
+  while (0)
+#else
 #define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
   do \
     { \
@@ -48,6 +68,7 @@
         VAL = oct_data_conv::dt_unknown; \
     } \
   while (0)
+#endif
 
 #define FIND_SIZED_FLOAT_TYPE(VAL, BITS) \
   do \
@@ -101,6 +122,52 @@
     }
 }
 
+static std::string
+strip_spaces (const std::string& str)
+{
+  int n = str.length ();
+
+  int k = 0;
+
+  std::string s (n, ' ');
+
+  for (int i = 0; i < n; i++)
+    if (! isspace (str[i]))
+      s[k++] = tolower (str[i]);
+
+  s.resize (k);
+
+  return s;
+}
+
+#define GET_SIZED_INT_TYPE(T, U) \
+  do \
+    { \
+      switch (sizeof (T)) \
+	{ \
+	case 1: \
+	  retval = dt_ ## U ## int8; \
+	  break; \
+ \
+	case 2: \
+	  retval = dt_ ## U ## int16; \
+	  break; \
+ \
+	case 4: \
+	  retval = dt_ ## U ## int32; \
+	  break; \
+ \
+	case 8: \
+	  retval = dt_ ## U ## int64; \
+	  break; \
+ \
+	default: \
+	  retval = dt_unknown; \
+	  break; \
+	} \
+    } \
+  while (0)
+
 oct_data_conv::data_type
 oct_data_conv::string_to_data_type (const std::string& str)
 {
@@ -117,62 +184,57 @@
       initialized = true;
     }
 
-  // XXX FIXME XXX -- finish implementing this.
-
-  int n = str.length ();
-
-  int k = 0;
-
-  std::string s (n, ' ');
+  std::string s = strip_spaces (str);
 
-  for (int i = 0; i < n; i++)
-    if (! isspace (str[i]))
-      s[k++] = tolower (str[i]);
-
-  s.resize (k);
-
-  if (s == "char")
+  if (s == "int8" || s == "integer*1")
+    retval = dt_int8;
+  else if (s == "uint8")
+    retval = dt_uint8;
+  else if (s == "int16" || s == "integer*2")
+    retval = dt_int16;
+  else if (s == "uint16")
+    retval = dt_uint16;
+  else if (s == "int32" || s == "integer*4")
+    retval = dt_int32;
+  else if (s == "uint32")
+    retval = dt_uint32;
+  else if (s == "int64" || s == "integer*8")
+    retval = dt_int64;
+  else if (s == "uint64")
+    retval = dt_uint64;
+  else if (s == "single" || s == "float32" || s == "real*4")
+    retval = dt_single;
+  else if (s == "double" || s == "float64" || s == "real*8")
+    retval = dt_double;
+  else if (s == "char" || s == "char*1")
     retval = dt_char;
   else if (s == "schar" || s == "signedchar")
     retval = dt_schar;
   else if (s == "uchar" || s == "unsignedchar")
     retval = dt_uchar;
   else if (s == "short")
-    retval = dt_short;
+    GET_SIZED_INT_TYPE (short, );
   else if (s == "ushort" || s == "unsignedshort")
-    retval = dt_ushort;
+    GET_SIZED_INT_TYPE (unsigned short, u);
   else if (s == "int")
-    retval = dt_int;
+    GET_SIZED_INT_TYPE (int, );
   else if (s == "uint" || s == "unsignedint")
-    retval = dt_uint;
+    GET_SIZED_INT_TYPE (unsigned int, u);
   else if (s == "long")
-    retval = dt_long;
+    GET_SIZED_INT_TYPE (long, );
   else if (s == "ulong" || s == "unsignedlong")
-    retval = dt_ulong;
+    GET_SIZED_INT_TYPE (unsigned long, u);
+  else if (s == "longlong")
+    GET_SIZED_INT_TYPE (long long, );
+  else if (s == "ulonglong" || s == "unsignedlonglong")
+    GET_SIZED_INT_TYPE (unsigned long long, u);
   else if (s == "float")
-    retval = dt_float;
-  else if (s == "double")
-    retval = dt_double;
-  else if (s == "int8" || s == "char*1" || s == "integer*1")
-    retval = sized_type_table[0][0];
-  else if (s == "int16" || s == "integer*2")
-    retval = sized_type_table[0][1];
-  else if (s == "int32" || s == "integer*4")
-    retval = sized_type_table[0][2];
-  else if (s == "int64" || s == "integer*8")
-    retval = sized_type_table[0][3];
-  else if (s == "uint8")
-    retval = sized_type_table[1][0];
-  else if (s == "uint16")
-    retval = sized_type_table[1][1];
-  else if (s == "uint32")
-    retval = sized_type_table[1][2];
-  else if (s == "uint64")
-    retval = sized_type_table[1][3];
-  else if (s == "float32" || s == "real*4")
-    retval = sized_type_table[2][2];
-  else if (s == "float64" || s == "real*8")
-    retval = sized_type_table[2][3];
+    {
+      if (sizeof (float) == sizeof (double))
+	retval = dt_double;
+      else
+	retval = dt_single;
+    }
   else
     (*current_liboctave_error_handler) ("invalid data type specified");
 
@@ -183,7 +245,217 @@
   return retval;
 }
 
-#define swap_1_bytes(x, y)
+void
+oct_data_conv::string_to_data_type
+  (const std::string& str, int& block_size,
+   oct_data_conv::data_type& input_type,
+   oct_data_conv::data_type& output_type)
+{
+  block_size = 1;
+  input_type = dt_uchar;
+  output_type = dt_double;
+
+  bool input_is_output = false;
+
+  std::string s = strip_spaces (str);
+
+  size_t pos = 0;
+
+  if (s[0] == '*')
+    input_is_output = true;
+  else
+    {
+      size_t len = s.length ();
+
+      while (pos < len && isdigit (s[pos]))
+	pos++;
+
+      if (pos > 0)
+	{
+	  if (s[pos] == '*')
+	    {
+	      block_size = atoi (s.c_str ());
+	      s = s.substr (pos+1);
+	    }
+	  else
+	    {
+	      (*current_liboctave_error_handler)
+		("invalid repeat count in `%s'", str.c_str ());
+
+	      return;
+	    }
+	}
+    }
+
+  pos = s.find ('=');
+
+  if (pos != std::string::npos)
+    {
+      if (s[pos+1] == '>')
+	{
+	  if (input_is_output)
+	    {
+	      input_is_output = false;
+
+	      (*current_liboctave_warning_handler)
+		("warning: ignoring leading * in fread precision");
+	    }
+
+	  input_type = string_to_data_type (s.substr (0, pos));
+	  output_type = string_to_data_type (s.substr (pos+2));
+	}
+      else
+	(*current_liboctave_error_handler)
+	  ("fread: invalid precision specified");
+    }
+  else
+    {
+      input_type = string_to_data_type (s);
+
+      if (input_is_output)
+	output_type = input_type;
+    }
+}
+
+void
+oct_data_conv::string_to_data_type
+  (const std::string& str, int& block_size,
+   oct_data_conv::data_type& output_type)
+{
+  block_size = 1;
+  output_type = dt_double;
+
+  std::string s = strip_spaces (str);
+
+  size_t pos = 0;
+
+  size_t len = s.length ();
+
+  while (pos < len && isdigit (s[pos]))
+    pos++;
+
+  if (pos > 0)
+    {
+      if (s[pos] == '*')
+	{
+	  block_size = atoi (s.c_str ());
+	  s = s.substr (pos+1);
+	}
+      else
+	{
+	  (*current_liboctave_error_handler)
+	    ("invalid repeat count in `%s'", str.c_str ());
+
+	  return;
+	}
+    }
+
+  output_type = string_to_data_type (s);
+}
+
+std::string
+oct_data_conv::data_type_as_string (oct_data_conv::data_type dt)
+{
+  std::string retval;
+
+  switch (dt)
+    {
+    case oct_data_conv::dt_int8:
+      retval = "int8";
+      break;
+
+    case oct_data_conv::dt_uint8:
+      retval = "uint8";
+      break;
+
+    case oct_data_conv::dt_int16:
+      retval = "int16";
+      break;
+
+    case oct_data_conv::dt_uint16:
+      retval = "uint16";
+      break;
+
+    case oct_data_conv::dt_int32:
+      retval = "int32";
+      break;
+
+    case oct_data_conv::dt_uint32:
+      retval = "uint32";
+      break;
+
+    case oct_data_conv::dt_int64:
+      retval = "int64";
+      break;
+
+    case oct_data_conv::dt_uint64:
+      retval = "uint64";
+      break;
+
+    case oct_data_conv::dt_single:
+      retval = "single";
+      break;
+
+    case oct_data_conv::dt_double:
+      retval = "double";
+      break;
+
+    case oct_data_conv::dt_char:
+      retval = "char";
+      break;
+
+    case oct_data_conv::dt_schar:
+      retval = "signed char";
+      break;
+
+    case oct_data_conv::dt_uchar:
+      retval = "usigned char";
+      break;
+
+    case oct_data_conv::dt_short:
+      retval = "short";
+      break;
+
+    case oct_data_conv::dt_ushort:
+      retval = "unsigned short";
+      break;
+
+    case oct_data_conv::dt_int:
+      retval = "int";
+      break;
+
+    case oct_data_conv::dt_uint:
+      retval = "usigned int";
+      break;
+
+    case oct_data_conv::dt_long:
+      retval = "long";
+      break;
+
+    case oct_data_conv::dt_ulong:
+      retval = "usigned long";
+      break;
+
+    case oct_data_conv::dt_longlong:
+      retval = "long long";
+      break;
+
+    case oct_data_conv::dt_ulonglong:
+      retval = "unsigned long long";
+      break;
+
+    case oct_data_conv::dt_float:
+      retval = "float";
+      break;
+
+    case oct_data_conv::dt_unknown:
+    default:
+      retval = "unknown";
+      break;
+    }
+
+  return retval;
+}
 
 #define LS_DO_READ(TYPE, swap, data, size, len, stream) \
   do \
@@ -193,7 +465,7 @@
 	  volatile TYPE *ptr = X_CAST (volatile TYPE *, data); \
 	  stream.read (X_CAST (char *, ptr), size * len); \
 	  if (swap) \
-	    swap_ ## size ## _bytes (ptr, len); \
+	    swap_bytes< size > (ptr, len); \
 	  TYPE tmp = ptr[0]; \
 	  for (int i = len - 1; i > 0; i--) \
 	    data[i] = ptr[i]; \
@@ -247,205 +519,206 @@
 // XXX FIXME XXX -- assumes sizeof (float) == 4
 
 static void
-IEEE_big_double_to_IEEE_little_double (double *d, int len)
+IEEE_big_double_to_IEEE_little_double (void *d, int len)
 {
-  swap_8_bytes (d, len);
+  swap_bytes<8> (d, len);
 }
 
 static void
-VAX_D_double_to_IEEE_little_double (double * /* d */, int /* len */)
+VAX_D_double_to_IEEE_little_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE little endian format");
 }
 
 static void
-VAX_G_double_to_IEEE_little_double (double * /* d */, int /* len */)
+VAX_G_double_to_IEEE_little_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE little endian format");
 }
 
 static void
-Cray_to_IEEE_little_double (double * /* d */, int /* len */)
+Cray_to_IEEE_little_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE little endian format");
 }
 
 static void
-IEEE_big_float_to_IEEE_little_float (float *d, int len)
+IEEE_big_float_to_IEEE_little_float (void *d, int len)
 {
-  swap_4_bytes (d, len);
+  swap_bytes<4> (d, len);
 }
 
 static void
-VAX_D_float_to_IEEE_little_float (float * /* d */, int /* len */)
+VAX_D_float_to_IEEE_little_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE little endian format");
 }
 
 static void
-VAX_G_float_to_IEEE_little_float (float * /* d */, int /* len */)
+VAX_G_float_to_IEEE_little_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE little endian format");
 }
 
 static void
-Cray_to_IEEE_little_float (float * /* d */, int /* len */)
+Cray_to_IEEE_little_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE little endian format");
 }
 
 static void
-IEEE_little_double_to_IEEE_big_double (double *d, int len)
+IEEE_little_double_to_IEEE_big_double (void *d, int len)
 {
-  swap_8_bytes (d, len);
+  swap_bytes<8> (d, len);
 }
 
 static void
-VAX_D_double_to_IEEE_big_double (double * /* d */, int /* len */)
+VAX_D_double_to_IEEE_big_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE big endian format");
 }
 
 static void
-VAX_G_double_to_IEEE_big_double (double * /* d */, int /* len */)
+VAX_G_double_to_IEEE_big_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE big endian format");
 }
 
 static void
-Cray_to_IEEE_big_double (double * /* d */, int /* len */)
+Cray_to_IEEE_big_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE big endian format");
 }
 
 static void
-IEEE_little_float_to_IEEE_big_float (float *d, int len)
+IEEE_little_float_to_IEEE_big_float (void *d, int len)
 {
-  swap_4_bytes (d, len);
+  swap_bytes<4> (d, len);
 }
 
 static void
-VAX_D_float_to_IEEE_big_float (float * /* d */, int /* len */)
+VAX_D_float_to_IEEE_big_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE big endian format");
 }
 
 static void
-VAX_G_float_to_IEEE_big_float (float * /* d */, int /* len */)
+VAX_G_float_to_IEEE_big_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE big endian format");
 }
 
 static void
-Cray_to_IEEE_big_float (float * /* d */, int /* len */)
+Cray_to_IEEE_big_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE big endian format");
 }
 
 static void
-IEEE_little_double_to_VAX_D_double (double * /* d */, int /* len */)
+IEEE_little_double_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX D");
 }
 
 static void
-IEEE_big_double_to_VAX_D_double (double * /* d */, int /* len */)
+IEEE_big_double_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX D");
 }
 
 static void
-VAX_G_double_to_VAX_D_double (double * /* d */, int /* len */)
+VAX_G_double_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX D");
 }
 
 static void
-Cray_to_VAX_D_double (double * /* d */, int /* len */)
+Cray_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "VAX D");
 }
 
 static void
-IEEE_little_float_to_VAX_D_float (float * /* d */, int /* len */)
+IEEE_little_float_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX D");
 }
 
 static void
-IEEE_big_float_to_VAX_D_float (float * /* d */, int /* len */)
+IEEE_big_float_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX D");
 }
 
 static void
-VAX_G_float_to_VAX_D_float (float * /* d */, int /* len */)
+VAX_G_float_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX D");
 }
 
 static void
-Cray_to_VAX_D_float (float * /* d */, int /* len */)
+Cray_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "VAX D");
 }
 
 static void
-IEEE_little_double_to_VAX_G_double (double * /* d */, int /* len */)
+IEEE_little_double_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX G");
 }
 
 static void
-IEEE_big_double_to_VAX_G_double (double * /* d */, int /* len */)
+IEEE_big_double_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX G");
 }
 
 static void
-VAX_D_double_to_VAX_G_double (double * /* d */, int /* len */)
+VAX_D_double_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "VAX G");
 }
 
 static void
-Cray_to_VAX_G_double (double * /* d */, int /* len */)
+Cray_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX G");
 }
 
 static void
-IEEE_little_float_to_VAX_G_float (float * /* d */, int /* len */)
+IEEE_little_float_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX G");
 }
 
 static void
-IEEE_big_float_to_VAX_G_float (float * /* d */, int /* len */)
+IEEE_big_float_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX G");
 }
 
 static void
-VAX_D_float_to_VAX_G_float (float * /* d */, int /* len */)
+VAX_D_float_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "VAX G");
 }
 
 static void
-Cray_to_VAX_G_float (float * /* d */, int /* len */)
+Cray_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX G");
 }
 
 void
-do_double_format_conversion (double *data, int len,
-			     oct_mach_info::float_format fmt)
+do_double_format_conversion (void *data, int len,
+			     oct_mach_info::float_format from_fmt,
+			     oct_mach_info::float_format to_fmt)
 {
-  switch (oct_mach_info::native_float_format ())
+  switch (to_fmt)
     {
     case oct_mach_info::flt_fmt_ieee_little_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  break;
@@ -473,7 +746,7 @@
       break;
 
     case oct_mach_info::flt_fmt_ieee_big_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_double_to_IEEE_big_double (data, len);
@@ -501,7 +774,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_d:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_double_to_VAX_D_double (data, len);
@@ -529,7 +802,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_g:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_double_to_VAX_G_double (data, len);
@@ -565,13 +838,14 @@
 }
 
 void
-do_float_format_conversion (float *data, int len,
-			    oct_mach_info::float_format fmt)
+do_float_format_conversion (void *data, int len,
+			    oct_mach_info::float_format from_fmt,
+			    oct_mach_info::float_format to_fmt)
 {
-  switch (oct_mach_info::native_float_format ())
+  switch (to_fmt)
     {
     case oct_mach_info::flt_fmt_ieee_little_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  break;
@@ -599,7 +873,7 @@
       break;
 
     case oct_mach_info::flt_fmt_ieee_big_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_float_to_IEEE_big_float (data, len);
@@ -627,7 +901,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_d:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_float_to_VAX_D_float (data, len);
@@ -655,7 +929,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_g:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_float_to_VAX_G_float (data, len);
@@ -691,8 +965,32 @@
 }
 
 void
+do_float_format_conversion (void *data, size_t sz, int len,
+			    oct_mach_info::float_format from_fmt,
+			    oct_mach_info::float_format to_fmt)
+{
+  switch (sz)
+    {
+    case sizeof (float):
+      do_float_format_conversion (data, len, from_fmt, to_fmt);
+      break;
+
+    case sizeof (double):
+      do_double_format_conversion (data, len, from_fmt, to_fmt);
+      break;
+
+    default:
+      (*current_liboctave_error_handler)
+	("impossible state reached in file `%s' at line %d",
+	 __FILE__, __LINE__);
+      break;
+    }
+}
+
+
+void
 read_doubles (std::istream& is, double *data, save_type type, int len,
-	      int swap, oct_mach_info::float_format fmt)
+	      bool swap, oct_mach_info::float_format fmt)
 {
   switch (type)
     {
@@ -724,7 +1022,7 @@
       {
 	volatile float *ptr = X_CAST (float *, data);
 	is.read (X_CAST (char *, data), 4 * len);
-	do_float_format_conversion (X_CAST (float *, data), len, fmt);
+	do_float_format_conversion (data, len, fmt);
 	float tmp = ptr[0];
 	for (int i = len - 1; i > 0; i--)
 	  data[i] = ptr[i];
--- a/liboctave/data-conv.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/liboctave/data-conv.h	Tue Aug 31 05:30:47 2004 +0000
@@ -66,23 +66,41 @@
 
   enum data_type
     {
-      dt_unknown,
-      dt_char,
-      dt_schar,
-      dt_uchar,
-      dt_short,
-      dt_ushort,
-      dt_int,
-      dt_uint,
-      dt_long,
-      dt_ulong,
-      dt_float,
-      dt_double,
-      dt_float_complex,
-      dt_double_complex
+      dt_int8      =  0,
+      dt_uint8     =  1,
+      dt_int16     =  2,
+      dt_uint16    =  3,
+      dt_int32     =  4,
+      dt_uint32    =  5,
+      dt_int64     =  6,
+      dt_uint64    =  7,
+      dt_single    =  8,
+      dt_double    =  9,
+      dt_char      = 10,
+      dt_schar     = 11,
+      dt_uchar     = 12,
+      dt_short     = 13,
+      dt_ushort    = 14,
+      dt_int       = 15,
+      dt_uint      = 16,
+      dt_long      = 17,
+      dt_ulong     = 18,
+      dt_longlong  = 19,
+      dt_ulonglong = 20,
+      dt_float     = 21,
+      dt_unknown   = 22 // Must be last, have largest value!
     };
 
   static data_type string_to_data_type (const std::string& s);
+
+  static void string_to_data_type (const std::string& s, int& block_size,
+				   data_type& input_type,
+				   data_type& output_type);
+
+  static void string_to_data_type (const std::string& s, int& block_size,
+				   data_type& output_type);
+
+  static std::string data_type_as_string (data_type dt);
 };
 
 // Add new entries to the end of this enum, otherwise Octave will not
@@ -104,16 +122,26 @@
   };
 
 extern void
-do_double_format_conversion (double *data, int len,
-			     oct_mach_info::float_format fmt);
+do_double_format_conversion (void *data, int len,
+			     oct_mach_info::float_format from_fmt,
+			     oct_mach_info::float_format to_fmt
+			       = oct_mach_info::native_float_format ());
 
 extern void
-do_float_format_conversion (float *data, int len,
-			    oct_mach_info::float_format fmt);
+do_float_format_conversion (void *data, int len,
+			    oct_mach_info::float_format from_fmt,
+			    oct_mach_info::float_format to_fmt
+			      = oct_mach_info::native_float_format ());
+
+extern void
+do_float_format_conversion (void *data, size_t sz, int len,
+			    oct_mach_info::float_format from_fmt,
+			    oct_mach_info::float_format to_fmt
+			      = oct_mach_info::native_float_format ());
 
 extern void
 read_doubles (std::istream& is, double *data, save_type type, int len,
-	      int swap, oct_mach_info::float_format fmt);
+	      bool swap, oct_mach_info::float_format fmt);
 extern void
 write_doubles (std::ostream& os, const double *data, save_type type, int len);
 
--- a/src/ChangeLog	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ChangeLog	Tue Aug 31 05:30:47 2004 +0000
@@ -1,3 +1,38 @@
+2004-08-31  John W. Eaton  <jwe@octave.org>
+
+	* ls-mat5.cc (read_int): New function.
+
+	* oct-stream.cc (octave_base_stream::do_read,
+	octave_base_stream::read, octave_base_stream::write): Delete.
+	* oct-stream.h: Delete decls.
+
+	* oct-stream.cc (octave_stream::read): Handle block_size and
+	separate input/output types.
+	(octave_stream::write): Handle block_size and various input types.
+	(octave_type_traits, octave_array_type_traits):	New traits classes.
+	(do_read): New templates to read data and perform type conversion.
+	(octave_stream::write (const Array<T>&, int,
+	oct_data_conv::data_type, int, oct_mach_info::float_format),
+	do_write, write_int):
+	New templates to write ints and perform type conversion.
+	Instantiate for various Octave types.
+
+	* ov.cc (octave_value::write): New function.
+	* ov.h: Provide decl.
+	* ov-base.cc (octave_base_value::write): New function.
+	* ov-base.h: Provide decl.
+	* ov-complex.h (octave_complex::write): New function.
+	* ov-cx-mat.h (octave_complex_matrix::write): New function.
+	* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::write): New function.
+	(OCTAVE_VALUE_INT_SCALAR_T::write): New function.
+	* ov-re-mat.h (octave_matrix::write): New function.
+	* ov-scalar.h (octave_scalar::write): New function.
+	* ov-str-mat.h (octave_char_matrix_str::write): New function.
+
+	* file-io.cc (Ffread): Handle block size, to/from format in
+	precision argument.
+	(Ffwrite): Handle block size in precision argument.
+
 2004-08-25  David Bateman  <dbateman@free.fr>
 
 	* ov-cell.cc (octave_cell::subsasgn): Delete elements of cell array
--- a/src/file-io.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/file-io.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -1129,8 +1129,12 @@
 
       if (! error_state)
 	{
-	  oct_data_conv::data_type dt
-	    = oct_data_conv::string_to_data_type (prec);
+	  int block_size = 1;
+	  oct_data_conv::data_type input_type;
+	  oct_data_conv::data_type output_type;
+
+	  oct_data_conv::string_to_data_type (prec, block_size,
+					      input_type, output_type);
 
 	  if (! error_state)
 	    {
@@ -1146,7 +1150,8 @@
 			= oct_mach_info::string_to_float_format (arch);
 
 		      if (! error_state)
-			retval = os.read (size, dt, skip, flt_fmt, count);
+			retval = os.read (size, block_size, input_type,
+					  output_type, skip, flt_fmt, count);
 		    }
 		  else
 		    ::error ("fread: architecture type must be a string");
@@ -1200,73 +1205,113 @@
 data to read and may be one of\n\
 \n\
 @table @code\n\
-@item \"char\"\n\
-@itemx \"char*1\"\n\
-@itemx \"integer*1\"\n\
-@itemx \"int8\"\n\
-Single character.\n\
-\n\
-@item \"signed char\"\n\
-@itemx \"schar\"\n\
+@item \"schar\"\n\
+@itemx \"signed char\"\n\
 Signed character.\n\
 \n\
-@item \"unsigned char\"\n\
-@itemx \"uchar\"\n\
-@itemx \"uint8\"\n\
+@item \"uchar\"\n\
+@itemx \"unsigned char\"\n\
 Unsigned character.\n\
 \n\
-@item \"short\"\n\
-Short integer.\n\
+@item \"int8\"\n\
+@itemx \"integer*1\"\n\
+\n\
+8-bit signed integer.\n\
 \n\
-@item \"unsigned short\"\n\
-@itemx \"ushort\"\n\
-Unsigned short integer.\n\
+@item \"int16\"\n\
+@itemx \"integer*2\"\n\
+16-bit signed integer.\n\
 \n\
-@item \"int\"\n\
-Integer.\n\
+@item \"int32\"\n\
+@itemx \"integer*4\"\n\
+32-bit signed integer.\n\
 \n\
-@item \"unsigned int\"\n\
-@itemx \"uint\"\n\
-Unsigned integer.\n\
+@item \"int64\"\n\
+@itemx \"integer*8\"\n\
+64-bit signed integer.\n\
+\n\
+@item \"uint8\"\n\
+8-bit unsigned integer.\n\
 \n\
-@item \"long\"\n\
-Long integer.\n\
+@item \"uint16\"\n\
+16-bit unsigned integer.\n\
 \n\
-@item \"unsigned long\"\n\
-@itemx \"ulong\"\n\
-Unsigned long integer.\n\
+@item \"uint32\"\n\
+32-bit unsigned integer.\n\
 \n\
-@item \"float\"\n\
+@item \"uint64\"\n\
+64-bit unsigned integer.\n\
+\n\
+@item \"single\"\n\
 @itemx \"float32\"\n\
 @itemx \"real*4\"\n\
-Single precision float.\n\
+32-bit floating point number.\n\
 \n\
 @item \"double\"\n\
 @itemx \"float64\"\n\
 @itemx \"real*8\"\n\
-Double precision float.\n\
+64-bit floating point number.\n\
+\n\
+@item \"char\"\n\
+@itemx \"char*1\"\n\
+Single character.\n\
 \n\
-@item \"integer*2\"\n\
-@itemx \"int16\"\n\
-Two byte signed integer.\n\
+@item \"short\"\n\
+Short integer (size is platform dependent).\n\
+\n\
+@item \"int\"\n\
+Integer (size is platform dependent).\n\
+\n\
+@item \"long\"\n\
+Long integer (size is platform dependent).\n\
 \n\
-@item \"integer*4\"\n\
-@itemx \"int32\"\n\
-Four byte signed integer.\n\
+@item \"ushort\"\n\
+@itemx \"unsigned short\"\n\
+Unsigned short integer (size is platform dependent).\n\
 \n\
-@item \"uint16\"\n\
-Two byte unsigned integer.\n\
+@item \"uint\"\n\
+@itemx \"unsigned int\"\n\
+Unsigned integer (size is platform dependent).\n\
 \n\
-@item \"uint32\"\n\
-Four byte unsigned integer.\n\
+@item \"ulong\"\n\
+@itemx \"unsigned long\"\n\
+Unsigned long integer (size is platform dependent).\n\
+\n\
+@item \"float\"\n\
+Single precision floating point number (size is platform dependent).\n\
 @end table\n\
 \n\
 @noindent\n\
 The default precision is @code{\"uchar\"}.\n\
 \n\
+The @var{precision} argument may also specify an optional repeat\n\
+count.  For example, @samp{32*single} causes @code{fread} to read\n\
+a block of 32 single precision floating point numbers.  Reading in\n\
+blocks is useful in combination with the @var{skip} argument.\n\
+\n\
+The @var{precision} argument may also specify a type conversion.\n\
+For example, @samp{int16=>int32} causes @code{fread} to read 16-bit\n\
+integer values and return an array of 32-bit integer values.  By\n\
+default, @code{fread} returns a double precision array.  The special\n\
+form @samp{*TYPE} is shorthand for @samp{TYPE=>TYPE}.\n\
+\n\
+The conversion and repeat counts may be combined.  For example,\n\
+@samp{32*single=>single} causes @code{fread} to read blocks of single\n\
+precision floating point values and return an array of single precision\n\
+values instead of the default array of double precision values.\n\
+\n\
 The optional argument @var{skip} specifies the number of bytes to skip\n\
-after each element is read.  If it is not specified, a value of 0 is\n\
-assumed.\n\
+after each element (or block of elements) is read.  If it is not\n\
+specified, a value of 0 is assumed.  If the final block read is not\n\
+complete, the final skip is omitted.  For example,\n\
+\n\
+@example\n\
+fread (f, 10, \"3*single=>single\", 8)\n\
+@end example\n\
+\n\
+@noindent\n\
+will omit the final 8-byte skip because the last read will not be\n\
+a complete block of 3 values.\n\
 \n\
 The optional argument @var{arch} is a string specifying the data format\n\
 for the file.  Valid values are\n\
@@ -1356,8 +1401,10 @@
 
   if (! error_state)
     {
-      oct_data_conv::data_type dt
-	= oct_data_conv::string_to_data_type (prec);
+      int block_size = 1;
+      oct_data_conv::data_type output_type;
+
+      oct_data_conv::string_to_data_type (prec, block_size, output_type);
 
       if (! error_state)
 	{
@@ -1373,7 +1420,8 @@
 		    = oct_mach_info::string_to_float_format (arch);
 
 		  if (! error_state)
-		    retval = os.write (data, dt, skip, flt_fmt);
+		    retval = os.write (data, block_size, output_type,
+				       skip, flt_fmt);
 		}
 	      else
 		::error ("fwrite: architecture type must be a string");
--- a/src/ls-mat4.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ls-mat4.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -155,11 +155,11 @@
 
   if (swap)
     {
-      swap_4_bytes (X_CAST (char *, &mopt));
-      swap_4_bytes (X_CAST (char *, &nr));
-      swap_4_bytes (X_CAST (char *, &nc));
-      swap_4_bytes (X_CAST (char *, &imag));
-      swap_4_bytes (X_CAST (char *, &len));
+      swap_bytes<4> (&mopt);
+      swap_bytes<4> (&nr);
+      swap_bytes<4> (&nc);
+      swap_bytes<4> (&imag);
+      swap_bytes<4> (&len);
     }
 
   if (mopt > 9999 || mopt < 0 || imag > 1 || imag < 0)
--- a/src/ls-mat5.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ls-mat5.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -172,7 +172,7 @@
     goto data_read_error;
 
   if (swap)
-    swap_4_bytes ((char *)&temp);
+    swap_bytes<4> (&temp);
 
   upper = (temp >> 16) & 0xffff;
   type = temp & 0xffff;
@@ -187,7 +187,7 @@
       if (! is.read (X_CAST (char *, &temp), 4 ))
 	goto data_read_error;
       if (swap)
-	swap_4_bytes ((char *)&temp);
+	swap_bytes<4> (&temp);
       bytes = temp;
     }
 
@@ -197,6 +197,15 @@
   return 1;
 }
 
+static void
+read_int (std::istream& is, bool swap, FOUR_BYTE_INT& val)
+{
+  is.read (reinterpret_cast<char *> (&val), 4);
+
+  if (swap)
+    swap_bytes<4> (&val);
+}
+
 // Extract one data element (scalar, matrix, string, etc.) from stream
 // IS and place it in TC, returning the name of the variable.
 //
@@ -378,7 +387,7 @@
 	  goto data_read_error;
 
 	if (swap)
-	  swap_4_bytes ((char *)&field_name_length);
+	  swap_bytes<4> (&field_name_length);
 
 	// field name subelement.  The length of this subelement tells
 	// us how many fields there are.
--- a/src/ls-oct-binary.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ls-oct-binary.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -153,7 +153,7 @@
   if (! is)
     return retval;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &name_len));
+    swap_bytes<4> (&name_len);
 
   {
     OCTAVE_LOCAL_BUFFER (char, name, name_len+1);
@@ -167,7 +167,7 @@
   if (! is)
     goto data_read_error;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &doc_len));
+    swap_bytes<4> (&doc_len);
 
   {
     OCTAVE_LOCAL_BUFFER (char, tdoc, doc_len+1);
@@ -213,7 +213,7 @@
 	if (! is.read (X_CAST (char *, &len), 4))
 	  goto data_read_error;
 	if (swap)
-	  swap_4_bytes (X_CAST (char *, &len));
+	  swap_bytes<4> (&len);
 	OCTAVE_LOCAL_BUFFER (char, s, len+1);
 	if (! is.read (X_CAST (char *, s), len))
 	  goto data_read_error;
@@ -240,7 +240,7 @@
 	if (! is.read (X_CAST (char *, &len), 4))
 	  goto data_read_error;
 	if (swap)
-	  swap_4_bytes (X_CAST (char *, &len));
+	  swap_bytes<4> (&len);
 	OCTAVE_LOCAL_BUFFER (char, s, len+1);
 	if (! is.read (X_CAST (char *, s), len))
 	  goto data_read_error;
--- a/src/oct-stream.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/oct-stream.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -31,6 +31,13 @@
 #include <fstream>
 #include <string>
 
+#include <Array.h>
+#include <Array2.h>
+#include <Array3.h>
+
+#include <Array.cc>
+
+#include "byte-swap.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-sstream.h"
@@ -1032,48 +1039,6 @@
   return do_gets (max_len, err, false, who);
 }
 
-octave_value
-octave_base_stream::read (const Array<double>& size,
-			  oct_data_conv::data_type dt, int skip,
-			  oct_mach_info::float_format ffmt,
-			  int& char_count)
-{
-  Matrix retval;
-
-  char_count = 0;
-
-  std::istream *isp = input_stream ();
-
-  if (isp)
-    {
-      std::istream& is = *isp;
-
-      int nr = -1;
-      int nc = -1;
-
-      bool ignore;
-
-      get_size (size, nr, nc, ignore, "fread");
-
-      if (! error_state)
-	{
-	  if (ffmt == oct_mach_info::flt_fmt_unknown)
-	    ffmt = float_format ();
-
-	  int tmp = retval.read (is, nr, nc, dt, skip, ffmt);
-
-	  if (tmp < 0)
-	    error ("fread: read error");
-	  else
-	    char_count = tmp;
-	}
-    }
-  else
-    invalid_operation ("fread", "reading");
-
-  return retval;
-}
-
 #if defined (__GNUG__) && ! defined (CXX_ISO_COMPLIANT_LIBRARY)
 
 #define OCTAVE_SCAN(is, fmt, arg) is.scan ((fmt).text, arg)
@@ -2092,49 +2057,6 @@
   return retval;
 }
 
-int
-octave_base_stream::write (const octave_value& data,
-			   oct_data_conv::data_type dt, int skip,
-			   oct_mach_info::float_format ffmt)
-{
-  int retval = -1;
-
-  std::ostream *osp = output_stream ();
-
-  if (osp)
-    {
-      std::ostream& os = *osp;
-
-      int status = 0;
-
-      // XXX FIXME XXX -- the octave_value class should probably have
-      // a write method that would handle the dispatch for us?
-      //
-      // If DATA is a character matrix, then it is a bit of a kluge to
-      // force it to be a double matrix and then write it out as uchar
-      // data, but this is the quick fix...
-
-      Matrix mval = data.matrix_value (true);
-
-      if (! error_state)
-	{
-	  if (ffmt == oct_mach_info::flt_fmt_unknown)
-	    ffmt = float_format ();
-
-	  status = mval.write (os, dt, skip, ffmt);
-
-	  if (status < 0)
-	    error ("fwrite: write error");
-	  else
-	    retval = status;
-	}
-    }
-  else
-    invalid_operation ("fwrite", "writing");
-
-  return retval;
-}
-
 class
 printf_value_cache
 {
@@ -2848,32 +2770,646 @@
     rep->close ();
 }
 
+// XXX FIXME XXX -- these trait classes probably belong somehwere else...
+
+template <typename T>
+class
+octave_type_traits
+{
+public:
+  typedef T val_type;
+};
+
+#define OCTAVE_TYPE_TRAIT(T, VAL_T) \
+  template <> \
+  class \
+  octave_type_traits<T> \
+  { \
+  public: \
+    typedef VAL_T val_type; \
+  }
+
+OCTAVE_TYPE_TRAIT (octave_int8, octave_int8::val_type);
+OCTAVE_TYPE_TRAIT (octave_uint8, octave_uint8::val_type);
+OCTAVE_TYPE_TRAIT (octave_int16, octave_int16::val_type);
+OCTAVE_TYPE_TRAIT (octave_uint16, octave_uint16::val_type);
+OCTAVE_TYPE_TRAIT (octave_int32, octave_int32::val_type);
+OCTAVE_TYPE_TRAIT (octave_uint32, octave_uint32::val_type);
+OCTAVE_TYPE_TRAIT (octave_int64, octave_int64::val_type);
+OCTAVE_TYPE_TRAIT (octave_uint64, octave_uint64::val_type);
+
+template <typename T>
+class octave_array_type_traits
+{
+public:
+  typedef T element_type;
+};
+
+#define OCTAVE_ARRAY_TYPE_TRAIT(T, ELT_T) \
+  template <> \
+  class \
+  octave_array_type_traits<T> \
+  { \
+  public: \
+    typedef ELT_T element_type; \
+  }
+
+OCTAVE_ARRAY_TYPE_TRAIT (charNDArray, char);
+OCTAVE_ARRAY_TYPE_TRAIT (int8NDArray, octave_int8);
+OCTAVE_ARRAY_TYPE_TRAIT (uint8NDArray, octave_uint8);
+OCTAVE_ARRAY_TYPE_TRAIT (int16NDArray, octave_int16);
+OCTAVE_ARRAY_TYPE_TRAIT (uint16NDArray, octave_uint16);
+OCTAVE_ARRAY_TYPE_TRAIT (int32NDArray, octave_int32);
+OCTAVE_ARRAY_TYPE_TRAIT (uint32NDArray, octave_uint32);
+OCTAVE_ARRAY_TYPE_TRAIT (int64NDArray, octave_int64);
+OCTAVE_ARRAY_TYPE_TRAIT (uint64NDArray, octave_uint64);
+OCTAVE_ARRAY_TYPE_TRAIT (NDArray, double);
+
+template <class RET_T, class READ_T>
 octave_value
-octave_stream::read (const Array<double>& size,
-		     oct_data_conv::data_type dt, int skip,
-		     oct_mach_info::float_format flt_fmt, int& count)
+do_read (octave_stream& strm, int nr, int nc, int block_size,
+	 int skip, bool do_float_fmt_conv,
+	 oct_mach_info::float_format from_flt_fmt, int& count)
 {
   octave_value retval;
 
+  RET_T nda;
+
+  bool ok = true;
+
+  count = 0;
+
+  typename octave_array_type_traits<RET_T>::element_type elt_zero
+    = typename octave_array_type_traits<RET_T>::element_type ();
+
+  typename octave_array_type_traits<RET_T>::element_type *dat = 0;
+
+  int max_size = 0;
+
+  int final_nr = 0;
+  int final_nc = 0;
+
+  if (nr > 0)
+    {
+      if (nc > 0)
+	{
+	  nda.resize (dim_vector (nr, nc), elt_zero);
+	  dat = nda.fortran_vec ();
+	  max_size = nr * nc;
+	}
+      else
+	{
+	  nda.resize (dim_vector (nr, 32), elt_zero);
+	  dat = nda.fortran_vec ();
+	  max_size = nr * 32;
+	}
+    }
+  else
+    {
+      nda.resize (dim_vector (32, 1), elt_zero);
+      dat = nda.fortran_vec ();
+      max_size = 32;
+    }
+
+  // XXX FIXME XXX -- byte order for Cray?
+
+  bool swap = false;
+
+  if (oct_mach_info::words_big_endian ())
+    swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
+	    || from_flt_fmt == oct_mach_info::flt_fmt_vax_g
+	    || from_flt_fmt == oct_mach_info::flt_fmt_vax_g);
+  else
+    swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
+
+  union
+  {
+    char buf[sizeof (typename octave_type_traits<READ_T>::val_type)];
+    typename octave_type_traits<READ_T>::val_type val;
+  } u;
+
+  std::istream *isp = strm.input_stream ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      int elts_read = 0;
+
+      for (;;)
+	{
+	  // XXX FIXME XXX -- maybe there should be a special case for
+	  // skip == 0.
+
+	  if (is)
+	    {
+	      if (nr > 0 && nc > 0 && count == max_size)
+		{
+		  final_nr = nr;
+		  final_nc = nc;
+
+		  break;
+		}
+
+	      is.read (u.buf, sizeof (typename octave_type_traits<READ_T>::val_type));
+
+	      // We only swap bytes for integer types.  For float
+	      // types, the format conversion will also handle byte
+	      // swapping.
+
+	      if (swap)
+		swap_bytes<sizeof (typename octave_type_traits<READ_T>::val_type)> (u.buf);
+	      else if (do_float_fmt_conv)
+		do_float_format_conversion
+		  (u.buf,
+		   sizeof (typename octave_type_traits<READ_T>::val_type),
+		   1, from_flt_fmt, oct_mach_info::float_format ());
+
+	      typename octave_array_type_traits<RET_T>::element_type tmp
+		= static_cast <typename octave_array_type_traits<RET_T>::element_type> (u.val);
+
+	      if (ok)
+		{
+		  if (is)
+		    {
+		      if (count == max_size)
+			{
+			  max_size *= 2;
+
+			  if (nr > 0)
+			    nda.resize (dim_vector (nr, max_size / nr),
+					elt_zero);
+			  else
+			    nda.resize (dim_vector (max_size, 1), elt_zero);
+
+			  dat = nda.fortran_vec ();
+			}
+
+		      dat[count++] = tmp;
+
+		      elts_read++;
+		    }
+
+		  if (skip != 0 && elts_read == block_size)
+		    {
+		      strm.seek (skip, SEEK_CUR);
+		      elts_read = 0;
+		    }
+
+		  if (is.eof ())
+		    {
+		      if (nr > 0)
+			{
+			  if (count > nr)
+			    {
+			      final_nr = nr;
+			      final_nc = (count - 1) / nr + 1;
+			    }
+			  else
+			    {
+			      final_nr = count;
+			      final_nc = 1;
+			    }
+			}
+		      else
+			{
+			  final_nr = count;
+			  final_nc = 1;
+			}
+
+		      break;
+		    }
+		}
+	      else
+		{
+		  ok = false;
+		  break;
+		}
+	    }
+	  else
+	    {
+	      ok = false;
+	      break;
+	    }
+	}
+    }
+
+  if (ok)
+    {
+      nda.resize (dim_vector (final_nr, final_nc), elt_zero);
+
+      retval = nda;
+    }
+
+  return retval;
+}
+
+#define DO_READ_VAL_TEMPLATE(RET_T, READ_T) \
+  template octave_value \
+  do_read<RET_T, READ_T> (octave_stream&, int, int, int, int, bool, \
+			  oct_mach_info::float_format, int&)
+
+// XXX FIXME XXX -- should we only have float if it is a different
+// size from double?
+
+#define INSTANTIATE_DO_READ(VAL_T) \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int8); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint8); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int16); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint16); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int32); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint32); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int64); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint64); \
+  DO_READ_VAL_TEMPLATE (VAL_T, float); \
+  DO_READ_VAL_TEMPLATE (VAL_T, double); \
+  DO_READ_VAL_TEMPLATE (VAL_T, char); \
+  DO_READ_VAL_TEMPLATE (VAL_T, signed char); \
+  DO_READ_VAL_TEMPLATE (VAL_T, unsigned char)
+
+INSTANTIATE_DO_READ(int8NDArray);
+INSTANTIATE_DO_READ(uint8NDArray);
+INSTANTIATE_DO_READ(int16NDArray);
+INSTANTIATE_DO_READ(uint16NDArray);
+INSTANTIATE_DO_READ(int32NDArray);
+INSTANTIATE_DO_READ(uint32NDArray);
+INSTANTIATE_DO_READ(int64NDArray);
+INSTANTIATE_DO_READ(uint64NDArray);
+// INSTANTIATE_DO_READ(floatNDArray);
+INSTANTIATE_DO_READ(NDArray);
+INSTANTIATE_DO_READ(charNDArray);
+
+typedef octave_value (*read_fptr) (octave_stream&, int, int, int, int, bool,
+				   oct_mach_info::float_format ffmt, int&);
+
+INSTANTIATE_ARRAY (read_fptr);
+template class Array2<read_fptr>;
+
+#define FILL_TABLE_ROW(R, VAL_T) \
+  read_fptr_table(R,oct_data_conv::dt_int8) = do_read<VAL_T, octave_int8>; \
+  read_fptr_table(R,oct_data_conv::dt_uint8) = do_read<VAL_T, octave_uint8>; \
+  read_fptr_table(R,oct_data_conv::dt_int16) = do_read<VAL_T, octave_int16>; \
+  read_fptr_table(R,oct_data_conv::dt_uint16) = do_read<VAL_T, octave_uint16>; \
+  read_fptr_table(R,oct_data_conv::dt_int32) = do_read<VAL_T, octave_int32>; \
+  read_fptr_table(R,oct_data_conv::dt_uint32) = do_read<VAL_T, octave_uint32>; \
+  read_fptr_table(R,oct_data_conv::dt_int64) = do_read<VAL_T, octave_int64>; \
+  read_fptr_table(R,oct_data_conv::dt_uint64) = do_read<VAL_T, octave_uint64>; \
+  read_fptr_table(R,oct_data_conv::dt_single) = do_read<VAL_T, float>; \
+  read_fptr_table(R,oct_data_conv::dt_double) = do_read<VAL_T, double>; \
+  read_fptr_table(R,oct_data_conv::dt_char) = do_read<VAL_T, char>; \
+  read_fptr_table(R,oct_data_conv::dt_schar) = do_read<VAL_T, signed char>; \
+  read_fptr_table(R,oct_data_conv::dt_uchar) = do_read<VAL_T, unsigned char>
+
+octave_value
+octave_stream::read (const Array<double>& size, int block_size,
+		     oct_data_conv::data_type input_type,
+		     oct_data_conv::data_type output_type,
+		     int skip, oct_mach_info::float_format ffmt,
+		     int& char_count)
+{
+  static bool initialized = false;
+
+  // Table function pointers for return types x read types.
+
+  static Array2<read_fptr> read_fptr_table (oct_data_conv::dt_unknown, 13, 0);
+
+  if (! initialized)
+    {
+      FILL_TABLE_ROW (oct_data_conv::dt_int8, int8NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint8, uint8NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_int16, int16NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint16, uint16NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_int32, int32NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint32, uint32NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_int64, int64NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint64, uint64NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_double, NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_char, charNDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_schar, charNDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uchar, charNDArray);
+
+      initialized = true;
+    }
+
+  octave_value retval;
+
   if (stream_ok ("fread"))
-    retval = rep->read (size, dt, skip, flt_fmt, count);
+    {
+      // XXX FIXME XXX -- we may eventually want to make this extensible.
+
+      // XXX FIXME XXX -- we need a better way to ensure that this
+      // numbering stays consistent with the order of the elements in the
+      // data_type enum in the oct_data_conv class.
+
+      char_count = 0;
+
+      int nr = -1;
+      int nc = -1;
+
+      bool ignore;
+
+      get_size (size, nr, nc, ignore, "fread");
+
+      if (! error_state)
+	{
+	  if (nr == 0 || nc == 0)
+	    retval = Matrix (nr, nc);
+	  else
+	    {
+	      if (ffmt == oct_mach_info::flt_fmt_unknown)
+		ffmt = float_format ();
+
+	      read_fptr fcn = read_fptr_table (output_type, input_type);
+
+	      bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double
+					 || input_type == oct_data_conv::dt_single)
+					&& ffmt != float_format ());
+
+	      if (fcn)
+		{
+		  retval = (*fcn) (*this, nr, nc, block_size, skip,
+				   do_float_fmt_conv, ffmt, char_count);
+
+		  // XXX FIXME XXX -- kluge!
+
+		  if (! error_state
+		      && (output_type == oct_data_conv::dt_char
+			  || output_type == oct_data_conv::dt_schar
+			  || output_type == oct_data_conv::dt_uchar))
+		    retval = octave_value (retval.char_matrix_value (), true);
+		}
+	      else
+		error ("fread: unable to read and convert requested types");
+	    }
+	}
+      else
+	invalid_operation ("fread", "reading");
+    }
 
   return retval;
 }
 
 int
-octave_stream::write (const octave_value& data,
-		      oct_data_conv::data_type dt, int skip,
+octave_stream::write (const octave_value& data, int block_size,
+		      oct_data_conv::data_type output_type, int skip,
 		      oct_mach_info::float_format flt_fmt)
 {
   int retval = -1;
 
   if (stream_ok ("fwrite"))
-    retval = rep->write (data, dt, skip, flt_fmt);
+    {
+      if (! error_state)
+	{
+	  if (flt_fmt == oct_mach_info::flt_fmt_unknown)
+	    flt_fmt = float_format ();
+
+	  int status = data.write (*this, block_size, output_type,
+				   skip, flt_fmt);
+
+	  if (status < 0)
+	    error ("fwrite: write error");
+	  else
+	    retval = status;
+	}
+      else
+	invalid_operation ("fwrite", "writing");
+    }
 
   return retval;
 }
 
+template <class T>
+void
+write_int (std::ostream& os, bool swap, const T& val)
+{
+  typename octave_type_traits<T>::val_type tmp = val.value ();
+
+  if (swap)
+    swap_bytes<sizeof (typename octave_type_traits<T>::val_type)> (&tmp);
+
+  os.write (reinterpret_cast<const char *> (&tmp),
+	    sizeof (typename octave_type_traits<T>::val_type));
+}
+
+template void write_int (std::ostream&, bool, const octave_int8&);
+template void write_int (std::ostream&, bool, const octave_uint8&);
+template void write_int (std::ostream&, bool, const octave_int16&);
+template void write_int (std::ostream&, bool, const octave_uint16&);
+template void write_int (std::ostream&, bool, const octave_int32&);
+template void write_int (std::ostream&, bool, const octave_uint32&);
+template void write_int (std::ostream&, bool, const octave_int64&);
+template void write_int (std::ostream&, bool, const octave_uint64&);
+
+template <class T>
+static inline bool
+do_write (std::ostream& os, const T& val, oct_data_conv::data_type output_type,
+	  oct_mach_info::float_format flt_fmt, bool swap,
+	  bool do_float_conversion)
+{
+  bool retval = true;
+
+  // For compatibility, Octave converts to the output type, then
+  // writes.  This means that truncation happens on the conversion.
+  // For example, the following program prints 0:
+  //
+  //   x = int8 (-1)
+  //   f = fopen ("foo.dat", "w");
+  //   fwrite (f, x, "unsigned char");
+  //   fclose (f);
+  //   f = fopen ("foo.dat", "r");
+  //   y = fread (f, 1, "unsigned char");
+  //   printf ("%d\n", y);
+
+  switch (output_type)
+    {
+    case oct_data_conv::dt_char:
+    case oct_data_conv::dt_schar:
+    case oct_data_conv::dt_int8:
+      write_int (os, swap, octave_int8 (val));
+      break;
+
+    case oct_data_conv::dt_uchar:
+    case oct_data_conv::dt_uint8:
+      write_int (os, swap, octave_uint8 (val));
+      break;
+
+    case oct_data_conv::dt_int16:
+      write_int (os, swap, octave_int16 (val));
+      break;
+
+    case oct_data_conv::dt_uint16:
+      write_int (os, swap, octave_uint16 (val));
+      break;
+
+    case oct_data_conv::dt_int32:
+      write_int (os, swap, octave_int32 (val));
+      break;
+
+    case oct_data_conv::dt_uint32:
+      write_int (os, swap, octave_uint32 (val));
+      break;
+
+    case oct_data_conv::dt_int64:
+      write_int (os, swap, octave_int64 (val));
+      break;
+
+    case oct_data_conv::dt_uint64:
+      write_int (os, swap, octave_uint64 (val));
+      break;
+
+    case oct_data_conv::dt_single:
+      {
+	float f = static_cast<float> (val);
+
+	if (do_float_conversion)
+	  do_float_format_conversion (&f, 1, flt_fmt);
+
+	os.write (reinterpret_cast<const char *> (&f), sizeof (float));
+      }
+      break;
+
+    case oct_data_conv::dt_double:
+      {
+	double d = static_cast<double> (val);
+	if (do_float_conversion)
+	  do_double_format_conversion (&d, 1, flt_fmt);
+
+	os.write (reinterpret_cast<const char *> (&d), sizeof (double));
+      }
+      break;
+
+    default:
+      retval = false;
+      (*current_liboctave_error_handler)
+	("write: invalid type specification");
+      break;
+    }
+
+  return retval;
+}
+
+template <class T>
+int
+octave_stream::write (const Array<T>& data, int block_size,
+		      oct_data_conv::data_type output_type,
+		      int skip, oct_mach_info::float_format flt_fmt)
+{
+  int retval = -1;
+
+  bool status = true;
+
+  int count = 0;
+
+  const T *d = data.data ();
+
+  int n = data.length ();
+
+  oct_mach_info::float_format native_flt_fmt
+    = oct_mach_info::float_format ();
+
+  bool do_float_conversion = (flt_fmt != native_flt_fmt);
+
+  // XXX FIXME XXX -- byte order for Cray?
+
+  bool swap = false;
+
+  if (oct_mach_info::words_big_endian ())
+    swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
+	    || flt_fmt == oct_mach_info::flt_fmt_vax_g
+	    || flt_fmt == oct_mach_info::flt_fmt_vax_g);
+  else
+    swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
+
+  for (int i = 0; i < n; i++)
+    {
+      std::ostream *osp = output_stream ();
+
+      if (osp)
+	{
+	  std::ostream& os = *osp;
+
+	  if (skip != 0 && (i % block_size) == 0)
+	    seek (skip, SEEK_CUR);
+
+	  if (os)
+	    {
+	      status = do_write (os, d[i], output_type, flt_fmt, swap,
+				 do_float_conversion);
+
+	      if (os && status)
+		count++;
+	      else
+		break;
+	    }
+	  else
+	    {
+	      status = false;
+	      break;
+	    }
+	}
+      else
+	{
+	  status = false;
+	  break;
+	}
+    }
+
+  if (status)
+    retval = count;
+
+  return retval;
+}
+
+template int
+octave_stream::write (const Array<char>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<double>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_int8>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_uint8>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_int16>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_uint16>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_int32>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_uint32>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_int64>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
+template int
+octave_stream::write (const Array<octave_uint64>&, int,
+		      oct_data_conv::data_type,
+		      int, oct_mach_info::float_format);
+
 octave_value
 octave_stream::scanf (const std::string& fmt, const Array<double>& size,
 		      int& count, const std::string& who)
--- a/src/oct-stream.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/oct-stream.h	Tue Aug 31 05:30:47 2004 +0000
@@ -432,14 +432,6 @@
   std::string getl (int max_len, bool& err, const std::string& who /* = "getl" */);
   std::string gets (int max_len, bool& err, const std::string& who /* = "gets" */);
 
-  octave_value do_read (int nr, int nc, oct_data_conv::data_type dt,
-			int skip, oct_mach_info::float_format flt_fmt,
-			int& count);
-
-  octave_value read (const Array<double>& size, oct_data_conv::data_type dt,
-		     int skip, oct_mach_info::float_format flt_fmt,
-		     int& count);
-
   octave_value do_scanf (scanf_format_list& fmt_list, int nr, int nc,
 			 bool one_elt_size_spec, int& count,
 			 const std::string& who /* = "scanf" */);
@@ -458,9 +450,6 @@
 
   int flush (void);
 
-  int write (const octave_value& data, oct_data_conv::data_type dt,
-	     int skip, oct_mach_info::float_format flt_fmt);
-
   int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
 		 const std::string& who /* = "printf" */);
 
@@ -517,11 +506,19 @@
 
   void close (void);
 
-  octave_value read (const Array<double>& size, oct_data_conv::data_type dt,
+  octave_value read (const Array<double>& size, int block_size,
+		     oct_data_conv::data_type input_type,
+		     oct_data_conv::data_type output_type,
 		     int skip, oct_mach_info::float_format flt_fmt,
 		     int& count);
 
-  int write (const octave_value& data, oct_data_conv::data_type dt,
+  int write (const octave_value& data, int block_size,
+	     oct_data_conv::data_type output_type,
+	     int skip, oct_mach_info::float_format flt_fmt);
+
+  template <class T>
+  int write (const Array<T>&, int block_size,
+	     oct_data_conv::data_type output_type,
 	     int skip, oct_mach_info::float_format flt_fmt);
 
   octave_value scanf (const std::string& fmt, const Array<double>& size,
@@ -602,6 +599,12 @@
 
       return retval;
     }
+
+  void invalid_operation (const std::string& who, const char *rw)
+    {
+      if (rep)
+	rep->invalid_operation (who, rw);
+    }
 };
 
 class
--- a/src/ov-base-int.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-base-int.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -42,6 +42,7 @@
 #include "gripes.h"
 #include "oct-obj.h"
 #include "oct-lvalue.h"
+#include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
 #include "ov-base-mat.h"
@@ -158,7 +159,7 @@
   if (! is.read (X_CAST (char *, &mdims), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &mdims));
+    swap_bytes<4> (&mdims);
   if (mdims >= 0)
     return false;
 
@@ -172,7 +173,7 @@
       if (! is.read (X_CAST (char *, &di), 4))
 	return false;
       if (swap)
-	swap_4_bytes (X_CAST (char *, &di));
+	swap_bytes<4> (&di);
       dv(i) = di;
     }
 
@@ -189,13 +190,13 @@
 	switch (bytes)
 	  {
 	  case 8:
-	    swap_8_bytes (X_CAST (char *, &m(i)));
+	    swap_bytes<8> (&m(i));
 	    break;
 	  case 4:
-	    swap_4_bytes (X_CAST (char *, &m(i)));
+	    swap_bytes<4> (&m(i));
 	    break;
 	  case 2:
-	    swap_2_bytes (X_CAST (char *, &m(i)));
+	    swap_bytes<2> (&m(i));
 	    break;
 	  case 1:
 	  default:
@@ -361,13 +362,13 @@
     switch (this->byte_size())
       {
       case 8:
-	swap_8_bytes (X_CAST (char *, &tmp));
+	swap_bytes<8> (&tmp);
 	break;
       case 4:
-	swap_4_bytes (X_CAST (char *, &tmp));
+	swap_bytes<4> (&tmp);
 	break;
       case 2:
-	swap_2_bytes (X_CAST (char *, &tmp));
+	swap_bytes<2> (&tmp);
 	break;
       case 1:
       default:
@@ -378,6 +379,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 template <class T>
 bool
 octave_base_int_scalar<T>::save_hdf5 (hid_t loc_id, const char *name, bool)
@@ -438,6 +440,7 @@
 
   return true;
 }
+
 #endif
 
 /*
--- a/src/ov-base.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-base.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -725,6 +725,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_base_value::save_hdf5 (hid_t, const char *, bool)
 {
@@ -740,8 +741,18 @@
 
   return false;
 }
+
 #endif
 
+int
+octave_base_value::write (octave_stream&, int, oct_data_conv::data_type,
+			  int, oct_mach_info::float_format) const
+{
+  gripe_wrong_type_arg ("octave_base_value::write()", type_name ());
+
+  return false;
+}
+
 CONVDECLX (matrix_conv)
 {
   return new octave_matrix ();
--- a/src/ov-base.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-base.h	Tue Aug 31 05:30:47 2004 +0000
@@ -308,6 +308,10 @@
   bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug);
 #endif
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const;
+
 private:
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
--- a/src/ov-bool-mat.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-bool-mat.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -304,7 +304,7 @@
   if (! is.read (X_CAST (char *, &mdims), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &mdims));
+    swap_bytes<4> (&mdims);
   if (mdims >= 0)
     return false;
 
@@ -321,7 +321,7 @@
       if (! is.read (X_CAST (char *, &di), 4))
 	return false;
       if (swap)
-	swap_4_bytes (X_CAST (char *, &di));
+	swap_bytes<4> (&di);
       dv(i) = di;
     }
   
@@ -339,6 +339,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_bool_matrix::save_hdf5 (hid_t loc_id, const char *name,
 			       bool /* save_as_floats */)
@@ -447,6 +448,7 @@
 
   return retval;
 }
+
 #endif
 
 /*
--- a/src/ov-bool.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-bool.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -162,6 +162,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_bool::save_hdf5 (hid_t loc_id, const char *name,
 			bool /* save_as_floats */)
@@ -220,6 +221,7 @@
 
   return true;
 }
+
 #endif
 
 /*
--- a/src/ov-cell.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-cell.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -634,7 +634,7 @@
   if (! is.read (X_CAST (char *, &mdims), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &mdims));
+    swap_bytes<4> (&mdims);
   if (mdims >= 0)
     return false;
 
@@ -648,7 +648,7 @@
       if (! is.read (X_CAST (char *, &di), 4))
 	return false;
       if (swap)
-	swap_4_bytes (X_CAST (char *, &di));
+	swap_bytes<4> (&di);
       dv(i) = di;
     }
   
--- a/src/ov-complex.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-complex.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -33,6 +33,7 @@
 #include "lo-ieee.h"
 
 #include "oct-obj.h"
+#include "oct-stream.h"
 #include "ops.h"
 #include "ov-complex.h"
 #include "ov-base.h"
@@ -236,6 +237,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_complex::save_hdf5 (hid_t loc_id, const char *name,
 			   bool /* save_as_floats */)
@@ -317,6 +319,7 @@
 
   return retval;
 }
+
 #endif
 
 /*
--- a/src/ov-complex.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-complex.h	Tue Aug 31 05:30:47 2004 +0000
@@ -96,7 +96,14 @@
   NDArray array_value (bool = false) const;
 
   octave_value resize (const dim_vector& dv) const
-    { ComplexNDArray retval (dv); if (dv.numel()) retval(0) = scalar; return retval; }
+    {
+      ComplexNDArray retval (dv);
+
+      if (dv.numel ())
+	retval(0) = scalar;
+
+      return retval;
+    }
 
   Complex complex_value (bool = false) const;
 
@@ -124,6 +131,15 @@
   bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug);
 #endif
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const
+    {
+      // Yes, for compatibility, we drop the imaginary part here.
+      return os.write (array_value (true), block_size, output_type,
+		       skip, flt_fmt);
+    }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
--- a/src/ov-cx-mat.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-cx-mat.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -31,11 +31,14 @@
 #include <iostream>
 #include <vector>
 
+#include "data-conv.h"
 #include "lo-ieee.h"
 #include "mx-base.h"
+#include "mach-info.h"
 
 #include "gripes.h"
 #include "oct-obj.h"
+#include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
 #include "ov-base-mat.h"
@@ -392,7 +395,7 @@
   if (! is.read (X_CAST (char *, &mdims), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &mdims));
+    swap_bytes<4> (&mdims);
   if (mdims < 0)
     {
       mdims = - mdims;
@@ -405,7 +408,7 @@
 	  if (! is.read (X_CAST (char *, &di), 4))
 	    return false;
 	  if (swap)
-	    swap_4_bytes (X_CAST (char *, &di));
+	    swap_bytes<4> (&di);
 	  dv(i) = di;
 	}
 
@@ -427,7 +430,7 @@
       if (! is.read (X_CAST (char *, &nc), 4))
 	return false;
       if (swap)
-	swap_4_bytes (X_CAST (char *, &nc));
+	swap_bytes<4> (&nc);
       if (! is.read (X_CAST (char *, &tmp), 1))
 	return false;
       ComplexMatrix m (nr, nc);
@@ -443,6 +446,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_complex_matrix::save_hdf5 (hid_t loc_id, const char *name,
 				  bool save_as_floats)
@@ -598,6 +602,7 @@
 
   return retval;
 }
+
 #endif
 
 void
--- a/src/ov-cx-mat.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-cx-mat.h	Tue Aug 31 05:30:47 2004 +0000
@@ -37,6 +37,7 @@
 #include "str-vec.h"
 
 #include "error.h"
+#include "oct-stream.h"
 #include "ov-base.h"
 #include "ov-base-mat.h"
 #include "ov-typeinfo.h"
@@ -127,6 +128,15 @@
   bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug);
 #endif
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const
+    {
+      // Yes, for compatibility, we drop the imaginary part here.
+      return os.write (matrix_value (true), block_size, output_type,
+		       skip, flt_fmt);
+    }
+
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
 private:
--- a/src/ov-intx.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-intx.h	Tue Aug 31 05:30:47 2004 +0000
@@ -31,6 +31,7 @@
 #include "str-vec.h"
 
 #include "error.h"
+#include "oct-stream.h"
 #include "ov-base.h"
 #include "ov-base-int.h"
 #include "ov-typeinfo.h"
@@ -73,6 +74,11 @@
 
   idx_vector index_vector (void) const { return idx_vector (matrix); }
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const
+    { return os.write (matrix, block_size, output_type, skip, flt_fmt); }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
@@ -123,6 +129,14 @@
 
   idx_vector index_vector (void) const { return idx_vector (scalar); }
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const
+    {
+      return os.write (OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION (),
+		       block_size, output_type, skip, flt_fmt);
+    }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
--- a/src/ov-list.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-list.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -623,7 +623,7 @@
   if (! is.read (X_CAST (char *, &len), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &len));
+    swap_bytes<4> (&len);
 
   if (len > 0)
     {
@@ -663,6 +663,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_list::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
 {
@@ -727,6 +728,7 @@
   
   return retval;
 }
+
 #endif
 
 /*
--- a/src/ov-range.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-range.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -342,21 +342,22 @@
   if (! is.read (X_CAST (char *, &bas), 8))
     return false;
   if (swap)
-    swap_8_bytes (X_CAST (char *, &bas));
+    swap_bytes<8> (&bas);
   if (! is.read (X_CAST (char *, &lim), 8))
     return false;
   if (swap)
-    swap_8_bytes (X_CAST (char *, &lim));
+    swap_bytes<8> (&lim);
   if (! is.read (X_CAST (char *, &inc), 8))
     return false;
   if (swap)
-    swap_8_bytes (X_CAST (char *, &inc));
+    swap_bytes<8> (&inc);
   Range r (bas, lim, inc);
   range = r;
   return true;
 }
 
 #if defined (HAVE_HDF5)
+
 // The following subroutines creates an HDF5 representation of the way
 // we will store Octave range types (triplets of floating-point numbers). 
 // NUM_TYPE is the HDF5 numeric type to use for storage (e.g. 
@@ -461,6 +462,7 @@
 
   return retval;
 }
+
 #endif
 
 /*
--- a/src/ov-re-mat.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-re-mat.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -33,8 +33,10 @@
 #include <iostream>
 #include <vector>
 
+#include "data-conv.h"
 #include "lo-ieee.h"
 #include "lo-utils.h"
+#include "mach-info.h"
 #include "mx-base.h"
 #include "quit.h"
 
@@ -42,6 +44,7 @@
 #include "gripes.h"
 #include "oct-obj.h"
 #include "oct-lvalue.h"
+#include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
 #include "ov-base-mat.h"
@@ -446,7 +449,7 @@
   if (! is.read (X_CAST (char *, &mdims), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &mdims));
+    swap_bytes<4> (&mdims);
   if (mdims < 0)
     {
       mdims = - mdims;
@@ -459,7 +462,7 @@
 	  if (! is.read (X_CAST (char *, &di), 4))
 	    return false;
 	  if (swap)
-	    swap_4_bytes (X_CAST (char *, &di));
+	    swap_bytes<4> (&di);
 	  dv(i) = di;
 	}
 
@@ -480,7 +483,7 @@
       if (! is.read (X_CAST (char *, &nc), 4))
 	return false;
       if (swap)
-	swap_4_bytes (X_CAST (char *, &nc));
+	swap_bytes<4> (&nc);
       if (! is.read (X_CAST (char *, &tmp), 1))
 	return false;
       Matrix m (nr, nc);
@@ -495,6 +498,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_matrix::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
 {
@@ -618,6 +622,7 @@
 
   return retval;
 }
+
 #endif
 
 void
--- a/src/ov-re-mat.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-re-mat.h	Tue Aug 31 05:30:47 2004 +0000
@@ -38,6 +38,7 @@
 #include "str-vec.h"
 
 #include "error.h"
+#include "oct-stream.h"
 #include "ov-base.h"
 #include "ov-base-mat.h"
 #include "ov-typeinfo.h"
@@ -136,6 +137,11 @@
   bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug);
 #endif
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const
+    { return os.write (matrix, block_size, output_type, skip, flt_fmt); }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
--- a/src/ov-scalar.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-scalar.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -30,9 +30,13 @@
 
 #include <iostream>
 
+#include "data-conv.h"
+#include "mach-info.h"
+
 #include "defun.h"
 #include "gripes.h"
 #include "oct-obj.h"
+#include "oct-stream.h"
 #include "ov-scalar.h"
 #include "ov-base.h"
 #include "ov-base-scalar.h"
@@ -208,6 +212,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_scalar::save_hdf5 (hid_t loc_id, const char *name,
 			  bool /* save_as_floats */)
@@ -266,6 +271,7 @@
 
   return true;
 }
+
 #endif
 
 /*
--- a/src/ov-scalar.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-scalar.h	Tue Aug 31 05:30:47 2004 +0000
@@ -98,7 +98,14 @@
     { return NDArray (dim_vector (1, 1), scalar); }
 
   octave_value resize (const dim_vector& dv) const
-    { NDArray retval (dv); if (dv.numel()) retval(0) = scalar; return retval; }
+    {
+      NDArray retval (dv);
+
+      if (dv.numel ())
+	retval(0) = scalar;
+
+      return retval;
+    }
 
   Complex complex_value (bool = false) const { return scalar; }
 
@@ -134,6 +141,14 @@
   bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug);
 #endif
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const
+    {
+      return os.write (array_value (), block_size, output_type,
+		       skip, flt_fmt);
+    }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
--- a/src/ov-str-mat.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-str-mat.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -31,10 +31,13 @@
 #include <iostream>
 #include <vector>
 
+#include "data-conv.h"
 #include "lo-ieee.h"
+#include "mach-info.h"
 #include "mx-base.h"
 
 #include "oct-obj.h"
+#include "oct-stream.h"
 #include "ops.h"
 #include "ov-re-mat.h"
 #include "ov-str-mat.h"
@@ -438,7 +441,7 @@
   if (! is.read (X_CAST (char *, &elements), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &elements));
+    swap_bytes<4> (&elements);
 
   if (elements < 0)
     {
@@ -452,7 +455,7 @@
 	  if (! is.read (X_CAST (char *, &di), 4))
 	    return false;
 	  if (swap)
-	    swap_4_bytes (X_CAST (char *, &di));
+	    swap_bytes<4> (&di);
 	  dv(i) = di;
 	}
       
@@ -474,7 +477,7 @@
 	  if (! is.read (X_CAST (char *, &len), 4))
 	    return false;
 	  if (swap)
-	    swap_4_bytes (X_CAST (char *, &len));
+	    swap_bytes<4> (&len);
 	  OCTAVE_LOCAL_BUFFER (char, btmp, len+1);
 	  if (! is.read (X_CAST (char *, btmp), len))
 	    return false;
@@ -492,6 +495,7 @@
 }
 
 #if defined (HAVE_HDF5)
+
 bool
 octave_char_matrix_str::save_hdf5 (hid_t loc_id, const char *name,
 				   bool /* save_as_floats */)
@@ -703,6 +707,7 @@
 
   return retval;
 }
+
 #endif
 
 /*
--- a/src/ov-str-mat.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-str-mat.h	Tue Aug 31 05:30:47 2004 +0000
@@ -36,6 +36,7 @@
 #include "str-vec.h"
 
 #include "error.h"
+#include "oct-stream.h"
 #include "ov.h"
 #include "ov-ch-mat.h"
 #include "ov-typeinfo.h"
@@ -140,6 +141,11 @@
   bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug);
 #endif
 
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const
+    { return os.write (matrix, block_size, output_type, skip, flt_fmt); }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
--- a/src/ov-struct.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov-struct.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -1083,7 +1083,7 @@
   if (! is.read (X_CAST (char *, &len), 4))
     return false;
   if (swap)
-    swap_4_bytes (X_CAST (char *, &len));
+    swap_bytes<4> (&len);
 
   if (len > 0)
     {
--- a/src/ov.cc	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov.cc	Tue Aug 31 05:30:47 2004 +0000
@@ -33,6 +33,7 @@
 #include "quit.h"
 
 #include "oct-obj.h"
+#include "oct-stream.h"
 #include "ov.h"
 #include "ov-base.h"
 #include "ov-bool.h"
@@ -1450,6 +1451,14 @@
 	 tn2.c_str (), tn1.c_str ());
 }
 
+int
+octave_value::write (octave_stream& os, int block_size,
+		     oct_data_conv::data_type output_type, int skip,
+		     oct_mach_info::float_format flt_fmt) const
+{
+  return rep->write (os, block_size, output_type, skip, flt_fmt);
+}
+
 octave_value
 octave_value::numeric_assign (const std::string& type,
 			      const std::list<octave_value_list>& idx,
--- a/src/ov.h	Tue Aug 31 00:51:31 2004 +0000
+++ b/src/ov.h	Tue Aug 31 05:30:47 2004 +0000
@@ -748,6 +748,10 @@
     { return rep->load_hdf5 (loc_id, name, have_h5giterate_bug); }
 #endif
 
+  virtual int write (octave_stream& os, int block_size,
+		     oct_data_conv::data_type output_type, int skip,
+		     oct_mach_info::float_format flt_fmt) const;
+
   octave_value *internal_rep (void) const { return rep; }
 
 protected: