changeset 3974:e2290bf911f0

[project @ 2002-07-04 17:38:22 by jwe]
author jwe
date Thu, 04 Jul 2002 17:38:23 +0000
parents 826092b5665e
children 1339486fb498
files doc/interpreter/basics.txi src/ChangeLog src/lex.l src/octave.gperf src/ov-usr-fcn.cc src/ov-usr-fcn.h
diffstat 6 files changed, 134 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/basics.txi
+++ b/doc/interpreter/basics.txi
@@ -816,7 +816,7 @@
 #! /bin/octave -qf
 printf ("%s", program_name);
 for i = 1:nargin
-  printf (" %s", argv{i});
+  printf (" %s", argv@{i@});
 endfor
 printf ("\n");
 @end group
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,25 @@
+2002-07-04  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* lex.l (EL): Warn that `...' is deprecated.
+
+	* ov-usr-fcn.cc (octave_user_function::varargout_to_vr_val,
+	octave_user_function::has_varargout): New functions.
+	(Fvr_val): Ensure varargout is not defined.
+	(octave_user_function::do_multi_index_op): Copy values from
+	varargout here.
+
 2002-07-03  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	* ov-usr-fcn.h (octave_user_function::varargin_sr): New data member.
+	* ov-usr-fcn.cc (octave_user_function::octave_user_function):
+	Initialize it.
+	(bind_automatic_vars): Handle varargin.  Change	all callers.
+
+	* octave.gperf: Handle varargin and varargout as keywords.
+	* lex.l (is_keyword): Likewise.
+	(IDENT): Move all actions into handle_identifier.
+	(handle_identifier): Now takes no args.
+
 	* lex.l (EL): Return VARARGIN or VARARGOUT, not ELLIPSIS.
 	* parse.y (param_list): Use VARARGIN instead of ELLIPSIS.
 	(return_list): Use VARARGOUT instead of ELLIPSIS.
--- a/src/lex.l
+++ b/src/lex.l
@@ -188,7 +188,7 @@
 static void handle_number (void);
 static int handle_string (char delim, int text_style = 0);
 static int handle_close_bracket (int spc_gobbled);
-static int handle_identifier (const std::string& tok, int spc_gobbled);
+static int handle_identifier (void);
 static bool have_continuation (bool trailing_comments_ok = true);
 static bool have_ellipsis_continuation (bool trailing_comments_ok = true);
 static void scan_for_comments (const char *);
@@ -481,9 +481,15 @@
 
 {EL} {
     if (lexer_flags.looking_at_parameter_list)
-      return VARARGIN;
+      {
+	warning ("`...' is deprecated; use varargin instead");
+	return VARARGIN;
+      }
     else if (lexer_flags.looking_at_return_list)
-      return VARARGOUT;
+      {
+	warning ("`...' is deprecated; use varargout instead");
+	return VARARGOUT;
+      }
     else
       return LEXICAL_ERROR;
   }
@@ -502,11 +508,7 @@
 %}
 
 {IDENT}{S}* {
-    std::string tok = strip_trailing_whitespace (yytext);
-    int c = yytext[yyleng-1];
-    int cont_is_spc = eat_continuation ();
-    int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
-    return handle_identifier (tok, spc_gobbled);
+    return handle_identifier ();
   }
 
 %{
@@ -1166,6 +1168,16 @@
 	  yylval.tok_val = new token (static_cast<double> (l), "", l, c);
 	  break;
 
+	case varargin_kw:
+	  if (! lexer_flags.looking_at_parameter_list)
+	    return 0;
+	  break;
+
+	case varargout_kw:
+	  if (! lexer_flags.looking_at_return_list)
+	    return 0;
+	  break;
+
 	default:
 	  panic_impossible ();
 	}
@@ -2175,8 +2187,16 @@
 // an identifier.  Handles keywords.
 
 static int
-handle_identifier (const std::string& tok, int spc_gobbled)
+handle_identifier (void)
 {
+  std::string tok = strip_trailing_whitespace (yytext);
+
+  int c = yytext[yyleng-1];
+
+  int cont_is_spc = eat_continuation ();
+
+  int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
+
   // It is almost always an error for an identifier to be followed
   // directly by another identifier.  Special cases are handled
   // below.
--- a/src/octave.gperf
+++ b/src/octave.gperf
@@ -35,6 +35,8 @@
   until_kw,
   unwind_protect_kw,
   unwind_protect_cleanup_kw,
+  varargin_kw,
+  varargout_kw,
   while_kw
 };
 
@@ -72,6 +74,8 @@
 until, UNTIL, until_kw
 unwind_protect, UNWIND, unwind_protect_kw
 unwind_protect_cleanup, CLEANUP, unwind_protect_cleanup_kw
+varargin, VARARGIN, varargin_kw
+varargout, VARARGOUT, varargout_kw
 while, WHILE, while_kw
 __FILE__, TEXT, magic_file_kw
 __LINE__, NUM, magic_line_kw
--- a/src/ov-usr-fcn.cc
+++ b/src/ov-usr-fcn.cc
@@ -31,6 +31,7 @@
 #include "str-vec.h"
 
 #include <defaults.h>
+#include "Cell.h"
 #include "defun.h"
 #include "error.h"
 #include "input.h"
@@ -83,7 +84,7 @@
     system_fcn_file (false), call_depth (0),
     num_named_args (0), args_passed (), num_args_passed (0),
     curr_va_arg_number (0), vr_list (0), symtab_entry (0),
-    argn_sr (0), nargin_sr (0), nargout_sr (0)
+    argn_sr (0), nargin_sr (0), nargout_sr (0), varargin_sr (0)
 {
   install_automatic_vars ();
 
@@ -202,6 +203,52 @@
 }
 
 void
+octave_user_function::varargout_to_vr_val (void)
+{
+  assert (vr_list && vr_list->empty ());
+
+  symbol_record *sr = sym_tab->lookup ("varargout");
+
+  if (sr && sr->is_variable ())
+    {
+      octave_value v = sr->def ();
+
+      Cell c = v.cell_value ();
+
+      if (! error_state)
+	{
+	  // XXX FIXME XXX -- should varargout be required to be a
+	  // cell array with a single row or column?  If not, should
+	  // we have a cleaner way of doing this operation?
+
+	  int n = c.length ();
+
+	  const octave_value *d = c.data ();
+
+	  for (int i = 0; i < n; i++)
+	    vr_list->append (d[i]);
+	}
+      else
+	error ("expecting varargout to be a cell array object");
+    }
+}
+
+bool
+octave_user_function::has_varargout (void) const
+{
+  bool retval = false;
+
+  if (takes_var_return ())
+    {
+      symbol_record *sr = sym_tab->lookup ("varargout");
+
+      retval = (sr && sr->is_variable ());
+    }
+
+  return retval;
+}
+
+void
 octave_user_function::stash_function_name (const std::string& s)
 {
   fcn_name = s;
@@ -393,7 +440,7 @@
   // variables.
 
   {
-    bind_automatic_vars (arg_names, nargin, nargout);
+    bind_automatic_vars (arg_names, nargin, nargout, octave_all_va_args ());
 
     bool echo_commands = (Vecho_executing_commands & ECHO_FUNCTIONS);
 
@@ -439,6 +486,9 @@
 	      ret_list->initialize_undefined_elements (tmp);
 	  }
 
+	if (has_varargout ())
+	  varargout_to_vr_val ();
+
 	retval = ret_list->convert_to_const_vector (vr_list);
       }
     else if (Vreturn_last_computed_value)
@@ -511,17 +561,33 @@
   argn_sr = sym_tab->lookup ("argn", true);
   nargin_sr = sym_tab->lookup ("nargin", true);
   nargout_sr = sym_tab->lookup ("nargout", true);
+
+  if (takes_varargs ())
+    varargin_sr = sym_tab->lookup ("varargin", true);
 }
 
 void
 octave_user_function::bind_automatic_vars
-  (const string_vector& arg_names, int nargin, int nargout)
+  (const string_vector& arg_names, int nargin, int nargout,
+   const octave_value_list& va_args)
 {
   if (! arg_names.empty ())
     argn_sr->define (arg_names);
 
   nargin_sr->define (static_cast<double> (nargin));
   nargout_sr->define (static_cast<double> (nargout));
+
+  if (takes_varargs ())
+    {
+      int n = va_args.length ();
+
+      Cell varargin (1, n);
+
+      for (int i = 0; i < n; i++)
+	varargin(0,i) = va_args(i);
+
+      varargin_sr->define (varargin);
+    }
 }
 
 DEFUNX ("va_arg", Fva_arg, args, ,
@@ -611,7 +677,9 @@
     {
       if (curr_function)
 	{
-	  if (curr_function->takes_var_return ())
+	  if (curr_function->has_varargout ())
+	    ::error ("vr_val and varargout cannot both be used in the same function");
+	  else if (curr_function->takes_var_return ())
 	    curr_function->octave_vr_val (args(0));
 	  else
 	    {
--- a/src/ov-usr-fcn.h
+++ b/src/ov-usr-fcn.h
@@ -112,6 +112,10 @@
 
   void octave_vr_val (const octave_value& val);
 
+  void varargout_to_vr_val (void);
+
+  bool has_varargout (void) const;
+
   void stash_function_name (const std::string& s);
 
   std::string function_name (void)
@@ -233,6 +237,9 @@
   // The symbol record for nargout in the local symbol table.
   symbol_record *nargout_sr;
 
+  // The symbol record for varargin in the local symbol table.
+  symbol_record *varargin_sr;
+
   void print_code_function_header (void);
 
   void print_code_function_trailer (void);
@@ -240,7 +247,7 @@
   void install_automatic_vars (void);
 
   void bind_automatic_vars (const string_vector& arg_names, int nargin,
-			    int nargout);
+			    int nargout, const octave_value_list& va_args);
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA