diff --git a/libinterp/corefcn/symtab.h b/libinterp/corefcn/symtab.h --- a/libinterp/corefcn/symtab.h +++ b/libinterp/corefcn/symtab.h @@ -843,6 +843,11 @@ public: subfunctions[scope] = f; } + bool is_subfunction (scope_id scope) + { + return subfunctions.find (scope) != subfunctions.end (); + } + void install_user_function (const octave_value& f) { function_on_path = f; @@ -1072,6 +1077,11 @@ public: rep->install_subfunction (f, scope); } + bool is_subfunction (scope_id scope) + { + return rep->is_subfunction (scope); + } + void install_user_function (const octave_value& f) { rep->install_user_function (f); @@ -1564,6 +1574,20 @@ public: } } + static bool is_subfunction (const std::string& name, scope_id scope) + { + fcn_table_iterator p = fcn_table.find (name); + + if (p != fcn_table.end ()) + { + fcn_info& finfo = p->second; + + return finfo.is_subfunction (scope); + } + + return false; + } + static void install_nestfunction (const std::string& name, const octave_value& fcn, scope_id parent_scope); diff --git a/libinterp/parse-tree/oct-parse.in.yy b/libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy +++ b/libinterp/parse-tree/oct-parse.in.yy @@ -55,6 +55,7 @@ along with Octave; see the file COPYING. #include "Cell.h" #include "call-stack.h" #include "comment-list.h" +#include "debug.h" #include "defaults.h" #include "defun.h" #include "dirfns.h" @@ -1446,17 +1447,30 @@ function_beg : push_fcn_symtab FCN function : function_beg stash_comment function1 { + bool ok = true; + $$ = parser.finish_function (0, $3, $2, $1->line (), - $1->column ()); - parser.recover_from_parsing_function (); + $1->column (), ok); + if (! ok) + { + // finish_function deleted $2 and $3. + YYABORT; + } } | function_beg stash_comment return_list '=' function1 { YYUSE ($4); + bool ok = true; + $$ = parser.finish_function ($3, $5, $2, $1->line (), - $1->column ()); - parser.recover_from_parsing_function (); + $1->column (), ok); + + if (! ok) + { + // finish_function deleted $2, $3, and $5. + YYABORT; + } } ; @@ -3244,10 +3258,12 @@ namespace octave base_parser::finish_function (tree_parameter_list *ret_list, octave_user_function *fcn, octave_comment_list *lc, - int l, int c) + int l, int c, bool& ok) { tree_function_def *retval = 0; + ok = true; + if (ret_list) ret_list->mark_as_formal_parameters (); @@ -3276,11 +3292,38 @@ namespace octave symbol_table::scope_id pscope = function_scopes[function_scopes.size ()-2]; + if (symbol_table::is_subfunction (nm, pscope)) + { + recover_from_parsing_function (); + + delete fcn; + + bison_error (nm + ": duplicate nested function found", + l, c); + + ok = false; + + return retval; + } + symbol_table::install_nestfunction (nm, octave_value (fcn), pscope); } else { + if (symbol_table::is_subfunction (nm, primary_fcn_scope)) + { + recover_from_parsing_function (); + + delete fcn; + + bison_error (nm + ": duplicate subfunction found", l, c); + + ok = false; + + return retval; + } + fcn->mark_as_subfunction (); subfunction_names.push_back (nm); @@ -3308,6 +3351,8 @@ namespace octave } } + recover_from_parsing_function (); + return retval; } @@ -3986,22 +4031,31 @@ namespace octave int err_line = l < 0 ? lexer.input_line_number : l; int err_col = c < 0 ? lexer.current_input_column - 1 : c; + std::string curr_line; + std::ostringstream output_buf; if (lexer.reading_fcn_file || lexer.reading_script_file || lexer.reading_classdef_file) - output_buf << "parse error near line " << err_line - << " of file " << lexer.fcn_file_full_name; + { + output_buf << "parse error near line " << err_line + << " of file " << lexer.fcn_file_full_name; + + curr_line = get_file_line (lexer.fcn_file_full_name, err_line); + } else - output_buf << "parse error:"; + { + output_buf << "parse error:"; + + if (l == lexer.input_line_number) + curr_line = lexer.current_input_line; + } if (str != "parse error") output_buf << "\n\n " << str; output_buf << "\n\n"; - std::string curr_line = lexer.current_input_line; - if (! curr_line.empty ()) { size_t len = curr_line.length (); diff --git a/libinterp/parse-tree/parse.h b/libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h +++ b/libinterp/parse-tree/parse.h @@ -294,7 +294,7 @@ namespace octave tree_function_def * finish_function (tree_parameter_list *ret_list, octave_user_function *fcn, octave_comment_list *lc, - int l, int c); + int l, int c, bool& ok); // Reset state after parsing function. void