# HG changeset patch # User jwe # Date 1025804303 0 # Node ID e2290bf911f063d8fed3b48aba02e76130bf5c40 # Parent 826092b5665effbfd673aae034a8a89e6f2014c5 [project @ 2002-07-04 17:38:22 by jwe] diff --git a/doc/interpreter/basics.txi b/doc/interpreter/basics.txi --- 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 diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,25 @@ +2002-07-04 John W. Eaton + + * 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 + * 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. diff --git a/src/lex.l b/src/lex.l --- 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 (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. diff --git a/src/octave.gperf b/src/octave.gperf --- 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 diff --git a/src/ov-usr-fcn.cc b/src/ov-usr-fcn.cc --- a/src/ov-usr-fcn.cc +++ b/src/ov-usr-fcn.cc @@ -31,6 +31,7 @@ #include "str-vec.h" #include +#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 (nargin)); nargout_sr->define (static_cast (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 { diff --git a/src/ov-usr-fcn.h b/src/ov-usr-fcn.h --- 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