changeset 3933:f9ea3dcf58ee

[project @ 2002-05-15 03:21:00 by jwe]
author jwe
date Wed, 15 May 2002 03:21:01 +0000
parents 2e2e32198722
children 31393822395b
files liboctave/Array-idx.h liboctave/Array.cc liboctave/Array.h liboctave/Array2-idx.h liboctave/Array2.cc liboctave/Array2.h liboctave/ArrayN-idx.h liboctave/ArrayN.h liboctave/CMatrix.h liboctave/ChangeLog liboctave/boolMatrix.h liboctave/chMatrix.h liboctave/cmd-edit.cc liboctave/cmd-edit.h liboctave/dMatrix.h liboctave/oct-rl-edit.c liboctave/oct-rl-edit.h src/Cell.h src/ChangeLog src/Map.h src/data.cc src/input.cc src/oct-lvalue.cc src/oct-lvalue.h src/oct-map.cc src/oct-map.h src/oct-obj.cc src/oct-obj.h src/octave.cc src/ov-base-mat.cc src/ov-base-mat.h src/ov-base-nd-array.cc src/ov-base-nd-array.h src/ov-base-scalar.cc src/ov-base-scalar.h src/ov-base.cc src/ov-base.h src/ov-bool-mat.h src/ov-bool.cc src/ov-bool.h src/ov-builtin.cc src/ov-builtin.h src/ov-cell.cc src/ov-cell.h src/ov-ch-mat.h src/ov-colon.h src/ov-complex.cc src/ov-complex.h src/ov-cx-mat.h src/ov-fcn.cc src/ov-fcn.h src/ov-file.h src/ov-list.cc src/ov-list.h src/ov-mapper.cc src/ov-mapper.h src/ov-range.cc src/ov-range.h src/ov-re-mat.h src/ov-re-nd-array.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-struct.h src/ov-usr-fcn.cc src/ov-usr-fcn.h src/ov-va-args.h src/ov.cc src/ov.h src/parse.y src/pr-output.cc src/pr-output.h src/pt-assign.h src/pt-binop.h src/pt-bp.cc src/pt-cell.h src/pt-check.cc src/pt-colon.h src/pt-const.h src/pt-exp.h src/pt-id.h src/pt-idx.cc src/pt-idx.h src/pt-mat.h src/pt-misc.h src/pt-plot.cc src/pt-pr-code.cc src/pt-pr-code.h src/pt-select.h src/pt-stmt.cc src/pt-stmt.h src/pt-unop.h src/symtab.cc src/symtab.h src/toplev.cc src/variables.cc
diffstat 98 files changed, 2489 insertions(+), 1010 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array-idx.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/Array-idx.h	Wed May 15 03:21:01 2002 +0000
@@ -69,13 +69,14 @@
 
 template <class T>
 Array<T>
-Array<T>::index (idx_vector& idx_arg) const
+Array<T>::index (idx_vector& idx_arg, int resize_ok,
+		 const T& resize_fill_value) const
 {
   Array<T> retval;
 
   int len = length ();
 
-  int n = idx_arg.freeze (len, "vector");
+  int n = idx_arg.freeze (len, "vector", resize_ok);
 
   if (idx_arg)
     {
@@ -100,7 +101,10 @@
 	  for (int i = 0; i < n; i++)
 	    {
 	      int ii = idx_arg.elem (i);
-	      retval.elem (i) = elem (ii);
+	      if (ii > len)
+		retval.elem (i) = resize_fill_value;
+	      else
+		retval.elem (i) = elem (ii);
 	    }
 	}
     }
--- a/liboctave/Array.cc	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/Array.cc	Wed May 15 03:21:01 2002 +0000
@@ -185,6 +185,16 @@
   return foo;
 }
 
+template <class T>
+void
+Array<T>::print_info (std::ostream& os, const std::string& prefix) const
+{
+  os << prefix << "rep address: " << rep << "\n"
+     << prefix << "rep->len:    " << rep->len << "\n"
+     << prefix << "rep->data:   " << static_cast<void *> (rep->data) << "\n"
+     << prefix << "rep->count:  " << rep->count << "\n";
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/Array.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/Array.h	Wed May 15 03:21:01 2002 +0000
@@ -30,6 +30,8 @@
 
 #include <cassert>
 
+#include <iostream>
+
 #include "lo-utils.h"
 
 class idx_vector;
@@ -232,6 +234,7 @@
     }
 
 #ifdef HEAVYWEIGHT_INDEXING
+
   void set_max_indices (int mi) { max_indices = mi; }
 
   void clear_index (void);
@@ -246,10 +249,14 @@
 
   Array<T> value (void);
 
-  Array<T> index (idx_vector& i) const;
+  Array<T> index (idx_vector& i, int resize_ok = 0,
+		  const T& rfv = Array<T>::resize_fill_value ()) const;
+
 #endif
 
   static T resize_fill_value (void) { return static_cast<T> (0); }
+
+  void print_info (std::ostream& os, const std::string& prefix) const;
 };
 
 template <class LT, class RT>
--- a/liboctave/Array2-idx.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/Array2-idx.h	Wed May 15 03:21:01 2002 +0000
@@ -56,13 +56,16 @@
 
 template <class T>
 Array2<T>
-Array2<T>::index (idx_vector& idx_arg) const
+Array2<T>::index (idx_vector& idx_arg, int resize_ok,
+		  const T& resize_fill_value) const
 {
   Array2<T> retval;
 
   int nr = d1;
   int nc = d2;
 
+  int orig_len = nr * nc;
+
   int idx_orig_rows = idx_arg.orig_rows ();
   int idx_orig_columns = idx_arg.orig_columns ();
 
@@ -77,7 +80,7 @@
     }
   else if (nr == 1 && nc == 1)
     {
-      Array<T> tmp = Array<T>::index (idx_arg);
+      Array<T> tmp = Array<T>::index (idx_arg, resize_ok);
 
       if (tmp.length () != 0)
 	retval = Array2<T> (tmp, idx_orig_rows, idx_orig_columns);
@@ -88,7 +91,7 @@
     {
       int result_is_column_vector = (nc == 1);
 
-      Array<T> tmp = Array<T>::index (idx_arg);
+      Array<T> tmp = Array<T>::index (idx_arg, resize_ok);
 
       int len = tmp.length ();
 
@@ -110,7 +113,7 @@
       // This code is only for indexing matrices.  The vector
       // cases are handled above.
 
-      idx_arg.freeze (nr * nc, "matrix");
+      idx_arg.freeze (nr * nc, "matrix", resize_ok);
 
       if (idx_arg)
 	{
@@ -125,15 +128,22 @@
 
 	  retval.resize (result_nr, result_nc);
 
+
+
 	  int k = 0;
 	  for (int j = 0; j < result_nc; j++)
 	    {
 	      for (int i = 0; i < result_nr; i++)
 		{
 		  int ii = idx_arg.elem (k++);
-		  int fr = ii % nr;
-		  int fc = (ii - fr) / nr;
-		  retval.elem (i, j) = elem (fr, fc);
+		  if (ii > orig_len)
+		    retval.elem (i, j) = resize_fill_value;
+		  else
+		    {
+		      int fr = ii % nr;
+		      int fc = (ii - fr) / nr;
+		      retval.elem (i, j) = elem (fr, fc);
+		    }
 		}
 	    }
 	}
@@ -148,15 +158,16 @@
 
 template <class T>
 Array2<T>
-Array2<T>::index (idx_vector& idx_i, idx_vector& idx_j) const
+Array2<T>::index (idx_vector& idx_i, idx_vector& idx_j, int resize_ok,
+		  const T& resize_fill_value) const
 {
   Array2<T> retval;
 
   int nr = d1;
   int nc = d2;
 
-  int n = idx_i.freeze (nr, "row");
-  int m = idx_j.freeze (nc, "column");
+  int n = idx_i.freeze (nr, "row", resize_ok);
+  int m = idx_j.freeze (nc, "column", resize_ok);
 
   if (idx_i && idx_j)
     {
@@ -178,7 +189,10 @@
 	      for (int i = 0; i < n; i++)
 		{
 		  int ii = idx_i.elem (i);
-		  retval.elem (i, j) = elem (ii, jj);
+		  if (ii > nr || jj > nc)
+		    retval.elem (i, j) = resize_fill_value;
+		  else
+		    retval.elem (i, j) = elem (ii, jj);
 		}
 	    }
 	}
--- a/liboctave/Array2.cc	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/Array2.cc	Wed May 15 03:21:01 2002 +0000
@@ -237,6 +237,17 @@
     }
 }
 
+template <class T>
+void
+Array2<T>::print_info (std::ostream& os, const std::string& prefix) const
+{
+  os << "\n"
+     << prefix << "rows: " << rows () << "\n"
+     << prefix << "cols: " << cols () << "\n";
+
+  Array<T>::print_info (os, prefix + "  ");
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/Array2.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/Array2.h	Wed May 15 03:21:01 2002 +0000
@@ -174,16 +174,22 @@
   Array2<T> transpose (void) const;
 
 #ifdef HEAVYWEIGHT_INDEXING
+
   void maybe_delete_elements (idx_vector& i);
 
   void maybe_delete_elements (idx_vector& i, idx_vector& j);
 
   Array2<T> value (void);
 
-  Array2<T> index (idx_vector& i) const;
+  Array2<T> index (idx_vector& i, int resize_ok = 0,
+		   const T& rfv = Array<T>::resize_fill_value ()) const;
 
-  Array2<T> index (idx_vector& i, idx_vector& j) const;
+  Array2<T> index (idx_vector& i, idx_vector& j, int resize_ok = 0,
+		   const T& rfv = Array<T>::resize_fill_value ()) const;
+
 #endif
+
+  void print_info (std::ostream& os, const std::string& prefix) const;
 };
 
 template <class LT, class RT>
--- a/liboctave/ArrayN-idx.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/ArrayN-idx.h	Wed May 15 03:21:01 2002 +0000
@@ -70,7 +70,8 @@
 
 template <class T>
 ArrayN<T>
-ArrayN<T>::index (idx_vector& idx) const
+ArrayN<T>::index (idx_vector& idx, int resize_ok,
+		  const T& resize_fill_value) const
 {
   ArrayN<T> retval;
   assert (0);
@@ -78,7 +79,7 @@
 }
 
 static inline Array<int>
-freeze (Array<idx_vector>& idx, const Array<int>& dimensions)
+freeze (Array<idx_vector>& idx, const Array<int>& dimensions, int resize_ok)
 {
   Array<int> retval;
 
@@ -89,7 +90,7 @@
   retval.resize (n);
 
   for (int i = 0; i < n; i++)
-    retval(i) = idx(i).freeze (dimensions(i), "XXX FIXME XXX");
+    retval(i) = idx(i).freeze (dimensions(i), "XXX FIXME XXX", resize_ok);
 
   return retval;
 }
@@ -199,13 +200,14 @@
 
 template <class T>
 ArrayN<T>
-ArrayN<T>::index (Array<idx_vector>& arr_idx) const
+ArrayN<T>::index (Array<idx_vector>& arr_idx, int resize_ok,
+		  const T& resize_fill_value) const
 {
   ArrayN<T> retval;
 
   int n_dims = dimensions.length ();
 
-  Array<int> frozen_lengths = freeze (arr_idx, dimensions);
+  Array<int> frozen_lengths = freeze (arr_idx, dimensions, resize_ok);
 
   if (frozen_lengths.length () == n_dims)
     {
@@ -239,7 +241,10 @@
 		{
 		  Array<int> elt_idx = get_elt_idx (result_idx);
 
-		  retval.elem (result_idx) = elem (elt_idx);
+		  if (elt_idx > orig_len)
+		    retval.elem (result_idx) = resize_fill_value;
+		  else
+		    retval.elem (result_idx) = elem (elt_idx);
 
 		  increment_index (result_idx, frozen_lengths);
 		}
--- a/liboctave/ArrayN.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/ArrayN.h	Wed May 15 03:21:01 2002 +0000
@@ -179,9 +179,12 @@
 
   ArrayN<T> value (void);
 
-  ArrayN<T> index (idx_vector& idx) const;
+  ArrayN<T> index (idx_vector& idx, int resize_ok = 0,
+		   const T& rfv = Array<T>::resize_fill_value ()) const;
 
-  ArrayN<T> index (Array<idx_vector>& idx) const;
+  ArrayN<T> index (Array<idx_vector>& idx, int resize_ok = 0,
+		   const T& rfv = Array<T>::resize_fill_value ()) const;
+
 #endif
 };
 
--- a/liboctave/CMatrix.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/CMatrix.h	Wed May 15 03:21:01 2002 +0000
@@ -273,6 +273,8 @@
   friend std::ostream& operator << (std::ostream& os, const ComplexMatrix& a);
   friend std::istream& operator >> (std::istream& is, ComplexMatrix& a);
 
+  static Complex resize_fill_value (void) { return Complex (0.0, 0.0); }
+
 private:
 
   ComplexMatrix (Complex *d, int r, int c) : MArray2<Complex> (d, r, c) { }
--- a/liboctave/ChangeLog	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/ChangeLog	Wed May 15 03:21:01 2002 +0000
@@ -1,3 +1,33 @@
+2002-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* oct-rl-edit.c (OCTAVE_RL_SAVE_STRING): New macro.
+	(octave_rl_set_name, octave_rl_set_basic_quote_characters): Use it.
+	(octave_rl_set_basic_word_break_characters,
+	octave_rl_set_completer_word_break_characters): New functions.
+	* oct-rl-edit.h: Provide decls.
+	* cmd-edit.cc (gnu_readline::do_set_basic_word_break_characters,
+	gnu_readline::do_set_completer_word_break_characters): New functions.
+	(command_editor::set_basic_quote_characters,
+	command_editor::set_completion_append_character): New static functions.
+	* cmd-edit.h: Provide decls.
+	(command_editor::do_set_basic_word_break_characters,
+	command_editor::do_set_completer_word_break_characters):
+	New virtual functions.
+
+	* CMatrix.h, boolMatrix.h, chMatrix.h, dMatrix.h
+	(resize_fill_value): New static function.
+
+	* Array-idx.h (Array<T>::index): New args, resize_ok and
+	resize_fill_value.
+	* Array2-idx.h (Array2<T>::index): Likewise.
+	* ArrayN-idx.h (ArrayN<T>::index): Likewise.
+
+	* Array2.cc (Array<T>::print_info): New function.
+	* Array2.h: Provide decl.
+
+	* Array.cc (Array<T>::print_info): New function.
+	* Array.h: Provide decl.
+
 2002-05-03  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* idx-vector.h (idx_vector::idx_vector (int)): New function.
--- a/liboctave/boolMatrix.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/boolMatrix.h	Wed May 15 03:21:01 2002 +0000
@@ -74,6 +74,8 @@
   friend std::istream& operator >> (std::istream& is, Matrix& a);
 #endif
 
+  static bool resize_fill_value (void) { return false; }
+
 private:
 
   boolMatrix (bool *b, int r, int c) : Array2<bool> (b, r, c) { }
--- a/liboctave/chMatrix.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/chMatrix.h	Wed May 15 03:21:01 2002 +0000
@@ -81,6 +81,8 @@
   friend std::istream& operator >> (std::istream& is, Matrix& a);
 #endif
 
+  static char resize_fill_value (void) { return '\0'; }
+
 private:
 
   charMatrix (char *ch, int r, int c) : MArray2<char> (ch, r, c) { }
--- a/liboctave/cmd-edit.cc	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/cmd-edit.cc	Wed May 15 03:21:01 2002 +0000
@@ -93,6 +93,10 @@
 
   void do_blink_matching_paren (bool flag);
 
+  void do_set_basic_word_break_characters (const std::string& s);
+
+  void do_set_completer_word_break_characters (const std::string& s);
+
   void do_set_basic_quote_characters (const std::string& s);
 
   void do_set_completion_append_character (char c);
@@ -270,6 +274,18 @@
 }
 
 void
+gnu_readline::do_set_basic_word_break_characters (const std::string& s)
+{
+  ::octave_rl_set_basic_word_break_characters (s.c_str ());
+}
+
+void
+gnu_readline::do_set_completer_word_break_characters (const std::string& s)
+{
+  ::octave_rl_set_completer_word_break_characters (s.c_str ());
+}
+
+void
 gnu_readline::do_set_basic_quote_characters (const std::string& s)
 {
   ::octave_rl_set_basic_quote_characters (s.c_str ());
@@ -635,6 +651,20 @@
 }
 
 void
+command_editor::set_basic_word_break_characters (const std::string& s)
+{
+  if (instance_ok ())
+    instance->do_set_basic_word_break_characters (s);
+}
+
+void
+command_editor::set_completer_word_break_characters (const std::string& s)
+{
+  if (instance_ok ())
+    instance->do_set_completer_word_break_characters (s);
+}
+
+void
 command_editor::set_basic_quote_characters (const std::string& s)
 {
   if (instance_ok ())
--- a/liboctave/cmd-edit.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/cmd-edit.h	Wed May 15 03:21:01 2002 +0000
@@ -73,6 +73,12 @@
 
   static void blink_matching_paren (bool flag);
 
+  static void command_editor::set_basic_word_break_characters
+    (const std::string& s);
+
+  static void command_editor::set_completer_word_break_characters
+    (const std::string& s);
+
   static void set_basic_quote_characters (const std::string& s);
 
   static void set_completion_append_character (char c);
@@ -159,6 +165,10 @@
 
   virtual void do_blink_matching_paren (bool) { }
 
+  virtual void do_set_basic_word_break_characters (const std::string&) { }
+
+  virtual void do_set_completer_word_break_characters (const std::string&) { }
+
   virtual void do_set_basic_quote_characters (const std::string&) { }
 
   virtual void do_set_completion_append_character (char) { }
--- a/liboctave/dMatrix.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/dMatrix.h	Wed May 15 03:21:01 2002 +0000
@@ -233,6 +233,8 @@
   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:
 
   Matrix (double *d, int r, int c) : MArray2<double> (d, r, c) { }
--- a/liboctave/oct-rl-edit.c	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/oct-rl-edit.c	Wed May 15 03:21:01 2002 +0000
@@ -33,6 +33,19 @@
 
 #include "oct-rl-edit.h"
 
+#define OCTAVE_RL_SAVE_STRING(ss, s) \
+  static char *ss = 0; \
+ \
+  if (ss) \
+    { \
+      free (ss); \
+      ss = 0; \
+    } \
+ \
+  ss = malloc (strlen (s) + 1); \
+ \
+  strcpy (ss, s)
+
 int
 octave_rl_screen_height (void)
 {
@@ -123,17 +136,7 @@
 void
 octave_rl_set_name (const char *n)
 {
-  static char *nm = 0;
-
-  if (nm)
-    {
-      free (nm);
-      nm = 0;
-    }
-
-  nm = malloc (strlen (n + 1));
-
-  strcpy (nm, n);
+  OCTAVE_RL_SAVE_STRING (nm, n);
 
   rl_readline_name = nm;
 
@@ -184,19 +187,25 @@
 }
 
 void
+octave_rl_set_basic_word_break_characters (const char *s)
+{
+  OCTAVE_RL_SAVE_STRING (ss, s);
+
+  rl_basic_word_break_characters = ss;
+}
+
+void
+octave_rl_set_completer_word_break_characters (const char *s)
+{
+  OCTAVE_RL_SAVE_STRING (ss, s);
+
+  rl_completer_word_break_characters = ss;
+}
+
+void
 octave_rl_set_basic_quote_characters (const char *s)
 {
-  static char *ss = 0;
-
-  if (ss)
-    {
-      free (ss);
-      ss = 0;
-    }
-
-  ss = malloc (strlen (s) + 1);
-
-  strcpy (ss, s);
+  OCTAVE_RL_SAVE_STRING (ss, s);
 
   rl_basic_quote_characters = ss;
 }
--- a/liboctave/oct-rl-edit.h	Tue May 07 18:10:44 2002 +0000
+++ b/liboctave/oct-rl-edit.h	Wed May 15 03:21:01 2002 +0000
@@ -72,6 +72,10 @@
 
 extern void octave_rl_read_init_file (const char *);
 
+extern void octave_rl_set_basic_word_break_characters (const char *);
+
+extern void octave_rl_set_completer_word_break_characters (const char *);
+
 extern void octave_rl_set_basic_quote_characters (const char *);
 
 extern void octave_rl_set_completion_append_character (char);
--- a/src/Cell.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/Cell.h	Wed May 15 03:21:01 2002 +0000
@@ -52,12 +52,22 @@
   Cell (const Array2<octave_value>& c)
     : Array2<octave_value> (c) { }
 
+  Cell (const Array<octave_value>& c, int nr, int nc)
+    : Array2<octave_value> (c, nr, nc) { }
+
   Cell (const Cell& c)
     : Array2<octave_value> (c) { }
 
-  boolMatrix all(void) const { return boolMatrix();} //FIXME
-  boolMatrix any(void) const {return boolMatrix();}  //FIXME
-  bool is_true(void) const {return false;} //FIXME
+  // XXX FIXME XXX
+  boolMatrix all (void) const { return boolMatrix (); }
+
+  // XXX FIXME XXX
+  boolMatrix any (void) const { return boolMatrix (); }
+
+  // XXX FIXME XXX
+  bool is_true (void) const { return false; }
+
+  static octave_value resize_fill_value (void) { return octave_value (); }
 };
 
 #endif
--- a/src/ChangeLog	Tue May 07 18:10:44 2002 +0000
+++ b/src/ChangeLog	Wed May 15 03:21:01 2002 +0000
@@ -1,5 +1,210 @@
+2002-05-14  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* ov.h (octave_value::get_count): Now const.
+
+	* ov.h, ov.cc (octave_value::do_non_const_unary_op,
+	octave_value::assign): Idx is now a list of octave_value_list
+	objects.
+
+	* ov-base.cc, ov-base.h	(octave_base_value::do_struct_elt_index_op,
+	octave_base_value::struct_elt_ref): Delete.
+	* ov-struct.cc, ov-struct.h (octave_sruct::do_struct_elt_index_op,
+	octave_struct::struct_elt_ref): Delete.
+	* ov.cc, ov.h (octave_value::do_struct_elt_index_op,
+	octave_value::struct_elt_ref, octave_value::assign_struct_elt,
+	octave_value::convert_and_assign, octave_value::try_assignment,
+	octave_value::try_assignment_with_conversion,
+	octave_value::simple_assign): Delete.
+
+	* parse.y (make_index_expression): Type is now a single
+	character.  Change all callers.  If expr is already an index
+	expression, append index to it.
+	(make_indirect_ref): Likewise.
+
+	* pt-pr-code.cc (octave_print_internal (std::ostream&, const
+	Cell&, bool, int)): Now just a dummy function, panic if called.
+
+	* pt-idx.cc (tree_index_expression::make_arg_struct): New function.
+	(tree_index_expression::type): Delete enum, rename from itype, now
+	a string.
+	(tree_index_expression::arg_nm): Now a list of string_vector objects.
+	(tree_index_expression::idx): Now a list of tree_argument_list*
+	objects.
+	(tree_index_expression::is_index_expression): Always return true.
+	(tree_index_expression::apend, make_value_list, make_subs_cell):
+	New functions.
+	
+	* pt-pr-code.cc (visit_index_expression): Handle new definition of
+	tree_index_expression object.
+	* pt-check.cc (visit_index_expression): Likewise.
+	* pt-bp.cc (visit_index_expression): Likewise.
+
+	* ov-usr-fcn.h (octave_user_function::restore_args_passed):
+	Clear args_passed even if nothing was saved.
+
+	* ov-base.cc (octave_base_value::subsasgn,
+	octave_base_value::map_keys, octave_base_value::print_info):
+	New functions.
+
+	* ov.h, ov.cc (octave_value::map_keys, octave_value::print_info,
+	octave_value::subsref, octave_value::subsasgn,
+	octave_value::numeric_assign, octave_value::next_subsref):
+	New functions.
+	(octave_value::empty_conv): New static function.
+	(octave_value (octave_value *, int)): New arg, count.
+
+	* ov-base-mat.cc (octave_base_matrix<MT>::subsref,
+	octave_base_matrix<MT>::subsasgn): New functions.
+	* ov-base-mat.h: Provide decls.
+
+	* ov-builtin.cc (octave_builtin::subsref): New function.
+	* ov-builtin.h: Provide decl.
+
+	* ov-range.cc (octave_range::subsref): New function.
+	* ov-range.h: Provide decl.
+
+	* ov-cell.cc (octave_cell::subsref, octave_cell::subsasgn,
+	octave_cell::list_value, octave_cell::print,
+	octave_cell::print_raw, octave_cell::print_name_tag): New functions.
+	* ov-cell.h: Provide decls.
+
+	* ov-struct.cc (octave_struct::dotref, octave_struct::subsref,
+	octave_struct::subsasgn, gripe_invalid_index,
+	gripe_invalid_index_for_assignment, grip_invalid_index_type,
+	gripe_failed_assignment): New functions.
+	(octave_struct::numeric_conv): New static function.
+	* ov-struct.h: Provide decls.
+	(octave_struct::is_constant): Return true.
+	(octave_struct::map_keys): New function.
+
+	* ov-list.cc (octave_list::subsref, octave_list::subsasgn):
+	New functions.
+	* ov-list.h: Provide decls.
+
+	* ov-usr-fcn.cc (octave_user_function::subsref,
+	octave_user_function::print_symtab_info): New functions.
+	* ov-usr-fcn.h: Provide decl.
+
+	* ov-mapper.cc (octave_mapper::subsref): New function.
+	* ov-mapper.h: Provide decl.
+
+	* ov-base.cc (octave_base_value::subsref,
+	octave_base_value::subsasgn): New functions.
+	* ov-base.h: Provide decls.
+
+	* ov-base.cc (octave_base_value::do_index_op): New arg, resize_ok.
+	* ov-base-mat.cc (octave_base_matrix<MT>::do_index_op): Likewise.
+	* ov-base-nd-array.cc (octave_base_nd_array<AT>::do_index_op): Ditto.
+	* ov-bool-mat.cc (octave_bool::do_index_op): Ditto.
+	* ov-str-mat.cc (octave_char_matrix_str::do_index_op): Ditto.
+	* ov-range.cc (octave_range::do_index_op): Ditto.
+	* ov-list.cc (octave_list::do_index_op): Ditto.
+	* ov.cc (octave_value::do_index_op): Ditto.
+	
+	* ov-base-mat.cc (octave_base_matrix<MT>::print_info): New function.
+
+	* ov-base-mat.h (octave_base_matrix<MT>::empty_clone): New function.
+	* ov-base-nd-array.h (octave_base_nd_array<AT>::empty_clone): Ditto.
+	* ov-base.h (octave_base_value::empty_clone): Ditto.
+	* ov-bool-mat.h (octave_bool::empty_clone): Ditto.
+	* ov-ch-mat.h (octave_char_matrix::empty_clone): Likewise.
+	* ov-colon.h (octave_magic_colon::empty_clone): Likewise.
+	* ov-complex.h (octave_complex::empty_clone): Likewise.
+	* ov-cx-mat.h (octave_complex_matrix::empty_clone): Likewise.
+	* ov-fcn.cc (octave_function::empty_clone): Likewise.
+	* ov-file.h (octave_file::empty_clone): Likewise.
+	* ov-range.h (octave_range::empty_clone): Likewise.
+	* ov-list.h (octave_list::empty_clone): Likewise.
+	* ov-re-mat.h (octave_matrix::empty_clone): Likewise.
+	* ov-re-nd-array.h (octave_double_nd_array::empty_clone): Likewise.
+	* ov-str-mat.h (octave_char_matrix_str::empty_clone): Likewise.
+	* ov-struct.h (octave_struct::empty_clone): Likewise.
+	* ov-va_args.h (octave_all_va_args::empty_clone): Likewise.
+	* ov.h (octave_value::empty_clone): Likewise.
+
+	* ov-base-mat.h (octave_base_matrix<MT>::clone): Now const.
+	* ov-base-nd-array.h (octave_base_nd_array<AT>::clone): Likewise.
+	* ov-base.h (octave_base_value::clone): Likewise.
+	* ov-bool-mat.h (octave_bool::clone): Likewise.
+	* ov-ch-mat.h (octave_char_matrix::clone): Likewise.
+	* ov-colon.h (octave_magic_colon::clone): Likewise.
+	* ov-complex.h (octave_complex::clone): Likewise.
+	* ov-cx-mat.h (octave_complex_matrix::clone): Likewise.
+	* ov-fcn.h (octave_function::clone): Likewise.
+	* ov-file.h (octave_file::clone): Likewise.
+	* ov-range.h (octave_range::clone): Likewise.
+	* ov-list.h (octave_list::clone): Likewise.
+	* ov-re-mat.h (octave_matrix::clone): Likewise.
+	* ov-re-nd-array.h (octave_double_nd_array::clone): Likewise.
+	* ov-str-mat.h (octave_char_matrix_str::clone): Likewise.
+	* ov-struct.h (octave_struct::clone): Likewise.
+	* ov-va_args.h (octave_all_va_args::clone): Likewise.
+	* ov.h (octave_value::clone): Likewise.
+
+	* oct-lvalue.cc (octave_lvalue::assign, octave_lvalue::set_index,
+	octave_lvalue::do_unary_op): Idx is now a list of indices.  Simplify.
+	* oct-lvalue.h (octave_lvalue::value): Simplify.
+	(octave_lvalue::struct_elt_names): Delete data member.
+	(octave_lvalue::type): Now string
+	Update decls.
+
+	* pt-exp.h (tree_expression::is_indirect_ref):
+	Delete virtual function.
+
+	* pt-plot.cc (subplot::extract_plot_data): Use subsref, instead of
+	do_index_op.
+
+	* pt-stmt.cc (tree_statement::eval): Don't try to avoid binding
+	ans for structure references.
+
+	* symtab.cc (symbol_record::symbol_def::print_info): Rename from
+	symbol_record::symbol_def::dump_symbol_info.
+	(symbol_record::print_info): Rename from
+	symbol_record::dump_symbol_info.  Now const..
+	(symbol_record::print_symbol_info_line): Now const.
+	(symbol_table::print_info): Rename from print_stats.  Accept
+	ostream arg.  Now const.  Print more info.
+	* symtab.h: Update decls.
+
+	* toplev.cc (octave_config_info): Indexing a map now returns a
+	list, but we only want to return the first element.
+
+	* variables.cc (generate_struct_completions, looks_like_struct):
+	Simplify using eval_string.
+	(F__print_symtab_info__): Rename from F__dump_symtab_info__.
+	Handle "top-level" and individual function names in addition to
+	"global".
+	(F__print_symbol_info__): Rename from F___dump_symbol_info__.
+
+	* octave.cc (intern_argv): Built-in variable argv is now a cell array.
+
+	* ov-complex.cc (valid_scalar_indices): Delete.
+	* ov-scalar.cc (valid_scalar_indices): Delete.
+
+	* oct-obj.cc (octave_value_list::valid_scalar_indices): New function.
+	(octave_value_list::index): New arg, resize_ok.
+	* oct-obj.h: Provide decls.
+
+	* oct-map.cc (Octave_map::keys): Rename from make_name_list.
+	Change all uses.
+	(Octave_map::assign, Octave_map::index): New functions.
+	* oct-map.h: Provide decls.
+
+	* data.cc (Fstruct_contains): Use map_value instead of
+	do_struct_elt_index_op.
+
+	* Cell.h (Cell (const Array2<octave_value>&, int, int)):
+	New constructor.
+	(Cell::resize_fill_value): New static function.
+
+	* input.cc (initialize_command_input): Set basic and completer
+	word break characters.
+
 2002-05-07  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	* ov.h (octave_value::subsref): New function.
+	* ov-base.cc (octave_base_value::subsref): Likewise.
+
 	* ov-struct.cc (octave_struct::print_raw): Print scalar struct
 	arrays more compactly.
 
@@ -12,7 +217,6 @@
 	(Octave_map::array_length): New fucntion.
 	* oct-obj.cc (octave_value_list::assign): New function.
 	
-
 2002-05-06  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* TEMPLATE-INST/Map-oct-obj.cc: New file.
--- a/src/Map.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/Map.h	Wed May 15 03:21:01 2002 +0000
@@ -75,7 +75,7 @@
   virtual void clear (void);			// delete all items
 	      
   virtual C& operator [] (const std::string& key) = 0;  // access contents by key
-	      
+
   virtual void del (const std::string& key) = 0;	// delete entry
 	      
   virtual Pix first (void) const = 0;		// Pix of first item or 0
--- a/src/data.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/data.cc	Wed May 15 03:21:01 2002 +0000
@@ -849,7 +849,7 @@
       if (args (0).is_map ())
 	{
 	  Octave_map m = args(0).map_value ();
-	  retval(0) = m.make_name_list ();
+	  retval(0) = m.keys ();
 	}
       else
 	gripe_wrong_type_arg ("struct_elements", args (0));
@@ -881,9 +881,11 @@
 
       if (args(0).is_map () && args(1).is_string ())
 	{
-	  std::string s = args(1).string_value ();
-	  octave_value tmp = args(0).do_struct_elt_index_op (s, true);
-	  retval = static_cast<double> (tmp.is_defined ());
+	  std::string key = args(1).string_value ();
+
+	  Octave_map m = args(0).map_value ();
+
+	  retval = static_cast<double> (m.contains (key));
 	}
       else
 	print_usage ("struct_contains");
--- a/src/input.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/input.cc	Wed May 15 03:21:01 2002 +0000
@@ -476,6 +476,15 @@
 
   command_editor::set_name ("Octave");
 
+  // XX FIXME XXX -- this needs to include a comma too, but that
+  // causes trouble for the new struct element completion code.
+
+  static char *s = "\t\n !\"\'*+-/:;<=>[\\]^`~";
+
+  command_editor::set_basic_word_break_characters (s);
+
+  command_editor::set_completer_word_break_characters (s);
+
   command_editor::set_basic_quote_characters ("\"");
 
   command_editor::set_completion_function (generate_completion);
--- a/src/oct-lvalue.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/oct-lvalue.cc	Wed May 15 03:21:01 2002 +0000
@@ -32,38 +32,22 @@
 void
 octave_lvalue::assign (octave_value::assign_op op, const octave_value& rhs)
 {
-  octave_value saved_val;
-
-  if (chg_fcn)
-    saved_val = *val;
+  octave_value tmp (idx.empty ()
+		    ? val->assign (op, rhs)
+		    : val->assign (op, type, idx, rhs));
 
-  if (idx.empty ())
-    {
-      if (struct_elt_name.empty ())
-	val->assign (op, rhs);
-      else
-	val->assign_struct_elt (op, struct_elt_name, rhs);
-    }
-  else
-    {
-      if (struct_elt_name.empty ())
-	val->assign (op, idx, rhs);
-      else
-	val->assign_struct_elt (op, struct_elt_name, idx, rhs);
-    }
-
-  if (chg_fcn && ! error_state && chg_fcn () < 0)
-    *val = saved_val;
+  if (! (error_state || chg_fcn && chg_fcn () < 0))
+    *val = tmp;
 }
 
 void
-octave_lvalue::set_index (const octave_value_list& i,
-			  tree_index_expression::type t)
+octave_lvalue::set_index (const std::string& t,
+			  const SLList<octave_value_list>& i)
 {
   if (! index_set)
     {
+      type = t;
       idx = i;
-      itype = t;
       index_set = true;
     }
   else
@@ -73,18 +57,12 @@
 void
 octave_lvalue::do_unary_op (octave_value::unary_op op)
 {
-  octave_value saved_val;
-
-  if (chg_fcn)
-    saved_val = *val;
+  octave_value tmp (idx.empty ()
+		    ? val->do_non_const_unary_op (op)
+		    : val->do_non_const_unary_op (op, type, idx));
 
-  if (idx.empty ())
-    val->do_non_const_unary_op (op);
-  else
-    val->do_non_const_unary_op (op, idx);
-
-  if (chg_fcn && ! error_state && chg_fcn () < 0)
-    *val = saved_val;
+  if (! (error_state || chg_fcn && chg_fcn () < 0))
+    *val = tmp;
 }
 
 /*
--- a/src/oct-lvalue.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/oct-lvalue.h	Wed May 15 03:21:01 2002 +0000
@@ -28,6 +28,8 @@
 
 #include <string>
 
+#include "SLList.h"
+
 #include "oct-obj.h"
 #include "pt-idx.h"
 #include "symtab.h"
@@ -44,25 +46,20 @@
 
   octave_lvalue (octave_value *v = &dummy_val,
 		 symbol_record::change_function f = 0)
-    : val (v), idx (), chg_fcn (f), struct_elt_name (), index_set (false) { }
-
-  octave_lvalue (octave_value *v, const std::string& nm,
-		 symbol_record::change_function f = 0)
-    : val (v), idx (), chg_fcn (f), struct_elt_name (nm), index_set (false) { }
+    : val (v), type (), idx (), chg_fcn (f), index_set (false) { }
 
   octave_lvalue (const octave_lvalue& vr)
-    : val (vr.val), idx (vr.idx), itype (vr.itype), chg_fcn (vr.chg_fcn),
-      struct_elt_name (vr.struct_elt_name), index_set (vr.index_set) { }
+    : val (vr.val), type (vr.type), idx (vr.idx), chg_fcn (vr.chg_fcn),
+      index_set (vr.index_set) { }
 
   octave_lvalue& operator = (const octave_lvalue& vr)
     {
       if (this != &vr)
 	{
 	  val = vr.val;
+	  type = vr.type;
 	  idx = vr.idx;
-	  itype = vr.itype;
 	  chg_fcn = vr.chg_fcn;
-	  struct_elt_name = vr.struct_elt_name;
 	  index_set = vr.index_set;
 	}
 
@@ -81,43 +78,25 @@
 
   void assign (octave_value::assign_op, const octave_value&);
 
-  octave_lvalue struct_elt_ref (const std::string& nm)
-    {
-      val->make_unique ();
-      return val->struct_elt_ref (nm);
-    }
+  void set_index (const std::string& t, const SLList<octave_value_list>& i);
 
-  void set_index (const octave_value_list& i,
-		  tree_index_expression::type t
-		    = tree_index_expression::unknown);
-
-  void clear_index (void) { idx = octave_value_list (); }
+  void clear_index (void) { type = std::string (); idx.clear (); }
 
   void do_unary_op (octave_value::unary_op op);
 
   octave_value value (void)
-    {
-      return struct_elt_name.empty ()
-	? (idx.empty ()
-	   ? *val
-	   : val->do_index_op (idx))
-	: (idx.empty ()
-	   ? val->do_struct_elt_index_op (struct_elt_name)
-	   : val->do_struct_elt_index_op (struct_elt_name, idx));
-    }
+    { return idx.empty () ? *val : val->subsref (type, idx); }
 
 private:
 
   octave_value *val;
 
-  octave_value_list idx;
+  std::string type;
 
-  tree_index_expression::type itype;
+  SLList<octave_value_list> idx;
 
   symbol_record::change_function chg_fcn;
 
-  std::string struct_elt_name;
-
   bool index_set;
 };
 
--- a/src/oct-map.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/oct-map.cc	Wed May 15 03:21:01 2002 +0000
@@ -35,7 +35,7 @@
 #include "utils.h"
 
 string_vector
-Octave_map::make_name_list (void)
+Octave_map::keys (void) const
 {
   int len = length ();
 
@@ -87,6 +87,42 @@
   return *this;
 }
 
+Octave_map&
+Octave_map::assign (const std::string& key, const octave_value_list& rhs)
+{
+  if (map.empty ())
+    map[key] = rhs;
+  else
+    {
+      octave_value_list tmp = map.contents (map.first ());
+
+      if (tmp.length () == rhs.length ())
+	map[key] = rhs;
+      else
+	error ("invalid structure assignment");
+    }
+
+  return *this;
+}
+
+Octave_map
+Octave_map::index (idx_vector& idx)
+{
+  Octave_map retval;
+
+  for (Pix p = first (); p != 0; next (p))
+    {
+      octave_value_list tmp = contents(p).index (idx);
+
+      if (error_state)
+	break;
+
+      retval[key(p)] = tmp;
+    }
+
+  return error_state ? Octave_map () : retval;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/oct-map.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/oct-map.h	Wed May 15 03:21:01 2002 +0000
@@ -82,13 +82,17 @@
 
   void clear (void) { map.clear (); }
 
-  string_vector make_name_list (void);
+  string_vector keys (void) const;
 
   int array_length () const;
 
   Octave_map& assign (const idx_vector& idx, const std::string& key,
 		      const octave_value_list& rhs);
 
+  Octave_map& assign (const std::string& key, const octave_value_list& rhs);
+
+  Octave_map index (idx_vector& idx);
+
 private:
 
   // The map of names to values.
--- a/src/oct-obj.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/oct-obj.cc	Wed May 15 03:21:01 2002 +0000
@@ -34,6 +34,18 @@
 octave_allocator
 octave_value_list::allocator (sizeof (octave_value_list));
 
+bool
+octave_value_list::valid_scalar_indices (void) const
+{
+  int n = data.length ();
+
+  for (int i = 0; i < n; i++)
+    if (! data(i).valid_as_scalar_index ())
+      return false;
+
+  return true;
+}
+
 octave_value_list&
 octave_value_list::prepend (const octave_value& val)
 {
@@ -137,9 +149,9 @@
 }
 
 octave_value_list
-octave_value_list::index (idx_vector& i) const
+octave_value_list::index (idx_vector& i, int resize_ok) const
 {
-  return octave_value_list (data.index (i));
+  return octave_value_list (data.index (i, resize_ok, octave_value ()));
 }
 
 octave_value_list&
--- a/src/oct-obj.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/oct-obj.h	Wed May 15 03:21:01 2002 +0000
@@ -111,6 +111,8 @@
       return *this;
     }
 
+  bool valid_scalar_indices (void) const;
+
   // Assignment will resize on range errors.
 
   octave_value& operator () (int n) { return elem (n); }
@@ -136,7 +138,7 @@
   octave_value_list splice (int offset, int length,
 			    const octave_value_list& lst) const;
 
-  octave_value_list index (idx_vector& i) const;
+  octave_value_list index (idx_vector& i, int resize_ok = 0) const;
 
   octave_value_list& assign (const idx_vector& i,
 			     const octave_value_list& rhs);
--- a/src/octave.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/octave.cc	Wed May 15 03:21:01 2002 +0000
@@ -51,6 +51,7 @@
 #include "str-vec.h"
 
 #include <defaults.h>
+#include "Cell.h"
 #include "defun.h"
 #include "error.h"
 #include "file-io.h"
@@ -159,14 +160,18 @@
   bind_builtin_variable ("nargin", static_cast<double> (argc-1),
 			 true, true, 0);
 
-  octave_value_list octave_argv;
+  Cell octave_argv;
 
   if (argc > 1)
     {
+      Array<octave_value> tmp (argc-1);
+
       // Skip program name in argv.
-      while (--argc > 0)
-	octave_argv(argc-1) = octave_value (*(argv+argc));
+      int i = argc;
+      while (--i > 0)
+	tmp(i-1) = octave_value (*(argv+i));
 
+      octave_argv = Cell (tmp, argc-1, 1);
     }
 
   bind_builtin_constant ("argv", octave_argv, true, true);
--- a/src/ov-base-mat.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base-mat.cc	Wed May 15 03:21:01 2002 +0000
@@ -30,14 +30,83 @@
 
 #include <iostream>
 
+#include "Cell.h"
 #include "oct-obj.h"
+#include "oct-map.h"
 #include "ov-base.h"
 #include "ov-base-mat.h"
 #include "pr-output.h"
 
 template <class MT>
 octave_value
-octave_base_matrix<MT>::do_index_op (const octave_value_list& idx)
+octave_base_matrix<MT>::subsref (const std::string type,
+				 const SLList<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_index_op (idx.front ());
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval.next_subsref (type, idx);
+}
+
+template <class MT>
+octave_value
+octave_base_matrix<MT>::subsasgn (const std::string type,
+				  const SLList<octave_value_list>& idx,
+				  const octave_value& rhs)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      {
+	if (type.length () == 1)
+	  retval = numeric_assign (type, idx, rhs);
+	else
+	  {
+	    std::string nm = type_name ();
+	    error ("in indexed assignment of %s, last rhs index must be ()",
+		   nm.c_str ());
+	  }
+      }
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval;
+}
+
+template <class MT>
+octave_value
+octave_base_matrix<MT>::do_index_op (const octave_value_list& idx,
+				     int resize_ok)
 {
   octave_value retval;
 
@@ -50,7 +119,7 @@
 	idx_vector i = idx (0).index_vector ();
 	idx_vector j = idx (1).index_vector ();
 
-	retval = MT (matrix.index (i, j));
+	retval = MT (matrix.index (i, j, resize_ok, MT::resize_fill_value ()));
       }
       break;
 
@@ -58,7 +127,7 @@
       {
 	idx_vector i = idx (0).index_vector ();
 
-	retval = MT (matrix.index (i));
+	retval = MT (matrix.index (i, resize_ok, MT::resize_fill_value ()));
       }
       break;
 
@@ -162,7 +231,8 @@
 
 template <class MT>
 void
-octave_base_matrix<MT>::print_raw (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_matrix<MT>::print_raw (std::ostream& os,
+				   bool pr_as_read_syntax) const
 {
   octave_print_internal (os, matrix, pr_as_read_syntax,
 			 current_print_indent_level ());
@@ -170,7 +240,8 @@
 
 template <class MT>
 bool
-octave_base_matrix<MT>::print_name_tag (std::ostream& os, const std::string& name) const
+octave_base_matrix<MT>::print_name_tag (std::ostream& os,
+					const std::string& name) const
 {
   bool retval = false;
 
@@ -189,6 +260,14 @@
   return retval;
 }
 
+template <class MT>
+void
+octave_base_matrix<MT>::print_info (std::ostream& os,
+				    const std::string& prefix) const
+{
+  matrix.print_info (os, prefix);
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/ov-base-mat.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base-mat.h	Wed May 15 03:21:01 2002 +0000
@@ -63,9 +63,20 @@
 
   ~octave_base_matrix (void) { }
 
-  octave_value *clone (void) { return new octave_base_matrix (*this); }
+  octave_value *clone (void) const { return new octave_base_matrix (*this); }
+  octave_value *empty_clone (void) const { return new octave_base_matrix (); }
+
+  octave_value subsref (const std::string type,
+			const SLList<octave_value_list>& idx);
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value subsasgn (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 const octave_value& rhs);
+
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
+
+  octave_value do_index_op (const octave_value_list& idx)
+    { return do_index_op (idx, 0); }
 
   void assign (const octave_value_list& idx, const MT& rhs);
 
@@ -101,6 +112,8 @@
 
   bool print_name_tag (std::ostream& os, const std::string& name) const;
 
+  void print_info (std::ostream& os, const std::string& prefix) const;
+
 protected:
 
   MT matrix;
--- a/src/ov-base-nd-array.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base-nd-array.cc	Wed May 15 03:21:01 2002 +0000
@@ -50,7 +50,8 @@
 
 template <class AT>
 octave_value
-octave_base_nd_array<AT>::do_index_op (const octave_value_list& idx)
+octave_base_nd_array<AT>::do_index_op (const octave_value_list& idx,
+				       int resize_ok)
 {
   octave_value retval;
 
@@ -61,14 +62,14 @@
       Array<idx_vector> i = idx_list_to_idx_array (idx);
 
       retval
-	= octave_value (new octave_base_nd_array<AT> (AT (array.index (i))));
+	= octave_value (new octave_base_nd_array<AT> (AT (array.index (i, resize_ok))));
     }
   else if (len == 1)
     {
       idx_vector i = idx(0).index_vector ();
 
       retval
-	= octave_value (new octave_base_nd_array<AT> (AT (array.index (i))));
+	= octave_value (new octave_base_nd_array<AT> (AT (array.index (i, resize_ok))));
     }
   else
     {
--- a/src/ov-base-nd-array.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base-nd-array.h	Wed May 15 03:21:01 2002 +0000
@@ -63,9 +63,10 @@
 
   ~octave_base_nd_array (void) { }
 
-  octave_value *clone (void) { return new octave_base_nd_array (*this); }
+  octave_value *clone (void) const { return new octave_base_nd_array (*this); }
+  octave_value *empty_clone (void) const { return new octave_base_nd_array (); }
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
 
   bool is_matrix_type (void) const { return false; }
 
--- a/src/ov-base-scalar.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base-scalar.cc	Wed May 15 03:21:01 2002 +0000
@@ -31,10 +31,85 @@
 #include <iostream>
 
 #include "ov-base.h"
+#include "ov-cx-mat.h"
+#include "ov-re-mat.h"
 #include "ov-base-scalar.h"
 #include "pr-output.h"
 
 template <class ST>
+octave_value
+octave_base_scalar<ST>::subsref (const std::string type,
+				 const SLList<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_index_op (idx.front ());
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval.next_subsref (type, idx);
+}
+
+template <class ST>
+octave_value
+octave_base_scalar<ST>::subsasgn (const std::string type,
+				  const SLList<octave_value_list>& idx,
+				  const octave_value& rhs)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      {
+	if (type.length () == 1)
+	  {
+	    if (idx.front().valid_scalar_indices ()
+		&& rhs.is_scalar_type ()
+		&& rhs.is_numeric_type ())
+	      retval = rhs;
+	    else
+	      retval = numeric_assign (type, idx, rhs);
+	  }
+	else
+	  {
+	    std::string nm = type_name ();
+	    error ("in indexed assignment of %s, last rhs index must be ()",
+		   nm.c_str ());
+	  }
+      }
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval;
+}
+
+template <class ST>
 void
 octave_base_scalar<ST>::print (std::ostream& os, bool pr_as_read_syntax) const
 {
@@ -44,7 +119,8 @@
 
 template <class ST>
 void
-octave_base_scalar<ST>::print_raw (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_scalar<ST>::print_raw (std::ostream& os,
+				   bool pr_as_read_syntax) const
 {
   indent (os);
   octave_print_internal (os, scalar, pr_as_read_syntax);
@@ -52,7 +128,8 @@
 
 template <class ST>
 bool
-octave_base_scalar<ST>::print_name_tag (std::ostream& os, const std::string& name) const
+octave_base_scalar<ST>::print_name_tag (std::ostream& os,
+					const std::string& name) const
 {
   indent (os);
   os << name << " = ";
--- a/src/ov-base-scalar.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base-scalar.h	Wed May 15 03:21:01 2002 +0000
@@ -59,6 +59,13 @@
 
   ~octave_base_scalar (void) { }
 
+  octave_value subsref (const std::string type,
+			const SLList<octave_value_list>& idx);
+
+  octave_value subsasgn (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 const octave_value& rhs);
+
   int rows (void) const { return 1; }
 
   int columns (void) const { return 1; }
--- a/src/ov-base.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base.cc	Wed May 15 03:21:01 2002 +0000
@@ -53,7 +53,25 @@
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value, "<unknown type>");
 
 octave_value
-octave_base_value::do_index_op (const octave_value_list&)
+octave_base_value::subsref (const std::string,
+			    const SLList<octave_value_list>&)
+{
+  std::string nm = type_name ();
+  error ("can't perform indexing operations for %s type", nm.c_str ());
+  return octave_value ();
+}
+
+octave_value_list
+octave_base_value::subsref (const std::string,
+			    const SLList<octave_value_list>&, int)
+{
+  std::string nm = type_name ();
+  error ("can't perform indexing operations for %s type", nm.c_str ());
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::do_index_op (const octave_value_list&, int)
 {
   std::string nm = type_name ();
   error ("can't perform indexing operations for %s type", nm.c_str ());
@@ -77,32 +95,28 @@
 }
 
 octave_value
-octave_base_value::do_struct_elt_index_op (const std::string&,
-					   const octave_value_list&,
-					   bool)
-{
-  std::string nm = type_name ();
-  error ("can't perform indexed structure reference operations for %s type",
-	 nm.c_str ());
-  return octave_value ();
-}
-
-octave_value
-octave_base_value::do_struct_elt_index_op (const std::string&, bool)
+octave_base_value::subsasgn (const std::string type,
+			     const SLList<octave_value_list>& idx,
+			     const octave_value& rhs)
 {
-  std::string nm = type_name ();
-  error ("can't perform structure reference operations for %s type",
-	 nm.c_str ());
-  return octave_value ();
-}
+  octave_value retval;
 
-octave_lvalue
-octave_base_value::struct_elt_ref (octave_value *, const std::string&)
-{
-  std::string nm = type_name ();
-  error ("can't perform structure reference operations for %s type",
-	 nm.c_str ());
-  return octave_lvalue ();
+  if (is_defined ())
+    {
+      std::string nm = type_name ();
+      error ("can't perform indexed assignment for %s type", nm.c_str ());
+    }
+  else
+    {
+      // Create new object of appropriate type for given index and rhs
+      // types and then call subsasgn again for that object.
+
+      octave_value tmp = octave_value::empty_conv (type, rhs);
+
+      retval = tmp.subsasgn (type, idx, rhs);
+    }
+
+  return retval;
 }
 
 octave_value
@@ -143,6 +157,13 @@
   return true;
 }
 
+void
+octave_base_value::print_info (std::ostream& os,
+			       const std::string& prefix) const
+{
+  os << "no info for type: " << type_name () << "\n";
+}
+
 int
 octave_base_value::int_value (bool require_int, bool frc_str_conv) const
 {
@@ -271,6 +292,14 @@
   return retval;
 }
 
+string_vector
+octave_base_value::map_keys (void) const
+{
+  string_vector retval;
+  gripe_wrong_type_arg ("octave_base_value::map_keys()", type_name ());
+  return retval;
+}
+
 octave_stream
 octave_base_value::stream_value (void) const
 {
--- a/src/ov-base.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-base.h	Wed May 15 03:21:01 2002 +0000
@@ -62,7 +62,8 @@
 
   ~octave_base_value (void) { }
 
-  octave_value *clone (void) { return new octave_base_value (*this); }
+  octave_value *clone (void) const { return new octave_base_value (*this); }
+  octave_value *empty_clone (void) const { return new octave_base_value (); }
 
   type_conv_fcn numeric_conversion_function (void) const
     { return static_cast<type_conv_fcn> (0); }
@@ -70,20 +71,26 @@
   octave_value *try_narrowing_conversion (void)
     { return static_cast<octave_value *> (0); }
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value subsref (const std::string type,
+			const SLList<octave_value_list>& idx);
+
+  octave_value_list subsref (const std::string type,
+			     const SLList<octave_value_list>& idx,
+			     int nargout);
+
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
+
+  octave_value do_index_op (const octave_value_list& idx)
+    { return do_index_op (idx, 0); }
 
   octave_value_list
   do_multi_index_op (int nargout, const octave_value_list& idx);
 
   idx_vector index_vector (void) const;
 
-  octave_value
-  do_struct_elt_index_op (const std::string& nm, const octave_value_list& idx,
-			  bool silent);
-
-  octave_value do_struct_elt_index_op (const std::string& nm, bool silent);
-
-  octave_lvalue struct_elt_ref (octave_value *parent, const std::string& nm);
+  octave_value subsasgn (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 const octave_value& rhs);
 
   int rows (void) const { return -1; }
 
@@ -184,6 +191,8 @@
 
   Octave_map map_value (void) const;
 
+  string_vector map_keys (void) const;
+
   octave_stream stream_value (void) const;
 
   int stream_number (void) const;
@@ -206,6 +215,8 @@
 
   bool print_name_tag (std::ostream& os, const std::string& name) const;
 
+  void print_info (std::ostream& os, const std::string& prefix) const;
+
 private:
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
--- a/src/ov-bool-mat.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-bool-mat.h	Wed May 15 03:21:01 2002 +0000
@@ -66,7 +66,8 @@
 
   ~octave_bool_matrix (void) { }
 
-  octave_value *clone (void) { return new octave_bool_matrix (*this); }
+  octave_value *clone (void) const { return new octave_bool_matrix (*this); }
+  octave_value *empty_clone (void) const { return new octave_bool_matrix (); }
 
   type_conv_fcn numeric_conversion_function (void) const;
 
--- a/src/ov-bool.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-bool.cc	Wed May 15 03:21:01 2002 +0000
@@ -76,7 +76,7 @@
 }
 
 octave_value
-octave_bool::do_index_op (const octave_value_list& idx)
+octave_bool::do_index_op (const octave_value_list& idx, int resize_ok)
 {
   octave_value retval;
 
@@ -96,7 +96,7 @@
 
       octave_value tmp (new octave_matrix (matrix_value ()));
 
-      retval = tmp.do_index_op (idx);
+      retval = tmp.do_index_op (idx, resize_ok);
     }
 
   return retval;
--- a/src/ov-bool.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-bool.h	Wed May 15 03:21:01 2002 +0000
@@ -64,11 +64,12 @@
 
   ~octave_bool (void) { }
 
-  octave_value *clone (void) { return new octave_bool (*this); }
+  octave_value *clone (void) const { return new octave_bool (*this); }
+  octave_value *empty_clone (void) const { return new octave_bool (); }
 
   type_conv_fcn numeric_conversion_function (void) const;
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
 
   idx_vector index_vector (void) const { return idx_vector (scalar); }
 
--- a/src/ov-builtin.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-builtin.cc	Wed May 15 03:21:01 2002 +0000
@@ -52,6 +52,37 @@
 }
 
 octave_value_list
+octave_builtin::subsref (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_multi_index_op (nargout, idx.front ());
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval;
+
+  // XXX FIXME XXX
+  //  return retval.next_subsref (type, idx);
+}
+
+octave_value_list
 octave_builtin::do_multi_index_op (int nargout, const octave_value_list& args)
 {
   octave_value_list retval;
--- a/src/ov-builtin.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-builtin.h	Wed May 15 03:21:01 2002 +0000
@@ -50,6 +50,10 @@
 
   ~octave_builtin (void) { }
 
+  octave_value_list subsref (const std::string type,
+			     const SLList<octave_value_list>& idx,
+			     int nargout);
+
   octave_function *function_value (bool) { return this; }
 
   bool is_builtin_function (void) const { return true; }
--- a/src/ov-cell.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-cell.cc	Wed May 15 03:21:01 2002 +0000
@@ -50,6 +50,160 @@
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_cell, "cell");
 
+octave_value
+octave_cell::subsref (const std::string type,
+		      const SLList<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_index_op (idx.front ());
+      break;
+
+    case '{':
+      {
+	octave_value tmp = do_index_op (idx.front ());
+
+	Cell tcell = tmp.cell_value ();
+
+	if (tcell.length () == 1)
+	  retval = tcell(0,0);
+	else
+	  {
+	    int nr = tcell.rows ();
+	    int nc = tcell.columns ();
+	    octave_value_list lst (nr * nc, octave_value ());
+	    int k = 0;
+	    for (int j = 0; j < nc; j++)
+	      for (int i = 0; i < nr; i++)
+		lst(k++) = tcell(i,j);
+	    retval = lst;
+	  }
+      }
+      break;
+
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval.next_subsref (type, idx);
+}
+
+octave_value
+octave_cell::subsasgn (const std::string type,
+		       const SLList<octave_value_list>& idx,
+		       const octave_value& rhs)
+{
+  octave_value retval;
+
+  int n = type.length ();
+
+  octave_value t_rhs = rhs;
+
+  if (n > 1)
+    {
+      switch (type[0])
+	{
+	case '(':
+	  {
+	    octave_value tmp = do_index_op (idx.front (), true);
+
+	    if (! tmp.is_defined ())
+	      tmp = octave_value::empty_conv (type.substr (1), rhs);
+
+	    if (! error_state)
+	      {
+		SLList<octave_value_list> next_idx (idx);
+
+		next_idx.remove_front ();
+
+		t_rhs = tmp.subsasgn (type.substr (1), next_idx, rhs);
+	      }
+	  }
+	  break;
+
+	case '{':
+	  {
+	    octave_value tmp = do_index_op (idx.front (), true);
+
+	    if (! tmp.is_defined ())
+	      tmp = octave_value::empty_conv (type.substr (1), rhs);
+
+	    Cell tcell = tmp.cell_value ();
+
+	    if (! error_state && tcell.length () == 1)
+	      {
+		tmp = tcell(0,0);
+
+		SLList<octave_value_list> next_idx (idx);
+
+		next_idx.remove_front ();
+
+		t_rhs = tmp.subsasgn (type.substr (1), next_idx, rhs);
+	      }
+	  }
+	  break;
+
+	case '.':
+	  {
+	    std::string nm = type_name ();
+	    error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+	  }
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+    }
+
+  switch (type[0])
+    {
+    case '(':
+      {
+	octave_value_list i = idx.front ();
+
+	if (t_rhs.is_cell ())
+	  octave_base_matrix<Cell>::assign (i, t_rhs.cell_value ());
+	else
+	  octave_base_matrix<Cell>::assign (i, Cell (t_rhs));
+
+	retval = octave_value (this, count + 1);
+      }
+      break;
+
+    case '{':
+      {
+	octave_value_list i = idx.front ();
+
+	octave_base_matrix<Cell>::assign (i, Cell (t_rhs));
+
+	retval = octave_value (this, count + 1);
+      }
+      break;
+
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval;
+}
+
 void
 octave_cell::assign (const octave_value_list& idx, const octave_value& rhs)
 {
@@ -59,6 +213,89 @@
     octave_base_matrix<Cell>::assign (idx, Cell (rhs));
 }
 
+octave_value_list
+octave_cell::list_value (void) const
+{
+  octave_value_list retval;
+
+  int nr = rows ();
+  int nc = columns ();
+
+  if (nr == 1 && nc > 0)
+    {
+      retval.resize (nc);
+
+      for (int i = 0; i < nc; i++)
+	retval(i) = matrix(0,i);
+    }
+  else if (nc == 1 && nr > 0)
+    {
+      retval.resize (nr);
+
+      for (int i = 0; i < nr; i++)
+	retval(i) = matrix(i,0);
+    }
+  else
+    error ("invalid conversion from cell array to list");
+
+  return retval;
+}
+
+void
+octave_cell::print (std::ostream& os, bool) const
+{
+  print_raw (os);
+}
+
+void
+octave_cell::print_raw (std::ostream& os, bool) const
+{
+  int nr = rows ();
+  int nc = columns ();
+
+  if (nr > 0 && nc > 0)
+    {
+      indent (os);
+      os << "{";
+      newline (os);
+
+      increment_indent_level ();
+
+      for (int j = 0; j < nc; j++)
+	{
+	  for (int i = 0; i < nr; i++)
+	    {
+	      std::ostrstream buf;
+	      buf << "[" << i+1 << "," << j+1 << "]" << std::ends;
+	      const char *nm = buf.str ();
+
+	      octave_value val = matrix(i,j);
+
+	      val.print_with_name (os, nm);
+
+	      delete [] nm;
+	    }
+	}
+
+      decrement_indent_level ();
+
+      indent (os);
+      os << "}";
+      newline (os);
+    }
+  else
+    os << "{}";
+}
+
+bool
+octave_cell::print_name_tag (std::ostream& os, const std::string& name) const
+{
+  indent (os);
+  os << name << " =";
+  newline (os);
+  return false;
+}
+
 DEFUN (iscell, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} iscell (@var{x})\n\
--- a/src/ov-cell.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-cell.h	Wed May 15 03:21:01 2002 +0000
@@ -66,18 +66,34 @@
 
   void assign (const octave_value_list& idx, const octave_value& rhs);
 
-  octave_value *clone (void) { return new octave_cell (*this); }
+  octave_value *clone (void) const { return new octave_cell (*this); }
+  octave_value *empty_clone (void) const { return new octave_cell (); }
 
 #if 0
   octave_value *try_narrowing_conversion (void);
 #endif
 
+  octave_value subsref (const std::string type,
+			const SLList<octave_value_list>& idx);
+
+  octave_value subsasgn (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 const octave_value& rhs);
+
   bool is_defined (void) const { return true; }
 
   bool is_cell (void) const { return true; }
 
   Cell cell_value (void) const { return matrix; }
 
+  octave_value_list list_value (void) const;
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+  bool print_name_tag (std::ostream& os, const std::string& name) const;
+
 private:
   DECLARE_OCTAVE_ALLOCATOR
 
--- a/src/ov-ch-mat.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-ch-mat.h	Wed May 15 03:21:01 2002 +0000
@@ -76,7 +76,8 @@
 
   ~octave_char_matrix (void) { }
 
-  octave_value *clone (void) { return new octave_char_matrix (*this); }
+  octave_value *clone (void) const { return new octave_char_matrix (*this); }
+  octave_value *empty_clone (void) const { return new octave_char_matrix (); }
 
   bool is_char_matrix (void) const { return true; }
   bool is_real_matrix (void) const { return true; }
--- a/src/ov-colon.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-colon.h	Wed May 15 03:21:01 2002 +0000
@@ -55,7 +55,8 @@
 
   ~octave_magic_colon (void) { }
 
-  octave_value *clone (void) { return new octave_magic_colon (*this); }
+  octave_value *clone (void) const { return new octave_magic_colon (*this); }
+  octave_value *empty_clone (void) const { return new octave_magic_colon (); }
 
   idx_vector index_vector (void) const { return idx_vector (':'); }
 
--- a/src/ov-complex.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-complex.cc	Wed May 15 03:21:01 2002 +0000
@@ -60,24 +60,12 @@
   return retval;
 }
 
-static inline bool
-valid_scalar_indices (const octave_value_list& args)
-{
-  int nargin = args.length ();
-
-  for (int i = 0; i < nargin; i++)
-    if (! args(i).valid_as_scalar_index ())
-      return false;
-
-  return true;
-}
-
 octave_value
-octave_complex::do_index_op (const octave_value_list& idx)
+octave_complex::do_index_op (const octave_value_list& idx, int resize_ok)
 {
   octave_value retval;
 
-  if (valid_scalar_indices (idx))
+  if (idx.valid_scalar_indices ())
     retval = scalar;
   else
     {
@@ -93,7 +81,7 @@
 
       octave_value tmp (new octave_complex_matrix (complex_matrix_value ()));
 
-      retval = tmp.do_index_op (idx);
+      retval = tmp.do_index_op (idx, resize_ok);
     }
 
   return retval;
--- a/src/ov-complex.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-complex.h	Wed May 15 03:21:01 2002 +0000
@@ -64,11 +64,12 @@
 
   ~octave_complex (void) { }
 
-  octave_value *clone (void) { return new octave_complex (*this); }
+  octave_value *clone (void) const { return new octave_complex (*this); }
+  octave_value *empty_clone (void) const { return new octave_complex (); }
 
   octave_value *try_narrowing_conversion (void);
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
 
   bool is_complex_scalar (void) const { return true; }
 
--- a/src/ov-cx-mat.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-cx-mat.h	Wed May 15 03:21:01 2002 +0000
@@ -73,7 +73,8 @@
 
   ~octave_complex_matrix (void) { }
 
-  octave_value *clone (void) { return new octave_complex_matrix (*this); }
+  octave_value *clone (void) const { return new octave_complex_matrix (*this); }
+  octave_value *empty_clone (void) const { return new octave_complex_matrix (); }
 
   octave_value *try_narrowing_conversion (void);
 
--- a/src/ov-fcn.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-fcn.cc	Wed May 15 03:21:01 2002 +0000
@@ -34,7 +34,14 @@
 DEFINE_OCTAVE_ALLOCATOR (octave_function);
 
 octave_function *
-octave_function::clone (void)
+octave_function::clone (void) const
+{
+  panic_impossible ();
+  return 0;
+}
+
+octave_function *
+octave_function::empty_clone (void) const
 {
   panic_impossible ();
   return 0;
--- a/src/ov-fcn.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-fcn.h	Wed May 15 03:21:01 2002 +0000
@@ -50,9 +50,8 @@
 
   ~octave_function (void) { }
 
-  // This should only be called for derived types.
-
-  octave_function *clone (void);
+  octave_function *clone (void) const;
+  octave_function *empty_clone (void) const;
 
   bool is_defined (void) const { return true; }
 
--- a/src/ov-file.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-file.h	Wed May 15 03:21:01 2002 +0000
@@ -60,7 +60,8 @@
 
   ~octave_file (void) { }
 
-  octave_value *clone (void) { return new octave_file (*this); }
+  octave_value *clone (void) const { return new octave_file (*this); }
+  octave_value *empty_clone (void) const { return new octave_file (); }
 
   type_conv_fcn numeric_conversion_function (void) const;
 
--- a/src/ov-list.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-list.cc	Wed May 15 03:21:01 2002 +0000
@@ -43,7 +43,62 @@
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_list, "list");
 
 octave_value
-octave_list::do_index_op (const octave_value_list& idx)
+octave_list::subsref (const std::string type,
+		      const SLList<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      {
+	octave_value_list tmp_idx = idx.front ();
+
+	if (tmp_idx.length () == 1)
+	  {
+	    idx_vector i = tmp_idx (0).index_vector ();
+
+	    retval = octave_value_list (lst.index (i));
+	  }
+	else
+	  error ("only one index allowed for lists");
+      }
+      break;
+
+    case '{':
+      {
+	octave_value_list tmp_idx = idx.front ();
+
+	if (tmp_idx.length () == 1)
+	  {
+	    idx_vector i = tmp_idx (0).index_vector ();
+
+	    octave_value_list tmp = lst.index (i);
+
+	    if (tmp.length () == 1)
+	      retval = tmp(0);
+	  }
+	else
+	  error ("only one index allowed for lists");
+      }
+      break;
+
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval.next_subsref (type, idx);
+}
+
+octave_value
+octave_list::do_index_op (const octave_value_list& idx, int resize_ok)
 {
   octave_value retval;
 
@@ -51,7 +106,7 @@
     {
       idx_vector i = idx (0).index_vector ();
 
-      retval = octave_value_list (lst.index (i));
+      retval = octave_value_list (lst.index (i, resize_ok));
     }
   else
     error ("lists may only be indexed by a single scalar");
@@ -59,6 +114,79 @@
   return retval;
 }
 
+octave_value
+octave_list::subsasgn (const std::string type,
+		       const SLList<octave_value_list>& idx,
+		       const octave_value& rhs)
+{
+  octave_value retval;
+
+  int n = type.length ();
+
+  octave_value t_rhs = rhs;
+
+  if (n > 1)
+    {
+      switch (type[0])
+	{
+	case '(':
+	  {
+	    octave_value tmp = do_index_op (idx.front (), true);
+
+	    if (! tmp.is_defined ())
+	      tmp = octave_value::empty_conv (type.substr (1), rhs);
+
+	    if (! error_state)
+	      {
+		SLList<octave_value_list> next_idx (idx);
+
+		next_idx.remove_front ();
+
+		t_rhs = tmp.subsasgn (type.substr (1), next_idx, rhs);
+	      }
+	  }
+	  break;
+
+	case '{':
+	case '.':
+	  {
+	    std::string nm = type_name ();
+	    error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+	  }
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+    }
+
+  switch (type[0])
+    {
+    case '(':
+      {
+	octave_value_list i = idx.front ();
+
+	assign (i, t_rhs);
+
+	retval = octave_value (this, count + 1);
+      }
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval;
+}
+
 void
 octave_list::assign (const octave_value_list& idx, const octave_value& rhs)
 {
--- a/src/ov-list.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-list.h	Wed May 15 03:21:01 2002 +0000
@@ -61,9 +61,17 @@
 
   ~octave_list (void) { }
 
-  octave_value *clone (void) { return new octave_list (*this); }
+  octave_value *clone (void) const { return new octave_list (*this); }
+  octave_value *empty_clone (void) const { return new octave_list (); }
+
+  octave_value subsref (const std::string type,
+			const SLList<octave_value_list>& idx);
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
+
+  octave_value subsasgn (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 const octave_value& rhs);
 
   void assign (const octave_value_list& idx, const octave_value& rhs);
 
--- a/src/ov-mapper.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-mapper.cc	Wed May 15 03:21:01 2002 +0000
@@ -231,6 +231,37 @@
 }
 
 octave_value_list
+octave_mapper::subsref (const std::string type,
+			const SLList<octave_value_list>& idx,
+			int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_multi_index_op (nargout, idx.front ());
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval;
+
+  // XXX FIXME XXX
+  //  return retval.next_subsref (type, idx);
+}
+
+octave_value_list
 octave_mapper::do_multi_index_op (int, const octave_value_list& args)
 {
   octave_value retval;
--- a/src/ov-mapper.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-mapper.h	Wed May 15 03:21:01 2002 +0000
@@ -63,6 +63,10 @@
 
   octave_function *function_value (bool) { return this; }
 
+  octave_value_list subsref (const std::string type,
+			     const SLList<octave_value_list>& idx,
+			     int nargout);
+
   octave_value_list
   do_multi_index_op (int nargout, const octave_value_list& args);
 
--- a/src/ov-range.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-range.cc	Wed May 15 03:21:01 2002 +0000
@@ -35,6 +35,7 @@
 
 #include "gripes.h"
 #include "ops.h"
+#include "oct-obj.h"
 #include "ov-range.h"
 #include "ov-re-mat.h"
 #include "ov-scalar.h"
@@ -81,7 +82,34 @@
 }
 
 octave_value
-octave_range::do_index_op (const octave_value_list& idx)
+octave_range::subsref (const std::string type,
+		       const SLList<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_index_op (idx.front ());
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval.next_subsref (type, idx);
+}
+
+octave_value
+octave_range::do_index_op (const octave_value_list& idx, int resize_ok)
 {
   // XXX FIXME XXX -- this doesn't solve the problem of
   //
@@ -95,7 +123,7 @@
 
   octave_value tmp (new octave_matrix (range.matrix_value ()));
 
-  return tmp.do_index_op (idx);
+  return tmp.do_index_op (idx, resize_ok);
 }
 
 double
--- a/src/ov-range.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-range.h	Wed May 15 03:21:01 2002 +0000
@@ -40,6 +40,7 @@
 #include "oct-alloc.h"
 #include "str-vec.h"
 
+#include "SLList.h"
 #include "error.h"
 #include "ov-base.h"
 #include "ov-typeinfo.h"
@@ -78,13 +79,20 @@
 
   ~octave_range (void) { }
 
-  octave_value *clone (void) { return new octave_range (*this); }
+  octave_value *clone (void) const { return new octave_range (*this); }
+  octave_value *empty_clone (void) const { return new octave_range (); }
 
   type_conv_fcn numeric_conversion_function (void) const;
 
   octave_value *try_narrowing_conversion (void);
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value subsref (const std::string type,
+			const SLList<octave_value_list>& idx);
+
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
+
+  octave_value do_index_op (const octave_value_list& idx)
+    { return do_index_op (idx, 0); }
 
   idx_vector index_vector (void) const { return idx_vector (range); }
 
--- a/src/ov-re-mat.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-re-mat.h	Wed May 15 03:21:01 2002 +0000
@@ -73,7 +73,8 @@
 
   ~octave_matrix (void) { }
 
-  octave_value *clone (void) { return new octave_matrix (*this); }
+  octave_value *clone (void) const { return new octave_matrix (*this); }
+  octave_value *empty_clone (void) const { return new octave_matrix (); }
 
   octave_value *try_narrowing_conversion (void);
 
--- a/src/ov-re-nd-array.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-re-nd-array.h	Wed May 15 03:21:01 2002 +0000
@@ -60,7 +60,8 @@
 
   ~octave_double_nd_array (void) { }
 
-  octave_value *clone (void) { return new octave_double_nd_array (*this); }
+  octave_value *clone (void) const { return new octave_double_nd_array (*this); }
+  octave_value *empty_clone (void) const { return new octave_double_nd_array (); }
 
 #if 0
   octave_value *try_narrowing_conversion (void);
--- a/src/ov-scalar.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-scalar.cc	Wed May 15 03:21:01 2002 +0000
@@ -49,24 +49,12 @@
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_scalar, "scalar");
 
-static inline bool
-valid_scalar_indices (const octave_value_list& args)
-{
-  int nargin = args.length ();
-
-  for (int i = 0; i < nargin; i++)
-    if (! args(i).valid_as_scalar_index ())
-      return false;
-
-  return true;
-}
-
 octave_value
-octave_scalar::do_index_op (const octave_value_list& idx)
+octave_scalar::do_index_op (const octave_value_list& idx, int resize_ok)
 {
   octave_value retval;
 
-  if (valid_scalar_indices (idx))
+  if (idx.valid_scalar_indices ())
     retval = scalar;
   else
     {
@@ -82,7 +70,7 @@
 
       octave_value tmp (new octave_matrix (matrix_value ()));
 
-      retval = tmp.do_index_op (idx);
+      retval = tmp.do_index_op (idx, resize_ok);
     }
 
   return retval;
--- a/src/ov-scalar.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-scalar.h	Wed May 15 03:21:01 2002 +0000
@@ -65,9 +65,10 @@
 
   ~octave_scalar (void) { }
 
-  octave_value *clone (void) { return new octave_scalar (*this); }
+  octave_value *clone (void) const { return new octave_scalar (*this); }
+  octave_value *empty_clone (void) const { return new octave_scalar (); }
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
 
   idx_vector index_vector (void) const { return idx_vector (scalar); }
 
--- a/src/ov-str-mat.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-str-mat.cc	Wed May 15 03:21:01 2002 +0000
@@ -62,7 +62,8 @@
 }
 
 octave_value
-octave_char_matrix_str::do_index_op (const octave_value_list& idx)
+octave_char_matrix_str::do_index_op (const octave_value_list& idx,
+				     int resize_ok)
 {
   octave_value retval;
 
@@ -75,7 +76,8 @@
 	idx_vector i = idx (0).index_vector ();
 	idx_vector j = idx (1).index_vector ();
 
-	retval = octave_value (charMatrix (matrix.index (i, j)), true);
+	retval = octave_value (charMatrix (matrix.index (i, j, resize_ok)),
+			       true);
       }
       break;
 
@@ -83,7 +85,7 @@
       {
 	idx_vector i = idx (0).index_vector ();
 
-	retval = octave_value (charMatrix (matrix.index (i)), true);
+	retval = octave_value (charMatrix (matrix.index (i, resize_ok)), true);
       }
       break;
 
--- a/src/ov-str-mat.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-str-mat.h	Wed May 15 03:21:01 2002 +0000
@@ -79,11 +79,12 @@
 
   ~octave_char_matrix_str (void) { }
 
-  octave_value *clone (void) { return new octave_char_matrix_str (*this); }
+  octave_value *clone (void) const { return new octave_char_matrix_str (*this); }
+  octave_value *empty_clone (void) const { return new octave_char_matrix_str (); }
 
   type_conv_fcn numeric_conversion_function (void) const;
 
-  octave_value do_index_op (const octave_value_list& idx);
+  octave_value do_index_op (const octave_value_list& idx, int resize_ok);
 
   void assign (const octave_value_list& idx, const charMatrix& rhs);
 
--- a/src/ov-struct.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-struct.cc	Wed May 15 03:21:01 2002 +0000
@@ -30,6 +30,7 @@
 
 #include <iostream>
 
+#include "Cell.h"
 #include "error.h"
 #include "oct-lvalue.h"
 #include "ov-list.h"
@@ -41,35 +42,324 @@
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, "struct");
 
-octave_value
-octave_struct::do_struct_elt_index_op (const std::string& nm,
-				       const octave_value_list& idx,
-				       bool silent)
+octave_value_list
+octave_struct::dotref (const octave_value_list& idx)
 {
-  // XXX DO_ME XXX
-  return octave_value ();
-}
+  octave_value_list retval;
+
+  assert (idx.length () == 1);
 
-octave_value
-octave_struct::do_struct_elt_index_op (const std::string& nm, bool silent)
-{
-  octave_value retval;
+  std::string nm = idx(0).string_value ();
+
+  Pix p = map.seek (nm);
 
-  Pix idx = map.seek (nm);
-
-  if (idx)
-    retval = map.contents (idx);
-  else if (! silent)
+  if (p)
+    retval = map.contents (p);
+  else
     error ("structure has no member `%s'", nm.c_str ());
 
   return retval;
 }
 
-octave_lvalue
-octave_struct::struct_elt_ref (octave_value *, const std::string& nm)
+static void
+gripe_invalid_index (void)
+{
+  error ("invalid index for structure array");
+}
+
+static void
+gripe_invalid_index_for_assignment (void)
+{
+  error ("invalid index for structure array assignment");
+}
+
+static void
+gripe_invalid_index_type (const std::string& nm, char t)
+{
+  error ("%s cannot be indexed with %c", nm.c_str (), t);
+}
+
+static void
+gripe_failed_assignment (void)
+{
+  error ("assignment to structure element failed");
+}
+
+octave_value
+octave_struct::subsref (const std::string type,
+			const SLList<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  int skip = 1;
+
+  switch (type[0])
+    {
+    case '(':
+      {
+	if (type.length () > 1 && type[1] == '.')
+	  {
+	    Pix p = idx.first ();
+	    idx.next (p);
+	    octave_value_list key_idx = idx(p);
+
+	    octave_value_list tmp = dotref (key_idx);
+
+	    if (! error_state)
+	      {
+		octave_value_list t_idx = idx.front ();
+
+		if (t_idx.length () == 1)
+		  {
+		    idx_vector i = t_idx(0).index_vector ();
+		    octave_value_list t = tmp.index (i);
+
+		    retval = (t.length () == 1) ? t(0) : octave_value (t);
+
+		    // We handled two index elements, so tell
+		    // next_subsref to skip both of them.
+
+		    skip++;
+		  }
+		else
+		  gripe_invalid_index ();
+	      }
+	  }
+	else
+	  {
+	    octave_value_list t_idx = idx.front ();
+
+	    if (t_idx.length () == 1)
+	      {
+		idx_vector i = t_idx(0).index_vector ();
+		retval = map.index (i);
+	      }
+	    else
+	      gripe_invalid_index ();
+	  }
+      }
+      break;
+
+    case '.':
+      {
+	octave_value_list t = dotref (idx.front ());
+
+	retval = (t.length () == 1) ? t(0) : octave_value (t);
+      }
+      break;
+
+    case '{':
+      gripe_invalid_index_type (type_name (), type[0]);
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  if (! error_state)
+    retval = retval.next_subsref (type, idx, skip);
+
+  return retval;
+}
+
+octave_value
+octave_struct::numeric_conv (const octave_value_list& val,
+			     const std::string& type)
+{
+  octave_value retval;
+
+  if (val.length () == 1)
+    {
+      retval = val(0);
+
+      if (type.length () > 0 && type[0] == '.' && ! retval.is_map ())
+	retval = Octave_map ();
+    }
+  else
+    gripe_invalid_index_for_assignment ();
+
+  return retval;
+}
+
+octave_value
+octave_struct::subsasgn (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 const octave_value& rhs)
 {
-  // XXX FIXME XXX -- struct array
-  return octave_lvalue (&map[nm](0));
+  octave_value retval;
+
+  int n = type.length ();
+
+  octave_value t_rhs = rhs;
+
+  if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
+    {
+      switch (type[0])
+	{
+	case '(':
+	  {
+	    if (type.length () > 1 && type[1] == '.')
+	      {
+		Pix p = idx.first ();
+		octave_value_list t_idx = idx(p);
+
+		if (t_idx.length () == 1)
+		  {
+		    idx.next (p);
+		    octave_value_list key_idx = idx(p);
+
+		    assert (key_idx.length () == 1);
+
+		    std::string key = key_idx(0).string_value ();
+
+		    octave_value u;
+
+		    if (! map.contains (key))
+		      u = octave_value::empty_conv (type.substr (2), rhs);
+		    else
+		      {
+			octave_value_list map_val = map[key];
+
+			octave_value_list t_idx = idx.front ();
+
+			idx_vector i = t_idx(0).index_vector ();
+
+			octave_value_list map_elt = map_val.index (i, true);
+
+			u = numeric_conv (map_elt, type.substr (2));
+		      }
+
+		    if (! error_state)
+		      {
+			SLList<octave_value_list> next_idx (idx);
+
+			// We handled two index elements, so subsasgn to
+			// needs to skip both of them.
+
+			next_idx.remove_front ();
+			next_idx.remove_front ();
+
+			t_rhs = u.subsasgn (type.substr (2), next_idx, rhs);
+		      }
+		  }
+		else
+		  gripe_invalid_index_for_assignment ();
+	      }
+	    else
+	      gripe_invalid_index_for_assignment ();
+	  }
+	  break;
+
+	case '.':
+	  {
+	    octave_value_list key_idx = idx.front ();
+
+	    assert (key_idx.length () == 1);
+
+	    std::string key = key_idx(0).string_value ();
+
+	    octave_value u;
+
+	    if (! map.contains (key))
+	      u = octave_value::empty_conv (type.substr (1), rhs);
+	    else
+	      {
+		octave_value_list map_val = map[key];
+
+		u = numeric_conv (map_val, type.substr (1));
+	      }
+
+	    if (! error_state)
+	      {
+		SLList<octave_value_list> next_idx (idx);
+
+		next_idx.remove_front ();
+
+		t_rhs = u.subsasgn (type.substr (1), next_idx, rhs);
+	      }
+	  }
+	  break;
+
+	case '{':
+	  gripe_invalid_index_type (type_name (), type[0]);
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+    }
+
+  if (! error_state)
+    {
+      switch (type[0])
+	{
+	case '(':
+	  {
+	    if (n > 1 && type[1] == '.')
+	      {
+		Pix p = idx.first ();
+		idx.next (p);
+		octave_value_list key_idx = idx(p);
+
+		assert (key_idx.length () == 1);
+
+		std::string key = key_idx(0).string_value ();
+
+		if (! error_state)
+		  {
+		    octave_value_list t_idx = idx.front ();
+
+		    if (t_idx.length () == 1)
+		      {
+			idx_vector i = t_idx(0).index_vector ();
+
+			map.assign (i, key, t_rhs);
+
+			if (! error_state)
+			  retval = octave_value (this, count + 1);
+			else
+			  gripe_failed_assignment ();
+		      }
+		    else
+		      gripe_invalid_index_for_assignment ();
+		  }
+		else
+		  gripe_failed_assignment ();
+	      }
+	    else
+	      gripe_invalid_index_for_assignment ();
+	  }
+	  break;
+
+	case '.':
+	  {
+	    octave_value_list key_idx = idx.front ();
+
+	    assert (key_idx.length () == 1);
+
+	    std::string key = key_idx(0).string_value ();
+
+	    map.assign (key, t_rhs);
+
+	    if (! error_state)
+	      retval = octave_value (this, count + 1);
+	    else
+	      gripe_failed_assignment ();
+	  }
+	  break;
+
+	case '{':
+	  gripe_invalid_index_type (type_name (), type[0]);
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+    }
+  else
+    gripe_failed_assignment ();
+
+  return retval;
 }
 
 void
--- a/src/ov-struct.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-struct.h	Wed May 15 03:21:01 2002 +0000
@@ -64,24 +64,31 @@
 
   ~octave_struct (void) { }
 
-  octave_value *clone (void) { return new octave_struct (*this); }
+  octave_value *clone (void) const { return new octave_struct (*this); }
+  octave_value *empty_clone (void) const { return new octave_struct (); }
+
+  octave_value_list dotref (const octave_value_list& idx);
 
-  octave_value
-  do_struct_elt_index_op (const std::string& nm, const octave_value_list& idx,
-			  bool silent);
+  octave_value subsref (const std::string type,
+			const SLList<octave_value_list>& idx);
 
-  octave_value do_struct_elt_index_op (const std::string& nm, bool silent);
+  static octave_value numeric_conv (const octave_value_list& val,
+				    const std::string& type);
 
-  octave_lvalue struct_elt_ref (octave_value *parent, const std::string& nm);
+  octave_value subsasgn (const std::string type,
+			 const SLList<octave_value_list>& idx,
+			 const octave_value& rhs);
 
   bool is_defined (void) const { return true; }
 
-  bool is_constant (void) const { return false; }
+  bool is_constant (void) const { return true; }
 
   bool is_map (void) const { return true; }
 
   Octave_map map_value (void) const { return map; }
 
+  string_vector map_keys (void) const { return map.keys (); }
+
   void print (std::ostream& os, bool pr_as_read_syntax = false) const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
--- a/src/ov-usr-fcn.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-usr-fcn.cc	Wed May 15 03:21:01 2002 +0000
@@ -257,6 +257,37 @@
 }
 
 octave_value_list
+octave_user_function::subsref (const std::string type,
+			       const SLList<octave_value_list>& idx,
+			       int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_multi_index_op (nargout, idx.front ());
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval;
+
+  // XXX FIXME XXX
+  //  return retval.next_subsref (type, idx);
+}
+
+octave_value_list
 octave_user_function::do_multi_index_op (int nargout,
 					 const octave_value_list& args)
 {
@@ -450,6 +481,15 @@
 }
 
 void
+octave_user_function::print_symtab_info (std::ostream& os) const
+{
+  if (sym_tab)
+    sym_tab->print_info (os);
+  else
+    warning ("%s: no symbol table info!", fcn_name.c_str ());
+}
+
+void
 octave_user_function::print_code_function_header (void)
 {
   tree_print_code tpc (octave_stdout, Vps4);
--- a/src/ov-usr-fcn.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-usr-fcn.h	Wed May 15 03:21:01 2002 +0000
@@ -127,10 +127,16 @@
 
   void restore_args_passed (void)
     {
-      if (! saved_args.empty ())
+      if (saved_args.empty ())
+	args_passed = octave_value_list ();
+      else
 	args_passed = saved_args.pop ();
     }
 
+  octave_value_list subsref (const std::string type,
+			     const SLList<octave_value_list>& idx,
+			     int nargout);
+
   octave_value_list
   do_multi_index_op (int nargout, const octave_value_list& args);
 
@@ -148,6 +154,8 @@
 
   void accept (tree_walker& tw);
 
+  void print_symtab_info (std::ostream& os) const;
+
 private:
 
   octave_user_function (void);
--- a/src/ov-va-args.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov-va-args.h	Wed May 15 03:21:01 2002 +0000
@@ -55,7 +55,8 @@
 
   ~octave_all_va_args (void) { }
 
-  octave_value *clone (void) { return new octave_all_va_args (*this); }
+  octave_value *clone (void) const { return new octave_all_va_args (*this); }
+  octave_value *empty_clone (void) const { return new octave_all_va_args (); }
 
   bool is_defined (void) const { return true; }
 
--- a/src/ov.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov.cc	Wed May 15 03:21:01 2002 +0000
@@ -32,7 +32,6 @@
 #include "str-vec.h"
 
 #include "oct-obj.h"
-#include "oct-lvalue.h"
 #include "ov.h"
 #include "ov-base.h"
 #include "ov-bool.h"
@@ -508,10 +507,10 @@
   rep->count = 1;
 }
 
-octave_value::octave_value (octave_value *new_rep)
+octave_value::octave_value (octave_value *new_rep, int count)
   : rep (new_rep)
 {
-  rep->count = 1;
+  rep->count = count;
 }
 
 octave_value::~octave_value (void)
@@ -529,7 +528,7 @@
 }
 
 octave_value *
-octave_value::clone (void)
+octave_value::clone (void) const
 {
   panic_impossible ();
   return 0;
@@ -551,34 +550,121 @@
 }
 
 octave_value_list
+octave_value::subsref (const std::string type,
+		       const SLList<octave_value_list>& idx, int nargout)
+{
+  if (is_constant ())
+    return rep->subsref (type, idx);
+  else
+    return rep->subsref (type, idx, nargout);
+}
+
+octave_value
+octave_value::next_subsref (const std::string type,
+			    const SLList<octave_value_list>& idx,
+			    int skip) 
+{
+  assert (skip > 0);
+
+  if (idx.length () > skip)
+    {
+      SLList<octave_value_list> new_idx (idx);
+      for (int i = 0; i < skip; i++)
+	new_idx.remove_front ();
+      return subsref (type.substr (skip), new_idx);
+    }
+  else
+    return *this;
+}
+
+octave_value_list
 octave_value::do_multi_index_op (int nargout, const octave_value_list& idx)
 {
   return rep->do_multi_index_op (nargout, idx);
 }
 
 static void
-gripe_no_conversion (const std::string& on, const std::string& tn1, const std::string& tn2)
+gripe_no_conversion (const std::string& on, const std::string& tn1,
+		     const std::string& tn2)
 {
   error ("operator %s: no conversion for assignment of `%s' to indexed `%s'",
 	 on.c_str (), tn2.c_str (), tn1.c_str ());
 }
 
+#if 0
 static void
-gripe_assign_failed (const std::string& on, const std::string& tn1, const std::string& tn2)
+gripe_assign_failed (const std::string& on, const std::string& tn1,
+		     const std::string& tn2)
 {
   error ("assignment failed for `%s %s %s'",
 	 tn1.c_str (), on.c_str (), tn2.c_str ());
 }
+#endif
 
 static void
-gripe_assign_failed_or_no_method (const std::string& on, const std::string& tn1,
+gripe_assign_failed_or_no_method (const std::string& on,
+				  const std::string& tn1,
 				  const std::string& tn2)
 {
   error ("assignment failed, or no method for `%s %s %s'",
 	 tn1.c_str (), on.c_str (), tn2.c_str ());
 }
 
-void
+octave_value
+octave_value::subsasgn (const std::string type,
+			const SLList<octave_value_list>& idx,
+			const octave_value& rhs)
+{
+  return rep->subsasgn (type, idx, rhs);
+}
+
+octave_value
+octave_value::assign (assign_op op, const std::string type,
+		      const SLList<octave_value_list>& idx,
+		      const octave_value& rhs)
+{
+  octave_value retval;
+
+  make_unique ();
+
+  octave_value t_rhs = rhs;
+
+  if (op != op_asn_eq)
+    {
+      // XXX FIXME XXX -- only do the following stuff if we can't find
+      // a specific function to call to handle the op= operation for
+      // the types we have.
+
+      octave_value t = subsref (type, idx);
+
+      if (! error_state)
+	{
+	  binary_op binop = op_eq_to_binary_op (op);
+
+	  if (! error_state)
+	    t_rhs = do_binary_op (binop, t, rhs);
+	}
+    }
+
+  if (! error_state)
+    {
+      if (type[0] == '.' && ! is_map ())
+	{
+	  octave_value tmp = Octave_map ();
+	  retval = tmp.subsasgn (type, idx, t_rhs);
+	}
+      else
+	retval = subsasgn (type, idx, t_rhs);
+    }
+
+  if (error_state)
+    gripe_assign_failed_or_no_method (assign_op_as_string (op),
+				      type_name (), rhs.type_name ());
+
+  return retval;
+}
+
+const octave_value&
 octave_value::assign (assign_op op, const octave_value& rhs)
 {
   if (op == op_asn_eq)
@@ -603,119 +689,8 @@
 	gripe_assign_failed_or_no_method (assign_op_as_string (op),
 					  type_name (), rhs.type_name ());
     }
-}
 
-void
-octave_value::simple_assign (octave_value::assign_op orig_op,
-			     const octave_value_list& idx,
-			     const octave_value& rhs)
-{
-  make_unique ();
-
-  bool assignment_ok = try_assignment (op_asn_eq, idx, rhs);
-
-  if (! (error_state || assignment_ok))
-    {
-      assignment_ok = try_assignment_with_conversion (op_asn_eq, idx, rhs);
-
-      if (! (error_state || assignment_ok))
-	gripe_no_conversion (assign_op_as_string (orig_op),
-			     type_name (), rhs.type_name ());
-    }
-}
-
-void
-octave_value::assign (octave_value::assign_op op,
-		      const octave_value_list& idx,
-		      const octave_value& rhs)
-{
-  if (Vresize_on_range_error || is_defined ())
-    {
-      if (op == op_asn_eq)
-	simple_assign (op, idx, rhs);
-      else
-	{
-	  // XXX FIXME XXX -- only do the following stuff if we can't
-	  // find a specific function to call to handle the op=
-	  // operation for the types we have.
-
-	  octave_value t1 = *this;
-
-	  t1 = t1.do_index_op (idx);
-
-	  if (! error_state)
-	    {
-	      binary_op binop = op_eq_to_binary_op (op);
-
-	      if (! error_state)
-		{
-		  octave_value t2 = do_binary_op (binop, t1, rhs);
-
-		  if (! error_state)
-		    {
-		      simple_assign (op, idx, t2);
-
-		      if (error_state)
-			gripe_assign_failed (assign_op_as_string (op),
-					     type_name (), rhs.type_name ());
-		    }
-		  else
-		    gripe_assign_failed_or_no_method (assign_op_as_string (op),
-						      type_name (),
-						      rhs.type_name ());
-		}
-	      else
-		gripe_assign_failed_or_no_method (assign_op_as_string (op),
-						  type_name (),
-						  rhs.type_name ());
-	    }
-	  else
-	    gripe_assign_failed (assign_op_as_string (op),
-				 type_name (), rhs.type_name ());
-	}
-
-      if (! error_state)
-	maybe_mutate ();
-    }
-  else
-    {
-      error ("indexed assignment to previously undefined variables");
-      error ("is only possible when resize_on_range_error is true");
-    }
-}
-
-void
-octave_value::assign_struct_elt (assign_op op, const std::string& elt_nm,
-				 const octave_value& rhs)
-{
-  make_unique ();
-
-  rep->assign_struct_elt (op, elt_nm, rhs);
-}
-
-
-void
-octave_value::assign_struct_elt (assign_op op, const std::string& elt_nm,
-				 const octave_value_list& idx,
-				 const octave_value& rhs)
-{
-  make_unique ();
-
-  rep->assign_struct_elt (op, elt_nm, idx, rhs);
-}
-
-octave_lvalue
-octave_value::struct_elt_ref (const std::string& nm)
-{
-  return rep->struct_elt_ref (this, nm);
-}
-
-octave_lvalue
-octave_value::struct_elt_ref (octave_value *, const std::string&)
-{
-  panic_impossible ();
-
-  return octave_lvalue ();
+  return *this;
 }
 
 Cell
@@ -980,164 +955,113 @@
 }
 
 static void
-gripe_assign_conversion_failed (const std::string& tn1, const std::string& tn2)
+gripe_assign_conversion_failed (const std::string& tn1,
+				const std::string& tn2)
 {
   error ("type conversion for assignment of `%s' to indexed `%s' failed",
 	 tn2.c_str (), tn1.c_str ());
 }
 
-bool
-octave_value::convert_and_assign (octave_value::assign_op op,
-				  const octave_value_list& idx,
-				  const octave_value& rhs)
-{
-  bool assignment_ok = false;
-
-  int t_lhs = type_id ();
-  int t_rhs = rhs.type_id ();
-
-  int t_result
-    = octave_value_typeinfo::lookup_pref_assign_conv (t_lhs, t_rhs);
-
-  if (t_result >= 0)
-    {
-      type_conv_fcn cf
-	= octave_value_typeinfo::lookup_widening_op (t_lhs, t_result);
-
-      if (cf)
-	{
-	  octave_value *tmp = cf (*rep);
-
-	  if (tmp)
-	    {
-	      octave_value *old_rep = rep;
-	      rep = tmp;
-	      rep->count = 1;
-
-	      assignment_ok = try_assignment (op, idx, rhs);
-
-	      if (! assignment_ok && old_rep)
-		{
-		  if (--rep->count == 0)
-		    delete rep;
-
-		  rep = old_rep;
-		  old_rep = 0;
-		}
-
-	      if (old_rep && --old_rep->count == 0)
-		delete old_rep;
-	    }
-	  else
-	    gripe_assign_conversion_failed (type_name (), rhs.type_name ());
-	}
-      else
-	gripe_indexed_assignment (type_name (), rhs.type_name ());
-    }
-
-  return (assignment_ok && ! error_state);
-}
-
-bool
-octave_value::try_assignment_with_conversion (octave_value::assign_op op,
-					      const octave_value_list& idx,
-					      const octave_value& rhs)
-{
-  bool assignment_ok = convert_and_assign (op, idx, rhs);
-
-  if (! (error_state || assignment_ok))
-    {
-      octave_value tmp_rhs;
-      type_conv_fcn cf_rhs = rhs.numeric_conversion_function ();
-
-      if (cf_rhs)
-	{
-	  octave_value *tmp = cf_rhs (*rhs.rep);
-
-	  if (tmp)
-	    tmp_rhs = octave_value (tmp);
-	  else
-	    {
-	      gripe_assign_conversion_failed (type_name (), rhs.type_name ());
-	      return false;
-	    }
-	}
-      else
-	tmp_rhs = rhs;
-
-      octave_value *old_rep = 0;
-      type_conv_fcn cf_this = numeric_conversion_function ();
-
-      if (cf_this)
-	{
-	  old_rep = rep;
-
-	  octave_value *tmp = cf_this (*rep);
-
-	  if (tmp)
-	    {
-	      rep = tmp;
-	      rep->count = 1;
-	    }
-	  else
-	    {
-	      gripe_assign_conversion_failed (type_name (), rhs.type_name ());
-	      return false;
-	    }
-	}
-
-      if (cf_this || cf_rhs)
-	{
-	  assignment_ok = try_assignment (op, idx, tmp_rhs);
-
-	  if (! (error_state || assignment_ok))
-	    assignment_ok = convert_and_assign (op, idx, tmp_rhs);
-	}
-
-      if (! assignment_ok && old_rep)
-	{
-	  if (--rep->count == 0)
-	    delete rep;
-
-	  rep = old_rep;
-	  old_rep = 0;
-	}
-
-      if (old_rep && --old_rep->count == 0)
-	delete old_rep;
-    }
-
-  return (assignment_ok && ! error_state);
-}
-
-bool
-octave_value::try_assignment (octave_value::assign_op op,
-			      const octave_value_list& idx,
+octave_value
+octave_value::numeric_assign (const std::string type,
+			      const SLList<octave_value_list>& idx,
 			      const octave_value& rhs)
 {
-  bool retval = false;
+  octave_value retval;
 
   int t_lhs = type_id ();
   int t_rhs = rhs.type_id ();
 
   assign_op_fcn f
-    = octave_value_typeinfo::lookup_assign_op (op, t_lhs, t_rhs);
+    = octave_value_typeinfo::lookup_assign_op (op_asn_eq, t_lhs, t_rhs);
+
+  bool done = false;
 
   if (f)
     {
-      f (*rep, idx, *(rhs.rep));
+      f (*this, idx.front (), rhs.get_rep ());
 
-      retval = (! error_state);
+      done = (! error_state);
     }
+
+  if (done)
+    retval = octave_value (this, count + 1);
   else
     {
-      f = octave_value_typeinfo::lookup_assignany_op (op, t_lhs);
+      int t_result
+	= octave_value_typeinfo::lookup_pref_assign_conv (t_lhs, t_rhs);
+
+      if (t_result >= 0)
+	{
+	  type_conv_fcn cf
+	    = octave_value_typeinfo::lookup_widening_op (t_lhs, t_result);
+
+	  if (cf)
+	    {
+	      octave_value *tmp (cf (*this));
 
-      if (f)
+	      if (tmp)
+		{
+		  retval = tmp->subsasgn (type, idx, rhs);
+
+		  done = (! error_state);
+		}
+	      else
+		gripe_assign_conversion_failed (type_name (),
+						rhs.type_name ());
+	    }
+	  else
+	    gripe_indexed_assignment (type_name (), rhs.type_name ());
+	}
+
+      if (! (done || error_state))
 	{
-	  f (*rep, idx, rhs);
+	  octave_value tmp_rhs;
+	  type_conv_fcn cf_rhs = rhs.numeric_conversion_function ();
+
+	  if (cf_rhs)
+	    {
+	      octave_value *tmp = cf_rhs (rhs.get_rep ());
+
+	      if (tmp)
+		tmp_rhs = octave_value (tmp);
+	      else
+		{
+		  gripe_assign_conversion_failed (type_name (),
+						  rhs.type_name ());
+		  return octave_value ();
+		}
+	    }
+	  else
+	    tmp_rhs = rhs;
+
+	  type_conv_fcn cf_this = numeric_conversion_function ();
+
+	  octave_value *tmp_lhs = this;
 
-	  retval = (! error_state);
+	  if (cf_this)
+	    {
+	      octave_value *tmp = cf_this (*this);
+
+	      if (tmp)
+		tmp_lhs = tmp;
+	      else
+		{
+		  gripe_assign_conversion_failed (type_name (),
+						  rhs.type_name ());
+		  return octave_value ();
+		}
+	    }
+
+	  if (cf_this || cf_rhs)
+	    {
+	      retval = tmp_lhs->subsasgn (type, idx, tmp_rhs);
+
+	      done = (! error_state);
+	    }
+	  else
+	    gripe_no_conversion (assign_op_as_string (op_asn_eq),
+				 type_name (), rhs.type_name ());
 	}
     }
 
@@ -1145,7 +1069,8 @@
 }
 
 static void
-gripe_binary_op (const std::string& on, const std::string& tn1, const std::string& tn2)
+gripe_binary_op (const std::string& on, const std::string& tn1,
+		 const std::string& tn2)
 {
   error ("binary operator `%s' not implemented for `%s' by `%s' operations",
 	 on.c_str (), tn1.c_str (), tn2.c_str ());
@@ -1158,8 +1083,8 @@
 }
 
 octave_value
-do_binary_op (octave_value::binary_op op, const octave_value& v1,
-	      const octave_value& v2)
+do_binary_op (octave_value::binary_op op,
+	      const octave_value& v1, const octave_value& v2)
 {
   octave_value retval;
 
@@ -1233,6 +1158,16 @@
   return retval;
 }
 
+void
+octave_value::print_info (std::ostream& os, const std::string& prefix) const
+{
+  os << prefix << "type_name: " << type_name () << "\n"
+     << prefix << "count:     " << get_count () << "\n"
+     << prefix << "rep info:  ";
+
+  rep->print_info (os, prefix + " ");
+}
+
 static void
 gripe_unary_op (const std::string& on, const std::string& tn)
 {
@@ -1291,14 +1226,15 @@
 }
 
 static void
-gripe_unary_op_conversion_failed (const std::string& op, const std::string& tn)
+gripe_unary_op_conversion_failed (const std::string& op,
+				  const std::string& tn)
 {
   error ("operator %s: type conversion for `%s' failed",
 	 op.c_str (), tn.c_str ());
 }
 
-void
-octave_value::do_non_const_unary_op (octave_value::unary_op op)
+const octave_value&
+octave_value::do_non_const_unary_op (unary_op op)
 {
   octave_value retval;
 
@@ -1359,30 +1295,50 @@
       else
 	gripe_unary_op (octave_value::unary_op_as_string (op), type_name ());
     }
+
+  return *this;
 }
 
+#if 0
 static void
-gripe_unary_op_failed_or_no_method (const std::string& on, const std::string& tn)
+gripe_unary_op_failed_or_no_method (const std::string& on,
+				    const std::string& tn) 
 {
   error ("operator %s: no method, or unable to evaluate for %s operand",
 	 on.c_str (), tn.c_str ());
 }
+#endif
 
 void
-octave_value::do_non_const_unary_op (octave_value::unary_op op,
-				     const octave_value_list& idx)
+octave_value::do_non_const_unary_op (unary_op op, const octave_value_list& idx)
 {
-  // XXX FIXME XXX -- only do the following stuff if we can't find a
-  // specific function to call to handle the op= operation for the
-  // types we have.
+  abort ();
+}
+
+octave_value
+octave_value::do_non_const_unary_op (unary_op op, const std::string type,
+				     const SLList<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  if (idx.empty ())
+    {
+      do_non_const_unary_op (op);
 
-  assign_op assop = unary_op_to_assign_op (op);
+      retval = *this;
+    }
+  else
+    {
+      // XXX FIXME XXX -- only do the following stuff if we can't find a
+      // specific function to call to handle the op= operation for the
+      // types we have.
 
-  if (! error_state)
-    assign (assop, idx, 1.0);
-  else
-    gripe_unary_op_failed_or_no_method (unary_op_as_string (op),
-					type_name ());
+      assign_op assop = unary_op_to_assign_op (op);
+
+      retval = assign (assop, type, idx, 1.0);
+    }
+
+  return retval;
 }
 
 // Current indentation.
@@ -1521,6 +1477,42 @@
   return binop;
 }
 
+octave_value
+octave_value::empty_conv (const std::string& type, const octave_value& rhs)
+{
+  octave_value retval;
+
+  if (type.length () > 0)
+    {
+      switch (type[0])
+	{
+	case '(':
+	  {
+	    if (type.length () > 1 && type[1] == '.')
+	      retval = Octave_map ();
+	    else
+	      retval = octave_value (rhs.empty_clone ());
+	  }
+	  break;
+
+	case '{':
+	  retval = Cell ();
+	  break;
+
+	case '.':
+	  retval = Octave_map ();
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+    }
+  else
+    retval = octave_value (rhs.empty_clone ());
+
+  return retval;
+}
+
 void
 install_types (void)
 {
--- a/src/ov.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/ov.h	Wed May 15 03:21:01 2002 +0000
@@ -38,6 +38,8 @@
 #include "oct-alloc.h"
 #include "str-vec.h"
 
+#include "SLList.h"
+
 class Cell;
 class Octave_map;
 class octave_stream;
@@ -147,6 +149,9 @@
 
   static std::string assign_op_as_string (assign_op);
 
+  static octave_value empty_conv (const std::string& type,
+				  const octave_value& rhs = octave_value ());
+
   enum magic_colon { magic_colon_t };
   enum all_va_args { all_va_args_t };
 
@@ -178,7 +183,7 @@
   octave_value (octave_value::magic_colon);
   octave_value (octave_value::all_va_args);
 
-  octave_value (octave_value *new_rep);
+  octave_value (octave_value *new_rep, int count = 1);
 
   // Copy constructor.
 
@@ -188,15 +193,18 @@
       rep->count++;
     }
 
+  // This should only be called for derived types.
+
+  virtual octave_value *clone (void) const;
+
+  virtual octave_value *empty_clone (void) const
+    { return rep->empty_clone (); }
+
   // Delete the representation of this constant if the count drops to
   // zero.
 
   virtual ~octave_value (void);
 
-  // This should only be called for derived types.
-
-  virtual octave_value *clone (void);
-
   void make_unique (void)
     {
       if (rep->count > 1)
@@ -223,7 +231,7 @@
       return *this;
     }
 
-  int get_count (void) { return rep->count; }
+  int get_count (void) const { return rep->count; }
 
   virtual type_conv_fcn numeric_conversion_function (void) const
     { return rep->numeric_conversion_function (); }
@@ -233,44 +241,50 @@
   virtual octave_value *try_narrowing_conversion (void)
     { return rep->try_narrowing_conversion (); }
 
-  virtual octave_value do_index_op (const octave_value_list& idx)
-    { return rep->do_index_op (idx); }
+  virtual octave_value subsref (const std::string type,
+				const SLList<octave_value_list>& idx)
+    { return rep->subsref (type, idx); }
+
+  octave_value subsref (const std::string type, const octave_value_list& idx)
+    {
+      SLList<octave_value_list> i;
+
+      i.append (idx);
+
+      return rep->subsref (type, i);
+    }
+
+  virtual octave_value_list subsref (const std::string type,
+				     const SLList<octave_value_list>& idx,
+    				     int nargout);
+
+  octave_value next_subsref (const std::string type, const
+			     SLList<octave_value_list>& idx,
+			     int skip = 1);
+
+  virtual octave_value do_index_op (const octave_value_list& idx,
+				    int resize_ok)
+    { return rep->do_index_op (idx, resize_ok); }
+
+  octave_value do_index_op (const octave_value_list& idx)
+    { return do_index_op (idx, 0); }
 
   virtual octave_value_list
   do_multi_index_op (int nargout, const octave_value_list& idx);
 
-  void assign (assign_op, const octave_value& rhs);
-
-  void assign (assign_op, const octave_value_list& idx,
-	       const octave_value& rhs);
+  virtual octave_value subsasgn (const std::string type,
+				 const SLList<octave_value_list>& idx,
+				 const octave_value& rhs);
 
-  virtual void
-  assign_struct_elt (assign_op, const std::string& elt_nm,
-		     const octave_value& rhs);
+  octave_value assign (assign_op op, const std::string type,
+		       const SLList<octave_value_list>& idx,
+		       const octave_value& rhs);
 
-  virtual void
-  assign_struct_elt (assign_op, const std::string& elt_nm,
-		     const octave_value_list& idx,
-		     const octave_value& rhs);
+  const octave_value& assign (assign_op, const octave_value& rhs);
 
   virtual idx_vector index_vector (void) const
     { return rep->index_vector (); }
 
-  virtual octave_value
-  do_struct_elt_index_op (const std::string& nm, bool silent = false)
-    { return rep->do_struct_elt_index_op (nm, silent); }
-
-  virtual octave_value
-  do_struct_elt_index_op (const std::string& nm,
-			  const octave_value_list& idx,
-			  bool silent = false)
-    { return rep->do_struct_elt_index_op (nm, idx, silent); }
-
-  octave_lvalue struct_elt_ref (const std::string& nm);
-
-  virtual octave_lvalue
-  struct_elt_ref (octave_value *parent, const std::string& nm);
-
   // Size.
 
   virtual int rows (void) const
@@ -433,6 +447,9 @@
 
   virtual Octave_map map_value (void) const;
 
+  virtual string_vector map_keys (void) const
+    { return rep->map_keys (); }
+
   virtual octave_stream stream_value (void) const;
 
   virtual int stream_number (void) const;
@@ -495,24 +512,35 @@
 
   // Unary and binary operations.
 
-  friend octave_value do_unary_op (octave_value::unary_op,
-				   const octave_value&);
+  friend octave_value do_unary_op (unary_op op,
+				   const octave_value& a);
 
-  void do_non_const_unary_op (octave_value::unary_op);
+  const octave_value& do_non_const_unary_op (unary_op op);
+
+  void do_non_const_unary_op (unary_op op, const octave_value_list& idx);
 
-  void do_non_const_unary_op (octave_value::unary_op,
-			      const octave_value_list& idx);
+  octave_value do_non_const_unary_op (unary_op op, const std::string type,
+				      const SLList<octave_value_list>& idx);
 
-  friend octave_value do_binary_op (octave_value::binary_op,
-				    const octave_value&,
-				    const octave_value&);
+  friend octave_value do_binary_op (binary_op op,
+				    const octave_value& a,
+				    const octave_value& b);
 
   const octave_value& get_rep (void) const { return *rep; }
 
+  virtual void print_info (std::ostream& os,
+			   const std::string& prefix = std::string ()) const;
+
 protected:
 
   octave_value (const octave_xvalue&) : rep (0) { }
 
+  // This should only be called for derived types.
+
+  octave_value numeric_assign (const std::string type,
+			       const SLList<octave_value_list>& idx,
+			       const octave_value& rhs);
+
   void reset_indent_level (void) const
     { curr_print_indent_level = 0; }
 
@@ -531,23 +559,13 @@
 
   void reset (void) const;
 
-private:
-
   union
     {
       octave_value *rep;      // The real representation.
       int count;              // A reference count.
     };
 
-  bool convert_and_assign (assign_op, const octave_value_list& idx,
-			   const octave_value& rhs);
-
-  bool try_assignment_with_conversion (assign_op,
-				       const octave_value_list& idx,
-				       const octave_value& rhs);
-
-  bool try_assignment (assign_op, const octave_value_list& idx,
-		       const octave_value& rhs);
+private:
 
   static int curr_print_indent_level;
   static bool beginning_of_line;
@@ -556,9 +574,6 @@
 
   binary_op op_eq_to_binary_op (assign_op op);
 
-  void simple_assign (assign_op orig_op, const octave_value_list& idx,
-		      const octave_value& rhs);
-
   DECLARE_OCTAVE_ALLOCATOR
 };
 
--- a/src/parse.y	Tue May 07 18:10:44 2002 +0000
+++ b/src/parse.y	Wed May 15 03:21:01 2002 +0000
@@ -280,8 +280,8 @@
 
 // Make an index expression.
 static tree_index_expression *
-make_index_expression (tree_expression *expr, tree_argument_list *args,
-		       tree_index_expression::type);
+make_index_expression (tree_expression *expr,
+		       tree_argument_list *args, char type);
 
 // Make an indirect reference expression.
 static tree_index_expression *
@@ -697,25 +697,13 @@
 postfix_expr	: primary_expr
 		  { $$ = $1; }
 		| postfix_expr '(' ')'
-		  {
-		    $$ = make_index_expression ($1, 0,
-						tree_index_expression::paren);
-		  }
+		  { $$ = make_index_expression ($1, 0, '('); }
 		| postfix_expr '(' arg_list ')'
-		  {
-		    $$ = make_index_expression ($1, $3,
-						tree_index_expression::paren);
-		  }
+		  { $$ = make_index_expression ($1, $3, '('); }
 		| postfix_expr '{' '}'
-		  {
-		    $$ = make_index_expression ($1, 0,
-						tree_index_expression::brace);
-		  }
+		  { $$ = make_index_expression ($1, 0, '{'); }
 		| postfix_expr '{' arg_list '}'
-		  {
-		    $$ = make_index_expression ($1, $3,
-						tree_index_expression::brace);
-		  }
+		  { $$ = make_index_expression ($1, $3, '{'); }
 		| postfix_expr PLUS_PLUS
 		  { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
 		| postfix_expr MINUS_MINUS
@@ -852,10 +840,7 @@
 		;
 
 word_list_cmd	: identifier word_list
-		  {
-		    $$ = make_index_expression ($1, $2,
-						tree_index_expression::paren);
-		  }
+		  { $$ = make_index_expression ($1, $2, '('); }
 		;
 
 word_list	: TEXT
@@ -2591,7 +2576,7 @@
 
 static tree_index_expression *
 make_index_expression (tree_expression *expr, tree_argument_list *args,
-		       tree_index_expression::type t)
+		       char type)
 {
   tree_index_expression *retval = 0;
 
@@ -2600,7 +2585,16 @@
 
   expr->mark_postfix_indexed ();
 
-  retval =  new tree_index_expression (expr, args, l, c, t);
+  if (expr->is_index_expression ())
+    {
+      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+      tmp->append (args, type);
+
+      retval = tmp;
+    }
+  else
+    retval = new tree_index_expression (expr, args, l, c, type);
 
   return retval;
 }
@@ -2615,7 +2609,16 @@
   int l = expr->line ();
   int c = expr->column ();
 
-  retval = new tree_index_expression (expr, elt, l, c);
+  if (expr->is_index_expression ())
+    {
+      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+      tmp->append (elt);
+
+      retval = tmp;
+    }
+  else
+    retval = new tree_index_expression (expr, elt, l, c);
 
   lexer_flags.looking_at_indirect_ref = false;
 
--- a/src/pr-output.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/pr-output.cc	Wed May 15 03:21:01 2002 +0000
@@ -38,12 +38,12 @@
 #include "Range.h"
 #include "cmd-edit.h"
 #include "dMatrix.h"
-#include "Cell.h"
 #include "lo-mappers.h"
 #include "mach-info.h"
 #include "oct-cmplx.h"
 #include "str-vec.h"
 
+#include "Cell.h"
 #include "defun.h"
 #include "error.h"
 #include "gripes.h"
@@ -1755,37 +1755,10 @@
     }
 }
 
-void
-octave_print_internal (std::ostream& os, const Cell& cell_val,
-		       bool pr_as_read_syntax, int extra_indent)
+extern void
+octave_print_internal (std::ostream&, const Cell&, bool, int, bool)
 {
-  int nr = cell_val.rows ();
-  int nc = cell_val.columns();
-
-  if (nr > 0 && nc > 0)
-    {
-      os << "{\n";
-
-      for (int j = 0; j < nc; j++)
-	{
-	  for (int i = 0; i < nr; i++)
-	    {
-	      std::ostrstream buf;
-	      buf << "[" << i+1 << "," << j+1 << "]" << std::ends;
-	      const char *nm = buf.str ();
-
-	      octave_value val = cell_val(i,j);
-
-	      val.print_with_name (os, nm);
-
-	      delete [] nm;
-	    }
-	}
-
-      os << "}";
-    }
-  else
-    os << "{}";
+  panic_impossible ();
 }
 
 DEFUN (disp, args, nargout,
--- a/src/pr-output.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pr-output.h	Wed May 15 03:21:01 2002 +0000
@@ -69,9 +69,10 @@
 		       bool pr_as_string = false);
 
 extern void
-octave_print_internal (std::ostream& os, const Cell& c,
+octave_print_internal (std::ostream& os, const Cell& cell,
 		       bool pr_as_read_syntax = false,
-		       int extra_indent = 0);
+		       int extra_indent = 0,
+		       bool pr_as_string = false);
 
 #endif
 
--- a/src/pt-assign.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-assign.h	Wed May 15 03:21:01 2002 +0000
@@ -59,15 +59,13 @@
 
   ~tree_simple_assignment (void);
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
   octave_value_list rvalue (int nargout);
 
-  bool is_assignment_expression (void) const
-    { return true; }
+  bool is_assignment_expression (void) const { return true; }
 
   void eval_error (void);
 
@@ -127,11 +125,9 @@
 
   ~tree_multi_assignment (void);
 
-  bool is_assignment_expression (void) const
-    { return true; }
+  bool is_assignment_expression (void) const { return true; }
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
--- a/src/pt-binop.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-binop.h	Wed May 15 03:21:01 2002 +0000
@@ -62,8 +62,7 @@
       delete op_rhs;
     }
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
@@ -119,8 +118,7 @@
 
   ~tree_boolean_expression (void) { }
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
--- a/src/pt-bp.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-bp.cc	Wed May 15 03:21:01 2002 +0000
@@ -345,22 +345,21 @@
   if (found)
     return;
 
-  if (cmd.expr_type () == tree_index_expression::dot)
-    {
-      if (cmd.line () >= line)
-	take_action (cmd);
-    }
-  else
+  tree_expression *expr = cmd.expression ();
+
+  if (expr && expr->line () >= line)
+    take_action (*expr);
+
+  SLList<tree_argument_list *> lst = cmd.arg_lists ();
+
+  if (! lst.empty ())
     {
-      tree_expression *expr = cmd.expression ();
-
-      if (expr && expr->line () >= line)
-	take_action (*expr);
+      for (Pix p = lst.first (); p != 0; lst.next (p))
+	{
+	  tree_argument_list *elt = lst(p);
 
-      tree_argument_list *lst = cmd.arg_list ();
-
-      if (lst)
-	lst->accept (*this);
+	  elt->accept (*this);
+	}
     }
 }
 
--- a/src/pt-cell.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-cell.h	Wed May 15 03:21:01 2002 +0000
@@ -50,8 +50,7 @@
 
   ~tree_cell (void) { }
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
--- a/src/pt-check.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-check.cc	Wed May 15 03:21:01 2002 +0000
@@ -248,10 +248,19 @@
   if (e)
     e->accept (*this);
 
-  tree_argument_list *list = expr.arg_list ();
+  SLList<tree_argument_list *> lst = expr.arg_lists ();
+
+  Pix p = lst.first ();
 
-  if (list)
-    list->accept (*this);
+  while (p)
+    {
+      tree_argument_list *elt = lst (p);
+
+      if (elt)
+	elt->accept (*this);
+
+      lst.next (p);
+    }
 }
 
 void
--- a/src/pt-colon.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-colon.h	Wed May 15 03:21:01 2002 +0000
@@ -65,8 +65,7 @@
 
   tree_colon_expression *append (tree_expression *t);
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
--- a/src/pt-const.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-const.h	Wed May 15 03:21:01 2002 +0000
@@ -54,19 +54,15 @@
 
   ~tree_constant (void) { }
 
-  void *operator new (size_t size)
-    { return allocator.alloc (size); }
+  void *operator new (size_t size) { return allocator.alloc (size); }
 
-  void operator delete (void *p, size_t size)
-    { allocator.free (p, size); }
+  void operator delete (void *p, size_t size) { allocator.free (p, size); }
 
   // Type.  It would be nice to eliminate the need for this.
 
-  bool is_constant (void) const
-    { return true; }
+  bool is_constant (void) const { return true; }
 
-  void maybe_mutate (void)
-    { val.maybe_mutate (); }
+  void maybe_mutate (void) { val.maybe_mutate (); }
 
   void print (std::ostream& os, bool pr_as_read_syntax = false,
 	      bool pr_orig_txt = true);
@@ -74,8 +70,7 @@
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false,
 		  bool pr_orig_txt = true);
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void)
     {
@@ -90,11 +85,9 @@
   // Store the original text corresponding to this constant for later
   // pretty printing.
 
-  void stash_original_text (const std::string& s)
-    { orig_text = s; }
+  void stash_original_text (const std::string& s) { orig_text = s; }
 
-  std::string original_text (void) const
-    { return orig_text; }
+  std::string original_text (void) const { return orig_text; }
 
 private:
 
--- a/src/pt-exp.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-exp.h	Wed May 15 03:21:01 2002 +0000
@@ -47,34 +47,23 @@
 
   virtual ~tree_expression (void) { }
 
-  virtual bool is_constant (void) const
-    { return false; }
+  virtual bool is_constant (void) const { return false; }
 
-  virtual bool is_matrix_constant (void) const
-    { return false; }
+  virtual bool is_matrix_constant (void) const { return false; }
 
-  virtual bool is_identifier (void) const
-    { return false; }
+  virtual bool is_identifier (void) const { return false; }
 
-  virtual bool is_index_expression (void) const
-    { return false; }
-
-  virtual bool is_indirect_ref (void) const
-    { return false; }
+  virtual bool is_index_expression (void) const { return false; }
 
-  virtual bool is_assignment_expression (void) const
-    { return false; }
+  virtual bool is_assignment_expression (void) const { return false; }
 
-  virtual bool is_prefix_expression (void) const
-    { return false; }
+  virtual bool is_prefix_expression (void) const { return false; }
 
   virtual bool is_logically_true (const char *);
 
-  virtual bool lvalue_ok (void) const
-    { return false; }
+  virtual bool lvalue_ok (void) const { return false; }
 
-  virtual bool rvalue_ok (void) const
-    { return false; }
+  virtual bool rvalue_ok (void) const { return false; }
 
   virtual octave_value rvalue (void);
 
@@ -82,20 +71,15 @@
 
   virtual octave_lvalue lvalue (void);
 
-  int paren_count (void) const
-    { return num_parens; }
+  int paren_count (void) const { return num_parens; }
 
-  bool is_postfix_indexed (void) const
-    { return postfix_indexed; }
+  bool is_postfix_indexed (void) const { return postfix_indexed; }
 
-  bool print_result (void) const
-    { return print_flag; }
+  bool print_result (void) const { return print_flag; }
 
-  virtual std::string oper (void) const
-    { return "<unknown>"; }
+  virtual std::string oper (void) const { return "<unknown>"; }
 
-  virtual std::string name (void) const
-    { return "<unknown>"; }
+  virtual std::string name (void) const { return "<unknown>"; }
 
   virtual std::string original_text (void) const;
 
--- a/src/pt-id.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-id.h	Wed May 15 03:21:01 2002 +0000
@@ -56,8 +56,7 @@
 
   ~tree_identifier (void) { }
 
-  bool is_identifier (void) const
-    { return true; }
+  bool is_identifier (void) const { return true; }
 
   std::string name (void) const;
 
@@ -81,8 +80,7 @@
   // We really need to know whether this symbol referst to a variable
   // or a function, but we may not know that yet.
 
-  bool lvalue_ok (void) const
-    { return true; }
+  bool lvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
--- a/src/pt-idx.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-idx.cc	Wed May 15 03:21:01 2002 +0000
@@ -28,6 +28,7 @@
 #include <config.h>
 #endif
 
+#include "Cell.h"
 #include "error.h"
 #include "oct-map.h"
 #include "oct-obj.h"
@@ -41,24 +42,54 @@
 #include "utils.h"
 #include "variables.h"
 
+#include "SLList.cc"
+
+template class SLNode<string_vector>;
+template class SLList<string_vector>;
+
 // Index expressions.
 
 tree_index_expression::tree_index_expression (tree_expression *e,
 					      tree_argument_list *lst,
-					      int l, int c, type t)
-  : tree_expression (l, c), expr (e), list (lst),
-    itype (t), arg_nm (lst ? lst->get_arg_names () : string_vector ()) { }
+					      int l, int c, char t)
+  : tree_expression (l, c), expr (e), args (), type (), arg_nm ()
+{
+  append (lst, t);
+}
 
 tree_index_expression::tree_index_expression (tree_expression *e,
 					      const std::string& n,
 					      int l = -1, int c = -1)
-  : tree_expression (l, c), expr (e), list (0), itype (dot),
-    arg_nm (n) { }
+  : tree_expression (l, c), expr (e), args (), type (), arg_nm ()
+{
+  append (n);
+}
+
+void
+tree_index_expression::append (tree_argument_list *lst, char t)
+{
+  args.append (lst);
+  type.append (1, t);
+  arg_nm.append (lst ? lst->get_arg_names () : string_vector ());
+}
+
+void
+tree_index_expression::append (const std::string& n)
+{
+  args.append (static_cast<tree_argument_list *> (0));
+  type.append (".");
+  arg_nm.append (n);
+}
 
 tree_index_expression::~tree_index_expression (void)
 {
   delete expr;
-  delete list;
+
+  while (! args.empty ())
+    {
+      tree_argument_list *t = args.remove_front ();
+      delete t;
+    }
 }
 
 // This is useful for printing the name of the variable in an indexed
@@ -70,7 +101,101 @@
   // ??? FIXME ???
   std::string xname = expr->name ();
 
-  return (! dot || xname == "<unknown>") ? xname : xname + "." + arg_nm(0);
+  return (type[0] != '.' || xname == "<unknown>")
+    ? xname : xname + "." + arg_nm.front ()(0);
+}
+
+static Cell
+make_subs_cell (tree_argument_list *args, const string_vector& arg_nm)
+{
+  Cell retval;
+
+  octave_value_list arg_values;
+
+  if (args)
+    arg_values = args->convert_to_const_vector ();
+
+  if (! error_state)
+    {
+      int n = arg_values.length ();
+
+      if (n > 0)
+	{
+	  arg_values.stash_name_tags (arg_nm);
+
+	  retval.resize (1, n);
+
+	  for (int i = 0; i < n; i++)
+	    retval(0,i) = arg_values(i);
+	}
+    }
+
+  return retval;
+}
+
+static inline octave_value_list
+make_value_list (tree_argument_list *args, const string_vector& arg_nm)
+{
+  octave_value_list retval;
+
+  if (args)
+    retval = args->convert_to_const_vector ();
+
+  if (! error_state)
+    {
+      int n = retval.length ();
+
+      if (n > 0)
+	retval.stash_name_tags (arg_nm);
+    }
+
+  return retval;
+}
+
+Octave_map
+tree_index_expression::make_arg_struct (void) const
+{
+  int n = args.length ();
+
+  octave_value_list subs_list (n, octave_value ());
+  octave_value_list type_list (n, octave_value ());
+
+  Pix p_args = args.first ();
+  Pix p_arg_nm = arg_nm.first ();
+
+  Octave_map m;
+
+  for (int i = 0; i < n; i++)
+    {
+      switch (type[i])
+	{
+	case '(':
+	  subs_list(i) = make_subs_cell (args(p_args), arg_nm(p_arg_nm));
+	  break;
+
+	case '{':
+	  subs_list(i) = make_subs_cell (args(p_args), arg_nm(p_arg_nm));
+	  break;
+
+	case '.':
+	  subs_list(i) = arg_nm(p_arg_nm)(0);
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+
+      if (error_state)
+	return m;
+
+      args.next (p_args);
+      arg_nm.next (p_arg_nm);
+    }
+
+  m ["subs"] = subs_list;
+  m ["type"] = type_list;
+
+  return m;
 }
 
 octave_value_list
@@ -85,66 +210,43 @@
 
   if (! error_state)
     {
-      if (itype == dot)
-	{
-	  MAYBE_DO_BREAKPOINT;
+      SLList<octave_value_list> idx;
 
-	  if (nargout > 1)
-	    error ("invalid number of output arguments for structure reference");
-	  else
-	    {
-	      octave_value_list tmp = expr->rvalue (nargout);
+      int n = args.length ();
+
+      Pix p_args = args.first ();
+      Pix p_arg_nm = arg_nm.first ();
 
-	      if (tmp.empty ())
-		eval_error ();
-	      else
-		{
-		  octave_value val = tmp(0).do_struct_elt_index_op (arg_nm(0));
+      for (int i = 0; i < n; i++)
+	{
+	  switch (type[i])
+	    {
+	    case '(':
+	      idx.append (make_value_list (args(p_args), arg_nm(p_arg_nm)));
+	      break;
 
-		  if (print_result () && nargout == 0 && val.is_defined ())
-		    {
-		      // ??? FIXME ???
-
-		      std::string xname = name ();
-
-		      if (xname == "<unknown>")
-			bind_ans (val, true);
-		      else
-			val.print_with_name (octave_stdout, xname);
-		    }
+	    case '{':
+	      idx.append (make_value_list (args(p_args), arg_nm(p_arg_nm)));
+	      break;
 
-		  retval = val;
-		}
-	    }
-	}
-      else if (itype == paren || itype == brace)
-	{
-	  octave_value_list args;
+	    case '.':
+	      idx.append (arg_nm(p_arg_nm)(0));
+	      break;
 
-	  if (list)
-	    args = list->convert_to_const_vector ();
-
-	  if (! error_state)
-	    {
-	      if (! args.empty ())
-		args.stash_name_tags (arg_nm);
+	    default:
+	      panic_impossible ();
+	    }
 
-	      // XXX FIXME XXX -- is this the right thing to do?
-	      if (tmp.is_constant ())
-		retval = tmp.do_index_op (args);
-	      else
-		retval = tmp.do_multi_index_op (nargout, args);
-	    }
-	  else
-	    eval_error ();
+	  if (error_state)
+	    break;
+
+	  args.next (p_args);
+	  arg_nm.next (p_arg_nm);
 	}
-#if 0
-      else
-	panic_impossible ();
-#endif
+
+      if (! error_state)
+	retval = tmp.subsref (type, idx, nargout);
     }
-  else
-    eval_error ();
 
   return retval;
 }
@@ -167,35 +269,46 @@
 {
   octave_lvalue retval;
 
+  SLList<octave_value_list> idx;
+
+  int n = args.length ();
+
+  Pix p_args = args.first ();
+  Pix p_arg_nm = arg_nm.first ();
+
+  for (int i = 0; i < n; i++)
+    {
+      switch (type[i])
+	{
+	case '(':
+	  idx.append (make_value_list (args(p_args), arg_nm(p_arg_nm)));
+	  break;
+
+	case '{':
+	  idx.append (make_value_list (args(p_args), arg_nm(p_arg_nm)));
+	  break;
+
+	case '.':
+	  idx.append (arg_nm(p_arg_nm)(0));
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+
+      if (error_state)
+	break;
+
+      args.next (p_args);
+      arg_nm.next (p_arg_nm);
+    }
+
   if (! error_state)
     {
-      if (itype == dot)
-	{
-	  octave_lvalue tmp = expr->lvalue ();
-
-	  if (tmp.is_undefined () || ! tmp.is_map ())
-	    tmp.define (Octave_map ());
-
-	  retval = tmp.struct_elt_ref (arg_nm(0));
-	}
-      else if (itype == paren || itype == brace)
-	{
-	  retval = expr->lvalue ();
+      retval = expr->lvalue ();
 
-	  if (! error_state)
-	    {
-	      octave_value_list args;
-	  
-	      if (list)
-		args = list->convert_to_const_vector ();
-
-	      retval.set_index (args);
-	    }
-#if 0
-	  else
-	    panic_impossible ();
-#endif
-	}
+      if (! error_state)
+	retval.set_index (type, idx);
     }
 
   return retval;
@@ -211,9 +324,9 @@
 
       const char *type_str;
 
-      if (itype == dot)
+      if (type[0] == '.')
 	type_str = "structure reference operator";
-      else if (list)
+      else if (args.front ())
 	type_str = "index expression";
       else
 	type_str = "expression";
--- a/src/pt-idx.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-idx.h	Wed May 15 03:21:01 2002 +0000
@@ -31,10 +31,12 @@
 
 class tree_walker;
 
+class Octave_map;
 class octave_value;
 class octave_value_list;
 class octave_lvalue;
 
+#include "SLList.h"
 #include "str-vec.h"
 
 #include "pt-exp.h"
@@ -46,46 +48,33 @@
 {
 public:
 
-  enum type
-    {
-      unknown,
-      paren,
-      brace,
-      dot
-    };
-
   tree_index_expression (tree_expression *e = 0, tree_argument_list *lst = 0,
-			 int l = -1, int c = -1, type t = paren);
+			 int l = -1, int c = -1, char t = '(');
 
   tree_index_expression (tree_expression *e, const std::string& n,
 			 int l = -1, int c = -1);
 
   ~tree_index_expression (void);
 
-  bool is_index_expression (void) const
-    { return (itype == paren || itype == brace); }
+  void append (tree_argument_list *lst = 0, char t = '(');
 
-  bool is_indirect_ref (void) const
-    { return (itype == dot); }
+  void append (const std::string& n);
+
+  bool is_index_expression (void) const { return true; }
 
   std::string name (void) const;
 
-  std::string struct_elt_name (void) const
-    { return itype == dot ? arg_nm(0) : "<unknown>"; }
+  tree_expression *expression (void) { return expr; }
 
-  type expr_type (void) { return itype; }
+  SLList<tree_argument_list *> arg_lists (void) { return args; }
 
-  tree_expression *expression (void)
-    { return expr; }
+  std::string type_tags (void) { return type; }
 
-  tree_argument_list *arg_list (void)
-    { return list; }
+  SLList<string_vector> arg_names (void) { return arg_nm; }
 
-  bool lvalue_ok (void) const
-    { return (itype == dot || expr->lvalue_ok ()); }
+  bool lvalue_ok (void) const { return expr->lvalue_ok (); }
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
@@ -102,14 +91,16 @@
   // The LHS of this index expression.
   tree_expression *expr;
 
-  // The indices (only valid if itype == paren || itype == brace).
-  tree_argument_list *list;
+  // The indices (only valid if type == paren || type == brace).
+  SLList<tree_argument_list *> args;
 
   // The type of this index expression.
-  type itype;
+  std::string type;
 
   // The names of the arguments.
-  string_vector arg_nm;
+  SLList<string_vector> arg_nm;
+
+  Octave_map tree_index_expression::make_arg_struct (void) const;
 
   // No copying!
 
--- a/src/pt-mat.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-mat.h	Wed May 15 03:21:01 2002 +0000
@@ -58,8 +58,7 @@
 
   bool all_elements_are_constant (void) const;
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
--- a/src/pt-misc.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-misc.h	Wed May 15 03:21:01 2002 +0000
@@ -57,17 +57,13 @@
 
   void mark_as_formal_parameters (void);
 
-  void mark_varargs (void)
-    { marked_for_varargs = 1; }
+  void mark_varargs (void) { marked_for_varargs = 1; }
 
-  bool takes_varargs (void) const
-    { return marked_for_varargs != 0; }
+  bool takes_varargs (void) const { return marked_for_varargs != 0; }
 
-  void mark_varargs_only (void)
-    { marked_for_varargs = -1; }
+  void mark_varargs_only (void) { marked_for_varargs = -1; }
 
-  bool varargs_only (void)
-    { return (marked_for_varargs < 0); }
+  bool varargs_only (void) { return (marked_for_varargs < 0); }
 
   void initialize_undefined_elements (octave_value& val);
 
--- a/src/pt-plot.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-plot.cc	Wed May 15 03:21:01 2002 +0000
@@ -666,7 +666,7 @@
       args(1) = val;
       args(0) = octave_value::magic_colon_t;
 
-      retval = data.do_index_op (args);
+      retval = data.subsref ("(", args);
 
       if (error_state)
 	return octave_value ();
--- a/src/pt-pr-code.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-pr-code.cc	Wed May 15 03:21:01 2002 +0000
@@ -484,21 +484,53 @@
       expr_has_parens = e->is_postfix_indexed ();
     }
 
-  tree_argument_list *list = expr.arg_list ();
+  SLList<tree_argument_list *> arg_lists = expr.arg_lists ();
+  std::string type_tags = expr.type_tags ();
+  SLList<string_vector> arg_names = expr.arg_names ();
 
-  if (expr.expr_type () == tree_index_expression::dot)
-    {
-      os << "." << expr.struct_elt_name ();
-    }
-  else if (list)
+  int n = type_tags.length ();
+
+  Pix arg_lists_p = arg_lists.first ();
+  Pix arg_names_p = arg_names.first ();
+
+  for (int i = 0; i < n; i++)
     {
-      os << " (";
-      list->accept (*this);
-      os << ")";
-    }
-  else if (expr_has_parens)
-    {
-      os << " ()";
+      switch (type_tags[i])
+	{
+	case '(':
+	  {
+	    os << " (";
+	    tree_argument_list *l = arg_lists (arg_lists_p);
+	    if (l)
+	      l->accept (*this);
+	    os << ")";
+	  }
+	  break;
+	    
+	case '{':
+	  {
+	    os << " {";
+	    tree_argument_list *l = arg_lists (arg_lists_p);
+	    if (l)
+	      l->accept (*this);
+	    os << "}";
+	  }
+	  break;
+	    
+	case '.':
+	  {
+	    string_vector nm = arg_names (arg_names_p);
+	    assert (nm.length () == 1);
+	    os << "." << nm(0);
+	  }
+	  break;
+
+	default:
+	  panic_impossible ();
+	}
+
+      arg_lists.next (arg_lists_p);
+      arg_names.next (arg_names_p);
     }
 
   print_parens (expr, ")");
--- a/src/pt-pr-code.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-pr-code.h	Wed May 15 03:21:01 2002 +0000
@@ -155,14 +155,11 @@
   // TRUE means we are at the beginning of a line.
   bool beginning_of_line;
 
-  void reset_indent_level (void)
-    { curr_print_indent_level = 0; }
+  void reset_indent_level (void) { curr_print_indent_level = 0; }
 
-  void increment_indent_level (void)
-    { curr_print_indent_level += 2; }
+  void increment_indent_level (void) { curr_print_indent_level += 2; }
 
-  void decrement_indent_level (void)
-    { curr_print_indent_level -= 2; }
+  void decrement_indent_level (void) { curr_print_indent_level -= 2; }
 
   void newline (void);
 
--- a/src/pt-select.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-select.h	Wed May 15 03:21:01 2002 +0000
@@ -181,8 +181,7 @@
 
   ~tree_switch_case (void);
 
-  bool is_default_case (void)
-    { return ! label; }
+  bool is_default_case (void) { return ! label; }
 
   bool label_matches (const octave_value& val);
 
--- a/src/pt-stmt.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-stmt.cc	Wed May 15 03:21:01 2002 +0000
@@ -126,8 +126,7 @@
 	      do_bind_ans = id->is_function ();
 	    }
 	  else
-	    do_bind_ans = (! (expr->is_indirect_ref ()
-			      || expr->is_assignment_expression ()));
+	    do_bind_ans = (! expr->is_assignment_expression ());
 
 	  retval = expr->rvalue (nargout);
 
--- a/src/pt-stmt.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-stmt.h	Wed May 15 03:21:01 2002 +0000
@@ -57,14 +57,11 @@
 
   ~tree_statement (void);
 
-  void set_print_flag (bool print)
-    { print_flag = print; }
+  void set_print_flag (bool print) { print_flag = print; }
 
-  bool is_command (void)
-    { return cmd != 0; }
+  bool is_command (void) { return cmd != 0; }
 
-  bool is_expression (void)
-    { return expr != 0; }
+  bool is_expression (void) { return expr != 0; }
 
   int line (void);
   int column (void);
--- a/src/pt-unop.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/pt-unop.h	Wed May 15 03:21:01 2002 +0000
@@ -94,8 +94,7 @@
 
   ~tree_prefix_expression (void) { }
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
@@ -131,8 +130,7 @@
 
   ~tree_postfix_expression (void) { }
 
-  bool rvalue_ok (void) const
-    { return true; }
+  bool rvalue_ok (void) const { return true; }
 
   octave_value rvalue (void);
 
--- a/src/symtab.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/symtab.cc	Wed May 15 03:21:01 2002 +0000
@@ -42,7 +42,6 @@
 #include "error.h"
 #include "oct-lvalue.h"
 #include "ov.h"
-#include "pager.h"
 #include "pt-pr-code.h"
 #include "symtab.h"
 #include "utils.h"
@@ -179,11 +178,11 @@
 }
 
 void
-SYMBOL_DEF::dump_symbol_info (void)
+SYMBOL_DEF::print_info (ostream& os, const std::string& prefix) const
 {
-  octave_stdout << "symbol_def::count: " << count << "\n";
-  octave_stdout << "def.type_name():   " << definition.type_name () << "\n";
-  octave_stdout << "def.count():       " << definition.get_count () << "\n";
+  os << prefix << "symbol_def::count: " << count << "\n";
+
+  definition.print_info (os, prefix + "  ");
 }
 
 // Individual records in a symbol table.
@@ -445,7 +444,7 @@
 }
 
 void
-symbol_record::print_symbol_info_line (std::ostream& os)
+symbol_record::print_symbol_info_line (std::ostream& os) const
 {
   os << (is_read_only () ? " r-" : " rw")
      << (is_eternal () ? "-" : "d")
@@ -477,12 +476,12 @@
 }
 
 void
-symbol_record::dump_symbol_info (void)
+symbol_record::print_info (ostream& os, const std::string& prefix) const
 {
   if (definition)
-    definition->dump_symbol_info ();
+    definition->print_info (os, prefix);
   else
-    octave_stdout << "symbol " << name () << " is undefined\n";
+    os << prefix << "symbol " << name () << " is undefined\n";
 }
 
 bool
@@ -875,7 +874,7 @@
 }
 
 void
-symbol_table::print_stats (void)
+symbol_table::print_info (ostream& os) const
 {
   int count = 0;
   int empty_chains = 0;
@@ -889,7 +888,7 @@
       symbol_record *ptr = table[i].next ();
 
       if (ptr)
-	octave_stdout << "chain number " << i << ":\n";
+	os << "chain number " << i << ":\n";
       else
 	{
 	  empty_chains++;
@@ -900,7 +899,9 @@
 	{
 	  num_this_chain++;
 
-	  octave_stdout << "  " << ptr->name () << "\n";
+	  os << "  " << ptr->name () << "\n";
+
+	  ptr->print_info (os, "    ");
 
 	  ptr = ptr->next ();
 	}
@@ -914,14 +915,14 @@
 	min_chain_length = num_this_chain;
 
       if (num_this_chain > 0)
-	octave_stdout << "\n";
+	os << "\n";
     }
 
-  octave_stdout << "max chain length: " << max_chain_length << "\n";
-  octave_stdout << "min chain length: " << min_chain_length << "\n";
-  octave_stdout << "empty chains:     " << empty_chains << "\n";
-  octave_stdout << "total chains:     " << table_size << "\n";
-  octave_stdout << "total symbols:    " << count << "\n";
+  os << "max chain length: " << max_chain_length << "\n";
+  os << "min chain length: " << min_chain_length << "\n";
+  os << "empty chains:     " << empty_chains << "\n";
+  os << "total chains:     " << table_size << "\n";
+  os << "total symbols:    " << count << "\n";
 }
 
 // Chris Torek's fave hash function.
--- a/src/symtab.h	Tue May 07 18:10:44 2002 +0000
+++ b/src/symtab.h	Wed May 15 03:21:01 2002 +0000
@@ -201,7 +201,8 @@
     // Reference count.
     int count;
 
-    void dump_symbol_info (void);
+    void print_info (std::ostream& os,
+		     const std::string& prefix = std::string ()) const;
 
     // No copying!
 
@@ -338,9 +339,10 @@
 
   void pop_context (void);
 
-  void print_symbol_info_line (std::ostream& os);
+  void print_symbol_info_line (std::ostream& os) const;
 
-  void dump_symbol_info (void);
+  void print_info (std::ostream& os,
+		   const std::string& prefix = std::string ()) const;
 
 private:
 
@@ -444,7 +446,7 @@
 
   void pop_context (void);
 
-  void print_stats (void);
+  void print_info (ostream& os) const;
 
 private:
 
--- a/src/toplev.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/toplev.cc	Wed May 15 03:21:01 2002 +0000
@@ -762,7 +762,7 @@
       std::string arg = args(0).string_value ();
 
       if (! error_state)
-	retval = octave_value (m [arg.c_str ()]);
+	retval = octave_value (m [arg.c_str ()](0));
     }
   else if (nargin == 0)
     retval = octave_value (m);
--- a/src/variables.cc	Tue May 07 18:10:44 2002 +0000
+++ b/src/variables.cc	Wed May 15 03:21:01 2002 +0000
@@ -45,6 +45,7 @@
 #include "oct-map.h"
 #include "oct-obj.h"
 #include "ov.h"
+#include "ov-usr-fcn.h"
 #include "pager.h"
 #include "parse.h"
 #include "symtab.h"
@@ -265,22 +266,14 @@
 }
 
 string_vector
-generate_struct_completions (const std::string& text, std::string& prefix, std::string& hint)
+generate_struct_completions (const std::string& text,
+			     std::string& prefix, std::string& hint)
 {
   string_vector names;
 
   size_t pos = text.rfind ('.');
 
-  std::string id;
-  string_vector elts;
-
-  if (pos == NPOS)
-    {
-      hint = text;
-      prefix = text;
-      elts.resize (1, text);
-    }
-  else
+  if (pos != NPOS)
     {
       if (pos == text.length ())
 	hint = "";
@@ -288,41 +281,14 @@
 	hint = text.substr (pos+1);
 
       prefix = text.substr (0, pos);
-
-      elts = get_struct_elts (prefix);
     }
 
-  id = elts[0];
-
-  symbol_record *sr = curr_sym_tab->lookup (id);
-
-  if (! sr)
-    sr = global_sym_tab->lookup (id);
-
-  if (sr && sr->is_defined ())
-    {
-      octave_value tmp = sr->def ();
+  int parse_status;
 
-      // XXX FIXME XXX -- make this work for all types that can do
-      // structure reference operations.
-      if (tmp.is_map ())
-	{
-	  for (int i = 1; i < elts.length (); i++)
-	    {
-	      tmp = tmp.do_struct_elt_index_op (elts[i], true);
+  octave_value tmp = eval_string (prefix, true, parse_status);
 
-	      if (! tmp.is_map ())
-		break;
-	    }
-
-	  if (tmp.is_map ())
-	    {
-	      Octave_map m = tmp.map_value ();
-
-	      names = m.make_name_list ();
-	    }
-	}
-    }
+  if (tmp.is_defined () && tmp.is_map ())
+    names = tmp.map_keys ();
 
   return names;
 }
@@ -330,44 +296,11 @@
 bool
 looks_like_struct (const std::string& text)
 {
-  bool retval = true;
-
-  string_vector elts = get_struct_elts (text);
-
-  std::string id = elts[0];
-
-  symbol_record *sr = curr_sym_tab->lookup (id);
-
-  if (! sr)
-    sr = global_sym_tab->lookup (id);
-
-  if (sr && sr->is_defined ())
-    {
-      octave_value tmp = sr->def ();
-
-      // XXX FIXME XXX -- should this work for all types that can do
-      // structure reference operations?
+  int parse_status;
 
-      if (tmp.is_map ())
-	{
-	  for (int i = 1; i < elts.length (); i++)
-	    {
-	      tmp = tmp.do_struct_elt_index_op (elts[i], true);
+  octave_value tmp = eval_string (text, true, parse_status);
 
-	      if (! tmp.is_map ())
-		{
-		  retval = false;
-		  break;
-		}
-	    }
-	}
-      else
-	retval = false;
-    }
-  else
-    retval = false;
-
-  return retval;	
+  return (tmp.is_defined () && tmp.is_map ());
 }
 
 DEFUN (is_global, args, ,
@@ -1303,9 +1236,9 @@
   return retval;
 }
 
-DEFUN (__dump_symtab_info__, args, ,
+DEFUN (__print_symtab_info__, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __dump_symtab_info__ ()\n\
+@deftypefn {Built-in Function} {} __print_symtab_info__ ()\n\
 Print raw symbol table statistices.\n\
 @end deftypefn")
 {
@@ -1318,19 +1251,36 @@
       std::string arg = args(0).string_value ();
 
       if (arg == "global")
-	global_sym_tab->print_stats ();
+	global_sym_tab->print_info (octave_stdout);
+      else if (arg == "top-level")
+	top_level_sym_tab->print_info (octave_stdout);
       else
-	print_usage ("__dump_symtab_info__");
+	{
+	  symbol_record *gsr = global_sym_tab->lookup (arg, true);
+
+	  if (gsr && gsr->is_user_function ())
+	    {
+	      octave_value tmp = gsr->def ();
+	      const octave_value& rep = tmp.get_rep ();
+	      
+	      const octave_user_function& fcn
+		= static_cast<const octave_user_function&> (rep);
+
+	      fcn.print_symtab_info (octave_stdout);
+	    }
+	  else
+	    error ("no user-defined function named %s", arg.c_str ());
+	}
     }
   else if (nargin == 0)
-    curr_sym_tab->print_stats ();
+    curr_sym_tab->print_info (octave_stdout);
   else
-    print_usage ("__dump_symtab_info__");
+    print_usage ("__print_symtab_info__");
 
   return retval;
 }
 
-DEFUN (__dump_symbol_info__, args, ,
+DEFUN (__print_symbol_info__, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} __dump_symbol_info__ (@var{name})\n\
 Print symbol table information for the symbol @var{name}.\n\
@@ -1349,16 +1299,16 @@
 	  symbol_record *sr = curr_sym_tab->lookup (symbol_name);
 
 	  if (sr)
-	    sr->dump_symbol_info ();
+	    sr->print_info (octave_stdout);
 	  else
-	    error ("__dymp_symbol_info__: symbol %s not found",
+	    error ("__print_symbol_info__: symbol %s not found",
 		   symbol_name.c_str ());
 	}
       else
-	print_usage ("__dump_symbol_info__");
+	print_usage ("__print_symbol_info__");
     }
   else
-    print_usage ("__dump_symbol_info__");
+    print_usage ("__print_symbol_info__");
 
   return retval;
 }