changeset 5279:bd32f770c09a

[project @ 2005-04-12 21:55:31 by jwe]
author jwe
date Tue, 12 Apr 2005 21:55:31 +0000
parents fe23ec6763b7
children 25c12c80ccc3
files src/ChangeLog src/OPERATORS/op-str-m.cc src/OPERATORS/op-str-s.cc src/OPERATORS/op-str-str.cc src/file-io.cc src/lex.l src/ls-mat4.cc src/ls-mat5.cc src/oct-stream.cc src/oct-stream.h src/octave.gperf src/ov-base.cc src/ov-base.h src/ov-bool-mat.cc src/ov-bool-mat.h src/ov-bool-sparse.cc src/ov-bool-sparse.h src/ov-bool.cc src/ov-bool.h src/ov-cell.h src/ov-ch-mat.h src/ov-fcn-inline.cc src/ov-fcn-inline.h src/ov-range.cc src/ov-range.h src/ov-re-mat.cc src/ov-re-mat.h src/ov-scalar.cc src/ov-scalar.h src/ov-str-mat.cc src/ov-str-mat.h src/ov.cc src/ov.h src/parse.y
diffstat 34 files changed, 341 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,51 @@
+2005-04-12  John W. Eaton  <jwe@octave.org>
+
+	* file-io.cc (Ffprintf, Fprintf, Fsprintf):
+	Pass octave_value to octave_stream::printf for FMT.
+	(Fscanf, Fsscanf): Likewise, for octave_stream::scanf and
+	octave_stream::oscanf.
+
+	* oct-stream.cc, oct-stream.h (octave_stream::printf,
+	octave_stream::scanf, octave_stream::oscanf): New versions that
+	accept an octave_value for FMT.
+	(octave_stream::puts): New version that accepts octave_value for
+	value to print.
+	(octave_base_stream::do_scanf): If all_char_conv, force
+	conversion to string to avoid warning.
+
+	* ov-str-mat.h, ov-str-mat.cc (octave_char_matrix_sq_str): New class.
+	(octave_char_matrix_dq_str): New typedef.
+
+	* ov.h, ov.cc: All string constructors now take type argument.
+
+	* ov.cc (install_types): Register octave_char_matrix_sq_str.
+
+	* ov.h (octave_value::convert_to_str): New arg, type.
+	(octave_value::convert_to_str_internal): Likewise.
+	Change all derived classes.
+
+	* ov.h (octave_value::is_sq_string): New predicate.
+
+	* octave.gperf (__FILE__): Now a DQ_STRING.
+
+	* ls-mat4.cc (read_mat_binary_data): Force sq strings here.
+	* ls-mat5.cc (read_mat5_binary_element): And here.
+
+	* lex.l (<COMMAND_START>[\;\,]): Return SQ_STRING, not STRING.
+	(<COMMAND_START>[^#% \t\r\n\;\,\"\'][^ \t\r\n\;\,]*{S}*): Likewise.
+	(handle_string): Type of string to return depends on delimeter.
+
+	* parse.y (DQ_STRING, SQ_STRING): New token types.
+	(STRING): Delete token type.
+	(string): New non-terminal.
+	(constant): Recognize string here instead of STRING.
+	(word_list): Likewise.
+	(opt_sep): Handle DQ_STRING and SQ_STRING.
+
+	* OPERATORS/op-str-m.cc, OPERATORS/op-str-s.cc,
+	OPERATORS/op-str-str.cc: Define operators for both sq and dq
+	strings.
+
 2005-04-08  John W. Eaton  <jwe@octave.org>
 
 	* Makefile.in (clean): Use exact filenames instead of *.xxx.
--- a/src/OPERATORS/op-str-m.cc
+++ b/src/OPERATORS/op-str-m.cc
@@ -36,7 +36,9 @@
 {
   CAST_BINOP_ARGS (octave_char_matrix_str&, const octave_matrix&);
 
-  octave_value tmp = v2.convert_to_str_internal (false, false);
+  octave_value tmp
+    = v2.convert_to_str_internal (false, false,
+				  a1.is_sq_string () ? '\'' : '"');
 
   if (! error_state)
     v1.assign (idx, tmp.char_matrix_value ());
@@ -52,7 +54,8 @@
     gripe_implicit_conversion (v2.type_name (), v1.type_name ());
 
   return octave_value (v1.char_array_value (). concat (v2.array_value (), 
-			       ra_idx), true);
+						       ra_idx),
+		       true, a1.is_sq_string () ? '\'' : '"');
 }
 
 DEFCATOP (m_str, matrix, char_matrix_str)
@@ -63,16 +66,21 @@
     gripe_implicit_conversion (v1.type_name (), v2.type_name ());
 
   return octave_value (v1.array_value (). concat (v2.char_array_value (), 
-			       ra_idx), true);
+						  ra_idx),
+		       true, a2.is_sq_string () ? '\'' : '"');
 }
 
 void
 install_str_m_ops (void)
 {
   INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_str, octave_matrix, assign);
+  INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_sq_str, octave_matrix, assign);
 
   INSTALL_CATOP (octave_char_matrix_str, octave_matrix, str_m);
+  INSTALL_CATOP (octave_char_matrix_sq_str, octave_matrix, str_m);
+
   INSTALL_CATOP (octave_matrix, octave_char_matrix_str, m_str);
+  INSTALL_CATOP (octave_matrix, octave_char_matrix_sq_str, m_str);
 }
 
 /*
--- a/src/OPERATORS/op-str-s.cc
+++ b/src/OPERATORS/op-str-s.cc
@@ -36,7 +36,9 @@
 {
   CAST_BINOP_ARGS (octave_char_matrix_str&, const octave_scalar&);
 
-  octave_value tmp = v2.convert_to_str_internal (false, false);
+  octave_value tmp
+    = v2.convert_to_str_internal (false, false,
+ 				  a1.is_sq_string () ? '\'' : '"');
 
   if (! error_state)
     v1.assign (idx, tmp.char_matrix_value ());
@@ -51,8 +53,9 @@
   if (Vwarn_num_to_str)
     gripe_implicit_conversion (v2.type_name (), v1.type_name ());
 
-  return octave_value (v1.char_array_value (). concat (v2.array_value (), 
-			       ra_idx), true);
+  return octave_value (v1.char_array_value (). concat (v2.array_value (),
+						       ra_idx),
+		       true, a1.is_sq_string () ? '\'' : '"');
 }
 
 DEFCATOP (s_str, scalar, char_matrix_str)
@@ -63,16 +66,21 @@
     gripe_implicit_conversion (v1.type_name (), v2.type_name ());
 
   return octave_value (v1.array_value (). concat (v2.char_array_value (), 
-			       ra_idx), true);
+						  ra_idx),
+		       true, a2.is_sq_string () ? '\'' : '"');
 }
 
 void
 install_str_s_ops (void)
 {
   INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_str, octave_scalar, assign);
+  INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_sq_str, octave_scalar, assign);
 
   INSTALL_CATOP (octave_char_matrix_str, octave_scalar, str_s);
+  INSTALL_CATOP (octave_char_matrix_sq_str, octave_scalar, str_s);
+
   INSTALL_CATOP (octave_scalar, octave_char_matrix_str, s_str);
+  INSTALL_CATOP (octave_scalar, octave_char_matrix_sq_str, s_str);
 }
 
 /*
--- a/src/OPERATORS/op-str-str.cc
+++ b/src/OPERATORS/op-str-str.cc
@@ -33,7 +33,7 @@
 
 // string unary ops.
 
-DEFUNOP (transpose, matrix)
+DEFUNOP (transpose, char_matrix_str)
 {
   CAST_UNOP_ARG (const octave_char_matrix_str&);
 
@@ -43,7 +43,8 @@
       return octave_value ();
     }
   else
-    return octave_value (v.char_matrix_value().transpose (), true);
+    return octave_value (v.char_matrix_value().transpose (), true,
+			 a.is_sq_string () ? '\'' : '"');
 }
 
 // string by string ops.
@@ -117,21 +118,40 @@
 {
   CAST_BINOP_ARGS (octave_char_matrix_str&, const octave_char_matrix_str&);
   return octave_value (v1.char_array_value (). concat (v2.char_array_value (), 
-			       ra_idx), true);
+						       ra_idx),
+		       true,
+		       (a1.is_sq_string () && a2.is_sq_string ()
+			? '\'' : '"'));
 }
 
 void
 install_str_str_ops (void)
 {
   INSTALL_UNOP (op_transpose, octave_char_matrix_str, transpose);
+  INSTALL_UNOP (op_transpose, octave_char_matrix_sq_str, transpose);
+
   INSTALL_UNOP (op_hermitian, octave_char_matrix_str, transpose);
+  INSTALL_UNOP (op_hermitian, octave_char_matrix_sq_str, transpose);
 
   INSTALL_BINOP (op_eq, octave_char_matrix_str, octave_char_matrix_str, eq);
+  INSTALL_BINOP (op_eq, octave_char_matrix_str, octave_char_matrix_sq_str, eq);
+  INSTALL_BINOP (op_eq, octave_char_matrix_sq_str, octave_char_matrix_str, eq);
+  INSTALL_BINOP (op_eq, octave_char_matrix_sq_str, octave_char_matrix_sq_str, eq);
+
   INSTALL_BINOP (op_ne, octave_char_matrix_str, octave_char_matrix_str, ne);
+  INSTALL_BINOP (op_ne, octave_char_matrix_str, octave_char_matrix_sq_str, ne);
+  INSTALL_BINOP (op_ne, octave_char_matrix_sq_str, octave_char_matrix_str, ne);
+  INSTALL_BINOP (op_ne, octave_char_matrix_sq_str, octave_char_matrix_sq_str, ne);
 
   INSTALL_CATOP (octave_char_matrix_str, octave_char_matrix_str, str_str);
+  INSTALL_CATOP (octave_char_matrix_str, octave_char_matrix_sq_str, str_str);
+  INSTALL_CATOP (octave_char_matrix_sq_str, octave_char_matrix_str, str_str);
+  INSTALL_CATOP (octave_char_matrix_sq_str, octave_char_matrix_sq_str, str_str);
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_str, octave_char_matrix_str, assign);
+  INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_str, octave_char_matrix_sq_str, assign);
+  INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_sq_str, octave_char_matrix_str, assign);
+  INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_sq_str, octave_char_matrix_sq_str, assign);
 }
 
 /*
--- a/src/file-io.cc
+++ b/src/file-io.cc
@@ -776,8 +776,6 @@
 	{
 	  if (args(fmt_n).is_string ())
 	    {
-	      std::string fmt = args(fmt_n).string_value ();
-
 	      octave_value_list tmp_args;
 
 	      if (nargin > 1 + fmt_n)
@@ -788,7 +786,7 @@
 		    tmp_args(i-fmt_n-1) = args(i);
 		}
 
-	      result = os.printf (fmt, tmp_args, who);
+	      result = os.printf (args(fmt_n), tmp_args, who);
 	    }
 	  else
 	    ::error ("%s: format must be a string", who.c_str ());
@@ -825,8 +823,6 @@
     {
       if (args(0).is_string ())
 	{
-	  std::string fmt = args(0).string_value ();
-
 	  octave_value_list tmp_args;
 
 	  if (nargin > 1)
@@ -837,7 +833,7 @@
 		tmp_args(i-1) = args(i);
 	    }
 
-	  result = stdout_stream.printf (fmt, tmp_args, who);
+	  result = stdout_stream.printf (args(0), tmp_args, who);
 	}
       else
 	::error ("%s: format must be a string", who.c_str ());
@@ -929,8 +925,6 @@
 	{
 	  if (args(0).is_string ())
 	    {
-	      std::string fmt = args(0).string_value ();
-
 	      octave_value_list tmp_args;
 
 	      if (nargin > 1)
@@ -941,7 +935,7 @@
 		    tmp_args(i-1) = args(i);
 		}
 
-	      retval(2) = os.printf (fmt, tmp_args, who);
+	      retval(2) = os.printf (args(0), tmp_args, who);
 	      retval(1) = os.error ();
 	      retval(0) = ostr->str ();
 	    }
@@ -1014,11 +1008,7 @@
       if (! error_state)
 	{
 	  if (args(1).is_string ())
-	    {
-	      std::string fmt = args(1).string_value ();
-
-	      retval = os.oscanf (fmt, who);
-	    }
+	    retval = os.oscanf (args(1), who);
 	  else
 	    ::error ("%s: format must be a string", who.c_str ());
 	}
@@ -1036,8 +1026,6 @@
 	    {
 	      if (args(1).is_string ())
 		{
-		  std::string fmt = args(1).string_value ();
-
 		  octave_idx_type count = 0;
 
 		  Array<double> size = (nargin == 3)
@@ -1046,7 +1034,7 @@
 
 		  if (! error_state)
 		    {
-		      octave_value tmp = os.scanf (fmt, size, count, who);
+		      octave_value tmp = os.scanf (args(1), size, count, who);
 
 		      retval(1) = count;
 		      retval(0) = tmp;
@@ -1090,11 +1078,7 @@
 	  if (os.is_valid ())
 	    {
 	      if (args(1).is_string ())
-		{
-		  std::string fmt = args(1).string_value ();
-
-		  retval = os.oscanf (fmt, who);
-		}
+		retval = os.oscanf (args(1), who);
 	      else
 		::error ("%s: format must be a string", who.c_str ());
 	    }
@@ -1124,15 +1108,13 @@
 		{
 		  if (args(1).is_string ())
 		    {
-		      std::string fmt = args(1).string_value ();
-
 		      octave_idx_type count = 0;
 
 		      Array<double> size = (nargin == 3)
 			? args(2).vector_value ()
 			: Array<double> (1, lo_ieee_inf_value ());
 
-		      octave_value tmp = os.scanf (fmt, size, count, who);
+		      octave_value tmp = os.scanf (args(1), size, count, who);
 
 		      // XXX FIXME XXX -- is this the right thing to do?
 		      // Extract error message first, because getting
--- a/src/lex.l
+++ b/src/lex.l
@@ -321,7 +321,7 @@
 
 <COMMAND_START>[\;\,] {
     if (lexer_flags.doing_rawcommand)
-      TOK_PUSH_AND_RETURN (yytext, STRING);
+      TOK_PUSH_AND_RETURN (yytext, SQ_STRING);
 
     BEGIN (INITIAL);
 
@@ -338,7 +338,7 @@
 
 <COMMAND_START>[^#% \t\r\n\;\,\"\'][^ \t\r\n\;\,]*{S}* {
     std::string tok = strip_trailing_whitespace (yytext);
-    TOK_PUSH_AND_RETURN (tok, STRING);
+    TOK_PUSH_AND_RETURN (tok, SQ_STRING);
   }
 
 %{
@@ -1983,7 +1983,7 @@
 		  std::string s;  
 		  yyunput (c, yytext);
 		  buf << OSSTREAM_ENDS;
-		  if (lexer_flags.doing_rawcommand)
+		  if (lexer_flags.doing_rawcommand || delim == '\'')
 		    s = OSSTREAM_STR (buf);
 		  else
 		    s = do_string_escapes (OSSTREAM_STR(buf));
@@ -2005,7 +2005,7 @@
 		  else if (delim == '\'')
 		    gripe_single_quote_string ();
 
-		  return STRING;
+		  return delim == '"' ? DQ_STRING : SQ_STRING;
 		}
 	    }
 	}
--- a/src/ls-mat4.cc
+++ b/src/ls-mat4.cc
@@ -372,7 +372,7 @@
 	tc = order ? re.transpose () : re;
 
       if (type == 1)
-	tc = tc.convert_to_str ();
+	tc = tc.convert_to_str (false, true, '\'');
 
       return retval;
     }
--- a/src/ls-mat5.cc
+++ b/src/ls-mat5.cc
@@ -910,7 +910,7 @@
 	    tc = re;
 
 	    if (arrayclass == mxCHAR_CLASS)
-	      tc = tc.convert_to_str (false, true);
+	      tc = tc.convert_to_str (false, true, '\'');
 	  }
       }
     }
--- a/src/oct-stream.cc
+++ b/src/oct-stream.cc
@@ -1948,7 +1948,7 @@
       retval = mval;
 
       if (all_char_conv)
-	retval = retval.convert_to_str ();
+	retval = retval.convert_to_str (false, true);
     }
 
   return retval;
@@ -3583,6 +3583,31 @@
   return retval;
 }
 
+octave_value
+octave_stream::scanf (const octave_value& fmt, const Array<double>& size,
+		      int& count, const std::string& who)
+{
+  octave_value retval = Matrix ();
+
+  if (fmt.is_string ())
+    {
+      std::string sfmt = fmt.string_value ();
+
+      if (fmt.is_sq_string ())
+	sfmt = do_string_escapes (sfmt);
+
+      retval = scanf (sfmt, size, count, who);
+    }
+  else
+    {
+      // Note that this is not ::error () !
+
+      error (who + ": format must be a string");
+    }
+
+  return retval;
+}
+
 octave_value_list
 octave_stream::oscanf (const std::string& fmt, const std::string& who)
 {
@@ -3594,6 +3619,30 @@
   return retval;
 }
 
+octave_value_list
+octave_stream::oscanf (const octave_value& fmt, const std::string& who)
+{
+  octave_value_list retval;
+
+  if (fmt.is_string ())
+    {
+      std::string sfmt = fmt.string_value ();
+
+      if (fmt.is_sq_string ())
+	sfmt = do_string_escapes (sfmt);
+
+      retval = oscanf (sfmt, who);
+    }
+  else
+    {
+      // Note that this is not ::error () !
+
+      error (who + ": format must be a string");
+    }
+
+  return retval;
+}
+
 int
 octave_stream::printf (const std::string& fmt, const octave_value_list& args,
 		       const std::string& who)
@@ -3607,6 +3656,31 @@
 }
 
 int
+octave_stream::printf (const octave_value& fmt, const octave_value_list& args,
+		       const std::string& who)
+{
+  int retval = 0;
+
+  if (fmt.is_string ())
+    {
+      std::string sfmt = fmt.string_value ();
+
+      if (fmt.is_sq_string ())
+	sfmt = do_string_escapes (sfmt);
+
+      retval = printf (sfmt, args, who);
+    }
+  else
+    {
+      // Note that this is not ::error () !
+
+      error (who + ": format must be a string");
+    }
+
+  return retval;
+}
+
+int
 octave_stream::puts (const std::string& s, const std::string& who)
 {
   int retval = -1;
@@ -3627,7 +3701,7 @@
   if (tc_s.is_string ())
     {
       std::string s = tc_s.string_value ();      
-      retval = rep->puts (s, who);
+      retval = puts (s, who);
     }
   else
     {
--- a/src/oct-stream.h
+++ b/src/oct-stream.h
@@ -525,12 +525,21 @@
   octave_value scanf (const std::string& fmt, const Array<double>& size,
 		      octave_idx_type& count, const std::string& who /* = "scanf" */);
 
+  octave_value scanf (const octave_value& fmt, const Array<double>& size,
+		      int& count, const std::string& who /* = "scanf" */);
+
   octave_value_list oscanf (const std::string& fmt,
 			    const std::string& who /* = "scanf" */);
 
+  octave_value_list oscanf (const octave_value& fmt,
+			    const std::string& who /* = "scanf" */);
+
   int printf (const std::string& fmt, const octave_value_list& args,
 	      const std::string& who /* = "printf" */);
 
+  int printf (const octave_value& fmt, const octave_value_list& args,
+	      const std::string& who /* = "printf" */);
+
   int puts (const std::string& s, const std::string& who /* = "puts" */);
   int puts (const octave_value& s, const std::string& who /* = "puts" */);
 
--- a/src/octave.gperf
+++ b/src/octave.gperf
@@ -73,5 +73,5 @@
 varargin, VARARGIN, varargin_kw
 varargout, VARARGOUT, varargout_kw
 while, WHILE, while_kw
-__FILE__, STRING, magic_file_kw
+__FILE__, DQ_STRING, magic_file_kw
 __LINE__, NUM, magic_line_kw
--- a/src/ov-base.cc
+++ b/src/ov-base.cc
@@ -194,7 +194,7 @@
 }
 
 octave_value
-octave_base_value::convert_to_str_internal (bool, bool) const
+octave_base_value::convert_to_str_internal (bool, bool, char) const
 {
   gripe_wrong_type_arg ("octave_base_value::convert_to_str_internal ()",
 			type_name ());
--- a/src/ov-base.h
+++ b/src/ov-base.h
@@ -124,6 +124,8 @@
 
   bool is_string (void) const { return false; }
 
+  bool is_sq_string (void) const { return false; }
+
   bool is_range (void) const { return false; }
 
   bool is_map (void) const { return false; }
@@ -286,7 +288,7 @@
 
   octave_value_list list_value (void) const;
 
-  octave_value convert_to_str_internal (bool pad, bool force) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
   void convert_to_row_or_column_vector (void);
 
--- a/src/ov-bool-mat.cc
+++ b/src/ov-bool-mat.cc
@@ -136,10 +136,11 @@
 }
 
 octave_value
-octave_bool_matrix::convert_to_str_internal (bool pad, bool force) const
+octave_bool_matrix::convert_to_str_internal (bool pad, bool force,
+					     char type) const
 {
   octave_value tmp = octave_value (array_value ());
-  return tmp.convert_to_str (pad, force);
+  return tmp.convert_to_str (pad, force, type);
 }
 
 void
--- a/src/ov-bool-mat.h
+++ b/src/ov-bool-mat.h
@@ -117,7 +117,7 @@
   SparseBoolMatrix sparse_bool_matrix_value (bool = false) const
   { return SparseBoolMatrix (matrix.matrix_value ()); }
 
-  octave_value convert_to_str_internal (bool pad, bool force) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/src/ov-bool-sparse.cc
+++ b/src/ov-bool-sparse.cc
@@ -134,10 +134,11 @@
 }
 
 octave_value
-octave_sparse_bool_matrix::convert_to_str_internal (bool pad, bool force) const
+octave_sparse_bool_matrix::convert_to_str_internal (bool pad, bool force,
+						    char type) const
 {
   octave_value tmp = octave_value (array_value ());
-  return tmp.convert_to_str (pad, force);
+  return tmp.convert_to_str (pad, force, type);
 }
 
 // XXX FIXME XXX These are inefficient ways of creating full matrices
--- a/src/ov-bool-sparse.h
+++ b/src/ov-bool-sparse.h
@@ -120,7 +120,7 @@
   SparseBoolMatrix sparse_bool_matrix_value (bool = false) const
     { return matrix; }
 
-  octave_value convert_to_str_internal (bool pad, bool force) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
   bool save_binary (std::ostream& os, bool& save_as_floats);
 
--- a/src/ov-bool.cc
+++ b/src/ov-bool.cc
@@ -103,13 +103,13 @@
 }
 
 octave_value
-octave_bool::convert_to_str_internal (bool, bool) const
+octave_bool::convert_to_str_internal (bool, bool, char type) const
 {
   char s[2];
   s[0] = static_cast<char> (scalar);
   s[1] = '\0';
 
-  return octave_value (s);
+  return octave_value (s, type);
 }
 
 bool 
--- a/src/ov-bool.h
+++ b/src/ov-bool.h
@@ -111,7 +111,7 @@
   octave_value resize (const dim_vector& dv) const
     { boolNDArray retval (dv); if (dv.numel()) retval(0) = scalar; return retval; }
 
-  octave_value convert_to_str_internal (bool pad, bool force) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
   bool save_ascii (std::ostream& os, bool& infnan_warned,
 		 bool strip_nan_and_inf);
--- a/src/ov-cell.h
+++ b/src/ov-cell.h
@@ -100,8 +100,8 @@
 
   octave_value_list list_value (void) const;
 
-  octave_value convert_to_str_internal (bool pad, bool force) const
-    { return all_strings (pad, force); }
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const
+    { return octave_value (all_strings (pad, force), type); }
 
   string_vector all_strings (bool pad = false, bool force = false) const;
 
--- a/src/ov-ch-mat.h
+++ b/src/ov-ch-mat.h
@@ -114,8 +114,8 @@
   charNDArray char_array_value (bool = false) const
     { return matrix; }
 
-  octave_value convert_to_str_internal (bool, bool) const
-    { return octave_value (matrix, true); }
+  octave_value convert_to_str_internal (bool, bool, char type) const
+    { return octave_value (matrix, true, type); }
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/src/ov-fcn-inline.cc
+++ b/src/ov-fcn-inline.cc
@@ -560,9 +560,9 @@
 }
 
 octave_value
-octave_fcn_inline::convert_to_str_internal (bool, bool) const
+octave_fcn_inline::convert_to_str_internal (bool, bool, char type) const
 {
-  return octave_value (fcn_text ());
+  return octave_value (fcn_text (), type);
 }
 
 DEFUN (inline, args, ,
--- a/src/ov-fcn-inline.h
+++ b/src/ov-fcn-inline.h
@@ -63,7 +63,7 @@
 
   string_vector fcn_arg_names (void) const { return ifargs; }
 
-  octave_value convert_to_str_internal (bool, bool) const;
+  octave_value convert_to_str_internal (bool, bool, char) const;
 
   bool save_ascii (std::ostream& os, bool& infnan_warned,
 		 bool strip_nan_and_inf);
--- a/src/ov-range.cc
+++ b/src/ov-range.cc
@@ -208,10 +208,10 @@
 }
 
 octave_value
-octave_range::convert_to_str_internal (bool pad, bool force) const
+octave_range::convert_to_str_internal (bool pad, bool force, char type) const
 {
   octave_value tmp (range.matrix_value ());
-  return tmp.convert_to_str (pad, force);
+  return tmp.convert_to_str (pad, force, type);
 }
 
 void
--- a/src/ov-range.h
+++ b/src/ov-range.h
@@ -165,7 +165,7 @@
 
   Range range_value (void) const { return range; }
 
-  octave_value convert_to_str_internal (bool pad, bool force) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
   void print (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/src/ov-re-mat.cc
+++ b/src/ov-re-mat.cc
@@ -199,7 +199,7 @@
 }
 
 octave_value
-octave_matrix::convert_to_str_internal (bool, bool) const
+octave_matrix::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
   dim_vector dv = dims ();
@@ -208,7 +208,7 @@
   if (nel == 0)
     {
       char s = '\0';
-      retval = octave_value (&s);
+      retval = octave_value (&s, type);
     }
   else
     {
@@ -249,7 +249,7 @@
 	    }
 	}
 
-      retval = octave_value (chm, 1);
+      retval = octave_value (chm, true, type);
     }
 
   return retval;
--- a/src/ov-re-mat.h
+++ b/src/ov-re-mat.h
@@ -117,7 +117,7 @@
 
   void decrement (void) { matrix -= 1.0; }
 
-  octave_value convert_to_str_internal (bool pad, bool force) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/src/ov-scalar.cc
+++ b/src/ov-scalar.cc
@@ -106,7 +106,7 @@
 }
 
 octave_value
-octave_scalar::convert_to_str_internal (bool, bool) const
+octave_scalar::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
 
@@ -125,7 +125,7 @@
 	  ::warning ("range error for conversion to character value");
 	}
 
-      retval = octave_value (std::string (1, static_cast<char> (ival)));
+      retval = octave_value (std::string (1, static_cast<char> (ival)), type);
     }
 
   return retval;
--- a/src/ov-scalar.h
+++ b/src/ov-scalar.h
@@ -127,7 +127,7 @@
 
   streamoff_array streamoff_array_value (void) const;
 
-  octave_value convert_to_str_internal (bool pad, bool force) const;
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
   void increment (void) { ++scalar; }
 
--- a/src/ov-str-mat.cc
+++ b/src/ov-str-mat.cc
@@ -48,8 +48,10 @@
 #include "ls-utils.h"
 
 DEFINE_OCTAVE_ALLOCATOR (octave_char_matrix_str);
+DEFINE_OCTAVE_ALLOCATOR (octave_char_matrix_sq_str);
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_str, "string", "char");
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_sq_str, "sq_string", "char");
 
 static octave_value *
 default_numeric_conversion_function (const octave_value& a)
--- a/src/ov-str-mat.h
+++ b/src/ov-str-mat.h
@@ -149,6 +149,54 @@
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
 
+typedef octave_char_matrix_str octave_char_matrix_dq_str;
+
+class
+octave_char_matrix_sq_str : public octave_char_matrix_str
+{
+public:
+
+  octave_char_matrix_sq_str (void)
+    : octave_char_matrix_str () { }
+
+  octave_char_matrix_sq_str (const charMatrix& chm)
+    : octave_char_matrix_str (chm) { }
+
+  octave_char_matrix_sq_str (const charNDArray& chm)
+    : octave_char_matrix_str (chm) { }
+
+  octave_char_matrix_sq_str (char c)
+    : octave_char_matrix_str (c) { }
+
+  octave_char_matrix_sq_str (const char *s)
+    : octave_char_matrix_str (s) { }
+
+  octave_char_matrix_sq_str (const std::string& s)
+    : octave_char_matrix_str (s) { }
+
+  octave_char_matrix_sq_str (const string_vector& s)
+    : octave_char_matrix_str (s) { }
+
+  octave_char_matrix_sq_str (const octave_char_matrix_str& chm)
+    : octave_char_matrix_str (chm) { }
+
+  octave_char_matrix_sq_str (const octave_char_matrix_sq_str& chms)
+    : octave_char_matrix_str (chms) { }
+
+  ~octave_char_matrix_sq_str (void) { }
+
+  octave_value *clone (void) const { return new octave_char_matrix_sq_str (*this); }
+  octave_value *empty_clone (void) const { return new octave_char_matrix_sq_str (); }
+
+  bool is_sq_string (void) const { return true; }
+
+private:
+
+  DECLARE_OCTAVE_ALLOCATOR
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
 #endif
 
 /*
--- a/src/ov.cc
+++ b/src/ov.cc
@@ -550,55 +550,69 @@
   maybe_mutate ();
 }
 
-octave_value::octave_value (char c)
-  : rep (new octave_char_matrix_str (c))
+octave_value::octave_value (char c, char type)
+  : rep (type == '"'
+	 ? new octave_char_matrix_dq_str (c)
+	 : new octave_char_matrix_sq_str (c))
 {
   rep->count = 1;
   maybe_mutate ();
 }
 
-octave_value::octave_value (const char *s)
-  : rep (new octave_char_matrix_str (s))
+octave_value::octave_value (const char *s, char type)
+  : rep (type == '"'
+	 ? new octave_char_matrix_dq_str (s)
+	 : new octave_char_matrix_sq_str (s))
 {
   rep->count = 1;
   maybe_mutate ();
 }
 
-octave_value::octave_value (const std::string& s)
-  : rep (new octave_char_matrix_str (s))
+octave_value::octave_value (const std::string& s, char type)
+  : rep (type == '"'
+	 ? new octave_char_matrix_dq_str (s)
+	 : new octave_char_matrix_sq_str (s))
 {
   rep->count = 1;
   maybe_mutate ();
 }
 
-octave_value::octave_value (const string_vector& s)
-  : rep (new octave_char_matrix_str (s))
+octave_value::octave_value (const string_vector& s, char type)
+  : rep (type == '"'
+	 ? new octave_char_matrix_dq_str (s)
+	 : new octave_char_matrix_sq_str (s))
 {
   rep->count = 1;
   maybe_mutate ();
 }
 
-octave_value::octave_value (const charMatrix& chm, bool is_str)
+octave_value::octave_value (const charMatrix& chm, bool is_str, char type)
   : rep (is_str
-	 ? new octave_char_matrix_str (chm)
+	 ? (type == '"'
+	    ? new octave_char_matrix_dq_str (chm)
+	    : new octave_char_matrix_sq_str (chm))
 	 : new octave_char_matrix (chm))
 {
   rep->count = 1;
   maybe_mutate ();
 }
 
-octave_value::octave_value (const charNDArray& chm, bool is_str)
+octave_value::octave_value (const charNDArray& chm, bool is_str, char type)
   : rep (is_str
-	 ? new octave_char_matrix_str (chm)
+	 ? (type == '"'
+	    ? new octave_char_matrix_dq_str (chm)
+	    : new octave_char_matrix_sq_str (chm))
 	 : new octave_char_matrix (chm))
 {
   rep->count = 1;
   maybe_mutate ();
 }
 
-octave_value::octave_value (const ArrayN<char>& chm, bool is_str)
+octave_value::octave_value (const ArrayN<char>& chm, bool is_str, char type)
   : rep (is_str
-	 ? new octave_char_matrix_str (chm)
+	 ? (type == '"'
+	    ? new octave_char_matrix_dq_str (chm)
+	    : new octave_char_matrix_sq_str (chm))
 	 : new octave_char_matrix (chm))
 {
   rep->count = 1;
@@ -1458,9 +1472,9 @@
 }
 
 octave_value
-octave_value::convert_to_str (bool pad, bool force) const
+octave_value::convert_to_str (bool pad, bool force, char type) const
 {
-  octave_value retval = convert_to_str_internal (pad, force);
+  octave_value retval = convert_to_str_internal (pad, force, type);
 
   if (! force && is_numeric_type () && Vwarn_num_to_str)
     gripe_implicit_conversion (type_name (), retval.type_name ());
@@ -2180,6 +2194,7 @@
   octave_bool_matrix::register_type ();
   octave_char_matrix::register_type ();
   octave_char_matrix_str::register_type ();
+  octave_char_matrix_sq_str::register_type ();
   octave_int8_scalar::register_type ();
   octave_int16_scalar::register_type ();
   octave_int32_scalar::register_type ();
--- a/src/ov.h
+++ b/src/ov.h
@@ -208,13 +208,16 @@
   octave_value (bool b);
   octave_value (const boolMatrix& bm);
   octave_value (const boolNDArray& bnda);
-  octave_value (char c);
-  octave_value (const char *s);
-  octave_value (const std::string& s);
-  octave_value (const string_vector& s);
-  octave_value (const charMatrix& chm, bool is_string = false);
-  octave_value (const charNDArray& chnda, bool is_string = false);
-  octave_value (const ArrayN<char>& chnda, bool is_string = false);
+  octave_value (char c, char type = '"');
+  octave_value (const char *s, char type = '"');
+  octave_value (const std::string& s, char type = '"');
+  octave_value (const string_vector& s, char type = '"');
+  octave_value (const charMatrix& chm, bool is_string = false,
+		char type = '"');
+  octave_value (const charNDArray& chnda, bool is_string = false,
+		char type = '"');
+  octave_value (const ArrayN<char>& chnda, bool is_string = false,
+		char type = '"');
   octave_value (const SparseMatrix& m, const SparseType& t = SparseType ());
   octave_value (const SparseComplexMatrix& m, 
 		const SparseType& t = SparseType ());
@@ -425,6 +428,9 @@
   virtual bool is_string (void) const
     { return rep->is_string (); }
 
+  virtual bool is_sq_string (void) const
+    { return rep->is_sq_string (); }
+
   virtual bool is_range (void) const
     { return rep->is_range (); }
 
@@ -697,10 +703,12 @@
   // class wants a certain kind of constant, he should simply ask for
   // it, and we should convert it if possible.
 
-  octave_value convert_to_str (bool pad = false, bool force = false) const;
+  octave_value convert_to_str (bool pad = false, bool force = false,
+			       char type = '"') const;
 
-  virtual octave_value convert_to_str_internal (bool pad, bool force) const
-    { return rep->convert_to_str_internal (pad, force); }
+  virtual octave_value
+  convert_to_str_internal (bool pad, bool force, char type) const
+    { return rep->convert_to_str_internal (pad, force, type); }
 
   virtual void convert_to_row_or_column_vector (void)
     { rep->convert_to_row_or_column_vector (); }
--- a/src/parse.y
+++ b/src/parse.y
@@ -406,7 +406,7 @@
 %token <tok_val> STRUCT_ELT
 %token <tok_val> NAME
 %token <tok_val> END
-%token <tok_val> STRING
+%token <tok_val> DQ_STRING SQ_STRING
 %token <tok_val> FOR WHILE DO UNTIL
 %token <tok_val> IF ELSEIF ELSE
 %token <tok_val> SWITCH CASE OTHERWISE
@@ -425,7 +425,7 @@
 %type <comment_type> stash_comment function_beg
 %type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep
 %type <tree_type> input
-%type <tree_constant_type> constant magic_colon anon_fcn_handle
+%type <tree_constant_type> string constant magic_colon anon_fcn_handle
 %type <tree_fcn_handle_type> fcn_handle
 %type <tree_matrix_type> matrix_rows matrix_rows1
 %type <tree_cell_type> cell_rows cell_rows1
@@ -578,12 +578,18 @@
 		  }
 		;
 
+string		: DQ_STRING
+		  { $$ = make_constant (DQ_STRING, $1); }
+		| SQ_STRING
+		  { $$ = make_constant (SQ_STRING, $1); }
+		;
+
 constant	: NUM
 		  { $$ = make_constant (NUM, $1); }
 		| IMAG_NUM
 		  { $$ = make_constant (IMAG_NUM, $1); }
-		| STRING
-		  { $$ = make_constant (STRING, $1); }
+		| string
+		  { $$ = $1; }
 		;
 
 in_matrix_or_assign_lhs
@@ -894,15 +900,11 @@
 		  { $$ = make_index_expression ($1, $2, '('); }
 		;
 
-word_list	: STRING 
+word_list	: string
+		  { $$ = new tree_argument_list ($1); }
+		| word_list string
 		  {
-		    tree_constant *tmp = make_constant (STRING, $1);
-		    $$ = new tree_argument_list (tmp);
-		  }
-		| word_list STRING
-		  {
-		    tree_constant *tmp = make_constant (STRING, $2);
-		    $1->append (tmp);
+		    $1->append ($2);
 		    $$ = $1;
 		  }
 		;
@@ -1764,9 +1766,10 @@
       }
       break;
 
-    case STRING:
+    case DQ_STRING:
+    case SQ_STRING:
       {
-	octave_value tmp (tok_val->text ());
+	octave_value tmp (tok_val->text (), op == DQ_STRING ? '"' : '\'');
 	retval = new tree_constant (tmp, l, c);
       }
       break;